Merge "usb: ehci: Add snapshot of EHCI msm driver"
diff --git a/Documentation/devicetree/bindings/arm/coresight.txt b/Documentation/devicetree/bindings/arm/coresight.txt
index 3a96610..bda03f0 100644
--- a/Documentation/devicetree/bindings/arm/coresight.txt
+++ b/Documentation/devicetree/bindings/arm/coresight.txt
@@ -1,12 +1,222 @@
 * CoreSight Components:
 
 CoreSight components are compliant with the ARM CoreSight architecture
-specification and can be connected in various topologies to suit a particular
-SoCs tracing needs. These trace components can generally be classified as
-sinks, links and sources. Trace data produced by one or more sources flows
-through the intermediate links connecting the source to the currently selected
-sink. Each CoreSight component device should use these properties to describe
-its hardware characteristcs.
+specification and can be connected in various topologies to suite a particular
+SoCs tracing needs. These trace components can generally be classified as sinks,
+links and sources. Trace data produced by one or more sources flows through the
+intermediate links connecting the source to the currently selected sink. Each
+CoreSight component device should use these properties to describe its hardware
+characteristcs.
+
+Required properties:
+
+- compatible : name of the component used for driver matching, should be one of
+	the following:
+	"arm,coresight-tmc" for coresight tmc-etr or tmc-etf device,
+	"arm,coresight-tpiu" for coresight tpiu device,
+	"qcom,coresight-replicator" for coresight replicator device,
+	"arm,coresight-funnel" for coresight funnel devices,
+	"qcom,coresight-tpda" for coresight tpda device,
+	"qcom,coresight-tpdm" for coresight tpdm device,
+	"qcom,coresight-dbgui" for coresight dbgui device
+	"arm,coresight-stm" for coresight stm trace device,
+	"arm,coresight-etm" for coresight etm trace devices,
+	"arm,coresight-etmv4" for coresight etmv4 trace devices,
+	"qcom,coresight-csr" for coresight csr device,
+	"arm,coresight-cti" for coresight cti devices,
+	"qcom,coresight-hwevent" for coresight hardware event devices
+	"arm,coresight-fuse" for coresight fuse v1 device,
+	"arm,coresight-fuse-v2" for coresight fuse v2 device,
+	"arm,coresight-fuse-v3" for coresight fuse v3 device,
+	"qcom,coresight-remote-etm" for coresight remote processor etm trace device,
+	"qcom,coresight-qpdi" for coresight qpdi device
+- reg : physical base address and length of the register set(s) of the component.
+	Not required for the following compatible string:
+	- "qcom,coresight-remote-etm"
+- reg-names : names corresponding to each reg property value.
+	Not required for the following compatible string:
+	- "qcom,coresight-remote-etm"
+	The reg-names that need to be used with corresponding compatible string
+	for a coresight device are:
+	- for coresight tmc-etr or tmc-etf device:
+		compatible : should be "arm,coresight-tmc"
+		reg-names  : should be:
+			"tmc-base" - physical base address of tmc configuration
+				registers
+			"bam-base" - physical base address of tmc-etr bam registers
+	- for coresight tpiu device:
+		compatible : should be "arm,coresight-tpiu"
+		reg-names  : should be:
+			"tpiu-base" - physical base address of tpiu registers
+	- for coresight replicator device
+		compatible : should be "qcom,coresight-replicator"
+		reg-names  : should be:
+			"replicator-base" - physical base address of replicator
+				registers
+	- for coresight funnel devices
+		compatible : should be "arm,coresight-funnel"
+		reg-names  : should be:
+			"funnel-base" - physical base address of funnel registers
+	- for coresight tpda trace device
+		compatible : should be "qcom,coresight-tpda"
+		reg-names  : should be:
+			"tpda-base" - physical base address of tpda registers
+	- for coresight tpdm trace device
+		compatible : should be "qcom,coresight-tpdm"
+		reg-names  : should be:
+			"tpdm-base" - physical base address of tpdm registers
+	- for coresight dbgui device:
+		compatible : should be "qcom,coresight-dbgui"
+		reg-names  : should be:
+			"dbgui-base" - physical base address of dbgui registers
+	- for coresight stm trace device
+		compatible : should be "arm,coresight-stm"
+		reg-names  : should be:
+			"stm-base" - physical base address of stm configuration
+				registers
+			"stm-data-base" - physical base address of stm data registers
+	- for coresight etm trace devices
+		compatible : should be "arm,coresight-etm"
+		reg-names  : should be:
+			"etm-base" - physical base address of etm registers
+	- for coresight etmv4 trace devices
+		compatible : should be "arm,coresight-etmv4"
+		reg-names  : should be:
+			"etm-base" - physical base address of etmv4 registers
+	- for coresight csr device:
+		compatible : should be "qcom,coresight-csr"
+		reg-names  : should be:
+			"csr-base" - physical base address of csr registers
+	- for coresight cti devices:
+		compatible : should be "arm,coresight-cti"
+		reg-names  : should be:
+			"cti<num>-base" - physical base address of cti registers
+	- for coresight hardware event devices:
+		compatible : should be "qcom,coresight-hwevent"
+		reg-names  : should be:
+			"<ss-mux>" - physical base address of hardware event mux
+				control registers where <ss-mux> is subsystem mux it
+				represents
+	- for coresight fuse device:
+		compatible : should be "arm,coresight-fuse"
+		reg-names  : should be:
+			"fuse-base" - physical base address of fuse registers
+			"nidnt-fuse-base" - physical base address of nidnt fuse registers
+			"qpdi-fuse-base" - physical base address of qpdi fuse registers
+	- for coresight qpdi device:
+		compatible : should be "qcom,coresight-qpdi"
+		reg-names  : should be:
+			"qpdi-base" - physical base address of qpdi registers
+- coresight-id : unique integer identifier for the component
+- coresight-name : unique descriptive name of the component
+- coresight-nr-inports : number of input ports on the component
+
+Optional properties:
+
+- coresight-outports : list of output port numbers of this component
+- coresight-child-list : list of phandles pointing to the children of this
+			 component
+- coresight-child-ports : list of input port numbers of the children
+- coresight-default-sink : represents the default compile time CoreSight sink
+- coresight-ctis : list of ctis that this component interacts with
+- qcom,cti-save : boolean, indicating cti context needs to be saved and restored
+- qcom,cti-hwclk : boolean, indicating support of hardware clock to access cti
+		   registers to be saved and restored
+- qcom,cti-gpio-trigin : cti trigger input driven by gpio
+- qcom,cti-gpio-trigout : cti trigger output sent to gpio
+- qcom,pc-save : program counter save implemented
+- qcom,blk-size : block size for tmc-etr to usb transfers
+- qcom,memory-size : size of coherent memory to be allocated for tmc-etr buffer
+- qcom,round-robin : indicates if per core etms are allowed round-robin access
+		     by the funnel
+- qcom,write-64bit : only 64bit data writes supported by stm
+- qcom,data-barrier : barrier required for every stm data write to channel space
+- <supply-name>-supply: phandle to the regulator device tree node. The required
+			<supply-name> is "vdd" for SD card and "vdd-io" for SD
+			I/O supply. Used for tpiu component
+- qcom,<supply>-voltage-level : specifies voltage level for vdd supply. Should
+				be specified in pairs (min, max) with units
+				being uV. Here <supply> can be "vdd" for SD card
+				vdd supply or "vdd-io" for SD I/O vdd supply.
+- qcom,<supply>-current-level : specifies current load levels for vdd supply.
+				Should be specified in pairs (lpm, hpm) with
+				units being uA. Here <supply> can be "vdd" for
+				SD card vdd supply or "vdd-io" for SD I/O vdd
+				supply.
+- qcom,hwevent-clks : list of clocks required by hardware event driver
+- qcom,hwevent-regs : list of regulators required by hardware event driver
+- qcom,byte-cntr-absent : specifies if the byte counter feature is absent on
+			  the device. Only relevant in case of tmc-etr device.
+- interrupts : <a b c> where a is 0 or 1 depending on if the interrupt is
+		spi/ppi, b is the interrupt number and c is the mask,
+- interrupt-names : a list of strings that map in order to the list of
+		    interrupts specified in the 'interrupts' property.
+- qcom,sg-enable : indicates whether scatter gather feature is supported for TMC
+		   ETR configuration.
+- qcom,force-reg-dump : boolean, indicate whether TMC register need to be dumped.
+			Used for TMC component
+- qcom,nidntsw : boolean, indicating NIDnT software debug or trace support
+		 present. Used for tpiu component
+- qcom,nidnthw : boolean, indicating NIDnT hardware sensing support present.
+		 Used for tpiu component
+  qcom,nidntsw and qcom,nidnthw are mutually exclusive properties, either of
+  these may specified for tpiu component
+- qcom,nidnt-swduart : boolean, indicating NIDnT swd uart support present. Used
+		       for tpiu component
+- qcom,nidnt-swdtrc : boolean, indicating NIDnT swd trace support present. Used
+		      for tpiu component
+- qcom,nidnt-jtag : boolean, indicating NIDnT jtag debug support present. Used
+		    for tpiu component
+- qcom,nidnt-spmi : boolean, indicating NIDnT spmi debug support present. Used
+		    for tpiu component
+- nidnt-gpio : specifies gpio for NIDnT hardware detection
+- nidnt-gpio-polarity : specifies gpio polarity for NIDnT hardware detection
+- pinctrl-names : names corresponding to the numbered pinctrl. The allowed
+		  names are subset of the following: cti-trigin-pctrl,
+		  cti-trigout-pctrl. Used for cti component
+- pinctrl-<n>: list of pinctrl phandles for the different pinctrl states. Refer
+	       to "Documentation/devicetree/bindings/pinctrl/pinctrl-bindings.txt".
+- qcom,funnel-save-restore : boolean, indicating funnel port needs to be disabled
+			     for the ETM whose CPU is being powered down. The port
+			     state is restored when CPU is powered up. Used for
+			     funnel component.
+- qcom,tmc-flush-powerdown : boolean, indicating trace data needs to be flushed before
+			     powering down CPU. Used for TMC component.
+- qcom,bc-elem-size : specifies the BC element size supported by each monitor
+		      connected to the aggregator on each port. Should be specified
+		      in pairs (port, bc element size).
+- qcom,tc-elem-size : specifies the TC element size supported by each monitor
+		      connected to the aggregator on each port. Should be specified
+		      in pairs (port, tc element size).
+- qcom,dsb-elem-size : specifies the DSB element size supported by each monitor
+		       connected to the aggregator on each port. Should be specified
+		       in pairs (port, dsb element size).
+- qcom,cmb-elem-size : specifies the CMB element size supported by each monitor
+		       connected to the aggregator on each port. Should be specified
+		       in pairs (port, cmb element size).
+- qcom,clk-enable: specifies whether additional clock bit needs to be set for
+		   M4M TPDM.
+- qcom,tpda-atid : specifies the ATID for TPDA.
+- qcom,inst-id : QMI instance id for remote ETMs.
+- qcom,noovrflw-enable : boolean, indicating whether no overflow bit needs to be
+			 set in ETM stall control register.
+- coresight-cti-cpu : cpu phandle for cpu cti, required when qcom,cti-save is true
+- coresight-etm-cpu : specifies phandle for the cpu associated with the ETM device
+- qcom,dbgui-addr-offset : indicates the offset of dbgui address registers
+- qcom,dbgui-data-offset : indicates the offset of dbgui data registers
+- qcom,dbgui-size : indicates the size of dbgui address and data registers
+- qcom,pmic-carddetect-gpio : indicates the hotplug capabilities of the qpdi driver
+- qcom,cpuss-debug-cgc: debug clock gating phandle for etm
+	reg : the clock gating register for each cluster
+	cluster : indicate the cluster number
+
+coresight-outports, coresight-child-list and coresight-child-ports lists will
+be of the same length and will have a one to one correspondence among the
+elements at the same list index.
+
+coresight-default-sink must be specified for one of the sink devices that is
+intended to be made the default sink. Other sink devices must not have this
+specified. Not specifying this property on any of the sinks is invalid.
 
 * Required properties for all components *except* non-configurable replicators:
 
diff --git a/Documentation/devicetree/bindings/arm/msm/acpuclock/clock-a7.txt b/Documentation/devicetree/bindings/arm/msm/acpuclock/clock-a7.txt
new file mode 100644
index 0000000..dc7966a
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/acpuclock/clock-a7.txt
@@ -0,0 +1,43 @@
+* Qualcomm Application CPU clock driver
+
+clock-a7 is the driver for the Root Clock Generator (rcg) hw which controls
+the cpu rate. RCGs support selecting one of several clock inputs, as well as
+a configurable divider. This hw is different than normal rcgs in that it may
+optionally have a register which encodes the maximum rate supported by hw.
+
+Required properties:
+- compatible: "qcom,clock-a53-8916", "qcom,clock-a7-9650",
+		"qcom,clock-a7-mdm9607", "qcom,clock-a7-sdx20"
+- reg: pairs of physical address and region size
+- reg-names: "rcg-base" is expected
+- clock-names: list of names of clock inputs
+- qcom,speedX-bin-vZ:
+		A table of CPU frequency (Hz) to regulator voltage (uV) mapping.
+		Format: <freq uV>
+		This represents the max frequency possible for each possible
+		power configuration for a CPU that's binned as speed bin X,
+		speed bin revision Z. Speed bin values can be between [0-7]
+		and the version can be between [0-3].
+
+- cpu-vdd-supply: regulator phandle for cpu power domain.
+
+Optional properties:
+- reg-names: "efuse", "efuse1"
+- qcom,safe-freq: Frequency in HZ
+	     When switching rates from A to B, the mux div clock will
+             instead switch from A -> safe_freq -> B.
+- qcom,enable-opp: This will allow to register the cpu clock with OPP
+	     framework.
+
+Example:
+	qcom,acpuclk@f9011050 {
+		compatible = "qcom,clock-a7-8226";
+		reg = <0xf9011050 0x8>;
+		reg-names = "rcg_base";
+		cpu-vdd-supply = <&apc_vreg_corner>;
+
+		clock-names = "clk-4", "clk-5";
+		qcom,speed0-bin-v0 =
+			<384000000 1150000>,
+			<600000000 1200000>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
index 4afbb24b..37718e1 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-controller.txt
@@ -1,6 +1,6 @@
-Qualcomm Technologies MSM Clock controller
+Qualcomm Technologies, Inc. MSM Clock controller
 
-Qualcomm Technologies MSM Clock controller devices contain PLLs, root clock
+Qualcomm Technologies, Inc. MSM Clock controller devices contain PLLs, root clock
 generators and other clocking hardware blocks that provide stable, low power
 clocking to hardware blocks on Qualcomm Technologies SOCs. The clock controller
 device node lists the power supplies needed to be scaled using the vdd_*-supply
@@ -12,8 +12,10 @@
 Required properties:
 - compatible:           Must be one of following,
 			"qcom,gcc-8953"
+			"qcom,gcc-8909"
 			"qcom,gcc-sdm632"
 			"qcom,cc-debug-8953"
+			"qcom,cc-debug-8909"
 			"qcom,cc-debug-sdm632"
 			"qcom,gcc-mdss-8953"
 			"qcom,gcc-mdss-sdm632"
@@ -28,6 +30,8 @@
 			"qcom,gcc-8920"
 			"qcom,gcc-spm-8952"
 			"qcom,gcc-spm-8937"
+			"qcom,rpmcc-8909"
+			"qcom,rpmcc-8909-pm660"
 			"qcom,cc-debug-8952"
 			"qcom,cc-debug-8953"
 			"qcom,cc-debug-8937"
@@ -36,12 +40,18 @@
 			"qcom,cc-debug-8920"
 			"qcom,gcc-mdss-8953"
 			"qcom,gcc-mdss-8952"
+			"qcom,gcc-mdss-8909"
 			"qcom,gcc-mdss-8937"
 			"qcom,gcc-mdss-8917"
 			"qcom,gcc-mdss-8940"
 			"qcom,gcc-mdss-8920"
 			"qcom,gcc-gfx-8953"
 			"qcom,gcc-gfx-sdm450"
+			"qcom,gcc-mdm9607"
+			"qcom,cc-debug-mdm9607"
+			"qcom,gcc-9650"
+			"qcom,cc-debug-9650"
+			"qcom,gcc-sdx20"
 
 - reg:                  Pairs of physical base addresses and region sizes of
                         memory mapped registers.
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt b/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt
index d9e1510..5d570d0 100644
--- a/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt
+++ b/Documentation/devicetree/bindings/arm/msm/clock-cpu-8939.txt
@@ -1,4 +1,4 @@
-Qualcomm Technology MSM8939 CPU clock tree
+Qualcomm Technologies, Inc. MSM8939 CPU clock tree
 
 clock-cpu-8939 is a device that represents the MSM8939 or MSM8952 CPU
 subsystem clock tree. It lists the various power supplies that need to be
diff --git a/Documentation/devicetree/bindings/arm/msm/clock-cpu-sdm632.txt b/Documentation/devicetree/bindings/arm/msm/clock-cpu-sdm632.txt
new file mode 100644
index 0000000..2d89614
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/clock-cpu-sdm632.txt
@@ -0,0 +1,94 @@
+Qualcomm Technologies, Inc SDM632 CPU clock driver
+
+clock-cpu-sdm632 is a device that represents the SDM632 CPU subystem clock
+tree. It lists the various power supplies that need to be scaled when the
+clocks are scaled and also other HW specific parameters like fmax tables etc.
+
+The root clock generator could have the ramp controller in built.
+Ramp control will allow programming the sequence ID for pulse swallowing,
+enable sequence and for linking sequence IDs.
+
+Required properties:
+- compatible:		Must be "qcom,clock-cpu-sdm632".
+
+- reg:			Pairs of physical base addresses and region sizes of
+			memory mapped registers.
+- reg-names:		Names of the bases for the above registers. Expected
+			bases are:
+			"apcs-c1-pll-base", "apcs-c0-pll-base",
+			"apcs-cci-pll-base", "apcs-c1-rcg-base",
+			"apcs-c0-rcg-base", "apcs-cci-rcg-base",
+			"efuse", "rcgwr-c0-base(optional)",
+			"rcgwr-c1-base(optional)".
+- clocks:		The clocks sources used by the cluster/cci mux.
+- clock-names:		Name of the clocks for the above clocks.
+- vdd-mx-supply:	The regulator powering all the PLLs of clusters & cci.
+- vdd-c0-supply:	The regulator powering the cluster 0.
+- vdd-c1-supply:	The regulator powering the cluster 1.
+- vdd-cci-supply:	The regulator powering the CCI cluster.
+
+- qcom,speedX-bin-vY-ZZZ:
+			A table of CPU frequency (Hz) to voltage (corner)
+			mapping that represents the max frequency possible
+			for each supported voltage level for a CPU. 'X' is
+			the speed bin into which the device falls into - a
+			bin will have unique frequency-voltage relationships.
+			'Y' is the characterization version, implying that
+			characterization (deciding what speed bin a device
+			falls into) methods and/or encoding may change. The
+			values 'X' and 'Y' are read from efuse registers, and
+			the right table is picked from multiple possible tables.
+			'ZZZ' can be cl for(c0 & c1) or cci depending on whether
+			the table for the clusters or cci.
+
+Example:
+	clock_cpu {
+		compatible = "qcom,cpu-clock-sdm632";
+		reg =   <0xb114000  0x68>,
+			<0xb014000  0x68>,
+			<0xb016000  0x8>,
+			<0xb116000  0x8>,
+			<0xb1d0000  0x8>,
+			<0xb011050  0x8>,
+			<0xb111050  0x8>,
+			<0xb1d1050  0x8>,
+			<0x00a412c  0x8>;
+		reg-names = "rcgwr-c0-base", "rcgwr-c1-base",
+			    "apcs-c1-pll-base", "apcs-c0-pll-base",
+			    "apcs-cci-pll-base", "apcs-c1-rcg-base",
+			    "apcs-c0-rcg-base", "apcs-cci-rcg-base",
+			    "efuse";
+		qcom,num-clusters = <2>;
+		vdd-mx-supply = <&pm8953_s7_level_ao>;
+		vdd-c0-supply = <&apc_vreg_corner>;
+		vdd-c1-supply = <&apc_vreg_corner>;
+		vdd-cci-supply = <&apc_vreg_corner>;
+		clocks = <&clock_gcc clk_xo_a_clk_src>;
+		clock-names = "xo_a";
+		qcom,speed0-bin-v0-c0 =
+			<          0 0>,
+			<   614400000 1>,
+			<   883200000 2>,
+			<  1036200000 3>,
+			<  1363200000 4>,
+			<  1563000000 5>,
+			<  1670400000 6>,
+			<  1785600000 7>;
+		qcom,speed0-bin-v0-c1 =
+			<          0 0>,
+			<   633600000 1>,
+			<   902400000 2>,
+			<  1094400000 3>,
+			<  1401600000 4>,
+			<  1555200000 5>,
+			<  1785600000 6>;
+		qcom,speed0-bin-v0-cci =
+			<          0 0>,
+			<  307200000 1>,
+			<  403200000 2>,
+			<  499200000 3>,
+			<  691200000 4>,
+			<  768000000 5>,
+			<  787200000 6>;
+		#clock-cells = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/core_sleep_status.txt b/Documentation/devicetree/bindings/arm/msm/core_sleep_status.txt
new file mode 100644
index 0000000..56fa470
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/core_sleep_status.txt
@@ -0,0 +1,49 @@
+* MSM Sleep status
+
+MSM Sleep status device is used to check the power collapsed status of a
+offlined core. The core that initiates the hotplug would wait on the
+sleep status device before CPU_DEAD notifications are sent out. Some hardware
+devices require that the offlined core is power collapsed before turning off
+the resources that are used by the offlined core.
+
+The required properties of core sleep status node are:
+- compatible: qcom,cpu-sleep-status
+
+The required properties of sleep status node are:
+- reg: physical address of the sleep status register for the cpus
+- qcom,cpu-sleep-status-mask - The bit mask within the status register that
+	indicates the Core's sleep state.
+
+Example:
+	qcom,cpu-sleep-status {
+		compatible = "qcom,cpu-sleep-status";
+	};
+
+	cpus {
+		#address-cells = <2>;
+		#size-cells = <0>;
+
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			compatible = "qcom,kryo";
+
+			qcom,sleep-status = <&cpu0_slp_sts>;
+		};
+
+		CPU1: cpu@1 {
+			device_type = "cpu";
+			compatible = "qcom,kryo";
+
+			qcom,sleep-status = <&cpu1_slp_sts>;
+		};
+	};
+
+	cpu0_slp_sts: cpu-sleep-status@9981058 {
+		reg = <0x9981058 0x100>;
+		qcom,sleep-status-mask = <0xc00000>;
+	};
+
+	cpu1_slp_sts: cpu-sleep-status@9991058 {
+		reg = <0x9991058 0x100>;
+		qcom,sleep-status-mask = <0xc00000>;
+	}
diff --git a/Documentation/devicetree/bindings/arm/msm/glink_bgcom_xprt.txt b/Documentation/devicetree/bindings/arm/msm/glink_bgcom_xprt.txt
new file mode 100644
index 0000000..d034bb8
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/glink_bgcom_xprt.txt
@@ -0,0 +1,33 @@
+Qualcomm Technologies, Inc. G-link bgcom Transport
+
+Required properties:
+-compatible : should be "qcom,glink-bgcom-xprt".
+-label : the name of the subsystem this link connects to.
+
+Optional properties:
+-qcom,qos-config: Reference to the qos configuration elements.It depends on
+		ramp-time.
+-qcom,ramp-time: Worst case time in microseconds to transition to this power
+		state. Power states are numbered by array index position.
+
+Example:
+
+	qcom,glink-bgcom-xprt-bg {
+		compatible = "qcom,glink-bgcom-xprt";
+		label = "bg";
+		qcom,qos-config = <&glink_qos_bg>;
+		qcom,ramp-time = <0x10>,
+				     <0x20>,
+				     <0x30>,
+				     <0x40>;
+	};
+
+	glink_qos_bg: qcom,glink-qos-config-bg {
+		compatible = "qcom,glink-qos-config";
+		qcom,flow-info = <0x80 0x0>,
+				 <0x70 0x1>,
+				 <0x60 0x2>,
+				 <0x50 0x3>;
+		qcom,mtu-size = <0x800>;
+		qcom,tput-stats-cycle = <0xa>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt b/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt
new file mode 100644
index 0000000..9fc2031
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/jtag-fuse.txt
@@ -0,0 +1,22 @@
+* JTAG-FUSE
+
+The jtag-fuse entry specifies the memory mapped addresses for the fuse
+registers. The jtag-fuse driver uses these to provide api(s) that can be used
+by jtag save and restore driver(s) to query whether the Hardware they manage
+is functionally disabled or not and take corresponding steps.
+
+Required Properties:
+compatible: component name used for driver matching, should be one of the
+	following:
+	"qcom,jtag-fuse" for jtag fuse device
+	"qcom,jtag-fuse-v2" for jtag fuse v2 device
+	"qcom,jtag-fuse-v3" for jtag fuse v3 device
+reg: physical base address and length of the register set
+reg-names: should be "fuse-base"
+
+Example:
+	jtag_fuse: jtagfuse@fc4be024 {
+		compatible = "qcom,jtag-fuse";
+		reg = <0xfc4be024 0x8>;
+		reg-names = "fuse-base";
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-workarounds.txt b/Documentation/devicetree/bindings/arm/msm/lpm-workarounds.txt
new file mode 100644
index 0000000..0304035
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-workarounds.txt
@@ -0,0 +1,55 @@
+* LPM Workarounds
+
+The required properties are:
+
+- compatible: "qcom,lpm-workarounds"
+
+The optional properties are:
+- reg: The physical address and the size of the l1_l2_gcc and l2_pwr_sts
+	regitsters of performance cluster.
+
+- reg-names: "l2_pwr_sts" - string to identify l2_pwr_sts physical address.
+	     "l1_l2_gcc" - string to identify l1_l2_gcc physical address.
+
+- qcom,lpm-wa-cx-turbo-unvote: Indicates the workaround to unvote CX turbo
+	vote when system is coming out of rpm assisted power collaspe.
+	lpm-cx-supply is required if this is present.
+
+- lpm-cx-supply:  will hold handle for CX regulator supply which is used
+	to unvote.
+
+- qcom,lpm-wa-skip-l2-spm: Due to a hardware bug on 8939 and 8909, secure
+	world needs to disable and enable L2 SPM to get the proper context
+	in secure watchdog bite cases. With this workaround there is a race
+	in programming L2 SPM between HLOS and secure world. This leads to
+	stability issues. To avoid this program L2 SPM only in secure world
+	based on the L2 mode flag passed. Set lpm-wa-skip-l2-spm node if this
+	is required.
+
+- qcom,lpm-wa-dynamic-clock-gating: Due to a hardware bug on 8952, L1/L2 dynamic
+	clock gating needs to be enabled by software for performance cluster
+	cores and L2. Set lpm-wa-dynamic-clock-gating node if this workaround is
+	required.
+
+- qcom,cpu-offline-mask: Dynamic clock gating should be enabled when cluster is
+	in L2 PC. Each bit of cpu-offline-mask lists the cpu no. to hotplug by KTM
+	driver.
+
+- qcom,non-boot-cpu-index: will hold index of non boot cluster cpu.
+
+- qcom,l1-l2-gcc-secure: indicates L1/L2 clock enabling register is secure.
+
+Example:
+
+qcom,lpm-workarounds {
+	compatible = "qcom,lpm-workarounds";
+	reg = <0x0B011018 0x4>,
+	      <0x0B011088 0x4>;
+	reg-names = "l2-pwr-sts", "l1-l2-gcc";
+	lpm-cx-supply = <&pm8916_s2_corner>;
+	qcom,lpm-wa-cx-turbo-unvote;
+	qcom,lpm-wa-skip-l2-spm;
+	qcom,lpm-wa-dynamic-clock-gating;
+	qcom,cpu-offline-mask = "0xF";
+	qcom,non-boot-cpu-index = <4>;
+}
diff --git a/Documentation/devicetree/bindings/arm/msm/mpm.txt b/Documentation/devicetree/bindings/arm/msm/mpm.txt
new file mode 100644
index 0000000..c3535cb
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/mpm.txt
@@ -0,0 +1,77 @@
+* MSM Sleep Power Manager (mpm-v2)
+
+The MPM acts a sleep power manager to shutdown the clock source and put the
+device into a retention mode to save power. The MPM is also responsible for
+waking up and bringing up the resources from sleep. The MPM driver configures
+interrupts monitored by the MPM hardware before entering sleep through a
+RPM interface.
+
+The required nodes for the MPM driver are:
+
+- compatible: "qcom, mpm-v2"
+- reg: Specifies the base physical address(s) and the size of the MPM
+	registers. The MPM driver access two memory regions for confifure the
+	virtual MPM driver on the RPM. The first region is the memory space
+	shared with the virtual MPM driver. The second region is the address
+	to the register that triggers a interrupt to the RPM.
+- reg-names: "vmpm" - string to identify the shared memory space region
+	     "ipc" - string to identify the register that triggers a interrupt
+- clocks: clock identifers used by clock driver while looking up mpm clocks.
+- clock-names: name of the clock used by mpm driver.
+- qcom,ipc-bit-offset: The bit to set in the ipc register that triggers a interrupt
+	to the RPM
+- qcom,gic-parent: phandle to the gic interrupt controller
+- qcom,gic-map: Provides a mapping of how a GIC interrupt is connect to a MPM. The
+	mapping is presented in tuples. Each tuple represents a MPM pin and
+	which GIC interrupt is routed to it. Since MPM monitors interrupts
+	only during system wide low power mode, system interrupts originating
+	from other processors can be ignored and assigned an MPM pin mapping
+	of 0xff.
+- qcom,gpio-parent: phandle to the GPIO interrupt controller
+- qcom,gpio-map: Provides a mapping of how a GPIO interrupt is connect to a MPM. The
+	mapping is presented in tuples. Each tuple represents a MPM pin and
+	which GIC interrupt is routed to it. Since MPM monitors interrupts
+	only during system wide low power mode, system interrupts originating
+	from other processors can be ignored and assigned an MPM pin mapping
+	of 0xff.
+
+Optional Properties:
+
+- qcom,num-mpm-irqs : Specifies the number of mpm interrupts supported on a
+	target. If the property isn't present, 64 interrupts are
+	considered for the target by default.
+
+Example:
+	qcom,mpm@fc4281d0 {
+		compatible = "qcom,mpm-v2";
+		reg = <0xfc4281d0 0x1000>, /* MSM_RPM_MPM_BASE 4K*/
+		    <0xfa006000 0x1000>;   /* MSM_APCS_GCC_BASE 4K*/
+		reg-names = "vmpm", "ipc"
+			interrupts = <0 171 1>;
+		clocks = <&clock_rpm clk_xo_lpm_clk>;
+		clock-names = "xo";
+
+		qcom,ipc-bit-offset = <0>;
+
+		qcom,gic-parent = <&intc>;
+		qcom,gic-map = <25 132>,
+			<27 111>,
+			<0xff 48>,
+			<0xff 51>,
+			<0xff 52>,
+			<0xff 53>,
+			<0xff 54>,
+			<0xff 55>;
+
+		qcom,gpio-parent = <&msmgpio>;
+		qcom,gpio-map = <1  46>,
+			<2 150>,
+			<4 103>,
+			<5 104>,
+			<6 105>,
+			<7 106>,
+			<8 107>,
+			<53 37>,
+			<54 24>,
+			<55 14>;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/msm.txt b/Documentation/devicetree/bindings/arm/msm/msm.txt
index 1b8b7cf..47aabfd 100644
--- a/Documentation/devicetree/bindings/arm/msm/msm.txt
+++ b/Documentation/devicetree/bindings/arm/msm/msm.txt
@@ -119,6 +119,12 @@
 - MSM8937
   compatible = "qcom,msm8937"
 
+- SDM439
+  compatible = "qcom,sdm439"
+
+- SDM429
+  compatible = "qcom,sdm429"
+
 - MDM9640
   compatible = "qcom,mdm9640"
 
@@ -321,6 +327,12 @@
 compatible = "qcom,msm8937-qrd"
 compatible = "qcom,msm8937-pmi8950-qrd-sku1"
 compatible = "qcom,msm8937-pmi8937-qrd-sku2"
+compatible = "qcom,sdm429-cdp"
+compatible = "qcom,sdm429-mtp"
+compatible = "qcom,sdm429-qrd"
+compatible = "qcom,sdm439-cdp"
+compatible = "qcom,sdm439-mtp"
+compatible = "qcom,sdm439-qrd"
 compatible = "qcom,msm8953-rumi"
 compatible = "qcom,msm8953-sim"
 compatible = "qcom,msm8953-cdp"
diff --git a/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
new file mode 100644
index 0000000..de66152
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/msm_thermal.txt
@@ -0,0 +1,448 @@
+MSM thermal driver (MSM_THERMAL)
+
+MSM_THERMAL is a kernel platform driver which regulates thermal conditions
+on the device during kernel boot. The goal of MSM_THERMAL is to prevent the
+temperature of the system from exceeding a thermal limit at which it cannot
+operate. Examples are CPU junction thermal limit, or POP memory thermal limit.
+The MSM_THERMAL driver polls the TSENS sensor hardware during boot, and
+reduces the maximum CPU frequency allowed in steps, to limit power/thermal
+output when a threshold temperature is crossed. It restores the maximum CPU
+frequency allowed in the same stepwise fashion when the threshold temperature
+(with hysteresis gap) is cleared.
+
+The devicetree representation of the MSM_THERMAL block should be:
+
+Required properties
+
+- compatible: "qcom,msm-thermal"
+- qcom,sensor-id: The id of the TSENS sensor polled for temperature.
+			Typically the sensor closest to CPU0.
+- qcom,poll-ms: Sampling interval to read sensor, in ms.
+- qcom,limit-temp: Threshold temperature to start stepping CPU down, in degC.
+- qcom,temp-hysteresis: Degrees C below threshold temperature to step CPU up.
+- qcom,freq-step: Number of frequency steps to take on each CPU mitigation.
+
+Optional properties
+
+- reg:                  Physical address for uio mapping
+- qcom,core-limit-temp: Threshold temperature to start shutting down cores
+			in degC
+- qcom,core-temp-hysteresis: Degrees C below which the cores will be brought
+			online in sequence.
+- qcom,hotplug-temp: Threshold temperature to start shutting down cores
+			in degC. This will be used when polling based
+			core control is disabled. The difference between hotplug-temp
+			and core-limit-temp is that core-limit-temp is used during
+			early boot prior to thermal_sys being available for hotplug.
+- qcom,hotplug-temp-hysteresis: Degrees C below which thermal will not force the
+			cores to be offlined. Cores can be brought online if needed.
+- qcom,freq-mitigation-temp: Threshold temperature to mitigate
+			the CPU max frequency in degC. This will be
+			used when polling based frequency control is disabled.
+			The difference between freq-mitigation-temp
+			and limit-temp is that limit-temp is used during
+			early boot prior to thermal_sys being available for registering
+			temperature thresholds. Also, this emergency frequency
+			mitigation is a single step frequency mitigation to a predefined value
+			as opposed to the step by step frequency mitigation during boot-up.
+- qcom,freq-mitigation-temp-hysteresis: Degrees C below which thermal will not mitigate the
+			cpu max frequency.
+- qcom,freq-mitigation-value: The frequency value (in kHz) to which the thermal
+			should mitigate the CPU, when the freq-mitigation-temp
+			threshold is reached.
+- qcom,vdd-restriction-temp: When temperature is below this threshold, will
+			enable vdd restriction which will set higher voltage on
+			key voltage rails, in degC.
+- qcom,vdd-restriction-temp-hysteresis: When temperature is above this threshold
+			will disable vdd restriction on key rails, in degC.
+- qcom,pmic-sw-mode-temp: Threshold temperature to disable auto mode on the
+			rail, in degC. If this property exists,
+			qcom,pmic-sw-mode-temp-hysteresis and
+			qcom,pmic-sw-mode-regs need to exist, otherwise return error.
+- qcom,pmic-sw-mode-temp-hysteresis: Degree below threshold temperature to
+			enable auto mode on the rail, in degC. If this property exists,
+			qcom,pmic-sw-mode-temp and qcom,pmic-sw-mode-regs need to
+			exist, otherwise return error.
+- qcom,pmic-sw-mode-regs: Array of the regulator names that will want to
+			disable/enable automode based on the threshold. If this
+			property exists, qcom,pmic-sw-mode-temp and
+			qcom,pmic-sw-mode-temp-hysteresis need to exist, otherwise
+			return error. Also, if this property is defined, will have to
+			define <consumer_supply_name>-supply = <&phandle_of_regulator>
+- <consumer_supply_name>-supply = <&phandle_of_regulator>: consumer_supply_name
+			is the name that's defined in thermal driver.
+			phandle_of_regulator is defined by reuglator device tree.
+- qcom,online-hotplug-core: This property should be defined in targets where
+			KTM should online cores, which are hotplugged due to
+			thermal condition.
+- qcom,synchronous-cluster-id: This property specifies an array of synchronous cluster-ID's.
+			This property will be used by KTM to optimize the synchronous
+			cluster frequency update.
+- qcom,synchronous-cluster-map: This property specifies an array of cluster-ID,
+			number of cpus in that cluster and their corresponding cpu
+			phandles. This property should be defined in targets where
+			the kernel topology module is not present.
+			In the older kernel version, where the kernel topology module is
+			not available, KTM gets the mapping information from this property.
+- qcom,disable-vdd-mx:  If this property is defined, the feature VDD MX
+			restriction will be disabled. All other properties
+			corresponding to this feature will be ignored.
+- qcom,disable-vdd-rstr: If this property is defined, the feature VDD
+			restriction will be disabled. All other properties
+			corresponding to this feature will be ignored.
+- qcom,disable-sensor-info: If this property is defined, the feature sensor
+			alias info will be disabled. All other properties
+			corresponding to this feature will be ignored.
+- qcom,disable-ocr:     If this property is defined, the feature optimum current
+			request will be disabled. All other properties
+			corresponding to this feature will be ignored.
+- qcom,disable-psm:     If this property is defined, the feature PMIC software
+			mode will be disabled. All other properties
+			corresponding to this feature will be ignored.
+- qcom,disable-gfx-phase-ctrl: If this property is defined, the feature graphics
+			phase control will be disabled. All other properties
+			corresponding to this feature will be ignored.
+- qcom,disable-cx-phase-ctrl: If this property is defined, the feature
+			cx phase control will be disabled. All other properties
+			corresponding to this feature will be ignored.
+- qcom,therm-ddr-lm-info: If this optional property is defined, it enables
+			DDR frequency restriction feature. It expects array of
+			sensor id to be monitored, high threshold  and low threshold
+			for that sensor respectively.
+
+Optional child nodes
+- qcom,pmic-opt-curr-temp: Threshold temperature for requesting optimum current (request
+			dual phase) for rails with PMIC, in degC. If this property exists,
+			then the properties, qcom,pmic-opt-curr-temp-hysteresis and
+			qcom,pmic-opt-curr-regs should also be defined to enable this
+			feature.
+- qcom,pmic-opt-curr-temp-hysteresis: Degree below the threshold to disable the optimum
+			current request for a rail, in degC. If this property exists,
+			then the properties, qcom,pmic-opt-curr-temp and
+			qcom,pmic-opt-curr-regs should also be defined to enable
+			this feature.
+- qcom,pmic-opt-curr-regs: Name of the rails for which the optimum current should be
+			requested. If this property exists, then the properties,
+			qcom,pmic-opt-curr-temp and qcom,pmic-opt-curr-temp-hysteresis
+			should also be defined to enable this feature.
+- qcom,pmic-opt-curr-sensor-id: Sensor, which needs to be monitored for requesting OCR
+			when qcom,pmic-opt-curr-temp threshold is reached.
+			It is an optional property, if it is configured, msm_thermal will
+			monitor only this sensor, otherwise it will monitor all TSENS for
+			this feature. If this property exists, then the properties,
+			qcom,pmic-opt-curr-temp, qcom,pmic-opt-curr-temp-hysteresis and
+			qcom,pmic-opt-curr-regs should also be defined to enable this feature.
+- qcom,<vdd restriction child node name>: Define the name of the child node.
+			If this property exisits, qcom,vdd-rstr-reg, qcom,levels
+			need to exist. qcom,min-level is optional if qcom,freq-req
+			exists, otherwise it's required.
+- qcom,vdd-rstr-reg: Name of the rail
+- qcom,levels: Array of the level values. Unit is corner voltage for voltage request
+			or kHz for frequency request.
+- qcom,min-level: Request this level as minimum level when disabling voltage
+			restriction. Unit is corner voltage for voltage request.
+			This will not be required if qcom,freq-req exists.
+- qcom,freq-req: Flag to determine if we should restrict frequency on this rail
+			instead of voltage.
+- qcom,max-freq-level: Request this frequency as scaling maximum level when
+			enabling vdd restriction feature for a rail. This is
+			an optional property which is only applicable to the rail
+			with "qcom,freq-req" property set.
+- qcom,cx-phase-hot-crit-temp: Threshold temperature for sending the 'HOT_CRITICAL'
+			temperature band to RPM, in degC. This will aid RPM
+			in deciding the number of phases required for CX rail.
+			If this property exists, then the property,
+			qcom,cx-phase-hot-crit-temp-hyst should also be defined to
+			enable this feature.
+- qcom,cx-phase-hot-crit-temp-hyst: Degree below the threshold to send the 'WARM'
+			temperature band to RPM, in degC. This will aid RPM
+			in deciding the number of phases required for CX.
+			If this property exists, then the property,
+			qcom,cx-phase-hot-crit-temp should also be defined to enable
+			this feature.
+- qcom,cx-phase-resource-key: The key name to be used for sending the CX
+			temperature band message to RPM. This property should
+			be defined along with the other properties required for
+			CX phase selection feature.
+- qcom,gfx-phase-hot-crit-temp: Threshold temperature for sending the 'HOT_CRITICAL'
+			temperature band to RPM, in degC. This will aid RPM in
+			deciding the number of phases required for GFX rail.
+			If this property exists, then the properties,
+			qcom,gfx-phase-hot-crit-temp-hyst and qcom,gfx-sensor-id
+			should also be defined to enable this feature.
+- qcom,gfx-phase-hot-crit-temp-hyst: Degree below the threshold to clear the 'HOT_CRITICAL'
+			band and send the 'WARM' temperature band to RPM, in degC.
+			This will aid RPM in deciding the number of phases required
+			for GFX rail. If this property exists, then the properties,
+			qcom,gfx-phase-hot-crit-temp and qcom,gfx-sensor-id
+			should also be defined to enable this feature.
+- qcom,gfx-phase-warm-temp: Threshold temperature for sending the 'WARM' temperature
+			band to RPM, in degC. This will aid RPM in deciding the
+			number of phases required for GFX rail. If this property
+			exists, then the properties, qcom,gfx-sensor-id and
+			qcom,gfx-phase-warm-temp-hyst should also be defined to
+			enable this feature.
+- qcom,gfx-phase-warm-temp-hyst: Degree below the threshold to clear the 'WARM'
+			band and send the 'NORMAL' temperature band to RPM, in degC.
+			This will aid RPM in deciding the number of phases required
+			for GFX rail. If this property exists, then the property,
+			qcom,gfx-sensor-id and qcom,gfx-phase-warm-temp should also
+			be defined to enable this feature.
+-qcom,gfx-sensor-id:     The ID of the TSENS sensor, which is closest to graphics
+			processor, monitoring the GPU temperature. If this property
+			exists, then the property, qcom,gfx-phase-hot-crit-temp and
+			qcom,gfx-phase-hot-crit-temp-hyst or/and qcom,gfx-phase-warm-temp
+			and qcom,gfx-phase-warm-temp-hyst should also be defined to
+			enable this feature.
+- qcom,gfx-phase-resource-key: The key name to be used for sending the GFX temperature
+			band message to RPM. This property should be defined along
+			with the other properties required for GFX phase selection
+			feature.
+- qcom,rpm-phase-resource-type: The RPM resource type name to be used for sending
+			temperature bands for CX and GFX phase selection. This
+			property should be defined along with the other properties
+			required for CX and GFX phase selection feature.
+- qcom,rpm-phase-resource-id: The RPM resource ID to be used for sending temperature
+			bands for CX and GFX phase selection. This property should
+			be defined along with the other properties required for CX
+			and GFX phase selection feature.
+- qcom,mx-restriction-temp: Threshold temperature below which the module votes for
+			higher data retention voltage of MX and CX supply. If and only if this
+			property exists, then the property qcom,mx-restriction-temp-hysteresis,
+			qcom,mx-retention-min should also be present. Also, if this
+			property is defined, will have to define vdd-mx-supply =
+			<&phandle_of_regulator>
+- qcom,mx-restriction-temp-hysteresis: Degree above the threshold to remove MX and CX vote.
+			If this property exists, then the property qcom,mx-restriction-temp,
+			qcom,mx-retention-min should also be present.Also, if this
+			property is defined, will have to define vdd-mx-supply =
+			<&phandle_of_regulator>
+- qcom,mx-retention-min: Minimum data retention voltage to be applied to MX rail if
+			the low threshold is crossed. If this property exists, then the
+			property qcom,mx-restriction-temp and
+			qcom,mx-restriction-temp-hysteresis should also be present.
+			Also, if this property is defined, will have to define
+			vdd-mx-supply = <&phandle_of_regulator>
+- qcom,cx-retention-min: Minimum data retention voltage to be applied to CX rail if the low
+			threshold is crossed. If this property exists, then the property
+			qcom,mx-restriction-temp and qcom,mx-restriction-temp-hysteresis
+			should also be present. Also, if this property is defined, will
+			have to define vdd-cx-supply = <&phandle_of_regulator>.
+- qcom,mx-restriction-sensor_id: sensor id, which needs to be monitored for requesting MX/CX
+			retention voltage. If this optional property is defined, msm_thermal
+			will monitor only this sensor, otherwise by default it will monitor
+			all TSENS for this feature. If this property exists, then the properties,
+			qcom,mx-restriction-temp, qcom,mx-restriction-temp-hysteresis and
+			qcom,mx-retention-min should also be defined to enable this feature.
+- qcom,therm-reset-temp: Degree above which the KTM will initiate a secure watchdog reset.
+			When this property is defined, KTM will monitor all the tsens from
+			boot time and will initiate a secure watchdog reset if any of the
+			tsens temperature reaches this threshold. This reset helps in
+			generating more informative crash dumps opposed to the crash dump
+			generated by the hardware reset.
+
+Example:
+
+	qcom,msm-thermal {
+		compatible = "qcom,msm-thermal";
+		reg = <0x70000 0x1000>;
+		qcom,sensor-id = <0>;
+		qcom,poll-ms = <250>;
+		qcom,limit-temp = <60>;
+		qcom,temp-hysteresis = <10>;
+		qcom,freq-step = <2>;
+		qcom,therm-reset-temp = <115>;
+		qcom,core-limit-temp = <90>;
+		qcom,core-temp-hysteresis = <10>;
+		qcom,hotplug-temp = <110>;
+		qcom,hotplug-temp-hysteresis = <20>;
+		qcom,freq-mitigation-temp = <110>;
+		qcom,freq-mitigation-temp-hysteresis = <20>;
+		qcom,freq-mitigation-value = <960000>;
+		qcom,rpm-phase-resource-type = "misc";
+		qcom,rpm-phase-resource-id = <0>;
+		qcom,cx-phase-resource-key = "tmpc";
+		qcom,cx-phase-hot-crit-temp = <75>;
+		qcom,cx-phase-hot-crit-temp-hyst = <15>;
+		qcom,gfx-phase-warm-temp = <60>;
+		qcom,gfx-phase-warm-temp-hyst = <10>;
+		qcom,gfx-phase-hot-crit-temp = <85>;
+		qcom,gfx-phase-hot-crit-temp-hyst = <15>;
+		qcom,gfx-sensor-id = <4>;
+		qcom,gfx-phase-resource-key = "tmpg";
+		qcom,pmic-sw-mode-temp = <90>;
+		qcom,pmic-sw-mode-temp-hysteresis = <80>;
+		qcom,pmic-sw-mode-regs = "vdd-dig";
+		qcom,vdd-restriction-temp = <5>;
+		qcom,vdd-restriction-temp-hysteresis = <10>;
+		vdd-dig-supply=<&pm8841_s2_floor_corner>
+		qcom,mx-restriction-temp = <5>;
+		qcom,mx-restriction-temp-hysteresis = <10>;
+		qcom,mx-retention-min = <710000>;
+		qcom,mx-restriction-sensor_id = <2>;
+		vdd-mx-supply = <&pma8084_s1>;
+		qcom,cx-retention-min = <RPM_SMD_REGULATOR_LEVEL_RETENTION_PLUS>;
+		vdd-cx-supply = <&pmd9635_s5_level>;
+		qcom,online-hotplug-core;
+		qcom,therm-ddr-lm-info = <1 90 75>;
+		qcom,synchronous-cluster-id = <0 1>; /* Indicates cluster 0 and 1 are synchronous */
+		qcom,synchronous-cluster-map =  <0 2 &CPU0 &CPU1>,
+						<1 2 &CPU2 &CPU3>;
+		/* <cluster-ID, number of cores in cluster, cpu phandles>.
+		** In the above case, the cluster with ID 0 & 1 has 2 cores
+		** and their phandles are mentioned.
+		*/
+
+		qcom,vdd-dig-rstr{
+			qcom,vdd-rstr-reg = "vdd-dig";
+			qcom,levels = <5 7 7>; /* Nominal, Super Turbo, Super Turbo */
+			qcom,min-level = <1>; /* No Request */
+		};
+
+		qcom,vdd-apps-rstr{
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <1881600 1958400 2265600>;
+			qcom,freq-req;
+			qcom,max-freq-level = <1958400>;
+		};
+	};
+
+
+
+The sensor information node is an optional node that holds information
+about thermal sensors on a target. The information includes sensor type,
+sensor name, sensor alias and sensor scaling factor. The parent node
+name is qcom,sensor-information. It has a list of optional child
+nodes, each representing a sensor. The child node is named as
+qcom,sensor-information-<id>. The id takes values sequentially
+from 0 to N-1 where N is the number of sensors. This id doesn't
+relate to zone id or sensor id.
+
+The devicetree representation of sensor information node should be:
+
+1.0 Required properties:
+
+- compatible: "qcom,sensor-information"
+
+1.1 Optional nodes:
+
+qcom,sensor-information-<id>
+
+The below properties belong to the child node qcom,sensor-information-<id>.
+Following are the required and optional properties of a child node.
+
+1.1.a Required properties:
+
+- qcom,sensor-type: Type of a sensor. A sensor can be of type tsens,
+			alarm or adc.
+			tsens: 	Sensors that are on MSM die.
+			alarm: 	Sensors that are on PMIC die.
+			adc:   	Sensors that are usually thermistors
+				placed out of the die.
+- qcom,sensor-name: Name of a sensor as defined by low level sensor driver.
+
+1.1.b Optional properties:
+
+- qcom,alias-name: Alias name for a sensor. The alias name corresponds
+			to a device such as gpu/pop-mem whose temperature
+			is relative to the sensor temperature defined in the
+			child node. This node can not be used for providing
+			alias name for cpu devices. Thermal driver assigns the
+			cpu device alias, based on the sensor defined in the
+			cpu mitigation profile.
+- qcom,scaling-factor: The unit that needs to be multiplied to the
+			sensor temperature to get temperature unit in
+			degree centigrade. If this property is not
+			present, a default scaling factor of 1 is assigned
+			to a sensor.
+
+Example:
+
+	qcom,sensor-information {
+		compatible = "qcom,sensor-information";
+		sensor_information0: qcom,sensor-information-0 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor0";
+		};
+
+		sensor_information1: qcom,sensor-information-1 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor1";
+		};
+
+		sensor_information2: qcom,sensor-information-2 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor2";
+		};
+
+		sensor_information3: qcom,sensor-information-3 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor3";
+		};
+
+		sensor_information4: qcom,sensor-information-4 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor4";
+		};
+
+		sensor_information5: qcom,sensor-information-5 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor5";
+		};
+
+		sensor_information6: qcom,sensor-information-6 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor6";
+			qcom,alias-name = "cpu7";
+		}
+
+		sensor_information7: qcom,sensor-information-7 {
+			qcom,sensor-type =  "alarm";
+			qcom,sensor-name = "pm8994_tz";
+			qcom,scaling-factor = <1000>;
+                };
+
+	};
+
+===============================================================================
+Mitigation Profile:
+===============================================================================
+Thermal driver allows users to specify various mitigation profiles and
+associate a profile to a device. The device should have a phandle, to associate
+itself with a mitigation profile, using a "qcom,limits-info" property.
+This profile can specify whether to mitigate the device during various
+limiting conditions.
+
+Required Node:
+- qcom,limit_info-#: This is a mitigation profile node. A profile should
+			normally have a sensor(s) to monitor and a list
+			of properties enabling or disabling a mitigation.
+
+Required properties:
+
+- qcom,temperature-sensor: Array of phandle(s) to the temperature sensor(s) that
+			need(s) to be used for monitoring the device associated
+			with this mitigation profile. Right now the first
+			sensor will be used for KTM CPU monitoring. Alias
+			name of multiple sensors monitoring a same device will
+			be differentiated by appending an index like, "cpu0_0"
+			and "cpu0_1". A single sensor monitoring multiple
+			devices will have an alias name like "cpu0-cpu1-cpu2".
+
+Optional properties:
+
+- qcom,boot-frequency-mitigate: Enable thermal frequency mitigation
+			during boot.
+- qcom,emergency-frequency-mitigate: Enable emergency frequency mitigation.
+- qcom,hotplug-mitigation-enable: Enable hotplug mitigation. This enables
+			hotplug mitigation both during boot and emergency
+			condition.
+
+Example:
+	mitigation_profile7: qcom,limit_info-7 {
+		qcom,temperature-sensor =
+			<&sensor_information6 &sensor_information8>;
+		qcom,boot-frequency-mitigate;
+		qcom,emergency-frequency-mitigate;
+		qcom,hotplug-mitigation-enable;
+	};
diff --git a/Documentation/devicetree/bindings/arm/msm/proxy-client.txt b/Documentation/devicetree/bindings/arm/msm/proxy-client.txt
new file mode 100644
index 0000000..29cfaf9
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/proxy-client.txt
@@ -0,0 +1,34 @@
+Bus Proxy Client Bindings
+
+Bus proxy client provides means to cast proxy bandwidth votes during bootup
+which is removed at the end of boot. This feature can be used in situations
+where a shared resource can be scaled between several possible perfomance
+levels and hardware requires that it be at a high level at the beginning of
+boot before the client has probed and voted for required bandwidth.
+
+Required properties:
+- compatible:			Must be "qcom,bus-proxy-client".
+
+Optional properties:
+- qcom,msm-bus,name:		String representing the client-name.
+- qcom,msm-bus,num-cases:	Total number of usecases.
+- qcom,msm-bus,active-only:	Boolean context flag for requests in active or
+				dual (active & sleep) contex.
+- qcom,msm-bus,num-paths:	Total number of master-slave pairs.
+- qcom,msm-bus,vectors-KBps:	Arrays of unsigned integers representing:
+				master-id, slave-id, arbitrated bandwidth
+				in KBps, instantaneous bandwidth in KBps.
+
+Example:
+
+	qcom,proxy-client {
+		compatible = "qcom,bus-proxy-client";
+		qcom,msm-bus,name = "proxy_client";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,active-only;
+		qcom,msm-bus,vectors-KBps =
+			<22 512 0 0>, <23 512 0 0>,
+			<22 512 0 6400000>, <23 512 0 6400000>,
+			<22 512 0 6400000>, <23 512 0 6400000>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/qcom,debugcc.txt b/Documentation/devicetree/bindings/clock/qcom,debugcc.txt
new file mode 100644
index 0000000..a4452a5
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/qcom,debugcc.txt
@@ -0,0 +1,20 @@
+Qualcomm Technologies, Inc. Debug Clock Controller Binding
+----------------------------------------------------------
+
+Required properties :
+- compatible : shall contain only one of the following:
+			"qcom,debugcc-sdm845"
+			"qcom,debugcc-sdxpoorwills"
+
+- clock-names: Shall contain "xo_clk_src"
+- clocks: phandle + clock reference to the CXO clock.
+- #clock-cells : Shall contain 1.
+
+Example:
+	clock_debug: qcom,cc-debug {
+		compatible = "qcom,sdxpoorwills";
+		qcom,gcc = <&clock_gcc>;
+		clock-names = "xo_clk_src";
+		clocks = <&clock_rpmh RPMH_CXO_CLK>;
+		#clock-cells = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/clock/qcom,gcc.txt b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
index 7330db4..ba29471 100644
--- a/Documentation/devicetree/bindings/clock/qcom,gcc.txt
+++ b/Documentation/devicetree/bindings/clock/qcom,gcc.txt
@@ -20,7 +20,6 @@
 			"qcom,gcc-sdm845-v2"
 			"qcom,gcc-sdm845-v2.1"
 			"qcom,gcc-sdm670"
-			"qcom,debugcc-sdm845"
 			"qcom,gcc-sdxpoorwills"
 
 - reg : shall contain base register location and length
diff --git a/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt b/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt
index 35383adb..91a49af 100644
--- a/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt
+++ b/Documentation/devicetree/bindings/extcon/qcom,pm8941-misc.txt
@@ -8,7 +8,7 @@
 - compatible:
     Usage: required
     Value type: <string>
-    Definition: Should contain "qcom,pm8941-misc";
+    Definition: Should contain "qcom,pm8941-misc" or "qcom,pmd-vbus-det";
 
 - reg:
     Usage: required
diff --git a/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt b/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt
index 12ced5f..833b108 100644
--- a/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt
+++ b/Documentation/devicetree/bindings/interrupt-controller/qti,mpm.txt
@@ -8,13 +8,16 @@
 
 Platform interrupt controller MPM is next in hierarchy, followed by others.
 
+This defines 2 interrupt controllers to monitor the interrupts when the system is asleep:
+
+One for to monitor the wakeup capable gic interrupts called wakegic.
+
 Properties:
 
 - compatible:
 	Usage: required
 	Value type: <string>
-	Definition: Should contain "qcom,mpm" for mpm pin data
-	and the respective target compatible flag.
+	Definition: Should contain "qcom,mpm-gic" and the respective target compatible flag.
 
 - interrupts:
 	Usage: required
@@ -48,18 +51,42 @@
 
 Example:
 
-mpm: mpm@7781b8 {
-	compatible = "qcom,mpm";
+wakegic: wake-gic@7781b8 {
+	compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953", "qcom,mpm-gic-msm8937";
 	interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
-	reg = <0x7781b8 0x1000>,
-	    <0x17911008 0x4>;   /* MSM_APCS_GCC_BASE 4K */
+	reg = <0x601d4 0x1000>,
+	    <0xb011008 0x4>;  /* MSM_APCS_GCC_BASE 4K */
 	reg-names = "vmpm", "ipc";
-	qcom,num-mpm-irqs = <96>;
+	interrupt-controller;
+	interrupt-parent = <&intc>;
+	#interrupt-cells = <3>;
+};
 
-	wakegic: wake-gic {
-		compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953";
-		interrupt-controller;
-		#interrupt-cells = <3>;
-		interrupt-parent = <&intc>;
-	};
+
+One for to monitor the wakeup capable gpio interrupts called wakegpio.
+
+properties:
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: Should contain "qcom,mpm-gpio" and the respective target compatible flag.
+
+- interrupt-parent:
+	Usage: required
+	Value type: <phandle>
+	Definition: Specifies the interrupt parent necessary for hierarchical domain to operate.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <bool>
+	Definition: Identifies the node as an interrupt controller.
+
+Example:
+
+wakegpio: wake-gpio {
+	compatible = "qcom,mpm-gpio", "qcom,mpm-gpio-msm8953", "qcom,mpm-gpio-msm8937";
+	interrupt-controller;
+	interrupt-parent = <&tlmm>;
+	#interrupt-cells = <2>;
 };
diff --git a/Documentation/devicetree/bindings/mcd/mcd.txt b/Documentation/devicetree/bindings/mcd/mcd.txt
new file mode 100644
index 0000000..4077ee2
--- /dev/null
+++ b/Documentation/devicetree/bindings/mcd/mcd.txt
@@ -0,0 +1,29 @@
+* MCD (MobiCore Driver)
+
+t-base is an operating system running in the secure world (TrustZone).
+The t-base implementation consists of several components in the
+secure world and the non-secure world (kernel and user space). The
+MobiCore driver communicates with the t-base operating system that
+exists in TrustZone.
+
+Required properties:
+  - compatible: Should be "qcom,mcd"
+  - qcom,ce-hw-instance: should contain crypto HW instance
+  - qcom,ce-device: Device number
+  - clocks: Array of <clock_controller_phandle clock_reference> listing
+            all the clocks that are accesed by this subsystem.
+  - qcom,ce-opp-freq: indicates the CE operating frequency in Hz, changes from target to target.
+
+Example:
+	mcd {
+		compatible = "qcom,mcd";
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,ce-opp-freq = <100000000>;
+	};
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-cpas.txt b/Documentation/devicetree/bindings/media/video/msm-cam-cpas.txt
index 4b16103..f9bda3b 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-cpas.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-cpas.txt
@@ -147,6 +147,13 @@
   Definition: Bool property specifying whether Clients are connected
               through CAMNOC for AXI access.
 
+- nvmem-cells
+  Usage: optional
+  Definition: nvmem cell node
+
+- nvmem-cell-names
+  Usage: required
+  Definition: If nvmem node is present, cell name is required
 ===================================================================
 Third Level Node - CAM AXI Port properties
 ===================================================================
diff --git a/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt b/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt
index cf551f6..c47cb34 100644
--- a/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt
+++ b/Documentation/devicetree/bindings/media/video/msm-cam-fd.txt
@@ -49,7 +49,7 @@
 - compatible
   Usage: required
   Value type: <string>
-  Definition: Should be "qcom,fd41".
+  Definition: Should be one of "qcom,fd41", "qcom,fd501".
 
 - reg-names
   Usage: optional
diff --git a/Documentation/devicetree/bindings/mhi/msm_mhi_dev.txt b/Documentation/devicetree/bindings/mhi/msm_mhi_dev.txt
index 49d33a3..3017468 100644
--- a/Documentation/devicetree/bindings/mhi/msm_mhi_dev.txt
+++ b/Documentation/devicetree/bindings/mhi/msm_mhi_dev.txt
@@ -19,6 +19,18 @@
   - qcom,mhi-ep-msi: End point MSI number.
   - qcom,mhi-version: MHI specification version supported by the device.
 
+Optional property:
+  - qcom,use-ipa-software-channel: If property is present use IPA hardware
+		accelerated path for MHI software channel data transfers
+		between host and device.
+  - qcom,mhi-config-iatu: If property is present map the control and data region
+		between host and device using iatu.
+  - qcom,mhi-interrupt: If property is present register for mhi interrupt.
+  - qcom,mhi-local-pa-base: The physical base address on the device used by the
+		MHI device driver to map the control and data region with the
+		MHI driver on the host. This property is required if iatu
+		property qcom,mhi-config-iatu is present.
+
 Example:
 
 	mhi: qcom,msm-mhi-dev {
diff --git a/Documentation/devicetree/bindings/pinctrl/msm.txt b/Documentation/devicetree/bindings/pinctrl/msm.txt
new file mode 100644
index 0000000..839bd05
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/msm.txt
@@ -0,0 +1,17 @@
+MSM Pinctrl Bindings
+
+Required properties:
+- compatible: "qcom,msm8996-pinctrl"
+              "qcom,mdm9640-pinctrl"
+	      "qcom,msm8909-pinctrl"
+- reg: Should be the base address and length of the TLMM block.
+- interrupts: Should be the parent IRQ of the TLMM block.
+- interrupt-controller: Marks the device node as an interrupt controller.
+- #interrupt-cells: Should be two.
+- gpio-controller: Marks the device node as a GPIO controller.
+- #gpio-cells : Should be two.
+                 The first cell is the gpio pin number and the
+                 second cell is used for optional parameters.
+
+Optional properties:
+- qcom,tlmm-emmc-boot-select : Should be the bit-field position to set.
diff --git a/Documentation/devicetree/bindings/pinctrl/qcom,msm8917-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/qcom,msm8917-pinctrl.txt
new file mode 100644
index 0000000..d2327a257
--- /dev/null
+++ b/Documentation/devicetree/bindings/pinctrl/qcom,msm8917-pinctrl.txt
@@ -0,0 +1,204 @@
+Qualcomm Technologies, Inc. MSM8917 TLMM block
+
+This binding describes the Top Level Mode Multiplexer block found in the
+MSM8917 platform.
+
+- compatible:
+	Usage: required
+	Value type: <string>
+	Definition: must be "qcom,msm8917-pinctrl"
+
+- reg:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: the base address and size of the TLMM register space.
+
+- interrupts:
+	Usage: required
+	Value type: <prop-encoded-array>
+	Definition: should specify the TLMM summary IRQ.
+
+- interrupt-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as an interrupt controller
+
+- #interrupt-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/interrupt-controller/irq.h>
+
+- gpio-controller:
+	Usage: required
+	Value type: <none>
+	Definition: identifies this node as a gpio controller
+
+- #gpio-cells:
+	Usage: required
+	Value type: <u32>
+	Definition: must be 2. Specifying the pin number and flags, as defined
+		    in <dt-bindings/gpio/gpio.h>
+
+Please refer to ../gpio/gpio.txt and ../interrupt-controller/interrupts.txt for
+a general description of GPIO and interrupt bindings.
+
+Please refer to pinctrl-bindings.txt in this directory for details of the
+common pinctrl bindings used by client devices, including the meaning of the
+phrase "pin configuration node".
+
+The pin configuration nodes act as a container for an arbitrary number of
+subnodes. Each of these subnodes represents some desired configuration for a
+pin, a group, or a list of pins or groups. This configuration can include the
+mux function to select on those pin(s)/group(s), and various pin configuration
+parameters, such as pull-up, drive strength, etc.
+
+
+PIN CONFIGURATION NODES:
+
+The name of each subnode is not important; all subnodes should be enumerated
+and processed purely based on their content.
+
+Each subnode only affects those parameters that are explicitly listed. In
+other words, a subnode that lists a mux function but no pin configuration
+parameters implies no information about any pin configuration parameters.
+Similarly, a pin subnode that describes a pullup parameter implies no
+information about e.g. the mux function.
+
+
+The following generic properties as defined in pinctrl-bindings.txt are valid
+to specify in a pin configuration subnode:
+
+- pins:
+	Usage: required
+	Value type: <string-array>
+	Definition: List of gpio pins affected by the properties specified in
+		    this subnode.
+		    Valid pins are:
+		    gpio0-gpio133,
+		    sdc1_clk,
+		    sdc1_cmd,
+		    sdc1_data,
+		    sdc1_rclk,
+		    sdc2_clk,
+		    sdc2_cmd,
+		    sdc2_data,
+		    qdsd_clk,
+		    qdsd_cmd,
+		    qdsd_data0,
+		    qdsd_data1,
+		    qdsd_data2,
+		    qdsd_data3,
+
+- function:
+	Usage: required
+	Value type: <string>
+	Definition: Specify the alternative function to be configured for the
+		    specified pins. Functions are only valid for gpio pins.
+		    Valid values are:
+        qdss_tracedata_b, blsp_uart1, gpio, blsp_spi1, adsp_ext, blsp_i2c1, prng_rosc,
+        qdss_cti_trig_out_b0, blsp_spi2, blsp_uart2, blsp_uart3, pbs0, pbs1,
+        pwr_modem_enabled_b, blsp_i2c3, gcc_gp2_clk_b, ldo_update,
+        atest_combodac_to_gpio_native, ldo_en, blsp_i2c2, gcc_gp1_clk_b, pbs2,
+        atest_gpsadc_dtest0_native, blsp_spi3, gcc_gp3_clk_b, blsp_spi4, blsp_uart4,
+        sec_mi2s, pwr_nav_enabled_b, codec_mad, pwr_crypto_enabled_b, blsp_i2c4,
+        blsp_spi5, blsp_uart5, qdss_traceclk_a, atest_bbrx1, m_voc,
+        qdss_cti_trig_in_a0, qdss_cti_trig_in_b0, blsp_i2c6, qdss_traceclk_b,
+        atest_wlan0, atest_wlan1, atest_bbrx0, blsp_i2c5, qdss_tracectl_a,
+        atest_gpsadc_dtest1_native, qdss_tracedata_a, blsp_spi6, blsp_uart6,
+        qdss_tracectl_b, mdp_vsync, pri_mi2s_mclk_a, sec_mi2s_mclk_a, cam_mclk,
+        cci_i2c, pwr_modem_enabled_a, cci_timer0, cci_timer1, cam1_standby,
+        pwr_nav_enabled_a, cam1_rst, pwr_crypto_enabled_a, forced_usb,
+        qdss_cti_trig_out_b1, cam2_rst, webcam_standby, cci_async, webcam_rst,
+        ov_ldo, sd_write, accel_int, gcc_gp1_clk_a, alsp_int, gcc_gp2_clk_a,
+        mag_int, gcc_gp3_clk_a, blsp6_spi, fp_int, qdss_cti_trig_in_b1, uim_batt,
+        cam2_standby, uim1_data, uim1_clk, uim1_reset, uim1_present, uim2_data,
+        uim2_clk, uim2_reset, uim2_present, sensor_rst, mipi_dsi0, smb_int,
+        cam0_ldo, us_euro, atest_char3, dbg_out, bimc_dte0, ts_resout, ts_sample,
+        sec_mi2s_mclk_b, pri_mi2s, sdcard_det, atest_char1, ebi_cdc, audio_reset,
+        atest_char0, audio_ref, cdc_pdm0, pri_mi2s_mclk_b, lpass_slimbus,
+        lpass_slimbus0, lpass_slimbus1, codec_int1, codec_int2, wcss_bt,
+        atest_char2, ebi_ch0, wcss_wlan2, wcss_wlan1, wcss_wlan0, wcss_wlan,
+        wcss_fm, ext_lpass, cri_trng, cri_trng1, cri_trng0, blsp_spi7, blsp_uart7,
+        pri_mi2s_ws, blsp_i2c7, gcc_tlmm, dmic0_clk, dmic0_data, key_volp,
+        qdss_cti_trig_in_a1, us_emitter, wsa_irq, wsa_io, wsa_reset, blsp_spi8,
+        blsp_uart8, blsp_i2c8, gcc_plltest, nav_pps_in_a, pa_indicator, modem_tsync,
+        nav_tsync, nav_pps_in_b, nav_pps, gsm0_tx, atest_char, atest_tsens,
+        bimc_dte1, ssbi_wtr1, fp_gpio, coex_uart, key_snapshot, key_focus, nfc_pwr,
+        blsp8_spi, qdss_cti_trig_out_a0, qdss_cti_trig_out_a1
+
+- bias-disable:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as no pull.
+
+- bias-pull-down:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull down.
+
+- bias-pull-up:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins should be configued as pull up.
+
+- output-high:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    high.
+		    Not valid for sdc pins.
+
+- output-low:
+	Usage: optional
+	Value type: <none>
+	Definition: The specified pins are configured in output mode, driven
+		    low.
+		    Not valid for sdc pins.
+
+- drive-strength:
+	Usage: optional
+	Value type: <u32>
+	Definition: Selects the drive strength for the specified pins, in mA.
+		    Valid values are: 2, 4, 6, 8, 10, 12, 14 and 16
+
+Example:
+
+	tlmm: pinctrl@1000000 {
+		compatible = "qcom,msm8917-pinctrl";
+		reg = <0x1000000 0x300000>;
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		pmx-uartconsole {
+			uart_console_active: uart_console_active {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "blsp_uart2";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			uart_console_sleep: uart_console_sleep {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "blsp_uart2";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+
+		};
+	};
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
index 3481b80..6363aa3 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-qg.txt
@@ -144,6 +144,12 @@
 	Value type: <u32>
 	Definition: Resistance of the battery connectors in mOhms.
 
+- qcom,ignore-shutdown-soc-secs
+	Usage:      optional
+	Value type: <u32>
+	Definition: Time in seconds beyond which shutdown SOC is ignored.
+		    If not specified the default value is 360 secs.
+
 ==========================================================
 Second Level Nodes - Peripherals managed by QGAUGE driver
 ==========================================================
diff --git a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
index 8f8c87e..b7e6a31b 100644
--- a/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
+++ b/Documentation/devicetree/bindings/power/supply/qcom/qpnp-smb5.txt
@@ -109,10 +109,18 @@
 
 - qcom,auto-recharge-soc
   Usage:      optional
-  Value type: <empty>
-  Definition: Specifies if automatic recharge needs to be based off battery
-		SOC. If this property is not specified, then auto recharge will
-		be based off battery voltage.
+  Value type: <u32>
+  Definition: Specifies the SOC threshold at which the charger will
+		restart charging after termination. The value specified
+		ranges from 0 - 100. The feature is enabled if this
+		property is specified with a valid SOC value.
+
+- qcom,auto-recharge-vbat-mv
+  Usage:      optional
+  Value type: <u32>
+  Definition: Specifies the battery voltage threshold at which the charger
+		will restart charging after termination. The value specified
+		is in milli-volts.
 
 - qcom,suspend-input-on-debug-batt
   Usage:      optional
diff --git a/Documentation/devicetree/bindings/qdsp/msm-mdsprpc-mem.txt b/Documentation/devicetree/bindings/qdsp/msm-mdsprpc-mem.txt
new file mode 100644
index 0000000..2a5fc0f
--- /dev/null
+++ b/Documentation/devicetree/bindings/qdsp/msm-mdsprpc-mem.txt
@@ -0,0 +1,24 @@
+Qualcomm Technologies, Inc. FastRPC MDSP CMA Heap
+
+The MSM MDSPRPC memory device allocates CMA memory, for sharing memory
+of FastRPC buffers to remote processor(MDSP).
+
+Required properties:
+-compatible: Must be "qcom,msm-mdsprpc-mem-region"
+-memory-region: A phandle that points to a memory heap where the
+heap memory is allocated
+
+Example:
+	qcom,mdsprpc-mem {
+		compatible = "qcom,msm-mdsprpc-mem-region";
+		memory-region = <&mdsp_mem>;
+	};
+
+Ion Heap:
+
+Ion heap allows for sharing of buffers between different processors
+and between user space and kernel space.
+(see Documentation/devicetree/bindings/arm/msm/msm_ion.txt).
+
+Required properties for Ion heap:
+- compatible : "qcom,msm-ion"
diff --git a/Documentation/devicetree/bindings/soc/qcom/bg_daemon.txt b/Documentation/devicetree/bindings/soc/qcom/bg_daemon.txt
new file mode 100644
index 0000000..149a01a
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/bg_daemon.txt
@@ -0,0 +1,14 @@
+Qualcomm Technologies Inc. bg-daemon
+
+BG-Daemon : When Modem goes down, to re-establish the connections,
+BG-Daemon toggles the bg-reset gpio to reset BG.
+
+Required properties:
+- compatible : should be "qcom,bg-daemon"
+- qcom,bg-reset-gpio : gpio for the apps processor use to soft reset BG
+
+Example:
+	qcom,bg-daemon {
+		compatible = "qcom,bg-daemon";
+		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+	};
diff --git a/Documentation/devicetree/bindings/soc/qcom/bg_rsb.txt b/Documentation/devicetree/bindings/soc/qcom/bg_rsb.txt
new file mode 100644
index 0000000..26a13cd
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/bg_rsb.txt
@@ -0,0 +1,19 @@
+Qualcomm technologies Inc bg-rsb
+
+BG-RSB : bg-rsb is used to communicate with BG over Glink to
+configure the RSB events. bg-rsb enable/disable LDO11 and LDO15
+before making any communication to BG regarding RSB.
+It also provides an input device, which is used to send the RSB/Button
+events to input framework.
+
+Required properties:
+- compatible : should be "qcom,bg-rsb"
+- vdd-ldo1-supply : pm660_l11 regulator
+- vdd-ldo2-supply : for pm660_l15 regulator
+
+Example:
+	qcom,bg-rsb {
+		compatible = "qcom,bg-rsb";
+		vdd-ldo1-supply = <&pm660_l11>;
+		vdd-ldo2-supply = <&pm660_l15>;
+	};
diff --git a/Documentation/devicetree/bindings/soc/qcom/bg_spi.txt b/Documentation/devicetree/bindings/soc/qcom/bg_spi.txt
new file mode 100644
index 0000000..e9a28a9
--- /dev/null
+++ b/Documentation/devicetree/bindings/soc/qcom/bg_spi.txt
@@ -0,0 +1,24 @@
+Qualcomm technologies Inc bg-spi
+
+BG-COM SPI : bg-spi is used for the  communication with Blackghost
+chipset. It uses SPI protocol for communication.
+BG-COM: bgcome is a thin transport layer over glink which provides
+the read/write APIs to communicate with Blackghost chipset.
+
+Required properties:
+- compatible : should be "qcom,bg-spi"
+- spi-max-frequency : Maximum SPI clocking speed of device in Hz
+- qcom,irq-gpio : GPIO pin
+- reg : Register set
+
+Example:
+	spi@78b6000 { /* BLSP1 QUP2 */
+		status = "ok";
+		qcom,bg-spi {
+			compatible = "qcom,bg-spi";
+			reg = <0>;
+			spi-max-frequency = <19200000>;
+			interrupt-parent = <&msm_gpio>;
+			qcom,irq-gpio = <&msm_gpio 110 1>;
+		};
+	};
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index fa11e70..33dc684 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -1872,6 +1872,128 @@
 		asoc-wsa-codec-prefixes = "SpkrLeft";
 	};
 
+* MSM8909 BG ASoC Machine driver
+
+Required properties:
+- compatible : "qcom,msm-bg-audio-codec"
+- qcom,model : The user-visible name of this sound card.
+- qcom,pinctrl-names : Lists all the possible combinations of the gpio sets
+	mentioned in qcom,msm-gpios. Say we have 2^N combinations for N GPIOs,
+	this would list all the 2^N combinations.
+- pinctrl-names : The combinations of gpio sets from above that are supported in
+	the flavor. This can be sometimes same as qcom,pinctrl-names i.e with 2^N
+	combinations or will have less incase if some combination is not supported.
+- pinctrl-# : Pinctrl states as mentioned in pinctrl-names.
+- qcom,audio-routing : A list of the connections between audio components.
+	Each entry is a pair of strings, the first being the connection's sink,
+	the second being the connection's source.
+
+Optional properties:
+- qcom,cdc-us-euro-gpios : GPIO on which gnd/mic swap signal is coming.
+- asoc-platform: This is phandle list containing the references to platform device
+		nodes that are used as part of the sound card dai-links.
+- asoc-platform-names:  This property contains list of platform names. The order of
+			the platform names should match to that of the phandle order
+			given in "asoc-platform".
+- asoc-cpu: This is phandle list containing the references to cpu dai device nodes
+	that are used as part of the sound card dai-links.
+- asoc-cpu-names: This property contains list of cpu dai names. The order of the
+	cpu dai names should match to that of the phandle order given
+	in "asoc-cpu". The cpu names are in the form of "%s.%d" form,
+	where the id (%d) field represents the back-end AFE port id that
+	this CPU dai is associated with.
+- asoc-codec: This is phandle list containing the references to codec dai device
+	nodes that are used as part of the sound card dai-links.
+- asoc-codec-names: This property contains list of codec dai names. The order of the
+		codec dai names should match to that of the phandle order given
+		in "asoc-codec".
+- vdd-spkr-supply: BG codec supply's speaker regulator device tree node.
+
+Example:
+	sound {
+		status = "disabled";
+		compatible = "qcom,msm-bg-audio-codec";
+		qcom,model = "msm-bg-snd-card";
+		reg = <0x7702000 0x4>,
+		      <0x7702004 0x4>,
+		      <0x7702008 0x4>,
+		      <0x770200c 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			    "csr_gp_io_mux_spkr_ctl",
+			    "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+			    "csr_gp_io_lpaif_sec_pcm_sec_mode_muxsel";
+		qcom,msm-snd-card-id = <0>;
+		qcom,msm-ext-pa = "primary";
+		qcom,tdm-audio-intf;
+		qcom,msm-afe-clk-ver = <1>;
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&lpa>,
+				<&voice_svc>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				      "msm-pcm-dsp.2", "msm-voip-dsp",
+				      "msm-pcm-voice", "msm-pcm-loopback",
+				      "msm-compress-dsp", "msm-pcm-hostless",
+				      "msm-pcm-afe", "msm-lsm-client",
+				      "msm-pcm-routing", "msm-pcm-lpa",
+				      "msm-voice-svc";
+		asoc-cpu = <&dai_pri_auxpcm>,
+				<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
+				<&dai_mi2s3>, <&dai_mi2s5>, <&dai_mi2s6>,
+				<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
+				<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
+				<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>,
+				<&incall_music_rx>, <&incall_music_2_rx>,
+				<&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>,
+				<&dai_pri_tdm_rx_1>, <&dai_pri_tdm_tx_1>,
+				<&dai_pri_tdm_rx_2>, <&dai_pri_tdm_tx_2>,
+				<&dai_pri_tdm_rx_3>, <&dai_pri_tdm_tx_3>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
+				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
+				"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+				"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+				"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+				"msm-dai-q6-dev.32770", "msm-dai-q6-tdm.36864",
+				"msm-dai-q6-tdm.36865", "msm-dai-q6-tdm.36866",
+				"msm-dai-q6-tdm.36867", "msm-dai-q6-tdm.36868",
+				"msm-dai-q6-tdm.36869", "msm-dai-q6-tdm.36870",
+				"msm-dai-q6-tdm.36871";
+		asoc-codec = <&stub_codec>;
+		asoc-codec-names = "msm-stub-codec.1";
+	};
+
+* BG Codec Driver.
+
+Required properties:
+- compatible : "qcom,bg-codec"
+- qcom,bg-glink : Glink component required for the BG codec communication.
+	- compatible :"qcom,bg-cdc-glink"
+- qcom,msm-glink-channels: Number of glink channels available to communicate
+			   with the glink client
+- vdd-spkr-supply: BG codec supply's speaker regulator device tree node.
+
+Optional properties:
+- qcom,bg-speaker-connected: This flag will notify BG codec driver that speaker
+			is connected to target or not. Based on this flag BG
+			codec driver will send smart pa init params to BG.
+
+Example:
+
+        bg_cdc: bg_codec {
+                status = "disabled";
+                compatible = "qcom,bg-codec";
+                qcom,bg-glink {
+                        compatible = "qcom,bg-cdc-glink";
+                        qcom,msm-glink-channels = <4>;
+                };
+        };
+
 * MDM9607 ASoC Machine driver
 
 Required properties:
diff --git a/Documentation/devicetree/bindings/soundwire/swr-wcd-ctrl.txt b/Documentation/devicetree/bindings/soundwire/swr-wcd-ctrl.txt
index 757ca9a..8a67d6d 100644
--- a/Documentation/devicetree/bindings/soundwire/swr-wcd-ctrl.txt
+++ b/Documentation/devicetree/bindings/soundwire/swr-wcd-ctrl.txt
@@ -8,6 +8,7 @@
 	 which the swr-devid is <0x0 0x032000> where 0x03 represents
 	 device Unique_ID, 0x20 represents Part_Id1 and 0x00
 	 represents part_Id2.
+- qcom,swr-num-dev : Maximum number of possible slave devices.
 - #address-cells = <2>;
 - #size-cells = <0>;
 
@@ -16,6 +17,7 @@
  Example:
 	swr_master {
 		compatible = "qcom,swr-wcd";
+		qcom,swr-num-dev = <2>;
 		#address-cells = <2>;
 		#size-cells = <0>;
 
diff --git a/Documentation/devicetree/bindings/thermal/qcom-bcl-pmic5.txt b/Documentation/devicetree/bindings/thermal/qcom-bcl-pmic5.txt
new file mode 100644
index 0000000..5322d89
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/qcom-bcl-pmic5.txt
@@ -0,0 +1,37 @@
+===============================================================================
+BCL Peripheral driver for PMIC5:
+===============================================================================
+Qualcomm Technologies, Inc's PMIC has battery current limiting peripheral,
+which can monitor for high battery current and low battery voltage in the
+hardware. The BCL peripheral driver interacts with the PMIC peripheral using
+the SPMI driver interface. The hardware can take threshold for notifying for
+high battery current or low battery voltage events. This driver works only
+with PMIC version 5, where the same BCL peripheral can be found in multiple
+PMIC's that are used in a device, with limited functionalities. For example,
+one PMIC can have only vbat monitoring, while the other PMIC can have both
+vbat and ibat monitoring. This is a common driver, that can interact
+with the multiple BCL peripherals.
+
+Required Parameters:
+- compatible: must be
+	'qcom,msm-bcl-pmic5' for bcl peripheral in PMIC version 5.
+- reg: <a b> where 'a' is the starting register address of the PMIC
+	peripheral and 'b' is the size of the peripheral address space.
+- interrupts: <a b c> Where 'a' is the SLAVE ID of the PMIC, 'b' is
+		the peripheral ID and 'c' is the interrupt number in PMIC.
+- interrupt-names: user defined names for the interrupts. These
+		interrupt names will be used by the drivers to identify the
+		interrupts, instead of specifying the ID's. bcl driver will
+		accept these standard interrupts.
+		"bcl-low-vbat"
+		"bcl-high-ibat"
+
+Example:
+		bcl@4200 {
+			compatible = "qcom,msm-bcl-pmic5";
+			reg = <0x4200 0xFF>;
+			interrupts = <0x2 0x42 0x0>,
+					<0x2 0x42 0x1>;
+			interrupt-names = "bcl-high-ibat",
+						"bcl-low-vbat";
+		};
diff --git a/Documentation/devicetree/bindings/thermal/qcom-bcl-soc.txt b/Documentation/devicetree/bindings/thermal/qcom-bcl-soc.txt
new file mode 100644
index 0000000..00be6de
--- /dev/null
+++ b/Documentation/devicetree/bindings/thermal/qcom-bcl-soc.txt
@@ -0,0 +1,13 @@
+===============================================================================
+PMIC state of charge driver:
+===============================================================================
+Battery state of charge driver can monitor for change in battery charge and
+notify thermal framework, when the value goes below a certain threshold.
+
+Required Parameters:
+- compatible: must be 'qcom,msm-bcl-soc' for battery state of charge driver.
+
+Example:
+	bcl-soc {
+		compatible = "qcom,msm-bcl-soc";
+	};
diff --git a/Documentation/devicetree/bindings/usb/msm-android-usb.txt b/Documentation/devicetree/bindings/usb/msm-android-usb.txt
new file mode 100644
index 0000000..4422a18
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/msm-android-usb.txt
@@ -0,0 +1,36 @@
+ANDROID USB:
+
+This describes the device tree node for the Android USB gadget device.
+This works in conjunction with a USB Device Controller (UDC) to provide
+a dynamically configurable composition of functions to be exposed when
+connected to a USB host.
+
+Required properties:
+- compatible: should be "qcom,android-usb"
+
+Optional properties :
+- reg  : offset and length of memory region that is used by device to
+  update USB PID and serial numbers used by bootloader in DLOAD mode.
+- qcom,pm-qos-latency : This property must be a list of three integer values
+  (perf, normal, sleep) where each value respresents DMA latency in microsecs.
+  First value represents DMA latency to vote with pm_qos when back to back USB
+  transfers are happening and it requires USB thoughput to be maximum.
+  Second value represents value to vote when not many USB transfers are
+  happening and it is OK to have higher DMA latency to save power.
+  Third value represents DMA latency to vote when USB BUS is IDLE and absolutely
+  no transfers are happening. It should allow transition to lowest power state.
+- qcom,usb-core-id: Index to refer USB hardware core to bind android gadget driver
+  with UDC if multiple USB peripheral controllers are present. If unspecified,
+  core is set to zero by default.
+- qcom,supported-func: Represents list of supported function drivers. If this
+  property is present android USB driver dynamically creats the list of
+  supported function drivers and uses this list instead of statically defined default
+  supported function driver list.
+Example Android USB device node :
+	android_usb@fc42b0c8 {
+		compatible = "qcom,android-usb";
+		reg = <0xfc42b0c8 0xc8>;
+		qcom,pm-qos-latency = <2 1001 12701>;
+		qcom,supported-func = "rndis_gsi","ecm_gsi","rmnet_gsi";
+		qcom,usb-core-id = <1>;
+	};
diff --git a/Documentation/devicetree/bindings/usb/msm-phy.txt b/Documentation/devicetree/bindings/usb/msm-phy.txt
index e94299f..b880890 100644
--- a/Documentation/devicetree/bindings/usb/msm-phy.txt
+++ b/Documentation/devicetree/bindings/usb/msm-phy.txt
@@ -24,6 +24,9 @@
  - reset-names: reset signal name strings sorted in the same order as the resets
    property.
 
+Optional properties:
+ - qcom,param-override-seq: parameter override sequence with value, reg offset pair.
+
 Example:
 	hsphy@f9200000 {
 		compatible = "qcom,usb-hsphy-snps-femto";
@@ -32,6 +35,7 @@
 		vdda18-supply = <&pm8941_l6>;
 		vdda33-supply = <&pm8941_l24>;
 		qcom,vdd-voltage-level = <0 872000 872000>;
+		qcom,param-override-seq = <0x43 0x70>;
 	};
 
 SSUSB-QMP PHY
@@ -186,6 +190,7 @@
    state when attached in host mode and "suspend" state when detached.
  - qcom,tune2-efuse-correction: The value to be adjusted from fused value for
    improved rise/fall times.
+ - qcom,host-chirp-erratum: Indicates host chirp fix is required.
  - nvmem-cells: specifies the handle to represent the SoC revision.
    usually it is defined by qfprom device node.
  - nvmem-cell-names: specifies the given nvmem cell name as defined in
diff --git a/Makefile b/Makefile
index 1de0efc..42db02e 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 VERSION = 4
 PATCHLEVEL = 9
-SUBLEVEL = 81
+SUBLEVEL = 82
 EXTRAVERSION =
 NAME = Roaring Lionus
 
diff --git a/arch/alpha/kernel/pci_impl.h b/arch/alpha/kernel/pci_impl.h
index 2b0ac42..412bb3c 100644
--- a/arch/alpha/kernel/pci_impl.h
+++ b/arch/alpha/kernel/pci_impl.h
@@ -143,7 +143,8 @@
 };
 
 #if defined(CONFIG_ALPHA_SRM) && \
-    (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA))
+    (defined(CONFIG_ALPHA_CIA) || defined(CONFIG_ALPHA_LCA) || \
+     defined(CONFIG_ALPHA_AVANTI))
 # define NEED_SRM_SAVE_RESTORE
 #else
 # undef NEED_SRM_SAVE_RESTORE
diff --git a/arch/alpha/kernel/process.c b/arch/alpha/kernel/process.c
index b483156..60c17b9 100644
--- a/arch/alpha/kernel/process.c
+++ b/arch/alpha/kernel/process.c
@@ -265,12 +265,13 @@
 	   application calling fork.  */
 	if (clone_flags & CLONE_SETTLS)
 		childti->pcb.unique = regs->r20;
+	else
+		regs->r20 = 0;	/* OSF/1 has some strange fork() semantics.  */
 	childti->pcb.usp = usp ?: rdusp();
 	*childregs = *regs;
 	childregs->r0 = 0;
 	childregs->r19 = 0;
 	childregs->r20 = 1;	/* OSF/1 has some strange fork() semantics.  */
-	regs->r20 = 0;
 	stack = ((struct switch_stack *) regs) - 1;
 	*childstack = *stack;
 	childstack->r26 = (unsigned long) ret_from_fork;
diff --git a/arch/alpha/kernel/traps.c b/arch/alpha/kernel/traps.c
index 74aceea..32ba92c 100644
--- a/arch/alpha/kernel/traps.c
+++ b/arch/alpha/kernel/traps.c
@@ -158,11 +158,16 @@
 	for(i=0; i < kstack_depth_to_print; i++) {
 		if (((long) stack & (THREAD_SIZE-1)) == 0)
 			break;
-		if (i && ((i % 4) == 0))
-			printk("\n       ");
-		printk("%016lx ", *stack++);
+		if ((i % 4) == 0) {
+			if (i)
+				pr_cont("\n");
+			printk("       ");
+		} else {
+			pr_cont(" ");
+		}
+		pr_cont("%016lx", *stack++);
 	}
-	printk("\n");
+	pr_cont("\n");
 	dik_show_trace(sp);
 }
 
diff --git a/arch/arm/boot/dts/qcom/pm8950.dtsi b/arch/arm/boot/dts/qcom/pm8950.dtsi
deleted file mode 100644
index f47872a..0000000
--- a/arch/arm/boot/dts/qcom/pm8950.dtsi
+++ /dev/null
@@ -1,388 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-&spmi_bus {
-	qcom,pm8950@0 {
-		compatible ="qcom,spmi-pmic";
-		reg = <0x0 SPMI_USID>;
-		#address-cells = <2>;
-		#size-cells = <0>;
-
-		pm8950_revid: qcom,revid@100 {
-			compatible = "qcom,qpnp-revid";
-			reg = <0x100 0x100>;
-		};
-
-		pm8950_temp_alarm: qcom,temp-alarm@2400 {
-			compatible = "qcom,qpnp-temp-alarm";
-			reg = <0x2400 0x100>;
-			interrupts = <0x0 0x24 0x0>;
-			label = "pm8950_tz";
-			qcom,channel-num = <8>;
-			qcom,threshold-set = <0>;
-			qcom,temp_alarm-vadc = <&pm8950_vadc>;
-		};
-
-		qcom,power-on@800 {
-			compatible = "qcom,qpnp-power-on";
-			reg = <0x800 0x100>;
-			interrupts = <0x0 0x8 0x0>,
-				<0x0 0x8 0x1>,
-				<0x0 0x8 0x4>,
-				<0x0 0x8 0x5>;
-			interrupt-names = "kpdpwr", "resin",
-				"resin-bark", "kpdpwr-resin-bark";
-			qcom,pon-dbc-delay = <15625>;
-			qcom,system-reset;
-
-			qcom,pon_1 {
-				qcom,pon-type = <0>;
-				qcom,pull-up = <1>;
-				linux,code = <116>;
-			};
-
-			qcom,pon_2 {
-				qcom,pon-type = <1>;
-				qcom,pull-up = <1>;
-				linux,code = <114>;
-			};
-		};
-
-		pm8950_coincell: qcom,coincell@2800 {
-			compatible = "qcom,qpnp-coincell";
-			reg = <0x2800 0x100>;
-		};
-
-		pm8950_mpps: mpps {
-			compatible = "qcom,qpnp-pin";
-			spmi-dev-container;
-			gpio-controller;
-			#gpio-cells = <2>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			label = "pm8950-mpp";
-
-			mpp@a000 {
-				reg = <0xa000 0x100>;
-				qcom,pin-num = <1>;
-				status = "disabled";
-			};
-
-			mpp@a100 {
-				/* MPP2 - PA_THERM config */
-				reg = <0xa100 0x100>;
-				qcom,pin-num = <2>;
-				qcom,mode = <4>; /* AIN input */
-				qcom,invert = <1>; /* Enable MPP */
-				qcom,ain-route = <1>; /* AMUX 6 */
-				qcom,master-en = <1>;
-				qcom,src-sel = <0>; /* Function constant */
-			};
-
-			mpp@a200 {
-				reg = <0xa200 0x100>;
-				qcom,pin-num = <3>;
-				status = "disabled";
-			};
-
-			mpp@a300 {
-				/* MPP4 - CASE_THERM config */
-				reg = <0xa300 0x100>;
-				qcom,pin-num = <4>;
-				qcom,mode = <4>; /* AIN input */
-				qcom,invert = <1>; /* Enable MPP */
-				qcom,ain-route = <3>; /* AMUX 8 */
-				qcom,master-en = <1>;
-				qcom,src-sel = <0>; /* Function constant */
-			};
-		};
-
-		pm8950_gpios: gpios {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-pin";
-			gpio-controller;
-			#gpio-cells = <2>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			label = "pm8950-gpio";
-
-			gpio@c000 {
-				reg = <0xc000 0x100>;
-				qcom,pin-num = <1>;
-				status = "disabled";
-			};
-
-			gpio@c100 {
-				reg = <0xc100 0x100>;
-				qcom,pin-num = <2>;
-				status = "disabled";
-			};
-
-			gpio@c200 {
-				reg = <0xc200 0x100>;
-				qcom,pin-num = <3>;
-				status = "disabled";
-			};
-
-			gpio@c300 {
-				reg = <0xc300 0x100>;
-				qcom,pin-num = <4>;
-				status = "disabled";
-			};
-
-			gpio@c400 {
-				reg = <0xc400 0x100>;
-				qcom,pin-num = <5>;
-				status = "disabled";
-			};
-
-			gpio@c500 {
-				reg = <0xc500 0x100>;
-				qcom,pin-num = <6>;
-				status = "disabled";
-			};
-
-			gpio@c600 {
-				reg = <0xc600 0x100>;
-				qcom,pin-num = <7>;
-				status = "disabled";
-			};
-
-			gpio@c700 {
-				reg = <0xc700 0x100>;
-				qcom,pin-num = <8>;
-				status = "disabled";
-			};
-		};
-
-		pm8950_vadc: vadc@3100 {
-			compatible = "qcom,qpnp-vadc";
-			reg = <0x3100 0x100>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <0x0 0x31 0x0>;
-			interrupt-names = "eoc-int-en-set";
-			qcom,adc-bit-resolution = <15>;
-			qcom,adc-vdd-reference = <1800>;
-			qcom,vadc-poll-eoc;
-			qcom,pmic-revid = <&pm8950_revid>;
-
-			chan@5 {
-				label = "vcoin";
-				reg = <5>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@7 {
-				label = "vph_pwr";
-				reg = <7>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@8 {
-				label = "die_temp";
-				reg = <8>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <3>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@9 {
-				label = "ref_625mv";
-				reg = <9>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@a {
-				label = "ref_1250v";
-				reg = <0xa>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@c {
-				label = "ref_buf_625mv";
-				reg = <0xc>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@36 {
-				label = "pa_therm0";
-				reg = <0x36>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@11 {
-				label = "pa_therm1";
-				reg = <0x11>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
-			};
-
-			chan@32 {
-				label = "xo_therm";
-				reg = <0x32>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <4>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
-			};
-
-			chan@3c {
-				label = "xo_therm_buf";
-				reg = <0x3c>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <4>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
-			};
-
-			chan@13 {
-				label = "case_therm";
-				reg = <0x13>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
-			};
-		};
-
-		pm8950_adc_tm: vadc@3400 {
-			compatible = "qcom,qpnp-adc-tm";
-			reg = <0x3400 0x100>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts =	<0x0 0x34 0x0>,
-					<0x0 0x34 0x3>,
-					<0x0 0x34 0x4>;
-			interrupt-names =	"eoc-int-en-set",
-						"high-thr-en-set",
-						"low-thr-en-set";
-			qcom,adc-bit-resolution = <15>;
-			qcom,adc-vdd-reference = <1800>;
-			qcom,adc_tm-vadc = <&pm8950_vadc>;
-			qcom,pmic-revid = <&pm8950_revid>;
-
-			chan@36 {
-				label = "pa_therm0";
-				reg = <0x36>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "ratiometric";
-				qcom,scale-function = <2>;
-				qcom,hw-settle-time = <2>;
-				qcom,fast-avg-setup = <0>;
-				qcom,btm-channel-number = <0x48>;
-				qcom,thermal-node;
-			};
-
-			chan@7 {
-				label = "vph_pwr";
-				reg = <0x7>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-				qcom,btm-channel-number = <0x68>;
-			};
-		};
-
-		pm8950_rtc: qcom,pm8950_rtc {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-rtc";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			qcom,qpnp-rtc-write = <0>;
-			qcom,qpnp-rtc-alarm-pwrup = <0>;
-
-			qcom,pm8950_rtc_rw@6000 {
-				reg = <0x6000 0x100>;
-			};
-
-			qcom,pm8950_rtc_alarm@6100 {
-				reg = <0x6100 0x100>;
-				interrupts = <0x0 0x61 0x1>;
-			};
-		};
-
-		qcom,leds@a300 {
-			compatible = "qcom,leds-qpnp";
-			reg = <0xa300 0x100>;
-			label = "mpp";
-		};
-	};
-
-	pm8950_1: qcom,pm8950@1 {
-		compatible ="qcom,spmi-pmic";
-		reg = <0x1 SPMI_USID>;
-		#address-cells = <2>;
-		#size-cells = <0>;
-
-		pm8950_pwm: pwm@bc00 {
-			status = "disabled";
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xbc00 0x100>;
-			reg-names = "qpnp-lpg-channel-base";
-			qcom,channel-id = <0>;
-			qcom,supported-sizes = <6>, <9>;
-			#pwm-cells = <2>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/qcom/pmi8950.dtsi b/arch/arm/boot/dts/qcom/pmi8950.dtsi
deleted file mode 100644
index 0ec1f0b..0000000
--- a/arch/arm/boot/dts/qcom/pmi8950.dtsi
+++ /dev/null
@@ -1,641 +0,0 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <dt-bindings/msm/power-on.h>
-
-&spmi_bus {
-	qcom,pmi8950@2 {
-		compatible ="qcom,spmi-pmic";
-		reg = <0x2 SPMI_USID>;
-		#address-cells = <2>;
-		#size-cells = <0>;
-
-		pmi8950_revid: qcom,revid@100 {
-			compatible = "qcom,qpnp-revid";
-			reg = <0x100 0x100>;
-		};
-
-		qcom,power-on@800 {
-			compatible = "qcom,qpnp-power-on";
-			reg = <0x800 0x100>;
-			qcom,secondary-pon-reset;
-			qcom,hard-reset-poweroff-type =
-				<PON_POWER_OFF_SHUTDOWN>;
-
-			pon_perph_reg: qcom,pon_perph_reg {
-				regulator-name = "pon_spare_reg";
-				qcom,pon-spare-reg-addr = <0x8c>;
-				qcom,pon-spare-reg-bit = <1>;
-			};
-		};
-
-		pmi8950_vadc: vadc@3100 {
-			compatible = "qcom,qpnp-vadc";
-			reg = <0x3100 0x100>;
-			#address-cells = <1>;
-			#size-cells = <0>;
-			interrupts = <0x2 0x31 0x0>;
-			interrupt-names = "eoc-int-en-set";
-			qcom,adc-bit-resolution = <15>;
-			qcom,adc-vdd-reference = <1800>;
-			qcom,vadc-poll-eoc;
-
-			chan@0 {
-				label = "usbin";
-				reg = <0>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <4>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@1 {
-				label = "dcin";
-				reg = <1>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <4>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@3 {
-				label = "vchg_sns";
-				reg = <3>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@9 {
-				label = "ref_625mv";
-				reg = <9>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@a {
-				label = "ref_1250v";
-				reg = <0xa>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@d {
-				label = "chg_temp";
-				reg = <0xd>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <0>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <16>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-				qcom,vadc-thermal-node;
-			};
-
-			chan@43 {
-				label = "usb_dp";
-				reg = <0x43>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-
-			chan@44 {
-				label = "usb_dm";
-				reg = <0x44>;
-				qcom,decimation = <0>;
-				qcom,pre-div-channel-scaling = <1>;
-				qcom,calibration-type = "absolute";
-				qcom,scale-function = <0>;
-				qcom,hw-settle-time = <0>;
-				qcom,fast-avg-setup = <0>;
-			};
-		};
-
-		pmi8950_gpios: gpios {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-pin";
-			gpio-controller;
-			#gpio-cells = <2>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			label = "pmi8950-gpio";
-
-			gpio@c000 {
-				reg = <0xc000 0x100>;
-				qcom,pin-num = <1>;
-				status = "disabled";
-			};
-
-			gpio@c100 {
-				reg = <0xc100 0x100>;
-				qcom,pin-num = <2>;
-				status = "disabled";
-			};
-		};
-
-		pmi8950_mpps: mpps {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-pin";
-			gpio-controller;
-			#gpio-cells = <2>;
-			#address-cells = <1>;
-			#size-cells = <1>;
-			label = "pmi8950-mpp";
-
-			mpp@a000 {
-				reg = <0xa000 0x100>;
-				qcom,pin-num = <1>;
-				status = "disabled";
-			};
-
-			mpp@a100 {
-				reg = <0xa100 0x100>;
-				qcom,pin-num = <2>;
-				status = "disabled";
-			};
-
-			mpp@a200 {
-				reg = <0xa200 0x100>;
-				qcom,pin-num = <3>;
-				status = "disabled";
-			};
-
-			mpp@a300 {
-				reg = <0xa300 0x100>;
-				qcom,pin-num = <4>;
-				status = "disabled";
-			};
-		};
-
-		pmi8950_charger: qcom,qpnp-smbcharger {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-smbcharger";
-			#address-cells = <1>;
-			#size-cells = <1>;
-
-			qcom,iterm-ma = <100>;
-			qcom,float-voltage-mv = <4200>;
-			qcom,resume-delta-mv = <200>;
-			qcom,chg-inhibit-fg;
-			qcom,rparasitic-uohm = <100000>;
-			qcom,bms-psy-name = "bms";
-			qcom,thermal-mitigation = <1500 700 600 0>;
-			qcom,parallel-usb-min-current-ma = <1400>;
-			qcom,parallel-usb-9v-min-current-ma = <900>;
-			qcom,parallel-allowed-lowering-ma = <500>;
-			qcom,pmic-revid = <&pmi8950_revid>;
-			qcom,force-aicl-rerun;
-			qcom,aicl-rerun-period-s = <180>;
-			qcom,autoadjust-vfloat;
-
-			qcom,chgr@1000 {
-				reg = <0x1000 0x100>;
-				interrupts =	<0x2 0x10 0x0>,
-						<0x2 0x10 0x1>,
-						<0x2 0x10 0x2>,
-						<0x2 0x10 0x3>,
-						<0x2 0x10 0x4>,
-						<0x2 0x10 0x5>,
-						<0x2 0x10 0x6>,
-						<0x2 0x10 0x7>;
-
-				interrupt-names =	"chg-error",
-							"chg-inhibit",
-							"chg-prechg-sft",
-							"chg-complete-chg-sft",
-							"chg-p2f-thr",
-							"chg-rechg-thr",
-							"chg-taper-thr",
-							"chg-tcc-thr";
-			};
-
-			qcom,otg@1100 {
-				reg = <0x1100 0x100>;
-				interrupts =	<0x2 0x11 0x0>,
-						<0x2 0x11 0x1>,
-						<0x2 0x11 0x3>;
-				interrupt-names =	"otg-fail",
-							"otg-oc",
-						"usbid-change";
-			};
-
-			qcom,bat-if@1200 {
-				reg = <0x1200 0x100>;
-				interrupts =	<0x2 0x12 0x0>,
-						<0x2 0x12 0x1>,
-						<0x2 0x12 0x2>,
-						<0x2 0x12 0x3>,
-					<0x2 0x12 0x4>,
-						<0x2 0x12 0x5>,
-						<0x2 0x12 0x6>,
-						<0x2 0x12 0x7>;
-
-				interrupt-names =	"batt-hot",
-							"batt-warm",
-							"batt-cold",
-							"batt-cool",
-						"batt-ov",
-							"batt-low",
-							"batt-missing",
-							"batt-term-missing";
-			};
-
-			qcom,usb-chgpth@1300 {
-				reg = <0x1300 0x100>;
-				interrupts =	<0x2 0x13 0x0>,
-						<0x2 0x13 0x1>,
-					<0x2 0x13 0x2>,
-						<0x2 0x13 0x5>;
-
-				interrupt-names =	"usbin-uv",
-						"usbin-ov",
-							"usbin-src-det",
-							"aicl-done";
-			};
-
-			qcom,dc-chgpth@1400 {
-				reg = <0x1400 0x100>;
-				interrupts =	<0x2 0x14 0x0>,
-						<0x2 0x14 0x1>;
-				interrupt-names =	"dcin-uv",
-							"dcin-ov";
-			};
-
-			qcom,chgr-misc@1600 {
-				reg = <0x1600 0x100>;
-				interrupts =	<0x2 0x16 0x0>,
-						<0x2 0x16 0x1>,
-						<0x2 0x16 0x2>,
-					<0x2 0x16 0x3>,
-						<0x2 0x16 0x4>,
-						<0x2 0x16 0x5>;
-
-				interrupt-names =	"power-ok",
-							"temp-shutdown",
-							"wdog-timeout",
-							"flash-fail",
-							"otst2",
-							"otst3";
-			};
-
-			smbcharger_charger_otg: qcom,smbcharger-boost-otg {
-				regulator-name = "smbcharger_charger_otg";
-			};
-		};
-
-		pmi8950_fg: qcom,fg {
-			spmi-dev-container;
-			compatible = "qcom,qpnp-fg";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			qcom,resume-soc = <95>;
-			status = "okay";
-			qcom,bcl-lm-threshold-ma = <127>;
-			qcom,bcl-mh-threshold-ma = <405>;
-			qcom,fg-iterm-ma = <150>;
-			qcom,fg-chg-iterm-ma = <100>;
-			qcom,pmic-revid = <&pmi8950_revid>;
-			qcom,fg-cutoff-voltage-mv = <3500>;
-			qcom,cycle-counter-en;
-			qcom,capacity-learning-on;
-
-			qcom,fg-soc@4000 {
-			status = "okay";
-				reg = <0x4000 0x100>;
-				interrupts =	<0x2 0x40 0x0>,
-						<0x2 0x40 0x1>,
-						<0x2 0x40 0x2>,
-						<0x2 0x40 0x3>,
-						<0x2 0x40 0x4>,
-						<0x2 0x40 0x5>,
-						<0x2 0x40 0x6>;
-
-				interrupt-names =	"high-soc",
-							"low-soc",
-							"full-soc",
-							"empty-soc",
-							"delta-soc",
-							"first-est-done",
-							"update-soc";
-			};
-
-			qcom,fg-batt@4100 {
-				reg = <0x4100 0x100>;
-				interrupts =	<0x2 0x41 0x0>,
-						<0x2 0x41 0x1>,
-					<0x2 0x41 0x2>,
-						<0x2 0x41 0x3>,
-						<0x2 0x41 0x4>,
-						<0x2 0x41 0x5>,
-						<0x2 0x41 0x6>,
-						<0x2 0x41 0x7>;
-
-				interrupt-names =	"soft-cold",
-							"soft-hot",
-							"vbatt-low",
-							"batt-ided",
-							"batt-id-req",
-							"batt-unknown",
-							"batt-missing",
-							"batt-match";
-			};
-
-			qcom,revid-tp-rev@1f1 {
-				reg = <0x1f1 0x1>;
-			};
-
-			qcom,fg-memif@4400 {
-				status = "okay";
-				reg = <0x4400 0x100>;
-				interrupts =	<0x2 0x44 0x0>,
-						<0x2 0x44 0x2>;
-
-				interrupt-names =	"mem-avail",
-							"data-rcvry-sug";
-			};
-		};
-
-		bcl@4200 {
-			compatible = "qcom,msm-bcl";
-			reg = <0x4200 0xFF 0x88E 0x2>;
-			reg-names = "fg_user_adc", "pon_spare";
-			interrupts = <0x2 0x42 0x0>,
-					<0x2 0x42 0x1>;
-			interrupt-names = "bcl-high-ibat-int",
-					"bcl-low-vbat-int";
-			qcom,vbat-scaling-factor = <39000>;
-			qcom,vbat-gain-numerator = <1>;
-			qcom,vbat-gain-denominator = <128>;
-			qcom,vbat-polling-delay-ms = <100>;
-			qcom,ibat-scaling-factor = <39000>;
-			qcom,ibat-gain-numerator = <1>;
-			qcom,ibat-gain-denominator = <128>;
-			qcom,ibat-offset-numerator = <1200>;
-			qcom,ibat-offset-denominator = <1>;
-			qcom,ibat-polling-delay-ms = <100>;
-			qcom,inhibit-derating-ua = <550000>;
-		};
-
-		qcom,leds@a100 {
-			compatible = "qcom,leds-qpnp";
-			reg = <0xa100 0x100>;
-			label = "mpp";
-		};
-	};
-
-	qcom,pmi8950@3 {
-		compatible ="qcom,spmi-pmic";
-		reg = <0x3 SPMI_USID>;
-		#address-cells = <1>;
-		#size-cells = <1>;
-
-		pmi8950_pwm: pwm@b000 {
-			status = "disabled";
-			compatible = "qcom,qpnp-pwm";
-			reg = <0xb000 0x100>;
-			reg-names = "qpnp-lpg-channel-base";
-			qcom,channel-id = <0>;
-			qcom,supported-sizes = <6>, <9>;
-			#pwm-cells = <2>;
-		};
-
-		labibb: qpnp-labibb-regulator {
-			status = "disabled";
-			spmi-dev-container;
-			compatible = "qcom,qpnp-labibb-regulator";
-			#address-cells = <1>;
-			#size-cells = <1>;
-			qcom,pmic-revid = <&pmi8950_revid>;
-
-			ibb_regulator: qcom,ibb@dc00 {
-				reg = <0xdc00 0x100>;
-				reg-names = "ibb_reg";
-				regulator-name = "ibb_reg";
-
-				regulator-min-microvolt = <4600000>;
-				regulator-max-microvolt = <6000000>;
-
-				qcom,qpnp-ibb-min-voltage = <1400000>;
-				qcom,qpnp-ibb-step-size = <100000>;
-				qcom,qpnp-ibb-slew-rate = <2000000>;
-				qcom,qpnp-ibb-use-default-voltage;
-				qcom,qpnp-ibb-init-voltage = <5500000>;
-				qcom,qpnp-ibb-init-amoled-voltage = <4000000>;
-				qcom,qpnp-ibb-init-lcd-voltage = <5500000>;
-
-				qcom,qpnp-ibb-soft-start = <1000>;
-
-				qcom,qpnp-ibb-discharge-resistor = <32>;
-				qcom,qpnp-ibb-lab-pwrup-delay = <8000>;
-				qcom,qpnp-ibb-lab-pwrdn-delay = <8000>;
-				qcom,qpnp-ibb-en-discharge;
-
-				qcom,qpnp-ibb-full-pull-down;
-				qcom,qpnp-ibb-pull-down-enable;
-				qcom,qpnp-ibb-switching-clock-frequency =
-									<1480>;
-				qcom,qpnp-ibb-limit-maximum-current = <1550>;
-				qcom,qpnp-ibb-debounce-cycle = <16>;
-				qcom,qpnp-ibb-limit-max-current-enable;
-				qcom,qpnp-ibb-ps-enable;
-			};
-
-			lab_regulator: qcom,lab@de00 {
-				reg = <0xde00 0x100>;
-				reg-names = "lab";
-				regulator-name = "lab_reg";
-
-				regulator-min-microvolt = <4600000>;
-				regulator-max-microvolt = <6000000>;
-
-				qcom,qpnp-lab-min-voltage = <4600000>;
-				qcom,qpnp-lab-step-size = <100000>;
-				qcom,qpnp-lab-slew-rate = <5000>;
-				qcom,qpnp-lab-use-default-voltage;
-				qcom,qpnp-lab-init-voltage = <5500000>;
-				qcom,qpnp-lab-init-amoled-voltage = <4600000>;
-				qcom,qpnp-lab-init-lcd-voltage = <5500000>;
-
-				qcom,qpnp-lab-soft-start = <800>;
-
-				qcom,qpnp-lab-full-pull-down;
-				qcom,qpnp-lab-pull-down-enable;
-				qcom,qpnp-lab-switching-clock-frequency =
-									<1600>;
-				qcom,qpnp-lab-limit-maximum-current = <800>;
-				qcom,qpnp-lab-limit-max-current-enable;
-				qcom,qpnp-lab-ps-threshold = <40>;
-				qcom,qpnp-lab-ps-enable;
-				qcom,qpnp-lab-nfet-size = <100>;
-				qcom,qpnp-lab-pfet-size = <100>;
-				qcom,qpnp-lab-max-precharge-time = <500>;
-			};
-
-		};
-
-		wled: qcom,leds@d800 {
-			compatible = "qcom,qpnp-wled";
-			reg = <0xd800 0x100>,
-				<0xd900 0x100>,
-				<0xdc00 0x100>,
-				<0xde00 0x100>;
-			reg-names = "qpnp-wled-ctrl-base",
-					"qpnp-wled-sink-base",
-					"qpnp-wled-ibb-base",
-					"qpnp-wled-lab-base";
-			interrupts = <0x3 0xd8 0x2>;
-			interrupt-names = "sc-irq";
-			status = "okay";
-			linux,name = "wled";
-			linux,default-trigger = "bkl-trigger";
-			qcom,fdbk-output = "auto";
-			qcom,vref-mv = <350>;
-			qcom,switch-freq-khz = <800>;
-			qcom,ovp-mv = <29500>;
-			qcom,ilim-ma = <980>;
-			qcom,boost-duty-ns = <26>;
-			qcom,mod-freq-khz = <9600>;
-			qcom,dim-mode = "hybrid";
-			qcom,dim-method = "linear";
-			qcom,hyb-thres = <625>;
-			qcom,sync-dly-us = <800>;
-			qcom,fs-curr-ua = <20000>;
-			qcom,led-strings-list = [00 01];
-			qcom,en-ext-pfet-sc-pro;
-			qcom,cons-sync-write-delay-us = <1000>;
-		};
-
-		flash_led: qcom,leds@d300 {
-			compatible = "qcom,qpnp-flash-led";
-			status = "okay";
-			reg = <0xd300 0x100>;
-			label = "flash";
-			qcom,headroom = <500>;
-			qcom,startup-dly = <128>;
-			qcom,clamp-curr = <200>;
-			qcom,pmic-charger-support;
-			qcom,self-check-enabled;
-			qcom,thermal-derate-enabled;
-			qcom,thermal-derate-threshold = <100>;
-			qcom,thermal-derate-rate = "5_PERCENT";
-			qcom,current-ramp-enabled;
-			qcom,ramp_up_step = "6P7_US";
-			qcom,ramp_dn_step = "6P7_US";
-			qcom,vph-pwr-droop-enabled;
-			qcom,vph-pwr-droop-threshold = <3000>;
-			qcom,vph-pwr-droop-debounce-time = <10>;
-			qcom,headroom-sense-ch0-enabled;
-			qcom,headroom-sense-ch1-enabled;
-			qcom,pmic-revid = <&pmi8950_revid>;
-
-			pmi8950_flash0: qcom,flash_0 {
-				label = "flash";
-				qcom,led-name = "led:flash_0";
-				qcom,default-led-trigger =
-						"flash0_trigger";
-				qcom,max-current = <1000>;
-				qcom,duration = <1280>;
-				qcom,id = <0>;
-				qcom,current = <625>;
-			};
-
-			pmi8950_flash1: qcom,flash_1 {
-				label = "flash";
-				qcom,led-name = "led:flash_1";
-				qcom,default-led-trigger =
-						"flash1_trigger";
-				qcom,max-current = <1000>;
-				qcom,duration = <1280>;
-				qcom,id = <1>;
-				qcom,current = <625>;
-			};
-
-			pmi8950_torch0: qcom,torch_0 {
-				label = "torch";
-				qcom,led-name = "led:torch_0";
-				qcom,default-led-trigger =
-						"torch0_trigger";
-				qcom,max-current = <200>;
-				qcom,id = <0>;
-				qcom,current = <120>;
-			};
-
-			pmi8950_torch1: qcom,torch_1 {
-				label = "torch";
-				qcom,led-name = "led:torch_1";
-				qcom,default-led-trigger =
-						"torch1_trigger";
-				qcom,max-current = <200>;
-				qcom,id = <1>;
-				qcom,current = <120>;
-			};
-
-			pmi8950_switch: qcom,switch {
-				label = "switch";
-				qcom,led-name = "led:switch";
-				qcom,default-led-trigger =
-						"switch_trigger";
-				qcom,max-current = <1000>;
-				qcom,duration = <1280>;
-				qcom,id = <2>;
-				qcom,current = <625>;
-				reg0 {
-					regulator-name = "pon_spare_reg";
-				};
-			};
-		};
-
-		pmi_haptic: qcom,haptic@c000 {
-			compatible = "qcom,qpnp-haptic";
-			reg = <0xc000 0x100>;
-			interrupts = <0x3 0xc0 0x0>,
-					<0x3 0xc0 0x1>;
-			interrupt-names = "sc-irq", "play-irq";
-			qcom,pmic-revid = <&pmi8950_revid>;
-			vcc_pon-supply = <&pon_perph_reg>;
-			qcom,play-mode = "direct";
-			qcom,wave-play-rate-us = <5263>;
-			qcom,actuator-type = "erm";
-			qcom,wave-shape = "square";
-			qcom,vmax-mv = <2000>;
-			qcom,ilim-ma = <800>;
-			qcom,sc-deb-cycles = <8>;
-			qcom,int-pwm-freq-khz = <505>;
-			qcom,en-brake;
-			qcom,brake-pattern = [03 03 00 00];
-			qcom,use-play-irq;
-			qcom,use-sc-irq;
-			qcom,wave-samples = [3e 3e 3e 3e 3e 3e 3e 3e];
-			qcom,wave-rep-cnt = <1>;
-			qcom,wave-samp-rep-cnt = <1>;
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
index eb5c210..c652a44 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-coresight.dtsi
@@ -504,7 +504,7 @@
 			};
 
 			port@2 {
-				reg = <3>;
+				reg = <1>;
 				funnel_in1_in_modem_etm0: endpoint {
 					slave-mode;
 					remote-endpoint =
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
index e90d97d..52eaba3 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-cdp.dts
@@ -21,6 +21,15 @@
 	qcom,board-id = <1 0x1>, <1 0x101>;
 };
 
+&vbus_detect {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+	extcon = <&vbus_detect>;
+};
+
 &pcie_ep {
 	status = "okay";
 };
@@ -28,3 +37,7 @@
 &pcie0 {
 	status = "disabled";
 };
+
+&mhi_device {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
index 86d8636..b68e401 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pcie-ep-mtp.dts
@@ -21,6 +21,15 @@
 	qcom,board-id = <8 0x1>, <8 0x101>;
 };
 
+&vbus_detect {
+	status = "okay";
+};
+
+&usb {
+	status = "okay";
+	extcon = <&vbus_detect>;
+};
+
 &pcie_ep {
 	status = "okay";
 };
@@ -28,3 +37,7 @@
 &pcie0 {
 	status = "disabled";
 };
+
+&mhi_device {
+	status = "okay";
+};
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
index 6c172c1..e3f49d0 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pinctrl.dtsi
@@ -1465,6 +1465,64 @@
 				input-enable;
 			};
 		};
+
+		cnss_pins {
+			cnss_wlan_en_active: cnss_wlan_en_active {
+				mux {
+					pins = "gpio52";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio52";
+					drive-strength = <16>;
+					output-high;
+					bias-pull-up;
+				};
+			};
+
+			cnss_wlan_en_sleep: cnss_wlan_en_sleep {
+				mux {
+					pins = "gpio52";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio52";
+					drive-strength = <2>;
+					output-low;
+					bias-pull-down;
+				};
+			};
+
+			cnss_sdio_active: cnss_sdio_active {
+				mux {
+					pins = "gpio31";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio31";
+					drive-strength = <16>;
+					output-high;
+					bias-pull-up;
+				};
+			};
+
+			cnss_sdio_sleep: cnss_sdio_sleep {
+				mux {
+					pins = "gpio31";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio31";
+					drive-strength = <2>;
+					output-low;
+					bias-pull-down;
+				};
+			};
+		};
 	};
 };
 
@@ -1475,4 +1533,11 @@
 			bias-high-impedance;
 		};
 	};
+
+	vdd_wlan {
+		vdd_wlan_default: vdd_wlan_default {
+			pins = "gpio6";
+			bias-high-impedance;
+		};
+	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
index eab887c..4111071 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-pm.dtsi
@@ -92,4 +92,10 @@
 			};
 		};
 	};
+
+	qcom,rpm-stats@c300000 {
+		compatible = "qcom,rpm-stats";
+		reg = <0xC300000 0x1000>, <0xC3F0004 0x4>;
+		reg-names = "phys_addr_base", "offset_addr";
+	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
index 162f0d9..7543f7c 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-regulator.dtsi
@@ -404,4 +404,12 @@
 		gpio = <&tlmm 83 GPIO_ACTIVE_HIGH>;
 		enable-active-high;
 	};
+
+	vreg_wlan: vreg_wlan {
+		compatible = "regulator-fixed";
+		regulator-name = "vreg_wlan";
+		startup-delay-us = <4000>;
+		enable-active-high;
+		gpio = <&pmxpoorwills_gpios 6 GPIO_ACTIVE_HIGH>;
+	};
 };
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
index ec65472..3bccd8a 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills-usb.dtsi
@@ -126,6 +126,9 @@
 
 		resets = <&clock_gcc GCC_QUSB2PHY_BCR>;
 		reset-names = "phy_reset";
+
+		/* override parameters */
+		qcom,param-override-seq = <0x43 0x70>; /* override_x1 */
 	};
 
 	dbm_1p5: dbm@a6f8000 {
diff --git a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
index 8f59515..d9a84d9 100644
--- a/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
+++ b/arch/arm/boot/dts/qcom/sdxpoorwills.dtsi
@@ -61,6 +61,12 @@
 			reusable;
 			size = <0x400000>;
 		 };
+
+		dump_mem: mem_dump_region {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0 0x2400000>;
+		};
 	};
 
 	cpus {
@@ -419,6 +425,23 @@
 		status = "disabled";
 	};
 
+	mhi_device: mhi_dev@1c04000 {
+		compatible = "qcom,msm-mhi-dev";
+		reg = <0x1c04000 0x1000>,
+			<0x1e22000 0x4>,
+			<0x1e22148 0x4>;
+			reg-names = "mhi_mmio_base", "ipa_uc_mbox_crdb",
+			"ipa_uc_mbox_erdb";
+			qcom,mhi-ep-msi = <0>;
+			qcom,mhi-version = <0x1000000>;
+			qcom,use-ipa-software-channel;
+			interrupts = <0 145 0>;
+			interrupt-names = "mhi-device-inta";
+			qcom,mhi-ifc-id = <0x030417cb>;
+			qcom,mhi-interrupt;
+		status = "disabled";
+	};
+
 	gdsc_emac: qcom,gdsc@147004 {
 		compatible = "qcom,gdsc";
 		regulator-name = "gdsc_emac";
@@ -710,6 +733,56 @@
 		reg = <0xc37000c 8>;
 	};
 
+	mem_dump {
+		compatible = "qcom,mem-dump";
+		memory-region = <&dump_mem>;
+
+		rpmh_dump {
+			qcom,dump-size = <0x2000000>;
+			qcom,dump-id = <0xec>;
+		};
+
+		fcm_dump {
+			qcom,dump-size = <0x8400>;
+			qcom,dump-id = <0xee>;
+		};
+
+		rpm_sw_dump {
+			qcom,dump-size = <0x28000>;
+			qcom,dump-id = <0xea>;
+		};
+
+		pmic_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xe4>;
+		};
+
+		tmc_etf_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xf0>;
+		};
+
+		tmc_etr_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x100>;
+		};
+
+		tmc_etf_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x101>;
+		};
+
+		misc_data_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0xe8>;
+		};
+
+		tpdm_swao_dump {
+			qcom,dump-size = <0x512>;
+			qcom,dump-id = <0xf2>;
+		};
+	};
+
 	qcom,msm_gsi {
 		compatible = "qcom,msm_gsi";
 	};
@@ -895,11 +968,11 @@
 		#mbox-cells = <1>;
 	};
 
-	usb_detect: qcom,gpio-usbdetect {
-		compatible = "qcom,gpio-usbdetect";
+	vbus_detect: qcom,pmd-vbus-det {
+		compatible = "qcom,pmd-vbus-det";
 		interrupt-parent = <&spmi_bus>;
 		interrupts = <0x0 0x0d 0x0 IRQ_TYPE_NONE>;
-		interrupt-names = "vbus_det_irq";
+		interrupt-names = "usb_vbus";
 		status = "disabled";
 	};
 
@@ -997,6 +1070,46 @@
 		compatible = "qcom,msm-rtb";
 		qcom,rtb-size = <0x100000>;
 	};
+
+	cnss_pcie: qcom,cnss {
+		compatible = "qcom,cnss";
+		wlan-en-gpio = <&tlmm 52 0>;
+		vdd-wlan-supply = <&vreg_wlan>;
+		vdd-wlan-xtal-supply = <&pmxpoorwills_l6>;
+		vdd-wlan-io-supply = <&pmxpoorwills_l6>;
+		qcom,notify-modem-status;
+		pinctrl-names = "wlan_en_active", "wlan_en_sleep";
+		pinctrl-0 = <&cnss_wlan_en_active>;
+		pinctrl-1 = <&cnss_wlan_en_sleep>;
+		qcom,wlan-rc-num = <0>;
+		qcom,wlan-ramdump-dynamic = <0x200000>;
+
+		qcom,msm-bus,name = "msm-cnss";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+				<45 512 0 0>, <1 512 0 0>,
+				/* Upto 200 Mbps */
+				<45 512 41421 655360>, <1 512 41421 655360>,
+				/* Upto 400 Mbps */
+				<45 512 98572 655360>, <1 512 98572 1600000>,
+				/* Upto 800 Mbps */
+				<45 512 207108 1146880>, <1 512 207108 3124992>;
+	};
+
+	cnss_sdio: qcom,cnss_sdio {
+		compatible = "qcom,cnss_sdio";
+		subsys-name = "AR6320_SDIO";
+		vdd-wlan-supply = <&vreg_wlan>;
+		vdd-wlan-xtal-supply = <&pmxpoorwills_l5>;
+		vdd-wlan-io-supply = <&pmxpoorwills_l6>;
+		qcom,wlan-ramdump-dynamic = <0x200000>;
+		pinctrl-names = "active", "sleep";
+		pinctrl-0 = <&cnss_sdio_active>;
+		pinctrl-1 = <&cnss_sdio_sleep>;
+		qcom,is-antenna-shared;
+		status = "disabled";
+	};
 };
 
 #include "pmxpoorwills.dtsi"
diff --git a/arch/arm/configs/msm8953-perf_defconfig b/arch/arm/configs/msm8953-perf_defconfig
index 7f4120f..4d5ebe4 100644
--- a/arch/arm/configs/msm8953-perf_defconfig
+++ b/arch/arm/configs/msm8953-perf_defconfig
@@ -275,6 +275,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -288,8 +289,12 @@
 # CONFIG_SERIO_SERPORT is not set
 # CONFIG_VT is not set
 # CONFIG_LEGACY_PTYS is not set
+CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_SMD_PKT=y
 CONFIG_MSM_ADSPRPC=y
 CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
@@ -312,8 +317,10 @@
 CONFIG_QPNP_FG=y
 CONFIG_SMB135X_CHARGER=y
 CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
 CONFIG_QPNP_SMBCHARGER=y
 CONFIG_QPNP_TYPEC=y
+CONFIG_QPNP_QG=y
 CONFIG_MSM_APM=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
@@ -326,6 +333,7 @@
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_CPR=y
 CONFIG_REGULATOR_CPR4_APSS=y
 CONFIG_REGULATOR_CPRH_KBSS=y
 CONFIG_REGULATOR_MEM_ACC=y
@@ -341,7 +349,13 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_QCOM_KGSL=y
 CONFIG_FB=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_LOGO=y
@@ -382,7 +396,6 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_MSM=y
 CONFIG_USB_SERIAL=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
@@ -408,9 +421,11 @@
 CONFIG_USB_CONFIGFS_F_ACC=y
 CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
 CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
 CONFIG_USB_CONFIGFS_F_HID=y
 CONFIG_USB_CONFIGFS_F_DIAG=y
 CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
@@ -426,6 +441,7 @@
 CONFIG_MMC_CQ_HCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QTI_TRI_LED=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_QPNP_FLASH=y
 CONFIG_LEDS_QPNP_FLASH_V2=y
@@ -433,6 +449,7 @@
 CONFIG_LEDS_QPNP_HAPTICS=y
 CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
 CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
@@ -454,8 +471,12 @@
 CONFIG_QPNP_COINCELL=y
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
+CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
 CONFIG_MSM_BOOT_STATS=y
@@ -468,14 +489,10 @@
 CONFIG_MSM_SMEM=y
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_DEBUG=y
-CONFIG_MSM_GLINK=y
-CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
-CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
-CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_TZ_SMMU=y
 CONFIG_MSM_SMP2P=y
-CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
-CONFIG_MSM_GLINK_PKT=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
@@ -486,9 +503,19 @@
 CONFIG_MSM_PM=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
+CONFIG_PWM_QTI_LPG=y
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/msm8953_defconfig b/arch/arm/configs/msm8953_defconfig
index 2f76154..ad2c8bf 100644
--- a/arch/arm/configs/msm8953_defconfig
+++ b/arch/arm/configs/msm8953_defconfig
@@ -285,6 +285,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -300,8 +301,12 @@
 # CONFIG_LEGACY_PTYS is not set
 CONFIG_SERIAL_MSM=y
 CONFIG_SERIAL_MSM_CONSOLE=y
+CONFIG_SERIAL_MSM_SMD=y
+CONFIG_DIAG_CHAR=y
+CONFIG_DIAG_USES_SMD=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM_LEGACY=y
+CONFIG_MSM_SMD_PKT=y
 CONFIG_MSM_ADSPRPC=y
 CONFIG_MSM_RDBG=m
 CONFIG_I2C_CHARDEV=y
@@ -324,8 +329,10 @@
 CONFIG_QPNP_FG=y
 CONFIG_SMB135X_CHARGER=y
 CONFIG_SMB1351_USB_CHARGER=y
+CONFIG_QPNP_SMB5=y
 CONFIG_QPNP_SMBCHARGER=y
 CONFIG_QPNP_TYPEC=y
+CONFIG_QPNP_QG=y
 CONFIG_MSM_APM=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
@@ -338,6 +345,7 @@
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_PROXY_CONSUMER=y
+CONFIG_REGULATOR_CPR=y
 CONFIG_REGULATOR_CPR4_APSS=y
 CONFIG_REGULATOR_CPRH_KBSS=y
 CONFIG_REGULATOR_MEM_ACC=y
@@ -353,8 +361,14 @@
 CONFIG_MEDIA_CONTROLLER=y
 CONFIG_VIDEO_V4L2_SUBDEV_API=y
 CONFIG_V4L_PLATFORM_DRIVERS=y
+CONFIG_QCOM_KGSL=y
 CONFIG_FB=y
 CONFIG_FB_VIRTUAL=y
+CONFIG_FB_MSM=y
+CONFIG_FB_MSM_MDSS=y
+CONFIG_FB_MSM_MDSS_WRITEBACK=y
+CONFIG_FB_MSM_MDSS_DSI_CTRL_STATUS=y
+CONFIG_FB_MSM_MDSS_XLOG_DEBUG=y
 CONFIG_BACKLIGHT_LCD_SUPPORT=y
 CONFIG_BACKLIGHT_CLASS_DEVICE=y
 CONFIG_LOGO=y
@@ -395,7 +409,6 @@
 CONFIG_USB_STORAGE_KARMA=y
 CONFIG_USB_STORAGE_CYPRESS_ATACB=y
 CONFIG_USB_DWC3=y
-CONFIG_USB_DWC3_GADGET=y
 CONFIG_USB_DWC3_MSM=y
 CONFIG_USB_SERIAL=y
 CONFIG_USB_EHSET_TEST_FIXTURE=y
@@ -421,9 +434,11 @@
 CONFIG_USB_CONFIGFS_F_ACC=y
 CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
 CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
 CONFIG_USB_CONFIGFS_F_HID=y
 CONFIG_USB_CONFIGFS_F_DIAG=y
 CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
@@ -440,6 +455,7 @@
 CONFIG_MMC_CQ_HCI=y
 CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
+CONFIG_LEDS_QTI_TRI_LED=y
 CONFIG_LEDS_QPNP=y
 CONFIG_LEDS_QPNP_FLASH=y
 CONFIG_LEDS_QPNP_FLASH_V2=y
@@ -447,6 +463,7 @@
 CONFIG_LEDS_QPNP_HAPTICS=y
 CONFIG_LEDS_QPNP_VIBRATOR_LDO=y
 CONFIG_LEDS_TRIGGERS=y
+CONFIG_LEDS_TRIGGER_TIMER=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_RTC_CLASS=y
@@ -469,9 +486,15 @@
 CONFIG_QPNP_REVID=y
 CONFIG_USB_BAM=y
 CONFIG_MSM_EXT_DISPLAY=y
+CONFIG_MSM_MDSS_PLL=y
 CONFIG_REMOTE_SPINLOCK_MSM=y
 CONFIG_MAILBOX=y
-# CONFIG_IOMMU_SUPPORT is not set
+CONFIG_ARM_SMMU=y
+CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_IOMMU_DEBUG=y
+CONFIG_IOMMU_DEBUG_TRACKING=y
+CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
 CONFIG_MSM_BOOT_STATS=y
@@ -486,15 +509,11 @@
 CONFIG_MSM_SMEM=y
 CONFIG_MSM_SMD=y
 CONFIG_MSM_SMD_DEBUG=y
-CONFIG_MSM_GLINK=y
-CONFIG_MSM_GLINK_LOOPBACK_SERVER=y
-CONFIG_MSM_GLINK_SMEM_NATIVE_XPRT=y
-CONFIG_MSM_GLINK_SPI_XPRT=y
+CONFIG_MSM_TZ_SMMU=y
 CONFIG_TRACER_PKT=y
 CONFIG_MSM_SMP2P=y
-CONFIG_MSM_IPC_ROUTER_GLINK_XPRT=y
+CONFIG_MSM_IPC_ROUTER_SMD_XPRT=y
 CONFIG_MSM_QMI_INTERFACE=y
-CONFIG_MSM_GLINK_PKT=y
 CONFIG_MSM_SUBSYSTEM_RESTART=y
 CONFIG_MSM_PIL=y
 CONFIG_MSM_PIL_SSR_GENERIC=y
@@ -505,9 +524,19 @@
 CONFIG_MSM_PM=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
+CONFIG_WCNSS_CORE=y
+CONFIG_WCNSS_CORE_PRONTO=y
+CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_SPDM_SCM=y
+CONFIG_DEVFREQ_SPDM=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
+CONFIG_PWM_QTI_LPG=y
 CONFIG_QTI_MPM=y
 CONFIG_ANDROID=y
 CONFIG_ANDROID_BINDER_IPC=y
diff --git a/arch/arm/configs/sdxpoorwills-perf_defconfig b/arch/arm/configs/sdxpoorwills-perf_defconfig
index 1f04446..54fc9eb 100644
--- a/arch/arm/configs/sdxpoorwills-perf_defconfig
+++ b/arch/arm/configs/sdxpoorwills-perf_defconfig
@@ -142,6 +142,7 @@
 CONFIG_BRIDGE_EBT_DNAT=y
 CONFIG_BRIDGE_EBT_SNAT=y
 CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_PRIO=y
 CONFIG_RMNET_DATA=y
@@ -199,7 +200,12 @@
 CONFIG_USB_NET_SMSC75XX=y
 CONFIG_USB_NET_SMSC95XX=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+CONFIG_CNSS_PCI=y
+CONFIG_CLD_HL_SDIO_CORE=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_LOGGER=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
@@ -231,6 +237,7 @@
 CONFIG_POWER_RESET_QCOM=y
 CONFIG_QCOM_DLOAD_MODE=y
 CONFIG_POWER_SUPPLY=y
+CONFIG_SMB1351_USB_CHARGER=y
 CONFIG_SMB138X_CHARGER=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
@@ -323,7 +330,6 @@
 CONFIG_EP_PCIE=y
 CONFIG_EP_PCIE_HW=y
 CONFIG_QPNP_REVID=y
-CONFIG_GPIO_USB_DETECT=y
 CONFIG_USB_BAM=y
 CONFIG_MSM_CLK_RPMH=y
 CONFIG_MSM_CLK_AOP_QMP=y
@@ -340,6 +346,7 @@
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_QCOM_BUS_SCALING=y
 CONFIG_QCOM_BUS_CONFIG_RPMH=y
 CONFIG_MSM_SMEM=y
@@ -359,6 +366,7 @@
 CONFIG_MSM_PM=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
+CONFIG_EXTCON_QCOM_SPMI_MISC=y
 CONFIG_IIO=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
diff --git a/arch/arm/configs/sdxpoorwills_defconfig b/arch/arm/configs/sdxpoorwills_defconfig
index 0b5a266..ac19abd 100644
--- a/arch/arm/configs/sdxpoorwills_defconfig
+++ b/arch/arm/configs/sdxpoorwills_defconfig
@@ -144,6 +144,7 @@
 CONFIG_BRIDGE_EBT_DNAT=y
 CONFIG_BRIDGE_EBT_SNAT=y
 CONFIG_BRIDGE=y
+CONFIG_VLAN_8021Q=y
 CONFIG_NET_SCHED=y
 CONFIG_NET_SCH_PRIO=y
 CONFIG_RMNET_DATA=y
@@ -191,7 +192,12 @@
 CONFIG_USB_NET_SMSC75XX=y
 CONFIG_USB_NET_SMSC95XX=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CNSS=y
+CONFIG_CNSS_SDIO=y
+CONFIG_CNSS_PCI=y
+CONFIG_CLD_HL_SDIO_CORE=y
 CONFIG_CLD_LL_CORE=y
+CONFIG_CNSS_LOGGER=y
 # CONFIG_INPUT_MOUSEDEV is not set
 CONFIG_INPUT_EVDEV=y
 # CONFIG_INPUT_KEYBOARD is not set
@@ -224,6 +230,7 @@
 CONFIG_POWER_RESET_QCOM=y
 CONFIG_QCOM_DLOAD_MODE=y
 CONFIG_POWER_SUPPLY=y
+CONFIG_SMB1351_USB_CHARGER=y
 CONFIG_SMB138X_CHARGER=y
 CONFIG_SENSORS_QPNP_ADC_VOLTAGE=y
 CONFIG_THERMAL=y
@@ -322,7 +329,6 @@
 CONFIG_EP_PCIE=y
 CONFIG_EP_PCIE_HW=y
 CONFIG_QPNP_REVID=y
-CONFIG_GPIO_USB_DETECT=y
 CONFIG_USB_BAM=y
 CONFIG_MSM_CLK_RPMH=y
 CONFIG_MSM_CLK_AOP_QMP=y
@@ -339,6 +345,7 @@
 CONFIG_QCOM_SCM=y
 CONFIG_MSM_BOOT_STATS=y
 CONFIG_QCOM_WATCHDOG_V2=y
+CONFIG_QCOM_MEMORY_DUMP_V2=y
 CONFIG_QCOM_BUS_SCALING=y
 CONFIG_QCOM_BUS_CONFIG_RPMH=y
 CONFIG_MSM_SMEM=y
@@ -359,6 +366,7 @@
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
+CONFIG_EXTCON_QCOM_SPMI_MISC=y
 CONFIG_IIO=y
 CONFIG_PWM=y
 CONFIG_PWM_QPNP=y
diff --git a/arch/arm/kvm/arm.c b/arch/arm/kvm/arm.c
index 19b5f5c..c38bfbe 100644
--- a/arch/arm/kvm/arm.c
+++ b/arch/arm/kvm/arm.c
@@ -1165,6 +1165,7 @@
 			cpu_hyp_reset();
 
 		return NOTIFY_OK;
+	case CPU_PM_ENTER_FAILED:
 	case CPU_PM_EXIT:
 		if (__this_cpu_read(kvm_arm_hardware_enabled))
 			/* The hardware was enabled before suspend. */
diff --git a/arch/arm/kvm/handle_exit.c b/arch/arm/kvm/handle_exit.c
index 42f5daf..4e57ebc 100644
--- a/arch/arm/kvm/handle_exit.c
+++ b/arch/arm/kvm/handle_exit.c
@@ -38,7 +38,7 @@
 
 	ret = kvm_psci_call(vcpu);
 	if (ret < 0) {
-		kvm_inject_undefined(vcpu);
+		vcpu_set_reg(vcpu, 0, ~0UL);
 		return 1;
 	}
 
@@ -47,7 +47,16 @@
 
 static int handle_smc(struct kvm_vcpu *vcpu, struct kvm_run *run)
 {
-	kvm_inject_undefined(vcpu);
+	/*
+	 * "If an SMC instruction executed at Non-secure EL1 is
+	 * trapped to EL2 because HCR_EL2.TSC is 1, the exception is a
+	 * Trap exception, not a Secure Monitor Call exception [...]"
+	 *
+	 * We need to advance the PC after the trap, as it would
+	 * otherwise return to the same address...
+	 */
+	vcpu_set_reg(vcpu, 0, ~0UL);
+	kvm_skip_instr(vcpu, kvm_vcpu_trap_il_is32bit(vcpu));
 	return 1;
 }
 
diff --git a/arch/arm/mach-qcom/Kconfig b/arch/arm/mach-qcom/Kconfig
index 5122af2..3a649df 100644
--- a/arch/arm/mach-qcom/Kconfig
+++ b/arch/arm/mach-qcom/Kconfig
@@ -77,6 +77,31 @@
 	select HAVE_CLK_PREPARE
 	select COMMON_CLK_MSM
 
+config ARCH_MSM8909
+	bool "Enable support for MSM8909"
+	select HAVE_ARM_ARCH_TIMER
+	select MAY_HAVE_SPARSE_IRQ
+	select PINCTRL_MSM_TLMM
+	select USE_PINCTRL_IRQ
+	select MSM_PM if PM
+	select MSM_RPM_SMD
+	select MSM_RPM_STATS_LOG
+	select MSM_RPM_LOG
+	select MSM_CORTEX_A7
+	select QCOM_SCM if SMP
+	select CPU_FREQ
+	select CPU_FREQ_MSM
+	select PM_DEVFREQ
+	select PM_OPP
+	select MSM_DEVFREQ_DEVBW
+	select DEVFREQ_SIMPLE_DEV
+	select DEVFREQ_GOV_MSM_BW_HWMON
+	select MSM_BIMC_BWMON
+	select CLKDEV_LOOKUP
+	select HAVE_CLK
+	select HAVE_CLK_PREPARE
+	select COMMON_CLK_MSM
+
 config ARCH_SDM450
 	bool "Enable support for SDM450"
 	select CPU_V7
diff --git a/arch/arm/mach-qcom/Makefile b/arch/arm/mach-qcom/Makefile
index cc06259..0e1ef7e 100644
--- a/arch/arm/mach-qcom/Makefile
+++ b/arch/arm/mach-qcom/Makefile
@@ -3,4 +3,5 @@
 obj-$(CONFIG_ARCH_SDXPOORWILLS) += board-poorwills.o
 obj-$(CONFIG_ARCH_MSM8953) += board-msm8953.o
 obj-$(CONFIG_ARCH_MSM8937) += board-msm8937.o
+obj-$(CONFIG_ARCH_MSM8909) += board-msm8909.o
 obj-$(CONFIG_ARCH_SDM450) += board-sdm450.o
diff --git a/arch/arm/mach-qcom/board-msm8909.c b/arch/arm/mach-qcom/board-msm8909.c
new file mode 100644
index 0000000..da9ca7d
--- /dev/null
+++ b/arch/arm/mach-qcom/board-msm8909.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <asm/mach/map.h>
+#include <asm/mach/arch.h>
+#include "board-dt.h"
+
+static const char *msm8909_dt_match[] __initconst = {
+	"qcom,msm8909",
+	NULL
+};
+
+static void __init msm8909_init(void)
+{
+	board_dt_populate(NULL);
+}
+
+DT_MACHINE_START(MSM8909_DT,
+	"Qualcomm Technologies, Inc. MSM 8909 (Flattened Device Tree)")
+	.init_machine	= msm8909_init,
+	.dt_compat	= msm8909_dt_match,
+MACHINE_END
diff --git a/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
new file mode 100644
index 0000000..aa5accd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/8909w-pm660.dtsi
@@ -0,0 +1,499 @@
+/*
+ * 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 <dt-bindings/spmi/spmi.h>
+#include <dt-bindings/interrupt-controller/irq.h>
+#include <dt-bindings/thermal/thermal.h>
+
+&soc {
+	qcom,csid@1b08000 {
+		/delete-property/ qcom,mipi-csi-vdd-supply;
+	};
+
+	qcom,csid@1b08400 {
+		/delete-property/ qcom,mipi-csi-vdd-supply;
+	};
+
+	i2c@78b9000 {
+		synaptics@20 {
+			/delete-property/ avdd-supply;
+			/delete-property/ vdd-supply;
+		};
+	};
+
+	qcom,wcnss-wlan@a000000 {
+		/delete-property/ qcom,iris-vddpa-voltage-level;
+		/delete-property/ qcom,iris-vddpa-supply;
+		/delete-property/ qcom,wcnss-adc_tm;
+		/delete-property/ qcom,is-dual-band-disabled;
+		/delete-property/ qcom,iris-vddpa-current;
+		qcom,pronto-vddmx-supply = <&pm660_s2_corner_ao>;
+		qcom,pronto-vddcx-supply = <&pm660_s3_corner>;
+		qcom,pronto-vddpx-supply = <&pm660_l13>;
+		qcom,iris-vddxo-supply	 = <&pm660_l12>;
+		qcom,iris-vddrfa-supply  = <&pm660_l6>;
+		qcom,iris-vdddig-supply  = <&pm660_l13>;
+		qcom,wcn-external-gpio-support;
+	};
+
+	qcom,pronto@a21b000 {
+		vdd_pronto_pll-supply = <&pm660_l12>;
+	};
+
+	qcom,mss@4080000 {
+		vdd_cx-supply = <&pm660_s2_corner>;
+		vdd_mx-supply = <&pm660_s3_corner_ao>;
+		vdd_pll-supply = <&pm660_l12>;
+	};
+
+	tpiu@820000 {
+		/delete-property/ vdd-supply;
+		/delete-property/ vdd-io-supply;
+	};
+
+	qpdi@1941000 {
+		/delete-property/ vdd-supply;
+		/delete-property/ vdd-io-supply;
+	};
+
+	qcom,msm-thermal {
+		/delete-property/ vdd-dig-supply;
+	};
+
+	msm8x16_wcd_codec@f000 {
+		/delete-property/ cdc-vdda-cp-supply;
+		/delete-property/ cdc-vdda-h-supply;
+		/delete-property/ cdc-vdd-px-supply;
+		/delete-property/ cdc-vdd-pa-supply;
+		/delete-property/ cdc-vdd-mic-bias-supply;
+	};
+};
+
+&i2c_3 {
+	qcom,actuator@0 {
+		/delete-property/ cam_vaf-supply;
+	};
+
+	qcom,eeprom@6c {
+		/delete-property/ cam_vdig-supply;
+		/delete-property/ cam_vana-supply;
+		/delete-property/ cam_vio-supply;
+		/delete-property/ cam_vaf-supply;
+	};
+
+	qcom,camera@0 {
+		/delete-property/ cam_vdig-supply;
+		/delete-property/ cam_vana-supply;
+		/delete-property/ cam_vio-supply;
+		/delete-property/ cam_vaf-supply;
+	};
+
+	qcom,camera@1 {
+		/delete-property/ cam_vana-supply;
+		/delete-property/ cam_vio-supply;
+	};
+};
+
+
+&sdhc_2 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vdd-io-supply;
+};
+
+&soc {
+	/delete-node/ qcom,rpm-smd;
+	rpm_bus: qcom,rpm-smd {
+		compatible = "qcom,rpm-smd";
+		rpm-channel-name = "rpm_requests";
+		rpm-channel-type = <15>;
+	};
+};
+
+#include "pm660.dtsi"
+#include "pm660-rpm-regulator.dtsi"
+
+/* over-write the PM660 GPIO mappings for 8909w */
+&pm660_gpios {
+		interrupts  = <0x0 0xc3 0 IRQ_TYPE_NONE>,
+			      <0x0 0xc4 0 IRQ_TYPE_NONE>,
+			      <0x0 0xcb 0 IRQ_TYPE_NONE>;
+		interrupt-names = "pm660_gpio4", "pm660_gpio5", "pm660_gpio12";
+		qcom,gpios-disallowed = <1 2 3 6 7 8 9 10 11 13>;
+};
+
+#include "msm8909w-pm660-regulator.dtsi"
+#include "msm8909-pm660-pm.dtsi"
+
+&soc {
+	qcom,gcc@1800000 {
+		vdd_dig-supply = <&pm660_s2_corner>;
+		vdd_sr2_dig-supply = <&pm660_s2_corner_ao>;
+		vdd_sr2_pll-supply = <&pm660_l12_ao>;
+
+	};
+
+	usb@78d9000 {
+		hsusb_vdd_dig-supply = <&pm660_l5>;
+		HSUSB_1p8-supply = <&pm660_l12>;
+		HSUSB_3p3-supply = <&pm660_l16>;
+	};
+
+	qcom,clock-a7@0b011050 {
+		cpu-vdd-supply = <&apc_vreg_corner>;
+	};
+
+	qcom,rpmcc@1800000 {
+		compatible = "qcom,rpmcc-8909-pm660";
+	};
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm660_l19>;
+	vdd-io-supply = <&pm660_l13>;
+};
+
+&pm660_vadc {
+	/delete-node/ chan@1d;
+};
+
+&mdss_dsi{
+	vdda-supply = <&pm660_l5>; /*1.2V*/
+	vddio-supply = <&pm660_l12>; /*1.8V*/
+	qcom,mdss_dsi_ctrl0@1ac8000 {
+		bklt-supply = <&bob_vreg>;
+		vdd-supply = <&pm660_l18>; /*1.8*/
+		vddio-supply = <&pm660_l11>;
+	};
+};
+
+&mdss_dsi0_pll {
+	vddio-supply = <&pm660_l12>; /*1.8V*/
+};
+
+&pm660_0 {
+	pm660_charger: qcom,qpnp-smb2 {
+		compatible = "qcom,qpnp-smb2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#cooling-cells = <2>;
+
+		qcom,pmic-revid = <&pm660_revid>;
+
+		io-channels = <&pm660_rradc 8>,
+			      <&pm660_rradc 10>,
+			      <&pm660_rradc 3>,
+			      <&pm660_rradc 4>;
+		io-channel-names = "charger_temp",
+				   "charger_temp_max",
+				   "usbin_i",
+				   "usbin_v";
+
+		qcom,wipower-max-uw = <5000000>;
+
+		qcom,thermal-mitigation
+				= <3000000 2500000 2000000 1500000
+					1000000 500000>;
+		qcom,auto-recharge-soc;
+
+		qcom,chgr@1000 {
+			reg = <0x1000 0x100>;
+			interrupts =
+				<0x0 0x10 0x0 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x10 0x1 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x10 0x2 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x10 0x3 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x10 0x4 IRQ_TYPE_EDGE_RISING>;
+
+			interrupt-names = "chg-error",
+					  "chg-state-change",
+					  "step-chg-state-change",
+					  "step-chg-soc-update-fail",
+					  "step-chg-soc-update-request";
+		};
+
+		qcom,otg@1100 {
+			reg = <0x1100 0x100>;
+			interrupts = <0x0 0x11 0x0 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x11 0x1 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x11 0x2 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x11 0x3 IRQ_TYPE_EDGE_BOTH>;
+
+			interrupt-names = "otg-fail",
+					  "otg-overcurrent",
+					  "otg-oc-dis-sw-sts",
+					  "testmode-change-detect";
+		};
+
+		qcom,bat-if@1200 {
+			reg = <0x1200 0x100>;
+			interrupts =
+				<0x0 0x12 0x0 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x12 0x1 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x12 0x2 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x12 0x3 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x12 0x4 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x12 0x5 IRQ_TYPE_EDGE_BOTH>;
+
+			interrupt-names = "bat-temp",
+					  "bat-ocp",
+					  "bat-ov",
+					  "bat-low",
+					  "bat-therm-or-id-missing",
+					  "bat-terminal-missing";
+		};
+
+		qcom,usb-chgpth@1300 {
+			reg = <0x1300 0x100>;
+			interrupts =
+				<0x0 0x13 0x0 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x13 0x1 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x13 0x2 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x13 0x3 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x13 0x5 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x13 0x6 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x13 0x7 IRQ_TYPE_EDGE_RISING>;
+
+			interrupt-names = "usbin-collapse",
+					  "usbin-lt-3p6v",
+					  "usbin-uv",
+					  "usbin-ov",
+					  "usbin-plugin",
+					  "usbin-src-change",
+					  "usbin-icl-change",
+					  "type-c-change";
+		};
+
+		qcom,dc-chgpth@1400 {
+			reg = <0x1400 0x100>;
+			interrupts =
+				<0x0 0x14 0x0 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x14 0x1 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x14 0x2 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x14 0x3 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x14 0x4 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x14 0x5 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x14 0x6 IRQ_TYPE_EDGE_RISING>;
+
+			interrupt-names = "dcin-collapse",
+					  "dcin-lt-3p6v",
+					  "dcin-uv",
+					  "dcin-ov",
+					  "dcin-plugin",
+					  "div2-en-dg",
+					  "dcin-icl-change";
+		};
+
+		qcom,chgr-misc@1600 {
+			reg = <0x1600 0x100>;
+			interrupts =
+				<0x0 0x16 0x0 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x16 0x1 IRQ_TYPE_EDGE_RISING>,
+				<0x0 0x16 0x2 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x16 0x3 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x16 0x4 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x16 0x5 IRQ_TYPE_EDGE_BOTH>,
+				<0x0 0x16 0x6 IRQ_TYPE_EDGE_FALLING>,
+				<0x0 0x16 0x7 IRQ_TYPE_EDGE_BOTH>;
+
+			interrupt-names = "wdog-snarl",
+					  "wdog-bark",
+					  "aicl-fail",
+					  "aicl-done",
+					  "high-duty-cycle",
+					  "input-current-limiting",
+					  "temperature-change",
+					  "switcher-power-ok";
+		};
+		smb2_vbus: qcom,smb2-vbus {
+			regulator-name = "smb2-vbus";
+		};
+
+		smb2_vconn: qcom,smb2-vconn {
+			regulator-name = "smb2-vconn";
+		};
+	};
+
+	pm660_rradc: rradc@4500 {
+		compatible = "qcom,rradc";
+		reg = <0x4500 0x100>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		#io-channel-cells = <1>;
+		qcom,pmic-revid = <&pm660_revid>;
+	};
+
+	pm660_fg: qpnp,fg {
+		compatible = "qcom,fg-gen3";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		qcom,pmic-revid = <&pm660_revid>;
+		io-channels = <&pm660_rradc 0>,
+			      <&pm660_rradc 7>;
+		io-channel-names = "rradc_batt_id",
+				   "rradc_die_temp";
+		qcom,rradc-base = <0x4500>;
+		qcom,fg-esr-timer-awake = <64 96>;
+		qcom,fg-esr-timer-asleep = <224 256>;
+		qcom,fg-esr-timer-charging = <0 96>;
+		qcom,cycle-counter-en;
+		qcom,hold-soc-while-full;
+		qcom,fg-auto-recharge-soc;
+		qcom,fg-recharge-soc-thr = <98>;
+		status = "okay";
+
+		qcom,fg-batt-soc@4000 {
+			status = "okay";
+			reg = <0x4000 0x100>;
+			interrupts = <0x0 0x40 0x0 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x40 0x1 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x40 0x2
+						IRQ_TYPE_EDGE_RISING>,
+				     <0x0 0x40 0x3
+						IRQ_TYPE_EDGE_RISING>,
+				     <0x0 0x40 0x4 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x40 0x5
+						IRQ_TYPE_EDGE_RISING>,
+				     <0x0 0x40 0x6 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x40 0x7 IRQ_TYPE_EDGE_BOTH>;
+			interrupt-names = "soc-update",
+					  "soc-ready",
+					  "bsoc-delta",
+					  "msoc-delta",
+					  "msoc-low",
+					  "msoc-empty",
+					  "msoc-high",
+					  "msoc-full";
+		};
+
+		qcom,fg-batt-info@4100 {
+			status = "okay";
+			reg = <0x4100 0x100>;
+			interrupts = <0x0 0x41 0x0 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x41 0x1 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x41 0x2 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x41 0x3 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x41 0x6 IRQ_TYPE_EDGE_BOTH>;
+			interrupt-names = "vbatt-pred-delta",
+					  "vbatt-low",
+					  "esr-delta",
+					  "batt-missing",
+					  "batt-temp-delta";
+		};
+
+		qcom,fg-memif@4400 {
+			status = "okay";
+			reg = <0x4400 0x100>;
+			interrupts = <0x0 0x44 0x0 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x44 0x1 IRQ_TYPE_EDGE_BOTH>,
+				     <0x0 0x44 0x2 IRQ_TYPE_EDGE_BOTH>;
+			interrupt-names = "ima-rdy",
+					  "mem-xcp",
+					  "dma-grant";
+		};
+	};
+};
+
+&pm660_1 {
+	pm660_haptics: qcom,haptics@c000 {
+		compatible = "qcom,qpnp-haptics";
+		reg = <0xc000 0x100>;
+		interrupts = <0x1 0xc0 0x0 IRQ_TYPE_EDGE_BOTH>,
+			     <0x1 0xc0 0x1 IRQ_TYPE_EDGE_BOTH>;
+		interrupt-names = "hap-sc-irq", "hap-play-irq";
+		qcom,pmic-revid = <&pm660_revid>;
+		qcom,pmic-misc = <&pm660_misc>;
+		qcom,misc-clk-trim-error-reg = <0xf3>;
+		qcom,actuator-type = <1>;
+		qcom,play-mode = "direct";
+		qcom,vmax-mv = <3200>;
+		qcom,ilim-ma = <800>;
+		qcom,sc-dbc-cycles = <8>;
+		qcom,wave-play-rate-us = <6667>;
+		qcom,en-brake;
+		qcom,lra-high-z = "opt0";
+		qcom,lra-auto-res-mode = "qwd";
+		qcom,lra-res-cal-period = <4>;
+	};
+};
+
+/* pm660 gpio pinctrl configuration */
+&pm660_gpios {
+	/* GPIO 4 (NFC_CLK_REQ) */
+	nfc_clk {
+		nfc_clk_default: nfc_clk_default {
+		pins = "gpio4";
+		function = "normal";
+		input-enable;
+		power-source = <1>;
+		};
+	};
+
+	vreg_bob {
+		vreg_regulator_bob: vreg_regulator-bob {
+			pins = "gpio12";
+			function = "normal";
+			output-enable;
+			qcom,drive-strength = "medium";
+		};
+	};
+
+	bg_daemon_reset {
+		bg_daemon_reset_msm: bg_daemon_reset_msm {
+			pins = "gpio5";
+			function = "func1";
+			output-enable;
+			qcom,drive-strength = "medium";
+			bias-disable;
+		};
+	};
+};
+
+&pm660_misc {
+	qcom,support-twm-config;
+};
+
+/ {
+	/delete-node/ qcom,battery-data;
+	mtp_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "fg-gen3-batterydata-palladium-1500mah.dtsi"
+	};
+};
+
+&pm660_charger {
+	qcom,pd-not-supported;
+};
+
+&pm660_fg {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
+&pm660_pdphy {
+	/delete-property/ vdd-pdphy-supply;
+};
+
+&thermal_zones {
+	vbat_adc {
+		cooling-maps {
+			/delete-node/ vbat_map6;
+			/delete-node/ vbat_map7;
+		};
+	};
+	soc {
+		cooling-maps {
+		/delete-node/ soc_map6;
+		/delete-node/ soc_map7;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/Makefile b/arch/arm64/boot/dts/qcom/Makefile
index caed4e1..612b9f5 100644
--- a/arch/arm64/boot/dts/qcom/Makefile
+++ b/arch/arm64/boot/dts/qcom/Makefile
@@ -297,7 +297,14 @@
 	msm8953-pmi8937-ext-codec-mtp.dtb \
 	msm8953-pmi632-cdp-s2.dtb
 
-dtb-$(CONFIG_ARCH_MSM8937) += msm8937-pmi8950-mtp.dtb
+dtb-$(CONFIG_ARCH_MSM8937) += msm8937-pmi8950-mtp.dtb \
+	msm8937-interposer-sdm439-cdp.dtb \
+	msm8937-interposer-sdm439-mtp.dtb \
+	msm8937-interposer-sdm439-qrd.dtb
+
+dtb-$(CONFIG_ARCH_MSM8917) += msm8917-pmi8950-mtp.dtb
+
+dtb-$(CONFIG_ARCH_MSM8909) += msm8909w-bg-wtp-v2.dtb
 
 dtb-$(CONFIG_ARCH_SDM450) += sdm450-rcm.dtb \
 	sdm450-cdp.dtb \
@@ -315,6 +322,14 @@
 	sdm632-mtp-s3.dtb	\
 	sdm632-qrd-sku4.dtb
 
+dtb-$(CONFIG_ARCH_SDM439) += sdm439-mtp.dtb \
+	sdm439-cdp.dtb \
+	sdm439-qrd.dtb
+
+dtb-$(CONFIG_ARCH_SDM429) += sdm429-mtp.dtb \
+	sdm429-cdp.dtb \
+	sdm429-qrd.dtb
+
 endif
 
 always		:= $(dtb-y)
diff --git a/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-palladium-1500mah.dtsi b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-palladium-1500mah.dtsi
new file mode 100644
index 0000000..251440a
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/fg-gen3-batterydata-palladium-1500mah.dtsi
@@ -0,0 +1,81 @@
+/* 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.
+ */
+
+qcom,palladium_1500mah_averaged_masterslave_nov28th2017 {
+	/* #Palladium_1500mAh_averaged_MasterSlave_Nov28th2017*/
+	qcom,max-voltage-uv = <4200000>;
+	qcom,fg-cc-cv-threshold-mv = <4180>;
+	qcom,fastchg-current-ma = <1500>;
+	qcom,batt-id-kohm = <75>;
+	qcom,battery-beta = <3435>;
+	qcom,battery-type = "palladium_1500mah_averaged_masterslave_nov28th2017";
+	qcom,checksum = <0x1C13>;
+	qcom,gui-version = "PM660GUI - 0.0.0.45";
+	qcom,fg-profile-data = [
+		 A6 1F B2 05
+		 1F 0A F7 FC
+		 22 1D 32 F2
+		 B9 02 1C 0D
+		 25 11 FB 2B
+		 88 4C 0A 62
+		 65 00 00 00
+		 0E 00 00 00
+		 00 00 3D C4
+		 5D C5 A4 C2
+		 2A 00 08 00
+		 0F C5 76 D4
+		 71 FC 36 F3
+		 7D 06 C4 03
+		 EB DD F0 22
+		 1E 06 09 20
+		 27 00 14 00
+		 47 1F 5F FC
+		 9B 03 BE 06
+		 EE 1C 17 02
+		 F6 0D 27 03
+		 22 11 0B 32
+		 6D 4C 19 62
+		 7D 00 00 00
+		 0E 00 00 00
+		 00 00 6E CC
+		 03 CA FB BC
+		 26 00 00 00
+		 E9 DB 76 D4
+		 41 FD 89 EB
+		 3E 06 A9 F3
+		 C3 05 F3 13
+		 9C 33 CC FF
+		 07 10 00 00
+		 BD 05 33 43
+		 26 00 40 00
+		 35 02 0A FA
+		 FF 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+		 00 00 00 00
+	];
+};
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-8937.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8937.dtsi
new file mode 100644
index 0000000..e862b0f
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-8937.dtsi
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+
+&soc {
+	kgsl_smmu: arm,smmu-kgsl@1c40000 {
+		status = "ok";
+		compatible = "qcom,smmu-v2";
+		qcom,tz-device-id = "GPU";
+		reg = <0x1c40000 0x10000>;
+		#iommu-cells = <1>;
+		#global-interrupts = <0>;
+		interrupts =  <GIC_SPI 225 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 232 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 233 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 234 IRQ_TYPE_LEVEL_HIGH>;
+		qcom,dynamic;
+		qcom,use-3-lvl-tables;
+		qcom,enable-smmu-halt;
+		qcom,skip-init;
+		vdd-supply = <&gdsc_oxili_cx>;
+		qcom,regulator-names = "vdd";
+		clocks = <&clock_gcc clk_gcc_oxili_ahb_clk>,
+			     <&clock_gcc clk_gcc_bimc_gfx_clk>;
+		clock-names = "gpu_ahb_clk", "gcc_bimc_gfx_clk";
+	};
+
+	/* A test device to test the SMMU operation */
+	kgsl_iommu_test_device0 {
+		status = "disabled";
+		compatible = "iommu-debug-test";
+		/* The SID should be valid one to get the proper
+		 *SMR,S2CR indices.
+		 */
+		iommus = <&kgsl_smmu 0x0>;
+	};
+
+	apps_iommu: qcom,iommu@1e00000 {
+		status = "okay";
+		compatible = "qcom,qsmmu-v500";
+		reg = <0x1e00000 0x40000>,
+			<0x1ee2000 0x20>;
+		reg-names = "base", "tcu-base";
+		#iommu-cells = <2>;
+		qcom,tz-device-id = "APPS";
+		qcom,skip-init;
+		qcom,enable-static-cb;
+		qcom,use-3-lvl-tables;
+		qcom,disable-atos;
+		#global-interrupts = <0>;
+		#size-cells = <1>;
+		#address-cells = <1>;
+		ranges;
+		interrupts = <GIC_SPI 253 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 254 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 255 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 53 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 54 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 58 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 60 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 61 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 76 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 77 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 80 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 101 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 102 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 103 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 104 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 105 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 106 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 109 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 110 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 111 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 112 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 113 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 114 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 116 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 117 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 118 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 119 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 120 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 121 IRQ_TYPE_LEVEL_HIGH>,
+				<GIC_SPI 122 IRQ_TYPE_LEVEL_HIGH>;
+		clocks = <&clock_gcc clk_gcc_smmu_cfg_clk>,
+			     <&clock_gcc clk_gcc_apss_tcu_clk>;
+		clock-names = "iface_clk", "core_clk";
+	};
+};
+
+#include "msm-arm-smmu-impl-defs-8937.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm-arm-smmu-impl-defs-8937.dtsi b/arch/arm64/boot/dts/qcom/msm-arm-smmu-impl-defs-8937.dtsi
new file mode 100644
index 0000000..ce3e1c3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm-arm-smmu-impl-defs-8937.dtsi
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&kgsl_smmu {
+	attach-impl-defs = <0x6000 0x270>,
+		<0x6060 0x1055>,
+		<0x6800 0x6>,
+		<0x6900 0x3ff>,
+		<0x6924 0x204>,
+		<0x6928 0x10800>,
+		<0x6930 0x400>,
+		<0x6960 0xffffffff>,
+		<0x6b64 0xa0000>,
+		<0x6b68 0xaaab92a>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm-gdsc-8916.dtsi b/arch/arm64/boot/dts/qcom/msm-gdsc-8916.dtsi
index 49e148c..0e58559 100644
--- a/arch/arm64/boot/dts/qcom/msm-gdsc-8916.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm-gdsc-8916.dtsi
@@ -1,5 +1,6 @@
 /*
- * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2015, 2017-2018, The Linux Foundation. All rights
+ * reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
diff --git a/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi b/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
new file mode 100644
index 0000000..f2cea32
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-audio-bg_codec.dtsi
@@ -0,0 +1,195 @@
+/* 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.
+ */
+
+&soc {
+	audio_codec_bg: sound {
+		status = "disabled";
+		compatible = "qcom,msm-bg-audio-codec";
+		qcom,model = "msm-bg-snd-card";
+		reg = <0x7702000 0x4>,
+		      <0x7702004 0x4>,
+		      <0x7702008 0x4>,
+		      <0x770200c 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			    "csr_gp_io_mux_spkr_ctl",
+			    "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+			    "csr_gp_io_lpaif_sec_pcm_sec_mode_muxsel";
+
+		qcom,msm-snd-card-id = <0>;
+		qcom,msm-ext-pa = "primary";
+		qcom,tdm-audio-intf;
+		qcom,msm-afe-clk-ver = <1>;
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&lpa>,
+				<&voice_svc>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2", "msm-voip-dsp",
+				"msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless",
+				"msm-pcm-afe", "msm-lsm-client",
+				"msm-pcm-routing", "msm-pcm-lpa",
+				"msm-voice-svc";
+		asoc-cpu = <&dai_pri_auxpcm>,
+				<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
+				<&dai_mi2s3>, <&dai_mi2s5>, <&dai_mi2s6>,
+				<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
+				<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
+				<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>,
+				<&incall_music_rx>, <&incall_music_2_rx>,
+				<&dai_pri_tdm_rx_0>, <&dai_pri_tdm_tx_0>,
+				<&dai_pri_tdm_rx_1>, <&dai_pri_tdm_tx_1>,
+				<&dai_pri_tdm_rx_2>, <&dai_pri_tdm_tx_2>,
+				<&dai_pri_tdm_rx_3>, <&dai_pri_tdm_tx_3>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
+				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
+				"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+				"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+				"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+				"msm-dai-q6-dev.32770", "msm-dai-q6-tdm.36864",
+				"msm-dai-q6-tdm.36865", "msm-dai-q6-tdm.36866",
+				"msm-dai-q6-tdm.36867", "msm-dai-q6-tdm.36868",
+				"msm-dai-q6-tdm.36869", "msm-dai-q6-tdm.36870",
+				"msm-dai-q6-tdm.36871";
+		asoc-codec = <&stub_codec>;
+		asoc-codec-names = "msm-stub-codec.1";
+	};
+
+	pri_tdm_rx: qcom,msm-dai-tdm-pri-rx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37120>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36864 36866 36868 36870>;
+		qcom,msm-cpudai-tdm-clk-rate = <0>;
+		qcom,msm-cpudai-tdm-afe-ebit-unsupported;
+		qcom,msm-cpudai-tdm-sec-port-enable;
+		qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+		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 = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_rx_1: qcom,msm-dai-q6-tdm-pri-rx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36866>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_rx_2: qcom,msm-dai-q6-tdm-pri-rx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36868>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_rx_3: qcom,msm-dai-q6-tdm-pri-rx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36870>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	pri_tdm_tx: qcom,msm-dai-tdm-pri-tx {
+		compatible = "qcom,msm-dai-tdm";
+		qcom,msm-cpudai-tdm-group-id = <37121>;
+		qcom,msm-cpudai-tdm-group-num-ports = <4>;
+		qcom,msm-cpudai-tdm-group-port-id = <36865 36867 36869 36871>;
+		qcom,msm-cpudai-tdm-clk-rate = <0>;
+		qcom,msm-cpudai-tdm-afe-ebit-unsupported;
+		qcom,msm-cpudai-tdm-sec-port-enable;
+		qcom,msm-cpudai-tdm-clk-attribute = /bits/ 16 <1>;
+		pinctrl-names = "default", "sleep";
+		pinctrl-0 = <&quat_mi2s_active &quat_mi2s_din_active>;
+		pinctrl-1 = <&quat_mi2s_sleep &quat_mi2s_din_sleep>;
+		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 = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_tx_1: qcom,msm-dai-q6-tdm-pri-tx-1 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36867>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_tx_2: qcom,msm-dai-q6-tdm-pri-tx-2 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36869>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+		dai_pri_tdm_tx_3: qcom,msm-dai-q6-tdm-pri-tx-3 {
+			compatible = "qcom,msm-dai-q6-tdm";
+			qcom,msm-cpudai-tdm-dev-id = <36871>;
+			qcom,msm-cpudai-tdm-sync-mode = <0>;
+			qcom,msm-cpudai-tdm-sync-src = <0>;
+			qcom,msm-cpudai-tdm-data-out = <0>;
+			qcom,msm-cpudai-tdm-invert-sync = <0>;
+			qcom,msm-cpudai-tdm-data-delay = <0>;
+			qcom,msm-cpudai-tdm-data-align = <0>;
+		};
+	};
+
+	wdsp_glink: qcom,wcd-dsp-glink {
+		compatible = "qcom,wcd-dsp-glink";
+		qcom,msm-codec-glink-edge = "bg";
+	};
+
+	bg_cdc: bg_codec {
+		status = "disabled";
+		compatible = "qcom,bg-codec";
+		qcom,subsys-name = "modem";
+		qcom,bg-glink {
+			compatible = "qcom,bg-cdc-glink";
+			qcom,msm-glink-channels = <4>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-bus.dtsi b/arch/arm64/boot/dts/qcom/msm8909-bus.dtsi
new file mode 100644
index 0000000..eea1a85
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-bus.dtsi
@@ -0,0 +1,1064 @@
+/* Copyright (c) 2014-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/msm/msm-bus-ids.h>
+#include <dt-bindings/msm/msm-bus-rule-ops.h>
+
+&soc {
+	static-rules {
+		compatible = "qcom,msm-bus-static-bw-rules";
+
+		rule0 {
+			qcom,src-nodes = <&mas_apps_proc>;
+			qcom,src-field = <FLD_CLK>;
+			qcom,src-op = <OP_LE>;
+			qcom,thresh = <200000>;
+			qcom,mode = <THROTTLE_ON>;
+			qcom,dest-node = <&mas_apps_proc>;
+			qcom,dest-bw = <600000>;
+		};
+
+		rule1 {
+			qcom,src-nodes = <&mas_apps_proc>;
+			qcom,src-field = <FLD_CLK>;
+			qcom,src-op = <OP_LE>;
+			qcom,thresh = <400000>;
+			qcom,mode = <THROTTLE_ON>;
+			qcom,dest-node = <&mas_apps_proc>;
+			qcom,dest-bw = <1200000>;
+		};
+
+		rule2 {
+			qcom,src-nodes = <&mas_apps_proc>;
+			qcom,src-field = <FLD_CLK>;
+			qcom,src-op = <OP_GT>;
+			qcom,thresh = <400000>;
+			qcom,mode = <THROTTLE_OFF>;
+			qcom,dest-node = <&mas_apps_proc>;
+		};
+
+		rule3 {
+			qcom,src-nodes = <&mas_oxili>;
+			qcom,src-field = <FLD_CLK>;
+			qcom,src-op = <OP_LE>;
+			qcom,thresh = <200000>;
+			qcom,mode = <THROTTLE_ON>;
+			qcom,dest-node = <&mas_oxili>;
+			qcom,dest-bw = <600000>;
+		};
+
+		rule4 {
+			qcom,src-nodes = <&mas_oxili>;
+			qcom,src-field = <FLD_CLK>;
+			qcom,src-op = <OP_LE>;
+			qcom,thresh = <400000>;
+			qcom,mode = <THROTTLE_ON>;
+			qcom,dest-node = <&mas_oxili>;
+			qcom,dest-bw = <1200000>;
+		};
+
+		rule5 {
+			qcom,src-nodes = <&mas_oxili>;
+			qcom,src-field = <FLD_CLK>;
+			qcom,src-op = <OP_GT>;
+			qcom,thresh = <400000>;
+			qcom,mode = <THROTTLE_OFF>;
+			qcom,dest-node = <&mas_oxili>;
+		};
+	};
+
+	/* Version = 2 */
+	ad_hoc_bus: ad-hoc-bus {
+		compatible = "qcom,msm-bus-device";
+		reg = <0x580000 0x13000>,
+			<0x580000 0x13000>,
+			<0x400000 0x62000>,
+			<0x500000 0x11000>;
+		reg-names = "snoc-base", "snoc-mm-base",
+				 "bimc-base", "pcnoc-base";
+
+		/*Buses*/
+
+		fab_bimc: fab-bimc {
+			cell-id = <MSM_BUS_FAB_BIMC>;
+			label = "fab-bimc";
+			qcom,fab-dev;
+			qcom,base-name = "bimc-base";
+			qcom,bus-type = <2>;
+			qcom,util-fact = <154>;
+			clock-names = "bus_clk", "bus_a_clk";
+			clocks = <&clock_rpm  clk_bimc_msmbus_clk>,
+				<&clock_rpm  clk_bimc_msmbus_a_clk>;
+		};
+
+		fab_pcnoc: fab-pcnoc {
+			cell-id = <MSM_BUS_FAB_PERIPH_NOC>;
+			label = "fab-pcnoc";
+			qcom,fab-dev;
+			qcom,base-name = "pcnoc-base";
+			qcom,base-offset = <0x7000>;
+			qcom,qos-delta = <0x1000>;
+			qcom,bus-type = <1>;
+			clock-names = "bus_clk", "bus_a_clk";
+			clocks = <&clock_rpm  clk_pcnoc_msmbus_clk>,
+				<&clock_rpm  clk_pcnoc_msmbus_a_clk>;
+		};
+
+		fab_snoc: fab-snoc {
+			cell-id = <MSM_BUS_FAB_SYS_NOC>;
+			label = "fab-snoc";
+			qcom,fab-dev;
+			qcom,base-name = "snoc-base";
+			qcom,base-offset = <0x7000>;
+			qcom,qos-off = <0x1000>;
+			qcom,bus-type = <1>;
+			clock-names = "bus_clk", "bus_a_clk", "bus_qos_clk";
+			clocks = <&clock_rpm  clk_snoc_msmbus_clk>,
+				<&clock_rpm  clk_snoc_msmbus_a_clk>,
+				<&clock_gcc clk_gcc_snoc_qosgen_clk>;
+		};
+
+		fab_snoc_mm: fab-snoc-mm {
+			cell-id = <MSM_BUS_FAB_MMSS_NOC>;
+			label = "fab-snoc-mm";
+			qcom,fab-dev;
+			qcom,base-name = "snoc-mm-base";
+			qcom,base-offset = <0x7000>;
+			qcom,qos-off = <0x1000>;
+			qcom,bus-type = <1>;
+			qcom,util-fact = <167>;
+			clock-names = "bus_clk", "bus_a_clk";
+			clocks = <&clock_rpm  clk_snoc_mm_msmbus_clk>,
+				<&clock_rpm  clk_snoc_mm_msmbus_a_clk>;
+		};
+
+		/* Masters */
+		mas_apps_proc: mas-apps-proc {
+			cell-id = <MSM_BUS_MASTER_AMPSS_M0>;
+			label = "mas-apps-proc";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,qport = <0>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&slv_bimc_snoc &slv_ebi>;
+			qcom,prio-lvl = <0>;
+			qcom,prio-rd = <0>;
+			qcom,prio-wr = <0>;
+			qcom,ws = <10000>;
+			qcom,gp = <5000>;
+			qcom,thmp = <50>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_APPSS_PROC>;
+		};
+
+		mas_oxili: mas-oxili {
+			cell-id = <MSM_BUS_MASTER_GRAPHICS_3D>;
+			label = "mas-oxili";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,qport = <2>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&slv_bimc_snoc &slv_ebi>;
+			qcom,prio-lvl = <0>;
+			qcom,prio-rd = <0>;
+			qcom,prio-wr = <0>;
+			qcom,ws = <10000>;
+			qcom,gp = <5000>;
+			qcom,thmp = <50>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_GFX3D>;
+		};
+
+		mas_snoc_bimc_0: mas-snoc-bimc-0 {
+			cell-id = <MSM_BUS_SNOC_BIMC_0_MAS>;
+			label = "mas-snoc-bimc-0";
+			qcom,buswidth = <8>;
+			qcom,qport = <3>;
+			qcom,qos-mode = "bypass";
+			qcom,connections = <&slv_ebi>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SNOC_BIMC_0>;
+		};
+
+		mas_snoc_bimc_1: mas-snoc-bimc-1 {
+			cell-id = <MSM_BUS_SNOC_BIMC_1_MAS>;
+			label = "mas-snoc-bimc-1";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,qport = <4>;
+			qcom,qos-mode = "bypass";
+			qcom,connections = <&slv_ebi>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SNOC_BIMC_1>;
+		};
+
+		mas_tcu_0: mas-tcu-0 {
+			cell-id = <MSM_BUS_MASTER_TCU_0>;
+			label = "mas-tcu-0";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,qport = <5>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&slv_bimc_snoc &slv_ebi>;
+			qcom,prio-lvl = <2>;
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_TCU_0>;
+		};
+
+		mas_tcu_1: mas-tcu-1 {
+			cell-id = <MSM_BUS_MASTER_TCU_1>;
+			label = "mas-tcu-1";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,qport = <6>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&slv_bimc_snoc &slv_ebi>;
+			qcom,prio-lvl = <2>;
+			qcom,prio-rd = <2>;
+			qcom,prio-wr = <2>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_TCU_1>;
+		};
+
+		mas_audio: mas-audio {
+			cell-id = <MSM_BUS_MASTER_AUDIO>;
+			label = "mas-audio";
+			qcom,buswidth = <4>;
+			qcom,connections = <&pcnoc_m_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_AUDIO>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_spdm: mas-spdm {
+			cell-id = <MSM_BUS_MASTER_SPDM>;
+			label = "mas-spdm";
+			qcom,buswidth = <4>;
+			qcom,connections = <&pcnoc_m_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SPDM>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_dehr: mas-dehr {
+			cell-id = <MSM_BUS_MASTER_DEHR>;
+			label = "mas-dehr";
+			qcom,buswidth = <4>;
+			qcom,connections = <&pcnoc_m_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_DEHR>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_qpic: mas-qpic {
+			cell-id = <MSM_BUS_MASTER_QPIC>;
+			label = "mas-qpic";
+			qcom,buswidth = <4>;
+			qcom,connections = <&pcnoc_m_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QPIC>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_blsp_1: mas-blsp-1 {
+			cell-id = <MSM_BUS_MASTER_BLSP_1>;
+			label = "mas-blsp-1";
+			qcom,buswidth = <4>;
+			qcom,connections = <&pcnoc_m_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_BLSP_1>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_usb_hs: mas-usb-hs {
+			cell-id = <MSM_BUS_MASTER_USB_HS>;
+			label = "mas-usb-hs";
+			qcom,buswidth = <4>;
+			qcom,connections = <&pcnoc_m_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_USB_HS>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_crypto: mas-crypto {
+			cell-id = <MSM_BUS_MASTER_CRYPTO_CORE0>;
+			label = "mas-crypto";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,qport = <0>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&pcnoc_int_1>;
+			qcom,prio1 = <0>;
+			qcom,prio0 = <0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_CRYPTO>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_sdcc_1: mas-sdcc-1 {
+			cell-id = <MSM_BUS_MASTER_SDCC_1>;
+			label = "mas-sdcc-1";
+			qcom,buswidth = <8>;
+			qcom,qport = <7>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&pcnoc_int_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SDCC_1>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_sdcc_2: mas-sdcc-2 {
+			cell-id = <MSM_BUS_MASTER_SDCC_2>;
+			label = "mas-sdcc-2";
+			qcom,buswidth = <8>;
+			qcom,qport = <8>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&pcnoc_int_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SDCC_2>;
+			qcom,blacklist =
+				<&slv_blsp_1 &slv_message_ram &slv_usb_hs
+				 &slv_venus_cfg &slv_gpu_cfg &slv_camera_ss_cfg
+				 &slv_crypto_0_cfg &slv_tlmm &slv_tcu
+				 &slv_pdm &slv_snoc_cfg &slv_qpic
+				 &slv_tcsr &slv_prng &slv_sdcc_2
+				 &slv_pmic_arb &slv_disp_ss_cfg &slv_usb_phy
+				 &slv_sdcc_1 &slv_audio>;
+		};
+
+		mas_snoc_pcnoc: mas-snoc-pcnoc {
+			cell-id = <MSM_BUS_SNOC_PNOC_MAS>;
+			label = "mas-snoc-pcnoc";
+			qcom,buswidth = <8>;
+			qcom,qport = <9>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&pcnoc_int_0>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SNOC_PCNOC>;
+		};
+
+		mas_qdss_bam: mas-qdss-bam {
+			cell-id = <MSM_BUS_MASTER_QDSS_BAM>;
+			label = "mas-qdss-bam";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,qport = <11>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&qdss_int>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_BAM>;
+			qcom,blacklist =
+				<&slv_kpss_ahb &slv_cats_1 &slv_qdss_stm
+				 &slv_cats_0>;
+		};
+
+		mas_bimc_snoc: mas-bimc-snoc {
+			cell-id = <MSM_BUS_BIMC_SNOC_MAS>;
+			label = "mas-bimc-snoc";
+			qcom,buswidth = <8>;
+			qcom,connections = <&snoc_int_0 &snoc_int_1>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_BIMC_SNOC>;
+		};
+
+		mas_mdp: mas-mdp {
+			cell-id = <MSM_BUS_MASTER_MDP_PORT0>;
+			label = "mas-mdp";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,qport = <7>;
+			qcom,qos-mode = "bypass";
+			qcom,connections = <&mm_int_1 &mm_int_2>;
+			qcom,bus-dev = <&fab_snoc_mm>;
+			qcom,mas-rpm-id = <ICBID_MASTER_MDP>;
+			qcom,blacklist = <&slv_kpss_ahb &slv_imem &slv_cats_1
+				 &slv_qdss_stm &slv_cats_0>;
+		};
+
+		mas_pcnoc_snoc: mas-pcnoc-snoc {
+			cell-id = <MSM_BUS_PNOC_SNOC_MAS>;
+			label = "mas-pcnoc-snoc";
+			qcom,buswidth = <8>;
+			qcom,qport = <5>;
+			qcom,qos-mode = "fixed";
+			qcom,connections =
+				<&snoc_int_0 &snoc_int_1 &snoc_int_bimc>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PNOC_SNOC>;
+			qcom,blacklist = <&slv_cats_1 &slv_cats_0>;
+		};
+
+		mas_venus: mas-venus {
+			cell-id = <MSM_BUS_MASTER_VIDEO_P0>;
+			label = "mas-venus";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,qport = <8>;
+			qcom,qos-mode = "bypass";
+			qcom,connections = <&mm_int_0 &mm_int_2>;
+			qcom,bus-dev = <&fab_snoc_mm>;
+			qcom,mas-rpm-id = <ICBID_MASTER_VIDEO>;
+			qcom,blacklist = <&slv_kpss_ahb &slv_imem &slv_cats_1
+				 &slv_qdss_stm &slv_cats_0>;
+		};
+
+		mas_vfe: mas-vfe {
+			cell-id = <MSM_BUS_MASTER_VFE>;
+			label = "mas-vfe";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,qport = <9>;
+			qcom,qos-mode = "bypass";
+			qcom,connections = <&mm_int_1 &mm_int_2>;
+			qcom,bus-dev = <&fab_snoc_mm>;
+			qcom,mas-rpm-id = <ICBID_MASTER_VFE>;
+			qcom,blacklist = <&slv_kpss_ahb &slv_imem &slv_cats_1
+				 &slv_qdss_stm &slv_cats_0>;
+		};
+
+		mas_qdss_etr: mas-qdss-etr {
+			cell-id = <MSM_BUS_MASTER_QDSS_ETR>;
+			label = "mas-qdss-etr";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,qport = <10>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&qdss_int>;
+			qcom,prio1 = <1>;
+			qcom,prio0 = <1>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_ETR>;
+			qcom,blacklist =
+				<&slv_kpss_ahb &slv_cats_1 &slv_qdss_stm
+				 &slv_cats_0>;
+		};
+
+	/*Internal nodes*/
+		pcnoc_m_0: pcnoc-m-0 {
+			cell-id = <MSM_BUS_PNOC_M_0>;
+			label = "pcnoc-m-0";
+			qcom,buswidth = <8>;
+			qcom,qport = <5>;
+			qcom,qos-mode = "bypass";
+			qcom,connections = <&slv_pcnoc_snoc>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_M_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_M_0>;
+		};
+
+		pcnoc_m_1: pcnoc-m-1 {
+			cell-id = <MSM_BUS_PNOC_M_1>;
+			label = "pcnoc-m-1";
+			qcom,buswidth = <8>;
+			qcom,qport = <6>;
+			qcom,qos-mode = "fixed";
+			qcom,connections = <&slv_pcnoc_snoc>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_M_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_M_1>;
+		};
+
+		pcnoc_int_0: pcnoc-int-0 {
+			cell-id = <MSM_BUS_PNOC_INT_0>;
+			label = "pcnoc-int-0";
+			qcom,buswidth = <8>;
+			qcom,connections = <&pcnoc_s_3 &pcnoc_s_2 &pcnoc_s_1 \
+			 &pcnoc_s_0 &pcnoc_s_7 &pcnoc_s_5 &pcnoc_s_4 &slv_tcu>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_0>;
+		};
+
+		pcnoc_int_1: pcnoc-int-1 {
+			cell-id = <MSM_BUS_PNOC_INT_1>;
+			label = "pcnoc-int-1";
+			qcom,buswidth = <8>;
+			qcom,connections = <&slv_pcnoc_snoc>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_INT_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_INT_1>;
+		};
+
+		pcnoc_s_0: pcnoc-s-0 {
+			cell-id = <MSM_BUS_PNOC_SLV_0>;
+			label = "pcnoc-s-0";
+			qcom,buswidth = <4>;
+			qcom,connections = <&slv_sdcc_1 &slv_tcsr &slv_blsp_1>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_0>;
+		};
+
+		pcnoc_s_1: pcnoc-s-1 {
+			cell-id = <MSM_BUS_PNOC_SLV_1>;
+			label = "pcnoc-s-1";
+			qcom,buswidth = <4>;
+			qcom,connections = <&slv_message_ram &slv_crypto_0_cfg \
+			 &slv_usb_hs &slv_pdm &slv_prng &slv_qpic>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_1>;
+		};
+
+		pcnoc_s_2: pcnoc-s-2 {
+			cell-id = <MSM_BUS_PNOC_SLV_2>;
+			label = "pcnoc-s-2";
+			qcom,buswidth = <4>;
+			qcom,connections = <&slv_spdm &slv_sdcc_2 \
+					&slv_audio &slv_dehr_cfg>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_2>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_2>;
+		};
+
+		pcnoc_s_3: pcnoc-s-3 {
+			cell-id = <MSM_BUS_PNOC_SLV_3>;
+			label = "pcnoc-s-3";
+			qcom,buswidth = <4>;
+			qcom,connections = <&slv_qdss_cfg &slv_usb_phy \
+					&slv_snoc_cfg>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_3>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_3>;
+		};
+
+		pcnoc_s_4: pcnoc-s-4 {
+			cell-id = <MSM_BUS_PNOC_SLV_4>;
+			label = "pcnoc-s-4";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,connections =
+					<&slv_camera_ss_cfg &slv_disp_ss_cfg \
+					&slv_venus_cfg>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_4>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_4>;
+		};
+
+		pcnoc_s_5: pcnoc-s-5 {
+			cell-id = <MSM_BUS_PNOC_SLV_5>;
+			label = "pcnoc-s-5";
+			qcom,buswidth = <4>;
+			qcom,connections = <&slv_tlmm>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_5>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_5>;
+		};
+
+		pcnoc_s_7: pcnoc-s-7 {
+			cell-id = <MSM_BUS_PNOC_SLV_7>;
+			label = "pcnoc-s-7";
+			qcom,buswidth = <4>;
+			qcom,connections = <&slv_gpu_cfg &slv_imem_cfg \
+					&slv_bimc_cfg &slv_pmic_arb>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_PCNOC_S_7>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_S_7>;
+		};
+
+		mm_int_0: mm-int-0 {
+			cell-id = <MSM_BUS_SNOC_MM_INT_0>;
+			label = "mm-int-0";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,connections = <&mm_int_bimc>;
+			qcom,bus-dev = <&fab_snoc_mm>;
+			qcom,mas-rpm-id = <ICBID_MASTER_MM_INT_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_MM_INT_0>;
+		};
+
+		mm_int_1: mm-int-1 {
+			cell-id = <MSM_BUS_SNOC_MM_INT_1>;
+			label = "mm-int-1";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,connections = <&mm_int_bimc>;
+			qcom,bus-dev = <&fab_snoc_mm>;
+			qcom,mas-rpm-id = <ICBID_MASTER_MM_INT_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_MM_INT_1>;
+		};
+
+		mm_int_2: mm-int-2 {
+			cell-id = <MSM_BUS_SNOC_MM_INT_2>;
+			label = "mm-int-2";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,connections = <&snoc_int_0>;
+			qcom,bus-dev = <&fab_snoc_mm>;
+			qcom,mas-rpm-id = <ICBID_MASTER_MM_INT_2>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_MM_INT_2>;
+		};
+
+		mm_int_bimc: mm-int-bimc {
+			cell-id = <MSM_BUS_SNOC_MM_INT_BIMC>;
+			label = "mm-int-bimc";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,connections = <&slv_snoc_bimc_1>;
+			qcom,bus-dev = <&fab_snoc_mm>;
+			qcom,mas-rpm-id = <ICBID_MASTER_MM_INT_BIMC>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_MM_INT_BIMC>;
+		};
+
+		qdss_int: qdss-int {
+			cell-id = <MSM_BUS_SNOC_QDSS_INT>;
+			label = "qdss-int";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,connections = <&snoc_int_0 &snoc_int_bimc>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_QDSS_INT>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_QDSS_INT>;
+		};
+
+		snoc_int_0: snoc-int-0 {
+			cell-id = <MSM_BUS_SNOC_INT_0>;
+			label = "snoc-int-0";
+			qcom,buswidth = <8>;
+			qcom,connections = <&slv_imem &slv_qdss_stm \
+					&slv_snoc_pcnoc>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SNOC_INT_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_INT_0>;
+		};
+
+		snoc_int_1: snoc-int-1 {
+			cell-id = <MSM_BUS_SNOC_INT_1>;
+			label = "snoc-int-1";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,connections = <&slv_cats_0 &slv_kpss_ahb \
+					 &slv_cats_1>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SNOC_INT_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_INT_1>;
+		};
+
+		snoc_int_bimc: snoc-int-bimc {
+			cell-id = <MSM_BUS_SNOC_INT_BIMC>;
+			label = "snoc-int-bimc";
+			qcom,buswidth = <8>;
+			qcom,connections = <&slv_snoc_bimc_0>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,mas-rpm-id = <ICBID_MASTER_SNOC_INT_BIMC>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_INT_BIMC>;
+		};
+
+	/*Slaves*/
+		slv_ebi:slv-ebi {
+			cell-id = <MSM_BUS_SLAVE_EBI_CH0>;
+			label = "slv-ebi";
+			qcom,buswidth = <8>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_EBI1>;
+		};
+
+		slv_bimc_snoc:slv-bimc-snoc {
+			cell-id = <MSM_BUS_BIMC_SNOC_SLV>;
+			label = "slv-bimc-snoc";
+			qcom,buswidth = <8>;
+			qcom,bus-dev = <&fab_bimc>;
+			qcom,connections = <&mas_bimc_snoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_BIMC_SNOC>;
+		};
+
+		slv_tcsr:slv-tcsr {
+			cell-id = <MSM_BUS_SLAVE_TCSR>;
+			label = "slv-tcsr";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_TCSR>;
+		};
+
+		slv_sdcc_1:slv-sdcc-1 {
+			cell-id = <MSM_BUS_SLAVE_SDCC_1>;
+			label = "slv-sdcc-1";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SDCC_1>;
+		};
+
+		slv_blsp_1:slv-blsp-1 {
+			cell-id = <MSM_BUS_SLAVE_BLSP_1>;
+			label = "slv-blsp-1";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_BLSP_1>;
+		};
+
+		slv_crypto_0_cfg:slv-crypto-0-cfg {
+			cell-id = <MSM_BUS_SLAVE_CRYPTO_0_CFG>;
+			label = "slv-crypto-0-cfg";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_CRYPTO_0_CFG>;
+		};
+
+		slv_message_ram:slv-message-ram {
+			cell-id = <MSM_BUS_SLAVE_MESSAGE_RAM>;
+			label = "slv-message-ram";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_MESSAGE_RAM>;
+		};
+
+		slv_pdm:slv-pdm {
+			cell-id = <MSM_BUS_SLAVE_PDM>;
+			label = "slv-pdm";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PDM>;
+		};
+
+		slv_prng:slv-prng {
+			cell-id = <MSM_BUS_SLAVE_PRNG>;
+			label = "slv-prng";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PRNG>;
+		};
+
+		slv_usb_hs:slv-usb-hs {
+			cell-id = <MSM_BUS_SLAVE_USB_HS>;
+			label = "slv-usb-hs";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_USB_HS>;
+		};
+
+		slv_qpic:slv-qpic {
+			cell-id = <MSM_BUS_SLAVE_QPIC>;
+			label = "slv-qpic";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_QPIC>;
+		};
+
+		slv_spdm: slv-spdm {
+			cell-id = <MSM_BUS_SLAVE_SPDM>;
+			label = "slv-spdm";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SPDM_WRAPPER>;
+		};
+
+		slv_sdcc_2:slv-sdcc-2 {
+			cell-id = <MSM_BUS_SLAVE_SDCC_2>;
+			label = "slv-sdcc-2";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SDCC_2>;
+		};
+
+		slv_audio:slv-audio {
+			cell-id = <MSM_BUS_SLAVE_AUDIO>;
+			label = "slv-audio";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_AUDIO>;
+		};
+
+		slv_dehr_cfg: slv-dehr-cfg {
+			cell-id = <MSM_BUS_SLAVE_DEHR_CFG>;
+			label = "slv-dehr-cfg";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_DEHR_CFG>;
+		};
+
+		slv_snoc_cfg:slv-snoc-cfg {
+			cell-id = <MSM_BUS_SLAVE_SNOC_CFG>;
+			label = "slv-snoc-cfg";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_CFG>;
+		};
+
+		slv_qdss_cfg: slv-qdss-cfg {
+			cell-id = <MSM_BUS_SLAVE_QDSS_CFG>;
+			label = "slv-qdss-cfg";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_QDSS_CFG>;
+		};
+
+		slv_usb_phy:slv-usb-phy {
+			cell-id = <MSM_BUS_SLAVE_USB_PHYS_CFG>;
+			label = "slv-usb-phy";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_USB_PHY_CFG>;
+		};
+
+		slv_camera_ss_cfg:slv-camera-ss-cfg {
+			cell-id = <MSM_BUS_SLAVE_CAMERA_CFG>;
+			label = "slv-camera-ss-cfg";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_CAMERA_CFG>;
+		};
+
+		slv_disp_ss_cfg:slv-disp-ss-cfg {
+			cell-id = <MSM_BUS_SLAVE_DISPLAY_CFG>;
+			label = "slv-disp-ss-cfg";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_DISPLAY_CFG>;
+		};
+
+		slv_venus_cfg:slv-venus-cfg {
+			cell-id = <MSM_BUS_SLAVE_VENUS_CFG>;
+			label = "slv-venus-cfg";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_VENUS_CFG>;
+		};
+
+		slv_tlmm:slv-tlmm {
+			cell-id = <MSM_BUS_SLAVE_TLMM>;
+			label = "slv-tlmm";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_TLMM>;
+		};
+
+		slv_gpu_cfg:slv-gpu-cfg {
+			cell-id = <MSM_BUS_SLAVE_GRAPHICS_3D_CFG>;
+			label = "slv-gpu-cfg";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_GFX3D_CFG>;
+		};
+
+		slv_imem_cfg: slv-imem-cfg {
+			cell-id = <MSM_BUS_SLAVE_IMEM_CFG>;
+			label = "slv-imem-cfg";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_IMEM_CFG>;
+		};
+
+		 slv_bimc_cfg: slv-bimc-cfg {
+			cell-id = <MSM_BUS_SLAVE_BIMC_CFG>;
+			label = "slv-bimc-cfg";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_BIMC_CFG>;
+		};
+
+		slv_pmic_arb:slv-pmic-arb {
+			cell-id = <MSM_BUS_SLAVE_PMIC_ARB>;
+			label = "slv-pmic-arb";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PMIC_ARB>;
+		};
+
+		slv_tcu:slv-tcu {
+			cell-id = <MSM_BUS_SLAVE_TCU>;
+			label = "slv-tcu";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_TCU>;
+		};
+
+		slv_pcnoc_snoc:slv-pcnoc-snoc {
+			cell-id = <MSM_BUS_PNOC_SNOC_SLV>;
+			label = "slv-pcnoc-snoc";
+			qcom,buswidth = <8>;
+			qcom,bus-dev = <&fab_pcnoc>;
+			qcom,connections = <&mas_pcnoc_snoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_PCNOC_SNOC>;
+		};
+
+		slv_kpss_ahb:slv-kpss-ahb {
+			cell-id = <MSM_BUS_SLAVE_APPSS>;
+			label = "slv-kpss-ahb";
+			qcom,buswidth = <4>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_APPSS>;
+		};
+
+		slv_snoc_bimc_0:slv-snoc-bimc-0 {
+			cell-id = <MSM_BUS_SNOC_BIMC_0_SLV>;
+			label = "slv-snoc-bimc-0";
+			qcom,buswidth = <8>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,connections = <&mas_snoc_bimc_0>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_BIMC_0>;
+		};
+
+		slv_snoc_bimc_1:slv-snoc-bimc-1 {
+			cell-id = <MSM_BUS_SNOC_BIMC_1_SLV>;
+			label = "slv-snoc-bimc-1";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,connections = <&mas_snoc_bimc_1>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_BIMC_1>;
+		};
+
+		slv_imem:slv-imem {
+			cell-id = <MSM_BUS_SLAVE_SYSTEM_IMEM>;
+			label = "slv-imem";
+			qcom,buswidth = <8>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_IMEM>;
+		};
+
+		slv_snoc_pcnoc:slv-snoc-pcnoc {
+			cell-id = <MSM_BUS_SNOC_PNOC_SLV>;
+			label = "slv-snoc-pcnoc";
+			qcom,buswidth = <8>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,connections = <&mas_snoc_pcnoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_SNOC_PCNOC>;
+		};
+
+		slv_qdss_stm:slv-qdss-stm {
+			cell-id = <MSM_BUS_SLAVE_QDSS_STM>;
+			label = "slv-qdss-stm";
+			qcom,buswidth = <4>;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_QDSS_STM>;
+		};
+
+		slv_cats_0:slv-cats-0 {
+			cell-id = <MSM_BUS_SLAVE_CATS_128>;
+			label = "slv-cats-0";
+			qcom,buswidth = <16>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_CATS_0>;
+		};
+
+		slv_cats_1:slv-cats-1 {
+			cell-id = <MSM_BUS_SLAVE_OCMEM_64>;
+			label = "slv-cats-1";
+			qcom,buswidth = <8>;
+			qcom,ap-owned;
+			qcom,bus-dev = <&fab_snoc>;
+			qcom,slv-rpm-id = <ICBID_SLAVE_CATS_1>;
+		};
+	};
+
+	devfreq_spdm_cpu {
+		compatible = "qcom,devfreq_spdm";
+		qcom,msm-bus,name = "devfreq_spdm";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<1 512 0 0>,
+				<1 512 0 0>;
+		qcom,msm-bus,active-only;
+		qcom,spdm-client = <0>;
+
+		clock-names = "cci_clk";
+		clocks = <&clock_cpu clk_a7ssmux>;
+
+		qcom,bw-upstep = <400>;
+		qcom,bw-dwnstep = <400>;
+		qcom,max-vote = <4000>;
+		qcom,up-step-multp = <3>;
+		qcom,spdm-interval = <100>;
+
+		qcom,ports = <11>;
+		qcom,alpha-up = <8>;
+		qcom,alpha-down = <15>;
+		qcom,bucket-size = <8>;
+
+		/*max pl1 freq, max pl2 freq*/
+		qcom,pl-freqs = <390000000 410000000>;
+
+		/* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
+		qcom,reject-rate = <5000 5000 5000 5000 5000 5000>;
+		/* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
+		qcom,response-time-us = <5000 5000 5000 5000 3000 3000>;
+		/* pl1 low, pl1 high, pl2 low, pl2 high, pl3 low, pl3 high */
+		qcom,cci-response-time-us = <5000 5000 5000 5000 1000 1000>;
+		qcom,max-cci-freq = <1090000000>;
+	};
+
+	devfreq_spdm_gov {
+		compatible = "qcom,gov_spdm_hyp";
+		interrupt-names = "spdm-irq";
+		interrupts = <0 192 0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8909-coresight.dtsi
new file mode 100644
index 0000000..4e7d6f8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-coresight.dtsi
@@ -0,0 +1,623 @@
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	tmc_etr: tmc@826000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0x826000 0x1000>,
+		      <0x884000 0x15000>;
+		reg-names = "tmc-base", "bam-base";
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
+
+		qcom,memory-size = <0x100000>;
+		qcom,sg-enable;
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+		coresight-ctis = <&cti0 &cti8>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	tpiu: tpiu@820000 {
+		compatible = "arm,coresight-tpiu";
+		reg = <0x820000 0x1000>,
+		      <0x1100000 0xb0000>;
+		reg-names = "tpiu-base", "nidnt-base";
+
+		coresight-id = <1>;
+		coresight-name = "coresight-tpiu";
+		coresight-nr-inports = <1>;
+
+		qcom,nidnthw;
+		qcom,nidnt-swduart;
+		qcom,nidnt-swdtrc;
+		qcom,nidnt-jtag;
+		qcom,nidnt-spmi;
+		nidnt-gpio = <38>;
+		nidnt-gpio-polarity = <1>;
+
+		interrupts = <0 82 0>;
+		interrupt-names = "nidnt-irq";
+
+		vdd-supply = <&pm8909_l11>;
+		qcom,vdd-voltage-level = <2950000 2950000>;
+		qcom,vdd-current-level = <15000 400000>;
+
+		vdd-io-supply = <&pm8909_l12>;
+		qcom,vdd-io-voltage-level = <2950000 2950000>;
+		qcom,vdd-io-current-level = <200 50000>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	replicator: replicator@824000 {
+		compatible = "qcom,coresight-replicator";
+		reg = <0x824000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-id = <2>;
+		coresight-name = "coresight-replicator";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0 1>;
+		coresight-child-list = <&tmc_etr &tpiu>;
+		coresight-child-ports = <0 0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	tmc_etf: tmc@825000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0x825000 0x1000>;
+		reg-names = "tmc-base";
+
+		coresight-id = <3>;
+		coresight-name = "coresight-tmc-etf";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&replicator>;
+		coresight-child-ports = <0>;
+		coresight-default-sink;
+		coresight-ctis = <&cti0 &cti8>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	funnel_in0: funnel@821000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0x821000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	funnel_in2: funnel@869000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0x869000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in2";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <6>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	funnel_in3: funnel@868000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0x868000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <6>;
+		coresight-name = "coresight-funnel-in3";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in2>;
+		coresight-child-ports = <7>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti0: cti@810000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x810000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <7>;
+		coresight-name = "coresight-cti0";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti1: cti@811000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x811000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <8>;
+		coresight-name = "coresight-cti1";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti2: cti@812000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x812000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <9>;
+		coresight-name = "coresight-cti2";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti3: cti@813000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x813000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <10>;
+		coresight-name = "coresight-cti3";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti4: cti@814000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x814000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <11>;
+		coresight-name = "coresight-cti4";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti5: cti@815000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x815000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <12>;
+		coresight-name = "coresight-cti5";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti6: cti@816000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x816000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <13>;
+		coresight-name = "coresight-cti6";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+
+		qcom,cti-gpio-trigout = <2>;
+		pinctrl-names = "cti-trigout-pctrl";
+		pinctrl-0 = <&trigout_a0>;
+	};
+
+	cti7: cti@817000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x817000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <14>;
+		coresight-name = "coresight-cti7";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti8: cti@818000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x818000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <15>;
+		coresight-name = "coresight-cti8";
+		coresight-nr-inports = <0>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_cpu0: cti@851000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x851000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <16>;
+		coresight-name = "coresight-cti-cpu0";
+		coresight-nr-inports = <0>;
+		coresight-cti-cpu = <&CPU0>;
+
+		qcom,cti-save;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_cpu1: cti@852000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x852000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <17>;
+		coresight-name = "coresight-cti-cpu1";
+		coresight-nr-inports = <0>;
+		coresight-cti-cpu = <&CPU1>;
+
+		qcom,cti-save;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_cpu2: cti@853000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x853000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <18>;
+		coresight-name = "coresight-cti-cpu2";
+		coresight-nr-inports = <0>;
+		coresight-cti-cpu = <&CPU2>;
+
+		qcom,cti-save;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_cpu3: cti@854000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x854000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <19>;
+		coresight-name = "coresight-cti-cpu3";
+		coresight-nr-inports = <0>;
+		coresight-cti-cpu = <&CPU3>;
+
+		qcom,cti-save;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_rpm_cpu0: cti@83c000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x83c000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <20>;
+		coresight-name = "coresight-cti-rpm-cpu0";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_modem_cpu0: cti@838000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x838000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <21>;
+		coresight-name = "coresight-cti-modem-cpu0";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_wcn_cpu0: cti@835000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x835000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <22>;
+		coresight-name = "coresight-cti-wcn-cpu0";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	cti_video_cpu0: cti@830000 {
+		compatible = "arm,coresight-cti";
+		reg = <0x830000 0x1000>;
+		reg-names = "cti-base";
+
+		coresight-id = <23>;
+		coresight-name = "coresight-cti-video-cpu0";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	stm: stm@802000 {
+		compatible = "arm,coresight-stm";
+		reg = <0x802000 0x1000>,
+		      <0x9280000 0x180000>;
+		reg-names = "stm-base", "stm-data-base";
+
+		coresight-id = <24>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <7>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	csr: csr@801000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0x801000 0x1000>;
+		reg-names = "csr-base";
+
+		coresight-id = <25>;
+		coresight-name = "coresight-csr";
+		coresight-nr-inports = <0>;
+
+		qcom,blk-size = <1>;
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	funnel_apss: funnel@855000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0x855000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-id = <26>;
+		coresight-name = "coresight-funnel-apss";
+		coresight-nr-inports = <4>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <4>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			<&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	etm0: etm@84c000 {
+		compatible = "arm,coresight-etm";
+		reg = <0x84c000 0x1000>;
+		reg-names = "etm-base";
+
+		coresight-id = <27>;
+		coresight-name = "coresight-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_apss>;
+		coresight-child-ports = <0>;
+		coresight-etm-cpu = <&CPU0>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	etm1: etm@84d000 {
+		compatible = "arm,coresight-etm";
+		reg = <0x84d000 0x1000>;
+		reg-names = "etm-base";
+
+		coresight-id = <28>;
+		coresight-name = "coresight-etm1";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_apss>;
+		coresight-child-ports = <1>;
+		coresight-etm-cpu = <&CPU1>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	etm2: etm@84e000 {
+		compatible = "arm,coresight-etm";
+		reg = <0x84e000 0x1000>;
+		reg-names = "etm-base";
+
+		coresight-id = <29>;
+		coresight-name = "coresight-etm2";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_apss>;
+		coresight-child-ports = <2>;
+		coresight-etm-cpu = <&CPU2>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	etm3: etm@84f000 {
+		compatible = "arm,coresight-etm";
+		reg = <0x84f000 0x1000>;
+		reg-names = "etm-base";
+
+		coresight-id = <30>;
+		coresight-name = "coresight-etm3";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_apss>;
+		coresight-child-ports = <3>;
+		coresight-etm-cpu = <&CPU3>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	hwevent: hwevent@86c000 {
+		compatible = "qcom,coresight-hwevent";
+		reg = <0x86c000 0x108>,
+		      <0x86cfb0 0x4>,
+		      <0x78c5010 0x4>,
+		      <0x7885010 0x4>;
+		reg-names = "wrapper-mux", "wrapper-lockaccess", "usbbam-mux",
+				"blsp-mux";
+		coresight-id = <31>;
+		coresight-name = "coresight-hwevent";
+		coresight-nr-inports = <0>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+
+	rpm_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-id = <32>;
+		coresight-name = "coresight-rpm-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <0>;
+
+		qcom,inst-id = <4>;
+	};
+
+	wcn_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-id = <33>;
+		coresight-name = "coresight-wcn-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in3>;
+		coresight-child-ports = <0>;
+
+		qcom,inst-id = <3>;
+	};
+
+	modem_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+
+		coresight-id = <34>;
+		coresight-name = "coresight-modem-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in0>;
+		coresight-child-ports = <2>;
+
+		qcom,inst-id = <2>;
+	};
+
+	fuse: fuse@5e01c {
+		compatible = "arm,coresight-fuse-v2";
+		reg = <0x5e01c 0x8>,
+		      <0x58040 0x4>,
+		      <0x5e00c 0x4>;
+		reg-names = "fuse-base", "nidnt-fuse-base", "qpdi-fuse-base";
+
+		coresight-id = <35>;
+		coresight-name = "coresight-fuse";
+		coresight-nr-inports = <0>;
+	};
+
+	qpdi: qpdi@1941000 {
+		compatible = "qcom,coresight-qpdi";
+		reg = <0x1941000 0x4>;
+		reg-names = "qpdi-base";
+
+		coresight-id = <36>;
+		coresight-name = "coresight-qpdi";
+		coresight-nr-inports = <0>;
+
+		vdd-supply = <&pm8909_l11>;
+		qcom,vdd-voltage-level = <2800000 2950000>;
+		qcom,vdd-current-level = <15000 400000>;
+
+		vdd-io-supply = <&pm8909_l12>;
+		qcom,vdd-io-voltage-level = <1800000 2950000>;
+		qcom,vdd-io-current-level = <200 50000>;
+	};
+
+	dbgui: dbgui@86d000 {
+		compatible = "qcom,coresight-dbgui";
+		reg = <0x86d000 0x1000>;
+		reg-names = "dbgui-base";
+
+		coresight-id = <37>;
+		coresight-name = "coresight-dbgui";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in2>;
+		coresight-child-ports = <2>;
+
+		qcom,dbgui-addr-offset = <0x30>;
+		qcom,dbgui-data-offset = <0xB0>;
+		qcom,dbgui-size = <32>;
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-ion.dtsi b/arch/arm64/boot/dts/qcom/msm8909-ion.dtsi
new file mode 100644
index 0000000..74f2be0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-ion.dtsi
@@ -0,0 +1,48 @@
+/* Copyright (c) 2014, 2016-2018, Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ion-heap@25 {
+			reg = <25>;
+			qcom,ion-heap-type = "SYSTEM";
+		};
+
+		qcom,ion-heap@27 { /* QSEECOM HEAP */
+			reg = <27>;
+			memory-region = <&venus_qseecom_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+
+		qcom,ion-heap@28 { /* AUDIO HEAP */
+			reg = <28>;
+			memory-region = <&audio_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+
+		modem_heap: qcom,ion-heap@26 { /* MODEM HEAP */
+			reg = <26>;
+			memory-region = <&modem_adsp_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+
+		adsp_heap: qcom,ion-heap@22 { /* MODEM HEAP */
+			reg = <22>;
+			memory-region = <&adsp_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-ipcrouter.dtsi b/arch/arm64/boot/dts/qcom/msm8909-ipcrouter.dtsi
new file mode 100644
index 0000000..aceefdf
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-ipcrouter.dtsi
@@ -0,0 +1,37 @@
+/* Copyright (c) 2016,2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	qcom,ipc_router {
+		compatible = "qcom,ipc_router";
+		qcom,node-id = <1>;
+	};
+
+	qcom,ipc_router_modem_xprt {
+		compatible = "qcom,ipc_router_smd_xprt";
+		qcom,ch-name = "IPCRTR";
+		qcom,xprt-remote = "modem";
+		qcom,xprt-linkid = <1>;
+		qcom,xprt-version = <1>;
+		qcom,fragmented-data;
+		qcom,disable-pil-loading;
+	};
+
+	qcom,ipc_router_wcnss_xprt {
+		compatible = "qcom,ipc_router_smd_xprt";
+		qcom,ch-name = "IPCRTR";
+		qcom,xprt-remote = "wcnss";
+		qcom,xprt-linkid = <1>;
+		qcom,xprt-version = <1>;
+		qcom,fragmented-data;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mdss-pll.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mdss-pll.dtsi
new file mode 100644
index 0000000..aa81972
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-mdss-pll.dtsi
@@ -0,0 +1,53 @@
+/* Copyright (c) 2016,2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	mdss_dsi0_pll: qcom,mdss_dsi_pll@1ac8300 {
+		compatible = "qcom,mdss_dsi_pll_8909";
+		label = "MDSS DSI 0 PLL";
+		cell-index = <0>;
+		#clock-cells = <1>;
+
+		reg = <0x1ac8300 0xd4>, <0x0184d074 0x8>;
+		reg-names = "pll_base", "gdsc_base";
+
+		gdsc-supply = <&gdsc_mdss>;
+		vddio-supply = <&pm8909_l6>;
+
+		clocks = <&clock_gcc clk_gcc_mdss_ahb_clk>;
+		clock-names = "iface_clk";
+		clock-rate = <0>;
+
+		qcom,platform-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,platform-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "gdsc";
+				qcom,supply-min-voltage = <0>;
+				qcom,supply-max-voltage = <0>;
+				qcom,supply-enable-load = <0>;
+				qcom,supply-disable-load = <0>;
+			};
+
+			qcom,platform-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/arm64/boot/dts/qcom/msm8909-mdss.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mdss.dtsi
new file mode 100644
index 0000000..0d824e0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-mdss.dtsi
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2014-2016,2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	mdss_mdp: qcom,mdss_mdp@1a00000 {
+		compatible = "qcom,mdss_mdp3";
+		reg = <0x1a00000 0x100000>,
+			<0x1ab0000 0x3000>;
+		reg-names = "mdp_phys", "vbif_phys";
+		interrupts = <0 72 0>;
+
+		vdd-supply = <&gdsc_mdss>;
+		clocks = <&clock_gcc clk_gcc_mdss_ahb_clk>,
+			 <&clock_gcc clk_gcc_mdss_axi_clk>,
+			 <&clock_gcc clk_mdp_clk_src>,
+			 <&clock_gcc clk_gcc_mdss_mdp_clk>,
+			 <&clock_gcc clk_gcc_mdss_vsync_clk>;
+		clock-names = "iface_clk", "bus_clk", "core_clk_src",
+				"core_clk", "vsync_clk";
+
+		mdss_fb0: qcom,mdss_fb_primary {
+			cell-index = <0>;
+			compatible = "qcom,mdss-fb";
+			qcom,cont-splash-memory {
+			linux,contiguous-region = <&cont_splash_mem>;
+			};
+		};
+
+		smmu_mdp_unsec: qcom,smmu_mdp_unsec_cb {
+			compatible = "qcom,smmu_mdp_unsec";
+		};
+		smmu_mdp_sec: qcom,smmu_mdp_sec_cb {
+			compatible = "qcom,smmu_mdp_sec";
+		};
+	};
+
+	mdss_dsi: qcom,mdss_dsi@0 {
+		compatible = "qcom,mdss-dsi";
+		hw-config = "single_dsi";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		qcom,mdss-fb-map-prim = <&mdss_fb0>;
+		gdsc-supply = <&gdsc_mdss>;
+		vdda-supply = <&pm8909_l2>;
+		vddio-supply = <&pm8909_l6>;
+
+		/* Bus Scale Settings */
+		qcom,msm-bus,name = "mdss_dsi";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<22 512 0 0>,
+			<22 512 0 1000>;
+
+		ranges = <0x1ac8000 0x1ac8000 0x25c
+			0x1ac8500 0x1ac8500 0x280
+			0x1ac8780 0x1ac8780 0x30
+			0x193e000 0x193e000 0x30>;
+
+		clocks = <&clock_gcc clk_gcc_mdss_mdp_clk>,
+			 <&clock_gcc clk_gcc_mdss_ahb_clk>,
+			 <&clock_gcc clk_gcc_mdss_axi_clk>;
+		clock-names = "mdp_core_clk", "iface_clk", "bus_clk";
+
+		qcom,mmss-ulp-clamp-ctrl-offset = <0x20>;
+		qcom,mmss-phyreset-ctrl-offset = <0x24>;
+
+		qcom,core-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,core-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "gdsc";
+				qcom,supply-min-voltage = <0>;
+				qcom,supply-max-voltage = <0>;
+				qcom,supply-enable-load = <0>;
+				qcom,supply-disable-load = <0>;
+			};
+		};
+
+		qcom,ctrl-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,ctrl-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vdda";
+				qcom,supply-min-voltage = <1200000>;
+				qcom,supply-max-voltage = <1200000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+				qcom,supply-post-on-sleep = <5>;
+			};
+		};
+
+		qcom,phy-supply-entries {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			qcom,phy-supply-entry@0 {
+				reg = <0>;
+				qcom,supply-name = "vddio";
+				qcom,supply-min-voltage = <1800000>;
+				qcom,supply-max-voltage = <1800000>;
+				qcom,supply-enable-load = <100000>;
+				qcom,supply-disable-load = <100>;
+			};
+		};
+
+		mdss_dsi0: qcom,mdss_dsi_ctrl0@1ac8000 {
+			compatible = "qcom,mdss-dsi-ctrl";
+			label = "MDSS DSI CTRL->0";
+			cell-index = <0>;
+			reg = <0x1ac8000 0x25c>,
+			      <0x1ac8500 0x280>,
+			      <0x1ac8780 0x30>,
+			      <0x193e000 0x30>;
+			reg-names = "dsi_ctrl", "dsi_phy",
+				"dsi_phy_regulator", "mmss_misc_phys";
+
+			qcom,dsi-irq-line;
+			interrupts = <0 80 0>;
+
+			qcom,mdss-mdp = <&mdss_mdp>;
+			vdd-supply = <&pm8909_l17>;
+			vddio-supply = <&pm8909_l6>;
+
+			clocks = <&clock_gcc_mdss clk_gcc_mdss_byte0_clk>,
+				 <&clock_gcc_mdss clk_gcc_mdss_pclk0_clk>,
+				 <&clock_gcc clk_gcc_mdss_esc0_clk>;
+			clock-names = "byte_clk", "pixel_clk", "core_clk";
+
+			qcom,regulator-ldo-mode;
+
+			qcom,platform-strength-ctrl = [ff 06];
+			qcom,platform-bist-ctrl = [00 00 b1 ff 00 00];
+			qcom,platform-regulator-settings =
+					[00 01 01 00 20 07 00];
+			qcom,platform-lane-config =
+				[00 00 00 00 00 00 00 01 97
+				00 00 00 00 05 00 00 01 97
+				00 00 00 00 0a 00 00 01 97
+				00 00 00 00 0f 00 00 01 97
+				00 c0 00 00 00 00 00 01 bb];
+		};
+	};
+};
+
+/* #include "msm8909-mdss-panels.dtsi" */
diff --git a/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
new file mode 100644
index 0000000..7f18173
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-mtp.dtsi
@@ -0,0 +1,428 @@
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8909.dtsi"
+#include "msm8909-pinctrl.dtsi"
+#include "msm8909-regulator.dtsi"
+
+&soc {
+	/*
+	 * DT node to add support for SMB135x charger and integrate
+	 * with VM-BMS.
+	 */
+	i2c@78b8000 {
+		smb1357_otg_vreg: smb1357-charger@57 {
+			compatible = "qcom,smb1357-charger";
+			reg = <0x57>;
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <58 8>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&smb_int_default>;
+
+			qcom,bmd-algo-disabled;
+			qcom,float-voltage-mv = <4200>;
+			qcom,charging-timeout = <1536>;
+			qcom,recharge-thresh-mv = <100>;
+			regulator-name = "smb1357_otg_vreg";
+			qcom,soft-vfloat-comp-disabled;
+			qcom,thermal-mitigation = <1500 700 600 0>;
+
+			qcom,bms-psy-name = "bms";
+
+			/*
+			 * Disable SMB1357 based charging termination as BMS
+			 * controls charging.
+			 */
+			qcom,iterm-disabled;
+
+			/*
+			 * Disable charge inhibit feature to start chargin on
+			 * charger insertion independent of battery voltage.
+			 */
+			qcom,inhibit-disabled;
+
+			/* BMS is controlling charging/re-charge */
+			qcom,bms-controlled-charging;
+
+			/*
+			 * To enable charger node:
+			 * set status = "ok" and
+			 * add 'qcom,use-external-charger' to pm8909_chg node
+			 */
+			status = "disabled";
+		};
+	};
+
+	/*
+	 * DT node to add support for SMB358 charger and integrate
+	 * with VM-BMS.
+	 */
+	i2c@78b8000 {
+	};
+
+	i2c@78b9000 { /* BLSP1 QUP5 */
+		synaptics@20 {
+			compatible = "synaptics,dsx";
+			reg = <0x20>;
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <13 0x2008>;
+			avdd-supply = <&pm8909_l17>;
+			vdd-supply = <&pm8909_l6>;
+			/* pins used by touchscreen */
+			pinctrl-names = "pmx_ts_active",
+				"pmx_ts_suspend","pmx_ts_release";
+			pinctrl-0 = <&ts_int_active &ts_reset_active>;
+			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+			pinctrl-2 = <&ts_release>;
+			synaptics,irq-gpio = <&msm_gpio 13 0x2008>;
+			synaptics,reset-gpio = <&msm_gpio 12 0x0>;
+			synaptics,disable-gpios;
+			synaptics,display-coords = <0 0 719 1279>;
+			synaptics,panel-coords = <0 0 719 1405>;
+		};
+	};
+
+	i2c@78b6000 { /* BLSP1 QUP2 */
+		nq@28 {
+			compatible = "qcom,nq-nci";
+			reg = <0x28>;
+			qcom,nq-irq = <&msm_gpio 21 0x00>;
+			qcom,nq-ven = <&msm_gpio 20 0x00>;
+			qcom,nq-firm = <&msm_gpio 45 0x00>;
+			qcom,clk-src = "BBCLK2";
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <21 0>;
+			interrupt-names = "nfc_irq";
+			pinctrl-names = "nfc_active","nfc_suspend";
+			pinctrl-0 = <&nfc_int_active &nfc_disable_active>;
+			pinctrl-1 = <&nfc_int_suspend &nfc_disable_suspend>;
+			clocks = <&clock_rpm clk_bb_clk2_pin>;
+			clock-names = "ref_clk";
+		};
+	};
+
+	gpio_keys {
+		compatible = "gpio-keys";
+		input-name = "gpio-keys";
+		pinctrl-names = "tlmm_gpio_key_active","tlmm_gpio_key_suspend";
+		pinctrl-0 = <&gpio_key_active>;
+		pinctrl-1 = <&gpio_key_suspend>;
+
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&msm_gpio 91 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&msm_gpio 92 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+
+		vol_up {
+			label = "volume_up";
+			gpios = <&msm_gpio 90 0x1>;
+			linux,input-type = <1>;
+			linux,code = <115>;
+			gpio-key,wakeup;
+			debounce-interval = <15>;
+		};
+	};
+
+	audio_codec_mtp: sound {
+		compatible = "qcom,msm8952-audio-codec";
+		qcom,model = "msm8909-snd-card";
+		reg = <0x7702000 0x4>,
+		      <0x7702004 0x4>,
+		      <0x7702008 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			    "csr_gp_io_mux_spkr_ctl",
+			    "csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel";
+
+		qcom,msm-snd-card-id = <0>;
+		qcom,msm-codec-type = "internal";
+		qcom,msm-ext-pa = "primary";
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,msm-hs-micbias-type = "internal";
+		qcom,msm-micbias1-ext-cap;
+		qcom,split-a2dp;
+		qcom,audio-routing =
+			"RX_BIAS", "MCLK",
+			"SPK_RX_BIAS", "MCLK",
+			"INT_LDO_H", "MCLK",
+			"MIC BIAS External", "Handset Mic",
+			"MIC BIAS Internal2", "Headset Mic",
+			"MIC BIAS External", "Secondary Mic",
+			"AMIC1", "MIC BIAS External",
+			"AMIC2", "MIC BIAS Internal2",
+			"AMIC3", "MIC BIAS External";
+		qcom,msm-gpios =
+			"pri_i2s",
+			"us_eu_gpio";
+		qcom,pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"us_eu_gpio_act",
+			"pri_i2s_us_eu_gpio_act";
+		pinctrl-names =
+			"all_off",
+			"pri_i2s_act",
+			"us_eu_gpio_act",
+			"pri_i2s_us_eu_gpio_act";
+		pinctrl-0 = <&cdc_pdm_lines_sus &cross_conn_det_sus
+							&vdd_spkdrv_sus>;
+		pinctrl-1 = <&cdc_pdm_lines_act &cross_conn_det_sus
+							&vdd_spkdrv_act>;
+		pinctrl-2 = <&cdc_pdm_lines_sus &cross_conn_det_act
+							&vdd_spkdrv_sus>;
+		pinctrl-3 = <&cdc_pdm_lines_act &cross_conn_det_act
+							&vdd_spkdrv_act>;
+		qcom,cdc-us-euro-gpios = <&msm_gpio 97 0>;
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&lpa>,
+				<&voice_svc>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2", "msm-voip-dsp",
+				"msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless",
+				"msm-pcm-afe", "msm-lsm-client",
+				"msm-pcm-routing", "msm-pcm-lpa",
+				"msm-voice-svc";
+		asoc-cpu = <&dai_pri_auxpcm>,
+				<&dai_mi2s0>, <&dai_mi2s1>, <&dai_mi2s2>,
+				<&dai_mi2s3>, <&dai_mi2s5>, <&dai_mi2s6>,
+				<&bt_sco_rx>, <&bt_sco_tx>, <&bt_a2dp_rx>,
+				<&int_fm_rx>, <&int_fm_tx>, <&afe_pcm_rx>,
+				<&afe_pcm_tx>, <&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>,
+				<&incall_music_rx>, <&incall_music_2_rx>;
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.5", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12290", "msm-dai-q6-dev.12292",
+				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.224",
+				"msm-dai-q6-dev.225", "msm-dai-q6-dev.241",
+				"msm-dai-q6-dev.240", "msm-dai-q6-dev.32771",
+				"msm-dai-q6-dev.32772", "msm-dai-q6-dev.32773",
+				"msm-dai-q6-dev.32770";
+		asoc-codec = <&stub_codec>, <&pm8909_conga_dig>;
+		asoc-codec-names = "msm-stub-codec.1", "cajon_codec";
+	};
+};
+
+&blsp1_uart1 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_sleep>;
+};
+
+&qcom_rng {
+	status = "okay";
+};
+
+&qcom_crypto {
+	status = "okay";
+};
+
+&qcom_cedev {
+	status = "okay";
+};
+
+&qcom_seecom {
+	status = "okay";
+};
+
+&qcom_tzlog {
+	status = "okay";
+};
+
+&qnand_1 {
+	status = "ok";
+};
+
+&sdhc_1 {
+	vdd-supply = <&pm8909_l8>;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 400000>;
+
+	vdd-io-supply = <&pm8909_l5>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 60000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off>;
+
+	qcom,bus-speed-mode = "HS200_1p8v", "DDR_1p8v";
+	qcom,nonremovable;
+
+	status = "ok";
+};
+
+&sdhc_2 {
+	 #address-cells = <0>;
+	interrupt-parent = <&sdhc_2>;
+	interrupts = <0 1 2>;
+	#interrupt-cells = <1>;
+	interrupt-map-mask = <0xffffffff>;
+	interrupt-map = <0 &intc 0 125 0
+			1 &intc 0 221 0
+			2 &msm_gpio 38 0>;
+	interrupt-names = "hc_irq", "pwr_irq", "status_irq";
+	cd-gpios = <&msm_gpio 38 0x1>;
+
+	vdd-supply = <&pm8909_l11>;
+	qcom,vdd-voltage-level = <1800000 2950000>;
+	qcom,vdd-current-level = <15000 400000>;
+
+	vdd-io-supply = <&pm8909_l12>;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 50000>;
+
+	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>;
+
+	status = "ok";
+};
+
+&i2c_1 { /* BLSP1 QUP1 */
+};
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&msm_gpio {
+	pmx_mdss {
+		mdss_dsi_active: mdss_dsi_active {
+			mux {
+				pins = "gpio25", "gpio37";
+			};
+			config {
+				pins = "gpio25", "gpio37";
+			};
+		};
+		mdss_dsi_suspend: mdss_dsi_suspend {
+			mux {
+				pins = "gpio25", "gpio37";
+			};
+			config {
+				pins = "gpio25", "gpio37";
+			};
+		};
+	};
+	pmx_mdss_te {
+		mdss_te_active: mdss_te_active {
+			mux {
+				pins = "gpio24";
+			};
+			config {
+				pins = "gpio24";
+			};
+		};
+		mdss_te_suspend: mdss_te_suspend {
+			mux {
+				pins = "gpio24";
+			};
+			config {
+				pins = "gpio24";
+			};
+		};
+	};
+	mpu6050_int_pin {
+		mpu6050_default: mpu6050_default {
+			mux {
+				pins = "gpio96";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio96";
+				drive-dtrength = <6>;
+				bias-pull-down;
+			};
+		};
+		mpu6050_sleep: mpu6050_sleep {
+			mux {
+				pins = "gpio96";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio96";
+				drive-dtrength = <2>;
+				bias-pull-down;
+			};
+		};
+	};
+	ak8963_int_pin {
+		ak8963_default: ak8963_default {
+			mux {
+				pins = "gpio65";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio65";
+				drive-strength = <6>;
+				bias-pull-up;
+			};
+		};
+		ak8963_sleep: ak8963_sleep {
+			mux {
+				pins = "gpio65";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio65";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+		};
+	};
+};
+
+/* CoreSight */
+&tpiu {
+	pinctrl-names = "sdcard", "trace", "swduart",
+			"swdtrc", "jtag", "spmi";
+	/* NIDnT */
+	pinctrl-0 = <&qdsd_clk_sdcard &qdsd_cmd_sdcard
+		     &qdsd_data0_sdcard &qdsd_data1_sdcard
+		     &qdsd_data2_sdcard &qdsd_data3_sdcard>;
+	pinctrl-1 = <&qdsd_clk_trace &qdsd_cmd_trace
+		     &qdsd_data0_trace &qdsd_data1_trace
+		     &qdsd_data2_trace &qdsd_data3_trace>;
+	pinctrl-2 = <&qdsd_cmd_swduart &qdsd_data0_swduart
+		     &qdsd_data1_swduart &qdsd_data2_swduart
+		     &qdsd_data3_swduart>;
+	pinctrl-3 = <&qdsd_clk_swdtrc &qdsd_cmd_swdtrc
+		     &qdsd_data0_swdtrc &qdsd_data1_swdtrc
+		     &qdsd_data2_swdtrc &qdsd_data3_swdtrc>;
+	pinctrl-4 = <&qdsd_cmd_jtag &qdsd_data0_jtag
+		     &qdsd_data1_jtag &qdsd_data2_jtag
+		     &qdsd_data3_jtag>;
+	pinctrl-5 = <&qdsd_clk_spmi &qdsd_cmd_spmi
+		     &qdsd_data0_spmi &qdsd_data3_spmi>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
new file mode 100644
index 0000000..25688ff
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-pinctrl.dtsi
@@ -0,0 +1,2193 @@
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	msm_gpio: pinctrl@1000000 {
+		compatible = "qcom,msm8909-pinctrl";
+		reg = <0x1000000 0x300000>;
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+		/* sensors */
+		cam_sensor_mclk0_default: cam_sensor_mclk0_default {
+			/* MCLK0 */
+			mux {
+				/* CLK, DATA */
+				pins = "gpio26";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio26";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk0_sleep: cam_sensor_mclk0_sleep {
+			/* MCLK0 */
+			mux {
+				/* CLK, DATA */
+				pins = "gpio26";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio26";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_default: cam_sensor_rear_default {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio35", "gpio34";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio35","gpio34";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_rear_sleep: cam_sensor_rear_sleep {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio35","gpio34";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio35","gpio34";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk1_default: cam_sensor_mclk1_default {
+			/* MCLK1 */
+			mux {
+				/* CLK, DATA */
+				pins = "gpio27";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio27";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_mclk1_sleep: cam_sensor_mclk1_sleep {
+			/* MCLK1 */
+			mux {
+				/* CLK, DATA */
+				pins = "gpio27";
+				function = "cam_mclk";
+			};
+
+			config {
+				pins = "gpio27";
+				bias-pull-down; /* PULL DOWN */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_front_default: cam_sensor_front_default {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio28","gpio33";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio28","gpio33";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_front_sleep: cam_sensor_front_sleep {
+			/* RESET, STANDBY */
+			mux {
+				pins = "gpio28","gpio33";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio28","gpio33";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_flash_default: cam_sensor_flash_default {
+		/* FLASH_RESET,FLASH_EN,FLASH_NOW */
+			mux {
+				pins = "gpio36", "gpio31", "gpio32";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio36", "gpio31", "gpio32";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		cam_sensor_flash_sleep: cam_sensor_flash_sleep {
+			 mux {
+				pins = "gpio36", "gpio31", "gpio32";
+				function = "gpio";
+			};
+			config {
+				pins = "gpio36", "gpio31", "gpio32";
+				bias-disable; /* No PULL */
+				drive-strength = <2>; /* 2 MA */
+			};
+		};
+
+		uart_console_active: uart_console_active {
+			mux {
+				pins = "gpio4", "gpio5";
+				function = "blsp_uart1";
+			};
+			config {
+				pins = "gpio4", "gpio5";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+		uart_console_sleep: uart_console_sleep {
+			mux {
+				pins = "gpio4", "gpio5";
+				function = "blsp_uart1";
+			};
+			config {
+				pins = "gpio4", "gpio5";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+		};
+
+		uart_console2_active: uart_console2_active {
+			mux {
+				pins = "gpio20", "gpio21";
+				function = "blsp_uart2";
+			};
+			config {
+				pins = "gpio20", "gpio21";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+		uart_console2_sleep: uart_console2_sleep {
+			mux {
+				pins = "gpio20", "gpio21";
+				function = "blsp_uart2";
+			};
+			config {
+				pins = "gpio20", "gpio21";
+				drive-strength = <2>;
+				bias-pull-down;
+			};
+		};
+
+		blsp1_uart2_tx_active: blsp1_uart2_tx_active {
+			mux {
+				pins = "gpio20";
+				function = "blsp_uart2";
+			};
+
+			config {
+				pins = "gpio20";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		blsp1_uart2_tx_sleep: blsp1_uart2_tx_sleep {
+			mux {
+				pins = "gpio20";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio20";
+				drive-strength = <2>;
+				bias-pull-up;
+			};
+		};
+
+		blsp1_uart2_rxcts_active: blsp1_uart2_rxcts_active {
+			mux {
+				pins = "gpio21", "gpio111";
+				function = "blsp_uart2";
+			};
+
+			config {
+				pins = "gpio21", "gpio111";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		blsp1_uart2_rxcts_sleep: blsp1_uart2_rxcts_sleep {
+			mux {
+				pins = "gpio21", "gpio111";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio21", "gpio111";
+				drive-strength = <2>;
+				bias-no-pull;
+			};
+		};
+
+		blsp1_uart2_rfr_active: blsp1_uart2_rfr_active {
+			mux {
+				pins = "gpio112";
+				function = "blsp_uart2";
+			};
+
+			config {
+				pins = "gpio112";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		blsp1_uart2_rfr_sleep: blsp1_uart2_rfr_sleep {
+			mux {
+				pins = "gpio112";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio112";
+				drive-strength = <2>;
+				bias-no-pull;
+			};
+		};
+
+		pmx_mdss {
+			mdss_dsi_active: mdss_dsi_active {
+				mux {
+					pins = "gpio25", "gpio37";
+					function = "gpio";
+				};
+
+				config {
+					drive-strength = <8>; /* 8 mA */
+					bias-disable = <0>; /* no pull */
+					output-high;
+				};
+			};
+
+			mdss_dsi_suspend: mdss_dsi_suspend {
+				mux {
+					pins = "gpio25", "gpio37";
+					function = "gpio";
+				};
+
+				config {
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+					output-low;
+				};
+			};
+		};
+
+		pmx_mdss_te {
+			mdss_te_active: mdss_te_active {
+				mux {
+					pins = "gpio24";
+					function = "mdp_vsync";
+				};
+
+				config {
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+				};
+			};
+
+			mdss_te_suspend: mdss_te_suspend {
+				mux {
+					pins = "gpio24";
+					function = "mdp_vsync";
+				};
+
+				config {
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+				};
+			};
+		};
+
+		spi0 {
+			spi0_default: spi0_default {
+				mux {
+					pins = "gpio8", "gpio9",
+						"gpio11";
+					function = "blsp_spi6";
+				};
+				config {
+					pins = "gpio8", "gpio9",
+						"gpio11";
+					drive-strength = <12>; /* 12 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			spi0_sleep: spi0_sleep {
+				mux {
+					pins = "gpio8", "gpio9",
+						"gpio11";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio8", "gpio9",
+						"gpio11";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* pull down */
+				};
+			};
+			spi0_cs0_active: spi0_cs0_active {
+				mux {
+					pins = "gpio10";
+					function = "blsp_spi6";
+				};
+				config {
+					pins = "gpio10";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+			spi0_cs0_sleep: spi0_cs0_sleep {
+				mux {
+					pins = "gpio10";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio10";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		spi2 {
+			spi2_default: spi2_default {
+				mux {
+					pins = "gpio20", "gpio21",
+						"gpio112";
+					function = "blsp_spi2";
+				};
+				config {
+					pins = "gpio20", "gpio21",
+						"gpio112";
+					drive-strength = <12>; /* 12 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			spi2_sleep: spi2_sleep {
+				mux {
+					pins = "gpio20", "gpio21",
+						"gpio112";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio20", "gpio21",
+						"gpio112";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* pull down */
+				};
+			};
+			spi2_cs0_active: spi2_cs0_active {
+				mux {
+					pins = "gpio111";
+					function = "blsp_spi2";
+				};
+				config {
+					pins = "gpio111";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+			spi2_cs0_sleep: spi2_cs0_sleep {
+				mux {
+					pins = "gpio111";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio111";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		spi4 {
+			spi4_default: spi4_default {
+				mux {
+					pins = "gpio12", "gpio13",
+						"gpio15";
+					function = "blsp_spi4";
+				};
+				config {
+					pins = "gpio12", "gpio13",
+						"gpio15";
+					drive-strength = <12>; /* 12 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			spi4_sleep: spi4_sleep {
+				mux {
+					pins = "gpio12", "gpio13",
+						"gpio15";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio12", "gpio13",
+						"gpio15";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* pull down */
+				};
+			};
+			spi4_cs0_active: spi4_cs0_active {
+				mux {
+					pins = "gpio14";
+					function = "blsp_spi4";
+				};
+				config {
+					pins = "gpio14";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+			spi4_cs0_sleep: spi4_cs0_sleep {
+				mux {
+					pins = "gpio14";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio14";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_i2c_1 {
+			i2c_1_active: i2c_1_active {
+				mux {
+					pins = "gpio6", "gpio7";
+					function = "blsp_i2c1";
+				};
+				config {
+					pins = "gpio6", "gpio7";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			i2c_1_sleep: i2c_1_sleep {
+				mux {
+					pins = "gpio6", "gpio7";
+					function = "blsp_i2c1";
+				};
+				config {
+					pins = "gpio6", "gpio7";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+		};
+
+		pmx_i2c_2 {
+			i2c_2_active: i2c_2_active {
+				mux {
+					pins = "gpio111", "gpio112";
+					function = "blsp_i2c2";
+				};
+				config {
+					pins = "gpio111", "gpio112";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			i2c_2_sleep: i2c_2_sleep {
+				mux {
+					pins = "gpio111", "gpio112";
+					function = "blsp_i2c2";
+				};
+				config {
+					pins = "gpio111", "gpio112";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+		};
+
+		nfc {
+			nfcw_int_active: nfcw_int_active {
+				mux {
+					pins = "gpio50";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio50";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			nfcw_int_suspend: nfcw_int_suspend {
+				mux {
+					pins = "gpio50";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio50";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			nfcw_disable_active: nfcw_disable_active {
+				mux {
+					pins = "gpio36";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio36";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			nfcw_disable_suspend: nfcw_disable_suspend {
+				mux {
+					pins = "gpio36";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio36";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+
+			nfcv2k_disable_active: nfcv2k_disable_active {
+				mux {
+					pins = "gpio52";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio52";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			nfcv2k_disable_suspend: nfcv2k_disable_suspend {
+				mux {
+					pins = "gpio52";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio52";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+
+			nfc_int_active: nfc_int_active {
+				mux {
+					pins = "gpio21";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio21";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			nfc_int_suspend: nfc_int_suspend {
+				mux {
+					pins = "gpio21";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio21";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			nfc_disable_active: nfc_disable_active {
+				mux {
+					pins = "gpio20";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio20";
+					drive-strength = <6>;
+					bias-pull-up;
+				};
+			};
+
+			nfc_disable_suspend: nfc_disable_suspend {
+				mux {
+					pins = "gpio20";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio20";
+					drive-strength = <6>;
+					bias-disable;
+				};
+			};
+		};
+
+		pmx_i2c_3 {
+			i2c_3_active: i2c_3_active {
+				mux {
+					pins = "gpio29", "gpio30";
+					function = "blsp_i2c3";
+				};
+				config {
+					pins = "gpio29", "gpio30";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			i2c_3_sleep: i2c_3_sleep {
+				mux {
+					pins = "gpio29", "gpio30";
+					function = "blsp_i2c3";
+				};
+				config {
+					pins = "gpio29", "gpio30";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+		};
+
+		pmx_i2c_4 {
+			i2c_4_active: i2c_4_active {
+				mux {
+					pins = "gpio14", "gpio15";
+					function = "blsp_i2c4";
+				};
+				config {
+					pins = "gpio14", "gpio15";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			i2c_4_sleep: i2c_4_sleep {
+				mux {
+					pins = "gpio14", "gpio15";
+					function = "blsp_i2c4";
+				};
+				config {
+					pins = "gpio14", "gpio15";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+		};
+
+		pmx_i2c_5 {
+			i2c_5_active: i2c_5_active {
+				mux {
+					pins = "gpio19", "gpio18";
+					function = "blsp_i2c5";
+				};
+				config {
+					pins = "gpio19", "gpio18";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+			i2c_5_sleep: i2c_5_sleep {
+				mux {
+					pins = "gpio19", "gpio18";
+					function = "blsp_i2c5";
+				};
+				config {
+					pins = "gpio19", "gpio18";
+					drive-strength = <2>; /* 2 MA */
+					bias-disable; /* No PULL */
+				};
+			};
+		};
+
+		smb_int_pin {
+			smb_int_default: smb_int_default {
+				mux {
+					pins = "gpio58";
+					function ="smb_int";
+				};
+				config {
+					pins = "gpio58";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-up;           /* PULL UP*/
+				};
+			};
+			smb_int_sleep: smb_int_sleep {
+				mux {
+					pins = "gpio58";
+					function ="smb_int";
+				};
+				config {
+					pins = "gpio58";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-up;           /* PULL UP*/
+				};
+			};
+		};
+
+		pmx_sdc1_clk {
+			sdc1_clk_on: sdc1_clk_on {
+				config {
+					pins = "sdc1_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <16>; /* 16 MA */
+				};
+			};
+			sdc1_clk_off: sdc1_clk_off {
+				config {
+					pins = "sdc1_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc1_cmd {
+			sdc1_cmd_on: sdc1_cmd_on {
+				config {
+					pins = "sdc1_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+			sdc1_cmd_off: sdc1_cmd_off {
+				config {
+					pins = "sdc1_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc1_data {
+			sdc1_data_on: sdc1_data_on {
+				config {
+					pins = "sdc1_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+			sdc1_data_off: sdc1_data_off {
+				config {
+					pins = "sdc1_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc2_clk {
+			sdc2_clk_on: sdc2_clk_on {
+				config {
+					pins = "sdc2_clk";
+					drive-strength = <16>; /* 16 MA */
+					bias-disable; /* NO pull */
+				};
+			};
+			sdc2_clk_off: sdc2_clk_off {
+				config {
+					pins = "sdc2_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc2_cmd {
+			sdc2_cmd_on: sdc2_cmd_on {
+				config {
+					pins = "sdc2_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+			sdc2_cmd_off: sdc2_cmd_off {
+				config {
+					pins = "sdc2_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc2_data {
+			sdc2_data_on: sdc2_data_on {
+				config {
+					pins = "sdc2_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+			sdc2_data_off: sdc2_data_off {
+				config {
+					pins = "sdc2_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		sdhc2_cd_pin {
+			sdc2_cd_on: cd_on {
+				mux {
+					pins = "gpio38";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio38";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+			sdc2_cd_off: cd_off {
+				mux {
+					pins = "gpio38";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio38";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		/* add pingrp for touchscreen */
+		pmx_ts_int_active {
+			ts_int_active: ts_int_active {
+				mux {
+					pins = "gpio13";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio13";
+					drive-strength = <8>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_ts_int_suspend {
+			ts_int_suspend: ts_int_suspend {
+				mux {
+					pins = "gpio13";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio13";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pmx_ts_reset_active {
+			ts_reset_active: ts_reset_active {
+				mux {
+					pins = "gpio12";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio12";
+					drive-strength = <8>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_ts_reset_suspend {
+			ts_reset_suspend: ts_reset_suspend {
+				mux {
+					pins = "gpio12";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio12";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		/* Pinctrl dt nodes for reset gpio for ITE tech controller */
+		pmx_ts_ite_reset_active {
+			ts_ite_reset_active: ts_ite_reset_active {
+				mux {
+					pins = "gpio12";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio12";
+					drive-strength = <8>;
+					bias-pull-down;
+					output-high;
+				};
+			};
+		};
+
+		pmx_ts_ite_reset_suspend {
+			ts_ite_reset_suspend: ts_ite_reset_suspend {
+				mux {
+					pins = "gpio12";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio12";
+					drive-strength = <2>;
+					bias-pull-down;
+					output-low;
+				};
+			};
+		};
+
+		pmx_ts_release {
+			ts_release: ts_release {
+				mux {
+					pins = "gpio13", "gpio12";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio13", "gpio12";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		tlmm_gpio_key {
+			gpio_key_active: gpio_key_active {
+				mux {
+					pins = "gpio90", "gpio91", "gpio92";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio90", "gpio91", "gpio92";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+
+			gpio_key_suspend: gpio_key_suspend {
+				mux {
+					pins = "gpio90", "gpio91", "gpio92";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio90", "gpio91", "gpio92";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		wcnss_pmux_5wire {
+			wcnss_default: wcnss_default {
+				wcss_wlan2 {
+					pins = "gpio40";
+					function = "wcss_wlan2";
+				};
+				wcss_wlan1 {
+					pins = "gpio41";
+					function = "wcss_wlan1";
+				};
+				wcss_wlan0 {
+					pins = "gpio42";
+					function = "wcss_wlan0";
+				};
+				wcss_wlan {
+					pins = "gpio43", "gpio44";
+					function = "wcss_wlan";
+				};
+				config {
+					pins = "gpio40", "gpio41",
+						"gpio42", "gpio43",
+						"gpio44";
+					drive-strength = <6>; /* 6 MA */
+					bias-pull-up; /* PULL UP */
+				};
+			};
+
+			wcnss_sleep: wcnss_sleep {
+				wcss_wlan2 {
+					pins = "gpio40";
+					function = "wcss_wlan2";
+				};
+				wcss_wlan1 {
+					pins = "gpio41";
+					function = "wcss_wlan1";
+				};
+				wcss_wlan0 {
+					pins = "gpio42";
+					function = "wcss_wlan0";
+				};
+				wcss_wlan {
+					pins = "gpio43", "gpio44";
+					function = "wcss_wlan";
+				};
+
+				config {
+					pins = "gpio40", "gpio41",
+						"gpio42", "gpio43",
+						"gpio44";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* PULL Down */
+				};
+			};
+		};
+
+		wcnss_pmux_gpio: wcnss_pmux_gpio {
+			wcnss_gpio_default: wcnss_gpio_default {
+				mux {
+					pins = "gpio40", "gpio41",
+						"gpio42", "gpio43",
+						"gpio44";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio40", "gpio41",
+						"gpio42", "gpio43",
+						"gpio44";
+					drive-strength = <6>; /* 6 MA */
+					bias-pull-up; /* PULL UP */
+				};
+			};
+		};
+
+		trigout_a0: trigout_a0 {
+			mux {
+				pins = "gpio23";
+				function  = "qdss_cti_trig_out_a0";
+			};
+
+			config {
+				pins = "gpio23";
+				drive-strength = <2>;
+				bias-disable;
+			};
+		};
+
+		pmx_qdsd_clk {
+			qdsd_clk_sdcard: clk_sdcard {
+				config {
+					pins = "qdsd_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <7>; /* 7 MA */
+				};
+			};
+			qdsd_clk_trace: clk_trace {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_clk_swdtrc: clk_swdtrc {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_clk_spmi: clk_spmi {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_cmd {
+			qdsd_cmd_sdcard: cmd_sdcard {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_cmd_trace: cmd_trace {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_cmd_swduart: cmd_uart {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_cmd_swdtrc: cmd_swdtrc {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_cmd_jtag: cmd_jtag {
+				config {
+					pins = "qdsd_cmd";
+					bias-disable; /* NO pull */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_cmd_spmi: cmd_spmi {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <4>; /* 4 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data0 {
+			qdsd_data0_sdcard: data0_sdcard {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data0_trace: data0_trace {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data0_swduart: data0_uart {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data0_swdtrc: data0_swdtrc {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data0_jtag: data0_jtag {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-up; /* pull up */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data0_spmi: data0_spmi {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data1 {
+			qdsd_data1_sdcard: data1_sdcard {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data1_trace: data1_trace {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data1_swduart: data1_uart {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data1_swdtrc: data1_swdtrc {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data1_jtag: data1_jtag {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data2 {
+			qdsd_data2_sdcard: data2_sdcard {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data2_trace: data2_trace {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data2_swduart: data2_uart {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data2_swdtrc: data2_swdtrc {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data2_jtag: data2_jtag {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-up; /* pull up */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data3 {
+			qdsd_data3_sdcard: data3_sdcard {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data3_trace: data3_trace {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+			qdsd_data3_swduart: data3_uart {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data3_swdtrc: data3_swdtrc {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data3_jtag: data3_jtag {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <0>; /* 0 MA */
+				};
+			};
+			qdsd_data3_spmi: data3_spmi {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <3>; /* 3 MA */
+				};
+			};
+		};
+
+		/* CoreSight */
+		tpiu_seta_1 {
+			seta_1: seta {
+				mux {
+					pins = "gpio6";
+					function = "qdss_traceclk_a";
+				};
+				config {
+					pins = "gpio6";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_2 {
+			seta_2: seta {
+				mux {
+					pins = "gpio8";
+					function = "qdss_tracectl_a";
+				};
+				config {
+					pins = "gpio8";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_3 {
+			seta_3: seta {
+				mux {
+					pins = "gpio9";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio9";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_4 {
+			seta_4: seta {
+				mux {
+					pins = "gpio10";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio10";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_5 {
+			seta_5: seta {
+				mux {
+					pins = "gpio39";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio39";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_6 {
+			seta_6: seta {
+				mux {
+					pins = "gpio40";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio40";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_7 {
+			seta_7: seta {
+				mux {
+					pins = "gpio41";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio41";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_8 {
+			seta_8: seta {
+				mux {
+					pins = "gpio42";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio42";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_9 {
+			seta_9: seta {
+				mux {
+					pins = "gpio43";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio43";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_10 {
+			seta_10: seta {
+				mux {
+					pins = "gpio45";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio45";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_11 {
+			seta_11: seta {
+				mux {
+					pins = "gpio46";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio46";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_12 {
+			seta_12: seta {
+				mux {
+					pins = "gpio47";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio47";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_13 {
+			seta_13: seta {
+				mux {
+					pins = "gpio48";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio48";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_14 {
+			seta_14: seta {
+				mux {
+					pins = "gpio58";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio58";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_15 {
+			seta_15: seta {
+				mux {
+					pins = "gpio65";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio65";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_16 {
+			seta_16: seta {
+				mux {
+					pins = "gpio94";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio94";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_17 {
+			seta_17: seta {
+				mux {
+					pins = "gpio96";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio96";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_seta_18 {
+			seta_18: seta {
+				mux {
+					pins = "gpio97";
+					function = "qdss_tracedata_a";
+				};
+				config {
+					pins = "gpio97";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_1 {
+			setb_1: setb {
+				mux {
+					pins = "gpio4";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio4";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_2 {
+			setb_2: setb {
+				mux {
+					pins = "gpio5";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio5";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_3 {
+			setb_3: setb {
+				mux {
+					pins = "gpio14";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio14";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_4 {
+			setb_4: setb {
+				mux {
+					pins = "gpio16";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio16";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_5 {
+			setb_5: setb {
+				mux {
+					pins = "gpio17";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio17";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_6 {
+			setb_6: setb {
+				mux {
+					pins = "gpio26";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio26";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_7 {
+			setb_7: setb {
+				mux {
+					pins = "gpio27";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio27";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_8 {
+			setb_8: setb {
+				mux {
+					pins = "gpio28";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio28";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_9 {
+			setb_9: setb {
+				mux {
+					pins = "gpio29";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio29";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_10 {
+			setb_10: setb {
+				mux {
+					pins = "gpio30";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio30";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_11 {
+			setb_11: setb {
+				mux {
+					pins = "gpio31";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio31";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_12 {
+			setb_12: setb {
+				mux {
+					pins = "gpio32";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio32";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_13 {
+			setb_13: setb {
+				mux {
+					pins = "gpio33";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio33";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_14 {
+			setb_14: setb {
+				mux {
+					pins = "gpio34";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio34";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_15 {
+			setb_15: setb {
+				mux {
+					pins = "gpio35";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio35";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_16 {
+			setb_16: setb {
+				mux {
+					pins = "gpio36";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio36";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_17 {
+			setb_17: setb {
+				mux {
+					pins = "gpio37";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio37";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		tpiu_setb_18 {
+			setb_18: setb {
+				mux {
+					pins = "gpio93";
+					function = "qdss_tracedata_b";
+				};
+				config {
+					pins = "gpio93";
+					drive-strength = <16>;
+					bias-disable;
+				};
+			};
+		};
+
+		vdd_spkdrv {
+			vdd_spkdrv_act: vdd_spkdrv_on {
+				mux {
+					pins = "gpio4";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio4";
+					drive-strength = <8>;
+				};
+			};
+			vdd_spkdrv_sus: vdd_spkdrv_off {
+				mux {
+					pins = "gpio4";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio4";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		cdc-dmic-lines {
+			cdc_dmic0_clk_act: dmic0_clk_on {
+				mux {
+					pins = "gpio4";
+					function = "dmic0_clk";
+				};
+
+				config {
+					pins = "gpio4";
+					drive-strength = <8>;
+					bias-pull-none;
+				};
+			};
+
+			cdc_dmic0_clk_sus: dmic0_clk_off {
+				mux {
+					pins = "gpio4";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio4";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			cdc_dmic0_data_act: dmic0_data_on {
+				mux {
+					pins = "gpio5";
+					function = "dmic0_data";
+				};
+
+				config {
+					pins = "gpio5";
+					drive-strength = <8>;
+					bias-pull-none;
+				};
+			};
+
+			cdc_dmic0_data_sus: dmic0_data_off {
+				mux {
+					pins = "gpio5";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio5";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		cdc-pdm-lines {
+			cdc_pdm_lines_act: pdm_lines_on {
+				mux {
+					pins = "gpio59", "gpio60", "gpio61",
+						"gpio62", "gpio63", "gpio64";
+					function = "cdc_pdm0";
+				};
+
+				config {
+					pins = "gpio59", "gpio60", "gpio61",
+						"gpio62", "gpio63", "gpio64";
+					drive-strength = <8>;
+				};
+			};
+			cdc_pdm_lines_sus: pdm_lines_off {
+				mux {
+					pins = "gpio59", "gpio60", "gpio61",
+						"gpio62", "gpio63", "gpio64";
+					function = "cdc_pdm0";
+				};
+
+				config {
+					pins = "gpio59", "gpio60", "gpio61",
+						"gpio62", "gpio63", "gpio64";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		cross-conn-det {
+			cross_conn_det_act: lines_on {
+				mux {
+					pins = "gpio97";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio97";
+					drive-strength = <8>;
+					output-low;
+					bias-pull-down;
+				};
+			};
+
+			cross_conn_det_sus: lines_off {
+				mux {
+					pins = "gpio97";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio97";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pmx_i2s_mclk {
+			label = "i2s_mclk";
+			i2s_mclk_active: i2s_mclk_active {
+				mux {
+					pins = "gpio59";
+					function = "pri_mi2s_mclk_a";
+				};
+				config {
+					pins = "gpio59";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+
+			i2s_mclk_sleep: i2s_mclk_sleep {
+				mux {
+					pins = "gpio59";
+					function = "pri_mi2s_mclk_a";
+				};
+				configs {
+					pins = "gpio59";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+		pmx_pri_mi2s {
+			label = "pri_mi2s";
+			pri_mi2s_active: pri_mi2s_active {
+				mux {
+					pins = "gpio60";
+					function = "pri_mi2s_sck_a";
+				};
+				configs {
+					pins = "gpio60";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+					output-high;
+				};
+			};
+			pri_mi2s_sleep: pri_mi2s_sleep {
+				mux {
+					pins = "gpio60";
+					function = "pri_mi2s_sck_a";
+				};
+				configs {
+					pins = "gpio60";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+
+			pri_mi2s_ws_active: pri_mi2s_ws_active {
+				mux {
+					pins = "gpio61";
+					function = "pri_mi2s_ws_a";
+				};
+
+				config {
+					pins = "gpio61";
+					drive-strength = <8>;   /* 8 mA */
+					bias-disable;       /* NO PULL*/
+					output-high;
+				};
+			};
+
+			pri_mi2s_ws_sleep: pri_mi2s_ws_sleep {
+				mux {
+					pins = "gpio61";
+					function = "pri_mi2s_ws_a";
+				};
+
+				config {
+					pins = "gpio61";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;     /* PULL DOWN */
+				};
+			};
+
+			pri_mi2s_dout_active: pri_mi2s_dout_active {
+				mux {
+					pins = "gpio63";
+					function = "pri_mi2s_data1_a";
+				};
+
+				config {
+					pins = "gpio63";
+					drive-strength = <8>;   /* 8 mA */
+					bias-disable;       /* NO PULL*/
+					output-high;
+				};
+			};
+
+			pri_mi2s_dout_sleep: pri_mi2s_dout_sleep {
+				mux {
+					pins = "gpio63";
+					function = "pri_mi2s_data1_a";
+				};
+
+				config {
+					pins = "gpio63";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;     /* PULL DOWN */
+				};
+			};
+
+			pri_mi2s_din_sleep: pri_mi2s_din_sleep {
+				mux {
+					pins = "gpio62";
+					function = "pri_mi2s_data0_a";
+				};
+
+				config {
+					pins = "gpio62";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;     /* PULL DOWN */
+				};
+			};
+
+			pri_mi2s_din_active: pri_mi2s_din_active {
+				mux {
+					pins = "gpio62";
+					function = "pri_mi2s_data0_a";
+				};
+
+				config {
+					pins = "gpio62";
+					drive-strength = <8>;   /* 8 mA */
+					bias-disable;       /* NO PULL */
+				};
+			};
+		};
+
+		pmx_quat_mi2s {
+			label = "quat_mi2s";
+			quat_mi2s_active: quat_mi2s_active {
+				mux {
+					pins = "gpio0", "gpio1";
+					function = "sec_mi2s";
+				};
+				configs {
+					pins = "gpio0", "gpio1";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;           /* No PULL */
+				};
+			};
+			quat_mi2s_sleep: quat_mi2s_sleep {
+				mux {
+					pins = "gpio0", "gpio1";
+					function = "sec_mi2s";
+				};
+				configs {
+					pins = "gpio0", "gpio1";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+		pmx_quat_mi2s_din {
+			label = "quat_mi2s_din";
+			quat_mi2s_din_active: quat_mi2s_din_active {
+				mux {
+					pins = "gpio2", "gpio3";
+					function = "sec_mi2s";
+				};
+				configs {
+					pins = "gpio2", "gpio3";
+					drive-strength = <8>;   /* 8 MA */
+					bias-disable;	        /* No PULL */
+					output-high;
+				};
+			};
+			quat_mi2s_din_sleep: quat_mi2s_din_sleep {
+				mux {
+					pins = "gpio2", "gpio3";
+					function = "sec_mi2s";
+				};
+				configs {
+					pins = "gpio2", "gpio3";
+					drive-strength = <2>;   /* 2 MA */
+					bias-pull-down;	        /* PULL DOWN */
+				};
+			};
+		};
+
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-pm660-pm.dtsi b/arch/arm64/boot/dts/qcom/msm8909-pm660-pm.dtsi
new file mode 100644
index 0000000..dc2e850
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-pm660-pm.dtsi
@@ -0,0 +1,303 @@
+/* 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 <dt-bindings/msm/pm.h>
+
+&soc {
+	qcom,spm@b089000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb089000 0x1000>;
+		qcom,name = "cpu0";
+		qcom,cpu = <&CPU0>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+	};
+
+	qcom,spm@b099000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb099000 0x1000>;
+		qcom,name = "cpu1";
+		qcom,cpu = <&CPU1>;
+		qcom,core-id = <1>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+	};
+
+	qcom,spm@b0a9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb0a9000 0x1000>;
+		qcom,name = "cpu2";
+		qcom,cpu = <&CPU2>;
+		qcom,core-id = <2>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+	};
+
+	qcom,spm@b0b9000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb0b9000 0x1000>;
+		qcom,name = "cpu3";
+		qcom,cpu = <&CPU3>;
+		qcom,core-id = <3>;
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x01>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-wfi";
+			qcom,sequence = [60 03 60 0b 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-spc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [20 10 80 30 90 5b 60 03 60 3b 76 76
+						0b 94 5b 80 10 26 30 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+	};
+
+	qcom,spm@b012000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb012000 0x1000>;
+		qcom,name = "system-l2";
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x14>;
+		qcom,saw2-spm-dly= <0x3c102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,saw2-pmic-data0 = <0x05030080>;
+		qcom,saw2-pmic-data1 = <0x00030000>;
+		qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,vctl-timeout-us = <500>;
+		qcom,vctl-port = <0x0>;
+		qcom,vctl-port-ub = <0x1>;
+		qcom,pfm-port = <0x2>;
+		qcom,mode0 {
+			qcom,label = "qcom,saw2-spm-cmd-ret";
+			qcom,sequence = [00 03 00 0f];
+			qcom,spm_en;
+		};
+		qcom,mode1 {
+			qcom,label = "qcom,saw2-spm-cmd-gdhs";
+			qcom,sequence = [00 20 32 6b c0 e0 d0 42 03 50 4e 02
+					02 d0 e0 c0 22 6b 02 32 50 0f];
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+		qcom,mode2 {
+			qcom,label = "qcom,saw2-spm-cmd-pc";
+			qcom,sequence = [00 20 32 b0 6b c0 e0 d0 42 11 07
+				01 b0 50 4e 02 02 d0 e0 c0 22 6b 02 32 52
+				0f]; /*APC_L2RAM_ON */
+			qcom,spm_en;
+			qcom,pc_mode;
+		};
+	};
+
+	qcom,lpm-levels {
+		compatible = "qcom,lpm-levels";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,pm-cluster@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			label = "system";
+			qcom,spm-device-names = "l2";
+			qcom,default-level = <0>;
+
+			qcom,pm-cluster-level@0 {
+				reg = <0>;
+				label = "l2-cache-active";
+				qcom,spm-l2-mode = "active";
+				qcom,latency-us = <270>;
+				qcom,ss-power = <455>;
+				qcom,energy-overhead = <250621>;
+				qcom,time-overhead = <500>;
+			};
+
+			qcom,pm-cluster-level@1{
+				reg = <1>;
+				label = "l2-gdhs";
+				qcom,spm-l2-mode = "gdhs";
+				qcom,latency-us = <500>;
+				qcom,ss-power = <427>;
+				qcom,energy-overhead = <431578>;
+				qcom,time-overhead = <900>;
+				qcom,min-child-idx = <1>;
+				qcom,reset-level = <LPM_RESET_LVL_GDHS>;
+			};
+
+			qcom,pm-cluster-level@2{
+				reg = <2>;
+				label = "l2-pc";
+				qcom,spm-l2-mode = "pc";
+				qcom,latency-us = <11530>;
+				qcom,ss-power = <400>;
+				qcom,energy-overhead = <800000>;
+				qcom,time-overhead = <2500>;
+				qcom,min-child-idx = <2>;
+				qcom,notify-rpm;
+				qcom,no-cache-flush;
+				qcom,reset-level = <LPM_RESET_LVL_PC>;
+			};
+
+			qcom,pm-cpu {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				qcom,pm-cpu-level@0{
+					reg = <0>;
+					qcom,spm-cpu-mode = "wfi";
+					qcom,latency-us = <1>;
+					qcom,ss-power = <473>;
+					qcom,energy-overhead = <100000>;
+					qcom,time-overhead = <50>;
+				};
+
+				qcom,pm-cpu-level@1 {
+					reg = <1>;
+					qcom,spm-cpu-mode = "standalone_pc";
+					qcom,latency-us = <240>;
+					qcom,ss-power = <467>;
+					qcom,energy-overhead = <202781>;
+					qcom,time-overhead = <420>;
+					qcom,use-broadcast-timer;
+					qcom,reset-level =
+						<LPM_RESET_LVL_PC>;
+				};
+
+				qcom,pm-cpu-level@2 {
+					reg = <2>;
+					qcom,spm-cpu-mode = "pc";
+					qcom,latency-us = <270>;
+					qcom,ss-power = <455>;
+					qcom,energy-overhead = <250621>;
+					qcom,time-overhead = <500>;
+					qcom,use-broadcast-timer;
+					qcom,reset-level =
+						<LPM_RESET_LVL_PC>;
+				};
+			};
+		};
+	};
+
+	qcom,pm@8600664 {
+		compatible = "qcom,pm";
+		reg = <0x8600664 0x40>;
+		clocks = <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk", "cpu1_clk",
+			      "cpu2_clk", "cpu3_clk";
+		qcom,pc-mode = "tz_l2_int";
+		qcom,use-sync-timer;
+		qcom,synced-clocks;
+	};
+
+	qcom,rpm-stats@29dba0 {
+		compatible = "qcom,rpm-stats";
+		reg = <0x29dba0 0x1000>;
+		reg-names = "phys_addr_base";
+		qcom,sleep-stats-version = <2>;
+	};
+
+	qcom,rpm-master-stats@60150 {
+		compatible = "qcom,rpm-master-stats";
+		reg = <0x60150 0x2030>;
+		qcom,masters = "APSS", "MPSS", "PRONTO";
+		qcom,master-stats-version = <2>;
+		qcom,master-offset = <4096>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8909-regulator.dtsi
new file mode 100644
index 0000000..7197f88
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-regulator.dtsi
@@ -0,0 +1,280 @@
+/* Copyright (c) 2014-2015, 2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/* RPM controlled regulators */
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		status = "okay";
+		pm8909_s1_corner: regulator-s1-corner {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_s1_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+		pm8909_s1_corner_ao: regulator-s1-corner-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_s1_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+		pm8909_s1_floor_corner: regulator-s1-floor-corner {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_s1_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
+		pm8909_s1_corner_so: regulator-s1-corner-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_s1_corner_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,init-voltage = <1>;
+			qcom,use-voltage-corner;
+		};
+	};
+
+	rpm-regulator-smpa2 {
+		status = "okay";
+		pm8909_s2: regulator-s2 {
+			status = "okay";
+			regulator-min-microvolt = <1850000>;
+			regulator-max-microvolt = <1850000>;
+			qcom,init-voltage = <1850000>;
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+			status = "okay";
+		pm8909_l1: regulator-l1 {
+			status = "okay";
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,init-voltage = <1000000>;
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+			status = "okay";
+		pm8909_l2: regulator-l2 {
+			status = "okay";
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <12000000>;
+		};
+	};
+
+	/* PM8909 L3 VDD_MX supply */
+	rpm-regulator-ldoa3 {
+			status = "okay";
+		pm8909_l3: regulator-l3 {
+			status = "okay";
+			regulator-min-microvolt = <500000>;
+			regulator-max-microvolt = <1350000>;
+		};
+
+		pm8909_l3_corner_ao: regulator-l3-corner-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l3_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+
+		pm8909_l3_corner_so: regulator-l3-corner-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l3_corner_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,init-voltage = <1>;
+			qcom,use-voltage-corner;
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+			status = "okay";
+		pm8909_l4: regulator-l4 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+			status = "okay";
+		pm8909_l5: regulator-l5 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+			status = "okay";
+		pm8909_l6: regulator-l6 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+			status = "okay";
+		pm8909_l7: regulator-l7 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+
+		pm8909_l7_ao: regulator-l7-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l7_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+
+		pm8909_l7_so: regulator-l7-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l7_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-enable = <0>;
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+			status = "okay";
+		pm8909_l8: regulator-l8 {
+			status = "okay";
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2900000>;
+			qcom,init-voltage = <2850000>;
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+			status = "okay";
+		pm8909_l9: regulator-l9 {
+			status = "okay";
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3000000>;
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+			status = "okay";
+		pm8909_l10: regulator-l10 {
+			status = "okay";
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,init-voltage = <1225000>;
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+			status = "okay";
+		pm8909_l11: regulator-l11 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+			status = "okay";
+		pm8909_l12: regulator-l12 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+			status = "okay";
+		pm8909_l13: regulator-l13 {
+			status = "okay";
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,init-voltage = <3075000>;
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+			status = "okay";
+		pm8909_l14: regulator-l14 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+			status = "okay";
+		pm8909_l15: regulator-l15 {
+			status = "okay";
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+			status = "okay";
+		pm8909_l17: regulator-l17 {
+			status = "okay";
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2800000>;
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+			status = "okay";
+		pm8909_l18: regulator-l18 {
+			status = "okay";
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,init-voltage = <2700000>;
+		};
+	};
+};
+
+&soc {
+	spk_vreg: regulator_spk {
+		status = "disabled";
+		compatible = "regulator-fixed";
+		regulator-name = "spk_vreg";
+		startup-delay-us = <0>;
+		enable-active-high;
+		gpio = <&msm_gpio 4 0>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909-smp2p.dtsi b/arch/arm64/boot/dts/qcom/msm8909-smp2p.dtsi
new file mode 100644
index 0000000..fe5d707
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909-smp2p.dtsi
@@ -0,0 +1,164 @@
+/* Copyright (c) 2014-2015,2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	qcom,smp2p-modem {
+		compatible = "qcom,smp2p";
+		reg = <0x0b011008 0x4>;
+		qcom,remote-pid = <1>;
+		qcom,irq-bitmask = <0x4000>;
+		interrupts = <0 27 1>;
+	};
+
+	qcom,smp2p-wcnss {
+		compatible = "qcom,smp2p";
+		reg = <0x0b011008 0x4>;
+		qcom,remote-pid = <4>;
+		qcom,irq-bitmask = <0x40000>;
+		interrupts = <0 143 1>;
+	};
+
+	smp2pgpio_smp2p_15_in: qcom,smp2pgpio-smp2p-15-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <15>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_15_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_15_in";
+		gpios = <&smp2pgpio_smp2p_15_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_15_out: qcom,smp2pgpio-smp2p-15-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <15>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_15_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_15_out";
+		gpios = <&smp2pgpio_smp2p_15_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_in: qcom,smp2pgpio-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_in";
+		gpios = <&smp2pgpio_smp2p_1_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_1_out: qcom,smp2pgpio-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_1_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_1_out";
+		gpios = <&smp2pgpio_smp2p_1_out 0 0>;
+	};
+
+	smp2pgpio_smp2p_4_in: qcom,smp2pgpio-smp2p-4-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_in {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_in";
+		gpios = <&smp2pgpio_smp2p_4_in 0 0>;
+	};
+
+	smp2pgpio_smp2p_4_out: qcom,smp2pgpio-smp2p-4-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "smp2p";
+		qcom,remote-pid = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	qcom,smp2pgpio_test_smp2p_4_out {
+		compatible = "qcom,smp2pgpio_test_smp2p_4_out";
+		gpios = <&smp2pgpio_smp2p_4_out 0 0>;
+	};
+
+	smp2pgpio_ssr_smp2p_4_in: qcom,smp2pgpio-ssr-smp2p-4-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "slave-kernel";
+		qcom,remote-pid = <4>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	smp2pgpio_ssr_smp2p_4_out: qcom,smp2pgpio-ssr-smp2p-4-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "master-kernel";
+		qcom,remote-pid = <4>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	smp2pgpio_ssr_smp2p_1_in: qcom,smp2pgpio-ssr-smp2p-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "slave-kernel";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+
+	smp2pgpio_ssr_smp2p_1_out: qcom,smp2pgpio-ssr-smp2p-1-out {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "master-kernel";
+		qcom,remote-pid = <1>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909.dtsi b/arch/arm64/boot/dts/qcom/msm8909.dtsi
new file mode 100644
index 0000000..1d30819
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909.dtsi
@@ -0,0 +1,1883 @@
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "skeleton64.dtsi"
+#include <dt-bindings/clock/msm-clocks-8909.h>
+#include <dt-bindings/clock/msm-clocks-a7.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8909";
+	compatible = "qcom,msm8909";
+	qcom,msm-id =	<245 0>,
+			<258 0>,
+			<265 0>,
+			<275 0>;
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs = "sched_enable_hmp=1";
+	};
+
+	aliases {
+		/* smdtty devices */
+		smd1 = &smdtty_apps_fm;
+		smd2 = &smdtty_apps_riva_bt_acl;
+		smd3 = &smdtty_apps_riva_bt_cmd;
+		smd5 = &smdtty_apps_riva_ant_cmd;
+		smd6 = &smdtty_apps_riva_ant_data;
+		smd7 = &smdtty_data1;
+		smd8 = &smdtty_data4;
+		smd11 = &smdtty_data11;
+		smd21 = &smdtty_data21;
+		smd36 = &smdtty_loopback;
+
+		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+		sdhc2 = &sdhc_2; /* SDC2 SD card slot */
+		spi0 = &spi_0; /* SPI0 controller device */
+		spi2 = &spi_2;
+		spi4 = &spi_4;
+		i2c5 = &i2c_5; /* I2c5 cntroller device */
+		i2c3 = &i2c_3; /* I2C3 controller */
+		i2c1 = &i2c_1; /* I2C1 controller */
+		i2c2 = &i2c_2; /* I2C2 NFC qup2 device */
+		i2c4 = &i2c_4; /* I2C4 controller device */
+		qpic_nand1 = &qnand_1; /* qpic nand controller */
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu-map {
+			cluster0 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+				core1 {
+					cpu = <&CPU1>;
+				};
+				core2 {
+					cpu = <&CPU2>;
+				};
+				core3 {
+					cpu = <&CPU3>;
+				};
+			};
+		};
+
+		CPU0: cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x0>;
+			qcom,sleep-status = <&cpu0_slp_sts>;
+			qcom,limits-info = <&mitigation_profile0>;
+		};
+
+		CPU1: cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x1>;
+			qcom,sleep-status = <&cpu1_slp_sts>;
+			qcom,limits-info = <&mitigation_profile2>;
+		};
+
+		CPU2: cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x2>;
+			qcom,sleep-status = <&cpu2_slp_sts>;
+			qcom,limits-info = <&mitigation_profile1>;
+		};
+
+		CPU3: cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a7";
+			reg = <0x3>;
+			qcom,sleep-status = <&cpu3_slp_sts>;
+			qcom,limits-info = <&mitigation_profile2>;
+		};
+	};
+
+	firmware: firmware {
+		android {
+			compatible = "android,firmware";
+			fstab {
+				compatible = "android,fstab";
+				vendor_fstab: vendor {
+					compatible = "android,vendor";
+					dev =
+			"/dev/block/platform/soc/7824900.sdhci/by-name/vendor";
+					type = "ext4";
+					mnt_flags = "ro,barrier=1,discard";
+					fsmgr_flags = "wait,verify";
+					status = "ok";
+				};
+				system_fstab: system {
+					compatible = "android,system";
+					dev =
+			"/dev/block/platform/soc/7824900.sdhci/by-name/system";
+					type = "ext4";
+					mnt_flags = "ro,barrier=1,discard";
+					fsmgr_flags = "wait,verify";
+					status = "ok";
+				};
+			};
+		};
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		external_image_mem: external_image__region@0 {
+			reg = <0x0 0x87a00000 0x0 0x0600000>;
+			compatible = "removed-dma-pool";
+			no-map;
+		};
+
+		modem_adsp_mem: modem_adsp_region@0 {
+			reg = <0x0 0x88000000 0x0 0x05500000>;
+			compatible = "removed-dma-pool";
+			no-map;
+		};
+
+		peripheral_mem: pheripheral_region@0 {
+			reg = <0x0 0x8d500000 0x0 0x0700000>;
+			compatible = "removed-dma-pool";
+			no-map;
+		};
+
+		venus_qseecom_mem: venus_qseecom_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alloc-ranges = <0x0 0x80000000 0x0 0x10000000>;
+			alignment = <0 0x400000>;
+			size = <0 0x0800000>;
+		};
+
+		audio_mem: audio_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x400000>;
+		};
+
+		adsp_mem: adsp_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x400000>;
+		};
+
+		cont_splash_mem: splash_region@83000000 {
+			reg = <0x0 0x83000000 0x0 0xc00000>;
+		};
+	};
+
+	soc: soc { };
+};
+
+#include "msm8909-ion.dtsi"
+#include "msm8909-smp2p.dtsi"
+#include "msm8909-ipcrouter.dtsi"
+#include "msm-gdsc-8916.dtsi"
+#include "msm8909-coresight.dtsi"
+#include "msm8909-bus.dtsi"
+#include "msm8909-mdss.dtsi"
+#include "msm8909-mdss-pll.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0 0 0xffffffff>;
+	compatible = "simple-bus";
+
+	intc: interrupt-controller@b000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x0b000000 0x1000>,
+		<0x0b002000 0x1000>;
+	};
+
+	restart@4ab000 {
+		compatible = "qcom,pshold";
+		reg =	<0x4ab000 0x4>,
+			<0x193d100 0x4>;
+		reg-names = "pshold-base", "tcsr-boot-misc-detect";
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 2 0xf08>,
+			     <1 3 0xf08>,
+			     <1 4 0xf08>,
+			     <1 1 0xf08>;
+		clock-frequency = <19200000>;
+	};
+
+	timer@b020000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xb020000 0x1000>;
+		clock-frequency = <19200000>;
+
+		frame@b021000 {
+			frame-number = <0>;
+			interrupts = <0 8 0x4>,
+				     <0 7 0x4>;
+			reg = <0xb021000 0x1000>,
+			      <0xb022000 0x1000>;
+		};
+		frame@b023000 {
+			frame-number = <1>;
+			interrupts = <0 9 0x4>;
+			reg = <0xb023000 0x1000>;
+			status = "disabled";
+		};
+		frame@b024000 {
+			frame-number = <2>;
+			interrupts = <0 10 0x4>;
+			reg = <0xb024000 0x1000>;
+			status = "disabled";
+		};
+		frame@b025000 {
+			frame-number = <3>;
+			interrupts = <0 11 0x4>;
+			reg = <0xb025000 0x1000>;
+			status = "disabled";
+		};
+		frame@b026000 {
+			frame-number = <4>;
+			interrupts = <0 12 0x4>;
+			reg = <0xb026000 0x1000>;
+			status = "disabled";
+		};
+		frame@b027000 {
+			frame-number = <5>;
+			interrupts = <0 13 0x4>;
+			reg = <0xb027000 0x1000>;
+			status = "disabled";
+		};
+		frame@b028000 {
+			frame-number = <6>;
+			interrupts = <0 14 0x4>;
+			reg = <0xb028000 0x1000>;
+			status = "disabled";
+		};
+	};
+
+	clock_rpm: qcom,rpmcc@1800000 {
+		compatible = "qcom,rpmcc-8909";
+		reg = <0x1800000 0x80000>;
+		reg-names = "cc_base";
+		#clock-cells = <1>;
+	};
+
+	clock_gcc: qcom,gcc@1800000 {
+		compatible = "qcom,gcc-8909";
+		reg = <0x1800000 0x80000>,
+		      <0xb016000 0x00040>;
+		reg-names = "cc_base", "apcs_base";
+		vdd_dig-supply = <&pm8909_s1_corner>;
+		vdd_sr2_dig-supply = <&pm8909_s1_corner_ao>;
+		vdd_sr2_pll-supply = <&pm8909_l7_ao>;
+		clocks = <&clock_rpm clk_xo_clk_src>,
+			<&clock_rpm clk_xo_a_clk_src>;
+		clock-names = "xo", "xo_a";
+		#clock-cells = <1>;
+	};
+
+	clock_gcc_mdss: qcom,gcc-mdss@1ac8300 {
+		compatible = "qcom,gcc-mdss-8909";
+		clocks = <&mdss_dsi0_pll clk_dsi_pll0_pixel_clk_src>,
+			 <&mdss_dsi0_pll clk_dsi_pll0_byte_clk_src>;
+		clock-names = "pixel_src", "byte_src";
+		#clock-cells = <1>;
+	};
+
+	clock_debug: qcom,cc-debug@1874000 {
+		compatible = "qcom,cc-debug-8909";
+		reg = <0x1874000 0x4>,
+			<0xb01101c 0x8>;
+		reg-names = "cc_base", "meas";
+		clocks = <&clock_rpm clk_rpm_debug_mux>;
+		clock-names = "rpm_debug_mux";
+		#clock-cells = <1>;
+	};
+
+	clock_cpu: qcom,clock-a7@0b011050 {
+		compatible = "qcom,clock-a53-8916";
+		reg = <0x0b011050 0x8>,
+		      <0x0005c00c 0x8>;
+		reg-names = "rcg-base", "efuse";
+		qcom,safe-freq = < 400000000 >;
+		cpu-vdd-supply = <&pm8909_s1_corner_ao>;
+		qcom,a7ssmux-opp-store-vcorner = <&CPU0>;
+		clocks = <&clock_gcc clk_gpll0_ao_clk_src>,
+			 <&clock_gcc clk_a7sspll>;
+		clock-names = "clk-4", "clk-5";
+		qcom,speed0-bin-v0 =
+			<          0 0>,
+			<  400000000 4>,
+			<  800000000 5>,
+			< 1267200000 7>;
+		qcom,speed2-bin-v0 =
+			<          0 0>,
+			<  400000000 4>,
+			<  800000000 5>,
+			< 1094400000 7>;
+		#clock-cells = <1>;
+	};
+
+	cpubw: qcom,cpubw {
+		compatible = "qcom,devbw";
+		governor = "cpufreq";
+		qcom,src-dst-ports = <1 512>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			<  762 /* 100 MHz */>,
+			< 1525 /* 200 MHz */>,
+			< 3051 /* 400 MHz */>,
+			< 4066 /* 533 MHz */>;
+	};
+
+	devfreq-cpufreq {
+		cpubw-cpufreq {
+			target-dev = <&cpubw>;
+			cpu-to-dev-map =
+				 <  400000  762>,
+				 <  800000  1525>,
+				 <  998400  3051>,
+				 < 1094400  4066>;
+		};
+	};
+
+	qcom,cpu-bwmon {
+		compatible = "qcom,bimc-bwmon2";
+		reg = <0x408000 0x300>, <0x401000 0x200>;
+		reg-names = "base", "global_base";
+		interrupts = <0 183 4>;
+		qcom,mport = <0>;
+		qcom,target-dev = <&cpubw>;
+	};
+
+	qcom,msm-cpufreq {
+		reg = <0 4>;
+		compatible = "qcom,msm-cpufreq";
+		clocks = <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk", "cpu1_clk",
+				"cpu2_clk", "cpu3_clk";
+		qcom,cpufreq-table =
+			 <  200000 >,
+			 <  400000 >,
+			 <  533330 >,
+			 <  800000 >,
+			 <  998400 >,
+			 < 1094400 >,
+			 < 1190400 >,
+			 < 1248000 >,
+			 < 1267200 >;
+	};
+
+
+	blsp1_uart1: serial@78af000 {
+		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uart";
+		reg = <0x78af000 0x200>;
+		interrupts = <0 107 0>;
+		status = "disabled";
+		clocks = <&clock_gcc clk_gcc_blsp1_uart1_apps_clk>,
+			 <&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		clock-names = "core", "iface";
+	};
+
+	blsp1_uart2_hs: uart@78b0000 {		/*BLSP1 UART2*/
+		compatible = "qcom,msm-hsuart-v14";
+		reg = <0x78b0000 0x200>,
+			<0x7884000 0x1f000>;
+		reg-names = "core_mem", "bam_mem";
+		interrupt-names = "core_irq", "bam_irq", "wakeup_irq";
+		#address-cells = <0>;
+		interrupt-parent = <&blsp1_uart2_hs>;
+		interrupts = <0 1 2>;
+		#interrupt-cells = <1>;
+		interrupt-map-mask = <0xffffffff>;
+		interrupt-map = <0 &intc 0 108 0
+				1 &intc 0 238 0
+				2 &msm_gpio 21 0>;
+		qcom,inject-rx-on-wakeup;
+		qcom,rx-char-to-inject = <0xfd>;
+		qcom,master-id = <86>;
+		clock-names = "core_clk", "iface_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+				<&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		pinctrl-names = "sleep", "default";
+		pinctrl-0 = <&blsp1_uart2_tx_sleep>, <&blsp1_uart2_rxcts_sleep>,
+					<&blsp1_uart2_rfr_sleep>;
+		pinctrl-1 = <&blsp1_uart2_tx_active>,
+			<&blsp1_uart2_rxcts_active>, <&blsp1_uart2_rfr_active>;
+
+		qcom,bam-tx-ep-pipe-index = <2>;
+		qcom,bam-rx-ep-pipe-index = <3>;
+		qcom,msm-bus,name = "blsp1_uart2_hs";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<86 512 0 0>,
+				<86 512 500 800>;
+		status = "disabled";
+	};
+
+	qcom,sps {
+		compatible = "qcom,msm_sps_4k";
+		qcom,device-type = <3>;
+		qcom,pipe-attr-ee;
+	};
+
+	thermal_zones: thermal-zones {};
+
+	qcom,sensor-information {
+		compatible = "qcom,sensor-information";
+		sensor_information0: qcom,sensor-information-0 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor0";
+			qcom,alias-name = "pop_mem";
+		};
+
+		sensor_information1: qcom,sensor-information-1 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor1";
+		};
+
+		sensor_information2: qcom,sensor-information-2 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor2";
+		};
+
+		sensor_information3: qcom,sensor-information-3 {
+			qcom,sensor-type =  "tsens";
+			qcom,sensor-name = "tsens_tz_sensor3";
+		};
+
+		sensor_information4: qcom,sensor-information-4 {
+			qcom,sensor-type = "tsens";
+			qcom,sensor-name = "tsens_tz_sensor4";
+		};
+
+		sensor_information5: qcom,sensor-information-5 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "pa_therm0";
+		};
+
+		sensor_information6: qcom,sensor-information-6 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "case_therm";
+		};
+
+		sensor_information7: qcom,sensor-information-7 {
+			qcom,sensor-type = "alarm";
+			qcom,sensor-name = "pm8909_tz";
+			qcom,scaling-factor = <1000>;
+		};
+
+		sensor_information8: qcom,sensor-information-8 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "xo_therm";
+		};
+
+		sensor_information9: qcom,sensor-information-9 {
+			qcom,sensor-type = "adc";
+			qcom,sensor-name = "xo_therm_buf";
+		};
+	};
+
+	mitigation_profile0: qcom,limit_info-0 {
+		qcom,temperature-sensor = <&sensor_information3>;
+		qcom,boot-frequency-mitigate;
+		qcom,emergency-frequency-mitigate;
+	};
+
+	mitigation_profile1: qcom,limit_info-1 {
+		qcom,temperature-sensor = <&sensor_information3>;
+		qcom,boot-frequency-mitigate;
+		qcom,hotplug-mitigation-enable;
+	};
+
+	mitigation_profile2: qcom,limit_info-2 {
+		qcom,temperature-sensor = <&sensor_information4>;
+		qcom,boot-frequency-mitigate;
+		qcom,hotplug-mitigation-enable;
+	};
+
+	qcom,ipc-spinlock@1905000 {
+		compatible = "qcom,ipc-spinlock-sfpb";
+		reg = <0x1905000 0x8000>;
+		qcom,num-locks = <8>;
+	};
+
+	qcom,smem@87d00000 {
+		compatible = "qcom,smem";
+		reg = <0x87d00000 0x100000>,
+			<0x0b011008 0x4>,
+			<0x60000 0x8000>,
+			<0x193D000 0x8>;
+		reg-names = "smem", "irq-reg-base",
+				"aux-mem1", "smem_targ_info_reg";
+		qcom,mpu-enabled;
+
+		qcom,smd-modem {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <0>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x1000>;
+			interrupts = <0 25 1>;
+			label = "modem";
+			qcom,not-loadable;
+		};
+
+		qcom,smsm-modem {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <0>;
+			qcom,smsm-irq-offset = <0x0>;
+			qcom,smsm-irq-bitmask = <0x2000>;
+			interrupts = <0 26 1>;
+		};
+
+		qcom,smd-wcnss {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <6>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x20000>;
+			interrupts = <0 142 1>;
+			label = "wcnss";
+		};
+
+		qcom,smsm-wcnss {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <6>;
+			qcom,smsm-irq-offset = <0x0>;
+			qcom,smsm-irq-bitmask = <0x80000>;
+			interrupts = <0 144 1>;
+		};
+
+		qcom,smd-rpm {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <15>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x1>;
+			interrupts = <0 168 1>;
+			label = "rpm";
+			qcom,irq-no-suspend;
+			qcom,not-loadable;
+		};
+	};
+
+	rpm_bus: qcom,rpm-smd {
+		compatible = "qcom,rpm-smd";
+		rpm-channel-name = "rpm_requests";
+		rpm-channel-type = <15>; /* SMD_APPS_RPM */
+	};
+
+	qcom,smdtty {
+		compatible = "qcom,smdtty";
+
+		smdtty_apps_fm: qcom,smdtty-apps-fm {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_FM";
+		};
+
+		smdtty_apps_riva_bt_acl: smdtty-apps-riva-bt-acl {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_BT_ACL";
+		};
+
+		smdtty_apps_riva_bt_cmd: qcom,smdtty-apps-riva-bt-cmd {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_BT_CMD";
+		};
+
+		smdtty_apps_riva_ant_cmd: smdtty-apps-riva-ant-cmd {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_ANT_CMD";
+		};
+
+		smdtty_apps_riva_ant_data: smdtty-apps-riva-ant-data {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_ANT_DATA";
+		};
+
+		smdtty_data1: qcom,smdtty-data1 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA1";
+		};
+
+		smdtty_data4: qcom,smdtty-data4 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA4";
+		};
+
+		smdtty_data11: qcom,smdtty-data11 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA11";
+		};
+
+		smdtty_data21: qcom,smdtty-data21 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA21";
+		};
+
+		smdtty_loopback: smdtty-loopback {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "LOOPBACK";
+			qcom,smdtty-dev-name = "LOOPBACK_TTY";
+		};
+	};
+
+	qcom,smdpkt {
+		compatible = "qcom,smdpkt";
+
+		qcom,smdpkt-data5-cntl {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA5_CNTL";
+			qcom,smdpkt-dev-name = "smdcntl0";
+		};
+
+		qcom,smdpkt-data22 {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA22";
+			qcom,smdpkt-dev-name = "smd22";
+		};
+
+		qcom,smdpkt-data40-cntl {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA40_CNTL";
+			qcom,smdpkt-dev-name = "smdcntl8";
+		};
+
+		qcom,smdpkt-apr-apps2 {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "apr_apps2";
+			qcom,smdpkt-dev-name = "apr_apps2";
+		};
+
+		qcom,smdpkt-loopback {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "LOOPBACK";
+			qcom,smdpkt-dev-name = "smd_pkt_loopback";
+		};
+	};
+
+	wcnss: qcom,wcnss-wlan@a000000 {
+		compatible = "qcom,wcnss_wlan";
+		reg = <0x0a000000 0x280000>,
+			<0xb011008 0x04>,
+			<0x0a21b000 0x3000>,
+			<0x03204000 0x00000100>,
+			<0x03200800 0x00000200>,
+			<0x0A100400 0x00000200>,
+			<0x0A205050 0x00000200>,
+			<0x0A219000 0x00000020>,
+			<0x0A080488 0x00000008>,
+			<0x0A080fb0 0x00000008>,
+			<0x0A08040c 0x00000008>,
+			<0x0A0120a8 0x00000008>,
+			<0x0A012448 0x00000008>,
+			<0x0A080c00 0x00000001>,
+			<0x0005E000 0x00000064>;
+
+		reg-names = "wcnss_mmio", "wcnss_fiq",
+			    "pronto_phy_base", "riva_phy_base",
+			    "riva_ccu_base", "pronto_a2xb_base",
+			    "pronto_ccpu_base", "pronto_saw2_base",
+			    "wlan_tx_phy_aborts","wlan_brdg_err_source",
+			    "wlan_tx_status", "alarms_txctl",
+			    "alarms_tactl", "pronto_mcu_base",
+			    "pronto_qfuse";
+
+		interrupts = <0 145 0 0 146 0>;
+		interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+		qcom,pronto-vddmx-supply = <&pm8909_l3_corner_ao>;
+		qcom,pronto-vddcx-supply = <&pm8909_s1_corner>;
+		qcom,pronto-vddpx-supply = <&pm8909_l7>;
+		qcom,iris-vddxo-supply   = <&pm8909_l7>;
+		qcom,iris-vddrfa-supply  = <&pm8909_l10>;
+		qcom,iris-vddpa-supply   = <&pm8909_l9>;
+		qcom,iris-vdddig-supply  = <&pm8909_l5>;
+
+		qcom,iris-vddxo-voltage-level = <1800000 0 1800000>;
+		qcom,iris-vddrfa-voltage-level = <1300000 0 1300000>;
+		qcom,iris-vddpa-voltage-level = <3300000 0 3300000>;
+		qcom,iris-vdddig-voltage-level = <1800000 0 1800000>;
+
+		qcom,vddmx-voltage-level = <5 1 7>;
+		qcom,vddcx-voltage-level = <5 1 7>;
+		qcom,vddpx-voltage-level = <1800000 0 1800000>;
+
+		qcom,iris-vddxo-current = <10000>;
+		qcom,iris-vddrfa-current = <100000>;
+		qcom,iris-vddpa-current = <515000>;
+		qcom,iris-vdddig-current = <10000>;
+
+		qcom,pronto-vddmx-current = <0>;
+		qcom,pronto-vddcx-current = <0>;
+		qcom,pronto-vddpx-current = <0>;
+
+		pinctrl-names = "wcnss_default", "wcnss_sleep",
+						"wcnss_gpio_default";
+		pinctrl-0 = <&wcnss_default>;
+		pinctrl-1 = <&wcnss_sleep>;
+		pinctrl-2 = <&wcnss_gpio_default>;
+
+		gpios = <&msm_gpio 40 0>, <&msm_gpio 41 0>, <&msm_gpio 42 0>,
+					<&msm_gpio 43 0>, <&msm_gpio 44 0>;
+
+		clocks = <&clock_rpm clk_xo_wlan_clk>,
+			 <&clock_rpm clk_rf_clk2>,
+			 <&clock_debug clk_gcc_debug_mux>,
+			 <&clock_gcc clk_wcnss_m_clk>;
+		clock-names = "xo", "rf_clk", "measure", "wcnss_debug";
+
+		qcom,wlan-rx-buff-count = <512>;
+		qcom,has-autodetect-xo;
+		qcom,is-pronto-v3;
+		qcom,is-dual-band-disabled;
+		qcom,is-pronto-vadc;
+		qcom,has-pronto-hw;
+		qcom,wcnss-adc_tm = <&pm8909_adc_tm>;
+	};
+
+	usb_otg: usb@78d9000 {
+		compatible = "qcom,hsusb-otg";
+		reg = <0x78d9000 0x400>, <0x6c000 0x200>;
+		reg-names = "core", "phy_csr";
+
+		interrupts = <0 134 0>,<0 140 0>;
+		interrupt-names = "core_irq", "async_irq";
+
+		hsusb_vdd_dig-supply = <&pm8909_l2>;
+		HSUSB_1p8-supply = <&pm8909_l7>;
+		HSUSB_3p3-supply = <&pm8909_l13>;
+		qcom,vdd-voltage-level = <0 1200000 1200000>;
+
+		qcom,hsusb-otg-phy-init-seq = <0x73 0x80 0xffffffff>;
+		qcom,hsusb-otg-phy-type = <3>; /* SNPS Femto PHY */
+		qcom,hsusb-otg-mode = <1>; /* DEVICE only */
+		qcom,hsusb-otg-otg-control = <2>; /* PMIC */
+		qcom,dp-manual-pullup;
+		qcom,phy-dvdd-always-on;
+		qcom,hsusb-otg-mpm-dpsehv-int = <49>;
+		qcom,hsusb-otg-mpm-dmsehv-int = <58>;
+
+		qcom,msm-bus,name = "usb2";
+		qcom,msm-bus,num-cases = <3>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<87 512 0 0>,
+				<87 512 80000 0>,
+				<87 512 6000  6000>;
+		clocks = <&clock_gcc clk_gcc_usb_hs_ahb_clk>,
+			 <&clock_gcc clk_gcc_usb_hs_system_clk>,
+			 <&clock_gcc clk_gcc_usb2a_phy_sleep_clk>,
+			 <&clock_rpm clk_bimc_usb_a_clk>,
+			 <&clock_rpm clk_snoc_usb_a_clk>,
+			 <&clock_rpm clk_pcnoc_usb_a_clk>,
+			 <&clock_gcc clk_gcc_qusb2_phy_clk>,
+			 <&clock_gcc clk_gcc_usb2_hs_phy_only_clk>,
+			 <&clock_gcc clk_gcc_usb_hs_phy_cfg_ahb_clk>,
+			 <&clock_rpm clk_xo_otg_clk>;
+		clock-names = "iface_clk", "core_clk", "sleep_clk",
+				"bimc_clk", "snoc_clk", "pcnoc_clk",
+				"phy_reset_clk", "phy_por_clk", "phy_csr_clk",
+				"xo";
+		qcom,bus-clk-rate = <400000000 200000000 100000000>;
+		qcom,max-nominal-sysclk-rate = <100000000>;
+		qcom,boost-sysclk-with-streaming;
+	};
+
+	android_usb: android_usb@086000c8 {
+		compatible = "qcom,android-usb";
+		reg = <0x086000c8 0xc8>;
+		qcom,pm-qos-latency = <2 1001 12701>;
+	};
+
+	qcom,usbbam@78c4000 {
+		compatible = "qcom,usb-bam-msm";
+		reg = <0x78c4000 0x15000>;
+		reg-names = "hsusb";
+		interrupts = <0 135 0>;
+		interrupt-names = "hsusb";
+		qcom,bam-type = <1>;
+		qcom,usb-bam-num-pipes = <2>;
+		qcom,usb-bam-fifo-baseaddr = <0x08603800>;
+		qcom,ignore-core-reset-ack;
+		qcom,disable-clk-gating;
+		qcom,reset-bam-on-disconnect;
+
+		qcom,pipe0 {
+			label = "hsusb-qdss-in-0";
+			qcom,usb-bam-mem-type = <2>;
+			qcom,dir = <1>;
+			qcom,pipe-num = <0>;
+			qcom,peer-bam = <0>;
+			qcom,peer-bam-physical-address = <0x884000>;
+			qcom,src-bam-pipe-index = <0>;
+			qcom,dst-bam-pipe-index = <0>;
+			qcom,data-fifo-offset = <0x0>;
+			qcom,data-fifo-size = <0x600>;
+			qcom,descriptor-fifo-offset = <0x600>;
+			qcom,descriptor-fifo-size = <0x200>;
+		};
+	};
+
+	spmi_bus: qcom,spmi@200f000 {
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0x200f000 0x1000>,
+			<0x2400000 0x400000>,
+			<0x2c00000 0x400000>,
+			<0x3800000 0x200000>,
+			<0x200a000 0x2100>;
+		reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+		interrupt-names = "periph_irq";
+		interrupts = <0 190 0>;
+		qcom,ee = <0>;
+		qcom,channel = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		#interrupt-cells = <4>;
+		interrupt-controller;
+		cell-index = <0>;
+	};
+
+	qcom,rmtfs_sharedmem@87c00000 {
+
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x87c00000 0xe0000>;
+		reg-names = "rmtfs";
+		qcom,client-id = <0x00000001>;
+	};
+
+	qcom,dsp_sharedmem@87ce0000 {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x87ce0000 0x10000>;
+		reg-names = "rfsa_dsp";
+		qcom,client-id = <0x011013ec>;
+	};
+
+	qcom,mdm_sharedmem@87cf0000 {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x87cf0000 0x10000>;
+		reg-names = "rfsa_mdm";
+		qcom,client-id = <0x011013ed>;
+	};
+
+	cpu-pmu {
+		compatible = "arm,cortex-a7-pmu";
+		qcom,irq-is-percpu;
+		interrupts = <1 7 0xf00>;
+	};
+
+	jtag_fuse: jtagfuse@5e01c {
+		compatible = "qcom,jtag-fuse-v2";
+		reg = <0x5e01c 0x8>;
+		reg-names = "fuse-base";
+	};
+
+	jtag_mm0: jtagmm@84c000 {
+		compatible = "qcom,jtag-mm";
+		reg = <0x84c000 0x1000>,
+		      <0x840000 0x1000>;
+		reg-names = "etm-base","debug-base";
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+
+		qcom,coresight-jtagmm-cpu = <&CPU0>;
+	};
+
+	jtag_mm1: jtagmm@84d000 {
+		compatible = "qcom,jtag-mm";
+		reg = <0x84d000 0x1000>,
+		      <0x842000 0x1000>;
+		reg-names = "etm-base","debug-base";
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+
+		qcom,coresight-jtagmm-cpu = <&CPU1>;
+	};
+
+	jtag_mm2: jtagmm@84e000 {
+		compatible = "qcom,jtag-mm";
+		reg = <0x84e000 0x1000>,
+		      <0x844000 0x1000>;
+		reg-names = "etm-base","debug-base";
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+
+		qcom,coresight-jtagmm-cpu = <&CPU2>;
+	};
+
+	jtag_mm3: jtagmm@84f000 {
+		compatible = "qcom,jtag-mm";
+		reg = <0x84f000 0x1000>,
+		      <0x846000 0x1000>;
+		reg-names = "etm-base","debug-base";
+
+		clocks = <&clock_rpm clk_qdss_clk>,
+			 <&clock_rpm clk_qdss_a_clk>;
+		clock-names = "core_clk", "core_a_clk";
+
+		qcom,coresight-jtagmm-cpu = <&CPU3>;
+	};
+
+	qnand_1: nand@7980000 {
+		compatible = "qcom,msm-nand";
+		reg = <0x7980000 0x1000>,
+			<0x7984000 0x1a000>,
+			<0x5e02c 0x4>;
+		reg-names = "nand_phys",
+		    "bam_phys", "boot_cfg";
+		qcom,reg-adjustment-offset = <0>;
+		interrupts = <0 132 0>;
+		interrupt-names = "bam_irq";
+
+		qcom,msm-bus,name = "qpic_nand";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<91 512 0 0>,
+		/* Voting for max b/w on PNOC bus for now */
+			<91 512 400000 800000>;
+
+		clock-names = "core_clk";
+		clocks = <&clock_rpm clk_qpic_clk>;
+		status = "disabled";
+	};
+
+	sdhc_1: sdhci@7824000 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0x07824900 0x11c>, <0x07824000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		interrupts = <0 123 0>, <0 138 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		qcom,bus-width = <8>;
+
+		qcom,pm-qos-irq-type = "affine_irq";
+		qcom,pm-qos-irq-latency = <2 250>;
+
+		qcom,msm-bus,name = "sdhc1";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+				<78 512 1046 3200>,    /* 400 KB/s*/
+				<78 512 52286 160000>, /* 20 MB/s */
+				<78 512 65360 200000>, /* 25 MB/s */
+				<78 512 130718 400000>, /* 50 MB/s */
+				<78 512 261438 800000>, /* 100 MB/s */
+				<78 512 261438 800000>, /* 200 MB/s */
+				<78 512 1338562 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
+
+		clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>,
+			 <&clock_gcc clk_gcc_sdcc1_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,clk-rates = <400000 25000000 50000000 100000000 177770000>;
+		qcom,devfreq,freq-table = <50000000 177770000>;
+
+		status = "disabled";
+	};
+
+	sdhc_2: sdhci@07864000 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0x07864900 0x11c>, <0x07864000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		interrupts = <0 125 0>, <0 221 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		qcom,bus-width = <4>;
+
+		qcom,pm-qos-irq-type = "affine_irq";
+		qcom,pm-qos-irq-latency = <2 250>;
+
+		qcom,msm-bus,name = "sdhc2";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+				<81 512 1046 3200>,    /* 400 KB/s*/
+				<81 512 52286 160000>, /* 20 MB/s */
+				<81 512 65360 200000>, /* 25 MB/s */
+				<81 512 130718 400000>, /* 50 MB/s */
+				<81 512 261438 800000>, /* 100 MB/s */
+				<81 512 261438 800000>, /* 200 MB/s */
+				<81 512 1338562 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+						100000000 200000000 4294967295>;
+
+		clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>,
+			 <&clock_gcc clk_gcc_sdcc2_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+
+		qcom,clk-rates = <400000 25000000 50000000 100000000 200000000>;
+		qcom,devfreq,freq-table = <50000000 200000000>;
+
+		status = "disabled";
+	};
+
+	qcom,wdt@b017000 {
+		compatible = "qcom,msm-watchdog";
+		reg = <0xb017000 0x1000>;
+		reg-names = "wdt-base";
+		interrupts = <0 3 0>, <0 4 0>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <10000>;
+		qcom,ipi-ping;
+	};
+
+	qcom,msm-rtb {
+		compatible = "qcom,msm-rtb";
+		qcom,rtb-size = <0x100000>; /* 1M EBI1 buffer */
+	};
+
+	qcom,msm-imem@8600000 {
+		compatible = "qcom,msm-imem";
+		reg = <0x08600000 0x1000>; /* Address and size of IMEM */
+		ranges = <0x0 0x08600000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mem_dump_table@10 {
+			compatible = "qcom,msm-imem-mem_dump_table";
+			reg = <0x10 8>;
+		};
+
+		boot_stats@6b0 {
+			compatible = "qcom,msm-imem-boot_stats";
+			reg = <0x6b0 32>;
+		};
+
+		pil@94c {
+			compatible = "qcom,msm-imem-pil";
+			reg = <0x94c 200>;
+		};
+
+		restart_reason@65c {
+			compatible = "qcom,msm-imem-restart_reason";
+			reg = <0x65c 4>;
+		};
+	};
+
+	qcom,mpm2-sleep-counter@4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0x4a3000 0x1000>;
+		clock-frequency = <32768>;
+	};
+
+	spi_0: spi@78ba000 { /* BLSP1 QUP6 */
+		compatible = "qcom,spi-qup-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0x78ba000 0x600>,
+		      <0x7884000 0x23000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 100 0>, <0 238 0>;
+		spi-max-frequency = <19200000>;
+		pinctrl-names = "spi_default", "spi_sleep";
+		pinctrl-0 = <&spi0_default &spi0_cs0_active>;
+		pinctrl-1 = <&spi0_sleep &spi0_cs0_sleep>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+		<&clock_gcc clk_gcc_blsp1_qup6_spi_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,use-pinctrl;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <14>;
+		qcom,bam-producer-pipe-index = <15>;
+		qcom,master-id = <86>;
+	};
+
+	spi_2: spi@78b6000 { /* BLSP1 QUP2 */
+		compatible = "qcom,spi-qup-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0x78b6000 0x600>,
+		      <0x7884000 0x23000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 96 0>, <0 238 0>;
+		spi-max-frequency = <50000000>;
+		pinctrl-names = "spi_default", "spi_sleep";
+		pinctrl-0 = <&spi2_default &spi2_cs0_active>;
+		pinctrl-1 = <&spi2_sleep &spi2_cs0_sleep>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+		<&clock_gcc clk_gcc_blsp1_qup2_spi_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,use-pinctrl;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <6>;
+		qcom,bam-producer-pipe-index = <7>;
+		qcom,master-id = <86>;
+		status = "disabled";
+	};
+
+	spi_4: spi@78B8000{ /* BLSP1 QUP4 */
+		compatible = "qcom,spi-qup-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "spi_physical", "spi_bam_physical";
+		reg = <0x78b8000 0x600>,
+		      <0x7884000 0x23000>;
+		interrupt-names = "spi_irq", "spi_bam_irq";
+		interrupts = <0 98 0>, <0 238 0>;
+		spi-max-frequency = <50000000>;
+		pinctrl-names = "spi_default", "spi_sleep";
+		pinctrl-0 = <&spi4_default &spi4_cs0_active>;
+		pinctrl-1 = <&spi4_sleep &spi4_cs0_sleep>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+		<&clock_gcc clk_gcc_blsp1_qup4_spi_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,infinite-mode = <0>;
+		qcom,use-bam;
+		qcom,use-pinctrl;
+		qcom,ver-reg-exists;
+		qcom,bam-consumer-pipe-index = <10>;
+		qcom,bam-producer-pipe-index = <11>;
+		qcom,master-id = <86>;
+		status = "disabled";
+	};
+
+	dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */
+		#dma-cells = <4>;
+		compatible = "qcom,sps-dma";
+		reg = <0x7884000 0x23000>;
+		interrupts = <0 238 0>;
+		qcom,summing-threshold = <10>;
+	};
+
+	i2c_2: i2c@78b6000 { /* BLSP1 QUP2 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b6000 0x1000>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 96 0>;
+		qcom,clk-freq-out = <400000>;
+		qcom,clk-freq-in  = <19200000>;
+		clock-names = "iface_clk", "core_clk";
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			 <&clock_gcc clk_gcc_blsp1_qup2_i2c_apps_clk>;
+
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_2_active>;
+		pinctrl-1 = <&i2c_2_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		dmas = <&dma_blsp1 6 64 0x20000020 0x20>,
+			<&dma_blsp1 7 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		qcom,master-id = <86>;
+	};
+
+	i2c_4: i2c@78b8000 { /* BLSP1 QUP4 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b8000 0x1000>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 98 0>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			 <&clock_gcc clk_gcc_blsp1_qup4_i2c_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,clk-freq-out = <400000>;
+		qcom,clk-freq-in  = <19200000>;
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_4_active>;
+		pinctrl-1 = <&i2c_4_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		dmas = <&dma_blsp1 10 64 0x20000020 0x20>,
+			<&dma_blsp1 11 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		qcom,master-id = <86>;
+	};
+
+	 i2c_5: i2c@78b9000 { /* BLSP1 QUP5 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b9000 0x1000>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 99 0>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			 <&clock_gcc clk_gcc_blsp1_qup5_i2c_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,clk-freq-out = <100000>;
+		qcom,clk-freq-in  = <19200000>;
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_5_active>;
+		pinctrl-1 = <&i2c_5_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		dmas = <&dma_blsp1 12 64 0x20000020 0x20>,
+		<&dma_blsp1 13 32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		qcom,master-id = <86>;
+};
+
+	i2c_3: i2c@78b7000 { /* BLSP1 QUP3 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b7000 0x1000>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 97 0>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			 <&clock_gcc clk_gcc_blsp1_qup3_i2c_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,clk-freq-out = <100000>;
+		qcom,clk-freq-in  = <19200000>;
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_3_active>;
+		pinctrl-1 = <&i2c_3_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		dmas = <&dma_blsp1 8 64 0x20000020 0x20>,
+			<&dma_blsp1 9  32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		qcom,master-id = <86>;
+	};
+
+	i2c_1: i2c@78b5000 { /* BLSP1 QUP1 */
+		compatible = "qcom,i2c-msm-v2";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		reg-names = "qup_phys_addr";
+		reg = <0x78b5000 0x1000>;
+		interrupt-names = "qup_irq";
+		interrupts = <0 95 0>;
+		clocks = <&clock_gcc clk_gcc_blsp1_ahb_clk>,
+			 <&clock_gcc clk_gcc_blsp1_qup1_i2c_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+		qcom,clk-freq-out = <100000>;
+		qcom,clk-freq-in  = <19200000>;
+		pinctrl-names = "i2c_active", "i2c_sleep";
+		pinctrl-0 = <&i2c_1_active>;
+		pinctrl-1 = <&i2c_1_sleep>;
+		qcom,noise-rjct-scl = <0>;
+		qcom,noise-rjct-sda = <0>;
+		dmas = <&dma_blsp1 4 64 0x20000020 0x20>,
+			<&dma_blsp1 5  32 0x20000020 0x20>;
+		dma-names = "tx", "rx";
+		qcom,master-id = <86>;
+	};
+
+	qcom,venus@1de0000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x1de0000 0x4000>;
+
+		vdd-supply = <&gdsc_venus>;
+		qcom,proxy-reg-names = "vdd";
+
+		clocks = <&clock_gcc clk_gcc_venus0_vcodec0_clk>,
+			 <&clock_gcc clk_gcc_venus0_ahb_clk>,
+			 <&clock_gcc clk_gcc_venus0_axi_clk>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>,
+			 <&clock_gcc clk_crypto_clk_src>;
+
+		clock-names = "core_clk", "iface_clk", "bus_clk",
+				"scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+
+		qcom,proxy-clock-names = "core_clk", "iface_clk",
+					 "bus_clk", "scm_core_clk",
+					 "scm_iface_clk", "scm_bus_clk",
+					 "scm_core_clk_src";
+		qcom,scm_core_clk_src-freq = <80000000>;
+
+		qcom,pas-id = <9>;
+		qcom,proxy-timeout-ms = <100>;
+		qcom,firmware-name = "venus";
+		memory-region = <&venus_qseecom_mem>;
+	};
+
+	pcm0: qcom,msm-pcm {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <0>;
+	};
+
+	routing: qcom,msm-pcm-routing {
+		compatible = "qcom,msm-pcm-routing";
+	};
+
+	pcm1: qcom,msm-pcm-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <1>;
+		qcom,msm-pcm-low-latency;
+		qcom,latency-level = "regular";
+	};
+
+	pcm2: qcom,msm-ultra-low-latency {
+		compatible = "qcom,msm-pcm-dsp";
+		qcom,msm-pcm-dsp-id = <2>;
+		qcom,msm-pcm-low-latency;
+		qcom,latency-level = "ultra";
+	};
+
+	lpa: qcom,msm-pcm-lpa {
+		compatible = "qcom,msm-pcm-lpa";
+	};
+
+	compress: qcom,msm-compress-dsp {
+		compatible = "qcom,msm-compress-dsp";
+	};
+
+	voip: qcom,msm-voip-dsp {
+		compatible = "qcom,msm-voip-dsp";
+	};
+
+	voice: qcom,msm-pcm-voice {
+		compatible = "qcom,msm-pcm-voice";
+		qcom,destroy-cvd;
+		qcom,vote-bms;
+	};
+
+	stub_codec: qcom,msm-stub-codec {
+		compatible = "qcom,msm-stub-codec";
+	};
+
+	qcom,msm-dai-fe {
+		compatible = "qcom,msm-dai-fe";
+	};
+
+	afe: qcom,msm-pcm-afe {
+		compatible = "qcom,msm-pcm-afe";
+	};
+
+	voice_svc: qcom,msm-voice-svc {
+		compatible = "qcom,msm-voice-svc";
+	};
+
+	loopback: qcom,msm-pcm-loopback {
+		compatible = "qcom,msm-pcm-loopback";
+	};
+
+	qcom,msm-dai-mi2s {
+		compatible = "qcom,msm-dai-mi2s";
+		dai_mi2s0: qcom,msm-dai-q6-mi2s-prim {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <0>;
+			qcom,msm-mi2s-rx-lines = <3>;
+			qcom,msm-mi2s-tx-lines = <0>;
+		};
+
+		dai_mi2s1: qcom,msm-dai-q6-mi2s-sec {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <1>;
+			qcom,msm-mi2s-rx-lines = <1>;
+			qcom,msm-mi2s-tx-lines = <0>;
+		};
+
+		dai_mi2s3: qcom,msm-dai-q6-mi2s-quat {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <3>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
+		};
+
+		dai_mi2s5: qcom,msm-dai-q6-mi2s-quin {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <5>;
+			qcom,msm-mi2s-rx-lines = <1>;
+			qcom,msm-mi2s-tx-lines = <2>;
+		};
+
+		dai_mi2s2: qcom,msm-dai-q6-mi2s-tert {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <2>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
+		};
+
+		dai_mi2s6: qcom,msm-dai-q6-mi2s-senary {
+			compatible = "qcom,msm-dai-q6-mi2s";
+			qcom,msm-dai-q6-mi2s-dev-id = <6>;
+			qcom,msm-mi2s-rx-lines = <0>;
+			qcom,msm-mi2s-tx-lines = <3>;
+		};
+	};
+
+	dai_hdmi: qcom,msm-dai-q6-hdmi {
+		compatible = "qcom,msm-dai-q6-hdmi";
+		qcom,msm-dai-q6-dev-id = <8>;
+	};
+
+	lsm: qcom,msm-lsm-client {
+		compatible = "qcom,msm-lsm-client";
+	};
+
+	qcom,msm-dai-q6 {
+		compatible = "qcom,msm-dai-q6";
+		sb_0_rx: qcom,msm-dai-q6-sb-0-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16384>;
+		};
+
+		sb_0_tx: qcom,msm-dai-q6-sb-0-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16385>;
+		};
+
+		sb_1_rx: qcom,msm-dai-q6-sb-1-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16386>;
+		};
+
+		sb_1_tx: qcom,msm-dai-q6-sb-1-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16387>;
+		};
+
+		sb_3_rx: qcom,msm-dai-q6-sb-3-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16390>;
+		};
+
+		sb_3_tx: qcom,msm-dai-q6-sb-3-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16391>;
+		};
+
+		sb_4_rx: qcom,msm-dai-q6-sb-4-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16392>;
+		};
+
+		sb_4_tx: qcom,msm-dai-q6-sb-4-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <16393>;
+		};
+
+		bt_sco_rx: qcom,msm-dai-q6-bt-sco-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12288>;
+		};
+
+		bt_sco_tx: qcom,msm-dai-q6-bt-sco-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12289>;
+		};
+
+		bt_a2dp_rx: qcom,msm-dai-q6-bt-a2dp-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12290>;
+		};
+
+		int_fm_rx: qcom,msm-dai-q6-int-fm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12292>;
+		};
+
+		int_fm_tx: qcom,msm-dai-q6-int-fm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <12293>;
+		};
+
+		afe_pcm_rx: qcom,msm-dai-q6-be-afe-pcm-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <224>;
+		};
+
+		afe_pcm_tx: qcom,msm-dai-q6-be-afe-pcm-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <225>;
+		};
+
+		afe_proxy_rx: qcom,msm-dai-q6-afe-proxy-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <241>;
+		};
+
+		afe_proxy_tx: qcom,msm-dai-q6-afe-proxy-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <240>;
+		};
+
+		afe_loopback_tx: qcom,msm-dai-q6-afe-loopback-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <24577>;
+		};
+
+		incall_record_rx: qcom,msm-dai-q6-incall-record-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32771>;
+		};
+
+		incall_record_tx: qcom,msm-dai-q6-incall-record-tx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32772>;
+		};
+
+		incall_music_rx: qcom,msm-dai-q6-incall-music-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32773>;
+		};
+
+		incall_music_2_rx: qcom,msm-dai-q6-incall-music-2-rx {
+			compatible = "qcom,msm-dai-q6-dev";
+			qcom,msm-dai-q6-dev-id = <32770>;
+		};
+	};
+
+	hostless: qcom,msm-pcm-hostless {
+		compatible = "qcom,msm-pcm-hostless";
+	};
+
+	dai_pri_auxpcm: qcom,msm-pri-auxpcm {
+		compatible = "qcom,msm-auxpcm-dev";
+		qcom,msm-cpudai-auxpcm-mode = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-sync = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-frame = <5>, <4>;
+		qcom,msm-cpudai-auxpcm-quant = <2>, <2>;
+		qcom,msm-cpudai-auxpcm-num-slots = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-slot-mapping = <1>, <1>;
+		qcom,msm-cpudai-auxpcm-data = <0>, <0>;
+		qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>, <2048000>;
+		qcom,msm-auxpcm-interface = "primary";
+	};
+
+	qcom,msm-audio-ion {
+		compatible = "qcom,msm-audio-ion";
+	};
+
+	qcom,mdsprpc-mem {
+		compatible = "qcom,msm-mdsprpc-mem-region";
+		memory-region = <&adsp_mem>;
+	};
+
+	qcom,msm-adsp-loader {
+		compatible = "qcom,adsp-loader";
+		qcom,adsp-state = <0>;
+		qcom,proc-img-to-load = "modem";
+	};
+
+	qcom,avtimer@770600c {
+		compatible = "qcom,avtimer";
+		reg = <0x0770600C 0x4>,
+			<0x07706010 0x4>;
+		reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+		qcom,clk-div = <27>;
+	};
+
+	qcom,memshare {
+		compatible = "qcom,memshare";
+
+		qcom,client_1 {
+			compatible = "qcom,memshare-peripheral";
+			qcom,peripheral-size = <0x200000>;
+			qcom,client-id = <0>;
+			qcom,allocate-boot-time;
+			label = "modem";
+		};
+
+		qcom,client_2 {
+			compatible = "qcom,memshare-peripheral";
+			qcom,peripheral-size = <0x300000>;
+			qcom,client-id = <2>;
+			label = "modem";
+		};
+
+		qcom,client_3 {
+			compatible = "qcom,memshare-peripheral";
+			qcom,peripheral-size = <0>;
+			qcom,client-id = <1>;
+			label = "modem";
+		};
+	};
+
+
+	qcom_tzlog: tz-log@8600720 {
+		compatible = "qcom,tz-log";
+		reg = <0x08600720 0x1000>;
+		status = "disabled";
+	};
+
+	qcom_rng: qrng@22000 {
+		compatible = "qcom,msm-rng";
+		reg = <0x22000 0x200>;
+		qcom,msm-rng-iface-clk;
+		qcom,msm-bus,name = "msm-rng-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<1 618 0 0>,		/* No vote */
+				<1 618 0 800>;		/* 100 MB/s */
+		clocks = <&clock_gcc clk_gcc_prng_ahb_clk>;
+		clock-names = "iface_clk";
+		status = "disabled";
+	};
+
+	qcom_crypto: qcrypto@720000 {
+		compatible = "qcom,qcrypto";
+		reg = <0x720000 0x20000>,
+		      <0x704000 0x20000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <2>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		qcom,clk-mgmt-sus-res;
+		qcom,msm-bus,name = "qcrypto-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<55 512 0 0>,
+				<55 512 393600 800000>; /* 49.2MHz & 100MHz */
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,use-sw-aes-cbc-ecb-ctr-algo;
+		qcom,use-sw-aes-xts-algo;
+		qcom,use-sw-ahash-algo;
+		status = "disabled";
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	qcom_cedev: qcedev@720000 {
+		compatible = "qcom,qcedev";
+		reg = <0x720000 0x20000>,
+		      <0x704000 0x20000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <1>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		qcom,ce-hw-shared;
+		qcom,msm-bus,name = "qcedev-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<55 512 0 0>,
+				<55 512 3936000 393600>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		status = "disabled";
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	qcom_seecom: qseecom@87a00000 {
+		compatible = "qcom,qseecom";
+		reg = <0x87a00000 0x200000>;
+		reg-names = "secapp-region";
+		qcom,disk-encrypt-pipe-pair = <2>;
+		qcom,hlos-ce-hw-instance = <0>;
+		qcom,qsee-ce-hw-instance = <0>;
+		qcom,msm-bus,name = "qseecom-noc";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,support-bus-scaling;
+		qcom,support-fde;
+		qcom,msm-bus,vectors-KBps =
+				<55 512 0 0>,
+				<55 512 0 0>,
+				<55 512 120000 1200000>,
+				<55 512 393600 3936000>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		status = "disabled";
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	qcom,pronto@a21b000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x0a21b000 0x3000>;
+		interrupts = <0 149 1>;
+
+		vdd_pronto_pll-supply = <&pm8909_l7>;
+		proxy-reg-names = "vdd_pronto_pll";
+		vdd_pronto_pll-uV-uA = <1800000 18000>;
+		clocks = <&clock_rpm clk_xo_pil_pronto_clk>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>,
+			 <&clock_gcc clk_crypto_clk_src>;
+
+		clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+		qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+				 "scm_bus_clk", "scm_core_clk_src";
+		qcom,scm_core_clk_src = <80000000>;
+
+		qcom,pas-id = <6>;
+		qcom,proxy-timeout-ms = <10000>;
+		qcom,smem-id = <422>;
+		qcom,sysmon-id = <6>;
+		qcom,ssctl-instance-id = <0x13>;
+		qcom,firmware-name = "wcnss";
+
+		/* GPIO inputs from wcnss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_4_in 3 0>;
+
+		/* GPIO output to wcnss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
+		memory-region = <&peripheral_mem>;
+	};
+
+	qcom,mss@4080000 {
+		compatible = "qcom,pil-q6v55-mss";
+		reg = <0x04080000 0x100>,
+		      <0x0194f000 0x010>,
+		      <0x01950000 0x008>,
+		      <0x01951000 0x008>,
+		      <0x04020000 0x040>,
+		      <0x0183e000 0x004>;
+		reg-names = "qdsp6_base", "halt_q6", "halt_modem", "halt_nc",
+				 "rmb_base", "restart_reg";
+
+		interrupts = <0 24 1>;
+		vdd_cx-supply = <&pm8909_s1_corner>;
+		vdd_cx-voltage = <7>;
+		vdd_mx-supply = <&pm8909_l3_corner_ao>;
+		vdd_mx-uV = <3>;
+		vdd_pll-supply = <&pm8909_l7>;
+		qcom,vdd_pll = <1800000>;
+
+		clocks = <&clock_rpm clk_xo_pil_mss_clk>,
+			 <&clock_gcc clk_gcc_mss_cfg_ahb_clk>,
+			 <&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>,
+			 <&clock_gcc clk_gcc_boot_rom_ahb_clk>;
+		clock-names = "xo", "iface_clk", "bus_clk", "mem_clk";
+		qcom,proxy-clock-names = "xo";
+		qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk";
+
+		qcom,firmware-name = "modem";
+		qcom,pil-self-auth;
+		qcom,sysmon-id = <0>;
+		qcom,ssctl-instance-id = <0x12>;
+
+		/* GPIO inputs from mss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>;
+
+		/* GPIO output to mss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+		memory-region = <&modem_adsp_mem>;
+	};
+
+	mcd {
+		compatible = "qcom,mcd";
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	cpu0_slp_sts: cpu-sleep-status@b088008 {
+		reg = <0xb088008 0x100>;
+		qcom,sleep-status-mask= <0x80000>;
+	};
+
+	cpu1_slp_sts: cpu-sleep-status@b098008 {
+		reg = <0xb098008 0x100>;
+		qcom,sleep-status-mask= <0x80000>;
+	};
+
+	cpu2_slp_sts: cpu-sleep-status@b0a8008 {
+		reg = <0xb0a8008 0x100>;
+		qcom,sleep-status-mask= <0x80000>;
+	};
+
+	cpu3_slp_sts: cpu-sleep-status@b0b8008 {
+		reg = <0xb0b8008 0x100>;
+		qcom,sleep-status-mask= <0x80000>;
+	};
+};
+
+&gdsc_venus {
+	clock-names = "bus_clk", "core_clk";
+	clocks = <&clock_gcc clk_gcc_venus0_axi_clk>,
+		 <&clock_gcc clk_gcc_venus0_vcodec0_clk>;
+	status = "okay";
+};
+
+&gdsc_venus_core0 {
+	qcom,support-hw-trigger;
+	clock-names = "core0_clk";
+	clocks = <&clock_gcc clk_gcc_venus0_core0_vcodec0_clk>;
+	status = "okay";
+};
+
+&gdsc_mdss {
+	clock-names = "core_clk", "bus_clk";
+	clocks = <&clock_gcc clk_gcc_mdss_mdp_clk>,
+		 <&clock_gcc clk_gcc_mdss_axi_clk>;
+	status = "okay";
+};
+
+&gdsc_vfe {
+	clock-names = "core_clk", "bus_clk", "csi_clk";
+	clocks = <&clock_gcc clk_gcc_camss_vfe0_clk>,
+		 <&clock_gcc clk_gcc_camss_vfe_axi_clk>,
+		 <&clock_gcc clk_gcc_camss_csi_vfe0_clk>;
+	status = "okay";
+};
+
+&gdsc_oxili_gx {
+	clock-names = "core_clk";
+	clocks = <&clock_gcc clk_gcc_oxili_gfx3d_clk>;
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
new file mode 100644
index 0000000..945b945
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-memory.dtsi
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&external_image_mem {
+	reg = <0x0 0x87b00000 0x0 0x0500000>;
+};
+
+&modem_adsp_mem {
+	reg = <0x0 0x88000000 0x0 0x05200000>;
+};
+
+&peripheral_mem {
+	reg = <0x0 0x8d200000 0x0 0x0600000>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
new file mode 100644
index 0000000..8bcbe68
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909w-bg-wtp-v2.dts
@@ -0,0 +1,304 @@
+/*
+ * Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8909-mtp.dtsi"
+#include "msm8909w.dtsi"
+#include "msm8909w-bg-memory.dtsi"
+#include "8909w-pm660.dtsi"
+#include "msm8909-audio-bg_codec.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8909W-PM660 BLACKGHOST WTP";
+	compatible = "qcom,msm8909-mtp", "qcom,msm8909", "qcom,mtp";
+	qcom,msm-id =   <245 0>,
+			<258 0>,
+			<275 0>,
+			<300 0>;
+	qcom,board-id = <8 0x10f>;
+	qcom,pmic-id =  <0x0001001b 0x0 0x0 0x0>,
+			<0x0001011b 0x0 0x0 0x0>;
+};
+
+&soc {
+	i2c@78b9000 { /* BLSP1 QUP5 */
+		synaptics@20 {
+			compatible = "synaptics,dsx-i2c";
+			reg = <0x20>;
+			interrupt-parent = <&msm_gpio>;
+			interrupts = <98 0x2008>;
+			vdd_ana-supply = <&pm660_l18>;
+			vcc_i2c-supply = <&pm660_l13>;
+			synaptics,pwr-reg-name = "vdd_ana";
+			synaptics,bus-reg-name = "vcc_i2c";
+			pinctrl-names = "pmx_ts_active", "pmx_ts_suspend",
+							"pmx_ts_release";
+			pinctrl-0 = <&ts_int_active &ts_reset_active>;
+			pinctrl-1 = <&ts_int_suspend &ts_reset_suspend>;
+			pinctrl-2 = <&ts_release>;
+			synaptics,irq-gpio = <&msm_gpio 98 0x2008>;
+			synaptics,irq-on-state = <0>;
+			synaptics,irq-flags = <0x2008>;
+			synaptics,power-delay-ms = <200>;
+			synaptics,reset-delay-ms = <200>;
+			synaptics,max-y-for-2d = <389>;
+			synaptics,wakeup-gestures-en;
+			synaptics,resume-in-workqueue;
+			synaptics,x-flip;
+			synaptics,y-flip;
+			/delete-property/ synaptics,reset-gpio;
+			/delete-property/ synaptics,display-coords;
+			/delete-property/ synaptics,panel-coords;
+			/delete-property/ synaptics,power-down;
+			/delete-property/ synaptics,disable-gpios;
+			/delete-property/ synaptics,is_wake;
+		};
+
+		/delete-node/ it7260@46;
+	};
+
+	qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+	};
+
+	qcom,glink-bgcom-xprt-bg {
+		compatible = "qcom,glink-bgcom-xprt";
+		label = "bg";
+		qcom,qos-config = <&glink_qos_bg>;
+		qcom,ramp-time = <0x10>,
+				     <0x20>,
+				     <0x30>,
+				     <0x40>;
+	};
+
+	glink_qos_bg: qcom,glink-qos-config-bg {
+		compatible = "qcom,glink-qos-config";
+		qcom,flow-info = <0x80 0x0>,
+				 <0x70 0x1>,
+				 <0x60 0x2>,
+				 <0x50 0x3>;
+		qcom,mtu-size = <0x800>;
+		qcom,tput-stats-cycle = <0xa>;
+	};
+
+	qcom,glink_pkt {
+		compatible = "qcom,glinkpkt";
+
+		qcom,glinkpkt-bg-daemon {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "bg-daemon";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_daemon";
+		};
+
+		qcom,glinkpkt-bg-display-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-ctrl";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_ctrl";
+		};
+
+		qcom,glinkpkt-bg-display-data {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "display-data";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_display_data";
+		};
+
+		qcom,glinkpkt-bg-rsb-ctrl {
+			qcom,glinkpkt-transport = "bgcom";
+			qcom,glinkpkt-edge = "bg";
+			qcom,glinkpkt-ch-name = "RSB_CTRL";
+			qcom,glinkpkt-dev-name = "glink_pkt_bg_rsb_ctrl";
+		};
+	};
+
+	spi@78B8000 {  /* BLSP1 QUP4 */
+		status = "ok";
+		qcom,bg-spi {
+			compatible = "qcom,bg-spi";
+			reg = <0>;
+			spi-max-frequency = <16000000>;
+			interrupt-parent = <&msm_gpio>;
+			qcom,irq-gpio = <&msm_gpio 110 1>;
+		};
+	};
+
+	qcom,msm-thermal {
+		vdd-dig-supply = <&pm660_s2_floor_corner>;
+
+		msm_thermal_freq: qcom,vdd-apps-rstr {
+			qcom,vdd-rstr-reg = "vdd-apps";
+			qcom,levels = <1094400>;
+			qcom,freq-req;
+		};
+	};
+
+	qcom,bg-rsb {
+		compatible = "qcom,bg-rsb";
+		vdd-ldo1-supply = <&pm660_l11>;
+		vdd-ldo2-supply = <&pm660_l15>;
+	};
+
+	qcom,bg-daemon {
+		compatible = "qcom,bg-daemon";
+		qcom,bg-reset-gpio = <&pm660_gpios 5 0>;
+	};
+
+	qcom,bcl {
+		compatible = "qcom,bcl";
+		qcom,bcl-enable;
+		qcom,bcl-framework-interface;
+		qcom,bcl-freq-control-list = <&CPU0 &CPU1 &CPU2 &CPU3>;
+		qcom,bcl-hotplug-list = <&CPU2 &CPU3>;
+		qcom,bcl-soc-hotplug-list = <&CPU2 &CPU3>;
+		qcom,ibat-monitor {
+			qcom,low-threshold-uamp = <1000000>;
+			qcom,high-threshold-uamp = <2000000>;
+			qcom,mitigation-freq-khz = <1094400>;
+			qcom,vph-high-threshold-uv = <3500000>;
+			qcom,vph-low-threshold-uv = <3200000>;
+			qcom,soc-low-threshold = <10>;
+			qcom,thermal-handle = <&msm_thermal_freq>;
+		};
+	};
+};
+
+&audio_codec_mtp {
+	status = "disabled";
+};
+
+&audio_codec_bg {
+	status = "ok";
+};
+
+&bg_cdc {
+	status = "ok";
+	vdd-spkr-supply = <&pm660_l11>;
+};
+
+&i2c_1 {
+	status = "okay";
+	nq@28 {
+		compatible = "qcom,nq-nci";
+		reg = <0x28>;
+		qcom,nq-irq = <&msm_gpio 50 0x00>;
+		qcom,nq-ven = <&msm_gpio 36 0x00>;
+		qcom,nq-firm = <&msm_gpio 38 0x00>;
+		qcom,nq-esepwr = <&msm_gpio 49 0x00>;
+		qcom,nq-clkreq = <&pm660_gpios 4 0x00>;
+		qcom,clk-src = "BBCLK3";
+		interrupt-parent = <&msm_gpio>;
+		interrupts = <50 0>;
+		interrupt-names = "nfc_irq";
+		pinctrl-names = "nfc_active","nfc_suspend";
+		pinctrl-0 = <&nfcw_int_active
+			     &nfcw_disable_active
+			     &nfc_clk_default>;
+		pinctrl-1 = <&nfcw_int_suspend &nfcw_disable_suspend>;
+		clock-names = "ref_clk";
+	};
+};
+
+&spi_0 {
+	status = "disabled";
+};
+
+&i2c_3 {
+	status = "disabled";
+};
+
+&i2c_4 {
+	status = "disabled";
+};
+
+&i2c_2 {
+	status = "disabled";
+};
+
+&sdhc_2 {
+	status = "disabled";
+};
+
+&blsp1_uart1 {
+	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_sleep>;
+};
+
+/* Pinctrl dt nodes for interrupt & reset gpio for Synaptics touch controller */
+&ts_int_active {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+	};
+};
+
+&ts_int_suspend {
+	mux {
+		pins = "gpio98";
+	};
+
+	config {
+		pins = "gpio98";
+		/delete-property/ bias-pull-down;
+		bias-disable; /* No PULL */
+	};
+};
+
+&ts_reset_active {
+	mux {
+		pins = "gpio16";
+	};
+
+	config {
+		pins = "gpio16";
+	};
+};
+
+&ts_reset_suspend {
+	mux {
+		pins = "gpio16";
+	};
+
+	config {
+		pins = "gpio16";
+	};
+};
+
+&ts_release {
+	mux {
+		pins = "gpio98", "gpio16";
+	};
+
+	config {
+		pins = "gpio98", "gpio16";
+	};
+};
+
+&spi4_cs0_active {
+	mux {
+		pins = "gpio14";
+		function = "blsp_spi4";
+	};
+	config {
+		pins = "gpio14";
+		drive-strength = <2>;
+		bias-disable; /* No PULL */
+		output-high;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi b/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
new file mode 100644
index 0000000..512b0fb
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909w-pm660-regulator.dtsi
@@ -0,0 +1,411 @@
+/* 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.
+ */
+
+&rpm_bus {
+	/* CX supply */
+	rpm-regulator-smpa2 {
+		status = "okay";
+		pm660_s2_corner: regulator-s2-corner {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s2_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+			status = "okay";
+		};
+
+		pm660_s2_corner_ao: regulator-s2-corner-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s2_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+
+		pm660_s2_floor_corner: regulator-s2-floor-corner {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s2_floor_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-floor-corner;
+			qcom,always-send-voltage;
+		};
+
+		pm660_s2_corner_so: regulator-s2-corner-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s2_corner_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,init-voltage = <1>;
+			qcom,use-voltage-corner;
+		};
+	};
+
+	/* MX supply */
+	rpm-regulator-smpa3 {
+		status = "okay";
+		pm660_s3_corner: regulator-s3-corner {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s3_corner";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+			status = "okay";
+		};
+
+		pm660_s3_corner_ao: regulator-s3-corner-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s3_corner_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,use-voltage-corner;
+		};
+
+		pm660_s3_corner_so: regulator-s3-corner-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s3_corner_so";
+			qcom,set = <2>;
+			regulator-min-microvolt = <1>;
+			regulator-max-microvolt = <7>;
+			qcom,init-voltage = <1>;
+			qcom,use-voltage-corner;
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		status = "okay";
+		pm660_s4: regulator-s4 {
+			regulator-min-microvolt = <2040000>;
+			regulator-max-microvolt = <2040000>;
+			qcom,init-voltage = <2040000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		status = "okay";
+		pm660_s5: regulator-s5 {
+			regulator-min-microvolt = <1350000>;
+			regulator-max-microvolt = <1350000>;
+			qcom,init-voltage = <1350000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa6 {
+		status = "okay";
+		pm660_s6: regulator-s6 {
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,init-voltage = <1225000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		pm660_l1: regulator-l1 {
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,init-voltage = <1000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		pm660_l2: regulator-l2 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		pm660_l3: regulator-l3 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1050000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		pm660_l5: regulator-l5 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		pm660_l6: regulator-l6 {
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,init-voltage = <1300000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		pm660_l7: regulator-l7 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		pm660_l8: regulator-l8 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		pm660_l9: regulator-l9 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm660_l10: regulator-l10 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		status = "okay";
+		pm660_l11: regulator-l11 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		status = "okay";
+		pm660_l12: regulator-l12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+
+		pm660_l12_ao: regulator-l12-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l12_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		status = "okay";
+		pm660_l13: regulator-l13 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		status = "okay";
+		pm660_l14: regulator-l14 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		status = "okay";
+		pm660_l15: regulator-l15 {
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3300000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		status = "okay";
+		pm660_l16: regulator-l16 {
+			regulator-min-microvolt = <3100000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3100000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		status = "okay";
+		pm660_l17: regulator-l17 {
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,init-voltage = <2700000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		status = "okay";
+		pm660_l18: regulator-l18 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <3000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		status = "okay";
+		pm660_l19: regulator-l19 {
+			regulator-min-microvolt = <2900000>;
+			regulator-max-microvolt = <2900000>;
+			qcom,init-voltage = <2900000>;
+			status = "okay";
+		};
+	};
+};
+
+/* SPM controlled regulators */
+&spmi_bus {
+	qcom,pm660@1 {
+		pm660_s1: spm-regulator@1400 {
+			compatible = "qcom,spm-regulator";
+			regulator-name = "pm660_s1";
+			reg = <0x1400 0x100>;
+			regulator-min-microvolt = <1052000>;
+			regulator-max-microvolt = <1352000>;
+		};
+	};
+};
+
+/* CPR controlled regulator */
+&soc {
+	mem_acc_vreg_corner: regulator@1942130 {
+		compatible = "qcom,mem-acc-regulator";
+		reg = <0x1942130 0x4>;
+		reg-names = "acc-sel-l1";
+		regulator-name = "mem_acc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <3>;
+
+		qcom,acc-sel-l1-bit-pos = <0>;
+		qcom,corner-acc-map = <0 1 1>;
+	};
+
+	apc_vreg_corner: regulator@b018000 {
+		compatible = "qcom,cpr-regulator";
+		reg = <0xb018000 0x1000>, <0xb011064 4>, <0x58000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+		interrupts = <0 15 0>;
+		regulator-name = "apc_corner";
+		qcom,cpr-fuse-corners = <3>;
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <9>;
+
+		qcom,cpr-voltage-ceiling = <1052000 1228000 1352000>;
+		qcom,cpr-voltage-floor = <1052000 1052000 1156000>;
+		vdd-apc-supply = <&pm660_s1>;
+
+		qcom,vdd-mx-corner-map = <4 5 7>;
+		qcom,vdd-mx-vmin-method = <4>;
+		vdd-mx-supply = <&pm660_s3_corner_ao>;
+		qcom,vdd-mx-vmax = <7>;
+
+		mem-acc-supply = <&mem_acc_vreg_corner>;
+
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <10>;
+		qcom,cpr-up-threshold = <0>;
+		qcom,cpr-down-threshold = <2>;
+		qcom,cpr-idle-clocks = <15>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <4000>;
+
+		qcom,cpr-fuse-row = <26 0>;
+		qcom,cpr-fuse-target-quot = <42 24 6>;
+		qcom,cpr-fuse-ro-sel = <61 61 54>;
+		qcom,cpr-fuse-bp-cpr-disable = <58>;
+		qcom,cpr-fuse-init-voltage =
+					<26 36 6 0>,
+					<26 18 6 0>,
+					<26 0 6 0>;
+		qcom,cpr-fuse-revision = <26 59 2 0>;
+		qcom,cpr-init-voltage-ref = <1052000 1228000 1352000>;
+		qcom,cpr-init-voltage-step = <10000>;
+		qcom,cpr-corner-map = <1 1 2 2 3 3 3 3 3>;
+		qcom,cpr-init-voltage-as-ceiling;
+		qcom,cpr-corner-frequency-map =
+					<1 200000000>,
+					<2 400000000>,
+					<3 533330000>,
+					<4 800000000>,
+					<5 998400000>,
+					<6 1094400000>,
+					<7 1190400000>,
+					<8 1248000000>,
+					<9 1267200000>;
+		qcom,speed-bin-fuse-sel = <1 34 3 0>;
+		qcom,cpr-speed-bin-max-corners =
+					<0 (-1) 2 4 9>,
+					<2 (-1) 2 4 6>;
+		qcom,cpr-quot-adjust-scaling-factor-max = <1400>;
+	};
+
+	bob_vreg: bob_vreg {
+		compatible = "regulator-fixed";
+		regulator-name = "bob_vreg";
+		startup-delay-us = <400>;
+		enable-active-high;
+		gpio = <&pm660_gpios 12 0>;
+		status = "okay";
+		regulator-boot-on;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8909w.dtsi b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
new file mode 100644
index 0000000..d35407c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8909w.dtsi
@@ -0,0 +1,102 @@
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	chosen {
+		bootargs="sched_enable_hmp=0";
+	};
+};
+
+&soc {
+	/delete-node/ qcom,clock-a7@0b011050;
+	clock_cpu: qcom,clock-a7@0b011050 {
+		compatible = "qcom,clock-a53-8916";
+		reg = <0x0b011050 0x8>,
+		      <0x0005c00c 0x8>;
+		reg-names = "rcg-base", "efuse";
+		qcom,safe-freq = < 400000000 >;
+		cpu-vdd-supply = <&apc_vreg_corner>;
+		clocks = <&clock_gcc clk_gpll0_ao_clk_src>,
+			 <&clock_gcc clk_a7sspll>;
+		clock-names = "clk-4", "clk-5";
+		qcom,a7ssmux-opp-store-vcorner = <&CPU0>;
+		qcom,speed0-bin-v0 =
+			<          0 0>,
+			<  800000000 4>,
+			< 1267200000 9>;
+
+		qcom,speed2-bin-v0 =
+			<          0 0>,
+			<  800000000 4>,
+			< 1094400000 6>;
+		#clock-cells = <1>;
+	};
+
+	/delete-node/ qcom,msm-cpufreq;
+	qcom,msm-cpufreq {
+		reg = <0 4>;
+		compatible = "qcom,msm-cpufreq";
+		clocks = <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>,
+			 <&clock_cpu  clk_a7ssmux>;
+		clock-names = "cpu0_clk", "cpu1_clk",
+				"cpu2_clk", "cpu3_clk";
+		qcom,cpufreq-table =
+			 <  800000 >,
+			 < 1094400 >,
+			 < 1267200 >;
+	};
+
+	/delete-node/ qcom,cpubw;
+	cpubw: qcom,cpubw {
+		compatible = "qcom,devbw";
+		governor = "cpufreq";
+		qcom,src-dst-ports = <1 512>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			<  732 /*  96 MHz */>,
+			< 1464 /* 192 MHz */>,
+			< 2929 /* 384 MHz */>;
+	};
+
+	/delete-node/ devfreq-cpufreq;
+	devfreq-cpufreq {
+		cpubw-cpufreq {
+			target-dev = <&cpubw>;
+			cpu-to-dev-map =
+				 <  800000  1464>,
+				 < 1094400  2929>,
+				 < 1267200  2929>;
+		};
+	};
+};
+
+&qcom_crypto {
+	qcom,msm-bus,vectors-KBps =
+		<55 512 0 0>,
+		<55 512 393600 393600>; /* 49.2MHz & 49.2MHz */
+};
+
+&qcom_cedev {
+	qcom,msm-bus,vectors-KBps =
+		<55 512 0 0>,
+		<55 512 393600 393600>; /* 49.2MHz & 49.2MHz */
+};
+
+&qcom_seecom {
+	qcom,msm-bus,vectors-KBps =
+		<55 512 0 0>,
+		<55 512 0 0>,
+		<55 512 196800 196800>,
+		<55 512 393600 393600>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-cpu.dtsi b/arch/arm64/boot/dts/qcom/msm8917-cpu.dtsi
new file mode 100644
index 0000000..792d5d1
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-cpu.dtsi
@@ -0,0 +1,119 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	psci {
+		compatible = "arm,psci-1.0";
+		method = "smc";
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu-map {
+
+			cluster0 {
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+				core1 {
+					cpu = <&CPU1>;
+				};
+				core2 {
+					cpu = <&CPU2>;
+				};
+				core3 {
+					cpu = <&CPU3>;
+				};
+			};
+		};
+
+		CPU0: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x100>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-level = <2>;
+			      /* A53 L2 dump not supported */
+			      qcom,dump-size = <0x0>;
+			};
+			L1_I_100: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_100: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+		CPU1: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x101>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L1_I_101: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_101: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+		CPU2: cpu@102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x102>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L1_I_102: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_102: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+		CPU3: cpu@103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x103>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L1_I_103: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_103: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-ion.dtsi b/arch/arm64/boot/dts/qcom/msm8917-ion.dtsi
new file mode 100644
index 0000000..823d99d
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-ion.dtsi
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	qcom,ion {
+		compatible = "qcom,msm-ion";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,ion-heap@25 {
+			reg = <25>;
+			qcom,ion-heap-type = "SYSTEM";
+		};
+
+		qcom,ion-heap@8 { /* CP_MM HEAP */
+			reg = <8>;
+			memory-region = <&secure_mem>;
+			qcom,ion-heap-type = "SECURE_DMA";
+		};
+
+		qcom,ion-heap@27 { /* QSEECOM HEAP */
+			reg = <27>;
+			memory-region = <&qseecom_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
new file mode 100644
index 0000000..65bc046
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-mtp.dtsi
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&blsp1_uart2 {
+	status = "ok";
+};
+
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
new file mode 100644
index 0000000..b8516d5
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pinctrl.dtsi
@@ -0,0 +1,1669 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	tlmm: pinctrl@1000000 {
+		compatible = "qcom,msm8917-pinctrl";
+		reg = <0x1000000 0x300000>;
+		interrupts = <0 208 0>;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+
+
+		/* add pingrp for touchscreen */
+		pmx_ts_int_active {
+			ts_int_active: ts_int_active {
+				mux {
+					pins = "gpio65";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio65";
+					drive-strength = <8>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_ts_int_suspend {
+			ts_int_suspend: ts_int_suspend {
+				mux {
+					pins = "gpio65";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio65";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pmx_ts_reset_active {
+			ts_reset_active: ts_reset_active {
+				mux {
+					pins = "gpio64";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio64";
+					drive-strength = <8>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		pmx_ts_reset_suspend {
+			ts_reset_suspend: ts_reset_suspend {
+				mux {
+					pins = "gpio64";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio64";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pmx_ts_release {
+			ts_release: ts_release {
+				mux {
+					pins = "gpio65", "gpio64";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio65", "gpio64";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pmx-uartconsole {
+			uart_console_active: uart_console_active {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "blsp_uart2";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			uart_console_sleep: uart_console_sleep {
+				mux {
+					pins = "gpio4", "gpio5";
+					function = "blsp_uart2";
+				};
+
+				config {
+					pins = "gpio4", "gpio5";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+
+		};
+
+		blsp1_uart1 {
+			blsp1_uart1_active: blsp1_uart1_active {
+				mux {
+					pins = "gpio0", "gpio1",
+						"gpio2", "gpio3";
+					function = "blsp_uart1";
+				};
+
+				config {
+					pins = "gpio0", "gpio1",
+						"gpio2", "gpio3";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			blsp1_uart1_sleep: blsp1_uart1_sleep {
+				mux {
+					pins = "gpio0", "gpio1",
+						"gpio2", "gpio3";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio0", "gpio1",
+						"gpio2", "gpio3";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		wcnss_pmux_5wire {
+			/* Active configuration of bus pins */
+			wcnss_default: wcnss_default {
+				wcss_wlan2 {
+					pins = "gpio76";
+					function = "wcss_wlan2";
+				};
+				wcss_wlan1 {
+					pins = "gpio77";
+					function = "wcss_wlan1";
+				};
+				wcss_wlan0 {
+					pins = "gpio78";
+					function = "wcss_wlan0";
+				};
+				wcss_wlan {
+					pins = "gpio79", "gpio80";
+					function = "wcss_wlan";
+				};
+
+				config {
+					pins = "gpio76", "gpio77",
+					       "gpio78", "gpio79",
+					       "gpio80";
+					drive-strength = <6>; /* 6 MA */
+					bias-pull-up; /* PULL UP */
+				};
+			};
+
+			wcnss_sleep: wcnss_sleep {
+				wcss_wlan2 {
+					pins = "gpio76";
+					function = "wcss_wlan2";
+				};
+				wcss_wlan1 {
+					pins =  "gpio77";
+					function = "wcss_wlan1";
+				};
+				wcss_wlan0 {
+					pins = "gpio78";
+					function = "wcss_wlan0";
+				};
+				wcss_wlan {
+					pins = "gpio79", "gpio80";
+					function = "wcss_wlan";
+				};
+
+				config {
+					pins = "gpio76", "gpio77",
+					       "gpio78", "gpio79",
+					       "gpio80";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* PULL Down */
+				};
+			};
+		};
+
+		wcnss_pmux_gpio: wcnss_pmux_gpio {
+			wcnss_gpio_default: wcnss_gpio_default {
+				/* Active configuration of bus pins */
+				mux {
+					/* Uses general purpose pins */
+					pins = "gpio76", "gpio77",
+					       "gpio78", "gpio79",
+					       "gpio80";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio76", "gpio77",
+					       "gpio78", "gpio79",
+					       "gpio80";
+					drive-strength = <6>; /* 6 MA */
+					bias-pull-up; /* PULL UP */
+				};
+			};
+		};
+
+		pmx_mdss: pmx_mdss {
+			mdss_dsi_active: mdss_dsi_active {
+				mux {
+					pins = "gpio60", "gpio98";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio60", "gpio98";
+					drive-strength = <8>; /* 8 mA */
+					bias-disable = <0>; /* no pull */
+					output-high;
+				};
+			};
+			mdss_dsi_suspend: mdss_dsi_suspend {
+				mux {
+					pins = "gpio60", "gpio98";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio60", "gpio98";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+				};
+			};
+		};
+
+		pmx_mdss_te {
+			mdss_te_active: mdss_te_active {
+				mux {
+					pins = "gpio24";
+					function = "mdp_vsync";
+				};
+
+				config {
+					pins = "gpio24";
+					drive-strength = <2>; /* 8 mA */
+					bias-pull-down; /* pull down*/
+				};
+			};
+			mdss_te_suspend: mdss_te_suspend {
+				mux {
+					pins = "gpio24";
+					function = "mdp_vsync";
+				};
+
+				config {
+					pins = "gpio24";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+				};
+			};
+		};
+
+		pmx_qdsd_clk {
+			qdsd_clk_sdcard: clk_sdcard {
+				config {
+					pins = "qdsd_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <16>; /* 16 MA */
+				};
+			};
+			qdsd_clk_trace: clk_trace {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_clk_swdtrc: clk_swdtrc {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_clk_spmi: clk_spmi {
+				config {
+					pins = "qdsd_clk";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_cmd {
+			qdsd_cmd_sdcard: cmd_sdcard {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_cmd_trace: cmd_trace {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_cmd_swduart: cmd_uart {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_cmd_swdtrc: cmd_swdtrc {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_cmd_jtag: cmd_jtag {
+				config {
+					pins = "qdsd_cmd";
+					bias-disable; /* NO pull */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_cmd_spmi: cmd_spmi {
+				config {
+					pins = "qdsd_cmd";
+					bias-pull-down; /* pull down */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data0 {
+			qdsd_data0_sdcard: data0_sdcard {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data0_trace: data0_trace {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data0_swduart: data0_uart {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data0_swdtrc: data0_swdtrc {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data0_jtag: data0_jtag {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data0_spmi: data0_spmi {
+				config {
+					pins = "qdsd_data0";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		 pmx_qdsd_data1 {
+			qdsd_data1_sdcard: data1_sdcard {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data1_trace: data1_trace {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data1_swduart: data1_uart {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data1_swdtrc: data1_swdtrc {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data1_jtag: data1_jtag {
+				config {
+					pins = "qdsd_data1";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_qdsd_data2 {
+			qdsd_data2_sdcard: data2_sdcard {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data2_trace: data2_trace {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data2_swduart: data2_uart {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data2_swdtrc: data2_swdtrc {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-down; /* pull down */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data2_jtag: data2_jtag {
+				config {
+					pins = "qdsd_data2";
+					bias-pull-up; /* pull up */
+					drive-strength = <8>; /* 8 MA */
+				};
+			 };
+		};
+
+		pmx_qdsd_data3 {
+			qdsd_data3_sdcard: data3_sdcard {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data3_trace: data3_trace {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+			qdsd_data3_swduart: data3_uart {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data3_swdtrc: data3_swdtrc {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data3_jtag: data3_jtag {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+			qdsd_data3_spmi: data3_spmi {
+				config {
+					pins = "qdsd_data3";
+					bias-pull-down; /* pull down */
+					drive-strength = <8>; /* 8 MA */
+				};
+			};
+		};
+
+		pmx_sdc1_rclk {
+			sdc1_rclk_on: sdc1_rclk_on {
+				config {
+					pins = "sdc1_rclk";
+					bias-pull-down; /* pull down */
+				};
+			};
+
+			sdc1_rclk_off: sdc1_rclk_off {
+				config {
+					pins = "sdc1_rclk";
+					bias-pull-down; /* pull down */
+				};
+			};
+		};
+
+		pmx_sdc1_clk {
+			sdc1_clk_on: sdc1_clk_on {
+				config {
+					pins = "sdc1_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <16>; /* 16 MA */
+				};
+			};
+
+			sdc1_clk_off: sdc1_clk_off {
+				config {
+					pins = "sdc1_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc1_cmd {
+			sdc1_cmd_on: sdc1_cmd_on {
+				config {
+					pins = "sdc1_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+
+			sdc1_cmd_off: sdc1_cmd_off {
+				config {
+					pins = "sdc1_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc1_data {
+			sdc1_data_on: sdc1_data_on {
+				config {
+					pins = "sdc1_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+
+			sdc1_data_off: sdc1_data_off {
+				config {
+					pins = "sdc1_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		sdhc2_cd_pin {
+			sdc2_cd_on: cd_on {
+				mux {
+					pins = "gpio67";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio67";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+
+			sdc2_cd_off: cd_off {
+				mux {
+					pins = "gpio67";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio67";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		pmx_sdc2_clk {
+			sdc2_clk_on: sdc2_clk_on {
+				config {
+					pins = "sdc2_clk";
+					drive-strength = <16>; /* 16 MA */
+					bias-disable; /* NO pull */
+				};
+			};
+
+			sdc2_clk_off: sdc2_clk_off {
+				config {
+					pins = "sdc2_clk";
+					bias-disable; /* NO pull */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc2_cmd {
+			sdc2_cmd_on: sdc2_cmd_on {
+				config {
+					pins = "sdc2_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+
+			sdc2_cmd_off: sdc2_cmd_off {
+				config {
+					pins = "sdc2_cmd";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			};
+		};
+
+		pmx_sdc2_data {
+			sdc2_data_on: sdc2_data_on {
+				config {
+					pins = "sdc2_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <10>; /* 10 MA */
+				};
+			};
+
+			sdc2_data_off: sdc2_data_off {
+				config {
+					pins = "sdc2_data";
+					bias-pull-up; /* pull up */
+					drive-strength = <2>; /* 2 MA */
+				};
+			 };
+		};
+
+		sdc2_wlan_gpio {
+			sdc2_wlan_gpio_active: sdc2_wlan_gpio_active {
+				config {
+					pins = "gpio99";
+					output-high;
+					drive-strength = <8>;
+					bias-pull-up;
+				};
+			};
+			sdc2_wlan_gpio_sleep: sdc2_wlan_gpio_sleep {
+				config {
+					pins = "gpio99";
+					output-low;
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		wcd9xxx_intr {
+			wcd_intr_default: wcd_intr_default{
+				mux {
+					pins = "gpio73";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio73";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down; /* pull down */
+					input-enable;
+				};
+			};
+		};
+
+		pri_mi2s_mclk_b_lines {
+			pri_mi2s_mclk_b_default: pri_mi2s_mclk_default {
+				mux {
+					pins = "gpio69";
+					function = "pri_mi2s_mclk_b";
+				};
+				config {
+					pins = "gpio69";
+					drive-strength = <8>;
+					bias-disable;
+					input-enable;
+				};
+			};
+		};
+
+		sec_mi2s_mclk_a_lines {
+			sec_mi2s_mclk_a_active: sec_mi2s_mclk_a_active {
+				mux {
+					pins = "gpio25";
+					function = "sec_mi2s_mclk_a";
+				};
+
+				config {
+					pins = "gpio25";
+					drive-strength = <8>; /* 8 MA */
+					output-high;
+					bias-disable;
+				};
+			};
+
+			sec_mi2s_mclk_a_sleep: sec_mi2s_mclk_a_sleep {
+				mux {
+					pins = "gpio25";
+					function = "sec_mi2s_mclk_a";
+				};
+
+				config {
+					pins = "gpio25";
+					drive-strength = <2>; /* 2 MA */
+					output-low;
+					bias-pull-down;
+				};
+			};
+		};
+
+		cdc_reset_ctrl {
+			cdc_reset_sleep: cdc_reset_sleep {
+				mux {
+					pins = "gpio68";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio68";
+					drive-strength = <16>;
+					bias-disable;
+					output-low;
+				};
+			};
+			cdc_reset_active:cdc_reset_active {
+				mux {
+					pins = "gpio68";
+					function = "gpio";
+				};
+				config {
+					pins = "gpio68";
+					drive-strength = <16>;
+					bias-pull-down;
+					output-high;
+				};
+			};
+		};
+
+		cdc-pdm-2-lines {
+			cdc_pdm_lines_2_act: pdm_lines_2_on {
+				mux {
+					pins = "gpio70", "gpio71", "gpio72";
+					function = "cdc_pdm0";
+				};
+
+				config {
+					pins = "gpio70", "gpio71", "gpio72";
+					drive-strength = <8>;
+				};
+			};
+
+			cdc_pdm_lines_2_sus: pdm_lines_2_off {
+				mux {
+					pins = "gpio70", "gpio71", "gpio72";
+					function = "cdc_pdm0";
+				};
+
+				config {
+					pins = "gpio70", "gpio71", "gpio72";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		cdc-pdm-lines {
+			cdc_pdm_lines_act: pdm_lines_on {
+				mux {
+					pins = "gpio69", "gpio73", "gpio74";
+					function = "cdc_pdm0";
+				};
+
+				config {
+					pins = "gpio69", "gpio73", "gpio74";
+					drive-strength = <8>;
+				};
+			};
+			cdc_pdm_lines_sus: pdm_lines_off {
+				mux {
+					pins = "gpio69", "gpio73", "gpio74";
+					function = "cdc_pdm0";
+				};
+
+				config {
+					pins = "gpio69", "gpio73", "gpio74";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		cross-conn-det {
+			cross_conn_det_act: lines_on {
+				mux {
+					pins = "gpio63";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio63";
+					drive-strength = <8>;
+					output-low;
+					bias-pull-down;
+				};
+			};
+
+			cross_conn_det_sus: lines_off {
+				mux {
+					pins = "gpio63";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio63";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		/* WSA VI sense */
+		wsa-vi {
+			wsa_vi_on: wsa_vi_on {
+				mux {
+					pins = "gpio94", "gpio95";
+					function = "wsa_io";
+				};
+
+				config {
+					pins = "gpio94", "gpio95";
+					drive-strength = <8>; /* 8 MA */
+					bias-disable; /* NO pull */
+				};
+			};
+
+			wsa_vi_off: wsa_vi_off {
+				mux {
+					pins = "gpio94", "gpio95";
+					function = "wsa_io";
+				};
+
+				config {
+					pins = "gpio94", "gpio95";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down;
+				};
+			};
+		};
+
+		/* WSA Reset */
+		wsa_reset {
+			wsa_reset_on: wsa_reset_on {
+				mux {
+					pins = "gpio96";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio96";
+					drive-strength = <2>; /* 2 MA */
+					output-high;
+				};
+			};
+
+			wsa_reset_off: wsa_reset_off {
+				mux {
+					pins = "gpio96";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio96";
+					drive-strength = <2>; /* 2 MA */
+					output-low;
+				};
+			};
+		};
+
+		/* WSA CLK */
+		wsa_clk {
+			wsa_clk_on: wsa_clk_on {
+				mux {
+					pins = "gpio25";
+					function = "pri_mi2s_mclk_a";
+				};
+
+				config {
+					pins = "gpio25";
+					drive-strength = <8>; /* 8 MA */
+					output-high;
+				};
+			};
+
+			wsa_clk_off: wsa_clk_off {
+				mux {
+					pins = "gpio25";
+					function = "pri_mi2s_mclk_a";
+				};
+
+				config {
+					pins = "gpio25";
+					drive-strength = <2>; /* 2 MA */
+					output-low;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pri-tlmm-lines {
+			pri_tlmm_lines_act: pri_tlmm_lines_act {
+				mux {
+					pins = "gpio85", "gpio88";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio85", "gpio88";
+					drive-strength = <8>;
+				};
+			};
+
+			pri_tlmm_lines_sus: pri_tlmm_lines_sus {
+				mux {
+					pins = "gpio85", "gpio88";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio85", "gpio88";
+					drive-strength = <2>;
+					bias-pull-down;
+				};
+			};
+		};
+
+		pri-tlmm-ws-lines {
+			pri_tlmm_ws_act: pri_tlmm_ws_act {
+				mux {
+					pins = "gpio87";
+					function = "pri_mi2s_ws";
+				};
+
+				config {
+					pins = "gpio87";
+					drive-strength = <16>;
+					bias-disable;
+					output-high;
+				};
+			};
+
+			pri_tlmm_ws_sus: pri_tlmm_ws_sus {
+				mux {
+					pins = "gpio87";
+					function = "pri_mi2s_ws";
+				};
+
+				config {
+					pins = "gpio87";
+					drive-strength = <2>;
+					bias-pull-down;
+					input-enable;
+				};
+			};
+		};
+
+		spi3 {
+			spi3_default: spi3_default {
+			/* active state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio8", "gpio9", "gpio11";
+					function = "blsp_spi3";
+				};
+
+				config {
+					pins = "gpio8", "gpio9", "gpio11";
+					drive-strength = <12>; /* 12 MA */
+					bias-disable = <0>; /* No PULL */
+				};
+			};
+
+			spi3_sleep: spi3_sleep {
+				/* suspended state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio8", "gpio9", "gpio11";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio8", "gpio9", "gpio11";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* PULL Down */
+				};
+			};
+
+			spi3_cs0_active: cs0_active {
+				/* CS */
+				mux {
+					pins = "gpio10";
+					function = "blsp_spi3";
+				};
+
+				config {
+					pins = "gpio10";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+
+			spi3_cs0_sleep: cs0_sleep {
+				/* CS */
+				mux {
+					pins = "gpio10";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio10";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+		};
+
+		spi6 {
+			spi6_default: spi6_default {
+				/* active state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio20", "gpio21", "gpio23";
+					function = "blsp_spi6";
+				};
+
+				config {
+					pins = "gpio20", "gpio21", "gpio23";
+					drive-strength = <16>; /* 16 MA */
+					bias-disable = <0>; /* No PULL */
+				};
+			};
+
+			spi6_sleep: spi6_sleep {
+				/* suspended state */
+				mux {
+					/* MOSI, MISO, CLK */
+					pins = "gpio20", "gpio21", "gpio23";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio20", "gpio21", "gpio23";
+					drive-strength = <2>; /* 2 MA */
+					bias-pull-down; /* PULL Down */
+				};
+			};
+
+			spi6_cs0_active: cs0_active {
+				/* CS */
+				mux {
+					pins = "gpio47";
+					function = "blsp6_spi";
+				};
+
+				config {
+					pins = "gpio47";
+					drive-strength = <16>;
+					bias-disable = <0>;
+				};
+			};
+
+			spi6_cs0_sleep: cs0_sleep {
+				/* CS */
+				mux {
+					pins = "gpio47";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio47";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+
+			spi6_cs1_active: cs1_active {
+				/* CS */
+				mux {
+					pins = "gpio22";
+					function = "blsp_spi6";
+				};
+
+				config {
+					pins = "gpio22";
+					drive-strength = <16>;
+					bias-disable = <0>;
+				};
+			};
+
+			spi6_cs1_sleep: cs1_sleep {
+				/* CS */
+				mux {
+					pins = "gpio22";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio22";
+					drive-strength = <2>;
+					bias-disable = <0>;
+				};
+			};
+		};
+
+		i2c_2 {
+			i2c_2_active: i2c_2_active {
+				/* active state */
+				mux {
+					pins = "gpio6", "gpio7";
+					function = "blsp_i2c2";
+				};
+
+				config {
+					pins = "gpio6", "gpio7";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			i2c_2_sleep: i2c_2_sleep {
+				/* suspended state */
+				mux {
+					pins = "gpio6", "gpio7";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio6", "gpio7";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		i2c_3 {
+			i2c_3_active: i2c_3_active {
+				/* active state */
+				mux {
+					pins = "gpio10", "gpio11";
+					function = "blsp_i2c3";
+				};
+
+				config {
+					pins = "gpio10", "gpio11";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			i2c_3_sleep: i2c_3_sleep {
+				/* suspended state */
+				mux {
+					pins = "gpio10", "gpio11";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio10", "gpio11";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		/* IO Expander SX150xq */
+		i2c_4 {
+			i2c_4_active: i2c_4_active {
+				/* active state */
+				mux {
+					pins = "gpio14", "gpio15";
+					function = "blsp_i2c4";
+				};
+
+				config {
+					pins = "gpio14", "gpio15";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			i2c_4_sleep: i2c_4_sleep {
+				/* suspended state */
+				mux {
+					pins = "gpio14", "gpio15";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio14", "gpio15";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		i2c_5 {
+			i2c_5_active: i2c_5_active {
+				/* active state */
+				mux {
+					pins = "gpio18", "gpio19";
+					function = "blsp_i2c5";
+				};
+
+				config {
+					pins = "gpio18", "gpio19";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			i2c_5_sleep: i2c_5_sleep {
+				/* suspended state */
+				mux {
+					pins = "gpio18", "gpio19";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio18", "gpio19";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		i2c_6 {
+			i2c_6_active: i2c_6_active {
+				/* active state */
+				mux {
+					pins = "gpio22", "gpio23";
+					function = "blsp_i2c6";
+				};
+
+				config {
+					pins = "gpio22", "gpio23";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+
+			i2c_6_sleep: i2c_6_sleep {
+				/* suspended state */
+				mux {
+					pins = "gpio22", "gpio23";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio22", "gpio23";
+					drive-strength = <2>;
+					bias-disable;
+				};
+			};
+		};
+
+		pmx_rd_nfc_int {
+			/*qcom,pins = <&gp 17>;*/
+			pins = "gpio17";
+			qcom,pin-func = <0>;
+			qcom,num-grp-pins = <1>;
+			label = "pmx_nfc_int";
+
+			nfc_int_active: active {
+				drive-strength = <6>;
+				bias-pull-up;
+			};
+
+			nfc_int_suspend: suspend {
+				drive-strength = <6>;
+				bias-pull-up;
+			};
+		};
+
+		pmx_nfc_reset {
+			/*qcom,pins = <&gp 16>;*/
+			pins = "gpio16";
+			qcom,pin-func = <0>;
+			qcom,num-grp-pins = <1>;
+			label = "pmx_nfc_disable";
+
+			nfc_disable_active: active {
+				drive-strength = <6>;
+				bias-pull-up;
+			};
+
+			nfc_disable_suspend: suspend {
+				drive-strength = <6>;
+				bias-disable;
+			};
+		};
+
+		tlmm_gpio_key {
+			gpio_key_active: gpio_key_active {
+				mux {
+					pins = "gpio91", "gpio127", "gpio128";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+
+			gpio_key_suspend: gpio_key_suspend {
+				mux {
+					pins = "gpio91", "gpio127", "gpio128";
+					drive-strength = <2>;
+					bias-pull-up;
+				};
+			};
+		};
+
+		tlmm_pmi_flash_led {
+			rear_flash_led_enable: rear_flash_led_enable {
+				mux {
+					pins = "gpio33";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio33";
+					drive-strength = <16>;
+					output-high;
+				};
+			};
+
+			rear_flash_led_disable: rear_flash_led_disable {
+				mux {
+					pins = "gpio33";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio33";
+					drive-strength = <2>;
+					output-low;
+				};
+			};
+
+			front_flash_led_enable: front_flash_led_enable {
+				mux {
+					pins = "gpio50";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio50";
+					drive-strength = <16>;
+					output-high;
+				};
+			};
+
+			front_flash_led_disable: front_flash_led_disable {
+				mux {
+					pins = "gpio50";
+					function = "gpio";
+				};
+
+				config {
+					pins = "gpio50";
+					drive-strength = <2>;
+					output-low;
+				};
+			};
+		};
+
+		usbc_int_default: usbc_int_default {
+			mux {
+				pins = "gpio97", "gpio131";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio97", "gpio131";
+				drive-strength = <2>;
+				bias-pull-up;
+			};
+		};
+
+		pri_mi2s_sck {
+			pri_mi2s_sck_sleep: pri_mi2s_sck_sleep {
+				mux {
+					pins = "gpio85";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio85";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+					input-enable;
+				};
+			};
+
+			pri_mi2s_sck_active: pri_mi2s_sck_active {
+				mux {
+					pins = "gpio85";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio85";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;           /* NO PULL */
+					output-high;
+				};
+			};
+		};
+
+		pri_mi2s_sd0 {
+			pri_mi2s_sd0_sleep: pri_mi2s_sd0_sleep {
+				mux {
+					pins = "gpio88";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio88";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+					input-enable;
+				};
+			};
+
+			pri_mi2s_sd0_active: pri_mi2s_sd0_active {
+				mux {
+					pins = "gpio88";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio88";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;           /* NO PULL */
+				};
+			};
+		};
+
+		pri_mi2s_sd1 {
+			pri_mi2s_sd1_sleep: pri_mi2s_sd1_sleep {
+				mux {
+					pins = "gpio86";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio86";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+					input-enable;
+				};
+			};
+			pri_mi2s_sd1_active: pri_mi2s_sd1_active {
+				mux {
+					pins = "gpio86";
+					function = "pri_mi2s";
+				};
+
+				config {
+					pins = "gpio86";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;           /* NO PULL */
+					output-high;
+				};
+			};
+		};
+		sec_mi2s_ws {
+			sec_mi2s_ws_sleep: sec_mi2s_ws_sleep {
+				mux {
+					pins = "gpio95";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio95";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+			sec_mi2s_ws_active: sec_mi2s_ws_active {
+				mux {
+					pins = "gpio95";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio95";
+					drive-strength = <16>;
+					bias-disable;
+					output-high;
+				};
+			};
+		};
+		sec_mi2s_sck {
+			sec_mi2s_sck_sleep: sec_mi2s_sck_sleep {
+				mux {
+					pins = "gpio94";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio94";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+				};
+			};
+			sec_mi2s_sck_active: sec_mi2s_sck_active {
+				mux {
+					pins = "gpio94";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio94";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;           /* NO PULL */
+					output-high;
+				};
+			};
+		};
+
+		sec_mi2s_sd0 {
+			sec_mi2s_sd0_sleep: sec_mi2s_sd0_sleep {
+				mux {
+					pins = "gpio12";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio12";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+					input-enable;
+				};
+			};
+			sec_mi2s_sd0_active: sec_mi2s_sd0_active {
+				mux {
+					pins = "gpio12";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio12";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;           /* NO PULL */
+					output-high;
+				};
+			};
+		};
+
+		sec_mi2s_sd1 {
+			sec_mi2s_sd1_sleep: sec_mi2s_sd1_sleep {
+				mux {
+					pins = "gpio13";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio13";
+					drive-strength = <2>;   /* 2 mA */
+					bias-pull-down;         /* PULL DOWN */
+					input-enable;
+				};
+			};
+			sec_mi2s_sd1_active: sec_mi2s_sd1_active {
+				mux {
+					pins = "gpio13";
+					function = "sec_mi2s";
+				};
+
+				config {
+					pins = "gpio13";
+					drive-strength = <16>;   /* 16 mA */
+					bias-disable;           /* NO PULL */
+				};
+			};
+		};
+
+		usb_mode_select: usb_mode_select {
+			mux {
+				pins = "gpio130";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio130";
+				drive-strength = <2>;
+				bias-disable;
+				input-enable;
+			};
+		};
+
+		usb2533_hub_reset: usb2533_hub_reset {
+			mux {
+				pins = "gpio100";
+				function = "gpio";
+			};
+
+			config {
+				pins = "gpio100";
+				drive-strength = <2>;
+				output-low;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dts b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dts
new file mode 100644
index 0000000..3fe60a3
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2015-2016, 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8917.dtsi"
+#include "msm8917-pmi8950-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917-PMI8950 MTP";
+	compatible = "qcom,msm8917-mtp", "qcom,msm8917", "qcom,mtp";
+	qcom,board-id= <8 0>;
+	qcom,pmic-id = <0x10019 0x010011 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
new file mode 100644
index 0000000..a78f5fe
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917-pmi8950-mtp.dtsi
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "pmi8950.dtsi"
+#include "msm8917-mtp.dtsi"
+
+&soc {
+	led_flash0: qcom,camera-flash {
+		cell-index = <0>;
+		compatible = "qcom,camera-flash";
+		qcom,flash-type = <1>;
+		qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>;
+		qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>;
+		qcom,switch-source = <&pmi8950_switch>;
+	};
+
+	bluetooth: bt_qca6174 {
+		compatible = "qca,qca6174";
+		qca,bt-reset-gpio = <&tlmm 129 0>; /* BT_EN */
+	};
+};
+
+&vendor{
+	mtp_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "batterydata-itech-3000mah.dtsi"
+		#include "batterydata-ascent-3450mAh.dtsi"
+	};
+};
+
+&pm8937_gpios {
+	gpio@c400 {
+		qcom,mode = <0>;
+		qcom,output-type = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-sel = <0>;
+		qcom,master-en = <1>;
+		status = "okay";
+	};
+};
+
+&pmi8950_fg {
+	qcom,battery-data = <&mtp_batterydata>;
+};
+
+&pmi8950_charger {
+	qcom,battery-data = <&mtp_batterydata>;
+	qcom,chg-led-sw-controls;
+	qcom,chg-led-support;
+	/delete-property/ dpdm-supply;
+};
+
+&labibb {
+	status = "ok";
+	qpnp,qpnp-labibb-mode = "lcd";
+};
+
+&ibb_regulator {
+	qcom,qpnp-ibb-discharge-resistor = <32>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8917.dtsi b/arch/arm64/boot/dts/qcom/msm8917.dtsi
new file mode 100644
index 0000000..c1160ad
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8917.dtsi
@@ -0,0 +1,606 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "skeleton64.dtsi"
+#include <dt-bindings/regulator/qcom,rpm-smd-regulator.h>
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+#include <dt-bindings/spmi/spmi.h>
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8917";
+	compatible = "qcom,msm8917";
+	qcom,msm-id = <303 0x0>, <308 0x0>, <309 0x0>;
+	interrupt-parent = <&intc>;
+
+	chosen {
+		bootargs = "sched_enable_hmp=1";
+	};
+
+	aliases {
+		/* smdtty devices */
+		smd1 = &smdtty_apps_fm;
+		smd2 = &smdtty_apps_riva_bt_acl;
+		smd3 = &smdtty_apps_riva_bt_cmd;
+		smd4 = &smdtty_mbalbridge;
+		smd5 = &smdtty_apps_riva_ant_cmd;
+		smd6 = &smdtty_apps_riva_ant_data;
+		smd7 = &smdtty_data1;
+		smd8 = &smdtty_data4;
+		smd11 = &smdtty_data11;
+		smd21 = &smdtty_data21;
+		smd36 = &smdtty_loopback;
+	};
+
+	reserved-memory {
+		#address-cells = <2>;
+		#size-cells = <2>;
+		ranges;
+
+		other_ext_mem: other_ext_region@0 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0x0 0x85b00000 0x0 0xd00000>;
+		};
+
+		modem_mem: modem_region@0 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0x0 0x86800000 0x0 0x5000000>;
+		};
+
+		adsp_fw_mem: adsp_fw_region@0 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0x0 0x8b800000 0x0 0x1100000>;
+		};
+
+		wcnss_fw_mem: wcnss_fw_region@0 {
+			compatible = "removed-dma-pool";
+			no-map;
+			reg = <0x0 0x8c900000 0x0 0x700000>;
+		};
+
+		venus_mem: venus_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alloc-ranges = <0x0 0x80000000 0x0 0x10000000>;
+			alignment = <0 0x400000>;
+			size = <0 0x0800000>;
+		};
+
+		secure_mem: secure_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x7000000>;
+		};
+
+		qseecom_mem: qseecom_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x1000000>;
+		};
+
+		adsp_mem: adsp_region@0 {
+			compatible = "shared-dma-pool";
+			reusable;
+			alignment = <0 0x400000>;
+			size = <0 0x400000>;
+		};
+
+		cont_splash_mem: splash_region@83000000 {
+			reg = <0x0 0x90000000 0x0 0x1400000>;
+		};
+	};
+
+	soc: soc { };
+
+	vendor: vendor {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0 0 0 0xffffffff>;
+		compatible = "simple-bus";
+	};
+};
+
+#include "msm8917-pinctrl.dtsi"
+#include "msm8917-cpu.dtsi"
+#include "msm8917-ion.dtsi"
+
+&soc {
+	#address-cells = <1>;
+	#size-cells = <1>;
+	ranges = <0 0 0 0xffffffff>;
+	compatible = "simple-bus";
+
+	intc: interrupt-controller@b000000 {
+		compatible = "qcom,msm-qgic2";
+		interrupt-controller;
+		#interrupt-cells = <3>;
+		reg = <0x0b000000 0x1000>,
+		      <0x0b002000 0x1000>;
+	};
+
+	timer {
+		compatible = "arm,armv8-timer";
+		interrupts = <1 2 0xff08>,
+			     <1 3 0xff08>,
+			     <1 4 0xff08>,
+			     <1 1 0xff08>;
+		clock-frequency = <19200000>;
+	};
+
+	qcom,sps {
+		compatible = "qcom,msm_sps_4k";
+		qcom,pipe-attr-ee;
+	};
+
+	timer@b120000 {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges;
+		compatible = "arm,armv7-timer-mem";
+		reg = <0xb120000 0x1000>;
+		clock-frequency = <19200000>;
+
+		frame@b121000 {
+			frame-number = <0>;
+			interrupts = <0 8 0x4>,
+				     <0 7 0x4>;
+			reg = <0xb121000 0x1000>,
+			      <0xb122000 0x1000>;
+		};
+
+		frame@b123000 {
+			frame-number = <1>;
+			interrupts = <0 9 0x4>;
+			reg = <0xb123000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b124000 {
+			frame-number = <2>;
+			interrupts = <0 10 0x4>;
+			reg = <0xb124000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b125000 {
+			frame-number = <3>;
+			interrupts = <0 11 0x4>;
+			reg = <0xb125000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b126000 {
+			frame-number = <4>;
+			interrupts = <0 12 0x4>;
+			reg = <0xb126000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b127000 {
+			frame-number = <5>;
+			interrupts = <0 13 0x4>;
+			reg = <0xb127000 0x1000>;
+			status = "disabled";
+		};
+
+		frame@b128000 {
+			frame-number = <6>;
+			interrupts = <0 14 0x4>;
+			reg = <0xb128000 0x1000>;
+			status = "disabled";
+		};
+	};
+
+	qcom,rmtfs_sharedmem@00000000 {
+		compatible = "qcom,sharedmem-uio";
+		reg = <0x00000000 0x00180000>;
+		reg-names = "rmtfs";
+		qcom,client-id = <0x00000001>;
+	};
+
+	restart@4ab000 {
+		compatible = "qcom,pshold";
+		reg = <0x4ab000 0x4>,
+			<0x193d100 0x4>;
+		reg-names = "pshold-base", "tcsr-boot-misc-detect";
+	};
+
+	qcom,mpm2-sleep-counter@4a3000 {
+		compatible = "qcom,mpm2-sleep-counter";
+		reg = <0x4a3000 0x1000>;
+		clock-frequency = <32768>;
+	};
+
+	cpu-pmu {
+		compatible = "arm,armv8-pmuv3";
+		interrupts = <1 7 0xff00>;
+	};
+
+	slim_msm: slim@c140000{
+		cell-index = <1>;
+		compatible = "qcom,slim-ngd";
+		reg = <0xc140000 0x2c000>,
+		      <0xc104000 0x2a000>;
+		reg-names = "slimbus_physical", "slimbus_bam_physical";
+		interrupts = <0 163 0>, <0 180 0>;
+		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
+		qcom,apps-ch-pipes = <0x600000>;
+		qcom,ea-pc = <0x230>;
+		status = "disabled";
+	};
+
+	blsp1_uart2: serial@78b0000 {
+		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
+		reg = <0x78b0000 0x200>;
+		interrupts = <0 108 0>;
+		status = "disabled";
+	};
+
+	dma_blsp1: qcom,sps-dma@7884000 { /* BLSP1 */
+		#dma-cells = <4>;
+		compatible = "qcom,sps-dma";
+		reg = <0x7884000 0x1f000>;
+		interrupts = <0 238 0>;
+		qcom,summing-threshold = <10>;
+	};
+
+	dma_blsp2: qcom,sps-dma@7ac4000 { /* BLSP2 */
+		#dma-cells = <4>;
+		compatible = "qcom,sps-dma";
+		reg = <0x7ac4000 0x1f000>;
+		interrupts = <0 239 0>;
+		qcom,summing-threshold = <10>;
+	};
+
+	rpm_bus: qcom,rpm-smd {
+		compatible = "qcom,rpm-smd";
+		rpm-channel-name = "rpm_requests";
+		rpm-channel-type = <15>; /* SMD_APPS_RPM */
+	};
+
+	cpubw: qcom,cpubw {
+		compatible = "qcom,devbw";
+		governor = "cpufreq";
+		qcom,src-dst-ports = <1 512>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			<   769 /*  100.8 MHz */ >,
+			<  1611 /*  211.2 MHz */ >,
+			<  2270 /*  297.6 MHz */ >,	/*SVS */
+			<  2929 /*  384   MHz */ >,
+			<  4248 /*  556.8 MHz */ >,	/*SVS+*/
+			<  4541 /*  595.2 MHz */ >,	/*NOM*/
+			<  5126 /*  672   MHz */ >,	/*NOM+*/
+			<  5645 /*  740   MHz */ >;	/*TURBO*/
+	};
+
+	mincpubw: qcom,mincpubw {
+		compatible = "qcom,devbw";
+		governor = "cpufreq";
+		qcom,src-dst-ports = <1 512>;
+		qcom,active-only;
+		qcom,bw-tbl =
+			<   769 /*  100.8 MHz */ >,
+			<  1611 /*  211.2 MHz */ >,
+			<  2270 /*  297.6 MHz */ >,
+			<  2929 /*  384   MHz */ >,
+			<  4248 /*  556.8 MHz */ >,
+			<  4541 /*  595.2 MHz */ >,
+			<  5126 /*  672   MHz */ >,
+			<  5645 /*  740   MHz */ >;
+	};
+
+	qcom,cpu-bwmon {
+		compatible = "qcom,bimc-bwmon2";
+		reg = <0x408000 0x300>, <0x401000 0x200>;
+		reg-names = "base", "global_base";
+		interrupts = <0 183 4>;
+		qcom,mport = <0>;
+		qcom,target-dev = <&cpubw>;
+	};
+
+	qcom,wdt@b017000 {
+		compatible = "qcom,msm-watchdog";
+		reg = <0xb017000 0x1000>;
+		reg-names = "wdt-base";
+		interrupts = <0 3 0>, <0 4 0>;
+		qcom,bark-time = <11000>;
+		qcom,pet-time = <10000>;
+		qcom,ipi-ping;
+		qcom,wakeup-enable;
+	};
+
+	spmi_bus: qcom,spmi@200f000 {
+		compatible = "qcom,spmi-pmic-arb";
+		reg = <0x200f000 0x1000>,
+			<0x2400000 0x800000>,
+			<0x2c00000 0x800000>,
+			<0x3800000 0x200000>,
+			<0x200a000 0x2100>;
+		reg-names = "core", "chnls", "obsrvr", "intr", "cnfg";
+		interrupt-names = "periph_irq";
+		interrupts = <GIC_SPI 190 IRQ_TYPE_NONE>;
+		qcom,ee = <0>;
+		qcom,channel = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+		interrupt-controller;
+		#interrupt-cells = <4>;
+		cell-index = <0>;
+	};
+
+	qcom,msm-rtb {
+		compatible = "qcom,msm-rtb";
+		qcom,rtb-size = <0x100000>; /* 1M EBI1 buffer */
+	};
+
+	qcom,msm-imem@8600000 {
+		compatible = "qcom,msm-imem";
+		reg = <0x08600000 0x1000>; /* Address and size of IMEM */
+		ranges = <0x0 0x08600000 0x1000>;
+		#address-cells = <1>;
+		#size-cells = <1>;
+
+		mem_dump_table@10 {
+			compatible = "qcom,msm-imem-mem_dump_table";
+			reg = <0x10 8>;
+		};
+
+		dload_type@18 {
+			compatible = "qcom,msm-imem-dload-type";
+			reg = <0x18 4>;
+		};
+
+		restart_reason@65c {
+			compatible = "qcom,msm-imem-restart_reason";
+			reg = <0x65c 4>;
+		};
+
+		boot_stats@6b0 {
+			compatible = "qcom,msm-imem-boot_stats";
+			reg = <0x6b0 32>;
+		};
+
+		pil@94c {
+			compatible = "qcom,msm-imem-pil";
+			reg = <0x94c 200>;
+		};
+
+	};
+
+
+	qcom,ipc-spinlock@1905000 {
+		compatible = "qcom,ipc-spinlock-sfpb";
+		reg = <0x1905000 0x8000>;
+		qcom,num-locks = <8>;
+	};
+
+	qcom,smem@86300000 {
+		compatible = "qcom,smem";
+		reg = <0x86300000 0x100000>,
+			<0xb011008 0x4>,
+			<0x60000 0x8000>,
+			<0x193d000 0x8>;
+		reg-names = "smem", "irq-reg-base", "aux-mem1",
+				"smem_targ_info_reg";
+		qcom,mpu-enabled;
+
+		qcom,smd-modem {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <0>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x1000>;
+			interrupts = <0 25 1>;
+			label = "modem";
+			qcom,not-loadable;
+		};
+
+		qcom,smsm-modem {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <0>;
+			qcom,smsm-irq-offset = <0x0>;
+			qcom,smsm-irq-bitmask = <0x2000>;
+			interrupts = <0 26 1>;
+		};
+
+		qcom,smd-wcnss {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <6>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x20000>;
+			interrupts = <0 142 1>;
+			label = "wcnss";
+		};
+
+		qcom,smsm-wcnss {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <6>;
+			qcom,smsm-irq-offset = <0x0>;
+			qcom,smsm-irq-bitmask = <0x80000>;
+			interrupts = <0 144 1>;
+		};
+
+		qcom,smd-adsp {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <1>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x100>;
+			interrupts = <0 289 1>;
+			label = "adsp";
+		};
+
+		qcom,smsm-adsp {
+			compatible = "qcom,smsm";
+			qcom,smsm-edge = <1>;
+			qcom,smsm-irq-offset = <0x0>;
+			qcom,smsm-irq-bitmask = <0x200>;
+			interrupts = <0 290 1>;
+		};
+
+		qcom,smd-rpm {
+			compatible = "qcom,smd";
+			qcom,smd-edge = <15>;
+			qcom,smd-irq-offset = <0x0>;
+			qcom,smd-irq-bitmask = <0x1>;
+			interrupts = <0 168 1>;
+			label = "rpm";
+			qcom,irq-no-suspend;
+			qcom,not-loadable;
+		};
+	};
+
+	qcom,smdtty {
+		compatible = "qcom,smdtty";
+
+		smdtty_apps_fm: qcom,smdtty-apps-fm {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_FM";
+		};
+
+		smdtty_apps_riva_bt_acl: smdtty-apps-riva-bt-acl {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_BT_ACL";
+		};
+
+		smdtty_apps_riva_bt_cmd: qcom,smdtty-apps-riva-bt-cmd {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_BT_CMD";
+		};
+
+		smdtty_mbalbridge: qcom,smdtty-mbalbridge {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "MBALBRIDGE";
+		};
+
+		smdtty_apps_riva_ant_cmd: smdtty-apps-riva-ant-cmd {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_ANT_CMD";
+		};
+
+		smdtty_apps_riva_ant_data: smdtty-apps-riva-ant-data {
+			qcom,smdtty-remote = "wcnss";
+			qcom,smdtty-port-name = "APPS_RIVA_ANT_DATA";
+		};
+
+		smdtty_data1: qcom,smdtty-data1 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA1";
+		};
+
+		smdtty_data4: qcom,smdtty-data4 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA4";
+		};
+
+		smdtty_data11: qcom,smdtty-data11 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA11";
+		};
+
+		smdtty_data21: qcom,smdtty-data21 {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "DATA21";
+		};
+
+		smdtty_loopback: smdtty-loopback {
+			qcom,smdtty-remote = "modem";
+			qcom,smdtty-port-name = "LOOPBACK";
+			qcom,smdtty-dev-name = "LOOPBACK_TTY";
+		};
+	};
+
+	qcom,smdpkt {
+		compatible = "qcom,smdpkt";
+
+		qcom,smdpkt-data5-cntl {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA5_CNTL";
+			qcom,smdpkt-dev-name = "smdcntl0";
+		};
+
+		qcom,smdpkt-data22 {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA22";
+			qcom,smdpkt-dev-name = "smd22";
+		};
+
+		qcom,smdpkt-data40-cntl {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "DATA40_CNTL";
+			qcom,smdpkt-dev-name = "smdcntl8";
+		};
+
+		qcom,smdpkt-apr-apps2 {
+			qcom,smdpkt-remote = "adsp";
+			qcom,smdpkt-port-name = "apr_apps2";
+			qcom,smdpkt-dev-name = "apr_apps2";
+		};
+
+		qcom,smdpkt-loopback {
+			qcom,smdpkt-remote = "modem";
+			qcom,smdpkt-port-name = "LOOPBACK";
+			qcom,smdpkt-dev-name = "smd_pkt_loopback";
+		};
+	};
+
+	qcom_tzlog: tz-log@8600720 {
+		compatible = "qcom,tz-log";
+		reg = <0x08600720 0x2000>;
+	};
+
+	qcom,ipc_router {
+		compatible = "qcom,ipc_router";
+		qcom,node-id = <1>;
+	};
+
+	qcom,ipc_router_modem_xprt {
+		compatible = "qcom,ipc_router_smd_xprt";
+		qcom,ch-name = "IPCRTR";
+		qcom,xprt-remote = "modem";
+		qcom,xprt-linkid = <1>;
+		qcom,xprt-version = <1>;
+		qcom,fragmented-data;
+		qcom,disable-pil-loading;
+	};
+
+	qcom,ipc_router_q6_xprt {
+		compatible = "qcom,ipc_router_smd_xprt";
+		qcom,ch-name = "IPCRTR";
+		qcom,xprt-remote = "adsp";
+		qcom,xprt-linkid = <1>;
+		qcom,xprt-version = <1>;
+		qcom,fragmented-data;
+	};
+
+	qcom,ipc_router_wcnss_xprt {
+		compatible = "qcom,ipc_router_smd_xprt";
+		qcom,ch-name = "IPCRTR";
+		qcom,xprt-remote = "wcnss";
+		qcom,xprt-linkid = <1>;
+		qcom,xprt-version = <1>;
+		qcom,fragmented-data;
+	};
+
+	qcom,adsprpc-mem {
+		compatible = "qcom,msm-adsprpc-mem-region";
+		memory-region = <&adsp_mem>;
+	};
+
+};
+
+#include "pm8937-rpm-regulator.dtsi"
+#include "pm8937.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/msm8937-audio.dtsi b/arch/arm64/boot/dts/qcom/msm8937-audio.dtsi
new file mode 100644
index 0000000..2e4d38e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-audio.dtsi
@@ -0,0 +1,436 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm-audio-lpass.dtsi"
+#include "msm8953-wsa881x.dtsi"
+
+&msm_audio_ion {
+	iommus = <&apps_iommu 0x2001 0x0>;
+	qcom,smmu-sid-mask = /bits/ 64 <0xf>;
+};
+
+&soc {
+	qcom,msm-audio-apr {
+		compatible = "qcom,msm-audio-apr";
+		msm_audio_apr_dummy {
+			compatible = "qcom,msm-audio-apr-dummy";
+		};
+	};
+
+	qcom,avtimer@c0a300c {
+		compatible = "qcom,avtimer";
+		reg = <0x0c0a300c 0x4>,
+			<0x0c0a3010 0x4>;
+		reg-names = "avtimer_lsb_addr", "avtimer_msb_addr";
+		qcom,clk-div = <27>;
+	};
+
+	int_codec: sound {
+		status = "okay";
+		compatible = "qcom,msm8952-audio-codec";
+		qcom,model = "msm8952-snd-card-mtp";
+		reg = <0xc051000 0x4>,
+			<0xc051004 0x4>,
+			<0xc055000 0x4>,
+			<0xc052000 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			"csr_gp_io_mux_spkr_ctl",
+			"csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+			"csr_gp_io_mux_quin_ctl";
+
+		qcom,msm-ext-pa = "primary";
+		qcom,msm-mclk-freq = <9600000>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,msm-hs-micbias-type = "external";
+		qcom,msm-micbias1-ext-cap;
+
+		qcom,audio-routing =
+				"RX_BIAS", "MCLK",
+				"SPK_RX_BIAS", "MCLK",
+				"INT_LDO_H", "MCLK",
+				"RX_I2S_CLK", "MCLK",
+				"TX_I2S_CLK", "MCLK",
+				"MIC BIAS External", "Handset Mic",
+				"MIC BIAS External2", "Headset Mic",
+				"MIC BIAS External", "Secondary Mic",
+				"AMIC1", "MIC BIAS External",
+				"AMIC2", "MIC BIAS External2",
+				"AMIC3", "MIC BIAS External",
+				"ADC1_IN", "ADC1_OUT",
+				"ADC2_IN", "ADC2_OUT",
+				"ADC3_IN", "ADC3_OUT",
+				"PDM_IN_RX1", "PDM_OUT_RX1",
+				"PDM_IN_RX2", "PDM_OUT_RX2",
+				"PDM_IN_RX3", "PDM_OUT_RX3",
+				"WSA_SPK OUT", "VDD_WSA_SWITCH",
+				"SpkrMono WSA_IN", "WSA_SPK OUT";
+
+		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+		qcom,cdc-us-eu-gpios = <&cdc_us_euro_sw>;
+		qcom,pri-mi2s-gpios = <&cdc_pri_mi2s_gpios>;
+		qcom,quin-mi2s-gpios = <&cdc_quin_mi2s_gpios>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>, <&pcm_noirq>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2", "msm-voip-dsp",
+				"msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless",
+				"msm-pcm-afe", "msm-lsm-client",
+				"msm-pcm-routing", "msm-pcm-dsp-noirq";
+		asoc-cpu = <&dai_pri_auxpcm>,
+			<&dai_mi2s0>, <&dai_mi2s1>,
+			<&dai_mi2s2>, <&dai_mi2s3>,
+			<&dai_mi2s4>, <&dai_mi2s5>,
+			<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+			<&sb_3_rx>, <&sb_3_tx>, <&sb_4_rx>, <&sb_4_tx>,
+			<&bt_sco_rx>, <&bt_sco_tx>,
+			<&int_fm_rx>, <&int_fm_tx>,
+			<&afe_pcm_rx>, <&afe_pcm_tx>,
+			<&afe_proxy_rx>, <&afe_proxy_tx>,
+			<&incall_record_rx>, <&incall_record_tx>,
+			<&incall_music_rx>, <&incall_music_2_rx>;
+
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-mi2s.0", "msm-dai-q6-mi2s.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.4", "msm-dai-q6-mi2s.6",
+				"msm-dai-q6-dev.16384", "msmdai-q6-dev.16385",
+				"msm-dai-q6-dev.16386", "msm-dai-q6-dev.16387",
+				"msm-dai-q6-dev.16390", "msm-dai-q6-dev.16391",
+				"msm-dai-q6-dev.16392", "msm-dai-q6-dev.16393",
+				"msm-dai-q6-dev.12288", "msm-dai-q6-dev.12289",
+				"msm-dai-q6-dev.12292", "msm-dai-q6-dev.12293",
+				"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+				"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+				"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+				"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770";
+
+		asoc-codec = <&stub_codec>, <&msm_digital_codec>,
+				<&pmic_analog_codec>;
+		asoc-codec-names = "msm-stub-codec.1", "msm-dig-codec",
+					"analog-codec";
+		asoc-wsa-codec-names = "wsa881x-i2c-codec.2-000f";
+		asoc-wsa-codec-prefixes = "SpkrMono";
+		msm-vdd-wsa-switch-supply = <&pm8937_l5>;
+		qcom,msm-vdd-wsa-switch-voltage = <1800000>;
+		qcom,msm-vdd-wsa-switch-current = <10000>;
+	};
+
+	cdc_us_euro_sw: msm_cdc_pinctrl_us_euro_sw {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cross_conn_det_act>;
+		pinctrl-1 = <&cross_conn_det_sus>;
+	};
+
+	cdc_pri_mi2s_gpios: msm_cdc_pinctrl_pri {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_pdm_lines_act &cdc_pdm_lines_2_act>;
+		pinctrl-1 = <&cdc_pdm_lines_sus &cdc_pdm_lines_2_sus>;
+	};
+
+	cdc_quin_mi2s_gpios: msm_cdc_pinctrl_quin {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&pri_tlmm_lines_act &pri_tlmm_ws_act>;
+		pinctrl-1 = <&pri_tlmm_lines_sus &pri_tlmm_ws_sus>;
+	};
+
+
+	i2c@78b6000 {
+		status = "okay";
+		#address-cells = <1>;
+		#size-cells = <0>;
+		wsa881x_i2c_f: wsa881x-i2c-codec@f {
+			status = "okay";
+			compatible = "qcom,wsa881x-i2c-codec";
+			reg = <0x0f>;
+			qcom,wsa-analog-vi-gpio = <&wsa881x_analog_vi_gpio>;
+			qcom,wsa-analog-clk-gpio = <&wsa881x_analog_clk_gpio>;
+			qcom,wsa-analog-reset-gpio =
+				<&wsa881x_analog_reset_gpio>;
+		};
+		wsa881x_i2c_45: wsa881x-i2c-codec@45 {
+			status = "okay";
+			compatible = "qcom,wsa881x-i2c-codec";
+			reg = <0x45>;
+		};
+	};
+
+	wsa881x_analog_vi_gpio: wsa881x_analog_vi_pctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wsa_vi_on>;
+		pinctrl-1 = <&wsa_vi_off>;
+	};
+	wsa881x_analog_clk_gpio: wsa881x_analog_clk_pctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wsa_clk_on>;
+		pinctrl-1 = <&wsa_clk_off>;
+	};
+	wsa881x_analog_reset_gpio: wsa881x_analog_reset_pctrl {
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&wsa_reset_on>;
+		pinctrl-1 = <&wsa_reset_off>;
+	};
+
+	ext_codec: sound-9335 {
+		status = "disabled";
+		compatible = "qcom,msm8952-audio-slim-codec";
+		qcom,model = "msm8952-tasha-snd-card";
+
+		reg = <0xc051000 0x4>,
+			<0xc051004 0x4>,
+			<0xc055000 0x4>,
+			<0xc052000 0x4>;
+		reg-names = "csr_gp_io_mux_mic_ctl",
+			"csr_gp_io_mux_spkr_ctl",
+			"csr_gp_io_lpaif_pri_pcm_pri_mode_muxsel",
+			"csr_gp_io_mux_quin_ctl";
+
+		qcom,audio-routing =
+			"AIF4 VI", "MCLK",
+			"AIF4 VI", "MICBIAS_REGULATOR",
+			"RX_BIAS", "MCLK",
+			"MADINPUT", "MCLK",
+			"AIF4 MAD", "MICBIAS_REGULATOR",
+			"AMIC2", "MIC BIAS2",
+			"MIC BIAS2", "Headset Mic",
+			"AMIC3", "MIC BIAS2",
+			"MIC BIAS2", "ANCRight Headset Mic",
+			"AMIC4", "MIC BIAS2",
+			"MIC BIAS2", "ANCLeft Headset Mic",
+			"AMIC5", "MIC BIAS3",
+			"MIC BIAS3", "Handset Mic",
+			"AMIC6", "MIC BIAS4",
+			"MIC BIAS4", "Analog Mic6",
+			"DMIC0", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic0",
+			"DMIC1", "MIC BIAS1",
+			"MIC BIAS1", "Digital Mic1",
+			"DMIC2", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic2",
+			"DMIC3", "MIC BIAS3",
+			"MIC BIAS3", "Digital Mic3",
+			"DMIC4", "MIC BIAS4",
+			"MIC BIAS4", "Digital Mic4",
+			"DMIC5", "MIC BIAS4",
+			"MIC BIAS4", "Digital Mic5",
+			"MIC BIAS1", "MICBIAS_REGULATOR",
+			"MIC BIAS2", "MICBIAS_REGULATOR",
+			"MIC BIAS3", "MICBIAS_REGULATOR",
+			"MIC BIAS4", "MICBIAS_REGULATOR",
+			"SpkrLeft IN", "SPK1 OUT",
+			"SpkrRight IN", "SPK2 OUT";
+
+		qcom,tasha-mclk-clk-freq = <9600000>;
+
+		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
+				<&loopback>, <&compress>, <&hostless>,
+				<&afe>, <&lsm>, <&routing>;
+		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
+				"msm-pcm-dsp.2", "msm-voip-dsp",
+				"msm-pcm-voice", "msm-pcm-loopback",
+				"msm-compress-dsp", "msm-pcm-hostless",
+				"msm-pcm-afe", "msm-lsm-client",
+				"msm-pcm-routing";
+
+		asoc-cpu = <&dai_pri_auxpcm>,
+				<&dai_mi2s2>, <&dai_mi2s3>, <&dai_mi2s5>,
+				<&sb_0_rx>, <&sb_0_tx>, <&sb_1_rx>, <&sb_1_tx>,
+				<&sb_2_rx>, <&sb_2_tx>, <&sb_3_rx>, <&sb_3_tx>,
+				<&sb_4_rx>, <&sb_4_tx>, <&sb_5_tx>,
+				<&afe_pcm_rx>, <&afe_pcm_tx>,
+				<&afe_proxy_rx>, <&afe_proxy_tx>,
+				<&incall_record_rx>, <&incall_record_tx>,
+				<&incall_music_rx>, <&incall_music_2_rx>,
+				<&sb_5_rx>, <&bt_sco_rx>, <&bt_sco_tx>,
+				<&int_fm_rx>, <&int_fm_tx>, <&sb_6_rx>;
+
+		asoc-cpu-names = "msm-dai-q6-auxpcm.1",
+				"msm-dai-q6-mi2s.2", "msm-dai-q6-mi2s.3",
+				"msm-dai-q6-mi2s.5", "msm-dai-q6-dev.16384",
+				"msm-dai-q6-dev.16385", "msm-dai-q6-dev.16386",
+				"msm-dai-q6-dev.16387", "msm-dai-q6-dev.16388",
+				"msm-dai-q6-dev.16389", "msm-dai-q6-dev.16390",
+				"msm-dai-q6-dev.16391", "msm-dai-q6-dev.16392",
+				"msm-dai-q6-dev.16393", "msm-dai-q6-dev.16395",
+				"msm-dai-q6-dev.224", "msm-dai-q6-dev.225",
+				"msm-dai-q6-dev.241", "msm-dai-q6-dev.240",
+				"msm-dai-q6-dev.32771", "msm-dai-q6-dev.32772",
+				"msm-dai-q6-dev.32773", "msm-dai-q6-dev.32770",
+				"msm-dai-q6-dev.16394", "msm-dai-q6-dev.12288",
+				"msm-dai-q6-dev.12289", "msm-dai-q6-dev.12292",
+				"msm-dai-q6-dev.12293", "msm-dai-q6-dev.16396";
+
+		asoc-codec = <&stub_codec>, <&hdmi_dba>;
+		asoc-codec-names = "msm-stub-codec.1", "msm-hdmi-dba-codec-rx";
+		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+
+		qcom,wsa-max-devs = <2>;
+		qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
+				<&wsa881x_213>, <&wsa881x_214>;
+		qcom,wsa-aux-dev-prefix = "SpkrLeft", "SpkrRight",
+				"SpkrLeft", "SpkrRight";
+	};
+
+	wcd9xxx_intc: wcd9xxx-irq {
+		status = "disabled";
+		interrupt-parent = <&tlmm>;
+		interrupts = <73 0>;
+		qcom,gpio-connect = <&tlmm 73 0>;
+	};
+
+	clock_audio: audio_ext_clk {
+		status = "disabled";
+		compatible = "qcom,audio-ref-clk";
+		clock-names = "osr_clk";
+		qcom,node_has_rpm_clock;
+		#clock-cells = <1>;
+		qcom,audio-ref-clk-gpio = <&pm8937_gpios 1 0>;
+		qcom,lpass-mclk-id = "pri_mclk";
+		clocks = <&clock_gcc clk_div_clk2>;
+		pinctrl-0 = <&cdc_mclk2_sleep>;
+		pinctrl-1 = <&cdc_mclk2_active>;
+	};
+
+	wcd_rst_gpio: wcd_gpio_ctrl {
+		status = "disabled";
+		qcom,cdc-rst-n-gpio = <&tlmm 68 0>;
+	};
+};
+
+&slim_msm {
+	status = "disabled";
+	wcd9335: tasha_codec {
+		status = "disabled";
+		compatible = "qcom,tasha-slim-pgd";
+		clock-names = "wcd_clk", "wcd_native_clk";
+		clocks = <&clock_audio clk_audio_pmi_clk>,
+			<&clock_audio clk_audio_ap_clk2>;
+
+		qcom,cdc-reset-gpio = <&tlmm 68 0>;
+
+		cdc-vdd-buck-supply = <&eldo2_pm8937>;
+		qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-buck-current = <650000>;
+
+		cdc-buck-sido-supply = <&eldo2_pm8937>;
+		qcom,cdc-buck-sido-voltage = <1800000 1800000>;
+		qcom,cdc-buck-sido-current = <250000>;
+
+		cdc-vdd-tx-h-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-tx-h-current = <25000>;
+
+		cdc-vdd-rx-h-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-rx-h-current = <25000>;
+
+		cdc-vdd-px-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-px-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-px-current = <10000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8937_l13>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <15000>;
+	};
+};
+
+&pm8937_gpios {
+	gpio@c000 {
+		status = "ok";
+		qcom,mode = <1>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <0>;
+		qcom,src-sel = <2>;
+		qcom,master-en = <1>;
+		qcom,out-strength = <2>;
+	};
+};
+
+&pm8937_1 {
+	pmic_analog_codec: analog-codec@f000 {
+		status = "okay";
+		compatible = "qcom,pmic-analog-codec";
+		reg = <0xf000 0x200>;
+		#address-cells = <2>;
+		#size-cells = <0>;
+		interrupt-parent = <&spmi_bus>;
+		interrupts = <0x1 0xf0 0x0 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x1 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x2 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x3 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x4 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x5 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x6 IRQ_TYPE_NONE>,
+			<0x1 0xf0 0x7 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x0 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x1 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x2 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x3 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x4 IRQ_TYPE_NONE>,
+			<0x1 0xf1 0x5 IRQ_TYPE_NONE>;
+		interrupt-names = "spk_cnp_int",
+				"spk_clip_int",
+				"spk_ocp_int",
+				"ins_rem_det1",
+				"but_rel_det",
+				"but_press_det",
+				"ins_rem_det",
+				"mbhc_int",
+				"ear_ocp_int",
+				"hphr_ocp_int",
+				"hphl_ocp_det",
+				"ear_cnp_int",
+				"hphr_cnp_int",
+				"hphl_cnp_int";
+
+		cdc-vdda-cp-supply = <&pm8937_s4>;
+		qcom,cdc-vdda-cp-voltage = <2050000 2050000>;
+		qcom,cdc-vdda-cp-current = <210000>;
+
+		cdc-vdd-io-supply = <&pm8937_l5>;
+		qcom,cdc-vdd-io-voltage = <1800000 1800000>;
+		qcom,cdc-vdd-io-current = <5000>;
+
+		cdc-vdd-pa-supply = <&pm8937_s4>;
+		qcom,cdc-vdd-pa-voltage = <1900000 2050000>;
+		qcom,cdc-vdd-pa-current = <260000>;
+
+		cdc-vdd-mic-bias-supply = <&pm8937_l13>;
+		qcom,cdc-vdd-mic-bias-voltage = <3075000 3075000>;
+		qcom,cdc-vdd-mic-bias-current = <5000>;
+
+		qcom,cdc-mclk-clk-rate = <9600000>;
+
+		qcom,cdc-static-supplies = "cdc-vdd-io",
+					"cdc-vdd-pa",
+					"cdc-vdda-cp";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+
+		msm_digital_codec: msm-dig-codec {
+			compatible = "qcom,msm-digital-codec";
+			reg = <0xc0f0000 0x0>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
new file mode 100644
index 0000000..b82767915
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-coresight.dtsi
@@ -0,0 +1,1192 @@
+/*
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 an
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	tmc_etr: tmc@6028000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b961>;
+
+		reg = <0x6028000 0x1000>,
+				<0x6044000 0x15000>;
+		reg-names = "tmc-base", "bam-base";
+
+		interrupts = <0 166 0>;
+		interrupt-names = "byte-cntr-irq";
+
+		arm,buffer-size = <0x100000>;
+		arm,sg-enable;
+
+		coresight-name = "coresight-tmc-etr";
+		coresight-ctis = <&cti0 &cti8>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			tmc_etr_in_replicator: endpoint {
+				slave-mode;
+				remote-endpoint = <&replicator_out_tmc_etr>;
+			};
+		};
+	};
+
+	tmc_etf: tmc@6027000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b961>;
+
+		reg = <0x6027000 0x1000>;
+		reg-names = "tmc-base";
+
+		coresight-name = "coresight-tmc-etf";
+
+		arm,default-sink;
+		coresight-ctis = <&cti0 &cti8>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				tmc_etf_out_replicator:endpoint {
+					remote-endpoint =
+						<&replicator_in_tmc_etf>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				tmc_etf_in_funnel_in0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_in0_out_tmc_etf>;
+				};
+			};
+		};
+	};
+
+	replicator: replicator@6026000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b909>;
+
+		reg = <0x6026000 0x1000>;
+		reg-names = "replicator-base";
+
+		coresight-name = "coresight-replicator";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				replicator_out_tmc_etr: endpoint {
+					remote-endpoint =
+						<&tmc_etr_in_replicator>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				replicator_in_tmc_etf: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tmc_etf_out_replicator>;
+				};
+			};
+		};
+	};
+
+	funnel_in0: funnel@6021000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6021000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-in0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				funnel_in0_out_tmc_etf: endpoint {
+					remote-endpoint =
+						<&tmc_etf_in_funnel_in0>;
+				};
+			};
+
+			port@1 {
+				reg = <7>;
+				funnel_in0_in_stm: endpoint {
+					slave-mode;
+					remote-endpoint = <&stm_out_funnel_in0>;
+				};
+			};
+
+			port@2 {
+				reg = <6>;
+				funnel_in0_in_tpda: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&tpda_out_funnel_in0>;
+				};
+			};
+
+			port@3 {
+				reg = <3>;
+				funnel_in0_in_funnel_center: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_center_out_funnel_in0>;
+				};
+			};
+
+			port@4 {
+				reg = <4>;
+				funnel_in0_in_funnel_right: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_right_out_funnel_in0>;
+				};
+			};
+
+			port@5 {
+				reg = <5>;
+				funnel_in0_in_funnel_mm: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_mm_out_funnel_in0>;
+				};
+			};
+		};
+	};
+
+	funnel_center: funnel@6100000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6100000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-center";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				funnel_center_out_funnel_in0: endpoint {
+					remote-endpoint =
+						<&funnel_in0_in_funnel_center>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_center_in_rpm_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&rpm_etm0_out_funnel_center>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				funnel_center_in_dbgui: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&dbgui_out_funnel_center>;
+				};
+			};
+		};
+	};
+
+	funnel_right: funnel@6120000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6120000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-right";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				funnel_right_out_funnel_in0: endpoint {
+					remote-endpoint =
+						<&funnel_in0_in_funnel_right>;
+				};
+			};
+
+			port@1 {
+				reg = <1>;
+				funnel_right_in_modem_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&modem_etm0_out_funnel_right>;
+				};
+			};
+
+			port@2 {
+				reg = <2>;
+				funnel_right_in_funnel_apss: endpoint {
+					slave-mode;
+					remote-endpoint =
+					       <&funnel_apss_out_funnel_right>;
+				};
+			};
+		};
+	};
+
+	funnel_mm: funnel@6130000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6130000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-mm";
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				funnel_mm_out_funnel_in0: endpoint {
+					remote-endpoint =
+						<&funnel_in0_in_funnel_mm>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_mm_in_wcn_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&wcn_etm0_out_funnel_mm>;
+				};
+			};
+
+			port@2 {
+				reg = <4>;
+				funnel_mm_in_funnel_cam: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&funnel_cam_out_funnel_mm>;
+				};
+			};
+
+			port@3 {
+				reg = <5>;
+				funnel_mm_in_audio_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&audio_etm0_out_funnel_mm>;
+				};
+			};
+		};
+	};
+
+	funnel_cam: funnel@6132000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x6132000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-cam";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			funnel_cam_out_funnel_mm: endpoint {
+				remote-endpoint = <&funnel_mm_in_funnel_cam>;
+			};
+		};
+	};
+
+	funnel_apss: funnel@61a1000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b908>;
+
+		reg = <0x61a1000 0x1000>;
+		reg-names = "funnel-base";
+
+		coresight-name = "coresight-funnel-apss";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			port@0 {
+				funnel_apss_out_funnel_right: endpoint {
+					remote-endpoint =
+						<&funnel_right_in_funnel_apss>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				funnel_apss0_in_etm4: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm4_out_funnel_apss0>;
+				};
+			};
+
+			port@2 {
+				reg = <1>;
+				funnel_apss0_in_etm5: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm5_out_funnel_apss0>;
+				};
+			};
+
+			port@3 {
+				reg = <2>;
+				funnel_apss0_in_etm6: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm6_out_funnel_apss0>;
+				};
+			};
+
+			port@4 {
+				reg = <3>;
+				funnel_apss0_in_etm7: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm7_out_funnel_apss0>;
+				};
+			};
+
+			port@5 {
+				reg = <4>;
+				funnel_apss0_in_etm0: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm0_out_funnel_apss0>;
+				};
+			};
+
+			port@6 {
+				reg = <5>;
+				funnel_apss0_in_etm1: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm1_out_funnel_apss0>;
+				};
+			};
+
+			port@7 {
+				reg = <6>;
+				funnel_apss0_in_etm2: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm2_out_funnel_apss0>;
+					};
+			};
+
+			port@8 {
+				reg = <7>;
+				funnel_apss0_in_etm3: endpoint {
+					slave-mode;
+					remote-endpoint =
+						<&etm3_out_funnel_apss0>;
+				};
+			};
+		};
+	};
+
+	etm4: etm@619c000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x619c000 0x1000>;
+		cpu = <&CPU4>;
+		coresight-name = "coresight-etm4";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm4_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm4>;
+			};
+		};
+	};
+
+	etm5: etm@619d000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x619d000 0x1000>;
+		cpu = <&CPU5>;
+		coresight-name = "coresight-etm5";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm5_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm5>;
+			};
+		};
+	};
+
+	etm6: etm@619e000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x619e000 0x1000>;
+		cpu = <&CPU6>;
+		coresight-name = "coresight-etm6";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm6_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm6>;
+			};
+		};
+	};
+
+	etm7: etm@619f000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x619f000 0x1000>;
+		cpu = <&CPU7>;
+		coresight-name = "coresight-etm7";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm7_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm7>;
+			};
+		};
+	};
+
+	etm0: etm@61bc000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x61bc000 0x1000>;
+		cpu = <&CPU0>;
+		coresight-name = "coresight-etm0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm0_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm0>;
+			};
+		};
+	};
+
+	etm1: etm@61bd000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x61bd000 0x1000>;
+		cpu = <&CPU1>;
+		coresight-name = "coresight-etm1";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm1_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm1>;
+			};
+		};
+	};
+
+	etm2: etm@61be000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x61be000 0x1000>;
+		cpu = <&CPU2>;
+		coresight-name = "coresight-etm2";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm2_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm2>;
+			};
+		};
+	};
+
+	etm3: etm@61bf000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x000bb95d>;
+
+		reg = <0x61bf000 0x1000>;
+		coresight-name = "coresight-etm3";
+		cpu = <&CPU3>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			etm3_out_funnel_apss0: endpoint {
+				remote-endpoint = <&funnel_apss0_in_etm3>;
+			};
+		};
+	};
+
+	stm: stm@6002000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b962>;
+
+		reg = <0x6002000 0x1000>,
+		      <0x9280000 0x180000>;
+		reg-names = "stm-base", "stm-stimulus-base";
+
+		coresight-name = "coresight-stm";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			stm_out_funnel_in0: endpoint {
+				remote-endpoint = <&funnel_in0_in_stm>;
+			};
+		};
+	};
+
+	cti0: cti@6010000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6010000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti1: cti@6011000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6011000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti1";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti2: cti@6012000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6012000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti2";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti3: cti@6013000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6013000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti3";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti4: cti@6014000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6014000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti4";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti5: cti@6015000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6015000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti5";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti6: cti@6016000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6016000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti6";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti7: cti@6017000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6017000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti7";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti8: cti@6018000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6018000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti8";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti9: cti@6019000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6019000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti9";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti10: cti@601a000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x601a000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti10";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti11: cti@601b000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x601b000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti11";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti12: cti@601c000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x601c000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti12";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti13: cti@601d000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x601d000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti13";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti14: cti@601e000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x601e000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti14";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti15: cti@601f000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x601f000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti15";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu0: cti@6198000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6198000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu0";
+		cpu = <&CPU0>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu1: cti@6199000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6199000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu1";
+		cpu = <&CPU1>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu2: cti@619a000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x619a000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu2";
+		cpu = <&CPU2>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu3: cti@619b000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x619b000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu3";
+		cpu = <&CPU3>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu4: cti@61b8000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x61b8000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu4";
+		cpu = <&CPU4>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu5: cti@61b9000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x61b9000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu5";
+		cpu = <&CPU5>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu6: cti@61ba000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x61ba000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu6";
+		cpu = <&CPU6>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_cpu7: cti@61bb000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x61bb000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-cpu7";
+		cpu = <&CPU7>;
+		qcom,cti-save;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_modem_cpu0: cti@6128000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6128000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-modem-cpu0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_modem_cpu1: cti@6124000{
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6124000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-modem-cpu1";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	/* Venus CTI */
+	cti_video_cpu0: cti@6134000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6134000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-video-cpu0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	/* Pronto CTI */
+	cti_wcn_cpu0: cti@6139000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x6139000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-wcn-cpu0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	/* LPASS CTI */
+	cti_audio_cpu0: cti@613c000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x613c000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-audio-cpu0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	cti_rpm_cpu0: cti@610c000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b966>;
+
+		reg = <0x610c000 0x1000>;
+		reg-names = "cti-base";
+		coresight-name = "coresight-cti-rpm-cpu0";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	/* Pronto ETM */
+	wcn_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+		coresight-name = "coresight-wcn-etm0";
+		qcom,inst-id = <3>;
+
+		port {
+			wcn_etm0_out_funnel_mm: endpoint {
+				remote-endpoint = <&funnel_mm_in_wcn_etm0>;
+			};
+		};
+	};
+
+	rpm_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+		coresight-name = "coresight-rpm-etm0";
+		qcom,inst-id = <4>;
+
+		port {
+			rpm_etm0_out_funnel_center: endpoint {
+				remote-endpoint = <&funnel_center_in_rpm_etm0>;
+			};
+		};
+	};
+
+	/* LPASS ETM */
+	audio_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+		coresight-name = "coresight-audio-etm0";
+		qcom,inst-id = <5>;
+
+		port {
+			audio_etm0_out_funnel_mm: endpoint {
+				remote-endpoint = <&funnel_mm_in_audio_etm0>;
+			};
+		};
+	};
+
+	/* MSS_SCL */
+	modem_etm0 {
+		compatible = "qcom,coresight-remote-etm";
+		coresight-name = "coresight-modem-etm0";
+		qcom,inst-id = <11>;
+
+		port {
+			modem_etm0_out_funnel_right: endpoint {
+				remote-endpoint = <&funnel_right_in_modem_etm0>;
+			};
+		};
+	};
+
+
+	csr: csr@6001000 {
+		compatible = "qcom,coresight-csr";
+		reg = <0x6001000 0x1000>;
+		reg-names = "csr-base";
+		coresight-name = "coresight-csr";
+
+		qcom,blk-size = <1>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+	dbgui: dbgui@6108000 {
+		compatible = "qcom,coresight-dbgui";
+		reg = <0x6108000 0x1000>;
+		reg-names = "dbgui-base";
+		coresight-name = "coresight-dbgui";
+
+		qcom,dbgui-addr-offset = <0x30>;
+		qcom,dbgui-data-offset = <0x130>;
+		qcom,dbgui-size = <64>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			dbgui_out_funnel_center: endpoint {
+				remote-endpoint = <&funnel_center_in_dbgui>;
+			};
+		};
+	};
+
+	tpda: tpda@6003000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b969>;
+
+		reg = <0x6003000 0x1000>;
+		reg-names = "tpda-base";
+		coresight-name = "coresight-tpda";
+
+		qcom,tpda-atid = <64>;
+		qcom,cmb-elem-size = <0 32>;
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		ports {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+			port@0 {
+				tpda_out_funnel_in0: endpoint {
+					remote-endpoint = <&funnel_in0_in_tpda>;
+				};
+			};
+
+			port@1 {
+				reg = <0>;
+				tpda_in_tpdm_dcc: endpoint {
+					slave-mode;
+						remote-endpoint =
+							<&tpdm_dcc_out_tpda>;
+				};
+			};
+		};
+	};
+
+	tpdm_dcc: tpdm@6110000 {
+		compatible = "arm,primecell";
+		arm,primecell-periphid = <0x0003b968>;
+
+		reg = <0x6110000 0x1000>;
+		reg-names = "tpdm-base";
+		coresight-name = "coresight-tpdm-dcc";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+
+		port {
+			tpdm_dcc_out_tpda: endpoint {
+				remote-endpoint = <&tpda_in_tpdm_dcc>;
+			};
+		};
+	};
+
+	hwevent: hwevent@6101000 {
+		compatible = "qcom,coresight-hwevent";
+
+		reg = <0x6101000 0x148>,
+		      <0x6101fb0 0x4>,
+		      <0x6121000 0x148>,
+		      <0x6121fb0 0x4>,
+		      <0x6131000 0x148>,
+		      <0x6131fb0 0x4>,
+		      <0x7105010 0x4>,
+		      <0x7885010 0x4>;
+
+		reg-names = "center-wrapper-mux", "center-wrapper-lockaccess",
+				"right-wrapper-mux", "right-wrapper-lockaccess",
+				"mm-wrapper-mux", "mm-wrapper-lockaccess",
+				"usbbam-mux", "blsp-mux";
+
+		coresight-name = "coresight-hwevent";
+
+		clocks = <&clock_gcc clk_qdss_clk>,
+			 <&clock_gcc clk_qdss_a_clk>;
+		clock-names = "apb_pclk";
+	};
+
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
index 84f73a4..7aaaf7e 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-cpu.dtsi
@@ -57,6 +57,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x100>;
 			enable-method = "psci";
+			efficiency = <1126>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
 			L2_1: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -79,6 +81,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x101>;
 			enable-method = "psci";
+			efficiency = <1126>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
 			L1_I_101: l1-icache {
 				compatible = "arm,arch-cache";
@@ -95,6 +99,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x102>;
 			enable-method = "psci";
+			efficiency = <1126>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
 			L1_I_102: l1-icache {
 				compatible = "arm,arch-cache";
@@ -111,6 +117,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x103>;
 			enable-method = "psci";
+			efficiency = <1126>;
+			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
 			L1_I_103: l1-icache {
 				compatible = "arm,arch-cache";
@@ -127,6 +135,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x0>;
 			enable-method = "psci";
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
 			L2_0: l2-cache {
 			      compatible = "arm,arch-cache";
@@ -148,6 +158,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x1>;
 			enable-method = "psci";
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
 			L1_I_1: l1-icache {
 				compatible = "arm,arch-cache";
@@ -164,6 +176,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x2>;
 			enable-method = "psci";
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
 			L1_I_2: l1-icache {
 				compatible = "arm,arch-cache";
@@ -180,6 +194,8 @@
 			compatible = "arm,cortex-a53";
 			reg = <0x3>;
 			enable-method = "psci";
+			efficiency = <1024>;
+			sched-energy-costs = <&CPU_COST_1 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
 			L1_I_3: l1-icache {
 				compatible = "arm,arch-cache";
@@ -191,4 +207,57 @@
 			};
 		};
 	};
+
+	energy_costs: energy-costs {
+		compatible = "sched-energy";
+
+		CPU_COST_0: core-cost0 {
+			busy-cost-data = <
+				 700000  623
+				1000000  917
+				1100000  1106
+				1250000  1432
+				1400000  1740
+			>;
+			idle-cost-data = <
+				100 80 60 40
+			>;
+		};
+		CPU_COST_1: core-cost1 {
+			busy-cost-data = <
+				 500000  70
+				 800000  114
+				 900000  141
+				1000000  178
+				1100000  213
+			>;
+			idle-cost-data = <
+				40 20 10 8
+			>;
+		};
+		CLUSTER_COST_0: cluster-cost0 {
+			busy-cost-data = <
+				 500000  19
+				 800000  29
+				 900000  36
+				1000000  46
+				1100000  55
+			>;
+			idle-cost-data = <
+				4 3 2 1
+			>;
+		};
+		CLUSTER_COST_1: cluster-cost1 {
+			busy-cost-data = <
+				 700000  85
+				1000000  126
+				1100000  152
+				1250000  197
+				1400000  239
+			>;
+			idle-cost-data = <
+				4 3 2 1
+			>;
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8937-gpu.dtsi b/arch/arm64/boot/dts/qcom/msm8937-gpu.dtsi
new file mode 100644
index 0000000..2ee4c0e
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-gpu.dtsi
@@ -0,0 +1,224 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&soc {
+	msm_bus: qcom,kgsl-busmon {
+		label = "kgsl-busmon";
+		compatible = "qcom,kgsl-busmon";
+	};
+
+	gpubw: qcom,gpubw {
+		compatible = "qcom,devbw";
+		governor = "bw_vbif";
+		qcom,src-dst-ports = <26 512>;
+		/*
+		 * active-only flag is used while registering the bus
+		 * governor.It helps release the bus vote when the CPU
+		 * subsystem is inactiv3
+		 */
+		qcom,active-only;
+		qcom,bw-tbl =
+			< 0    >, /*  off */
+			<  769 >, /* 1. DDR:100.80 MHz BIMC: 50.40 MHz */
+			< 1611 >, /* 2. DDR:211.20 MHz BIMC: 105.60 MHz */
+			< 2124 >, /* 3. DDR:278.40 MHz BIMC: 139.20 MHz */
+			< 2929 >, /* 4. DDR:384.00 MHz BIMC: 192.00 MHz */
+			< 4101 >, /* 5. DDR:537.60 MHz BIMC: 268.80 MHz */
+			< 4248 >, /* 6. DDR:556.80 MHz BIMC: 278.40 MHz */
+			< 5346 >, /* 7. DDR:662.40 MHz BIMC: 331.20 MHz */
+			< 5712 >, /* 8. DDR:748.80 MHz BIMC: 374.40 MHz */
+			< 6152 >, /* 9. DDR:806.40 MHz BIMC: 403.20 MHz */
+			< 7031 >; /* 10. DDR:921.60 MHz BIMC: 460.80 MHz */
+	};
+
+	msm_gpu: qcom,kgsl-3d0@1c00000 {
+		label = "kgsl-3d0";
+		compatible = "qcom,kgsl-3d0", "qcom,kgsl-3d";
+		status = "ok";
+		reg = <0x1c00000 0x40000
+		       0xa0000 0x6fff>;
+		reg-names = "kgsl_3d0_reg_memory", "qfprom_memory";
+		interrupts = <0 33 0>;
+		interrupt-names = "kgsl_3d0_irq";
+		qcom,id = <0>;
+		qcom,chipid = <0x05000500>;
+
+		qcom,initial-pwrlevel = <2>;
+
+		qcom,idle-timeout = <80>; //msecs
+		qcom,strtstp-sleepwake;
+
+		qcom,highest-bank-bit = <14>;
+
+		qcom,snapshot-size = <1048576>; //bytes
+
+		clocks = <&clock_gcc clk_gcc_oxili_gfx3d_clk>,
+			<&clock_gcc clk_gcc_oxili_ahb_clk>,
+			<&clock_gcc clk_gcc_bimc_gfx_clk>,
+			<&clock_gcc clk_gcc_bimc_gpu_clk>,
+			<&clock_gcc clk_gcc_oxili_timer_clk>,
+			<&clock_gcc clk_gcc_oxili_aon_clk>;
+
+		clock-names = "core_clk", "iface_clk",
+			      "mem_iface_clk", "alt_mem_iface_clk",
+			      "rbbmtimer_clk", "alwayson_clk";
+
+
+		/* Bus Scale Settings */
+		qcom,gpubw-dev = <&gpubw>;
+		qcom,bus-control;
+		qcom,bus-width = <16>;
+		qcom,msm-bus,name = "grp3d";
+		qcom,msm-bus,num-cases = <11>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<26 512 0 0>,	    /*    off        */
+				<26 512 0  806400>, /* 1. 100.80 MHz */
+				<26 512 0 1689600>, /* 2. 211.20 MHz */
+				<26 512 0 2227200>, /* 3. 278.40 MHz */
+				<26 512 0 3072000>, /* 4. 384.00 MHz */
+				<26 512 0 4300800>, /* 5. 537.60 MHz */
+				<26 512 0 4454400>, /* 6. 556.80 MHz */
+				<26 512 0 5299200>, /* 7. 662.40 MHz */
+				<26 512 0 5990400>, /* 8. 748.80 MHz */
+				<26 512 0 6451200>, /* 9. 806.40 MHz */
+				<26 512 0 7372800>; /* 10. 921.60 MHz */
+
+		/* GDSC regulator names */
+		regulator-names = "vddcx", "vdd";
+		/* GDSC oxili regulators */
+		vddcx-supply = <&gdsc_oxili_cx>;
+		vdd-supply = <&gdsc_oxili_gx>;
+
+		/* CPU latency parameter */
+		qcom,pm-qos-active-latency = <360>;
+		qcom,pm-qos-wakeup-latency = <360>;
+
+		/*  Quirks  */
+		qcom,gpu-quirk-two-pass-use-wfi;
+		qcom,gpu-quirk-dp2clockgating-disable;
+		qcom,gpu-quirk-lmloadkill-disable;
+
+		/* Enable context aware freq. scaling */
+		qcom,enable-ca-jump;
+
+		/* Context aware jump busy penalty in us */
+		qcom,ca-busy-penalty = <12000>;
+
+		/* Context aware jump target power level */
+		qcom,ca-target-pwrlevel = <1>;
+
+		/* GPU Mempools */
+		qcom,gpu-mempools {
+			#address-cells= <1>;
+			#size-cells = <0>;
+			compatible = "qcom,gpu-mempools";
+
+			qcom,mempool-max-pages = <32768>;
+
+			/* 4K Page Pool configuration */
+			qcom,gpu-mempool@0 {
+				reg = <0>;
+				qcom,mempool-page-size = <4096>;
+			};
+			/* 64K Page Pool configuration */
+			qcom,gpu-mempool@1 {
+				reg = <1>;
+				qcom,mempool-page-size = <65536>;
+			};
+		};
+
+		/* Power levels */
+		qcom,gpu-pwrlevels {
+			#address-cells = <1>;
+			#size-cells = <0>;
+
+			compatible = "qcom,gpu-pwrlevels";
+
+			/* TURBO */
+			qcom,gpu-pwrlevel@0 {
+				reg = <0>;
+				qcom,gpu-freq = <450000000>;
+				qcom,bus-freq = <9>;
+				qcom,bus-min = <9>;
+				qcom,bus-max = <9>;
+			};
+
+			/* NOM+ */
+			qcom,gpu-pwrlevel@1 {
+				reg = <1>;
+				qcom,gpu-freq = <400000000>;
+				qcom,bus-freq = <7>;
+				qcom,bus-min = <6>;
+				qcom,bus-max = <9>;
+			};
+
+			/* NOM */
+			qcom,gpu-pwrlevel@2 {
+				reg = <2>;
+				qcom,gpu-freq = <375000000>;
+				qcom,bus-freq = <6>;
+				qcom,bus-min = <5>;
+				qcom,bus-max = <8>;
+			};
+
+			/* SVS+ */
+			qcom,gpu-pwrlevel@3 {
+				reg = <3>;
+				qcom,gpu-freq = <300000000>;
+				qcom,bus-freq = <5>;
+				qcom,bus-min = <4>;
+				qcom,bus-max = <7>;
+			};
+
+			/* SVS */
+			qcom,gpu-pwrlevel@4 {
+				reg = <4>;
+				qcom,gpu-freq = <216000000>;
+				qcom,bus-freq = <3>;
+				qcom,bus-min = <1>;
+				qcom,bus-max = <4>;
+			};
+
+			/* XO */
+			qcom,gpu-pwrlevel@5 {
+				reg = <5>;
+				qcom,gpu-freq = <19200000>;
+				qcom,bus-freq = <0>;
+				qcom,bus-min = <0>;
+				qcom,bus-max = <0>;
+			};
+		};
+	};
+
+	kgsl_msm_iommu: qcom,kgsl-iommu@1c40000 {
+		compatible = "qcom,kgsl-smmu-v2";
+
+		reg = <0x1c40000 0x10000>;
+		qcom,protect = <0x40000 0x10000>;
+		qcom,micro-mmu-control = <0x6000>;
+
+		clocks = <&clock_gcc clk_gcc_oxili_ahb_clk>,
+			 <&clock_gcc clk_gcc_bimc_gfx_clk>;
+
+		clock-names = "gpu_ahb_clk", "gcc_bimc_gfx_clk";
+
+		qcom,secure_align_mask = <0xfff>;
+		qcom,retention;
+		gfx3d_user: gfx3d_user {
+			compatible = "qcom,smmu-kgsl-cb";
+			label = "gfx3d_user";
+			iommus = <&kgsl_smmu 0>;
+			qcom,gpu-offset = <0x48000>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-cdp.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-cdp.dts
new file mode 100644
index 0000000..4045e9c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-cdp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8937-interposer-sdm439.dtsi"
+#include "sdm439-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8937 Interposer SDM439 CDP";
+	compatible = "qcom,msm8937-cdp", "qcom,msm8937", "qcom,cdp";
+	qcom,board-id = <1 2>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-mtp.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-mtp.dts
new file mode 100644
index 0000000..b34974c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8937-interposer-sdm439.dtsi"
+#include "sdm439-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8937 Interposer SDM439 MTP";
+	compatible = "qcom,msm8937-mtp", "qcom,msm8937", "qcom,mtp";
+	qcom,board-id = <8 1>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
new file mode 100644
index 0000000..2bad28b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439-qrd.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "msm8937-interposer-sdm439.dtsi"
+#include "sdm439-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. MSM8937 Interposer SDM439 QRD";
+	compatible = "qcom,msm8937-qrd", "qcom,msm8937", "qcom,qrd";
+	qcom,board-id = <0xb 2>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
new file mode 100644
index 0000000..4c2fc88
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-interposer-sdm439.dtsi
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8937.dtsi"
+#include "sdm439-pm8953.dtsi"
+#include "sdm439-pmi632.dtsi"
+
+&soc {
+	mem_acc_vreg_corner: regulator@01946004 {
+		compatible = "qcom,mem-acc-regulator";
+		regulator-name = "mem_acc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <3>;
+
+		qcom,acc-reg-addr-list =
+			<0x01942138 0x01942130 0x01942120
+			 0x01942124 0x01946000 0x01946004>;
+
+		qcom,acc-init-reg-config = <1 0xff>, <2 0x5555>, <6 0x55>;
+
+		qcom,num-acc-corners = <3>;
+		qcom,boot-acc-corner = <2>;
+		qcom,corner1-reg-config =
+			/* SVS+ => SVS+ */
+			<(-1) (-1)>,     <(-1) (-1)>,   <(-1) (-1)>,
+			<(-1) (-1)>,     <(-1) (-1)>,   <(-1) (-1)>,
+			/* SVS+ => NOM */
+			<  3 0x1041041>, <  4  0x1041>, <  5  0x2020202>,
+			<(-1) (-1)>,     <(-1) (-1)>,   <(-1) (-1)>,
+			/* SVS+ => TURBO/NOM+ */
+			<  3 0x1041041>, <  4  0x1041>, <  5  0x2020202>,
+			<  3 0x0>,       <  4  0x0>,    <  5  0x0>;
+
+		qcom,corner2-reg-config =
+			/* NOM => SVS+ */
+			<  3 0x30c30c3>, <  4  0x30c3>, <  5  0x6060606>,
+			/* NOM => NOM */
+			<(-1) (-1)>,     <(-1) (-1)>,   <(-1) (-1)>,
+			/* NOM => TURBO/NOM+ */
+			<  3 0x0>,       <  4  0x0>,    <  5  0x0>;
+
+		qcom,corner3-reg-config =
+			/* TURBO/NOM+ => SVS+ */
+			<  3 0x1041041>, <  4  0x1041>, <  5  0x2020202>,
+			<  3 0x30c30c3>, <  4  0x30c3>, <  5  0x6060606>,
+			/* TURBO/NOM+ => NOM */
+			<  3 0x1041041>, <  4  0x1041>, <  5  0x2020202>,
+			<(-1) (-1)>,     <(-1) (-1)>,   <(-1) (-1)>,
+			/* TURBO/NOM+ => TURBO/NOM+ */
+			<(-1) (-1)>,     <(-1) (-1)>,   <(-1) (-1)>,
+			<(-1) (-1)>,     <(-1) (-1)>,   <(-1) (-1)>;
+	};
+
+	apc_vreg_corner: regulator@b018000 {
+		compatible = "qcom,cpr-regulator";
+		reg = <0xb018000 0x1000>, <0xb011064 4>, <0xa4000 0x1000>;
+		reg-names = "rbcpr", "rbcpr_clk", "efuse_addr";
+		interrupts = <0 15 0>;
+		regulator-name = "apc_corner";
+		regulator-min-microvolt = <1>;
+		regulator-max-microvolt = <7>;
+
+		qcom,cpr-fuse-corners = <3>;
+		qcom,cpr-voltage-ceiling = <1155000 1225000 1350000>;
+		qcom,cpr-voltage-floor =   <1050000 1050000 1090000>;
+		vdd-apc-supply = <&pm8953_s5>;
+
+		mem-acc-supply = <&mem_acc_vreg_corner>;
+
+		qcom,cpr-ref-clk = <19200>;
+		qcom,cpr-timer-delay = <5000>;
+		qcom,cpr-timer-cons-up = <0>;
+		qcom,cpr-timer-cons-down = <2>;
+		qcom,cpr-irq-line = <0>;
+		qcom,cpr-step-quotient = <10>;
+		qcom,cpr-up-threshold = <2>;
+		qcom,cpr-down-threshold = <4>;
+		qcom,cpr-idle-clocks = <15>;
+		qcom,cpr-gcnt-time = <1>;
+		qcom,vdd-apc-step-up-limit = <1>;
+		qcom,vdd-apc-step-down-limit = <1>;
+		qcom,cpr-apc-volt-step = <5000>;
+
+		qcom,cpr-fuse-row = <67 0>;
+		qcom,cpr-fuse-target-quot = <42 24 6>;
+		qcom,cpr-fuse-ro-sel = <60 57 54>;
+		qcom,cpr-init-voltage-ref = <1155000 1225000 1350000>;
+		qcom,cpr-fuse-init-voltage =
+					<67 36 6 0>,
+					<67 18 6 0>,
+					<67  0 6 0>;
+		qcom,cpr-fuse-quot-offset =
+					<71 26 6 0>,
+					<71 20 6 0>,
+					<70 54 7 0>;
+		qcom,cpr-fuse-quot-offset-scale = <5 5 5>;
+		qcom,cpr-init-voltage-step = <10000>;
+		qcom,cpr-corner-map = <1 2 3 3 3 3 3>;
+		qcom,cpr-corner-frequency-map =
+				<1 960000000>,
+				<2 1094400000>,
+				<3 1209600000>,
+				<4 1248000000>,
+				<5 1344000000>,
+				<6 1401000000>,
+				<7 1497600000>;
+		qcom,speed-bin-fuse-sel = <37 34 3 0>;
+		qcom,cpr-speed-bin-max-corners =
+					<0 0 1 2 6>,
+					<1 0 1 2 7>,
+					<2 0 1 2 3>;
+		qcom,cpr-fuse-revision = <69 39 3 0>;
+		qcom,cpr-quot-adjust-scaling-factor-max = <0 1400 1400>;
+		qcom,cpr-voltage-scaling-factor-max = <0 2000 2000>;
+		qcom,cpr-scaled-init-voltage-as-ceiling;
+		qcom,cpr-fuse-version-map =
+			<0	(-1)	1	(-1)	(-1)	(-1)>,
+			<(-1)	(-1)	2	(-1)	(-1)	(-1)>,
+			<(-1)	(-1)	3	(-1)	(-1)	(-1)>,
+			<(-1)	(-1)  (-1)	(-1)	(-1)	(-1)>;
+		qcom,cpr-quotient-adjustment =
+				<(-20)	(-40)	(-20)>,
+				<0	(-40)	 (20)>,
+				<0	  0	 (20)>,
+				<0	  0	    0>;
+		qcom,cpr-init-voltage-adjustment =
+				<0		0	      0>,
+				<(10000)     (15000)	(20000)>,
+				<0		0	      0>,
+				<0		0	      0>;
+		qcom,cpr-enable;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-ion.dtsi b/arch/arm64/boot/dts/qcom/msm8937-ion.dtsi
index 823d99d..96e7166 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-ion.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-ion.dtsi
@@ -33,5 +33,11 @@
 			memory-region = <&qseecom_mem>;
 			qcom,ion-heap-type = "DMA";
 		};
+
+		qcom,ion-heap@19 { /* QSEECOM TA HEAP */
+			reg = <19>;
+			memory-region = <&qseecom_ta_mem>;
+			qcom,ion-heap-type = "DMA";
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
index 7fdcb2d..ab2a365 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-mdss-panels.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,14 +16,8 @@
 #include "dsi-panel-truly-1080p-cmd.dtsi"
 #include "dsi-panel-r69006-1080p-cmd.dtsi"
 #include "dsi-panel-r69006-1080p-video.dtsi"
-#include "dsi-panel-hx8394f-720p-video.dtsi"
 #include "dsi-adv7533-1080p.dtsi"
 #include "dsi-adv7533-720p.dtsi"
-#include "dsi-panel-truly-720p-video.dtsi"
-#include "dsi-panel-truly-wuxga-video.dtsi"
-#include "dsi-panel-truly-720p-cmd.dtsi"
-#include "dsi-panel-lead-fl10802-fwvga-video.dtsi"
-#include "dsi-panel-icn9706-720-1440p-video.dtsi"
 
 &soc {
 	dsi_panel_pwr_supply: dsi_panel_pwr_supply {
@@ -48,5 +42,23 @@
 			qcom,supply-disable-load = <100>;
 		};
 
+		qcom,panel-supply-entry@2 {
+			reg = <2>;
+			qcom,supply-name = "lab";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+
+		qcom,panel-supply-entry@3 {
+			reg = <3>;
+			qcom,supply-name = "ibb";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-post-on-sleep = <10>;
+		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8937-mdss.dtsi b/arch/arm64/boot/dts/qcom/msm8937-mdss.dtsi
index 07ff464..2c86c8f 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-mdss.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-mdss.dtsi
@@ -185,11 +185,11 @@
 
 		smmu_mdp_unsec: qcom,smmu_mdp_unsec_cb {
 			compatible = "qcom,smmu_mdp_unsec";
-			iommus = <&apps_iommu 0xC00 0>; /* For NS ctx bank */
+			iommus = <&apps_iommu 0x2800 0>; /* For NS ctx bank */
 		};
 		smmu_mdp_sec: qcom,smmu_mdp_sec_cb {
 			compatible = "qcom,smmu_mdp_sec";
-			iommus = <&apps_iommu 0xC01 0>; /* For SEC Ctx Bank */
+			iommus = <&apps_iommu 0x2801 0>; /* For SEC Ctx Bank */
 		};
 
 		mdss_fb0: qcom,mdss_fb_primary {
diff --git a/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi
index 4cd3568..f9af6cd 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-mtp.dtsi
@@ -11,6 +11,106 @@
  * GNU General Public License for more details.
  */
 
+#include "msm8937-pinctrl.dtsi"
 &blsp1_uart2 {
 	status = "ok";
+	pinctrl-names = "default";
+	pinctrl-0 = <&uart_console_active>;
 };
+
+&sdhc_1 {
+	/* device core power supply */
+	vdd-supply = <&pm8937_l8>;
+	qcom,vdd-voltage-level = <2900000 2900000>;
+	qcom,vdd-current-level = <200 570000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8937_l5>;
+	qcom,vdd-io-always-on;
+	qcom,vdd-io-lpm-sup;
+	qcom,vdd-io-voltage-level = <1800000 1800000>;
+	qcom,vdd-io-current-level = <200 325000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc1_clk_on &sdc1_cmd_on &sdc1_data_on &sdc1_rclk_on>;
+	pinctrl-1 = <&sdc1_clk_off &sdc1_cmd_off &sdc1_data_off &sdc1_rclk_off>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000 192000000
+								384000000>;
+	qcom,nonremovable;
+	qcom,bus-speed-mode = "HS400_1p8v", "HS200_1p8v", "DDR_1p8v";
+
+	status = "ok";
+};
+
+&sdhc_2 {
+	/* device core power supply */
+	vdd-supply = <&pm8937_l11>;
+	qcom,vdd-voltage-level = <2950000 2950000>;
+	qcom,vdd-current-level = <15000 800000>;
+
+	/* device communication power supply */
+	vdd-io-supply = <&pm8937_l12>;
+	qcom,vdd-io-voltage-level = <1800000 2950000>;
+	qcom,vdd-io-current-level = <200 22000>;
+
+	pinctrl-names = "active", "sleep";
+	pinctrl-0 = <&sdc2_clk_on &sdc2_cmd_on &sdc2_data_on &sdc2_cd_on>;
+	pinctrl-1 = <&sdc2_clk_off &sdc2_cmd_off &sdc2_data_off>;
+
+	cd-gpios = <&tlmm 67 0x1>;
+
+	qcom,clk-rates = <400000 20000000 25000000 50000000 100000000
+								200000000>;
+	qcom,bus-speed-mode = "SDR12", "SDR25", "SDR50", "DDR50", "SDR104";
+
+	status = "ok";
+};
+
+#include "msm8937-mdss-panels.dtsi"
+
+&mdss_mdp {
+	qcom,mdss-pref-prim-intf = "dsi";
+};
+
+&mdss_dsi {
+	hw-config = "single_dsi";
+};
+
+&mdss_dsi0 {
+	qcom,dsi-pref-prim-pan = <&dsi_truly_1080_vid>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	qcom,platform-bklight-en-gpio = <&tlmm 59 0>;
+};
+
+&mdss_dsi1 {
+	status = "disabled";
+	qcom,dsi-pref-prim-pan = <&dsi_adv7533_1080p>;
+	pinctrl-names = "mdss_default", "mdss_sleep";
+	pinctrl-0 = <&mdss_dsi_active &mdss_te_active>;
+	pinctrl-1 = <&mdss_dsi_suspend &mdss_te_suspend>;
+
+	qcom,pluggable;
+	qcom,platform-te-gpio = <&tlmm 24 0>;
+	qcom,platform-reset-gpio = <&tlmm 61 0>;
+	qcom,platform-bklight-en-gpio = <&tlmm 59 0>;
+};
+
+&dsi_truly_1080_vid {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,mdss-dsi-pan-enable-dynamic-fps;
+	qcom,mdss-dsi-pan-fps-update = "dfps_immediate_porch_mode_vfp";
+};
+
+&dsi_truly_1080_cmd {
+	qcom,panel-supply-entries = <&dsi_panel_pwr_supply>;
+	qcom,ulps-enabled;
+	qcom,partial-update-enabled;
+	qcom,panel-roi-alignment = <2 2 4 2 1080 2>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
index 17ee465..1b273ef 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pinctrl.dtsi
@@ -19,6 +19,7 @@
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
+		interrupt-parent = <&wakegpio>;
 		#interrupt-cells = <2>;
 
 		pmx-uartconsole {
@@ -369,6 +370,31 @@
 			};
 		};
 
+		cdc_mclk2_pin {
+			cdc_mclk2_sleep: cdc_mclk2_sleep {
+				mux {
+					pins = "gpio66";
+					function = "pri_mi2s";
+				};
+				config {
+					pins = "gpio66";
+					drive-strength = <2>; /* 2 mA */
+					bias-pull-down;       /* PULL DOWN */
+				};
+			};
+			cdc_mclk2_active: cdc_mclk2_active {
+				mux {
+					pins = "gpio66";
+					function = "pri_mi2s";
+				};
+				config {
+					pins = "gpio66";
+					drive-strength = <8>; /* 8 mA */
+					bias-disable;         /* NO PULL */
+				};
+			};
+		};
+
 		blsp2_uart1_active: blsp2_uart1_active {
 			mux {
 				pins = "gpio16", "gpio17", "gpio18", "gpio19";
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pm.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pm.dtsi
new file mode 100644
index 0000000..463ba63
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/msm8937-pm.dtsi
@@ -0,0 +1,268 @@
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/msm/pm.h>
+
+&soc {
+	qcom,spm@b1d2000 {
+		compatible = "qcom,spm-v2";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		reg = <0xb1d2000 0x1000>;
+		qcom,name = "system-cci";
+		qcom,saw2-ver-reg = <0xfd0>;
+		qcom,saw2-cfg = <0x14>;
+		qcom,saw2-spm-dly= <0x3C102800>;
+		qcom,saw2-spm-ctl = <0xe>;
+		qcom,cpu-vctl-list = <&CPU0 &CPU1 &CPU2 &CPU3
+				&CPU4 &CPU5 &CPU6 &CPU7>;
+		qcom,vctl-timeout-us = <500>;
+		qcom,vctl-port = <0x0>;
+		qcom,phase-port = <0x1>;
+		qcom,pfm-port = <0x2>;
+	};
+
+	qcom,lpm-levels {
+		compatible = "qcom,lpm-levels";
+		qcom,use-psci;
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		qcom,pm-cluster@0 {
+			reg = <0>;
+			#address-cells = <1>;
+			#size-cells = <0>;
+			label = "system";
+			qcom,psci-mode-shift = <8>;
+			qcom,psci-mode-mask = <0xf>;
+
+			qcom,pm-cluster-level@0{
+				reg = <0>;
+				label = "system-active";
+				qcom,psci-mode = <0>;
+				qcom,latency-us = <415>;
+				qcom,ss-power = <405>;
+				qcom,energy-overhead = <558549>;
+				qcom,time-overhead = <980>;
+			};
+
+			qcom,pm-cluster-level@1{
+				reg = <1>;
+				label = "system-wfi";
+				qcom,psci-mode = <1>;
+				qcom,latency-us = <475>;
+				qcom,ss-power = <346>;
+				qcom,energy-overhead = <718929>;
+				qcom,time-overhead = <1050>;
+				qcom,min-child-idx = <1>;
+			};
+
+			qcom,pm-cluster-level@2{
+				reg = <2>;
+				label = "system-ret";
+				qcom,psci-mode = <2>;
+				qcom,latency-us = <900>;
+				qcom,ss-power = <320>;
+				qcom,energy-overhead = <918687>;
+				qcom,time-overhead = <1250>;
+				qcom,min-child-idx = <1>;
+				qcom,reset-level = <LPM_RESET_LVL_RET>;
+			};
+
+			qcom,pm-cluster-level@3{
+				reg = <3>;
+				label = "system-pc";
+				qcom,psci-mode = <3>;
+				qcom,latency-us = <10782>;
+				qcom,ss-power = <306>;
+				qcom,energy-overhead = <1060040>;
+				qcom,time-overhead = <1426>;
+				qcom,min-child-idx = <2>;
+				qcom,notify-rpm;
+				qcom,is-reset;
+				qcom,reset-level = <LPM_RESET_LVL_PC>;
+			};
+
+			qcom,pm-cluster@0{
+				reg = <0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				label = "perf";
+				qcom,psci-mode-shift = <4>;
+				qcom,psci-mode-mask = <0xf>;
+
+				qcom,pm-cluster-level@0{
+					reg = <0>;
+					label = "perf-l2-wfi";
+					qcom,psci-mode = <1>;
+					qcom,latency-us = <210>;
+					qcom,ss-power = <472>;
+					qcom,energy-overhead = <233383>;
+					qcom,time-overhead = <326>;
+				};
+
+				qcom,pm-cluster-level@1{
+					reg = <1>;
+					label = "perf-l2-gdhs";
+					qcom,psci-mode = <4>;
+					qcom,latency-us = <267>;
+					qcom,ss-power = <435>;
+					qcom,energy-overhead = <388012>;
+					qcom,time-overhead = <627>;
+					qcom,min-child-idx = <1>;
+					qcom,reset-level = <LPM_RESET_LVL_GDHS>;
+				};
+
+				qcom,pm-cluster-level@2{
+					reg = <2>;
+					label = "perf-l2-pc";
+					qcom,psci-mode = <5>;
+					qcom,latency-us = <305>;
+					qcom,ss-power = <405>;
+					qcom,energy-overhead = <564794>;
+					qcom,time-overhead = <879>;
+					qcom,min-child-idx = <1>;
+					qcom,is-reset;
+					qcom,reset-level = <LPM_RESET_LVL_PC>;
+				};
+
+				qcom,pm-cpu {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					qcom,psci-mode-shift = <0>;
+					qcom,psci-mode-mask = <0xf>;
+					qcom,cpu = <&CPU0 &CPU1 &CPU2 &CPU3>;
+
+					qcom,pm-cpu-level@0 {
+						reg = <0>;
+						qcom,psci-cpu-mode = <0>;
+						label = "wfi";
+						qcom,latency-us = <1>;
+						qcom,ss-power = <530>;
+						qcom,energy-overhead = <62806>;
+						qcom,time-overhead = <67>;
+					};
+
+					qcom,pm-cpu-level@1 {
+						reg = <1>;
+						qcom,psci-cpu-mode = <3>;
+						label = "pc";
+						qcom,latency-us = <190>;
+						qcom,ss-power = <472>;
+						qcom,energy-overhead = <233383>;
+						qcom,time-overhead = <326>;
+						qcom,use-broadcast-timer;
+						qcom,is-reset;
+						qcom,reset-level =
+							<LPM_RESET_LVL_PC>;
+					};
+				};
+			};
+
+			qcom,pm-cluster@1{
+				reg = <1>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				label = "pwr";
+				qcom,psci-mode-shift = <4>;
+				qcom,psci-mode-mask = <0xf>;
+
+				qcom,pm-cluster-level@0{
+					reg = <0>;
+					label = "pwr-l2-wfi";
+					qcom,psci-mode = <1>;
+					qcom,latency-us = <221>;
+					qcom,ss-power = <460>;
+					qcom,energy-overhead = <219499>;
+					qcom,time-overhead = <400>;
+				};
+
+				qcom,pm-cluster-level@1{
+					reg = <1>;
+					label = "pwr-l2-gdhs";
+					qcom,psci-mode = <4>;
+					qcom,latency-us = <337>;
+					qcom,ss-power = <433>;
+					qcom,energy-overhead = <372429>;
+					qcom,time-overhead = <717>;
+					qcom,min-child-idx = <1>;
+					qcom,reset-level =
+						<LPM_RESET_LVL_GDHS>;
+				};
+
+				qcom,pm-cluster-level@2{
+					reg = <2>;
+					label = "pwr-l2-pc";
+					qcom,psci-mode = <5>;
+					qcom,latency-us = <415>;
+					qcom,ss-power = <405>;
+					qcom,energy-overhead = <558549>;
+					qcom,time-overhead = <980>;
+					qcom,min-child-idx = <1>;
+					qcom,is-reset;
+					qcom,reset-level =
+						<LPM_RESET_LVL_PC>;
+				};
+
+				qcom,pm-cpu {
+					#address-cells = <1>;
+					#size-cells = <0>;
+					qcom,psci-mode-shift = <0>;
+					qcom,psci-mode-mask = <0xf>;
+					qcom,cpu = <&CPU4 &CPU5 &CPU6 &CPU7>;
+
+					qcom,pm-cpu-level@0 {
+						reg = <0>;
+						qcom,psci-cpu-mode = <0>;
+						label = "wfi";
+						qcom,latency-us = <1>;
+						qcom,ss-power = <540>;
+						qcom,energy-overhead = <93024>;
+						qcom,time-overhead = <57>;
+					};
+
+					qcom,pm-cpu-level@1 {
+						reg = <1>;
+						qcom,psci-cpu-mode = <3>;
+						label = "pc";
+						qcom,latency-us = <221>;
+						qcom,ss-power = <460>;
+						qcom,energy-overhead = <219499>;
+						qcom,time-overhead = <400>;
+						qcom,use-broadcast-timer;
+						qcom,is-reset;
+						qcom,reset-level =
+							<LPM_RESET_LVL_PC>;
+					};
+				};
+			};
+		};
+	};
+
+	qcom,rpm-stats@200000 {
+		compatible = "qcom,rpm-stats";
+		reg = <0x200000 0x1000>,
+		      <0x290014 0x4>,
+		      <0x29001c 0x4>;
+		reg-names = "phys_addr_base", "offset_addr",
+						"heap_phys_addrbase";
+		qcom,sleep-stats-version = <2>;
+	};
+
+	qcom,rpm-master-stats@60150 {
+		compatible = "qcom,rpm-master-stats";
+		reg = <0x60150 0x5000>;
+		qcom,masters = "APSS", "MPSS", "PRONTO", "TZ", "LPASS";
+		qcom,master-stats-version = <2>;
+		qcom,master-offset = <4096>;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
index 3da16e4..1afa230 100644
--- a/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937-pmi8950-mtp.dtsi
@@ -14,17 +14,6 @@
 #include "pmi8950.dtsi"
 #include "msm8937-mtp.dtsi"
 
-&soc {
-	led_flash0: qcom,camera-flash {
-		cell-index = <0>;
-		compatible = "qcom,camera-flash";
-		qcom,flash-type = <1>;
-		qcom,flash-source = <&pmi8950_flash0 &pmi8950_flash1>;
-		qcom,torch-source = <&pmi8950_torch0 &pmi8950_torch1>;
-		qcom,switch-source = <&pmi8950_switch>;
-	};
-};
-
 &vendor {
 	mtp_batterydata: qcom,battery-data {
 		qcom,batt-id-range-pct = <15>;
@@ -44,6 +33,10 @@
 	/delete-property/ dpdm-supply;
 };
 
+&usb_otg {
+	extcon = <&qpnp_smbcharger>;
+};
+
 &labibb {
 	status = "ok";
 	qpnp,qpnp-labibb-mode = "lcd";
@@ -52,3 +45,13 @@
 &ibb_regulator {
 	qcom,qpnp-ibb-discharge-resistor = <32>;
 };
+
+&mdss_dsi0 {
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+};
+
+&mdss_dsi1 {
+	lab-supply = <&lab_regulator>;
+	ibb-supply = <&ibb_regulator>;
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8937.dtsi b/arch/arm64/boot/dts/qcom/msm8937.dtsi
index 61688b7..b498236 100644
--- a/arch/arm64/boot/dts/qcom/msm8937.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8937.dtsi
@@ -21,12 +21,38 @@
 	model = "Qualcomm Technologies, Inc. MSM8937";
 	compatible = "qcom,msm8937";
 	qcom,msm-id = <294 0x0>;
-	interrupt-parent = <&intc>;
+	interrupt-parent = <&wakegic>;
 
 	chosen {
 		bootargs = "sched_enable_hmp=1";
 	};
 
+	firmware: firmware {
+		android {
+			compatible = "android,firmware";
+			fstab {
+				compatible = "android,fstab";
+				vendor {
+					compatible = "android,vendor";
+					dev = "/dev/block/platform/soc/7824900.sdhci/by-name/vendor";
+					type = "ext4";
+					mnt_flags = "ro,barrier=1,discard";
+					fsmgr_flags = "wait";
+					status = "ok";
+				};
+				system {
+					compatible = "android,system";
+					dev = "/dev/block/platform/soc/7824900.sdhci/by-name/system";
+					type = "ext4";
+					mnt_flags = "ro,barrier=1,discard";
+					fsmgr_flags = "wait";
+					status = "ok";
+				};
+
+			};
+		};
+	};
+
 	reserved-memory {
 		#address-cells = <2>;
 		#size-cells = <2>;
@@ -79,6 +105,14 @@
 			size = <0 0x1000000>;
 		};
 
+		qseecom_ta_mem: qseecom_ta_region {
+			 compatible = "shared-dma-pool";
+			 alloc-ranges = <0 0x00000000 0 0xffffffff>;
+			 reusable;
+			 alignment = <0 0x400000>;
+			 size = <0 0x1000000>;
+		};
+
 		adsp_mem: adsp_region@0 {
 			compatible = "shared-dma-pool";
 			reusable;
@@ -109,6 +143,8 @@
 		i2c5 = &i2c_5;
 		spi3 = &spi_3;
 		i2c3 = &i2c_3;
+		sdhc1 = &sdhc_1; /* SDC1 eMMC slot */
+		sdhc2 = &sdhc_2; /* SDC2 for SD card */
 	};
 
 	soc: soc { };
@@ -126,8 +162,13 @@
 #include "msm8937-pinctrl.dtsi"
 #include "msm8937-cpu.dtsi"
 #include "msm8937-ion.dtsi"
+#include "msm-arm-smmu-8937.dtsi"
 #include "msm8937-smp2p.dtsi"
 #include "msm8937-bus.dtsi"
+#include "msm8937-pm.dtsi"
+#include "msm8937-gpu.dtsi"
+#include "msm8937-mdss.dtsi"
+#include "msm8937-mdss-pll.dtsi"
 
 &soc {
 	#address-cells = <1>;
@@ -138,11 +179,31 @@
 	intc: interrupt-controller@b000000 {
 		compatible = "qcom,msm-qgic2";
 		interrupt-controller;
+		interrupt-parent = <&intc>;
 		#interrupt-cells = <3>;
 		reg = <0x0b000000 0x1000>,
 		      <0x0b002000 0x1000>;
 	};
 
+	wakegic: wake-gic {
+		compatible = "qcom,mpm-gic-msm8937", "qcom,mpm-gic";
+		interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
+		reg = <0x601d0 0x1000>,
+			<0xb011008 0x4>;  /* MSM_APCS_GCC_BASE 4K */
+		reg-names = "vmpm", "ipc";
+		qcom,num-mpm-irqs = <96>;
+		interrupt-controller;
+		interrupt-parent = <&intc>;
+		#interrupt-cells = <3>;
+	};
+
+	wakegpio: wake-gpio {
+		compatible = "qcom,mpm-gpio-msm8937", "qcom,mpm-gpio";
+		interrupt-controller;
+		interrupt-parent = <&intc>;
+		#interrupt-cells = <2>;
+	};
+
 	timer {
 		compatible = "arm,armv8-timer";
 		interrupts = <1 2 0xff08>,
@@ -426,6 +487,9 @@
 		compatible = "qcom,msm-uartdm-v1.4", "qcom,msm-uartdm";
 		reg = <0x78b0000 0x200>;
 		interrupts = <0 108 0>;
+		clocks = <&clock_gcc clk_gcc_blsp1_uart2_apps_clk>,
+		<&clock_gcc clk_gcc_blsp1_ahb_clk>;
+		clock-names = "core", "iface";
 		status = "disabled";
 	};
 
@@ -479,6 +543,17 @@
 		#clock-cells = <1>;
 	};
 
+	clock_gcc_mdss: qcom,gcc-mdss@1800000 {
+		compatible = "qcom,gcc-mdss-8937";
+		clocks = <&mdss_dsi0_pll clk_dsi_pll0_pixel_clk_src>,
+			 <&mdss_dsi0_pll clk_dsi_pll0_byte_clk_src>,
+			 <&mdss_dsi1_pll clk_dsi_pll1_pixel_clk_src>,
+			 <&mdss_dsi1_pll clk_dsi_pll1_byte_clk_src>;
+		clock-names = "pclk0_src", "byte0_src", "pclk1_src",
+			"byte1_src";
+		#clock-cells = <1>;
+	};
+
 	clock_cpu: qcom,cpu-clock-8939@b111050 {
 		compatible = "qcom,cpu-clock-8939";
 		reg =   <0xb011050 0x8>,
@@ -664,6 +739,50 @@
 		status = "disabled";
 	};
 
+	msm_cpufreq: qcom,msm-cpufreq {
+		compatible = "qcom,msm-cpufreq";
+		clock-names = "l2_clk", "cpu0_clk", "cpu1_clk", "cpu2_clk",
+				"cpu3_clk", "cpu4_clk", "cpu5_clk",
+				"cpu6_clk", "cpu7_clk";
+		clocks = <&clock_cpu clk_cci_clk>,
+			 <&clock_cpu clk_a53_bc_clk>,
+			 <&clock_cpu clk_a53_bc_clk>,
+			 <&clock_cpu clk_a53_bc_clk>,
+			 <&clock_cpu clk_a53_bc_clk>,
+			 <&clock_cpu clk_a53_lc_clk>,
+			 <&clock_cpu clk_a53_lc_clk>,
+			 <&clock_cpu clk_a53_lc_clk>,
+			 <&clock_cpu clk_a53_lc_clk>;
+
+		qcom,governor-per-policy;
+
+		qcom,cpufreq-table-0 =
+			 <  960000 >,
+			 < 1094400 >,
+			 < 1209600 >,
+			 < 1248000 >,
+			 < 1344000 >,
+			 < 1401000 >,
+			 < 1497600 >;
+
+		qcom,cpufreq-table-4 =
+			 <  768000 >,
+			 <  902400 >,
+			 <  998400 >,
+			 < 1094400 >,
+			 < 1209600 >;
+	};
+
+	cci_cache: qcom,cci {
+		compatible = "devfreq-simple-dev";
+		clock-names = "devfreq_clk";
+		clocks = <&clock_cpu clk_cci_clk>;
+		governor = "cpufreq";
+		freq-tbl-khz =
+			<  400000 >,
+			<  533333 >;
+	};
+
 	cpubw: qcom,cpubw {
 		compatible = "qcom,devbw";
 		governor = "cpufreq";
@@ -709,6 +828,48 @@
 			<  7031 /*  921.6 MHz */ >;     /* TURBO */
 	};
 
+	devfreq-cpufreq {
+		cpubw-cpufreq {
+		target-dev = <&cpubw>;
+		cpu-to-dev-map-0 =
+			<  998400  2929 >,      /* SVS   */
+			< 1094400  5053 >,	/* NOM   */
+			< 1248000  5712 >,	/* NOM+  */
+			< 1344000  7031 >,
+			< 1497600  7031 >;	/* TURBO */
+		cpu-to-dev-map-4 =
+			<  806400  2929 >,	/* SVS  */
+			<  902400  5053 >,	/* NOM   */
+			<  998400  6152 >,	/* NOM+  */
+			< 1209600  7031 >;	/* TURBO */
+		};
+
+		cci-cpufreq {
+		target-dev = <&cci_cache>;
+		cpu-to-dev-map-0 =
+			<  998400  400000 >,    /* SVS   */
+			< 1094400  400000 >,	/* NOM   */
+			< 1248000  533333 >,	/* NOM+  */
+			< 1344000  533333 >,
+			< 1497600  533333 >;	/* TURBO */
+		cpu-to-dev-map-4 =
+			<  806400  400000 >,	/* SVS  */
+			<  902400  400000 >,	/* NOM   */
+			<  998400  533333 >,	/* NOM+  */
+			< 1209600  533333 >;	/* TURBO */
+		};
+
+		mincpubw-cpufreq {
+			target-dev = <&mincpubw>;
+			cpu-to-dev-map-0 =
+				< 1094400 2929 >,
+				< 1497600 4248 >;
+			cpu-to-dev-map-4 =
+				<  998400 2929 >,
+				< 1209600 4248 >;
+		};
+	};
+
 	blsp2_uart1: uart@7aef000 {
 		compatible = "qcom,msm-hsuart-v14";
 		reg = <0x7aef000 0x200>,
@@ -1157,13 +1318,503 @@
 		compatible = "qcom,msm-adsprpc-mem-region";
 		memory-region = <&adsp_mem>;
 	};
+	qcom,msm_fastrpc {
+		compatible = "qcom,msm-fastrpc-legacy-compute";
+		qcom,msm_fastrpc_compute_cb {
+			compatible = "qcom,msm-fastrpc-legacy-compute-cb";
+			label = "adsprpc-smd";
+			iommus = <&apps_iommu 0x2008 0x7>;
+			sids = <0x8 0x9 0xa 0xb 0xc 0xd 0xe 0xf>;
+		};
+	};
+
+	sdcc1_ice: sdcc1ice@7803000 {
+		compatible = "qcom,ice";
+		reg = <0x7803000 0x8000>;
+		interrupt-names = "sdcc_ice_nonsec_level_irq",
+				  "sdcc_ice_sec_level_irq";
+		interrupts = <0 312 0>, <0 313 0>;
+		qcom,enable-ice-clk;
+		clock-names = "ice_core_clk_src", "ice_core_clk",
+				"bus_clk", "iface_clk";
+		clocks = <&clock_gcc clk_sdcc1_ice_core_clk_src>,
+			 <&clock_gcc clk_gcc_sdcc1_ice_core_clk>,
+			 <&clock_gcc clk_gcc_sdcc1_apps_clk>,
+			 <&clock_gcc clk_gcc_sdcc1_ahb_clk>;
+		qcom,op-freq-hz = <200000000>, <0>, <0>, <0>;
+		qcom,msm-bus,name = "sdcc_ice_noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<78 512 0 0>,    /* No vote */
+			<78 512 1000 0>; /* Max. bandwidth */
+		qcom,bus-vector-names = "MIN", "MAX";
+		qcom,instance-type = "sdcc";
+	};
+
+	sdhc_1: sdhci@7824900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0x7824900 0x500>, <0x7824000 0x800>, <0x7824e00 0x200>;
+		reg-names = "hc_mem", "core_mem", "cmdq_mem";
+
+		interrupts = <0 123 0>, <0 138 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		sdhc-msm-crypto = <&sdcc1_ice>;
+		qcom,bus-width = <8>;
+		qcom,large-address-bus;
+
+		qcom,devfreq,freq-table = <50000000 200000000>;
+
+		qcom,pm-qos-irq-type = "affine_irq";
+		qcom,pm-qos-irq-latency = <2 200>;
+
+		qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+		qcom,pm-qos-cmdq-latency-us = <2 200>, <2 200>;
+
+		qcom,pm-qos-legacy-latency-us = <2 200>, <2 200>;
+
+		qcom,msm-bus,name = "sdhc1";
+		qcom,msm-bus,num-cases = <9>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <78 512 0 0>, /* No vote */
+			<78 512 1046 3200>,    /* 400 KB/s*/
+			<78 512 52286 160000>, /* 20 MB/s */
+			<78 512 65360 200000>, /* 25 MB/s */
+			<78 512 130718 400000>, /* 50 MB/s */
+			<78 512 130718 400000>, /* 100 MB/s */
+			<78 512 261438 800000>, /* 200 MB/s */
+			<78 512 261438 800000>, /* 400 MB/s */
+			<78 512 1338562 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000
+			50000000 100000000 200000000 400000000 4294967295>;
+
+		clocks = <&clock_gcc clk_gcc_sdcc1_ahb_clk>,
+			 <&clock_gcc clk_gcc_sdcc1_apps_clk>,
+			 <&clock_gcc clk_gcc_sdcc1_ice_core_clk>;
+		clock-names = "iface_clk", "core_clk", "ice_core_clk";
+		qcom,ice-clk-rates = <200000000 100000000>;
+
+		qcom,scaling-lower-bus-speed-mode = "DDR52";
+		status = "disabled";
+	};
+
+	sdhc_2: sdhci@7864900 {
+		compatible = "qcom,sdhci-msm";
+		reg = <0x7864900 0x500>, <0x7864000 0x800>;
+		reg-names = "hc_mem", "core_mem";
+
+		interrupts = <0 125 0>, <0 221 0>;
+		interrupt-names = "hc_irq", "pwr_irq";
+
+		qcom,bus-width = <4>;
+		qcom,large-address-bus;
+
+		qcom,pm-qos-irq-type = "affine_irq";
+		qcom,pm-qos-irq-latency = <2 200>;
+
+		qcom,pm-qos-cpu-groups = <0x0f 0xf0>;
+		qcom,pm-qos-legacy-latency-us = <2 200>, <2 200>;
+
+		qcom,msm-bus,name = "sdhc2";
+		qcom,msm-bus,num-cases = <8>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps = <81 512 0 0>, /* No vote */
+			<81 512 1046 3200>,    /* 400 KB/s*/
+			<81 512 52286 160000>, /* 20 MB/s */
+			<81 512 65360 200000>, /* 25 MB/s */
+			<81 512 130718 400000>, /* 50 MB/s */
+			<81 512 261438 800000>, /* 100 MB/s */
+			<81 512 261438 800000>, /* 200 MB/s */
+			<81 512 1338562 4096000>; /* Max. bandwidth */
+		qcom,bus-bw-vectors-bps = <0 400000 20000000 25000000 50000000
+			100000000 200000000 4294967295>;
+
+		qcom,devfreq,freq-table = <50000000 200000000>;
+		clocks = <&clock_gcc clk_gcc_sdcc2_ahb_clk>,
+			<&clock_gcc clk_gcc_sdcc2_apps_clk>;
+		clock-names = "iface_clk", "core_clk";
+
+		status = "disabled";
+	};
+
+	qcom_seecom: qseecom@85b00000 {
+		compatible = "qcom,qseecom";
+		reg = <0x85b00000 0x800000>;
+		reg-names = "secapp-region";
+		qcom,hlos-num-ce-hw-instances = <1>;
+		qcom,hlos-ce-hw-instance = <0>;
+		qcom,qsee-ce-hw-instance = <0>;
+		qcom,disk-encrypt-pipe-pair = <2>;
+		qcom,support-fde;
+		qcom,msm-bus,name = "qseecom-noc";
+		qcom,msm-bus,num-cases = <4>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,support-bus-scaling;
+		qcom,msm-bus,vectors-KBps =
+			<55 512 0 0>,
+			<55 512 0 0>,
+			<55 512 120000 1200000>,
+			<55 512 393600 3936000>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			<&clock_gcc clk_gcc_crypto_clk>,
+			<&clock_gcc clk_gcc_crypto_ahb_clk>,
+			<&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+			"iface_clk", "bus_clk";
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	qcom_rng: qrng@e3000 {
+		compatible = "qcom,msm-rng";
+		reg = <0xe3000 0x1000>;
+		qcom,msm-rng-iface-clk;
+		qcom,no-qrng-config;
+		qcom,msm-bus,name = "msm-rng-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+			<1 618 0 0>,            /* No vote */
+			<1 618 0 800>;          /* 100 MB/s */
+		clocks = <&clock_gcc clk_gcc_prng_ahb_clk>;
+		clock-names = "iface_clk";
+	};
+
+	qcom_crypto: qcrypto@720000 {
+		compatible = "qcom,qcrypto";
+		reg = <0x720000 0x20000>,
+			<0x704000 0x20000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <2>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		qcom,ce-hw-shared;
+		qcom,clk-mgmt-sus-res;
+		qcom,msm-bus,name = "qcrypto-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<55 512 0 0>,
+				<55 512 393600 393600>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,use-sw-aes-cbc-ecb-ctr-algo;
+		qcom,use-sw-aes-xts-algo;
+		qcom,use-sw-aes-ccm-algo;
+		qcom,use-sw-ahash-algo;
+		qcom,use-sw-hmac-algo;
+		qcom,use-sw-aead-algo;
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	qcom_cedev: qcedev@720000 {
+		compatible = "qcom,qcedev";
+		reg = <0x720000 0x20000>,
+			<0x704000 0x20000>;
+		reg-names = "crypto-base","crypto-bam-base";
+		interrupts = <0 207 0>;
+		qcom,bam-pipe-pair = <1>;
+		qcom,ce-hw-instance = <0>;
+		qcom,ce-device = <0>;
+		qcom,ce-hw-shared;
+		qcom,msm-bus,name = "qcedev-noc";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<55 512 0 0>,
+				<55 512 393600 393600>;
+		clocks = <&clock_gcc clk_crypto_clk_src>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>;
+		clock-names = "core_clk_src", "core_clk",
+				"iface_clk", "bus_clk";
+		qcom,ce-opp-freq = <100000000>;
+	};
+
+	pil_mss: qcom,mss@4080000 {
+		compatible = "qcom,pil-q6v55-mss";
+		reg = <0x04080000 0x100>,
+		      <0x0194f000 0x010>,
+		      <0x01950000 0x008>,
+		      <0x01951000 0x008>,
+		      <0x04020000 0x040>,
+		      <0x01871000 0x004>;
+		reg-names = "qdsp6_base", "halt_q6", "halt_modem", "halt_nc",
+				 "rmb_base", "restart_reg";
+
+		interrupts = <GIC_SPI 24 IRQ_TYPE_EDGE_RISING>;
+		vdd_mss-supply = <&pm8937_s1>;
+		vdd_cx-supply = <&pm8937_s2_level>;
+		vdd_cx-voltage = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+		vdd_mx-supply = <&pm8937_l3_level_ao>;
+		vdd_mx-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+		vdd_pll-supply = <&pm8937_l7>;
+		qcom,vdd_pll = <1800000>;
+		vdd_mss-uV = <RPM_SMD_REGULATOR_LEVEL_TURBO>;
+
+		clocks = <&clock_gcc clk_xo_pil_mss_clk>,
+			 <&clock_gcc clk_gcc_mss_cfg_ahb_clk>,
+			 <&clock_gcc clk_gcc_mss_q6_bimc_axi_clk>,
+			 <&clock_gcc clk_gcc_boot_rom_ahb_clk>;
+		clock-names = "xo", "iface_clk", "bus_clk", "mem_clk";
+		qcom,proxy-clock-names = "xo";
+		qcom,active-clock-names = "iface_clk", "bus_clk", "mem_clk";
+
+		qcom,pas-id = <5>;
+		qcom,pil-mss-memsetup;
+		qcom,firmware-name = "modem";
+		qcom,pil-self-auth;
+		qcom,override-acc-1 = <0x80800000>;
+		qcom,sysmon-id = <0>;
+		qcom,ssctl-instance-id = <0x12>;
+		qcom,qdsp6v56-1-8-inrush-current;
+		qcom,reset-clk;
+
+		/* GPIO inputs from mss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_1_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_1_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_1_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_1_in 3 0>;
+		qcom,gpio-shutdown-ack = <&smp2pgpio_ssr_smp2p_1_in 7 0>;
+
+		/* GPIO output to mss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_1_out 0 0>;
+
+		memory-region = <&modem_mem>;
+	};
+
+	qcom,lpass@c200000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0xc200000 0x00100>;
+		interrupts = <GIC_SPI 293 IRQ_TYPE_EDGE_RISING>;
+
+		vdd_cx-supply = <&pm8937_s2_level>;
+		qcom,proxy-reg-names = "vdd_cx";
+		qcom,vdd_cx-uV-uA = <RPM_SMD_REGULATOR_LEVEL_TURBO 100000>;
+
+		clocks = <&clock_gcc clk_xo_pil_lpass_clk>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>,
+			 <&clock_gcc clk_crypto_clk_src>;
+		clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+		qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+				 "scm_bus_clk", "scm_core_clk_src";
+		qcom,scm_core_clk_src-freq = <80000000>;
+
+		qcom,mas-crypto = <&mas_crypto>;
+		qcom,pas-id = <1>;
+		qcom,proxy-timeout-ms = <10000>;
+		qcom,smem-id = <423>;
+		qcom,sysmon-id = <1>;
+		qcom,ssctl-instance-id = <0x14>;
+		qcom,firmware-name = "adsp";
+
+		/* GPIO inputs from lpass */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_2_in 0 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_2_in 2 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_2_in 1 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_2_in 3 0>;
+
+		/* GPIO output to lpass */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_2_out 0 0>;
+
+		memory-region = <&adsp_fw_mem>;
+	};
+
+	qcom,pronto@a21b000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x0a21b000 0x3000>;
+		interrupts = <GIC_SPI 149 IRQ_TYPE_EDGE_RISING>;
+
+		vdd_pronto_pll-supply = <&pm8937_l7>;
+		proxy-reg-names = "vdd_pronto_pll";
+		vdd_pronto_pll-uV-uA = <1800000 18000>;
+		clocks = <&clock_gcc clk_xo_pil_pronto_clk>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>,
+			 <&clock_gcc clk_crypto_clk_src>;
+
+		clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+		qcom,proxy-clock-names = "xo", "scm_core_clk", "scm_iface_clk",
+				 "scm_bus_clk", "scm_core_clk_src";
+		qcom,scm_core_clk_src = <80000000>;
+
+		qcom,mas-crypto = <&mas_crypto>;
+		qcom,pas-id = <6>;
+		qcom,proxy-timeout-ms = <10000>;
+		qcom,smem-id = <422>;
+		qcom,sysmon-id = <6>;
+		qcom,ssctl-instance-id = <0x13>;
+		qcom,firmware-name = "wcnss";
+
+		/* GPIO inputs from wcnss */
+		qcom,gpio-err-fatal = <&smp2pgpio_ssr_smp2p_4_in 0 0>;
+		qcom,gpio-err-ready = <&smp2pgpio_ssr_smp2p_4_in 1 0>;
+		qcom,gpio-proxy-unvote = <&smp2pgpio_ssr_smp2p_4_in 2 0>;
+		qcom,gpio-stop-ack = <&smp2pgpio_ssr_smp2p_4_in 3 0>;
+
+		/* GPIO output to wcnss */
+		qcom,gpio-force-stop = <&smp2pgpio_ssr_smp2p_4_out 0 0>;
+		memory-region = <&wcnss_fw_mem>;
+	};
+
+	qcom,venus@1de0000 {
+		compatible = "qcom,pil-tz-generic";
+		reg = <0x1de0000 0x4000>;
+
+		vdd-supply = <&gdsc_venus>;
+		qcom,proxy-reg-names = "vdd";
+
+		clocks = <&clock_gcc clk_gcc_venus0_vcodec0_clk>,
+			 <&clock_gcc clk_gcc_venus0_ahb_clk>,
+			 <&clock_gcc clk_gcc_venus0_axi_clk>,
+			 <&clock_gcc clk_gcc_crypto_clk>,
+			 <&clock_gcc clk_gcc_crypto_ahb_clk>,
+			 <&clock_gcc clk_gcc_crypto_axi_clk>,
+			 <&clock_gcc clk_crypto_clk_src>;
+
+		clock-names = "core_clk", "iface_clk", "bus_clk",
+				"scm_core_clk", "scm_iface_clk",
+				"scm_bus_clk", "scm_core_clk_src";
+
+		qcom,proxy-clock-names = "core_clk", "iface_clk",
+					 "bus_clk", "scm_core_clk",
+					 "scm_iface_clk", "scm_bus_clk",
+					 "scm_core_clk_src";
+		qcom,scm_core_clk_src-freq = <80000000>;
+
+		qcom,msm-bus,name = "pil-venus";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <1>;
+		qcom,msm-bus,vectors-KBps =
+				<63 512 0 0>,
+				<63 512 0 304000>;
+
+		qcom,mas-crypto = <&mas_crypto>;
+		qcom,pas-id = <9>;
+		qcom,proxy-timeout-ms = <100>;
+		qcom,firmware-name = "venus";
+		memory-region = <&venus_mem>;
+	};
+
+	qcom,wcnss-wlan@0a000000 {
+		compatible = "qcom,wcnss_wlan";
+		reg = <0x0a000000 0x280000>,
+		      <0xb011008 0x04>,
+		      <0x0a21b000 0x3000>,
+		      <0x03204000 0x00000100>,
+		      <0x03200800 0x00000200>,
+		      <0x0a100400 0x00000200>,
+		      <0x0a205050 0x00000200>,
+		      <0x0a219000 0x00000020>,
+		      <0x0a080488 0x00000008>,
+		      <0x0a080fb0 0x00000008>,
+		      <0x0a08040c 0x00000008>,
+		      <0x0a0120a8 0x00000008>,
+		      <0x0a012448 0x00000008>,
+		      <0x0a080c00 0x00000001>;
+
+		reg-names = "wcnss_mmio", "wcnss_fiq",
+			    "pronto_phy_base", "riva_phy_base",
+			    "riva_ccu_base", "pronto_a2xb_base",
+			    "pronto_ccpu_base", "pronto_saw2_base",
+			    "wlan_tx_phy_aborts","wlan_brdg_err_source",
+			    "wlan_tx_status", "alarms_txctl",
+			    "alarms_tactl", "pronto_mcu_base";
+
+		interrupts = <0 145 0 0 146 0>;
+		interrupt-names = "wcnss_wlantx_irq", "wcnss_wlanrx_irq";
+
+		qcom,pronto-vddmx-supply = <&pm8937_l3_level_ao>;
+		qcom,pronto-vddcx-supply = <&pm8937_s2_level>;
+		qcom,pronto-vddpx-supply = <&pm8937_l5>;
+		qcom,iris-vddxo-supply   = <&pm8937_l7>;
+		qcom,iris-vddrfa-supply  = <&pm8937_l19>;
+		qcom,iris-vddpa-supply   = <&pm8937_l9>;
+		qcom,iris-vdddig-supply  = <&pm8937_l5>;
+
+		qcom,iris-vddxo-voltage-level = <1800000 0 1800000>;
+		qcom,iris-vddrfa-voltage-level = <1300000 0 1300000>;
+		qcom,iris-vddpa-voltage-level = <3300000 0 3300000>;
+		qcom,iris-vdddig-voltage-level = <1800000 0 1800000>;
+
+		qcom,vddmx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_TURBO
+					RPM_SMD_REGULATOR_LEVEL_NONE
+					RPM_SMD_REGULATOR_LEVEL_TURBO>;
+		qcom,vddcx-voltage-level = <RPM_SMD_REGULATOR_LEVEL_NOM
+					RPM_SMD_REGULATOR_LEVEL_NONE
+					RPM_SMD_REGULATOR_LEVEL_BINNING>;
+		qcom,vddpx-voltage-level = <1800000 0 1800000>;
+
+		qcom,iris-vddxo-current = <10000>;
+		qcom,iris-vddrfa-current = <100000>;
+		qcom,iris-vddpa-current = <515000>;
+		qcom,iris-vdddig-current = <10000>;
+
+		qcom,pronto-vddmx-current = <0>;
+		qcom,pronto-vddcx-current = <0>;
+		qcom,pronto-vddpx-current = <0>;
+
+		pinctrl-names = "wcnss_default", "wcnss_sleep",
+				"wcnss_gpio_default";
+		pinctrl-0 = <&wcnss_default>;
+		pinctrl-1 = <&wcnss_sleep>;
+		pinctrl-2 = <&wcnss_gpio_default>;
+
+		gpios = <&tlmm 76 0>, <&tlmm 77 0>, <&tlmm 78 0>,
+			<&tlmm 79 0>, <&tlmm 80 0>;
+
+		clocks = <&clock_gcc clk_xo_wlan_clk>,
+			 <&clock_gcc clk_rf_clk2>,
+			 <&clock_debug clk_gcc_debug_mux_8937>,
+			 <&clock_gcc clk_wcnss_m_clk>,
+			 <&clock_gcc clk_snoc_wcnss_a_clk>;
+
+		clock-names = "xo", "rf_clk", "measure", "wcnss_debug",
+				"snoc_wcnss";
+
+		qcom,snoc-wcnss-clock-freq = <200000000>;
+
+		qcom,has-autodetect-xo;
+		qcom,is-pronto-v3;
+		qcom,has-pronto-hw;
+		qcom,has-vsys-adc-channel;
+		qcom,wcnss-adc_tm = <&pm8937_adc_tm>;
+	};
+
+	bam_dmux: qcom,bam_dmux@4044000 {
+		compatible = "qcom,bam_dmux";
+		reg = <0x4044000 0x19000>;
+		interrupts = <0 162 1>;
+		qcom,rx-ring-size = <32>;
+		qcom,max-rx-mtu = <4096>;
+		qcom,fast-shutdown;
+		qcom,no-cpu-affinity;
+	};
+
+	ssc_sensors: qcom,msm-ssc-sensors {
+		compatible = "qcom,msm-ssc-sensors";
+		status = "ok";
+	};
 
 };
 
 #include "pm8937-rpm-regulator.dtsi"
 #include "msm8937-regulator.dtsi"
 #include "pm8937.dtsi"
+#include "msm8937-audio.dtsi"
 #include "msm-gdsc-8916.dtsi"
+#include "msm8937-coresight.dtsi"
 
 &gdsc_venus {
 	clock-names = "bus_clk", "core_clk";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi b/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
index c19f267..fc10b4d 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-audio.dtsi
@@ -248,16 +248,23 @@
 			"SpkrRight IN", "SPK2 OUT";
 
 		qcom,tasha-mclk-clk-freq = <9600000>;
+		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
+		qcom,msm-mbhc-hphl-swh = <0>;
+		qcom,msm-mbhc-gnd-swh = <0>;
+		qcom,cdc-us-eu-gpios = <&cdc_us_euro_sw>;
+		qcom,quin-mi2s-gpios = <&cdc_quin_mi2s_gpios>;
 
 		asoc-platform = <&pcm0>, <&pcm1>, <&pcm2>, <&voip>, <&voice>,
 				<&loopback>, <&compress>, <&hostless>,
-				<&afe>, <&lsm>, <&routing>;
+				<&afe>, <&lsm>, <&routing>, <&cpe>, <&compr>,
+				<&pcm_noirq>;
 		asoc-platform-names = "msm-pcm-dsp.0", "msm-pcm-dsp.1",
 				"msm-pcm-dsp.2", "msm-voip-dsp",
 				"msm-pcm-voice", "msm-pcm-loopback",
 				"msm-compress-dsp", "msm-pcm-hostless",
 				"msm-pcm-afe", "msm-lsm-client",
-				"msm-pcm-routing";
+				"msm-pcm-routing", "msm-cpe-lsm",
+				"msm-compr-dsp", "msm-pcm-dsp-noirq";
 
 		asoc-cpu = <&dai_pri_auxpcm>,
 				<&dai_mi2s2>, <&dai_mi2s3>, <&dai_mi2s5>,
@@ -289,9 +296,6 @@
 
 		asoc-codec = <&stub_codec>, <&hdmi_dba>;
 		asoc-codec-names = "msm-stub-codec.1", "msm-hdmi-dba-codec-rx";
-		qcom,cdc-us-euro-gpios = <&tlmm 63 0>;
-		qcom,msm-mbhc-hphl-swh = <0>;
-		qcom,msm-mbhc-gnd-swh = <0>;
 
 		qcom,wsa-max-devs = <2>;
 		qcom,wsa-devs = <&wsa881x_211>, <&wsa881x_212>,
@@ -300,11 +304,19 @@
 				"SpkrLeft", "SpkrRight";
 	};
 
+	cpe: qcom,msm-cpe-lsm {
+		compatible = "qcom,msm-cpe-lsm";
+	};
+
 	wcd9xxx_intc: wcd9xxx-irq {
 		status = "disabled";
+		compatible = "qcom,wcd9xxx-irq";
+		interrupt-controller;
+		#interrupt-cells = <1>;
 		interrupt-parent = <&tlmm>;
-		interrupts = <73 0>;
 		qcom,gpio-connect = <&tlmm 73 0>;
+		pinctrl-names = "default";
+		pinctrl-0 = <&wcd_intr_default>;
 	};
 
 	clock_audio: audio_ext_clk {
@@ -313,29 +325,64 @@
 		clock-names = "osr_clk";
 		qcom,node_has_rpm_clock;
 		#clock-cells = <1>;
+		pinctrl-names = "active", "sleep";
+		pinctrl-0 = <&tasha_mclk_default>;
+		pinctrl-1 = <&tasha_mclk_default>;
 		qcom,audio-ref-clk-gpio = <&pm8953_gpios 1 0>;
-		qcom,lpass-mclk-id = "pri_mclk";
 		clocks = <&clock_gcc clk_div_clk2>;
-		pinctrl-0 = <&cdc_mclk2_sleep>;
-		pinctrl-1 = <&cdc_mclk2_active>;
 	};
 
-	wcd_rst_gpio: wcd_gpio_ctrl {
+	wcd_rst_gpio: msm_cdc_pinctrl@67 {
 		status = "disabled";
-		qcom,cdc-rst-n-gpio = <&tlmm 67 0>;
+		compatible = "qcom,msm-cdc-pinctrl";
+		pinctrl-names = "aud_active", "aud_sleep";
+		pinctrl-0 = <&cdc_reset_active>;
+		pinctrl-1 = <&cdc_reset_sleep>;
 	};
 };
 
 &slim_msm {
 	status = "disabled";
+
+	dai_slim: msm_dai_slim {
+		status = "disabled";
+		compatible = "qcom,msm-dai-slim";
+		elemental-addr = [ff ff ff fe 17 02];
+	};
+
 	wcd9335: tasha_codec {
 		status = "disabled";
 		compatible = "qcom,tasha-slim-pgd";
+		elemental-addr = [00 01 A0 01 17 02];
+
+		qcom,cdc-slim-ifd = "tasha-slim-ifd";
+		qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 01 17 02];
+
+		interrupt-parent = <&wcd9xxx_intc>;
+		interrupts = <0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
+				17 18 19 20 21 22 23 24 25 26 27 28 29 30>;
+
+		qcom,wcd-rst-gpio-node = <&wcd_rst_gpio>;
+
 		clock-names = "wcd_clk", "wcd_native_clk";
 		clocks = <&clock_audio clk_audio_pmi_clk>,
 			<&clock_audio clk_audio_ap_clk2>;
 
-		qcom,cdc-reset-gpio = <&tlmm 67 0>;
+		qcom,cdc-static-supplies =
+				"cdc-vdd-buck",
+				"cdc-buck-sido",
+				"cdc-vdd-tx-h",
+				"cdc-vdd-rx-h",
+				"cdc-vdd-px";
+
+		qcom,cdc-on-demand-supplies = "cdc-vdd-mic-bias";
+		qcom,cdc-micbias1-mv = <1800>;
+		qcom,cdc-micbias2-mv = <1800>;
+		qcom,cdc-micbias3-mv = <1800>;
+		qcom,cdc-micbias4-mv = <1800>;
+
+		qcom,cdc-dmic-sample-rate = <2400000>;
+		qcom,cdc-mclk-clk-rate = <9600000>;
 
 		cdc-vdd-buck-supply = <&eldo2_8953>;
 		qcom,cdc-vdd-buck-voltage = <1800000 1800000>;
@@ -372,6 +419,17 @@
 		qcom,master-en = <1>;
 		qcom,out-strength = <2>;
 	};
+
+	tasha_mclk {
+		tasha_mclk_default: tasha_mclk_default{
+			pins = "gpio1";
+			function = "func1";
+			qcom,drive-strength = <2>;
+			power-source = <0>;
+			bias-disable;
+			output-low;
+		};
+	};
 };
 
 &pm8953_1 {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
index 9aa5260..8f75caf 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-cdp.dtsi
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
 #include "msm8953-audio-cdp.dtsi"
 
 &blsp1_uart0 {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
index 59a3136..ee22633 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
+++ b/arch/arm64/boot/dts/qcom/msm8953-ext-codec-mtp.dts
@@ -26,3 +26,75 @@
 	qcom,pmic-id = <0x010016 0x010011 0x0 0x0>;
 };
 
+&int_codec {
+	status = "disabled";
+};
+
+&pmic_analog_codec {
+	status = "disabled";
+};
+
+&wsa881x_i2c_f {
+	status = "disabled";
+};
+
+&wsa881x_i2c_45 {
+	status = "disabled";
+};
+
+&cdc_pri_mi2s_gpios {
+	status = "disabled";
+};
+
+&wsa881x_analog_vi_gpio {
+	status = "disabled";
+};
+
+&wsa881x_analog_clk_gpio {
+	status = "disabled";
+};
+
+&wsa881x_analog_reset_gpio {
+	status = "disabled";
+};
+
+&cdc_comp_gpios {
+	status = "disabled";
+};
+
+&slim_msm {
+	status = "okay";
+};
+
+&dai_slim {
+	status = "okay";
+};
+
+&wcd9xxx_intc {
+	status = "okay";
+};
+
+&clock_audio {
+	status = "okay";
+};
+
+&wcd9335 {
+	status = "okay";
+};
+
+&cdc_us_euro_sw {
+	status = "okay";
+};
+
+&cdc_quin_mi2s_gpios {
+	status = "okay";
+};
+
+&wcd_rst_gpio {
+	status = "okay";
+};
+
+&ext_codec {
+	qcom,model = "msm8953-tasha-snd-card";
+	status = "okay";
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi b/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi
index 26f4338..b62d12d 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-ipc.dtsi
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -11,6 +11,8 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/gpio/gpio.h>
+
 &blsp1_uart0 {
 	status = "ok";
 	pinctrl-names = "default";
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
index 28a6b74..c6bc2b9 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mdss-panels.dtsi
@@ -47,6 +47,23 @@
 			qcom,supply-enable-load = <100000>;
 			qcom,supply-disable-load = <100>;
 		};
+		qcom,panel-supply-entry@2 {
+			reg = <2>;
+			qcom,supply-name = "lab";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+		};
+		qcom,panel-supply-entry@3 {
+			reg = <3>;
+			qcom,supply-name = "ibb";
+			qcom,supply-min-voltage = <4600000>;
+			qcom,supply-max-voltage = <6000000>;
+			qcom,supply-enable-load = <100000>;
+			qcom,supply-disable-load = <100>;
+			qcom,supply-post-on-sleep = <10>;
+		};
 	};
 };
 
diff --git a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
index 65fba16..76e39f6 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-mtp.dtsi
@@ -11,6 +11,9 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
+
 &blsp1_uart0 {
 	status = "ok";
 	pinctrl-names = "default";
@@ -194,3 +197,9 @@
 		};
 	};
 };
+
+&thermal_zones {
+	case-therm-step {
+		status = "disabled";
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
index 171b7c4..6503b33 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-pinctrl.dtsi
@@ -20,6 +20,7 @@
 		gpio-controller;
 		#gpio-cells = <2>;
 		interrupt-controller;
+		interrupt-parent = <&wakegpio>;
 		#interrupt-cells = <2>;
 
 		pmx-uartconsole {
diff --git a/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi b/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
index 4e1c030..845bf70 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-qrd.dtsi
@@ -11,6 +11,9 @@
  * GNU General Public License for more details.
  */
 
+#include <dt-bindings/gpio/gpio.h>
+#include <dt-bindings/clock/msm-clocks-8953.h>
+
 &soc {
 	i2c@78b7000 { /* BLSP1 QUP3 */
 		/delete-node/ synaptics@4b;
diff --git a/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi b/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi
index d5a6f52..54634ce 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-thermal.dtsi
@@ -253,6 +253,21 @@
 		};
 	};
 
+	case-therm-adc {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8953_vadc 0x13>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
 	gpu1-step {
 		polling-delay-passive = <250>;
 		polling-delay = <0>;
@@ -1087,4 +1102,101 @@
 			};
 		};
 	};
+
+	pa-therm0 {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8953_adc_tm 0x36>;
+		thermal-governor = "user_space";
+
+		trips {
+			active-config0 {
+				temperature = <65000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+	};
+
+	case-therm-step {
+		polling-delay-passive = <2000>;
+		polling-delay = <0>;
+		thermal-sensors = <&pm8953_vadc 0x13>;
+		thermal-governor = "step_wise";
+
+		trips {
+			cpus_trip: cpus-trip {
+				temperature = <43000>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+			modem_trip0: modem-trip0 {
+				temperature = <45000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+			modem_trip1: modem-trip1 {
+				temperature = <48000>;
+				hysteresis = <3000>;
+				type = "passive";
+			};
+			modem_trip2: modem-trip2 {
+				temperature = <54000>;
+				hysteresis = <4000>;
+				type = "passive";
+			};
+		};
+
+		cooling-maps {
+			skin_cpu0 {
+				trip = <&cpus_trip>;
+				/* throttle from fmax to 1689600KHz */
+				cooling-device = <&CPU0 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu1 {
+				trip = <&cpus_trip>;
+				cooling-device = <&CPU1 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu2 {
+				trip = <&cpus_trip>;
+				cooling-device = <&CPU2 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu3 {
+				trip = <&cpus_trip>;
+				cooling-device = <&CPU3 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu4 {
+				trip = <&cpus_trip>;
+				cooling-device = <&CPU4 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu5 {
+				trip = <&cpus_trip>;
+				cooling-device = <&CPU5 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu6 {
+				trip = <&cpus_trip>;
+				cooling-device = <&CPU6 THERMAL_NO_LIMIT 3>;
+			};
+			skin_cpu7 {
+				trip = <&cpus_trip>;
+				cooling-device = <&CPU7 THERMAL_NO_LIMIT 3>;
+			};
+			modem_lvl1 {
+				trip = <&modem_trip1>;
+				cooling-device = <&modem_pa 2 2>;
+			};
+			modem_lvl2 {
+				trip = <&modem_trip2>;
+				cooling-device = <&modem_pa 3 3>;
+			};
+			modem_proc_lvl1 {
+				trip = <&modem_trip0>;
+				cooling-device = <&modem_proc 1 1>;
+			};
+			modem_proc_lvl2 {
+				trip = <&modem_trip2>;
+				cooling-device = <&modem_proc 3 3>;
+			};
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/msm8953-wsa881x.dtsi b/arch/arm64/boot/dts/qcom/msm8953-wsa881x.dtsi
index 671b736..86f5323 100644
--- a/arch/arm64/boot/dts/qcom/msm8953-wsa881x.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953-wsa881x.dtsi
@@ -15,6 +15,7 @@
 	tasha_codec {
 		swr_master {
 			compatible = "qcom,swr-wcd";
+			qcom,swr-num-dev = <2>;
 			#address-cells = <2>;
 			#size-cells = <0>;
 
diff --git a/arch/arm64/boot/dts/qcom/msm8953.dtsi b/arch/arm64/boot/dts/qcom/msm8953.dtsi
index b4111b9..bb370cc 100644
--- a/arch/arm64/boot/dts/qcom/msm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/msm8953.dtsi
@@ -25,10 +25,6 @@
 	qcom,msm-name = "MSM8953";
 	interrupt-parent = <&wakegic>;
 
-	chosen {
-		bootargs = "sched_enable_hmp=1 sched_enable_power_aware=1";
-	};
-
 	firmware: firmware {
 		android {
 			compatible = "android,firmware";
@@ -138,6 +134,12 @@
 			alignment = <0 0x400000>;
 			size = <0 0x800000>;
 		};
+
+		dump_mem: mem_dump_region {
+			compatible = "shared-dma-pool";
+			reusable;
+			size = <0 0x2400000>;
+		};
 	};
 
 	aliases {
@@ -214,20 +216,23 @@
 		      <0x0b002000 0x1000>;
 	};
 
-	mpm: mpm@601d4 {
-		compatible = "qcom,mpm";
+	wakegic: wake-gic@601d4 {
+		compatible = "qcom,mpm-gic-msm8953", "qcom,mpm-gic";
 		interrupts = <GIC_SPI 171 IRQ_TYPE_EDGE_RISING>;
 		reg = <0x601d4 0x1000>,
 			<0xb011008 0x4>;  /* MSM_APCS_GCC_BASE 4K */
 		reg-names = "vmpm", "ipc";
 		qcom,num-mpm-irqs = <96>;
+		interrupt-controller;
+		interrupt-parent = <&intc>;
+		#interrupt-cells = <3>;
+	};
 
-		wakegic: wake-gic {
-			compatible = "qcom,mpm-gic", "qcom,mpm-gic-msm8953";
-			interrupt-controller;
-			interrupt-parent = <&intc>;
-			#interrupt-cells = <3>;
-		};
+	wakegpio: wake-gpio {
+		compatible = "qcom,mpm-gpio-msm8953", "qcom,mpm-gpio";
+		interrupt-controller;
+		interrupt-parent = <&intc>;
+		#interrupt-cells = <2>;
 	};
 
 	qcom,msm-gladiator@b1c0000 {
@@ -336,6 +341,52 @@
 
 	thermal_zones: thermal-zones {};
 
+	mem_dump {
+		compatible = "qcom,mem-dump";
+		memory-region = <&dump_mem>;
+
+		rpmh_dump {
+			qcom,dump-size = <0x2000000>;
+			qcom,dump-id = <0xec>;
+		};
+
+		fcm_dump {
+			qcom,dump-size = <0x8400>;
+			qcom,dump-id = <0xee>;
+		};
+
+		rpm_sw_dump {
+			qcom,dump-size = <0x28000>;
+			qcom,dump-id = <0xea>;
+		};
+
+		pmic_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xe4>;
+		};
+
+		tmc_etf_dump {
+			qcom,dump-size = <0x10000>;
+			qcom,dump-id = <0xf0>;
+		};
+
+		tmc_etr_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x100>;
+		};
+
+		tmc_etf_reg_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0x101>;
+		};
+
+		misc_data_dump {
+			qcom,dump-size = <0x1000>;
+			qcom,dump-id = <0xe8>;
+		};
+
+	};
+
 	tsens0: tsens@4a8000 {
 		compatible = "qcom,msm8953-tsens";
 		reg = <0x4a8000 0x1000>,
@@ -1391,8 +1442,8 @@
 		interrupts = <GIC_SPI 190 IRQ_TYPE_NONE>;
 		qcom,ee = <0>;
 		qcom,channel = <0>;
-		#address-cells = <2>;
-		#size-cells = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
 		interrupt-controller;
 		#interrupt-cells = <4>;
 		cell-index = <0>;
diff --git a/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi
new file mode 100644
index 0000000..ff91250
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm660-rpm-regulator.dtsi
@@ -0,0 +1,381 @@
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa2 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s3 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa5 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s5 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa6 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s6 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_s6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l1 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l3 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l5 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l6 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l7 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l7";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l8 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l8";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l9 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l9";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l10 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l10";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <11>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l11 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l11";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l12 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l12";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <13>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l13 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l13";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l14 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l14";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <15>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l15 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l15";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <16>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l16 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l16";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <17>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l17 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l17";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <18>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l18 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l18";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <19>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l19 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm660_l19";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/pm660.dtsi b/arch/arm64/boot/dts/qcom/pm660.dtsi
index 7724714..fa10500 100644
--- a/arch/arm64/boot/dts/qcom/pm660.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm660.dtsi
@@ -507,20 +507,6 @@
 				type = "passive";
 			};
 		};
-		cooling-maps {
-			vbat_map6 {
-				trip = <&pm660_vbat_adc>;
-				cooling-device =
-					<&CPU6 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			vbat_map7 {
-				trip = <&pm660_vbat_adc>;
-				cooling-device =
-					<&CPU7 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-		};
 	};
 
 	vbat_low {
@@ -569,20 +555,6 @@
 				type = "passive";
 			};
 		};
-		cooling-maps {
-			soc_map6 {
-				trip = <&pm660_low_soc>;
-				cooling-device =
-					<&CPU6 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			soc_map7 {
-				trip = <&pm660_low_soc>;
-				cooling-device =
-					<&CPU7 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-		};
 	};
 
 	pm660_temp_alarm: pm660_tz {
@@ -608,97 +580,5 @@
 				type = "critical";
 			};
 		};
-		cooling-maps {
-			trip0_cpu0 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU0 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip0_cpu1 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU1 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip0_cpu2 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU2 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip0_cpu3 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU3 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip0_cpu4 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU4 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip0_cpu5 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU5 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip0_cpu6 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU6 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip0_cpu7 {
-				trip = <&pm660_trip0>;
-				cooling-device =
-					<&CPU7 (THERMAL_MAX_LIMIT-1)
-						(THERMAL_MAX_LIMIT-1)>;
-			};
-			trip1_cpu1 {
-				trip = <&pm660_trip1>;
-				cooling-device =
-					<&CPU1 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			trip1_cpu2 {
-				trip = <&pm660_trip1>;
-				cooling-device =
-					<&CPU2 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			trip1_cpu3 {
-				trip = <&pm660_trip1>;
-				cooling-device =
-					<&CPU3 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			trip1_cpu4 {
-				trip = <&pm660_trip1>;
-				cooling-device =
-					<&CPU4 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			trip1_cpu5 {
-				trip = <&pm660_trip1>;
-				cooling-device =
-					<&CPU5 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			trip1_cpu6 {
-				trip = <&pm660_trip1>;
-				cooling-device =
-					<&CPU6 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-			trip1_cpu7 {
-				trip = <&pm660_trip1>;
-				cooling-device =
-					<&CPU7 THERMAL_MAX_LIMIT
-						THERMAL_MAX_LIMIT>;
-			};
-		};
 	};
 };
diff --git a/arch/arm64/boot/dts/qcom/pm8909-rpm-regulator.dtsi b/arch/arm64/boot/dts/qcom/pm8909-rpm-regulator.dtsi
new file mode 100644
index 0000000..6da90de
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/pm8909-rpm-regulator.dtsi
@@ -0,0 +1,317 @@
+/* Copyright (c) 2016, 2018 The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+	rpm-regulator-smpa1 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s1 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_s1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-smpa2 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "smpa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <1>;
+		qcom,hpm-min-load = <100000>;
+		status = "disabled";
+
+		regulator-s2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_s2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <1>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l1 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l1";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <2>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l2 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l2";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <3>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l3 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l3";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l4 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l4";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <5>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l5 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l5";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <6>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l6 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l6";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <7>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l7 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l7";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <8>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l8 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l8";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <9>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l9 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l9";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <10>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l10 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l10";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <11>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l11 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l11";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <12>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l12 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l12";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <13>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l13 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l13";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l14 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l14";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <15>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "disabled";
+
+		regulator-l15 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l15";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <17>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l17 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l17";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+
+	rpm-regulator-ldoa18 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <18>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "disabled";
+
+		regulator-l18 {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8909_l18";
+			qcom,set = <3>;
+			status = "disabled";
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/pm8953.dtsi b/arch/arm64/boot/dts/qcom/pm8953.dtsi
index 6cce3b7..3a587a8 100644
--- a/arch/arm64/boot/dts/qcom/pm8953.dtsi
+++ b/arch/arm64/boot/dts/qcom/pm8953.dtsi
@@ -35,6 +35,7 @@
 				"resin-bark", "kpdpwr-resin-bark";
 			qcom,pon-dbc-delay = <15625>;
 			qcom,system-reset;
+			qcom,store-hard-reset-reason;
 
 			qcom,pon_1 {
 				qcom,pon-type = <0>;
@@ -78,6 +79,24 @@
 
 			gpio-controller;
 			#gpio-cells = <2>;
+
+			case_therm {
+				cas_therm_default: cas_therm_default {
+					pins = "mpp4";
+					function = "analog";
+					input-enable;
+					qcom,amux-route = <3>;
+				};
+			};
+
+			pa_therm1 {
+				pa_therm1_default: pa_therm1_default {
+					pins = "mpp2";
+					function = "analog";
+					input-enable;
+					qcom,amux-route = <1>;
+				};
+			};
 		};
 
 		pm8953_gpios: gpios {
@@ -87,15 +106,16 @@
 			interrupts = <0x0 0xc0 0 IRQ_TYPE_NONE>,
 				<0x0 0xc1 0 IRQ_TYPE_NONE>,
 				<0x0 0xc3 0 IRQ_TYPE_NONE>,
+				<0x0 0xc4 0 IRQ_TYPE_NONE>,
 				<0x0 0xc6 0 IRQ_TYPE_NONE>,
 				<0x0 0xc7 0 IRQ_TYPE_NONE>;
 			interrupt-names = "pm8953_gpio1", "pm8953_gpio2",
-					"pm8953_gpio4", "pm8953_gpio7",
-					"pm8953_gpio8";
+					"pm8953_gpio4", "pm8953_gpio5",
+					"pm8953_gpio7", "pm8953_gpio8";
 
 			gpio-controller;
 			#gpio-cells = <2>;
-			qcom,gpios-disallowed = <3 5 6>;
+			qcom,gpios-disallowed = <3 6>;
 		};
 
 		pm8953_vadc: vadc@3100 {
@@ -109,6 +129,8 @@
 			qcom,adc-vdd-reference = <1800>;
 			qcom,vadc-poll-eoc;
 			#thermal-sensor-cells = <1>;
+			pinctrl-names = "default";
+			pinctrl-0 = <&pa_therm1_default &cas_therm_default>;
 
 			chan@5 {
 				label = "vcoin";
@@ -231,6 +253,7 @@
 				qcom,scale-function = <2>;
 				qcom,hw-settle-time = <2>;
 				qcom,fast-avg-setup = <0>;
+				qcom,vadc-thermal-node;
 			};
 		};
 
@@ -248,6 +271,7 @@
 			qcom,adc-bit-resolution = <15>;
 			qcom,adc-vdd-reference = <1800>;
 			qcom,adc_tm-vadc = <&pm8953_vadc>;
+			#thermal-sensor-cells = <1>;
 		};
 
 		pm8953_rtc: qcom,pm8953_rtc {
diff --git a/arch/arm64/boot/dts/qcom/pmi632.dtsi b/arch/arm64/boot/dts/qcom/pmi632.dtsi
index e263058..becc510 100644
--- a/arch/arm64/boot/dts/qcom/pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi632.dtsi
@@ -18,8 +18,8 @@
 	qcom,pmi632@2 {
 		compatible = "qcom,spmi-pmic";
 		reg = <0x2 SPMI_USID>;
-		#address-cells = <2>;
-		#size-cells = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
 
 		pmi632_revid: qcom,revid@100 {
 			compatible = "qcom,qpnp-revid";
@@ -37,7 +37,7 @@
 			reg = <0x3100 0x100>;
 			#address-cells = <1>;
 			#size-cells = <0>;
-			interrupts = <0x0 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
+			interrupts = <0x2 0x31 0x0 IRQ_TYPE_EDGE_RISING>;
 			interrupt-names = "eoc-int-en-set";
 			qcom,adc-vdd-reference = <1875>;
 			qcom,adc-full-scale-code = <0x70e4>;
@@ -219,10 +219,15 @@
 			compatible = "qcom,qpnp-smb5";
 			#address-cells = <1>;
 			#size-cells = <1>;
+			#cooling-cells = <2>;
 
 			qcom,pmic-revid = <&pmi632_revid>;
 			dpdm-supply = <&qusb_phy>;
 
+			qcom,thermal-mitigation
+				= <3000000 2500000 2000000 1500000
+					1000000 500000>;
+
 			qcom,chgr@1000 {
 				reg = <0x1000 0x100>;
 				interrupts =
@@ -232,8 +237,8 @@
 					<0x2 0x10 0x3 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x10 0x4 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x10 0x5 IRQ_TYPE_EDGE_RISING>,
-					<0x2 0x10 0x6 IRQ_TYPE_LEVEL_HIGH>,
-					<0x2 0x10 0x7 IRQ_TYPE_LEVEL_HIGH>;
+					<0x2 0x10 0x6 IRQ_TYPE_EDGE_RISING>,
+					<0x2 0x10 0x7 IRQ_TYPE_EDGE_RISING>;
 
 				interrupt-names = "chgr-error",
 						  "chg-state-change",
@@ -251,7 +256,7 @@
 					<0x2 0x11 0x0 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x11 0x1 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x11 0x2 IRQ_TYPE_EDGE_RISING>,
-					<0x2 0x11 0x3 IRQ_TYPE_LEVEL_HIGH>,
+					<0x2 0x11 0x3 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x11 0x4 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x11 0x5 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x11 0x6 IRQ_TYPE_EDGE_RISING>,
@@ -277,7 +282,7 @@
 					<0x2 0x12 0x4 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x12 0x5 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x12 0x6 IRQ_TYPE_EDGE_BOTH>,
-					<0x2 0x12 0x7 IRQ_TYPE_LEVEL_HIGH>;
+					<0x2 0x12 0x7 IRQ_TYPE_EDGE_BOTH>;
 
 				interrupt-names = "bat-temp",
 						  "all-chnl-conv-done",
@@ -296,8 +301,8 @@
 					<0x2 0x13 0x1 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x13 0x2 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x13 0x3 IRQ_TYPE_EDGE_BOTH>,
-					<0x2 0x13 0x4 IRQ_TYPE_LEVEL_HIGH>,
-					<0x2 0x13 0x5 IRQ_TYPE_LEVEL_HIGH>,
+					<0x2 0x13 0x4 IRQ_TYPE_EDGE_BOTH>,
+					<0x2 0x13 0x5 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x13 0x6 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x13 0x7 IRQ_TYPE_EDGE_RISING>;
 
@@ -315,12 +320,12 @@
 				reg = <0x1500 0x100>;
 				interrupts =
 					<0x2 0x15 0x0 IRQ_TYPE_EDGE_BOTH>,
-					<0x2 0x15 0x1 IRQ_TYPE_LEVEL_HIGH>,
+					<0x2 0x15 0x1 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x15 0x2 IRQ_TYPE_EDGE_RISING>,
-					<0x2 0x15 0x3 IRQ_TYPE_LEVEL_HIGH>,
-					<0x2 0x15 0x4 IRQ_TYPE_EDGE_RISING>,
+					<0x2 0x15 0x3 IRQ_TYPE_EDGE_RISING>,
+					<0x2 0x15 0x4 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x15 0x5 IRQ_TYPE_EDGE_RISING>,
-					<0x2 0x15 0x6 IRQ_TYPE_LEVEL_HIGH>,
+					<0x2 0x15 0x6 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x15 0x7 IRQ_TYPE_EDGE_RISING>;
 
 				interrupt-names = "typec-or-rid-detect-change",
@@ -338,11 +343,11 @@
 				interrupts =
 					<0x2 0x16 0x0 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x16 0x1 IRQ_TYPE_EDGE_RISING>,
-					<0x2 0x16 0x2 IRQ_TYPE_LEVEL_HIGH>,
-					<0x2 0x16 0x3 IRQ_TYPE_LEVEL_HIGH>,
-					<0x2 0x16 0x4 IRQ_TYPE_LEVEL_HIGH>,
+					<0x2 0x16 0x2 IRQ_TYPE_EDGE_RISING>,
+					<0x2 0x16 0x3 IRQ_TYPE_EDGE_RISING>,
+					<0x2 0x16 0x4 IRQ_TYPE_EDGE_BOTH>,
 					<0x2 0x16 0x5 IRQ_TYPE_EDGE_RISING>,
-					<0x2 0x16 0x6 IRQ_TYPE_EDGE_FALLING>,
+					<0x2 0x16 0x6 IRQ_TYPE_EDGE_RISING>,
 					<0x2 0x16 0x7 IRQ_TYPE_EDGE_RISING>;
 
 				interrupt-names = "wdog-snarl",
@@ -407,13 +412,28 @@
 				reg = <0xb100 0x100>;
 			};
 		};
+
+		bcl_sensor: bcl@3d00 {
+			compatible = "qcom,msm-bcl-pmic5";
+			reg = <0x3d00 0xff>;
+			interrupts = <0x2 0x3d 0x0 IRQ_TYPE_NONE>,
+					<0x2 0x3d 0x1 IRQ_TYPE_NONE>;
+			interrupt-names = "bcl-high-ibat",
+						"bcl-low-vbat";
+			#thermal-sensor-cells = <1>;
+		};
+
+		bcl_soc: bcl-soc {
+			compatible = "qcom,msm-bcl-soc";
+			#thermal-sensor-cells = <0>;
+		};
 	};
 
 	pmi632_3: qcom,pmi632@3 {
 		compatible ="qcom,spmi-pmic";
 		reg = <0x3 SPMI_USID>;
-		#address-cells = <2>;
-		#size-cells = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
 
 		pmi632_vib: qcom,vibrator@5700 {
 			compatible = "qcom,qpnp-vibrator-ldo";
@@ -436,16 +456,19 @@
 				label = "red";
 				pwms = <&pmi632_pwm 0 1000000>;
 				led-sources = <0>;
+				linux,default-trigger = "timer";
 			};
 			green {
 				label = "green";
 				pwms = <&pmi632_pwm 1 1000000>;
 				led-sources = <1>;
+				linux,default-trigger = "timer";
 			};
 			blue {
 				label = "blue";
 				pwms = <&pmi632_pwm 2 1000000>;
 				led-sources = <2>;
+				linux,default-trigger = "timer";
 			};
 		};
 
@@ -571,3 +594,52 @@
 		qcom,switch-source = <&pmi632_switch0>;
 	};
 };
+
+&thermal_zones {
+	ibat-high {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "step_wise";
+		thermal-sensors = <&bcl_sensor 0>;
+
+		trips {
+			pmi632_ibat:ibat-high {
+				temperature = <3500>;
+				hysteresis = <200>;
+				type = "passive";
+			};
+		};
+	};
+
+	vbat_low {
+		polling-delay-passive = <100>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_cap";
+		thermal-sensors = <&bcl_sensor 2>;
+		tracks-low;
+
+		trips {
+			pmi632_vbat_low: vbat-low {
+				temperature = <3000>;
+				hysteresis = <100>;
+				type = "passive";
+			};
+		};
+	};
+
+	soc {
+		polling-delay-passive = <100>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_cap";
+		thermal-sensors = <&bcl_soc>;
+		tracks-low;
+
+		trips {
+			pmi632_low_soc: low-soc {
+				temperature = <10>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/pmi8950.dtsi b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
index 6f1f899..8797ea8 100644
--- a/arch/arm64/boot/dts/qcom/pmi8950.dtsi
+++ b/arch/arm64/boot/dts/qcom/pmi8950.dtsi
@@ -18,8 +18,8 @@
 	qcom,pmi8950@2 {
 		compatible ="qcom,spmi-pmic";
 		reg = <0x2 SPMI_USID>;
-		#address-cells = <2>;
-		#size-cells = <0>;
+		#address-cells = <1>;
+		#size-cells = <1>;
 
 		pmi8950_revid: qcom,revid@100 {
 			compatible = "qcom,qpnp-revid";
diff --git a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
index bad4fd7..e56f1b0 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-360camera.dtsi
@@ -301,7 +301,7 @@
 			label = "cam_snapshot";
 			gpios = <&tlmm 91 GPIO_ACTIVE_LOW>;
 			linux,input-type = <1>;
-			linux,code = <766>;
+			linux,code = <767>;
 			gpio-key,wakeup;
 			debounce-interval = <15>;
 			linux,can-disable;
diff --git a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
index 2bef956..6b31136 100644
--- a/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
+++ b/arch/arm64/boot/dts/qcom/qcs605-lc.dtsi
@@ -91,6 +91,13 @@
 			};
 		};
 	};
+
+	qcom,chd_silver {
+		compatible = "qcom,core-hang-detect";
+		label = "silver";
+		qcom,threshold-arr = <0x17e00058 0x17e10058>;
+		qcom,config-arr = <0x17e00060 0x17e10060>;
+	};
 };
 
 &pm660_temp_alarm {
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cdp.dts b/arch/arm64/boot/dts/qcom/sdm429-cdp.dts
new file mode 100644
index 0000000..f3312bd
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-cdp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm429.dtsi"
+#include "sdm429-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM429 CDP";
+	compatible = "qcom,sdm429-cdp", "qcom,sdm429", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm429-cdp.dtsi
new file mode 100644
index 0000000..4ba4c00
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-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 "sdm439-cdp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
new file mode 100644
index 0000000..9960c47
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-cpu.dtsi
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	/delete-node/ cpus;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		cpu-map {
+
+			cluster0 {
+			};
+
+			cluster1 {
+				core0 {
+					cpu = <&CPU0>;
+				};
+				core1 {
+					cpu = <&CPU1>;
+				};
+				core2 {
+					cpu = <&CPU2>;
+				};
+				core3 {
+					cpu = <&CPU3>;
+				};
+			};
+		};
+
+		CPU0: cpu@100 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x100>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L2_1: l2-cache {
+			      compatible = "arm,arch-cache";
+			      cache-level = <2>;
+			      /* A53 L2 dump not supported */
+			      qcom,dump-size = <0x0>;
+			};
+			L1_I_100: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_100: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+		CPU1: cpu@101 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x101>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L1_I_101: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_101: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+		CPU2: cpu@102 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x102>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L1_I_102: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_102: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+		CPU3: cpu@103 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a53";
+			reg = <0x103>;
+			enable-method = "psci";
+			cpu-release-addr = <0x0 0x90000000>;
+			next-level-cache = <&L2_1>;
+			L1_I_103: l1-icache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x8800>;
+			};
+			L1_D_103: l1-dcache {
+				compatible = "arm,arch-cache";
+				qcom,dump-size = <0x9000>;
+			};
+		};
+
+	};
+
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-mtp.dts b/arch/arm64/boot/dts/qcom/sdm429-mtp.dts
new file mode 100644
index 0000000..a809be7
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-mtp.dts
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/dts-v1/;
+
+#include "sdm429.dtsi"
+#include "sdm429-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM429 MTP";
+	compatible = "qcom,sdm429-mtp", "qcom,sdm429", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm429-mtp.dtsi
new file mode 100644
index 0000000..839fa56
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-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 "sdm439-mtp.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd.dts b/arch/arm64/boot/dts/qcom/sdm429-qrd.dts
new file mode 100644
index 0000000..d97cf54
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-qrd.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 "sdm429.dtsi"
+#include "sdm429-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM429 QRD";
+	compatible = "qcom,sdm429-qrd", "qcom,sdm429", "qcom,qrd";
+	qcom,board-id = <0xb 0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm429-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm429-qrd.dtsi
new file mode 100644
index 0000000..7116662
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429-qrd.dtsi
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "sdm439-qrd.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm429.dtsi b/arch/arm64/boot/dts/qcom/sdm429.dtsi
new file mode 100644
index 0000000..88cf1da
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm429.dtsi
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include "sdm439.dtsi"
+#include "sdm429-cpu.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM429";
+	compatible = "qcom,sdm429";
+	qcom,msm-id = <354 0x0>;
+};
+
+&soc {
+	/delete-node/ qcom,spm@b1d2000;
+	/delete-node/ qcom,lpm-levels;
+	/delete-node/ etm@619c000;
+	/delete-node/ etm@619d000;
+	/delete-node/ etm@619e000;
+	/delete-node/ etm@619f000;
+	/delete-node/ cti@61b8000;
+	/delete-node/ cti@61b9000;
+	/delete-node/ cti@61ba000;
+	/delete-node/ cti@61bb000;
+};
+
+&funnel_apss {
+	ports {
+		/delete-node/ port@1;
+		/delete-node/ port@2;
+		/delete-node/ port@3;
+		/delete-node/ port@4;
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dts b/arch/arm64/boot/dts/qcom/sdm439-cdp.dts
new file mode 100644
index 0000000..1306230
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-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 "sdm439.dtsi"
+#include "sdm439-cdp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM439 CDP";
+	compatible = "qcom,sdm439-cdp", "qcom,sdm439", "qcom,cdp";
+	qcom,board-id = <1 0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
new file mode 100644
index 0000000..069cc3b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-cdp.dtsi
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+&blsp1_uart2 {
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dts b/arch/arm64/boot/dts/qcom/sdm439-mtp.dts
new file mode 100644
index 0000000..9f221f0
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-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 "sdm439.dtsi"
+#include "sdm439-mtp.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM439 MTP";
+	compatible = "qcom,sdm439-mtp", "qcom,sdm439", "qcom,mtp";
+	qcom,board-id = <8 0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
new file mode 100644
index 0000000..069cc3b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-mtp.dtsi
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+&blsp1_uart2 {
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
new file mode 100644
index 0000000..e025730
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-pm8953.dtsi
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+&rpm_bus {
+	/* Deleting all pm8937 regulators */
+	/delete-node/ rpm-regulator-smpa1;
+	/delete-node/ rpm-regulator-smpa2;
+	/delete-node/ rpm-regulator-smpa3;
+	/delete-node/ rpm-regulator-smpa4;
+	/delete-node/ rpm-regulator-ldoa2;
+	/delete-node/ rpm-regulator-ldoa3;
+	/delete-node/ rpm-regulator-ldoa5;
+	/delete-node/ rpm-regulator-ldoa6;
+	/delete-node/ rpm-regulator-ldoa7;
+	/delete-node/ rpm-regulator-ldoa8;
+	/delete-node/ rpm-regulator-ldoa9;
+	/delete-node/ rpm-regulator-ldoa10;
+	/delete-node/ rpm-regulator-ldoa11;
+	/delete-node/ rpm-regulator-ldoa12;
+	/delete-node/ rpm-regulator-ldoa13;
+	/delete-node/ rpm-regulator-ldoa14;
+	/delete-node/ rpm-regulator-ldoa15;
+	/delete-node/ rpm-regulator-ldoa16;
+	/delete-node/ rpm-regulator-ldoa17;
+	/delete-node/ rpm-regulator-ldoa19;
+	/delete-node/ rpm-regulator-ldoa22;
+	/delete-node/ rpm-regulator-ldoa23;
+};
+
+&spmi_bus {
+	/delete-node/ qcom,pm8937@0;
+	/delete-node/ qcom,pm8937@1;
+};
+
+&thermal_zones {
+	/delete-node/ pa-therm1-adc;
+	/delete-node/ xo-therm-adc;
+	/delete-node/ xo-therm-buf-adc;
+	/delete-node/ case-therm-adc;
+	/delete-node/ pa-therm0-adc;
+};
+
+&soc {
+	/delete-node/ regulator@01946004;
+	/delete-node/ regulator@b018000;
+	/delete-node/ eldo2;
+	/delete-node/ adv_vreg;
+
+	qcom,gcc@1800000 {
+		/delete-property/ vdd_dig-supply;
+		/delete-property/ vdd_sr2_dig-supply;
+		/delete-property/ vdd_sr2_pll-supply;
+		/delete-property/ vdd_hf_dig-supply;
+		/delete-property/ vdd_hf_pll-supply;
+	};
+
+	qcom,cpu-clock-8939@b111050 {
+		/delete-property/ vdd-c0-supply;
+		/delete-property/ vdd-c1-supply;
+		/delete-property/ vdd-cci-supply;
+	};
+
+	usb@78db000 {
+		/delete-property/ hsusb_vdd_dig-supply;
+		/delete-property/ HSUSB_1p8-supply;
+		/delete-property/ HSUSB_3p3-supply;
+	};
+
+	qcom,lpass@c200000 {
+		/delete-property/ vdd_cx-supply;
+	};
+
+	qcom,pronto@a21b000 {
+		/delete-property/ vdd_pronto_pll-supply;
+	};
+
+	qcom,wcnss-wlan@0a000000 {
+		/delete-property/ qcom,pronto-vddmx-supply;
+		/delete-property/ qcom,pronto-vddcx-supply;
+		/delete-property/ qcom,pronto-vddpx-supply;
+		/delete-property/ qcom,iris-vddxo-supply;
+		/delete-property/ qcom,iris-vddrfa-supply;
+		/delete-property/ qcom,iris-vddpa-supply;
+		/delete-property/ qcom,iris-vdddig-supply;
+		/delete-property/ qcom,wcnss-adc_tm;
+	};
+};
+
+&pil_mss {
+	/delete-property/ vdd_mss-supply;
+	/delete-property/ vdd_cx-supply;
+	/delete-property/ vdd_cx-voltage;
+	/delete-property/ vdd_mx-supply;
+	/delete-property/ vdd_mx-uV;
+	/delete-property/ vdd_pll-supply;
+};
+
+&mdss_dsi {
+	/delete-property/ vdda-supply;
+	/delete-property/ vddio-supply;
+};
+
+&usb_otg {
+	/delete-property/ hsusb_vdd_dig-supply;
+	/delete-property/ HSUSB_1p8-supply;
+	/delete-property/ HSUSB_3p3-supply;
+};
+
+&mdss_dsi0_pll {
+	/delete-property/ vddio-supply;
+};
+
+&mdss_dsi1_pll {
+	/delete-property/ vddio-supply;
+};
+
+&mdss_dsi0 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vddio-supply;
+};
+
+&mdss_dsi1 {
+	/delete-property/ vdd-supply;
+	/delete-property/ vddio-supply;
+};
+
+&int_codec {
+	/delete-property/ asoc-codec;
+	/delete-property/ msm-vdd-wsa-switch-supply;
+};
+
+&clock_audio {
+	/delete-property/ qcom,audio-ref-clk-gpio;
+};
+
+&wcd9335 {
+	/delete-property/ cdc-vdd-buck-supply;
+	/delete-property/ cdc-buck-sido-supply;
+	/delete-property/ cdc-vdd-tx-h-supply;
+	/delete-property/ cdc-vdd-rx-h-supply;
+	/delete-property/ cdc-vdd-px-supply;
+	/delete-property/ cdc-vdd-mic-bias-supply;
+};
+
+#include "pm8953.dtsi"
+#include "pm8953-rpm-regulator.dtsi"
+#include "sdm439-regulator.dtsi"
diff --git a/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
new file mode 100644
index 0000000..ad2b0fe
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-pmi632.dtsi
@@ -0,0 +1,40 @@
+/*
+ * 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 "pmi632.dtsi"
+
+&pmi632_charger {
+	dpdm-supply = <&usb_otg>;
+};
+
+&usb_otg {
+	vbus_otg-supply = <&smb5_vbus>;
+};
+
+&pmi632_pon {
+	qcom,ps-hold-hard-reset-disable;
+	qcom,ps-hold-shutdown-disable;
+};
+
+/{
+	mtp_batterydata: qcom,battery-data {
+		qcom,batt-id-range-pct = <15>;
+		#include "qg-batterydata-ascent-3450mah.dtsi"
+		#include "qg-batterydata-mlp356477-2800mah.dtsi"
+	};
+};
+
+&pmi632_qg {
+	qcom,battery-data = <&mtp_batterydata>;
+	qcom,rbat-conn-mohm = <20>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dts b/arch/arm64/boot/dts/qcom/sdm439-qrd.dts
new file mode 100644
index 0000000..7b93e0c
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.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 "sdm439.dtsi"
+#include "sdm439-qrd.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM439 QRD";
+	compatible = "qcom,sdm439-qrd", "qcom,sdm439", "qcom,qrd";
+	qcom,board-id = <0xb 0>;
+	qcom,pmic-id = <0x010016 0x25 0x0 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
new file mode 100644
index 0000000..069cc3b
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-qrd.dtsi
@@ -0,0 +1,16 @@
+/*
+ * 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.
+ */
+
+&blsp1_uart2 {
+	status = "ok";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
new file mode 100644
index 0000000..27307d8
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439-regulator.dtsi
@@ -0,0 +1,382 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <dt-bindings/interrupt-controller/arm-gic.h>
+
+&rpm_bus {
+	/* PM8953 regulators */
+	rpm-regulator-smpa1 {
+		status = "okay";
+		pm8953_s1: regulator-s1 {
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+			qcom,use-voltage-level;
+			status = "okay";
+		};
+	};
+
+	/* PM8953 S2 - VDD_CX supply */
+	rpm-regulator-smpa2 {
+		status = "okay";
+		pm8953_s2_level: regulator-s2-level {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_s2_level";
+			qcom,set = <3>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+			qcom,use-voltage-level;
+		};
+
+		pm8953_s2_floor_level: regulator-s2-floor-level {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_s2_floor_level";
+			qcom,set = <3>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+			qcom,use-voltage-floor-level;
+			qcom,always-send-voltage;
+		};
+
+		pm8953_s2_level_ao: regulator-s2-level-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_s2_level_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+			qcom,use-voltage-level;
+		};
+	};
+
+	rpm-regulator-smpa3 {
+		status = "okay";
+		pm8953_s3: regulator-s3 {
+			regulator-min-microvolt = <1280000>;
+			regulator-max-microvolt = <1280000>;
+			qcom,init-voltage = <1280000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-smpa4 {
+		status = "okay";
+		pm8953_s4: regulator-s4 {
+			regulator-min-microvolt = <2040000>;
+			regulator-max-microvolt = <2040000>;
+			qcom,init-voltage = <2040000>;
+			status = "okay";
+		};
+	};
+
+	/* VDD_MX supply */
+	rpm-regulator-smpa7 {
+		status = "okay";
+		pm8953_s7_level: regulator-s7-level {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_s7_level";
+			qcom,set = <3>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+			qcom,init-voltage-level =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			qcom,use-voltage-level;
+			qcom,always-send-voltage;
+		};
+
+		pm8953_s7_level_ao: regulator-s7-level-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_s7_level_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+			qcom,use-voltage-level;
+			qcom,always-send-voltage;
+		};
+
+		pm8953_s7_level_so: regulator-s7-level-so {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_s7_level_so";
+			qcom,set = <2>;
+			regulator-min-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			regulator-max-microvolt =
+					<RPM_SMD_REGULATOR_LEVEL_TURBO>;
+			qcom,init-voltage-level =
+					<RPM_SMD_REGULATOR_LEVEL_RETENTION>;
+			qcom,use-voltage-level;
+		};
+	};
+
+	rpm-regulator-ldoa1 {
+		status = "okay";
+		pm8953_l1: regulator-l1 {
+			regulator-min-microvolt = <1000000>;
+			regulator-max-microvolt = <1000000>;
+			qcom,init-voltage = <1000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa2 {
+		status = "okay";
+		pm8953_l2: regulator-l2 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa3 {
+		status = "okay";
+		pm8953_l3: regulator-l3 {
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,init-voltage = <1200000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa4 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <4>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <10000>;
+		status = "okay";
+		pm8953_l4: regulator-l4 {
+			compatible = "qcom,rpm-smd-regulator-resource";
+			regulator-name = "pm8953_l4";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa5 {
+		status = "okay";
+		pm8953_l5: regulator-l5 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa6 {
+		status = "okay";
+		pm8953_l6: regulator-l6 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa7 {
+		status = "okay";
+		pm8953_l7: regulator-l7 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+
+		pm8953_l7_ao: regulator-l7-ao {
+			compatible = "qcom,rpm-smd-regulator";
+			regulator-name = "pm8953_l7_ao";
+			qcom,set = <1>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+		};
+	};
+
+	rpm-regulator-ldoa8 {
+		status = "okay";
+		pm8953_l8: regulator-l8 {
+			regulator-min-microvolt = <2900000>;
+			regulator-max-microvolt = <2900000>;
+			qcom,init-voltage = <2900000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa9 {
+		status = "okay";
+		pm8953_l9: regulator-l9 {
+			regulator-min-microvolt = <3300000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3300000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa10 {
+		status = "okay";
+		pm8953_l10: regulator-l10 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,init-voltage = <3000000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa11 {
+		status = "okay";
+		pm8953_l11: regulator-l11 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <2950000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa12 {
+		status = "okay";
+		pm8953_l12: regulator-l12 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa13 {
+		status = "okay";
+		pm8953_l13: regulator-l13 {
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3300000>;
+			qcom,init-voltage = <3075000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa14 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <14>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "okay";
+		pm8953_l14: regulator-l14 {
+			compatible = "qcom,rpm-smd-regulator-resource";
+			regulator-name = "pm8953_l14";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa15 {
+		compatible = "qcom,rpm-smd-regulator-resource";
+		qcom,resource-name = "ldoa";
+		qcom,resource-id = <15>;
+		qcom,regulator-type = <0>;
+		qcom,hpm-min-load = <5000>;
+		status = "okay";
+		pm8953_l15: regulator-l15 {
+			compatible = "qcom,rpm-smd-regulator-resource";
+			regulator-name = "pm8953_l15";
+			qcom,set = <3>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa16 {
+		status = "okay";
+		pm8953_l16: regulator-l16 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,init-voltage = <1800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa17 {
+		status = "okay";
+		pm8953_l17: regulator-l17 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,init-voltage = <2850000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa19 {
+		status = "okay";
+		pm8953_l19: regulator-l19 {
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1350000>;
+			qcom,init-voltage = <1300000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa22 {
+		status = "okay";
+		pm8953_l22: regulator-l22 {
+			regulator-min-microvolt = <2800000>;
+			regulator-max-microvolt = <2800000>;
+			qcom,init-voltage = <2800000>;
+			status = "okay";
+		};
+	};
+
+	rpm-regulator-ldoa23 {
+		status = "okay";
+		pm8953_l23: regulator-l23 {
+			regulator-min-microvolt = <800000>;
+			regulator-max-microvolt = <800000>;
+			qcom,init-voltage = <800000>;
+			status = "okay";
+		};
+	};
+};
+
+&spmi_bus {
+	qcom,pm8953@1 {
+		/* PM8953 S5 + S6 = VDD_APC_supply */
+		pm8953_s5: spm-regulator@2000 {
+			compatible = "qcom,spm-regulator";
+			reg = <0x2000 0x100>;
+			regulator-name = "pm8953_s5";
+			regulator-min-microvolt = <490000>;
+			regulator-max-microvolt = <910000>;
+
+			pm8953_s5_limit: avs-limit-regulator {
+				regulator-name = "pm8953_s5_avs_limit";
+				regulator-min-microvolt = <490000>;
+				regulator-max-microvolt = <910000>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm439.dtsi b/arch/arm64/boot/dts/qcom/sdm439.dtsi
new file mode 100644
index 0000000..b176858
--- /dev/null
+++ b/arch/arm64/boot/dts/qcom/sdm439.dtsi
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm8937.dtsi"
+#include "sdm439-pm8953.dtsi"
+#include "sdm439-pmi632.dtsi"
+
+/ {
+	model = "Qualcomm Technologies, Inc. SDM439";
+	compatible = "qcom,sdm439";
+	qcom,msm-id = <353 0x0>;
+};
+
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
index c47e323..d8a0e9d 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-cdp-s2.dtsi
@@ -37,25 +37,3 @@
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
 };
-
-
-&dsi_panel_pwr_supply {
-	qcom,panel-supply-entry@2 {
-		reg = <2>;
-		qcom,supply-name = "lab";
-		qcom,supply-min-voltage = <4600000>;
-		qcom,supply-max-voltage = <6000000>;
-		qcom,supply-enable-load = <100000>;
-		qcom,supply-disable-load = <100>;
-	};
-	qcom,panel-supply-entry@3 {
-		reg = <3>;
-		qcom,supply-name = "ibb";
-		qcom,supply-min-voltage = <4600000>;
-		qcom,supply-max-voltage = <6000000>;
-		qcom,supply-enable-load = <100000>;
-		qcom,supply-disable-load = <100>;
-		qcom,supply-post-on-sleep = <10>;
-	};
-};
-
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
index d532434..129d507 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632-mtp-s3.dtsi
@@ -38,24 +38,3 @@
 	qcom,mdss-dsi-bl-pmic-bank-select = <0>;
 	qcom,mdss-dsi-pwm-gpio = <&pm8953_gpios 8 0>;
 };
-
-&dsi_panel_pwr_supply {
-	qcom,panel-supply-entry@2 {
-		reg = <2>;
-		qcom,supply-name = "lab";
-		qcom,supply-min-voltage = <4600000>;
-		qcom,supply-max-voltage = <6000000>;
-		qcom,supply-enable-load = <100000>;
-		qcom,supply-disable-load = <100>;
-	};
-	qcom,panel-supply-entry@3 {
-		reg = <3>;
-		qcom,supply-name = "ibb";
-		qcom,supply-min-voltage = <4600000>;
-		qcom,supply-max-voltage = <6000000>;
-		qcom,supply-enable-load = <100000>;
-		qcom,supply-disable-load = <100>;
-		qcom,supply-post-on-sleep = <10>;
-	};
-};
-
diff --git a/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi b/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
index f0f7ad7..aaf4c43 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-pmi632.dtsi
@@ -60,3 +60,107 @@
 &pm8953_pwm {
 	status = "ok";
 };
+
+&thermal_zones {
+	vbat_low {
+		cooling-maps {
+			vbat_map4 {
+				trip = <&pmi632_vbat_low>;
+				cooling-device =
+					<&CPU4 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			vbat_map5 {
+				trip = <&pmi632_vbat_low>;
+				cooling-device =
+					<&CPU5 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			vbat_map6 {
+				trip = <&pmi632_vbat_low>;
+				cooling-device =
+					<&CPU6 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			vbat_map7 {
+				trip = <&pmi632_vbat_low>;
+				cooling-device =
+					<&CPU7 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	soc {
+		cooling-maps {
+			soc_map4 {
+				trip = <&pmi632_low_soc>;
+				cooling-device =
+					<&CPU4 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			soc_map5 {
+				trip = <&pmi632_low_soc>;
+				cooling-device =
+					<&CPU5 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			soc_map6 {
+				trip = <&pmi632_low_soc>;
+				cooling-device =
+					<&CPU6 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			soc_map7 {
+				trip = <&pmi632_low_soc>;
+				cooling-device =
+					<&CPU7 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	case-therm-step {
+		trips {
+			batt_trip1: batt-trip1 {
+				temperature = <38000>;
+				hysteresis = <3000>;
+				type = "passive";
+			};
+			batt_trip2: batt-trip2 {
+				temperature = <40000>;
+				hysteresis = <2000>;
+				type = "passive";
+			};
+			batt_trip3: batt-trip3 {
+				temperature = <43000>;
+				hysteresis = <3000>;
+				type = "passive";
+			};
+			batt_trip4: batt-trip4 {
+				temperature = <48000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+
+		cooling-maps {
+			battery_lvl1 {
+				trip = <&batt_trip1>;
+				cooling-device = <&pmi632_charger 2 2>;
+			};
+			battery_lvl2 {
+				trip = <&batt_trip2>;
+				cooling-device = <&pmi632_charger 3 3>;
+			};
+			battery_lvl3 {
+				trip = <&batt_trip3>;
+				cooling-device = <&pmi632_charger 4 4>;
+			};
+			battery_lvl4 {
+				trip = <&batt_trip4>;
+				cooling-device = <&pmi632_charger 5 5>;
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
index d33c42c..4a63f9e 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm450-qrd-sku4.dtsi
@@ -36,9 +36,10 @@
 	status = "okay";
 	qcom,model = "msm8953-sku4-snd-card";
 	qcom,msm-micbias1-ext-cap;
+	qcom,msm-micbias2-ext-cap;
 	qcom,msm-mbhc-hphl-swh = <1>;
 	qcom,msm-mbhc-gnd-swh = <0>;
-	qcom,msm-hs-micbias-type = "internal";
+	qcom,msm-hs-micbias-type = "external";
 };
 
 &wsa881x_i2c_f {
@@ -144,3 +145,7 @@
 		};
 	};
 };
+
+&sdhc_2 {
+	cd-gpios = <&tlmm 133 0x0>;
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm450-rcm.dts b/arch/arm64/boot/dts/qcom/sdm450-rcm.dts
index 1b7831b..68a7ca2 100644
--- a/arch/arm64/boot/dts/qcom/sdm450-rcm.dts
+++ b/arch/arm64/boot/dts/qcom/sdm450-rcm.dts
@@ -17,6 +17,7 @@
 #include "pmi8950.dtsi"
 #include "msm8953-cdp.dtsi"
 #include "msm8953-pmi8950.dtsi"
+#include "msm8953-camera-sensor-cdp.dtsi"
 
 / {
 	model = "Qualcomm Technologies, Inc. SDM450 + PMI8950 RCM";
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
index 903b432..a544d59 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-cdp-s2.dts
@@ -24,3 +24,33 @@
 	qcom,pmic-id = <0x010016 0x25 0xC 0x0>;
 };
 
+
+&soc {
+	gpio_keys {
+		/delete-node/home;
+	};
+};
+
+&tlmm {
+	tlmm_gpio_key {
+		gpio_key_active: gpio_key_active {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+
+		gpio_key_suspend: gpio_key_suspend {
+			mux {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+
+			config {
+				pins = "gpio85", "gpio86", "gpio87";
+			};
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi b/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi
index 031fd7e..4bda08bd 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632-cpu.dtsi
@@ -58,6 +58,7 @@
 			efficiency = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
+			#cooling-cells = <2>;
 			L2_0: l2-cache {
 			      compatible = "arm,arch-cache";
 			      cache-level = <2>;
@@ -85,6 +86,7 @@
 			efficiency = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
+			#cooling-cells = <2>;
 			L1_I_1: l1-icache {
 			      compatible = "arm,arch-cache";
 			      qcom,dump-size = <0x9040>;
@@ -106,6 +108,7 @@
 			efficiency = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
+			#cooling-cells = <2>;
 			L1_I_2: l1-icache {
 			      compatible = "arm,arch-cache";
 			      qcom,dump-size = <0x9040>;
@@ -127,6 +130,7 @@
 			efficiency = <1024>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_0>;
 			next-level-cache = <&L2_0>;
+			#cooling-cells = <2>;
 			L1_I_3: l1-icache {
 			      compatible = "arm,arch-cache";
 			      qcom,dump-size = <0x9040>;
@@ -148,6 +152,7 @@
 			efficiency = <1638>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
+			#cooling-cells = <2>;
 			L2_1: l2-cache {
 			      compatible = "arm,arch-cache";
 			      cache-level = <2>;
@@ -173,6 +178,7 @@
 			efficiency = <1638>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
+			#cooling-cells = <2>;
 			L1_I_101: l1-icache {
 			      compatible = "arm,arch-cache";
 			      qcom,dump-size = <0x12000>;
@@ -194,6 +200,7 @@
 			efficiency = <1638>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
+			#cooling-cells = <2>;
 			L1_I_102: l1-icache {
 			      compatible = "arm,arch-cache";
 			      qcom,dump-size = <0x12000>;
@@ -215,6 +222,7 @@
 			efficiency = <1638>;
 			sched-energy-costs = <&CPU_COST_0 &CLUSTER_COST_1>;
 			next-level-cache = <&L2_1>;
+			#cooling-cells = <2>;
 			L1_I_103: l1-icache {
 			      compatible = "arm,arch-cache";
 			      qcom,dump-size = <0x12000>;
diff --git a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
index 6b90e1d..a158e33 100644
--- a/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
+++ b/arch/arm64/boot/dts/qcom/sdm632-qrd-sku4.dts
@@ -29,3 +29,23 @@
 		qcom,scale-function = <22>;
 	};
 };
+
+&soc {
+	gpio_keys {
+		camera_focus {
+			label = "camera_focus";
+			gpios = <&tlmm 87 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x210>;
+			debounce-interval = <15>;
+		};
+
+		camera_snapshot {
+			label = "camera_snapshot";
+			gpios = <&tlmm 86 0x1>;
+			linux,input-type = <1>;
+			linux,code = <0x2fe>;
+			debounce-interval = <15>;
+		};
+	};
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm632.dtsi b/arch/arm64/boot/dts/qcom/sdm632.dtsi
index 80e6749..a321552 100644
--- a/arch/arm64/boot/dts/qcom/sdm632.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm632.dtsi
@@ -36,3 +36,510 @@
 &clock_gcc_gfx {
 	compatible = "qcom,gcc-gfx-sdm632";
 };
+
+&thermal_zones {
+	/delete-node/ camera-usr;
+	/delete-node/ apc1-l2-usr;
+	/delete-node/ apc0-cpu0-usr;
+	/delete-node/ apc0-cpu1-usr;
+	/delete-node/ apc0-cpu2-usr;
+	/delete-node/ apc0-cpu3-usr;
+	/delete-node/ apc0-l2-usr;
+	/delete-node/ gpu0-usr;
+	/delete-node/ gpu1-usr;
+	/delete-node/ gpu1-step;
+	/delete-node/ deca-cpu-max-step;
+	/delete-node/ apc0-cpu0-step;
+	/delete-node/ apc0-cpu1-step;
+	/delete-node/ apc0-cpu2-step;
+	/delete-node/ apc0-cpu3-step;
+	/delete-node/ camera-lowf;
+	/delete-node/ apc1-l2-lowf;
+	/delete-node/ apc0-cpu0-lowf;
+	/delete-node/ apc0-cpu1-lowf;
+	/delete-node/ apc0-cpu2-lowf;
+	/delete-node/ apc0-cpu3-lowf;
+	/delete-node/ apc0-l2-lowf;
+	/delete-node/ gpu0-lowf;
+	/delete-node/ gpu1-lowf;
+
+	case-therm-step {
+		status = "disabled";
+	};
+
+	video-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "user_space";
+		thermal-sensors = <&tsens0 3>;
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	cpuss0-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 8>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	cpuss1-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 9>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	cpuss3-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 13>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	camera-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 14>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	gpu0-usr {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 15>;
+		thermal-governor = "user_space";
+		trips {
+			active-config0 {
+				temperature = <125000>;
+				hysteresis = <1000>;
+				type = "passive";
+			};
+		};
+	};
+
+	gpu0-step {
+		polling-delay-passive = <250>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 15>;
+		thermal-governor = "step_wise";
+
+		trips {
+			sdm632_gpu_trip0: gpu-trip0 {
+				temperature = <95000>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			gpu_cdev0 {
+				trip = <&sdm632_gpu_trip0>;
+				cooling-device =
+					<&msm_gpu THERMAL_NO_LIMIT
+						THERMAL_NO_LIMIT>;
+			};
+		};
+	};
+
+	hepta-cpu-max-step {
+		polling-delay-passive = <50>;
+		polling-delay = <100>;
+		thermal-governor = "step_wise";
+
+		trips {
+			sdm632_cpu_trip:cpu-trip {
+				temperature = <95000>;
+				hysteresis = <0>;
+				type = "passive";
+			};
+		};
+
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU0 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			cpu1_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU1 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			cpu2_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU2 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			cpu3_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU3 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			cpu4_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU4 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			cpu5_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU5 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			cpu6_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU6 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			cpu7_cdev {
+				trip = <&sdm632_cpu_trip>;
+				cooling-device =
+					<&CPU7 THERMAL_NO_LIMIT
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+		};
+	};
+
+	cpuss3-step {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-sensors = <&tsens0 13>;
+		thermal-governor = "step_wise";
+
+		trips {
+			cpuss3_trip: cpuss3-trip {
+				temperature = <105000>;
+				hysteresis = <15000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_cdev {
+				trip = <&cpuss3_trip>;
+				cooling-device =
+					<&CPU0 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			cpu1_cdev {
+				trip = <&cpuss3_trip>;
+				cooling-device =
+					<&CPU1 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			cpu2_cdev {
+				trip = <&cpuss3_trip>;
+				cooling-device =
+					<&CPU2 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			cpu3_cdev {
+				trip = <&cpuss3_trip>;
+				cooling-device =
+					<&CPU3 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	video-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 3>;
+		tracks-low;
+
+		trips {
+			video_trip: video-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&video_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&video_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&video_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&video_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	cpuss0-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 8>;
+		tracks-low;
+
+		trips {
+			sdm632_cpuss0_trip: cpuss0-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&sdm632_cpuss0_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	cpuss1-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 9>;
+		tracks-low;
+
+		trips {
+			sdm632_cpuss1_trip: cpuss1-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&sdm632_cpuss1_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&sdm632_cpuss1_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&sdm632_cpuss1_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&sdm632_cpuss1_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	cpuss3-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 13>;
+		tracks-low;
+
+		trips {
+			sdm632_cpuss3_trip: cpuss3-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&sdm632_cpuss3_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&sdm632_cpuss3_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&sdm632_cpuss3_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&sdm632_cpuss3_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	camera-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 14>;
+		tracks-low;
+
+		trips {
+			sdm632_camera_trip: camera-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&sdm632_camera_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&sdm632_camera_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&sdm632_camera_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&sdm632_camera_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+
+	gpu0-lowf {
+		polling-delay-passive = <0>;
+		polling-delay = <0>;
+		thermal-governor = "low_limits_floor";
+		thermal-sensors = <&tsens0 15>;
+		tracks-low;
+
+		trips {
+			sdm632_gpu0_trip: gpu0-trip {
+				temperature = <5000>;
+				hysteresis = <5000>;
+				type = "passive";
+			};
+		};
+		cooling-maps {
+			cpu0_vdd_cdev {
+				trip = <&sdm632_gpu0_trip>;
+				cooling-device = <&CPU0 (THERMAL_MAX_LIMIT - 4)
+						(THERMAL_MAX_LIMIT - 4)>;
+			};
+			gpu_vdd_cdev {
+				trip = <&sdm632_gpu0_trip>;
+				cooling-device = <&msm_gpu 2 2>;
+			};
+			cx_vdd_cdev {
+				trip = <&sdm632_gpu0_trip>;
+				cooling-device = <&cx_cdev 0 0>;
+			};
+			modem_vdd_cdev {
+				trip = <&sdm632_gpu0_trip>;
+				cooling-device = <&modem_vdd 0 0>;
+			};
+		};
+	};
+};
+
+&clock_cpu {
+	/delete-property/ vdd-cl-supply;
+	status = "disabled";
+	compatible = "qcom,cpu-clock-sdm632";
+	reg =   <0xb114000  0x68>,
+		<0xb014000  0x68>,
+		<0xb016000  0x8>,
+		<0xb116000  0x8>,
+		<0xb1d0000  0x8>,
+		<0xb011050  0x8>,
+		<0xb111050  0x8>,
+		<0xb1d1050  0x8>,
+		<0x00a412c  0x8>;
+	reg-names = "rcgwr-c0-base", "rcgwr-c1-base",
+		    "apcs-c1-pll-base", "apcs-c0-pll-base",
+		    "apcs-cci-pll-base", "apcs-c1-rcg-base",
+		    "apcs-c0-rcg-base", "apcs-cci-rcg-base",
+		    "efuse";
+	qcom,num-clusters = <2>;
+	clocks = <&clock_gcc clk_xo_a_clk_src>;
+	clock-names = "xo_a";
+	qcom,speed0-bin-v0-c0 =
+		<          0 0>,
+		<   614400000 1>,
+		<   883200000 2>,
+		<  1036200000 3>,
+		<  1363200000 4>,
+		<  1563000000 5>,
+		<  1670400000 6>,
+		<  1785600000 7>;
+	qcom,speed0-bin-v0-c1 =
+		<          0 0>,
+		<   633600000 1>,
+		<   902400000 2>,
+		<  1094400000 3>,
+		<  1401600000 4>,
+		<  1555200000 5>,
+		<  1785600000 6>;
+	qcom,speed0-bin-v0-cci =
+		<          0 0>,
+		<  307200000 1>,
+		<  403200000 2>,
+		<  499200000 3>,
+		<  691200000 4>,
+		<  768000000 5>,
+		<  787200000 6>;
+	#clock-cells = <1>;
+};
+
+&apc_vreg {
+	status = "disabled";
+};
diff --git a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
index d9068b1..46e555a5 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-camera.dtsi
@@ -403,13 +403,16 @@
 		label = "cpas";
 		arch-compat = "cpas_top";
 		status = "ok";
-		reg-names = "cam_cpas_top", "cam_camnoc";
+		reg-names = "cam_cpas_top", "cam_camnoc", "core_top_csr_tcsr";
 		reg = <0xac40000 0x1000>,
-			<0xac42000 0x5000>;
-		reg-cam-base = <0x40000 0x42000>;
+			<0xac42000 0x5000>,
+			<0x01fc0000 0x30000>;
+		reg-cam-base = <0x40000 0x42000 0x0>;
 		interrupt-names = "cpas_camnoc";
 		interrupts = <0 459 0>;
 		qcom,cpas-hw-ver = <0x170110>; /* Titan v170 v1.1.0 */
+		nvmem-cells = <&minor_rev>;
+		nvmem-cell-names = "minor_rev";
 		regulator-names = "camss-vdd";
 		camss-vdd-supply = <&titan_top_gdsc>;
 		clock-names = "gcc_ahb_clk",
diff --git a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
index 9acef75..011192a 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-gpu.dtsi
@@ -429,38 +429,74 @@
 
 				qcom,speed-bin = <163>;
 
-				qcom,initial-pwrlevel = <3>;
+				qcom,initial-pwrlevel = <7>;
 
-				/* SVS_L1 */
+				/* TURBO_L1 */
 				qcom,gpu-pwrlevel@0 {
 					reg = <0>;
-					qcom,gpu-freq = <430000000>;
+					qcom,gpu-freq = <780000000>;
 					qcom,bus-freq = <11>;
+					qcom,bus-min = <10>;
+					qcom,bus-max = <11>;
+				};
+
+				/* TURBO */
+				qcom,gpu-pwrlevel@1 {
+					reg = <1>;
+					qcom,gpu-freq = <750000000>;
+					qcom,bus-freq = <11>;
+					qcom,bus-min = <9>;
+					qcom,bus-max = <11>;
+				};
+
+				/* NOM_L1 */
+				qcom,gpu-pwrlevel@2 {
+					reg = <2>;
+					qcom,gpu-freq = <650000000>;
+					qcom,bus-freq = <10>;
 					qcom,bus-min = <8>;
 					qcom,bus-max = <11>;
 				};
 
-				/* SVS */
-				qcom,gpu-pwrlevel@1 {
-					reg = <1>;
-					qcom,gpu-freq = <355000000>;
-					qcom,bus-freq = <8>;
-					qcom,bus-min = <5>;
-					qcom,bus-max = <9>;
+				/* NOM */
+				qcom,gpu-pwrlevel@3 {
+					reg = <3>;
+					qcom,gpu-freq = <565000000>;
+					qcom,bus-freq = <9>;
+					qcom,bus-min = <8>;
+					qcom,bus-max = <10>;
 				};
 
-				/* LOW SVS */
-				qcom,gpu-pwrlevel@2 {
-					reg = <2>;
-					qcom,gpu-freq = <267000000>;
-					qcom,bus-freq = <6>;
-					qcom,bus-min = <4>;
+				/* SVS_L1 */
+				qcom,gpu-pwrlevel@4 {
+					reg = <4>;
+					qcom,gpu-freq = <430000000>;
+					qcom,bus-freq = <8>;
+					qcom,bus-min = <7>;
+					qcom,bus-max = <10>;
+				};
+
+				/* SVS */
+				qcom,gpu-pwrlevel@5 {
+					reg = <5>;
+					qcom,gpu-freq = <355000000>;
+					qcom,bus-freq = <7>;
+					qcom,bus-min = <5>;
 					qcom,bus-max = <8>;
 				};
 
+				/* LOW SVS */
+				qcom,gpu-pwrlevel@6 {
+					reg = <6>;
+					qcom,gpu-freq = <267000000>;
+					qcom,bus-freq = <6>;
+					qcom,bus-min = <4>;
+					qcom,bus-max = <7>;
+				};
+
 				/* MIN SVS */
-				qcom,gpu-pwrlevel@3 {
-					reg = <3>;
+				qcom,gpu-pwrlevel@7 {
+					reg = <7>;
 					qcom,gpu-freq = <180000000>;
 					qcom,bus-freq = <4>;
 					qcom,bus-min = <3>;
@@ -468,8 +504,8 @@
 				};
 
 				/* XO */
-				qcom,gpu-pwrlevel@4 {
-					reg = <4>;
+				qcom,gpu-pwrlevel@8 {
+					reg = <8>;
 					qcom,gpu-freq = <0>;
 					qcom,bus-freq = <0>;
 					qcom,bus-min = <0>;
diff --git a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
index f3e5ddb..b2601ee 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-smp2p.dtsi
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -268,4 +268,16 @@
 		interrupt-controller;
 		#interrupt-cells = <2>;
 	};
+
+	/* wlan - inbound entry from mss/WLAN PD */
+	smp2pgpio_wlan_1_in: qcom,smp2pgpio-wlan-1-in {
+		compatible = "qcom,smp2pgpio";
+		qcom,entry-name = "wlan";
+		qcom,remote-pid = <1>;
+		qcom,is-inbound;
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
index f259838..39cbef0 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-thermal.dtsi
@@ -689,4 +689,133 @@
 			};
 		};
 	};
+
+	vbat_adc {
+		cooling-maps {
+			vbat_map6 {
+				trip = <&pm660_vbat_adc>;
+				cooling-device =
+					<&CPU6 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			vbat_map7 {
+				trip = <&pm660_vbat_adc>;
+				cooling-device =
+					<&CPU7 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	soc {
+		cooling-maps {
+			soc_map6 {
+				trip = <&pm660_low_soc>;
+				cooling-device =
+					<&CPU6 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			soc_map7 {
+				trip = <&pm660_low_soc>;
+				cooling-device =
+					<&CPU7 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
+
+	pm660_temp_alarm: pm660_tz {
+		cooling-maps {
+			trip0_cpu0 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU0 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip0_cpu1 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU1 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip0_cpu2 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU2 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip0_cpu3 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU3 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip0_cpu4 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU4 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip0_cpu5 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU5 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip0_cpu6 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU6 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip0_cpu7 {
+				trip = <&pm660_trip0>;
+				cooling-device =
+					<&CPU7 (THERMAL_MAX_LIMIT-1)
+						(THERMAL_MAX_LIMIT-1)>;
+			};
+			trip1_cpu1 {
+				trip = <&pm660_trip1>;
+				cooling-device =
+					<&CPU1 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			trip1_cpu2 {
+				trip = <&pm660_trip1>;
+				cooling-device =
+					<&CPU2 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			trip1_cpu3 {
+				trip = <&pm660_trip1>;
+				cooling-device =
+					<&CPU3 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			trip1_cpu4 {
+				trip = <&pm660_trip1>;
+				cooling-device =
+					<&CPU4 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			trip1_cpu5 {
+				trip = <&pm660_trip1>;
+				cooling-device =
+					<&CPU5 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			trip1_cpu6 {
+				trip = <&pm660_trip1>;
+				cooling-device =
+					<&CPU6 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+			trip1_cpu7 {
+				trip = <&pm660_trip1>;
+				cooling-device =
+					<&CPU7 THERMAL_MAX_LIMIT
+						THERMAL_MAX_LIMIT>;
+			};
+		};
+	};
 };
diff --git a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
index 3df6d09..8b1f3d1 100644
--- a/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670-usb.dtsi
@@ -35,6 +35,27 @@
 	vdd-supply = <&pm660l_l1>;
 	vdda18-supply = <&pm660_l10>;
 	vdda33-supply = <&pm660l_l7>;
+	qcom,host-chirp-erratum;
+	qcom,qusb-phy-host-init-seq =
+			/* <value reg_offset> */
+			   <0x23 0x210 /* PWR_CTRL1 */
+			    0x03 0x04  /* PLL_ANALOG_CONTROLS_TWO */
+			    0x7c 0x18c /* PLL_CLOCK_INVERTERS */
+			    0x80 0x2c  /* PLL_CMODE */
+			    0x0a 0x184 /* PLL_LOCK_DELAY */
+			    0x19 0xb4  /* PLL_DIGITAL_TIMERS_TWO */
+			    0x40 0x194 /* PLL_BIAS_CONTROL_1 */
+			    0x20 0x198 /* PLL_BIAS_CONTROL_2 */
+			    0x21 0x214 /* PWR_CTRL2 */
+			    0x08 0x220 /* IMP_CTRL1 */
+			    0x58 0x224 /* IMP_CTRL2 */
+			    0x45 0x240 /* TUNE1 */
+			    0x29 0x244 /* TUNE2 */
+			    0xca 0x248 /* TUNE3 */
+			    0x04 0x24c /* TUNE4 */
+			    0x03 0x250 /* TUNE5 */
+			    0x00 0x23c /* CHG_CTRL2 */
+			    0x22 0x210>; /* PWR_CTRL1 */
 	qcom,qusb-phy-init-seq =
 			/* <value reg_offset> */
 			   <0x23 0x210 /* PWR_CTRL1 */
diff --git a/arch/arm64/boot/dts/qcom/sdm670.dtsi b/arch/arm64/boot/dts/qcom/sdm670.dtsi
index e576baf..e6bf8ee 100644
--- a/arch/arm64/boot/dts/qcom/sdm670.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm670.dtsi
@@ -1675,7 +1675,7 @@
 		};
 	};
 
-	qcom,chd_sliver {
+	qcom,chd_silver {
 		compatible = "qcom,core-hang-detect";
 		label = "silver";
 		qcom,threshold-arr = <0x17e00058 0x17e10058 0x17e20058
@@ -2585,6 +2585,8 @@
 		qcom,vdd-3.3-ch0-config = <3000000 3312000>;
 		qcom,wlan-msa-memory = <0x100000>;
 		qcom,wlan-msa-fixed-region = <&wlan_msa_mem>;
+		qcom,gpio-force-fatal-error = <&smp2pgpio_wlan_1_in 0 0>;
+		qcom,gpio-early-crash-ind = <&smp2pgpio_wlan_1_in 1 0>;
 		qcom,smmu-s1-bypass;
 	};
 
@@ -2668,6 +2670,18 @@
 			< 1 >;
 	};
 
+	bus_proxy_client: qcom,bus_proxy_client {
+		compatible = "qcom,bus-proxy-client";
+		qcom,msm-bus,name = "bus-proxy-client";
+		qcom,msm-bus,num-cases = <2>;
+		qcom,msm-bus,num-paths = <2>;
+		qcom,msm-bus,vectors-KBps =
+			<22 512 0 0>, <23 512 0 0>,
+			<22 512 0 5000000>, <23 512 0 5000000>;
+		qcom,msm-bus,active-only;
+		status = "ok";
+	};
+
 	devfreq_memlat_0: qcom,cpu0-memlat-mon {
 		compatible = "qcom,arm-memlat-mon";
 		qcom,cpulist = <&CPU0 &CPU1 &CPU2 &CPU3 &CPU4 &CPU5>;
diff --git a/arch/arm64/boot/dts/qcom/sdm845.dtsi b/arch/arm64/boot/dts/qcom/sdm845.dtsi
index f158f07..a667b01 100644
--- a/arch/arm64/boot/dts/qcom/sdm845.dtsi
+++ b/arch/arm64/boot/dts/qcom/sdm845.dtsi
@@ -87,7 +87,7 @@
 				qcom,dump-size = <0xa000>;
 			};
 			L1_TLB_0: l1-tlb {
-				qcom,dump-size = <0x3000>;
+				qcom,dump-size = <0x6000>;
 			};
 		};
 
@@ -118,7 +118,7 @@
 				qcom,dump-size = <0xa000>;
 			};
 			L1_TLB_100: l1-tlb {
-				qcom,dump-size = <0x3000>;
+				qcom,dump-size = <0x6000>;
 			};
 		};
 
@@ -149,7 +149,7 @@
 				qcom,dump-size = <0xa000>;
 			};
 			L1_TLB_200: l1-tlb {
-				qcom,dump-size = <0x3000>;
+				qcom,dump-size = <0x6000>;
 			};
 		};
 
@@ -180,7 +180,7 @@
 				qcom,dump-size = <0xa000>;
 			};
 			L1_TLB_300: l1-tlb {
-				qcom,dump-size = <0x3000>;
+				qcom,dump-size = <0x6000>;
 			};
 		};
 
@@ -211,7 +211,7 @@
 				qcom,dump-size = <0x14000>;
 			};
 			L1_TLB_400: l1-tlb {
-				qcom,dump-size = <0x3c00>;
+				qcom,dump-size = <0x6800>;
 			};
 		};
 
@@ -242,7 +242,7 @@
 				qcom,dump-size = <0x14000>;
 			};
 			L1_TLB_500: l1-tlb {
-				qcom,dump-size = <0x3c00>;
+				qcom,dump-size = <0x6800>;
 			};
 		};
 
@@ -273,7 +273,7 @@
 				qcom,dump-size = <0x14000>;
 			};
 			L1_TLB_600: l1-tlb {
-				qcom,dump-size = <0x3c00>;
+				qcom,dump-size = <0x6800>;
 			};
 		};
 
@@ -304,7 +304,7 @@
 				qcom,dump-size = <0x14000>;
 			};
 			L1_TLB_700: l1-tlb {
-				qcom,dump-size = <0x3c00>;
+				qcom,dump-size = <0x6800>;
 			};
 		};
 
@@ -2045,35 +2045,35 @@
 		};
 		qcom,l1_tlb_dump0 {
 			qcom,dump-node = <&L1_TLB_0>;
-			qcom,dump-id = <0x20>;
+			qcom,dump-id = <0x120>;
 		};
 		qcom,l1_tlb_dump100 {
 			qcom,dump-node = <&L1_TLB_100>;
-			qcom,dump-id = <0x21>;
+			qcom,dump-id = <0x121>;
 		};
 		qcom,l1_tlb_dump200 {
 			qcom,dump-node = <&L1_TLB_200>;
-			qcom,dump-id = <0x22>;
+			qcom,dump-id = <0x122>;
 		};
 		qcom,l1_tlb_dump300 {
 			qcom,dump-node = <&L1_TLB_300>;
-			qcom,dump-id = <0x23>;
+			qcom,dump-id = <0x123>;
 		};
 		qcom,l1_tlb_dump400 {
 			qcom,dump-node = <&L1_TLB_400>;
-			qcom,dump-id = <0x24>;
+			qcom,dump-id = <0x124>;
 		};
 		qcom,l1_tlb_dump500 {
 			qcom,dump-node = <&L1_TLB_500>;
-			qcom,dump-id = <0x25>;
+			qcom,dump-id = <0x125>;
 		};
 		qcom,l1_tlb_dump600 {
 			qcom,dump-node = <&L1_TLB_600>;
-			qcom,dump-id = <0x26>;
+			qcom,dump-id = <0x126>;
 		};
 		qcom,l1_tlb_dump700 {
 			qcom,dump-node = <&L1_TLB_700>;
-			qcom,dump-id = <0x27>;
+			qcom,dump-id = <0x127>;
 		};
 	};
 
diff --git a/arch/arm64/configs/msm8953-perf_defconfig b/arch/arm64/configs/msm8953-perf_defconfig
index 6e73c48..1db7cbe 100644
--- a/arch/arm64/configs/msm8953-perf_defconfig
+++ b/arch/arm64/configs/msm8953-perf_defconfig
@@ -277,6 +277,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -340,6 +341,8 @@
 CONFIG_QTI_VIRTUAL_SENSOR=y
 CONFIG_QTI_QMI_COOLING_DEVICE=y
 CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_MSM_BCL_PMIC5=y
+CONFIG_QTI_BCL_SOC_DRIVER=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_CPR=y
@@ -464,9 +467,11 @@
 CONFIG_USB_CONFIGFS_F_ACC=y
 CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
 CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
 CONFIG_USB_CONFIGFS_F_HID=y
 CONFIG_USB_CONFIGFS_F_DIAG=y
 CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
@@ -515,6 +520,7 @@
 CONFIG_MAILBOX=y
 CONFIG_ARM_SMMU=y
 CONFIG_QCOM_LAZY_MAPPING=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
 CONFIG_MSM_BOOT_STATS=y
@@ -539,13 +545,17 @@
 CONFIG_ICNSS=y
 CONFIG_MSM_PERFORMANCE=y
 CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_PM=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_SPDM_SCM=y
 CONFIG_DEVFREQ_SPDM=y
diff --git a/arch/arm64/configs/msm8953_defconfig b/arch/arm64/configs/msm8953_defconfig
index 2e924d4..49812fb 100644
--- a/arch/arm64/configs/msm8953_defconfig
+++ b/arch/arm64/configs/msm8953_defconfig
@@ -287,6 +287,7 @@
 CONFIG_PPPOPNS=y
 CONFIG_PPP_ASYNC=y
 CONFIG_PPP_SYNC_TTY=y
+CONFIG_USB_USBNET=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
 CONFIG_CLD_LL_CORE=y
 CONFIG_INPUT_EVDEV=y
@@ -352,6 +353,8 @@
 CONFIG_QTI_VIRTUAL_SENSOR=y
 CONFIG_QTI_QMI_COOLING_DEVICE=y
 CONFIG_REGULATOR_COOLING_DEVICE=y
+CONFIG_MSM_BCL_PMIC5=y
+CONFIG_QTI_BCL_SOC_DRIVER=y
 CONFIG_MFD_SPMI_PMIC=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_CPR=y
@@ -477,9 +480,11 @@
 CONFIG_USB_CONFIGFS_F_ACC=y
 CONFIG_USB_CONFIGFS_F_AUDIO_SRC=y
 CONFIG_USB_CONFIGFS_UEVENT=y
+CONFIG_USB_CONFIGFS_F_MIDI=y
 CONFIG_USB_CONFIGFS_F_HID=y
 CONFIG_USB_CONFIGFS_F_DIAG=y
 CONFIG_USB_CONFIGFS_F_CDEV=y
+CONFIG_USB_CONFIGFS_F_CCID=y
 CONFIG_USB_CONFIGFS_F_QDSS=y
 CONFIG_MMC=y
 CONFIG_MMC_PERF_PROFILING=y
@@ -532,6 +537,7 @@
 CONFIG_IOMMU_DEBUG=y
 CONFIG_IOMMU_DEBUG_TRACKING=y
 CONFIG_IOMMU_TESTS=y
+CONFIG_QCOM_RUN_QUEUE_STATS=y
 CONFIG_MSM_SPM=y
 CONFIG_MSM_L2_SPM=y
 CONFIG_MSM_BOOT_STATS=y
@@ -559,14 +565,18 @@
 CONFIG_ICNSS=y
 CONFIG_MSM_PERFORMANCE=y
 CONFIG_MSM_EVENT_TIMER=y
+CONFIG_MSM_AVTIMER=y
 CONFIG_MSM_PM=y
 CONFIG_QCOM_DCC=y
 CONFIG_QTI_RPM_STATS_LOG=y
 CONFIG_QCOM_FORCE_WDOG_BITE_ON_PANIC=y
 CONFIG_MEM_SHARE_QMI_SERVICE=y
+CONFIG_MSM_BAM_DMUX=y
 CONFIG_WCNSS_CORE=y
 CONFIG_WCNSS_CORE_PRONTO=y
 CONFIG_WCNSS_REGISTER_DUMP_ON_BITE=y
+CONFIG_QCOM_BIMC_BWMON=y
+CONFIG_DEVFREQ_GOV_QCOM_BW_HWMON=y
 CONFIG_QCOM_DEVFREQ_DEVBW=y
 CONFIG_SPDM_SCM=y
 CONFIG_DEVFREQ_SPDM=y
diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c
index c66fa93..63001be 100644
--- a/arch/arm64/mm/mmu.c
+++ b/arch/arm64/mm/mmu.c
@@ -823,6 +823,10 @@
 
 int pud_set_huge(pud_t *pud, phys_addr_t phys, pgprot_t prot)
 {
+	/* ioremap_page_range doesn't honour BBM */
+	if (pud_present(READ_ONCE(*pud)))
+		return 0;
+
 	BUG_ON(phys & ~PUD_MASK);
 	set_pud(pud, __pud(phys | PUD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))));
 	return 1;
@@ -830,6 +834,10 @@
 
 int pmd_set_huge(pmd_t *pmd, phys_addr_t phys, pgprot_t prot)
 {
+	/* ioremap_page_range doesn't honour BBM */
+	if (pmd_present(READ_ONCE(*pmd)))
+		return 0;
+
 	BUG_ON(phys & ~PMD_MASK);
 	set_pmd(pmd, __pmd(phys | PMD_TYPE_SECT | pgprot_val(mk_sect_prot(prot))));
 	return 1;
diff --git a/arch/mn10300/mm/misalignment.c b/arch/mn10300/mm/misalignment.c
index b9920b1..70cef54 100644
--- a/arch/mn10300/mm/misalignment.c
+++ b/arch/mn10300/mm/misalignment.c
@@ -437,7 +437,7 @@
 
 	info.si_signo	= SIGSEGV;
 	info.si_errno	= 0;
-	info.si_code	= 0;
+	info.si_code	= SEGV_MAPERR;
 	info.si_addr	= (void *) regs->pc;
 	force_sig_info(SIGSEGV, &info, current);
 	return;
diff --git a/arch/openrisc/kernel/traps.c b/arch/openrisc/kernel/traps.c
index 3d3f606..605a284 100644
--- a/arch/openrisc/kernel/traps.c
+++ b/arch/openrisc/kernel/traps.c
@@ -302,12 +302,12 @@
 	siginfo_t info;
 
 	if (user_mode(regs)) {
-		/* Send a SIGSEGV */
-		info.si_signo = SIGSEGV;
+		/* Send a SIGBUS */
+		info.si_signo = SIGBUS;
 		info.si_errno = 0;
-		/* info.si_code has been set above */
-		info.si_addr = (void *)address;
-		force_sig_info(SIGSEGV, &info, current);
+		info.si_code = BUS_ADRALN;
+		info.si_addr = (void __user *)address;
+		force_sig_info(SIGBUS, &info, current);
 	} else {
 		printk("KERNEL: Unaligned Access 0x%.8lx\n", address);
 		show_registers(regs);
diff --git a/arch/powerpc/include/asm/hvcall.h b/arch/powerpc/include/asm/hvcall.h
index 0e12cb2..dc0996b 100644
--- a/arch/powerpc/include/asm/hvcall.h
+++ b/arch/powerpc/include/asm/hvcall.h
@@ -319,6 +319,7 @@
 #define H_CPU_BEHAV_BNDS_CHK_SPEC_BAR	(1ull << 61) // IBM bit 2
 
 #ifndef __ASSEMBLY__
+#include <linux/types.h>
 
 /**
  * plpar_hcall_norets: - Make a pseries hypervisor call with no return arguments
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index ff63934..c5b9977 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -607,7 +607,8 @@
 		break;
 	}
 
-	force_sig_info(SIGFPE, &info, current);
+	info.si_signo = SIGFPE;
+	force_sig_info(info.si_signo, &info, current);
 }
 #endif
 
diff --git a/arch/x86/crypto/poly1305_glue.c b/arch/x86/crypto/poly1305_glue.c
index e32142b..28c3720 100644
--- a/arch/x86/crypto/poly1305_glue.c
+++ b/arch/x86/crypto/poly1305_glue.c
@@ -164,7 +164,6 @@
 	.init		= poly1305_simd_init,
 	.update		= poly1305_simd_update,
 	.final		= crypto_poly1305_final,
-	.setkey		= crypto_poly1305_setkey,
 	.descsize	= sizeof(struct poly1305_simd_desc_ctx),
 	.base		= {
 		.cra_name		= "poly1305",
diff --git a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c
index 36870b2..d088050 100644
--- a/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c
+++ b/arch/x86/crypto/sha512-mb/sha512_mb_mgr_init_avx2.c
@@ -57,10 +57,12 @@
 {
 	unsigned int j;
 
-	state->lens[0] = 0;
-	state->lens[1] = 1;
-	state->lens[2] = 2;
-	state->lens[3] = 3;
+	/* initially all lanes are unused */
+	state->lens[0] = 0xFFFFFFFF00000000;
+	state->lens[1] = 0xFFFFFFFF00000001;
+	state->lens[2] = 0xFFFFFFFF00000002;
+	state->lens[3] = 0xFFFFFFFF00000003;
+
 	state->unused_lanes = 0xFF03020100;
 	for (j = 0; j < 4; j++)
 		state->ldata[j].job_in_lane = NULL;
diff --git a/arch/x86/include/asm/vsyscall.h b/arch/x86/include/asm/vsyscall.h
index 9ee8506..62210da 100644
--- a/arch/x86/include/asm/vsyscall.h
+++ b/arch/x86/include/asm/vsyscall.h
@@ -13,7 +13,6 @@
  */
 extern bool emulate_vsyscall(struct pt_regs *regs, unsigned long address);
 extern bool vsyscall_enabled(void);
-extern unsigned long vsyscall_pgprot;
 #else
 static inline void map_vsyscall(void) {}
 static inline bool emulate_vsyscall(struct pt_regs *regs, unsigned long address)
@@ -22,5 +21,6 @@
 }
 static inline bool vsyscall_enabled(void) { return false; }
 #endif
+extern unsigned long vsyscall_pgprot;
 
 #endif /* _ASM_X86_VSYSCALL_H */
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index d49da86..d66224e 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -4967,14 +4967,15 @@
 
 	if (is_guest_mode(vcpu) &&
 	    vector == vmx->nested.posted_intr_nv) {
-		/* the PIR and ON have been set by L1. */
-		kvm_vcpu_trigger_posted_interrupt(vcpu);
 		/*
 		 * If a posted intr is not recognized by hardware,
 		 * we will accomplish it in the next vmentry.
 		 */
 		vmx->nested.pi_pending = true;
 		kvm_make_request(KVM_REQ_EVENT, vcpu);
+		/* the PIR and ON have been set by L1. */
+		if (!kvm_vcpu_trigger_posted_interrupt(vcpu))
+			kvm_vcpu_kick(vcpu);
 		return 0;
 	}
 	return -1;
diff --git a/arch/xtensa/include/asm/futex.h b/arch/xtensa/include/asm/futex.h
index b39531b..72bfc1c 100644
--- a/arch/xtensa/include/asm/futex.h
+++ b/arch/xtensa/include/asm/futex.h
@@ -109,7 +109,6 @@
 			      u32 oldval, u32 newval)
 {
 	int ret = 0;
-	u32 prev;
 
 	if (!access_ok(VERIFY_WRITE, uaddr, sizeof(u32)))
 		return -EFAULT;
@@ -120,26 +119,24 @@
 
 	__asm__ __volatile__ (
 	"	# futex_atomic_cmpxchg_inatomic\n"
-	"1:	l32i	%1, %3, 0\n"
-	"	mov	%0, %5\n"
-	"	wsr	%1, scompare1\n"
-	"2:	s32c1i	%0, %3, 0\n"
-	"3:\n"
+	"	wsr	%5, scompare1\n"
+	"1:	s32c1i	%1, %4, 0\n"
+	"	s32i	%1, %6, 0\n"
+	"2:\n"
 	"	.section .fixup,\"ax\"\n"
 	"	.align 4\n"
-	"4:	.long	3b\n"
-	"5:	l32r	%1, 4b\n"
-	"	movi	%0, %6\n"
+	"3:	.long	2b\n"
+	"4:	l32r	%1, 3b\n"
+	"	movi	%0, %7\n"
 	"	jx	%1\n"
 	"	.previous\n"
 	"	.section __ex_table,\"a\"\n"
-	"	.long 1b,5b,2b,5b\n"
+	"	.long 1b,4b\n"
 	"	.previous\n"
-	: "+r" (ret), "=&r" (prev), "+m" (*uaddr)
-	: "r" (uaddr), "r" (oldval), "r" (newval), "I" (-EFAULT)
+	: "+r" (ret), "+r" (newval), "+m" (*uaddr), "+m" (*uval)
+	: "r" (uaddr), "r" (oldval), "r" (uval), "I" (-EFAULT)
 	: "memory");
 
-	*uval = prev;
 	return ret;
 }
 
diff --git a/block/blk-cgroup.c b/block/blk-cgroup.c
index 8ba0af7..d673a69 100644
--- a/block/blk-cgroup.c
+++ b/block/blk-cgroup.c
@@ -184,7 +184,7 @@
 		goto err_free_blkg;
 	}
 
-	wb_congested = wb_congested_get_create(&q->backing_dev_info,
+	wb_congested = wb_congested_get_create(q->backing_dev_info,
 					       blkcg->css.id,
 					       GFP_NOWAIT | __GFP_NOWARN);
 	if (!wb_congested) {
@@ -469,8 +469,8 @@
 const char *blkg_dev_name(struct blkcg_gq *blkg)
 {
 	/* some drivers (floppy) instantiate a queue w/o disk registered */
-	if (blkg->q->backing_dev_info.dev)
-		return dev_name(blkg->q->backing_dev_info.dev);
+	if (blkg->q->backing_dev_info->dev)
+		return dev_name(blkg->q->backing_dev_info->dev);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(blkg_dev_name);
diff --git a/block/blk-core.c b/block/blk-core.c
index 37b814a..3bf59cd 100644
--- a/block/blk-core.c
+++ b/block/blk-core.c
@@ -75,7 +75,7 @@
 	 * flip its congestion state for events on other blkcgs.
 	 */
 	if (rl == &rl->q->root_rl)
-		clear_wb_congested(rl->q->backing_dev_info.wb.congested, sync);
+		clear_wb_congested(rl->q->backing_dev_info->wb.congested, sync);
 #endif
 }
 
@@ -86,7 +86,7 @@
 #else
 	/* see blk_clear_congested() */
 	if (rl == &rl->q->root_rl)
-		set_wb_congested(rl->q->backing_dev_info.wb.congested, sync);
+		set_wb_congested(rl->q->backing_dev_info->wb.congested, sync);
 #endif
 }
 
@@ -105,22 +105,6 @@
 	q->nr_congestion_off = nr;
 }
 
-/**
- * blk_get_backing_dev_info - get the address of a queue's backing_dev_info
- * @bdev:	device
- *
- * Locates the passed device's request queue and returns the address of its
- * backing_dev_info.  This function can only be called if @bdev is opened
- * and the return value is never NULL.
- */
-struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev)
-{
-	struct request_queue *q = bdev_get_queue(bdev);
-
-	return &q->backing_dev_info;
-}
-EXPORT_SYMBOL(blk_get_backing_dev_info);
-
 void blk_rq_init(struct request_queue *q, struct request *rq)
 {
 	memset(rq, 0, sizeof(*rq));
@@ -586,7 +570,7 @@
 	blk_flush_integrity();
 
 	/* @q won't process any more request, flush async actions */
-	del_timer_sync(&q->backing_dev_info.laptop_mode_wb_timer);
+	del_timer_sync(&q->backing_dev_info->laptop_mode_wb_timer);
 	blk_sync_queue(q);
 
 	if (q->mq_ops)
@@ -598,8 +582,6 @@
 		q->queue_lock = &q->__queue_lock;
 	spin_unlock_irq(lock);
 
-	bdi_unregister(&q->backing_dev_info);
-
 	/* @q is and will stay empty, shutdown and put */
 	blk_put_queue(q);
 }
@@ -695,7 +677,6 @@
 struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
 {
 	struct request_queue *q;
-	int err;
 
 	q = kmem_cache_alloc_node(blk_requestq_cachep,
 				gfp_mask | __GFP_ZERO, node_id);
@@ -710,17 +691,17 @@
 	if (!q->bio_split)
 		goto fail_id;
 
-	q->backing_dev_info.ra_pages =
-			(VM_MAX_READAHEAD * 1024) / PAGE_SIZE;
-	q->backing_dev_info.capabilities = BDI_CAP_CGROUP_WRITEBACK;
-	q->backing_dev_info.name = "block";
-	q->node = node_id;
-
-	err = bdi_init(&q->backing_dev_info);
-	if (err)
+	q->backing_dev_info = bdi_alloc_node(gfp_mask, node_id);
+	if (!q->backing_dev_info)
 		goto fail_split;
 
-	setup_timer(&q->backing_dev_info.laptop_mode_wb_timer,
+	q->backing_dev_info->ra_pages =
+			(VM_MAX_READAHEAD * 1024) / PAGE_SIZE;
+	q->backing_dev_info->capabilities = BDI_CAP_CGROUP_WRITEBACK;
+	q->backing_dev_info->name = "block";
+	q->node = node_id;
+
+	setup_timer(&q->backing_dev_info->laptop_mode_wb_timer,
 		    laptop_mode_timer_fn, (unsigned long) q);
 	setup_timer(&q->timeout, blk_rq_timed_out_timer, (unsigned long) q);
 	INIT_WORK(&q->timeout_work, NULL);
@@ -771,7 +752,7 @@
 fail_ref:
 	percpu_ref_exit(&q->q_usage_counter);
 fail_bdi:
-	bdi_destroy(&q->backing_dev_info);
+	bdi_put(q->backing_dev_info);
 fail_split:
 	bioset_free(q->bio_split);
 fail_id:
@@ -1197,7 +1178,7 @@
 	 * disturb iosched and blkcg but weird is bettern than dead.
 	 */
 	printk_ratelimited(KERN_WARNING "%s: dev %s: request aux data allocation failed, iosched may be disturbed\n",
-			   __func__, dev_name(q->backing_dev_info.dev));
+			   __func__, dev_name(q->backing_dev_info->dev));
 
 	rq->cmd_flags &= ~REQ_ELVPRIV;
 	rq->elv.icq = NULL;
@@ -2739,7 +2720,7 @@
 	BUG_ON(blk_queued_rq(req));
 
 	if (unlikely(laptop_mode) && req->cmd_type == REQ_TYPE_FS)
-		laptop_io_completion(&req->q->backing_dev_info);
+		laptop_io_completion(req->q->backing_dev_info);
 
 	blk_delete_timer(req);
 
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index 478f572..e4ebd79 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -418,7 +418,7 @@
 	bi->tuple_size = template->tuple_size;
 	bi->tag_size = template->tag_size;
 
-	disk->queue->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
+	disk->queue->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
 }
 EXPORT_SYMBOL(blk_integrity_register);
 
@@ -431,7 +431,7 @@
  */
 void blk_integrity_unregister(struct gendisk *disk)
 {
-	disk->queue->backing_dev_info.capabilities &= ~BDI_CAP_STABLE_WRITES;
+	disk->queue->backing_dev_info->capabilities &= ~BDI_CAP_STABLE_WRITES;
 	memset(&disk->queue->integrity, 0, sizeof(struct blk_integrity));
 }
 EXPORT_SYMBOL(blk_integrity_unregister);
diff --git a/block/blk-sysfs.c b/block/blk-sysfs.c
index 9cc8d7c..07c75d0 100644
--- a/block/blk-sysfs.c
+++ b/block/blk-sysfs.c
@@ -75,7 +75,7 @@
 
 static ssize_t queue_ra_show(struct request_queue *q, char *page)
 {
-	unsigned long ra_kb = q->backing_dev_info.ra_pages <<
+	unsigned long ra_kb = q->backing_dev_info->ra_pages <<
 					(PAGE_SHIFT - 10);
 
 	return queue_var_show(ra_kb, (page));
@@ -90,7 +90,7 @@
 	if (ret < 0)
 		return ret;
 
-	q->backing_dev_info.ra_pages = ra_kb >> (PAGE_SHIFT - 10);
+	q->backing_dev_info->ra_pages = ra_kb >> (PAGE_SHIFT - 10);
 
 	return ret;
 }
@@ -627,7 +627,7 @@
 	struct request_queue *q =
 		container_of(kobj, struct request_queue, kobj);
 
-	bdi_exit(&q->backing_dev_info);
+	bdi_put(q->backing_dev_info);
 	blkcg_exit_queue(q);
 
 	if (q->elevator) {
diff --git a/block/compat_ioctl.c b/block/compat_ioctl.c
index 556826a..570021a 100644
--- a/block/compat_ioctl.c
+++ b/block/compat_ioctl.c
@@ -661,7 +661,6 @@
 	struct block_device *bdev = inode->i_bdev;
 	struct gendisk *disk = bdev->bd_disk;
 	fmode_t mode = file->f_mode;
-	struct backing_dev_info *bdi;
 	loff_t size;
 	unsigned int max_sectors;
 
@@ -708,9 +707,8 @@
 	case BLKFRAGET:
 		if (!arg)
 			return -EINVAL;
-		bdi = blk_get_backing_dev_info(bdev);
 		return compat_put_long(arg,
-				       (bdi->ra_pages * PAGE_SIZE) / 512);
+			       (bdev->bd_bdi->ra_pages * PAGE_SIZE) / 512);
 	case BLKROGET: /* compatible */
 		return compat_put_int(arg, bdev_read_only(bdev) != 0);
 	case BLKBSZGET_32: /* get the logical block size (cf. BLKSSZGET) */
@@ -728,8 +726,7 @@
 	case BLKFRASET:
 		if (!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		bdi = blk_get_backing_dev_info(bdev);
-		bdi->ra_pages = (arg * 512) / PAGE_SIZE;
+		bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE;
 		return 0;
 	case BLKGETSIZE:
 		size = i_size_read(bdev->bd_inode);
diff --git a/block/genhd.c b/block/genhd.c
index c6eb25d..6ad0fd0 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -613,7 +613,7 @@
 	disk_alloc_events(disk);
 
 	/* Register BDI before referencing it from bdev */
-	bdi = &disk->queue->backing_dev_info;
+	bdi = disk->queue->backing_dev_info;
 	bdi_register_owner(bdi, disk_to_dev(disk));
 
 	blk_register_region(disk_devt(disk), disk->minors, NULL,
@@ -649,16 +649,27 @@
 			     DISK_PITER_INCL_EMPTY | DISK_PITER_REVERSE);
 	while ((part = disk_part_iter_next(&piter))) {
 		invalidate_partition(disk, part->partno);
+		bdev_unhash_inode(part_devt(part));
 		delete_partition(disk, part->partno);
 	}
 	disk_part_iter_exit(&piter);
 
 	invalidate_partition(disk, 0);
+	bdev_unhash_inode(disk_devt(disk));
 	set_capacity(disk, 0);
 	disk->flags &= ~GENHD_FL_UP;
 
 	sysfs_remove_link(&disk_to_dev(disk)->kobj, "bdi");
-	blk_unregister_queue(disk);
+	if (disk->queue) {
+		/*
+		 * Unregister bdi before releasing device numbers (as they can
+		 * get reused and we'd get clashes in sysfs).
+		 */
+		bdi_unregister(disk->queue->backing_dev_info);
+		blk_unregister_queue(disk);
+	} else {
+		WARN_ON(1);
+	}
 	blk_unregister_region(disk_devt(disk), disk->minors);
 
 	part_stat_set_all(&disk->part0, 0);
@@ -1358,7 +1369,7 @@
 	owner = disk->fops->owner;
 	if (owner && !try_module_get(owner))
 		return NULL;
-	kobj = kobject_get(&disk_to_dev(disk)->kobj);
+	kobj = kobject_get_unless_zero(&disk_to_dev(disk)->kobj);
 	if (kobj == NULL) {
 		module_put(owner);
 		return NULL;
diff --git a/block/ioctl.c b/block/ioctl.c
index 755119c..c4555b1 100644
--- a/block/ioctl.c
+++ b/block/ioctl.c
@@ -502,7 +502,6 @@
 int blkdev_ioctl(struct block_device *bdev, fmode_t mode, unsigned cmd,
 			unsigned long arg)
 {
-	struct backing_dev_info *bdi;
 	void __user *argp = (void __user *)arg;
 	loff_t size;
 	unsigned int max_sectors;
@@ -525,8 +524,7 @@
 	case BLKFRAGET:
 		if (!arg)
 			return -EINVAL;
-		bdi = blk_get_backing_dev_info(bdev);
-		return put_long(arg, (bdi->ra_pages * PAGE_SIZE) / 512);
+		return put_long(arg, (bdev->bd_bdi->ra_pages*PAGE_SIZE) / 512);
 	case BLKROGET:
 		return put_int(arg, bdev_read_only(bdev) != 0);
 	case BLKBSZGET: /* get block device soft block size (cf. BLKSSZGET) */
@@ -553,8 +551,7 @@
 	case BLKFRASET:
 		if(!capable(CAP_SYS_ADMIN))
 			return -EACCES;
-		bdi = blk_get_backing_dev_info(bdev);
-		bdi->ra_pages = (arg * 512) / PAGE_SIZE;
+		bdev->bd_bdi->ra_pages = (arg * 512) / PAGE_SIZE;
 		return 0;
 	case BLKBSZSET:
 		return blkdev_bszset(bdev, mode, argp);
diff --git a/crypto/ahash.c b/crypto/ahash.c
index cce0268..f3fa104 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -625,5 +625,16 @@
 }
 EXPORT_SYMBOL_GPL(ahash_attr_alg);
 
+bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg)
+{
+	struct crypto_alg *alg = &halg->base;
+
+	if (alg->cra_type != &crypto_ahash_type)
+		return crypto_shash_alg_has_setkey(__crypto_shash_alg(alg));
+
+	return __crypto_ahash_alg(alg)->setkey != NULL;
+}
+EXPORT_SYMBOL_GPL(crypto_hash_alg_has_setkey);
+
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Asynchronous cryptographic hash type");
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 0c654e5..af9ad45 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -691,7 +691,8 @@
 	inst->alg.finup  = cryptd_hash_finup_enqueue;
 	inst->alg.export = cryptd_hash_export;
 	inst->alg.import = cryptd_hash_import;
-	inst->alg.setkey = cryptd_hash_setkey;
+	if (crypto_shash_alg_has_setkey(salg))
+		inst->alg.setkey = cryptd_hash_setkey;
 	inst->alg.digest = cryptd_hash_digest_enqueue;
 
 	err = ahash_register_instance(tmpl, inst);
diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
index a14100e..6e9389c 100644
--- a/crypto/mcryptd.c
+++ b/crypto/mcryptd.c
@@ -534,7 +534,8 @@
 	inst->alg.finup  = mcryptd_hash_finup_enqueue;
 	inst->alg.export = mcryptd_hash_export;
 	inst->alg.import = mcryptd_hash_import;
-	inst->alg.setkey = mcryptd_hash_setkey;
+	if (crypto_hash_alg_has_setkey(halg))
+		inst->alg.setkey = mcryptd_hash_setkey;
 	inst->alg.digest = mcryptd_hash_digest_enqueue;
 
 	err = ahash_register_instance(tmpl, inst);
diff --git a/crypto/poly1305_generic.c b/crypto/poly1305_generic.c
index 2df9835d..bca9923 100644
--- a/crypto/poly1305_generic.c
+++ b/crypto/poly1305_generic.c
@@ -51,17 +51,6 @@
 }
 EXPORT_SYMBOL_GPL(crypto_poly1305_init);
 
-int crypto_poly1305_setkey(struct crypto_shash *tfm,
-			   const u8 *key, unsigned int keylen)
-{
-	/* Poly1305 requires a unique key for each tag, which implies that
-	 * we can't set it on the tfm that gets accessed by multiple users
-	 * simultaneously. Instead we expect the key as the first 32 bytes in
-	 * the update() call. */
-	return -ENOTSUPP;
-}
-EXPORT_SYMBOL_GPL(crypto_poly1305_setkey);
-
 static void poly1305_setrkey(struct poly1305_desc_ctx *dctx, const u8 *key)
 {
 	/* r &= 0xffffffc0ffffffc0ffffffc0fffffff */
@@ -80,6 +69,11 @@
 	dctx->s[3] = le32_to_cpuvp(key + 12);
 }
 
+/*
+ * Poly1305 requires a unique key for each tag, which implies that we can't set
+ * it on the tfm that gets accessed by multiple users simultaneously. Instead we
+ * expect the key as the first 32 bytes in the update() call.
+ */
 unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
 					const u8 *src, unsigned int srclen)
 {
@@ -285,7 +279,6 @@
 	.init		= crypto_poly1305_init,
 	.update		= crypto_poly1305_update,
 	.final		= crypto_poly1305_final,
-	.setkey		= crypto_poly1305_setkey,
 	.descsize	= sizeof(struct poly1305_desc_ctx),
 	.base		= {
 		.cra_name		= "poly1305",
diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
index fe03d00..b1815b2 100644
--- a/drivers/acpi/nfit/core.c
+++ b/drivers/acpi/nfit/core.c
@@ -1535,6 +1535,9 @@
 		struct kernfs_node *nfit_kernfs;
 
 		nvdimm = nfit_mem->nvdimm;
+		if (!nvdimm)
+			continue;
+
 		nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit");
 		if (nfit_kernfs)
 			nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs,
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index 2fa8304..7a34310 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -275,8 +275,8 @@
 	device->driver_data = hc;
 
 	acpi_ec_add_query_handler(hc->ec, hc->query_bit, NULL, smbus_alarm, hc);
-	printk(KERN_INFO PREFIX "SBS HC: EC = 0x%p, offset = 0x%0x, query_bit = 0x%0x\n",
-		hc->ec, hc->offset, hc->query_bit);
+	dev_info(&device->dev, "SBS HC: offset = 0x%0x, query_bit = 0x%0x\n",
+		 hc->offset, hc->query_bit);
 
 	return 0;
 }
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index c940382..9b46ef4 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -265,9 +265,9 @@
 	{ PCI_VDEVICE(INTEL, 0x3b23), board_ahci }, /* PCH AHCI */
 	{ PCI_VDEVICE(INTEL, 0x3b24), board_ahci }, /* PCH RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b25), board_ahci }, /* PCH RAID */
-	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH AHCI */
+	{ PCI_VDEVICE(INTEL, 0x3b29), board_ahci }, /* PCH M AHCI */
 	{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
-	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
+	{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH M RAID */
 	{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
 	{ PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
 	{ PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
@@ -290,9 +290,9 @@
 	{ PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
 	{ PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
-	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT M AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
-	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT RAID */
+	{ PCI_VDEVICE(INTEL, 0x1c05), board_ahci }, /* CPT M RAID */
 	{ PCI_VDEVICE(INTEL, 0x1c06), board_ahci }, /* CPT RAID */
 	{ PCI_VDEVICE(INTEL, 0x1c07), board_ahci }, /* CPT RAID */
 	{ PCI_VDEVICE(INTEL, 0x1d02), board_ahci }, /* PBG AHCI */
@@ -301,20 +301,20 @@
 	{ PCI_VDEVICE(INTEL, 0x2826), board_ahci }, /* PBG RAID */
 	{ PCI_VDEVICE(INTEL, 0x2323), board_ahci }, /* DH89xxCC AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1e02), board_ahci }, /* Panther Point AHCI */
-	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point AHCI */
+	{ PCI_VDEVICE(INTEL, 0x1e03), board_ahci }, /* Panther Point M AHCI */
 	{ PCI_VDEVICE(INTEL, 0x1e04), board_ahci }, /* Panther Point RAID */
 	{ PCI_VDEVICE(INTEL, 0x1e05), board_ahci }, /* Panther Point RAID */
 	{ PCI_VDEVICE(INTEL, 0x1e06), board_ahci }, /* Panther Point RAID */
-	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x1e07), board_ahci }, /* Panther Point M RAID */
 	{ PCI_VDEVICE(INTEL, 0x1e0e), board_ahci }, /* Panther Point RAID */
 	{ PCI_VDEVICE(INTEL, 0x8c02), board_ahci }, /* Lynx Point AHCI */
-	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8c03), board_ahci }, /* Lynx Point M AHCI */
 	{ PCI_VDEVICE(INTEL, 0x8c04), board_ahci }, /* Lynx Point RAID */
-	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c05), board_ahci }, /* Lynx Point M RAID */
 	{ PCI_VDEVICE(INTEL, 0x8c06), board_ahci }, /* Lynx Point RAID */
-	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point M RAID */
 	{ PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
-	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point M RAID */
 	{ PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
 	{ PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
 	{ PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
@@ -355,21 +355,21 @@
 	{ PCI_VDEVICE(INTEL, 0x9c87), board_ahci }, /* Wildcat Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x9c8f), board_ahci }, /* Wildcat Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x8c82), board_ahci }, /* 9 Series AHCI */
-	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series AHCI */
+	{ PCI_VDEVICE(INTEL, 0x8c83), board_ahci }, /* 9 Series M AHCI */
 	{ PCI_VDEVICE(INTEL, 0x8c84), board_ahci }, /* 9 Series RAID */
-	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c85), board_ahci }, /* 9 Series M RAID */
 	{ PCI_VDEVICE(INTEL, 0x8c86), board_ahci }, /* 9 Series RAID */
-	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c87), board_ahci }, /* 9 Series M RAID */
 	{ PCI_VDEVICE(INTEL, 0x8c8e), board_ahci }, /* 9 Series RAID */
-	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series RAID */
+	{ PCI_VDEVICE(INTEL, 0x8c8f), board_ahci }, /* 9 Series M RAID */
 	{ PCI_VDEVICE(INTEL, 0x9d03), board_ahci }, /* Sunrise Point-LP AHCI */
 	{ PCI_VDEVICE(INTEL, 0x9d05), board_ahci }, /* Sunrise Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0x9d07), board_ahci }, /* Sunrise Point-LP RAID */
 	{ PCI_VDEVICE(INTEL, 0xa102), board_ahci }, /* Sunrise Point-H AHCI */
-	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H AHCI */
+	{ PCI_VDEVICE(INTEL, 0xa103), board_ahci }, /* Sunrise Point-H M AHCI */
 	{ PCI_VDEVICE(INTEL, 0xa105), board_ahci }, /* Sunrise Point-H RAID */
 	{ PCI_VDEVICE(INTEL, 0xa106), board_ahci }, /* Sunrise Point-H RAID */
-	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H RAID */
+	{ PCI_VDEVICE(INTEL, 0xa107), board_ahci }, /* Sunrise Point-H M RAID */
 	{ PCI_VDEVICE(INTEL, 0xa10f), board_ahci }, /* Sunrise Point-H RAID */
 	{ PCI_VDEVICE(INTEL, 0x2822), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0x2823), board_ahci }, /* Lewisburg AHCI*/
@@ -383,6 +383,11 @@
 	{ PCI_VDEVICE(INTEL, 0xa206), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa252), board_ahci }, /* Lewisburg RAID*/
 	{ PCI_VDEVICE(INTEL, 0xa256), board_ahci }, /* Lewisburg RAID*/
+	{ PCI_VDEVICE(INTEL, 0xa356), board_ahci }, /* Cannon Lake PCH-H RAID */
+	{ PCI_VDEVICE(INTEL, 0x0f22), board_ahci }, /* Bay Trail AHCI */
+	{ PCI_VDEVICE(INTEL, 0x0f23), board_ahci }, /* Bay Trail AHCI */
+	{ PCI_VDEVICE(INTEL, 0x22a3), board_ahci }, /* Cherry Trail AHCI */
+	{ PCI_VDEVICE(INTEL, 0x5ae3), board_ahci }, /* Apollo Lake AHCI */
 
 	/* JMicron 360/1/3/5/6, match class to avoid IDE function */
 	{ PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index 0651010..0335e23 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -165,6 +165,11 @@
 
 	  If you are unsure about this, say N here.
 
+config FW_CACHE
+       bool "Enable firmware caching during suspend"
+       depends on PM_SLEEP
+       default n
+
 config WANT_DEV_COREDUMP
 	bool
 	help
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 914433f..813a191 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -994,7 +994,7 @@
 	return _request_firmware_load(fw_priv, opt_flags, timeout);
 }
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
 /* kill pending requests without uevent to avoid blocking suspend */
 static void kill_requests_without_uevent(void)
 {
@@ -1395,7 +1395,7 @@
 }
 EXPORT_SYMBOL(request_firmware_nowait);
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
 static ASYNC_DOMAIN_EXCLUSIVE(fw_cache_domain);
 
 /**
@@ -1741,7 +1741,7 @@
 	INIT_LIST_HEAD(&fw_cache.head);
 	fw_cache.state = FW_LOADER_NO_CACHE;
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
 	spin_lock_init(&fw_cache.name_lock);
 	INIT_LIST_HEAD(&fw_cache.fw_names);
 
@@ -1768,7 +1768,7 @@
 
 static void __exit firmware_class_exit(void)
 {
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_FW_CACHE
 	unregister_syscore_ops(&fw_syscore_ops);
 	unregister_pm_notifier(&fw_cache.pm_notify);
 #endif
diff --git a/drivers/block/aoe/aoeblk.c b/drivers/block/aoe/aoeblk.c
index ec9d861..027b876 100644
--- a/drivers/block/aoe/aoeblk.c
+++ b/drivers/block/aoe/aoeblk.c
@@ -396,8 +396,8 @@
 	WARN_ON(d->gd);
 	WARN_ON(d->flags & DEVFL_UP);
 	blk_queue_max_hw_sectors(q, BLK_DEF_MAX_SECTORS);
-	q->backing_dev_info.name = "aoe";
-	q->backing_dev_info.ra_pages = READ_AHEAD / PAGE_SIZE;
+	q->backing_dev_info->name = "aoe";
+	q->backing_dev_info->ra_pages = READ_AHEAD / PAGE_SIZE;
 	d->bufpool = mp;
 	d->blkq = gd->queue = q;
 	q->queuedata = d;
diff --git a/drivers/block/drbd/drbd_main.c b/drivers/block/drbd/drbd_main.c
index 8348272..d305f05 100644
--- a/drivers/block/drbd/drbd_main.c
+++ b/drivers/block/drbd/drbd_main.c
@@ -2462,7 +2462,7 @@
 
 	if (get_ldev(device)) {
 		q = bdev_get_queue(device->ldev->backing_bdev);
-		r = bdi_congested(&q->backing_dev_info, bdi_bits);
+		r = bdi_congested(q->backing_dev_info, bdi_bits);
 		put_ldev(device);
 		if (r)
 			reason = 'b';
@@ -2834,8 +2834,8 @@
 	/* we have no partitions. we contain only ourselves. */
 	device->this_bdev->bd_contains = device->this_bdev;
 
-	q->backing_dev_info.congested_fn = drbd_congested;
-	q->backing_dev_info.congested_data = device;
+	q->backing_dev_info->congested_fn = drbd_congested;
+	q->backing_dev_info->congested_data = device;
 
 	blk_queue_make_request(q, drbd_make_request);
 	blk_queue_write_cache(q, true, true);
diff --git a/drivers/block/drbd/drbd_nl.c b/drivers/block/drbd/drbd_nl.c
index f35db29..908c704 100644
--- a/drivers/block/drbd/drbd_nl.c
+++ b/drivers/block/drbd/drbd_nl.c
@@ -1328,11 +1328,13 @@
 	if (b) {
 		blk_queue_stack_limits(q, b);
 
-		if (q->backing_dev_info.ra_pages != b->backing_dev_info.ra_pages) {
+		if (q->backing_dev_info->ra_pages !=
+		    b->backing_dev_info->ra_pages) {
 			drbd_info(device, "Adjusting my ra_pages to backing device's (%lu -> %lu)\n",
-				 q->backing_dev_info.ra_pages,
-				 b->backing_dev_info.ra_pages);
-			q->backing_dev_info.ra_pages = b->backing_dev_info.ra_pages;
+				 q->backing_dev_info->ra_pages,
+				 b->backing_dev_info->ra_pages);
+			q->backing_dev_info->ra_pages =
+						b->backing_dev_info->ra_pages;
 		}
 	}
 	fixup_discard_if_not_supported(q);
@@ -3345,7 +3347,7 @@
 		s->dev_disk_flags = md->flags;
 		q = bdev_get_queue(device->ldev->backing_bdev);
 		s->dev_lower_blocked =
-			bdi_congested(&q->backing_dev_info,
+			bdi_congested(q->backing_dev_info,
 				      (1 << WB_async_congested) |
 				      (1 << WB_sync_congested));
 		put_ldev(device);
diff --git a/drivers/block/drbd/drbd_proc.c b/drivers/block/drbd/drbd_proc.c
index be2b93f..8378142 100644
--- a/drivers/block/drbd/drbd_proc.c
+++ b/drivers/block/drbd/drbd_proc.c
@@ -288,7 +288,7 @@
 			seq_printf(seq, "%2d: cs:Unconfigured\n", i);
 		} else {
 			/* reset device->congestion_reason */
-			bdi_rw_congested(&device->rq_queue->backing_dev_info);
+			bdi_rw_congested(device->rq_queue->backing_dev_info);
 
 			nc = rcu_dereference(first_peer_device(device)->connection->net_conf);
 			wp = nc ? nc->wire_protocol - DRBD_PROT_A + 'A' : ' ';
diff --git a/drivers/block/drbd/drbd_req.c b/drivers/block/drbd/drbd_req.c
index de279fe..cb6bdb7 100644
--- a/drivers/block/drbd/drbd_req.c
+++ b/drivers/block/drbd/drbd_req.c
@@ -938,7 +938,7 @@
 
 	switch (rbm) {
 	case RB_CONGESTED_REMOTE:
-		bdi = &device->ldev->backing_bdev->bd_disk->queue->backing_dev_info;
+		bdi = device->ldev->backing_bdev->bd_disk->queue->backing_dev_info;
 		return bdi_read_congested(bdi);
 	case RB_LEAST_PENDING:
 		return atomic_read(&device->local_cnt) >
diff --git a/drivers/block/pktcdvd.c b/drivers/block/pktcdvd.c
index 90fa4ac..4a5bccd 100644
--- a/drivers/block/pktcdvd.c
+++ b/drivers/block/pktcdvd.c
@@ -1276,7 +1276,7 @@
 	 		&& pd->bio_queue_size <= pd->write_congestion_off);
 	spin_unlock(&pd->lock);
 	if (wakeup) {
-		clear_bdi_congested(&pd->disk->queue->backing_dev_info,
+		clear_bdi_congested(pd->disk->queue->backing_dev_info,
 					BLK_RW_ASYNC);
 	}
 
@@ -2405,7 +2405,7 @@
 	spin_lock(&pd->lock);
 	if (pd->write_congestion_on > 0
 	    && pd->bio_queue_size >= pd->write_congestion_on) {
-		set_bdi_congested(&q->backing_dev_info, BLK_RW_ASYNC);
+		set_bdi_congested(q->backing_dev_info, BLK_RW_ASYNC);
 		do {
 			spin_unlock(&pd->lock);
 			congestion_wait(BLK_RW_ASYNC, HZ);
@@ -2779,7 +2779,7 @@
 	pd->pkt_dev = MKDEV(pktdev_major, idx);
 	ret = pkt_new_dev(pd, dev);
 	if (ret)
-		goto out_new_dev;
+		goto out_mem2;
 
 	/* inherit events of the host device */
 	disk->events = pd->bdev->bd_disk->events;
@@ -2797,8 +2797,6 @@
 	mutex_unlock(&ctl_mutex);
 	return 0;
 
-out_new_dev:
-	blk_cleanup_queue(disk->queue);
 out_mem2:
 	put_disk(disk);
 out_mem:
diff --git a/drivers/block/rbd.c b/drivers/block/rbd.c
index e32badd..2622e14 100644
--- a/drivers/block/rbd.c
+++ b/drivers/block/rbd.c
@@ -4524,7 +4524,7 @@
 	q->limits.discard_zeroes_data = 1;
 
 	if (!ceph_test_opt(rbd_dev->rbd_client->client, NOCRC))
-		q->backing_dev_info.capabilities |= BDI_CAP_STABLE_WRITES;
+		q->backing_dev_info->capabilities |= BDI_CAP_STABLE_WRITES;
 
 	disk->queue = q;
 
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index ed9de1b..58f7c39 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -122,7 +122,7 @@
 {
 	revalidate_disk(zram->disk);
 	/* revalidate_disk reset the BDI_CAP_STABLE_WRITES so set again */
-	zram->disk->queue->backing_dev_info.capabilities |=
+	zram->disk->queue->backing_dev_info->capabilities |=
 		BDI_CAP_STABLE_WRITES;
 }
 
diff --git a/drivers/bluetooth/btsdio.c b/drivers/bluetooth/btsdio.c
index 1cb958e..94e914a 100644
--- a/drivers/bluetooth/btsdio.c
+++ b/drivers/bluetooth/btsdio.c
@@ -31,6 +31,7 @@
 #include <linux/errno.h>
 #include <linux/skbuff.h>
 
+#include <linux/mmc/host.h>
 #include <linux/mmc/sdio_ids.h>
 #include <linux/mmc/sdio_func.h>
 
@@ -291,6 +292,14 @@
 		tuple = tuple->next;
 	}
 
+	/* BCM43341 devices soldered onto the PCB (non-removable) use an
+	 * uart connection for bluetooth, ignore the BT SDIO interface.
+	 */
+	if (func->vendor == SDIO_VENDOR_ID_BROADCOM &&
+	    func->device == SDIO_DEVICE_ID_BROADCOM_43341 &&
+	    !mmc_card_is_removable(func->card->host))
+		return -ENODEV;
+
 	data = devm_kzalloc(&func->dev, sizeof(*data), GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index 6930286..3257647 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -23,6 +23,7 @@
 
 #include <linux/module.h>
 #include <linux/usb.h>
+#include <linux/usb/quirks.h>
 #include <linux/firmware.h>
 #include <asm/unaligned.h>
 
@@ -369,8 +370,8 @@
 #define BTUSB_FIRMWARE_LOADED	7
 #define BTUSB_FIRMWARE_FAILED	8
 #define BTUSB_BOOTING		9
-#define BTUSB_RESET_RESUME	10
-#define BTUSB_DIAG_RUNNING	11
+#define BTUSB_DIAG_RUNNING	10
+#define BTUSB_OOB_WAKE_ENABLED	11
 
 struct btusb_data {
 	struct hci_dev       *hdev;
@@ -2928,9 +2929,9 @@
 
 		/* QCA Rome devices lose their updated firmware over suspend,
 		 * but the USB hub doesn't notice any status change.
-		 * Explicitly request a device reset on resume.
+		 * explicitly request a device reset on resume.
 		 */
-		set_bit(BTUSB_RESET_RESUME, &data->flags);
+		interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
 	}
 
 #ifdef CONFIG_BT_HCIBTUSB_RTL
@@ -2941,7 +2942,7 @@
 		 * but the USB hub doesn't notice any status change.
 		 * Explicitly request a device reset on resume.
 		 */
-		set_bit(BTUSB_RESET_RESUME, &data->flags);
+		interface_to_usbdev(intf)->quirks |= USB_QUIRK_RESET_RESUME;
 	}
 #endif
 
@@ -3098,14 +3099,6 @@
 	btusb_stop_traffic(data);
 	usb_kill_anchored_urbs(&data->tx_anchor);
 
-	/* Optionally request a device reset on resume, but only when
-	 * wakeups are disabled. If wakeups are enabled we assume the
-	 * device will stay powered up throughout suspend.
-	 */
-	if (test_bit(BTUSB_RESET_RESUME, &data->flags) &&
-	    !device_may_wakeup(&data->udev->dev))
-		data->udev->reset_resume = 1;
-
 	return 0;
 }
 
diff --git a/drivers/char/adsprpc.c b/drivers/char/adsprpc.c
index a6cabf7..c9ceb48 100644
--- a/drivers/char/adsprpc.c
+++ b/drivers/char/adsprpc.c
@@ -56,6 +56,8 @@
 #define TZ_PIL_AUTH_QDSP6_PROC 1
 #define ADSP_MMAP_HEAP_ADDR 4
 #define ADSP_MMAP_REMOTE_HEAP_ADDR 8
+#define FASTRPC_DMAHANDLE_NOMAP (16)
+
 #define FASTRPC_ENOSUCH 39
 #define VMID_SSC_Q6     5
 #define VMID_ADSP_Q6    6
@@ -72,6 +74,8 @@
 #define M_CRCLIST	(64)
 #define SESSION_ID_INDEX (30)
 #define FASTRPC_CTX_MAGIC (0xbeeddeed)
+#define FASTRPC_CTX_MAX (256)
+#define FASTRPC_CTXID_MASK (0xFF0)
 
 #define IS_CACHE_ALIGNED(x) (((x) & ((L1_CACHE_BYTES)-1)) == 0)
 
@@ -210,6 +214,7 @@
 	unsigned int magic;
 	unsigned int *attrs;
 	uint32_t *crc;
+	uint64_t ctxid;
 };
 
 struct fastrpc_ctx_lst {
@@ -292,6 +297,8 @@
 	unsigned int latency;
 	bool glink;
 	bool legacy;
+	spinlock_t ctxlock;
+	struct smq_invoke_ctx *ctxtable[FASTRPC_CTX_MAX];
 };
 
 struct fastrpc_mmap {
@@ -667,6 +674,9 @@
 			dma_free_coherent(me->dev, map->size,
 				(void *)map->va, (dma_addr_t)map->phys);
 		}
+	} else if (map->flags == FASTRPC_DMAHANDLE_NOMAP) {
+		if (!IS_ERR_OR_NULL(map->handle))
+			ion_free(fl->apps->client, map->handle);
 	} else {
 		int destVM[1] = {VMID_HLOS};
 		int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC};
@@ -746,6 +756,26 @@
 		map->phys = (uintptr_t)region_phys;
 		map->size = len;
 		map->va = (uintptr_t)region_vaddr;
+	} else if (mflags == FASTRPC_DMAHANDLE_NOMAP) {
+		ion_phys_addr_t iphys;
+
+		VERIFY(err, !IS_ERR_OR_NULL(map->handle =
+				ion_import_dma_buf_fd(fl->apps->client, fd)));
+		if (err)
+			goto bail;
+
+		map->uncached = 1;
+		map->buf = NULL;
+		map->attach = NULL;
+		map->table = NULL;
+		map->va = 0;
+		map->phys = 0;
+
+		err = ion_phys(fl->apps->client, map->handle,
+			&iphys, &map->size);
+		if (err)
+			goto bail;
+		map->phys = (uint64_t)iphys;
 	} else {
 		if (map->attr && (map->attr & FASTRPC_ATTR_KEEP_MAP)) {
 			pr_info("adsprpc: buffer mapped with persist attr %x\n",
@@ -1038,7 +1068,7 @@
 			 struct smq_invoke_ctx **po)
 {
 	struct fastrpc_apps *me = &gfa;
-	int err = 0, bufs, size = 0;
+	int err = 0, bufs, ii, size = 0;
 	struct smq_invoke_ctx *ctx = NULL;
 	struct fastrpc_ctx_lst *clst = &fl->clst;
 	struct fastrpc_ioctl_invoke *invoke = &invokefd->inv;
@@ -1103,6 +1133,21 @@
 	hlist_add_head(&ctx->hn, &clst->pending);
 	spin_unlock(&fl->hlock);
 
+	spin_lock(&me->ctxlock);
+	for (ii = 0; ii < FASTRPC_CTX_MAX; ii++) {
+		if (!me->ctxtable[ii]) {
+			me->ctxtable[ii] = ctx;
+			ctx->ctxid = (ptr_to_uint64(ctx) & ~0xFFF)|(ii << 4);
+			break;
+		}
+	}
+	spin_unlock(&me->ctxlock);
+	VERIFY(err, ii < FASTRPC_CTX_MAX);
+	if (err) {
+		pr_err("adsprpc: out of context memory\n");
+		goto bail;
+	}
+
 	*po = ctx;
 bail:
 	if (ctx && err)
@@ -1125,6 +1170,7 @@
 static void context_free(struct smq_invoke_ctx *ctx)
 {
 	int i;
+	struct fastrpc_apps *me = &gfa;
 	int nbufs = REMOTE_SCALARS_INBUFS(ctx->sc) +
 		    REMOTE_SCALARS_OUTBUFS(ctx->sc);
 	spin_lock(&ctx->fl->hlock);
@@ -1137,6 +1183,17 @@
 	mutex_unlock(&ctx->fl->fl_map_mutex);
 	fastrpc_buf_free(ctx->buf, 1);
 	ctx->magic = 0;
+	ctx->ctxid = 0;
+
+	spin_lock(&me->ctxlock);
+	for (i = 0; i < FASTRPC_CTX_MAX; i++) {
+		if (me->ctxtable[i] == ctx) {
+			me->ctxtable[i] = NULL;
+			break;
+		}
+	}
+	spin_unlock(&me->ctxlock);
+
 	kfree(ctx);
 }
 
@@ -1298,8 +1355,12 @@
 	handles = REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc);
 	mutex_lock(&ctx->fl->fl_map_mutex);
 	for (i = bufs; i < bufs + handles; i++) {
+		int dmaflags = 0;
+
+		if (ctx->attrs && (ctx->attrs[i] & FASTRPC_ATTR_NOMAP))
+			dmaflags = FASTRPC_DMAHANDLE_NOMAP;
 		VERIFY(err, !fastrpc_mmap_create(ctx->fl, ctx->fds[i],
-				FASTRPC_ATTR_NOVA, 0, 0, 0, &ctx->maps[i]));
+			FASTRPC_ATTR_NOVA, 0, 0, dmaflags, &ctx->maps[i]));
 		if (err) {
 			mutex_unlock(&ctx->fl->fl_map_mutex);
 			goto bail;
@@ -1643,7 +1704,7 @@
 		msg->tid |= (1 << SESSION_ID_INDEX);
 	if (kernel)
 		msg->pid = 0;
-	msg->invoke.header.ctx = ptr_to_uint64(ctx) | fl->pd;
+	msg->invoke.header.ctx = ctx->ctxid | fl->pd;
 	msg->invoke.header.handle = handle;
 	msg->invoke.header.sc = ctx->sc;
 	msg->invoke.page.addr = ctx->buf ? ctx->buf->phys : 0;
@@ -1676,19 +1737,30 @@
 {
 	struct fastrpc_apps *me = &gfa;
 	struct smq_invoke_rsp rsp = {0};
-	struct smq_invoke_ctx *ctx;
 	int ret = 0, err = 0;
+	uint32_t index;
 
 	do {
 		ret = smd_read_from_cb(me->channel[cid].chan, &rsp,
 					sizeof(rsp));
 		if (ret != sizeof(rsp))
 			break;
-		ctx = (struct smq_invoke_ctx *)(uint64_to_ptr(rsp.ctx & ~1));
-		VERIFY(err, (ctx && ctx->magic == FASTRPC_CTX_MAGIC));
+
+		index = (uint32_t)((rsp.ctx & FASTRPC_CTXID_MASK) >> 4);
+		VERIFY(err, index < FASTRPC_CTX_MAX);
 		if (err)
 			goto bail;
-		context_notify_user(uint64_to_ptr(rsp.ctx & ~1), rsp.retval);
+
+		VERIFY(err, !IS_ERR_OR_NULL(me->ctxtable[index]));
+		if (err)
+			goto bail;
+
+		VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp.ctx & ~1)) &&
+			me->ctxtable[index]->magic == FASTRPC_CTX_MAGIC));
+		if (err)
+			goto bail;
+
+		context_notify_user(me->ctxtable[index], rsp.retval);
 	} while (ret == sizeof(rsp));
 bail:
 	if (err)
@@ -1722,6 +1794,7 @@
 	INIT_HLIST_HEAD(&me->drivers);
 	INIT_HLIST_HEAD(&me->maps);
 	spin_lock_init(&me->hlock);
+	spin_lock_init(&me->ctxlock);
 	mutex_init(&me->smd_mutex);
 	me->channel = &gcinfo[0];
 	for (i = 0; i < NUM_CHANNELS; i++) {
@@ -2510,19 +2583,29 @@
 	const void *pkt_priv, const void *ptr, size_t size)
 {
 	struct smq_invoke_rsp *rsp = (struct smq_invoke_rsp *)ptr;
-	struct smq_invoke_ctx *ctx;
+	struct fastrpc_apps *me = &gfa;
+	uint32_t index;
 	int err = 0;
 
 	VERIFY(err, (rsp && size >= sizeof(*rsp)));
 	if (err)
 		goto bail;
 
-	ctx = (struct smq_invoke_ctx *)(uint64_to_ptr(rsp->ctx & ~1));
-	VERIFY(err, (ctx && ctx->magic == FASTRPC_CTX_MAGIC));
+	index = (uint32_t)((rsp->ctx & FASTRPC_CTXID_MASK) >> 4);
+	VERIFY(err, index < FASTRPC_CTX_MAX);
 	if (err)
 		goto bail;
 
-	context_notify_user(ctx, rsp->retval);
+	VERIFY(err, !IS_ERR_OR_NULL(me->ctxtable[index]));
+	if (err)
+		goto bail;
+
+	VERIFY(err, ((me->ctxtable[index]->ctxid == (rsp->ctx & ~1)) &&
+		me->ctxtable[index]->magic == FASTRPC_CTX_MAGIC));
+	if (err)
+		goto bail;
+
+	context_notify_user(me->ctxtable[index], rsp->retval);
 bail:
 	if (err)
 		pr_err("adsprpc: invalid response or context\n");
diff --git a/drivers/char/adsprpc_shared.h b/drivers/char/adsprpc_shared.h
index 535160a..bb7b654 100644
--- a/drivers/char/adsprpc_shared.h
+++ b/drivers/char/adsprpc_shared.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -47,6 +47,9 @@
 /* Fastrpc attribute for keeping the map persistent */
 #define FASTRPC_ATTR_KEEP_MAP	0x8
 
+/* Fastrpc attribute for no map */
+#define FASTRPC_ATTR_NOMAP   (16)
+
 /* Driver should operate in parallel with the co-processor */
 #define FASTRPC_MODE_PARALLEL    0
 
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 6e1674b..e81b01a 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -1668,7 +1668,7 @@
 		}
 		if (!param->diag_id ||
 			(param->pd_val < UPD_WLAN) ||
-			(param->pd_val > NUM_MD_SESSIONS)) {
+			(param->pd_val >= NUM_MD_SESSIONS)) {
 			DIAG_LOG(DIAG_DEBUG_USERSPACE,
 			"diag_id support is not present for the pd mask = %d\n",
 			param->pd_mask);
diff --git a/drivers/char/diag/diagfwd_glink.c b/drivers/char/diag/diagfwd_glink.c
index e9683e0..59e45a7 100644
--- a/drivers/char/diag/diagfwd_glink.c
+++ b/drivers/char/diag/diagfwd_glink.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -257,7 +257,8 @@
 static void diag_state_open_glink(void *ctxt);
 static void diag_state_close_glink(void *ctxt);
 static int diag_glink_write(void *ctxt, unsigned char *buf, int len);
-static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len);
+static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len,
+			struct diagfwd_buf_t *fwd_buf);
 static void diag_glink_queue_read(void *ctxt);
 
 static struct diag_peripheral_ops glink_ops = {
@@ -320,7 +321,8 @@
 	return (int)(atomic_read(&info->diag_state));
 }
 
-static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len)
+static int diag_glink_read(void *ctxt, unsigned char *buf, int buf_len,
+			struct diagfwd_buf_t *fwd_buf)
 {
 	struct diag_glink_info *glink_info =  NULL;
 	int ret_val = 0;
diff --git a/drivers/char/diag/diagfwd_peripheral.c b/drivers/char/diag/diagfwd_peripheral.c
index 7908b82..f53d9d5 100644
--- a/drivers/char/diag/diagfwd_peripheral.c
+++ b/drivers/char/diag/diagfwd_peripheral.c
@@ -1286,11 +1286,10 @@
 	 * Logging mode here is reflecting previous mode
 	 * status and will be updated to new mode later.
 	 *
-	 * Keeping the buffers busy for Memory Device Mode.
+	 * Keeping the buffers busy for Memory Device and Multi Mode.
 	 */
 
-	if ((driver->logging_mode != DIAG_USB_MODE) ||
-		driver->usb_connected) {
+	if (driver->logging_mode != DIAG_USB_MODE) {
 		if (fwd_info->buf_1) {
 			atomic_set(&fwd_info->buf_1->in_busy, 0);
 			DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
@@ -1701,7 +1700,8 @@
 
 	DIAG_LOG(DIAG_DEBUG_PERIPHERALS, "issued a read p: %d t: %d buf: %pK\n",
 		 fwd_info->peripheral, fwd_info->type, read_buf);
-	err = fwd_info->p_ops->read(fwd_info->ctxt, read_buf, read_len);
+	err = fwd_info->p_ops->read(fwd_info->ctxt, read_buf, read_len,
+			temp_buf);
 	if (err)
 		goto fail_return;
 
diff --git a/drivers/char/diag/diagfwd_peripheral.h b/drivers/char/diag/diagfwd_peripheral.h
index 4124b17..d8e0b68 100644
--- a/drivers/char/diag/diagfwd_peripheral.h
+++ b/drivers/char/diag/diagfwd_peripheral.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -65,7 +65,8 @@
 	void (*open)(void *ctxt);
 	void (*close)(void *ctxt);
 	int (*write)(void *ctxt, unsigned char *buf, int len);
-	int (*read)(void *ctxt, unsigned char *buf, int len);
+	int (*read)(void *ctxt, unsigned char *buf, int len,
+			struct diagfwd_buf_t *fwd_buf);
 	void (*queue_read)(void *ctxt);
 };
 
diff --git a/drivers/char/diag/diagfwd_smd.c b/drivers/char/diag/diagfwd_smd.c
index 27433a7..d530204 100644
--- a/drivers/char/diag/diagfwd_smd.c
+++ b/drivers/char/diag/diagfwd_smd.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -198,7 +198,8 @@
 static void diag_state_close_smd(void *ctxt);
 static void smd_notify(void *ctxt, unsigned int event);
 static int diag_smd_write(void *ctxt, unsigned char *buf, int len);
-static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len);
+static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len,
+			struct diagfwd_buf_t *fwd_buf);
 static void diag_smd_queue_read(void *ctxt);
 
 static struct diag_peripheral_ops smd_ops = {
@@ -780,7 +781,8 @@
 	return 0;
 }
 
-static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len)
+static int diag_smd_read(void *ctxt, unsigned char *buf, int buf_len,
+			struct diagfwd_buf_t *fwd_buf)
 {
 	int pkt_len = 0;
 	int err = 0;
@@ -791,7 +793,7 @@
 	uint32_t read_len = 0;
 	struct diag_smd_info *smd_info = NULL;
 
-	if (!ctxt || !buf || buf_len <= 0)
+	if (!ctxt || !buf || buf_len <= 0 || !fwd_buf)
 		return -EIO;
 
 	smd_info = (struct diag_smd_info *)ctxt;
@@ -810,7 +812,15 @@
 		diagfwd_channel_read_done(smd_info->fwd_ctxt, buf, 0);
 		return -ERESTARTSYS;
 	}
-
+	if (atomic_read(&fwd_buf->in_busy) == 0) {
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+			"%s closing read thread. Buffer is already marked freed p: %d t: %d buf_num: %d\n",
+			 smd_info->name, GET_BUF_PERIPHERAL(fwd_buf->ctxt),
+			 GET_BUF_TYPE(fwd_buf->ctxt),
+			 GET_BUF_NUM(fwd_buf->ctxt));
+		diag_ws_release();
+		return 0;
+	}
 	/*
 	 * Reset the buffers. Also release the wake source hold earlier.
 	 */
diff --git a/drivers/char/diag/diagfwd_socket.c b/drivers/char/diag/diagfwd_socket.c
index f3c587d..401dbb0f 100644
--- a/drivers/char/diag/diagfwd_socket.c
+++ b/drivers/char/diag/diagfwd_socket.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -224,7 +224,8 @@
 static void diag_state_open_socket(void *ctxt);
 static void diag_state_close_socket(void *ctxt);
 static int diag_socket_write(void *ctxt, unsigned char *buf, int len);
-static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len);
+static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len,
+			struct diagfwd_buf_t *fwd_buf);
 static void diag_socket_queue_read(void *ctxt);
 static void socket_init_work_fn(struct work_struct *work);
 static int socket_ready_notify(struct notifier_block *nb,
@@ -1062,7 +1063,8 @@
 	}
 }
 
-static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len)
+static int diag_socket_read(void *ctxt, unsigned char *buf, int buf_len,
+			struct diagfwd_buf_t *fwd_buf)
 {
 	int err = 0;
 	int pkt_len = 0;
@@ -1082,7 +1084,7 @@
 	if (!info)
 		return -ENODEV;
 
-	if (!buf || !ctxt || buf_len <= 0)
+	if (!buf || !ctxt || buf_len <= 0 || !fwd_buf)
 		return -EINVAL;
 
 	temp = buf;
@@ -1091,13 +1093,17 @@
 	err = wait_event_interruptible(info->read_wait_q,
 				      (info->data_ready > 0) || (!info->hdl) ||
 				      (atomic_read(&info->diag_state) == 0));
-	if (err) {
-		mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
-		diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-		mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
-		return -ERESTARTSYS;
+	if (err)
+		goto fail;
+	if (atomic_read(&fwd_buf->in_busy) == 0) {
+		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
+			"%s closing read thread. Buffer is already marked freed p: %d t: %d buf_num: %d\n",
+			 info->name, GET_BUF_PERIPHERAL(fwd_buf->ctxt),
+			 GET_BUF_TYPE(fwd_buf->ctxt),
+			 GET_BUF_NUM(fwd_buf->ctxt));
+		diag_ws_release();
+		return 0;
 	}
-
 	/*
 	 * There is no need to continue reading over peripheral in this case.
 	 * Release the wake source hold earlier.
@@ -1106,10 +1112,7 @@
 		DIAG_LOG(DIAG_DEBUG_PERIPHERALS,
 			 "%s closing read thread. diag state is closed\n",
 			 info->name);
-		mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
-		diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
-		mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
-		return 0;
+		goto fail;
 	}
 
 	if (!info->hdl) {
@@ -1211,7 +1214,7 @@
 	mutex_lock(&driver->diagfwd_channel_mutex[info->peripheral]);
 	diagfwd_channel_read_done(info->fwd_ctxt, buf, 0);
 	mutex_unlock(&driver->diagfwd_channel_mutex[info->peripheral]);
-	return -EIO;
+	return 0;
 }
 
 static int diag_socket_write(void *ctxt, unsigned char *buf, int len)
diff --git a/drivers/clk/msm/Makefile b/drivers/clk/msm/Makefile
index 74c8055..776e8a8 100644
--- a/drivers/clk/msm/Makefile
+++ b/drivers/clk/msm/Makefile
@@ -19,6 +19,13 @@
 obj-$(CONFIG_ARCH_MSM8937)	+= clock-gcc-8952.o
 obj-$(CONFIG_ARCH_MSM8937)	+= clock-cpu-8939.o
 obj-$(CONFIG_ARCH_MSM8937)	+= clock-rcgwr.o
+obj-$(CONFIG_ARCH_MSM8953)	+= clock-cpu-sdm632.o
+
+# MDM9607
+obj-$(CONFIG_ARCH_MDM9607)      +=clock-gcc-mdm9607.o
+
+# MDM9650
+obj-$(CONFIG_ARCH_MDM9650)      += clock-gcc-mdm9650.o
 endif
 
 obj-y               += mdss/
diff --git a/drivers/clk/msm/clock-alpha-pll.c b/drivers/clk/msm/clock-alpha-pll.c
index dbe8d8e..37e34d5 100644
--- a/drivers/clk/msm/clock-alpha-pll.c
+++ b/drivers/clk/msm/clock-alpha-pll.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -774,6 +774,13 @@
 		writel_relaxed(regval, USER_CTL_HI_REG(pll));
 	}
 
+	if (masks->cal_l_val_mask && pll->cal_l_val) {
+		regval = readl_relaxed(USER_CTL_HI_REG(pll));
+		regval &= ~masks->cal_l_val_mask;
+		regval |= pll->cal_l_val;
+		writel_relaxed(regval, USER_CTL_HI_REG(pll));
+	}
+
 	if (masks->test_ctl_lo_mask) {
 		regval = readl_relaxed(TEST_CTL_LO_REG(pll));
 		regval &= ~masks->test_ctl_lo_mask;
diff --git a/drivers/clk/msm/clock-cpu-sdm632.c b/drivers/clk/msm/clock-cpu-sdm632.c
new file mode 100644
index 0000000..b59739a
--- /dev/null
+++ b/drivers/clk/msm/clock-cpu-sdm632.c
@@ -0,0 +1,1169 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/cpu.h>
+#include <linux/mutex.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/pm_qos.h>
+#include <linux/regulator/consumer.h>
+#include <linux/of.h>
+#include <linux/clk/msm-clock-generic.h>
+#include <linux/suspend.h>
+#include <linux/of_platform.h>
+#include <linux/pm_opp.h>
+#include <soc/qcom/clock-local2.h>
+#include <soc/qcom/pm.h>
+#include <soc/qcom/clock-pll.h>
+#include <soc/qcom/clock-alpha-pll.h>
+#include <linux/regulator/rpm-smd-regulator.h>
+
+#include <dt-bindings/clock/msm-clocks-8953.h>
+
+#include "clock.h"
+
+#define APCS_PLL_MODE		0x0
+#define APCS_PLL_L_VAL		0x8
+#define APCS_PLL_ALPHA_VAL	0x10
+#define APCS_PLL_USER_CTL	0x18
+#define APCS_PLL_CONFIG_CTL_LO	0x20
+#define APCS_PLL_CONFIG_CTL_HI	0x24
+#define APCS_PLL_STATUS		0x28
+#define APCS_PLL_TEST_CTL_LO	0x30
+#define APCS_PLL_TEST_CTL_HI	0x34
+
+#define PLL_MODE(x)	(*(x)->base + (unsigned long) (x)->mode_reg)
+
+#define GLB_DIAG	0x0b11101c
+
+static struct clk_ops clk_ops_variable_rate;
+
+DEFINE_EXT_CLK(xo_a_clk, NULL);
+DEFINE_VDD_REGS_INIT(vdd_cpu, 1);
+
+enum {
+	APCS_C0_PLL_BASE,
+	APCS_C1_PLL_BASE,
+	APCS_CCI_PLL_BASE,
+	N_PLL_BASES,
+};
+
+enum vdd_mx_pll_levels {
+	VDD_MX_OFF,
+	VDD_MX_MIN,
+	VDD_MX_LOWER,
+	VDD_MX_SVS,
+	VDD_MX_NUM,
+};
+
+static int vdd_pll_levels[] = {
+	RPM_REGULATOR_LEVEL_NONE,       /* VDD_PLL_OFF */
+	RPM_REGULATOR_LEVEL_MIN_SVS,    /* VDD_PLL_MIN */
+	RPM_REGULATOR_LEVEL_LOW_SVS,    /* VDD_PLL_LOW_SVS */
+	RPM_REGULATOR_LEVEL_SVS,	/* VDD_PLL_SVS */
+};
+
+static DEFINE_VDD_REGULATORS(vdd_mx, VDD_MX_NUM, 1,
+					vdd_pll_levels, NULL);
+
+#define VDD_MX_FMAX_MAP2(l1, f1, l2, f2) \
+	.vdd_class = &vdd_mx,                  \
+	.fmax = (unsigned long[VDD_MX_NUM]) {   \
+		[VDD_MX_##l1] = (f1),           \
+		[VDD_MX_##l2] = (f2),           \
+	},                                      \
+	.num_fmax = VDD_MX_NUM
+
+#define VDD_MX_FMAX_MAP1(l1, f1) \
+	.vdd_class = &vdd_mx,                  \
+	.fmax = (unsigned long[VDD_MX_NUM]) {   \
+		[VDD_MX_##l1] = (f1),           \
+	},                                      \
+	.num_fmax = VDD_MX_NUM
+
+static void __iomem *virt_bases[N_PLL_BASES];
+
+/* Power PLL */
+static struct pll_clk apcs_c0_pll = {
+	.mode_reg = (void __iomem *)APCS_PLL_MODE,
+	.l_reg = (void __iomem *)APCS_PLL_L_VAL,
+	.alpha_reg = (void __iomem *)APCS_PLL_ALPHA_VAL,
+	.config_reg = (void __iomem *)APCS_PLL_USER_CTL,
+	.config_ctl_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_LO,
+	.config_ctl_hi_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_HI,
+	.test_ctl_lo_reg = (void __iomem *)APCS_PLL_TEST_CTL_LO,
+	.test_ctl_hi_reg = (void __iomem *)APCS_PLL_TEST_CTL_HI,
+	.status_reg = (void __iomem *)APCS_PLL_MODE,
+	.init_test_ctl = true,
+	.test_ctl_dbg = true,
+	.masks = {
+		.main_output_mask = BIT(0),
+		.early_output_mask = BIT(3),
+		.lock_mask = BIT(31),
+	},
+	.vals = {
+		.config_ctl_val = 0x200D4828,
+		.config_ctl_hi_val = 0x006,
+		.test_ctl_hi_val = 0x00004000,
+		.test_ctl_lo_val = 0x1C000000,
+	},
+	.max_rate = 1785600000UL,
+	.min_rate = 614400000UL,
+	.src_rate =  19200000UL,
+	.base = &virt_bases[APCS_C0_PLL_BASE],
+	.c = {
+		.parent = &xo_a_clk.c,
+		.dbg_name = "apcs_c0_pll",
+		.ops = &clk_ops_variable_rate,
+		VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+		CLK_INIT(apcs_c0_pll.c),
+	},
+};
+
+/* Perf PLL */
+static struct pll_clk apcs_c1_pll = {
+	.mode_reg = (void __iomem *)APCS_PLL_MODE,
+	.l_reg = (void __iomem *)APCS_PLL_L_VAL,
+	.alpha_reg = (void __iomem *)APCS_PLL_ALPHA_VAL,
+	.config_reg = (void __iomem *)APCS_PLL_USER_CTL,
+	.config_ctl_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_LO,
+	.config_ctl_hi_reg = (void __iomem *)APCS_PLL_CONFIG_CTL_HI,
+	.test_ctl_lo_reg = (void __iomem *)APCS_PLL_TEST_CTL_LO,
+	.test_ctl_hi_reg = (void __iomem *)APCS_PLL_TEST_CTL_HI,
+	.status_reg = (void __iomem *)APCS_PLL_MODE,
+	.init_test_ctl = true,
+	.test_ctl_dbg = true,
+	.masks = {
+		.main_output_mask = BIT(0),
+		.early_output_mask = BIT(3),
+		.lock_mask = BIT(31),
+	},
+	.vals = {
+		.config_ctl_val = 0x200D4828,
+		.config_ctl_hi_val = 0x006,
+		.test_ctl_hi_val = 0x00004000,
+		.test_ctl_lo_val = 0x1C000000,
+	},
+	.max_rate = 2054400000UL,
+	.min_rate = 633600000UL,
+	.src_rate =  19200000UL,
+	.base = &virt_bases[APCS_C1_PLL_BASE],
+	.c = {
+		.parent = &xo_a_clk.c,
+		.dbg_name = "apcs_c1_pll",
+		.ops = &clk_ops_variable_rate,
+		VDD_MX_FMAX_MAP2(MIN, 1200000000UL, LOWER, 2400000000UL),
+		CLK_INIT(apcs_c1_pll.c),
+	},
+};
+
+static struct alpha_pll_masks pll_masks_p = {
+	.lock_mask = BIT(31),
+	.update_mask = BIT(22),
+	.output_mask = 0xf,
+	.vco_mask = BM(21, 20) >> 20,
+	.vco_shift = 20,
+	.alpha_en_mask = BIT(24),
+	.cal_l_val_mask = BM(31, 16),
+};
+
+static struct alpha_pll_vco_tbl apcs_cci_pll_vco[] = {
+	VCO(2, 500000000, 1000000000),
+};
+
+static struct alpha_pll_clk apcs_cci_pll = {
+	.masks = &pll_masks_p,
+	.offset = 0x1D0000,
+	.vco_tbl = apcs_cci_pll_vco,
+	.num_vco = ARRAY_SIZE(apcs_cci_pll_vco),
+	.enable_config = 0x8,  /* Early output */
+	.slew = true,
+	.config_ctl_val = 0x4001055b,
+	.cal_l_val = 0x27 << 16,  /* Mid of VCO mode - 748.8MHz */
+	.base = &virt_bases[APCS_CCI_PLL_BASE],
+	.c = {
+		.parent = &xo_a_clk.c,
+		.rate = 787200000,
+		.dbg_name = "apcs_cci_pll",
+		.ops = &clk_ops_dyna_alpha_pll,
+		/* TODO: FMAX */
+		VDD_MX_FMAX_MAP1(SVS, 1000000000UL),
+		CLK_INIT(apcs_cci_pll.c),
+	},
+};
+
+enum {
+	A53SS_MUX_PERF,
+	A53SS_MUX_PWR,
+	A53SS_MUX_CCI,
+	A53SS_MUX_NUM,
+};
+
+static const char * const pll_names[] = { "c1", "c0", "cci" };
+static const char * const mux_names[] = { "c1", "c0", "cci" };
+
+struct a53_cpu_clk {
+	u32 cpu_reg_mask;
+	cpumask_t cpumask;
+	bool hw_low_power_ctrl;
+	struct pm_qos_request req;
+	struct clk c;
+	struct latency_level latency_lvl;
+	s32 cpu_latency_no_l2_pc_us;
+};
+
+static struct mux_div_clk a53ssmux_perf = {
+	.ops = &rcg_mux_div_ops,
+	.data = {
+		.max_div = 32,
+		.min_div = 2,
+		.is_half_divider = true,
+	},
+	.c = {
+		.dbg_name = "a53ssmux_perf",
+		.ops = &clk_ops_mux_div_clk,
+		CLK_INIT(a53ssmux_perf.c),
+	},
+	.div_mask = BM(4, 0),
+	.src_mask = BM(10, 8) >> 8,
+	.src_shift = 8,
+	MUX_SRC_LIST(
+		{ &apcs_c1_pll.c, 5},
+	),
+};
+
+static struct mux_div_clk a53ssmux_pwr = {
+	.ops = &rcg_mux_div_ops,
+	.data = {
+		.max_div = 32,
+		.min_div = 2,
+		.is_half_divider = true,
+	},
+	.c = {
+		.dbg_name = "a53ssmux_pwr",
+		.ops = &clk_ops_mux_div_clk,
+		CLK_INIT(a53ssmux_pwr.c),
+	},
+	.div_mask = BM(4, 0),
+	.src_mask = BM(10, 8) >> 8,
+	.src_shift = 8,
+	MUX_SRC_LIST(
+		{ &apcs_c0_pll.c, 5},
+	),
+};
+
+static struct mux_div_clk a53ssmux_cci = {
+	.ops = &rcg_mux_div_ops,
+	.data = {
+		.max_div = 32,
+		.min_div = 2,
+		.is_half_divider = true,
+	},
+	.c = {
+		.dbg_name = "a53ssmux_cci",
+		.ops = &clk_ops_mux_div_clk,
+		CLK_INIT(a53ssmux_cci.c),
+	},
+	.div_mask = BM(4, 0),
+	.src_mask = BM(10, 8) >> 8,
+	.src_shift = 8,
+	MUX_SRC_LIST(
+		{ &apcs_cci_pll.c, 5},
+	),
+};
+
+static struct a53_cpu_clk a53_pwr_clk;
+static struct a53_cpu_clk a53_perf_clk;
+static struct a53_cpu_clk a53_cci_clk;
+
+static void do_nothing(void *unused) { }
+
+static inline struct a53_cpu_clk *to_a53_cpu_clk(struct clk *c)
+{
+	return container_of(c, struct a53_cpu_clk, c);
+}
+
+static enum handoff a53_cpu_clk_handoff(struct clk *c)
+{
+	c->rate = clk_get_rate(c->parent);
+	return HANDOFF_DISABLED_CLK;
+}
+
+static long a53_cpu_clk_round_rate(struct clk *c, unsigned long rate)
+{
+	return clk_round_rate(c->parent, rate);
+}
+
+static int a53_cpu_clk_set_rate(struct clk *c, unsigned long rate)
+{
+	int ret = 0;
+	struct a53_cpu_clk *cpuclk = to_a53_cpu_clk(c);
+	bool hw_low_power_ctrl = cpuclk->hw_low_power_ctrl;
+
+	/*
+	 * If hardware control of the clock tree is enabled during power
+	 * collapse, setup a PM QOS request to prevent power collapse and
+	 * wake up one of the CPUs in this clock domain, to ensure software
+	 * control while the clock rate is being switched.
+	 */
+	if (hw_low_power_ctrl) {
+		memset(&cpuclk->req, 0, sizeof(cpuclk->req));
+		cpumask_copy(&cpuclk->req.cpus_affine,
+				(const struct cpumask *)&cpuclk->cpumask);
+		cpuclk->req.type = PM_QOS_REQ_AFFINE_CORES;
+		pm_qos_add_request(&cpuclk->req, PM_QOS_CPU_DMA_LATENCY,
+				cpuclk->cpu_latency_no_l2_pc_us - 1);
+		smp_call_function_any(&cpuclk->cpumask, do_nothing,
+				NULL, 1);
+	}
+
+	ret = clk_set_rate(c->parent, rate);
+
+	/* Remove PM QOS request */
+	if (hw_low_power_ctrl)
+		pm_qos_remove_request(&cpuclk->req);
+
+	return ret;
+}
+
+static void __iomem *variable_pll_list_registers(struct clk *c, int n,
+				struct clk_register_data **regs, u32 *size)
+{
+	struct pll_clk *pll = to_pll_clk(c);
+	static struct clk_register_data data[] = {
+		{"MODE", 0x0},
+		{"L", 0x8},
+		{"ALPHA", 0x10},
+		{"USER_CTL", 0x18},
+		{"CONFIG_CTL_LO", 0x20},
+		{"CONFIG_CTL_HI", 0x24},
+		{"STATUS", 0x28},
+	};
+	if (n)
+		return ERR_PTR(-EINVAL);
+
+	*regs = data;
+	*size = ARRAY_SIZE(data);
+	return PLL_MODE(pll);
+}
+
+static const struct clk_ops clk_ops_cpu = {
+	.set_rate = a53_cpu_clk_set_rate,
+	.round_rate = a53_cpu_clk_round_rate,
+	.handoff = a53_cpu_clk_handoff,
+};
+
+static struct a53_cpu_clk a53_perf_clk = {
+	.cpu_reg_mask = 0x103,
+	.latency_lvl = {
+		.affinity_level = LPM_AFF_LVL_L2,
+		.reset_level = LPM_RESET_LVL_GDHS,
+		.level_name = "perf",
+	},
+	.cpu_latency_no_l2_pc_us = 280,
+	.c = {
+		.parent = &a53ssmux_perf.c,
+		.ops = &clk_ops_cpu,
+		.vdd_class = &vdd_cpu,
+		.dbg_name = "a53_perf_clk",
+		CLK_INIT(a53_perf_clk.c),
+	},
+};
+
+static struct a53_cpu_clk a53_pwr_clk = {
+	.cpu_reg_mask = 0x3,
+	.latency_lvl = {
+		.affinity_level = LPM_AFF_LVL_L2,
+		.reset_level = LPM_RESET_LVL_GDHS,
+		.level_name = "pwr",
+	},
+	.cpu_latency_no_l2_pc_us = 280,
+	.c = {
+		.parent = &a53ssmux_pwr.c,
+		.ops = &clk_ops_cpu,
+		.vdd_class = &vdd_cpu,
+		.dbg_name = "a53_pwr_clk",
+		CLK_INIT(a53_pwr_clk.c),
+	},
+};
+
+static struct a53_cpu_clk a53_cci_clk = {
+	.c = {
+		.parent = &a53ssmux_cci.c,
+		.ops = &clk_ops_cpu,
+		.vdd_class = &vdd_cpu,
+		.dbg_name = "a53_cci_clk",
+		CLK_INIT(a53_cci_clk.c),
+	},
+};
+
+static void __iomem *meas_base;
+
+static struct measure_clk apc0_m_clk = {
+	.c = {
+		.ops = &clk_ops_empty,
+		.dbg_name = "apc0_m_clk",
+		CLK_INIT(apc0_m_clk.c),
+	},
+};
+
+static struct measure_clk apc1_m_clk = {
+	.c = {
+		.ops = &clk_ops_empty,
+		.dbg_name = "apc1_m_clk",
+		CLK_INIT(apc1_m_clk.c),
+	},
+};
+
+static struct measure_clk cci_m_clk = {
+	.c = {
+		.ops = &clk_ops_empty,
+		.dbg_name = "cci_m_clk",
+		CLK_INIT(cci_m_clk.c),
+	},
+};
+
+static struct mux_clk cpu_debug_ter_mux = {
+	.ops = &mux_reg_ops,
+	.mask = 0x3,
+	.shift = 8,
+	MUX_SRC_LIST(
+		{ &apc0_m_clk.c, 0},
+		{ &apc1_m_clk.c, 1},
+		{ &cci_m_clk.c,  2},
+	),
+	.base = &meas_base,
+	.c = {
+		.dbg_name = "cpu_debug_ter_mux",
+		.ops = &clk_ops_gen_mux,
+		CLK_INIT(cpu_debug_ter_mux.c),
+	},
+};
+
+static struct mux_clk cpu_debug_sec_mux = {
+	.ops = &mux_reg_ops,
+	.mask = 0x7,
+	.shift = 12,
+	MUX_SRC_LIST(
+		{ &cpu_debug_ter_mux.c, 0},
+	),
+	MUX_REC_SRC_LIST(
+		&cpu_debug_ter_mux.c,
+	),
+	.base = &meas_base,
+	.c = {
+		.dbg_name = "cpu_debug_sec_mux",
+		.ops = &clk_ops_gen_mux,
+		CLK_INIT(cpu_debug_sec_mux.c),
+	},
+};
+
+static struct mux_clk cpu_debug_pri_mux = {
+	.ops = &mux_reg_ops,
+	.mask = 0x3,
+	.shift = 16,
+	MUX_SRC_LIST(
+		{ &cpu_debug_sec_mux.c, 0},
+	),
+	MUX_REC_SRC_LIST(
+		&cpu_debug_sec_mux.c,
+	),
+	.base = &meas_base,
+	.c = {
+		.dbg_name = "cpu_debug_pri_mux",
+		.ops = &clk_ops_gen_mux,
+		CLK_INIT(cpu_debug_pri_mux.c),
+	},
+};
+
+static struct clk_lookup a53_cpu_clocks[] = {
+	/* PLLs */
+	CLK_LIST(apcs_c0_pll),
+	CLK_LIST(apcs_c1_pll),
+	CLK_LIST(apcs_cci_pll),
+
+	/* Muxes */
+	CLK_LIST(a53ssmux_pwr),
+	CLK_LIST(a53ssmux_perf),
+	CLK_LIST(a53ssmux_cci),
+
+	/* CPU clocks */
+	CLK_LIST(a53_pwr_clk),
+	CLK_LIST(a53_perf_clk),
+	CLK_LIST(a53_cci_clk),
+
+	/* debug clocks */
+	CLK_LIST(apc0_m_clk),
+	CLK_LIST(apc1_m_clk),
+	CLK_LIST(cci_m_clk),
+	CLK_LIST(cpu_debug_pri_mux),
+};
+
+static struct pll_clk *a53sspll[] = { &apcs_c1_pll, &apcs_c0_pll };
+
+static struct mux_div_clk *a53ssmux[] = { &a53ssmux_perf, &a53ssmux_pwr,
+						&a53ssmux_cci };
+
+static struct a53_cpu_clk *cpuclk[] = { &a53_perf_clk, &a53_pwr_clk,
+						&a53_cci_clk };
+
+static struct clk *logical_cpu_to_clk(int cpu)
+{
+	struct device_node *cpu_node = of_get_cpu_node(cpu, NULL);
+	u32 reg;
+
+	if (cpu_node && !of_property_read_u32(cpu_node, "reg", &reg)) {
+		if ((reg | a53_pwr_clk.cpu_reg_mask) ==
+						a53_pwr_clk.cpu_reg_mask)
+			return &a53_pwr_clk.c;
+		if ((reg | a53_perf_clk.cpu_reg_mask) ==
+						a53_perf_clk.cpu_reg_mask)
+			return &a53_perf_clk.c;
+	}
+
+	return NULL;
+}
+
+static int of_get_fmax_vdd_class(struct platform_device *pdev, struct clk *c,
+								char *prop_name)
+{
+	struct device_node *of = pdev->dev.of_node;
+	int prop_len, i;
+	struct clk_vdd_class *vdd = c->vdd_class;
+	u32 *array;
+
+	if (!of_find_property(of, prop_name, &prop_len)) {
+		dev_err(&pdev->dev, "missing %s\n", prop_name);
+		return -EINVAL;
+	}
+
+	prop_len /= sizeof(u32);
+	if (prop_len % 2) {
+		dev_err(&pdev->dev, "bad length %d\n", prop_len);
+		return -EINVAL;
+	}
+
+	prop_len /= 2;
+	vdd->level_votes = devm_kzalloc(&pdev->dev,
+				prop_len * sizeof(*vdd->level_votes),
+					GFP_KERNEL);
+	if (!vdd->level_votes)
+		return -ENOMEM;
+
+	vdd->vdd_uv = devm_kzalloc(&pdev->dev, prop_len * sizeof(int),
+					GFP_KERNEL);
+	if (!vdd->vdd_uv)
+		return -ENOMEM;
+
+	c->fmax = devm_kzalloc(&pdev->dev, prop_len * sizeof(unsigned long),
+					GFP_KERNEL);
+	if (!c->fmax)
+		return -ENOMEM;
+
+	array = devm_kzalloc(&pdev->dev,
+			prop_len * sizeof(u32) * 2, GFP_KERNEL);
+	if (!array)
+		return -ENOMEM;
+
+	of_property_read_u32_array(of, prop_name, array, prop_len * 2);
+	for (i = 0; i < prop_len; i++) {
+		c->fmax[i] = array[2 * i];
+		vdd->vdd_uv[i] = array[2 * i + 1];
+	}
+
+	devm_kfree(&pdev->dev, array);
+	vdd->num_levels = prop_len;
+	vdd->cur_level = prop_len;
+	vdd->use_max_uV = true;
+	c->num_fmax = prop_len;
+	return 0;
+}
+
+static void get_speed_bin(struct platform_device *pdev, int *bin,
+								int *version)
+{
+	struct resource *res;
+	void __iomem *base;
+	u32 pte_efuse;
+
+	*bin = 0;
+	*version = 0;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "efuse");
+	if (!res) {
+		dev_info(&pdev->dev,
+			 "No speed/PVS binning available. Defaulting to 0!\n");
+		return;
+	}
+
+	base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!base) {
+		dev_warn(&pdev->dev,
+			 "Unable to read efuse data. Defaulting to 0!\n");
+		return;
+	}
+
+	pte_efuse = readl_relaxed(base);
+	devm_iounmap(&pdev->dev, base);
+
+	*bin = (pte_efuse >> 8) & 0x7;
+
+	dev_info(&pdev->dev, "Speed bin: %d PVS Version: %d\n", *bin,
+								*version);
+}
+
+static int cpu_parse_pll_data(struct platform_device *pdev, int pll_count)
+{
+	int pll_num;
+	struct resource *res;
+	struct clk *c;
+	char pll_name[] = "apcs-xxx-pll-base";
+
+	for (pll_num = 0; pll_num < pll_count; pll_num++) {
+		snprintf(pll_name, ARRAY_SIZE(pll_name), "apcs-%s-pll-base",
+						pll_names[pll_num]);
+
+		res = platform_get_resource_byname(pdev,
+						IORESOURCE_MEM, pll_name);
+		if (!res) {
+			dev_err(&pdev->dev, "missing %s\n", pll_name);
+			return -EINVAL;
+		}
+
+		if (pll_num < APCS_CCI_PLL_BASE) {
+			a53sspll[pll_num]->base = devm_ioremap(&pdev->dev,
+					res->start, resource_size(res));
+			if (!a53sspll[pll_num]->base) {
+				dev_err(&pdev->dev, "ioremap failed for %s\n",
+								pll_name);
+				return -ENOMEM;
+			}
+		} else {
+			apcs_cci_pll.base = devm_ioremap(&pdev->dev,
+				res->start, resource_size(res));
+			if (!apcs_cci_pll.base) {
+				dev_err(&pdev->dev, "ioremap failed for %s\n",
+					pll_name);
+				return -ENOMEM;
+			}
+		}
+	}
+
+	c = devm_clk_get(&pdev->dev, "xo_a");
+	if (IS_ERR(c)) {
+		if (PTR_ERR(c) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Unable to get xo clock\n");
+		return PTR_ERR(c);
+	}
+	xo_a_clk.c.parent = c;
+
+	return 0;
+}
+
+static int cpu_parse_devicetree(struct platform_device *pdev, int mux_id)
+{
+	struct resource *res;
+	char rcg_name[] = "apcs-xxx-rcg-base";
+	char vdd_name[] = "vdd-xxx";
+	struct regulator *regulator;
+
+	snprintf(rcg_name, ARRAY_SIZE(rcg_name), "apcs-%s-rcg-base",
+						mux_names[mux_id]);
+
+	res = platform_get_resource_byname(pdev,
+					IORESOURCE_MEM, rcg_name);
+	if (!res) {
+		dev_err(&pdev->dev, "missing %s\n", rcg_name);
+		return -EINVAL;
+	}
+
+	a53ssmux[mux_id]->base = devm_ioremap(&pdev->dev, res->start,
+							resource_size(res));
+	if (!a53ssmux[mux_id]->base) {
+		dev_err(&pdev->dev, "ioremap failed for %s\n", rcg_name);
+		return -ENOMEM;
+	}
+
+	snprintf(vdd_name, ARRAY_SIZE(vdd_name), "vdd-%s", mux_names[mux_id]);
+	regulator = devm_regulator_get(&pdev->dev, vdd_name);
+	if (IS_ERR(regulator)) {
+		if (PTR_ERR(regulator) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "unable to get regulator\n");
+		return PTR_ERR(regulator);
+	}
+
+	cpuclk[mux_id]->c.vdd_class->regulator[0] = regulator;
+
+	return 0;
+}
+
+static int add_opp(struct clk *c, struct device *cpudev, struct device *vregdev,
+			unsigned long max_rate)
+{
+	unsigned long rate = 0;
+	int level;
+	long ret, uv, corner;
+	int j = 1;
+
+	while (1) {
+		rate = c->fmax[j++];
+
+		level = find_vdd_level(c, rate);
+		if (level <= 0) {
+			pr_warn("clock-cpu: no vdd level for %lu.\n", rate);
+			return -EINVAL;
+		}
+
+		corner = c->vdd_class->vdd_uv[level];
+		if (corner < 0)
+			return -EINVAL;
+
+		/* Get actual voltage corresponding to each corner */
+		uv = regulator_list_corner_voltage(c->vdd_class->regulator[0],
+							corner);
+		if (uv < 0) {
+			pr_warn("%s: no uv for corner %ld - err: %ld\n",
+						c->dbg_name, corner, uv);
+			return uv;
+		}
+
+		/*
+		 * Populate both CPU and regulator devices with the
+		 * freq-to-corner OPP table to maintain backward
+		 * compatibility.
+		 */
+		ret = dev_pm_opp_add(cpudev, rate, uv);
+		if (ret) {
+			pr_warn("clock-cpu: couldn't add OPP for %lu\n",
+				rate);
+			return ret;
+		}
+
+		ret = dev_pm_opp_add(vregdev, rate, uv);
+		if (ret) {
+			pr_warn("clock-cpu: couldn't add OPP for %lu\n",
+				rate);
+			return ret;
+		}
+
+		if (rate >= max_rate)
+			break;
+	}
+
+	return 0;
+}
+
+static void print_opp_table(int a53_c0_cpu, int a53_c1_cpu)
+{
+	struct dev_pm_opp *oppfmax, *oppfmin;
+	unsigned long apc0_fmax, apc1_fmax, apc0_fmin, apc1_fmin;
+
+	apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
+	apc0_fmin = a53_pwr_clk.c.fmax[1];
+	apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
+	apc1_fmin = a53_perf_clk.c.fmax[1];
+
+	rcu_read_lock();
+	oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu),
+						apc0_fmax, true);
+	oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c0_cpu),
+						apc0_fmin, true);
+	/*
+	 * One time information during boot. Important to know that this
+	 * looks sane since it can eventually make its way to the
+	 * scheduler.
+	 */
+	pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n",
+			apc0_fmin, dev_pm_opp_get_voltage(oppfmin));
+	pr_info("clock_cpu: a53_c0: OPP voltage for %lu: %ld\n",
+			apc0_fmax, dev_pm_opp_get_voltage(oppfmax));
+
+	oppfmax = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu),
+						apc1_fmax, true);
+	oppfmin = dev_pm_opp_find_freq_exact(get_cpu_device(a53_c1_cpu),
+						apc1_fmin, true);
+	pr_info("clock_cpu: a53_c1: OPP voltage for %lu: %lu\n", apc1_fmin,
+		dev_pm_opp_get_voltage(oppfmin));
+	pr_info("clock_cpu: a53_c1: OPP voltage for %lu: %lu\n", apc1_fmax,
+		dev_pm_opp_get_voltage(oppfmax));
+	rcu_read_unlock();
+}
+
+static void populate_opp_table(struct platform_device *pdev)
+{
+	struct platform_device *apc0_dev, *apc1_dev;
+	struct device_node *apc0_node = NULL, *apc1_node;
+	unsigned long apc0_fmax, apc1_fmax;
+	int cpu, a53_c0_cpu = 0, a53_c1_cpu = 0;
+
+	apc0_node = of_parse_phandle(pdev->dev.of_node,
+						"vdd-c0-supply", 0);
+	if (!apc0_node) {
+		pr_err("can't find the apc0 dt node.\n");
+		return;
+	}
+
+	apc1_node = of_parse_phandle(pdev->dev.of_node, "vdd-c1-supply", 0);
+	if (!apc1_node) {
+		pr_err("can't find the apc1 dt node.\n");
+		return;
+	}
+
+	apc0_dev = of_find_device_by_node(apc0_node);
+	if (!apc0_dev) {
+		pr_err("can't find the apc0 device node.\n");
+		return;
+	}
+
+	apc1_dev = of_find_device_by_node(apc1_node);
+	if (!apc1_dev) {
+		pr_err("can't find the apc1 device node.\n");
+		return;
+	}
+
+	apc0_fmax = a53_pwr_clk.c.fmax[a53_pwr_clk.c.num_fmax - 1];
+
+	apc1_fmax = a53_perf_clk.c.fmax[a53_perf_clk.c.num_fmax - 1];
+
+	for_each_possible_cpu(cpu) {
+		if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c) {
+			a53_c0_cpu = cpu;
+			WARN(add_opp(&a53_pwr_clk.c, get_cpu_device(cpu),
+			&apc0_dev->dev,		apc0_fmax),
+				"Failed to add OPP levels for %d\n", cpu);
+		}
+		if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c) {
+			a53_c1_cpu = cpu;
+			WARN(add_opp(&a53_perf_clk.c, get_cpu_device(cpu),
+			&apc1_dev->dev,		apc1_fmax),
+				"Failed to add OPP levels for %d\n", cpu);
+		}
+	}
+	/* One time print during bootup */
+	pr_info("clock-cpu: OPP tables populated (cpu %d and %d)",
+		a53_c0_cpu, a53_c1_cpu);
+
+	print_opp_table(a53_c0_cpu, a53_c1_cpu);
+
+}
+
+static int clock_sdm632_pm_event(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	switch (event) {
+	case PM_POST_HIBERNATION:
+	case PM_POST_SUSPEND:
+		clk_unprepare(&a53_pwr_clk.c);
+		clk_unprepare(&a53_perf_clk.c);
+		clk_unprepare(&a53_cci_clk.c);
+		break;
+	case PM_HIBERNATION_PREPARE:
+	case PM_SUSPEND_PREPARE:
+		clk_prepare(&a53_pwr_clk.c);
+		clk_prepare(&a53_perf_clk.c);
+		clk_prepare(&a53_cci_clk.c);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_DONE;
+}
+
+static struct notifier_block clock_sdm632_pm_notifier = {
+	.notifier_call = clock_sdm632_pm_event,
+};
+
+/**
+ * clock_panic_callback() - panic notification callback function.
+ *		This function is invoked when a kernel panic occurs.
+ * @nfb:	Notifier block pointer
+ * @event:	Value passed unmodified to notifier function
+ * @data:	Pointer passed unmodified to notifier function
+ *
+ * Return: NOTIFY_OK
+ */
+static int clock_panic_callback(struct notifier_block *nfb,
+					unsigned long event, void *data)
+{
+	unsigned long rate;
+
+	rate  = (a53_perf_clk.c.count) ? a53_perf_clk.c.rate : 0;
+	pr_err("%s frequency: %10lu Hz\n", a53_perf_clk.c.dbg_name, rate);
+
+	rate  = (a53_pwr_clk.c.count) ? a53_pwr_clk.c.rate : 0;
+	pr_err("%s frequency: %10lu Hz\n", a53_pwr_clk.c.dbg_name, rate);
+
+	return NOTIFY_OK;
+}
+
+static struct notifier_block clock_panic_notifier = {
+	.notifier_call = clock_panic_callback,
+	.priority = 1,
+};
+
+/* Configure PLL at Nominal frequency */
+static unsigned long pwrcl_early_boot_rate = 1363200000;
+static unsigned long perfcl_early_boot_rate = 1401600000;
+static unsigned long cci_early_boot_rate = 691200000;
+
+static int clock_a53_probe(struct platform_device *pdev)
+{
+	int speed_bin, version, rc, cpu, mux_id;
+	char prop_name[] = "qcom,speedX-bin-vX-XXX";
+	int mux_num = A53SS_MUX_NUM;
+
+	get_speed_bin(pdev, &speed_bin, &version);
+
+	rc = cpu_parse_pll_data(pdev, N_PLL_BASES);
+	if (rc)
+		return rc;
+
+	/* PLL core logic */
+	vdd_mx.regulator[0] = devm_regulator_get(&pdev->dev, "vdd-mx");
+	if (IS_ERR(vdd_mx.regulator[0])) {
+		dev_err(&pdev->dev, "Get vdd-mx regulator!!!\n");
+		if (PTR_ERR(vdd_mx.regulator[0]) != -EPROBE_DEFER)
+			dev_err(&pdev->dev,
+				"Unable to get vdd-mx regulator!!!\n");
+		return PTR_ERR(vdd_mx.regulator[0]);
+	}
+
+	for (mux_id = 0; mux_id < mux_num; mux_id++) {
+		rc = cpu_parse_devicetree(pdev, mux_id);
+		if (rc)
+			return rc;
+
+		snprintf(prop_name, ARRAY_SIZE(prop_name),
+					"qcom,speed%d-bin-v%d-%s",
+					speed_bin, version, mux_names[mux_id]);
+
+		rc = of_get_fmax_vdd_class(pdev, &cpuclk[mux_id]->c,
+								prop_name);
+		if (rc) {
+			/* Fall back to most conservative PVS table */
+			dev_err(&pdev->dev, "Unable to load voltage plan %s!\n",
+								prop_name);
+
+			snprintf(prop_name, ARRAY_SIZE(prop_name),
+				"qcom,speed0-bin-v0-%s", mux_names[mux_id]);
+			rc = of_get_fmax_vdd_class(pdev, &cpuclk[mux_id]->c,
+								prop_name);
+			if (rc) {
+				dev_err(&pdev->dev,
+					"Unable to load safe voltage plan\n");
+				return rc;
+			}
+			dev_info(&pdev->dev, "Safe voltage plan loaded.\n");
+		}
+	}
+
+	/* Debug MUX */
+	meas_base = devm_ioremap(&pdev->dev, GLB_DIAG, SZ_8);
+	if (!meas_base) {
+		dev_err(&pdev->dev, "Failed to ioremap GLB_DIAG registers\n");
+		return -ENOMEM;
+	}
+
+	rc = of_msm_clock_register(pdev->dev.of_node, a53_cpu_clocks,
+						ARRAY_SIZE(a53_cpu_clocks));
+
+	if (rc) {
+		dev_err(&pdev->dev, "msm_clock_register failed\n");
+		return rc;
+	}
+
+	/* Force to move to PLL configuartion */
+	rc = clk_set_rate(&a53_cci_clk.c, cci_early_boot_rate);
+	if (rc)
+		dev_err(&pdev->dev, "Can't set CCI PLL rate for CCI\n");
+
+	rc = clk_set_rate(&a53_pwr_clk.c, pwrcl_early_boot_rate);
+	if (rc)
+		dev_err(&pdev->dev, "Can't set pwr PLL rate for Cluster-0 %ld\n",
+					pwrcl_early_boot_rate);
+
+	rc = clk_set_rate(&a53_perf_clk.c, perfcl_early_boot_rate);
+	if (rc)
+		dev_err(&pdev->dev, "Can't set perf PLL rate for Cluster-1 %ld\n",
+					perfcl_early_boot_rate);
+
+	rc = clock_rcgwr_init(pdev);
+	if (rc)
+		dev_err(&pdev->dev, "Failed to init RCGwR\n");
+
+	/*
+	 * We don't want the CPU clocks to be turned off at late init
+	 * if CPUFREQ or HOTPLUG configs are disabled. So, bump up the
+	 * refcount of these clocks. Any cpufreq/hotplug manager can assume
+	 * that the clocks have already been prepared and enabled by the time
+	 * they take over.
+	 */
+	get_online_cpus();
+	for_each_online_cpu(cpu) {
+		WARN(clk_prepare_enable(&cpuclk[cpu/4]->c),
+				"Unable to turn on CPU clock");
+		WARN(clk_prepare_enable(&a53_cci_clk.c),
+				"Unable to turn on CCI clock");
+	}
+	put_online_cpus();
+
+	for_each_possible_cpu(cpu) {
+		if (logical_cpu_to_clk(cpu) == &a53_perf_clk.c)
+			cpumask_set_cpu(cpu, &a53_perf_clk.cpumask);
+		if (logical_cpu_to_clk(cpu) == &a53_pwr_clk.c)
+			cpumask_set_cpu(cpu, &a53_pwr_clk.cpumask);
+	}
+
+	a53_pwr_clk.hw_low_power_ctrl = true;
+	a53_perf_clk.hw_low_power_ctrl = true;
+
+	register_pm_notifier(&clock_sdm632_pm_notifier);
+
+	populate_opp_table(pdev);
+
+	atomic_notifier_chain_register(&panic_notifier_list,
+						&clock_panic_notifier);
+
+	return 0;
+}
+
+static const struct of_device_id clock_a53_match_table[] = {
+	{.compatible = "qcom,cpu-clock-sdm632"},
+	{}
+};
+
+static struct platform_driver clock_a53_driver = {
+	.probe = clock_a53_probe,
+	.driver = {
+		.name = "cpu-clock-sdm632",
+		.of_match_table = clock_a53_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init clock_a53_init(void)
+{
+	return platform_driver_register(&clock_a53_driver);
+}
+arch_initcall(clock_a53_init);
+
+static int __init clock_cpu_lpm_get_latency(void)
+{
+	int rc = 0;
+	struct device_node *ofnode = of_find_compatible_node(NULL, NULL,
+					"qcom,cpu-clock-sdm632");
+
+	if (!ofnode)
+		return 0;
+
+	rc = lpm_get_latency(&a53_perf_clk.latency_lvl,
+			&a53_perf_clk.cpu_latency_no_l2_pc_us);
+	if (rc < 0)
+		pr_err("Failed to get the L2 PC value for perf\n");
+
+	rc = lpm_get_latency(&a53_pwr_clk.latency_lvl,
+			&a53_pwr_clk.cpu_latency_no_l2_pc_us);
+	if (rc < 0)
+		pr_err("Failed to get the L2 PC value for pwr\n");
+
+	pr_debug("Latency for pwr/perf cluster %d : %d\n",
+		a53_pwr_clk.cpu_latency_no_l2_pc_us,
+		a53_perf_clk.cpu_latency_no_l2_pc_us);
+
+	return rc;
+}
+late_initcall(clock_cpu_lpm_get_latency);
+
+#define PWR_PLL_BASE			0xb116000
+#define PERF_PLL_BASE			0xb016000
+#define CCI_PLL_BASE			0xb1d0000
+#define APCS_ALIAS1_CMD_RCGR		0xb011050
+#define APCS_ALIAS1_CFG_OFF		0x4
+#define APCS_ALIAS1_CORE_CBCR_OFF	0x8
+#define SRC_SEL				0x4
+#define SRC_DIV				0x1
+
+static int __init cpu_clock_init(void)
+{
+	void __iomem  *base;
+	int regval = 0, count;
+	struct device_node *ofnode = of_find_compatible_node(NULL, NULL,
+						"qcom,cpu-clock-sdm632");
+	if (!ofnode)
+		return 0;
+
+	virt_bases[APCS_C0_PLL_BASE] = ioremap_nocache(PWR_PLL_BASE, SZ_1K);
+	virt_bases[APCS_C1_PLL_BASE] = ioremap_nocache(PERF_PLL_BASE, SZ_1K);
+	virt_bases[APCS_CCI_PLL_BASE] = ioremap_nocache(CCI_PLL_BASE, SZ_1K);
+	clk_ops_variable_rate = clk_ops_variable_rate_pll_hwfsm;
+	clk_ops_variable_rate.list_registers = variable_pll_list_registers;
+
+	/* Initialize the PLLs */
+	__variable_rate_pll_init(&apcs_c0_pll.c);
+	__variable_rate_pll_init(&apcs_c1_pll.c);
+	__init_alpha_pll(&apcs_cci_pll.c);
+
+	/* Enable the PLLs */
+	apcs_c0_pll.c.ops->set_rate(&apcs_c0_pll.c, pwrcl_early_boot_rate);
+	clk_ops_variable_rate_pll.enable(&apcs_c0_pll.c);
+
+	apcs_c1_pll.c.ops->set_rate(&apcs_c1_pll.c, perfcl_early_boot_rate);
+	clk_ops_variable_rate_pll.enable(&apcs_c1_pll.c);
+
+	apcs_cci_pll.c.ops->set_rate(&apcs_cci_pll.c, cci_early_boot_rate);
+	clk_ops_dyna_alpha_pll.enable(&apcs_cci_pll.c);
+
+	base = ioremap_nocache(APCS_ALIAS1_CMD_RCGR, SZ_8);
+	regval = readl_relaxed(base);
+
+	/* Source from GPLL0 */
+	regval = (SRC_SEL << 8) | SRC_DIV; /* 0x401 */
+	writel_relaxed(regval, base + APCS_ALIAS1_CFG_OFF);
+	/* Make sure src sel and src div is set before update bit */
+	mb();
+
+	/* update bit */
+	regval = readl_relaxed(base);
+	regval |= BIT(0);
+	writel_relaxed(regval, base);
+	/* Make sure src sel and src div is set before update bit */
+	mb();
+
+	/* Wait for update to take effect */
+	for (count = 500; count > 0; count--) {
+		if (!(readl_relaxed(base)) & BIT(0))
+			break;
+		udelay(1);
+	}
+
+	/* Enable the branch */
+	regval =  readl_relaxed(base + APCS_ALIAS1_CORE_CBCR_OFF);
+	regval |= BIT(0);
+	writel_relaxed(regval, base + APCS_ALIAS1_CORE_CBCR_OFF);
+
+	/* Branch enable should be complete */
+	mb();
+	iounmap(base);
+
+	pr_info("CPU clocks configured\n");
+
+	return 0;
+}
+early_initcall(cpu_clock_init);
diff --git a/drivers/clk/msm/clock-gcc-mdm9607.c b/drivers/clk/msm/clock-gcc-mdm9607.c
new file mode 100644
index 0000000..3900b08
--- /dev/null
+++ b/drivers/clk/msm/clock-gcc-mdm9607.c
@@ -0,0 +1,1954 @@
+/*
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/clk.h>
+#include <linux/regulator/consumer.h>
+#include <linux/ctype.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/spinlock.h>
+#include <soc/qcom/clock-local2.h>
+#include <soc/qcom/clock-pll.h>
+#include <soc/qcom/clock-alpha-pll.h>
+#include <soc/qcom/clock-voter.h>
+#include <soc/qcom/clock-rpm.h>
+#include <soc/qcom/rpm-smd.h>
+
+#include <linux/clk/msm-clock-generic.h>
+#include <linux/regulator/rpm-smd-regulator.h>
+
+#include <dt-bindings/clock/mdm-clocks-9607.h>
+#include <dt-bindings/clock/mdm-clocks-hwio-9607.h>
+
+#include "clock.h"
+
+enum {
+	GCC_BASE,
+	DEBUG_BASE,
+	APCS_PLL_BASE,
+	N_BASES,
+};
+
+static void __iomem *virt_bases[N_BASES];
+
+#define GCC_REG_BASE(x) (void __iomem *)(virt_bases[GCC_BASE] + (x))
+
+DEFINE_CLK_RPM_SMD_BRANCH(xo_clk_src, xo_a_clk_src,
+				RPM_MISC_CLK_TYPE, XO_ID, 19200000);
+
+DEFINE_CLK_RPM_SMD(pcnoc_clk, pcnoc_a_clk, RPM_BUS_CLK_TYPE, PCNOC_ID, NULL);
+DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
+DEFINE_CLK_RPM_SMD(qpic_clk, qpic_a_clk, RPM_QPIC_CLK_TYPE, QPIC_ID, NULL);
+DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE, QDSS_ID);
+
+DEFINE_CLK_RPM_SMD_XO_BUFFER(bb_clk1, bb_clk1_a, BB_CLK1_ID);
+
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(bb_clk1_pin, bb_clk1_a_pin, BB_CLK1_ID);
+
+static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_usb_clk, &bimc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_usb_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_keepalive_a_clk, &pcnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_msmbus_clk, &pcnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_msmbus_a_clk, &pcnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_usb_clk, &pcnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_usb_a_clk, &pcnoc_a_clk.c, LONG_MAX);
+
+static DEFINE_CLK_BRANCH_VOTER(xo_lpm_clk, &xo_clk_src.c);
+static DEFINE_CLK_BRANCH_VOTER(xo_otg_clk, &xo_clk_src.c);
+static DEFINE_CLK_BRANCH_VOTER(xo_pil_mss_clk, &xo_clk_src.c);
+
+#define F_APCS_STROMER_PLL(f, l, m, pre_div, post_div, vco) \
+	{ \
+		.freq_hz = (f), \
+		.l_val = (l), \
+		.a_val = (m), \
+		.pre_div_val = BVAL(14, 12, (pre_div)), \
+		.post_div_val = BVAL(11, 8, (post_div)), \
+		.vco_val = BVAL(21, 20, (vco)), \
+	}
+
+static DEFINE_VDD_REGULATORS(vdd_stromer_pll, VDD_DIG_NUM, 1, vdd_corner, NULL);
+
+static struct alpha_pll_masks pll_masks_p = {
+	.lock_mask = BIT(31),
+	.active_mask = BIT(30),
+	.vco_mask = BM(21, 20) >> 20,
+	.vco_shift = 20,
+	.alpha_en_mask = BIT(24),
+	.output_mask = 0xf,
+	.update_mask = BIT(22),
+	.post_div_mask = BM(11, 8),
+};
+
+static struct alpha_pll_vco_tbl p_vco[] = {
+	VCO(0,  700000000, 1400000000),
+};
+
+static struct alpha_pll_clk a7sspll = {
+	.masks = &pll_masks_p,
+	.vco_tbl = p_vco,
+	.num_vco = ARRAY_SIZE(p_vco),
+	.base = &virt_bases[APCS_PLL_BASE],
+	.offset = APCS_MODE,
+	.slew = true,
+	.enable_config = 1,
+	.post_div_config = 0,
+	.c = {
+		.parent = &xo_a_clk_src.c,
+		.dbg_name = "a7sspll",
+		.ops = &clk_ops_dyna_alpha_pll,
+		VDD_STROMER_FMAX_MAP1(LOW, 1400000000),
+		CLK_INIT(a7sspll.c),
+	},
+};
+
+static unsigned int soft_vote_gpll0;
+
+static struct pll_vote_clk gpll0_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_MODE,
+	.status_mask = BIT(30),
+	.base = &virt_bases[GCC_BASE],
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
+	.c = {
+		.parent = &xo_clk_src.c,
+		.rate = 800000000,
+		.dbg_name = "gpll0_clk_src",
+		.ops = &clk_ops_pll_acpu_vote,
+		CLK_INIT(gpll0_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk gpll0_ao_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_MODE,
+	.status_mask = BIT(30),
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.parent = &xo_a_clk_src.c,
+		.rate = 800000000,
+		.dbg_name = "gpll0_ao_clk_src",
+		.ops = &clk_ops_pll_acpu_vote,
+		CLK_INIT(gpll0_ao_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk gpll2_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(3),
+	.status_reg = (void __iomem *)GPLL2_MODE,
+	.status_mask = BIT(30),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.parent = &xo_clk_src.c,
+		.rate = 480000000,
+		.dbg_name = "gpll2_clk_src",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(gpll2_clk_src.c),
+	},
+};
+
+static struct pll_vote_clk gpll1_clk_src = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(1),
+	.status_reg = (void __iomem *)GPLL1_STATUS,
+	.status_mask = BIT(17),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.parent = &xo_clk_src.c,
+		.rate = 614400000,
+		.dbg_name = "gpll1_clk_src",
+		.ops = &clk_ops_pll_vote,
+		CLK_INIT(gpll1_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_apss_ahb_clk_src[] = {
+	F(  19200000,           xo_a,    1,    0,     0),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F( 100000000,          gpll0,    8,    0,     0),
+	F_END
+};
+
+static struct rcg_clk apss_ahb_clk_src = {
+	.cmd_rcgr_reg = APSS_AHB_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_apss_ahb_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "apss_ahb_clk_src",
+		.ops = &clk_ops_rcg,
+		CLK_INIT(apss_ahb_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_emac_0_125m_clk_src[] = {
+	F(      19200000,                   xo,    1,    0,     0),
+	F_EXT(  25000000,      emac_0_125m_clk,    5,    0,     0),
+	F_EXT( 125000000,      emac_0_125m_clk,    1,    0,     0),
+	F_END
+};
+
+static struct rcg_clk emac_0_125m_clk_src = {
+	.cmd_rcgr_reg = EMAC_0_125M_CMD_RCGR,
+	.current_freq = ftbl_emac_0_125m_clk_src,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_emac_0_125m_clk_src,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "emac_0_125m_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 125000000),
+		CLK_INIT(emac_0_125m_clk_src.c),
+		},
+};
+
+static struct clk_freq_tbl ftbl_emac_0_sys_25m_clk_src[] = {
+	F(      19200000,                   xo,    1,    0,     0),
+	F_EXT(	25000000,      emac_0_125m_clk,    5,    0,     0),
+	F_EXT( 125000000,      emac_0_125m_clk,    1,    0,     0),
+	F_END
+};
+static struct rcg_clk emac_0_sys_25m_clk_src = {
+	.cmd_rcgr_reg = EMAC_0_SYS_25M_CMD_RCGR,
+	.current_freq = ftbl_emac_0_sys_25m_clk_src,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_emac_0_sys_25m_clk_src,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "emac_0_sys_25m_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 125000000),
+		CLK_INIT(emac_0_sys_25m_clk_src.c),
+		},
+};
+
+static struct clk_freq_tbl ftbl_emac_0_tx_clk_src[] = {
+	F(      19200000,                   xo,    1,    0,     0),
+	F_EXT( 125000000,        emac_0_tx_clk,    1,    0,     0),
+	F_END
+};
+static struct rcg_clk emac_0_tx_clk_src = {
+	.cmd_rcgr_reg = EMAC_0_TX_CMD_RCGR,
+	.current_freq = ftbl_emac_0_tx_clk_src,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_emac_0_tx_clk_src,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "emac_0_tx_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 125000000),
+		CLK_INIT(emac_0_tx_clk_src.c),
+		},
+};
+
+static struct clk_freq_tbl ftbl_blsp_i2c_apps_clk_src[] = {
+	F(  19200000,             xo,    1,    0,     0),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup1_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 50000000),
+		CLK_INIT(blsp1_qup1_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
+	F(    960000,             xo,   10,    1,     2),
+	F(   4800000,             xo,    4,    0,     0),
+	F(   9600000,             xo,    2,    0,     0),
+	F(  16000000,          gpll0,   10,    1,     5),
+	F(  19200000,             xo,    1,    0,     0),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup1_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup1_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup2_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 50000000),
+		CLK_INIT(blsp1_qup2_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup2_spi_apps_clk_src[] = {
+	F(    960000,             xo,   10,    1,     2),
+	F(   4800000,             xo,    4,    0,     0),
+	F(   9600000,             xo,    2,    0,     0),
+	F(  16000000,          gpll0,   10,    1,     5),
+	F(  19200000,             xo,    1,    0,     0),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup2_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup2_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup2_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup3_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 50000000),
+		CLK_INIT(blsp1_qup3_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup3_spi_apps_clk_src[] = {
+	F(    960000,             xo,   10,    1,     2),
+	F(   4800000,             xo,    4,    0,     0),
+	F(   9600000,             xo,    2,    0,     0),
+	F(  16000000,          gpll0,   10,    1,     5),
+	F(  18180000,          gpll0,    1,    1,    44),
+	F(  19200000,             xo,    1,    0,     0),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  36360000,          gpll0,    1,    1,    22),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup3_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup3_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 18180000, NOMINAL, 36360000),
+		CLK_INIT(blsp1_qup3_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup4_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 50000000),
+		CLK_INIT(blsp1_qup4_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup4_spi_apps_clk_src[] = {
+	F(    960000,             xo,   10,    1,     2),
+	F(   4800000,             xo,    4,    0,     0),
+	F(   9600000,             xo,    2,    0,     0),
+	F(  16000000,          gpll0,   10,    1,     5),
+	F(  19200000,             xo,    1,    0,     0),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup4_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup4_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup4_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup5_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP5_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup5_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 50000000),
+		CLK_INIT(blsp1_qup5_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup5_spi_apps_clk_src[] = {
+	F(    960000,             xo,   10,    1,     2),
+	F(   4800000,             xo,    4,    0,     0),
+	F(   9600000,             xo,    2,    0,     0),
+	F(  16000000,          gpll0,   10,    1,     5),
+	F(  19200000,             xo,    1,    0,     0),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup5_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP5_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup5_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup5_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup5_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup6_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP6_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup6_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 50000000),
+		CLK_INIT(blsp1_qup6_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup6_spi_apps_clk_src[] = {
+	F(    960000,             xo,   10,    1,     2),
+	F(   4800000,             xo,    4,    0,     0),
+	F(   9600000,             xo,    2,    0,     0),
+	F(  16000000,          gpll0,   10,    1,     5),
+	F(  19200000,             xo,    1,    0,     0),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup6_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP6_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup6_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_qup6_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 25000000, NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup6_spi_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp_uart_apps_clk_src[] = {
+	F(   3686400,          gpll0,    1,   72, 15625),
+	F(   7372800,          gpll0,    1,  144, 15625),
+	F(  14745600,          gpll0,    1,  288, 15625),
+	F(  16000000,          gpll0,   10,    1,     5),
+	F(  19200000,             xo,    1,    0,     0),
+	F(  24000000,          gpll0,    1,    3,   100),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  32000000,          gpll0,    1,    1,    25),
+	F(  40000000,          gpll0,    1,    1,    20),
+	F(  46400000,          gpll0,    1,   29,   500),
+	F(  48000000,          gpll0,    1,    3,    50),
+	F(  51200000,          gpll0,    1,    8,   125),
+	F(  56000000,          gpll0,    1,    7,   100),
+	F(  58982400,          gpll0,    1, 1152, 15625),
+	F(  60000000,          gpll0,    1,    3,    40),
+	F_END
+};
+
+static struct rcg_clk blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 48480000, NOMINAL, 64000000),
+		CLK_INIT(blsp1_uart1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart2_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 48480000, NOMINAL, 64000000),
+		CLK_INIT(blsp1_uart2_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART3_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart3_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 48480000, NOMINAL, 64000000),
+		CLK_INIT(blsp1_uart3_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART4_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart4_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 48480000, NOMINAL, 64000000),
+		CLK_INIT(blsp1_uart4_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart5_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART5_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart5_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 48480000, NOMINAL, 64000000),
+		CLK_INIT(blsp1_uart5_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart6_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART6_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "blsp1_uart6_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP2(LOWER, 48480000, NOMINAL, 64000000),
+		CLK_INIT(blsp1_uart6_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_crypto_clk_src[] = {
+	F(  50000000,          gpll0,   16,    0,     0),
+	F(  80000000,          gpll0,   10,    0,     0),
+	F( 100000000,          gpll0,    8,    0,     0),
+	F( 160000000,          gpll0,    5,    0,     0),
+	F_END
+};
+
+static struct rcg_clk crypto_clk_src = {
+	.cmd_rcgr_reg = CRYPTO_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_crypto_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "crypto_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 80000000, NOMINAL, 160000000),
+		CLK_INIT(crypto_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gp_clk_src[] = {
+	F(  19200000,             xo,    1,    0,     0),
+	F_END
+};
+
+static struct rcg_clk gp1_clk_src = {
+	.cmd_rcgr_reg = GP1_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gp_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp1_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp1_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp2_clk_src = {
+	.cmd_rcgr_reg = GP2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gp_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp2_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp3_clk_src = {
+	.cmd_rcgr_reg = GP3_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_gp_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gp3_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 100000000, NOMINAL, 200000000),
+		CLK_INIT(gp3_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_pdm2_clk_src[] = {
+	F(  64000000,          gpll0, 12.5,    0,     0),
+	F_END
+};
+
+static struct rcg_clk pdm2_clk_src = {
+	.cmd_rcgr_reg = PDM2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_pdm2_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "pdm2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 64000000),
+		CLK_INIT(pdm2_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_sdcc_apps_clk[] = {
+	F(    144000,             xo,   16,    3,    25),
+	F(    400000,             xo,   12,    1,     4),
+	F(  20000000,          gpll0,   10,    1,     4),
+	F(  25000000,          gpll0,   16,    1,     2),
+	F(  50000000,          gpll0,   16,    0,     0),
+	F( 100000000,          gpll0,    8,    0,     0),
+	F( 177777778,          gpll0,  4.5,    0,     0),
+	F( 200000000,          gpll0,    4,    0,     0),
+	F_END
+};
+
+static struct rcg_clk sdcc1_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_sdcc_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc1_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 50000000, NOMINAL, 200000000),
+		CLK_INIT(sdcc1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk sdcc2_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_sdcc_apps_clk,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "sdcc2_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 50000000, NOMINAL, 200000000),
+		CLK_INIT(sdcc2_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_usb_hs_system_clk_src[] = {
+	F(  19200000,             xo,    1,    0,     0),
+	F(  57140000,          gpll0,   14,    0,     0),
+	F(  69565000,          gpll0, 11.5,    0,     0),
+	F( 133330000,          gpll0,    6,    0,     0),
+	F( 177778000,          gpll0,  4.5,    0,     0),
+	F_END
+};
+
+static struct rcg_clk usb_hs_system_clk_src = {
+	.cmd_rcgr_reg = USB_HS_SYSTEM_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_usb_hs_system_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hs_system_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOWER, 69570000, NOMINAL, 133330000,
+						HIGH, 177780000),
+		CLK_INIT(usb_hs_system_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_usb_hsic_clk_src[] = {
+	F( 480000000,          gpll2,    1,    0,     0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_usb_hsic_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 480000000),
+		CLK_INIT(usb_hsic_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_usb_hsic_io_cal_clk_src[] = {
+	F(   9600000,             xo,    2,    0,     0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_io_cal_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_IO_CAL_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_usb_hsic_io_cal_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_io_cal_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 9600000),
+		CLK_INIT(usb_hsic_io_cal_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_usb_hsic_system_clk_src[] = {
+	F(  19200000,             xo,    1,    0,     0),
+	F(  57140000,          gpll0,   14,    0,     0),
+	F( 133330000,          gpll0,    6,    0,     0),
+	F( 177778000,          gpll0,  4.5,    0,     0),
+	F_END
+};
+
+static struct rcg_clk usb_hsic_system_clk_src = {
+	.cmd_rcgr_reg = USB_HSIC_SYSTEM_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_usb_hsic_system_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "usb_hsic_system_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP3(LOWER, 57140000, NOMINAL, 133330000,
+							HIGH, 177778000),
+		CLK_INIT(usb_hsic_system_clk_src.c),
+	},
+};
+
+static struct local_vote_clk gcc_apss_ahb_clk = {
+	.cbcr_reg = APSS_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(14),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_apss_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_apss_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_apss_axi_clk = {
+	.cbcr_reg = APSS_AXI_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(13),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_apss_axi_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_apss_axi_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_blsp1_ahb_clk = {
+	.cbcr_reg = BLSP1_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(10),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_blsp1_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_boot_rom_ahb_clk = {
+	.cbcr_reg = BOOT_ROM_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(7),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_boot_rom_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_boot_rom_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_crypto_ahb_clk = {
+	.cbcr_reg = CRYPTO_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(0),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_crypto_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_crypto_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_crypto_axi_clk = {
+	.cbcr_reg = CRYPTO_AXI_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(1),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_crypto_axi_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_crypto_axi_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_crypto_clk = {
+	.cbcr_reg = CRYPTO_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(2),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_crypto_clk",
+		.parent = &crypto_clk_src.c,
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_crypto_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_apss_tcu_clk = {
+	.cbcr_reg = APSS_TCU_CBCR,
+	.vote_reg = APCS_SMMU_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(1),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_apss_tcu_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_apss_tcu_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_prng_ahb_clk = {
+	.cbcr_reg = PRNG_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(8),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_prng_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_prng_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_smmu_cfg_clk = {
+	.cbcr_reg = SMMU_CFG_CBCR,
+	.vote_reg = APCS_SMMU_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(12),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_smmu_cfg_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_smmu_cfg_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_qdss_dap_clk = {
+	.cbcr_reg = QDSS_DAP_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(19),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_qdss_dap_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_qdss_dap_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
+		.parent = &blsp1_qup1_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_spi_apps_clk",
+		.parent = &blsp1_qup1_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",
+		.parent = &blsp1_qup2_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_spi_apps_clk",
+		.parent = &blsp1_qup2_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
+		.parent = &blsp1_qup3_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_spi_apps_clk",
+		.parent = &blsp1_qup3_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_i2c_apps_clk",
+		.parent = &blsp1_qup4_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_spi_apps_clk",
+		.parent = &blsp1_qup4_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup5_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP5_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup5_i2c_apps_clk",
+		.parent = &blsp1_qup5_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup5_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup5_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP5_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup5_spi_apps_clk",
+		.parent = &blsp1_qup5_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup5_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup6_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP6_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup6_i2c_apps_clk",
+		.parent = &blsp1_qup6_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup6_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup6_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP6_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_qup6_spi_apps_clk",
+		.parent = &blsp1_qup6_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup6_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart1_apps_clk = {
+	.cbcr_reg = BLSP1_UART1_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart1_apps_clk",
+		.parent = &blsp1_uart1_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart2_apps_clk = {
+	.cbcr_reg = BLSP1_UART2_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart2_apps_clk",
+		.parent = &blsp1_uart2_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart3_apps_clk = {
+	.cbcr_reg = BLSP1_UART3_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart3_apps_clk",
+		.parent = &blsp1_uart3_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart3_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart4_apps_clk = {
+	.cbcr_reg = BLSP1_UART4_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart4_apps_clk",
+		.parent = &blsp1_uart4_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart4_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart5_apps_clk = {
+	.cbcr_reg = BLSP1_UART5_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart5_apps_clk",
+		.parent = &blsp1_uart5_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart5_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart6_apps_clk = {
+	.cbcr_reg = BLSP1_UART6_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_blsp1_uart6_apps_clk",
+		.parent = &blsp1_uart6_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart6_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp1_clk = {
+	.cbcr_reg = GP1_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp1_clk",
+		.parent = &gp1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp1_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp2_clk = {
+	.cbcr_reg = GP2_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp2_clk",
+		.parent = &gp2_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp3_clk = {
+	.cbcr_reg = GP3_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_gp3_clk",
+		.parent = &gp3_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp3_clk.c),
+	},
+};
+
+static struct branch_clk gcc_mss_cfg_ahb_clk = {
+	.cbcr_reg = MSS_CFG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_mss_cfg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_mss_cfg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_mss_q6_bimc_axi_clk = {
+	.cbcr_reg = MSS_Q6_BIMC_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_mss_q6_bimc_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_mss_q6_bimc_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm2_clk = {
+	.cbcr_reg = PDM2_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_pdm2_clk",
+		.parent = &pdm2_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm_ahb_clk = {
+	.cbcr_reg = PDM_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_pdm_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_ahb_clk = {
+	.cbcr_reg = SDCC1_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc1_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_apps_clk = {
+	.cbcr_reg = SDCC1_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc1_apps_clk",
+		.parent = &sdcc1_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc2_ahb_clk = {
+	.cbcr_reg = SDCC2_AHB_CBCR,
+	.has_sibling = 1,
+	.toggle_memory = true,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc2_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc2_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc2_apps_clk = {
+	.cbcr_reg = SDCC2_APPS_CBCR,
+	.has_sibling = 0,
+	.toggle_memory = true,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sdcc2_apps_clk",
+		.parent = &sdcc2_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_emac_0_125m_clk = {
+	.cbcr_reg = EMAC_0_125M_CBCR,
+	.has_sibling = 0,
+	.toggle_memory = true,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_emac_0_125m_clk",
+		.parent = &emac_0_125m_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_emac_0_125m_clk.c),
+	},
+};
+
+static struct branch_clk gcc_emac_0_ahb_clk = {
+	.cbcr_reg = EMAC_0_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_emac_0_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_emac_0_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_emac_0_axi_clk = {
+	.cbcr_reg = EMAC_0_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_emac_0_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_emac_0_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_emac_0_sys_25m_clk = {
+	.cbcr_reg = EMAC_0_SYS_25M_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_emac_0_sys_25m_clk",
+		.parent = &emac_0_sys_25m_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_emac_0_sys_25m_clk.c),
+	},
+};
+
+static struct branch_clk gcc_emac_0_sys_clk = {
+	.cbcr_reg = EMAC_0_SYS_CBCR,
+	.has_sibling = 1,
+	.toggle_memory = true,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_emac_0_sys_clk",
+		.parent = &emac_0_125m_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_emac_0_sys_clk.c),
+	},
+};
+
+static struct branch_clk gcc_emac_0_tx_clk = {
+	.cbcr_reg = EMAC_0_TX_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_emac_0_tx_clk",
+		.parent = &emac_0_tx_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_emac_0_tx_clk.c),
+	},
+};
+
+static struct gate_clk gcc_emac_0_rx_clk = {
+	.en_reg = EMAC_0_RX_CBCR,
+	.en_mask = BIT(0),
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_emac_0_rx_clk",
+		.ops = &clk_ops_gate,
+		CLK_INIT(gcc_emac_0_rx_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb2a_phy_sleep_clk = {
+	.cbcr_reg = USB2A_PHY_SLEEP_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb2a_phy_sleep_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb2a_phy_sleep_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hs_phy_cfg_ahb_clk = {
+	.cbcr_reg = USB_HS_PHY_CFG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hs_phy_cfg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hs_phy_cfg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hs_ahb_clk = {
+	.cbcr_reg = USB_HS_AHB_CBCR,
+	.has_sibling = 1,
+	.toggle_memory = true,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hs_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hs_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hs_system_clk = {
+	.cbcr_reg = USB_HS_SYSTEM_CBCR,
+	.bcr_reg = USB_HS_BCR,
+	.has_sibling = 0,
+	.toggle_memory = true,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hs_system_clk",
+		.parent = &usb_hs_system_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hs_system_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_ahb_clk = {
+	.cbcr_reg = USB_HSIC_AHB_CBCR,
+	.has_sibling = 1,
+	.toggle_memory = true,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_clk = {
+	.cbcr_reg = USB_HSIC_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_clk",
+		.parent = &usb_hsic_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_io_cal_clk = {
+	.cbcr_reg = USB_HSIC_IO_CAL_CBCR,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_io_cal_clk",
+		.parent = &usb_hsic_io_cal_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_io_cal_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_io_cal_sleep_clk = {
+	.cbcr_reg = USB_HSIC_IO_CAL_SLEEP_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_io_cal_sleep_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_io_cal_sleep_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_hsic_system_clk = {
+	.cbcr_reg = USB_HSIC_SYSTEM_CBCR,
+	.bcr_reg  = USB_HS_HSIC_BCR,
+	.toggle_memory = true,
+	.has_sibling = 0,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb_hsic_system_clk",
+		.parent = &usb_hsic_system_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_hsic_system_clk.c),
+	},
+};
+
+static struct reset_clk gcc_usb2_hs_phy_only_clk = {
+	.reset_reg = USB2_HS_PHY_ONLY_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_usb2_hs_phy_only_clk",
+		.ops = &clk_ops_rst,
+		CLK_INIT(gcc_usb2_hs_phy_only_clk.c),
+	},
+};
+
+static struct reset_clk gcc_qusb2_phy_clk = {
+	.reset_reg = QUSB2_PHY_BCR,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_qusb2_phy_clk",
+		.ops = &clk_ops_rst,
+		CLK_INIT(gcc_qusb2_phy_clk.c),
+	},
+};
+
+static struct measure_clk apc0_m_clk = {
+	.c = {
+		.ops = &clk_ops_empty,
+		.dbg_name = "apc0_m_clk",
+		CLK_INIT(apc0_m_clk.c),
+	},
+};
+
+static struct measure_clk l2_m_clk = {
+	.c = {
+		.ops = &clk_ops_empty,
+		.dbg_name = "l2_m_clk",
+		CLK_INIT(l2_m_clk.c),
+	},
+};
+
+static void __iomem *meas_base;
+
+static struct mux_clk apss_debug_pri_mux = {
+	.ops = &mux_reg_ops,
+	.mask = 0x7,
+	.shift = 3,
+	MUX_SRC_LIST(
+		{&apc0_m_clk.c, 3},
+		{&l2_m_clk.c, 2},
+	),
+	.base = &meas_base,
+	.c = {
+		.dbg_name = "apss_debug_pri_mux",
+		.ops = &clk_ops_gen_mux,
+		CLK_INIT(apss_debug_pri_mux.c),
+	},
+};
+
+static int  gcc_set_mux_sel(struct mux_clk *clk, int sel)
+{
+	u32 regval;
+
+	regval = readl_relaxed(GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+	regval &= 0x1FF;
+	writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL));
+
+	if (sel == 0xFFFF)
+		return 0;
+	mux_reg_ops.set_mux_sel(clk, sel);
+
+	return 0;
+}
+
+static struct measure_clk_data debug_mux_priv = {
+	.cxo = &xo_clk_src.c,
+	.plltest_reg = PLLTEST_PAD_CFG,
+	.plltest_val = 0x51A00,
+	.xo_div4_cbcr = GCC_XO_DIV4_CBCR,
+	.ctl_reg = CLOCK_FRQ_MEASURE_CTL,
+	.status_reg = CLOCK_FRQ_MEASURE_STATUS,
+	.base = &virt_bases[DEBUG_BASE],
+};
+static struct clk_ops clk_ops_debug_mux;
+static struct clk_mux_ops gcc_debug_mux_ops;
+static struct mux_clk gcc_debug_mux = {
+	.priv = &debug_mux_priv,
+	.ops = &gcc_debug_mux_ops,
+	.offset = GCC_DEBUG_CLK_CTL,
+	.mask = 0x1FF,
+	.en_offset = GCC_DEBUG_CLK_CTL,
+	.en_mask = BIT(16),
+	.base = &virt_bases[DEBUG_BASE],
+	MUX_SRC_LIST(
+		{ &pcnoc_clk.c, 0x0008 },
+		{ &bimc_clk.c, 0x155 },
+		{ &gcc_gp1_clk.c, 0x0010 },
+		{ &gcc_gp2_clk.c, 0x0011 },
+		{ &gcc_gp3_clk.c, 0x0012 },
+		{ &gcc_mss_cfg_ahb_clk.c, 0x0030 },
+		{ &gcc_mss_q6_bimc_axi_clk.c, 0x0031 },
+		{ &gcc_qdss_dap_clk.c, 0x0049 },
+		{ &gcc_apss_tcu_clk.c, 0x0050 },
+		{ &gcc_smmu_cfg_clk.c, 0x005b },
+		{ &gcc_usb_hs_system_clk.c, 0x0060 },
+		{ &gcc_usb_hs_ahb_clk.c, 0x0061 },
+		{ &gcc_usb2a_phy_sleep_clk.c, 0x0063 },
+		{ &gcc_usb_hs_phy_cfg_ahb_clk.c, 0x0064 },
+		{ &gcc_sdcc1_apps_clk.c, 0x0068 },
+		{ &gcc_sdcc1_ahb_clk.c, 0x0069 },
+		{ &gcc_sdcc2_apps_clk.c, 0x0070 },
+		{ &gcc_sdcc2_ahb_clk.c, 0x0071 },
+		{ &gcc_blsp1_ahb_clk.c, 0x0088 },
+		{ &gcc_blsp1_qup1_spi_apps_clk.c, 0x008a },
+		{ &gcc_blsp1_qup1_i2c_apps_clk.c, 0x008b },
+		{ &gcc_blsp1_uart1_apps_clk.c, 0x008c },
+		{ &gcc_blsp1_qup2_spi_apps_clk.c, 0x008e },
+		{ &gcc_blsp1_qup2_i2c_apps_clk.c, 0x0090 },
+		{ &gcc_blsp1_uart2_apps_clk.c, 0x0091 },
+		{ &gcc_blsp1_qup3_spi_apps_clk.c, 0x0093 },
+		{ &gcc_blsp1_qup3_i2c_apps_clk.c, 0x0094 },
+		{ &gcc_blsp1_uart3_apps_clk.c, 0x0095 },
+		{ &gcc_blsp1_qup4_spi_apps_clk.c, 0x0098 },
+		{ &gcc_blsp1_qup4_i2c_apps_clk.c, 0x0099 },
+		{ &gcc_blsp1_uart4_apps_clk.c, 0x009a },
+		{ &gcc_blsp1_qup5_spi_apps_clk.c, 0x009c },
+		{ &gcc_blsp1_qup5_i2c_apps_clk.c, 0x009d },
+		{ &gcc_blsp1_uart5_apps_clk.c, 0x009e },
+		{ &gcc_blsp1_qup6_spi_apps_clk.c, 0x00a1 },
+		{ &gcc_blsp1_qup6_i2c_apps_clk.c, 0x00a2 },
+		{ &gcc_blsp1_uart6_apps_clk.c, 0x00a3 },
+		{ &gcc_pdm_ahb_clk.c, 0x00d0 },
+		{ &gcc_pdm2_clk.c, 0x00d2 },
+		{ &gcc_prng_ahb_clk.c, 0x00d8 },
+		{ &gcc_boot_rom_ahb_clk.c, 0x00f8 },
+		{ &gcc_crypto_clk.c, 0x0138 },
+		{ &gcc_crypto_axi_clk.c, 0x0139 },
+		{ &gcc_crypto_ahb_clk.c, 0x013a },
+		{ &gcc_apss_ahb_clk.c, 0x0168 },
+		{ &gcc_apss_axi_clk.c, 0x0169 },
+		{ &gcc_usb_hsic_ahb_clk.c, 0x0198 },
+		{ &gcc_usb_hsic_system_clk.c, 0x0199 },
+		{ &gcc_usb_hsic_clk.c, 0x019a },
+		{ &gcc_usb_hsic_io_cal_clk.c, 0x019b },
+		{ &gcc_usb_hsic_io_cal_sleep_clk.c, 0x019c },
+		{ &gcc_emac_0_axi_clk.c, 0x01b8 },
+		{ &gcc_emac_0_ahb_clk.c, 0x01b9 },
+		{ &gcc_emac_0_sys_25m_clk.c, 0x01ba },
+		{ &gcc_emac_0_tx_clk.c, 0x01bb },
+		{ &gcc_emac_0_125m_clk.c, 0x01bc },
+		{ &gcc_emac_0_rx_clk.c, 0x01bd },
+		{ &gcc_emac_0_sys_clk.c, 0x01be },
+	),
+	.c = {
+		.dbg_name = "gcc_debug_mux",
+		.ops = &clk_ops_debug_mux,
+		.flags = CLKFLAG_NO_RATE_CACHE | CLKFLAG_MEASURE,
+		CLK_INIT(gcc_debug_mux.c),
+	},
+};
+/* Clock lookup */
+static struct clk_lookup msm_clocks_lookup[] = {
+	 CLK_LIST(gpll0_clk_src),
+	 CLK_LIST(gpll0_ao_clk_src),
+	 CLK_LIST(gpll2_clk_src),
+	 CLK_LIST(gpll1_clk_src),
+	 CLK_LIST(a7sspll),
+
+	 CLK_LIST(pcnoc_clk),
+	 CLK_LIST(pcnoc_a_clk),
+	 CLK_LIST(pcnoc_msmbus_clk),
+	 CLK_LIST(pcnoc_msmbus_a_clk),
+	 CLK_LIST(pcnoc_keepalive_a_clk),
+	 CLK_LIST(pcnoc_usb_clk),
+	 CLK_LIST(pcnoc_usb_a_clk),
+	 CLK_LIST(bimc_clk),
+	 CLK_LIST(bimc_a_clk),
+	 CLK_LIST(bimc_msmbus_clk),
+	 CLK_LIST(bimc_msmbus_a_clk),
+	 CLK_LIST(bimc_usb_clk),
+	 CLK_LIST(bimc_usb_a_clk),
+	 CLK_LIST(qdss_clk),
+	 CLK_LIST(qdss_a_clk),
+	 CLK_LIST(qpic_clk),
+	 CLK_LIST(qpic_a_clk),
+	 CLK_LIST(xo_clk_src),
+	 CLK_LIST(xo_a_clk_src),
+	 CLK_LIST(xo_otg_clk),
+	 CLK_LIST(xo_lpm_clk),
+	 CLK_LIST(xo_pil_mss_clk),
+
+	 CLK_LIST(bb_clk1),
+	 CLK_LIST(bb_clk1_pin),
+
+	 CLK_LIST(gcc_apss_ahb_clk),
+	 CLK_LIST(gcc_apss_axi_clk),
+	 CLK_LIST(gcc_blsp1_ahb_clk),
+	 CLK_LIST(gcc_boot_rom_ahb_clk),
+	 CLK_LIST(gcc_crypto_ahb_clk),
+	 CLK_LIST(gcc_crypto_axi_clk),
+	 CLK_LIST(gcc_crypto_clk),
+	 CLK_LIST(gcc_prng_ahb_clk),
+	 CLK_LIST(gcc_apss_tcu_clk),
+	 CLK_LIST(gcc_qdss_dap_clk),
+	 CLK_LIST(gcc_smmu_cfg_clk),
+	 CLK_LIST(apss_ahb_clk_src),
+	 CLK_LIST(emac_0_125m_clk_src),
+	 CLK_LIST(blsp1_qup1_i2c_apps_clk_src),
+	 CLK_LIST(blsp1_qup1_spi_apps_clk_src),
+	 CLK_LIST(blsp1_qup2_i2c_apps_clk_src),
+	 CLK_LIST(blsp1_qup2_spi_apps_clk_src),
+	 CLK_LIST(blsp1_qup3_i2c_apps_clk_src),
+	 CLK_LIST(blsp1_qup3_spi_apps_clk_src),
+	 CLK_LIST(blsp1_qup4_i2c_apps_clk_src),
+	 CLK_LIST(blsp1_qup4_spi_apps_clk_src),
+	 CLK_LIST(blsp1_qup5_i2c_apps_clk_src),
+	 CLK_LIST(blsp1_qup5_spi_apps_clk_src),
+	 CLK_LIST(blsp1_qup6_i2c_apps_clk_src),
+	 CLK_LIST(blsp1_qup6_spi_apps_clk_src),
+	 CLK_LIST(blsp1_uart1_apps_clk_src),
+	 CLK_LIST(blsp1_uart2_apps_clk_src),
+	 CLK_LIST(blsp1_uart3_apps_clk_src),
+	 CLK_LIST(blsp1_uart4_apps_clk_src),
+	 CLK_LIST(blsp1_uart5_apps_clk_src),
+	 CLK_LIST(blsp1_uart6_apps_clk_src),
+	 CLK_LIST(crypto_clk_src),
+	 CLK_LIST(gp1_clk_src),
+	 CLK_LIST(gp2_clk_src),
+	 CLK_LIST(gp3_clk_src),
+	 CLK_LIST(pdm2_clk_src),
+	 CLK_LIST(sdcc1_apps_clk_src),
+	 CLK_LIST(sdcc2_apps_clk_src),
+	 CLK_LIST(emac_0_sys_25m_clk_src),
+	 CLK_LIST(emac_0_tx_clk_src),
+	 CLK_LIST(usb_hs_system_clk_src),
+	 CLK_LIST(usb_hsic_clk_src),
+	 CLK_LIST(usb_hsic_io_cal_clk_src),
+	 CLK_LIST(usb_hsic_system_clk_src),
+	 CLK_LIST(gcc_blsp1_qup1_i2c_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup1_spi_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup2_i2c_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup2_spi_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup3_i2c_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup3_spi_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup4_i2c_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup4_spi_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup5_i2c_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup5_spi_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup6_i2c_apps_clk),
+	 CLK_LIST(gcc_blsp1_qup6_spi_apps_clk),
+	 CLK_LIST(gcc_blsp1_uart1_apps_clk),
+	 CLK_LIST(gcc_blsp1_uart2_apps_clk),
+	 CLK_LIST(gcc_blsp1_uart3_apps_clk),
+	 CLK_LIST(gcc_blsp1_uart4_apps_clk),
+	 CLK_LIST(gcc_blsp1_uart5_apps_clk),
+	 CLK_LIST(gcc_blsp1_uart6_apps_clk),
+	 CLK_LIST(gcc_gp1_clk),
+	 CLK_LIST(gcc_gp2_clk),
+	 CLK_LIST(gcc_gp3_clk),
+	 CLK_LIST(gcc_mss_cfg_ahb_clk),
+	 CLK_LIST(gcc_mss_q6_bimc_axi_clk),
+	 CLK_LIST(gcc_pdm2_clk),
+	 CLK_LIST(gcc_pdm_ahb_clk),
+	 CLK_LIST(gcc_sdcc1_ahb_clk),
+	 CLK_LIST(gcc_sdcc1_apps_clk),
+	 CLK_LIST(gcc_sdcc2_ahb_clk),
+	 CLK_LIST(gcc_sdcc2_apps_clk),
+	 CLK_LIST(gcc_emac_0_125m_clk),
+	 CLK_LIST(gcc_emac_0_ahb_clk),
+	 CLK_LIST(gcc_emac_0_axi_clk),
+	 CLK_LIST(gcc_emac_0_sys_25m_clk),
+	 CLK_LIST(gcc_emac_0_sys_clk),
+	 CLK_LIST(gcc_emac_0_tx_clk),
+	 CLK_LIST(gcc_emac_0_rx_clk),
+	 CLK_LIST(gcc_usb2a_phy_sleep_clk),
+	 CLK_LIST(gcc_usb_hs_phy_cfg_ahb_clk),
+	 CLK_LIST(gcc_usb_hs_ahb_clk),
+	 CLK_LIST(gcc_usb_hs_system_clk),
+	 CLK_LIST(gcc_usb_hsic_ahb_clk),
+	 CLK_LIST(gcc_usb_hsic_clk),
+	 CLK_LIST(gcc_usb_hsic_io_cal_clk),
+	 CLK_LIST(gcc_usb_hsic_io_cal_sleep_clk),
+	 CLK_LIST(gcc_usb_hsic_system_clk),
+	 CLK_LIST(gcc_usb2_hs_phy_only_clk),
+	 CLK_LIST(gcc_qusb2_phy_clk),
+};
+
+static int msm_gcc_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret;
+	u32 regval;
+
+	ret = vote_bimc(&bimc_clk, INT_MAX);
+	if (ret < 0)
+		return ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cc_base");
+	if (!res) {
+		dev_err(&pdev->dev, "Register base not defined\n");
+		return -ENOMEM;
+	}
+
+	virt_bases[GCC_BASE] = devm_ioremap(&pdev->dev, res->start,
+							resource_size(res));
+	if (!virt_bases[GCC_BASE]) {
+		dev_err(&pdev->dev, "Failed to ioremap CC registers\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs_base");
+	if (!res) {
+		dev_err(&pdev->dev, "APCS PLL Register base not defined\n");
+		return -ENOMEM;
+	}
+
+	virt_bases[APCS_PLL_BASE] = devm_ioremap(&pdev->dev, res->start,
+							resource_size(res));
+	if (!virt_bases[APCS_PLL_BASE]) {
+		dev_err(&pdev->dev, "Failed to ioremap APCS PLL registers\n");
+		return -ENOMEM;
+	}
+
+	vdd_dig.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_dig");
+	if (IS_ERR(vdd_dig.regulator[0])) {
+		if (!(PTR_ERR(vdd_dig.regulator[0]) == -EPROBE_DEFER))
+			dev_err(&pdev->dev,
+					"Unable to get vdd_dig regulator!!!\n");
+		return PTR_ERR(vdd_dig.regulator[0]);
+	}
+
+	vdd_stromer_pll.regulator[0] = devm_regulator_get(&pdev->dev,
+							"vdd_stromer_dig");
+	if (IS_ERR(vdd_stromer_pll.regulator[0])) {
+		if (!(PTR_ERR(vdd_stromer_pll.regulator[0]) == -EPROBE_DEFER))
+			dev_err(&pdev->dev,
+				"Unable to get vdd_stromer_dig regulator!!!\n");
+		return PTR_ERR(vdd_stromer_pll.regulator[0]);
+	}
+
+	 /*Vote for GPLL0 to turn on. Needed by acpuclock. */
+	regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
+	regval |= BIT(0);
+	writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE));
+
+	ret = of_msm_clock_register(pdev->dev.of_node,
+				msm_clocks_lookup,
+				ARRAY_SIZE(msm_clocks_lookup));
+	if (ret)
+		return ret;
+
+	ret = enable_rpm_scaling();
+	if (ret)
+		return ret;
+
+	clk_set_rate(&apss_ahb_clk_src.c, 19200000);
+	clk_prepare_enable(&apss_ahb_clk_src.c);
+	/*
+	 * Hold an active set vote for PCNOC AHB source. Sleep set
+	 * vote is 0.
+	 */
+	clk_set_rate(&pcnoc_keepalive_a_clk.c, 19200000);
+	clk_prepare_enable(&pcnoc_keepalive_a_clk.c);
+
+	clk_prepare_enable(&xo_a_clk_src.c);
+
+	dev_info(&pdev->dev, "Registered GCC clocks\n");
+
+	return 0;
+}
+
+static const struct of_device_id msm_clock_gcc_match_table[] = {
+	{ .compatible = "qcom,gcc-mdm9607" },
+	{},
+};
+
+static struct platform_driver msm_clock_gcc_driver = {
+	.probe = msm_gcc_probe,
+	.driver = {
+		.name = "qcom,gcc-mdm9607",
+		.of_match_table = msm_clock_gcc_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_gcc_init(void)
+{
+	return platform_driver_register(&msm_clock_gcc_driver);
+}
+arch_initcall(msm_gcc_init);
+
+static struct clk_lookup msm_clocks_measure[] = {
+	CLK_LOOKUP_OF("measure", gcc_debug_mux, "debug"),
+	CLK_LIST(apss_debug_pri_mux),
+	CLK_LIST(apc0_m_clk),
+	CLK_LIST(l2_m_clk),
+};
+
+static int msm_clock_debug_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct resource *res;
+
+	clk_ops_debug_mux = clk_ops_gen_mux;
+	clk_ops_debug_mux.get_rate = measure_get_rate;
+
+	gcc_debug_mux_ops = mux_reg_ops;
+	gcc_debug_mux_ops.set_mux_sel = gcc_set_mux_sel;
+
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cc_base");
+	if (!res) {
+		dev_err(&pdev->dev, "Register base not defined\n");
+		return -ENOMEM;
+	}
+
+	virt_bases[DEBUG_BASE] = devm_ioremap(&pdev->dev, res->start,
+							resource_size(res));
+	if (!virt_bases[DEBUG_BASE]) {
+		dev_err(&pdev->dev, "Failed to ioremap debug cc registers\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "meas");
+	if (!res) {
+		dev_err(&pdev->dev, "GLB clock diag base not defined.\n");
+		return -EINVAL;
+	}
+
+	meas_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!meas_base) {
+		dev_err(&pdev->dev, "Unable to map GLB clock diag base.\n");
+		return -ENOMEM;
+	}
+
+	ret =  of_msm_clock_register(pdev->dev.of_node, msm_clocks_measure,
+					ARRAY_SIZE(msm_clocks_measure));
+	if (ret) {
+		dev_err(&pdev->dev, "Failed to register debug Mux\n");
+		return ret;
+	}
+
+	dev_info(&pdev->dev, "Registered Debug Mux successfully\n");
+	return ret;
+}
+
+static const struct of_device_id msm_clock_debug_match_table[] = {
+	{ .compatible = "qcom,cc-debug-mdm9607" },
+	{}
+};
+
+static struct platform_driver msm_clock_debug_driver = {
+	.probe = msm_clock_debug_probe,
+	.driver = {
+		.name = "qcom,cc-debug-mdm9607",
+		.of_match_table = msm_clock_debug_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init msm_clock_debug_init(void)
+{
+	return platform_driver_register(&msm_clock_debug_driver);
+}
+
+late_initcall(msm_clock_debug_init);
diff --git a/drivers/clk/msm/clock-gcc-mdm9650.c b/drivers/clk/msm/clock-gcc-mdm9650.c
new file mode 100644
index 0000000..ea351a1
--- /dev/null
+++ b/drivers/clk/msm/clock-gcc-mdm9650.c
@@ -0,0 +1,1862 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/clk/msm-clock-generic.h>
+#include <dt-bindings/clock/mdm-clocks-9650.h>
+#include <soc/qcom/clock-rpm.h>
+#include <soc/qcom/clock-local2.h>
+#include <soc/qcom/clock-voter.h>
+#include <soc/qcom/clock-pll.h>
+#include <soc/qcom/clock-alpha-pll.h>
+#include <soc/qcom/rpm-smd.h>
+
+#include "vdd-level-9650.h"
+
+#define RPM_MISC_CLK_TYPE	0x306b6c63
+#define RPM_BUS_CLK_TYPE	0x316b6c63
+#define RPM_MEM_CLK_TYPE	0x326b6c63
+#define RPM_IPA_CLK_TYPE	0x617069
+#define RPM_CE_CLK_TYPE		0x6563
+#define RPM_QPIC_CLK_TYPE	0x63697071
+
+#define RPM_SMD_KEY_ENABLE	0x62616E45
+
+#define CXO_CLK_SRC_ID		0x0
+#define QDSS_CLK_ID		0x1
+#define PCNOC_CLK_ID		0x0
+#define SNOC_CLK_ID		0x1
+#define BIMC_CLK_ID		0x0
+#define IPA_CLK_ID		0x0
+#define QPIC_CLK_ID		0x0
+#define CE_CLK_ID		0x0
+#define XO_ID			0x0
+#define MSS_CFG_AHB_CLK_ID	0x0
+
+#define RF_CLK1_ID		0x4
+#define RF_CLK2_ID		0x5
+#define RF_CLK3_ID		0x6
+#define LN_BB_CLK_ID		0x8
+#define DIV_CLK1_ID		0xb
+
+#define RF_CLK1_PIN_ID		0x4
+#define RF_CLK2_PIN_ID		0x5
+#define RF_CLK3_PIN_ID		0x6
+
+static void __iomem *virt_base;
+static void __iomem *virt_dbgbase;
+static void __iomem *virt_apcsbase;
+
+#define GCC_REG_BASE(x) (void __iomem *)(virt_base + (x))
+
+#define xo_source_val 0
+#define xo_a_clk_source_val 0
+#define gpll0_out_main_cgc_source_val 1
+#define gpll0_ao_out_main_cgc_source_val 1
+#define gpll0_out_main_div2_cgc_source_val 2
+
+#define FIXDIV(div) (div ? (2 * (div) - 1) : (0))
+
+#define F(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)FIXDIV(div)) \
+			| BVAL(10, 8, s##_source_val), \
+	}
+
+#define F_EXT(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)FIXDIV(div)) \
+			| BVAL(10, 8, s##_source_val), \
+	}
+
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
+static DEFINE_VDD_REGULATORS(vdd_dig_ao, VDD_DIG_NUM, 1, vdd_corner, NULL);
+
+#define GPLL0_MODE                                       (0x21000)
+#define MSS_Q6_BIMC_AXI_CBCR                             (0x49004)
+#define QUSB2A_PHY_BCR                                   (0x41028)
+#define SDCC1_APPS_CMD_RCGR                              (0x42004)
+#define SDCC1_APPS_CBCR                                  (0x42018)
+#define SDCC1_AHB_CBCR                                   (0x4201C)
+#define BLSP1_AHB_CBCR                                   (0x1008)
+#define BLSP1_QUP1_SPI_APPS_CBCR                         (0x2004)
+#define BLSP1_QUP1_I2C_APPS_CBCR                         (0x2008)
+#define BLSP1_QUP1_I2C_APPS_CMD_RCGR                     (0x200C)
+#define BLSP1_QUP2_I2C_APPS_CMD_RCGR                     (0x3000)
+#define BLSP1_QUP3_I2C_APPS_CMD_RCGR                     (0x4000)
+#define BLSP1_QUP4_I2C_APPS_CMD_RCGR                     (0x5000)
+#define BLSP1_QUP1_SPI_APPS_CMD_RCGR                     (0x2024)
+#define BLSP1_UART1_APPS_CBCR                            (0x203C)
+#define BLSP1_UART1_APPS_CMD_RCGR                        (0x2044)
+#define BLSP1_QUP2_SPI_APPS_CBCR                         (0x300C)
+#define BLSP1_QUP2_I2C_APPS_CBCR                         (0x3010)
+#define BLSP1_QUP2_SPI_APPS_CMD_RCGR                     (0x3014)
+#define BLSP1_UART2_APPS_CBCR                            (0x302C)
+#define BLSP1_UART2_APPS_CMD_RCGR                        (0x3034)
+#define BLSP1_QUP3_SPI_APPS_CBCR                         (0x401C)
+#define BLSP1_QUP3_I2C_APPS_CBCR                         (0x4020)
+#define BLSP1_QUP3_SPI_APPS_CMD_RCGR                     (0x4024)
+#define BLSP1_UART3_APPS_CBCR                            (0x403C)
+#define BLSP1_UART3_APPS_CMD_RCGR                        (0x4044)
+#define BLSP1_QUP4_SPI_APPS_CBCR                         (0x501C)
+#define BLSP1_QUP4_I2C_APPS_CBCR                         (0x5020)
+#define BLSP1_QUP4_SPI_APPS_CMD_RCGR                     (0x5024)
+#define BLSP1_UART4_APPS_CBCR                            (0x503C)
+#define BLSP1_UART4_APPS_CMD_RCGR                        (0x5044)
+#define PDM_AHB_CBCR                                     (0x44004)
+#define PDM2_CBCR                                        (0x4400C)
+#define PDM2_CMD_RCGR                                    (0x44010)
+#define PRNG_AHB_CBCR                                    (0x13004)
+#define BOOT_ROM_AHB_CBCR                                (0x1300C)
+#define RPM_MISC                                         (0x2D028)
+#define GCC_XO_CMD_RCGR                                  (0x30018)
+#define GCC_XO_DIV4_CBCR                                 (0x30034)
+#define APSS_TCU_CBCR                                    (0x12018)
+#define SMMU_CFG_CBCR                                    (0x12038)
+#define APCS_GPLL_ENA_VOTE                               (0x45000)
+#define APCS_CLOCK_BRANCH_ENA_VOTE                       (0x45004)
+#define APCS_SMMU_CLOCK_BRANCH_ENA_VOTE                  (0x4500C)
+#define APSS_AHB_CMD_RCGR                                (0x46000)
+#define GCC_DEBUG_CLK_CTL                                (0x74000)
+#define CLOCK_FRQ_MEASURE_CTL                            (0x74004)
+#define CLOCK_FRQ_MEASURE_STATUS                         (0x74008)
+#define PLLTEST_PAD_CFG                                  (0x7400C)
+#define GP1_CBCR                                         (0x8000)
+#define GP1_CMD_RCGR                                     (0x8004)
+#define GP2_CBCR                                         (0x9000)
+#define GP2_CMD_RCGR                                     (0x9004)
+#define GP3_CBCR                                         (0xA000)
+#define GP3_CMD_RCGR                                     (0xA004)
+#define PCIE_CFG_AHB_CBCR                                (0x5D008)
+#define PCIE_PIPE_CBCR                                   (0x5D00C)
+#define PCIE_AXI_CBCR                                    (0x5D010)
+#define PCIE_SLEEP_CBCR                                  (0x5D014)
+#define PCIE_AXI_MSTR_CBCR                               (0x5D018)
+#define PCIE_AUX_CMD_RCGR                                (0x5D030)
+#define PCIEPHY_PHY_BCR                                  (0x5D048)
+#define PCIE_REF_CLK_EN                                  (0x5D04C)
+#define PCIE_PHY_BCR                                     (0x5D050)
+#define USB_SS_REF_CLK_EN                                (0x5E07C)
+#define USB_PHY_CFG_AHB_CBCR                             (0x5E080)
+#define SYS_NOC_USB3_AXI_CBCR                            (0x5E084)
+#define USB_30_BCR                                       (0x5E070)
+#define USB30_MASTER_CBCR                                (0x5E000)
+#define USB30_SLEEP_CBCR                                 (0x5E004)
+#define USB30_MOCK_UTMI_CBCR                             (0x5E008)
+#define USB30_MASTER_CMD_RCGR                            (0x5E00C)
+#define USB30_MOCK_UTMI_CMD_RCGR                         (0x5E020)
+#define USB3_PHY_BCR                                     (0x5E034)
+#define USB3PHY_PHY_BCR                                  (0x5E03C)
+#define USB3_PIPE_CBCR                                   (0x5E040)
+#define USB3_AUX_CBCR                                    (0x5E044)
+#define USB3_AUX_CMD_RCGR                                (0x5E05C)
+#define USB3_AXI_TBU_CBCR                                (0x12060)
+#define PCIE_AXI_TBU_CBCR                                (0x12064)
+#define QUSB_REF_CLK_EN                                  (0x41030)
+#define DCC_CBCR                                         (0x77004)
+#define MSS_CFG_AHB_CBCR				 (0x49000)
+
+/* sdx20 */
+#define PCIE_AUX_CBCR						(0x5D024)
+#define PCIE_AUX_PHY_CMD_RCGR		(0x5D030)
+#define PCIE_BCR					(0x5D004)
+#define PCIE_AUX_CLK_SEL			(0x5D028)
+
+DEFINE_CLK_RPM_SMD_BRANCH(xo, xo_a_clk, RPM_MISC_CLK_TYPE,
+			  XO_ID, 19200000);
+
+DEFINE_CLK_RPM_SMD(ce_clk, ce_a_clk, RPM_CE_CLK_TYPE,
+		   CE_CLK_ID, NULL);
+DEFINE_CLK_RPM_SMD(pcnoc_clk, pcnoc_a_clk, RPM_BUS_CLK_TYPE,
+		   PCNOC_CLK_ID, NULL);
+DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE,
+		   BIMC_CLK_ID, NULL);
+DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE,
+		   SNOC_CLK_ID, NULL);
+DEFINE_CLK_RPM_SMD(ipa_clk, ipa_a_clk, RPM_IPA_CLK_TYPE,
+		   IPA_CLK_ID, NULL);
+DEFINE_CLK_RPM_SMD(qpic_clk, qpic_a_clk, RPM_QPIC_CLK_TYPE,
+		   QPIC_CLK_ID, NULL);
+DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE,
+			QDSS_CLK_ID);
+
+static DEFINE_CLK_VOTER(bimc_msmbus_clk, &bimc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(bimc_msmbus_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(mcd_ce_clk, &ce_clk.c, 85710000);
+static DEFINE_CLK_VOTER(pcnoc_keepalive_a_clk, &pcnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_msmbus_clk, &pcnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_msmbus_a_clk, &pcnoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_pm_clk, &pcnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(pcnoc_sps_clk, &pcnoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(qcedev_ce_clk, &ce_clk.c, 85710000);
+static DEFINE_CLK_VOTER(qcrypto_ce_clk, &ce_clk.c, 85710000);
+static DEFINE_CLK_VOTER(qseecom_ce_clk, &ce_clk.c, 85710000);
+static DEFINE_CLK_VOTER(scm_ce_clk, &ce_clk.c, 85710000);
+static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_BRANCH_VOTER(cxo_dwc3_clk, &xo.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_lpm_clk, &xo.c);
+static DEFINE_CLK_BRANCH_VOTER(cxo_otg_clk, &xo.c);
+
+DEFINE_CLK_RPM_SMD_XO_BUFFER(div_clk1, div_clk1_ao, DIV_CLK1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(ln_bb_clk, ln_bb_a_clk, LN_BB_CLK_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(rf_clk1, rf_clk1_ao, RF_CLK1_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(rf_clk2, rf_clk2_ao, RF_CLK2_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER(rf_clk3, rf_clk3_ao, RF_CLK3_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(rf_clk1_pin, rf_clk1_pin_ao,
+				     RF_CLK1_PIN_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(rf_clk2_pin, rf_clk2_pin_ao,
+				     RF_CLK2_PIN_ID);
+DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(rf_clk3_pin, rf_clk3_pin_ao,
+				     RF_CLK3_PIN_ID);
+
+static struct alpha_pll_masks alpha_pll_masks_20nm_p = {
+	.lock_mask = BIT(31),
+	.update_mask = BIT(22),
+	.vco_mask = BM(21, 20) >> 20,
+	.vco_shift = 20,
+	.alpha_en_mask = BIT(24),
+};
+
+static struct alpha_pll_vco_tbl alpha_pll_vco_20nm_p[] = {
+	VCO(3,  250000000,  500000000),
+	VCO(2,  500000000, 1000000000),
+	VCO(1, 1000000000, 1500000000),
+	VCO(0, 1500000000, 2000000000),
+};
+
+static struct alpha_pll_clk a7pll_clk = {
+	.masks = &alpha_pll_masks_20nm_p,
+	.base = &virt_apcsbase,
+	.vco_tbl = alpha_pll_vco_20nm_p,
+	.num_vco = ARRAY_SIZE(alpha_pll_vco_20nm_p),
+	.c = {
+		.parent = &xo_a_clk.c,
+		.dbg_name = "a7pll_clk",
+		.ops = &clk_ops_alpha_pll,
+		VDD_DIG_FMAX_MAP2_AO(LOW, 1000000000, NOMINAL, 2000000000),
+		CLK_INIT(a7pll_clk.c),
+	},
+};
+
+static unsigned int soft_vote_gpll0;
+
+static struct pll_vote_clk gpll0 = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_MODE,
+	.status_mask = BIT(30),
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_PRIMARY,
+	.base = &virt_base,
+	.c = {
+		.rate = 600000000,
+		.parent = &xo.c,
+		.dbg_name = "gpll0",
+		.ops = &clk_ops_pll_acpu_vote,
+		CLK_INIT(gpll0.c),
+	},
+};
+
+static struct pll_vote_clk gpll0_ao = {
+	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE,
+	.en_mask = BIT(0),
+	.status_reg = (void __iomem *)GPLL0_MODE,
+	.status_mask = BIT(30),
+	.soft_vote = &soft_vote_gpll0,
+	.soft_vote_mask = PLL_SOFT_VOTE_ACPU,
+	.base = &virt_base,
+	.c = {
+		.rate = 600000000,
+		.parent = &xo_a_clk.c,
+		.dbg_name = "gpll0_ao",
+		.ops = &clk_ops_pll_acpu_vote,
+		CLK_INIT(gpll0_ao.c),
+	},
+};
+
+DEFINE_EXT_CLK(gpll0_out_main_cgc, &gpll0.c);
+DEFINE_EXT_CLK(gpll0_ao_out_main_cgc, &gpll0_ao.c);
+
+DEFINE_FIXED_DIV_CLK(gpll0_out_main_div2_cgc, 2, &gpll0.c);
+
+static struct gate_clk gpll0_out_msscc = {
+	.en_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(18),
+	.delay_us = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gpll0_out_msscc",
+		.ops = &clk_ops_gate,
+		CLK_INIT(gpll0_out_msscc.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_apss_ahb_clk_src[] = {
+	F(  19200000,         xo_a_clk,    1,    0,     0),
+	F(  50000000, gpll0_ao_out_main_cgc,   12,    0,     0),
+	F( 100000000, gpll0_ao_out_main_cgc,    6,    0,     0),
+	F( 133333333, gpll0_ao_out_main_cgc,  4.5,    0,     0),
+	F_END
+};
+
+static struct rcg_clk apss_ahb_clk_src = {
+	.cmd_rcgr_reg = APSS_AHB_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_apss_ahb_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "apss_ahb_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP4(LOWER, 19200000, LOW, 50000000,
+				  NOMINAL, 100000000, HIGH, 133333333),
+		CLK_INIT(apss_ahb_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_usb30_master_clk_src[] = {
+	F(  60000000, gpll0_out_main_div2_cgc,    5,    0,     0),
+	F( 120000000, gpll0_out_main_cgc,    5,    0,     0),
+	F( 171430000, gpll0_out_main_cgc,  3.5,    0,     0),
+	F( 200000000, gpll0_out_main_cgc,    3,    0,     0),
+	F_END
+};
+
+static struct rcg_clk usb30_master_clk_src = {
+	.cmd_rcgr_reg = USB30_MASTER_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_usb30_master_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "usb30_master_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP4(LOWER, 60000000, LOW, 120000000,
+				  NOMINAL, 171430000, HIGH, 200000000),
+		CLK_INIT(usb30_master_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp_i2c_apps_clk_src[] = {
+	F(  19200000,         xo,    1,    0,     0),
+	F(  50000000, gpll0_out_main_cgc,   12,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup1_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 19200000, LOW, 50000000),
+		CLK_INIT(blsp1_qup1_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup1_spi_apps_clk_src[] = {
+	F(    960000,         xo,   10,    1,     2),
+	F(   4800000,         xo,    4,    0,     0),
+	F(   9600000,         xo,    2,    0,     0),
+	F(  15000000, gpll0_out_main_cgc,   10,    1,     4),
+	F(  19200000,         xo,    1,    0,     0),
+	F(  24000000, gpll0_out_main_cgc, 12.5,    1,     2),
+	F(  25000000, gpll0_out_main_cgc,   12,    1,     2),
+	F(  50000000, gpll0_out_main_cgc,   12,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup1_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP1_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup1_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup1_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 12500000, LOW, 25000000,
+				  NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup1_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup2_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup2_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 19200000),
+		CLK_INIT(blsp1_qup2_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup2_spi_apps_clk_src[] = {
+	F(    960000,         xo,   10,    1,     2),
+	F(   4800000,         xo,    4,    0,     0),
+	F(   9600000,         xo,    2,    0,     0),
+	F(  15000000, gpll0_out_main_cgc,   10,    1,     4),
+	F(  19200000,         xo,    1,    0,     0),
+	F(  24000000, gpll0_out_main_cgc, 12.5,    1,     2),
+	F(  25000000, gpll0_out_main_cgc,   12,    1,     2),
+	F(  50000000, gpll0_out_main_cgc,   12,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup2_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP2_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup2_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup2_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 12500000, LOW, 25000000,
+				  NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup2_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup3_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup3_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 19200000),
+		CLK_INIT(blsp1_qup3_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup3_spi_apps_clk_src[] = {
+	F(    960000,         xo,   10,    1,     2),
+	F(   4800000,         xo,    4,    0,     0),
+	F(   9600000,         xo,    2,    0,     0),
+	F(  15000000, gpll0_out_main_cgc,   10,    1,     4),
+	F(  19200000,         xo,    1,    0,     0),
+	F(  24000000, gpll0_out_main_cgc, 12.5,    1,     2),
+	F(  25000000, gpll0_out_main_cgc,   12,    1,     2),
+	F(  50000000, gpll0_out_main_cgc,   12,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup3_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP3_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup3_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup3_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 12500000, LOW, 25000000,
+				  NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup3_spi_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_qup4_i2c_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_I2C_APPS_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_blsp_i2c_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup4_i2c_apps_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP1(LOWER, 19200000),
+		CLK_INIT(blsp1_qup4_i2c_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp1_qup4_spi_apps_clk_src[] = {
+	F(    960000,         xo,   10,    1,     2),
+	F(   4800000,         xo,    4,    0,     0),
+	F(   9600000,         xo,    2,    0,     0),
+	F(  15000000, gpll0_out_main_cgc,   10,    1,     4),
+	F(  19200000,         xo,    1,    0,     0),
+	F(  24000000, gpll0_out_main_cgc, 12.5,    1,     2),
+	F(  25000000, gpll0_out_main_cgc,   12,    1,     2),
+	F(  50000000, gpll0_out_main_cgc,   12,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_qup4_spi_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_QUP4_SPI_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp1_qup4_spi_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_qup4_spi_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 12500000, LOW, 25000000,
+				  NOMINAL, 50000000),
+		CLK_INIT(blsp1_qup4_spi_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_blsp_uart_apps_clk_src[] = {
+	F(   3686400, gpll0_out_main_div2_cgc,    1,  192, 15625),
+	F(   7372800, gpll0_out_main_div2_cgc,    1,  384, 15625),
+	F(  14745600, gpll0_out_main_div2_cgc,    1,  768, 15625),
+	F(  16000000, gpll0_out_main_div2_cgc,    1,    4,    75),
+	F(  19200000,         xo,    1,    0,     0),
+	F(  24000000, gpll0_out_main_cgc,    5,    1,     5),
+	F(  32000000, gpll0_out_main_cgc,    1,    4,    75),
+	F(  40000000, gpll0_out_main_cgc,   15,    0,     0),
+	F(  46400000, gpll0_out_main_cgc,    1,   29,   375),
+	F(  48000000, gpll0_out_main_cgc, 12.5,    0,     0),
+	F(  51200000, gpll0_out_main_cgc,    1,   32,   375),
+	F(  56000000, gpll0_out_main_cgc,    1,    7,    75),
+	F(  58982400, gpll0_out_main_cgc,    1, 1536, 15625),
+	F(  60000000, gpll0_out_main_cgc,   10,    0,     0),
+	F(  63157895, gpll0_out_main_cgc,  9.5,    0,     0),
+	F_END
+};
+
+static struct rcg_clk blsp1_uart1_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_uart1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 19200000, LOW, 48000000,
+				  NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart1_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart2_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART2_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_uart2_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 19200000, LOW, 48000000,
+				  NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart2_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart3_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART3_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_uart3_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 19200000, LOW, 48000000,
+				  NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart3_apps_clk_src.c),
+	},
+};
+
+static struct rcg_clk blsp1_uart4_apps_clk_src = {
+	.cmd_rcgr_reg = BLSP1_UART4_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_blsp_uart_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "blsp1_uart4_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 19200000, LOW, 48000000,
+				  NOMINAL, 63160000),
+		CLK_INIT(blsp1_uart4_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_gp_clk_src[] = {
+	F(  19200000,         xo,    1,    0,     0),
+	F(  50000000, gpll0_out_main_div2_cgc,    6,    0,     0),
+	F( 100000000, gpll0_out_main_cgc,    6,    0,     0),
+	F( 200000000, gpll0_out_main_cgc,    3,    0,     0),
+	F_END
+};
+
+static struct rcg_clk gp1_clk_src = {
+	.cmd_rcgr_reg = GP1_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gp_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gp1_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 50000000, LOW, 100000000,
+				  NOMINAL, 200000000),
+		CLK_INIT(gp1_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp2_clk_src = {
+	.cmd_rcgr_reg = GP2_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gp_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gp2_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 50000000, LOW, 100000000,
+				  NOMINAL, 200000000),
+		CLK_INIT(gp2_clk_src.c),
+	},
+};
+
+static struct rcg_clk gp3_clk_src = {
+	.cmd_rcgr_reg = GP3_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_gp_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gp3_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 50000000, LOW, 100000000,
+				  NOMINAL, 200000000),
+		CLK_INIT(gp3_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_pcie_aux_clk_src[] = {
+	F(   1000000,         xo,    1,    5,    96),
+	F(  19200000,         xo,    1,    0,     0),
+	F_END
+};
+
+static struct rcg_clk pcie_aux_clk_src = {
+	.cmd_rcgr_reg = PCIE_AUX_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_pcie_aux_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "pcie_aux_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP1(LOWER, 19200000),
+		CLK_INIT(pcie_aux_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_pdm2_clk_src[] = {
+	F(  19200000,         xo,    1,    0,     0),
+	F(  60000000, gpll0_out_main_cgc,   10,    0,     0),
+	F_END
+};
+
+static struct rcg_clk pdm2_clk_src = {
+	.cmd_rcgr_reg = PDM2_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_pdm2_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "pdm2_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 19200000, LOW, 60000000),
+		CLK_INIT(pdm2_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_sdcc1_apps_clk_src[] = {
+	F(    144000,         xo,   16,    3,    25),
+	F(    400000,         xo,   12,    1,     4),
+	F(  20000000, gpll0_out_main_div2_cgc,   15,    0,     0),
+	F(  25000000, gpll0_out_main_div2_cgc,   12,    0,     0),
+	F(  50000000, gpll0_out_main_div2_cgc,    6,    0,     0),
+	F( 100000000, gpll0_out_main_cgc,    6,    0,     0),
+	F( 200000000, gpll0_out_main_cgc,    3,    0,     0),
+	F_END
+};
+
+static struct rcg_clk sdcc1_apps_clk_src = {
+	.cmd_rcgr_reg = SDCC1_APPS_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_sdcc1_apps_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "sdcc1_apps_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP3(LOWER, 50000000, LOW, 100000000,
+				  NOMINAL, 200000000),
+		CLK_INIT(sdcc1_apps_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_usb30_mock_utmi_clk_src[] = {
+	F(  19200000,         xo,    1,    0,     0),
+	F(  30000000, gpll0_out_main_div2_cgc,   10,    0,     0),
+	F(  60000000, gpll0_out_main_cgc,   10,    0,     0),
+	F_END
+};
+
+static struct rcg_clk usb30_mock_utmi_clk_src = {
+	.cmd_rcgr_reg = USB30_MOCK_UTMI_CMD_RCGR,
+	.set_rate = set_rate_hid,
+	.freq_tbl = ftbl_usb30_mock_utmi_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "usb30_mock_utmi_clk_src",
+		.ops = &clk_ops_rcg,
+		VDD_DIG_FMAX_MAP2(LOWER, 30000000, LOW, 60000000),
+		CLK_INIT(usb30_mock_utmi_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_usb3_aux_clk_src[] = {
+	F(   1000000,         xo,    1,    5,    96),
+	F_END
+};
+
+static struct rcg_clk usb3_aux_clk_src = {
+	.cmd_rcgr_reg = USB3_AUX_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_usb3_aux_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "usb3_aux_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP1(LOWER, 19200000),
+		CLK_INIT(usb3_aux_clk_src.c),
+	},
+};
+
+static struct reset_clk gcc_pcie_phy_reset = {
+	.reset_reg = PCIE_PHY_BCR,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pcie_phy_reset",
+		.ops = &clk_ops_rst,
+		CLK_INIT(gcc_pcie_phy_reset.c),
+	},
+};
+
+static struct reset_clk gcc_qusb2a_phy_reset = {
+	.reset_reg = QUSB2A_PHY_BCR,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_qusb2a_phy_reset",
+		.ops = &clk_ops_rst,
+		CLK_INIT(gcc_qusb2a_phy_reset.c),
+	},
+};
+
+static struct reset_clk gcc_usb3phy_phy_reset = {
+	.reset_reg = USB3PHY_PHY_BCR,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb3phy_phy_reset",
+		.ops = &clk_ops_rst,
+		CLK_INIT(gcc_usb3phy_phy_reset.c),
+	},
+};
+
+static struct reset_clk gcc_usb3_phy_reset = {
+	.reset_reg = USB3_PHY_BCR,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb3_phy_reset",
+		.ops = &clk_ops_rst,
+		CLK_INIT(gcc_usb3_phy_reset.c),
+	},
+};
+
+static struct local_vote_clk gcc_blsp1_ahb_clk = {
+	.cbcr_reg = BLSP1_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(10),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_blsp1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
+		.parent = &blsp1_qup1_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup1_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP1_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup1_spi_apps_clk",
+		.parent = &blsp1_qup1_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup1_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",
+		.parent = &blsp1_qup2_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup2_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP2_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup2_spi_apps_clk",
+		.parent = &blsp1_qup2_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup2_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
+		.parent = &blsp1_qup3_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup3_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP3_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup3_spi_apps_clk",
+		.parent = &blsp1_qup3_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup3_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_i2c_apps_clk",
+		.parent = &blsp1_qup4_i2c_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_i2c_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_qup4_spi_apps_clk = {
+	.cbcr_reg = BLSP1_QUP4_SPI_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_qup4_spi_apps_clk",
+		.parent = &blsp1_qup4_spi_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_qup4_spi_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart1_apps_clk = {
+	.cbcr_reg = BLSP1_UART1_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_uart1_apps_clk",
+		.parent = &blsp1_uart1_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart1_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart2_apps_clk = {
+	.cbcr_reg = BLSP1_UART2_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_uart2_apps_clk",
+		.parent = &blsp1_uart2_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart2_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart3_apps_clk = {
+	.cbcr_reg = BLSP1_UART3_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_uart3_apps_clk",
+		.parent = &blsp1_uart3_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart3_apps_clk.c),
+	},
+};
+
+static struct branch_clk gcc_blsp1_uart4_apps_clk = {
+	.cbcr_reg = BLSP1_UART4_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_blsp1_uart4_apps_clk",
+		.parent = &blsp1_uart4_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_blsp1_uart4_apps_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_boot_rom_ahb_clk = {
+	.cbcr_reg = BOOT_ROM_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(7),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_boot_rom_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_boot_rom_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_dcc_clk = {
+	.cbcr_reg = DCC_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_dcc_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_dcc_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp1_clk = {
+	.cbcr_reg = GP1_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_gp1_clk",
+		.parent = &gp1_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp1_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp2_clk = {
+	.cbcr_reg = GP2_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_gp2_clk",
+		.parent = &gp2_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_gp3_clk = {
+	.cbcr_reg = GP3_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_gp3_clk",
+		.parent = &gp3_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_gp3_clk.c),
+	},
+};
+
+static struct branch_clk gcc_mss_q6_bimc_axi_clk = {
+	.cbcr_reg = MSS_Q6_BIMC_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_mss_q6_bimc_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_mss_q6_bimc_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pcie_axi_clk = {
+	.cbcr_reg = PCIE_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pcie_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pcie_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pcie_axi_mstr_clk = {
+	.cbcr_reg = PCIE_AXI_MSTR_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pcie_axi_mstr_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pcie_axi_mstr_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pcie_cfg_ahb_clk = {
+	.cbcr_reg = PCIE_CFG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pcie_cfg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pcie_cfg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pcie_pipe_clk = {
+	.cbcr_reg = PCIE_PIPE_CBCR,
+	.bcr_reg = PCIEPHY_PHY_BCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.halt_check = DELAY,
+	.c = {
+		.dbg_name = "gcc_pcie_pipe_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pcie_pipe_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pcie_sleep_clk = {
+	.cbcr_reg = PCIE_SLEEP_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pcie_sleep_clk",
+		.parent = &pcie_aux_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pcie_sleep_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm2_clk = {
+	.cbcr_reg = PDM2_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pdm2_clk",
+		.parent = &pdm2_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm2_clk.c),
+	},
+};
+
+static struct branch_clk gcc_pdm_ahb_clk = {
+	.cbcr_reg = PDM_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pdm_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pdm_ahb_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_prng_ahb_clk = {
+	.cbcr_reg = PRNG_AHB_CBCR,
+	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(8),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_prng_ahb_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_prng_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_ahb_clk = {
+	.cbcr_reg = SDCC1_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_sdcc1_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sdcc1_apps_clk = {
+	.cbcr_reg = SDCC1_APPS_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_sdcc1_apps_clk",
+		.parent = &sdcc1_apps_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sdcc1_apps_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_apss_tcu_clk = {
+	.cbcr_reg = APSS_TCU_CBCR,
+	.vote_reg = APCS_SMMU_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(1),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_apss_tcu_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_apss_tcu_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_pcie_axi_tbu_clk = {
+	.cbcr_reg = PCIE_AXI_TBU_CBCR,
+	.vote_reg = APCS_SMMU_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(16),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pcie_axi_tbu_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_pcie_axi_tbu_clk.c),
+	},
+};
+
+static struct gate_clk gcc_pcie_ref_clk = {
+	.en_reg = PCIE_REF_CLK_EN,
+	.en_mask = BIT(0),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_pcie_ref_clk",
+		.ops = &clk_ops_gate,
+		CLK_INIT(gcc_pcie_ref_clk.c),
+	},
+};
+
+static struct gate_clk gcc_usb_ss_ref_clk = {
+	.en_reg = USB_SS_REF_CLK_EN,
+	.en_mask = BIT(0),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb_ss_ref_clk",
+		.ops = &clk_ops_gate,
+		CLK_INIT(gcc_usb_ss_ref_clk.c),
+	},
+};
+
+static struct gate_clk gcc_qusb_ref_clk = {
+	.en_reg = QUSB_REF_CLK_EN,
+	.en_mask = BIT(0),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_qusb_ref_clk",
+		.ops = &clk_ops_gate,
+		CLK_INIT(gcc_qusb_ref_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_smmu_cfg_clk = {
+	.cbcr_reg = SMMU_CFG_CBCR,
+	.vote_reg = APCS_SMMU_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(12),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_smmu_cfg_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_smmu_cfg_clk.c),
+	},
+};
+
+static struct local_vote_clk gcc_usb3_axi_tbu_clk = {
+	.cbcr_reg = USB3_AXI_TBU_CBCR,
+	.vote_reg = APCS_SMMU_CLOCK_BRANCH_ENA_VOTE,
+	.en_mask = BIT(15),
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb3_axi_tbu_clk",
+		.ops = &clk_ops_vote,
+		CLK_INIT(gcc_usb3_axi_tbu_clk.c),
+	},
+};
+
+static struct branch_clk gcc_sys_noc_usb3_axi_clk = {
+	.cbcr_reg = SYS_NOC_USB3_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_sys_noc_usb3_axi_clk",
+		.parent = &usb30_master_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sys_noc_usb3_axi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb30_master_clk = {
+	.cbcr_reg = USB30_MASTER_CBCR,
+	.bcr_reg = USB_30_BCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb30_master_clk",
+		.parent = &usb30_master_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb30_master_clk.c),
+		.depends = &gcc_sys_noc_usb3_axi_clk.c,
+	},
+};
+
+static struct branch_clk gcc_usb30_mock_utmi_clk = {
+	.cbcr_reg = USB30_MOCK_UTMI_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb30_mock_utmi_clk",
+		.parent = &usb30_mock_utmi_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb30_mock_utmi_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb30_sleep_clk = {
+	.cbcr_reg = USB30_SLEEP_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb30_sleep_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb30_sleep_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb3_aux_clk = {
+	.cbcr_reg = USB3_AUX_CBCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb3_aux_clk",
+		.parent = &usb3_aux_clk_src.c,
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb3_aux_clk.c),
+	},
+};
+
+static struct gate_clk gcc_usb3_pipe_clk = {
+	.en_reg = USB3_PIPE_CBCR,
+	.en_mask = BIT(0),
+	.delay_us = 50,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb3_pipe_clk",
+		.ops = &clk_ops_gate,
+		CLK_INIT(gcc_usb3_pipe_clk.c),
+	},
+};
+
+static struct branch_clk gcc_usb_phy_cfg_ahb_clk = {
+	.cbcr_reg = USB_PHY_CFG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_usb_phy_cfg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_usb_phy_cfg_ahb_clk.c),
+	},
+};
+
+static struct branch_clk gcc_mss_cfg_ahb_clk = {
+	.cbcr_reg = MSS_CFG_AHB_CBCR,
+	.has_sibling = 1,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "gcc_mss_cfg_ahb_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_mss_cfg_ahb_clk.c),
+	},
+};
+
+static struct mux_clk gcc_debug_mux;
+static struct clk_ops clk_ops_debug_mux;
+static struct clk_mux_ops gcc_debug_mux_ops;
+static struct branch_clk gcc_pcie_aux_clk;
+
+static struct measure_clk_data debug_mux_priv = {
+	.cxo = &xo.c,
+	.plltest_reg = PLLTEST_PAD_CFG,
+	.plltest_val = 0x51A00,
+	.xo_div4_cbcr = GCC_XO_DIV4_CBCR,
+	.ctl_reg = CLOCK_FRQ_MEASURE_CTL,
+	.status_reg = CLOCK_FRQ_MEASURE_STATUS,
+	.base = &virt_base,
+};
+
+static struct mux_clk gcc_debug_mux = {
+	.priv = &debug_mux_priv,
+	.ops = &gcc_debug_mux_ops,
+	.en_mask = BIT(16),
+	.mask = 0x3FF,
+	.base = &virt_dbgbase,
+	MUX_REC_SRC_LIST(
+	),
+	MUX_SRC_LIST(
+		{ &snoc_clk.c, 0x0000 },
+		{ &gcc_sys_noc_usb3_axi_clk.c, 0x0001 },
+		{ &pcnoc_clk.c, 0x0008 },
+		{ &gcc_mss_cfg_ahb_clk.c, 0x0030 },
+		{ &qdss_clk.c, 0x0042 },
+		{ &gcc_apss_tcu_clk.c, 0x0050 },
+		{ &gcc_smmu_cfg_clk.c, 0x005b },
+		{ &gcc_sdcc1_apps_clk.c, 0x0068 },
+		{ &gcc_sdcc1_ahb_clk.c, 0x0069 },
+		{ &gcc_blsp1_ahb_clk.c, 0x0088 },
+		{ &gcc_blsp1_qup1_spi_apps_clk.c, 0x008a },
+		{ &gcc_blsp1_qup1_i2c_apps_clk.c, 0x008b },
+		{ &gcc_blsp1_uart1_apps_clk.c, 0x008c },
+		{ &gcc_blsp1_qup2_spi_apps_clk.c, 0x008e },
+		{ &gcc_blsp1_qup2_i2c_apps_clk.c, 0x0090 },
+		{ &gcc_blsp1_uart2_apps_clk.c, 0x0091 },
+		{ &gcc_blsp1_qup3_spi_apps_clk.c, 0x0093 },
+		{ &gcc_blsp1_qup3_i2c_apps_clk.c, 0x0094 },
+		{ &gcc_blsp1_uart3_apps_clk.c, 0x0095 },
+		{ &gcc_blsp1_qup4_spi_apps_clk.c, 0x0098 },
+		{ &gcc_blsp1_qup4_i2c_apps_clk.c, 0x0099 },
+		{ &gcc_blsp1_uart4_apps_clk.c, 0x009a },
+		{ &gcc_pdm_ahb_clk.c, 0x00d0 },
+		{ &gcc_pdm2_clk.c, 0x00d2 },
+		{ &gcc_prng_ahb_clk.c, 0x00d8 },
+		{ &gcc_boot_rom_ahb_clk.c, 0x00f8 },
+		{ &ce_clk.c, 0x0138 },
+		{ &bimc_clk.c, 0x0155 },
+		{ &gcc_usb3_axi_tbu_clk.c, 0x0203 },
+		{ &gcc_pcie_axi_tbu_clk.c, 0x0204 },
+		{ &ipa_clk.c, 0x0218 },
+		{ &qpic_clk.c, 0x0220 },
+		{ &gcc_usb30_master_clk.c, 0x0230 },
+		{ &gcc_usb30_sleep_clk.c, 0x0231 },
+		{ &gcc_usb30_mock_utmi_clk.c, 0x0232 },
+		{ &gcc_usb_phy_cfg_ahb_clk.c, 0x0233 },
+		{ &gcc_usb3_pipe_clk.c, 0x0234 },
+		{ &gcc_usb3_aux_clk.c, 0x0235 },
+		{ &gcc_pcie_cfg_ahb_clk.c, 0x0238 },
+		{ &gcc_pcie_pipe_clk.c, 0x0239 },
+		{ &gcc_pcie_axi_clk.c, 0x023a },
+		{ &gcc_pcie_sleep_clk.c, 0x023b },
+		{ &gcc_pcie_axi_mstr_clk.c, 0x023c },
+		{ &gcc_dcc_clk.c, 0x0278 },
+		{&gcc_pcie_aux_clk.c, 0x023d },
+	),
+	.c = {
+		.dbg_name = "gcc_debug_mux",
+		.ops = &clk_ops_debug_mux,
+		.flags = CLKFLAG_NO_RATE_CACHE | CLKFLAG_MEASURE,
+		CLK_INIT(gcc_debug_mux.c),
+	},
+};
+
+static struct clk_lookup msm_clocks_rpm_9650[] = {
+	CLK_LIST(xo),
+	CLK_LIST(xo_a_clk),
+	CLK_LIST(ce_clk),
+	CLK_LIST(ce_a_clk),
+	CLK_LIST(pcnoc_clk),
+	CLK_LIST(pcnoc_a_clk),
+	CLK_LIST(bimc_clk),
+	CLK_LIST(bimc_a_clk),
+	CLK_LIST(snoc_clk),
+	CLK_LIST(snoc_a_clk),
+	CLK_LIST(ipa_clk),
+	CLK_LIST(ipa_a_clk),
+	CLK_LIST(qpic_clk),
+	CLK_LIST(qpic_a_clk),
+	CLK_LIST(qdss_clk),
+	CLK_LIST(qdss_a_clk),
+	CLK_LIST(bimc_msmbus_clk),
+	CLK_LIST(bimc_msmbus_a_clk),
+	CLK_LIST(mcd_ce_clk),
+	CLK_LIST(pcnoc_keepalive_a_clk),
+	CLK_LIST(pcnoc_msmbus_clk),
+	CLK_LIST(pcnoc_msmbus_a_clk),
+	CLK_LIST(pcnoc_pm_clk),
+	CLK_LIST(pcnoc_sps_clk),
+	CLK_LIST(qcedev_ce_clk),
+	CLK_LIST(qcrypto_ce_clk),
+	CLK_LIST(qseecom_ce_clk),
+	CLK_LIST(scm_ce_clk),
+	CLK_LIST(snoc_msmbus_clk),
+	CLK_LIST(snoc_msmbus_a_clk),
+	CLK_LIST(cxo_dwc3_clk),
+	CLK_LIST(cxo_lpm_clk),
+	CLK_LIST(cxo_otg_clk),
+	CLK_LIST(div_clk1),
+	CLK_LIST(div_clk1_ao),
+	CLK_LIST(ln_bb_clk),
+	CLK_LIST(ln_bb_a_clk),
+	CLK_LIST(rf_clk1),
+	CLK_LIST(rf_clk1_ao),
+	CLK_LIST(rf_clk2),
+	CLK_LIST(rf_clk2_ao),
+	CLK_LIST(rf_clk3),
+	CLK_LIST(rf_clk3_ao),
+	CLK_LIST(rf_clk1_pin),
+	CLK_LIST(rf_clk1_pin_ao),
+	CLK_LIST(rf_clk2_pin),
+	CLK_LIST(rf_clk2_pin_ao),
+	CLK_LIST(rf_clk3_pin),
+	CLK_LIST(rf_clk3_pin_ao),
+};
+
+static struct clk_lookup msm_clocks_gcc_9650[] = {
+	CLK_LIST(gpll0),
+	CLK_LIST(gpll0_ao),
+	CLK_LIST(gpll0_out_main_cgc),
+	CLK_LIST(gpll0_out_main_div2_cgc),
+	CLK_LIST(gpll0_out_msscc),
+	CLK_LIST(apss_ahb_clk_src),
+	CLK_LIST(usb30_master_clk_src),
+	CLK_LIST(blsp1_qup1_i2c_apps_clk_src),
+	CLK_LIST(blsp1_qup1_spi_apps_clk_src),
+	CLK_LIST(blsp1_qup2_i2c_apps_clk_src),
+	CLK_LIST(blsp1_qup2_spi_apps_clk_src),
+	CLK_LIST(blsp1_qup3_i2c_apps_clk_src),
+	CLK_LIST(blsp1_qup3_spi_apps_clk_src),
+	CLK_LIST(blsp1_qup4_i2c_apps_clk_src),
+	CLK_LIST(blsp1_qup4_spi_apps_clk_src),
+	CLK_LIST(blsp1_uart1_apps_clk_src),
+	CLK_LIST(blsp1_uart2_apps_clk_src),
+	CLK_LIST(blsp1_uart3_apps_clk_src),
+	CLK_LIST(blsp1_uart4_apps_clk_src),
+	CLK_LIST(gp1_clk_src),
+	CLK_LIST(gp2_clk_src),
+	CLK_LIST(gp3_clk_src),
+	CLK_LIST(pcie_aux_clk_src),
+	CLK_LIST(pdm2_clk_src),
+	CLK_LIST(sdcc1_apps_clk_src),
+	CLK_LIST(usb30_mock_utmi_clk_src),
+	CLK_LIST(usb3_aux_clk_src),
+	CLK_LIST(gcc_pcie_phy_reset),
+	CLK_LIST(gcc_qusb2a_phy_reset),
+	CLK_LIST(gcc_usb3phy_phy_reset),
+	CLK_LIST(gcc_usb3_phy_reset),
+	CLK_LIST(gcc_blsp1_ahb_clk),
+	CLK_LIST(gcc_blsp1_qup1_i2c_apps_clk),
+	CLK_LIST(gcc_blsp1_qup1_spi_apps_clk),
+	CLK_LIST(gcc_blsp1_qup2_i2c_apps_clk),
+	CLK_LIST(gcc_blsp1_qup2_spi_apps_clk),
+	CLK_LIST(gcc_blsp1_qup3_i2c_apps_clk),
+	CLK_LIST(gcc_blsp1_qup3_spi_apps_clk),
+	CLK_LIST(gcc_blsp1_qup4_i2c_apps_clk),
+	CLK_LIST(gcc_blsp1_qup4_spi_apps_clk),
+	CLK_LIST(gcc_blsp1_uart1_apps_clk),
+	CLK_LIST(gcc_blsp1_uart2_apps_clk),
+	CLK_LIST(gcc_blsp1_uart3_apps_clk),
+	CLK_LIST(gcc_blsp1_uart4_apps_clk),
+	CLK_LIST(gcc_boot_rom_ahb_clk),
+	CLK_LIST(gcc_dcc_clk),
+	CLK_LIST(gcc_gp1_clk),
+	CLK_LIST(gcc_gp2_clk),
+	CLK_LIST(gcc_gp3_clk),
+	CLK_LIST(gcc_mss_q6_bimc_axi_clk),
+	CLK_LIST(gcc_pcie_axi_clk),
+	CLK_LIST(gcc_pcie_axi_mstr_clk),
+	CLK_LIST(gcc_pcie_cfg_ahb_clk),
+	CLK_LIST(gcc_pcie_pipe_clk),
+	CLK_LIST(gcc_pcie_sleep_clk),
+	CLK_LIST(gcc_pdm2_clk),
+	CLK_LIST(gcc_pdm_ahb_clk),
+	CLK_LIST(gcc_prng_ahb_clk),
+	CLK_LIST(gcc_sdcc1_ahb_clk),
+	CLK_LIST(gcc_sdcc1_apps_clk),
+	CLK_LIST(gcc_apss_tcu_clk),
+	CLK_LIST(gcc_pcie_axi_tbu_clk),
+	CLK_LIST(gcc_pcie_ref_clk),
+	CLK_LIST(gcc_usb_ss_ref_clk),
+	CLK_LIST(gcc_qusb_ref_clk),
+	CLK_LIST(gcc_smmu_cfg_clk),
+	CLK_LIST(gcc_usb3_axi_tbu_clk),
+	CLK_LIST(gcc_sys_noc_usb3_axi_clk),
+	CLK_LIST(gcc_usb30_master_clk),
+	CLK_LIST(gcc_usb30_mock_utmi_clk),
+	CLK_LIST(gcc_usb30_sleep_clk),
+	CLK_LIST(gcc_usb3_aux_clk),
+	CLK_LIST(gcc_usb3_pipe_clk),
+	CLK_LIST(gcc_usb_phy_cfg_ahb_clk),
+	CLK_LIST(gcc_mss_cfg_ahb_clk),
+	CLK_LIST(a7pll_clk),
+};
+
+/* sdx20 */
+/* Fractional Val offset from PLL base */
+#define APCS_CPU_PLL_FRAC_OFF	0x40
+
+static int set_pcie_aux_mux_sel(struct mux_clk *clk, int sel);
+static int get_pcie_aux_mux_sel(struct mux_clk *clk);
+
+static struct alpha_pll_masks fabia_pll_masks_p = {
+	.lock_mask = BIT(31),
+	.active_mask = BIT(30),
+	.update_mask = BIT(22),
+	.output_mask = 0xf,
+};
+
+static struct alpha_pll_vco_tbl fabia_pll_vco_p[] = {
+	VCO(0,  250000000,  2000000000),
+	VCO(1,  125000000,  1000000000),
+};
+
+static struct rcg_clk pcie_aux_phy_clk_src = {
+	.cmd_rcgr_reg = PCIE_AUX_PHY_CMD_RCGR,
+	.set_rate = set_rate_mnd,
+	.freq_tbl = ftbl_pcie_aux_clk_src,
+	.current_freq = &rcg_dummy_freq,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "pcie_aux_phy_clk_src",
+		.ops = &clk_ops_rcg_mnd,
+		VDD_DIG_FMAX_MAP1(LOWER, 19200000),
+		CLK_INIT(pcie_aux_phy_clk_src.c),
+	},
+};
+
+static struct clk_freq_tbl ftbl_apss_ahb_clk_src_sdx20[] = {
+	F(  50000000, gpll0_ao_out_main_cgc,   12,    0,     0),
+	F( 100000000, gpll0_ao_out_main_cgc,    6,    0,     0),
+	F( 133333333, gpll0_ao_out_main_cgc,  4.5,    0,     0),
+	F_END
+};
+
+static struct clk_freq_tbl ftbl_usb30_mock_utmi_clk_src_sdx20[] = {
+	F(  19200000,         xo,    1,    0,     0),
+	F_END
+};
+
+DEFINE_CLK_DUMMY(pcie20_phy_aux_clk, 16600000);
+
+static struct clk_mux_ops pcie_aux_mux_ops = {
+	.set_mux_sel = set_pcie_aux_mux_sel,
+	.get_mux_sel = get_pcie_aux_mux_sel
+};
+
+static struct mux_clk pcie_aux_mux_clk  = {
+	.num_parents = 2,
+	.offset = PCIE_AUX_CLK_SEL,
+	.parents = (struct clk_src[]) {
+		{&pcie20_phy_aux_clk.c, 0},
+		{&xo.c, 2},
+	},
+	.ops = &pcie_aux_mux_ops,
+	.mask = 0x3,
+	.shift = 0,
+	.base = &virt_base,
+	.c = {
+		.dbg_name = "pcie_aux_mux_clk",
+		.ops = &clk_ops_gen_mux,
+		.flags = CLKFLAG_NO_RATE_CACHE,
+		CLK_INIT(pcie_aux_mux_clk.c),
+	}
+};
+
+static struct branch_clk gcc_pcie_aux_clk = {
+	.cbcr_reg = PCIE_AUX_CBCR,
+	.bcr_reg = PCIE_BCR,
+	.has_sibling = 0,
+	.base = &virt_base,
+	.c = {
+		.parent = &pcie_aux_mux_clk.c,
+		.dbg_name = "gcc_pcie_aux_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_pcie_aux_clk.c),
+	},
+};
+
+static struct clk_lookup msm_clocks_gcc_sdx20[] = {
+	CLK_LIST(gcc_pcie_aux_clk),
+	CLK_LIST(pcie_aux_phy_clk_src),
+	CLK_LIST(pcie20_phy_aux_clk),
+	CLK_LIST(pcie_aux_mux_clk),
+};
+
+static int set_pcie_aux_mux_sel(struct mux_clk *clk, int sel)
+{
+	u32 regval;
+
+	regval = readl_relaxed(*clk->base + clk->offset);
+	regval &= ~(clk->mask << clk->shift);
+	regval |= (sel & clk->mask) << clk->shift;
+	writel_relaxed(regval, *clk->base + clk->offset);
+
+	return 0;
+}
+
+static int get_pcie_aux_mux_sel(struct mux_clk *clk)
+{
+	u32 regval;
+
+	regval = readl_relaxed(*clk->base + clk->offset);
+	return (regval >> clk->shift) & clk->mask;
+}
+
+static void msm_clocks_gcc_sdx20_fixup(void)
+{
+	gcc_pcie_sleep_clk.c.parent =  &pcie_aux_phy_clk_src.c;
+
+	a7pll_clk.fabia_frac_offset = APCS_CPU_PLL_FRAC_OFF;
+	a7pll_clk.masks = &fabia_pll_masks_p;
+	a7pll_clk.vco_tbl =  fabia_pll_vco_p;
+	a7pll_clk.num_vco =  ARRAY_SIZE(fabia_pll_vco_p);
+	a7pll_clk.c.ops = &clk_ops_fabia_alpha_pll;
+	a7pll_clk.is_fabia = true;
+
+	apss_ahb_clk_src.freq_tbl = ftbl_apss_ahb_clk_src_sdx20;
+	usb30_mock_utmi_clk_src.freq_tbl =
+		ftbl_usb30_mock_utmi_clk_src_sdx20;
+
+	sdcc1_apps_clk_src.c.fmax[VDD_DIG_MIN] = 25000000;
+	sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOWER] = 50000000;
+	sdcc1_apps_clk_src.c.fmax[VDD_DIG_LOW] = 1000000000;
+	sdcc1_apps_clk_src.c.fmax[VDD_DIG_NOMINAL] = 2000000000;
+
+	blsp1_qup1_spi_apps_clk_src.c.fmax[VDD_DIG_MIN] = 6250000;
+	blsp1_qup1_spi_apps_clk_src.c.fmax[VDD_DIG_MIN] = 6250000;
+	blsp1_qup2_i2c_apps_clk_src.c.fmax[VDD_DIG_MIN] = 9600000;
+	blsp1_qup2_spi_apps_clk_src.c.fmax[VDD_DIG_MIN] = 6250000;
+	blsp1_qup3_i2c_apps_clk_src.c.fmax[VDD_DIG_MIN] = 9600000;
+	blsp1_qup3_spi_apps_clk_src.c.fmax[VDD_DIG_MIN] = 6250000;
+
+	pcie_aux_clk_src.c.ops = &clk_ops_dummy;
+}
+
+static int msm_gcc_9650_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret;
+	bool for_sdx20 = false;
+
+	ret = vote_bimc(&bimc_clk, INT_MAX);
+	if (ret < 0)
+		return ret;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cc_base");
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get CC base.\n");
+		return -EINVAL;
+	}
+	virt_base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!virt_base) {
+		dev_err(&pdev->dev, "Failed to map in CC registers.\n");
+		return -ENOMEM;
+	}
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "apcs_base");
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get APCS base.\n");
+		return -EINVAL;
+	}
+	virt_apcsbase = devm_ioremap(&pdev->dev, res->start,
+						resource_size(res));
+	if (!virt_apcsbase) {
+		dev_err(&pdev->dev, "Failed to map in APCS registers.\n");
+		return -ENOMEM;
+	}
+
+	vdd_dig.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_dig");
+	if (IS_ERR(vdd_dig.regulator[0])) {
+		if (!(PTR_ERR(vdd_dig.regulator[0]) == -EPROBE_DEFER))
+			dev_err(&pdev->dev, "Unable to get vdd_dig regulator!");
+		return PTR_ERR(vdd_dig.regulator[0]);
+	}
+
+	vdd_dig_ao.regulator[0] = devm_regulator_get(&pdev->dev, "vdd_dig_ao");
+	if (IS_ERR(vdd_dig_ao.regulator[0])) {
+		if (!(PTR_ERR(vdd_dig_ao.regulator[0]) == -EPROBE_DEFER))
+			dev_err(&pdev->dev, "Unable to get vdd_dig_ao regulator!");
+		return PTR_ERR(vdd_dig_ao.regulator[0]);
+	}
+
+	ret = of_msm_clock_register(pdev->dev.of_node,
+				    msm_clocks_rpm_9650,
+				    ARRAY_SIZE(msm_clocks_rpm_9650));
+	if (ret)
+		return ret;
+
+	if (of_device_is_compatible(pdev->dev.of_node, "qcom,gcc-9650")) {
+		vdd_dig.use_max_uV = true;
+		vdd_dig_ao.use_max_uV = true;
+	}
+
+	for_sdx20 = of_device_is_compatible(pdev->dev.of_node,
+						"qcom,gcc-sdx20");
+
+	ret = enable_rpm_scaling();
+	if (ret < 0)
+		return ret;
+
+	dev_info(&pdev->dev, "Registered RPM clocks.\n");
+
+	/*
+	 * Update for sdx20 clocks.
+	 */
+	if (for_sdx20)
+		msm_clocks_gcc_sdx20_fixup();
+
+	ret = of_msm_clock_register(pdev->dev.of_node,
+				    msm_clocks_gcc_9650,
+				    ARRAY_SIZE(msm_clocks_gcc_9650));
+	if (ret)
+		return ret;
+
+	/*
+	 * Register sdx20 clocks.
+	 */
+	if (for_sdx20)
+		ret = of_msm_clock_register(pdev->dev.of_node,
+				    msm_clocks_gcc_sdx20,
+				    ARRAY_SIZE(msm_clocks_gcc_sdx20));
+	if (ret)
+		return ret;
+
+	/*
+	 * Hold an active set vote for the PCNOC AHB source.
+	 * Sleep set vote is 0.
+	 */
+	clk_set_rate(&pcnoc_keepalive_a_clk.c, 19200000);
+	clk_prepare_enable(&pcnoc_keepalive_a_clk.c);
+
+	clk_prepare_enable(&xo_a_clk.c);
+
+	dev_info(&pdev->dev, "Registered GCC clocks.\n");
+
+	return 0;
+}
+
+static const struct of_device_id msm_clock_gcc_match_table[] = {
+	{ .compatible = "qcom,gcc-9650" },
+	{ .compatible = "qcom,gcc-sdx20" },
+	{}
+};
+
+static struct platform_driver msm_clock_gcc_driver = {
+	.probe = msm_gcc_9650_probe,
+	.driver = {
+		.name = "qcom,gcc-9650",
+		.of_match_table = msm_clock_gcc_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+int __init msm_gcc_9650_init(void)
+{
+	return platform_driver_register(&msm_clock_gcc_driver);
+}
+arch_initcall(msm_gcc_9650_init);
+
+/* ======== Clock Debug Controller ======== */
+static struct clk_lookup msm_clocks_measure_9650[] = {
+	CLK_LOOKUP_OF("measure", gcc_debug_mux, "debug"),
+};
+
+static const struct of_device_id msm_clock_debug_match_table[] = {
+	{ .compatible = "qcom,cc-debug-9650" },
+	{}
+};
+
+static int msm_clock_debug_9650_probe(struct platform_device *pdev)
+{
+	struct resource *res;
+	int ret;
+
+	clk_ops_debug_mux = clk_ops_gen_mux;
+	clk_ops_debug_mux.get_rate = measure_get_rate;
+
+	gcc_debug_mux_ops = mux_reg_ops;
+
+	res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "cc_base");
+	if (!res) {
+		dev_err(&pdev->dev, "Failed to get CC base.\n");
+		return -EINVAL;
+	}
+	virt_dbgbase = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!virt_dbgbase) {
+		dev_err(&pdev->dev, "Failed to map in CC registers.\n");
+		return -ENOMEM;
+	}
+
+	ret = of_msm_clock_register(pdev->dev.of_node,
+				    msm_clocks_measure_9650,
+				    ARRAY_SIZE(msm_clocks_measure_9650));
+	if (ret)
+		return ret;
+
+	dev_info(&pdev->dev, "Registered debug mux.\n");
+	return ret;
+}
+
+static struct platform_driver msm_clock_debug_driver = {
+	.probe = msm_clock_debug_9650_probe,
+	.driver = {
+		.name = "qcom,cc-debug-9650",
+		.of_match_table = msm_clock_debug_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+int __init msm_clock_debug_9650_init(void)
+{
+	return platform_driver_register(&msm_clock_debug_driver);
+}
+late_initcall(msm_clock_debug_9650_init);
diff --git a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
index c5d12e5..20b8e34 100644
--- a/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
+++ b/drivers/clk/msm/mdss/mdss-dsi-pll-8996-util.c
@@ -485,7 +485,8 @@
 	struct dsi_pll_input *pin = &pdb->in;
 	struct dsi_pll_output *pout = &pdb->out;
 	s64 multiplier = BIT(20);
-	s64 dec_start_multiple, dec_start, pll_comp_val;
+	s64 dec_start_multiple, dec_start;
+	u64 pll_comp_val;
 	s32 duration, div_frac_start;
 	s64 vco_clk_rate = pll->vco_current_rate;
 	s64 fref = pll->vco_ref_clk_rate;
@@ -560,8 +561,8 @@
 {
 	struct dsi_pll_input *pin = &pdb->in;
 	struct dsi_pll_output *pout = &pdb->out;
-	s64 data;
-	u32 cnt;
+	u64 data;
+	u64 cnt;
 
 	data = fref * pin->vco_measure_time;
 	do_div(data, 1000000);
diff --git a/drivers/clk/msm/vdd-level-9650.h b/drivers/clk/msm/vdd-level-9650.h
new file mode 100644
index 0000000..d8f95b0
--- /dev/null
+++ b/drivers/clk/msm/vdd-level-9650.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __DRIVERS_CLK_QCOM_VDD_LEVEL_9650_H
+#define __DRIVERS_CLK_QCOM_VDD_LEVEL_9650_H
+
+#include <linux/clk/msm-clock-generic.h>
+#include <linux/regulator/rpm-smd-regulator.h>
+#include <linux/regulator/consumer.h>
+
+#define VDD_DIG_FMAX_MAP1(l1, f1) \
+	.vdd_class = &vdd_dig,			\
+	.fmax = (unsigned long[VDD_DIG_NUM]) {	\
+		[VDD_DIG_##l1] = (f1),		\
+	},					\
+	.num_fmax = VDD_DIG_NUM
+#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
+	.vdd_class = &vdd_dig,			\
+	.fmax = (unsigned long[VDD_DIG_NUM]) {	\
+		[VDD_DIG_##l1] = (f1),		\
+		[VDD_DIG_##l2] = (f2),		\
+	},					\
+	.num_fmax = VDD_DIG_NUM
+#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
+	.vdd_class = &vdd_dig,			\
+	.fmax = (unsigned long[VDD_DIG_NUM]) {	\
+		[VDD_DIG_##l1] = (f1),		\
+		[VDD_DIG_##l2] = (f2),		\
+		[VDD_DIG_##l3] = (f3),		\
+	},					\
+	.num_fmax = VDD_DIG_NUM
+#define VDD_DIG_FMAX_MAP4(l1, f1, l2, f2, l3, f3, l4, f4) \
+	.vdd_class = &vdd_dig,			\
+	.fmax = (unsigned long[VDD_DIG_NUM]) {	\
+		[VDD_DIG_##l1] = (f1),		\
+		[VDD_DIG_##l2] = (f2),		\
+		[VDD_DIG_##l3] = (f3),		\
+		[VDD_DIG_##l4] = (f4),		\
+	},					\
+	.num_fmax = VDD_DIG_NUM
+
+#define VDD_DIG_FMAX_MAP2_AO(l1, f1, l2, f2) \
+	.vdd_class = &vdd_dig_ao,			\
+	.fmax = (unsigned long[VDD_DIG_NUM]) {	\
+		[VDD_DIG_##l1] = (f1),		\
+		[VDD_DIG_##l2] = (f2),		\
+	},					\
+	.num_fmax = VDD_DIG_NUM
+
+#define VDD_GPU_PLL_FMAX_MAP2(l1, f1, l2, f2)	\
+	.vdd_class = &vdd_gpucc_mx,		\
+	.fmax = (unsigned long[VDD_DIG_NUM]) {	\
+		[VDD_DIG_##l1] = (f1),		\
+		[VDD_DIG_##l2] = (f2),		\
+	},					\
+	.num_fmax = VDD_DIG_NUM
+
+#define VDD_GPU_PLL_FMAX_MAP3(l1, f1, l2, f2, l3, f3)	\
+	.vdd_class = &vdd_gpucc_mx,			\
+	.fmax = (unsigned long[VDD_DIG_NUM]) {		\
+		[VDD_DIG_##l1] = (f1),			\
+		[VDD_DIG_##l2] = (f2),			\
+		[VDD_DIG_##l3] = (f3),			\
+	},						\
+	.num_fmax = VDD_DIG_NUM
+
+enum vdd_dig_levels {
+	VDD_DIG_NONE,
+	VDD_DIG_MIN,		/* MIN SVS */
+	VDD_DIG_LOWER,		/* SVS2 */
+	VDD_DIG_LOW,		/* SVS */
+	VDD_DIG_NOMINAL,	/* NOM */
+	VDD_DIG_HIGH,		/* TURBO */
+	VDD_DIG_NUM
+};
+
+static int vdd_corner[] = {
+	RPM_REGULATOR_LEVEL_NONE,		/* VDD_DIG_NONE */
+	RPM_REGULATOR_LEVEL_MIN_SVS,		/* VDD_DIG_MIN */
+	RPM_REGULATOR_LEVEL_LOW_SVS,		/* VDD_DIG_LOWER */
+	RPM_REGULATOR_LEVEL_SVS,		/* VDD_DIG_LOW */
+	RPM_REGULATOR_LEVEL_NOM,		/* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_LEVEL_TURBO,		/* VDD_DIG_HIGH */
+};
+
+#endif
diff --git a/drivers/clk/qcom/Kconfig b/drivers/clk/qcom/Kconfig
index 87d067a..79739bc 100644
--- a/drivers/clk/qcom/Kconfig
+++ b/drivers/clk/qcom/Kconfig
@@ -252,4 +252,13 @@
 	Say Y if you want to support CPU clock scaling using
 	CPUfreq drivers for dyanmic power management.
 
+config MDM_DEBUGCC_SDXPOORWILLS
+	tristate "SDXPOORWILLS Debug Clock Controller"
+	depends on COMMON_CLK_QCOM
+	help
+	  Support for the debug clock controller on sdxpoorwills
+	  based devices.
+	  Say Y if you want to support the clock measurement
+	  functionality.
+
 source "drivers/clk/qcom/mdss/Kconfig"
diff --git a/drivers/clk/qcom/Makefile b/drivers/clk/qcom/Makefile
index 8cb46a7..0cd2e94 100644
--- a/drivers/clk/qcom/Makefile
+++ b/drivers/clk/qcom/Makefile
@@ -23,6 +23,7 @@
 obj-$(CONFIG_IPQ_GCC_806X) += gcc-ipq806x.o
 obj-$(CONFIG_IPQ_LCC_806X) += lcc-ipq806x.o
 obj-$(CONFIG_MDM_CLOCK_CPU_SDXPOORWILLS) += clk-cpu-a7.o
+obj-$(CONFIG_MDM_DEBUGCC_SDXPOORWILLS) += debugcc-sdxpoorwills.o
 obj-$(CONFIG_MDM_GCC_9615) += gcc-mdm9615.o
 obj-$(CONFIG_MDM_GCC_SDXPOORWILLS) += gcc-sdxpoorwills.o
 obj-$(CONFIG_MDM_LCC_9615) += lcc-mdm9615.o
diff --git a/drivers/clk/qcom/clk-cpu-osm.c b/drivers/clk/qcom/clk-cpu-osm.c
index bf4df55..f53d1ee 100644
--- a/drivers/clk/qcom/clk-cpu-osm.c
+++ b/drivers/clk/qcom/clk-cpu-osm.c
@@ -432,6 +432,7 @@
 static DEFINE_CLK_VOTER(l3_cluster0_vote_clk, l3_clk, 0);
 static DEFINE_CLK_VOTER(l3_cluster1_vote_clk, l3_clk, 0);
 static DEFINE_CLK_VOTER(l3_misc_vote_clk, l3_clk, 0);
+static DEFINE_CLK_VOTER(l3_gpu_vote_clk, l3_clk, 0);
 
 static struct clk_osm pwrcl_clk = {
 	.cluster_num = 1,
@@ -581,6 +582,7 @@
 	[L3_CLUSTER0_VOTE_CLK] = &l3_cluster0_vote_clk.hw,
 	[L3_CLUSTER1_VOTE_CLK] = &l3_cluster1_vote_clk.hw,
 	[L3_MISC_VOTE_CLK] = &l3_misc_vote_clk.hw,
+	[L3_GPU_VOTE_CLK] = &l3_gpu_vote_clk.hw,
 	[PWRCL_CLK] = &pwrcl_clk.hw,
 	[CPU0_PWRCL_CLK] = &cpu0_pwrcl_clk.hw,
 	[CPU1_PWRCL_CLK] = &cpu1_pwrcl_clk.hw,
@@ -1345,6 +1347,8 @@
 			"clk: Failed to enable cluster1 clock for L3\n");
 	WARN(clk_prepare_enable(l3_misc_vote_clk.hw.clk),
 			"clk: Failed to enable misc clock for L3\n");
+	WARN(clk_prepare_enable(l3_gpu_vote_clk.hw.clk),
+			"clk: Failed to enable iocoherent bwmon clock for L3\n");
 
 	/*
 	 * Call clk_prepare_enable for the silver clock explicitly in order to
diff --git a/drivers/clk/qcom/clk-debug.c b/drivers/clk/qcom/clk-debug.c
index d366ad4..d101536 100644
--- a/drivers/clk/qcom/clk-debug.c
+++ b/drivers/clk/qcom/clk-debug.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -275,7 +275,7 @@
 	if (clk_set_parent(measure->clk, hw->clk))
 		return 0;
 
-	debugfs_create_file("clk_measure", 0x444, dentry, hw,
+	debugfs_create_file("clk_measure", 0444, dentry, hw,
 					&clk_measure_fops);
 	return 0;
 }
diff --git a/drivers/clk/qcom/clk-debug.h b/drivers/clk/qcom/clk-debug.h
index aa8d97b..a9f71b4 100644
--- a/drivers/clk/qcom/clk-debug.h
+++ b/drivers/clk/qcom/clk-debug.h
@@ -44,6 +44,7 @@
 	GPU_CC,
 	VIDEO_CC,
 	CPU,
+	MAX_NUM_CC,
 };
 
 /**
diff --git a/drivers/clk/qcom/debugcc-sdxpoorwills.c b/drivers/clk/qcom/debugcc-sdxpoorwills.c
new file mode 100644
index 0000000..d66a623
--- /dev/null
+++ b/drivers/clk/qcom/debugcc-sdxpoorwills.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "clk: %s: " fmt, __func__
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+
+#include "clk-debug.h"
+
+static struct measure_clk_data debug_mux_priv = {
+	.ctl_reg = 0x79004,
+	.status_reg = 0x79008,
+	.xo_div4_cbcr = 0x22008,
+};
+
+static const char *const debug_mux_parent_names[] = {
+	"gcc_blsp1_ahb_clk",
+	"gcc_blsp1_qup1_i2c_apps_clk",
+	"gcc_blsp1_qup1_spi_apps_clk",
+	"gcc_blsp1_qup2_i2c_apps_clk",
+	"gcc_blsp1_qup2_spi_apps_clk",
+	"gcc_blsp1_qup3_i2c_apps_clk",
+	"gcc_blsp1_qup3_spi_apps_clk",
+	"gcc_blsp1_qup4_i2c_apps_clk",
+	"gcc_blsp1_qup4_spi_apps_clk",
+	"gcc_blsp1_sleep_clk",
+	"gcc_blsp1_uart1_apps_clk",
+	"gcc_blsp1_uart2_apps_clk",
+	"gcc_blsp1_uart3_apps_clk",
+	"gcc_blsp1_uart4_apps_clk",
+	"gcc_boot_rom_ahb_clk",
+	"gcc_ce1_ahb_clk",
+	"gcc_ce1_axi_clk",
+	"gcc_ce1_clk",
+	"gcc_cpuss_ahb_clk",
+	"gcc_cpuss_gnoc_clk",
+	"gcc_cpuss_rbcpr_clk",
+	"gcc_eth_axi_clk",
+	"gcc_eth_ptp_clk",
+	"gcc_eth_rgmii_clk",
+	"gcc_eth_slave_ahb_clk",
+	"gcc_gp1_clk",
+	"gcc_gp2_clk",
+	"gcc_gp3_clk",
+	"gcc_pcie_aux_clk",
+	"gcc_pcie_cfg_ahb_clk",
+	"gcc_pcie_mstr_axi_clk",
+	"gcc_pcie_phy_refgen_clk",
+	"gcc_pcie_pipe_clk",
+	"gcc_pcie_sleep_clk",
+	"gcc_pcie_slv_axi_clk",
+	"gcc_pcie_slv_q2a_axi_clk",
+	"gcc_pdm2_clk",
+	"gcc_pdm_ahb_clk",
+	"gcc_pdm_xo4_clk",
+	"gcc_prng_ahb_clk",
+	"gcc_sdcc1_ahb_clk",
+	"gcc_sdcc1_apps_clk",
+	"gcc_spmi_fetcher_ahb_clk",
+	"gcc_spmi_fetcher_clk",
+	"gcc_sys_noc_cpuss_ahb_clk",
+	"gcc_sys_noc_usb3_clk",
+	"gcc_usb30_master_clk",
+	"gcc_usb30_mock_utmi_clk",
+	"gcc_usb30_sleep_clk",
+	"gcc_usb3_phy_aux_clk",
+	"gcc_usb3_phy_pipe_clk",
+	"gcc_usb_phy_cfg_ahb2phy_clk",
+	"gcc_xo_div4_clk",
+	"measure_only_ipa_2x_clk",
+};
+
+static struct clk_debug_mux gcc_debug_mux = {
+	.priv = &debug_mux_priv,
+	.debug_offset = 0x79000,
+	.post_div_offset = 0x29000,
+	.cbcr_offset = 0x29004,
+	.src_sel_mask = 0x3FF,
+	.src_sel_shift = 0,
+	.post_div_mask = 0xF,
+	.post_div_shift = 0,
+	MUX_SRC_LIST(
+		{ "gcc_blsp1_ahb_clk", 0x34, 4, GCC,
+			0x34, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup1_i2c_apps_clk", 0x37, 4, GCC,
+			0x37, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup1_spi_apps_clk", 0x36, 4, GCC,
+			0x36, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup2_i2c_apps_clk", 0x3B, 4, GCC,
+			0x3B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup2_spi_apps_clk", 0x3A, 4, GCC,
+			0x3A, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup3_i2c_apps_clk", 0x3F, 4, GCC,
+			0x3F, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup3_spi_apps_clk", 0x3E, 4, GCC,
+			0x3E, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup4_i2c_apps_clk", 0x43, 4, GCC,
+			0x43, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_qup4_spi_apps_clk", 0x42, 4, GCC,
+			0x42, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_sleep_clk", 0x35, 4, GCC,
+			0x35, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_uart1_apps_clk", 0x38, 4, GCC,
+			0x38, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_uart2_apps_clk", 0x3C, 4, GCC,
+			0x3C, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_uart3_apps_clk", 0x40, 4, GCC,
+			0x40, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_blsp1_uart4_apps_clk", 0x44, 4, GCC,
+			0x44, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_boot_rom_ahb_clk", 0x4B, 4, GCC,
+			0x4B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_ce1_ahb_clk", 0x60, 4, GCC,
+			0x60, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_ce1_axi_clk", 0x5F, 4, GCC,
+			0x5F, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_ce1_clk", 0x5E, 4, GCC,
+			0x5E, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_cpuss_ahb_clk", 0x74, 4, GCC,
+			0x74, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_cpuss_gnoc_clk", 0x75, 4, GCC,
+			0x75, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_cpuss_rbcpr_clk", 0x76, 4, GCC,
+			0x76, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_eth_axi_clk", 0xCB, 4, GCC,
+			0xCB, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_eth_ptp_clk", 0xFD, 4, GCC,
+			0xFD, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_eth_rgmii_clk", 0xC9, 4, GCC,
+			0xC9, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_eth_slave_ahb_clk", 0xCA, 4, GCC,
+			0xCA, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_gp1_clk", 0x85, 4, GCC,
+			0x85, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_gp2_clk", 0x86, 4, GCC,
+			0x86, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_gp3_clk", 0x87, 4, GCC,
+			0x87, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_aux_clk", 0x99, 4, GCC,
+			0x99, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_cfg_ahb_clk", 0x98, 4, GCC,
+			0x98, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_mstr_axi_clk", 0x97, 4, GCC,
+			0x97, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_phy_refgen_clk", 0x104, 4, GCC,
+			0x104, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_pipe_clk", 0x9A, 4, GCC,
+			0x9A, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_sleep_clk", 0x9C, 4, GCC,
+			0x9C, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_slv_axi_clk", 0x96, 4, GCC,
+			0x96, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pcie_slv_q2a_axi_clk", 0x95, 4, GCC,
+			0x95, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pdm2_clk", 0x48, 4, GCC,
+			0x48, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pdm_ahb_clk", 0x46, 4, GCC,
+			0x46, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_pdm_xo4_clk", 0x47, 4, GCC,
+			0x47, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_prng_ahb_clk", 0x49, 4, GCC,
+			0x49, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_sdcc1_ahb_clk", 0x33, 4, GCC,
+			0x33, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_sdcc1_apps_clk", 0x32, 4, GCC,
+			0x32, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_spmi_fetcher_ahb_clk", 0xB5, 4, GCC,
+			0xB5, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_spmi_fetcher_clk", 0xB4, 4, GCC,
+			0xB4, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_sys_noc_cpuss_ahb_clk", 0x10B, 4, GCC,
+			0x10B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_sys_noc_usb3_clk", 0xB, 4, GCC,
+			0xB, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_usb30_master_clk", 0x28, 4, GCC,
+			0x28, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_usb30_mock_utmi_clk", 0x2A, 4, GCC,
+			0x2A, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_usb30_sleep_clk", 0x29, 4, GCC,
+			0x29, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_usb3_phy_aux_clk", 0x2B, 4, GCC,
+			0x2B, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_usb3_phy_pipe_clk", 0x2D, 4, GCC,
+			0x2D, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_usb_phy_cfg_ahb2phy_clk", 0x31, 4, GCC,
+			0x31, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "gcc_xo_div4_clk", 0x63, 4, GCC,
+			0x63, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+		{ "measure_only_ipa_2x_clk", 0xAC, 4, GCC,
+			0xAC, 0x3FF, 0, 0xF, 0, 4, 0x79000, 0x29000, 0x29004 },
+	),
+	.hw.init = &(struct clk_init_data){
+		.name = "gcc_debug_mux",
+		.ops = &clk_debug_mux_ops,
+		.parent_names = debug_mux_parent_names,
+		.num_parents = ARRAY_SIZE(debug_mux_parent_names),
+		.flags = CLK_IS_MEASURE,
+	},
+};
+
+static const struct of_device_id clk_debug_match_table[] = {
+	{ .compatible = "qcom,debugcc-sdxpoorwills" },
+	{ }
+};
+
+static int clk_debug_sdxpoorwills_probe(struct platform_device *pdev)
+{
+	struct clk *clk;
+	int ret = 0;
+
+	clk = devm_clk_get(&pdev->dev, "xo_clk_src");
+	if (IS_ERR(clk)) {
+		if (PTR_ERR(clk) != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "Unable to get xo clock\n");
+		return PTR_ERR(clk);
+	}
+
+	debug_mux_priv.cxo = clk;
+
+	gcc_debug_mux.regmap = devm_kcalloc(&pdev->dev, MAX_NUM_CC,
+				sizeof(*gcc_debug_mux.regmap), GFP_KERNEL);
+	if (!gcc_debug_mux.regmap)
+		return -ENOMEM;
+
+	if (!of_get_property(pdev->dev.of_node, "qcom,gcc", NULL))
+		return -ENODEV;
+
+	gcc_debug_mux.regmap[GCC] =
+		syscon_regmap_lookup_by_phandle(pdev->dev.of_node, "qcom,gcc");
+	if (IS_ERR(gcc_debug_mux.regmap[GCC])) {
+		pr_err("Failed to map qcom,gcc\n");
+		return PTR_ERR(gcc_debug_mux.regmap[GCC]);
+	}
+
+	clk = devm_clk_register(&pdev->dev, &gcc_debug_mux.hw);
+	if (IS_ERR(clk)) {
+		dev_err(&pdev->dev, "Unable to register GCC debug mux\n");
+		return PTR_ERR(clk);
+	}
+
+	ret = clk_debug_measure_register(&gcc_debug_mux.hw);
+	if (ret)
+		dev_err(&pdev->dev, "Could not register Measure clock\n");
+
+	return ret;
+}
+
+static struct platform_driver clk_debug_driver = {
+	.probe = clk_debug_sdxpoorwills_probe,
+	.driver = {
+		.name = "debugcc-sdxpoorwills",
+		.of_match_table = clk_debug_match_table,
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init clk_debug_sdxpoorwills_init(void)
+{
+	return platform_driver_register(&clk_debug_driver);
+}
+fs_initcall(clk_debug_sdxpoorwills_init);
+
+MODULE_DESCRIPTION("QTI DEBUG CC SDXPOORWILLS Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:debugcc-sdxpoorwills");
diff --git a/drivers/clk/qcom/gcc-sdxpoorwills.c b/drivers/clk/qcom/gcc-sdxpoorwills.c
index c6e8faa..2fb2e34 100644
--- a/drivers/clk/qcom/gcc-sdxpoorwills.c
+++ b/drivers/clk/qcom/gcc-sdxpoorwills.c
@@ -1711,6 +1711,19 @@
 	},
 };
 
+/* Measure-only clock for gcc_ipa_2x_clk. */
+static struct clk_dummy measure_only_ipa_2x_clk = {
+	.rrate = 1000,
+	.hw.init = &(struct clk_init_data){
+		.name = "measure_only_ipa_2x_clk",
+		.ops = &clk_dummy_ops,
+	},
+};
+
+static struct clk_hw *gcc_sdxpoorwills_hws[] = {
+	[MEASURE_ONLY_IPA_2X_CLK] = &measure_only_ipa_2x_clk.hw,
+};
+
 static struct clk_regmap *gcc_sdxpoorwills_clocks[] = {
 	[GCC_BLSP1_AHB_CLK] = &gcc_blsp1_ahb_clk.clkr,
 	[GCC_BLSP1_QUP1_I2C_APPS_CLK] = &gcc_blsp1_qup1_i2c_apps_clk.clkr,
@@ -1854,7 +1867,8 @@
 
 static int gcc_sdxpoorwills_probe(struct platform_device *pdev)
 {
-	int ret = 0;
+	int i, ret = 0;
+	struct clk *clk;
 	struct regmap *regmap;
 
 	regmap = qcom_cc_map(pdev, &gcc_sdxpoorwills_desc);
@@ -1869,6 +1883,13 @@
 		return PTR_ERR(vdd_cx.regulator[0]);
 	}
 
+	/* Register the dummy measurement clocks */
+	for (i = 0; i < ARRAY_SIZE(gcc_sdxpoorwills_hws); i++) {
+		clk = devm_clk_register(&pdev->dev, gcc_sdxpoorwills_hws[i]);
+		if (IS_ERR(clk))
+			return PTR_ERR(clk);
+	}
+
 	ret = qcom_cc_really_probe(pdev, &gcc_sdxpoorwills_desc, regmap);
 	if (ret) {
 		dev_err(&pdev->dev, "Failed to register GCC clocks\n");
diff --git a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
index 7290205..874c229 100644
--- a/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
+++ b/drivers/clk/qcom/mdss/mdss-dsi-pll-10nm.c
@@ -925,6 +925,11 @@
 	if (!vco->priv)
 		pr_err("vco priv is null\n");
 
+	if (!pll) {
+		pr_err("pll is null\n");
+		return 0;
+	}
+
 	/*
 	 * Calculate the vco rate from HW registers only for handoff cases.
 	 * For other cases where a vco_10nm_set_rate() has already been
diff --git a/drivers/clocksource/timer-stm32.c b/drivers/clocksource/timer-stm32.c
index 1b2574c..b167cc6 100644
--- a/drivers/clocksource/timer-stm32.c
+++ b/drivers/clocksource/timer-stm32.c
@@ -16,6 +16,7 @@
 #include <linux/of_irq.h>
 #include <linux/clk.h>
 #include <linux/reset.h>
+#include <linux/slab.h>
 
 #define TIM_CR1		0x00
 #define TIM_DIER	0x0c
@@ -106,6 +107,10 @@
 	unsigned long rate, max_delta;
 	int irq, ret, bits, prescaler = 1;
 
+	data = kmemdup(&clock_event_ddata, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
 	clk = of_clk_get(np, 0);
 	if (IS_ERR(clk)) {
 		ret = PTR_ERR(clk);
@@ -156,8 +161,8 @@
 
 	writel_relaxed(prescaler - 1, data->base + TIM_PSC);
 	writel_relaxed(TIM_EGR_UG, data->base + TIM_EGR);
-	writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
 	writel_relaxed(0, data->base + TIM_SR);
+	writel_relaxed(TIM_DIER_UIE, data->base + TIM_DIER);
 
 	data->periodic_top = DIV_ROUND_CLOSEST(rate, prescaler * HZ);
 
@@ -184,6 +189,7 @@
 err_clk_enable:
 	clk_put(clk);
 err_clk_get:
+	kfree(data);
 	return ret;
 }
 
diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c
index 4615122..786ba01 100644
--- a/drivers/cpuidle/lpm-levels.c
+++ b/drivers/cpuidle/lpm-levels.c
@@ -1371,11 +1371,6 @@
 	const struct cpumask *cpumask = get_cpu_mask(dev->cpu);
 	ktime_t start = ktime_get();
 	uint64_t start_time = ktime_to_ns(start), end_time;
-	struct power_params *pwr_params;
-
-	pwr_params = &cpu->levels[idx].pwr;
-	sched_set_cpu_cstate(dev->cpu, idx + 1,
-			pwr_params->energy_overhead, pwr_params->latency_us);
 
 	cpu_prepare(cpu, idx, true);
 	cluster_prepare(cpu->parent, cpumask, idx, true, start_time);
@@ -1394,7 +1389,6 @@
 
 	cluster_unprepare(cpu->parent, cpumask, idx, true, end_time);
 	cpu_unprepare(cpu, idx, true);
-	sched_set_cpu_cstate(smp_processor_id(), 0, 0, 0);
 	dev->last_residency = ktime_us_delta(ktime_get(), start);
 	update_history(dev, idx);
 	trace_cpu_idle_exit(idx, success);
@@ -1748,7 +1742,7 @@
 	int cpu;
 
 	for_each_possible_cpu(cpu) {
-		rc = arm_cpuidle_init(smp_processor_id());
+		rc = arm_cpuidle_init(cpu);
 		if (rc) {
 			pr_err("CPU%d ARM CPUidle init failed (%d)\n", cpu, rc);
 			return rc;
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 98468b9..2ca101a 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -228,12 +228,16 @@
 		 * without any error (HW optimizations for later
 		 * CAAM eras), then try again.
 		 */
-		rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
-		if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
-		    !(rdsta_val & (1 << sh_idx)))
-			ret = -EAGAIN;
 		if (ret)
 			break;
+
+		rdsta_val = rd_reg32(&ctrl->r4tst[0].rdsta) & RDSTA_IFMASK;
+		if ((status && status != JRSTA_SSRC_JUMP_HALT_CC) ||
+		    !(rdsta_val & (1 << sh_idx))) {
+			ret = -EAGAIN;
+			break;
+		}
+
 		dev_info(ctrldev, "Instantiated RNG4 SH%d\n", sh_idx);
 		/* Clear the contents before recreating the descriptor */
 		memset(desc, 0x00, CAAM_CMD_SZ * 7);
diff --git a/drivers/devfreq/devfreq_spdm_debugfs.c b/drivers/devfreq/devfreq_spdm_debugfs.c
index 4e49d5b..d39ff73 100644
--- a/drivers/devfreq/devfreq_spdm_debugfs.c
+++ b/drivers/devfreq/devfreq_spdm_debugfs.c
@@ -34,7 +34,7 @@
 	int i;
 	int next_idx;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
@@ -42,6 +42,8 @@
 		size = -EINVAL;
 	}
 
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u\n", &i) != 1) {
 		size = -EINVAL;
 		goto err;
@@ -105,7 +107,7 @@
 	int ext_status = 0;
 	int i;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
@@ -113,6 +115,8 @@
 		goto out;
 	}
 
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n", &spdm_data->config_data.pl_freqs[0],
 	       &spdm_data->config_data.pl_freqs[1]) != 2) {
 		size = -EINVAL;
@@ -164,7 +168,7 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
@@ -172,6 +176,8 @@
 		goto out;
 	}
 
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n", &spdm_data->config_data.reject_rate[0],
 	       &spdm_data->config_data.reject_rate[1]) != 2) {
 		size = -EINVAL;
@@ -224,13 +230,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n", &spdm_data->config_data.reject_rate[2],
 	       &spdm_data->config_data.reject_rate[3]) != 2) {
 		size = -EINVAL;
@@ -282,13 +291,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n", &spdm_data->config_data.reject_rate[4],
 	       &spdm_data->config_data.reject_rate[5]) != 2) {
 		size = -EINVAL;
@@ -340,13 +352,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n", &spdm_data->config_data.response_time_us[0],
 	       &spdm_data->config_data.response_time_us[1]) != 2) {
 		size = -EINVAL;
@@ -398,13 +413,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n", &spdm_data->config_data.response_time_us[2],
 	       &spdm_data->config_data.response_time_us[3]) != 2) {
 		size = -EINVAL;
@@ -456,13 +474,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n", &spdm_data->config_data.response_time_us[4],
 	       &spdm_data->config_data.response_time_us[5]) != 2) {
 		size = -EINVAL;
@@ -515,13 +536,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n",
 		   &spdm_data->config_data.cci_response_time_us[0],
 		   &spdm_data->config_data.cci_response_time_us[1]) != 2) {
@@ -575,13 +599,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n",
 		   &spdm_data->config_data.cci_response_time_us[2],
 		   &spdm_data->config_data.cci_response_time_us[3]) != 2) {
@@ -635,13 +662,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u\n",
 		   &spdm_data->config_data.cci_response_time_us[4],
 		   &spdm_data->config_data.cci_response_time_us[5]) != 2){
@@ -694,13 +724,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u\n", &spdm_data->config_data.max_cci_freq) != 1) {
 		size = -EINVAL;
 		goto out;
@@ -748,13 +781,16 @@
 	struct spdm_args desc = { { 0 } };
 	int ext_status = 0;
 
-	if (size > sizeof(buf))
+	if (size > sizeof(buf) - 1)
 		return -EINVAL;
 
 	if (copy_from_user(buf, data, size)) {
 		size = -EINVAL;
 		goto out;
 	}
+
+	buf[size] = '\0';
+
 	if (sscanf(buf, "%u %u %u %u\n", &spdm_data->config_data.upstep,
 	       &spdm_data->config_data.downstep,
 	       &spdm_data->config_data.max_vote,
diff --git a/drivers/devfreq/governor_bw_hwmon.c b/drivers/devfreq/governor_bw_hwmon.c
index 3026bc2..cb04014 100644
--- a/drivers/devfreq/governor_bw_hwmon.c
+++ b/drivers/devfreq/governor_bw_hwmon.c
@@ -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
@@ -171,7 +171,7 @@
 #define MAX_MS	500U
 
 /* Returns MBps of read/writes for the sampling window. */
-static unsigned int bytes_to_mbps(long long bytes, unsigned int us)
+static unsigned long bytes_to_mbps(unsigned long long bytes, unsigned int us)
 {
 	bytes *= USEC_PER_SEC;
 	do_div(bytes, us);
diff --git a/drivers/dma/dmatest.c b/drivers/dma/dmatest.c
index e0bd578..ebe72a4 100644
--- a/drivers/dma/dmatest.c
+++ b/drivers/dma/dmatest.c
@@ -339,7 +339,7 @@
 {
 	struct dmatest_done *done = arg;
 	struct dmatest_thread *thread =
-		container_of(arg, struct dmatest_thread, done_wait);
+		container_of(done, struct dmatest_thread, test_done);
 	if (!thread->done) {
 		done->done = true;
 		wake_up_all(done->wait);
diff --git a/drivers/edac/octeon_edac-lmc.c b/drivers/edac/octeon_edac-lmc.c
index cda6dab..6b65a10 100644
--- a/drivers/edac/octeon_edac-lmc.c
+++ b/drivers/edac/octeon_edac-lmc.c
@@ -79,6 +79,7 @@
 	if (!pvt->inject)
 		int_reg.u64 = cvmx_read_csr(CVMX_LMCX_INT(mci->mc_idx));
 	else {
+		int_reg.u64 = 0;
 		if (pvt->error_type == 1)
 			int_reg.s.sec_err = 1;
 		if (pvt->error_type == 2)
diff --git a/drivers/extcon/extcon-qcom-spmi-misc.c b/drivers/extcon/extcon-qcom-spmi-misc.c
index b8cde09..41245d8 100644
--- a/drivers/extcon/extcon-qcom-spmi-misc.c
+++ b/drivers/extcon/extcon-qcom-spmi-misc.c
@@ -1,6 +1,6 @@
 /**
  * extcon-qcom-spmi-misc.c - Qualcomm USB extcon driver to support USB ID
- *				detection based on extcon-usb-gpio.c.
+ *			and VBUS detection based on extcon-usb-gpio.c.
  *
  * Copyright (C) 2016 Linaro, Ltd.
  * Stephen Boyd <stephen.boyd@linaro.org>
@@ -28,30 +28,56 @@
 
 struct qcom_usb_extcon_info {
 	struct extcon_dev *edev;
-	int irq;
+	int id_irq;
+	int vbus_irq;
 	struct delayed_work wq_detcable;
 	unsigned long debounce_jiffies;
 };
 
 static const unsigned int qcom_usb_extcon_cable[] = {
+	EXTCON_USB,
 	EXTCON_USB_HOST,
 	EXTCON_NONE,
 };
 
 static void qcom_usb_extcon_detect_cable(struct work_struct *work)
 {
-	bool id;
+	bool state = 0;
 	int ret;
+	union extcon_property_value val;
 	struct qcom_usb_extcon_info *info = container_of(to_delayed_work(work),
 						    struct qcom_usb_extcon_info,
 						    wq_detcable);
 
-	/* check ID and update cable state */
-	ret = irq_get_irqchip_state(info->irq, IRQCHIP_STATE_LINE_LEVEL, &id);
-	if (ret)
-		return;
+	if (info->id_irq > 0) {
+		/* check ID and update cable state */
+		ret = irq_get_irqchip_state(info->id_irq,
+				IRQCHIP_STATE_LINE_LEVEL, &state);
+		if (ret)
+			return;
 
-	extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !id);
+		if (!state) {
+			val.intval = true;
+			extcon_set_property(info->edev, EXTCON_USB_HOST,
+						EXTCON_PROP_USB_SS, val);
+		}
+		extcon_set_state_sync(info->edev, EXTCON_USB_HOST, !state);
+	}
+
+	if (info->vbus_irq > 0) {
+		/* check VBUS and update cable state */
+		ret = irq_get_irqchip_state(info->vbus_irq,
+				IRQCHIP_STATE_LINE_LEVEL, &state);
+		if (ret)
+			return;
+
+		if (state) {
+			val.intval = true;
+			extcon_set_property(info->edev, EXTCON_USB,
+						EXTCON_PROP_USB_SS, val);
+		}
+		extcon_set_cable_state_(info->edev, EXTCON_USB, state);
+	}
 }
 
 static irqreturn_t qcom_usb_irq_handler(int irq, void *dev_id)
@@ -86,21 +112,48 @@
 		return ret;
 	}
 
+	ret = extcon_set_property_capability(info->edev,
+			EXTCON_USB, EXTCON_PROP_USB_SS);
+	ret |= extcon_set_property_capability(info->edev,
+			EXTCON_USB_HOST, EXTCON_PROP_USB_SS);
+	if (ret) {
+		dev_err(dev, "failed to register extcon props rc=%d\n",
+						ret);
+		return ret;
+	}
+
 	info->debounce_jiffies = msecs_to_jiffies(USB_ID_DEBOUNCE_MS);
 	INIT_DELAYED_WORK(&info->wq_detcable, qcom_usb_extcon_detect_cable);
 
-	info->irq = platform_get_irq_byname(pdev, "usb_id");
-	if (info->irq < 0)
-		return info->irq;
-
-	ret = devm_request_threaded_irq(dev, info->irq, NULL,
+	info->id_irq = platform_get_irq_byname(pdev, "usb_id");
+	if (info->id_irq > 0) {
+		ret = devm_request_threaded_irq(dev, info->id_irq, NULL,
 					qcom_usb_irq_handler,
 					IRQF_TRIGGER_RISING |
 					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
 					pdev->name, info);
-	if (ret < 0) {
-		dev_err(dev, "failed to request handler for ID IRQ\n");
-		return ret;
+		if (ret < 0) {
+			dev_err(dev, "failed to request handler for ID IRQ\n");
+			return ret;
+		}
+	}
+
+	info->vbus_irq = platform_get_irq_byname(pdev, "usb_vbus");
+	if (info->vbus_irq > 0) {
+		ret = devm_request_threaded_irq(dev, info->vbus_irq, NULL,
+					qcom_usb_irq_handler,
+					IRQF_TRIGGER_RISING |
+					IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
+					pdev->name, info);
+		if (ret < 0) {
+			dev_err(dev, "failed to request handler for VBUS IRQ\n");
+			return ret;
+		}
+	}
+
+	if (info->id_irq < 0 && info->vbus_irq < 0) {
+		dev_err(dev, "ID and VBUS IRQ not found\n");
+		return -EINVAL;
 	}
 
 	platform_set_drvdata(pdev, info);
@@ -127,8 +180,12 @@
 	struct qcom_usb_extcon_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (device_may_wakeup(dev))
-		ret = enable_irq_wake(info->irq);
+	if (device_may_wakeup(dev)) {
+		if (info->id_irq > 0)
+			ret = enable_irq_wake(info->id_irq);
+		if (info->vbus_irq > 0)
+			ret = enable_irq_wake(info->vbus_irq);
+	}
 
 	return ret;
 }
@@ -138,8 +195,12 @@
 	struct qcom_usb_extcon_info *info = dev_get_drvdata(dev);
 	int ret = 0;
 
-	if (device_may_wakeup(dev))
-		ret = disable_irq_wake(info->irq);
+	if (device_may_wakeup(dev)) {
+		if (info->id_irq > 0)
+			ret = disable_irq_wake(info->id_irq);
+		if (info->vbus_irq > 0)
+			ret = disable_irq_wake(info->vbus_irq);
+	}
 
 	return ret;
 }
@@ -150,6 +211,7 @@
 
 static const struct of_device_id qcom_usb_extcon_dt_match[] = {
 	{ .compatible = "qcom,pm8941-misc", },
+	{ .compatible = "qcom,pmd-vbus-det", },
 	{ }
 };
 MODULE_DEVICE_TABLE(of, qcom_usb_extcon_dt_match);
diff --git a/drivers/gpu/drm/bridge/lt9611.c b/drivers/gpu/drm/bridge/lt9611.c
index 4327e93..887dd6f 100644
--- a/drivers/gpu/drm/bridge/lt9611.c
+++ b/drivers/gpu/drm/bridge/lt9611.c
@@ -708,15 +708,24 @@
 	u32 h_act = 0;
 	struct lt9611_reg_cfg reg_cfg[] = {
 		{0xff, 0x83, 0},
+		{0x0b, 0x01, 0},
+		{0x0c, 0x10, 0},
+		{0x48, 0x00, 0},
+		{0x49, 0x81, 0},
 
-		{0x2d, 0x38, 0}, /* up_lmt */
-		{0x2e, 0x00, 0},
-		{0x31, 0x10, 0}, /* low lmt */
-		{0x32, 0x00, 0},
+		/* stage 1 */
+		{0x21, 0x4a, 0},
+		{0x24, 0x71, 0},
+		{0x25, 0x30, 0},
+		{0x2a, 0x01, 0},
 
-		{0xff, 0x80, 0},
-		{0x11, 0x5a, 0}, /* pcr reset */
-		{0x11, 0xfa, 0},
+		/* stage 2 */
+		{0x4a, 0x40, 0},
+		{0x1d, 0x10, 0},
+
+		/* MK limit */
+		{0x2d, 0x38, 0},
+		{0x31, 0x08, 0},
 	};
 
 	if (!pdata || !cfg) {
@@ -724,54 +733,31 @@
 		return -EINVAL;
 	}
 
+	lt9611_write_array(pdata, reg_cfg, sizeof(reg_cfg));
+
 	h_act = cfg->h_active;
 
 	if (h_act == 1920) {
-		lt9611_write(pdata, 0xff, 0x83);
-		lt9611_write(pdata, 0x48, 0x00);
-		lt9611_write(pdata, 0x49, 0x81);
-
-		lt9611_write(pdata, 0x4a, 0x10);
-		lt9611_write(pdata, 0x1d, 0x10);
-		lt9611_write(pdata, 0x21, 0x41);
-		lt9611_write(pdata, 0x22, 0x40);
-		lt9611_write(pdata, 0x24, 0x11);
-		lt9611_write(pdata, 0x25, 0x30);
 		lt9611_write(pdata, 0x26, 0x37);
-		lt9611_write(pdata, 0x2a, 0x02);
 	} else if (h_act == 3840) {
-		lt9611_write(pdata, 0xff, 0x83);
 		lt9611_write(pdata, 0x0b, 0x03);
 		lt9611_write(pdata, 0x0c, 0xd0);
 		lt9611_write(pdata, 0x48, 0x03);
-		lt9611_write(pdata, 0x49, 0xd0);
-
-		lt9611_write(pdata, 0x4a, 0x01);
-		lt9611_write(pdata, 0x1d, 0x10);
-		lt9611_write(pdata, 0x21, 0x41);
-		lt9611_write(pdata, 0x22, 0x40);
-		lt9611_write(pdata, 0x24, 0x70);
-		lt9611_write(pdata, 0x25, 0x50);
-		lt9611_write(pdata, 0x26, 0x37);
-		lt9611_write(pdata, 0x2a, 0x03);
-	} else if (h_act == 640) {
-		lt9611_write(pdata, 0xff, 0x83);
-		lt9611_write(pdata, 0x0b, 0x01);
-		lt9611_write(pdata, 0x0c, 0x20);
-		lt9611_write(pdata, 0x48, 0x00);
-		lt9611_write(pdata, 0x49, 0x81);
-
+		lt9611_write(pdata, 0x49, 0xe0);
+		lt9611_write(pdata, 0x24, 0x72);
+		lt9611_write(pdata, 0x25, 0x00);
+		lt9611_write(pdata, 0x2a, 0x01);
 		lt9611_write(pdata, 0x4a, 0x10);
 		lt9611_write(pdata, 0x1d, 0x10);
-		lt9611_write(pdata, 0x21, 0x41);
-		lt9611_write(pdata, 0x22, 0x40);
-		lt9611_write(pdata, 0x24, 0x11);
-		lt9611_write(pdata, 0x25, 0x30);
-		lt9611_write(pdata, 0x26, 0x13);
-		lt9611_write(pdata, 0x2a, 0x03);
+		lt9611_write(pdata, 0x26, 0x37);
+	} else if (h_act == 640) {
+		lt9611_write(pdata, 0x26, 0x14);
 	}
 
-	lt9611_write_array(pdata, reg_cfg, sizeof(reg_cfg));
+	/* pcr rst */
+	lt9611_write(pdata, 0xff, 0x80);
+	lt9611_write(pdata, 0x11, 0x5a);
+	lt9611_write(pdata, 0x11, 0xfa);
 
 	return 0;
 }
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 7fdc42e..74163a9 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -5063,6 +5063,12 @@
 	 */
 	final->t8 = 1;
 	final->t9 = 1;
+
+	/*
+	 * HW has only a 100msec granularity for t11_t12 so round it up
+	 * accordingly.
+	 */
+	final->t11_t12 = roundup(final->t11_t12, 100 * 10);
 }
 
 static void
diff --git a/drivers/gpu/drm/msm/dp/dp_display.c b/drivers/gpu/drm/msm/dp/dp_display.c
index 731a554..bf903b9 100644
--- a/drivers/gpu/drm/msm/dp/dp_display.c
+++ b/drivers/gpu/drm/msm/dp/dp_display.c
@@ -816,7 +816,7 @@
 	struct dp_display_private *dp = container_of(dw,
 			struct dp_display_private, connect_work);
 
-	if (dp->dp_display.is_connected) {
+	if (dp->dp_display.is_connected && dp_display_framework_ready(dp)) {
 		pr_debug("HPD already on\n");
 		return;
 	}
@@ -1085,6 +1085,11 @@
 
 	dp->aux->init(dp->aux, dp->parser->aux_cfg);
 
+	if (dp->debug->psm_enabled) {
+		dp->link->psm_config(dp->link, &dp->panel->link_info, false);
+		dp->debug->psm_enabled = false;
+	}
+
 	rc = dp->ctrl->on(dp->ctrl);
 
 	if (dp->debug->tpg_state)
@@ -1227,10 +1232,9 @@
 	 * any notification from driver. Initialize post_open callback to notify
 	 * DP connection once framework restarts.
 	 */
-	if (dp->usbpd->hpd_high && dp->usbpd->alt_mode_cfg_done) {
+	if (dp->usbpd->hpd_high && dp->usbpd->alt_mode_cfg_done)
 		dp_display->post_open = dp_display_post_open;
-		dp->dp_display.is_connected = false;
-	}
+
 	dp->power_on = false;
 	dp->aux->state = DP_STATE_CTRL_POWERED_OFF;
 end:
diff --git a/drivers/gpu/drm/msm/dp/dp_drm.c b/drivers/gpu/drm/msm/dp/dp_drm.c
index b834230..7c817d3 100644
--- a/drivers/gpu/drm/msm/dp/dp_drm.c
+++ b/drivers/gpu/drm/msm/dp/dp_drm.c
@@ -184,7 +184,12 @@
 	bridge = to_dp_bridge(drm_bridge);
 	dp = bridge->display;
 
-	if (dp && dp->connector)
+	if (!dp) {
+		pr_err("dp is null\n");
+		return;
+	}
+
+	if (dp->connector)
 		sde_connector_helper_bridge_disable(dp->connector);
 
 	rc = dp->pre_disable(dp);
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
index e2e0148..1682e61 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.c
@@ -17,6 +17,7 @@
 #include <linux/list.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
+#include <linux/of_gpio.h>
 #include <linux/err.h>
 
 #include "msm_drv.h"
@@ -36,6 +37,7 @@
 #define NO_OVERRIDE -1
 
 #define MISR_BUFF_SIZE	256
+#define ESD_MODE_STRING_MAX_LEN 256
 
 #define MAX_NAME_SIZE	64
 
@@ -309,6 +311,89 @@
 	dsi_panel_release_panel_lock(display->panel);
 }
 
+static irqreturn_t dsi_display_panel_te_irq_handler(int irq, void *data)
+{
+	struct dsi_display *display = (struct dsi_display *)data;
+
+	/*
+	 * This irq handler is used for sole purpose of identifying
+	 * ESD attacks on panel and we can safely assume IRQ_HANDLED
+	 * in case of display not being initalized yet
+	 */
+	if (!display)
+		return IRQ_HANDLED;
+
+	complete_all(&display->esd_te_gate);
+	return IRQ_HANDLED;
+}
+
+static void dsi_display_change_te_irq_status(struct dsi_display *display,
+					bool enable)
+{
+	if (!display) {
+		pr_err("Invalid params\n");
+		return;
+	}
+
+	/* Handle unbalanced irq enable/disbale calls */
+	if (enable && !display->is_te_irq_enabled) {
+		enable_irq(gpio_to_irq(display->disp_te_gpio));
+		display->is_te_irq_enabled = true;
+	} else if (!enable && display->is_te_irq_enabled) {
+		disable_irq(gpio_to_irq(display->disp_te_gpio));
+		display->is_te_irq_enabled = false;
+	}
+}
+
+static void dsi_display_register_te_irq(struct dsi_display *display)
+{
+	int rc;
+	struct platform_device *pdev;
+	struct device *dev;
+
+	pdev = display->pdev;
+	if (!pdev) {
+		pr_err("invalid platform device\n");
+		return;
+	}
+
+	dev = &pdev->dev;
+	if (!dev) {
+		pr_err("invalid device\n");
+		return;
+	}
+
+	rc = devm_request_irq(dev, gpio_to_irq(display->disp_te_gpio),
+			dsi_display_panel_te_irq_handler, IRQF_TRIGGER_FALLING,
+			"TE_GPIO", display);
+	if (rc) {
+		pr_err("TE request_irq failed for ESD rc:%d\n", rc);
+		return;
+	}
+
+	init_completion(&display->esd_te_gate);
+
+	disable_irq(gpio_to_irq(display->disp_te_gpio));
+	display->is_te_irq_enabled = false;
+}
+
+static bool dsi_display_is_te_based_esd(struct dsi_display *display)
+{
+	u32 status_mode = 0;
+
+	if (!display->panel) {
+		pr_err("Invalid panel data\n");
+		return false;
+	}
+
+	status_mode = display->panel->esd_config.status_mode;
+
+	if (status_mode == ESD_MODE_PANEL_TE &&
+			gpio_is_valid(display->disp_te_gpio))
+		return true;
+	return false;
+}
+
 /* Allocate memory for cmd dma tx buffer */
 static int dsi_host_alloc_cmd_tx_buffer(struct dsi_display *display)
 {
@@ -421,6 +506,27 @@
 	return false;
 }
 
+static void dsi_display_parse_te_gpio(struct dsi_display *display)
+{
+	struct platform_device *pdev;
+	struct device *dev;
+
+	pdev = display->pdev;
+	if (!pdev) {
+		pr_err("Inavlid platform device\n");
+		return;
+	}
+
+	dev = &pdev->dev;
+	if (!dev) {
+		pr_err("Inavlid platform device\n");
+		return;
+	}
+
+	display->disp_te_gpio = of_get_named_gpio(dev->of_node,
+					"qcom,platform-te-gpio", 0);
+}
+
 static int dsi_display_read_status(struct dsi_display_ctrl *ctrl,
 		struct dsi_panel *panel)
 {
@@ -566,10 +672,19 @@
 
 static int dsi_display_status_check_te(struct dsi_display *display)
 {
-	int rc = 0;
+	int rc = 1;
+	int const esd_te_timeout = msecs_to_jiffies(3*20);
 
-	pr_debug(" ++\n");
-	/* TODO: wait for TE interrupt from panel */
+	dsi_display_change_te_irq_status(display, true);
+
+	reinit_completion(&display->esd_te_gate);
+	if (!wait_for_completion_timeout(&display->esd_te_gate,
+				esd_te_timeout)) {
+		pr_err("ESD check failed\n");
+		rc = -EINVAL;
+	}
+
+	dsi_display_change_te_irq_status(display, false);
 
 	return rc;
 }
@@ -917,62 +1032,6 @@
 	return rc;
 }
 
-static ssize_t debugfs_esd_trigger_check(struct file *file,
-				  const char __user *user_buf,
-				  size_t user_len,
-				  loff_t *ppos)
-{
-	struct dsi_display *display = file->private_data;
-	char *buf;
-	int rc = 0;
-	u32 esd_trigger;
-
-	if (!display)
-		return -ENODEV;
-
-	if (*ppos)
-		return 0;
-
-	if (user_len > sizeof(u32))
-		return -EINVAL;
-
-	buf = kzalloc(user_len, GFP_KERNEL);
-	if (!buf)
-		return -ENOMEM;
-
-	if (copy_from_user(buf, user_buf, user_len)) {
-		rc = -EINVAL;
-		goto error;
-	}
-
-	buf[user_len] = '\0'; /* terminate the string */
-
-	if (kstrtouint(buf, 10, &esd_trigger)) {
-		rc = -EINVAL;
-		goto error;
-	}
-
-	if (esd_trigger != 1) {
-		rc = -EINVAL;
-		goto error;
-	}
-
-	display->esd_trigger = esd_trigger;
-
-	if (display->esd_trigger) {
-		rc = dsi_panel_trigger_esd_attack(display->panel);
-		if (rc) {
-			pr_err("Failed to trigger ESD attack\n");
-			return rc;
-		}
-	}
-
-	rc = user_len;
-error:
-	kfree(buf);
-	return rc;
-}
-
 static ssize_t debugfs_misr_read(struct file *file,
 				 char __user *user_buf,
 				 size_t user_len,
@@ -1038,6 +1097,191 @@
 	return len;
 }
 
+static ssize_t debugfs_esd_trigger_check(struct file *file,
+				  const char __user *user_buf,
+				  size_t user_len,
+				  loff_t *ppos)
+{
+	struct dsi_display *display = file->private_data;
+	char *buf;
+	int rc = 0;
+	u32 esd_trigger;
+
+	if (!display)
+		return -ENODEV;
+
+	if (*ppos)
+		return 0;
+
+	if (user_len > sizeof(u32))
+		return -EINVAL;
+
+	buf = kzalloc(user_len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, user_buf, user_len)) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	buf[user_len] = '\0'; /* terminate the string */
+
+	if (kstrtouint(buf, 10, &esd_trigger)) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (esd_trigger != 1) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	display->esd_trigger = esd_trigger;
+
+	if (display->esd_trigger) {
+		rc = dsi_panel_trigger_esd_attack(display->panel);
+		if (rc) {
+			pr_err("Failed to trigger ESD attack\n");
+			return rc;
+		}
+	}
+
+	rc = user_len;
+error:
+	kfree(buf);
+	return rc;
+}
+
+static ssize_t debugfs_alter_esd_check_mode(struct file *file,
+				  const char __user *user_buf,
+				  size_t user_len,
+				  loff_t *ppos)
+{
+	struct dsi_display *display = file->private_data;
+	struct drm_panel_esd_config *esd_config;
+	char *buf;
+	int rc = 0;
+	size_t len = min_t(size_t, user_len, ESD_MODE_STRING_MAX_LEN);
+
+	if (!display)
+		return -ENODEV;
+
+	if (*ppos)
+		return 0;
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	if (copy_from_user(buf, user_buf, user_len)) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	buf[len] = '\0'; /* terminate the string */
+	if (!display->panel) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	esd_config = &display->panel->esd_config;
+	if (!esd_config) {
+		pr_err("Invalid panel esd config\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (!esd_config->esd_enabled)
+		goto error;
+
+	if (!strcmp(buf, "te_signal_check\n")) {
+		esd_config->status_mode = ESD_MODE_PANEL_TE;
+		dsi_display_change_te_irq_status(display, true);
+	}
+
+	if (!strcmp(buf, "reg_read\n")) {
+		rc = dsi_panel_parse_esd_reg_read_configs(display->panel,
+						display->panel_of);
+		if (rc) {
+			pr_err("failed to alter esd check mode,rc=%d\n",
+						rc);
+			rc = user_len;
+			goto error;
+		}
+		esd_config->status_mode = ESD_MODE_REG_READ;
+		if (dsi_display_is_te_based_esd(display))
+			dsi_display_change_te_irq_status(display, false);
+	}
+
+	rc = len;
+error:
+	kfree(buf);
+	return rc;
+}
+
+static ssize_t debugfs_read_esd_check_mode(struct file *file,
+				 char __user *user_buf,
+				 size_t user_len,
+				 loff_t *ppos)
+{
+	struct dsi_display *display = file->private_data;
+	struct drm_panel_esd_config *esd_config;
+	char *buf;
+	int rc = 0;
+	size_t len = min_t(size_t, user_len, ESD_MODE_STRING_MAX_LEN);
+
+	if (!display)
+		return -ENODEV;
+
+	if (*ppos)
+		return 0;
+
+	if (!display->panel) {
+		pr_err("invalid panel data\n");
+		return -EINVAL;
+	}
+
+	buf = kzalloc(len, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	esd_config = &display->panel->esd_config;
+	if (!esd_config) {
+		pr_err("Invalid panel esd config\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (!esd_config->esd_enabled) {
+		rc = snprintf(buf, len, "ESD feature not enabled");
+		goto output_mode;
+	}
+
+	if (esd_config->status_mode == ESD_MODE_REG_READ)
+		rc = snprintf(buf, len, "reg_read");
+
+	if (esd_config->status_mode == ESD_MODE_PANEL_TE)
+		rc = snprintf(buf, len, "te_signal_check");
+
+output_mode:
+	if (!rc) {
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (copy_to_user(user_buf, buf, len)) {
+		rc = -EFAULT;
+		goto error;
+	}
+
+	*ppos += len;
+
+error:
+	kfree(buf);
+	return len;
+}
+
 static const struct file_operations dump_info_fops = {
 	.open = simple_open,
 	.read = debugfs_dump_info_read,
@@ -1054,6 +1298,12 @@
 	.write = debugfs_esd_trigger_check,
 };
 
+static const struct file_operations esd_check_mode_fops = {
+	.open = simple_open,
+	.write = debugfs_alter_esd_check_mode,
+	.read = debugfs_read_esd_check_mode,
+};
+
 static int dsi_display_debugfs_init(struct dsi_display *display)
 {
 	int rc = 0;
@@ -1093,6 +1343,18 @@
 		goto error_remove_dir;
 	}
 
+	dump_file = debugfs_create_file("esd_check_mode",
+					0644,
+					dir,
+					display,
+					&esd_check_mode_fops);
+	if (IS_ERR_OR_NULL(dump_file)) {
+		rc = PTR_ERR(dump_file);
+		pr_err("[%s] debugfs for esd check mode failed, rc=%d\n",
+		       display->name, rc);
+		goto error_remove_dir;
+	}
+
 	misr_data = debugfs_create_file("misr_data",
 					0600,
 					dir,
@@ -3094,6 +3356,9 @@
 		display->type = DSI_DISPLAY_SINGLE;
 	}
 
+	/* Parse TE gpio */
+	dsi_display_parse_te_gpio(display);
+
 error:
 	return rc;
 }
@@ -3950,6 +4215,9 @@
 		}
 	}
 
+	/* register te irq handler */
+	dsi_display_register_te_irq(display);
+
 	/* Initialize resources for continuous splash */
 	rc = dsi_display_splash_res_init(display);
 	if (rc)
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
index 53004e4..bb6c8c6 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_display.h
@@ -132,6 +132,9 @@
  * @is_active:        Is display active.
  * @is_cont_splash_enabled:  Is continuous splash enabled
  * @display_lock:     Mutex for dsi_display interface.
+ * @disp_te_gpio:     GPIO for panel TE interrupt.
+ * @is_te_irq_enabled:bool to specify whether TE interrupt is enabled.
+ * @esd_te_gate:      completion gate to signal TE interrupt.
  * @ctrl_count:       Number of DSI interfaces required by panel.
  * @ctrl:             Controller information for DSI display.
  * @panel:            Handle to DSI panel.
@@ -173,6 +176,9 @@
 	bool is_active;
 	bool is_cont_splash_enabled;
 	struct mutex display_lock;
+	int disp_te_gpio;
+	bool is_te_irq_enabled;
+	struct completion esd_te_gate;
 
 	u32 ctrl_count;
 	struct dsi_display_ctrl ctrl[MAX_DSI_CTRLS_PER_DISPLAY];
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
index d8b90e3..31d6fd1 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.c
@@ -18,6 +18,7 @@
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
 #include <video/mipi_display.h>
+#include <linux/firmware.h>
 
 #include "dsi_panel.h"
 #include "dsi_ctrl_hw.h"
@@ -710,12 +711,58 @@
 error:
 	return rc;
 }
-static int dsi_panel_parse_timing(struct dsi_mode_info *mode,
-				  struct device_node *of_node)
+
+static int dsi_panel_fw_parse(const struct firmware *fw_entry,
+		char *id_match, u32 *param_value)
 {
-	int rc = 0;
+	int value, numlen = 1, index = 0;
+	char id[SZ_256];
+
+	while (sscanf(fw_entry->data + index,
+			"%255s %d", id, &value) > 0) {
+		if (!strcmp(id, id_match)) {
+			*param_value = value;
+			return 0;
+		}
+
+		while ((value / 10) > 0) {
+			value /= 10;
+			numlen++;
+		}
+
+		index += (strlen(id) + numlen + 1);
+		numlen = 1;
+	}
+
+	return -EINVAL;
+}
+
+static int dsi_panel_parse(struct device_node *of_node,
+	const struct firmware *fw_entry, char *id_match, u32 *val)
+{
+	if (fw_entry && fw_entry->data)
+		return dsi_panel_fw_parse(fw_entry, id_match, val);
+	else
+		return of_property_read_u32(of_node, id_match, val);
+
+	return 0;
+}
+
+static int dsi_panel_parse_timing(struct device *parent,
+	struct dsi_mode_info *mode, const char *name,
+	struct device_node *of_node)
+{
+	int fw = 0, rc = 0;
 	u64 tmp64;
 	struct dsi_display_mode *display_mode;
+	const struct firmware *fw_entry = NULL;
+	char *fw_name = "dsi_prop";
+
+	if (strcmp(name, "Simulator video mode dsi panel") == 0)
+		fw = request_firmware(&fw_entry, fw_name, parent);
+
+	if (fw)
+		fw_entry = NULL;
 
 	display_mode = container_of(mode, struct dsi_display_mode, timing);
 
@@ -730,47 +777,47 @@
 	mode->clk_rate_hz = !rc ? tmp64 : 0;
 	display_mode->priv_info->clk_rate_hz = mode->clk_rate_hz;
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-framerate",
-				  &mode->refresh_rate);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-panel-framerate", &mode->refresh_rate);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-panel-framerate, rc=%d\n",
 		       rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-width",
-				  &mode->h_active);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-panel-width", &mode->h_active);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-panel-width, rc=%d\n", rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-front-porch",
-				  &mode->h_front_porch);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-h-front-porch", &mode->h_front_porch);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-h-front-porch, rc=%d\n",
 		       rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-back-porch",
-				  &mode->h_back_porch);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-h-back-porch", &mode->h_back_porch);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-h-back-porch, rc=%d\n",
 		       rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-pulse-width",
-				  &mode->h_sync_width);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-h-pulse-width", &mode->h_sync_width);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-h-pulse-width, rc=%d\n",
 		       rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-h-sync-skew",
-				  &mode->h_skew);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-h-sync-skew", &mode->h_skew);
 	if (rc)
 		pr_err("qcom,mdss-dsi-h-sync-skew is not defined, rc=%d\n", rc);
 
@@ -778,32 +825,32 @@
 		mode->h_active, mode->h_front_porch, mode->h_back_porch,
 		mode->h_sync_width);
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-panel-height",
-				  &mode->v_active);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-panel-height", &mode->v_active);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-panel-height, rc=%d\n",
 		       rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-back-porch",
-				  &mode->v_back_porch);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-v-back-porch", &mode->v_back_porch);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-v-back-porch, rc=%d\n",
 		       rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-front-porch",
-				  &mode->v_front_porch);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-v-front-porch", &mode->v_front_porch);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-v-back-porch, rc=%d\n",
 		       rc);
 		goto error;
 	}
 
-	rc = of_property_read_u32(of_node, "qcom,mdss-dsi-v-pulse-width",
-				  &mode->v_sync_width);
+	rc = dsi_panel_parse(of_node, fw_entry,
+		"qcom,mdss-dsi-v-pulse-width", &mode->v_sync_width);
 	if (rc) {
 		pr_err("failed to read qcom,mdss-dsi-v-pulse-width, rc=%d\n",
 		       rc);
@@ -2580,54 +2627,23 @@
 	kfree(esd_config->status_cmd.cmds);
 }
 
-static int dsi_panel_parse_esd_config(struct dsi_panel *panel,
-				     struct device_node *of_node)
+int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel,
+				struct device_node *of_node)
 {
+	struct drm_panel_esd_config *esd_config;
 	int rc = 0;
 	u32 tmp;
 	u32 i, status_len, *lenp;
 	struct property *data;
-	const char *string;
-	struct drm_panel_esd_config *esd_config;
-	u8 *esd_mode = NULL;
 
-	esd_config = &panel->esd_config;
-	esd_config->status_mode = ESD_MODE_MAX;
-	esd_config->esd_enabled = of_property_read_bool(of_node,
-		"qcom,esd-check-enabled");
-
-	if (!esd_config->esd_enabled)
-		return 0;
-
-	rc = of_property_read_string(of_node,
-			"qcom,mdss-dsi-panel-status-check-mode", &string);
-	if (!rc) {
-		if (!strcmp(string, "bta_check")) {
-			esd_config->status_mode = ESD_MODE_SW_BTA;
-		} else if (!strcmp(string, "reg_read")) {
-			esd_config->status_mode = ESD_MODE_REG_READ;
-		} else if (!strcmp(string, "te_signal_check")) {
-			if (panel->panel_mode == DSI_OP_CMD_MODE) {
-				esd_config->status_mode = ESD_MODE_PANEL_TE;
-			} else {
-				pr_err("TE-ESD not valid for video mode\n");
-				rc = -EINVAL;
-				goto error;
-			}
-		} else {
-			pr_err("No valid panel-status-check-mode string\n");
-			rc = -EINVAL;
-			goto error;
-		}
-	} else {
-		pr_debug("status check method not defined!\n");
-		rc = -EINVAL;
-		goto error;
+	if (!panel || !of_node) {
+		pr_err("Invalid Params\n");
+		return -EINVAL;
 	}
 
-	if ((esd_config->status_mode == ESD_MODE_SW_BTA) ||
-		(esd_config->status_mode == ESD_MODE_PANEL_TE))
-		return 0;
+	esd_config = &panel->esd_config;
+	if (!esd_config)
+		return -EINVAL;
 
 	dsi_panel_parse_cmd_sets_sub(&esd_config->status_cmd,
 				DSI_CMD_SET_PANEL_STATUS, of_node);
@@ -2702,8 +2718,10 @@
 	}
 
 	esd_config->status_buf = kzalloc(SZ_4K, GFP_KERNEL);
-	if (!esd_config->status_buf)
+	if (!esd_config->status_buf) {
+		rc = -ENOMEM;
 		goto error4;
+	}
 
 	rc = of_property_read_u32_array(of_node,
 		"qcom,mdss-dsi-panel-status-value",
@@ -2714,15 +2732,6 @@
 				esd_config->groups * status_len);
 	}
 
-	if (panel->esd_config.status_mode == ESD_MODE_REG_READ)
-		esd_mode = "register_read";
-	else if (panel->esd_config.status_mode == ESD_MODE_SW_BTA)
-		esd_mode = "bta_trigger";
-	else if (panel->esd_config.status_mode ==  ESD_MODE_PANEL_TE)
-		esd_mode = "te_check";
-
-	pr_info("ESD enabled with mode: %s\n", esd_mode);
-
 	return 0;
 
 error4:
@@ -2735,6 +2744,70 @@
 error1:
 	kfree(esd_config->status_cmd.cmds);
 error:
+	return rc;
+}
+
+static int dsi_panel_parse_esd_config(struct dsi_panel *panel,
+				     struct device_node *of_node)
+{
+	int rc = 0;
+	const char *string;
+	struct drm_panel_esd_config *esd_config;
+	u8 *esd_mode = NULL;
+
+	esd_config = &panel->esd_config;
+	esd_config->status_mode = ESD_MODE_MAX;
+	esd_config->esd_enabled = of_property_read_bool(of_node,
+		"qcom,esd-check-enabled");
+
+	if (!esd_config->esd_enabled)
+		return 0;
+
+	rc = of_property_read_string(of_node,
+			"qcom,mdss-dsi-panel-status-check-mode", &string);
+	if (!rc) {
+		if (!strcmp(string, "bta_check")) {
+			esd_config->status_mode = ESD_MODE_SW_BTA;
+		} else if (!strcmp(string, "reg_read")) {
+			esd_config->status_mode = ESD_MODE_REG_READ;
+		} else if (!strcmp(string, "te_signal_check")) {
+			if (panel->panel_mode == DSI_OP_CMD_MODE) {
+				esd_config->status_mode = ESD_MODE_PANEL_TE;
+			} else {
+				pr_err("TE-ESD not valid for video mode\n");
+				rc = -EINVAL;
+				goto error;
+			}
+		} else {
+			pr_err("No valid panel-status-check-mode string\n");
+			rc = -EINVAL;
+			goto error;
+		}
+	} else {
+		pr_debug("status check method not defined!\n");
+		rc = -EINVAL;
+		goto error;
+	}
+
+	if (panel->esd_config.status_mode == ESD_MODE_REG_READ) {
+		rc = dsi_panel_parse_esd_reg_read_configs(panel, of_node);
+		if (rc) {
+			pr_err("failed to parse esd reg read mode params, rc=%d\n",
+						rc);
+			goto error;
+		}
+		esd_mode = "register_read";
+	} else if (panel->esd_config.status_mode == ESD_MODE_SW_BTA) {
+		esd_mode = "bta_trigger";
+	} else if (panel->esd_config.status_mode ==  ESD_MODE_PANEL_TE) {
+		esd_mode = "te_check";
+	}
+
+	pr_info("ESD enabled with mode: %s\n", esd_mode);
+
+	return 0;
+
+error:
 	panel->esd_config.esd_enabled = false;
 	return rc;
 }
@@ -3090,7 +3163,8 @@
 		if (index != child_idx++)
 			continue;
 
-		rc = dsi_panel_parse_timing(&mode->timing, child_np);
+		rc = dsi_panel_parse_timing(panel->parent, &mode->timing,
+			panel->name, child_np);
 		if (rc) {
 			pr_err("failed to parse panel timing, rc=%d\n", rc);
 			goto parse_fail;
diff --git a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
index 3b226b0..f8b65ab 100644
--- a/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
+++ b/drivers/gpu/drm/msm/dsi-staging/dsi_panel.h
@@ -283,6 +283,9 @@
 				struct device_node *of_node,
 				int topology_override);
 
+int dsi_panel_parse_esd_reg_read_configs(struct dsi_panel *panel,
+				struct device_node *of_node);
+
 void dsi_panel_ext_bridge_put(struct dsi_panel *panel);
 
 #endif /* _DSI_PANEL_H_ */
diff --git a/drivers/gpu/drm/msm/msm_smmu.c b/drivers/gpu/drm/msm/msm_smmu.c
index 211acce..85867b2 100644
--- a/drivers/gpu/drm/msm/msm_smmu.c
+++ b/drivers/gpu/drm/msm/msm_smmu.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  * Copyright (C) 2013 Red Hat
  * Author: Rob Clark <robdclark@gmail.com>
  *
@@ -321,7 +321,7 @@
 		DRM_DEBUG("%pad/0x%x/0x%x/0x%lx\n", &sgt->sgl->dma_address,
 				sgt->sgl->dma_length, dir, attrs);
 		SDE_EVT32(sgt->sgl->dma_address, sgt->sgl->dma_length,
-				dir, attrs);
+				dir, attrs, client->secure);
 	}
 
 	return 0;
@@ -342,7 +342,8 @@
 	if (sgt && sgt->sgl) {
 		DRM_DEBUG("%pad/0x%x/0x%x\n", &sgt->sgl->dma_address,
 				sgt->sgl->dma_length, dir);
-		SDE_EVT32(sgt->sgl->dma_address, sgt->sgl->dma_length, dir);
+		SDE_EVT32(sgt->sgl->dma_address, sgt->sgl->dma_length, dir,
+			client->secure);
 	}
 
 	msm_dma_unmap_sg(client->dev, sgt->sgl, sgt->nents, dir, dma_buf);
diff --git a/drivers/gpu/drm/msm/sde/sde_color_processing.c b/drivers/gpu/drm/msm/sde/sde_color_processing.c
index 3e3533e..919ed97 100644
--- a/drivers/gpu/drm/msm/sde/sde_color_processing.c
+++ b/drivers/gpu/drm/msm/sde/sde_color_processing.c
@@ -25,6 +25,7 @@
 #include "sde_hw_interrupts.h"
 #include "sde_core_irq.h"
 #include "dsi_panel.h"
+#include "sde_hw_color_processing.h"
 
 struct sde_cp_node {
 	u32 property_id;
@@ -148,6 +149,24 @@
 	SDE_CP_CRTC_MAX_FEATURES,
 };
 
+#define HIGH_BUS_VOTE_NEEDED(feature) ((feature == SDE_CP_CRTC_DSPP_IGC) |\
+				 (feature == SDE_CP_CRTC_DSPP_GC) |\
+				 (feature == SDE_CP_CRTC_DSPP_SIXZONE) |\
+				 (feature == SDE_CP_CRTC_DSPP_GAMUT))
+
+static u32 crtc_feature_map[SDE_CP_CRTC_MAX_FEATURES] = {
+	[SDE_CP_CRTC_DSPP_IGC] = SDE_DSPP_IGC,
+	[SDE_CP_CRTC_DSPP_PCC] = SDE_DSPP_PCC,
+	[SDE_CP_CRTC_DSPP_GC] = SDE_DSPP_GC,
+	[SDE_CP_CRTC_DSPP_MEMCOL_SKIN] = SDE_DSPP_MEMCOLOR,
+	[SDE_CP_CRTC_DSPP_MEMCOL_SKY] = SDE_DSPP_MEMCOLOR,
+	[SDE_CP_CRTC_DSPP_MEMCOL_FOLIAGE] = SDE_DSPP_MEMCOLOR,
+	[SDE_CP_CRTC_DSPP_SIXZONE] = SDE_DSPP_SIXZONE,
+	[SDE_CP_CRTC_DSPP_GAMUT] = SDE_DSPP_GAMUT,
+	[SDE_CP_CRTC_DSPP_DITHER] = SDE_DSPP_DITHER,
+	[SDE_CP_CRTC_DSPP_VLUT] = SDE_DSPP_VLUT,
+};
+
 #define INIT_PROP_ATTACH(p, crtc, prop, node, feature, val) \
 	do { \
 		(p)->crtc = crtc; \
@@ -859,6 +878,10 @@
 	struct sde_hw_ctl *ctl;
 	uint32_t flush_mask = 0;
 	u32 num_mixers = 0, i = 0;
+	u32 sde_dspp_feature = SDE_DSPP_MAX;
+	struct msm_drm_private *priv = NULL;
+	struct sde_kms *sde_kms = NULL;
+	bool mdss_bus_vote = false;
 
 	if (!crtc || !crtc->dev) {
 		DRM_ERROR("invalid crtc %pK dev %pK\n", crtc,
@@ -878,6 +901,17 @@
 		return;
 	}
 
+	priv = crtc->dev->dev_private;
+	if (!priv || !priv->kms) {
+		SDE_ERROR("invalid kms\n");
+		return;
+	}
+	sde_kms = to_sde_kms(priv->kms);
+	if (!sde_kms) {
+		SDE_ERROR("invalid sde kms\n");
+		return;
+	}
+
 	mutex_lock(&sde_crtc->crtc_cp_lock);
 
 	/* Check if dirty lists are empty and ad features are disabled for
@@ -896,6 +930,16 @@
 
 	list_for_each_entry_safe(prop_node, n, &sde_crtc->dirty_list,
 				dirty_list) {
+		sde_dspp_feature = crtc_feature_map[prop_node->feature];
+		if (!mdss_bus_vote && HIGH_BUS_VOTE_NEEDED(prop_node->feature)
+			&& !reg_dmav1_dspp_feature_support(sde_dspp_feature)) {
+			sde_power_scale_reg_bus(&priv->phandle,
+				sde_kms->core_client,
+				VOTE_INDEX_HIGH, false);
+			pr_debug("Vote HIGH for data bus: feature %d\n",
+					prop_node->feature);
+			mdss_bus_vote = true;
+		}
 		sde_cp_crtc_setfeature(prop_node, sde_crtc);
 		/* Set the flush flag to true */
 		if (prop_node->is_dspp_feature)
@@ -903,6 +947,12 @@
 		else
 			set_lm_flush = true;
 	}
+	if (mdss_bus_vote) {
+		sde_power_scale_reg_bus(&priv->phandle, sde_kms->core_client,
+			VOTE_INDEX_LOW, false);
+		pr_debug("Vote LOW for data bus\n");
+		mdss_bus_vote = false;
+	}
 
 	list_for_each_entry_safe(prop_node, n, &sde_crtc->ad_dirty,
 				dirty_list) {
@@ -1180,6 +1230,7 @@
 {
 	struct sde_crtc *sde_crtc = NULL;
 	struct sde_cp_node *prop_node = NULL, *n = NULL;
+	bool ad_suspend = false;
 
 	if (!crtc) {
 		DRM_ERROR("crtc %pK\n", crtc);
@@ -1202,8 +1253,12 @@
 				 active_list) {
 		sde_cp_update_list(prop_node, sde_crtc, true);
 		list_del_init(&prop_node->active_list);
+		ad_suspend = true;
 	}
 	mutex_unlock(&sde_crtc->crtc_cp_lock);
+
+	if (ad_suspend)
+		sde_cp_ad_set_prop(sde_crtc, AD_SUSPEND);
 }
 
 void sde_cp_crtc_resume(struct drm_crtc *crtc)
@@ -1639,6 +1694,9 @@
 	struct sde_crtc *crtc;
 	struct drm_event event;
 	int i;
+	struct msm_drm_private *priv;
+	struct sde_kms *kms;
+	int ret;
 
 	crtc = to_sde_crtc(crtc_drm);
 	num_mixers = crtc->num_mixers;
@@ -1655,9 +1713,25 @@
 	if (!hw_dspp)
 		return;
 
+	kms = get_kms(crtc_drm);
+	if (!kms || !kms->dev) {
+		SDE_ERROR("invalid arg(s)\n");
+		return;
+	}
+
+	priv = kms->dev->dev_private;
+	ret = sde_power_resource_enable(&priv->phandle, kms->core_client, true);
+	if (ret) {
+		SDE_ERROR("failed to enable power resource %d\n", ret);
+		SDE_EVT32(ret, SDE_EVTLOG_ERROR);
+		return;
+	}
+
 	hw_dspp->ops.ad_read_intr_resp(hw_dspp, AD4_IN_OUT_BACKLIGHT,
 			&input_bl, &output_bl);
 
+	sde_power_resource_enable(&priv->phandle, kms->core_client,
+					false);
 	if (!input_bl || input_bl < output_bl)
 		return;
 
@@ -1898,6 +1972,9 @@
 	struct drm_event event;
 	struct drm_msm_hist *hist_data;
 	struct drm_msm_hist tmp_hist_data;
+	struct msm_drm_private *priv;
+	struct sde_kms *kms;
+	int ret;
 	u32 i, j;
 
 	if (!crtc_drm) {
@@ -1914,6 +1991,20 @@
 	if (!crtc->hist_blob)
 		return;
 
+	kms = get_kms(crtc_drm);
+	if (!kms || !kms->dev) {
+		SDE_ERROR("invalid arg(s)\n");
+		return;
+	}
+
+	priv = kms->dev->dev_private;
+	ret = sde_power_resource_enable(&priv->phandle, kms->core_client, true);
+	if (ret) {
+		SDE_ERROR("failed to enable power resource %d\n", ret);
+		SDE_EVT32(ret, SDE_EVTLOG_ERROR);
+		return;
+	}
+
 	/* read histogram data into blob */
 	hist_data = (struct drm_msm_hist *)crtc->hist_blob->data;
 	for (i = 0; i < crtc->num_mixers; i++) {
@@ -1921,6 +2012,8 @@
 		if (!hw_dspp || !hw_dspp->ops.read_histogram) {
 			DRM_ERROR("invalid dspp %pK or read_histogram func\n",
 				hw_dspp);
+			sde_power_resource_enable(&priv->phandle,
+						kms->core_client, false);
 			return;
 		}
 		if (!i) {
@@ -1933,6 +2026,8 @@
 		}
 	}
 
+	sde_power_resource_enable(&priv->phandle, kms->core_client,
+					false);
 	/* send histogram event with blob id */
 	event.length = sizeof(u32);
 	event.type = DRM_EVENT_HISTOGRAM;
diff --git a/drivers/gpu/drm/msm/sde/sde_crtc.c b/drivers/gpu/drm/msm/sde/sde_crtc.c
index 8c1599e..161b27e 100644
--- a/drivers/gpu/drm/msm/sde/sde_crtc.c
+++ b/drivers/gpu/drm/msm/sde/sde_crtc.c
@@ -4486,46 +4486,6 @@
 	return rc;
 }
 
-static int _sde_crtc_excl_rect_overlap_check(struct plane_state pstates[],
-	int cnt, int curr_cnt, struct sde_rect *excl_rect)
-{
-	struct sde_rect dst_rect, intersect;
-	int i, rc = -EINVAL;
-	const struct drm_plane_state *pstate;
-
-	for (i = 0; i < cnt; i++) {
-		if (i == curr_cnt)
-			continue;
-
-		pstate = pstates[i].drm_pstate;
-		POPULATE_RECT(&dst_rect, pstate->crtc_x, pstate->crtc_y,
-				pstate->crtc_w, pstate->crtc_h, false);
-		sde_kms_rect_intersect(&dst_rect, excl_rect, &intersect);
-
-		/* complete intersection of excl_rect is required */
-		if (intersect.w == excl_rect->w && intersect.h == excl_rect->h
-			    /* intersecting rect should be in another z_order */
-			    && pstates[curr_cnt].stage != pstates[i].stage) {
-			rc = 0;
-			goto end;
-		}
-	}
-
-	SDE_ERROR(
-	    "no overlapping rect for [%d] z_pos:%d, excl_rect:{%d,%d,%d,%d}\n",
-			i, pstates[curr_cnt].stage,
-			excl_rect->x, excl_rect->y, excl_rect->w, excl_rect->h);
-	for (i = 0; i < cnt; i++) {
-		pstate = pstates[i].drm_pstate;
-		SDE_ERROR("[%d] p:%d, z_pos:%d, src:{%d,%d,%d,%d}\n",
-				i, pstate->plane->base.id, pstates[i].stage,
-				pstate->crtc_x, pstate->crtc_y,
-				pstate->crtc_w, pstate->crtc_h);
-	}
-end:
-	return rc;
-}
-
 /* no input validation - caller API has all the checks */
 static int _sde_crtc_excl_dim_layer_check(struct drm_crtc_state *state,
 		struct plane_state pstates[], int cnt)
@@ -4558,17 +4518,16 @@
 		}
 	}
 
-	/* this is traversing on sorted z-order pstates */
+	/* log all src and excl_rect, useful for debugging */
 	for (i = 0; i < cnt; i++) {
 		pstate = pstates[i].drm_pstate;
 		sde_pstate = to_sde_plane_state(pstate);
-		if (sde_pstate->excl_rect.w && sde_pstate->excl_rect.h) {
-			/* check overlap on any other z-order */
-			rc = _sde_crtc_excl_rect_overlap_check(pstates, cnt,
-			     i, &sde_pstate->excl_rect);
-			if (rc)
-				goto end;
-		}
+		SDE_DEBUG("p %d z %d src{%d,%d,%d,%d} excl_rect{%d,%d,%d,%d}\n",
+			pstate->plane->base.id, pstates[i].stage,
+			pstate->crtc_x, pstate->crtc_y,
+			pstate->crtc_w, pstate->crtc_h,
+			sde_pstate->excl_rect.x, sde_pstate->excl_rect.y,
+			sde_pstate->excl_rect.w, sde_pstate->excl_rect.h);
 	}
 
 end:
@@ -6227,6 +6186,7 @@
 	spin_lock_irqsave(&crtc->spin_lock, flags);
 	list_for_each_entry(node, &crtc->user_event_list, list) {
 		if (node->event == event) {
+			list_del(&node->list);
 			found = true;
 			break;
 		}
@@ -6242,7 +6202,6 @@
 	 * no need to disable/de-register.
 	 */
 	if (!crtc_drm->enabled) {
-		list_del(&node->list);
 		kfree(node);
 		return 0;
 	}
@@ -6251,13 +6210,11 @@
 	if (ret) {
 		SDE_ERROR("failed to enable power resource %d\n", ret);
 		SDE_EVT32(ret, SDE_EVTLOG_ERROR);
-		list_del(&node->list);
 		kfree(node);
 		return ret;
 	}
 
 	ret = node->func(crtc_drm, false, &node->irq);
-	list_del(&node->list);
 	kfree(node);
 	sde_power_resource_enable(&priv->phandle, kms->core_client, false);
 	return ret;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
index cdc6a9c..ea39dcd 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.c
@@ -80,6 +80,17 @@
 #define LINE_LM_OFFSET			5
 #define LINE_MODE_WB_OFFSET		2
 
+/**
+ * these configurations are decided based on max mdp clock. It accounts
+ * for max and min display resolution based on virtual hardware resource
+ * support.
+ */
+#define MAX_DISPLAY_HEIGHT_WITH_DECIMATION		2160
+#define MAX_DISPLAY_HEIGHT				5120
+#define MIN_DISPLAY_HEIGHT				0
+#define MIN_DISPLAY_WIDTH				0
+#define MAX_LM_PER_DISPLAY				2
+
 /* maximum XIN halt timeout in usec */
 #define VBIF_XIN_HALT_TIMEOUT		0x4000
 
@@ -3216,7 +3227,7 @@
 	return rc;
 }
 
-static int _sde_hardware_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
+static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
 {
 	int rc = 0;
 
@@ -3249,6 +3260,46 @@
 	return rc;
 }
 
+static int _sde_hardware_post_caps(struct sde_mdss_cfg *sde_cfg,
+	uint32_t hw_rev)
+{
+	int rc = 0, i;
+	u32 max_horz_deci = 0, max_vert_deci = 0;
+
+	if (!sde_cfg)
+		return -EINVAL;
+
+	for (i = 0; i < sde_cfg->sspp_count; i++) {
+		if (sde_cfg->sspp[i].sblk) {
+			max_horz_deci = max(max_horz_deci,
+				sde_cfg->sspp[i].sblk->maxhdeciexp);
+			max_vert_deci = max(max_vert_deci,
+				sde_cfg->sspp[i].sblk->maxvdeciexp);
+		}
+	}
+
+	/* this should be updated based on HW rev in future */
+	sde_cfg->max_lm_per_display = MAX_LM_PER_DISPLAY;
+
+	if (max_horz_deci)
+		sde_cfg->max_display_width = sde_cfg->max_sspp_linewidth *
+			max_horz_deci;
+	else
+		sde_cfg->max_display_width = sde_cfg->max_mixer_width *
+			sde_cfg->max_lm_per_display;
+
+	if (max_vert_deci)
+		sde_cfg->max_display_height =
+			MAX_DISPLAY_HEIGHT_WITH_DECIMATION * max_vert_deci;
+	else
+		sde_cfg->max_display_height = MAX_DISPLAY_HEIGHT;
+
+	sde_cfg->min_display_height = MIN_DISPLAY_HEIGHT;
+	sde_cfg->min_display_width = MIN_DISPLAY_WIDTH;
+
+	return rc;
+}
+
 void sde_hw_catalog_deinit(struct sde_mdss_cfg *sde_cfg)
 {
 	int i;
@@ -3307,7 +3358,7 @@
 
 	sde_cfg->hwversion = hw_rev;
 
-	rc = _sde_hardware_caps(sde_cfg, hw_rev);
+	rc = _sde_hardware_pre_caps(sde_cfg, hw_rev);
 	if (rc)
 		goto end;
 
@@ -3379,6 +3430,10 @@
 	if (rc)
 		goto end;
 
+	rc = _sde_hardware_post_caps(sde_cfg, hw_rev);
+	if (rc)
+		goto end;
+
 	return sde_cfg;
 
 end:
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
index aa6c482..0bb61b3 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_catalog.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -909,6 +909,11 @@
  * @max_mixer_blendstages max layer mixer blend stages or
  *                       supported z order
  * @max_wb_linewidth   max writeback line width support.
+ * @max_display_width   maximum display width support.
+ * @max_display_height  maximum display height support.
+ * @max_lm_per_display  maximum layer mixer per display
+ * @min_display_width   minimum display width support.
+ * @min_display_height  minimum display height support.
  * @qseed_type         qseed2 or qseed3 support.
  * @csc_type           csc or csc_10bit support.
  * @smart_dma_rev      Supported version of SmartDMA feature.
@@ -935,6 +940,13 @@
 	u32 max_mixer_width;
 	u32 max_mixer_blendstages;
 	u32 max_wb_linewidth;
+
+	u32 max_display_width;
+	u32 max_display_height;
+	u32 min_display_width;
+	u32 min_display_height;
+	u32 max_lm_per_display;
+
 	u32 qseed_type;
 	u32 csc_type;
 	u32 smart_dma_rev;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
index 0dc3fed..05ac893 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -248,6 +248,32 @@
 	return rc;
 }
 
+bool reg_dmav1_dspp_feature_support(int feature)
+{
+	struct sde_hw_reg_dma_ops *dma_ops;
+	bool is_supported = false;
+
+	if (feature >= SDE_DSPP_MAX) {
+		DRM_ERROR("invalid feature %x max %x\n",
+			feature, SDE_DSPP_MAX);
+		return is_supported;
+	}
+
+	if (feature_map[feature] >= REG_DMA_FEATURES_MAX) {
+		DRM_ERROR("invalid feature map %d for feature %d\n",
+			feature_map[feature], feature);
+		return is_supported;
+	}
+
+	dma_ops = sde_reg_dma_get_ops();
+	if (IS_ERR_OR_NULL(dma_ops))
+		return is_supported;
+
+	dma_ops->check_support(feature_map[feature], DSPP0, &is_supported);
+
+	return is_supported;
+}
+
 int reg_dmav1_init_dspp_op_v4(int feature, enum sde_dspp idx)
 {
 	int rc = -ENOTSUPP;
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
index a8115d6..5cd212a 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
+++ b/drivers/gpu/drm/msm/sde/sde_hw_reg_dma_v1_color_proc.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -25,6 +25,13 @@
 int reg_dmav1_init_dspp_op_v4(int feature, enum sde_dspp idx);
 
 /**
+ * reg_dmav1_dspp_feature_support() - check if dspp feature using REG_DMA
+ *                                    or not.
+ * @feature: dspp feature
+ */
+bool reg_dmav1_dspp_feature_support(int feature);
+
+/**
  * reg_dma_init_sspp_op_v4() - initialize the sspp feature op for sde v4
  * @feature: sspp feature
  * @idx: sspp idx
diff --git a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
index 9355080..356f9ef 100644
--- a/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
+++ b/drivers/gpu/drm/msm/sde/sde_hw_sspp.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -375,19 +375,24 @@
 
 	c = &ctx->hw;
 
-	if (enable) {
-		if ((rect_mode == SDE_SSPP_RECT_SOLO)
-				|| (rect_mode == SDE_SSPP_RECT_0))
-			secure_bit_mask =
-				(rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
-		else
-			secure_bit_mask = 0xA;
+	if ((rect_mode == SDE_SSPP_RECT_SOLO)
+			|| (rect_mode == SDE_SSPP_RECT_0))
+		secure_bit_mask =
+			(rect_mode == SDE_SSPP_RECT_SOLO) ? 0xF : 0x5;
+	else
+		secure_bit_mask = 0xA;
 
-		secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
+	secure = SDE_REG_READ(c, SSPP_SRC_ADDR_SW_STATUS + idx);
+
+	if (enable)
 		secure |= secure_bit_mask;
-	}
+	else
+		secure &= ~secure_bit_mask;
 
 	SDE_REG_WRITE(c, SSPP_SRC_ADDR_SW_STATUS + idx, secure);
+
+	/* multiple planes share same sw_status register */
+	wmb();
 }
 
 
diff --git a/drivers/gpu/drm/msm/sde/sde_kms.c b/drivers/gpu/drm/msm/sde/sde_kms.c
index 5895a4d..3bede65 100644
--- a/drivers/gpu/drm/msm/sde/sde_kms.c
+++ b/drivers/gpu/drm/msm/sde/sde_kms.c
@@ -2315,7 +2315,7 @@
 		 * configuration.
 		 */
 		if (conn_iter &&
-			conn_iter->encoder_ids[0] == encoder->base.id) {
+			(conn_iter->encoder_ids[0] == encoder->base.id)) {
 			connector = conn_iter;
 			break;
 		}
@@ -3016,15 +3016,10 @@
 		goto drm_obj_init_err;
 	}
 
-	dev->mode_config.min_width = 0;
-	dev->mode_config.min_height = 0;
-
-	/*
-	 * max crtc width is equal to the max mixer width * 2 and max height is
-	 * is 4K
-	 */
-	dev->mode_config.max_width = sde_kms->catalog->max_mixer_width * 2;
-	dev->mode_config.max_height = 4096;
+	dev->mode_config.min_width = sde_kms->catalog->min_display_width;
+	dev->mode_config.min_height = sde_kms->catalog->min_display_height;
+	dev->mode_config.max_width = sde_kms->catalog->max_display_width;
+	dev->mode_config.max_height = sde_kms->catalog->max_display_height;
 
 	/*
 	 * Support format modifiers for compression etc.
diff --git a/drivers/gpu/drm/msm/sde/sde_rm.c b/drivers/gpu/drm/msm/sde/sde_rm.c
index 93304e16..52a5bc9 100644
--- a/drivers/gpu/drm/msm/sde/sde_rm.c
+++ b/drivers/gpu/drm/msm/sde/sde_rm.c
@@ -398,7 +398,7 @@
 		void __iomem *mmio,
 		struct drm_device *dev)
 {
-	int rc, i;
+	int rc = 0, i;
 	enum sde_hw_blk_type type;
 
 	if (!rm || !cat || !mmio || !dev) {
@@ -1182,7 +1182,7 @@
 	}
 
 	SDE_EVT32(status, irq_idx_pp_done, SDE_EVTLOG_ERROR);
-	SDE_ERROR("polling timed out. status = 0x%x\n", status);
+	SDE_DEBUG("polling timed out. status = 0x%x\n", status);
 	return -ETIMEDOUT;
 }
 
diff --git a/drivers/gpu/drm/msm/sde_power_handle.c b/drivers/gpu/drm/msm/sde_power_handle.c
index 40542ab..037c036 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.c
+++ b/drivers/gpu/drm/msm/sde_power_handle.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -844,6 +844,68 @@
 		sde_rsc_client_destroy(phandle->rsc_client);
 }
 
+
+int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
+	struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock)
+{
+	struct sde_power_client *client;
+	int rc = 0;
+	u32 max_usecase_ndx = VOTE_INDEX_DISABLE;
+
+	if (!skip_lock) {
+		mutex_lock(&phandle->phandle_lock);
+
+		if (WARN_ON(pclient->refcount == 0)) {
+			/*
+			 * This is not expected, clients calling without skip
+			 * lock are outside the power resource enable, which
+			 * means that they should have enabled the power
+			 * resource before trying to scale.
+			 */
+			rc = -EINVAL;
+			goto exit;
+		}
+	}
+
+	pr_debug("%pS: current idx:%d requested:%d client:%d\n",
+		__builtin_return_address(0), pclient->usecase_ndx,
+		usecase_ndx, pclient->id);
+
+	pclient->usecase_ndx = usecase_ndx;
+
+	list_for_each_entry(client, &phandle->power_client_clist, list) {
+		if (client->usecase_ndx < VOTE_INDEX_MAX &&
+		    client->usecase_ndx > max_usecase_ndx)
+			max_usecase_ndx = client->usecase_ndx;
+	}
+
+	rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
+						max_usecase_ndx);
+	if (rc)
+		pr_err("failed to set reg bus vote rc=%d\n", rc);
+
+exit:
+	if (!skip_lock)
+		mutex_unlock(&phandle->phandle_lock);
+
+	return rc;
+}
+
+static inline bool _resource_changed(u32 current_usecase_ndx,
+		u32 max_usecase_ndx)
+{
+	WARN_ON((current_usecase_ndx >= VOTE_INDEX_MAX)
+		|| (max_usecase_ndx >= VOTE_INDEX_MAX));
+
+	if (((current_usecase_ndx >= VOTE_INDEX_LOW) && /*current enabled */
+		(max_usecase_ndx == VOTE_INDEX_DISABLE)) || /* max disabled */
+		((current_usecase_ndx == VOTE_INDEX_DISABLE) && /* disabled */
+		(max_usecase_ndx >= VOTE_INDEX_LOW))) /* max enabled */
+		return true;
+
+	return false;
+}
+
 int sde_power_resource_enable(struct sde_power_handle *phandle,
 	struct sde_power_client *pclient, bool enable)
 {
@@ -877,7 +939,15 @@
 			max_usecase_ndx = client->usecase_ndx;
 	}
 
-	if (phandle->current_usecase_ndx != max_usecase_ndx) {
+	/*
+	 * Check if we need to enable/disable the power resource, we won't
+	 * only-scale up/down the AHB vote in this API; if a client wants to
+	 * bump up the AHB clock above the LOW (default) level, it needs to
+	 * call 'sde_power_scale_reg_bus' with the desired vote after the power
+	 * resource was enabled.
+	 */
+	if (_resource_changed(phandle->current_usecase_ndx,
+			max_usecase_ndx)) {
 		changed = true;
 		prev_usecase_ndx = phandle->current_usecase_ndx;
 		phandle->current_usecase_ndx = max_usecase_ndx;
@@ -920,8 +990,8 @@
 			}
 		}
 
-		rc = sde_power_reg_bus_update(phandle->reg_bus_hdl,
-							max_usecase_ndx);
+		rc = sde_power_scale_reg_bus(phandle, pclient,
+				max_usecase_ndx, true);
 		if (rc) {
 			pr_err("failed to set reg bus vote rc=%d\n", rc);
 			goto reg_bus_hdl_err;
@@ -952,8 +1022,8 @@
 
 		sde_power_rsc_update(phandle, false);
 
-		sde_power_reg_bus_update(phandle->reg_bus_hdl,
-							max_usecase_ndx);
+		sde_power_scale_reg_bus(phandle, pclient,
+				max_usecase_ndx, true);
 
 		if (!phandle->rsc_client)
 			msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg,
@@ -975,7 +1045,7 @@
 clk_err:
 	sde_power_rsc_update(phandle, false);
 rsc_err:
-	sde_power_reg_bus_update(phandle->reg_bus_hdl, prev_usecase_ndx);
+	sde_power_scale_reg_bus(phandle, pclient, max_usecase_ndx, true);
 reg_bus_hdl_err:
 	if (!phandle->rsc_client)
 		msm_dss_enable_vreg(mp->vreg_config, mp->num_vreg, 0);
diff --git a/drivers/gpu/drm/msm/sde_power_handle.h b/drivers/gpu/drm/msm/sde_power_handle.h
index fb7322e..f02ca0a 100644
--- a/drivers/gpu/drm/msm/sde_power_handle.h
+++ b/drivers/gpu/drm/msm/sde_power_handle.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -43,11 +43,15 @@
  * mdss_bus_vote_type: register bus vote type
  * VOTE_INDEX_DISABLE: removes the client vote
  * VOTE_INDEX_LOW: keeps the lowest vote for register bus
+ * VOTE_INDEX_MEDIUM: keeps medium vote for register bus
+ * VOTE_INDEX_HIGH: keeps the highest vote for register bus
  * VOTE_INDEX_MAX: invalid
  */
 enum mdss_bus_vote_type {
 	VOTE_INDEX_DISABLE,
 	VOTE_INDEX_LOW,
+	VOTE_INDEX_MEDIUM,
+	VOTE_INDEX_HIGH,
 	VOTE_INDEX_MAX,
 };
 
@@ -228,6 +232,19 @@
 	struct sde_power_client *pclient, bool enable);
 
 /**
+ * sde_power_scale_reg_bus() - Scale the registers bus for the specified client
+ * @pdata:  power handle containing the resources
+ * @client: client information to scale its vote
+ * @usecase_ndx: new use case to scale the reg bus
+ * @skip_lock: will skip holding the power rsrc mutex during the call, this is
+ *		for internal callers that already hold this required lock.
+ *
+ * Return: error code.
+ */
+int sde_power_scale_reg_bus(struct sde_power_handle *phandle,
+	struct sde_power_client *pclient, u32 usecase_ndx, bool skip_lock);
+
+/**
  * sde_power_resource_is_enabled() - return true if power resource is enabled
  * @pdata:  power handle containing the resources
  *
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index ab9f203..20b1bb85 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -3508,6 +3508,8 @@
 	.clk_set_options = adreno_clk_set_options,
 	.gpu_model = adreno_gpu_model,
 	.stop_fault_timer = adreno_dispatcher_stop_fault_timer,
+	.dispatcher_halt = adreno_dispatcher_halt,
+	.dispatcher_unhalt = adreno_dispatcher_unhalt,
 };
 
 static struct platform_driver adreno_platform_driver = {
diff --git a/drivers/gpu/msm/adreno_a6xx.c b/drivers/gpu/msm/adreno_a6xx.c
index 1250437..06bf506 100644
--- a/drivers/gpu/msm/adreno_a6xx.c
+++ b/drivers/gpu/msm/adreno_a6xx.c
@@ -1258,7 +1258,7 @@
 	_regwrite(gmu->pdc_reg_virt,
 			PDC_GPU_TCS3_CMD0_ADDR + PDC_CMD_OFFSET, 0x30000);
 	_regwrite(gmu->pdc_reg_virt,
-			PDC_GPU_TCS3_CMD0_DATA + PDC_CMD_OFFSET, 0x3);
+			PDC_GPU_TCS3_CMD0_DATA + PDC_CMD_OFFSET, 0x6);
 	_regwrite(gmu->pdc_reg_virt,
 			PDC_GPU_TCS3_CMD0_MSGID + PDC_CMD_OFFSET * 2, 0x10108);
 	_regwrite(gmu->pdc_reg_virt,
diff --git a/drivers/gpu/msm/adreno_dispatch.c b/drivers/gpu/msm/adreno_dispatch.c
index 86b3986..b8c282d 100644
--- a/drivers/gpu/msm/adreno_dispatch.c
+++ b/drivers/gpu/msm/adreno_dispatch.c
@@ -2857,6 +2857,16 @@
 	return ret;
 }
 
+void adreno_dispatcher_halt(struct kgsl_device *device)
+{
+	adreno_get_gpu_halt(ADRENO_DEVICE(device));
+}
+
+void adreno_dispatcher_unhalt(struct kgsl_device *device)
+{
+	adreno_put_gpu_halt(ADRENO_DEVICE(device));
+}
+
 /*
  * adreno_dispatcher_idle() - Wait for dispatcher to idle
  * @adreno_dev: Adreno device whose dispatcher needs to idle
@@ -2887,6 +2897,13 @@
 
 	mutex_unlock(&device->mutex);
 
+	/*
+	 * Flush the worker to make sure all executing
+	 * or pending dispatcher works on worker are
+	 * finished
+	 */
+	kthread_flush_worker(&kgsl_driver.worker);
+
 	ret = wait_for_completion_timeout(&dispatcher->idle_gate,
 			msecs_to_jiffies(ADRENO_IDLE_TIMEOUT));
 	if (ret == 0) {
diff --git a/drivers/gpu/msm/adreno_dispatch.h b/drivers/gpu/msm/adreno_dispatch.h
index 48f0cdc..61bd06f 100644
--- a/drivers/gpu/msm/adreno_dispatch.h
+++ b/drivers/gpu/msm/adreno_dispatch.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2008-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -103,6 +103,8 @@
 };
 
 void adreno_dispatcher_start(struct kgsl_device *device);
+void adreno_dispatcher_halt(struct kgsl_device *device);
+void adreno_dispatcher_unhalt(struct kgsl_device *device);
 int adreno_dispatcher_init(struct adreno_device *adreno_dev);
 void adreno_dispatcher_close(struct adreno_device *adreno_dev);
 int adreno_dispatcher_idle(struct adreno_device *adreno_dev);
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 49514e3..913f9bf 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -531,14 +531,21 @@
 	int ret = 0, id;
 	struct kgsl_process_private  *proc_priv = dev_priv->process_priv;
 
+	/*
+	 * Read and increment the context count under lock to make sure
+	 * no process goes beyond the specified context limit.
+	 */
+	spin_lock(&proc_priv->ctxt_count_lock);
 	if (atomic_read(&proc_priv->ctxt_count) > KGSL_MAX_CONTEXTS_PER_PROC) {
 		KGSL_DRV_ERR(device,
 			"Per process context limit reached for pid %u",
 			dev_priv->process_priv->pid);
+		spin_unlock(&proc_priv->ctxt_count_lock);
 		return -ENOSPC;
 	}
 
 	atomic_inc(&proc_priv->ctxt_count);
+	spin_unlock(&proc_priv->ctxt_count_lock);
 
 	id = _kgsl_get_context_id(device);
 	if (id == -ENOSPC) {
@@ -753,6 +760,8 @@
 
 	mutex_lock(&device->mutex);
 	status = kgsl_pwrctrl_change_state(device, KGSL_STATE_SUSPEND);
+	if (status == 0)
+		device->ftbl->dispatcher_halt(device);
 	mutex_unlock(&device->mutex);
 
 	KGSL_PWR_WARN(device, "suspend end\n");
@@ -767,6 +776,7 @@
 	KGSL_PWR_WARN(device, "resume start\n");
 	mutex_lock(&device->mutex);
 	if (device->state == KGSL_STATE_SUSPEND) {
+		device->ftbl->dispatcher_unhalt(device);
 		kgsl_pwrctrl_change_state(device, KGSL_STATE_SLUMBER);
 	} else if (device->state != KGSL_STATE_INIT) {
 		/*
@@ -918,6 +928,7 @@
 
 	spin_lock_init(&private->mem_lock);
 	spin_lock_init(&private->syncsource_lock);
+	spin_lock_init(&private->ctxt_count_lock);
 
 	idr_init(&private->mem_idr);
 	idr_init(&private->syncsource_idr);
@@ -4039,6 +4050,7 @@
 	struct kgsl_process_private *private = dev_priv->process_priv;
 	struct kgsl_gpuobj_set_info *param = data;
 	struct kgsl_mem_entry *entry;
+	int ret = 0;
 
 	if (param->id == 0)
 		return -EINVAL;
@@ -4051,13 +4063,16 @@
 		copy_metadata(entry, param->metadata, param->metadata_len);
 
 	if (param->flags & KGSL_GPUOBJ_SET_INFO_TYPE) {
-		entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK);
-		entry->memdesc.flags |= (uint64_t)(param->type <<
-						KGSL_MEMTYPE_SHIFT);
+		if (param->type <= (KGSL_MEMTYPE_MASK >> KGSL_MEMTYPE_SHIFT)) {
+			entry->memdesc.flags &= ~((uint64_t) KGSL_MEMTYPE_MASK);
+			entry->memdesc.flags |= (uint64_t)((param->type <<
+				KGSL_MEMTYPE_SHIFT) & KGSL_MEMTYPE_MASK);
+		} else
+			ret = -EINVAL;
 	}
 
 	kgsl_mem_entry_put(entry);
-	return 0;
+	return ret;
 }
 
 /**
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index b6a2edb..41d1a38 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -190,6 +190,8 @@
 	void (*gpu_model)(struct kgsl_device *device, char *str,
 		size_t bufsz);
 	void (*stop_fault_timer)(struct kgsl_device *device);
+	void (*dispatcher_halt)(struct kgsl_device *device);
+	void (*dispatcher_unhalt)(struct kgsl_device *device);
 };
 
 struct kgsl_ioctl {
@@ -443,6 +445,7 @@
  * @syncsource_lock: Spinlock to protect the syncsource idr
  * @fd_count: Counter for the number of FDs for this process
  * @ctxt_count: Count for the number of contexts for this process
+ * @ctxt_count_lock: Spinlock to protect ctxt_count
  */
 struct kgsl_process_private {
 	unsigned long priv;
@@ -463,6 +466,7 @@
 	spinlock_t syncsource_lock;
 	int fd_count;
 	atomic_t ctxt_count;
+	spinlock_t ctxt_count_lock;
 };
 
 /**
diff --git a/drivers/gpu/msm/kgsl_sync.h b/drivers/gpu/msm/kgsl_sync.h
index 7c9f334e..955401d 100644
--- a/drivers/gpu/msm/kgsl_sync.h
+++ b/drivers/gpu/msm/kgsl_sync.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2014, 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2014,2017-2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -137,8 +137,8 @@
 }
 
 
-struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
-					void (*func)(void *priv), void *priv,
+static inline struct kgsl_sync_fence_cb *kgsl_sync_fence_async_wait(int fd,
+					bool (*func)(void *priv), void *priv,
 					char *fence_name, int name_len)
 {
 	return NULL;
@@ -188,7 +188,7 @@
 
 }
 
-void kgsl_dump_fence(struct kgsl_drawobj_sync_event *event,
+static inline void kgsl_dump_fence(struct kgsl_drawobj_sync_event *event,
 					char *fence_str, int len)
 {
 }
diff --git a/drivers/hid/hid-core.c b/drivers/hid/hid-core.c
index f2a7483..b5888db 100644
--- a/drivers/hid/hid-core.c
+++ b/drivers/hid/hid-core.c
@@ -2366,7 +2366,6 @@
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EARTHMATE) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_DELORME, USB_DEVICE_ID_DELORME_EM_LT20) },
 	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0400) },
-	{ HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, 0x0401) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ESSENTIAL_REALITY, USB_DEVICE_ID_ESSENTIAL_REALITY_P5) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC5UH) },
 	{ HID_USB_DEVICE(USB_VENDOR_ID_ETT, USB_DEVICE_ID_TC4UM) },
@@ -2636,6 +2635,17 @@
 			strncmp(hdev->name, "www.masterkit.ru MA901", 22) == 0)
 			return true;
 		break;
+	case USB_VENDOR_ID_ELAN:
+		/*
+		 * Many Elan devices have a product id of 0x0401 and are handled
+		 * by the elan_i2c input driver. But the ACPI HID ELAN0800 dev
+		 * is not (and cannot be) handled by that driver ->
+		 * Ignore all 0x0401 devs except for the ELAN0800 dev.
+		 */
+		if (hdev->product == 0x0401 &&
+		    strncmp(hdev->name, "ELAN0800", 8) != 0)
+			return true;
+		break;
 	}
 
 	if (hdev->type == HID_TYPE_USBMOUSE &&
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index b35605d..62ad4f4 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -2033,6 +2033,34 @@
 }
 EXPORT_SYMBOL(qpnp_adc_scale_pmi_chg_temp);
 
+int32_t qpnp_adc_scale_die_temp_1390(struct qpnp_vadc_chip *chip,
+		int32_t adc_code,
+		const struct qpnp_adc_properties *adc_properties,
+		const struct qpnp_vadc_chan_properties *chan_properties,
+		struct qpnp_vadc_result *adc_chan_result)
+{
+	int rc = 0;
+
+	if (!chan_properties || !chan_properties->offset_gain_numerator ||
+		!chan_properties->offset_gain_denominator || !adc_properties
+		|| !adc_chan_result)
+		return -EINVAL;
+
+	rc = qpnp_adc_scale_default(chip, adc_code, adc_properties,
+			chan_properties, adc_chan_result);
+	if (rc < 0)
+		return rc;
+
+	pr_debug("raw_code:%x, v_adc:%lld\n", adc_code,
+						adc_chan_result->physical);
+	/* T = (1.49322 – V) / 0.00356 */
+	adc_chan_result->physical = 1493220 - adc_chan_result->physical;
+	adc_chan_result->physical = div64_s64(adc_chan_result->physical, 356);
+
+	return 0;
+}
+EXPORT_SYMBOL(qpnp_adc_scale_die_temp_1390);
+
 int32_t qpnp_adc_enable_voltage(struct qpnp_adc_drv *adc)
 {
 	int rc = 0;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index f5f914fc6..88b879c 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -225,6 +225,7 @@
 	[SCALE_I_DEFAULT] = {qpnp_iadc_scale_default},
 	[SCALE_USBIN_I] = {qpnp_adc_scale_usbin_curr},
 	[SCALE_BATT_THERM_TEMP_QRD] = {qpnp_adc_batt_therm_qrd},
+	[SCALE_SMB1390_DIE_TEMP] = {qpnp_adc_scale_die_temp_1390},
 };
 
 static struct qpnp_vadc_rscale_fn adc_vadc_rscale_fn[] = {
diff --git a/drivers/hwtracing/coresight/coresight-byte-cntr.c b/drivers/hwtracing/coresight/coresight-byte-cntr.c
index 81889b6..5173770 100644
--- a/drivers/hwtracing/coresight/coresight-byte-cntr.c
+++ b/drivers/hwtracing/coresight/coresight-byte-cntr.c
@@ -149,6 +149,8 @@
 	if (!byte_cntr_data->read_active)
 		goto err0;
 
+	bufp = (char *)(tmcdrvdata->buf + *ppos);
+
 	if (byte_cntr_data->enable) {
 		if (!atomic_read(&byte_cntr_data->irq_cnt)) {
 			mutex_unlock(&byte_cntr_data->byte_cntr_lock);
@@ -159,7 +161,6 @@
 			if (!byte_cntr_data->read_active)
 				goto err0;
 		}
-		bufp = (char *)(tmcdrvdata->buf + *ppos);
 
 		if (tmcdrvdata->mem_type == TMC_ETR_MEM_TYPE_CONTIG)
 			tmc_etr_read_bytes(byte_cntr_data, ppos,
@@ -268,8 +269,12 @@
 		return -EINVAL;
 	}
 
+	/* IRQ is a '8- byte' counter and to observe interrupt at
+	 * 'block_size' bytes of data
+	 */
 	coresight_csr_set_byte_cntr(byte_cntr_data->csr,
-				byte_cntr_data->block_size);
+				(byte_cntr_data->block_size) / 8);
+
 	fp->private_data = byte_cntr_data;
 	nonseekable_open(in, fp);
 	byte_cntr_data->enable = true;
diff --git a/drivers/hwtracing/coresight/coresight-tmc.c b/drivers/hwtracing/coresight/coresight-tmc.c
index 802d4f1..6597fd6 100644
--- a/drivers/hwtracing/coresight/coresight-tmc.c
+++ b/drivers/hwtracing/coresight/coresight-tmc.c
@@ -487,8 +487,13 @@
 	if (!drvdata->byte_cntr)
 		return -EINVAL;
 
+	if (val && val < 16) {
+		pr_err("Assign minimum block size of 16 bytes\n");
+		return -EINVAL;
+	}
+
 	mutex_lock(&drvdata->byte_cntr->byte_cntr_lock);
-	drvdata->byte_cntr->block_size = val * 8;
+	drvdata->byte_cntr->block_size = val;
 	mutex_unlock(&drvdata->byte_cntr->byte_cntr_lock);
 
 	return size;
diff --git a/drivers/input/misc/hbtp_input.c b/drivers/input/misc/hbtp_input.c
index 09fa146..3cb8815 100644
--- a/drivers/input/misc/hbtp_input.c
+++ b/drivers/input/misc/hbtp_input.c
@@ -39,6 +39,7 @@
 #define HBTP_HOLD_DURATION_US			(10)
 #define HBTP_PINCTRL_DDIC_SEQ_NUM		(4)
 #define HBTP_WAIT_TIMEOUT_MS			2000
+#define MSC_HBTP_ACTIVE_BLOB			0x05
 
 struct hbtp_data {
 	struct platform_device *pdev;
@@ -91,6 +92,7 @@
 	s16 ROI[MAX_ROI_SIZE];
 	s16 accelBuffer[MAX_ACCEL_SIZE];
 	u32 display_status;
+	u32 touch_flag;
 };
 
 static struct hbtp_data *hbtp;
@@ -234,6 +236,9 @@
 	__set_bit(BTN_TOUCH, input_dev->keybit);
 	__set_bit(INPUT_PROP_DIRECT, input_dev->propbit);
 
+	/* for Blob touch interference feature */
+	input_set_capability(input_dev, EV_MSC, MSC_HBTP_ACTIVE_BLOB);
+
 	for (i = KEY_HOME; i <= KEY_MICMUTE; i++)
 		__set_bit(i, input_dev->keybit);
 
@@ -273,10 +278,12 @@
 }
 
 static int hbtp_input_report_events(struct hbtp_data *hbtp_data,
-				struct hbtp_input_mt *mt_data)
+				struct hbtp_input_mt *mt_data, u32 flag)
 {
 	int i;
 	struct hbtp_input_touch *tch;
+	u32 flag_change;
+	bool active_blob;
 
 	for (i = 0; i < HBTP_MAX_FINGER; i++) {
 		tch = &(mt_data->touches[i]);
@@ -331,10 +338,19 @@
 			hbtp_data->touch_status[i] = tch->active;
 		}
 	}
+	flag_change = hbtp_data->touch_flag ^ flag;
+	if (flag_change) {
+		if (flag_change & HBTP_FLAG_ACTIVE_BLOB) {
+			active_blob = (flag & HBTP_FLAG_ACTIVE_BLOB) ?
+				true : false;
 
+			input_event(hbtp_data->input_dev, EV_MSC,
+				MSC_HBTP_ACTIVE_BLOB, active_blob);
+		}
+	}
 	input_report_key(hbtp->input_dev, BTN_TOUCH, mt_data->num_touches > 0);
 	input_sync(hbtp->input_dev);
-
+	hbtp_data->touch_flag = flag;
 	return 0;
 }
 
@@ -595,6 +611,7 @@
 {
 	int error = 0;
 	struct hbtp_input_mt mt_data;
+	struct hbtp_input_mt_ext mt_data_ext;
 	struct hbtp_input_absinfo absinfo[ABS_MT_LAST - ABS_MT_FIRST + 1];
 	struct hbtp_input_key key_data;
 	enum hbtp_afe_power_cmd power_cmd;
@@ -636,7 +653,26 @@
 			return -EFAULT;
 		}
 
-		hbtp_input_report_events(hbtp, &mt_data);
+		hbtp_input_report_events(hbtp, &mt_data, 0);
+		error = 0;
+		break;
+
+	case HBTP_SET_TOUCHDATA_EXT:
+		if (!hbtp || !hbtp->input_dev) {
+			pr_err("%s: The input device hasn't been created\n",
+				__func__);
+			return -EFAULT;
+		}
+
+		if (copy_from_user(&mt_data_ext, (void __user *)arg,
+					sizeof(struct hbtp_input_mt_ext))) {
+			pr_err("%s: Error copying data\n", __func__);
+			return -EFAULT;
+		}
+
+		hbtp_input_report_events(hbtp,
+			(struct hbtp_input_mt *)&mt_data_ext,
+			mt_data_ext.flag);
 		error = 0;
 		break;
 
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index bc01a41..56ac9e0 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1366,6 +1366,28 @@
 	.free_pages_exact = arm_smmu_free_pages_exact,
 };
 
+static void msm_smmu_tlb_inv_context(void *cookie)
+{
+}
+
+static void msm_smmu_tlb_inv_range_nosync(unsigned long iova, size_t size,
+					  size_t granule, bool leaf,
+					  void *cookie)
+{
+}
+
+static void msm_smmu_tlb_sync(void *cookie)
+{
+}
+
+static struct iommu_gather_ops msm_smmu_gather_ops = {
+	.tlb_flush_all	= msm_smmu_tlb_inv_context,
+	.tlb_add_flush	= msm_smmu_tlb_inv_range_nosync,
+	.tlb_sync	= msm_smmu_tlb_sync,
+	.alloc_pages_exact = arm_smmu_alloc_pages_exact,
+	.free_pages_exact = arm_smmu_free_pages_exact,
+};
+
 static phys_addr_t arm_smmu_verify_fault(struct iommu_domain *domain,
 					 dma_addr_t iova, u32 fsr)
 {
@@ -1887,6 +1909,9 @@
 	if (smmu->options & ARM_SMMU_OPT_MMU500_ERRATA1)
 		tlb = &qsmmuv500_errata1_smmu_gather_ops;
 
+	if (arm_smmu_is_slave_side_secure(smmu_domain))
+		tlb = &msm_smmu_gather_ops;
+
 	ret = arm_smmu_alloc_cb(domain, smmu, dev);
 	if (ret < 0)
 		goto out_unlock;
@@ -1907,6 +1932,7 @@
 				.sec_id = smmu->sec_id,
 				.cbndx = cfg->cbndx,
 			},
+			.tlb		= tlb,
 			.iommu_dev      = smmu->dev,
 		};
 		fmt = ARM_MSM_SECURE;
@@ -2277,8 +2303,6 @@
 	const struct iommu_gather_ops *tlb;
 
 	tlb = smmu_domain->pgtbl_cfg.tlb;
-	if (!tlb)
-		return;
 
 	mutex_lock(&smmu->stream_map_mutex);
 	for_each_cfg_sme(fwspec, i, idx) {
diff --git a/drivers/iommu/io-pgtable-msm-secure.c b/drivers/iommu/io-pgtable-msm-secure.c
index 983b28b..1ebf657 100644
--- a/drivers/iommu/io-pgtable-msm-secure.c
+++ b/drivers/iommu/io-pgtable-msm-secure.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -71,7 +71,7 @@
 	/* Now allocate memory for the secure page tables */
 	attrs = DMA_ATTR_NO_KERNEL_MAPPING;
 	dev.coherent_dma_mask = DMA_BIT_MASK(sizeof(dma_addr_t) * 8);
-	arch_setup_dma_ops(&dev, 0, 0, NULL, 1);
+	arch_setup_dma_ops(&dev, 0, 0, NULL, 0);
 	cpu_addr = dma_alloc_attrs(&dev, psize[0], &paddr, GFP_KERNEL, attrs);
 	if (!cpu_addr) {
 		pr_err("%s: Failed to allocate %d bytes for PTBL\n",
diff --git a/drivers/irqchip/qcom/Makefile b/drivers/irqchip/qcom/Makefile
index 1a8ee65..8871f9a 100644
--- a/drivers/irqchip/qcom/Makefile
+++ b/drivers/irqchip/qcom/Makefile
@@ -2,4 +2,4 @@
 obj-$(CONFIG_QTI_PDC_SDM845)		+= pdc-sdm845.o
 obj-$(CONFIG_QTI_PDC_SDM670)		+= pdc-sdm670.o
 obj-$(CONFIG_QTI_PDC_SDXPOORWILLS)	+= pdc-sdxpoorwills.o
-obj-$(CONFIG_QTI_MPM)			+= mpm.o mpm-8953.o
+obj-$(CONFIG_QTI_MPM)			+= mpm.o mpm-8953.o mpm-8937.o
diff --git a/drivers/irqchip/qcom/mpm-8937.c b/drivers/irqchip/qcom/mpm-8937.c
new file mode 100644
index 0000000..d6875eb
--- /dev/null
+++ b/drivers/irqchip/qcom/mpm-8937.c
@@ -0,0 +1,74 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include "mpm.h"
+
+const struct mpm_pin mpm_msm8937_gic_chip_data[] = {
+	{2, 216},
+	{49, 172},
+	{53, 104},
+	{58, 166},
+	{62, 222},
+	{-1},
+};
+
+const struct mpm_pin mpm_msm8937_gpio_chip_data[] = {
+	{3, 38},
+	{4, 1},
+	{5, 5},
+	{6, 9},
+	{8, 37},
+	{9, 36},
+	{10, 13},
+	{11, 35},
+	{12, 17},
+	{13, 21},
+	{14, 54},
+	{15, 34},
+	{16, 31},
+	{17, 58},
+	{18, 28},
+	{19, 42},
+	{20, 25},
+	{21, 12},
+	{22, 43},
+	{23, 44},
+	{24, 45},
+	{25, 46},
+	{26, 48},
+	{27, 65},
+	{28, 93},
+	{29, 97},
+	{30, 63},
+	{31, 70},
+	{32, 71},
+	{33, 72},
+	{34, 81},
+	{35, 126},
+	{36, 90},
+	{37, 128},
+	{38, 91},
+	{39, 41},
+	{40, 127},
+	{41, 86},
+	{50, 67},
+	{51, 73},
+	{52, 74},
+	{53, 62},
+	{54, 124},
+	{55, 61},
+	{56, 130},
+	{57, 59},
+	{59, 50},
+	{-1},
+};
diff --git a/drivers/irqchip/qcom/mpm-8953.c b/drivers/irqchip/qcom/mpm-8953.c
index c9b15af..358f40b 100644
--- a/drivers/irqchip/qcom/mpm-8953.c
+++ b/drivers/irqchip/qcom/mpm-8953.c
@@ -22,3 +22,60 @@
 	{88, 222}, /* ee0_krait_hlos_spmi_periph_irq */
 	{-1},
 };
+
+const struct mpm_pin mpm_msm8953_gpio_chip_data[] = {
+	{3, 38},
+	{4, 1},
+	{5, 5},
+	{6, 9},
+	{8, 37},
+	{9, 36},
+	{10, 13},
+	{11, 35},
+	{12, 17},
+	{13, 21},
+	{14, 54},
+	{15, 34},
+	{16, 31},
+	{17, 58},
+	{18, 28},
+	{19, 42},
+	{20, 25},
+	{21, 12},
+	{22, 43},
+	{23, 44},
+	{24, 45},
+	{25, 46},
+	{26, 48},
+	{27, 65},
+	{28, 93},
+	{29, 97},
+	{30, 63},
+	{31, 70},
+	{32, 71},
+	{33, 72},
+	{34, 81},
+	{35, 85},
+	{36, 90},
+	{50, 67},
+	{51, 73},
+	{52, 74},
+	{53, 62},
+	{59, 59},
+	{60, 60},
+	{61, 61},
+	{62, 86},
+	{63, 87},
+	{64, 91},
+	{65, 129},
+	{66, 130},
+	{67, 131},
+	{68, 132},
+	{69, 133},
+	{70, 137},
+	{71, 138},
+	{72, 139},
+	{73, 140},
+	{74, 141},
+	{-1},
+};
diff --git a/drivers/irqchip/qcom/mpm.c b/drivers/irqchip/qcom/mpm.c
index ba4cfa5..7c91b9e 100644
--- a/drivers/irqchip/qcom/mpm.c
+++ b/drivers/irqchip/qcom/mpm.c
@@ -20,6 +20,7 @@
 #include <linux/irq.h>
 #include <linux/tick.h>
 #include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic-v3.h>
 #include <linux/irqdomain.h>
 #include <linux/interrupt.h>
 #include<linux/ktime.h>
@@ -59,6 +60,7 @@
 	void __iomem *mpm_ipc_reg;
 	irq_hw_number_t ipc_irq;
 	struct irq_domain *gic_chip_domain;
+	struct irq_domain *gpio_chip_domain;
 };
 
 static int msm_pm_sleep_time_override;
@@ -200,6 +202,22 @@
 	}
 }
 
+static void msm_mpm_gpio_chip_mask(struct irq_data *d)
+{
+	msm_mpm_enable_irq(d, false);
+}
+
+static void msm_mpm_gpio_chip_unmask(struct irq_data *d)
+{
+	msm_mpm_enable_irq(d, true);
+}
+
+static int msm_mpm_gpio_chip_set_type(struct irq_data *d, unsigned int type)
+{
+	msm_mpm_set_type(d, type);
+	return 0;
+}
+
 static void msm_mpm_gic_chip_mask(struct irq_data *d)
 {
 	msm_mpm_enable_irq(d, false);
@@ -227,9 +245,61 @@
 	.irq_retrigger	= irq_chip_retrigger_hierarchy,
 	.irq_set_type	= msm_mpm_gic_chip_set_type,
 	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
-#ifdef CONFIG_SMP
 	.irq_set_affinity	= irq_chip_set_affinity_parent,
-#endif
+};
+
+static struct irq_chip msm_mpm_gpio_chip = {
+	.name		= "mpm-gpio",
+	.irq_mask	= msm_mpm_gpio_chip_mask,
+	.irq_disable	= msm_mpm_gpio_chip_mask,
+	.irq_unmask	= msm_mpm_gpio_chip_unmask,
+	.irq_set_type	= msm_mpm_gpio_chip_set_type,
+	.flags		= IRQCHIP_MASK_ON_SUSPEND | IRQCHIP_SKIP_SET_WAKE,
+	.irq_retrigger          = irq_chip_retrigger_hierarchy,
+	.irq_set_vcpu_affinity  = irq_chip_set_vcpu_affinity_parent,
+	.irq_eoi                = irq_chip_eoi_parent,
+	.irq_set_affinity	= irq_chip_set_affinity_parent,
+};
+
+static int msm_mpm_gpio_chip_translate(struct irq_domain *d,
+		struct irq_fwspec *fwspec,
+		unsigned long *hwirq,
+		unsigned int *type)
+{
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count != 2)
+			return -EINVAL;
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+	return -EINVAL;
+}
+
+static int msm_mpm_gpio_chip_alloc(struct irq_domain *domain,
+		unsigned int virq,
+		unsigned int nr_irqs,
+		void *data)
+{
+	int ret = 0;
+	struct irq_fwspec *fwspec = data;
+	irq_hw_number_t hwirq;
+	unsigned int type = IRQ_TYPE_NONE;
+
+	ret = msm_mpm_gpio_chip_translate(domain, fwspec, &hwirq, &type);
+	if (ret)
+		return ret;
+
+	irq_domain_set_hwirq_and_chip(domain, virq, hwirq,
+				&msm_mpm_gpio_chip, NULL);
+
+	return 0;
+}
+
+static const struct irq_domain_ops msm_mpm_gpio_chip_domain_ops = {
+	.translate	= msm_mpm_gpio_chip_translate,
+	.alloc		= msm_mpm_gpio_chip_alloc,
+	.free		= irq_domain_free_irqs_common,
 };
 
 static int msm_mpm_gic_chip_translate(struct irq_domain *d,
@@ -240,10 +310,34 @@
 	if (is_of_node(fwspec->fwnode)) {
 		if (fwspec->param_count < 3)
 			return -EINVAL;
-		*hwirq = fwspec->param[1];
+
+		switch (fwspec->param[0]) {
+		case 0:			/* SPI */
+			*hwirq = fwspec->param[1] + 32;
+			break;
+		case 1:			/* PPI */
+			*hwirq = fwspec->param[1] + 16;
+			break;
+		case GIC_IRQ_TYPE_LPI:	/* LPI */
+			*hwirq = fwspec->param[1];
+			break;
+		default:
+			return -EINVAL;
+		}
+
 		*type = fwspec->param[2] & IRQ_TYPE_SENSE_MASK;
 		return 0;
 	}
+
+	if (is_fwnode_irqchip(fwspec->fwnode)) {
+		if (fwspec->param_count != 2)
+			return -EINVAL;
+
+		*hwirq = fwspec->param[0];
+		*type = fwspec->param[1];
+		return 0;
+	}
+
 	return -EINVAL;
 }
 
@@ -296,15 +390,20 @@
 	irq_set_affinity(msm_mpm_dev_data.ipc_irq, cpumask);
 }
 
-static int msm_get_mpm_pin_map(unsigned int mpm_irq)
+static int msm_get_apps_irq(unsigned int mpm_irq)
 {
-	struct mpm_pin *mpm_gic_pin_map = NULL;
+	struct mpm_pin *mpm_pin = NULL;
 	int apps_irq;
 
-	mpm_gic_pin_map = (struct mpm_pin *)
+	mpm_pin = (struct mpm_pin *)
 		msm_mpm_dev_data.gic_chip_domain->host_data;
-	apps_irq = msm_get_irq_pin(mpm_irq, mpm_gic_pin_map);
-	return apps_irq;
+	apps_irq = msm_get_irq_pin(mpm_irq, mpm_pin);
+	if (apps_irq >= 0)
+		return apps_irq;
+
+	mpm_pin = (struct mpm_pin *)
+		msm_mpm_dev_data.gpio_chip_domain->host_data;
+	return  msm_get_irq_pin(mpm_irq, mpm_pin);
 
 }
 
@@ -407,7 +506,7 @@
 		trace_mpm_wakeup_pending_irqs(i, pending);
 		for_each_set_bit(k, &pending, 32) {
 			mpm_irq = 32 * i + k;
-			apps_irq = msm_get_mpm_pin_map(mpm_irq);
+			apps_irq = msm_get_apps_irq(mpm_irq);
 			desc = apps_irq ?
 				irq_to_desc(apps_irq) : NULL;
 
@@ -420,7 +519,7 @@
 	return IRQ_HANDLED;
 }
 
-static int msm_mpm_probe(struct device_node *node)
+static int msm_mpm_init(struct device_node *node)
 {
 	struct msm_mpm_device_data *dev = &msm_mpm_dev_data;
 	int ret = 0;
@@ -480,17 +579,35 @@
 		.compatible = "qcom,mpm-gic-msm8953",
 		.data = mpm_msm8953_gic_chip_data,
 	},
+	{
+		.compatible = "qcom,mpm-gic-msm8937",
+		.data = mpm_msm8937_gic_chip_data,
+	},
 	{}
 };
 
 MODULE_DEVICE_TABLE(of, mpm_gic_chip_data_table);
 
+static const struct of_device_id mpm_gpio_chip_data_table[] = {
+	{
+		.compatible = "qcom,mpm-gpio-msm8953",
+		.data = mpm_msm8953_gpio_chip_data,
+	},
+	{
+		.compatible = "qcom,mpm-gpio-msm8937",
+		.data = mpm_msm8937_gpio_chip_data,
+	},
+	{}
+};
+
+MODULE_DEVICE_TABLE(of, mpm_gpio_chip_data_table);
+
 static int __init mpm_gic_chip_init(struct device_node *node,
 					struct device_node *parent)
 {
 	struct irq_domain *parent_domain;
 	const struct of_device_id *id;
-	struct device_node *parent_node;
+	int ret;
 
 	if (!parent) {
 		pr_err("%s(): no parent for mpm-gic\n", node->full_name);
@@ -507,12 +624,13 @@
 
 	mpm_to_irq = kcalloc(num_mpm_irqs, sizeof(*mpm_to_irq), GFP_KERNEL);
 	if (!mpm_to_irq)
-		return  -ENOMEM;
+		return -ENOMEM;
 
 	id = of_match_node(mpm_gic_chip_data_table, node);
 	if (!id) {
 		pr_err("can not find mpm_gic_data_table of_node\n");
-		return -ENODEV;
+		ret = -ENODEV;
+		goto mpm_map_err;
 	}
 
 	msm_mpm_dev_data.gic_chip_domain = irq_domain_add_hierarchy(
@@ -520,13 +638,56 @@
 			&msm_mpm_gic_chip_domain_ops, (void *)id->data);
 	if (!msm_mpm_dev_data.gic_chip_domain) {
 		pr_err("gic domain add failed\n");
-		return -ENOMEM;
+		ret = -ENOMEM;
+		goto mpm_map_err;
 	}
 
 	msm_mpm_dev_data.gic_chip_domain->name = "qcom,mpm-gic";
 
-	parent_node = of_get_parent(node);
-	return msm_mpm_probe(parent_node);
+	ret = msm_mpm_init(node);
+	if (!ret)
+		return ret;
+	irq_domain_remove(msm_mpm_dev_data.gic_chip_domain);
+
+mpm_map_err:
+	kfree(mpm_to_irq);
+	return ret;
 }
 
 IRQCHIP_DECLARE(mpm_gic_chip, "qcom,mpm-gic", mpm_gic_chip_init);
+
+static int __init mpm_gpio_chip_init(struct device_node *node,
+					struct device_node *parent)
+{
+	struct irq_domain *parent_domain;
+	const struct of_device_id *id;
+
+	if (!parent) {
+		pr_err("%s(): no parent for mpm-gic\n", node->full_name);
+		return -ENXIO;
+	}
+
+	parent_domain = irq_find_host(parent);
+	if (!parent_domain) {
+		pr_err("unable to obtain gpio parent domain defer probe\n");
+		return -ENXIO;
+	}
+	id = of_match_node(mpm_gpio_chip_data_table, node);
+	if (!id) {
+		pr_err("match_table not found for mpm-gpio\n");
+		return -ENODEV;
+	}
+
+	msm_mpm_dev_data.gpio_chip_domain = irq_domain_add_hierarchy(
+			parent_domain, 0, num_mpm_irqs, node,
+			&msm_mpm_gpio_chip_domain_ops, (void *)id->data);
+
+	if (!msm_mpm_dev_data.gpio_chip_domain)
+		return -ENOMEM;
+
+	msm_mpm_dev_data.gpio_chip_domain->name = "qcom,mpm-gpio";
+
+	return 0;
+}
+
+IRQCHIP_DECLARE(mpm_gpio_chip, "qcom,mpm-gpio", mpm_gpio_chip_init);
diff --git a/drivers/irqchip/qcom/mpm.h b/drivers/irqchip/qcom/mpm.h
index 72185fc..50a127f 100644
--- a/drivers/irqchip/qcom/mpm.h
+++ b/drivers/irqchip/qcom/mpm.h
@@ -22,5 +22,9 @@
 };
 
 extern const struct mpm_pin mpm_msm8953_gic_chip_data[];
+extern const struct mpm_pin mpm_msm8953_gpio_chip_data[];
+
+extern const struct mpm_pin mpm_msm8937_gic_chip_data[];
+extern const struct mpm_pin mpm_msm8937_gpio_chip_data[];
 
 #endif /* __QCOM_MPM_H__ */
diff --git a/drivers/leds/led-triggers.c b/drivers/leds/led-triggers.c
index 431123b..dac7a71 100644
--- a/drivers/leds/led-triggers.c
+++ b/drivers/leds/led-triggers.c
@@ -44,7 +44,8 @@
 		goto unlock;
 	}
 
-	if (sysfs_streq(buf, "none")) {
+	if (sysfs_streq(buf, "none") &&
+			!(led_cdev->flags & LED_KEEP_TRIGGER)) {
 		led_trigger_remove(led_cdev);
 		goto unlock;
 	}
diff --git a/drivers/leds/leds-qti-tri-led.c b/drivers/leds/leds-qti-tri-led.c
index ab5e876..ea8ef9d 100644
--- a/drivers/leds/leds-qti-tri-led.c
+++ b/drivers/leds/leds-qti-tri-led.c
@@ -41,8 +41,6 @@
 #define TRILED_NUM_MAX			3
 
 #define PWM_PERIOD_DEFAULT_NS		1000000
-#define LED_BLINK_ON_MS			125
-#define LED_BLINK_OFF_MS		875
 
 struct pwm_setting {
 	u32	pre_period_ns;
@@ -309,8 +307,7 @@
 		led->cdev.blink_set = qpnp_tri_led_set_blink;
 		led->cdev.default_trigger = led->default_trigger;
 		led->cdev.brightness = LED_OFF;
-		led->cdev.blink_delay_on = LED_BLINK_ON_MS;
-		led->cdev.blink_delay_off = LED_BLINK_OFF_MS;
+		led->cdev.flags |= LED_KEEP_TRIGGER;
 
 		rc = devm_led_classdev_register(chip->dev, &led->cdev);
 		if (rc < 0) {
diff --git a/drivers/md/bcache/request.c b/drivers/md/bcache/request.c
index edb8d1a..723302c 100644
--- a/drivers/md/bcache/request.c
+++ b/drivers/md/bcache/request.c
@@ -1020,7 +1020,7 @@
 	struct request_queue *q = bdev_get_queue(dc->bdev);
 	int ret = 0;
 
-	if (bdi_congested(&q->backing_dev_info, bits))
+	if (bdi_congested(q->backing_dev_info, bits))
 		return 1;
 
 	if (cached_dev_get(dc)) {
@@ -1029,7 +1029,7 @@
 
 		for_each_cache(ca, d->c, i) {
 			q = bdev_get_queue(ca->bdev);
-			ret |= bdi_congested(&q->backing_dev_info, bits);
+			ret |= bdi_congested(q->backing_dev_info, bits);
 		}
 
 		cached_dev_put(dc);
@@ -1043,7 +1043,7 @@
 	struct gendisk *g = dc->disk.disk;
 
 	g->queue->make_request_fn		= cached_dev_make_request;
-	g->queue->backing_dev_info.congested_fn = cached_dev_congested;
+	g->queue->backing_dev_info->congested_fn = cached_dev_congested;
 	dc->disk.cache_miss			= cached_dev_cache_miss;
 	dc->disk.ioctl				= cached_dev_ioctl;
 }
@@ -1136,7 +1136,7 @@
 
 	for_each_cache(ca, d->c, i) {
 		q = bdev_get_queue(ca->bdev);
-		ret |= bdi_congested(&q->backing_dev_info, bits);
+		ret |= bdi_congested(q->backing_dev_info, bits);
 	}
 
 	return ret;
@@ -1147,7 +1147,7 @@
 	struct gendisk *g = d->disk;
 
 	g->queue->make_request_fn		= flash_dev_make_request;
-	g->queue->backing_dev_info.congested_fn = flash_dev_congested;
+	g->queue->backing_dev_info->congested_fn = flash_dev_congested;
 	d->cache_miss				= flash_dev_cache_miss;
 	d->ioctl				= flash_dev_ioctl;
 }
diff --git a/drivers/md/bcache/super.c b/drivers/md/bcache/super.c
index 28ce342..e44816f 100644
--- a/drivers/md/bcache/super.c
+++ b/drivers/md/bcache/super.c
@@ -804,7 +804,7 @@
 	blk_queue_make_request(q, NULL);
 	d->disk->queue			= q;
 	q->queuedata			= d;
-	q->backing_dev_info.congested_data = d;
+	q->backing_dev_info->congested_data = d;
 	q->limits.max_hw_sectors	= UINT_MAX;
 	q->limits.max_sectors		= UINT_MAX;
 	q->limits.max_segment_size	= UINT_MAX;
@@ -1131,9 +1131,9 @@
 	set_capacity(dc->disk.disk,
 		     dc->bdev->bd_part->nr_sects - dc->sb.data_offset);
 
-	dc->disk.disk->queue->backing_dev_info.ra_pages =
-		max(dc->disk.disk->queue->backing_dev_info.ra_pages,
-		    q->backing_dev_info.ra_pages);
+	dc->disk.disk->queue->backing_dev_info->ra_pages =
+		max(dc->disk.disk->queue->backing_dev_info->ra_pages,
+		    q->backing_dev_info->ra_pages);
 
 	bch_cached_dev_request_init(dc);
 	bch_cached_dev_writeback_init(dc);
diff --git a/drivers/md/dm-cache-target.c b/drivers/md/dm-cache-target.c
index c817627..bed056c 100644
--- a/drivers/md/dm-cache-target.c
+++ b/drivers/md/dm-cache-target.c
@@ -2290,7 +2290,7 @@
 static int is_congested(struct dm_dev *dev, int bdi_bits)
 {
 	struct request_queue *q = bdev_get_queue(dev->bdev);
-	return bdi_congested(&q->backing_dev_info, bdi_bits);
+	return bdi_congested(q->backing_dev_info, bdi_bits);
 }
 
 static int cache_is_congested(struct dm_target_callbacks *cb, int bdi_bits)
diff --git a/drivers/md/dm-era-target.c b/drivers/md/dm-era-target.c
index 80e3df1..68d4084 100644
--- a/drivers/md/dm-era-target.c
+++ b/drivers/md/dm-era-target.c
@@ -1379,7 +1379,7 @@
 static int dev_is_congested(struct dm_dev *dev, int bdi_bits)
 {
 	struct request_queue *q = bdev_get_queue(dev->bdev);
-	return bdi_congested(&q->backing_dev_info, bdi_bits);
+	return bdi_congested(q->backing_dev_info, bdi_bits);
 }
 
 static int era_is_congested(struct dm_target_callbacks *cb, int bdi_bits)
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index d837a28..b75ccef 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -1756,7 +1756,7 @@
 		char b[BDEVNAME_SIZE];
 
 		if (likely(q))
-			r |= bdi_congested(&q->backing_dev_info, bdi_bits);
+			r |= bdi_congested(q->backing_dev_info, bdi_bits);
 		else
 			DMWARN_LIMIT("%s: any_congested: nonexistent device %s",
 				     dm_device_name(t->md),
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 0b678b5..eb419a5 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2715,7 +2715,7 @@
 		return 1;
 
 	q = bdev_get_queue(pt->data_dev->bdev);
-	return bdi_congested(&q->backing_dev_info, bdi_bits);
+	return bdi_congested(q->backing_dev_info, bdi_bits);
 }
 
 static void requeue_bios(struct pool *pool)
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index 73e7262..8658ff3 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1380,7 +1380,7 @@
 			 * With request-based DM we only need to check the
 			 * top-level queue for congestion.
 			 */
-			r = md->queue->backing_dev_info.wb.state & bdi_bits;
+			r = md->queue->backing_dev_info->wb.state & bdi_bits;
 		} else {
 			map = dm_get_live_table_fast(md);
 			if (map)
@@ -1463,7 +1463,7 @@
 	 * - must do so here (in alloc_dev callchain) before queue is used
 	 */
 	md->queue->queuedata = md;
-	md->queue->backing_dev_info.congested_data = md;
+	md->queue->backing_dev_info->congested_data = md;
 }
 
 void dm_init_normal_md_queue(struct mapped_device *md)
@@ -1474,7 +1474,7 @@
 	/*
 	 * Initialize aspects of queue that aren't relevant for blk-mq
 	 */
-	md->queue->backing_dev_info.congested_fn = dm_any_congested;
+	md->queue->backing_dev_info->congested_fn = dm_any_congested;
 	blk_queue_bounce_limit(md->queue, BLK_BOUNCE_ANY);
 }
 
diff --git a/drivers/md/linear.c b/drivers/md/linear.c
index 12abf69..be51805 100644
--- a/drivers/md/linear.c
+++ b/drivers/md/linear.c
@@ -68,7 +68,7 @@
 
 	for (i = 0; i < conf->raid_disks && !ret ; i++) {
 		struct request_queue *q = bdev_get_queue(conf->disks[i].rdev->bdev);
-		ret |= bdi_congested(&q->backing_dev_info, bits);
+		ret |= bdi_congested(q->backing_dev_info, bits);
 	}
 
 	rcu_read_unlock();
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 8ebf1b9..df7d606 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -5312,8 +5312,8 @@
 			queue_flag_set_unlocked(QUEUE_FLAG_NONROT, mddev->queue);
 		else
 			queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, mddev->queue);
-		mddev->queue->backing_dev_info.congested_data = mddev;
-		mddev->queue->backing_dev_info.congested_fn = md_congested;
+		mddev->queue->backing_dev_info->congested_data = mddev;
+		mddev->queue->backing_dev_info->congested_fn = md_congested;
 	}
 	if (pers->sync_request) {
 		if (mddev->kobj.sd &&
@@ -5668,7 +5668,7 @@
 
 		__md_stop_writes(mddev);
 		__md_stop(mddev);
-		mddev->queue->backing_dev_info.congested_fn = NULL;
+		mddev->queue->backing_dev_info->congested_fn = NULL;
 
 		/* tell userspace to handle 'inactive' */
 		sysfs_notify_dirent_safe(mddev->sysfs_state);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 673efbd..6a7855a 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -169,7 +169,7 @@
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
-			ret |= bdi_congested(&q->backing_dev_info, bits);
+			ret |= bdi_congested(q->backing_dev_info, bits);
 			/* Just like multipath_map, we just check the
 			 * first available device
 			 */
diff --git a/drivers/md/raid0.c b/drivers/md/raid0.c
index 258986a..3716dae 100644
--- a/drivers/md/raid0.c
+++ b/drivers/md/raid0.c
@@ -35,7 +35,7 @@
 	for (i = 0; i < raid_disks && !ret ; i++) {
 		struct request_queue *q = bdev_get_queue(devlist[i]->bdev);
 
-		ret |= bdi_congested(&q->backing_dev_info, bits);
+		ret |= bdi_congested(q->backing_dev_info, bits);
 	}
 	return ret;
 }
@@ -415,8 +415,8 @@
 		 */
 		int stripe = mddev->raid_disks *
 			(mddev->chunk_sectors << 9) / PAGE_SIZE;
-		if (mddev->queue->backing_dev_info.ra_pages < 2* stripe)
-			mddev->queue->backing_dev_info.ra_pages = 2* stripe;
+		if (mddev->queue->backing_dev_info->ra_pages < 2* stripe)
+			mddev->queue->backing_dev_info->ra_pages = 2* stripe;
 	}
 
 	dump_zones(mddev);
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index 81a7875..208fbf7 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -717,9 +717,9 @@
 			 * non-congested targets, it can be removed
 			 */
 			if ((bits & (1 << WB_async_congested)) || 1)
-				ret |= bdi_congested(&q->backing_dev_info, bits);
+				ret |= bdi_congested(q->backing_dev_info, bits);
 			else
-				ret &= bdi_congested(&q->backing_dev_info, bits);
+				ret &= bdi_congested(q->backing_dev_info, bits);
 		}
 	}
 	rcu_read_unlock();
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index b19b551..8d40238 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -833,7 +833,7 @@
 		if (rdev && !test_bit(Faulty, &rdev->flags)) {
 			struct request_queue *q = bdev_get_queue(rdev->bdev);
 
-			ret |= bdi_congested(&q->backing_dev_info, bits);
+			ret |= bdi_congested(q->backing_dev_info, bits);
 		}
 	}
 	rcu_read_unlock();
@@ -3754,8 +3754,8 @@
 		 * maybe...
 		 */
 		stripe /= conf->geo.near_copies;
-		if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
-			mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
+		if (mddev->queue->backing_dev_info->ra_pages < 2 * stripe)
+			mddev->queue->backing_dev_info->ra_pages = 2 * stripe;
 	}
 
 	if (md_integrity_register(mddev))
@@ -4557,8 +4557,8 @@
 		int stripe = conf->geo.raid_disks *
 			((conf->mddev->chunk_sectors << 9) / PAGE_SIZE);
 		stripe /= conf->geo.near_copies;
-		if (conf->mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
-			conf->mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
+		if (conf->mddev->queue->backing_dev_info->ra_pages < 2 * stripe)
+			conf->mddev->queue->backing_dev_info->ra_pages = 2 * stripe;
 	}
 	conf->fullsync = 0;
 }
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index 475a7a1..90d863e 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -6155,10 +6155,10 @@
 		mddev_suspend(mddev);
 		conf->skip_copy = new;
 		if (new)
-			mddev->queue->backing_dev_info.capabilities |=
+			mddev->queue->backing_dev_info->capabilities |=
 				BDI_CAP_STABLE_WRITES;
 		else
-			mddev->queue->backing_dev_info.capabilities &=
+			mddev->queue->backing_dev_info->capabilities &=
 				~BDI_CAP_STABLE_WRITES;
 		mddev_resume(mddev);
 	}
@@ -6984,8 +6984,8 @@
 		int data_disks = conf->previous_raid_disks - conf->max_degraded;
 		int stripe = data_disks *
 			((mddev->chunk_sectors << 9) / PAGE_SIZE);
-		if (mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
-			mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
+		if (mddev->queue->backing_dev_info->ra_pages < 2 * stripe)
+			mddev->queue->backing_dev_info->ra_pages = 2 * stripe;
 
 		chunk_size = mddev->chunk_sectors << 9;
 		blk_queue_io_min(mddev->queue, chunk_size);
@@ -7591,8 +7591,8 @@
 			int data_disks = conf->raid_disks - conf->max_degraded;
 			int stripe = data_disks * ((conf->chunk_sectors << 9)
 						   / PAGE_SIZE);
-			if (conf->mddev->queue->backing_dev_info.ra_pages < 2 * stripe)
-				conf->mddev->queue->backing_dev_info.ra_pages = 2 * stripe;
+			if (conf->mddev->queue->backing_dev_info->ra_pages < 2 * stripe)
+				conf->mddev->queue->backing_dev_info->ra_pages = 2 * stripe;
 		}
 	}
 }
diff --git a/drivers/media/dvb-frontends/ascot2e.c b/drivers/media/dvb-frontends/ascot2e.c
index ad304ee..c61227c 100644
--- a/drivers/media/dvb-frontends/ascot2e.c
+++ b/drivers/media/dvb-frontends/ascot2e.c
@@ -155,7 +155,9 @@
 
 static int ascot2e_write_reg(struct ascot2e_priv *priv, u8 reg, u8 val)
 {
-	return ascot2e_write_regs(priv, reg, &val, 1);
+	u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return ascot2e_write_regs(priv, reg, &tmp, 1);
 }
 
 static int ascot2e_read_regs(struct ascot2e_priv *priv,
diff --git a/drivers/media/dvb-frontends/cxd2841er.c b/drivers/media/dvb-frontends/cxd2841er.c
index fd0f25e..b97647c 100644
--- a/drivers/media/dvb-frontends/cxd2841er.c
+++ b/drivers/media/dvb-frontends/cxd2841er.c
@@ -261,7 +261,9 @@
 static int cxd2841er_write_reg(struct cxd2841er_priv *priv,
 			       u8 addr, u8 reg, u8 val)
 {
-	return cxd2841er_write_regs(priv, addr, reg, &val, 1);
+	u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return cxd2841er_write_regs(priv, addr, reg, &tmp, 1);
 }
 
 static int cxd2841er_read_regs(struct cxd2841er_priv *priv,
diff --git a/drivers/media/dvb-frontends/helene.c b/drivers/media/dvb-frontends/helene.c
index dc43c5f..e06bcd4 100644
--- a/drivers/media/dvb-frontends/helene.c
+++ b/drivers/media/dvb-frontends/helene.c
@@ -331,7 +331,9 @@
 
 static int helene_write_reg(struct helene_priv *priv, u8 reg, u8 val)
 {
-	return helene_write_regs(priv, reg, &val, 1);
+	u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return helene_write_regs(priv, reg, &tmp, 1);
 }
 
 static int helene_read_regs(struct helene_priv *priv,
diff --git a/drivers/media/dvb-frontends/horus3a.c b/drivers/media/dvb-frontends/horus3a.c
index 0c089b5..4ebddc8 100644
--- a/drivers/media/dvb-frontends/horus3a.c
+++ b/drivers/media/dvb-frontends/horus3a.c
@@ -89,7 +89,9 @@
 
 static int horus3a_write_reg(struct horus3a_priv *priv, u8 reg, u8 val)
 {
-	return horus3a_write_regs(priv, reg, &val, 1);
+	u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return horus3a_write_regs(priv, reg, &tmp, 1);
 }
 
 static int horus3a_enter_power_save(struct horus3a_priv *priv)
diff --git a/drivers/media/dvb-frontends/itd1000.c b/drivers/media/dvb-frontends/itd1000.c
index cadcae4..ac9d259 100644
--- a/drivers/media/dvb-frontends/itd1000.c
+++ b/drivers/media/dvb-frontends/itd1000.c
@@ -99,8 +99,9 @@
 
 static inline int itd1000_write_reg(struct itd1000_state *state, u8 r, u8 v)
 {
-	int ret = itd1000_write_regs(state, r, &v, 1);
-	state->shadow[r] = v;
+	u8 tmp = v; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+	int ret = itd1000_write_regs(state, r, &tmp, 1);
+	state->shadow[r] = tmp;
 	return ret;
 }
 
diff --git a/drivers/media/dvb-frontends/mt312.c b/drivers/media/dvb-frontends/mt312.c
index fc08429..7824926 100644
--- a/drivers/media/dvb-frontends/mt312.c
+++ b/drivers/media/dvb-frontends/mt312.c
@@ -142,7 +142,10 @@
 static inline int mt312_writereg(struct mt312_state *state,
 				 const enum mt312_reg_addr reg, const u8 val)
 {
-	return mt312_write(state, reg, &val, 1);
+	u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+
+	return mt312_write(state, reg, &tmp, 1);
 }
 
 static inline u32 mt312_div(u32 a, u32 b)
diff --git a/drivers/media/dvb-frontends/stb0899_drv.c b/drivers/media/dvb-frontends/stb0899_drv.c
index 3d171b0..3deddbc 100644
--- a/drivers/media/dvb-frontends/stb0899_drv.c
+++ b/drivers/media/dvb-frontends/stb0899_drv.c
@@ -552,7 +552,8 @@
 
 int stb0899_write_reg(struct stb0899_state *state, unsigned int reg, u8 data)
 {
-	return stb0899_write_regs(state, reg, &data, 1);
+	u8 tmp = data;
+	return stb0899_write_regs(state, reg, &tmp, 1);
 }
 
 /*
diff --git a/drivers/media/dvb-frontends/stb6100.c b/drivers/media/dvb-frontends/stb6100.c
index 5add118..4746b1e 100644
--- a/drivers/media/dvb-frontends/stb6100.c
+++ b/drivers/media/dvb-frontends/stb6100.c
@@ -226,12 +226,14 @@
 
 static int stb6100_write_reg(struct stb6100_state *state, u8 reg, u8 data)
 {
+	u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
 	if (unlikely(reg >= STB6100_NUMREGS)) {
 		dprintk(verbose, FE_ERROR, 1, "Invalid register offset 0x%x", reg);
 		return -EREMOTEIO;
 	}
-	data = (data & stb6100_template[reg].mask) | stb6100_template[reg].set;
-	return stb6100_write_reg_range(state, &data, reg, 1);
+	tmp = (tmp & stb6100_template[reg].mask) | stb6100_template[reg].set;
+	return stb6100_write_reg_range(state, &tmp, reg, 1);
 }
 
 
diff --git a/drivers/media/dvb-frontends/stv0367.c b/drivers/media/dvb-frontends/stv0367.c
index abc379a..94cec81 100644
--- a/drivers/media/dvb-frontends/stv0367.c
+++ b/drivers/media/dvb-frontends/stv0367.c
@@ -804,7 +804,9 @@
 
 static int stv0367_writereg(struct stv0367_state *state, u16 reg, u8 data)
 {
-	return stv0367_writeregs(state, reg, &data, 1);
+	u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return stv0367_writeregs(state, reg, &tmp, 1);
 }
 
 static u8 stv0367_readreg(struct stv0367_state *state, u16 reg)
diff --git a/drivers/media/dvb-frontends/stv090x.c b/drivers/media/dvb-frontends/stv090x.c
index 25bdf6e..f0377e2 100644
--- a/drivers/media/dvb-frontends/stv090x.c
+++ b/drivers/media/dvb-frontends/stv090x.c
@@ -761,7 +761,9 @@
 
 static int stv090x_write_reg(struct stv090x_state *state, unsigned int reg, u8 data)
 {
-	return stv090x_write_regs(state, reg, &data, 1);
+	u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return stv090x_write_regs(state, reg, &tmp, 1);
 }
 
 static int stv090x_i2c_gate_ctrl(struct stv090x_state *state, int enable)
diff --git a/drivers/media/dvb-frontends/stv6110x.c b/drivers/media/dvb-frontends/stv6110x.c
index c611ad2..924f16f 100644
--- a/drivers/media/dvb-frontends/stv6110x.c
+++ b/drivers/media/dvb-frontends/stv6110x.c
@@ -97,7 +97,9 @@
 
 static int stv6110x_write_reg(struct stv6110x_state *stv6110x, u8 reg, u8 data)
 {
-	return stv6110x_write_regs(stv6110x, reg, &data, 1);
+	u8 tmp = data; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return stv6110x_write_regs(stv6110x, reg, &tmp, 1);
 }
 
 static int stv6110x_init(struct dvb_frontend *fe)
diff --git a/drivers/media/dvb-frontends/ts2020.c b/drivers/media/dvb-frontends/ts2020.c
index a9f6bbe..103b9c8 100644
--- a/drivers/media/dvb-frontends/ts2020.c
+++ b/drivers/media/dvb-frontends/ts2020.c
@@ -369,7 +369,7 @@
 		gain2 = clamp_t(long, gain2, 0, 13);
 		v_agc = clamp_t(long, v_agc, 400, 1100);
 
-		*_gain = -(gain1 * 2330 +
+		*_gain = -((__s64)gain1 * 2330 +
 			   gain2 * 3500 +
 			   v_agc * 24 / 10 * 10 +
 			   10000);
@@ -387,7 +387,7 @@
 		gain3 = clamp_t(long, gain3, 0, 6);
 		v_agc = clamp_t(long, v_agc, 600, 1600);
 
-		*_gain = -(gain1 * 2650 +
+		*_gain = -((__s64)gain1 * 2650 +
 			   gain2 * 3380 +
 			   gain3 * 2850 +
 			   v_agc * 176 / 100 * 10 -
diff --git a/drivers/media/dvb-frontends/zl10039.c b/drivers/media/dvb-frontends/zl10039.c
index f8c271b..0d2bef6 100644
--- a/drivers/media/dvb-frontends/zl10039.c
+++ b/drivers/media/dvb-frontends/zl10039.c
@@ -138,7 +138,9 @@
 				const enum zl10039_reg_addr reg,
 				const u8 val)
 {
-	return zl10039_write(state, reg, &val, 1);
+	const u8 tmp = val; /* see gcc.gnu.org/bugzilla/show_bug.cgi?id=81715 */
+
+	return zl10039_write(state, reg, &tmp, 1);
 }
 
 static int zl10039_init(struct dvb_frontend *fe)
diff --git a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
index a90b3d9..cf1859c 100644
--- a/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
+++ b/drivers/media/platform/msm/camera/cam_core/cam_hw_mgr_intf.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -123,10 +123,12 @@
  * struct cam_hw_stop_args - Payload for stop command
  *
  * @ctxt_to_hw_map:        HW context from the acquire
+ * @args:                  Arguments to pass for stop
  *
  */
 struct cam_hw_stop_args {
 	void              *ctxt_to_hw_map;
+	void              *args;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
index b18af0a..2837f5b 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.c
@@ -140,6 +140,7 @@
 	irq_handler_t irq_handler, void *irq_data)
 {
 	int rc = 0;
+	struct cam_cpas_private_soc *soc_private;
 
 	rc = cam_soc_util_get_dt_properties(soc_info);
 	if (rc) {
@@ -173,6 +174,12 @@
 		goto free_soc_private;
 	}
 
+	soc_private = soc_info->soc_private;
+	soc_private->soc_id = cam_soc_util_get_soc_id();
+	soc_private->hw_rev = cam_soc_util_get_hw_revision_node(soc_info);
+	CAM_DBG(CAM_CPAS, "soc id %d hw_rev %d",
+		soc_private->soc_id, soc_private->hw_rev);
+
 	return rc;
 
 free_soc_private:
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
index fe0187e..a93c063 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cam_cpas_soc.h
@@ -17,7 +17,6 @@
 #include "cam_cpas_hw.h"
 
 #define CAM_REGULATOR_LEVEL_MAX 16
-
 /**
  * struct cam_cpas_vdd_ahb_mapping : Voltage to ahb level mapping
  *
@@ -42,7 +41,8 @@
  * @axi_port_list_node : Node representing AXI Ports list
  * @num_vdd_ahb_mapping : Number of vdd to ahb level mapping supported
  * @vdd_ahb : AHB level mapping info for the supported vdd levels
- *
+ * @soc_id : SOC id
+ * @hw_rev : Camera hw revision
  */
 struct cam_cpas_private_soc {
 	const char *arch_compat;
@@ -54,6 +54,8 @@
 	struct device_node *axi_port_list_node;
 	uint32_t num_vdd_ahb_mapping;
 	struct cam_cpas_vdd_ahb_mapping vdd_ahb[CAM_REGULATOR_LEVEL_MAX];
+	uint32_t soc_id;
+	uint32_t hw_rev;
 };
 
 int cam_cpas_soc_init_resources(struct cam_hw_soc_info *soc_info,
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
index 0533ed8..8d08079 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.c
@@ -114,6 +114,15 @@
 		return -EINVAL;
 	}
 
+	rc = cam_common_util_get_string_index(soc_info->mem_block_name,
+		soc_info->num_mem_block, "core_top_csr_tcsr", &index);
+	if ((rc == 0) && (index < num_reg_map)) {
+		regbase_index[CAM_CPAS_REG_CSR_TCSR] = index;
+	} else {
+		CAM_DBG(CAM_CPAS, "regbase not found for CAMNOC, rc=%d, %d %d",
+			rc, index, num_reg_map);
+	}
+
 	return 0;
 }
 
@@ -456,6 +465,9 @@
 static int cam_cpastop_poweron(struct cam_hw_info *cpas_hw)
 {
 	int i;
+	struct cam_hw_soc_info *soc_info = &cpas_hw->soc_info;
+	struct cam_cpas *cpas_core = (struct cam_cpas *) cpas_hw->core_info;
+	struct cam_cpas_private_soc *soc_private = soc_info->soc_private;
 
 	cam_cpastop_reset_irq(cpas_hw);
 
@@ -478,6 +490,29 @@
 		}
 	}
 
+	if ((soc_private && soc_private->soc_id == SDM670_SOC_ID) &&
+		(soc_private->hw_rev == SDM670_V1_1)) {
+
+		struct cam_cpas_reg *reg_info;
+		int tcsr_index;
+		void __iomem *mem_base;
+
+		reg_info = &camnoc_info->errata_wa_list->tcsr_reg.
+			tcsr_conn_box_spare_0;
+		tcsr_index = cpas_core->regbase_index[CAM_CPAS_REG_CSR_TCSR];
+		if (tcsr_index == -1) {
+			CAM_DBG(CAM_CPAS, "index in not initialized");
+			return 0;
+		}
+		mem_base = soc_info->reg_map[tcsr_index].mem_base;
+
+		reg_info->value = TCSR_CONN_SET;
+		cam_io_w_mb(reg_info->value, mem_base + reg_info->offset);
+		CAM_DBG(CAM_CPAS, "tcsr(0x%lx) value %d",
+			(unsigned long int)mem_base + reg_info->offset,
+			cam_io_r_mb(mem_base + reg_info->offset));
+	}
+
 	return 0;
 }
 
@@ -489,6 +524,8 @@
 	int rc = 0;
 	struct cam_cpas_hw_errata_wa_list *errata_wa_list =
 		camnoc_info->errata_wa_list;
+	struct cam_cpas_private_soc *soc_private =
+		cpas_hw->soc_info.soc_private;
 
 	if (!errata_wa_list)
 		return 0;
@@ -512,6 +549,28 @@
 		}
 	}
 
+	if ((soc_private && soc_private->soc_id == SDM670_SOC_ID) &&
+		(soc_private->hw_rev == SDM670_V1_1)) {
+
+		struct cam_cpas_reg *reg_info;
+		int tcsr_index;
+		void __iomem *mem_base;
+
+		reg_info = &camnoc_info->errata_wa_list->tcsr_reg.
+			tcsr_conn_box_spare_0;
+		reg_info->value = TCSR_CONN_RESET;
+		tcsr_index = cpas_core->regbase_index[CAM_CPAS_REG_CSR_TCSR];
+		if (tcsr_index == -1) {
+			CAM_DBG(CAM_CPAS, "index in not initialized");
+			return 0;
+		}
+		mem_base = soc_info->reg_map[tcsr_index].mem_base;
+		cam_io_w_mb(reg_info->value, mem_base + reg_info->offset);
+		CAM_DBG(CAM_CPAS, "tcsr(0x%lx) value %d",
+			(unsigned long int)mem_base + reg_info->offset,
+			cam_io_r_mb(mem_base + reg_info->offset));
+	}
+
 	return rc;
 }
 
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.h b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.h
index 73f7e9b..080f6e6 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cam_cpastop_hw.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -162,14 +162,27 @@
 };
 
 /**
+ * struct cam_camnoc_tcsr_regs : Top control Status register
+ *
+ * @tcsr_conn_box_spare_0: spare register to select PriorityLvl
+ *         for IFE0 and IFE1 (HW workaround for SDM670 1.1)
+ *
+ */
+struct cam_camnoc_tcsr_regs {
+	struct cam_cpas_reg tcsr_conn_box_spare_0;
+};
+
+/**
  * struct cam_cpas_hw_errata_wa_list : List of HW Errata workaround info
  *
  * @camnoc_flush_slave_pending_trans: Errata workaround info for flushing
  *         camnoc slave pending transactions before turning off CPAS_TOP gdsc
+ * @tcsr_reg: HW workaround to select PriorityLvl for IFE0 and IFE(SDM670_1.1)
  *
  */
 struct cam_cpas_hw_errata_wa_list {
 	struct cam_cpas_hw_errata_wa camnoc_flush_slave_pending_trans;
+	struct cam_camnoc_tcsr_regs tcsr_reg;
 };
 
 /**
@@ -200,6 +213,7 @@
 	uint32_t errlog3_high;
 };
 
+
 /**
  * struct cam_camnoc_info : Overall CAMNOC settings info
  *
@@ -210,7 +224,6 @@
  * @irq_err_size: Array size of IRQ Error settings
  * @err_logger: Pointer to CAMNOC IRQ Error logger read registers
  * @errata_wa_list: HW Errata workaround info
- *
  */
 struct cam_camnoc_info {
 	struct cam_camnoc_specific *specific;
diff --git a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
index 3c572f0..0c7c799 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/cpas_top/cpastop_v170_110.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,6 +14,8 @@
 #define _CPASTOP_V170_110_H_
 
 #define TEST_IRQ_ENABLE 0
+#define TCSR_CONN_RESET 0x0
+#define TCSR_CONN_SET  0x3
 
 static struct cam_camnoc_irq_sbm cam_cpas110_irq_sbm = {
 	.sbm_enable = {
@@ -265,7 +267,7 @@
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.masked_value = 0,
 			.offset = 0x434, /* SPECIFIC_IFE02_PRIORITYLUT_HIGH */
-			.value = 0x66665555,
+			.value = 0x66666666,
 		},
 		.urgency = {
 			.enable = true,
@@ -313,7 +315,7 @@
 			.access_type = CAM_REG_TYPE_READ_WRITE,
 			.masked_value = 0,
 			.offset = 0x834, /* SPECIFIC_IFE13_PRIORITYLUT_HIGH */
-			.value = 0x66665555,
+			.value = 0x66666666,
 		},
 		.urgency = {
 			.enable = true,
@@ -528,6 +530,14 @@
 			.value = 0, /* expected to be 0 */
 		},
 	},
+	.tcsr_reg = {
+		.tcsr_conn_box_spare_0 = {
+			.enable = true,
+			.access_type = CAM_REG_TYPE_READ_WRITE,
+			.masked_value = 0,
+			.offset = 0xB3E4,
+		},
+	},
 };
 
 static struct cam_camnoc_info cam170_cpas110_camnoc_info = {
diff --git a/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h b/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h
index c844ef7..d1492fe 100644
--- a/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h
+++ b/drivers/media/platform/msm/camera/cam_cpas/include/cam_cpas_api.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -32,6 +32,7 @@
 enum cam_cpas_reg_base {
 	CAM_CPAS_REG_CPASTOP,
 	CAM_CPAS_REG_CAMNOC,
+	CAM_CPAS_REG_CSR_TCSR,
 	CAM_CPAS_REG_CAMSS,
 	CAM_CPAS_REG_MAX
 };
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
index 640c6f6..4d74dec 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1092,6 +1092,7 @@
 		CAM_ERR(CAM_FD, "Release cdm handle failed, handle=0x%x, rc=%d",
 			ctx_hw_private->cdm_handle, rc);
 
+	kfree(ctx_hw_private->cdm_cmd);
 	kfree(ctx_hw_private);
 	release_args->ctx_hw_private = NULL;
 
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
index 803da76..6d9d330 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_dev.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -22,6 +22,7 @@
 #include "cam_fd_hw_core.h"
 #include "cam_fd_hw_soc.h"
 #include "cam_fd_hw_v41.h"
+#include "cam_fd_hw_v501.h"
 
 static int cam_fd_hw_dev_probe(struct platform_device *pdev)
 {
@@ -193,6 +194,10 @@
 		.compatible = "qcom,fd41",
 		.data = &cam_fd_wrapper120_core410_info,
 	},
+	{
+		.compatible = "qcom,fd501",
+		.data = &cam_fd_wrapper200_core501_info,
+	},
 	{}
 };
 MODULE_DEVICE_TABLE(of, cam_fd_hw_dt_match);
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h
index 70448bb..78257a5 100644
--- a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v41.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -63,7 +63,7 @@
 		CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_RESET_DONE),
 	.qos_priority       = 4,
 	.qos_priority_level = 4,
-	.supported_modes    = CAM_FD_MODE_FACEDETECTION | CAM_FD_MODE_PYRAMID,
+	.supported_modes    = CAM_FD_MODE_FACEDETECTION,
 	.ro_mode_supported  = true,
 };
 
diff --git a/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h
new file mode 100644
index 0000000..44b9ab5
--- /dev/null
+++ b/drivers/media/platform/msm/camera/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_v501.h
@@ -0,0 +1,70 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _CAM_FD_HW_V501_H_
+#define _CAM_FD_HW_V501_H_
+
+static struct cam_fd_hw_static_info cam_fd_wrapper200_core501_info = {
+	.core_version = {
+		.major  = 5,
+		.minor  = 0,
+		.incr   = 1,
+	},
+	.wrapper_version = {
+		.major  = 2,
+		.minor  = 0,
+		.incr   = 0,
+	},
+	.core_regs = {
+		.version               = 0x38,
+		.control               = 0x0,
+		.result_cnt            = 0x4,
+		.result_addr           = 0x20,
+		.image_addr            = 0x24,
+		.work_addr             = 0x28,
+		.ro_mode               = 0x34,
+		.results_reg_base      = 0x400,
+		.raw_results_reg_base  = 0x800,
+	},
+	.wrapper_regs = {
+		.wrapper_version       = 0x0,
+		.cgc_disable           = 0x4,
+		.hw_stop               = 0x8,
+		.sw_reset              = 0x10,
+		.vbif_req_priority     = 0x20,
+		.vbif_priority_level   = 0x24,
+		.vbif_done_status      = 0x34,
+		.irq_mask              = 0x50,
+		.irq_status            = 0x54,
+		.irq_clear             = 0x58,
+	},
+	.results = {
+		.max_faces             = 35,
+		.per_face_entries      = 4,
+		.raw_results_available = true,
+		.raw_results_entries   = 512,
+	},
+	.enable_errata_wa = {
+		.single_irq_only         = true,
+		.ro_mode_enable_always   = true,
+		.ro_mode_results_invalid = true,
+	},
+	.irq_mask = CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_FRAME_DONE) |
+		CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_HALT_DONE) |
+		CAM_FD_IRQ_TO_MASK(CAM_FD_IRQ_RESET_DONE),
+	.qos_priority       = 4,
+	.qos_priority_level = 4,
+	.supported_modes    = CAM_FD_MODE_FACEDETECTION | CAM_FD_MODE_PYRAMID,
+	.ro_mode_supported  = true,
+};
+
+#endif /* _CAM_FD_HW_V501_H_ */
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
index aeec16c..4b5f22e 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/a5_hw/a5_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -207,37 +207,38 @@
 
 	if (!core_info->fw_elf) {
 		CAM_ERR(CAM_ICP, "Invalid elf size");
-		return -EINVAL;
+		rc = -EINVAL;
+		goto fw_download_failed;
 	}
 
 	fw_start = core_info->fw_elf->data;
 	rc = cam_icp_validate_fw(fw_start);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "fw elf validation failed");
-		return -EINVAL;
+		goto fw_download_failed;
 	}
 
 	rc = cam_icp_get_fw_size(fw_start, &fw_size);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "unable to get fw size");
-		return rc;
+		goto fw_download_failed;
 	}
 
 	if (core_info->fw_buf_len < fw_size) {
 		CAM_ERR(CAM_ICP, "mismatch in fw size: %u %llu",
 			fw_size, core_info->fw_buf_len);
-		goto fw_alloc_failed;
+		rc = -EINVAL;
+		goto fw_download_failed;
 	}
 
 	rc = cam_icp_program_fw(fw_start, core_info);
 	if (rc) {
 		CAM_ERR(CAM_ICP, "fw program is failed");
-		goto fw_program_failed;
+		goto fw_download_failed;
 	}
 
-	return 0;
-fw_program_failed:
-fw_alloc_failed:
+fw_download_failed:
+	release_firmware(core_info->fw_elf);
 	return rc;
 }
 
@@ -387,7 +388,6 @@
 	switch (cmd_type) {
 	case CAM_ICP_A5_CMD_FW_DOWNLOAD:
 		rc = cam_a5_download_fw(device_priv);
-
 		break;
 	case CAM_ICP_A5_CMD_SET_FW_BUF: {
 		struct cam_icp_a5_set_fw_buf_info *fw_buf_info = cmd_args;
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
index 1550a48..7be00ab 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.c
@@ -271,7 +271,7 @@
 	for (i = 0; i < CAM_ICP_CTX_MAX; i++) {
 		ctx_data = &hw_mgr->ctx_data[i];
 		mutex_lock(&ctx_data->ctx_mutex);
-		if ((ctx_data->state != CAM_ICP_CTX_STATE_FREE) &&
+		if ((ctx_data->state == CAM_ICP_CTX_STATE_ACQUIRED) &&
 			(ICP_DEV_TYPE_TO_CLK_TYPE(ctx_data->
 			icp_dev_acquire_info->dev_type) == clk_info->hw_type))
 			cam_icp_ctx_clk_info_init(ctx_data);
@@ -408,7 +408,7 @@
 	struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
 
 	spin_lock_irqsave(&icp_hw_mgr.hw_mgr_lock, flags);
-	task = cam_req_mgr_workq_get_task(icp_hw_mgr.msg_work);
+	task = cam_req_mgr_workq_get_task(icp_hw_mgr.timer_work);
 	if (!task) {
 		CAM_ERR(CAM_ICP, "no empty task");
 		spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
@@ -432,7 +432,7 @@
 	struct cam_req_mgr_timer *timer = (struct cam_req_mgr_timer *)data;
 
 	spin_lock_irqsave(&icp_hw_mgr.hw_mgr_lock, flags);
-	task = cam_req_mgr_workq_get_task(icp_hw_mgr.msg_work);
+	task = cam_req_mgr_workq_get_task(icp_hw_mgr.timer_work);
 	if (!task) {
 		CAM_ERR(CAM_ICP, "no empty task");
 		spin_unlock_irqrestore(&icp_hw_mgr.hw_mgr_lock, flags);
@@ -473,7 +473,7 @@
 	int rc = 0;
 
 	rc = crm_timer_init(&ctx_data->watch_dog,
-		2000, ctx_data, &cam_icp_ctx_timer_cb);
+		200, ctx_data, &cam_icp_ctx_timer_cb);
 	if (rc)
 		CAM_ERR(CAM_ICP, "Failed to start timer");
 
@@ -1314,32 +1314,6 @@
 	return rc;
 }
 
-static int cam_icp_mgr_process_cmd_and_free_mem(void *priv, void *data)
-{
-	int rc;
-	struct hfi_cmd_work_data *task_data = NULL;
-	struct cam_icp_hw_mgr *hw_mgr;
-
-	if (!data || !priv) {
-		CAM_ERR(CAM_ICP, "Invalid params%pK %pK", data, priv);
-		return -EINVAL;
-	}
-
-	hw_mgr = priv;
-	task_data = (struct hfi_cmd_work_data *)data;
-
-	if (!task_data->data) {
-		CAM_ERR(CAM_ICP, "Invalid data");
-		return -EINVAL;
-	}
-
-	rc = hfi_write_cmd(task_data->data);
-
-	kfree(task_data->data);
-	task_data->data = NULL;
-	return rc;
-}
-
 static int cam_icp_mgr_process_cmd(void *priv, void *data)
 {
 	int rc;
@@ -2214,14 +2188,13 @@
 	task_data->data = (void *)abort_cmd;
 	task_data->request_id = 0;
 	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
-	task->process_cb = cam_icp_mgr_process_cmd_and_free_mem;
+	task->process_cb = cam_icp_mgr_process_cmd;
 	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
 		CRM_TASK_PRIORITY_0);
 	if (rc) {
 		kfree(abort_cmd);
 		return rc;
 	}
-	CAM_DBG(CAM_ICP, "payload data = %pK", task_data->data);
 	CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK",
 		ctx_data->fw_handle, ctx_data);
 	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
@@ -2278,14 +2251,13 @@
 	task_data->data = (void *)destroy_cmd;
 	task_data->request_id = 0;
 	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
-	task->process_cb = cam_icp_mgr_process_cmd_and_free_mem;
+	task->process_cb = cam_icp_mgr_process_cmd;
 	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
 		CRM_TASK_PRIORITY_0);
 	if (rc) {
 		kfree(destroy_cmd);
 		return rc;
 	}
-	CAM_DBG(CAM_ICP, "payload data = %pK", task_data->data);
 	CAM_DBG(CAM_ICP, "fw_handle = %x ctx_data = %pK",
 		ctx_data->fw_handle, ctx_data);
 	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
@@ -2862,8 +2834,23 @@
 			packet->header.op_code & 0xff);
 		return -EINVAL;
 	}
-	CAM_DBG(CAM_ICP, "number of cmd/patch info: %u %u",
-			packet->num_cmd_buf, packet->num_patches);
+
+	if (packet->num_io_configs > IPE_IO_IMAGES_MAX) {
+		CAM_ERR(CAM_ICP, "Invalid number of io configs: %d %d",
+			IPE_IO_IMAGES_MAX, packet->num_io_configs);
+		return -EINVAL;
+	}
+
+	if (packet->num_cmd_buf > CAM_ICP_CTX_MAX_CMD_BUFFERS) {
+		CAM_ERR(CAM_ICP, "Invalid number of cmd buffers: %d %d",
+			CAM_ICP_CTX_MAX_CMD_BUFFERS, packet->num_cmd_buf);
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_ICP, "number of cmd/patch info: %u %u %u %u",
+			packet->num_cmd_buf,
+			packet->num_io_configs, IPE_IO_IMAGES_MAX,
+			packet->num_patches);
 	return 0;
 }
 
@@ -3560,7 +3547,7 @@
 
 static int cam_icp_mgr_send_ping(struct cam_icp_hw_ctx_data *ctx_data)
 {
-	struct hfi_cmd_ping_pkt *ping_pkt;
+	struct hfi_cmd_ping_pkt ping_pkt;
 	struct hfi_cmd_work_data *task_data;
 	unsigned long rem_jiffies;
 	int timeout = 5000;
@@ -3573,28 +3560,20 @@
 		return -ENOMEM;
 	}
 
-	ping_pkt = kzalloc(sizeof(struct hfi_cmd_ping_pkt), GFP_KERNEL);
-	if (!ping_pkt) {
-		rc = -ENOMEM;
-		return rc;
-	}
-	ping_pkt->size = sizeof(struct hfi_cmd_ping_pkt);
-	ping_pkt->pkt_type = HFI_CMD_SYS_PING;
-	ping_pkt->user_data = (uint64_t)ctx_data;
+	ping_pkt.size = sizeof(struct hfi_cmd_ping_pkt);
+	ping_pkt.pkt_type = HFI_CMD_SYS_PING;
+	ping_pkt.user_data = (uint64_t)ctx_data;
 	init_completion(&ctx_data->wait_complete);
 	task_data = (struct hfi_cmd_work_data *)task->payload;
-	task_data->data = (void *)ping_pkt;
+	task_data->data = (void *)&ping_pkt;
 	task_data->request_id = 0;
 	task_data->type = ICP_WORKQ_TASK_CMD_TYPE;
-	task->process_cb = cam_icp_mgr_process_cmd_and_free_mem;
+	task->process_cb = cam_icp_mgr_process_cmd;
 
 	rc = cam_req_mgr_workq_enqueue_task(task, &icp_hw_mgr,
 		CRM_TASK_PRIORITY_0);
-	if (rc) {
-		kfree(ping_pkt);
+	if (rc)
 		return rc;
-	}
-	CAM_DBG(CAM_ICP, "payload data = %pK", task_data->data);
 
 	rem_jiffies = wait_for_completion_timeout(&ctx_data->wait_complete,
 			msecs_to_jiffies((timeout)));
@@ -3772,10 +3751,6 @@
 		}
 	}
 
-	if (!hw_mgr->bps_ctxt_cnt || !hw_mgr->ipe_ctxt_cnt)
-		cam_icp_device_timer_start(hw_mgr);
-
-	cam_icp_ctx_timer_start(ctx_data);
 
 	rc = cam_icp_mgr_ipe_bps_resume(hw_mgr, ctx_data);
 	if (rc) {
@@ -3827,6 +3802,11 @@
 			(unsigned int)icp_dev_acquire_info->scratch_mem_size,
 			(unsigned int)ctx_data->fw_handle);
 	mutex_lock(&hw_mgr->hw_mgr_mutex);
+	/* Start device timer*/
+	if (((hw_mgr->bps_ctxt_cnt == 1) || (hw_mgr->ipe_ctxt_cnt == 1)))
+		cam_icp_device_timer_start(hw_mgr);
+	/* Start context timer*/
+	cam_icp_ctx_timer_start(ctx_data);
 	hw_mgr->ctxt_cnt++;
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 	CAM_DBG(CAM_ICP, "Acquire Done");
@@ -3842,7 +3822,6 @@
 send_ping_failed:
 	cam_icp_mgr_ipe_bps_power_collapse(hw_mgr, ctx_data, 0);
 ipe_bps_resume_failed:
-	cam_icp_ctx_timer_stop(&hw_mgr->ctx_data[ctx_id]);
 ubwc_cfg_failed:
 	if (!hw_mgr->ctxt_cnt)
 		cam_icp_mgr_icp_power_collapse(hw_mgr);
@@ -4034,17 +4013,24 @@
 	rc = cam_req_mgr_workq_create("icp_command_queue", ICP_WORKQ_NUM_TASK,
 		&icp_hw_mgr.cmd_work, CRM_WORKQ_USAGE_NON_IRQ);
 	if (rc) {
-		CAM_ERR(CAM_ICP, "unable to create a worker");
+		CAM_ERR(CAM_ICP, "unable to create a command worker");
 		goto cmd_work_failed;
 	}
 
 	rc = cam_req_mgr_workq_create("icp_message_queue", ICP_WORKQ_NUM_TASK,
 		&icp_hw_mgr.msg_work, CRM_WORKQ_USAGE_IRQ);
 	if (rc) {
-		CAM_ERR(CAM_ICP, "unable to create a worker");
+		CAM_ERR(CAM_ICP, "unable to create a message worker");
 		goto msg_work_failed;
 	}
 
+	rc = cam_req_mgr_workq_create("icp_timer_queue", ICP_WORKQ_NUM_TASK,
+		&icp_hw_mgr.timer_work, CRM_WORKQ_USAGE_IRQ);
+	if (rc) {
+		CAM_ERR(CAM_ICP, "unable to create a timer worker");
+		goto timer_work_failed;
+	}
+
 	icp_hw_mgr.cmd_work_data = (struct hfi_cmd_work_data *)
 		kzalloc(sizeof(struct hfi_cmd_work_data) * ICP_WORKQ_NUM_TASK,
 		GFP_KERNEL);
@@ -4057,9 +4043,15 @@
 	if (!icp_hw_mgr.msg_work_data)
 		goto msg_work_data_failed;
 
+	icp_hw_mgr.timer_work_data = (struct hfi_msg_work_data *)
+		kzalloc(sizeof(struct hfi_msg_work_data) * ICP_WORKQ_NUM_TASK,
+		GFP_KERNEL);
+	if (!icp_hw_mgr.timer_work_data)
+		goto timer_work_data_failed;
+
 	rc = cam_icp_hw_mgr_create_debugfs_entry();
 	if (rc)
-		goto msg_work_data_failed;
+		goto debugfs_create_failed;
 
 	for (i = 0; i < ICP_WORKQ_NUM_TASK; i++)
 		icp_hw_mgr.msg_work->task.pool[i].payload =
@@ -4069,10 +4061,20 @@
 		icp_hw_mgr.cmd_work->task.pool[i].payload =
 				&icp_hw_mgr.cmd_work_data[i];
 
+	for (i = 0; i < ICP_WORKQ_NUM_TASK; i++)
+		icp_hw_mgr.timer_work->task.pool[i].payload =
+				&icp_hw_mgr.timer_work_data[i];
 	return 0;
+
+debugfs_create_failed:
+	kfree(icp_hw_mgr.timer_work_data);
+timer_work_data_failed:
+	kfree(icp_hw_mgr.msg_work_data);
 msg_work_data_failed:
 	kfree(icp_hw_mgr.cmd_work_data);
 cmd_work_data_failed:
+	cam_req_mgr_workq_destroy(&icp_hw_mgr.timer_work);
+timer_work_failed:
 	cam_req_mgr_workq_destroy(&icp_hw_mgr.msg_work);
 msg_work_failed:
 	cam_req_mgr_workq_destroy(&icp_hw_mgr.cmd_work);
diff --git a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
index aac4a5e..cffec2e 100644
--- a/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_icp/icp_hw/icp_hw_mgr/cam_icp_hw_mgr.h
@@ -68,6 +68,8 @@
 #define CAM_ICP_CTX_STATE_ACQUIRED  0x2
 #define CAM_ICP_CTX_STATE_RELEASE   0x3
 
+#define CAM_ICP_CTX_MAX_CMD_BUFFERS 0x2
+
 /**
  * struct icp_hfi_mem_info
  * @qtbl: Memory info of queue table
@@ -253,11 +255,13 @@
  * @hfi_mem: Memory for hfi
  * @cmd_work: Work queue for hfi commands
  * @msg_work: Work queue for hfi messages
+ * @timer_work: Work queue for timer watchdog
  * @msg_buf: Buffer for message data from firmware
  * @dbg_buf: Buffer for debug data from firmware
  * @a5_complete: Completion info
  * @cmd_work_data: Pointer to command work queue task
  * @msg_work_data: Pointer to message work queue task
+ * @timer_work_data: Pointer to timer work queue task
  * @ctxt_cnt: Active context count
  * @ipe_ctxt_cnt: IPE Active context count
  * @bps_ctxt_cnt: BPS Active context count
@@ -298,11 +302,13 @@
 	struct icp_hfi_mem_info hfi_mem;
 	struct cam_req_mgr_core_workq *cmd_work;
 	struct cam_req_mgr_core_workq *msg_work;
+	struct cam_req_mgr_core_workq *timer_work;
 	uint32_t msg_buf[ICP_MSG_BUF_SIZE];
 	uint32_t dbg_buf[ICP_DBG_BUF_SIZE];
 	struct completion a5_complete;
 	struct hfi_cmd_work_data *cmd_work_data;
 	struct hfi_msg_work_data *msg_work_data;
+	struct hfi_msg_work_data *timer_work_data;
 	uint32_t ctxt_cnt;
 	uint32_t ipe_ctxt_cnt;
 	uint32_t bps_ctxt_cnt;
diff --git a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
index 6a294b2..fe42f70 100644
--- a/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
+++ b/drivers/media/platform/msm/camera/cam_isp/cam_isp_context.c
@@ -1187,7 +1187,9 @@
 				req_isp->fence_map_out[i].sync_id = -1;
 			}
 		}
+		spin_lock_bh(&ctx->lock);
 		list_add_tail(&req->list, &ctx->free_req_list);
+		spin_unlock_bh(&ctx->lock);
 	}
 
 	if (flush_req->type == CAM_REQ_MGR_FLUSH_TYPE_CANCEL_REQ &&
@@ -2221,7 +2223,7 @@
 }
 
 static int __cam_isp_ctx_stop_dev_in_activated_unlock(
-	struct cam_context *ctx)
+	struct cam_context *ctx, struct cam_start_stop_dev_cmd *stop_cmd)
 {
 	int rc = 0;
 	uint32_t i;
@@ -2240,6 +2242,7 @@
 	/* stop hw first */
 	if (ctx_isp->hw_ctx) {
 		stop.ctxt_to_hw_map = ctx_isp->hw_ctx;
+		stop.args = stop_cmd;
 		ctx->hw_mgr_intf->hw_stop(ctx->hw_mgr_intf->hw_mgr_priv,
 			&stop);
 	}
@@ -2288,7 +2291,7 @@
 {
 	int rc = 0;
 
-	__cam_isp_ctx_stop_dev_in_activated_unlock(ctx);
+	__cam_isp_ctx_stop_dev_in_activated_unlock(ctx, cmd);
 	ctx->state = CAM_CTX_ACQUIRED;
 	trace_cam_context_state("ISP", ctx);
 	return rc;
@@ -2299,7 +2302,7 @@
 {
 	int rc = 0;
 
-	rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx);
+	rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL);
 	if (rc)
 		CAM_ERR(CAM_ISP, "Stop device failed rc=%d", rc);
 
@@ -2369,7 +2372,8 @@
 
 	CAM_WARN(CAM_ISP,
 		"Received unlink in activated state. It's unexpected");
-	rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx);
+
+	rc = __cam_isp_ctx_stop_dev_in_activated_unlock(ctx, NULL);
 	if (rc)
 		CAM_WARN(CAM_ISP, "Stop device failed rc=%d", rc);
 
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
index 8c0c6d3..33dd8eb 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/cam_ife_hw_mgr.c
@@ -1686,6 +1686,7 @@
 	struct cam_hw_stop_args          *stop_args = stop_hw_args;
 	struct cam_ife_hw_mgr_res        *hw_mgr_res;
 	struct cam_ife_hw_mgr_ctx        *ctx;
+	enum cam_ife_csid_halt_cmd        csid_halt_type;
 	uint32_t                          i, master_base_idx = 0;
 
 	if (!hw_mgr_priv || !stop_hw_args) {
@@ -1701,6 +1702,12 @@
 	CAM_DBG(CAM_ISP, " Enter...ctx id:%d",
 		ctx->ctx_index);
 
+	/* Set the csid halt command */
+	if (!stop_args->args)
+		csid_halt_type = CAM_CSID_HALT_IMMEDIATELY;
+	else
+		csid_halt_type = CAM_CSID_HALT_AT_FRAME_BOUNDARY;
+
 	/* Note:stop resource will remove the irq mask from the hardware */
 
 	if (!ctx->num_base) {
@@ -1725,7 +1732,7 @@
 
 	/* Stop the master CSID path first */
 	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
-			master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+			master_base_idx, csid_halt_type);
 
 	/* stop rest of the CSID paths  */
 	for (i = 0; i < ctx->num_base; i++) {
@@ -1733,19 +1740,19 @@
 			continue;
 
 		cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_csid,
-			ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+			ctx->base[i].idx, csid_halt_type);
 	}
 
 	/* Stop the master CIDs first */
 	cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
-			master_base_idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+			master_base_idx, csid_halt_type);
 
 	/* stop rest of the CIDs  */
 	for (i = 0; i < ctx->num_base; i++) {
 		if (i == master_base_idx)
 			continue;
 		cam_ife_mgr_csid_stop_hw(ctx, &ctx->res_list_ife_cid,
-			ctx->base[i].idx, CAM_CSID_HALT_AT_FRAME_BOUNDARY);
+			ctx->base[i].idx, csid_halt_type);
 	}
 
 	if (cam_cdm_stream_off(ctx->cdm_handle))
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
index ff0c91f..1359f78 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/ife_csid_hw/cam_ife_csid_core.c
@@ -1037,16 +1037,23 @@
 
 static int cam_ife_csid_disable_hw(struct cam_ife_csid_hw *csid_hw)
 {
-	int rc = 0;
+	int rc = -EINVAL;
 	struct cam_hw_soc_info             *soc_info;
 	struct cam_ife_csid_reg_offset     *csid_reg;
 
+	/* Check for refcount */
+	if (!csid_hw->hw_info->open_count) {
+		CAM_WARN(CAM_ISP, "Unbalanced disable_hw");
+		return rc;
+	}
 
 	/*  Decrement ref Count */
-	if (csid_hw->hw_info->open_count)
-		csid_hw->hw_info->open_count--;
-	if (csid_hw->hw_info->open_count)
+	csid_hw->hw_info->open_count--;
+
+	if (csid_hw->hw_info->open_count) {
+		rc = 0;
 		return rc;
+	}
 
 	soc_info = &csid_hw->hw_info->soc_info;
 	csid_reg = csid_hw->csid_info->csid_reg;
@@ -2536,7 +2543,8 @@
 	/*wait for the path to halt */
 	for (i = 0; i < csid_stop->num_res; i++) {
 		res = csid_stop->node_res[i];
-		if (csid_stop->stop_cmd == CAM_CSID_HALT_AT_FRAME_BOUNDARY)
+		if (res->res_type == CAM_ISP_RESOURCE_PIX_PATH &&
+			csid_stop->stop_cmd == CAM_CSID_HALT_AT_FRAME_BOUNDARY)
 			rc = cam_ife_csid_res_wait_for_halt(csid_hw, res);
 		else
 			res->res_state = CAM_ISP_RESOURCE_STATE_INIT_HW;
diff --git a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
index f4aa5c3..3f843c3 100644
--- a/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
+++ b/drivers/media/platform/msm/camera/cam_isp/isp_hw_mgr/isp_hw/vfe_hw/vfe_top/cam_vfe_top_ver2.c
@@ -273,7 +273,8 @@
 	}
 
 	if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
-		CAM_DBG(CAM_ISP, "VFE:%d Not ready to set clocks yet :%d",
+		CAM_ERR_RATE_LIMIT(CAM_ISP,
+			"VFE:%d Not ready to set clocks yet :%d",
 			res->hw_intf->hw_idx,
 			hw_info->hw_state);
 	} else
@@ -321,7 +322,8 @@
 	}
 
 	if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
-		CAM_DBG(CAM_ISP, "VFE:%d Not ready to set BW yet :%d",
+		CAM_ERR_RATE_LIMIT(CAM_ISP,
+			"VFE:%d Not ready to set BW yet :%d",
 			res->hw_intf->hw_idx,
 			hw_info->hw_state);
 	} else
@@ -364,7 +366,8 @@
 	}
 
 	if (hw_info->hw_state != CAM_HW_STATE_POWER_UP) {
-		CAM_DBG(CAM_ISP, "VFE:%d Not ready to set BW yet :%d",
+		CAM_ERR_RATE_LIMIT(CAM_ISP,
+			"VFE:%d Not ready to set BW yet :%d",
 			res->hw_intf->hw_idx,
 			hw_info->hw_state);
 	} else {
@@ -517,6 +520,7 @@
 {
 	struct cam_vfe_top_ver2_priv            *top_priv;
 	struct cam_isp_resource_node            *mux_res;
+	struct cam_hw_info                      *hw_info = NULL;
 	int rc = 0;
 
 	if (!device_priv || !start_args) {
@@ -526,24 +530,33 @@
 
 	top_priv = (struct cam_vfe_top_ver2_priv *)device_priv;
 	mux_res = (struct cam_isp_resource_node *)start_args;
+	hw_info = (struct cam_hw_info  *)mux_res->hw_intf->hw_priv;
 
-	rc = cam_vfe_top_set_hw_clk_rate(top_priv);
-	if (rc) {
-		CAM_ERR(CAM_ISP, "set_hw_clk_rate failed, rc=%d", rc);
-		return rc;
-	}
+	if (hw_info->hw_state == CAM_HW_STATE_POWER_UP) {
+		rc = cam_vfe_top_set_hw_clk_rate(top_priv);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"set_hw_clk_rate failed, rc=%d", rc);
+			return rc;
+		}
 
-	rc = cam_vfe_top_set_axi_bw_vote(top_priv, true);
-	if (rc) {
-		CAM_ERR(CAM_ISP, "set_axi_bw_vote failed, rc=%d", rc);
-		return rc;
-	}
+		rc = cam_vfe_top_set_axi_bw_vote(top_priv, true);
+		if (rc) {
+			CAM_ERR(CAM_ISP,
+				"set_axi_bw_vote failed, rc=%d", rc);
+			return rc;
+		}
 
-	if (mux_res->start) {
-		rc = mux_res->start(mux_res);
+		if (mux_res->start) {
+			rc = mux_res->start(mux_res);
+		} else {
+			CAM_ERR(CAM_ISP,
+				"Invalid res id:%d", mux_res->res_id);
+			rc = -EINVAL;
+		}
 	} else {
-		CAM_ERR(CAM_ISP, "Invalid res id:%d", mux_res->res_id);
-		rc = -EINVAL;
+		CAM_ERR(CAM_ISP, "VFE HW not powered up");
+		rc = -EPERM;
 	}
 
 	return rc;
@@ -554,6 +567,7 @@
 {
 	struct cam_vfe_top_ver2_priv            *top_priv;
 	struct cam_isp_resource_node            *mux_res;
+	struct cam_hw_info                      *hw_info = NULL;
 	int i, rc = 0;
 
 	if (!device_priv || !stop_args) {
@@ -563,6 +577,7 @@
 
 	top_priv = (struct cam_vfe_top_ver2_priv   *)device_priv;
 	mux_res = (struct cam_isp_resource_node *)stop_args;
+	hw_info = (struct cam_hw_info  *)mux_res->hw_intf->hw_priv;
 
 	if (mux_res->res_id == CAM_ISP_HW_VFE_IN_CAMIF ||
 		(mux_res->res_id >= CAM_ISP_HW_VFE_IN_RDI0 &&
@@ -585,16 +600,23 @@
 			}
 		}
 
-		rc = cam_vfe_top_set_hw_clk_rate(top_priv);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "set_hw_clk_rate failed, rc=%d", rc);
-			return rc;
-		}
+		if (hw_info->hw_state == CAM_HW_STATE_POWER_UP) {
+			rc = cam_vfe_top_set_hw_clk_rate(top_priv);
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"set_hw_clk_rate failed, rc=%d", rc);
+				return rc;
+			}
 
-		rc = cam_vfe_top_set_axi_bw_vote(top_priv, true);
-		if (rc) {
-			CAM_ERR(CAM_ISP, "set_axi_bw_vote failed, rc=%d", rc);
-			return rc;
+			rc = cam_vfe_top_set_axi_bw_vote(top_priv, true);
+			if (rc) {
+				CAM_ERR(CAM_ISP,
+					"set_axi_bw_vote failed, rc=%d", rc);
+				return rc;
+			}
+		} else {
+			CAM_ERR(CAM_ISP, "VFE HW not powered up");
+			rc = -EPERM;
 		}
 	}
 
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
index 6e2e7e9..7bc505f 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -924,6 +924,7 @@
 	if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 0) {
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
 		CAM_ERR(CAM_JPEG, "Error Unbalanced deinit");
+		kfree(ctx_data->cdm_cmd);
 		return -EFAULT;
 	}
 
@@ -943,9 +944,12 @@
 	rc = cam_jpeg_mgr_release_ctx(hw_mgr, ctx_data);
 	if (rc) {
 		mutex_unlock(&hw_mgr->hw_mgr_mutex);
+		CAM_ERR(CAM_JPEG, "JPEG release ctx failed");
+		kfree(ctx_data->cdm_cmd);
 		return -EINVAL;
 	}
 
+	kfree(ctx_data->cdm_cmd);
 	CAM_DBG(CAM_JPEG, "handle %llu", ctx_data);
 
 	return rc;
@@ -999,7 +1003,7 @@
 			sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
 	if (!ctx_data->cdm_cmd) {
 		rc = -ENOMEM;
-		goto acq_cdm_hdl_failed;
+		goto jpeg_release_ctx;
 	}
 
 	mutex_lock(&ctx_data->ctx_mutex);
@@ -1046,20 +1050,8 @@
 		hw_mgr->cdm_info[dev_type][0].ref_cnt++;
 	}
 
-	ctx_data->cdm_cmd_chbase =
-		kzalloc(((sizeof(struct cam_cdm_bl_request)) +
-			(2 * sizeof(struct cam_cdm_bl_cmd))), GFP_KERNEL);
-	if (!ctx_data->cdm_cmd_chbase) {
-		rc = -ENOMEM;
-		goto start_cdm_hdl_failed;
-	}
 	size = hw_mgr->cdm_info[dev_type][0].
 		cdm_ops->cdm_required_size_changebase();
-	ctx_data->cmd_chbase_buf_addr = kzalloc(size*4, GFP_KERNEL);
-	if (!ctx_data->cdm_cmd_chbase) {
-		rc = -ENOMEM;
-		goto start_cdm_hdl_failed;
-	}
 
 	if (hw_mgr->cdm_info[dev_type][0].ref_cnt == 1)
 		if (cam_cdm_stream_on(
@@ -1101,6 +1093,7 @@
 	hw_mgr->cdm_info[dev_type][0].ref_cnt--;
 acq_cdm_hdl_failed:
 	kfree(ctx_data->cdm_cmd);
+jpeg_release_ctx:
 	cam_jpeg_mgr_release_ctx(hw_mgr, ctx_data);
 	mutex_unlock(&hw_mgr->hw_mgr_mutex);
 
diff --git a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
index dce47d2..5e10167 100644
--- a/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
+++ b/drivers/media/platform/msm/camera/cam_jpeg/jpeg_hw/cam_jpeg_hw_mgr.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -95,8 +95,6 @@
  * @in_use: Flag for context usage
  * @wait_complete: Completion info
  * @cdm_cmd: Cdm cmd submitted for that context.
- * @cdm_cmd_chbase: Change base cdm command from context
- * @cmd_chbase_buf_addr : Change base cmd buf address
  */
 struct cam_jpeg_hw_ctx_data {
 	void *context_priv;
@@ -106,8 +104,6 @@
 	bool in_use;
 	struct completion wait_complete;
 	struct cam_cdm_bl_request *cdm_cmd;
-	struct cam_cdm_bl_request *cdm_cmd_chbase;
-	uint32_t *cmd_chbase_buf_addr;
 };
 
 /**
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
index 262e49c..4f30f56 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/cam_csiphy_core.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -71,9 +71,9 @@
 			csiphy_reset_reg[i].reg_addr);
 
 		usleep_range(csiphy_dev->ctrl_reg->
-			csiphy_reset_reg[i].delay * 100,
+			csiphy_reset_reg[i].delay * 1000,
 			csiphy_dev->ctrl_reg->
-			csiphy_reset_reg[i].delay * 100 + 1000);
+			csiphy_reset_reg[i].delay * 1000 + 10);
 	}
 }
 
@@ -285,6 +285,10 @@
 					csiphybase +
 					csiphy_dev->ctrl_reg->
 					csiphy_common_reg[i].reg_addr);
+				usleep_range(csiphy_dev->ctrl_reg->
+					csiphy_common_reg[i].delay*1000,
+					csiphy_dev->ctrl_reg->
+					csiphy_common_reg[i].delay*1000 + 10);
 			break;
 			case CSIPHY_DEFAULT_PARAMS:
 				cam_io_w_mb(csiphy_dev->ctrl_reg->
@@ -292,6 +296,10 @@
 					csiphybase +
 					csiphy_dev->ctrl_reg->
 					csiphy_common_reg[i].reg_addr);
+				usleep_range(csiphy_dev->ctrl_reg->
+					csiphy_common_reg[i].delay*1000,
+					csiphy_dev->ctrl_reg->
+					csiphy_common_reg[i].delay*1000 + 10);
 			break;
 			default:
 			break;
@@ -506,6 +514,13 @@
 		bridge_params.media_entity_flag = 0;
 		bridge_params.priv = csiphy_dev;
 
+		if (csiphy_acq_params.combo_mode >= 2) {
+			CAM_ERR(CAM_CSIPHY, "Invalid combo_mode %d",
+				csiphy_acq_params.combo_mode);
+			rc = -EINVAL;
+			goto release_mutex;
+		}
+
 		csiphy_acq_dev.device_handle =
 			cam_create_device_hdl(&bridge_params);
 		csiphy_dev->bridge_intf.
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
index 2977834..3f743fc 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_csiphy/include/cam_csiphy_1_0_hwreg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,8 +19,8 @@
 	.mipi_csiphy_interrupt_status0_addr = 0x8B0,
 	.mipi_csiphy_interrupt_clear0_addr = 0x858,
 	.mipi_csiphy_glbl_irq_cmd_addr = 0x828,
-	.csiphy_common_array_size = 3,
-	.csiphy_reset_array_size = 3,
+	.csiphy_common_array_size = 5,
+	.csiphy_reset_array_size = 5,
 	.csiphy_2ph_config_array_size = 14,
 	.csiphy_3ph_config_array_size = 19,
 };
@@ -29,12 +29,16 @@
 	{0x0814, 0x00, 0x00, CSIPHY_LANE_ENABLE},
 	{0x0818, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x081C, 0x02, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 };
 
 struct csiphy_reg_t csiphy_reset_reg_1_0[] = {
-	{0x0814, 0x00, 0x50, CSIPHY_LANE_ENABLE},
+	{0x0814, 0x00, 0x05, CSIPHY_LANE_ENABLE},
 	{0x0818, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 	{0x081C, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x01, 0x01, CSIPHY_DEFAULT_PARAMS},
+	{0x0800, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
 };
 
 struct csiphy_reg_t csiphy_irq_reg_1_0[] = {
@@ -148,7 +152,7 @@
 		{0x0008, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
 		{0x0010, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0038, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
-		{0x0060, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+		{0x0060, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0064, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
 	},
 	{
@@ -164,7 +168,7 @@
 		{0x070C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0710, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0738, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
-		{0x0760, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+		{0x0760, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0764, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
 	},
 	{
@@ -179,7 +183,7 @@
 		{0x0208, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
 		{0x0210, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0238, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
-		{0x0260, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+		{0x0260, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0264, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
 	},
 	{
@@ -194,7 +198,7 @@
 		{0x0408, 0x00, 0x00, CSIPHY_SETTLE_CNT_LOWER_BYTE},
 		{0x0410, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0438, 0xFE, 0x00, CSIPHY_DEFAULT_PARAMS},
-		{0x0460, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+		{0x0460, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0464, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
 	},
 	{
@@ -210,7 +214,7 @@
 		{0x060C, 0xA5, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0610, 0x52, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0638, 0x1F, 0x00, CSIPHY_DEFAULT_PARAMS},
-		{0x0660, 0x00, 0x00, CSIPHY_DEFAULT_PARAMS},
+		{0x0660, 0x01, 0x00, CSIPHY_DEFAULT_PARAMS},
 		{0x0664, 0x7F, 0x00, CSIPHY_DEFAULT_PARAMS},
 	},
 };
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
index d5bb1b0..9e082cd 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor/cam_sensor_core.c
@@ -714,6 +714,9 @@
 		}
 
 		s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE;
+		CAM_INFO(CAM_SENSOR,
+			"CAM_ACQUIRE_DEV Success, sensor_id:0x%x",
+			s_ctrl->sensordata->slave_info.sensor_id);
 	}
 		break;
 	case CAM_RELEASE_DEV: {
@@ -751,6 +754,9 @@
 		s_ctrl->bridge_intf.session_hdl = -1;
 
 		s_ctrl->sensor_state = CAM_SENSOR_INIT;
+		CAM_INFO(CAM_SENSOR,
+			"CAM_RELEASE_DEV Success, sensor_id:0x%x",
+			s_ctrl->sensordata->slave_info.sensor_id);
 	}
 		break;
 	case CAM_QUERY_CAP: {
@@ -786,6 +792,9 @@
 			}
 		}
 		s_ctrl->sensor_state = CAM_SENSOR_START;
+		CAM_INFO(CAM_SENSOR,
+			"CAM_START_DEV Success, sensor_id:0x%x",
+			s_ctrl->sensordata->slave_info.sensor_id);
 	}
 		break;
 	case CAM_STOP_DEV: {
@@ -809,6 +818,9 @@
 
 		cam_sensor_release_resource(s_ctrl);
 		s_ctrl->sensor_state = CAM_SENSOR_ACQUIRE;
+		CAM_INFO(CAM_SENSOR,
+			"CAM_STOP_DEV Success, sensor_id:0x%x",
+			s_ctrl->sensordata->slave_info.sensor_id);
 	}
 		break;
 	case CAM_CONFIG_DEV: {
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c
index 131b0ae..07b390b 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -468,6 +468,63 @@
 	return rc;
 }
 
+int32_t cam_spi_write_seq(struct camera_io_master *client,
+	uint32_t addr, uint8_t *data,
+	enum camera_sensor_i2c_type addr_type, uint32_t num_byte)
+{
+	struct cam_camera_spi_inst *pg =
+		&client->spi_client->cmd_tbl.page_program;
+	const uint32_t page_size = client->spi_client->page_size;
+	uint8_t header_len = sizeof(pg->opcode) + pg->addr_len + pg->dummy_len;
+	uint16_t len;
+	uint32_t cur_len, end;
+	char *tx, *pdata = data;
+	int rc = -EINVAL;
+
+	if ((addr_type >= CAMERA_SENSOR_I2C_TYPE_MAX) ||
+		(addr_type <= CAMERA_SENSOR_I2C_TYPE_INVALID))
+		return rc;
+    /* single page write */
+	if ((addr % page_size) + num_byte <= page_size) {
+		len = header_len + num_byte;
+		tx = kmalloc(len, GFP_KERNEL | GFP_DMA);
+		if (!tx)
+			goto NOMEM;
+		rc = cam_spi_page_program(client, addr, data, addr_type,
+			num_byte, tx);
+		if (rc < 0)
+			goto ERROR;
+		goto OUT;
+	}
+	/* multi page write */
+	len = header_len + page_size;
+	tx = kmalloc(len, GFP_KERNEL | GFP_DMA);
+	if (!tx)
+		goto NOMEM;
+	while (num_byte) {
+		end = min(page_size, (addr % page_size) + num_byte);
+		cur_len = end - (addr % page_size);
+		CAM_ERR(CAM_SENSOR, "Addr: 0x%x curr_len: 0x%x pgSize: %d",
+			addr, cur_len, page_size);
+		rc = cam_spi_page_program(client, addr, pdata, addr_type,
+			cur_len, tx);
+		if (rc < 0)
+			goto ERROR;
+		addr += cur_len;
+		pdata += cur_len;
+		num_byte -= cur_len;
+	}
+	goto OUT;
+NOMEM:
+	pr_err("%s: memory allocation failed\n", __func__);
+	return -ENOMEM;
+ERROR:
+	pr_err("%s: error write\n", __func__);
+OUT:
+	kfree(tx);
+	return rc;
+}
+
 int cam_spi_write_table(struct camera_io_master *client,
 	struct cam_sensor_i2c_reg_setting *write_setting)
 {
@@ -508,3 +565,35 @@
 	addr_type = client_addr_type;
 	return rc;
 }
+
+int cam_spi_erase(struct camera_io_master *client,
+	uint32_t addr, enum camera_sensor_i2c_type addr_type,
+	uint32_t size) {
+	struct cam_camera_spi_inst *se = &client->spi_client->cmd_tbl.erase;
+	int rc = 0;
+	uint32_t cur;
+	uint32_t end = addr + size;
+	uint32_t erase_size = client->spi_client->erase_size;
+
+	end = addr + size;
+	for (cur = rounddown(addr, erase_size); cur < end; cur += erase_size) {
+		CAM_ERR(CAM_SENSOR, "%s: erasing 0x%x size: %d\n",
+			__func__, cur, erase_size);
+		rc = cam_spi_write_enable(client, addr_type);
+		if (rc < 0)
+			return rc;
+		rc = cam_spi_tx_helper(client, se, cur, NULL, addr_type, 0,
+			NULL, NULL);
+		if (rc < 0) {
+			CAM_ERR(CAM_SENSOR, "%s: erase failed\n", __func__);
+			return rc;
+		}
+		rc = cam_spi_wait(client, se, addr_type);
+		if (rc < 0) {
+			CAM_ERR(CAM_SENSOR, "%s: erase timedout\n", __func__);
+			return rc;
+		}
+	}
+
+	return rc;
+}
diff --git a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h
index ec1bede..a63bff2 100644
--- a/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h
+++ b/drivers/media/platform/msm/camera/cam_sensor_module/cam_sensor_io/cam_sensor_spi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -99,4 +99,12 @@
 int cam_spi_write_table(struct camera_io_master *client,
 	struct cam_sensor_i2c_reg_setting *write_setting);
 
+int cam_spi_erase(struct camera_io_master *client,
+	uint32_t addr, enum camera_sensor_i2c_type addr_type,
+	uint32_t size);
+
+int32_t cam_spi_write_seq(struct camera_io_master *client,
+	uint32_t addr, uint8_t *data,
+	enum camera_sensor_i2c_type addr_type, uint32_t num_byte);
+
 #endif
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
index 0b1896f..d0a13ab 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.c
@@ -15,8 +15,62 @@
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/of_gpio.h>
+#include <soc/qcom/socinfo.h>
 #include "cam_soc_util.h"
 #include "cam_debug_util.h"
+#include <linux/nvmem-consumer.h>
+
+uint32_t cam_soc_util_get_soc_id(void)
+{
+	return socinfo_get_id();
+}
+#if defined(CONFIG_NVMEM) && defined(CONFIG_QCOM_QFPROM)
+uint32_t cam_soc_util_get_hw_revision_node(struct cam_hw_soc_info *soc_info)
+{
+	struct nvmem_cell *cell;
+	ssize_t len;
+	uint32_t *buf, hw_rev;
+	struct platform_device *pdev;
+
+	pdev = soc_info->pdev;
+	/* read the soc hw revision and select revision node */
+	cell = nvmem_cell_get(&pdev->dev, "minor_rev");
+	if (IS_ERR_OR_NULL(cell)) {
+		if (PTR_ERR(cell) == -EPROBE_DEFER) {
+			CAM_ERR(CAM_UTIL, "Err to get nvmem cell: ret=%ld",
+				PTR_ERR(cell));
+			return -EINVAL;
+		}
+		CAM_ERR(CAM_UTIL, "No DTS entry");
+		return 0;
+	}
+
+	if (PTR_ERR(cell) == -ENOENT) {
+		CAM_DBG(CAM_UTIL, "nvme cell not found");
+		return 0;
+	}
+
+	buf = nvmem_cell_read(cell, &len);
+	nvmem_cell_put(cell);
+
+	if (IS_ERR_OR_NULL(buf)) {
+		CAM_ERR(CAM_UTIL, "Unable to read nvmem cell: ret=%ld",
+			PTR_ERR(buf));
+		return -EINVAL;
+	}
+
+	CAM_DBG(CAM_UTIL, "hw_rev = %u", *buf);
+	hw_rev = (*buf >> 28) & 0x3;
+	kfree(buf);
+
+	return hw_rev;
+}
+#else
+uint32_t cam_soc_util_get_hw_revision_node(struct cam_hw_soc_info *soc_info)
+{
+	return 0;
+}
+#endif
 
 int cam_soc_util_get_level_from_string(const char *string,
 	enum cam_vote_level *level)
diff --git a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
index 4b57d54..1f2d46d 100644
--- a/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
+++ b/drivers/media/platform/msm/camera/cam_utils/cam_soc_util.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -40,6 +40,11 @@
 /* maximum number of device clock */
 #define CAM_SOC_MAX_CLK             32
 
+/* soc id */
+#define SDM670_SOC_ID 336
+
+/* Minor Version */
+#define SDM670_V1_1 0x1
 /**
  * enum cam_vote_level - Enum for voting level
  *
@@ -615,5 +620,23 @@
 
 int cam_soc_util_clk_enable_default(struct cam_hw_soc_info *soc_info,
 	enum cam_vote_level clk_level);
+/**
+ * cam_soc_util_get_soc_id()
+ *
+ * @brief:           Read soc id
+ *
+ * @return           SOC id
+ */
+uint32_t cam_soc_util_get_soc_id(void);
 
+/**
+ * cam_soc_util_get_hw_revision_node()
+ *
+ * @brief:           Camera HW ID
+ *
+ * @soc_info:        Device soc information
+ *
+ * @return           HW id
+ */
+uint32_t cam_soc_util_get_hw_revision_node(struct cam_hw_soc_info *soc_info);
 #endif /* _CAM_SOC_UTIL_H_ */
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
index cc1ef7a..56cce54 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp.h
@@ -19,9 +19,6 @@
 #include <linux/io.h>
 #include <linux/list.h>
 #include <linux/delay.h>
-#ifdef CONFIG_MSM_AVTIMER
-#include <linux/avtimer_kernel.h>
-#endif
 #include <media/v4l2-subdev.h>
 #include <media/msmb_isp.h>
 #include <linux/msm-bus.h>
@@ -858,8 +855,6 @@
 	struct platform_device *child_list[VFE_SD_HW_MAX];
 	struct msm_vfe_common_subdev *common_sd;
 };
-
 int vfe_hw_probe(struct platform_device *pdev);
 void msm_isp_update_last_overflow_ab_ib(struct vfe_device *vfe_dev);
-
 #endif
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 de7d9ed..5fff66e 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp40.c
@@ -1106,8 +1106,10 @@
 				fe_cfg->stream_id);
 		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
 
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
index bc0a31f..a9ff454 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp44.c
@@ -891,8 +891,11 @@
 			vfe_dev->buf_mgr, fe_cfg->session_id,
 			fe_cfg->stream_id);
 		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
+
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0) {
 			pr_err("%s: No fetch buffer\n", __func__);
 			return -EINVAL;
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
index b319738..0239fe7 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp46.c
@@ -830,8 +830,10 @@
 			fe_cfg->stream_id);
 		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
 
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
index e03f76f..d1a95cd 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp47.c
@@ -1151,8 +1151,10 @@
 			fe_cfg->stream_id);
 		vfe_dev->fetch_engine_info.bufq_handle = bufq_handle;
 
+		mutex_lock(&vfe_dev->buf_mgr->lock);
 		rc = vfe_dev->buf_mgr->ops->get_buf_by_index(
 			vfe_dev->buf_mgr, bufq_handle, fe_cfg->buf_idx, &buf);
+		mutex_unlock(&vfe_dev->buf_mgr->lock);
 		if (rc < 0 || !buf) {
 			pr_err("%s: No fetch buffer rc= %d buf= %pK\n",
 				__func__, rc, buf);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
index fab2623f..73cd6a2 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.c
@@ -20,6 +20,9 @@
 #define HANDLE_TO_IDX(handle) (handle & 0xFF)
 #define ISP_SOF_DEBUG_COUNT 0
 
+#ifdef CONFIG_MSM_AVTIMER
+static struct avtimer_fptr_t avtimer_func;
+#endif
 static void msm_isp_reload_ping_pong_offset(
 		struct msm_vfe_axi_stream *stream_info);
 
@@ -1182,10 +1185,34 @@
 }
 
 #ifdef CONFIG_MSM_AVTIMER
+/**
+ * msm_isp_set_avtimer_fptr() - Set avtimer function pointer
+ * @avtimer: struct of type avtimer_fptr_t to hold function pointer.
+ *
+ * Initialize the function pointers sent by the avtimer driver
+ *
+ */
+void msm_isp_set_avtimer_fptr(struct avtimer_fptr_t avtimer)
+{
+	avtimer_func.fptr_avtimer_open   = avtimer.fptr_avtimer_open;
+	avtimer_func.fptr_avtimer_enable = avtimer.fptr_avtimer_enable;
+	avtimer_func.fptr_avtimer_get_time = avtimer.fptr_avtimer_get_time;
+}
+EXPORT_SYMBOL(msm_isp_set_avtimer_fptr);
+
 void msm_isp_start_avtimer(void)
 {
-	avcs_core_open();
-	avcs_core_disable_power_collapse(1);
+	if (avtimer_func.fptr_avtimer_open &&
+			avtimer_func.fptr_avtimer_enable) {
+		avtimer_func.fptr_avtimer_open();
+		avtimer_func.fptr_avtimer_enable(1);
+	}
+}
+void msm_isp_stop_avtimer(void)
+{
+	if (avtimer_func.fptr_avtimer_enable) {
+		avtimer_func.fptr_avtimer_enable(0);
+	}
 }
 
 void msm_isp_get_avtimer_ts(
@@ -1195,19 +1222,21 @@
 	uint32_t avtimer_usec = 0;
 	uint64_t avtimer_tick = 0;
 
-	rc = avcs_core_query_timer(&avtimer_tick);
-	if (rc < 0) {
-		pr_err_ratelimited("%s: Error: Invalid AVTimer Tick, rc=%d\n",
-			   __func__, rc);
-		/* In case of error return zero AVTimer Tick Value */
-		time_stamp->vt_time.tv_sec = 0;
-		time_stamp->vt_time.tv_usec = 0;
-	} else {
-		avtimer_usec = do_div(avtimer_tick, USEC_PER_SEC);
-		time_stamp->vt_time.tv_sec = (uint32_t)(avtimer_tick);
-		time_stamp->vt_time.tv_usec = avtimer_usec;
-		pr_debug("%s: AVTimer TS = %u:%u\n", __func__,
-			(uint32_t)(avtimer_tick), avtimer_usec);
+	if (avtimer_func.fptr_avtimer_get_time) {
+		rc = avtimer_func.fptr_avtimer_get_time(&avtimer_tick);
+		if (rc < 0) {
+			pr_err_ratelimited("%s: Error: Invalid AVTimer Tick, rc=%d\n",
+				   __func__, rc);
+			/* In case of error return zero AVTimer Tick Value */
+			time_stamp->vt_time.tv_sec = 0;
+			time_stamp->vt_time.tv_usec = 0;
+		} else {
+			avtimer_usec = do_div(avtimer_tick, USEC_PER_SEC);
+			time_stamp->vt_time.tv_sec = (uint32_t)(avtimer_tick);
+			time_stamp->vt_time.tv_usec = avtimer_usec;
+			pr_debug("%s: AVTimer TS = %u:%u\n", __func__,
+				(uint32_t)(avtimer_tick), avtimer_usec);
+		}
 	}
 }
 #else
@@ -1219,10 +1248,14 @@
 void msm_isp_get_avtimer_ts(
 		struct msm_isp_timestamp *time_stamp)
 {
-	pr_err_ratelimited("%s: Error: AVTimer driver not available\n",
+	struct timespec ts;
+
+	pr_debug("%s: AVTimer driver not available using system time\n",
 		__func__);
-	time_stamp->vt_time.tv_sec = 0;
-	time_stamp->vt_time.tv_usec = 0;
+
+	get_monotonic_boottime(&ts);
+	time_stamp->vt_time.tv_sec    = ts.tv_sec;
+	time_stamp->vt_time.tv_usec   = ts.tv_nsec/1000;
 }
 #endif
 
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
index c0ba7ab..5dcd967 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_axi_util.h
@@ -28,6 +28,7 @@
 
 int msm_isp_request_axi_stream(struct vfe_device *vfe_dev, void *arg);
 void msm_isp_start_avtimer(void);
+void msm_isp_stop_avtimer(void);
 void msm_isp_get_avtimer_ts(struct msm_isp_timestamp *time_stamp);
 int msm_isp_cfg_axi_stream(struct vfe_device *vfe_dev, void *arg);
 int msm_isp_release_axi_stream(struct vfe_device *vfe_dev, void *arg);
diff --git a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
index 9959f70..290bdc0 100644
--- a/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
+++ b/drivers/media/platform/msm/camera_v2/isp/msm_isp_util.c
@@ -2348,7 +2348,7 @@
 #ifdef CONFIG_MSM_AVTIMER
 static void msm_isp_end_avtimer(void)
 {
-	avcs_core_disable_power_collapse(0);
+	msm_isp_stop_avtimer();
 }
 #else
 static void msm_isp_end_avtimer(void)
diff --git a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
index 769a9a5..625a0db 100644
--- a/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
+++ b/drivers/media/platform/msm/camera_v2/sensor/actuator/msm_actuator.c
@@ -57,6 +57,11 @@
 
 	CDBG("Enter\n");
 
+	if (a_ctrl->i2c_reg_tbl == NULL) {
+		pr_err("failed. i2c reg table is NULL");
+		return -EFAULT;
+	}
+
 	if (a_ctrl->curr_step_pos != 0) {
 		a_ctrl->i2c_tbl_index = 0;
 		a_ctrl->func_tbl->actuator_parse_i2c_params(a_ctrl,
@@ -99,7 +104,7 @@
 	}
 
 	if (a_ctrl->i2c_reg_tbl == NULL) {
-		pr_err("failed. i2c reg tabl is NULL");
+		pr_err("failed. i2c reg table is NULL");
 		return;
 	}
 
@@ -526,6 +531,11 @@
 
 	CDBG("Enter\n");
 
+	if (a_ctrl->i2c_reg_tbl == NULL) {
+		pr_err("failed. i2c reg table is NULL");
+		return -EFAULT;
+	}
+
 	if (copy_from_user(&ringing_params_kernel,
 		&(move_params->ringing_params[0]),
 		sizeof(struct damping_params_t))) {
@@ -599,6 +609,10 @@
 		pr_err("Invalid direction = %d\n", dir);
 		return -EFAULT;
 	}
+	if (a_ctrl->i2c_reg_tbl == NULL) {
+		pr_err("failed. i2c reg table is NULL");
+		return -EFAULT;
+	}
 	if (dest_step_pos > a_ctrl->total_steps) {
 		pr_err("Step pos greater than total steps = %d\n",
 		dest_step_pos);
@@ -719,6 +733,10 @@
 		pr_err("Invalid direction = %d\n", dir);
 		return -EFAULT;
 	}
+	if (a_ctrl->i2c_reg_tbl == NULL) {
+		pr_err("failed. i2c reg table is NULL");
+		return -EFAULT;
+	}
 	if (dest_step_pos > a_ctrl->total_steps) {
 		pr_err("Step pos greater than total steps = %d\n",
 		dest_step_pos);
@@ -1182,7 +1200,8 @@
 	}
 
 	if (!a_ctrl || !a_ctrl->func_tbl ||
-		!a_ctrl->func_tbl->actuator_parse_i2c_params) {
+		!a_ctrl->func_tbl->actuator_parse_i2c_params ||
+		!a_ctrl->i2c_reg_tbl) {
 		pr_err("failed. NULL actuator pointers.");
 		return -EFAULT;
 	}
@@ -1294,12 +1313,10 @@
 
 	a_ctrl->region_size = set_info->af_tuning_params.region_size;
 	a_ctrl->pwd_step = set_info->af_tuning_params.pwd_step;
-	a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
 
 	if (copy_from_user(&a_ctrl->region_params,
 		(void __user *)set_info->af_tuning_params.region_params,
 		a_ctrl->region_size * sizeof(struct region_params_t))) {
-		a_ctrl->total_steps = 0;
 		pr_err("Error copying region_params\n");
 		return -EFAULT;
 	}
@@ -1341,6 +1358,7 @@
 		return -ENOMEM;
 	}
 
+	a_ctrl->total_steps = set_info->af_tuning_params.total_steps;
 	if (copy_from_user(&a_ctrl->reg_tbl,
 		(void __user *)set_info->actuator_params.reg_tbl_params,
 		a_ctrl->reg_tbl_size *
diff --git a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
index 9d92acf..6dac1ed 100644
--- a/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
+++ b/drivers/media/platform/msm/sde/rotator/sde_rotator_base.c
@@ -217,12 +217,18 @@
 	SDEROT_DBG("w:%d h:%d fps:%d pixfmt:%8.8x yuv:%d res:%llu rd:%d\n",
 		width, height, fps, pixfmt, is_yuv, res, is_rd);
 
+	if (!is_yuv)
+		goto exit;
+
+	/*
+	 * If (total_source_pixels <= 62208000  && YUV) -> RD/WROT=2 //1080p30
+	 * If (total_source_pixels <= 124416000 && YUV) -> RD/WROT=4 //1080p60
+	 * If (total_source_pixels <= 2160p && YUV && FPS <= 30) -> RD/WROT = 32
+	 */
 	if (res <= (RES_1080p * 30))
 		ot_lim = 2;
 	else if (res <= (RES_1080p * 60))
 		ot_lim = 4;
-	else if (res <= (RES_UHD * 30))
-		ot_lim = 8;
 
 exit:
 	SDEROT_DBG("ot_lim=%d\n", ot_lim);
@@ -252,6 +258,8 @@
 	val &= (0xFF << bit_off);
 	val = val >> bit_off;
 
+	SDEROT_EVTLOG(val, ot_lim);
+
 	if (val == ot_lim)
 		ot_lim = 0;
 
diff --git a/drivers/media/platform/msm/vidc/hfi_response_handler.c b/drivers/media/platform/msm/vidc/hfi_response_handler.c
index 44cc7dc..0881a30 100644
--- a/drivers/media/platform/msm/vidc/hfi_response_handler.c
+++ b/drivers/media/platform/msm/vidc/hfi_response_handler.c
@@ -856,6 +856,36 @@
 	return 0;
 }
 
+static int copy_nal_stream_format_caps_to_sessions(u32 nal_stream_format_value,
+		struct msm_vidc_capability *capabilities, u32 num_sessions,
+		u32 codecs, u32 domain) {
+	u32 i = 0;
+	struct msm_vidc_capability *capability;
+	u32 sess_codec;
+	u32 sess_domain;
+
+	for (i = 0; i < num_sessions; i++) {
+		sess_codec = 0;
+		sess_domain = 0;
+		capability = &capabilities[i];
+
+		if (capability->codec)
+			sess_codec =
+				vidc_get_hfi_codec(capability->codec);
+		if (capability->domain)
+			sess_domain =
+				vidc_get_hfi_domain(capability->domain);
+
+		if (!(sess_codec & codecs && sess_domain & domain))
+			continue;
+
+		capability->nal_stream_format.nal_stream_format_supported =
+				nal_stream_format_value;
+	}
+
+	return 0;
+}
+
 static enum vidc_status hfi_parse_init_done_properties(
 		struct msm_vidc_capability *capabilities,
 		u32 num_sessions, u8 *data_ptr, u32 num_properties,
@@ -984,6 +1014,15 @@
 		}
 		case HFI_PROPERTY_PARAM_NAL_STREAM_FORMAT_SUPPORTED:
 		{
+			struct hfi_nal_stream_format_supported *prop =
+				(struct hfi_nal_stream_format_supported *)
+					(data_ptr + next_offset);
+
+			copy_nal_stream_format_caps_to_sessions(
+					prop->nal_stream_format_supported,
+					capabilities, num_sessions,
+					codecs, domain);
+
 			next_offset +=
 				sizeof(struct hfi_nal_stream_format_supported);
 			num_properties--;
diff --git a/drivers/media/platform/msm/vidc/msm_venc.c b/drivers/media/platform/msm/vidc/msm_venc.c
index e627ee4..be24f8d 100644
--- a/drivers/media/platform/msm/vidc/msm_venc.c
+++ b/drivers/media/platform/msm/vidc/msm_venc.c
@@ -164,6 +164,15 @@
 	"Unlimited"
 };
 
+static const char *const mpeg_video_stream_format[] = {
+	"NAL Format Start Codes",
+	"NAL Format One NAL Per Buffer",
+	"NAL Format One Byte Length",
+	"NAL Format Two Byte Length",
+	"NAL Format Four Byte Length",
+	NULL
+};
+
 static struct msm_vidc_ctrl msm_venc_ctrls[] = {
 	{
 		.id = V4L2_CID_MPEG_VIDC_VIDEO_IDR_PERIOD,
@@ -1197,7 +1206,22 @@
 		.step = 1,
 		.qmenu = NULL,
 	},
-
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT,
+		.name = "NAL Format",
+		.type = V4L2_CTRL_TYPE_MENU,
+		.minimum = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES,
+		.maximum = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH,
+		.default_value = V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES,
+		.menu_skip_mask = ~(
+		(1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_STARTCODES) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_NAL_PER_BUFFER) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_ONE_BYTE_LENGTH) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_TWO_BYTE_LENGTH) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_NAL_FORMAT_FOUR_BYTE_LENGTH)
+		),
+		.qmenu = mpeg_video_stream_format,
+	},
 };
 
 #define NUM_CTRLS ARRAY_SIZE(msm_venc_ctrls)
@@ -1358,6 +1382,7 @@
 	struct hal_vui_timing_info vui_timing_info = {0};
 	enum hal_iframesize_type iframesize_type = HAL_IFRAMESIZE_TYPE_DEFAULT;
 	u32 color_primaries, custom_matrix;
+	struct hal_nal_stream_format_select stream_format;
 
 	if (!inst || !inst->core || !inst->core->device) {
 		dprintk(VIDC_ERR, "%s invalid parameters\n", __func__);
@@ -2211,6 +2236,13 @@
 		vui_timing_info.time_scale = NSEC_PER_SEC;
 		break;
 	}
+	case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT:
+	{
+		property_id = HAL_PARAM_NAL_STREAM_FORMAT_SELECT;
+		stream_format.nal_stream_format_select = BIT(ctrl->val);
+		pdata = &stream_format;
+		break;
+	}
 	case V4L2_CID_MPEG_VIDC_VIDEO_LTRMODE:
 	case V4L2_CID_MPEG_VIDC_VIDEO_LTRCOUNT:
 	case V4L2_CID_MPEG_VIDC_VENC_PARAM_SAR_WIDTH:
diff --git a/drivers/media/platform/msm/vidc/msm_vidc.c b/drivers/media/platform/msm/vidc/msm_vidc.c
index e7ae579..b515ad4 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc.c
@@ -1523,6 +1523,11 @@
 	case V4L2_CID_MPEG_VIDC_VIDEO_TME_PAYLOAD_VERSION:
 		ctrl->val = inst->capability.tme_version;
 		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_STREAM_FORMAT:
+		ctrl->val =
+			inst->capability.nal_stream_format.
+				nal_stream_format_supported;
+		break;
 	default:
 		/*
 		 * Other controls aren't really volatile, shouldn't need to
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
index 4be087f..0f74c7c 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_clocks.c
@@ -1018,9 +1018,10 @@
 		rc_mode =  msm_comm_g_ctrl_for_id(inst,
 				V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL);
 		if (rc_mode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_VFR ||
-			rc_mode ==
-				V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR)
-			pdata.video_work_mode = VIDC_WORK_MODE_2;
+		    rc_mode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_VBR_CFR ||
+		    rc_mode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_MBR_CFR ||
+		    rc_mode == V4L2_CID_MPEG_VIDC_VIDEO_RATE_CONTROL_MBR_VFR)
+		pdata.video_work_mode = VIDC_WORK_MODE_2;
 	} else {
 		return -EINVAL;
 	}
diff --git a/drivers/media/platform/msm/vidc/msm_vidc_platform.c b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
index c84490f..cb581b7 100644
--- a/drivers/media/platform/msm/vidc/msm_vidc_platform.c
+++ b/drivers/media/platform/msm/vidc/msm_vidc_platform.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -179,7 +179,7 @@
 	},
 	{
 		.key = "qcom,max-hw-load",
-		.value = 1944000,
+		.value = 2009280,
 	},
 	{
 		.key = "qcom,max-hq-mbs-per-frame",
diff --git a/drivers/media/platform/msm/vidc_3x/msm_vdec.c b/drivers/media/platform/msm/vidc_3x/msm_vdec.c
index b0f639a..04bdd65 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_vdec.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_vdec.c
@@ -2491,6 +2491,11 @@
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_PROFILE:
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_LEVEL);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control\n");
+			return -EINVAL;
+		}
 		property_id =
 			HAL_PARAM_PROFILE_LEVEL_CURRENT;
 		profile_level.profile = vdec_v4l2_to_hal(ctrl->id,
@@ -2502,6 +2507,11 @@
 		break;
 	case V4L2_CID_MPEG_VIDEO_H264_LEVEL:
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_PROFILE);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control\n");
+			return -EINVAL;
+		}
 		property_id =
 			HAL_PARAM_PROFILE_LEVEL_CURRENT;
 		profile_level.level = vdec_v4l2_to_hal(ctrl->id,
diff --git a/drivers/media/platform/msm/vidc_3x/msm_venc.c b/drivers/media/platform/msm/vidc_3x/msm_venc.c
index 50ec4bd..a728b69 100644
--- a/drivers/media/platform/msm/vidc_3x/msm_venc.c
+++ b/drivers/media/platform/msm/vidc_3x/msm_venc.c
@@ -2320,6 +2320,11 @@
 	switch (inst->fmts[CAPTURE_PORT].fourcc) {
 	case V4L2_PIX_FMT_VP8:
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_MAX_QP);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control");
+			return -EINVAL;
+		}
 		max = temp_ctrl->maximum;
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_VPX_MIN_QP);
 		min = temp_ctrl->minimum;
@@ -2329,6 +2334,11 @@
 	case V4L2_PIX_FMT_H263:
 	case V4L2_PIX_FMT_MPEG4:
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control");
+			return -EINVAL;
+		}
 		max = temp_ctrl->maximum;
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP);
 		min = temp_ctrl->minimum;
@@ -2338,6 +2348,11 @@
 	case V4L2_PIX_FMT_H264:
 	case V4L2_PIX_FMT_HEVC:
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MAX_QP);
+		if (!temp_ctrl) {
+			dprintk(VIDC_ERR,
+				"failed to get control");
+			return -EINVAL;
+		}
 		max = temp_ctrl->maximum;
 		temp_ctrl = TRY_GET_CTRL(V4L2_CID_MPEG_VIDEO_H264_MIN_QP);
 		min = temp_ctrl->minimum;
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index 0e8fb89..5c4aa24 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -504,18 +504,23 @@
 
 static int lme2510_return_status(struct dvb_usb_device *d)
 {
-	int ret = 0;
+	int ret;
 	u8 *data;
 
-	data = kzalloc(10, GFP_KERNEL);
+	data = kzalloc(6, GFP_KERNEL);
 	if (!data)
 		return -ENOMEM;
 
-	ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
-			0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
-	info("Firmware Status: %x (%x)", ret , data[2]);
+	ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
+			      0x06, 0x80, 0x0302, 0x00,
+			      data, 0x6, 200);
+	if (ret != 6)
+		ret = -EINVAL;
+	else
+		ret = data[2];
 
-	ret = (ret < 0) ? -ENODEV : data[2];
+	info("Firmware Status: %6ph", data);
+
 	kfree(data);
 	return ret;
 }
@@ -1079,8 +1084,6 @@
 
 		if (adap->fe[0]) {
 			info("FE Found M88RS2000");
-			dvb_attach(ts2020_attach, adap->fe[0], &ts2020_config,
-					&d->i2c_adap);
 			st->i2c_tuner_gate_w = 5;
 			st->i2c_tuner_gate_r = 5;
 			st->i2c_tuner_addr = 0x60;
@@ -1146,17 +1149,18 @@
 			ret = st->tuner_config;
 		break;
 	case TUNER_RS2000:
-		ret = st->tuner_config;
+		if (dvb_attach(ts2020_attach, adap->fe[0],
+			       &ts2020_config, &d->i2c_adap))
+			ret = st->tuner_config;
 		break;
 	default:
 		break;
 	}
 
-	if (ret)
+	if (ret) {
 		info("TUN Found %s tuner", tun_msg[ret]);
-	else {
-		info("TUN No tuner found --- resetting device");
-		lme_coldreset(d);
+	} else {
+		info("TUN No tuner found");
 		return -ENODEV;
 	}
 
@@ -1200,6 +1204,7 @@
 static int lme2510_identify_state(struct dvb_usb_device *d, const char **name)
 {
 	struct lme2510_state *st = d->priv;
+	int status;
 
 	usb_reset_configuration(d->udev);
 
@@ -1208,12 +1213,16 @@
 
 	st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware;
 
-	if (lme2510_return_status(d) == 0x44) {
+	status = lme2510_return_status(d);
+	if (status == 0x44) {
 		*name = lme_firmware_switch(d, 0);
 		return COLD;
 	}
 
-	return 0;
+	if (status != 0x47)
+		return -EINVAL;
+
+	return WARM;
 }
 
 static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index 9fd43a3..b20f03d 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -820,6 +820,8 @@
 	case XC2028_RESET_CLK:
 		deb_info("%s: XC2028_RESET_CLK %d\n", __func__, arg);
 		break;
+	case XC2028_I2C_FLUSH:
+		break;
 	default:
 		deb_info("%s: unknown command %d, arg %d\n", __func__,
 			 command, arg);
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index caa5540..2868766 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -431,6 +431,7 @@
 		state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
 		break;
 	case XC2028_RESET_CLK:
+	case XC2028_I2C_FLUSH:
 		break;
 	default:
 		err("%s: unknown command %d, arg %d\n", __func__,
diff --git a/drivers/media/usb/hdpvr/hdpvr-core.c b/drivers/media/usb/hdpvr/hdpvr-core.c
index a61d8fd..a20b60a 100644
--- a/drivers/media/usb/hdpvr/hdpvr-core.c
+++ b/drivers/media/usb/hdpvr/hdpvr-core.c
@@ -295,7 +295,7 @@
 	/* register v4l2_device early so it can be used for printks */
 	if (v4l2_device_register(&interface->dev, &dev->v4l2_dev)) {
 		dev_err(&interface->dev, "v4l2_device_register failed\n");
-		goto error;
+		goto error_free_dev;
 	}
 
 	mutex_init(&dev->io_mutex);
@@ -304,7 +304,7 @@
 	dev->usbc_buf = kmalloc(64, GFP_KERNEL);
 	if (!dev->usbc_buf) {
 		v4l2_err(&dev->v4l2_dev, "Out of memory\n");
-		goto error;
+		goto error_v4l2_unregister;
 	}
 
 	init_waitqueue_head(&dev->wait_buffer);
@@ -342,13 +342,13 @@
 	}
 	if (!dev->bulk_in_endpointAddr) {
 		v4l2_err(&dev->v4l2_dev, "Could not find bulk-in endpoint\n");
-		goto error;
+		goto error_put_usb;
 	}
 
 	/* init the device */
 	if (hdpvr_device_init(dev)) {
 		v4l2_err(&dev->v4l2_dev, "device init failed\n");
-		goto error;
+		goto error_put_usb;
 	}
 
 	mutex_lock(&dev->io_mutex);
@@ -356,7 +356,7 @@
 		mutex_unlock(&dev->io_mutex);
 		v4l2_err(&dev->v4l2_dev,
 			 "allocating transfer buffers failed\n");
-		goto error;
+		goto error_put_usb;
 	}
 	mutex_unlock(&dev->io_mutex);
 
@@ -364,7 +364,7 @@
 	retval = hdpvr_register_i2c_adapter(dev);
 	if (retval < 0) {
 		v4l2_err(&dev->v4l2_dev, "i2c adapter register failed\n");
-		goto error;
+		goto error_free_buffers;
 	}
 
 	client = hdpvr_register_ir_rx_i2c(dev);
@@ -397,13 +397,17 @@
 reg_fail:
 #if IS_ENABLED(CONFIG_I2C)
 	i2c_del_adapter(&dev->i2c_adapter);
+error_free_buffers:
 #endif
+	hdpvr_free_buffers(dev);
+error_put_usb:
+	usb_put_dev(dev->udev);
+	kfree(dev->usbc_buf);
+error_v4l2_unregister:
+	v4l2_device_unregister(&dev->v4l2_dev);
+error_free_dev:
+	kfree(dev);
 error:
-	if (dev) {
-		flush_work(&dev->worker);
-		/* this frees allocated memory */
-		hdpvr_delete(dev);
-	}
 	return retval;
 }
 
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index f37d64c..9eaab98 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -18,8 +18,18 @@
 #include <linux/videodev2.h>
 #include <linux/v4l2-subdev.h>
 #include <media/v4l2-dev.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ctrls.h>
 #include <media/v4l2-ioctl.h>
 
+/* Use the same argument order as copy_in_user */
+#define assign_in_user(to, from)					\
+({									\
+	typeof(*from) __assign_tmp;					\
+									\
+	get_user(__assign_tmp, from) || put_user(__assign_tmp, to);	\
+})
+
 static long native_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
 	long ret = -ENOIOCTLCMD;
@@ -33,157 +43,88 @@
 
 struct v4l2_clip32 {
 	struct v4l2_rect        c;
-	compat_caddr_t 		next;
+	compat_caddr_t		next;
 };
 
 struct v4l2_window32 {
 	struct v4l2_rect        w;
-	__u32		  	field;	/* enum v4l2_field */
+	__u32			field;	/* enum v4l2_field */
 	__u32			chromakey;
 	compat_caddr_t		clips; /* actually struct v4l2_clip32 * */
 	__u32			clipcount;
 	compat_caddr_t		bitmap;
+	__u8                    global_alpha;
 };
 
 static int get_v4l2_window32(struct v4l2_window __user *kp,
-			struct v4l2_window32 __user *up)
+			     struct v4l2_window32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
 {
-	u32 clipcount = 0;
+	struct v4l2_clip32 __user *uclips;
+	struct v4l2_clip __user *kclips;
+	compat_caddr_t p;
+	u32 clipcount;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_window32)) ||
-		!access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_window)) ||
-		copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
-		copy_in_user(&kp->field, &up->field, sizeof(up->field)) ||
-		copy_in_user(&kp->chromakey, &up->chromakey,
-			sizeof(up->chromakey)) ||
-		copy_in_user(&kp->clipcount, &up->clipcount,
-			sizeof(up->clipcount)))
-			return -EFAULT;
-	if (get_user(clipcount, &kp->clipcount))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    copy_in_user(&kp->w, &up->w, sizeof(up->w)) ||
+	    assign_in_user(&kp->field, &up->field) ||
+	    assign_in_user(&kp->chromakey, &up->chromakey) ||
+	    assign_in_user(&kp->global_alpha, &up->global_alpha) ||
+	    get_user(clipcount, &up->clipcount) ||
+	    put_user(clipcount, &kp->clipcount))
 		return -EFAULT;
 	if (clipcount > 2048)
 		return -EINVAL;
-	if (clipcount) {
-		struct v4l2_clip32 __user *uclips;
-		struct v4l2_clip __user *kclips;
-		int n = clipcount;
-		compat_caddr_t p;
+	if (!clipcount)
+		return put_user(NULL, &kp->clips);
 
-		if (get_user(p, &up->clips))
+	if (get_user(p, &up->clips))
+		return -EFAULT;
+	uclips = compat_ptr(p);
+	if (aux_space < clipcount * sizeof(*kclips))
+		return -EFAULT;
+	kclips = aux_buf;
+	if (put_user(kclips, &kp->clips))
+		return -EFAULT;
+
+	while (clipcount--) {
+		if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
 			return -EFAULT;
-		uclips = compat_ptr(p);
-		kclips = compat_alloc_user_space(n * sizeof(struct v4l2_clip));
-		if (put_user(kclips, &kp->clips))
+		if (put_user(clipcount ? kclips + 1 : NULL, &kclips->next))
 			return -EFAULT;
-		while (--n >= 0) {
-			if (copy_in_user(&kclips->c, &uclips->c, sizeof(uclips->c)))
-				return -EFAULT;
-			if (put_user(n ? kclips + 1 : NULL, &kclips->next))
-				return -EFAULT;
-			uclips += 1;
-			kclips += 1;
-		}
-	} else {
-		if (put_user(NULL, &kp->clips))
-			return -EFAULT;
+		uclips++;
+		kclips++;
 	}
 	return 0;
 }
 
 static int put_v4l2_window32(struct v4l2_window __user *kp,
-			struct v4l2_window32 __user *up)
+			     struct v4l2_window32 __user *up)
 {
-	if (copy_in_user(&up->w, &kp->w, sizeof(up->w)) ||
-		copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
-		copy_in_user(&up->chromakey, &kp->chromakey,
-			sizeof(up->chromakey)) ||
-		copy_in_user(&up->clipcount, &kp->clipcount,
-			sizeof(up->clipcount)))
-		return -EFAULT;
-	return 0;
-}
+	struct v4l2_clip __user *kclips = kp->clips;
+	struct v4l2_clip32 __user *uclips;
+	compat_caddr_t p;
+	u32 clipcount;
 
-static inline int get_v4l2_pix_format(struct v4l2_pix_format __user *kp,
-				struct v4l2_pix_format __user *up)
-{
-	if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format)))
+	if (copy_in_user(&up->w, &kp->w, sizeof(kp->w)) ||
+	    assign_in_user(&up->field, &kp->field) ||
+	    assign_in_user(&up->chromakey, &kp->chromakey) ||
+	    assign_in_user(&up->global_alpha, &kp->global_alpha) ||
+	    get_user(clipcount, &kp->clipcount) ||
+	    put_user(clipcount, &up->clipcount))
 		return -EFAULT;
-	return 0;
-}
+	if (!clipcount)
+		return 0;
 
-static inline int get_v4l2_pix_format_mplane(
-				struct v4l2_pix_format_mplane __user *kp,
-				struct v4l2_pix_format_mplane __user *up)
-{
-	if (copy_in_user(kp, up, sizeof(struct v4l2_pix_format_mplane)))
+	if (get_user(p, &up->clips))
 		return -EFAULT;
-	return 0;
-}
-
-static inline int put_v4l2_pix_format(struct v4l2_pix_format __user *kp,
-				struct v4l2_pix_format __user *up)
-{
-	if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format)))
-		return -EFAULT;
-	return 0;
-}
-
-static inline int put_v4l2_pix_format_mplane(
-				struct v4l2_pix_format_mplane __user *kp,
-				struct v4l2_pix_format_mplane __user *up)
-{
-	if (copy_in_user(up, kp, sizeof(struct v4l2_pix_format_mplane)))
-		return -EFAULT;
-	return 0;
-}
-
-static inline int get_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
-				struct v4l2_vbi_format __user *up)
-{
-	if (copy_in_user(kp, up, sizeof(struct v4l2_vbi_format)))
-		return -EFAULT;
-	return 0;
-}
-
-static inline int put_v4l2_vbi_format(struct v4l2_vbi_format __user *kp,
-				struct v4l2_vbi_format __user *up)
-{
-	if (copy_in_user(up, kp, sizeof(struct v4l2_vbi_format)))
-		return -EFAULT;
-	return 0;
-}
-
-static inline int get_v4l2_sliced_vbi_format(
-				struct v4l2_sliced_vbi_format __user *kp,
-				struct v4l2_sliced_vbi_format __user *up)
-{
-	if (copy_in_user(kp, up, sizeof(struct v4l2_sliced_vbi_format)))
-		return -EFAULT;
-	return 0;
-}
-
-static inline int put_v4l2_sliced_vbi_format(
-				struct v4l2_sliced_vbi_format __user *kp,
-				struct v4l2_sliced_vbi_format __user *up)
-{
-	if (copy_in_user(up, kp, sizeof(struct v4l2_sliced_vbi_format)))
-		return -EFAULT;
-	return 0;
-}
-
-static inline int get_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
-				struct v4l2_sdr_format __user *up)
-{
-	if (copy_in_user(kp, up, sizeof(struct v4l2_sdr_format)))
-		return -EFAULT;
-	return 0;
-}
-
-static inline int put_v4l2_sdr_format(struct v4l2_sdr_format __user *kp,
-					struct v4l2_sdr_format __user *up)
-{
-	if (copy_in_user(up, kp, sizeof(struct v4l2_sdr_format)))
-		return -EFAULT;
+	uclips = compat_ptr(p);
+	while (clipcount--) {
+		if (copy_in_user(&uclips->c, &kclips->c, sizeof(uclips->c)))
+			return -EFAULT;
+		uclips++;
+		kclips++;
+	}
 	return 0;
 }
 
@@ -217,120 +158,158 @@
 	__u32			reserved[8];
 };
 
-static int __get_v4l2_format32(struct v4l2_format __user *kp,
-				struct v4l2_format32 __user *up)
+static int __bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
 {
 	u32 type;
 
-	if (copy_in_user(&kp->type, &up->type, sizeof(up->type)))
+	if (get_user(type, &up->type))
 		return -EFAULT;
 
-	if (get_user(type, &kp->type))
+	switch (type) {
+	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+		u32 clipcount;
+
+		if (get_user(clipcount, &up->fmt.win.clipcount))
+			return -EFAULT;
+		if (clipcount > 2048)
+			return -EINVAL;
+		*size = clipcount * sizeof(struct v4l2_clip);
+		return 0;
+	}
+	default:
+		*size = 0;
+		return 0;
+	}
+}
+
+static int bufsize_v4l2_format(struct v4l2_format32 __user *up, u32 *size)
+{
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
 		return -EFAULT;
+	return __bufsize_v4l2_format(up, size);
+}
+
+static int __get_v4l2_format32(struct v4l2_format __user *kp,
+			       struct v4l2_format32 __user *up,
+			       void __user *aux_buf, u32 aux_space)
+{
+	u32 type;
+
+	if (get_user(type, &up->type) || put_user(type, &kp->type))
+		return -EFAULT;
+
 	switch (type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		return get_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+		return copy_in_user(&kp->fmt.pix, &up->fmt.pix,
+				    sizeof(kp->fmt.pix)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		return get_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
-						  &up->fmt.pix_mp);
+		return copy_in_user(&kp->fmt.pix_mp, &up->fmt.pix_mp,
+				    sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win);
+		return get_v4l2_window32(&kp->fmt.win, &up->fmt.win,
+					 aux_buf, aux_space);
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_VBI_OUTPUT:
-		return get_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+		return copy_in_user(&kp->fmt.vbi, &up->fmt.vbi,
+				    sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-		return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
+		return copy_in_user(&kp->fmt.sliced, &up->fmt.sliced,
+				    sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
-		return get_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+		return copy_in_user(&kp->fmt.sdr, &up->fmt.sdr,
+				    sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
 	default:
-		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-								kp->type);
 		return -EINVAL;
 	}
 }
 
 static int get_v4l2_format32(struct v4l2_format __user *kp,
-				struct v4l2_format32 __user *up)
+			     struct v4l2_format32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_format32)) ||
-		!access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_format)))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
 		return -EFAULT;
-	return __get_v4l2_format32(kp, up);
+	return __get_v4l2_format32(kp, up, aux_buf, aux_space);
+}
+
+static int bufsize_v4l2_create(struct v4l2_create_buffers32 __user *up,
+			       u32 *size)
+{
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)))
+		return -EFAULT;
+	return __bufsize_v4l2_format(&up->format, size);
 }
 
 static int get_v4l2_create32(struct v4l2_create_buffers __user *kp,
-				struct v4l2_create_buffers32 __user *up)
+			     struct v4l2_create_buffers32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
 {
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_create_buffers32)) ||
-		!access_ok(VERIFY_WRITE, kp,
-			sizeof(struct v4l2_create_buffers)) ||
-		copy_in_user(kp, up,
-			offsetof(struct v4l2_create_buffers32, format)))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    copy_in_user(kp, up,
+			 offsetof(struct v4l2_create_buffers32, format)))
 		return -EFAULT;
-	return __get_v4l2_format32(&kp->format, &up->format);
+	return __get_v4l2_format32(&kp->format, &up->format,
+				   aux_buf, aux_space);
 }
 
 static int __put_v4l2_format32(struct v4l2_format __user *kp,
-				struct v4l2_format32 __user *up)
+			       struct v4l2_format32 __user *up)
 {
 	u32 type;
 
-	if (copy_in_user(&up->type, &kp->type, sizeof(up->type)))
-		return -EFAULT;
-
 	if (get_user(type, &kp->type))
 		return -EFAULT;
 
 	switch (type) {
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-		return put_v4l2_pix_format(&kp->fmt.pix, &up->fmt.pix);
+		return copy_in_user(&up->fmt.pix, &kp->fmt.pix,
+				    sizeof(kp->fmt.pix)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-		return put_v4l2_pix_format_mplane(&kp->fmt.pix_mp,
-						  &up->fmt.pix_mp);
+		return copy_in_user(&up->fmt.pix_mp, &kp->fmt.pix_mp,
+				    sizeof(kp->fmt.pix_mp)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_VIDEO_OVERLAY:
 	case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
 		return put_v4l2_window32(&kp->fmt.win, &up->fmt.win);
 	case V4L2_BUF_TYPE_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_VBI_OUTPUT:
-		return put_v4l2_vbi_format(&kp->fmt.vbi, &up->fmt.vbi);
+		return copy_in_user(&up->fmt.vbi, &kp->fmt.vbi,
+				    sizeof(kp->fmt.vbi)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
 	case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-		return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
+		return copy_in_user(&up->fmt.sliced, &kp->fmt.sliced,
+				    sizeof(kp->fmt.sliced)) ? -EFAULT : 0;
 	case V4L2_BUF_TYPE_SDR_CAPTURE:
 	case V4L2_BUF_TYPE_SDR_OUTPUT:
-		return put_v4l2_sdr_format(&kp->fmt.sdr, &up->fmt.sdr);
+		return copy_in_user(&up->fmt.sdr, &kp->fmt.sdr,
+				    sizeof(kp->fmt.sdr)) ? -EFAULT : 0;
 	default:
-		pr_info("compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
-								kp->type);
 		return -EINVAL;
 	}
 }
 
 static int put_v4l2_format32(struct v4l2_format __user *kp,
-				struct v4l2_format32 __user *up)
+			     struct v4l2_format32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_format32)) ||
-		!access_ok(VERIFY_READ, kp, sizeof(struct v4l2_format)))
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)))
 		return -EFAULT;
 	return __put_v4l2_format32(kp, up);
 }
 
 static int put_v4l2_create32(struct v4l2_create_buffers __user *kp,
-				struct v4l2_create_buffers32 __user *up)
+			     struct v4l2_create_buffers32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_create_buffers32)) ||
-		!access_ok(VERIFY_READ, kp,
-			sizeof(struct v4l2_create_buffers)) ||
-		copy_in_user(up, kp,
-			offsetof(struct v4l2_create_buffers32, format)) ||
-		copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    copy_in_user(up, kp,
+			 offsetof(struct v4l2_create_buffers32, format)) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(kp->reserved)))
 		return -EFAULT;
 	return __put_v4l2_format32(&kp->format, &up->format);
 }
@@ -345,30 +324,27 @@
 };
 
 static int get_v4l2_standard32(struct v4l2_standard __user *kp,
-			struct v4l2_standard32 __user *up)
+			       struct v4l2_standard32 __user *up)
 {
 	/* other fields are not set by the user, nor used by the driver */
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_standard32)) ||
-		!access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_standard)) ||
-		copy_in_user(&kp->index, &up->index, sizeof(up->index)))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    assign_in_user(&kp->index, &up->index))
 		return -EFAULT;
 	return 0;
 }
 
 static int put_v4l2_standard32(struct v4l2_standard __user *kp,
-				struct v4l2_standard32 __user *up)
+			       struct v4l2_standard32 __user *up)
 {
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_standard32)) ||
-		!access_ok(VERIFY_READ, kp, sizeof(struct v4l2_standard)) ||
-		copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
-		copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
-		copy_in_user(up->name, kp->name, 24) ||
-		copy_in_user(&up->frameperiod, &kp->frameperiod,
-			sizeof(up->frameperiod)) ||
-		copy_in_user(&up->framelines, &kp->framelines,
-			sizeof(up->framelines)) ||
-		copy_in_user(up->reserved, kp->reserved, 4 * sizeof(__u32)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->index, &kp->index) ||
+	    assign_in_user(&up->id, &kp->id) ||
+	    copy_in_user(up->name, kp->name, sizeof(up->name)) ||
+	    copy_in_user(&up->frameperiod, &kp->frameperiod,
+			 sizeof(up->frameperiod)) ||
+	    assign_in_user(&up->framelines, &kp->framelines) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -407,160 +383,192 @@
 	__u32			reserved;
 };
 
-static int get_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
-				enum v4l2_memory memory)
+static int get_v4l2_plane32(struct v4l2_plane __user *up,
+			    struct v4l2_plane32 __user *up32,
+			    enum v4l2_memory memory)
 {
-	void __user *up_pln;
-	compat_long_t p;
+	compat_ulong_t p;
 
 	if (copy_in_user(up, up32, 2 * sizeof(__u32)) ||
-		copy_in_user(&up->data_offset, &up32->data_offset,
-				sizeof(__u32)) ||
-		copy_in_user(up->reserved, up32->reserved,
-				sizeof(up->reserved)) ||
-		copy_in_user(&up->length, &up32->length,
-				sizeof(__u32)))
+	    copy_in_user(&up->data_offset, &up32->data_offset,
+			 sizeof(up->data_offset)) ||
+	    copy_in_user(up->reserved, up32->reserved,
+			 sizeof(up->reserved)) ||
+	    copy_in_user(&up->length, &up32->length,
+			 sizeof(up->length)))
 		return -EFAULT;
 
-	if (memory == V4L2_MEMORY_USERPTR) {
-		if (get_user(p, &up32->m.userptr))
-			return -EFAULT;
-		up_pln = compat_ptr(p);
-		if (put_user((unsigned long)up_pln, &up->m.userptr))
-			return -EFAULT;
-	} else if (memory == V4L2_MEMORY_DMABUF) {
-		if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(int)))
-			return -EFAULT;
-	} else {
+	switch (memory) {
+	case V4L2_MEMORY_MMAP:
+	case V4L2_MEMORY_OVERLAY:
 		if (copy_in_user(&up->m.mem_offset, &up32->m.mem_offset,
-					sizeof(__u32)))
+				 sizeof(up32->m.mem_offset)))
 			return -EFAULT;
+		break;
+	case V4L2_MEMORY_USERPTR:
+		if (get_user(p, &up32->m.userptr) ||
+		    put_user((unsigned long)compat_ptr(p), &up->m.userptr))
+			return -EFAULT;
+		break;
+	case V4L2_MEMORY_DMABUF:
+		if (copy_in_user(&up->m.fd, &up32->m.fd, sizeof(up32->m.fd)))
+			return -EFAULT;
+		break;
 	}
 
 	return 0;
 }
 
-static int put_v4l2_plane32(struct v4l2_plane __user *up, struct v4l2_plane32 __user *up32,
-				enum v4l2_memory memory)
+static int put_v4l2_plane32(struct v4l2_plane __user *up,
+			    struct v4l2_plane32 __user *up32,
+			    enum v4l2_memory memory)
 {
+	unsigned long p;
+
 	if (copy_in_user(up32, up, 2 * sizeof(__u32)) ||
-		copy_in_user(&up32->data_offset, &up->data_offset,
-				sizeof(__u32)) ||
-		copy_in_user(up32->reserved, up->reserved,
-				sizeof(up32->reserved)))
+	    copy_in_user(&up32->data_offset, &up->data_offset,
+			 sizeof(up->data_offset)) ||
+	    copy_in_user(up32->reserved, up->reserved,
+			 sizeof(up32->reserved)))
 		return -EFAULT;
 
-	/* For MMAP, driver might've set up the offset, so copy it back.
-	 * USERPTR stays the same (was userspace-provided), so no copying. */
-	if (memory == V4L2_MEMORY_MMAP)
+	switch (memory) {
+	case V4L2_MEMORY_MMAP:
+	case V4L2_MEMORY_OVERLAY:
 		if (copy_in_user(&up32->m.mem_offset, &up->m.mem_offset,
-					sizeof(__u32)))
+				 sizeof(up->m.mem_offset)))
 			return -EFAULT;
-	/* For DMABUF, driver might've set up the fd, so copy it back. */
-	if (memory == V4L2_MEMORY_DMABUF)
-		if (copy_in_user(&up32->m.fd, &up->m.fd,
-					sizeof(int)))
+		break;
+	case V4L2_MEMORY_USERPTR:
+		if (get_user(p, &up->m.userptr) ||
+		    put_user((compat_ulong_t)ptr_to_compat((__force void *)p),
+			     &up32->m.userptr))
 			return -EFAULT;
+		break;
+	case V4L2_MEMORY_DMABUF:
+		if (copy_in_user(&up32->m.fd, &up->m.fd, sizeof(up->m.fd)))
+			return -EFAULT;
+		break;
+	}
 
 	return 0;
 }
 
-static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
-				struct v4l2_buffer32 __user *up)
+static int bufsize_v4l2_buffer(struct v4l2_buffer32 __user *up, u32 *size)
 {
+	u32 type;
+	u32 length;
+
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    get_user(type, &up->type) ||
+	    get_user(length, &up->length))
+		return -EFAULT;
+
+	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
+		if (length > VIDEO_MAX_PLANES)
+			return -EINVAL;
+
+		/*
+		 * We don't really care if userspace decides to kill itself
+		 * by passing a very big length value
+		 */
+		*size = length * sizeof(struct v4l2_plane);
+	} else {
+		*size = 0;
+	}
+	return 0;
+}
+
+static int get_v4l2_buffer32(struct v4l2_buffer __user *kp,
+			     struct v4l2_buffer32 __user *up,
+			     void __user *aux_buf, u32 aux_space)
+{
+	u32 type;
+	u32 length;
+	enum v4l2_memory memory;
 	struct v4l2_plane32 __user *uplane32;
 	struct v4l2_plane __user *uplane;
 	compat_caddr_t p;
-	int num_planes;
-	struct timeval time;
-	u32 plane_count, memory, type;
 	int ret;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_buffer32)) ||
-		!access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_buffer)) ||
-		copy_in_user(&kp->index, &up->index, sizeof(up->index)) ||
-		copy_in_user(&kp->type, &up->type, sizeof(up->type)) ||
-		copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
-		copy_in_user(&kp->memory, &up->memory, sizeof(up->memory)) ||
-		copy_in_user(&kp->length, &up->length, sizeof(up->length)))
-			return -EFAULT;
-
-	if (get_user(type, &kp->type))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    assign_in_user(&kp->index, &up->index) ||
+	    get_user(type, &up->type) ||
+	    put_user(type, &kp->type) ||
+	    assign_in_user(&kp->flags, &up->flags) ||
+	    get_user(memory, &up->memory) ||
+	    put_user(memory, &kp->memory) ||
+	    get_user(length, &up->length) ||
+	    put_user(length, &kp->length))
 		return -EFAULT;
+
 	if (V4L2_TYPE_IS_OUTPUT(type))
-		if (copy_in_user(&kp->bytesused, &up->bytesused,
-				sizeof(up->bytesused)) ||
-			copy_in_user(&kp->field, &up->field,
-				sizeof(up->field)) ||
-			get_user(time.tv_sec, &up->timestamp.tv_sec) ||
-			get_user(time.tv_usec, &up->timestamp.tv_usec) ||
-			put_user(time.tv_sec, &kp->timestamp.tv_sec) ||
-			put_user(time.tv_usec, &kp->timestamp.tv_usec))
+		if (assign_in_user(&kp->bytesused, &up->bytesused) ||
+		    assign_in_user(&kp->field, &up->field) ||
+		    assign_in_user(&kp->timestamp.tv_sec,
+				   &up->timestamp.tv_sec) ||
+		    assign_in_user(&kp->timestamp.tv_usec,
+				   &up->timestamp.tv_usec))
 			return -EFAULT;
 
-	if (get_user(memory, &kp->memory))
-		return -EFAULT;
 	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
-		if (get_user(plane_count, &kp->length))
-			return -EFAULT;
-		num_planes = plane_count;
+		u32 num_planes = length;
+
 		if (num_planes == 0) {
-			if (put_user(NULL, &kp->m.planes))
-				return -EFAULT;
-			/* num_planes == 0 is legal, e.g. when userspace doesn't
-			 * need planes array on DQBUF*/
-			return 0;
+			/*
+			 * num_planes == 0 is legal, e.g. when userspace doesn't
+			 * need planes array on DQBUF
+			 */
+			return put_user(NULL, &kp->m.planes);
 		}
+		if (num_planes > VIDEO_MAX_PLANES)
+			return -EINVAL;
 
 		if (get_user(p, &up->m.planes))
 			return -EFAULT;
 
 		uplane32 = compat_ptr(p);
 		if (!access_ok(VERIFY_READ, uplane32,
-				num_planes * sizeof(struct v4l2_plane32)))
+			       num_planes * sizeof(*uplane32)))
 			return -EFAULT;
 
-		/* We don't really care if userspace decides to kill itself
-		 * by passing a very big num_planes value */
-		uplane = compat_alloc_user_space(num_planes *
-						sizeof(struct v4l2_plane));
-		if (put_user(uplane, &kp->m.planes))
+		/*
+		 * We don't really care if userspace decides to kill itself
+		 * by passing a very big num_planes value
+		 */
+		if (aux_space < num_planes * sizeof(*uplane))
 			return -EFAULT;
 
-		while (--num_planes >= 0) {
+		uplane = aux_buf;
+		if (put_user((__force struct v4l2_plane *)uplane,
+			     &kp->m.planes))
+			return -EFAULT;
+
+		while (num_planes--) {
 			ret = get_v4l2_plane32(uplane, uplane32, memory);
 			if (ret)
 				return ret;
-			++uplane;
-			++uplane32;
+			uplane++;
+			uplane32++;
 		}
 	} else {
 		switch (memory) {
 		case V4L2_MEMORY_MMAP:
-			if (copy_in_user(&kp->m.offset, &up->m.offset,
-				sizeof(up->m.offset)))
-				return -EFAULT;
-			break;
-		case V4L2_MEMORY_USERPTR:
-			{
-			compat_long_t tmp;
-			unsigned long userptr;
-
-			if (get_user(tmp, &up->m.userptr))
-				return -EFAULT;
-
-			userptr = (unsigned long)compat_ptr(tmp);
-			put_user(userptr, &kp->m.userptr);
-			}
-			break;
 		case V4L2_MEMORY_OVERLAY:
-			if (copy_in_user(&kp->m.offset, &up->m.offset,
-				sizeof(up->m.offset)))
+			if (assign_in_user(&kp->m.offset, &up->m.offset))
 				return -EFAULT;
 			break;
+		case V4L2_MEMORY_USERPTR: {
+			compat_ulong_t userptr;
+
+			if (get_user(userptr, &up->m.userptr) ||
+			    put_user((unsigned long)compat_ptr(userptr),
+				     &kp->m.userptr))
+				return -EFAULT;
+			break;
+		}
 		case V4L2_MEMORY_DMABUF:
-			if (copy_in_user(&kp->m.fd, &up->m.fd,
-				sizeof(up->m.fd)))
+			if (assign_in_user(&kp->m.fd, &up->m.fd))
 				return -EFAULT;
 			break;
 		}
@@ -570,59 +578,50 @@
 }
 
 static int put_v4l2_buffer32(struct v4l2_buffer __user *kp,
-				struct v4l2_buffer32 __user *up)
+			     struct v4l2_buffer32 __user *up)
 {
+	u32 type;
+	u32 length;
+	enum v4l2_memory memory;
 	struct v4l2_plane32 __user *uplane32;
 	struct v4l2_plane __user *uplane;
 	compat_caddr_t p;
-	int num_planes;
 	int ret;
-	struct timeval time;
-	u32 memory, type, length;
 
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_buffer32)) ||
-		!access_ok(VERIFY_READ, kp, sizeof(struct v4l2_buffer)) ||
-		copy_in_user(&up->index, &kp->index, sizeof(up->index)) ||
-		copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
-		copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
-		copy_in_user(&up->memory, &kp->memory, sizeof(up->memory)))
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->index, &kp->index) ||
+	    get_user(type, &kp->type) ||
+	    put_user(type, &up->type) ||
+	    assign_in_user(&up->flags, &kp->flags) ||
+	    get_user(memory, &kp->memory) ||
+	    put_user(memory, &up->memory))
 		return -EFAULT;
 
-	if (copy_in_user(&up->bytesused, &kp->bytesused,
-			sizeof(up->bytesused)) ||
-		copy_in_user(&up->field, &kp->field, sizeof(up->field)) ||
-		get_user(time.tv_sec, &kp->timestamp.tv_sec) ||
-		get_user(time.tv_usec, &kp->timestamp.tv_usec) ||
-		put_user(time.tv_sec, &up->timestamp.tv_sec) ||
-		put_user(time.tv_usec, &up->timestamp.tv_usec) ||
-		copy_in_user(&up->timecode, &kp->timecode,
-			sizeof(struct v4l2_timecode)) ||
-		copy_in_user(&up->sequence, &kp->sequence,
-			sizeof(up->sequence)) ||
-		copy_in_user(&up->reserved2, &kp->reserved2,
-			sizeof(up->reserved2)) ||
-		copy_in_user(&up->reserved, &kp->reserved,
-			sizeof(up->reserved)) ||
-		copy_in_user(&up->length, &kp->length, sizeof(up->length)))
+	if (assign_in_user(&up->bytesused, &kp->bytesused) ||
+	    assign_in_user(&up->field, &kp->field) ||
+	    assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
+	    assign_in_user(&up->timestamp.tv_usec, &kp->timestamp.tv_usec) ||
+	    copy_in_user(&up->timecode, &kp->timecode, sizeof(kp->timecode)) ||
+	    assign_in_user(&up->sequence, &kp->sequence) ||
+	    assign_in_user(&up->reserved2, &kp->reserved2) ||
+	    assign_in_user(&up->reserved, &kp->reserved) ||
+	    get_user(length, &kp->length) ||
+	    put_user(length, &up->length))
 		return -EFAULT;
 
-	if (get_user(type, &kp->type) ||
-		get_user(memory, &kp->memory) ||
-		get_user(length, &kp->length))
-		return -EINVAL;
-
 	if (V4L2_TYPE_IS_MULTIPLANAR(type)) {
-		num_planes = length;
+		u32 num_planes = length;
+
 		if (num_planes == 0)
 			return 0;
 
-		if (get_user(uplane, &kp->m.planes))
+		if (get_user(uplane, ((__force struct v4l2_plane __user **)&kp->m.planes)))
 			return -EFAULT;
 		if (get_user(p, &up->m.planes))
 			return -EFAULT;
 		uplane32 = compat_ptr(p);
 
-		while (--num_planes >= 0) {
+		while (num_planes--) {
 			ret = put_v4l2_plane32(uplane, uplane32, memory);
 			if (ret)
 				return ret;
@@ -632,23 +631,16 @@
 	} else {
 		switch (memory) {
 		case V4L2_MEMORY_MMAP:
-			if (copy_in_user(&up->m.offset, &kp->m.offset,
-				sizeof(up->m.offset)))
+		case V4L2_MEMORY_OVERLAY:
+			if (assign_in_user(&up->m.offset, &kp->m.offset))
 				return -EFAULT;
 			break;
 		case V4L2_MEMORY_USERPTR:
-			if (copy_in_user(&up->m.userptr, &kp->m.userptr,
-				sizeof(up->m.userptr)))
-				return -EFAULT;
-			break;
-		case V4L2_MEMORY_OVERLAY:
-			if (copy_in_user(&up->m.offset, &kp->m.offset,
-				sizeof(up->m.offset)))
+			if (assign_in_user(&up->m.userptr, &kp->m.userptr))
 				return -EFAULT;
 			break;
 		case V4L2_MEMORY_DMABUF:
-			if (copy_in_user(&up->m.fd, &kp->m.fd,
-				sizeof(up->m.fd)))
+			if (assign_in_user(&up->m.fd, &kp->m.fd))
 				return -EFAULT;
 			break;
 		}
@@ -660,7 +652,7 @@
 struct v4l2_framebuffer32 {
 	__u32			capability;
 	__u32			flags;
-	compat_caddr_t 		base;
+	compat_caddr_t		base;
 	struct {
 		__u32		width;
 		__u32		height;
@@ -674,39 +666,32 @@
 };
 
 static int get_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
-					struct v4l2_framebuffer32 __user *up)
+				  struct v4l2_framebuffer32 __user *up)
 {
-	u32 tmp;
+	compat_caddr_t tmp;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
-		!access_ok(VERIFY_WRITE, kp,
-			sizeof(struct v4l2_framebuffer)) ||
-		get_user(tmp, &up->base) ||
-		put_user(compat_ptr(tmp), &kp->base) ||
-		copy_in_user(&kp->capability, &up->capability,
-			sizeof(up->capability)) ||
-		copy_in_user(&kp->flags, &up->flags, sizeof(up->flags)) ||
-		copy_in_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
-			return -EFAULT;
-
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    get_user(tmp, &up->base) ||
+	    put_user((__force void *)compat_ptr(tmp), &kp->base) ||
+	    assign_in_user(&kp->capability, &up->capability) ||
+	    assign_in_user(&kp->flags, &up->flags) ||
+	    copy_in_user(&kp->fmt, &up->fmt, sizeof(kp->fmt)))
+		return -EFAULT;
 	return 0;
 }
 
 static int put_v4l2_framebuffer32(struct v4l2_framebuffer __user *kp,
-					struct v4l2_framebuffer32 __user *up)
+				  struct v4l2_framebuffer32 __user *up)
 {
-	unsigned long base;
+	void *base;
 
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
-		!access_ok(VERIFY_READ, kp,
-			sizeof(struct v4l2_framebuffer)) ||
-		copy_from_user(&base, &kp->base, sizeof(base)) ||
-		put_user((u32)base, &up->base) ||
-		copy_in_user(&up->capability, &kp->capability,
-			sizeof(up->capability)) ||
-		copy_in_user(&up->flags, &kp->flags, sizeof(up->flags)) ||
-		copy_in_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    get_user(base, &kp->base) ||
+	    put_user(ptr_to_compat(base), &up->base) ||
+	    assign_in_user(&up->capability, &kp->capability) ||
+	    assign_in_user(&up->flags, &kp->flags) ||
+	    copy_in_user(&up->fmt, &kp->fmt, sizeof(kp->fmt)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -718,23 +703,26 @@
 	__u32        tuner;             /*  Associated tuner */
 	compat_u64   std;
 	__u32	     status;
-	__u32	     reserved[4];
+	__u32	     capabilities;
+	__u32	     reserved[3];
 };
 
-/* The 64-bit v4l2_input struct has extra padding at the end of the struct.
-   Otherwise it is identical to the 32-bit version. */
+/*
+ * The 64-bit v4l2_input struct has extra padding at the end of the struct.
+ * Otherwise it is identical to the 32-bit version.
+ */
 static inline int get_v4l2_input32(struct v4l2_input __user *kp,
-					struct v4l2_input32 __user *up)
+				   struct v4l2_input32 __user *up)
 {
-	if (copy_in_user(kp, up, sizeof(struct v4l2_input32)))
+	if (copy_in_user(kp, up, sizeof(*up)))
 		return -EFAULT;
 	return 0;
 }
 
 static inline int put_v4l2_input32(struct v4l2_input __user *kp,
-					struct v4l2_input32 __user *up)
+				   struct v4l2_input32 __user *up)
 {
-	if (copy_in_user(up, kp, sizeof(struct v4l2_input32)))
+	if (copy_in_user(up, kp, sizeof(*up)))
 		return -EFAULT;
 	return 0;
 }
@@ -758,70 +746,95 @@
 	};
 } __attribute__ ((packed));
 
-/* The following function really belong in v4l2-common, but that causes
-   a circular dependency between modules. We need to think about this, but
-   for now this will do. */
-
-/* Return non-zero if this control is a pointer type. Currently only
-   type STRING is a pointer type. */
-static inline int ctrl_is_pointer(u32 id)
+/* Return true if this control is a pointer type. */
+static inline bool ctrl_is_pointer(struct file *file, u32 id)
 {
-	switch (id) {
-	case V4L2_CID_RDS_TX_PS_NAME:
-	case V4L2_CID_RDS_TX_RADIO_TEXT:
-		return 1;
-	default:
-		return 0;
+	struct video_device *vdev = video_devdata(file);
+	struct v4l2_fh *fh = NULL;
+	struct v4l2_ctrl_handler *hdl = NULL;
+	struct v4l2_query_ext_ctrl qec = { id };
+	const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
+
+	if (test_bit(V4L2_FL_USES_V4L2_FH, &vdev->flags))
+		fh = file->private_data;
+
+	if (fh && fh->ctrl_handler)
+		hdl = fh->ctrl_handler;
+	else if (vdev->ctrl_handler)
+		hdl = vdev->ctrl_handler;
+
+	if (hdl) {
+		struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, id);
+
+		return ctrl && ctrl->is_ptr;
 	}
+
+	if (!ops || !ops->vidioc_query_ext_ctrl)
+		return false;
+
+	return !ops->vidioc_query_ext_ctrl(file, fh, &qec) &&
+		(qec.flags & V4L2_CTRL_FLAG_HAS_PAYLOAD);
 }
 
-static int get_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
-					struct v4l2_ext_controls32 __user *up)
+static int bufsize_v4l2_ext_controls(struct v4l2_ext_controls32 __user *up,
+				     u32 *size)
+{
+	u32 count;
+
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    get_user(count, &up->count))
+		return -EFAULT;
+	if (count > V4L2_CID_MAX_CTRLS)
+		return -EINVAL;
+	*size = count * sizeof(struct v4l2_ext_control);
+	return 0;
+}
+
+static int get_v4l2_ext_controls32(struct file *file,
+				   struct v4l2_ext_controls __user *kp,
+				   struct v4l2_ext_controls32 __user *up,
+				   void __user *aux_buf, u32 aux_space)
 {
 	struct v4l2_ext_control32 __user *ucontrols;
 	struct v4l2_ext_control __user *kcontrols;
-	int n;
-	compat_caddr_t p;
 	u32 count;
+	u32 n;
+	compat_caddr_t p;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_ext_controls32)) ||
-		!access_ok(VERIFY_WRITE, kp,
-			sizeof(struct v4l2_ext_controls)) ||
-		copy_in_user(&kp->which, &up->which,
-			sizeof(up->which)) ||
-		copy_in_user(&kp->count, &up->count, sizeof(up->count)) ||
-		copy_in_user(&kp->error_idx, &up->error_idx,
-			sizeof(up->error_idx)) ||
-		copy_in_user(kp->reserved, up->reserved,
-			       sizeof(up->reserved)))
-			return -EFAULT;
-
-	if (get_user(count, &kp->count))
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    assign_in_user(&kp->which, &up->which) ||
+	    get_user(count, &up->count) ||
+	    put_user(count, &kp->count) ||
+	    assign_in_user(&kp->error_idx, &up->error_idx) ||
+	    copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
 		return -EFAULT;
-	n = count;
-	if (n == 0) {
-		if (put_user(NULL, &kp->controls))
-			return -EINVAL;
-		return 0;
-	}
+
+	if (count == 0)
+		return put_user(NULL, &kp->controls);
+	if (count > V4L2_CID_MAX_CTRLS)
+		return -EINVAL;
 	if (get_user(p, &up->controls))
 		return -EFAULT;
 	ucontrols = compat_ptr(p);
-	if (!access_ok(VERIFY_READ, ucontrols,
-			n * sizeof(struct v4l2_ext_control32)))
+	if (!access_ok(VERIFY_READ, ucontrols, count * sizeof(*ucontrols)))
 		return -EFAULT;
-	kcontrols = compat_alloc_user_space(n * sizeof(struct v4l2_ext_control));
-	if (put_user(kcontrols, &kp->controls))
+	if (aux_space < count * sizeof(*kcontrols))
+		return -EFAULT;
+	kcontrols = aux_buf;
+	if (put_user((__force struct v4l2_ext_control *)kcontrols,
+		     &kp->controls))
 		return -EFAULT;
 
-	while (--n >= 0) {
+	for (n = 0; n < count; n++) {
 		u32 id;
 
 		if (copy_in_user(kcontrols, ucontrols, sizeof(*ucontrols)))
 			return -EFAULT;
+
 		if (get_user(id, &kcontrols->id))
 			return -EFAULT;
-		if (ctrl_is_pointer(id)) {
+
+		if (ctrl_is_pointer(file, id)) {
 			void __user *s;
 
 			if (get_user(p, &ucontrols->string))
@@ -836,53 +849,55 @@
 	return 0;
 }
 
-static int put_v4l2_ext_controls32(struct v4l2_ext_controls __user *kp,
-				struct v4l2_ext_controls32 __user *up)
+static int put_v4l2_ext_controls32(struct file *file,
+				   struct v4l2_ext_controls __user *kp,
+				   struct v4l2_ext_controls32 __user *up)
 {
 	struct v4l2_ext_control32 __user *ucontrols;
 	struct v4l2_ext_control __user *kcontrols;
-	int n;
 	u32 count;
+	u32 n;
 	compat_caddr_t p;
 
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_ext_controls32)) ||
-		!access_ok(VERIFY_READ, kp,
-			sizeof(struct v4l2_ext_controls)) ||
-		copy_in_user(&up->which, &kp->which,
-			sizeof(up->which)) ||
-		copy_in_user(&up->count, &kp->count,
-			sizeof(up->count)) ||
-		copy_in_user(&up->error_idx, &kp->error_idx,
-			sizeof(up->error_idx)) ||
-		copy_in_user(up->reserved, kp->reserved,
-			sizeof(up->reserved)) ||
-		get_user(count, &kp->count) ||
-		get_user(kcontrols, &kp->controls))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->which, &kp->which) ||
+	    get_user(count, &kp->count) ||
+	    put_user(count, &up->count) ||
+	    assign_in_user(&up->error_idx, &kp->error_idx) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)) ||
+	    get_user(kcontrols, &kp->controls))
+		return -EFAULT;
+
 	if (!count)
 		return 0;
-
-	n = count;
 	if (get_user(p, &up->controls))
 		return -EFAULT;
 	ucontrols = compat_ptr(p);
-	if (!access_ok(VERIFY_WRITE, ucontrols,
-			n * sizeof(struct v4l2_ext_control32)))
+	if (!access_ok(VERIFY_WRITE, ucontrols, count * sizeof(*ucontrols)))
 		return -EFAULT;
 
-	while (--n >= 0) {
-		unsigned size = sizeof(*ucontrols);
+	for (n = 0; n < count; n++) {
+		unsigned int size = sizeof(*ucontrols);
 		u32 id;
 
-		if (get_user(id, &kcontrols->id))
+		if (get_user(id, &kcontrols->id) ||
+		    put_user(id, &ucontrols->id) ||
+		    assign_in_user(&ucontrols->size, &kcontrols->size) ||
+		    copy_in_user(&ucontrols->reserved2, &kcontrols->reserved2,
+				 sizeof(ucontrols->reserved2)))
 			return -EFAULT;
-		/* Do not modify the pointer when copying a pointer control.
-		   The contents of the pointer was changed, not the pointer
-		   itself. */
-		if (ctrl_is_pointer(id))
+
+		/*
+		 * Do not modify the pointer when copying a pointer control.
+		 * The contents of the pointer was changed, not the pointer
+		 * itself.
+		 */
+		if (ctrl_is_pointer(file, id))
 			size -= sizeof(ucontrols->value64);
+
 		if (copy_in_user(ucontrols, kcontrols, size))
 			return -EFAULT;
+
 		ucontrols++;
 		kcontrols++;
 	}
@@ -903,22 +918,18 @@
 };
 
 static int put_v4l2_event32(struct v4l2_event __user *kp,
-			struct v4l2_event32 __user *up)
+			    struct v4l2_event32 __user *up)
 {
-	struct timespec ts;
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_event32)) ||
-		!access_ok(VERIFY_READ, kp, sizeof(struct v4l2_event)) ||
-		copy_in_user(&up->type, &kp->type, sizeof(up->type)) ||
-		copy_in_user(&up->u, &kp->u, sizeof(up->u)) ||
-		copy_in_user(&up->pending, &kp->pending,
-			sizeof(up->pending)) ||
-		copy_in_user(&up->sequence, &kp->sequence,
-			sizeof(up->sequence)) ||
-		copy_from_user(&ts, &kp->timestamp, sizeof(ts)) ||
-		compat_put_timespec(&ts, &up->timestamp) ||
-		copy_in_user(&up->id, &kp->id, sizeof(up->id)) ||
-		copy_in_user(up->reserved, kp->reserved, 8 * sizeof(__u32)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->type, &kp->type) ||
+	    copy_in_user(&up->u, &kp->u, sizeof(kp->u)) ||
+	    assign_in_user(&up->pending, &kp->pending) ||
+	    assign_in_user(&up->sequence, &kp->sequence) ||
+	    assign_in_user(&up->timestamp.tv_sec, &kp->timestamp.tv_sec) ||
+	    assign_in_user(&up->timestamp.tv_nsec, &kp->timestamp.tv_nsec) ||
+	    assign_in_user(&up->id, &kp->id) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -931,39 +942,34 @@
 };
 
 static int get_v4l2_edid32(struct v4l2_edid __user *kp,
-						struct v4l2_edid32 __user *up)
+			   struct v4l2_edid32 __user *up)
 {
-	u32 tmp;
+	compat_uptr_t tmp;
 
-	if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_edid32)) ||
-		!access_ok(VERIFY_WRITE, kp, sizeof(struct v4l2_edid)) ||
-		copy_in_user(&kp->pad, &up->pad, sizeof(up->pad)) ||
-		copy_in_user(&kp->start_block, &up->start_block,
-			sizeof(up->start_block)) ||
-		copy_in_user(&kp->blocks, &up->blocks, sizeof(up->blocks)) ||
-		get_user(tmp, &up->edid) ||
-		put_user(compat_ptr(tmp), &kp->edid) ||
-		copy_in_user(kp->reserved, up->reserved,
-			sizeof(kp->reserved)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_READ, up, sizeof(*up)) ||
+	    assign_in_user(&kp->pad, &up->pad) ||
+	    assign_in_user(&kp->start_block, &up->start_block) ||
+	    assign_in_user(&kp->blocks, &up->blocks) ||
+	    get_user(tmp, &up->edid) ||
+	    put_user(compat_ptr(tmp), &kp->edid) ||
+	    copy_in_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+		return -EFAULT;
 	return 0;
 }
 
 static int put_v4l2_edid32(struct v4l2_edid __user *kp,
-			struct v4l2_edid32 __user *up)
+			   struct v4l2_edid32 __user *up)
 {
-	unsigned long ptr;
+	void *edid;
 
-	if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_edid32)) ||
-		!access_ok(VERIFY_READ, kp, sizeof(struct v4l2_edid)) ||
-		copy_in_user(&up->pad, &kp->pad, sizeof(up->pad)) ||
-		copy_in_user(&up->start_block, &kp->start_block,
-			sizeof(up->start_block)) ||
-		copy_in_user(&up->blocks, &kp->blocks, sizeof(up->blocks)) ||
-		copy_from_user(&ptr, &kp->edid, sizeof(ptr)) ||
-		put_user((u32)ptr, &up->edid) ||
-		copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
-			return -EFAULT;
+	if (!access_ok(VERIFY_WRITE, up, sizeof(*up)) ||
+	    assign_in_user(&up->pad, &kp->pad) ||
+	    assign_in_user(&up->start_block, &kp->start_block) ||
+	    assign_in_user(&up->blocks, &kp->blocks) ||
+	    get_user(edid, &kp->edid) ||
+	    put_user(ptr_to_compat(edid), &up->edid) ||
+	    copy_in_user(up->reserved, kp->reserved, sizeof(up->reserved)))
+		return -EFAULT;
 	return 0;
 }
 
@@ -979,7 +985,7 @@
 #define VIDIOC_ENUMINPUT32	_IOWR('V', 26, struct v4l2_input32)
 #define VIDIOC_G_EDID32		_IOWR('V', 40, struct v4l2_edid32)
 #define VIDIOC_S_EDID32		_IOWR('V', 41, struct v4l2_edid32)
-#define VIDIOC_TRY_FMT32      	_IOWR('V', 64, struct v4l2_format32)
+#define VIDIOC_TRY_FMT32	_IOWR('V', 64, struct v4l2_format32)
 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
 #define VIDIOC_TRY_EXT_CTRLS32  _IOWR('V', 73, struct v4l2_ext_controls32)
@@ -995,30 +1001,26 @@
 #define VIDIOC_G_OUTPUT32	_IOR ('V', 46, s32)
 #define VIDIOC_S_OUTPUT32	_IOWR('V', 47, s32)
 
+static int alloc_userspace(unsigned int size, u32 aux_space,
+			   void __user **up_native)
+{
+	*up_native = compat_alloc_user_space(size + aux_space);
+	if (!*up_native)
+		return -ENOMEM;
+	if (clear_user(*up_native, size))
+		return -EFAULT;
+	return 0;
+}
+
 static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-	union {
-		struct v4l2_format v2f;
-		struct v4l2_buffer v2b;
-		struct v4l2_framebuffer v2fb;
-		struct v4l2_input v2i;
-		struct v4l2_standard v2s;
-		struct v4l2_ext_controls v2ecs;
-		struct v4l2_event v2ev;
-		struct v4l2_create_buffers v2crt;
-		struct v4l2_edid v2edid;
-		unsigned long vx;
-		int vi;
-	} *karg;
 	void __user *up = compat_ptr(arg);
+	void __user *up_native = NULL;
+	void __user *aux_buf;
+	u32 aux_space;
 	int compatible_arg = 1;
 	long err = 0;
 
-	karg = compat_alloc_user_space(sizeof(*karg));
-	if (karg == NULL) {
-		return -EFAULT;
-	}
-
 	/* First, convert the command. */
 	switch (cmd) {
 	case VIDIOC_G_FMT32: cmd = VIDIOC_G_FMT; break;
@@ -1054,31 +1056,52 @@
 	case VIDIOC_STREAMOFF:
 	case VIDIOC_S_INPUT:
 	case VIDIOC_S_OUTPUT:
-		err = copy_in_user(&karg->vi, (s32 __user *)up,
-			sizeof(karg->vi));
+		err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
+		if (!err && assign_in_user((unsigned int __user *)up_native,
+					   (compat_uint_t __user *)up))
+			err = -EFAULT;
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_INPUT:
 	case VIDIOC_G_OUTPUT:
+		err = alloc_userspace(sizeof(unsigned int), 0, &up_native);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_EDID:
 	case VIDIOC_S_EDID:
-		err = get_v4l2_edid32(&karg->v2edid, up);
+		err = alloc_userspace(sizeof(struct v4l2_edid), 0, &up_native);
+		if (!err)
+			err = get_v4l2_edid32(up_native, up);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_FMT:
 	case VIDIOC_S_FMT:
 	case VIDIOC_TRY_FMT:
-		err = get_v4l2_format32(&karg->v2f, up);
+		err = bufsize_v4l2_format(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_format),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_format);
+			err = get_v4l2_format32(up_native, up,
+						aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_CREATE_BUFS:
-		err = get_v4l2_create32(&karg->v2crt, up);
+		err = bufsize_v4l2_create(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_create_buffers),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_create_buffers);
+			err = get_v4l2_create32(up_native, up,
+						aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 
@@ -1086,36 +1109,63 @@
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
-		err = get_v4l2_buffer32(&karg->v2b, up);
+		err = bufsize_v4l2_buffer(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_buffer),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_buffer);
+			err = get_v4l2_buffer32(up_native, up,
+						aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_S_FBUF:
-		err = get_v4l2_framebuffer32(&karg->v2fb, up);
+		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
+				      &up_native);
+		if (!err)
+			err = get_v4l2_framebuffer32(up_native, up);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_FBUF:
+		err = alloc_userspace(sizeof(struct v4l2_framebuffer), 0,
+				      &up_native);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_ENUMSTD:
-		err = get_v4l2_standard32(&karg->v2s, up);
+		err = alloc_userspace(sizeof(struct v4l2_standard), 0,
+				      &up_native);
+		if (!err)
+			err = get_v4l2_standard32(up_native, up);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_ENUMINPUT:
-		err = get_v4l2_input32(&karg->v2i, up);
+		err = alloc_userspace(sizeof(struct v4l2_input), 0, &up_native);
+		if (!err)
+			err = get_v4l2_input32(up_native, up);
 		compatible_arg = 0;
 		break;
 
 	case VIDIOC_G_EXT_CTRLS:
 	case VIDIOC_S_EXT_CTRLS:
 	case VIDIOC_TRY_EXT_CTRLS:
-		err = get_v4l2_ext_controls32(&karg->v2ecs, up);
+		err = bufsize_v4l2_ext_controls(up, &aux_space);
+		if (!err)
+			err = alloc_userspace(sizeof(struct v4l2_ext_controls),
+					      aux_space, &up_native);
+		if (!err) {
+			aux_buf = up_native + sizeof(struct v4l2_ext_controls);
+			err = get_v4l2_ext_controls32(file, up_native, up,
+						      aux_buf, aux_space);
+		}
 		compatible_arg = 0;
 		break;
 	case VIDIOC_DQEVENT:
+		err = alloc_userspace(sizeof(struct v4l2_event), 0, &up_native);
 		compatible_arg = 0;
 		break;
 	}
@@ -1124,18 +1174,26 @@
 
 	if (compatible_arg)
 		err = native_ioctl(file, cmd, (unsigned long)up);
-	else {
-		err = native_ioctl(file, cmd, (unsigned long)karg);
-	}
+	else
+		err = native_ioctl(file, cmd, (unsigned long)up_native);
 
-	/* Special case: even after an error we need to put the
-	   results back for these ioctls since the error_idx will
-	   contain information on which control failed. */
+	if (err == -ENOTTY)
+		return err;
+
+	/*
+	 * Special case: even after an error we need to put the
+	 * results back for these ioctls since the error_idx will
+	 * contain information on which control failed.
+	 */
 	switch (cmd) {
 	case VIDIOC_G_EXT_CTRLS:
 	case VIDIOC_S_EXT_CTRLS:
 	case VIDIOC_TRY_EXT_CTRLS:
-		if (put_v4l2_ext_controls32(&karg->v2ecs, up))
+		if (put_v4l2_ext_controls32(file, up_native, up))
+			err = -EFAULT;
+		break;
+	case VIDIOC_S_EDID:
+		if (put_v4l2_edid32(up_native, up))
 			err = -EFAULT;
 		break;
 	}
@@ -1147,44 +1205,46 @@
 	case VIDIOC_S_OUTPUT:
 	case VIDIOC_G_INPUT:
 	case VIDIOC_G_OUTPUT:
-		err = copy_in_user(up, &karg->vi, sizeof(s32));
+		if (assign_in_user((compat_uint_t __user *)up,
+				   ((unsigned int __user *)up_native)))
+			err = -EFAULT;
 		break;
 
 	case VIDIOC_G_FBUF:
-		err = put_v4l2_framebuffer32(&karg->v2fb, up);
+		err = put_v4l2_framebuffer32(up_native, up);
 		break;
 
 	case VIDIOC_DQEVENT:
-		err = put_v4l2_event32(&karg->v2ev, up);
+		err = put_v4l2_event32(up_native, up);
 		break;
 
 	case VIDIOC_G_EDID:
-	case VIDIOC_S_EDID:
-		err = put_v4l2_edid32(&karg->v2edid, up);
+		err = put_v4l2_edid32(up_native, up);
 		break;
 
 	case VIDIOC_G_FMT:
 	case VIDIOC_S_FMT:
 	case VIDIOC_TRY_FMT:
-		err = put_v4l2_format32(&karg->v2f, up);
+		err = put_v4l2_format32(up_native, up);
 		break;
 
 	case VIDIOC_CREATE_BUFS:
-		err = put_v4l2_create32(&karg->v2crt, up);
+		err = put_v4l2_create32(up_native, up);
 		break;
 
+	case VIDIOC_PREPARE_BUF:
 	case VIDIOC_QUERYBUF:
 	case VIDIOC_QBUF:
 	case VIDIOC_DQBUF:
-		err = put_v4l2_buffer32(&karg->v2b, up);
+		err = put_v4l2_buffer32(up_native, up);
 		break;
 
 	case VIDIOC_ENUMSTD:
-		err = put_v4l2_standard32(&karg->v2s, up);
+		err = put_v4l2_standard32(up_native, up);
 		break;
 
 	case VIDIOC_ENUMINPUT:
-		err = put_v4l2_input32(&karg->v2i, up);
+		err = put_v4l2_input32(up_native, up);
 		break;
 	}
 	return err;
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 5a12b41..e2e23ff 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -2952,8 +2952,11 @@
 
 	/* Handles IOCTL */
 	err = func(file, cmd, parg);
-	if (err == -ENOIOCTLCMD)
+	if (err == -ENOTTY || err == -ENOIOCTLCMD) {
 		err = -ENOTTY;
+		goto out;
+	}
+
 	if (err == 0) {
 		if (cmd == VIDIOC_DQBUF)
 			trace_v4l2_dqbuf(video_devdata(file)->minor, parg);
diff --git a/drivers/mtd/nand/brcmnand/brcmnand.c b/drivers/mtd/nand/brcmnand/brcmnand.c
index d9fab22..1a4a790 100644
--- a/drivers/mtd/nand/brcmnand/brcmnand.c
+++ b/drivers/mtd/nand/brcmnand/brcmnand.c
@@ -2193,16 +2193,9 @@
 	if (ctrl->nand_version >= 0x0702)
 		tmp |= ACC_CONTROL_RD_ERASED;
 	tmp &= ~ACC_CONTROL_FAST_PGM_RDIN;
-	if (ctrl->features & BRCMNAND_HAS_PREFETCH) {
-		/*
-		 * FIXME: Flash DMA + prefetch may see spurious erased-page ECC
-		 * errors
-		 */
-		if (has_flash_dma(ctrl))
-			tmp &= ~ACC_CONTROL_PREFETCH;
-		else
-			tmp |= ACC_CONTROL_PREFETCH;
-	}
+	if (ctrl->features & BRCMNAND_HAS_PREFETCH)
+		tmp &= ~ACC_CONTROL_PREFETCH;
+
 	nand_writereg(ctrl, offs, tmp);
 
 	return 0;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index a77cfd7..21c0308 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -2320,6 +2320,7 @@
 static int nand_do_read_oob(struct mtd_info *mtd, loff_t from,
 			    struct mtd_oob_ops *ops)
 {
+	unsigned int max_bitflips = 0;
 	int page, realpage, chipnr;
 	struct nand_chip *chip = mtd_to_nand(mtd);
 	struct mtd_ecc_stats stats;
@@ -2377,6 +2378,8 @@
 				nand_wait_ready(mtd);
 		}
 
+		max_bitflips = max_t(unsigned int, max_bitflips, ret);
+
 		readlen -= len;
 		if (!readlen)
 			break;
@@ -2402,7 +2405,7 @@
 	if (mtd->ecc_stats.failed - stats.failed)
 		return -EBADMSG;
 
-	return  mtd->ecc_stats.corrected - stats.corrected ? -EUCLEAN : 0;
+	return max_bitflips;
 }
 
 /**
diff --git a/drivers/mtd/nand/sunxi_nand.c b/drivers/mtd/nand/sunxi_nand.c
index f9b2a77..e26c4f8 100644
--- a/drivers/mtd/nand/sunxi_nand.c
+++ b/drivers/mtd/nand/sunxi_nand.c
@@ -1835,8 +1835,14 @@
 
 	/* Add ECC info retrieval from DT */
 	for (i = 0; i < ARRAY_SIZE(strengths); i++) {
-		if (ecc->strength <= strengths[i])
+		if (ecc->strength <= strengths[i]) {
+			/*
+			 * Update ecc->strength value with the actual strength
+			 * that will be used by the ECC engine.
+			 */
+			ecc->strength = strengths[i];
 			break;
+		}
 	}
 
 	if (i >= ARRAY_SIZE(strengths)) {
diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
index d1e6931..46913ef2 100644
--- a/drivers/mtd/ubi/block.c
+++ b/drivers/mtd/ubi/block.c
@@ -99,6 +99,8 @@
 
 /* Linked list of all ubiblock instances */
 static LIST_HEAD(ubiblock_devices);
+static DEFINE_IDR(ubiblock_minor_idr);
+/* Protects ubiblock_devices and ubiblock_minor_idr */
 static DEFINE_MUTEX(devices_mutex);
 static int ubiblock_major;
 
@@ -353,8 +355,6 @@
 	.init_request	= ubiblock_init_request,
 };
 
-static DEFINE_IDR(ubiblock_minor_idr);
-
 int ubiblock_create(struct ubi_volume_info *vi)
 {
 	struct ubiblock *dev;
@@ -367,14 +367,15 @@
 	/* Check that the volume isn't already handled */
 	mutex_lock(&devices_mutex);
 	if (find_dev_nolock(vi->ubi_num, vi->vol_id)) {
-		mutex_unlock(&devices_mutex);
-		return -EEXIST;
+		ret = -EEXIST;
+		goto out_unlock;
 	}
-	mutex_unlock(&devices_mutex);
 
 	dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL);
-	if (!dev)
-		return -ENOMEM;
+	if (!dev) {
+		ret = -ENOMEM;
+		goto out_unlock;
+	}
 
 	mutex_init(&dev->dev_mutex);
 
@@ -439,14 +440,13 @@
 		goto out_free_queue;
 	}
 
-	mutex_lock(&devices_mutex);
 	list_add_tail(&dev->list, &ubiblock_devices);
-	mutex_unlock(&devices_mutex);
 
 	/* Must be the last step: anyone can call file ops from now on */
 	add_disk(dev->gd);
 	dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)",
 		 dev->ubi_num, dev->vol_id, vi->name);
+	mutex_unlock(&devices_mutex);
 	return 0;
 
 out_free_queue:
@@ -459,6 +459,8 @@
 	put_disk(dev->gd);
 out_free_dev:
 	kfree(dev);
+out_unlock:
+	mutex_unlock(&devices_mutex);
 
 	return ret;
 }
@@ -480,30 +482,36 @@
 int ubiblock_remove(struct ubi_volume_info *vi)
 {
 	struct ubiblock *dev;
+	int ret;
 
 	mutex_lock(&devices_mutex);
 	dev = find_dev_nolock(vi->ubi_num, vi->vol_id);
 	if (!dev) {
-		mutex_unlock(&devices_mutex);
-		return -ENODEV;
+		ret = -ENODEV;
+		goto out_unlock;
 	}
 
 	/* Found a device, let's lock it so we can check if it's busy */
 	mutex_lock(&dev->dev_mutex);
 	if (dev->refcnt > 0) {
-		mutex_unlock(&dev->dev_mutex);
-		mutex_unlock(&devices_mutex);
-		return -EBUSY;
+		ret = -EBUSY;
+		goto out_unlock_dev;
 	}
 
 	/* Remove from device list */
 	list_del(&dev->list);
-	mutex_unlock(&devices_mutex);
-
 	ubiblock_cleanup(dev);
 	mutex_unlock(&dev->dev_mutex);
+	mutex_unlock(&devices_mutex);
+
 	kfree(dev);
 	return 0;
+
+out_unlock_dev:
+	mutex_unlock(&dev->dev_mutex);
+out_unlock:
+	mutex_unlock(&devices_mutex);
+	return ret;
 }
 
 static int ubiblock_resize(struct ubi_volume_info *vi)
@@ -632,6 +640,7 @@
 	struct ubiblock *next;
 	struct ubiblock *dev;
 
+	mutex_lock(&devices_mutex);
 	list_for_each_entry_safe(dev, next, &ubiblock_devices, list) {
 		/* The module is being forcefully removed */
 		WARN_ON(dev->desc);
@@ -640,6 +649,7 @@
 		ubiblock_cleanup(dev);
 		kfree(dev);
 	}
+	mutex_unlock(&devices_mutex);
 }
 
 int __init ubiblock_init(void)
diff --git a/drivers/mtd/ubi/wl.c b/drivers/mtd/ubi/wl.c
index b5b8cd6..668b462 100644
--- a/drivers/mtd/ubi/wl.c
+++ b/drivers/mtd/ubi/wl.c
@@ -1529,6 +1529,46 @@
 }
 
 /**
+ * erase_aeb - erase a PEB given in UBI attach info PEB
+ * @ubi: UBI device description object
+ * @aeb: UBI attach info PEB
+ * @sync: If true, erase synchronously. Otherwise schedule for erasure
+ */
+static int erase_aeb(struct ubi_device *ubi, struct ubi_ainf_peb *aeb, bool sync)
+{
+	struct ubi_wl_entry *e;
+	int err;
+
+	e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
+	if (!e)
+		return -ENOMEM;
+
+	e->pnum = aeb->pnum;
+	e->ec = aeb->ec;
+	ubi->lookuptbl[e->pnum] = e;
+
+	if (sync) {
+		err = sync_erase(ubi, e, false);
+		if (err)
+			goto out_free;
+
+		wl_tree_add(e, &ubi->free);
+		ubi->free_count++;
+	} else {
+		err = schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false);
+		if (err)
+			goto out_free;
+	}
+
+	return 0;
+
+out_free:
+	wl_entry_destroy(ubi, e);
+
+	return err;
+}
+
+/**
  * ubi_wl_init - initialize the WL sub-system using attaching information.
  * @ubi: UBI device description object
  * @ai: attaching information
@@ -1566,18 +1606,10 @@
 	list_for_each_entry_safe(aeb, tmp, &ai->erase, u.list) {
 		cond_resched();
 
-		e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
-		if (!e)
+		err = erase_aeb(ubi, aeb, false);
+		if (err)
 			goto out_free;
 
-		e->pnum = aeb->pnum;
-		e->ec = aeb->ec;
-		ubi->lookuptbl[e->pnum] = e;
-		if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) {
-			wl_entry_destroy(ubi, e);
-			goto out_free;
-		}
-
 		found_pebs++;
 	}
 
@@ -1635,6 +1667,8 @@
 			ubi_assert(!ubi->lookuptbl[e->pnum]);
 			ubi->lookuptbl[e->pnum] = e;
 		} else {
+			bool sync = false;
+
 			/*
 			 * Usually old Fastmap PEBs are scheduled for erasure
 			 * and we don't have to care about them but if we face
@@ -1644,18 +1678,21 @@
 			if (ubi->lookuptbl[aeb->pnum])
 				continue;
 
-			e = kmem_cache_alloc(ubi_wl_entry_slab, GFP_KERNEL);
-			if (!e)
-				goto out_free;
+			/*
+			 * The fastmap update code might not find a free PEB for
+			 * writing the fastmap anchor to and then reuses the
+			 * current fastmap anchor PEB. When this PEB gets erased
+			 * and a power cut happens before it is written again we
+			 * must make sure that the fastmap attach code doesn't
+			 * find any outdated fastmap anchors, hence we erase the
+			 * outdated fastmap anchor PEBs synchronously here.
+			 */
+			if (aeb->vol_id == UBI_FM_SB_VOLUME_ID)
+				sync = true;
 
-			e->pnum = aeb->pnum;
-			e->ec = aeb->ec;
-			ubi_assert(!ubi->lookuptbl[e->pnum]);
-			ubi->lookuptbl[e->pnum] = e;
-			if (schedule_erase(ubi, e, aeb->vol_id, aeb->lnum, 0, false)) {
-				wl_entry_destroy(ubi, e);
+			err = erase_aeb(ubi, aeb, sync);
+			if (err)
 				goto out_free;
-			}
 		}
 
 		found_pebs++;
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index 62d1d07..dcec343 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -636,8 +636,8 @@
 			v->swtail = next_tail) {
 		rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom);
 		if (unlikely(rc)) {
-			wil_err(wil, "Error %d in wil_rx_refill[%d]\n",
-				rc, v->swtail);
+			wil_err_ratelimited(wil, "Error %d in rx refill[%d]\n",
+					    rc, v->swtail);
 			break;
 		}
 	}
diff --git a/drivers/of/base.c b/drivers/of/base.c
index a0bccb5..23a6d36 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -20,9 +20,11 @@
 
 #define pr_fmt(fmt)	"OF: " fmt
 
+#include <linux/bootmem.h>
 #include <linux/console.h>
 #include <linux/ctype.h>
 #include <linux/cpu.h>
+#include <linux/memblock.h>
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/of_graph.h>
@@ -198,9 +200,100 @@
 	return 0;
 }
 
+static struct device_node **phandle_cache;
+static u32 phandle_cache_mask;
+
+/*
+ * Assumptions behind phandle_cache implementation:
+ *   - phandle property values are in a contiguous range of 1..n
+ *
+ * If the assumptions do not hold, then
+ *   - the phandle lookup overhead reduction provided by the cache
+ *     will likely be less
+ */
+static void of_populate_phandle_cache(void)
+{
+	unsigned long flags;
+	u32 cache_entries;
+	struct device_node *np;
+	u32 phandles = 0;
+
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+
+	kfree(phandle_cache);
+	phandle_cache = NULL;
+
+	for_each_of_allnodes(np)
+		if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
+			phandles++;
+
+	cache_entries = roundup_pow_of_two(phandles);
+	phandle_cache_mask = cache_entries - 1;
+
+	phandle_cache = kcalloc(cache_entries, sizeof(*phandle_cache),
+				GFP_ATOMIC);
+
+	if (phandle_cache)
+		for_each_of_allnodes(np)
+			if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
+				phandle_cache[np->phandle & phandle_cache_mask] = np;
+
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+}
+
+void __init of_populate_phandle_cache_early(void)
+{
+	u32 cache_entries;
+	struct device_node *np;
+	u32 phandles = 0;
+	size_t size;
+
+	for_each_of_allnodes(np)
+		if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
+			phandles++;
+
+	cache_entries = roundup_pow_of_two(phandles);
+	phandle_cache_mask = cache_entries - 1;
+
+	size = cache_entries * sizeof(*phandle_cache);
+	phandle_cache = memblock_virt_alloc(size, 4);
+	memset(phandle_cache, 0, size);
+
+	for_each_of_allnodes(np)
+		if (np->phandle && np->phandle != OF_PHANDLE_ILLEGAL)
+			phandle_cache[np->phandle & phandle_cache_mask] = np;
+}
+
+#ifndef CONFIG_MODULES
+static int __init of_free_phandle_cache(void)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+
+	kfree(phandle_cache);
+	phandle_cache = NULL;
+
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+	return 0;
+}
+late_initcall_sync(of_free_phandle_cache);
+#endif
+
 void __init of_core_init(void)
 {
+	unsigned long flags;
 	struct device_node *np;
+	phys_addr_t size;
+
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+	size = (phandle_cache_mask + 1) * sizeof(*phandle_cache);
+	memblock_free(__pa(phandle_cache), size);
+	phandle_cache = NULL;
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+	of_populate_phandle_cache();
 
 	/* Create the kset, and register existing nodes */
 	mutex_lock(&of_mutex);
@@ -1093,16 +1186,32 @@
  */
 struct device_node *of_find_node_by_phandle(phandle handle)
 {
-	struct device_node *np;
+	struct device_node *np = NULL;
 	unsigned long flags;
+	phandle masked_handle;
 
 	if (!handle)
 		return NULL;
 
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	for_each_of_allnodes(np)
-		if (np->phandle == handle)
-			break;
+
+	masked_handle = handle & phandle_cache_mask;
+
+	if (phandle_cache) {
+		if (phandle_cache[masked_handle] &&
+		    handle == phandle_cache[masked_handle]->phandle)
+			np = phandle_cache[masked_handle];
+	}
+
+	if (!np) {
+		for_each_of_allnodes(np)
+			if (np->phandle == handle) {
+				if (phandle_cache)
+					phandle_cache[masked_handle] = np;
+				break;
+			}
+	}
+
 	of_node_get(np);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	return np;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index c0914fb..755b386 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -31,6 +31,8 @@
 #include <asm/setup.h>  /* for COMMAND_LINE_SIZE */
 #include <asm/page.h>
 
+#include "of_private.h"
+
 /*
  * of_fdt_limit_memory - limit the number of regions in the /memory node
  * @limit: maximum entries
@@ -1269,6 +1271,8 @@
 
 	/* Get pointer to "/chosen" and "/aliases" nodes for use everywhere */
 	of_alias_scan(early_init_dt_alloc_memory_arch);
+
+	of_populate_phandle_cache_early();
 }
 
 /**
diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h
index 18bbb451..c4d7fdc 100644
--- a/drivers/of/of_private.h
+++ b/drivers/of/of_private.h
@@ -86,6 +86,11 @@
 extern void __of_sysfs_remove_bin_file(struct device_node *np,
 				       struct property *prop);
 
+/* illegal phandle value (set when unresolved) */
+#define OF_PHANDLE_ILLEGAL	0xdeadbeef
+
+extern void __init of_populate_phandle_cache_early(void);
+
 /* iterators for transactions, used for overlays */
 /* forward iterator */
 #define for_each_transaction_entry(_oft, _te) \
diff --git a/drivers/of/resolver.c b/drivers/of/resolver.c
index 46325d6..67b1d72 100644
--- a/drivers/of/resolver.c
+++ b/drivers/of/resolver.c
@@ -21,9 +21,6 @@
 #include <linux/string.h>
 #include <linux/slab.h>
 
-/* illegal phandle value (set when unresolved) */
-#define OF_PHANDLE_ILLEGAL	0xdeadbeef
-
 /**
  * Find a node with the give full name by recursively following any of
  * the child node links.
diff --git a/drivers/pci/host/pci-msm.c b/drivers/pci/host/pci-msm.c
index b897813..20d48a0 100644
--- a/drivers/pci/host/pci-msm.c
+++ b/drivers/pci/host/pci-msm.c
@@ -5094,20 +5094,6 @@
 		return arch_setup_msi_irq_default(pdev, desc, 1);
 }
 
-static int msm_pcie_get_msi_multiple(int nvec)
-{
-	int msi_multiple = 0;
-
-	while (nvec) {
-		nvec = nvec >> 1;
-		msi_multiple++;
-	}
-	PCIE_GEN_DBG("log2 number of MSI multiple:%d\n",
-		msi_multiple - 1);
-
-	return msi_multiple - 1;
-}
-
 int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
 {
 	struct msi_desc *entry;
@@ -5123,7 +5109,7 @@
 
 	list_for_each_entry(entry, &dev->dev.msi_list, list) {
 		entry->msi_attrib.multiple =
-				msm_pcie_get_msi_multiple(nvec);
+			__ilog2_u32(__roundup_pow_of_two(nvec));
 
 		if (pcie_dev->msi_gicm_addr)
 			ret = arch_setup_msi_irq_qgic(dev, entry, nvec);
diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c
index b40a074..df63b7d 100644
--- a/drivers/pinctrl/intel/pinctrl-intel.c
+++ b/drivers/pinctrl/intel/pinctrl-intel.c
@@ -368,6 +368,18 @@
 	writel(value, padcfg0);
 }
 
+static void intel_gpio_set_gpio_mode(void __iomem *padcfg0)
+{
+	u32 value;
+
+	/* Put the pad into GPIO mode */
+	value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
+	/* Disable SCI/SMI/NMI generation */
+	value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
+	value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
+	writel(value, padcfg0);
+}
+
 static int intel_gpio_request_enable(struct pinctrl_dev *pctldev,
 				     struct pinctrl_gpio_range *range,
 				     unsigned pin)
@@ -375,7 +387,6 @@
 	struct intel_pinctrl *pctrl = pinctrl_dev_get_drvdata(pctldev);
 	void __iomem *padcfg0;
 	unsigned long flags;
-	u32 value;
 
 	raw_spin_lock_irqsave(&pctrl->lock, flags);
 
@@ -385,13 +396,7 @@
 	}
 
 	padcfg0 = intel_get_padcfg(pctrl, pin, PADCFG0);
-	/* Put the pad into GPIO mode */
-	value = readl(padcfg0) & ~PADCFG0_PMODE_MASK;
-	/* Disable SCI/SMI/NMI generation */
-	value &= ~(PADCFG0_GPIROUTIOXAPIC | PADCFG0_GPIROUTSCI);
-	value &= ~(PADCFG0_GPIROUTSMI | PADCFG0_GPIROUTNMI);
-	writel(value, padcfg0);
-
+	intel_gpio_set_gpio_mode(padcfg0);
 	/* Disable TX buffer and enable RX (this will be input) */
 	__intel_gpio_set_direction(padcfg0, true);
 
@@ -770,6 +775,8 @@
 
 	raw_spin_lock_irqsave(&pctrl->lock, flags);
 
+	intel_gpio_set_gpio_mode(reg);
+
 	value = readl(reg);
 
 	value &= ~(PADCFG0_RXEVCFG_MASK | PADCFG0_RXINV);
diff --git a/drivers/pinctrl/qcom/Kconfig b/drivers/pinctrl/qcom/Kconfig
index 6515ce4..695f30e 100644
--- a/drivers/pinctrl/qcom/Kconfig
+++ b/drivers/pinctrl/qcom/Kconfig
@@ -89,6 +89,16 @@
 	  Technologies Inc MSM8953 platform.
 	  If unsure say N.
 
+config PINCTRL_MSM8909
+       tristate "Qualcomm Technologies Inc MSM8909 pin controller driver"
+       depends on GPIOLIB && OF && (ARCH_MSM8909 || COMPILE_TEST)
+       select PINCTRL_MSM
+       help
+	  This is the pinctrl, pinmux, pinconf and gpiolib driver for the
+	  Qualcomm Technologies Inc TLMM block found on the Qualcomm
+	  Technologies Inc MSM8909 platform.
+	  If unsure say N.
+
 config PINCTRL_MSM8937
 	tristate "Qualcomm Technologies Inc MSM8937 pin controller driver"
 	depends on GPIOLIB && OF
diff --git a/drivers/pinctrl/qcom/Makefile b/drivers/pinctrl/qcom/Makefile
index db71677..2df5d18 100644
--- a/drivers/pinctrl/qcom/Makefile
+++ b/drivers/pinctrl/qcom/Makefile
@@ -12,6 +12,7 @@
 obj-$(CONFIG_PINCTRL_QDF2XXX)	+= pinctrl-qdf2xxx.o
 obj-$(CONFIG_PINCTRL_MDM9615)	+= pinctrl-mdm9615.o
 obj-$(CONFIG_PINCTRL_MSM8953)   += pinctrl-msm8953.o
+obj-$(CONFIG_PINCTRL_MSM8909)   += pinctrl-msm8909.o
 obj-$(CONFIG_PINCTRL_MSM8937)   += pinctrl-msm8937.o
 obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-gpio.o
 obj-$(CONFIG_PINCTRL_QCOM_SPMI_PMIC) += pinctrl-spmi-mpp.o
diff --git a/drivers/pinctrl/qcom/pinctrl-msm.c b/drivers/pinctrl/qcom/pinctrl-msm.c
index 1441678..9e1c8d2 100644
--- a/drivers/pinctrl/qcom/pinctrl-msm.c
+++ b/drivers/pinctrl/qcom/pinctrl-msm.c
@@ -25,6 +25,7 @@
 #include <linux/pinctrl/pinmux.h>
 #include <linux/pinctrl/pinconf.h>
 #include <linux/pinctrl/pinconf-generic.h>
+#include <linux/of_irq.h>
 #include <linux/slab.h>
 #include <linux/gpio.h>
 #include <linux/interrupt.h>
@@ -583,6 +584,9 @@
 	clear_bit(d->hwirq, pctrl->enabled_irqs);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	if (d->parent_data)
+		irq_chip_mask_parent(d);
 }
 
 static void msm_gpio_irq_enable(struct irq_data *d)
@@ -611,6 +615,9 @@
 	set_bit(d->hwirq, pctrl->enabled_irqs);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	if (d->parent_data)
+		irq_chip_enable_parent(d);
 }
 
 static void msm_gpio_irq_unmask(struct irq_data *d)
@@ -632,6 +639,9 @@
 	set_bit(d->hwirq, pctrl->enabled_irqs);
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
+
+	if (d->parent_data)
+		irq_chip_unmask_parent(d);
 }
 
 static void msm_gpio_irq_ack(struct irq_data *d)
@@ -745,6 +755,9 @@
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 
+	if (d->parent_data)
+		irq_chip_set_type_parent(d, type);
+
 	if (type & (IRQ_TYPE_LEVEL_LOW | IRQ_TYPE_LEVEL_HIGH))
 		irq_set_handler_locked(d, handle_level_irq);
 	else if (type & (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING))
@@ -765,9 +778,35 @@
 
 	spin_unlock_irqrestore(&pctrl->lock, flags);
 
+	if (d->parent_data)
+		irq_chip_set_wake_parent(d, on);
+
 	return 0;
 }
 
+static int msm_gpiochip_irq_reqres(struct irq_data *d)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+
+	if (!try_module_get(chip->owner))
+		return -ENODEV;
+
+	if (gpiochip_lock_as_irq(chip, d->hwirq)) {
+		pr_err("unable to lock HW IRQ %lu for IRQ\n", d->hwirq);
+		module_put(chip->owner);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void msm_gpiochip_irq_relres(struct irq_data *d)
+{
+	struct gpio_chip *chip = irq_data_get_irq_chip_data(d);
+
+	gpiochip_unlock_as_irq(chip, d->hwirq);
+	module_put(chip->owner);
+}
+
 static struct irq_chip msm_gpio_irq_chip = {
 	.name           = "msmgpio",
 	.irq_enable     = msm_gpio_irq_enable,
@@ -776,6 +815,65 @@
 	.irq_ack        = msm_gpio_irq_ack,
 	.irq_set_type   = msm_gpio_irq_set_type,
 	.irq_set_wake   = msm_gpio_irq_set_wake,
+	.irq_request_resources    = msm_gpiochip_irq_reqres,
+	.irq_release_resources	  = msm_gpiochip_irq_relres,
+	.flags                    = IRQCHIP_MASK_ON_SUSPEND |
+					IRQCHIP_SKIP_SET_WAKE,
+};
+
+static void msm_gpio_domain_set_info(struct irq_domain *d, unsigned int irq,
+							irq_hw_number_t hwirq)
+{
+	struct gpio_chip *gc = d->host_data;
+
+	irq_domain_set_info(d, irq, hwirq, gc->irqchip, d->host_data,
+		gc->irq_handler, NULL, NULL);
+
+	if (gc->can_sleep && !gc->irq_not_threaded)
+		irq_set_nested_thread(irq, 1);
+
+	irq_set_noprobe(irq);
+}
+
+static int msm_gpio_domain_translate(struct irq_domain *d,
+	struct irq_fwspec *fwspec, unsigned long *hwirq, unsigned int *type)
+{
+	if (is_of_node(fwspec->fwnode)) {
+		if (fwspec->param_count < 2)
+			return -EINVAL;
+		if (hwirq)
+			*hwirq = fwspec->param[0];
+		if (type)
+			*type = fwspec->param[1] & IRQ_TYPE_SENSE_MASK;
+		return 0;
+	}
+
+	return -EINVAL;
+}
+
+static int msm_gpio_domain_alloc(struct irq_domain *domain, unsigned int virq,
+					unsigned int nr_irqs, void *arg)
+{
+	int ret = 0;
+	irq_hw_number_t hwirq;
+	struct irq_fwspec *fwspec = arg, parent_fwspec;
+
+	ret = msm_gpio_domain_translate(domain, fwspec, &hwirq, NULL);
+	if (ret)
+		return ret;
+
+	msm_gpio_domain_set_info(domain, virq, hwirq);
+
+	parent_fwspec = *fwspec;
+	parent_fwspec.fwnode = domain->parent->fwnode;
+	return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs,
+						&parent_fwspec);
+}
+
+static const struct irq_domain_ops msm_gpio_domain_ops = {
+	.translate	= msm_gpio_domain_translate,
+	.alloc		= msm_gpio_domain_alloc,
+	.free		= irq_domain_free_irqs_top,
 };
 
 static struct irq_chip msm_dirconn_irq_chip;
@@ -1299,11 +1397,25 @@
 	}
 }
 
+static int msm_gpiochip_to_irq(struct gpio_chip *chip, unsigned int offset)
+{
+	struct irq_fwspec fwspec;
+
+	fwspec.fwnode = of_node_to_fwnode(chip->of_node);
+	fwspec.param[0] = offset;
+	fwspec.param[1] = IRQ_TYPE_NONE;
+	fwspec.param_count = 2;
+
+	return irq_create_fwspec_mapping(&fwspec);
+}
+
 static int msm_gpio_init(struct msm_pinctrl *pctrl)
 {
 	struct gpio_chip *chip;
 	int ret;
 	unsigned ngpio = pctrl->soc->ngpios;
+	struct device_node *irq_parent = NULL;
+	struct irq_domain *domain_parent;
 
 	if (WARN_ON(ngpio > MAX_NR_GPIO))
 		return -EINVAL;
@@ -1329,19 +1441,45 @@
 		return ret;
 	}
 
-	ret = gpiochip_irqchip_add(chip,
-				   &msm_gpio_irq_chip,
-				   0,
-				   handle_fasteoi_irq,
-				   IRQ_TYPE_NONE);
-	if (ret) {
-		dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
-		gpiochip_remove(&pctrl->chip);
-		return -ENOSYS;
-	}
+	irq_parent = of_irq_find_parent(chip->of_node);
+	if (of_device_is_compatible(irq_parent, "qcom,mpm-gpio")) {
+		chip->irqchip = &msm_gpio_irq_chip;
+		chip->irq_handler = handle_fasteoi_irq;
+		chip->irq_default_type = IRQ_TYPE_NONE;
+		chip->to_irq = msm_gpiochip_to_irq;
+		chip->lock_key = NULL;
+		domain_parent = irq_find_host(irq_parent);
+		if (!domain_parent) {
+			pr_err("unable to find parent domain\n");
+			gpiochip_remove(&pctrl->chip);
+			return -ENXIO;
+		}
 
-	gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip, pctrl->irq,
-				     msm_gpio_irq_handler);
+		chip->irqdomain = irq_domain_add_hierarchy(domain_parent, 0,
+							chip->ngpio,
+							chip->of_node,
+							&msm_gpio_domain_ops,
+							chip);
+		if (!chip->irqdomain) {
+			dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
+			chip->irqchip = NULL;
+			gpiochip_remove(&pctrl->chip);
+			return -ENXIO;
+		}
+	} else {
+		ret = gpiochip_irqchip_add(chip,
+					&msm_gpio_irq_chip,
+					0,
+					handle_fasteoi_irq,
+					IRQ_TYPE_NONE);
+		if (ret) {
+			dev_err(pctrl->dev, "Failed to add irqchip to gpiochip\n");
+			gpiochip_remove(&pctrl->chip);
+			return ret;
+		}
+	}
+	gpiochip_set_chained_irqchip(chip, &msm_gpio_irq_chip,
+				pctrl->irq, msm_gpio_irq_handler);
 
 	msm_gpio_setup_dir_connects(pctrl);
 	return 0;
diff --git a/drivers/pinctrl/qcom/pinctrl-msm8909.c b/drivers/pinctrl/qcom/pinctrl-msm8909.c
new file mode 100644
index 0000000..c8c3de7
--- /dev/null
+++ b/drivers/pinctrl/qcom/pinctrl-msm8909.c
@@ -0,0 +1,1299 @@
+/*
+ * Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/pinctrl/pinctrl.h>
+
+#include "pinctrl-msm.h"
+
+#define FUNCTION(fname)			                \
+	[msm_mux_##fname] = {		                \
+		.name = #fname,				\
+		.groups = fname##_groups,               \
+		.ngroups = ARRAY_SIZE(fname##_groups),	\
+	}
+
+#define REG_BASE 0x0
+#define REG_SIZE 0x1000
+#define PINGROUP(id, f1, f2, f3, f4, f5, f6, f7, f8, f9)	\
+	{					        \
+		.name = "gpio" #id,			\
+		.pins = gpio##id##_pins,		\
+		.npins = (unsigned int)ARRAY_SIZE(gpio##id##_pins),	\
+		.funcs = (int[]){			\
+			msm_mux_gpio, /* gpio mode */	\
+			msm_mux_##f1,			\
+			msm_mux_##f2,			\
+			msm_mux_##f3,			\
+			msm_mux_##f4,			\
+			msm_mux_##f5,			\
+			msm_mux_##f6,			\
+			msm_mux_##f7,			\
+			msm_mux_##f8,			\
+			msm_mux_##f9			\
+		},				        \
+		.nfuncs = 10,				\
+		.ctl_reg = REG_BASE + REG_SIZE * id,			\
+		.io_reg = REG_BASE + 0x4 + REG_SIZE * id,		\
+		.intr_cfg_reg = REG_BASE + 0x8 + REG_SIZE * id,		\
+		.intr_status_reg = REG_BASE + 0xc + REG_SIZE * id,	\
+		.intr_target_reg = REG_BASE + 0x8 + REG_SIZE * id,	\
+		.mux_bit = 2,			\
+		.pull_bit = 0,			\
+		.drv_bit = 6,			\
+		.oe_bit = 9,			\
+		.in_bit = 0,			\
+		.out_bit = 1,			\
+		.intr_enable_bit = 0,		\
+		.intr_status_bit = 0,		\
+		.intr_target_bit = 5,		\
+		.intr_target_kpss_val = 4,       \
+		.intr_raw_status_bit = 4,	\
+		.intr_polarity_bit = 1,		\
+		.intr_detection_bit = 2,	\
+		.intr_detection_width = 2,	\
+	}
+
+#define SDC_QDSD_PINGROUP(pg_name, ctl, pull, drv)	\
+	{					        \
+		.name = #pg_name,			\
+		.pins = pg_name##_pins,			\
+		.npins = (unsigned int)ARRAY_SIZE(pg_name##_pins),	\
+		.ctl_reg = ctl,				\
+		.io_reg = 0,				\
+		.intr_cfg_reg = 0,			\
+		.intr_status_reg = 0,			\
+		.intr_target_reg = 0,			\
+		.mux_bit = -1,				\
+		.pull_bit = pull,			\
+		.drv_bit = drv,				\
+		.oe_bit = -1,				\
+		.in_bit = -1,				\
+		.out_bit = -1,				\
+		.intr_enable_bit = -1,			\
+		.intr_status_bit = -1,			\
+		.intr_target_bit = -1,			\
+		.intr_raw_status_bit = -1,		\
+		.intr_polarity_bit = -1,		\
+		.intr_detection_bit = -1,		\
+		.intr_detection_width = -1,		\
+	}
+static const struct pinctrl_pin_desc msm8909_pins[] = {
+	PINCTRL_PIN(0, "GPIO_0"),
+	PINCTRL_PIN(1, "GPIO_1"),
+	PINCTRL_PIN(2, "GPIO_2"),
+	PINCTRL_PIN(3, "GPIO_3"),
+	PINCTRL_PIN(4, "GPIO_4"),
+	PINCTRL_PIN(5, "GPIO_5"),
+	PINCTRL_PIN(6, "GPIO_6"),
+	PINCTRL_PIN(7, "GPIO_7"),
+	PINCTRL_PIN(8, "GPIO_8"),
+	PINCTRL_PIN(9, "GPIO_9"),
+	PINCTRL_PIN(10, "GPIO_10"),
+	PINCTRL_PIN(11, "GPIO_11"),
+	PINCTRL_PIN(12, "GPIO_12"),
+	PINCTRL_PIN(13, "GPIO_13"),
+	PINCTRL_PIN(14, "GPIO_14"),
+	PINCTRL_PIN(15, "GPIO_15"),
+	PINCTRL_PIN(16, "GPIO_16"),
+	PINCTRL_PIN(17, "GPIO_17"),
+	PINCTRL_PIN(18, "GPIO_18"),
+	PINCTRL_PIN(19, "GPIO_19"),
+	PINCTRL_PIN(20, "GPIO_20"),
+	PINCTRL_PIN(21, "GPIO_21"),
+	PINCTRL_PIN(22, "GPIO_22"),
+	PINCTRL_PIN(23, "GPIO_23"),
+	PINCTRL_PIN(24, "GPIO_24"),
+	PINCTRL_PIN(25, "GPIO_25"),
+	PINCTRL_PIN(26, "GPIO_26"),
+	PINCTRL_PIN(27, "GPIO_27"),
+	PINCTRL_PIN(28, "GPIO_28"),
+	PINCTRL_PIN(29, "GPIO_29"),
+	PINCTRL_PIN(30, "GPIO_30"),
+	PINCTRL_PIN(31, "GPIO_31"),
+	PINCTRL_PIN(32, "GPIO_32"),
+	PINCTRL_PIN(33, "GPIO_33"),
+	PINCTRL_PIN(34, "GPIO_34"),
+	PINCTRL_PIN(35, "GPIO_35"),
+	PINCTRL_PIN(36, "GPIO_36"),
+	PINCTRL_PIN(37, "GPIO_37"),
+	PINCTRL_PIN(38, "GPIO_38"),
+	PINCTRL_PIN(39, "GPIO_39"),
+	PINCTRL_PIN(40, "GPIO_40"),
+	PINCTRL_PIN(41, "GPIO_41"),
+	PINCTRL_PIN(42, "GPIO_42"),
+	PINCTRL_PIN(43, "GPIO_43"),
+	PINCTRL_PIN(44, "GPIO_44"),
+	PINCTRL_PIN(45, "GPIO_45"),
+	PINCTRL_PIN(46, "GPIO_46"),
+	PINCTRL_PIN(47, "GPIO_47"),
+	PINCTRL_PIN(48, "GPIO_48"),
+	PINCTRL_PIN(49, "GPIO_49"),
+	PINCTRL_PIN(50, "GPIO_50"),
+	PINCTRL_PIN(51, "GPIO_51"),
+	PINCTRL_PIN(52, "GPIO_52"),
+	PINCTRL_PIN(53, "GPIO_53"),
+	PINCTRL_PIN(54, "GPIO_54"),
+	PINCTRL_PIN(55, "GPIO_55"),
+	PINCTRL_PIN(56, "GPIO_56"),
+	PINCTRL_PIN(57, "GPIO_57"),
+	PINCTRL_PIN(58, "GPIO_58"),
+	PINCTRL_PIN(59, "GPIO_59"),
+	PINCTRL_PIN(60, "GPIO_60"),
+	PINCTRL_PIN(61, "GPIO_61"),
+	PINCTRL_PIN(62, "GPIO_62"),
+	PINCTRL_PIN(63, "GPIO_63"),
+	PINCTRL_PIN(64, "GPIO_64"),
+	PINCTRL_PIN(65, "GPIO_65"),
+	PINCTRL_PIN(66, "GPIO_66"),
+	PINCTRL_PIN(67, "GPIO_67"),
+	PINCTRL_PIN(68, "GPIO_68"),
+	PINCTRL_PIN(69, "GPIO_69"),
+	PINCTRL_PIN(70, "GPIO_70"),
+	PINCTRL_PIN(71, "GPIO_71"),
+	PINCTRL_PIN(72, "GPIO_72"),
+	PINCTRL_PIN(73, "GPIO_73"),
+	PINCTRL_PIN(74, "GPIO_74"),
+	PINCTRL_PIN(75, "GPIO_75"),
+	PINCTRL_PIN(76, "GPIO_76"),
+	PINCTRL_PIN(77, "GPIO_77"),
+	PINCTRL_PIN(78, "GPIO_78"),
+	PINCTRL_PIN(79, "GPIO_79"),
+	PINCTRL_PIN(80, "GPIO_80"),
+	PINCTRL_PIN(81, "GPIO_81"),
+	PINCTRL_PIN(82, "GPIO_82"),
+	PINCTRL_PIN(83, "GPIO_83"),
+	PINCTRL_PIN(84, "GPIO_84"),
+	PINCTRL_PIN(85, "GPIO_85"),
+	PINCTRL_PIN(86, "GPIO_86"),
+	PINCTRL_PIN(87, "GPIO_87"),
+	PINCTRL_PIN(88, "GPIO_88"),
+	PINCTRL_PIN(89, "GPIO_89"),
+	PINCTRL_PIN(90, "GPIO_90"),
+	PINCTRL_PIN(91, "GPIO_91"),
+	PINCTRL_PIN(92, "GPIO_92"),
+	PINCTRL_PIN(93, "GPIO_93"),
+	PINCTRL_PIN(94, "GPIO_94"),
+	PINCTRL_PIN(95, "GPIO_95"),
+	PINCTRL_PIN(96, "GPIO_96"),
+	PINCTRL_PIN(97, "GPIO_97"),
+	PINCTRL_PIN(98, "GPIO_98"),
+	PINCTRL_PIN(99, "GPIO_99"),
+	PINCTRL_PIN(100, "GPIO_100"),
+	PINCTRL_PIN(101, "GPIO_101"),
+	PINCTRL_PIN(102, "GPIO_102"),
+	PINCTRL_PIN(103, "GPIO_103"),
+	PINCTRL_PIN(104, "GPIO_104"),
+	PINCTRL_PIN(105, "GPIO_105"),
+	PINCTRL_PIN(106, "GPIO_106"),
+	PINCTRL_PIN(107, "GPIO_107"),
+	PINCTRL_PIN(108, "GPIO_108"),
+	PINCTRL_PIN(109, "GPIO_109"),
+	PINCTRL_PIN(110, "GPIO_110"),
+	PINCTRL_PIN(111, "GPIO_111"),
+	PINCTRL_PIN(112, "GPIO_112"),
+	PINCTRL_PIN(113, "SDC1_CLK"),
+	PINCTRL_PIN(114, "SDC1_CMD"),
+	PINCTRL_PIN(115, "SDC1_DATA"),
+	PINCTRL_PIN(116, "SDC2_CLK"),
+	PINCTRL_PIN(117, "SDC2_CMD"),
+	PINCTRL_PIN(118, "SDC2_DATA"),
+	PINCTRL_PIN(119, "QDSD_CLK"),
+	PINCTRL_PIN(120, "QDSD_CMD"),
+	PINCTRL_PIN(121, "QDSD_DATA0"),
+	PINCTRL_PIN(122, "QDSD_DATA1"),
+	PINCTRL_PIN(123, "QDSD_DATA2"),
+	PINCTRL_PIN(124, "QDSD_DATA3"),
+};
+
+#define DECLARE_MSM_GPIO_PINS(pin) \
+	static const unsigned int gpio##pin##_pins[] = { pin }
+DECLARE_MSM_GPIO_PINS(0);
+DECLARE_MSM_GPIO_PINS(1);
+DECLARE_MSM_GPIO_PINS(2);
+DECLARE_MSM_GPIO_PINS(3);
+DECLARE_MSM_GPIO_PINS(4);
+DECLARE_MSM_GPIO_PINS(5);
+DECLARE_MSM_GPIO_PINS(6);
+DECLARE_MSM_GPIO_PINS(7);
+DECLARE_MSM_GPIO_PINS(8);
+DECLARE_MSM_GPIO_PINS(9);
+DECLARE_MSM_GPIO_PINS(10);
+DECLARE_MSM_GPIO_PINS(11);
+DECLARE_MSM_GPIO_PINS(12);
+DECLARE_MSM_GPIO_PINS(13);
+DECLARE_MSM_GPIO_PINS(14);
+DECLARE_MSM_GPIO_PINS(15);
+DECLARE_MSM_GPIO_PINS(16);
+DECLARE_MSM_GPIO_PINS(17);
+DECLARE_MSM_GPIO_PINS(18);
+DECLARE_MSM_GPIO_PINS(19);
+DECLARE_MSM_GPIO_PINS(20);
+DECLARE_MSM_GPIO_PINS(21);
+DECLARE_MSM_GPIO_PINS(22);
+DECLARE_MSM_GPIO_PINS(23);
+DECLARE_MSM_GPIO_PINS(24);
+DECLARE_MSM_GPIO_PINS(25);
+DECLARE_MSM_GPIO_PINS(26);
+DECLARE_MSM_GPIO_PINS(27);
+DECLARE_MSM_GPIO_PINS(28);
+DECLARE_MSM_GPIO_PINS(29);
+DECLARE_MSM_GPIO_PINS(30);
+DECLARE_MSM_GPIO_PINS(31);
+DECLARE_MSM_GPIO_PINS(32);
+DECLARE_MSM_GPIO_PINS(33);
+DECLARE_MSM_GPIO_PINS(34);
+DECLARE_MSM_GPIO_PINS(35);
+DECLARE_MSM_GPIO_PINS(36);
+DECLARE_MSM_GPIO_PINS(37);
+DECLARE_MSM_GPIO_PINS(38);
+DECLARE_MSM_GPIO_PINS(39);
+DECLARE_MSM_GPIO_PINS(40);
+DECLARE_MSM_GPIO_PINS(41);
+DECLARE_MSM_GPIO_PINS(42);
+DECLARE_MSM_GPIO_PINS(43);
+DECLARE_MSM_GPIO_PINS(44);
+DECLARE_MSM_GPIO_PINS(45);
+DECLARE_MSM_GPIO_PINS(46);
+DECLARE_MSM_GPIO_PINS(47);
+DECLARE_MSM_GPIO_PINS(48);
+DECLARE_MSM_GPIO_PINS(49);
+DECLARE_MSM_GPIO_PINS(50);
+DECLARE_MSM_GPIO_PINS(51);
+DECLARE_MSM_GPIO_PINS(52);
+DECLARE_MSM_GPIO_PINS(53);
+DECLARE_MSM_GPIO_PINS(54);
+DECLARE_MSM_GPIO_PINS(55);
+DECLARE_MSM_GPIO_PINS(56);
+DECLARE_MSM_GPIO_PINS(57);
+DECLARE_MSM_GPIO_PINS(58);
+DECLARE_MSM_GPIO_PINS(59);
+DECLARE_MSM_GPIO_PINS(60);
+DECLARE_MSM_GPIO_PINS(61);
+DECLARE_MSM_GPIO_PINS(62);
+DECLARE_MSM_GPIO_PINS(63);
+DECLARE_MSM_GPIO_PINS(64);
+DECLARE_MSM_GPIO_PINS(65);
+DECLARE_MSM_GPIO_PINS(66);
+DECLARE_MSM_GPIO_PINS(67);
+DECLARE_MSM_GPIO_PINS(68);
+DECLARE_MSM_GPIO_PINS(69);
+DECLARE_MSM_GPIO_PINS(70);
+DECLARE_MSM_GPIO_PINS(71);
+DECLARE_MSM_GPIO_PINS(72);
+DECLARE_MSM_GPIO_PINS(73);
+DECLARE_MSM_GPIO_PINS(74);
+DECLARE_MSM_GPIO_PINS(75);
+DECLARE_MSM_GPIO_PINS(76);
+DECLARE_MSM_GPIO_PINS(77);
+DECLARE_MSM_GPIO_PINS(78);
+DECLARE_MSM_GPIO_PINS(79);
+DECLARE_MSM_GPIO_PINS(80);
+DECLARE_MSM_GPIO_PINS(81);
+DECLARE_MSM_GPIO_PINS(82);
+DECLARE_MSM_GPIO_PINS(83);
+DECLARE_MSM_GPIO_PINS(84);
+DECLARE_MSM_GPIO_PINS(85);
+DECLARE_MSM_GPIO_PINS(86);
+DECLARE_MSM_GPIO_PINS(87);
+DECLARE_MSM_GPIO_PINS(88);
+DECLARE_MSM_GPIO_PINS(89);
+DECLARE_MSM_GPIO_PINS(90);
+DECLARE_MSM_GPIO_PINS(91);
+DECLARE_MSM_GPIO_PINS(92);
+DECLARE_MSM_GPIO_PINS(93);
+DECLARE_MSM_GPIO_PINS(94);
+DECLARE_MSM_GPIO_PINS(95);
+DECLARE_MSM_GPIO_PINS(96);
+DECLARE_MSM_GPIO_PINS(97);
+DECLARE_MSM_GPIO_PINS(98);
+DECLARE_MSM_GPIO_PINS(99);
+DECLARE_MSM_GPIO_PINS(100);
+DECLARE_MSM_GPIO_PINS(101);
+DECLARE_MSM_GPIO_PINS(102);
+DECLARE_MSM_GPIO_PINS(103);
+DECLARE_MSM_GPIO_PINS(104);
+DECLARE_MSM_GPIO_PINS(105);
+DECLARE_MSM_GPIO_PINS(106);
+DECLARE_MSM_GPIO_PINS(107);
+DECLARE_MSM_GPIO_PINS(108);
+DECLARE_MSM_GPIO_PINS(109);
+DECLARE_MSM_GPIO_PINS(110);
+DECLARE_MSM_GPIO_PINS(111);
+DECLARE_MSM_GPIO_PINS(112);
+
+static const unsigned int sdc1_clk_pins[] = { 113 };
+static const unsigned int sdc1_cmd_pins[] = { 114 };
+static const unsigned int sdc1_data_pins[] = { 115 };
+static const unsigned int sdc2_clk_pins[] = { 116 };
+static const unsigned int sdc2_cmd_pins[] = { 117 };
+static const unsigned int sdc2_data_pins[] = { 118 };
+static const unsigned int qdsd_clk_pins[] = { 119 };
+static const unsigned int qdsd_cmd_pins[] = { 120 };
+static const unsigned int qdsd_data0_pins[] = { 121 };
+static const unsigned int qdsd_data1_pins[] = { 122 };
+static const unsigned int qdsd_data2_pins[] = { 123 };
+static const unsigned int qdsd_data3_pins[] = { 124 };
+
+enum msm8909_functions {
+	msm_mux_blsp_spi3,
+	msm_mux_gpio,
+	msm_mux_sec_mi2s,
+	msm_mux_blsp_spi1,
+	msm_mux_blsp_uart1,
+	msm_mux_blsp_uim1,
+	msm_mux_blsp3_spi,
+	msm_mux_dmic0_clk,
+	msm_mux_qdss_tracectl_b,
+	msm_mux_blsp2_spi,
+	msm_mux_dmic0_data,
+	msm_mux_qdss_traceclk_b,
+	msm_mux_blsp_i2c1,
+	msm_mux_qdss_tracedata_a,
+	msm_mux_bimc_dte0,
+	msm_mux_bimc_dte1,
+	msm_mux_blsp_spi6,
+	msm_mux_m_voc,
+	msm_mux_blsp_i2c6,
+	msm_mux_dbg_out,
+	msm_mux_blsp_spi4,
+	msm_mux_gcc_gp2_clk_b,
+	msm_mux_gcc_gp3_clk_b,
+	msm_mux_blsp_i2c4,
+	msm_mux_gcc_gp1_clk_b,
+	msm_mux_qdss_tracedata_b,
+	msm_mux_blsp_spi5,
+	msm_mux_blsp_i2c5,
+	msm_mux_uim3_clk,
+	msm_mux_qdss_cti_trig_out_a0,
+	msm_mux_mdp_vsync,
+	msm_mux_ebi2_lcd,
+	msm_mux_dsi_rst,
+	msm_mux_cam_mclk,
+	msm_mux_uim3_data,
+	msm_mux_blsp_spi2,
+	msm_mux_blsp_uart2,
+	msm_mux_blsp_uim2,
+	msm_mux_qdss_cti_trig_in_a0,
+	msm_mux_uim3_present,
+	msm_mux_qdss_cti_trig_in_b0,
+	msm_mux_uim3_reset,
+	msm_mux_qdss_cti_trig_out_b0,
+	msm_mux_webcam1_rst,
+	msm_mux_pwr_modem_enabled_a,
+	msm_mux_blsp_i2c3,
+	msm_mux_flash_strobe,
+	msm_mux_cci_timer0,
+	msm_mux_cci_timer1,
+	msm_mux_atest_combodac_to_gpio_native,
+	msm_mux_cci_async,
+	msm_mux_cam1_standby,
+	msm_mux_pwr_nav_enabled_a,
+	msm_mux_cam1_rst,
+	msm_mux_pwr_crypto_enabled_a,
+	msm_mux_atest_bbrx1,
+	msm_mux_backlight_en,
+	msm_mux_blsp1_spi,
+	msm_mux_atest_bbrx0,
+	msm_mux_sd_card,
+	msm_mux_cci_timer2,
+	msm_mux_adsp_ext,
+	msm_mux_wcss_bt,
+	msm_mux_wcss_wlan2,
+	msm_mux_wcss_wlan1,
+	msm_mux_wcss_wlan0,
+	msm_mux_wcss_wlan,
+	msm_mux_prng_rosc,
+	msm_mux_wcss_fm,
+	msm_mux_ext_lpass,
+	msm_mux_qdss_tracectl_a,
+	msm_mux_qdss_traceclk_a,
+	msm_mux_uim2_data,
+	msm_mux_gcc_gp1_clk_a,
+	msm_mux_qdss_cti_trig_in_a1,
+	msm_mux_uim2_clk,
+	msm_mux_gcc_gp2_clk_a,
+	msm_mux_qdss_cti_trig_in_b1,
+	msm_mux_uim2_reset,
+	msm_mux_gcc_gp3_clk_a,
+	msm_mux_qdss_cti_trig_out_b1,
+	msm_mux_uim2_present,
+	msm_mux_qdss_cti_trig_out_a1,
+	msm_mux_uim1_data,
+	msm_mux_uim1_clk,
+	msm_mux_uim1_reset,
+	msm_mux_uim1_present,
+	msm_mux_uim_batt,
+	msm_mux_smb_int,
+	msm_mux_cdc_pdm0,
+	msm_mux_pri_mi2s_mclk_a,
+	msm_mux_atest_char3,
+	msm_mux_pri_mi2s_sck_a,
+	msm_mux_atest_char2,
+	msm_mux_pri_mi2s_ws_a,
+	msm_mux_atest_char1,
+	msm_mux_pri_mi2s_data0_a,
+	msm_mux_atest_char0,
+	msm_mux_atest_gpsadc_dtest0_native,
+	msm_mux_gcc_plltest,
+	msm_mux_pri_mi2s_data1_a,
+	msm_mux_atest_char,
+	msm_mux_atest_tsens,
+	msm_mux_ebi0_wrcdc,
+	msm_mux_mag_int,
+	msm_mux_atest_gpsadc_dtest1_native,
+	msm_mux_pa_indicator,
+	msm_mux_modem_tsync,
+	msm_mux_nav_tsync,
+	msm_mux_nav_pps,
+	msm_mux_gsm0_tx,
+	msm_mux_ssbi0,
+	msm_mux_ssbi1,
+	msm_mux_kpsns0,
+	msm_mux_pbs0,
+	msm_mux_kpsns1,
+	msm_mux_pbs1,
+	msm_mux_kpsns2,
+	msm_mux_pbs2,
+	msm_mux_ext_buck,
+	msm_mux_alsp_int,
+	msm_mux_pri_mi2s_sck_b,
+	msm_mux_pwr_modem_enabled_b,
+	msm_mux_pri_mi2s_data0_b,
+	msm_mux_pwr_nav_enabled_b,
+	msm_mux_gyro_accl,
+	msm_mux_pri_mi2s_data1_b,
+	msm_mux_pwr_crypto_enabled_b,
+	msm_mux_atest_wlan0,
+	msm_mux_euro_us,
+	msm_mux_atest_wlan1,
+	msm_mux_pri_mi2s_mclk_b,
+	msm_mux_ldo_update,
+	msm_mux_gcc_tlmm,
+	msm_mux_ebi2_a,
+	msm_mux_sd_write,
+	msm_mux_ldo_en,
+	msm_mux_msim_int,
+	msm_mux_pri_mi2s_ws_b,
+	msm_mux_blsp_i2c2,
+	msm_mux_NA,
+};
+
+static const char * const blsp_spi3_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3",
+};
+static const char * const gpio_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7",
+	"gpio8", "gpio9", "gpio10", "gpio11", "gpio12", "gpio13", "gpio14",
+	"gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21",
+	"gpio22", "gpio23", "gpio24", "gpio25", "gpio26", "gpio27", "gpio28",
+	"gpio29", "gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35",
+	"gpio36", "gpio37", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42",
+	"gpio43", "gpio44", "gpio45", "gpio46", "gpio47", "gpio48", "gpio49",
+	"gpio50",  "gpio51", "gpio52", "gpio53", "gpio54", "gpio55", "gpio56",
+	"gpio57", "gpio58", "gpio59", "gpio60", "gpio61", "gpio62", "gpio63",
+	"gpio64",  "gpio65", "gpio66", "gpio67", "gpio68", "gpio69", "gpio70",
+	"gpio71", "gpio72", "gpio73", "gpio74", "gpio75", "gpio76", "gpio77",
+	"gpio78", "gpio79", "gpio80", "gpio81", "gpio82", "gpio83", "gpio84",
+	"gpio85", "gpio86", "gpio87", "gpio88", "gpio89", "gpio90", "gpio91",
+	"gpio92", "gpio93", "gpio94", "gpio95", "gpio96", "gpio97", "gpio98",
+	"gpio99", "gpio100", "gpio101", "gpio102", "gpio103", "gpio104",
+	"gpio105", "gpio106", "gpio107", "gpio108", "gpio109", "gpio110",
+	"gpio111", "gpio112",
+};
+static const char * const sec_mi2s_groups[] = {
+	"gpio0", "gpio1", "gpio2", "gpio3", "gpio98",
+};
+static const char * const blsp_spi1_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uart1_groups[] = {
+	"gpio4", "gpio5", "gpio6", "gpio7",
+};
+static const char * const blsp_uim1_groups[] = {
+	"gpio4", "gpio5",
+};
+static const char * const blsp3_spi_groups[] = {
+	"gpio4", "gpio65", "gpio95",
+};
+static const char * const dmic0_clk_groups[] = {
+	"gpio4",
+};
+static const char * const qdss_tracectl_b_groups[] = {
+	"gpio4",
+};
+static const char * const blsp2_spi_groups[] = {
+	"gpio5", "gpio17", "gpio98",
+};
+static const char * const dmic0_data_groups[] = {
+	"gpio5",
+};
+static const char * const qdss_traceclk_b_groups[] = {
+	"gpio5",
+};
+static const char * const blsp_i2c1_groups[] = {
+	"gpio6", "gpio7",
+};
+static const char * const qdss_tracedata_a_groups[] = {
+	"gpio6", "gpio8", "gpio9", "gpio10", "gpio39", "gpio40", "gpio41",
+	"gpio42", "gpio43", "gpio47", "gpio48", "gpio58", "gpio65", "gpio94",
+	"gpio96", "gpio97",
+};
+static const char * const bimc_dte0_groups[] = {
+	"gpio6", "gpio59",
+};
+static const char * const bimc_dte1_groups[] = {
+	"gpio7", "gpio60",
+};
+static const char * const blsp_spi6_groups[] = {
+	"gpio8", "gpio9", "gpio10", "gpio11",
+};
+static const char * const m_voc_groups[] = {
+	"gpio8", "gpio95",
+};
+static const char * const blsp_i2c6_groups[] = {
+	"gpio10", "gpio11",
+};
+static const char * const dbg_out_groups[] = {
+	"gpio10",
+};
+static const char * const blsp_spi4_groups[] = {
+	"gpio12", "gpio13", "gpio14", "gpio15",
+};
+static const char * const gcc_gp2_clk_b_groups[] = {
+	"gpio12",
+};
+static const char * const gcc_gp3_clk_b_groups[] = {
+	"gpio13",
+};
+static const char * const blsp_i2c4_groups[] = {
+	"gpio14", "gpio15",
+};
+static const char * const gcc_gp1_clk_b_groups[] = {
+	"gpio14",
+};
+static const char * const qdss_tracedata_b_groups[] = {
+	"gpio14", "gpio16", "gpio17", "gpio26", "gpio27", "gpio28", "gpio29",
+	"gpio30", "gpio31", "gpio32", "gpio33", "gpio34", "gpio35", "gpio36",
+	"gpio37", "gpio93",
+};
+static const char * const blsp_spi5_groups[] = {
+	"gpio16", "gpio17", "gpio18", "gpio19",
+};
+static const char * const blsp_i2c5_groups[] = {
+	"gpio18", "gpio19",
+};
+static const char * const uim3_clk_groups[] = {
+	"gpio23",
+};
+static const char * const qdss_cti_trig_out_a0_groups[] = {
+	"gpio23",
+};
+static const char * const mdp_vsync_groups[] = {
+	"gpio24", "gpio25",
+};
+static const char * const ebi2_lcd_groups[] = {
+	"gpio24", "gpio24", "gpio25", "gpio95",
+};
+static const char * const dsi_rst_groups[] = {
+	"gpio25",
+};
+static const char * const cam_mclk_groups[] = {
+	"gpio26", "gpio27",
+};
+static const char * const uim3_data_groups[] = {
+	"gpio20",
+};
+static const char * const blsp_spi2_groups[] = {
+	"gpio20", "gpio21", "gpio111", "gpio112",
+};
+static const char * const blsp_uart2_groups[] = {
+	"gpio20", "gpio21", "gpio111", "gpio112",
+};
+static const char * const blsp_uim2_groups[] = {
+	"gpio20", "gpio21",
+};
+static const char * const qdss_cti_trig_in_a0_groups[] = {
+	"gpio20",
+};
+static const char * const uim3_present_groups[] = {
+	"gpio21",
+};
+static const char * const qdss_cti_trig_in_b0_groups[] = {
+	"gpio21",
+};
+static const char * const uim3_reset_groups[] = {
+	"gpio22",
+};
+static const char * const qdss_cti_trig_out_b0_groups[] = {
+	"gpio22",
+};
+static const char * const webcam1_rst_groups[] = {
+	"gpio28",
+};
+static const char * const pwr_modem_enabled_a_groups[] = {
+	"gpio28",
+};
+static const char * const blsp_i2c3_groups[] = {
+	"gpio29", "gpio30",
+};
+static const char * const flash_strobe_groups[] = {
+	"gpio31", "gpio32",
+};
+static const char * const cci_timer0_groups[] = {
+	"gpio31",
+};
+static const char * const cci_timer1_groups[] = {
+	"gpio32",
+};
+static const char * const atest_combodac_to_gpio_native_groups[] = {
+	"gpio32", "gpio38", "gpio39", "gpio40", "gpio41", "gpio42", "gpio43",
+	"gpio44", "gpio45", "gpio47", "gpio48", "gpio66", "gpio81", "gpio83",
+	"gpio84", "gpio85", "gpio86", "gpio94", "gpio95", "gpio110",
+};
+static const char * const cci_async_groups[] = {
+	"gpio33",
+};
+static const char * const cam1_standby_groups[] = {
+	"gpio34",
+};
+static const char * const pwr_nav_enabled_a_groups[] = {
+	"gpio34",
+};
+static const char * const cam1_rst_groups[] = {
+	"gpio35",
+};
+static const char * const pwr_crypto_enabled_a_groups[] = {
+	"gpio35",
+};
+static const char * const atest_bbrx1_groups[] = {
+	"gpio36",
+};
+static const char * const backlight_en_groups[] = {
+	"gpio37",
+};
+static const char * const blsp1_spi_groups[] = {
+	"gpio37", "gpio65", "gpio97",
+};
+static const char * const atest_bbrx0_groups[] = {
+	"gpio37",
+};
+static const char * const sd_card_groups[] = {
+	"gpio38",
+};
+static const char * const cci_timer2_groups[] = {
+	"gpio38",
+};
+static const char * const adsp_ext_groups[] = {
+	"gpio38",
+};
+static const char * const wcss_bt_groups[] = {
+	"gpio39", "gpio47", "gpio48",
+};
+static const char * const wcss_wlan2_groups[] = {
+	"gpio40",
+};
+static const char * const wcss_wlan1_groups[] = {
+	"gpio41",
+};
+static const char * const wcss_wlan0_groups[] = {
+	"gpio42",
+};
+static const char * const wcss_wlan_groups[] = {
+	"gpio43", "gpio44",
+};
+static const char * const prng_rosc_groups[] = {
+	"gpio43",
+};
+static const char * const wcss_fm_groups[] = {
+	"gpio45", "gpio46",
+};
+static const char * const ext_lpass_groups[] = {
+	"gpio45",
+};
+static const char * const qdss_tracectl_a_groups[] = {
+	"gpio45",
+};
+static const char * const qdss_traceclk_a_groups[] = {
+	"gpio46",
+};
+static const char * const uim2_data_groups[] = {
+	"gpio49",
+};
+static const char * const gcc_gp1_clk_a_groups[] = {
+	"gpio49",
+};
+static const char * const qdss_cti_trig_in_a1_groups[] = {
+	"gpio49",
+};
+static const char * const uim2_clk_groups[] = {
+	"gpio50",
+};
+static const char * const gcc_gp2_clk_a_groups[] = {
+	"gpio50",
+};
+static const char * const qdss_cti_trig_in_b1_groups[] = {
+	"gpio50",
+};
+static const char * const uim2_reset_groups[] = {
+	"gpio51",
+};
+static const char * const gcc_gp3_clk_a_groups[] = {
+	"gpio51",
+};
+static const char * const qdss_cti_trig_out_b1_groups[] = {
+	"gpio51",
+};
+static const char * const uim2_present_groups[] = {
+	"gpio52",
+};
+static const char * const qdss_cti_trig_out_a1_groups[] = {
+	"gpio52",
+};
+static const char * const uim1_data_groups[] = {
+	"gpio53",
+};
+static const char * const uim1_clk_groups[] = {
+	"gpio54",
+};
+static const char * const uim1_reset_groups[] = {
+	"gpio55",
+};
+static const char * const uim1_present_groups[] = {
+	"gpio56",
+};
+static const char * const uim_batt_groups[] = {
+	"gpio57",
+};
+static const char * const smb_int_groups[] = {
+	"gpio58",
+};
+static const char * const cdc_pdm0_groups[] = {
+	"gpio59", "gpio60", "gpio61", "gpio62", "gpio63", "gpio64",
+};
+static const char * const pri_mi2s_mclk_a_groups[] = {
+	"gpio59",
+};
+static const char * const atest_char3_groups[] = {
+	"gpio59",
+};
+static const char * const pri_mi2s_sck_a_groups[] = {
+	"gpio60",
+};
+static const char * const atest_char2_groups[] = {
+	"gpio60",
+};
+static const char * const pri_mi2s_ws_a_groups[] = {
+	"gpio61",
+};
+static const char * const atest_char1_groups[] = {
+	"gpio61",
+};
+static const char * const pri_mi2s_data0_a_groups[] = {
+	"gpio62",
+};
+static const char * const atest_char0_groups[] = {
+	"gpio62",
+};
+static const char * const atest_gpsadc_dtest0_native_groups[] = {
+	"gpio65",
+};
+static const char * const gcc_plltest_groups[] = {
+	"gpio66", "gpio67",
+};
+static const char * const pri_mi2s_data1_a_groups[] = {
+	"gpio63",
+};
+static const char * const atest_char_groups[] = {
+	"gpio63",
+};
+static const char * const atest_tsens_groups[] = {
+	"gpio63",
+};
+static const char * const ebi0_wrcdc_groups[] = {
+	"gpio64",
+};
+static const char * const mag_int_groups[] = {
+	"gpio65",
+};
+static const char * const atest_gpsadc_dtest1_native_groups[] = {
+	"gpio79",
+};
+static const char * const pa_indicator_groups[] = {
+	"gpio82",
+};
+static const char * const modem_tsync_groups[] = {
+	"gpio83",
+};
+static const char * const nav_tsync_groups[] = {
+	"gpio83",
+};
+static const char * const nav_pps_groups[] = {
+	"gpio83",
+};
+static const char * const gsm0_tx_groups[] = {
+	"gpio85",
+};
+static const char * const ssbi0_groups[] = {
+	"gpio88",
+};
+static const char * const ssbi1_groups[] = {
+	"gpio89",
+};
+static const char * const kpsns0_groups[] = {
+	"gpio90",
+};
+static const char * const pbs0_groups[] = {
+	"gpio90",
+};
+static const char * const kpsns1_groups[] = {
+	"gpio91",
+};
+static const char * const pbs1_groups[] = {
+	"gpio91",
+};
+static const char * const kpsns2_groups[] = {
+	"gpio92",
+};
+static const char * const pbs2_groups[] = {
+	"gpio92",
+};
+static const char * const ext_buck_groups[] = {
+	"gpio93",
+};
+static const char * const alsp_int_groups[] = {
+	"gpio94",
+};
+static const char * const pri_mi2s_sck_b_groups[] = {
+	"gpio94",
+};
+static const char * const pwr_modem_enabled_b_groups[] = {
+	"gpio94",
+};
+static const char * const pri_mi2s_data0_b_groups[] = {
+	"gpio95",
+};
+static const char * const pwr_nav_enabled_b_groups[] = {
+	"gpio95",
+};
+static const char * const gyro_accl_groups[] = {
+	"gpio96",
+};
+static const char * const pri_mi2s_data1_b_groups[] = {
+	"gpio96",
+};
+static const char * const pwr_crypto_enabled_b_groups[] = {
+	"gpio96",
+};
+static const char * const atest_wlan0_groups[] = {
+	"gpio96",
+};
+static const char * const euro_us_groups[] = {
+	"gpio97",
+};
+static const char * const atest_wlan1_groups[] = {
+	"gpio97",
+};
+static const char * const pri_mi2s_mclk_b_groups[] = {
+	"gpio98",
+};
+static const char * const ldo_update_groups[] = {
+	"gpio98",
+};
+static const char * const gcc_tlmm_groups[] = {
+	"gpio98",
+};
+static const char * const ebi2_a_groups[] = {
+	"gpio99",
+};
+static const char * const sd_write_groups[] = {
+	"gpio99",
+};
+static const char * const ldo_en_groups[] = {
+	"gpio99",
+};
+static const char * const msim_int_groups[] = {
+	"gpio110",
+};
+static const char * const pri_mi2s_ws_b_groups[] = {
+	"gpio110",
+};
+static const char * const blsp_i2c2_groups[] = {
+	"gpio111", "gpio112",
+};
+
+static const struct msm_function msm8909_functions[] = {
+	FUNCTION(blsp_spi3),
+	FUNCTION(gpio),
+	FUNCTION(sec_mi2s),
+	FUNCTION(blsp_spi1),
+	FUNCTION(blsp_uart1),
+	FUNCTION(blsp_uim1),
+	FUNCTION(blsp3_spi),
+	FUNCTION(dmic0_clk),
+	FUNCTION(qdss_tracectl_b),
+	FUNCTION(blsp2_spi),
+	FUNCTION(dmic0_data),
+	FUNCTION(qdss_traceclk_b),
+	FUNCTION(blsp_i2c1),
+	FUNCTION(qdss_tracedata_a),
+	FUNCTION(bimc_dte0),
+	FUNCTION(bimc_dte1),
+	FUNCTION(blsp_spi6),
+	FUNCTION(m_voc),
+	FUNCTION(blsp_i2c6),
+	FUNCTION(dbg_out),
+	FUNCTION(blsp_spi4),
+	FUNCTION(gcc_gp2_clk_b),
+	FUNCTION(gcc_gp3_clk_b),
+	FUNCTION(blsp_i2c4),
+	FUNCTION(gcc_gp1_clk_b),
+	FUNCTION(qdss_tracedata_b),
+	FUNCTION(blsp_spi5),
+	FUNCTION(blsp_i2c5),
+	FUNCTION(uim3_clk),
+	FUNCTION(qdss_cti_trig_out_a0),
+	FUNCTION(mdp_vsync),
+	FUNCTION(ebi2_lcd),
+	FUNCTION(dsi_rst),
+	FUNCTION(cam_mclk),
+	FUNCTION(uim3_data),
+	FUNCTION(blsp_spi2),
+	FUNCTION(blsp_uart2),
+	FUNCTION(blsp_uim2),
+	FUNCTION(qdss_cti_trig_in_a0),
+	FUNCTION(uim3_present),
+	FUNCTION(qdss_cti_trig_in_b0),
+	FUNCTION(uim3_reset),
+	FUNCTION(qdss_cti_trig_out_b0),
+	FUNCTION(webcam1_rst),
+	FUNCTION(pwr_modem_enabled_a),
+	FUNCTION(blsp_i2c3),
+	FUNCTION(flash_strobe),
+	FUNCTION(cci_timer0),
+	FUNCTION(cci_timer1),
+	FUNCTION(atest_combodac_to_gpio_native),
+	FUNCTION(cci_async),
+	FUNCTION(cam1_standby),
+	FUNCTION(pwr_nav_enabled_a),
+	FUNCTION(cam1_rst),
+	FUNCTION(pwr_crypto_enabled_a),
+	FUNCTION(atest_bbrx1),
+	FUNCTION(backlight_en),
+	FUNCTION(blsp1_spi),
+	FUNCTION(atest_bbrx0),
+	FUNCTION(sd_card),
+	FUNCTION(cci_timer2),
+	FUNCTION(adsp_ext),
+	FUNCTION(wcss_bt),
+	FUNCTION(wcss_wlan2),
+	FUNCTION(wcss_wlan1),
+	FUNCTION(wcss_wlan0),
+	FUNCTION(wcss_wlan),
+	FUNCTION(prng_rosc),
+	FUNCTION(wcss_fm),
+	FUNCTION(ext_lpass),
+	FUNCTION(qdss_tracectl_a),
+	FUNCTION(qdss_traceclk_a),
+	FUNCTION(uim2_data),
+	FUNCTION(gcc_gp1_clk_a),
+	FUNCTION(qdss_cti_trig_in_a1),
+	FUNCTION(uim2_clk),
+	FUNCTION(gcc_gp2_clk_a),
+	FUNCTION(qdss_cti_trig_in_b1),
+	FUNCTION(uim2_reset),
+	FUNCTION(gcc_gp3_clk_a),
+	FUNCTION(qdss_cti_trig_out_b1),
+	FUNCTION(uim2_present),
+	FUNCTION(qdss_cti_trig_out_a1),
+	FUNCTION(uim1_data),
+	FUNCTION(uim1_clk),
+	FUNCTION(uim1_reset),
+	FUNCTION(uim1_present),
+	FUNCTION(uim_batt),
+	FUNCTION(smb_int),
+	FUNCTION(cdc_pdm0),
+	FUNCTION(pri_mi2s_mclk_a),
+	FUNCTION(atest_char3),
+	FUNCTION(pri_mi2s_sck_a),
+	FUNCTION(atest_char2),
+	FUNCTION(pri_mi2s_ws_a),
+	FUNCTION(atest_char1),
+	FUNCTION(pri_mi2s_data0_a),
+	FUNCTION(atest_char0),
+	FUNCTION(atest_gpsadc_dtest0_native),
+	FUNCTION(gcc_plltest),
+	FUNCTION(pri_mi2s_data1_a),
+	FUNCTION(atest_char),
+	FUNCTION(atest_tsens),
+	FUNCTION(ebi0_wrcdc),
+	FUNCTION(mag_int),
+	FUNCTION(atest_gpsadc_dtest1_native),
+	FUNCTION(pa_indicator),
+	FUNCTION(modem_tsync),
+	FUNCTION(nav_tsync),
+	FUNCTION(nav_pps),
+	FUNCTION(gsm0_tx),
+	FUNCTION(ssbi0),
+	FUNCTION(ssbi1),
+	FUNCTION(kpsns0),
+	FUNCTION(pbs0),
+	FUNCTION(kpsns1),
+	FUNCTION(pbs1),
+	FUNCTION(kpsns2),
+	FUNCTION(pbs2),
+	FUNCTION(ext_buck),
+	FUNCTION(alsp_int),
+	FUNCTION(pri_mi2s_sck_b),
+	FUNCTION(pwr_modem_enabled_b),
+	FUNCTION(pri_mi2s_data0_b),
+	FUNCTION(pwr_nav_enabled_b),
+	FUNCTION(gyro_accl),
+	FUNCTION(pri_mi2s_data1_b),
+	FUNCTION(pwr_crypto_enabled_b),
+	FUNCTION(atest_wlan0),
+	FUNCTION(euro_us),
+	FUNCTION(atest_wlan1),
+	FUNCTION(pri_mi2s_mclk_b),
+	FUNCTION(ldo_update),
+	FUNCTION(gcc_tlmm),
+	FUNCTION(ebi2_a),
+	FUNCTION(sd_write),
+	FUNCTION(ldo_en),
+	FUNCTION(msim_int),
+	FUNCTION(pri_mi2s_ws_b),
+	FUNCTION(blsp_i2c2),
+};
+
+static const struct msm_pingroup msm8909_groups[] = {
+	PINGROUP(0, blsp_spi3, sec_mi2s, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(1, blsp_spi3, sec_mi2s, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(2, blsp_spi3, sec_mi2s, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(3, blsp_spi3, sec_mi2s, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(4, blsp_spi1, blsp_uart1, blsp_uim1, blsp3_spi, dmic0_clk, NA,
+		 NA, NA, NA),
+	PINGROUP(5, blsp_spi1, blsp_uart1, blsp_uim1, blsp2_spi, dmic0_data,
+		 NA, NA, NA, NA),
+	PINGROUP(6, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(7, blsp_spi1, blsp_uart1, blsp_i2c1, NA, NA, NA, NA, NA,
+		 bimc_dte1),
+	PINGROUP(8, blsp_spi6, m_voc, NA, NA, NA, NA, NA, qdss_tracedata_a, NA),
+	PINGROUP(9, blsp_spi6, NA, NA, NA, NA, NA, qdss_tracedata_a, NA, NA),
+	PINGROUP(10, blsp_spi6, blsp_i2c6, dbg_out, qdss_tracedata_a, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(11, blsp_spi6, blsp_i2c6, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(12, blsp_spi4, gcc_gp2_clk_b, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(13, blsp_spi4, gcc_gp3_clk_b, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(14, blsp_spi4, blsp_i2c4, gcc_gp1_clk_b, NA, NA, NA, NA, NA,
+		 qdss_tracedata_b),
+	PINGROUP(15, blsp_spi4, blsp_i2c4, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(16, blsp_spi5, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, NA),
+	PINGROUP(17, blsp_spi5, blsp2_spi, NA, NA, NA, NA, NA,
+		 qdss_tracedata_b, NA),
+	PINGROUP(18, blsp_spi5, blsp_i2c5, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(19, blsp_spi5, blsp_i2c5, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(20, uim3_data, blsp_spi2, blsp_uart2, blsp_uim2, NA,
+		 qdss_cti_trig_in_a0, NA, NA, NA),
+	PINGROUP(21, uim3_present, blsp_spi2, blsp_uart2, blsp_uim2, NA,
+		 qdss_cti_trig_in_b0, NA, NA, NA),
+	PINGROUP(22, uim3_reset, NA, qdss_cti_trig_out_b0, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(23, uim3_clk, qdss_cti_trig_out_a0, NA, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(24, mdp_vsync, ebi2_lcd, ebi2_lcd, NA, NA, NA, NA, NA, NA),
+	PINGROUP(25, mdp_vsync, ebi2_lcd, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(26, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(27, cam_mclk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(28, NA, pwr_modem_enabled_a, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(29, blsp_i2c3, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, NA),
+	PINGROUP(30, blsp_i2c3, NA, NA, NA, NA, NA, qdss_tracedata_b, NA, NA),
+	PINGROUP(31, cci_timer0, NA, NA, NA, NA, NA, NA, qdss_tracedata_b, NA),
+	PINGROUP(32, cci_timer1, NA, qdss_tracedata_b, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(33, cci_async, qdss_tracedata_b, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(34, pwr_nav_enabled_a, qdss_tracedata_b, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(35, pwr_crypto_enabled_a, qdss_tracedata_b, NA, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(36, qdss_tracedata_b, NA, atest_bbrx1, NA, NA, NA, NA, NA, NA),
+	PINGROUP(37, blsp1_spi, qdss_tracedata_b, NA, atest_bbrx0, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(38, cci_timer2, adsp_ext, NA, atest_combodac_to_gpio_native,
+		 NA, NA, NA, NA, NA),
+	PINGROUP(39, wcss_bt, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(40, wcss_wlan2, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(41, wcss_wlan1, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(42, wcss_wlan0, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(43, wcss_wlan, prng_rosc, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(44, wcss_wlan, NA, atest_combodac_to_gpio_native, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(45, wcss_fm, ext_lpass, qdss_tracectl_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(46, wcss_fm, qdss_traceclk_a, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(47, wcss_bt, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(48, wcss_bt, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA, NA),
+	PINGROUP(49, uim2_data, gcc_gp1_clk_a, qdss_cti_trig_in_a1, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(50, uim2_clk, gcc_gp2_clk_a, qdss_cti_trig_in_b1, NA, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(51, uim2_reset, gcc_gp3_clk_a, qdss_cti_trig_out_b1, NA, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(52, uim2_present, qdss_cti_trig_out_a1, NA, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(53, uim1_data, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(54, uim1_clk, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(55, uim1_reset, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(56, uim1_present, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(57, uim_batt, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(58, qdss_tracedata_a, smb_int, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(59, cdc_pdm0, pri_mi2s_mclk_a, atest_char3, NA, NA, NA, NA,
+		 NA, bimc_dte0),
+	PINGROUP(60, cdc_pdm0, pri_mi2s_sck_a, atest_char2, NA, NA, NA, NA, NA,
+		 bimc_dte1),
+	PINGROUP(61, cdc_pdm0, pri_mi2s_ws_a, atest_char1, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(62, cdc_pdm0, pri_mi2s_data0_a, atest_char0, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(63, cdc_pdm0, pri_mi2s_data1_a, atest_char, NA, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(64, cdc_pdm0, NA, NA, NA, NA, NA, ebi0_wrcdc, NA, NA),
+	PINGROUP(65, blsp3_spi, blsp1_spi, qdss_tracedata_a, NA,
+		 atest_gpsadc_dtest0_native, NA, NA, NA, NA),
+	PINGROUP(66, NA, gcc_plltest, NA, atest_combodac_to_gpio_native, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(67, NA, gcc_plltest, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(68, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(69, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(70, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(71, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(72, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(73, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(74, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(75, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(76, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(77, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(78, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(79, NA, NA, atest_gpsadc_dtest1_native, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(80, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(81, NA, NA, NA, atest_combodac_to_gpio_native, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(82, NA, pa_indicator, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(83, NA, modem_tsync, nav_tsync, nav_pps, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA),
+	PINGROUP(84, NA, NA, atest_combodac_to_gpio_native, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(85, gsm0_tx, NA, NA, atest_combodac_to_gpio_native, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(86, NA, NA, atest_combodac_to_gpio_native, NA, NA, NA, NA, NA,
+		 NA),
+	PINGROUP(87, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(88, NA, ssbi0, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(89, NA, ssbi1, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(90, pbs0, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(91, pbs1, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(92, pbs2, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(93, qdss_tracedata_b, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(94, pri_mi2s_sck_b, pwr_modem_enabled_b, qdss_tracedata_a, NA,
+		 atest_combodac_to_gpio_native, NA, NA, NA, NA),
+	PINGROUP(95, blsp3_spi, pri_mi2s_data0_b, ebi2_lcd, m_voc,
+		 pwr_nav_enabled_b, NA, atest_combodac_to_gpio_native, NA, NA),
+	PINGROUP(96, pri_mi2s_data1_b, NA, pwr_crypto_enabled_b,
+		 qdss_tracedata_a, NA, atest_wlan0, NA, NA, NA),
+	PINGROUP(97, blsp1_spi, qdss_tracedata_a, NA, atest_wlan1, NA, NA, NA,
+		 NA, NA),
+	PINGROUP(98, sec_mi2s, pri_mi2s_mclk_b, blsp2_spi, ldo_update, NA, NA,
+		 NA, NA, NA),
+	PINGROUP(99, ebi2_a, sd_write, ldo_en, NA, NA, NA, NA, NA, NA),
+	PINGROUP(100, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(101, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(102, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(103, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(104, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(105, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(106, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(107, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(108, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(109, NA, NA, NA, NA, NA, NA, NA, NA, NA),
+	PINGROUP(110, pri_mi2s_ws_b, NA, atest_combodac_to_gpio_native, NA, NA,
+		 NA, NA, NA, NA),
+	PINGROUP(111, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA),
+	PINGROUP(112, blsp_spi2, blsp_uart2, blsp_i2c2, NA, NA, NA, NA, NA, NA),
+	SDC_QDSD_PINGROUP(sdc1_clk, 0x10a000, 13, 6),
+	SDC_QDSD_PINGROUP(sdc1_cmd, 0x10a000, 11, 3),
+	SDC_QDSD_PINGROUP(sdc1_data, 0x10a000, 9, 0),
+	SDC_QDSD_PINGROUP(sdc2_clk, 0x109000, 14, 6),
+	SDC_QDSD_PINGROUP(sdc2_cmd, 0x109000, 11, 3),
+	SDC_QDSD_PINGROUP(sdc2_data, 0x109000, 9, 0),
+	SDC_QDSD_PINGROUP(qdsd_clk, 0x19c000, 3, 0),
+	SDC_QDSD_PINGROUP(qdsd_cmd, 0x19c000, 8, 5),
+	SDC_QDSD_PINGROUP(qdsd_data0, 0x19c000, 13, 10),
+	SDC_QDSD_PINGROUP(qdsd_data1, 0x19c000, 18, 15),
+	SDC_QDSD_PINGROUP(qdsd_data2, 0x19c000, 23, 20),
+	SDC_QDSD_PINGROUP(qdsd_data3, 0x19c000, 28, 25),
+};
+
+static const struct msm_pinctrl_soc_data msm8909_pinctrl = {
+	.pins = msm8909_pins,
+	.npins = ARRAY_SIZE(msm8909_pins),
+	.functions = msm8909_functions,
+	.nfunctions = ARRAY_SIZE(msm8909_functions),
+	.groups = msm8909_groups,
+	.ngroups = ARRAY_SIZE(msm8909_groups),
+	.ngpios = 113,
+};
+
+static int msm8909_pinctrl_probe(struct platform_device *pdev)
+{
+	return msm_pinctrl_probe(pdev, &msm8909_pinctrl);
+}
+
+static const struct of_device_id msm8909_pinctrl_of_match[] = {
+	{ .compatible = "qcom,msm8909-pinctrl", },
+	{ },
+};
+
+static struct platform_driver msm8909_pinctrl_driver = {
+	.driver = {
+		.name = "msm8909-pinctrl",
+		.owner = THIS_MODULE,
+		.of_match_table = msm8909_pinctrl_of_match,
+	},
+	.probe = msm8909_pinctrl_probe,
+	.remove = msm_pinctrl_remove,
+};
+
+static int __init msm8909_pinctrl_init(void)
+{
+	return platform_driver_register(&msm8909_pinctrl_driver);
+}
+arch_initcall(msm8909_pinctrl_init);
+
+static void __exit msm8909_pinctrl_exit(void)
+{
+	platform_driver_unregister(&msm8909_pinctrl_driver);
+}
+module_exit(msm8909_pinctrl_exit);
+
+MODULE_DESCRIPTION("QTI msm8909 pinctrl driver");
+MODULE_LICENSE("GPL v2");
+MODULE_DEVICE_TABLE(of, msm8909_pinctrl_of_match);
diff --git a/drivers/platform/msm/Kconfig b/drivers/platform/msm/Kconfig
index 4abd8f1..782ce62 100644
--- a/drivers/platform/msm/Kconfig
+++ b/drivers/platform/msm/Kconfig
@@ -163,7 +163,7 @@
 
 config MSM_MHI_DEV
         tristate "Modem Device Interface Driver"
-	depends on EP_PCIE && IPA
+	depends on EP_PCIE && IPA3
         help
           This kernel module is used to interact with PCIe Root complex
           supporting MHI protocol. MHI is a data transmission protocol
diff --git a/drivers/platform/msm/ipa/ipa_api.c b/drivers/platform/msm/ipa/ipa_api.c
index bf498f9..b99435d 100644
--- a/drivers/platform/msm/ipa/ipa_api.c
+++ b/drivers/platform/msm/ipa/ipa_api.c
@@ -3167,52 +3167,53 @@
 EXPORT_SYMBOL(ipa_get_smmu_params);
 
 /**
- * ipa_conn_wdi3_pipes() - connect wdi3 pipes
+ * ipa_conn_wdi_pipes() - connect wdi pipes
  */
-int ipa_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
-	struct ipa_wdi3_conn_out_params *out)
+int ipa_conn_wdi_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out,
+	ipa_wdi_meter_notifier_cb wdi_notify)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_conn_wdi3_pipes, in, out);
+	IPA_API_DISPATCH_RETURN(ipa_conn_wdi_pipes, in, out, wdi_notify);
 
 	return ret;
 }
 
 /**
- * ipa_disconn_wdi3_pipes() - disconnect wdi3 pipes
+ * ipa_disconn_wdi_pipes() - disconnect wdi pipes
  */
-int ipa_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa_disconn_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_disconn_wdi3_pipes, ipa_ep_idx_tx,
+	IPA_API_DISPATCH_RETURN(ipa_disconn_wdi_pipes, ipa_ep_idx_tx,
 		ipa_ep_idx_rx);
 
 	return ret;
 }
 
 /**
- * ipa_enable_wdi3_pipes() - enable wdi3 pipes
+ * ipa_enable_wdi_pipes() - enable wdi pipes
  */
-int ipa_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa_enable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_enable_wdi3_pipes, ipa_ep_idx_tx,
+	IPA_API_DISPATCH_RETURN(ipa_enable_wdi_pipes, ipa_ep_idx_tx,
 		ipa_ep_idx_rx);
 
 	return ret;
 }
 
 /**
- * ipa_disable_wdi3_pipes() - disable wdi3 pipes
+ * ipa_disable_wdi_pipes() - disable wdi pipes
  */
-int ipa_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
+int ipa_disable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx)
 {
 	int ret;
 
-	IPA_API_DISPATCH_RETURN(ipa_disable_wdi3_pipes, ipa_ep_idx_tx,
+	IPA_API_DISPATCH_RETURN(ipa_disable_wdi_pipes, ipa_ep_idx_tx,
 		ipa_ep_idx_rx);
 
 	return ret;
diff --git a/drivers/platform/msm/ipa/ipa_api.h b/drivers/platform/msm/ipa/ipa_api.h
index 79d0c70..fc4362f 100644
--- a/drivers/platform/msm/ipa/ipa_api.h
+++ b/drivers/platform/msm/ipa/ipa_api.h
@@ -403,16 +403,17 @@
 
 	void (*ipa_ntn_uc_dereg_rdyCB)(void);
 
-	int (*ipa_conn_wdi3_pipes)(struct ipa_wdi3_conn_in_params *in,
-		struct ipa_wdi3_conn_out_params *out);
+	int (*ipa_conn_wdi_pipes)(struct ipa_wdi_conn_in_params *in,
+		struct ipa_wdi_conn_out_params *out,
+		ipa_wdi_meter_notifier_cb wdi_notify);
 
-	int (*ipa_disconn_wdi3_pipes)(int ipa_ep_idx_tx,
+	int (*ipa_disconn_wdi_pipes)(int ipa_ep_idx_tx,
 		int ipa_ep_idx_rx);
 
-	int (*ipa_enable_wdi3_pipes)(int ipa_ep_idx_tx,
+	int (*ipa_enable_wdi_pipes)(int ipa_ep_idx_tx,
 		int ipa_ep_idx_rx);
 
-	int (*ipa_disable_wdi3_pipes)(int ipa_ep_idx_tx,
+	int (*ipa_disable_wdi_pipes)(int ipa_ep_idx_tx,
 		int ipa_ep_idx_rx);
 
 	int (*ipa_tz_unlock_reg)(struct ipa_tz_unlock_reg_info *reg_info,
diff --git a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
index eadd58b..9f8bfbe 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ecm_ipa.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -619,8 +619,10 @@
 	}
 
 	if (ecm_ipa_ctx->is_vlan_mode)
-		if (unlikely(skb->protocol != ETH_P_8021Q))
-			ECM_IPA_DEBUG("ether_type != ETH_P_8021Q && vlan\n");
+		if (unlikely(skb->protocol != htons(ETH_P_8021Q)))
+			ECM_IPA_DEBUG(
+				"ether_type != ETH_P_8021Q && vlan, prot = 0x%X\n"
+				, skb->protocol);
 
 	ret = ipa_tx_dp(ecm_ipa_ctx->ipa_to_usb_client, skb, NULL);
 	if (ret) {
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
index f4c8763..b2e454a 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -14,9 +14,10 @@
 #include <linux/msm_ipa.h>
 #include <linux/string.h>
 #include "../ipa_common_i.h"
+#include "../ipa_v3/ipa_pm.h"
 
-#define OFFLOAD_DRV_NAME "ipa_wdi3"
-#define IPA_WDI3_DBG(fmt, args...) \
+#define OFFLOAD_DRV_NAME "ipa_wdi"
+#define IPA_WDI_DBG(fmt, args...) \
 	do { \
 		pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
 			__func__, __LINE__, ## args); \
@@ -26,7 +27,7 @@
 			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
 	} while (0)
 
-#define IPA_WDI3_DBG_LOW(fmt, args...) \
+#define IPA_WDI_DBG_LOW(fmt, args...) \
 	do { \
 		pr_debug(OFFLOAD_DRV_NAME " %s:%d " fmt, \
 			__func__, __LINE__, ## args); \
@@ -34,7 +35,7 @@
 			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
 	} while (0)
 
-#define IPA_WDI3_ERR(fmt, args...) \
+#define IPA_WDI_ERR(fmt, args...) \
 	do { \
 		pr_err(OFFLOAD_DRV_NAME " %s:%d " fmt, \
 			__func__, __LINE__, ## args); \
@@ -44,32 +45,107 @@
 			OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
 	} while (0)
 
-struct ipa_wdi3_intf_info {
+struct ipa_wdi_intf_info {
 	char netdev_name[IPA_RESOURCE_NAME_MAX];
 	u8 hdr_len;
 	u32 partial_hdr_hdl[IPA_IP_MAX];
 	struct list_head link;
 };
 
-struct ipa_wdi3_context {
+struct ipa_wdi_context {
 	struct list_head head_intf_list;
-	ipa_notify_cb notify;
-	void *priv;
-	struct completion wdi3_completion;
+	struct completion wdi_completion;
 	struct mutex lock;
+	enum ipa_wdi_version wdi_version;
+	u8 is_smmu_enabled;
+	u32 tx_pipe_hdl;
+	u32 rx_pipe_hdl;
+	u8 num_sys_pipe_needed;
+	u32 sys_pipe_hdl[IPA_WDI_MAX_SUPPORTED_SYS_PIPE];
+	u32 ipa_pm_hdl;
+	ipa_wdi_meter_notifier_cb wdi_notify;
 };
 
-static struct ipa_wdi3_context *ipa_wdi3_ctx;
+static struct ipa_wdi_context *ipa_wdi_ctx;
 
-static int ipa_wdi3_commit_partial_hdr(
+int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
+	struct ipa_wdi_init_out_params *out)
+{
+	struct ipa_wdi_uc_ready_params uc_ready_params;
+	struct ipa_smmu_in_params smmu_in;
+	struct ipa_smmu_out_params smmu_out;
+
+	if (ipa_wdi_ctx) {
+		IPA_WDI_ERR("ipa_wdi_ctx was initialized before\n");
+		return -EFAULT;
+	}
+
+	if (in->wdi_version > IPA_WDI_3 || in->wdi_version < IPA_WDI_1) {
+		IPA_WDI_ERR("wrong wdi version: %d\n", in->wdi_version);
+		return -EFAULT;
+	}
+
+	ipa_wdi_ctx = kzalloc(sizeof(*ipa_wdi_ctx), GFP_KERNEL);
+	if (ipa_wdi_ctx == NULL)
+		return -ENOMEM;
+
+	mutex_init(&ipa_wdi_ctx->lock);
+	init_completion(&ipa_wdi_ctx->wdi_completion);
+	INIT_LIST_HEAD(&ipa_wdi_ctx->head_intf_list);
+
+	ipa_wdi_ctx->wdi_version = in->wdi_version;
+	uc_ready_params.notify = in->notify;
+	uc_ready_params.priv = in->priv;
+	ipa_wdi_ctx->wdi_notify = in->wdi_notify;
+
+	if (ipa_uc_reg_rdyCB(&uc_ready_params) != 0) {
+		mutex_destroy(&ipa_wdi_ctx->lock);
+		kfree(ipa_wdi_ctx);
+		ipa_wdi_ctx = NULL;
+		return -EFAULT;
+	}
+
+	out->is_uC_ready = uc_ready_params.is_uC_ready;
+
+	smmu_in.smmu_client = IPA_SMMU_WLAN_CLIENT;
+	if (ipa_get_smmu_params(&smmu_in, &smmu_out))
+		out->is_smmu_enabled = false;
+	else
+		out->is_smmu_enabled = smmu_out.smmu_enable;
+
+	ipa_wdi_ctx->is_smmu_enabled = out->is_smmu_enabled;
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_init);
+
+int ipa_wdi_cleanup(void)
+{
+	struct ipa_wdi_intf_info *entry;
+	struct ipa_wdi_intf_info *next;
+
+	/* clear interface list */
+	list_for_each_entry_safe(entry, next,
+		&ipa_wdi_ctx->head_intf_list, link) {
+		list_del(&entry->link);
+		kfree(entry);
+	}
+	mutex_destroy(&ipa_wdi_ctx->lock);
+	kfree(ipa_wdi_ctx);
+	ipa_wdi_ctx = NULL;
+	return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_cleanup);
+
+static int ipa_wdi_commit_partial_hdr(
 	struct ipa_ioc_add_hdr *hdr,
 	const char *netdev_name,
-	struct ipa_wdi3_hdr_info *hdr_info)
+	struct ipa_wdi_hdr_info *hdr_info)
 {
 	int i;
 
 	if (!hdr || !hdr_info || !netdev_name) {
-		IPA_WDI3_ERR("Invalid input\n");
+		IPA_WDI_ERR("Invalid input\n");
 		return -EINVAL;
 	}
 
@@ -90,18 +166,18 @@
 	}
 
 	if (ipa_add_hdr(hdr)) {
-		IPA_WDI3_ERR("fail to add partial headers\n");
+		IPA_WDI_ERR("fail to add partial headers\n");
 		return -EFAULT;
 	}
 
 	return 0;
 }
 
-int ipa_wdi3_reg_intf(struct ipa_wdi3_reg_intf_in_params *in)
+int ipa_wdi_reg_intf(struct ipa_wdi_reg_intf_in_params *in)
 {
 	struct ipa_ioc_add_hdr *hdr;
-	struct ipa_wdi3_intf_info *new_intf;
-	struct ipa_wdi3_intf_info *entry;
+	struct ipa_wdi_intf_info *new_intf;
+	struct ipa_wdi_intf_info *entry;
 	struct ipa_tx_intf tx;
 	struct ipa_rx_intf rx;
 	struct ipa_ioc_tx_intf_prop tx_prop[2];
@@ -110,36 +186,30 @@
 	int ret = 0;
 
 	if (in == NULL) {
-		IPA_WDI3_ERR("invalid params in=%pK\n", in);
+		IPA_WDI_ERR("invalid params in=NULL\n");
 		return -EINVAL;
 	}
 
-	if (!ipa_wdi3_ctx) {
-		ipa_wdi3_ctx = kzalloc(sizeof(*ipa_wdi3_ctx), GFP_KERNEL);
-		if (ipa_wdi3_ctx == NULL) {
-			IPA_WDI3_ERR("fail to alloc wdi3 ctx\n");
-			return -ENOMEM;
-		}
-		mutex_init(&ipa_wdi3_ctx->lock);
-		INIT_LIST_HEAD(&ipa_wdi3_ctx->head_intf_list);
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("wdi ctx is not initialized\n");
+		return -EPERM;
 	}
 
-	IPA_WDI3_DBG("register interface for netdev %s\n",
+	IPA_WDI_DBG("register interface for netdev %s\n",
 		in->netdev_name);
 
-	mutex_lock(&ipa_wdi3_ctx->lock);
-	list_for_each_entry(entry, &ipa_wdi3_ctx->head_intf_list, link)
+	mutex_lock(&ipa_wdi_ctx->lock);
+	list_for_each_entry(entry, &ipa_wdi_ctx->head_intf_list, link)
 		if (strcmp(entry->netdev_name, in->netdev_name) == 0) {
-			IPA_WDI3_DBG("intf was added before.\n");
-			mutex_unlock(&ipa_wdi3_ctx->lock);
+			IPA_WDI_DBG("intf was added before\n");
+			mutex_unlock(&ipa_wdi_ctx->lock);
 			return 0;
 		}
 
-	IPA_WDI3_DBG("intf was not added before, proceed.\n");
+	IPA_WDI_DBG("intf was not added before, proceed\n");
 	new_intf = kzalloc(sizeof(*new_intf), GFP_KERNEL);
 	if (new_intf == NULL) {
-		IPA_WDI3_ERR("fail to alloc new intf\n");
-		mutex_unlock(&ipa_wdi3_ctx->lock);
+		mutex_unlock(&ipa_wdi_ctx->lock);
 		return -ENOMEM;
 	}
 
@@ -152,20 +222,19 @@
 	len = sizeof(struct ipa_ioc_add_hdr) + 2 * sizeof(struct ipa_hdr_add);
 	hdr = kzalloc(len, GFP_KERNEL);
 	if (hdr == NULL) {
-		IPA_WDI3_ERR("fail to alloc %d bytes\n", len);
 		ret = -EFAULT;
 		goto fail_alloc_hdr;
 	}
 
-	if (ipa_wdi3_commit_partial_hdr(hdr, in->netdev_name, in->hdr_info)) {
-		IPA_WDI3_ERR("fail to commit partial headers\n");
+	if (ipa_wdi_commit_partial_hdr(hdr, in->netdev_name, in->hdr_info)) {
+		IPA_WDI_ERR("fail to commit partial headers\n");
 		ret = -EFAULT;
 		goto fail_commit_hdr;
 	}
 
 	new_intf->partial_hdr_hdl[IPA_IP_v4] = hdr->hdr[IPA_IP_v4].hdr_hdl;
 	new_intf->partial_hdr_hdl[IPA_IP_v6] = hdr->hdr[IPA_IP_v6].hdr_hdl;
-	IPA_WDI3_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
+	IPA_WDI_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
 		hdr->hdr[IPA_IP_v4].hdr_hdl, hdr->hdr[IPA_IP_v6].hdr_hdl);
 
 	/* populate tx prop */
@@ -175,12 +244,14 @@
 	memset(tx_prop, 0, sizeof(tx_prop));
 	tx_prop[0].ip = IPA_IP_v4;
 	tx_prop[0].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+	tx_prop[0].alt_dst_pipe = in->alt_dst_pipe;
 	tx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
 	strlcpy(tx_prop[0].hdr_name, hdr->hdr[IPA_IP_v4].name,
 		sizeof(tx_prop[0].hdr_name));
 
 	tx_prop[1].ip = IPA_IP_v6;
 	tx_prop[1].dst_pipe = IPA_CLIENT_WLAN1_CONS;
+	tx_prop[1].alt_dst_pipe = in->alt_dst_pipe;
 	tx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
 	strlcpy(tx_prop[1].hdr_name, hdr->hdr[IPA_IP_v6].name,
 		sizeof(tx_prop[1].hdr_name));
@@ -209,54 +280,53 @@
 	}
 
 	if (ipa_register_intf(in->netdev_name, &tx, &rx)) {
-		IPA_WDI3_ERR("fail to add interface prop\n");
+		IPA_WDI_ERR("fail to add interface prop\n");
 		ret = -EFAULT;
 		goto fail_commit_hdr;
 	}
 
-	list_add(&new_intf->link, &ipa_wdi3_ctx->head_intf_list);
-	init_completion(&ipa_wdi3_ctx->wdi3_completion);
+	list_add(&new_intf->link, &ipa_wdi_ctx->head_intf_list);
+	init_completion(&ipa_wdi_ctx->wdi_completion);
 
 	kfree(hdr);
-	mutex_unlock(&ipa_wdi3_ctx->lock);
+	mutex_unlock(&ipa_wdi_ctx->lock);
 	return 0;
 
 fail_commit_hdr:
 	kfree(hdr);
 fail_alloc_hdr:
 	kfree(new_intf);
-	mutex_unlock(&ipa_wdi3_ctx->lock);
+	mutex_unlock(&ipa_wdi_ctx->lock);
 	return ret;
 }
-EXPORT_SYMBOL(ipa_wdi3_reg_intf);
+EXPORT_SYMBOL(ipa_wdi_reg_intf);
 
-int ipa_wdi3_dereg_intf(const char *netdev_name)
+int ipa_wdi_dereg_intf(const char *netdev_name)
 {
 	int len, ret = 0;
 	struct ipa_ioc_del_hdr *hdr = NULL;
-	struct ipa_wdi3_intf_info *entry;
-	struct ipa_wdi3_intf_info *next;
+	struct ipa_wdi_intf_info *entry;
+	struct ipa_wdi_intf_info *next;
 
 	if (!netdev_name) {
-		IPA_WDI3_ERR("no netdev name.\n");
+		IPA_WDI_ERR("no netdev name\n");
 		return -EINVAL;
 	}
 
-	if (!ipa_wdi3_ctx) {
-		IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("wdi ctx is not initialized\n");
 		return -EPERM;
 	}
 
-	mutex_lock(&ipa_wdi3_ctx->lock);
-	list_for_each_entry_safe(entry, next, &ipa_wdi3_ctx->head_intf_list,
+	mutex_lock(&ipa_wdi_ctx->lock);
+	list_for_each_entry_safe(entry, next, &ipa_wdi_ctx->head_intf_list,
 		link)
 		if (strcmp(entry->netdev_name, netdev_name) == 0) {
 			len = sizeof(struct ipa_ioc_del_hdr) +
 				2 * sizeof(struct ipa_hdr_del);
 			hdr = kzalloc(len, GFP_KERNEL);
 			if (hdr == NULL) {
-				IPA_WDI3_ERR("fail to alloc %d bytes\n", len);
-				mutex_unlock(&ipa_wdi3_ctx->lock);
+				mutex_unlock(&ipa_wdi_ctx->lock);
 				return -ENOMEM;
 			}
 
@@ -264,20 +334,21 @@
 			hdr->num_hdls = 2;
 			hdr->hdl[0].hdl = entry->partial_hdr_hdl[0];
 			hdr->hdl[1].hdl = entry->partial_hdr_hdl[1];
-			IPA_WDI3_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
+			IPA_WDI_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
 				hdr->hdl[0].hdl, hdr->hdl[1].hdl);
 
 			if (ipa_del_hdr(hdr)) {
-				IPA_WDI3_ERR("fail to delete partial header\n");
+				IPA_WDI_ERR("fail to delete partial header\n");
 				ret = -EFAULT;
 				goto fail;
 			}
 
 			if (ipa_deregister_intf(entry->netdev_name)) {
-				IPA_WDI3_ERR("fail to del interface props\n");
+				IPA_WDI_ERR("fail to del interface props\n");
 				ret = -EFAULT;
 				goto fail;
 			}
+
 			list_del(&entry->link);
 			kfree(entry);
 
@@ -286,241 +357,512 @@
 
 fail:
 	kfree(hdr);
-	mutex_unlock(&ipa_wdi3_ctx->lock);
+	mutex_unlock(&ipa_wdi_ctx->lock);
 	return ret;
 }
-EXPORT_SYMBOL(ipa_wdi3_dereg_intf);
+EXPORT_SYMBOL(ipa_wdi_dereg_intf);
 
-static void ipa_wdi3_rm_notify(void *user_data, enum ipa_rm_event event,
+static void ipa_wdi_rm_notify(void *user_data, enum ipa_rm_event event,
 		unsigned long data)
 {
-	if (!ipa_wdi3_ctx) {
-		IPA_WDI3_ERR("Invalid context\n");
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("Invalid context\n");
 		return;
 	}
 
 	switch (event) {
 	case IPA_RM_RESOURCE_GRANTED:
-		complete_all(&ipa_wdi3_ctx->wdi3_completion);
+		complete_all(&ipa_wdi_ctx->wdi_completion);
 		break;
 
 	case IPA_RM_RESOURCE_RELEASED:
 		break;
 
 	default:
-		IPA_WDI3_ERR("Invalid RM Evt: %d", event);
+		IPA_WDI_ERR("Invalid RM Evt: %d", event);
 		break;
 	}
 }
 
-static int ipa_wdi3_cons_release(void)
+static int ipa_wdi_cons_release(void)
 {
 	return 0;
 }
 
-static int ipa_wdi3_cons_request(void)
+static int ipa_wdi_cons_request(void)
 {
 	int ret = 0;
 
-	if (!ipa_wdi3_ctx) {
-		IPA_WDI3_ERR("wdi3 ctx is not initialized\n");
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("wdi ctx is not initialized\n");
 		ret = -EFAULT;
 	}
 
 	return ret;
 }
 
-int ipa_wdi3_conn_pipes(struct ipa_wdi3_conn_in_params *in,
-			struct ipa_wdi3_conn_out_params *out)
+static void ipa_wdi_pm_cb(void *p, enum ipa_pm_cb_event event)
 {
-	int ret = 0;
+	IPA_WDI_DBG("received pm event %d\n", event);
+}
+
+int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
+			struct ipa_wdi_conn_out_params *out)
+{
+	int i, j, ret = 0;
 	struct ipa_rm_create_params param;
+	struct ipa_pm_register_params pm_params;
+	struct ipa_wdi_in_params in_tx;
+	struct ipa_wdi_in_params in_rx;
+	struct ipa_wdi_out_params out_tx;
+	struct ipa_wdi_out_params out_rx;
 
 	if (!(in && out)) {
-		IPA_WDI3_ERR("empty parameters. in=%pK out=%pK\n", in, out);
+		IPA_WDI_ERR("empty parameters. in=%pK out=%pK\n", in, out);
 		return -EINVAL;
 	}
 
-	if (!ipa_wdi3_ctx) {
-		ipa_wdi3_ctx = kzalloc(sizeof(*ipa_wdi3_ctx), GFP_KERNEL);
-		if (ipa_wdi3_ctx == NULL) {
-			IPA_WDI3_ERR("fail to alloc wdi3 ctx\n");
-			return -EFAULT;
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("wdi ctx is not initialized\n");
+		return -EPERM;
+	}
+
+	if (in->num_sys_pipe_needed > IPA_WDI_MAX_SUPPORTED_SYS_PIPE) {
+		IPA_WDI_ERR("ipa can only support up to %d sys pipe\n",
+			IPA_WDI_MAX_SUPPORTED_SYS_PIPE);
+		return -EINVAL;
+	}
+	ipa_wdi_ctx->num_sys_pipe_needed = in->num_sys_pipe_needed;
+	IPA_WDI_DBG("number of sys pipe %d\n", in->num_sys_pipe_needed);
+
+	/* setup sys pipe when needed */
+	for (i = 0; i < ipa_wdi_ctx->num_sys_pipe_needed; i++) {
+		ret = ipa_setup_sys_pipe(&in->sys_in[i],
+			&ipa_wdi_ctx->sys_pipe_hdl[i]);
+		if (ret) {
+			IPA_WDI_ERR("fail to setup sys pipe %d\n", i);
+			ret = -EFAULT;
+			goto fail_setup_sys_pipe;
 		}
-		mutex_init(&ipa_wdi3_ctx->lock);
-		INIT_LIST_HEAD(&ipa_wdi3_ctx->head_intf_list);
-	}
-	ipa_wdi3_ctx->notify = in->notify;
-	ipa_wdi3_ctx->priv = in->priv;
-
-	memset(&param, 0, sizeof(param));
-	param.name = IPA_RM_RESOURCE_WLAN_PROD;
-	param.reg_params.user_data = ipa_wdi3_ctx;
-	param.reg_params.notify_cb = ipa_wdi3_rm_notify;
-	param.floor_voltage = IPA_VOLTAGE_SVS;
-	ret = ipa_rm_create_resource(&param);
-	if (ret) {
-		IPA_WDI3_ERR("fail to create WLAN_PROD resource\n");
-		return -EFAULT;
 	}
 
-	memset(&param, 0, sizeof(param));
-	param.name = IPA_RM_RESOURCE_WLAN_CONS;
-	param.request_resource = ipa_wdi3_cons_request;
-	param.release_resource = ipa_wdi3_cons_release;
-	ret = ipa_rm_create_resource(&param);
-	if (ret) {
-		IPA_WDI3_ERR("fail to create WLAN_CONS resource\n");
-		goto fail_create_rm_cons;
+	if (!ipa_pm_is_used()) {
+		memset(&param, 0, sizeof(param));
+		param.name = IPA_RM_RESOURCE_WLAN_PROD;
+		param.reg_params.user_data = ipa_wdi_ctx;
+		param.reg_params.notify_cb = ipa_wdi_rm_notify;
+		param.floor_voltage = IPA_VOLTAGE_SVS;
+		ret = ipa_rm_create_resource(&param);
+		if (ret) {
+			IPA_WDI_ERR("fail to create WLAN_PROD resource\n");
+			ret = -EFAULT;
+			goto fail_setup_sys_pipe;
+		}
+
+		memset(&param, 0, sizeof(param));
+		param.name = IPA_RM_RESOURCE_WLAN_CONS;
+		param.request_resource = ipa_wdi_cons_request;
+		param.release_resource = ipa_wdi_cons_release;
+		ret = ipa_rm_create_resource(&param);
+		if (ret) {
+			IPA_WDI_ERR("fail to create WLAN_CONS resource\n");
+			goto fail_create_rm_cons;
+		}
+
+		if (ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+			IPA_RM_RESOURCE_APPS_CONS)) {
+			IPA_WDI_ERR("fail to add rm dependency\n");
+			ret = -EFAULT;
+			goto fail_add_dependency;
+		}
+	} else {
+		pm_params.name = "wdi";
+		pm_params.callback = ipa_wdi_pm_cb;
+		pm_params.user_data = NULL;
+		pm_params.group = IPA_PM_GROUP_DEFAULT;
+		if (ipa_pm_register(&pm_params, &ipa_wdi_ctx->ipa_pm_hdl)) {
+			IPA_WDI_ERR("fail to register ipa pm\n");
+			ret = -EFAULT;
+			goto fail_setup_sys_pipe;
+		}
 	}
 
-	if (ipa_rm_add_dependency(IPA_RM_RESOURCE_WLAN_PROD,
-		IPA_RM_RESOURCE_APPS_CONS)) {
-		IPA_WDI3_ERR("fail to add rm dependency\n");
-		ret = -EFAULT;
-		goto fail;
-	}
+	if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+		if (ipa_conn_wdi_pipes(in, out, ipa_wdi_ctx->wdi_notify)) {
+			IPA_WDI_ERR("fail to setup wdi pipes\n");
+			ret = -EFAULT;
+			goto fail_connect_pipe;
+		}
+	} else {
+		memset(&in_tx, 0, sizeof(in_tx));
+		memset(&in_rx, 0, sizeof(in_rx));
+		memset(&out_tx, 0, sizeof(out_tx));
+		memset(&out_rx, 0, sizeof(out_rx));
+		in_rx.wdi_notify = ipa_wdi_ctx->wdi_notify;
+		if (in->is_smmu_enabled == false) {
+			/* firsr setup rx pipe */
+			in_rx.sys.ipa_ep_cfg = in->u_rx.rx.ipa_ep_cfg;
+			in_rx.sys.client = in->u_rx.rx.client;
+			in_rx.sys.notify = in->notify;
+			in_rx.sys.priv = in->priv;
+			in_rx.smmu_enabled = in->is_smmu_enabled;
+			in_rx.u.ul.rdy_ring_base_pa =
+				in->u_rx.rx.transfer_ring_base_pa;
+			in_rx.u.ul.rdy_ring_size =
+				in->u_rx.rx.transfer_ring_size;
+			in_rx.u.ul.rdy_ring_rp_pa =
+				in->u_rx.rx.transfer_ring_doorbell_pa;
+			in_rx.u.ul.rdy_comp_ring_base_pa =
+				in->u_rx.rx.event_ring_base_pa;
+			in_rx.u.ul.rdy_comp_ring_wp_pa =
+				in->u_rx.rx.event_ring_doorbell_pa;
+			in_rx.u.ul.rdy_comp_ring_size =
+				in->u_rx.rx.event_ring_size;
+			if (ipa_connect_wdi_pipe(&in_rx, &out_rx)) {
+				IPA_WDI_ERR("fail to setup rx pipe\n");
+				ret = -EFAULT;
+				goto fail_connect_pipe;
+			}
+			ipa_wdi_ctx->rx_pipe_hdl = out_rx.clnt_hdl;
+			out->rx_uc_db_pa = out_rx.uc_door_bell_pa;
+			IPA_WDI_DBG("rx uc db pa: 0x%pad\n", &out->rx_uc_db_pa);
 
-	if (ipa_conn_wdi3_pipes(in, out)) {
-		IPA_WDI3_ERR("fail to setup wdi3 pipes\n");
-		ret = -EFAULT;
-		goto fail;
+			/* then setup tx pipe */
+			in_tx.sys.ipa_ep_cfg = in->u_tx.tx.ipa_ep_cfg;
+			in_tx.sys.client = in->u_tx.tx.client;
+			in_tx.smmu_enabled = in->is_smmu_enabled;
+			in_tx.u.dl.comp_ring_base_pa =
+				in->u_tx.tx.transfer_ring_base_pa;
+			in_tx.u.dl.comp_ring_size =
+				in->u_tx.tx.transfer_ring_size;
+			in_tx.u.dl.ce_ring_base_pa =
+				in->u_tx.tx.event_ring_base_pa;
+			in_tx.u.dl.ce_door_bell_pa =
+				in->u_tx.tx.event_ring_doorbell_pa;
+			in_tx.u.dl.ce_ring_size =
+				in->u_tx.tx.event_ring_size;
+			in_tx.u.dl.num_tx_buffers =
+				in->u_tx.tx.num_pkt_buffers;
+			if (ipa_connect_wdi_pipe(&in_tx, &out_tx)) {
+				IPA_WDI_ERR("fail to setup tx pipe\n");
+				ret = -EFAULT;
+				goto fail;
+			}
+			ipa_wdi_ctx->tx_pipe_hdl = out_tx.clnt_hdl;
+			out->tx_uc_db_pa = out_tx.uc_door_bell_pa;
+			IPA_WDI_DBG("tx uc db pa: 0x%pad\n", &out->tx_uc_db_pa);
+		} else { /* smmu is enabled */
+			/* firsr setup rx pipe */
+			in_rx.sys.ipa_ep_cfg = in->u_rx.rx_smmu.ipa_ep_cfg;
+			in_rx.sys.client = in->u_rx.rx_smmu.client;
+			in_rx.sys.notify = in->notify;
+			in_rx.sys.priv = in->priv;
+			in_rx.smmu_enabled = in->is_smmu_enabled;
+			in_rx.u.ul_smmu.rdy_ring =
+				in->u_rx.rx_smmu.transfer_ring_base;
+			in_rx.u.ul_smmu.rdy_ring_size =
+				in->u_rx.rx_smmu.transfer_ring_size;
+			in_rx.u.ul_smmu.rdy_ring_rp_pa =
+				in->u_rx.rx_smmu.transfer_ring_doorbell_pa;
+			in_rx.u.ul_smmu.rdy_comp_ring =
+				in->u_rx.rx_smmu.event_ring_base;
+			in_rx.u.ul_smmu.rdy_comp_ring_wp_pa =
+				in->u_rx.rx_smmu.event_ring_doorbell_pa;
+			in_rx.u.ul_smmu.rdy_comp_ring_size =
+				in->u_rx.rx_smmu.event_ring_size;
+			if (ipa_connect_wdi_pipe(&in_rx, &out_rx)) {
+				IPA_WDI_ERR("fail to setup rx pipe\n");
+				ret = -EFAULT;
+				goto fail_connect_pipe;
+			}
+			ipa_wdi_ctx->rx_pipe_hdl = out_rx.clnt_hdl;
+			out->rx_uc_db_pa = out_rx.uc_door_bell_pa;
+			IPA_WDI_DBG("rx uc db pa: 0x%pad\n", &out->rx_uc_db_pa);
+
+			/* then setup tx pipe */
+			in_tx.sys.ipa_ep_cfg = in->u_tx.tx_smmu.ipa_ep_cfg;
+			in_tx.sys.client = in->u_tx.tx_smmu.client;
+			in_tx.smmu_enabled = in->is_smmu_enabled;
+			in_tx.u.dl_smmu.comp_ring =
+				in->u_tx.tx_smmu.transfer_ring_base;
+			in_tx.u.dl_smmu.comp_ring_size =
+				in->u_tx.tx_smmu.transfer_ring_size;
+			in_tx.u.dl_smmu.ce_ring =
+				in->u_tx.tx_smmu.event_ring_base;
+			in_tx.u.dl_smmu.ce_door_bell_pa =
+				in->u_tx.tx_smmu.event_ring_doorbell_pa;
+			in_tx.u.dl_smmu.ce_ring_size =
+				in->u_tx.tx_smmu.event_ring_size;
+			in_tx.u.dl_smmu.num_tx_buffers =
+				in->u_tx.tx_smmu.num_pkt_buffers;
+			if (ipa_connect_wdi_pipe(&in_tx, &out_tx)) {
+				IPA_WDI_ERR("fail to setup tx pipe\n");
+				ret = -EFAULT;
+				goto fail;
+			}
+			ipa_wdi_ctx->tx_pipe_hdl = out_tx.clnt_hdl;
+			out->tx_uc_db_pa = out_tx.uc_door_bell_pa;
+			IPA_WDI_DBG("tx uc db pa: 0x%pad\n", &out->tx_uc_db_pa);
+		}
 	}
 
 	return 0;
 
 fail:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
+	ipa_disconnect_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl);
+fail_connect_pipe:
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+			IPA_RM_RESOURCE_APPS_CONS);
+	else
+		ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl);
+fail_add_dependency:
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS);
 fail_create_rm_cons:
-	ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
-
+	if (!ipa_pm_is_used())
+		ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD);
+fail_setup_sys_pipe:
+	for (j = 0; j < i; j++)
+		ipa_teardown_sys_pipe(ipa_wdi_ctx->sys_pipe_hdl[j]);
 	return ret;
 }
-EXPORT_SYMBOL(ipa_wdi3_conn_pipes);
+EXPORT_SYMBOL(ipa_wdi_conn_pipes);
 
-int ipa_wdi3_disconn_pipes(void)
+int ipa_wdi_disconn_pipes(void)
 {
-	int ipa_ep_idx_rx, ipa_ep_idx_tx;
+	int i, ipa_ep_idx_rx, ipa_ep_idx_tx;
 
-	if (!ipa_wdi3_ctx) {
-		IPA_WDI3_ERR("wdi3 ctx is not initialized\n");
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("wdi ctx is not initialized\n");
 		return -EPERM;
 	}
 
-	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
-	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
-	if (ipa_disconn_wdi3_pipes(ipa_ep_idx_rx, ipa_ep_idx_tx)) {
-		IPA_WDI3_ERR("fail to tear down wdi3 pipes\n");
-		return -EFAULT;
-	}
-
-	if (ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD,
-				IPA_RM_RESOURCE_APPS_CONS)) {
-		IPA_WDI3_ERR("fail to delete rm dependency\n");
-		return -EFAULT;
-	}
-
-	if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
-		IPA_WDI3_ERR("fail to delete WLAN_PROD resource\n");
-		return -EFAULT;
-	}
-
-	if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS)) {
-		IPA_WDI3_ERR("fail to delete WLAN_CONS resource\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(ipa_wdi3_disconn_pipes);
-
-int ipa_wdi3_enable_pipes(void)
-{
-	int ret;
-	int ipa_ep_idx_tx, ipa_ep_idx_rx;
-
-	if (!ipa_wdi3_ctx) {
-		IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
-		return -EPERM;
-	}
-
-	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
-	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
-	if (ipa_enable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
-		IPA_WDI3_ERR("fail to enable wdi3 pipes\n");
-		return -EFAULT;
-	}
-
-	ret = ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD);
-	if (ret == -EINPROGRESS) {
-		if (wait_for_completion_timeout(&ipa_wdi3_ctx->wdi3_completion,
-			10*HZ) == 0) {
-			IPA_WDI3_ERR("WLAN_PROD resource req time out\n");
+	/* tear down sys pipe if needed */
+	for (i = 0; i < ipa_wdi_ctx->num_sys_pipe_needed; i++) {
+		if (ipa_teardown_sys_pipe(ipa_wdi_ctx->sys_pipe_hdl[i])) {
+			IPA_WDI_ERR("fail to tear down sys pipe %d\n", i);
 			return -EFAULT;
 		}
-	} else if (ret != 0) {
-		IPA_WDI3_ERR("fail to request resource\n");
-		return -EFAULT;
-	}
-
-	return 0;
-}
-EXPORT_SYMBOL(ipa_wdi3_enable_pipes);
-
-int ipa_wdi3_disable_pipes(void)
-{
-	int ret;
-	int ipa_ep_idx_tx, ipa_ep_idx_rx;
-
-	if (!ipa_wdi3_ctx) {
-		IPA_WDI3_ERR("wdi3 ctx is not initialized.\n");
-		return -EPERM;
-	}
-
-	ret = ipa_rm_release_resource(IPA_RM_RESOURCE_WLAN_PROD);
-	if (ret != 0) {
-		IPA_WDI3_ERR("fail to release resource\n");
-		return -EFAULT;
 	}
 
 	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
 	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
-	if (ipa_disable_wdi3_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
-		IPA_WDI3_ERR("fail to disable wdi3 pipes\n");
-		return -EFAULT;
+
+	if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+		if (ipa_disconn_wdi_pipes(ipa_ep_idx_rx, ipa_ep_idx_tx)) {
+			IPA_WDI_ERR("fail to tear down wdi pipes\n");
+			return -EFAULT;
+		}
+	} else {
+		if (ipa_disconnect_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to tear down wdi tx pipes\n");
+			return -EFAULT;
+		}
+		if (ipa_disconnect_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to tear down wdi rx pipes\n");
+			return -EFAULT;
+		}
+	}
+
+	if (!ipa_pm_is_used()) {
+		if (ipa_rm_delete_dependency(IPA_RM_RESOURCE_WLAN_PROD,
+					IPA_RM_RESOURCE_APPS_CONS)) {
+			IPA_WDI_ERR("fail to delete rm dependency\n");
+			return -EFAULT;
+		}
+
+		if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_PROD)) {
+			IPA_WDI_ERR("fail to delete WLAN_PROD resource\n");
+			return -EFAULT;
+		}
+
+		if (ipa_rm_delete_resource(IPA_RM_RESOURCE_WLAN_CONS)) {
+			IPA_WDI_ERR("fail to delete WLAN_CONS resource\n");
+			return -EFAULT;
+		}
+	} else {
+		if (ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl)) {
+			IPA_WDI_ERR("fail to deregister ipa pm\n");
+			return -EFAULT;
+		}
 	}
 
 	return 0;
 }
-EXPORT_SYMBOL(ipa_wdi3_disable_pipes);
+EXPORT_SYMBOL(ipa_wdi_disconn_pipes);
 
-int ipa_wdi3_set_perf_profile(struct ipa_wdi3_perf_profile *profile)
+int ipa_wdi_enable_pipes(void)
+{
+	int ret;
+	int ipa_ep_idx_tx, ipa_ep_idx_rx;
+
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("wdi ctx is not initialized\n");
+		return -EPERM;
+	}
+
+	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
+	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
+
+	if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+		if (ipa_enable_wdi_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
+			IPA_WDI_ERR("fail to enable wdi pipes\n");
+			return -EFAULT;
+		}
+	} else {
+		if (ipa_enable_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to enable wdi tx pipe\n");
+			return -EFAULT;
+		}
+		if (ipa_resume_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to resume wdi tx pipe\n");
+			return -EFAULT;
+		}
+		if (ipa_enable_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to enable wdi rx pipe\n");
+			return -EFAULT;
+		}
+		if (ipa_resume_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to resume wdi rx pipe\n");
+			return -EFAULT;
+		}
+	}
+
+	if (!ipa_pm_is_used()) {
+		ret = ipa_rm_request_resource(IPA_RM_RESOURCE_WLAN_PROD);
+		if (ret == -EINPROGRESS) {
+			if (wait_for_completion_timeout(
+				&ipa_wdi_ctx->wdi_completion, 10*HZ) == 0) {
+				IPA_WDI_ERR("WLAN_PROD res req time out\n");
+				return -EFAULT;
+			}
+		} else if (ret != 0) {
+			IPA_WDI_ERR("fail to request resource\n");
+			return -EFAULT;
+		}
+	} else {
+		ret = ipa_pm_activate_sync(ipa_wdi_ctx->ipa_pm_hdl);
+		if (ret) {
+			IPA_WDI_ERR("fail to activate ipa pm\n");
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_enable_pipes);
+
+int ipa_wdi_disable_pipes(void)
+{
+	int ret;
+	int ipa_ep_idx_tx, ipa_ep_idx_rx;
+
+	if (!ipa_wdi_ctx) {
+		IPA_WDI_ERR("wdi ctx is not initialized.\n");
+		return -EPERM;
+	}
+
+	ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
+	ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
+
+	if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+		if (ipa_disable_wdi_pipes(ipa_ep_idx_tx, ipa_ep_idx_rx)) {
+			IPA_WDI_ERR("fail to disable wdi pipes\n");
+			return -EFAULT;
+		}
+	} else {
+		if (ipa_suspend_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to suspend wdi tx pipe\n");
+			return -EFAULT;
+		}
+		if (ipa_disable_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to disable wdi tx pipe\n");
+			return -EFAULT;
+		}
+		if (ipa_suspend_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to suspend wdi rx pipe\n");
+			return -EFAULT;
+		}
+		if (ipa_disable_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+			IPA_WDI_ERR("fail to disable wdi rx pipe\n");
+			return -EFAULT;
+		}
+	}
+
+	if (!ipa_pm_is_used()) {
+		ret = ipa_rm_release_resource(IPA_RM_RESOURCE_WLAN_PROD);
+		if (ret != 0) {
+			IPA_WDI_ERR("fail to release resource\n");
+			return -EFAULT;
+		}
+	} else {
+		ret = ipa_pm_deactivate_sync(ipa_wdi_ctx->ipa_pm_hdl);
+		if (ret) {
+			IPA_WDI_ERR("fail to deactivate ipa pm\n");
+			return -EFAULT;
+		}
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(ipa_wdi_disable_pipes);
+
+int ipa_wdi_set_perf_profile(struct ipa_wdi_perf_profile *profile)
 {
 	struct ipa_rm_perf_profile rm_profile;
 	enum ipa_rm_resource_name resource_name;
 
 	if (profile == NULL) {
-		IPA_WDI3_ERR("Invalid input\n");
+		IPA_WDI_ERR("Invalid input\n");
 		return -EINVAL;
 	}
 
-	rm_profile.max_supported_bandwidth_mbps =
-		profile->max_supported_bw_mbps;
+	if (!ipa_pm_is_used()) {
+		rm_profile.max_supported_bandwidth_mbps =
+			profile->max_supported_bw_mbps;
 
-	if (profile->client == IPA_CLIENT_WLAN1_PROD) {
-		resource_name = IPA_RM_RESOURCE_WLAN_PROD;
-	} else if (profile->client == IPA_CLIENT_WLAN1_CONS) {
-		resource_name = IPA_RM_RESOURCE_WLAN_CONS;
+		if (profile->client == IPA_CLIENT_WLAN1_PROD) {
+			resource_name = IPA_RM_RESOURCE_WLAN_PROD;
+		} else if (profile->client == IPA_CLIENT_WLAN1_CONS) {
+			resource_name = IPA_RM_RESOURCE_WLAN_CONS;
+		} else {
+			IPA_WDI_ERR("not supported\n");
+			return -EINVAL;
+		}
+
+		if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
+			IPA_WDI_ERR("fail to setup rm perf profile\n");
+			return -EFAULT;
+		}
 	} else {
-		IPA_WDI3_ERR("not supported\n");
-		return -EINVAL;
-	}
-
-	if (ipa_rm_set_perf_profile(resource_name, &rm_profile)) {
-		IPA_WDI3_ERR("fail to setup rm perf profile\n");
-		return -EFAULT;
+		if (ipa_pm_set_perf_profile(ipa_wdi_ctx->ipa_pm_hdl,
+			profile->max_supported_bw_mbps)) {
+			IPA_WDI_ERR("fail to setup pm perf profile\n");
+			return -EFAULT;
+		}
 	}
 
 	return 0;
 }
-EXPORT_SYMBOL(ipa_wdi3_set_perf_profile);
+EXPORT_SYMBOL(ipa_wdi_set_perf_profile);
+
+int ipa_wdi_create_smmu_mapping(u32 num_buffers,
+	struct ipa_wdi_buffer_info *info)
+{
+	return ipa_create_wdi_mapping(num_buffers, info);
+}
+EXPORT_SYMBOL(ipa_wdi_create_smmu_mapping);
+
+int ipa_wdi_release_smmu_mapping(u32 num_buffers,
+	struct ipa_wdi_buffer_info *info)
+{
+	return ipa_release_wdi_mapping(num_buffers, info);
+}
+EXPORT_SYMBOL(ipa_wdi_release_smmu_mapping);
+
+int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats)
+{
+	return ipa_get_wdi_stats(stats);
+}
+EXPORT_SYMBOL(ipa_wdi_get_stats);
diff --git a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
index ad23d82..4980167 100644
--- a/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_clients/rndis_ipa.c
@@ -2026,8 +2026,10 @@
 	}
 
 	if (rndis_ipa_ctx->is_vlan_mode)
-		if (unlikely(skb->protocol != ETH_P_8021Q))
-			RNDIS_IPA_DEBUG("ether_type != ETH_P_8021Q && vlan\n");
+		if (unlikely(skb->protocol != htons(ETH_P_8021Q)))
+			RNDIS_IPA_DEBUG(
+				"ether_type != ETH_P_8021Q && vlan, prot = 0x%X\n"
+				, skb->protocol);
 
 	/* make room at the head of the SKB to put the RNDIS header */
 	rndis_hdr = (struct rndis_pkt_hdr *)skb_push(skb,
diff --git a/drivers/platform/msm/ipa/ipa_common_i.h b/drivers/platform/msm/ipa/ipa_common_i.h
index 98a1cf9..b37a127 100644
--- a/drivers/platform/msm/ipa/ipa_common_i.h
+++ b/drivers/platform/msm/ipa/ipa_common_i.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -419,14 +419,15 @@
 			      void *user_data);
 void ipa_ntn_uc_dereg_rdyCB(void);
 
-int ipa_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
-	struct ipa_wdi3_conn_out_params *out);
+int ipa_conn_wdi_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out,
+	ipa_wdi_meter_notifier_cb wdi_notify);
 
-int ipa_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa_disconn_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
 
-int ipa_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa_enable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
 
-int ipa_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
+int ipa_disable_wdi_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
 
 const char *ipa_get_version_string(enum ipa_hw_type ver);
 int ipa_start_gsi_channel(u32 clnt_hdl);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa.c b/drivers/platform/msm/ipa/ipa_v2/ipa.c
index 78d1c96..e43a201 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa.c
@@ -4358,7 +4358,7 @@
 	else
 		IPADBG(":ipa Uc interface init ok\n");
 
-	result = ipa_wdi_init();
+	result = ipa2_wdi_init();
 	if (result)
 		IPAERR(":wdi init failed (%d)\n", -result);
 	else
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
index 91017a5..bd7f600 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_i.h
@@ -67,6 +67,16 @@
 #define IPA_MAX_NUM_REQ_CACHE 10
 #define IPA_IPC_LOG_PAGES 50
 
+#define IPA_WDI_RX_RING_RES 0
+#define IPA_WDI_RX_RING_RP_RES 1
+#define IPA_WDI_RX_COMP_RING_RES 2
+#define IPA_WDI_RX_COMP_RING_WP_RES 3
+#define IPA_WDI_TX_RING_RES 4
+#define IPA_WDI_CE_RING_RES 5
+#define IPA_WDI_CE_DB_RES 6
+#define IPA_WDI_TX_DB_RES 7
+#define IPA_WDI_MAX_RES 8
+
 #define IPADBG(fmt, args...) \
 	do { \
 		pr_debug(DRV_NAME " %s:%d " fmt, __func__, __LINE__, ## args);\
@@ -1578,8 +1588,9 @@
 int ipa2_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
 void ipa2_ntn_uc_dereg_rdyCB(void);
 
-int ipa2_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
-	struct ipa_wdi3_conn_out_params *out);
+int ipa2_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out,
+	ipa_wdi_meter_notifier_cb wdi_notify);
 int ipa2_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
 int ipa2_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
 int ipa2_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
@@ -1601,6 +1612,9 @@
  */
 int ipa2_uc_dereg_rdyCB(void);
 
+int ipa2_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+		phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
+		unsigned long *iova);
 /*
  * Tethering bridge (Rmnet / MBIM)
  */
@@ -1864,7 +1878,7 @@
 int ipa_active_clients_trylock(unsigned long *flags);
 void ipa_active_clients_unlock(void);
 void ipa_active_clients_trylock_unlock(unsigned long *flags);
-int ipa_wdi_init(void);
+int ipa2_wdi_init(void);
 int ipa_write_qmapid_wdi_pipe(u32 clnt_hdl, u8 qmap_id);
 int ipa_tag_process(struct ipa_desc *desc, int num_descs,
 		    unsigned long timeout);
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
index a3db092..66a8d0b 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_rt.c
@@ -51,6 +51,7 @@
 	u32 tmp[IPA_RT_FLT_HW_RULE_BUF_SIZE/4];
 	u8 *start;
 	int pipe_idx;
+	struct ipa_hdr_entry *hdr_entry;
 
 	if (buf == NULL) {
 		memset(tmp, 0, (IPA_RT_FLT_HW_RULE_BUF_SIZE/4));
@@ -74,6 +75,18 @@
 	}
 	rule_hdr->u.hdr.pipe_dest_idx = pipe_idx;
 	rule_hdr->u.hdr.system = !ipa_ctx->hdr_tbl_lcl;
+
+	/* Adding check to confirm still
+	 * header entry present in header table or not
+	 */
+
+	if (entry->hdr) {
+		hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+		if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+			IPAERR_RL("Header entry already deleted\n");
+			return -EPERM;
+		}
+	}
 	if (entry->hdr) {
 		if (entry->hdr->cookie == IPA_HDR_COOKIE) {
 			rule_hdr->u.hdr.hdr_offset =
@@ -140,6 +153,8 @@
 	u32 tmp[IPA_RT_FLT_HW_RULE_BUF_SIZE/4];
 	u8 *start;
 	int pipe_idx;
+	struct ipa_hdr_entry *hdr_entry;
+	struct ipa_hdr_proc_ctx_entry *hdr_proc_entry;
 
 	if (buf == NULL) {
 		memset(tmp, 0, IPA_RT_FLT_HW_RULE_BUF_SIZE);
@@ -162,6 +177,24 @@
 		return -EPERM;
 	}
 	rule_hdr->u.hdr_v2_5.pipe_dest_idx = pipe_idx;
+	/* Adding check to confirm still
+	 * header entry present in header table or not
+	 */
+
+	if (entry->hdr) {
+		hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+		if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+			IPAERR_RL("Header entry already deleted\n");
+			return -EPERM;
+		}
+	} else if (entry->proc_ctx) {
+		hdr_proc_entry = ipa_id_find(entry->rule.hdr_proc_ctx_hdl);
+		if (!hdr_proc_entry ||
+			hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+			IPAERR_RL("Proc header entry already deleted\n");
+			return -EPERM;
+		}
+	}
 	if (entry->proc_ctx || (entry->hdr && entry->hdr->is_hdr_proc_ctx)) {
 		struct ipa_hdr_proc_ctx_entry *proc_ctx;
 
@@ -1132,6 +1165,8 @@
 {
 	struct ipa_rt_entry *entry;
 	int id;
+	struct ipa_hdr_entry *hdr_entry;
+	struct ipa_hdr_proc_ctx_entry *hdr_proc_entry;
 
 	entry = ipa_id_find(rule_hdl);
 
@@ -1153,6 +1188,24 @@
 			return -EINVAL;
 		}
 	}
+	/* Adding check to confirm still
+	 * header entry present in header table or not
+	 */
+
+	if (entry->hdr) {
+		hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+		if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+			IPAERR_RL("Header entry already deleted\n");
+			return -EINVAL;
+		}
+	} else if (entry->proc_ctx) {
+		hdr_proc_entry = ipa_id_find(entry->rule.hdr_proc_ctx_hdl);
+		if (!hdr_proc_entry ||
+			hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+			IPAERR_RL("Proc header entry already deleted\n");
+			return -EINVAL;
+		}
+	}
 
 	if (entry->hdr)
 		__ipa_release_hdr(entry->hdr->id);
@@ -1466,6 +1519,7 @@
 {
 	struct ipa_rt_entry *entry;
 	struct ipa_hdr_entry *hdr = NULL;
+	struct ipa_hdr_entry *hdr_entry;
 
 	if (rtrule->rule.hdr_hdl) {
 		hdr = ipa_id_find(rtrule->rule.hdr_hdl);
@@ -1486,6 +1540,17 @@
 		goto error;
 	}
 
+	/* Adding check to confirm still
+	 * header entry present in header table or not
+	 */
+
+	if (entry->hdr) {
+		hdr_entry = ipa_id_find(entry->rule.hdr_hdl);
+		if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+			IPAERR_RL("Header entry already deleted\n");
+			return -EPERM;
+		}
+	}
 	if (entry->hdr)
 		entry->hdr->ref_cnt--;
 
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
index cf8f0b8..459c207 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_uc_wdi.c
@@ -26,15 +26,6 @@
 #define IPA_WDI_RESUMED BIT(2)
 #define IPA_UC_POLL_SLEEP_USEC 100
 
-#define IPA_WDI_RX_RING_RES 0
-#define IPA_WDI_RX_RING_RP_RES 1
-#define IPA_WDI_RX_COMP_RING_RES 2
-#define IPA_WDI_RX_COMP_RING_WP_RES 3
-#define IPA_WDI_TX_RING_RES 4
-#define IPA_WDI_CE_RING_RES 5
-#define IPA_WDI_CE_DB_RES 6
-#define IPA_WDI_MAX_RES 7
-
 struct ipa_wdi_res {
 	struct ipa_wdi_buffer_info *res;
 	unsigned int nents;
@@ -448,7 +439,7 @@
 	return 0;
 }
 
-int ipa_wdi_init(void)
+int ipa2_wdi_init(void)
 {
 	struct ipa_uc_hdlrs uc_wdi_cbs = { 0 };
 
@@ -629,7 +620,7 @@
 	}
 }
 
-static int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+int ipa2_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
 		phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
 		unsigned long *iova)
 {
@@ -845,7 +836,7 @@
 				in->smmu_enabled,
 				in->u.dl_smmu.comp_ring_size,
 				in->u.dl.comp_ring_size);
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
 					in->smmu_enabled,
 					in->u.dl.comp_ring_base_pa,
 					&in->u.dl_smmu.comp_ring,
@@ -870,7 +861,7 @@
 					in->smmu_enabled,
 					in->u.dl_smmu.ce_ring_size,
 					in->u.dl.ce_ring_size);
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
 						in->smmu_enabled,
 						in->u.dl.ce_ring_base_pa,
 						&in->u.dl_smmu.ce_ring,
@@ -891,7 +882,7 @@
 
 			pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa :
 				in->u.dl.ce_door_bell_pa;
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
 						in->smmu_enabled,
 						pa,
 						NULL,
@@ -919,7 +910,7 @@
 					in->smmu_enabled,
 					in->u.dl_smmu.comp_ring_size,
 					in->u.dl.comp_ring_size);
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
 						in->smmu_enabled,
 						in->u.dl.comp_ring_base_pa,
 						&in->u.dl_smmu.comp_ring,
@@ -939,7 +930,7 @@
 					in->smmu_enabled,
 					in->u.dl_smmu.ce_ring_size,
 					in->u.dl.ce_ring_size);
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
 						in->smmu_enabled,
 						in->u.dl.ce_ring_base_pa,
 						&in->u.dl_smmu.ce_ring,
@@ -954,7 +945,7 @@
 			tx->ce_ring_size = len;
 			pa = in->smmu_enabled ? in->u.dl_smmu.ce_door_bell_pa :
 				in->u.dl.ce_door_bell_pa;
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
 						in->smmu_enabled,
 						pa,
 						NULL,
@@ -995,7 +986,7 @@
 				in->smmu_enabled,
 				in->u.ul_smmu.rdy_ring_size,
 				in->u.ul.rdy_ring_size);
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
 						in->smmu_enabled,
 						in->u.ul.rdy_ring_base_pa,
 						&in->u.ul_smmu.rdy_ring,
@@ -1016,7 +1007,7 @@
 
 			pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa :
 				in->u.ul.rdy_ring_rp_pa;
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
 						in->smmu_enabled,
 						pa,
 						NULL,
@@ -1040,7 +1031,8 @@
 					in->smmu_enabled,
 					in->u.ul_smmu.rdy_comp_ring_size,
 					in->u.ul.rdy_comp_ring_size);
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_COMP_RING_RES,
+			if (ipa2_create_uc_smmu_mapping(
+						IPA_WDI_RX_COMP_RING_RES,
 						in->smmu_enabled,
 						in->u.ul.rdy_comp_ring_base_pa,
 						&in->u.ul_smmu.rdy_comp_ring,
@@ -1062,7 +1054,7 @@
 			pa = in->smmu_enabled ?
 				in->u.ul_smmu.rdy_comp_ring_wp_pa :
 				in->u.ul.rdy_comp_ring_wp_pa;
-			if (ipa_create_uc_smmu_mapping(
+			if (ipa2_create_uc_smmu_mapping(
 						IPA_WDI_RX_COMP_RING_WP_RES,
 						in->smmu_enabled,
 						pa,
@@ -1090,7 +1082,7 @@
 					in->smmu_enabled,
 					in->u.ul_smmu.rdy_ring_size,
 					in->u.ul.rdy_ring_size);
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
 						in->smmu_enabled,
 						in->u.ul.rdy_ring_base_pa,
 						&in->u.ul_smmu.rdy_ring,
@@ -1106,7 +1098,7 @@
 
 			pa = in->smmu_enabled ? in->u.ul_smmu.rdy_ring_rp_pa :
 				in->u.ul.rdy_ring_rp_pa;
-			if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
 						in->smmu_enabled,
 						pa,
 						NULL,
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
index 27120c8..c9273ec 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_utils.c
@@ -5160,10 +5160,10 @@
 	api_ctrl->ipa_get_pdev = ipa2_get_pdev;
 	api_ctrl->ipa_ntn_uc_reg_rdyCB = ipa2_ntn_uc_reg_rdyCB;
 	api_ctrl->ipa_ntn_uc_dereg_rdyCB = ipa2_ntn_uc_dereg_rdyCB;
-	api_ctrl->ipa_conn_wdi3_pipes = ipa2_conn_wdi3_pipes;
-	api_ctrl->ipa_disconn_wdi3_pipes = ipa2_disconn_wdi3_pipes;
-	api_ctrl->ipa_enable_wdi3_pipes = ipa2_enable_wdi3_pipes;
-	api_ctrl->ipa_disable_wdi3_pipes = ipa2_disable_wdi3_pipes;
+	api_ctrl->ipa_conn_wdi_pipes = ipa2_conn_wdi3_pipes;
+	api_ctrl->ipa_disconn_wdi_pipes = ipa2_disconn_wdi3_pipes;
+	api_ctrl->ipa_enable_wdi_pipes = ipa2_enable_wdi3_pipes;
+	api_ctrl->ipa_disable_wdi_pipes = ipa2_disable_wdi3_pipes;
 	api_ctrl->ipa_pm_is_used = ipa2_pm_is_used;
 
 	return 0;
diff --git a/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c b/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c
index a2c33a1..62748b2 100644
--- a/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c
+++ b/drivers/platform/msm/ipa/ipa_v2/ipa_wdi3_i.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -10,43 +10,27 @@
  * GNU General Public License for more details.
  */
 #include "ipa_i.h"
-#include "ipa_uc_offload_i.h"
 #include <linux/ipa_wdi3.h>
 
 #define IPA_HW_WDI3_RX_MBOX_START_INDEX 48
 #define IPA_HW_WDI3_TX_MBOX_START_INDEX 50
 
 static int ipa_send_wdi3_setup_pipe_cmd(
-	struct ipa_wdi3_setup_info *info, u8 dir)
+	u8 is_smmu_enabled, struct ipa_wdi_pipe_setup_info *info,
+	struct ipa_wdi_pipe_setup_info_smmu *info_smmu, u8 dir)
 {
 	int ipa_ep_idx;
-	int result = 0;
+	int result = 0, len;
+	unsigned long va;
 	struct ipa_mem_buffer cmd;
 	struct IpaHwWdi3SetUpCmdData_t *wdi3_params;
 	struct IpaHwOffloadSetUpCmdData_t *cmd_data;
 
-	if (info == NULL) {
+	if (info == NULL || info_smmu == NULL) {
 		IPAERR("invalid input\n");
 		return -EINVAL;
 	}
 
-	ipa_ep_idx = ipa_get_ep_mapping(info->client);
-	IPAERR("ep number: %d\n", ipa_ep_idx);
-	if (ipa_ep_idx == -1) {
-		IPAERR("fail to get ep idx.\n");
-		return -EFAULT;
-	}
-
-	IPAERR("client=%d ep=%d\n", info->client, ipa_ep_idx);
-	IPAERR("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
-	IPAERR("ring_size = %hu\n", info->transfer_ring_size);
-	IPAERR("ring_db_pa = 0x%pad\n", &info->transfer_ring_doorbell_pa);
-	IPAERR("evt_ring_base_pa = 0x%pad\n", &info->event_ring_base_pa);
-	IPAERR("evt_ring_size = %hu\n", info->event_ring_size);
-	IPAERR("evt_ring_db_pa = 0x%pad\n", &info->event_ring_doorbell_pa);
-	IPAERR("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
-	IPAERR("pkt_offset = %d.\n", info->pkt_offset);
-
 	cmd.size = sizeof(*cmd_data);
 	cmd.base = dma_alloc_coherent(ipa_ctx->uc_pdev, cmd.size,
 			&cmd.phys_base, GFP_KERNEL);
@@ -54,35 +38,181 @@
 		IPAERR("fail to get DMA memory.\n");
 		return -ENOMEM;
 	}
-	IPAERR("suceeded in allocating memory.\n");
 
 	cmd_data = (struct IpaHwOffloadSetUpCmdData_t *)cmd.base;
 	cmd_data->protocol = IPA_HW_FEATURE_WDI3;
 
-	wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
-	wdi3_params->transfer_ring_base_pa = (u32)info->transfer_ring_base_pa;
-	wdi3_params->transfer_ring_base_pa_hi =
-		(u32)((u64)info->transfer_ring_base_pa >> 32);
-	wdi3_params->transfer_ring_size = info->transfer_ring_size;
-	wdi3_params->transfer_ring_doorbell_pa =
-		(u32)info->transfer_ring_doorbell_pa;
-	wdi3_params->transfer_ring_doorbell_pa_hi =
-		(u32)((u64)info->transfer_ring_doorbell_pa >> 32);
-	wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
-	wdi3_params->event_ring_base_pa_hi =
-		(u32)((u64)info->event_ring_base_pa >> 32);
-	wdi3_params->event_ring_size = info->event_ring_size;
-	wdi3_params->event_ring_doorbell_pa =
-		(u32)info->event_ring_doorbell_pa;
-	wdi3_params->event_ring_doorbell_pa_hi =
-		(u32)((u64)info->event_ring_doorbell_pa >> 32);
-	wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
-	wdi3_params->ipa_pipe_number = ipa_ep_idx;
-	wdi3_params->dir = dir;
-	wdi3_params->pkt_offset = info->pkt_offset;
-	memcpy(wdi3_params->desc_format_template, info->desc_format_template,
-		sizeof(wdi3_params->desc_format_template));
-	IPAERR("suceeded in populating the command memory.\n");
+	if (!is_smmu_enabled) {
+		ipa_ep_idx = ipa_get_ep_mapping(info->client);
+		if (ipa_ep_idx == -1) {
+			IPAERR("fail to get ep idx.\n");
+			return -EFAULT;
+		}
+
+		IPADBG("client=%d ep=%d\n", info->client, ipa_ep_idx);
+		IPADBG("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
+		IPADBG("ring_size = %hu\n", info->transfer_ring_size);
+		IPADBG("ring_db_pa = 0x%pad\n",
+			&info->transfer_ring_doorbell_pa);
+		IPADBG("evt_ring_base_pa = 0x%pad\n",
+			&info->event_ring_base_pa);
+		IPADBG("evt_ring_size = %hu\n", info->event_ring_size);
+		IPADBG("evt_ring_db_pa = 0x%pad\n",
+			&info->event_ring_doorbell_pa);
+		IPADBG("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
+		IPADBG("pkt_offset = %d\n", info->pkt_offset);
+
+		wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+		wdi3_params->transfer_ring_base_pa =
+			(u32)info->transfer_ring_base_pa;
+		wdi3_params->transfer_ring_base_pa_hi =
+			(u32)((u64)info->transfer_ring_base_pa >> 32);
+		wdi3_params->transfer_ring_size = info->transfer_ring_size;
+		wdi3_params->transfer_ring_doorbell_pa =
+			(u32)info->transfer_ring_doorbell_pa;
+		wdi3_params->transfer_ring_doorbell_pa_hi =
+			(u32)((u64)info->transfer_ring_doorbell_pa >> 32);
+		wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
+		wdi3_params->event_ring_base_pa_hi =
+			(u32)((u64)info->event_ring_base_pa >> 32);
+		wdi3_params->event_ring_size = info->event_ring_size;
+		wdi3_params->event_ring_doorbell_pa =
+			(u32)info->event_ring_doorbell_pa;
+		wdi3_params->event_ring_doorbell_pa_hi =
+			(u32)((u64)info->event_ring_doorbell_pa >> 32);
+		wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
+		wdi3_params->ipa_pipe_number = ipa_ep_idx;
+		wdi3_params->dir = dir;
+		wdi3_params->pkt_offset = info->pkt_offset;
+		memcpy(wdi3_params->desc_format_template,
+			info->desc_format_template,
+			sizeof(wdi3_params->desc_format_template));
+	} else {
+		ipa_ep_idx = ipa_get_ep_mapping(info_smmu->client);
+		if (ipa_ep_idx == -1) {
+			IPAERR("fail to get ep idx\n");
+			return -EFAULT;
+		}
+
+		IPADBG("client=%d ep=%d\n", info_smmu->client, ipa_ep_idx);
+		IPADBG("ring_size = %hu\n", info_smmu->transfer_ring_size);
+		IPADBG("ring_db_pa = 0x%pad\n",
+			&info_smmu->transfer_ring_doorbell_pa);
+		IPADBG("evt_ring_size = %hu\n", info_smmu->event_ring_size);
+		IPADBG("evt_ring_db_pa = 0x%pad\n",
+			&info_smmu->event_ring_doorbell_pa);
+		IPADBG("num_pkt_buffers = %hu\n", info_smmu->num_pkt_buffers);
+		IPADBG("pkt_offset = %d\n", info_smmu->pkt_offset);
+
+		wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+
+		if (dir == IPA_WDI3_TX_DIR) {
+			len = info_smmu->transfer_ring_size;
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+				true, info->transfer_ring_base_pa,
+				&info_smmu->transfer_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_base_pa = (u32)va;
+			wdi3_params->transfer_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->transfer_ring_size = len;
+
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_TX_DB_RES,
+				true, info_smmu->transfer_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->transfer_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+
+			len = info_smmu->event_ring_size;
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+				true, info->event_ring_base_pa,
+				&info_smmu->event_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_base_pa = (u32)va;
+			wdi3_params->event_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->event_ring_size = len;
+
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+				true, info_smmu->event_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->event_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+		} else {
+			len = info_smmu->transfer_ring_size;
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+				true, info->transfer_ring_base_pa,
+				&info_smmu->transfer_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_base_pa = (u32)va;
+			wdi3_params->transfer_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->transfer_ring_size = len;
+
+			if (ipa2_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+				true, info_smmu->transfer_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->transfer_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+
+			len = info_smmu->event_ring_size;
+			if (ipa2_create_uc_smmu_mapping(
+				IPA_WDI_RX_COMP_RING_RES, true,
+				info->event_ring_base_pa,
+				&info_smmu->event_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_base_pa = (u32)va;
+			wdi3_params->event_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->event_ring_size = len;
+
+			if (ipa2_create_uc_smmu_mapping(
+				IPA_WDI_RX_COMP_RING_WP_RES, true,
+				info_smmu->event_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->event_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+		}
+		wdi3_params->num_pkt_buffers = info_smmu->num_pkt_buffers;
+		wdi3_params->ipa_pipe_number = ipa_ep_idx;
+		wdi3_params->dir = dir;
+		wdi3_params->pkt_offset = info_smmu->pkt_offset;
+		memcpy(wdi3_params->desc_format_template,
+			info_smmu->desc_format_template,
+			sizeof(wdi3_params->desc_format_template));
+	}
 
 	result = ipa_uc_send_cmd((u32)(cmd.phys_base),
 				IPA_CPU_2_HW_CMD_OFFLOAD_CHANNEL_SET_UP,
@@ -94,13 +224,15 @@
 	}
 
 	dma_free_coherent(ipa_ctx->uc_pdev, cmd.size, cmd.base, cmd.phys_base);
-	IPAERR("suceeded in freeing memory.\n");
 	return result;
 }
 
-int ipa2_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
-	struct ipa_wdi3_conn_out_params *out)
+int ipa2_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out,
+	ipa_wdi_meter_notifier_cb wdi_notify)
 {
+	enum ipa_client_type rx_client;
+	enum ipa_client_type tx_client;
 	struct ipa_ep_context *ep_rx;
 	struct ipa_ep_context *ep_tx;
 	int ipa_ep_idx_rx;
@@ -112,12 +244,26 @@
 		return -EINVAL;
 	}
 
-	ipa_ep_idx_rx = ipa_get_ep_mapping(in->rx.client);
-	ipa_ep_idx_tx = ipa_get_ep_mapping(in->tx.client);
+	if (in->is_smmu_enabled == false) {
+		rx_client = in->u_rx.rx.client;
+		tx_client = in->u_tx.tx.client;
+	} else {
+		rx_client = in->u_rx.rx_smmu.client;
+		tx_client = in->u_tx.tx_smmu.client;
+	}
+
+	ipa_ep_idx_rx = ipa_get_ep_mapping(rx_client);
+	ipa_ep_idx_tx = ipa_get_ep_mapping(tx_client);
+
 	if (ipa_ep_idx_rx == -1 || ipa_ep_idx_tx == -1) {
 		IPAERR("fail to alloc EP.\n");
 		return -EFAULT;
 	}
+	if (ipa_ep_idx_rx >= IPA_MAX_NUM_PIPES ||
+		ipa_ep_idx_tx >= IPA_MAX_NUM_PIPES) {
+		IPAERR("ep out of range.\n");
+		return -EFAULT;
+	}
 
 	ep_rx = &ipa_ctx->ep[ipa_ep_idx_rx];
 	ep_tx = &ipa_ctx->ep[ipa_ep_idx_tx];
@@ -132,9 +278,14 @@
 
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
+	if (wdi_notify)
+		ipa_ctx->uc_wdi_ctx.stats_notify = wdi_notify;
+	else
+		IPADBG("wdi_notify is null\n");
+
 	/* setup rx ep cfg */
 	ep_rx->valid = 1;
-	ep_rx->client = in->rx.client;
+	ep_rx->client = rx_client;
 	result = ipa_disable_data_path(ipa_ep_idx_rx);
 	if (result) {
 		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
@@ -145,65 +296,71 @@
 	ep_rx->client_notify = in->notify;
 	ep_rx->priv = in->priv;
 
-	memcpy(&ep_rx->cfg, &in->rx.ipa_ep_cfg, sizeof(ep_rx->cfg));
+	if (in->is_smmu_enabled == false)
+		memcpy(&ep_rx->cfg, &in->u_rx.rx.ipa_ep_cfg,
+			sizeof(ep_rx->cfg));
+	else
+		memcpy(&ep_rx->cfg, &in->u_rx.rx_smmu.ipa_ep_cfg,
+			sizeof(ep_rx->cfg));
 
 	if (ipa_cfg_ep(ipa_ep_idx_rx, &ep_rx->cfg)) {
 		IPAERR("fail to setup rx pipe cfg\n");
 		result = -EFAULT;
 		goto fail;
 	}
-	IPAERR("configured RX EP.\n");
 
-	if (ipa_send_wdi3_setup_pipe_cmd(&in->rx, IPA_WDI3_RX_DIR)) {
+	if (ipa_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+		&in->u_rx.rx, &in->u_rx.rx_smmu, IPA_WDI3_RX_DIR)) {
 		IPAERR("fail to send cmd to uc for rx pipe\n");
 		result = -EFAULT;
 		goto fail;
 	}
-	IPAERR("rx pipe was setup.\n");
-
 	ipa_install_dflt_flt_rules(ipa_ep_idx_rx);
 	out->rx_uc_db_pa = ipa_ctx->ipa_wrapper_base +
 		IPA_REG_BASE_OFST_v2_5 +
 		IPA_UC_MAILBOX_m_n_OFFS_v2_5(
 		IPA_HW_WDI3_RX_MBOX_START_INDEX/32,
 		IPA_HW_WDI3_RX_MBOX_START_INDEX % 32);
-	IPADBG("client %d (ep: %d) connected\n", in->rx.client,
+
+	IPADBG("client %d (ep: %d) connected\n", rx_client,
 		ipa_ep_idx_rx);
 
-	/* setup dl ep cfg */
+	/* setup tx ep cfg */
 	ep_tx->valid = 1;
-	ep_tx->client = in->tx.client;
+	ep_tx->client = tx_client;
 	result = ipa_disable_data_path(ipa_ep_idx_tx);
 	if (result) {
-		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
+		IPAERR("disable data path failed res=%d ep=%d.\n", result,
 			ipa_ep_idx_tx);
 		result = -EFAULT;
 		goto fail;
 	}
 
-	memcpy(&ep_tx->cfg, &in->tx.ipa_ep_cfg, sizeof(ep_tx->cfg));
+	if (in->is_smmu_enabled == false)
+		memcpy(&ep_tx->cfg, &in->u_tx.tx.ipa_ep_cfg,
+			sizeof(ep_tx->cfg));
+	else
+		memcpy(&ep_tx->cfg, &in->u_tx.tx_smmu.ipa_ep_cfg,
+			sizeof(ep_tx->cfg));
 
 	if (ipa_cfg_ep(ipa_ep_idx_tx, &ep_tx->cfg)) {
 		IPAERR("fail to setup tx pipe cfg\n");
 		result = -EFAULT;
 		goto fail;
 	}
-	IPAERR("configured TX EP in DMA mode.\n");
 
-	if (ipa_send_wdi3_setup_pipe_cmd(&in->tx, IPA_WDI3_TX_DIR)) {
+	if (ipa_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+		&in->u_tx.tx, &in->u_tx.tx_smmu, IPA_WDI3_TX_DIR)) {
 		IPAERR("fail to send cmd to uc for tx pipe\n");
 		result = -EFAULT;
 		goto fail;
 	}
-	IPAERR("tx pipe was setup.\n");
-
 	out->tx_uc_db_pa = ipa_ctx->ipa_wrapper_base +
 		IPA_REG_BASE_OFST_v2_5 +
 		IPA_UC_MAILBOX_m_n_OFFS_v2_5(
 		IPA_HW_WDI3_TX_MBOX_START_INDEX/32,
 		IPA_HW_WDI3_TX_MBOX_START_INDEX % 32);
-	out->tx_uc_db_va = ioremap(out->tx_uc_db_pa, 4);
-	IPADBG("client %d (ep: %d) connected\n", in->tx.client,
+	IPADBG("client %d (ep: %d) connected\n", tx_client,
 		ipa_ep_idx_tx);
 
 fail:
@@ -233,7 +390,6 @@
 
 	wdi3 = &cmd_data->CommonCh_params.Wdi3CommonCh_params;
 	wdi3->params.ipa_pipe_number = ipa_ep_idx;
-	IPAERR("cmd: %d ep_idx: %d\n", command, ipa_ep_idx);
 	result = ipa_uc_send_cmd((u32)(cmd.phys_base), command,
 				IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS,
 				false, 10*HZ);
@@ -256,6 +412,12 @@
 	IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
 	IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
 
+	if (ipa_ep_idx_tx < 0 || ipa_ep_idx_tx >= IPA_MAX_NUM_PIPES ||
+		ipa_ep_idx_rx < 0 || ipa_ep_idx_rx >= IPA_MAX_NUM_PIPES) {
+		IPAERR("invalid ipa ep index\n");
+		return -EINVAL;
+	}
+
 	ep_tx = &ipa_ctx->ep[ipa_ep_idx_tx];
 	ep_rx = &ipa_ctx->ep[ipa_ep_idx_rx];
 
@@ -291,8 +453,8 @@
 	struct ipa_ep_context *ep_tx, *ep_rx;
 	int result = 0;
 
-	IPAERR("ep_tx = %d\n", ipa_ep_idx_tx);
-	IPAERR("ep_rx = %d\n", ipa_ep_idx_rx);
+	IPADBG("ep_tx = %d\n", ipa_ep_idx_tx);
+	IPADBG("ep_rx = %d\n", ipa_ep_idx_rx);
 
 	ep_tx = &ipa_ctx->ep[ipa_ep_idx_tx];
 	ep_rx = &ipa_ctx->ep[ipa_ep_idx_rx];
@@ -301,7 +463,6 @@
 	if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_tx,
 		IPA_CPU_2_HW_CMD_OFFLOAD_ENABLE)) {
 		IPAERR("fail to enable tx pipe\n");
-		WARN_ON(1);
 		result = -EFAULT;
 		goto fail;
 	}
@@ -310,7 +471,6 @@
 	if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_tx,
 		IPA_CPU_2_HW_CMD_OFFLOAD_RESUME)) {
 		IPAERR("fail to resume tx pipe\n");
-		WARN_ON(1);
 		result = -EFAULT;
 		goto fail;
 	}
@@ -319,7 +479,6 @@
 	if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_rx,
 		IPA_CPU_2_HW_CMD_OFFLOAD_ENABLE)) {
 		IPAERR("fail to enable rx pipe\n");
-		WARN_ON(1);
 		result = -EFAULT;
 		goto fail;
 	}
@@ -328,7 +487,6 @@
 	if (ipa_send_wdi3_common_ch_cmd(ipa_ep_idx_rx,
 		IPA_CPU_2_HW_CMD_OFFLOAD_RESUME)) {
 		IPAERR("fail to resume rx pipe\n");
-		WARN_ON(1);
 		result = -EFAULT;
 		goto fail;
 	}
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 90edd2b..6aa15c1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -952,11 +952,13 @@
 				goto fail_pm;
 			}
 
-			result = ipa_pm_associate_ipa_cons_to_client(
-				ep->sys->pm_hdl, sys_in->client);
-			if (result) {
-				IPAERR("failed to associate IPA PM client\n");
-				goto fail_gen2;
+			if (IPA_CLIENT_IS_APPS_CONS(sys_in->client)) {
+				result = ipa_pm_associate_ipa_cons_to_client(
+					ep->sys->pm_hdl, sys_in->client);
+				if (result) {
+					IPAERR("failed to associate\n");
+					goto fail_gen2;
+				}
 			}
 
 			result = ipa_pm_set_perf_profile(ep->sys->pm_hdl,
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
index 7bd1731..4a8e7c7 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h
@@ -185,6 +185,16 @@
 #define IPA3_ACTIVE_CLIENTS_LOG_HASHTABLE_SIZE 50
 #define IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN 40
 
+#define IPA_WDI_RX_RING_RES			0
+#define IPA_WDI_RX_RING_RP_RES		1
+#define IPA_WDI_RX_COMP_RING_RES	2
+#define IPA_WDI_RX_COMP_RING_WP_RES	3
+#define IPA_WDI_TX_RING_RES			4
+#define IPA_WDI_CE_RING_RES			5
+#define IPA_WDI_CE_DB_RES			6
+#define IPA_WDI_TX_DB_RES			7
+#define IPA_WDI_MAX_RES				8
+
 struct ipa3_active_client_htable_entry {
 	struct hlist_node list;
 	char id_string[IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN];
@@ -1898,8 +1908,9 @@
 int ipa3_tear_down_uc_offload_pipes(int ipa_ep_idx_ul, int ipa_ep_idx_dl);
 int ipa3_ntn_uc_reg_rdyCB(void (*ipauc_ready_cb)(void *), void *priv);
 void ipa3_ntn_uc_dereg_rdyCB(void);
-int ipa3_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
-	struct ipa_wdi3_conn_out_params *out);
+int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out,
+	ipa_wdi_meter_notifier_cb wdi_notify);
 int ipa3_disconn_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
 int ipa3_enable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
 int ipa3_disable_wdi3_pipes(int ipa_ep_idx_tx, int ipa_ep_idx_rx);
@@ -1921,6 +1932,10 @@
  */
 int ipa3_uc_dereg_rdyCB(void);
 
+int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+		phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
+		unsigned long *iova);
+
 /*
  * Tethering bridge (Rmnet / MBIM)
  */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
index 1bdc0fb..a0f1f54 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c
@@ -52,6 +52,8 @@
 	struct ipa3_rt_entry *entry, u8 *buf)
 {
 	struct ipahal_rt_rule_gen_params gen_params;
+	struct ipa3_hdr_entry *hdr_entry;
+	struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
 	int res = 0;
 
 	memset(&gen_params, 0, sizeof(gen_params));
@@ -71,6 +73,25 @@
 		return -EPERM;
 	}
 
+	/* Adding check to confirm still
+	 * header entry present in header table or not
+	 */
+
+	if (entry->hdr) {
+		hdr_entry = ipa3_id_find(entry->rule.hdr_hdl);
+		if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+			IPAERR_RL("Header entry already deleted\n");
+			return -EPERM;
+		}
+	} else if (entry->proc_ctx) {
+		hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl);
+		if (!hdr_proc_entry ||
+			hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+			IPAERR_RL("Proc header entry already deleted\n");
+			return -EPERM;
+		}
+	}
+
 	if (entry->proc_ctx || (entry->hdr && entry->hdr->is_hdr_proc_ctx)) {
 		struct ipa3_hdr_proc_ctx_entry *proc_ctx;
 
@@ -1269,6 +1290,8 @@
 {
 	struct ipa3_rt_entry *entry;
 	int id;
+	struct ipa3_hdr_entry *hdr_entry;
+	struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
 
 	entry = ipa3_id_find(rule_hdl);
 
@@ -1291,6 +1314,25 @@
 		}
 	}
 
+	/* Adding check to confirm still
+	 * header entry present in header table or not
+	 */
+
+	if (entry->hdr) {
+		hdr_entry = ipa3_id_find(entry->rule.hdr_hdl);
+		if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+			IPAERR_RL("Header entry already deleted\n");
+			return -EINVAL;
+		}
+	} else if (entry->proc_ctx) {
+		hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl);
+		if (!hdr_proc_entry ||
+			hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+			IPAERR_RL("Proc header entry already deleted\n");
+			return -EINVAL;
+		}
+	}
+
 	if (entry->hdr)
 		__ipa3_release_hdr(entry->hdr->id);
 	else if (entry->proc_ctx)
@@ -1611,7 +1653,8 @@
 	struct ipa3_rt_entry *entry;
 	struct ipa3_hdr_entry *hdr = NULL;
 	struct ipa3_hdr_proc_ctx_entry *proc_ctx = NULL;
-
+	struct ipa3_hdr_entry *hdr_entry;
+	struct ipa3_hdr_proc_ctx_entry *hdr_proc_entry;
 	if (rtrule->rule.hdr_hdl) {
 		hdr = ipa3_id_find(rtrule->rule.hdr_hdl);
 		if ((hdr == NULL) || (hdr->cookie != IPA_HDR_COOKIE)) {
@@ -1638,6 +1681,25 @@
 		goto error;
 	}
 
+	/* Adding check to confirm still
+	 * header entry present in header table or not
+	 */
+
+	if (entry->hdr) {
+		hdr_entry = ipa3_id_find(entry->rule.hdr_hdl);
+		if (!hdr_entry || hdr_entry->cookie != IPA_HDR_COOKIE) {
+			IPAERR_RL("Header entry already deleted\n");
+			return -EPERM;
+		}
+	} else if (entry->proc_ctx) {
+		hdr_proc_entry = ipa3_id_find(entry->rule.hdr_proc_ctx_hdl);
+		if (!hdr_proc_entry ||
+			hdr_proc_entry->cookie != IPA_PROC_HDR_COOKIE) {
+			IPAERR_RL("Proc header entry already deleted\n");
+			return -EPERM;
+		}
+	}
+
 	if (entry->hdr)
 		entry->hdr->ref_cnt--;
 	if (entry->proc_ctx)
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
index 648db5e..ec777bc 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_uc_wdi.c
@@ -16,6 +16,7 @@
 #include "ipa_qmi_service.h"
 
 #define IPA_HOLB_TMR_DIS 0x0
+#define IPA_HOLB_TMR_EN 0x1
 
 #define IPA_HW_INTERFACE_WDI_VERSION 0x0001
 #define IPA_HW_WDI_RX_MBOX_START_INDEX 48
@@ -27,15 +28,6 @@
 #define IPA_WDI_RESUMED BIT(2)
 #define IPA_UC_POLL_SLEEP_USEC 100
 
-#define IPA_WDI_RX_RING_RES			0
-#define IPA_WDI_RX_RING_RP_RES		1
-#define IPA_WDI_RX_COMP_RING_RES	2
-#define IPA_WDI_RX_COMP_RING_WP_RES	3
-#define IPA_WDI_TX_RING_RES			4
-#define IPA_WDI_CE_RING_RES			5
-#define IPA_WDI_CE_DB_RES			6
-#define IPA_WDI_MAX_RES				7
-
 struct ipa_wdi_res {
 	struct ipa_wdi_buffer_info *res;
 	unsigned int nents;
@@ -669,7 +661,7 @@
 	}
 }
 
-static int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
+int ipa_create_uc_smmu_mapping(int res_idx, bool wlan_smmu_en,
 		phys_addr_t pa, struct sg_table *sgt, size_t len, bool device,
 		unsigned long *iova)
 {
@@ -702,6 +694,7 @@
 		case IPA_WDI_RX_RING_RP_RES:
 		case IPA_WDI_RX_COMP_RING_WP_RES:
 		case IPA_WDI_CE_DB_RES:
+		case IPA_WDI_TX_DB_RES:
 			if (ipa_create_uc_smmu_mapping_pa(pa, len,
 				(res_idx == IPA_WDI_CE_DB_RES) ? true : false,
 				iova)) {
@@ -839,35 +832,6 @@
 			in->u.ul.rdy_comp_ring_wp_pa;
 		ipa3_ctx->uc_ctx.rdy_comp_ring_size =
 			in->u.ul.rdy_comp_ring_size;
-
-		/* check if the VA is empty */
-		if (ipa3_ctx->ipa_wdi2) {
-			if (in->smmu_enabled) {
-				if (!in->u.ul_smmu.rdy_ring_rp_va ||
-					!in->u.ul_smmu.rdy_comp_ring_wp_va)
-					goto dma_alloc_fail;
-			} else {
-				if (!in->u.ul.rdy_ring_rp_va ||
-					!in->u.ul.rdy_comp_ring_wp_va)
-					goto dma_alloc_fail;
-			}
-			IPADBG("rdy_ring_rp value =%d\n",
-				in->smmu_enabled ?
-				*in->u.ul_smmu.rdy_ring_rp_va :
-				*in->u.ul.rdy_ring_rp_va);
-			IPADBG("rx_comp_ring_wp value=%d\n",
-				in->smmu_enabled ?
-				*in->u.ul_smmu.rdy_comp_ring_wp_va :
-				*in->u.ul.rdy_comp_ring_wp_va);
-				ipa3_ctx->uc_ctx.rdy_ring_rp_va =
-					in->smmu_enabled ?
-					in->u.ul_smmu.rdy_ring_rp_va :
-					in->u.ul.rdy_ring_rp_va;
-				ipa3_ctx->uc_ctx.rdy_comp_ring_wp_va =
-					in->smmu_enabled ?
-					in->u.ul_smmu.rdy_comp_ring_wp_va :
-					in->u.ul.rdy_comp_ring_wp_va;
-		}
 	}
 
 	cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
@@ -1534,6 +1498,24 @@
 	return result;
 }
 
+static void ipa3_cfg_holb_wdi_consumer(bool is_enable)
+{
+	u32 clnt_hdl;
+	struct ipa_ep_cfg_holb holb_cfg;
+
+	clnt_hdl = ipa3_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
+	if (clnt_hdl < ipa3_ctx->ipa_num_pipes &&
+		ipa3_ctx->ep[clnt_hdl].valid == 1) {
+		memset(&holb_cfg, 0, sizeof(holb_cfg));
+		if (is_enable)
+			holb_cfg.en = IPA_HOLB_TMR_EN;
+		else
+			holb_cfg.en = IPA_HOLB_TMR_DIS;
+		holb_cfg.tmr_val = 0;
+		ipa3_cfg_ep_holb(clnt_hdl, &holb_cfg);
+	}
+}
+
 /**
  * ipa3_suspend_wdi_pipe() - WDI client suspend
  * @clnt_hdl:	[in] opaque client handle assigned by IPA to client
@@ -1600,6 +1582,9 @@
 			}
 		}
 
+		/* Enabling HOLB on WDI consumer pipe */
+		ipa3_cfg_holb_wdi_consumer(true);
+
 		IPADBG("Post suspend event first for IPA Producer\n");
 		IPADBG("Client: %d clnt_hdl: %d\n", ep->client, clnt_hdl);
 		result = ipa3_uc_send_cmd(suspend.raw32b,
@@ -1609,8 +1594,12 @@
 
 		if (result) {
 			result = -EFAULT;
+			/* Disabling HOLB on WDI consumer pipe */
+			ipa3_cfg_holb_wdi_consumer(false);
 			goto uc_timeout;
 		}
+		/* Disabling HOLB on WDI consumer pipe */
+		ipa3_cfg_holb_wdi_consumer(false);
 	}
 
 	memset(&ep_cfg_ctrl, 0, sizeof(struct ipa_ep_cfg_ctrl));
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index b3726e1..d2b3b4e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4519,10 +4519,10 @@
 	api_ctrl->ipa_get_pdev = ipa3_get_pdev;
 	api_ctrl->ipa_ntn_uc_reg_rdyCB = ipa3_ntn_uc_reg_rdyCB;
 	api_ctrl->ipa_ntn_uc_dereg_rdyCB = ipa3_ntn_uc_dereg_rdyCB;
-	api_ctrl->ipa_conn_wdi3_pipes = ipa3_conn_wdi3_pipes;
-	api_ctrl->ipa_disconn_wdi3_pipes = ipa3_disconn_wdi3_pipes;
-	api_ctrl->ipa_enable_wdi3_pipes = ipa3_enable_wdi3_pipes;
-	api_ctrl->ipa_disable_wdi3_pipes = ipa3_disable_wdi3_pipes;
+	api_ctrl->ipa_conn_wdi_pipes = ipa3_conn_wdi3_pipes;
+	api_ctrl->ipa_disconn_wdi_pipes = ipa3_disconn_wdi3_pipes;
+	api_ctrl->ipa_enable_wdi_pipes = ipa3_enable_wdi3_pipes;
+	api_ctrl->ipa_disable_wdi_pipes = ipa3_disable_wdi3_pipes;
 	api_ctrl->ipa_tz_unlock_reg = ipa3_tz_unlock_reg;
 	api_ctrl->ipa_get_smmu_params = ipa3_get_smmu_params;
 	api_ctrl->ipa_is_vlan_mode = ipa3_is_vlan_mode;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
index 7801745..6c019b9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_wdi3_i.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -16,35 +16,21 @@
 #define IPA_HW_WDI3_TX_MBOX_START_INDEX 50
 
 static int ipa3_send_wdi3_setup_pipe_cmd(
-	struct ipa_wdi3_setup_info *info, u8 dir)
+	u8 is_smmu_enabled, struct ipa_wdi_pipe_setup_info *info,
+	struct ipa_wdi_pipe_setup_info_smmu *info_smmu, u8 dir)
 {
 	int ipa_ep_idx;
-	int result = 0;
+	int result = 0, len;
+	unsigned long va;
 	struct ipa_mem_buffer cmd;
 	struct IpaHwWdi3SetUpCmdData_t *wdi3_params;
 	struct IpaHwOffloadSetUpCmdData_t *cmd_data;
 
-	if (info == NULL) {
+	if (info == NULL || info_smmu == NULL) {
 		IPAERR("invalid input\n");
 		return -EINVAL;
 	}
 
-	ipa_ep_idx = ipa_get_ep_mapping(info->client);
-	if (ipa_ep_idx == -1) {
-		IPAERR("fail to get ep idx.\n");
-		return -EFAULT;
-	}
-
-	IPADBG("client=%d ep=%d\n", info->client, ipa_ep_idx);
-	IPADBG("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
-	IPADBG("ring_size = %hu\n", info->transfer_ring_size);
-	IPADBG("ring_db_pa = 0x%pad\n", &info->transfer_ring_doorbell_pa);
-	IPADBG("evt_ring_base_pa = 0x%pad\n", &info->event_ring_base_pa);
-	IPADBG("evt_ring_size = %hu\n", info->event_ring_size);
-	IPADBG("evt_ring_db_pa = 0x%pad\n", &info->event_ring_doorbell_pa);
-	IPADBG("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
-	IPADBG("pkt_offset = %d\n", info->pkt_offset);
-
 	cmd.size = sizeof(*cmd_data);
 	cmd.base = dma_alloc_coherent(ipa3_ctx->uc_pdev, cmd.size,
 			&cmd.phys_base, GFP_KERNEL);
@@ -56,29 +42,177 @@
 	cmd_data = (struct IpaHwOffloadSetUpCmdData_t *)cmd.base;
 	cmd_data->protocol = IPA_HW_FEATURE_WDI3;
 
-	wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
-	wdi3_params->transfer_ring_base_pa = (u32)info->transfer_ring_base_pa;
-	wdi3_params->transfer_ring_base_pa_hi =
-		(u32)((u64)info->transfer_ring_base_pa >> 32);
-	wdi3_params->transfer_ring_size = info->transfer_ring_size;
-	wdi3_params->transfer_ring_doorbell_pa =
-		(u32)info->transfer_ring_doorbell_pa;
-	wdi3_params->transfer_ring_doorbell_pa_hi =
-		(u32)((u64)info->transfer_ring_doorbell_pa >> 32);
-	wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
-	wdi3_params->event_ring_base_pa_hi =
-		(u32)((u64)info->event_ring_base_pa >> 32);
-	wdi3_params->event_ring_size = info->event_ring_size;
-	wdi3_params->event_ring_doorbell_pa =
-		(u32)info->event_ring_doorbell_pa;
-	wdi3_params->event_ring_doorbell_pa_hi =
-		(u32)((u64)info->event_ring_doorbell_pa >> 32);
-	wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
-	wdi3_params->ipa_pipe_number = ipa_ep_idx;
-	wdi3_params->dir = dir;
-	wdi3_params->pkt_offset = info->pkt_offset;
-	memcpy(wdi3_params->desc_format_template, info->desc_format_template,
-		sizeof(wdi3_params->desc_format_template));
+	if (!is_smmu_enabled) {
+		ipa_ep_idx = ipa_get_ep_mapping(info->client);
+		if (ipa_ep_idx == -1) {
+			IPAERR("fail to get ep idx.\n");
+			return -EFAULT;
+		}
+
+		IPADBG("client=%d ep=%d\n", info->client, ipa_ep_idx);
+		IPADBG("ring_base_pa = 0x%pad\n", &info->transfer_ring_base_pa);
+		IPADBG("ring_size = %hu\n", info->transfer_ring_size);
+		IPADBG("ring_db_pa = 0x%pad\n",
+			&info->transfer_ring_doorbell_pa);
+		IPADBG("evt_ring_base_pa = 0x%pad\n",
+			&info->event_ring_base_pa);
+		IPADBG("evt_ring_size = %hu\n", info->event_ring_size);
+		IPADBG("evt_ring_db_pa = 0x%pad\n",
+			&info->event_ring_doorbell_pa);
+		IPADBG("num_pkt_buffers = %hu\n", info->num_pkt_buffers);
+		IPADBG("pkt_offset = %d\n", info->pkt_offset);
+
+		wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+		wdi3_params->transfer_ring_base_pa =
+			(u32)info->transfer_ring_base_pa;
+		wdi3_params->transfer_ring_base_pa_hi =
+			(u32)((u64)info->transfer_ring_base_pa >> 32);
+		wdi3_params->transfer_ring_size = info->transfer_ring_size;
+		wdi3_params->transfer_ring_doorbell_pa =
+			(u32)info->transfer_ring_doorbell_pa;
+		wdi3_params->transfer_ring_doorbell_pa_hi =
+			(u32)((u64)info->transfer_ring_doorbell_pa >> 32);
+		wdi3_params->event_ring_base_pa = (u32)info->event_ring_base_pa;
+		wdi3_params->event_ring_base_pa_hi =
+			(u32)((u64)info->event_ring_base_pa >> 32);
+		wdi3_params->event_ring_size = info->event_ring_size;
+		wdi3_params->event_ring_doorbell_pa =
+			(u32)info->event_ring_doorbell_pa;
+		wdi3_params->event_ring_doorbell_pa_hi =
+			(u32)((u64)info->event_ring_doorbell_pa >> 32);
+		wdi3_params->num_pkt_buffers = info->num_pkt_buffers;
+		wdi3_params->ipa_pipe_number = ipa_ep_idx;
+		wdi3_params->dir = dir;
+		wdi3_params->pkt_offset = info->pkt_offset;
+		memcpy(wdi3_params->desc_format_template,
+			info->desc_format_template,
+			sizeof(wdi3_params->desc_format_template));
+	} else {
+		ipa_ep_idx = ipa_get_ep_mapping(info_smmu->client);
+		if (ipa_ep_idx == -1) {
+			IPAERR("fail to get ep idx\n");
+			return -EFAULT;
+		}
+
+		IPADBG("client=%d ep=%d\n", info_smmu->client, ipa_ep_idx);
+		IPADBG("ring_size = %hu\n", info_smmu->transfer_ring_size);
+		IPADBG("ring_db_pa = 0x%pad\n",
+			&info_smmu->transfer_ring_doorbell_pa);
+		IPADBG("evt_ring_size = %hu\n", info_smmu->event_ring_size);
+		IPADBG("evt_ring_db_pa = 0x%pad\n",
+			&info_smmu->event_ring_doorbell_pa);
+		IPADBG("num_pkt_buffers = %hu\n", info_smmu->num_pkt_buffers);
+		IPADBG("pkt_offset = %d\n", info_smmu->pkt_offset);
+
+		wdi3_params = &cmd_data->SetupCh_params.Wdi3SetupCh_params;
+
+		if (dir == IPA_WDI3_TX_DIR) {
+			len = info_smmu->transfer_ring_size;
+			if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_RING_RES,
+				true, info->transfer_ring_base_pa,
+				&info_smmu->transfer_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_base_pa = (u32)va;
+			wdi3_params->transfer_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->transfer_ring_size = len;
+
+			if (ipa_create_uc_smmu_mapping(IPA_WDI_TX_DB_RES,
+				true, info_smmu->transfer_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->transfer_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+
+			len = info_smmu->event_ring_size;
+			if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_RING_RES,
+				true, info->event_ring_base_pa,
+				&info_smmu->event_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_base_pa = (u32)va;
+			wdi3_params->event_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->event_ring_size = len;
+
+			if (ipa_create_uc_smmu_mapping(IPA_WDI_CE_DB_RES,
+				true, info_smmu->event_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->event_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+		} else {
+			len = info_smmu->transfer_ring_size;
+			if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RES,
+				true, info->transfer_ring_base_pa,
+				&info_smmu->transfer_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_base_pa = (u32)va;
+			wdi3_params->transfer_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->transfer_ring_size = len;
+
+			if (ipa_create_uc_smmu_mapping(IPA_WDI_RX_RING_RP_RES,
+				true, info_smmu->transfer_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->transfer_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->transfer_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+
+			len = info_smmu->event_ring_size;
+			if (ipa_create_uc_smmu_mapping(
+				IPA_WDI_RX_COMP_RING_RES, true,
+				info->event_ring_base_pa,
+				&info_smmu->event_ring_base, len,
+				false, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_base_pa = (u32)va;
+			wdi3_params->event_ring_base_pa_hi =
+				(u32)((u64)va >> 32);
+			wdi3_params->event_ring_size = len;
+
+			if (ipa_create_uc_smmu_mapping(
+				IPA_WDI_RX_COMP_RING_WP_RES, true,
+				info_smmu->event_ring_doorbell_pa,
+				NULL, 4, true, &va)) {
+				IPAERR("failed to get smmu mapping\n");
+				return -EFAULT;
+			}
+			wdi3_params->event_ring_doorbell_pa =
+				(u32)va;
+			wdi3_params->event_ring_doorbell_pa_hi =
+				(u32)((u64)va >> 32);
+		}
+		wdi3_params->num_pkt_buffers = info_smmu->num_pkt_buffers;
+		wdi3_params->ipa_pipe_number = ipa_ep_idx;
+		wdi3_params->dir = dir;
+		wdi3_params->pkt_offset = info_smmu->pkt_offset;
+		memcpy(wdi3_params->desc_format_template,
+			info_smmu->desc_format_template,
+			sizeof(wdi3_params->desc_format_template));
+	}
 
 	result = ipa3_uc_send_cmd((u32)(cmd.phys_base),
 				IPA_CPU_2_HW_CMD_OFFLOAD_CHANNEL_SET_UP,
@@ -93,9 +227,12 @@
 	return result;
 }
 
-int ipa3_conn_wdi3_pipes(struct ipa_wdi3_conn_in_params *in,
-	struct ipa_wdi3_conn_out_params *out)
+int ipa3_conn_wdi3_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out,
+	ipa_wdi_meter_notifier_cb wdi_notify)
 {
+	enum ipa_client_type rx_client;
+	enum ipa_client_type tx_client;
 	struct ipa3_ep_context *ep_rx;
 	struct ipa3_ep_context *ep_tx;
 	int ipa_ep_idx_rx;
@@ -107,8 +244,17 @@
 		return -EINVAL;
 	}
 
-	ipa_ep_idx_rx = ipa_get_ep_mapping(in->rx.client);
-	ipa_ep_idx_tx = ipa_get_ep_mapping(in->tx.client);
+	if (in->is_smmu_enabled == false) {
+		rx_client = in->u_rx.rx.client;
+		tx_client = in->u_tx.tx.client;
+	} else {
+		rx_client = in->u_rx.rx_smmu.client;
+		tx_client = in->u_tx.tx_smmu.client;
+	}
+
+	ipa_ep_idx_rx = ipa_get_ep_mapping(rx_client);
+	ipa_ep_idx_tx = ipa_get_ep_mapping(tx_client);
+
 	if (ipa_ep_idx_rx == -1 || ipa_ep_idx_tx == -1) {
 		IPAERR("fail to alloc EP.\n");
 		return -EFAULT;
@@ -132,9 +278,14 @@
 
 	IPA_ACTIVE_CLIENTS_INC_SIMPLE();
 
+	if (wdi_notify)
+		ipa3_ctx->uc_wdi_ctx.stats_notify = wdi_notify;
+	else
+		IPADBG("wdi_notify is null\n");
+
 	/* setup rx ep cfg */
 	ep_rx->valid = 1;
-	ep_rx->client = in->rx.client;
+	ep_rx->client = rx_client;
 	result = ipa3_disable_data_path(ipa_ep_idx_rx);
 	if (result) {
 		IPAERR("disable data path failed res=%d clnt=%d.\n", result,
@@ -145,7 +296,12 @@
 	ep_rx->client_notify = in->notify;
 	ep_rx->priv = in->priv;
 
-	memcpy(&ep_rx->cfg, &in->rx.ipa_ep_cfg, sizeof(ep_rx->cfg));
+	if (in->is_smmu_enabled == false)
+		memcpy(&ep_rx->cfg, &in->u_rx.rx.ipa_ep_cfg,
+			sizeof(ep_rx->cfg));
+	else
+		memcpy(&ep_rx->cfg, &in->u_rx.rx_smmu.ipa_ep_cfg,
+			sizeof(ep_rx->cfg));
 
 	if (ipa3_cfg_ep(ipa_ep_idx_rx, &ep_rx->cfg)) {
 		IPAERR("fail to setup rx pipe cfg\n");
@@ -153,7 +309,8 @@
 		goto fail;
 	}
 
-	if (ipa3_send_wdi3_setup_pipe_cmd(&in->rx, IPA_WDI3_RX_DIR)) {
+	if (ipa3_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+		&in->u_rx.rx, &in->u_rx.rx_smmu, IPA_WDI3_RX_DIR)) {
 		IPAERR("fail to send cmd to uc for rx pipe\n");
 		result = -EFAULT;
 		goto fail;
@@ -165,12 +322,12 @@
 		IPA_HW_WDI3_RX_MBOX_START_INDEX/32,
 		IPA_HW_WDI3_RX_MBOX_START_INDEX % 32);
 
-	IPADBG("client %d (ep: %d) connected\n", in->rx.client,
+	IPADBG("client %d (ep: %d) connected\n", rx_client,
 		ipa_ep_idx_rx);
 
-	/* setup dl ep cfg */
+	/* setup tx ep cfg */
 	ep_tx->valid = 1;
-	ep_tx->client = in->tx.client;
+	ep_tx->client = tx_client;
 	result = ipa3_disable_data_path(ipa_ep_idx_tx);
 	if (result) {
 		IPAERR("disable data path failed res=%d ep=%d.\n", result,
@@ -179,7 +336,12 @@
 		goto fail;
 	}
 
-	memcpy(&ep_tx->cfg, &in->tx.ipa_ep_cfg, sizeof(ep_tx->cfg));
+	if (in->is_smmu_enabled == false)
+		memcpy(&ep_tx->cfg, &in->u_tx.tx.ipa_ep_cfg,
+			sizeof(ep_tx->cfg));
+	else
+		memcpy(&ep_tx->cfg, &in->u_tx.tx_smmu.ipa_ep_cfg,
+			sizeof(ep_tx->cfg));
 
 	if (ipa3_cfg_ep(ipa_ep_idx_tx, &ep_tx->cfg)) {
 		IPAERR("fail to setup tx pipe cfg\n");
@@ -187,7 +349,8 @@
 		goto fail;
 	}
 
-	if (ipa3_send_wdi3_setup_pipe_cmd(&in->tx, IPA_WDI3_TX_DIR)) {
+	if (ipa3_send_wdi3_setup_pipe_cmd(in->is_smmu_enabled,
+		&in->u_tx.tx, &in->u_tx.tx_smmu, IPA_WDI3_TX_DIR)) {
 		IPAERR("fail to send cmd to uc for tx pipe\n");
 		result = -EFAULT;
 		goto fail;
@@ -197,13 +360,7 @@
 		ipahal_get_reg_mn_ofst(IPA_UC_MAILBOX_m_n,
 		IPA_HW_WDI3_TX_MBOX_START_INDEX/32,
 		IPA_HW_WDI3_TX_MBOX_START_INDEX % 32);
-	out->tx_uc_db_va = ioremap(out->tx_uc_db_pa, 4);
-	if (!out->tx_uc_db_va) {
-		IPAERR("fail to ioremap tx uc db\n");
-		result = -EFAULT;
-		goto fail;
-	}
-	IPADBG("client %d (ep: %d) connected\n", in->tx.client,
+	IPADBG("client %d (ep: %d) connected\n", tx_client,
 		ipa_ep_idx_tx);
 
 fail:
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
index 48e7d7c..c3422d1 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_reg.c
@@ -2129,11 +2129,11 @@
 		return;
 	}
 
-	valmask->val = (1 << IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_SHFT) &&
+	valmask->val = (1 << IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_SHFT) &
 		IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_BMSK;
 	valmask->mask = IPA_ENDP_INIT_AGGR_n_AGGR_FORCE_CLOSE_BMSK;
 
-	valmask->val |= ((0 << IPA_ENDP_INIT_AGGR_n_AGGR_EN_SHFT) &&
+	valmask->val |= ((0 << IPA_ENDP_INIT_AGGR_n_AGGR_EN_SHFT) &
 		IPA_ENDP_INIT_AGGR_n_AGGR_EN_BMSK);
 	valmask->mask |= IPA_ENDP_INIT_AGGR_n_AGGR_EN_BMSK;
 }
diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
index 23dafe1..833520c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c
@@ -2699,11 +2699,16 @@
 		ipa_stop_polling_stats();
 		if (atomic_read(&rmnet_ipa3_ctx->is_initialized))
 			platform_driver_unregister(&rmnet_ipa_driver);
+
+		if (atomic_read(&rmnet_ipa3_ctx->is_ssr) &&
+			ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0)
+			ipa3_q6_post_shutdown_cleanup();
 		IPAWANINFO("IPA BEFORE_SHUTDOWN handling is complete\n");
 		break;
 	case SUBSYS_AFTER_SHUTDOWN:
 		IPAWANINFO("IPA Received MPSS AFTER_SHUTDOWN\n");
-		if (atomic_read(&rmnet_ipa3_ctx->is_ssr))
+		if (atomic_read(&rmnet_ipa3_ctx->is_ssr) &&
+			ipa3_ctx->ipa_hw_type < IPA_HW_v4_0)
 			ipa3_q6_post_shutdown_cleanup();
 		IPAWANINFO("IPA AFTER_SHUTDOWN handling is complete\n");
 		break;
@@ -4026,11 +4031,6 @@
 	ipa3_qmi_init();
 
 	/* Register for Modem SSR */
-	if (ipa3_ctx != NULL)
-		/* SSR is not supported yet on IPA 4.0 */
-		if (ipa3_ctx->ipa_hw_type == IPA_HW_v4_0)
-			return platform_driver_register(&rmnet_ipa_driver);
-
 	rmnet_ipa3_ctx->subsys_notify_handle = subsys_notif_register_notifier(
 			SUBSYS_MODEM,
 			&ipa3_ssr_notifier);
diff --git a/drivers/platform/msm/mhi_dev/Makefile b/drivers/platform/msm/mhi_dev/Makefile
index c1969e2..53ef716 100644
--- a/drivers/platform/msm/mhi_dev/Makefile
+++ b/drivers/platform/msm/mhi_dev/Makefile
@@ -4,3 +4,4 @@
 obj-y += mhi_ring.o
 obj-y += mhi_uci.o
 obj-y += mhi_sm.o
+obj-y += mhi_dev_net.o
diff --git a/drivers/platform/msm/mhi_dev/mhi.c b/drivers/platform/msm/mhi_dev/mhi.c
index 7179fcd..c2187c6 100644
--- a/drivers/platform/msm/mhi_dev/mhi.c
+++ b/drivers/platform/msm/mhi_dev/mhi.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -34,13 +34,10 @@
 #include "mhi_sm.h"
 
 /* Wait time on the device for Host to set M0 state */
-#define MHI_M0_WAIT_MIN_USLEEP		20000000
-#define MHI_M0_WAIT_MAX_USLEEP		25000000
 #define MHI_DEV_M0_MAX_CNT		30
 /* Wait time before suspend/resume is complete */
-#define MHI_SUSPEND_WAIT_MIN		3100
-#define MHI_SUSPEND_WAIT_MAX		3200
-#define MHI_SUSPEND_WAIT_TIMEOUT	500
+#define MHI_SUSPEND_MIN			100
+#define MHI_SUSPEND_TIMEOUT		600
 #define MHI_MASK_CH_EV_LEN		32
 #define MHI_RING_CMD_ID			0
 #define MHI_RING_PRIMARY_EVT_ID		1
@@ -59,6 +56,13 @@
 #define HOST_ADDR_MSB(addr)		((addr >> 32) & 0xFFFFFFFF)
 
 #define MHI_IPC_LOG_PAGES		(100)
+#define MHI_REGLEN			0x100
+#define MHI_INIT			0
+#define MHI_REINIT			1
+
+#define TR_RING_ELEMENT_SZ	sizeof(struct mhi_dev_transfer_ring_element)
+#define RING_ELEMENT_TYPE_SZ	sizeof(union mhi_dev_ring_element_type)
+
 enum mhi_msg_level mhi_msg_lvl = MHI_MSG_ERROR;
 enum mhi_msg_level mhi_ipc_msg_lvl = MHI_MSG_VERBOSE;
 void *mhi_ipc_log;
@@ -67,106 +71,213 @@
 static void mhi_hwc_cb(void *priv, enum ipa_mhi_event_type event,
 	unsigned long data);
 static void mhi_ring_init_cb(void *user_data);
+static void mhi_update_state_info(uint32_t info);
+static int mhi_deinit(struct mhi_dev *mhi);
+static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify);
+static int mhi_dev_pcie_notify_event;
+static void mhi_dev_transfer_completion_cb(void *mreq);
 
-void mhi_dev_read_from_host(struct mhi_addr *host, dma_addr_t dev, size_t size)
+/*
+ * mhi_dev_ring_cache_completion_cb () - Call back function called
+ * by IPA driver when ring element cache is done
+ *
+ * @req : ring cache request
+ */
+static void  mhi_dev_ring_cache_completion_cb(void *req)
 {
-	int rc = 0;
-	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0;
+	struct ring_cache_req *ring_req = NULL;
 
-	host_addr_pa = ((u64) host->host_pa) | bit_40;
-
-	mhi_log(MHI_MSG_ERROR, "device 0x%x <<-- host 0x%llx, size %d\n",
-		dev, host_addr_pa, size);
-
-	rc = ipa_dma_sync_memcpy((u64) dev, host_addr_pa, (int) size);
-	if (rc)
-		pr_err("error while reading from host:%d\n", rc);
+	if (req)
+		ring_req = (struct ring_cache_req *)req;
+	else {
+		pr_err("%s():ring cache req data is NULL\n", __func__);
+		return;
+	}
+	complete(ring_req->done);
 }
-EXPORT_SYMBOL(mhi_dev_read_from_host);
 
-void mhi_dev_write_to_host(struct mhi_addr *host, void *dev, size_t size,
-						struct mhi_dev *mhi)
+void mhi_dev_read_from_host(struct mhi_dev *mhi, struct mhi_addr *transfer)
 {
 	int rc = 0;
-	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0;
+	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0, offset = 0;
+	struct ring_cache_req ring_req;
+
+	DECLARE_COMPLETION(done);
+
+	ring_req.done = &done;
 
 	if (!mhi) {
 		pr_err("invalid MHI ctx\n");
 		return;
 	}
 
-	host_addr_pa = ((u64) host->host_pa) | bit_40;
-	/* Copy the device content to a local device physical address */
-	memcpy(mhi->dma_cache, dev, size);
-	mhi_log(MHI_MSG_ERROR, "device 0x%llx --> host 0x%llx, size %d\n",
-		(uint64_t) mhi->cache_dma_handle, host_addr_pa, (int) size);
+	if (mhi->config_iatu) {
+		offset = (uint64_t) transfer->host_pa - mhi->ctrl_base.host_pa;
+		/* Mapping the translated physical address on the device */
+		host_addr_pa = (uint64_t) mhi->ctrl_base.device_pa + offset;
+	} else {
+		host_addr_pa = transfer->host_pa | bit_40;
+	}
 
-	rc = ipa_dma_sync_memcpy(host_addr_pa, (u64) mhi->cache_dma_handle,
-								(int) size);
+	mhi_log(MHI_MSG_VERBOSE,
+		"device 0x%x <<-- host 0x%llx, size %d\n",
+		transfer->phy_addr, host_addr_pa,
+		(int) transfer->size);
+	rc = ipa_dma_async_memcpy((u64)transfer->phy_addr, host_addr_pa,
+			(int)transfer->size,
+			mhi_dev_ring_cache_completion_cb, &ring_req);
 	if (rc)
 		pr_err("error while reading from host:%d\n", rc);
+
+	wait_for_completion(&done);
+}
+EXPORT_SYMBOL(mhi_dev_read_from_host);
+
+void mhi_dev_write_to_host(struct mhi_dev *mhi, struct mhi_addr *transfer,
+		struct event_req *ereq, enum mhi_dev_transfer_type tr_type)
+{
+	int rc = 0;
+	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0, offset = 0;
+	dma_addr_t dma;
+
+	if (!mhi) {
+		pr_err("invalid MHI ctx\n");
+		return;
+	}
+	if (mhi->config_iatu) {
+		offset = (uint64_t) transfer->host_pa - mhi->ctrl_base.host_pa;
+		/* Mapping the translated physical address on the device */
+		host_addr_pa = (uint64_t) mhi->ctrl_base.device_pa + offset;
+	} else {
+		host_addr_pa = transfer->host_pa | bit_40;
+	}
+
+	mhi_log(MHI_MSG_VERBOSE,
+		"device 0x%llx --> host 0x%llx, size %d\n",
+		(uint64_t) mhi->cache_dma_handle, host_addr_pa,
+		(int) transfer->size);
+	if (tr_type == MHI_DEV_DMA_ASYNC) {
+		dma = dma_map_single(&mhi->pdev->dev,
+				transfer->virt_addr, transfer->size,
+				DMA_TO_DEVICE);
+		if (ereq->event_type == SEND_EVENT_BUFFER) {
+			ereq->dma = dma;
+			ereq->dma_len = transfer->size;
+		} else if (ereq->event_type == SEND_EVENT_RD_OFFSET) {
+			ereq->event_rd_dma = dma;
+		}
+		rc = ipa_dma_async_memcpy(host_addr_pa, (uint64_t) dma,
+				(int)transfer->size,
+				ereq->client_cb, ereq);
+		if (rc)
+			pr_err("error while writing to host:%d\n", rc);
+	} else if (tr_type == MHI_DEV_DMA_SYNC) {
+		/* Copy the device content to a local device
+		 * physical address.
+		 */
+		memcpy(mhi->dma_cache, transfer->virt_addr,
+				transfer->size);
+		rc = ipa_dma_sync_memcpy(host_addr_pa,
+				(u64) mhi->cache_dma_handle,
+				(int) transfer->size);
+		if (rc)
+			pr_err("error while writing to host:%d\n", rc);
+	}
 }
 EXPORT_SYMBOL(mhi_dev_write_to_host);
 
 int mhi_transfer_host_to_device(void *dev, uint64_t host_pa, uint32_t len,
-							struct mhi_dev *mhi)
+		struct mhi_dev *mhi, struct mhi_req *mreq)
 {
 	int rc = 0;
-	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0;
+	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0, offset = 0;
+	struct mhi_dev_ring *ring = NULL;
 
-	if (!mhi) {
-		pr_err("Invalid mhi device\n");
+
+	if (!mhi || !dev || !host_pa || !mreq) {
+		pr_err("%s():Invalid parameters\n", __func__);
 		return -EINVAL;
 	}
 
-	if (!dev) {
-		pr_err("Invalid virt device\n");
-		return -EINVAL;
+	if (mhi->config_iatu) {
+		offset = (uint64_t)host_pa - mhi->data_base.host_pa;
+		/* Mapping the translated physical address on the device */
+		host_addr_pa = (uint64_t) mhi->data_base.device_pa + offset;
+	} else {
+		host_addr_pa = host_pa | bit_40;
 	}
 
-	if (!host_pa) {
-		pr_err("Invalid host pa device\n");
-		return -EINVAL;
-	}
-
-	host_addr_pa = host_pa | bit_40;
-	mhi_log(MHI_MSG_ERROR, "device 0x%llx <-- host 0x%llx, size %d\n",
+	mhi_log(MHI_MSG_VERBOSE, "device 0x%llx <-- host 0x%llx, size %d\n",
 		(uint64_t) mhi->read_dma_handle, host_addr_pa, (int) len);
-	rc = ipa_dma_sync_memcpy((u64) mhi->read_dma_handle,
-			host_addr_pa, (int) len);
-	if (rc) {
-		pr_err("error while reading from host:%d\n", rc);
-		return rc;
+
+	if (mreq->mode == IPA_DMA_SYNC) {
+		rc = ipa_dma_sync_memcpy((u64) mhi->read_dma_handle,
+				host_addr_pa, (int) len);
+		if (rc) {
+			pr_err("error while reading chan using sync:%d\n", rc);
+			return rc;
+		}
+		memcpy(dev, mhi->read_handle, len);
+	} else if (mreq->mode == IPA_DMA_ASYNC) {
+		ring = mreq->client->channel->ring;
+		mreq->dma = dma_map_single(&mhi->pdev->dev, dev, len,
+				DMA_FROM_DEVICE);
+		mhi_dev_ring_inc_index(ring, ring->rd_offset);
+
+		if (ring->rd_offset == ring->wr_offset)
+			mreq->snd_cmpl = 1;
+		else
+			mreq->snd_cmpl = 0;
+		rc = ipa_dma_async_memcpy(mreq->dma, host_addr_pa,
+				(int) len, mhi_dev_transfer_completion_cb,
+				mreq);
+		if (rc) {
+			pr_err("error while reading chan using async:%d\n", rc);
+			return rc;
+		}
 	}
-
-	memcpy(dev, mhi->read_handle, len);
-
 	return rc;
 }
 EXPORT_SYMBOL(mhi_transfer_host_to_device);
 
 int mhi_transfer_device_to_host(uint64_t host_addr, void *dev, uint32_t len,
-						struct mhi_dev *mhi)
+		struct mhi_dev *mhi, struct mhi_req *req)
 {
 	int rc = 0;
-	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0;
+	uint64_t bit_40 = ((u64) 1) << 40, host_addr_pa = 0, offset = 0;
+	struct mhi_dev_ring *ring = NULL;
 
-	if (!mhi || !dev || !host_addr) {
+	if (!mhi || !dev || !req  || !host_addr) {
 		pr_err("%sInvalid parameters\n", __func__);
 		return -EINVAL;
 	}
 
-	host_addr_pa = host_addr | bit_40;
-	memcpy(mhi->write_handle, dev, len);
+	if (mhi->config_iatu) {
+		offset = (uint64_t)host_addr - mhi->data_base.host_pa;
+		/* Mapping the translated physical address on the device */
+		host_addr_pa = (uint64_t) mhi->data_base.device_pa + offset;
+	} else {
+		host_addr_pa = host_addr | bit_40;
+	}
+	mhi_log(MHI_MSG_VERBOSE, "device 0x%llx ---> host 0x%llx, size %d\n",
+				(uint64_t) mhi->write_dma_handle,
+				host_addr_pa, (int) len);
 
-	mhi_log(MHI_MSG_ERROR, "device 0x%llx ---> host 0x%llx, size %d\n",
-		(uint64_t) mhi->write_dma_handle, host_addr_pa, (int) len);
-	rc = ipa_dma_sync_memcpy(host_addr_pa,
-			(u64) mhi->write_dma_handle,
-			(int) len);
-	if (rc)
-		pr_err("error while reading from host:%d\n", rc);
-
+	if (req->mode == IPA_DMA_SYNC) {
+		memcpy(mhi->write_handle, dev, len);
+		rc = ipa_dma_sync_memcpy(host_addr_pa,
+				(u64) mhi->write_dma_handle, (int) len);
+	} else if (req->mode == IPA_DMA_ASYNC) {
+		req->dma = dma_map_single(&mhi->pdev->dev, req->buf,
+				req->len, DMA_TO_DEVICE);
+		ring = req->client->channel->ring;
+		mhi_dev_ring_inc_index(ring, ring->rd_offset);
+		if (ring->rd_offset == ring->wr_offset)
+			req->snd_cmpl = 1;
+		rc = ipa_dma_async_memcpy(host_addr_pa,
+				(uint64_t) req->dma, (int) len,
+				mhi_dev_transfer_completion_cb, req);
+	}
 	return rc;
 }
 EXPORT_SYMBOL(mhi_transfer_device_to_host);
@@ -216,7 +327,7 @@
 
 	mhi_dev_get_erdb_db_cfg(mhi, &erdb_cfg);
 
-	mhi_log(MHI_MSG_ERROR,
+	mhi_log(MHI_MSG_VERBOSE,
 		"Event rings 0x%x => er_base 0x%x, er_end %d\n",
 		mhi->cfg.event_rings, erdb_cfg.base, erdb_cfg.end);
 	erdb_cfg.tgt_addr = (uint32_t) mhi->ipa_uc_mbox_erdb;
@@ -247,7 +358,7 @@
 	}
 
 	mhi_dev_get_erdb_db_cfg(mhi, &erdb_cfg);
-	mhi_log(MHI_MSG_ERROR,
+	mhi_log(MHI_MSG_VERBOSE,
 		"Event rings 0x%x => er_base 0x%x, er_end %d\n",
 		mhi->cfg.event_rings, erdb_cfg.base, erdb_cfg.end);
 
@@ -259,10 +370,18 @@
 	ipa_init_params.msi.mask = ((1 << cfg.msg_num) - 1);
 	ipa_init_params.first_er_idx = erdb_cfg.base;
 	ipa_init_params.first_ch_idx = HW_CHANNEL_BASE;
-	ipa_init_params.mmio_addr = ((uint32_t) mhi_ctx->mmio_base_pa_addr);
-	ipa_init_params.assert_bit40 = true;
 
-	mhi_log(MHI_MSG_ERROR,
+	if (mhi_ctx->config_iatu)
+		ipa_init_params.mmio_addr =
+			((uint32_t) mhi_ctx->mmio_base_pa_addr) + MHI_REGLEN;
+	else
+		ipa_init_params.mmio_addr =
+			((uint32_t) mhi_ctx->mmio_base_pa_addr);
+
+	if (!mhi_ctx->config_iatu)
+		ipa_init_params.assert_bit40 = true;
+
+	mhi_log(MHI_MSG_VERBOSE,
 		"MMIO Addr 0x%x, MSI config: U:0x%x L: 0x%x D: 0x%x\n",
 		ipa_init_params.mmio_addr, cfg.upper, cfg.lower, cfg.data);
 	ipa_init_params.notify = mhi_hwc_cb;
@@ -284,10 +403,15 @@
 
 	memset(&ipa_start_params, 0, sizeof(ipa_start_params));
 
-	ipa_start_params.channel_context_array_addr =
+	if (mhi->config_iatu) {
+		ipa_start_params.host_ctrl_addr = mhi->ctrl_base.device_pa;
+		ipa_start_params.host_data_addr = mhi->data_base.device_pa;
+	} else {
+		ipa_start_params.channel_context_array_addr =
 				mhi->ch_ctx_shadow.host_pa;
-	ipa_start_params.event_context_array_addr =
+		ipa_start_params.event_context_array_addr =
 				mhi->ev_ctx_shadow.host_pa;
+	}
 
 	rc = ipa_mhi_start(&ipa_start_params);
 	if (rc)
@@ -303,7 +427,7 @@
 
 	switch (event) {
 	case IPA_MHI_EVENT_READY:
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_INFO,
 			"HW Channel uC is ready event=0x%X\n", event);
 		rc = mhi_hwc_start(mhi_ctx);
 		if (rc) {
@@ -329,6 +453,11 @@
 			pr_err("Failed to enable command db\n");
 			return;
 		}
+
+		mhi_update_state_info(MHI_STATE_CONNECTED);
+
+		ep_pcie_mask_irq_event(mhi_ctx->phandle,
+				EP_PCIE_INT_EVT_MHI_A7, true);
 		break;
 	case IPA_MHI_EVENT_DATA_AVAILABLE:
 		rc = mhi_dev_notify_sm_event(MHI_DEV_EVENT_HW_ACC_WAKEUP);
@@ -352,6 +481,7 @@
 	memset(&connect_params, 0, sizeof(connect_params));
 
 	switch (type) {
+	case MHI_DEV_RING_EL_RESET:
 	case MHI_DEV_RING_EL_STOP:
 		rc = ipa_mhi_disconnect_pipe(
 			mhi->ipa_clnt_hndl[chid-HW_CHANNEL_BASE]);
@@ -402,15 +532,18 @@
 
 static void mhi_dev_fetch_ch_ctx(struct mhi_dev *mhi, uint32_t ch_id)
 {
-	struct mhi_addr addr;
+	struct mhi_addr data_transfer;
 
-	addr.host_pa = mhi->ch_ctx_shadow.host_pa +
+	if (mhi->use_ipa) {
+		data_transfer.host_pa = mhi->ch_ctx_shadow.host_pa +
 					sizeof(struct mhi_dev_ch_ctx) * ch_id;
-	addr.size  = sizeof(struct mhi_dev_ch_ctx);
+		data_transfer.phy_addr = mhi->ch_ctx_cache_dma_handle +
+					sizeof(struct mhi_dev_ch_ctx) * ch_id;
+	}
+
+	data_transfer.size  = sizeof(struct mhi_dev_ch_ctx);
 	/* Fetch the channel ctx (*dst, *src, size) */
-	mhi_dev_read_from_host(&addr, mhi->ch_ctx_cache_dma_handle +
-					(sizeof(struct mhi_dev_ch_ctx) * ch_id),
-				sizeof(struct mhi_dev_ch_ctx));
+	mhi_dev_read_from_host(mhi, &data_transfer);
 }
 
 int mhi_dev_syserr(struct mhi_dev *mhi)
@@ -436,24 +569,21 @@
 	struct mhi_dev_ring *ring = &mhi->ring[evnt_ring_idx];
 	union mhi_dev_ring_ctx *ctx;
 	struct ep_pcie_msi_config cfg;
-	struct mhi_addr msi_addr;
-	uint32_t msi = 0;
-	struct mhi_addr host_rp_addr;
+	struct mhi_addr transfer_addr;
 
-	rc = ep_pcie_get_msi_config(mhi->phandle,
-			&cfg);
-		if (rc) {
-			pr_err("Error retrieving pcie msi logic\n");
-			return rc;
-		}
+	rc = ep_pcie_get_msi_config(mhi->phandle, &cfg);
+	if (rc) {
+		pr_err("Error retrieving pcie msi logic\n");
+		return rc;
+	}
 
 	if (evnt_ring_idx > mhi->cfg.event_rings) {
 		pr_err("Invalid event ring idx: %lld\n", evnt_ring_idx);
 		return -EINVAL;
 	}
 
+	ctx = (union mhi_dev_ring_ctx *)&mhi->ev_ctx_cache[evnt_ring];
 	if (mhi_ring_get_state(ring) == RING_STATE_UINT) {
-		ctx = (union mhi_dev_ring_ctx *)&mhi->ev_ctx_cache[evnt_ring];
 		rc = mhi_ring_start(ring, ctx, mhi);
 		if (rc) {
 			mhi_log(MHI_MSG_ERROR,
@@ -464,23 +594,30 @@
 
 	mutex_lock(&mhi->mhi_event_lock);
 	/* add the ring element */
-	mhi_dev_add_element(ring, el);
+	mhi_dev_add_element(ring, el, NULL, 0);
 
 	ring->ring_ctx_shadow->ev.rp =  (ring->rd_offset *
 				sizeof(union mhi_dev_ring_element_type)) +
 				ring->ring_ctx->generic.rbase;
 
-	mhi_log(MHI_MSG_ERROR, "ev.rp = %llx for %lld\n",
+	mhi_log(MHI_MSG_VERBOSE, "ev.rp = %llx for %lld\n",
 				ring->ring_ctx_shadow->ev.rp, evnt_ring_idx);
 
-	host_rp_addr.host_pa = (mhi->ev_ctx_shadow.host_pa +
+	if (mhi->use_ipa)
+		transfer_addr.host_pa = (mhi->ev_ctx_shadow.host_pa +
 			sizeof(struct mhi_dev_ev_ctx) *
 			evnt_ring) + (uint32_t) &ring->ring_ctx->ev.rp -
 			(uint32_t) ring->ring_ctx;
-	mhi_dev_write_to_host(&host_rp_addr, &ring->ring_ctx_shadow->ev.rp,
-						sizeof(uint64_t),
-						mhi);
+	else
+		transfer_addr.device_va = (mhi->ev_ctx_shadow.device_va +
+			sizeof(struct mhi_dev_ev_ctx) *
+			evnt_ring) + (uint32_t) &ring->ring_ctx->ev.rp -
+			(uint32_t) ring->ring_ctx;
 
+	transfer_addr.virt_addr = &ring->ring_ctx_shadow->ev.rp;
+	transfer_addr.size = sizeof(uint64_t);
+
+	mhi_dev_write_to_host(mhi, &transfer_addr, NULL, MHI_DEV_DMA_SYNC);
 	/*
 	 * rp update in host memory should be flushed
 	 * before sending a MSI to the host
@@ -488,20 +625,141 @@
 	wmb();
 
 	mutex_unlock(&mhi->mhi_event_lock);
-	mhi_log(MHI_MSG_ERROR, "event sent:\n");
-	mhi_log(MHI_MSG_ERROR, "evnt ptr : 0x%llx\n", el->evt_tr_comp.ptr);
-	mhi_log(MHI_MSG_ERROR, "evnt len : 0x%x\n", el->evt_tr_comp.len);
-	mhi_log(MHI_MSG_ERROR, "evnt code :0x%x\n", el->evt_tr_comp.code);
-	mhi_log(MHI_MSG_ERROR, "evnt type :0x%x\n", el->evt_tr_comp.type);
-	mhi_log(MHI_MSG_ERROR, "evnt chid :0x%x\n", el->evt_tr_comp.chid);
+	mhi_log(MHI_MSG_VERBOSE, "event sent:\n");
+	mhi_log(MHI_MSG_VERBOSE, "evnt ptr : 0x%llx\n", el->evt_tr_comp.ptr);
+	mhi_log(MHI_MSG_VERBOSE, "evnt len : 0x%x\n", el->evt_tr_comp.len);
+	mhi_log(MHI_MSG_VERBOSE, "evnt code :0x%x\n", el->evt_tr_comp.code);
+	mhi_log(MHI_MSG_VERBOSE, "evnt type :0x%x\n", el->evt_tr_comp.type);
+	mhi_log(MHI_MSG_VERBOSE, "evnt chid :0x%x\n", el->evt_tr_comp.chid);
+	rc = ep_pcie_trigger_msi(mhi_ctx->phandle, ctx->ev.msivec);
+	if (rc) {
+		pr_err("%s: error sending msi\n", __func__);
+		return rc;
+	}
+	return rc;
+}
 
-	msi_addr.host_pa = (uint64_t)((uint64_t)cfg.upper << 32) |
-						(uint64_t)cfg.lower;
-	msi = cfg.data + mhi_ctx->mhi_ep_msi_num;
-	mhi_log(MHI_MSG_ERROR, "Sending MSI %d to 0x%llx as data = 0x%x\n",
-			mhi_ctx->mhi_ep_msi_num, msi_addr.host_pa, msi);
-	mhi_dev_write_to_host(&msi_addr, &msi, 4, mhi);
+/*
+ * mhi_dev_event_buf_completion_cb() -Cb function called by IPA driver
+ * when transfer completion event buffer copy is done.
+ *
+ * @req -  event_req structure
+ */
 
+static void mhi_dev_event_buf_completion_cb(void *req)
+{
+	struct event_req *ereq = NULL;
+
+	if (req) {
+		ereq = (struct event_req *)req;
+	} else {
+		pr_err("%s():event req data is invalid\n", __func__);
+		return;
+	}
+	dma_unmap_single(&mhi_ctx->pdev->dev, ereq->dma,
+			ereq->dma_len, DMA_TO_DEVICE);
+}
+
+/**
+ * mhi_dev_event_rd_offset_completion_cb() -CB function called by IPA driver
+ * when event rd_offset transfer is done.
+ *
+ * @req -  event_req structure
+ */
+
+static void mhi_dev_event_rd_offset_completion_cb(void *req)
+{
+	union mhi_dev_ring_ctx *ctx;
+	int rc = 0;
+	struct event_req *ereq = (struct event_req *)req;
+	struct mhi_dev_channel *ch = ereq->context;
+	struct mhi_dev *mhi = ch->ring->mhi_dev;
+	unsigned long flags;
+
+	dma_unmap_single(&mhi_ctx->pdev->dev, ereq->event_rd_dma,
+			sizeof(uint64_t), DMA_TO_DEVICE);
+	ctx = (union mhi_dev_ring_ctx *)&mhi->ev_ctx_cache[ereq->event_ring];
+	rc = ep_pcie_trigger_msi(mhi_ctx->phandle, ctx->ev.msivec);
+	if (rc)
+		pr_err("%s: error sending in msi\n", __func__);
+
+	/* return the event req to pre allocated pooled list */
+	spin_lock_irqsave(&mhi->lock, flags);
+	list_add_tail(&ereq->list, &ch->event_req_buffers);
+	spin_unlock_irqrestore(&mhi->lock, flags);
+}
+
+static int mhi_dev_send_multiple_tr_events(struct mhi_dev *mhi, int evnt_ring,
+		struct event_req *ereq, uint32_t evt_len)
+{
+	int rc = 0;
+	uint64_t evnt_ring_idx = mhi->ev_ring_start + evnt_ring;
+	struct mhi_dev_ring *ring = &mhi->ring[evnt_ring_idx];
+	union mhi_dev_ring_ctx *ctx;
+	struct mhi_addr transfer_addr;
+	static int count;
+
+	if (!ereq) {
+		pr_err("%s(): invalid event req\n", __func__);
+		return -EINVAL;
+	}
+
+	if (count == 0) {
+		rc = ep_pcie_get_msi_config(mhi->phandle, &mhi->msi_cfg);
+		if (rc) {
+			pr_err("Error retrieving pcie msi logic\n");
+			return rc;
+		}
+		count++;
+	}
+
+	if (evnt_ring_idx > mhi->cfg.event_rings) {
+		pr_err("Invalid event ring idx: %lld\n", evnt_ring_idx);
+		return -EINVAL;
+	}
+
+	ctx = (union mhi_dev_ring_ctx *)&mhi->ev_ctx_cache[evnt_ring];
+	if (mhi_ring_get_state(ring) == RING_STATE_UINT) {
+		rc = mhi_ring_start(ring, ctx, mhi);
+		if (rc) {
+			mhi_log(MHI_MSG_ERROR,
+				"error starting event ring %d\n", evnt_ring);
+			return rc;
+		}
+	}
+
+	/* add the ring element */
+	ereq->client_cb = mhi_dev_event_buf_completion_cb;
+	ereq->event_type = SEND_EVENT_BUFFER;
+	rc = mhi_dev_add_element(ring, ereq->tr_events, ereq, evt_len);
+	if (rc) {
+		pr_err("%s(): error in adding element rc %d\n", __func__, rc);
+		return rc;
+	}
+	ring->ring_ctx_shadow->ev.rp = (ring->rd_offset *
+		sizeof(union mhi_dev_ring_element_type)) +
+		ring->ring_ctx->generic.rbase;
+
+	mhi_log(MHI_MSG_VERBOSE, "ev.rp = %llx for %lld\n",
+		ring->ring_ctx_shadow->ev.rp, evnt_ring_idx);
+
+	if (mhi->use_ipa)
+		transfer_addr.host_pa = (mhi->ev_ctx_shadow.host_pa +
+		sizeof(struct mhi_dev_ev_ctx) *
+		evnt_ring) + (uint32_t)&ring->ring_ctx->ev.rp -
+		(uint32_t)ring->ring_ctx;
+	else
+		transfer_addr.device_va = (mhi->ev_ctx_shadow.device_va +
+		sizeof(struct mhi_dev_ev_ctx) *
+		evnt_ring) + (uint32_t)&ring->ring_ctx->ev.rp -
+		(uint32_t)ring->ring_ctx;
+
+	transfer_addr.virt_addr = &ring->ring_ctx_shadow->ev.rp;
+	transfer_addr.size = sizeof(uint64_t);
+	ereq->event_type = SEND_EVENT_RD_OFFSET;
+	ereq->client_cb = mhi_dev_event_rd_offset_completion_cb;
+	ereq->event_ring = evnt_ring;
+	mhi_dev_write_to_host(mhi, &transfer_addr, ereq, MHI_DEV_DMA_ASYNC);
 	return rc;
 }
 
@@ -564,6 +822,21 @@
 }
 EXPORT_SYMBOL(mhi_dev_send_ee_event);
 
+static void mhi_dev_trigger_cb(void)
+{
+	struct mhi_dev_ready_cb_info *info;
+	uint32_t state_data;
+
+	mutex_lock(&mhi_ctx->mhi_lock);
+	list_for_each_entry(info, &mhi_ctx->client_cb_list, list)
+		if (info->cb) {
+			mhi_ctrl_state_info(&state_data);
+			info->cb_data.ctrl_info = state_data;
+			info->cb(&info->cb_data);
+		}
+	mutex_unlock(&mhi_ctx->mhi_lock);
+}
+
 int mhi_dev_trigger_hw_acc_wakeup(struct mhi_dev *mhi)
 {
 	int rc = 0;
@@ -591,7 +864,7 @@
 	event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase
 			+ (mhi->ring[MHI_RING_CMD_ID].rd_offset *
 			(sizeof(union mhi_dev_ring_element_type)));
-	mhi_log(MHI_MSG_ERROR, "evt cmd comp ptr :%d\n",
+	mhi_log(MHI_MSG_VERBOSE, "evt cmd comp ptr :%d\n",
 			(uint32_t) event.evt_cmd_comp.ptr);
 	event.evt_cmd_comp.type = MHI_DEV_RING_EL_CMD_COMPLETION_EVT;
 	event.evt_cmd_comp.code = MHI_CMD_COMPL_CODE_SUCCESS;
@@ -607,27 +880,38 @@
 							struct mhi_dev *mhi)
 {
 	int rc = 0;
-	struct mhi_addr host_addr;
+	struct mhi_addr data_transfer;
 
 	if (ring->rd_offset != ring->wr_offset &&
 		mhi->ch_ctx_cache[ch_id].ch_type ==
 				MHI_DEV_CH_TYPE_OUTBOUND_CHANNEL) {
-		mhi_log(MHI_MSG_INFO, "Pending transaction to be processed\n");
+		mhi_log(MHI_MSG_INFO, "Pending outbound transaction\n");
 		return 0;
 	} else if (mhi->ch_ctx_cache[ch_id].ch_type ==
 			MHI_DEV_CH_TYPE_INBOUND_CHANNEL &&
 			mhi->ch[ch_id].wr_request_active) {
+		mhi_log(MHI_MSG_INFO, "Pending inbound transaction\n");
 		return 0;
 	}
 
 	/* set the channel to stop */
 	mhi->ch_ctx_cache[ch_id].ch_state = MHI_DEV_CH_STATE_STOP;
+	mhi->ch[ch_id].state = MHI_DEV_CH_STOPPED;
 
-	host_addr.host_pa = mhi->ch_ctx_shadow.host_pa +
+	if (mhi->use_ipa) {
+		data_transfer.host_pa = mhi->ch_ctx_shadow.host_pa +
 				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+	} else {
+		data_transfer.device_va = mhi->ch_ctx_shadow.device_va +
+				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+		data_transfer.device_pa = mhi->ch_ctx_shadow.device_pa +
+				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+	}
+	data_transfer.size = sizeof(enum mhi_dev_ch_ctx_state);
+	data_transfer.virt_addr = &mhi->ch_ctx_cache[ch_id].ch_state;
+
 	/* update the channel state in the host */
-	mhi_dev_write_to_host(&host_addr, &mhi->ch_ctx_cache[ch_id].ch_state,
-				sizeof(enum mhi_dev_ch_ctx_state), mhi);
+	mhi_dev_write_to_host(mhi, &data_transfer, NULL, MHI_DEV_DMA_SYNC);
 
 	/* send the completion event to the host */
 	rc = mhi_dev_send_cmd_comp_event(mhi);
@@ -644,14 +928,16 @@
 	uint32_t ch_id = 0;
 	union mhi_dev_ring_element_type event;
 	struct mhi_addr host_addr;
+	struct mhi_dev_channel *ch;
+	struct mhi_dev_ring *ring;
 
-	mhi_log(MHI_MSG_ERROR, "for channel:%d and cmd:%d\n",
-		ch_id, el->generic.type);
 	ch_id = el->generic.chid;
+	mhi_log(MHI_MSG_VERBOSE, "for channel:%d and cmd:%d\n",
+		ch_id, el->generic.type);
 
 	switch (el->generic.type) {
 	case MHI_DEV_RING_EL_START:
-		mhi_log(MHI_MSG_ERROR, "recived start cmd for channel %d\n",
+		mhi_log(MHI_MSG_VERBOSE, "recived start cmd for channel %d\n",
 								ch_id);
 		if (ch_id >= (HW_CHANNEL_BASE)) {
 			rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
@@ -680,6 +966,7 @@
 
 		/* set the channel to running */
 		mhi->ch_ctx_cache[ch_id].ch_state = MHI_DEV_CH_STATE_RUNNING;
+		mhi->ch[ch_id].state = MHI_DEV_CH_STARTED;
 		mhi->ch[ch_id].ch_id = ch_id;
 		mhi->ch[ch_id].ring = &mhi->ring[mhi->ch_ring_start + ch_id];
 		mhi->ch[ch_id].ch_type = mhi->ch_ctx_cache[ch_id].ch_type;
@@ -691,17 +978,26 @@
 			return;
 		}
 
-		host_addr.host_pa = mhi->ch_ctx_shadow.host_pa +
+		if (mhi->use_ipa)
+			host_addr.host_pa = mhi->ch_ctx_shadow.host_pa +
 					sizeof(struct mhi_dev_ch_ctx) * ch_id;
-		mhi_dev_write_to_host(&host_addr,
-					&mhi->ch_ctx_cache[ch_id].ch_state,
-					sizeof(enum mhi_dev_ch_ctx_state), mhi);
+		else
+			host_addr.device_va = mhi->ch_ctx_shadow.device_va +
+					sizeof(struct mhi_dev_ch_ctx) * ch_id;
+
+		host_addr.virt_addr = &mhi->ch_ctx_cache[ch_id].ch_state;
+		host_addr.size = sizeof(enum mhi_dev_ch_ctx_state);
+
+		mhi_dev_write_to_host(mhi, &host_addr, NULL, MHI_DEV_DMA_SYNC);
 
 send_start_completion_event:
 		rc = mhi_dev_send_cmd_comp_event(mhi);
 		if (rc)
 			pr_err("Error sending command completion event\n");
 
+		/* Trigger callback to clients */
+		mhi_dev_trigger_cb();
+
 		break;
 	case MHI_DEV_RING_EL_STOP:
 		if (ch_id >= HW_CHANNEL_BASE) {
@@ -738,32 +1034,99 @@
 			 * channel command to check if one can suspend the
 			 * command.
 			 */
+			ring = &mhi->ring[ch_id + mhi->ch_ring_start];
+			if (ring->state == RING_STATE_UINT) {
+				pr_err("Channel not opened for %d\n", ch_id);
+				return;
+			}
+
+			ch = &mhi->ch[ch_id];
+
+			mutex_lock(&ch->ch_lock);
+
 			mhi->ch[ch_id].state = MHI_DEV_CH_PENDING_STOP;
 			rc = mhi_dev_process_stop_cmd(
 				&mhi->ring[mhi->ch_ring_start + ch_id],
 				ch_id, mhi);
+			if (rc)
+				pr_err("stop event send failed\n");
+
+			mutex_unlock(&ch->ch_lock);
+		}
+		break;
+	case MHI_DEV_RING_EL_RESET:
+		mhi_log(MHI_MSG_VERBOSE,
+			"received reset cmd for channel %d\n", ch_id);
+		if (ch_id >= HW_CHANNEL_BASE) {
+			rc = mhi_hwc_chcmd(mhi, ch_id, el->generic.type);
+			if (rc) {
+				mhi_log(MHI_MSG_ERROR,
+					"send channel stop cmd event failed\n");
+				return;
+			}
+
+			/* send the completion event to the host */
+			event.evt_cmd_comp.ptr = mhi->cmd_ctx_cache->rbase +
+				(mhi->ring[MHI_RING_CMD_ID].rd_offset *
+				(sizeof(union mhi_dev_ring_element_type)));
+			event.evt_cmd_comp.type =
+					MHI_DEV_RING_EL_CMD_COMPLETION_EVT;
+			if (rc == 0)
+				event.evt_cmd_comp.code =
+					MHI_CMD_COMPL_CODE_SUCCESS;
+			else
+				event.evt_cmd_comp.code =
+					MHI_CMD_COMPL_CODE_UNDEFINED;
+
+			rc = mhi_dev_send_event(mhi, 0, &event);
 			if (rc) {
 				pr_err("stop event send failed\n");
 				return;
 			}
+		} else {
+
+			mhi_log(MHI_MSG_VERBOSE,
+					"received reset cmd for channel %d\n",
+					ch_id);
+
+			ring = &mhi->ring[ch_id + mhi->ch_ring_start];
+			if (ring->state == RING_STATE_UINT) {
+				pr_err("Channel not opened for %d\n", ch_id);
+				return;
+			}
+
+			ch = &mhi->ch[ch_id];
+
+			mutex_lock(&ch->ch_lock);
+
+			/* hard stop and set the channel to stop */
+			mhi->ch_ctx_cache[ch_id].ch_state =
+						MHI_DEV_CH_STATE_DISABLED;
+			mhi->ch[ch_id].state = MHI_DEV_CH_STOPPED;
+			if (mhi->use_ipa)
+				host_addr.host_pa =
+					mhi->ch_ctx_shadow.host_pa +
+					(sizeof(struct mhi_dev_ch_ctx) * ch_id);
+			else
+				host_addr.device_va =
+					mhi->ch_ctx_shadow.device_va +
+					(sizeof(struct mhi_dev_ch_ctx) * ch_id);
+
+			host_addr.virt_addr =
+					&mhi->ch_ctx_cache[ch_id].ch_state;
+			host_addr.size = sizeof(enum mhi_dev_ch_ctx_state);
+
+			/* update the channel state in the host */
+			mhi_dev_write_to_host(mhi, &host_addr, NULL,
+					MHI_DEV_DMA_SYNC);
+
+			/* send the completion event to the host */
+			rc = mhi_dev_send_cmd_comp_event(mhi);
+			if (rc)
+				pr_err("Error sending command completion event\n");
+			mutex_unlock(&ch->ch_lock);
 		}
 		break;
-	case MHI_DEV_RING_EL_RESET:
-		/* hard stop and set the channel to stop */
-		mhi->ch_ctx_cache[ch_id].ch_state = MHI_DEV_CH_STATE_STOP;
-		host_addr.host_pa = mhi->ch_ctx_shadow.host_pa +
-				sizeof(struct mhi_dev_ch_ctx) * ch_id;
-
-		/* update the channel state in the host */
-		mhi_dev_write_to_host(&host_addr,
-				&mhi->ch_ctx_cache[ch_id].ch_state,
-				sizeof(enum mhi_dev_ch_ctx_state), mhi);
-
-		/* send the completion event to the host */
-		rc = mhi_dev_send_cmd_comp_event(mhi);
-		if (rc)
-			pr_err("Error sending command completion event\n");
-		break;
 	default:
 		pr_err("%s: Invalid command:%d\n", __func__, el->generic.type);
 		break;
@@ -778,7 +1141,7 @@
 	struct mhi_dev_client_cb_reason reason;
 
 	if (ring->id < mhi->ch_ring_start) {
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_VERBOSE,
 			"invalid channel ring id (%d), should be < %d\n",
 			ring->id, mhi->ch_ring_start);
 		return;
@@ -816,7 +1179,7 @@
 	list_for_each_safe(cp, q, &mhi->process_ring_list) {
 		ring = list_entry(cp, struct mhi_dev_ring, list);
 		list_del(cp);
-		mhi_log(MHI_MSG_ERROR, "processing ring %d\n", ring->id);
+		mhi_log(MHI_MSG_VERBOSE, "processing ring %d\n", ring->id);
 		rc = mhi_dev_process_ring(ring);
 		if (rc) {
 			mhi_log(MHI_MSG_ERROR,
@@ -879,7 +1242,7 @@
 		if (chintr_value & 1) {
 			ring = &mhi->ring[ch_num + mhi->ch_ring_start];
 			if (ring->state == RING_STATE_UINT) {
-				pr_err("Channel not opened for %d\n", ch_num);
+				pr_debug("Channel not opened for %d\n", ch_num);
 				break;
 			}
 			mhi_ring_set_state(ring, RING_STATE_PENDING);
@@ -907,9 +1270,10 @@
 
 	for (i = 0; i < MHI_MASK_ROWS_CH_EV_DB; i++) {
 		ch_num = i * MHI_MASK_CH_EV_LEN;
-		chintr_value = mhi->chdb[i].status;
+		/* Process channel status whose mask is enabled */
+		chintr_value = (mhi->chdb[i].status & mhi->chdb[i].mask);
 		if (chintr_value) {
-			mhi_log(MHI_MSG_ERROR,
+			mhi_log(MHI_MSG_VERBOSE,
 				"processing id: %d, ch interrupt 0x%x\n",
 							i, chintr_value);
 			mhi_dev_queue_channel_db(mhi, chintr_value, ch_num);
@@ -923,6 +1287,153 @@
 	}
 }
 
+static int mhi_dev_abort(struct mhi_dev *mhi)
+{
+	struct mhi_dev_channel *ch;
+	struct mhi_dev_ring *ring;
+	int ch_id = 0, rc = 0;
+
+	/* Hard stop all the channels */
+	for (ch_id = 0; ch_id < mhi->cfg.channels; ch_id++) {
+		ring = &mhi->ring[ch_id + mhi->ch_ring_start];
+		if (ring->state == RING_STATE_UINT)
+			continue;
+
+		ch = &mhi->ch[ch_id];
+		mutex_lock(&ch->ch_lock);
+		mhi->ch[ch_id].state = MHI_DEV_CH_STOPPED;
+		mutex_unlock(&ch->ch_lock);
+	}
+
+	/* Update ctrl node */
+	mhi_update_state_info(MHI_STATE_DISCONNECTED);
+
+	flush_workqueue(mhi->ring_init_wq);
+	flush_workqueue(mhi->pending_ring_wq);
+
+	/* Initiate MHI IPA reset */
+	ipa_mhi_destroy();
+
+	/* Clean up initialized channels */
+	rc = mhi_deinit(mhi);
+	if (rc) {
+		pr_err("Error during mhi_deinit with %d\n", rc);
+		return rc;
+	}
+
+	rc = mhi_dev_mmio_mask_chdb_interrupts(mhi_ctx);
+	if (rc) {
+		pr_err("Failed to enable channel db\n");
+		return rc;
+	}
+
+	rc = mhi_dev_mmio_disable_ctrl_interrupt(mhi_ctx);
+	if (rc) {
+		pr_err("Failed to enable control interrupt\n");
+		return rc;
+	}
+
+	rc = mhi_dev_mmio_disable_cmdb_interrupt(mhi_ctx);
+	if (rc) {
+		pr_err("Failed to enable command db\n");
+		return rc;
+	}
+
+
+	atomic_set(&mhi_ctx->re_init_done, 0);
+
+	mhi_log(MHI_MSG_INFO,
+			"Register a PCIe callback during re-init\n");
+	mhi_ctx->event_reg.events = EP_PCIE_EVENT_LINKUP;
+	mhi_ctx->event_reg.user = mhi_ctx;
+	mhi_ctx->event_reg.mode = EP_PCIE_TRIGGER_CALLBACK;
+	mhi_ctx->event_reg.callback = mhi_dev_resume_init_with_link_up;
+	mhi_ctx->event_reg.options = MHI_REINIT;
+
+	rc = ep_pcie_register_event(mhi_ctx->phandle,
+					&mhi_ctx->event_reg);
+	if (rc) {
+		pr_err("Failed to register for events from PCIe\n");
+		return rc;
+	}
+
+	/* Set RESET field to 0 */
+	mhi_dev_mmio_reset(mhi_ctx);
+
+	return rc;
+}
+
+static void mhi_dev_transfer_completion_cb(void *mreq)
+{
+	struct mhi_dev_channel *ch;
+	struct mhi_dev_client *client;
+	union mhi_dev_ring_element_type *el;
+	int rc = 0;
+	struct mhi_req *req = (struct mhi_req *)mreq;
+	struct mhi_req *local_req = NULL;
+	union mhi_dev_ring_element_type *compl_ev = NULL;
+	struct mhi_dev *mhi = NULL;
+	unsigned long flags;
+
+	client = req->client;
+	ch = client->channel;
+	mhi = ch->ring->mhi_dev;
+	el = req->el;
+	local_req = req;
+	ch->curr_ereq->context = ch;
+
+	dma_unmap_single(&mhi_ctx->pdev->dev, req->dma,
+			req->len, DMA_FROM_DEVICE);
+
+	/* Trigger client call back */
+	req->client_cb(req);
+
+	if (el->tre.ieot) {
+		compl_ev = ch->curr_ereq->tr_events + ch->curr_ereq->num_events;
+		compl_ev->evt_tr_comp.chid = ch->ch_id;
+		compl_ev->evt_tr_comp.type =
+				MHI_DEV_RING_EL_TRANSFER_COMPLETION_EVENT;
+		compl_ev->evt_tr_comp.len = el->tre.len;
+		compl_ev->evt_tr_comp.code = MHI_CMD_COMPL_CODE_EOT;
+		compl_ev->evt_tr_comp.ptr = ch->ring->ring_ctx->generic.rbase +
+				local_req->rd_offset * TR_RING_ELEMENT_SZ;
+		ch->curr_ereq->num_events++;
+
+		if (ch->curr_ereq->num_events >= MAX_TR_EVENTS ||
+				local_req->snd_cmpl){
+			mhi_log(MHI_MSG_VERBOSE,
+					"num of tr events %d for ch %d\n",
+					ch->curr_ereq->num_events, ch->ch_id);
+			rc = mhi_dev_send_multiple_tr_events(mhi,
+				mhi->ch_ctx_cache[ch->ch_id].err_indx,
+				ch->curr_ereq, (ch->curr_ereq->num_events*
+				sizeof(union mhi_dev_ring_element_type)));
+			if (rc)
+				mhi_log(MHI_MSG_ERROR,
+						"failed to send compl evts\n");
+			if (!list_empty(&ch->event_req_buffers)) {
+				ch->curr_ereq =
+					container_of(ch->event_req_buffers.next,
+							struct event_req, list);
+				spin_lock_irqsave(&mhi->lock, flags);
+				list_del_init(&ch->curr_ereq->list);
+				spin_unlock_irqrestore(&mhi->lock, flags);
+				ch->curr_ereq->num_events = 0;
+			} else
+				pr_err("%s evt req buffers empty\n", __func__);
+		}
+	} else
+		mhi_log(MHI_MSG_ERROR, "ieot is not valid\n");
+
+	if (ch->state == MHI_DEV_CH_PENDING_STOP) {
+		ch->state = MHI_DEV_CH_STOPPED;
+		rc = mhi_dev_process_stop_cmd(ch->ring, ch->ch_id, mhi_ctx);
+		if (rc)
+			mhi_log(MHI_MSG_ERROR,
+			"Error while stopping channel (%d)\n", ch->ch_id);
+	}
+}
+
 static void mhi_dev_scheduler(struct work_struct *work)
 {
 	struct mhi_dev *mhi = container_of(work,
@@ -932,38 +1443,48 @@
 	struct mhi_dev_ring *ring;
 	enum mhi_dev_state state;
 	enum mhi_dev_event event = 0;
+	bool mhi_reset = false;
 
 	mutex_lock(&mhi_ctx->mhi_lock);
 	/* Check for interrupts */
 	mhi_dev_core_ack_ctrl_interrupts(mhi, &int_value);
 
 	if (int_value & MHI_MMIO_CTRL_INT_STATUS_A7_MSK) {
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_VERBOSE,
 			"processing ctrl interrupt with %d\n", int_value);
-		rc = mhi_dev_mmio_get_mhi_state(mhi, &state);
+		rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
 		if (rc) {
 			pr_err("%s: get mhi state failed\n", __func__);
 			mutex_unlock(&mhi_ctx->mhi_lock);
 			return;
 		}
 
+		if (mhi_reset) {
+			mhi_log(MHI_MSG_VERBOSE,
+				"processing mhi device reset\n");
+			rc = mhi_dev_abort(mhi);
+			if (rc)
+				pr_err("device reset failed:%d\n", rc);
+			mutex_unlock(&mhi_ctx->mhi_lock);
+			queue_work(mhi->ring_init_wq, &mhi->re_init);
+			return;
+		}
+
 		rc = mhi_dev_get_event_notify(state, &event);
 		if (rc) {
 			pr_err("unsupported state :%d\n", state);
-			mutex_unlock(&mhi_ctx->mhi_lock);
-			return;
+			goto fail;
 		}
 
 		rc = mhi_dev_notify_sm_event(event);
 		if (rc) {
 			pr_err("error sending SM event\n");
-			mutex_unlock(&mhi_ctx->mhi_lock);
-			return;
+			goto fail;
 		}
 	}
 
 	if (int_value & MHI_MMIO_CTRL_CRDB_STATUS_MSK) {
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_VERBOSE,
 			"processing cmd db interrupt with %d\n", int_value);
 		ring = &mhi->ring[MHI_RING_CMD_ID];
 		ring->state = RING_STATE_PENDING;
@@ -973,20 +1494,67 @@
 	/* get the specific channel interrupts */
 	mhi_dev_check_channel_interrupt(mhi);
 
+fail:
 	mutex_unlock(&mhi_ctx->mhi_lock);
-	ep_pcie_mask_irq_event(mhi->phandle,
+
+	if (mhi->config_iatu || mhi->mhi_int)
+		enable_irq(mhi->mhi_irq);
+	else
+		ep_pcie_mask_irq_event(mhi->phandle,
 				EP_PCIE_INT_EVT_MHI_A7, true);
 }
 
 void mhi_dev_notify_a7_event(struct mhi_dev *mhi)
 {
+
+	if (!atomic_read(&mhi->mhi_dev_wake)) {
+		pm_stay_awake(mhi->dev);
+		atomic_set(&mhi->mhi_dev_wake, 1);
+	}
+	mhi_log(MHI_MSG_VERBOSE, "acquiring mhi wakelock\n");
+
 	schedule_work(&mhi->chdb_ctrl_work);
-	mhi_log(MHI_MSG_ERROR, "mhi irq triggered\n");
+	mhi_log(MHI_MSG_VERBOSE, "mhi irq triggered\n");
 }
 EXPORT_SYMBOL(mhi_dev_notify_a7_event);
 
+static irqreturn_t mhi_dev_isr(int irq, void *dev_id)
+{
+	struct mhi_dev *mhi = dev_id;
+
+	disable_irq_nosync(mhi->mhi_irq);
+	schedule_work(&mhi->chdb_ctrl_work);
+	mhi_log(MHI_MSG_VERBOSE, "mhi irq triggered\n");
+
+	return IRQ_HANDLED;
+}
+
 int mhi_dev_config_outbound_iatu(struct mhi_dev *mhi)
 {
+	struct ep_pcie_iatu control, data;
+	int rc = 0;
+	struct ep_pcie_iatu entries[MHI_HOST_REGION_NUM];
+
+	data.start = mhi->data_base.device_pa;
+	data.end = mhi->data_base.device_pa + mhi->data_base.size - 1;
+	data.tgt_lower = HOST_ADDR_LSB(mhi->data_base.host_pa);
+	data.tgt_upper = HOST_ADDR_MSB(mhi->data_base.host_pa);
+
+	control.start = mhi->ctrl_base.device_pa;
+	control.end = mhi->ctrl_base.device_pa + mhi->ctrl_base.size - 1;
+	control.tgt_lower = HOST_ADDR_LSB(mhi->ctrl_base.host_pa);
+	control.tgt_upper = HOST_ADDR_MSB(mhi->ctrl_base.host_pa);
+
+	entries[0] = data;
+	entries[1] = control;
+
+	rc = ep_pcie_config_outbound_iatu(mhi_ctx->phandle, entries,
+					MHI_HOST_REGION_NUM);
+	if (rc) {
+		pr_err("error configure iATU\n");
+		return rc;
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL(mhi_dev_config_outbound_iatu);
@@ -996,6 +1564,7 @@
 	int rc = 0;
 	struct platform_device *pdev;
 	uint64_t addr1 = 0;
+	struct mhi_addr data_transfer;
 
 	pdev = mhi->pdev;
 
@@ -1014,6 +1583,37 @@
 					mhi->host_addr.data_limit_msb);
 	mhi->data_base.size = addr1 - mhi->data_base.host_pa;
 
+	if (mhi->config_iatu) {
+		if (mhi->ctrl_base.host_pa > mhi->data_base.host_pa) {
+			mhi->data_base.device_pa = mhi->device_local_pa_base;
+			mhi->ctrl_base.device_pa = mhi->device_local_pa_base +
+				mhi->ctrl_base.host_pa - mhi->data_base.host_pa;
+		} else {
+			mhi->ctrl_base.device_pa = mhi->device_local_pa_base;
+			mhi->data_base.device_pa = mhi->device_local_pa_base +
+				mhi->data_base.host_pa - mhi->ctrl_base.host_pa;
+		}
+
+		if (!mhi->use_ipa) {
+			mhi->ctrl_base.device_va =
+				(uintptr_t) devm_ioremap_nocache(&pdev->dev,
+				mhi->ctrl_base.device_pa,
+				mhi->ctrl_base.size);
+			if (!mhi->ctrl_base.device_va) {
+				pr_err("io remap failed for mhi address\n");
+				return -EINVAL;
+			}
+		}
+	}
+
+	if (mhi->config_iatu) {
+		rc = mhi_dev_config_outbound_iatu(mhi);
+		if (rc) {
+			pr_err("Configuring iATU failed\n");
+			return rc;
+		}
+	}
+
 	/* Get Channel, event and command context base pointer */
 	rc = mhi_dev_mmio_get_chc_base(mhi);
 	if (rc) {
@@ -1062,30 +1662,44 @@
 				GFP_KERNEL);
 	if (!mhi->ev_ctx_cache)
 		return -ENOMEM;
+	memset(mhi->ev_ctx_cache, 0, sizeof(struct mhi_dev_ev_ctx) *
+						mhi->cfg.event_rings);
 
 	mhi->ch_ctx_cache = dma_alloc_coherent(&pdev->dev,
 				sizeof(struct mhi_dev_ch_ctx) *
 				mhi->cfg.channels,
 				&mhi->ch_ctx_cache_dma_handle,
 				GFP_KERNEL);
-	if (!mhi_ctx->ch_ctx_cache)
+	if (!mhi->ch_ctx_cache)
 		return -ENOMEM;
+	memset(mhi->ch_ctx_cache, 0, sizeof(struct mhi_dev_ch_ctx) *
+						mhi->cfg.channels);
+
+	if (mhi->use_ipa) {
+		data_transfer.phy_addr = mhi->cmd_ctx_cache_dma_handle;
+		data_transfer.host_pa = mhi->cmd_ctx_shadow.host_pa;
+	}
+
+	data_transfer.size = mhi->cmd_ctx_shadow.size;
 
 	/* Cache the command and event context */
-	mhi_dev_read_from_host(&mhi->cmd_ctx_shadow,
-				mhi->cmd_ctx_cache_dma_handle,
-				mhi->cmd_ctx_shadow.size);
+	mhi_dev_read_from_host(mhi, &data_transfer);
 
-	mhi_dev_read_from_host(&mhi->ev_ctx_shadow,
-				mhi->ev_ctx_cache_dma_handle,
-				mhi->ev_ctx_shadow.size);
+	if (mhi->use_ipa) {
+		data_transfer.phy_addr = mhi->ev_ctx_cache_dma_handle;
+		data_transfer.host_pa = mhi->ev_ctx_shadow.host_pa;
+	}
 
-	mhi_log(MHI_MSG_ERROR,
+	data_transfer.size = mhi->ev_ctx_shadow.size;
+
+	mhi_dev_read_from_host(mhi, &data_transfer);
+
+	mhi_log(MHI_MSG_VERBOSE,
 			"cmd ring_base:0x%llx, rp:0x%llx, wp:0x%llx\n",
 					mhi->cmd_ctx_cache->rbase,
 					mhi->cmd_ctx_cache->rp,
 					mhi->cmd_ctx_cache->wp);
-	mhi_log(MHI_MSG_ERROR,
+	mhi_log(MHI_MSG_VERBOSE,
 			"ev ring_base:0x%llx, rp:0x%llx, wp:0x%llx\n",
 					mhi_ctx->ev_ctx_cache->rbase,
 					mhi->ev_ctx_cache->rp,
@@ -1104,7 +1718,7 @@
 int mhi_dev_suspend(struct mhi_dev *mhi)
 {
 	int ch_id = 0, rc = 0;
-	struct mhi_addr host_addr;
+	struct mhi_addr data_transfer;
 
 	mutex_lock(&mhi_ctx->mhi_write_test);
 	atomic_set(&mhi->is_suspended, 1);
@@ -1116,19 +1730,28 @@
 
 		mhi->ch_ctx_cache[ch_id].ch_state = MHI_DEV_CH_STATE_SUSPENDED;
 
-		host_addr.host_pa = mhi->ch_ctx_shadow.host_pa +
+		if (mhi->use_ipa) {
+			data_transfer.host_pa = mhi->ch_ctx_shadow.host_pa +
 				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+		} else {
+			data_transfer.device_va = mhi->ch_ctx_shadow.device_va +
+				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+			data_transfer.device_pa = mhi->ch_ctx_shadow.device_pa +
+				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+		}
+
+		data_transfer.size = sizeof(enum mhi_dev_ch_ctx_state);
+		data_transfer.virt_addr = &mhi->ch_ctx_cache[ch_id].ch_state;
 
 		/* update the channel state in the host */
-		mhi_dev_write_to_host(&host_addr,
-			&mhi->ch_ctx_cache[ch_id].ch_state,
-			sizeof(enum mhi_dev_ch_ctx_state), mhi);
+		mhi_dev_write_to_host(mhi, &data_transfer, NULL,
+				MHI_DEV_DMA_SYNC);
 
 	}
 
-	rc = ipa_dma_disable();
-	if (rc)
-		pr_err("Disable IPA failed\n");
+	atomic_set(&mhi->mhi_dev_wake, 0);
+	pm_relax(mhi->dev);
+	mhi_log(MHI_MSG_VERBOSE, "releasing mhi wakelock\n");
 
 	mutex_unlock(&mhi_ctx->mhi_write_test);
 
@@ -1139,13 +1762,7 @@
 int mhi_dev_resume(struct mhi_dev *mhi)
 {
 	int ch_id = 0, rc = 0;
-	struct mhi_addr host_addr;
-
-	rc = ipa_dma_enable();
-	if (rc) {
-		pr_err("IPA enable failed\n");
-		return rc;
-	}
+	struct mhi_addr data_transfer;
 
 	for (ch_id = 0; ch_id < mhi->cfg.channels; ch_id++) {
 		if (mhi->ch_ctx_cache[ch_id].ch_state !=
@@ -1153,14 +1770,24 @@
 			continue;
 
 		mhi->ch_ctx_cache[ch_id].ch_state = MHI_DEV_CH_STATE_RUNNING;
-		host_addr.host_pa = mhi->ch_ctx_shadow.host_pa +
+		if (mhi->use_ipa) {
+			data_transfer.host_pa = mhi->ch_ctx_shadow.host_pa +
 				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+		} else {
+			data_transfer.device_va = mhi->ch_ctx_shadow.device_va +
+				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+			data_transfer.device_pa = mhi->ch_ctx_shadow.device_pa +
+				sizeof(struct mhi_dev_ch_ctx) * ch_id;
+		}
+
+		data_transfer.size = sizeof(enum mhi_dev_ch_ctx_state);
+		data_transfer.virt_addr = &mhi->ch_ctx_cache[ch_id].ch_state;
 
 		/* update the channel state in the host */
-		mhi_dev_write_to_host(&host_addr,
-				&mhi->ch_ctx_cache[ch_id].ch_state,
-				sizeof(enum mhi_dev_ch_ctx_state), mhi);
+		mhi_dev_write_to_host(mhi, &data_transfer, NULL,
+				MHI_DEV_DMA_SYNC);
 	}
+	mhi_update_state_info(MHI_STATE_CONNECTED);
 
 	atomic_set(&mhi->is_suspended, 0);
 
@@ -1312,14 +1939,14 @@
 				mhi_dev_send_completion_event(ch,
 					ring->rd_offset, el->tre.len,
 					MHI_CMD_COMPL_CODE_EOB);
-				*chain = 1;
+			*chain = 1;
 		} else {
 			if (el->tre.ieot)
 				mhi_dev_send_completion_event(
 					ch, ring->rd_offset, el->tre.len,
 					MHI_CMD_COMPL_CODE_EOT);
-				td_done = 1;
-				*chain = 0;
+			td_done = 1;
+			*chain = 0;
 		}
 		mhi_dev_ring_inc_index(ring, ring->rd_offset);
 		ch->tre_bytes_left = 0;
@@ -1329,53 +1956,67 @@
 	return td_done;
 }
 
-int mhi_dev_read_channel(struct mhi_dev_client *handle_client,
-				void *buf, uint32_t buf_size, uint32_t *chain)
+int mhi_dev_read_channel(struct mhi_req *mreq)
 {
 	struct mhi_dev_channel *ch;
 	struct mhi_dev_ring *ring;
 	union mhi_dev_ring_element_type *el;
-	uint32_t ch_id;
 	size_t bytes_to_read, addr_offset;
 	uint64_t read_from_loc;
 	ssize_t bytes_read = 0;
 	uint32_t write_to_loc = 0;
-	size_t usr_buf_remaining = buf_size;
+	size_t usr_buf_remaining;
 	int td_done = 0, rc = 0;
+	struct mhi_dev_client *handle_client;
 
-	if (!handle_client) {
-		mhi_log(MHI_MSG_ERROR, "invalid client handle\n");
+	if (!mreq) {
+		mhi_log(MHI_MSG_ERROR, "invalid mhi request\n");
 		return -ENXIO;
 	}
 
+	if (mhi_ctx->ctrl_info != MHI_STATE_CONNECTED) {
+		pr_err("Channel not connected:%d\n", mhi_ctx->ctrl_info);
+		return -ENODEV;
+	}
+
+	if (!mreq->client) {
+		mhi_log(MHI_MSG_ERROR, "invalid mhi request\n");
+		return -ENXIO;
+	}
+	handle_client = mreq->client;
 	ch = handle_client->channel;
+	usr_buf_remaining = mreq->len;
 	ring = ch->ring;
-	ch_id = ch->ch_id;
-	*chain = 0;
+	mreq->chain = 0;
 
 	mutex_lock(&ch->ch_lock);
 
 	do {
 		el = &ring->ring_cache[ring->rd_offset];
+		mhi_log(MHI_MSG_VERBOSE, "evtptr : 0x%llx\n",
+						el->tre.data_buf_ptr);
+		mhi_log(MHI_MSG_VERBOSE, "evntlen : 0x%x, offset:%d\n",
+						el->tre.len, ring->rd_offset);
+
 		if (ch->tre_loc) {
 			bytes_to_read = min(usr_buf_remaining,
 						ch->tre_bytes_left);
-			*chain = 1;
-			mhi_log(MHI_MSG_ERROR,
+			mreq->chain = 1;
+			mhi_log(MHI_MSG_VERBOSE,
 				"remaining buffered data size %d\n",
 				(int) ch->tre_bytes_left);
 		} else {
 			if (ring->rd_offset == ring->wr_offset) {
-				mhi_log(MHI_MSG_ERROR,
+				mhi_log(MHI_MSG_VERBOSE,
 					"nothing to read, returning\n");
 				bytes_read = 0;
 				goto exit;
 			}
 
 			if (ch->state == MHI_DEV_CH_STOPPED) {
-				mhi_log(MHI_MSG_ERROR,
+				mhi_log(MHI_MSG_VERBOSE,
 					"channel (%d) already stopped\n",
-					ch_id);
+					mreq->chan);
 				bytes_read = -1;
 				goto exit;
 			}
@@ -1384,35 +2025,51 @@
 			ch->tre_size = el->tre.len;
 			ch->tre_bytes_left = ch->tre_size;
 
-			mhi_log(MHI_MSG_ERROR,
+			mhi_log(MHI_MSG_VERBOSE,
 			"user_buf_remaining %d, ch->tre_size %d\n",
 			usr_buf_remaining, ch->tre_size);
 			bytes_to_read = min(usr_buf_remaining, ch->tre_size);
 		}
 
+		bytes_read += bytes_to_read;
 		addr_offset = ch->tre_size - ch->tre_bytes_left;
 		read_from_loc = ch->tre_loc + addr_offset;
-		write_to_loc = (uint32_t) buf + (buf_size - usr_buf_remaining);
-
-		mhi_log(MHI_MSG_ERROR, "reading %d bytes from chan %d\n",
-				bytes_to_read, ch_id);
-
-		mhi_transfer_host_to_device((void *) write_to_loc,
-			read_from_loc, bytes_to_read, mhi_ctx);
-
-		bytes_read += bytes_to_read;
+		write_to_loc = (uint32_t) mreq->buf +
+			(mreq->len - usr_buf_remaining);
 		ch->tre_bytes_left -= bytes_to_read;
-		usr_buf_remaining -= bytes_to_read;
-		td_done = mhi_dev_check_tre_bytes_left(ch, ring, el, chain);
-	} while (usr_buf_remaining  && !td_done);
-
-	if (td_done && ch->state == MHI_DEV_CH_PENDING_STOP) {
-		ch->state = MHI_DEV_CH_STOPPED;
-		rc = mhi_dev_process_stop_cmd(ring, ch_id, mhi_ctx);
+		mreq->el = el;
+		mreq->actual_len = bytes_read;
+		mreq->rd_offset = ring->rd_offset;
+		mhi_log(MHI_MSG_VERBOSE, "reading %d bytes from chan %d\n",
+				bytes_to_read, mreq->chan);
+		rc = mhi_transfer_host_to_device((void *) write_to_loc,
+				read_from_loc, bytes_to_read, mhi_ctx, mreq);
 		if (rc) {
 			mhi_log(MHI_MSG_ERROR,
-				"Error while stopping channel (%d)\n", ch_id);
-			bytes_read = -1;
+					"Error while reading chan (%d) rc %d\n",
+					mreq->chan, rc);
+			mutex_unlock(&ch->ch_lock);
+			return rc;
+		}
+		usr_buf_remaining -= bytes_to_read;
+
+		if (mreq->mode == IPA_DMA_ASYNC) {
+			ch->tre_bytes_left = 0;
+			ch->tre_loc = 0;
+			goto exit;
+		} else {
+			td_done = mhi_dev_check_tre_bytes_left(ch, ring,
+					el, &mreq->chain);
+		}
+	} while (usr_buf_remaining  && !td_done);
+	if (td_done && ch->state == MHI_DEV_CH_PENDING_STOP) {
+		ch->state = MHI_DEV_CH_STOPPED;
+		rc = mhi_dev_process_stop_cmd(ring, mreq->chan, mhi_ctx);
+		if (rc) {
+			mhi_log(MHI_MSG_ERROR,
+					"Error while stopping channel (%d)\n",
+					mreq->chan);
+			bytes_read = -EIO;
 		}
 	}
 exit:
@@ -1441,32 +2098,33 @@
 	}
 }
 
-int mhi_dev_write_channel(struct mhi_dev_client *handle_client,
-						void *buf, size_t buf_size)
+int mhi_dev_write_channel(struct mhi_req *wreq)
 {
 	struct mhi_dev_channel *ch;
 	struct mhi_dev_ring *ring;
+	struct mhi_dev_client *handle_client;
 	union mhi_dev_ring_element_type *el;
 	enum mhi_dev_cmd_completion_code code = MHI_CMD_COMPL_CODE_INVALID;
 	int rc = 0;
-	uint64_t ch_id, skip_tres = 0, write_to_loc;
+	uint64_t skip_tres = 0, write_to_loc;
 	uint32_t read_from_loc;
-	size_t usr_buf_remaining = buf_size;
+	size_t usr_buf_remaining;
 	size_t usr_buf_offset = 0;
 	size_t bytes_to_write = 0;
 	size_t bytes_written = 0;
 	uint32_t tre_len = 0, suspend_wait_timeout = 0;
 
-	if (!handle_client) {
-		pr_err("%s: invalid client handle\n", __func__);
+	if (!wreq || !wreq->client || !wreq->buf) {
+		pr_err("%s: invalid parameters\n", __func__);
 		return -ENXIO;
 	}
 
-	if (!buf) {
-		pr_err("%s: invalid buffer to write data\n", __func__);
-		return -ENXIO;
+	if (mhi_ctx->ctrl_info != MHI_STATE_CONNECTED) {
+		pr_err("Channel not connected:%d\n", mhi_ctx->ctrl_info);
+		return -ENODEV;
 	}
 
+	usr_buf_remaining =  wreq->len;
 	mutex_lock(&mhi_ctx->mhi_write_test);
 
 	if (atomic_read(&mhi_ctx->is_suspended)) {
@@ -1482,31 +2140,29 @@
 		}
 	}
 
-	atomic_inc(&mhi_ctx->write_active);
 	while (atomic_read(&mhi_ctx->is_suspended) &&
-			suspend_wait_timeout < MHI_SUSPEND_WAIT_TIMEOUT) {
+			suspend_wait_timeout < MHI_SUSPEND_TIMEOUT) {
 		/* wait for the suspend to finish */
-		usleep_range(MHI_SUSPEND_WAIT_MIN, MHI_SUSPEND_WAIT_MAX);
+		msleep(MHI_SUSPEND_MIN);
 		suspend_wait_timeout++;
 	}
-
+	handle_client = wreq->client;
 	ch = handle_client->channel;
 	ch->wr_request_active = true;
 
 	ring = ch->ring;
-	ch_id = ch->ch_id;
 
 	mutex_lock(&ch->ch_lock);
 
 	if (ch->state == MHI_DEV_CH_STOPPED) {
 		mhi_log(MHI_MSG_ERROR,
-			"channel (%lld) already stopped\n", ch_id);
+			"channel %d already stopped\n", wreq->chan);
 		bytes_written = -1;
 		goto exit;
 	}
 
 	if (ch->state == MHI_DEV_CH_PENDING_STOP) {
-		if (mhi_dev_process_stop_cmd(ring, ch_id, mhi_ctx) < 0)
+		if (mhi_dev_process_stop_cmd(ring, wreq->chan, mhi_ctx) < 0)
 			bytes_written = -1;
 		goto exit;
 	}
@@ -1516,20 +2172,38 @@
 
 	do {
 		if (ring->rd_offset == ring->wr_offset) {
+			mhi_log(MHI_MSG_ERROR,
+					"%s():rd & wr offsets are equal\n",
+					__func__);
 			mhi_log(MHI_MSG_INFO, "No TREs available\n");
 			break;
 		}
 
 		el = &ring->ring_cache[ring->rd_offset];
 		tre_len = el->tre.len;
+		if (wreq->len > tre_len) {
+			pr_err("%s(): rlen = %d, tlen = %d: client buf > tre len\n",
+					__func__, wreq->len, tre_len);
+			bytes_written = -ENOMEM;
+			goto exit;
+		}
 
 		bytes_to_write = min(usr_buf_remaining, tre_len);
-		usr_buf_offset = buf_size - bytes_to_write;
-		read_from_loc = (uint32_t) buf + usr_buf_offset;
+		usr_buf_offset = wreq->len - bytes_to_write;
+		read_from_loc = (uint32_t) wreq->buf + usr_buf_offset;
 		write_to_loc = el->tre.data_buf_ptr;
-		mhi_transfer_device_to_host(write_to_loc,
+		wreq->rd_offset = ring->rd_offset;
+		wreq->el = el;
+		rc = mhi_transfer_device_to_host(write_to_loc,
 						(void *) read_from_loc,
-						bytes_to_write, mhi_ctx);
+						bytes_to_write,
+						mhi_ctx, wreq);
+		if (rc) {
+			mhi_log(MHI_MSG_ERROR,
+					"Error while writing chan (%d) rc %d\n",
+					wreq->chan, rc);
+			goto exit;
+		}
 		bytes_written += bytes_to_write;
 		usr_buf_remaining -= bytes_to_write;
 
@@ -1543,33 +2217,34 @@
 				skip_tres = 1;
 			code = MHI_CMD_COMPL_CODE_EOT;
 		}
-
-		if (mhi_dev_send_completion_event(ch,
-				ring->rd_offset, bytes_to_write, code) < 0) {
-			mhi_log(MHI_MSG_ERROR,
-				"error sending completion event ch_id:%lld\n",
-				ch_id);
+		if (wreq->mode == IPA_DMA_SYNC) {
+			rc = mhi_dev_send_completion_event(ch,
+					ring->rd_offset, bytes_to_write, code);
+			if (rc)
+				mhi_log(MHI_MSG_VERBOSE,
+						"err in snding cmpl evt ch:%d\n",
+						wreq->chan);
+			 mhi_dev_ring_inc_index(ring, ring->rd_offset);
 		}
 
 		if (ch->state == MHI_DEV_CH_PENDING_STOP)
 			break;
 
-		mhi_dev_ring_inc_index(ring, ring->rd_offset);
 	} while (!skip_tres && usr_buf_remaining);
 
 	if (skip_tres)
 		skip_to_next_td(ch);
 
 	if (ch->state == MHI_DEV_CH_PENDING_STOP) {
-		rc = mhi_dev_process_stop_cmd(ring, ch_id, mhi_ctx);
+		rc = mhi_dev_process_stop_cmd(ring, wreq->chan, mhi_ctx);
 		if (rc) {
 			mhi_log(MHI_MSG_ERROR,
-				"channel (%lld) stop failed\n", ch_id);
+				"channel %d stop failed\n", wreq->chan);
 		}
 	}
 exit:
+	ch->wr_request_active = false;
 	mutex_unlock(&ch->ch_lock);
-	atomic_dec(&mhi_ctx->write_active);
 	mutex_unlock(&mhi_ctx->mhi_write_test);
 	return bytes_written;
 }
@@ -1581,21 +2256,22 @@
 	struct ep_pcie_msi_config msi_cfg;
 	struct mhi_dev *mhi = container_of(work,
 				struct mhi_dev, ring_init_cb_work);
-
+	bool mhi_reset;
 	enum mhi_dev_state state;
-	uint32_t max_cnt = 0;
+	uint32_t max_cnt = 0, bhi_intvec = 0;
 
+	if (mhi->use_ipa) {
+		rc = ipa_dma_init();
+		if (rc) {
+			pr_err("ipa dma init failed\n");
+			return;
+		}
 
-	rc = ipa_dma_init();
-	if (rc) {
-		pr_err("ipa dma init failed\n");
-		return;
-	}
-
-	rc = ipa_dma_enable();
-	if (rc) {
-		pr_err("ipa enable failed\n");
-		return;
+		rc = ipa_dma_enable();
+		if (rc) {
+			pr_err("ipa enable failed\n");
+			return;
+		}
 	}
 
 	rc = mhi_dev_ring_init(mhi);
@@ -1604,34 +2280,39 @@
 		return;
 	}
 
-	/* Invoke MHI SM when device is in RESET state */
-	mhi_dev_sm_init(mhi);
-
-	/* set the env before setting the ready bit */
-	rc = mhi_dev_mmio_set_env(mhi, MHI_ENV_VALUE);
-	if (rc) {
-		pr_err("%s: env setting failed\n", __func__);
-		return;
-	}
-	mhi_uci_init();
-
-	/* All set...let's notify the host */
-	mhi_dev_sm_set_ready();
-
-	rc = ep_pcie_get_msi_config(mhi->phandle, &msi_cfg);
+	/*Enable MHI dev network stack Interface*/
+	rc = mhi_dev_net_interface_init();
 	if (rc)
-		pr_warn("MHI: error geting msi configs\n");
+		pr_err("%s Failed to initialize mhi_dev_net iface\n", __func__);
 
-	rc = mhi_dev_mmio_get_mhi_state(mhi, &state);
+	rc = mhi_dev_mmio_read(mhi, BHI_INTVEC, &bhi_intvec);
+	if (rc)
+		return;
+
+	if (bhi_intvec != 0xffffffff) {
+		/* Indicate the host that the device is ready */
+		rc = ep_pcie_get_msi_config(mhi->phandle, &msi_cfg);
+		if (!rc) {
+			rc = ep_pcie_trigger_msi(mhi_ctx->phandle, bhi_intvec);
+			if (rc) {
+				pr_err("%s: error sending msi\n", __func__);
+				return;
+			}
+		} else {
+			pr_err("MHI: error geting msi configs\n");
+		}
+	}
+
+	rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
 	if (rc) {
 		pr_err("%s: get mhi state failed\n", __func__);
 		return;
 	}
 
-	while (state != MHI_DEV_M0_STATE && max_cnt < MHI_DEV_M0_MAX_CNT) {
+	while (state != MHI_DEV_M0_STATE && max_cnt < MHI_SUSPEND_TIMEOUT) {
 		/* Wait for Host to set the M0 state */
-		usleep_range(MHI_M0_WAIT_MIN_USLEEP, MHI_M0_WAIT_MAX_USLEEP);
-		rc = mhi_dev_mmio_get_mhi_state(mhi, &state);
+		msleep(MHI_SUSPEND_MIN);
+		rc = mhi_dev_mmio_get_mhi_state(mhi, &state, &mhi_reset);
 		if (rc) {
 			pr_err("%s: get mhi state failed\n", __func__);
 			return;
@@ -1663,6 +2344,11 @@
 		pr_err("error during hwc_init\n");
 		return;
 	}
+
+	if (mhi_ctx->config_iatu || mhi_ctx->mhi_int)
+		enable_irq(mhi_ctx->mhi_irq);
+
+	mhi_update_state_info(MHI_STATE_CONNECTED);
 }
 
 static void mhi_ring_init_cb(void *data)
@@ -1677,6 +2363,78 @@
 	queue_work(mhi->ring_init_wq, &mhi->ring_init_cb_work);
 }
 
+int mhi_register_state_cb(void (*mhi_state_cb)
+				(struct mhi_dev_client_cb_data *cb_data),
+				void *data, enum mhi_client_channel channel)
+{
+	struct mhi_dev_ready_cb_info *cb_info = NULL;
+
+	if (!mhi_ctx) {
+		pr_err("MHI device not ready\n");
+		return -ENXIO;
+	}
+
+	if (channel > MHI_MAX_CHANNELS) {
+		pr_err("Invalid channel :%d\n", channel);
+		return -EINVAL;
+	}
+
+	mutex_lock(&mhi_ctx->mhi_lock);
+	cb_info = kmalloc(sizeof(struct mhi_dev_ready_cb_info), GFP_KERNEL);
+	if (!cb_info) {
+		mutex_unlock(&mhi_ctx->mhi_lock);
+		return -ENOMEM;
+	}
+
+	cb_info->cb = mhi_state_cb;
+	cb_info->cb_data.user_data = data;
+	cb_info->cb_data.channel = channel;
+
+	list_add_tail(&cb_info->list, &mhi_ctx->client_cb_list);
+
+	/**
+	 * If channel is open during registration, no callback is issued.
+	 * Instead return -EEXIST to notify the client. Clients request
+	 * is added to the list to notify future state change notification.
+	 */
+	if (mhi_ctx->ch[channel].state == MHI_DEV_CH_STARTED) {
+		mutex_unlock(&mhi_ctx->mhi_lock);
+		return -EEXIST;
+	}
+
+	mutex_unlock(&mhi_ctx->mhi_lock);
+
+	return 0;
+}
+EXPORT_SYMBOL(mhi_register_state_cb);
+
+static void mhi_update_state_info(uint32_t info)
+{
+	struct mhi_dev_client_cb_reason reason;
+
+	mhi_ctx->ctrl_info = info;
+
+	if (info == MHI_STATE_CONNECTED)
+		return;
+
+	reason.reason = MHI_DEV_CTRL_UPDATE;
+	uci_ctrl_update(&reason);
+}
+
+int mhi_ctrl_state_info(uint32_t *info)
+{
+	if (!info) {
+		pr_err("Invalid info\n");
+		return -EINVAL;
+	}
+
+	*info = mhi_ctx->ctrl_info;
+	mhi_log(MHI_MSG_VERBOSE, "ctrl:%d", mhi_ctx->ctrl_info);
+
+	return 0;
+}
+EXPORT_SYMBOL(mhi_ctrl_state_info);
+
 static int get_device_tree_data(struct platform_device *pdev)
 {
 	struct mhi_dev *mhi;
@@ -1725,13 +2483,11 @@
 	}
 
 	mhi->ipa_uc_mbox_erdb = res_mem->start;
-
 	mhi_ctx = mhi;
 
 	rc = of_property_read_u32((&pdev->dev)->of_node,
 				"qcom,mhi-ifc-id",
 				&mhi_ctx->ifc_id);
-
 	if (rc) {
 		pr_err("qcom,mhi-ifc-id does not exist.\n");
 		return rc;
@@ -1753,22 +2509,90 @@
 		return rc;
 	}
 
+	mhi_ctx->use_ipa = of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,use-ipa-software-channel");
+
+	mhi_ctx->config_iatu = of_property_read_bool((&pdev->dev)->of_node,
+				"qcom,mhi-config-iatu");
+
+	if (mhi_ctx->config_iatu) {
+		rc = of_property_read_u32((&pdev->dev)->of_node,
+				"qcom,mhi-local-pa-base",
+				&mhi_ctx->device_local_pa_base);
+		if (rc) {
+			pr_err("qcom,mhi-local-pa-base does not exist\n");
+			return rc;
+		}
+	}
+
+	mhi_ctx->mhi_int = of_property_read_bool((&pdev->dev)->of_node,
+					"qcom,mhi-interrupt");
+
+	if (mhi->config_iatu || mhi_ctx->mhi_int) {
+		mhi->mhi_irq = platform_get_irq_byname(pdev, "mhi-device-inta");
+		if (mhi->mhi_irq < 0) {
+			pr_err("Invalid MHI device interrupt\n");
+			rc = mhi->mhi_irq;
+			return rc;
+		}
+	}
+
+	device_init_wakeup(mhi->dev, true);
+	/* MHI device will be woken up from PCIe event */
+	device_set_wakeup_capable(mhi->dev, false);
+	/* Hold a wakelock until completion of M0 */
+	pm_stay_awake(mhi->dev);
+	atomic_set(&mhi->mhi_dev_wake, 1);
+
+	mhi_log(MHI_MSG_VERBOSE, "acquiring wakelock\n");
+
 	return 0;
 }
 
+static int mhi_deinit(struct mhi_dev *mhi)
+{
+	int rc = 0, i = 0, ring_id = 0;
+	struct mhi_dev_ring *ring;
+	struct platform_device *pdev = mhi->pdev;
+
+	ring_id = mhi->cfg.channels + mhi->cfg.event_rings + 1;
+
+	for (i = 0; i < ring_id; i++) {
+		ring = &mhi->ring[i];
+		if (ring->state == RING_STATE_UINT)
+			continue;
+
+		dma_free_coherent(mhi->dev, ring->ring_size *
+			sizeof(union mhi_dev_ring_element_type),
+			ring->ring_cache,
+			ring->ring_cache_dma_handle);
+	}
+
+	for (i = 0; i < mhi->cfg.channels; i++)
+		mutex_destroy(&mhi->ch[i].ch_lock);
+
+	devm_kfree(&pdev->dev, mhi->mmio_backup);
+	devm_kfree(&pdev->dev, mhi->ch);
+	devm_kfree(&pdev->dev, mhi->ring);
+
+	mhi_dev_sm_exit(mhi);
+
+	mhi->mmio_initialized = false;
+
+	return rc;
+}
+
 static int mhi_init(struct mhi_dev *mhi)
 {
 	int rc = 0, i = 0;
 	struct platform_device *pdev = mhi->pdev;
 
-
 	rc = mhi_dev_mmio_init(mhi);
 	if (rc) {
 		pr_err("Failed to update the MMIO init\n");
 		return rc;
 	}
 
-
 	mhi->ring = devm_kzalloc(&pdev->dev,
 			(sizeof(struct mhi_dev_ring) *
 			(mhi->cfg.channels + mhi->cfg.event_rings + 1)),
@@ -1782,46 +2606,148 @@
 	if (!mhi->ch)
 		return -ENOMEM;
 
-	for (i = 0; i < mhi->cfg.channels; i++)
-		mutex_init(&mhi->ch[i].ch_lock);
 
-	mhi->mmio_backup = devm_kzalloc(&pdev->dev, MHI_DEV_MMIO_RANGE,
-								GFP_KERNEL);
+	for (i = 0; i < mhi->cfg.channels; i++) {
+		mutex_init(&mhi->ch[i].ch_lock);
+		if (i == MHI_CLIENT_IP_SW_4_OUT || i == MHI_CLIENT_IP_SW_4_IN) {
+			int nreq = 0;
+
+			INIT_LIST_HEAD(&mhi->ch[i].event_req_buffers);
+			while (nreq < MHI_MAX_EVT_REQ) {
+				struct event_req *ereq;
+				/* Pre allocate event requests */
+				ereq = kzalloc(sizeof(struct event_req),
+						GFP_KERNEL);
+				if (!ereq)
+					return -ENOMEM;
+
+				/* pre allocate buffers to queue
+				 * transfer completion events
+				 */
+				ereq->tr_events = kzalloc(RING_ELEMENT_TYPE_SZ*
+						MAX_TR_EVENTS, GFP_KERNEL);
+				if (!ereq->tr_events) {
+					kfree(ereq);
+					return -ENOMEM;
+				}
+				list_add_tail(&ereq->list,
+						&mhi->ch[i].event_req_buffers);
+				nreq++;
+			}
+			mhi->ch[i].curr_ereq =
+				container_of(mhi->ch[i].event_req_buffers.next,
+						struct event_req, list);
+			list_del_init(&mhi->ch[i].curr_ereq->list);
+		}
+	}
+
+	spin_lock_init(&mhi->lock);
+	mhi->mmio_backup = devm_kzalloc(&pdev->dev,
+			MHI_DEV_MMIO_RANGE, GFP_KERNEL);
 	if (!mhi->mmio_backup)
 		return -ENOMEM;
 
-	mhi_ipc_log = ipc_log_context_create(MHI_IPC_LOG_PAGES, "mhi", 0);
-	if (mhi_ipc_log == NULL) {
-		dev_err(&pdev->dev,
-				"Failed to create IPC logging context\n");
-	}
-
 	return 0;
 }
 
-static int mhi_dev_probe(struct platform_device *pdev)
+static int mhi_dev_resume_mmio_mhi_reinit(struct mhi_dev *mhi_ctx)
 {
 	int rc = 0;
 
-	if (pdev->dev.of_node) {
-		rc = get_device_tree_data(pdev);
-		if (rc) {
-			pr_err("Error reading MHI Dev DT\n");
-			return rc;
+	mutex_lock(&mhi_ctx->mhi_lock);
+	if (atomic_read(&mhi_ctx->re_init_done)) {
+		mhi_log(MHI_MSG_INFO, "Re_init done, return\n");
+		mutex_unlock(&mhi_ctx->mhi_lock);
+		return 0;
+	}
+
+	rc = mhi_init(mhi_ctx);
+	if (rc) {
+		pr_err("Error initializing MHI MMIO with %d\n", rc);
+		goto fail;
+	}
+
+	mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT |
+		EP_PCIE_EVENT_PM_D3_COLD |
+		EP_PCIE_EVENT_PM_D0 |
+		EP_PCIE_EVENT_PM_RST_DEAST |
+		EP_PCIE_EVENT_MHI_A7 |
+		EP_PCIE_EVENT_LINKDOWN;
+	mhi_ctx->event_reg.user = mhi_ctx;
+	mhi_ctx->event_reg.mode = EP_PCIE_TRIGGER_CALLBACK;
+	mhi_ctx->event_reg.callback = mhi_dev_sm_pcie_handler;
+
+	rc = ep_pcie_register_event(mhi_ctx->phandle, &mhi_ctx->event_reg);
+	if (rc) {
+		pr_err("Failed to register for events from PCIe\n");
+		goto fail;
+	}
+
+	rc = ipa_register_ipa_ready_cb(mhi_ring_init_cb, mhi_ctx);
+	if (rc < 0) {
+		if (rc == -EEXIST) {
+			mhi_ring_init_cb(mhi_ctx);
+		} else {
+			pr_err("Error calling IPA cb with %d\n", rc);
+			goto fail;
 		}
 	}
 
-	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
-	if (!mhi_ctx->phandle) {
-		pr_err("PCIe driver is not ready yet.\n");
-		return -EPROBE_DEFER;
+	/* Invoke MHI SM when device is in RESET state */
+	rc = mhi_dev_sm_init(mhi_ctx);
+	if (rc) {
+		pr_err("%s: Error during SM init\n", __func__);
+		goto fail;
 	}
 
-	if (ep_pcie_get_linkstatus(mhi_ctx->phandle) != EP_PCIE_LINK_ENABLED) {
-		pr_err("PCIe link is not ready to use.\n");
-		return -EPROBE_DEFER;
+	/* set the env before setting the ready bit */
+	rc = mhi_dev_mmio_set_env(mhi_ctx, MHI_ENV_VALUE);
+	if (rc) {
+		pr_err("%s: env setting failed\n", __func__);
+		goto fail;
 	}
 
+	/* All set, notify the host */
+	rc = mhi_dev_sm_set_ready();
+	if (rc) {
+		pr_err("%s: unable to set ready bit\n", __func__);
+		goto fail;
+	}
+
+	atomic_set(&mhi_ctx->is_suspended, 0);
+fail:
+	atomic_set(&mhi_ctx->re_init_done, 1);
+	mutex_unlock(&mhi_ctx->mhi_lock);
+	return rc;
+}
+
+static void mhi_dev_reinit(struct work_struct *work)
+{
+	struct mhi_dev *mhi_ctx = container_of(work,
+				struct mhi_dev, re_init);
+	enum ep_pcie_link_status link_state;
+	int rc = 0;
+
+	link_state = ep_pcie_get_linkstatus(mhi_ctx->phandle);
+	if (link_state == EP_PCIE_LINK_ENABLED) {
+		/* PCIe link is up with BME set */
+		rc = mhi_dev_resume_mmio_mhi_reinit(mhi_ctx);
+		if (rc) {
+			pr_err("Failed to register for events from PCIe\n");
+			return;
+		}
+	}
+
+	mhi_log(MHI_MSG_VERBOSE, "Wait for PCIe linkup\n");
+}
+
+static int mhi_dev_resume_mmio_mhi_init(struct mhi_dev *mhi_ctx)
+{
+	struct platform_device *pdev;
+	int rc = 0;
+
+	pdev = mhi_ctx->pdev;
+
 	INIT_WORK(&mhi_ctx->chdb_ctrl_work, mhi_dev_scheduler);
 
 	mhi_ctx->pending_ring_wq = alloc_workqueue("mhi_pending_wq",
@@ -1835,6 +2761,8 @@
 
 	INIT_WORK(&mhi_ctx->ring_init_cb_work, mhi_dev_enable);
 
+	INIT_WORK(&mhi_ctx->re_init, mhi_dev_reinit);
+
 	mhi_ctx->ring_init_wq = alloc_workqueue("mhi_ring_init_cb_wq",
 							WQ_HIGHPRI, 0);
 	if (!mhi_ctx->ring_init_wq) {
@@ -1844,6 +2772,7 @@
 
 	INIT_LIST_HEAD(&mhi_ctx->event_ring_list);
 	INIT_LIST_HEAD(&mhi_ctx->process_ring_list);
+	INIT_LIST_HEAD(&mhi_ctx->client_cb_list);
 	mutex_init(&mhi_ctx->mhi_lock);
 	mutex_init(&mhi_ctx->mhi_event_lock);
 	mutex_init(&mhi_ctx->mhi_write_test);
@@ -1878,6 +2807,12 @@
 		return rc;
 	}
 
+	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
+	if (!mhi_ctx->phandle) {
+		pr_err("PCIe driver get handle failed.\n");
+		return -EINVAL;
+	}
+
 	mhi_ctx->event_reg.events = EP_PCIE_EVENT_PM_D3_HOT |
 		EP_PCIE_EVENT_PM_D3_COLD |
 		EP_PCIE_EVENT_PM_D0 |
@@ -1906,6 +2841,125 @@
 		}
 	}
 
+	/* Invoke MHI SM when device is in RESET state */
+	rc = mhi_dev_sm_init(mhi_ctx);
+	if (rc) {
+		pr_err("%s: Error during SM init\n", __func__);
+		return rc;
+	}
+
+	/* set the env before setting the ready bit */
+	rc = mhi_dev_mmio_set_env(mhi_ctx, MHI_ENV_VALUE);
+	if (rc) {
+		pr_err("%s: env setting failed\n", __func__);
+		return rc;
+	}
+
+	/* All set, notify the host */
+	mhi_dev_sm_set_ready();
+
+	if (mhi_ctx->config_iatu || mhi_ctx->mhi_int) {
+		rc = devm_request_irq(&pdev->dev, mhi_ctx->mhi_irq, mhi_dev_isr,
+			IRQF_TRIGGER_HIGH, "mhi_isr", mhi_ctx);
+		if (rc) {
+			dev_err(&pdev->dev, "request mhi irq failed %d\n", rc);
+			return -EINVAL;
+		}
+
+		disable_irq(mhi_ctx->mhi_irq);
+	}
+
+	return 0;
+}
+
+static void mhi_dev_resume_init_with_link_up(struct ep_pcie_notify *notify)
+{
+	if (!notify || !notify->user) {
+		pr_err("Null argument for notify\n");
+		return;
+	}
+
+	mhi_ctx = notify->user;
+	mhi_dev_pcie_notify_event = notify->options;
+	mhi_log(MHI_MSG_INFO,
+			"PCIe event=0x%x\n", notify->options);
+	queue_work(mhi_ctx->pcie_event_wq, &mhi_ctx->pcie_event);
+}
+
+static void mhi_dev_pcie_handle_event(struct work_struct *work)
+{
+	struct mhi_dev *mhi_ctx = container_of(work, struct mhi_dev,
+								pcie_event);
+	int rc = 0;
+
+	if (mhi_dev_pcie_notify_event == MHI_INIT) {
+		rc = mhi_dev_resume_mmio_mhi_init(mhi_ctx);
+		if (rc) {
+			pr_err("Error during MHI device initialization\n");
+			return;
+		}
+	} else if (mhi_dev_pcie_notify_event == MHI_REINIT) {
+		rc = mhi_dev_resume_mmio_mhi_reinit(mhi_ctx);
+		if (rc) {
+			pr_err("Error during MHI device re-initialization\n");
+			return;
+		}
+	}
+}
+
+static int mhi_dev_probe(struct platform_device *pdev)
+{
+	int rc = 0;
+
+	if (pdev->dev.of_node) {
+		rc = get_device_tree_data(pdev);
+		if (rc) {
+			pr_err("Error reading MHI Dev DT\n");
+			return rc;
+		}
+		mhi_ipc_log = ipc_log_context_create(MHI_IPC_LOG_PAGES,
+								"mhi", 0);
+		if (mhi_ipc_log == NULL) {
+			dev_err(&pdev->dev,
+				"Failed to create IPC logging context\n");
+		}
+		mhi_uci_init();
+		mhi_update_state_info(MHI_STATE_CONFIGURED);
+	}
+
+	INIT_WORK(&mhi_ctx->pcie_event, mhi_dev_pcie_handle_event);
+	mhi_ctx->pcie_event_wq = alloc_workqueue("mhi_dev_pcie_event_wq",
+							WQ_HIGHPRI, 0);
+	if (!mhi_ctx->pcie_event_wq) {
+		pr_err("no memory\n");
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	mhi_ctx->phandle = ep_pcie_get_phandle(mhi_ctx->ifc_id);
+	if (mhi_ctx->phandle) {
+		/* PCIe link is already up */
+		rc = mhi_dev_resume_mmio_mhi_init(mhi_ctx);
+		if (rc) {
+			pr_err("Error during MHI device initialization\n");
+			return rc;
+		}
+	} else {
+		pr_debug("Register a PCIe callback\n");
+		mhi_ctx->event_reg.events = EP_PCIE_EVENT_LINKUP;
+		mhi_ctx->event_reg.user = mhi_ctx;
+		mhi_ctx->event_reg.mode = EP_PCIE_TRIGGER_CALLBACK;
+		mhi_ctx->event_reg.callback = mhi_dev_resume_init_with_link_up;
+		mhi_ctx->event_reg.options = MHI_INIT;
+
+		rc = ep_pcie_register_event(mhi_ctx->phandle,
+							&mhi_ctx->event_reg);
+		if (rc) {
+			pr_err("Failed to register for events from PCIe\n");
+			return rc;
+		}
+	}
+
 	return 0;
 }
 
diff --git a/drivers/platform/msm/mhi_dev/mhi.h b/drivers/platform/msm/mhi_dev/mhi.h
index 1a73d92..38e52e2 100644
--- a/drivers/platform/msm/mhi_dev/mhi.h
+++ b/drivers/platform/msm/mhi_dev/mhi.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -274,7 +274,15 @@
 #define HW_CHANNEL_END			107
 #define MHI_ENV_VALUE			2
 #define MHI_MASK_ROWS_CH_EV_DB		4
-#define TRB_MAX_DATA_SIZE		4096
+#define TRB_MAX_DATA_SIZE		8192
+#define MHI_CTRL_STATE			25
+#define IPA_DMA_SYNC                    1
+#define IPA_DMA_ASYNC                   0
+
+/*maximum trasnfer completion events buffer*/
+#define MAX_TR_EVENTS			50
+/*maximum event requests */
+#define MHI_MAX_EVT_REQ			50
 
 /* Possible ring element types */
 union mhi_dev_ring_element_type {
@@ -324,7 +332,10 @@
 	uint64_t	host_pa;
 	uintptr_t	device_pa;
 	uintptr_t	device_va;
-	uint32_t	size;
+	size_t		size;
+	dma_addr_t	phy_addr;
+	void		*virt_addr;
+	bool		use_ipa_dma;
 };
 
 struct mhi_interrupt_state {
@@ -349,6 +360,23 @@
 	MHI_DEV_POLL,
 };
 
+enum mhi_ctrl_info {
+	MHI_STATE_CONFIGURED = 0,
+	MHI_STATE_CONNECTED = 1,
+	MHI_STATE_DISCONNECTED = 2,
+	MHI_STATE_INVAL,
+};
+
+enum mhi_dev_tr_compl_evt_type {
+	SEND_EVENT_BUFFER,
+	SEND_EVENT_RD_OFFSET,
+};
+
+enum mhi_dev_transfer_type {
+	MHI_DEV_DMA_SYNC,
+	MHI_DEV_DMA_ASYNC,
+};
+
 struct mhi_dev_channel;
 
 struct mhi_dev_ring {
@@ -394,6 +422,7 @@
 
 enum cb_reason {
 	MHI_DEV_TRE_AVAILABLE = 0,
+	MHI_DEV_CTRL_UPDATE,
 };
 
 struct mhi_dev_client_cb_reason {
@@ -423,14 +452,30 @@
 	uint32_t			nr_iov;
 };
 
+struct ring_cache_req {
+	struct completion	*done;
+	void			*context;
+};
+
+struct event_req {
+	union mhi_dev_ring_element_type *tr_events;
+	u32			num_events;
+	dma_addr_t		dma;
+	u32			dma_len;
+	dma_addr_t		event_rd_dma;
+	void			*context;
+	enum mhi_dev_tr_compl_evt_type event_type;
+	u32			event_ring;
+	void			(*client_cb)(void *req);
+	struct list_head	list;
+};
+
 struct mhi_dev_channel {
 	struct list_head		list;
 	struct list_head		clients;
 	/* synchronization for changing channel state,
 	 * adding/removing clients, mhi_dev callbacks, etc
 	 */
-	spinlock_t			lock;
-
 	struct mhi_dev_ring		*ring;
 
 	enum mhi_dev_channel_state	state;
@@ -440,6 +485,9 @@
 	/* client which the current inbound/outbound message is for */
 	struct mhi_dev_client		*active_client;
 
+	struct list_head		event_req_buffers;
+	struct event_req		*curr_ereq;
+
 	/* current TRE being processed */
 	uint64_t			tre_loc;
 	/* current TRE size */
@@ -466,6 +514,7 @@
 	struct mhi_config		cfg;
 	bool				mmio_initialized;
 
+	spinlock_t			lock;
 	/* Host control base information */
 	struct mhi_host_addr		host_addr;
 	struct mhi_addr			ctrl_base;
@@ -481,6 +530,7 @@
 	struct mhi_dev_ch_ctx		*cmd_ctx_cache;
 	dma_addr_t			cmd_ctx_cache_dma_handle;
 	struct mhi_dev_ring		*ring;
+	int				mhi_irq;
 	struct mhi_dev_channel		*ch;
 
 	int				ctrl_int;
@@ -491,6 +541,7 @@
 
 	/* Scheduler work */
 	struct work_struct		chdb_ctrl_work;
+
 	struct mutex			mhi_lock;
 	struct mutex			mhi_event_lock;
 
@@ -509,15 +560,22 @@
 	u32				ipa_clnt_hndl[4];
 	struct workqueue_struct		*ring_init_wq;
 	struct work_struct		ring_init_cb_work;
+	struct work_struct		re_init;
 
 	/* EP PCIe registration */
+	struct workqueue_struct		*pcie_event_wq;
 	struct ep_pcie_register_event	event_reg;
 	u32                             ifc_id;
 	struct ep_pcie_hw               *phandle;
+	struct work_struct		pcie_event;
+	struct ep_pcie_msi_config	msi_cfg;
 
 	atomic_t			write_active;
 	atomic_t			is_suspended;
+	atomic_t			mhi_dev_wake;
+	atomic_t			re_init_done;
 	struct mutex			mhi_write_test;
+	u32				device_local_pa_base;
 	u32				mhi_ep_msi_num;
 	u32				mhi_version;
 	void				*dma_cache;
@@ -535,6 +593,37 @@
 	 * region from device used in mhi_write()
 	 */
 	dma_addr_t			write_dma_handle;
+
+	/* Use IPA DMA for Software channel data transfer */
+	bool				use_ipa;
+
+	/* iATU is required to map control and data region */
+	bool				config_iatu;
+
+	/* MHI state info */
+	enum mhi_ctrl_info		ctrl_info;
+
+	/*Register for interrupt */
+	bool				mhi_int;
+	/* Registered client callback list */
+	struct list_head		client_cb_list;
+};
+
+struct mhi_req {
+	u32                             chan;
+	u32                             mode;
+	u32				chain;
+	void                            *buf;
+	dma_addr_t                      dma;
+	u32                             snd_cmpl;
+	void                            *context;
+	size_t                          len;
+	size_t                          actual_len;
+	uint32_t                        rd_offset;
+	struct mhi_dev_client           *client;
+	struct list_head                list;
+	union mhi_dev_ring_element_type *el;
+	void (*client_cb)(void *req);
 };
 
 enum mhi_msg_level {
@@ -609,7 +698,9 @@
 	MHI_CLIENT_CSVT_IN = 43,
 	MHI_CLIENT_SMCT_OUT = 44,
 	MHI_CLIENT_SMCT_IN = 45,
-	MHI_MAX_SOFTWARE_CHANNELS = 46,
+	MHI_CLIENT_IP_SW_4_OUT  = 46,
+	MHI_CLIENT_IP_SW_4_IN  = 47,
+	MHI_MAX_SOFTWARE_CHANNELS = 48,
 	MHI_CLIENT_TEST_OUT = 60,
 	MHI_CLIENT_TEST_IN = 61,
 	MHI_CLIENT_RESERVED_1_LOWER = 62,
@@ -626,6 +717,20 @@
 	uint32_t	buf_size;
 };
 
+struct mhi_dev_client_cb_data {
+	void			*user_data;
+	enum mhi_client_channel	channel;
+	enum mhi_ctrl_info	ctrl_info;
+};
+
+typedef void (*mhi_state_cb)(struct mhi_dev_client_cb_data *cb_dat);
+
+struct mhi_dev_ready_cb_info {
+	struct list_head		list;
+	mhi_state_cb			cb;
+	struct mhi_dev_client_cb_data	cb_data;
+};
+
 /**
  * mhi_dev_open_channel() - Channel open for a given client done prior
  *		to read/write.
@@ -643,24 +748,21 @@
 
 /**
  * mhi_dev_read_channel() - Channel read for a given client
- * @handle_client:	Client Handle issued during mhi_dev_open_channel
- * @buf: Pointer to the buffer used by the MHI core to copy the data received
- *	 from the Host.
- * @buf_size: Size of the buffer pointer.
- * @chain : Indicate if the received data is part of chained packet.
+ * @mreq:       mreq is the client argument which includes meta info
+ *              like write data location, buffer len, read offset, mode,
+ *              chain and client call back function which will be invoked
+ *              when data read is completed.
  */
-int mhi_dev_read_channel(struct mhi_dev_client *handle_client,
-				void *buf, uint32_t buf_size, uint32_t *chain);
+int mhi_dev_read_channel(struct mhi_req *mreq);
 
 /**
  * mhi_dev_write_channel() - Channel write for a given software client.
- * @handle_client:	Client Handle issued during mhi_dev_open_channel
- * @buf: Pointer to the buffer used by the MHI core to copy the data from the
- *	 device to the host.
- * @buf_size: Size of the buffer pointer.
+ * @wreq	wreq is the client argument which includes meta info like
+ *              client handle, read data location, buffer length, mode,
+ *              and client call back function which will free the packet.
+ *              when data write is completed.
  */
-int mhi_dev_write_channel(struct mhi_dev_client *handle_client, void *buf,
-							uint32_t buf_size);
+int mhi_dev_write_channel(struct mhi_req *wreq);
 
 /**
  * mhi_dev_channel_isempty() - Checks if there is any pending TRE's to process.
@@ -733,8 +835,8 @@
  * @element:	Transfer ring element to be copied to the host memory.
  */
 int mhi_dev_add_element(struct mhi_dev_ring *ring,
-				union mhi_dev_ring_element_type *element);
-
+				union mhi_dev_ring_element_type *element,
+				struct event_req *ereq, int evt_offset);
 /**
  * mhi_transfer_device_to_host() - memcpy equivalent API to transfer data
  *		from device to the host.
@@ -742,9 +844,10 @@
  * @src:	Source virtual address.
  * @len:	Numer of bytes to be transferred.
  * @mhi:	MHI dev structure.
+ * @req:        mhi_req structure
  */
 int mhi_transfer_device_to_host(uint64_t dst_pa, void *src, uint32_t len,
-				struct mhi_dev *mhi);
+				struct mhi_dev *mhi, struct mhi_req *req);
 
 /**
  * mhi_transfer_host_to_dev() - memcpy equivalent API to transfer data
@@ -753,19 +856,29 @@
  * @src_pa:	Source physical address.
  * @len:	Numer of bytes to be transferred.
  * @mhi:	MHI dev structure.
+ * @req:        mhi_req structure
  */
 int mhi_transfer_host_to_device(void *device, uint64_t src_pa, uint32_t len,
-				struct mhi_dev *mhi);
+				struct mhi_dev *mhi, struct mhi_req *mreq);
 
 /**
- * mhi_dev_write_to_host() - memcpy equivalent API to transfer data
- *		from device to host.
+ * mhi_dev_write_to_host() - Transfer data from device to host.
+ *		Based on support available, either IPA DMA or memcpy is used.
  * @host:	Host and device address details.
  * @buf:	Data buffer that needs to be written to the host.
  * @size:	Data buffer size.
  */
-void mhi_dev_write_to_host(struct mhi_addr *host, void *buf, size_t size,
-				struct mhi_dev *mhi);
+void mhi_dev_write_to_host(struct mhi_dev *mhi, struct mhi_addr *mhi_transfer,
+		struct event_req *ereq, enum mhi_dev_transfer_type type);
+/**
+ * mhi_dev_read_from_host() - memcpy equivalent API to transfer data
+ *		from host to device.
+ * @host:	Host and device address details.
+ * @buf:	Data buffer that needs to be read from the host.
+ * @size:	Data buffer size.
+ */
+void mhi_dev_read_from_host(struct mhi_dev *mhi,
+				struct mhi_addr *mhi_transfer);
 
 /**
  * mhi_dev_read_from_host() - memcpy equivalent API to transfer data
@@ -774,15 +887,7 @@
  * @buf:	Data buffer that needs to be read from the host.
  * @size:	Data buffer size.
  */
-void mhi_dev_read_from_host(struct mhi_addr *dst, dma_addr_t buf, size_t size);
 
-/**
- * mhi_dev_read_from_host() - memcpy equivalent API to transfer data
- *		from host to device.
- * @host:	Host and device address details.
- * @buf:	Data buffer that needs to be read from the host.
- * @size:	Data buffer size.
- */
 void mhi_ring_set_cb(struct mhi_dev_ring *ring,
 			void (*ring_cb)(struct mhi_dev *dev,
 			union mhi_dev_ring_element_type *el, void *ctx));
@@ -848,6 +953,7 @@
  * mhi_dev_mmio_enable_ctrl_interrupt() - Enable Control interrupt.
  * @dev:	MHI device structure.
  */
+
 int mhi_dev_mmio_enable_ctrl_interrupt(struct mhi_dev *dev);
 
 /**
@@ -1021,8 +1127,10 @@
  * mhi_dev_get_mhi_state() - Fetches the MHI state such as M0/M1/M2/M3.
  * @dev:	MHI device structure.
  * @state:	Pointer of type mhi_dev_state
+ * @mhi_reset:	MHI device reset from host.
  */
-int mhi_dev_mmio_get_mhi_state(struct mhi_dev *dev, enum mhi_dev_state *state);
+int mhi_dev_mmio_get_mhi_state(struct mhi_dev *dev, enum mhi_dev_state *state,
+						bool *mhi_reset);
 
 /**
  * mhi_dev_mmio_init() - Initializes the MMIO and reads the Number of event
@@ -1121,6 +1229,48 @@
  */
 int mhi_uci_init(void);
 
+/**
+ * mhi_dev_net_interface_init() - Initializes the mhi device network interface
+ *		which exposes the virtual network interface (mhi_dev_net0).
+ *		data packets will transfer between MHI host interface (mhi_swip)
+ *		and mhi_dev_net interface using software path
+ */
+int mhi_dev_net_interface_init(void);
+
+/**
+ * mhi_dev_net_exit() - Clean up and close MHI Network interface module.
+ */
+void mhi_dev_net_exit(void);
+
+/**
+ * mhi_dev_notify_a7_event() - Used by PCIe driver to notify A7 MHI device
+ *	interrupt after doorbell is received. Used by PCIe driver when MHI
+ *	A7 interrupts are routed to PCIe instead of MHI device.
+ */
 void mhi_dev_notify_a7_event(struct mhi_dev *mhi);
 
+/**
+ * mhi_ctrl_state_info() - Provide MHI state info
+ *		MHI_STATE=CONFIGURED - MHI device is present but not ready
+ *					for data traffic.
+ *		MHI_STATE=CONNECTED - MHI device is ready for data transfer.
+ *		MHI_STATE=DISCONNECTED - MHI device has its pipes suspended.
+ *		exposes device nodes for the supported MHI software
+ *		channels.
+ */
+int mhi_ctrl_state_info(uint32_t *info);
+
+/**
+ * uci_ctrl_update() - Update UCI once TRE's are available for clients to
+ *			consume.
+ */
+void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason);
+
+/**
+ * mhi_register_state_cb() - Clients can register and receive callback after
+ *		MHI channel is connected or disconnected.
+ */
+int mhi_register_state_cb(void (*mhi_state_cb)
+			(struct mhi_dev_client_cb_data *cb_data), void *data,
+			enum mhi_client_channel channel);
 #endif /* _MHI_H_ */
diff --git a/drivers/platform/msm/mhi_dev/mhi_dev_net.c b/drivers/platform/msm/mhi_dev/mhi_dev_net.c
new file mode 100644
index 0000000..d8dc85f
--- /dev/null
+++ b/drivers/platform/msm/mhi_dev/mhi_dev_net.c
@@ -0,0 +1,667 @@
+/* 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.
+ */
+/*
+ * MHI Device Network interface
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/ip.h>
+#include <linux/if_ether.h>
+#include <linux/skbuff.h>
+#include <linux/if_arp.h>
+#include <linux/netdevice.h>
+#include <linux/dma-mapping.h>
+#include <linux/ipc_logging.h>
+#include <linux/device.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/errno.h>
+#include <linux/ktime.h>
+
+#include "mhi.h"
+
+#define MHI_NET_DRIVER_NAME  "mhi_dev_net_drv"
+#define MHI_NET_DEV_NAME     "mhi_dev_net%d"
+#define MHI_NET_DEFAULT_MTU   8192
+#define MHI_NET_IPC_PAGES     (100)
+#define MHI_MAX_RX_REQ        (128)
+#define MHI_MAX_TX_REQ        (128)
+
+enum mhi_dev_net_dbg_lvl {
+	MHI_VERBOSE = 0x1,
+	MHI_INFO = 0x2,
+	MHI_DBG = 0x3,
+	MHI_WARNING = 0x4,
+	MHI_ERROR = 0x5,
+	MHI_CRITICAL = 0x6,
+	MSG_NET_reserved = 0x80000000
+};
+
+static enum mhi_dev_net_dbg_lvl mhi_net_msg_lvl = MHI_CRITICAL;
+static enum mhi_dev_net_dbg_lvl mhi_net_ipc_log_lvl = MHI_VERBOSE;
+static void *mhi_net_ipc_log;
+
+enum mhi_chan_dir {
+	MHI_DIR_INVALID = 0x0,
+	MHI_DIR_OUT = 0x1,
+	MHI_DIR_IN = 0x2,
+	MHI_DIR__reserved = 0x80000000
+};
+
+struct mhi_dev_net_chan_attr {
+	/* SW maintained channel id */
+	enum mhi_client_channel chan_id;
+	/* maximum buffer size for this channel */
+	size_t max_packet_size;
+	/* direction of the channel, see enum mhi_chan_dir */
+	enum mhi_chan_dir dir;
+};
+
+#define CHAN_TO_CLIENT(_CHAN_NR) (_CHAN_NR / 2)
+
+#define mhi_dev_net_log(_msg_lvl, _msg, ...) do { \
+	if (_msg_lvl >= mhi_net_msg_lvl) { \
+		pr_err("[%s] "_msg, __func__, ##__VA_ARGS__); \
+	} \
+	if (mhi_net_ipc_log && (_msg_lvl >= mhi_net_ipc_log_lvl)) { \
+		ipc_log_string(mhi_net_ipc_log,                     \
+			"[%s] " _msg, __func__, ##__VA_ARGS__);     \
+	} \
+} while (0)
+
+module_param(mhi_net_msg_lvl, uint, 0644);
+MODULE_PARM_DESC(mhi_net_msg_lvl, "mhi dev net dbg lvl");
+
+module_param(mhi_net_ipc_log_lvl, uint, 0644);
+MODULE_PARM_DESC(mhi_net_ipc_log_lvl, "mhi dev net dbg lvl");
+
+struct mhi_dev_net_client {
+	/* write channel - always even*/
+	u32 out_chan;
+	/* read channel - always odd */
+	u32 in_chan;
+	struct mhi_dev_client *out_handle;
+	struct mhi_dev_client *in_handle;
+	/*process pendig packets */
+	struct workqueue_struct *pending_pckt_wq;
+	struct work_struct       xmit_work;
+	/*Read data from host work queue*/
+	atomic_t  rx_enabled;
+	atomic_t  tx_enabled;
+	struct net_device *dev;
+	struct sk_buff_head tx_buffers;
+	struct list_head rx_buffers;
+	struct list_head wr_req_buffers;
+	struct mhi_dev_net_ctxt *net_ctxt;
+	/*To check write channel is empty or not*/
+	spinlock_t wrt_lock;
+	spinlock_t rd_lock;
+	struct mutex in_chan_lock;
+	struct mutex out_chan_lock;
+};
+
+struct mhi_dev_net_ctxt {
+	struct mhi_dev_net_chan_attr chan_attr[MHI_MAX_SOFTWARE_CHANNELS];
+	struct mhi_dev_net_client *client_handle;
+	void (*net_event_notifier)(struct mhi_dev_client_cb_reason *cb);
+};
+
+static struct mhi_dev_net_ctxt mhi_net_ctxt;
+static ssize_t mhi_dev_net_client_read(struct mhi_dev_net_client *);
+
+static int mhi_dev_net_init_ch_attributes(struct mhi_dev_net_ctxt *mhi_ctxt)
+{
+	u32 channel = 0;
+	struct mhi_dev_net_chan_attr *chan_attrib = NULL;
+
+	channel = MHI_CLIENT_IP_SW_4_OUT;
+	chan_attrib = &mhi_ctxt->chan_attr[channel];
+	chan_attrib->dir = MHI_DIR_OUT;
+	chan_attrib->chan_id = channel;
+	chan_attrib->max_packet_size = TRB_MAX_DATA_SIZE;
+	mhi_dev_net_log(MHI_INFO, "Write chan attributes dir %d chan_id %d\n",
+			chan_attrib->dir, chan_attrib->chan_id);
+
+	channel = MHI_CLIENT_IP_SW_4_IN;
+	chan_attrib = &mhi_ctxt->chan_attr[channel];
+	chan_attrib->dir = MHI_DIR_IN;
+	chan_attrib->chan_id = channel;
+	chan_attrib->max_packet_size = TRB_MAX_DATA_SIZE;
+	mhi_dev_net_log(MHI_INFO, "Read chan attributes dir %d chan_id %d\n",
+			chan_attrib->dir, chan_attrib->chan_id);
+	return 0;
+}
+
+static void mhi_dev_net_process_queue_packets(struct work_struct *work)
+{
+	struct mhi_dev_net_client *client = container_of(work,
+			struct mhi_dev_net_client, xmit_work);
+	unsigned long flags = 0;
+	int xfer_data = 0;
+	struct sk_buff *skb = NULL;
+	struct mhi_req *wreq = NULL;
+
+	if (mhi_dev_channel_isempty(client->in_handle)) {
+		mhi_dev_net_log(MHI_INFO, "%s stop network xmmit\n", __func__);
+		netif_stop_queue(client->dev);
+		return;
+	}
+	while (!((skb_queue_empty(&client->tx_buffers)) ||
+			(list_empty(&client->wr_req_buffers)))) {
+		spin_lock_irqsave(&client->wrt_lock, flags);
+		skb = skb_dequeue(&(client->tx_buffers));
+		if (!skb) {
+			mhi_dev_net_log(MHI_INFO,
+					"SKB is NULL from dequeue\n");
+			spin_unlock_irqrestore(&client->wrt_lock, flags);
+			return;
+		}
+		wreq = container_of(client->wr_req_buffers.next,
+				struct mhi_req, list);
+		list_del_init(&wreq->list);
+
+		wreq->client = client->in_handle;
+		wreq->context = skb;
+		wreq->buf = skb->data;
+		wreq->len = skb->len;
+		wreq->chan = client->in_chan;
+		wreq->mode = IPA_DMA_ASYNC;
+		if (skb_queue_empty(&client->tx_buffers) ||
+				list_empty(&client->wr_req_buffers)) {
+			wreq->snd_cmpl = 1;
+		} else
+			wreq->snd_cmpl = 0;
+		spin_unlock_irqrestore(&client->wrt_lock, flags);
+		xfer_data = mhi_dev_write_channel(wreq);
+		if (xfer_data <= 0) {
+			pr_err("%s(): Failed to write skb len %d\n",
+					__func__, skb->len);
+			kfree_skb(skb);
+			return;
+		}
+		client->dev->stats.tx_packets++;
+
+		/* Check if free buffers are available*/
+		if (mhi_dev_channel_isempty(client->in_handle)) {
+			mhi_dev_net_log(MHI_INFO,
+					"%s buffers are full stop xmit\n",
+					__func__);
+			netif_stop_queue(client->dev);
+			break;
+		}
+	} /* While TX queue is not empty */
+}
+
+static void mhi_dev_net_event_notifier(struct mhi_dev_client_cb_reason *reason)
+{
+	struct mhi_dev_net_client *client_handle = mhi_net_ctxt.client_handle;
+
+	if (reason->reason == MHI_DEV_TRE_AVAILABLE) {
+		if (reason->ch_id % 2) {
+			if (netif_queue_stopped(client_handle->dev)) {
+				netif_wake_queue(client_handle->dev);
+				queue_work(client_handle->pending_pckt_wq,
+						&client_handle->xmit_work);
+			}
+		} else
+			mhi_dev_net_client_read(client_handle);
+	}
+}
+
+static __be16 mhi_dev_net_eth_type_trans(struct sk_buff *skb)
+{
+	__be16 protocol = 0;
+	/* Determine L3 protocol */
+	switch (skb->data[0] & 0xf0) {
+	case 0x40:
+		protocol = htons(ETH_P_IP);
+		break;
+	case 0x60:
+		protocol = htons(ETH_P_IPV6);
+		break;
+	default:
+		/* Default is QMAP */
+		protocol = htons(ETH_P_MAP);
+		break;
+	}
+	return protocol;
+}
+
+static void mhi_dev_net_read_completion_cb(void *req)
+{
+	struct mhi_dev_net_client *net_handle =
+		mhi_net_ctxt.client_handle;
+	struct mhi_req *mreq =
+		(struct mhi_req *)req;
+	struct sk_buff *skb = mreq->context;
+	unsigned long   flags;
+
+	skb->len = mreq->actual_len;
+	skb->protocol =
+		mhi_dev_net_eth_type_trans(skb);
+	skb_put(skb, mreq->actual_len);
+	net_handle->dev->stats.rx_packets++;
+	skb->dev = net_handle->dev;
+	netif_rx(skb);
+	spin_lock_irqsave(&net_handle->rd_lock, flags);
+	list_add_tail(&mreq->list, &net_handle->rx_buffers);
+	spin_unlock_irqrestore(&net_handle->rd_lock, flags);
+}
+
+static ssize_t mhi_dev_net_client_read(struct mhi_dev_net_client *mhi_handle)
+{
+	int bytes_avail = 0;
+	int ret_val = 0;
+	u32 chan = 0;
+	struct mhi_dev_client *client_handle = NULL;
+	struct mhi_req *req;
+	struct sk_buff *skb;
+	unsigned long   flags;
+
+	client_handle = mhi_handle->out_handle;
+	chan = mhi_handle->out_chan;
+	if (!atomic_read(&mhi_handle->rx_enabled))
+		return -EPERM;
+	while (1) {
+		spin_lock_irqsave(&mhi_handle->rd_lock, flags);
+		if (list_empty(&mhi_handle->rx_buffers)) {
+			spin_unlock_irqrestore(&mhi_handle->rd_lock, flags);
+			break;
+		}
+
+		req = container_of(mhi_handle->rx_buffers.next,
+				struct mhi_req, list);
+		list_del_init(&req->list);
+		spin_unlock_irqrestore(&mhi_handle->rd_lock, flags);
+		skb = alloc_skb(MHI_NET_DEFAULT_MTU, GFP_ATOMIC);
+		if (skb == NULL) {
+			pr_err("%s(): skb alloc failed\n", __func__);
+			spin_lock_irqsave(&mhi_handle->rd_lock, flags);
+			list_add_tail(&req->list, &mhi_handle->rx_buffers);
+			spin_unlock_irqrestore(&mhi_handle->rd_lock, flags);
+			ret_val = -ENOMEM;
+			return ret_val;
+		}
+
+		req->client = client_handle;
+		req->chan = chan;
+		req->buf = skb->data;
+		req->len = MHI_NET_DEFAULT_MTU;
+		req->context = skb;
+		req->mode = IPA_DMA_ASYNC;
+		bytes_avail = mhi_dev_read_channel(req);
+
+		if (bytes_avail < 0) {
+			pr_err("Failed to read chan %d bytes_avail = %d\n",
+					chan, bytes_avail);
+			spin_lock_irqsave(&mhi_handle->rd_lock, flags);
+			kfree_skb(skb);
+			list_add_tail(&req->list, &mhi_handle->rx_buffers);
+			spin_unlock_irqrestore(&mhi_handle->rd_lock, flags);
+			ret_val = -EIO;
+			return 0;
+		}
+		/* no data to send to network stack, break */
+		if (!bytes_avail) {
+			spin_lock_irqsave(&mhi_handle->rd_lock, flags);
+			kfree_skb(skb);
+			list_add_tail(&req->list, &mhi_handle->rx_buffers);
+			spin_unlock_irqrestore(&mhi_handle->rd_lock, flags);
+			return 0;
+		}
+	}
+	/* coming out while only in case of no data or error */
+	return ret_val;
+
+}
+
+static void mhi_dev_net_write_completion_cb(void *req)
+{
+	struct mhi_dev_net_client *client_handle = mhi_net_ctxt.client_handle;
+	struct mhi_req *wreq = (struct mhi_req *)req;
+	struct sk_buff *skb = wreq->context;
+	unsigned long   flags;
+
+	kfree_skb(skb);
+	spin_lock_irqsave(&client_handle->wrt_lock, flags);
+	list_add_tail(&wreq->list, &client_handle->wr_req_buffers);
+	spin_unlock_irqrestore(&client_handle->wrt_lock, flags);
+}
+
+static int mhi_dev_net_alloc_write_reqs(struct mhi_dev_net_client *client)
+{
+	int nreq = 0, rc = 0;
+	struct mhi_req *wreq;
+
+	while (nreq < MHI_MAX_TX_REQ) {
+		wreq = kzalloc(sizeof(struct mhi_req), GFP_ATOMIC);
+		if (!wreq)
+			return -ENOMEM;
+		wreq->client_cb =  mhi_dev_net_write_completion_cb;
+		list_add_tail(&wreq->list, &client->wr_req_buffers);
+		nreq++;
+	}
+	mhi_dev_net_log(MHI_INFO,
+			"mhi write reqs allocation success\n");
+	return rc;
+
+}
+
+static int mhi_dev_net_alloc_read_reqs(struct mhi_dev_net_client *client)
+{
+	int nreq = 0, rc = 0;
+	struct mhi_req *mreq;
+
+	while (nreq < MHI_MAX_RX_REQ) {
+		mreq = kzalloc(sizeof(struct mhi_req), GFP_ATOMIC);
+		if (!mreq)
+			return -ENOMEM;
+		mreq->len =  TRB_MAX_DATA_SIZE;
+		mreq->client_cb =  mhi_dev_net_read_completion_cb;
+		list_add_tail(&mreq->list, &client->rx_buffers);
+		nreq++;
+	}
+	mhi_dev_net_log(MHI_INFO,
+			"mhi read reqs allocation success\n");
+	return rc;
+
+}
+
+static int mhi_dev_net_open(struct net_device *dev)
+{
+	struct mhi_dev_net_client *mhi_dev_net_ptr =
+		*(struct mhi_dev_net_client **)netdev_priv(dev);
+	mhi_dev_net_log(MHI_INFO,
+			"mhi_net_dev interface is up for IN %d OUT %d\n",
+			mhi_dev_net_ptr->out_chan,
+			mhi_dev_net_ptr->in_chan);
+	netif_start_queue(dev);
+	return 0;
+}
+
+static netdev_tx_t mhi_dev_net_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+	struct mhi_dev_net_client *mhi_dev_net_ptr =
+			*(struct mhi_dev_net_client **)netdev_priv(dev);
+	unsigned long flags;
+
+	if (skb->len <= 0) {
+		mhi_dev_net_log(MHI_ERROR,
+				"Invalid skb received freeing skb\n");
+		kfree_skb(skb);
+		return NETDEV_TX_OK;
+	}
+	spin_lock_irqsave(&mhi_dev_net_ptr->wrt_lock, flags);
+	skb_queue_tail(&(mhi_dev_net_ptr->tx_buffers), skb);
+	spin_unlock_irqrestore(&mhi_dev_net_ptr->wrt_lock, flags);
+
+	queue_work(mhi_dev_net_ptr->pending_pckt_wq,
+			&mhi_dev_net_ptr->xmit_work);
+
+	return NETDEV_TX_OK;
+}
+
+static int mhi_dev_net_stop(struct net_device *dev)
+{
+	netif_stop_queue(dev);
+	mhi_dev_net_log(MHI_VERBOSE, "mhi_dev_net interface is down\n");
+	return 0;
+}
+
+static int mhi_dev_net_change_mtu(struct net_device *dev, int new_mtu)
+{
+	if (0 > new_mtu || MHI_NET_DEFAULT_MTU < new_mtu)
+		return -EINVAL;
+	dev->mtu = new_mtu;
+	return 0;
+}
+
+static const struct net_device_ops mhi_dev_net_ops_ip = {
+	.ndo_open = mhi_dev_net_open,
+	.ndo_stop = mhi_dev_net_stop,
+	.ndo_start_xmit = mhi_dev_net_xmit,
+	.ndo_change_mtu = mhi_dev_net_change_mtu,
+};
+
+static void mhi_dev_net_setup(struct net_device *dev)
+{
+	dev->netdev_ops = &mhi_dev_net_ops_ip;
+	ether_setup(dev);
+
+	/* set this after calling ether_setup */
+	dev->type = ARPHRD_RAWIP;
+	dev->hard_header_len = 0;
+	dev->mtu = MHI_NET_DEFAULT_MTU;
+	dev->addr_len = 0;
+	dev->flags &= ~(IFF_BROADCAST | IFF_MULTICAST);
+}
+
+static int mhi_dev_net_enable_iface(struct mhi_dev_net_client *mhi_dev_net_ptr)
+{
+	int ret = 0;
+	struct mhi_dev_net_client **mhi_dev_net_ctxt = NULL;
+	struct net_device *netdev;
+
+	if (!mhi_dev_net_ptr)
+		return -EINVAL;
+
+	/* Initialize skb list head to queue the packets for mhi dev client */
+	skb_queue_head_init(&(mhi_dev_net_ptr->tx_buffers));
+
+	mhi_dev_net_log(MHI_INFO,
+			"mhi_dev_net interface registration\n");
+	netdev = alloc_netdev(sizeof(struct mhi_dev_net_client),
+			MHI_NET_DEV_NAME, NET_NAME_PREDICTABLE,
+			mhi_dev_net_setup);
+	if (!netdev) {
+		pr_err("Failed to allocate netdev for mhi_dev_net\n");
+		goto net_dev_alloc_fail;
+	}
+
+	mhi_dev_net_ctxt = netdev_priv(netdev);
+	mhi_dev_net_ptr->dev = netdev;
+	*mhi_dev_net_ctxt = mhi_dev_net_ptr;
+	ret = register_netdev(mhi_dev_net_ptr->dev);
+	if (ret) {
+		pr_err("Failed to register mhi_dev_net device\n");
+		goto net_dev_reg_fail;
+	}
+	mhi_dev_net_log(MHI_INFO, "Successfully registred mhi_dev_net\n");
+	return 0;
+
+net_dev_reg_fail:
+	free_netdev(mhi_dev_net_ptr->dev);
+net_dev_alloc_fail:
+	mhi_dev_close_channel(mhi_dev_net_ptr->in_handle);
+	mhi_dev_close_channel(mhi_dev_net_ptr->out_handle);
+	mhi_dev_net_ptr->dev = NULL;
+	return -ENOMEM;
+}
+
+static int mhi_dev_net_open_channels(struct mhi_dev_net_client *client)
+{
+	int rc = 0;
+	int ret = 0;
+	struct list_head *cp, *q;
+	struct mhi_req *mreq;
+
+	mhi_dev_net_log(MHI_DBG, "opening OUT %d IN %d channels\n",
+			client->out_chan,
+			client->in_chan);
+	mutex_lock(&client->out_chan_lock);
+	mutex_lock(&client->in_chan_lock);
+	mhi_dev_net_log(MHI_DBG,
+			"Initializing inbound chan %d.\n",
+			client->in_chan);
+
+	rc = mhi_dev_open_channel(client->out_chan, &client->out_handle,
+			mhi_net_ctxt.net_event_notifier);
+	if (rc < 0) {
+		mhi_dev_net_log(MHI_ERROR,
+				"Failed to open chan %d, ret 0x%x\n",
+				client->out_chan, rc);
+		goto handle_not_rdy_err;
+	} else
+		atomic_set(&client->rx_enabled, 1);
+
+	rc = mhi_dev_open_channel(client->in_chan, &client->in_handle,
+			mhi_net_ctxt.net_event_notifier);
+	if (rc < 0) {
+		mhi_dev_net_log(MHI_ERROR,
+				"Failed to open chan %d, ret 0x%x\n",
+				client->in_chan, rc);
+		goto handle_in_err;
+	} else
+		atomic_set(&client->tx_enabled, 1);
+
+	mutex_unlock(&client->in_chan_lock);
+	mutex_unlock(&client->out_chan_lock);
+	mhi_dev_net_log(MHI_INFO, "IN %d, OUT %d channels are opened",
+			client->in_chan, client->out_chan);
+
+	INIT_LIST_HEAD(&client->rx_buffers);
+	INIT_LIST_HEAD(&client->wr_req_buffers);
+	/* pre allocate read request buffer */
+
+	ret = mhi_dev_net_alloc_read_reqs(client);
+	if (ret) {
+		pr_err("failed to allocate rx req buffers\n");
+		goto rx_req_failed;
+	}
+	ret = mhi_dev_net_alloc_write_reqs(client);
+	if (ret) {
+		pr_err("failed to allocate write req buffers\n");
+		goto tx_req_failed;
+	}
+	if (atomic_read(&client->tx_enabled)) {
+		ret = mhi_dev_net_enable_iface(client);
+		if (ret < 0)
+			mhi_dev_net_log(MHI_ERROR,
+					"failed to enable mhi_dev_net iface\n");
+	}
+	return ret;
+tx_req_failed:
+	list_for_each_safe(cp, q, &client->rx_buffers);
+	mreq = list_entry(cp, struct mhi_req, list);
+	list_del(cp);
+	kfree(mreq);
+rx_req_failed:
+	mhi_dev_close_channel(client->in_handle);
+handle_in_err:
+	mhi_dev_close_channel(client->out_handle);
+handle_not_rdy_err:
+	mutex_unlock(&client->in_chan_lock);
+	mutex_unlock(&client->out_chan_lock);
+	return rc;
+}
+
+static int mhi_dev_net_close(void)
+{
+	struct mhi_dev_net_client *client;
+
+	mhi_dev_net_log(MHI_INFO,
+			"mhi_dev_net module is removed\n");
+	client = mhi_net_ctxt.client_handle;
+	mhi_dev_close_channel(client->out_handle);
+	mhi_dev_close_channel(client->in_handle);
+	atomic_set(&client->tx_enabled, 0);
+	atomic_set(&client->rx_enabled, 0);
+	if (client->dev != NULL) {
+		netif_stop_queue(client->dev);
+		unregister_netdev(client->dev);
+		free_netdev(client->dev);
+		client->dev = NULL;
+	}
+	/* freeing mhi client and IPC context */
+	kfree(client);
+	kfree(mhi_net_ipc_log);
+	return 0;
+}
+
+static int mhi_dev_net_rgstr_client(struct mhi_dev_net_client *client, int idx)
+{
+	client->out_chan = idx;
+	client->in_chan = idx + 1;
+	mutex_init(&client->in_chan_lock);
+	mutex_init(&client->out_chan_lock);
+	spin_lock_init(&client->wrt_lock);
+	spin_lock_init(&client->rd_lock);
+	mhi_dev_net_log(MHI_INFO, "Registering out %d, In %d channels\n",
+			client->out_chan, client->in_chan);
+
+	/* Open IN and OUT channels for Network client*/
+	mhi_dev_net_open_channels(client);
+	return 0;
+}
+
+int mhi_dev_net_interface_init(void)
+{
+	int ret_val = 0;
+	int index = 0;
+	struct mhi_dev_net_client *mhi_net_client = NULL;
+
+	mhi_net_client = kzalloc(sizeof(struct mhi_dev_net_client), GFP_KERNEL);
+	if (!mhi_net_client)
+		return -ENOMEM;
+
+	mhi_net_ipc_log = ipc_log_context_create(MHI_NET_IPC_PAGES,
+						"mhi-net", 0);
+	if (mhi_net_ipc_log == NULL)
+		mhi_dev_net_log(MHI_DBG,
+				"Failed to create IPC logging for mhi_dev_net\n");
+	mhi_net_ctxt.client_handle = mhi_net_client;
+
+	/*Process pending packet work queue*/
+	mhi_net_client->pending_pckt_wq =
+		create_singlethread_workqueue("pending_xmit_pckt_wq");
+	INIT_WORK(&mhi_net_client->xmit_work,
+			mhi_dev_net_process_queue_packets);
+
+	mhi_dev_net_log(MHI_INFO,
+			"Registering for MHI transfer events from host\n");
+	mhi_net_ctxt.net_event_notifier = mhi_dev_net_event_notifier;
+
+	ret_val = mhi_dev_net_init_ch_attributes(&mhi_net_ctxt);
+	if (ret_val < 0) {
+		mhi_dev_net_log(MHI_ERROR,
+				"Failed to init client attributes\n");
+		goto channel_init_fail;
+	}
+	mhi_dev_net_log(MHI_DBG, "Initializing client\n");
+	index = MHI_CLIENT_IP_SW_4_OUT;
+	ret_val = mhi_dev_net_rgstr_client(mhi_net_client, index);
+	if (ret_val) {
+		mhi_dev_net_log(MHI_CRITICAL,
+				"Failed to reg client %d ret 0\n", ret_val);
+		goto client_register_fail;
+	}
+	return ret_val;
+
+channel_init_fail:
+	kfree(mhi_net_client);
+	kfree(mhi_net_ipc_log);
+	return ret_val;
+client_register_fail:
+	kfree(mhi_net_client);
+	kfree(mhi_net_ipc_log);
+	return ret_val;
+}
+EXPORT_SYMBOL(mhi_dev_net_interface_init);
+
+void __exit mhi_dev_net_exit(void)
+{
+	mhi_dev_net_log(MHI_INFO,
+			"MHI Network Interface Module exited ");
+	mhi_dev_net_close();
+}
+EXPORT_SYMBOL(mhi_dev_net_exit);
diff --git a/drivers/platform/msm/mhi_dev/mhi_hwio.h b/drivers/platform/msm/mhi_dev/mhi_hwio.h
index 197713b..09a0118 100644
--- a/drivers/platform/msm/mhi_dev/mhi_hwio.h
+++ b/drivers/platform/msm/mhi_dev/mhi_hwio.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, 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
@@ -184,6 +184,10 @@
 #define ERDB_HIGHER_n_ERDB_HIGHER_MASK			0xffffffff
 #define ERDB_HIGHER_n_ERDB_HIGHER_SHIFT			0x0
 
+#define BHI_INTVEC					(0x220)
+#define BHI_INTVEC_MASK					0xFFFFFFFF
+#define BHI_INTVEC_SHIFT				0
+
 #define BHI_EXECENV					(0x228)
 #define BHI_EXECENV_MASK				0xFFFFFFFF
 #define BHI_EXECENV_SHIFT				0
diff --git a/drivers/platform/msm/mhi_dev/mhi_mmio.c b/drivers/platform/msm/mhi_dev/mhi_mmio.c
index 4043e0b..559fa84 100644
--- a/drivers/platform/msm/mhi_dev/mhi_mmio.c
+++ b/drivers/platform/msm/mhi_dev/mhi_mmio.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
@@ -133,6 +133,11 @@
 	chid_mask = (1 << chid_shft);
 	chid_idx = chdb_id/32;
 
+	if (chid_idx >= MHI_MASK_ROWS_CH_EV_DB) {
+		pr_err("Invalid channel id:%d\n", chid_idx);
+		return -EINVAL;
+	}
+
 	if (enable)
 		val = 1;
 
@@ -143,6 +148,13 @@
 		return rc;
 	}
 
+	rc = mhi_dev_mmio_read(dev, MHI_CHDB_INT_MASK_A7_n(chid_idx),
+						&dev->chdb[chid_idx].mask);
+	if (rc) {
+		pr_err("Read channel db INT on row:%d failed\n", chid_idx);
+		return rc;
+	}
+
 	return rc;
 }
 
@@ -246,7 +258,8 @@
 }
 EXPORT_SYMBOL(mhi_dev_mmio_disable_erdb_a7);
 
-int mhi_dev_mmio_get_mhi_state(struct mhi_dev *dev, enum mhi_dev_state *state)
+int mhi_dev_mmio_get_mhi_state(struct mhi_dev *dev, enum mhi_dev_state *state,
+						bool *mhi_reset)
 {
 	uint32_t reg_value = 0;
 	int rc = 0;
@@ -265,6 +278,9 @@
 	if (rc)
 		return rc;
 
+	if (reg_value & MHICTRL_RESET_MASK)
+		*mhi_reset = true;
+
 	pr_debug("MHICTRL is 0x%x\n", reg_value);
 
 	return 0;
@@ -286,6 +302,7 @@
 			pr_err("Set channel db on row:%d failed\n", i);
 			return rc;
 		}
+		dev->chdb[i].mask = mask;
 	}
 
 	return rc;
@@ -850,6 +867,9 @@
 	mhi_dev_mmio_clear_interrupts(dev);
 	mhi_dev_mmio_enable_ctrl_interrupt(dev);
 
+	/*Enable chdb interrupt*/
+	mhi_dev_mmio_enable_chdb_interrupts(dev);
+
 	/* Mask and enable control interrupt */
 	mb();
 
diff --git a/drivers/platform/msm/mhi_dev/mhi_ring.c b/drivers/platform/msm/mhi_dev/mhi_ring.c
index 3007b5a..d6791ea 100644
--- a/drivers/platform/msm/mhi_dev/mhi_ring.c
+++ b/drivers/platform/msm/mhi_dev/mhi_ring.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -47,38 +47,36 @@
 {
 	struct mhi_addr host_addr;
 
-	host_addr.device_pa = ring->ring_shadow.device_pa
+	if (ring->mhi_dev->use_ipa) {
+		host_addr.host_pa = ring->ring_shadow.host_pa
 			+ sizeof(union mhi_dev_ring_element_type) * start;
-	host_addr.device_va = ring->ring_shadow.device_va
+		host_addr.phy_addr = ring->ring_cache_dma_handle +
+			(sizeof(union mhi_dev_ring_element_type) * start);
+	} else {
+		host_addr.device_va = ring->ring_shadow.device_va
 			+ sizeof(union mhi_dev_ring_element_type) * start;
-	host_addr.host_pa = ring->ring_shadow.host_pa
-			+ sizeof(union mhi_dev_ring_element_type) * start;
+		host_addr.virt_addr = &ring->ring_cache[start];
+	}
+	host_addr.size = (end-start) * sizeof(union mhi_dev_ring_element_type);
 	if (start < end) {
-		mhi_dev_read_from_host(&host_addr,
-			(ring->ring_cache_dma_handle +
-			sizeof(union mhi_dev_ring_element_type) * start),
-			(end-start) *
-			sizeof(union mhi_dev_ring_element_type));
+		mhi_dev_read_from_host(ring->mhi_dev, &host_addr);
 	} else if (start > end) {
 		/* copy from 'start' to ring end, then ring start to 'end'*/
-		mhi_dev_read_from_host(&host_addr,
-			(ring->ring_cache_dma_handle +
-			sizeof(union mhi_dev_ring_element_type) * start),
-			(ring->ring_size-start) *
-			sizeof(union mhi_dev_ring_element_type));
+		host_addr.size = (ring->ring_size-start) *
+					sizeof(union mhi_dev_ring_element_type);
+		mhi_dev_read_from_host(ring->mhi_dev, &host_addr);
 		if (end) {
 			/* wrapped around */
 			host_addr.device_pa = ring->ring_shadow.device_pa;
 			host_addr.device_va = ring->ring_shadow.device_va;
 			host_addr.host_pa = ring->ring_shadow.host_pa;
-			mhi_dev_read_from_host(&host_addr,
-				(ring->ring_cache_dma_handle +
-				sizeof(union mhi_dev_ring_element_type) *
-				start),
-				end * sizeof(union mhi_dev_ring_element_type));
+			host_addr.virt_addr = &ring->ring_cache[0];
+			host_addr.phy_addr = ring->ring_cache_dma_handle;
+			host_addr.size = (end *
+				sizeof(union mhi_dev_ring_element_type));
+			mhi_dev_read_from_host(ring->mhi_dev, &host_addr);
 		}
 	}
-
 	return 0;
 }
 
@@ -95,21 +93,16 @@
 	mhi_ctx = ring->mhi_dev;
 
 	if (ring->wr_offset == wr_offset) {
-		mhi_log(MHI_MSG_INFO,
+		mhi_log(MHI_MSG_VERBOSE,
 			"nothing to cache for ring %d, local wr_ofst %d\n",
 			ring->id, ring->wr_offset);
-		mhi_log(MHI_MSG_INFO,
+		mhi_log(MHI_MSG_VERBOSE,
 			"new wr_offset %d\n", wr_offset);
 		return 0;
 	}
 
 	old_offset = ring->wr_offset;
 
-	mhi_log(MHI_MSG_ERROR,
-			"caching - rng size :%d local ofst:%d new ofst: %d\n",
-			(uint32_t) ring->ring_size, old_offset,
-			ring->wr_offset);
-
 	/*
 	 * copy the elements starting from old_offset to wr_offset
 	 * take in to account wrap around case event rings are not
@@ -118,12 +111,12 @@
 	if (ring->id >= mhi_ctx->ev_ring_start &&
 		ring->id < (mhi_ctx->ev_ring_start +
 				mhi_ctx->cfg.event_rings)) {
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_VERBOSE,
 				"not caching event ring %d\n", ring->id);
 		return 0;
 	}
 
-	mhi_log(MHI_MSG_ERROR, "caching ring %d, start %d, end %d\n",
+	mhi_log(MHI_MSG_VERBOSE, "caching ring %d, start %d, end %d\n",
 			ring->id, old_offset, wr_offset);
 
 	if (mhi_dev_fetch_ring_elements(ring, old_offset, wr_offset)) {
@@ -155,7 +148,7 @@
 			pr_err("%s: CMD DB read failed\n", __func__);
 			return rc;
 		}
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_VERBOSE,
 			"ring %d wr_offset from db 0x%x\n",
 			ring->id, (uint32_t) wr_offset);
 		break;
@@ -172,7 +165,7 @@
 			pr_err("%s: CH DB read failed\n", __func__);
 			return rc;
 		}
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_VERBOSE,
 			"ring %d wr_offset from db 0x%x\n",
 			ring->id, (uint32_t) wr_offset);
 		break;
@@ -203,10 +196,14 @@
 	/* get the element and invoke the respective callback */
 	el = &ring->ring_cache[offset];
 
+	mhi_log(MHI_MSG_VERBOSE, "evnt ptr : 0x%llx\n", el->tre.data_buf_ptr);
+	mhi_log(MHI_MSG_VERBOSE, "evnt len : 0x%x, offset:%d\n",
+						el->tre.len, offset);
+
 	if (ring->ring_cb)
 		ring->ring_cb(ring->mhi_dev, el, (void *)ring);
 	else
-		mhi_log(MHI_MSG_INFO, "No callback registered for ring %d\n",
+		mhi_log(MHI_MSG_ERROR, "No callback registered for ring %d\n",
 				ring->id);
 
 	return 0;
@@ -216,12 +213,17 @@
 int mhi_dev_process_ring(struct mhi_dev_ring *ring)
 {
 	int rc = 0;
+	union mhi_dev_ring_element_type *el;
 
 	if (!ring) {
 		pr_err("%s: Invalid ring context\n", __func__);
 		return -EINVAL;
 	}
 
+	mhi_log(MHI_MSG_VERBOSE,
+			"Before wr update ring_id (%d) element (%d) with wr:%d\n",
+			ring->id, ring->rd_offset, ring->wr_offset);
+
 	rc = mhi_dev_update_wr_offset(ring);
 	if (rc) {
 		mhi_log(MHI_MSG_ERROR,
@@ -230,6 +232,13 @@
 		return rc;
 	}
 
+	/* get the element and invoke the respective callback */
+	el = &ring->ring_cache[ring->wr_offset];
+
+	mhi_log(MHI_MSG_VERBOSE, "evnt ptr : 0x%llx\n", el->tre.data_buf_ptr);
+	mhi_log(MHI_MSG_VERBOSE, "evnt len : 0x%x, wr_offset:%d\n",
+						el->tre.len, ring->wr_offset);
+
 	if (ring->type == RING_TYPE_CH) {
 		/* notify the clients that there are elements in the ring */
 		rc = mhi_dev_process_ring_element(ring, ring->rd_offset);
@@ -237,6 +246,9 @@
 			pr_err("Error fetching elements\n");
 		return rc;
 	}
+	mhi_log(MHI_MSG_VERBOSE,
+			"After ring update ring_id (%d) element (%d) with wr:%d\n",
+			ring->id, ring->rd_offset, ring->wr_offset);
 
 	while (ring->rd_offset != ring->wr_offset) {
 		rc = mhi_dev_process_ring_element(ring, ring->rd_offset);
@@ -247,7 +259,7 @@
 			return rc;
 		}
 
-		mhi_log(MHI_MSG_ERROR,
+		mhi_log(MHI_MSG_VERBOSE,
 			"Processing ring (%d) rd_offset:%d, wr_offset:%d\n",
 			ring->id, ring->rd_offset, ring->wr_offset);
 
@@ -265,10 +277,12 @@
 EXPORT_SYMBOL(mhi_dev_process_ring);
 
 int mhi_dev_add_element(struct mhi_dev_ring *ring,
-				union mhi_dev_ring_element_type *element)
+				union mhi_dev_ring_element_type *element,
+				struct event_req *ereq, int evt_offset)
 {
 	uint32_t old_offset = 0;
 	struct mhi_addr host_addr;
+	uint32_t num_elem = 0;
 
 	if (!ring || !element) {
 		pr_err("%s: Invalid context\n", __func__);
@@ -278,33 +292,53 @@
 	mhi_dev_update_wr_offset(ring);
 
 	if ((ring->rd_offset + 1) % ring->ring_size == ring->wr_offset) {
-		mhi_log(MHI_MSG_INFO, "ring full to insert element\n");
+		mhi_log(MHI_MSG_VERBOSE, "ring full to insert element\n");
 		return -EINVAL;
 	}
 
 	old_offset = ring->rd_offset;
 
-	mhi_dev_ring_inc_index(ring, ring->rd_offset);
+	if (evt_offset) {
+		num_elem = evt_offset /
+			(sizeof(union mhi_dev_ring_element_type));
+		ring->rd_offset += num_elem;
+		if (ring->rd_offset >= ring->ring_size)
+			ring->rd_offset -= ring->ring_size;
+	} else
+		mhi_dev_ring_inc_index(ring, ring->rd_offset);
 
 	ring->ring_ctx->generic.rp = (ring->rd_offset *
-				sizeof(union mhi_dev_ring_element_type)) +
-				ring->ring_ctx->generic.rbase;
+		sizeof(union mhi_dev_ring_element_type)) +
+		ring->ring_ctx->generic.rbase;
 	/*
 	 * Write the element, ring_base has to be the
 	 * iomap of the ring_base for memcpy
 	 */
-	host_addr.host_pa = ring->ring_shadow.host_pa +
+
+	if (ring->mhi_dev->use_ipa)
+		host_addr.host_pa = ring->ring_shadow.host_pa +
 			sizeof(union mhi_dev_ring_element_type) * old_offset;
-	host_addr.device_va = ring->ring_shadow.device_va +
+	else
+		host_addr.device_va = ring->ring_shadow.device_va +
 			sizeof(union mhi_dev_ring_element_type) * old_offset;
 
-	mhi_log(MHI_MSG_ERROR, "adding element to ring (%d)\n", ring->id);
-	mhi_log(MHI_MSG_ERROR, "rd_ofset %d\n", ring->rd_offset);
-	mhi_log(MHI_MSG_ERROR, "type %d\n", element->generic.type);
+	host_addr.virt_addr = element;
 
-	mhi_dev_write_to_host(&host_addr, element,
-			sizeof(union mhi_dev_ring_element_type), ring->mhi_dev);
+	if (evt_offset)
+		host_addr.size = evt_offset;
+	else
+		host_addr.size = sizeof(union mhi_dev_ring_element_type);
 
+	mhi_log(MHI_MSG_VERBOSE, "adding element to ring (%d)\n", ring->id);
+	mhi_log(MHI_MSG_VERBOSE, "rd_ofset %d\n", ring->rd_offset);
+	mhi_log(MHI_MSG_VERBOSE, "type %d\n", element->generic.type);
+
+	if (ereq)
+		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
+				ereq, MHI_DEV_DMA_ASYNC);
+	else
+		mhi_dev_write_to_host(ring->mhi_dev, &host_addr,
+				NULL, MHI_DEV_DMA_SYNC);
 	return 0;
 }
 EXPORT_SYMBOL(mhi_dev_add_element);
@@ -362,16 +396,15 @@
 		(union mhi_dev_ring_ctx *) (mhi->ch_ctx_shadow.device_va +
 		(ring->id - mhi->ch_ring_start)*sizeof(union mhi_dev_ring_ctx));
 
-
 	ring->ring_ctx_shadow = ring->ring_ctx;
 
-	if (ring->type != RING_TYPE_ER) {
+	if (ring->type != RING_TYPE_ER || ring->type != RING_TYPE_CH) {
 		rc = mhi_dev_cache_ring(ring, wr_offset);
 		if (rc)
 			return rc;
 	}
 
-	mhi_log(MHI_MSG_ERROR, "ctx ring_base:0x%x, rp:0x%x, wp:0x%x\n",
+	mhi_log(MHI_MSG_VERBOSE, "ctx ring_base:0x%x, rp:0x%x, wp:0x%x\n",
 			(uint32_t)ring->ring_ctx->generic.rbase,
 			(uint32_t)ring->ring_ctx->generic.rp,
 			(uint32_t)ring->ring_ctx->generic.wp);
diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.c b/drivers/platform/msm/mhi_dev/mhi_sm.c
index 8179fad..1200a36 100644
--- a/drivers/platform/msm/mhi_dev/mhi_sm.c
+++ b/drivers/platform/msm/mhi_dev/mhi_sm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -396,7 +396,8 @@
 		res = true;
 		break;
 	case EP_PCIE_EVENT_PM_D3_HOT:
-		res = (curr_mstate == MHI_DEV_M3_STATE &&
+		res = ((curr_mstate == MHI_DEV_M3_STATE ||
+			curr_mstate == MHI_DEV_READY_STATE) &&
 			curr_dstate != MHI_SM_EP_PCIE_LINK_DISABLE);
 		break;
 	case EP_PCIE_EVENT_PM_D3_COLD:
@@ -437,7 +438,7 @@
 {
 	enum mhi_dev_state old_state;
 	struct ep_pcie_msi_config cfg;
-	int res;
+	int res = -EINVAL;
 
 	MHI_SM_FUNC_ENTRY();
 
@@ -476,6 +477,30 @@
 	mhi_sm_mmio_set_mhistatus(MHI_DEV_M0_STATE);
 
 	/* Tell the host, device move to M0 */
+	if (old_state == MHI_DEV_M3_STATE) {
+		if (mhi_sm_ctx->mhi_dev->use_ipa) {
+			res = ipa_dma_enable();
+			if (res) {
+				MHI_SM_ERR("IPA enable failed\n");
+				return res;
+			}
+		}
+
+		res = mhi_dev_resume(mhi_sm_ctx->mhi_dev);
+		if (res) {
+			MHI_SM_ERR("Failed resuming mhi core, returned %d",
+				res);
+			goto exit;
+		}
+
+		res = ipa_mhi_resume();
+		if (res) {
+			MHI_SM_ERR("Failed resuming ipa_mhi, returned %d",
+				res);
+			goto exit;
+		}
+	}
+
 	res = mhi_dev_send_state_change_event(mhi_sm_ctx->mhi_dev,
 				MHI_DEV_M0_STATE);
 	if (res) {
@@ -491,20 +516,6 @@
 			MHI_SM_ERR("failed sending EE event to host\n");
 			goto exit;
 		}
-	} else if (old_state == MHI_DEV_M3_STATE) {
-		/*Resuming MHI operation*/
-		res = mhi_dev_resume(mhi_sm_ctx->mhi_dev);
-		if (res) {
-			MHI_SM_ERR("Failed resuming mhi core, returned %d",
-				res);
-			goto exit;
-		}
-		res = ipa_mhi_resume();
-		if (res) {
-			MHI_SM_ERR("Failed resuming ipa_mhi, returned %d",
-				res);
-			goto exit;
-		}
 	}
 	res  = 0;
 
@@ -557,6 +568,14 @@
 		goto exit;
 	}
 
+	if (mhi_sm_ctx->mhi_dev->use_ipa) {
+		res = ipa_dma_disable();
+		if (res) {
+			MHI_SM_ERR("IPA disable failed\n");
+			return res;
+		}
+	}
+
 exit:
 	MHI_SM_FUNC_EXIT();
 	return res;
@@ -579,9 +598,9 @@
 
 	if (mhi_sm_ctx->mhi_state == MHI_DEV_M3_STATE) {
 		/*
-		 * ep_pcie driver is responsible to send the right wakeup
-		 * event, assert WAKE#, according to Link state
-		 */
+		  * ep_pcie driver is responsible to send the right wakeup
+		  * event, assert WAKE#, according to Link state
+		  */
 		res = ep_pcie_wakeup_host(mhi_sm_ctx->mhi_dev->phandle);
 		if (res) {
 			MHI_SM_ERR("Failed to wakeup MHI host, returned %d\n",
@@ -661,8 +680,8 @@
 		MHI_SM_ERR("EP-PCIE Link is disable cannot set MMIO to %s\n",
 			mhi_sm_mstate_str(MHI_DEV_SYSERR_STATE));
 
-	MHI_SM_ERR("/n/n/nASSERT ON DEVICE !!!!/n/n/n");
-	WARN_ON();
+	MHI_SM_ERR("/n/n/nError ON DEVICE !!!!/n/n/n");
+	WARN_ON(1);
 
 	MHI_SM_FUNC_EXIT();
 	return res;
@@ -918,6 +937,24 @@
 }
 EXPORT_SYMBOL(mhi_dev_sm_init);
 
+int mhi_dev_sm_exit(struct mhi_dev *mhi_dev)
+{
+	MHI_SM_FUNC_ENTRY();
+
+	atomic_set(&mhi_sm_ctx->pending_device_events, 0);
+	atomic_set(&mhi_sm_ctx->pending_pcie_events, 0);
+	mhi_sm_debugfs_destroy();
+	flush_workqueue(mhi_sm_ctx->mhi_sm_wq);
+	destroy_workqueue(mhi_sm_ctx->mhi_sm_wq);
+	ipa_dma_destroy();
+	mutex_destroy(&mhi_sm_ctx->mhi_state_lock);
+	devm_kfree(mhi_dev->dev, mhi_sm_ctx);
+	mhi_sm_ctx = NULL;
+
+	return 0;
+}
+EXPORT_SYMBOL(mhi_dev_sm_exit);
+
 /**
  * mhi_dev_sm_get_mhi_state() -Get current MHI state.
  * @state: return param
@@ -964,7 +1001,7 @@
  */
 int mhi_dev_sm_set_ready(void)
 {
-	int res;
+	int res = 0;
 	int is_ready;
 	enum mhi_dev_state state;
 
@@ -1011,6 +1048,7 @@
 		goto unlock_and_exit;
 	}
 	mhi_sm_mmio_set_mhistatus(MHI_DEV_READY_STATE);
+	res = 0;
 
 unlock_and_exit:
 	mutex_unlock(&mhi_sm_ctx->mhi_state_lock);
@@ -1153,6 +1191,7 @@
 		ep_pcie_mask_irq_event(mhi_sm_ctx->mhi_dev->phandle,
 				EP_PCIE_INT_EVT_MHI_A7, false);
 		mhi_dev_notify_a7_event(mhi_sm_ctx->mhi_dev);
+		kfree(dstate_change_evt);
 		goto exit;
 	default:
 		MHI_SM_ERR("Invalid ep_pcie event, received 0x%x event\n",
diff --git a/drivers/platform/msm/mhi_dev/mhi_sm.h b/drivers/platform/msm/mhi_dev/mhi_sm.h
index d477880..01e127b 100644
--- a/drivers/platform/msm/mhi_dev/mhi_sm.h
+++ b/drivers/platform/msm/mhi_dev/mhi_sm.h
@@ -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
@@ -41,6 +41,7 @@
 };
 
 int mhi_dev_sm_init(struct mhi_dev *dev);
+int mhi_dev_sm_exit(struct mhi_dev *dev);
 int mhi_dev_sm_set_ready(void);
 int mhi_dev_notify_sm_event(enum mhi_dev_event event);
 int mhi_dev_sm_get_mhi_state(enum mhi_dev_state *state);
diff --git a/drivers/platform/msm/mhi_dev/mhi_uci.c b/drivers/platform/msm/mhi_dev/mhi_uci.c
index 3279fa8..244cf04 100644
--- a/drivers/platform/msm/mhi_dev/mhi_uci.c
+++ b/drivers/platform/msm/mhi_dev/mhi_uci.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
@@ -73,6 +73,12 @@
 	u32 uci_ownership;
 };
 
+struct uci_ctrl {
+	wait_queue_head_t	ctrl_wq;
+	struct mhi_uci_ctxt_t	*uci_ctxt;
+	atomic_t		ctrl_data_update;
+};
+
 struct uci_client {
 	u32 client_index;
 	/* write channel - always odd*/
@@ -100,9 +106,13 @@
 struct mhi_uci_ctxt_t {
 	struct chan_attr chan_attrib[MHI_MAX_SOFTWARE_CHANNELS];
 	struct uci_client client_handles[MHI_SOFTWARE_CLIENT_LIMIT];
+	struct uci_ctrl ctrl_handle;
 	void (*event_notifier)(struct mhi_dev_client_cb_reason *cb);
 	dev_t start_ctrl_nr;
 	struct cdev cdev[MHI_MAX_SOFTWARE_CHANNELS];
+	dev_t ctrl_nr;
+	struct cdev *cdev_ctrl;
+	struct device *dev;
 	struct class *mhi_uci_class;
 	atomic_t mhi_disabled;
 	atomic_t mhi_enable_notif_wq_active;
@@ -129,12 +139,16 @@
 
 static ssize_t mhi_uci_client_read(struct file *file, char __user *buf,
 		size_t count, loff_t *offp);
+static ssize_t mhi_uci_ctrl_client_read(struct file *file, char __user *buf,
+		size_t count, loff_t *offp);
 static ssize_t mhi_uci_client_write(struct file *file,
 		const char __user *buf, size_t count, loff_t *offp);
 static int mhi_uci_client_open(struct inode *mhi_inode, struct file*);
+static int mhi_uci_ctrl_open(struct inode *mhi_inode, struct file*);
 static int mhi_uci_client_release(struct inode *mhi_inode,
 		struct file *file_handle);
 static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait);
+static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait);
 static struct mhi_uci_ctxt_t uci_ctxt;
 
 static int mhi_init_read_chan(struct uci_client *client_handle,
@@ -184,6 +198,8 @@
 	uintptr_t memcpy_result = 0;
 	u32 data_inserted_so_far = 0;
 	struct uci_client *uci_handle;
+	struct mhi_req ureq;
+
 
 	uci_handle = container_of(client_handle, struct uci_client,
 					out_handle);
@@ -206,15 +222,43 @@
 	} else {
 		data_loc = buf;
 	}
+	ureq.client = *client_handle;
+	ureq.buf = data_loc;
+	ureq.len = size;
+	ureq.chan = uci_handle->out_chan;
+	ureq.mode = IPA_DMA_SYNC;
 
-	data_inserted_so_far = mhi_dev_write_channel(*client_handle, data_loc,
-							size);
+	data_inserted_so_far = mhi_dev_write_channel(&ureq);
 
 error_memcpy:
 	kfree(data_loc);
 	return data_inserted_so_far;
 }
 
+static unsigned int mhi_uci_ctrl_poll(struct file *file, poll_table *wait)
+{
+	unsigned int mask = 0;
+	struct uci_ctrl *uci_ctrl_handle;
+
+	uci_ctrl_handle = file->private_data;
+
+	if (!uci_ctrl_handle)
+		return -ENODEV;
+
+	poll_wait(file, &uci_ctrl_handle->ctrl_wq, wait);
+	if (!atomic_read(&uci_ctxt.mhi_disabled) &&
+		atomic_read(&uci_ctrl_handle->ctrl_data_update)) {
+		uci_log(UCI_DBG_VERBOSE, "Client can read ctrl_state");
+		mask |= POLLIN | POLLRDNORM;
+	}
+
+	uci_log(UCI_DBG_VERBOSE,
+		"Client attempted to poll ctrl returning mask 0x%x\n",
+		mask);
+
+	return mask;
+}
+
 static unsigned int mhi_uci_client_poll(struct file *file, poll_table *wait)
 {
 	unsigned int mask = 0;
@@ -297,6 +341,22 @@
 	return rc;
 }
 
+static int mhi_uci_ctrl_open(struct inode *inode,
+			struct file *file_handle)
+{
+	struct uci_ctrl *uci_ctrl_handle;
+
+	uci_log(UCI_DBG_DBG, "Client opened ctrl file device node\n");
+
+	uci_ctrl_handle = &uci_ctxt.ctrl_handle;
+	if (!uci_ctrl_handle)
+		return -EINVAL;
+
+	file_handle->private_data = uci_ctrl_handle;
+
+	return 0;
+}
+
 static int mhi_uci_client_open(struct inode *mhi_inode,
 				struct file *file_handle)
 {
@@ -337,18 +397,20 @@
 		struct file *file_handle)
 {
 	struct uci_client *uci_handle = file_handle->private_data;
-	struct mhi_uci_ctxt_t *uci_ctxt = uci_handle->uci_ctxt;
+	struct mhi_uci_ctxt_t *uci_ctxt;
 	u32 nr_in_bufs = 0;
 	int rc = 0;
 	int in_chan = 0;
 	u32 buf_size = 0;
 
+	if (!uci_handle)
+		return -EINVAL;
+
+	uci_ctxt = uci_handle->uci_ctxt;
 	in_chan = iminor(mhi_inode) + 1;
 	nr_in_bufs = uci_ctxt->chan_attrib[in_chan].nr_trbs;
 	buf_size = uci_ctxt->chan_attrib[in_chan].max_packet_size;
 
-	if (!uci_handle)
-		return -EINVAL;
 	if (atomic_sub_return(1, &uci_handle->ref_count) == 0) {
 		uci_log(UCI_DBG_DBG,
 				"Last client left, closing channel 0x%x\n",
@@ -379,7 +441,54 @@
 	return rc;
 }
 
-static ssize_t mhi_uci_client_read(struct file *file, char __user *buf,
+static ssize_t mhi_uci_ctrl_client_read(struct file *file,
+		char __user *user_buf,
+		size_t count, loff_t *offp)
+{
+	uint32_t rc = 0, info;
+	int nbytes, size;
+	char buf[MHI_CTRL_STATE];
+	struct uci_ctrl *uci_ctrl_handle = NULL;
+
+	if (!file || !user_buf || !count ||
+		(count < MHI_CTRL_STATE) || !file->private_data)
+		return -EINVAL;
+
+	uci_ctrl_handle = file->private_data;
+	rc = mhi_ctrl_state_info(&info);
+	if (rc)
+		return -EINVAL;
+
+	switch (info) {
+	case MHI_STATE_CONFIGURED:
+		nbytes = scnprintf(buf, sizeof(buf),
+			"MHI_STATE=CONFIGURED");
+		break;
+	case MHI_STATE_CONNECTED:
+		nbytes = scnprintf(buf, sizeof(buf),
+			"MHI_STATE=CONNECTED");
+		break;
+	case MHI_STATE_DISCONNECTED:
+		nbytes = scnprintf(buf, sizeof(buf),
+			"MHI_STATE=DISCONNECTED");
+		break;
+	default:
+		pr_err("invalid info:%d\n", info);
+		return -EINVAL;
+	}
+
+
+	size = simple_read_from_buffer(user_buf, count, offp, buf, nbytes);
+
+	atomic_set(&uci_ctrl_handle->ctrl_data_update, 0);
+
+	if (size == 0)
+		*offp = 0;
+
+	return size;
+}
+
+static ssize_t mhi_uci_client_read(struct file *file, char __user *ubuf,
 		size_t uspace_buf_size, loff_t *bytes_pending)
 {
 	struct uci_client *uci_handle = NULL;
@@ -387,39 +496,40 @@
 	int bytes_avail = 0;
 	int ret_val = 0;
 	struct mutex *mutex;
-	u32 chan = 0;
 	ssize_t bytes_copied = 0;
 	u32 addr_offset = 0;
-	uint32_t buf_size;
-	uint32_t chained = 0;
 	void *local_buf = NULL;
+	struct mhi_req ureq;
 
-	if (!file || !buf || !uspace_buf_size ||
+	if (!file || !ubuf || !uspace_buf_size ||
 			!file->private_data)
 		return -EINVAL;
 
 	uci_handle = file->private_data;
 	client_handle = uci_handle->in_handle;
 	mutex = &uci_handle->in_chan_lock;
-	chan = uci_handle->in_chan;
+	ureq.chan = uci_handle->in_chan;
 
 	mutex_lock(mutex);
+	ureq.client = client_handle;
+	ureq.buf = uci_handle->in_buf_list[0].addr;
+	ureq.len = uci_handle->in_buf_list[0].buf_size;
+	ureq.mode = IPA_DMA_SYNC;
 
-	local_buf = uci_handle->in_buf_list[0].addr;
-	buf_size = uci_handle->in_buf_list[0].buf_size;
-
-
-	uci_log(UCI_DBG_VERBOSE, "Client attempted read on chan %d\n", chan);
+	uci_log(UCI_DBG_VERBOSE, "Client attempted read on chan %d\n",
+			ureq.chan);
 	do {
 		if (!uci_handle->pkt_loc &&
 				!atomic_read(&uci_ctxt.mhi_disabled)) {
 
-			bytes_avail = mhi_dev_read_channel(client_handle,
-					local_buf, buf_size, &chained);
+			bytes_avail = mhi_dev_read_channel(&ureq);
 
 			uci_log(UCI_DBG_VERBOSE,
-				"reading from mhi_core local_buf = %p,buf_size = 0x%x bytes_read = 0x%x\n",
-				local_buf, buf_size, bytes_avail);
+				"reading from mhi_core local_buf = %p",
+				local_buf);
+			uci_log(UCI_DBG_VERBOSE,
+					"buf_size = 0x%x bytes_read = 0x%x\n",
+					 ureq.len, bytes_avail);
 
 			if (bytes_avail < 0) {
 				uci_log(UCI_DBG_ERROR,
@@ -430,13 +540,14 @@
 			}
 
 			if (bytes_avail > 0) {
-				uci_handle->pkt_loc = (void *)local_buf;
-				uci_handle->pkt_size = bytes_avail;
+				uci_handle->pkt_loc = (void *) ureq.buf;
+				uci_handle->pkt_size = ureq.actual_len;
 
 				*bytes_pending = (loff_t)uci_handle->pkt_size;
 				uci_log(UCI_DBG_VERBOSE,
-					"Got pkt of size 0x%x at addr %p, chan %d\n",
-					uci_handle->pkt_size, local_buf, chan);
+					"Got pkt of sz 0x%x at adr %p, ch %d\n",
+					uci_handle->pkt_size,
+					ureq.buf, ureq.chan);
 			} else {
 				uci_handle->pkt_loc = 0;
 				uci_handle->pkt_size = 0;
@@ -448,7 +559,7 @@
 			uci_log(UCI_DBG_VERBOSE,
 				"No data read_data_ready %d, chan %d\n",
 				atomic_read(&uci_handle->read_data_ready),
-				chan);
+				ureq.chan);
 
 			ret_val = wait_event_interruptible(uci_handle->read_wq,
 				(!mhi_dev_channel_isempty(client_handle)));
@@ -458,17 +569,17 @@
 				goto error;
 			}
 			uci_log(UCI_DBG_VERBOSE,
-				"Thread woke up. Got data on chan %d read_data_ready %d\n",
-				chan,
+				"wk up Got data on ch %d read_data_ready %d\n",
+				ureq.chan,
 				atomic_read(&uci_handle->read_data_ready));
 
 			/* A valid packet was returned from MHI */
 		} else if (bytes_avail > 0) {
 			uci_log(UCI_DBG_VERBOSE,
-				"Got packet: avail pkts %d phy_adr %p, chan %d\n",
+				"Got packet: avail pkts %d phy_adr %p, ch %d\n",
 				atomic_read(&uci_handle->read_data_ready),
-				local_buf,
-				chan);
+				ureq.buf,
+				ureq.chan);
 			break;
 			/*
 			 * MHI did not return a valid packet, but we have one
@@ -477,16 +588,16 @@
 		} else {
 			uci_log(UCI_DBG_CRITICAL,
 				"chan %d err: avail pkts %d phy_adr %p",
-				chan,
+				ureq.chan,
 				atomic_read(&uci_handle->read_data_ready),
-				local_buf);
+				ureq.buf);
 			return -EIO;
 		}
 	} while (!uci_handle->pkt_loc);
 
 	if (uspace_buf_size >= *bytes_pending) {
 		addr_offset = uci_handle->pkt_size - *bytes_pending;
-		if (copy_to_user(buf, uci_handle->pkt_loc + addr_offset,
+		if (copy_to_user(ubuf, uci_handle->pkt_loc + addr_offset,
 							*bytes_pending)) {
 			ret_val = -EIO;
 			goto error;
@@ -495,10 +606,10 @@
 		bytes_copied = *bytes_pending;
 		*bytes_pending = 0;
 		uci_log(UCI_DBG_VERBOSE, "Copied 0x%x of 0x%x, chan %d\n",
-				bytes_copied, (u32)*bytes_pending, chan);
+				bytes_copied, (u32)*bytes_pending, ureq.chan);
 	} else {
 		addr_offset = uci_handle->pkt_size - *bytes_pending;
-		if (copy_to_user(buf, (void *) (uintptr_t)uci_handle->pkt_loc +
+		if (copy_to_user(ubuf, (void *) (uintptr_t)uci_handle->pkt_loc +
 					addr_offset, uspace_buf_size)) {
 			ret_val = -EIO;
 			goto error;
@@ -508,13 +619,13 @@
 		uci_log(UCI_DBG_VERBOSE, "Copied 0x%x of 0x%x,chan %d\n",
 				bytes_copied,
 				(u32)*bytes_pending,
-				chan);
+				ureq.chan);
 	}
 	/* We finished with this buffer, map it back */
 	if (*bytes_pending == 0) {
 		uci_log(UCI_DBG_VERBOSE,
 				"All data consumed. Pkt loc %p ,chan %d\n",
-				uci_handle->pkt_loc, chan);
+				uci_handle->pkt_loc, ureq.chan);
 		uci_handle->pkt_loc = 0;
 		uci_handle->pkt_size = 0;
 	}
@@ -599,6 +710,8 @@
 		case MHI_CLIENT_SAHARA_IN:
 		case MHI_CLIENT_EFS_OUT:
 		case MHI_CLIENT_EFS_IN:
+		case MHI_CLIENT_MBIM_OUT:
+		case MHI_CLIENT_MBIM_IN:
 		case MHI_CLIENT_QMI_OUT:
 		case MHI_CLIENT_QMI_IN:
 		case MHI_CLIENT_IP_CTRL_0_OUT:
@@ -634,6 +747,23 @@
 	return 0;
 }
 
+void uci_ctrl_update(struct mhi_dev_client_cb_reason *reason)
+{
+	struct uci_ctrl *uci_ctrl_handle = NULL;
+
+	if (reason->reason == MHI_DEV_CTRL_UPDATE) {
+		uci_ctrl_handle = &uci_ctxt.ctrl_handle;
+		if (!uci_ctrl_handle) {
+			pr_err("Invalid uci ctrl handle\n");
+			return;
+		}
+
+		uci_log(UCI_DBG_DBG, "received state change update\n");
+		wake_up(&uci_ctrl_handle->ctrl_wq);
+		atomic_set(&uci_ctrl_handle->ctrl_data_update, 1);
+	}
+}
+EXPORT_SYMBOL(uci_ctrl_update);
 
 static void uci_event_notifier(struct mhi_dev_client_cb_reason *reason)
 {
@@ -718,6 +848,12 @@
 	return rc;
 }
 
+static const struct file_operations mhi_uci_ctrl_client_fops = {
+	.open = mhi_uci_ctrl_open,
+	.read = mhi_uci_ctrl_client_read,
+	.poll = mhi_uci_ctrl_poll,
+};
+
 static const struct file_operations mhi_uci_client_fops = {
 	.read = mhi_uci_client_read,
 	.write = mhi_uci_client_write,
@@ -770,16 +906,25 @@
 			}
 		}
 	}
+
+	init_waitqueue_head(&uci_ctxt.ctrl_handle.ctrl_wq);
 	uci_log(UCI_DBG_INFO, "Allocating char devices.\n");
 	r = alloc_chrdev_region(&uci_ctxt.start_ctrl_nr,
 			0, MHI_MAX_SOFTWARE_CHANNELS,
 			DEVICE_NAME);
-
 	if (IS_ERR_VALUE(r)) {
 		uci_log(UCI_DBG_ERROR,
 				"Failed to alloc char devs, ret 0x%x\n", r);
 		goto failed_char_alloc;
 	}
+
+	r = alloc_chrdev_region(&uci_ctxt.ctrl_nr, 0, 1, DEVICE_NAME);
+	if (IS_ERR_VALUE(r)) {
+		uci_log(UCI_DBG_ERROR,
+				"Failed to alloc char ctrl devs, 0x%x\n", r);
+		goto failed_char_alloc;
+	}
+
 	uci_log(UCI_DBG_INFO, "Creating class\n");
 	uci_ctxt.mhi_uci_class = class_create(THIS_MODULE,
 						DEVICE_NAME);
@@ -803,12 +948,12 @@
 					i, r);
 				goto failed_char_add;
 			}
+
 			uci_ctxt.client_handles[i].dev =
 				device_create(uci_ctxt.mhi_uci_class, NULL,
 						uci_ctxt.start_ctrl_nr + i,
 						NULL, DEVICE_NAME "_pipe_%d",
 						i * 2);
-
 			if (IS_ERR(uci_ctxt.client_handles[i].dev)) {
 				uci_log(UCI_DBG_ERROR,
 						"Failed to add cdev %d\n", i);
@@ -817,6 +962,37 @@
 			}
 		}
 	}
+
+	/* Control node */
+	uci_ctxt.cdev_ctrl = cdev_alloc();
+	if (uci_ctxt.cdev_ctrl == NULL) {
+		pr_err("%s: ctrl cdev alloc failed\n", __func__);
+		return 0;
+	}
+
+	cdev_init(uci_ctxt.cdev_ctrl, &mhi_uci_ctrl_client_fops);
+	uci_ctxt.cdev_ctrl->owner = THIS_MODULE;
+	r = cdev_add(uci_ctxt.cdev_ctrl, uci_ctxt.ctrl_nr, 1);
+	if (IS_ERR_VALUE(r)) {
+		uci_log(UCI_DBG_ERROR,
+		"Failed to add ctrl cdev %d, ret 0x%x\n", i, r);
+		kfree(uci_ctxt.cdev_ctrl);
+		uci_ctxt.cdev_ctrl = NULL;
+		return 0;
+	}
+
+	uci_ctxt.dev =
+		device_create(uci_ctxt.mhi_uci_class, NULL,
+				uci_ctxt.ctrl_nr,
+				NULL, DEVICE_NAME "_ctrl");
+	if (IS_ERR(uci_ctxt.dev)) {
+		uci_log(UCI_DBG_ERROR,
+				"Failed to add ctrl cdev %d\n", i);
+		cdev_del(uci_ctxt.cdev_ctrl);
+		kfree(uci_ctxt.cdev_ctrl);
+		uci_ctxt.cdev_ctrl = NULL;
+	}
+
 	return 0;
 
 failed_char_add:
diff --git a/drivers/platform/msm/qpnp-revid.c b/drivers/platform/msm/qpnp-revid.c
index 05e8172..99c5f27 100644
--- a/drivers/platform/msm/qpnp-revid.c
+++ b/drivers/platform/msm/qpnp-revid.c
@@ -50,6 +50,7 @@
 	[PM2433_SUBTYPE] = "PM2433",
 	[PMD9655_SUBTYPE] = "PMD9655",
 	[PM8950_SUBTYPE] = "PM8950",
+	[PM8953_SUBTYPE] = "PM8953",
 	[PMI8950_SUBTYPE] = "PMI8950",
 	[PMK8001_SUBTYPE] = "PMK8001",
 	[PMI8996_SUBTYPE] = "PMI8996",
diff --git a/drivers/platform/msm/usb_bam.c b/drivers/platform/msm/usb_bam.c
index dec698f..6314270 100644
--- a/drivers/platform/msm/usb_bam.c
+++ b/drivers/platform/msm/usb_bam.c
@@ -3313,7 +3313,7 @@
 	return ret;
 }
 
-bool usb_bam_get_prod_granted(enum usb_ctrl bam_type, u8 idx)
+bool usb_bam_get_prod_granted(enum usb_ctrl bam_type)
 {
 	return (info[bam_type].cur_prod_state == IPA_RM_RESOURCE_GRANTED);
 }
diff --git a/drivers/power/supply/qcom/fg-core.h b/drivers/power/supply/qcom/fg-core.h
index a2a35c6..e77cf35 100644
--- a/drivers/power/supply/qcom/fg-core.h
+++ b/drivers/power/supply/qcom/fg-core.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -86,6 +86,13 @@
 
 #define MAX_CC_STEPS			20
 
+enum prof_load_status {
+	PROFILE_MISSING,
+	PROFILE_LOADED,
+	PROFILE_SKIPPED,
+	PROFILE_NOT_LOADED,
+};
+
 /* Debug flag definitions */
 enum fg_debug_flag {
 	FG_IRQ			= BIT(0), /* Show interrupts */
@@ -446,6 +453,7 @@
 	enum slope_limit_status	slope_limit_sts;
 	bool			profile_available;
 	bool			profile_loaded;
+	enum prof_load_status	profile_load_status;
 	bool			battery_missing;
 	bool			fg_restarting;
 	bool			charge_full;
diff --git a/drivers/power/supply/qcom/qg-core.h b/drivers/power/supply/qcom/qg-core.h
index aadef7f..6f2e42e 100644
--- a/drivers/power/supply/qcom/qg-core.h
+++ b/drivers/power/supply/qcom/qg-core.h
@@ -43,6 +43,7 @@
 	int			s3_exit_ibat_ua;
 	int			delta_soc;
 	int			rbat_conn_mohm;
+	int			ignore_shutdown_soc_secs;
 };
 
 struct qpnp_qg {
@@ -79,6 +80,7 @@
 
 	/* status variable */
 	u32			*debug_mask;
+	bool			qg_device_open;
 	bool			profile_loaded;
 	bool			battery_missing;
 	bool			data_ready;
@@ -91,6 +93,8 @@
 	int			charge_type;
 	int			next_wakeup_ms;
 	u32			wa_flags;
+	u32			seq_no;
+	u32			charge_counter_uah;
 	ktime_t			last_user_update_time;
 	ktime_t			last_fifo_update_time;
 
diff --git a/drivers/power/supply/qcom/qg-soc.c b/drivers/power/supply/qcom/qg-soc.c
index 4fdd258..5b27779 100644
--- a/drivers/power/supply/qcom/qg-soc.c
+++ b/drivers/power/supply/qcom/qg-soc.c
@@ -48,6 +48,9 @@
 
 static bool is_scaling_required(struct qpnp_qg *chip)
 {
+	if (!chip->profile_loaded)
+		return false;
+
 	if ((abs(chip->catch_up_soc - chip->msoc) < chip->dt.delta_soc) &&
 		chip->catch_up_soc != 0 && chip->catch_up_soc != 100)
 		return false;
diff --git a/drivers/power/supply/qcom/qg-util.c b/drivers/power/supply/qcom/qg-util.c
index 44e5048..65f0f6d 100644
--- a/drivers/power/supply/qcom/qg-util.c
+++ b/drivers/power/supply/qcom/qg-util.c
@@ -36,7 +36,14 @@
 	int rc, i;
 	u32 dummy = 0;
 
+	rc = regmap_bulk_read(chip->regmap, addr, val, len);
+	if (rc < 0) {
+		pr_err("Failed regmap_read for address %04x rc=%d\n", addr, rc);
+		return rc;
+	}
+
 	if (is_sticky_register(addr)) {
+		/* write to the sticky register to clear it */
 		rc = regmap_write(chip->regmap, addr, dummy);
 		if (rc < 0) {
 			pr_err("Failed regmap_write for %04x rc=%d\n",
@@ -45,12 +52,6 @@
 		}
 	}
 
-	rc = regmap_bulk_read(chip->regmap, addr, val, len);
-	if (rc < 0) {
-		pr_err("Failed regmap_read for address %04x rc=%d\n", addr, rc);
-		return rc;
-	}
-
 	if (*chip->debug_mask & QG_DEBUG_BUS_READ) {
 		pr_info("length %d addr=%04x\n", len, addr);
 		for (i = 0; i < len; i++)
@@ -122,7 +123,7 @@
 	}
 
 	if (rt) {
-		*fifo_length &= COUNT_FIFO_RT_MASK;
+		*fifo_length = reg & COUNT_FIFO_RT_MASK;
 	} else {
 		*fifo_length = (reg & FIFO_LENGTH_MASK) >> FIFO_LENGTH_SHIFT;
 		*fifo_length += 1;
diff --git a/drivers/power/supply/qcom/qpnp-fg-gen3.c b/drivers/power/supply/qcom/qpnp-fg-gen3.c
index 0894f37..8cc8328 100644
--- a/drivers/power/supply/qcom/qpnp-fg-gen3.c
+++ b/drivers/power/supply/qcom/qpnp-fg-gen3.c
@@ -916,11 +916,16 @@
 #define DEFAULT_BATT_TYPE	"Unknown Battery"
 #define MISSING_BATT_TYPE	"Missing Battery"
 #define LOADING_BATT_TYPE	"Loading Battery"
+#define SKIP_BATT_TYPE		"Skipped loading battery"
 static const char *fg_get_battery_type(struct fg_chip *chip)
 {
-	if (chip->battery_missing)
+	if (chip->battery_missing ||
+		chip->profile_load_status == PROFILE_MISSING)
 		return MISSING_BATT_TYPE;
 
+	if (chip->profile_load_status == PROFILE_SKIPPED)
+		return SKIP_BATT_TYPE;
+
 	if (chip->bp.batt_type_str) {
 		if (chip->profile_loaded)
 			return chip->bp.batt_type_str;
@@ -2714,12 +2719,14 @@
 				buf, PROFILE_COMP_LEN, FG_IMA_DEFAULT);
 		if (rc < 0) {
 			pr_err("Error in reading battery profile, rc:%d\n", rc);
+			chip->profile_load_status = PROFILE_SKIPPED;
 			return false;
 		}
 		profiles_same = memcmp(chip->batt_profile, buf,
 					PROFILE_COMP_LEN) == 0;
 		if (profiles_same) {
 			fg_dbg(chip, FG_STATUS, "Battery profile is same, not loading it\n");
+			chip->profile_load_status = PROFILE_LOADED;
 			return false;
 		}
 
@@ -2733,6 +2740,7 @@
 				dump_sram(chip->batt_profile, PROFILE_LOAD_WORD,
 					PROFILE_LEN);
 			}
+			chip->profile_load_status = PROFILE_SKIPPED;
 			return false;
 		}
 
@@ -2876,6 +2884,7 @@
 
 	rc = fg_get_batt_profile(chip);
 	if (rc < 0) {
+		chip->profile_load_status = PROFILE_MISSING;
 		pr_warn("profile for batt_id=%dKOhms not found..using OTP, rc:%d\n",
 			chip->batt_id_ohms / 1000, rc);
 		goto out;
@@ -2927,6 +2936,7 @@
 	}
 
 	fg_dbg(chip, FG_STATUS, "SOC is ready\n");
+	chip->profile_load_status = PROFILE_LOADED;
 done:
 	rc = fg_bp_params_config(chip);
 	if (rc < 0)
@@ -2952,7 +2962,10 @@
 
 	batt_psy_initialized(chip);
 	fg_notify_charger(chip);
-	chip->profile_loaded = true;
+
+	if (chip->profile_load_status == PROFILE_LOADED)
+		chip->profile_loaded = true;
+
 	fg_dbg(chip, FG_STATUS, "profile loaded successfully");
 out:
 	chip->soc_reporting_ready = true;
@@ -4312,6 +4325,7 @@
 	if (chip->battery_missing) {
 		chip->profile_available = false;
 		chip->profile_loaded = false;
+		chip->profile_load_status = PROFILE_NOT_LOADED;
 		chip->soc_reporting_ready = false;
 		chip->batt_id_ohms = -EINVAL;
 		cancel_delayed_work_sync(&chip->pl_enable_work);
diff --git a/drivers/power/supply/qcom/qpnp-qg.c b/drivers/power/supply/qcom/qpnp-qg.c
index 55cb5ef..56233f5 100644
--- a/drivers/power/supply/qcom/qpnp-qg.c
+++ b/drivers/power/supply/qcom/qpnp-qg.c
@@ -226,6 +226,8 @@
 	u8 v_fifo[MAX_FIFO_LENGTH * 2], i_fifo[MAX_FIFO_LENGTH * 2];
 	u32 sample_interval = 0, sample_count = 0, fifo_v = 0, fifo_i = 0;
 
+	chip->kdata.fifo_time = (u32)ktime_get_seconds();
+
 	if (!fifo_length) {
 		pr_debug("No FIFO data\n");
 		return 0;
@@ -245,6 +247,20 @@
 		return rc;
 	}
 
+	/*
+	 * If there is pending data from suspend, append the new FIFO
+	 * data to it.
+	 */
+	if (chip->suspend_data) {
+		j = chip->kdata.fifo_length; /* append the data */
+		chip->suspend_data = false;
+		qg_dbg(chip, QG_DEBUG_FIFO,
+			"Pending suspend-data FIFO length=%d\n", j);
+	} else {
+		/* clear any old pending data */
+		chip->kdata.fifo_length = 0;
+	}
+
 	for (i = 0; i < fifo_length * 2; i = i + 2, j++) {
 		rc = qg_read(chip, chip->qg_base + QG_V_FIFO0_DATA0_REG + i,
 					&v_fifo[i], 2);
@@ -278,7 +294,8 @@
 					chip->kdata.fifo[j].count);
 	}
 
-	chip->kdata.fifo_length = fifo_length;
+	chip->kdata.fifo_length += fifo_length;
+	chip->kdata.seq_no = chip->seq_no++ % U32_MAX;
 
 	return rc;
 }
@@ -330,6 +347,9 @@
 	chip->kdata.fifo[index].count = count;
 	chip->kdata.fifo_length++;
 
+	if (chip->kdata.fifo_length == 1)	/* Only accumulator data */
+		chip->kdata.seq_no = chip->seq_no++ % U32_MAX;
+
 	qg_dbg(chip, QG_DEBUG_FIFO, "ACC v_avg=%duV i_avg=%duA interval=%d count=%d\n",
 			chip->kdata.fifo[index].v,
 			(int)chip->kdata.fifo[index].i,
@@ -507,11 +527,8 @@
 		qg_dbg(chip, QG_DEBUG_SOC, "udata SOC=%d last SOC=%d\n",
 			chip->udata.param[QG_SOC].data, chip->catch_up_soc);
 
-		/* Only scale if SOC has changed */
-		if (chip->catch_up_soc != chip->udata.param[QG_SOC].data) {
-			chip->catch_up_soc = chip->udata.param[QG_SOC].data;
-			qg_scale_soc(chip, false);
-		}
+		chip->catch_up_soc = chip->udata.param[QG_SOC].data;
+		qg_scale_soc(chip, false);
 
 		/* update parameters to SDAM */
 		chip->sdam_data[SDAM_SOC] =
@@ -527,6 +544,10 @@
 			pr_err("Failed to update SDAM params, rc=%d\n", rc);
 	}
 
+	if (chip->udata.param[QG_CHARGE_COUNTER].valid)
+		chip->charge_counter_uah =
+			chip->udata.param[QG_CHARGE_COUNTER].data;
+
 	vote(chip->awake_votable, UDATA_READY_VOTER, false, 0);
 }
 
@@ -650,6 +671,7 @@
 static irqreturn_t qg_good_ocv_handler(int irq, void *data)
 {
 	int rc;
+	u8 status = 0;
 	u32 ocv_uv;
 	struct qpnp_qg *chip = data;
 
@@ -657,6 +679,15 @@
 
 	mutex_lock(&chip->data_lock);
 
+	rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status, 1);
+	if (rc < 0) {
+		pr_err("Failed to read status2 register rc=%d\n", rc);
+		goto done;
+	}
+
+	if (!(status & GOOD_OCV_BIT))
+		goto done;
+
 	rc = qg_read_ocv(chip, &ocv_uv, GOOD_OCV);
 	if (rc < 0) {
 		pr_err("Failed to read good_ocv, rc=%d\n", rc);
@@ -716,6 +747,10 @@
 {
 	struct qpnp_qg *chip = data;
 
+	/* ignore if the QG device is not open */
+	if (!chip->qg_device_open)
+		return 0;
+
 	if (awake)
 		pm_stay_awake(chip->dev);
 	else
@@ -958,6 +993,9 @@
 	case POWER_SUPPLY_PROP_BATT_PROFILE_VERSION:
 		pval->intval = chip->bp.qg_profile_version;
 		break;
+	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
+		pval->intval = chip->charge_counter_uah;
+		break;
 	default:
 		pr_debug("Unsupported property %d\n", psp);
 		break;
@@ -978,6 +1016,7 @@
 	POWER_SUPPLY_PROP_VOLTAGE_NOW,
 	POWER_SUPPLY_PROP_VOLTAGE_OCV,
 	POWER_SUPPLY_PROP_CURRENT_NOW,
+	POWER_SUPPLY_PROP_CHARGE_COUNTER,
 	POWER_SUPPLY_PROP_RESISTANCE,
 	POWER_SUPPLY_PROP_RESISTANCE_ID,
 	POWER_SUPPLY_PROP_RESISTANCE_CAPACITIVE,
@@ -1169,6 +1208,7 @@
 		goto fail_read;
 	}
 
+
 	if (copy_to_user(buf, &chip->kdata, data_size)) {
 		pr_err("Failed in copy_to_user\n");
 		rc = -EFAULT;
@@ -1176,9 +1216,6 @@
 	}
 	chip->data_ready = false;
 
-	/* clear data */
-	memset(&chip->kdata, 0, sizeof(chip->kdata));
-
 	/* release all wake sources */
 	vote(chip->awake_votable, GOOD_OCV_VOTER, false, 0);
 	vote(chip->awake_votable, FIFO_DONE_VOTER, false, 0);
@@ -1186,7 +1223,11 @@
 	vote(chip->awake_votable, SUSPEND_DATA_VOTER, false, 0);
 
 	qg_dbg(chip, QG_DEBUG_DEVICE,
-			"QG device read complete Size=%ld\n", data_size);
+		"QG device read complete Seq_no=%u Size=%ld\n",
+				chip->kdata.seq_no, data_size);
+
+	/* clear data */
+	memset(&chip->kdata, 0, sizeof(chip->kdata));
 
 	mutex_unlock(&chip->data_lock);
 
@@ -1211,7 +1252,7 @@
 	}
 
 	if (count != 0 && count < data_size) {
-		pr_err("Invalid datasize %zu expected %zu\n", count, data_size);
+		pr_err("Invalid datasize %zu expected %lu\n", count, data_size);
 		goto fail;
 	}
 
@@ -1251,14 +1292,28 @@
 				struct qpnp_qg, qg_cdev);
 
 	file->private_data = chip;
+	chip->qg_device_open = true;
 	qg_dbg(chip, QG_DEBUG_DEVICE, "QG device opened!\n");
 
 	return 0;
 }
 
+static int qg_device_release(struct inode *inode, struct file *file)
+{
+	struct qpnp_qg *chip = container_of(inode->i_cdev,
+				struct qpnp_qg, qg_cdev);
+
+	file->private_data = chip;
+	chip->qg_device_open = false;
+	qg_dbg(chip, QG_DEBUG_DEVICE, "QG device closed!\n");
+
+	return 0;
+}
+
 static const struct file_operations qg_fops = {
 	.owner		= THIS_MODULE,
 	.open		= qg_device_open,
+	.release	= qg_device_release,
 	.read		= qg_device_read,
 	.write		= qg_device_write,
 	.poll		= qg_device_poll,
@@ -1323,7 +1378,7 @@
 		return rc;
 	}
 
-	batt_id_mv = result.physical / 1000;
+	batt_id_mv = div_s64(result.physical, 1000);
 	if (batt_id_mv == 0) {
 		pr_debug("batt_id_mv = 0 from ADC\n");
 		return 0;
@@ -1437,9 +1492,9 @@
 
 static int qg_determine_pon_soc(struct qpnp_qg *chip)
 {
-	u8 status;
-	int rc, batt_temp = 0;
-	bool use_pon_ocv = false;
+	u8 status = 0, ocv_type = 0;
+	int rc = 0, batt_temp = 0;
+	bool use_pon_ocv = true, use_shutdown_ocv = false;
 	unsigned long rtc_sec = 0;
 	u32 ocv_uv = 0, soc = 0, shutdown[SDAM_MAX] = {0};
 
@@ -1448,83 +1503,77 @@
 		return 0;
 	}
 
-	rc = qg_get_battery_temp(chip, &batt_temp);
-	if (rc) {
-		pr_err("Failed to read BATT_TEMP at PON rc=%d\n", rc);
-		return rc;
-	}
-
-	rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG,
-					&status, 1);
+	rc = get_rtc_time(&rtc_sec);
 	if (rc < 0) {
-		pr_err("Failed to read status2 register rc=%d\n", rc);
-		return rc;
+		pr_err("Failed to read RTC time rc=%d\n", rc);
+		goto use_pon_ocv;
 	}
 
-	if (status & GOOD_OCV_BIT) {
-		qg_dbg(chip, QG_DEBUG_PON, "Using GOOD_OCV @ PON\n");
-		rc = qg_read_ocv(chip, &ocv_uv, GOOD_OCV);
-		if (rc < 0) {
-			pr_err("Failed to read good_ocv rc=%d\n", rc);
-			use_pon_ocv = true;
-		} else {
-			rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
-			if (rc < 0) {
-				pr_err("Failed to lookup SOC (GOOD_OCV) @ PON rc=%d\n",
-					rc);
-				use_pon_ocv = true;
-			}
-		}
-	} else {
-		rc = get_rtc_time(&rtc_sec);
-		if (rc < 0) {
-			pr_err("Failed to read RTC time rc=%d\n", rc);
-			use_pon_ocv = true;
+	rc = qg_sdam_read_all(shutdown);
+	if (rc < 0) {
+		pr_err("Failed to read shutdown params rc=%d\n", rc);
+		goto use_pon_ocv;
+	}
+
+	qg_dbg(chip, QG_DEBUG_PON, "Shutdown: Valid=%d SOC=%d OCV=%duV time=%dsecs, time_now=%ldsecs\n",
+			shutdown[SDAM_VALID],
+			shutdown[SDAM_SOC],
+			shutdown[SDAM_OCV_UV],
+			shutdown[SDAM_TIME_SEC],
+			rtc_sec);
+	/*
+	 * Use the shutdown SOC if
+	 * 1. The device was powered off for < ignore_shutdown_time
+	 * 2. SDAM read is a success & SDAM data is valid
+	 */
+	if (shutdown[SDAM_VALID] && is_between(0,
+			chip->dt.ignore_shutdown_soc_secs,
+			(rtc_sec - shutdown[SDAM_TIME_SEC]))) {
+		use_pon_ocv = false;
+		use_shutdown_ocv = true;
+		ocv_uv = shutdown[SDAM_OCV_UV];
+		soc = shutdown[SDAM_SOC];
+		qg_dbg(chip, QG_DEBUG_PON, "Using SHUTDOWN_SOC @ PON\n");
+	}
+
+use_pon_ocv:
+	if (use_pon_ocv == true) {
+		rc = qg_get_battery_temp(chip, &batt_temp);
+		if (rc) {
+			pr_err("Failed to read BATT_TEMP at PON rc=%d\n", rc);
 			goto done;
 		}
 
-		rc = qg_sdam_read_all(shutdown);
+		rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status, 1);
 		if (rc < 0) {
-			pr_err("Failed to read shutdown params rc=%d\n", rc);
-			use_pon_ocv = true;
+			pr_err("Failed to read status2 register rc=%d\n", rc);
 			goto done;
 		}
-		qg_dbg(chip, QG_DEBUG_PON, "Shutdown: SOC=%d OCV=%duV time=%dsecs, time_now=%ldsecs\n",
-				shutdown[SDAM_SOC],
-				shutdown[SDAM_OCV_UV],
-				shutdown[SDAM_TIME_SEC],
-				rtc_sec);
-		/*
-		 * Use the shutdown SOC if
-		 * 1. The device was powered off for < 180 seconds
-		 * 2. SDAM read is a success & SDAM data is valid
-		 */
-		use_pon_ocv = true;
-		if (!rc && shutdown[SDAM_VALID] &&
-			((rtc_sec - shutdown[SDAM_TIME_SEC]) < 180)) {
-			use_pon_ocv = false;
-			ocv_uv = shutdown[SDAM_OCV_UV];
-			soc = shutdown[SDAM_SOC];
-			qg_dbg(chip, QG_DEBUG_PON, "Using SHUTDOWN_SOC @ PON\n");
+
+		if (status & GOOD_OCV_BIT)
+			ocv_type = GOOD_OCV;
+		else
+			ocv_type = PON_OCV;
+
+		qg_dbg(chip, QG_DEBUG_PON, "Using %s @ PON\n",
+				ocv_type == GOOD_OCV ? "GOOD_OCV" : "PON_OCV");
+
+		rc = qg_read_ocv(chip, &ocv_uv, ocv_type);
+		if (rc < 0) {
+			pr_err("Failed to read ocv rc=%d\n", rc);
+			goto done;
+		}
+
+		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
+		if (rc < 0) {
+			pr_err("Failed to lookup SOC@PON rc=%d\n", rc);
+			goto done;
 		}
 	}
 done:
-	/*
-	 * Use PON OCV if
-	 * OCV_UV is not set or shutdown SOC is invalid.
-	 */
-	if (use_pon_ocv || !ocv_uv || !rtc_sec) {
-		qg_dbg(chip, QG_DEBUG_PON, "Using PON_OCV @ PON\n");
-		rc = qg_read_ocv(chip, &ocv_uv, PON_OCV);
-		if (rc < 0) {
-			pr_err("Failed to read HW PON ocv rc=%d\n", rc);
-			return rc;
-		}
-		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
-		if (rc < 0) {
-			pr_err("Failed to lookup SOC @ PON rc=%d\n", rc);
-			soc = 50;
-		}
+	if (rc < 0) {
+		pr_err("Failed to get SOC @ PON, rc=%d\n", rc);
+		return rc;
 	}
 
 	chip->pon_soc = chip->catch_up_soc = chip->msoc = soc;
@@ -1544,10 +1593,9 @@
 	if (rc < 0)
 		pr_err("Failed to update sdam params rc=%d\n", rc);
 
-	pr_info("use_pon_ocv=%d good_ocv=%d ocv_uv=%duV temp=%d soc=%d\n",
+	pr_info("use_pon_ocv=%d use_good_ocv=%d use_shutdown_ocv=%d ocv_uv=%duV soc=%d\n",
 			use_pon_ocv, !!(status & GOOD_OCV_BIT),
-			ocv_uv, batt_temp, chip->msoc);
-
+			use_shutdown_ocv, ocv_uv, chip->msoc);
 	return 0;
 }
 
@@ -1857,6 +1905,7 @@
 #define DEFAULT_S2_ACC_LENGTH		128
 #define DEFAULT_S2_ACC_INTVL_MS		100
 #define DEFAULT_DELTA_SOC		1
+#define DEFAULT_SHUTDOWN_SOC_SECS	360
 static int qg_parse_dt(struct qpnp_qg *chip)
 {
 	int rc = 0;
@@ -2014,6 +2063,12 @@
 	else
 		chip->dt.delta_soc = temp;
 
+	rc = of_property_read_u32(node, "qcom,ignore-shutdown-soc-secs", &temp);
+	if (rc < 0)
+		chip->dt.ignore_shutdown_soc_secs = DEFAULT_SHUTDOWN_SOC_SECS;
+	else
+		chip->dt.ignore_shutdown_soc_secs = temp;
+
 	rc = of_property_read_u32(node, "qcom,rbat-conn-mohm", &temp);
 	if (rc < 0)
 		chip->dt.rbat_conn_mohm = 0;
@@ -2029,9 +2084,16 @@
 
 static int process_suspend(struct qpnp_qg *chip)
 {
+	u8 status = 0;
 	int rc;
 	u32 fifo_rt_length = 0, sleep_fifo_length = 0;
 
+	/* skip if profile is not loaded */
+	if (!chip->profile_loaded)
+		return 0;
+
+	chip->suspend_data = false;
+
 	/* ignore any suspend processing if we are charging */
 	if (chip->charge_status == POWER_SUPPLY_STATUS_CHARGING) {
 		qg_dbg(chip, QG_DEBUG_PM, "Charging @ suspend - ignore processing\n");
@@ -2081,6 +2143,9 @@
 		chip->suspend_data = true;
 	}
 
+	/* read STATUS2 register to clear its last state */
+	qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status, 1);
+
 	qg_dbg(chip, QG_DEBUG_PM, "FIFO rt_length=%d sleep_fifo_length=%d default_s2_count=%d suspend_data=%d\n",
 			fifo_rt_length, sleep_fifo_length,
 			chip->dt.s2_fifo_length, chip->suspend_data);
@@ -2090,9 +2155,13 @@
 
 static int process_resume(struct qpnp_qg *chip)
 {
-	int rc, batt_temp = 0;
 	u8 status2 = 0, rt_status = 0;
-	u32 ocv_uv = 0, soc = 0;
+	u32 ocv_uv = 0;
+	int rc, batt_temp = 0;
+
+	/* skip if profile is not loaded */
+	if (!chip->profile_loaded)
+		return 0;
 
 	rc = qg_read(chip, chip->qg_base + QG_STATUS2_REG, &status2, 1);
 	if (rc < 0) {
@@ -2114,23 +2183,12 @@
 
 		chip->kdata.param[QG_GOOD_OCV_UV].data = ocv_uv;
 		chip->kdata.param[QG_GOOD_OCV_UV].valid = true;
+		 /* Clear suspend data as there has been a GOOD OCV */
 		chip->suspend_data = false;
-		rc = lookup_soc_ocv(&soc, ocv_uv, batt_temp, false);
-		if (rc < 0) {
-			pr_err("Failed to lookup OCV, rc=%d\n", rc);
-			return rc;
-		}
-		chip->catch_up_soc = soc;
-		/* update the SOC immediately */
-		qg_scale_soc(chip, true);
-
-		qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV soc=%d\n",
-				ocv_uv, soc);
+		qg_dbg(chip, QG_DEBUG_PM, "GOOD OCV @ resume good_ocv=%d uV\n",
+				ocv_uv);
 	}
-	/*
-	 * If the wakeup was not because of FIFO_DONE
-	 * send the pending data collected during suspend.
-	 */
+
 	rc = qg_read(chip, chip->qg_base + QG_INT_LATCHED_STS_REG,
 						&rt_status, 1);
 	if (rc < 0) {
@@ -2139,18 +2197,23 @@
 	}
 	rt_status &= FIFO_UPDATE_DONE_INT_LAT_STS_BIT;
 
-	if (!rt_status && chip->suspend_data) {
+	qg_dbg(chip, QG_DEBUG_PM, "FIFO_DONE_STS=%d suspend_data=%d good_ocv=%d\n",
+				!!rt_status, chip->suspend_data,
+				chip->kdata.param[QG_GOOD_OCV_UV].valid);
+	/*
+	 * If this is not a wakeup from FIFO-done,
+	 * process the data immediately if - we have data from
+	 * suspend or there is a good OCV.
+	 */
+	if (!rt_status && (chip->suspend_data ||
+			chip->kdata.param[QG_GOOD_OCV_UV].valid)) {
 		vote(chip->awake_votable, SUSPEND_DATA_VOTER, true, 0);
 		/* signal the read thread */
 		chip->data_ready = true;
 		wake_up_interruptible(&chip->qg_wait_q);
+		chip->suspend_data = false;
 	}
 
-	qg_dbg(chip, QG_DEBUG_PM, "fifo_done rt_status=%d suspend_data=%d data_ready=%d\n",
-			!!rt_status, chip->suspend_data, chip->data_ready);
-
-	chip->suspend_data = false;
-
 	return rc;
 }
 
diff --git a/drivers/power/supply/qcom/qpnp-smb5.c b/drivers/power/supply/qcom/qpnp-smb5.c
index b3f66d5..b91850d 100644
--- a/drivers/power/supply/qcom/qpnp-smb5.c
+++ b/drivers/power/supply/qcom/qpnp-smb5.c
@@ -158,7 +158,8 @@
 	int			chg_inhibit_thr_mv;
 	bool			no_battery;
 	bool			hvdcp_disable;
-	bool			auto_recharge_soc;
+	int			auto_recharge_soc;
+	int			auto_recharge_vbat_mv;
 	int			wd_bark_time;
 	int			batt_profile_fcc_ua;
 	int			batt_profile_fv_uv;
@@ -329,8 +330,23 @@
 		return -EINVAL;
 	}
 
-	chip->dt.auto_recharge_soc = of_property_read_bool(node,
-						"qcom,auto-recharge-soc");
+	chip->dt.auto_recharge_soc = -EINVAL;
+	rc = of_property_read_u32(node, "qcom,auto-recharge-soc",
+				&chip->dt.auto_recharge_soc);
+	if (!rc && (chip->dt.auto_recharge_soc < 0 ||
+			chip->dt.auto_recharge_soc > 100)) {
+		pr_err("qcom,auto-recharge-soc is incorrect\n");
+		return -EINVAL;
+	}
+	chg->auto_recharge_soc = chip->dt.auto_recharge_soc;
+
+	chip->dt.auto_recharge_vbat_mv = -EINVAL;
+	rc = of_property_read_u32(node, "qcom,auto-recharge-vbat-mv",
+				&chip->dt.auto_recharge_vbat_mv);
+	if (!rc && (chip->dt.auto_recharge_vbat_mv < 0)) {
+		pr_err("qcom,auto-recharge-vbat-mv is incorrect\n");
+		return -EINVAL;
+	}
 
 	chg->dcp_icl_ua = chip->dt.usb_icl_ua;
 
@@ -956,6 +972,7 @@
 	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT_MAX,
 	POWER_SUPPLY_PROP_CHARGE_CONTROL_LIMIT,
 	POWER_SUPPLY_PROP_CHARGE_COUNTER,
+	POWER_SUPPLY_PROP_RECHARGE_SOC,
 };
 
 static int smb5_batt_get_prop(struct power_supply *psy,
@@ -1045,6 +1062,9 @@
 	case POWER_SUPPLY_PROP_CHARGE_COUNTER:
 		rc = smblib_get_prop_batt_charge_counter(chg, val);
 		break;
+	case POWER_SUPPLY_PROP_RECHARGE_SOC:
+		val->intval = chg->auto_recharge_soc;
+		break;
 	default:
 		pr_err("batt power supply prop %d not supported\n", psp);
 		return -EINVAL;
@@ -1555,15 +1575,66 @@
 		return rc;
 	}
 
-	rc = smblib_masked_write(chg, CHGR_CFG2_REG,
-			SOC_BASED_RECHG_BIT,
-			chip->dt.auto_recharge_soc ? SOC_BASED_RECHG_BIT : 0);
+	rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
+				(chip->dt.auto_recharge_vbat_mv != -EINVAL) ?
+				VBAT_BASED_RECHG_BIT : 0);
 	if (rc < 0) {
-		dev_err(chg->dev, "Couldn't configure FG_UPDATE_CFG2_SEL_REG rc=%d\n",
+		dev_err(chg->dev, "Couldn't configure VBAT-rechg CHG_CFG2_REG rc=%d\n",
 			rc);
 		return rc;
 	}
 
+	/* program the auto-recharge VBAT threshold */
+	if (chip->dt.auto_recharge_vbat_mv != -EINVAL) {
+		u32 temp = VBAT_TO_VRAW_ADC(chip->dt.auto_recharge_vbat_mv);
+
+		temp = ((temp & 0xFF00) >> 8) | ((temp & 0xFF) << 8);
+		rc = smblib_batch_write(chg,
+			CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG, (u8 *)&temp, 2);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't configure ADC_RECHARGE_THRESHOLD REG rc=%d\n",
+				rc);
+			return rc;
+		}
+		/* Program the sample count for VBAT based recharge to 3 */
+		rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
+					NO_OF_SAMPLE_FOR_RCHG,
+					2 << NO_OF_SAMPLE_FOR_RCHG_SHIFT);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
+				rc);
+			return rc;
+		}
+	}
+
+	rc = smblib_masked_write(chg, CHGR_CFG2_REG, RECHG_MASK,
+				(chip->dt.auto_recharge_soc != -EINVAL) ?
+				SOC_BASED_RECHG_BIT : VBAT_BASED_RECHG_BIT);
+	if (rc < 0) {
+		dev_err(chg->dev, "Couldn't configure SOC-rechg CHG_CFG2_REG rc=%d\n",
+			rc);
+		return rc;
+	}
+
+	/* program the auto-recharge threshold */
+	if (chip->dt.auto_recharge_soc != -EINVAL) {
+		rc = smblib_write(chg, CHARGE_RCHG_SOC_THRESHOLD_CFG_REG,
+				(chip->dt.auto_recharge_soc * 255) / 100);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't configure CHG_RCHG_SOC_REG rc=%d\n",
+				rc);
+			return rc;
+		}
+		/* Program the sample count for SOC based recharge to 1 */
+		rc = smblib_masked_write(chg, CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG,
+						NO_OF_SAMPLE_FOR_RCHG, 0);
+		if (rc < 0) {
+			dev_err(chg->dev, "Couldn't configure CHGR_NO_SAMPLE_FOR_TERM_RCHG_CFG rc=%d\n",
+				rc);
+			return rc;
+		}
+	}
+
 	if (chg->sw_jeita_enabled) {
 		rc = smblib_disable_hw_jeita(chg, true);
 		if (rc < 0) {
@@ -1639,30 +1710,25 @@
 	[CHG_STATE_CHANGE_IRQ] = {
 		.name		= "chg-state-change",
 		.handler	= chg_state_change_irq_handler,
+		.wake		= true,
 	},
 	[STEP_CHG_STATE_CHANGE_IRQ] = {
 		.name		= "step-chg-state-change",
-		.handler	= default_irq_handler,
 	},
 	[STEP_CHG_SOC_UPDATE_FAIL_IRQ] = {
 		.name		= "step-chg-soc-update-fail",
-		.handler	= default_irq_handler,
 	},
 	[STEP_CHG_SOC_UPDATE_REQ_IRQ] = {
 		.name		= "step-chg-soc-update-req",
-		.handler	= default_irq_handler,
 	},
 	[FG_FVCAL_QUALIFIED_IRQ] = {
 		.name		= "fg-fvcal-qualified",
-		.handler	= default_irq_handler,
 	},
 	[VPH_ALARM_IRQ] = {
 		.name		= "vph-alarm",
-		.handler	= default_irq_handler,
 	},
 	[VPH_DROP_PRECHG_IRQ] = {
 		.name		= "vph-drop-prechg",
-		.handler	= default_irq_handler,
 	},
 	/* DCDC IRQs */
 	[OTG_FAIL_IRQ] = {
@@ -1671,19 +1737,17 @@
 	},
 	[OTG_OC_DISABLE_SW_IRQ] = {
 		.name		= "otg-oc-disable-sw",
-		.handler	= default_irq_handler,
 	},
 	[OTG_OC_HICCUP_IRQ] = {
 		.name		= "otg-oc-hiccup",
-		.handler	= default_irq_handler,
 	},
 	[BSM_ACTIVE_IRQ] = {
 		.name		= "bsm-active",
-		.handler	= default_irq_handler,
 	},
 	[HIGH_DUTY_CYCLE_IRQ] = {
 		.name		= "high-duty-cycle",
 		.handler	= high_duty_cycle_irq_handler,
+		.wake		= true,
 	},
 	[INPUT_CURRENT_LIMITING_IRQ] = {
 		.name		= "input-current-limiting",
@@ -1691,7 +1755,6 @@
 	},
 	[CONCURRENT_MODE_DISABLE_IRQ] = {
 		.name		= "concurrent-mode-disable",
-		.handler	= default_irq_handler,
 	},
 	[SWITCHER_POWER_OK_IRQ] = {
 		.name		= "switcher-power-ok",
@@ -1701,10 +1764,10 @@
 	[BAT_TEMP_IRQ] = {
 		.name		= "bat-temp",
 		.handler	= batt_temp_changed_irq_handler,
+		.wake		= true,
 	},
 	[ALL_CHNL_CONV_DONE_IRQ] = {
 		.name		= "all-chnl-conv-done",
-		.handler	= default_irq_handler,
 	},
 	[BAT_OV_IRQ] = {
 		.name		= "bat-ov",
@@ -1724,11 +1787,9 @@
 	},
 	[BUCK_OC_IRQ] = {
 		.name		= "buck-oc",
-		.handler	= default_irq_handler,
 	},
 	[VPH_OV_IRQ] = {
 		.name		= "vph-ov",
-		.handler	= default_irq_handler,
 	},
 	/* USB INPUT IRQs */
 	[USBIN_COLLAPSE_IRQ] = {
@@ -1750,23 +1811,24 @@
 	[USBIN_PLUGIN_IRQ] = {
 		.name		= "usbin-plugin",
 		.handler	= usb_plugin_irq_handler,
+		.wake           = true,
 	},
 	[USBIN_REVI_CHANGE_IRQ] = {
 		.name		= "usbin-revi-change",
-		.handler	= default_irq_handler,
 	},
 	[USBIN_SRC_CHANGE_IRQ] = {
 		.name		= "usbin-src-change",
 		.handler	= usb_source_change_irq_handler,
+		.wake           = true,
 	},
 	[USBIN_ICL_CHANGE_IRQ] = {
 		.name		= "usbin-icl-change",
 		.handler	= icl_change_irq_handler,
+		.wake           = true,
 	},
 	/* DC INPUT IRQs */
 	[DCIN_VASHDN_IRQ] = {
 		.name		= "dcin-vashdn",
-		.handler	= default_irq_handler,
 	},
 	[DCIN_UV_IRQ] = {
 		.name		= "dcin-uv",
@@ -1783,7 +1845,6 @@
 	},
 	[DCIN_REVI_IRQ] = {
 		.name		= "dcin-revi",
-		.handler	= default_irq_handler,
 	},
 	[DCIN_PON_IRQ] = {
 		.name		= "dcin-pon",
@@ -1797,14 +1858,15 @@
 	[TYPEC_OR_RID_DETECTION_CHANGE_IRQ] = {
 		.name		= "typec-or-rid-detect-change",
 		.handler	= typec_or_rid_detection_change_irq_handler,
+		.wake           = true,
 	},
 	[TYPEC_VPD_DETECT_IRQ] = {
 		.name		= "typec-vpd-detect",
-		.handler	= default_irq_handler,
 	},
 	[TYPEC_CC_STATE_CHANGE_IRQ] = {
 		.name		= "typec-cc-state-change",
 		.handler	= typec_state_change_irq_handler,
+		.wake           = true,
 	},
 	[TYPEC_VCONN_OC_IRQ] = {
 		.name		= "typec-vconn-oc",
@@ -1812,11 +1874,9 @@
 	},
 	[TYPEC_VBUS_CHANGE_IRQ] = {
 		.name		= "typec-vbus-change",
-		.handler	= default_irq_handler,
 	},
 	[TYPEC_ATTACH_DETACH_IRQ] = {
 		.name		= "typec-attach-detach",
-		.handler	= default_irq_handler,
 	},
 	[TYPEC_LEGACY_CABLE_DETECT_IRQ] = {
 		.name		= "typec-legacy-cable-detect",
@@ -1824,12 +1884,10 @@
 	},
 	[TYPEC_TRY_SNK_SRC_DETECT_IRQ] = {
 		.name		= "typec-try-snk-src-detect",
-		.handler	= default_irq_handler,
 	},
 	/* MISCELLANEOUS IRQs */
 	[WDOG_SNARL_IRQ] = {
 		.name		= "wdog-snarl",
-		.handler	= NULL,
 	},
 	[WDOG_BARK_IRQ] = {
 		.name		= "wdog-bark",
@@ -1837,7 +1895,6 @@
 	},
 	[AICL_FAIL_IRQ] = {
 		.name		= "aicl-fail",
-		.handler	= default_irq_handler,
 	},
 	[AICL_DONE_IRQ] = {
 		.name		= "aicl-done",
@@ -1845,24 +1902,19 @@
 	},
 	[SMB_EN_IRQ] = {
 		.name		= "smb-en",
-		.handler	= default_irq_handler,
 	},
 	[IMP_TRIGGER_IRQ] = {
 		.name		= "imp-trigger",
-		.handler	= default_irq_handler,
 	},
 	[TEMP_CHANGE_IRQ] = {
 		.name		= "temp-change",
-		.handler	= default_irq_handler,
 	},
 	[TEMP_CHANGE_SMB_IRQ] = {
 		.name		= "temp-change-smb",
-		.handler	= default_irq_handler,
 	},
 	/* FLASH */
 	[VREG_OK_IRQ] = {
 		.name		= "vreg-ok",
-		.handler	= schgm_flash_default_irq_handler,
 	},
 	[ILIM_S2_IRQ] = {
 		.name		= "ilim2-s2",
@@ -1870,15 +1922,12 @@
 	},
 	[ILIM_S1_IRQ] = {
 		.name		= "ilim1-s1",
-		.handler	= schgm_flash_default_irq_handler,
 	},
 	[VOUT_DOWN_IRQ] = {
 		.name		= "vout-down",
-		.handler	= schgm_flash_default_irq_handler,
 	},
 	[VOUT_UP_IRQ] = {
 		.name		= "vout-up",
-		.handler	= schgm_flash_default_irq_handler,
 	},
 	[FLASH_STATE_CHANGE_IRQ] = {
 		.name		= "flash-state-change",
@@ -1886,11 +1935,9 @@
 	},
 	[TORCH_REQ_IRQ] = {
 		.name		= "torch-req",
-		.handler	= schgm_flash_default_irq_handler,
 	},
 	[FLASH_EN_IRQ] = {
 		.name		= "flash-en",
-		.handler	= schgm_flash_default_irq_handler,
 	},
 };
 
diff --git a/drivers/power/supply/qcom/smb-lib.c b/drivers/power/supply/qcom/smb-lib.c
index 496a276..90745fd 100644
--- a/drivers/power/supply/qcom/smb-lib.c
+++ b/drivers/power/supply/qcom/smb-lib.c
@@ -4805,7 +4805,7 @@
 
 	if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) {
 		smblib_err(chg, "VCONN failed to enable after %d attempts\n",
-			   chg->otg_attempts - 1);
+			   chg->vconn_attempts - 1);
 		chg->vconn_en = false;
 		chg->vconn_attempts = 0;
 		goto unlock;
@@ -4829,14 +4829,7 @@
 		chg->vconn_attempts = 0;
 		goto unlock;
 	}
-
 	smblib_dbg(chg, PR_OTG, "VCONN OC fell after %dms\n", 2 * i + 1);
-	if (++chg->vconn_attempts > VCONN_MAX_ATTEMPTS) {
-		smblib_err(chg, "VCONN failed to enable after %d attempts\n",
-			   chg->vconn_attempts - 1);
-		chg->vconn_en = false;
-		goto unlock;
-	}
 
 	rc = _smblib_vconn_regulator_enable(chg->vconn_vreg->rdev);
 	if (rc < 0) {
diff --git a/drivers/power/supply/qcom/smb1351-charger.c b/drivers/power/supply/qcom/smb1351-charger.c
index dfedece..63d57fe 100644
--- a/drivers/power/supply/qcom/smb1351-charger.c
+++ b/drivers/power/supply/qcom/smb1351-charger.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2016-2017 The Linux Foundation. All rights reserved.
+/* Copyright (c) 2016-2018 The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -15,6 +15,7 @@
 #include <linux/i2c.h>
 #include <linux/debugfs.h>
 #include <linux/errno.h>
+#include <linux/extcon.h>
 #include <linux/module.h>
 #include <linux/interrupt.h>
 #include <linux/slab.h>
@@ -376,6 +377,7 @@
 #define USB2_MAX_CURRENT_MA			500
 #define USB3_MIN_CURRENT_MA			150
 #define USB3_MAX_CURRENT_MA			900
+#define DCP_MAX_CURRENT_MA			1500
 #define SMB1351_IRQ_REG_COUNT			8
 #define SMB1351_CHG_PRE_MIN_MA			100
 #define SMB1351_CHG_FAST_MIN_MA			1000
@@ -424,6 +426,12 @@
 	[SMB1351] = "SMB1351",
 };
 
+static const unsigned int smb1351_extcon_cable[] = {
+	EXTCON_USB,
+	EXTCON_USB_HOST,
+	EXTCON_NONE,
+};
+
 struct smb1351_charger {
 	struct i2c_client	*client;
 	struct device		*dev;
@@ -472,6 +480,7 @@
 	enum chip_version	version;
 
 	/* psy */
+	struct power_supply_desc	usb_psy_d;
 	struct power_supply	*usb_psy;
 	int			usb_psy_ma;
 	struct power_supply	*bms_psy;
@@ -505,6 +514,12 @@
 	/* pinctrl parameters */
 	const char		*pinctrl_state_name;
 	struct pinctrl		*smb_pinctrl;
+
+	/* standalone */
+	bool			charger_present;
+	struct extcon_dev       *extcon;
+	struct regulator	*dpdm_reg;
+	enum power_supply_type	charger_type;
 };
 
 struct smb_irq_info {
@@ -633,6 +648,65 @@
 	return rc;
 }
 
+static int smb1351_get_closest_usb_setpoint(int val)
+{
+	int i;
+
+	for (i = ARRAY_SIZE(usb_chg_current) - 1; i >= 0; i--) {
+		if (usb_chg_current[i] <= val)
+			break;
+	}
+	if (i < 0)
+		i = 0;
+
+	if (i >= ARRAY_SIZE(usb_chg_current) - 1)
+		return ARRAY_SIZE(usb_chg_current) - 1;
+
+	/* check what is closer, i or i + 1 */
+	if (abs(usb_chg_current[i] - val) < abs(usb_chg_current[i + 1] - val))
+		return i;
+	else
+		return i + 1;
+}
+
+static int smb1351_request_dpdm(struct smb1351_charger *chip, bool enable)
+{
+	int rc = 0;
+
+	/* fetch the DPDM regulator */
+	if (!chip->dpdm_reg && of_get_property(chip->dev->of_node,
+				"dpdm-supply", NULL)) {
+		chip->dpdm_reg = devm_regulator_get(chip->dev, "dpdm");
+		if (IS_ERR(chip->dpdm_reg)) {
+			rc = PTR_ERR(chip->dpdm_reg);
+			pr_err("Couldn't get dpdm regulator rc=%d\n",
+					rc);
+			chip->dpdm_reg = NULL;
+			return rc;
+		}
+	}
+
+	if (enable) {
+		if (chip->dpdm_reg && !regulator_is_enabled(chip->dpdm_reg)) {
+			pr_err("enabling DPDM regulator\n");
+			rc = regulator_enable(chip->dpdm_reg);
+			if (rc < 0)
+				pr_err("Couldn't enable dpdm regulator rc=%d\n",
+					rc);
+		}
+	} else {
+		if (chip->dpdm_reg && regulator_is_enabled(chip->dpdm_reg)) {
+			pr_err("disabling DPDM regulator\n");
+			rc = regulator_disable(chip->dpdm_reg);
+			if (rc < 0)
+				pr_err("Couldn't disable dpdm regulator rc=%d\n",
+					rc);
+		}
+	}
+
+	return rc;
+}
+
 static int smb1351_usb_suspend(struct smb1351_charger *chip, int reason,
 					bool suspend)
 {
@@ -1290,6 +1364,75 @@
 	return rc;
 }
 
+static char *smb1351_usb_supplicants[] = {
+	"bms",
+};
+
+static enum power_supply_property smb1351_usb_properties[] = {
+	POWER_SUPPLY_PROP_PRESENT,
+	POWER_SUPPLY_PROP_ONLINE,
+	POWER_SUPPLY_PROP_CURRENT_MAX,
+	POWER_SUPPLY_PROP_TYPE,
+};
+
+static int smb1351_usb_get_property(struct power_supply *psy,
+		enum power_supply_property psp,
+				  union power_supply_propval *val)
+{
+	struct smb1351_charger *chip = power_supply_get_drvdata(psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		val->intval = chip->usb_psy_ma * 1000;
+		break;
+	case POWER_SUPPLY_PROP_PRESENT:
+		val->intval = chip->chg_present;
+		break;
+	case POWER_SUPPLY_PROP_ONLINE:
+		val->intval = chip->chg_present && !chip->usb_suspended_status;
+		break;
+	case POWER_SUPPLY_PROP_TYPE:
+		val->intval = chip->charger_type;
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static int smb1351_usb_set_property(struct power_supply *psy,
+				  enum power_supply_property psp,
+				  const union power_supply_propval *val)
+{
+	struct smb1351_charger *chip = power_supply_get_drvdata(psy);
+
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		chip->usb_psy_ma = val->intval / 1000;
+		smb1351_enable_volatile_writes(chip);
+		smb1351_set_usb_chg_current(chip, chip->usb_psy_ma);
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	power_supply_changed(psy);
+	return 0;
+}
+
+static int smb1351_usb_is_writeable(struct power_supply *psy,
+					enum power_supply_property psp)
+{
+	switch (psp) {
+	case POWER_SUPPLY_PROP_CURRENT_MAX:
+		return 1;
+	default:
+		break;
+	}
+
+	return 0;
+}
+
 static int smb1351_batt_property_is_writeable(struct power_supply *psy,
 					enum power_supply_property psp)
 {
@@ -1535,27 +1678,6 @@
 	return 0;
 }
 
-static int smb1351_get_closest_usb_setpoint(int val)
-{
-	int i;
-
-	for (i = ARRAY_SIZE(usb_chg_current) - 1; i >= 0; i--) {
-		if (usb_chg_current[i] <= val)
-			break;
-	}
-	if (i < 0)
-		i = 0;
-
-	if (i >= ARRAY_SIZE(usb_chg_current) - 1)
-		return ARRAY_SIZE(usb_chg_current) - 1;
-
-	/* check what is closer, i or i + 1 */
-	if (abs(usb_chg_current[i] - val) < abs(usb_chg_current[i + 1] - val))
-		return i;
-	else
-		return i + 1;
-}
-
 static bool smb1351_is_input_current_limited(struct smb1351_charger *chip)
 {
 	int rc;
@@ -2001,10 +2123,10 @@
 static int smb1351_apsd_complete_handler(struct smb1351_charger *chip,
 						u8 status)
 {
-	int rc;
+	int rc, usb_psy_ma = 0;
 	u8 reg = 0;
-	union power_supply_propval prop = {0, };
 	enum power_supply_type type = POWER_SUPPLY_TYPE_UNKNOWN;
+	union extcon_property_value val;
 
 	/*
 	 * If apsd is disabled, charger detection is done by
@@ -2055,18 +2177,12 @@
 						type, chip->chg_present);
 		if (!chip->battery_missing && !chip->apsd_rerun) {
 			if (type == POWER_SUPPLY_TYPE_USB) {
-				pr_debug("Setting usb psy dp=f dm=f SDP and rerun\n");
-				prop.intval = POWER_SUPPLY_DP_DM_DPF_DMF;
-				power_supply_set_property(chip->usb_psy,
-						POWER_SUPPLY_PROP_DP_DM, &prop);
+				smb1351_request_dpdm(chip, false);
+				smb1351_request_dpdm(chip, true);
 				chip->apsd_rerun = true;
 				rerun_apsd(chip);
 				return 0;
 			}
-			pr_debug("Set usb psy dp=f dm=f DCP and no rerun\n");
-			prop.intval = POWER_SUPPLY_DP_DM_DPF_DMF;
-			power_supply_set_property(chip->usb_psy,
-					POWER_SUPPLY_PROP_DP_DM, &prop);
 		}
 		/*
 		 * If defined force hvdcp 2p0 property,
@@ -2087,35 +2203,33 @@
 					msecs_to_jiffies(HVDCP_NOTIFY_MS));
 		}
 
-		prop.intval = type;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_TYPE, &prop);
-		/*
-		 * SMB is now done sampling the D+/D- lines,
-		 * indicate USB driver
-		 */
-		pr_debug("updating usb_psy present=%d\n", chip->chg_present);
-		prop.intval = chip->chg_present;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_PRESENT,
-				&prop);
+		chip->charger_type = type;
+		if (type == POWER_SUPPLY_TYPE_USB
+				|| type == POWER_SUPPLY_TYPE_USB_CDP) {
+			val.intval = true;
+			extcon_set_property(chip->extcon, EXTCON_USB,
+						EXTCON_PROP_USB_SS, val);
+			extcon_set_cable_state_(chip->extcon, EXTCON_USB, true);
+		}
 		chip->apsd_rerun = false;
+
+		/* set the charge current as required */
+		if (type == POWER_SUPPLY_TYPE_USB)
+			usb_psy_ma = USB2_MIN_CURRENT_MA;
+		else /* DCP */
+			usb_psy_ma = DCP_MAX_CURRENT_MA;
+
+		chip->usb_psy_ma = usb_psy_ma;
+		smb1351_enable_volatile_writes(chip);
+		rc = smb1351_set_usb_chg_current(chip, chip->usb_psy_ma);
+		if (rc < 0)
+			pr_err("Failed to set USB current rc=%d\n", rc);
+
 	} else if (!chip->apsd_rerun) {
 		/* Handle Charger removal */
-		prop.intval = POWER_SUPPLY_TYPE_UNKNOWN;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_TYPE, &prop);
-
-		chip->chg_present = false;
-		prop.intval = chip->chg_present;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_PRESENT,
-				&prop);
-
-		pr_debug("Set usb psy dm=r df=r\n");
-		prop.intval = POWER_SUPPLY_DP_DM_DPR_DMR;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_DP_DM, &prop);
+		chip->charger_type = POWER_SUPPLY_TYPE_UNKNOWN;
+		extcon_set_cable_state_(chip->extcon, EXTCON_USB, false);
+		smb1351_request_dpdm(chip, false);
 	}
 
 	return 0;
@@ -2163,42 +2277,7 @@
 
 static int smb1351_usbin_uv_handler(struct smb1351_charger *chip, u8 status)
 {
-	union power_supply_propval pval = {0, };
-
-	/* use this to detect USB insertion only if !apsd */
-	if (chip->disable_apsd) {
-		/*
-		 * If APSD is disabled, src det interrupt won't trigger.
-		 * Hence use usbin_uv for removal and insertion notification
-		 */
-		if (status == 0) {
-			chip->chg_present = true;
-			pr_debug("updating usb_psy present=%d\n",
-						chip->chg_present);
-			pval.intval = POWER_SUPPLY_TYPE_USB;
-			power_supply_set_property(chip->usb_psy,
-					POWER_SUPPLY_PROP_TYPE, &pval);
-
-			pval.intval = chip->chg_present;
-			power_supply_set_property(chip->usb_psy,
-					POWER_SUPPLY_PROP_PRESENT,
-					&pval);
-		} else {
-			chip->chg_present = false;
-
-			pval.intval = POWER_SUPPLY_TYPE_UNKNOWN;
-			power_supply_set_property(chip->usb_psy,
-					POWER_SUPPLY_PROP_TYPE, &pval);
-
-			pr_debug("updating usb_psy present=%d\n",
-							chip->chg_present);
-			pval.intval = chip->chg_present;
-			power_supply_set_property(chip->usb_psy,
-					POWER_SUPPLY_PROP_PRESENT,
-					&pval);
-		}
-		return 0;
-	}
+	smb1351_request_dpdm(chip, !!status);
 
 	if (status) {
 		cancel_delayed_work_sync(&chip->hvdcp_det_work);
@@ -2218,24 +2297,19 @@
 {
 	int rc;
 	u8 reg = 0;
-	union power_supply_propval pval = {0, };
 
 	rc = smb1351_read_reg(chip, IRQ_E_REG, &reg);
 	if (rc)
 		pr_err("Couldn't read IRQ_E rc = %d\n", rc);
 
 	if (status != 0) {
-		chip->chg_present = false;
 		chip->usbin_ov = true;
+		chip->charger_type = POWER_SUPPLY_TYPE_UNKNOWN;
+		if (chip->chg_present)
+			extcon_set_cable_state_(chip->extcon, EXTCON_USB,
+						false);
+		chip->chg_present = false;
 
-		pval.intval = POWER_SUPPLY_TYPE_UNKNOWN;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_TYPE, &pval);
-
-		pval.intval = chip->chg_present;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_PRESENT,
-				&pval);
 	} else {
 		chip->usbin_ov = false;
 		if (reg & IRQ_USBIN_UV_BIT)
@@ -2244,13 +2318,6 @@
 			smb1351_apsd_complete_handler(chip, 1);
 	}
 
-	if (chip->usb_psy) {
-		pval.intval = status ? POWER_SUPPLY_HEALTH_OVERVOLTAGE
-					: POWER_SUPPLY_HEALTH_GOOD;
-		power_supply_set_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_HEALTH, &pval);
-		pr_debug("chip ov status is %d\n", pval.intval);
-	}
 	pr_debug("chip->chg_present = %d\n", chip->chg_present);
 
 	return 0;
@@ -2319,6 +2386,21 @@
 	return 0;
 }
 
+static int smb1351_rid_handler(struct smb1351_charger *chip,
+						u8 status)
+{
+	union extcon_property_value val;
+
+	if (!!status) {
+		val.intval = true;
+		extcon_set_property(chip->extcon, EXTCON_USB_HOST,
+					EXTCON_PROP_USB_SS, val);
+	}
+	extcon_set_cable_state_(chip->extcon, EXTCON_USB_HOST, !!status);
+
+	return 0;
+}
+
 static struct irq_handler_info handlers[] = {
 	[0] = {
 		.stat_reg	= IRQ_A_REG,
@@ -2413,6 +2495,7 @@
 			{	.name	 = "otg_oc_retry",
 			},
 			{	.name	 = "rid",
+				.smb_irq = smb1351_rid_handler,
 			},
 			{	.name	 = "otg_fail",
 			},
@@ -2524,30 +2607,21 @@
 {
 	struct smb1351_charger *chip = power_supply_get_drvdata(psy);
 	union power_supply_propval prop = {0,};
-	int rc, current_limit = 0, online = 0;
+	int rc, current_limit = 0;
 
 	if (chip->bms_psy_name)
 		chip->bms_psy =
 			power_supply_get_by_name((char *)chip->bms_psy_name);
 
 	rc = power_supply_get_property(chip->usb_psy,
-				POWER_SUPPLY_PROP_ONLINE, &prop);
-	if (rc)
-		pr_err("Couldn't read USB online property, rc=%d\n", rc);
-	else
-		online = prop.intval;
-
-	rc = power_supply_get_property(chip->usb_psy,
 				POWER_SUPPLY_PROP_CURRENT_MAX, &prop);
 	if (rc)
 		pr_err("Couldn't read USB current_max property, rc=%d\n", rc);
 	else
 		current_limit = prop.intval / 1000;
 
-	pr_debug("online = %d, current_limit = %d\n", online, current_limit);
+	pr_debug("current_limit = %d\n", current_limit);
 
-	smb1351_enable_volatile_writes(chip);
-	smb1351_set_usb_chg_current(chip, current_limit);
 
 	pr_debug("updating batt psy\n");
 }
@@ -3002,28 +3076,65 @@
 {
 	int rc;
 	struct smb1351_charger *chip;
-	struct power_supply *usb_psy;
 	struct power_supply_config batt_psy_cfg = {};
+	struct power_supply_config usb_psy_cfg = {};
 	u8 reg = 0;
 
-	usb_psy = power_supply_get_by_name("usb");
-	if (!usb_psy) {
-		pr_debug("USB psy not found; deferring probe\n");
-		return -EPROBE_DEFER;
-	}
-
 	chip = devm_kzalloc(&client->dev, sizeof(*chip), GFP_KERNEL);
 	if (!chip)
 		return -ENOMEM;
 
 	chip->client = client;
 	chip->dev = &client->dev;
-	chip->usb_psy = usb_psy;
 	chip->fake_battery_soc = -EINVAL;
+
+	chip->extcon = devm_extcon_dev_allocate(chip->dev,
+					smb1351_extcon_cable);
+	if (IS_ERR(chip->extcon)) {
+		pr_err("failed to allocate extcon device\n");
+		rc = PTR_ERR(chip->extcon);
+		return rc;
+	}
+
+	rc = devm_extcon_dev_register(chip->dev, chip->extcon);
+	if (rc) {
+		pr_err("failed to register extcon device\n");
+		return rc;
+	}
+
+	rc = extcon_set_property_capability(chip->extcon,
+			EXTCON_USB, EXTCON_PROP_USB_SS);
+	rc |= extcon_set_property_capability(chip->extcon,
+			EXTCON_USB_HOST, EXTCON_PROP_USB_SS);
+	if (rc < 0) {
+		pr_err("Failed to register extcon capability rc=%d\n", rc);
+		return rc;
+	}
+
+	chip->usb_psy_d.name = "usb";
+	chip->usb_psy_d.type = POWER_SUPPLY_TYPE_USB;
+	chip->usb_psy_d.get_property = smb1351_usb_get_property;
+	chip->usb_psy_d.set_property = smb1351_usb_set_property;
+	chip->usb_psy_d.properties = smb1351_usb_properties;
+	chip->usb_psy_d.num_properties = ARRAY_SIZE(smb1351_usb_properties);
+	chip->usb_psy_d.property_is_writeable = smb1351_usb_is_writeable;
+
+	usb_psy_cfg.drv_data = chip;
+	usb_psy_cfg.supplied_to = smb1351_usb_supplicants;
+	usb_psy_cfg.num_supplicants = ARRAY_SIZE(smb1351_usb_supplicants);
+
+	chip->usb_psy = devm_power_supply_register(chip->dev,
+				&chip->usb_psy_d, &usb_psy_cfg);
+	if (IS_ERR(chip->usb_psy)) {
+		pr_err("Unable to register usb_psy rc = %ld\n",
+			PTR_ERR(chip->usb_psy));
+		rc = PTR_ERR(chip->usb_psy);
+		return rc;
+	}
+
 	INIT_DELAYED_WORK(&chip->chg_remove_work, smb1351_chg_remove_work);
 	INIT_DELAYED_WORK(&chip->hvdcp_det_work, smb1351_hvdcp_det_work);
 	device_init_wakeup(chip->dev, true);
-
 	/* probe the device to check if its actually connected */
 	rc = smb1351_read_reg(chip, CHG_REVISION_REG, &reg);
 	if (rc) {
diff --git a/drivers/power/supply/qcom/smb5-lib.c b/drivers/power/supply/qcom/smb5-lib.c
index dbadd95..46cedb3 100644
--- a/drivers/power/supply/qcom/smb5-lib.c
+++ b/drivers/power/supply/qcom/smb5-lib.c
@@ -62,11 +62,15 @@
 	return regmap_write(chg->regmap, addr, val);
 }
 
+int smblib_batch_write(struct smb_charger *chg, u16 addr, u8 *val,
+			int count)
+{
+	return regmap_bulk_write(chg->regmap, addr, val, count);
+}
+
 int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val)
 {
-
 	return regmap_update_bits(chg->regmap, addr, mask, val);
-
 }
 
 int smblib_get_jeita_cc_delta(struct smb_charger *chg, int *cc_delta_ua)
@@ -707,20 +711,21 @@
 	int rc;
 	union power_supply_propval val;
 
-	if (!chg->suspend_input_on_debug_batt)
-		return;
-
 	rc = power_supply_get_property(chg->bms_psy,
 			POWER_SUPPLY_PROP_DEBUG_BATTERY, &val);
 	if (rc < 0) {
 		smblib_err(chg, "Couldn't get debug battery prop rc=%d\n", rc);
 		return;
 	}
-
-	vote(chg->usb_icl_votable, DEBUG_BOARD_VOTER, val.intval, 0);
-	vote(chg->dc_suspend_votable, DEBUG_BOARD_VOTER, val.intval, 0);
-	if (val.intval)
-		pr_info("Input suspended: Fake battery\n");
+	if (chg->suspend_input_on_debug_batt) {
+		vote(chg->usb_icl_votable, DEBUG_BOARD_VOTER, val.intval, 0);
+		vote(chg->dc_suspend_votable, DEBUG_BOARD_VOTER, val.intval, 0);
+		if (val.intval)
+			pr_info("Input suspended: Fake battery\n");
+	} else {
+		vote(chg->chg_disable_votable, DEBUG_BOARD_VOTER,
+					val.intval, 0);
+	}
 }
 
 int smblib_rerun_apsd_if_required(struct smb_charger *chg)
diff --git a/drivers/power/supply/qcom/smb5-lib.h b/drivers/power/supply/qcom/smb5-lib.h
index d7b9a17..335764e 100644
--- a/drivers/power/supply/qcom/smb5-lib.h
+++ b/drivers/power/supply/qcom/smb5-lib.h
@@ -70,6 +70,8 @@
 #define BOOST_BACK_STORM_COUNT	3
 #define WEAK_CHG_STORM_COUNT	8
 
+#define VBAT_TO_VRAW_ADC(v)		div_u64((u64)v * 1000000UL, 194637UL)
+
 enum smb_mode {
 	PARALLEL_MASTER = 0,
 	PARALLEL_SLAVE,
@@ -344,6 +346,7 @@
 	bool			use_extcon;
 	bool			otg_present;
 	int			hw_max_icl_ua;
+	int			auto_recharge_soc;
 
 	/* workaround flag */
 	u32			wa_flags;
@@ -372,6 +375,8 @@
 int smblib_read(struct smb_charger *chg, u16 addr, u8 *val);
 int smblib_masked_write(struct smb_charger *chg, u16 addr, u8 mask, u8 val);
 int smblib_write(struct smb_charger *chg, u16 addr, u8 val);
+int smblib_batch_write(struct smb_charger *chg, u16 addr, u8 *val, int count);
+int smblib_batch_read(struct smb_charger *chg, u16 addr, u8 *val, int count);
 
 int smblib_get_charge_param(struct smb_charger *chg,
 			    struct smb_chg_param *param, int *val_u);
diff --git a/drivers/power/supply/qcom/smb5-reg.h b/drivers/power/supply/qcom/smb5-reg.h
index 9a418c8..afc45ab 100644
--- a/drivers/power/supply/qcom/smb5-reg.h
+++ b/drivers/power/supply/qcom/smb5-reg.h
@@ -66,11 +66,17 @@
 #define CHARGING_ENABLE_CMD_BIT			BIT(0)
 
 #define CHGR_CFG2_REG				(CHGR_BASE + 0x51)
-#define SOC_BASED_RECHG_BIT			BIT(1)
+#define RECHG_MASK				GENMASK(2, 1)
+#define VBAT_BASED_RECHG_BIT			BIT(2)
+#define SOC_BASED_RECHG_BIT			GENMASK(2, 1)
 #define CHARGER_INHIBIT_BIT			BIT(0)
 
 #define CHGR_FAST_CHARGE_CURRENT_CFG_REG	(CHGR_BASE + 0x61)
 
+#define CHGR_NO_SAMPLE_TERM_RCHG_CFG_REG	(CHGR_BASE + 0x6B)
+#define NO_OF_SAMPLE_FOR_RCHG_SHIFT		2
+#define NO_OF_SAMPLE_FOR_RCHG			GENMASK(3, 2)
+
 #define CHGR_FLOAT_VOLTAGE_CFG_REG		(CHGR_BASE + 0x70)
 
 #define CHARGE_INHIBIT_THRESHOLD_CFG_REG	(CHGR_BASE + 0x72)
@@ -80,6 +86,12 @@
 #define INHIBIT_ANALOG_VFLT_MINUS_200MV		2
 #define INHIBIT_ANALOG_VFLT_MINUS_300MV		3
 
+#define CHARGE_RCHG_SOC_THRESHOLD_CFG_REG	(CHGR_BASE + 0x7D)
+
+#define CHGR_ADC_RECHARGE_THRESHOLD_MSB_REG	(CHGR_BASE + 0x7E)
+
+#define CHGR_ADC_RECHARGE_THRESHOLD_LSB_REG	(CHGR_BASE + 0x7F)
+
 #define JEITA_EN_CFG_REG			(CHGR_BASE + 0x90)
 #define JEITA_EN_HOT_SL_FCV_BIT			BIT(3)
 #define JEITA_EN_COLD_SL_FCV_BIT		BIT(2)
diff --git a/drivers/pwm/pwm-qti-lpg.c b/drivers/pwm/pwm-qti-lpg.c
index 328f4b6..85a5ea0 100644
--- a/drivers/pwm/pwm-qti-lpg.c
+++ b/drivers/pwm/pwm-qti-lpg.c
@@ -28,6 +28,7 @@
 
 #define REG_SIZE_PER_LPG	0x100
 
+#define REG_LPG_PERPH_SUBTYPE		0x05
 #define REG_LPG_PWM_SIZE_CLK		0x41
 #define REG_LPG_PWM_FREQ_PREDIV_CLK	0x42
 #define REG_LPG_PWM_TYPE_CONFIG		0x43
@@ -36,9 +37,15 @@
 #define REG_LPG_ENABLE_CONTROL		0x46
 #define REG_LPG_PWM_SYNC		0x47
 
+/* REG_LPG_PERPH_SUBTYPE */
+#define SUBTYPE_PWM			0x0b
+#define SUBTYPE_LPG_LITE		0x11
+
 /* REG_LPG_PWM_SIZE_CLK */
-#define LPG_PWM_SIZE_MASK		BIT(4)
-#define LPG_PWM_SIZE_SHIFT		4
+#define LPG_PWM_SIZE_MASK_LPG		BIT(4)
+#define LPG_PWM_SIZE_MASK_PWM		BIT(2)
+#define LPG_PWM_SIZE_SHIFT_LPG		4
+#define LPG_PWM_SIZE_SHIFT_PWM		2
 #define LPG_PWM_CLK_FREQ_SEL_MASK	GENMASK(1, 0)
 
 /* REG_LPG_PWM_FREQ_PREDIV_CLK */
@@ -95,6 +102,7 @@
 	u32				lpg_idx;
 	u32				reg_base;
 	u8				src_sel;
+	u8				subtype;
 	int				current_period_ns;
 	int				current_duty_ns;
 };
@@ -108,6 +116,23 @@
 	u32			num_lpgs;
 };
 
+static int qpnp_lpg_read(struct qpnp_lpg_channel *lpg, u16 addr, u8 *val)
+{
+	int rc;
+	unsigned int tmp;
+
+	mutex_lock(&lpg->chip->bus_lock);
+	rc = regmap_read(lpg->chip->regmap, lpg->reg_base + addr, &tmp);
+	if (rc < 0)
+		dev_err(lpg->chip->dev, "Read addr 0x%x failed, rc=%d\n",
+				lpg->reg_base + addr, rc);
+	else
+		*val = (u8)tmp;
+	mutex_unlock(&lpg->chip->bus_lock);
+
+	return rc;
+}
+
 static int qpnp_lpg_write(struct qpnp_lpg_channel *lpg, u16 addr, u8 val)
 {
 	int rc;
@@ -166,10 +191,24 @@
 	return -EINVAL;
 }
 
+static int qpnp_lpg_set_glitch_removal(struct qpnp_lpg_channel *lpg, bool en)
+{
+	int rc;
+	u8 mask, val;
+
+	val = en ? LPG_PWM_EN_GLITCH_REMOVAL_MASK : 0;
+	mask = LPG_PWM_EN_GLITCH_REMOVAL_MASK;
+	rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_TYPE_CONFIG, mask, val);
+	if (rc < 0)
+		dev_err(lpg->chip->dev, "Write LPG_PWM_TYPE_CONFIG failed, rc=%d\n",
+							rc);
+	return rc;
+}
+
 static int qpnp_lpg_set_pwm_config(struct qpnp_lpg_channel *lpg)
 {
 	int rc;
-	u8 val, mask;
+	u8 val, mask, shift;
 	int pwm_size_idx, pwm_clk_idx, prediv_idx, clk_exp_idx;
 
 	pwm_size_idx = __find_index_in_array(lpg->pwm_config.pwm_size,
@@ -187,8 +226,16 @@
 
 	/* pwm_clk_idx is 1 bit lower than the register value */
 	pwm_clk_idx += 1;
-	val = pwm_size_idx << LPG_PWM_SIZE_SHIFT | pwm_clk_idx;
-	mask = LPG_PWM_SIZE_MASK | LPG_PWM_CLK_FREQ_SEL_MASK;
+	if (lpg->subtype == SUBTYPE_PWM) {
+		shift = LPG_PWM_SIZE_SHIFT_PWM;
+		mask = LPG_PWM_SIZE_MASK_PWM;
+	} else {
+		shift = LPG_PWM_SIZE_SHIFT_LPG;
+		mask = LPG_PWM_SIZE_MASK_LPG;
+	}
+
+	val = pwm_size_idx << shift | pwm_clk_idx;
+	mask |= LPG_PWM_CLK_FREQ_SEL_MASK;
 	rc = qpnp_lpg_masked_write(lpg, REG_LPG_PWM_SIZE_CLK, mask, val);
 	if (rc < 0) {
 		dev_err(lpg->chip->dev, "Write LPG_PWM_SIZE_CLK failed, rc=%d\n",
@@ -377,6 +424,13 @@
 		return -ENODEV;
 	}
 
+	rc = qpnp_lpg_set_glitch_removal(lpg, true);
+	if (rc < 0) {
+		dev_err(lpg->chip->dev, "Enable glitch-removal failed, rc=%d\n",
+							rc);
+		return rc;
+	}
+
 	mask = LPG_PWM_SRC_SELECT_MASK | LPG_EN_LPG_OUT_BIT;
 	val = lpg->src_sel << LPG_PWM_SRC_SELECT_SHIFT | LPG_EN_LPG_OUT_BIT;
 
@@ -405,9 +459,16 @@
 	val = lpg->src_sel << LPG_PWM_SRC_SELECT_SHIFT;
 
 	rc = qpnp_lpg_masked_write(lpg, REG_LPG_ENABLE_CONTROL, mask, val);
-	if (rc < 0)
+	if (rc < 0) {
 		dev_err(pwm_chip->dev, "Disable PWM output failed for channel %d, rc=%d\n",
 						lpg->lpg_idx, rc);
+		return;
+	}
+
+	rc = qpnp_lpg_set_glitch_removal(lpg, false);
+	if (rc < 0)
+		dev_err(lpg->chip->dev, "Disable glitch-removal failed, rc=%d\n",
+							rc);
 }
 
 #ifdef CONFIG_DEBUG_FS
@@ -490,6 +551,12 @@
 		chip->lpgs[i].lpg_idx = i;
 		chip->lpgs[i].reg_base = base + i * REG_SIZE_PER_LPG;
 		chip->lpgs[i].src_sel = PWM_OUTPUT;
+		rc = qpnp_lpg_read(&chip->lpgs[i], REG_LPG_PERPH_SUBTYPE,
+				&chip->lpgs[i].subtype);
+		if (rc < 0) {
+			dev_err(chip->dev, "Read subtype failed, rc=%d\n", rc);
+			return rc;
+		}
 	}
 
 	return rc;
@@ -511,16 +578,15 @@
 		return -EINVAL;
 	}
 
+	mutex_init(&chip->bus_lock);
 	rc = qpnp_lpg_parse_dt(chip);
 	if (rc < 0) {
 		dev_err(chip->dev, "Devicetree properties parsing failed, rc=%d\n",
 				rc);
-		return rc;
+		goto destroy;
 	}
 
 	dev_set_drvdata(chip->dev, chip);
-
-	mutex_init(&chip->bus_lock);
 	chip->pwm_chip.dev = chip->dev;
 	chip->pwm_chip.base = -1;
 	chip->pwm_chip.npwm = chip->num_lpgs;
@@ -529,9 +595,12 @@
 	rc = pwmchip_add(&chip->pwm_chip);
 	if (rc < 0) {
 		dev_err(chip->dev, "Add pwmchip failed, rc=%d\n", rc);
-		mutex_destroy(&chip->bus_lock);
+		goto destroy;
 	}
 
+	return 0;
+destroy:
+	mutex_destroy(&chip->bus_lock);
 	return rc;
 }
 
diff --git a/drivers/regulator/qpnp-lcdb-regulator.c b/drivers/regulator/qpnp-lcdb-regulator.c
index 9fc5a4a..79d7cba 100644
--- a/drivers/regulator/qpnp-lcdb-regulator.c
+++ b/drivers/regulator/qpnp-lcdb-regulator.c
@@ -998,12 +998,13 @@
 #define VOLTAGE_MIN_STEP_50_MV			4950
 #define VOLTAGE_STEP_100_MV			100
 #define VOLTAGE_STEP_50_MV			50
+#define VOLTAGE_STEP_25_MV			25
 #define VOLTAGE_STEP_50MV_OFFSET		0xA
 static int qpnp_lcdb_set_bst_voltage(struct qpnp_lcdb *lcdb,
 					int voltage_mv, u8 type)
 {
 	int rc = 0;
-	u8 val, mask = 0;
+	u8 val, voltage_step, mask = 0;
 	int bst_voltage_mv;
 	u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
 	struct ldo_regulator *ldo = &lcdb->ldo;
@@ -1020,10 +1021,16 @@
 		bst_voltage_mv = MAX_BST_VOLTAGE_MV;
 
 	if (bst_voltage_mv != bst->voltage_mv) {
+		if (pmic_subtype == PM660L_SUBTYPE) {
+			mask = PM660_BST_OUTPUT_VOLTAGE_MASK;
+			voltage_step = VOLTAGE_STEP_50_MV;
+		} else {
+			mask =  BST_OUTPUT_VOLTAGE_MASK;
+			voltage_step = VOLTAGE_STEP_25_MV;
+		}
+
 		val = DIV_ROUND_UP(bst_voltage_mv - MIN_BST_VOLTAGE_MV,
-						VOLTAGE_STEP_50_MV);
-		mask = (pmic_subtype == PM660L_SUBTYPE) ?
-			PM660_BST_OUTPUT_VOLTAGE_MASK : BST_OUTPUT_VOLTAGE_MASK;
+							voltage_step);
 		rc = qpnp_lcdb_masked_write(lcdb, lcdb->base +
 					LCDB_BST_OUTPUT_VOLTAGE_REG,
 					mask, val);
@@ -1044,7 +1051,7 @@
 					int *voltage_mv)
 {
 	int rc;
-	u8 val, mask = 0;
+	u8 val, voltage_step, mask = 0;
 	u16 pmic_subtype = lcdb->pmic_rev_id->pmic_subtype;
 
 	rc = qpnp_lcdb_read(lcdb, lcdb->base + LCDB_BST_OUTPUT_VOLTAGE_REG,
@@ -1054,10 +1061,16 @@
 		return rc;
 	}
 
-	mask = (pmic_subtype == PM660L_SUBTYPE) ?
-		PM660_BST_OUTPUT_VOLTAGE_MASK : BST_OUTPUT_VOLTAGE_MASK;
+	if (pmic_subtype == PM660L_SUBTYPE) {
+		mask = PM660_BST_OUTPUT_VOLTAGE_MASK;
+		voltage_step = VOLTAGE_STEP_50_MV;
+	} else {
+		mask =  BST_OUTPUT_VOLTAGE_MASK;
+		voltage_step = VOLTAGE_STEP_25_MV;
+	}
+
 	val &= mask;
-	*voltage_mv = (val * VOLTAGE_STEP_50_MV) + MIN_BST_VOLTAGE_MV;
+	*voltage_mv = (val * voltage_step) + MIN_BST_VOLTAGE_MV;
 
 	return 0;
 }
diff --git a/drivers/rtc/rtc-pm8xxx.c b/drivers/rtc/rtc-pm8xxx.c
index fac8355..5309edc 100644
--- a/drivers/rtc/rtc-pm8xxx.c
+++ b/drivers/rtc/rtc-pm8xxx.c
@@ -74,16 +74,18 @@
 /*
  * Steps to write the RTC registers.
  * 1. Disable alarm if enabled.
- * 2. Write 0x00 to LSB.
- * 3. Write Byte[1], Byte[2], Byte[3] then Byte[0].
- * 4. Enable alarm if disabled in step 1.
+ * 2. Disable rtc if enabled.
+ * 3. Write 0x00 to LSB.
+ * 4. Write Byte[1], Byte[2], Byte[3] then Byte[0].
+ * 5. Enable rtc if disabled in step 2.
+ * 6. Enable alarm if disabled in step 1.
  */
 static int pm8xxx_rtc_set_time(struct device *dev, struct rtc_time *tm)
 {
 	int rc, i;
 	unsigned long secs, irq_flags;
-	u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0;
-	unsigned int ctrl_reg;
+	u8 value[NUM_8_BIT_RTC_REGS], alarm_enabled = 0, rtc_disabled = 0;
+	unsigned int ctrl_reg, rtc_ctrl_reg;
 	struct pm8xxx_rtc *rtc_dd = dev_get_drvdata(dev);
 	const struct pm8xxx_rtc_regs *regs = rtc_dd->regs;
 
@@ -92,23 +94,38 @@
 
 	rtc_tm_to_time(tm, &secs);
 
+	dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
+
 	for (i = 0; i < NUM_8_BIT_RTC_REGS; i++) {
 		value[i] = secs & 0xFF;
 		secs >>= 8;
 	}
 
-	dev_dbg(dev, "Seconds value to be written to RTC = %lu\n", secs);
-
 	spin_lock_irqsave(&rtc_dd->ctrl_reg_lock, irq_flags);
 
-	rc = regmap_read(rtc_dd->regmap, regs->ctrl, &ctrl_reg);
+	rc = regmap_read(rtc_dd->regmap, regs->alarm_ctrl, &ctrl_reg);
 	if (rc)
 		goto rtc_rw_fail;
 
 	if (ctrl_reg & regs->alarm_en) {
 		alarm_enabled = 1;
 		ctrl_reg &= ~regs->alarm_en;
-		rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
+		rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
+		if (rc) {
+			dev_err(dev, "Write to RTC Alarm control register failed\n");
+			goto rtc_rw_fail;
+		}
+	}
+
+	/* Disable RTC H/w before writing on RTC register */
+	rc = regmap_read(rtc_dd->regmap, regs->ctrl, &rtc_ctrl_reg);
+	if (rc)
+		goto rtc_rw_fail;
+
+	if (rtc_ctrl_reg & PM8xxx_RTC_ENABLE) {
+		rtc_disabled = 1;
+		rtc_ctrl_reg &= ~PM8xxx_RTC_ENABLE;
+		rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
 		if (rc) {
 			dev_err(dev, "Write to RTC control register failed\n");
 			goto rtc_rw_fail;
@@ -137,15 +154,25 @@
 		goto rtc_rw_fail;
 	}
 
-	if (alarm_enabled) {
-		ctrl_reg |= regs->alarm_en;
-		rc = regmap_write(rtc_dd->regmap, regs->ctrl, ctrl_reg);
+	/* Enable RTC H/w after writing on RTC register */
+	if (rtc_disabled) {
+		rtc_ctrl_reg |= PM8xxx_RTC_ENABLE;
+		rc = regmap_write(rtc_dd->regmap, regs->ctrl, rtc_ctrl_reg);
 		if (rc) {
 			dev_err(dev, "Write to RTC control register failed\n");
 			goto rtc_rw_fail;
 		}
 	}
 
+	if (alarm_enabled) {
+		ctrl_reg |= regs->alarm_en;
+		rc = regmap_write(rtc_dd->regmap, regs->alarm_ctrl, ctrl_reg);
+		if (rc) {
+			dev_err(dev, "Write to RTC Alarm control register failed\n");
+			goto rtc_rw_fail;
+		}
+	}
+
 rtc_rw_fail:
 	spin_unlock_irqrestore(&rtc_dd->ctrl_reg_lock, irq_flags);
 
diff --git a/drivers/scsi/ufs/ufs-qcom.c b/drivers/scsi/ufs/ufs-qcom.c
index ba44523..bca52ca 100644
--- a/drivers/scsi/ufs/ufs-qcom.c
+++ b/drivers/scsi/ufs/ufs-qcom.c
@@ -2615,6 +2615,27 @@
 	kfree(testbus);
 }
 
+static void ufs_qcom_print_utp_hci_testbus(struct ufs_hba *hba)
+{
+	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
+	u32 *testbus = NULL;
+	int i, nminor = 32, testbus_len = nminor * sizeof(u32);
+
+	testbus = kmalloc(testbus_len, GFP_KERNEL);
+	if (!testbus)
+		return;
+
+	host->testbus.select_major = TSTBUS_UTP_HCI;
+	for (i = 0; i <= nminor; i++) {
+		host->testbus.select_minor = i;
+		ufs_qcom_testbus_config(host);
+		testbus[i] = ufshcd_readl(hba, UFS_TEST_BUS);
+	}
+	print_hex_dump(KERN_ERR, "UTP_HCI_TEST_BUS ", DUMP_PREFIX_OFFSET,
+			16, 4, testbus, testbus_len, false);
+	kfree(testbus);
+}
+
 static void ufs_qcom_dump_dbg_regs(struct ufs_hba *hba, bool no_sleep)
 {
 	struct ufs_qcom_host *host = ufshcd_get_variant(hba);
@@ -2633,6 +2654,8 @@
 	usleep_range(1000, 1100);
 	ufs_qcom_print_unipro_testbus(hba);
 	usleep_range(1000, 1100);
+	ufs_qcom_print_utp_hci_testbus(hba);
+	usleep_range(1000, 1100);
 	ufs_qcom_phy_dbg_register_dump(phy);
 	usleep_range(1000, 1100);
 	ufs_qcom_ice_print_regs(host);
diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c
index 02dfbcc..2fe484a 100644
--- a/drivers/scsi/ufs/ufshcd.c
+++ b/drivers/scsi/ufs/ufshcd.c
@@ -3,7 +3,7 @@
  *
  * This code is based on drivers/scsi/ufs/ufshcd.c
  * Copyright (C) 2011-2013 Samsung India Software Operations
- * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * Authors:
  *	Santosh Yaraganavi <santosh.sy@samsung.com>
@@ -620,6 +620,11 @@
 	ufshcd_cmd_log(hba, str, "dme", 0, cmd_id, 0);
 }
 
+static void ufshcd_custom_cmd_log(struct ufs_hba *hba, char *str)
+{
+	ufshcd_cmd_log(hba, str, "custom", 0, 0, 0);
+}
+
 static void ufshcd_print_cmd_log(struct ufs_hba *hba)
 {
 	int i;
@@ -670,6 +675,10 @@
 {
 }
 
+static void ufshcd_custom_cmd_log(struct ufs_hba *hba, char *str)
+{
+}
+
 static void ufshcd_print_cmd_log(struct ufs_hba *hba)
 {
 }
@@ -892,7 +901,7 @@
 
 	dev_err(hba->dev, "UFS Host state=%d\n", hba->ufshcd_state);
 	dev_err(hba->dev, "lrb in use=0x%lx, outstanding reqs=0x%lx tasks=0x%lx\n",
-		hba->lrb_in_use, hba->outstanding_tasks, hba->outstanding_reqs);
+		hba->lrb_in_use, hba->outstanding_reqs, hba->outstanding_tasks);
 	dev_err(hba->dev, "saved_err=0x%x, saved_uic_err=0x%x, saved_ce_err=0x%x\n",
 		hba->saved_err, hba->saved_uic_err, hba->saved_ce_err);
 	dev_err(hba->dev, "Device power mode=%d, UIC link state=%d\n",
@@ -6353,7 +6362,7 @@
 	 * Dump controller state before resetting. Transfer requests state
 	 * will be dump as part of the request completion.
 	 */
-	if ((hba->saved_err & (INT_FATAL_ERRORS | UIC_ERROR)) ||
+	if ((hba->saved_err & (INT_FATAL_ERRORS | UIC_ERROR | UIC_LINK_LOST)) ||
 	    hba->auto_h8_err) {
 		dev_err(hba->dev, "%s: saved_err 0x%x saved_uic_err 0x%x",
 			__func__, hba->saved_err, hba->saved_uic_err);
@@ -6370,7 +6379,7 @@
 		hba->auto_h8_err = false;
 	}
 
-	if ((hba->saved_err & INT_FATAL_ERRORS)
+	if ((hba->saved_err & (INT_FATAL_ERRORS | UIC_LINK_LOST))
 	    || hba->saved_ce_err || hba->force_host_reset ||
 	    ((hba->saved_err & UIC_ERROR) &&
 	    (hba->saved_uic_err & (UFSHCD_UIC_DL_PA_INIT_ERROR |
@@ -6498,6 +6507,7 @@
 	hba = container_of(work, struct ufs_hba, rls_work);
 	ufshcd_scsi_block_requests(hba);
 	pm_runtime_get_sync(hba->dev);
+	down_write(&hba->lock);
 	ret = ufshcd_wait_for_doorbell_clr(hba, U64_MAX);
 	if (ret) {
 		dev_err(hba->dev,
@@ -6531,6 +6541,7 @@
 		hba->restore_needed = false;
 
 out:
+	up_write(&hba->lock);
 	ufshcd_scsi_unblock_requests(hba);
 	pm_runtime_put_sync(hba->dev);
 }
@@ -6647,6 +6658,12 @@
 	if (hba->errors & INT_FATAL_ERRORS || hba->ce_error)
 		queue_eh_work = true;
 
+	if (hba->errors & UIC_LINK_LOST) {
+		dev_err(hba->dev, "%s: UIC_LINK_LOST received, errors 0x%x\n",
+					__func__, hba->errors);
+		queue_eh_work = true;
+	}
+
 	if (hba->errors & UIC_ERROR) {
 		hba->uic_error = 0;
 		retval = ufshcd_update_uic_error(hba);
@@ -8950,7 +8967,8 @@
 		if (ufshcd_is_clkscaling_supported(hba)) {
 			if (hba->devfreq)
 				ufshcd_suspend_clkscaling(hba);
-			destroy_workqueue(hba->clk_scaling.workq);
+			if (hba->clk_scaling.workq)
+				destroy_workqueue(hba->clk_scaling.workq);
 		}
 		ufshcd_disable_clocks(hba, false);
 		ufshcd_setup_hba_vreg(hba, false);
@@ -10131,11 +10149,14 @@
 	if (ret)
 		goto out;
 
+	ufshcd_custom_cmd_log(hba, "waited-for-DB-clear");
+
 	/* scale down the gear before scaling down clocks */
 	if (!scale_up) {
 		ret = ufshcd_scale_gear(hba, false);
 		if (ret)
 			goto clk_scaling_unprepare;
+		ufshcd_custom_cmd_log(hba, "Gear-scaled-down");
 	}
 
 	/*
@@ -10148,17 +10169,20 @@
 		if (ret)
 			/* link will be bad state so no need to scale_up_gear */
 			return ret;
+		ufshcd_custom_cmd_log(hba, "Hibern8-entered");
 	}
 
 	ret = ufshcd_scale_clks(hba, scale_up);
 	if (ret)
 		goto scale_up_gear;
+	ufshcd_custom_cmd_log(hba, "Clk-freq-switched");
 
 	if (ufshcd_is_auto_hibern8_supported(hba)) {
 		ret = ufshcd_uic_hibern8_exit(hba);
 		if (ret)
 			/* link will be bad state so no need to scale_up_gear */
 			return ret;
+		ufshcd_custom_cmd_log(hba, "Hibern8-Exited");
 	}
 
 	/* scale up the gear after scaling up clocks */
@@ -10168,6 +10192,7 @@
 			ufshcd_scale_clks(hba, false);
 			goto clk_scaling_unprepare;
 		}
+		ufshcd_custom_cmd_log(hba, "Gear-scaled-up");
 	}
 
 	if (!ret) {
diff --git a/drivers/scsi/ufs/ufshci.h b/drivers/scsi/ufs/ufshci.h
index c0e4650..87affc4 100644
--- a/drivers/scsi/ufs/ufshci.h
+++ b/drivers/scsi/ufs/ufshci.h
@@ -154,7 +154,7 @@
 
 #define UFSHCD_UIC_MASK		(UIC_COMMAND_COMPL | UFSHCD_UIC_PWR_MASK)
 
-#define UFSHCD_ERROR_MASK	(UIC_ERROR |\
+#define UFSHCD_ERROR_MASK	(UIC_ERROR | UIC_LINK_LOST |\
 				DEVICE_FATAL_ERROR |\
 				CONTROLLER_FATAL_ERROR |\
 				SYSTEM_BUS_FATAL_ERROR |\
diff --git a/drivers/slimbus/slim-msm.c b/drivers/slimbus/slim-msm.c
index 01779f9..24a3ccf 100644
--- a/drivers/slimbus/slim-msm.c
+++ b/drivers/slimbus/slim-msm.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -490,32 +490,26 @@
 	return SLIM_P_INPROGRESS;
 }
 
-static int msm_slim_iommu_map(struct msm_slim_ctrl *dev, phys_addr_t iobuf,
+static dma_addr_t msm_slim_iommu_map(struct msm_slim_ctrl *dev, void *buf_addr,
 			      u32 len)
 {
-	int ret;
+	dma_addr_t ret;
+	struct device *devp = dev->iommu_desc.cb_dev ? dev->iommu_desc.cb_dev :
+							dev->dev;
+	ret = dma_map_single(devp, buf_addr, len, DMA_BIDIRECTIONAL);
 
-	if (!dev->iommu_desc.cb_dev)
-		return 0;
+	if (dma_mapping_error(devp, ret))
+		return DMA_ERROR_CODE;
 
-	ret = iommu_map(dev->iommu_desc.iommu_map->domain,
-			rounddown(iobuf, PAGE_SIZE),
-			rounddown(iobuf, PAGE_SIZE),
-			roundup((len + (iobuf - rounddown(iobuf, PAGE_SIZE))),
-				PAGE_SIZE), IOMMU_READ | IOMMU_WRITE);
 	return ret;
 }
 
-static void msm_slim_iommu_unmap(struct msm_slim_ctrl *dev, phys_addr_t iobuf,
+static void msm_slim_iommu_unmap(struct msm_slim_ctrl *dev, dma_addr_t buf_addr,
 				u32 len)
 {
-	if (!dev->iommu_desc.cb_dev)
-		return;
-
-	iommu_unmap(dev->iommu_desc.iommu_map->domain,
-		    rounddown(iobuf, PAGE_SIZE),
-		    roundup((len + (iobuf - rounddown(iobuf, PAGE_SIZE))),
-			    PAGE_SIZE));
+	struct device *devp = dev->iommu_desc.cb_dev ? dev->iommu_desc.cb_dev :
+							dev->dev;
+	dma_unmap_single(devp, buf_addr, len, DMA_BIDIRECTIONAL);
 }
 
 static void msm_slim_port_cb(struct sps_event_notify *ev)
@@ -539,11 +533,12 @@
 		complete(comp);
 }
 
-int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, phys_addr_t iobuf,
+int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, void *buf,
 			u32 len, struct completion *comp)
 {
 	struct sps_register_event sreg;
 	int ret;
+	dma_addr_t dma_buf;
 	struct msm_slim_ctrl *dev = slim_get_ctrldata(ctrl);
 
 	if (pn >= dev->port_nums)
@@ -552,9 +547,11 @@
 	if (!dev->pipes[pn].connected)
 		return -ENOTCONN;
 
-	ret = msm_slim_iommu_map(dev, iobuf, len);
-	if (ret)
-		return ret;
+	dma_buf =  msm_slim_iommu_map(dev, buf, len);
+	if (dma_buf == DMA_ERROR_CODE) {
+		dev_err(dev->dev, "error DMA mapping buffers\n");
+		return -ENOMEM;
+	}
 
 	sreg.options = (SPS_EVENT_DESC_DONE|SPS_EVENT_ERROR);
 	sreg.mode = SPS_TRIGGER_WAIT;
@@ -564,10 +561,10 @@
 	ret = sps_register_event(dev->pipes[pn].sps, &sreg);
 	if (ret) {
 		dev_dbg(dev->dev, "sps register event error:%x\n", ret);
-		msm_slim_iommu_unmap(dev, iobuf, len);
+		msm_slim_iommu_unmap(dev, dma_buf, len);
 		return ret;
 	}
-	ret = sps_transfer_one(dev->pipes[pn].sps, iobuf, len, comp,
+	ret = sps_transfer_one(dev->pipes[pn].sps, dma_buf, len, comp,
 				SPS_IOVEC_FLAG_INT);
 	dev_dbg(dev->dev, "sps submit xfer error code:%x\n", ret);
 	if (!ret) {
@@ -581,7 +578,7 @@
 		/* Make sure that port registers are updated before returning */
 		mb();
 	} else {
-		msm_slim_iommu_unmap(dev, iobuf, len);
+		msm_slim_iommu_unmap(dev, dma_buf, len);
 	}
 
 	return ret;
diff --git a/drivers/slimbus/slim-msm.h b/drivers/slimbus/slim-msm.h
index 5859c5f..edebfd9 100644
--- a/drivers/slimbus/slim-msm.h
+++ b/drivers/slimbus/slim-msm.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -423,7 +423,7 @@
 int msm_slim_connect_pipe_port(struct msm_slim_ctrl *dev, u8 pn);
 enum slim_port_err msm_slim_port_xfer_status(struct slim_controller *ctr,
 				u8 pn, phys_addr_t *done_buf, u32 *done_len);
-int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, phys_addr_t iobuf,
+int msm_slim_port_xfer(struct slim_controller *ctrl, u8 pn, void *buf,
 			u32 len, struct completion *comp);
 int msm_send_msg_buf(struct msm_slim_ctrl *dev, u32 *buf, u8 len, u32 tx_reg);
 u32 *msm_get_msg_buf(struct msm_slim_ctrl *dev, int len,
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index f34467b..1140b33 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1600,14 +1600,14 @@
  * Client will call slim_port_get_xfer_status to get error and/or number of
  * bytes transferred if used asynchronously.
  */
-int slim_port_xfer(struct slim_device *sb, u32 ph, phys_addr_t iobuf, u32 len,
+int slim_port_xfer(struct slim_device *sb, u32 ph, void *buf, u32 len,
 				struct completion *comp)
 {
 	struct slim_controller *ctrl = sb->ctrl;
 	u8 pn = SLIM_HDL_TO_PORT(ph);
 
 	dev_dbg(&ctrl->dev, "port xfer: num:%d", pn);
-	return ctrl->port_xfer(ctrl, pn, iobuf, len, comp);
+	return ctrl->port_xfer(ctrl, pn, buf, len, comp);
 }
 EXPORT_SYMBOL(slim_port_xfer);
 
diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
index e5e3147..c5a15b2 100644
--- a/drivers/soc/qcom/Kconfig
+++ b/drivers/soc/qcom/Kconfig
@@ -646,6 +646,15 @@
 	  monitor events that require the core to be awake and ready to
 	  handle the event.
 
+config MSM_AVTIMER
+	tristate "Avtimer Driver"
+	default n
+	help
+	  This driver gets the Q6 out of power collapsed state
+	  and exposes ioctl control to read avtimer tick.
+	  Enables camera to use for VT call to get avtimer
+	  timestamp.
+
 config MSM_PM
 	depends on PM
 	select MSM_IDLE_STATS if DEBUG_FS
diff --git a/drivers/soc/qcom/glink.c b/drivers/soc/qcom/glink.c
index 59897ea..4892f50 100644
--- a/drivers/soc/qcom/glink.c
+++ b/drivers/soc/qcom/glink.c
@@ -37,6 +37,7 @@
 #define GLINK_QOS_DEF_NUM_PRIORITY	1
 #define GLINK_QOS_DEF_MTU		2048
 
+#define GLINK_CH_XPRT_NAME_SIZE ((3 * GLINK_NAME_SIZE) + 4)
 #define GLINK_KTHREAD_PRIO 1
 
 /**
@@ -1274,8 +1275,7 @@
 	spin_unlock_irqrestore(&ctx->rmt_rx_intent_lst_lock_lhc2, flags);
 
 	GLINK_DBG_CH(ctx, "%s: R[%u]:%zu Pushed remote intent\n", __func__,
-			intent->id,
-			intent->intent_size);
+			riid, size);
 }
 
 /**
@@ -2905,6 +2905,7 @@
 	size_t intent_size;
 	bool is_atomic =
 		tx_flags & (GLINK_TX_SINGLE_THREADED | GLINK_TX_ATOMIC);
+	char glink_name[GLINK_CH_XPRT_NAME_SIZE];
 	unsigned long flags;
 	void *cookie = NULL;
 
@@ -2946,21 +2947,22 @@
 		tracer_pkt_log_event(data, GLINK_CORE_TX);
 	}
 
+	scnprintf(glink_name, GLINK_CH_XPRT_NAME_SIZE, "%s_%s_%s", ctx->name,
+			ctx->transport_ptr->edge, ctx->transport_ptr->name);
 	/* find matching rx intent (first-fit algorithm for now) */
 	if (ch_pop_remote_rx_intent(ctx, size, &riid, &intent_size, &cookie)) {
 		if (!(tx_flags & GLINK_TX_REQ_INTENT)) {
 			/* no rx intent available */
-			GLINK_ERR_CH(ctx,
-				"%s: R[%u]:%zu Intent not present for lcid\n",
-				__func__, riid, size);
+			GLINK_ERR(
+				"%s: %s: R[%u]:%zu Intent not present\n",
+				glink_name, __func__, riid, size);
 			ret = -EAGAIN;
 			goto glink_tx_common_err;
 		}
 		if (is_atomic && !(ctx->transport_ptr->capabilities &
 					  GCAP_AUTO_QUEUE_RX_INT)) {
-			GLINK_ERR_CH(ctx,
-				"%s: Cannot request intent in atomic context\n",
-				__func__);
+			GLINK_ERR("%s: %s: %s\n", glink_name, __func__,
+				"Cannot request intent in atomic context");
 			ret = -EINVAL;
 			goto glink_tx_common_err;
 		}
@@ -2970,8 +2972,8 @@
 		ret = ctx->transport_ptr->ops->tx_cmd_rx_intent_req(
 				ctx->transport_ptr->ops, ctx->lcid, size);
 		if (ret) {
-			GLINK_ERR_CH(ctx, "%s: Request intent failed %d\n",
-					__func__, ret);
+			GLINK_ERR("%s: %s: Request intent failed %d\n",
+					glink_name, __func__, ret);
 			goto glink_tx_common_err;
 		}
 
@@ -2979,18 +2981,18 @@
 						&intent_size, &cookie)) {
 			rwref_read_put(&ctx->ch_state_lhb2);
 			if (is_atomic) {
-				GLINK_ERR_CH(ctx,
-				    "%s Intent of size %zu not ready\n",
-				    __func__, size);
+				GLINK_ERR("%s: %s: Intent of size %zu %s\n",
+					glink_name, __func__, size,
+					"not ready");
 				ret = -EAGAIN;
 				goto glink_tx_common_err_2;
 			}
 
 			if (ctx->transport_ptr->local_state == GLINK_XPRT_DOWN
 			    || !ch_is_fully_opened(ctx)) {
-				GLINK_ERR_CH(ctx,
-					"%s: Channel closed while waiting for intent\n",
-					__func__);
+				GLINK_ERR("%s: %s: %s %s\n", glink_name,
+					 __func__, "Channel closed while",
+					"waiting for intent");
 				ret = -EBUSY;
 				goto glink_tx_common_err_2;
 			}
@@ -3000,17 +3002,17 @@
 					&ctx->int_req_ack_complete,
 					ctx->rx_intent_req_timeout_jiffies)) {
 				GLINK_ERR(
-					"%s: Intent request ack with size: %zu not granted for lcid\n",
-					__func__, size);
+					"%s: %s: %s %zu not granted for lcid\n",
+					glink_name, __func__,
+					"Intent request ack with size:", size);
 				ret = -ETIMEDOUT;
 				goto glink_tx_common_err_2;
 			}
 
 			if (!ctx->int_req_ack) {
-				GLINK_ERR_CH(ctx,
-				    "%s: Intent Request with size: %zu %s",
-				    __func__, size,
-				    "not granted for lcid\n");
+				GLINK_ERR("%s: %s: %s %zu %s\n", glink_name,
+					__func__, "Intent Request with size:",
+					size, "not granted for lcid");
 				ret = -EAGAIN;
 				goto glink_tx_common_err_2;
 			}
@@ -3019,9 +3021,9 @@
 			if (!wait_for_completion_timeout(
 					&ctx->int_req_complete,
 					ctx->rx_intent_req_timeout_jiffies)) {
-				GLINK_ERR(
-					"%s: Intent request with size: %zu not granted for lcid\n",
-					__func__, size);
+				GLINK_ERR("%s: %s: %s %zu %s\n", glink_name,
+					 __func__, "Intent request with size: ",
+					size, "not granted for lcid");
 				ret = -ETIMEDOUT;
 				goto glink_tx_common_err_2;
 			}
diff --git a/drivers/soc/qcom/glink_smem_native_xprt.c b/drivers/soc/qcom/glink_smem_native_xprt.c
index da122fc..d9cd0fa 100644
--- a/drivers/soc/qcom/glink_smem_native_xprt.c
+++ b/drivers/soc/qcom/glink_smem_native_xprt.c
@@ -53,6 +53,8 @@
 #define RPM_FIFO_ADDR_ALIGN_BYTES 3
 #define TRACER_PKT_FEATURE BIT(2)
 #define DEFERRED_CMDS_THRESHOLD 25
+#define NUM_LOG_PAGES	4
+
 /**
  * enum command_types - definition of the types of commands sent/received
  * @VERSION_CMD:		Version and feature set supported
@@ -169,6 +171,7 @@
  * @tx_blocked_signal_sent:	Flag to indicate the flush signal has already
  *				been sent, and a response is pending from the
  *				remote side.  Protected by @write_lock.
+ * @debug_mask			mask to set debugging level.
  * @kwork:			Work to be executed when an irq is received.
  * @kworker:			Handle to the entity processing of
 				deferred commands.
@@ -189,6 +192,7 @@
  * @ramp_time_us:		Array of ramp times in microseconds where array
  *				index position represents a power state.
  * @mailbox:			Mailbox transport channel description reference.
+ * @log_ctx:			Pointer to log context.
  */
 struct edge_info {
 	struct glink_transport_if xprt_if;
@@ -214,6 +218,7 @@
 	wait_queue_head_t tx_blocked_queue;
 	bool tx_resume_needed;
 	bool tx_blocked_signal_sent;
+	unsigned int debug_mask;
 	struct kthread_work kwork;
 	struct kthread_worker kworker;
 	struct task_struct *task;
@@ -229,6 +234,7 @@
 	uint32_t readback;
 	unsigned long *ramp_time_us;
 	struct mailbox_config_info *mailbox;
+	void *log_ctx;
 };
 
 /**
@@ -261,6 +267,27 @@
 	{1, TRACER_PKT_FEATURE, negotiate_features_v1},
 };
 
+#define SMEM_IPC_LOG(einfo, str, id, param1, param2) do { \
+	if ((glink_xprt_debug_mask & QCOM_GLINK_DEBUG_ENABLE) \
+		&& (einfo->debug_mask & QCOM_GLINK_DEBUG_ENABLE)) \
+		ipc_log_string(einfo->log_ctx, \
+				"%s: Rx:%x:%x Tx:%x:%x Cmd:%x P1:%x P2:%x\n", \
+				str, einfo->rx_ch_desc->read_index, \
+				einfo->rx_ch_desc->write_index, \
+				einfo->tx_ch_desc->read_index, \
+				einfo->tx_ch_desc->write_index, \
+				id, param1, param2); \
+} while (0) \
+
+enum {
+	QCOM_GLINK_DEBUG_ENABLE = 1U << 0,
+	QCOM_GLINK_DEBUG_DISABLE = 1U << 1,
+};
+
+static unsigned int glink_xprt_debug_mask = QCOM_GLINK_DEBUG_ENABLE;
+module_param_named(debug_mask, glink_xprt_debug_mask,
+		   uint, 0664);
+
 /**
  * send_irq() - send an irq to a remote entity as an event signal
  * @einfo:	Which remote entity that should receive the irq.
@@ -640,6 +667,7 @@
 	read_notif_req.reserved = 0;
 	read_notif_req.reserved2 = 0;
 
+	SMEM_IPC_LOG(einfo, __func__, READ_NOTIF_CMD, 0, 0);
 	if (!einfo->tx_blocked_signal_sent) {
 		einfo->tx_blocked_signal_sent = true;
 		fifo_write(einfo, &read_notif_req, sizeof(read_notif_req));
@@ -968,8 +996,12 @@
 			cmd.param2 = d_cmd->param2;
 			cmd_data = d_cmd->data;
 			kfree(d_cmd);
+			SMEM_IPC_LOG(einfo, "kthread", cmd.id, cmd.param1,
+								cmd.param2);
 		} else {
 			fifo_read(einfo, &cmd, sizeof(cmd));
+			SMEM_IPC_LOG(einfo, "IRQ", cmd.id, cmd.param1,
+								cmd.param2);
 			cmd_data = NULL;
 		}
 
@@ -1297,6 +1329,7 @@
 	cmd.version = version;
 	cmd.features = features;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.version, cmd.features);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
 }
@@ -1332,6 +1365,7 @@
 	cmd.version = version;
 	cmd.features = features;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.version, cmd.features);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
 }
@@ -1417,6 +1451,7 @@
 	memcpy(buf, &cmd, sizeof(cmd));
 	memcpy(buf + sizeof(cmd), name, cmd.length);
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.length);
 	fifo_tx(einfo, buf, buf_size);
 
 	kfree(buf);
@@ -1455,6 +1490,7 @@
 	cmd.lcid = lcid;
 	cmd.reserved = 0;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.reserved);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
@@ -1492,6 +1528,7 @@
 	cmd.rcid = rcid;
 	cmd.reserved = 0;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.rcid, cmd.reserved);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
 }
@@ -1526,6 +1563,7 @@
 	cmd.rcid = rcid;
 	cmd.reserved = 0;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.rcid, cmd.reserved);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
 }
@@ -1686,6 +1724,7 @@
 	cmd.size = size;
 	cmd.liid = liid;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.count);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
@@ -1726,6 +1765,7 @@
 	cmd.lcid = lcid;
 	cmd.liid = liid;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.liid);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
 }
@@ -1771,6 +1811,7 @@
 	cmd.lcid = lcid;
 	cmd.size = size;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.size);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
@@ -1816,6 +1857,7 @@
 	else
 		cmd.response = 0;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.response);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
@@ -1854,6 +1896,7 @@
 	cmd.lcid = lcid;
 	cmd.sigs = sigs;
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.sigs);
 	fifo_tx(einfo, &cmd, sizeof(cmd));
 
 	srcu_read_unlock(&einfo->use_ref, rcu_id);
@@ -2051,6 +2094,7 @@
 		return ret;
 	}
 
+	SMEM_IPC_LOG(einfo, __func__, cmd.id, cmd.lcid, cmd.riid);
 	GLINK_DBG("%s %s: lcid[%u] riid[%u] cmd[%d], size[%d], size_left[%d]\n",
 		"<SMEM>", __func__, cmd.lcid, cmd.riid, cmd.id, cmd.size,
 		cmd.size_left);
@@ -2370,6 +2414,7 @@
 	uint32_t irq_mask;
 	struct resource *r;
 	u32 *cpu_array;
+	char log_name[GLINK_NAME_SIZE*2+7] = {0};
 
 	node = pdev->dev.of_node;
 
@@ -2529,6 +2574,16 @@
 		kfree(cpu_array);
 	}
 
+	einfo->debug_mask = QCOM_GLINK_DEBUG_ENABLE;
+	snprintf(log_name, sizeof(log_name), "%s_%s_xprt",
+			einfo->xprt_cfg.edge, einfo->xprt_cfg.name);
+	if (einfo->debug_mask & QCOM_GLINK_DEBUG_ENABLE)
+		einfo->log_ctx =
+			ipc_log_context_create(NUM_LOG_PAGES, log_name, 0);
+	if (!einfo->log_ctx)
+		GLINK_ERR("%s: unable to create log context for [%s:%s]\n",
+			__func__, einfo->xprt_cfg.edge,
+			einfo->xprt_cfg.name);
 	register_debugfs_info(einfo);
 	/* fake an interrupt on this edge to see if the remote side is up */
 	irq_handler(0, einfo);
@@ -2570,6 +2625,7 @@
 	char toc[RPM_TOC_SIZE];
 	uint32_t *tocp;
 	uint32_t num_toc_entries;
+	char log_name[GLINK_NAME_SIZE*2+7] = {0};
 
 	node = pdev->dev.of_node;
 
@@ -2776,7 +2832,16 @@
 	if (rc < 0)
 		pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
 								irq_line);
-
+	einfo->debug_mask = QCOM_GLINK_DEBUG_DISABLE;
+	snprintf(log_name, sizeof(log_name), "%s_%s_xprt",
+			einfo->xprt_cfg.edge, einfo->xprt_cfg.name);
+	if (einfo->debug_mask & QCOM_GLINK_DEBUG_ENABLE)
+		einfo->log_ctx =
+			ipc_log_context_create(NUM_LOG_PAGES, log_name, 0);
+	if (!einfo->log_ctx)
+		GLINK_ERR("%s: unable to create log context for [%s:%s]\n",
+			__func__, einfo->xprt_cfg.edge,
+			einfo->xprt_cfg.name);
 	register_debugfs_info(einfo);
 	einfo->xprt_if.glink_core_if_ptr->link_up(&einfo->xprt_if);
 	return 0;
@@ -2822,6 +2887,7 @@
 	struct mailbox_config_info *mbox_cfg;
 	uint32_t mbox_cfg_size;
 	phys_addr_t cfg_p_addr;
+	char log_name[GLINK_NAME_SIZE*2+7] = {0};
 
 	node = pdev->dev.of_node;
 
@@ -3020,7 +3086,16 @@
 	if (rc < 0)
 		pr_err("%s: enable_irq_wake() failed on %d\n", __func__,
 								irq_line);
-
+	einfo->debug_mask = QCOM_GLINK_DEBUG_DISABLE;
+	snprintf(log_name, sizeof(log_name), "%s_%s_xprt",
+			einfo->xprt_cfg.edge, einfo->xprt_cfg.name);
+	if (einfo->debug_mask & QCOM_GLINK_DEBUG_ENABLE)
+		einfo->log_ctx =
+			ipc_log_context_create(NUM_LOG_PAGES, log_name, 0);
+	if (!einfo->log_ctx)
+		GLINK_ERR("%s: unable to create log context for [%s:%s]\n",
+			__func__, einfo->xprt_cfg.edge,
+			einfo->xprt_cfg.name);
 	register_debugfs_info(einfo);
 
 	writel_relaxed(mbox_cfg_size, mbox_size);
diff --git a/drivers/soc/qcom/lpm-stats.c b/drivers/soc/qcom/lpm-stats.c
index a4d59f4..97c2f51 100644
--- a/drivers/soc/qcom/lpm-stats.c
+++ b/drivers/soc/qcom/lpm-stats.c
@@ -694,9 +694,10 @@
 {
 	struct list_head *centry = NULL;
 	struct lpm_stats *pos = NULL;
+	struct lpm_stats *n = NULL;
 
 	centry = &stats->child;
-	list_for_each_entry_reverse(pos, centry, sibling) {
+	list_for_each_entry_safe_reverse(pos, n, centry, sibling) {
 		if (!list_empty(&pos->child)) {
 			cleanup_stats(pos);
 			continue;
diff --git a/drivers/soc/qcom/memshare/msm_memshare.c b/drivers/soc/qcom/memshare/msm_memshare.c
index e58fa2e..0ae25a1 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.c
+++ b/drivers/soc/qcom/memshare/msm_memshare.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -324,7 +324,7 @@
 {
 	int i;
 	int ret;
-	u32 source_vmlist[2] = {VMID_HLOS, VMID_MSS_MSA};
+	u32 source_vmlist[1] = {VMID_MSS_MSA};
 	int dest_vmids[1] = {VMID_HLOS};
 	int dest_perms[1] = {PERM_READ|PERM_WRITE|PERM_EXEC};
 	struct notif_data *notifdata = NULL;
@@ -335,6 +335,9 @@
 
 	case SUBSYS_BEFORE_SHUTDOWN:
 		bootup_request++;
+		for (i = 0; ((i < MAX_CLIENTS) &&
+			!memblock[i].guarantee); i++)
+			memblock[i].alloc_request = 0;
 		break;
 
 	case SUBSYS_RAMDUMP_NOTIFICATION:
@@ -374,14 +377,15 @@
 				if (memblock[i].peripheral ==
 					DHMS_MEM_PROC_MPSS_V01 &&
 					!memblock[i].guarantee &&
-					memblock[i].allotted) {
+					memblock[i].allotted &&
+					!memblock[i].alloc_request) {
 					pr_debug("memshare: hypervisor unmapping  for client id: %d\n",
 						memblock[i].client_id);
 					ret = hyp_assign_phys(
 							memblock[i].phy_addr,
 							memblock[i].size,
 							source_vmlist,
-							2, dest_vmids,
+							1, dest_vmids,
 							dest_perms, 1);
 					if (ret &&
 						memblock[i].hyp_mapping == 1) {
@@ -393,7 +397,6 @@
 						 */
 						pr_err("memshare: %s, failed to unmap the region\n",
 							__func__);
-						memblock[i].hyp_mapping = 1;
 					} else {
 						memblock[i].hyp_mapping = 0;
 					}
@@ -425,9 +428,8 @@
 {
 	int ret;
 	u32 source_vmlist[1] = {VMID_HLOS};
-	int dest_vmids[2] = {VMID_HLOS, VMID_MSS_MSA};
-	int dest_perms[2] = {PERM_READ|PERM_WRITE,
-				PERM_READ|PERM_WRITE};
+	int dest_vmids[1] = {VMID_MSS_MSA};
+	int dest_perms[1] = {PERM_READ|PERM_WRITE};
 
 	if (client_id == DHMS_MEM_CLIENT_INVALID) {
 		pr_err("memshare: %s, Invalid Client\n", __func__);
@@ -437,7 +439,7 @@
 	ret = hyp_assign_phys(memblock[client_id].phy_addr,
 			memblock[client_id].size,
 			source_vmlist, 1, dest_vmids,
-			dest_perms, 2);
+			dest_perms, 1);
 
 	if (ret != 0) {
 		pr_err("memshare: hyp_assign_phys failed size=%u err=%d\n",
@@ -539,6 +541,7 @@
 			memblock[client_id].allotted = 1;
 			memblock[client_id].size = alloc_req->num_bytes;
 			memblock[client_id].peripheral = alloc_req->proc_id;
+			memblock[client_id].alloc_request = 1;
 		}
 	}
 	pr_debug("memshare: In %s, free memory count for client id: %d = %d",
@@ -603,9 +606,11 @@
 {
 	struct mem_free_generic_req_msg_v01 *free_req;
 	struct mem_free_generic_resp_msg_v01 free_resp;
-	int rc;
-	int flag = 0;
+	int rc, flag = 0, ret = 0;
 	uint32_t client_id;
+	u32 source_vmlist[1] = {VMID_MSS_MSA};
+	int dest_vmids[1] = {VMID_HLOS};
+	int dest_perms[1] = {PERM_READ|PERM_WRITE|PERM_EXEC};
 
 	mutex_lock(&memsh_drv->mem_free);
 	free_req = (struct mem_free_generic_req_msg_v01 *)req;
@@ -624,6 +629,17 @@
 					memblock[client_id].allotted) {
 		pr_debug("memshare: %s: size: %d",
 				__func__, memblock[client_id].size);
+		ret = hyp_assign_phys(memblock[client_id].phy_addr,
+				memblock[client_id].size, source_vmlist, 1,
+				dest_vmids, dest_perms, 1);
+		if (ret && memblock[client_id].hyp_mapping == 1) {
+		/*
+		 * This is an error case as hyp mapping was successful
+		 * earlier but during unmap it lead to failure.
+		 */
+			pr_err("memshare: %s, failed to unmap the region\n",
+				__func__);
+		}
 		dma_free_attrs(memsh_drv->dev, memblock[client_id].size,
 			memblock[client_id].virtual_addr,
 			memblock[client_id].phy_addr,
@@ -959,6 +975,7 @@
 			return rc;
 		}
 		memblock[num_clients].allotted = 1;
+		memblock[num_clients].alloc_request = 1;
 		shared_hyp_mapping(num_clients);
 	}
 
diff --git a/drivers/soc/qcom/memshare/msm_memshare.h b/drivers/soc/qcom/memshare/msm_memshare.h
index ca11137..6b54652 100644
--- a/drivers/soc/qcom/memshare/msm_memshare.h
+++ b/drivers/soc/qcom/memshare/msm_memshare.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2013-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2013-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -39,6 +39,8 @@
 	uint32_t guarantee;
 	/* Memory alloted or not */
 	uint32_t allotted;
+	/* Memory allocation request received or not */
+	uint32_t alloc_request;
 	/* Size required for client */
 	uint32_t size;
 	/*
diff --git a/drivers/soc/qcom/microdump_collector.c b/drivers/soc/qcom/microdump_collector.c
index 47f3336..4a22b4d 100644
--- a/drivers/soc/qcom/microdump_collector.c
+++ b/drivers/soc/qcom/microdump_collector.c
@@ -41,7 +41,7 @@
 	unsigned int smem_id = 611;
 	struct ramdump_segment segment[2];
 
-	if (code == SUBSYS_RAMDUMP_NOTIFICATION) {
+	if (SUBSYS_RAMDUMP_NOTIFICATION == code || SUBSYS_SOC_RESET == code) {
 
 		memset(segment, 0, sizeof(segment));
 
diff --git a/drivers/soc/qcom/msm_bus/Makefile b/drivers/soc/qcom/msm_bus/Makefile
index 15569b1..c2ef70c 100644
--- a/drivers/soc/qcom/msm_bus/Makefile
+++ b/drivers/soc/qcom/msm_bus/Makefile
@@ -7,7 +7,7 @@
 
 ifdef CONFIG_QCOM_BUS_CONFIG_RPMH
 	obj-y += msm_bus_fabric_rpmh.o msm_bus_arb_rpmh.o msm_bus_rules.o \
-		msm_bus_bimc_rpmh.o msm_bus_noc_rpmh.o
+		msm_bus_bimc_rpmh.o msm_bus_noc_rpmh.o msm_bus_proxy_client.o
 	obj-$(CONFIG_OF) += msm_bus_of_rpmh.o
 else
 	obj-y += msm_bus_fabric_adhoc.o msm_bus_arb_adhoc.o msm_bus_rules.o \
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
index 437984c..8af9b5a 100644
--- a/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
+++ b/drivers/soc/qcom/msm_bus/msm_bus_arb_rpmh.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -1133,7 +1133,7 @@
 	}
 
 	curr = client->curr;
-	if (curr >= pdata->num_usecases) {
+	if (curr >= pdata->num_usecases || curr < 0) {
 		MSM_BUS_ERR("Invalid index Defaulting curr to 0");
 		curr = 0;
 	}
diff --git a/drivers/soc/qcom/msm_bus/msm_bus_proxy_client.c b/drivers/soc/qcom/msm_bus/msm_bus_proxy_client.c
new file mode 100644
index 0000000..cdf61f6
--- /dev/null
+++ b/drivers/soc/qcom/msm_bus/msm_bus_proxy_client.c
@@ -0,0 +1,93 @@
+/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/msm-bus.h>
+
+struct proxy_client {
+	struct msm_bus_scale_pdata *pdata;
+	unsigned int client_handle;
+};
+
+static struct proxy_client proxy_client_info;
+
+static int msm_bus_device_proxy_client_probe(struct platform_device *pdev)
+{
+	int ret;
+
+	proxy_client_info.pdata = msm_bus_cl_get_pdata(pdev);
+
+	if (!proxy_client_info.pdata)
+		return 0;
+
+	proxy_client_info.client_handle =
+		msm_bus_scale_register_client(proxy_client_info.pdata);
+
+	if (!proxy_client_info.client_handle) {
+		dev_err(&pdev->dev, "Unable to register bus client\n");
+		return -ENODEV;
+	}
+
+	ret = msm_bus_scale_client_update_request(
+					proxy_client_info.client_handle, 1);
+	if (ret)
+		dev_err(&pdev->dev, "Bandwidth update failed (%d)\n", ret);
+
+	return ret;
+}
+
+static const struct of_device_id proxy_client_match[] = {
+	{.compatible = "qcom,bus-proxy-client"},
+	{}
+};
+
+static struct platform_driver msm_bus_proxy_client_driver = {
+	.probe = msm_bus_device_proxy_client_probe,
+	.driver = {
+		.name = "msm_bus_proxy_client_device",
+		.owner = THIS_MODULE,
+		.of_match_table = proxy_client_match,
+	},
+};
+
+static int __init msm_bus_proxy_client_init_driver(void)
+{
+	int rc;
+
+	rc =  platform_driver_register(&msm_bus_proxy_client_driver);
+	if (rc) {
+		pr_err("Failed to register proxy client device driver");
+		return rc;
+	}
+
+	return rc;
+}
+
+static int __init msm_bus_proxy_client_unvote(void)
+{
+	int ret;
+
+	if (!proxy_client_info.pdata || !proxy_client_info.client_handle)
+		return 0;
+
+	ret = msm_bus_scale_client_update_request(
+					proxy_client_info.client_handle, 0);
+	if (ret)
+		pr_err("%s: bandwidth update request failed (%d)\n",
+			__func__, ret);
+
+	msm_bus_scale_unregister_client(proxy_client_info.client_handle);
+
+	return 0;
+}
+
+subsys_initcall_sync(msm_bus_proxy_client_init_driver);
+late_initcall_sync(msm_bus_proxy_client_unvote);
diff --git a/drivers/soc/qcom/msm_performance.c b/drivers/soc/qcom/msm_performance.c
index b5ce753..fb3af15 100644
--- a/drivers/soc/qcom/msm_performance.c
+++ b/drivers/soc/qcom/msm_performance.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2014-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2014-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -26,59 +26,6 @@
 #include <linux/input.h>
 #include <linux/kthread.h>
 
-static struct mutex managed_cpus_lock;
-
-/* Maximum number to clusters that this module will manage */
-static unsigned int num_clusters;
-struct cluster {
-	cpumask_var_t cpus;
-	/* stats for load detection */
-	/* IO */
-	u64 last_io_check_ts;
-	unsigned int iowait_enter_cycle_cnt;
-	unsigned int iowait_exit_cycle_cnt;
-	spinlock_t iowait_lock;
-	unsigned int cur_io_busy;
-	bool io_change;
-	/* CPU */
-	unsigned int mode;
-	bool mode_change;
-	u64 last_mode_check_ts;
-	unsigned int single_enter_cycle_cnt;
-	unsigned int single_exit_cycle_cnt;
-	unsigned int multi_enter_cycle_cnt;
-	unsigned int multi_exit_cycle_cnt;
-	spinlock_t mode_lock;
-	/* Perf Cluster Peak Loads */
-	unsigned int perf_cl_peak;
-	u64 last_perf_cl_check_ts;
-	bool perf_cl_detect_state_change;
-	unsigned int perf_cl_peak_enter_cycle_cnt;
-	unsigned int perf_cl_peak_exit_cycle_cnt;
-	spinlock_t perf_cl_peak_lock;
-	/* Tunables */
-	unsigned int single_enter_load;
-	unsigned int pcpu_multi_enter_load;
-	unsigned int perf_cl_peak_enter_load;
-	unsigned int single_exit_load;
-	unsigned int pcpu_multi_exit_load;
-	unsigned int perf_cl_peak_exit_load;
-	unsigned int single_enter_cycles;
-	unsigned int single_exit_cycles;
-	unsigned int multi_enter_cycles;
-	unsigned int multi_exit_cycles;
-	unsigned int perf_cl_peak_enter_cycles;
-	unsigned int perf_cl_peak_exit_cycles;
-	unsigned int current_freq;
-	spinlock_t timer_lock;
-	unsigned int timer_rate;
-	struct timer_list mode_exit_timer;
-	struct timer_list perf_cl_peak_mode_exit_timer;
-};
-
-static struct cluster **managed_clusters;
-static bool clusters_inited;
-
 
 /* To handle cpufreq min/max request */
 struct cpu_status {
@@ -87,8 +34,6 @@
 };
 static DEFINE_PER_CPU(struct cpu_status, cpu_stats);
 
-static int init_cluster_control(void);
-static int init_events_group(void);
 struct events {
 	spinlock_t cpu_hotplug_lock;
 	bool cpu_hotplug;
@@ -97,176 +42,7 @@
 static struct events events_group;
 static struct task_struct *events_notify_thread;
 
-#define LAST_UPDATE_TOL		USEC_PER_MSEC
-
-struct input_events {
-	unsigned int evt_x_cnt;
-	unsigned int evt_y_cnt;
-	unsigned int evt_pres_cnt;
-	unsigned int evt_dist_cnt;
-};
-struct trig_thr {
-	unsigned int pwr_cl_trigger_threshold;
-	unsigned int perf_cl_trigger_threshold;
-	unsigned int ip_evt_threshold;
-};
-struct load_stats {
-	u64 last_wallclock;
-	/* IO wait related */
-	u64 last_iowait;
-	unsigned int last_iopercent;
-	/* CPU load related */
-	unsigned int cpu_load;
-	/* CPU Freq */
-	unsigned int freq;
-};
-static bool input_events_handler_registered;
-static struct input_events *ip_evts;
-static struct trig_thr thr;
-static unsigned int use_input_evts_with_hi_slvt_detect;
-static int register_input_handler(void);
-static void unregister_input_handler(void);
-static DEFINE_PER_CPU(struct load_stats, cpu_load_stats);
-
-/* Bitmask to keep track of the workloads being detected */
-static unsigned int workload_detect;
-#define IO_DETECT	1
-#define MODE_DETECT	2
-#define PERF_CL_PEAK_DETECT	4
-
-/* IOwait related tunables */
-static unsigned int io_enter_cycles = 4;
-static unsigned int io_exit_cycles = 4;
-static u64 iowait_ceiling_pct = 25;
-static u64 iowait_floor_pct = 8;
-#define LAST_IO_CHECK_TOL	(3 * USEC_PER_MSEC)
-
-static unsigned int aggr_iobusy;
-static unsigned int aggr_mode;
-
-static struct task_struct *notify_thread;
-
-static struct input_handler *handler;
-
-/* CPU workload detection related */
-#define NO_MODE		(0)
-#define SINGLE		(1)
-#define MULTI		(2)
-#define MIXED		(3)
-#define PERF_CL_PEAK		(4)
-#define DEF_SINGLE_ENT		90
-#define DEF_PCPU_MULTI_ENT	85
-#define DEF_PERF_CL_PEAK_ENT	80
-#define DEF_SINGLE_EX		60
-#define DEF_PCPU_MULTI_EX	50
-#define DEF_PERF_CL_PEAK_EX		70
-#define DEF_SINGLE_ENTER_CYCLE	4
-#define DEF_SINGLE_EXIT_CYCLE	4
-#define DEF_MULTI_ENTER_CYCLE	4
-#define DEF_MULTI_EXIT_CYCLE	4
-#define DEF_PERF_CL_PEAK_ENTER_CYCLE	100
-#define DEF_PERF_CL_PEAK_EXIT_CYCLE	20
-#define LAST_LD_CHECK_TOL	(2 * USEC_PER_MSEC)
-#define CLUSTER_0_THRESHOLD_FREQ	147000
-#define CLUSTER_1_THRESHOLD_FREQ	190000
-#define INPUT_EVENT_CNT_THRESHOLD	15
-#define MAX_LENGTH_CPU_STRING	256
-
 /**************************sysfs start********************************/
-
-static int set_num_clusters(const char *buf, const struct kernel_param *kp)
-{
-	unsigned int val;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-	if (num_clusters)
-		return -EINVAL;
-
-	num_clusters = val;
-
-	if (init_cluster_control()) {
-		num_clusters = 0;
-		return -ENOMEM;
-	}
-
-	return 0;
-}
-
-static int get_num_clusters(char *buf, const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u", num_clusters);
-}
-
-static const struct kernel_param_ops param_ops_num_clusters = {
-	.set = set_num_clusters,
-	.get = get_num_clusters,
-};
-device_param_cb(num_clusters, &param_ops_num_clusters, NULL, 0644);
-
-
-static int set_managed_cpus(const char *buf, const struct kernel_param *kp)
-{
-	int i, ret;
-	struct cpumask tmp_mask;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	ret = cpulist_parse(buf, &tmp_mask);
-
-	if (ret)
-		return ret;
-
-	for (i = 0; i < num_clusters; i++) {
-		if (cpumask_empty(managed_clusters[i]->cpus)) {
-			mutex_lock(&managed_cpus_lock);
-			cpumask_copy(managed_clusters[i]->cpus, &tmp_mask);
-			mutex_unlock(&managed_cpus_lock);
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static int get_managed_cpus(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0, total_cnt = 0;
-	char tmp[MAX_LENGTH_CPU_STRING] = "";
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++) {
-		cnt = cpumap_print_to_pagebuf(true, buf,
-						managed_clusters[i]->cpus);
-		if ((i + 1) < num_clusters &&
-		    (total_cnt + cnt + 1) <= MAX_LENGTH_CPU_STRING) {
-			snprintf(tmp + total_cnt, cnt, "%s", buf);
-			tmp[cnt-1] = ':';
-			tmp[cnt] = '\0';
-			total_cnt += cnt;
-		} else if ((i + 1) == num_clusters &&
-			(total_cnt + cnt) <= MAX_LENGTH_CPU_STRING) {
-			snprintf(tmp + total_cnt, cnt, "%s", buf);
-			total_cnt += cnt;
-		} else {
-			pr_err("invalid string for managed_cpu:%s%s\n", tmp,
-				buf);
-			break;
-		}
-	}
-	snprintf(buf, PAGE_SIZE, "%s", tmp);
-	return total_cnt;
-}
-
-static const struct kernel_param_ops param_ops_managed_cpus = {
-	.set = set_managed_cpus,
-	.get = get_managed_cpus,
-};
-device_param_cb(managed_cpus, &param_ops_managed_cpus, NULL, 0644);
-
 /*
  * Userspace sends cpu#:min_freq_value to vote for min_freq_value as the new
  * scaling_min. To withdraw its vote it needs to enter cpu#:0
@@ -425,1716 +201,8 @@
 };
 module_param_cb(cpu_max_freq, &param_ops_cpu_max_freq, NULL, 0644);
 
-static int set_ip_evt_trigger_threshold(const char *buf,
-		const struct kernel_param *kp)
-{
-	unsigned int val;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-
-	thr.ip_evt_threshold = val;
-	return 0;
-}
-
-static int get_ip_evt_trigger_threshold(char *buf,
-		const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u", thr.ip_evt_threshold);
-}
-
-static const struct kernel_param_ops param_ops_ip_evt_trig_thr = {
-	.set = set_ip_evt_trigger_threshold,
-	.get = get_ip_evt_trigger_threshold,
-};
-device_param_cb(ip_evt_trig_thr, &param_ops_ip_evt_trig_thr, NULL, 0644);
-
-
-static int set_perf_cl_trigger_threshold(const char *buf,
-		 const struct kernel_param *kp)
-{
-	unsigned int val;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-
-	thr.perf_cl_trigger_threshold = val;
-	return 0;
-}
-
-static int get_perf_cl_trigger_threshold(char *buf,
-		const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u", thr.perf_cl_trigger_threshold);
-}
-
-static const struct kernel_param_ops param_ops_perf_trig_thr = {
-	.set = set_perf_cl_trigger_threshold,
-	.get = get_perf_cl_trigger_threshold,
-};
-device_param_cb(perf_cl_trig_thr, &param_ops_perf_trig_thr, NULL, 0644);
-
-
-static int set_pwr_cl_trigger_threshold(const char *buf,
-		const struct kernel_param *kp)
-{
-	unsigned int val;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-
-	thr.pwr_cl_trigger_threshold = val;
-	return 0;
-}
-
-static int get_pwr_cl_trigger_threshold(char *buf,
-		const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u", thr.pwr_cl_trigger_threshold);
-}
-
-static const struct kernel_param_ops param_ops_pwr_trig_thr = {
-	.set = set_pwr_cl_trigger_threshold,
-	.get = get_pwr_cl_trigger_threshold,
-};
-device_param_cb(pwr_cl_trig_thr, &param_ops_pwr_trig_thr, NULL, 0644);
-
-static int freq_greater_than_threshold(struct cluster *cl, int idx)
-{
-	int rc = 0;
-	/* Check for Cluster 0 */
-	if (!idx && cl->current_freq >= thr.pwr_cl_trigger_threshold)
-		rc = 1;
-	/* Check for Cluster 1 */
-	if (idx && cl->current_freq >= thr.perf_cl_trigger_threshold)
-		rc = 1;
-	return rc;
-}
-
-static bool input_events_greater_than_threshold(void)
-{
-
-	bool rc = false;
-
-	if ((ip_evts->evt_x_cnt >= thr.ip_evt_threshold) ||
-	    (ip_evts->evt_y_cnt >= thr.ip_evt_threshold) ||
-	    !use_input_evts_with_hi_slvt_detect)
-		rc = true;
-
-	return rc;
-}
-
-static int set_single_enter_load(const char *buf, const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		if (val < managed_clusters[i]->single_exit_load)
-			return -EINVAL;
-
-		managed_clusters[i]->single_enter_load = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_single_enter_load(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-				"%u:", managed_clusters[i]->single_enter_load);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_enter_load = {
-	.set = set_single_enter_load,
-	.get = get_single_enter_load,
-};
-device_param_cb(single_enter_load, &param_ops_single_enter_load, NULL, 0644);
-
-static int set_single_exit_load(const char *buf, const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		if (val > managed_clusters[i]->single_enter_load)
-			return -EINVAL;
-
-		managed_clusters[i]->single_exit_load = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_single_exit_load(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-				"%u:", managed_clusters[i]->single_exit_load);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_exit_load = {
-	.set = set_single_exit_load,
-	.get = get_single_exit_load,
-};
-device_param_cb(single_exit_load, &param_ops_single_exit_load, NULL, 0644);
-
-static int set_pcpu_multi_enter_load(const char *buf,
-					const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		if (val < managed_clusters[i]->pcpu_multi_exit_load)
-			return -EINVAL;
-
-		managed_clusters[i]->pcpu_multi_enter_load = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_pcpu_multi_enter_load(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-			"%u:", managed_clusters[i]->pcpu_multi_enter_load);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_pcpu_multi_enter_load = {
-	.set = set_pcpu_multi_enter_load,
-	.get = get_pcpu_multi_enter_load,
-};
-device_param_cb(pcpu_multi_enter_load, &param_ops_pcpu_multi_enter_load,
-								NULL, 0644);
-
-static int set_pcpu_multi_exit_load(const char *buf,
-						const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		if (val > managed_clusters[i]->pcpu_multi_enter_load)
-			return -EINVAL;
-
-		managed_clusters[i]->pcpu_multi_exit_load = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_pcpu_multi_exit_load(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-			"%u:", managed_clusters[i]->pcpu_multi_exit_load);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_pcpu_multi_exit_load = {
-	.set = set_pcpu_multi_exit_load,
-	.get = get_pcpu_multi_exit_load,
-};
-device_param_cb(pcpu_multi_exit_load, &param_ops_pcpu_multi_exit_load,
-		NULL, 0644);
-static int set_perf_cl_peak_enter_load(const char *buf,
-				const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		if (val < managed_clusters[i]->perf_cl_peak_exit_load)
-			return -EINVAL;
-
-		managed_clusters[i]->perf_cl_peak_enter_load = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_perf_cl_peak_enter_load(char *buf,
-				const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-			"%u:", managed_clusters[i]->perf_cl_peak_enter_load);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_enter_load = {
-	.set = set_perf_cl_peak_enter_load,
-	.get = get_perf_cl_peak_enter_load,
-};
-device_param_cb(perf_cl_peak_enter_load, &param_ops_perf_cl_peak_enter_load,
-		 NULL, 0644);
-
-static int set_perf_cl_peak_exit_load(const char *buf,
-				const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		if (val > managed_clusters[i]->perf_cl_peak_enter_load)
-			return -EINVAL;
-
-		managed_clusters[i]->perf_cl_peak_exit_load = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_perf_cl_peak_exit_load(char *buf,
-				const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-			"%u:", managed_clusters[i]->perf_cl_peak_exit_load);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_exit_load = {
-	.set = set_perf_cl_peak_exit_load,
-	.get = get_perf_cl_peak_exit_load,
-};
-device_param_cb(perf_cl_peak_exit_load, &param_ops_perf_cl_peak_exit_load,
-		 NULL, 0644);
-
-static int set_perf_cl_peak_enter_cycles(const char *buf,
-				const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		managed_clusters[i]->perf_cl_peak_enter_cycles = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_perf_cl_peak_enter_cycles(char *buf,
-				const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "%u:",
-				managed_clusters[i]->perf_cl_peak_enter_cycles);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_enter_cycles = {
-	.set = set_perf_cl_peak_enter_cycles,
-	.get = get_perf_cl_peak_enter_cycles,
-};
-device_param_cb(perf_cl_peak_enter_cycles, &param_ops_perf_cl_peak_enter_cycles,
-		NULL, 0644);
-
-
-static int set_perf_cl_peak_exit_cycles(const char *buf,
-				const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		managed_clusters[i]->perf_cl_peak_exit_cycles = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_perf_cl_peak_exit_cycles(char *buf,
-			const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-			"%u:", managed_clusters[i]->perf_cl_peak_exit_cycles);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_perf_cl_peak_exit_cycles = {
-	.set = set_perf_cl_peak_exit_cycles,
-	.get = get_perf_cl_peak_exit_cycles,
-};
-device_param_cb(perf_cl_peak_exit_cycles, &param_ops_perf_cl_peak_exit_cycles,
-		 NULL, 0644);
-
-
-static int set_single_enter_cycles(const char *buf,
-				const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		managed_clusters[i]->single_enter_cycles = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_single_enter_cycles(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, "%u:",
-				managed_clusters[i]->single_enter_cycles);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_enter_cycles = {
-	.set = set_single_enter_cycles,
-	.get = get_single_enter_cycles,
-};
-device_param_cb(single_enter_cycles, &param_ops_single_enter_cycles,
-		NULL, 0644);
-
-
-static int set_single_exit_cycles(const char *buf,
-				const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		managed_clusters[i]->single_exit_cycles = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_single_exit_cycles(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-				"%u:", managed_clusters[i]->single_exit_cycles);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_single_exit_cycles = {
-	.set = set_single_exit_cycles,
-	.get = get_single_exit_cycles,
-};
-device_param_cb(single_exit_cycles, &param_ops_single_exit_cycles, NULL, 0644);
-
-static int set_multi_enter_cycles(const char *buf,
-				const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		managed_clusters[i]->multi_enter_cycles = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_multi_enter_cycles(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-				"%u:", managed_clusters[i]->multi_enter_cycles);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_multi_enter_cycles = {
-	.set = set_multi_enter_cycles,
-	.get = get_multi_enter_cycles,
-};
-device_param_cb(multi_enter_cycles, &param_ops_multi_enter_cycles, NULL, 0644);
-
-static int set_multi_exit_cycles(const char *buf, const struct kernel_param *kp)
-{
-	unsigned int val, i, ntokens = 0;
-	const char *cp = buf;
-	unsigned int bytes_left;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	while ((cp = strpbrk(cp + 1, ":")))
-		ntokens++;
-
-	if (ntokens != (num_clusters - 1))
-		return -EINVAL;
-
-	cp = buf;
-	for (i = 0; i < num_clusters; i++) {
-
-		if (sscanf(cp, "%u\n", &val) != 1)
-			return -EINVAL;
-
-		managed_clusters[i]->multi_exit_cycles = val;
-
-		bytes_left = PAGE_SIZE - (cp - buf);
-		cp = strnchr(cp, bytes_left, ':');
-		cp++;
-	}
-
-	return 0;
-}
-
-static int get_multi_exit_cycles(char *buf, const struct kernel_param *kp)
-{
-	int i, cnt = 0;
-
-	if (!clusters_inited)
-		return cnt;
-
-	for (i = 0; i < num_clusters; i++)
-		cnt += snprintf(buf + cnt, PAGE_SIZE - cnt,
-				"%u:", managed_clusters[i]->multi_exit_cycles);
-	cnt--;
-	cnt += snprintf(buf + cnt, PAGE_SIZE - cnt, " ");
-	return cnt;
-}
-
-static const struct kernel_param_ops param_ops_multi_exit_cycles = {
-	.set = set_multi_exit_cycles,
-	.get = get_multi_exit_cycles,
-};
-device_param_cb(multi_exit_cycles, &param_ops_multi_exit_cycles, NULL, 0644);
-
-static int set_io_enter_cycles(const char *buf, const struct kernel_param *kp)
-{
-	unsigned int val;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-
-	io_enter_cycles = val;
-
-	return 0;
-}
-
-static int get_io_enter_cycles(char *buf, const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u", io_enter_cycles);
-}
-
-static const struct kernel_param_ops param_ops_io_enter_cycles = {
-	.set = set_io_enter_cycles,
-	.get = get_io_enter_cycles,
-};
-device_param_cb(io_enter_cycles, &param_ops_io_enter_cycles, NULL, 0644);
-
-static int set_io_exit_cycles(const char *buf, const struct kernel_param *kp)
-{
-	unsigned int val;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-
-	io_exit_cycles = val;
-
-	return 0;
-}
-
-static int get_io_exit_cycles(char *buf, const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u", io_exit_cycles);
-}
-
-static const struct kernel_param_ops param_ops_io_exit_cycles = {
-	.set = set_io_exit_cycles,
-	.get = get_io_exit_cycles,
-};
-device_param_cb(io_exit_cycles, &param_ops_io_exit_cycles, NULL, 0644);
-
-static int set_iowait_floor_pct(const char *buf, const struct kernel_param *kp)
-{
-	u64 val;
-
-	if (sscanf(buf, "%llu\n", &val) != 1)
-		return -EINVAL;
-	if (val > iowait_ceiling_pct)
-		return -EINVAL;
-
-	iowait_floor_pct = val;
-
-	return 0;
-}
-
-static int get_iowait_floor_pct(char *buf, const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%llu", iowait_floor_pct);
-}
-
-static const struct kernel_param_ops param_ops_iowait_floor_pct = {
-	.set = set_iowait_floor_pct,
-	.get = get_iowait_floor_pct,
-};
-device_param_cb(iowait_floor_pct, &param_ops_iowait_floor_pct, NULL, 0644);
-
-static int set_iowait_ceiling_pct(const char *buf,
-						const struct kernel_param *kp)
-{
-	u64 val;
-
-	if (sscanf(buf, "%llu\n", &val) != 1)
-		return -EINVAL;
-	if (val < iowait_floor_pct)
-		return -EINVAL;
-
-	iowait_ceiling_pct = val;
-
-	return 0;
-}
-
-static int get_iowait_ceiling_pct(char *buf, const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%llu", iowait_ceiling_pct);
-}
-
-static const struct kernel_param_ops param_ops_iowait_ceiling_pct = {
-	.set = set_iowait_ceiling_pct,
-	.get = get_iowait_ceiling_pct,
-};
-device_param_cb(iowait_ceiling_pct, &param_ops_iowait_ceiling_pct, NULL, 0644);
-
-static int set_workload_detect(const char *buf, const struct kernel_param *kp)
-{
-	unsigned int val, i;
-	struct cluster *i_cl;
-	unsigned long flags;
-
-	if (!clusters_inited)
-		return -EINVAL;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-
-	if (val == workload_detect)
-		return 0;
-
-	workload_detect = val;
-	if (!(workload_detect & IO_DETECT)) {
-		for (i = 0; i < num_clusters; i++) {
-			i_cl = managed_clusters[i];
-			spin_lock_irqsave(&i_cl->iowait_lock, flags);
-			i_cl->iowait_enter_cycle_cnt = 0;
-			i_cl->iowait_exit_cycle_cnt = 0;
-			i_cl->cur_io_busy = 0;
-			i_cl->io_change = true;
-			spin_unlock_irqrestore(&i_cl->iowait_lock, flags);
-		}
-	}
-	if (!(workload_detect & MODE_DETECT)) {
-		for (i = 0; i < num_clusters; i++) {
-			i_cl = managed_clusters[i];
-			spin_lock_irqsave(&i_cl->mode_lock, flags);
-			i_cl->single_enter_cycle_cnt = 0;
-			i_cl->single_exit_cycle_cnt = 0;
-			i_cl->multi_enter_cycle_cnt = 0;
-			i_cl->multi_exit_cycle_cnt = 0;
-			i_cl->mode = 0;
-			i_cl->mode_change = true;
-			spin_unlock_irqrestore(&i_cl->mode_lock, flags);
-		}
-	}
-
-	if (!(workload_detect & PERF_CL_PEAK_DETECT)) {
-		for (i = 0; i < num_clusters; i++) {
-			i_cl = managed_clusters[i];
-			spin_lock_irqsave(&i_cl->perf_cl_peak_lock, flags);
-			i_cl->perf_cl_peak_enter_cycle_cnt = 0;
-			i_cl->perf_cl_peak_exit_cycle_cnt = 0;
-			i_cl->perf_cl_peak = 0;
-			spin_unlock_irqrestore(&i_cl->perf_cl_peak_lock, flags);
-		}
-	}
-
-	wake_up_process(notify_thread);
-	return 0;
-}
-
-static int get_workload_detect(char *buf, const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u", workload_detect);
-}
-
-static const struct kernel_param_ops param_ops_workload_detect = {
-	.set = set_workload_detect,
-	.get = get_workload_detect,
-};
-device_param_cb(workload_detect, &param_ops_workload_detect, NULL, 0644);
-
-
-static int set_input_evts_with_hi_slvt_detect(const char *buf,
-					const struct kernel_param *kp)
-{
-
-	unsigned int val;
-
-	if (sscanf(buf, "%u\n", &val) != 1)
-		return -EINVAL;
-
-	if (val == use_input_evts_with_hi_slvt_detect)
-		return 0;
-
-	use_input_evts_with_hi_slvt_detect = val;
-
-	if ((workload_detect & PERF_CL_PEAK_DETECT) &&
-		!input_events_handler_registered &&
-		use_input_evts_with_hi_slvt_detect) {
-		if (register_input_handler() == -ENOMEM) {
-			use_input_evts_with_hi_slvt_detect = 0;
-			return -ENOMEM;
-		}
-	} else if ((workload_detect & PERF_CL_PEAK_DETECT) &&
-				input_events_handler_registered &&
-				!use_input_evts_with_hi_slvt_detect) {
-		unregister_input_handler();
-	}
-	return 0;
-}
-
-static int get_input_evts_with_hi_slvt_detect(char *buf,
-					const struct kernel_param *kp)
-{
-	return snprintf(buf, PAGE_SIZE, "%u",
-			use_input_evts_with_hi_slvt_detect);
-}
-
-static const struct kernel_param_ops param_ops_ip_evts_with_hi_slvt_detect = {
-	.set = set_input_evts_with_hi_slvt_detect,
-	.get = get_input_evts_with_hi_slvt_detect,
-};
-device_param_cb(input_evts_with_hi_slvt_detect,
-	&param_ops_ip_evts_with_hi_slvt_detect, NULL, 0644);
-
-static struct kobject *mode_kobj;
-
-static ssize_t show_aggr_mode(struct kobject *kobj,
-					struct kobj_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%u\n", aggr_mode);
-}
-static struct kobj_attribute aggr_mode_attr =
-__ATTR(aggr_mode, 0444, show_aggr_mode, NULL);
-
-static ssize_t show_aggr_iobusy(struct kobject *kobj,
-					struct kobj_attribute *attr, char *buf)
-{
-	return snprintf(buf, PAGE_SIZE, "%u\n", aggr_iobusy);
-}
-static struct kobj_attribute aggr_iobusy_attr =
-__ATTR(aggr_iobusy, 0444, show_aggr_iobusy, NULL);
-
-static struct attribute *attrs[] = {
-	&aggr_mode_attr.attr,
-	&aggr_iobusy_attr.attr,
-	NULL,
-};
-
-static struct attribute_group attr_group = {
-	.attrs = attrs,
-};
-
-static bool check_notify_status(void)
-{
-	int i;
-	struct cluster *cl;
-	bool any_change = false;
-	unsigned long flags;
-
-
-	for (i = 0; i < num_clusters; i++) {
-		cl = managed_clusters[i];
-		spin_lock_irqsave(&cl->iowait_lock, flags);
-		if (!any_change)
-			any_change = cl->io_change;
-		cl->io_change = false;
-		spin_unlock_irqrestore(&cl->iowait_lock, flags);
-
-		spin_lock_irqsave(&cl->mode_lock, flags);
-		if (!any_change)
-			any_change = cl->mode_change;
-		cl->mode_change = false;
-		spin_unlock_irqrestore(&cl->mode_lock, flags);
-
-		spin_lock_irqsave(&cl->perf_cl_peak_lock, flags);
-		if (!any_change)
-			any_change = cl->perf_cl_detect_state_change;
-		cl->perf_cl_detect_state_change = false;
-		spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
-	}
-
-	return any_change;
-}
-
-static int notify_userspace(void *data)
-{
-	unsigned int i, io, cpu_mode, perf_cl_peak_mode;
-
-	while (1) {
-		set_current_state(TASK_INTERRUPTIBLE);
-		if (!check_notify_status()) {
-			schedule();
-
-			if (kthread_should_stop())
-				break;
-		}
-		set_current_state(TASK_RUNNING);
-
-		io = 0;
-		cpu_mode = 0;
-		perf_cl_peak_mode = 0;
-		for (i = 0; i < num_clusters; i++) {
-			io |= managed_clusters[i]->cur_io_busy;
-			cpu_mode |= managed_clusters[i]->mode;
-			perf_cl_peak_mode |= managed_clusters[i]->perf_cl_peak;
-		}
-		if (io != aggr_iobusy) {
-			aggr_iobusy = io;
-			sysfs_notify(mode_kobj, NULL, "aggr_iobusy");
-			pr_debug("msm_perf: Notifying IO: %u\n", aggr_iobusy);
-		}
-		if ((aggr_mode & (SINGLE | MULTI)) != cpu_mode) {
-			aggr_mode &= ~(SINGLE | MULTI);
-			aggr_mode |= cpu_mode;
-			sysfs_notify(mode_kobj, NULL, "aggr_mode");
-			pr_debug("msm_perf: Notifying CPU mode:%u\n",
-								aggr_mode);
-		}
-		if ((aggr_mode & PERF_CL_PEAK) != perf_cl_peak_mode) {
-			aggr_mode &= ~(PERF_CL_PEAK);
-			aggr_mode |= perf_cl_peak_mode;
-			sysfs_notify(mode_kobj, NULL, "aggr_mode");
-			pr_debug("msm_perf: Notifying Gaming mode:%u\n",
-								aggr_mode);
-		}
-	}
-
-	return 0;
-}
-
-static void check_cluster_iowait(struct cluster *cl, u64 now)
-{
-	struct load_stats *pcpu_st;
-	unsigned int i;
-	unsigned long flags;
-	unsigned int temp_iobusy;
-	u64 max_iowait = 0;
-
-	spin_lock_irqsave(&cl->iowait_lock, flags);
-
-	if (((now - cl->last_io_check_ts)
-		< (cl->timer_rate - LAST_IO_CHECK_TOL)) ||
-		!(workload_detect & IO_DETECT)) {
-		spin_unlock_irqrestore(&cl->iowait_lock, flags);
-		return;
-	}
-
-	temp_iobusy = cl->cur_io_busy;
-	for_each_cpu(i, cl->cpus) {
-		pcpu_st = &per_cpu(cpu_load_stats, i);
-		if ((now - pcpu_st->last_wallclock)
-			> (cl->timer_rate + LAST_UPDATE_TOL))
-			continue;
-		if (max_iowait < pcpu_st->last_iopercent)
-			max_iowait = pcpu_st->last_iopercent;
-	}
-
-	if (!cl->cur_io_busy) {
-		if (max_iowait > iowait_ceiling_pct) {
-			cl->iowait_enter_cycle_cnt++;
-			if (cl->iowait_enter_cycle_cnt >= io_enter_cycles) {
-				cl->cur_io_busy = 1;
-				cl->iowait_enter_cycle_cnt = 0;
-			}
-		} else {
-			cl->iowait_enter_cycle_cnt = 0;
-		}
-	} else {
-		if (max_iowait < iowait_floor_pct) {
-			cl->iowait_exit_cycle_cnt++;
-			if (cl->iowait_exit_cycle_cnt >= io_exit_cycles) {
-				cl->cur_io_busy = 0;
-				cl->iowait_exit_cycle_cnt = 0;
-			}
-		} else {
-			cl->iowait_exit_cycle_cnt = 0;
-		}
-	}
-
-	cl->last_io_check_ts = now;
-	trace_track_iowait(cpumask_first(cl->cpus), cl->iowait_enter_cycle_cnt,
-			cl->iowait_exit_cycle_cnt, cl->cur_io_busy, max_iowait);
-
-	if (temp_iobusy != cl->cur_io_busy) {
-		cl->io_change = true;
-		pr_debug("msm_perf: IO changed to %u\n", cl->cur_io_busy);
-	}
-
-	spin_unlock_irqrestore(&cl->iowait_lock, flags);
-	if (cl->io_change)
-		wake_up_process(notify_thread);
-}
-
-static void disable_timer(struct cluster *cl)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cl->timer_lock, flags);
-
-	if (del_timer(&cl->mode_exit_timer)) {
-		trace_single_cycle_exit_timer_stop(cpumask_first(cl->cpus),
-			cl->single_enter_cycles, cl->single_enter_cycle_cnt,
-			cl->single_exit_cycles, cl->single_exit_cycle_cnt,
-			cl->multi_enter_cycles, cl->multi_enter_cycle_cnt,
-			cl->multi_exit_cycles, cl->multi_exit_cycle_cnt,
-			cl->timer_rate, cl->mode);
-	}
-
-	spin_unlock_irqrestore(&cl->timer_lock, flags);
-}
-
-static void start_timer(struct cluster *cl)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&cl->timer_lock, flags);
-	if ((cl->mode & SINGLE) && !timer_pending(&cl->mode_exit_timer)) {
-		/* Set timer for the Cluster since there is none pending */
-		cl->mode_exit_timer.expires = get_jiffies_64() +
-		usecs_to_jiffies(cl->single_exit_cycles * cl->timer_rate);
-		cl->mode_exit_timer.data = cpumask_first(cl->cpus);
-		add_timer(&cl->mode_exit_timer);
-		trace_single_cycle_exit_timer_start(cpumask_first(cl->cpus),
-			cl->single_enter_cycles, cl->single_enter_cycle_cnt,
-			cl->single_exit_cycles, cl->single_exit_cycle_cnt,
-			cl->multi_enter_cycles, cl->multi_enter_cycle_cnt,
-			cl->multi_exit_cycles, cl->multi_exit_cycle_cnt,
-			cl->timer_rate, cl->mode);
-	}
-	spin_unlock_irqrestore(&cl->timer_lock, flags);
-}
-
-static void disable_perf_cl_peak_timer(struct cluster *cl)
-{
-
-	if (del_timer(&cl->perf_cl_peak_mode_exit_timer)) {
-		trace_perf_cl_peak_exit_timer_stop(cpumask_first(cl->cpus),
-			cl->perf_cl_peak_enter_cycles,
-			cl->perf_cl_peak_enter_cycle_cnt,
-			cl->perf_cl_peak_exit_cycles,
-			cl->perf_cl_peak_exit_cycle_cnt,
-			cl->timer_rate, cl->mode);
-	}
-
-}
-
-static void start_perf_cl_peak_timer(struct cluster *cl)
-{
-	if ((cl->mode & PERF_CL_PEAK) &&
-		!timer_pending(&cl->perf_cl_peak_mode_exit_timer)) {
-		/* Set timer for the Cluster since there is none pending */
-		cl->perf_cl_peak_mode_exit_timer.expires = get_jiffies_64() +
-		usecs_to_jiffies(cl->perf_cl_peak_exit_cycles * cl->timer_rate);
-		cl->perf_cl_peak_mode_exit_timer.data = cpumask_first(cl->cpus);
-		add_timer(&cl->perf_cl_peak_mode_exit_timer);
-		trace_perf_cl_peak_exit_timer_start(cpumask_first(cl->cpus),
-			cl->perf_cl_peak_enter_cycles,
-			cl->perf_cl_peak_enter_cycle_cnt,
-			cl->perf_cl_peak_exit_cycles,
-			cl->perf_cl_peak_exit_cycle_cnt,
-			cl->timer_rate, cl->mode);
-	}
-}
-
-static const struct input_device_id msm_perf_input_ids[] = {
-
-	{
-		.flags = INPUT_DEVICE_ID_MATCH_EVBIT,
-		.evbit = {BIT_MASK(EV_ABS)},
-		.absbit = { [BIT_WORD(ABS_MT_POSITION_X)] =
-			BIT_MASK(ABS_MT_POSITION_X) |
-			BIT_MASK(ABS_MT_POSITION_Y)},
-	},
-
-	{},
-};
-
-static void msm_perf_input_event_handler(struct input_handle *handle,
-					unsigned int type,
-					unsigned int code,
-					int value)
-{
-	if (type != EV_ABS)
-		return;
-
-	switch (code) {
-
-	case ABS_MT_POSITION_X:
-		ip_evts->evt_x_cnt++;
-		break;
-	case ABS_MT_POSITION_Y:
-		ip_evts->evt_y_cnt++;
-		break;
-
-	case ABS_MT_DISTANCE:
-		break;
-
-	case ABS_MT_PRESSURE:
-		break;
-
-	default:
-		break;
-
-	}
-}
-static int msm_perf_input_connect(struct input_handler *handler,
-				struct input_dev *dev,
-				const struct input_device_id *id)
-{
-	int rc;
-	struct input_handle *handle;
-
-	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
-	if (!handle)
-		return -ENOMEM;
-
-	handle->dev = dev;
-	handle->handler = handler;
-	handle->name = handler->name;
-
-	rc = input_register_handle(handle);
-	if (rc) {
-		pr_err("Failed to register handle\n");
-		goto error;
-	}
-
-	rc = input_open_device(handle);
-	if (rc) {
-		pr_err("Failed to open device\n");
-		goto error_unregister;
-	}
-	return 0;
-
-error_unregister:
-	input_unregister_handle(handle);
-error:
-	kfree(handle);
-	return rc;
-}
-
-static void  msm_perf_input_disconnect(struct input_handle *handle)
-{
-	input_close_device(handle);
-	input_unregister_handle(handle);
-	kfree(handle);
-}
-
-static void unregister_input_handler(void)
-{
-	if (handler != NULL) {
-		input_unregister_handler(handler);
-		input_events_handler_registered = false;
-	}
-}
-
-static int register_input_handler(void)
-{
-	int rc;
-
-	if (handler == NULL) {
-		handler = kzalloc(sizeof(*handler), GFP_KERNEL);
-		if (!handler)
-			return -ENOMEM;
-		handler->event = msm_perf_input_event_handler;
-		handler->connect = msm_perf_input_connect;
-		handler->disconnect = msm_perf_input_disconnect;
-		handler->name = "msm_perf";
-		handler->id_table = msm_perf_input_ids;
-		handler->private = NULL;
-	}
-	rc = input_register_handler(handler);
-	if (rc) {
-		pr_err("Unable to register the input handler for msm_perf\n");
-		kfree(handler);
-	} else {
-		input_events_handler_registered = true;
-	}
-	return rc;
-}
-
-static void check_perf_cl_peak_load(struct cluster *cl, u64 now)
-{
-	struct load_stats *pcpu_st;
-	unsigned int i, ret_mode, max_load = 0;
-	unsigned int total_load = 0, cpu_cnt = 0;
-	unsigned long flags;
-	bool cpu_of_cluster_zero = true;
-
-	spin_lock_irqsave(&cl->perf_cl_peak_lock, flags);
-
-	cpu_of_cluster_zero = cpumask_first(cl->cpus) ? false:true;
-	/*
-	 * If delta of last load to now < than timer_rate - ld check tolerance
-	 * which is 18ms OR if perf_cl_peak detection not set
-	 * OR the first CPU of Cluster is CPU 0 (LVT)
-	 * then return do nothing. We are interested only in SLVT
-	 */
-	if (((now - cl->last_perf_cl_check_ts)
-		< (cl->timer_rate - LAST_LD_CHECK_TOL)) ||
-		!(workload_detect & PERF_CL_PEAK_DETECT) ||
-		cpu_of_cluster_zero) {
-		spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
-		return;
-	}
-	for_each_cpu(i, cl->cpus) {
-		pcpu_st = &per_cpu(cpu_load_stats, i);
-		if ((now - pcpu_st->last_wallclock)
-			> (cl->timer_rate + LAST_UPDATE_TOL))
-			continue;
-		if (pcpu_st->cpu_load > max_load)
-			max_load = pcpu_st->cpu_load;
-		 /*
-		  * Save the frequency for the cpu of the cluster
-		  * This frequency is the most recent/current
-		  * as obtained due to a transition
-		  * notifier callback.
-		  */
-		cl->current_freq = pcpu_st->freq;
-	}
-	ret_mode = cl->perf_cl_peak;
-
-	if (!(cl->perf_cl_peak & PERF_CL_PEAK)) {
-		if (max_load >= cl->perf_cl_peak_enter_load &&
-			freq_greater_than_threshold(cl,
-				cpumask_first(cl->cpus))) {
-			/*
-			 * Reset the event count  for the first cycle
-			 * of perf_cl_peak we detect
-			 */
-			if (!cl->perf_cl_peak_enter_cycle_cnt)
-				ip_evts->evt_x_cnt = ip_evts->evt_y_cnt = 0;
-			cl->perf_cl_peak_enter_cycle_cnt++;
-			if (cl->perf_cl_peak_enter_cycle_cnt >=
-				cl->perf_cl_peak_enter_cycles) {
-				if (input_events_greater_than_threshold())
-					ret_mode |= PERF_CL_PEAK;
-				cl->perf_cl_peak_enter_cycle_cnt = 0;
-			}
-		} else {
-			cl->perf_cl_peak_enter_cycle_cnt = 0;
-			/* Reset the event count */
-			ip_evts->evt_x_cnt = ip_evts->evt_y_cnt = 0;
-		}
-	} else {
-		if (max_load >= cl->perf_cl_peak_exit_load &&
-			freq_greater_than_threshold(cl,
-				cpumask_first(cl->cpus))) {
-			cl->perf_cl_peak_exit_cycle_cnt = 0;
-			disable_perf_cl_peak_timer(cl);
-		} else {
-			start_perf_cl_peak_timer(cl);
-			cl->perf_cl_peak_exit_cycle_cnt++;
-			if (cl->perf_cl_peak_exit_cycle_cnt
-				>= cl->perf_cl_peak_exit_cycles) {
-				ret_mode &= ~PERF_CL_PEAK;
-				cl->perf_cl_peak_exit_cycle_cnt = 0;
-				disable_perf_cl_peak_timer(cl);
-			}
-		}
-	}
-
-	cl->last_perf_cl_check_ts = now;
-	if (ret_mode != cl->perf_cl_peak) {
-		pr_debug("msm_perf: Mode changed to %u\n", ret_mode);
-		cl->perf_cl_peak = ret_mode;
-		cl->perf_cl_detect_state_change = true;
-	}
-
-	trace_cpu_mode_detect(cpumask_first(cl->cpus), max_load,
-		cl->single_enter_cycle_cnt, cl->single_exit_cycle_cnt,
-		total_load, cl->multi_enter_cycle_cnt,
-		cl->multi_exit_cycle_cnt, cl->perf_cl_peak_enter_cycle_cnt,
-		cl->perf_cl_peak_exit_cycle_cnt, cl->mode, cpu_cnt);
-
-	spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
-
-	if (cl->perf_cl_detect_state_change)
-		wake_up_process(notify_thread);
-
-}
-
-static void check_cpu_load(struct cluster *cl, u64 now)
-{
-	struct load_stats *pcpu_st;
-	unsigned int i, max_load = 0, total_load = 0, ret_mode, cpu_cnt = 0;
-	unsigned int total_load_ceil, total_load_floor;
-	unsigned long flags;
-
-	spin_lock_irqsave(&cl->mode_lock, flags);
-
-	if (((now - cl->last_mode_check_ts)
-		< (cl->timer_rate - LAST_LD_CHECK_TOL)) ||
-		!(workload_detect & MODE_DETECT)) {
-		spin_unlock_irqrestore(&cl->mode_lock, flags);
-		return;
-	}
-
-	for_each_cpu(i, cl->cpus) {
-		pcpu_st = &per_cpu(cpu_load_stats, i);
-		if ((now - pcpu_st->last_wallclock)
-			> (cl->timer_rate + LAST_UPDATE_TOL))
-			continue;
-		if (pcpu_st->cpu_load > max_load)
-			max_load = pcpu_st->cpu_load;
-		total_load += pcpu_st->cpu_load;
-		cpu_cnt++;
-	}
-
-	if (cpu_cnt > 1) {
-		total_load_ceil = cl->pcpu_multi_enter_load * cpu_cnt;
-		total_load_floor = cl->pcpu_multi_exit_load * cpu_cnt;
-	} else {
-		total_load_ceil = UINT_MAX;
-		total_load_floor = UINT_MAX;
-	}
-
-	ret_mode = cl->mode;
-	if (!(cl->mode & SINGLE)) {
-		if (max_load >= cl->single_enter_load) {
-			cl->single_enter_cycle_cnt++;
-			if (cl->single_enter_cycle_cnt
-				>= cl->single_enter_cycles) {
-				ret_mode |= SINGLE;
-				cl->single_enter_cycle_cnt = 0;
-			}
-		} else {
-			cl->single_enter_cycle_cnt = 0;
-		}
-	} else {
-		if (max_load < cl->single_exit_load) {
-			start_timer(cl);
-			cl->single_exit_cycle_cnt++;
-			if (cl->single_exit_cycle_cnt
-				>= cl->single_exit_cycles) {
-				ret_mode &= ~SINGLE;
-				cl->single_exit_cycle_cnt = 0;
-				disable_timer(cl);
-			}
-		} else {
-			cl->single_exit_cycle_cnt = 0;
-			disable_timer(cl);
-		}
-	}
-
-	if (!(cl->mode & MULTI)) {
-		if (total_load >= total_load_ceil) {
-			cl->multi_enter_cycle_cnt++;
-			if (cl->multi_enter_cycle_cnt
-				>= cl->multi_enter_cycles) {
-				ret_mode |= MULTI;
-				cl->multi_enter_cycle_cnt = 0;
-			}
-		} else {
-			cl->multi_enter_cycle_cnt = 0;
-		}
-	} else {
-		if (total_load < total_load_floor) {
-			cl->multi_exit_cycle_cnt++;
-			if (cl->multi_exit_cycle_cnt
-				>= cl->multi_exit_cycles) {
-				ret_mode &= ~MULTI;
-				cl->multi_exit_cycle_cnt = 0;
-			}
-		} else {
-			cl->multi_exit_cycle_cnt = 0;
-		}
-	}
-
-	cl->last_mode_check_ts = now;
-
-	if (ret_mode != cl->mode) {
-		cl->mode = ret_mode;
-		cl->mode_change = true;
-		pr_debug("msm_perf: Mode changed to %u\n", ret_mode);
-	}
-
-	trace_cpu_mode_detect(cpumask_first(cl->cpus), max_load,
-		cl->single_enter_cycle_cnt, cl->single_exit_cycle_cnt,
-		total_load, cl->multi_enter_cycle_cnt,
-		cl->multi_exit_cycle_cnt, cl->perf_cl_peak_enter_cycle_cnt,
-		cl->perf_cl_peak_exit_cycle_cnt, cl->mode, cpu_cnt);
-
-	spin_unlock_irqrestore(&cl->mode_lock, flags);
-
-	if (cl->mode_change)
-		wake_up_process(notify_thread);
-}
-
-static void check_workload_stats(unsigned int cpu, unsigned int rate, u64 now)
-{
-	struct cluster *cl = NULL;
-	unsigned int i;
-
-	for (i = 0; i < num_clusters; i++) {
-		if (cpumask_test_cpu(cpu, managed_clusters[i]->cpus)) {
-			cl = managed_clusters[i];
-			break;
-		}
-	}
-	if (cl == NULL)
-		return;
-
-	cl->timer_rate = rate;
-	check_cluster_iowait(cl, now);
-	check_cpu_load(cl, now);
-	check_perf_cl_peak_load(cl, now);
-}
-
-static int perf_govinfo_notify(struct notifier_block *nb, unsigned long val,
-								void *data)
-{
-	struct cpufreq_govinfo *gov_info = data;
-	unsigned int cpu = gov_info->cpu;
-	struct load_stats *cpu_st = &per_cpu(cpu_load_stats, cpu);
-	u64 now, cur_iowait, time_diff, iowait_diff;
-
-	if (!clusters_inited || !workload_detect)
-		return NOTIFY_OK;
-
-	cur_iowait = get_cpu_iowait_time_us(cpu, &now);
-	if (cur_iowait >= cpu_st->last_iowait)
-		iowait_diff = cur_iowait - cpu_st->last_iowait;
-	else
-		iowait_diff = 0;
-
-	if (now > cpu_st->last_wallclock)
-		time_diff = now - cpu_st->last_wallclock;
-	else
-		return NOTIFY_OK;
-
-	if (iowait_diff <= time_diff) {
-		iowait_diff *= 100;
-		cpu_st->last_iopercent = div64_u64(iowait_diff, time_diff);
-	} else {
-		cpu_st->last_iopercent = 100;
-	}
-
-	cpu_st->last_wallclock = now;
-	cpu_st->last_iowait = cur_iowait;
-	cpu_st->cpu_load = gov_info->load;
-
-	 /*
-	  * Avoid deadlock in case governor notifier ran in the context
-	  * of notify_work thread
-	  */
-	if (current == notify_thread)
-		return NOTIFY_OK;
-
-	check_workload_stats(cpu, gov_info->sampling_rate_us, now);
-
-	return NOTIFY_OK;
-}
-
-static int perf_cputrans_notify(struct notifier_block *nb, unsigned long val,
-								void *data)
-{
-	struct cpufreq_freqs *freq = data;
-	unsigned int cpu = freq->cpu;
-	unsigned long flags;
-	unsigned int i;
-	struct cluster *cl = NULL;
-	struct load_stats *cpu_st = &per_cpu(cpu_load_stats, cpu);
-
-	if (!clusters_inited || !workload_detect)
-		return NOTIFY_OK;
-	for (i = 0; i < num_clusters; i++) {
-		if (cpumask_test_cpu(cpu, managed_clusters[i]->cpus)) {
-			cl = managed_clusters[i];
-			break;
-		}
-	}
-	if (cl == NULL)
-		return NOTIFY_OK;
-	if (val == CPUFREQ_POSTCHANGE) {
-		spin_lock_irqsave(&cl->perf_cl_peak_lock, flags);
-		cpu_st->freq = freq->new;
-		spin_unlock_irqrestore(&cl->perf_cl_peak_lock, flags);
-	}
-
-	/*
-	 * Avoid deadlock in case governor notifier ran in the context
-	 * of notify_work thread
-	 */
-	if (current == notify_thread)
-		return NOTIFY_OK;
-	return NOTIFY_OK;
-}
-
-static struct notifier_block perf_govinfo_nb = {
-	.notifier_call = perf_govinfo_notify,
-};
-
-static struct notifier_block perf_cputransitions_nb = {
-	.notifier_call = perf_cputrans_notify,
-};
-
-static void single_mod_exit_timer(unsigned long data)
-{
-	int i;
-	struct cluster *i_cl = NULL;
-	unsigned long flags;
-
-	if (!clusters_inited)
-		return;
-
-	for (i = 0; i < num_clusters; i++) {
-		if (cpumask_test_cpu(data,
-			managed_clusters[i]->cpus)) {
-			i_cl = managed_clusters[i];
-			break;
-		}
-	}
-
-	if (i_cl == NULL)
-		return;
-
-	spin_lock_irqsave(&i_cl->mode_lock, flags);
-	if (i_cl->mode & SINGLE) {
-		/* Disable SINGLE mode and exit since the timer expired */
-		i_cl->mode = i_cl->mode & ~SINGLE;
-		i_cl->single_enter_cycle_cnt = 0;
-		i_cl->single_exit_cycle_cnt = 0;
-		trace_single_mode_timeout(cpumask_first(i_cl->cpus),
-			i_cl->single_enter_cycles, i_cl->single_enter_cycle_cnt,
-			i_cl->single_exit_cycles, i_cl->single_exit_cycle_cnt,
-			i_cl->multi_enter_cycles, i_cl->multi_enter_cycle_cnt,
-			i_cl->multi_exit_cycles, i_cl->multi_exit_cycle_cnt,
-			i_cl->timer_rate, i_cl->mode);
-	}
-	spin_unlock_irqrestore(&i_cl->mode_lock, flags);
-	wake_up_process(notify_thread);
-}
-
-static void perf_cl_peak_mod_exit_timer(unsigned long data)
-{
-	int i;
-	struct cluster *i_cl = NULL;
-	unsigned long flags;
-
-	if (!clusters_inited)
-		return;
-
-	for (i = 0; i < num_clusters; i++) {
-		if (cpumask_test_cpu(data,
-			managed_clusters[i]->cpus)) {
-			i_cl = managed_clusters[i];
-			break;
-		}
-	}
 
-	if (i_cl == NULL)
-		return;
 
-	spin_lock_irqsave(&i_cl->perf_cl_peak_lock, flags);
-	if (i_cl->perf_cl_peak & PERF_CL_PEAK) {
-		/* Disable PERF_CL_PEAK mode and exit since the timer expired */
-		i_cl->perf_cl_peak = i_cl->perf_cl_peak & ~PERF_CL_PEAK;
-		i_cl->perf_cl_peak_enter_cycle_cnt = 0;
-		i_cl->perf_cl_peak_exit_cycle_cnt = 0;
-	}
-	spin_unlock_irqrestore(&i_cl->perf_cl_peak_lock, flags);
-	wake_up_process(notify_thread);
-}
 
 /* CPU Hotplug */
 static struct kobject *events_kobj;
@@ -2186,19 +254,18 @@
 	.notifier_call = perf_adjust_notify,
 };
 
-static void hotplug_notify(int action)
+static int hotplug_notify(unsigned int cpu)
 {
 	unsigned long flags;
 
-	if (!events_group.init_success)
-		return;
-
-	if ((action == CPU_ONLINE) || (action == CPU_DEAD)) {
+	if (events_group.init_success) {
 		spin_lock_irqsave(&(events_group.cpu_hotplug_lock), flags);
 		events_group.cpu_hotplug = true;
 		spin_unlock_irqrestore(&(events_group.cpu_hotplug_lock), flags);
 		wake_up_process(events_notify_thread);
 	}
+
+	return 0;
 }
 
 static int events_notify_userspace(void *data)
@@ -2233,138 +300,7 @@
 
 	return 0;
 }
-static int __ref msm_performance_cpu_callback(struct notifier_block *nfb,
-		unsigned long action, void *hcpu)
-{
-	uint32_t cpu = (uintptr_t)hcpu;
-	unsigned int i;
-	struct cluster *i_cl = NULL;
 
-	hotplug_notify(action);
-
-	if (!clusters_inited)
-		return NOTIFY_OK;
-
-	for (i = 0; i < num_clusters; i++) {
-		if (managed_clusters[i]->cpus == NULL)
-			return NOTIFY_OK;
-		if (cpumask_test_cpu(cpu, managed_clusters[i]->cpus)) {
-			i_cl = managed_clusters[i];
-			break;
-		}
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block __refdata msm_performance_cpu_notifier = {
-	.notifier_call = msm_performance_cpu_callback,
-};
-
-static int init_cluster_control(void)
-{
-	unsigned int i;
-	int ret = 0;
-
-	struct kobject *module_kobj;
-
-	managed_clusters = kcalloc(num_clusters, sizeof(struct cluster *),
-								GFP_KERNEL);
-	if (!managed_clusters)
-		return -ENOMEM;
-	for (i = 0; i < num_clusters; i++) {
-		managed_clusters[i] = kcalloc(1, sizeof(struct cluster),
-								GFP_KERNEL);
-		if (!managed_clusters[i]) {
-			ret = -ENOMEM;
-			goto error;
-		}
-		if (!alloc_cpumask_var(&managed_clusters[i]->cpus,
-		     GFP_KERNEL)) {
-			ret = -ENOMEM;
-			goto error;
-		}
-
-		managed_clusters[i]->single_enter_load = DEF_SINGLE_ENT;
-		managed_clusters[i]->single_exit_load = DEF_SINGLE_EX;
-		managed_clusters[i]->single_enter_cycles
-						= DEF_SINGLE_ENTER_CYCLE;
-		managed_clusters[i]->single_exit_cycles
-						= DEF_SINGLE_EXIT_CYCLE;
-		managed_clusters[i]->pcpu_multi_enter_load
-						= DEF_PCPU_MULTI_ENT;
-		managed_clusters[i]->pcpu_multi_exit_load = DEF_PCPU_MULTI_EX;
-		managed_clusters[i]->multi_enter_cycles = DEF_MULTI_ENTER_CYCLE;
-		managed_clusters[i]->multi_exit_cycles = DEF_MULTI_EXIT_CYCLE;
-		managed_clusters[i]->perf_cl_peak_enter_load =
-						DEF_PERF_CL_PEAK_ENT;
-		managed_clusters[i]->perf_cl_peak_exit_load =
-						DEF_PERF_CL_PEAK_EX;
-		managed_clusters[i]->perf_cl_peak_enter_cycles =
-						DEF_PERF_CL_PEAK_ENTER_CYCLE;
-		managed_clusters[i]->perf_cl_peak_exit_cycles =
-						DEF_PERF_CL_PEAK_EXIT_CYCLE;
-
-		/* Initialize trigger threshold */
-		thr.perf_cl_trigger_threshold = CLUSTER_1_THRESHOLD_FREQ;
-		thr.pwr_cl_trigger_threshold = CLUSTER_0_THRESHOLD_FREQ;
-		thr.ip_evt_threshold = INPUT_EVENT_CNT_THRESHOLD;
-		spin_lock_init(&(managed_clusters[i]->iowait_lock));
-		spin_lock_init(&(managed_clusters[i]->mode_lock));
-		spin_lock_init(&(managed_clusters[i]->timer_lock));
-		spin_lock_init(&(managed_clusters[i]->perf_cl_peak_lock));
-		init_timer(&managed_clusters[i]->mode_exit_timer);
-		managed_clusters[i]->mode_exit_timer.function =
-			single_mod_exit_timer;
-		init_timer(&managed_clusters[i]->perf_cl_peak_mode_exit_timer);
-		managed_clusters[i]->perf_cl_peak_mode_exit_timer.function =
-			perf_cl_peak_mod_exit_timer;
-	}
-
-	mutex_init(&managed_cpus_lock);
-
-	ip_evts = kcalloc(1, sizeof(struct input_events), GFP_KERNEL);
-	if (!ip_evts) {
-		ret = -ENOMEM;
-		goto error;
-	}
-	module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME);
-	if (!module_kobj) {
-		pr_err("msm_perf: Couldn't find module kobject\n");
-		ret = -ENOENT;
-		goto error;
-	}
-	mode_kobj = kobject_create_and_add("workload_modes", module_kobj);
-	if (!mode_kobj) {
-		pr_err("msm_perf: Failed to add mode_kobj\n");
-		ret = -ENOMEM;
-		kobject_put(module_kobj);
-		goto error;
-	}
-	ret = sysfs_create_group(mode_kobj, &attr_group);
-	if (ret) {
-		pr_err("msm_perf: Failed to create sysfs\n");
-		kobject_put(module_kobj);
-		kobject_put(mode_kobj);
-		goto error;
-	}
-	notify_thread = kthread_run(notify_userspace, NULL, "wrkld_notify");
-
-	clusters_inited = true;
-
-	return 0;
-
-error:
-	for (i = 0; i < num_clusters; i++) {
-		if (!managed_clusters[i])
-			break;
-		if (managed_clusters[i]->cpus)
-			free_cpumask_var(managed_clusters[i]->cpus);
-		kfree(managed_clusters[i]);
-	}
-	kfree(managed_clusters);
-	return ret;
-}
 
 static int init_events_group(void)
 {
@@ -2403,16 +339,17 @@
 static int __init msm_performance_init(void)
 {
 	unsigned int cpu;
+	int rc;
 
 	cpufreq_register_notifier(&perf_cpufreq_nb, CPUFREQ_POLICY_NOTIFIER);
-	cpufreq_register_notifier(&perf_govinfo_nb, CPUFREQ_GOVINFO_NOTIFIER);
-	cpufreq_register_notifier(&perf_cputransitions_nb,
-					CPUFREQ_TRANSITION_NOTIFIER);
 
 	for_each_present_cpu(cpu)
 		per_cpu(cpu_stats, cpu).max = UINT_MAX;
 
-	register_cpu_notifier(&msm_performance_cpu_notifier);
+	rc = cpuhp_setup_state_nocalls(CPUHP_AP_ONLINE,
+		"msm_performance_cpu_hotplug",
+		hotplug_notify,
+		NULL);
 
 	init_events_group();
 
diff --git a/drivers/soc/qcom/rpm-smd.c b/drivers/soc/qcom/rpm-smd.c
index 3fc7fbf..c29cfcb 100644
--- a/drivers/soc/qcom/rpm-smd.c
+++ b/drivers/soc/qcom/rpm-smd.c
@@ -31,7 +31,6 @@
 #include <linux/device.h>
 #include <linux/notifier.h>
 #include <linux/slab.h>
-#include <linux/workqueue.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_platform.h>
@@ -126,8 +125,6 @@
 	return atomic_notifier_chain_unregister(&msm_rpm_sleep_notifier, nb);
 }
 
-static struct workqueue_struct *msm_rpm_smd_wq;
-
 enum {
 	MSM_RPM_MSG_REQUEST_TYPE = 0,
 	MSM_RPM_MSG_TYPE_NR,
@@ -2120,15 +2117,6 @@
 
 	smd_disable_read_intr(msm_rpm_data.ch_info);
 
-	msm_rpm_smd_wq = alloc_workqueue("rpm-smd",
-				WQ_UNBOUND | WQ_MEM_RECLAIM | WQ_HIGHPRI, 1);
-	if (!msm_rpm_smd_wq) {
-		pr_err("%s: Unable to alloc rpm-smd workqueue\n", __func__);
-		ret = -EINVAL;
-		goto fail;
-	}
-	queue_work(msm_rpm_smd_wq, &msm_rpm_data.work);
-
 	probe_status = ret;
 skip_init:
 	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
diff --git a/drivers/soc/qcom/rq_stats.c b/drivers/soc/qcom/rq_stats.c
index 5850c46..1b4cf4f 100644
--- a/drivers/soc/qcom/rq_stats.c
+++ b/drivers/soc/qcom/rq_stats.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2010-2015, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2010-2015, 2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -264,7 +264,7 @@
 static ssize_t show_def_timer_ms(struct kobject *kobj,
 		struct kobj_attribute *attr, char *buf)
 {
-	int64_t diff;
+	uint64_t diff;
 	unsigned int udiff;
 
 	diff = ktime_to_ns(ktime_get()) - rq_info.def_start_time;
diff --git a/drivers/soc/qcom/watchdog_v2.c b/drivers/soc/qcom/watchdog_v2.c
index 8040d6d..5630dc0 100644
--- a/drivers/soc/qcom/watchdog_v2.c
+++ b/drivers/soc/qcom/watchdog_v2.c
@@ -701,7 +701,7 @@
 	wdog_dd->user_pet_complete = true;
 	wdog_dd->user_pet_enabled = false;
 	wake_up_process(wdog_dd->watchdog_task);
-	init_timer_deferrable(&wdog_dd->pet_timer);
+	init_timer(&wdog_dd->pet_timer);
 	wdog_dd->pet_timer.data = (unsigned long)wdog_dd;
 	wdog_dd->pet_timer.function = pet_task_wakeup;
 	wdog_dd->pet_timer.expires = jiffies + delay_time;
diff --git a/drivers/thermal/of-thermal.c b/drivers/thermal/of-thermal.c
index bb5f706..c662cd7 100644
--- a/drivers/thermal/of-thermal.c
+++ b/drivers/thermal/of-thermal.c
@@ -430,7 +430,16 @@
 	if (trip >= data->ntrips || trip < 0)
 		return -EDOM;
 
-	*temp = data->trips[trip].temperature;
+	if (data->senps && data->senps->ops->get_trip_temp) {
+		int ret;
+
+		ret = data->senps->ops->get_trip_temp(data->senps->sensor_data,
+						      trip, temp);
+		if (ret)
+			return ret;
+	} else {
+		*temp = data->trips[trip].temperature;
+	}
 
 	return 0;
 }
diff --git a/drivers/thermal/qcom/Kconfig b/drivers/thermal/qcom/Kconfig
index e7d6241..c3c662d 100644
--- a/drivers/thermal/qcom/Kconfig
+++ b/drivers/thermal/qcom/Kconfig
@@ -71,3 +71,24 @@
 	  voltage.
 
 	  If you want this support, you should say Y here.
+
+config MSM_BCL_PMIC5
+	bool "BCL driver for BCL peripherals in PMIC5"
+	depends on SPMI && THERMAL_OF
+	help
+	  Say Y here to enable this BCL driver for PMIC5. This driver
+	  provides routines to configure and monitor the BCL
+	  PMIC peripheral. This driver registers the battery current and
+	  voltage sensors with the thermal core framework and can take
+	  threshold input and notify the thermal core when the threshold is
+	  reached.
+
+config QTI_BCL_SOC_DRIVER
+	bool "QTI Battery state of charge sensor driver"
+	depends on THERMAL_OF
+	help
+	  This driver registers battery state of charge as a sensor with
+	  thermal zone. This sensor can monitor for state of charge
+	  threshold and notify the thermal framework.
+
+	  If you want this support, you should say Y here.
diff --git a/drivers/thermal/qcom/Makefile b/drivers/thermal/qcom/Makefile
index 257b714..b5b56c7 100644
--- a/drivers/thermal/qcom/Makefile
+++ b/drivers/thermal/qcom/Makefile
@@ -6,3 +6,5 @@
 obj-$(CONFIG_QTI_AOP_REG_COOLING_DEVICE) += regulator_aop_cdev.o
 obj-$(CONFIG_REGULATOR_COOLING_DEVICE) += regulator_cdev.o
 obj-$(CONFIG_QTI_QMI_COOLING_DEVICE) += thermal_mitigation_device_service_v01.o qmi_cooling.o
+obj-$(CONFIG_MSM_BCL_PMIC5) += bcl_pmic5.o
+obj-$(CONFIG_QTI_BCL_SOC_DRIVER) += bcl_soc.o
diff --git a/drivers/thermal/qcom/bcl_pmic5.c b/drivers/thermal/qcom/bcl_pmic5.c
new file mode 100644
index 0000000..9c35c79
--- /dev/null
+++ b/drivers/thermal/qcom/bcl_pmic5.c
@@ -0,0 +1,529 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+#include <linux/regmap.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/spmi.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/thermal.h>
+
+#include "../thermal_core.h"
+
+#define BCL_DRIVER_NAME       "bcl_pmic5"
+#define BCL_MONITOR_EN        0x46
+
+#define BCL_IBAT_HIGH         0x4B
+#define BCL_IBAT_TOO_HIGH     0x4C
+#define BCL_IBAT_READ         0x86
+#define BCL_IBAT_SCALING_UA   78127
+
+#define BCL_VBAT_READ         0x76
+#define BCL_VBAT_ADC_LOW      0x48
+#define BCL_VBAT_COMP_LOW     0x49
+#define BCL_VBAT_COMP_TLOW    0x4A
+#define BCL_VBAT_SCALING_UV   49827
+#define BCL_VBAT_NO_READING   127
+#define BCL_VBAT_BASE_MV      2000
+#define BCL_VBAT_INC_MV       25
+#define BCL_VBAT_MAX_MV       3600
+
+enum bcl_dev_type {
+	BCL_HIGH_IBAT,
+	BCL_VHIGH_IBAT,
+	BCL_LOW_VBAT,
+	BCL_VLOW_VBAT,
+	BCL_CLOW_VBAT,
+	BCL_TYPE_MAX,
+};
+
+static char bcl_int_names[BCL_TYPE_MAX][25] = {
+	"bcl-high-ibat",
+	"bcl-very-high-ibat",
+	"bcl-low-vbat",
+	"bcl-very-low-vbat",
+	"bcl-crit-low-vbat"
+};
+
+struct bcl_peripheral_data {
+	int                     irq_num;
+	long int		trip_thresh;
+	int                     last_val;
+	struct mutex            state_trans_lock;
+	bool			irq_enabled;
+	struct thermal_zone_of_device_ops ops;
+	struct thermal_zone_device *tz_dev;
+};
+
+struct bcl_device {
+	struct regmap			*regmap;
+	uint16_t			fg_bcl_addr;
+	struct bcl_peripheral_data	param[BCL_TYPE_MAX];
+};
+
+static struct bcl_device *bcl_perph;
+
+static int bcl_read_register(int16_t reg_offset, unsigned int *data)
+{
+	int ret = 0;
+
+	if (!bcl_perph) {
+		pr_err("BCL device not initialized\n");
+		return -EINVAL;
+	}
+	ret = regmap_read(bcl_perph->regmap,
+			       (bcl_perph->fg_bcl_addr + reg_offset),
+			       data);
+	if (ret < 0) {
+		pr_err("Error reading register %d. err:%d", reg_offset, ret);
+		return ret;
+	}
+
+	return ret;
+}
+
+static int bcl_write_general_register(int16_t reg_offset,
+					uint16_t base, uint8_t data)
+{
+	int  ret = 0;
+	uint8_t *write_buf = &data;
+
+	if (!bcl_perph) {
+		pr_err("BCL device not initialized\n");
+		return -EINVAL;
+	}
+	ret = regmap_write(bcl_perph->regmap, (base + reg_offset), *write_buf);
+	if (ret < 0) {
+		pr_err("Error reading register %d. err:%d", reg_offset, ret);
+		return ret;
+	}
+	pr_debug("wrote 0x%02x to 0x%04x\n", data, base + reg_offset);
+
+	return ret;
+}
+
+static int bcl_write_register(int16_t reg_offset, uint8_t data)
+{
+	return bcl_write_general_register(reg_offset,
+			bcl_perph->fg_bcl_addr, data);
+}
+
+static void convert_adc_to_vbat_thresh_val(int *val)
+{
+	/*
+	 * Threshold register is bit shifted from ADC MSB.
+	 * So the scaling factor is half.
+	 */
+	*val = (*val * BCL_VBAT_SCALING_UV) / 2000;
+}
+
+static void convert_adc_to_vbat_val(int *val)
+{
+	*val = (*val * BCL_VBAT_SCALING_UV) / 1000;
+}
+
+static void convert_ibat_to_adc_val(int *val)
+{
+	/*
+	 * Threshold register is bit shifted from ADC MSB.
+	 * So the scaling factor is half.
+	 */
+	*val = (*val * 2000) / BCL_IBAT_SCALING_UA;
+}
+
+static void convert_adc_to_ibat_val(int *val)
+{
+	*val = (*val * BCL_IBAT_SCALING_UA) / 1000;
+}
+
+static int bcl_set_ibat(void *data, int low, int high)
+{
+	int ret = 0, ibat_ua, thresh_value;
+	int8_t val = 0;
+	int16_t addr;
+	struct bcl_peripheral_data *bat_data =
+		(struct bcl_peripheral_data *)data;
+
+	mutex_lock(&bat_data->state_trans_lock);
+	thresh_value = high;
+	if (bat_data->trip_thresh == thresh_value)
+		goto set_trip_exit;
+
+	if (bat_data->irq_num && bat_data->irq_enabled) {
+		disable_irq_nosync(bat_data->irq_num);
+		bat_data->irq_enabled = false;
+	}
+	if (thresh_value == INT_MAX) {
+		bat_data->trip_thresh = thresh_value;
+		goto set_trip_exit;
+	}
+
+	ibat_ua = thresh_value;
+	convert_ibat_to_adc_val(&thresh_value);
+	val = (int8_t)thresh_value;
+	if (&bcl_perph->param[BCL_HIGH_IBAT] == bat_data) {
+		addr = BCL_IBAT_HIGH;
+		pr_debug("ibat high threshold:%d mA ADC:0x%02x\n",
+				ibat_ua, val);
+	} else if (&bcl_perph->param[BCL_VHIGH_IBAT] == bat_data) {
+		addr = BCL_IBAT_TOO_HIGH;
+		pr_debug("ibat too high threshold:%d mA ADC:0x%02x\n",
+				ibat_ua, val);
+	} else {
+		goto set_trip_exit;
+	}
+	ret = bcl_write_register(addr, val);
+	if (ret) {
+		pr_err("Error accessing BCL peripheral. err:%d\n", ret);
+		goto set_trip_exit;
+	}
+	bat_data->trip_thresh = ibat_ua;
+
+	if (bat_data->irq_num && !bat_data->irq_enabled) {
+		enable_irq(bat_data->irq_num);
+		bat_data->irq_enabled = true;
+	}
+
+set_trip_exit:
+	mutex_unlock(&bat_data->state_trans_lock);
+
+	return ret;
+}
+
+static int bcl_read_ibat(void *data, int *adc_value)
+{
+	int ret = 0;
+	unsigned int val = 0;
+	struct bcl_peripheral_data *bat_data =
+		(struct bcl_peripheral_data *)data;
+
+	*adc_value = val;
+	ret = bcl_read_register(BCL_IBAT_READ, &val);
+	if (ret) {
+		pr_err("BCL register read error. err:%d\n", ret);
+		goto bcl_read_exit;
+	}
+	*adc_value = val;
+	if (*adc_value == 0) {
+		/*
+		 * The sensor sometime can read a value 0 if there is
+		 * consequtive reads
+		 */
+		*adc_value = bat_data->last_val;
+	} else {
+		convert_adc_to_ibat_val(adc_value);
+		bat_data->last_val = *adc_value;
+	}
+	pr_debug("ibat:%d mA\n", bat_data->last_val);
+
+bcl_read_exit:
+	return ret;
+}
+
+static int bcl_get_vbat_trip(void *data, int type, int *trip)
+{
+	int ret = 0;
+	unsigned int val = 0;
+	struct bcl_peripheral_data *bat_data =
+		(struct bcl_peripheral_data *)data;
+	int16_t addr;
+
+	*trip = 0;
+	if (&bcl_perph->param[BCL_LOW_VBAT] == bat_data)
+		addr = BCL_VBAT_ADC_LOW;
+	else if (&bcl_perph->param[BCL_VLOW_VBAT] == bat_data)
+		addr = BCL_VBAT_COMP_LOW;
+	else if (&bcl_perph->param[BCL_CLOW_VBAT] == bat_data)
+		addr = BCL_VBAT_COMP_TLOW;
+	else
+		return -ENODEV;
+
+	ret = bcl_read_register(addr, &val);
+	if (ret) {
+		pr_err("BCL register read error. err:%d\n", ret);
+		return ret;
+	}
+
+	if (addr == BCL_VBAT_ADC_LOW) {
+		*trip = val;
+		convert_adc_to_vbat_thresh_val(trip);
+		pr_debug("vbat trip: %d mV\n", val);
+	} else {
+		*trip = 2250 + val * 25;
+		if (*trip > BCL_VBAT_MAX_MV)
+			*trip = BCL_VBAT_MAX_MV;
+		pr_debug("vbat-%s-low trip: %d mV\n",
+				(addr == BCL_VBAT_COMP_LOW) ?
+				"too" : "critical",
+				bat_data->irq_num);
+	}
+
+	return 0;
+}
+
+static int bcl_set_vbat(void *data, int low, int high)
+{
+	struct bcl_peripheral_data *bat_data =
+		(struct bcl_peripheral_data *)data;
+
+	mutex_lock(&bat_data->state_trans_lock);
+
+	if (low == INT_MIN &&
+		bat_data->irq_num && bat_data->irq_enabled) {
+		disable_irq_nosync(bat_data->irq_num);
+		bat_data->irq_enabled = false;
+		pr_debug("vbat: disable irq:%d\n", bat_data->irq_num);
+	} else if (low != INT_MIN &&
+		 bat_data->irq_num && !bat_data->irq_enabled) {
+		enable_irq(bat_data->irq_num);
+		bat_data->irq_enabled = true;
+		pr_debug("vbat: enable irq:%d\n", bat_data->irq_num);
+	}
+
+	/*
+	 * Vbat threshold's are pre-configured and cant be
+	 * programmed.
+	 */
+	mutex_unlock(&bat_data->state_trans_lock);
+
+	return 0;
+}
+
+static int bcl_read_vbat(void *data, int *adc_value)
+{
+	int ret = 0;
+	unsigned int val = 0;
+	struct bcl_peripheral_data *bat_data =
+		(struct bcl_peripheral_data *)data;
+
+	*adc_value = val;
+	ret = bcl_read_register(BCL_VBAT_READ, &val);
+	if (ret) {
+		pr_err("BCL register read error. err:%d\n", ret);
+		goto bcl_read_exit;
+	}
+	*adc_value = val;
+	if (*adc_value == BCL_VBAT_NO_READING) {
+		*adc_value = bat_data->last_val;
+	} else {
+		convert_adc_to_vbat_val(adc_value);
+		bat_data->last_val = *adc_value;
+	}
+	pr_debug("vbat:%d mv\n", bat_data->last_val);
+
+bcl_read_exit:
+	return ret;
+}
+
+static irqreturn_t bcl_handle_irq(int irq, void *data)
+{
+	struct bcl_peripheral_data *perph_data =
+		(struct bcl_peripheral_data *)data;
+
+	mutex_lock(&perph_data->state_trans_lock);
+	if (!perph_data->irq_enabled) {
+		WARN_ON(1);
+		disable_irq_nosync(irq);
+		perph_data->irq_enabled = false;
+		goto exit_intr;
+	}
+	mutex_unlock(&perph_data->state_trans_lock);
+	of_thermal_handle_trip(perph_data->tz_dev);
+
+	return IRQ_HANDLED;
+
+exit_intr:
+	mutex_unlock(&perph_data->state_trans_lock);
+	return IRQ_HANDLED;
+}
+
+static int bcl_get_devicetree_data(struct platform_device *pdev)
+{
+	int ret = 0;
+	const __be32 *prop = NULL;
+	struct device_node *dev_node = pdev->dev.of_node;
+
+	prop = of_get_address(dev_node, 0, NULL, NULL);
+	if (prop) {
+		bcl_perph->fg_bcl_addr = be32_to_cpu(*prop);
+		pr_debug("fg_user_adc@%04x\n", bcl_perph->fg_bcl_addr);
+	} else {
+		dev_err(&pdev->dev, "No fg_user_adc registers found\n");
+		return -ENODEV;
+	}
+
+	return ret;
+}
+
+static void bcl_fetch_trip(struct platform_device *pdev, const char *int_name,
+		struct bcl_peripheral_data *data,
+		irqreturn_t (*handle)(int, void *))
+{
+	int ret = 0, irq_num = 0;
+
+	mutex_lock(&data->state_trans_lock);
+	data->irq_num = 0;
+	data->irq_enabled = false;
+	if (!handle) {
+		mutex_unlock(&data->state_trans_lock);
+		return;
+	}
+
+	irq_num = platform_get_irq_byname(pdev, int_name);
+	if (irq_num) {
+		ret = devm_request_threaded_irq(&pdev->dev,
+				irq_num, NULL, handle,
+				IRQF_TRIGGER_RISING | IRQF_ONESHOT,
+				int_name, data);
+		if (ret) {
+			dev_err(&pdev->dev,
+				"Error requesting trip irq. err:%d",
+				ret);
+			mutex_unlock(&data->state_trans_lock);
+			return;
+		}
+		disable_irq_nosync(irq_num);
+		data->irq_num = irq_num;
+	}
+	mutex_unlock(&data->state_trans_lock);
+}
+
+static void bcl_vbat_init(struct platform_device *pdev,
+		enum bcl_dev_type type)
+{
+	struct bcl_peripheral_data *vbat = &bcl_perph->param[type];
+	irqreturn_t (*handle)(int, void *) = (type == BCL_LOW_VBAT) ?
+						bcl_handle_irq : NULL;
+
+	mutex_init(&vbat->state_trans_lock);
+	bcl_fetch_trip(pdev, bcl_int_names[type], vbat, handle);
+	vbat->ops.get_temp = bcl_read_vbat;
+	vbat->ops.set_trips = bcl_set_vbat;
+	vbat->ops.get_trip_temp = bcl_get_vbat_trip;
+	vbat->tz_dev = thermal_zone_of_sensor_register(&pdev->dev,
+				type, vbat, &vbat->ops);
+	if (IS_ERR(vbat->tz_dev)) {
+		pr_debug("vbat[%s] register failed. err:%ld\n",
+				bcl_int_names[type],
+				PTR_ERR(vbat->tz_dev));
+		vbat->tz_dev = NULL;
+		return;
+	}
+	thermal_zone_device_update(vbat->tz_dev, THERMAL_DEVICE_UP);
+}
+
+static void bcl_probe_vbat(struct platform_device *pdev)
+{
+	bcl_vbat_init(pdev, BCL_LOW_VBAT);
+	bcl_vbat_init(pdev, BCL_VLOW_VBAT);
+	bcl_vbat_init(pdev, BCL_CLOW_VBAT);
+}
+
+static void bcl_ibat_init(struct platform_device *pdev,
+				enum bcl_dev_type type)
+{
+	struct bcl_peripheral_data *ibat = &bcl_perph->param[type];
+	irqreturn_t (*handle)(int, void *) = (type == BCL_HIGH_IBAT) ?
+						bcl_handle_irq : NULL;
+
+	mutex_init(&ibat->state_trans_lock);
+	bcl_fetch_trip(pdev, bcl_int_names[type], ibat, handle);
+	ibat->ops.get_temp = bcl_read_ibat;
+	ibat->ops.set_trips = bcl_set_ibat;
+	ibat->tz_dev = thermal_zone_of_sensor_register(&pdev->dev,
+				type, ibat, &ibat->ops);
+	if (IS_ERR(ibat->tz_dev)) {
+		pr_debug("ibat:[%s] register failed. err:%ld\n",
+				bcl_int_names[type],
+				PTR_ERR(ibat->tz_dev));
+		ibat->tz_dev = NULL;
+		return;
+	}
+	thermal_zone_device_update(ibat->tz_dev, THERMAL_DEVICE_UP);
+}
+
+static void bcl_probe_ibat(struct platform_device *pdev)
+{
+	bcl_ibat_init(pdev, BCL_HIGH_IBAT);
+	bcl_ibat_init(pdev, BCL_VHIGH_IBAT);
+}
+
+static void bcl_configure_bcl_peripheral(void)
+{
+	bcl_write_register(BCL_MONITOR_EN, BIT(7));
+}
+
+static int bcl_remove(struct platform_device *pdev)
+{
+	int i = 0;
+
+	for (; i < BCL_TYPE_MAX; i++) {
+		if (!bcl_perph->param[i].tz_dev)
+			continue;
+		thermal_zone_of_sensor_unregister(&pdev->dev,
+				bcl_perph->param[i].tz_dev);
+	}
+	bcl_perph = NULL;
+
+	return 0;
+}
+
+static int bcl_probe(struct platform_device *pdev)
+{
+	bcl_perph = devm_kzalloc(&pdev->dev, sizeof(*bcl_perph), GFP_KERNEL);
+	if (!bcl_perph)
+		return -ENOMEM;
+
+	bcl_perph->regmap = dev_get_regmap(pdev->dev.parent, NULL);
+	if (!bcl_perph->regmap) {
+		dev_err(&pdev->dev, "Couldn't get parent's regmap\n");
+		return -EINVAL;
+	}
+
+	bcl_get_devicetree_data(pdev);
+	bcl_probe_ibat(pdev);
+	bcl_probe_vbat(pdev);
+	bcl_configure_bcl_peripheral();
+
+	dev_set_drvdata(&pdev->dev, bcl_perph);
+
+	return 0;
+}
+
+static const struct of_device_id bcl_match[] = {
+	{
+		.compatible = "qcom,msm-bcl-pmic5",
+	},
+	{},
+};
+
+static struct platform_driver bcl_driver = {
+	.probe  = bcl_probe,
+	.remove = bcl_remove,
+	.driver = {
+		.name           = BCL_DRIVER_NAME,
+		.owner          = THIS_MODULE,
+		.of_match_table = bcl_match,
+	},
+};
+
+builtin_platform_driver(bcl_driver);
diff --git a/drivers/thermal/qcom/bcl_soc.c b/drivers/thermal/qcom/bcl_soc.c
new file mode 100644
index 0000000..e4d5157
--- /dev/null
+++ b/drivers/thermal/qcom/bcl_soc.c
@@ -0,0 +1,192 @@
+/*
+ * Copyright (c) 2018, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s:%s " fmt, KBUILD_MODNAME, __func__
+
+#include <linux/module.h>
+#include <linux/workqueue.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/mutex.h>
+#include <linux/power_supply.h>
+#include <linux/thermal.h>
+
+#include "../thermal_core.h"
+
+#define BCL_DRIVER_NAME       "bcl_soc_peripheral"
+
+struct bcl_device {
+	struct notifier_block			psy_nb;
+	struct work_struct			soc_eval_work;
+	long int				trip_temp;
+	int					trip_val;
+	struct mutex				state_trans_lock;
+	bool					irq_enabled;
+	struct thermal_zone_device		*tz_dev;
+	struct thermal_zone_of_device_ops	ops;
+};
+
+static struct bcl_device *bcl_perph;
+
+static int bcl_set_soc(void *data, int low, int high)
+{
+	if (low == bcl_perph->trip_temp)
+		return 0;
+
+	mutex_lock(&bcl_perph->state_trans_lock);
+	pr_debug("low soc threshold:%d\n", low);
+	bcl_perph->trip_temp = low;
+	if (low == INT_MIN) {
+		bcl_perph->irq_enabled = false;
+		goto unlock_and_exit;
+	}
+	bcl_perph->irq_enabled = true;
+	schedule_work(&bcl_perph->soc_eval_work);
+
+unlock_and_exit:
+	mutex_unlock(&bcl_perph->state_trans_lock);
+	return 0;
+}
+
+static int bcl_read_soc(void *data, int *val)
+{
+	static struct power_supply *batt_psy;
+	union power_supply_propval ret = {0,};
+	int err = 0;
+
+	*val = 100;
+	if (!batt_psy)
+		batt_psy = power_supply_get_by_name("battery");
+	if (batt_psy) {
+		err = power_supply_get_property(batt_psy,
+				POWER_SUPPLY_PROP_CAPACITY, &ret);
+		if (err) {
+			pr_err("battery percentage read error:%d\n",
+				err);
+			return err;
+		}
+		*val = ret.intval;
+	}
+	pr_debug("soc:%d\n", *val);
+
+	return err;
+}
+
+static void bcl_evaluate_soc(struct work_struct *work)
+{
+	int battery_percentage;
+
+	if (bcl_read_soc(NULL, &battery_percentage))
+		return;
+
+	mutex_lock(&bcl_perph->state_trans_lock);
+	if (!bcl_perph->irq_enabled)
+		goto eval_exit;
+	if (battery_percentage > bcl_perph->trip_temp)
+		goto eval_exit;
+
+	bcl_perph->trip_val = battery_percentage;
+	mutex_unlock(&bcl_perph->state_trans_lock);
+	of_thermal_handle_trip(bcl_perph->tz_dev);
+
+	return;
+eval_exit:
+	mutex_unlock(&bcl_perph->state_trans_lock);
+}
+
+static int battery_supply_callback(struct notifier_block *nb,
+			unsigned long event, void *data)
+{
+	struct power_supply *psy = data;
+
+	if (strcmp(psy->desc->name, "battery"))
+		return NOTIFY_OK;
+	schedule_work(&bcl_perph->soc_eval_work);
+
+	return NOTIFY_OK;
+}
+
+static int bcl_soc_remove(struct platform_device *pdev)
+{
+	power_supply_unreg_notifier(&bcl_perph->psy_nb);
+	flush_work(&bcl_perph->soc_eval_work);
+	if (bcl_perph->tz_dev)
+		thermal_zone_of_sensor_unregister(&pdev->dev,
+				bcl_perph->tz_dev);
+
+	return 0;
+}
+
+static int bcl_soc_probe(struct platform_device *pdev)
+{
+	int ret = 0;
+
+	bcl_perph = devm_kzalloc(&pdev->dev, sizeof(*bcl_perph), GFP_KERNEL);
+	if (!bcl_perph)
+		return -ENOMEM;
+
+	mutex_init(&bcl_perph->state_trans_lock);
+	bcl_perph->ops.get_temp = bcl_read_soc;
+	bcl_perph->ops.set_trips = bcl_set_soc;
+	INIT_WORK(&bcl_perph->soc_eval_work, bcl_evaluate_soc);
+	bcl_perph->psy_nb.notifier_call = battery_supply_callback;
+
+	ret = power_supply_reg_notifier(&bcl_perph->psy_nb);
+	if (ret < 0) {
+		pr_err("soc notifier registration error. defer. err:%d\n",
+			ret);
+		ret = -EPROBE_DEFER;
+		goto bcl_soc_probe_exit;
+	}
+	bcl_perph->tz_dev = thermal_zone_of_sensor_register(&pdev->dev,
+				0, bcl_perph, &bcl_perph->ops);
+	if (IS_ERR(bcl_perph->tz_dev)) {
+		pr_err("soc TZ register failed. err:%ld\n",
+				PTR_ERR(bcl_perph->tz_dev));
+		ret = PTR_ERR(bcl_perph->tz_dev);
+		bcl_perph->tz_dev = NULL;
+		goto bcl_soc_probe_exit;
+	}
+	thermal_zone_device_update(bcl_perph->tz_dev, THERMAL_DEVICE_UP);
+	schedule_work(&bcl_perph->soc_eval_work);
+
+	dev_set_drvdata(&pdev->dev, bcl_perph);
+
+	return 0;
+
+bcl_soc_probe_exit:
+	bcl_soc_remove(pdev);
+	return ret;
+}
+
+static const struct of_device_id bcl_match[] = {
+	{
+		.compatible = "qcom,msm-bcl-soc",
+	},
+	{},
+};
+
+static struct platform_driver bcl_driver = {
+	.probe  = bcl_soc_probe,
+	.remove = bcl_soc_remove,
+	.driver = {
+		.name           = BCL_DRIVER_NAME,
+		.owner          = THIS_MODULE,
+		.of_match_table = bcl_match,
+	},
+};
+
+builtin_platform_driver(bcl_driver);
diff --git a/drivers/thermal/qcom/qti_virtual_sensor.c b/drivers/thermal/qcom/qti_virtual_sensor.c
index 9b4fae8..cc66f37 100644
--- a/drivers/thermal/qcom/qti_virtual_sensor.c
+++ b/drivers/thermal/qcom/qti_virtual_sensor.c
@@ -79,6 +79,18 @@
 				"apc1-l2-usr"},
 		.logic = VIRT_MAXIMUM,
 	},
+	{
+		.virt_zone_name = "hepta-cpu-max-step",
+		.num_sensors = 7,
+		.sensor_names = {"apc1-cpu0-usr",
+				"apc1-cpu1-usr",
+				"apc1-cpu2-usr",
+				"apc1-cpu3-usr",
+				"cpuss0-usr",
+				"cpuss1-usr",
+				"cpuss3-usr"},
+		.logic = VIRT_MAXIMUM,
+	},
 };
 
 int qti_virtual_sensor_register(struct device *dev)
diff --git a/drivers/usb/dwc3/core.c b/drivers/usb/dwc3/core.c
index e0321a1..edf855c 100644
--- a/drivers/usb/dwc3/core.c
+++ b/drivers/usb/dwc3/core.c
@@ -256,9 +256,9 @@
 
 	dwc3_writel(dwc->regs, DWC3_GUSB3PIPECTL(0), reg);
 
-	dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT);
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_RESET_EVENT, 0);
 
-	dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT);
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_POST_RESET_EVENT, 0);
 
 	return 0;
 }
@@ -366,7 +366,7 @@
 		dwc3_free_one_event_buffer(dwc, evt);
 
 	/* free GSI related event buffers */
-	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_FREE);
+	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_FREE, 0);
 }
 
 /**
@@ -389,7 +389,7 @@
 	dwc->ev_buf = evt;
 
 	/* alloc GSI related event buffers */
-	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_ALLOC);
+	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_ALLOC, 0);
 	return 0;
 }
 
@@ -420,7 +420,7 @@
 	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);
 
 	/* setup GSI related event buffers */
-	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_SETUP);
+	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_SETUP, 0);
 	return 0;
 }
 
@@ -442,7 +442,7 @@
 	dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), 0);
 
 	/* cleanup GSI related event buffers */
-	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEANUP);
+	dwc3_notify_event(dwc, DWC3_GSI_EVT_BUF_CLEANUP, 0);
 }
 
 static int dwc3_alloc_scratch_buffers(struct dwc3 *dwc)
@@ -1026,19 +1026,20 @@
 	dwc3_gadget_restart(dwc);
 }
 
-static void (*notify_event)(struct dwc3 *, unsigned int);
-void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned int))
+static void (*notify_event)(struct dwc3 *, unsigned int, unsigned int);
+void dwc3_set_notifier(void (*notify)(struct dwc3 *, unsigned int,
+							unsigned int))
 {
 	notify_event = notify;
 }
 EXPORT_SYMBOL(dwc3_set_notifier);
 
-int dwc3_notify_event(struct dwc3 *dwc, unsigned int event)
+int dwc3_notify_event(struct dwc3 *dwc, unsigned int event, unsigned int value)
 {
 	int ret = 0;
 
 	if (dwc->notify_event)
-		dwc->notify_event(dwc, event);
+		dwc->notify_event(dwc, event, value);
 	else
 		ret = -ENODEV;
 
@@ -1459,7 +1460,7 @@
 	int		ret;
 
 	/* Check if platform glue driver handling PM, if not then handle here */
-	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT))
+	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT, 0))
 		return 0;
 
 	ret = dwc3_suspend_common(dwc);
@@ -1477,7 +1478,7 @@
 	int		ret;
 
 	/* Check if platform glue driver handling PM, if not then handle here */
-	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT))
+	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT, 0))
 		return 0;
 
 	device_init_wakeup(dev, false);
@@ -1533,7 +1534,7 @@
 	int		ret;
 
 	/* Check if platform glue driver handling PM, if not then handle here */
-	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT))
+	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_SUSPEND_EVENT, 0))
 		return 0;
 
 	ret = dwc3_suspend_common(dwc);
@@ -1551,7 +1552,7 @@
 	int		ret;
 
 	/* Check if platform glue driver handling PM, if not then handle here */
-	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT))
+	if (!dwc3_notify_event(dwc, DWC3_CORE_PM_RESUME_EVENT, 0))
 		return 0;
 
 	pinctrl_pm_select_default_state(dev);
diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
index b91642a..69d3fa8 100644
--- a/drivers/usb/dwc3/core.h
+++ b/drivers/usb/dwc3/core.h
@@ -821,21 +821,22 @@
 	__le64	dma_adr[DWC3_MAX_HIBER_SCRATCHBUFS];
 };
 
-#define DWC3_CONTROLLER_ERROR_EVENT		0
-#define DWC3_CONTROLLER_RESET_EVENT		1
-#define DWC3_CONTROLLER_POST_RESET_EVENT	2
-#define DWC3_CORE_PM_SUSPEND_EVENT		3
-#define DWC3_CORE_PM_RESUME_EVENT		4
-#define DWC3_CONTROLLER_CONNDONE_EVENT		5
-#define DWC3_CONTROLLER_NOTIFY_OTG_EVENT	6
-#define DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT	7
-#define DWC3_CONTROLLER_RESTART_USB_SESSION	8
+#define DWC3_CONTROLLER_ERROR_EVENT			0
+#define DWC3_CONTROLLER_RESET_EVENT			1
+#define DWC3_CONTROLLER_POST_RESET_EVENT		2
+#define DWC3_CORE_PM_SUSPEND_EVENT			3
+#define DWC3_CORE_PM_RESUME_EVENT			4
+#define DWC3_CONTROLLER_CONNDONE_EVENT			5
+#define DWC3_CONTROLLER_NOTIFY_OTG_EVENT		6
+#define DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT		7
+#define DWC3_CONTROLLER_RESTART_USB_SESSION		8
+#define DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER		9
 
 /* USB GSI event buffer related notification */
-#define DWC3_GSI_EVT_BUF_ALLOC			9
-#define DWC3_GSI_EVT_BUF_SETUP			10
-#define DWC3_GSI_EVT_BUF_CLEANUP		11
-#define DWC3_GSI_EVT_BUF_FREE			12
+#define DWC3_GSI_EVT_BUF_ALLOC			10
+#define DWC3_GSI_EVT_BUF_SETUP			11
+#define DWC3_GSI_EVT_BUF_CLEANUP		12
+#define DWC3_GSI_EVT_BUF_FREE			13
 
 #define MAX_INTR_STATS				10
 
@@ -1081,7 +1082,7 @@
 	const char		*hsphy_interface;
 
 	unsigned		connected:1;
-	void (*notify_event)(struct dwc3 *, unsigned int);
+	void (*notify_event)(struct dwc3 *, unsigned int, unsigned int);
 	struct work_struct	wakeup_work;
 
 	unsigned		delayed_status:1;
@@ -1416,6 +1417,9 @@
 void dwc3_usb3_phy_suspend(struct dwc3 *dwc, int suspend);
 
 extern void dwc3_set_notifier(
-		void (*notify)(struct dwc3 *dwc3, unsigned int event));
-extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned int event);
+	void (*notify)(struct dwc3 *dwc3, unsigned int event,
+						unsigned int value));
+extern int dwc3_notify_event(struct dwc3 *dwc3, unsigned int event,
+							unsigned int value);
+
 #endif /* __DRIVERS_USB_DWC3_CORE_H */
diff --git a/drivers/usb/dwc3/dbm.c b/drivers/usb/dwc3/dbm.c
index 44c082a..48b3894 100644
--- a/drivers/usb/dwc3/dbm.c
+++ b/drivers/usb/dwc3/dbm.c
@@ -37,6 +37,7 @@
 	DBM_HW_TRB2_EP,
 	DBM_HW_TRB3_EP,
 	DBM_PIPE_CFG,
+	DBM_DISABLE_UPDXFER,
 	DBM_SOFT_RESET,
 	DBM_GEN_CFG,
 	DBM_GEVNTADR_LSB,
@@ -103,6 +104,7 @@
 	[DBM_HW_TRB2_EP]	= { 0x0240, 0x4 },
 	[DBM_HW_TRB3_EP]	= { 0x0250, 0x4 },
 	[DBM_PIPE_CFG]		= { 0x0274, 0x0 },
+	[DBM_DISABLE_UPDXFER]	= { 0x0298, 0x0 },
 	[DBM_SOFT_RESET]	= { 0x020C, 0x0 },
 	[DBM_GEN_CFG]		= { 0x0210, 0x0 },
 	[DBM_GEVNTADR_LSB]	= { 0x0260, 0x0 },
@@ -192,7 +194,7 @@
 		if (dbm->ep_num_mapping[i] == usb_ep)
 			return i;
 
-	pr_err("%s: No DBM EP matches USB EP %d", __func__, usb_ep);
+	pr_debug("%s: No DBM EP matches USB EP %d", __func__, usb_ep);
 	return -ENODEV; /* Not found */
 }
 
@@ -291,6 +293,7 @@
 {
 	int dbm_ep;
 	u32 ep_cfg;
+	u32 data;
 
 	if (!dbm) {
 		pr_err("%s: dbm pointer is NULL!\n", __func__);
@@ -312,9 +315,6 @@
 		return -ENODEV;
 	}
 
-	/* First, reset the dbm endpoint */
-	ep_soft_reset(dbm, dbm_ep, 0);
-
 	/* Set ioc bit for dbm_ep if needed */
 	msm_dbm_write_reg_field(dbm, DBM_DBG_CNFG,
 		DBM_ENABLE_IOC_MASK & 1 << dbm_ep, ioc ? 1 : 0);
@@ -337,6 +337,10 @@
 
 	msm_dbm_write_ep_reg_field(dbm, DBM_EP_CFG, dbm_ep, DBM_EN_EP, 1);
 
+	data = msm_dbm_read_reg(dbm, DBM_DISABLE_UPDXFER);
+	data &= ~(0x1 << dbm_ep);
+	msm_dbm_write_reg(dbm, DBM_DISABLE_UPDXFER, data);
+
 	return dbm_ep;
 }
 
@@ -381,7 +385,7 @@
 	dbm_ep = find_matching_dbm_ep(dbm, usb_ep);
 
 	if (dbm_ep < 0) {
-		pr_err("usb ep index %d has no corresponding dbm ep\n", usb_ep);
+		pr_debug("usb ep index %d has no corespondng dbm ep\n", usb_ep);
 		return -ENODEV;
 	}
 
@@ -391,23 +395,10 @@
 	data &= (~0x1);
 	msm_dbm_write_ep_reg(dbm, DBM_EP_CFG, dbm_ep, data);
 
-	/* Reset the dbm endpoint */
-	ep_soft_reset(dbm, dbm_ep, true);
 	/*
-	 * The necessary delay between asserting and deasserting the dbm ep
-	 * reset is based on the number of active endpoints. If there is more
-	 * than one endpoint, a 1 msec delay is required. Otherwise, a shorter
-	 * delay will suffice.
-	 *
-	 * As this function can be called in atomic context, sleeping variants
-	 * for delay are not possible - albeit a 1ms delay.
+	 * ep_soft_reset is not required during disconnect as pipe reset on
+	 * next connect will take care of the same.
 	 */
-	if (dbm_get_num_of_eps_configured(dbm) > 1)
-		udelay(1000);
-	else
-		udelay(10);
-	ep_soft_reset(dbm, dbm_ep, false);
-
 	return 0;
 }
 
@@ -449,6 +440,35 @@
 	return 0;
 }
 
+/**
+ * Disable update xfer before queueing stop xfer command to USB3 core.
+ *
+ * @usb_ep - USB physical EP number.
+ *
+ */
+int dwc3_dbm_disable_update_xfer(struct dbm *dbm, u8 usb_ep)
+{
+	u32 data;
+	int dbm_ep;
+
+	if (!dbm) {
+		pr_err("%s: dbm pointer is NULL!\n", __func__);
+		return -EPERM;
+	}
+
+	dbm_ep = find_matching_dbm_ep(dbm, usb_ep);
+
+	if (dbm_ep < 0) {
+		pr_err("usb ep index %d has no corresponding dbm ep\n", usb_ep);
+		return -ENODEV;
+	}
+
+	data = msm_dbm_read_reg(dbm, DBM_DISABLE_UPDXFER);
+	data |= (0x1 << dbm_ep);
+	msm_dbm_write_reg(dbm, DBM_DISABLE_UPDXFER, data);
+
+	return 0;
+}
 
 int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, unsigned long addr,
 				u32 size, u8 dst_pipe_idx)
diff --git a/drivers/usb/dwc3/dbm.h b/drivers/usb/dwc3/dbm.h
index d8e1ce9..259900d 100644
--- a/drivers/usb/dwc3/dbm.h
+++ b/drivers/usb/dwc3/dbm.h
@@ -65,6 +65,7 @@
 				int size);
 int dbm_data_fifo_config(struct dbm *dbm, u8 dep_num, unsigned long addr,
 				u32 size, u8 dst_pipe_idx);
+int dwc3_dbm_disable_update_xfer(struct dbm *dbm, u8 usb_ep);
 void dbm_set_speed(struct dbm *dbm, bool speed);
 void dbm_enable(struct dbm *dbm);
 int dbm_ep_soft_reset(struct dbm *dbm, u8 usb_ep, bool enter_reset);
diff --git a/drivers/usb/dwc3/dwc3-msm.c b/drivers/usb/dwc3/dwc3-msm.c
index a91dceb0..ded62f1 100644
--- a/drivers/usb/dwc3/dwc3-msm.c
+++ b/drivers/usb/dwc3/dwc3-msm.c
@@ -289,7 +289,8 @@
 
 static void dwc3_pwr_event_handler(struct dwc3_msm *mdwc);
 static int dwc3_msm_gadget_vbus_draw(struct dwc3_msm *mdwc, unsigned int mA);
-static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event);
+static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
+						unsigned int value);
 static int dwc3_restart_usb_host_mode(struct notifier_block *nb,
 					unsigned long event, void *ptr);
 
@@ -441,6 +442,16 @@
 	return dwc3_msm_is_dev_superspeed(mdwc);
 }
 
+static int dwc3_msm_dbm_disable_updxfer(struct dwc3 *dwc, u8 usb_ep)
+{
+	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
+
+	dev_dbg(mdwc->dev, "%s\n", __func__);
+	dwc3_dbm_disable_update_xfer(mdwc->dbm, usb_ep);
+
+	return 0;
+}
+
 #if IS_ENABLED(CONFIG_USB_DWC3_GADGET) || IS_ENABLED(CONFIG_USB_DWC3_DUAL_ROLE)
 /**
  * Configure the DBM with the BAM's data fifo.
@@ -697,67 +708,8 @@
 	struct dwc3_msm_req_complete *req_complete;
 	unsigned long flags;
 	int ret = 0, size;
-	u8 bam_pipe;
-	bool producer;
-	bool disable_wb;
-	bool internal_mem;
-	bool ioc;
 	bool superspeed;
 
-	if (!(request->udc_priv & MSM_SPS_MODE)) {
-		/* Not SPS mode, call original queue */
-		dev_vdbg(mdwc->dev, "%s: not sps mode, use regular queue\n",
-					__func__);
-
-		return (mdwc->original_ep_ops[dep->number])->queue(ep,
-								request,
-								gfp_flags);
-	}
-
-	/* HW restriction regarding TRB size (8KB) */
-	if (req->request.length < 0x2000) {
-		dev_err(mdwc->dev, "%s: Min TRB size is 8KB\n", __func__);
-		return -EINVAL;
-	}
-
-	/*
-	 * Override req->complete function, but before doing that,
-	 * store it's original pointer in the req_complete_list.
-	 */
-	req_complete = kzalloc(sizeof(*req_complete), gfp_flags);
-	if (!req_complete)
-		return -ENOMEM;
-
-	req_complete->req = request;
-	req_complete->orig_complete = request->complete;
-	list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
-	request->complete = dwc3_msm_req_complete_func;
-
-	/*
-	 * Configure the DBM endpoint
-	 */
-	bam_pipe = request->udc_priv & MSM_PIPE_ID_MASK;
-	producer = ((request->udc_priv & MSM_PRODUCER) ? true : false);
-	disable_wb = ((request->udc_priv & MSM_DISABLE_WB) ? true : false);
-	internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
-	ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
-
-	ret = dbm_ep_config(mdwc->dbm, dep->number, bam_pipe, producer,
-				disable_wb, internal_mem, ioc);
-	if (ret < 0) {
-		dev_err(mdwc->dev,
-			"error %d after calling dbm_ep_config\n", ret);
-		return ret;
-	}
-
-	dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n",
-			__func__, request, ep->name, request->length);
-	size = dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0));
-	dbm_event_buffer_config(mdwc->dbm,
-		dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
-		dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRHI(0)),
-		DWC3_GEVNTSIZ_SIZE(size));
-
 	/*
 	 * We must obtain the lock of the dwc3 core driver,
 	 * including disabling interrupts, so we will be sure
@@ -770,31 +722,83 @@
 		dev_err(mdwc->dev,
 			"%s: trying to queue request %p to disabled ep %s\n",
 			__func__, request, ep->name);
-		ret = -EPERM;
-		goto err;
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EPERM;
+	}
+
+	if (!mdwc->original_ep_ops[dep->number]) {
+		dev_err(mdwc->dev,
+			"ep [%s,%d] was unconfigured as msm endpoint\n",
+			ep->name, dep->number);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EINVAL;
+	}
+
+	if (!request) {
+		dev_err(mdwc->dev, "%s: request is NULL\n", __func__);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EINVAL;
+	}
+
+	if (!(request->udc_priv & MSM_SPS_MODE)) {
+		dev_err(mdwc->dev, "%s: sps mode is not set\n",
+					__func__);
+
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EINVAL;
+	}
+
+	/* HW restriction regarding TRB size (8KB) */
+	if (req->request.length < 0x2000) {
+		dev_err(mdwc->dev, "%s: Min TRB size is 8KB\n", __func__);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EINVAL;
 	}
 
 	if (dep->number == 0 || dep->number == 1) {
 		dev_err(mdwc->dev,
 			"%s: trying to queue dbm request %p to control ep %s\n",
 			__func__, request, ep->name);
-		ret = -EPERM;
-		goto err;
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EPERM;
 	}
 
-
-	if (dep->trb_dequeue != dep->trb_enqueue ||
-			!list_empty(&dep->pending_list)
-			|| !list_empty(&dep->started_list)) {
+	if (dep->trb_dequeue != dep->trb_enqueue
+					|| !list_empty(&dep->pending_list)
+					|| !list_empty(&dep->started_list)) {
 		dev_err(mdwc->dev,
 			"%s: trying to queue dbm request %p tp ep %s\n",
 			__func__, request, ep->name);
-		ret = -EPERM;
-		goto err;
-	} else {
-		dep->trb_dequeue = 0;
-		dep->trb_enqueue = 0;
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -EPERM;
 	}
+	dep->trb_dequeue = 0;
+	dep->trb_enqueue = 0;
+
+	/*
+	 * Override req->complete function, but before doing that,
+	 * store it's original pointer in the req_complete_list.
+	 */
+	req_complete = kzalloc(sizeof(*req_complete), gfp_flags);
+
+	if (!req_complete) {
+		dev_err(mdwc->dev, "%s: not enough memory\n", __func__);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return -ENOMEM;
+	}
+
+	req_complete->req = request;
+	req_complete->orig_complete = request->complete;
+	list_add_tail(&req_complete->list_item, &mdwc->req_complete_list);
+	request->complete = dwc3_msm_req_complete_func;
+
+	dev_vdbg(dwc->dev, "%s: queing request %p to ep %s length %d\n",
+			__func__, request, ep->name, request->length);
+	size = dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTSIZ(0));
+	dbm_event_buffer_config(mdwc->dbm,
+		dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRLO(0)),
+		dwc3_msm_read_reg(mdwc->base, DWC3_GEVNTADRHI(0)),
+		DWC3_GEVNTSIZ_SIZE(size));
 
 	ret = __dwc3_msm_ep_queue(dep, req);
 	if (ret < 0) {
@@ -1471,37 +1475,68 @@
  *
  * @return int - 0 on success, negetive on error.
  */
-int msm_ep_config(struct usb_ep *ep)
+int msm_ep_config(struct usb_ep *ep, struct usb_request *request)
 {
 	struct dwc3_ep *dep = to_dwc3_ep(ep);
 	struct dwc3 *dwc = dep->dwc;
 	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct usb_ep_ops *new_ep_ops;
+	int ret = 0;
+	u8 bam_pipe;
+	bool producer;
+	bool disable_wb;
+	bool internal_mem;
+	bool ioc;
+	unsigned long flags;
 
 
+	spin_lock_irqsave(&dwc->lock, flags);
 	/* Save original ep ops for future restore*/
 	if (mdwc->original_ep_ops[dep->number]) {
 		dev_err(mdwc->dev,
 			"ep [%s,%d] already configured as msm endpoint\n",
 			ep->name, dep->number);
+		spin_unlock_irqrestore(&dwc->lock, flags);
 		return -EPERM;
 	}
 	mdwc->original_ep_ops[dep->number] = ep->ops;
 
 	/* Set new usb ops as we like */
 	new_ep_ops = kzalloc(sizeof(struct usb_ep_ops), GFP_ATOMIC);
-	if (!new_ep_ops)
+	if (!new_ep_ops) {
+		spin_unlock_irqrestore(&dwc->lock, flags);
 		return -ENOMEM;
+	}
 
 	(*new_ep_ops) = (*ep->ops);
 	new_ep_ops->queue = dwc3_msm_ep_queue;
 	new_ep_ops->gsi_ep_op = dwc3_msm_gsi_ep_op;
 	ep->ops = new_ep_ops;
 
+	if (!mdwc->dbm || !request || (dep->endpoint.ep_type == EP_TYPE_GSI)) {
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return 0;
+	}
+
 	/*
-	 * Do HERE more usb endpoint configurations
-	 * which are specific to MSM.
+	 * Configure the DBM endpoint if required.
 	 */
+	bam_pipe = request->udc_priv & MSM_PIPE_ID_MASK;
+	producer = ((request->udc_priv & MSM_PRODUCER) ? true : false);
+	disable_wb = ((request->udc_priv & MSM_DISABLE_WB) ? true : false);
+	internal_mem = ((request->udc_priv & MSM_INTERNAL_MEM) ? true : false);
+	ioc = ((request->udc_priv & MSM_ETD_IOC) ? true : false);
+
+	ret = dbm_ep_config(mdwc->dbm, dep->number, bam_pipe, producer,
+					disable_wb, internal_mem, ioc);
+	if (ret < 0) {
+		dev_err(mdwc->dev,
+			"error %d after calling dbm_ep_config\n", ret);
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return ret;
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return 0;
 }
@@ -1522,12 +1557,15 @@
 	struct dwc3 *dwc = dep->dwc;
 	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct usb_ep_ops *old_ep_ops;
+	unsigned long flags;
 
+	spin_lock_irqsave(&dwc->lock, flags);
 	/* Restore original ep ops */
 	if (!mdwc->original_ep_ops[dep->number]) {
 		dev_err(mdwc->dev,
 			"ep [%s,%d] was not configured as msm endpoint\n",
 			ep->name, dep->number);
+		spin_unlock_irqrestore(&dwc->lock, flags);
 		return -EINVAL;
 	}
 	old_ep_ops = (struct usb_ep_ops	*)ep->ops;
@@ -1539,6 +1577,32 @@
 	 * Do HERE more usb endpoint un-configurations
 	 * which are specific to MSM.
 	 */
+	if (!mdwc->dbm || (dep->endpoint.ep_type == EP_TYPE_GSI)) {
+		spin_unlock_irqrestore(&dwc->lock, flags);
+		return 0;
+	}
+
+	if (dep->trb_dequeue == dep->trb_enqueue
+					&& list_empty(&dep->pending_list)
+					&& list_empty(&dep->started_list)) {
+		dev_dbg(mdwc->dev,
+			"%s: request is not queued, disable DBM ep for ep %s\n",
+			__func__, ep->name);
+		/* Unconfigure dbm ep */
+		dbm_ep_unconfig(mdwc->dbm, dep->number);
+
+		/*
+		 * If this is the last endpoint we unconfigured, than reset also
+		 * the event buffers; unless unconfiguring the ep due to lpm,
+		 * in which case the event buffer only gets reset during the
+		 * block reset.
+		 */
+		if (dbm_get_num_of_eps_configured(mdwc->dbm) == 0 &&
+				!dbm_reset_ep_after_lpm(mdwc->dbm))
+			dbm_event_buffer_config(mdwc->dbm, 0, 0, 0);
+	}
+
+	spin_unlock_irqrestore(&dwc->lock, flags);
 
 	return 0;
 }
@@ -1764,7 +1828,8 @@
 	dwc3_msm_gadget_vbus_draw(mdwc, dwc->vbus_draw);
 }
 
-static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event)
+static void dwc3_msm_notify_event(struct dwc3 *dwc, unsigned int event,
+							unsigned int value)
 {
 	struct dwc3_msm *mdwc = dev_get_drvdata(dwc->dev->parent);
 	struct dwc3_event_buffer *evt;
@@ -1951,6 +2016,9 @@
 							evt->buf, evt->dma);
 		}
 		break;
+	case DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER:
+		dwc3_msm_dbm_disable_updxfer(dwc, value);
+		break;
 	default:
 		dev_dbg(mdwc->dev, "unknown dwc3 event\n");
 		break;
@@ -3819,6 +3887,9 @@
 	if (on) {
 		dev_dbg(mdwc->dev, "%s: turn on host\n", __func__);
 
+		pm_runtime_get_sync(mdwc->dev);
+		dbg_event(0xFF, "StrtHost gync",
+			atomic_read(&mdwc->dev->power.usage_count));
 		mdwc->hs_phy->flags |= PHY_HOST_MODE;
 		if (dwc->maximum_speed == USB_SPEED_SUPER) {
 			mdwc->ss_phy->flags |= PHY_HOST_MODE;
@@ -3827,9 +3898,6 @@
 		}
 
 		usb_phy_notify_connect(mdwc->hs_phy, USB_SPEED_HIGH);
-		pm_runtime_get_sync(mdwc->dev);
-		dbg_event(0xFF, "StrtHost gync",
-			atomic_read(&mdwc->dev->power.usage_count));
 		if (!IS_ERR_OR_NULL(mdwc->vbus_reg))
 			ret = regulator_enable(mdwc->vbus_reg);
 		if (ret) {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 8f0ca3f..3157195 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -416,7 +416,7 @@
 		if (cmd != DWC3_DEPCMD_ENDTRANSFER) {
 			dwc->ep_cmd_timeout_cnt++;
 			dwc3_notify_event(dwc,
-				DWC3_CONTROLLER_RESTART_USB_SESSION);
+				DWC3_CONTROLLER_RESTART_USB_SESSION, 0);
 		}
 		cmd_status = -ETIMEDOUT;
 	}
@@ -2074,7 +2074,7 @@
 	dwc->vbus_draw = mA;
 	dev_dbg(dwc->dev, "Notify controller from %s. mA = %u\n", __func__, mA);
 	dbg_event(0xFF, "currentDraw", mA);
-	dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT);
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_SET_CURRENT_DRAW_EVENT, 0);
 	return 0;
 }
 
@@ -2105,7 +2105,8 @@
 	 * during enumeration.
 	 */
 	dwc->b_suspend = false;
-	dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
+
 	ret = dwc3_gadget_run_stop(dwc, is_on, false);
 	spin_unlock_irqrestore(&dwc->lock, flags);
 
@@ -2416,7 +2417,7 @@
 	struct dwc3		*dwc = gadget_to_dwc(g);
 
 	dbg_event(0xFF, "RestartUSBSession", 0);
-	return dwc3_notify_event(dwc, DWC3_CONTROLLER_RESTART_USB_SESSION);
+	return dwc3_notify_event(dwc, DWC3_CONTROLLER_RESTART_USB_SESSION, 0);
 }
 
 static const struct usb_gadget_ops dwc3_gadget_ops = {
@@ -2969,6 +2970,10 @@
 	if (!dep->resource_index)
 		return;
 
+	if (dep->endpoint.endless)
+		dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_DISABLE_UPDXFER,
+								dep->number);
+
 	/*
 	 * NOTICE: We are violating what the Databook says about the
 	 * EndTransfer command. Ideally we would _always_ wait for the
@@ -3062,7 +3067,7 @@
 	dbg_event(0xFF, "DISCONNECT INT", 0);
 	dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
 	dwc->b_suspend = false;
-	dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
 
 	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
 	reg &= ~DWC3_DCTL_INITU1ENA;
@@ -3122,7 +3127,7 @@
 	dbg_event(0xFF, "BUS RESET", 0);
 	dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
 	dwc->b_suspend = false;
-	dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
 
 	dwc3_usb3_phy_suspend(dwc, false);
 	usb_gadget_vbus_draw(&dwc->gadget, 100);
@@ -3297,7 +3302,8 @@
 		return;
 	}
 
-	dwc3_notify_event(dwc, DWC3_CONTROLLER_CONNDONE_EVENT);
+	dwc3_notify_event(dwc, DWC3_CONTROLLER_CONNDONE_EVENT, 0);
+
 	/*
 	 * Configure PHY via GUSB3PIPECTLn if required.
 	 *
@@ -3332,7 +3338,8 @@
 		 */
 		dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
 		dwc->b_suspend = false;
-		dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
+		dwc3_notify_event(dwc,
+				DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
 
 		/*
 		 * set state to U0 as function level resume is trying to queue
@@ -3476,7 +3483,7 @@
 
 		dev_dbg(dwc->dev, "Notify OTG from %s\n", __func__);
 		dwc->b_suspend = true;
-		dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT);
+		dwc3_notify_event(dwc, DWC3_CONTROLLER_NOTIFY_OTG_EVENT, 0);
 	}
 
 	dwc->link_state = next;
@@ -3640,7 +3647,8 @@
 			evt->lpos = (evt->lpos + left) %
 					DWC3_EVENT_BUFFERS_SIZE;
 			dwc3_writel(dwc->regs, DWC3_GEVNTCOUNT(0), left);
-			if (dwc3_notify_event(dwc, DWC3_CONTROLLER_ERROR_EVENT))
+			if (dwc3_notify_event(dwc,
+						DWC3_CONTROLLER_ERROR_EVENT, 0))
 				dwc->err_evt_seen = 0;
 			break;
 		}
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index a5659f99..75205bf 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -3808,6 +3808,7 @@
 	udc->gadget.max_speed    = USB_SPEED_HIGH;
 	udc->gadget.is_otg       = 0;
 	udc->gadget.name         = driver->name;
+	udc->gadget.is_chipidea  = true;
 
 	/* alloc resources */
 	udc->qh_pool = dma_pool_create("ci13xxx_qh", dev,
diff --git a/drivers/usb/gadget/composite.c b/drivers/usb/gadget/composite.c
index e85f24d..ae9e5e8 100644
--- a/drivers/usb/gadget/composite.c
+++ b/drivers/usb/gadget/composite.c
@@ -1773,7 +1773,8 @@
 				value = min(w_length, (u16) value);
 			break;
 		case USB_DT_BOS:
-			if (gadget_is_superspeed(gadget) ||
+			if ((gadget_is_superspeed(gadget) &&
+				(gadget->speed >= USB_SPEED_SUPER)) ||
 				!disable_l1_for_hs) {
 				value = bos_desc(cdev);
 				value = min(w_length, (u16) value);
diff --git a/drivers/usb/gadget/function/Makefile b/drivers/usb/gadget/function/Makefile
index 857c734..a9344a5 100644
--- a/drivers/usb/gadget/function/Makefile
+++ b/drivers/usb/gadget/function/Makefile
@@ -66,5 +66,5 @@
 obj-$(CONFIG_USB_F_QDSS)        += usb_f_qdss.o
 usb_f_qcrndis-y			:= f_qc_rndis.o u_data_ipa.o
 obj-$(CONFIG_USB_F_QCRNDIS)	+= usb_f_qcrndis.o
-usb_f_rmnet_bam-y		:= f_rmnet.o u_ctrl_qti.o
+usb_f_rmnet_bam-y		:= f_rmnet.o u_ctrl_qti.o u_bam_dmux.o
 obj-$(CONFIG_USB_F_RMNET_BAM)	+= usb_f_rmnet_bam.o
diff --git a/drivers/usb/gadget/function/f_audio_source.c b/drivers/usb/gadget/function/f_audio_source.c
index 2373262..aaa15da 100644
--- a/drivers/usb/gadget/function/f_audio_source.c
+++ b/drivers/usb/gadget/function/f_audio_source.c
@@ -396,15 +396,22 @@
 	s64 msecs;
 	s64 frames;
 	ktime_t now;
+	unsigned long flags;
 
+	spin_lock_irqsave(&audio->lock, flags);
 	/* audio->substream will be null if we have been closed */
-	if (!audio->substream)
+	if (!audio->substream) {
+		spin_unlock_irqrestore(&audio->lock, flags);
 		return;
+	}
 	/* audio->buffer_pos will be null if we have been stopped */
-	if (!audio->buffer_pos)
+	if (!audio->buffer_pos) {
+		spin_unlock_irqrestore(&audio->lock, flags);
 		return;
+	}
 
 	runtime = audio->substream->runtime;
+	spin_unlock_irqrestore(&audio->lock, flags);
 
 	/* compute number of frames to send */
 	now = ktime_get();
@@ -427,8 +434,21 @@
 
 	while (frames > 0) {
 		req = audio_req_get(audio);
-		if (!req)
+		spin_lock_irqsave(&audio->lock, flags);
+		/* audio->substream will be null if we have been closed */
+		if (!audio->substream) {
+			spin_unlock_irqrestore(&audio->lock, flags);
+			return;
+		}
+		/* audio->buffer_pos will be null if we have been stopped */
+		if (!audio->buffer_pos) {
+			spin_unlock_irqrestore(&audio->lock, flags);
+			return;
+		}
+		if (!req) {
+			spin_unlock_irqrestore(&audio->lock, flags);
 			break;
+		}
 
 		length = frames_to_bytes(runtime, frames);
 		if (length > IN_EP_MAX_PACKET_SIZE)
@@ -454,6 +474,7 @@
 		}
 
 		req->length = length;
+		spin_unlock_irqrestore(&audio->lock, flags);
 		ret = usb_ep_queue(audio->in_ep, req, GFP_ATOMIC);
 		if (ret < 0) {
 			pr_err("usb_ep_queue failed ret: %d\n", ret);
diff --git a/drivers/usb/gadget/function/f_gsi.c b/drivers/usb/gadget/function/f_gsi.c
index e7f072a..7d509db 100644
--- a/drivers/usb/gadget/function/f_gsi.c
+++ b/drivers/usb/gadget/function/f_gsi.c
@@ -2081,13 +2081,8 @@
 		/* for rndis and rmnet alt is always 0 update alt accordingly */
 		if (gsi->prot_id == IPA_USB_RNDIS ||
 				gsi->prot_id == IPA_USB_RMNET ||
-				gsi->prot_id == IPA_USB_DIAG) {
-			if (gsi->d_port.in_ep &&
-				!gsi->d_port.in_ep->driver_data)
+				gsi->prot_id == IPA_USB_DIAG)
 				alt = 1;
-			else
-				alt = 0;
-		}
 
 		if (alt > 1)
 			goto notify_ep_disable;
@@ -2380,7 +2375,7 @@
 		if (!ep)
 			goto fail;
 		gsi->d_port.in_ep = ep;
-		msm_ep_config(gsi->d_port.in_ep);
+		msm_ep_config(gsi->d_port.in_ep, NULL);
 		ep->driver_data = cdev;	/* claim */
 	}
 
@@ -2390,7 +2385,7 @@
 		if (!ep)
 			goto fail;
 		gsi->d_port.out_ep = ep;
-		msm_ep_config(gsi->d_port.out_ep);
+		msm_ep_config(gsi->d_port.out_ep, NULL);
 		ep->driver_data = cdev;	/* claim */
 	}
 
diff --git a/drivers/usb/gadget/function/f_qc_rndis.c b/drivers/usb/gadget/function/f_qc_rndis.c
index a8e7092..908805a 100644
--- a/drivers/usb/gadget/function/f_qc_rndis.c
+++ b/drivers/usb/gadget/function/f_qc_rndis.c
@@ -102,7 +102,7 @@
 	struct usb_ep			*notify;
 	struct usb_request		*notify_req;
 	atomic_t			notify_count;
-	struct gadget_ipa_port		bam_port;
+	struct data_port		bam_port;
 	struct cdev			cdev;
 	struct device			*dev;
 	u8				port_num;
diff --git a/drivers/usb/gadget/function/f_rmnet.c b/drivers/usb/gadget/function/f_rmnet.c
index d6d7e73..47b87b0a 100644
--- a/drivers/usb/gadget/function/f_rmnet.c
+++ b/drivers/usb/gadget/function/f_rmnet.c
@@ -19,7 +19,6 @@
 #include <linux/usb_bam.h>
 #include <linux/module.h>
 
-#include "u_rmnet.h"
 #include "u_data_ipa.h"
 #include "configfs.h"
 
@@ -31,13 +30,15 @@
 struct f_rmnet {
 	struct usb_function             func;
 	enum qti_port_type		qti_port_type;
-	enum ipa_func_type		func_type;
+	enum bam_dmux_func_type		bam_dmux_func_type;
+	enum data_xport_type		xport_type;
+	enum ipa_func_type		ipa_func_type;
 	struct grmnet			port;
 	int				ifc_id;
 	atomic_t			online;
 	atomic_t			ctrl_online;
 	struct usb_composite_dev	*cdev;
-	struct gadget_ipa_port		ipa_port;
+	struct data_port		bam_port;
 	spinlock_t			lock;
 
 	/* usb eps*/
@@ -308,11 +309,22 @@
 
 	if (!strncasecmp("rmnet", name, MAX_INST_NAME_LEN)) {
 		dev->qti_port_type = QTI_PORT_RMNET;
-		dev->func_type = USB_IPA_FUNC_RMNET;
+		dev->xport_type = BAM2BAM_IPA;
+		dev->ipa_func_type = USB_IPA_FUNC_RMNET;
 	} else if (!strncasecmp("dpl", name, MAX_INST_NAME_LEN)) {
 		dev->qti_port_type = QTI_PORT_DPL;
-		dev->func_type = USB_IPA_FUNC_DPL;
+		dev->xport_type = BAM2BAM_IPA;
+		dev->ipa_func_type = USB_IPA_FUNC_DPL;
+	} else if (!strncasecmp("rmnet_bam_dmux", name, MAX_INST_NAME_LEN)) {
+		dev->qti_port_type = QTI_PORT_RMNET;
+		dev->xport_type = BAM_DMUX;
+		dev->bam_dmux_func_type = BAM_DMUX_FUNC_RMNET;
+	} else if (!strncasecmp("dpl_bam_dmux", name, MAX_INST_NAME_LEN)) {
+		dev->qti_port_type = QTI_PORT_DPL;
+		dev->xport_type = BAM_DMUX;
+		dev->bam_dmux_func_type = BAM_DMUX_FUNC_DPL;
 	}
+
 	return 0;
 
 error:
@@ -380,7 +392,8 @@
 	enum usb_ctrl		usb_bam_type;
 	int bam_pipe_num = (dev->qti_port_type == QTI_PORT_DPL) ? 1 : 0;
 
-	ret = gqti_ctrl_connect(&dev->port, dev->qti_port_type, dev->ifc_id);
+	ret = gqti_ctrl_connect(&dev->port, dev->qti_port_type, dev->ifc_id,
+							dev->xport_type);
 	if (ret) {
 		pr_err("%s: gqti_ctrl_connect failed: err:%d\n",
 			__func__, ret);
@@ -388,31 +401,42 @@
 	}
 	if (dev->qti_port_type == QTI_PORT_DPL)
 		dev->port.send_encap_cmd(QTI_PORT_DPL, NULL, 0);
-	dev->ipa_port.cdev = dev->cdev;
-	ipa_data_port_select(dev->func_type);
-	usb_bam_type = usb_bam_get_bam_type(gadget->name);
+	dev->bam_port.cdev = dev->cdev;
+	if (dev->xport_type == BAM_DMUX) {
+		ret = gbam_connect(&dev->bam_port, dev->bam_dmux_func_type);
+		if (ret)
+			pr_err("%s: gbam_connect failed: err:%d\n",
+				__func__, ret);
+	} else {
+		ipa_data_port_select(dev->ipa_func_type);
+		usb_bam_type = usb_bam_get_bam_type(gadget->name);
 
-	if (dev->ipa_port.in) {
-		dst_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
-			IPA_P_BAM, PEER_PERIPHERAL_TO_USB,
-			USB_BAM_DEVICE, bam_pipe_num);
+		if (dev->bam_port.in) {
+			dst_connection_idx = usb_bam_get_connection_idx(
+						usb_bam_type, IPA_P_BAM,
+						PEER_PERIPHERAL_TO_USB,
+						USB_BAM_DEVICE, bam_pipe_num);
+		}
+		if (dev->bam_port.out) {
+			src_connection_idx = usb_bam_get_connection_idx(
+						usb_bam_type, IPA_P_BAM,
+						USB_TO_PEER_PERIPHERAL,
+						USB_BAM_DEVICE, bam_pipe_num);
+		}
+		if (dst_connection_idx < 0 || src_connection_idx < 0) {
+			pr_err("%s: usb_bam_get_connection_idx failed\n",
+				__func__);
+			gqti_ctrl_disconnect(&dev->port, dev->qti_port_type);
+			return -EINVAL;
+		}
+		ret = ipa_data_connect(&dev->bam_port, dev->ipa_func_type,
+				src_connection_idx, dst_connection_idx);
+		if (ret)
+			pr_err("%s: ipa_data_connect failed: err:%d\n",
+				__func__, ret);
 	}
-	if (dev->ipa_port.out) {
-		src_connection_idx = usb_bam_get_connection_idx(usb_bam_type,
-			IPA_P_BAM, USB_TO_PEER_PERIPHERAL,
-			USB_BAM_DEVICE, bam_pipe_num);
-	}
-	if (dst_connection_idx < 0 || src_connection_idx < 0) {
-		pr_err("%s: usb_bam_get_connection_idx failed\n",
-			__func__);
-		gqti_ctrl_disconnect(&dev->port, dev->qti_port_type);
-		return -EINVAL;
-	}
-	ret = ipa_data_connect(&dev->ipa_port, dev->func_type,
-			src_connection_idx, dst_connection_idx);
+
 	if (ret) {
-		pr_err("%s: ipa_data_connect failed: err:%d\n",
-			__func__, ret);
 		gqti_ctrl_disconnect(&dev->port, dev->qti_port_type);
 		return ret;
 	}
@@ -422,7 +446,11 @@
 static int gport_rmnet_disconnect(struct f_rmnet *dev)
 {
 	gqti_ctrl_disconnect(&dev->port, dev->qti_port_type);
-	ipa_data_disconnect(&dev->ipa_port, dev->func_type);
+	if (dev->xport_type == BAM_DMUX)
+		gbam_disconnect(&dev->bam_port, dev->bam_dmux_func_type);
+	else
+		ipa_data_disconnect(&dev->bam_port, dev->ipa_func_type);
+
 	return 0;
 }
 
@@ -488,7 +516,10 @@
 		usb_ep_fifo_flush(dev->notify);
 		frmnet_purge_responses(dev);
 	}
-	ipa_data_suspend(&dev->ipa_port, dev->func_type, remote_wakeup_allowed);
+
+	if (dev->xport_type == BAM2BAM_IPA)
+		ipa_data_suspend(&dev->bam_port, dev->ipa_func_type,
+							remote_wakeup_allowed);
 }
 
 static void frmnet_resume(struct usb_function *f)
@@ -503,8 +534,9 @@
 
 	pr_debug("%s: dev: %pK remote_wakeup: %d\n", __func__, dev,
 			remote_wakeup_allowed);
-
-	ipa_data_resume(&dev->ipa_port, dev->func_type, remote_wakeup_allowed);
+	if (dev->xport_type == BAM2BAM_IPA)
+		ipa_data_resume(&dev->bam_port, dev->ipa_func_type,
+							remote_wakeup_allowed);
 }
 
 static void frmnet_disable(struct usb_function *f)
@@ -557,20 +589,20 @@
 		dev->notify->driver_data = dev;
 	}
 
-	if (dev->ipa_port.in && !dev->ipa_port.in->desc
-		&& config_ep_by_speed(cdev->gadget, f, dev->ipa_port.in)) {
+	if (dev->bam_port.in && !dev->bam_port.in->desc
+		&& config_ep_by_speed(cdev->gadget, f, dev->bam_port.in)) {
 		pr_err("%s(): config_ep_by_speed failed.\n",
 				__func__);
-		dev->ipa_port.in->desc = NULL;
+		dev->bam_port.in->desc = NULL;
 		ret = -EINVAL;
 		goto err_disable_ep;
 	}
 
-	if (dev->ipa_port.out && !dev->ipa_port.out->desc
-		&& config_ep_by_speed(cdev->gadget, f, dev->ipa_port.out)) {
+	if (dev->bam_port.out && !dev->bam_port.out->desc
+		&& config_ep_by_speed(cdev->gadget, f, dev->bam_port.out)) {
 		pr_err("%s(): config_ep_by_speed failed.\n",
 				__func__);
-		dev->ipa_port.out->desc = NULL;
+		dev->bam_port.out->desc = NULL;
 		ret = -EINVAL;
 		goto err_disable_ep;
 	}
@@ -954,7 +986,7 @@
 					__func__);
 			return -ENODEV;
 		}
-		dev->ipa_port.in = ep;
+		dev->bam_port.in = ep;
 		ep->driver_data = cdev;
 	}
 
@@ -966,7 +998,7 @@
 			status = -ENODEV;
 			goto ep_auto_out_fail;
 		}
-		dev->ipa_port.out = ep;
+		dev->bam_port.out = ep;
 		ep->driver_data = cdev;
 	}
 
@@ -1058,11 +1090,11 @@
 		dev->notify->driver_data = NULL;
 		dev->notify = NULL;
 ep_auto_notify_fail:
-		dev->ipa_port.out->driver_data = NULL;
-		dev->ipa_port.out = NULL;
+		dev->bam_port.out->driver_data = NULL;
+		dev->bam_port.out = NULL;
 ep_auto_out_fail:
-		dev->ipa_port.in->driver_data = NULL;
-		dev->ipa_port.in = NULL;
+		dev->bam_port.in->driver_data = NULL;
+		dev->bam_port.in = NULL;
 
 	return status;
 }
@@ -1163,7 +1195,11 @@
 {
 	struct f_rmnet_opts *opts = container_of(f, struct f_rmnet_opts,
 						func_inst);
-	ipa_data_free(opts->dev->func_type);
+	if (opts->dev->xport_type == BAM_DMUX)
+		gbam_cleanup(opts->dev->bam_dmux_func_type);
+	else
+		ipa_data_free(opts->dev->ipa_func_type);
+
 	kfree(opts->dev);
 	kfree(opts);
 }
@@ -1194,14 +1230,20 @@
 	}
 
 	if (dev->qti_port_type >= QTI_NUM_PORTS ||
-		dev->func_type >= USB_IPA_NUM_FUNCS) {
+		dev->xport_type >= NR_XPORT_TYPES ||
+		dev->ipa_func_type >= USB_IPA_NUM_FUNCS ||
+		dev->bam_dmux_func_type >= BAM_DMUX_NUM_FUNCS) {
 		pr_err("%s: invalid prot\n", __func__);
 		ret = -EINVAL;
 		goto fail;
 	}
 
 	INIT_LIST_HEAD(&dev->cpkt_resp_q);
-	ret = ipa_data_setup(dev->func_type);
+	if (dev->xport_type == BAM_DMUX)
+		ret = gbam_setup(dev->bam_dmux_func_type);
+	else
+		ret = ipa_data_setup(dev->ipa_func_type);
+
 	if (ret)
 		goto fail;
 
diff --git a/drivers/usb/gadget/function/f_rndis.c b/drivers/usb/gadget/function/f_rndis.c
index 56a8e1b..6153c54 100644
--- a/drivers/usb/gadget/function/f_rndis.c
+++ b/drivers/usb/gadget/function/f_rndis.c
@@ -93,6 +93,9 @@
 	atomic_t			notify_count;
 };
 
+static struct f_rndis *__rndis;
+static spinlock_t _rndis_lock;
+
 static inline struct f_rndis *func_to_rndis(struct usb_function *f)
 {
 	return container_of(f, struct f_rndis, port.func);
@@ -422,10 +425,19 @@
 
 static void rndis_response_complete(struct usb_ep *ep, struct usb_request *req)
 {
-	struct f_rndis			*rndis = req->context;
-	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	struct f_rndis			*rndis;
+	struct usb_composite_dev	*cdev;
 	int				status = req->status;
+	struct usb_ep *notify_ep;
 
+	spin_lock(&_rndis_lock);
+	rndis = __rndis;
+	if (!rndis || !rndis->notify) {
+		spin_unlock(&_rndis_lock);
+		return;
+	}
+
+	cdev = rndis->port.func.config->cdev;
 	/* after TX:
 	 *  - USB_CDC_GET_ENCAPSULATED_RESPONSE (ep0/control)
 	 *  - RNDIS_RESPONSE_AVAILABLE (status/irq)
@@ -435,7 +447,7 @@
 	case -ESHUTDOWN:
 		/* connection gone */
 		atomic_set(&rndis->notify_count, 0);
-		break;
+		goto out;
 	default:
 		DBG(cdev, "RNDIS %s response error %d, %d/%d\n",
 			ep->name, status,
@@ -443,29 +455,53 @@
 		/* FALLTHROUGH */
 	case 0:
 		if (ep != rndis->notify)
-			break;
+			goto out;
 
 		/* handle multiple pending RNDIS_RESPONSE_AVAILABLE
 		 * notifications by resending until we're done
 		 */
 		if (atomic_dec_and_test(&rndis->notify_count))
-			break;
-		status = usb_ep_queue(rndis->notify, req, GFP_ATOMIC);
+			goto out;
+		notify_ep = rndis->notify;
+		spin_unlock(&_rndis_lock);
+		status = usb_ep_queue(notify_ep, req, GFP_ATOMIC);
 		if (status) {
-			atomic_dec(&rndis->notify_count);
+			spin_lock(&_rndis_lock);
+			if (!__rndis)
+				goto out;
+			atomic_dec(&__rndis->notify_count);
 			DBG(cdev, "notify/1 --> %d\n", status);
+			spin_unlock(&_rndis_lock);
 		}
-		break;
 	}
+
+	return;
+
+out:
+	spin_unlock(&_rndis_lock);
 }
 
 static void rndis_command_complete(struct usb_ep *ep, struct usb_request *req)
 {
-	struct f_rndis			*rndis = req->context;
-	struct usb_composite_dev	*cdev = rndis->port.func.config->cdev;
+	struct f_rndis			*rndis;
+	struct usb_composite_dev	*cdev;
 	int				status;
 	rndis_init_msg_type		*buf;
 
+	if (req->status != 0) {
+		pr_err("%s: RNDIS command completion error:%d\n",
+				__func__, req->status);
+		return;
+	}
+
+	spin_lock(&_rndis_lock);
+	rndis = __rndis;
+	if (!rndis || !rndis->notify) {
+		spin_unlock(&_rndis_lock);
+		return;
+	}
+
+	cdev = rndis->port.func.config->cdev;
 	/* received RNDIS command from USB_CDC_SEND_ENCAPSULATED_COMMAND */
 //	spin_lock(&dev->lock);
 	status = rndis_msg_parser(rndis->params, (u8 *) req->buf);
@@ -488,6 +524,7 @@
 			rndis->port.multi_pkt_xfer = 0;
 	}
 //	spin_unlock(&dev->lock);
+	spin_unlock(&_rndis_lock);
 }
 
 static int
@@ -639,13 +676,16 @@
 {
 	struct f_rndis		*rndis = func_to_rndis(f);
 	struct usb_composite_dev *cdev = f->config->cdev;
+	unsigned long flags;
 
 	if (!rndis->notify->enabled)
 		return;
 
 	DBG(cdev, "rndis deactivated\n");
 
+	spin_lock_irqsave(&_rndis_lock, flags);
 	rndis_uninit(rndis->params);
+	spin_unlock_irqrestore(&_rndis_lock, flags);
 	gether_disconnect(&rndis->port);
 
 	usb_ep_disable(rndis->notify);
@@ -793,7 +833,8 @@
 	rndis->notify_req = usb_ep_alloc_request(ep, GFP_KERNEL);
 	if (!rndis->notify_req)
 		goto fail;
-	rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT, GFP_KERNEL);
+	rndis->notify_req->buf = kmalloc(STATUS_BYTECOUNT +
+			cdev->gadget->extra_buf_alloc, GFP_KERNEL);
 	if (!rndis->notify_req->buf)
 		goto fail;
 	rndis->notify_req->length = STATUS_BYTECOUNT;
@@ -937,6 +978,7 @@
 	opts->rndis_os_desc.ext_compat_id = opts->rndis_ext_compat_id;
 
 	mutex_init(&opts->lock);
+	spin_lock_init(&_rndis_lock);
 	opts->func_inst.free_func_inst = rndis_free_inst;
 	opts->net = gether_setup_default();
 	if (IS_ERR(opts->net)) {
@@ -966,11 +1008,15 @@
 {
 	struct f_rndis *rndis;
 	struct f_rndis_opts *opts;
+	unsigned long flags;
 
 	rndis = func_to_rndis(f);
 	rndis_deregister(rndis->params);
 	opts = container_of(f->fi, struct f_rndis_opts, func_inst);
+	spin_lock_irqsave(&_rndis_lock, flags);
 	kfree(rndis);
+	__rndis = NULL;
+	spin_unlock_irqrestore(&_rndis_lock, flags);
 	mutex_lock(&opts->lock);
 	opts->refcnt--;
 	mutex_unlock(&opts->lock);
@@ -999,6 +1045,8 @@
 	if (!rndis)
 		return ERR_PTR(-ENOMEM);
 
+	__rndis = rndis;
+
 	opts = container_of(fi, struct f_rndis_opts, func_inst);
 	mutex_lock(&opts->lock);
 	opts->refcnt++;
diff --git a/drivers/usb/gadget/function/rndis.c b/drivers/usb/gadget/function/rndis.c
index 5d8e6fa..038993d 100644
--- a/drivers/usb/gadget/function/rndis.c
+++ b/drivers/usb/gadget/function/rndis.c
@@ -932,6 +932,7 @@
 	}
 #endif
 
+	spin_lock_init(&params->lock);
 	params->confignr = i;
 	params->used = 1;
 	params->state = RNDIS_UNINITIALIZED;
@@ -1096,29 +1097,36 @@
 void rndis_free_response(struct rndis_params *params, u8 *buf)
 {
 	rndis_resp_t *r, *n;
+	unsigned long flags;
 
+	spin_lock_irqsave(&params->lock, flags);
 	list_for_each_entry_safe(r, n, &params->resp_queue, list) {
 		if (r->buf == buf) {
 			list_del(&r->list);
 			kfree(r);
 		}
 	}
+	spin_unlock_irqrestore(&params->lock, flags);
 }
 EXPORT_SYMBOL_GPL(rndis_free_response);
 
 u8 *rndis_get_next_response(struct rndis_params *params, u32 *length)
 {
 	rndis_resp_t *r, *n;
+	unsigned long flags;
 
 	if (!length) return NULL;
 
+	spin_lock_irqsave(&params->lock, flags);
 	list_for_each_entry_safe(r, n, &params->resp_queue, list) {
 		if (!r->send) {
 			r->send = 1;
 			*length = r->length;
+			spin_unlock_irqrestore(&params->lock, flags);
 			return r->buf;
 		}
 	}
+	spin_unlock_irqrestore(&params->lock, flags);
 
 	return NULL;
 }
@@ -1127,6 +1135,7 @@
 static rndis_resp_t *rndis_add_response(struct rndis_params *params, u32 length)
 {
 	rndis_resp_t *r;
+	unsigned long flags;
 
 	/* NOTE: this gets copied into ether.c USB_BUFSIZ bytes ... */
 	r = kmalloc(sizeof(rndis_resp_t) + length, GFP_ATOMIC);
@@ -1136,7 +1145,9 @@
 	r->length = length;
 	r->send = 0;
 
+	spin_lock_irqsave(&params->lock, flags);
 	list_add_tail(&r->list, &params->resp_queue);
+	spin_unlock_irqrestore(&params->lock, flags);
 	return r;
 }
 
@@ -1144,7 +1155,7 @@
 			struct sk_buff *skb,
 			struct sk_buff_head *list)
 {
-	int num_pkts = 1;
+	int num_pkts = 0;
 
 	if (skb->len > rndis_ul_max_xfer_size_rcvd)
 		rndis_ul_max_xfer_size_rcvd = skb->len;
@@ -1154,12 +1165,6 @@
 		struct sk_buff          *skb2;
 		u32             msg_len, data_offset, data_len;
 
-		/* some rndis hosts send extra byte to avoid zlp, ignore it */
-		if (skb->len == 1) {
-			dev_kfree_skb_any(skb);
-			return 0;
-		}
-
 		if (skb->len < sizeof *hdr) {
 			pr_err("invalid rndis pkt: skblen:%u hdr_len:%zu",
 					skb->len, sizeof *hdr);
@@ -1188,9 +1193,12 @@
 			return -EINVAL;
 		}
 
+		num_pkts++;
+
 		skb_pull(skb, data_offset + 8);
 
-		if (msg_len == skb->len) {
+		if (data_len == skb->len ||
+				data_len == (skb->len - 1)) {
 			skb_trim(skb, data_len);
 			break;
 		}
@@ -1205,8 +1213,6 @@
 		skb_pull(skb, msg_len - sizeof *hdr);
 		skb_trim(skb2, data_len);
 		skb_queue_tail(list, skb2);
-
-		num_pkts++;
 	}
 
 	if (num_pkts > rndis_ul_max_pkt_per_xfer_rcvd)
@@ -1244,7 +1250,9 @@
 			 "speed     : %d\n"
 			 "cable     : %s\n"
 			 "vendor ID : 0x%08X\n"
-			 "vendor    : %s\n",
+			 "vendor    : %s\n"
+			 "ul-max-xfer-size:%zu max-xfer-size-rcvd: %d\n"
+			 "ul-max-pkts-per-xfer:%d max-pkts-per-xfer-rcvd:%d\n",
 			 param->confignr, (param->used) ? "y" : "n",
 			 ({ char *s = "?";
 			 switch (param->state) {
@@ -1258,7 +1266,13 @@
 			 param->medium,
 			 (param->media_state) ? 0 : param->speed*100,
 			 (param->media_state) ? "disconnected" : "connected",
-			 param->vendorID, param->vendorDescr);
+			 param->vendorID, param->vendorDescr,
+			 param->dev ? param->max_pkt_per_xfer *
+				 (param->dev->mtu + sizeof(struct ethhdr) +
+				 sizeof(struct rndis_packet_msg_type) + 22) : 0,
+			 rndis_ul_max_xfer_size_rcvd,
+			 param->max_pkt_per_xfer,
+			 rndis_ul_max_pkt_per_xfer_rcvd);
 	return 0;
 }
 
diff --git a/drivers/usb/gadget/function/rndis.h b/drivers/usb/gadget/function/rndis.h
index a3051c4..2211146 100644
--- a/drivers/usb/gadget/function/rndis.h
+++ b/drivers/usb/gadget/function/rndis.h
@@ -203,6 +203,7 @@
 
 	void			*v;
 	struct list_head	resp_queue;
+	spinlock_t		lock;
 } rndis_params;
 
 /* RNDIS Message parser and other useless functions */
diff --git a/drivers/usb/gadget/function/u_bam_dmux.c b/drivers/usb/gadget/function/u_bam_dmux.c
index 2ad184a..78dfe7b 100644
--- a/drivers/usb/gadget/function/u_bam_dmux.c
+++ b/drivers/usb/gadget/function/u_bam_dmux.c
@@ -21,6 +21,7 @@
 #include <linux/debugfs.h>
 #include <linux/bitops.h>
 #include <linux/termios.h>
+#include <linux/platform_device.h>
 
 #include <soc/qcom/bam_dmux.h>
 
@@ -28,32 +29,18 @@
 #include <linux/usb/usb_ctrl_qti.h>
 #include <linux/usb_bam.h>
 
-#include "usb_gadget_xport.h"
 #include "u_rmnet.h"
 
-#define BAM_N_PORTS	 2
-#define BAM2BAM_N_PORTS	 4
-
 static struct workqueue_struct *gbam_wq;
-static int n_bam_ports;
-static int n_bam2bam_ports;
 static unsigned int n_tx_req_queued;
 
-static unsigned int bam_ch_ids[BAM_N_PORTS] = {
+static unsigned int bam_ch_ids[BAM_DMUX_NUM_FUNCS] = {
+	BAM_DMUX_USB_RMNET_0,
 	BAM_DMUX_USB_RMNET_0,
 	BAM_DMUX_USB_DPL
 };
 
-static char bam_ch_names[BAM_N_PORTS][BAM_DMUX_CH_NAME_MAX_LEN];
-
-static const enum ipa_client_type usb_prod[BAM2BAM_N_PORTS] = {
-	IPA_CLIENT_USB_PROD, IPA_CLIENT_USB2_PROD,
-	IPA_CLIENT_USB3_PROD, IPA_CLIENT_USB4_PROD
-};
-static const enum ipa_client_type usb_cons[BAM2BAM_N_PORTS] = {
-	IPA_CLIENT_USB_CONS, IPA_CLIENT_USB2_CONS,
-	IPA_CLIENT_USB3_CONS, IPA_CLIENT_USB4_CONS
-};
+static char bam_ch_names[BAM_DMUX_NUM_FUNCS][BAM_DMUX_CH_NAME_MAX_LEN];
 
 #define BAM_PENDING_PKTS_LIMIT			220
 #define BAM_MUX_TX_PKT_DROP_THRESHOLD		1000
@@ -119,11 +106,6 @@
 	U_BAM_RESUME_E
 };
 
-struct sys2ipa_sw {
-	void		*teth_priv;
-	ipa_notify_cb	teth_cb;
-};
-
 struct bam_ch_info {
 	unsigned long		flags;
 	unsigned int		id;
@@ -141,22 +123,6 @@
 
 	struct usb_request	*rx_req;
 	struct usb_request	*tx_req;
-	bool			tx_req_dequeued;
-	bool			rx_req_dequeued;
-
-	u32			src_pipe_idx;
-	u32			dst_pipe_idx;
-	u8			src_connection_idx;
-	u8			dst_connection_idx;
-	enum usb_ctrl		usb_bam_type;
-
-	enum transport_type trans;
-	struct usb_bam_connect_ipa_params ipa_params;
-
-	/* added to support sys to ipa sw UL path */
-	struct sys2ipa_sw	ul_params;
-	enum usb_bam_pipe_type	src_pipe_type;
-	enum usb_bam_pipe_type	dst_pipe_type;
 
 	/* stats */
 	unsigned int		pending_pkts_with_bam;
@@ -184,21 +150,19 @@
 	spinlock_t		port_lock_dl;
 	spinlock_t		port_lock;
 
-	struct grmnet		*port_usb;
+	struct data_port	*port_usb;
 	struct usb_gadget	*gadget;
 
 	struct bam_ch_info	data_ch;
 
 	struct work_struct	connect_w;
 	struct work_struct	disconnect_w;
-	struct work_struct	suspend_w;
-	struct work_struct	resume_w;
 };
 
 static struct bam_portmaster {
 	struct gbam_port *port;
 	struct platform_driver pdrv;
-} bam_ports[BAM_N_PORTS];
+} bam_ports[BAM_DMUX_NUM_FUNCS];
 
 struct  u_bam_data_connect_info {
 	u32 usb_bam_pipe_idx;
@@ -206,10 +170,7 @@
 	unsigned long usb_bam_handle;
 };
 
-struct gbam_port *bam2bam_ports[BAM2BAM_N_PORTS];
 static void gbam_start_rx(struct gbam_port *port);
-static void gbam_start_endless_rx(struct gbam_port *port);
-static void gbam_start_endless_tx(struct gbam_port *port);
 static void gbam_notify(void *p, int event, unsigned long data);
 static void gbam_data_write_tobam(struct work_struct *w);
 
@@ -260,7 +221,6 @@
 	struct bam_ch_info *d;
 	struct sk_buff *skb;
 	dma_addr_t      skb_buf_dma_addr;
-	struct usb_gadget *gadget;
 
 	if (!port)
 		return NULL;
@@ -283,24 +243,7 @@
 			goto alloc_exit;
 
 		skb_reserve(skb, BAM_MUX_HDR);
-
-		if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-
-			gadget = port->port_usb->gadget;
-
-			skb_buf_dma_addr =
-				dma_map_single(&gadget->dev, skb->data,
-					bam_mux_rx_req_size, DMA_BIDIRECTIONAL);
-
-			if (dma_mapping_error(&gadget->dev, skb_buf_dma_addr)) {
-				pr_err("%s: Could not DMA map SKB buffer\n",
-					__func__);
-				skb_buf_dma_addr = DMA_ERROR_CODE;
-			}
-		} else {
-			skb_buf_dma_addr = DMA_ERROR_CODE;
-		}
-
+		skb_buf_dma_addr = DMA_ERROR_CODE;
 
 		memcpy(skb->cb, &skb_buf_dma_addr,
 			sizeof(skb_buf_dma_addr));
@@ -308,6 +251,9 @@
 	} else {
 		pr_debug("%s: pull skb from pool\n", __func__);
 		skb = __skb_dequeue(&d->rx_skb_idle);
+		if (!skb)
+			goto alloc_exit;
+
 		if (skb_headroom(skb) < BAM_MUX_HDR)
 			skb_reserve(skb, BAM_MUX_HDR);
 	}
@@ -341,10 +287,13 @@
 		return;
 	d = &port->data_ch;
 
-	gadget = port->port_usb->gadget;
+	gadget = port->port_usb->cdev->gadget;
 
 	while (d->rx_skb_idle.qlen > 0) {
 		skb = __skb_dequeue(&d->rx_skb_idle);
+		if (!skb)
+			break;
+
 		dma_addr = gbam_get_dma_from_skb(skb);
 
 		if (gadget && dma_addr != DMA_ERROR_CODE) {
@@ -359,36 +308,6 @@
 	}
 }
 
-/*----- sys2bam towards the IPA --------------- */
-static void gbam_ipa_sys2bam_notify_cb(void *priv, enum ipa_dp_evt_type event,
-		unsigned long data)
-{
-	struct sys2ipa_sw	*ul = (struct sys2ipa_sw *)priv;
-	struct gbam_port	*port;
-	struct bam_ch_info	*d;
-
-	switch (event) {
-	case IPA_WRITE_DONE:
-		d = container_of(ul, struct bam_ch_info, ul_params);
-		port = container_of(d, struct gbam_port, data_ch);
-		/* call into bam_demux functionality that'll recycle the data */
-		gbam_notify(port, BAM_DMUX_WRITE_DONE, data);
-		break;
-	case IPA_RECEIVE:
-		/* call the callback given by tethering driver init function
-		 * (and was given to ipa_connect)
-		 */
-		if (ul->teth_cb)
-			ul->teth_cb(ul->teth_priv, event, data);
-		break;
-	default:
-		/* unexpected event */
-		pr_err("%s: unexpected event %d\n", __func__, event);
-		break;
-	}
-}
-
-
 /*--------------------------------------------- */
 
 /*------------data_path----------------------------*/
@@ -485,7 +404,7 @@
 	gbam_write_data_tohost(port);
 }
 
-void gbam_data_recv_cb(void *p, struct sk_buff *skb)
+static void gbam_data_recv_cb(void *p, struct sk_buff *skb)
 {
 	struct gbam_port	*port = p;
 	struct bam_ch_info	*d = &port->data_ch;
@@ -506,8 +425,7 @@
 
 	if (d->tx_skb_q.qlen > bam_mux_tx_pkt_drop_thld) {
 		d->tohost_drp_cnt++;
-		if (printk_ratelimited())
-			pr_err("%s: tx pkt dropped: tx_drop_cnt:%u\n",
+		printk_ratelimited(KERN_ERR "%s: tx pkt dropped: tx_drop_cnt:%u\n",
 					__func__, d->tohost_drp_cnt);
 		spin_unlock_irqrestore(&port->port_lock_dl, flags);
 		dev_kfree_skb_any(skb);
@@ -520,7 +438,7 @@
 	gbam_write_data_tohost(port);
 }
 
-void gbam_data_write_done(void *p, struct sk_buff *skb)
+static void gbam_data_write_done(void *p, struct sk_buff *skb)
 {
 	struct gbam_port	*port = p;
 	struct bam_ch_info	*d = &port->data_ch;
@@ -599,10 +517,7 @@
 
 	set_bit(BAM_CH_WRITE_INPROGRESS, &d->flags);
 
-	while (!gbam_ul_bam_limit_reached(d) &&
-			(d->trans != USB_GADGET_XPORT_BAM2BAM_IPA ||
-			usb_bam_get_prod_granted(d->usb_bam_type,
-					d->dst_connection_idx))) {
+	while (!gbam_ul_bam_limit_reached(d)) {
 		skb =  __skb_dequeue(&d->rx_skb_q);
 		if (!skb)
 			break;
@@ -617,23 +532,7 @@
 				d->pending_bytes_with_bam, port->port_num);
 
 		spin_unlock_irqrestore(&port->port_lock_ul, flags);
-		if (d->src_pipe_type == USB_BAM_PIPE_SYS2BAM) {
-			dma_addr_t         skb_dma_addr;
-			struct ipa_tx_meta ipa_meta = {0x0};
-
-			skb_dma_addr = gbam_get_dma_from_skb(skb);
-			if (skb_dma_addr != DMA_ERROR_CODE) {
-				ipa_meta.dma_address = skb_dma_addr;
-				ipa_meta.dma_address_valid = true;
-			}
-
-			ret = ipa_tx_dp(usb_prod[port->port_num],
-				skb,
-				&ipa_meta);
-		} else {
-			ret = msm_bam_dmux_write(d->id, skb);
-		}
-
+		ret = msm_bam_dmux_write(d->id, skb);
 		spin_lock_irqsave(&port->port_lock_ul, flags);
 		if (ret) {
 			pr_debug("%s: write error:%d\n", __func__, ret);
@@ -723,14 +622,12 @@
 		spin_lock(&port->port_lock_ul);
 		gbam_free_skb_to_pool(port, skb);
 		spin_unlock(&port->port_lock_ul);
-		req->buf = 0;
+		req->buf = NULL;
 		usb_ep_free_request(ep, req);
 		return;
 	default:
-		if (printk_ratelimited())
-			pr_err("%s: %s response error %d, %d/%d\n",
-				__func__, ep->name, status,
-				req->actual, req->length);
+		printk_ratelimited(KERN_ERR "%s: %s response error %d, %d/%d\n",
+			__func__, ep->name, status, req->actual, req->length);
 		spin_lock(&port->port_lock_ul);
 		gbam_free_skb_to_pool(port, skb);
 		spin_unlock(&port->port_lock_ul);
@@ -741,14 +638,6 @@
 
 	if (queue) {
 		__skb_queue_tail(&d->rx_skb_q, skb);
-		if ((d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) &&
-			!usb_bam_get_prod_granted(d->usb_bam_type,
-					d->dst_connection_idx)) {
-			list_add_tail(&req->list, &d->rx_idle);
-			spin_unlock(&port->port_lock_ul);
-			return;
-		}
-
 		queue_work(gbam_wq, &d->write_tobam_w);
 	}
 
@@ -778,11 +667,6 @@
 	req->dma = gbam_get_dma_from_skb(skb);
 	req->length = bam_mux_rx_req_size;
 
-	if (req->dma != DMA_ERROR_CODE)
-		req->dma_pre_mapped = true;
-	else
-		req->dma_pre_mapped = false;
-
 	req->context = skb;
 
 	status = usb_ep_queue(ep, req, GFP_ATOMIC);
@@ -791,8 +675,7 @@
 		gbam_free_skb_to_pool(port, skb);
 		spin_unlock(&port->port_lock_ul);
 
-		if (printk_ratelimited())
-			pr_err("%s: data rx enqueue err %d\n",
+		printk_ratelimited(KERN_ERR "%s: data rx enqueue err %d\n",
 					__func__, status);
 
 		spin_lock(&port->port_lock_ul);
@@ -801,20 +684,6 @@
 	}
 }
 
-static void gbam_endless_rx_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	int status = req->status;
-
-	pr_debug("%s status: %d\n", __func__, status);
-}
-
-static void gbam_endless_tx_complete(struct usb_ep *ep, struct usb_request *req)
-{
-	int status = req->status;
-
-	pr_debug("%s status: %d\n", __func__, status);
-}
-
 static void gbam_start_rx(struct gbam_port *port)
 {
 	struct usb_request		*req;
@@ -850,11 +719,6 @@
 		req->dma = gbam_get_dma_from_skb(skb);
 		req->length = bam_mux_rx_req_size;
 
-		if (req->dma != DMA_ERROR_CODE)
-			req->dma_pre_mapped = true;
-		else
-			req->dma_pre_mapped = false;
-
 		req->context = skb;
 
 		spin_unlock_irqrestore(&port->port_lock_ul, flags);
@@ -863,8 +727,7 @@
 		if (ret) {
 			gbam_free_skb_to_pool(port, skb);
 
-			if (printk_ratelimited())
-				pr_err("%s: rx queue failed %d\n",
+			printk_ratelimited(KERN_ERR "%s: rx queue failed %d\n",
 							__func__, ret);
 
 			if (port->port_usb)
@@ -878,182 +741,6 @@
 	spin_unlock_irqrestore(&port->port_lock_ul, flags);
 }
 
-static void gbam_start_endless_rx(struct gbam_port *port)
-{
-	struct bam_ch_info *d = &port->data_ch;
-	int status;
-	struct usb_ep *ep;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->port_lock_ul, flags);
-	if (!port->port_usb || !d->rx_req) {
-		spin_unlock_irqrestore(&port->port_lock_ul, flags);
-		pr_err("%s: port->port_usb is NULL", __func__);
-		return;
-	}
-
-	ep = port->port_usb->out;
-	spin_unlock_irqrestore(&port->port_lock_ul, flags);
-	pr_debug("%s: enqueue\n", __func__);
-	status = usb_ep_queue(ep, d->rx_req, GFP_ATOMIC);
-	if (status)
-		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
-}
-
-static void gbam_start_endless_tx(struct gbam_port *port)
-{
-	struct bam_ch_info *d = &port->data_ch;
-	int status;
-	struct usb_ep *ep;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->port_lock_dl, flags);
-	if (!port->port_usb || !d->tx_req) {
-		spin_unlock_irqrestore(&port->port_lock_dl, flags);
-		pr_err("%s: port->port_usb is NULL", __func__);
-		return;
-	}
-
-	ep = port->port_usb->in;
-	spin_unlock_irqrestore(&port->port_lock_dl, flags);
-	pr_debug("%s: enqueue\n", __func__);
-	status = usb_ep_queue(ep, d->tx_req, GFP_ATOMIC);
-	if (status)
-		pr_err("%s: error enqueuing transfer, %d\n", __func__, status);
-}
-
-static void gbam_stop_endless_rx(struct gbam_port *port)
-{
-	struct bam_ch_info *d = &port->data_ch;
-	int status;
-	unsigned long flags;
-	struct usb_ep *ep;
-
-	spin_lock_irqsave(&port->port_lock_ul, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock_ul, flags);
-		pr_err("%s: port->port_usb is NULL", __func__);
-		return;
-	}
-
-	ep = port->port_usb->out;
-	d->rx_req_dequeued = true;
-	spin_unlock_irqrestore(&port->port_lock_ul, flags);
-	pr_debug("%s: dequeue\n", __func__);
-	status = usb_ep_dequeue(ep, d->rx_req);
-	if (status)
-		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
-}
-
-static void gbam_stop_endless_tx(struct gbam_port *port)
-{
-	struct bam_ch_info *d = &port->data_ch;
-	int status;
-	unsigned long flags;
-	struct usb_ep *ep;
-
-	spin_lock_irqsave(&port->port_lock_dl, flags);
-	if (!port->port_usb) {
-		spin_unlock_irqrestore(&port->port_lock_dl, flags);
-		pr_err("%s: port->port_usb is NULL", __func__);
-		return;
-	}
-
-	ep = port->port_usb->in;
-	d->tx_req_dequeued = true;
-	spin_unlock_irqrestore(&port->port_lock_dl, flags);
-	pr_debug("%s: dequeue\n", __func__);
-	status = usb_ep_dequeue(ep, d->tx_req);
-	if (status)
-		pr_err("%s: error dequeuing transfer, %d\n", __func__, status);
-}
-
-
-/*
- * This function configured data fifo based on index passed to get bam2bam
- * configuration.
- */
-static void configure_data_fifo(enum usb_ctrl bam_type, u8 idx,
-		struct usb_ep *ep, enum usb_bam_pipe_type pipe_type)
-{
-	struct u_bam_data_connect_info bam_info;
-	struct sps_mem_buffer data_fifo = {0};
-
-	if (pipe_type == USB_BAM_PIPE_BAM2BAM) {
-		get_bam2bam_connection_info(bam_type, idx,
-				&bam_info.usb_bam_pipe_idx,
-				NULL, &data_fifo, NULL);
-
-		msm_data_fifo_config(ep,
-				data_fifo.phys_base,
-				data_fifo.size,
-				bam_info.usb_bam_pipe_idx);
-	}
-}
-
-
-static void gbam_start(void *param, enum usb_bam_pipe_dir dir)
-{
-	struct gbam_port *port = param;
-	struct usb_gadget *gadget = NULL;
-	struct bam_ch_info *d;
-	unsigned long flags;
-
-	if (port == NULL) {
-		pr_err("%s: port is NULL\n", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (port->port_usb == NULL) {
-		pr_err("%s: port_usb is NULL, disconnected\n", __func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return;
-	}
-
-	gadget = port->port_usb->gadget;
-	d = &port->data_ch;
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	if (gadget == NULL) {
-		pr_err("%s: gadget is NULL\n", __func__);
-		return;
-	}
-
-	if (dir == USB_TO_PEER_PERIPHERAL) {
-		if (port->data_ch.src_pipe_type == USB_BAM_PIPE_BAM2BAM)
-			gbam_start_endless_rx(port);
-		else {
-			gbam_start_rx(port);
-			queue_work(gbam_wq, &d->write_tobam_w);
-		}
-	} else {
-		if (gadget_is_dwc3(gadget) &&
-		    msm_dwc3_reset_ep_after_lpm(gadget)) {
-			configure_data_fifo(d->usb_bam_type,
-				d->dst_connection_idx,
-				port->port_usb->in, d->dst_pipe_type);
-		}
-		gbam_start_endless_tx(port);
-	}
-}
-
-static void gbam_stop(void *param, enum usb_bam_pipe_dir dir)
-{
-	struct gbam_port *port = param;
-
-	if (dir == USB_TO_PEER_PERIPHERAL) {
-		/*
-		 * Only handling BAM2BAM, as there is no equivalent to
-		 * gbam_stop_endless_rx() for the SYS2BAM use case
-		 */
-		if (port->data_ch.src_pipe_type == USB_BAM_PIPE_BAM2BAM)
-			gbam_stop_endless_rx(port);
-	} else {
-		gbam_stop_endless_tx(port);
-	}
-}
-
 static int _gbam_start_io(struct gbam_port *port, bool in)
 {
 	unsigned long		flags;
@@ -1222,52 +909,6 @@
 	return;
 }
 
-static void gbam2bam_disconnect_work(struct work_struct *w)
-{
-	struct gbam_port *port =
-			container_of(w, struct gbam_port, disconnect_w);
-	struct bam_ch_info *d;
-	int ret;
-	unsigned long flags;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (!port->is_connected) {
-		pr_debug("%s: Port already disconnected. Bailing out.\n",
-			__func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return;
-	}
-
-	port->is_connected = false;
-	d = &port->data_ch;
-
-	/*
-	 * Unlock the port here and not at the end of this work,
-	 * because we do not want to activate usb_bam, ipa and
-	 * tethe bridge logic in atomic context and wait uneeded time.
-	 * Either way other works will not fire until end of this work
-	 * and event functions (as bam_data_connect) will not influance
-	 * while lower layers connect pipes, etc.
-	 */
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		ret = usb_bam_disconnect_ipa(d->usb_bam_type, &d->ipa_params);
-		if (ret)
-			pr_err("%s: usb_bam_disconnect_ipa failed: err:%d\n",
-				__func__, ret);
-		usb_bam_free_fifos(d->usb_bam_type, d->src_connection_idx);
-		usb_bam_free_fifos(d->usb_bam_type, d->dst_connection_idx);
-		teth_bridge_disconnect(d->ipa_params.src_client);
-		/*
-		 * Decrement usage count which was incremented upon cable
-		 * connect or cable disconnect in suspended state
-		 */
-		usb_gadget_autopm_put_async(port->gadget);
-	}
-}
-
 static void gbam_connect_work(struct work_struct *w)
 {
 	struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
@@ -1304,425 +945,6 @@
 	pr_debug("%s: done\n", __func__);
 }
 
-static void gbam2bam_connect_work(struct work_struct *w)
-{
-	struct gbam_port *port = container_of(w, struct gbam_port, connect_w);
-	struct usb_gadget *gadget = NULL;
-	struct teth_bridge_connect_params connect_params;
-	struct teth_bridge_init_params teth_bridge_params;
-	struct bam_ch_info *d;
-	u32 sps_params;
-	int ret;
-	unsigned long flags, flags_ul;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->last_event == U_BAM_DISCONNECT_E) {
-		pr_debug("%s: Port is about to disconnected. Bailing out.\n",
-			__func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return;
-	}
-
-	if (port->is_connected) {
-		pr_debug("%s: Port already connected. Bail out.\n",
-			__func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return;
-	}
-	port->is_connected = true;
-
-	spin_lock_irqsave(&port->port_lock_ul, flags_ul);
-	spin_lock(&port->port_lock_dl);
-	if (!port->port_usb) {
-		pr_debug("%s: usb cable is disconnected, exiting\n", __func__);
-		spin_unlock(&port->port_lock_dl);
-		spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return;
-	}
-
-	gadget = port->port_usb->gadget;
-	if (!gadget) {
-		spin_unlock(&port->port_lock_dl);
-		spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		pr_err("%s: port_usb.gadget is NULL, exiting\n", __func__);
-		return;
-	}
-	d = &port->data_ch;
-
-	/*
-	 * Unlock the port here and not at the end of this work,
-	 * because we do not want to activate usb_bam, ipa and
-	 * tethe bridge logic in atomic context and wait uneeded time.
-	 * Either way other works will not fire until end of this work
-	 * and event functions (as bam_data_connect) will not influance
-	 * while lower layers connect pipes, etc.
-	 */
-	spin_unlock(&port->port_lock_dl);
-	spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
-
-	d->ipa_params.usb_connection_speed = gadget->speed;
-
-	/*
-	 * Invalidate prod and cons client handles from previous
-	 * disconnect.
-	 */
-	d->ipa_params.cons_clnt_hdl = -1;
-	d->ipa_params.prod_clnt_hdl = -1;
-
-	if (usb_bam_get_pipe_type(d->usb_bam_type, d->ipa_params.src_idx,
-			&d->src_pipe_type) ||
-		usb_bam_get_pipe_type(d->usb_bam_type, d->ipa_params.dst_idx,
-				&d->dst_pipe_type)) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		pr_err("%s:usb_bam_get_pipe_type() failed\n", __func__);
-		return;
-	}
-	if (d->dst_pipe_type != USB_BAM_PIPE_BAM2BAM) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		pr_err("%s: no software preparation for DL not using bam2bam\n",
-				__func__);
-		return;
-	}
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	usb_bam_alloc_fifos(d->usb_bam_type, d->src_connection_idx);
-	usb_bam_alloc_fifos(d->usb_bam_type, d->dst_connection_idx);
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	/* check if USB cable is disconnected or not */
-	if (!port || !port->port_usb) {
-		pr_debug("%s: cable is disconnected.\n",
-						 __func__);
-		spin_unlock_irqrestore(&port->port_lock,
-							flags);
-		goto free_fifos;
-	}
-	if (gadget_is_dwc3(gadget)) {
-		/* Configure for RX */
-		configure_data_fifo(d->usb_bam_type, d->src_connection_idx,
-				    port->port_usb->out, d->src_pipe_type);
-		sps_params = MSM_SPS_MODE | MSM_DISABLE_WB | MSM_PRODUCER |
-								d->src_pipe_idx;
-		d->rx_req->length = 32*1024;
-		d->rx_req->udc_priv = sps_params;
-		msm_ep_config(port->port_usb->out, d->rx_req);
-
-		/* Configure for TX */
-		configure_data_fifo(d->usb_bam_type, d->dst_connection_idx,
-				    port->port_usb->in, d->dst_pipe_type);
-		sps_params = MSM_SPS_MODE | MSM_DISABLE_WB | d->dst_pipe_idx;
-		d->tx_req->length = 32*1024;
-		d->tx_req->udc_priv = sps_params;
-		msm_ep_config(port->port_usb->in, d->tx_req);
-
-	} else {
-		/* Configure for RX */
-		get_bam2bam_connection_info(d->usb_bam_type,
-				d->src_connection_idx,
-				&d->src_pipe_idx,
-				NULL, NULL, NULL);
-		sps_params = (MSM_SPS_MODE | d->src_pipe_idx |
-				MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
-		d->rx_req->udc_priv = sps_params;
-
-		/* Configure for TX */
-		get_bam2bam_connection_info(d->usb_bam_type,
-				d->dst_connection_idx,
-				&d->dst_pipe_idx,
-				NULL, NULL, NULL);
-		sps_params = (MSM_SPS_MODE | d->dst_pipe_idx |
-				MSM_VENDOR_ID) & ~MSM_IS_FINITE_TRANSFER;
-		d->tx_req->udc_priv = sps_params;
-
-	}
-
-	teth_bridge_params.client = d->ipa_params.src_client;
-	ret = teth_bridge_init(&teth_bridge_params);
-	if (ret) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		pr_err("%s:teth_bridge_init() failed\n", __func__);
-		goto ep_unconfig;
-	}
-
-	/* Support for UL using system-to-IPA */
-	if (d->src_pipe_type == USB_BAM_PIPE_SYS2BAM) {
-		d->ul_params.teth_priv =
-			teth_bridge_params.private_data;
-		d->ul_params.teth_cb =
-			teth_bridge_params.usb_notify_cb;
-		d->ipa_params.notify = gbam_ipa_sys2bam_notify_cb;
-		d->ipa_params.priv = &d->ul_params;
-		d->ipa_params.reset_pipe_after_lpm = false;
-
-	} else {
-		d->ipa_params.notify =
-			teth_bridge_params.usb_notify_cb;
-		d->ipa_params.priv =
-			teth_bridge_params.private_data;
-		d->ipa_params.reset_pipe_after_lpm =
-			(gadget_is_dwc3(gadget) &&
-			 msm_dwc3_reset_ep_after_lpm(gadget));
-	}
-	d->ipa_params.ipa_ep_cfg.mode.mode = IPA_BASIC;
-	d->ipa_params.skip_ep_cfg = teth_bridge_params.skip_ep_cfg;
-	d->ipa_params.dir = USB_TO_PEER_PERIPHERAL;
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	ret = usb_bam_connect_ipa(d->usb_bam_type, &d->ipa_params);
-	if (ret) {
-		pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
-			__func__, ret);
-		goto ep_unconfig;
-	}
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	/* check if USB cable is disconnected or not */
-	if (port->last_event ==  U_BAM_DISCONNECT_E) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		pr_debug("%s:%d: cable is disconnected.\n",
-						 __func__, __LINE__);
-		goto ep_unconfig;
-	}
-
-	/* Remove support for UL using system-to-IPA towards DL */
-	if (d->src_pipe_type == USB_BAM_PIPE_SYS2BAM) {
-		d->ipa_params.notify = d->ul_params.teth_cb;
-		d->ipa_params.priv = d->ul_params.teth_priv;
-	}
-	if (d->dst_pipe_type == USB_BAM_PIPE_BAM2BAM)
-		d->ipa_params.reset_pipe_after_lpm =
-			(gadget_is_dwc3(gadget) &&
-			 msm_dwc3_reset_ep_after_lpm(gadget));
-	else
-		d->ipa_params.reset_pipe_after_lpm = false;
-	d->ipa_params.dir = PEER_PERIPHERAL_TO_USB;
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	ret = usb_bam_connect_ipa(d->usb_bam_type, &d->ipa_params);
-	if (ret) {
-		pr_err("%s: usb_bam_connect_ipa failed: err:%d\n",
-			__func__, ret);
-		goto ep_unconfig;
-	}
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	/* check if USB cable is disconnected or not */
-	if (port->last_event ==  U_BAM_DISCONNECT_E) {
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		pr_debug("%s:%d: cable is disconnected.\n",
-						 __func__, __LINE__);
-		goto ep_unconfig;
-	}
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-	gqti_ctrl_update_ipa_pipes(port->port_usb, port->port_num,
-					d->ipa_params.ipa_prod_ep_idx,
-					d->ipa_params.ipa_cons_ep_idx);
-
-	connect_params.ipa_usb_pipe_hdl = d->ipa_params.prod_clnt_hdl;
-	connect_params.usb_ipa_pipe_hdl = d->ipa_params.cons_clnt_hdl;
-	connect_params.tethering_mode = TETH_TETHERING_MODE_RMNET;
-	connect_params.client_type = d->ipa_params.src_client;
-	ret = teth_bridge_connect(&connect_params);
-	if (ret) {
-		pr_err("%s:teth_bridge_connect() failed\n", __func__);
-		goto ep_unconfig;
-	}
-
-	/* queue in & out requests */
-	if (d->src_pipe_type == USB_BAM_PIPE_BAM2BAM) {
-		gbam_start_endless_rx(port);
-	} else {
-		/* The use-case of UL (OUT) ports using sys2bam is based on
-		 * partial reuse of the system-to-bam_demux code. The following
-		 * lines perform the branching out of the standard bam2bam flow
-		 * on the USB side of the UL channel
-		 */
-		if (_gbam_start_io(port, false)) {
-			pr_err("%s: _gbam_start_io failed\n", __func__);
-			return;
-		}
-		gbam_start_rx(port);
-	}
-	gbam_start_endless_tx(port);
-
-	pr_debug("%s: done\n", __func__);
-	return;
-
-ep_unconfig:
-	if (gadget_is_dwc3(gadget)) {
-		spin_lock_irqsave(&port->port_lock, flags);
-		/* check if USB cable is disconnected or not */
-		if (port->port_usb) {
-			msm_ep_unconfig(port->port_usb->in);
-			msm_ep_unconfig(port->port_usb->out);
-		}
-		spin_unlock_irqrestore(&port->port_lock, flags);
-	}
-free_fifos:
-	usb_bam_free_fifos(d->usb_bam_type, d->src_connection_idx);
-	usb_bam_free_fifos(d->usb_bam_type, d->dst_connection_idx);
-
-}
-
-static int gbam_wake_cb(void *param)
-{
-	struct gbam_port	*port = (struct gbam_port *)param;
-	struct usb_gadget	*gadget;
-	unsigned long flags;
-	struct usb_function *func;
-	int ret;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		pr_debug("%s: usb cable is disconnected, exiting\n",
-				__func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return -ENODEV;
-	}
-
-	gadget = port->port_usb->gadget;
-	func = port->port_usb->f;
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	pr_debug("%s: woken up by peer\n", __func__);
-
-	if ((gadget->speed == USB_SPEED_SUPER) &&
-	    (func->func_is_suspended))
-		ret = usb_func_wakeup(func);
-	else
-		ret = usb_gadget_wakeup(gadget);
-
-	if ((ret == -EBUSY) || (ret == -EAGAIN))
-		pr_debug("Remote wakeup is delayed due to LPM exit\n");
-	else if (ret)
-		pr_err("Failed to wake up the USB core. ret=%d\n", ret);
-
-	return ret;
-}
-
-static void gbam2bam_suspend_work(struct work_struct *w)
-{
-	struct gbam_port *port = container_of(w, struct gbam_port, suspend_w);
-	struct bam_ch_info *d;
-	int ret;
-	unsigned long flags;
-
-	pr_debug("%s: suspend work started\n", __func__);
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if ((port->last_event == U_BAM_DISCONNECT_E) ||
-	    (port->last_event == U_BAM_RESUME_E)) {
-		pr_debug("%s: Port is about to disconnect/resume. Bail out\n",
-			__func__);
-		goto exit;
-	}
-
-	d = &port->data_ch;
-
-	ret = usb_bam_register_wake_cb(d->usb_bam_type, d->dst_connection_idx,
-					gbam_wake_cb, port);
-	if (ret) {
-		pr_err("%s(): Failed to register BAM wake callback.\n",
-			__func__);
-		goto exit;
-	}
-
-	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		usb_bam_register_start_stop_cbs(d->usb_bam_type,
-			 d->dst_connection_idx, gbam_start, gbam_stop, port);
-
-		/*
-		 * release lock here because gbam_start() or
-		 * gbam_stop() called from usb_bam_suspend()
-		 * re-acquires port lock.
-		 */
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		usb_bam_suspend(d->usb_bam_type, &d->ipa_params);
-		spin_lock_irqsave(&port->port_lock, flags);
-	}
-
-exit:
-	/*
-	 * Decrement usage count after IPA handshake is done to allow gadget
-	 * parent to go to lpm. This counter was incremented upon cable connect
-	 */
-	usb_gadget_autopm_put_async(port->gadget);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
-static void gbam2bam_resume_work(struct work_struct *w)
-{
-	struct gbam_port *port = container_of(w, struct gbam_port, resume_w);
-	struct bam_ch_info *d;
-	struct usb_gadget *gadget = NULL;
-	int ret;
-	unsigned long flags;
-
-	pr_debug("%s: resume work started\n", __func__);
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	if (port->last_event == U_BAM_DISCONNECT_E || !port->port_usb) {
-		pr_debug("%s: usb cable is disconnected, exiting\n",
-			__func__);
-		goto exit;
-	}
-
-	d = &port->data_ch;
-	gadget = port->port_usb->gadget;
-
-	ret = usb_bam_register_wake_cb(d->usb_bam_type, d->dst_connection_idx,
-					NULL, NULL);
-	if (ret) {
-		pr_err("%s(): Failed to register BAM wake callback.\n",
-			__func__);
-		goto exit;
-	}
-
-	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		if (gadget_is_dwc3(gadget) &&
-		    msm_dwc3_reset_ep_after_lpm(gadget)) {
-			if (d->tx_req_dequeued) {
-				msm_ep_unconfig(port->port_usb->in);
-				configure_data_fifo(d->usb_bam_type,
-					d->dst_connection_idx,
-					port->port_usb->in, d->dst_pipe_type);
-			}
-			if (d->rx_req_dequeued) {
-				msm_ep_unconfig(port->port_usb->out);
-				configure_data_fifo(d->usb_bam_type,
-					d->src_connection_idx,
-					port->port_usb->out, d->src_pipe_type);
-			}
-
-			spin_unlock_irqrestore(&port->port_lock, flags);
-			if (d->tx_req_dequeued)
-				msm_dwc3_reset_dbm_ep(port->port_usb->in);
-			if (d->rx_req_dequeued)
-				msm_dwc3_reset_dbm_ep(port->port_usb->out);
-			spin_lock_irqsave(&port->port_lock, flags);
-			if (port->port_usb) {
-				if (d->tx_req_dequeued)
-					msm_ep_config(port->port_usb->in,
-							d->tx_req);
-				if (d->rx_req_dequeued)
-					msm_ep_config(port->port_usb->out,
-							d->rx_req);
-			}
-		}
-		d->tx_req_dequeued = false;
-		d->rx_req_dequeued = false;
-		usb_bam_resume(d->usb_bam_type, &d->ipa_params);
-	}
-
-exit:
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
 /* BAM data channel ready, allow attempt to open */
 static int gbam_data_ch_probe(struct platform_device *pdev)
 {
@@ -1734,8 +956,11 @@
 
 	pr_debug("%s: name:%s\n", __func__, pdev->name);
 
-	for (i = 0; i < n_bam_ports; i++) {
+	for (i = 0; i < BAM_DMUX_NUM_FUNCS; i++) {
 		port = bam_ports[i].port;
+		if (!port)
+			continue;
+
 		d = &port->data_ch;
 
 		if (!strcmp(bam_ch_names[i], pdev->name)) {
@@ -1770,9 +995,12 @@
 
 	pr_debug("%s: name:%s\n", __func__, pdev->name);
 
-	for (i = 0; i < n_bam_ports; i++) {
+	for (i = 0; i < BAM_DMUX_NUM_FUNCS; i++) {
 		if (!strcmp(bam_ch_names[i], pdev->name)) {
 			port = bam_ports[i].port;
+			if (!port)
+				continue;
+
 			d = &port->data_ch;
 
 			spin_lock_irqsave(&port->port_lock_ul, flags);
@@ -1805,10 +1033,10 @@
 	return 0;
 }
 
-static void gbam_port_free(int portno)
+static void gbam_port_free(enum bam_dmux_func_type func)
 {
-	struct gbam_port *port = bam_ports[portno].port;
-	struct platform_driver *pdrv = &bam_ports[portno].pdrv;
+	struct gbam_port *port = bam_ports[func].port;
+	struct platform_driver *pdrv = &bam_ports[func].pdrv;
 
 	if (port)
 		platform_driver_unregister(pdrv);
@@ -1816,14 +1044,7 @@
 	kfree(port);
 }
 
-static void gbam2bam_port_free(int portno)
-{
-	struct gbam_port *port = bam2bam_ports[portno];
-
-	kfree(port);
-}
-
-static int gbam_port_alloc(int portno)
+static int gbam_port_alloc(enum bam_dmux_func_type func)
 {
 	struct gbam_port	*port;
 	struct bam_ch_info	*d;
@@ -1833,7 +1054,7 @@
 	if (!port)
 		return -ENOMEM;
 
-	port->port_num = portno;
+	port->port_num = func;
 
 	/* port initialization */
 	port->is_connected = false;
@@ -1853,60 +1074,20 @@
 	skb_queue_head_init(&d->tx_skb_q);
 	skb_queue_head_init(&d->rx_skb_q);
 	skb_queue_head_init(&d->rx_skb_idle);
-	d->id = bam_ch_ids[portno];
+	d->id = bam_ch_ids[func];
 
-	bam_ports[portno].port = port;
+	bam_ports[func].port = port;
 
-	scnprintf(bam_ch_names[portno], BAM_DMUX_CH_NAME_MAX_LEN,
-			"bam_dmux_ch_%d", bam_ch_ids[portno]);
-	pdrv = &bam_ports[portno].pdrv;
+	scnprintf(bam_ch_names[func], BAM_DMUX_CH_NAME_MAX_LEN,
+			"bam_dmux_ch_%d", bam_ch_ids[func]);
+	pdrv = &bam_ports[func].pdrv;
 	pdrv->probe = gbam_data_ch_probe;
 	pdrv->remove = gbam_data_ch_remove;
-	pdrv->driver.name = bam_ch_names[portno];
+	pdrv->driver.name = bam_ch_names[func];
 	pdrv->driver.owner = THIS_MODULE;
 
 	platform_driver_register(pdrv);
-	pr_debug("%s: port:%pK portno:%d\n", __func__, port, portno);
-
-	return 0;
-}
-
-static int gbam2bam_port_alloc(int portno)
-{
-	struct gbam_port	*port;
-	struct bam_ch_info	*d;
-
-	port = kzalloc(sizeof(struct gbam_port), GFP_KERNEL);
-	if (!port)
-		return -ENOMEM;
-
-	port->port_num = portno;
-
-	/* port initialization */
-	port->is_connected = false;
-	spin_lock_init(&port->port_lock_ul);
-	spin_lock_init(&port->port_lock_dl);
-	spin_lock_init(&port->port_lock);
-
-	INIT_WORK(&port->connect_w, gbam2bam_connect_work);
-	INIT_WORK(&port->disconnect_w, gbam2bam_disconnect_work);
-	INIT_WORK(&port->suspend_w, gbam2bam_suspend_work);
-	INIT_WORK(&port->resume_w, gbam2bam_resume_work);
-
-	/* data ch */
-	d = &port->data_ch;
-	d->port = port;
-	d->ipa_params.src_client = usb_prod[portno];
-	d->ipa_params.dst_client = usb_cons[portno];
-	bam2bam_ports[portno] = port;
-
-	/* UL workaround requirements */
-	skb_queue_head_init(&d->rx_skb_q);
-	skb_queue_head_init(&d->rx_skb_idle);
-	INIT_LIST_HEAD(&d->rx_idle);
-	INIT_WORK(&d->write_tobam_w, gbam_data_write_tobam);
-
-	pr_debug("%s: port:%pK portno:%d\n", __func__, port, portno);
+	pr_debug("%s: port:%pK portno:%d\n", __func__, port, func);
 
 	return 0;
 }
@@ -1928,7 +1109,7 @@
 	if (!buf)
 		return -ENOMEM;
 
-	for (i = 0; i < n_bam_ports; i++) {
+	for (i = 0; i < BAM_DMUX_NUM_FUNCS; i++) {
 		port = bam_ports[i].port;
 		if (!port)
 			continue;
@@ -1991,7 +1172,7 @@
 	int			i;
 	unsigned long		flags;
 
-	for (i = 0; i < n_bam_ports; i++) {
+	for (i = 0; i < BAM_DMUX_NUM_FUNCS; i++) {
 		port = bam_ports[i].port;
 		if (!port)
 			continue;
@@ -2021,48 +1202,12 @@
 	return count;
 }
 
-const struct file_operations gbam_stats_ops = {
+static const struct file_operations gbam_stats_ops = {
 	.read = gbam_read_stats,
 	.write = gbam_reset_stats,
 };
 
-static ssize_t gbam_rw_write(struct file *file, const char __user *ubuf,
-				size_t count, loff_t *ppos)
-{
-	struct gbam_port	*port = bam2bam_ports[0];
-	struct usb_function	*func;
-	struct usb_gadget	*gadget;
-	unsigned long		flags;
-
-	if (!port)
-		return -ENODEV;
-
-	spin_lock_irqsave(&port->port_lock, flags);
-	if (!port->port_usb) {
-		pr_debug("%s: usb cable is disconnected, exiting\n",
-				__func__);
-		spin_unlock_irqrestore(&port->port_lock, flags);
-		return -ENODEV;
-	}
-
-	gadget = port->port_usb->gadget;
-	func = port->port_usb->f;
-	spin_unlock_irqrestore(&port->port_lock, flags);
-
-	if ((gadget->speed == USB_SPEED_SUPER) && (func->func_is_suspended)) {
-		pr_debug("%s Initiating usb_func rwakeup\n", __func__);
-		usb_func_wakeup(func);
-	}
-
-	return count;
-}
-
-
-const struct file_operations debug_remote_wakeup_fops = {
-	.write = gbam_rw_write,
-};
-
-struct dentry *gbam_dent;
+static struct dentry *gbam_dent;
 static void gbam_debugfs_init(void)
 {
 	struct dentry *dfile;
@@ -2070,14 +1215,11 @@
 	if (gbam_dent)
 		return;
 
-	gbam_dent = debugfs_create_dir("usb_rmnet", 0);
+	gbam_dent = debugfs_create_dir("usb_rmnet", NULL);
 	if (!gbam_dent || IS_ERR(gbam_dent))
 		return;
 
-	debugfs_create_file("remote_wakeup", 0444, gbam_dent, 0,
-			&debug_remote_wakeup_fops);
-
-	dfile = debugfs_create_file("status", 0444, gbam_dent, 0,
+	dfile = debugfs_create_file("status", 0444, gbam_dent, NULL,
 			&gbam_stats_ops);
 	if (!dfile || IS_ERR(dfile)) {
 		debugfs_remove(gbam_dent);
@@ -2094,29 +1236,16 @@
 static inline void gbam_debugfs_remove(void) {}
 #endif
 
-void gbam_disconnect(struct grmnet *gr, u8 port_num, enum transport_type trans)
+void gbam_disconnect(struct data_port *gr, enum bam_dmux_func_type func)
 {
 	struct gbam_port	*port;
-	unsigned long		flags, flags_ul, flags_dl;
+	unsigned long		flags, flags_ul;
 	struct bam_ch_info	*d;
 
-	pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, port_num);
+	pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, func);
 
-	if (trans == USB_GADGET_XPORT_BAM2BAM) {
-		pr_err("%s: invalid xport#%d\n", __func__, trans);
-		return;
-	}
-	if (trans == USB_GADGET_XPORT_BAM_DMUX &&
-		port_num >= n_bam_ports) {
-		pr_err("%s: invalid bam portno#%d\n",
-			   __func__, port_num);
-		return;
-	}
-
-	if ((trans == USB_GADGET_XPORT_BAM2BAM_IPA) &&
-				port_num >= n_bam2bam_ports) {
-		pr_err("%s: invalid bam2bam portno#%d\n",
-			   __func__, port_num);
+	if (func >= BAM_DMUX_NUM_FUNCS) {
+		pr_err("%s: invalid bam portno#%d\n", __func__, func);
 		return;
 	}
 
@@ -2124,10 +1253,7 @@
 		pr_err("%s: grmnet port is null\n", __func__);
 		return;
 	}
-	if (trans == USB_GADGET_XPORT_BAM_DMUX)
-		port = bam_ports[port_num].port;
-	else
-		port = bam2bam_ports[port_num];
+	port = bam_ports[func].port;
 
 	if (!port) {
 		pr_err("%s: NULL port", __func__);
@@ -2142,124 +1268,58 @@
 		spin_unlock_irqrestore(&port->port_lock, flags);
 		return;
 	}
-	/*
-	 * Suspend with remote wakeup enabled. Increment usage
-	 * count when disconnect happens in suspended state.
-	 * Corresponding decrement happens in the end of this
-	 * function if IPA handshake is already done or it is done
-	 * in disconnect work after finishing IPA handshake.
-	 */
-	if (port->last_event == U_BAM_SUSPEND_E)
-		usb_gadget_autopm_get_noresume(port->gadget);
 
 	port->port_usb = gr;
 
-	if (trans == USB_GADGET_XPORT_BAM_DMUX)
-		gbam_free_buffers(port);
-	else if (trans == USB_GADGET_XPORT_BAM2BAM_IPA)
-		gbam_free_rx_buffers(port);
+	gbam_free_buffers(port);
 
 	spin_lock_irqsave(&port->port_lock_ul, flags_ul);
 	spin_lock(&port->port_lock_dl);
-	port->port_usb = 0;
+	port->port_usb = NULL;
 	n_tx_req_queued = 0;
 	spin_unlock(&port->port_lock_dl);
 	spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
 
 	usb_ep_disable(gr->in);
-	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		spin_lock_irqsave(&port->port_lock_dl, flags_dl);
-		if (d->tx_req) {
-			usb_ep_free_request(gr->in, d->tx_req);
-			d->tx_req = NULL;
-		}
-		spin_unlock_irqrestore(&port->port_lock_dl, flags_dl);
-	}
 	/* disable endpoints */
-	if (gr->out) {
+	if (gr->out)
 		usb_ep_disable(gr->out);
-		if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-			spin_lock_irqsave(&port->port_lock_ul, flags_ul);
-			if (d->rx_req) {
-				usb_ep_free_request(gr->out, d->rx_req);
-				d->rx_req = NULL;
-			}
-			spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
-		}
-	}
-
-	/*
-	 * Set endless flag to false as USB Endpoint is already
-	 * disable.
-	 */
-	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-
-		if (d->dst_pipe_type == USB_BAM_PIPE_BAM2BAM)
-			gr->in->endless = false;
-
-		if (d->src_pipe_type == USB_BAM_PIPE_BAM2BAM && gr->out)
-			gr->out->endless = false;
-	}
 
 	gr->in->driver_data = NULL;
 	if (gr->out)
 		gr->out->driver_data = NULL;
 
 	port->last_event = U_BAM_DISCONNECT_E;
-	/* Disable usb irq for CI gadget. It will be enabled in
-	 * usb_bam_disconnect_pipe() after disconnecting all pipes
-	 * and USB BAM reset is done.
-	 */
-	if (!gadget_is_dwc3(port->gadget) &&
-			(trans == USB_GADGET_XPORT_BAM2BAM_IPA))
-		msm_usb_irq_disable(true);
-
 	queue_work(gbam_wq, &port->disconnect_w);
 
 	spin_unlock_irqrestore(&port->port_lock, flags);
 }
 
-int gbam_connect(struct grmnet *gr, u8 port_num,
-		enum transport_type trans, u8 src_connection_idx,
-		u8 dst_connection_idx)
+int gbam_connect(struct data_port *gr, enum bam_dmux_func_type func)
 {
 	struct gbam_port	*port;
 	struct bam_ch_info	*d;
 	int			ret;
 	unsigned long		flags, flags_ul;
 
-	pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, port_num);
+	pr_debug("%s: grmnet:%pK port#%d\n", __func__, gr, func);
 
 	if (!gr) {
 		pr_err("%s: grmnet port is null\n", __func__);
 		return -ENODEV;
 	}
 
-	if (!gr->gadget) {
+	if (!gr->cdev->gadget) {
 		pr_err("%s: gadget handle not passed\n", __func__);
 		return -EINVAL;
 	}
 
-	if (trans == USB_GADGET_XPORT_BAM2BAM) {
-		pr_err("%s: invalid xport#%d\n", __func__, trans);
-		return -EINVAL;
-	}
-
-	if (trans == USB_GADGET_XPORT_BAM_DMUX && port_num >= n_bam_ports) {
-		pr_err("%s: invalid portno#%d\n", __func__, port_num);
+	if (func >= BAM_DMUX_NUM_FUNCS) {
+		pr_err("%s: invalid portno#%d\n", __func__, func);
 		return -ENODEV;
 	}
 
-	if ((trans == USB_GADGET_XPORT_BAM2BAM_IPA)
-			&& port_num >= n_bam2bam_ports) {
-		pr_err("%s: invalid portno#%d\n", __func__, port_num);
-		return -ENODEV;
-	}
-
-	if (trans == USB_GADGET_XPORT_BAM_DMUX)
-		port = bam_ports[port_num].port;
-	else
-		port = bam2bam_ports[port_num];
+	port = bam_ports[func].port;
 
 	if (!port) {
 		pr_err("%s: NULL port", __func__);
@@ -2269,108 +1329,28 @@
 	spin_lock_irqsave(&port->port_lock, flags);
 
 	d = &port->data_ch;
-	d->trans = trans;
 
 	spin_lock_irqsave(&port->port_lock_ul, flags_ul);
 	spin_lock(&port->port_lock_dl);
 	port->port_usb = gr;
-	port->gadget = port->port_usb->gadget;
+	port->gadget = port->port_usb->cdev->gadget;
 
-	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		d->rx_req = usb_ep_alloc_request(port->port_usb->out,
-								GFP_ATOMIC);
-		if (!d->rx_req) {
-			pr_err("%s: RX request allocation failed\n", __func__);
-			d->rx_req = NULL;
-			spin_unlock(&port->port_lock_dl);
-			spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
-			spin_unlock_irqrestore(&port->port_lock, flags);
-			return -ENOMEM;
-		}
-
-		d->rx_req->context = port;
-		d->rx_req->complete = gbam_endless_rx_complete;
-		d->rx_req->length = 0;
-		d->rx_req->no_interrupt = 1;
-
-		d->tx_req = usb_ep_alloc_request(port->port_usb->in,
-								GFP_ATOMIC);
-		if (!d->tx_req) {
-			pr_err("%s: TX request allocation failed\n", __func__);
-			d->tx_req = NULL;
-			usb_ep_free_request(port->port_usb->out, d->rx_req);
-			d->rx_req = NULL;
-			spin_unlock(&port->port_lock_dl);
-			spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
-			spin_unlock_irqrestore(&port->port_lock, flags);
-			return -ENOMEM;
-		}
-
-		d->tx_req->context = port;
-		d->tx_req->complete = gbam_endless_tx_complete;
-		d->tx_req->length = 0;
-		d->tx_req->no_interrupt = 1;
-	}
-
-	if (d->trans == USB_GADGET_XPORT_BAM_DMUX) {
-		d->to_host = 0;
-		d->to_modem = 0;
-		d->pending_pkts_with_bam = 0;
-		d->pending_bytes_with_bam = 0;
-		d->tohost_drp_cnt = 0;
-		d->tomodem_drp_cnt = 0;
-		d->rx_flow_control_disable = 0;
-		d->rx_flow_control_enable = 0;
-		d->rx_flow_control_triggered = 0;
-		d->max_num_pkts_pending_with_bam = 0;
-		d->max_bytes_pending_with_bam = 0;
-		d->delayed_bam_mux_write_done = 0;
-	}
+	d->to_host = 0;
+	d->to_modem = 0;
+	d->pending_pkts_with_bam = 0;
+	d->pending_bytes_with_bam = 0;
+	d->tohost_drp_cnt = 0;
+	d->tomodem_drp_cnt = 0;
+	d->rx_flow_control_disable = 0;
+	d->rx_flow_control_enable = 0;
+	d->rx_flow_control_triggered = 0;
+	d->max_num_pkts_pending_with_bam = 0;
+	d->max_bytes_pending_with_bam = 0;
+	d->delayed_bam_mux_write_done = 0;
 
 	spin_unlock(&port->port_lock_dl);
 	spin_unlock_irqrestore(&port->port_lock_ul, flags_ul);
 
-	if (d->trans == USB_GADGET_XPORT_BAM2BAM_IPA) {
-		d->src_connection_idx = src_connection_idx;
-		d->dst_connection_idx = dst_connection_idx;
-		d->usb_bam_type = usb_bam_get_bam_type(gr->gadget->name);
-		d->ipa_params.src_pipe = &(d->src_pipe_idx);
-		d->ipa_params.dst_pipe = &(d->dst_pipe_idx);
-		d->ipa_params.src_idx = src_connection_idx;
-		d->ipa_params.dst_idx = dst_connection_idx;
-
-		/*
-		 * Query pipe type using IPA src/dst index with
-		 * usbbam driver. It is being set either as
-		 * BAM2BAM or SYS2BAM.
-		 */
-		if (usb_bam_get_pipe_type(d->usb_bam_type,
-				d->ipa_params.src_idx, &d->src_pipe_type) ||
-		    usb_bam_get_pipe_type(d->usb_bam_type,
-				d->ipa_params.dst_idx, &d->dst_pipe_type)) {
-			pr_err("%s:usb_bam_get_pipe_type() failed\n",
-				__func__);
-			ret = -EINVAL;
-			usb_ep_free_request(port->port_usb->out, d->rx_req);
-			d->rx_req = NULL;
-			usb_ep_free_request(port->port_usb->in, d->tx_req);
-			d->tx_req = NULL;
-			goto exit;
-		}
-		/*
-		 * Check for pipe_type. If it is BAM2BAM, then it is required
-		 * to disable Xfer complete and Xfer not ready interrupts for
-		 * that particular endpoint. Hence it set endless flag based
-		 * it which is considered into UDC driver while enabling
-		 * USB Endpoint.
-		 */
-		if (d->dst_pipe_type == USB_BAM_PIPE_BAM2BAM)
-			port->port_usb->in->endless = true;
-
-		if (d->src_pipe_type == USB_BAM_PIPE_BAM2BAM)
-			port->port_usb->out->endless = true;
-	}
-
 	ret = usb_ep_enable(gr->in);
 	if (ret) {
 		pr_err("%s: usb_ep_enable failed eptype:IN ep:%pK",
@@ -2379,11 +1359,6 @@
 		d->rx_req = NULL;
 		usb_ep_free_request(port->port_usb->in, d->tx_req);
 		d->tx_req = NULL;
-		if (d->dst_pipe_type == USB_BAM_PIPE_BAM2BAM)
-			port->port_usb->in->endless = false;
-
-		if (d->src_pipe_type == USB_BAM_PIPE_BAM2BAM)
-			port->port_usb->out->endless = false;
 		goto exit;
 	}
 	gr->in->driver_data = port;
@@ -2398,30 +1373,18 @@
 		if (ret) {
 			pr_err("%s: usb_ep_enable failed eptype:OUT ep:%pK",
 					__func__, gr->out);
-			gr->in->driver_data = 0;
+			gr->in->driver_data = NULL;
 			usb_ep_disable(gr->in);
 			usb_ep_free_request(port->port_usb->out, d->rx_req);
 			d->rx_req = NULL;
 			usb_ep_free_request(port->port_usb->in, d->tx_req);
 			d->tx_req = NULL;
-			if (d->dst_pipe_type == USB_BAM_PIPE_BAM2BAM)
-				port->port_usb->in->endless = false;
-
-			if (d->src_pipe_type == USB_BAM_PIPE_BAM2BAM)
-				port->port_usb->out->endless = false;
 			goto exit;
 		}
 		gr->out->driver_data = port;
 	}
 
 	port->last_event = U_BAM_CONNECT_E;
-	/*
-	 * Increment usage count upon cable connect. Decrement after IPA
-	 * handshake is done in disconnect work (due to cable disconnect)
-	 * or in suspend work.
-	 */
-	if (trans == USB_GADGET_XPORT_BAM2BAM_IPA)
-		usb_gadget_autopm_get_noresume(port->gadget);
 	queue_work(gbam_wq, &port->connect_w);
 
 	ret = 0;
@@ -2430,24 +1393,14 @@
 	return ret;
 }
 
-void gbam_data_flush_workqueue(void)
+int gbam_setup(enum bam_dmux_func_type func)
 {
-	pr_debug("%s(): Flushing workqueue\n", __func__);
-	flush_workqueue(gbam_wq);
-}
-
-int gbam_setup(unsigned int no_bam_port)
-{
-	int	i;
 	int	ret;
-	int	bam_port_start = n_bam_ports;
-	int	total_bam_ports = bam_port_start + no_bam_port;
 
-	pr_debug("%s: requested BAM ports:%d\n", __func__, no_bam_port);
+	pr_debug("%s: requested BAM port:%d\n", __func__, func);
 
-	if (!no_bam_port || total_bam_ports > BAM_N_PORTS) {
-		pr_err("%s: Invalid num of ports count:%d\n",
-				__func__, no_bam_port);
+	if (func >= BAM_DMUX_NUM_FUNCS) {
+		pr_err("%s: Invalid num of ports count:%d\n", __func__, func);
 		return -EINVAL;
 	}
 
@@ -2461,171 +1414,54 @@
 		}
 	}
 
-	for (i = bam_port_start; i < (bam_port_start + no_bam_port); i++) {
-		n_bam_ports++;
-		pr_debug("gbam_port_alloc called for %d\n", i);
-		ret = gbam_port_alloc(i);
-		if (ret) {
-			n_bam_ports--;
-			pr_err("%s: Unable to alloc port:%d\n", __func__, i);
-			goto free_bam_ports;
-		}
+	ret = gbam_port_alloc(func);
+	if (ret) {
+		pr_err("%s: Unable to alloc port:%d\n", __func__, func);
+		goto destroy_wq;
 	}
 
 	gbam_debugfs_init();
 
-	return bam_port_start;
+	return 0;
 
-free_bam_ports:
-	for (i = 0; i < n_bam_ports; i++)
-		gbam_port_free(i);
+destroy_wq:
 	destroy_workqueue(gbam_wq);
 
 	return ret;
 }
 
-int gbam2bam_setup(unsigned int no_bam2bam_port)
-{
-	int	i;
-	int	ret;
-	int	bam2bam_port_start = n_bam2bam_ports;
-	int	total_bam2bam_ports = bam2bam_port_start + no_bam2bam_port;
-
-	pr_debug("%s: requested BAM2BAM ports:%d\n", __func__, no_bam2bam_port);
-
-	if (!no_bam2bam_port || total_bam2bam_ports > BAM2BAM_N_PORTS) {
-		pr_err("%s: Invalid num of ports count:%d\n",
-				__func__, no_bam2bam_port);
-		return -EINVAL;
-	}
-
-	if (!gbam_wq) {
-		gbam_wq = alloc_workqueue("k_gbam", WQ_UNBOUND |
-					WQ_MEM_RECLAIM, 1);
-		if (!gbam_wq) {
-			pr_err("%s: Unable to create workqueue gbam_wq\n",
-					__func__);
-			return -ENOMEM;
-		}
-	}
-
-	for (i = bam2bam_port_start; i < (bam2bam_port_start +
-				no_bam2bam_port); i++) {
-		n_bam2bam_ports++;
-		ret = gbam2bam_port_alloc(i);
-		if (ret) {
-			n_bam2bam_ports--;
-			pr_err("%s: Unable to alloc port:%d\n", __func__, i);
-			goto free_bam2bam_ports;
-		}
-	}
-
-	gbam_debugfs_init();
-
-	return bam2bam_port_start;
-
-free_bam2bam_ports:
-	for (i = 0; i < n_bam2bam_ports; i++)
-		gbam2bam_port_free(i);
-	destroy_workqueue(gbam_wq);
-
-	return ret;
-}
-
-void gbam_cleanup(void)
+void gbam_cleanup(enum bam_dmux_func_type func)
 {
 	gbam_debugfs_remove();
-}
-
-void gbam_suspend(struct grmnet *gr, u8 port_num, enum transport_type trans)
-{
-	struct gbam_port	*port;
-	struct bam_ch_info *d;
-	unsigned long flags;
-
-	if (trans != USB_GADGET_XPORT_BAM2BAM_IPA)
-		return;
-
-	port = bam2bam_ports[port_num];
-
-	if (!port) {
-		pr_err("%s: NULL port", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	d = &port->data_ch;
-
-	pr_debug("%s: suspended port %d\n", __func__, port_num);
-
-	port->last_event = U_BAM_SUSPEND_E;
-	queue_work(gbam_wq, &port->suspend_w);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
-}
-
-void gbam_resume(struct grmnet *gr, u8 port_num, enum transport_type trans)
-{
-	struct gbam_port	*port;
-	struct bam_ch_info *d;
-	unsigned long flags;
-
-	if (trans != USB_GADGET_XPORT_BAM2BAM_IPA)
-		return;
-
-	port = bam2bam_ports[port_num];
-
-	if (!port) {
-		pr_err("%s: NULL port", __func__);
-		return;
-	}
-
-	spin_lock_irqsave(&port->port_lock, flags);
-
-	d = &port->data_ch;
-
-	pr_debug("%s: resumed port %d\n", __func__, port_num);
-
-	port->last_event = U_BAM_RESUME_E;
-	/*
-	 * Increment usage count here to disallow gadget parent suspend.
-	 * This counter will decrement after IPA handshake is done in
-	 * disconnect work (due to cable disconnect) or in bam_disconnect
-	 * in suspended state.
-	 */
-	usb_gadget_autopm_get_noresume(port->gadget);
-	queue_work(gbam_wq, &port->resume_w);
-
-	spin_unlock_irqrestore(&port->port_lock, flags);
+	gbam_port_free(func);
 }
 
 int gbam_mbim_connect(struct usb_gadget *g, struct usb_ep *in,
 			struct usb_ep *out)
 {
-	struct grmnet *gr;
+	struct data_port *gr;
 
 	gr = kzalloc(sizeof(*gr), GFP_ATOMIC);
 	if (!gr)
 		return -ENOMEM;
 	gr->in = in;
 	gr->out = out;
-	gr->gadget = g;
+	gr->cdev->gadget = g;
 
-	return gbam_connect(gr, 0, USB_GADGET_XPORT_BAM_DMUX, 0, 0);
+	return gbam_connect(gr, BAM_DMUX_FUNC_MBIM);
 }
 
 void gbam_mbim_disconnect(void)
 {
-	struct gbam_port *port = bam_ports[0].port;
-	struct grmnet *gr = port->port_usb;
+	struct gbam_port *port = bam_ports[BAM_DMUX_FUNC_MBIM].port;
+	struct data_port *gr = port->port_usb;
 
 	if (!gr) {
 		pr_err("%s: port_usb is NULL\n", __func__);
 		return;
 	}
 
-	gbam_disconnect(gr, 0, USB_GADGET_XPORT_BAM_DMUX);
+	gbam_disconnect(gr, BAM_DMUX_FUNC_MBIM);
 	kfree(gr);
 }
 
@@ -2633,13 +1469,7 @@
 {
 	int ret = 0;
 
-	/*
-	 * MBIM requires only 1 USB_GADGET_XPORT_BAM_DMUX
-	 * port. The port is always 0 and is shared
-	 * between RMNET and MBIM.
-	 */
-	if (!n_bam_ports)
-		ret = gbam_setup(1);
+	ret = gbam_setup(BAM_DMUX_FUNC_MBIM);
 
 	return ret;
 }
diff --git a/drivers/usb/gadget/function/u_ctrl_qti.c b/drivers/usb/gadget/function/u_ctrl_qti.c
index 21839a3e..4ab7bc4 100644
--- a/drivers/usb/gadget/function/u_ctrl_qti.c
+++ b/drivers/usb/gadget/function/u_ctrl_qti.c
@@ -17,6 +17,8 @@
 #include <linux/cdev.h>
 #include <linux/debugfs.h>
 
+#include <soc/qcom/bam_dmux.h>
+
 #include "u_rmnet.h"
 #include "f_qdss.h"
 
@@ -206,7 +208,8 @@
 	qti_ctrl_queue_notify(port);
 }
 
-int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned int intf)
+int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned int intf,
+						enum data_xport_type dxport)
 {
 	struct qti_ctrl_port	*port;
 	struct grmnet *g_rmnet = NULL;
@@ -226,8 +229,16 @@
 
 	spin_lock_irqsave(&port->lock, flags);
 	port->port_type = qport;
-	port->ep_type = DATA_EP_TYPE_HSUSB;
-	port->intf = intf;
+	if (dxport == BAM_DMUX) {
+		port->ep_type = DATA_EP_TYPE_BAM_DMUX;
+		port->intf = (qport == QTI_PORT_RMNET) ?
+			BAM_DMUX_USB_RMNET_0 : BAM_DMUX_USB_DPL;
+		port->ipa_prod_idx = 0;
+		port->ipa_cons_idx = 0;
+	} else {
+		port->ep_type = DATA_EP_TYPE_HSUSB;
+		port->intf = intf;
+	}
 
 	if (gr) {
 		port->port_usb = gr;
diff --git a/drivers/usb/gadget/function/u_data_ipa.c b/drivers/usb/gadget/function/u_data_ipa.c
index f379028..7af152b3 100644
--- a/drivers/usb/gadget/function/u_data_ipa.c
+++ b/drivers/usb/gadget/function/u_data_ipa.c
@@ -23,7 +23,6 @@
 #include <linux/usb_bam.h>
 
 #include "u_data_ipa.h"
-#include "u_rmnet.h"
 
 struct ipa_data_ch_info {
 	struct usb_request			*rx_req;
@@ -45,7 +44,7 @@
 	u8					src_connection_idx;
 	u8					dst_connection_idx;
 	enum usb_ctrl				usb_bam_type;
-	struct gadget_ipa_port			*port_usb;
+	struct data_port			*port_usb;
 	struct usb_gadget			*gadget;
 	atomic_t				pipe_connect_notified;
 	struct usb_bam_connect_ipa_params	ipa_params;
@@ -299,7 +298,7 @@
  * switch is being trigger. This API performs restoring USB endpoint operation
  * and disable USB endpoint used for accelerated path.
  */
-void ipa_data_disconnect(struct gadget_ipa_port *gp, enum ipa_func_type func)
+void ipa_data_disconnect(struct data_port *gp, enum ipa_func_type func)
 {
 	struct ipa_data_ch_info *port;
 	unsigned long flags;
@@ -402,7 +401,7 @@
 {
 	struct ipa_data_ch_info *port = container_of(w, struct ipa_data_ch_info,
 								connect_w);
-	struct gadget_ipa_port	*gport;
+	struct data_port	*gport;
 	struct usb_gadget	*gadget = NULL;
 	struct teth_bridge_connect_params connect_params;
 	struct teth_bridge_init_params teth_bridge_params;
@@ -478,7 +477,7 @@
 		configure_fifo(port->usb_bam_type,
 				port->src_connection_idx,
 				port->port_usb->out);
-		ret = msm_ep_config(gport->out);
+		ret = msm_ep_config(gport->out, port->rx_req);
 		if (ret) {
 			pr_err("msm_ep_config() failed for OUT EP\n");
 			spin_unlock_irqrestore(&port->port_lock, flags);
@@ -503,7 +502,7 @@
 		port->tx_req->udc_priv = sps_params;
 		configure_fifo(port->usb_bam_type,
 				port->dst_connection_idx, gport->in);
-		ret = msm_ep_config(gport->in);
+		ret = msm_ep_config(gport->in, port->tx_req);
 		if (ret) {
 			pr_err("msm_ep_config() failed for IN EP\n");
 			spin_unlock_irqrestore(&port->port_lock, flags);
@@ -730,7 +729,7 @@
  * initiate USB BAM IPA connection. This API is enabling accelerated endpoints
  * and schedule connect_work() which establishes USB IPA BAM communication.
  */
-int ipa_data_connect(struct gadget_ipa_port *gp, enum ipa_func_type func,
+int ipa_data_connect(struct data_port *gp, enum ipa_func_type func,
 		u8 src_connection_idx, u8 dst_connection_idx)
 {
 	struct ipa_data_ch_info *port;
@@ -939,7 +938,7 @@
  * It is being used to initiate USB BAM IPA suspend functionality
  * for USB bus suspend functionality.
  */
-void ipa_data_suspend(struct gadget_ipa_port *gp, enum ipa_func_type func,
+void ipa_data_suspend(struct data_port *gp, enum ipa_func_type func,
 			bool remote_wakeup_enabled)
 {
 	struct ipa_data_ch_info *port;
@@ -1050,7 +1049,7 @@
  * It is being used to initiate USB resume functionality
  * for USB bus resume case.
  */
-void ipa_data_resume(struct gadget_ipa_port *gp, enum ipa_func_type func,
+void ipa_data_resume(struct data_port *gp, enum ipa_func_type func,
 			bool remote_wakeup_enabled)
 {
 	struct ipa_data_ch_info *port;
diff --git a/drivers/usb/gadget/function/u_data_ipa.h b/drivers/usb/gadget/function/u_data_ipa.h
index 70d4293..d2d419b 100644
--- a/drivers/usb/gadget/function/u_data_ipa.h
+++ b/drivers/usb/gadget/function/u_data_ipa.h
@@ -34,19 +34,6 @@
 /* Max Number of IPA data ports supported */
 #define IPA_N_PORTS USB_IPA_NUM_FUNCS
 
-struct gadget_ipa_port {
-	struct usb_composite_dev	*cdev;
-	struct usb_function		*func;
-	int				rx_buffer_size;
-	struct usb_ep			*in;
-	struct usb_ep			*out;
-	int				ipa_consumer_ep;
-	int				ipa_producer_ep;
-	const struct usb_endpoint_descriptor	*in_ep_desc_backup;
-	const struct usb_endpoint_descriptor	*out_ep_desc_backup;
-
-};
-
 struct ipa_function_bind_info {
 	struct usb_string *string_defs;
 	int data_str_idx;
@@ -85,16 +72,16 @@
 };
 
 void ipa_data_port_select(enum ipa_func_type func);
-void ipa_data_disconnect(struct gadget_ipa_port *gp, enum ipa_func_type func);
-int ipa_data_connect(struct gadget_ipa_port *gp, enum ipa_func_type func,
+void ipa_data_disconnect(struct data_port *gp, enum ipa_func_type func);
+int ipa_data_connect(struct data_port *gp, enum ipa_func_type func,
 			u8 src_connection_idx, u8 dst_connection_idx);
 int ipa_data_setup(enum ipa_func_type func);
 void ipa_data_free(enum ipa_func_type func);
 
 void ipa_data_flush_workqueue(void);
-void ipa_data_resume(struct gadget_ipa_port *gp, enum ipa_func_type func,
+void ipa_data_resume(struct data_port *gp, enum ipa_func_type func,
 		bool remote_wakeup_enabled);
-void ipa_data_suspend(struct gadget_ipa_port *gp, enum ipa_func_type func,
+void ipa_data_suspend(struct data_port *gp, enum ipa_func_type func,
 		bool remote_wakeup_enabled);
 
 void ipa_data_set_ul_max_xfer_size(u32 ul_max_xfer_size);
@@ -109,11 +96,34 @@
 
 void ipa_data_stop_rndis_ipa(enum ipa_func_type func);
 
+#ifdef CONFIG_USB_F_QCRNDIS
 void *rndis_qc_get_ipa_priv(void);
 void *rndis_qc_get_ipa_rx_cb(void);
 bool rndis_qc_get_skip_ep_config(void);
 void *rndis_qc_get_ipa_tx_cb(void);
 void rndis_ipa_reset_trigger(void);
+#else
+static inline void *rndis_qc_get_ipa_priv(void)
+{
+	return NULL;
+}
+static inline void *rndis_qc_get_ipa_rx_cb(void)
+{
+	return NULL;
+}
+static inline bool rndis_qc_get_skip_ep_config(void)
+{
+	return true;
+}
+static inline void *rndis_qc_get_ipa_tx_cb(void)
+{
+	return NULL;
+}
+static inline void rndis_ipa_reset_trigger(void)
+{
+}
+#endif /* CONFIG_USB_F_QCRNDIS */
+
 #if IS_ENABLED(CONFIG_USB_CONFIGFS_RMNET_BAM)
 void gqti_ctrl_update_ipa_pipes(void *gr, enum qti_port_type qport,
 				u32 ipa_prod, u32 ipa_cons);
diff --git a/drivers/usb/gadget/function/u_ether.c b/drivers/usb/gadget/function/u_ether.c
index d50510f..24f8f1c 100644
--- a/drivers/usb/gadget/function/u_ether.c
+++ b/drivers/usb/gadget/function/u_ether.c
@@ -23,6 +23,8 @@
 #include <linux/if_vlan.h>
 #include <linux/if_arp.h>
 #include <linux/msm_rmnet.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
 
 #include "u_ether.h"
 
@@ -57,6 +59,9 @@
 
 static struct workqueue_struct	*uether_wq;
 
+/* Extra buffer size to allocate for tx */
+#define EXTRA_ALLOCATION_SIZE_U_ETH	128
+
 struct eth_dev {
 	/* lock is held while accessing port_usb
 	 */
@@ -70,7 +75,7 @@
 	struct list_head	tx_reqs, rx_reqs;
 	unsigned		tx_qlen;
 /* Minimum number of TX USB request queued to UDC */
-#define TX_REQ_THRESHOLD	5
+#define MAX_TX_REQ_WITH_NO_INT	5
 	int			no_tx_req_used;
 	int			tx_skb_hold_count;
 	u32			tx_req_bufsize;
@@ -99,14 +104,35 @@
 	bool			no_skb_reserve;
 	u8			host_mac[ETH_ALEN];
 	u8			dev_mac[ETH_ALEN];
+	unsigned long		tx_throttle;
+	unsigned long		rx_throttle;
+	unsigned int		tx_pkts_rcvd;
+	unsigned long		skb_expand_cnt;
+	struct dentry		*uether_dent;
+	struct dentry		*uether_dfile;
 };
 
+static void uether_debugfs_init(struct eth_dev *dev);
+static void uether_debugfs_exit(struct eth_dev *dev);
+
 /*-------------------------------------------------------------------------*/
 
 #define RX_EXTRA	20	/* bytes guarding against rx overflows */
 
 #define DEFAULT_QLEN	2	/* double buffering by default */
 
+/*
+ * Usually downlink rates are higher than uplink rates and it
+ * deserve higher number of requests. For CAT-6 data rates of
+ * 300Mbps (~30 packets per milli-sec) 40 usb request may not
+ * be sufficient. At this rate and with interrupt moderation
+ * of interconnect, data can be very bursty. tx_qmult is the
+ * additional multipler on qmult.
+ */
+static unsigned int tx_qmult = 2;
+module_param(tx_qmult, uint, 0644);
+MODULE_PARM_DESC(tx_qmult, "Additional queue length multiplier for tx");
+
 /* for dual-speed hardware, use deeper queues at high/super speed */
 static inline int qlen(struct usb_gadget *gadget, unsigned qmult)
 {
@@ -118,6 +144,10 @@
 }
 
 /*-------------------------------------------------------------------------*/
+#define U_ETHER_RX_PENDING_TSHOLD 500
+
+static unsigned int u_ether_rx_pending_thld = U_ETHER_RX_PENDING_TSHOLD;
+module_param(u_ether_rx_pending_thld, uint, 0644);
 
 /* REVISIT there must be a better way than having two sets
  * of debug calls ...
@@ -231,11 +261,11 @@
 		out = dev->port_usb->out_ep;
 	else
 		out = NULL;
-	spin_unlock_irqrestore(&dev->lock, flags);
 
-	if (!out)
+	if (!out) {
+		spin_unlock_irqrestore(&dev->lock, flags);
 		return -ENOTCONN;
-
+	}
 
 	/* Padding up to RX_EXTRA handles minor disagreements with host.
 	 * Normally we use the USB "terminate on short read" convention;
@@ -259,9 +289,10 @@
 
 	if (dev->port_usb->is_fixed)
 		size = max_t(size_t, size, dev->port_usb->fixed_out_len);
+	spin_unlock_irqrestore(&dev->lock, flags);
 
 	DBG(dev, "%s: size: %zd\n", __func__, size);
-	skb = alloc_skb(size + NET_IP_ALIGN, gfp_flags);
+	skb = alloc_skb(size, gfp_flags);
 	if (skb == NULL) {
 		DBG(dev, "no rx skb\n");
 		goto enomem;
@@ -272,7 +303,7 @@
 	 * RNDIS headers involve variable numbers of LE32 values.
 	 */
 	if (likely(!dev->no_skb_reserve))
-		skb_reserve(skb, NET_IP_ALIGN);
+		skb_reserve(skb, 0);
 
 	req->buf = skb->data;
 	req->length = size;
@@ -356,9 +387,20 @@
 	}
 
 clean:
-	spin_lock(&dev->req_lock);
-	list_add(&req->list, &dev->rx_reqs);
-	spin_unlock(&dev->req_lock);
+	if (queue && dev->rx_frames.qlen <= u_ether_rx_pending_thld) {
+		if (rx_submit(dev, req, GFP_ATOMIC) < 0) {
+			spin_lock(&dev->req_lock);
+			list_add(&req->list, &dev->rx_reqs);
+			spin_unlock(&dev->req_lock);
+		}
+	} else {
+		/* rx buffers draining is delayed,defer further queuing to wq */
+		if (queue)
+			dev->rx_throttle++;
+		spin_lock(&dev->req_lock);
+		list_add(&req->list, &dev->rx_reqs);
+		spin_unlock(&dev->req_lock);
+	}
 
 	if (queue)
 		queue_work(uether_wq, &dev->rx_work);
@@ -409,7 +451,7 @@
 
 	spin_lock(&dev->req_lock);
 	if (link->in_ep) {
-		status = prealloc(&dev->tx_reqs, link->in_ep, n);
+		status = prealloc(&dev->tx_reqs, link->in_ep, n * tx_qmult);
 			if (status < 0)
 			goto fail;
 	}
@@ -458,6 +500,31 @@
 	spin_unlock_irqrestore(&dev->req_lock, flags);
 }
 
+static __be16 ether_ip_type_trans(struct sk_buff *skb,
+	struct net_device *dev)
+{
+	__be16	protocol = 0;
+
+	skb->dev = dev;
+
+	switch (skb->data[0] & 0xf0) {
+	case 0x40:
+		protocol = htons(ETH_P_IP);
+		break;
+	case 0x60:
+		protocol = htons(ETH_P_IPV6);
+		break;
+	default:
+		if ((skb->data[0] & 0x40) == 0x00)
+			protocol = htons(ETH_P_MAP);
+		else
+			pr_debug_ratelimited("[%s] L3 protocol decode error: 0x%02x",
+					dev->name, skb->data[0] & 0xf0);
+	}
+
+	return protocol;
+}
+
 static void process_rx_w(struct work_struct *work)
 {
 	struct eth_dev	*dev = container_of(work, struct eth_dev, rx_work);
@@ -477,7 +544,12 @@
 			dev_kfree_skb_any(skb);
 			continue;
 		}
-		skb->protocol = eth_type_trans(skb, dev->net);
+
+		if (test_bit(RMNET_MODE_LLP_IP, &dev->flags))
+			skb->protocol = ether_ip_type_trans(skb, dev->net);
+		else
+			skb->protocol = eth_type_trans(skb, dev->net);
+
 		dev->net->stats.rx_packets++;
 		dev->net->stats.rx_bytes += skb->len;
 
@@ -511,6 +583,11 @@
 	int length;
 	int retval;
 
+	if (!dev->port_usb) {
+		usb_ep_free_request(ep, req);
+		return;
+	}
+
 	switch (req->status) {
 	default:
 		dev->net->stats.tx_errors++;
@@ -521,21 +598,21 @@
 		break;
 	case 0:
 		if (!req->zero)
-			dev->net->stats.tx_bytes += req->length-1;
+			dev->net->stats.tx_bytes += req->actual-1;
 		else
-			dev->net->stats.tx_bytes += req->length;
+			dev->net->stats.tx_bytes += req->actual;
 	}
 	dev->net->stats.tx_packets++;
 
 	spin_lock(&dev->req_lock);
-	list_add_tail(&req->list, &dev->tx_reqs);
 
-	if (dev->port_usb->multi_pkt_xfer) {
+	if (dev->port_usb->multi_pkt_xfer && !req->context) {
 		dev->no_tx_req_used--;
 		req->length = 0;
 		in = dev->port_usb->in_ep;
 
-		if (!list_empty(&dev->tx_reqs)) {
+		/* Do not process further if no_interrupt is set */
+		if (!req->no_interrupt && !list_empty(&dev->tx_reqs)) {
 			new_req = container_of(dev->tx_reqs.next,
 					struct usb_request, list);
 			list_del(&new_req->list);
@@ -563,11 +640,27 @@
 					length++;
 				}
 
+				/* set when tx completion interrupt needed */
+				spin_lock(&dev->req_lock);
+				dev->tx_qlen++;
+				if (dev->tx_qlen == MAX_TX_REQ_WITH_NO_INT) {
+					new_req->no_interrupt = 0;
+					dev->tx_qlen = 0;
+				} else {
+					new_req->no_interrupt = 1;
+				}
+				spin_unlock(&dev->req_lock);
 				new_req->length = length;
+				new_req->complete = tx_complete;
 				retval = usb_ep_queue(in, new_req, GFP_ATOMIC);
 				switch (retval) {
 				default:
 					DBG(dev, "tx queue err %d\n", retval);
+					new_req->length = 0;
+					spin_lock(&dev->req_lock);
+					list_add_tail(&new_req->list,
+							&dev->tx_reqs);
+					spin_unlock(&dev->req_lock);
 					break;
 				case 0:
 					spin_lock(&dev->req_lock);
@@ -577,17 +670,37 @@
 				}
 			} else {
 				spin_lock(&dev->req_lock);
-				list_add(&new_req->list, &dev->tx_reqs);
+				/*
+				 * Put the idle request at the back of the
+				 * queue. The xmit function will put the
+				 * unfinished request at the beginning of the
+				 * queue.
+				 */
+				list_add_tail(&new_req->list, &dev->tx_reqs);
 				spin_unlock(&dev->req_lock);
 			}
 		} else {
 			spin_unlock(&dev->req_lock);
 		}
 	} else {
+		/* 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
+				+ dev->gadget->extra_buf_alloc, GFP_ATOMIC);
+			req->context = NULL;
+		} else {
+			req->buf = NULL;
+		}
+
 		spin_unlock(&dev->req_lock);
 		dev_kfree_skb_any(skb);
 	}
 
+	/* put the completed req back to tx_reqs tail pool */
+	spin_lock(&dev->req_lock);
+	list_add_tail(&req->list, &dev->tx_reqs);
+	spin_unlock(&dev->req_lock);
+
 	if (netif_carrier_ok(dev->net))
 		netif_wake_queue(dev->net);
 }
@@ -597,7 +710,7 @@
 	return cdc_filter & USB_CDC_PACKET_TYPE_PROMISCUOUS;
 }
 
-static void alloc_tx_buffer(struct eth_dev *dev)
+static int alloc_tx_buffer(struct eth_dev *dev)
 {
 	struct list_head	*act;
 	struct usb_request	*req;
@@ -612,9 +725,26 @@
 	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,
-						GFP_ATOMIC);
+			req->buf = kmalloc(dev->tx_req_bufsize
+				+ dev->gadget->extra_buf_alloc, GFP_ATOMIC);
+
+		if (!req->buf)
+			goto free_buf;
+
+		/* req->context is not used for multi_pkt_xfers */
+		req->context = NULL;
 	}
+	return 0;
+
+free_buf:
+	/* tx_req_bufsize = 0 retries mem alloc on next eth_start_xmit */
+	dev->tx_req_bufsize = 0;
+	list_for_each(act, &dev->tx_reqs) {
+		req = container_of(act, struct usb_request, list);
+		kfree(req->buf);
+		req->buf = NULL;
+	}
+	return -ENOMEM;
 }
 
 static netdev_tx_t eth_start_xmit(struct sk_buff *skb,
@@ -622,19 +752,25 @@
 {
 	struct eth_dev		*dev = netdev_priv(net);
 	int			length = 0;
+	int			tail_room = 0;
+	int			extra_alloc = 0;
 	int			retval;
 	struct usb_request	*req = NULL;
+	struct sk_buff		*new_skb;
 	unsigned long		flags;
-	struct usb_ep		*in;
-	u16			cdc_filter;
+	struct usb_ep		*in = NULL;
+	u16			cdc_filter = 0;
+	bool			multi_pkt_xfer = false;
+	u32			fixed_in_len = 0;
+	bool			is_fixed = false;
 
 	spin_lock_irqsave(&dev->lock, flags);
 	if (dev->port_usb) {
 		in = dev->port_usb->in_ep;
 		cdc_filter = dev->port_usb->cdc_filter;
-	} else {
-		in = NULL;
-		cdc_filter = 0;
+		is_fixed = dev->port_usb->is_fixed;
+		fixed_in_len = dev->port_usb->fixed_in_len;
+		multi_pkt_xfer = dev->port_usb->multi_pkt_xfer;
 	}
 	spin_unlock_irqrestore(&dev->lock, flags);
 
@@ -643,10 +779,6 @@
 		return NETDEV_TX_OK;
 	}
 
-	/* Allocate memory for tx_reqs to support multi packet transfer */
-	if (dev->port_usb->multi_pkt_xfer && !dev->tx_req_bufsize)
-		alloc_tx_buffer(dev);
-
 	/* apply outgoing CDC or RNDIS filters */
 	if (skb && !is_promisc(cdc_filter)) {
 		u8		*dest = skb->data;
@@ -669,7 +801,41 @@
 		/* ignores USB_CDC_PACKET_TYPE_DIRECTED */
 	}
 
+	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);
+	if (multi_pkt_xfer && !dev->tx_req_bufsize) {
+		retval = alloc_tx_buffer(dev);
+		if (retval < 0) {
+			spin_unlock_irqrestore(&dev->req_lock, flags);
+			return -ENOMEM;
+		}
+	}
+
 	/*
 	 * this freelist can be empty if an interrupt triggered disconnect()
 	 * and reconfigured the gadget (shutting down this queue) after the
@@ -684,37 +850,20 @@
 	list_del(&req->list);
 
 	/* temporarily stop TX queue when the freelist empties */
-	if (list_empty(&dev->tx_reqs))
+	if (list_empty(&dev->tx_reqs)) {
+		/*
+		 * tx_throttle gives info about number of times u_ether
+		 * asked network layer to stop queueing packets to it
+		 * when transmit resources are unavailable
+		 */
+		dev->tx_throttle++;
 		netif_stop_queue(net);
-	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
-	 */
-	if (dev->wrap) {
-		unsigned long	flags;
-
-		spin_lock_irqsave(&dev->lock, flags);
-		if (dev->port_usb)
-			skb = dev->wrap(dev->port_usb, skb);
-		spin_unlock_irqrestore(&dev->lock, flags);
-		if (!skb) {
-			/* 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;
-		}
 	}
 
-	spin_lock_irqsave(&dev->req_lock, flags);
 	dev->tx_skb_hold_count++;
 	spin_unlock_irqrestore(&dev->req_lock, flags);
 
-	if (dev->port_usb->multi_pkt_xfer) {
+	if (multi_pkt_xfer) {
 		memcpy(req->buf + req->length, skb->data, skb->len);
 		req->length = req->length + skb->len;
 		length = req->length;
@@ -722,7 +871,13 @@
 
 		spin_lock_irqsave(&dev->req_lock, flags);
 		if (dev->tx_skb_hold_count < dev->dl_max_pkts_per_xfer) {
-			if (dev->no_tx_req_used > TX_REQ_THRESHOLD) {
+			/*
+			 * should allow aggregation only, if the number of
+			 * requests queued more than the tx requests that can
+			 * be queued with no interrupt flag set sequentially.
+			 * Otherwise, packets may be blocked forever.
+			 */
+			if (dev->no_tx_req_used > MAX_TX_REQ_WITH_NO_INT) {
 				list_add(&req->list, &dev->tx_reqs);
 				spin_unlock_irqrestore(&dev->req_lock, flags);
 				goto success;
@@ -736,6 +891,35 @@
 		dev->tx_skb_hold_count = 0;
 		spin_unlock_irqrestore(&dev->lock, flags);
 	} else {
+		bool do_align = false;
+
+		/* Check if TX buffer should be aligned before queuing to hw */
+		if (dev->gadget->is_chipidea &&
+		    !IS_ALIGNED((size_t)skb->data, 4))
+			do_align = true;
+
+		/*
+		 * Some UDC requires allocation of some extra bytes for
+		 * TX buffer due to hardware requirement. Check if extra
+		 * bytes are already there, otherwise allocate new buffer
+		 * with extra bytes and do memcpy to align skb as well.
+		 */
+		if (dev->gadget->extra_buf_alloc)
+			extra_alloc = EXTRA_ALLOCATION_SIZE_U_ETH;
+		tail_room = skb_tailroom(skb);
+		if (do_align || tail_room < extra_alloc) {
+			pr_debug("%s:align skb and update tail_room %d to %d\n",
+					__func__, tail_room, extra_alloc);
+			tail_room = extra_alloc;
+			new_skb = skb_copy_expand(skb, 0, tail_room,
+						  GFP_ATOMIC);
+			if (!new_skb)
+				return -ENOMEM;
+			dev_kfree_skb_any(skb);
+			skb = new_skb;
+			dev->skb_expand_cnt++;
+		}
+
 		length = skb->len;
 		req->buf = skb->data;
 		req->context = skb;
@@ -744,9 +928,7 @@
 	req->complete = tx_complete;
 
 	/* NCM requires no zlp if transfer is dwNtbInMaxSize */
-	if (dev->port_usb &&
-	    dev->port_usb->is_fixed &&
-	    length == dev->port_usb->fixed_in_len &&
+	if (is_fixed && length == fixed_in_len &&
 	    (length % in->maxpacket) == 0)
 		req->zero = 0;
 	else
@@ -766,13 +948,15 @@
 	/* throttle highspeed IRQ rate back slightly */
 	if (gadget_is_dualspeed(dev->gadget) &&
 			 (dev->gadget->speed == USB_SPEED_HIGH)) {
+		spin_lock_irqsave(&dev->req_lock, flags);
 		dev->tx_qlen++;
-		if (dev->tx_qlen == (dev->qmult/2)) {
+		if (dev->tx_qlen == MAX_TX_REQ_WITH_NO_INT) {
 			req->no_interrupt = 0;
 			dev->tx_qlen = 0;
 		} else {
 			req->no_interrupt = 1;
 		}
+		spin_unlock_irqrestore(&dev->req_lock, flags);
 	} else {
 		req->no_interrupt = 0;
 	}
@@ -787,11 +971,11 @@
 	}
 
 	if (retval) {
-		if (!dev->port_usb->multi_pkt_xfer)
+		if (!multi_pkt_xfer)
 			dev_kfree_skb_any(skb);
-drop:
+		else
+			req->length = 0;
 		dev->net->stats.tx_dropped++;
-multiframe:
 		spin_lock_irqsave(&dev->req_lock, flags);
 		if (list_empty(&dev->tx_reqs))
 			netif_start_queue(net);
@@ -1174,6 +1358,7 @@
 		 *  - tx queueing enabled if open *and* carrier is "on"
 		 */
 		netif_carrier_off(net);
+		uether_debugfs_init(dev);
 	}
 
 	return dev;
@@ -1375,8 +1560,10 @@
 	if (!dev)
 		return;
 
+	uether_debugfs_exit(dev);
 	unregister_netdev(dev->net);
 	flush_work(&dev->work);
+	cancel_work_sync(&dev->rx_work);
 	free_netdev(dev->net);
 }
 EXPORT_SYMBOL_GPL(gether_cleanup);
@@ -1514,8 +1701,10 @@
 			list_del(&req->list);
 
 			spin_unlock(&dev->req_lock);
-			if (link->multi_pkt_xfer)
+			if (link->multi_pkt_xfer) {
 				kfree(req->buf);
+				req->buf = NULL;
+			}
 			usb_ep_free_request(link->in_ep, req);
 			spin_lock(&dev->req_lock);
 		}
@@ -1545,6 +1734,12 @@
 		link->out_ep->desc = NULL;
 	}
 
+	pr_debug("%s(): tx_throttle count= %lu", __func__,
+					dev->tx_throttle);
+	/* reset tx_throttle count */
+	dev->tx_throttle = 0;
+	dev->rx_throttle = 0;
+
 	/* finish forgetting about this USB link episode */
 	dev->header_len = 0;
 	dev->unwrap = NULL;
@@ -1556,6 +1751,73 @@
 }
 EXPORT_SYMBOL_GPL(gether_disconnect);
 
+static int uether_stat_show(struct seq_file *s, void *unused)
+{
+	struct eth_dev *dev = s->private;
+	int ret = 0;
+
+	if (dev) {
+		seq_printf(s, "tx_throttle = %lu\n", dev->tx_throttle);
+		seq_printf(s, "tx_pkts_rcvd=%u\n", dev->tx_pkts_rcvd);
+		seq_printf(s, "rx_throttle = %lu\n", dev->rx_throttle);
+		seq_printf(s, "skb_expand_cnt = %lu\n",
+					dev->skb_expand_cnt);
+	}
+	return ret;
+}
+
+static int uether_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, uether_stat_show, inode->i_private);
+}
+
+static ssize_t uether_stat_reset(struct file *file,
+		const char __user *ubuf, size_t count, loff_t *ppos)
+{
+	struct seq_file *s = file->private_data;
+	struct eth_dev *dev = s->private;
+	unsigned long flags;
+
+	spin_lock_irqsave(&dev->lock, flags);
+	/* Reset tx_throttle */
+	dev->tx_throttle = 0;
+	dev->rx_throttle = 0;
+	dev->skb_expand_cnt = 0;
+	spin_unlock_irqrestore(&dev->lock, flags);
+	return count;
+}
+
+static const struct file_operations uether_stats_ops = {
+	.open = uether_open,
+	.read = seq_read,
+	.write = uether_stat_reset,
+};
+
+static void uether_debugfs_init(struct eth_dev *dev)
+{
+	struct dentry *uether_dent;
+	struct dentry *uether_dfile;
+
+	uether_dent = debugfs_create_dir("uether_rndis", NULL);
+	if (IS_ERR(uether_dent))
+		return;
+	dev->uether_dent = uether_dent;
+
+	uether_dfile = debugfs_create_file("status", 0644,
+				uether_dent, dev, &uether_stats_ops);
+	if (!uether_dfile || IS_ERR(uether_dfile))
+		debugfs_remove(uether_dent);
+	dev->uether_dfile = uether_dfile;
+}
+
+static void uether_debugfs_exit(struct eth_dev *dev)
+{
+	debugfs_remove(dev->uether_dfile);
+	debugfs_remove(dev->uether_dent);
+	dev->uether_dent = NULL;
+	dev->uether_dfile = NULL;
+}
+
 static int __init gether_init(void)
 {
 	uether_wq  = create_singlethread_workqueue("uether");
diff --git a/drivers/usb/gadget/function/u_qdss.c b/drivers/usb/gadget/function/u_qdss.c
index b4353ac..d445e51 100644
--- a/drivers/usb/gadget/function/u_qdss.c
+++ b/drivers/usb/gadget/function/u_qdss.c
@@ -131,11 +131,12 @@
 
 static int init_data(struct usb_ep *ep)
 {
+	struct f_qdss *qdss = ep->driver_data;
 	int res = 0;
 
 	pr_debug("init_data\n");
 
-	res = msm_ep_config(ep);
+	res = msm_ep_config(ep, qdss->endless_req);
 	if (res)
 		pr_err("msm_ep_config failed\n");
 
diff --git a/drivers/usb/gadget/function/u_rmnet.h b/drivers/usb/gadget/function/u_rmnet.h
index 0126932..f639722 100644
--- a/drivers/usb/gadget/function/u_rmnet.h
+++ b/drivers/usb/gadget/function/u_rmnet.h
@@ -20,12 +20,32 @@
 
 #include "f_qdss.h"
 
+enum bam_dmux_func_type {
+	BAM_DMUX_FUNC_RMNET,
+	BAM_DMUX_FUNC_MBIM,
+	BAM_DMUX_FUNC_DPL,
+	BAM_DMUX_NUM_FUNCS,
+};
+
 struct rmnet_ctrl_pkt {
 	void	*buf;
 	int	len;
 	struct list_head	list;
 };
 
+struct data_port {
+	struct usb_composite_dev	*cdev;
+	struct usb_function		*func;
+	int				rx_buffer_size;
+	struct usb_ep			*in;
+	struct usb_ep			*out;
+	int				ipa_consumer_ep;
+	int				ipa_producer_ep;
+	const struct usb_endpoint_descriptor	*in_ep_desc_backup;
+	const struct usb_endpoint_descriptor	*out_ep_desc_backup;
+
+};
+
 struct grmnet {
 	/* to usb host, aka laptop, windows pc etc. Will
 	 * be filled by usb driver of rmnet functionality
@@ -49,7 +69,23 @@
 	NR_CTRL_CLIENTS
 };
 
-int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned int intf);
+enum data_xport_type {
+	BAM_DMUX,
+	BAM2BAM_IPA,
+	NR_XPORT_TYPES
+};
+
+int gbam_connect(struct data_port *gr, enum bam_dmux_func_type func);
+void gbam_disconnect(struct data_port *gr, enum bam_dmux_func_type func);
+void gbam_cleanup(enum bam_dmux_func_type func);
+int gbam_setup(enum bam_dmux_func_type func);
+int gbam_mbim_connect(struct usb_gadget *g, struct usb_ep *in,
+			struct usb_ep *out);
+void gbam_mbim_disconnect(void);
+int gbam_mbim_setup(void);
+
+int gqti_ctrl_connect(void *gr, enum qti_port_type qport, unsigned int intf,
+						enum data_xport_type dxport);
 void gqti_ctrl_disconnect(void *gr, enum qti_port_type qport);
 int gqti_ctrl_init(void);
 void gqti_ctrl_cleanup(void);
diff --git a/drivers/usb/gadget/function/uvc_configfs.c b/drivers/usb/gadget/function/uvc_configfs.c
index 984b1d7..4debbcbf 100644
--- a/drivers/usb/gadget/function/uvc_configfs.c
+++ b/drivers/usb/gadget/function/uvc_configfs.c
@@ -2518,7 +2518,7 @@
 	.release		= uvc_attr_release,
 };
 
-#define UVCG_OPTS_ATTR(cname, conv, str2u, uxx, vnoc, limit)		\
+#define UVCG_OPTS_ATTR(cname, aname, conv, str2u, uxx, vnoc, limit)	\
 static ssize_t f_uvc_opts_##cname##_show(				\
 	struct config_item *item, char *page)				\
 {									\
@@ -2565,12 +2565,12 @@
 
 #define identity_conv(x) (x)
 
-UVCG_OPTS_ATTR(streaming_interval, identity_conv, kstrtou8, u8, identity_conv,
-	       16);
-UVCG_OPTS_ATTR(streaming_maxpacket, le16_to_cpu, kstrtou16, u16, le16_to_cpu,
-	       3072);
-UVCG_OPTS_ATTR(streaming_maxburst, identity_conv, kstrtou8, u8, identity_conv,
-	       15);
+UVCG_OPTS_ATTR(streaming_interval, streaming_interval, identity_conv,
+	       kstrtou8, u8, identity_conv, 16);
+UVCG_OPTS_ATTR(streaming_maxpacket, streaming_maxpacket, le16_to_cpu,
+	       kstrtou16, u16, le16_to_cpu, 3072);
+UVCG_OPTS_ATTR(streaming_maxburst, streaming_maxburst, identity_conv,
+	       kstrtou8, u8, identity_conv, 15);
 
 #undef identity_conv
 
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index 09ae74e..4220575 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -340,14 +340,14 @@
 	 * seconds), then it should assume that the there are
 	 * larger problems with the xHC and assert HCRST.
 	 */
-	ret = xhci_handshake(&xhci->op_regs->cmd_ring,
+	ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
 			CMD_RING_RUNNING, 0, 5 * 1000 * 1000);
 	if (ret < 0) {
 		/* we are about to kill xhci, give it one more chance */
 		xhci_write_64(xhci, temp_64 | CMD_RING_ABORT,
 			      &xhci->op_regs->cmd_ring);
 		udelay(1000);
-		ret = xhci_handshake(&xhci->op_regs->cmd_ring,
+		ret = xhci_handshake_check_state(xhci, &xhci->op_regs->cmd_ring,
 				     CMD_RING_RUNNING, 0, 3 * 1000 * 1000);
 		if (ret < 0) {
 			xhci_err(xhci, "Stopped the command ring failed, "
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index ac704d4..84ace86 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -78,6 +78,25 @@
 	return -ETIMEDOUT;
 }
 
+int xhci_handshake_check_state(struct xhci_hcd *xhci,
+		void __iomem *ptr, u32 mask, u32 done, int usec)
+{
+	u32	result;
+
+	do {
+		result = readl_relaxed(ptr);
+		if (result == ~(u32)0 ||
+		xhci->xhc_state == XHCI_STATE_REMOVING)	/* card removed */
+			return -ENODEV;
+		result &= mask;
+		if (result == done)
+			return 0;
+		udelay(1);
+		usec--;
+	} while (usec > 0);
+	return -ETIMEDOUT;
+}
+
 /*
  * Disable interrupts and begin the xHCI halting process.
  */
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index c11eab1..4c1f556 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -1864,6 +1864,8 @@
 /* xHCI host controller glue */
 typedef void (*xhci_get_quirks_t)(struct device *, struct xhci_hcd *);
 int xhci_handshake(void __iomem *ptr, u32 mask, u32 done, int usec);
+int xhci_handshake_check_state(struct xhci_hcd *xhci,
+		void __iomem *ptr, u32 mask, u32 done, int usec);
 void xhci_quiesce(struct xhci_hcd *xhci);
 int xhci_halt(struct xhci_hcd *xhci);
 int xhci_reset(struct xhci_hcd *xhci);
diff --git a/drivers/usb/phy/phy-msm-qusb-v2.c b/drivers/usb/phy/phy-msm-qusb-v2.c
index ad4c0a3..e28173b 100644
--- a/drivers/usb/phy/phy-msm-qusb-v2.c
+++ b/drivers/usb/phy/phy-msm-qusb-v2.c
@@ -71,6 +71,7 @@
 #define SQ_CTRL1_CHIRP_DISABLE		0x20
 #define SQ_CTRL2_CHIRP_DISABLE		0x80
 
+#define PORT_TUNE1_OVERRIDE_VAL		0xc5
 #define DEBUG_CTRL1_OVERRIDE_VAL	0x09
 
 /* PERIPH_SS_PHY_REFGEN_NORTH_BG_CTRL register bits */
@@ -151,6 +152,7 @@
 
 	struct hrtimer		timer;
 	int			soc_min_rev;
+	bool			host_chirp_erratum;
 };
 
 #ifdef CONFIG_NVMEM
@@ -198,6 +200,9 @@
 /* Reads the SoC version */
 static int qusb_phy_get_socrev(struct device *dev, struct qusb_phy *qphy)
 {
+	if (!qphy->host_chirp_erratum)
+		return 0;
+
 	qphy->soc_min_rev  = qfprom_read(dev, "minor_rev");
 	if (qphy->soc_min_rev < 0)
 		dev_err(dev, "failed getting soc_min_rev, err : %d\n",
@@ -471,10 +476,24 @@
 
 	dev_dbg(phy->dev, "%s\n", __func__);
 
-	qusb_phy_reset(qphy);
 	qusb_phy_write_seq(qphy->base, qphy->qusb_phy_host_init_seq,
 			qphy->host_init_seq_len, 0);
 
+	/* If soc revision is mentioned and host_chirp_erratum flag is set
+	 * then override TUNE1 and DEBUG_CTRL1
+	 */
+	if (qphy->soc_min_rev && qphy->host_chirp_erratum) {
+		writel_relaxed(PORT_TUNE1_OVERRIDE_VAL,
+				qphy->base + qphy->phy_reg[PORT_TUNE1]);
+		writel_relaxed(DEBUG_CTRL1_OVERRIDE_VAL,
+				qphy->base + qphy->phy_reg[DEBUG_CTRL1]);
+	}
+
+	if (qphy->refgen_north_bg_reg)
+		if (readl_relaxed(qphy->refgen_north_bg_reg) & BANDGAP_BYPASS)
+			writel_relaxed(BIAS_CTRL_2_OVERRIDE_VAL,
+				qphy->base + qphy->phy_reg[BIAS_CTRL_2]);
+
 	/* Ensure above write is completed before turning ON ref clk */
 	wmb();
 
@@ -504,6 +523,12 @@
 	qusb_phy_enable_clocks(qphy, true);
 
 	qusb_phy_reset(qphy);
+
+	if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE) {
+		qusb_phy_host_init(phy);
+		return 0;
+	}
+
 	if (qphy->emulation) {
 		if (qphy->emu_init_seq)
 			qusb_phy_write_seq(qphy->emu_phy_base + 0x8000,
@@ -560,11 +585,6 @@
 			writel_relaxed(BIAS_CTRL_2_OVERRIDE_VAL,
 				qphy->base + qphy->phy_reg[BIAS_CTRL_2]);
 
-	/* if soc revision is mentioned override DEBUG_CTRL1 value */
-	if (qphy->soc_min_rev)
-		writel_relaxed(DEBUG_CTRL1_OVERRIDE_VAL,
-				qphy->base + qphy->phy_reg[DEBUG_CTRL1]);
-
 	/* ensure above writes are completed before re-enabling PHY */
 	wmb();
 
@@ -754,9 +774,6 @@
 
 	qphy->cable_connected = true;
 
-	if (qphy->qusb_phy_host_init_seq && qphy->phy.flags & PHY_HOST_MODE)
-		qusb_phy_host_init(phy);
-
 	dev_dbg(phy->dev, "QUSB PHY: connect notification cable_connected=%d\n",
 							qphy->cable_connected);
 	return 0;
@@ -1170,6 +1187,9 @@
 			return -ENOMEM;
 	}
 
+	qphy->host_chirp_erratum = of_property_read_bool(dev->of_node,
+					"qcom,host-chirp-erratum");
+
 	ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
 					 (u32 *) qphy->vdd_levels,
 					 ARRAY_SIZE(qphy->vdd_levels));
diff --git a/drivers/usb/phy/phy-msm-snps-hs.c b/drivers/usb/phy/phy-msm-snps-hs.c
index 3482c93..e625839 100644
--- a/drivers/usb/phy/phy-msm-snps-hs.c
+++ b/drivers/usb/phy/phy-msm-snps-hs.c
@@ -96,6 +96,9 @@
 	bool			suspended;
 	bool			cable_connected;
 
+	int			*param_override_seq;
+	int			param_override_seq_cnt;
+
 	/* emulation targets specific */
 	void __iomem		*emu_phy_base;
 	int			*emu_init_seq;
@@ -381,6 +384,11 @@
 	msm_usb_write_readback(phy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL1,
 				VBUSVLDEXT0, VBUSVLDEXT0);
 
+	/* set parameter ovrride  if needed */
+	if (phy->param_override_seq)
+		hsusb_phy_write_seq(phy->base, phy->param_override_seq,
+				phy->param_override_seq_cnt, 0);
+
 	msm_usb_write_readback(phy->base, USB2_PHY_USB_PHY_HS_PHY_CTRL_COMMON2,
 				VREGBYPASS, VREGBYPASS);
 
@@ -576,6 +584,34 @@
 		}
 	}
 
+	phy->param_override_seq_cnt = of_property_count_elems_of_size(
+					dev->of_node,
+					"qcom,param-override-seq",
+					sizeof(*phy->param_override_seq));
+	if (phy->param_override_seq_cnt > 0) {
+		phy->param_override_seq = devm_kcalloc(dev,
+					phy->param_override_seq_cnt,
+					sizeof(*phy->param_override_seq),
+					GFP_KERNEL);
+		if (!phy->param_override_seq)
+			return -ENOMEM;
+
+		if (phy->param_override_seq_cnt % 2) {
+			dev_err(dev, "invalid param_override_seq_len\n");
+			return -EINVAL;
+		}
+
+		ret = of_property_read_u32_array(dev->of_node,
+				"qcom,param-override-seq",
+				phy->param_override_seq,
+				phy->param_override_seq_cnt);
+		if (ret) {
+			dev_err(dev, "qcom,param-override-seq read failed %d\n",
+				ret);
+			return ret;
+		}
+	}
+
 	ret = of_property_read_u32_array(dev->of_node, "qcom,vdd-voltage-level",
 					 (u32 *) phy->vdd_levels,
 					 ARRAY_SIZE(phy->vdd_levels));
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index d89714b..155a9b9 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -4110,6 +4110,7 @@
 remove_cdev:
 	pm_runtime_disable(&pdev->dev);
 	device_remove_file(&pdev->dev, &dev_attr_dpdm_pulldown_enable);
+	msm_otg_debugfs_cleanup();
 phy_reg_deinit:
 	devm_regulator_unregister(motg->phy.dev, motg->dpdm_rdev);
 remove_phy:
diff --git a/drivers/video/fbdev/Kconfig b/drivers/video/fbdev/Kconfig
index eb44e99..1809e66 100644
--- a/drivers/video/fbdev/Kconfig
+++ b/drivers/video/fbdev/Kconfig
@@ -2334,8 +2334,7 @@
 	select FB_CFB_FILLRECT
 	select FB_CFB_COPYAREA
 	select FB_CFB_IMAGEBLIT
-	select SYNC
-	select SW_SYNC
+	select SYNC_FILE
 	---help---
 	  The MSM driver implements a frame buffer interface to
 	  provide access to the display hardware and provide
diff --git a/drivers/video/fbdev/msm/Kconfig b/drivers/video/fbdev/msm/Kconfig
index 60b86e7..e8f902b 100644
--- a/drivers/video/fbdev/msm/Kconfig
+++ b/drivers/video/fbdev/msm/Kconfig
@@ -21,8 +21,7 @@
 
 config FB_MSM_MDSS
 	bool "MDSS HW"
-	select SYNC
-	select SW_SYNC
+	select SYNC_FILE
 	select FB_MSM_MDSS_COMMON
 	---help---
 	The Mobile Display Sub System (MDSS) driver supports devices which
diff --git a/drivers/video/fbdev/msm/mdss.h b/drivers/video/fbdev/msm/mdss.h
index 17bad06..12a3171 100644
--- a/drivers/video/fbdev/msm/mdss.h
+++ b/drivers/video/fbdev/msm/mdss.h
@@ -232,6 +232,13 @@
 	u32 *dest_scaler_off;
 	u32 *dest_scaler_lut_off;
 	struct mdss_mdp_qseed3_lut_tbl lut_tbl;
+
+	/*
+	 * Lock is mainly to serialize access to LUT.
+	 * LUT values come asynchronously from userspace
+	 * via ioctl.
+	 */
+	struct mutex scaler_lock;
 };
 
 struct mdss_data_type;
diff --git a/drivers/video/fbdev/msm/mdss_fb.c b/drivers/video/fbdev/msm/mdss_fb.c
index 1ce9be0..ae9b7cf 100644
--- a/drivers/video/fbdev/msm/mdss_fb.c
+++ b/drivers/video/fbdev/msm/mdss_fb.c
@@ -279,7 +279,7 @@
 				      enum led_brightness value)
 {
 	struct msm_fb_data_type *mfd = dev_get_drvdata(led_cdev->dev->parent);
-	int bl_lvl;
+	u64 bl_lvl;
 
 	if (mfd->boot_notification_led) {
 		led_trigger_event(mfd->boot_notification_led, 0);
@@ -518,13 +518,13 @@
 {
 	struct fb_info *fbi = dev_get_drvdata(dev);
 	struct msm_fb_data_type *mfd = fbi->par;
-	unsigned int fps_int, fps_float;
+	u64 fps_int, fps_float;
 
 	if (mfd->panel_power_state != MDSS_PANEL_POWER_ON)
 		mfd->fps_info.measured_fps = 0;
-	fps_int = (unsigned int) mfd->fps_info.measured_fps;
+	fps_int = (u64) mfd->fps_info.measured_fps;
 	fps_float = do_div(fps_int, 10);
-	return scnprintf(buf, PAGE_SIZE, "%d.%d\n", fps_int, fps_float);
+	return scnprintf(buf, PAGE_SIZE, "%llu.%llu\n", fps_int, fps_float);
 
 }
 
@@ -2292,9 +2292,10 @@
 			pr_debug("vma=%pK, addr=%x len=%ld\n",
 					vma, (unsigned int)addr, len);
 			pr_debug("vm_start=%x vm_end=%x vm_page_prot=%ld\n",
-					(unsigned int)vma->vm_start,
-					(unsigned int)vma->vm_end,
-				(unsigned long int)vma->vm_page_prot.pgprot);
+				(unsigned int)vma->vm_start,
+				(unsigned int)vma->vm_end,
+				(unsigned long int)pgprot_val(
+							vma->vm_page_prot));
 
 			io_remap_pfn_range(vma, addr, page_to_pfn(page), len,
 					vma->vm_page_prot);
diff --git a/drivers/video/fbdev/msm/mdss_fb.h b/drivers/video/fbdev/msm/mdss_fb.h
index 19e6299..c85f033 100644
--- a/drivers/video/fbdev/msm/mdss_fb.h
+++ b/drivers/video/fbdev/msm/mdss_fb.h
@@ -307,7 +307,7 @@
 	u32 calib_mode;
 	u32 calib_mode_bl;
 	u32 ad_bl_level;
-	u32 bl_level;
+	u64 bl_level;
 	u32 bl_scale;
 	u32 bl_min_lvl;
 	u32 unset_bl_level;
diff --git a/drivers/video/fbdev/msm/mdss_mdp.c b/drivers/video/fbdev/msm/mdss_mdp.c
index a9a5d8f..13a4bb6 100644
--- a/drivers/video/fbdev/msm/mdss_mdp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp.c
@@ -2124,6 +2124,7 @@
 			return -EINVAL;
 	}
 
+	mutex_init(&mdata->scaler_off->scaler_lock);
 	return 0;
 }
 
diff --git a/drivers/video/fbdev/msm/mdss_mdp_debug.c b/drivers/video/fbdev/msm/mdss_mdp_debug.c
index d24ff53..6024ea1 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_debug.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_debug.c
@@ -1414,7 +1414,7 @@
 		seq_printf(s, "vsync: %08u \tunderrun: %08u\n",
 				ctl->vsync_cnt, ctl->underrun_cnt);
 		if (ctl->mfd) {
-			seq_printf(s, "user_bl: %08u \tmod_bl: %08u\n",
+			seq_printf(s, "user_bl: %08llu \tmod_bl: %08u\n",
 				ctl->mfd->bl_level, ctl->mfd->bl_level_scaled);
 		}
 	} else {
diff --git a/drivers/video/fbdev/msm/mdss_mdp_overlay.c b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
index 3144b6c..3ae59a2 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_overlay.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_overlay.c
@@ -2015,7 +2015,7 @@
 {
 	int vsync_diff;
 	int round_up = 0;
-	s64 ts_diff = (cur_ts - base_ts) * display_fp1000s;
+	u64 ts_diff = (cur_ts - base_ts) * display_fp1000s;
 
 	do_div(ts_diff, 1000000);
 	vsync_diff = (int)ts_diff;
@@ -2065,7 +2065,7 @@
 	struct mdss_mdp_frc_cadence_calc *calc = &frc_info->calc;
 	struct mdss_mdp_frc_data *first = &calc->samples[0];
 	struct mdss_mdp_frc_data *last = &calc->samples[cnt-1];
-	s64 ts_diff =
+	u64 ts_diff =
 		(last->timestamp - first->timestamp)
 				* frc_info->display_fp1000s;
 	u32 fcnt_diff =
@@ -6792,14 +6792,18 @@
 	if (!mdata->scaler_off)
 		return -EFAULT;
 
+	mutex_lock(&mdata->scaler_off->scaler_lock);
+
 	qseed3_lut_tbl = &mdata->scaler_off->lut_tbl;
 	if ((lut_tbl->dir_lut_size !=
 		DIR_LUT_IDX * DIR_LUT_COEFFS * sizeof(uint32_t)) ||
 		(lut_tbl->cir_lut_size !=
 		 CIR_LUT_IDX * CIR_LUT_COEFFS * sizeof(uint32_t)) ||
 		(lut_tbl->sep_lut_size !=
-		 SEP_LUT_IDX * SEP_LUT_COEFFS * sizeof(uint32_t)))
+		 SEP_LUT_IDX * SEP_LUT_COEFFS * sizeof(uint32_t))) {
+		mutex_unlock(&mdata->scaler_off->scaler_lock);
 		return -EINVAL;
+	}
 
 	if (!qseed3_lut_tbl->dir_lut) {
 		qseed3_lut_tbl->dir_lut = devm_kzalloc(&mdata->pdev->dev,
@@ -6807,7 +6811,7 @@
 				GFP_KERNEL);
 		if (!qseed3_lut_tbl->dir_lut) {
 			ret = -ENOMEM;
-			goto fail;
+			goto err;
 		}
 	}
 
@@ -6817,7 +6821,7 @@
 				GFP_KERNEL);
 		if (!qseed3_lut_tbl->cir_lut) {
 			ret = -ENOMEM;
-			goto fail;
+			goto fail_free_dir_lut;
 		}
 	}
 
@@ -6827,44 +6831,52 @@
 				GFP_KERNEL);
 		if (!qseed3_lut_tbl->sep_lut) {
 			ret = -ENOMEM;
-			goto fail;
+			goto fail_free_cir_lut;
 		}
 	}
 
 	/* Invalidate before updating */
 	qseed3_lut_tbl->valid = false;
 
-
 	if (copy_from_user(qseed3_lut_tbl->dir_lut,
 				(void *)(unsigned long)lut_tbl->dir_lut,
 				lut_tbl->dir_lut_size)) {
 		ret = -EINVAL;
-		goto err;
+		goto fail_free_sep_lut;
 	}
 
 	if (copy_from_user(qseed3_lut_tbl->cir_lut,
 				(void *)(unsigned long)lut_tbl->cir_lut,
 				lut_tbl->cir_lut_size)) {
 		ret = -EINVAL;
-		goto err;
+		goto fail_free_sep_lut;
 	}
 
 	if (copy_from_user(qseed3_lut_tbl->sep_lut,
 				(void *)(unsigned long)lut_tbl->sep_lut,
 				lut_tbl->sep_lut_size)) {
 		ret = -EINVAL;
-		goto err;
+		goto fail_free_sep_lut;
 	}
 
 	qseed3_lut_tbl->valid = true;
+	mutex_unlock(&mdata->scaler_off->scaler_lock);
+
 	return ret;
 
-fail:
-	kfree(qseed3_lut_tbl->dir_lut);
-	kfree(qseed3_lut_tbl->cir_lut);
-	kfree(qseed3_lut_tbl->sep_lut);
+fail_free_sep_lut:
+	devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->sep_lut);
+fail_free_cir_lut:
+	devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->cir_lut);
+fail_free_dir_lut:
+	devm_kfree(&mdata->pdev->dev, qseed3_lut_tbl->dir_lut);
 err:
+	qseed3_lut_tbl->dir_lut = NULL;
+	qseed3_lut_tbl->cir_lut = NULL;
+	qseed3_lut_tbl->sep_lut = NULL;
 	qseed3_lut_tbl->valid = false;
+	mutex_unlock(&mdata->scaler_off->scaler_lock);
+
 	return ret;
 }
 
diff --git a/drivers/video/fbdev/msm/mdss_mdp_pp.c b/drivers/video/fbdev/msm/mdss_mdp_pp.c
index 74b698c..13afa46 100644
--- a/drivers/video/fbdev/msm/mdss_mdp_pp.c
+++ b/drivers/video/fbdev/msm/mdss_mdp_pp.c
@@ -1578,11 +1578,16 @@
 	};
 
 	mdata = mdss_mdp_get_mdata();
+
+	mutex_lock(&mdata->scaler_off->scaler_lock);
+
 	lut_tbl = &mdata->scaler_off->lut_tbl;
 	if ((!lut_tbl) || (!lut_tbl->valid)) {
+		mutex_unlock(&mdata->scaler_off->scaler_lock);
 		pr_err("%s:Invalid QSEED3 LUT TABLE\n", __func__);
 		return -EINVAL;
 	}
+
 	if ((scaler->lut_flag & SCALER_LUT_DIR_WR) ||
 		(scaler->lut_flag & SCALER_LUT_Y_CIR_WR) ||
 		(scaler->lut_flag & SCALER_LUT_UV_CIR_WR) ||
@@ -1632,6 +1637,7 @@
 	if (scaler->lut_flag & SCALER_LUT_SWAP)
 		writel_relaxed(BIT(0), MDSS_MDP_REG_SCALER_COEF_LUT_CTRL +
 				offset);
+	mutex_unlock(&mdata->scaler_off->scaler_lock);
 
 	return 0;
 }
@@ -5772,7 +5778,7 @@
 			struct mdss_ad_input *input, int wait) {
 	int ret = 0;
 	struct mdss_ad_info *ad;
-	u32 bl;
+	u64 bl;
 	struct mdss_overlay_private *mdp5_data;
 
 	ret = mdss_mdp_get_ad(mfd, &ad);
diff --git a/drivers/video/fbdev/msm/mdss_smmu.c b/drivers/video/fbdev/msm/mdss_smmu.c
index 7a44824..fbbdaf2 100644
--- a/drivers/video/fbdev/msm/mdss_smmu.c
+++ b/drivers/video/fbdev/msm/mdss_smmu.c
@@ -316,7 +316,7 @@
 	}
 	ATRACE_END("map_buffer");
 	*iova = table->sgl->dma_address;
-	*size = table->sgl->dma_length;
+	*size = sg_dma_len(table->sgl);
 	return 0;
 }
 
diff --git a/drivers/video/fbdev/msm/mdss_sync.c b/drivers/video/fbdev/msm/mdss_sync.c
index 7b1028ab..22fdcf5 100644
--- a/drivers/video/fbdev/msm/mdss_sync.c
+++ b/drivers/video/fbdev/msm/mdss_sync.c
@@ -51,6 +51,7 @@
 struct mdss_timeline {
 	struct kref kref;
 	spinlock_t lock;
+	spinlock_t list_lock;
 	char name[MDSS_SYNC_NAME_SIZE];
 	u32 next_value;
 	u32 value;
@@ -58,6 +59,7 @@
 	struct list_head fence_list_head;
 };
 
+#if defined(CONFIG_SYNC_FILE)
 /*
  * to_mdss_fence - get mdss fence from fence base object
  * @fence: Pointer to fence base object
@@ -148,12 +150,13 @@
 static void mdss_fence_release(struct fence *fence)
 {
 	struct mdss_fence *f = to_mdss_fence(fence);
-	unsigned long flags;
+	struct mdss_timeline *tl = to_mdss_timeline(fence);
 
-	spin_lock_irqsave(fence->lock, flags);
+	pr_debug("%s for fence %s\n", __func__, f->name);
+	spin_lock(&tl->list_lock);
 	if (!list_empty(&f->fence_list))
 		list_del(&f->fence_list);
-	spin_unlock_irqrestore(fence->lock, flags);
+	spin_unlock(&tl->list_lock);
 	mdss_put_timeline(to_mdss_timeline(fence));
 	kfree_rcu(f, base.rcu);
 }
@@ -202,6 +205,7 @@
 	kref_init(&tl->kref);
 	snprintf(tl->name, sizeof(tl->name), "%s", name);
 	spin_lock_init(&tl->lock);
+	spin_lock_init(&tl->list_lock);
 	tl->context = fence_context_alloc(1);
 	INIT_LIST_HEAD(&tl->fence_list_head);
 
@@ -227,15 +231,41 @@
 {
 	struct mdss_fence *f, *next;
 	s32 val;
+	bool is_signaled = false;
+	struct list_head local_list_head;
+	unsigned long flags;
 
+	INIT_LIST_HEAD(&local_list_head);
+
+	spin_lock(&tl->list_lock);
+	if (list_empty(&tl->fence_list_head)) {
+		pr_debug("fence list is empty\n");
+		spin_unlock(&tl->list_lock);
+		return 0;
+	}
+
+	list_for_each_entry_safe(f, next, &tl->fence_list_head, fence_list)
+		list_move(&f->fence_list, &local_list_head);
+	spin_unlock(&tl->list_lock);
+
+	spin_lock_irqsave(&tl->lock, flags);
 	val = tl->next_value - tl->value;
 	if (val >= increment)
 		tl->value += increment;
+	spin_unlock_irqrestore(&tl->lock, flags);
 
-	list_for_each_entry_safe(f, next, &tl->fence_list_head, fence_list) {
-		if (fence_is_signaled_locked(&f->base)) {
+	list_for_each_entry_safe(f, next, &local_list_head, fence_list) {
+		spin_lock_irqsave(&tl->lock, flags);
+		is_signaled = fence_is_signaled_locked(&f->base);
+		spin_unlock_irqrestore(&tl->lock, flags);
+		if (is_signaled) {
 			pr_debug("%s signaled\n", f->name);
 			list_del_init(&f->fence_list);
+			fence_put(&f->base);
+		} else {
+			spin_lock(&tl->list_lock);
+			list_move(&f->fence_list, &tl->fence_list_head);
+			spin_unlock(&tl->list_lock);
 		}
 	}
 
@@ -248,7 +278,6 @@
  */
 void mdss_resync_timeline(struct mdss_timeline *tl)
 {
-	unsigned long flags;
 	s32 val;
 
 	if (!tl) {
@@ -256,14 +285,12 @@
 		return;
 	}
 
-	spin_lock_irqsave(&tl->lock, flags);
 	val = tl->next_value - tl->value;
 	if (val > 0) {
 		pr_warn("flush %s:%d TL(Nxt %d , Crnt %d)\n", tl->name, val,
 			tl->next_value, tl->value);
 		mdss_inc_timeline_locked(tl, val);
 	}
-	spin_unlock_irqrestore(&tl->lock, flags);
 }
 
 /*
@@ -277,8 +304,8 @@
 		u32 *timestamp, int offset)
 {
 	struct mdss_fence *f;
-	unsigned long flags;
 	u32 val;
+	unsigned long flags;
 
 	if (!tl) {
 		pr_err("invalid parameters\n");
@@ -294,9 +321,12 @@
 	val = tl->next_value + offset;
 	tl->next_value += 1;
 	fence_init(&f->base, &mdss_fence_ops, &tl->lock, tl->context, val);
-	list_add_tail(&f->fence_list, &tl->fence_list_head);
 	mdss_get_timeline(tl);
 	spin_unlock_irqrestore(&tl->lock, flags);
+
+	spin_lock(&tl->list_lock);
+	list_add_tail(&f->fence_list, &tl->fence_list_head);
+	spin_unlock(&tl->list_lock);
 	snprintf(f->name, sizeof(f->name), "%s_%u", fence_name, val);
 
 	if (timestamp)
@@ -315,7 +345,6 @@
  */
 int mdss_inc_timeline(struct mdss_timeline *tl, int increment)
 {
-	unsigned long flags;
 	int rc;
 
 	if (!tl) {
@@ -323,10 +352,7 @@
 		return -EINVAL;
 	}
 
-	spin_lock_irqsave(&tl->lock, flags);
 	rc = mdss_inc_timeline_locked(tl, increment);
-	spin_unlock_irqrestore(&tl->lock, flags);
-
 	return rc;
 }
 
@@ -468,3 +494,4 @@
 
 	return fence->name;
 }
+#endif
diff --git a/drivers/video/fbdev/msm/mdss_sync.h b/drivers/video/fbdev/msm/mdss_sync.h
index 39a1aa7b..a2e84d4 100644
--- a/drivers/video/fbdev/msm/mdss_sync.h
+++ b/drivers/video/fbdev/msm/mdss_sync.h
@@ -112,11 +112,12 @@
 {
 	return -EBADF;
 }
+
+static inline
 const char *mdss_get_sync_fence_name(struct mdss_fence *fence)
 {
 	return NULL;
 }
-}
 #endif
 
 #endif /* MDSS_SYNC_H */
diff --git a/drivers/video/fbdev/msm/msm_mdss_io_8974.c b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
index 39d26a4..ec1ee60 100644
--- a/drivers/video/fbdev/msm/msm_mdss_io_8974.c
+++ b/drivers/video/fbdev/msm/msm_mdss_io_8974.c
@@ -2033,7 +2033,7 @@
 {
 	int rc = 0;
 	struct mdss_dsi_ctrl_pdata *mctrl = NULL;
-	int i, *vote_cnt;
+	int i, *vote_cnt = NULL;
 
 	void *m_clk_handle;
 	bool is_ecg = false;
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 4874b0f..518dfa1 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -169,15 +169,21 @@
 	return 0;
 }
 
-static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
-				unsigned int new_timeout)
+static void __imx2_wdt_set_timeout(struct watchdog_device *wdog,
+				   unsigned int new_timeout)
 {
 	struct imx2_wdt_device *wdev = watchdog_get_drvdata(wdog);
 
-	wdog->timeout = new_timeout;
-
 	regmap_update_bits(wdev->regmap, IMX2_WDT_WCR, IMX2_WDT_WCR_WT,
 			   WDOG_SEC_TO_COUNT(new_timeout));
+}
+
+static int imx2_wdt_set_timeout(struct watchdog_device *wdog,
+				unsigned int new_timeout)
+{
+	__imx2_wdt_set_timeout(wdog, new_timeout);
+
+	wdog->timeout = new_timeout;
 	return 0;
 }
 
@@ -371,7 +377,11 @@
 
 	/* The watchdog IP block is running */
 	if (imx2_wdt_is_running(wdev)) {
-		imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
+		/*
+		 * Don't update wdog->timeout, we'll restore the current value
+		 * during resume.
+		 */
+		__imx2_wdt_set_timeout(wdog, IMX2_WDT_MAX_TIME);
 		imx2_wdt_ping(wdog);
 	}
 
diff --git a/fs/block_dev.c b/fs/block_dev.c
index cb936c9..9900693 100644
--- a/fs/block_dev.c
+++ b/fs/block_dev.c
@@ -614,6 +614,7 @@
 #ifdef CONFIG_SYSFS
 	INIT_LIST_HEAD(&bdev->bd_holder_disks);
 #endif
+	bdev->bd_bdi = &noop_backing_dev_info;
 	inode_init_once(&ei->vfs_inode);
 	/* Initialize mutex for freeze. */
 	mutex_init(&bdev->bd_fsfreeze_mutex);
@@ -628,6 +629,12 @@
 	spin_lock(&bdev_lock);
 	list_del_init(&bdev->bd_list);
 	spin_unlock(&bdev_lock);
+	/* Detach inode from wb early as bdi_put() may free bdi->wb */
+	inode_detach_wb(inode);
+	if (bdev->bd_bdi != &noop_backing_dev_info) {
+		bdi_put(bdev->bd_bdi);
+		bdev->bd_bdi = &noop_backing_dev_info;
+	}
 }
 
 static const struct super_operations bdev_sops = {
@@ -698,6 +705,21 @@
 
 static LIST_HEAD(all_bdevs);
 
+/*
+ * If there is a bdev inode for this device, unhash it so that it gets evicted
+ * as soon as last inode reference is dropped.
+ */
+void bdev_unhash_inode(dev_t dev)
+{
+	struct inode *inode;
+
+	inode = ilookup5(blockdev_superblock, hash(dev), bdev_test, &dev);
+	if (inode) {
+		remove_inode_hash(inode);
+		iput(inode);
+	}
+}
+
 struct block_device *bdget(dev_t dev)
 {
 	struct block_device *bdev;
@@ -769,13 +791,22 @@
 
 	spin_lock(&bdev_lock);
 	bdev = inode->i_bdev;
-	if (bdev) {
+	if (bdev && !inode_unhashed(bdev->bd_inode)) {
 		bdgrab(bdev);
 		spin_unlock(&bdev_lock);
 		return bdev;
 	}
 	spin_unlock(&bdev_lock);
 
+	/*
+	 * i_bdev references block device inode that was already shut down
+	 * (corresponding device got removed).  Remove the reference and look
+	 * up block device inode again just in case new device got
+	 * reestablished under the same device number.
+	 */
+	if (bdev)
+		bd_forget(inode);
+
 	bdev = bdget(inode->i_rdev);
 	if (bdev) {
 		spin_lock(&bdev_lock);
@@ -1334,6 +1365,9 @@
 			}
 			bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
 		}
+
+		if (bdev->bd_bdi == &noop_backing_dev_info)
+			bdev->bd_bdi = bdi_get(disk->queue->backing_dev_info);
 	} else {
 		if (bdev->bd_contains == bdev) {
 			ret = 0;
@@ -1586,12 +1620,6 @@
 		kill_bdev(bdev);
 
 		bdev_write_inode(bdev);
-		/*
-		 * Detaching bdev inode from its wb in __destroy_inode()
-		 * is too late: the queue which embeds its bdi (along with
-		 * root wb) can be gone as soon as we put_disk() below.
-		 */
-		inode_detach_wb(bdev->bd_inode);
 	}
 	if (bdev->bd_contains == bdev) {
 		if (disk->fops->release)
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 1cd3257..c66054c 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -1816,7 +1816,7 @@
 	list_for_each_entry_rcu(device, &info->fs_devices->devices, dev_list) {
 		if (!device->bdev)
 			continue;
-		bdi = blk_get_backing_dev_info(device->bdev);
+		bdi = device->bdev->bd_bdi;
 		if (bdi_congested(bdi, bdi_bits)) {
 			ret = 1;
 			break;
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 894d563..a8a1fb4 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2063,8 +2063,15 @@
 		goto out;
 	 }
 
-	btrfs_set_extent_delalloc(inode, page_start, page_end, &cached_state,
-				  0);
+	ret = btrfs_set_extent_delalloc(inode, page_start, page_end,
+					&cached_state, 0);
+	if (ret) {
+		mapping_set_error(page->mapping, ret);
+		end_extent_writepage(page, ret, page_start, page_end);
+		ClearPageChecked(page);
+		goto out;
+	}
+
 	ClearPageChecked(page);
 	set_page_dirty(page);
 out:
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 06a77e4..fad7b37 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -366,7 +366,7 @@
 	 */
 	blk_start_plug(&plug);
 
-	bdi = blk_get_backing_dev_info(device->bdev);
+	bdi = device->bdev->bd_bdi;
 	fs_info = device->dev_root->fs_info;
 	limit = btrfs_async_submit_limit(fs_info);
 	limit = limit * 2 / 3;
diff --git a/fs/cifs/cifsencrypt.c b/fs/cifs/cifsencrypt.c
index 5eb0412..73360df 100644
--- a/fs/cifs/cifsencrypt.c
+++ b/fs/cifs/cifsencrypt.c
@@ -318,9 +318,8 @@
 {
 	int i;
 	int rc;
-	char password_with_pad[CIFS_ENCPWD_SIZE];
+	char password_with_pad[CIFS_ENCPWD_SIZE] = {0};
 
-	memset(password_with_pad, 0, CIFS_ENCPWD_SIZE);
 	if (password)
 		strncpy(password_with_pad, password, CIFS_ENCPWD_SIZE);
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 580b3a4..441d434 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1667,7 +1667,7 @@
 			tmp_end++;
 			if (!(tmp_end < end && tmp_end[1] == delim)) {
 				/* No it is not. Set the password to NULL */
-				kfree(vol->password);
+				kzfree(vol->password);
 				vol->password = NULL;
 				break;
 			}
@@ -1705,7 +1705,7 @@
 					options = end;
 			}
 
-			kfree(vol->password);
+			kzfree(vol->password);
 			/* Now build new password string */
 			temp_len = strlen(value);
 			vol->password = kzalloc(temp_len+1, GFP_KERNEL);
@@ -4159,7 +4159,7 @@
 		reset_cifs_unix_caps(0, tcon, NULL, vol_info);
 out:
 	kfree(vol_info->username);
-	kfree(vol_info->password);
+	kzfree(vol_info->password);
 	kfree(vol_info);
 
 	return tcon;
diff --git a/fs/cifs/file.c b/fs/cifs/file.c
index cf192f9..02e403a 100644
--- a/fs/cifs/file.c
+++ b/fs/cifs/file.c
@@ -3285,20 +3285,18 @@
 
 int cifs_file_strict_mmap(struct file *file, struct vm_area_struct *vma)
 {
-	int rc, xid;
+	int xid, rc = 0;
 	struct inode *inode = file_inode(file);
 
 	xid = get_xid();
 
-	if (!CIFS_CACHE_READ(CIFS_I(inode))) {
+	if (!CIFS_CACHE_READ(CIFS_I(inode)))
 		rc = cifs_zap_mapping(inode);
-		if (rc)
-			return rc;
-	}
-
-	rc = generic_file_mmap(file, vma);
-	if (rc == 0)
+	if (!rc)
+		rc = generic_file_mmap(file, vma);
+	if (!rc)
 		vma->vm_ops = &cifs_file_vm_ops;
+
 	free_xid(xid);
 	return rc;
 }
@@ -3308,16 +3306,16 @@
 	int rc, xid;
 
 	xid = get_xid();
+
 	rc = cifs_revalidate_file(file);
-	if (rc) {
+	if (rc)
 		cifs_dbg(FYI, "Validation prior to mmap failed, error=%d\n",
 			 rc);
-		free_xid(xid);
-		return rc;
-	}
-	rc = generic_file_mmap(file, vma);
-	if (rc == 0)
+	if (!rc)
+		rc = generic_file_mmap(file, vma);
+	if (!rc)
 		vma->vm_ops = &cifs_file_vm_ops;
+
 	free_xid(xid);
 	return rc;
 }
diff --git a/fs/cifs/misc.c b/fs/cifs/misc.c
index 5419afe..323d8e3 100644
--- a/fs/cifs/misc.c
+++ b/fs/cifs/misc.c
@@ -99,14 +99,11 @@
 	kfree(buf_to_free->serverOS);
 	kfree(buf_to_free->serverDomain);
 	kfree(buf_to_free->serverNOS);
-	if (buf_to_free->password) {
-		memset(buf_to_free->password, 0, strlen(buf_to_free->password));
-		kfree(buf_to_free->password);
-	}
+	kzfree(buf_to_free->password);
 	kfree(buf_to_free->user_name);
 	kfree(buf_to_free->domainName);
-	kfree(buf_to_free->auth_key.response);
-	kfree(buf_to_free);
+	kzfree(buf_to_free->auth_key.response);
+	kzfree(buf_to_free);
 }
 
 struct cifs_tcon *
@@ -137,10 +134,7 @@
 	}
 	atomic_dec(&tconInfoAllocCount);
 	kfree(buf_to_free->nativeFileSystem);
-	if (buf_to_free->password) {
-		memset(buf_to_free->password, 0, strlen(buf_to_free->password));
-		kfree(buf_to_free->password);
-	}
+	kzfree(buf_to_free->password);
 	kfree(buf_to_free);
 }
 
diff --git a/fs/cifs/smb2pdu.c b/fs/cifs/smb2pdu.c
index 69b610ad..94c4c19 100644
--- a/fs/cifs/smb2pdu.c
+++ b/fs/cifs/smb2pdu.c
@@ -585,8 +585,7 @@
 	}
 
 	/* check validate negotiate info response matches what we got earlier */
-	if (pneg_rsp->Dialect !=
-			cpu_to_le16(tcon->ses->server->vals->protocol_id))
+	if (pneg_rsp->Dialect != cpu_to_le16(tcon->ses->server->dialect))
 		goto vneg_out;
 
 	if (pneg_rsp->SecurityMode != cpu_to_le16(tcon->ses->server->sec_mode))
diff --git a/fs/gfs2/ops_fstype.c b/fs/gfs2/ops_fstype.c
index ff72ac6..77f1e25 100644
--- a/fs/gfs2/ops_fstype.c
+++ b/fs/gfs2/ops_fstype.c
@@ -1226,7 +1226,7 @@
 	 * We set the bdi here to the queue backing, file systems can
 	 * overwrite this in ->fill_super()
 	 */
-	s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info;
+	s->s_bdi = bdev_get_queue(s->s_bdev)->backing_dev_info;
 	return 0;
 }
 
diff --git a/fs/kernfs/file.c b/fs/kernfs/file.c
index 78219d5..d6512cd 100644
--- a/fs/kernfs/file.c
+++ b/fs/kernfs/file.c
@@ -275,7 +275,7 @@
 {
 	struct kernfs_open_file *of = kernfs_of(file);
 	const struct kernfs_ops *ops;
-	size_t len;
+	ssize_t len;
 	char *buf;
 
 	if (of->atomic_write_len) {
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index bd81bcf..1ac1593 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -787,10 +787,8 @@
 
 	spin_lock(&dreq->lock);
 
-	if (test_bit(NFS_IOHDR_ERROR, &hdr->flags)) {
-		dreq->flags = 0;
+	if (test_bit(NFS_IOHDR_ERROR, &hdr->flags))
 		dreq->error = hdr->error;
-	}
 	if (dreq->error == 0) {
 		nfs_direct_good_bytes(dreq, hdr);
 		if (nfs_write_need_commit(hdr)) {
diff --git a/fs/nfs/io.c b/fs/nfs/io.c
index 1fc5d1c..d18ccc1 100644
--- a/fs/nfs/io.c
+++ b/fs/nfs/io.c
@@ -98,7 +98,7 @@
 {
 	if (!test_bit(NFS_INO_ODIRECT, &nfsi->flags)) {
 		set_bit(NFS_INO_ODIRECT, &nfsi->flags);
-		nfs_wb_all(inode);
+		nfs_sync_mapping(inode->i_mapping);
 	}
 }
 
diff --git a/fs/nfs/nfs4idmap.c b/fs/nfs/nfs4idmap.c
index c444285..f1160cd 100644
--- a/fs/nfs/nfs4idmap.c
+++ b/fs/nfs/nfs4idmap.c
@@ -567,9 +567,13 @@
 	struct idmap_msg *im;
 	struct idmap *idmap = (struct idmap *)aux;
 	struct key *key = cons->key;
-	int ret = -ENOMEM;
+	int ret = -ENOKEY;
+
+	if (!aux)
+		goto out1;
 
 	/* msg and im are freed in idmap_pipe_destroy_msg */
+	ret = -ENOMEM;
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		goto out1;
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index b7a07ba..b8e4474 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -2145,7 +2145,7 @@
 		nfs_pageio_reset_write_mds(desc);
 		mirror->pg_recoalesce = 1;
 	}
-	hdr->release(hdr);
+	hdr->completion_ops->completion(hdr);
 }
 
 static enum pnfs_try_status
@@ -2256,7 +2256,7 @@
 		nfs_pageio_reset_read_mds(desc);
 		mirror->pg_recoalesce = 1;
 	}
-	hdr->release(hdr);
+	hdr->completion_ops->completion(hdr);
 }
 
 /*
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 9905735..9a3b382 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -1806,6 +1806,8 @@
 		set_bit(NFS_CONTEXT_RESEND_WRITES, &req->wb_context->flags);
 	next:
 		nfs_unlock_and_release_request(req);
+		/* Latency breaker */
+		cond_resched();
 	}
 	nfss = NFS_SERVER(data->inode);
 	if (atomic_long_read(&nfss->writeback) < NFS_CONGESTION_OFF_THRESH)
diff --git a/fs/nilfs2/super.c b/fs/nilfs2/super.c
index c95d369..ff158f0 100644
--- a/fs/nilfs2/super.c
+++ b/fs/nilfs2/super.c
@@ -1068,7 +1068,7 @@
 	sb->s_time_gran = 1;
 	sb->s_max_links = NILFS_LINK_MAX;
 
-	sb->s_bdi = &bdev_get_queue(sb->s_bdev)->backing_dev_info;
+	sb->s_bdi = bdev_get_queue(sb->s_bdev)->backing_dev_info;
 
 	err = load_nilfs(nilfs, sb);
 	if (err)
diff --git a/fs/overlayfs/readdir.c b/fs/overlayfs/readdir.c
index f241b4e..a1be6ba 100644
--- a/fs/overlayfs/readdir.c
+++ b/fs/overlayfs/readdir.c
@@ -434,10 +434,14 @@
 	struct dentry *dentry = file->f_path.dentry;
 	struct file *realfile = od->realfile;
 
+	/* Nothing to sync for lower */
+	if (!OVL_TYPE_UPPER(ovl_path_type(dentry)))
+		return 0;
+
 	/*
 	 * Need to check if we started out being a lower dir, but got copied up
 	 */
-	if (!od->is_upper && OVL_TYPE_UPPER(ovl_path_type(dentry))) {
+	if (!od->is_upper) {
 		struct inode *inode = file_inode(file);
 
 		realfile = lockless_dereference(od->upperfile);
diff --git a/fs/pipe.c b/fs/pipe.c
index 9faecf1..3434553 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -609,12 +609,17 @@
 
 static bool too_many_pipe_buffers_soft(unsigned long user_bufs)
 {
-	return pipe_user_pages_soft && user_bufs >= pipe_user_pages_soft;
+	return pipe_user_pages_soft && user_bufs > pipe_user_pages_soft;
 }
 
 static bool too_many_pipe_buffers_hard(unsigned long user_bufs)
 {
-	return pipe_user_pages_hard && user_bufs >= pipe_user_pages_hard;
+	return pipe_user_pages_hard && user_bufs > pipe_user_pages_hard;
+}
+
+static bool is_unprivileged_user(void)
+{
+	return !capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN);
 }
 
 struct pipe_inode_info *alloc_pipe_info(void)
@@ -633,12 +638,12 @@
 
 	user_bufs = account_pipe_buffers(user, 0, pipe_bufs);
 
-	if (too_many_pipe_buffers_soft(user_bufs)) {
+	if (too_many_pipe_buffers_soft(user_bufs) && is_unprivileged_user()) {
 		user_bufs = account_pipe_buffers(user, pipe_bufs, 1);
 		pipe_bufs = 1;
 	}
 
-	if (too_many_pipe_buffers_hard(user_bufs))
+	if (too_many_pipe_buffers_hard(user_bufs) && is_unprivileged_user())
 		goto out_revert_acct;
 
 	pipe->bufs = kcalloc(pipe_bufs, sizeof(struct pipe_buffer),
@@ -1069,7 +1074,7 @@
 	if (nr_pages > pipe->buffers &&
 			(too_many_pipe_buffers_hard(user_bufs) ||
 			 too_many_pipe_buffers_soft(user_bufs)) &&
-			!capable(CAP_SYS_RESOURCE) && !capable(CAP_SYS_ADMIN)) {
+			is_unprivileged_user()) {
 		ret = -EPERM;
 		goto out_revert_acct;
 	}
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 5c89a07..df7e079 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -507,23 +507,15 @@
 				return -EFAULT;
 		} else {
 			if (kern_addr_valid(start)) {
-				unsigned long n;
-
 				/*
 				 * Using bounce buffer to bypass the
 				 * hardened user copy kernel text checks.
 				 */
-				memcpy(buf, (char *) start, tsz);
-				n = copy_to_user(buffer, buf, tsz);
-				/*
-				 * We cannot distinguish between fault on source
-				 * and fault on destination. When this happens
-				 * we clear too and hope it will trigger the
-				 * EFAULT again.
-				 */
-				if (n) { 
-					if (clear_user(buffer + tsz - n,
-								n))
+				if (probe_kernel_read(buf, (void *) start, tsz)) {
+					if (clear_user(buffer, tsz))
+						return -EFAULT;
+				} else {
+					if (copy_to_user(buffer, buf, tsz))
 						return -EFAULT;
 				}
 			} else {
diff --git a/fs/super.c b/fs/super.c
index 2987fe3..847d82d 100644
--- a/fs/super.c
+++ b/fs/super.c
@@ -1030,7 +1030,7 @@
 	 * We set the bdi here to the queue backing, file systems can
 	 * overwrite this in ->fill_super()
 	 */
-	s->s_bdi = &bdev_get_queue(s->s_bdev)->backing_dev_info;
+	s->s_bdi = bdev_get_queue(s->s_bdev)->backing_dev_info;
 	return 0;
 }
 
diff --git a/fs/ubifs/xattr.c b/fs/ubifs/xattr.c
index d9f9615..3979d76 100644
--- a/fs/ubifs/xattr.c
+++ b/fs/ubifs/xattr.c
@@ -270,7 +270,8 @@
 }
 
 static int __ubifs_setxattr(struct inode *host, const char *name,
-			    const void *value, size_t size, int flags)
+			    const void *value, size_t size, int flags,
+			    bool check_lock)
 {
 	struct inode *inode;
 	struct ubifs_info *c = host->i_sb->s_fs_info;
@@ -279,7 +280,8 @@
 	union ubifs_key key;
 	int err;
 
-	ubifs_assert(inode_is_locked(host));
+	if (check_lock)
+		ubifs_assert(inode_is_locked(host));
 
 	if (size > UBIFS_MAX_INO_DATA)
 		return -ERANGE;
@@ -548,7 +550,8 @@
 		}
 		strcpy(name, XATTR_SECURITY_PREFIX);
 		strcpy(name + XATTR_SECURITY_PREFIX_LEN, xattr->name);
-		err = __ubifs_setxattr(inode, name, xattr->value, xattr->value_len, 0);
+		err = __ubifs_setxattr(inode, name, xattr->value,
+				       xattr->value_len, 0, false);
 		kfree(name);
 		if (err < 0)
 			break;
@@ -594,7 +597,8 @@
 	name = xattr_full_name(handler, name);
 
 	if (value)
-		return __ubifs_setxattr(inode, name, value, size, flags);
+		return __ubifs_setxattr(inode, name, value, size, flags,
+					true);
 	else
 		return __ubifs_removexattr(inode, name);
 }
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 3f45d98..7a04b03 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -744,7 +744,7 @@
 	int			nmaps,
 	const struct xfs_buf_ops *ops)
 {
-	if (bdi_read_congested(target->bt_bdi))
+	if (bdi_read_congested(target->bt_bdev->bd_bdi))
 		return;
 
 	xfs_buf_read_map(target, map, nmaps,
@@ -1782,7 +1782,6 @@
 	btp->bt_mount = mp;
 	btp->bt_dev =  bdev->bd_dev;
 	btp->bt_bdev = bdev;
-	btp->bt_bdi = blk_get_backing_dev_info(bdev);
 
 	if (xfs_setsize_buftarg_early(btp, bdev))
 		goto error_free;
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index f961b19..c26b36a 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -107,7 +107,6 @@
 typedef struct xfs_buftarg {
 	dev_t			bt_dev;
 	struct block_device	*bt_bdev;
-	struct backing_dev_info	*bt_bdi;
 	struct xfs_mount	*bt_mount;
 	unsigned int		bt_meta_sectorsize;
 	size_t			bt_meta_sectormask;
diff --git a/include/crypto/internal/hash.h b/include/crypto/internal/hash.h
index cac5735..5203560 100644
--- a/include/crypto/internal/hash.h
+++ b/include/crypto/internal/hash.h
@@ -88,6 +88,8 @@
 	return alg->setkey != shash_no_setkey;
 }
 
+bool crypto_hash_alg_has_setkey(struct hash_alg_common *halg);
+
 int crypto_init_ahash_spawn(struct crypto_ahash_spawn *spawn,
 			    struct hash_alg_common *alg,
 			    struct crypto_instance *inst);
diff --git a/include/crypto/poly1305.h b/include/crypto/poly1305.h
index 894df59..d586f74 100644
--- a/include/crypto/poly1305.h
+++ b/include/crypto/poly1305.h
@@ -30,8 +30,6 @@
 };
 
 int crypto_poly1305_init(struct shash_desc *desc);
-int crypto_poly1305_setkey(struct crypto_shash *tfm,
-			   const u8 *key, unsigned int keylen);
 unsigned int crypto_poly1305_setdesckey(struct poly1305_desc_ctx *dctx,
 					const u8 *src, unsigned int srclen);
 int crypto_poly1305_update(struct shash_desc *desc,
diff --git a/include/dt-bindings/clock/mdm-clocks-9607.h b/include/dt-bindings/clock/mdm-clocks-9607.h
new file mode 100644
index 0000000..c2c5f26
--- /dev/null
+++ b/include/dt-bindings/clock/mdm-clocks-9607.h
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 2015, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MDM_CLOCKS_9607_H
+#define __MDM_CLOCKS_9607_H
+
+/*PLL Sources */
+#define clk_gpll0_clk_src					 0x5933b69f
+#define clk_gpll0_ao_clk_src                                     0x6b2fb034
+#define clk_gpll2_clk_src					 0x7c34503b
+#define clk_gpll1_clk_src					 0x916f8847
+
+#define clk_a7sspll						 0x0b2e5cbd
+
+/*RPM and Voter clocks */
+#define clk_pcnoc_clk						 0xc1296d0f
+#define clk_pcnoc_a_clk						 0x9bcffee4
+#define clk_pcnoc_msmbus_clk					 0x2b53b688
+#define clk_pcnoc_msmbus_a_clk					 0x9753a54f
+#define clk_pcnoc_keepalive_a_clk				 0x9464f720
+#define clk_pcnoc_usb_clk					 0x57adc448
+#define clk_pcnoc_usb_a_clk					 0x11d6a74e
+#define clk_bimc_clk						 0x4b80bf00
+#define clk_bimc_a_clk						 0x4b25668a
+#define clk_bimc_msmbus_clk					 0xd212feea
+#define clk_bimc_msmbus_a_clk					 0x71d1a499
+#define clk_bimc_usb_clk					 0x9bd2b2bf
+#define clk_bimc_usb_a_clk					 0xea410834
+#define clk_qdss_clk						 0x1492202a
+#define clk_qdss_a_clk						 0xdd121669
+#define clk_qpic_clk						 0x3ce6f7bb
+#define clk_qpic_a_clk						 0xd70ccb7c
+#define clk_xo_clk_src						 0x23f5649f
+#define clk_xo_a_clk_src					 0x2fdd2c7c
+#define clk_xo_otg_clk						 0x79bca5cc
+#define clk_xo_lpm_clk						 0x2be48257
+#define clk_xo_pil_mss_clk					 0xe97a8354
+#define clk_bb_clk1						 0xf5304268
+#define clk_bb_clk1_pin						 0x6dd0a779
+
+/* SRCs */
+#define clk_apss_ahb_clk_src					 0x36f8495f
+#define clk_emac_0_125m_clk_src					 0x955db353
+#define clk_blsp1_qup1_i2c_apps_clk_src				 0x17f78f5e
+#define clk_blsp1_qup1_spi_apps_clk_src				 0xf534c4fa
+#define clk_blsp1_qup2_i2c_apps_clk_src				 0x8de71c79
+#define clk_blsp1_qup2_spi_apps_clk_src				 0x33cf809a
+#define clk_blsp1_qup3_i2c_apps_clk_src				 0xf161b902
+#define clk_blsp1_qup3_spi_apps_clk_src				 0x5e95683f
+#define clk_blsp1_qup4_i2c_apps_clk_src				 0xb2ecce68
+#define clk_blsp1_qup4_spi_apps_clk_src				 0xddb5bbdb
+#define clk_blsp1_qup5_i2c_apps_clk_src				 0x71ea7804
+#define clk_blsp1_qup5_spi_apps_clk_src				 0x9752f35f
+#define clk_blsp1_qup6_i2c_apps_clk_src				 0x28806803
+#define clk_blsp1_qup6_spi_apps_clk_src				 0x44a1edc4
+#define clk_blsp1_uart1_apps_clk_src				 0xf8146114
+#define clk_blsp1_uart2_apps_clk_src				 0xfc9c2f73
+#define clk_blsp1_uart3_apps_clk_src				 0x600497f2
+#define clk_blsp1_uart4_apps_clk_src				 0x56bff15c
+#define clk_blsp1_uart5_apps_clk_src				 0x218ef697
+#define clk_blsp1_uart6_apps_clk_src				 0x8fbdbe4c
+#define clk_crypto_clk_src					 0x37a21414
+#define clk_gp1_clk_src						 0xad85b97a
+#define clk_gp2_clk_src						 0xfb1f0065
+#define clk_gp3_clk_src						 0x63b693d6
+#define clk_pdm2_clk_src					 0x31e494fd
+#define clk_sdcc1_apps_clk_src					 0xd4975db2
+#define clk_sdcc2_apps_clk_src					 0xfc46c821
+#define clk_emac_0_sys_25m_clk_src				 0x92fe3614
+#define clk_emac_0_tx_clk_src					 0x0487ec76
+#define clk_usb_hs_system_clk_src				 0x28385546
+#define clk_usb_hsic_clk_src					 0x141b01df
+#define clk_usb_hsic_io_cal_clk_src				 0xc83584bd
+#define clk_usb_hsic_system_clk_src				 0x52ef7224
+
+/*Branch*/
+#define clk_gcc_apss_ahb_clk					 0x2b0d39ff
+#define clk_gcc_apss_axi_clk					 0x1d47f4ff
+#define clk_gcc_prng_ahb_clk					 0x397e7eaa
+#define clk_gcc_qdss_dap_clk					 0x7fa9aa73
+#define clk_gcc_apss_tcu_clk					 0xaf56a329
+#define clk_gcc_blsp1_ahb_clk					 0x8caa5b4f
+#define clk_gcc_blsp1_qup1_i2c_apps_clk				 0xc303fae9
+#define clk_gcc_blsp1_qup1_spi_apps_clk				 0x759a76b0
+#define clk_gcc_blsp1_qup2_i2c_apps_clk				 0x1076f220
+#define clk_gcc_blsp1_qup2_spi_apps_clk				 0x3e77d48f
+#define clk_gcc_blsp1_qup3_i2c_apps_clk				 0x9e25ac82
+#define clk_gcc_blsp1_qup3_spi_apps_clk				 0xfb978880
+#define clk_gcc_blsp1_qup4_i2c_apps_clk				 0xd7f40f6f
+#define clk_gcc_blsp1_qup4_spi_apps_clk				 0x80f8722f
+#define clk_gcc_blsp1_qup5_i2c_apps_clk				 0xacae5604
+#define clk_gcc_blsp1_qup5_spi_apps_clk				 0xbf3e15d7
+#define clk_gcc_blsp1_qup6_i2c_apps_clk				 0x5c6ad820
+#define clk_gcc_blsp1_qup6_spi_apps_clk				 0x780d9f85
+#define clk_gcc_blsp1_uart1_apps_clk				 0xc7c62f90
+#define clk_gcc_blsp1_uart2_apps_clk				 0xf8a61c96
+#define clk_gcc_blsp1_uart3_apps_clk				 0xc3298bd7
+#define clk_gcc_blsp1_uart4_apps_clk				 0x26be16c0
+#define clk_gcc_blsp1_uart5_apps_clk				 0x28a6bc74
+#define clk_gcc_blsp1_uart6_apps_clk				 0x28fd3466
+#define clk_gcc_boot_rom_ahb_clk				 0xde2adeb1
+#define clk_gcc_crypto_ahb_clk					 0x94de4919
+#define clk_gcc_crypto_axi_clk					 0xd4415c9b
+#define clk_gcc_crypto_clk					 0x00d390d2
+#define clk_gcc_gp1_clk						 0x057f7b69
+#define clk_gcc_gp2_clk						 0x9bf83ffd
+#define clk_gcc_gp3_clk						 0xec6539ee
+#define clk_gcc_mss_cfg_ahb_clk					 0x111cde81
+#define clk_gcc_mss_q6_bimc_axi_clk				 0x67544d62
+#define clk_gcc_pdm2_clk					 0x99d55711
+#define clk_gcc_pdm_ahb_clk					 0x365664f6
+#define clk_gcc_sdcc1_ahb_clk					 0x691e0caa
+#define clk_gcc_sdcc1_apps_clk					 0x9ad6fb96
+#define clk_gcc_sdcc2_ahb_clk					 0x23d5727f
+#define clk_gcc_sdcc2_apps_clk					 0x861b20ac
+#define clk_gcc_emac_0_125m_clk					 0xe556de53
+#define clk_gcc_emac_0_ahb_clk					 0x6a741d38
+#define clk_gcc_emac_0_axi_clk					 0xf2b04fb4
+#define clk_gcc_emac_0_rx_clk					 0x869a4e5c
+#define clk_gcc_emac_0_sys_25m_clk				 0x5812832b
+#define clk_gcc_emac_0_sys_clk					 0x34fb62b0
+#define clk_gcc_emac_0_tx_clk					 0x331d3573
+#define clk_gcc_smmu_cfg_clk					 0x75eaefa5
+#define clk_gcc_usb2a_phy_sleep_clk				 0x6caa736f
+#define clk_gcc_usb_hs_phy_cfg_ahb_clk				 0xe13808fd
+#define clk_gcc_usb_hs_ahb_clk					 0x72ce8032
+#define clk_gcc_usb_hs_system_clk				 0xa11972e5
+#define clk_gcc_usb_hsic_ahb_clk				 0x3ec2631a
+#define clk_gcc_usb_hsic_clk					 0x8de18b0e
+#define clk_gcc_usb_hsic_io_cal_clk				 0xbc21f776
+#define clk_gcc_usb_hsic_io_cal_sleep_clk			 0x20e09a22
+#define clk_gcc_usb_hsic_system_clk				 0x145e9366
+#define clk_gcc_usb2_hs_phy_only_clk				 0x0047179d
+#define clk_gcc_qusb2_phy_clk					 0x996884d5
+/* DEBUG */
+#define clk_gcc_debug_mux					 0x8121ac15
+#define clk_apss_debug_pri_mux					 0xc691ff55
+#define clk_apc0_m_clk						 0xce1e9473
+#define clk_apc1_m_clk						 0x990fbaf7
+#define clk_apc2_m_clk						 0x252cd4ae
+#define clk_apc3_m_clk						 0x78c64486
+#define clk_l2_m_clk						 0x4bedf4d0
+
+#define clk_wcnss_m_clk						 0x709f430b
+
+#endif
diff --git a/include/dt-bindings/clock/mdm-clocks-9650.h b/include/dt-bindings/clock/mdm-clocks-9650.h
new file mode 100644
index 0000000..d62a806
--- /dev/null
+++ b/include/dt-bindings/clock/mdm-clocks-9650.h
@@ -0,0 +1,160 @@
+/*
+ * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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_CLOCKS_9650_H
+#define __MSM_CLOCKS_9650_H
+
+/* RPM controlled clocks */
+#define clk_xo 0xf13dfee3
+#define clk_xo_a_clk 0xd939b99b
+#define clk_ce_clk 0xd8bc64e1
+#define clk_ce_a_clk 0x4dfefd47
+#define clk_pcnoc_clk 0xc1296d0f
+#define clk_pcnoc_a_clk 0x9bcffee4
+#define clk_bimc_clk 0x4b80bf00
+#define clk_bimc_a_clk 0x4b25668a
+#define clk_snoc_clk 0x2c341aa0
+#define clk_snoc_a_clk 0x8fcef2af
+#define clk_ipa_clk 0xfa685cda
+#define clk_ipa_a_clk 0xeeec2919
+#define clk_qpic_clk 0x3ce6f7bb
+#define clk_qpic_a_clk 0xd70ccb7c
+#define clk_qdss_clk 0x1492202a
+#define clk_qdss_a_clk 0xdd121669
+#define clk_bimc_msmbus_clk 0xd212feea
+#define clk_bimc_msmbus_a_clk 0x71d1a499
+#define clk_mcd_ce_clk 0x7ad13979
+#define clk_pcnoc_keepalive_a_clk 0x9464f720
+#define clk_pcnoc_msmbus_clk 0x2b53b688
+#define clk_pcnoc_msmbus_a_clk 0x9753a54f
+#define clk_pcnoc_pm_clk 0x5e636b5d
+#define clk_pcnoc_sps_clk 0x23d3f584
+#define clk_qcedev_ce_clk 0x2e7f9cee
+#define clk_qcrypto_ce_clk 0xd8cd060b
+#define clk_qseecom_ce_clk 0xea036e4b
+#define clk_scm_ce_clk 0xfd35bb87
+#define clk_snoc_msmbus_clk 0xe6900bb6
+#define clk_snoc_msmbus_a_clk 0x5d4683bd
+#define clk_cxo_dwc3_clk 0xf79c19f6
+#define clk_cxo_lpm_clk 0x94adbf3d
+#define clk_cxo_otg_clk 0x4eec0bb9
+#define clk_div_clk1 0xaa1157a6
+#define clk_div_clk1_ao 0x6b943d68
+#define clk_ln_bb_clk 0x3ab0b36d
+#define clk_ln_bb_a_clk 0xc7257ea8
+#define clk_rf_clk1 0xaabeea5a
+#define clk_rf_clk1_ao 0x72a10cb8
+#define clk_rf_clk1_pin 0x8f463562
+#define clk_rf_clk1_pin_ao 0x62549ff6
+#define clk_rf_clk2 0x24a30992
+#define clk_rf_clk2_ao 0x944d8bbd
+#define clk_rf_clk2_pin 0xa7c5602a
+#define clk_rf_clk2_pin_ao 0x2d75eb4d
+#define clk_rf_clk3 0xb673936b
+#define clk_rf_clk3_ao 0x038bb968
+#define clk_rf_clk3_pin 0x726f53f5
+#define clk_rf_clk3_pin_ao 0x76f9240f
+
+/* APSS controlled clocks */
+#define clk_gpll0 0x1ebe3bc4
+#define clk_gpll0_ao 0xa1368304
+#define clk_gpll0_out_msscc 0x7d794829
+#define clk_apss_ahb_clk_src 0x36f8495f
+#define clk_usb30_master_clk_src 0xc6262f89
+#define clk_blsp1_qup1_i2c_apps_clk_src 0x17f78f5e
+#define clk_blsp1_qup1_spi_apps_clk_src 0xf534c4fa
+#define clk_blsp1_qup2_i2c_apps_clk_src 0x8de71c79
+#define clk_blsp1_qup2_spi_apps_clk_src 0x33cf809a
+#define clk_blsp1_qup3_i2c_apps_clk_src 0xf161b902
+#define clk_blsp1_qup3_spi_apps_clk_src 0x5e95683f
+#define clk_blsp1_qup4_i2c_apps_clk_src 0xb2ecce68
+#define clk_blsp1_qup4_spi_apps_clk_src 0xddb5bbdb
+#define clk_blsp1_uart1_apps_clk_src 0xf8146114
+#define clk_blsp1_uart2_apps_clk_src 0xfc9c2f73
+#define clk_blsp1_uart3_apps_clk_src 0x600497f2
+#define clk_blsp1_uart4_apps_clk_src 0x56bff15c
+#define clk_gp1_clk_src 0xad85b97a
+#define clk_gp2_clk_src 0xfb1f0065
+#define clk_gp3_clk_src 0x63b693d6
+#define clk_pcie_aux_clk_src 0xebc50566
+#define clk_pdm2_clk_src 0x31e494fd
+#define clk_sdcc1_apps_clk_src 0xd4975db2
+#define clk_usb30_mock_utmi_clk_src 0xa024a976
+#define clk_usb3_aux_clk_src 0xfde7ae09
+#define clk_gcc_pcie_phy_reset 0x9bc3c959
+#define clk_gcc_qusb2a_phy_reset 0x2a9dfa9f
+#define clk_gcc_usb3phy_phy_reset 0xb1a4f885
+#define clk_gcc_usb3_phy_reset 0x03d559f1
+#define clk_gpll0_out_main_cgc 0xb0298998
+#define clk_gcc_blsp1_ahb_clk 0x8caa5b4f
+#define clk_gcc_blsp1_qup1_i2c_apps_clk 0xc303fae9
+#define clk_gcc_blsp1_qup1_spi_apps_clk 0x759a76b0
+#define clk_gcc_blsp1_qup2_i2c_apps_clk 0x1076f220
+#define clk_gcc_blsp1_qup2_spi_apps_clk 0x3e77d48f
+#define clk_gcc_blsp1_qup3_i2c_apps_clk 0x9e25ac82
+#define clk_gcc_blsp1_qup3_spi_apps_clk 0xfb978880
+#define clk_gcc_blsp1_qup4_i2c_apps_clk 0xd7f40f6f
+#define clk_gcc_blsp1_qup4_spi_apps_clk 0x80f8722f
+#define clk_gcc_blsp1_uart1_apps_clk 0xc7c62f90
+#define clk_gcc_blsp1_uart2_apps_clk 0xf8a61c96
+#define clk_gcc_blsp1_uart3_apps_clk 0xc3298bd7
+#define clk_gcc_blsp1_uart4_apps_clk 0x26be16c0
+#define clk_gcc_boot_rom_ahb_clk 0xde2adeb1
+#define clk_gcc_dcc_clk 0xd1000c50
+#define clk_gpll0_out_main_div2_cgc 0xc76ac7ae
+#define clk_gcc_gp1_clk 0x057f7b69
+#define clk_gcc_gp2_clk 0x9bf83ffd
+#define clk_gcc_gp3_clk 0xec6539ee
+#define clk_gcc_mss_q6_bimc_axi_clk 0x67544d62
+#define clk_gcc_pcie_axi_clk 0xb833d9e3
+#define clk_gcc_pcie_axi_mstr_clk 0x54d09178
+#define clk_gcc_pcie_cfg_ahb_clk 0xddc9a515
+#define clk_gcc_pcie_pipe_clk 0x8be62558
+#define clk_gcc_pcie_sleep_clk 0x8b8bfc3b
+#define clk_gcc_pdm2_clk 0x99d55711
+#define clk_gcc_pdm_ahb_clk 0x365664f6
+#define clk_gcc_prng_ahb_clk 0x397e7eaa
+#define clk_gcc_sdcc1_ahb_clk 0x691e0caa
+#define clk_gcc_sdcc1_apps_clk 0x9ad6fb96
+#define clk_gcc_apss_tcu_clk 0xaf56a329
+#define clk_gcc_pcie_axi_tbu_clk 0xab70f06e
+#define clk_gcc_pcie_ref_clk 0x63fca50a
+#define clk_gcc_usb_ss_ref_clk 0xb85dadfa
+#define clk_gcc_qusb_ref_clk 0x16e35a90
+#define clk_gcc_smmu_cfg_clk 0x75eaefa5
+#define clk_gcc_usb3_axi_tbu_clk 0x18779c6e
+#define clk_gcc_sys_noc_usb3_axi_clk 0x94d26800
+#define clk_gcc_usb30_master_clk 0xb3b4e2cb
+#define clk_gcc_usb30_mock_utmi_clk 0xa800b65a
+#define clk_gcc_usb30_sleep_clk 0xd0b65c92
+#define clk_gcc_usb3_aux_clk 0x555d16b2
+#define clk_gcc_usb3_pipe_clk 0x26f8a97a
+#define clk_gcc_usb_phy_cfg_ahb_clk 0xccb7e26f
+#define clk_gcc_mss_cfg_ahb_clk 0x111cde81
+
+/* a7pll */
+#define clk_a7pll_clk		0x3dd5dd94
+
+/* clock_debug controlled clocks */
+#define clk_gcc_debug_mux 0x8121ac15
+
+/* Audio External Clocks */
+#define clk_audio_lpass_mclk 0x575ec22b
+
+/* sdx20 */
+#define clk_gcc_pcie_aux_clk 0x06d8e933
+#define clk_pcie_aux_phy_clk_src 0x672e340c
+#define clk_pcie20_phy_aux_clk 0x613dfb19
+#define clk_pcie_aux_mux_clk 0x3e75325b
+
+#endif
diff --git a/include/dt-bindings/clock/mdm-clocks-hwio-9607.h b/include/dt-bindings/clock/mdm-clocks-hwio-9607.h
new file mode 100644
index 0000000..e8bb4e0
--- /dev/null
+++ b/include/dt-bindings/clock/mdm-clocks-hwio-9607.h
@@ -0,0 +1,227 @@
+/*
+ * Copyright (c) 2015-2016, The Linux Foundation. All rights reserved.
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 __MDM_CLOCKS_9607_HWIO_H
+#define __MDM_CLOCKS_9607_HWIO_H
+
+#define GPLL0_MODE				0x21000
+#define GPLL0_STATUS				0x21024
+#define GPLL1_MODE				0x20000
+#define GPLL1_STATUS				0x2001C
+#define GPLL2_MODE				0x25000
+#define GPLL2_STATUS				0x25024
+#define APCS_GPLL_ENA_VOTE			0x45000
+#define APCS_MODE				0x00018
+#define APSS_AHB_CMD_RCGR			0x46000
+#define PRNG_AHB_CBCR				0x13004
+#define EMAC_0_125M_CMD_RCGR			0x4E028
+#define BLSP1_QUP1_I2C_APPS_CMD_RCGR		 0x200C
+#define BLSP1_QUP1_SPI_APPS_CMD_RCGR		 0x2024
+#define BLSP1_QUP2_I2C_APPS_CMD_RCGR		 0x3000
+#define BLSP1_QUP2_SPI_APPS_CMD_RCGR		 0x3014
+#define BLSP1_QUP3_I2C_APPS_CMD_RCGR		 0x4000
+#define BLSP1_QUP3_SPI_APPS_CMD_RCGR		 0x4024
+#define BLSP1_QUP4_I2C_APPS_CMD_RCGR		 0x5000
+#define BLSP1_QUP4_SPI_APPS_CMD_RCGR		 0x5024
+#define BLSP1_QUP5_I2C_APPS_CMD_RCGR		 0x6000
+#define BLSP1_QUP5_SPI_APPS_CMD_RCGR		 0x6024
+#define BLSP1_QUP6_I2C_APPS_CMD_RCGR		 0x7000
+#define BLSP1_QUP6_SPI_APPS_CMD_RCGR		 0x7024
+#define BLSP1_UART1_APPS_CMD_RCGR		 0x2044
+#define BLSP1_UART2_APPS_CMD_RCGR		 0x3034
+#define BLSP1_UART3_APPS_CMD_RCGR		 0x4044
+#define BLSP1_UART4_APPS_CMD_RCGR		 0x5044
+#define BLSP1_UART5_APPS_CMD_RCGR		 0x6044
+#define BLSP1_UART6_APPS_CMD_RCGR		 0x7044
+#define CRYPTO_CMD_RCGR			0x16004
+#define GP1_CMD_RCGR				 0x8004
+#define GP2_CMD_RCGR				 0x9004
+#define GP3_CMD_RCGR				 0xA004
+#define PDM2_CMD_RCGR				0x44010
+#define QPIC_CMD_RCGR				0x3F004
+#define SDCC1_APPS_CMD_RCGR			0x42004
+#define SDCC2_APPS_CMD_RCGR			0x43004
+#define EMAC_0_SYS_25M_CMD_RCGR		0x4E03C
+#define EMAC_0_TX_CMD_RCGR			0x4E014
+#define USB_HS_SYSTEM_CMD_RCGR			0x41010
+#define USB_HSIC_CMD_RCGR			0x3D018
+#define USB_HSIC_IO_CAL_CMD_RCGR		0x3D030
+#define USB_HSIC_SYSTEM_CMD_RCGR		0x3D000
+#define BIMC_PCNOC_AXI_CBCR			0x31024
+#define BLSP1_AHB_CBCR				 0x1008
+#define APCS_CLOCK_BRANCH_ENA_VOTE		0x45004
+#define BLSP1_QUP1_I2C_APPS_CBCR		 0x2008
+#define BLSP1_QUP1_SPI_APPS_CBCR		 0x2004
+#define BLSP1_QUP2_I2C_APPS_CBCR		 0x3010
+#define BLSP1_QUP2_SPI_APPS_CBCR		 0x300C
+#define BLSP1_QUP3_I2C_APPS_CBCR		 0x4020
+#define BLSP1_QUP3_SPI_APPS_CBCR		 0x401C
+#define BLSP1_QUP4_I2C_APPS_CBCR		 0x5020
+#define BLSP1_QUP4_SPI_APPS_CBCR		 0x501C
+#define BLSP1_QUP5_I2C_APPS_CBCR		 0x6020
+#define BLSP1_QUP5_SPI_APPS_CBCR		 0x601C
+#define BLSP1_QUP6_I2C_APPS_CBCR		 0x7020
+#define BLSP1_QUP6_SPI_APPS_CBCR		 0x701C
+#define BLSP1_UART1_APPS_CBCR			 0x203C
+#define BLSP1_UART2_APPS_CBCR			 0x302C
+#define BLSP1_UART3_APPS_CBCR			 0x403C
+#define BLSP1_UART4_APPS_CBCR			 0x503C
+#define BLSP1_UART5_APPS_CBCR			 0x603C
+#define BLSP1_UART6_APPS_CBCR			 0x703C
+#define APSS_AHB_CBCR				0x4601C
+#define APSS_AXI_CBCR				0x46020
+#define BOOT_ROM_AHB_CBCR			0x1300C
+#define CRYPTO_AHB_CBCR			0x16024
+#define CRYPTO_AXI_CBCR			0x16020
+#define CRYPTO_CBCR				0x1601C
+#define GP1_CBCR				 0x8000
+#define GP2_CBCR				 0x9000
+#define GP3_CBCR				 0xA000
+#define MSS_CFG_AHB_CBCR			0x49000
+#define MSS_Q6_BIMC_AXI_CBCR			0x49004
+#define PCNOC_APSS_AHB_CBCR			0x27030
+#define PDM2_CBCR				0x4400C
+#define PDM_AHB_CBCR				0x44004
+#define QPIC_AHB_CBCR				0x3F01C
+#define QPIC_CBCR				0x3F018
+#define QPIC_SYSTEM_CBCR			0x3F020
+#define SDCC1_AHB_CBCR				0x4201C
+#define SDCC1_APPS_CBCR			0x42018
+#define SDCC2_AHB_CBCR				0x4301C
+#define SDCC2_APPS_CBCR			0x43018
+#define EMAC_0_125M_CBCR			0x4E010
+#define EMAC_0_AHB_CBCR			0x4E000
+#define EMAC_0_AXI_CBCR			0x4E008
+#define EMAC_0_RX_CBCR				0x4E030
+#define EMAC_0_SYS_25M_CBCR			0x4E038
+#define EMAC_0_SYS_CBCR				0x4E034
+#define EMAC_0_TX_CBCR				0x4E00C
+#define APSS_TCU_CBCR				0x12018
+#define SMMU_CFG_CBCR				0x12038
+#define QDSS_DAP_CBCR				0x29084
+#define APCS_SMMU_CLOCK_BRANCH_ENA_VOTE		0x4500C
+#define USB2A_PHY_SLEEP_CBCR			0x4102C
+#define USB_HS_PHY_CFG_AHB_CBCR			0x41030
+#define USB_HS_AHB_CBCR				0x41008
+#define USB_HS_SYSTEM_CBCR			0x41004
+#define USB_HS_BCR				0x41000
+#define USB_HSIC_AHB_CBCR			0x3D04C
+#define USB_HSIC_CBCR				0x3D050
+#define USB_HSIC_IO_CAL_CBCR			0x3D054
+#define USB_HSIC_IO_CAL_SLEEP_CBCR		0x3D058
+#define USB_HSIC_SYSTEM_CBCR			0x3D048
+#define USB_HS_HSIC_BCR				0x3D05C
+#define USB2_HS_PHY_ONLY_BCR			0x41034
+#define QUSB2_PHY_BCR				0x4103C
+#define GCC_DEBUG_CLK_CTL			0x74000
+#define CLOCK_FRQ_MEASURE_CTL			0x74004
+#define CLOCK_FRQ_MEASURE_STATUS		0x74008
+#define PLLTEST_PAD_CFG			0x7400C
+#define GCC_XO_DIV4_CBCR			0x30034
+
+#define xo_source_val				0
+#define xo_a_source_val			0
+#define gpll0_source_val			1
+#define gpll2_source_val			1
+#define emac_0_125m_clk_source_val		1
+#define emac_0_tx_clk_source_val		2
+
+#define F(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.src_clk = &s##_clk_src.c, \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_source_val), \
+	}
+
+#define F_EXT(f, s, div, m, n) \
+	{ \
+		.freq_hz = (f), \
+		.m_val = (m), \
+		.n_val = ~((n)-(m)) * !!(n), \
+		.d_val = ~(n),\
+		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
+			| BVAL(10, 8, s##_source_val), \
+		}
+
+#define VDD_DIG_FMAX_MAP1(l1, f1) \
+	.vdd_class = &vdd_dig, \
+	.fmax = (unsigned long[VDD_DIG_NUM]) {  \
+		[VDD_DIG_##l1] = (f1),          \
+	},                                      \
+	.num_fmax = VDD_DIG_NUM
+
+#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
+	.vdd_class = &vdd_dig, \
+	.fmax = (unsigned long[VDD_DIG_NUM]) {  \
+		[VDD_DIG_##l1] = (f1),          \
+		[VDD_DIG_##l2] = (f2),          \
+	},                                      \
+	.num_fmax = VDD_DIG_NUM
+
+#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
+	.vdd_class = &vdd_dig, \
+	.fmax = (unsigned long[VDD_DIG_NUM]) {  \
+		[VDD_DIG_##l1] = (f1),          \
+		[VDD_DIG_##l2] = (f2),          \
+		[VDD_DIG_##l3] = (f3),          \
+	},                                      \
+	.num_fmax = VDD_DIG_NUM
+
+enum vdd_dig_levels {
+	VDD_DIG_NONE,
+	VDD_DIG_LOWER,
+	VDD_DIG_LOW,
+	VDD_DIG_NOMINAL,
+	VDD_DIG_HIGH,
+	VDD_DIG_NUM
+};
+
+static int vdd_corner[] = {
+	RPM_REGULATOR_LEVEL_NONE,              /* VDD_DIG_NONE */
+	RPM_REGULATOR_LEVEL_SVS,		/* VDD_DIG_LOWER */
+	RPM_REGULATOR_LEVEL_SVS_PLUS,		/*VDD_DIG_LOW*/
+	RPM_REGULATOR_LEVEL_NOM,            /* VDD_DIG_NOMINAL */
+	RPM_REGULATOR_LEVEL_TURBO,		/* VDD_DIG_HIGH */
+};
+
+static DEFINE_VDD_REGULATORS(vdd_dig, VDD_DIG_NUM, 1, vdd_corner, NULL);
+
+
+#define VDD_STROMER_FMAX_MAP1(l1, f1) \
+	.vdd_class = &vdd_stromer_pll, \
+	.fmax = (unsigned long[VDD_DIG_NUM]) {  \
+		[VDD_DIG_##l1] = (f1),          \
+	},                                      \
+	.num_fmax = VDD_DIG_NUM
+
+
+#define RPM_MISC_CLK_TYPE			0x306b6c63
+#define RPM_BUS_CLK_TYPE			0x316b6c63
+#define RPM_MEM_CLK_TYPE			0x326b6c63
+#define RPM_SMD_KEY_ENABLE			0x62616E45
+#define RPM_QPIC_CLK_TYPE			0x63697071
+
+#define XO_ID					0x0
+#define QDSS_ID				0x1
+#define PCNOC_ID				0x0
+#define BIMC_ID				0x0
+#define QPIC_ID				0x0
+
+/* XO clock */
+#define BB_CLK1_ID				1
+#define RF_CLK2_ID				5
+
+#endif
diff --git a/include/dt-bindings/clock/msm-clocks-8952.h b/include/dt-bindings/clock/msm-clocks-8952.h
index e8afdba..4547751 100644
--- a/include/dt-bindings/clock/msm-clocks-8952.h
+++ b/include/dt-bindings/clock/msm-clocks-8952.h
@@ -339,6 +339,7 @@
 
 #define clk_audio_ap_clk			0x312ac429
 #define clk_audio_pmi_clk			0xb7ba2274
+#define clk_audio_ap_clk2			0xf0fbaf5b
 #define clk_audio_lpass_mclk			0x575ec22b
 
 /* GCC block resets */
diff --git a/include/dt-bindings/clock/msm-clocks-8953.h b/include/dt-bindings/clock/msm-clocks-8953.h
index 6bfca0b..9550a41 100644
--- a/include/dt-bindings/clock/msm-clocks-8953.h
+++ b/include/dt-bindings/clock/msm-clocks-8953.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2015-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -313,6 +313,12 @@
 #define clk_cpu_debug_pri_mux				 0x61a2945f
 #define clk_debug_cpu_clk                                0x0e696b2b
 
+#define clk_apcs_c0_pll					 0xfbc57bbd
+#define clk_apcs_c1_pll					 0x17d32f1e
+#define clk_apcs_cci_pll				 0x09affb3c
+#define clk_a53ssmux_cci				 0x15560bd5
+#define clk_a53_cci_clk					 0x4cdbbe58
+
 #define clk_audio_ap_clk				 0x312ac429
 #define clk_audio_pmi_clk				 0xb7ba2274
 #define clk_audio_ap_clk2				 0xf0fbaf5b
diff --git a/include/dt-bindings/clock/qcom,cpucc-sdm845.h b/include/dt-bindings/clock/qcom,cpucc-sdm845.h
index f039284..bbfb849 100644
--- a/include/dt-bindings/clock/qcom,cpucc-sdm845.h
+++ b/include/dt-bindings/clock/qcom,cpucc-sdm845.h
@@ -30,5 +30,6 @@
 #define L3_MISC_VOTE_CLK					13
 #define CPU4_PWRCL_CLK						14
 #define CPU5_PWRCL_CLK						15
+#define L3_GPU_VOTE_CLK						16
 
 #endif
diff --git a/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
index 36d34b1..1018b0e 100644
--- a/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
+++ b/include/dt-bindings/clock/qcom,gcc-sdxpoorwills.h
@@ -126,4 +126,7 @@
 #define GCC_USB_PHY_CFG_AHB2PHY_BCR				18
 #define GCC_EMAC_BCR						19
 
+/* Dummy clocks for rate measurement */
+#define MEASURE_ONLY_IPA_2X_CLK					0
+
 #endif
diff --git a/include/linux/backing-dev-defs.h b/include/linux/backing-dev-defs.h
index c357f27..0691068 100644
--- a/include/linux/backing-dev-defs.h
+++ b/include/linux/backing-dev-defs.h
@@ -10,6 +10,7 @@
 #include <linux/flex_proportions.h>
 #include <linux/timer.h>
 #include <linux/workqueue.h>
+#include <linux/kref.h>
 
 struct page;
 struct device;
@@ -20,6 +21,7 @@
  */
 enum wb_state {
 	WB_registered,		/* bdi_register() was done */
+	WB_shutting_down,	/* wb_shutdown() in progress */
 	WB_writeback_running,	/* Writeback is in progress */
 	WB_has_dirty_io,	/* Dirty inodes on ->b_{dirty|io|more_io} */
 };
@@ -53,7 +55,9 @@
 	atomic_t refcnt;		/* nr of attached wb's and blkg */
 
 #ifdef CONFIG_CGROUP_WRITEBACK
-	struct backing_dev_info *bdi;	/* the associated bdi */
+	struct backing_dev_info *__bdi;	/* the associated bdi, set to NULL
+					 * on bdi unregistration. For memcg-wb
+					 * internal use only! */
 	int blkcg_id;			/* ID of the associated blkcg */
 	struct rb_node rb_node;		/* on bdi->cgwb_congestion_tree */
 #endif
@@ -142,6 +146,7 @@
 
 	char *name;
 
+	struct kref refcnt;	/* Reference counter for the structure */
 	unsigned int min_ratio;
 	unsigned int max_ratio, max_prop_frac;
 
@@ -156,7 +161,6 @@
 #ifdef CONFIG_CGROUP_WRITEBACK
 	struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
 	struct rb_root cgwb_congested_tree; /* their congested states */
-	atomic_t usage_cnt; /* counts both cgwbs and cgwb_contested's */
 #else
 	struct bdi_writeback_congested *wb_congested;
 #endif
diff --git a/include/linux/backing-dev.h b/include/linux/backing-dev.h
index 43b93a9..c52a48c 100644
--- a/include/linux/backing-dev.h
+++ b/include/linux/backing-dev.h
@@ -18,7 +18,14 @@
 #include <linux/slab.h>
 
 int __must_check bdi_init(struct backing_dev_info *bdi);
-void bdi_exit(struct backing_dev_info *bdi);
+
+static inline struct backing_dev_info *bdi_get(struct backing_dev_info *bdi)
+{
+	kref_get(&bdi->refcnt);
+	return bdi;
+}
+
+void bdi_put(struct backing_dev_info *bdi);
 
 __printf(3, 4)
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
@@ -29,6 +36,7 @@
 
 int __must_check bdi_setup_and_register(struct backing_dev_info *, char *);
 void bdi_destroy(struct backing_dev_info *bdi);
+struct backing_dev_info *bdi_alloc_node(gfp_t gfp_mask, int node_id);
 
 void wb_start_writeback(struct bdi_writeback *wb, long nr_pages,
 			bool range_cyclic, enum wb_reason reason);
@@ -183,7 +191,7 @@
 	sb = inode->i_sb;
 #ifdef CONFIG_BLOCK
 	if (sb_is_blkdev_sb(sb))
-		return blk_get_backing_dev_info(I_BDEV(inode));
+		return I_BDEV(inode)->bd_bdi;
 #endif
 	return sb->s_bdi;
 }
diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h
index 0693c3e..46cd13d 100644
--- a/include/linux/blkdev.h
+++ b/include/linux/blkdev.h
@@ -345,7 +345,7 @@
 	 */
 	struct delayed_work	delay_work;
 
-	struct backing_dev_info	backing_dev_info;
+	struct backing_dev_info	*backing_dev_info;
 
 	/*
 	 * The queue owner gets to use this for whatever they like.
@@ -1031,7 +1031,6 @@
 extern void blk_queue_rq_timeout(struct request_queue *, unsigned int);
 extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable);
 extern void blk_queue_write_cache(struct request_queue *q, bool enabled, bool fua);
-extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
 
 extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
 extern int blk_rq_map_sg_no_cluster(struct request_queue *q, struct request *rq,
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 4f6ec47..7fb621f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -475,6 +475,7 @@
 	int			bd_invalidated;
 	struct gendisk *	bd_disk;
 	struct request_queue *  bd_queue;
+	struct backing_dev_info *bd_bdi;
 	struct list_head	bd_list;
 	/*
 	 * Private data.  You must have bd_claim'ed the block_device
@@ -2398,6 +2399,7 @@
 #ifdef CONFIG_BLOCK
 extern int register_blkdev(unsigned int, const char *);
 extern void unregister_blkdev(unsigned int, const char *);
+extern void bdev_unhash_inode(dev_t dev);
 extern struct block_device *bdget(dev_t);
 extern struct block_device *bdgrab(struct block_device *bdev);
 extern void bd_set_size(struct block_device *, loff_t size);
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 3562047..bbc65ef 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -14,7 +14,6 @@
 #include <linux/hrtimer.h>
 #include <linux/kref.h>
 #include <linux/workqueue.h>
-#include <linux/sched.h>
 
 #include <linux/atomic.h>
 #include <asm/ptrace.h>
@@ -499,13 +498,6 @@
 	return this_cpu_read(ksoftirqd);
 }
 
-static inline bool ksoftirqd_running_on(int cpu)
-{
-	struct task_struct *tsk = per_cpu(ksoftirqd, cpu);
-
-	return tsk && (tsk->state == TASK_RUNNING);
-}
-
 /* Tasklets --- multithreaded analogue of BHs.
 
    Main feature differing them of generic softirqs: tasklet
diff --git a/include/linux/ipa_wdi3.h b/include/linux/ipa_wdi3.h
index aed8c59..6f00711 100644
--- a/include/linux/ipa_wdi3.h
+++ b/include/linux/ipa_wdi3.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -24,15 +24,49 @@
 	(IPA_HW_WDI3_TCL_DATA_CMD_ER_DESC_SIZE) : \
 	(IPA_HW_WDI3_IPA2FW_ER_DESC_SIZE))
 
+#define IPA_WDI_MAX_SUPPORTED_SYS_PIPE 3
+
+enum ipa_wdi_version {
+	IPA_WDI_1,
+	IPA_WDI_2,
+	IPA_WDI_3
+};
+
 /**
- * struct ipa_wdi3_hdr_info - Header to install on IPA HW
+ * struct ipa_wdi_init_in_params - wdi init input parameters
+ *
+ * @wdi_version: wdi version
+ * @notify: uc ready callback
+ * @priv: uc ready callback cookie
+ */
+struct ipa_wdi_init_in_params {
+	enum ipa_wdi_version wdi_version;
+	ipa_uc_ready_cb notify;
+	void *priv;
+	ipa_wdi_meter_notifier_cb wdi_notify;
+};
+
+/**
+ * struct ipa_wdi_init_out_params - wdi init output parameters
+ *
+ * @is_uC_ready: is uC ready. No API should be called until uC
+    is ready.
+ * @is_smmu_enable: is smmu enabled
+ */
+struct ipa_wdi_init_out_params {
+	bool is_uC_ready;
+	bool is_smmu_enabled;
+};
+
+/**
+ * struct ipa_wdi_hdr_info - Header to install on IPA HW
  *
  * @hdr: header to install on IPA HW
  * @hdr_len: length of header
  * @dst_mac_addr_offset: destination mac address offset
  * @hdr_type: layer two header type
  */
-struct ipa_wdi3_hdr_info {
+struct ipa_wdi_hdr_info {
 	u8 *hdr;
 	u8 hdr_len;
 	u8 dst_mac_addr_offset;
@@ -40,7 +74,7 @@
 };
 
 /**
- * struct ipa_wdi3_reg_intf_in_params - parameters for uC offload
+ * struct ipa_wdi_reg_intf_in_params - parameters for uC offload
  *	interface registration
  *
  * @netdev_name: network interface name
@@ -49,16 +83,17 @@
  * @meta_data: meta data if any
  * @meta_data_mask: meta data mask
  */
-struct ipa_wdi3_reg_intf_in_params {
+struct ipa_wdi_reg_intf_in_params {
 	const char *netdev_name;
-	struct ipa_wdi3_hdr_info hdr_info[IPA_IP_MAX];
+	struct ipa_wdi_hdr_info hdr_info[IPA_IP_MAX];
+	enum ipa_client_type alt_dst_pipe;
 	u8 is_meta_data_valid;
 	u32 meta_data;
 	u32 meta_data_mask;
 };
 
 /**
- * struct  ipa_wdi3_setup_info - WDI3 TX/Rx configuration
+ * struct  ipa_wdi_pipe_setup_info - WDI TX/Rx configuration
  * @ipa_ep_cfg: ipa endpoint configuration
  * @client: type of "client"
  * @transfer_ring_base_pa:  physical address of the base of the transfer ring
@@ -71,20 +106,20 @@
 	will update the headpointer of the event ring
  * @num_pkt_buffers:  Number of pkt buffers allocated. The size of the event
 	ring and the transfer ring has to be atleast ( num_pkt_buffers + 1)
- * @pkt_offset: packet offset (wdi3 header length)
+ * @pkt_offset: packet offset (wdi header length)
  * @desc_format_template[IPA_HW_WDI3_MAX_ER_DESC_SIZE]:  Holds a cached
 	template of the desc format
  */
-struct ipa_wdi3_setup_info {
+struct ipa_wdi_pipe_setup_info {
 	struct ipa_ep_cfg ipa_ep_cfg;
 	enum ipa_client_type client;
-	dma_addr_t  transfer_ring_base_pa;
+	phys_addr_t  transfer_ring_base_pa;
 	u32  transfer_ring_size;
-	dma_addr_t  transfer_ring_doorbell_pa;
+	phys_addr_t  transfer_ring_doorbell_pa;
 
-	dma_addr_t  event_ring_base_pa;
+	phys_addr_t  event_ring_base_pa;
 	u32  event_ring_size;
-	dma_addr_t  event_ring_doorbell_pa;
+	phys_addr_t  event_ring_doorbell_pa;
 	u16  num_pkt_buffers;
 
 	u16 pkt_offset;
@@ -93,40 +128,87 @@
 };
 
 /**
- * struct  ipa_wdi3_conn_in_params - information provided by
+ * struct  ipa_wdi_pipe_setup_info_smmu - WDI TX/Rx configuration
+ * @ipa_ep_cfg: ipa endpoint configuration
+ * @client: type of "client"
+ * @transfer_ring_base_pa:  physical address of the base of the transfer ring
+ * @transfer_ring_size:  size of the transfer ring
+ * @transfer_ring_doorbell_pa:  physical address of the doorbell that
+	IPA uC will update the tailpointer of the transfer ring
+ * @event_ring_base_pa:  physical address of the base of the event ring
+ * @event_ring_size:  event ring size
+ * @event_ring_doorbell_pa:  physical address of the doorbell that IPA uC
+	will update the headpointer of the event ring
+ * @num_pkt_buffers:  Number of pkt buffers allocated. The size of the event
+	ring and the transfer ring has to be atleast ( num_pkt_buffers + 1)
+ * @pkt_offset: packet offset (wdi header length)
+ * @desc_format_template[IPA_HW_WDI3_MAX_ER_DESC_SIZE]:  Holds a cached
+	template of the desc format
+ */
+struct ipa_wdi_pipe_setup_info_smmu {
+	struct ipa_ep_cfg ipa_ep_cfg;
+	enum ipa_client_type client;
+	struct sg_table  transfer_ring_base;
+	u32  transfer_ring_size;
+	phys_addr_t  transfer_ring_doorbell_pa;
+
+	struct sg_table  event_ring_base;
+	u32  event_ring_size;
+	phys_addr_t  event_ring_doorbell_pa;
+	u16  num_pkt_buffers;
+
+	u16 pkt_offset;
+
+	u32  desc_format_template[IPA_HW_WDI3_MAX_ER_DESC_SIZE];
+};
+
+/**
+ * struct  ipa_wdi_conn_in_params - information provided by
  *		uC offload client
  * @notify: client callback function
  * @priv: client cookie
+ * @is_smmu_enabled: if smmu is enabled
+ * @num_sys_pipe_needed: number of sys pipe needed
+ * @sys_in: parameters to setup sys pipe in mcc mode
  * @tx: parameters to connect TX pipe(from IPA to WLAN)
+ * @tx_smmu: smmu parameters to connect TX pipe(from IPA to WLAN)
  * @rx: parameters to connect RX pipe(from WLAN to IPA)
+ * @rx_smmu: smmu parameters to connect RX pipe(from WLAN to IPA)
  */
-struct ipa_wdi3_conn_in_params {
+struct ipa_wdi_conn_in_params {
 	ipa_notify_cb notify;
 	void *priv;
-	struct ipa_wdi3_setup_info tx;
-	struct ipa_wdi3_setup_info rx;
+	bool is_smmu_enabled;
+	u8 num_sys_pipe_needed;
+	struct ipa_sys_connect_params sys_in[IPA_WDI_MAX_SUPPORTED_SYS_PIPE];
+	union {
+		struct ipa_wdi_pipe_setup_info tx;
+		struct ipa_wdi_pipe_setup_info_smmu tx_smmu;
+	} u_tx;
+	union {
+		struct ipa_wdi_pipe_setup_info rx;
+		struct ipa_wdi_pipe_setup_info_smmu rx_smmu;
+	} u_rx;
 };
 
 /**
- * struct  ipa_wdi3_conn_out_params - information provided
+ * struct  ipa_wdi_conn_out_params - information provided
  *				to WLAN driver
  * @tx_uc_db_pa: physical address of IPA uC doorbell for TX
- * @tx_uc_db_va: virtual address of IPA uC doorbell for TX
  * @rx_uc_db_pa: physical address of IPA uC doorbell for RX
  */
-struct ipa_wdi3_conn_out_params {
-	dma_addr_t tx_uc_db_pa;
-	void __iomem *tx_uc_db_va;
-	dma_addr_t rx_uc_db_pa;
+struct ipa_wdi_conn_out_params {
+	phys_addr_t tx_uc_db_pa;
+	phys_addr_t rx_uc_db_pa;
 };
 
 /**
- * struct  ipa_wdi3_perf_profile - To set BandWidth profile
+ * struct  ipa_wdi_perf_profile - To set BandWidth profile
  *
  * @client: type of client
  * @max_supported_bw_mbps: maximum bandwidth needed (in Mbps)
  */
-struct ipa_wdi3_perf_profile {
+struct ipa_wdi_perf_profile {
 	enum ipa_client_type client;
 	u32 max_supported_bw_mbps;
 };
@@ -134,117 +216,193 @@
 #if defined CONFIG_IPA || defined CONFIG_IPA3
 
 /**
- * ipa_wdi3_reg_intf - Client should call this function to
- * init WDI3 IPA offload data path
+ * ipa_wdi_init - Client should call this function to
+ * init WDI IPA offload data path
  *
  * Note: Should not be called from atomic context and only
  * after checking IPA readiness using ipa_register_ipa_ready_cb()
  *
  * @Return 0 on success, negative on failure
  */
-int ipa_wdi3_reg_intf(
-	struct ipa_wdi3_reg_intf_in_params *in);
+int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
+	struct ipa_wdi_init_out_params *out);
 
 /**
- * ipa_wdi3_dereg_intf - Client Driver should call this
+ * ipa_wdi_cleanup - Client should call this function to
+ * clean up WDI IPA offload data path
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_wdi_cleanup(void);
+
+/**
+ * ipa_wdi_reg_intf - Client should call this function to
+ * register interface
+ *
+ * Note: Should not be called from atomic context
+ *
+ * @Return 0 on success, negative on failure
+ */
+int ipa_wdi_reg_intf(
+	struct ipa_wdi_reg_intf_in_params *in);
+
+/**
+ * ipa_wdi_dereg_intf - Client Driver should call this
  * function to deregister before unload and after disconnect
  *
  * @Return 0 on success, negative on failure
  */
-int ipa_wdi3_dereg_intf(const char *netdev_name);
+int ipa_wdi_dereg_intf(const char *netdev_name);
 
 /**
- * ipa_wdi3_conn_pipes - Client should call this
+ * ipa_wdi_conn_pipes - Client should call this
  * function to connect pipes
  *
  * @in:	[in] input parameters from client
  * @out: [out] output params to client
  *
- * Note: Should not be called from atomic context and only
- * after checking IPA readiness using ipa_register_ipa_ready_cb()
+ * Note: Should not be called from atomic context
  *
  * @Return 0 on success, negative on failure
  */
-int ipa_wdi3_conn_pipes(struct ipa_wdi3_conn_in_params *in,
-			struct ipa_wdi3_conn_out_params *out);
+int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out);
 
 /**
- * ipa_wdi3_disconn_pipes() - Client should call this
+ * ipa_wdi_disconn_pipes() - Client should call this
  *		function to disconnect pipes
  *
  * Note: Should not be called from atomic context
  *
  * Returns: 0 on success, negative on failure
  */
-int ipa_wdi3_disconn_pipes(void);
+int ipa_wdi_disconn_pipes(void);
 
 /**
- * ipa_wdi3_enable_pipes() - Client should call this
+ * ipa_wdi_enable_pipes() - Client should call this
  *		function to enable IPA offload data path
  *
  * Note: Should not be called from atomic context
  *
  * Returns: 0 on success, negative on failure
  */
-int ipa_wdi3_enable_pipes(void);
+int ipa_wdi_enable_pipes(void);
 
 /**
- * ipa_wdi3_disable_pipes() - Client should call this
+ * ipa_wdi_disable_pipes() - Client should call this
  *		function to disable IPA offload data path
  *
  * Note: Should not be called from atomic context
  *
  * Returns: 0 on success, negative on failure
  */
-int ipa_wdi3_disable_pipes(void);
+int ipa_wdi_disable_pipes(void);
 
 /**
- * ipa_wdi3_set_perf_profile() - Client should call this function to
+ * ipa_wdi_set_perf_profile() - Client should call this function to
  *		set IPA clock bandwidth based on data rates
  *
  * @profile: [in] BandWidth profile to use
  *
  * Returns: 0 on success, negative on failure
  */
-int ipa_wdi3_set_perf_profile(struct ipa_wdi3_perf_profile *profile);
+int ipa_wdi_set_perf_profile(struct ipa_wdi_perf_profile *profile);
 
+/**
+ * ipa_wdi_create_smmu_mapping() - Create smmu mapping
+ *
+ * @num_buffers: number of buffers
+ *
+ * @info: wdi buffer info
+ */
+int ipa_wdi_create_smmu_mapping(u32 num_buffers,
+	struct ipa_wdi_buffer_info *info);
+
+/**
+ * ipa_wdi_release_smmu_mapping() - Release smmu mapping
+ *
+ * @num_buffers: number of buffers
+ *
+ * @info: wdi buffer info
+ */
+int ipa_wdi_release_smmu_mapping(u32 num_buffers,
+	struct ipa_wdi_buffer_info *info);
+
+/**
+ * ipa_wdi_get_stats() - Query WDI statistics
+ * @stats:	[inout] stats blob from client populated by driver
+ *
+ * Returns:	0 on success, negative on failure
+ *
+ * @note Cannot be called from atomic context
+ *
+ */
+int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats);
 
 #else /* (CONFIG_IPA || CONFIG_IPA3) */
 
-static inline int ipa_wdi3_reg_intf(
-	struct ipa_wdi3_reg_intf_in_params *in)
+static inline int ipa_wdi_init(struct ipa_wdi_init_in_params *in,
+	struct ipa_wdi_init_out_params *out)
 {
 	return -EPERM;
 }
 
-static inline int ipa_wdi3_dereg_intf(const char *netdev_name)
+static inline int ipa_wdi_cleanup(void)
 {
 	return -EPERM;
 }
 
-static inline int ipa_wdi3_conn_pipes(struct ipa_wdi3_conn_in_params *in,
-			struct ipa_wdi3_conn_out_params *out)
+static inline int ipa_wdi_reg_intf(
+	struct ipa_wdi_reg_intf_in_params *in)
 {
 	return -EPERM;
 }
 
-static inline int ipa_wdi3_disconn_pipes(void)
+static inline int ipa_wdi_dereg_intf(const char *netdev_name)
 {
 	return -EPERM;
 }
 
-static inline int ipa_wdi3_enable_pipes(void)
+static inline int ipa_wdi_conn_pipes(struct ipa_wdi_conn_in_params *in,
+	struct ipa_wdi_conn_out_params *out)
 {
 	return -EPERM;
 }
 
-static inline int ipa_wdi3_disable_pipes(void)
+static inline int ipa_wdi_disconn_pipes(void)
 {
 	return -EPERM;
 }
 
-static inline int ipa_wdi3_set_perf_profile(
-	struct ipa_wdi3_perf_profile *profile)
+static inline int ipa_wdi_enable_pipes(void)
+{
+	return -EPERM;
+}
+
+static inline int ipa_wdi_disable_pipes(void)
+{
+	return -EPERM;
+}
+
+static inline int ipa_wdi_set_perf_profile(
+	struct ipa_wdi_perf_profile *profile)
+{
+	return -EPERM;
+}
+
+static inline int ipa_wdi_create_smmu_mapping(u32 num_buffers,
+	struct ipa_wdi_buffer_info *info)
+{
+	return -EPERM;
+}
+
+static inline int ipa_wdi_release_smmu_mapping(u32 num_buffers,
+	struct ipa_wdi_buffer_info *info)
+{
+	return -EPERM;
+}
+
+static inline int ipa_wdi_get_stats(struct IpaHwStatsWDIInfoData_t *stats)
 {
 	return -EPERM;
 }
diff --git a/include/linux/kobject.h b/include/linux/kobject.h
index 74de8b6..5c8b65a 100644
--- a/include/linux/kobject.h
+++ b/include/linux/kobject.h
@@ -108,6 +108,8 @@
 extern int __must_check kobject_move(struct kobject *, struct kobject *);
 
 extern struct kobject *kobject_get(struct kobject *kobj);
+extern struct kobject * __must_check kobject_get_unless_zero(
+						struct kobject *kobj);
 extern void kobject_put(struct kobject *kobj);
 
 extern const void *kobject_namespace(struct kobject *kobj);
diff --git a/include/linux/mtd/map.h b/include/linux/mtd/map.h
index 3aa56e3..b5b43f9 100644
--- a/include/linux/mtd/map.h
+++ b/include/linux/mtd/map.h
@@ -270,75 +270,67 @@
 #define INVALIDATE_CACHED_RANGE(map, from, size) \
 	do { if (map->inval_cache) map->inval_cache(map, from, size); } while (0)
 
+#define map_word_equal(map, val1, val2)					\
+({									\
+	int i, ret = 1;							\
+	for (i = 0; i < map_words(map); i++)				\
+		if ((val1).x[i] != (val2).x[i]) {			\
+			ret = 0;					\
+			break;						\
+		}							\
+	ret;								\
+})
 
-static inline int map_word_equal(struct map_info *map, map_word val1, map_word val2)
-{
-	int i;
+#define map_word_and(map, val1, val2)					\
+({									\
+	map_word r;							\
+	int i;								\
+	for (i = 0; i < map_words(map); i++)				\
+		r.x[i] = (val1).x[i] & (val2).x[i];			\
+	r;								\
+})
 
-	for (i = 0; i < map_words(map); i++) {
-		if (val1.x[i] != val2.x[i])
-			return 0;
-	}
+#define map_word_clr(map, val1, val2)					\
+({									\
+	map_word r;							\
+	int i;								\
+	for (i = 0; i < map_words(map); i++)				\
+		r.x[i] = (val1).x[i] & ~(val2).x[i];			\
+	r;								\
+})
 
-	return 1;
-}
+#define map_word_or(map, val1, val2)					\
+({									\
+	map_word r;							\
+	int i;								\
+	for (i = 0; i < map_words(map); i++)				\
+		r.x[i] = (val1).x[i] | (val2).x[i];			\
+	r;								\
+})
 
-static inline map_word map_word_and(struct map_info *map, map_word val1, map_word val2)
-{
-	map_word r;
-	int i;
+#define map_word_andequal(map, val1, val2, val3)			\
+({									\
+	int i, ret = 1;							\
+	for (i = 0; i < map_words(map); i++) {				\
+		if (((val1).x[i] & (val2).x[i]) != (val2).x[i]) {	\
+			ret = 0;					\
+			break;						\
+		}							\
+	}								\
+	ret;								\
+})
 
-	for (i = 0; i < map_words(map); i++)
-		r.x[i] = val1.x[i] & val2.x[i];
-
-	return r;
-}
-
-static inline map_word map_word_clr(struct map_info *map, map_word val1, map_word val2)
-{
-	map_word r;
-	int i;
-
-	for (i = 0; i < map_words(map); i++)
-		r.x[i] = val1.x[i] & ~val2.x[i];
-
-	return r;
-}
-
-static inline map_word map_word_or(struct map_info *map, map_word val1, map_word val2)
-{
-	map_word r;
-	int i;
-
-	for (i = 0; i < map_words(map); i++)
-		r.x[i] = val1.x[i] | val2.x[i];
-
-	return r;
-}
-
-static inline int map_word_andequal(struct map_info *map, map_word val1, map_word val2, map_word val3)
-{
-	int i;
-
-	for (i = 0; i < map_words(map); i++) {
-		if ((val1.x[i] & val2.x[i]) != val3.x[i])
-			return 0;
-	}
-
-	return 1;
-}
-
-static inline int map_word_bitsset(struct map_info *map, map_word val1, map_word val2)
-{
-	int i;
-
-	for (i = 0; i < map_words(map); i++) {
-		if (val1.x[i] & val2.x[i])
-			return 1;
-	}
-
-	return 0;
-}
+#define map_word_bitsset(map, val1, val2)				\
+({									\
+	int i, ret = 0;							\
+	for (i = 0; i < map_words(map); i++) {				\
+		if ((val1).x[i] & (val2).x[i]) {			\
+			ret = 1;					\
+			break;						\
+		}							\
+	}								\
+	ret;								\
+})
 
 static inline map_word map_word_load(struct map_info *map, const void *ptr)
 {
diff --git a/include/linux/qpnp/qpnp-adc.h b/include/linux/qpnp/qpnp-adc.h
index a2a0152..71764767 100644
--- a/include/linux/qpnp/qpnp-adc.h
+++ b/include/linux/qpnp/qpnp-adc.h
@@ -390,6 +390,7 @@
  * %SCALE_USBIN_I: Conversion for USB input current.
  * %SCALE_BATT_THERM_TEMP_QRD: Conversion to temperature(decidegC) based on btm
  *			parameters for QRD.
+ * %SCALE_SMB1390_DIE_TEMP: Conversion for SMB1390 die temp
  * %SCALE_NONE: Do not use this scaling type.
  */
 enum qpnp_adc_scale_fn_type {
@@ -413,6 +414,7 @@
 	SCALE_I_DEFAULT,
 	SCALE_USBIN_I,
 	SCALE_BATT_THERM_TEMP_QRD,
+	SCALE_SMB1390_DIE_TEMP,
 	SCALE_NONE,
 };
 
@@ -1712,6 +1714,25 @@
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt);
 /**
+ * qpnp_adc_scale_die_temp_1390() -  Scales the pre-calibrated digital output
+ *		of an ADC to the ADC reference and compensates for the
+ *		gain and offset. The voltage measured by HKADC is related to
+ *		the junction temperature according to
+ *		V_adc = 1.496 – 0.00381*Tj
+ * @dev:	Structure device for qpnp vadc
+ * @adc_code:	pre-calibrated digital output of the ADC.
+ * @adc_prop:	adc properties of the pm8xxx adc such as bit resolution,
+ *		reference voltage.
+ * @chan_prop:	individual channel properties to compensate the i/p scaling,
+ *		slope and offset.
+ * @chan_rslt:	physical result to be stored.
+ */
+int32_t qpnp_adc_scale_die_temp_1390(struct qpnp_vadc_chip *dev,
+			int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt);
+/**
  * qpnp_get_vadc() - Clients need to register with the vadc using the
  *		corresponding device instance it wants to read the channels
  *		from. Read the bindings document on how to pass the phandle
@@ -2149,6 +2170,12 @@
 			const struct qpnp_vadc_chan_properties *chan_prop,
 			struct qpnp_vadc_result *chan_rslt)
 { return -ENXIO; }
+static inline int32_t qpnp_adc_scale_die_temp_1390(struct qpnp_vadc_chip *vadc,
+			int32_t adc_code,
+			const struct qpnp_adc_properties *adc_prop,
+			const struct qpnp_vadc_chan_properties *chan_prop,
+			struct qpnp_vadc_result *chan_rslt)
+{ return -ENXIO; }
 static inline struct qpnp_vadc_chip *qpnp_get_vadc(struct device *dev,
 							const char *name)
 { return ERR_PTR(-ENXIO); }
diff --git a/include/linux/qpnp/qpnp-revid.h b/include/linux/qpnp/qpnp-revid.h
index 8933742..c1206c6 100644
--- a/include/linux/qpnp/qpnp-revid.h
+++ b/include/linux/qpnp/qpnp-revid.h
@@ -162,6 +162,9 @@
 
 #define PM8950_V2P0_REV4	0x02
 
+/* PM8953 */
+#define PM8953_SUBTYPE		0x16
+
 /* PMI8950 */
 #define PMI8950_SUBTYPE		0x11
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 290e2b2..8933c9f 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2754,11 +2754,6 @@
 	return 0;
 }
 
-static inline void
-sched_set_cpu_cstate(int cpu, int cstate, int wakeup_energy, int wakeup_latency)
-{
-}
-
 #ifdef CONFIG_SCHED_WALT
 extern int register_cpu_cycle_counter_cb(struct cpu_cycle_counter_cb *cb);
 extern void sched_set_io_is_busy(int val);
diff --git a/include/linux/slimbus/slimbus.h b/include/linux/slimbus/slimbus.h
index 53af941..4b5dc54 100644
--- a/include/linux/slimbus/slimbus.h
+++ b/include/linux/slimbus/slimbus.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2011-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2011-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -601,7 +601,7 @@
 	int			(*framer_handover)(struct slim_controller *ctrl,
 				struct slim_framer *new_framer);
 	int			(*port_xfer)(struct slim_controller *ctrl,
-				u8 pn, phys_addr_t iobuf, u32 len,
+				u8 pn, void *buf, u32 len,
 				struct completion *comp);
 	enum slim_port_err	(*port_xfer_status)(struct slim_controller *ctr,
 				u8 pn, phys_addr_t *done_buf, u32 *done_len);
@@ -869,7 +869,7 @@
  * Client will call slim_port_get_xfer_status to get error and/or number of
  * bytes transferred if used asynchronously.
  */
-extern int slim_port_xfer(struct slim_device *sb, u32 ph, phys_addr_t iobuf,
+extern int slim_port_xfer(struct slim_device *sb, u32 ph, void *buf,
 				u32 len, struct completion *comp);
 
 /*
diff --git a/include/linux/thermal.h b/include/linux/thermal.h
index 52bc890..33c1dae 100644
--- a/include/linux/thermal.h
+++ b/include/linux/thermal.h
@@ -393,6 +393,8 @@
  *		   temperature.
  * @set_trip_temp: a pointer to a function that sets the trip temperature on
  *		   hardware.
+ * @get_trip_temp: a pointer to a function that gets the trip temperature on
+ *		   hardware.
  */
 struct thermal_zone_of_device_ops {
 	int (*get_temp)(void *, int *);
@@ -400,6 +402,7 @@
 	int (*set_trips)(void *, int, int);
 	int (*set_emul_temp)(void *, int);
 	int (*set_trip_temp)(void *, int, int);
+	int (*get_trip_temp)(void *, int, int *);
 };
 
 /**
diff --git a/include/linux/usb/gadget.h b/include/linux/usb/gadget.h
index 6acd229..3f3a7e4 100644
--- a/include/linux/usb/gadget.h
+++ b/include/linux/usb/gadget.h
@@ -481,6 +481,7 @@
  * @bam2bam_func_enabled; Indicates function using bam2bam is enabled or not.
  * @extra_buf_alloc: Extra allocation size for AXI prefetch so that out of
  * boundary access is protected.
+ * @is_chipidea: True if ChipIdea device controller
  *
  * Gadgets have a mostly-portable "gadget driver" implementing device
  * functions, handling all usb configurations and interfaces.  Gadget
@@ -537,6 +538,7 @@
 	bool				bam2bam_func_enabled;
 	u32				extra_buf_alloc;
 	bool				l1_supported;
+	bool				is_chipidea;
 };
 #define work_to_gadget(w)	(container_of((w), struct usb_gadget, work))
 
@@ -1133,7 +1135,7 @@
 			const char *ep_name);
 
 #ifdef CONFIG_USB_DWC3_MSM
-int msm_ep_config(struct usb_ep *ep);
+int msm_ep_config(struct usb_ep *ep, struct usb_request *request);
 int msm_ep_unconfig(struct usb_ep *ep);
 void dwc3_tx_fifo_resize_request(struct usb_ep *ep, bool qdss_enable);
 int msm_data_fifo_config(struct usb_ep *ep, unsigned long addr, u32 size,
@@ -1145,7 +1147,7 @@
 	u32 size, u8 dst_pipe_idx)
 {	return -ENODEV; }
 
-static inline int msm_ep_config(struct usb_ep *ep)
+static inline int msm_ep_config(struct usb_ep *ep, struct usb_request *request)
 { return -ENODEV; }
 
 static inline int msm_ep_unconfig(struct usb_ep *ep)
diff --git a/include/linux/usb_bam.h b/include/linux/usb_bam.h
index 84d7549..e5d4c04 100644
--- a/include/linux/usb_bam.h
+++ b/include/linux/usb_bam.h
@@ -426,7 +426,7 @@
  *
  * @return true when producer granted, false when prodcuer is released.
  */
-bool usb_bam_get_prod_granted(enum usb_ctrl bam_type, u8 idx);
+bool usb_bam_get_prod_granted(enum usb_ctrl bam_type);
 
 /* Allocates memory for data fifo and descriptor fifos. */
 int usb_bam_alloc_fifos(enum usb_ctrl cur_bam, u8 idx);
@@ -519,7 +519,7 @@
 	return -ENODEV;
 }
 
-static inline bool usb_bam_get_prod_granted(enum usb_ctrl bam_type, u8 idx)
+static inline bool usb_bam_get_prod_granted(enum usb_ctrl bam_type)
 {
 	return false;
 }
diff --git a/include/linux/writeback.h b/include/linux/writeback.h
index 797100e..9a8eb83 100644
--- a/include/linux/writeback.h
+++ b/include/linux/writeback.h
@@ -224,6 +224,7 @@
 static inline void inode_detach_wb(struct inode *inode)
 {
 	if (inode->i_wb) {
+		WARN_ON_ONCE(!(inode->i_state & I_CLEAR));
 		wb_put(inode->i_wb);
 		inode->i_wb = NULL;
 	}
diff --git a/include/media/msmb_isp.h b/include/media/msmb_isp.h
index 6f5da29..95679cb 100644
--- a/include/media/msmb_isp.h
+++ b/include/media/msmb_isp.h
@@ -29,6 +29,13 @@
 	} u;
 };
 #endif
-
+#ifdef CONFIG_MSM_AVTIMER
+struct avtimer_fptr_t {
+	int (*fptr_avtimer_open)(void);
+	int (*fptr_avtimer_enable)(int enable);
+	int (*fptr_avtimer_get_time)(uint64_t *avtimer_tick);
+};
+void msm_isp_set_avtimer_fptr(struct avtimer_fptr_t avtimer_func);
+#endif
 #endif
 
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index d5e79f1..520c4c3 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -61,6 +61,9 @@
 /* Indicate backport support for per chain rssi scan */
 #define CFG80211_SCAN_PER_CHAIN_RSSI_SUPPORT 1
 
+/* Indicate backport support for external authentication*/
+#define CFG80211_EXTERNAL_AUTH_SUPPORT 1
+
 /**
  * DOC: Introduction
  *
@@ -1878,11 +1881,16 @@
  * @ASSOC_REQ_DISABLE_HT:  Disable HT (802.11n)
  * @ASSOC_REQ_DISABLE_VHT:  Disable VHT
  * @ASSOC_REQ_USE_RRM: Declare RRM capability in this association
+ * @CONNECT_REQ_EXTERNAL_AUTH_SUPPORT: User space indicates external
+ *	authentication capability. Drivers can offload authentication to
+ *	userspace if this flag is set. Only applicable for cfg80211_connect()
+ *	request (connect callback).
  */
 enum cfg80211_assoc_req_flags {
-	ASSOC_REQ_DISABLE_HT		= BIT(0),
-	ASSOC_REQ_DISABLE_VHT		= BIT(1),
-	ASSOC_REQ_USE_RRM		= BIT(2),
+	ASSOC_REQ_DISABLE_HT			= BIT(0),
+	ASSOC_REQ_DISABLE_VHT			= BIT(1),
+	ASSOC_REQ_USE_RRM			= BIT(2),
+	CONNECT_REQ_EXTERNAL_AUTH_SUPPORT	= BIT(3),
 };
 
 /**
@@ -2554,6 +2562,33 @@
 };
 
 /**
+ * struct cfg80211_external_auth_params - Trigger External authentication.
+ *
+ * Commonly used across the external auth request and event interfaces.
+ *
+ * @action: action type / trigger for external authentication. Only significant
+ *	for the authentication request event interface (driver to user space).
+ * @bssid: BSSID of the peer with which the authentication has
+ *	to happen. Used by both the authentication request event and
+ *	authentication response command interface.
+ * @ssid: SSID of the AP.  Used by both the authentication request event and
+ *	authentication response command interface.
+ * @key_mgmt_suite: AKM suite of the respective authentication. Used by the
+ *	authentication request event interface.
+ * @status: status code, %WLAN_STATUS_SUCCESS for successful authentication,
+ *	use %WLAN_STATUS_UNSPECIFIED_FAILURE if user space cannot give you
+ *	the real status code for failures. Used only for the authentication
+ *	response command interface (user space to driver).
+ */
+struct cfg80211_external_auth_params {
+	enum nl80211_external_auth_action action;
+	u8 bssid[ETH_ALEN] __aligned(2);
+	struct cfg80211_ssid ssid;
+	unsigned int key_mgmt_suite;
+	u16 status;
+};
+
+/**
  * struct cfg80211_ops - backend description for wireless configuration
  *
  * This struct is registered by fullmac card drivers and/or wireless stacks
@@ -2862,6 +2897,9 @@
  *	All other parameters must be ignored.
  *
  * @set_multicast_to_unicast: configure multicast to unicast conversion for BSS
+ *
+ * @external_auth: indicates result of offloaded authentication processing from
+ *     user space
  */
 struct cfg80211_ops {
 	int	(*suspend)(struct wiphy *wiphy, struct cfg80211_wowlan *wow);
@@ -3146,6 +3184,8 @@
 	int	(*set_multicast_to_unicast)(struct wiphy *wiphy,
 					    struct net_device *dev,
 					    const bool enabled);
+	int     (*external_auth)(struct wiphy *wiphy, struct net_device *dev,
+				 struct cfg80211_external_auth_params *params);
 };
 
 /*
@@ -3937,6 +3977,9 @@
  * @conn: (private) cfg80211 software SME connection state machine data
  * @connect_keys: (private) keys to set after connection is established
  * @conn_bss_type: connecting/connected BSS type
+ * @conn_owner_nlportid: (private) connection owner socket port ID
+ * @disconnect_wk: (private) auto-disconnect work
+ * @disconnect_bssid: (private) the BSSID to use for auto-disconnect
  * @ibss_fixed: (private) IBSS is using fixed BSSID
  * @ibss_dfs_possible: (private) IBSS may change to a DFS channel
  * @event_list: (private) list for internal event processing
@@ -3968,6 +4011,10 @@
 	struct cfg80211_conn *conn;
 	struct cfg80211_cached_keys *connect_keys;
 	enum ieee80211_bss_type conn_bss_type;
+	u32 conn_owner_nlportid;
+
+	struct work_struct disconnect_wk;
+	u8 disconnect_bssid[ETH_ALEN];
 
 	struct list_head event_list;
 	spinlock_t event_lock;
@@ -6078,6 +6125,17 @@
  */
 bool cfg80211_is_gratuitous_arp_unsolicited_na(struct sk_buff *skb);
 
+/**
+ * cfg80211_external_auth_request - userspace request for authentication
+ * @netdev: network device
+ * @params: External authentication parameters
+ * @gfp: allocation flags
+ * Returns: 0 on success, < 0 on error
+ */
+int cfg80211_external_auth_request(struct net_device *netdev,
+				   struct cfg80211_external_auth_params *params,
+				   gfp_t gfp);
+
 /* Logging, debugging and troubleshooting/diagnostic helpers. */
 
 /* wiphy_printk helpers, similar to dev_printk */
diff --git a/include/soc/qcom/clock-alpha-pll.h b/include/soc/qcom/clock-alpha-pll.h
index f8130f1..20f8a2f 100644
--- a/include/soc/qcom/clock-alpha-pll.h
+++ b/include/soc/qcom/clock-alpha-pll.h
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2012-2018, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,7 @@
 	u32 alpha_en_mask;	/* alpha_en bit */
 	u32 output_mask;	/* pllout_* bits */
 	u32 post_div_mask;
+	u32 cal_l_val_mask;
 
 	u32 test_ctl_lo_mask;
 	u32 test_ctl_hi_mask;
@@ -61,6 +62,7 @@
 	u32 config_ctl_val;	/* config register init value */
 	u32 test_ctl_lo_val;	/* test control settings */
 	u32 test_ctl_hi_val;
+	u32 cal_l_val;		/* Calibration L value */
 
 	struct alpha_pll_vco_tbl *vco_tbl;
 	u32 num_vco;
diff --git a/include/trace/events/power.h b/include/trace/events/power.h
index 8cfb1d7..a29c76f 100644
--- a/include/trace/events/power.h
+++ b/include/trace/events/power.h
@@ -858,322 +858,6 @@
 		      __entry->freq)
 );
 
-DECLARE_EVENT_CLASS(kpm_module,
-
-	TP_PROTO(unsigned int managed_cpus, unsigned int max_cpus),
-
-	TP_ARGS(managed_cpus, max_cpus),
-
-	TP_STRUCT__entry(
-		__field(u32, managed_cpus)
-		__field(u32, max_cpus)
-	),
-
-	TP_fast_assign(
-		__entry->managed_cpus = managed_cpus;
-		__entry->max_cpus = max_cpus;
-	),
-
-	TP_printk("managed:%x max_cpus=%u", (unsigned int)__entry->managed_cpus,
-					(unsigned int)__entry->max_cpus)
-);
-
-DEFINE_EVENT(kpm_module, set_max_cpus,
-	TP_PROTO(unsigned int managed_cpus, unsigned int max_cpus),
-	TP_ARGS(managed_cpus, max_cpus)
-);
-
-DEFINE_EVENT(kpm_module, reevaluate_hotplug,
-	TP_PROTO(unsigned int managed_cpus, unsigned int max_cpus),
-	TP_ARGS(managed_cpus, max_cpus)
-);
-
-DECLARE_EVENT_CLASS(kpm_module2,
-
-	TP_PROTO(unsigned int cpu, unsigned int enter_cycle_cnt,
-		unsigned int exit_cycle_cnt,
-		unsigned int io_busy, u64 iowait),
-
-	TP_ARGS(cpu, enter_cycle_cnt, exit_cycle_cnt, io_busy, iowait),
-
-	TP_STRUCT__entry(
-		__field(u32, cpu)
-		__field(u32, enter_cycle_cnt)
-		__field(u32, exit_cycle_cnt)
-		__field(u32, io_busy)
-		__field(u64, iowait)
-	),
-
-	TP_fast_assign(
-		__entry->cpu = cpu;
-		__entry->enter_cycle_cnt = enter_cycle_cnt;
-		__entry->exit_cycle_cnt = exit_cycle_cnt;
-		__entry->io_busy = io_busy;
-		__entry->iowait = iowait;
-	),
-
-	TP_printk("CPU:%u enter_cycles=%u exit_cycles=%u io_busy=%u iowait=%lu",
-		(unsigned int)__entry->cpu,
-		(unsigned int)__entry->enter_cycle_cnt,
-		(unsigned int)__entry->exit_cycle_cnt,
-		(unsigned int)__entry->io_busy,
-		(unsigned long)__entry->iowait)
-);
-
-DEFINE_EVENT(kpm_module2, track_iowait,
-	TP_PROTO(unsigned int cpu, unsigned int enter_cycle_cnt,
-		unsigned int exit_cycle_cnt, unsigned int io_busy, u64 iowait),
-	TP_ARGS(cpu, enter_cycle_cnt, exit_cycle_cnt, io_busy, iowait)
-);
-
-DECLARE_EVENT_CLASS(cpu_modes,
-
-	TP_PROTO(unsigned int cpu, unsigned int max_load,
-		unsigned int single_enter_cycle_cnt,
-		unsigned int single_exit_cycle_cnt,
-		unsigned int total_load, unsigned int multi_enter_cycle_cnt,
-		unsigned int multi_exit_cycle_cnt,
-		unsigned int perf_cl_peak_enter_cycle_cnt,
-		unsigned int perf_cl_peak_exit_cycle_cnt,
-		unsigned int mode,
-		unsigned int cpu_cnt),
-
-	TP_ARGS(cpu, max_load, single_enter_cycle_cnt, single_exit_cycle_cnt,
-		total_load, multi_enter_cycle_cnt, multi_exit_cycle_cnt,
-		perf_cl_peak_enter_cycle_cnt, perf_cl_peak_exit_cycle_cnt, mode,
-		cpu_cnt),
-
-	TP_STRUCT__entry(
-		__field(u32, cpu)
-		__field(u32, max_load)
-		__field(u32, single_enter_cycle_cnt)
-		__field(u32, single_exit_cycle_cnt)
-		__field(u32, total_load)
-		__field(u32, multi_enter_cycle_cnt)
-		__field(u32, multi_exit_cycle_cnt)
-		__field(u32, perf_cl_peak_enter_cycle_cnt)
-		__field(u32, perf_cl_peak_exit_cycle_cnt)
-		__field(u32, mode)
-		__field(u32, cpu_cnt)
-	),
-
-	TP_fast_assign(
-		__entry->cpu = cpu;
-		__entry->max_load = max_load;
-		__entry->single_enter_cycle_cnt = single_enter_cycle_cnt;
-		__entry->single_exit_cycle_cnt = single_exit_cycle_cnt;
-		__entry->total_load = total_load;
-		__entry->multi_enter_cycle_cnt = multi_enter_cycle_cnt;
-		__entry->multi_exit_cycle_cnt = multi_exit_cycle_cnt;
-		__entry->perf_cl_peak_enter_cycle_cnt =
-				perf_cl_peak_enter_cycle_cnt;
-		__entry->perf_cl_peak_exit_cycle_cnt =
-				perf_cl_peak_exit_cycle_cnt;
-		__entry->mode = mode;
-		__entry->cpu_cnt = cpu_cnt;
-	),
-
-	TP_printk("%u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%u",
-		(unsigned int)__entry->cpu, (unsigned int)__entry->max_load,
-		(unsigned int)__entry->single_enter_cycle_cnt,
-		(unsigned int)__entry->single_exit_cycle_cnt,
-		(unsigned int)__entry->total_load,
-		(unsigned int)__entry->multi_enter_cycle_cnt,
-		(unsigned int)__entry->multi_exit_cycle_cnt,
-		(unsigned int)__entry->perf_cl_peak_enter_cycle_cnt,
-		(unsigned int)__entry->perf_cl_peak_exit_cycle_cnt,
-		(unsigned int)__entry->mode,
-		(unsigned int)__entry->cpu_cnt)
-);
-
-DEFINE_EVENT(cpu_modes, cpu_mode_detect,
-	TP_PROTO(unsigned int cpu, unsigned int max_load,
-		unsigned int single_enter_cycle_cnt,
-		unsigned int single_exit_cycle_cnt,
-		unsigned int total_load, unsigned int multi_enter_cycle_cnt,
-		unsigned int multi_exit_cycle_cnt,
-		unsigned int perf_cl_peak_enter_cycle_cnt,
-		unsigned int perf_cl_peak_exit_cycle_cnt,
-		unsigned int mode,
-		unsigned int cpu_cnt),
-	TP_ARGS(cpu, max_load, single_enter_cycle_cnt, single_exit_cycle_cnt,
-		total_load, multi_enter_cycle_cnt, multi_exit_cycle_cnt,
-		perf_cl_peak_enter_cycle_cnt, perf_cl_peak_exit_cycle_cnt,
-		mode, cpu_cnt)
-);
-
-DECLARE_EVENT_CLASS(timer_status,
-	TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
-		unsigned int single_enter_cycle_cnt,
-		unsigned int single_exit_cycles,
-		unsigned int single_exit_cycle_cnt,
-		unsigned int multi_enter_cycles,
-		unsigned int multi_enter_cycle_cnt,
-		unsigned int multi_exit_cycles,
-		unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
-		unsigned int mode),
-	TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
-		single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
-		multi_enter_cycle_cnt, multi_exit_cycles,
-		multi_exit_cycle_cnt, timer_rate, mode),
-
-	TP_STRUCT__entry(
-		__field(unsigned int, cpu)
-		__field(unsigned int, single_enter_cycles)
-		__field(unsigned int, single_enter_cycle_cnt)
-		__field(unsigned int, single_exit_cycles)
-		__field(unsigned int, single_exit_cycle_cnt)
-		__field(unsigned int, multi_enter_cycles)
-		__field(unsigned int, multi_enter_cycle_cnt)
-		__field(unsigned int, multi_exit_cycles)
-		__field(unsigned int, multi_exit_cycle_cnt)
-		__field(unsigned int, timer_rate)
-		__field(unsigned int, mode)
-	),
-
-	TP_fast_assign(
-		__entry->cpu = cpu;
-		__entry->single_enter_cycles = single_enter_cycles;
-		__entry->single_enter_cycle_cnt = single_enter_cycle_cnt;
-		__entry->single_exit_cycles = single_exit_cycles;
-		__entry->single_exit_cycle_cnt = single_exit_cycle_cnt;
-		__entry->multi_enter_cycles = multi_enter_cycles;
-		__entry->multi_enter_cycle_cnt = multi_enter_cycle_cnt;
-		__entry->multi_exit_cycles = multi_exit_cycles;
-		__entry->multi_exit_cycle_cnt = multi_exit_cycle_cnt;
-		__entry->timer_rate = timer_rate;
-		__entry->mode = mode;
-	),
-
-	TP_printk("%u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u:%4u",
-		(unsigned int) __entry->cpu,
-		(unsigned int) __entry->single_enter_cycles,
-		(unsigned int) __entry->single_enter_cycle_cnt,
-		(unsigned int) __entry->single_exit_cycles,
-		(unsigned int) __entry->single_exit_cycle_cnt,
-		(unsigned int) __entry->multi_enter_cycles,
-		(unsigned int) __entry->multi_enter_cycle_cnt,
-		(unsigned int) __entry->multi_exit_cycles,
-		(unsigned int) __entry->multi_exit_cycle_cnt,
-		(unsigned int) __entry->timer_rate,
-		(unsigned int) __entry->mode)
-);
-
-DEFINE_EVENT(timer_status, single_mode_timeout,
-	TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
-		unsigned int single_enter_cycle_cnt,
-		unsigned int single_exit_cycles,
-		unsigned int single_exit_cycle_cnt,
-		unsigned int multi_enter_cycles,
-		unsigned int multi_enter_cycle_cnt,
-		unsigned int multi_exit_cycles,
-		unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
-		unsigned int mode),
-	TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
-		single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
-		multi_enter_cycle_cnt, multi_exit_cycles, multi_exit_cycle_cnt,
-		timer_rate, mode)
-);
-
-DEFINE_EVENT(timer_status, single_cycle_exit_timer_start,
-	TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
-		unsigned int single_enter_cycle_cnt,
-		unsigned int single_exit_cycles,
-		unsigned int single_exit_cycle_cnt,
-		unsigned int multi_enter_cycles,
-		unsigned int multi_enter_cycle_cnt,
-		unsigned int multi_exit_cycles,
-		unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
-		unsigned int mode),
-	TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
-		single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
-		multi_enter_cycle_cnt, multi_exit_cycles, multi_exit_cycle_cnt,
-		timer_rate, mode)
-);
-
-DEFINE_EVENT(timer_status, single_cycle_exit_timer_stop,
-	TP_PROTO(unsigned int cpu, unsigned int single_enter_cycles,
-		unsigned int single_enter_cycle_cnt,
-		unsigned int single_exit_cycles,
-		unsigned int single_exit_cycle_cnt,
-		unsigned int multi_enter_cycles,
-		unsigned int multi_enter_cycle_cnt,
-		unsigned int multi_exit_cycles,
-		unsigned int multi_exit_cycle_cnt, unsigned int timer_rate,
-		unsigned int mode),
-	TP_ARGS(cpu, single_enter_cycles, single_enter_cycle_cnt,
-		single_exit_cycles, single_exit_cycle_cnt, multi_enter_cycles,
-		multi_enter_cycle_cnt, multi_exit_cycles, multi_exit_cycle_cnt,
-		timer_rate, mode)
-);
-
-DECLARE_EVENT_CLASS(perf_cl_peak_timer_status,
-	TP_PROTO(unsigned int cpu, unsigned int perf_cl_peak_enter_cycles,
-		unsigned int perf_cl_peak_enter_cycle_cnt,
-		unsigned int perf_cl_peak_exit_cycles,
-		unsigned int perf_cl_peak_exit_cycle_cnt,
-		unsigned int timer_rate,
-		unsigned int mode),
-	TP_ARGS(cpu, perf_cl_peak_enter_cycles, perf_cl_peak_enter_cycle_cnt,
-		perf_cl_peak_exit_cycles, perf_cl_peak_exit_cycle_cnt,
-		timer_rate, mode),
-
-	TP_STRUCT__entry(
-		__field(unsigned int, cpu)
-		__field(unsigned int, perf_cl_peak_enter_cycles)
-		__field(unsigned int, perf_cl_peak_enter_cycle_cnt)
-		__field(unsigned int, perf_cl_peak_exit_cycles)
-		__field(unsigned int, perf_cl_peak_exit_cycle_cnt)
-		__field(unsigned int, timer_rate)
-		__field(unsigned int, mode)
-	),
-
-	TP_fast_assign(
-		__entry->cpu = cpu;
-		__entry->perf_cl_peak_enter_cycles = perf_cl_peak_enter_cycles;
-		__entry->perf_cl_peak_enter_cycle_cnt =
-				perf_cl_peak_enter_cycle_cnt;
-		__entry->perf_cl_peak_exit_cycles = perf_cl_peak_exit_cycles;
-		__entry->perf_cl_peak_exit_cycle_cnt =
-				perf_cl_peak_exit_cycle_cnt;
-		__entry->timer_rate = timer_rate;
-		__entry->mode = mode;
-	),
-
-	TP_printk("%u:%4u:%4u:%4u:%4u:%4u:%4u",
-		(unsigned int) __entry->cpu,
-		(unsigned int) __entry->perf_cl_peak_enter_cycles,
-		(unsigned int) __entry->perf_cl_peak_enter_cycle_cnt,
-		(unsigned int) __entry->perf_cl_peak_exit_cycles,
-		(unsigned int) __entry->perf_cl_peak_exit_cycle_cnt,
-		(unsigned int) __entry->timer_rate,
-		(unsigned int) __entry->mode)
-);
-
-DEFINE_EVENT(perf_cl_peak_timer_status, perf_cl_peak_exit_timer_start,
-	TP_PROTO(unsigned int cpu, unsigned int perf_cl_peak_enter_cycles,
-		unsigned int perf_cl_peak_enter_cycle_cnt,
-		unsigned int perf_cl_peak_exit_cycles,
-		unsigned int perf_cl_peak_exit_cycle_cnt,
-		unsigned int timer_rate,
-		unsigned int mode),
-	TP_ARGS(cpu, perf_cl_peak_enter_cycles, perf_cl_peak_enter_cycle_cnt,
-		perf_cl_peak_exit_cycles, perf_cl_peak_exit_cycle_cnt,
-		timer_rate, mode)
-);
-
-
-DEFINE_EVENT(perf_cl_peak_timer_status, perf_cl_peak_exit_timer_stop,
-	TP_PROTO(unsigned int cpu, unsigned int perf_cl_peak_enter_cycles,
-		unsigned int perf_cl_peak_enter_cycle_cnt,
-		unsigned int perf_cl_peak_exit_cycles,
-		unsigned int perf_cl_peak_exit_cycle_cnt,
-		unsigned int timer_rate,
-		unsigned int mode),
-	TP_ARGS(cpu, perf_cl_peak_enter_cycles, perf_cl_peak_enter_cycle_cnt,
-		perf_cl_peak_exit_cycles, perf_cl_peak_exit_cycle_cnt,
-		timer_rate, mode)
-);
 
 #endif /* _TRACE_POWER_H */
 
diff --git a/include/uapi/linux/hbtp_input.h b/include/uapi/linux/hbtp_input.h
index 3b124ff..8bc189f 100644
--- a/include/uapi/linux/hbtp_input.h
+++ b/include/uapi/linux/hbtp_input.h
@@ -9,6 +9,7 @@
 #define MAX_ROI_SIZE		144
 #define MAX_ACCEL_SIZE		128
 
+#define HBTP_FLAG_ACTIVE_BLOB      0x01
 #define HBTP_EVENT_TYPE_DISPLAY	"EVENT_TYPE=HBTP_DISPLAY"
 
 struct hbtp_input_touch {
@@ -33,6 +34,13 @@
 	struct timeval time_val;
 };
 
+struct hbtp_input_mt_ext {
+	__s32  num_touches;
+	struct hbtp_input_touch touches[HBTP_MAX_FINGER];
+	struct timeval time_val;
+	__u32  flag;
+};
+
 struct hbtp_input_absinfo {
 	bool  active;
 	__u16 code;
@@ -77,6 +85,8 @@
 					enum hbtp_afe_power_ctrl)
 #define HBTP_SET_SENSORDATA	_IOW(HBTP_INPUT_IOCTL_BASE, 207, \
 					struct hbtp_sensor_data)
+#define HBTP_SET_TOUCHDATA_EXT	_IOW(HBTP_INPUT_IOCTL_BASE, 208, \
+					struct hbtp_input_mt_ext)
 
 #endif	/* _UAPI_HBTP_INPUT_H */
 
diff --git a/include/uapi/linux/nl80211.h b/include/uapi/linux/nl80211.h
index 3092188..9399a35 100644
--- a/include/uapi/linux/nl80211.h
+++ b/include/uapi/linux/nl80211.h
@@ -944,6 +944,43 @@
  *	does not result in a change for the current association. Currently,
  *	only the %NL80211_ATTR_IE data is used and updated with this command.
  *
+ * @NL80211_CMD_SET_PMK: For offloaded 4-Way handshake, set the PMK or PMK-R0
+ *	for the given authenticator address (specified with &NL80211_ATTR_MAC).
+ *	When &NL80211_ATTR_PMKR0_NAME is set, &NL80211_ATTR_PMK specifies the
+ *	PMK-R0, otherwise it specifies the PMK.
+ * @NL80211_CMD_DEL_PMK: For offloaded 4-Way handshake, delete the previously
+ *	configured PMK for the authenticator address identified by
+ *	&NL80211_ATTR_MAC.
+ * @NL80211_CMD_PORT_AUTHORIZED: An event that indicates that the 4 way
+ *	handshake was completed successfully by the driver. The BSSID is
+ *	specified with &NL80211_ATTR_MAC. Drivers that support 4 way handshake
+ *	offload should send this event after indicating 802.11 association with
+ *	&NL80211_CMD_CONNECT or &NL80211_CMD_ROAM. If the 4 way handshake failed
+ *	&NL80211_CMD_DISCONNECT should be indicated instead.
+ *
+ * @NL80211_CMD_RELOAD_REGDB: Request that the regdb firmware file is reloaded.
+ *
+ * @NL80211_CMD_EXTERNAL_AUTH: This interface is exclusively defined for host
+ *	drivers that do not define separate commands for authentication and
+ *	association, but rely on user space for the authentication to happen.
+ *	This interface acts both as the event request (driver to user space)
+ *	to trigger the authentication and command response (userspace to
+ *	driver) to indicate the authentication status.
+ *
+ *	User space uses the %NL80211_CMD_CONNECT command to the host driver to
+ *	trigger a connection. The host driver selects a BSS and further uses
+ *	this interface to offload only the authentication part to the user
+ *	space. Authentication frames are passed between the driver and user
+ *	space through the %NL80211_CMD_FRAME interface. Host driver proceeds
+ *	further with the association after getting successful authentication
+ *	status. User space indicates the authentication status through
+ *	%NL80211_ATTR_STATUS_CODE attribute in %NL80211_CMD_EXTERNAL_AUTH
+ *	command interface.
+ *
+ *	Host driver reports this status on an authentication failure to the
+ *	user space through the connect result as the user space would have
+ *	initiated the connection through the connect request.
+ *
  * @NL80211_CMD_MAX: highest used command number
  * @__NL80211_CMD_AFTER_LAST: internal use
  */
@@ -1143,6 +1180,15 @@
 
 	NL80211_CMD_UPDATE_CONNECT_PARAMS,
 
+	NL80211_CMD_SET_PMK,
+	NL80211_CMD_DEL_PMK,
+
+	NL80211_CMD_PORT_AUTHORIZED,
+
+	NL80211_CMD_RELOAD_REGDB,
+
+	NL80211_CMD_EXTERNAL_AUTH,
+
 	/* add new commands above here */
 
 	/* used to define NL80211_CMD_MAX below */
@@ -1870,6 +1916,8 @@
  *	and remove functions. NAN notifications will be sent in unicast to that
  *	socket. Without this attribute, any socket can add functions and the
  *	notifications will be sent to the %NL80211_MCGRP_NAN multicast group.
+ *	If set during %NL80211_CMD_ASSOCIATE or %NL80211_CMD_CONNECT the
+ *	station will deauthenticate when the socket is closed.
  *
  * @NL80211_ATTR_TDLS_INITIATOR: flag attribute indicating the current end is
  *	the TDLS link initiator.
@@ -2077,6 +2125,16 @@
  *	the driver or is not needed (because roaming used the Fast Transition
  *	protocol).
  *
+ * @NL80211_ATTR_EXTERNAL_AUTH_ACTION: Identify the requested external
+ *     authentication operation (u32 attribute with an
+ *     &enum nl80211_external_auth_action value). This is used with the
+ *     &NL80211_CMD_EXTERNAL_AUTH request event.
+ * @NL80211_ATTR_EXTERNAL_AUTH_SUPPORT: Flag attribute indicating that the user
+ *     space supports external authentication. This attribute shall be used
+ *     only with %NL80211_CMD_CONNECT request. The driver may offload
+ *     authentication processing to user space if this capability is indicated
+ *     in NL80211_CMD_CONNECT requests from the user space.
+ *
  * @NUM_NL80211_ATTR: total number of nl80211_attrs available
  * @NL80211_ATTR_MAX: highest attribute number currently defined
  * @__NL80211_ATTR_AFTER_LAST: internal use
@@ -2503,6 +2561,9 @@
 	NL80211_ATTR_PMKR0_NAME,
 	NL80211_ATTR_PORT_AUTHORIZED,
 
+	NL80211_ATTR_EXTERNAL_AUTH_ACTION,
+	NL80211_ATTR_EXTERNAL_AUTH_SUPPORT,
+
 	/* add attributes here, update the policy in nl80211.c */
 
 	__NL80211_ATTR_AFTER_LAST,
@@ -5401,4 +5462,15 @@
 	NL80211_NAN_MATCH_ATTR_MAX = NUM_NL80211_NAN_MATCH_ATTR - 1
 };
 
+/**
+ * nl80211_external_auth_action - Action to perform with external
+ *     authentication request. Used by NL80211_ATTR_EXTERNAL_AUTH_ACTION.
+ * @NL80211_EXTERNAL_AUTH_START: Start the authentication.
+ * @NL80211_EXTERNAL_AUTH_ABORT: Abort the ongoing authentication.
+ */
+enum nl80211_external_auth_action {
+	NL80211_EXTERNAL_AUTH_START,
+	NL80211_EXTERNAL_AUTH_ABORT,
+};
+
 #endif /* __LINUX_NL80211_H */
diff --git a/include/uapi/linux/qg.h b/include/uapi/linux/qg.h
index c0b2b6e..54488ff 100644
--- a/include/uapi/linux/qg.h
+++ b/include/uapi/linux/qg.h
@@ -38,6 +38,8 @@
 };
 
 struct qg_kernel_data {
+	unsigned int			seq_no;
+	unsigned int			fifo_time;
 	unsigned int			fifo_length;
 	struct fifo_data		fifo[MAX_FIFO_LENGTH];
 	struct qg_param			param[QG_MAX];
diff --git a/include/uapi/media/msm_vidc.h b/include/uapi/media/msm_vidc.h
index 59fab2f..cac2b32 100644
--- a/include/uapi/media/msm_vidc.h
+++ b/include/uapi/media/msm_vidc.h
@@ -296,6 +296,9 @@
 	MSM_VIDC_INTERLACE_INTERLEAVE_FRAME_BOTTOMFIELDFIRST = 0x04,
 	MSM_VIDC_INTERLACE_FRAME_TOPFIELDFIRST = 0x08,
 	MSM_VIDC_INTERLACE_FRAME_BOTTOMFIELDFIRST = 0x10,
+#define MSM_VIDC_INTERLACE_FRAME_MBAFF \
+	MSM_VIDC_INTERLACE_FRAME_MBAFF
+	MSM_VIDC_INTERLACE_FRAME_MBAFF = 0x20,
 };
 
 /* enum msm_vidc_framepack_type */
diff --git a/kernel/async.c b/kernel/async.c
index d2edd6e..d84d486 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -84,20 +84,24 @@
 
 static async_cookie_t lowest_in_progress(struct async_domain *domain)
 {
-	struct list_head *pending;
+	struct async_entry *first = NULL;
 	async_cookie_t ret = ASYNC_COOKIE_MAX;
 	unsigned long flags;
 
 	spin_lock_irqsave(&async_lock, flags);
 
-	if (domain)
-		pending = &domain->pending;
-	else
-		pending = &async_global_pending;
+	if (domain) {
+		if (!list_empty(&domain->pending))
+			first = list_first_entry(&domain->pending,
+					struct async_entry, domain_list);
+	} else {
+		if (!list_empty(&async_global_pending))
+			first = list_first_entry(&async_global_pending,
+					struct async_entry, global_list);
+	}
 
-	if (!list_empty(pending))
-		ret = list_first_entry(pending, struct async_entry,
-				       domain_list)->cookie;
+	if (first)
+		ret = first->cookie;
 
 	spin_unlock_irqrestore(&async_lock, flags);
 	return ret;
diff --git a/kernel/power/qos.c b/kernel/power/qos.c
index 5183134..0469d80 100644
--- a/kernel/power/qos.c
+++ b/kernel/power/qos.c
@@ -597,12 +597,11 @@
 #ifdef CONFIG_SMP
 	case PM_QOS_REQ_AFFINE_IRQ:
 		if (irq_can_set_affinity(req->irq)) {
-			int ret = 0;
 			struct irq_desc *desc = irq_to_desc(req->irq);
 			struct cpumask *mask;
 
 			if (!desc)
-				break;
+				return;
 
 			mask = desc->irq_data.common->affinity;
 
@@ -612,13 +611,6 @@
 			req->irq_notify.notify = pm_qos_irq_notify;
 			req->irq_notify.release = pm_qos_irq_release;
 
-			ret = irq_set_affinity_notifier(req->irq,
-					&req->irq_notify);
-			if (ret) {
-				WARN(1, KERN_ERR "IRQ affinity notify set failed\n");
-				req->type = PM_QOS_REQ_ALL_CORES;
-				cpumask_setall(&req->cpus_affine);
-			}
 		} else {
 			req->type = PM_QOS_REQ_ALL_CORES;
 			cpumask_setall(&req->cpus_affine);
@@ -640,6 +632,24 @@
 	trace_pm_qos_add_request(pm_qos_class, value);
 	pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints,
 			     req, PM_QOS_ADD_REQ, value);
+
+#ifdef CONFIG_SMP
+	if (req->type == PM_QOS_REQ_AFFINE_IRQ &&
+			irq_can_set_affinity(req->irq)) {
+		int ret = 0;
+
+		ret = irq_set_affinity_notifier(req->irq,
+					&req->irq_notify);
+		if (ret) {
+			WARN(1, "IRQ affinity notify set failed\n");
+			req->type = PM_QOS_REQ_ALL_CORES;
+			cpumask_setall(&req->cpus_affine);
+			pm_qos_update_target(
+				pm_qos_array[pm_qos_class]->constraints,
+				req, PM_QOS_UPDATE_REQ, value);
+		}
+	}
+#endif
 }
 EXPORT_SYMBOL_GPL(pm_qos_add_request);
 
diff --git a/kernel/relay.c b/kernel/relay.c
index 8f18d31..2603e04 100644
--- a/kernel/relay.c
+++ b/kernel/relay.c
@@ -611,7 +611,6 @@
 
 	kref_put(&chan->kref, relay_destroy_channel);
 	mutex_unlock(&relay_channels_mutex);
-	kfree(chan);
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(relay_open);
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 31b45b7..ad2b980 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6447,6 +6447,19 @@
 		call_rcu_sched(&old_rd->rcu, free_rootdomain);
 }
 
+void sched_get_rd(struct root_domain *rd)
+{
+	atomic_inc(&rd->refcount);
+}
+
+void sched_put_rd(struct root_domain *rd)
+{
+	if (!atomic_dec_and_test(&rd->refcount))
+		return;
+
+	call_rcu_sched(&rd->rcu, free_rootdomain);
+}
+
 static int init_rootdomain(struct root_domain *rd)
 {
 	memset(rd, 0, sizeof(*rd));
diff --git a/kernel/sched/debug.c b/kernel/sched/debug.c
index c091ca4..16065b2 100644
--- a/kernel/sched/debug.c
+++ b/kernel/sched/debug.c
@@ -784,7 +784,6 @@
 	P(sysctl_sched_child_runs_first);
 	P(sysctl_sched_features);
 #ifdef CONFIG_SCHED_WALT
-	P(sched_init_task_load_windows);
 	P(min_capacity);
 	P(max_capacity);
 	P(sched_ravg_window);
diff --git a/kernel/sched/rt.c b/kernel/sched/rt.c
index 73f11c4..e6abbb4 100644
--- a/kernel/sched/rt.c
+++ b/kernel/sched/rt.c
@@ -2261,8 +2261,11 @@
 
 	rto_start_unlock(&rq->rd->rto_loop_start);
 
-	if (cpu >= 0)
+	if (cpu >= 0) {
+		/* Make sure the rd does not get freed while pushing */
+		sched_get_rd(rq->rd);
 		irq_work_queue_on(&rq->rd->rto_push_work, cpu);
+	}
 }
 
 /* Called from hardirq context */
@@ -2292,8 +2295,10 @@
 
 	raw_spin_unlock(&rd->rto_lock);
 
-	if (cpu < 0)
+	if (cpu < 0) {
+		sched_put_rd(rd);
 		return;
+	}
 
 	/* Try the next RT overloaded CPU */
 	irq_work_queue_on(&rd->rto_push_work, cpu);
diff --git a/kernel/sched/sched.h b/kernel/sched/sched.h
index e0aa30d..9bab9e2 100644
--- a/kernel/sched/sched.h
+++ b/kernel/sched/sched.h
@@ -679,6 +679,8 @@
 };
 
 extern struct root_domain def_root_domain;
+extern void sched_get_rd(struct root_domain *rd);
+extern void sched_put_rd(struct root_domain *rd);
 
 #ifdef HAVE_RT_PUSH_IPI
 extern void rto_push_irq_work_func(struct irq_work *work);
@@ -2391,7 +2393,6 @@
 extern unsigned int max_possible_capacity;
 extern unsigned int min_max_possible_capacity;
 extern unsigned int max_power_cost;
-extern unsigned int sched_init_task_load_windows;
 extern unsigned int up_down_migrate_scale_factor;
 extern unsigned int sysctl_sched_restrict_cluster_spill;
 extern unsigned int sched_pred_alert_load;
diff --git a/kernel/sched/walt.c b/kernel/sched/walt.c
index 23fd885..39c58b5 100644
--- a/kernel/sched/walt.c
+++ b/kernel/sched/walt.c
@@ -119,7 +119,6 @@
 __read_mostly unsigned int walt_cpu_util_freq_divisor;
 
 /* Initial task load. Newly created tasks are assigned this load. */
-unsigned int __read_mostly sched_init_task_load_windows;
 unsigned int __read_mostly sysctl_sched_init_task_load_pct = 15;
 
 /*
@@ -1939,8 +1938,8 @@
 void init_new_task_load(struct task_struct *p, bool idle_task)
 {
 	int i;
-	u32 init_load_windows = sched_init_task_load_windows;
-	u32 init_load_pct = current->init_load_pct;
+	u32 init_load_windows;
+	u32 init_load_pct;
 
 	p->init_load_pct = 0;
 	rcu_assign_pointer(p->grp, NULL);
@@ -1957,9 +1956,13 @@
 	if (idle_task)
 		return;
 
-	if (init_load_pct)
-		init_load_windows = div64_u64((u64)init_load_pct *
-			  (u64)sched_ravg_window, 100);
+	if (current->init_load_pct)
+		init_load_pct = current->init_load_pct;
+	else
+		init_load_pct = sysctl_sched_init_task_load_pct;
+
+	init_load_windows = div64_u64((u64)init_load_pct *
+				(u64)sched_ravg_window, 100);
 
 	p->ravg.demand = init_load_windows;
 	p->ravg.coloc_demand = init_load_windows;
@@ -3242,8 +3245,4 @@
 
 	walt_cpu_util_freq_divisor =
 	    (sched_ravg_window >> SCHED_CAPACITY_SHIFT) * 100;
-
-	sched_init_task_load_windows =
-		div64_u64((u64)sysctl_sched_init_task_load_pct *
-			  (u64)sched_ravg_window, 100);
 }
diff --git a/kernel/sched/walt.h b/kernel/sched/walt.h
index da53ea4..7edae12 100644
--- a/kernel/sched/walt.h
+++ b/kernel/sched/walt.h
@@ -40,7 +40,6 @@
 extern unsigned int min_possible_efficiency;
 extern unsigned int max_possible_freq;
 extern unsigned int sched_major_task_runtime;
-extern unsigned int __read_mostly sched_init_task_load_windows;
 extern unsigned int __read_mostly sched_load_granule;
 
 extern struct mutex cluster_lock;
diff --git a/kernel/softirq.c b/kernel/softirq.c
index 6833ffa..b593317 100644
--- a/kernel/softirq.c
+++ b/kernel/softirq.c
@@ -85,17 +85,6 @@
 }
 
 /*
- * If ksoftirqd is scheduled, we do not want to process pending softirqs
- * right now. Let ksoftirqd handle this at its own rate, to get fairness.
- */
-static bool ksoftirqd_running(void)
-{
-	struct task_struct *tsk = __this_cpu_read(ksoftirqd);
-
-	return tsk && (tsk->state == TASK_RUNNING);
-}
-
-/*
  * preempt_count and SOFTIRQ_OFFSET usage:
  * - preempt_count is changed by SOFTIRQ_OFFSET on entering or leaving
  *   softirq processing.
@@ -245,8 +234,16 @@
 static inline void lockdep_softirq_end(bool in_hardirq) { }
 #endif
 
-#define long_softirq_pending()	(local_softirq_pending() & LONG_SOFTIRQ_MASK)
-#define defer_for_rt()		(long_softirq_pending() && cpupri_check_rt())
+#define softirq_deferred_for_rt(pending)		\
+({							\
+	__u32 deferred = 0;				\
+	if (cpupri_check_rt()) {			\
+		deferred = pending & LONG_SOFTIRQ_MASK; \
+		pending &= ~LONG_SOFTIRQ_MASK;		\
+	}						\
+	deferred;					\
+})
+
 asmlinkage __visible void __softirq_entry __do_softirq(void)
 {
 	unsigned long end = jiffies + MAX_SOFTIRQ_TIME;
@@ -254,6 +251,7 @@
 	int max_restart = MAX_SOFTIRQ_RESTART;
 	struct softirq_action *h;
 	bool in_hardirq;
+	__u32 deferred;
 	__u32 pending;
 	int softirq_bit;
 
@@ -265,14 +263,14 @@
 	current->flags &= ~PF_MEMALLOC;
 
 	pending = local_softirq_pending();
+	deferred = softirq_deferred_for_rt(pending);
 	account_irq_enter_time(current);
-
 	__local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET);
 	in_hardirq = lockdep_softirq_start();
 
 restart:
 	/* Reset the pending bitmask before enabling irqs */
-	set_softirq_pending(0);
+	set_softirq_pending(deferred);
 	__this_cpu_write(active_softirqs, pending);
 
 	local_irq_enable();
@@ -308,15 +306,16 @@
 	local_irq_disable();
 
 	pending = local_softirq_pending();
+	deferred = softirq_deferred_for_rt(pending);
+
 	if (pending) {
 		if (time_before(jiffies, end) && !need_resched() &&
-		    !defer_for_rt() &&
 		    --max_restart)
 			goto restart;
-
-		wakeup_softirqd();
 	}
 
+	if (pending | deferred)
+		wakeup_softirqd();
 	lockdep_softirq_end(in_hardirq);
 	account_irq_exit_time(current);
 	__local_bh_enable(SOFTIRQ_OFFSET);
@@ -336,7 +335,7 @@
 
 	pending = local_softirq_pending();
 
-	if (pending && !ksoftirqd_running())
+	if (pending)
 		do_softirq_own_stack();
 
 	local_irq_restore(flags);
@@ -363,10 +362,7 @@
 
 static inline void invoke_softirq(void)
 {
-	if (ksoftirqd_running())
-		return;
-
-	if (!force_irqthreads && !defer_for_rt()) {
+	if (!force_irqthreads) {
 #ifdef CONFIG_HAVE_IRQ_EXIT_ON_IRQ_STACK
 		/*
 		 * We can safely execute softirq on the current stack if
diff --git a/kernel/sysctl.c b/kernel/sysctl.c
index b057784..6340010 100644
--- a/kernel/sysctl.c
+++ b/kernel/sysctl.c
@@ -334,6 +334,13 @@
 		.extra1		= &zero,
 		.extra2		= &one,
 	},
+	{
+		.procname	= "sched_initial_task_util",
+		.data		= &sysctl_sched_init_task_load_pct,
+		.maxlen		= sizeof(unsigned int),
+		.mode		= 0644,
+		.proc_handler	= proc_dointvec,
+	},
 #endif
 	{
 		.procname	= "sched_upmigrate",
@@ -392,13 +399,6 @@
 	},
 #endif
 	{
-		.procname	= "sched_initial_task_util",
-		.data		= &sysctl_sched_initial_task_util,
-		.maxlen		= sizeof(unsigned int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec,
-	},
-	{
 		.procname	= "sched_cstate_aware",
 		.data		= &sysctl_sched_cstate_aware,
 		.maxlen		= sizeof(unsigned int),
diff --git a/kernel/time/posix-timers.c b/kernel/time/posix-timers.c
index f2826c3..fc7c37a 100644
--- a/kernel/time/posix-timers.c
+++ b/kernel/time/posix-timers.c
@@ -507,17 +507,22 @@
 {
 	struct task_struct *rtn = current->group_leader;
 
-	if ((event->sigev_notify & SIGEV_THREAD_ID ) &&
-		(!(rtn = find_task_by_vpid(event->sigev_notify_thread_id)) ||
-		 !same_thread_group(rtn, current) ||
-		 (event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_SIGNAL))
+	switch (event->sigev_notify) {
+	case SIGEV_SIGNAL | SIGEV_THREAD_ID:
+		rtn = find_task_by_vpid(event->sigev_notify_thread_id);
+		if (!rtn || !same_thread_group(rtn, current))
+			return NULL;
+		/* FALLTHRU */
+	case SIGEV_SIGNAL:
+	case SIGEV_THREAD:
+		if (event->sigev_signo <= 0 || event->sigev_signo > SIGRTMAX)
+			return NULL;
+		/* FALLTHRU */
+	case SIGEV_NONE:
+		return task_pid(rtn);
+	default:
 		return NULL;
-
-	if (((event->sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE) &&
-	    ((event->sigev_signo <= 0) || (event->sigev_signo > SIGRTMAX)))
-		return NULL;
-
-	return task_pid(rtn);
+	}
 }
 
 void posix_timers_register_clock(const clockid_t clock_id,
@@ -745,8 +750,7 @@
 	/* interval timer ? */
 	if (iv.tv64)
 		cur_setting->it_interval = ktime_to_timespec(iv);
-	else if (!hrtimer_active(timer) &&
-		 (timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
+	else if (!hrtimer_active(timer) && timr->it_sigev_notify != SIGEV_NONE)
 		return;
 
 	now = timer->base->get_time();
@@ -757,7 +761,7 @@
 	 * expiry is > now.
 	 */
 	if (iv.tv64 && (timr->it_requeue_pending & REQUEUE_PENDING ||
-	    (timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE))
+			timr->it_sigev_notify == SIGEV_NONE))
 		timr->it_overrun += (unsigned int) hrtimer_forward(timer, now, iv);
 
 	remaining = __hrtimer_expires_remaining_adjusted(timer, now);
@@ -767,7 +771,7 @@
 		 * A single shot SIGEV_NONE timer must return 0, when
 		 * it is expired !
 		 */
-		if ((timr->it_sigev_notify & ~SIGEV_THREAD_ID) != SIGEV_NONE)
+		if (timr->it_sigev_notify != SIGEV_NONE)
 			cur_setting->it_value.tv_nsec = 1;
 	} else
 		cur_setting->it_value = ktime_to_timespec(remaining);
@@ -865,7 +869,7 @@
 	timr->it.real.interval = timespec_to_ktime(new_setting->it_interval);
 
 	/* SIGEV_NONE timers are not queued ! See common_timer_get */
-	if (((timr->it_sigev_notify & ~SIGEV_THREAD_ID) == SIGEV_NONE)) {
+	if (timr->it_sigev_notify == SIGEV_NONE) {
 		/* Setup correct expiry time for relative timers */
 		if (mode == HRTIMER_MODE_REL) {
 			hrtimer_add_expires(timer, timer->base->get_time());
diff --git a/kernel/time/timer.c b/kernel/time/timer.c
index a6f8a44..41481dc 100644
--- a/kernel/time/timer.c
+++ b/kernel/time/timer.c
@@ -208,6 +208,7 @@
 
 static DEFINE_PER_CPU(struct timer_base, timer_bases[NR_BASES]);
 struct timer_base timer_base_deferrable;
+static atomic_t deferrable_pending;
 
 #if defined(CONFIG_SMP) && defined(CONFIG_NO_HZ_COMMON)
 unsigned int sysctl_timer_migration = 1;
@@ -1488,8 +1489,6 @@
 
 
 #ifdef CONFIG_SMP
-static atomic_t deferrable_pending;
-
 /*
  * check_pending_deferrable_timers - Check for unbound deferrable timer expiry
  * @cpu - Current CPU
@@ -1670,27 +1669,6 @@
 	spin_unlock_irq(&base->lock);
 }
 
-#ifdef CONFIG_SMP
-static inline bool should_this_cpu_run_deferrable_timers(void)
-{
-	int tick_cpu = READ_ONCE(tick_do_timer_cpu);
-
-	if (atomic_cmpxchg(&deferrable_pending, 1, 0) &&
-			tick_cpu == TICK_DO_TIMER_NONE)
-		return true;
-
-	if (tick_cpu == smp_processor_id())
-		return true;
-
-	return (tick_cpu >= 0 && ksoftirqd_running_on(tick_cpu));
-}
-#else
-static inline bool should_this_cpu_run_deferrable_timers(void)
-{
-	return true;
-}
-#endif
-
 /*
  * This function runs timers and the timer-tq in bottom half context.
  */
@@ -1715,7 +1693,9 @@
 	if (IS_ENABLED(CONFIG_NO_HZ_COMMON))
 		__run_timers(this_cpu_ptr(&timer_bases[BASE_DEF]));
 
-	if (should_this_cpu_run_deferrable_timers())
+	if ((atomic_cmpxchg(&deferrable_pending, 1, 0) &&
+		tick_do_timer_cpu == TICK_DO_TIMER_NONE) ||
+		tick_do_timer_cpu == smp_processor_id())
 		__run_timers(&timer_base_deferrable);
 }
 
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 5b8d718..2884fe0 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3911,7 +3911,6 @@
 		func_g.type = filter_parse_regex(glob, strlen(glob),
 						 &func_g.search, &not);
 		func_g.len = strlen(func_g.search);
-		func_g.search = glob;
 
 		/* we do not support '!' for function probes */
 		if (WARN_ON(not))
diff --git a/lib/kobject.c b/lib/kobject.c
index 445dcae..763d70a 100644
--- a/lib/kobject.c
+++ b/lib/kobject.c
@@ -601,12 +601,15 @@
 }
 EXPORT_SYMBOL(kobject_get);
 
-static struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
+struct kobject * __must_check kobject_get_unless_zero(struct kobject *kobj)
 {
+	if (!kobj)
+		return NULL;
 	if (!kref_get_unless_zero(&kobj->kref))
 		kobj = NULL;
 	return kobj;
 }
+EXPORT_SYMBOL(kobject_get_unless_zero);
 
 /*
  * kobject_cleanup - free kobject resources.
diff --git a/lib/ubsan.c b/lib/ubsan.c
index fb0409d..50d1d5c 100644
--- a/lib/ubsan.c
+++ b/lib/ubsan.c
@@ -265,14 +265,14 @@
 }
 EXPORT_SYMBOL(__ubsan_handle_divrem_overflow);
 
-static void handle_null_ptr_deref(struct type_mismatch_data *data)
+static void handle_null_ptr_deref(struct type_mismatch_data_common *data)
 {
 	unsigned long flags;
 
-	if (suppress_report(&data->location))
+	if (suppress_report(data->location))
 		return;
 
-	ubsan_prologue(&data->location, &flags);
+	ubsan_prologue(data->location, &flags);
 
 	pr_err("%s null pointer of type %s\n",
 		type_check_kinds[data->type_check_kind],
@@ -281,15 +281,15 @@
 	ubsan_epilogue(&flags);
 }
 
-static void handle_missaligned_access(struct type_mismatch_data *data,
+static void handle_misaligned_access(struct type_mismatch_data_common *data,
 				unsigned long ptr)
 {
 	unsigned long flags;
 
-	if (suppress_report(&data->location))
+	if (suppress_report(data->location))
 		return;
 
-	ubsan_prologue(&data->location, &flags);
+	ubsan_prologue(data->location, &flags);
 
 	pr_err("%s misaligned address %p for type %s\n",
 		type_check_kinds[data->type_check_kind],
@@ -299,15 +299,15 @@
 	ubsan_epilogue(&flags);
 }
 
-static void handle_object_size_mismatch(struct type_mismatch_data *data,
+static void handle_object_size_mismatch(struct type_mismatch_data_common *data,
 					unsigned long ptr)
 {
 	unsigned long flags;
 
-	if (suppress_report(&data->location))
+	if (suppress_report(data->location))
 		return;
 
-	ubsan_prologue(&data->location, &flags);
+	ubsan_prologue(data->location, &flags);
 	pr_err("%s address %p with insufficient space\n",
 		type_check_kinds[data->type_check_kind],
 		(void *) ptr);
@@ -315,19 +315,47 @@
 	ubsan_epilogue(&flags);
 }
 
-void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
+static void ubsan_type_mismatch_common(struct type_mismatch_data_common *data,
 				unsigned long ptr)
 {
 
 	if (!ptr)
 		handle_null_ptr_deref(data);
 	else if (data->alignment && !IS_ALIGNED(ptr, data->alignment))
-		handle_missaligned_access(data, ptr);
+		handle_misaligned_access(data, ptr);
 	else
 		handle_object_size_mismatch(data, ptr);
 }
+
+void __ubsan_handle_type_mismatch(struct type_mismatch_data *data,
+				unsigned long ptr)
+{
+	struct type_mismatch_data_common common_data = {
+		.location = &data->location,
+		.type = data->type,
+		.alignment = data->alignment,
+		.type_check_kind = data->type_check_kind
+	};
+
+	ubsan_type_mismatch_common(&common_data, ptr);
+}
 EXPORT_SYMBOL(__ubsan_handle_type_mismatch);
 
+void __ubsan_handle_type_mismatch_v1(struct type_mismatch_data_v1 *data,
+				unsigned long ptr)
+{
+
+	struct type_mismatch_data_common common_data = {
+		.location = &data->location,
+		.type = data->type,
+		.alignment = 1UL << data->log_alignment,
+		.type_check_kind = data->type_check_kind
+	};
+
+	ubsan_type_mismatch_common(&common_data, ptr);
+}
+EXPORT_SYMBOL(__ubsan_handle_type_mismatch_v1);
+
 void __ubsan_handle_nonnull_return(struct nonnull_return_data *data)
 {
 	unsigned long flags;
diff --git a/lib/ubsan.h b/lib/ubsan.h
index b2d18d4..d8b8085 100644
--- a/lib/ubsan.h
+++ b/lib/ubsan.h
@@ -36,6 +36,20 @@
 	unsigned char type_check_kind;
 };
 
+struct type_mismatch_data_v1 {
+	struct source_location location;
+	struct type_descriptor *type;
+	unsigned char log_alignment;
+	unsigned char type_check_kind;
+};
+
+struct type_mismatch_data_common {
+	struct source_location *location;
+	struct type_descriptor *type;
+	unsigned long alignment;
+	unsigned char type_check_kind;
+};
+
 struct nonnull_arg_data {
 	struct source_location location;
 	struct source_location attr_location;
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 6ff2d77..62ca907 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -237,6 +237,7 @@
 
 	bdi_class->dev_groups = bdi_dev_groups;
 	bdi_debug_init();
+
 	return 0;
 }
 postcore_initcall(bdi_class_init);
@@ -293,6 +294,8 @@
 
 	memset(wb, 0, sizeof(*wb));
 
+	if (wb != &bdi->wb)
+		bdi_get(bdi);
 	wb->bdi = bdi;
 	wb->last_old_flush = jiffies;
 	INIT_LIST_HEAD(&wb->b_dirty);
@@ -312,8 +315,10 @@
 	INIT_DELAYED_WORK(&wb->dwork, wb_workfn);
 
 	wb->congested = wb_congested_get_create(bdi, blkcg_id, gfp);
-	if (!wb->congested)
-		return -ENOMEM;
+	if (!wb->congested) {
+		err = -ENOMEM;
+		goto out_put_bdi;
+	}
 
 	err = fprop_local_init_percpu(&wb->completions, gfp);
 	if (err)
@@ -333,9 +338,14 @@
 	fprop_local_destroy_percpu(&wb->completions);
 out_put_cong:
 	wb_congested_put(wb->congested);
+out_put_bdi:
+	if (wb != &bdi->wb)
+		bdi_put(bdi);
 	return err;
 }
 
+static void cgwb_remove_from_bdi_list(struct bdi_writeback *wb);
+
 /*
  * Remove bdi from the global list and shutdown any threads we have running
  */
@@ -345,10 +355,18 @@
 	spin_lock_bh(&wb->work_lock);
 	if (!test_and_clear_bit(WB_registered, &wb->state)) {
 		spin_unlock_bh(&wb->work_lock);
+		/*
+		 * Wait for wb shutdown to finish if someone else is just
+		 * running wb_shutdown(). Otherwise we could proceed to wb /
+		 * bdi destruction before wb_shutdown() is finished.
+		 */
+		wait_on_bit(&wb->state, WB_shutting_down, TASK_UNINTERRUPTIBLE);
 		return;
 	}
+	set_bit(WB_shutting_down, &wb->state);
 	spin_unlock_bh(&wb->work_lock);
 
+	cgwb_remove_from_bdi_list(wb);
 	/*
 	 * Drain work list and shutdown the delayed_work.  !WB_registered
 	 * tells wb_workfn() that @wb is dying and its work_list needs to
@@ -357,6 +375,12 @@
 	mod_delayed_work(bdi_wq, &wb->dwork, 0);
 	flush_delayed_work(&wb->dwork);
 	WARN_ON(!list_empty(&wb->work_list));
+	/*
+	 * Make sure bit gets cleared after shutdown is finished. Matches with
+	 * the barrier provided by test_and_clear_bit() above.
+	 */
+	smp_wmb();
+	clear_bit(WB_shutting_down, &wb->state);
 }
 
 static void wb_exit(struct bdi_writeback *wb)
@@ -370,6 +394,8 @@
 
 	fprop_local_destroy_percpu(&wb->completions);
 	wb_congested_put(wb->congested);
+	if (wb != &wb->bdi->wb)
+		bdi_put(wb->bdi);
 }
 
 #ifdef CONFIG_CGROUP_WRITEBACK
@@ -379,11 +405,9 @@
 /*
  * cgwb_lock protects bdi->cgwb_tree, bdi->cgwb_congested_tree,
  * blkcg->cgwb_list, and memcg->cgwb_list.  bdi->cgwb_tree is also RCU
- * protected.  cgwb_release_wait is used to wait for the completion of cgwb
- * releases from bdi destruction path.
+ * protected.
  */
 static DEFINE_SPINLOCK(cgwb_lock);
-static DECLARE_WAIT_QUEUE_HEAD(cgwb_release_wait);
 
 /**
  * wb_congested_get_create - get or create a wb_congested
@@ -436,7 +460,7 @@
 		return NULL;
 
 	atomic_set(&new_congested->refcnt, 0);
-	new_congested->bdi = bdi;
+	new_congested->__bdi = bdi;
 	new_congested->blkcg_id = blkcg_id;
 	goto retry;
 
@@ -464,10 +488,10 @@
 	}
 
 	/* bdi might already have been destroyed leaving @congested unlinked */
-	if (congested->bdi) {
+	if (congested->__bdi) {
 		rb_erase(&congested->rb_node,
-			 &congested->bdi->cgwb_congested_tree);
-		congested->bdi = NULL;
+			 &congested->__bdi->cgwb_congested_tree);
+		congested->__bdi = NULL;
 	}
 
 	spin_unlock_irqrestore(&cgwb_lock, flags);
@@ -478,11 +502,6 @@
 {
 	struct bdi_writeback *wb = container_of(work, struct bdi_writeback,
 						release_work);
-	struct backing_dev_info *bdi = wb->bdi;
-
-	spin_lock_irq(&cgwb_lock);
-	list_del_rcu(&wb->bdi_node);
-	spin_unlock_irq(&cgwb_lock);
 
 	wb_shutdown(wb);
 
@@ -493,9 +512,6 @@
 	percpu_ref_exit(&wb->refcnt);
 	wb_exit(wb);
 	kfree_rcu(wb, rcu);
-
-	if (atomic_dec_and_test(&bdi->usage_cnt))
-		wake_up_all(&cgwb_release_wait);
 }
 
 static void cgwb_release(struct percpu_ref *refcnt)
@@ -515,6 +531,13 @@
 	percpu_ref_kill(&wb->refcnt);
 }
 
+static void cgwb_remove_from_bdi_list(struct bdi_writeback *wb)
+{
+	spin_lock_irq(&cgwb_lock);
+	list_del_rcu(&wb->bdi_node);
+	spin_unlock_irq(&cgwb_lock);
+}
+
 static int cgwb_create(struct backing_dev_info *bdi,
 		       struct cgroup_subsys_state *memcg_css, gfp_t gfp)
 {
@@ -578,7 +601,6 @@
 		/* we might have raced another instance of this function */
 		ret = radix_tree_insert(&bdi->cgwb_tree, memcg_css->id, wb);
 		if (!ret) {
-			atomic_inc(&bdi->usage_cnt);
 			list_add_tail_rcu(&wb->bdi_node, &bdi->wb_list);
 			list_add(&wb->memcg_node, memcg_cgwb_list);
 			list_add(&wb->blkcg_node, blkcg_cgwb_list);
@@ -668,7 +690,6 @@
 
 	INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC);
 	bdi->cgwb_congested_tree = RB_ROOT;
-	atomic_set(&bdi->usage_cnt, 1);
 
 	ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
 	if (!ret) {
@@ -678,36 +699,26 @@
 	return ret;
 }
 
-static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
+static void cgwb_bdi_unregister(struct backing_dev_info *bdi)
 {
 	struct radix_tree_iter iter;
-	struct rb_node *rbn;
 	void **slot;
+	struct bdi_writeback *wb;
 
 	WARN_ON(test_bit(WB_registered, &bdi->wb.state));
 
 	spin_lock_irq(&cgwb_lock);
-
 	radix_tree_for_each_slot(slot, &bdi->cgwb_tree, &iter, 0)
 		cgwb_kill(*slot);
 
-	while ((rbn = rb_first(&bdi->cgwb_congested_tree))) {
-		struct bdi_writeback_congested *congested =
-			rb_entry(rbn, struct bdi_writeback_congested, rb_node);
-
-		rb_erase(rbn, &bdi->cgwb_congested_tree);
-		congested->bdi = NULL;	/* mark @congested unlinked */
+	while (!list_empty(&bdi->wb_list)) {
+		wb = list_first_entry(&bdi->wb_list, struct bdi_writeback,
+				      bdi_node);
+		spin_unlock_irq(&cgwb_lock);
+		wb_shutdown(wb);
+		spin_lock_irq(&cgwb_lock);
 	}
-
 	spin_unlock_irq(&cgwb_lock);
-
-	/*
-	 * All cgwb's and their congested states must be shutdown and
-	 * released before returning.  Drain the usage counter to wait for
-	 * all cgwb's and cgwb_congested's ever created on @bdi.
-	 */
-	atomic_dec(&bdi->usage_cnt);
-	wait_event(cgwb_release_wait, !atomic_read(&bdi->usage_cnt));
 }
 
 /**
@@ -747,6 +758,28 @@
 	spin_unlock_irq(&cgwb_lock);
 }
 
+static void cgwb_bdi_exit(struct backing_dev_info *bdi)
+{
+	struct rb_node *rbn;
+
+	spin_lock_irq(&cgwb_lock);
+	while ((rbn = rb_first(&bdi->cgwb_congested_tree))) {
+		struct bdi_writeback_congested *congested =
+			rb_entry(rbn, struct bdi_writeback_congested, rb_node);
+
+		rb_erase(rbn, &bdi->cgwb_congested_tree);
+		congested->__bdi = NULL;	/* mark @congested unlinked */
+	}
+	spin_unlock_irq(&cgwb_lock);
+}
+
+static void cgwb_bdi_register(struct backing_dev_info *bdi)
+{
+	spin_lock_irq(&cgwb_lock);
+	list_add_tail_rcu(&bdi->wb.bdi_node, &bdi->wb_list);
+	spin_unlock_irq(&cgwb_lock);
+}
+
 #else	/* CONFIG_CGROUP_WRITEBACK */
 
 static int cgwb_bdi_init(struct backing_dev_info *bdi)
@@ -767,11 +800,23 @@
 	return 0;
 }
 
-static void cgwb_bdi_destroy(struct backing_dev_info *bdi)
+static void cgwb_bdi_unregister(struct backing_dev_info *bdi) { }
+
+static void cgwb_bdi_exit(struct backing_dev_info *bdi)
 {
 	wb_congested_put(bdi->wb_congested);
 }
 
+static void cgwb_bdi_register(struct backing_dev_info *bdi)
+{
+	list_add_tail_rcu(&bdi->wb.bdi_node, &bdi->wb_list);
+}
+
+static void cgwb_remove_from_bdi_list(struct bdi_writeback *wb)
+{
+	list_del_rcu(&wb->bdi_node);
+}
+
 #endif	/* CONFIG_CGROUP_WRITEBACK */
 
 int bdi_init(struct backing_dev_info *bdi)
@@ -780,6 +825,7 @@
 
 	bdi->dev = NULL;
 
+	kref_init(&bdi->refcnt);
 	bdi->min_ratio = 0;
 	bdi->max_ratio = 100;
 	bdi->max_prop_frac = FPROP_FRAC_BASE;
@@ -789,12 +835,26 @@
 
 	ret = cgwb_bdi_init(bdi);
 
-	list_add_tail_rcu(&bdi->wb.bdi_node, &bdi->wb_list);
-
 	return ret;
 }
 EXPORT_SYMBOL(bdi_init);
 
+struct backing_dev_info *bdi_alloc_node(gfp_t gfp_mask, int node_id)
+{
+	struct backing_dev_info *bdi;
+
+	bdi = kmalloc_node(sizeof(struct backing_dev_info),
+			   gfp_mask | __GFP_ZERO, node_id);
+	if (!bdi)
+		return NULL;
+
+	if (bdi_init(bdi)) {
+		kfree(bdi);
+		return NULL;
+	}
+	return bdi;
+}
+
 int bdi_register(struct backing_dev_info *bdi, struct device *parent,
 		const char *fmt, ...)
 {
@@ -810,6 +870,7 @@
 	if (IS_ERR(dev))
 		return PTR_ERR(dev);
 
+	cgwb_bdi_register(bdi);
 	bdi->dev = dev;
 
 	bdi_debug_register(bdi, dev_name(dev));
@@ -838,6 +899,8 @@
 			MINOR(owner->devt));
 	if (rc)
 		return rc;
+	/* Leaking owner reference... */
+	WARN_ON(bdi->owner);
 	bdi->owner = owner;
 	get_device(owner);
 	return 0;
@@ -861,7 +924,7 @@
 	/* make sure nobody finds us on the bdi_list anymore */
 	bdi_remove_from_list(bdi);
 	wb_shutdown(&bdi->wb);
-	cgwb_bdi_destroy(bdi);
+	cgwb_bdi_unregister(bdi);
 
 	if (bdi->dev) {
 		bdi_debug_unregister(bdi);
@@ -875,10 +938,25 @@
 	}
 }
 
-void bdi_exit(struct backing_dev_info *bdi)
+static void bdi_exit(struct backing_dev_info *bdi)
 {
 	WARN_ON_ONCE(bdi->dev);
 	wb_exit(&bdi->wb);
+	cgwb_bdi_exit(bdi);
+}
+
+static void release_bdi(struct kref *ref)
+{
+	struct backing_dev_info *bdi =
+			container_of(ref, struct backing_dev_info, refcnt);
+
+	bdi_exit(bdi);
+	kfree(bdi);
+}
+
+void bdi_put(struct backing_dev_info *bdi)
+{
+	kref_put(&bdi->refcnt, release_bdi);
 }
 
 void bdi_destroy(struct backing_dev_info *bdi)
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index dd7817cd3..e6fbdf4 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -1987,11 +1987,11 @@
 	 * We want to write everything out, not just down to the dirty
 	 * threshold
 	 */
-	if (!bdi_has_dirty_io(&q->backing_dev_info))
+	if (!bdi_has_dirty_io(q->backing_dev_info))
 		return;
 
 	rcu_read_lock();
-	list_for_each_entry_rcu(wb, &q->backing_dev_info.wb_list, bdi_node)
+	list_for_each_entry_rcu(wb, &q->backing_dev_info->wb_list, bdi_node)
 		if (wb_has_dirty_io(wb))
 			wb_start_writeback(wb, nr_pages, true,
 					   WB_REASON_LAPTOP_TIMER);
diff --git a/net/dccp/proto.c b/net/dccp/proto.c
index b68168f..9d43c1f 100644
--- a/net/dccp/proto.c
+++ b/net/dccp/proto.c
@@ -259,6 +259,7 @@
 {
 	struct inet_connection_sock *icsk = inet_csk(sk);
 	struct inet_sock *inet = inet_sk(sk);
+	struct dccp_sock *dp = dccp_sk(sk);
 	int err = 0;
 	const int old_state = sk->sk_state;
 
@@ -278,6 +279,10 @@
 		sk->sk_err = ECONNRESET;
 
 	dccp_clear_xmit_timers(sk);
+	ccid_hc_rx_delete(dp->dccps_hc_rx_ccid, sk);
+	ccid_hc_tx_delete(dp->dccps_hc_tx_ccid, sk);
+	dp->dccps_hc_rx_ccid = NULL;
+	dp->dccps_hc_tx_ccid = NULL;
 
 	__skb_queue_purge(&sk->sk_receive_queue);
 	__skb_queue_purge(&sk->sk_write_queue);
diff --git a/net/rmnet_data/rmnet_data_handlers.c b/net/rmnet_data/rmnet_data_handlers.c
index 50dd516..98b2511 100644
--- a/net/rmnet_data/rmnet_data_handlers.c
+++ b/net/rmnet_data/rmnet_data_handlers.c
@@ -356,6 +356,7 @@
 			napi = get_current_napi_context();
 
 			skb_size = skb->len;
+			skb_get_hash(skb);
 			gro_res = napi_gro_receive(napi, skb);
 			trace_rmnet_gro_downlink(gro_res);
 			rmnet_optional_gro_flush(napi, ep, skb_size);
diff --git a/net/rmnet_data/rmnet_map_data.c b/net/rmnet_data/rmnet_map_data.c
index cc377bb..771a6b7 100644
--- a/net/rmnet_data/rmnet_map_data.c
+++ b/net/rmnet_data/rmnet_map_data.c
@@ -292,7 +292,7 @@
 		config->agg_count = 1;
 		getnstimeofday(&config->agg_time);
 		trace_rmnet_start_aggregation(skb);
-		rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_AGG_CPY_EXPAND);
+		dev_kfree_skb_any(skb);
 		goto schedule;
 	}
 	diff = timespec_sub(config->agg_last, config->agg_time);
@@ -321,7 +321,7 @@
 	dest_buff = skb_put(config->agg_skb, skb->len);
 	memcpy(dest_buff, skb->data, skb->len);
 	config->agg_count++;
-	rmnet_kfree_skb(skb, RMNET_STATS_SKBFREE_AGG_INTO_BUFF);
+	dev_kfree_skb_any(skb);
 
 schedule:
 	if (config->agg_state != RMNET_MAP_TXFER_SCHEDULED) {
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 8201e6d..95d5088 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1117,6 +1117,8 @@
 		     wdev->iftype == NL80211_IFTYPE_ADHOC) && !wdev->use_4addr)
 			dev->priv_flags |= IFF_DONT_BRIDGE;
 
+		INIT_WORK(&wdev->disconnect_wk, cfg80211_autodisconnect_wk);
+
 		nl80211_notify_iface(rdev, wdev, NL80211_CMD_NEW_INTERFACE);
 		break;
 	case NETDEV_GOING_DOWN:
@@ -1205,6 +1207,7 @@
 #ifdef CONFIG_CFG80211_WEXT
 			kzfree(wdev->wext.keys);
 #endif
+			flush_work(&wdev->disconnect_wk);
 		}
 		/*
 		 * synchronise (so that we won't find this netdev
diff --git a/net/wireless/core.h b/net/wireless/core.h
index c40f3de..478e37a 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -382,6 +382,7 @@
 		       struct cfg80211_roam_info *info);
 int cfg80211_mgd_wext_connect(struct cfg80211_registered_device *rdev,
 			      struct wireless_dev *wdev);
+void cfg80211_autodisconnect_wk(struct work_struct *work);
 
 /* SME implementation */
 void cfg80211_conn_work(struct work_struct *work);
diff --git a/net/wireless/mlme.c b/net/wireless/mlme.c
index 5499e9f..5f85a4e 100644
--- a/net/wireless/mlme.c
+++ b/net/wireless/mlme.c
@@ -350,6 +350,11 @@
 	     !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
 		return 0;
 
+	if (ether_addr_equal(wdev->disconnect_bssid, bssid) ||
+	    (wdev->current_bss &&
+	     ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
+		wdev->conn_owner_nlportid = 0;
+
 	return rdev_deauth(rdev, dev, &req);
 }
 
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 466aa7e..7cea430 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -434,6 +434,7 @@
 					.len = FILS_ERP_MAX_RRK_LEN },
 	[NL80211_ATTR_FILS_CACHE_ID] = { .len = 2 },
 	[NL80211_ATTR_PMK] = { .type = NLA_BINARY, .len = PMK_MAX_LEN },
+	[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT] = { .type = NLA_FLAG },
 };
 
 /* policy for the key attributes */
@@ -3787,9 +3788,10 @@
 			return false;
 		return true;
 	case NL80211_CMD_CONNECT:
-		/* SAE not supported yet */
-		if (auth_type == NL80211_AUTHTYPE_SAE)
+		if (!(rdev->wiphy.features & NL80211_FEATURE_SAE) &&
+		    auth_type == NL80211_AUTHTYPE_SAE)
 			return false;
+
 		/* FILS with SK PFS or PK not supported yet */
 		if (auth_type == NL80211_AUTHTYPE_FILS_SK_PFS ||
 		    auth_type == NL80211_AUTHTYPE_FILS_PK)
@@ -8129,8 +8131,17 @@
 	err = nl80211_crypto_settings(rdev, info, &req.crypto, 1);
 	if (!err) {
 		wdev_lock(dev->ieee80211_ptr);
+
 		err = cfg80211_mlme_assoc(rdev, dev, chan, bssid,
 					  ssid, ssid_len, &req);
+
+		if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+			dev->ieee80211_ptr->conn_owner_nlportid =
+				info->snd_portid;
+			memcpy(dev->ieee80211_ptr->disconnect_bssid,
+			       bssid, ETH_ALEN);
+		}
+
 		wdev_unlock(dev->ieee80211_ptr);
 	}
 
@@ -8878,12 +8889,32 @@
 		return -EINVAL;
 	}
 
+	if (nla_get_flag(info->attrs[NL80211_ATTR_EXTERNAL_AUTH_SUPPORT])) {
+		if (!info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+			return -EINVAL;
+		}
+		connect.flags |= CONNECT_REQ_EXTERNAL_AUTH_SUPPORT;
+	}
+
 	wdev_lock(dev->ieee80211_ptr);
+
 	err = cfg80211_connect(rdev, dev, &connect, connkeys,
 			       connect.prev_bssid);
-	wdev_unlock(dev->ieee80211_ptr);
 	if (err)
 		kzfree(connkeys);
+
+	if (!err && info->attrs[NL80211_ATTR_SOCKET_OWNER]) {
+		dev->ieee80211_ptr->conn_owner_nlportid = info->snd_portid;
+		if (connect.bssid)
+			memcpy(dev->ieee80211_ptr->disconnect_bssid,
+			       connect.bssid, ETH_ALEN);
+		else
+			memset(dev->ieee80211_ptr->disconnect_bssid,
+			       0, ETH_ALEN);
+	}
+
+	wdev_unlock(dev->ieee80211_ptr);
+
 	return err;
 }
 
@@ -12021,6 +12052,41 @@
 	return rdev_set_multicast_to_unicast(rdev, dev, enabled);
 }
 
+static int nl80211_external_auth(struct sk_buff *skb, struct genl_info *info)
+{
+	struct cfg80211_registered_device *rdev = info->user_ptr[0];
+	struct net_device *dev = info->user_ptr[1];
+	struct cfg80211_external_auth_params params;
+
+	if (rdev->ops->external_auth)
+		return -EOPNOTSUPP;
+
+	if (!info->attrs[NL80211_ATTR_SSID])
+		return -EINVAL;
+
+	if (!info->attrs[NL80211_ATTR_BSSID])
+		return -EINVAL;
+
+	if (!info->attrs[NL80211_ATTR_STATUS_CODE])
+		return -EINVAL;
+
+	memset(&params, 0, sizeof(params));
+
+	params.ssid.ssid_len = nla_len(info->attrs[NL80211_ATTR_SSID]);
+	if (params.ssid.ssid_len == 0 ||
+	    params.ssid.ssid_len > IEEE80211_MAX_SSID_LEN)
+		return -EINVAL;
+	memcpy(params.ssid.ssid, nla_data(info->attrs[NL80211_ATTR_SSID]),
+	       params.ssid.ssid_len);
+
+	memcpy(params.bssid, nla_data(info->attrs[NL80211_ATTR_BSSID]),
+	       ETH_ALEN);
+
+	params.status = nla_get_u16(info->attrs[NL80211_ATTR_STATUS_CODE]);
+
+	return rdev_external_auth(rdev, dev, &params);
+}
+
 #define NL80211_FLAG_NEED_WIPHY		0x01
 #define NL80211_FLAG_NEED_NETDEV	0x02
 #define NL80211_FLAG_NEED_RTNL		0x04
@@ -12910,6 +12976,14 @@
 		.internal_flags = NL80211_FLAG_NEED_NETDEV |
 				  NL80211_FLAG_NEED_RTNL,
 	},
+	{
+		.cmd = NL80211_CMD_EXTERNAL_AUTH,
+		.doit = nl80211_external_auth,
+		.policy = nl80211_policy,
+		.flags = GENL_ADMIN_PERM,
+		.internal_flags = NL80211_FLAG_NEED_NETDEV_UP |
+				  NL80211_FLAG_NEED_RTNL,
+	},
 };
 
 /* notification functions */
@@ -14737,6 +14811,8 @@
 
 			if (wdev->owner_nlportid == notify->portid)
 				schedule_destroy_work = true;
+			else if (wdev->conn_owner_nlportid == notify->portid)
+				schedule_work(&wdev->disconnect_wk);
 		}
 
 		spin_lock_bh(&rdev->beacon_registrations_lock);
@@ -14901,6 +14977,47 @@
 	nlmsg_free(msg);
 }
 
+int cfg80211_external_auth_request(struct net_device *dev,
+				   struct cfg80211_external_auth_params *params,
+				   gfp_t gfp)
+{
+	struct wireless_dev *wdev = dev->ieee80211_ptr;
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+	struct sk_buff *msg;
+	void *hdr;
+
+	if (!wdev->conn_owner_nlportid)
+		return -EINVAL;
+
+	msg = nlmsg_new(NLMSG_DEFAULT_SIZE, gfp);
+	if (!msg)
+		return -ENOMEM;
+
+	hdr = nl80211hdr_put(msg, 0, 0, 0, NL80211_CMD_EXTERNAL_AUTH);
+	if (!hdr)
+		goto nla_put_failure;
+
+	if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) ||
+	    nla_put_u32(msg, NL80211_ATTR_IFINDEX, dev->ifindex) ||
+	    nla_put_u32(msg, NL80211_ATTR_AKM_SUITES, params->key_mgmt_suite) ||
+	    nla_put_u32(msg, NL80211_ATTR_EXTERNAL_AUTH_ACTION,
+			params->action) ||
+	    nla_put(msg, NL80211_ATTR_BSSID, ETH_ALEN, params->bssid) ||
+	    nla_put(msg, NL80211_ATTR_SSID, params->ssid.ssid_len,
+		    params->ssid.ssid))
+		goto nla_put_failure;
+
+	genlmsg_end(msg, hdr);
+	genlmsg_unicast(wiphy_net(&rdev->wiphy), msg,
+			wdev->conn_owner_nlportid);
+	return 0;
+
+ nla_put_failure:
+	nlmsg_free(msg);
+	return -ENOBUFS;
+}
+EXPORT_SYMBOL(cfg80211_external_auth_request);
+
 /* initialisation/exit functions */
 
 int nl80211_init(void)
diff --git a/net/wireless/rdev-ops.h b/net/wireless/rdev-ops.h
index 2f42507..091806d 100644
--- a/net/wireless/rdev-ops.h
+++ b/net/wireless/rdev-ops.h
@@ -1153,4 +1153,19 @@
 	trace_rdev_return_int(&rdev->wiphy, ret);
 	return ret;
 }
+
+static inline int
+rdev_external_auth(struct cfg80211_registered_device *rdev,
+		   struct net_device *dev,
+		   struct cfg80211_external_auth_params *params)
+{
+	int ret = -EOPNOTSUPP;
+
+	trace_rdev_external_auth(&rdev->wiphy, dev, params);
+	if (rdev->ops->external_auth)
+		ret = rdev->ops->external_auth(&rdev->wiphy, dev, params);
+	trace_rdev_return_int(&rdev->wiphy, ret);
+	return ret;
+}
+
 #endif /* __CFG80211_RDEV_OPS */
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index d414049..2d64e0f 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -763,6 +763,7 @@
 		kzfree(wdev->connect_keys);
 		wdev->connect_keys = NULL;
 		wdev->ssid_len = 0;
+		wdev->conn_owner_nlportid = 0;
 		if (cr->bss) {
 			cfg80211_unhold_bss(bss_from_pub(cr->bss));
 			cfg80211_put_bss(wdev->wiphy, cr->bss);
@@ -1010,6 +1011,7 @@
 
 	wdev->current_bss = NULL;
 	wdev->ssid_len = 0;
+	wdev->conn_owner_nlportid = 0;
 
 	nl80211_send_disconnected(rdev, dev, reason, ie, ie_len, from_ap);
 
@@ -1182,6 +1184,8 @@
 	kzfree(wdev->connect_keys);
 	wdev->connect_keys = NULL;
 
+	wdev->conn_owner_nlportid = 0;
+
 	if (wdev->conn)
 		err = cfg80211_sme_disconnect(wdev, reason);
 	else if (!rdev->ops->disconnect)
@@ -1199,3 +1203,32 @@
 
 	return err;
 }
+
+/*
+ * Used to clean up after the connection / connection attempt owner socket
+ * disconnects
+ */
+void cfg80211_autodisconnect_wk(struct work_struct *work)
+{
+	struct wireless_dev *wdev =
+		container_of(work, struct wireless_dev, disconnect_wk);
+	struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
+
+	wdev_lock(wdev);
+
+	if (wdev->conn_owner_nlportid) {
+		/*
+		 * Use disconnect_bssid if still connecting and ops->disconnect
+		 * not implemented.  Otherwise we can use cfg80211_disconnect.
+		 */
+		if (rdev->ops->disconnect || wdev->current_bss)
+			cfg80211_disconnect(rdev, wdev->netdev,
+					    WLAN_REASON_DEAUTH_LEAVING, true);
+		else
+			cfg80211_mlme_deauth(rdev, wdev->netdev,
+					     wdev->disconnect_bssid, NULL, 0,
+					     WLAN_REASON_DEAUTH_LEAVING, false);
+	}
+
+	wdev_unlock(wdev);
+}
diff --git a/net/wireless/trace.h b/net/wireless/trace.h
index ea1b47e..80ea75a 100644
--- a/net/wireless/trace.h
+++ b/net/wireless/trace.h
@@ -2230,6 +2230,29 @@
 		  WIPHY_PR_ARG, NETDEV_PR_ARG, MAC_PR_ARG(addr))
 );
 
+TRACE_EVENT(rdev_external_auth,
+	    TP_PROTO(struct wiphy *wiphy, struct net_device *netdev,
+		     struct cfg80211_external_auth_params *params),
+	    TP_ARGS(wiphy, netdev, params),
+	    TP_STRUCT__entry(WIPHY_ENTRY
+			     NETDEV_ENTRY
+			     MAC_ENTRY(bssid)
+			     __array(u8, ssid, IEEE80211_MAX_SSID_LEN + 1)
+			     __field(u16, status)
+	    ),
+	    TP_fast_assign(WIPHY_ASSIGN;
+			   NETDEV_ASSIGN;
+			   MAC_ASSIGN(bssid, params->bssid);
+			   memset(__entry->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
+			   memcpy(__entry->ssid, params->ssid.ssid,
+				  params->ssid.ssid_len);
+			   __entry->status = params->status;
+	    ),
+	    TP_printk(WIPHY_PR_FMT ", " NETDEV_PR_FMT ", bssid: " MAC_PR_FMT
+		      ", ssid: %s, status: %u", WIPHY_PR_ARG, NETDEV_PR_ARG,
+		      __entry->bssid, __entry->ssid, __entry->status)
+);
+
 /*************************************************************
  *	     cfg80211 exported functions traces		     *
  *************************************************************/
diff --git a/sound/soc/intel/skylake/skl-nhlt.c b/sound/soc/intel/skylake/skl-nhlt.c
index 3f8e6f0..dcf0369 100644
--- a/sound/soc/intel/skylake/skl-nhlt.c
+++ b/sound/soc/intel/skylake/skl-nhlt.c
@@ -41,7 +41,8 @@
 	obj = acpi_evaluate_dsm(handle, OSC_UUID, 1, 1, NULL);
 	if (obj && obj->type == ACPI_TYPE_BUFFER) {
 		nhlt_ptr = (struct nhlt_resource_desc  *)obj->buffer.pointer;
-		nhlt_table = (struct nhlt_acpi_table *)
+		if (nhlt_ptr->length)
+			nhlt_table = (struct nhlt_acpi_table *)
 				memremap(nhlt_ptr->min_addr, nhlt_ptr->length,
 				MEMREMAP_WB);
 		ACPI_FREE(obj);
diff --git a/sound/soc/rockchip/rockchip_i2s.c b/sound/soc/rockchip/rockchip_i2s.c
index 974915c..08bfee4 100644
--- a/sound/soc/rockchip/rockchip_i2s.c
+++ b/sound/soc/rockchip/rockchip_i2s.c
@@ -476,6 +476,7 @@
 	case I2S_INTCR:
 	case I2S_XFER:
 	case I2S_CLR:
+	case I2S_TXDR:
 	case I2S_RXDR:
 	case I2S_FIFOLR:
 	case I2S_INTSR:
@@ -490,6 +491,9 @@
 	switch (reg) {
 	case I2S_INTSR:
 	case I2S_CLR:
+	case I2S_FIFOLR:
+	case I2S_TXDR:
+	case I2S_RXDR:
 		return true;
 	default:
 		return false;
@@ -499,6 +503,8 @@
 static bool rockchip_i2s_precious_reg(struct device *dev, unsigned int reg)
 {
 	switch (reg) {
+	case I2S_RXDR:
+		return true;
 	default:
 		return false;
 	}