Merge "msm: vidc: refine instance info stats"
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 3a96610..ee9b465 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -110,6 +110,9 @@
 	* cpu: the cpu phandle this ETM/PTM is affined to. When omitted the
 	  source is considered to belong to CPU0.
 
+	* qcom,tupwr-disable: For ETM, don't keep trace unit powered across power
+	  collapse.
+
 * Optional property for TMC:
 
 	* arm,buffer-size: size of contiguous buffer space for TMC ETR
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 9df16fb..1a9c8bd 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -95,6 +95,9 @@
 - QCS605
   compatible = "qcom,qcs605"
 
+- SXR1120
+  compatible = "qcom,sxr1120"
+
 - SDA670
   compatible = "qcom,sda670"
 
@@ -324,6 +327,8 @@
 compatible = "qcom,sdm670-qrd"
 compatible = "qcom,qcs605-cdp"
 compatible = "qcom,qcs605-mtp"
+compatible = "qcom,sxr1120-mtp"
+compatible = "qcom,sxr1120-cdp"
 compatible = "qcom,sda670-cdp"
 compatible = "qcom,sda670-mtp"
 compatible = "qcom,sda670-hdk"
diff --git a/Documentation/devicetree/bindings/display/msm/sde.txt b/Documentation/devicetree/bindings/display/msm/sde.txt
index 0589165..15f1e93 100644
--- a/Documentation/devicetree/bindings/display/msm/sde.txt
+++ b/Documentation/devicetree/bindings/display/msm/sde.txt
@@ -103,6 +103,8 @@
 - qcom,sde-dsc-size:		A u32 value indicates the address range for each dsc.
 - qcom,sde-cdm-size:		A u32 value indicates the address range for each cdm.
 - qcom,sde-pp-size:		A u32 value indicates the address range for each pingpong.
+- qcom,sde-te-source:		Array of GPIO sources indicating which pingpong TE is
+				sourced to which panel TE gpio.
 - qcom,sde-wb-size:		A u32 value indicates the address range for each writeback.
 - qcom,sde-len:			A u32 entry for SDE address range.
 - qcom,sde-intf-max-prefetch-lines:	Array of u32 values for max prefetch lines on
@@ -502,6 +504,7 @@
     qcom,sde-pp-off = <0x00071000 0x00071800
 			  0x00072000 0x00072800>;
     qcom,sde-pp-slave = <0x0 0x0 0x0 0x0>;
+    qcom,sde-te-source = <0x0 0x1 0x0 0x0>;
     qcom,sde-cdm-off = <0x0007a200>;
     qcom,sde-dsc-off = <0x00081000 0x00081400>;
     qcom,sde-intf-max-prefetch-lines = <0x15 0x15 0x15 0x15>;
diff --git a/Documentation/devicetree/bindings/fb/mdss-dsi.txt b/Documentation/devicetree/bindings/fb/mdss-dsi.txt
index 1934bc5..2d689d2 100644
--- a/Documentation/devicetree/bindings/fb/mdss-dsi.txt
+++ b/Documentation/devicetree/bindings/fb/mdss-dsi.txt
@@ -113,6 +113,7 @@
 - qcom,platform-bklight-en-gpio-invert:	Invert the gpio used to enable display back-light
 - qcom,panel-mode-gpio:			Specifies the GPIO to select video/command/single-port/dual-port
 					mode of panel through gpio when it supports these modes.
+- qcom,ext-vdd-gpio:			Specifies the GPIO to enable external VDD supply.
 - pinctrl-names:			List of names to assign mdss pin states defined in pinctrl device node
 					Refer to pinctrl-bindings.txt
 - pinctrl-<0..n>:			Lists phandles each pointing to the pin configuration node within a pin
diff --git a/Documentation/devicetree/bindings/fb/mdss-spi-client.txt b/Documentation/devicetree/bindings/fb/mdss-spi-client.txt
new file mode 100644
index 0000000..0d5fde8
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-spi-client.txt
@@ -0,0 +1,27 @@
+Qualcomm Technologies, Inc. mdss-spi-client
+
+mdss-spi-client is for SPI display to send the FB data to SPI master.
+
+Required properties:
+- compatible : should be "qcom,mdss-spi-client"
+- spi-max-frequency : Maximum SPI clocking speed of device in Hz
+
+Optional properties:
+- label: A string used to describe the controller used.
+- spi-cpol : Boolean property indicating device requires inverse
+  clock polarity (CPOL) mode
+- spi-cpha :  Empty property indicating device requires shifted
+  clock phase (CPHA) mode
+- spi-cs-high :  Empty property indicating device requires
+  chip select active high
+
+Example:
+spi@78b9000 { /* BLSP1 QUP5 */
+	qcom,mdss_spi_client {
+		reg = <0>;
+		compatible = "qcom,mdss-spi-client";
+		label = "MDSS SPI QUP5 CLIENT";
+		spi-max-frequency = <50000000>;
+	};
+};
+
diff --git a/Documentation/devicetree/bindings/fb/mdss-spi-panel.txt b/Documentation/devicetree/bindings/fb/mdss-spi-panel.txt
new file mode 100644
index 0000000..d46068f
--- /dev/null
+++ b/Documentation/devicetree/bindings/fb/mdss-spi-panel.txt
@@ -0,0 +1,203 @@
+Qualcomm Technologies, Inc. mdss-spi-panel
+
+mdss-spi-panel is a SPI panel device which supports panels that
+are compatible with display serial interface specification.
+
+Required properties:
+- qcom,mdss-spi-panel-controller:	Specifies the phandle for the SPI controller that
+					this panel will be mapped to.
+- qcom,mdss-spi-panel-width:		Specifies panel width in pixels.
+- qcom,mdss-spi-panel-height:		Specifies panel height in pixels.
+- qcom,mdss-spi-bpp:			Specifies the panel bits per pixels.
+					3  = for rgb111
+					8  = for rgb332
+					12 = for rgb444
+					16 = for rgb565
+					18 = for rgb666
+					24 = for rgb888
+- qcom,mdss-spi-panel-destination:	A string that specifies the destination display for the panel.
+					"display_1" = DISPLAY_1
+					"display_2" = DISPLAY_2
+- qcom,mdss-spi-on-command:		A byte stream formed by multiple packets
+					byte 0: wait number of specified ms after command
+						 transmitted
+					byte 1: 8 bits length in network byte order
+					byte 3 and beyond: number byte of payload
+- qcom,mdss-spi-off-command:		A byte stream formed by multiple packets
+					byte 0: wait number of specified ms after command
+						 transmitted
+					byte 1: 8 bits length in network byte order
+					byte 3 and beyond: number byte of payload
+Optional properties:
+- qcom,mdss-spi-panel-name:		A string used as a descriptive name of the panel
+- qcom,cont-splash-enabled:		Boolean used to enable continuous splash mode.
+					If this property is specified, it is required to
+					to specify the memory reserved for the splash
+					screen using the qcom,memblock-reserve binding
+					for the framebuffer device attached to the panel.
+- qcom,mdss-spi-h-back-porch:		Horizontal back porch value in pixels.
+					6 = default value.
+- qcom,mdss-spi-h-front-porch:		Horizontal front porch value in pixels.
+					6 = default value.
+- qcom,mdss-spi-h-pulse-width:		Horizontal pulse width.
+					2 = default value.
+- qcom,mdss-spi-h-sync-skew:		Horizontal sync skew value.
+					0 = default value.
+- qcom,mdss-spi-v-back-porch:		Vertical back porch value in pixels.
+					6 = default value.
+- qcom,mdss-spi-v-front-porch:		Vertical front porch value in pixels.
+					6 = default value.
+- qcom,mdss-spi-v-pulse-width:		Vertical pulse width.
+					2 = default value.
+- qcom,mdss-spi-bl-pmic-control-type:	A string that specifies the implementation of backlight
+					control for this panel.
+					"bl_ctrl_pwm" = Backlight controlled by PWM gpio.
+					"bl_ctrl_wled" = Backlight controlled by WLED.
+					other: Unknown backlight control. (default)
+- qcom,mdss-spi-bl-min-level:		Specifies the min backlight level supported by the panel.
+					0 = default value.
+- qcom,mdss-spi-bl-max-level:		Specifies the max backlight level supported by the panel.
+					255 = default value.
+- qcom,mdss-spi-panel-framerate:	Specifies the frame rate for the panel.
+- qcom,esd-check-enabled:		Boolean used to enable ESD recovery feature.
+- qcom,mdss-spi-panel-status-check-mode:Specifies the panel status check method for ESD recovery.
+					"send_init_command" = send init code to recover panel status.
+					"reg_read" = Read register value to check the panel status.
+- qcom,mdss-spi-panel-status-reg:Unsigned 8bits integer value to specifies the value
+					of panel status register address.
+- qcom,mdss-spi-panel-status-read-length:Unsigned 8bits integer value that specifies
+					the expected read-back length of the panel register.
+- qcom,mdss-spi-panel-status-value:An unsigned 8bits integer araray that specifies the
+					values of the panel status register which is used to
+					check the panel status.
+					The size of this array is specified by
+					qcom,mdss-dsi-panel-status-read-length.
+
+Example:
+&mdss_mdp {
+	spi_gc9305_qvga_cmd: qcom,mdss_spi_gc9305_qvga_cmd {
+		qcom,mdss-spi-panel-name = "gc9305 qvga command mode spi panel";
+		qcom,mdss-spi-panel-destination = "display_1";
+		qcom,mdss-spi-panel-controller = <&mdss_spi>;
+		qcom,mdss-spi-panel-framerate = <30>;
+		qcom,mdss-spi-panel-width = <240>;
+		qcom,mdss-spi-panel-height = <320>;
+		qcom,mdss-spi-h-front-porch = <79>;
+		qcom,mdss-spi-h-back-porch = <59>;
+		qcom,mdss-spi-h-pulse-width = <60>;
+		qcom,mdss-spi-v-back-porch = <10>;
+		qcom,mdss-spi-v-front-porch = <7>;
+		qcom,mdss-spi-v-pulse-width = <2>;
+		qcom,mdss-spi-h-left-border = <0>;
+		qcom,mdss-spi-h-right-border = <0>;
+		qcom,mdss-spi-v-top-border = <0>;
+		qcom,mdss-spi-v-bottom-border = <0>;
+		qcom,mdss-spi-bpp = <16>;
+		qcom,mdss-spi-on-command = [00 01 FE
+			00 01 EF
+			00 02 36 48
+			00 02 3A 05
+			00 02 35 00
+			00 03 A4 44 44
+			00 03 A5 42 42
+			00 03 AA 88 88
+			00 03 E8 12 40
+			00 03 E3 01 10
+			00 02 FF 61
+			00 02 AC 00
+			00 03 A6 2A 2A
+			00 03 A7 2B 2B
+			00 03 A8 18 18
+			00 03 A9 2A 2A
+			00 02 AD 33
+			00 02 AF 55
+			00 02 AE 2B
+			00 05 2A 00 00 00 EF
+			00 05 2B 00 00 01 3F
+			00 01 2C
+			00 07 F0 02 02 00 08 0C 10
+			00 07 F1 01 00 00 14 1D 0E
+			00 07 F2 10 09 37 04 04 48
+			00 07 F3 10 0B 3F 05 05 4E
+			00 07 F4 0D 19 17 1D 1E 0F
+			00 07 F5 06 12 13 1A 1B 0F
+			78 01 11
+			00 01 29
+			00 01 2C];
+		qcom,mdss-spi-off-command = [20 01 28
+			20 01 10];
+		qcom,mdss-spi-bl-min-level = <1>;
+		qcom,mdss-spi-bl-max-level = <4095>;
+		qcom,esd-check-enabled;
+		qcom,mdss-spi-panel-status-check-mode = "reg_read";
+		qcom,mdss-spi-panel-status-reg = /bits/ 8 <0x09>;
+		qcom,mdss-spi-panel-status-read-length = <4>;
+		qcom,mdss-spi-panel-status-value = /bits/ 8 <0x52 0x29 0x83 0x00>;
+	};
+};
+
+mdss-spi-display is a spi interface display which support send frame
+data and command to panel, compatible with SPI interface specification.
+
+Required properties:
+- compatible:	This property applies to SPI panels only.
+			compatible = "qcom,mdss-spi-display".
+- vdd-supply:	Phandle for vdd regulator device node.
+- vddio-supply:	Phandle for vdd-io regulator device node.
+- qcom,mdss-fb-map:	pHandle that specifies the framebuffer to which the interface is mapped.
+- qcom,mdss-mdp:	pHandle that specifies the mdss-mdp device.
+- qcom,panel-supply-entries:	A node that lists the elements of the supply used to
+				power the DSI panel. There can be more than one instance
+				of this binding, in which case the entry would be appended
+				with the supply entry index. For a detailed description
+				fields in the supply entry, refer to the qcom,ctrl-supply-entries
+				binding above.
+- qcom,platform-spi-dc-gpio: 	Pull down this gpio indicate current package is command,
+				Pull up this gpio indicate current package is parameter or pixels.
+
+Optional properties:
+- label:A string used to describe the controller used.
+	-- qcom,supply-name: name of the supply (vdd/vdda/vddio)
+	-- qcom,supply-min-voltage: minimum voltage level (uV)
+	-- qcom,supply-max-voltage: maximum voltage level (uV)
+	-- qcom,supply-enable-load: load drawn (uA) from enabled supply
+	-- qcom,supply-disable-load: load drawn (uA) from disabled supply
+	-- qcom,supply-pre-on-sleep: time to sleep (ms) before turning on
+	-- qcom,supply-post-on-sleep: time to sleep (ms) after turning on
+	-- qcom,supply-pre-off-sleep: time to sleep (ms) before turning off
+	-- qcom,supply-post-off-sleep: time to sleep (ms) after turning off
+
+Example:
+	mdss_spi: qcom,mdss_spi {
+		compatible = "qcom,mdss-spi-display";
+		label = "mdss spi panel";
+
+		qcom,mdss-fb-map = <&mdss_fb0>;
+		qcom,mdss-mdp = <&mdss_mdp>;
+		vdd-supply = <&pm8909_l17>;
+		vddio-supply = <&pm8909_l6>;
+		qcom,platform-spi-dc-gpio = <&msm_gpio 110 0>;
+
+		qcom,panel-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,panel-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdd";
+				qcom,supply-min-voltage = <2850000>;
+				qcom,supply-max-voltage = <2850000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+			};
+
+			qcom,panel-supply-entry@1 {
+				reg = <1>;
+				qcom,supply-name = "vddio";
+				qcom,supply-min-voltage = <1800000>;
+				qcom,supply-max-voltage = <1800000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+			};
+		};
+	};
diff --git a/arch/arm/configs/msm8909-perf_defconfig b/arch/arm/configs/msm8909-perf_defconfig
index f42b90a..b0c2adc 100644
--- a/arch/arm/configs/msm8909-perf_defconfig
+++ b/arch/arm/configs/msm8909-perf_defconfig
@@ -475,6 +475,7 @@
 CONFIG_TMPFS=y
 CONFIG_ECRYPT_FS=y
 CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/configs/msm8909w-perf_defconfig b/arch/arm/configs/msm8909w-perf_defconfig
index 887ab5c..2b784c9 100644
--- a/arch/arm/configs/msm8909w-perf_defconfig
+++ b/arch/arm/configs/msm8909w-perf_defconfig
@@ -475,6 +475,7 @@
 CONFIG_TMPFS=y
 CONFIG_ECRYPT_FS=y
 CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/configs/msm8909w_defconfig b/arch/arm/configs/msm8909w_defconfig
index 8c5f143..c9d7fdb 100644
--- a/arch/arm/configs/msm8909w_defconfig
+++ b/arch/arm/configs/msm8909w_defconfig
@@ -444,6 +444,7 @@
 CONFIG_TMPFS=y
 CONFIG_ECRYPT_FS=y
 CONFIG_ECRYPT_FS_MESSAGING=y
+CONFIG_SDCARD_FS=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_PRINTK_TIME=y
diff --git a/arch/arm/configs/msm8937-perf_defconfig b/arch/arm/configs/msm8937-perf_defconfig
index dae45e1..ced854d 100644
--- a/arch/arm/configs/msm8937-perf_defconfig
+++ b/arch/arm/configs/msm8937-perf_defconfig
@@ -67,6 +67,7 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
diff --git a/arch/arm/configs/msm8937_defconfig b/arch/arm/configs/msm8937_defconfig
index 3c43fa3..40d5cb1 100644
--- a/arch/arm/configs/msm8937_defconfig
+++ b/arch/arm/configs/msm8937_defconfig
@@ -70,6 +70,7 @@
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_HIGHMEM=y
+CONFIG_ARM_MODULE_PLTS=y
 CONFIG_CMA=y
 CONFIG_CMA_DEBUGFS=y
 CONFIG_ZSMALLOC=y
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 06e5360..8caee2f 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -572,6 +572,7 @@
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MEM_SHARE_QMI_SERVICE=y
@@ -620,8 +621,11 @@
 CONFIG_IPC_LOGGING=y
 CONFIG_CPU_FREQ_SWITCH_PROFILER=y
 CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
 CONFIG_CORESIGHT_REMOTE_ETM=y
 CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_DBGUI=y
 CONFIG_CORESIGHT_STM=y
 CONFIG_CORESIGHT_TPDA=y
 CONFIG_CORESIGHT_TPDM=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 70adcf1..e76f045 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -590,6 +590,7 @@
 CONFIG_MSM_EVENT_TIMER=y
 CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_PM=y
+CONFIG_QCOM_DCC=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MEM_SHARE_QMI_SERVICE=y
@@ -684,8 +685,12 @@
 CONFIG_PID_IN_CONTEXTIDR=y
 CONFIG_DEBUG_SET_MODULE_RONX=y
 CONFIG_CORESIGHT=y
+CONFIG_CORESIGHT_LINK_AND_SINK_TMC=y
+CONFIG_CORESIGHT_SOURCE_ETM4X=y
 CONFIG_CORESIGHT_REMOTE_ETM=y
 CONFIG_CORESIGHT_REMOTE_ETM_DEFAULT_ENABLE=0
+CONFIG_CORESIGHT_QCOM_REPLICATOR=y
+CONFIG_CORESIGHT_DBGUI=y
 CONFIG_CORESIGHT_STM=y
 CONFIG_CORESIGHT_TPDA=y
 CONFIG_CORESIGHT_TPDM=y
diff --git a/arch/arm/mach-qcom/board-msm8917.c b/arch/arm/mach-qcom/board-msm8917.c
index 63bc43b..0bd6984 100644
--- a/arch/arm/mach-qcom/board-msm8917.c
+++ b/arch/arm/mach-qcom/board-msm8917.c
@@ -17,6 +17,7 @@
 
 static const char *msm8917_dt_match[] __initconst = {
 	"qcom,msm8917",
+	"qcom,apq8017",
 	NULL
 };
 
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index 1d845e8..ae21ef5 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -142,11 +142,16 @@
 		sdm670-pm660a-tasha-codec-cdp-overlay.dtbo \
 		sdm670-aqt1000-cdp-overlay.dtbo \
 		sdm670-pm660a-aqt1000-cdp-overlay.dtbo \
+		sxr1120-lc-mtp-overlay.dtbo \
+		sxr1120-lc-external-codec-mtp-overlay.dtbo \
+		sxr1120-lc-cdp-overlay.dtbo \
+		sxr1120-lc-external-codec-cdp-overlay.dtbo \
 		qcs605-cdp-overlay.dtbo \
 		qcs605-mtp-overlay.dtbo \
 		qcs605-360camera-overlay.dtbo \
 		qcs605-external-codec-mtp-overlay.dtbo \
 		qcs605-lc-mtp-overlay.dtbo \
+		qcs605-lc-cdp-overlay.dtbo \
 		sdm710-cdp-overlay.dtbo \
 		sdm710-mtp-overlay.dtbo \
 		sdm710-qrd-overlay.dtbo \
@@ -198,11 +203,16 @@
 sda670-hdk-overlay.dtbo-base := sda670.dtb
 sda670-pm660a-cdp-overlay.dtbo-base := sda670.dtb
 sda670-pm660a-mtp-overlay.dtbo-base := sda670.dtb
+sxr1120-lc-mtp-overlay.dtbo-base := sxr1120-lc.dtb
+sxr1120-lc-external-codec-mtp-overlay.dtbo-base := sxr1120-lc.dtb
+sxr1120-lc-cdp-overlay.dtbo-base := sxr1120-lc.dtb
+sxr1120-lc-external-codec-cdp-overlay.dtbo-base := sxr1120-lc.dtb
 qcs605-cdp-overlay.dtbo-base := qcs605.dtb
 qcs605-mtp-overlay.dtbo-base := qcs605.dtb
 qcs605-external-codec-mtp-overlay.dtbo-base := qcs605.dtb
 qcs605-lc-mtp-overlay.dtbo-base := qcs605-lc.dtb
 qcs605-360camera-overlay.dtbo-base := qcs605.dtb
+qcs605-lc-cdp-overlay.dtbo-base := qcs605-lc-cdp-base.dtb
 sdm710-cdp-overlay.dtbo-base := sdm710.dtb
 sdm710-mtp-overlay.dtbo-base := sdm710.dtb
 sdm710-qrd-overlay.dtbo-base := sdm710.dtb
@@ -253,11 +263,16 @@
 	sdm670-pm660a-tasha-codec-cdp.dtb \
 	sda670-pm660a-mtp.dtb \
 	sda670-pm660a-cdp.dtb \
+	sxr1120-lc-mtp.dtb \
+	sxr1120-lc-external-codec-mtp.dtb \
+	sxr1120-lc-cdp.dtb \
+	sxr1120-lc-external-codec-cdp.dtb \
 	qcs605-360camera.dtb \
 	qcs605-mtp.dtb \
 	qcs605-cdp.dtb \
 	qcs605-external-codec-mtp.dtb \
 	qcs605-lc-mtp.dtb \
+	qcs605-lc-cdp.dtb \
 	sdm710-mtp.dtb \
 	sdm710-cdp.dtb \
 	sdm710-qrd.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
index d28e139..9261dfe 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8009-audio-external_codec.dtsi
@@ -19,6 +19,12 @@
 };
 
 &soc {
+	qcom,msm-audio-apr {
+		compatible = "qcom,msm-audio-apr";
+		msm_audio_apr_dummy {
+			compatible = "qcom,msm-audio-apr-dummy";
+		};
+	};
 	sound-9335 {
 		compatible = "qcom,apq8009-audio-i2s-codec";
 		qcom,model = "apq8009-tashalite-snd-card";
@@ -234,16 +240,17 @@
 		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-clk-internal = <1>;
+		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-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>;
 		};
 	};
@@ -254,17 +261,26 @@
 		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-clk-internal = <1>;
+		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-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>;
 		};
 	};
 };
+
+&wcd9xxx_intc {
+	status = "okay";
+};
+
+&clock_audio {
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
index 1866e2f..2afd5ac 100644
--- a/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
+++ b/arch/arm64/boot/dts/qcom/apq8009-mtp-wcd9326-refboard.dts
@@ -95,7 +95,7 @@
 };
 
 &soc {
-	sound-9335 {
+	ext_codec: sound-9335 {
 		qcom,audio-routing =
 			"AIF4 VI", "MCLK",
 			"RX_BIAS", "MCLK",
@@ -112,12 +112,22 @@
 			"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>;
-		};
+		qcom,msm-gpios =
+			"us_eu_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"us_eu_gpio_act";
+		pinctrl-names =
+			"all_off",
+			"us_eu_gpio_act";
+		pinctrl-0 = <&cross_conn_det_sus>;
+		pinctrl-1 = <&cross_conn_det_act>;
+		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+		qcom,quat-mi2s-gpios = <&cdc_quat_mi2s_gpios>;
+
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+					"SpkrLeft", "SpkrRight";
 	};
 
 	i2c@78b9000 {
@@ -205,6 +215,36 @@
 		qcom,id-det-gpio = <&msm_gpio 110 0>;
 		qcom,dpdm_switch_gpio = <&pm8916_gpios 3 0>;
 	};
+
+	i2c@78b8000 {
+		wcd9xxx_codec@d {
+			status = "okay";
+			qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+		};
+	};
+
+	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&pri_mi2s_active &pri_mi2s_ws_active
+		     &pri_mi2s_dout_active &pri_mi2s_din_active>;
+		pinctrl-1 = <&pri_mi2s_sleep &pri_mi2s_ws_sleep
+		     &pri_mi2s_dout_sleep &pri_mi2s_din_sleep>;
+	};
+
+	cdc_quat_mi2s_gpios: msm_cdc_pinctrl_quat {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+	};
+
+	wcd_rst_gpio: wcd_gpio_ctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_reset_active>;
+		pinctrl-1 = <&cdc_reset_sleep>;
+	};
 };
 
 &wcnss {
@@ -327,4 +367,16 @@
 	status = "disabled";
 };
 
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&ext_codec {
+	status = "okay";
+};
+
+&blsp1_uart2_hs {
+	status = "disabled";
+};
+
 /delete-node/ &cont_splash_mem;
diff --git a/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts b/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
index 9f0edda..8782001 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/apq8053-iot-mtp.dts
@@ -86,3 +86,12 @@
 	qcom,model = "msm8953-tasha-snd-card";
 	status = "okay";
 };
+
+&soc {
+	usb_detect: usb_detect {
+		compatible = "linux,extcon-usb-gpio";
+		pintctrl-names = "default";
+		pinctrl-0 = <&ssusb_mode_sel>;
+		id-gpio = <&tlmm 12 0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
index 4d9c40c..993799b 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.1.dtsi
@@ -14,7 +14,7 @@
 #include "apq8053-lite-dragon.dtsi"
 
 &mdss_dsi0 {
-	qcom,ext_vdd-gpio = <&tlmm 100 0>;
+	qcom,ext-vdd-gpio = <&tlmm 100 0>;
 	qcom,platform-bklight-en-gpio = <&tlmm 95 0>;
 
 	qcom,platform-lane-config = [00 00 ff 0f
diff --git a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
index 396fd55..1744c90 100644
--- a/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
+++ b/arch/arm64/boot/dts/qcom/apq8053-lite-dragon-v2.2.dtsi
@@ -18,6 +18,41 @@
 	/delete-node/ himax_ts@48;
 };
 
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+	hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_boent51021_1200p_video>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	vdd-supply = <&pm8953_l10>;
+	vddio-supply = <&pm8953_l6>;
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	qcom,ext-vdd-gpio = <&tlmm 100 0>;
+	qcom,platform-bklight-en-gpio = <&tlmm 95 0>;
+
+	qcom,platform-lane-config = [00 00 ff 0f
+				00 00 ff 0f
+				00 00 ff 0f
+				00 00 ff 0f
+				00 00 ff 8f];
+};
+
+&mdss_dsi1 {
+	status = "disabled";
+};
+
 &eeprom0 {
 	gpios = <&tlmm 26 0>,
 		<&tlmm 40 0>,
diff --git a/arch/arm64/boot/dts/qcom/dsi-panel-boent51021-1200p-video.dtsi b/arch/arm64/boot/dts/qcom/dsi-panel-boent51021-1200p-video.dtsi
new file mode 100644
index 0000000..04accd8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/dsi-panel-boent51021-1200p-video.dtsi
@@ -0,0 +1,92 @@
+/* Novatek Android Driver Sample Code for Novatek chipset
+ *
+ * Copyright (C) 2015-2018 Novatek Microelectronics Corp.
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+&mdss_mdp {
+	dsi_boent51021_1200p_video: qcom,mdss_dsi_boent51021_1200p_video {
+		qcom,mdss-dsi-panel-name =
+			"boent51021 1200p video mode dsi panel";
+		qcom,mdss-dsi-panel-controller = <&mdss_dsi0>;
+		qcom,mdss-dsi-panel-type = "dsi_video_mode";
+		qcom,mdss-dsi-panel-framerate = <60>;
+		qcom,mdss-dsi-virtual-channel-id = <0>;
+		qcom,mdss-dsi-stream = <0>;
+		qcom,mdss-dsi-panel-width = <1200>;
+		qcom,mdss-dsi-panel-height = <1920>;
+		qcom,mdss-dsi-h-front-porch = <100>;
+		qcom,mdss-dsi-h-back-porch = <32>;
+		qcom,mdss-dsi-h-pulse-width = <1>;
+		qcom,mdss-dsi-h-sync-skew = <0>;
+		qcom,mdss-dsi-v-back-porch = <14>;
+		qcom,mdss-dsi-v-front-porch = <25>;
+		qcom,mdss-dsi-v-pulse-width = <1>;
+		qcom,mdss-dsi-h-left-border = <0>;
+		qcom,mdss-dsi-h-right-border = <0>;
+		qcom,mdss-dsi-v-top-border = <0>;
+		qcom,mdss-dsi-v-bottom-border = <0>;
+		qcom,mdss-dsi-bpp = <24>;
+		qcom,mdss-dsi-underflow-color = <0xff>;
+		qcom,mdss-dsi-border-color = <0>;
+		qcom,mdss-dsi-on-command = [
+			23 01 00 00 01 00 02 8f a5
+			23 01 00 00 00 00 02 83 00
+			23 01 00 00 00 00 02 84 00
+			23 01 00 00 00 00 02 8c 80
+			23 01 00 00 00 00 02 cd 6c
+			23 01 00 00 00 00 02 c8 fc
+			23 01 00 00 00 00 02 97 00
+			23 01 00 00 00 00 02 8b 10
+			23 01 00 00 00 00 02 a9 20
+			23 01 00 00 00 00 02 83 aa
+			23 01 00 00 00 00 02 84 11
+			23 01 00 00 00 00 02 a9 4b
+			23 01 00 00 00 00 02 85 04
+			23 01 00 00 00 00 02 86 08
+			23 01 00 00 00 00 02 9c 10
+			05 01 00 00 00 00 02 11 00
+			23 01 00 00 00 00 02 8f 00
+		];
+		qcom,mdss-dsi-off-command = [
+			23 01 00 00 00 00 02 83 00
+			23 01 00 00 78 00 02 84 00
+			05 01 00 00 78 00 02 10 00
+		];
+		qcom,mdss-dsi-on-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-off-command-state = "dsi_lp_mode";
+		qcom,mdss-dsi-h-sync-pulse = <1>;
+		qcom,mdss-dsi-traffic-mode = "burst_mode";
+		qcom,mdss-dsi-lane-map = "lane_map_0123";
+		qcom,mdss-dsi-bllp-eof-power-mode;
+		qcom,mdss-dsi-bllp-power-mode;
+		qcom,mdss-dsi-lane-0-state;
+		qcom,mdss-dsi-lane-1-state;
+		qcom,mdss-dsi-lane-2-state;
+		qcom,mdss-dsi-lane-3-state;
+		qcom,mdss-dsi-panel-timings = [
+			f2 3a 28 00 6c 70 2c 3e 2e 03 04 00];
+		qcom,mdss-dsi-t-clk-post = <0x0e>;
+		qcom,mdss-dsi-t-clk-pre = <0x33>;
+		qcom,mdss-dsi-bl-min-level = <1>;
+		qcom,mdss-dsi-bl-max-level = <4095>;
+		qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+		qcom,mdss-dsi-dma-trigger = "trigger_sw";
+		qcom,mdss-dsi-mdp-trigger = "none";
+		qcom,mdss-dsi-force-clock-lane-hs;
+		qcom,mdss-dsi-bl-pmic-control-type = "bl_ctrl_wled";
+		qcom,mdss-pan-physical-width-dimension = <135>;
+		qcom,mdss-pan-physical-height-dimension = <216>;
+		qcom,mdss-dsi-lp11-init;
+		qcom,mdss-dsi-post-init-delay = <1>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
index c86da64..eda92c5 100644
--- a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
@@ -1890,6 +1890,34 @@
 			};
 		};
 
+		cdc_reset_ctrl {
+			cdc_reset_sleep: cdc_reset_sleep {
+				mux {
+					pins = "gpio27";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio27";
+					drive-strength = <16>;
+					bias-disable;
+					output-low;
+				};
+			};
+			cdc_reset_active:cdc_reset_active {
+				mux {
+					pins = "gpio27";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio27"; /* gpio67 old */
+					drive-strength = <16>;
+					bias-pull-down;
+					output-high;
+				};
+			};
+		};
+
+
 		cdc-dmic-lines {
 			cdc_dmic0_clk_act: dmic0_clk_on {
 				mux {
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 3a42017..255c146 100644
--- a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
@@ -54,6 +54,8 @@
 			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;
diff --git a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
index b952908..d085d2d 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
@@ -462,6 +462,8 @@
 
 		reg = <0x619c000 0x1000>;
 		cpu = <&CPU4>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm4";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -481,6 +483,8 @@
 
 		reg = <0x619d000 0x1000>;
 		cpu = <&CPU5>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm5";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -500,6 +504,8 @@
 
 		reg = <0x619e000 0x1000>;
 		cpu = <&CPU6>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm6";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -519,6 +525,8 @@
 
 		reg = <0x619f000 0x1000>;
 		cpu = <&CPU7>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm7";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -538,6 +546,8 @@
 
 		reg = <0x61bc000 0x1000>;
 		cpu = <&CPU0>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm0";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -557,6 +567,8 @@
 
 		reg = <0x61bd000 0x1000>;
 		cpu = <&CPU1>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm1";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -576,6 +588,8 @@
 
 		reg = <0x61be000 0x1000>;
 		cpu = <&CPU2>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm2";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
@@ -594,6 +608,8 @@
 		arm,primecell-periphid = <0x000bb95d>;
 
 		reg = <0x61bf000 0x1000>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm3";
 		cpu = <&CPU3>;
 
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
index 71157e2..2bad28b 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
@@ -22,10 +22,3 @@
 	qcom,board-id = <0xb 2>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
-
-&pmi632_vadc {
-	chan@4a {
-		qcom,scale-function = <22>;
-	};
-};
-
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 67ec032..330d721 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -998,7 +998,7 @@
 		reg-names = "wdt-base";
 		interrupts = <0 3 0>, <0 4 0>;
 		qcom,bark-time = <11000>;
-		qcom,pet-time = <10000>;
+		qcom,pet-time = <9760>;
 		qcom,ipi-ping;
 		qcom,wakeup-enable;
 		status = "okay";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
index 196a526..d3c2e26 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-coresight.dtsi
@@ -505,6 +505,8 @@
 
 		reg = <0x619c000 0x1000>;
 		cpu = <&CPU0>;
+
+		qcom,tupwr-disable;
 		coresight-name = "coresight-etm0";
 
 		clocks = <&clock_gcc clk_qdss_clk>,
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index 7ee30f6..a80b4fe 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -25,6 +25,7 @@
 #include "dsi-panel-lt8912-1080p-video.dtsi"
 #include "dsi-panel-hx8399c-fhd-plus-video.dtsi"
 #include "dsi-panel-hx83100a-800p-video.dtsi"
+#include "dsi-panel-boent51021-1200p-video.dtsi"
 
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -169,3 +170,11 @@
 		1f 1c 05 06 03 03 04 a0
 		1f 10 05 06 03 03 04 a0];
 };
+
+&dsi_boent51021_1200p_video {
+	qcom,mdss-dsi-panel-timings-phy-v2 = [25 20 08 0a 06 03 04 a0
+		25 20 08 0a 06 03 04 a0
+		25 20 08 0a 06 03 04 a0
+		25 20 08 0a 06 03 04 a0
+		25 1d 08 0a 06 03 04 a0];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index cc3c392..e8de4ef 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -1731,5 +1731,19 @@
 				bias-disable;
 			};
 		};
+
+		ssusb_mode_sel: ssusb_mode_sel {
+			mux {
+				pins = "gpio12";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio12";
+				drive-strength = <2>;
+				bias-disable;
+				input-disable;
+			};
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index 0c1bbc2..335bd62 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -1235,7 +1235,7 @@
 		reg-names = "wdt-base";
 		interrupts = <0 3 0>, <0 4 0>;
 		qcom,bark-time = <11000>;
-		qcom,pet-time = <10000>;
+		qcom,pet-time = <9760>;
 		qcom,ipi-ping;
 		qcom,wakeup-enable;
 		qcom,scandump-size = <0x40000>;
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-base.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-base.dts
new file mode 100644
index 0000000..e08acea
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-base.dts
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QCS605 LC CDP Base SoC";
+	compatible = "qcom,qcs605";
+	qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-overlay.dts
new file mode 100644
index 0000000..5987fb3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp-overlay.dts
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include "qcs605-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 CDP";
+	compatible = "qcom,qcs605-cdp", "qcom,qcs605", "qcom,cdp";
+	qcom,msm-id = <347 0x0>;
+	qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dts b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dts
new file mode 100644
index 0000000..753b496
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "qcs605-lc.dtsi"
+#include "qcs605-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. QC605 LC Groot + PM8005 CDP";
+	compatible = "qcom,qcs605-cdp", "qcom,qcs605", "qcom,cdp";
+	qcom,board-id = <1 4>;
+};
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dtsi
new file mode 100644
index 0000000..e32128c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc-cdp.dtsi
@@ -0,0 +1,87 @@
+/*
+ * 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 "qcs605-lc-pmic-overlay.dtsi"
+
+&qupv3_se9_2uart {
+	status = "disabled";
+};
+
+&qupv3_se12_2uart {
+	status = "ok";
+};
+
+&qupv3_se8_spi {
+	status = "disabled";
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm660_l19>;
+	qcom,vdd-voltage-level = <2960000 2960000>;
+	qcom,vdd-current-level = <0 570000>;
+
+	vdd-io-supply = <&pm660_l8>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <0 325000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc1_clk_on  &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+	status = "ok";
+};
+
+&tlmm {
+	sdc2_cd_on: cd_on {
+		mux {
+			pins = "gpio116";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio116";
+			drive-strength = <2>;
+			bias-pull-up;
+			};
+		};
+
+	sdc2_cd_off: cd_off {
+		mux {
+			pins = "gpio116";
+			function = "gpio";
+		};
+
+		config {
+			pins = "gpio116";
+			drive-strength = <2>;
+			bias-disable;
+			};
+	};
+};
+
+&sdhc_2 {
+	/* VDD external regulator is enabled/disabled by pm660_l18 regulator */
+	vdd-io-supply = <&pm660_l18>;
+	qcom,vdd-io-voltage-level = <1800000 2960000>;
+	qcom,vdd-io-current-level = <0 22000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off &sdc2_cd_off>;
+
+	cd-gpios = <&tlmm 116 0x1>;
+
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-camera-sensor-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda670-camera-sensor-hdk.dtsi
new file mode 100644
index 0000000..484ed64
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sda670-camera-sensor-hdk.dtsi
@@ -0,0 +1,412 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	com,camera-flash@0 {
+		cell-index = <0>;
+		reg = <0x00 0x00>;
+		compatible = "qcom,camera-flash";
+		flash-source = <&pm660l_flash0 &pm660l_flash1>;
+		torch-source = <&pm660l_torch0 &pm660l_torch1>;
+		switch-source = <&pm660l_switch0>;
+		status = "ok";
+	};
+
+	qcom,camera-flash@1 {
+		cell-index = <1>;
+		reg = <0x01 0x00>;
+		compatible = "qcom,camera-flash";
+		flash-source = <&pm660l_flash0 &pm660l_flash1>;
+		torch-source = <&pm660l_torch0 &pm660l_torch1>;
+		switch-source = <&pm660l_switch0>;
+		status = "ok";
+	};
+
+	led_flash_front: qcom,camera-flash@2 {
+		cell-index = <2>;
+		reg = <0x02 0x00>;
+		compatible = "qcom,camera-flash";
+		flash-source = <&pm660l_flash2>;
+		torch-source = <&pm660l_torch2>;
+		switch-source = <&pm660l_switch1>;
+		status = "ok";
+	};
+
+	gpio-regulator@0 {
+		compatible = "regulator-fixed";
+		reg = <0x00 0x00>;
+		regulator-name = "actuator_regulator";
+		regulator-min-microvolt = <2800000>;
+		regulator-max-microvolt = <2800000>;
+		regulator-enable-ramp-delay = <100>;
+		enable-active-high;
+		gpio = <&tlmm 27 0>;
+	};
+
+	camera_ldo: gpio-regulator@2 {
+		compatible = "regulator-fixed";
+		reg = <0x02 0x00>;
+		regulator-name = "camera_ldo";
+		regulator-min-microvolt = <1352000>;
+		regulator-max-microvolt = <1352000>;
+		regulator-enable-ramp-delay = <233>;
+		enable-active-high;
+		gpio = <&pm660l_gpios 3 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&camera_dvdd_en_default>;
+		vin-supply = <&pm660_s6>;
+	};
+
+	camera_rear_ldo: gpio-regulator@1 {
+		compatible = "regulator-fixed";
+		reg = <0x01 0x00>;
+		regulator-name = "camera_rear_ldo";
+		regulator-min-microvolt = <1352000>;
+		regulator-max-microvolt = <1352000>;
+		regulator-enable-ramp-delay = <135>;
+		enable-active-high;
+		gpio = <&pm660l_gpios 4 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&camera_rear_dvdd_en_default>;
+		vin-supply = <&pm660_s6>;
+	};
+
+	camera_vio_ldo: gpio-regulator@3 {
+		compatible = "regulator-fixed";
+		reg = <0x03 0x00>;
+		regulator-name = "camera_vio_ldo";
+		regulator-min-microvolt = <1800000>;
+		regulator-max-microvolt = <1800000>;
+		regulator-enable-ramp-delay = <233>;
+		enable-active-high;
+		gpio = <&tlmm 29 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&cam_sensor_rear_vio>;
+		vin-supply = <&pm660_s4>;
+	};
+
+	camera_vana_ldo: gpio-regulator@4 {
+		compatible = "regulator-fixed";
+		reg = <0x04 0x00>;
+		regulator-name = "camera_vana_ldo";
+		regulator-min-microvolt = <2850000>;
+		regulator-max-microvolt = <2850000>;
+		regulator-enable-ramp-delay = <233>;
+		enable-active-high;
+		gpio = <&tlmm 8 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&cam_sensor_rear_vana>;
+		vin-supply = <&pm660l_bob>;
+	};
+};
+
+&cam_cci {
+	qcom,cam-res-mgr {
+		compatible = "qcom,cam-res-mgr";
+		status = "ok";
+	};
+
+	qcom,actuator@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,actuator";
+		cci-master = <0>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <2800000>;
+		rgltr-max-voltage = <2800000>;
+		rgltr-load-current = <0>;
+	};
+
+	qcom,actuator@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,actuator";
+		cci-master = <1>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <2800000>;
+		rgltr-max-voltage = <2800000>;
+		rgltr-load-current = <0>;
+	};
+
+	qcom,actuator@2 {
+		cell-index = <2>;
+		reg = <0x2>;
+		compatible = "qcom,actuator";
+		cci-master = <1>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <2800000>;
+		rgltr-max-voltage = <2800000>;
+		rgltr-load-current = <0>;
+	};
+
+	ois_rear: qcom,ois@0 {
+		cell-index = <0>;
+		reg = <0x0>;
+		compatible = "qcom,ois";
+		cci-master = <0>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <2800000>;
+		rgltr-max-voltage = <2800000>;
+		rgltr-load-current = <0>;
+		status = "disabled";
+	};
+
+	qcom,eeprom@0 {
+		cell-index = <0>;
+		reg = <0>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_rear_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+			"cam_clk", "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1800000 2850000 1352000 0 2800000>;
+		rgltr-max-voltage = <1800000 2850000 1352000 0 2800000>;
+		rgltr-load-current = <0 80000 105000 0 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>;
+	};
+
+	qcom,eeprom@1 {
+		cell-index = <1>;
+		reg = <0x1>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+			"cam_clk", "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1352000 1800000 2850000 0 2800000>;
+		rgltr-max-voltage = <1352000 1800000 2850000 0 2800000>;
+		rgltr-load-current = <105000 0 80000 0 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>;
+		gpio-reset = <1>;
+		gpio-req-tbl-num = <0 1>;
+		gpio-req-tbl-flags = <1 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1";
+		sensor-position = <0>;
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+
+	qcom,eeprom@2 {
+		cell-index = <2>;
+		reg = <0x2>;
+		compatible = "qcom,eeprom";
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		cam_vaf-supply = <&actuator_regulator>;
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+			"cam_clk", "cam_vaf";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1352000 1800000 2850000 0 2800000>;
+		rgltr-max-voltage = <1352000 1800000 2850000 0 2800000>;
+		rgltr-load-current = <105000 0 80000 0 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>;
+		gpio-reset = <1>;
+		gpio-req-tbl-num = <0 1>;
+		gpio-req-tbl-flags = <1 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1";
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@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>;
+		actuator-src = <&actuator_rear>;
+		ois-src = <&ois_rear>;
+		eeprom-src = <&eeprom_rear>;
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_rear_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vio", "cam_vana", "cam_vdig",
+			"cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1800000 2850000 1352000 0>;
+		rgltr-max-voltage = <1800000 2850000 1352000 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>;
+	};
+
+	qcom,cam-sensor@1 {
+		cell-index = <1>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x1>;
+		csiphy-sd-index = <1>;
+		sensor-position-roll = <270>;
+		sensor-position-pitch = <0>;
+		sensor-position-yaw = <180>;
+		led-flash-src = <&led_flash_rear_aux>;
+		actuator-src = <&actuator_rear_aux>;
+		eeprom-src = <&eeprom_rear_aux>;
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+			"cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1352000 1800000 2850000 0>;
+		rgltr-max-voltage = <1352000 1800000 2850000 0>;
+		rgltr-load-current = <105000 0 80000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>;
+		gpio-reset = <1>;
+		gpio-req-tbl-num = <0 1>;
+		gpio-req-tbl-flags = <1 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1";
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+
+	qcom,cam-sensor@2 {
+		cell-index = <2>;
+		compatible = "qcom,cam-sensor";
+		reg = <0x02>;
+		csiphy-sd-index = <2>;
+		sensor-position-roll = <270>;
+		sensor-position-pitch = <0>;
+		sensor-position-yaw = <0>;
+		eeprom-src = <&eeprom_front>;
+		actuator-src = <&actuator_front>;
+		led-flash-src = <&led_flash_front>;
+		cam_vio-supply = <&camera_vio_ldo>;
+		cam_vana-supply = <&camera_vana_ldo>;
+		cam_vdig-supply = <&camera_ldo>;
+		cam_clk-supply = <&titan_top_gdsc>;
+		regulator-names = "cam_vdig", "cam_vio", "cam_vana",
+			"cam_clk";
+		rgltr-cntrl-support;
+		rgltr-min-voltage = <1352000 1800000 2850000 0>;
+		rgltr-max-voltage = <1352000 1800000 2850000 0>;
+		rgltr-load-current = <105000 0 80000 0>;
+		gpio-no-mux = <0>;
+		pinctrl-names = "cam_default", "cam_suspend";
+		pinctrl-0 = <&cam_sensor_mclk1_active
+				&cam_sensor_rear2_active>;
+		pinctrl-1 = <&cam_sensor_mclk1_suspend
+				&cam_sensor_rear2_suspend>;
+		gpios = <&tlmm 14 0>,
+			<&tlmm 28 0>;
+		gpio-reset = <1>;
+		gpio-req-tbl-num = <0 1>;
+		gpio-req-tbl-flags = <1 0>;
+		gpio-req-tbl-label = "CAMIF_MCLK1",
+					"CAM_RESET1";
+		sensor-mode = <0>;
+		cci-master = <1>;
+		status = "ok";
+		clocks = <&clock_camcc CAM_CC_MCLK1_CLK>;
+		clock-names = "cam_clk";
+		clock-cntl-level = "turbo";
+		clock-rates = <24000000>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
index 4daf8b4..8471d11 100644
--- a/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
+++ b/arch/arm64/boot/dts/qcom/sda670-hdk.dtsi
@@ -11,6 +11,7 @@
  */
 #include "sdm670-qrd.dtsi"
 #include "sdm670-external-codec.dtsi"
+#include "sda670-camera-sensor-hdk.dtsi"
 
 &dsi_dual_nt36850_truly_cmd_display {
 	/delete-property/ qcom,dsi-display-active;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
index 7a61a7a..a940515 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
@@ -570,11 +570,11 @@
 &tlmm {
 	smb_int_default: smb_int_default {
 		mux {
-			pins = "gpio59";
+			pins = "gpio61";
 			function = "gpio";
 		};
 		config {
-			pins = "gpio59";
+			pins = "gpio61";
 			drive-strength = <2>;
 			bias-pull-up;
 			input-enable;
@@ -587,7 +587,7 @@
 	pinctrl-0 = <&smb_int_default
 		&smb_en_default &pmi632_sense_default>;
 	interrupt-parent = <&tlmm>;
-	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_0: qcom,smb1355-charger@1000 {
 		status ="ok";
 		/delete-property/ io-channels;
@@ -601,7 +601,7 @@
 	pinctrl-0 = <&smb_int_default
 		&smb_en_default &pmi632_sense_default>;
 	interrupt-parent = <&tlmm>;
-	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_1: qcom,smb1355-charger@1000 {
 		status ="ok";
 		/delete-property/ io-channels;
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
index b8a9f2b..4a2fbff 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
@@ -22,10 +22,3 @@
 	qcom,board-id = <0xb 2>;
 	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
 };
-
-&pmi632_vadc {
-	chan@4a {
-		qcom,scale-function = <22>;
-	};
-};
-
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
index 5b3caf7..ac31fc8 100644
--- a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -348,6 +348,12 @@
 #include "smb1355.dtsi"
 };
 
+&pmi632_vadc {
+	chan@4a {
+		qcom,scale-function = <22>;
+	};
+};
+
 &pmi632_gpios {
 	smb_en {
 		smb_en_default: smb_en_default {
@@ -370,11 +376,11 @@
 &tlmm {
 	smb_int_default: smb_int_default {
 		mux {
-			pins = "gpio59";
+			pins = "gpio61";
 			function = "gpio";
 		};
 		config {
-			pins = "gpio59";
+			pins = "gpio61";
 			drive-strength = <2>;
 			bias-pull-up;
 			input-enable;
@@ -387,7 +393,7 @@
 	pinctrl-0 = <&smb_int_default
 		&smb_en_default &pmi632_sense_default>;
 	interrupt-parent = <&tlmm>;
-	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_0: qcom,smb1355-charger@1000 {
 		status ="ok";
 		/delete-property/ io-channels;
@@ -401,7 +407,7 @@
 	pinctrl-0 = <&smb_int_default
 		&smb_en_default &pmi632_sense_default>;
 	interrupt-parent = <&tlmm>;
-	interrupts = <59 IRQ_TYPE_LEVEL_LOW>;
+	interrupts = <61 IRQ_TYPE_LEVEL_LOW>;
 	smb1355_charger_1: qcom,smb1355-charger@1000 {
 		status ="ok";
 		/delete-property/ io-channels;
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp-overlay.dts
new file mode 100644
index 0000000..c3aa763
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp-overlay.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/;
+/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 "sxr1120-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 CDP";
+	compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+	qcom,msm-id = <370 0x0>;
+	qcom,board-id = <1 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dts
new file mode 100644
index 0000000..6237873
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-cdp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 CDP";
+	compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+	qcom,board-id = <1 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dtsi
new file mode 100644
index 0000000..d4d42c5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-cdp.dtsi
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "qcs605-lc-cdp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp-overlay.dts
new file mode 100644
index 0000000..e90f3b4
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp-overlay.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sxr1120-lc-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec CDP";
+	compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+	qcom,msm-id = <370 0x0>;
+	qcom,board-id = <1 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp.dts
new file mode 100644
index 0000000..76c424d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-cdp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec CDP";
+	compatible = "qcom,sxr1120-cdp", "qcom,sxr1120", "qcom,cdp";
+	qcom,board-id = <1 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp-overlay.dts
new file mode 100644
index 0000000..946298f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp-overlay.dts
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+/plugin/;
+
+#include <dt-bindings/clock/qcom,gcc-sdm845.h>
+#include <dt-bindings/clock/qcom,camcc-sdm845.h>
+#include <dt-bindings/clock/qcom,dispcc-sdm845.h>
+#include <dt-bindings/clock/qcom,rpmh.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+#include "sxr1120-lc-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec MTP";
+	compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+	qcom,msm-id = <370 0x0>;
+	qcom,board-id = <8 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp.dts
new file mode 100644
index 0000000..e53bbe3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-external-codec-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 Ext. Audio Codec MTP";
+	compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+	qcom,board-id = <8 1>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp-overlay.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp-overlay.dts
new file mode 100644
index 0000000..8af46ef
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp-overlay.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/;
+/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 "sxr1120-lc-mtp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 MTP";
+	compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+	qcom,msm-id = <370 0x0>;
+	qcom,board-id = <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dts
new file mode 100644
index 0000000..ffcdeda
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dts
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+/dts-v1/;
+
+#include "sxr1120-lc.dtsi"
+#include "sxr1120-lc-mtp.dtsi"
+#include "qcs605-lc-audio-overlay.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC Groot+PM8005 MTP";
+	compatible = "qcom,sxr1120-mtp", "qcom,sxr1120", "qcom,mtp";
+	qcom,board-id = <8 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
new file mode 100644
index 0000000..270aa0e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc-mtp.dtsi
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "qcs605-lc-mtp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc.dts b/arch/arm64/boot/dts/qcom/sxr1120-lc.dts
new file mode 100644
index 0000000..5967388
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc.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 "sxr1120-lc.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 LC SoC";
+	compatible = "qcom,sxr1120";
+	qcom,board-id = <0 0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
new file mode 100644
index 0000000..1413e2c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sxr1120-lc.dtsi
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "qcs605-lc.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SXR1120 SoC";
+	compatible = "qcom,sxr1120";
+	qcom,msm-id = <370 0x0>;
+};
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index bb98179..92e369e 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -73,7 +73,6 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
-CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index fb1c316..fc1eb458 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -76,7 +76,6 @@
 CONFIG_SWP_EMULATION=y
 CONFIG_CP15_BARRIER_EMULATION=y
 CONFIG_SETEND_EMULATION=y
-CONFIG_ARM64_SW_TTBR0_PAN=y
 # CONFIG_ARM64_VHE is not set
 CONFIG_RANDOMIZE_BASE=y
 CONFIG_BUILD_ARM64_APPENDED_DTB_IMAGE=y
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index 7d8605b..d52c80c 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -1567,9 +1567,18 @@
 		if (map && (map->attr & FASTRPC_ATTR_COHERENT))
 			continue;
 
-		if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart)
-			dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
-			uint64_to_ptr(rpra[i].buf.pv + rpra[i].buf.len));
+		if (rpra && rpra[i].buf.len && ctx->overps[oix]->mstart) {
+			if (map && map->handle)
+				msm_ion_do_cache_op(ctx->fl->apps->client,
+					map->handle,
+					uint64_to_ptr(rpra[i].buf.pv),
+					rpra[i].buf.len,
+					ION_IOC_CLEAN_INV_CACHES);
+			else
+				dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
+					uint64_to_ptr(rpra[i].buf.pv
+						+ rpra[i].buf.len));
+		}
 	}
 	PERF_END);
 	for (i = bufs; rpra && i < bufs + handles; i++) {
@@ -1578,11 +1587,6 @@
 		rpra[i].dma.offset = (uint32_t)(uintptr_t)lpra[i].buf.pv;
 	}
 
-	if (!ctx->fl->sctx->smmu.coherent) {
-		PERF(ctx->fl->profile, GET_COUNTER(perf_counter, PERF_FLUSH),
-		dmac_flush_range((char *)rpra, (char *)rpra + ctx->used);
-		PERF_END);
-	}
  bail:
 	return err;
 }
@@ -1671,14 +1675,33 @@
 		if (buf_page_start(ptr_to_uint64((void *)rpra)) ==
 				buf_page_start(rpra[i].buf.pv))
 			continue;
-		if (!IS_CACHE_ALIGNED((uintptr_t)uint64_to_ptr(rpra[i].buf.pv)))
-			dmac_flush_range(uint64_to_ptr(rpra[i].buf.pv),
-				(char *)(uint64_to_ptr(rpra[i].buf.pv + 1)));
+		if (!IS_CACHE_ALIGNED((uintptr_t)
+				uint64_to_ptr(rpra[i].buf.pv))) {
+			if (map && map->handle)
+				msm_ion_do_cache_op(ctx->fl->apps->client,
+					map->handle,
+					uint64_to_ptr(rpra[i].buf.pv),
+					sizeof(uintptr_t),
+					ION_IOC_CLEAN_INV_CACHES);
+			else
+				dmac_flush_range(
+					uint64_to_ptr(rpra[i].buf.pv), (char *)
+					uint64_to_ptr(rpra[i].buf.pv + 1));
+		}
+
 		end = (uintptr_t)uint64_to_ptr(rpra[i].buf.pv +
 							rpra[i].buf.len);
-		if (!IS_CACHE_ALIGNED(end))
-			dmac_flush_range((char *)end,
-				(char *)end + 1);
+		if (!IS_CACHE_ALIGNED(end)) {
+			if (map && map->handle)
+				msm_ion_do_cache_op(ctx->fl->apps->client,
+						map->handle,
+						uint64_to_ptr(end),
+						sizeof(uintptr_t),
+						ION_IOC_CLEAN_INV_CACHES);
+			else
+				dmac_flush_range((char *)end,
+					(char *)end + 1);
+		}
 	}
 }
 
@@ -1687,7 +1710,6 @@
 	int i, inbufs, outbufs;
 	uint32_t sc = ctx->sc;
 	remote_arg64_t *rpra = ctx->rpra;
-	int used = ctx->used;
 
 	inbufs = REMOTE_SCALARS_INBUFS(sc);
 	outbufs = REMOTE_SCALARS_OUTBUFS(sc);
@@ -1718,8 +1740,6 @@
 						 + rpra[i].buf.len));
 	}
 
-	if (rpra)
-		dmac_inv_range(rpra, (char *)rpra + used);
 }
 
 static int fastrpc_invoke_send(struct smq_invoke_ctx *ctx,
diff --git a/drivers/extcon/extcon-usb-gpio.c b/drivers/extcon/extcon-usb-gpio.c
index 2e093c3..2b108fa 100644
--- a/drivers/extcon/extcon-usb-gpio.c
+++ b/drivers/extcon/extcon-usb-gpio.c
@@ -277,9 +277,8 @@
 	if (info->vbus_gpiod)
 		enable_irq(info->vbus_irq);
 
-	if (!device_may_wakeup(dev))
-		queue_delayed_work(system_power_efficient_wq,
-				   &info->wq_detcable, 0);
+	queue_delayed_work(system_power_efficient_wq,
+			   &info->wq_detcable, 0);
 
 	return ret;
 }
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index f5c24e2..34a3d5f 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -2380,7 +2380,6 @@
 	struct sde_crtc *sde_crtc;
 	struct sde_kms *sde_kms;
 	unsigned long flags;
-	bool frame_done = false;
 	bool in_clone_mode = false;
 
 	if (!work) {
@@ -2435,10 +2434,6 @@
 			SDE_EVT32_VERBOSE(DRMID(crtc), fevent->event,
 							SDE_EVTLOG_FUNC_CASE3);
 		}
-
-		if (fevent->event & (SDE_ENCODER_FRAME_EVENT_DONE
-					| SDE_ENCODER_FRAME_EVENT_ERROR))
-			frame_done = true;
 	}
 
 	if (fevent->event & SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE) {
@@ -2459,9 +2454,6 @@
 		SDE_ERROR("crtc%d ts:%lld received panel dead event\n",
 				crtc->base.id, ktime_to_ns(fevent->ts));
 
-	if (frame_done)
-		complete_all(&sde_crtc->frame_done_comp);
-
 	spin_lock_irqsave(&sde_crtc->spin_lock, flags);
 	list_add_tail(&fevent->list, &sde_crtc->frame_event_list);
 	spin_unlock_irqrestore(&sde_crtc->spin_lock, flags);
@@ -3341,10 +3333,10 @@
 			&cstate->property_state);
 }
 
-static int _sde_crtc_wait_for_frame_done(struct drm_crtc *crtc)
+static int _sde_crtc_flush_event_thread(struct drm_crtc *crtc)
 {
 	struct sde_crtc *sde_crtc;
-	int ret, rc = 0, i;
+	int i;
 
 	if (!crtc) {
 		SDE_ERROR("invalid argument\n");
@@ -3368,17 +3360,9 @@
 			kthread_flush_work(&sde_crtc->frame_events[i].work);
 	}
 
-	ret = wait_for_completion_timeout(&sde_crtc->frame_done_comp,
-			msecs_to_jiffies(SDE_FRAME_DONE_TIMEOUT));
-	if (!ret) {
-		SDE_ERROR("frame done completion wait timed out, ret:%d\n",
-				ret);
-		SDE_EVT32(DRMID(crtc), SDE_EVTLOG_FATAL);
-		rc = -ETIMEDOUT;
-	}
 	SDE_EVT32_VERBOSE(DRMID(crtc), SDE_EVTLOG_FUNC_EXIT);
 
-	return rc;
+	return 0;
 }
 
 static int _sde_crtc_commit_kickoff_rot(struct drm_crtc *crtc,
@@ -3705,7 +3689,6 @@
 	struct sde_kms *sde_kms;
 	struct sde_crtc_state *cstate;
 	bool is_error, reset_req;
-	int ret;
 
 	if (!crtc) {
 		SDE_ERROR("invalid argument\n");
@@ -3764,23 +3747,11 @@
 	}
 	sde_crtc->reset_request = reset_req;
 
-	/* wait for frame_event_done completion */
-	SDE_ATRACE_BEGIN("wait_for_frame_done_event");
-	ret = _sde_crtc_wait_for_frame_done(crtc);
-	SDE_ATRACE_END("wait_for_frame_done_event");
+	SDE_ATRACE_BEGIN("flush_event_thread");
+	_sde_crtc_flush_event_thread(crtc);
+	SDE_ATRACE_END("flush_event_thread");
 	sde_crtc_calc_fps(sde_crtc);
 
-	if (ret) {
-		SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
-				crtc->base.id,
-				atomic_read(&sde_crtc->frame_pending));
-
-		is_error = true;
-
-		/* force offline rotation mode since the commit has no pipes */
-		cstate->sbuf_cfg.rot_op_mode = SDE_CTL_ROT_OP_MODE_OFFLINE;
-	}
-
 	if (atomic_inc_return(&sde_crtc->frame_pending) == 1) {
 		/* acquire bandwidth and other resources */
 		SDE_DEBUG("crtc%d first commit\n", crtc->base.id);
@@ -3818,7 +3789,6 @@
 		sde_encoder_kickoff(encoder, false);
 	}
 
-	reinit_completion(&sde_crtc->frame_done_comp);
 	SDE_ATRACE_END("crtc_commit");
 	return;
 }
@@ -4219,11 +4189,7 @@
 	if (cstate->num_ds_enabled)
 		sde_crtc->ds_reconfig = true;
 
-	/* wait for frame_event_done completion */
-	if (_sde_crtc_wait_for_frame_done(crtc))
-		SDE_ERROR("crtc%d wait for frame done failed;frame_pending%d\n",
-				crtc->base.id,
-				atomic_read(&sde_crtc->frame_pending));
+	_sde_crtc_flush_event_thread(crtc);
 
 	SDE_EVT32(DRMID(crtc), sde_crtc->enabled, sde_crtc->suspend,
 			sde_crtc->vblank_requested,
@@ -4238,6 +4204,8 @@
 	sde_crtc->enabled = false;
 
 	if (atomic_read(&sde_crtc->frame_pending)) {
+		SDE_ERROR("crtc%d frame_pending%d\n", crtc->base.id,
+				atomic_read(&sde_crtc->frame_pending));
 		SDE_EVT32(DRMID(crtc), atomic_read(&sde_crtc->frame_pending),
 							SDE_EVTLOG_FUNC_CASE2);
 		sde_core_perf_crtc_release_bw(crtc);
@@ -4731,8 +4699,6 @@
 
 	for (i = 1; i < SSPP_MAX; i++) {
 		if (pipe_staged[i]) {
-			sde_plane_clear_multirect(pipe_staged[i]);
-
 			if (is_sde_plane_virtual(pipe_staged[i]->plane)) {
 				SDE_ERROR(
 					"r1 only virt plane:%d not supported\n",
@@ -4740,6 +4706,7 @@
 				rc  = -EINVAL;
 				goto end;
 			}
+			sde_plane_clear_multirect(pipe_staged[i]);
 		}
 	}
 
@@ -6097,7 +6064,6 @@
 	mutex_init(&sde_crtc->rp_lock);
 	INIT_LIST_HEAD(&sde_crtc->rp_head);
 
-	init_completion(&sde_crtc->frame_done_comp);
 	sde_crtc->enabled = false;
 
 	INIT_LIST_HEAD(&sde_crtc->frame_event_list);
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.h b/drivers/gpu/drm/msm/sde/sde_crtc.h
index c02a81e..99177b1 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.h
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.h
@@ -190,7 +190,6 @@
  * @frame_events  : static allocation of in-flight frame events
  * @frame_event_list : available frame event list
  * @spin_lock     : spin lock for frame event, transaction status, etc...
- * @frame_done_comp    : for frame_event_done synchronization
  * @event_thread  : Pointer to event handler thread
  * @event_worker  : Event worker queue
  * @event_cache   : Local cache of event worker structures
@@ -262,7 +261,6 @@
 	struct sde_crtc_frame_event frame_events[SDE_CRTC_FRAME_EVENT_SIZE];
 	struct list_head frame_event_list;
 	spinlock_t spin_lock;
-	struct completion frame_done_comp;
 
 	/* for handling internal event thread */
 	struct sde_crtc_event event_cache[SDE_CRTC_MAX_EVENT_COUNT];
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index b54c152..f9a59b0 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -1489,12 +1489,13 @@
 
 		vsync_cfg.pp_count = sde_enc->num_phys_encs;
 		vsync_cfg.frame_rate = mode_info.frame_rate;
+		vsync_cfg.vsync_source =
+			sde_enc->cur_master->hw_pp->caps->te_source;
 		if (is_dummy)
 			vsync_cfg.vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_1;
 		else if (disp_info->is_te_using_watchdog_timer)
 			vsync_cfg.vsync_source = SDE_VSYNC_SOURCE_WD_TIMER_0;
-		else
-			vsync_cfg.vsync_source = SDE_VSYNC0_SOURCE_GPIO;
+
 		vsync_cfg.is_dummy = is_dummy;
 
 		hw_mdptop->ops.setup_vsync_source(hw_mdptop, &vsync_cfg);
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index 475f8d0..baec526 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -249,6 +249,7 @@
 	DITHER_OFF,
 	DITHER_LEN,
 	DITHER_VER,
+	TE_SOURCE,
 	PP_PROP_MAX,
 };
 
@@ -589,6 +590,7 @@
 	{DITHER_OFF, "qcom,sde-dither-off", false, PROP_TYPE_U32_ARRAY},
 	{DITHER_LEN, "qcom,sde-dither-size", false, PROP_TYPE_U32},
 	{DITHER_VER, "qcom,sde-dither-version", false, PROP_TYPE_U32},
+	{TE_SOURCE, "qcom,sde-te-source", false, PROP_TYPE_U32_ARRAY},
 };
 
 static struct sde_prop_type dsc_prop[] = {
@@ -2628,6 +2630,10 @@
 		snprintf(pp->name, SDE_HW_BLK_NAME_LEN, "pingpong_%u",
 				pp->id - PINGPONG_0);
 		pp->len = PROP_VALUE_ACCESS(prop_value, PP_LEN, 0);
+		pp->te_source = PROP_VALUE_ACCESS(prop_value, TE_SOURCE, i);
+		if (!prop_exists[TE_SOURCE] ||
+			pp->te_source > SDE_VSYNC_SOURCE_WD_TIMER_0)
+			pp->te_source = SDE_VSYNC0_SOURCE_GPIO;
 
 		sblk->te.base = PROP_VALUE_ACCESS(prop_value, TE_OFF, i);
 		sblk->te.id = SDE_PINGPONG_TE;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index 65919e9..52bdc78 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -653,6 +653,7 @@
  */
 struct sde_pingpong_cfg  {
 	SDE_HW_BLK_INFO;
+	u32 te_source;
 	const struct sde_pingpong_sub_blks *sblk;
 };
 
diff --git a/drivers/gpu/drm/msm/sde/sde_plane.c b/drivers/gpu/drm/msm/sde/sde_plane.c
index 2e46599..dc55ad5 100644
--- a/drivers/gpu/drm/msm/sde/sde_plane.c
+++ b/drivers/gpu/drm/msm/sde/sde_plane.c
@@ -3449,6 +3449,25 @@
 				src_w, src_h);
 			return -EINVAL;
 		}
+
+		/*
+		 * SSPP fetch , unpack output and QSEED3 input lines need
+		 * to match for Y plane
+		 */
+		if (i == 0 &&
+			(sde_plane_get_property(pstate, PLANE_PROP_SRC_CONFIG) &
+			BIT(SDE_DRM_DEINTERLACE)) &&
+			((pstate->scaler3_cfg.src_height[i] != (src_h/2)) ||
+			(pstate->pixel_ext.roi_h[i] != (src_h/2)))) {
+			SDE_ERROR_PLANE(psde,
+				"de-interlace fail roi[%d] %d/%d, src %dx%d, src %dx%d\n",
+				i, pstate->pixel_ext.roi_w[i],
+				pstate->pixel_ext.roi_h[i],
+				pstate->scaler3_cfg.src_width[i],
+				pstate->scaler3_cfg.src_height[i],
+				src_w, src_h);
+			return -EINVAL;
+		}
 	}
 
 	pstate->scaler_check_state = SDE_PLANE_SCLCHECK_SCALER_V2;
diff --git a/drivers/hwtracing/coresight/coresight-etm3x.c b/drivers/hwtracing/coresight/coresight-etm3x.c
index 3bbcc95..04870ce 100644
--- a/drivers/hwtracing/coresight/coresight-etm3x.c
+++ b/drivers/hwtracing/coresight/coresight-etm3x.c
@@ -712,10 +712,6 @@
 
 	CS_UNLOCK(drvdata->base);
 
-	/* check the state of the fuse */
-	if (!coresight_authstatus_enabled(drvdata->base))
-		goto out;
-
 	/* First dummy read */
 	(void)etm_readl(drvdata, ETMPDSR);
 	/* Provide power to ETM: ETMPDCR[3] == 1 */
@@ -725,6 +721,11 @@
 	 * certain registers might be ignored.
 	 */
 	etm_clr_pwrdwn(drvdata);
+
+	/* check the state of the fuse */
+	if (!coresight_authstatus_enabled(drvdata->base))
+		goto out;
+
 	/*
 	 * Set prog bit. It will be set from reset but this is included to
 	 * ensure it is set
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index 5db74f0..95d13a9 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -27,6 +27,7 @@
 #include <linux/cpu.h>
 #include <linux/coresight.h>
 #include <linux/coresight-pmu.h>
+#include <linux/of.h>
 #include <linux/pm_wakeup.h>
 #include <linux/amba/bus.h>
 #include <linux/seq_file.h>
@@ -167,12 +168,14 @@
 	writel_relaxed(config->vmid_mask0, drvdata->base + TRCVMIDCCTLR0);
 	writel_relaxed(config->vmid_mask1, drvdata->base + TRCVMIDCCTLR1);
 
-	/*
-	 * Request to keep the trace unit powered and also
-	 * emulation of powerdown
-	 */
-	writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR) | TRCPDCR_PU,
-		       drvdata->base + TRCPDCR);
+	if (!drvdata->tupwr_disable) {
+		/*
+		 * Request to keep the trace unit powered and also
+		 * emulation of powerdown
+		 */
+		writel_relaxed(readl_relaxed(drvdata->base + TRCPDCR)
+				| TRCPDCR_PU, drvdata->base + TRCPDCR);
+	}
 
 	/* Enable the trace unit */
 	writel_relaxed(1, drvdata->base + TRCPRGCTLR);
@@ -313,10 +316,12 @@
 
 	CS_UNLOCK(drvdata->base);
 
-	/* power can be removed from the trace unit now */
-	control = readl_relaxed(drvdata->base + TRCPDCR);
-	control &= ~TRCPDCR_PU;
-	writel_relaxed(control, drvdata->base + TRCPDCR);
+	if (!drvdata->tupwr_disable) {
+		/* power can be removed from the trace unit now */
+		control = readl_relaxed(drvdata->base + TRCPDCR);
+		control &= ~TRCPDCR_PU;
+		writel_relaxed(control, drvdata->base + TRCPDCR);
+	}
 
 	control = readl_relaxed(drvdata->base + TRCPRGCTLR);
 
@@ -1041,6 +1046,9 @@
 
 	etmdrvdata[drvdata->cpu] = drvdata;
 
+	drvdata->tupwr_disable = of_property_read_bool(drvdata->dev->of_node,
+				"qcom,tupwr-disable");
+
 	dev_info(dev, "CPU%d: %s initialized\n",
 			drvdata->cpu, (char *)id->data);
 
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 4e51ecdc..5f34bdc 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2015, 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2015, 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -345,6 +345,7 @@
  * @nooverflow:	Indicate if overflow prevention is supported.
  * @atbtrig:	If the implementation can support ATB triggers
  * @lpoverride:	If the implementation can support low-power state over.
+ * @tupwr_disable:	If disable the support of keeping trace unit powered.
  * @config:	structure holding configuration parameters.
  */
 struct etmv4_drvdata {
@@ -391,6 +392,7 @@
 	bool				nooverflow;
 	bool				atbtrig;
 	bool				lpoverride;
+	bool				tupwr_disable;
 	struct etmv4_config		config;
 };
 
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c
index 9968e44..0ebc9ab 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_bsp.c
@@ -99,7 +99,6 @@
 {
 	int result = MPU_SUCCESS;
 	char tx_buf[2] = {0x0, 0x0};
-	int tmp_size = size;
 	u8 *tmp_buf = buf;
 	struct i2c_msg msg[2];
 
@@ -225,7 +224,7 @@
 {
 	struct struct_icm20602_raw_data raw_data;
 
-	if (type & ACCEL != 0) {
+	if ((type) & (ACCEL) != 0) {
 		icm20602_read_reg(st,
 			reg_set_20602.ACCEL_XOUT_H.address,
 			&raw_data.ACCEL_XOUT_H);
@@ -257,7 +256,7 @@
 			raw_data.ACCEL_ZOUT_L);
 	}
 
-	if (type & GYRO != 0) {
+	if ((type) & (GYRO) != 0) {
 		icm20602_read_reg(st,
 			reg_set_20602.GYRO_XOUT_H.address,
 			&raw_data.GYRO_XOUT_H);
@@ -327,7 +326,7 @@
 	return MPU_SUCCESS;
 }
 
-static int icm20602_stop_fifo(struct inv_icm20602_state *st)
+int icm20602_stop_fifo(struct inv_icm20602_state *st)
 {
 	struct icm20602_user_config *config = NULL;
 
@@ -434,10 +433,7 @@
 static int icm20602_set_self_test(struct inv_icm20602_state *st)
 {
 	uint8_t raw_data[6] = {0, 0, 0, 0, 0, 0};
-	uint8_t selfTest[6];
-	float factory_trim[6];
 	int result = 0;
-	int ii;
 
 	reg_set_20602.SMPLRT_DIV.reg_u.REG.SMPLRT_DIV = 0;
 	result |= icm20602_write_reg_simple(st, reg_set_20602.SMPLRT_DIV);
@@ -456,7 +452,7 @@
 	reg_set_20602.ACCEL_CONFIG.reg_u.REG.ACCEL_FS_SEL = ICM20602_ACC_FSR_2G;
 	result |= icm20602_write_reg_simple(st, reg_set_20602.ACCEL_CONFIG);
 
-	//icm20602_read_ST_code(st);
+	icm20602_read_ST_code(st);
 
 	return 0;
 }
@@ -466,8 +462,7 @@
 {
 	struct struct_icm20602_real_data *real_data =
 		kmalloc(sizeof(struct inv_icm20602_state), GFP_ATOMIC);
-	struct icm20602_user_config *config = st->config;
-	int i, j;
+	int i;
 
 	for (i = 0; i < SELFTEST_COUNT; i++) {
 		icm20602_read_raw(st, real_data, ACCEL);
@@ -514,7 +509,7 @@
 {
 	struct struct_icm20602_real_data *real_data =
 		kmalloc(sizeof(struct inv_icm20602_state), GFP_ATOMIC);
-	int i, j;
+	int i;
 
 	for (i = 0; i < SELFTEST_COUNT; i++) {
 		icm20602_read_raw(st, real_data, GYRO);
@@ -570,7 +565,7 @@
 	st_otp.Y = (st_otp.Y != 0) ? mpu_st_tb[acc_ST_code.Y - 1] : 0;
 	st_otp.Z = (st_otp.Z != 0) ? mpu_st_tb[acc_ST_code.Z - 1] : 0;
 
-	if (st_otp.X & st_otp.Y & st_otp.Z == 0)
+	if ((st_otp.X) & (st_otp.Y) & (st_otp.Z) == 0)
 		otp_value_zero = true;
 
 	st_shift_cust.X = acc_st->X - acc->X;
@@ -627,11 +622,11 @@
 	gyro_ST_code.Y = st->config->gyro_self_test.Y;
 	gyro_ST_code.Z = st->config->gyro_self_test.Z;
 
-	st_otp.X = (st_otp.X != 0) ? mpu_st_tb[gyro_ST_code.X - 1] : 0;
-	st_otp.Y = (st_otp.Y != 0) ? mpu_st_tb[gyro_ST_code.Y - 1] : 0;
-	st_otp.Z = (st_otp.Z != 0) ? mpu_st_tb[gyro_ST_code.Z - 1] : 0;
+	st_otp.X = (gyro_ST_code.X != 0) ? mpu_st_tb[gyro_ST_code.X - 1] : 0;
+	st_otp.Y = (gyro_ST_code.Y != 0) ? mpu_st_tb[gyro_ST_code.Y - 1] : 0;
+	st_otp.Z = (gyro_ST_code.Z != 0) ? mpu_st_tb[gyro_ST_code.Z - 1] : 0;
 
-	if (st_otp.X & st_otp.Y & st_otp.Z == 0)
+	if ((st_otp.X) & (st_otp.Y) & (st_otp.Z) == 0)
 		otp_value_zero = true;
 
 	st_shift_cust.X = gyro_st->X - gyro->X;
@@ -741,8 +736,6 @@
 {
 	struct icm20602_user_config *config = NULL;
 	int result = MPU_SUCCESS;
-	int sample_rate;
-	uint8_t fchoice_b;
 
 	if (st == NULL)
 		return -MPU_FAIL;
@@ -928,7 +921,6 @@
 {
 	int result = MPU_SUCCESS;
 	uint8_t retry = 0, val = 0;
-	uint8_t usr_ctrl = 0;
 
 	pr_debug("icm20602_detect\n");
 	/* reset to make sure previous state are not there */
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
index 15df447..7dda14e 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_core.c
@@ -29,6 +29,7 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include "inv_icm20602_iio.h"
+#include <linux/regulator/consumer.h>
 
 /* Attribute of icm20602 device init show */
 static ssize_t inv_icm20602_init_show(struct device *dev,
@@ -89,7 +90,10 @@
 static ssize_t inv_gyro_lpf_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, 4, "%d\n", st->config->gyro_lpf);
 }
 
 static ssize_t inv_gyro_lpf_store(struct device *dev,
@@ -105,6 +109,7 @@
 	if (gyro_lpf > INV_ICM20602_GYRO_LFP_NUM)
 		return -EINVAL;
 	config->gyro_lpf = gyro_lpf;
+
 	return count;
 }
 static IIO_DEVICE_ATTR(
@@ -118,7 +123,10 @@
 static ssize_t inv_gyro_fsr_show(struct device *dev,
 	struct device_attribute *attr, char *buf)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, 4, "%d\n", st->config->gyro_fsr);
 }
 
 static ssize_t inv_gyro_fsr_store(struct device *dev,
@@ -145,30 +153,37 @@
 						inv_gyro_fsr_store,
 						0);
 
-/* Attribute of gyro_self_test */
-static ssize_t inv_gyro_self_test_show(struct device *dev,
+/* Attribute of self_test */
+static ssize_t inv_self_test_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
 	return 0;
 }
 
-static ssize_t inv_gyro_self_test_store(struct device *dev,
+static ssize_t inv_self_test_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	icm20602_self_test(st);
+	return count;
 }
 static IIO_DEVICE_ATTR(
-						inv_icm20602_gyro_self_test,
+						inv_icm20602_self_test,
 						0644,
-						inv_gyro_self_test_show,
-						inv_gyro_self_test_store,
+						inv_self_test_show,
+						inv_self_test_store,
 						0);
 
 /* Attribute of gyro fsr base on enum inv_icm20602_acc_fsr_e */
 static ssize_t inv_gyro_acc_fsr_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, 4, "%d\n", st->config->acc_fsr);
 }
 
 static ssize_t inv_gyro_acc_fsr_store(struct device *dev,
@@ -198,7 +213,10 @@
 static ssize_t inv_gyro_acc_lpf_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, 4, "%d\n", st->config->acc_lpf);
 }
 
 static ssize_t inv_gyro_acc_lpf_store(struct device *dev,
@@ -224,30 +242,14 @@
 						inv_gyro_acc_lpf_store,
 						0);
 
-/* Attribute of acc_self_test */
-static ssize_t inv_acc_self_test_show(struct device *dev,
-		struct device_attribute *attr, char *buf)
-{
-	return 0;
-}
-
-static ssize_t inv_acc_self_test_store(struct device *dev,
-	struct device_attribute *attr, const char *buf, size_t count)
-{
-	return 0;
-}
-static IIO_DEVICE_ATTR(
-						inv_icm20602_acc_self_test,
-						0644,
-						inv_acc_self_test_show,
-						inv_acc_self_test_store,
-						0);
-
 /* Attribute of user_fps_in_ms */
 static ssize_t inv_user_fps_in_ms_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, 4, "%d\n", st->config->user_fps_in_ms);
 }
 
 static ssize_t inv_user_fps_in_ms_store(struct device *dev,
@@ -277,13 +279,27 @@
 static ssize_t inv_sampling_frequency_show(struct device *dev,
 		struct device_attribute *attr, char *buf)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	return snprintf(buf, 4, "%d\n", st->config->gyro_accel_sample_rate);
 }
 
 static ssize_t inv_sampling_frequency_store(struct device *dev,
 	struct device_attribute *attr, const char *buf, size_t count)
 {
-	return 0;
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+	struct icm20602_user_config *config = st->config;
+	int gyro_accel_sample_rate;
+
+	if (kstrtoint(buf, 10, &gyro_accel_sample_rate))
+		return -EINVAL;
+	if (gyro_accel_sample_rate < 10)
+		return -EINVAL;
+
+	config->gyro_accel_sample_rate = gyro_accel_sample_rate;
+	return count;
 }
 static IIO_DEV_ATTR_SAMP_FREQ(
 						0644,
@@ -293,11 +309,11 @@
 static struct attribute *inv_icm20602_attributes[] = {
 	&iio_dev_attr_inv_icm20602_init.dev_attr.attr,
 
-	&iio_dev_attr_inv_icm20602_gyro_self_test.dev_attr.attr,
 	&iio_dev_attr_inv_icm20602_gyro_fsr.dev_attr.attr,
 	&iio_dev_attr_inv_icm20602_gyro_lpf.dev_attr.attr,
 
-	&iio_dev_attr_inv_icm20602_acc_self_test.dev_attr.attr,
+	&iio_dev_attr_inv_icm20602_self_test.dev_attr.attr,
+
 	&iio_dev_attr_inv_icm20602_acc_fsr.dev_attr.attr,
 	&iio_dev_attr_inv_icm20602_acc_lpf.dev_attr.attr,
 
@@ -363,6 +379,44 @@
 	.validate_trigger = inv_icm20602_validate_trigger,
 };
 
+static int icm20602_ldo_work(struct inv_icm20602_state *st, bool enable)
+{
+	int ret = 0;
+
+	if (enable) {
+		ret = regulator_set_voltage(st->reg_ldo,
+			ICM20602_LDO_VTG_MIN_UV, ICM20602_LDO_VTG_MAX_UV);
+		if (ret)
+			pr_err("Failed to request LDO voltage.\n");
+
+		ret = regulator_enable(st->reg_ldo);
+		if (ret)
+			pr_err("Failed to enable LDO %d\n", ret);
+	} else {
+		ret = regulator_disable(st->reg_ldo);
+		if (ret)
+			pr_err("Failed to disable LDO %d\n", ret);
+		regulator_set_load(st->reg_ldo, 0);
+	}
+
+	return MPU_SUCCESS;
+}
+
+static int icm20602_init_regulators(struct inv_icm20602_state *st)
+{
+	struct regulator *reg;
+
+	reg = regulator_get(&st->client->dev, "vdd-ldo");
+	if (IS_ERR_OR_NULL(reg)) {
+		pr_err("Unable to get regulator for LDO\n");
+		return -MPU_FAIL;
+	}
+
+	st->reg_ldo = reg;
+
+	return MPU_SUCCESS;
+}
+
 static int of_populate_icm20602_dt(struct inv_icm20602_state *st)
 {
 	int result = MPU_SUCCESS;
@@ -450,6 +504,8 @@
 				result);
 		goto out_remove_trigger;
 	}
+	icm20602_init_regulators(st);
+	icm20602_ldo_work(st, true);
 
 	result = inv_icm20602_probe_trigger(indio_dev);
 	if (result) {
@@ -471,7 +527,6 @@
 	inv_icm20602_remove_trigger(st);
 out_unreg_ring:
 	iio_triggered_buffer_cleanup(indio_dev);
-out_free:
 	iio_device_free(indio_dev);
 	gpio_free(st->gpio);
 
@@ -494,11 +549,24 @@
 
 static int inv_icm20602_suspend(struct device *dev)
 {
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	icm20602_stop_fifo(st);
+	icm20602_ldo_work(st, false);
 	return 0;
 }
 
 static int inv_icm20602_resume(struct device *dev)
 {
+	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
+	struct inv_icm20602_state *st = iio_priv(indio_dev);
+
+	icm20602_ldo_work(st, true);
+	icm20602_detect(st);
+	icm20602_init_device(st);
+	icm20602_start_fifo(st);
+
 	return 0;
 }
 
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
index 9ea5ae5..b369ae4 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_iio.h
@@ -41,6 +41,9 @@
 #define INV20602_SMD_IRQ_TRIGGER    1
 #endif
 
+#define ICM20602_LDO_VTG_MIN_UV 3300000
+#define ICM20602_LDO_VTG_MAX_UV 3300000
+
 #define INV_ICM20602_TIME_STAMP_TOR           5
 #define ICM20602_PACKAGE_SIZE 14
 
@@ -217,6 +220,7 @@
 	struct struct_icm20602_data *data_push;
 	enum inv_devices chip_type;
 	int gpio;
+	struct regulator *reg_ldo;
 	DECLARE_KFIFO(timestamps, long long, TIMESTAMP_FIFO_SIZE);
 };
 
@@ -281,4 +285,6 @@
 int icm20602_read_fifo(struct inv_icm20602_state *st,
 	void *buf, const int size);
 int icm20602_start_fifo(struct inv_icm20602_state *st);
+int icm20602_stop_fifo(struct inv_icm20602_state *st);
+bool icm20602_self_test(struct inv_icm20602_state *st);
 #endif
diff --git a/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c b/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c
index de02656..081bec9 100644
--- a/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c
+++ b/drivers/iio/imu/inv_icm20602/inv_icm20602_ring.c
@@ -67,9 +67,8 @@
 	struct icm20602_user_config *config = st->config;
 	int package_count;
 	char *buf = st->buf;
-	struct struct_icm20602_data *data_push = st->data_push;
 	s64 timestamp;
-	u8 int_status, int_wm_status;
+	u8 int_status;
 	u16 fifo_count;
 	int i;
 
@@ -81,6 +80,7 @@
 	if (int_status & BIT_FIFO_OFLOW_INT) {
 		icm20602_fifo_count(st, &fifo_count);
 		pr_debug("fifo_count = %d\n", fifo_count);
+		inv_clear_kfifo(st);
 		icm20602_reset_fifo(st);
 		goto end_session;
 	}
@@ -105,14 +105,6 @@
 	mutex_unlock(&indio_dev->mlock);
 	iio_trigger_notify_done(indio_dev->trig);
 	return MPU_SUCCESS;
-
-flush_fifo:
-	/* Flush HW and SW FIFOs. */
-	inv_clear_kfifo(st);
-	icm20602_reset_fifo(st);
-	mutex_unlock(&indio_dev->mlock);
-	iio_trigger_notify_done(indio_dev->trig);
-	return MPU_SUCCESS;
 }
 
 /*
diff --git a/drivers/infiniband/hw/hfi1/debugfs.c b/drivers/infiniband/hw/hfi1/debugfs.c
index 632ba21..0022660 100644
--- a/drivers/infiniband/hw/hfi1/debugfs.c
+++ b/drivers/infiniband/hw/hfi1/debugfs.c
@@ -67,13 +67,13 @@
 	loff_t *ppos)
 {
 	struct dentry *d = file->f_path.dentry;
-	int srcu_idx;
 	ssize_t r;
 
-	r = debugfs_use_file_start(d, &srcu_idx);
-	if (likely(!r))
-		r = seq_read(file, buf, size, ppos);
-	debugfs_use_file_finish(srcu_idx);
+	r = debugfs_file_get(d);
+	if (unlikely(r))
+		return r;
+	r = seq_read(file, buf, size, ppos);
+	debugfs_file_put(d);
 	return r;
 }
 
@@ -83,13 +83,13 @@
 	int whence)
 {
 	struct dentry *d = file->f_path.dentry;
-	int srcu_idx;
 	loff_t r;
 
-	r = debugfs_use_file_start(d, &srcu_idx);
-	if (likely(!r))
-		r = seq_lseek(file, offset, whence);
-	debugfs_use_file_finish(srcu_idx);
+	r = debugfs_file_get(d);
+	if (unlikely(r))
+		return r;
+	r = seq_lseek(file, offset, whence);
+	debugfs_file_put(d);
 	return r;
 }
 
diff --git a/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c b/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c
index 08b5ce2..3905bd2 100644
--- a/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c
+++ b/drivers/input/misc/vl53l0x/src/vl53l0x_api_calibration.c
@@ -506,7 +506,7 @@
 					*pIsAperture = 1;
 					if ((byteIndex < 2) && (bitIndex < 4))
 						*pIsAperture = 0;
-						spadTypeIdentified = 1;
+					spadTypeIdentified = 1;
 				}
 			}
 			tempByte >>= 1;
diff --git a/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c b/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c
index ceb3585..6824c02 100644
--- a/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c
+++ b/drivers/input/misc/vl53l0x/src/vl53l0x_api_core.c
@@ -182,7 +182,7 @@
 			Status = VL_RdByte(Dev, 0x83, &strobe);
 			if ((strobe != 0x00) || Status != VL_ERROR_NONE)
 				break;
-				LoopNb = LoopNb + 1;
+			LoopNb = LoopNb + 1;
 		} while (LoopNb < VL_DEFAULT_MAX_LOOP);
 
 		if (LoopNb >= VL_DEFAULT_MAX_LOOP)
diff --git a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
index 78ca637..99cbc11 100644
--- a/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
+++ b/drivers/input/misc/vl53l0x/stmvl53l0x_module.c
@@ -777,18 +777,18 @@
 				size_t count)
 {
 	struct vl_data *data = dev_get_drvdata(dev);
-
+	int ret;
 	unsigned int val;
 
-	kstrtoint(buf, 10, &val);
+	ret = kstrtoint(buf, 10, &val);
 	if ((val != 0) && (val != 1)) {
-		err("store unvalid value=%ld\n", val);
+		err("store unvalid value=%d\n", val);
 		return count;
 	}
 	mutex_lock(&data->work_mutex);
 	dbg("Enter, enable_ps_sensor flag:%d\n",
 		data->enable_ps_sensor);
-	dbg("enable ps senosr ( %ld)\n", val);
+	dbg("enable ps senosr ( %d)\n", val);
 
 	if (val == 1) {
 		/* turn on tof sensor */
@@ -831,10 +831,11 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	int on;
+	int ret;
 
-	kstrtoint(buf, 10, &on);
+	ret = kstrtoint(buf, 10, &on);
 	if ((on != 0) &&  (on != 1)) {
-		err("set debug=%ld\n", on);
+		err("set debug=%d\n", on);
 		return count;
 	}
 	data->enableDebug = on;
@@ -862,10 +863,11 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	int delay_ms;
+	int ret;
 
-	kstrtoint(buf, 10, &delay_ms);
+	ret = kstrtoint(buf, 10, &delay_ms);
 	if (delay_ms == 0) {
-		err("set delay_ms=%ld\n", delay_ms);
+		err("set delay_ms=%d\n", delay_ms);
 		return count;
 	}
 	mutex_lock(&data->work_mutex);
@@ -895,10 +897,11 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	int timingBudget;
+	int ret;
 
-	kstrtoint(buf, 10, &timingBudget);
+	ret = kstrtoint(buf, 10, &timingBudget);
 	if (timingBudget == 0) {
-		err("set timingBudget=%ld\n", timingBudget);
+		err("set timingBudget=%d\n", timingBudget);
 		return count;
 	}
 	mutex_lock(&data->work_mutex);
@@ -929,10 +932,11 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	int useLongRange;
+	int ret;
 
-	kstrtoint(buf, 10, &useLongRange);
+	ret = kstrtoint(buf, 10, &useLongRange);
 	if ((useLongRange != 0) &&  (useLongRange != 1)) {
-		err("set useLongRange=%ld\n", useLongRange);
+		err("set useLongRange=%d\n", useLongRange);
 		return count;
 	}
 
@@ -960,7 +964,6 @@
 	struct VL_RangingMeasurementData_t Measure;
 
 	papi_func_tbl->PerformSingleRangingMeasurement(data, &Measure);
-	dbg("Measure = %d\n", Measure.RangeMilliMeter);
 	return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
 }
 
@@ -972,11 +975,7 @@
 static ssize_t stmvl53l0x_show_xtalk(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
-	struct vl_data *data = dev_get_drvdata(dev);
-	struct VL_RangingMeasurementData_t Measure;
-
-	dbg("Measure = %d\n", Measure.RangeMilliMeter);
-	return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
+	return 0;
 }
 
 static ssize_t stmvl53l0x_set_xtalk(struct device *dev,
@@ -985,8 +984,9 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	unsigned int targetDistance;
+	int ret;
 
-	kstrtoint(buf, 10, &targetDistance);
+	ret = kstrtoint(buf, 10, &targetDistance);
 	data->xtalkCalDistance = targetDistance;
 	stmvl53l0x_start(data, 3, XTALKCALIB_MODE);
 	return count;
@@ -1004,7 +1004,6 @@
 	struct VL_RangingMeasurementData_t Measure;
 
 	papi_func_tbl->PerformSingleRangingMeasurement(data, &Measure);
-	dbg("Measure = %d\n", Measure.RangeMilliMeter);
 	return snprintf(buf, 4, "%d\n", Measure.RangeMilliMeter);
 }
 
@@ -1014,8 +1013,9 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	unsigned int targetDistance;
+	int ret;
 
-	kstrtoint(buf, 10, &targetDistance);
+	ret = kstrtoint(buf, 10, &targetDistance);
 	data->offsetCalDistance = targetDistance;
 	stmvl53l0x_start(data, 3, OFFSETCALIB_MODE);
 	return count;
@@ -1067,9 +1067,9 @@
 
 	papi_func_tbl->GetOffsetCalibrationDataMicroMeter(data,
 					&offset_calibration_data);
-	dbg("GetOffsetCalibrationDataMicroMeter = %ld\n",
+	dbg("GetOffsetCalibrationDataMicroMeter = %d\n",
 					offset_calibration_data);
-	return snprintf(buf, 2, "%ld\n",
+	return snprintf(buf, 2, "%d\n",
 			offset_calibration_data);
 }
 
@@ -1079,8 +1079,9 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	int32_t offset_calibration_data;
+	int ret;
 
-	kstrtoint(buf, 10, &offset_calibration_data);
+	ret = kstrtoint(buf, 10, &offset_calibration_data);
 	papi_func_tbl->SetOffsetCalibrationDataMicroMeter(data,
 			offset_calibration_data);
 	return count;
@@ -1100,9 +1101,9 @@
 
 	papi_func_tbl->GetXTalkCompensationRateMegaCps(data,
 					&xtalk_compensation_rate);
-	dbg("xtalk_compensation_rate = %ld\n",
+	dbg("xtalk_compensation_rate = %d\n",
 					xtalk_compensation_rate);
-	return snprintf(buf, 2, "%ld\n", xtalk_compensation_rate);
+	return snprintf(buf, 2, "%d\n", xtalk_compensation_rate);
 
 }
 
@@ -1112,8 +1113,9 @@
 {
 	struct vl_data *data = dev_get_drvdata(dev);
 	unsigned int xtalk_compensation_rate;
+	int ret;
 
-	kstrtoint(buf, 10, &xtalk_compensation_rate);
+	ret = kstrtoint(buf, 10, &xtalk_compensation_rate);
 	papi_func_tbl->SetXTalkCompensationRateMegaCps(data,
 						xtalk_compensation_rate);
 	return count;
@@ -1689,7 +1691,7 @@
 			vl53l0x_dev,
 			&ref_spad_count,
 			&is_aperture_spads);
-		dbg("SPAD calibration:%lu,%u\n", ref_spad_count,
+		dbg("SPAD calibration:%d,%d\n", ref_spad_count,
 					(unsigned int)is_aperture_spads);
 		return rc;
 	} else if (mode == REFCALIB_MODE) {
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 19b1aac..72ab3ba 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -889,8 +889,6 @@
 		msm_camera_io_w(temp | (framedrop_period - 1) << 2,
 		vfe_base + VFE40_WM_BASE(stream_info->wm[vfe_idx][i]) + 0xC);
 	}
-
-	msm_camera_io_w_mb(0x1, vfe_base + 0x378);
 }
 
 static void msm_vfe40_clear_framedrop(struct vfe_device *vfe_dev,
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_4_3_hwreg.h b/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_4_3_hwreg.h
new file mode 100644
index 0000000..ac0a989
--- /dev/null
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/include/msm_csid_3_4_3_hwreg.h
@@ -0,0 +1,63 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef MSM_CSID_3_4_3_HWREG_H
+#define MSM_CSID_3_4_3_HWREG_H
+
+#include <sensor/csid/msm_csid.h>
+
+static uint8_t csid_lane_assign_v3_4_3[PHY_LANE_MAX] = {0, 4, 1, 2, 3};
+static struct csid_reg_parms_t csid_v3_4_3 = {
+	/* MIPI	CSID registers */
+	0x0,
+	0x4,
+	0x8,
+	0xC,
+	0x10,
+	0x14,
+	0x18,
+	0x1C,
+	0x20,
+	0x60,
+	0x64,
+	0x68,
+	0x6C,
+	0x70,
+	0x74,
+	0x78,
+	0x7C,
+	0x80,
+	0x84,
+	0x88,
+	0x8C,
+	0x90,
+	0x94,
+	0x98,
+	0xA0,
+	0xA4,
+	0xAC,
+	0xB0,
+	0xB4,
+	11,
+	0x7FFF,
+	0x4,
+	17,
+	0x30040003,
+	0xFFFFFFFF,
+	0xFFFFFFFF,
+	0xFFFFFFFF,
+	0x7f010800,
+	20,
+	0xFFFFFFFF,
+	0xFFFFFFFF,
+};
+#endif
diff --git a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
index d5e7989..9d3184e 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/csid/msm_csid.c
@@ -26,6 +26,7 @@
 #include "include/msm_csid_3_5_hwreg.h"
 #include "include/msm_csid_3_4_1_hwreg.h"
 #include "include/msm_csid_3_4_2_hwreg.h"
+#include "include/msm_csid_3_4_3_hwreg.h"
 #include "include/msm_csid_3_6_0_hwreg.h"
 #include "include/msm_csid_3_5_1_hwreg.h"
 #include "cam_hw_ops.h"
@@ -42,6 +43,7 @@
 #define CSID_VERSION_V34                      0x30040000
 #define CSID_VERSION_V34_1                    0x30040001
 #define CSID_VERSION_V34_2                    0x30040002
+#define CSID_VERSION_V34_3                    0x30040003
 #define CSID_VERSION_V36                      0x30060000
 #define CSID_VERSION_V37                      0x30070000
 #define CSID_VERSION_V35                      0x30050000
@@ -1179,6 +1181,12 @@
 		new_csid_dev->ctrl_reg->csid_lane_assign =
 			csid_lane_assign_v3_4_2;
 	} else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
+		"qcom,csid-v3.4.3")) {
+		new_csid_dev->ctrl_reg->csid_reg = csid_v3_4_3;
+		new_csid_dev->hw_dts_version = CSID_VERSION_V34_3;
+		new_csid_dev->ctrl_reg->csid_lane_assign =
+			csid_lane_assign_v3_4_3;
+	} else if (of_device_is_compatible(new_csid_dev->pdev->dev.of_node,
 		"qcom,csid-v3.6.0")) {
 		new_csid_dev->ctrl_reg->csid_reg = csid_v3_6_0;
 		new_csid_dev->hw_dts_version = CSID_VERSION_V36;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index ee643b1..e6a4ed30 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -1548,10 +1548,6 @@
 	}
 	case V4L2_CID_MPEG_VIDC_IMG_GRID_DIMENSION:
 	{
-		int i = 0, j = 0;
-		u32 width = 0, height = 0;
-		u32 trows, tcols;
-
 		property_id = HAL_CONFIG_HEIC_GRID_ENABLE;
 		if (inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC) {
 			dprintk(VIDC_ERR, "Grid is supported only for HEVC\n");
@@ -1566,38 +1562,6 @@
 		grid_enable.grid_enable = ctrl->val;
 		inst->img_grid_dimension = ctrl->val;
 		pdata = &grid_enable;
-
-		/* Update tile info table */
-		width = inst->prop.width[OUTPUT_PORT];
-		height = inst->prop.height[OUTPUT_PORT];
-		tcols = (width + inst->img_grid_dimension - 1) /
-					inst->img_grid_dimension;
-		trows = (height + inst->img_grid_dimension - 1) /
-					inst->img_grid_dimension;
-		inst->tinfo.count = trows * tcols;
-		if (inst->tinfo.count > MAX_HEIC_TILES_COUNT) {
-			dprintk(VIDC_ERR, "Tiles count exceeds maximum\n");
-			rc = -ENOTSUPP;
-			break;
-		}
-
-		dprintk(VIDC_DBG,
-			"Grid dimension %d width %d height %d row %d col %d\n",
-			inst->img_grid_dimension, width, height,
-			trows, tcols);
-
-		for (j = 0; j < trows; ++j) {
-			for (i = 0; i < tcols; ++i) {
-				inst->tinfo.tile_rects[j*tcols+i].left =
-					(i * inst->img_grid_dimension);
-				inst->tinfo.tile_rects[j*tcols+i].top =
-					(j * inst->img_grid_dimension);
-				inst->tinfo.tile_rects[j*tcols+i].width =
-					inst->img_grid_dimension;
-				inst->tinfo.tile_rects[j*tcols+i].height =
-					inst->img_grid_dimension;
-			}
-		}
 		break;
 	}
 	case V4L2_CID_MPEG_VIDEO_BITRATE_PEAK:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index 8e32504..651d0a2 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -901,6 +901,51 @@
 	return rc;
 }
 
+static int msm_vidc_create_tile_info_table(struct msm_vidc_inst *inst)
+{
+	int i = 0, j = 0;
+	u32 width = 0, height = 0;
+	u32 trows = 0, tcols = 0;
+
+	/* Don't create table for non-HEIC formats*/
+	if (inst->img_grid_dimension <= 0 ||
+		inst->fmts[CAPTURE_PORT].fourcc != V4L2_PIX_FMT_HEVC)
+		return 0;
+
+	width = inst->prop.width[OUTPUT_PORT];
+	height = inst->prop.height[OUTPUT_PORT];
+	tcols = (width + inst->img_grid_dimension - 1) /
+		inst->img_grid_dimension;
+	trows = (height + inst->img_grid_dimension - 1) /
+		inst->img_grid_dimension;
+	inst->tinfo.count = trows * tcols;
+	if (inst->tinfo.count > MAX_HEIC_TILES_COUNT) {
+		dprintk(VIDC_ERR,
+			"Tiles count (%d) exceeds maximum\n",
+			inst->tinfo.count);
+		return -ENOTSUPP;
+	}
+
+	dprintk(VIDC_DBG,
+		"Grid dimension %d width %d height %d row %d col %d\n",
+		inst->img_grid_dimension, width, height,
+		trows, tcols);
+
+	for (j = 0; j < trows; ++j) {
+		for (i = 0; i < tcols; ++i) {
+			inst->tinfo.tile_rects[j*tcols+i].left =
+				(i * inst->img_grid_dimension);
+			inst->tinfo.tile_rects[j*tcols+i].top =
+				(j * inst->img_grid_dimension);
+			inst->tinfo.tile_rects[j*tcols+i].width =
+				inst->img_grid_dimension;
+			inst->tinfo.tile_rects[j*tcols+i].height =
+				inst->img_grid_dimension;
+		}
+	}
+	return 0;
+}
+
 static inline int start_streaming(struct msm_vidc_inst *inst)
 {
 	int rc = 0;
@@ -909,6 +954,13 @@
 
 	hdev = inst->core->device;
 
+	/* Create tile info table */
+	rc = msm_vidc_create_tile_info_table(inst);
+	if (rc) {
+		dprintk(VIDC_ERR, "Tile info table was not generated\n");
+		goto fail_start;
+	}
+
 	/* Check if current session is under HW capability */
 	rc = msm_vidc_check_session_supported(inst);
 	if (rc) {
diff --git a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c
index 887c8eb..a6ed374 100644
--- a/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c
+++ b/drivers/misc/fpr_FingerprintCard/fpc1020_platform_tee.c
@@ -75,8 +75,8 @@
 struct fpc1020_data {
 	struct device *dev;
 	struct pinctrl *fingerprint_pinctrl;
-	struct pinctrl_state **pinctrl_state;
-	struct regulator **vreg;
+	struct pinctrl_state *pinctrl_state[ARRAY_SIZE(pctl_names)];
+	struct regulator *vreg[ARRAY_SIZE(vreg_conf)];
 	struct wakeup_source ttw_wl;
 	struct mutex lock; /* To set/get exported values in sysfs */
 	int irq_gpio;
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index d61f20e..07fb743 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -4061,8 +4061,11 @@
 	int retry = 0;
 
 	do {
-		if (retry++)
+		if (retry++) {
+			mutex_unlock(&app_access_lock);
 			msleep(QSEECOM_TA_ION_ALLOCATE_DELAY);
+			mutex_lock(&app_access_lock);
+		}
 		ihandle = ion_alloc(qseecom.ion_clnt, fw_size,
 			SZ_4K, ION_HEAP(ION_QSECOM_TA_HEAP_ID), 0);
 	} while (IS_ERR_OR_NULL(ihandle) &&
@@ -4212,8 +4215,12 @@
 	ret = qseecom_scm_call(SCM_SVC_TZSCHEDULER, 1, cmd_buf, cmd_len,
 			&resp, sizeof(resp));
 	if (ret) {
-		pr_err("scm_call to load failed : ret %d\n", ret);
-		ret = -EIO;
+		pr_err("scm_call to load failed : ret %d, result %x\n",
+			ret, resp.result);
+		if (resp.result == QSEOS_RESULT_FAIL_APP_ALREADY_LOADED)
+			ret = -EEXIST;
+		else
+			ret = -EIO;
 		goto exit_disable_clk_vote;
 	}
 
@@ -4465,6 +4472,7 @@
 	}
 	mutex_lock(&app_access_lock);
 
+recheck:
 	app_ireq.qsee_cmd_id = QSEOS_APP_LOOKUP_COMMAND;
 	strlcpy(app_ireq.app_name, app_name, MAX_APP_NAME_SIZE);
 	ret = __qseecom_check_app_exists(app_ireq, &app_id);
@@ -4494,7 +4502,10 @@
 		pr_debug("%s: Loading app for the first time'\n",
 				qseecom.pdev->init_name);
 		ret = __qseecom_load_fw(data, app_name, &app_id);
-		if (ret < 0)
+		if (ret == -EEXIST) {
+			pr_err("recheck if TA %s is loaded\n", app_name);
+			goto recheck;
+		} else if (ret < 0)
 			goto exit_ion_free;
 	}
 	data->client.app_id = app_id;
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_com.h b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
index 33e0314..36d49e4 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_com.h
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_com.h
@@ -359,7 +359,7 @@
 	ulong                        global_irq_counter;
 
 	bool                         dump_conf;
-
+	bool                         config_mmio_init;
 	bool                         enumerated;
 	enum ep_pcie_link_status     link_status;
 	bool                         perst_deast;
diff --git a/drivers/platform/msm/ep_pcie/ep_pcie_core.c b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
index 4558530..0ada0bf 100644
--- a/drivers/platform/msm/ep_pcie/ep_pcie_core.c
+++ b/drivers/platform/msm/ep_pcie/ep_pcie_core.c
@@ -503,6 +503,13 @@
 		"Initial version of MMIO is:0x%x\n",
 		readl_relaxed(dev->mmio + PCIE20_MHIVER));
 
+	if (dev->config_mmio_init) {
+		EP_PCIE_DBG(dev,
+			"PCIe V%d: MMIO already initialized, return\n",
+				dev->rev);
+		return;
+	}
+
 	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);
@@ -511,6 +518,8 @@
 	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);
+
+	dev->config_mmio_init = true;
 }
 
 static void ep_pcie_core_init(struct ep_pcie_dev_t *dev, bool configured)
diff --git a/drivers/platform/msm/gsi/gsi.c b/drivers/platform/msm/gsi/gsi.c
index 1af3447..b2474dc 100644
--- a/drivers/platform/msm/gsi/gsi.c
+++ b/drivers/platform/msm/gsi/gsi.c
@@ -1876,6 +1876,32 @@
 }
 EXPORT_SYMBOL(gsi_alloc_channel);
 
+static void __gsi_read_channel_scratch(unsigned long chan_hdl,
+		union __packed gsi_channel_scratch * val)
+{
+	uint32_t reg;
+
+	reg = gsi_readl(gsi_ctx->base +
+		GSI_EE_n_GSI_CH_k_SCRATCH_0_OFFS(chan_hdl,
+			gsi_ctx->per.ee));
+	val->data.word1 = reg;
+
+	reg = gsi_readl(gsi_ctx->base +
+		GSI_EE_n_GSI_CH_k_SCRATCH_1_OFFS(chan_hdl,
+			gsi_ctx->per.ee));
+	val->data.word2 = reg;
+
+	reg = gsi_readl(gsi_ctx->base +
+		GSI_EE_n_GSI_CH_k_SCRATCH_2_OFFS(chan_hdl,
+			gsi_ctx->per.ee));
+	val->data.word3 = reg;
+
+	reg = gsi_readl(gsi_ctx->base +
+		GSI_EE_n_GSI_CH_k_SCRATCH_3_OFFS(chan_hdl,
+			gsi_ctx->per.ee));
+	val->data.word4 = reg;
+}
+
 static void __gsi_write_channel_scratch(unsigned long chan_hdl,
 		union __packed gsi_channel_scratch val)
 {
@@ -1936,6 +1962,40 @@
 }
 EXPORT_SYMBOL(gsi_write_channel_scratch);
 
+int gsi_read_channel_scratch(unsigned long chan_hdl,
+	union __packed gsi_channel_scratch * ch_scratch)
+{
+	struct gsi_chan_ctx *ctx;
+
+	if (!gsi_ctx) {
+		pr_err("%s:%d gsi context not allocated\n", __func__, __LINE__);
+		return -GSI_STATUS_NODEV;
+	}
+
+	if (chan_hdl >= gsi_ctx->max_ch) {
+		GSIERR("bad params chan_hdl=%lu\n", chan_hdl);
+		return -GSI_STATUS_INVALID_PARAMS;
+	}
+
+	if (gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_ALLOCATED &&
+		gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STARTED &&
+		gsi_ctx->chan[chan_hdl].state != GSI_CHAN_STATE_STOPPED) {
+		GSIERR("bad state %d\n",
+				gsi_ctx->chan[chan_hdl].state);
+		return -GSI_STATUS_UNSUPPORTED_OP;
+	}
+
+	ctx = &gsi_ctx->chan[chan_hdl];
+
+	mutex_lock(&ctx->mlock);
+	__gsi_read_channel_scratch(chan_hdl, ch_scratch);
+	ctx->restore_scratch = *ch_scratch;
+	mutex_unlock(&ctx->mlock);
+
+	return GSI_STATUS_SUCCESS;
+}
+EXPORT_SYMBOL(gsi_read_channel_scratch);
+
 int gsi_query_channel_db_addr(unsigned long chan_hdl,
 		uint32_t *db_addr_wp_lsb, uint32_t *db_addr_wp_msb)
 {
diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h
index 92849d9..4a3f4ec 100644
--- a/drivers/platform/msm/gsi/gsi.h
+++ b/drivers/platform/msm/gsi/gsi.h
@@ -137,6 +137,7 @@
 	bool allocated;
 	atomic_t poll_mode;
 	union __packed gsi_channel_scratch scratch;
+	union __packed gsi_channel_scratch restore_scratch;
 	struct gsi_chan_stats stats;
 	bool enable_dp_stats;
 	bool print_dp_stats;
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
index df19384..5812d8d 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c
@@ -67,7 +67,8 @@
 static char dbg_buff[IPA_GSB_MAX_MSG_LEN];
 
 #define IPA_GSB_SKB_HEADROOM 256
-#define IPA_GSB_AGGR_BYTE_LIMIT 6
+#define IPA_GSB_SKB_DUMMY_HEADER 42
+#define IPA_GSB_AGGR_BYTE_LIMIT 14
 #define IPA_GSB_AGGR_TIME_LIMIT 1
 
 static struct dentry *dent;
@@ -278,22 +279,36 @@
 			 "%s_ipv4", iface_info->netdev_name);
 	snprintf(hdr->hdr[1].name, sizeof(hdr->hdr[1].name),
 			 "%s_ipv6", iface_info->netdev_name);
-	/* partial header: [hdl][QMAP ID][pkt size][ETH header] */
+	/*
+	 * partial header:
+	 * [hdl][QMAP ID][pkt size][Dummy Header][ETH header]
+	 */
 	for (i = IPA_IP_v4; i < IPA_IP_MAX; i++) {
-		hdr->hdr[i].hdr_len = ETH_HLEN + sizeof(struct ipa_gsb_mux_hdr);
+		/*
+		 * Optimization: add dummy header to reserve space
+		 * for rndis header, so we can do the skb_clone
+		 * instead of deep copy.
+		 */
+		hdr->hdr[i].hdr_len = ETH_HLEN +
+			sizeof(struct ipa_gsb_mux_hdr) +
+			IPA_GSB_SKB_DUMMY_HEADER;
 		hdr->hdr[i].type = IPA_HDR_L2_ETHERNET_II;
 		hdr->hdr[i].is_partial = 1;
 		hdr->hdr[i].is_eth2_ofst_valid = 1;
-		hdr->hdr[i].eth2_ofst = sizeof(struct ipa_gsb_mux_hdr);
+		hdr->hdr[i].eth2_ofst = sizeof(struct ipa_gsb_mux_hdr) +
+			IPA_GSB_SKB_DUMMY_HEADER;
 		/* populate iface handle */
 		hdr->hdr[i].hdr[0] = iface_info->iface_hdl;
 		/* populate src ETH address */
-		memcpy(&hdr->hdr[i].hdr[10], iface_info->device_ethaddr, 6);
+		memcpy(&hdr->hdr[i].hdr[10 + IPA_GSB_SKB_DUMMY_HEADER],
+			iface_info->device_ethaddr, 6);
 		/* populate Ethertype */
 		if (i == IPA_IP_v4)
-			*(u16 *)(hdr->hdr[i].hdr + 16) = htons(ETH_P_IP);
+			*(u16 *)(hdr->hdr[i].hdr + 16 +
+				IPA_GSB_SKB_DUMMY_HEADER) = htons(ETH_P_IP);
 		else
-			*(u16 *)(hdr->hdr[i].hdr + 16) = htons(ETH_P_IPV6);
+			*(u16 *)(hdr->hdr[i].hdr + 16 +
+				IPA_GSB_SKB_DUMMY_HEADER) = htons(ETH_P_IPV6);
 	}
 
 	if (ipa_add_hdr(hdr)) {
@@ -410,7 +425,7 @@
 		return;
 	}
 
-	IPA_GSB_DBG("wake up clients\n");
+	IPA_GSB_DBG_LOW("wake up clients\n");
 	for (i = 0; i < MAX_SUPPORTED_IFACE; i++)
 		if (ipa_gsb_ctx->iface[i] != NULL)
 			ipa_gsb_ctx->iface[i]->wakeup_request(
@@ -629,21 +644,6 @@
 }
 EXPORT_SYMBOL(ipa_bridge_cleanup);
 
-static struct sk_buff *ipa_gsb_skb_copy(struct sk_buff *skb, int len)
-{
-	struct sk_buff *skb2 = NULL;
-
-	skb2 = __dev_alloc_skb(len + IPA_GSB_SKB_HEADROOM, GFP_KERNEL);
-	if (likely(skb2)) {
-		skb_reserve(skb2, IPA_GSB_SKB_HEADROOM);
-		memcpy(skb2->data, skb->data, len);
-		skb2->len = len;
-		skb_set_tail_pointer(skb2, len);
-	}
-
-	return skb2;
-}
-
 static void ipa_gsb_cons_cb(void *priv, enum ipa_dp_evt_type evt,
 	unsigned long data)
 {
@@ -665,21 +665,33 @@
 		mux_hdr = (struct ipa_gsb_mux_hdr *)skb->data;
 		pkt_size = mux_hdr->pkt_size;
 		/* 4-byte padding */
-		pad_byte = ((pkt_size + sizeof(*mux_hdr) + ETH_HLEN + 3) & ~3)
-			- (pkt_size + sizeof(*mux_hdr) + ETH_HLEN);
+		pad_byte = ((pkt_size + sizeof(*mux_hdr) + ETH_HLEN +
+			3 + IPA_GSB_SKB_DUMMY_HEADER) & ~3) -
+			(pkt_size + sizeof(*mux_hdr) +
+			ETH_HLEN + IPA_GSB_SKB_DUMMY_HEADER);
 		hdl = mux_hdr->iface_hdl;
-		IPA_GSB_DBG("pkt_size: %d, pad_byte: %d, hdl: %d\n",
+		IPA_GSB_DBG_LOW("pkt_size: %d, pad_byte: %d, hdl: %d\n",
 			pkt_size, pad_byte, hdl);
 
-		/* remove 4 byte mux header */
-		skb_pull(skb, sizeof(*mux_hdr));
-		skb2 = ipa_gsb_skb_copy(skb, pkt_size + ETH_HLEN);
+		/* remove 4 byte mux header AND dummy header*/
+		skb_pull(skb, sizeof(*mux_hdr) + IPA_GSB_SKB_DUMMY_HEADER);
+
+		skb2 = skb_clone(skb, GFP_KERNEL);
+		if (!skb2) {
+			IPA_GSB_ERR("skb_clone failed\n");
+			WARN_ON(1);
+			break;
+		}
+		skb_trim(skb2, pkt_size + ETH_HLEN);
 		ipa_gsb_ctx->iface[hdl]->send_dl_skb(
 			ipa_gsb_ctx->iface[hdl]->priv, skb2);
 		ipa_gsb_ctx->iface[hdl]->iface_stats.num_dl_packets++;
-
 		skb_pull(skb, pkt_size + ETH_HLEN + pad_byte);
 	}
+	if (skb) {
+		dev_kfree_skb_any(skb);
+		skb = NULL;
+	}
 }
 
 static void ipa_gsb_tx_dp_notify(void *priv, enum ipa_dp_evt_type evt,
@@ -702,7 +714,7 @@
 	/* change to host order */
 	*(u32 *)mux_hdr = ntohl(*(u32 *)mux_hdr);
 	hdl = mux_hdr->iface_hdl;
-	IPA_GSB_DBG("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl);
+	IPA_GSB_DBG_LOW("evt: %d, hdl in tx_dp_notify: %d\n", evt, hdl);
 
 	/* remove 4 byte mux header */
 	skb_pull(skb, sizeof(struct ipa_gsb_mux_hdr));
@@ -740,7 +752,8 @@
 	/* configure TX EP */
 	cons_params.client = IPA_CLIENT_ODU_EMB_CONS;
 	cons_params.ipa_ep_cfg.hdr.hdr_len =
-		ETH_HLEN + sizeof(struct ipa_gsb_mux_hdr);
+		ETH_HLEN + sizeof(struct ipa_gsb_mux_hdr) +
+		IPA_GSB_SKB_DUMMY_HEADER;
 	cons_params.ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1;
 	cons_params.ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 2;
 	cons_params.ipa_ep_cfg.hdr_ext.hdr_pad_to_alignment = 2;
@@ -911,7 +924,7 @@
 		return -EFAULT;
 	}
 
-	IPA_GSB_DBG("client hdl: %d\n", hdl);
+	IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);
 
 	if (!ipa_gsb_ctx->iface[hdl]->is_connected) {
 		IPA_GSB_ERR("iface is not connected\n");
@@ -919,7 +932,7 @@
 	}
 
 	if (ipa_gsb_ctx->iface[hdl]->is_resumed) {
-		IPA_GSB_DBG("iface was already resumed\n");
+		IPA_GSB_DBG_LOW("iface was already resumed\n");
 		return 0;
 	}
 
@@ -946,7 +959,7 @@
 
 	ipa_gsb_ctx->iface[hdl]->is_resumed = true;
 	ipa_gsb_ctx->num_resumed_iface++;
-	IPA_GSB_DBG("num resumed iface: %d\n",
+	IPA_GSB_DBG_LOW("num resumed iface: %d\n",
 		ipa_gsb_ctx->num_resumed_iface);
 
 	mutex_unlock(&ipa_gsb_ctx->lock);
@@ -963,7 +976,7 @@
 		return -EFAULT;
 	}
 
-	IPA_GSB_DBG("client hdl: %d\n", hdl);
+	IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);
 
 	if (!ipa_gsb_ctx->iface[hdl]->is_connected) {
 		IPA_GSB_ERR("iface is not connected\n");
@@ -971,7 +984,7 @@
 	}
 
 	if (!ipa_gsb_ctx->iface[hdl]->is_resumed) {
-		IPA_GSB_DBG("iface was already suspended\n");
+		IPA_GSB_DBG_LOW("iface was already suspended\n");
 		return 0;
 	}
 
@@ -999,7 +1012,7 @@
 
 	ipa_gsb_ctx->iface[hdl]->is_resumed = false;
 	ipa_gsb_ctx->num_resumed_iface--;
-	IPA_GSB_DBG("num resumed iface: %d\n",
+	IPA_GSB_DBG_LOW("num resumed iface: %d\n",
 		ipa_gsb_ctx->num_resumed_iface);
 
 	mutex_unlock(&ipa_gsb_ctx->lock);
@@ -1032,11 +1045,11 @@
 	struct sk_buff *skb2;
 	int ret;
 
-	IPA_GSB_DBG("client hdl: %d\n", hdl);
+	IPA_GSB_DBG_LOW("client hdl: %d\n", hdl);
 
 	/* make sure skb has enough headroom */
 	if (unlikely(skb_headroom(skb) < sizeof(struct ipa_gsb_mux_hdr))) {
-		IPA_GSB_DBG("skb doesn't have enough headroom\n");
+		IPA_GSB_DBG_LOW("skb doesn't have enough headroom\n");
 		skb2 = skb_copy_expand(skb, sizeof(struct ipa_gsb_mux_hdr),
 			0, GFP_ATOMIC);
 		if (!skb2) {
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index 906e911..b4af0a09 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015, 2017-2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,13 +24,39 @@
 #endif
 
 #define IPA_MHI_DRV_NAME "ipa_mhi_client"
+
 #define IPA_MHI_DBG(fmt, args...) \
-	pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
-		 __func__, __LINE__, ## args)
+	do { \
+		pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+			IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+
+#define IPA_MHI_DBG_LOW(fmt, args...) \
+	do { \
+		pr_debug(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+			IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+
+
 #define IPA_MHI_ERR(fmt, args...) \
-	pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args)
+	do { \
+		pr_err(IPA_MHI_DRV_NAME " %s:%d " fmt, \
+			__func__, __LINE__, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf(), \
+				IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+		IPA_IPC_LOGGING(ipa_get_ipc_logbuf_low(), \
+				IPA_MHI_DRV_NAME " %s:%d " fmt, ## args); \
+	} while (0)
+
 #define IPA_MHI_FUNC_ENTRY() \
 	IPA_MHI_DBG("ENTRY\n")
+
 #define IPA_MHI_FUNC_EXIT() \
 	IPA_MHI_DBG("EXIT\n")
 
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
index c7df5cf..8b998fe 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_usb.c
@@ -1336,7 +1336,12 @@
 	chan_params.chan_params.ring_base_addr =
 		params->xfer_ring_base_addr_iova;
 	chan_params.chan_params.ring_base_vaddr = NULL;
-	chan_params.chan_params.use_db_eng = GSI_CHAN_DB_MODE;
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
+		chan_params.chan_params.use_db_eng = GSI_CHAN_DIRECT_MODE;
+	else
+		chan_params.chan_params.use_db_eng = GSI_CHAN_DB_MODE;
+	chan_params.chan_params.prefetch_mode =
+		ipa_get_ep_prefetch_mode(chan_params.client);
 	chan_params.chan_params.max_prefetch = GSI_ONE_PREFETCH_SEG;
 	if (params->dir == GSI_CHAN_DIR_FROM_GSI)
 		chan_params.chan_params.low_weight =
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index 82c8709..9190e9e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -6270,7 +6270,7 @@
 			iova_p, &pa_p, size_p);
 		ipa3_iommu_map(cb->mapping->domain,
 			iova_p, pa_p, size_p,
-			IOMMU_READ | IOMMU_WRITE | IOMMU_MMIO);
+			IOMMU_READ | IOMMU_WRITE);
 	}
 
 
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 34f3265..d3ed36a 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -35,6 +35,9 @@
 #define IPA_GENERIC_AGGR_TIME_LIMIT 1
 #define IPA_GENERIC_AGGR_PKT_LIMIT 0
 
+#define IPA_GSB_AGGR_BYTE_LIMIT 14
+#define IPA_GSB_RX_BUFF_BASE_SZ 16384
+
 #define IPA_GENERIC_RX_BUFF_BASE_SZ 8192
 #define IPA_REAL_GENERIC_RX_BUFF_SZ(X) (SKB_DATA_ALIGN(\
 		(X) + NET_SKB_PAD) +\
@@ -2946,11 +2949,14 @@
 			/* recycle skb for GSB use case */
 			if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) {
 				sys->free_rx_wrapper =
-					ipa3_recycle_rx_wrapper;
+					ipa3_free_rx_wrapper;
 				sys->repl_hdlr =
-					ipa3_replenish_rx_cache_recycle;
+					ipa3_replenish_rx_cache;
+				/* Overwrite buffer size & aggr limit for GSB */
 				sys->rx_buff_sz = IPA_GENERIC_RX_BUFF_SZ(
-					IPA_GENERIC_RX_BUFF_BASE_SZ);
+					IPA_GSB_RX_BUFF_BASE_SZ);
+				in->ipa_ep_cfg.aggr.aggr_byte_limit =
+					IPA_GSB_AGGR_BYTE_LIMIT;
 			} else {
 				sys->free_rx_wrapper =
 					ipa3_free_rx_wrapper;
@@ -3695,8 +3701,13 @@
 	ep->gsi_mem_info.chan_ring_base_vaddr =
 		gsi_channel_props.ring_base_vaddr;
 
-	gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
+		gsi_channel_props.use_db_eng = GSI_CHAN_DIRECT_MODE;
+	else
+		gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
 	gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
+	gsi_channel_props.prefetch_mode =
+		ipa_get_ep_prefetch_mode(ep->client);
 	if (ep->client == IPA_CLIENT_APPS_CMD_PROD)
 		gsi_channel_props.low_weight = IPA_GSI_MAX_CH_LOW_WEIGHT;
 	else
@@ -3935,7 +3946,12 @@
 		dma_alloc_coherent(ipa3_ctx->pdev, gsi_channel_props.ring_len,
 		&dma_addr, 0);
 	gsi_channel_props.ring_base_addr = dma_addr;
-	gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
+
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
+		gsi_channel_props.use_db_eng = GSI_CHAN_DIRECT_MODE;
+	else
+		gsi_channel_props.use_db_eng = GSI_CHAN_DB_MODE;
+
 	gsi_channel_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
 	gsi_channel_props.low_weight = 1;
 	gsi_channel_props.err_cb = ipa_gsi_chan_err_cb;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
index 6703bf5..b090151 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_flt.c
@@ -1014,41 +1014,12 @@
 		goto error;
 	}
 
+	if (__ipa_validate_flt_rule(&frule->rule, &rt_tbl, ip))
+		goto error;
+
 	if (entry->rt_tbl)
 		entry->rt_tbl->ref_cnt--;
 
-	if (frule->rule.action != IPA_PASS_TO_EXCEPTION) {
-		if (!frule->rule.eq_attrib_type) {
-			if (!frule->rule.rt_tbl_hdl) {
-				IPAERR_RL("invalid RT tbl\n");
-				goto error;
-			}
-
-			rt_tbl = ipa3_id_find(frule->rule.rt_tbl_hdl);
-			if (rt_tbl == NULL) {
-				IPAERR_RL("RT tbl not found\n");
-				goto error;
-			}
-
-			if (rt_tbl->cookie != IPA_RT_TBL_COOKIE) {
-				IPAERR_RL("RT table cookie is invalid\n");
-				goto error;
-			}
-		} else {
-			if (frule->rule.rt_tbl_idx > ((ip == IPA_IP_v4) ?
-				IPA_MEM_PART(v4_modem_rt_index_hi) :
-				IPA_MEM_PART(v6_modem_rt_index_hi))) {
-				IPAERR_RL("invalid RT tbl\n");
-				goto error;
-			}
-		}
-	} else {
-		if (frule->rule.rt_tbl_idx > 0) {
-			IPAERR_RL("invalid RT tbl\n");
-			goto error;
-		}
-	}
-
 	entry->rule = frule->rule;
 	entry->rt_tbl = rt_tbl;
 	if (entry->rt_tbl)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 268f5fa..c860bd0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -2258,6 +2258,8 @@
  */
 int ipa3_get_ep_mapping(enum ipa_client_type client);
 
+enum gsi_prefetch_mode ipa_get_ep_prefetch_mode(enum ipa_client_type client);
+
 bool ipa3_is_ready(void);
 
 void ipa3_proxy_clk_vote(void);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
index 82cd8187..dd97038 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_mhi.c
@@ -56,9 +56,9 @@
 
 
 #define IPA_MHI_FUNC_ENTRY() \
-	IPA_MHI_DBG_LOW("ENTRY\n")
+	IPA_MHI_DBG("ENTRY\n")
 #define IPA_MHI_FUNC_EXIT() \
-	IPA_MHI_DBG_LOW("EXIT\n")
+	IPA_MHI_DBG("EXIT\n")
 
 #define IPA_MHI_MAX_UL_CHANNELS 1
 #define IPA_MHI_MAX_DL_CHANNELS 1
@@ -198,6 +198,7 @@
 	union __packed gsi_channel_scratch ch_scratch;
 	struct ipa3_ep_context *ep;
 	const struct ipa_gsi_ep_config *ep_cfg;
+	bool burst_mode_enabled = false;
 
 	IPA_MHI_FUNC_ENTRY();
 
@@ -280,8 +281,21 @@
 	ch_props.ring_len = params->ch_ctx_host->rlen;
 	ch_props.ring_base_addr = IPA_MHI_HOST_ADDR_COND(
 			params->ch_ctx_host->rbase);
-	ch_props.use_db_eng = GSI_CHAN_DB_MODE;
+
+	if (params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_DEFAULT ||
+		params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_ENABLE) {
+		burst_mode_enabled = true;
+	}
+
+	if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0 &&
+		!burst_mode_enabled)
+		ch_props.use_db_eng = GSI_CHAN_DIRECT_MODE;
+	else
+		ch_props.use_db_eng = GSI_CHAN_DB_MODE;
+
 	ch_props.max_prefetch = GSI_ONE_PREFETCH_SEG;
+	ch_props.prefetch_mode =
+		ipa_get_ep_prefetch_mode(client);
 	ch_props.low_weight = 1;
 	ch_props.err_cb = params->ch_err_cb;
 	ch_props.chan_user_data = params->channel;
@@ -307,9 +321,9 @@
 		ch_scratch.mhi.outstanding_threshold = 0;
 	}
 	ch_scratch.mhi.oob_mod_threshold = 4;
-	if (params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_DEFAULT ||
-		params->ch_ctx_host->brstmode == IPA_MHI_BURST_MODE_ENABLE) {
-		ch_scratch.mhi.burst_mode_enabled = true;
+
+	if (burst_mode_enabled) {
+		ch_scratch.mhi.burst_mode_enabled = burst_mode_enabled;
 		ch_scratch.mhi.polling_configuration =
 			ipa3_mhi_get_ch_poll_cfg(client, params->ch_ctx_host,
 				(ch_props.ring_len / ch_props.re_size));
@@ -549,6 +563,7 @@
 	int res;
 	int ipa_ep_idx;
 	struct ipa3_ep_context *ep;
+	union __packed gsi_channel_scratch gsi_ch_scratch;
 
 	IPA_MHI_FUNC_ENTRY();
 
@@ -563,11 +578,34 @@
 		/*
 		 * set polling mode bit to DB mode before
 		 * resuming the channel
+		 *
+		 * For MHI-->IPA pipes:
+		 * when resuming due to transition to M0,
+		 * set the polling mode bit to 0.
+		 * In other cases, restore it's value form
+		 * when you stopped the channel.
+		 * Here, after successful resume client move to M0 state.
+		 * So, by default setting polling mode bit to 0.
+		 *
+		 * For IPA-->MHI pipe:
+		 * always restore the polling mode bit.
 		 */
-		res = gsi_write_channel_scratch(
-			ep->gsi_chan_hdl, ch_scratch);
+
+		res = gsi_read_channel_scratch(
+			ep->gsi_chan_hdl, &gsi_ch_scratch);
 		if (res) {
-			IPA_MHI_ERR("write ch scratch fail %d\n"
+			IPA_MHI_ERR("Read ch scratch fail %d\n"
+				, res);
+			return res;
+		}
+
+		if (IPA_CLIENT_IS_PROD(client))
+			gsi_ch_scratch.mhi.polling_mode = false;
+
+		res = gsi_write_channel_scratch(
+			ep->gsi_chan_hdl, gsi_ch_scratch);
+		if (res) {
+			IPA_MHI_ERR("Write ch scratch fail %d\n"
 				, res);
 			return res;
 		}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 554023e..73fb499 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1126,86 +1126,86 @@
 			true,
 			IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
 			QMB_MASTER_SELECT_DDR,
-			{ 6, 2, 8, 16, IPA_EE_UC } },
+			{ 6, 2, 8, 16, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_USB_PROD]            = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
 			QMB_MASTER_SELECT_DDR,
-			{ 0, 8, 8, 16, IPA_EE_AP } },
+			{ 0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_APPS_LAN_PROD]   = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 8, 10, 8, 16, IPA_EE_AP } },
+			{ 8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_APPS_WAN_PROD] = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
 			QMB_MASTER_SELECT_DDR,
-			{ 2, 3, 16, 32, IPA_EE_AP } },
+			{ 2, 3, 16, 32, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_APPS_CMD_PROD]	  = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
-			{ 5, 4, 20, 24, IPA_EE_AP } },
+			{ 5, 4, 20, 24, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_ODU_PROD]            = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
 			QMB_MASTER_SELECT_DDR,
-			{ 1, 0, 8, 16, IPA_EE_AP } },
+			{ 1, 0, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_ETHERNET_PROD]	  = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_REP_SEQ_TYPE_2PKT_PROC_PASS_NO_DEC_UCP_DMAP,
 			QMB_MASTER_SELECT_DDR,
-			{ 9, 0, 8, 16, IPA_EE_UC } },
+			{ 9, 0, 8, 16, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_Q6_WAN_PROD]         = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 3, 0, 16, 32, IPA_EE_Q6 } },
+			{ 3, 0, 16, 32, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_Q6_CMD_PROD]	  = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 4, 1, 20, 24, IPA_EE_Q6 } },
+			{ 4, 1, 20, 24, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	/* Only for test purpose */
 	[IPA_4_0][IPA_CLIENT_TEST_PROD]           = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{0, 8, 8, 16, IPA_EE_AP } },
+			{0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_TEST1_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{0, 8, 8, 16, IPA_EE_AP } },
+			{0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_TEST2_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 1, 0, 8, 16, IPA_EE_AP } },
+			{ 1, 0, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_TEST3_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 7, 9, 8, 16, IPA_EE_AP } },
+			{ 7, 9, 8, 16, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_TEST4_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{8, 10, 8, 16, IPA_EE_AP } },
+			{8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 
 
 	[IPA_4_0][IPA_CLIENT_WLAN1_CONS]          = {
@@ -1213,73 +1213,73 @@
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 18, 3, 6, 9, IPA_EE_UC } },
+			{ 18, 3, 6, 9, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_WLAN2_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 20, 13, 9, 9, IPA_EE_AP } },
+			{ 20, 13, 9, 9, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_WLAN3_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 21, 14, 9, 9, IPA_EE_AP } },
+			{ 21, 14, 9, 9, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_USB_CONS]            = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 19, 12, 9, 9, IPA_EE_AP } },
+			{ 19, 12, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_USB_DPL_CONS]        = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 15, 7, 5, 5, IPA_EE_AP } },
+			{ 15, 7, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_APPS_LAN_CONS]       = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 10, 5, 9, 9, IPA_EE_AP } },
+			{ 10, 5, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_APPS_WAN_CONS]       = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 11, 6, 9, 9, IPA_EE_AP } },
+			{ 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_ODU_EMB_CONS]        = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 17, 1, 17, 17, IPA_EE_AP } },
+			{ 17, 1, 17, 17, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_ETHERNET_CONS]	  = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 22, 1, 17, 17, IPA_EE_UC } },
+			{ 22, 1, 17, 17, IPA_EE_UC, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_Q6_LAN_CONS]         = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 14, 4, 9, 9, IPA_EE_Q6 } },
+			{ 14, 4, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_Q6_WAN_CONS]         = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 13, 3, 9, 9, IPA_EE_Q6 } },
+			{ 13, 3, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 16, 5, 9, 9, IPA_EE_Q6 } },
+			{ 16, 5, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	/* Only for test purpose */
 	/* MBIM aggregation test pipes should have the same QMB as USB_CONS */
 	[IPA_4_0][IPA_CLIENT_TEST_CONS]           = {
@@ -1287,38 +1287,38 @@
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 11, 6, 9, 9, IPA_EE_AP } },
+			{ 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_TEST1_CONS]           = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 11, 6, 9, 9, IPA_EE_AP } },
+			{ 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_TEST2_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 12, 2, 5, 5, IPA_EE_AP } },
+			{ 12, 2, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_TEST3_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 19, 12, 9, 9, IPA_EE_AP } },
+			{ 19, 12, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0][IPA_CLIENT_TEST4_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 21, 14, 9, 9, IPA_EE_AP } },
+			{ 21, 14, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	/* Dummy consumer (pipe 31) is used in L2TP rt rule */
 	[IPA_4_0][IPA_CLIENT_DUMMY_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 31, 31, 8, 8, IPA_EE_AP } },
+			{ 31, 31, 8, 8, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 
 	/* IPA_4_0_MHI */
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_WAN_PROD]   = {
@@ -1326,74 +1326,74 @@
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 2, 3, 16, 32, IPA_EE_AP } },
+			{ 2, 3, 16, 32, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_CMD_PROD]	  = {
 			true, IPA_v4_0_MHI_GROUP_DDR,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
-			{ 5, 4, 20, 24, IPA_EE_AP } },
+			{ 5, 4, 20, 24, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_MHI_PROD]            = {
 			true, IPA_v4_0_MHI_GROUP_PCIE,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_PCIE,
-			{ 1, 0, 8, 16, IPA_EE_AP } },
+			{ 1, 0, 8, 16, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_WAN_PROD]         = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 3, 0, 16, 32, IPA_EE_Q6 } },
+			{ 3, 0, 16, 32, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_CMD_PROD]	  = {
 			true, IPA_v4_0_MHI_GROUP_PCIE,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_PKT_PROCESS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 4, 1, 20, 24, IPA_EE_Q6 } },
+			{ 4, 1, 20, 24, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_PROD] = {
 			true, IPA_v4_0_MHI_GROUP_DMA,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
-			{ 7, 9, 8, 16, IPA_EE_AP } },
+			{ 7, 9, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_PROD] = {
 			true, IPA_v4_0_MHI_GROUP_DMA,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_DMA_ONLY,
 			QMB_MASTER_SELECT_DDR,
-			{ 8, 10, 8, 16, IPA_EE_AP } },
+			{ 8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	/* Only for test purpose */
 	[IPA_4_0_MHI][IPA_CLIENT_TEST_PROD]           = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{0, 8, 8, 16, IPA_EE_AP } },
+			{0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST1_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{0, 8, 8, 16, IPA_EE_AP } },
+			{0, 8, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST2_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 1, 0, 8, 16, IPA_EE_AP } },
+			{ 1, 0, 8, 16, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST3_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{7, 9, 8, 16, IPA_EE_AP } },
+			{7, 9, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST4_PROD]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			true,
 			IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
 			QMB_MASTER_SELECT_DDR,
-			{ 8, 10, 8, 16, IPA_EE_AP } },
+			{ 8, 10, 8, 16, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 
 
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_LAN_CONS]       = {
@@ -1401,87 +1401,87 @@
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 10, 5, 9, 9, IPA_EE_AP } },
+			{ 10, 5, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_APPS_WAN_CONS]       = {
 			true, IPA_v4_0_MHI_GROUP_DDR,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 11, 6, 9, 9, IPA_EE_AP } },
+			{ 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_MHI_CONS]            = {
 			true, IPA_v4_0_MHI_GROUP_PCIE,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
-			{ 17, 1, 17, 17, IPA_EE_AP } },
+			{ 17, 1, 17, 17, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_LAN_CONS]         = {
 			true, IPA_v4_0_MHI_GROUP_DDR,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 14, 4, 9, 9, IPA_EE_Q6 } },
+			{ 14, 4, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_WAN_CONS]         = {
 			true, IPA_v4_0_MHI_GROUP_DDR,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 13, 3, 9, 9, IPA_EE_Q6 } },
+			{ 13, 3, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_SYNC_CONS] = {
 			true, IPA_v4_0_MHI_GROUP_DMA,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
-			{ 20, 13, 9, 9, IPA_EE_AP } },
+			{ 20, 13, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_MEMCPY_DMA_ASYNC_CONS] = {
 			true, IPA_v4_0_MHI_GROUP_DMA,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
-			{ 21, 14, 9, 9, IPA_EE_AP } },
+			{ 21, 14, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_Q6_LTE_WIFI_AGGR_CONS] = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 16, 5, 9, 9, IPA_EE_Q6 } },
+			{ 16, 5, 9, 9, IPA_EE_Q6, GSI_USE_PREFETCH_BUFS } },
 	/* Only for test purpose */
 	[IPA_4_0_MHI][IPA_CLIENT_TEST_CONS]           = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
-			{ 11, 6, 9, 9, IPA_EE_AP } },
+			{ 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST1_CONS]           = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
-			{ 11, 6, 9, 9, IPA_EE_AP } },
+			{ 11, 6, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST2_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 12, 2, 5, 5, IPA_EE_AP } },
+			{ 12, 2, 5, 5, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST3_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
-			{ 19, 12, 9, 9, IPA_EE_AP } },
+			{ 19, 12, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	[IPA_4_0_MHI][IPA_CLIENT_TEST4_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_PCIE,
-			{ 21, 14, 9, 9, IPA_EE_AP } },
+			{ 21, 14, 9, 9, IPA_EE_AP, GSI_ESCAPE_BUF_ONLY } },
 	/* Dummy consumer (pipe 31) is used in L2TP rt rule */
 	[IPA_4_0_MHI][IPA_CLIENT_DUMMY_CONS]          = {
 			true, IPA_v4_0_GROUP_UL_DL,
 			false,
 			IPA_DPS_HPS_SEQ_TYPE_INVALID,
 			QMB_MASTER_SELECT_DDR,
-			{ 31, 31, 8, 8, IPA_EE_AP } },
+			{ 31, 31, 8, 8, IPA_EE_AP, GSI_USE_PREFETCH_BUFS } },
 };
 
 /**
@@ -2133,6 +2133,28 @@
 	return ipa_ep_idx;
 }
 
+
+/**
+ * ipa_get_ep_prefetch_mode() - provide prefetch_mode endpoint
+ * @client: client type
+ *
+ * Return value: prefetch_mode
+ */
+enum gsi_prefetch_mode ipa_get_ep_prefetch_mode(enum ipa_client_type client)
+{
+	enum gsi_prefetch_mode prefetch_mode;
+
+	if (client >= IPA_CLIENT_MAX || client < 0) {
+		IPAERR_RL("Bad client number: client =%d\n", client);
+		return -IPA_EP_NOT_ALLOCATED;
+	}
+
+	prefetch_mode = ipa3_ep_mapping[ipa3_get_hw_type_index()][client].
+		ipa_gsi_ep_info.prefetch_mode;
+
+	return prefetch_mode;
+}
+
 /**
  * ipa3_get_gsi_ep_info() - provide gsi ep information
  * @client: IPA client value
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index f06d6f3..ab43d32 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -824,13 +824,13 @@
 }
 EXPORT_SYMBOL(mhi_dev_send_ee_event);
 
-static void mhi_dev_trigger_cb(void)
+static void mhi_dev_trigger_cb(enum mhi_client_channel ch_id)
 {
 	struct mhi_dev_ready_cb_info *info;
 	enum mhi_ctrl_info state_data;
 
 	list_for_each_entry(info, &mhi_ctx->client_cb_list, list)
-		if (info->cb) {
+		if (info->cb && info->cb_data.channel == ch_id) {
 			mhi_ctrl_state_info(info->cb_data.channel, &state_data);
 			info->cb_data.ctrl_info = state_data;
 			info->cb(&info->cb_data);
@@ -1023,7 +1023,7 @@
 
 		mhi_update_state_info(ch_id, MHI_STATE_CONNECTED);
 		/* Trigger callback to clients */
-		mhi_dev_trigger_cb();
+		mhi_dev_trigger_cb(ch_id);
 		if (ch_id == MHI_CLIENT_MBIM_OUT)
 			kobject_uevent_env(&mhi_ctx->dev->kobj,
 						KOBJ_CHANGE, connected);
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index 9374bc8..aafb5c8 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -1119,7 +1119,7 @@
 					&ctx->usb_bam_connections[idx];
 	unsigned long peer_bam_handle;
 
-	ret = sps_phy2h(pipe_connect->dst_phy_addr, &peer_bam_handle);
+	ret = sps_phy2h(pipe_connect->src_phy_addr, &peer_bam_handle);
 	if (ret) {
 		log_event_err("%s: sps_phy2h failed (src BAM) %d\n",
 				__func__, ret);
diff --git a/drivers/power/supply/power_supply_sysfs.c b/drivers/power/supply/power_supply_sysfs.c
index 3ab93fe..cd76a09 100644
--- a/drivers/power/supply/power_supply_sysfs.c
+++ b/drivers/power/supply/power_supply_sysfs.c
@@ -335,6 +335,9 @@
 	POWER_SUPPLY_ATTR(battery_info),
 	POWER_SUPPLY_ATTR(battery_info_id),
 	POWER_SUPPLY_ATTR(enable_jeita_detection),
+	POWER_SUPPLY_ATTR(esr_actual),
+	POWER_SUPPLY_ATTR(esr_nominal),
+	POWER_SUPPLY_ATTR(soh),
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_ATTR(charge_counter_ext),
 	/* Properties of type `const char *' */
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index e834b8e..f21b2a8 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -60,6 +60,7 @@
 	bool			cl_feedback_on;
 	bool			esr_disable;
 	bool			esr_discharge_enable;
+	bool			qg_ext_sense;
 };
 
 struct qg_esr_data {
@@ -120,6 +121,10 @@
 	int			charge_type;
 	int			chg_iterm_ma;
 	int			next_wakeup_ms;
+	int			esr_actual;
+	int			esr_nominal;
+	int			soh;
+	int			soc_reporting_ready;
 	u32			fifo_done_count;
 	u32			wa_flags;
 	u32			seq_no;
@@ -151,11 +156,18 @@
 	struct ttf		*ttf;
 };
 
+struct ocv_all {
+	u32 ocv_uv;
+	u32 ocv_raw;
+	char ocv_type[20];
+};
+
 enum ocv_type {
 	S7_PON_OCV,
 	S3_GOOD_OCV,
 	S3_LAST_OCV,
 	SDAM_PON_OCV,
+	PON_OCV_MAX,
 };
 
 enum debug_mask {
diff --git a/drivers/power/supply/qcom/qg-reg.h b/drivers/power/supply/qcom/qg-reg.h
index d586a72..e0f400d 100644
--- a/drivers/power/supply/qcom/qg-reg.h
+++ b/drivers/power/supply/qcom/qg-reg.h
@@ -17,6 +17,7 @@
 #define QG_TYPE					0x0D
 
 #define QG_STATUS1_REG				0x08
+#define QG_OK_BIT				BIT(7)
 #define BATTERY_PRESENT_BIT			BIT(0)
 #define ESR_MEAS_DONE_BIT			BIT(4)
 
@@ -32,6 +33,7 @@
 #define QG_INT_RT_STS_REG			0x10
 #define FIFO_UPDATE_DONE_RT_STS_BIT		BIT(3)
 #define VBAT_LOW_INT_RT_STS_BIT			BIT(1)
+#define BATTERY_MISSING_INT_RT_STS_BIT		BIT(0)
 
 #define QG_INT_LATCHED_STS_REG			0x18
 #define FIFO_UPDATE_DONE_INT_LAT_STS_BIT	BIT(3)
@@ -64,6 +66,12 @@
 #define QG_S3_ENTRY_IBAT_THRESHOLD_REG		0x5E
 #define QG_S3_EXIT_IBAT_THRESHOLD_REG		0x5F
 
+#define QG_S5_OCV_VALIDATE_MEAS_CTL1_REG	0x60
+#define ALLOW_S5_BIT				BIT(7)
+
+#define QG_S7_PON_OCV_MEAS_CTL1_REG		0x64
+#define ADC_CONV_DLY_MASK			GENMASK(3, 0)
+
 #define QG_ESR_MEAS_TRIG_REG			0x68
 #define HW_ESR_MEAS_START_BIT			BIT(0)
 
@@ -105,6 +113,9 @@
 #define QG_SDAM_ESR_DISCHARGE_DELTA_OFFSET	0x6E /* 4-byte 0x6E-0x71 */
 #define QG_SDAM_ESR_CHARGE_SF_OFFSET		0x72 /* 2-byte 0x72-0x73 */
 #define QG_SDAM_ESR_DISCHARGE_SF_OFFSET		0x74 /* 2-byte 0x74-0x75 */
-#define QG_SDAM_PON_OCV_OFFSET			0x7C /* 2-byte 0x7C-0x7D */
+#define QG_SDAM_MAX_OFFSET			0xA4
+
+/* Below offset is used by PBS */
+#define QG_SDAM_PON_OCV_OFFSET			0xBC /* 2-byte 0xBC-0xBD */
 
 #endif
diff --git a/drivers/power/supply/qcom/qg-sdam.c b/drivers/power/supply/qcom/qg-sdam.c
index e7ffcb5..a7cb97e 100644
--- a/drivers/power/supply/qcom/qg-sdam.c
+++ b/drivers/power/supply/qcom/qg-sdam.c
@@ -111,7 +111,7 @@
 	length = sdam_info[param].length;
 	rc = regmap_bulk_write(chip->regmap, offset, (u8 *)&data, length);
 	if (rc < 0)
-		pr_err("Failed to write offset=%0x4x param=%d value=%d\n",
+		pr_err("Failed to write offset=%0x4 param=%d value=%d\n",
 					offset, param, data);
 	else
 		pr_debug("QG SDAM write param=%s value=%d\n",
@@ -137,11 +137,12 @@
 		return -EINVAL;
 	}
 
+	*data = 0;
 	offset = chip->sdam_base + sdam_info[param].offset;
 	length = sdam_info[param].length;
 	rc = regmap_raw_read(chip->regmap, offset, (u8 *)data, length);
 	if (rc < 0)
-		pr_err("Failed to read offset=%0x4x param=%d\n",
+		pr_err("Failed to read offset=%0x4 param=%d\n",
 					offset, param);
 	else
 		pr_debug("QG SDAM read param=%s value=%d\n",
@@ -163,11 +164,11 @@
 	offset = chip->sdam_base + offset;
 	rc = regmap_bulk_write(chip->regmap, offset, data, (size_t)length);
 	if (rc < 0) {
-		pr_err("Failed to write offset=%0x4x value=%d\n",
+		pr_err("Failed to write offset=%0x4 value=%d\n",
 					offset, *data);
 	} else {
 		for (i = 0; i < length; i++)
-			pr_debug("QG SDAM write offset=%0x4x value=%d\n",
+			pr_debug("QG SDAM write offset=%0x4 value=%d\n",
 					offset++, data[i]);
 	}
 
@@ -187,10 +188,10 @@
 	offset = chip->sdam_base + offset;
 	rc = regmap_raw_read(chip->regmap, offset, (u8 *)data, (size_t)length);
 	if (rc < 0) {
-		pr_err("Failed to read offset=%0x4x\n", offset);
+		pr_err("Failed to read offset=%0x4\n", offset);
 	} else {
 		for (i = 0; i < length; i++)
-			pr_debug("QG SDAM read offset=%0x4x value=%d\n",
+			pr_debug("QG SDAM read offset=%0x4 value=%d\n",
 					offset++, data[i]);
 	}
 
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index a8a7826..99e0f33 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -25,10 +25,12 @@
 #include <linux/platform_device.h>
 #include <linux/power_supply.h>
 #include <linux/regmap.h>
+#include <linux/slab.h>
 #include <linux/uaccess.h>
 #include <linux/pmic-voter.h>
 #include <linux/qpnp/qpnp-adc.h>
 #include <uapi/linux/qg.h>
+#include <uapi/linux/qg-profile.h>
 #include "fg-alg.h"
 #include "qg-sdam.h"
 #include "qg-core.h"
@@ -685,6 +687,7 @@
 
 	rc = qg_sdam_read(SDAM_ESR_CHARGE_SF, &data);
 	if (!rc && data) {
+		data = CAP(QG_ESR_SF_MIN, QG_ESR_SF_MAX, data);
 		chip->kdata.param[QG_ESR_CHARGE_SF].data = data;
 		chip->kdata.param[QG_ESR_CHARGE_SF].valid = true;
 		qg_dbg(chip, QG_DEBUG_ESR,
@@ -695,6 +698,7 @@
 
 	rc = qg_sdam_read(SDAM_ESR_DISCHARGE_SF, &data);
 	if (!rc && data) {
+		data = CAP(QG_ESR_SF_MIN, QG_ESR_SF_MAX, data);
 		chip->kdata.param[QG_ESR_DISCHARGE_SF].data = data;
 		chip->kdata.param[QG_ESR_DISCHARGE_SF].valid = true;
 		qg_dbg(chip, QG_DEBUG_ESR,
@@ -1002,6 +1006,7 @@
 		qg_dbg(chip, QG_DEBUG_ESR, "ESR_SW=%d during %s\n",
 			chip->esr_avg, is_charging ? "CHARGE" : "DISCHARGE");
 		qg_retrieve_esr_params(chip);
+		chip->esr_actual = chip->esr_avg;
 	}
 
 	return 0;
@@ -1052,23 +1057,22 @@
 	if (chip->udata.param[QG_ESR].valid)
 		chip->esr_last = chip->udata.param[QG_ESR].data;
 
+	if (chip->esr_actual != -EINVAL && chip->udata.param[QG_ESR].valid) {
+		chip->esr_nominal = chip->udata.param[QG_ESR].data;
+		if (chip->qg_psy)
+			power_supply_changed(chip->qg_psy);
+	}
+
 	if (!chip->dt.esr_disable)
 		qg_store_esr_params(chip);
 
 	qg_dbg(chip, QG_DEBUG_STATUS, "udata update: batt_soc=%d cc_soc=%d full_soc=%d qg_esr=%d\n",
-		chip->batt_soc, chip->cc_soc, chip->full_soc, chip->esr_last);
+		(chip->batt_soc != INT_MIN) ? chip->batt_soc : -EINVAL,
+		(chip->cc_soc != INT_MIN) ? chip->cc_soc : -EINVAL,
+		chip->full_soc, chip->esr_last);
 	vote(chip->awake_votable, UDATA_READY_VOTER, false, 0);
 }
 
-static irqreturn_t qg_default_irq_handler(int irq, void *data)
-{
-	struct qpnp_qg *chip = data;
-
-	qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n");
-
-	return IRQ_HANDLED;
-}
-
 #define MAX_FIFO_DELTA_PERCENT		10
 static irqreturn_t qg_fifo_update_done_handler(int irq, void *data)
 {
@@ -1154,6 +1158,11 @@
 		pr_err("Failed to read RT status, rc=%d\n", rc);
 		goto done;
 	}
+	/* ignore VBAT low if battery is missing */
+	if ((status & BATTERY_MISSING_INT_RT_STS_BIT) ||
+			chip->battery_missing)
+		goto done;
+
 	chip->vbat_low = !!(status & VBAT_LOW_INT_RT_STS_BIT);
 
 	rc = process_rt_fifo_data(chip, chip->vbat_low, false);
@@ -1170,8 +1179,20 @@
 {
 	struct qpnp_qg *chip = data;
 	u32 ocv_uv = 0;
+	int rc;
+	u8 status = 0;
 
 	qg_dbg(chip, QG_DEBUG_IRQ, "IRQ triggered\n");
+
+	rc = qg_read(chip, chip->qg_base + QG_INT_RT_STS_REG, &status, 1);
+	if (rc < 0)
+		pr_err("Failed to read RT status rc=%d\n", rc);
+
+	/* ignore VBAT empty if battery is missing */
+	if ((status & BATTERY_MISSING_INT_RT_STS_BIT) ||
+			chip->battery_missing)
+		return IRQ_HANDLED;
+
 	pr_warn("VBATT EMPTY SOC = 0\n");
 
 	chip->catch_up_soc = 0;
@@ -1232,7 +1253,6 @@
 static struct qg_irq_info qg_irqs[] = {
 	[QG_BATT_MISSING_IRQ] = {
 		.name		= "qg-batt-missing",
-		.handler	= qg_default_irq_handler,
 	},
 	[QG_VBATT_LOW_IRQ] = {
 		.name		= "qg-vbat-low",
@@ -1256,11 +1276,9 @@
 	},
 	[QG_FSM_STAT_CHG_IRQ] = {
 		.name		= "qg-fsm-state-chg",
-		.handler	= qg_default_irq_handler,
 	},
 	[QG_EVENT_IRQ] = {
 		.name		= "qg-event",
-		.handler	= qg_default_irq_handler,
 	},
 };
 
@@ -1691,6 +1709,17 @@
 			chip->cl->learned_cap_uah = pval->intval;
 		mutex_unlock(&chip->cl->lock);
 		break;
+	case POWER_SUPPLY_PROP_SOH:
+		chip->soh = pval->intval;
+		qg_dbg(chip, QG_DEBUG_STATUS, "SOH update: SOH=%d esr_actual=%d esr_nominal=%d\n",
+				chip->soh, chip->esr_actual, chip->esr_nominal);
+		break;
+	case POWER_SUPPLY_PROP_ESR_ACTUAL:
+		chip->esr_actual = pval->intval;
+		break;
+	case POWER_SUPPLY_PROP_ESR_NOMINAL:
+		chip->esr_nominal = pval->intval;
+		break;
 	default:
 		break;
 	}
@@ -1737,6 +1766,9 @@
 	case POWER_SUPPLY_PROP_RESISTANCE_NOW:
 		pval->intval = chip->esr_last;
 		break;
+	case POWER_SUPPLY_PROP_SOC_REPORTING_READY:
+		pval->intval = chip->soc_reporting_ready;
+		break;
 	case POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE:
 		pval->intval = chip->dt.rbat_conn_mohm;
 		break;
@@ -1785,6 +1817,17 @@
 	case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
 		rc = ttf_get_time_to_empty(chip->ttf, &pval->intval);
 		break;
+	case POWER_SUPPLY_PROP_ESR_ACTUAL:
+		pval->intval = (chip->esr_actual == -EINVAL) ?  -EINVAL :
+					(chip->esr_actual * 1000);
+		break;
+	case POWER_SUPPLY_PROP_ESR_NOMINAL:
+		pval->intval = (chip->esr_nominal == -EINVAL) ?  -EINVAL :
+					(chip->esr_nominal * 1000);
+		break;
+	case POWER_SUPPLY_PROP_SOH:
+		pval->intval = chip->soh;
+		break;
 	default:
 		pr_debug("Unsupported property %d\n", psp);
 		break;
@@ -1798,6 +1841,9 @@
 {
 	switch (psp) {
 	case POWER_SUPPLY_PROP_CHARGE_FULL:
+	case POWER_SUPPLY_PROP_ESR_ACTUAL:
+	case POWER_SUPPLY_PROP_ESR_NOMINAL:
+	case POWER_SUPPLY_PROP_SOH:
 		return 1;
 	default:
 		break;
@@ -1815,6 +1861,7 @@
 	POWER_SUPPLY_PROP_RESISTANCE,
 	POWER_SUPPLY_PROP_RESISTANCE_ID,
 	POWER_SUPPLY_PROP_RESISTANCE_NOW,
+	POWER_SUPPLY_PROP_SOC_REPORTING_READY,
 	POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE,
 	POWER_SUPPLY_PROP_DEBUG_BATTERY,
 	POWER_SUPPLY_PROP_BATTERY_TYPE,
@@ -1828,6 +1875,9 @@
 	POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
 	POWER_SUPPLY_PROP_TIME_TO_FULL_AVG,
 	POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
+	POWER_SUPPLY_PROP_ESR_ACTUAL,
+	POWER_SUPPLY_PROP_ESR_NOMINAL,
+	POWER_SUPPLY_PROP_SOH,
 };
 
 static const struct power_supply_desc qg_psy_desc = {
@@ -1914,6 +1964,7 @@
 {
 	int rc;
 	bool parallel_enabled = is_parallel_enabled(chip);
+	bool update_smb = false;
 
 	if (parallel_enabled == chip->parallel_enabled)
 		return 0;
@@ -1924,7 +1975,14 @@
 
 	mutex_lock(&chip->data_lock);
 
-	rc = process_rt_fifo_data(chip, false, true);
+	/*
+	 * Parallel charger uses the same external sense, hence do not
+	 * enable SMB sensing if PMI632 is configured for external sense.
+	 */
+	if (!chip->dt.qg_ext_sense)
+		update_smb = true;
+
+	rc = process_rt_fifo_data(chip, false, update_smb);
 	if (rc < 0)
 		pr_err("Failed to process RT FIFO data, rc=%d\n", rc);
 
@@ -1949,6 +2007,110 @@
 	return 0;
 }
 
+static int qg_handle_battery_removal(struct qpnp_qg *chip)
+{
+	int rc, length = QG_SDAM_MAX_OFFSET - QG_SDAM_VALID_OFFSET;
+	u8 *data;
+
+	/* clear SDAM */
+	data = kcalloc(length, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	rc = qg_sdam_multibyte_write(QG_SDAM_VALID_OFFSET, data, length);
+	if (rc < 0)
+		pr_err("Failed to clear SDAM rc=%d\n", rc);
+
+	return rc;
+}
+
+#define MAX_QG_OK_RETRIES	20
+static int qg_handle_battery_insertion(struct qpnp_qg *chip)
+{
+	int rc, count = 0;
+	u32 ocv_uv = 0, ocv_raw = 0;
+	u8 reg = 0;
+
+	do {
+		rc = qg_read(chip, chip->qg_base + QG_STATUS1_REG, &reg, 1);
+		if (rc < 0) {
+			pr_err("Failed to read STATUS1_REG rc=%d\n", rc);
+			return rc;
+		}
+
+		if (reg & QG_OK_BIT)
+			break;
+
+		msleep(200);
+		count++;
+	} while (count < MAX_QG_OK_RETRIES);
+
+	if (count == MAX_QG_OK_RETRIES) {
+		qg_dbg(chip, QG_DEBUG_STATUS, "QG_OK not set!\n");
+		return 0;
+	}
+
+	/* read S7 PON OCV */
+	rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S7_PON_OCV);
+	if (rc < 0) {
+		pr_err("Failed to read PON OCV rc=%d\n", rc);
+		return rc;
+	}
+
+	qg_dbg(chip, QG_DEBUG_STATUS,
+		"S7_OCV on battery insertion = %duV\n", ocv_uv);
+
+	chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
+	chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
+	/* clear all the userspace data */
+	chip->kdata.param[QG_CLEAR_LEARNT_DATA].data = 1;
+	chip->kdata.param[QG_CLEAR_LEARNT_DATA].valid = true;
+
+	vote(chip->awake_votable, GOOD_OCV_VOTER, true, 0);
+	/* signal the read thread */
+	chip->data_ready = true;
+	wake_up_interruptible(&chip->qg_wait_q);
+
+	return 0;
+}
+
+static int qg_battery_status_update(struct qpnp_qg *chip)
+{
+	int rc;
+	union power_supply_propval prop = {0, };
+
+	if (!is_batt_available(chip))
+		return 0;
+
+	mutex_lock(&chip->data_lock);
+
+	rc = power_supply_get_property(chip->batt_psy,
+			POWER_SUPPLY_PROP_PRESENT, &prop);
+	if (rc < 0) {
+		pr_err("Failed to get battery-present, rc=%d\n", rc);
+		goto done;
+	}
+
+	if (chip->battery_missing && prop.intval) {
+		pr_warn("Battery inserted!\n");
+		rc = qg_handle_battery_insertion(chip);
+		if (rc < 0)
+			pr_err("Failed in battery-insertion rc=%d\n", rc);
+	} else if (!chip->battery_missing && !prop.intval) {
+		pr_warn("Battery removed!\n");
+		rc = qg_handle_battery_removal(chip);
+		if (rc < 0)
+			pr_err("Failed in battery-removal rc=%d\n", rc);
+	}
+
+	chip->battery_missing = !prop.intval;
+
+done:
+	mutex_unlock(&chip->data_lock);
+	return rc;
+}
+
+
 static void qg_status_change_work(struct work_struct *work)
 {
 	struct qpnp_qg *chip = container_of(work,
@@ -1961,6 +2123,10 @@
 		goto out;
 	}
 
+	rc = qg_battery_status_update(chip);
+	if (rc < 0)
+		pr_err("Failed to process battery status update rc=%d\n", rc);
+
 	rc = power_supply_get_property(chip->batt_psy,
 			POWER_SUPPLY_PROP_CHARGE_TYPE, &prop);
 	if (rc < 0)
@@ -2380,12 +2546,21 @@
 	return 0;
 }
 
+
+static struct ocv_all ocv[] = {
+	[S7_PON_OCV] = { 0, 0, "S7_PON_OCV"},
+	[S3_GOOD_OCV] = { 0, 0, "S3_GOOD_OCV"},
+	[S3_LAST_OCV] = { 0, 0, "S3_LAST_OCV"},
+	[SDAM_PON_OCV] = { 0, 0, "SDAM_PON_OCV"},
+};
+
+#define S7_ERROR_MARGIN_UV		20000
 static int qg_determine_pon_soc(struct qpnp_qg *chip)
 {
-	int rc = 0, batt_temp = 0;
+	int rc = 0, batt_temp = 0, i;
 	bool use_pon_ocv = true;
 	unsigned long rtc_sec = 0;
-	u32 ocv_uv = 0, ocv_raw = 0, soc = 0, shutdown[SDAM_MAX] = {0};
+	u32 ocv_uv = 0, soc = 0, shutdown[SDAM_MAX] = {0};
 	char ocv_type[20] = "NONE";
 
 	if (!chip->profile_loaded) {
@@ -2434,33 +2609,47 @@
 			goto done;
 		}
 
-		/*
-		 * Read S3_LAST_OCV, if S3_LAST_OCV is invalid,
-		 * read the SDAM_PON_OCV
-		 * if SDAM is not-set, use S7_PON_OCV.
-		 */
-		strlcpy(ocv_type, "S3_LAST_SOC", 20);
-		rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, S3_LAST_OCV);
-		if (rc < 0)
-			goto done;
-
-		if (ocv_raw == FIFO_V_RESET_VAL) {
-			/* S3_LAST_OCV is invalid */
-			strlcpy(ocv_type, "SDAM_PON_SOC", 20);
-			rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw, SDAM_PON_OCV);
+		/* read all OCVs */
+		for (i = S7_PON_OCV; i < PON_OCV_MAX; i++) {
+			rc = qg_read_ocv(chip, &ocv[i].ocv_uv,
+						&ocv[i].ocv_raw, i);
 			if (rc < 0)
-				goto done;
+				pr_err("Failed to read %s OCV rc=%d\n",
+						ocv[i].ocv_type, rc);
+			else
+				qg_dbg(chip, QG_DEBUG_PON, "%s OCV=%d\n",
+					ocv[i].ocv_type, ocv[i].ocv_uv);
+		}
 
-			if (!ocv_uv) {
-				/* SDAM_PON_OCV is not set */
+		if (ocv[S3_LAST_OCV].ocv_raw == FIFO_V_RESET_VAL) {
+			if (!ocv[SDAM_PON_OCV].ocv_uv) {
 				strlcpy(ocv_type, "S7_PON_SOC", 20);
-				rc = qg_read_ocv(chip, &ocv_uv, &ocv_raw,
-							S7_PON_OCV);
-				if (rc < 0)
-					goto done;
+				ocv_uv = ocv[S7_PON_OCV].ocv_uv;
+			} else if (ocv[SDAM_PON_OCV].ocv_uv <=
+					ocv[S7_PON_OCV].ocv_uv) {
+				strlcpy(ocv_type, "S7_PON_SOC", 20);
+				ocv_uv = ocv[S7_PON_OCV].ocv_uv;
+			} else if (!shutdown[SDAM_VALID] &&
+				((ocv[SDAM_PON_OCV].ocv_uv -
+					ocv[S7_PON_OCV].ocv_uv) >
+					S7_ERROR_MARGIN_UV)) {
+				strlcpy(ocv_type, "S7_PON_SOC", 20);
+				ocv_uv = ocv[S7_PON_OCV].ocv_uv;
+			} else {
+				strlcpy(ocv_type, "SDAM_PON_SOC", 20);
+				ocv_uv = ocv[SDAM_PON_OCV].ocv_uv;
+			}
+		} else {
+			if (ocv[S3_LAST_OCV].ocv_uv >= ocv[S7_PON_OCV].ocv_uv) {
+				strlcpy(ocv_type, "S3_LAST_SOC", 20);
+				ocv_uv = ocv[S3_LAST_OCV].ocv_uv;
+			} else {
+				strlcpy(ocv_type, "S7_PON_SOC", 20);
+				ocv_uv = ocv[S7_PON_OCV].ocv_uv;
 			}
 		}
 
+		ocv_uv = CAP(QG_MIN_OCV_UV, QG_MAX_OCV_UV, ocv_uv);
 		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
 		if (rc < 0) {
 			pr_err("Failed to lookup SOC@PON rc=%d\n", rc);
@@ -2493,6 +2682,9 @@
 	pr_info("using %s @ PON ocv_uv=%duV soc=%d\n",
 			ocv_type, ocv_uv, chip->msoc);
 
+	/* SOC reporting is now ready */
+	chip->soc_reporting_ready = 1;
+
 	return 0;
 }
 
@@ -2515,6 +2707,7 @@
 	return 0;
 }
 
+#define ADC_CONV_DLY_512MS		0xA
 static int qg_hw_init(struct qpnp_qg *chip)
 {
 	int rc, temp;
@@ -2695,6 +2888,22 @@
 		return rc;
 	}
 
+	/* disable S5 */
+	rc = qg_masked_write(chip, chip->qg_base +
+				QG_S5_OCV_VALIDATE_MEAS_CTL1_REG,
+				ALLOW_S5_BIT, 0);
+	if (rc < 0)
+		pr_err("Failed to disable S5 rc=%d\n", rc);
+
+	/* change PON OCV time to 512ms */
+	rc = qg_masked_write(chip, chip->qg_base +
+				QG_S7_PON_OCV_MEAS_CTL1_REG,
+				ADC_CONV_DLY_MASK,
+				ADC_CONV_DLY_512MS);
+	if (rc < 0)
+		pr_err("Failed to reconfigure S7-delay rc=%d\n", rc);
+
+
 	return 0;
 }
 
@@ -3117,6 +3326,8 @@
 	else
 		chip->dt.esr_disable_soc = temp * 100;
 
+	chip->dt.qg_ext_sense = of_property_read_bool(node, "qcom,qg-ext-sns");
+
 	/* Capacity learning params*/
 	if (!chip->dt.cl_disable) {
 		chip->dt.cl_feedback_on = of_property_read_bool(node,
@@ -3176,9 +3387,9 @@
 			chip->cl->dt.min_start_soc, chip->cl->dt.max_start_soc,
 			chip->cl->dt.min_temp, chip->cl->dt.max_temp);
 	}
-	qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d\n",
+	qg_dbg(chip, QG_DEBUG_PON, "DT: vbatt_empty_mv=%dmV vbatt_low_mv=%dmV delta_soc=%d ext-sns=%d\n",
 			chip->dt.vbatt_empty_mv, chip->dt.vbatt_low_mv,
-			chip->dt.delta_soc);
+			chip->dt.delta_soc, chip->dt.qg_ext_sense);
 
 	return 0;
 }
@@ -3407,6 +3618,9 @@
 	chip->cc_soc = INT_MIN;
 	chip->full_soc = QG_SOC_FULL;
 	chip->chg_iterm_ma = INT_MIN;
+	chip->soh = -EINVAL;
+	chip->esr_actual = -EINVAL;
+	chip->esr_nominal = -EINVAL;
 
 	rc = qg_alg_init(chip);
 	if (rc < 0) {
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 07a6198..cc01399 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -167,6 +167,8 @@
 #define PM660_BST_HEADROOM_DEFAULT_MV	200
 #define BST_HEADROOM_DEFAULT_MV		150
 
+#define PMIC5_LCDB_OFF_ON_DELAY_US	20000
+
 struct ldo_regulator {
 	struct regulator_desc		rdesc;
 	struct regulator_dev		*rdev;
@@ -1340,22 +1342,27 @@
 
 static int qpnp_lcdb_regulator_register(struct qpnp_lcdb *lcdb, u8 type)
 {
-	int rc = 0;
+	int rc = 0, off_on_delay = 0;
 	struct regulator_init_data *init_data;
 	struct regulator_config cfg = {};
 	struct regulator_desc *rdesc;
 	struct regulator_dev *rdev;
 	struct device_node *node;
 
+	if (lcdb->pmic_rev_id->pmic_subtype != PM660L_SUBTYPE)
+		off_on_delay = PMIC5_LCDB_OFF_ON_DELAY_US;
+
 	if (type == LDO) {
 		node			= lcdb->ldo.node;
 		rdesc			= &lcdb->ldo.rdesc;
 		rdesc->ops		= &qpnp_lcdb_ldo_ops;
+		rdesc->off_on_delay	= off_on_delay;
 		rdev			= lcdb->ldo.rdev;
 	} else if (type == NCP) {
 		node			= lcdb->ncp.node;
 		rdesc			= &lcdb->ncp.rdesc;
 		rdesc->ops		= &qpnp_lcdb_ncp_ops;
+		rdesc->off_on_delay	= off_on_delay;
 		rdev			= lcdb->ncp.rdev;
 	} else {
 		pr_err("Invalid regulator type %d\n", type);
diff --git a/drivers/soc/qcom/socinfo.c b/drivers/soc/qcom/socinfo.c
index 1ac30eb..fffef10 100644
--- a/drivers/soc/qcom/socinfo.c
+++ b/drivers/soc/qcom/socinfo.c
@@ -602,6 +602,9 @@
 	/* SDM710 ID */
 	[360] = {MSM_CPU_SDM710, "SDM710"},
 
+	/* SXR1120 ID */
+	[370] = {MSM_CPU_SXR1120, "SXR1120"},
+
 	/* 8953 ID */
 	[293] = {MSM_CPU_8953, "MSM8953"},
 	[304] = {MSM_CPU_8953, "APQ8053"},
@@ -618,6 +621,12 @@
 	[294] = {MSM_CPU_8937, "MSM8937"},
 	[295] = {MSM_CPU_8937, "APQ8937"},
 
+	/* MSM8917 IDs */
+	[303] = {MSM_CPU_8917, "MSM8917"},
+	[307] = {MSM_CPU_8917, "APQ8017"},
+	[308] = {MSM_CPU_8917, "MSM8217"},
+	[309] = {MSM_CPU_8917, "MSM8617"},
+
 	/* SDM429 and SDM439 ID*/
 	[353] = {MSM_CPU_SDM439, "SDM439"},
 	[354] = {MSM_CPU_SDM429, "SDM429"},
@@ -1551,6 +1560,10 @@
 		dummy_socinfo.id = 347;
 		strlcpy(dummy_socinfo.build_id, "qcs605 - ",
 			sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_sxr1120()) {
+		dummy_socinfo.id = 370;
+		strlcpy(dummy_socinfo.build_id, "sxr1120 - ",
+			sizeof(dummy_socinfo.build_id));
 	} else if (early_machine_is_mdm9650()) {
 		dummy_socinfo.id = 286;
 		strlcpy(dummy_socinfo.build_id, "mdm9650 - ",
@@ -1567,6 +1580,10 @@
 		dummy_socinfo.id = 294;
 		strlcpy(dummy_socinfo.build_id, "msm8937 - ",
 			sizeof(dummy_socinfo.build_id));
+	} else if (early_machine_is_msm8917()) {
+		dummy_socinfo.id = 303;
+		strlcpy(dummy_socinfo.build_id, "msm8917 - ",
+			sizeof(dummy_socinfo.build_id));
 	} else if (early_machine_is_sdm450()) {
 		dummy_socinfo.id = 338;
 		strlcpy(dummy_socinfo.build_id, "sdm450 - ",
diff --git a/drivers/usb/dwc3/ep0.c b/drivers/usb/dwc3/ep0.c
index 902d36e..d9baac6 100644
--- a/drivers/usb/dwc3/ep0.c
+++ b/drivers/usb/dwc3/ep0.c
@@ -43,6 +43,8 @@
 static void __dwc3_ep0_do_control_status(struct dwc3 *dwc, struct dwc3_ep *dep);
 static void __dwc3_ep0_do_control_data(struct dwc3 *dwc,
 		struct dwc3_ep *dep, struct dwc3_request *req);
+static int dwc3_ep0_delegate_req(struct dwc3 *dwc,
+		struct usb_ctrlrequest *ctrl);
 
 static const char *dwc3_ep0_state_string(enum dwc3_ep0_state state)
 {
@@ -358,12 +360,14 @@
 static void dwc3_ep0_status_cmpl(struct usb_ep *ep, struct usb_request *req)
 {
 }
+
 /*
  * ch 9.4.5
  */
 static int dwc3_ep0_handle_status(struct dwc3 *dwc,
 		struct usb_ctrlrequest *ctrl)
 {
+	int ret;
 	struct dwc3_ep		*dep;
 	u32			recip;
 	u32			reg;
@@ -397,7 +401,8 @@
 		 * Function Remote Wake Capable	D0
 		 * Function Remote Wakeup	D1
 		 */
-		break;
+		ret = dwc3_ep0_delegate_req(dwc, ctrl);
+		return ret;
 
 	case USB_RECIP_ENDPOINT:
 		dep = dwc3_wIndex_to_dep(dwc, ctrl->wIndex);
@@ -524,6 +529,9 @@
 			if (wIndex & USB_INTRF_FUNC_SUSPEND_RW)
 				/* XXX enable remote wakeup */
 				;
+			ret = dwc3_ep0_delegate_req(dwc, ctrl);
+			if (ret)
+				return ret;
 			break;
 		default:
 			return -EINVAL;
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index 55c8648..d4d4882 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -922,6 +922,11 @@
 			log_event_dbg("%s: ST_CON_IN_PROG_EVT_HOST_READY",
 					 __func__);
 		} else if (event == EVT_CONNECTED) {
+			if (peek_event(d_port) == EVT_SUSPEND) {
+				log_event_dbg("%s: ST_CON_IN_PROG_EVT_SUSPEND",
+					 __func__);
+				break;
+			}
 			ipa_data_path_enable(d_port);
 			d_port->sm_state = STATE_CONNECTED;
 			log_event_dbg("%s: ST_CON_IN_PROG_EVT_CON %d",
@@ -2541,6 +2546,14 @@
 	log_event_dbg("%s: completed", __func__);
 }
 
+static int gsi_get_status(struct usb_function *f)
+{
+	unsigned int remote_wakeup_en_status = f->func_wakeup_allowed ? 1 : 0;
+
+	return (remote_wakeup_en_status << FUNC_WAKEUP_ENABLE_SHIFT) |
+		(1 << FUNC_WAKEUP_CAPABLE_SHIFT);
+}
+
 static int gsi_func_suspend(struct usb_function *f, u8 options)
 {
 	bool func_wakeup_allowed;
@@ -3308,6 +3321,7 @@
 	gsi->function.disable = gsi_disable;
 	gsi->function.free_func = gsi_free_func;
 	gsi->function.suspend = gsi_suspend;
+	gsi->function.get_status = gsi_get_status;
 	gsi->function.func_suspend = gsi_func_suspend;
 	gsi->function.resume = gsi_resume;
 
diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
index a75e5d3..24bc2d4 100644
--- a/drivers/usb/gadget/function/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -386,10 +386,31 @@
 					struct sk_buff *skb)
 {
 	struct sk_buff *skb2;
+	struct rndis_packet_msg_type *header = NULL;
+	struct f_rndis *rndis = func_to_rndis(&port->func);
 
 	if (!skb)
 		return NULL;
 
+	if (rndis->port.multi_pkt_xfer) {
+		if (port->header) {
+			header = port->header;
+			header->MessageType = cpu_to_le32(RNDIS_MSG_PACKET);
+			header->MessageLength = cpu_to_le32(skb->len +
+							sizeof(*header));
+			header->DataOffset = cpu_to_le32(36);
+			header->DataLength = cpu_to_le32(skb->len);
+			pr_debug("MessageLength:%d DataLength:%d\n",
+						header->MessageLength,
+						header->DataLength);
+			return skb;
+		}
+
+		dev_kfree_skb(skb);
+		pr_err("RNDIS header is NULL.\n");
+		return NULL;
+	}
+
 	skb2 = skb_realloc_headroom(skb, sizeof(struct rndis_packet_msg_type));
 	rndis_add_hdr(skb2);
 
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index 9e38809..c75e790 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -246,6 +246,7 @@
 }
 
 static void rx_complete(struct usb_ep *ep, struct usb_request *req);
+static void tx_complete(struct usb_ep *ep, struct usb_request *req);
 
 static int
 rx_submit(struct eth_dev *dev, struct usb_request *req, gfp_t gfp_flags)
@@ -307,7 +308,6 @@
 
 	req->buf = skb->data;
 	req->length = size;
-	req->complete = rx_complete;
 	req->context = skb;
 
 	retval = usb_ep_queue(out, req, gfp_flags);
@@ -410,6 +410,7 @@
 {
 	unsigned		i;
 	struct usb_request	*req;
+	bool			usb_in;
 
 	if (!n)
 		return -ENOMEM;
@@ -420,10 +421,22 @@
 		if (i-- == 0)
 			goto extra;
 	}
+
+	if (ep->desc->bEndpointAddress & USB_DIR_IN)
+		usb_in = true;
+	else
+		usb_in = false;
+
 	while (i--) {
 		req = usb_ep_alloc_request(ep, GFP_ATOMIC);
 		if (!req)
 			return list_empty(list) ? -ENOMEM : 0;
+		/* update completion handler */
+		if (usb_in)
+			req->complete = tx_complete;
+		else
+			req->complete = rx_complete;
+
 		list_add(&req->list, list);
 	}
 	return 0;
@@ -575,7 +588,7 @@
 
 static void tx_complete(struct usb_ep *ep, struct usb_request *req)
 {
-	struct sk_buff	*skb = req->context;
+	struct sk_buff	*skb;
 	struct eth_dev	*dev = ep->driver_data;
 	struct net_device *net = dev->net;
 	struct usb_request *new_req;
@@ -683,6 +696,7 @@
 			spin_unlock(&dev->req_lock);
 		}
 	} else {
+		skb = req->context;
 		/* Is aggregation already enabled and buffers allocated ? */
 		if (dev->port_usb->multi_pkt_xfer && dev->tx_req_bufsize) {
 			req->buf = kzalloc(dev->tx_req_bufsize
@@ -725,7 +739,7 @@
 	list_for_each(act, &dev->tx_reqs) {
 		req = container_of(act, struct usb_request, list);
 		if (!req->buf)
-			req->buf = kmalloc(dev->tx_req_bufsize
+			req->buf = kzalloc(dev->tx_req_bufsize
 				+ dev->gadget->extra_buf_alloc, GFP_ATOMIC);
 
 		if (!req->buf)
@@ -804,29 +818,6 @@
 	}
 
 	dev->tx_pkts_rcvd++;
-	/*
-	 * no buffer copies needed, unless the network stack did it
-	 * or the hardware can't use skb buffers.
-	 * or there's not enough space for extra headers we need
-	 */
-	spin_lock_irqsave(&dev->lock, flags);
-	if (dev->wrap && dev->port_usb)
-		skb = dev->wrap(dev->port_usb, skb);
-	spin_unlock_irqrestore(&dev->lock, flags);
-
-	if (!skb) {
-		if (dev->port_usb && dev->port_usb->supports_multi_frame) {
-			/*
-			 * Multi frame CDC protocols may store the frame for
-			 * later which is not a dropped frame.
-			 */
-		} else {
-			dev->net->stats.tx_dropped++;
-		}
-
-		/* no error code for dropped packets */
-		return NETDEV_TX_OK;
-	}
 
 	/* Allocate memory for tx_reqs to support multi packet transfer */
 	spin_lock_irqsave(&dev->req_lock, flags);
@@ -861,13 +852,45 @@
 		dev->tx_throttle++;
 		netif_stop_queue(net);
 	}
-
-	dev->tx_skb_hold_count++;
 	spin_unlock_irqrestore(&dev->req_lock, flags);
 
+	/* no buffer copies needed, unless the network stack did it
+	 * or the hardware can't use skb buffers.
+	 * or there's not enough space for extra headers we need
+	 */
+	spin_lock_irqsave(&dev->lock, flags);
+	if (dev->wrap) {
+		if (dev->port_usb)
+			skb = dev->wrap(dev->port_usb, skb);
+		if (!skb) {
+			spin_unlock_irqrestore(&dev->lock, flags);
+			/* Multi frame CDC protocols may store the frame for
+			 * later which is not a dropped frame.
+			 */
+			if (dev->port_usb &&
+					dev->port_usb->supports_multi_frame)
+				goto multiframe;
+			goto drop;
+		}
+	}
+
+	dev->tx_skb_hold_count++;
+	spin_unlock_irqrestore(&dev->lock, flags);
+
 	if (multi_pkt_xfer) {
+		pr_debug("req->length:%d header_len:%u\n"
+				"skb->len:%d skb->data_len:%d\n",
+				req->length, dev->header_len,
+				skb->len, skb->data_len);
+		/* Add RNDIS Header */
+		memcpy(req->buf + req->length, dev->port_usb->header,
+						dev->header_len);
+		/* Increment req length by header size */
+		req->length += dev->header_len;
+		/* Copy received IP data from SKB */
 		memcpy(req->buf + req->length, skb->data, skb->len);
-		req->length = req->length + skb->len;
+		/* Increment req length by skb data length */
+		req->length += skb->len;
 		length = req->length;
 		dev_kfree_skb_any(skb);
 
@@ -927,8 +950,6 @@
 		req->context = skb;
 	}
 
-	req->complete = tx_complete;
-
 	/* NCM requires no zlp if transfer is dwNtbInMaxSize */
 	if (is_fixed && length == fixed_in_len &&
 	    (length % in->maxpacket) == 0)
@@ -977,11 +998,13 @@
 			dev_kfree_skb_any(skb);
 		else
 			req->length = 0;
+drop:
 		dev->net->stats.tx_dropped++;
+multiframe:
 		spin_lock_irqsave(&dev->req_lock, flags);
 		if (list_empty(&dev->tx_reqs))
 			netif_start_queue(net);
-		list_add(&req->list, &dev->tx_reqs);
+		list_add_tail(&req->list, &dev->tx_reqs);
 		spin_unlock_irqrestore(&dev->req_lock, flags);
 	}
 success:
@@ -1443,6 +1466,8 @@
 	else
 		INFO(dev, "MAC %pM\n", dev->dev_mac);
 
+	uether_debugfs_init(dev);
+
 	return status;
 }
 EXPORT_SYMBOL_GPL(gether_register_netdev);
@@ -1594,6 +1619,11 @@
 	if (!dev)
 		return ERR_PTR(-EINVAL);
 
+	/* size of rndis_packet_msg_type is 44 */
+	link->header = kzalloc(44, GFP_ATOMIC);
+	if (!link->header)
+		return ERR_PTR(-ENOMEM);
+
 	if (link->in_ep) {
 		link->in_ep->driver_data = dev;
 		result = usb_ep_enable(link->in_ep);
@@ -1657,8 +1687,12 @@
 	}
 fail0:
 	/* caller is responsible for cleanup on error */
-	if (result < 0)
+	if (result < 0) {
+		kfree(link->header);
+
 		return ERR_PTR(result);
+	}
+
 	return dev->net;
 }
 EXPORT_SYMBOL_GPL(gether_connect);
@@ -1711,6 +1745,9 @@
 			spin_lock(&dev->req_lock);
 		}
 		spin_unlock(&dev->req_lock);
+		/* Free rndis header buffer memory */
+		kfree(link->header);
+		link->header = NULL;
 		link->in_ep->desc = NULL;
 	}
 
diff --git a/drivers/usb/gadget/function/u_ether.h b/drivers/usb/gadget/function/u_ether.h
index 3ff09d1..a10503a 100644
--- a/drivers/usb/gadget/function/u_ether.h
+++ b/drivers/usb/gadget/function/u_ether.h
@@ -87,6 +87,7 @@
 	/* called on network open/close */
 	void				(*open)(struct gether *);
 	void				(*close)(struct gether *);
+	struct rndis_packet_msg_type	*header;
 };
 
 #define	DEFAULT_FILTER	(USB_CDC_PACKET_TYPE_BROADCAST \
diff --git a/drivers/video/fbdev/msm/Kconfig b/drivers/video/fbdev/msm/Kconfig
index e8f902b..a5e0662 100644
--- a/drivers/video/fbdev/msm/Kconfig
+++ b/drivers/video/fbdev/msm/Kconfig
@@ -82,6 +82,16 @@
 	MHL (Mobile High-Definition Link) technology
 	uses USB connector to output HDMI content
 
+config FB_MSM_MDSS_SPI_PANEL
+        depends on FB_MSM_MDSS
+        bool "Support SPI panel feature"
+        default n
+        ---help---
+        The MDSS SPI Panel provides support for transmittimg SPI signals of
+        MDSS frame buffer data to connected panel. Limited by SPI rate, the
+        current max fps only reach to 27 fps, and limited by MDP hardware
+        architecture only supply on MDP3
+
 config FB_MSM_MDSS_MHL3
 	depends on FB_MSM_MDSS_HDMI_PANEL
 	bool "MHL3 SII8620 Support"
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile
index 81d4953..26a940c 100644
--- a/drivers/video/fbdev/msm/Makefile
+++ b/drivers/video/fbdev/msm/Makefile
@@ -46,6 +46,11 @@
 obj-$(CONFIG_FB_MSM_MDSS) += mdss-dsi.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_panel.o
 
+ifeq ($(CONFIG_SPI_QUP), y)
+obj-$(CONFIG_FB_MSM_MDSS_SPI_PANEL) += mdss_spi_client.o
+obj-$(CONFIG_FB_MSM_MDSS_SPI_PANEL) += mdss_spi_panel.o
+endif
+
 ifneq ($(CONFIG_FB_MSM_MDSS_MDP3), y)
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_hdmi_util.o
 obj-$(CONFIG_FB_MSM_MDSS) += mdss_hdmi_edid.o
diff --git a/drivers/video/fbdev/msm/dsi_status_v2.c b/drivers/video/fbdev/msm/dsi_status_v2.c
index 35b0984..87720cf 100644
--- a/drivers/video/fbdev/msm/dsi_status_v2.c
+++ b/drivers/video/fbdev/msm/dsi_status_v2.c
@@ -18,6 +18,7 @@
 
 #include "mdss_dsi.h"
 #include "mdp3_ctrl.h"
+#include "mdss_spi_panel.h"
 
 /*
  * mdp3_check_te_status() - Check the status of panel for TE based ESD.
@@ -165,3 +166,79 @@
 	mdss_fb_report_panel_dead(pdsi_status->mfd);
 }
 
+#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL)
+void mdp3_check_spi_panel_status(struct work_struct *work, uint32_t interval)
+{
+	struct dsi_status_data *pdsi_status = NULL;
+	struct mdss_panel_data *pdata = NULL;
+	struct spi_panel_data *ctrl_pdata = NULL;
+	struct mdp3_session_data *mdp3_session = NULL;
+	int ret = 0;
+
+	pdsi_status = container_of(to_delayed_work(work),
+			struct dsi_status_data, check_status);
+
+	if (!pdsi_status || !(pdsi_status->mfd)) {
+		pr_err("%s: mfd not available\n", __func__);
+		return;
+	}
+
+	pdata = dev_get_platdata(&pdsi_status->mfd->pdev->dev);
+	if (!pdata) {
+		pr_err("%s: panel data not available\n", __func__);
+		return;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data, panel_data);
+	if (!ctrl_pdata || !ctrl_pdata->check_status) {
+		pr_err("%s: Dsi ctrl or status_check callback not available\n",
+				__func__);
+		return;
+	}
+
+	mdp3_session = pdsi_status->mfd->mdp.private1;
+	if (!mdp3_session) {
+		pr_err("%s: Display is off\n", __func__);
+		return;
+	}
+
+	if (mdp3_session->in_splash_screen) {
+		schedule_delayed_work(&pdsi_status->check_status,
+			msecs_to_jiffies(interval));
+		pr_debug("%s: cont splash is on\n", __func__);
+		return;
+	}
+
+	mutex_lock(&mdp3_session->lock);
+	if (!mdp3_session->status) {
+		pr_debug("%s: display off already\n", __func__);
+		mutex_unlock(&mdp3_session->lock);
+		return;
+	}
+
+	if (!ret)
+		ret = ctrl_pdata->check_status(ctrl_pdata);
+	else
+		pr_err("%s:wait_for_dma_done error\n", __func__);
+	mutex_unlock(&mdp3_session->lock);
+
+	if (mdss_fb_is_power_on_interactive(pdsi_status->mfd)) {
+		if (ret > 0) {
+			schedule_delayed_work(&pdsi_status->check_status,
+				msecs_to_jiffies(interval));
+		} else {
+			char *envp[2] = {"PANEL_ALIVE=0", NULL};
+
+			pdata->panel_info.panel_dead = true;
+			ret = kobject_uevent_env(
+			&pdsi_status->mfd->fbi->dev->kobj, KOBJ_CHANGE, envp);
+			pr_err("%s:panel has gone bad, sending uevent - %s\n",
+			 __func__, envp[0]);
+		}
+	}
+}
+#else
+void mdp3_check_spi_panel_status(struct work_struct *work, uint32_t interval)
+{
+}
+#endif
diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c
index c9db88e..54e9919 100644
--- a/drivers/video/fbdev/msm/mdp3.c
+++ b/drivers/video/fbdev/msm/mdp3.c
@@ -56,6 +56,7 @@
 #include "mdss_debug.h"
 #include "mdss_smmu.h"
 #include "mdss.h"
+#include "mdss_spi_panel.h"
 
 #ifndef EXPORT_COMPAT
 #define EXPORT_COMPAT(x)
@@ -109,6 +110,7 @@
 
 static struct mdss_panel_intf pan_types[] = {
 	{"dsi", MDSS_PANEL_INTF_DSI},
+	{"spi", MDSS_PANEL_INTF_SPI},
 };
 static char mdss_mdp3_panel[MDSS_MAX_PANEL_LEN];
 
@@ -127,6 +129,13 @@
 	},
 };
 
+#ifndef CONFIG_FB_MSM_MDSS_SPI_PANEL
+void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata, u32 bl_level)
+{
+
+}
+#endif
+
 static irqreturn_t mdp3_irq_handler(int irq, void *ptr)
 {
 	int i = 0;
@@ -1350,7 +1359,11 @@
 						client == MDP3_CLIENT_DMA_P)
 				mdss_smmu_unmap_dma_buf(data->tab_clone,
 					dom, dir, data->srcp_dma_buf);
-			else
+			else if (client == MDP3_CLIENT_SPI) {
+				ion_unmap_kernel(iclient, data->srcp_ihdl);
+				ion_free(iclient, data->srcp_ihdl);
+				data->srcp_ihdl = NULL;
+			} else
 				mdss_smmu_unmap_dma_buf(data->srcp_table,
 					dom, dir, data->srcp_dma_buf);
 			data->mapped = false;
@@ -1416,7 +1429,13 @@
 				data->srcp_dma_buf = NULL;
 				return ret;
 			}
-
+			data->srcp_ihdl = ion_import_dma_buf(iclient,
+				data->srcp_dma_buf);
+			if (IS_ERR_OR_NULL(data->srcp_ihdl)) {
+				pr_err("error on ion_import_fd\n");
+				data->srcp_ihdl = NULL;
+				return -EIO;
+			}
 			data->srcp_attachment =
 			mdss_smmu_dma_buf_attach(data->srcp_dma_buf,
 					&mdp3_res->pdev->dev, dom);
@@ -1449,6 +1468,25 @@
 					data->tab_clone, dom,
 					&data->addr, &data->len,
 					DMA_BIDIRECTIONAL);
+			} else if (client == MDP3_CLIENT_SPI) {
+				void *vaddr;
+
+					if (ion_handle_get_size(iclient,
+						data->srcp_ihdl,
+						(size_t *)&data->len) < 0) {
+						pr_err("get size failed\n");
+						return -EINVAL;
+					}
+					 vaddr = ion_map_kernel(iclient,
+						data->srcp_ihdl);
+					if (IS_ERR_OR_NULL(vaddr)) {
+						pr_err("Mapping failed\n");
+						mdp3_put_img(data, client);
+						return -EINVAL;
+					}
+					data->addr = (dma_addr_t) vaddr;
+					data->len -= img->offset;
+					return 0;
 			} else {
 				ret = mdss_smmu_map_dma_buf(data->srcp_dma_buf,
 					data->srcp_table, dom, &data->addr,
@@ -1741,6 +1779,8 @@
 	if (pdata->panel_info.type == MIPI_VIDEO_PANEL) {
 		status = MDP3_REG_READ(MDP3_REG_DSI_VIDEO_EN);
 		rc = status & 0x1;
+	} else if (pdata->panel_info.type == SPI_PANEL) {
+		rc = is_spi_panel_continuous_splash_on(pdata);
 	} else {
 		status = MDP3_REG_READ(MDP3_REG_DMA_P_CONFIG);
 		status &= 0x180000;
@@ -1777,7 +1817,11 @@
 	mdp3_clk_set_rate(MDP3_CLK_MDP_SRC, mdp_clk_rate,
 			MDP3_CLIENT_DMA_P);
 
-	rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
+	/*DMA not used on SPI interface, remove DMA bus voting*/
+	if (panel_info->type == SPI_PANEL)
+		rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0);
+	else
+		rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
 	bus_handle->restore_ab[MDP3_CLIENT_DMA_P] = ab;
 	bus_handle->restore_ib[MDP3_CLIENT_DMA_P] = ib;
 
@@ -1795,6 +1839,8 @@
 
 	if (panel_info->type == MIPI_VIDEO_PANEL)
 		mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_VIDEO].active = 1;
+	else if (panel_info->type == SPI_PANEL)
+		mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_SPI_CMD].active = 1;
 	else
 		mdp3_res->intf[MDP3_DMA_OUTPUT_SEL_DSI_CMD].active = 1;
 
@@ -2485,6 +2531,9 @@
 	mdp3_res->mdss_util->mdp_probe_done = true;
 	pr_debug("%s: END\n", __func__);
 
+	if (mdp3_res->pan_cfg.pan_intf == MDSS_PANEL_INTF_SPI)
+		mdp3_interface.check_dsi_status = mdp3_check_spi_panel_status;
+
 probe_done:
 	if (IS_ERR_VALUE(rc))
 		kfree(mdp3_res->mdp3_hw.irq_info);
diff --git a/drivers/video/fbdev/msm/mdp3.h b/drivers/video/fbdev/msm/mdp3.h
index 7132dee..6b56052 100644
--- a/drivers/video/fbdev/msm/mdp3.h
+++ b/drivers/video/fbdev/msm/mdp3.h
@@ -84,6 +84,7 @@
 	MDP3_CLIENT_DSI = 1,
 	MDP3_CLIENT_PPP,
 	MDP3_CLIENT_IOMMU,
+	MDP3_CLIENT_SPI,
 	MDP3_CLIENT_MAX,
 };
 
@@ -208,6 +209,8 @@
 	bool solid_fill_vote_en;
 	struct list_head reg_bus_clist;
 	struct mutex reg_bus_lock;
+	int bklt_level;
+	int bklt_update;
 	bool twm_en;
 	u32 max_bw;
 
@@ -267,6 +270,7 @@
 void mdp3_enable_regulator(int enable);
 void mdp3_check_dsi_ctrl_status(struct work_struct *work,
 				uint32_t interval);
+void mdp3_check_spi_panel_status(struct work_struct *work, uint32_t interval);
 int mdp3_dynamic_clock_gating_ctrl(int enable);
 int mdp3_footswitch_ctrl(int enable);
 int mdp3_qos_remapper_setup(struct mdss_panel_data *panel);
@@ -279,6 +283,8 @@
 void mdp3_clear_irq(u32 interrupt_mask);
 int mdp3_enable_panic_ctrl(void);
 
+void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata, u32 bl_level);
+
 int mdp3_layer_pre_commit(struct msm_fb_data_type *mfd,
 	struct file *file, struct mdp_layer_commit_v1 *commit);
 int mdp3_layer_atomic_validate(struct msm_fb_data_type *mfd,
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c
index 50b232a..c976c0e 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.c
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.c
@@ -23,11 +23,13 @@
 #include <linux/dma-buf.h>
 #include <linux/pm_runtime.h>
 #include <linux/iommu.h>
+#include <linux/msm_ion.h>
 
 #include "mdp3_ctrl.h"
 #include "mdp3.h"
 #include "mdp3_ppp.h"
 #include "mdss_smmu.h"
+#include "mdss_spi_panel.h"
 #include "mdss_sync.h"
 
 #define VSYNC_EXPIRE_TICK	4
@@ -72,7 +74,7 @@
 	bufq->pop_idx = 0;
 }
 
-void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq)
+void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client)
 {
 	int count = bufq->count;
 
@@ -83,7 +85,7 @@
 		struct mdp3_img_data *data = &bufq->img_data[bufq->pop_idx];
 
 		bufq->pop_idx = (bufq->pop_idx + 1) % MDP3_MAX_BUF_QUEUE;
-		mdp3_put_img(data, MDP3_CLIENT_DMA_P);
+		mdp3_put_img(data, client);
 	}
 	bufq->count = 0;
 	bufq->push_idx = 0;
@@ -122,6 +124,18 @@
 	return bufq->count;
 }
 
+int mdp3_get_ion_client(struct msm_fb_data_type *mfd)
+{
+	int intf_type;
+
+	intf_type = mdp3_ctrl_get_intf_type(mfd);
+
+	if (intf_type == MDP3_DMA_OUTPUT_SEL_SPI_CMD)
+		return MDP3_CLIENT_SPI;
+	else
+		return MDP3_CLIENT_DMA_P;
+}
+
 void mdp3_ctrl_notifier_register(struct mdp3_session_data *ses,
 	struct notifier_block *notifier)
 {
@@ -308,8 +322,11 @@
 	struct mdp3_notification vsync_client;
 	struct mdp3_notification *arg = NULL;
 	bool mod_vsync_timer = false;
+	int intf_type;
 
 	pr_debug("mdp3_ctrl_vsync_enable =%d\n", enable);
+
+	intf_type = mdp3_ctrl_get_intf_type(mfd);
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 	if (!mdp3_session || !mdp3_session->panel || !mdp3_session->dma ||
 		!mdp3_session->intf)
@@ -347,18 +364,25 @@
 		}
 	}
 
-	mdp3_clk_enable(1, 0);
-	mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
-	mdp3_clk_enable(0, 0);
+	if (intf_type == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
+		mdp3_spi_vsync_enable(mdp3_session->panel, arg);
+	} else {
+		mdp3_clk_enable(1, 0);
+		mdp3_session->dma->vsync_enable(mdp3_session->dma, arg);
+		mdp3_clk_enable(0, 0);
+	}
 
 	/*
 	 * Need to fake vsync whenever dsi interface is not
 	 * active or when dsi clocks are currently off
 	 */
-	if (mod_vsync_timer) {
+	if (mod_vsync_timer && (intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD)) {
 		mod_timer(&mdp3_session->vsync_timer,
 			jiffies + msecs_to_jiffies(mdp3_session->vsync_period));
-	} else if (!enable) {
+	} else if (enable && !mdp3_session->clk_on) {
+		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
+		mdp3_ctrl_clk_enable(mfd, 1);
+	} else if (!enable && (intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD)) {
 		del_timer(&mdp3_session->vsync_timer);
 	}
 
@@ -597,14 +621,32 @@
 static int mdp3_ctrl_res_req_bus(struct msm_fb_data_type *mfd, int status)
 {
 	int rc = 0;
+	u32 vtotal = 0;
+	int frame_rate = DEFAULT_FRAME_RATE;
 
 	if (status) {
+		struct mdss_panel_info *panel_info = mfd->panel_info;
 		u64 ab = 0;
 		u64 ib = 0;
 
+		frame_rate = mdss_panel_get_framerate(mfd->panel_info,
+			FPS_RESOLUTION_HZ);
 		mdp3_calc_dma_res(mfd->panel_info, NULL, &ab, &ib,
 			ppp_bpp(mfd->fb_imgType));
-		rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib);
+		vtotal = panel_info->yres + panel_info->lcdc.v_back_porch +
+			panel_info->lcdc.v_front_porch +
+			panel_info->lcdc.v_pulse_width;
+		ab = panel_info->xres * vtotal * ppp_bpp(mfd->fb_imgType);
+		ab *= frame_rate;
+		ib = ab;
+
+		/*DMA not used on SPI interface, remove DMA bus voting*/
+		if (mdp3_ctrl_get_intf_type(mfd) ==
+			 MDP3_DMA_OUTPUT_SEL_SPI_CMD)
+			rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0);
+		else
+			rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P,
+				ab, ib);
 	} else {
 		rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0);
 	}
@@ -653,6 +695,9 @@
 	case LCDC_PANEL:
 		type = MDP3_DMA_OUTPUT_SEL_LCDC;
 		break;
+	case SPI_PANEL:
+		type = MDP3_DMA_OUTPUT_SEL_SPI_CMD;
+		break;
 	default:
 		type = MDP3_DMA_OUTPUT_SEL_MAX;
 	}
@@ -717,7 +762,8 @@
 
 	cfg.type = mdp3_ctrl_get_intf_type(mfd);
 	if (cfg.type == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
-		cfg.type == MDP3_DMA_OUTPUT_SEL_LCDC) {
+		cfg.type == MDP3_DMA_OUTPUT_SEL_LCDC ||
+		cfg.type == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
 		video->hsync_period = hsync_period;
 		video->hsync_pulse_width = h_pulse_width;
 		video->vsync_period = vsync_period;
@@ -765,7 +811,7 @@
 	struct fb_var_screeninfo *var;
 	struct mdp3_dma_output_config outputConfig;
 	struct mdp3_dma_source sourceConfig;
-	int frame_rate = mfd->panel_info->mipi.frame_rate;
+	int frame_rate = DEFAULT_FRAME_RATE;
 	int vbp, vfp, vspw;
 	int vtotal, vporch;
 	struct mdp3_notification dma_done_callback;
@@ -774,6 +820,7 @@
 
 	mdp3_session = (struct mdp3_session_data *)mfd->mdp.private1;
 
+	frame_rate = mdss_panel_get_framerate(panel_info, FPS_RESOLUTION_HZ);
 	vbp = panel_info->lcdc.v_back_porch;
 	vfp = panel_info->lcdc.v_front_porch;
 	vspw = panel_info->lcdc.v_pulse_width;
@@ -814,7 +861,7 @@
 		sourceConfig.stride = fix->line_length;
 	}
 
-	te.frame_rate = panel_info->mipi.frame_rate;
+	te.frame_rate = frame_rate;
 	te.hw_vsync_mode = panel_info->mipi.hw_vsync_mode;
 	te.tear_check_en = panel_info->te.tear_check_en;
 	te.sync_cfg_height = panel_info->te.sync_cfg_height;
@@ -1003,6 +1050,7 @@
 static int mdp3_ctrl_off(struct msm_fb_data_type *mfd)
 {
 	int rc = 0;
+	int client = 0;
 	bool intf_stopped = true;
 	struct mdp3_session_data *mdp3_session;
 	struct mdss_panel_data *panel;
@@ -1156,10 +1204,11 @@
 				pr_err("%s: pm_runtime_put failed (rc %d)\n",
 					__func__, rc);
 		}
-		mdp3_bufq_deinit(&mdp3_session->bufq_out);
+		client = mdp3_get_ion_client(mfd);
+		mdp3_bufq_deinit(&mdp3_session->bufq_out, client);
 		if (mdp3_session->overlay.id != MSMFB_NEW_REQUEST) {
 			mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
-			mdp3_bufq_deinit(&mdp3_session->bufq_in);
+			mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
 		}
 	}
 
@@ -1189,6 +1238,10 @@
 		mdp3_ctrl_clk_enable(mdp3_session->mfd, 0);
 	}
 off_error:
+	if (mdp3_session->overlay.id != MSMFB_NEW_REQUEST) {
+		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
+		mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
+	}
 	MDSS_XLOG(XLOG_FUNC_EXIT, __LINE__);
 	mutex_unlock(&mdp3_session->lock);
 	/* Release the last reference to the runtime device */
@@ -1336,14 +1389,16 @@
 	struct fb_info *fbi = mfd->fbi;
 	struct fb_fix_screeninfo *fix;
 	int format;
+	int client;
 
 	fix = &fbi->fix;
 	format = mdp3_ctrl_get_source_format(mfd->fb_imgType);
 	mutex_lock(&mdp3_session->lock);
 
+	client = mdp3_get_ion_client(mfd);
 	if (mdp3_session->overlay.id == ndx && ndx == 1) {
 		mdp3_session->overlay.id = MSMFB_NEW_REQUEST;
-		mdp3_bufq_deinit(&mdp3_session->bufq_in);
+		mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
 	} else {
 		rc = -EINVAL;
 	}
@@ -1362,18 +1417,20 @@
 	struct msmfb_data *img = &req->data;
 	struct mdp3_img_data data;
 	struct mdp3_dma *dma = mdp3_session->dma;
+	int client;
 
+	client = mdp3_get_ion_client(mfd);
 	memset(&data, 0, sizeof(struct mdp3_img_data));
-	if (mfd->panel.type == MIPI_CMD_PANEL)
+	if (mfd->panel.type == MIPI_CMD_PANEL || client == MDP3_CLIENT_SPI)
 		is_panel_type_cmd = true;
 	if (is_panel_type_cmd) {
-		rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+		rc = mdp3_iommu_enable(client);
 		if (rc) {
 			pr_err("fail to enable iommu\n");
 			return rc;
 		}
 	}
-	rc = mdp3_get_img(img, &data, MDP3_CLIENT_DMA_P);
+	rc = mdp3_get_img(img, &data, client);
 	if (rc) {
 		pr_err("fail to get overlay buffer\n");
 		goto err;
@@ -1383,14 +1440,14 @@
 		pr_err("buf size(0x%lx) is smaller than dma config(0x%x)\n",
 			data.len, (dma->source_config.stride *
 			dma->source_config.height));
-		mdp3_put_img(&data, MDP3_CLIENT_DMA_P);
+		mdp3_put_img(&data, client);
 		rc = -EINVAL;
 		goto err;
 	}
 	rc = mdp3_bufq_push(&mdp3_session->bufq_in, &data);
 	if (rc) {
 		pr_err("fail to queue the overlay buffer, buffer drop\n");
-		mdp3_put_img(&data, MDP3_CLIENT_DMA_P);
+		mdp3_put_img(&data, client);
 		goto err;
 	}
 	rc = 0;
@@ -1449,8 +1506,11 @@
 	struct mdp3_img_data *data;
 	struct mdss_panel_info *panel_info;
 	int rc = 0;
+	int client;
 	static bool splash_done;
 	struct mdss_panel_data *panel;
+	int frame_rate = DEFAULT_FRAME_RATE;
+	int stride;
 
 	if (!mfd || !mfd->mdp.private1)
 		return -EINVAL;
@@ -1460,6 +1520,9 @@
 	if (!mdp3_session || !mdp3_session->dma)
 		return -EINVAL;
 
+	frame_rate = mdss_panel_get_framerate(panel_info, FPS_RESOLUTION_HZ);
+	client = mdp3_get_ion_client(mfd);
+
 	if (mdp3_bufq_count(&mdp3_session->bufq_in) == 0) {
 		pr_debug("no buffer in queue yet\n");
 		return -EPERM;
@@ -1510,7 +1573,17 @@
 	if (data) {
 		mdp3_ctrl_reset_countdown(mdp3_session, mfd);
 		mdp3_ctrl_clk_enable(mfd, 1);
-		if (mdp3_session->dma->update_src_cfg &&
+		stride = mdp3_session->dma->source_config.stride;
+		if (mdp3_ctrl_get_intf_type(mfd) ==
+			MDP3_DMA_OUTPUT_SEL_SPI_CMD){
+			mdp3_session->intf->active = false;
+			msm_ion_do_cache_op(mdp3_res->ion_client,
+				data->srcp_ihdl, (void *)(int)data->addr,
+					data->len, ION_IOC_INV_CACHES);
+			rc = mdss_spi_panel_kickoff(mdp3_session->panel,
+				(void *)(int)data->addr, (int)data->len,
+					stride);
+		} else if (mdp3_session->dma->update_src_cfg &&
 				panel_info->partial_update_enabled) {
 			panel->panel_info.roi.x = mdp3_session->dma->roi.x;
 			panel->panel_info.roi.y = mdp3_session->dma->roi.y;
@@ -1530,7 +1603,9 @@
 				MDP_NOTIFY_FRAME_TIMEOUT);
 		} else {
 			if (mdp3_ctrl_get_intf_type(mfd) ==
-						MDP3_DMA_OUTPUT_SEL_DSI_VIDEO) {
+				MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+				mdp3_ctrl_get_intf_type(mfd) ==
+					MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
 				mdp3_ctrl_notify(mdp3_session,
 					MDP_NOTIFY_FRAME_DONE);
 			}
@@ -1545,16 +1620,16 @@
 		mdp3_release_splash_memory(mfd);
 		data = mdp3_bufq_pop(&mdp3_session->bufq_out);
 		if (data)
-			mdp3_put_img(data, MDP3_CLIENT_DMA_P);
+			mdp3_put_img(data, client);
 	}
 
 	if (mdp3_session->first_commit) {
 		/*wait to ensure frame is sent to panel*/
 		if (panel_info->mipi.post_init_delay)
-			msleep(((1000 / panel_info->mipi.frame_rate) + 1) *
+			msleep(((1000 / frame_rate) + 1) *
 					panel_info->mipi.post_init_delay);
 		else
-			msleep(1000 / panel_info->mipi.frame_rate);
+			msleep((1000 / frame_rate) + 1);
 		mdp3_session->first_commit = false;
 		if (panel)
 			rc |= panel->event_handler(panel,
@@ -1569,6 +1644,12 @@
 		mdp3_session->esd_recovery = false;
 	}
 
+	/*Update backlight only if its changed*/
+	if (mdp3_res->bklt_level && mdp3_res->bklt_update) {
+		mdss_spi_panel_bl_ctrl_update(panel, mdp3_res->bklt_level);
+		mdp3_res->bklt_update = false;
+	}
+
 	/* start vsync tick countdown for cmd mode if vsync isn't enabled */
 	if (mfd->panel.type == MIPI_CMD_PANEL && !mdp3_session->vsync_enabled)
 		mdp3_ctrl_vsync_enable(mdp3_session->mfd, 0);
@@ -1695,17 +1776,18 @@
 	}
 
 	panel = mdp3_session->panel;
-	if (mdp3_session->first_commit) {
-		/*wait to ensure frame is sent to panel*/
-		if (panel_info->mipi.post_init_delay)
-			msleep(((1000 / panel_info->mipi.frame_rate) + 1) *
-					panel_info->mipi.post_init_delay);
-		else
-			msleep(1000 / panel_info->mipi.frame_rate);
-		mdp3_session->first_commit = false;
-		if (panel)
-			panel->event_handler(panel, MDSS_EVENT_POST_PANEL_ON,
-					NULL);
+	if (mdp3_ctrl_get_intf_type(mfd) != MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
+		if (mdp3_session->first_commit) {
+			if (panel_info->mipi.init_delay)
+				msleep(((1000 / panel_info->mipi.frame_rate)
+				+ 1) * panel_info->mipi.post_init_delay);
+			else
+				msleep(1000 / panel_info->mipi.frame_rate);
+					mdp3_session->first_commit = false;
+			if (panel)
+				panel->event_handler(panel,
+					MDSS_EVENT_POST_PANEL_ON, NULL);
+		}
 	}
 
 	mdp3_session->vsync_before_commit = 0;
@@ -1716,6 +1798,11 @@
 		mdp3_session->esd_recovery = false;
 	}
 
+	/*Update backlight only if its changed*/
+	if (mdp3_res->bklt_level && mdp3_res->bklt_update) {
+		mdss_spi_panel_bl_ctrl_update(panel, mdp3_res->bklt_level);
+		mdp3_res->bklt_update = false;
+	}
 
 pan_error:
 	mutex_unlock(&mdp3_session->lock);
@@ -1756,7 +1843,8 @@
 	switch (metadata->op) {
 	case metadata_op_frame_rate:
 		metadata->data.panel_frame_rate =
-			mfd->panel_info->mipi.frame_rate;
+			 mdss_panel_get_framerate(mfd->panel_info,
+				FPS_RESOLUTION_HZ);
 		break;
 	case metadata_op_get_caps:
 		metadata->data.caps.mdp_rev = 305;
@@ -2893,6 +2981,7 @@
 	struct msm_mdp_interface *mdp3_interface = &mfd->mdp;
 	struct mdp3_session_data *mdp3_session = NULL;
 	u32 intf_type = MDP3_DMA_OUTPUT_SEL_DSI_VIDEO;
+	int frame_rate = DEFAULT_FRAME_RATE;
 	int rc;
 	int splash_mismatch = 0;
 	struct sched_param sched = { .sched_priority = 16 };
@@ -2902,6 +2991,8 @@
 	if (rc)
 		splash_mismatch = 1;
 
+	frame_rate = mdss_panel_get_framerate(mfd->panel_info,
+		FPS_RESOLUTION_HZ);
 	mdp3_interface->on_fnc = mdp3_ctrl_on;
 	mdp3_interface->off_fnc = mdp3_ctrl_off;
 	mdp3_interface->do_histogram = NULL;
@@ -2980,10 +3071,11 @@
 	init_timer(&mdp3_session->vsync_timer);
 	mdp3_session->vsync_timer.function = mdp3_vsync_timer_func;
 	mdp3_session->vsync_timer.data = (u32)mdp3_session;
-	mdp3_session->vsync_period = 1000 / mfd->panel_info->mipi.frame_rate;
+	mdp3_session->vsync_period = 1000 / frame_rate;
 	mfd->mdp.private1 = mdp3_session;
 	init_completion(&mdp3_session->dma_completion);
-	if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO)
+	if (intf_type != MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
+		intf_type != MDP3_DMA_OUTPUT_SEL_SPI_CMD)
 		mdp3_session->wait_for_dma_done = mdp3_wait_for_dma_done;
 
 	rc = sysfs_create_group(&dev->kobj, &vsync_fs_attr_group);
diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.h b/drivers/video/fbdev/msm/mdp3_ctrl.h
index b7b667b..5193af1 100644
--- a/drivers/video/fbdev/msm/mdp3_ctrl.h
+++ b/drivers/video/fbdev/msm/mdp3_ctrl.h
@@ -84,12 +84,13 @@
 	struct work_struct retire_work;
 };
 
-void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq);
+void mdp3_bufq_deinit(struct mdp3_buffer_queue *bufq, int client);
 int mdp3_ctrl_init(struct msm_fb_data_type *mfd);
 int mdp3_bufq_push(struct mdp3_buffer_queue *bufq,
 			struct mdp3_img_data *data);
 int mdp3_ctrl_get_source_format(u32 imgType);
 int mdp3_ctrl_get_pack_pattern(u32 imgType);
 int mdp3_ctrl_reset(struct msm_fb_data_type *mfd);
+int mdp3_get_ion_client(struct msm_fb_data_type *mfd);
 
 #endif /* MDP3_CTRL_H */
diff --git a/drivers/video/fbdev/msm/mdp3_dma.c b/drivers/video/fbdev/msm/mdp3_dma.c
index 71fcbf9..b223c87 100644
--- a/drivers/video/fbdev/msm/mdp3_dma.c
+++ b/drivers/video/fbdev/msm/mdp3_dma.c
@@ -114,7 +114,8 @@
 	}
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
-		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC ||
+		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
 		if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
 			mdp3_irq_enable(MDP3_INTR_LCDC_START_OF_FRAME);
 	} else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
@@ -150,7 +151,8 @@
 	}
 
 	if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_VIDEO ||
-		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC) {
+		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_LCDC ||
+		dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_SPI_CMD) {
 		if (type & MDP3_DMA_CALLBACK_TYPE_VSYNC)
 			mdp3_irq_disable(MDP3_INTR_LCDC_START_OF_FRAME);
 	} else if (dma->output_config.out_sel == MDP3_DMA_OUTPUT_SEL_DSI_CMD) {
@@ -1268,6 +1270,22 @@
 	return 0;
 }
 
+static int spi_cmd_config(struct mdp3_intf *intf, struct mdp3_intf_cfg *cfg)
+{
+	return 0;
+}
+
+static int spi_cmd_start(struct mdp3_intf *intf)
+{
+	intf->active = true;
+	return 0;
+}
+
+static int spi_cmd_stop(struct mdp3_intf *intf)
+{
+	intf->active = false;
+	return 0;
+}
 int mdp3_intf_init(struct mdp3_intf *intf)
 {
 	switch (intf->cfg.type) {
@@ -1286,6 +1304,11 @@
 		intf->start = dsi_cmd_start;
 		intf->stop = dsi_cmd_stop;
 		break;
+	case MDP3_DMA_OUTPUT_SEL_SPI_CMD:
+		intf->config = spi_cmd_config;
+		intf->start = spi_cmd_start;
+		intf->stop = spi_cmd_stop;
+		break;
 
 	default:
 		return -EINVAL;
diff --git a/drivers/video/fbdev/msm/mdp3_dma.h b/drivers/video/fbdev/msm/mdp3_dma.h
index 24caedb9..ec327b6 100644
--- a/drivers/video/fbdev/msm/mdp3_dma.h
+++ b/drivers/video/fbdev/msm/mdp3_dma.h
@@ -47,6 +47,7 @@
 	MDP3_DMA_OUTPUT_SEL_DSI_CMD,
 	MDP3_DMA_OUTPUT_SEL_LCDC,
 	MDP3_DMA_OUTPUT_SEL_DSI_VIDEO,
+	MDP3_DMA_OUTPUT_SEL_SPI_CMD,
 	MDP3_DMA_OUTPUT_SEL_MAX
 };
 
diff --git a/drivers/video/fbdev/msm/mdp3_layer.c b/drivers/video/fbdev/msm/mdp3_layer.c
index 0078466..98b5c19 100644
--- a/drivers/video/fbdev/msm/mdp3_layer.c
+++ b/drivers/video/fbdev/msm/mdp3_layer.c
@@ -197,6 +197,7 @@
 	struct msmfb_data img;
 	bool is_panel_type_cmd = false;
 	struct mdp3_img_data data;
+	int intf_type;
 	int rc = 0;
 
 	layer = &input_layer[0];
@@ -208,23 +209,24 @@
 		goto err;
 	}
 
+	intf_type = mdp3_get_ion_client(mfd);
 	memset(&img, 0, sizeof(img));
 	img.memory_id = buffer->planes[0].fd;
 	img.offset = buffer->planes[0].offset;
 
 	memset(&data, 0, sizeof(struct mdp3_img_data));
 
-	if (mfd->panel.type == MIPI_CMD_PANEL)
+	if (mfd->panel.type == MIPI_CMD_PANEL || intf_type == MDP3_CLIENT_SPI)
 		is_panel_type_cmd = true;
 	if (is_panel_type_cmd) {
-		rc = mdp3_iommu_enable(MDP3_CLIENT_DMA_P);
+		rc = mdp3_iommu_enable(intf_type);
 		if (rc) {
 			pr_err("fail to enable iommu\n");
 			return rc;
 		}
 	}
 
-	rc = mdp3_get_img(&img, &data, MDP3_CLIENT_DMA_P);
+	rc = mdp3_get_img(&img, &data, intf_type);
 	if (rc) {
 		pr_err("fail to get overlay buffer\n");
 		goto err;
@@ -260,7 +262,7 @@
 	struct mdp3_session_data *mdp3_session;
 	struct mdp3_dma *dma;
 	int layer_count = commit->input_layer_cnt;
-	int stride, format;
+	int stride, format, client;
 
 	/* Handle NULL commit */
 	if (!layer_count) {
@@ -273,7 +275,8 @@
 
 	mutex_lock(&mdp3_session->lock);
 
-	mdp3_bufq_deinit(&mdp3_session->bufq_in);
+	client = mdp3_get_ion_client(mfd);
+	mdp3_bufq_deinit(&mdp3_session->bufq_in, client);
 
 	layer_list = commit->input_layers;
 	layer = &layer_list[0];
diff --git a/drivers/video/fbdev/msm/mdp3_ppp.c b/drivers/video/fbdev/msm/mdp3_ppp.c
index 3391059..5459510 100644
--- a/drivers/video/fbdev/msm/mdp3_ppp.c
+++ b/drivers/video/fbdev/msm/mdp3_ppp.c
@@ -542,6 +542,7 @@
 {
 	struct mdss_panel_info *panel_info = mfd->panel_info;
 	int i, lcount = 0;
+	int frame_rate = DEFAULT_FRAME_RATE;
 	struct mdp_blit_req *req;
 	struct bpp_info bpp;
 	u64 old_solid_fill_pixel = 0;
@@ -556,6 +557,7 @@
 
 	ATRACE_BEGIN(__func__);
 	lcount = lreq->count;
+	frame_rate = mdss_panel_get_framerate(panel_info, FPS_RESOLUTION_HZ);
 	if (lcount == 0) {
 		pr_err("Blit with request count 0, continue to recover!!!\n");
 		ATRACE_END(__func__);
@@ -583,11 +585,11 @@
 		is_blit_optimization_possible(lreq, i);
 		req = &(lreq->req_list[i]);
 
-		if (req->fps > 0 && req->fps <= panel_info->mipi.frame_rate) {
+		if (req->fps > 0 && req->fps <= frame_rate) {
 			if (fps == 0)
 				fps = req->fps;
 			else
-				fps = panel_info->mipi.frame_rate;
+				fps = frame_rate;
 		}
 
 		mdp3_get_bpp_info(req->src.format, &bpp);
@@ -645,7 +647,7 @@
 	}
 
 	if (fps == 0)
-		fps = panel_info->mipi.frame_rate;
+		fps = frame_rate;
 
 	if (lreq->req_list[0].flags & MDP_SOLID_FILL) {
 		honest_ppp_ab = ppp_res.solid_fill_byte * 4;
diff --git a/drivers/video/fbdev/msm/mdp3_ppp_data.c b/drivers/video/fbdev/msm/mdp3_ppp_data.c
index ac88d9b..dd2cce0 100644
--- a/drivers/video/fbdev/msm/mdp3_ppp_data.c
+++ b/drivers/video/fbdev/msm/mdp3_ppp_data.c
@@ -89,8 +89,8 @@
 };
 
 const uint32_t swapped_pack_patt_lut[MDP_IMGTYPE_LIMIT] = {
-	[MDP_RGB_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
-	[MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
+	[MDP_RGB_565] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
+	[MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
 	[MDP_RGB_888] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8),
 	[MDP_BGR_888] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8),
 	[MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R,
diff --git a/drivers/video/fbdev/msm/mdss_dsi.c b/drivers/video/fbdev/msm/mdss_dsi.c
index 816eed0..b4e4bdd 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.c
+++ b/drivers/video/fbdev/msm/mdss_dsi.c
@@ -383,6 +383,14 @@
 		ret = 0;
 	}
 
+	if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio)) {
+		ret = gpio_direction_output(
+			ctrl_pdata->vdd_ext_gpio, 0);
+		if (ret)
+			pr_err("%s: unable to set dir for vdd gpio\n",
+					__func__);
+	}
+
 	if (mdss_dsi_pinctrl_set_state(ctrl_pdata, false))
 		pr_debug("reset disable: pinctrl not enabled\n");
 
@@ -410,6 +418,15 @@
 	ctrl_pdata = container_of(pdata, struct mdss_dsi_ctrl_pdata,
 				panel_data);
 
+	if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio)) {
+		ret = gpio_direction_output(
+				ctrl_pdata->vdd_ext_gpio, 1);
+		usleep_range(3000, 4000); /* h/w recommended delay */
+		if (ret)
+			pr_err("%s: unable to set dir for vdd gpio\n",
+					__func__);
+	}
+
 	ret = msm_mdss_enable_vreg(
 		ctrl_pdata->panel_power_data.vreg_config,
 		ctrl_pdata->panel_power_data.num_vreg, 1);
@@ -3263,6 +3280,7 @@
 	struct mdss_util_intf *util;
 	static int te_irq_registered;
 	struct mdss_panel_data *pdata;
+	struct mdss_panel_cfg *pan_cfg = NULL;
 
 	if (!pdev || !pdev->dev.of_node) {
 		pr_err("%s: pdev not found for DSI controller\n", __func__);
@@ -3295,6 +3313,14 @@
 		return -ENODEV;
 	}
 
+	pan_cfg = util->panel_intf_type(MDSS_PANEL_INTF_SPI);
+	if (IS_ERR(pan_cfg)) {
+		return PTR_ERR(pan_cfg);
+	} else if (pan_cfg) {
+		pr_debug("%s: SPI is primary\n", __func__);
+		return -ENODEV;
+	}
+
 	ctrl_pdata->mdss_util = util;
 	atomic_set(&ctrl_pdata->te_irq_ready, 0);
 
@@ -4183,6 +4209,11 @@
 			of_property_read_bool(ctrl_pdev->dev.of_node,
 				"qcom,platform-bklight-en-gpio-invert");
 
+	ctrl_pdata->vdd_ext_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+		"qcom,ext-vdd-gpio", 0);
+	if (!gpio_is_valid(ctrl_pdata->vdd_ext_gpio))
+		pr_info("%s: ext vdd gpio not specified\n", __func__);
+
 	ctrl_pdata->rst_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
 			 "qcom,platform-reset-gpio", 0);
 	if (!gpio_is_valid(ctrl_pdata->rst_gpio))
diff --git a/drivers/video/fbdev/msm/mdss_dsi.h b/drivers/video/fbdev/msm/mdss_dsi.h
index 2ff2951..5d2d677 100644
--- a/drivers/video/fbdev/msm/mdss_dsi.h
+++ b/drivers/video/fbdev/msm/mdss_dsi.h
@@ -435,6 +435,7 @@
 	int rst_gpio;
 	int disp_en_gpio;
 	int bklt_en_gpio;
+	int vdd_ext_gpio;
 	int mode_gpio;
 	int intf_mux_gpio;
 	bool bklt_en_gpio_invert;
diff --git a/drivers/video/fbdev/msm/mdss_dsi_panel.c b/drivers/video/fbdev/msm/mdss_dsi_panel.c
index 85ed42e..b94280d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_panel.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_panel.c
@@ -326,6 +326,15 @@
 			goto bklt_en_gpio_err;
 		}
 	}
+	if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio)) {
+		rc = gpio_request(ctrl_pdata->vdd_ext_gpio,
+						"vdd_enable");
+		if (rc) {
+			pr_err("request vdd enable gpio failed, rc=%d\n",
+				rc);
+			goto vdd_en_gpio_err;
+		}
+	}
 	if (gpio_is_valid(ctrl_pdata->mode_gpio)) {
 		rc = gpio_request(ctrl_pdata->mode_gpio, "panel_mode");
 		if (rc) {
@@ -337,6 +346,9 @@
 	return rc;
 
 mode_gpio_err:
+	if (gpio_is_valid(ctrl_pdata->vdd_ext_gpio))
+		gpio_free(ctrl_pdata->vdd_ext_gpio);
+vdd_en_gpio_err:
 	if (gpio_is_valid(ctrl_pdata->bklt_en_gpio))
 		gpio_free(ctrl_pdata->bklt_en_gpio);
 bklt_en_gpio_err:
diff --git a/drivers/video/fbdev/msm/mdss_dsi_status.c b/drivers/video/fbdev/msm/mdss_dsi_status.c
index c5af962..326768d 100644
--- a/drivers/video/fbdev/msm/mdss_dsi_status.c
+++ b/drivers/video/fbdev/msm/mdss_dsi_status.c
@@ -146,15 +146,18 @@
 		return NOTIFY_DONE;
 
 	mfd = evdata->info->par;
-	ctrl_pdata = container_of(dev_get_platdata(&mfd->pdev->dev),
+	if (mfd->panel_info->type == SPI_PANEL) {
+		pinfo = mfd->panel_info;
+	} else {
+		ctrl_pdata = container_of(dev_get_platdata(&mfd->pdev->dev),
 				struct mdss_dsi_ctrl_pdata, panel_data);
-	if (!ctrl_pdata) {
-		pr_err("%s: DSI ctrl not available\n", __func__);
-		return NOTIFY_BAD;
+		if (!ctrl_pdata) {
+			pr_err("%s: DSI ctrl not available\n", __func__);
+			return NOTIFY_BAD;
+		}
+
+		pinfo = &ctrl_pdata->panel_data.panel_info;
 	}
-
-	pinfo = &ctrl_pdata->panel_data.panel_info;
-
 	if ((!(pinfo->esd_check_enabled) &&
 			dsi_status_disable) ||
 			(dsi_status_disable == DSI_STATUS_CHECK_DISABLE)) {
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 72f651e..edeecb4 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -345,6 +345,9 @@
 	case EDP_PANEL:
 		ret = snprintf(buf, PAGE_SIZE, "edp panel\n");
 		break;
+	case SPI_PANEL:
+		ret = snprintf(buf, PAGE_SIZE, "spi panel\n");
+		break;
 	default:
 		ret = snprintf(buf, PAGE_SIZE, "unknown panel\n");
 		break;
@@ -1214,6 +1217,7 @@
 	struct mdss_panel_data *pdata;
 	struct fb_info *fbi;
 	int rc;
+	const char *data;
 
 	if (fbi_list_index >= MAX_FBI_LIST)
 		return -ENOMEM;
@@ -1262,6 +1266,21 @@
 
 	mfd->pdev = pdev;
 
+	if (mfd->panel.type == SPI_PANEL)
+		mfd->fb_imgType = MDP_RGB_565;
+	if (mfd->panel.type == MIPI_VIDEO_PANEL || mfd->panel.type ==
+		MIPI_CMD_PANEL || mfd->panel.type == SPI_PANEL){
+		rc = of_property_read_string(pdev->dev.of_node,
+			"qcom,mdss-fb-format", &data);
+		if (!rc) {
+			if (!strcmp(data, "rgb888"))
+				mfd->fb_imgType = MDP_RGB_888;
+			else if (!strcmp(data, "rgb565"))
+				mfd->fb_imgType = MDP_RGB_565;
+			else
+				mfd->fb_imgType = MDP_RGBA_8888;
+			}
+		}
 	mfd->split_fb_left = mfd->split_fb_right = 0;
 
 	mdss_fb_set_split_mode(mfd, pdata);
@@ -1374,6 +1393,7 @@
 		mfd->mdp_sync_pt_data.threshold = 1;
 		mfd->mdp_sync_pt_data.retire_threshold = 0;
 		break;
+	case SPI_PANEL:
 	case MIPI_CMD_PANEL:
 		mfd->mdp_sync_pt_data.threshold = 1;
 		mfd->mdp_sync_pt_data.retire_threshold = 1;
diff --git a/drivers/video/fbdev/msm/mdss_panel.h b/drivers/video/fbdev/msm/mdss_panel.h
index aa90d5f..314dc0e 100644
--- a/drivers/video/fbdev/msm/mdss_panel.h
+++ b/drivers/video/fbdev/msm/mdss_panel.h
@@ -60,6 +60,7 @@
 #define WRITEBACK_PANEL		10	/* Wifi display */
 #define LVDS_PANEL		11	/* LVDS */
 #define EDP_PANEL		12	/* LVDS */
+#define SPI_PANEL		13
 
 #define DSC_PPS_LEN		128
 
@@ -108,6 +109,7 @@
 	MDSS_PANEL_INTF_DSI,
 	MDSS_PANEL_INTF_EDP,
 	MDSS_PANEL_INTF_HDMI,
+	MDSS_PANEL_INTF_SPI,
 };
 
 enum {
@@ -118,6 +120,12 @@
 };
 
 enum {
+	MDSS_PANEL_BLANK_BLANK = 0,
+	MDSS_PANEL_BLANK_UNBLANK,
+	MDSS_PANEL_BLANK_LOW_POWER,
+};
+
+enum {
 	MDSS_PANEL_LOW_PERSIST_MODE_OFF = 0,
 	MDSS_PANEL_LOW_PERSIST_MODE_ON,
 };
@@ -430,6 +438,10 @@
 	char frame_rate;	/* fps */
 };
 
+struct spi_panel_info {
+	char frame_rate;
+};
+
 /**
  * struct dynamic_fps_data - defines dynamic fps related data
  * @hfp: horizontal front porch
@@ -677,6 +689,7 @@
 	u32 partial_update_roi_merge;
 	struct ion_handle *splash_ihdl;
 	int panel_power_state;
+	int blank_state;
 	int compression_mode;
 
 	uint32_t panel_dead;
@@ -736,6 +749,7 @@
 	struct lcd_panel_info lcdc;
 	struct fbc_panel_info fbc;
 	struct mipi_panel_info mipi;
+	struct spi_panel_info spi;
 	struct lvds_panel_info lvds;
 	struct edp_panel_info edp;
 
@@ -875,6 +889,9 @@
 			frame_rate = panel_info->lcdc.frame_rate;
 			break;
 		}
+	case SPI_PANEL:
+		frame_rate = panel_info->spi.frame_rate;
+		break;
 	default:
 		pixel_total = (panel_info->lcdc.h_back_porch +
 			  panel_info->lcdc.h_front_porch +
diff --git a/drivers/video/fbdev/msm/mdss_spi_client.c b/drivers/video/fbdev/msm/mdss_spi_client.c
new file mode 100644
index 0000000..541e382
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_client.c
@@ -0,0 +1,198 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/spi/spi.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/qpnp/pin.h>
+#include <linux/delay.h>
+
+#include "mdss_spi_client.h"
+
+#define MAX_READ_SPEED_HZ	9600000
+#define SPI_PANEL_COMMAND_LEN	1
+static struct spi_device *mdss_spi_client;
+
+int mdss_spi_read_data(u8 reg_addr, u8 *data, u8 len)
+{
+	int rc = 0;
+	u32 max_speed_hz;
+	u8 memory_write_reg = 0x2c;
+	u8 empty_pack[] = {0x29, 0x29, 0x29};
+	struct spi_transfer t[4] = {
+		[0] = {
+			.tx_buf = &reg_addr,
+			.len = 1,
+		},
+		[1] = {
+			.rx_buf = data,
+			.len = len,
+		},
+		[2] = {
+			.tx_buf = &empty_pack,
+			.len = 3,
+		},
+		[3] = {
+			.tx_buf = &memory_write_reg,
+			.len = 1,
+		}
+	};
+	struct spi_message m;
+
+	if (!mdss_spi_client) {
+		pr_err("%s: spi client not available\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_spi_client->bits_per_word = 8;
+	max_speed_hz = mdss_spi_client->max_speed_hz;
+	mdss_spi_client->max_speed_hz = MAX_READ_SPEED_HZ;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t[0], &m);
+	spi_message_add_tail(&t[1], &m);
+	rc = spi_sync(mdss_spi_client, &m);
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t[2], &m);
+	rc = spi_sync(mdss_spi_client, &m);
+	spi_message_init(&m);
+	spi_message_add_tail(&t[3], &m);
+	rc = spi_sync(mdss_spi_client, &m);
+	mdss_spi_client->max_speed_hz = max_speed_hz;
+
+	return rc;
+}
+
+int mdss_spi_tx_command(const void *buf)
+{
+	int rc = 0;
+	struct spi_transfer t = {
+		.tx_buf = buf,
+		.len    = SPI_PANEL_COMMAND_LEN,
+	};
+	struct spi_message m;
+
+	if (!mdss_spi_client) {
+		pr_err("%s: spi client not available\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_spi_client->bits_per_word = 8;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+	rc = spi_sync(mdss_spi_client, &m);
+
+	return rc;
+}
+
+int mdss_spi_tx_parameter(const void *buf, size_t len)
+{
+	int rc = 0;
+	struct spi_transfer t = {
+		.tx_buf = buf,
+		.len    = len,
+	};
+	struct spi_message m;
+
+	if (!mdss_spi_client) {
+		pr_err("%s: spi client not available\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_spi_client->bits_per_word = 8;
+
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+	rc = spi_sync(mdss_spi_client, &m);
+
+	return rc;
+}
+
+int mdss_spi_tx_pixel(const void *buf, size_t len)
+{
+	int rc = 0;
+	struct spi_transfer t = {
+		.tx_buf = buf,
+		.len    = len,
+		};
+	struct spi_message m;
+
+	if (!mdss_spi_client) {
+		pr_err("%s: spi client not available\n", __func__);
+		return -EINVAL;
+	}
+
+	mdss_spi_client->bits_per_word = 16;
+	spi_message_init(&m);
+	spi_message_add_tail(&t, &m);
+	rc = spi_sync(mdss_spi_client, &m);
+
+	return rc;
+}
+
+static int mdss_spi_client_probe(struct spi_device *spidev)
+{
+	int irq;
+	int cs;
+	int cpha, cpol, cs_high;
+	u32 max_speed;
+	struct device_node *np;
+
+	irq = spidev->irq;
+	cs = spidev->chip_select;
+	cpha = (spidev->mode & SPI_CPHA) ? 1:0;
+	cpol = (spidev->mode & SPI_CPOL) ? 1:0;
+	cs_high = (spidev->mode & SPI_CS_HIGH) ? 1:0;
+	max_speed = spidev->max_speed_hz;
+	np = spidev->dev.of_node;
+	pr_debug("cs[%x] CPHA[%x] CPOL[%x] CS_HIGH[%x] Max_speed[%d]\n",
+		cs, cpha, cpol, cs_high, max_speed);
+	mdss_spi_client = spidev;
+
+	return 0;
+}
+
+
+static const struct of_device_id mdss_spi_dt_match[] = {
+	{ .compatible = "qcom,mdss-spi-client" },
+	{},
+};
+
+static struct spi_driver mdss_spi_client_driver = {
+	.probe = mdss_spi_client_probe,
+	.driver = {
+		.name = "mdss-spi-client",
+		.owner  = THIS_MODULE,
+		.of_match_table = mdss_spi_dt_match,
+	},
+};
+
+static int __init mdss_spi_init(void)
+{
+	int ret;
+
+	ret = spi_register_driver(&mdss_spi_client_driver);
+
+	return 0;
+}
+module_init(mdss_spi_init);
+
+static void __exit mdss_spi_exit(void)
+{
+	spi_unregister_driver(&mdss_spi_client_driver);
+}
+module_exit(mdss_spi_exit);
+
diff --git a/drivers/video/fbdev/msm/mdss_spi_client.h b/drivers/video/fbdev/msm/mdss_spi_client.h
new file mode 100644
index 0000000..2d15625
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_client.h
@@ -0,0 +1,20 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MDSS_SPI_CLINET_H__
+#define __MDSS_SPI_CLINET_H__
+
+int mdss_spi_tx_command(const void *buf);
+int mdss_spi_tx_parameter(const void *buf, size_t len);
+int mdss_spi_tx_pixel(const void *buf, size_t len);
+int mdss_spi_read_data(u8 reg_addr, u8 *data, u8 len);
+#endif /* End of __MDSS_SPI_CLINET_H__ */
diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.c b/drivers/video/fbdev/msm/mdss_spi_panel.c
new file mode 100644
index 0000000..86a1c1c
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_panel.c
@@ -0,0 +1,1713 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of_gpio.h>
+#include <linux/gpio.h>
+#include <linux/qpnp/pin.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/leds.h>
+#include <linux/qpnp/pwm.h>
+#include <linux/of_device.h>
+
+#include "mdss.h"
+#include "mdss_panel.h"
+#include "mdss_spi_panel.h"
+#include "mdss_spi_client.h"
+#include "mdp3.h"
+
+DEFINE_LED_TRIGGER(bl_led_trigger);
+static int mdss_spi_panel_reset(struct mdss_panel_data *pdata, int enable)
+{
+	struct spi_panel_data *ctrl_pdata = NULL;
+	struct mdss_panel_info *pinfo = NULL;
+	int i, rc = 0;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	if (!gpio_is_valid(ctrl_pdata->rst_gpio)) {
+		pr_debug("%s:%d, reset line not configured\n",
+			   __func__, __LINE__);
+		return rc;
+	}
+
+	if (!gpio_is_valid(ctrl_pdata->disp_dc_gpio)) {
+		pr_debug("%s:%d, dc line not configured\n",
+			   __func__, __LINE__);
+		return rc;
+	}
+
+	pr_debug("%s: enable = %d\n", __func__, enable);
+	pinfo = &(ctrl_pdata->panel_data.panel_info);
+
+	if (enable) {
+		rc = gpio_request(ctrl_pdata->rst_gpio, "disp_rst_n");
+		if (rc) {
+			pr_err("display reset gpio request failed\n");
+			return rc;
+		}
+
+		rc = gpio_request(ctrl_pdata->disp_dc_gpio, "disp_dc");
+		if (rc) {
+			pr_err("display dc gpio request failed\n");
+			return rc;
+		}
+
+		if (!pinfo->cont_splash_enabled) {
+			for (i = 0; i < pdata->panel_info.rst_seq_len; ++i) {
+				gpio_direction_output((ctrl_pdata->rst_gpio),
+					pdata->panel_info.rst_seq[i]);
+				if (pdata->panel_info.rst_seq[++i])
+					usleep_range(pinfo->rst_seq[i] * 1000,
+					pinfo->rst_seq[i] * 1000);
+			}
+		}
+
+		if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
+			pr_debug("%s: Panel Not properly turned OFF\n",
+						__func__);
+			ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
+			pr_err("%s: Reset panel done\n", __func__);
+		}
+	} else {
+		gpio_direction_output((ctrl_pdata->rst_gpio), 0);
+		gpio_free(ctrl_pdata->rst_gpio);
+
+		gpio_direction_output(ctrl_pdata->disp_dc_gpio, 0);
+		gpio_free(ctrl_pdata->disp_dc_gpio);
+	}
+	return rc;
+}
+
+
+static int mdss_spi_panel_pinctrl_set_state(
+	struct spi_panel_data *ctrl_pdata,
+	bool active)
+{
+	struct pinctrl_state *pin_state;
+	int rc = -EFAULT;
+
+	if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.pinctrl))
+		return PTR_ERR(ctrl_pdata->pin_res.pinctrl);
+
+	pin_state = active ? ctrl_pdata->pin_res.gpio_state_active
+				: ctrl_pdata->pin_res.gpio_state_suspend;
+	if (!IS_ERR_OR_NULL(pin_state)) {
+		rc = pinctrl_select_state(ctrl_pdata->pin_res.pinctrl,
+				pin_state);
+		if (rc)
+			pr_err("%s: can not set %s pins\n", __func__,
+			       active ? MDSS_PINCTRL_STATE_DEFAULT
+			       : MDSS_PINCTRL_STATE_SLEEP);
+	} else {
+		pr_err("%s: invalid '%s' pinstate\n", __func__,
+		       active ? MDSS_PINCTRL_STATE_DEFAULT
+		       : MDSS_PINCTRL_STATE_SLEEP);
+	}
+	return rc;
+}
+
+
+static int mdss_spi_panel_pinctrl_init(struct platform_device *pdev)
+{
+	struct spi_panel_data *ctrl_pdata;
+
+	ctrl_pdata = platform_get_drvdata(pdev);
+	ctrl_pdata->pin_res.pinctrl = devm_pinctrl_get(&pdev->dev);
+	if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.pinctrl)) {
+		pr_err("%s: failed to get pinctrl\n", __func__);
+		return PTR_ERR(ctrl_pdata->pin_res.pinctrl);
+	}
+
+	ctrl_pdata->pin_res.gpio_state_active
+		= pinctrl_lookup_state(ctrl_pdata->pin_res.pinctrl,
+				MDSS_PINCTRL_STATE_DEFAULT);
+	if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.gpio_state_active))
+		pr_warn("%s: can not get default pinstate\n", __func__);
+
+	ctrl_pdata->pin_res.gpio_state_suspend
+		= pinctrl_lookup_state(ctrl_pdata->pin_res.pinctrl,
+				MDSS_PINCTRL_STATE_SLEEP);
+	if (IS_ERR_OR_NULL(ctrl_pdata->pin_res.gpio_state_suspend))
+		pr_warn("%s: can not get sleep pinstate\n", __func__);
+
+	return 0;
+}
+
+
+static int mdss_spi_panel_power_on(struct mdss_panel_data *pdata)
+{
+	int ret = 0;
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+	ret = msm_mdss_enable_vreg(
+		ctrl_pdata->panel_power_data.vreg_config,
+		ctrl_pdata->panel_power_data.num_vreg, 1);
+	if (ret) {
+		pr_err("%s: failed to enable vregs for %s\n",
+			__func__, "PANEL_PM");
+	}
+
+	/*
+	 * If continuous splash screen feature is enabled, then we need to
+	 * request all the GPIOs that have already been configured in the
+	 * bootloader. This needs to be done irresepective of whether
+	 * the lp11_init flag is set or not.
+	 */
+	if (pdata->panel_info.cont_splash_enabled) {
+		if (mdss_spi_panel_pinctrl_set_state(ctrl_pdata, true))
+			pr_debug("reset enable: pinctrl not enabled\n");
+
+		ret = mdss_spi_panel_reset(pdata, 1);
+		if (ret)
+			pr_err("%s: Panel reset failed. rc=%d\n",
+					__func__, ret);
+	}
+
+	return ret;
+}
+
+
+static int mdss_spi_panel_power_off(struct mdss_panel_data *pdata)
+{
+	int ret = 0;
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		ret = -EINVAL;
+		goto end;
+	}
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	ret = mdss_spi_panel_reset(pdata, 0);
+	if (ret) {
+		pr_warn("%s: Panel reset failed. rc=%d\n", __func__, ret);
+		ret = 0;
+	}
+
+	if (mdss_spi_panel_pinctrl_set_state(ctrl_pdata, false))
+		pr_warn("reset disable: pinctrl not enabled\n");
+
+	ret = msm_mdss_enable_vreg(
+		ctrl_pdata->panel_power_data.vreg_config,
+		ctrl_pdata->panel_power_data.num_vreg, 0);
+	if (ret)
+		pr_err("%s: failed to disable vregs for %s\n",
+			__func__, "PANEL_PM");
+
+end:
+	return ret;
+}
+
+
+static int mdss_spi_panel_power_ctrl(struct mdss_panel_data *pdata,
+	int power_state)
+{
+	int ret;
+	struct mdss_panel_info *pinfo;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	pinfo = &pdata->panel_info;
+	pr_debug("%s: cur_power_state=%d req_power_state=%d\n", __func__,
+		pinfo->panel_power_state, power_state);
+
+	if (pinfo->panel_power_state == power_state) {
+		pr_debug("%s: no change needed\n", __func__);
+		return 0;
+	}
+
+	switch (power_state) {
+	case MDSS_PANEL_POWER_OFF:
+		ret = mdss_spi_panel_power_off(pdata);
+		break;
+	case MDSS_PANEL_POWER_ON:
+		ret = mdss_spi_panel_power_on(pdata);
+		break;
+	default:
+		pr_err("%s: unknown panel power state requested (%d)\n",
+			__func__, power_state);
+		ret = -EINVAL;
+	}
+
+	if (!ret)
+		pinfo->panel_power_state = power_state;
+
+	return ret;
+}
+
+static int mdss_spi_panel_unblank(struct mdss_panel_data *pdata)
+{
+	int ret = 0;
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	if (!(ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT)) {
+		ret = ctrl_pdata->on(pdata);
+		if (ret) {
+			pr_err("%s: unable to initialize the panel\n",
+							__func__);
+			return ret;
+		}
+		ctrl_pdata->ctrl_state |= CTRL_STATE_PANEL_INIT;
+	}
+
+	return ret;
+}
+
+static int mdss_spi_panel_blank(struct mdss_panel_data *pdata, int power_state)
+{
+	int ret = 0;
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	if (ctrl_pdata->ctrl_state & CTRL_STATE_PANEL_INIT) {
+		ret = ctrl_pdata->off(pdata);
+		if (ret) {
+			pr_err("%s: Panel OFF failed\n", __func__);
+			return ret;
+		}
+		ctrl_pdata->ctrl_state &= ~CTRL_STATE_PANEL_INIT;
+	}
+
+	return ret;
+}
+
+
+static int mdss_spi_panel_event_handler(struct mdss_panel_data *pdata,
+				  int event, void *arg)
+{
+	int rc = 0;
+	struct spi_panel_data *ctrl_pdata = NULL;
+	int power_state;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	switch (event) {
+	case MDSS_EVENT_LINK_READY:
+		rc = mdss_spi_panel_power_ctrl(pdata, MDSS_PANEL_POWER_ON);
+		if (rc) {
+			pr_err("%s:Panel power on failed. rc=%d\n",
+							__func__, rc);
+			return rc;
+		}
+		mdss_spi_panel_pinctrl_set_state(ctrl_pdata, true);
+		mdss_spi_panel_reset(pdata, 1);
+		break;
+	case MDSS_EVENT_UNBLANK:
+		rc = mdss_spi_panel_unblank(pdata);
+		break;
+	case MDSS_EVENT_PANEL_ON:
+		ctrl_pdata->ctrl_state |= CTRL_STATE_MDP_ACTIVE;
+		break;
+	case MDSS_EVENT_BLANK:
+		power_state = (int) (unsigned long) arg;
+		break;
+	case MDSS_EVENT_PANEL_OFF:
+		power_state = (int) (unsigned long) arg;
+		ctrl_pdata->ctrl_state &= ~CTRL_STATE_MDP_ACTIVE;
+		rc = mdss_spi_panel_blank(pdata, power_state);
+		rc = mdss_spi_panel_power_ctrl(pdata, power_state);
+		break;
+	default:
+		pr_debug("%s: unhandled event=%d\n", __func__, event);
+		break;
+	}
+	pr_debug("%s-:event=%d, rc=%d\n", __func__, event, rc);
+	return rc;
+}
+
+int is_spi_panel_continuous_splash_on(struct mdss_panel_data *pdata)
+{
+	int i = 0, voltage = 0;
+	struct mdss_vreg *vreg;
+	int num_vreg;
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+			panel_data);
+	vreg = ctrl_pdata->panel_power_data.vreg_config;
+	num_vreg = ctrl_pdata->panel_power_data.num_vreg;
+
+	for (i = 0; i < num_vreg; i++) {
+		if (regulator_is_enabled(vreg[i].vreg) <= 0)
+			return false;
+		voltage = regulator_get_voltage(vreg[i].vreg);
+		if (!(voltage >= vreg[i].min_voltage &&
+			 voltage <= vreg[i].max_voltage))
+			return false;
+	}
+
+	return true;
+}
+
+static void enable_spi_panel_te_irq(struct spi_panel_data *ctrl_pdata,
+							bool enable)
+{
+	static bool is_enabled = true;
+
+	if (is_enabled == enable)
+		return;
+
+	if (!gpio_is_valid(ctrl_pdata->disp_te_gpio)) {
+		pr_err("%s:%d,SPI panel TE GPIO not configured\n",
+			   __func__, __LINE__);
+		return;
+	}
+
+	if (enable)
+		enable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
+	else
+		disable_irq(gpio_to_irq(ctrl_pdata->disp_te_gpio));
+
+	is_enabled = enable;
+}
+
+int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
+			char *buf, int len, int dma_stride)
+{
+	struct spi_panel_data *ctrl_pdata = NULL;
+	char *tx_buf;
+	int rc = 0;
+	int panel_yres;
+	int panel_xres;
+	int padding_length = 0;
+	int actual_stride = 0;
+	int byte_per_pixel = 0;
+	int scan_count = 0;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	tx_buf = ctrl_pdata->tx_buf;
+	panel_xres = ctrl_pdata->panel_data.panel_info.xres;
+	panel_yres = ctrl_pdata->panel_data.panel_info.yres;
+
+	byte_per_pixel = ctrl_pdata->panel_data.panel_info.bpp / 8;
+	actual_stride = panel_xres * byte_per_pixel;
+	padding_length = dma_stride - actual_stride;
+
+	/* remove the padding and copy to continuous buffer */
+	while (scan_count < panel_yres) {
+		memcpy((tx_buf + scan_count * actual_stride),
+			(buf + scan_count * (actual_stride + padding_length)),
+				actual_stride);
+		scan_count++;
+	}
+
+	enable_spi_panel_te_irq(ctrl_pdata, true);
+
+	mutex_lock(&ctrl_pdata->spi_tx_mutex);
+	reinit_completion(&ctrl_pdata->spi_panel_te);
+
+	rc = wait_for_completion_timeout(&ctrl_pdata->spi_panel_te,
+				   msecs_to_jiffies(SPI_PANEL_TE_TIMEOUT));
+
+	if (rc == 0)
+		pr_err("wait panel TE time out\n");
+
+	rc = mdss_spi_tx_pixel(tx_buf, ctrl_pdata->byte_pre_frame);
+	mutex_unlock(&ctrl_pdata->spi_tx_mutex);
+
+	return rc;
+}
+
+static int mdss_spi_read_panel_data(struct mdss_panel_data *pdata,
+		u8 reg_addr, u8 *data, u8 len)
+{
+	int rc = 0;
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+		panel_data);
+
+	mutex_lock(&ctrl_pdata->spi_tx_mutex);
+	gpio_direction_output(ctrl_pdata->disp_dc_gpio, 0);
+	rc = mdss_spi_read_data(reg_addr, data, len);
+	gpio_direction_output(ctrl_pdata->disp_dc_gpio, 1);
+	mutex_unlock(&ctrl_pdata->spi_tx_mutex);
+
+	return rc;
+}
+
+static int mdss_spi_panel_on(struct mdss_panel_data *pdata)
+{
+	struct spi_panel_data *ctrl = NULL;
+	struct mdss_panel_info *pinfo;
+	int i;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+	pinfo = &pdata->panel_info;
+	ctrl = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	for (i = 0; i < ctrl->on_cmds.cmd_cnt; i++) {
+		/* pull down dc gpio indicate this is command */
+		gpio_direction_output(ctrl->disp_dc_gpio, 0);
+		mdss_spi_tx_command(ctrl->on_cmds.cmds[i].command);
+		gpio_direction_output((ctrl->disp_dc_gpio), 1);
+
+		if (ctrl->on_cmds.cmds[i].dchdr.dlen > 1) {
+			mdss_spi_tx_parameter(ctrl->on_cmds.cmds[i].parameter,
+					ctrl->on_cmds.cmds[i].dchdr.dlen-1);
+		}
+		if (ctrl->on_cmds.cmds[i].dchdr.wait != 0)
+			msleep(ctrl->on_cmds.cmds[i].dchdr.wait);
+	}
+
+	pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
+
+	pr_debug("%s:-\n", __func__);
+
+	return 0;
+}
+
+
+static int mdss_spi_panel_off(struct mdss_panel_data *pdata)
+{
+	struct spi_panel_data *ctrl = NULL;
+	struct mdss_panel_info *pinfo;
+	int i;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return -EINVAL;
+	}
+
+	pinfo = &pdata->panel_info;
+	ctrl = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	for (i = 0; i < ctrl->off_cmds.cmd_cnt; i++) {
+		/* pull down dc gpio indicate this is command */
+		gpio_direction_output(ctrl->disp_dc_gpio, 0);
+		mdss_spi_tx_command(ctrl->off_cmds.cmds[i].command);
+		gpio_direction_output((ctrl->disp_dc_gpio), 1);
+
+		if (ctrl->off_cmds.cmds[i].dchdr.dlen > 1) {
+			mdss_spi_tx_parameter(ctrl->off_cmds.cmds[i].parameter,
+					ctrl->off_cmds.cmds[i].dchdr.dlen-1);
+		}
+
+		if (ctrl->off_cmds.cmds[i].dchdr.wait != 0)
+			msleep(ctrl->off_cmds.cmds[i].dchdr.wait);
+	}
+
+	pinfo->blank_state = MDSS_PANEL_BLANK_BLANK;
+
+	pr_debug("%s:-\n", __func__);
+	return 0;
+}
+
+static void mdss_spi_put_dt_vreg_data(struct device *dev,
+	struct mdss_module_power *module_power)
+{
+	if (!module_power) {
+		pr_err("%s: invalid input\n", __func__);
+		return;
+	}
+
+	if (module_power->vreg_config) {
+		devm_kfree(dev, module_power->vreg_config);
+		module_power->vreg_config = NULL;
+	}
+	module_power->num_vreg = 0;
+}
+
+
+static int mdss_spi_get_panel_vreg_data(struct device *dev,
+			struct mdss_module_power *mp)
+{
+	int i = 0, rc = 0;
+	u32 tmp = 0;
+	struct device_node *of_node = NULL, *supply_node = NULL;
+	struct device_node *supply_root_node = NULL;
+
+	if (!dev || !mp) {
+		pr_err("%s: invalid input\n", __func__);
+		rc = -EINVAL;
+		return rc;
+	}
+
+	of_node = dev->of_node;
+
+	mp->num_vreg = 0;
+
+	supply_root_node = of_get_child_by_name(of_node,
+				"qcom,panel-supply-entries");
+
+	for_each_available_child_of_node(supply_root_node, supply_node) {
+		mp->num_vreg++;
+	}
+	if (mp->num_vreg == 0) {
+		pr_debug("%s: no vreg\n", __func__);
+		goto novreg;
+	} else {
+		pr_debug("%s: vreg found. count=%d\n", __func__, mp->num_vreg);
+	}
+
+	mp->vreg_config = kcalloc(mp->num_vreg, sizeof(struct mdss_vreg),
+				GFP_KERNEL);
+
+	if (mp->vreg_config != NULL) {
+		for_each_available_child_of_node(supply_root_node,
+				supply_node) {
+			const char *st = NULL;
+			/* vreg-name */
+			rc = of_property_read_string(supply_node,
+				"qcom,supply-name", &st);
+			if (rc) {
+				pr_err("%s: error reading name. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			snprintf(mp->vreg_config[i].vreg_name,
+				ARRAY_SIZE((mp->vreg_config[i].vreg_name)),
+					"%s", st);
+			/* vreg-min-voltage */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-min-voltage", &tmp);
+			if (rc) {
+				pr_err("%s: error reading min volt. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].min_voltage = tmp;
+
+			/* vreg-max-voltage */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-max-voltage", &tmp);
+			if (rc) {
+				pr_err("%s: error reading max volt. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].max_voltage = tmp;
+
+			/* enable-load */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-enable-load", &tmp);
+			if (rc) {
+				pr_err("%s: error read enable load. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].load[DSS_REG_MODE_ENABLE] = tmp;
+
+			/* disable-load */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-disable-load", &tmp);
+			if (rc) {
+				pr_err("%s: error read disable load. rc=%d\n",
+					__func__, rc);
+				goto error;
+			}
+			mp->vreg_config[i].load[DSS_REG_MODE_DISABLE] = tmp;
+
+			/* pre-sleep */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-pre-on-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error read pre on value\n",
+						__func__);
+				rc = 0;
+			} else {
+				mp->vreg_config[i].pre_on_sleep = tmp;
+			}
+
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-pre-off-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error read pre off value\n",
+						__func__);
+				rc = 0;
+			} else {
+				mp->vreg_config[i].pre_off_sleep = tmp;
+			}
+
+			/* post-sleep */
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-post-on-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error read post on value\n",
+						__func__);
+				rc = 0;
+			} else {
+				mp->vreg_config[i].post_on_sleep = tmp;
+			}
+
+			rc = of_property_read_u32(supply_node,
+				"qcom,supply-post-off-sleep", &tmp);
+			if (rc) {
+				pr_debug("%s: error read post off value\n",
+						__func__);
+				rc = 0;
+			} else {
+				mp->vreg_config[i].post_off_sleep = tmp;
+			}
+
+			++i;
+		}
+	}
+	return rc;
+error:
+	kfree(mp->vreg_config);
+	mp->vreg_config = NULL;
+
+novreg:
+	mp->num_vreg = 0;
+
+	return rc;
+
+}
+
+static int mdss_spi_panel_parse_cmds(struct device_node *np,
+		struct spi_panel_cmds *pcmds, char *cmd_key)
+{
+	const char *data;
+	int blen = 0, len;
+	char *buf, *bp;
+	struct spi_ctrl_hdr *dchdr;
+	int i, cnt;
+
+	data = of_get_property(np, cmd_key, &blen);
+	if (!data) {
+		pr_err("%s: failed, key=%s\n", __func__, cmd_key);
+		return -ENOMEM;
+	}
+
+	buf = kcalloc(blen, sizeof(char), GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	memcpy(buf, data, blen);
+
+	/* scan dcs commands */
+	bp = buf;
+	len = blen;
+	cnt = 0;
+	while (len >= sizeof(*dchdr)) {
+		dchdr = (struct spi_ctrl_hdr *)bp;
+		if (dchdr->dlen > len) {
+			pr_err("%s: dtsi parse error, len=%d",
+				__func__, dchdr->dlen);
+			goto exit_free;
+		}
+		bp += sizeof(*dchdr);
+		len -= sizeof(*dchdr);
+		bp += dchdr->dlen;
+		len -= dchdr->dlen;
+		cnt++;
+	}
+
+	if (len != 0) {
+		pr_err("%s: dcs_cmd=%x len=%d error",
+				__func__, buf[0], len);
+		goto exit_free;
+	}
+
+	pcmds->cmds = kcalloc(cnt, sizeof(struct spi_cmd_desc),
+						GFP_KERNEL);
+	if (!pcmds->cmds)
+		goto exit_free;
+
+	pcmds->cmd_cnt = cnt;
+	pcmds->buf = buf;
+	pcmds->blen = blen;
+
+	bp = buf;
+	len = blen;
+	for (i = 0; i < cnt; i++) {
+		dchdr = (struct spi_ctrl_hdr *)bp;
+		len -= sizeof(*dchdr);
+		bp += sizeof(*dchdr);
+		pcmds->cmds[i].dchdr = *dchdr;
+		pcmds->cmds[i].command = bp;
+		pcmds->cmds[i].parameter = bp + sizeof(char);
+		bp += dchdr->dlen;
+		len -= dchdr->dlen;
+	}
+
+	pr_debug("%s: dcs_cmd=%x, len=%d, cmd_cnt=%d\n", __func__,
+		pcmds->buf[0], pcmds->blen, pcmds->cmd_cnt);
+
+	return 0;
+
+exit_free:
+	kfree(buf);
+	return -ENOMEM;
+}
+static int mdss_spi_panel_parse_reset_seq(struct device_node *np,
+		u32 rst_seq[MDSS_SPI_RST_SEQ_LEN], u32 *rst_len,
+		const char *name)
+{
+	int num = 0, i;
+	int rc;
+	struct property *data;
+	u32 tmp[MDSS_SPI_RST_SEQ_LEN];
+
+	*rst_len = 0;
+	data = of_find_property(np, name, &num);
+	num /= sizeof(u32);
+	if (!data || !num || num > MDSS_SPI_RST_SEQ_LEN || num % 2) {
+		pr_err("%s:%d, error reading %s, length found = %d\n",
+			__func__, __LINE__, name, num);
+	} else {
+		rc = of_property_read_u32_array(np, name, tmp, num);
+		if (rc)
+			pr_err("%s:%d, error reading %s, rc = %d\n",
+				__func__, __LINE__, name, rc);
+		else {
+			for (i = 0; i < num; ++i)
+				rst_seq[i] = tmp[i];
+			*rst_len = num;
+		}
+	}
+	return 0;
+}
+
+static bool mdss_send_panel_cmd_for_esd(struct spi_panel_data *ctrl_pdata)
+{
+
+	if (ctrl_pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return false;
+	}
+
+	mutex_lock(&ctrl_pdata->spi_tx_mutex);
+	mdss_spi_panel_on(&ctrl_pdata->panel_data);
+	mutex_unlock(&ctrl_pdata->spi_tx_mutex);
+
+	return true;
+}
+
+static bool mdss_spi_reg_status_check(struct spi_panel_data *ctrl_pdata)
+{
+	int ret = 0;
+	int i = 0;
+
+	if (ctrl_pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return false;
+	}
+
+	pr_debug("%s: Checking Register status\n", __func__);
+
+	ret = mdss_spi_read_panel_data(&ctrl_pdata->panel_data,
+					ctrl_pdata->panel_status_reg,
+					ctrl_pdata->act_status_value,
+					ctrl_pdata->status_cmds_rlen);
+	if (ret < 0) {
+		pr_err("%s: Read status register returned error\n", __func__);
+	} else {
+		for (i = 0; i < ctrl_pdata->status_cmds_rlen; i++) {
+			pr_debug("act_value[%d] = %x, exp_value[%d] = %x\n",
+					i, ctrl_pdata->act_status_value[i],
+					i, ctrl_pdata->exp_status_value[i]);
+			if (ctrl_pdata->act_status_value[i] !=
+					ctrl_pdata->exp_status_value[i])
+				return false;
+		}
+	}
+
+	return true;
+}
+
+static void mdss_spi_parse_esd_params(struct device_node *np,
+		struct spi_panel_data	*ctrl)
+{
+	u32 tmp;
+	int rc;
+	struct property *data;
+	const char *string;
+	struct mdss_panel_info *pinfo = &ctrl->panel_data.panel_info;
+
+	pinfo->esd_check_enabled = of_property_read_bool(np,
+		"qcom,esd-check-enabled");
+
+	if (!pinfo->esd_check_enabled)
+		return;
+
+	ctrl->status_mode = SPI_ESD_MAX;
+
+	rc = of_property_read_string(np,
+			"qcom,mdss-spi-panel-status-check-mode", &string);
+	if (!rc) {
+		if (!strcmp(string, "reg_read")) {
+			ctrl->status_mode = SPI_ESD_REG;
+			ctrl->check_status =
+				mdss_spi_reg_status_check;
+		} else if (!strcmp(string, "send_init_command")) {
+			ctrl->status_mode = SPI_SEND_PANEL_COMMAND;
+			ctrl->check_status =
+				mdss_send_panel_cmd_for_esd;
+				return;
+		} else {
+			pr_err("No valid panel-status-check-mode string\n");
+			pinfo->esd_check_enabled = false;
+			return;
+		}
+	}
+
+	rc = of_property_read_u8(np, "qcom,mdss-spi-panel-status-reg",
+				&ctrl->panel_status_reg);
+	if (rc) {
+		pr_warn("%s:%d, Read status reg failed, disable ESD check\n",
+				__func__, __LINE__);
+		pinfo->esd_check_enabled = false;
+		return;
+	}
+
+	rc = of_property_read_u32(np, "qcom,mdss-spi-panel-status-read-length",
+					&tmp);
+	if (rc) {
+		pr_warn("%s:%d, Read reg length failed, disable ESD check\n",
+				__func__, __LINE__);
+		pinfo->esd_check_enabled = false;
+		return;
+	}
+
+	ctrl->status_cmds_rlen = (!rc ? tmp : 1);
+
+	ctrl->exp_status_value = kzalloc(sizeof(u8) *
+				 (ctrl->status_cmds_rlen + 1), GFP_KERNEL);
+	ctrl->act_status_value = kzalloc(sizeof(u8) *
+				(ctrl->status_cmds_rlen + 1), GFP_KERNEL);
+
+	if (!ctrl->exp_status_value || !ctrl->act_status_value) {
+		pr_err("%s: Error allocating memory for status buffer\n",
+						__func__);
+		pinfo->esd_check_enabled = false;
+		return;
+	}
+
+	data = of_find_property(np, "qcom,mdss-spi-panel-status-value", &tmp);
+	tmp /= sizeof(u8);
+	if (!data || (tmp != ctrl->status_cmds_rlen)) {
+		pr_err("%s: Panel status values not found\n", __func__);
+		pinfo->esd_check_enabled = false;
+		memset(ctrl->exp_status_value, 0, ctrl->status_cmds_rlen);
+	} else {
+		rc = of_property_read_u8_array(np,
+			"qcom,mdss-spi-panel-status-value",
+			ctrl->exp_status_value, tmp);
+		if (rc) {
+			pr_err("%s: Error reading panel status values\n",
+				__func__);
+			pinfo->esd_check_enabled = false;
+			memset(ctrl->exp_status_value, 0,
+				ctrl->status_cmds_rlen);
+		}
+	}
+}
+
+static int mdss_spi_panel_parse_dt(struct device_node *np,
+		struct spi_panel_data	*ctrl_pdata)
+{
+	u32 tmp;
+	int rc;
+	const char *data;
+	struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
+
+	pinfo->cont_splash_enabled = of_property_read_bool(np,
+					"qcom,cont-splash-enabled");
+
+	rc = of_property_read_u32(np, "qcom,mdss-spi-panel-width", &tmp);
+	if (rc) {
+		pr_err("%s: panel width not specified\n", __func__);
+		return -EINVAL;
+	}
+	pinfo->xres = (!rc ? tmp : 240);
+
+	rc = of_property_read_u32(np, "qcom,mdss-spi-panel-height", &tmp);
+	if (rc) {
+		pr_err("%s:panel height not specified\n", __func__);
+		return -EINVAL;
+	}
+	pinfo->yres = (!rc ? tmp : 320);
+
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-physical-width-dimension", &tmp);
+	pinfo->physical_width = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np,
+		"qcom,mdss-pan-physical-height-dimension", &tmp);
+	pinfo->physical_height = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-panel-framerate", &tmp);
+	pinfo->spi.frame_rate = (!rc ? tmp : 30);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-h-front-porch", &tmp);
+	pinfo->lcdc.h_front_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-h-back-porch", &tmp);
+	pinfo->lcdc.h_back_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-h-pulse-width", &tmp);
+	pinfo->lcdc.h_pulse_width = (!rc ? tmp : 2);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-h-sync-skew", &tmp);
+	pinfo->lcdc.hsync_skew = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-v-back-porch", &tmp);
+	pinfo->lcdc.v_back_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-v-front-porch", &tmp);
+	pinfo->lcdc.v_front_porch = (!rc ? tmp : 6);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-v-pulse-width", &tmp);
+	pinfo->lcdc.v_pulse_width = (!rc ? tmp : 2);
+
+
+	rc = of_property_read_u32(np, "qcom,mdss-spi-bpp", &tmp);
+	if (rc) {
+		pr_err("%s: bpp not specified\n", __func__);
+		return -EINVAL;
+	}
+	pinfo->bpp = (!rc ? tmp : 16);
+
+	pinfo->pdest = DISPLAY_1;
+
+	ctrl_pdata->bklt_ctrl = SPI_UNKNOWN_CTRL;
+	data = of_get_property(np, "qcom,mdss-spi-bl-pmic-control-type", NULL);
+	if (data) {
+		if (!strcmp(data, "bl_ctrl_wled")) {
+			led_trigger_register_simple("bkl-trigger",
+				&bl_led_trigger);
+			pr_debug("%s: SUCCESS-> WLED TRIGGER register\n",
+				__func__);
+			ctrl_pdata->bklt_ctrl = SPI_BL_WLED;
+		} else if (!strcmp(data, "bl_gpio_pulse")) {
+			led_trigger_register_simple("gpio-bklt-trigger",
+				&bl_led_trigger);
+			pr_debug("%s: SUCCESS-> GPIO PULSE TRIGGER register\n",
+				__func__);
+			ctrl_pdata->bklt_ctrl = SPI_BL_WLED;
+		} else if (!strcmp(data, "bl_ctrl_pwm")) {
+			ctrl_pdata->bklt_ctrl = SPI_BL_PWM;
+			ctrl_pdata->pwm_pmi = of_property_read_bool(np,
+					"qcom,mdss-spi-bl-pwm-pmi");
+			rc = of_property_read_u32(np,
+				"qcom,mdss-spi-bl-pmic-pwm-frequency", &tmp);
+			if (rc) {
+				pr_err("%s: Error, panel pwm_period\n",
+					 __func__);
+				return -EINVAL;
+			}
+			ctrl_pdata->pwm_period = tmp;
+			if (ctrl_pdata->pwm_pmi) {
+				ctrl_pdata->pwm_bl = of_pwm_get(np, NULL);
+				if (IS_ERR(ctrl_pdata->pwm_bl)) {
+					pr_err("%s: Error, pwm device\n",
+							__func__);
+					ctrl_pdata->pwm_bl = NULL;
+					return -EINVAL;
+				}
+			} else {
+				rc = of_property_read_u32(np,
+					"qcom,mdss-spi-bl-pmic-bank-select",
+								 &tmp);
+				if (rc) {
+					pr_err("%s: Error, lpg channel\n",
+						__func__);
+					return -EINVAL;
+				}
+				ctrl_pdata->pwm_lpg_chan = tmp;
+				tmp = of_get_named_gpio(np,
+					"qcom,mdss-spi-pwm-gpio", 0);
+				ctrl_pdata->pwm_pmic_gpio = tmp;
+				pr_debug("%s: Configured PWM bklt ctrl\n",
+								 __func__);
+			}
+		}
+	}
+	rc = of_property_read_u32(np, "qcom,mdss-brightness-max-level", &tmp);
+	pinfo->brightness_max = (!rc ? tmp : MDSS_MAX_BL_BRIGHTNESS);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-bl-min-level", &tmp);
+	pinfo->bl_min = (!rc ? tmp : 0);
+	rc = of_property_read_u32(np, "qcom,mdss-spi-bl-max-level", &tmp);
+	pinfo->bl_max = (!rc ? tmp : 255);
+	ctrl_pdata->bklt_max = pinfo->bl_max;
+
+
+	mdss_spi_panel_parse_reset_seq(np, pinfo->rst_seq,
+					&(pinfo->rst_seq_len),
+					"qcom,mdss-spi-reset-sequence");
+
+	mdss_spi_panel_parse_cmds(np, &ctrl_pdata->on_cmds,
+		"qcom,mdss-spi-on-command");
+
+	mdss_spi_panel_parse_cmds(np, &ctrl_pdata->off_cmds,
+		"qcom,mdss-spi-off-command");
+
+	mdss_spi_parse_esd_params(np, ctrl_pdata);
+
+
+	return 0;
+}
+
+static void mdss_spi_panel_pwm_cfg(struct spi_panel_data *ctrl)
+{
+	if (ctrl->pwm_pmi)
+		return;
+
+	ctrl->pwm_bl = pwm_request(ctrl->pwm_lpg_chan, "lcd-bklt");
+	if (ctrl->pwm_bl == NULL || IS_ERR(ctrl->pwm_bl)) {
+		pr_err("%s: Error: lpg_chan=%d pwm request failed",
+				__func__, ctrl->pwm_lpg_chan);
+	}
+	ctrl->pwm_enabled = 0;
+}
+
+static void mdss_spi_panel_bklt_pwm(struct spi_panel_data *ctrl, int level)
+{
+	int ret;
+	u32 duty;
+	u32 period_ns;
+
+	if (ctrl->pwm_bl == NULL) {
+		pr_err("%s: no PWM\n", __func__);
+		return;
+	}
+
+	if (level == 0) {
+		if (ctrl->pwm_enabled) {
+			ret = pwm_config_us(ctrl->pwm_bl, level,
+					ctrl->pwm_period);
+			if (ret)
+				pr_err("%s: pwm_config_us() failed err=%d.\n",
+						__func__, ret);
+			pwm_disable(ctrl->pwm_bl);
+		}
+		ctrl->pwm_enabled = 0;
+		return;
+	}
+
+	duty = level * ctrl->pwm_period;
+	duty /= ctrl->bklt_max;
+
+	pr_debug("%s: bklt_ctrl=%d pwm_period=%d pwm_gpio=%d pwm_lpg_chan=%d\n",
+			__func__, ctrl->bklt_ctrl, ctrl->pwm_period,
+				ctrl->pwm_pmic_gpio, ctrl->pwm_lpg_chan);
+
+	if (ctrl->pwm_period >= USEC_PER_SEC) {
+		ret = pwm_config_us(ctrl->pwm_bl, duty, ctrl->pwm_period);
+		if (ret) {
+			pr_err("%s: pwm_config_us() failed err=%d\n",
+					__func__, ret);
+			return;
+		}
+	} else {
+		period_ns = ctrl->pwm_period * NSEC_PER_USEC;
+		ret = pwm_config(ctrl->pwm_bl,
+				level * period_ns / ctrl->bklt_max,
+				period_ns);
+		if (ret) {
+			pr_err("%s: pwm_config() failed err=%d\n",
+					__func__, ret);
+			return;
+		}
+	}
+
+	if (!ctrl->pwm_enabled) {
+		ret = pwm_enable(ctrl->pwm_bl);
+		if (ret)
+			pr_err("%s: pwm_enable() failed err=%d\n", __func__,
+				ret);
+		ctrl->pwm_enabled = 1;
+	}
+}
+
+static void mdss_spi_panel_bl_ctrl(struct mdss_panel_data *pdata,
+							u32 bl_level)
+{
+	if (bl_level) {
+		mdp3_res->bklt_level = bl_level;
+		mdp3_res->bklt_update = true;
+	} else {
+		mdss_spi_panel_bl_ctrl_update(pdata, bl_level);
+	}
+}
+
+#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL) && defined(CONFIG_SPI_QUP)
+void mdss_spi_panel_bl_ctrl_update(struct mdss_panel_data *pdata,
+							u32 bl_level)
+{
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	if ((bl_level < pdata->panel_info.bl_min) && (bl_level != 0))
+		bl_level = pdata->panel_info.bl_min;
+
+	switch (ctrl_pdata->bklt_ctrl) {
+	case SPI_BL_WLED:
+		led_trigger_event(bl_led_trigger, bl_level);
+		break;
+	case SPI_BL_PWM:
+		mdss_spi_panel_bklt_pwm(ctrl_pdata, bl_level);
+		break;
+	default:
+		pr_err("%s: Unknown bl_ctrl configuration %d\n",
+			__func__, ctrl_pdata->bklt_ctrl);
+		break;
+	}
+}
+#endif
+
+static int mdss_spi_panel_init(struct device_node *node,
+	struct spi_panel_data	*ctrl_pdata,
+	bool cmd_cfg_cont_splash)
+{
+	int rc = 0;
+	static const char *panel_name;
+	struct mdss_panel_info *pinfo;
+
+	if (!node || !ctrl_pdata) {
+		pr_err("%s: Invalid arguments\n", __func__);
+		return -ENODEV;
+	}
+
+	pinfo = &ctrl_pdata->panel_data.panel_info;
+
+	pr_debug("%s:%d\n", __func__, __LINE__);
+	pinfo->panel_name[0] = '\0';
+	panel_name = of_get_property(node, "qcom,mdss-spi-panel-name", NULL);
+	if (!panel_name) {
+		pr_info("%s:%d, Panel name not specified\n",
+						__func__, __LINE__);
+	} else {
+		pr_debug("%s: Panel Name = %s\n", __func__, panel_name);
+		strlcpy(&pinfo->panel_name[0], panel_name, MDSS_MAX_PANEL_LEN);
+	}
+	rc = mdss_spi_panel_parse_dt(node, ctrl_pdata);
+	if (rc) {
+		pr_err("%s:%d panel dt parse failed\n", __func__, __LINE__);
+		return rc;
+	}
+
+	ctrl_pdata->byte_pre_frame = pinfo->xres * pinfo->yres * pinfo->bpp/8;
+
+	ctrl_pdata->tx_buf = kmalloc(ctrl_pdata->byte_pre_frame, GFP_KERNEL);
+
+	if (!cmd_cfg_cont_splash)
+		pinfo->cont_splash_enabled = false;
+
+	pr_info("%s: Continuous splash %s\n", __func__,
+		pinfo->cont_splash_enabled ? "enabled" : "disabled");
+
+	pinfo->dynamic_switch_pending = false;
+	pinfo->is_lpm_mode = false;
+	pinfo->esd_rdy = false;
+
+	ctrl_pdata->on = mdss_spi_panel_on;
+	ctrl_pdata->off = mdss_spi_panel_off;
+	ctrl_pdata->panel_data.set_backlight = mdss_spi_panel_bl_ctrl;
+
+	return 0;
+}
+
+static int mdss_spi_get_panel_cfg(char *panel_cfg,
+				struct spi_panel_data	*ctrl_pdata)
+{
+	int rc;
+	struct mdss_panel_cfg *pan_cfg = NULL;
+
+	if (!ctrl_pdata)
+		return MDSS_PANEL_INTF_INVALID;
+
+	pan_cfg = ctrl_pdata->mdss_util->panel_intf_type(MDSS_PANEL_INTF_SPI);
+	if (IS_ERR(pan_cfg)) {
+		return PTR_ERR(pan_cfg);
+	} else if (!pan_cfg) {
+		panel_cfg[0] = 0;
+		return 0;
+	}
+
+	pr_debug("%s:%d: cfg:[%s]\n", __func__, __LINE__,
+		 pan_cfg->arg_cfg);
+	ctrl_pdata->panel_data.panel_info.is_prim_panel = true;
+	rc = strlcpy(panel_cfg, pan_cfg->arg_cfg,
+		     sizeof(pan_cfg->arg_cfg));
+	return rc;
+}
+
+static int mdss_spi_panel_regulator_init(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	if (!pdev) {
+		pr_err("%s: invalid input\n", __func__);
+		return -EINVAL;
+	}
+
+	ctrl_pdata = platform_get_drvdata(pdev);
+	if (!ctrl_pdata) {
+		pr_err("%s: invalid driver data\n", __func__);
+		return -EINVAL;
+	}
+
+	rc = msm_mdss_config_vreg(&pdev->dev,
+		ctrl_pdata->panel_power_data.vreg_config,
+		ctrl_pdata->panel_power_data.num_vreg, 1);
+	if (rc)
+		pr_err("%s: failed to init vregs for %s\n",
+			__func__, "PANEL_PM");
+
+	return rc;
+
+}
+
+static irqreturn_t spi_panel_te_handler(int irq, void *data)
+{
+	struct spi_panel_data *ctrl_pdata = (struct spi_panel_data *)data;
+	static int count = 2;
+
+	if (!ctrl_pdata) {
+		pr_err("%s: SPI display not available\n", __func__);
+		return IRQ_HANDLED;
+	}
+	complete(&ctrl_pdata->spi_panel_te);
+
+	if (ctrl_pdata->vsync_client.handler && !(--count)) {
+		ctrl_pdata->vsync_client.handler(ctrl_pdata->vsync_client.arg);
+		count = 2;
+	}
+
+	return IRQ_HANDLED;
+}
+
+void mdp3_spi_vsync_enable(struct mdss_panel_data *pdata,
+				struct mdp3_notification *vsync_client)
+{
+	int updated = 0;
+	struct spi_panel_data *ctrl_pdata = NULL;
+
+	if (pdata == NULL) {
+		pr_err("%s: Invalid input data\n", __func__);
+		return;
+	}
+
+	ctrl_pdata = container_of(pdata, struct spi_panel_data,
+				panel_data);
+
+	if (vsync_client) {
+		if (ctrl_pdata->vsync_client.handler != vsync_client->handler) {
+			ctrl_pdata->vsync_client = *vsync_client;
+			updated = 1;
+		}
+	} else {
+		if (ctrl_pdata->vsync_client.handler) {
+			ctrl_pdata->vsync_client.handler = NULL;
+			ctrl_pdata->vsync_client.arg = NULL;
+			updated = 1;
+		}
+	}
+
+	if (updated) {
+		if (vsync_client && vsync_client->handler)
+			enable_spi_panel_te_irq(ctrl_pdata, true);
+		else
+			enable_spi_panel_te_irq(ctrl_pdata, false);
+	}
+}
+
+static struct device_node *mdss_spi_pref_prim_panel(
+		struct platform_device *pdev)
+{
+	struct device_node *spi_pan_node = NULL;
+
+	pr_debug("%s:%d: Select primary panel from dt\n",
+					__func__, __LINE__);
+	spi_pan_node = of_parse_phandle(pdev->dev.of_node,
+					"qcom,spi-pref-prim-pan", 0);
+	if (!spi_pan_node)
+		pr_err("%s:can't find panel phandle\n", __func__);
+
+	return spi_pan_node;
+}
+
+static int spi_panel_device_register(struct device_node *pan_node,
+				struct spi_panel_data *ctrl_pdata)
+{
+	int rc;
+	struct mdss_panel_info *pinfo = &(ctrl_pdata->panel_data.panel_info);
+	struct device_node *spi_ctrl_np = NULL;
+	struct platform_device *ctrl_pdev = NULL;
+
+	pinfo->type = SPI_PANEL;
+
+	spi_ctrl_np = of_parse_phandle(pan_node,
+				"qcom,mdss-spi-panel-controller", 0);
+	if (!spi_ctrl_np) {
+		pr_err("%s: SPI controller node not initialized\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	ctrl_pdev = of_find_device_by_node(spi_ctrl_np);
+	if (!ctrl_pdev) {
+		of_node_put(spi_ctrl_np);
+		pr_err("%s: SPI controller node not find\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	rc = mdss_spi_panel_regulator_init(ctrl_pdev);
+	if (rc) {
+		pr_err("%s: failed to init regulator, rc=%d\n",
+						__func__, rc);
+		return rc;
+	}
+
+	pinfo->panel_max_fps = mdss_panel_get_framerate(pinfo,
+		FPS_RESOLUTION_HZ);
+	pinfo->panel_max_vtotal = mdss_panel_get_vtotal(pinfo);
+
+	ctrl_pdata->disp_te_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+		"qcom,platform-te-gpio", 0);
+	if (!gpio_is_valid(ctrl_pdata->disp_te_gpio))
+		pr_err("%s:%d, TE gpio not specified\n",
+						__func__, __LINE__);
+
+	ctrl_pdata->disp_dc_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+		"qcom,platform-spi-dc-gpio", 0);
+	if (!gpio_is_valid(ctrl_pdata->disp_dc_gpio))
+		pr_err("%s:%d, SPI DC gpio not specified\n",
+						__func__, __LINE__);
+
+	ctrl_pdata->rst_gpio = of_get_named_gpio(ctrl_pdev->dev.of_node,
+			 "qcom,platform-reset-gpio", 0);
+	if (!gpio_is_valid(ctrl_pdata->rst_gpio))
+		pr_err("%s:%d, reset gpio not specified\n",
+						__func__, __LINE__);
+
+	ctrl_pdata->panel_data.event_handler = mdss_spi_panel_event_handler;
+
+	if (ctrl_pdata->bklt_ctrl == SPI_BL_PWM)
+		mdss_spi_panel_pwm_cfg(ctrl_pdata);
+
+	ctrl_pdata->ctrl_state = CTRL_STATE_UNKNOWN;
+
+	if (pinfo->cont_splash_enabled) {
+		rc = mdss_spi_panel_power_ctrl(&(ctrl_pdata->panel_data),
+			MDSS_PANEL_POWER_ON);
+		if (rc) {
+			pr_err("%s: Panel power on failed\n", __func__);
+			return rc;
+		}
+		if (ctrl_pdata->bklt_ctrl == SPI_BL_PWM)
+			ctrl_pdata->pwm_enabled = 1;
+		pinfo->blank_state = MDSS_PANEL_BLANK_UNBLANK;
+		ctrl_pdata->ctrl_state |=
+			(CTRL_STATE_PANEL_INIT | CTRL_STATE_MDP_ACTIVE);
+	} else {
+		pinfo->panel_power_state = MDSS_PANEL_POWER_OFF;
+	}
+
+	rc = mdss_register_panel(ctrl_pdev, &(ctrl_pdata->panel_data));
+	if (rc) {
+		pr_err("%s: unable to register SPI panel\n", __func__);
+		return rc;
+	}
+
+	pr_debug("%s: Panel data initialized\n", __func__);
+	return 0;
+}
+
+
+/**
+ * mdss_spi_find_panel_of_node(): find device node of spi panel
+ * @pdev: platform_device of the spi ctrl node
+ * @panel_cfg: string containing intf specific config data
+ *
+ * Function finds the panel device node using the interface
+ * specific configuration data. This configuration data is
+ * could be derived from the result of bootloader's GCDB
+ * panel detection mechanism. If such config data doesn't
+ * exist then this panel returns the default panel configured
+ * in the device tree.
+ *
+ * returns pointer to panel node on success, NULL on error.
+ */
+static struct device_node *mdss_spi_find_panel_of_node(
+		struct platform_device *pdev, char *panel_cfg)
+{
+	int len, i;
+	int ctrl_id = pdev->id - 1;
+	char panel_name[MDSS_MAX_PANEL_LEN] = "";
+	char ctrl_id_stream[3] =  "0:";
+	char *stream = NULL, *pan = NULL;
+	struct device_node *spi_pan_node = NULL, *mdss_node = NULL;
+
+	len = strlen(panel_cfg);
+	if (!len) {
+		/* no panel cfg chg, parse dt */
+		pr_err("%s:%d: no cmd line cfg present\n",
+			 __func__, __LINE__);
+		goto end;
+	} else {
+		if (ctrl_id == 1)
+			strlcpy(ctrl_id_stream, "1:", 3);
+
+		stream = strnstr(panel_cfg, ctrl_id_stream, len);
+		if (!stream) {
+			pr_err("controller config is not present\n");
+			goto end;
+		}
+		stream += 2;
+
+		pan = strnchr(stream, strlen(stream), ':');
+		if (!pan) {
+			strlcpy(panel_name, stream, MDSS_MAX_PANEL_LEN);
+		} else {
+			for (i = 0; (stream + i) < pan; i++)
+				panel_name[i] = *(stream + i);
+			panel_name[i] = 0;
+		}
+
+		pr_debug("%s:%d:%s:%s\n", __func__, __LINE__,
+			 panel_cfg, panel_name);
+
+		mdss_node = of_parse_phandle(pdev->dev.of_node,
+					     "qcom,mdss-mdp", 0);
+		if (!mdss_node) {
+			pr_err("%s: %d: mdss_node null\n",
+			       __func__, __LINE__);
+			return NULL;
+		}
+
+		spi_pan_node = of_find_node_by_name(mdss_node,
+						    panel_name);
+		if (!spi_pan_node) {
+			pr_err("%s: invalid pan node, selecting prim panel\n",
+			       __func__);
+			goto end;
+		}
+		return spi_pan_node;
+	}
+end:
+	if (strcmp(panel_name, NONE_PANEL))
+		spi_pan_node = mdss_spi_pref_prim_panel(pdev);
+	of_node_put(mdss_node);
+	return spi_pan_node;
+}
+
+
+static int mdss_spi_panel_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+	struct spi_panel_data	*ctrl_pdata;
+	struct mdss_panel_cfg *pan_cfg = NULL;
+	struct device_node *spi_pan_node = NULL;
+	bool cmd_cfg_cont_splash = true;
+	char panel_cfg[MDSS_MAX_PANEL_LEN];
+	struct mdss_util_intf *util;
+	const char *ctrl_name;
+
+	util = mdss_get_util_intf();
+	if (util == NULL) {
+		pr_err("Failed to get mdss utility functions\n");
+		return -ENODEV;
+	}
+
+	if (!util->mdp_probe_done) {
+		pr_err("%s: MDP not probed yet\n", __func__);
+		return -EPROBE_DEFER;
+	}
+
+	if (!pdev->dev.of_node) {
+		pr_err("SPI driver only supports device tree probe\n");
+		return -ENOTSUPP;
+	}
+
+	pan_cfg = util->panel_intf_type(MDSS_PANEL_INTF_DSI);
+	if (IS_ERR(pan_cfg)) {
+		pr_err("%s: return MDSS_PANEL_INTF_DSI\n", __func__);
+		return PTR_ERR(pan_cfg);
+	} else if (pan_cfg) {
+		pr_err("%s: DSI is primary\n", __func__);
+		return -ENODEV;
+	}
+
+	ctrl_pdata = platform_get_drvdata(pdev);
+	if (!ctrl_pdata) {
+		ctrl_pdata = devm_kzalloc(&pdev->dev,
+					  sizeof(struct spi_panel_data),
+					  GFP_KERNEL);
+		if (!ctrl_pdata) {
+			pr_err("%s: FAILED: cannot alloc spi panel\n",
+			       __func__);
+			rc = -ENOMEM;
+			goto error_no_mem;
+		}
+		platform_set_drvdata(pdev, ctrl_pdata);
+	}
+
+	ctrl_pdata->mdss_util = util;
+
+	ctrl_name = of_get_property(pdev->dev.of_node, "label", NULL);
+	if (!ctrl_name)
+		pr_info("%s:%d, Ctrl name not specified\n",
+			__func__, __LINE__);
+	else
+		pr_debug("%s: Ctrl name = %s\n",
+			__func__, ctrl_name);
+
+
+	rc = of_platform_populate(pdev->dev.of_node,
+				  NULL, NULL, &pdev->dev);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: failed to add child nodes, rc=%d\n",
+			__func__, rc);
+		goto error_no_mem;
+	}
+
+	rc = mdss_spi_panel_pinctrl_init(pdev);
+	if (rc)
+		pr_warn("%s: failed to get pin resources\n", __func__);
+
+	rc = mdss_spi_get_panel_vreg_data(&pdev->dev,
+					&ctrl_pdata->panel_power_data);
+	if (rc) {
+		dev_err(&pdev->dev,
+			"%s: failed to get panel vreg data, rc=%d\n",
+			__func__, rc);
+		goto error_vreg;
+	}
+
+	/* SPI panels can be different between controllers */
+	rc = mdss_spi_get_panel_cfg(panel_cfg, ctrl_pdata);
+	if (!rc)
+		/* spi panel cfg not present */
+		pr_warn("%s:%d:spi specific cfg not present\n",
+			__func__, __LINE__);
+
+	/* find panel device node */
+	spi_pan_node = mdss_spi_find_panel_of_node(pdev, panel_cfg);
+	if (!spi_pan_node) {
+		pr_err("%s: can't find panel node %s\n", __func__, panel_cfg);
+		goto error_pan_node;
+	}
+
+	cmd_cfg_cont_splash = true;
+
+	rc = mdss_spi_panel_init(spi_pan_node, ctrl_pdata, cmd_cfg_cont_splash);
+	if (rc) {
+		pr_err("%s: spi panel init failed\n", __func__);
+		goto error_pan_node;
+	}
+
+	rc = spi_panel_device_register(spi_pan_node, ctrl_pdata);
+	if (rc) {
+		pr_err("%s: spi panel dev reg failed\n", __func__);
+		goto error_pan_node;
+	}
+
+	ctrl_pdata->panel_data.event_handler = mdss_spi_panel_event_handler;
+
+
+	init_completion(&ctrl_pdata->spi_panel_te);
+	mutex_init(&ctrl_pdata->spi_tx_mutex);
+
+	rc = devm_request_irq(&pdev->dev,
+		gpio_to_irq(ctrl_pdata->disp_te_gpio),
+		spi_panel_te_handler, IRQF_TRIGGER_RISING,
+		"TE_GPIO", ctrl_pdata);
+	if (rc) {
+		pr_err("TE request_irq failed.\n");
+		return rc;
+	}
+
+	pr_debug("%s: spi panel  initialized\n", __func__);
+	return 0;
+
+error_pan_node:
+	of_node_put(spi_pan_node);
+error_vreg:
+	mdss_spi_put_dt_vreg_data(&pdev->dev,
+			&ctrl_pdata->panel_power_data);
+error_no_mem:
+	devm_kfree(&pdev->dev, ctrl_pdata);
+	return rc;
+}
+
+
+static const struct of_device_id mdss_spi_panel_match[] = {
+	{ .compatible = "qcom,mdss-spi-display" },
+	{},
+};
+
+static struct platform_driver this_driver = {
+	.probe = mdss_spi_panel_probe,
+	.driver = {
+		.name = "spi_panel",
+		.owner  = THIS_MODULE,
+		.of_match_table = mdss_spi_panel_match,
+	},
+};
+
+static int __init mdss_spi_display_init(void)
+{
+	int ret;
+
+	ret = platform_driver_register(&this_driver);
+	return 0;
+}
+module_init(mdss_spi_display_init);
+
+MODULE_DEVICE_TABLE(of, mdss_spi_panel_match);
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/fbdev/msm/mdss_spi_panel.h b/drivers/video/fbdev/msm/mdss_spi_panel.h
new file mode 100644
index 0000000..80b7ea8
--- /dev/null
+++ b/drivers/video/fbdev/msm/mdss_spi_panel.h
@@ -0,0 +1,148 @@
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __MDSS_SPI_PANEL_H__
+#define __MDSS_SPI_PANEL_H__
+
+#if defined(CONFIG_FB_MSM_MDSS_SPI_PANEL) && defined(CONFIG_SPI_QUP)
+#include <linux/list.h>
+#include <linux/mdss_io_util.h>
+#include <linux/irqreturn.h>
+#include <linux/pinctrl/consumer.h>
+#include <linux/gpio.h>
+
+#include "mdss_panel.h"
+#include "mdp3_dma.h"
+
+#define MDSS_MAX_BL_BRIGHTNESS 255
+
+#define MDSS_SPI_RST_SEQ_LEN	10
+
+#define NONE_PANEL "none"
+
+#define CTRL_STATE_UNKNOWN		0x00
+#define CTRL_STATE_PANEL_INIT		BIT(0)
+#define CTRL_STATE_MDP_ACTIVE		BIT(1)
+
+#define MDSS_PINCTRL_STATE_DEFAULT "mdss_default"
+#define MDSS_PINCTRL_STATE_SLEEP  "mdss_sleep"
+#define SPI_PANEL_TE_TIMEOUT	400
+
+enum spi_panel_data_type {
+	panel_cmd,
+	panel_parameter,
+	panel_pixel,
+	UNKNOWN_FORMAT,
+};
+
+enum spi_panel_bl_ctrl {
+	SPI_BL_PWM,
+	SPI_BL_WLED,
+	SPI_BL_DCS_CMD,
+	SPI_UNKNOWN_CTRL,
+};
+
+struct spi_pinctrl_res {
+	struct pinctrl *pinctrl;
+	struct pinctrl_state *gpio_state_active;
+	struct pinctrl_state *gpio_state_suspend;
+};
+#define SPI_PANEL_DST_FORMAT_RGB565		0
+
+struct spi_ctrl_hdr {
+	char wait;	/* ms */
+	char dlen;	/* 8 bits */
+};
+
+struct spi_cmd_desc {
+	struct spi_ctrl_hdr dchdr;
+	char *command;
+	char *parameter;
+};
+
+struct spi_panel_cmds {
+	char *buf;
+	int blen;
+	struct spi_cmd_desc *cmds;
+	int cmd_cnt;
+};
+
+enum spi_panel_status_mode {
+	SPI_ESD_REG,
+	SPI_SEND_PANEL_COMMAND,
+	SPI_ESD_MAX,
+};
+
+
+struct spi_panel_data {
+	struct mdss_panel_data panel_data;
+	struct mdss_util_intf *mdss_util;
+	struct spi_pinctrl_res pin_res;
+	struct mdss_module_power panel_power_data;
+	struct completion spi_panel_te;
+	struct mdp3_notification vsync_client;
+	unsigned int vsync_status;
+	int byte_pre_frame;
+	char *tx_buf;
+	u8 ctrl_state;
+	int disp_te_gpio;
+	int rst_gpio;
+	int disp_dc_gpio;	/* command or data */
+	struct spi_panel_cmds on_cmds;
+	struct spi_panel_cmds off_cmds;
+	bool (*check_status)(struct spi_panel_data *pdata);
+	int (*on)(struct mdss_panel_data *pdata);
+	int (*off)(struct mdss_panel_data *pdata);
+	struct mutex spi_tx_mutex;
+	struct pwm_device *pwm_bl;
+	int bklt_ctrl;	/* backlight ctrl */
+	bool pwm_pmi;
+	int pwm_period;
+	int pwm_pmic_gpio;
+	int pwm_lpg_chan;
+	int pwm_enabled;
+	int bklt_max;
+	int status_mode;
+	u32 status_cmds_rlen;
+	u8 panel_status_reg;
+	u8 *exp_status_value;
+	u8 *act_status_value;
+	unsigned char *return_buf;
+};
+
+int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
+				char *buf, int len, int stride);
+int is_spi_panel_continuous_splash_on(struct mdss_panel_data *pdata);
+void mdp3_spi_vsync_enable(struct mdss_panel_data *pdata,
+				struct mdp3_notification *vsync_client);
+void mdp3_check_spi_panel_status(struct work_struct *work,
+				uint32_t interval);
+
+#else
+static inline int mdss_spi_panel_kickoff(struct mdss_panel_data *pdata,
+				char *buf, int len, int stride){
+	return 0;
+}
+static inline int is_spi_panel_continuous_splash_on(
+				struct mdss_panel_data *pdata)
+{
+	return 0;
+}
+static inline int mdp3_spi_vsync_enable(struct mdss_panel_data *pdata,
+			struct mdp3_notification *vsync_client){
+	return 0;
+}
+
+#endif/* End of CONFIG_FB_MSM_MDSS_SPI_PANEL && ONFIG_SPI_QUP */
+
+#endif /* End of __MDSS_SPI_PANEL_H__ */
diff --git a/fs/debugfs/file.c b/fs/debugfs/file.c
index 354e2ab..0536072 100644
--- a/fs/debugfs/file.c
+++ b/fs/debugfs/file.c
@@ -22,7 +22,6 @@
 #include <linux/slab.h>
 #include <linux/atomic.h>
 #include <linux/device.h>
-#include <linux/srcu.h>
 #include <asm/poll.h>
 
 #include "internal.h"
@@ -48,66 +47,108 @@
 	.llseek =	noop_llseek,
 };
 
+#define F_DENTRY(filp) ((filp)->f_path.dentry)
+
+const struct file_operations *debugfs_real_fops(const struct file *filp)
+{
+	struct debugfs_fsdata *fsd = F_DENTRY(filp)->d_fsdata;
+
+	if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT) {
+		/*
+		 * Urgh, we've been called w/o a protecting
+		 * debugfs_file_get().
+		 */
+		WARN_ON(1);
+		return NULL;
+	}
+
+	return fsd->real_fops;
+}
+EXPORT_SYMBOL_GPL(debugfs_real_fops);
+
 /**
- * debugfs_use_file_start - mark the beginning of file data access
+ * debugfs_file_get - mark the beginning of file data access
  * @dentry: the dentry object whose data is being accessed.
- * @srcu_idx: a pointer to some memory to store a SRCU index in.
  *
- * Up to a matching call to debugfs_use_file_finish(), any
- * successive call into the file removing functions debugfs_remove()
- * and debugfs_remove_recursive() will block. Since associated private
+ * Up to a matching call to debugfs_file_put(), any successive call
+ * into the file removing functions debugfs_remove() and
+ * debugfs_remove_recursive() will block. Since associated private
  * file data may only get freed after a successful return of any of
  * the removal functions, you may safely access it after a successful
- * call to debugfs_use_file_start() without worrying about
- * lifetime issues.
+ * call to debugfs_file_get() without worrying about lifetime issues.
  *
  * If -%EIO is returned, the file has already been removed and thus,
  * it is not safe to access any of its data. If, on the other hand,
  * it is allowed to access the file data, zero is returned.
- *
- * Regardless of the return code, any call to
- * debugfs_use_file_start() must be followed by a matching call
- * to debugfs_use_file_finish().
  */
-int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx)
-	__acquires(&debugfs_srcu)
+int debugfs_file_get(struct dentry *dentry)
 {
-	*srcu_idx = srcu_read_lock(&debugfs_srcu);
-	barrier();
+	struct debugfs_fsdata *fsd;
+	void *d_fsd;
+
+	d_fsd = READ_ONCE(dentry->d_fsdata);
+	if (!((unsigned long)d_fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)) {
+		fsd = d_fsd;
+	} else {
+		fsd = kmalloc(sizeof(*fsd), GFP_KERNEL);
+		if (!fsd)
+			return -ENOMEM;
+
+		fsd->real_fops = (void *)((unsigned long)d_fsd &
+					~DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
+		refcount_set(&fsd->active_users, 1);
+		init_completion(&fsd->active_users_drained);
+		if (cmpxchg(&dentry->d_fsdata, d_fsd, fsd) != d_fsd) {
+			kfree(fsd);
+			fsd = READ_ONCE(dentry->d_fsdata);
+		}
+	}
+
+	/*
+	 * In case of a successful cmpxchg() above, this check is
+	 * strictly necessary and must follow it, see the comment in
+	 * __debugfs_remove_file().
+	 * OTOH, if the cmpxchg() hasn't been executed or wasn't
+	 * successful, this serves the purpose of not starving
+	 * removers.
+	 */
 	if (d_unlinked(dentry))
 		return -EIO;
+
+	if (!refcount_inc_not_zero(&fsd->active_users))
+		return -EIO;
+
 	return 0;
 }
-EXPORT_SYMBOL_GPL(debugfs_use_file_start);
+EXPORT_SYMBOL_GPL(debugfs_file_get);
 
 /**
- * debugfs_use_file_finish - mark the end of file data access
- * @srcu_idx: the SRCU index "created" by a former call to
- *            debugfs_use_file_start().
+ * debugfs_file_put - mark the end of file data access
+ * @dentry: the dentry object formerly passed to
+ *          debugfs_file_get().
  *
  * Allow any ongoing concurrent call into debugfs_remove() or
  * debugfs_remove_recursive() blocked by a former call to
- * debugfs_use_file_start() to proceed and return to its caller.
+ * debugfs_file_get() to proceed and return to its caller.
  */
-void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu)
+void debugfs_file_put(struct dentry *dentry)
 {
-	srcu_read_unlock(&debugfs_srcu, srcu_idx);
-}
-EXPORT_SYMBOL_GPL(debugfs_use_file_finish);
+	struct debugfs_fsdata *fsd = READ_ONCE(dentry->d_fsdata);
 
-#define F_DENTRY(filp) ((filp)->f_path.dentry)
+	if (refcount_dec_and_test(&fsd->active_users))
+		complete(&fsd->active_users_drained);
+}
+EXPORT_SYMBOL_GPL(debugfs_file_put);
 
 static int open_proxy_open(struct inode *inode, struct file *filp)
 {
-	const struct dentry *dentry = F_DENTRY(filp);
+	struct dentry *dentry = F_DENTRY(filp);
 	const struct file_operations *real_fops = NULL;
-	int srcu_idx, r;
+	int r;
 
-	r = debugfs_use_file_start(dentry, &srcu_idx);
-	if (r) {
-		r = -ENOENT;
-		goto out;
-	}
+	r = debugfs_file_get(dentry);
+	if (r)
+		return r == -EIO ? -ENOENT : r;
 
 	real_fops = debugfs_real_fops(filp);
 	real_fops = fops_get(real_fops);
@@ -124,7 +165,7 @@
 		r = real_fops->open(inode, filp);
 
 out:
-	debugfs_use_file_finish(srcu_idx);
+	debugfs_file_put(dentry);
 	return r;
 }
 
@@ -138,16 +179,16 @@
 #define FULL_PROXY_FUNC(name, ret_type, filp, proto, args)		\
 static ret_type full_proxy_ ## name(proto)				\
 {									\
-	const struct dentry *dentry = F_DENTRY(filp);			\
-	const struct file_operations *real_fops =			\
-		debugfs_real_fops(filp);				\
-	int srcu_idx;							\
+	struct dentry *dentry = F_DENTRY(filp);			\
+	const struct file_operations *real_fops;			\
 	ret_type r;							\
 									\
-	r = debugfs_use_file_start(dentry, &srcu_idx);			\
-	if (likely(!r))						\
-		r = real_fops->name(args);				\
-	debugfs_use_file_finish(srcu_idx);				\
+	r = debugfs_file_get(dentry);					\
+	if (unlikely(r))						\
+		return r;						\
+	real_fops = debugfs_real_fops(filp);				\
+	r = real_fops->name(args);					\
+	debugfs_file_put(dentry);					\
 	return r;							\
 }
 
@@ -172,18 +213,16 @@
 static unsigned int full_proxy_poll(struct file *filp,
 				struct poll_table_struct *wait)
 {
-	const struct dentry *dentry = F_DENTRY(filp);
-	const struct file_operations *real_fops = debugfs_real_fops(filp);
-	int srcu_idx;
+	struct dentry *dentry = F_DENTRY(filp);
 	unsigned int r = 0;
+	const struct file_operations *real_fops;
 
-	if (debugfs_use_file_start(dentry, &srcu_idx)) {
-		debugfs_use_file_finish(srcu_idx);
+	if (debugfs_file_get(dentry))
 		return POLLHUP;
-	}
 
+	real_fops = debugfs_real_fops(filp);
 	r = real_fops->poll(filp, wait);
-	debugfs_use_file_finish(srcu_idx);
+	debugfs_file_put(dentry);
 	return r;
 }
 
@@ -227,16 +266,14 @@
 
 static int full_proxy_open(struct inode *inode, struct file *filp)
 {
-	const struct dentry *dentry = F_DENTRY(filp);
+	struct dentry *dentry = F_DENTRY(filp);
 	const struct file_operations *real_fops = NULL;
 	struct file_operations *proxy_fops = NULL;
-	int srcu_idx, r;
+	int r;
 
-	r = debugfs_use_file_start(dentry, &srcu_idx);
-	if (r) {
-		r = -ENOENT;
-		goto out;
-	}
+	r = debugfs_file_get(dentry);
+	if (r)
+		return r == -EIO ? -ENOENT : r;
 
 	real_fops = debugfs_real_fops(filp);
 	real_fops = fops_get(real_fops);
@@ -274,7 +311,7 @@
 	kfree(proxy_fops);
 	fops_put(real_fops);
 out:
-	debugfs_use_file_finish(srcu_idx);
+	debugfs_file_put(dentry);
 	return r;
 }
 
@@ -285,13 +322,14 @@
 ssize_t debugfs_attr_read(struct file *file, char __user *buf,
 			size_t len, loff_t *ppos)
 {
+	struct dentry *dentry = F_DENTRY(file);
 	ssize_t ret;
-	int srcu_idx;
 
-	ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
-	if (likely(!ret))
-		ret = simple_attr_read(file, buf, len, ppos);
-	debugfs_use_file_finish(srcu_idx);
+	ret = debugfs_file_get(dentry);
+	if (unlikely(ret))
+		return ret;
+	ret = simple_attr_read(file, buf, len, ppos);
+	debugfs_file_put(dentry);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(debugfs_attr_read);
@@ -299,13 +337,14 @@
 ssize_t debugfs_attr_write(struct file *file, const char __user *buf,
 			 size_t len, loff_t *ppos)
 {
+	struct dentry *dentry = F_DENTRY(file);
 	ssize_t ret;
-	int srcu_idx;
 
-	ret = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
-	if (likely(!ret))
-		ret = simple_attr_write(file, buf, len, ppos);
-	debugfs_use_file_finish(srcu_idx);
+	ret = debugfs_file_get(dentry);
+	if (unlikely(ret))
+		return ret;
+	ret = simple_attr_write(file, buf, len, ppos);
+	debugfs_file_put(dentry);
 	return ret;
 }
 EXPORT_SYMBOL_GPL(debugfs_attr_write);
@@ -739,14 +778,14 @@
 {
 	char buf[3];
 	bool val;
-	int r, srcu_idx;
+	int r;
+	struct dentry *dentry = F_DENTRY(file);
 
-	r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
-	if (likely(!r))
-		val = *(bool *)file->private_data;
-	debugfs_use_file_finish(srcu_idx);
-	if (r)
+	r = debugfs_file_get(dentry);
+	if (unlikely(r))
 		return r;
+	val = *(bool *)file->private_data;
+	debugfs_file_put(dentry);
 
 	if (val)
 		buf[0] = 'Y';
@@ -764,8 +803,9 @@
 	char buf[32];
 	size_t buf_size;
 	bool bv;
-	int r, srcu_idx;
+	int r;
 	bool *val = file->private_data;
+	struct dentry *dentry = F_DENTRY(file);
 
 	buf_size = min(count, (sizeof(buf)-1));
 	if (copy_from_user(buf, user_buf, buf_size))
@@ -773,12 +813,11 @@
 
 	buf[buf_size] = '\0';
 	if (strtobool(buf, &bv) == 0) {
-		r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
-		if (likely(!r))
-			*val = bv;
-		debugfs_use_file_finish(srcu_idx);
-		if (r)
+		r = debugfs_file_get(dentry);
+		if (unlikely(r))
 			return r;
+		*val = bv;
+		debugfs_file_put(dentry);
 	}
 
 	return count;
@@ -840,14 +879,15 @@
 			      size_t count, loff_t *ppos)
 {
 	struct debugfs_blob_wrapper *blob = file->private_data;
+	struct dentry *dentry = F_DENTRY(file);
 	ssize_t r;
-	int srcu_idx;
 
-	r = debugfs_use_file_start(F_DENTRY(file), &srcu_idx);
-	if (likely(!r))
-		r = simple_read_from_buffer(user_buf, count, ppos, blob->data,
-					blob->size);
-	debugfs_use_file_finish(srcu_idx);
+	r = debugfs_file_get(dentry);
+	if (unlikely(r))
+		return r;
+	r = simple_read_from_buffer(user_buf, count, ppos, blob->data,
+				blob->size);
+	debugfs_file_put(dentry);
 	return r;
 }
 
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 3d7de9f..f7f672d 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -27,14 +27,11 @@
 #include <linux/parser.h>
 #include <linux/magic.h>
 #include <linux/slab.h>
-#include <linux/srcu.h>
 
 #include "internal.h"
 
 #define DEBUGFS_DEFAULT_MODE	0700
 
-DEFINE_SRCU(debugfs_srcu);
-
 static struct vfsmount *debugfs_mount;
 static int debugfs_mount_count;
 static bool debugfs_registered;
@@ -185,6 +182,14 @@
 	.evict_inode	= debugfs_evict_inode,
 };
 
+static void debugfs_release_dentry(struct dentry *dentry)
+{
+	void *fsd = dentry->d_fsdata;
+
+	if (!((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT))
+		kfree(dentry->d_fsdata);
+}
+
 static struct vfsmount *debugfs_automount(struct path *path)
 {
 	debugfs_automount_t f;
@@ -194,6 +199,7 @@
 
 static const struct dentry_operations debugfs_dops = {
 	.d_delete = always_delete_dentry,
+	.d_release = debugfs_release_dentry,
 	.d_automount = debugfs_automount,
 };
 
@@ -324,7 +330,8 @@
 	inode->i_private = data;
 
 	inode->i_fop = proxy_fops;
-	dentry->d_fsdata = (void *)real_fops;
+	dentry->d_fsdata = (void *)((unsigned long)real_fops |
+				DEBUGFS_FSDATA_IS_REAL_FOPS_BIT);
 
 	d_instantiate(dentry, inode);
 	fsnotify_create(d_inode(dentry->d_parent), dentry);
@@ -581,18 +588,43 @@
 }
 EXPORT_SYMBOL_GPL(debugfs_create_symlink);
 
+static void __debugfs_remove_file(struct dentry *dentry, struct dentry *parent)
+{
+	struct debugfs_fsdata *fsd;
+
+	simple_unlink(d_inode(parent), dentry);
+	d_delete(dentry);
+
+	/*
+	 * Paired with the closing smp_mb() implied by a successful
+	 * cmpxchg() in debugfs_file_get(): either
+	 * debugfs_file_get() must see a dead dentry or we must see a
+	 * debugfs_fsdata instance at ->d_fsdata here (or both).
+	 */
+	smp_mb();
+	fsd = READ_ONCE(dentry->d_fsdata);
+	if ((unsigned long)fsd & DEBUGFS_FSDATA_IS_REAL_FOPS_BIT)
+		return;
+	if (!refcount_dec_and_test(&fsd->active_users))
+		wait_for_completion(&fsd->active_users_drained);
+}
+
 static int __debugfs_remove(struct dentry *dentry, struct dentry *parent)
 {
 	int ret = 0;
 
 	if (simple_positive(dentry)) {
 		dget(dentry);
-		if (d_is_dir(dentry))
-			ret = simple_rmdir(d_inode(parent), dentry);
-		else
-			simple_unlink(d_inode(parent), dentry);
-		if (!ret)
-			d_delete(dentry);
+		if (!d_is_reg(dentry)) {
+			if (d_is_dir(dentry))
+				ret = simple_rmdir(d_inode(parent), dentry);
+			else
+				simple_unlink(d_inode(parent), dentry);
+			if (!ret)
+				d_delete(dentry);
+		} else {
+			__debugfs_remove_file(dentry, parent);
+		}
 		dput(dentry);
 	}
 	return ret;
@@ -626,8 +658,6 @@
 	inode_unlock(d_inode(parent));
 	if (!ret)
 		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-
-	synchronize_srcu(&debugfs_srcu);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove);
 
@@ -701,8 +731,6 @@
 	if (!__debugfs_remove(child, parent))
 		simple_release_fs(&debugfs_mount, &debugfs_mount_count);
 	inode_unlock(d_inode(parent));
-
-	synchronize_srcu(&debugfs_srcu);
 }
 EXPORT_SYMBOL_GPL(debugfs_remove_recursive);
 
diff --git a/fs/debugfs/internal.h b/fs/debugfs/internal.h
index b3e8443..49ba8dd 100644
--- a/fs/debugfs/internal.h
+++ b/fs/debugfs/internal.h
@@ -12,6 +12,8 @@
 #ifndef _DEBUGFS_INTERNAL_H_
 #define _DEBUGFS_INTERNAL_H_
 
+#include <linux/refcount.h>
+
 struct file_operations;
 
 /* declared over in file.c */
@@ -19,4 +21,18 @@
 extern const struct file_operations debugfs_open_proxy_file_operations;
 extern const struct file_operations debugfs_full_proxy_file_operations;
 
+struct debugfs_fsdata {
+	const struct file_operations *real_fops;
+	refcount_t active_users;
+	struct completion active_users_drained;
+};
+
+/*
+ * A dentry's ->d_fsdata either points to the real fops or to a
+ * dynamically allocated debugfs_fsdata instance.
+ * In order to distinguish between these two cases, a real fops
+ * pointer gets its lowest bit set.
+ */
+#define DEBUGFS_FSDATA_IS_REAL_FOPS_BIT BIT(0)
+
 #endif /* _DEBUGFS_INTERNAL_H_ */
diff --git a/include/linux/debugfs.h b/include/linux/debugfs.h
index b20a094..2e75ae2 100644
--- a/include/linux/debugfs.h
+++ b/include/linux/debugfs.h
@@ -23,7 +23,6 @@
 
 struct device;
 struct file_operations;
-struct srcu_struct;
 
 struct debugfs_blob_wrapper {
 	void *data;
@@ -43,25 +42,6 @@
 
 extern struct dentry *arch_debugfs_dir;
 
-extern struct srcu_struct debugfs_srcu;
-
-/**
- * debugfs_real_fops - getter for the real file operation
- * @filp: a pointer to a struct file
- *
- * Must only be called under the protection established by
- * debugfs_use_file_start().
- */
-static inline const struct file_operations *debugfs_real_fops(struct file *filp)
-	__must_hold(&debugfs_srcu)
-{
-	/*
-	 * Neither the pointer to the struct file_operations, nor its
-	 * contents ever change -- srcu_dereference() is not needed here.
-	 */
-	return filp->f_path.dentry->d_fsdata;
-}
-
 #define DEFINE_DEBUGFS_ATTRIBUTE(__fops, __get, __set, __fmt)		\
 static int __fops ## _open(struct inode *inode, struct file *file)	\
 {									\
@@ -105,10 +85,10 @@
 void debugfs_remove(struct dentry *dentry);
 void debugfs_remove_recursive(struct dentry *dentry);
 
-int debugfs_use_file_start(const struct dentry *dentry, int *srcu_idx)
-	__acquires(&debugfs_srcu);
+const struct file_operations *debugfs_real_fops(const struct file *filp);
 
-void debugfs_use_file_finish(int srcu_idx) __releases(&debugfs_srcu);
+int debugfs_file_get(struct dentry *dentry);
+void debugfs_file_put(struct dentry *dentry);
 
 ssize_t debugfs_attr_read(struct file *file, char __user *buf,
 			size_t len, loff_t *ppos);
@@ -223,15 +203,12 @@
 static inline void debugfs_remove_recursive(struct dentry *dentry)
 { }
 
-static inline int debugfs_use_file_start(const struct dentry *dentry,
-					int *srcu_idx)
-	__acquires(&debugfs_srcu)
+static inline int debugfs_file_get(struct dentry *dentry)
 {
 	return 0;
 }
 
-static inline void debugfs_use_file_finish(int srcu_idx)
-	__releases(&debugfs_srcu)
+static inline void debugfs_file_put(struct dentry *dentry)
 { }
 
 static inline ssize_t debugfs_attr_read(struct file *file, char __user *buf,
diff --git a/include/linux/ipa.h b/include/linux/ipa.h
index 1a1c68e..2c31666 100644
--- a/include/linux/ipa.h
+++ b/include/linux/ipa.h
@@ -1156,6 +1156,7 @@
  * @ipa_if_tlv: number of IPA_IF TLV
  * @ipa_if_aos: number of IPA_IF AOS
  * @ee: Execution environment
+ * @prefetch_mode: Prefetch mode to be used
  */
 struct ipa_gsi_ep_config {
 	int ipa_ep_num;
@@ -1163,6 +1164,7 @@
 	int ipa_if_tlv;
 	int ipa_if_aos;
 	int ee;
+	enum gsi_prefetch_mode prefetch_mode;
 };
 
 /**
diff --git a/include/linux/msm_gsi.h b/include/linux/msm_gsi.h
index 3b1e0e7..79e7daa 100644
--- a/include/linux/msm_gsi.h
+++ b/include/linux/msm_gsi.h
@@ -854,6 +854,18 @@
 		union __packed gsi_channel_scratch val);
 
 /**
+ * gsi_read_channel_scratch - Peripheral should call this function to
+ * read the scratch area of the channel context
+ *
+ * @chan_hdl:  Client handle previously obtained from
+ *             gsi_alloc_channel
+ *
+ * @Return gsi_status
+ */
+int gsi_read_channel_scratch(unsigned long chan_hdl,
+		union __packed gsi_channel_scratch *ch_scratch);
+
+/**
  * gsi_start_channel - Peripheral should call this function to
  * start a channel i.e put into running state
  *
@@ -1111,6 +1123,7 @@
  * gsi_alloc_channel (for as many channels as needed; channels can have
  * no event ring, an exclusive event ring or a shared event ring)
  * gsi_write_channel_scratch
+ * gsi_read_channel_scratch
  * gsi_start_channel
  * gsi_queue_xfer/gsi_start_xfer
  * gsi_config_channel_mode/gsi_poll_channel (if clients wants to poll on
@@ -1195,6 +1208,12 @@
 	return -GSI_STATUS_UNSUPPORTED_OP;
 }
 
+static inline int gsi_read_channel_scratch(unsigned long chan_hdl,
+		union __packed gsi_channel_scratch *ch_scratch)
+{
+	return -GSI_STATUS_UNSUPPORTED_OP;
+}
+
 static inline int gsi_start_channel(unsigned long chan_hdl)
 {
 	return -GSI_STATUS_UNSUPPORTED_OP;
diff --git a/include/linux/power_supply.h b/include/linux/power_supply.h
index 78c2a9f..ad6d53d 100644
--- a/include/linux/power_supply.h
+++ b/include/linux/power_supply.h
@@ -286,6 +286,9 @@
 	POWER_SUPPLY_PROP_BATTERY_INFO,
 	POWER_SUPPLY_PROP_BATTERY_INFO_ID,
 	POWER_SUPPLY_PROP_ENABLE_JEITA_DETECTION,
+	POWER_SUPPLY_PROP_ESR_ACTUAL,
+	POWER_SUPPLY_PROP_ESR_NOMINAL,
+	POWER_SUPPLY_PROP_SOH,
 	/* Local extensions of type int64_t */
 	POWER_SUPPLY_PROP_CHARGE_COUNTER_EXT,
 	/* Properties of type `const char *' */
diff --git a/include/linux/usb/composite.h b/include/linux/usb/composite.h
index 7f4367b..dbf6240 100644
--- a/include/linux/usb/composite.h
+++ b/include/linux/usb/composite.h
@@ -45,6 +45,9 @@
 #define FUNC_SUSPEND_OPT_SUSP_MASK BIT(0)
 #define FUNC_SUSPEND_OPT_RW_EN_MASK BIT(1)
 
+#define FUNC_WAKEUP_CAPABLE_SHIFT  0
+#define FUNC_WAKEUP_ENABLE_SHIFT   1
+
 /*
  * USB function drivers should return USB_GADGET_DELAYED_STATUS if they
  * wish to delay the data/status stages of the control transfer till they
diff --git a/include/soc/qcom/qseecomi.h b/include/soc/qcom/qseecomi.h
index a7d4190..d249168 100644
--- a/include/soc/qcom/qseecomi.h
+++ b/include/soc/qcom/qseecomi.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,7 @@
 #define QSEECOM_KEY_ID_SIZE   32
 
 #define QSEOS_RESULT_FAIL_SEND_CMD_NO_THREAD  -19   /*0xFFFFFFED*/
+#define QSEOS_RESULT_FAIL_APP_ALREADY_LOADED  -38   /*0xFFFFFFDA*/
 #define QSEOS_RESULT_FAIL_UNSUPPORTED_CE_PIPE -63
 #define QSEOS_RESULT_FAIL_KS_OP               -64
 #define QSEOS_RESULT_FAIL_KEY_ID_EXISTS       -65
diff --git a/include/soc/qcom/socinfo.h b/include/soc/qcom/socinfo.h
index e7d42ce..d4ebb7d 100644
--- a/include/soc/qcom/socinfo.h
+++ b/include/soc/qcom/socinfo.h
@@ -110,10 +110,14 @@
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sda670")
 #define early_machine_is_sdm710()	\
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sdm670")
+#define early_machine_is_sxr1120()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,sxr1120")
 #define early_machine_is_msm8953()	\
 	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_msm8917()	\
+	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,msm8917")
 #define early_machine_is_mdm9607()      \
 	of_flat_dt_is_compatible(of_get_flat_dt_root(), "qcom,mdm9607")
 #define early_machine_is_sdm450()	\
@@ -175,8 +179,10 @@
 #define early_machine_is_qcs605()	0
 #define early_machine_is_sda670()	0
 #define early_machine_is_sdm710()	0
+#define early_machine_is_sxr1120()	0
 #define early_machine_is_msm8953()	0
 #define early_machine_is_msm8937()	0
+#define early_machine_is_msm8917()	0
 #define early_machine_is_sdm450()	0
 #define early_machine_is_sdm632()	0
 #define early_machine_is_sdm439()	0
@@ -250,11 +256,13 @@
 	MSM_CPU_QCS605,
 	MSM_CPU_SDA670,
 	MSM_CPU_SDM710,
+	MSM_CPU_SXR1120,
 	MSM_CPU_8953,
 	MSM_CPU_SDM450,
 	MSM_CPU_SDM632,
 	MSM_CPU_SDA632,
 	MSM_CPU_8937,
+	MSM_CPU_8917,
 	MSM_CPU_9607,
 	MSM_CPU_SDM439,
 	MSM_CPU_SDM429,
diff --git a/include/uapi/linux/qg-profile.h b/include/uapi/linux/qg-profile.h
index bffddbb..0230b32 100644
--- a/include/uapi/linux/qg-profile.h
+++ b/include/uapi/linux/qg-profile.h
@@ -55,6 +55,8 @@
 #define QG_MAX_FCC_MAH				16000
 #define QG_MIN_SLOPE				1
 #define QG_MAX_SLOPE				50000
+#define QG_ESR_SF_MIN				5000
+#define QG_ESR_SF_MAX				20000
 
 /*  IOCTLs to query battery profile data */
 #define BPIOCXSOC	_IOWR('B', 0x01, struct battery_params) /* SOC */
diff --git a/include/uapi/linux/qg.h b/include/uapi/linux/qg.h
index 2194e1f..40882a7 100644
--- a/include/uapi/linux/qg.h
+++ b/include/uapi/linux/qg.h
@@ -19,7 +19,7 @@
 	QG_ESR_CHARGE_SF,
 	QG_ESR_DISCHARGE_SF,
 	QG_FULL_SOC,
-	QG_RESERVED_8,
+	QG_CLEAR_LEARNT_DATA,
 	QG_RESERVED_9,
 	QG_RESERVED_10,
 	QG_MAX,
@@ -32,6 +32,7 @@
 #define QG_ESR_CHARGE_SF QG_ESR_CHARGE_SF
 #define QG_ESR_DISCHARGE_SF QG_ESR_DISCHARGE_SF
 #define QG_FULL_SOC QG_FULL_SOC
+#define QG_CLEAR_LEARNT_DATA QG_CLEAR_LEARNT_DATA
 
 struct fifo_data {
 	unsigned int			v;
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index 0469d80..d6a0b0f 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -478,8 +478,6 @@
 	val = c->default_value;
 
 	for_each_cpu(cpu, mask) {
-		if (cpu_isolated(cpu))
-			continue;
 
 		switch (c->type) {
 		case PM_QOS_MIN:
diff --git a/kernel/trace/ipc_logging_debug.c b/kernel/trace/ipc_logging_debug.c
index 7a4c630..3a13ef3 100644
--- a/kernel/trace/ipc_logging_debug.c
+++ b/kernel/trace/ipc_logging_debug.c
@@ -78,17 +78,16 @@
 	struct dentry *d = file->f_path.dentry;
 	char *buffer;
 	int bsize;
-	int srcu_idx;
 	int r;
 
-	r = debugfs_use_file_start(d, &srcu_idx);
+	r = debugfs_file_get(d);
 	if (!r) {
 		ilctxt = file->private_data;
 		r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
-	}
-	debugfs_use_file_finish(srcu_idx);
-	if (r)
+	} else {
 		return r;
+	}
+	debugfs_file_put(d);
 
 	buffer = kmalloc(count, GFP_KERNEL);
 	if (!buffer) {
@@ -119,18 +118,17 @@
 	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);
+	r = debugfs_file_get(d);
 	if (!r) {
 		ilctxt = file->private_data;
 		r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
-	}
-	debugfs_use_file_finish(srcu_idx);
-	if (r)
+	} else {
 		return r;
+	}
+	debugfs_file_put(d);
 
 	if (copy_from_user(local_buf, buff, bsize)) {
 		count = -EFAULT;
@@ -172,17 +170,16 @@
 	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);
+	r = debugfs_file_get(d);
 	if (!r) {
 		ilctxt = file->private_data;
 		r = kref_get_unless_zero(&ilctxt->refcount) ? 0 : -EIO;
-	}
-	debugfs_use_file_finish(srcu_idx);
-	if (r)
+	} else {
 		return r;
+	}
+	debugfs_file_put(d);
 
 	bsize = simple_read_from_buffer(buff, count, ppos,
 				ilctxt->disabled?"1\n":"0\n", bsize);
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index 37641d1..640818c 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -269,7 +269,6 @@
 
 config DEBUG_FS
 	bool "Debug Filesystem"
-	select SRCU
 	help
 	  debugfs is a virtual file system that kernel developers use to put
 	  debugging files into.  Enable this option to be able to read and
diff --git a/scripts/build-all.py b/scripts/build-all.py
index bd468cd..4a60ebc 100755
--- a/scripts/build-all.py
+++ b/scripts/build-all.py
@@ -59,12 +59,8 @@
 
 def check_kernel():
     """Ensure that PWD is a kernel directory"""
-    have_defconfig = any([
-        os.path.isfile('arch/arm64/configs/msm_defconfig'),
-        os.path.isfile('arch/arm64/configs/sdm845_defconfig')])
-
-    if not all([os.path.isfile('MAINTAINERS'), have_defconfig]):
-        fail("This doesn't seem to be an MSM kernel dir")
+    if not os.path.isfile('MAINTAINERS'):
+        fail("This doesn't seem to be a kernel dir")
 
 def check_build():
     """Ensure that the build directory is present."""