Merge "msm: pm-8x60: Unconditionally support WFI hotplug" into msm-3.4
diff --git a/Documentation/devicetree/bindings/coresight/coresight.txt b/Documentation/devicetree/bindings/coresight/coresight.txt
new file mode 100644
index 0000000..c584073
--- /dev/null
+++ b/Documentation/devicetree/bindings/coresight/coresight.txt
@@ -0,0 +1,106 @@
+* CoreSight Components
+
+CoreSight components are compliant with the ARM CoreSight architecture
+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
+- reg : physical base address and length of the register set(s) of the component
+- 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
+
+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.
+
+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
+
+Examples:
+
+1. Sinks
+	tmc_etr: tmc@fc322000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc322000 0x1000>;
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+		coresight-default-sink;
+	};
+
+	tpiu: tpiu@fc318000 {
+		compatible = "arm,coresight-tpiu";
+		reg = <0xfc318000 0x1000>;
+
+		coresight-id = <1>;
+		coresight-name = "coresight-tpiu";
+		coresight-nr-inports = <1>;
+	};
+
+2. Links
+	funnel_merg: funnel@fc31b000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc31b000 0x1000>;
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-merg";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in0: funnel@fc319000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc319000 0x1000>;
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <0>;
+	};
+
+3. Sources
+	stm: stm@fc321000 {
+		compatible = "arm,coresight-stm";
+		reg = <0xfc321000 0x1000>,
+		      <0xfa280000 0x180000>;
+
+		coresight-id = <9>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <7>;
+	};
+
+	etm0: etm@fc33c000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33c000 0x1000>;
+
+		coresight-id = <10>;
+		coresight-name = "coresight-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_kpss>;
+		coresight-child-ports = <0>;
+	};
diff --git a/Documentation/devicetree/bindings/gpio/gpio-msm.txt b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
new file mode 100644
index 0000000..359d700
--- /dev/null
+++ b/Documentation/devicetree/bindings/gpio/gpio-msm.txt
@@ -0,0 +1,39 @@
+MSM GPIO controller bindings
+
+Required properties:
+- compatible:
+  - "qcom,msm-gpio" for MSM controllers
+- #gpio-cells : Should be two.
+  - first cell is the pin number
+  - second cell is used to specify optional parameters (unused)
+- gpio-controller : Marks the device node as a GPIO controller.
+- #interrupt-cells : Should be 2.
+- interrupt-controller: Mark the device node as an interrupt controller
+
+Example:
+
+	msmgpio: gpio@fd510000 {
+		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
+		interrupt-controller;
+		#interrupt-cells = <2>;
+		reg = <0xfd510000 0x4000>;
+	};
+
+To specify gpios for a device:
+
+	device1@f991f000 {
+		compatible = "qcom,msm-device-v1";
+		reg = <0xf991f000 0x1000>;
+		gpios = <&msmgpio 45 0>;
+		cs-gpios = <&msmgpio 46 0>;
+	};
+
+45, 46 - gpio numbers.
+The driver for device1 can call of_get_gpio() to extract the
+gpio45. In order to extract gpio46, the driver needs to call
+of_get_named_gpio with "cs-gpios" as the name parameter.
+Please refer to the file: include/linux/of_gpio.h for the
+complete list of APIs the driver can use to extract gpio
+information from the device tree.
diff --git a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
index 95e7f88..32c9c35 100644
--- a/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
+++ b/Documentation/devicetree/bindings/pil/pil-q6v5-mss.txt
@@ -7,11 +7,12 @@
 
 Required properties:
 - compatible:	      Must be "qcom,pil-q6v5-mss"
-- reg:		      Four pairs of physical base addresses and region sizes of
+- reg:		      Five pairs of physical base addresses and region sizes of
 		      memory mapped registers. The first region corresponds to
 		      QDSP6SS_PUB, the second to the bus port halt register
-		      base, the third to the MSS_RELAY_MSG_BUFFER base, and the
-		      fourth to the MSS_RESTART register.
+		      base, the third to the MSS_RELAY_MSG_BUFFER base, the
+		      fourth to the MSS_RESTART register, and the fifth to the
+		      MSS_CLAMP_IO register.
 - vdd_mss-supply:     Reference to the regulator that supplies the processor.
 - qcom,firmware-name: Base name of the firmware image. Ex. "mdsp"
 - qcom,pil-self-auth: <0> if the hardware does not require self-authenticating
@@ -24,7 +25,8 @@
 		reg = <0xfc880000 0x100>,
 		      <0xfd485000 0x400>,
 		      <0xfc820000 0x020>,
-		      <0xfc401680 0x004>;
+		      <0xfc401680 0x004>,
+		      <0xfc980008 0x004>;
 		vdd_mss-supply = <&pm8841_s3>;
 
 		qcom,firmware-name = "mba";
diff --git a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
index c9bc284..2116888 100644
--- a/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
+++ b/Documentation/devicetree/bindings/regulator/qpnp-regulator.txt
@@ -76,11 +76,13 @@
 					1 = 0.25 uA
 					2 = 0.55 uA
 					3 = 0.75 uA
-
-- spmi-dev-container:	This specifies that all the device nodes specified
-	within this node should have their resources coalesced into a single
-	spmi_device.  This is used to specify all SPMI peripherals that
-	logically make up a single regulator device.
+- qcom,force-type: 	       Override the type and subtype register values. Useful for some
+				regulators that have invalid types advertised by the hardware.
+				The format is two unsigned integers of the form <type subtype>.
+- spmi-dev-container:	       Specifies that all the device nodes specified
+				within this node should have their resources coalesced into a
+				single spmi_device.  This is used to specify all SPMI peripherals
+				that logically make up a single regulator device.
 
 Note, if a given optional qcom,* binding is not present, then the qpnp-regulator
 driver will leave that feature in the default hardware state.
diff --git a/Documentation/devicetree/bindings/sound/taiko_codec.txt b/Documentation/devicetree/bindings/sound/taiko_codec.txt
new file mode 100644
index 0000000..9f3719b
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/taiko_codec.txt
@@ -0,0 +1,82 @@
+taiko audio CODEC
+
+Required properties:
+
+  - compatible : "qcom,taiko-slim-pgd"
+  - elemental-addr: codec slimbus slave PGD enumeration address.(48 bits)
+
+  - qcom,cdc-reset-gpio: gpio used for codec SOC reset.
+
+  - <supply-name>-supply: phandle to the regulator device tree node
+  - qcom,<supply-name>-voltage -  specifies voltage levels for supply. Should be
+       specified in pairs (min, max), units mV.
+  - qcom,<supply-name>-current - specifies max current in mA that can drawn
+       from the <supply-name>.
+
+    above three properties with "supply-name" set to  "qcom,cdc-vdd-buck", "qcom,cdc-vdd-tx-h",
+     "qcom,cdc-vdd-rx-h", "qcom,cdc-vddpx-1", "qcom,cdc-vdd-a-1p2v", "qcom,cdc-vddcx-1",
+     "qcom,cdc-vddcx-2" should be present.
+
+ - qcom,cdc-micbias-ldoh-v - LDOH output in volts ( should be 1.95 V and 3.00 V).
+
+ - qcom,cdc-micbias-cfilt1-mv - cfilt1 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt2-mv - cfilt2 output voltage in milli volts.
+ - qcom,cdc-micbias-cfilt3-mv - cfilt3 output voltage in milli volts.
+   cfilt volatge can be set to max of qcom,cdc-micbias-ldoh-v - 0.15V.
+
+ - qcom,cdc-micbias1-cfilt-sel = cfilt to use for micbias1 (should be from 1 to 3).
+ - qcom,cdc-micbias2-cfilt-sel = cfilt to use for micbias2 (should be from 1 to 3).
+ - qcom,cdc-micbias3-cfilt-sel = cfilt to use for micbias3 (should be from 1 to 3).
+ - qcom,cdc-micbias4-cfilt-sel = cfilt to use for micbias4 (should be from 1 to 3).
+
+ - qcom,cdc-slim-ifd-dev - namme of the codec slim interface device.
+ - qcom,cdc-slim-ifd-elemental-addr - codec slimbus slave interface device
+				     enumeration address.
+Example:
+
+taiko_codec {
+	compatible = "qcom,taiko-slim-pgd";
+	elemental-addr = [00 01 A0 00 17 02];
+
+	qcom,cdc-reset-gpio = <&msmgpio 63 0>;
+
+	cdc-vdd-buck-supply = <&pm8941_s2>;
+	qcom,cdc-vdd-buck-voltage = <2150000 2150000>;
+	qcom,cdc-vdd-buck-current = <500000>;
+
+	cdc-vdd-tx-h-supply = <&pm8941_s3>;
+	qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+	qcom,cdc-vdd-tx-h-current = <200000>;
+
+	cdc-vdd-rx-h-supply = <&pm8941_s3>;
+	qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+	qcom,cdc-vdd-rx-h-current = <200000>;
+
+	cdc-vddpx-1-supply = <&pm8941_s3>;
+	qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+	qcom,cdc-vddpx-1-current = <5000>;
+
+	cdc-vdd-a-1p2v-supply = <&pm8941_l1>;
+	qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+	qcom,cdc-vdd-a-1p2v-current = <5000>;
+
+	cdc-vddcx-1-supply = <&pm8941_l1>;
+	qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+	qcom,cdc-vddcx-1-current = <5000>;
+
+	cdc-vddcx-2-supply = <&pm8941_l1>;
+	qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+	qcom,cdc-vddcx-2-current = <5000>;
+
+	qcom,cdc-micbias-ldoh-v = <0x3>;
+	qcom,cdc-micbias-cfilt1-mv = <1800>;
+	qcom,cdc-micbias-cfilt2-mv = <2700>;
+	qcom,cdc-micbias-cfilt3-mv = <1800>;
+	qcom,cdc-micbias1-cfilt-sel = <0x0>;
+	qcom,cdc-micbias2-cfilt-sel = <0x1>;
+	qcom,cdc-micbias3-cfilt-sel = <0x2>;
+	qcom,cdc-micbias4-cfilt-sel = <0x2>;
+
+	qcom,cdc-slim-ifd = "taiko-slim-ifd";
+	qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+};
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 8fb7a8e..7930de5 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -1849,9 +1849,6 @@
 config ARCH_MEMORY_REMOVE
 	def_bool n
 
-config ARCH_POPULATES_NODE_MAP
-	def_bool n
-
 config ENABLE_DMM
 	def_bool n
 
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index d84c8e0..967d5ec 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -91,6 +91,7 @@
 			compatible = "qcom,qpnp-regulator";
 			reg = <0x1700 0x300>;
 			status = "disabled";
+			qcom,force-type = <0x1c 0x08>;
 
 			qcom,ctl@1700 {
 				reg = <0x1700 0x100>;
@@ -131,6 +132,7 @@
 			compatible = "qcom,qpnp-regulator";
 			reg = <0x1d00 0x300>;
 			status = "disabled";
+			qcom,force-type = <0x1c 0x08>;
 
 			qcom,ctl@1d00 {
 				reg = <0x1d00 0x100>;
@@ -151,6 +153,7 @@
 			compatible = "qcom,qpnp-regulator";
 			reg = <0x2000 0x300>;
 			status = "disabled";
+			qcom,force-type = <0x1c 0x08>;
 
 			qcom,ctl@0 {
 				reg = <0x2000 0x100>;
@@ -171,6 +174,7 @@
 			compatible = "qcom,qpnp-regulator";
 			reg = <0x2300 0x300>;
 			status = "disabled";
+			qcom,force-type = <0x1c 0x08>;
 
 			qcom,ctl@2300 {
 				reg = <0x2300 0x100>;
@@ -191,6 +195,7 @@
 			compatible = "qcom,qpnp-regulator";
 			reg = <0x2600 0x300>;
 			status = "disabled";
+			qcom,force-type = <0x1c 0x08>;
 
 			qcom,ctl@2600 {
 				reg = <0x2600 0x100>;
@@ -211,6 +216,7 @@
 			compatible = "qcom,qpnp-regulator";
 			reg = <0x2900 0x300>;
 			status = "disabled";
+			qcom,force-type = <0x1c 0x08>;
 
 			qcom,ctl@2900 {
 				reg = <0x2900 0x100>;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index cb1ac34..ee0a264 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -350,6 +350,72 @@
 				qcom,hw-settle-time = <0>;
 				qcom,fast-avg-setup = <0>;
 			};
+
+			chan@2 {
+				label = "vchg_sns";
+				qcom,channel-num = <2>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <6>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@5 {
+				label = "vcoin";
+				qcom,channel-num = <5>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <3>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@6 {
+				label = "vbat_sns";
+				qcom,channel-num = <6>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <3>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@7 {
+				label = "vph_pwr";
+				qcom,channel-num = <7>;
+				qcom,decimation = <0>;
+				qcom,pre-div-channel-scaling = <3>;
+				qcom,calibration-type = "absolute";
+				qcom,scale-function = <0>;
+				qcom,hw-settle-time = <0>;
+				qcom,fast-avg-setup = <0>;
+			};
+
+			chan@9 {
+				label = "ref_625mv";
+				qcom,channel-num = <9>;
+				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@10 {
+				label = "ref_1125v";
+				qcom,channel-num = <10>;
+				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>;
+			};
 		};
 
 		iadc@3600 {
@@ -425,7 +491,7 @@
 			#address-cells = <1>;
 			#size-cells = <1>;
 			compatible = "qcom,qpnp-regulator";
-			reg = <0x1400 0x300>;
+			reg = <0x1a00 0x300>;
 			status = "disabled";
 
 			qcom,ctl@1a00 {
@@ -478,6 +544,7 @@
 			regulator-name = "8941_l5";
 			reg = <0x4400 0x100>;
 			compatible = "qcom,qpnp-regulator";
+			qcom,force-type = <0x04 0x10>;
 			status = "disabled";
 		};
 
@@ -492,6 +559,7 @@
 			regulator-name = "8941_l7";
 			reg = <0x4600 0x100>;
 			compatible = "qcom,qpnp-regulator";
+			qcom,force-type = <0x04 0x10>;
 			status = "disabled";
 		};
 
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index 29edf30..bfe24d2 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -17,5 +17,9 @@
 / {
 	model = "Qualcomm MSM 8974 CDP";
 	compatible = "qcom,msm8974-cdp", "qcom,msm8974";
-	qcom,msm-id = <126 1 0>;
+	qcom,msm-id = <126 1 0>, <126 8 0>;
+
+	serial@f991e000 {
+		status = "ok";
+	};
 };
diff --git a/arch/arm/boot/dts/msm8974-coresight.dtsi b/arch/arm/boot/dts/msm8974-coresight.dtsi
new file mode 100644
index 0000000..c28ef9e
--- /dev/null
+++ b/arch/arm/boot/dts/msm8974-coresight.dtsi
@@ -0,0 +1,177 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+/ {
+	tmc_etr: tmc@fc322000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc322000 0x1000>;
+
+		coresight-id = <0>;
+		coresight-name = "coresight-tmc-etr";
+		coresight-nr-inports = <1>;
+		coresight-default-sink;
+	};
+
+	tpiu: tpiu@fc318000 {
+		compatible = "arm,coresight-tpiu";
+		reg = <0xfc318000 0x1000>;
+
+		coresight-id = <1>;
+		coresight-name = "coresight-tpiu";
+		coresight-nr-inports = <1>;
+	};
+
+	replicator: replicator@fc31c000 {
+		compatible = "qcom,coresight-replicator";
+		reg = <0xfc31c000 0x1000>;
+
+		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>;
+	};
+
+	tmc_etf: tmc@fc307000 {
+		compatible = "arm,coresight-tmc";
+		reg = <0xfc307000 0x1000>;
+
+		coresight-id = <3>;
+		coresight-name = "coresight-tmc-etf";
+		coresight-nr-inports = <1>;
+		coresight-outports = <0>;
+		coresight-child-list = <&replicator>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_merg: funnel@fc31b000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc31b000 0x1000>;
+
+		coresight-id = <4>;
+		coresight-name = "coresight-funnel-merg";
+		coresight-nr-inports = <2>;
+		coresight-outports = <0>;
+		coresight-child-list = <&tmc_etf>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in0: funnel@fc319000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc319000 0x1000>;
+
+		coresight-id = <5>;
+		coresight-name = "coresight-funnel-in0";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <0>;
+	};
+
+	funnel_in1: funnel@fc31a000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc31a000 0x1000>;
+
+		coresight-id = <6>;
+		coresight-name = "coresight-funnel-in1";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_merg>;
+		coresight-child-ports = <1>;
+	};
+
+	funnel_kpss: funnel@fc345000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc345000 0x1000>;
+
+		coresight-id = <7>;
+		coresight-name = "coresight-funnel-kpss";
+		coresight-nr-inports = <4>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <5>;
+	};
+
+	funnel_mmss: funnel@fc364000 {
+		compatible = "arm,coresight-funnel";
+		reg = <0xfc364000 0x1000>;
+
+		coresight-id = <8>;
+		coresight-name = "coresight-funnel-mmss";
+		coresight-nr-inports = <8>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <1>;
+	};
+
+	stm: stm@fc321000 {
+		compatible = "arm,coresight-stm";
+		reg = <0xfc321000 0x1000>,
+		      <0xfa280000 0x180000>;
+
+		coresight-id = <9>;
+		coresight-name = "coresight-stm";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_in1>;
+		coresight-child-ports = <7>;
+	};
+
+	etm0: etm@fc33c000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33c000 0x1000>;
+
+		coresight-id = <10>;
+		coresight-name = "coresight-etm0";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_kpss>;
+		coresight-child-ports = <0>;
+	};
+
+	etm1: etm@fc33d000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33d000 0x1000>;
+
+		coresight-id = <11>;
+		coresight-name = "coresight-etm1";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_kpss>;
+		coresight-child-ports = <1>;
+	};
+
+	etm2: etm@fc33e000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33e000 0x1000>;
+
+		coresight-id = <12>;
+		coresight-name = "coresight-etm2";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_kpss>;
+		coresight-child-ports = <2>;
+	};
+
+	etm3: etm@fc33f000 {
+		compatible = "arm,coresight-etm";
+		reg = <0xfc33f000 0x1000>;
+
+		coresight-id = <13>;
+		coresight-name = "coresight-etm3";
+		coresight-nr-inports = <0>;
+		coresight-outports = <0>;
+		coresight-child-list = <&funnel_kpss>;
+		coresight-child-ports = <3>;
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-regulator.dtsi b/arch/arm/boot/dts/msm8974-regulator.dtsi
index a187223..eb269eb 100644
--- a/arch/arm/boot/dts/msm8974-regulator.dtsi
+++ b/arch/arm/boot/dts/msm8974-regulator.dtsi
@@ -10,13 +10,38 @@
  * GNU General Public License for more details.
  */
 
-
-/* QPNP controlled regulators: */
-
 &spmi_bus {
-
 	qcom,pm8941@1 {
 
+		pm8941_s1: regulator@1400 {
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			status = "okay";
+		};
+
+		regulator@1700 {
+			regulator-min-microvolt = <2150000>;
+			regulator-max-microvolt = <2150000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+			regulator-name = "8941_s2_local";
+			regulator-always-on;
+			qcom,system-load = <100000>;
+		};
+
+		pm8941_s3: regulator@1a00 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			status = "okay";
+		};
+
 		pm8941_boost: regulator@a000 {
 			regulator-min-microvolt = <5000000>;
 			regulator-max-microvolt = <5000000>;
@@ -24,6 +49,216 @@
 			status = "okay";
 		};
 
+		pm8941_l1: regulator@4000 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			status = "okay";
+		};
+
+		pm8941_l2: regulator@4100 {
+			parent-supply = <&pm8941_s3>;
+			regulator-min-microvolt = <1200000>;
+			regulator-max-microvolt = <1200000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l3: regulator@4200 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l4: regulator@4300 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1225000>;
+			regulator-max-microvolt = <1225000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l6: regulator@4500 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l8: regulator@4700 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l9: regulator@4800 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l10: regulator@4900 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l11: regulator@4a00 {
+			parent-supply = <&pm8941_s1>;
+			regulator-min-microvolt = <1300000>;
+			regulator-max-microvolt = <1300000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		regulator@4b00 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+			regulator-name = "8941_l12_local";
+			regulator-always-on;
+			qcom,system-load = <100000>;
+		};
+
+		pm8941_l13: regulator@4c00 {
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l14: regulator@4d00 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <1800000>;
+			regulator-max-microvolt = <1800000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l15: regulator@4e00 {
+			parent-supply = <&pm8941_s2>;
+			regulator-min-microvolt = <2050000>;
+			regulator-max-microvolt = <2050000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l16: regulator@4f00 {
+			regulator-min-microvolt = <2700000>;
+			regulator-max-microvolt = <2700000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l17: regulator@5000 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l18: regulator@5100 {
+			regulator-min-microvolt = <2850000>;
+			regulator-max-microvolt = <2850000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l19: regulator@5200 {
+			regulator-min-microvolt = <2900000>;
+			regulator-max-microvolt = <2900000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l20: regulator@5300 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l21: regulator@5400 {
+			regulator-min-microvolt = <2950000>;
+			regulator-max-microvolt = <2950000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l22: regulator@5500 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l23: regulator@5600 {
+			regulator-min-microvolt = <3000000>;
+			regulator-max-microvolt = <3000000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_l24: regulator@5700 {
+			regulator-min-microvolt = <3075000>;
+			regulator-max-microvolt = <3075000>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_lvs1: regulator@8000 {
+			parent-supply = <&pm8941_s3>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_lvs2: regulator@8100 {
+			parent-supply = <&pm8941_s3>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
+		pm8941_lvs3: regulator@8200 {
+			parent-supply = <&pm8941_s3>;
+			qcom,enable-time = <200>;
+			qcom,pull-down-enable = <1>;
+			status = "okay";
+		};
+
 		pm8941_mvs1: regulator@8300 {
 			parent-supply = <&pm8941_boost>;
 			qcom,enable-time = <200>;
@@ -41,34 +276,40 @@
 
 	qcom,pm8841@5 {
 
-		pm8841_s5: regulator@2000 {
-			regulator-min-microvolt = <850000>;
-			regulator-max-microvolt = <1100000>;
+		regulator@1400 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			status = "okay";
+			regulator-name = "8841_s1_local";
+			qcom,system-load = <100000>;
+		};
+
+		regulator@1700 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
+			qcom,enable-time = <500>;
+			qcom,pull-down-enable = <1>;
+			regulator-always-on;
+			regulator-name = "8841_s2_local";
+			qcom,system-load = <100000>;
+			status = "okay";
+		};
+
+		pm8841_s3: regulator@1a00 {
+			regulator-min-microvolt = <1050000>;
+			regulator-max-microvolt = <1050000>;
 			qcom,enable-time = <500>;
 			qcom,pull-down-enable = <1>;
 			regulator-always-on;
 			status = "okay";
 		};
 
-		pm8841_s6: regulator@2300 {
-			regulator-min-microvolt = <850000>;
-			regulator-max-microvolt = <1100000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8841_s7: regulator@2600 {
-			regulator-min-microvolt = <850000>;
-			regulator-max-microvolt = <1100000>;
-			qcom,enable-time = <500>;
-			qcom,pull-down-enable = <1>;
-			status = "okay";
-		};
-
-		pm8841_s8: regulator@2900 {
-			regulator-min-microvolt = <850000>;
-			regulator-max-microvolt = <1100000>;
+		pm8841_s4: regulator@1d00 {
+			regulator-min-microvolt = <900000>;
+			regulator-max-microvolt = <900000>;
 			qcom,enable-time = <500>;
 			qcom,pull-down-enable = <1>;
 			status = "okay";
@@ -76,7 +317,6 @@
 	};
 };
 
-
 /* RPM controlled regulators: */
 
 &rpm_bus {
@@ -124,39 +364,6 @@
 		};
 	};
 
-	rpm-regulator-smpb3 {
-		status = "okay";
-		pm8841_s3: regulator-s3 {
-			regulator-min-microvolt = <1050000>;
-			regulator-max-microvolt = <1050000>;
-			qcom,init-voltage = <1050000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-smpb4 {
-		status = "okay";
-		pm8841_s4: regulator-s4 {
-			regulator-min-microvolt = <900000>;
-			regulator-max-microvolt = <900000>;
-			qcom,init-voltage = <900000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-smpa1 {
-		status = "okay";
-		pm8941_s1: regulator-s1 {
-			regulator-min-microvolt = <1300000>;
-			regulator-max-microvolt = <1300000>;
-			qcom,init-voltage = <1300000>;
-			qcom,init-current = <100>;
-			qcom,system-load = <100000>;
-			regulator-always-on;
-			status = "okay";
-		};
-	};
-
 	rpm-regulator-smpa2 {
 		status = "okay";
 		qcom,allow-atomic = <1>;
@@ -176,140 +383,6 @@
 		};
 	};
 
-	rpm-regulator-smpa3 {
-		status = "okay";
-		pm8941_s3: regulator-s3 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,init-voltage = <1800000>;
-			qcom,init-current = <100>;
-			qcom,system-load = <100000>;
-			regulator-always-on;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa1 {
-		status = "okay";
-		pm8941_l1: regulator-l1 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <1225000>;
-			regulator-max-microvolt = <1225000>;
-			qcom,init-voltage = <1225000>;
-			qcom,init-current = <10>;
-			qcom,system-load = <10000>;
-			regulator-always-on;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa2 {
-		status = "okay";
-		pm8941_l2: regulator-l2 {
-			parent-supply = <&pm8941_s3>;
-			regulator-min-microvolt = <1200000>;
-			regulator-max-microvolt = <1200000>;
-			qcom,init-voltage = <1200000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa3 {
-		status = "okay";
-		pm8941_l3: regulator-l3 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <1225000>;
-			regulator-max-microvolt = <1225000>;
-			qcom,init-voltage = <1225000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa4 {
-		status = "okay";
-		pm8941_l4: regulator-l4 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <12250000>;
-			regulator-max-microvolt = <12250000>;
-			qcom,init-voltage = <12250000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa5 {
-		status = "okay";
-		pm8941_l5: regulator-l5 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,init-voltage = <1800000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa6 {
-		status = "okay";
-		pm8941_l6: regulator-l6 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,init-voltage = <1800000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa7 {
-		status = "okay";
-		pm8941_l7: regulator-l7 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,init-voltage = <1800000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa8 {
-		status = "okay";
-		pm8941_l8: regulator-l8 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,init-voltage = <1800000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa9 {
-		status = "okay";
-		pm8941_l9: regulator-l9 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,init-voltage = <2950000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa10 {
-		status = "okay";
-		pm8941_l10: regulator-l10 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,init-voltage = <2950000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa11 {
-		status = "okay";
-		pm8941_l11: regulator-l11 {
-			parent-supply = <&pm8941_s1>;
-			regulator-min-microvolt = <1300000>;
-			regulator-max-microvolt = <1300000>;
-			qcom,init-voltage = <1300000>;
-			status = "okay";
-		};
-	};
-
 	rpm-regulator-ldoa12 {
 		status = "okay";
 		qcom,allow-atomic = <1>;
@@ -329,152 +402,6 @@
 			compatible = "qcom,rpm-regulator-smd";
 		};
 	};
-
-	rpm-regulator-ldoa13 {
-		status = "okay";
-		pm8941_l13: regulator-l13 {
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,init-voltage = <2950000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa14 {
-		status = "okay";
-		pm8941_l14: regulator-l14 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <1800000>;
-			regulator-max-microvolt = <1800000>;
-			qcom,init-voltage = <1800000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa15 {
-		status = "okay";
-		pm8941_l15: regulator-l15 {
-			parent-supply = <&pm8941_s2>;
-			regulator-min-microvolt = <2050000>;
-			regulator-max-microvolt = <2050000>;
-			qcom,init-voltage = <2050000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa16 {
-		status = "okay";
-		pm8941_l16: regulator-l16 {
-			regulator-min-microvolt = <2700000>;
-			regulator-max-microvolt = <2700000>;
-			qcom,init-voltage = <2700000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa17 {
-		status = "okay";
-		pm8941_l17: regulator-l17 {
-			regulator-min-microvolt = <2850000>;
-			regulator-max-microvolt = <2850000>;
-			qcom,init-voltage = <2850000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa18 {
-		status = "okay";
-		pm8941_l18: regulator-l18 {
-			regulator-min-microvolt = <2850000>;
-			regulator-max-microvolt = <2850000>;
-			qcom,init-voltage = <2850000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa19 {
-		status = "okay";
-		pm8941_l19: regulator-l19 {
-			regulator-min-microvolt = <2900000>;
-			regulator-max-microvolt = <2900000>;
-			qcom,init-voltage = <2900000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa20 {
-		status = "okay";
-		pm8941_l20: regulator-l20 {
-			regulator-min-microvolt = <2950000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,init-voltage = <2950000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa21 {
-		status = "okay";
-		pm8941_l21: regulator-l21 {
-			regulator-min-microvolt = <2950000>;
-			regulator-max-microvolt = <2950000>;
-			qcom,init-voltage = <2950000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa22 {
-		status = "okay";
-		pm8941_l22: regulator-l22 {
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-			qcom,init-voltage = <3000000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa23 {
-		status = "okay";
-		pm8941_l23: regulator-l23 {
-			regulator-min-microvolt = <3000000>;
-			regulator-max-microvolt = <3000000>;
-			qcom,init-voltage = <3000000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-ldoa24 {
-		status = "okay";
-		pm8941_l24: regulator-l24 {
-			regulator-min-microvolt = <3075000>;
-			regulator-max-microvolt = <3075000>;
-			qcom,init-voltage = <3075000>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-vsa1 {
-		status = "okay";
-		pm8941_lvs1: regulator-lvs1 {
-			parent-supply = <&pm8941_s3>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-vsa2 {
-		status = "okay";
-		pm8941_lvs2: regulator-lvs2 {
-			parent-supply = <&pm8941_s3>;
-			status = "okay";
-		};
-	};
-
-	rpm-regulator-vsa3 {
-		status = "okay";
-		pm8941_lvs3: regulator-lvs3 {
-			parent-supply = <&pm8941_s3>;
-			status = "okay";
-		};
-	};
 };
 
 / {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index e3dad4f..0b7d2c5 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -14,6 +14,7 @@
 /include/ "msm8974_pm.dtsi"
 /include/ "msm8974-iommu.dtsi"
 /include/ "msm8974-camera.dtsi"
+/include/ "msm8974-coresight.dtsi"
 /include/ "msm-gdsc.dtsi"
 /include/ "msm8974-ion.dtsi"
 /include/ "msm8974-gpu.dtsi"
@@ -33,10 +34,11 @@
 
 	msmgpio: gpio@fd510000 {
 		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		reg = <0xfd510000 0x4000>;
-		#gpio-cells = <2>;
 	};
 
 	timer {
@@ -73,6 +75,13 @@
 		status = "disabled";
 	};
 
+	serial@f991e000 {
+		compatible = "qcom,msm-lsuart-v14";
+		reg = <0xf991e000 0x1000>;
+		interrupts = <0 108 0>;
+		status = "disabled";
+	};
+
 	usb@f9a55000 {
 		compatible = "qcom,hsusb-otg";
 		reg = <0xf9a55000 0x400>;
@@ -220,6 +229,53 @@
 		interrupt-names = "slimbus_irq", "slimbus_bam_irq";
 		qcom,min-clk-gear = <10>;
 		qcom,rxreg-access;
+
+		taiko_codec {
+			compatible = "qcom,taiko-slim-pgd";
+			elemental-addr = [00 01 A0 00 17 02];
+
+			qcom,cdc-reset-gpio = <&msmgpio 63 0>;
+
+			cdc-vdd-buck-supply = <&pm8941_s2>;
+			qcom,cdc-vdd-buck-voltage = <2150000 2150000>;
+			qcom,cdc-vdd-buck-current = <650000>;
+
+			cdc-vdd-tx-h-supply = <&pm8941_s3>;
+			qcom,cdc-vdd-tx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-tx-h-current = <25000>;
+
+			cdc-vdd-rx-h-supply = <&pm8941_s3>;
+			qcom,cdc-vdd-rx-h-voltage = <1800000 1800000>;
+			qcom,cdc-vdd-rx-h-current = <25000>;
+
+			cdc-vddpx-1-supply = <&pm8941_s3>;
+			qcom,cdc-vddpx-1-voltage = <1800000 1800000>;
+			qcom,cdc-vddpx-1-current = <10000>;
+
+			cdc-vdd-a-1p2v-supply = <&pm8941_l1>;
+			qcom,cdc-vdd-a-1p2v-voltage = <1225000 1225000>;
+			qcom,cdc-vdd-a-1p2v-current = <10000>;
+
+			cdc-vddcx-1-supply = <&pm8941_l1>;
+			qcom,cdc-vddcx-1-voltage = <1225000 1225000>;
+			qcom,cdc-vddcx-1-current = <10000>;
+
+			cdc-vddcx-2-supply = <&pm8941_l1>;
+			qcom,cdc-vddcx-2-voltage = <1225000 1225000>;
+			qcom,cdc-vddcx-2-current = <10000>;
+
+			qcom,cdc-micbias-ldoh-v = <0x3>;
+			qcom,cdc-micbias-cfilt1-mv = <1800>;
+			qcom,cdc-micbias-cfilt2-mv = <2700>;
+			qcom,cdc-micbias-cfilt3-mv = <1800>;
+			qcom,cdc-micbias1-cfilt-sel = <0x0>;
+			qcom,cdc-micbias2-cfilt-sel = <0x1>;
+			qcom,cdc-micbias3-cfilt-sel = <0x2>;
+			qcom,cdc-micbias4-cfilt-sel = <0x2>;
+
+			qcom,cdc-slim-ifd = "taiko-slim-ifd";
+			qcom,cdc-slim-ifd-elemental-addr = [00 00 A0 00 17 02];
+		};
 	};
 
 	spmi_bus: qcom,spmi@fc4c0000 {
@@ -467,7 +523,8 @@
 		reg = <0xfc880000 0x100>,
 		      <0xfd485000 0x400>,
 		      <0xfc820000 0x020>,
-		      <0xfc401680 0x004>;
+		      <0xfc401680 0x004>,
+		      <0xfc980008 0x004>;
 		vdd_mss-supply = <&pm8841_s3>;
 
 		qcom,firmware-name = "mba";
@@ -628,16 +685,18 @@
 		compatible = "qcom,qcedev";
 		reg = <0xfd440000 0x20000>,
 		      <0xfd444000 0x8000>;
+		reg-names = "crypto-base","crypto-bam-base";
 		interrupts = <0 235 0>;
-		qcom,bam-pipes = <0>;
+		qcom,bam-pipe-pair = <0>;
 	};
 
         qcom,qcrypto@fd444000 {
 		compatible = "qcom,qcrypto";
 		reg = <0xfd440000 0x20000>,
 		      <0xfd444000 0x8000>;
+		reg-names = "crypto-base","crypto-bam-base";
 		interrupts = <0 235 0>;
-		qcom,bam-pipes = <1>;
+		qcom,bam-pipe-pair = <1>;
 	};
 
 	qcom,usbbam@f9304000 {
@@ -675,6 +734,15 @@
 			qcom,descriptor-fifo-size = <0x1400>;
 		};
 	};
+
+	qcom,msm-thermal {
+		compatible = "qcom,msm-thermal";
+		qcom,sensor-id = <0>;
+		qcom,poll-ms = <250>;
+		qcom,limit-temp = <60>;
+		qcom,temp-hysteresis = <10>;
+		qcom,freq-step = <2>;
+	};
 };
 
 /include/ "msm-pm8x41-rpm-regulator.dtsi"
diff --git a/arch/arm/boot/dts/msm9625.dts b/arch/arm/boot/dts/msm9625.dts
index deddc5f..42425ed 100644
--- a/arch/arm/boot/dts/msm9625.dts
+++ b/arch/arm/boot/dts/msm9625.dts
@@ -37,6 +37,8 @@
 
 	msmgpio: gpio@fd510000 {
 		compatible = "qcom,msm-gpio";
+		gpio-controller;
+		#gpio-cells = <2>;
 		interrupt-controller;
 		#interrupt-cells = <2>;
 		reg = <0xfd510000 0x4000>;
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 1f2e285..3854403 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -356,6 +356,7 @@
 CONFIG_IMX074_EEPROM=y
 CONFIG_IMX091_EEPROM=y
 CONFIG_MSM_GEMINI=y
+CONFIG_MSM_MERCURY=y
 CONFIG_MSM_CSI20_HEADER=y
 CONFIG_S5K3L1YX=y
 CONFIG_IMX091=y
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 8c79847..06501ba 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -359,6 +359,7 @@
 CONFIG_IMX074_EEPROM=y
 CONFIG_IMX091_EEPROM=y
 CONFIG_MSM_GEMINI=y
+CONFIG_MSM_MERCURY=y
 CONFIG_MSM_CSI20_HEADER=y
 CONFIG_S5K3L1YX=y
 CONFIG_IMX091=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index 6f4db42..c73c62e 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -51,6 +51,9 @@
 CONFIG_MSM_TZ_LOG=y
 CONFIG_MSM_DIRECT_SCLK_ACCESS=y
 CONFIG_MSM_OCMEM=y
+CONFIG_MSM_OCMEM_LOCAL_POWER_CTRL=y
+CONFIG_MSM_OCMEM_DEBUG=y
+CONFIG_MSM_OCMEM_POWER_DISABLE=y
 CONFIG_MSM_MEMORY_DUMP=y
 CONFIG_MSM_CACHE_ERP=y
 CONFIG_MSM_L1_ERR_PANIC=y
@@ -66,7 +69,6 @@
 CONFIG_HIGHMEM=y
 CONFIG_VMALLOC_RESERVE=0x19000000
 CONFIG_USE_OF=y
-CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
@@ -130,6 +132,7 @@
 CONFIG_SERIAL_MSM_HSL=y
 CONFIG_SERIAL_MSM_HSL_CONSOLE=y
 CONFIG_DIAG_CHAR=y
+CONFIG_HVC_DCC=y
 CONFIG_HW_RANDOM=y
 CONFIG_HW_RANDOM_MSM=y
 CONFIG_DCC_TTY=y
@@ -255,4 +258,3 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_MSM_BUS_SCALING=y
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index ca3e996..7d26726 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -541,7 +541,8 @@
 	dump_stack();
 
 	pr_info("\nsending IPI to all other CPUs:\n");
-	smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE);
+	if (!cpus_empty(backtrace_mask))
+		smp_cross_call(&backtrace_mask, IPI_CPU_BACKTRACE);
 
 	/* Wait for up to 10 seconds for all other CPUs to do the backtrace */
 	for (i = 0; i < 10 * 1000; i++) {
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index f026a94..5331f2c 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -2327,6 +2327,15 @@
 	  related operations of OCMEM. Both local power management
 	  and RPM assisted power management operations are supported.
 
+config MSM_OCMEM_POWER_DISABLE
+	bool "OCMEM Disable Power Control"
+	depends on MSM_OCMEM_DEBUG
+	help
+	  Disable all OCMEM power management.
+	  This keeps all OCMEM macros turned ON at all times thus
+	  never allowing them to be turned OFF. Both local power
+	  management and RPM assisted power modes are supported.
+
 config MSM_RTB
 	bool "Register tracing"
 	help
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index ea7fb32..665b861 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2277,11 +2277,13 @@
 	&msm8960_device_ebi1_ch0_erp,
 	&msm8960_device_ebi1_ch1_erp,
 	&epm_adc_device,
-	&apq8064_qdss_device,
-	&msm_etb_device,
-	&msm_tpiu_device,
-	&msm_funnel_device,
-	&apq8064_etm_device,
+	&coresight_tpiu_device,
+	&coresight_etb_device,
+	&apq8064_coresight_funnel_device,
+	&coresight_etm0_device,
+	&coresight_etm1_device,
+	&coresight_etm2_device,
+	&coresight_etm3_device,
 	&apq_cpudai_slim_4_rx,
 	&apq_cpudai_slim_4_tx,
 #ifdef CONFIG_MSM_GEMINI
@@ -2911,6 +2913,7 @@
 static void __init apq8064_common_init(void)
 {
 	u32 platform_version;
+	platform_device_register(&msm_gpio_device);
 	msm_tsens_early_init(&apq_tsens_pdata);
 	msm_thermal_init(&msm_thermal_pdata);
 	if (socinfo_init() < 0)
diff --git a/arch/arm/mach-msm/board-8930-gpiomux.c b/arch/arm/mach-msm/board-8930-gpiomux.c
index e0f012a..ff0a61f 100644
--- a/arch/arm/mach-msm/board-8930-gpiomux.c
+++ b/arch/arm/mach-msm/board-8930-gpiomux.c
@@ -688,6 +688,22 @@
 	},
 };
 
+static struct gpiomux_setting gyro_int_line = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct msm_gpiomux_config msm8930_gyro_int_config[] __initdata = {
+	{
+		.gpio = 69,	/* Gyro Interrupt Line */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gyro_int_line,
+			[GPIOMUX_ACTIVE] = &gyro_int_line,
+		},
+	},
+};
+
 int __init msm8930_init_gpiomux(void)
 {
 	int rc = msm_gpiomux_init(NR_GPIO_IRQS);
@@ -758,5 +774,9 @@
 	msm_gpiomux_install(msm8930_sd_det_config,
 			ARRAY_SIZE(msm8930_sd_det_config));
 
+	if (machine_is_msm8930_fluid() || machine_is_msm8930_mtp())
+		msm_gpiomux_install(msm8930_gyro_int_config,
+			ARRAY_SIZE(msm8930_gyro_int_config));
+
 	return 0;
 }
diff --git a/arch/arm/mach-msm/board-8930-regulator.c b/arch/arm/mach-msm/board-8930-regulator.c
index d3a4960..d4bd18f 100644
--- a/arch/arm/mach-msm/board-8930-regulator.c
+++ b/arch/arm/mach-msm/board-8930-regulator.c
@@ -99,6 +99,9 @@
 	REGULATOR_SUPPLY("cam_vdig",		"4-0048"),
 	REGULATOR_SUPPLY("cam_vdig",            "4-0020"),
 };
+VREG_CONSUMERS(L13) = {
+	REGULATOR_SUPPLY("8038_l13",		NULL),
+};
 VREG_CONSUMERS(L14) = {
 	REGULATOR_SUPPLY("8038_l14",		NULL),
 	REGULATOR_SUPPLY("pa_therm",		"pm8xxx-adc"),
@@ -148,6 +151,9 @@
 	REGULATOR_SUPPLY("8038_l24",		NULL),
 	REGULATOR_SUPPLY("riva_vddmx",		"wcnss_wlan.0"),
 };
+VREG_CONSUMERS(L25) = {
+	REGULATOR_SUPPLY("8038_l25",		NULL),
+};
 VREG_CONSUMERS(L26) = {
 	REGULATOR_SUPPLY("8038_l26",		NULL),
 };
@@ -492,6 +498,7 @@
 	RPM_LDO(L10,	 0, 1, 0, 2900000, 2900000, NULL,      0, 0),
 	RPM_LDO(L11,	 1, 1, 0, 1800000, 1800000, "8038_s4", 10000, 10000),
 	RPM_LDO(L12,	 0, 1, 0, 1200000, 1200000, "8038_s2", 0, 0),
+	RPM_LDO(L13,	 0, 0, 0, 2220000, 2220000, NULL,      0, 0),
 	RPM_LDO(L14,	 0, 1, 0, 1800000, 1800000, NULL,      0, 0),
 	RPM_LDO(L15,	 0, 1, 0, 1800000, 2950000, NULL,      0, 0),
 	RPM_LDO(L17,	 0, 1, 0, 1800000, 2950000, NULL,      0, 0),
@@ -501,6 +508,7 @@
 	RPM_LDO(L22,	 1, 1, 0, 1850000, 2950000, NULL,      10000, 10000),
 	RPM_LDO(L23,	 1, 1, 1, 1800000, 1800000, "8038_s4", 0, 0),
 	RPM_LDO(L24,	 0, 1, 1,  500000, 1150000, "8038_s2", 10000, 10000),
+	RPM_LDO(L25,	 0, 0, 0, 1740000, 1740000, "8038_l13", 0, 0),
 	RPM_LDO(L26,     1, 1, 0, 1050000, 1050000, "8038_s2", 10000, 10000),
 
 	/*	ID     a_on pd ss		    supply */
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 0678461..4fce029 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2239,14 +2239,11 @@
 	&msm8930_ion_dev,
 #endif
 	&msm_device_tz_log,
-
-#ifdef CONFIG_MSM_QDSS
-	&msm_qdss_device,
-	&msm_etb_device,
-	&msm_tpiu_device,
-	&msm_funnel_device,
-	&msm_etm_device,
-#endif
+	&coresight_tpiu_device,
+	&coresight_etb_device,
+	&coresight_funnel_device,
+	&coresight_etm0_device,
+	&coresight_etm1_device,
 	&msm_device_dspcrashd_8960,
 	&msm8960_device_watchdog,
 #ifdef MSM8930_PHASE_2
@@ -2434,6 +2431,7 @@
 static struct i2c_board_info __initdata mpu3050_i2c_boardinfo[] = {
 	{
 		I2C_BOARD_INFO("mpu3050", 0x68),
+		.irq = MSM_GPIO_TO_INT(MPU3050_INT_GPIO),
 		.platform_data = &mpu3050_gyro,
 	},
 };
@@ -2575,6 +2573,7 @@
 	if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
 		pr_err("meminfo_init() failed!\n");
 
+	platform_device_register(&msm_gpio_device);
 	msm_tsens_early_init(&msm_tsens_pdata);
 	msm_thermal_init(&msm_thermal_pdata);
 	BUG_ON(msm_rpm_init(&msm8930_rpm_data));
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 25677c3..ad788bc 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2664,13 +2664,11 @@
 	&msm8960_rpm_log_device,
 	&msm8960_rpm_stat_device,
 	&msm_device_tz_log,
-#ifdef CONFIG_MSM_QDSS
-	&msm_qdss_device,
-	&msm_etb_device,
-	&msm_tpiu_device,
-	&msm_funnel_device,
-	&msm_etm_device,
-#endif
+	&coresight_tpiu_device,
+	&coresight_etb_device,
+	&coresight_funnel_device,
+	&coresight_etm0_device,
+	&coresight_etm1_device,
 	&msm_device_dspcrashd_8960,
 	&msm8960_device_watchdog,
 	&msm8960_rtb_device,
@@ -3084,6 +3082,7 @@
 	if (meminfo_init(SYS_MEMORY, SZ_256M) < 0)
 		pr_err("meminfo_init() failed!\n");
 
+	platform_device_register(&msm_gpio_device);
 	msm_tsens_early_init(&msm_tsens_pdata);
 	msm_thermal_init(&msm_thermal_pdata);
 	BUG_ON(msm_rpm_init(&msm8960_rpm_data));
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 6fcc779..bf80262 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -101,13 +101,13 @@
 		},
 	},
 	{
-		.gpio      = 45,	       /* BLSP8 UART TX */
+		.gpio      = 4,			/* BLSP2 UART TX */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
 		},
 	},
 	{
-		.gpio      = 46,	       /* BLSP8 UART RX */
+		.gpio      = 5,			/* BLSP2 UART RX */
 		.settings = {
 			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
 		},
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 1049bcb..388307b 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -26,6 +26,7 @@
 #endif
 #include <linux/regulator/machine.h>
 #include <linux/regulator/krait-regulator.h>
+#include <linux/msm_thermal.h>
 #include <asm/mach/map.h>
 #include <asm/hardware/gic.h>
 #include <mach/board.h>
@@ -434,6 +435,7 @@
 	else
 		msm_clock_init(&msm8974_clock_init_data);
 	msm8974_init_buses();
+	msm_thermal_device_init();
 }
 
 static struct of_device_id irq_match[] __initdata  = {
@@ -461,8 +463,6 @@
 }
 
 static struct of_dev_auxdata msm_8974_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("qcom,msm-lsuart-v14", 0xF991F000, \
-			"msm_serial_hsl.0", NULL),
 	OF_DEV_AUXDATA("qcom,hsusb-otg", 0xF9A55000, \
 			"msm_otg", NULL),
 	OF_DEV_AUXDATA("qcom,dwc-usb3-msm", 0xF9200000, \
@@ -487,6 +487,34 @@
 	OF_DEV_AUXDATA("qcom,pil-mba",     0xFC820000, "pil-mba", NULL),
 	OF_DEV_AUXDATA("qcom,pil-pronto", 0xFB21B000, \
 			"pil_pronto", NULL),
+	OF_DEV_AUXDATA("arm,coresight-tmc", 0xFC322000, \
+			"coresight-tmc-etr", NULL),
+	OF_DEV_AUXDATA("arm,coresight-tpiu", 0xFC318000, \
+			"coresight-tpiu", NULL),
+	OF_DEV_AUXDATA("qcom,coresight-replicator", 0xFC31C000, \
+			"coresight-replicator", NULL),
+	OF_DEV_AUXDATA("arm,coresight-tmc", 0xFC307000, \
+			"coresight-tmc-etf", NULL),
+	OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC31B000, \
+			"coresight-funnel-merg", NULL),
+	OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC319000, \
+			"coresight-funnel-in0", NULL),
+	OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC31A000, \
+			"coresight-funnel-in1", NULL),
+	OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC345000, \
+			"coresight-funnel-kpss", NULL),
+	OF_DEV_AUXDATA("arm,coresight-funnel", 0xFC364000, \
+			"coresight-funnel-mmss", NULL),
+	OF_DEV_AUXDATA("arm,coresight-stm", 0xFC321000, \
+			"coresight-stm", NULL),
+	OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33C000, \
+			"coresight-etm0", NULL),
+	OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33D000, \
+			"coresight-etm1", NULL),
+	OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33E000, \
+			"coresight-etm2", NULL),
+	OF_DEV_AUXDATA("arm,coresight-etm", 0xFC33F000, \
+			"coresight-etm3", NULL),
 	OF_DEV_AUXDATA("qcom,msm-rng", 0xF9BFF000, \
 			"msm_rng", NULL),
 	OF_DEV_AUXDATA("qcom,qseecom", 0xFE806000, \
diff --git a/arch/arm/mach-msm/board-9615.c b/arch/arm/mach-msm/board-9615.c
index a312e2b..f885774 100644
--- a/arch/arm/mach-msm/board-9615.c
+++ b/arch/arm/mach-msm/board-9615.c
@@ -976,6 +976,7 @@
 				msm_android_usb_hsic_device.dev.platform_data;
 
 	msm9615_device_init();
+	platform_device_register(&msm_gpio_device);
 	msm9615_init_gpiomux();
 	msm9615_i2c_init();
 	regulator_suppress_info_printing();
diff --git a/arch/arm/mach-msm/board-msm8x60.c b/arch/arm/mach-msm/board-msm8x60.c
index 50b1ac5..38f1170 100644
--- a/arch/arm/mach-msm/board-msm8x60.c
+++ b/arch/arm/mach-msm/board-msm8x60.c
@@ -10213,6 +10213,7 @@
 #endif
 	pmic_reset_irq = PM8058_IRQ_BASE + PM8058_RESOUT_IRQ;
 
+	platform_device_register(&msm_gpio_device);
 	/*
 	 * Initialize RPM first as other drivers and devices may need
 	 * it for their initialization.
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index 3b715a4..21b6c0a 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5176,11 +5176,13 @@
 	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 	CLK_LOOKUP("core_a_clk",	qdss_a_clk.c,		""),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_etb.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_tpiu.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_funnel.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_stm.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_etm.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-tpiu.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etb.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-funnel.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.1"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.2"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.3"),
 
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		""),
 	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		""),
@@ -5515,11 +5517,13 @@
 	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 	CLK_LOOKUP("core_a_clk",	qdss_a_clk.c,		""),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_etb.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_tpiu.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_funnel.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_stm.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_etm.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-tpiu.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etb.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-funnel.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.1"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.2"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.3"),
 
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		NULL),
 	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		NULL),
@@ -5861,11 +5865,13 @@
 	CLK_LOOKUP("dfab_clk",		dfab_msmbus_clk.c,	"msm_bus"),
 	CLK_LOOKUP("dfab_a_clk",	dfab_msmbus_a_clk.c,	"msm_bus"),
 	CLK_LOOKUP("core_a_clk",	qdss_a_clk.c,		""),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_etb.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_tpiu.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_funnel.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_stm.0"),
-	CLK_LOOKUP("core_clk",		qdss_clk.c,		"msm_etm.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-tpiu.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etb.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-funnel.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.0"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.1"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.2"),
+	CLK_LOOKUP("core_clk",		qdss_clk.c,	"coresight-etm.3"),
 
 	CLK_LOOKUP("ebi1_clk",		ebi1_clk.c,		NULL),
 	CLK_LOOKUP("mmfpb_clk",		mmfpb_clk.c,		NULL),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 007e63e..8ac1c88 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -18,6 +18,7 @@
 #include <linux/spinlock.h>
 #include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/iopoll.h>
 
 #include <mach/clk.h>
 #include <mach/rpm-regulator-smd.h>
@@ -103,6 +104,7 @@
 #define CLOCK_FRQ_MEASURE_CTL_REG      0x1884
 #define CLOCK_FRQ_MEASURE_STATUS_REG   0x1888
 #define GCC_XO_DIV4_CBCR_REG           0x10C8
+#define GCC_PLLTEST_PAD_CFG_REG        0x188C
 #define APCS_GPLL_ENA_VOTE_REG         0x1480
 #define MMSS_PLL_VOTE_APCS_REG         0x0100
 #define MMSS_DEBUG_CLK_CTL_REG         0x0900
@@ -383,6 +385,8 @@
 #define GP1_CBCR                                 0x1900
 #define GP2_CBCR                                 0x1940
 #define GP3_CBCR                                 0x1980
+#define AUDIO_CORE_GDSCR			 0x7000
+#define AUDIO_CORE_IXFABRIC_CBCR		 0x1B000
 #define AUDIO_CORE_LPAIF_CODEC_SPKR_OSR_CBCR     0xA014
 #define AUDIO_CORE_LPAIF_CODEC_SPKR_IBIT_CBCR    0xA018
 #define AUDIO_CORE_LPAIF_CODEC_SPKR_EBIT_CBCR    0xA01C
@@ -485,9 +489,12 @@
 #define OCMEMNOC_CBCR                            0x50B4
 #define LPASS_Q6SS_AHB_LFABIF_CBCR               0x22000
 #define LPASS_Q6SS_XO_CBCR                       0x26000
+#define LPASS_Q6_AXI_CBCR			 0x11C0
+#define Q6SS_AHBM_CBCR				 0x22004
 #define MSS_XO_Q6_CBCR                           0x108C
 #define MSS_BUS_Q6_CBCR                          0x10A4
 #define MSS_CFG_AHB_CBCR                         0x0280
+#define MSS_Q6_BIMC_AXI_CBCR			 0x0284
 
 #define APCS_CLOCK_BRANCH_ENA_VOTE 0x1484
 #define APCS_CLOCK_SLEEP_ENA_VOTE  0x1488
@@ -756,6 +763,7 @@
 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_acpu_a_clk, &bimc_a_clk.c, LONG_MAX);
+static DEFINE_CLK_VOTER(ocmemgx_gfx3d_clk, &ocmemgx_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ocmemgx_msmbus_clk, &ocmemgx_clk.c, LONG_MAX);
 static DEFINE_CLK_VOTER(ocmemgx_msmbus_a_clk, &ocmemgx_a_clk.c, LONG_MAX);
 
@@ -2284,6 +2292,17 @@
 	},
 };
 
+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 clk_freq_tbl ftbl_mmss_axi_clk[] = {
 	F_MM( 19200000,    cxo,     1,   0,   0),
 	F_MM(150000000,  gpll0,     4,   0,   0),
@@ -3758,8 +3777,7 @@
 static struct branch_clk mmss_mmssnoc_axi_clk = {
 	.cbcr_reg = MMSS_MMSSNOC_AXI_CBCR,
 	.parent = &axi_clk_src.c,
-	/* The bus driver needs set_rate to go through to the parent */
-	.has_sibling = 0,
+	.has_sibling = 1,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "mmss_mmssnoc_axi_clk",
@@ -3771,12 +3789,14 @@
 static struct branch_clk mmss_s0_axi_clk = {
 	.cbcr_reg = MMSS_S0_AXI_CBCR,
 	.parent = &axi_clk_src.c,
-	.has_sibling = 1,
+	/* The bus driver needs set_rate to go through to the parent */
+	.has_sibling = 0,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "mmss_s0_axi_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(mmss_s0_axi_clk.c),
+		.depends = &mmss_mmssnoc_axi_clk.c,
 	},
 };
 
@@ -3866,7 +3886,7 @@
 
 static struct branch_clk oxili_gfx3d_clk = {
 	.cbcr_reg = OXILI_GFX3D_CBCR,
-	.has_sibling = 1,
+	.parent = &ocmemgx_gfx3d_clk.c,
 	.base = &virt_bases[MMSS_BASE],
 	.c = {
 		.dbg_name = "oxili_gfx3d_clk",
@@ -3888,7 +3908,7 @@
 };
 
 static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
-	F_LPASS(28800000, lpapll0, 1, 15, 256),
+	F_LPASS(24576000, lpapll0, 4, 1, 5),
 	F_END
 };
 
@@ -3932,7 +3952,7 @@
 	F_LPASS(  512000, lpapll0, 16, 1, 60),
 	F_LPASS(  768000, lpapll0, 16, 1, 40),
 	F_LPASS( 1024000, lpapll0, 16, 1, 30),
-	F_LPASS( 1536000, lpapll0, 16, 1, 10),
+	F_LPASS( 1536000, lpapll0, 16, 1, 20),
 	F_LPASS( 2048000, lpapll0, 16, 1, 15),
 	F_LPASS( 3072000, lpapll0, 16, 1, 10),
 	F_LPASS( 4096000, lpapll0, 15, 1,  8),
@@ -4303,6 +4323,28 @@
 	},
 };
 
+static struct branch_clk audio_core_ixfabric_clk = {
+	.cbcr_reg = AUDIO_CORE_IXFABRIC_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "audio_core_ixfabric_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(audio_core_ixfabric_clk.c),
+	},
+};
+
+static struct branch_clk gcc_lpass_q6_axi_clk = {
+	.cbcr_reg = LPASS_Q6_AXI_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_lpass_q6_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_lpass_q6_axi_clk.c),
+	},
+};
+
 static struct branch_clk q6ss_xo_clk = {
 	.cbcr_reg = LPASS_Q6SS_XO_CBCR,
 	.bcr_reg = LPASS_Q6SS_BCR,
@@ -4315,6 +4357,17 @@
 	},
 };
 
+static struct branch_clk q6ss_ahbm_clk = {
+	.cbcr_reg = Q6SS_AHBM_CBCR,
+	.has_sibling = 1,
+	.base = &virt_bases[LPASS_BASE],
+	.c = {
+		.dbg_name = "q6ss_ahbm_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(q6ss_ahbm_clk.c),
+	},
+};
+
 static struct branch_clk mss_xo_q6_clk = {
 	.cbcr_reg = MSS_XO_Q6_CBCR,
 	.bcr_reg = MSS_Q6SS_BCR,
@@ -4425,6 +4478,8 @@
 	{&gcc_sdcc2_ahb_clk.c,			GCC_BASE, 0x0071},
 	{&gcc_ocmem_noc_cfg_ahb_clk.c,		GCC_BASE, 0x0029},
 	{&gcc_ce1_clk.c,			GCC_BASE, 0x0138},
+	{&gcc_lpass_q6_axi_clk.c,		GCC_BASE, 0x0160},
+	{&gcc_mss_q6_bimc_axi_clk.c,		GCC_BASE, 0x0031},
 	{&mmss_mmssnoc_axi_clk.c,		MMSS_BASE, 0x0004},
 	{&ocmemnoc_clk.c,			MMSS_BASE, 0x0007},
 	{&ocmemcx_ocmemnoc_clk.c,		MMSS_BASE, 0x0009},
@@ -4505,6 +4560,8 @@
 	{&audio_core_slimbus_lfabif_clk.c,	LPASS_BASE, 0x003e},
 	{&q6ss_xo_clk.c,			LPASS_BASE, 0x002b},
 	{&q6ss_ahb_lfabif_clk.c,		LPASS_BASE, 0x001e},
+	{&q6ss_ahbm_clk.c,			LPASS_BASE, 0x001d},
+	{&audio_core_ixfabric_clk.c,		LPASS_BASE, 0x0059},
 	{&mss_bus_q6_clk.c,			MSS_BASE, 0x003c},
 	{&mss_xo_q6_clk.c,			MSS_BASE, 0x0007},
 
@@ -4563,12 +4620,12 @@
 		break;
 
 	case LPASS_BASE:
-		clk_sel = 0x169;
+		clk_sel = 0x161;
 		regval = BVAL(11, 0, measure_mux[i].debug_mux);
 		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
 
 		/* Activate debug clock output */
-		regval |= BIT(16);
+		regval |= BIT(20);
 		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
 		break;
 
@@ -4674,6 +4731,7 @@
 		ret = (raw_count_full * clk->multiplier);
 	}
 
+	writel_relaxed(0x51A00, GCC_REG_BASE(GCC_PLLTEST_PAD_CFG_REG));
 	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
 
 	clk_disable_unprepare(&cxo_clk_src.c);
@@ -4722,8 +4780,8 @@
 	CLK_LOOKUP("bus_clk", pnoc_sdcc4_clk.c, "msm_sdcc.4"),
 	CLK_DUMMY("xo",		XO_CLK,		NULL,	OFF),
 	CLK_DUMMY("xo",		XO_CLK,		"pil_pronto",		OFF),
-	CLK_DUMMY("core_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
-	CLK_DUMMY("iface_clk",	BLSP2_UART_CLK,	"msm_serial_hsl.0",	OFF),
+	CLK_DUMMY("core_clk",	BLSP2_UART_CLK,	"f991f000.serial",	OFF),
+	CLK_DUMMY("iface_clk",	BLSP2_UART_CLK,	"f991f000.serial",	OFF),
 	CLK_DUMMY("core_clk",	SDC1_CLK,	NULL,			OFF),
 	CLK_DUMMY("iface_clk",	SDC1_P_CLK,	NULL,			OFF),
 	CLK_DUMMY("core_clk",	SDC3_CLK,	NULL,			OFF),
@@ -4757,7 +4815,8 @@
 	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
 
 	CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, "msm_sps"),
-	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991f000.serial"),
+	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f991e000.serial"),
 	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "spi_qsd.1"),
 	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, ""),
@@ -4772,8 +4831,8 @@
 	CLK_LOOKUP("core_clk", gcc_blsp1_qup6_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp1_qup6_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp1_uart1_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_uart2_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "msm_serial_hsl.0"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart2_apps_clk.c, "f991e000.serial"),
+	CLK_LOOKUP("core_clk", gcc_blsp1_uart3_apps_clk.c, "f991f000.serial"),
 	CLK_LOOKUP("core_clk", gcc_blsp1_uart4_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp1_uart5_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
@@ -4949,6 +5008,7 @@
 
 
 	/* LPASS clocks */
+	CLK_LOOKUP("bus_clk", audio_core_ixfabric_clk.c, ""),
 	CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
 	CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c,
 			"fe12f000.slim"),
@@ -4972,7 +5032,7 @@
 	CLK_LOOKUP("osr_clk", audio_core_lpaif_quad_osr_clk.c, ""),
 	CLK_LOOKUP("ebit_clk", audio_core_lpaif_quad_ebit_clk.c, ""),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_quad_ibit_clk.c, ""),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c,
+	CLK_LOOKUP("pcm_clk", audio_core_lpaif_pcm0_clk_src.c,
 						"msm-dai-q6.4106"),
 	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
 	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c,
@@ -4986,12 +5046,16 @@
 	CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcmoe_clk.c,
 						"msm-dai-q6.4106"),
 
-	CLK_LOOKUP("core_clk",       mss_xo_q6_clk.c, "pil-q6v5-mss"),
-	CLK_LOOKUP("bus_clk",       mss_bus_q6_clk.c, "pil-q6v5-mss"),
-	CLK_LOOKUP("bus_clk",  gcc_mss_cfg_ahb_clk.c, ""),
-	CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c, "pil-q6v5-mss"),
-	CLK_LOOKUP("core_clk",         q6ss_xo_clk.c, "pil-q6v5-lpass"),
-	CLK_LOOKUP("bus_clk",  q6ss_ahb_lfabif_clk.c, "pil-q6v5-lpass"),
+	CLK_LOOKUP("core_clk",       mss_xo_q6_clk.c,  "pil-q6v5-mss"),
+	CLK_LOOKUP("bus_clk", gcc_mss_q6_bimc_axi_clk.c, "pil-q6v5-mss"),
+	CLK_LOOKUP("iface_clk", gcc_mss_cfg_ahb_clk.c, "pil-q6v5-mss"),
+	CLK_LOOKUP("reg_clk",       mss_bus_q6_clk.c,  "pil-q6v5-mss"),
+	CLK_LOOKUP("mem_clk", gcc_boot_rom_ahb_clk.c,  "pil-q6v5-mss"),
+
+	CLK_LOOKUP("core_clk",         q6ss_xo_clk.c,  "pil-q6v5-lpass"),
+	CLK_LOOKUP("bus_clk", gcc_lpass_q6_axi_clk.c,  "pil-q6v5-lpass"),
+	CLK_LOOKUP("iface_clk", q6ss_ahb_lfabif_clk.c, "pil-q6v5-lpass"),
+	CLK_LOOKUP("reg_clk",        q6ss_ahbm_clk.c,  "pil-q6v5-lpass"),
 	CLK_LOOKUP("core_clk", gcc_prng_ahb_clk.c, "msm_rng"),
 
 	CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
@@ -5021,8 +5085,8 @@
 	CLK_LOOKUP("ocmem_a_clk", ocmemgx_msmbus_a_clk.c, "msm_bus"),
 	CLK_LOOKUP("bus_clk",	ocmemnoc_clk.c,		"msm_ocmem_noc"),
 	CLK_LOOKUP("bus_a_clk",	ocmemnoc_clk.c,		"msm_ocmem_noc"),
-	CLK_LOOKUP("bus_clk",	mmss_mmssnoc_axi_clk.c,	"msm_mmss_noc"),
-	CLK_LOOKUP("bus_a_clk",	mmss_mmssnoc_axi_clk.c,	"msm_mmss_noc"),
+	CLK_LOOKUP("bus_clk",	mmss_s0_axi_clk.c,	"msm_mmss_noc"),
+	CLK_LOOKUP("bus_a_clk",	mmss_s0_axi_clk.c,	"msm_mmss_noc"),
 	CLK_LOOKUP("iface_clk", gcc_mmss_noc_cfg_ahb_clk.c, ""),
 	CLK_LOOKUP("iface_clk", gcc_ocmem_noc_cfg_ahb_clk.c, ""),
 
@@ -5220,9 +5284,24 @@
 #define PLL_AUX_OUTPUT_BIT 1
 #define PLL_AUX2_OUTPUT_BIT 2
 
+#define PWR_ON_MASK		BIT(31)
+#define EN_REST_WAIT_MASK	(0xF << 20)
+#define EN_FEW_WAIT_MASK	(0xF << 16)
+#define CLK_DIS_WAIT_MASK	(0xF << 12)
+#define SW_OVERRIDE_MASK	BIT(2)
+#define HW_CONTROL_MASK		BIT(1)
+#define SW_COLLAPSE_MASK	BIT(0)
+
+/* Wait 2^n CXO cycles between all states. Here, n=2 (4 cycles). */
+#define EN_REST_WAIT_VAL	(0x2 << 20)
+#define EN_FEW_WAIT_VAL		(0x2 << 16)
+#define CLK_DIS_WAIT_VAL	(0x2 << 12)
+#define GDSC_TIMEOUT_US		50000
+
 static void __init reg_init(void)
 {
-	u32 regval;
+	u32 regval, status;
+	int ret;
 
 	if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
 			& gpll0_clk_src.status_mask))
@@ -5252,6 +5331,31 @@
 	 * register.
 	 */
 	writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
+
+	/*
+	 * TODO: The following sequence enables the LPASS audio core GDSC.
+	 * Remove when this becomes unnecessary.
+	 */
+
+	/*
+	 * Disable HW trigger: collapse/restore occur based on registers writes.
+	 * Disable SW override: Use hardware state-machine for sequencing.
+	 */
+	regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+	regval &= ~(HW_CONTROL_MASK | SW_OVERRIDE_MASK);
+
+	/* Configure wait time between states. */
+	regval &= ~(EN_REST_WAIT_MASK | EN_FEW_WAIT_MASK | CLK_DIS_WAIT_MASK);
+	regval |= EN_REST_WAIT_VAL | EN_FEW_WAIT_VAL | CLK_DIS_WAIT_VAL;
+	writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+	regval = readl_relaxed(LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+	regval &= ~BIT(0);
+	writel_relaxed(regval, LPASS_REG_BASE(AUDIO_CORE_GDSCR));
+
+	ret = readl_poll_timeout(LPASS_REG_BASE(AUDIO_CORE_GDSCR), status,
+				status & PWR_ON_MASK, 50, GDSC_TIMEOUT_US);
+	WARN(ret, "LPASS Audio Core GDSC did not power on.\n");
 }
 
 static void __init msm8974_clock_post_init(void)
@@ -5272,6 +5376,11 @@
 	 */
 	clk_prepare_enable(&cxo_a_clk_src.c);
 
+	/* TODO: Temporarily enable a clock to allow access to LPASS core
+	 * registers.
+	 */
+	clk_prepare_enable(&audio_core_ixfabric_clk.c);
+
 	/*
 	 * TODO: Temporarily enable NOC configuration AHB clocks. Remove when
 	 * the bus driver is ready.
diff --git a/arch/arm/mach-msm/clock-rpm.c b/arch/arm/mach-msm/clock-rpm.c
index 207dbef..be69827 100644
--- a/arch/arm/mach-msm/clock-rpm.c
+++ b/arch/arm/mach-msm/clock-rpm.c
@@ -54,6 +54,23 @@
 	return (rc < 0) ? rc : iv.value * r->factor;
 }
 
+static int clk_rpmrs_handoff(struct rpm_clk *r)
+{
+	struct msm_rpm_iv_pair iv = { .id = r->rpm_status_id, };
+	int rc = msm_rpm_get_status(&iv, 1);
+
+	if (rc < 0)
+		return rc;
+
+	if (!r->branch) {
+		r->last_set_khz = iv.value;
+		r->last_set_sleep_khz = iv.value;
+		r->c.rate = iv.value * r->factor;
+	}
+
+	return 0;
+}
+
 static int clk_rpmrs_set_rate_smd(struct rpm_clk *r, uint32_t value,
 				uint32_t context, int noirq)
 {
@@ -71,10 +88,16 @@
 						r->rpm_clk_id, &kvp, 1);
 }
 
+static int clk_rpmrs_handoff_smd(struct rpm_clk *r)
+{
+	return 0;
+}
+
 struct clk_rpmrs_data {
 	int (*set_rate_fn)(struct rpm_clk *r, uint32_t value,
 				uint32_t context, int noirq);
 	int (*get_rate_fn)(struct rpm_clk *r);
+	int (*handoff_fn)(struct rpm_clk *r);
 	int ctx_active_id;
 	int ctx_sleep_id;
 };
@@ -82,12 +105,14 @@
 struct clk_rpmrs_data clk_rpmrs_data = {
 	.set_rate_fn = clk_rpmrs_set_rate,
 	.get_rate_fn = clk_rpmrs_get_rate,
+	.handoff_fn = clk_rpmrs_handoff,
 	.ctx_active_id = MSM_RPM_CTX_SET_0,
 	.ctx_sleep_id = MSM_RPM_CTX_SET_SLEEP,
 };
 
 struct clk_rpmrs_data clk_rpmrs_data_smd = {
 	.set_rate_fn = clk_rpmrs_set_rate_smd,
+	.handoff_fn = clk_rpmrs_handoff_smd,
 	.ctx_active_id = MSM_RPM_CTX_ACTIVE_SET,
 	.ctx_sleep_id = MSM_RPM_CTX_SLEEP_SET,
 };
@@ -257,7 +282,6 @@
 static enum handoff rpm_clk_handoff(struct clk *clk)
 {
 	struct rpm_clk *r = to_rpm_clk(clk);
-	struct msm_rpm_iv_pair iv = { r->rpm_status_id };
 	int rc;
 
 	/*
@@ -266,16 +290,10 @@
 	 * assume these clocks are enabled (unless the RPM call fails) so
 	 * child clocks of these RPM clocks can still be handed off.
 	 */
-	rc  = msm_rpm_get_status(&iv, 1);
+	rc  = r->rpmrs_data->handoff_fn(r);
 	if (rc < 0)
 		return HANDOFF_DISABLED_CLK;
 
-	if (!r->branch) {
-		r->last_set_khz = iv.value;
-		r->last_set_sleep_khz = iv.value;
-		clk->rate = iv.value * r->factor;
-	}
-
 	return HANDOFF_ENABLED_CLK;
 }
 
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 792bc1d..0d05df9 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -102,6 +102,15 @@
 	.bark_time = 11000,
 	.has_secure = true,
 	.needs_expired_enable = true,
+	.base = MSM_TMR0_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+	{
+		.start	= WDT0_ACCSCSSNBARK_INT,
+		.end	= WDT0_ACCSCSSNBARK_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm8064_device_watchdog = {
@@ -110,6 +119,8 @@
 	.dev = {
 		.platform_data = &msm_watchdog_pdata,
 	},
+	.num_resources	= ARRAY_SIZE(msm_watchdog_resources),
+	.resource	= msm_watchdog_resources,
 };
 
 static struct resource msm_dmov_resource[] = {
@@ -2666,43 +2677,105 @@
 	.resource	= msm_cache_erp_resources,
 };
 
-#define MSM_QDSS_PHYS_BASE		0x01A00000
-#define MSM_ETM_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x1C000)
+#define CORESIGHT_PHYS_BASE		0x01A00000
+#define CORESIGHT_FUNNEL_PHYS_BASE	(CORESIGHT_PHYS_BASE + 0x4000)
+#define CORESIGHT_ETM2_PHYS_BASE	(CORESIGHT_PHYS_BASE + 0x1E000)
+#define CORESIGHT_ETM3_PHYS_BASE	(CORESIGHT_PHYS_BASE + 0x1F000)
 
-#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
-
-static struct qdss_source msm_qdss_sources[] = {
-	QDSS_SOURCE("msm_etm", 0x33),
-	QDSS_SOURCE("msm_oxili", 0x80),
-};
-
-static struct msm_qdss_platform_data qdss_pdata = {
-	.src_table = msm_qdss_sources,
-	.size = ARRAY_SIZE(msm_qdss_sources),
-	.afamily = 1,
-};
-
-struct platform_device apq8064_qdss_device = {
-	.name          = "msm_qdss",
-	.id            = -1,
-	.dev           = {
-		.platform_data = &qdss_pdata,
-	},
-};
-
-static struct resource msm_etm_resources[] = {
+static struct resource coresight_funnel_resources[] = {
 	{
-		.start = MSM_ETM_PHYS_BASE,
-		.end   = MSM_ETM_PHYS_BASE + (SZ_4K * 4) - 1,
+		.start = CORESIGHT_FUNNEL_PHYS_BASE,
+		.end   = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 };
 
-struct platform_device apq8064_etm_device = {
-	.name          = "msm_etm",
+static const int coresight_funnel_outports[] = { 0, 1 };
+static const int coresight_funnel_child_ids[] = { 0, 1 };
+static const int coresight_funnel_child_ports[] = { 0, 0 };
+
+static struct coresight_platform_data coresight_funnel_pdata = {
+	.id		= 2,
+	.name		= "coresight-funnel",
+	.nr_inports	= 4,
+	.outports	= coresight_funnel_outports,
+	.child_ids	= coresight_funnel_child_ids,
+	.child_ports	= coresight_funnel_child_ports,
+	.nr_outports	= ARRAY_SIZE(coresight_funnel_outports),
+};
+
+struct platform_device apq8064_coresight_funnel_device = {
+	.name          = "coresight-funnel",
 	.id            = 0,
-	.num_resources = ARRAY_SIZE(msm_etm_resources),
-	.resource      = msm_etm_resources,
+	.num_resources = ARRAY_SIZE(coresight_funnel_resources),
+	.resource      = coresight_funnel_resources,
+	.dev = {
+		.platform_data = &coresight_funnel_pdata,
+	},
+};
+
+static struct resource coresight_etm2_resources[] = {
+	{
+		.start = CORESIGHT_ETM2_PHYS_BASE,
+		.end   = CORESIGHT_ETM2_PHYS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static const int coresight_etm2_outports[] = { 0 };
+static const int coresight_etm2_child_ids[] = { 2 };
+static const int coresight_etm2_child_ports[] = { 4 };
+
+static struct coresight_platform_data coresight_etm2_pdata = {
+	.id		= 6,
+	.name		= "coresight-etm2",
+	.nr_inports	= 1,
+	.outports	= coresight_etm2_outports,
+	.child_ids	= coresight_etm2_child_ids,
+	.child_ports	= coresight_etm2_child_ports,
+	.nr_outports	= ARRAY_SIZE(coresight_etm2_outports),
+};
+
+struct platform_device coresight_etm2_device = {
+	.name          = "coresight-etm",
+	.id            = 2,
+	.num_resources = ARRAY_SIZE(coresight_etm2_resources),
+	.resource      = coresight_etm2_resources,
+	.dev = {
+		.platform_data = &coresight_etm2_pdata,
+	},
+};
+
+static struct resource coresight_etm3_resources[] = {
+	{
+		.start = CORESIGHT_ETM3_PHYS_BASE,
+		.end   = CORESIGHT_ETM3_PHYS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static const int coresight_etm3_outports[] = { 0 };
+static const int coresight_etm3_child_ids[] = { 2 };
+static const int coresight_etm3_child_ports[] = { 5 };
+
+static struct coresight_platform_data coresight_etm3_pdata = {
+	.id		= 7,
+	.name		= "coresight-etm3",
+	.nr_inports	= 3,
+	.outports	= coresight_etm3_outports,
+	.child_ids	= coresight_etm3_child_ids,
+	.child_ports	= coresight_etm3_child_ports,
+	.nr_outports	= ARRAY_SIZE(coresight_etm3_outports),
+};
+
+struct platform_device coresight_etm3_device = {
+	.name          = "coresight-etm",
+	.id            = 3,
+	.num_resources = ARRAY_SIZE(coresight_etm3_resources),
+	.resource      = coresight_etm3_resources,
+	.dev = {
+		.platform_data = &coresight_etm3_pdata,
+	},
 };
 
 struct msm_iommu_domain_name apq8064_iommu_ctx_names[] = {
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index 724eed8..8347580 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -1331,6 +1331,15 @@
 	.pet_time = 10000,
 	.bark_time = 11000,
 	.has_secure = true,
+	.base = MSM_TMR0_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+	{
+		.start	= WDT0_ACCSCSSNBARK_INT,
+		.end	= WDT0_ACCSCSSNBARK_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm8960_device_watchdog = {
@@ -1339,6 +1348,8 @@
 	.dev = {
 		.platform_data = &msm_watchdog_pdata,
 	},
+	.num_resources	= ARRAY_SIZE(msm_watchdog_resources),
+	.resource	= msm_watchdog_resources,
 };
 
 static struct resource msm_dmov_resource[] = {
@@ -3457,95 +3468,199 @@
 
 #endif /* CONFIG_MSM_DSPS */
 
-#ifdef CONFIG_MSM_QDSS
+#define CORESIGHT_PHYS_BASE		0x01A00000
+#define CORESIGHT_TPIU_PHYS_BASE	(CORESIGHT_PHYS_BASE + 0x3000)
+#define CORESIGHT_ETB_PHYS_BASE		(CORESIGHT_PHYS_BASE + 0x1000)
+#define CORESIGHT_FUNNEL_PHYS_BASE	(CORESIGHT_PHYS_BASE + 0x4000)
+#define CORESIGHT_STM_PHYS_BASE		(CORESIGHT_PHYS_BASE + 0x6000)
+#define CORESIGHT_ETM0_PHYS_BASE	(CORESIGHT_PHYS_BASE + 0x1C000)
+#define CORESIGHT_ETM1_PHYS_BASE	(CORESIGHT_PHYS_BASE + 0x1D000)
 
-#define MSM_QDSS_PHYS_BASE		0x01A00000
-#define MSM_ETB_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x1000)
-#define MSM_TPIU_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x3000)
-#define MSM_FUNNEL_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x4000)
-#define MSM_ETM_PHYS_BASE		(MSM_QDSS_PHYS_BASE + 0x1C000)
+#define CORESIGHT_STM_CHANNEL_PHYS_BASE	(0x14000000 + 0x280000)
 
-#define QDSS_SOURCE(src_name, fpm) { .name = src_name, .fport_mask = fpm, }
-
-static struct qdss_source msm_qdss_sources[] = {
-	QDSS_SOURCE("msm_etm", 0x3),
-};
-
-static struct msm_qdss_platform_data qdss_pdata = {
-	.src_table = msm_qdss_sources,
-	.size = ARRAY_SIZE(msm_qdss_sources),
-	.afamily = 1,
-};
-
-struct platform_device msm_qdss_device = {
-	.name          = "msm_qdss",
-	.id            = -1,
-	.dev           = {
-		.platform_data = &qdss_pdata,
-	},
-};
-
-static struct resource msm_etb_resources[] = {
+static struct resource coresight_tpiu_resources[] = {
 	{
-		.start = MSM_ETB_PHYS_BASE,
-		.end   = MSM_ETB_PHYS_BASE + SZ_4K - 1,
+		.start = CORESIGHT_TPIU_PHYS_BASE,
+		.end   = CORESIGHT_TPIU_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 };
 
-struct platform_device msm_etb_device = {
-	.name          = "msm_etb",
-	.id            = 0,
-	.num_resources = ARRAY_SIZE(msm_etb_resources),
-	.resource      = msm_etb_resources,
+static struct coresight_platform_data coresight_tpiu_pdata = {
+	.id		= 0,
+	.name		= "coresight-tpiu",
+	.nr_inports	= 1,
+	.nr_outports	= 0,
 };
 
-static struct resource msm_tpiu_resources[] = {
+struct platform_device coresight_tpiu_device = {
+	.name          = "coresight-tpiu",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(coresight_tpiu_resources),
+	.resource      = coresight_tpiu_resources,
+	.dev = {
+		.platform_data = &coresight_tpiu_pdata,
+	},
+};
+
+static struct resource coresight_etb_resources[] = {
 	{
-		.start = MSM_TPIU_PHYS_BASE,
-		.end   = MSM_TPIU_PHYS_BASE + SZ_4K - 1,
+		.start = CORESIGHT_ETB_PHYS_BASE,
+		.end   = CORESIGHT_ETB_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 };
 
-struct platform_device msm_tpiu_device = {
-	.name          = "msm_tpiu",
-	.id            = 0,
-	.num_resources = ARRAY_SIZE(msm_tpiu_resources),
-	.resource      = msm_tpiu_resources,
+static struct coresight_platform_data coresight_etb_pdata = {
+	.id		= 1,
+	.name		= "coresight-etb",
+	.nr_inports	= 1,
+	.nr_outports	= 0,
+	.default_sink	= true,
 };
 
-static struct resource msm_funnel_resources[] = {
+struct platform_device coresight_etb_device = {
+	.name          = "coresight-etb",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(coresight_etb_resources),
+	.resource      = coresight_etb_resources,
+	.dev = {
+		.platform_data = &coresight_etb_pdata,
+	},
+};
+
+static struct resource coresight_funnel_resources[] = {
 	{
-		.start = MSM_FUNNEL_PHYS_BASE,
-		.end   = MSM_FUNNEL_PHYS_BASE + SZ_4K - 1,
+		.start = CORESIGHT_FUNNEL_PHYS_BASE,
+		.end   = CORESIGHT_FUNNEL_PHYS_BASE + SZ_4K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 };
 
-struct platform_device msm_funnel_device = {
-	.name          = "msm_funnel",
-	.id            = 0,
-	.num_resources = ARRAY_SIZE(msm_funnel_resources),
-	.resource      = msm_funnel_resources,
+static const int coresight_funnel_outports[] = { 0, 1 };
+static const int coresight_funnel_child_ids[] = { 0, 1 };
+static const int coresight_funnel_child_ports[] = { 0, 0 };
+
+static struct coresight_platform_data coresight_funnel_pdata = {
+	.id		= 2,
+	.name		= "coresight-funnel",
+	.nr_inports	= 4,
+	.outports	= coresight_funnel_outports,
+	.child_ids	= coresight_funnel_child_ids,
+	.child_ports	= coresight_funnel_child_ports,
+	.nr_outports	= ARRAY_SIZE(coresight_funnel_outports),
 };
 
-static struct resource msm_etm_resources[] = {
+struct platform_device coresight_funnel_device = {
+	.name          = "coresight-funnel",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(coresight_funnel_resources),
+	.resource      = coresight_funnel_resources,
+	.dev = {
+		.platform_data = &coresight_funnel_pdata,
+	},
+};
+
+static struct resource coresight_stm_resources[] = {
 	{
-		.start = MSM_ETM_PHYS_BASE,
-		.end   = MSM_ETM_PHYS_BASE + (SZ_4K * 2) - 1,
+		.start = CORESIGHT_STM_PHYS_BASE,
+		.end   = CORESIGHT_STM_PHYS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+	{
+		.start = CORESIGHT_STM_CHANNEL_PHYS_BASE,
+		.end   = CORESIGHT_STM_CHANNEL_PHYS_BASE + SZ_1M + SZ_512K - 1,
 		.flags = IORESOURCE_MEM,
 	},
 };
 
-struct platform_device msm_etm_device = {
-	.name          = "msm_etm",
-	.id            = 0,
-	.num_resources = ARRAY_SIZE(msm_etm_resources),
-	.resource      = msm_etm_resources,
+static const int coresight_stm_outports[] = { 0 };
+static const int coresight_stm_child_ids[] = { 2 };
+static const int coresight_stm_child_ports[] = { 2 };
+
+static struct coresight_platform_data coresight_stm_pdata = {
+	.id		= 3,
+	.name		= "coresight-stm",
+	.nr_inports	= 0,
+	.outports	= coresight_stm_outports,
+	.child_ids	= coresight_stm_child_ids,
+	.child_ports	= coresight_stm_child_ports,
+	.nr_outports	= ARRAY_SIZE(coresight_stm_outports),
 };
 
-#endif
+struct platform_device coresight_stm_device = {
+	.name          = "coresight-stm",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(coresight_stm_resources),
+	.resource      = coresight_stm_resources,
+	.dev = {
+		.platform_data = &coresight_stm_pdata,
+	},
+};
+
+static struct resource coresight_etm0_resources[] = {
+	{
+		.start = CORESIGHT_ETM0_PHYS_BASE,
+		.end   = CORESIGHT_ETM0_PHYS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static const int coresight_etm0_outports[] = { 0 };
+static const int coresight_etm0_child_ids[] = { 2 };
+static const int coresight_etm0_child_ports[] = { 0 };
+
+static struct coresight_platform_data coresight_etm0_pdata = {
+	.id		= 4,
+	.name		= "coresight-etm0",
+	.nr_inports	= 0,
+	.outports	= coresight_etm0_outports,
+	.child_ids	= coresight_etm0_child_ids,
+	.child_ports	= coresight_etm0_child_ports,
+	.nr_outports	= ARRAY_SIZE(coresight_etm0_outports),
+};
+
+struct platform_device coresight_etm0_device = {
+	.name          = "coresight-etm",
+	.id            = 0,
+	.num_resources = ARRAY_SIZE(coresight_etm0_resources),
+	.resource      = coresight_etm0_resources,
+	.dev = {
+		.platform_data = &coresight_etm0_pdata,
+	},
+};
+
+static struct resource coresight_etm1_resources[] = {
+	{
+		.start = CORESIGHT_ETM1_PHYS_BASE,
+		.end   = CORESIGHT_ETM1_PHYS_BASE + SZ_4K - 1,
+		.flags = IORESOURCE_MEM,
+	},
+};
+
+static const int coresight_etm1_outports[] = { 0 };
+static const int coresight_etm1_child_ids[] = { 2 };
+static const int coresight_etm1_child_ports[] = { 1 };
+
+static struct coresight_platform_data coresight_etm1_pdata = {
+	.id		= 5,
+	.name		= "coresight-etm1",
+	.nr_inports	= 0,
+	.outports	= coresight_etm1_outports,
+	.child_ids	= coresight_etm1_child_ids,
+	.child_ports	= coresight_etm1_child_ports,
+	.nr_outports	= ARRAY_SIZE(coresight_etm1_outports),
+};
+
+struct platform_device coresight_etm1_device = {
+	.name          = "coresight-etm",
+	.id            = 1,
+	.num_resources = ARRAY_SIZE(coresight_etm1_resources),
+	.resource      = coresight_etm1_resources,
+	.dev = {
+		.platform_data = &coresight_etm1_pdata,
+	},
+};
 
 static struct resource msm_ebi1_ch0_erp_resources[] = {
 	{
@@ -3913,6 +4028,11 @@
 	},
 };
 
+struct platform_device msm_gpio_device = {
+	.name = "msmgpio",
+	.id = -1,
+};
+
 struct platform_device mdm_sglte_device = {
 	.name		= "mdm2_modem",
 	.id		= -1,
diff --git a/arch/arm/mach-msm/devices-9615.c b/arch/arm/mach-msm/devices-9615.c
index 9f03878..c307714 100644
--- a/arch/arm/mach-msm/devices-9615.c
+++ b/arch/arm/mach-msm/devices-9615.c
@@ -70,6 +70,15 @@
 	.bark_time = 11000,
 	.has_secure = false,
 	.use_kernel_fiq = true,
+	.base = MSM_TMR_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+	{
+		.start	= WDT0_ACCSCSSNBARK_INT,
+		.end	= WDT0_ACCSCSSNBARK_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm9615_device_watchdog = {
@@ -78,6 +87,8 @@
 	.dev = {
 		.platform_data = &msm_watchdog_pdata,
 	},
+	.num_resources	= ARRAY_SIZE(msm_watchdog_resources),
+	.resource	= msm_watchdog_resources,
 };
 
 static struct resource msm_dmov_resource[] = {
@@ -1372,6 +1383,10 @@
 	},
 };
 
+struct platform_device msm_gpio_device = {
+	.name = "msmgpio",
+	.id = -1,
+};
 
 void __init msm9615_device_init(void)
 {
@@ -1382,7 +1397,6 @@
 		msm_rpmrs_levels[0].latency_us;
 	msm_android_usb_hsic_pdata.swfi_latency =
 		msm_rpmrs_levels[0].latency_us;
-
 }
 
 #define MSM_SHARED_RAM_PHYS 0x40000000
diff --git a/arch/arm/mach-msm/devices-fsm9xxx.c b/arch/arm/mach-msm/devices-fsm9xxx.c
index 5f4d940..639eeae 100644
--- a/arch/arm/mach-msm/devices-fsm9xxx.c
+++ b/arch/arm/mach-msm/devices-fsm9xxx.c
@@ -419,6 +419,15 @@
 	.bark_time = 11000,
 	.has_secure = false,
 	.has_vic = true,
+	.base = MSM_TMR_BASE + WDT1_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+	{
+		.start	= INT_WDT1_ACCSCSSBARK,
+		.end	= INT_WDT1_ACCSCSSBARK,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device fsm9xxx_device_watchdog = {
@@ -427,5 +436,7 @@
 	.dev = {
 		.platform_data = &fsm_watchdog_pdata,
 	},
+	.num_resources	= ARRAY_SIZE(msm_watchdog_resources),
+	.resource	= msm_watchdog_resources,
 };
 
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 9ea817f..9f31a18 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -100,6 +100,11 @@
 #define MSM_UART9DM_PHYS    (MSM_GSBI9_PHYS + 0x40000)
 #define INT_UART9DM_IRQ     GSBI9_UARTDM_IRQ
 
+struct platform_device msm_gpio_device = {
+	.name = "msmgpio",
+	.id = -1,
+};
+
 static void charm_ap2mdm_kpdpwr_on(void)
 {
 	gpio_direction_output(AP2MDM_PMIC_RESET_N, 0);
@@ -1991,6 +1996,15 @@
 	.pet_time = 10000,
 	.bark_time = 11000,
 	.has_secure = true,
+	.base = MSM_TMR0_BASE + WDT0_OFFSET,
+};
+
+static struct resource msm_watchdog_resources[] = {
+	{
+		.start	= WDT0_ACCSCSSNBARK_INT,
+		.end	= WDT0_ACCSCSSNBARK_INT,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm8660_device_watchdog = {
@@ -1999,6 +2013,8 @@
 	.dev = {
 		.platform_data = &msm_watchdog_pdata,
 	},
+	.num_resources	= ARRAY_SIZE(msm_watchdog_resources),
+	.resource	= msm_watchdog_resources,
 };
 
 static struct resource msm_dmov_resource_adm0[] = {
@@ -2299,10 +2315,14 @@
 #ifdef CONFIG_MSM_BUS_SCALING
 	.vidc_bus_client_pdata = &vidc_bus_client_data,
 #endif
+#ifdef CONFIG_MSM_VIDC_CONTENT_PROTECTION
+	.cp_enabled = 1,
+#else
+	.cp_enabled = 0,
+#endif
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 	.memtype = ION_CP_MM_HEAP_ID,
 	.enable_ion = 1,
-	.cp_enabled = 1,
 	.secure_wb_heap = 1,
 #else
 	.memtype = MEMTYPE_SMI_KERNEL,
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 84fe195..8e2ab7d 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -363,13 +363,14 @@
 extern struct platform_device msm9615_device_watchdog;
 extern struct platform_device fsm9xxx_device_watchdog;
 
-extern struct platform_device apq8064_qdss_device;
-extern struct platform_device msm_qdss_device;
-extern struct platform_device msm_etb_device;
-extern struct platform_device msm_tpiu_device;
-extern struct platform_device msm_funnel_device;
-extern struct platform_device msm_etm_device;
-extern struct platform_device apq8064_etm_device;
+extern struct platform_device coresight_tpiu_device;
+extern struct platform_device coresight_etb_device;
+extern struct platform_device coresight_funnel_device;
+extern struct platform_device apq8064_coresight_funnel_device;
+extern struct platform_device coresight_etm0_device;
+extern struct platform_device coresight_etm1_device;
+extern struct platform_device coresight_etm2_device;
+extern struct platform_device coresight_etm3_device;
 #endif
 
 extern struct platform_device msm_bus_8064_apps_fabric;
@@ -435,3 +436,5 @@
 extern struct platform_device msm8930aa_device_acpuclk;
 extern struct platform_device msm8960_device_acpuclk;
 extern struct platform_device msm9615_device_acpuclk;
+
+extern struct platform_device msm_gpio_device;
diff --git a/arch/arm/mach-msm/hotplug.c b/arch/arm/mach-msm/hotplug.c
index f8324ce..d1d9f4b 100644
--- a/arch/arm/mach-msm/hotplug.c
+++ b/arch/arm/mach-msm/hotplug.c
@@ -54,8 +54,8 @@
 			 * OK, proper wakeup, we're done
 			 */
 			pen_release = -1;
-			dmac_flush_range((void *)&pen_release,
-				(void *)(&pen_release + sizeof(pen_release)));
+			dmac_flush_range((char *)&pen_release,
+				(char *)&pen_release + sizeof(pen_release));
 			break;
 		}
 
@@ -67,8 +67,8 @@
 		 * possible, since we are currently running incoherently, and
 		 * therefore cannot safely call printk() or anything else
 		 */
-		dmac_inv_range((void *)&pen_release,
-			       (void *)(&pen_release + sizeof(pen_release)));
+		dmac_inv_range((char *)&pen_release,
+			       (char *)&pen_release + sizeof(pen_release));
 		pr_debug("CPU%u: spurious wakeup call\n", cpu);
 	}
 }
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
index 684f9d3..47056a8 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
@@ -100,6 +100,7 @@
 	RPM_VREG_ID_PM8038_L10,
 	RPM_VREG_ID_PM8038_L11,
 	RPM_VREG_ID_PM8038_L12,
+	RPM_VREG_ID_PM8038_L13,
 	RPM_VREG_ID_PM8038_L14,
 	RPM_VREG_ID_PM8038_L15,
 	RPM_VREG_ID_PM8038_L16,
@@ -111,6 +112,7 @@
 	RPM_VREG_ID_PM8038_L22,
 	RPM_VREG_ID_PM8038_L23,
 	RPM_VREG_ID_PM8038_L24,
+	RPM_VREG_ID_PM8038_L25,
 	RPM_VREG_ID_PM8038_L26,
 	RPM_VREG_ID_PM8038_L27,
 	RPM_VREG_ID_PM8038_S1,
@@ -154,6 +156,7 @@
 };
 
 /* Minimum high power mode loads in uA. */
+#define RPM_VREG_8930_LDO_5_HPM_MIN_LOAD		0
 #define RPM_VREG_8930_LDO_50_HPM_MIN_LOAD		5000
 #define RPM_VREG_8930_LDO_150_HPM_MIN_LOAD		10000
 #define RPM_VREG_8930_LDO_300_HPM_MIN_LOAD		10000
diff --git a/arch/arm/mach-msm/krait-regulator.c b/arch/arm/mach-msm/krait-regulator.c
index 03a34d6..63b00c2 100644
--- a/arch/arm/mach-msm/krait-regulator.c
+++ b/arch/arm/mach-msm/krait-regulator.c
@@ -269,7 +269,11 @@
 
 static int set_pmic_gang_phases(int phase_count)
 {
-	return msm_spm_apcs_set_phase(phase_count);
+	/*
+	 * TODO : spm writes for phase control,
+	 * pmic phase control is not working yet
+	 */
+	return 0;
 }
 
 static int set_pmic_gang_voltage(int uV)
diff --git a/arch/arm/mach-msm/msm_watchdog.c b/arch/arm/mach-msm/msm_watchdog.c
index b471426..aca7667 100644
--- a/arch/arm/mach-msm/msm_watchdog.c
+++ b/arch/arm/mach-msm/msm_watchdog.c
@@ -37,22 +37,23 @@
 
 #define TCSR_WDT_CFG	0x30
 
-#define WDT0_RST	0x38
-#define WDT0_EN		0x40
-#define WDT0_STS	0x44
-#define WDT0_BARK_TIME	0x4C
-#define WDT0_BITE_TIME	0x5C
+#define WDT_RST		0x0
+#define WDT_EN		0x8
+#define WDT_STS		0xC
+#define WDT_BARK_TIME	0x14
+#define WDT_BITE_TIME	0x24
 
 #define WDT_HZ		32768
 
 struct msm_watchdog_dump msm_dump_cpu_ctx;
 
-static void __iomem *msm_tmr0_base;
+static void __iomem *msm_wdt_base;
 
 static unsigned long delay_time;
 static unsigned long bark_time;
 static unsigned long long last_pet;
 static bool has_vic;
+static unsigned int msm_wdog_irq;
 
 /*
  * On the kernel command line specify
@@ -116,8 +117,8 @@
 	if (!enable)
 		return 0;
 
-	__raw_writel(1, msm_tmr0_base + WDT0_RST);
-	__raw_writel(0, msm_tmr0_base + WDT0_EN);
+	__raw_writel(1, msm_wdt_base + WDT_RST);
+	__raw_writel(0, msm_wdt_base + WDT_EN);
 	mb();
 	return 0;
 }
@@ -127,8 +128,8 @@
 	if (!enable)
 		return 0;
 
-	__raw_writel(1, msm_tmr0_base + WDT0_EN);
-	__raw_writel(1, msm_tmr0_base + WDT0_RST);
+	__raw_writel(1, msm_wdt_base + WDT_EN);
+	__raw_writel(1, msm_wdt_base + WDT_RST);
 	mb();
 	return 0;
 }
@@ -137,14 +138,14 @@
 			      unsigned long event, void *ptr)
 {
 	if (panic_timeout == 0) {
-		__raw_writel(0, msm_tmr0_base + WDT0_EN);
+		__raw_writel(0, msm_wdt_base + WDT_EN);
 		mb();
 	} else {
 		__raw_writel(WDT_HZ * (panic_timeout + 4),
-				msm_tmr0_base + WDT0_BARK_TIME);
+				msm_wdt_base + WDT_BARK_TIME);
 		__raw_writel(WDT_HZ * (panic_timeout + 4),
-				msm_tmr0_base + WDT0_BITE_TIME);
-		__raw_writel(1, msm_tmr0_base + WDT0_RST);
+				msm_wdt_base + WDT_BITE_TIME);
+		__raw_writel(1, msm_wdt_base + WDT_RST);
 	}
 	return NOTIFY_DONE;
 }
@@ -162,14 +163,14 @@
 {
 	struct wdog_disable_work_data *work_data =
 		container_of(work, struct wdog_disable_work_data, work);
-	__raw_writel(0, msm_tmr0_base + WDT0_EN);
+	__raw_writel(0, msm_wdt_base + WDT_EN);
 	mb();
 	if (has_vic) {
-		free_irq(WDT0_ACCSCSSNBARK_INT, 0);
+		free_irq(msm_wdog_irq, 0);
 	} else {
-		disable_percpu_irq(WDT0_ACCSCSSNBARK_INT);
+		disable_percpu_irq(msm_wdog_irq);
 		if (!appsbark_fiq) {
-			free_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+			free_percpu_irq(msm_wdog_irq,
 					percpu_pdata);
 			free_percpu(percpu_pdata);
 		}
@@ -178,7 +179,7 @@
 	atomic_notifier_chain_unregister(&panic_notifier_list, &panic_blk);
 	cancel_delayed_work(&dogwork_struct);
 	/* may be suspended after the first write above */
-	__raw_writel(0, msm_tmr0_base + WDT0_EN);
+	__raw_writel(0, msm_wdt_base + WDT_EN);
 	complete(&work_data->complete);
 	pr_info("MSM Watchdog deactivated.\n");
 }
@@ -229,11 +230,11 @@
 	if (!enable)
 		return;
 
-	slack = __raw_readl(msm_tmr0_base + WDT0_STS) >> 3;
+	slack = __raw_readl(msm_wdt_base + WDT_STS) >> 3;
 	slack = ((bark_time*WDT_HZ)/1000) - slack;
 	if (slack < min_slack_ticks)
 		min_slack_ticks = slack;
-	__raw_writel(1, msm_tmr0_base + WDT0_RST);
+	__raw_writel(1, msm_wdt_base + WDT_RST);
 	time_ns = sched_clock();
 	slack_ns = (last_pet + bark_time_ns) - time_ns;
 	if (slack_ns < min_slack_ns)
@@ -329,7 +330,7 @@
 	int ret;
 
 	if (has_vic) {
-		ret = request_irq(WDT0_ACCSCSSNBARK_INT, wdog_bark_handler, 0,
+		ret = request_irq(msm_wdog_irq, wdog_bark_handler, 0,
 				  "apps_wdog_bark", NULL);
 		if (ret)
 			return;
@@ -344,7 +345,7 @@
 		}
 
 		msm_wdog_fiq_setup(stack);
-		gic_set_irq_secure(WDT0_ACCSCSSNBARK_INT);
+		gic_set_irq_secure(msm_wdog_irq);
 	} else {
 		percpu_pdata = alloc_percpu(struct msm_watchdog_pdata *);
 		if (!percpu_pdata) {
@@ -354,7 +355,7 @@
 		}
 
 		/* Must request irq before sending scm command */
-		ret = request_percpu_irq(WDT0_ACCSCSSNBARK_INT,
+		ret = request_percpu_irq(msm_wdog_irq,
 			wdog_bark_handler, "apps_wdog_bark", percpu_pdata);
 		if (ret) {
 			free_percpu(percpu_pdata);
@@ -364,20 +365,20 @@
 
 	configure_bark_dump();
 
-	__raw_writel(timeout, msm_tmr0_base + WDT0_BARK_TIME);
-	__raw_writel(timeout + 3*WDT_HZ, msm_tmr0_base + WDT0_BITE_TIME);
+	__raw_writel(timeout, msm_wdt_base + WDT_BARK_TIME);
+	__raw_writel(timeout + 3*WDT_HZ, msm_wdt_base + WDT_BITE_TIME);
 
 	schedule_delayed_work_on(0, &dogwork_struct, delay_time);
 
 	atomic_notifier_chain_register(&panic_notifier_list,
 				       &panic_blk);
 
-	__raw_writel(1, msm_tmr0_base + WDT0_EN);
-	__raw_writel(1, msm_tmr0_base + WDT0_RST);
+	__raw_writel(1, msm_wdt_base + WDT_EN);
+	__raw_writel(1, msm_wdt_base + WDT_RST);
 	last_pet = sched_clock();
 
 	if (!has_vic)
-		enable_percpu_irq(WDT0_ACCSCSSNBARK_INT, IRQ_TYPE_EDGE_RISING);
+		enable_percpu_irq(msm_wdog_irq, IRQ_TYPE_EDGE_RISING);
 
 	printk(KERN_INFO "MSM Watchdog Initialized\n");
 
@@ -400,7 +401,8 @@
 		appsbark_fiq = pdata->use_kernel_fiq;
 	}
 
-	msm_tmr0_base = msm_timer_get_timer0_base();
+	msm_wdt_base = pdata->base;
+	msm_wdog_irq = platform_get_irq(pdev, 0);
 
 	/*
 	 * This is only temporary till SBLs turn on the XPUs
diff --git a/arch/arm/mach-msm/msm_watchdog.h b/arch/arm/mach-msm/msm_watchdog.h
index 00ff0b6..5fb82ee 100644
--- a/arch/arm/mach-msm/msm_watchdog.h
+++ b/arch/arm/mach-msm/msm_watchdog.h
@@ -13,6 +13,10 @@
 #ifndef __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
 #define __ARCH_ARM_MACH_MSM_MSM_WATCHDOG_H
 
+/* The base is just address of the WDT_RST register */
+#define WDT0_OFFSET	0x38
+#define WDT1_OFFSET	0x60
+
 struct msm_watchdog_pdata {
 	/* pet interval period in ms */
 	unsigned int pet_time;
@@ -23,6 +27,7 @@
 	bool has_vic;
 	/* You have to be running in secure mode to use FIQ */
 	bool use_kernel_fiq;
+	void __iomem *base;
 };
 
 struct msm_watchdog_dump {
diff --git a/arch/arm/mach-msm/ocmem_core.c b/arch/arm/mach-msm/ocmem_core.c
index 019f59f..d8cfefc 100644
--- a/arch/arm/mach-msm/ocmem_core.c
+++ b/arch/arm/mach-msm/ocmem_core.c
@@ -383,6 +383,32 @@
 	return 0;
 }
 
+#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
+/* Initializes a region to be turned ON in wide mode */
+static int ocmem_region_set_default_state(unsigned int r_num)
+{
+	unsigned m_num = 0;
+
+	mutex_lock(&region_ctrl_lock);
+
+	for (m_num = 0; m_num < num_banks; m_num++) {
+		apply_macro_vote(0, r_num, m_num, MACRO_ON);
+		aggregate_macro_state(r_num, m_num);
+	}
+
+	aggregate_region_state(r_num);
+	commit_region_state(r_num);
+
+	mutex_unlock(&region_ctrl_lock);
+	return 0;
+}
+
+#else
+static int ocmem_region_set_default_state(unsigned int region_num)
+{
+	return 0;
+}
+#endif
 
 #if defined(CONFIG_MSM_OCMEM_POWER_DEBUG)
 
@@ -489,6 +515,15 @@
 	REGION_DEFAULT_OFF -> REGION_DEFAULT_ON
 **/
 
+#if defined(CONFIG_MSM_OCMEM_POWER_DISABLE)
+/* If power management is disabled leave the macro states as is */
+static int switch_power_state(int id, unsigned long offset, unsigned long len,
+			unsigned new_state)
+{
+	return 0;
+}
+
+#else
 static int switch_power_state(int id, unsigned long offset, unsigned long len,
 			unsigned new_state)
 {
@@ -579,6 +614,7 @@
 	WARN_ON(1);
 	return -EINVAL;
 }
+#endif
 
 /* Interfaces invoked from the scheduler */
 int ocmem_memory_off(int id, unsigned long offset, unsigned long len)
@@ -700,6 +736,10 @@
 			goto hw_not_supported;
 		}
 
+		if (ocmem_region_set_default_state(i)) {
+			pr_err("Failed to initialize region %d\n", i);
+			goto hw_not_supported;
+		}
 	}
 	return 0;
 hw_not_supported:
diff --git a/arch/arm/mach-msm/pil-mba.c b/arch/arm/mach-msm/pil-mba.c
index d0ba7d0..2176b26 100644
--- a/arch/arm/mach-msm/pil-mba.c
+++ b/arch/arm/mach-msm/pil-mba.c
@@ -37,7 +37,6 @@
 
 #define STATUS_META_DATA_AUTH_SUCCESS	0x3
 #define STATUS_AUTH_COMPLETE		0x4
-#define STATUS_ERROR_MASK		BIT(31)
 
 #define AUTH_TIMEOUT_US			10000000
 #define PROXY_TIMEOUT_MS		10000
@@ -75,7 +74,7 @@
 			      const u8 *metadata, size_t size)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
-	u32 status;
+	s32 status;
 	int ret;
 
 	/* Copy metadata to assigned shared buffer location */
@@ -89,10 +88,14 @@
 	writel_relaxed(drv->metadata_phys, drv->reg_base + RMB_PMI_META_DATA);
 	writel_relaxed(CMD_META_DATA_READY, drv->reg_base + RMB_MBA_COMMAND);
 	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-		status == STATUS_META_DATA_AUTH_SUCCESS,
+		status == STATUS_META_DATA_AUTH_SUCCESS || status < 0,
 		POLL_INTERVAL_US, AUTH_TIMEOUT_US);
-	if (ret)
+	if (ret) {
 		dev_err(pil->dev, "MBA authentication timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		ret = -EINVAL;
+	}
 
 	return ret;
 }
@@ -101,6 +104,7 @@
 			       size_t size)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
+	s32 status;
 
 	/* Begin image authentication */
 	if (drv->img_length == 0) {
@@ -111,28 +115,33 @@
 	drv->img_length += size;
 	writel_relaxed(drv->img_length, drv->reg_base + RMB_PMI_CODE_LENGTH);
 
-	return readl_relaxed(drv->reg_base + RMB_MBA_STATUS)
-			& STATUS_ERROR_MASK;
+	status = readl_relaxed(drv->reg_base + RMB_MBA_STATUS);
+	if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		return -EINVAL;
+	}
+
+	return 0;
 }
 
 static int pil_mba_auth(struct pil_desc *pil)
 {
 	struct mba_data *drv = dev_get_drvdata(pil->dev);
 	int ret;
-	u32 status;
+	s32 status;
 
 	/* Wait for all segments to be authenticated or an error to occur */
 	ret = readl_poll_timeout(drv->reg_base + RMB_MBA_STATUS, status,
-			status == STATUS_AUTH_COMPLETE ||
-			status & STATUS_ERROR_MASK,
+			status == STATUS_AUTH_COMPLETE || status < 0,
 			50, AUTH_TIMEOUT_US);
-	if (ret)
-		return ret;
+	if (ret) {
+		dev_err(pil->dev, "MBA authentication timed out\n");
+	} else if (status < 0) {
+		dev_err(pil->dev, "MBA returned error %d\n", status);
+		ret = -EINVAL;
+	}
 
-	if (status & STATUS_ERROR_MASK)
-		return -EINVAL;
-
-	return 0;
+	return ret;
 }
 
 static int pil_mba_shutdown(struct pil_desc *pil)
diff --git a/arch/arm/mach-msm/pil-q6v5-lpass.c b/arch/arm/mach-msm/pil-q6v5-lpass.c
index 311f8a7..44d8bc6 100644
--- a/arch/arm/mach-msm/pil-q6v5-lpass.c
+++ b/arch/arm/mach-msm/pil-q6v5-lpass.c
@@ -18,13 +18,56 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/clk.h>
-
+#include <mach/clk.h>
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
 
 #define QDSP6SS_RST_EVB			0x010
 #define PROXY_TIMEOUT_MS		10000
 
+static int pil_lpass_enable_clks(struct q6v5_data *drv)
+{
+	int ret;
+
+	ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
+	if (ret)
+		goto err_reset;
+	ret = clk_prepare_enable(drv->core_clk);
+	if (ret)
+		goto err_core_clk;
+	ret = clk_prepare_enable(drv->ahb_clk);
+	if (ret)
+		goto err_ahb_clk;
+	ret = clk_prepare_enable(drv->axi_clk);
+	if (ret)
+		goto err_axi_clk;
+	ret = clk_prepare_enable(drv->reg_clk);
+	if (ret)
+		goto err_reg_clk;
+
+	return 0;
+
+err_reg_clk:
+	clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+	clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+	clk_disable_unprepare(drv->core_clk);
+err_core_clk:
+	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+err_reset:
+	return ret;
+}
+
+static void pil_lpass_disable_clks(struct q6v5_data *drv)
+{
+	clk_disable_unprepare(drv->reg_clk);
+	clk_disable_unprepare(drv->axi_clk);
+	clk_disable_unprepare(drv->ahb_clk);
+	clk_disable_unprepare(drv->core_clk);
+	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+}
+
 static int pil_lpass_shutdown(struct pil_desc *pil)
 {
 	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
@@ -37,10 +80,10 @@
 	 * performed during the shutdown succeed.
 	 */
 	if (drv->is_booted == false)
-		pil_q6v5_enable_clks(pil);
+		pil_lpass_enable_clks(drv);
 
 	pil_q6v5_shutdown(pil);
-	pil_q6v5_disable_clks(pil);
+	pil_lpass_disable_clks(drv);
 
 	drv->is_booted = false;
 
@@ -52,7 +95,7 @@
 	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
 	int ret;
 
-	ret = pil_q6v5_enable_clks(pil);
+	ret = pil_lpass_enable_clks(drv);
 	if (ret)
 		return ret;
 
@@ -62,7 +105,7 @@
 
 	ret = pil_q6v5_reset(pil);
 	if (ret) {
-		pil_q6v5_disable_clks(pil);
+		pil_lpass_disable_clks(drv);
 		return ret;
 	}
 
@@ -96,6 +139,22 @@
 	desc->owner = THIS_MODULE;
 	desc->proxy_timeout = PROXY_TIMEOUT_MS;
 
+	drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+	if (IS_ERR(drv->core_clk))
+		return PTR_ERR(drv->core_clk);
+
+	drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+	if (IS_ERR(drv->ahb_clk))
+		return PTR_ERR(drv->ahb_clk);
+
+	drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+	if (IS_ERR(drv->axi_clk))
+		return PTR_ERR(drv->axi_clk);
+
+	drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
+	if (IS_ERR(drv->reg_clk))
+		return PTR_ERR(drv->reg_clk);
+
 	drv->pil = msm_pil_register(desc);
 	if (IS_ERR(drv->pil))
 		return PTR_ERR(drv->pil);
diff --git a/arch/arm/mach-msm/pil-q6v5-mss.c b/arch/arm/mach-msm/pil-q6v5-mss.c
index 5c9c3c4..6a30940 100644
--- a/arch/arm/mach-msm/pil-q6v5-mss.c
+++ b/arch/arm/mach-msm/pil-q6v5-mss.c
@@ -38,6 +38,9 @@
 #define MSS_MODEM_HALT_BASE		0x200
 #define MSS_NC_HALT_BASE		0x280
 
+/* MSS_CLAMP_IO Register Value */
+#define MSS_IO_UNCLAMP_ALL		0x40
+
 /* RMB Status Register Values */
 #define STATUS_PBL_SUCCESS		0x1
 #define STATUS_XPU_UNLOCKED		0x1
@@ -71,6 +74,55 @@
 	return regulator_disable(drv->vreg);
 }
 
+static int pil_mss_enable_clks(struct q6v5_data *drv)
+{
+	int ret;
+
+	ret = clk_prepare_enable(drv->ahb_clk);
+	if (ret)
+		goto err_ahb_clk;
+	ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
+	if (ret)
+		goto err_reset;
+	ret = clk_prepare_enable(drv->core_clk);
+	if (ret)
+		goto err_core_clk;
+	ret = clk_prepare_enable(drv->axi_clk);
+	if (ret)
+		goto err_axi_clk;
+	ret = clk_prepare_enable(drv->reg_clk);
+	if (ret)
+		goto err_reg_clk;
+	ret = clk_prepare_enable(drv->rom_clk);
+	if (ret)
+		goto err_rom_clk;
+
+	return 0;
+
+err_rom_clk:
+	clk_disable_unprepare(drv->reg_clk);
+err_reg_clk:
+	clk_disable_unprepare(drv->axi_clk);
+err_axi_clk:
+	clk_disable_unprepare(drv->core_clk);
+err_core_clk:
+	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+err_reset:
+	clk_disable_unprepare(drv->ahb_clk);
+err_ahb_clk:
+	return ret;
+}
+
+static void pil_mss_disable_clks(struct q6v5_data *drv)
+{
+	clk_disable_unprepare(drv->rom_clk);
+	clk_disable_unprepare(drv->reg_clk);
+	clk_disable_unprepare(drv->axi_clk);
+	clk_disable_unprepare(drv->core_clk);
+	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
+	clk_disable_unprepare(drv->ahb_clk);
+}
+
 static int wait_for_mba_ready(struct device *dev)
 {
 	struct q6v5_data *drv = dev_get_drvdata(dev);
@@ -120,11 +172,11 @@
 	 */
 	if (drv->is_booted == false) {
 		pil_mss_power_up(pil->dev);
-		pil_q6v5_enable_clks(pil);
+		pil_mss_enable_clks(drv);
 	}
 	pil_q6v5_shutdown(pil);
 
-	pil_q6v5_disable_clks(pil);
+	pil_mss_disable_clks(drv);
 	pil_mss_power_down(pil->dev);
 
 	writel_relaxed(1, drv->restart_reg);
@@ -152,7 +204,7 @@
 	if (ret)
 		goto err_power;
 
-	ret = pil_q6v5_enable_clks(pil);
+	ret = pil_mss_enable_clks(drv);
 	if (ret)
 		goto err_clks;
 
@@ -166,6 +218,9 @@
 				drv->reg_base + QDSP6SS_RST_EVB);
 	}
 
+	/* De-assert MSS IO clamps */
+	writel_relaxed(MSS_IO_UNCLAMP_ALL, drv->io_clamp_reg);
+
 	ret = pil_q6v5_reset(pil);
 	if (ret)
 		goto err_q6v5_reset;
@@ -184,7 +239,7 @@
 err_auth:
 	pil_q6v5_shutdown(pil);
 err_q6v5_reset:
-	pil_q6v5_disable_clks(pil);
+	pil_mss_disable_clks(drv);
 err_clks:
 	pil_mss_power_down(pil->dev);
 err_power:
@@ -233,6 +288,12 @@
 	if (!drv->restart_reg)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 4);
+	drv->io_clamp_reg = devm_ioremap(&pdev->dev, res->start,
+					resource_size(res));
+	if (!drv->io_clamp_reg)
+		return -ENOMEM;
+
 	drv->vreg = devm_regulator_get(&pdev->dev, "vdd_mss");
 	if (IS_ERR(drv->vreg))
 		return PTR_ERR(drv->vreg);
@@ -247,9 +308,25 @@
 		return ret;
 	}
 
-	drv->mem_clk = devm_clk_get(&pdev->dev, "mem_clk");
-	if (IS_ERR(drv->mem_clk))
-		return PTR_ERR(drv->mem_clk);
+	drv->ahb_clk = devm_clk_get(&pdev->dev, "iface_clk");
+	if (IS_ERR(drv->ahb_clk))
+		return PTR_ERR(drv->ahb_clk);
+
+	drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
+	if (IS_ERR(drv->core_clk))
+		return PTR_ERR(drv->core_clk);
+
+	drv->axi_clk = devm_clk_get(&pdev->dev, "bus_clk");
+	if (IS_ERR(drv->axi_clk))
+		return PTR_ERR(drv->axi_clk);
+
+	drv->reg_clk = devm_clk_get(&pdev->dev, "reg_clk");
+	if (IS_ERR(drv->reg_clk))
+		return PTR_ERR(drv->reg_clk);
+
+	drv->rom_clk = devm_clk_get(&pdev->dev, "mem_clk");
+	if (IS_ERR(drv->rom_clk))
+		return PTR_ERR(drv->rom_clk);
 
 	drv->pil = msm_pil_register(desc);
 	if (IS_ERR(drv->pil))
diff --git a/arch/arm/mach-msm/pil-q6v5.c b/arch/arm/mach-msm/pil-q6v5.c
index a362a7e3..772031b 100644
--- a/arch/arm/mach-msm/pil-q6v5.c
+++ b/arch/arm/mach-msm/pil-q6v5.c
@@ -20,9 +20,7 @@
 #include <linux/err.h>
 #include <linux/of.h>
 #include <linux/clk.h>
-
 #include <mach/clk.h>
-
 #include "peripheral-loader.h"
 #include "pil-q6v5.h"
 
@@ -30,6 +28,7 @@
 #define QDSP6SS_RESET			0x014
 #define QDSP6SS_GFMUX_CTL		0x020
 #define QDSP6SS_PWR_CTL			0x030
+#define QDSP6SS_CGC_OVERRIDE		0x034
 
 /* AXI Halt Register Offsets */
 #define AXI_HALTREQ			0x0
@@ -39,15 +38,15 @@
 #define HALT_ACK_TIMEOUT_US		100000
 
 /* QDSP6SS_RESET */
+#define Q6SS_STOP_CORE			BIT(0)
 #define Q6SS_CORE_ARES			BIT(1)
-#define Q6SS_ETM_ISDB_ARES		BIT(3)
-#define Q6SS_STOP_CORE			BIT(4)
+#define Q6SS_BUS_ARES_ENA		BIT(2)
 
 /* QDSP6SS_GFMUX_CTL */
 #define Q6SS_CLK_ENA			BIT(1)
 
 /* QDSP6SS_PWR_CTL */
-#define Q6SS_L2DATA_SLP_NRET_N		BIT(0)
+#define Q6SS_L2DATA_SLP_NRET_N		(BIT(0)|BIT(1)|BIT(2))
 #define Q6SS_L2TAG_SLP_NRET_N		BIT(16)
 #define Q6SS_ETB_SLP_NRET_N		BIT(17)
 #define Q6SS_L2DATA_STBY_N		BIT(18)
@@ -55,6 +54,10 @@
 #define Q6SS_CLAMP_IO			BIT(20)
 #define QDSS_BHS_ON			BIT(21)
 
+/* QDSP6SS_CGC_OVERRIDE */
+#define Q6SS_CORE_CLK_EN		BIT(0)
+#define Q6SS_CORE_RCLK_EN		BIT(1)
+
 int pil_q6v5_make_proxy_votes(struct pil_desc *pil)
 {
 	int ret;
@@ -107,50 +110,6 @@
 }
 EXPORT_SYMBOL(pil_q6v5_init_image);
 
-int pil_q6v5_enable_clks(struct pil_desc *pil)
-{
-	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
-	int ret;
-
-	ret = clk_reset(drv->core_clk, CLK_RESET_DEASSERT);
-	if (ret)
-		goto err_reset;
-	ret = clk_prepare_enable(drv->core_clk);
-	if (ret)
-		goto err_core_clk;
-	ret = clk_prepare_enable(drv->bus_clk);
-	if (ret)
-		goto err_bus_clk;
-	if (drv->mem_clk) {
-		ret = clk_prepare_enable(drv->mem_clk);
-		if (ret)
-			goto err_mem_clk;
-	}
-
-	return 0;
-
-err_mem_clk:
-	clk_disable_unprepare(drv->bus_clk);
-err_bus_clk:
-	clk_disable_unprepare(drv->core_clk);
-err_core_clk:
-	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
-err_reset:
-	return ret;
-}
-EXPORT_SYMBOL(pil_q6v5_enable_clks);
-
-void pil_q6v5_disable_clks(struct pil_desc *pil)
-{
-	struct q6v5_data *drv = dev_get_drvdata(pil->dev);
-
-	clk_disable_unprepare(drv->bus_clk);
-	clk_disable_unprepare(drv->core_clk);
-	clk_disable_unprepare(drv->mem_clk);
-	clk_reset(drv->core_clk, CLK_RESET_ASSERT);
-}
-EXPORT_SYMBOL(pil_q6v5_disable_clks);
-
 void pil_q6v5_shutdown(struct pil_desc *pil)
 {
 	u32 val;
@@ -174,7 +133,7 @@
 
 	/* Assert Q6 resets */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
-	val = (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES);
+	val = (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA);
 	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
 
 	/* Kill power at block headswitch (affects LPASS only) */
@@ -191,7 +150,7 @@
 
 	/* Assert resets, stop core */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
-	val |= (Q6SS_CORE_ARES | Q6SS_ETM_ISDB_ARES | Q6SS_STOP_CORE);
+	val |= (Q6SS_CORE_ARES | Q6SS_BUS_ARES_ENA | Q6SS_STOP_CORE);
 	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
 
 	/* Enable power block headswitch (only affects LPASS) */
@@ -211,9 +170,15 @@
 	writel_relaxed(val, drv->reg_base + QDSP6SS_PWR_CTL);
 
 	/* Bring core out of reset */
-	val = Q6SS_STOP_CORE;
+	val = readl_relaxed(drv->reg_base + QDSP6SS_RESET);
+	val &= ~Q6SS_CORE_ARES;
 	writel_relaxed(val, drv->reg_base + QDSP6SS_RESET);
 
+	/* Disable clock gating for core and rclk */
+	val = readl_relaxed(drv->reg_base + QDSP6SS_CGC_OVERRIDE);
+	val |= Q6SS_CORE_RCLK_EN | Q6SS_CORE_CLK_EN;
+	writel_relaxed(val, drv->reg_base + QDSP6SS_CGC_OVERRIDE);
+
 	/* Turn on core clock */
 	val = readl_relaxed(drv->reg_base + QDSP6SS_GFMUX_CTL);
 	val |= Q6SS_CLK_ENA;
@@ -266,14 +231,6 @@
 	if (IS_ERR(drv->xo))
 		return ERR_CAST(drv->xo);
 
-	drv->bus_clk = devm_clk_get(&pdev->dev, "bus_clk");
-	if (IS_ERR(drv->bus_clk))
-		return ERR_CAST(drv->bus_clk);
-
-	drv->core_clk = devm_clk_get(&pdev->dev, "core_clk");
-	if (IS_ERR(drv->core_clk))
-		return ERR_CAST(drv->core_clk);
-
 	desc->dev = &pdev->dev;
 
 	return desc;
diff --git a/arch/arm/mach-msm/pil-q6v5.h b/arch/arm/mach-msm/pil-q6v5.h
index e0d7a20..03f93fa 100644
--- a/arch/arm/mach-msm/pil-q6v5.h
+++ b/arch/arm/mach-msm/pil-q6v5.h
@@ -21,13 +21,16 @@
 
 struct q6v5_data {
 	void __iomem *reg_base;
-	struct clk *xo;
-	struct clk *bus_clk;
-	struct clk *core_clk;
-	struct clk *mem_clk;
+	struct clk *xo;		/* XO clock source */
+	struct clk *ahb_clk;	/* PIL access to registers */
+	struct clk *axi_clk;	/* CPU access to memory */
+	struct clk *core_clk;	/* CPU core */
+	struct clk *reg_clk;	/* CPU access registers */
+	struct clk *rom_clk;	/* Boot ROM */
 	void __iomem *axi_halt_base;
 	void __iomem *rmb_base;
 	void __iomem *restart_reg;
+	void __iomem *io_clamp_reg;
 	unsigned long start_addr;
 	struct regulator *vreg;
 	bool is_booted;
@@ -42,8 +45,6 @@
 			size_t size);
 void pil_q6v5_shutdown(struct pil_desc *pil);
 int pil_q6v5_reset(struct pil_desc *pil);
-int pil_q6v5_enable_clks(struct pil_desc *pil);
-void pil_q6v5_disable_clks(struct pil_desc *pil);
 struct pil_desc *pil_q6v5_init(struct platform_device *pdev);
 
 #endif
diff --git a/arch/arm/mach-msm/pil-venus.c b/arch/arm/mach-msm/pil-venus.c
index 6a0aeaa..49c39ec 100644
--- a/arch/arm/mach-msm/pil-venus.c
+++ b/arch/arm/mach-msm/pil-venus.c
@@ -228,12 +228,6 @@
 	writel_relaxed(drv->fw_sz, wrapper_base +
 			VENUS_WRAPPER_VBIF_SS_SEC_FW_END_ADDR);
 
-	rc = iommu_attach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
-	if (rc) {
-		dev_err(pil->dev, "venus fw iommu attach failed\n");
-		goto err_iommu_attach;
-	}
-
 	/* Enable all Venus internal clocks */
 	writel_relaxed(0, wrapper_base + VENUS_WRAPPER_CLOCK_CONFIG);
 	writel_relaxed(0, wrapper_base + VENUS_WRAPPER_CPU_CLOCK_CONFIG);
@@ -247,6 +241,12 @@
 	 */
 	udelay(1);
 
+	rc = iommu_attach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
+	if (rc) {
+		dev_err(pil->dev, "venus fw iommu attach failed\n");
+		goto err_iommu_attach;
+	}
+
 	/* Map virtual addr space 0 - fw_sz to firmware physical addr space */
 	rc = msm_iommu_map_contig_buffer(pa, drv->venus_domain_num, 0,
 					 drv->fw_sz, SZ_4K, 0, &iova);
@@ -285,19 +285,6 @@
 
 	venus_clock_prepare_enable(pil->dev);
 
-	/* Halt AXI and AXI OCMEM VBIF Access */
-	reg = readl_relaxed(vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
-	reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
-	writel_relaxed(reg, vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
-
-	/* Request for AXI bus port halt */
-	rc = readl_poll_timeout(vbif_base + VENUS_VBIF_AXI_HALT_CTRL1,
-			reg, reg & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
-			POLL_INTERVAL_US,
-			VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
-	if (rc)
-		dev_err(pil->dev, "Port halt timeout\n");
-
 	/* Assert the reset to ARM9 */
 	reg = readl_relaxed(wrapper_base + VENUS_WRAPPER_SW_RESET);
 	reg |= BIT(4);
@@ -311,6 +298,19 @@
 
 	iommu_detach_device(drv->iommu_fw_domain, drv->iommu_fw_ctx);
 
+	/* Halt AXI and AXI OCMEM VBIF Access */
+	reg = readl_relaxed(vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
+	reg |= VENUS_VBIF_AXI_HALT_CTRL0_HALT_REQ;
+	writel_relaxed(reg, vbif_base + VENUS_VBIF_AXI_HALT_CTRL0);
+
+	/* Request for AXI bus port halt */
+	rc = readl_poll_timeout(vbif_base + VENUS_VBIF_AXI_HALT_CTRL1,
+			reg, reg & VENUS_VBIF_AXI_HALT_CTRL1_HALT_ACK,
+			POLL_INTERVAL_US,
+			VENUS_VBIF_AXI_HALT_ACK_TIMEOUT_US);
+	if (rc)
+		dev_err(pil->dev, "Port halt timeout\n");
+
 	venus_clock_disable_unprepare(pil->dev);
 
 	regulator_disable(drv->gdsc);
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index a11ca95..28b7748 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -120,6 +120,29 @@
 	return 0;
 }
 
+static int __cpuinit krait_release_secondary_p3(unsigned long base, int cpu)
+{
+	void *base_ptr = ioremap_nocache(base + (cpu * 0x10000), SZ_4K);
+	if (!base_ptr)
+		return -ENODEV;
+
+	writel_relaxed(0x021, base_ptr+0x04);
+	mb();
+	udelay(2);
+
+	writel_relaxed(0x020, base_ptr+0x04);
+	mb();
+	udelay(2);
+
+	writel_relaxed(0x000, base_ptr+0x04);
+	mb();
+
+	writel_relaxed(0x080, base_ptr+0x04);
+	mb();
+	iounmap(base_ptr);
+	return 0;
+}
+
 static int __cpuinit release_secondary(unsigned int cpu)
 {
 	BUG_ON(cpu >= get_core_count());
@@ -134,6 +157,9 @@
 	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab())
 		return krait_release_secondary(0x02088000, cpu);
 
+	if (cpu_is_msm8974())
+		return krait_release_secondary_p3(0xf9088000, cpu);
+
 	WARN(1, "unknown CPU case in release_secondary\n");
 	return -EINVAL;
 }
@@ -205,8 +231,8 @@
 		if (pen_release == -1)
 			break;
 
-		dmac_inv_range((void *)&pen_release,
-			       (void *)(&pen_release+sizeof(pen_release)));
+		dmac_inv_range((char *)&pen_release,
+			       (char *)&pen_release + sizeof(pen_release));
 		udelay(10);
 	}
 
diff --git a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
index 1092c77..5c1e7ce 100644
--- a/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
+++ b/arch/arm/mach-msm/qdsp6v2/audio_acdb.c
@@ -20,7 +20,7 @@
 #include <mach/qdsp6v2/audio_acdb.h>
 
 
-#define MAX_NETWORKS		12
+#define MAX_NETWORKS		15
 
 struct sidetone_atomic_cal {
 	atomic_t	enable;
diff --git a/arch/arm/mach-msm/rpm-regulator-8930.c b/arch/arm/mach-msm/rpm-regulator-8930.c
index 0de67b1..3878e22 100644
--- a/arch/arm/mach-msm/rpm-regulator-8930.c
+++ b/arch/arm/mach-msm/rpm-regulator-8930.c
@@ -71,6 +71,11 @@
 	VOLTAGE_RANGE( 750000, 1537500, 12500),
 };
 
+static struct vreg_range ln_ldo_ranges[] = {
+	VOLTAGE_RANGE( 690000, 1110000,  60000),
+	VOLTAGE_RANGE(1380000, 2220000, 120000),
+};
+
 static struct vreg_range smps_ranges[] = {
 	VOLTAGE_RANGE( 375000,  737500, 12500),
 	VOLTAGE_RANGE( 750000, 1487500, 12500),
@@ -90,6 +95,7 @@
 static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
 static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
 static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
+static struct vreg_set_points ln_ldo_set_points = SET_POINTS(ln_ldo_ranges);
 static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
 static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
 static struct vreg_set_points corner_set_points = SET_POINTS(corner_ranges);
@@ -98,6 +104,7 @@
 	&pldo_set_points,
 	&nldo_set_points,
 	&nldo1200_set_points,
+	&ln_ldo_set_points,
 	&smps_set_points,
 	&ftsmps_set_points,
 	&corner_set_points,
@@ -173,6 +180,7 @@
 	LDO(L10,  "8038_l10",  "8038_l10_pc", pldo,     LDO_600,  0),
 	LDO(L11,  "8038_l11",  "8038_l11_pc", pldo,     LDO_600,  0),
 	LDO(L12,  "8038_l12",  "8038_l12_pc", nldo,     LDO_300,  1),
+	LDO(L13,  "8038_l13",  NULL,          ln_ldo,   LDO_5,    0),
 	LDO(L14,  "8038_l14",  "8038_l14_pc", pldo,     LDO_50,   0),
 	LDO(L15,  "8038_l15",  "8038_l15_pc", pldo,     LDO_150,  0),
 	LDO(L16,  "8038_l16",  NULL,          nldo1200, LDO_1200, 1),
@@ -184,6 +192,7 @@
 	LDO(L22,  "8038_l22",  "8038_l22_pc", pldo,     LDO_50,   0),
 	LDO(L23,  "8038_l23",  "8038_l23_pc", pldo,     LDO_50,   0),
 	LDO(L24,  "8038_l24",  NULL,          nldo1200, LDO_1200, 1),
+	LDO(L25,  "8038_l25",  NULL,          ln_ldo,   LDO_5,    0),
 	LDO(L26,  "8038_l26",  "8038_l26_pc", nldo,     LDO_150,  1),
 	LDO(L27,  "8038_l27",  NULL,          nldo1200, LDO_1200, 1),
 
@@ -237,8 +246,12 @@
 {
 	int real_id = 0;
 
-	if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L15_PC)
+	if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L12_PC)
 		real_id = id - RPM_VREG_ID_PM8038_L2_PC;
+	else if (id >= RPM_VREG_ID_PM8038_L14_PC
+			&& id <= RPM_VREG_ID_PM8038_L15_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L14_PC
+				+ RPM_VREG_ID_PM8038_L14;
 	else if (id >= RPM_VREG_ID_PM8038_L17_PC
 			&& id <= RPM_VREG_ID_PM8038_L18_PC)
 		real_id = id - RPM_VREG_ID_PM8038_L17_PC
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index b6fb52a..57f41ca 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -250,8 +250,8 @@
 #endif
 }
 
-#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
-static void __init arm_bootmem_free_apnm(unsigned long max_low,
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+static void __init arm_bootmem_free_hmnm(unsigned long max_low,
 	unsigned long max_high)
 {
 	unsigned long max_zone_pfns[MAX_NR_ZONES];
@@ -267,7 +267,7 @@
 		unsigned long start = memblock_region_memory_base_pfn(reg);
 		unsigned long end = memblock_region_memory_end_pfn(reg);
 
-		add_active_range(0, start, end);
+		memblock_set_node(PFN_PHYS(start), PFN_PHYS(end - start), 0);
 	}
 	free_area_init_nodes(max_zone_pfns);
 }
@@ -491,8 +491,8 @@
 	 */
 	sparse_init();
 
-#ifdef CONFIG_ARCH_POPULATES_NODE_MAP
-	arm_bootmem_free_apnm(max_low, max_high);
+#ifdef CONFIG_HAVE_MEMBLOCK_NODE_MAP
+	arm_bootmem_free_hmnm(max_low, max_high);
 #else
 	/*
 	 * Now free the memory - free_area_init_node needs
diff --git a/drivers/bluetooth/hci_ldisc.c b/drivers/bluetooth/hci_ldisc.c
index 121bf7c9..5c04693 100644
--- a/drivers/bluetooth/hci_ldisc.c
+++ b/drivers/bluetooth/hci_ldisc.c
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
  *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (c) 2000-2001, 2010-2011, Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2000-2001, 2010-2012, Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -51,6 +51,7 @@
 static bool reset = 0;
 
 static struct hci_uart_proto *hup[HCI_UART_MAX_PROTO];
+static void hci_uart_tty_wakeup_action(unsigned long data);
 
 int hci_uart_register_proto(struct hci_uart_proto *p)
 {
@@ -276,6 +277,8 @@
 	tty->receive_room = 65536;
 
 	spin_lock_init(&hu->rx_lock);
+	tasklet_init(&hu->tty_wakeup_task, hci_uart_tty_wakeup_action,
+			 (unsigned long)hu);
 
 	/* Flush any pending characters in the driver and line discipline. */
 
@@ -309,6 +312,8 @@
 		if (hdev)
 			hci_uart_close(hdev);
 
+		tasklet_kill(&hu->tty_wakeup_task);
+
 		if (test_and_clear_bit(HCI_UART_PROTO_SET, &hu->flags)) {
 			hu->proto->close(hu);
 			if (hdev) {
@@ -323,6 +328,8 @@
  *
  *    Callback for transmit wakeup. Called when low level
  *    device driver can accept more send data.
+ *    This callback gets called from the isr context so
+ *    schedule the send data operation to tasklet.
  *
  * Arguments:        tty    pointer to associated tty instance data
  * Return Value:    None
@@ -330,12 +337,26 @@
 static void hci_uart_tty_wakeup(struct tty_struct *tty)
 {
 	struct hci_uart *hu = (void *)tty->disc_data;
+	tasklet_schedule(&hu->tty_wakeup_task);
+}
+
+/* hci_uart_tty_wakeup_action()
+ *
+ * Scheduled action to transmit data when low level device
+ * driver can accept more data.
+ */
+static void hci_uart_tty_wakeup_action(unsigned long data)
+{
+	struct hci_uart *hu = (struct hci_uart *)data;
+	struct tty_struct *tty;
 
 	BT_DBG("");
 
 	if (!hu)
 		return;
 
+	tty = hu->tty;
+
 	clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
 
 	if (tty != hu->tty)
diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h
index dc48239..123fc24 100644
--- a/drivers/bluetooth/hci_uart.h
+++ b/drivers/bluetooth/hci_uart.h
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2002-2003  Maxim Krasnyansky <maxk@qualcomm.com>
  *  Copyright (C) 2004-2005  Marcel Holtmann <marcel@holtmann.org>
- *  Copyright (c) 2000-2001, 2010, Code Aurora Forum. All rights reserved.
+ *  Copyright (c) 2000-2001, 2010, 2012 Code Aurora Forum. All rights reserved.
  *
  *
  *  This program is free software; you can redistribute it and/or modify
@@ -66,6 +66,7 @@
 	unsigned long		hdev_flags;
 
 	struct hci_uart_proto	*proto;
+	struct tasklet_struct	tty_wakeup_task;
 	void			*priv;
 
 	struct sk_buff		*tx_skb;
diff --git a/drivers/char/msm_rotator.c b/drivers/char/msm_rotator.c
index 4d34362..6f3b79b 100644
--- a/drivers/char/msm_rotator.c
+++ b/drivers/char/msm_rotator.c
@@ -421,6 +421,7 @@
 		break;
 	case MDP_Y_CRCB_H2V1:
 	case MDP_Y_CBCR_H2V1:
+	case MDP_Y_CRCB_H1V2:
 		p->num_planes = 2;
 		p->plane_size[0] = w * h;
 		p->plane_size[1] = w * h;
@@ -651,9 +652,12 @@
 	int bpp;
 	uint32_t dst_format;
 
-	if (info->src.format == MDP_YCRYCB_H2V1)
-		dst_format = MDP_Y_CRCB_H2V1;
-	else
+	if (info->src.format == MDP_YCRYCB_H2V1) {
+		if (info->rotations & MDP_ROT_90)
+			dst_format = MDP_Y_CRCB_H1V2;
+		else
+			dst_format = MDP_Y_CRCB_H2V1;
+	} else
 		return -EINVAL;
 
 	if (info->dst.format != dst_format)
@@ -1286,7 +1290,10 @@
 		info.dst.format = info.src.format;
 		break;
 	case MDP_YCRYCB_H2V1:
-		info.dst.format = MDP_Y_CRCB_H2V1;
+		if (info.rotations & MDP_ROT_90)
+			info.dst.format = MDP_Y_CRCB_H1V2;
+		else
+			info.dst.format = MDP_Y_CRCB_H2V1;
 		break;
 	case MDP_Y_CB_CR_H2V2:
 	case MDP_Y_CBCR_H2V2_TILE:
diff --git a/drivers/coresight/Makefile b/drivers/coresight/Makefile
index 2ee2093..bded488 100644
--- a/drivers/coresight/Makefile
+++ b/drivers/coresight/Makefile
@@ -1,2 +1,3 @@
 
-obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-etb.o coresight-tpiu.o coresight-funnel.o coresight-stm.o coresight-etm.o
+obj-$(CONFIG_OF) += of_coresight.o
+obj-$(CONFIG_MSM_QDSS) += coresight.o coresight-tmc.o coresight-tpiu.o coresight-etb.o coresight-funnel.o coresight-replicator.o coresight-stm.o coresight-etm.o
diff --git a/drivers/coresight/coresight-etb.c b/drivers/coresight/coresight-etb.c
index 2bffae5..56cee06 100644
--- a/drivers/coresight/coresight-etb.c
+++ b/drivers/coresight/coresight-etb.c
@@ -23,8 +23,9 @@
 #include <linux/uaccess.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/mutex.h>
+#include <linux/spinlock.h>
 #include <linux/clk.h>
+#include <linux/of_coresight.h>
 #include <linux/coresight.h>
 
 #include "coresight-priv.h"
@@ -32,6 +33,17 @@
 #define etb_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
 #define etb_readl(drvdata, off)		__raw_readl(drvdata->base + off)
 
+#define ETB_LOCK(drvdata)						\
+do {									\
+	mb();								\
+	etb_writel(drvdata, 0x0, CORESIGHT_LAR);			\
+} while (0)
+#define ETB_UNLOCK(drvdata)						\
+do {									\
+	etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
+	mb();								\
+} while (0)
+
 #define ETB_RAM_DEPTH_REG	(0x004)
 #define ETB_STATUS_REG		(0x00C)
 #define ETB_RAM_READ_DATA_REG	(0x010)
@@ -50,42 +62,29 @@
 #define ETB_ITATBCTR1		(0xEF4)
 #define ETB_ITATBCTR0		(0xEF8)
 
-
 #define BYTES_PER_WORD		4
 #define ETB_SIZE_WORDS		4096
 #define FRAME_SIZE_WORDS	4
 
-#define ETB_LOCK()							\
-do {									\
-	mb();								\
-	etb_writel(drvdata, 0x0, CORESIGHT_LAR);			\
-} while (0)
-#define ETB_UNLOCK()							\
-do {									\
-	etb_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
-	mb();								\
-} while (0)
-
 struct etb_drvdata {
-	uint8_t		*buf;
-	void __iomem	*base;
-	bool		enabled;
-	bool		reading;
-	spinlock_t	spinlock;
-	atomic_t	in_use;
-	struct device	*dev;
-	struct kobject	*kobj;
-	struct clk	*clk;
-	uint32_t	trigger_cntr;
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	struct miscdevice	miscdev;
+	struct clk		*clk;
+	spinlock_t		spinlock;
+	bool			reading;
+	atomic_t		in_use;
+	uint8_t			*buf;
+	bool			enable;
+	uint32_t		trigger_cntr;
 };
 
-static struct etb_drvdata *drvdata;
-
-static void __etb_enable(void)
+static void __etb_enable(struct etb_drvdata *drvdata)
 {
 	int i;
 
-	ETB_UNLOCK();
+	ETB_UNLOCK(drvdata);
 
 	etb_writel(drvdata, 0x0, ETB_RAM_WRITE_POINTER);
 	for (i = 0; i < ETB_SIZE_WORDS; i++)
@@ -98,11 +97,12 @@
 	etb_writel(drvdata, BIT(13) | BIT(0), ETB_FFCR);
 	etb_writel(drvdata, BIT(0), ETB_CTL_REG);
 
-	ETB_LOCK();
+	ETB_LOCK(drvdata);
 }
 
-int etb_enable(void)
+static int etb_enable(struct coresight_device *csdev)
 {
+	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	int ret;
 	unsigned long flags;
 
@@ -111,25 +111,24 @@
 		return ret;
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
-	__etb_enable();
-	drvdata->enabled = true;
-	dev_info(drvdata->dev, "ETB enabled\n");
+	__etb_enable(drvdata);
+	drvdata->enable = true;
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
 
+	dev_info(drvdata->dev, "ETB enabled\n");
 	return 0;
 }
 
-static void __etb_disable(void)
+static void __etb_disable(struct etb_drvdata *drvdata)
 {
 	int count;
 	uint32_t ffcr;
 
-	ETB_UNLOCK();
+	ETB_UNLOCK(drvdata);
 
 	ffcr = etb_readl(drvdata, ETB_FFCR);
 	ffcr |= (BIT(12) | BIT(6));
 	etb_writel(drvdata, ffcr, ETB_FFCR);
-
 	for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFCR), 6) != 0
 				&& count > 0; count--)
 		udelay(1);
@@ -137,30 +136,16 @@
 	     etb_readl(drvdata, ETB_FFCR));
 
 	etb_writel(drvdata, 0x0, ETB_CTL_REG);
-
 	for (count = TIMEOUT_US; BVAL(etb_readl(drvdata, ETB_FFSR), 1) != 1
 				&& count > 0; count--)
 		udelay(1);
 	WARN(count == 0, "timeout while disabling DRVDATA, ETB_FFSR: %#x\n",
 	     etb_readl(drvdata, ETB_FFSR));
 
-	ETB_LOCK();
+	ETB_LOCK(drvdata);
 }
 
-void etb_disable(void)
-{
-	unsigned long flags;
-
-	spin_lock_irqsave(&drvdata->spinlock, flags);
-	__etb_disable();
-	drvdata->enabled = false;
-	dev_info(drvdata->dev, "ETB disabled\n");
-	spin_unlock_irqrestore(&drvdata->spinlock, flags);
-
-	clk_disable_unprepare(drvdata->clk);
-}
-
-static void __etb_dump(void)
+static void __etb_dump(struct etb_drvdata *drvdata)
 {
 	int i;
 	uint8_t *buf_ptr;
@@ -170,7 +155,7 @@
 	uint32_t frame_off;
 	uint32_t frame_endoff;
 
-	ETB_UNLOCK();
+	ETB_UNLOCK(drvdata);
 
 	read_ptr = etb_readl(drvdata, ETB_RAM_READ_POINTER);
 	write_ptr = etb_readl(drvdata, ETB_RAM_WRITE_POINTER);
@@ -211,26 +196,69 @@
 
 	etb_writel(drvdata, read_ptr, ETB_RAM_READ_POINTER);
 
-	ETB_LOCK();
+	ETB_LOCK(drvdata);
 }
 
-void etb_dump(void)
+static void etb_disable(struct coresight_device *csdev)
+{
+	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	__etb_disable(drvdata);
+	__etb_dump(drvdata);
+	drvdata->enable = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	clk_disable_unprepare(drvdata->clk);
+
+	dev_info(drvdata->dev, "ETB disabled\n");
+}
+
+static void etb_abort(struct coresight_device *csdev)
+{
+	struct etb_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	unsigned long flags;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	__etb_disable(drvdata);
+	__etb_dump(drvdata);
+	drvdata->enable = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "ETB aborted\n");
+}
+
+static const struct coresight_ops_sink etb_sink_ops = {
+	.enable		= etb_enable,
+	.disable	= etb_disable,
+	.abort		= etb_abort,
+};
+
+static const struct coresight_ops etb_cs_ops = {
+	.sink_ops	= &etb_sink_ops,
+};
+
+static void etb_dump(struct etb_drvdata *drvdata)
 {
 	unsigned long flags;
 
 	spin_lock_irqsave(&drvdata->spinlock, flags);
-	if (drvdata->enabled) {
-		__etb_disable();
-		__etb_dump();
-		__etb_enable();
-
-		dev_info(drvdata->dev, "ETB dumped\n");
+	if (drvdata->enable) {
+		__etb_disable(drvdata);
+		__etb_dump(drvdata);
+		__etb_enable(drvdata);
 	}
 	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "ETB dumped\n");
 }
 
 static int etb_open(struct inode *inode, struct file *file)
 {
+	struct etb_drvdata *drvdata = container_of(file->private_data,
+						   struct etb_drvdata, miscdev);
+
 	if (atomic_cmpxchg(&drvdata->in_use, 0, 1))
 		return -EBUSY;
 
@@ -241,8 +269,11 @@
 static ssize_t etb_read(struct file *file, char __user *data,
 				size_t len, loff_t *ppos)
 {
+	struct etb_drvdata *drvdata = container_of(file->private_data,
+						   struct etb_drvdata, miscdev);
+
 	if (drvdata->reading == false) {
-		etb_dump();
+		etb_dump(drvdata);
 		drvdata->reading = true;
 	}
 
@@ -258,38 +289,35 @@
 
 	dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
 		__func__, len, (int) (ETB_SIZE_WORDS * BYTES_PER_WORD - *ppos));
-
 	return len;
 }
 
 static int etb_release(struct inode *inode, struct file *file)
 {
-	drvdata->reading = false;
+	struct etb_drvdata *drvdata = container_of(file->private_data,
+						   struct etb_drvdata, miscdev);
 
+	drvdata->reading = false;
 	atomic_set(&drvdata->in_use, 0);
 
 	dev_dbg(drvdata->dev, "%s: released\n", __func__);
-
 	return 0;
 }
 
 static const struct file_operations etb_fops = {
-	.owner =	THIS_MODULE,
-	.open =		etb_open,
-	.read =		etb_read,
-	.release =	etb_release,
-};
-
-static struct miscdevice etb_misc = {
-	.name =		"msm_etb",
-	.minor =	MISC_DYNAMIC_MINOR,
-	.fops =		&etb_fops,
+	.owner		= THIS_MODULE,
+	.open		= etb_open,
+	.read		= etb_read,
+	.release	= etb_release,
+	.llseek		= no_llseek,
 };
 
 static ssize_t etb_show_trigger_cntr(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->trigger_cntr;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -297,6 +325,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etb_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -308,120 +337,105 @@
 static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, etb_show_trigger_cntr,
 		   etb_store_trigger_cntr);
 
-static int __devinit etb_sysfs_init(void)
-{
-	int ret;
+static struct attribute *etb_attrs[] = {
+	&dev_attr_trigger_cntr.attr,
+	NULL,
+};
 
-	drvdata->kobj = kobject_create_and_add("etb", qdss_get_modulekobj());
-	if (!drvdata->kobj) {
-		dev_err(drvdata->dev, "failed to create ETB sysfs kobject\n");
-		ret = -ENOMEM;
-		goto err_create;
-	}
+static struct attribute_group etb_attr_grp = {
+	.attrs = etb_attrs,
+};
 
-	ret = sysfs_create_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
-	if (ret) {
-		dev_err(drvdata->dev, "failed to create ETB sysfs trigger_cntr"
-		" attribute\n");
-		goto err_file;
-	}
-
-	return 0;
-err_file:
-	kobject_put(drvdata->kobj);
-err_create:
-	return ret;
-}
-
-static void __devexit etb_sysfs_exit(void)
-{
-	sysfs_remove_file(drvdata->kobj, &dev_attr_trigger_cntr.attr);
-	kobject_put(drvdata->kobj);
-}
+static const struct attribute_group *etb_attr_grps[] = {
+	&etb_attr_grp,
+	NULL,
+};
 
 static int __devinit etb_probe(struct platform_device *pdev)
 {
 	int ret;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct etb_drvdata *drvdata;
 	struct resource *res;
+	struct coresight_desc *desc;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto err_kzalloc_drvdata;
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
 	}
 
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -EINVAL;
-		goto err_res;
-	}
+	if (!res)
+		return -ENODEV;
 
-	drvdata->base = ioremap_nocache(res->start, resource_size(res));
-	if (!drvdata->base) {
-		ret = -EINVAL;
-		goto err_ioremap;
-	}
-
-	drvdata->dev = &pdev->dev;
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
 
 	spin_lock_init(&drvdata->spinlock);
 
-	drvdata->clk = clk_get(drvdata->dev, "core_clk");
-	if (IS_ERR(drvdata->clk)) {
-		ret = PTR_ERR(drvdata->clk);
-		goto err_clk_get;
-	}
+	drvdata->clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(drvdata->clk))
+		return PTR_ERR(drvdata->clk);
 
 	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
 	if (ret)
-		goto err_clk_rate;
+		return ret;
 
-	ret = misc_register(&etb_misc);
+	drvdata->buf = devm_kzalloc(dev, ETB_SIZE_WORDS * BYTES_PER_WORD,
+				    GFP_KERNEL);
+	if (!drvdata->buf)
+		return -ENOMEM;
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_SINK;
+	desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+	desc->ops = &etb_cs_ops;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->groups = etb_attr_grps;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
+
+	drvdata->miscdev.name = ((struct coresight_platform_data *)
+				 (pdev->dev.platform_data))->name;
+	drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+	drvdata->miscdev.fops = &etb_fops;
+	ret = misc_register(&drvdata->miscdev);
 	if (ret)
-		goto err_misc;
+		goto err;
 
-	drvdata->buf = kzalloc(ETB_SIZE_WORDS * BYTES_PER_WORD, GFP_KERNEL);
-	if (!drvdata->buf) {
-		ret = -ENOMEM;
-		goto err_alloc;
-	}
-
-	etb_sysfs_init();
-
-	dev_info(drvdata->dev, "ETB initialized\n");
+	dev_info(dev, "ETB initialized\n");
 	return 0;
-
-err_alloc:
-	misc_deregister(&etb_misc);
-err_misc:
-err_clk_rate:
-	clk_put(drvdata->clk);
-err_clk_get:
-	iounmap(drvdata->base);
-err_ioremap:
-err_res:
-	kfree(drvdata);
-err_kzalloc_drvdata:
-	dev_err(drvdata->dev, "ETB init failed\n");
+err:
+	coresight_unregister(drvdata->csdev);
 	return ret;
 }
 
 static int __devexit etb_remove(struct platform_device *pdev)
 {
-	if (drvdata->enabled)
-		etb_disable();
-	etb_sysfs_exit();
-	kfree(drvdata->buf);
-	misc_deregister(&etb_misc);
-	clk_put(drvdata->clk);
-	iounmap(drvdata->base);
-	kfree(drvdata);
+	struct etb_drvdata *drvdata = platform_get_drvdata(pdev);
 
+	misc_deregister(&drvdata->miscdev);
+	coresight_unregister(drvdata->csdev);
 	return 0;
 }
 
 static struct of_device_id etb_match[] = {
-	{.compatible = "qcom,msm-etb"},
+	{.compatible = "arm,coresight-etb"},
 	{}
 };
 
@@ -429,7 +443,7 @@
 	.probe          = etb_probe,
 	.remove         = __devexit_p(etb_remove),
 	.driver         = {
-		.name   = "msm_etb",
+		.name   = "coresight-etb",
 		.owner	= THIS_MODULE,
 		.of_match_table = etb_match,
 	},
diff --git a/drivers/coresight/coresight-etm.c b/drivers/coresight/coresight-etm.c
index b3d2a16..e805c7f 100644
--- a/drivers/coresight/coresight-etm.c
+++ b/drivers/coresight/coresight-etm.c
@@ -26,17 +26,30 @@
 #include <linux/pm_qos.h>
 #include <linux/sysfs.h>
 #include <linux/stat.h>
+#include <linux/mutex.h>
 #include <linux/clk.h>
+#include <linux/of_coresight.h>
 #include <linux/coresight.h>
 #include <asm/sections.h>
 #include <mach/socinfo.h>
 
 #include "coresight-priv.h"
 
-#define etm_writel(drvdata, cpu, val, off)	\
-			__raw_writel((val), drvdata->base + (SZ_4K * cpu) + off)
-#define etm_readl(drvdata, cpu, off)	\
-			__raw_readl(drvdata->base + (SZ_4K * cpu) + off)
+#define etm_writel(drvdata, val, off)	\
+			__raw_writel((val), drvdata->base + off)
+#define etm_readl(drvdata, off)		\
+			__raw_readl(drvdata->base + off)
+
+#define ETM_LOCK(drvdata)						\
+do {									\
+	mb();								\
+	etm_writel(drvdata, 0x0, CORESIGHT_LAR);			\
+} while (0)
+#define ETM_UNLOCK(drvdata)						\
+do {									\
+	etm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
+	mb();								\
+} while (0)
 
 /*
  * Device registers:
@@ -119,7 +132,7 @@
 
 #define ETM_SEQ_STATE_MAX_VAL	(0x2)
 
-enum {
+enum etm_addr_type {
 	ETM_ADDR_TYPE_NONE,
 	ETM_ADDR_TYPE_SINGLE,
 	ETM_ADDR_TYPE_RANGE,
@@ -127,42 +140,24 @@
 	ETM_ADDR_TYPE_STOP,
 };
 
-#define ETM_LOCK(cpu)							\
-do {									\
-	mb();								\
-	etm_writel(drvdata, cpu, 0x0, CORESIGHT_LAR);			\
-} while (0)
-#define ETM_UNLOCK(cpu)							\
-do {									\
-	etm_writel(drvdata, cpu, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
-	mb();								\
-} while (0)
-
-
-#ifdef MODULE_PARAM_PREFIX
-#undef MODULE_PARAM_PREFIX
-#endif
-#define MODULE_PARAM_PREFIX "coresight."
-
 #ifdef CONFIG_MSM_QDSS_ETM_DEFAULT_ENABLE
-static int etm_boot_enable = 1;
+static int boot_enable = 1;
 #else
-static int etm_boot_enable;
+static int boot_enable;
 #endif
 module_param_named(
-	etm_boot_enable, etm_boot_enable, int, S_IRUGO
+	boot_enable, boot_enable, int, S_IRUGO
 );
 
 struct etm_drvdata {
 	void __iomem			*base;
-	bool				enabled;
+	struct device			*dev;
+	struct coresight_device		*csdev;
+	struct clk			*clk;
+	struct mutex			mutex;
 	struct wake_lock		wake_lock;
 	struct pm_qos_request		qos_req;
-	struct qdss_source		*src;
-	struct mutex			mutex;
-	struct device			*dev;
-	struct kobject			*kobj;
-	struct clk			*clk;
+	int				cpu;
 	uint8_t				arch;
 	uint8_t				nr_addr_cmp;
 	uint8_t				nr_cntr;
@@ -200,9 +195,6 @@
 	uint32_t			timestamp_event;
 };
 
-static struct etm_drvdata *drvdata;
-
-
 /* ETM clock is derived from the processor clock and gets enabled on a
  * logical OR of below items on Krait (pass2 onwards):
  * 1.CPMR[ETMCLKEN] is 1
@@ -218,115 +210,107 @@
  * clock vote in the driver and the save-restore code uses 1. above
  * for its vote
  */
-static void etm_set_pwrdwn(int cpu)
+static void etm_set_pwrdwn(struct etm_drvdata *drvdata)
 {
 	uint32_t etmcr;
 
-	etmcr = etm_readl(drvdata, cpu, ETMCR);
+	etmcr = etm_readl(drvdata, ETMCR);
 	etmcr |= BIT(0);
-	etm_writel(drvdata, cpu, etmcr, ETMCR);
+	etm_writel(drvdata, etmcr, ETMCR);
 }
 
-static void etm_clr_pwrdwn(int cpu)
+static void etm_clr_pwrdwn(struct etm_drvdata *drvdata)
 {
 	uint32_t etmcr;
 
-	etmcr = etm_readl(drvdata, cpu, ETMCR);
+	etmcr = etm_readl(drvdata, ETMCR);
 	etmcr &= ~BIT(0);
-	etm_writel(drvdata, cpu, etmcr, ETMCR);
+	etm_writel(drvdata, etmcr, ETMCR);
 }
 
-static void etm_set_prog(int cpu)
+static void etm_set_prog(struct etm_drvdata *drvdata)
 {
 	uint32_t etmcr;
 	int count;
 
-	etmcr = etm_readl(drvdata, cpu, ETMCR);
+	etmcr = etm_readl(drvdata, ETMCR);
 	etmcr |= BIT(10);
-	etm_writel(drvdata, cpu, etmcr, ETMCR);
-
-	for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 1
+	etm_writel(drvdata, etmcr, ETMCR);
+	for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 1
 				&& count > 0; count--)
 		udelay(1);
 	WARN(count == 0, "timeout while setting prog bit, ETMSR: %#x\n",
-	     etm_readl(drvdata, cpu, ETMSR));
+	     etm_readl(drvdata, ETMSR));
 }
 
-static void etm_clr_prog(int cpu)
+static void etm_clr_prog(struct etm_drvdata *drvdata)
 {
 	uint32_t etmcr;
 	int count;
 
-	etmcr = etm_readl(drvdata, cpu, ETMCR);
+	etmcr = etm_readl(drvdata, ETMCR);
 	etmcr &= ~BIT(10);
-	etm_writel(drvdata, cpu, etmcr, ETMCR);
-
-	for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, cpu, ETMSR), 1) != 0
+	etm_writel(drvdata, etmcr, ETMCR);
+	for (count = TIMEOUT_US; BVAL(etm_readl(drvdata, ETMSR), 1) != 0
 				&& count > 0; count--)
 		udelay(1);
 	WARN(count == 0, "timeout while clearing prog bit, ETMSR: %#x\n",
-	     etm_readl(drvdata, cpu, ETMSR));
+	     etm_readl(drvdata, ETMSR));
 }
 
-static void __etm_enable(int cpu)
+static void __etm_enable(struct etm_drvdata *drvdata)
 {
 	int i;
 
-	ETM_UNLOCK(cpu);
+	ETM_UNLOCK(drvdata);
 	/* Vote for ETM power/clock enable */
-	etm_clr_pwrdwn(cpu);
-	etm_set_prog(cpu);
+	etm_clr_pwrdwn(drvdata);
+	etm_set_prog(drvdata);
 
-	etm_writel(drvdata, cpu, drvdata->ctrl | BIT(10), ETMCR);
-	etm_writel(drvdata, cpu, drvdata->trigger_event, ETMTRIGGER);
-	etm_writel(drvdata, cpu, drvdata->startstop_ctrl, ETMTSSCR);
-	etm_writel(drvdata, cpu, drvdata->enable_event, ETMTEEVR);
-	etm_writel(drvdata, cpu, drvdata->enable_ctrl1, ETMTECR1);
-	etm_writel(drvdata, cpu, drvdata->fifofull_level, ETMFFLR);
+	etm_writel(drvdata, drvdata->ctrl | BIT(10), ETMCR);
+	etm_writel(drvdata, drvdata->trigger_event, ETMTRIGGER);
+	etm_writel(drvdata, drvdata->startstop_ctrl, ETMTSSCR);
+	etm_writel(drvdata, drvdata->enable_event, ETMTEEVR);
+	etm_writel(drvdata, drvdata->enable_ctrl1, ETMTECR1);
+	etm_writel(drvdata, drvdata->fifofull_level, ETMFFLR);
 	for (i = 0; i < drvdata->nr_addr_cmp; i++) {
-		etm_writel(drvdata, cpu, drvdata->addr_val[i], ETMACVRn(i));
-		etm_writel(drvdata, cpu, drvdata->addr_acctype[i], ETMACTRn(i));
+		etm_writel(drvdata, drvdata->addr_val[i], ETMACVRn(i));
+		etm_writel(drvdata, drvdata->addr_acctype[i], ETMACTRn(i));
 	}
 	for (i = 0; i < drvdata->nr_cntr; i++) {
-		etm_writel(drvdata, cpu, drvdata->cntr_rld_val[i],
-			   ETMCNTRLDVRn(i));
-		etm_writel(drvdata, cpu, drvdata->cntr_event[i], ETMCNTENRn(i));
-		etm_writel(drvdata, cpu, drvdata->cntr_rld_event[i],
+		etm_writel(drvdata, drvdata->cntr_rld_val[i], ETMCNTRLDVRn(i));
+		etm_writel(drvdata, drvdata->cntr_event[i], ETMCNTENRn(i));
+		etm_writel(drvdata, drvdata->cntr_rld_event[i],
 			   ETMCNTRLDEVRn(i));
-		etm_writel(drvdata, cpu, drvdata->cntr_val[i], ETMCNTVRn(i));
+		etm_writel(drvdata, drvdata->cntr_val[i], ETMCNTVRn(i));
 	}
-	etm_writel(drvdata, cpu, drvdata->seq_12_event, ETMSQ12EVR);
-	etm_writel(drvdata, cpu, drvdata->seq_21_event, ETMSQ21EVR);
-	etm_writel(drvdata, cpu, drvdata->seq_23_event, ETMSQ23EVR);
-	etm_writel(drvdata, cpu, drvdata->seq_31_event, ETMSQ31EVR);
-	etm_writel(drvdata, cpu, drvdata->seq_32_event, ETMSQ32EVR);
-	etm_writel(drvdata, cpu, drvdata->seq_13_event, ETMSQ13EVR);
-	etm_writel(drvdata, cpu, drvdata->seq_curr_state, ETMSQR);
+	etm_writel(drvdata, drvdata->seq_12_event, ETMSQ12EVR);
+	etm_writel(drvdata, drvdata->seq_21_event, ETMSQ21EVR);
+	etm_writel(drvdata, drvdata->seq_23_event, ETMSQ23EVR);
+	etm_writel(drvdata, drvdata->seq_31_event, ETMSQ31EVR);
+	etm_writel(drvdata, drvdata->seq_32_event, ETMSQ32EVR);
+	etm_writel(drvdata, drvdata->seq_13_event, ETMSQ13EVR);
+	etm_writel(drvdata, drvdata->seq_curr_state, ETMSQR);
 	for (i = 0; i < drvdata->nr_ext_out; i++)
-		etm_writel(drvdata, cpu, 0x0000406F, ETMEXTOUTEVRn(i));
+		etm_writel(drvdata, 0x0000406F, ETMEXTOUTEVRn(i));
 	for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
-		etm_writel(drvdata, cpu, drvdata->ctxid_val[i], ETMCIDCVRn(i));
-	etm_writel(drvdata, cpu, drvdata->ctxid_mask, ETMCIDCMR);
-	etm_writel(drvdata, cpu, drvdata->sync_freq, ETMSYNCFR);
-	etm_writel(drvdata, cpu, 0x00000000, ETMEXTINSELR);
-	etm_writel(drvdata, cpu, drvdata->timestamp_event, ETMTSEVR);
-	etm_writel(drvdata, cpu, 0x00000000, ETMAUXCR);
-	etm_writel(drvdata, cpu, cpu+1, ETMTRACEIDR);
-	etm_writel(drvdata, cpu, 0x00000000, ETMVMIDCVR);
+		etm_writel(drvdata, drvdata->ctxid_val[i], ETMCIDCVRn(i));
+	etm_writel(drvdata, drvdata->ctxid_mask, ETMCIDCMR);
+	etm_writel(drvdata, drvdata->sync_freq, ETMSYNCFR);
+	etm_writel(drvdata, 0x00000000, ETMEXTINSELR);
+	etm_writel(drvdata, drvdata->timestamp_event, ETMTSEVR);
+	etm_writel(drvdata, 0x00000000, ETMAUXCR);
+	etm_writel(drvdata, drvdata->cpu + 1, ETMTRACEIDR);
+	etm_writel(drvdata, 0x00000000, ETMVMIDCVR);
 
-	etm_clr_prog(cpu);
-	ETM_LOCK(cpu);
+	etm_clr_prog(drvdata);
+	ETM_LOCK(drvdata);
 }
 
-static int etm_enable(void)
+static int etm_enable(struct coresight_device *csdev)
 {
-	int ret, cpu;
-
-	if (drvdata->enabled) {
-		dev_err(drvdata->dev, "ETM tracing already enabled\n");
-		ret = -EPERM;
-		goto err;
-	}
+	struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	int ret;
 
 	wake_lock(&drvdata->wake_lock);
 	/* 1. causes all online cpus to come out of idle PC
@@ -342,52 +326,37 @@
 	if (ret)
 		goto err_clk;
 
-	ret = qdss_enable(drvdata->src);
-	if (ret)
-		goto err_qdss;
-
-	for_each_online_cpu(cpu)
-		__etm_enable(cpu);
-
-	drvdata->enabled = true;
+	mutex_lock(&drvdata->mutex);
+	__etm_enable(drvdata);
+	mutex_unlock(&drvdata->mutex);
 
 	pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
 	wake_unlock(&drvdata->wake_lock);
 
 	dev_info(drvdata->dev, "ETM tracing enabled\n");
 	return 0;
-
-err_qdss:
-	clk_disable_unprepare(drvdata->clk);
 err_clk:
 	pm_qos_update_request(&drvdata->qos_req, PM_QOS_DEFAULT_VALUE);
 	wake_unlock(&drvdata->wake_lock);
-err:
 	return ret;
 }
 
-static void __etm_disable(int cpu)
+static void __etm_disable(struct etm_drvdata *drvdata)
 {
-	ETM_UNLOCK(cpu);
-	etm_set_prog(cpu);
+	ETM_UNLOCK(drvdata);
+	etm_set_prog(drvdata);
 
 	/* program trace enable to low by using always false event */
-	etm_writel(drvdata, cpu, 0x6F | BIT(14), ETMTEEVR);
+	etm_writel(drvdata, 0x6F | BIT(14), ETMTEEVR);
 
 	/* Vote for ETM power/clock disable */
-	etm_set_pwrdwn(cpu);
-	ETM_LOCK(cpu);
+	etm_set_pwrdwn(drvdata);
+	ETM_LOCK(drvdata);
 }
 
-static int etm_disable(void)
+static void etm_disable(struct coresight_device *csdev)
 {
-	int ret, cpu;
-
-	if (!drvdata->enabled) {
-		dev_err(drvdata->dev, "ETM tracing already disabled\n");
-		ret = -EPERM;
-		goto err;
-	}
+	struct etm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 
 	wake_lock(&drvdata->wake_lock);
 	/* 1. causes all online cpus to come out of idle PC
@@ -399,12 +368,9 @@
 	 */
 	pm_qos_update_request(&drvdata->qos_req, 0);
 
-	for_each_online_cpu(cpu)
-		__etm_disable(cpu);
-
-	drvdata->enabled = false;
-
-	qdss_disable(drvdata->src);
+	mutex_lock(&drvdata->mutex);
+	__etm_disable(drvdata);
+	mutex_unlock(&drvdata->mutex);
 
 	clk_disable_unprepare(drvdata->clk);
 
@@ -412,55 +378,23 @@
 	wake_unlock(&drvdata->wake_lock);
 
 	dev_info(drvdata->dev, "ETM tracing disabled\n");
-	return 0;
-err:
-	return ret;
 }
 
-/* Memory mapped writes to clear os lock not supported */
-static void etm_os_unlock(void *unused)
-{
-	unsigned long value = 0x0;
+static const struct coresight_ops_source etm_source_ops = {
+	.enable		= etm_enable,
+	.disable	= etm_disable,
+};
 
-	asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
-	asm("isb\n\t");
-}
-
-static ssize_t etm_show_enabled(struct device *dev,
-				struct device_attribute *attr, char *buf)
-{
-	unsigned long val = drvdata->enabled;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-
-static ssize_t etm_store_enabled(struct device *dev,
-				 struct device_attribute *attr,
-				 const char *buf, size_t size)
-{
-	int ret = 0;
-	unsigned long val;
-
-	if (sscanf(buf, "%lx", &val) != 1)
-		return -EINVAL;
-
-	mutex_lock(&drvdata->mutex);
-	if (val)
-		ret = etm_enable();
-	else
-		ret = etm_disable();
-	mutex_unlock(&drvdata->mutex);
-
-	if (ret)
-		return ret;
-	return size;
-}
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, etm_show_enabled,
-		   etm_store_enabled);
+static const struct coresight_ops etm_cs_ops = {
+	.source_ops	= &etm_source_ops,
+};
 
 static ssize_t etm_show_nr_addr_cmp(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->nr_addr_cmp;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 static DEVICE_ATTR(nr_addr_cmp, S_IRUGO, etm_show_nr_addr_cmp, NULL);
@@ -468,7 +402,9 @@
 static ssize_t etm_show_nr_cntr(struct device *dev,
 				struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->nr_cntr;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 static DEVICE_ATTR(nr_cntr, S_IRUGO, etm_show_nr_cntr, NULL);
@@ -476,7 +412,9 @@
 static ssize_t etm_show_nr_ctxid_cmp(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->nr_ctxid_cmp;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 static DEVICE_ATTR(nr_ctxid_cmp, S_IRUGO, etm_show_nr_ctxid_cmp, NULL);
@@ -484,7 +422,9 @@
 static ssize_t etm_show_reset(struct device *dev, struct device_attribute *attr,
 			      char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->reset;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -493,6 +433,7 @@
 			       struct device_attribute *attr, const char *buf,
 			       size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	int i;
 	unsigned long val;
 
@@ -536,7 +477,11 @@
 		for (i = 0; i < drvdata->nr_ctxid_cmp; i++)
 			drvdata->ctxid_val[i] = 0x0;
 		drvdata->ctxid_mask = 0x0;
-		drvdata->sync_freq = 0x80;
+		/* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
+		if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
+			drvdata->sync_freq = 0x100;
+		else
+			drvdata->sync_freq = 0x80;
 		drvdata->timestamp_event = 0x406F;
 	}
 	mutex_unlock(&drvdata->mutex);
@@ -547,13 +492,16 @@
 static ssize_t etm_show_mode(struct device *dev, struct device_attribute *attr,
 			      char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->mode;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
 static ssize_t etm_store_mode(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -581,6 +529,7 @@
 		drvdata->ctrl |= BIT(28);
 	else
 		drvdata->ctrl &= ~BIT(28);
+
 	if (drvdata->mode & ETM_MODE_CTXID)
 		drvdata->ctrl |= (BIT(14) | BIT(15));
 	else
@@ -594,7 +543,9 @@
 static ssize_t etm_show_trigger_event(struct device *dev,
 				      struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->trigger_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -602,6 +553,7 @@
 				       struct device_attribute *attr,
 				       const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -616,7 +568,9 @@
 static ssize_t etm_show_enable_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->enable_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -624,6 +578,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -638,7 +593,9 @@
 static ssize_t etm_show_fifofull_level(struct device *dev,
 				       struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->fifofull_level;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -646,6 +603,7 @@
 					struct device_attribute *attr,
 					const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -660,7 +618,9 @@
 static ssize_t etm_show_addr_idx(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->addr_idx;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -668,6 +628,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -689,6 +650,7 @@
 static ssize_t etm_show_addr_single(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 	uint8_t idx;
 
@@ -709,6 +671,7 @@
 				     struct device_attribute *attr,
 				     const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 	uint8_t idx;
 
@@ -734,6 +697,7 @@
 static ssize_t etm_show_addr_range(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val1, val2;
 	uint8_t idx;
 
@@ -761,6 +725,7 @@
 				    struct device_attribute *attr,
 				    const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val1, val2;
 	uint8_t idx;
 
@@ -798,6 +763,7 @@
 static ssize_t etm_show_addr_start(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 	uint8_t idx;
 
@@ -818,6 +784,7 @@
 				    struct device_attribute *attr,
 				    const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 	uint8_t idx;
 
@@ -845,6 +812,7 @@
 static ssize_t etm_show_addr_stop(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 	uint8_t idx;
 
@@ -865,6 +833,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 	uint8_t idx;
 
@@ -892,6 +861,7 @@
 static ssize_t etm_show_addr_acctype(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	mutex_lock(&drvdata->mutex);
@@ -904,6 +874,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -920,7 +891,9 @@
 static ssize_t etm_show_cntr_idx(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->addr_idx;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -928,6 +901,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -949,7 +923,9 @@
 static ssize_t etm_show_cntr_rld_val(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
+
 	mutex_lock(&drvdata->mutex);
 	val = drvdata->cntr_rld_val[drvdata->cntr_idx];
 	mutex_unlock(&drvdata->mutex);
@@ -960,6 +936,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -976,6 +953,7 @@
 static ssize_t etm_show_cntr_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	mutex_lock(&drvdata->mutex);
@@ -988,6 +966,7 @@
 				    struct device_attribute *attr,
 				    const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1004,6 +983,7 @@
 static ssize_t etm_show_cntr_rld_event(struct device *dev,
 				       struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	mutex_lock(&drvdata->mutex);
@@ -1016,6 +996,7 @@
 					struct device_attribute *attr,
 					const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1032,6 +1013,7 @@
 static ssize_t etm_show_cntr_val(struct device *dev,
 				 struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	mutex_lock(&drvdata->mutex);
@@ -1044,6 +1026,7 @@
 				  struct device_attribute *attr,
 				  const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1060,7 +1043,9 @@
 static ssize_t etm_show_seq_12_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->seq_12_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1068,6 +1053,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1082,7 +1068,9 @@
 static ssize_t etm_show_seq_21_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->seq_21_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1090,6 +1078,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1104,7 +1093,9 @@
 static ssize_t etm_show_seq_23_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->seq_23_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1112,6 +1103,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1126,7 +1118,9 @@
 static ssize_t etm_show_seq_31_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->seq_31_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1134,6 +1128,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1148,7 +1143,9 @@
 static ssize_t etm_show_seq_32_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->seq_32_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1156,6 +1153,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1170,7 +1168,9 @@
 static ssize_t etm_show_seq_13_event(struct device *dev,
 				     struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->seq_13_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1178,6 +1178,7 @@
 				      struct device_attribute *attr,
 				      const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1192,7 +1193,9 @@
 static ssize_t etm_show_seq_curr_state(struct device *dev,
 				       struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->seq_curr_state;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1200,6 +1203,7 @@
 					struct device_attribute *attr,
 					const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1216,7 +1220,9 @@
 static ssize_t etm_show_ctxid_idx(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->ctxid_idx;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1224,6 +1230,7 @@
 				   struct device_attribute *attr,
 				   const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1245,6 +1252,7 @@
 static ssize_t etm_show_ctxid_val(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	mutex_lock(&drvdata->mutex);
@@ -1257,6 +1265,7 @@
 				   struct device_attribute *attr,
 				   const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1273,7 +1282,9 @@
 static ssize_t etm_show_ctxid_mask(struct device *dev,
 				   struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->ctxid_mask;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1281,6 +1292,7 @@
 				    struct device_attribute *attr,
 				    const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1295,6 +1307,7 @@
 static ssize_t etm_show_sync_freq(struct device *dev,
 				  struct device_attribute *attr, char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->sync_freq;
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
@@ -1303,6 +1316,7 @@
 				   struct device_attribute *attr,
 				   const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1318,7 +1332,9 @@
 					struct device_attribute *attr,
 					char *buf)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->timestamp_event;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -1326,6 +1342,7 @@
 					 struct device_attribute *attr,
 					 const char *buf, size_t size)
 {
+	struct etm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -1376,39 +1393,18 @@
 	.attrs = etm_attrs,
 };
 
-static int __devinit etm_sysfs_init(void)
+static const struct attribute_group *etm_attr_grps[] = {
+	&etm_attr_grp,
+	NULL,
+};
+
+/* Memory mapped writes to clear os lock not supported */
+static void etm_os_unlock(void *unused)
 {
-	int ret;
+	unsigned long value = 0x0;
 
-	drvdata->kobj = kobject_create_and_add("etm", qdss_get_modulekobj());
-	if (!drvdata->kobj) {
-		dev_err(drvdata->dev, "failed to create ETM sysfs kobject\n");
-		ret = -ENOMEM;
-		goto err_create;
-	}
-
-	ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
-	if (ret) {
-		dev_err(drvdata->dev, "failed to create ETM sysfs enabled"
-		" attribute\n");
-		goto err_file;
-	}
-
-	if (sysfs_create_group(drvdata->kobj, &etm_attr_grp))
-		dev_err(drvdata->dev, "failed to create ETM sysfs group\n");
-
-	return 0;
-err_file:
-	kobject_put(drvdata->kobj);
-err_create:
-	return ret;
-}
-
-static void __devexit etm_sysfs_exit(void)
-{
-	sysfs_remove_group(drvdata->kobj, &etm_attr_grp);
-	sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
-	kobject_put(drvdata->kobj);
+	asm("mcr p14, 1, %0, c1, c0, 4\n\t" : : "r" (value));
+	asm("isb\n\t");
 }
 
 static bool __devinit etm_arch_supported(uint8_t arch)
@@ -1422,34 +1418,32 @@
 	return true;
 }
 
-static int __devinit etm_init_arch_data(void)
+static int __devinit etm_init_arch_data(struct etm_drvdata *drvdata)
 {
 	int ret;
-	/* use cpu 0 for setup */
-	int cpu = 0;
 	uint32_t etmidr;
 	uint32_t etmccr;
 
 	/* Unlock OS lock first to allow memory mapped reads and writes */
 	etm_os_unlock(NULL);
 	smp_call_function(etm_os_unlock, NULL, 1);
-	ETM_UNLOCK(cpu);
+	ETM_UNLOCK(drvdata);
 	/* Vote for ETM power/clock enable */
-	etm_clr_pwrdwn(cpu);
+	etm_clr_pwrdwn(drvdata);
 	/* Set prog bit. It will be set from reset but this is included to
 	 * ensure it is set
 	 */
-	etm_set_prog(cpu);
+	etm_set_prog(drvdata);
 
 	/* find all capabilities */
-	etmidr = etm_readl(drvdata, cpu, ETMIDR);
+	etmidr = etm_readl(drvdata, ETMIDR);
 	drvdata->arch = BMVAL(etmidr, 4, 11);
 	if (etm_arch_supported(drvdata->arch) == false) {
 		ret = -EINVAL;
 		goto err;
 	}
 
-	etmccr = etm_readl(drvdata, cpu, ETMCCR);
+	etmccr = etm_readl(drvdata, ETMCCR);
 	drvdata->nr_addr_cmp = BMVAL(etmccr, 0, 3) * 2;
 	drvdata->nr_cntr = BMVAL(etmccr, 13, 15);
 	drvdata->nr_ext_inp = BMVAL(etmccr, 17, 19);
@@ -1457,15 +1451,15 @@
 	drvdata->nr_ctxid_cmp = BMVAL(etmccr, 24, 25);
 
 	/* Vote for ETM power/clock disable */
-	etm_set_pwrdwn(cpu);
-	ETM_LOCK(cpu);
+	etm_set_pwrdwn(drvdata);
+	ETM_LOCK(drvdata);
 
 	return 0;
 err:
 	return ret;
 }
 
-static void __devinit etm_init_default_data(void)
+static void __devinit etm_init_default_data(struct etm_drvdata *drvdata)
 {
 	int i;
 
@@ -1489,7 +1483,11 @@
 	drvdata->seq_31_event = 0x406F;
 	drvdata->seq_32_event = 0x406F;
 	drvdata->seq_13_event = 0x406F;
-	drvdata->sync_freq = 0x80;
+	/* Bits[7:0] of ETMSYNCFR are reserved on Krait pass3 onwards */
+	if (cpu_is_krait() && !cpu_is_krait_v1() && !cpu_is_krait_v2())
+		drvdata->sync_freq = 0x100;
+	else
+		drvdata->sync_freq = 0x80;
 	drvdata->timestamp_event = 0x406F;
 
 	/* Overrides for Krait pass1 */
@@ -1511,112 +1509,108 @@
 static int __devinit etm_probe(struct platform_device *pdev)
 {
 	int ret;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct etm_drvdata *drvdata;
 	struct resource *res;
+	static int etm_count;
+	struct coresight_desc *desc;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto err_kzalloc_drvdata;
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
 	}
 
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -EINVAL;
-		goto err_res;
-	}
+	if (!res)
+		return -ENODEV;
 
-	drvdata->base = ioremap_nocache(res->start, resource_size(res));
-	if (!drvdata->base) {
-		ret = -EINVAL;
-		goto err_ioremap;
-	}
-
-	drvdata->dev = &pdev->dev;
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
 
 	mutex_init(&drvdata->mutex);
-	wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "msm_etm");
+	wake_lock_init(&drvdata->wake_lock, WAKE_LOCK_SUSPEND, "coresight-etm");
 	pm_qos_add_request(&drvdata->qos_req, PM_QOS_CPU_DMA_LATENCY,
 			   PM_QOS_DEFAULT_VALUE);
-	drvdata->src = qdss_get("msm_etm");
-	if (IS_ERR(drvdata->src)) {
-		ret = PTR_ERR(drvdata->src);
-		goto err_qdssget;
-	}
 
-	drvdata->clk = clk_get(drvdata->dev, "core_clk");
+	drvdata->clk = devm_clk_get(dev, "core_clk");
 	if (IS_ERR(drvdata->clk)) {
 		ret = PTR_ERR(drvdata->clk);
-		goto err_clk_get;
+		goto err0;
 	}
 
 	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
 	if (ret)
-		goto err_clk_rate;
+		goto err0;
+
+	drvdata->cpu = etm_count++;
 
 	ret = clk_prepare_enable(drvdata->clk);
 	if (ret)
-		goto err_clk_enable;
+		goto err0;
 
-	ret = etm_init_arch_data();
+	ret = etm_init_arch_data(drvdata);
 	if (ret)
-		goto err_arch;
-
-	etm_init_default_data();
-
-	ret = etm_sysfs_init();
-	if (ret)
-		goto err_sysfs;
-
-	drvdata->enabled = false;
+		goto err1;
+	etm_init_default_data(drvdata);
 
 	clk_disable_unprepare(drvdata->clk);
 
-	dev_info(drvdata->dev, "ETM initialized\n");
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto err0;
+	}
+	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_PROC;
+	desc->ops = &etm_cs_ops;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->groups = etm_attr_grps;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev)) {
+		ret = PTR_ERR(drvdata->csdev);
+		goto err0;
+	}
 
-	if (etm_boot_enable)
-		etm_enable();
+	dev_info(dev, "ETM initialized\n");
+
+	if (boot_enable)
+		coresight_enable(drvdata->csdev);
 
 	return 0;
-
-err_sysfs:
-err_arch:
+err1:
 	clk_disable_unprepare(drvdata->clk);
-err_clk_enable:
-err_clk_rate:
-	clk_put(drvdata->clk);
-err_clk_get:
-	qdss_put(drvdata->src);
-err_qdssget:
+err0:
 	pm_qos_remove_request(&drvdata->qos_req);
 	wake_lock_destroy(&drvdata->wake_lock);
 	mutex_destroy(&drvdata->mutex);
-	iounmap(drvdata->base);
-err_ioremap:
-err_res:
-	kfree(drvdata);
-err_kzalloc_drvdata:
-	dev_err(drvdata->dev, "ETM init failed\n");
 	return ret;
 }
 
 static int __devexit etm_remove(struct platform_device *pdev)
 {
-	if (drvdata->enabled)
-		etm_disable();
-	etm_sysfs_exit();
-	clk_put(drvdata->clk);
-	qdss_put(drvdata->src);
+	struct etm_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	coresight_unregister(drvdata->csdev);
 	pm_qos_remove_request(&drvdata->qos_req);
 	wake_lock_destroy(&drvdata->wake_lock);
 	mutex_destroy(&drvdata->mutex);
-	iounmap(drvdata->base);
-	kfree(drvdata);
-
 	return 0;
 }
 
 static struct of_device_id etm_match[] = {
-	{.compatible = "qcom,msm-etm"},
+	{.compatible = "arm,coresight-etm"},
 	{}
 };
 
@@ -1624,7 +1618,7 @@
 	.probe          = etm_probe,
 	.remove         = __devexit_p(etm_remove),
 	.driver         = {
-		.name   = "msm_etm",
+		.name   = "coresight-etm",
 		.owner	= THIS_MODULE,
 		.of_match_table = etm_match,
 	},
diff --git a/drivers/coresight/coresight-funnel.c b/drivers/coresight/coresight-funnel.c
index 79a27f4..3d5c0c2 100644
--- a/drivers/coresight/coresight-funnel.c
+++ b/drivers/coresight/coresight-funnel.c
@@ -20,113 +20,118 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/of_coresight.h>
 #include <linux/coresight.h>
 
 #include "coresight-priv.h"
 
-#define funnel_writel(drvdata, id, val, off)	\
-			__raw_writel((val), drvdata->base + (SZ_4K * id) + off)
-#define funnel_readl(drvdata, id, off)		\
-			__raw_readl(drvdata->base + (SZ_4K * id) + off)
+#define funnel_writel(drvdata, val, off)	\
+			__raw_writel((val), drvdata->base + off)
+#define funnel_readl(drvdata, off)		\
+			__raw_readl(drvdata->base + off)
 
-#define FUNNEL_FUNCTL			(0x000)
-#define FUNNEL_PRICTL			(0x004)
-#define FUNNEL_ITATBDATA0		(0xEEC)
-#define FUNNEL_ITATBCTR2		(0xEF0)
-#define FUNNEL_ITATBCTR1		(0xEF4)
-#define FUNNEL_ITATBCTR0		(0xEF8)
-
-
-#define FUNNEL_LOCK(id)							\
+#define FUNNEL_LOCK(drvdata)						\
 do {									\
 	mb();								\
-	funnel_writel(drvdata, id, 0x0, CORESIGHT_LAR);			\
+	funnel_writel(drvdata, 0x0, CORESIGHT_LAR);			\
 } while (0)
-#define FUNNEL_UNLOCK(id)						\
+#define FUNNEL_UNLOCK(drvdata)						\
 do {									\
-	funnel_writel(drvdata, id, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
+	funnel_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
 	mb();								\
 } while (0)
 
-#define FUNNEL_HOLDTIME_MASK		(0xF00)
-#define FUNNEL_HOLDTIME_SHFT		(0x8)
-#define FUNNEL_HOLDTIME			(0x7 << FUNNEL_HOLDTIME_SHFT)
+#define FUNNEL_FUNCTL		(0x000)
+#define FUNNEL_PRICTL		(0x004)
+#define FUNNEL_ITATBDATA0	(0xEEC)
+#define FUNNEL_ITATBCTR2	(0xEF0)
+#define FUNNEL_ITATBCTR1	(0xEF4)
+#define FUNNEL_ITATBCTR0	(0xEF8)
+
+#define FUNNEL_HOLDTIME_MASK	(0xF00)
+#define FUNNEL_HOLDTIME_SHFT	(0x8)
+#define FUNNEL_HOLDTIME		(0x7 << FUNNEL_HOLDTIME_SHFT)
 
 struct funnel_drvdata {
-	void __iomem	*base;
-	bool		enabled;
-	struct mutex	mutex;
-	struct device	*dev;
-	struct kobject	*kobj;
-	struct clk	*clk;
-	uint32_t	priority;
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	struct clk		*clk;
+	uint32_t		priority;
 };
 
-static struct funnel_drvdata *drvdata;
-
-static void __funnel_enable(uint8_t id, uint32_t port_mask)
+static void __funnel_enable(struct funnel_drvdata *drvdata, int port)
 {
 	uint32_t functl;
 
-	FUNNEL_UNLOCK(id);
+	FUNNEL_UNLOCK(drvdata);
 
-	functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
+	functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
 	functl &= ~FUNNEL_HOLDTIME_MASK;
 	functl |= FUNNEL_HOLDTIME;
-	functl |= port_mask;
-	funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
-	funnel_writel(drvdata, id, drvdata->priority, FUNNEL_PRICTL);
+	functl |= (1 << port);
+	funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
+	funnel_writel(drvdata, drvdata->priority, FUNNEL_PRICTL);
 
-	FUNNEL_LOCK(id);
+	FUNNEL_LOCK(drvdata);
 }
 
-int funnel_enable(uint8_t id, uint32_t port_mask)
+static int funnel_enable(struct coresight_device *csdev, int inport,
+			 int outport)
 {
+	struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
 	int ret;
 
 	ret = clk_prepare_enable(drvdata->clk);
 	if (ret)
 		return ret;
 
-	mutex_lock(&drvdata->mutex);
-	__funnel_enable(id, port_mask);
-	drvdata->enabled = true;
-	dev_info(drvdata->dev, "FUNNEL port mask 0x%lx enabled\n",
-					(unsigned long) port_mask);
-	mutex_unlock(&drvdata->mutex);
+	__funnel_enable(drvdata, inport);
 
+	dev_info(drvdata->dev, "FUNNEL inport %d enabled\n", inport);
 	return 0;
 }
 
-static void __funnel_disable(uint8_t id, uint32_t port_mask)
+static void __funnel_disable(struct funnel_drvdata *drvdata, int inport)
 {
 	uint32_t functl;
 
-	FUNNEL_UNLOCK(id);
+	FUNNEL_UNLOCK(drvdata);
 
-	functl = funnel_readl(drvdata, id, FUNNEL_FUNCTL);
-	functl &= ~port_mask;
-	funnel_writel(drvdata, id, functl, FUNNEL_FUNCTL);
+	functl = funnel_readl(drvdata, FUNNEL_FUNCTL);
+	functl &= ~(1 << inport);
+	funnel_writel(drvdata, functl, FUNNEL_FUNCTL);
 
-	FUNNEL_LOCK(id);
+	FUNNEL_LOCK(drvdata);
 }
 
-void funnel_disable(uint8_t id, uint32_t port_mask)
+static void funnel_disable(struct coresight_device *csdev, int inport,
+			   int outport)
 {
-	mutex_lock(&drvdata->mutex);
-	__funnel_disable(id, port_mask);
-	drvdata->enabled = false;
-	dev_info(drvdata->dev, "FUNNEL port mask 0x%lx disabled\n",
-					(unsigned long) port_mask);
-	mutex_unlock(&drvdata->mutex);
+	struct funnel_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	__funnel_disable(drvdata, inport);
 
 	clk_disable_unprepare(drvdata->clk);
+
+	dev_info(drvdata->dev, "FUNNEL inport %d disabled\n", inport);
 }
 
+static const struct coresight_ops_link funnel_link_ops = {
+	.enable		= funnel_enable,
+	.disable	= funnel_disable,
+};
+
+static const struct coresight_ops funnel_cs_ops = {
+	.link_ops	= &funnel_link_ops,
+};
+
 static ssize_t funnel_show_priority(struct device *dev,
 				    struct device_attribute *attr, char *buf)
 {
+	struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->priority;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -134,6 +139,7 @@
 				     struct device_attribute *attr,
 				     const char *buf, size_t size)
 {
+	struct funnel_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -145,107 +151,86 @@
 static DEVICE_ATTR(priority, S_IRUGO | S_IWUSR, funnel_show_priority,
 		   funnel_store_priority);
 
-static int __devinit funnel_sysfs_init(void)
-{
-	int ret;
+static struct attribute *funnel_attrs[] = {
+	&dev_attr_priority.attr,
+	NULL,
+};
 
-	drvdata->kobj = kobject_create_and_add("funnel", qdss_get_modulekobj());
-	if (!drvdata->kobj) {
-		dev_err(drvdata->dev, "failed to create FUNNEL sysfs kobject\n");
-		ret = -ENOMEM;
-		goto err_create;
-	}
+static struct attribute_group funnel_attr_grp = {
+	.attrs = funnel_attrs,
+};
 
-	ret = sysfs_create_file(drvdata->kobj, &dev_attr_priority.attr);
-	if (ret) {
-		dev_err(drvdata->dev, "failed to create FUNNEL sysfs priority"
-		" attribute\n");
-		goto err_file;
-	}
-
-	return 0;
-err_file:
-	kobject_put(drvdata->kobj);
-err_create:
-	return ret;
-}
-
-static void __devexit funnel_sysfs_exit(void)
-{
-	sysfs_remove_file(drvdata->kobj, &dev_attr_priority.attr);
-	kobject_put(drvdata->kobj);
-}
+static const struct attribute_group *funnel_attr_grps[] = {
+	&funnel_attr_grp,
+	NULL,
+};
 
 static int __devinit funnel_probe(struct platform_device *pdev)
 {
 	int ret;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct funnel_drvdata *drvdata;
 	struct resource *res;
+	struct coresight_desc *desc;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto err_kzalloc_drvdata;
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
 	}
 
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -EINVAL;
-		goto err_res;
-	}
+	if (!res)
+		return -ENODEV;
 
-	drvdata->base = ioremap_nocache(res->start, resource_size(res));
-	if (!drvdata->base) {
-		ret = -EINVAL;
-		goto err_ioremap;
-	}
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
 
-	drvdata->dev = &pdev->dev;
-
-	mutex_init(&drvdata->mutex);
-
-	drvdata->clk = clk_get(drvdata->dev, "core_clk");
-	if (IS_ERR(drvdata->clk)) {
-		ret = PTR_ERR(drvdata->clk);
-		goto err_clk_get;
-	}
+	drvdata->clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(drvdata->clk))
+		return PTR_ERR(drvdata->clk);
 
 	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
 	if (ret)
-		goto err_clk_rate;
+		return ret;
 
-	funnel_sysfs_init();
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_LINK;
+	desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_MERG;
+	desc->ops = &funnel_cs_ops;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->groups = funnel_attr_grps;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
 
-	dev_info(drvdata->dev, "FUNNEL initialized\n");
+	dev_info(dev, "FUNNEL initialized\n");
 	return 0;
-
-err_clk_rate:
-	clk_put(drvdata->clk);
-err_clk_get:
-	mutex_destroy(&drvdata->mutex);
-	iounmap(drvdata->base);
-err_ioremap:
-err_res:
-	kfree(drvdata);
-err_kzalloc_drvdata:
-	dev_err(drvdata->dev, "FUNNEL init failed\n");
-	return ret;
 }
 
 static int __devexit funnel_remove(struct platform_device *pdev)
 {
-	if (drvdata->enabled)
-		funnel_disable(0x0, 0xFF);
-	funnel_sysfs_exit();
-	clk_put(drvdata->clk);
-	mutex_destroy(&drvdata->mutex);
-	iounmap(drvdata->base);
-	kfree(drvdata);
+	struct funnel_drvdata *drvdata = platform_get_drvdata(pdev);
 
+	coresight_unregister(drvdata->csdev);
 	return 0;
 }
 
 static struct of_device_id funnel_match[] = {
-	{.compatible = "qcom,msm-funnel"},
+	{.compatible = "arm,coresight-funnel"},
 	{}
 };
 
@@ -253,7 +238,7 @@
 	.probe          = funnel_probe,
 	.remove         = __devexit_p(funnel_remove),
 	.driver         = {
-		.name   = "msm_funnel",
+		.name   = "coresight-funnel",
 		.owner	= THIS_MODULE,
 		.of_match_table = funnel_match,
 	},
diff --git a/drivers/coresight/coresight-priv.h b/drivers/coresight/coresight-priv.h
index dab854c..a28a3a5 100644
--- a/drivers/coresight/coresight-priv.h
+++ b/drivers/coresight/coresight-priv.h
@@ -36,13 +36,4 @@
 #define BMVAL(val, lsb, msb)	((val & BM(lsb, msb)) >> lsb)
 #define BVAL(val, n)		((val & BIT(n)) >> n)
 
-int etb_enable(void);
-void etb_disable(void);
-void etb_dump(void);
-void tpiu_disable(void);
-int funnel_enable(uint8_t id, uint32_t port_mask);
-void funnel_disable(uint8_t id, uint32_t port_mask);
-
-struct kobject *qdss_get_modulekobj(void);
-
 #endif
diff --git a/drivers/coresight/coresight-replicator.c b/drivers/coresight/coresight-replicator.c
new file mode 100644
index 0000000..fec76c5
--- /dev/null
+++ b/drivers/coresight/coresight-replicator.c
@@ -0,0 +1,211 @@
+/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+
+#include "coresight-priv.h"
+
+#define replicator_writel(drvdata, val, off)	\
+				__raw_writel((val), drvdata->base + off)
+#define replicator_readl(drvdata, off)		\
+				__raw_readl(drvdata->base + off)
+
+#define REPLICATOR_LOCK(drvdata)					\
+do {									\
+	mb();								\
+	replicator_writel(drvdata, 0x0, CORESIGHT_LAR);			\
+} while (0)
+#define REPLICATOR_UNLOCK(drvdata)					\
+do {									\
+	replicator_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);	\
+	mb();								\
+} while (0)
+
+#define REPLICATOR_IDFILTER0		(0x000)
+#define REPLICATOR_IDFILTER1		(0x004)
+#define REPLICATOR_ITATBCTR0		(0xEFC)
+#define REPLICATOR_ITATBCTR1		(0xEF8)
+
+struct replicator_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	struct clk		*clk;
+};
+
+static void __replicator_enable(struct replicator_drvdata *drvdata, int outport)
+{
+	REPLICATOR_UNLOCK(drvdata);
+
+	if (outport == 0) {
+		replicator_writel(drvdata, 0x0, REPLICATOR_IDFILTER0);
+		replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER1);
+	} else {
+		replicator_writel(drvdata, 0x0, REPLICATOR_IDFILTER1);
+		replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER0);
+	}
+
+	REPLICATOR_LOCK(drvdata);
+}
+
+static int replicator_enable(struct coresight_device *csdev, int inport,
+			     int outport)
+{
+	struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	int ret;
+
+	ret = clk_prepare_enable(drvdata->clk);
+	if (ret)
+		return ret;
+
+	__replicator_enable(drvdata, outport);
+
+	dev_info(drvdata->dev, "REPLICATOR enabled\n");
+	return 0;
+}
+
+static void __replicator_disable(struct replicator_drvdata *drvdata,
+				 int outport)
+{
+	REPLICATOR_UNLOCK(drvdata);
+
+	if (outport == 0)
+		replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER0);
+	else
+		replicator_writel(drvdata, 0xFF, REPLICATOR_IDFILTER1);
+
+	REPLICATOR_LOCK(drvdata);
+}
+
+static void replicator_disable(struct coresight_device *csdev, int inport,
+			       int outport)
+{
+	struct replicator_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	__replicator_disable(drvdata, outport);
+
+	clk_disable_unprepare(drvdata->clk);
+
+	dev_info(drvdata->dev, "REPLICATOR disabled\n");
+}
+
+static const struct coresight_ops_link replicator_link_ops = {
+	.enable		= replicator_enable,
+	.disable	= replicator_disable,
+};
+
+static const struct coresight_ops replicator_cs_ops = {
+	.link_ops	= &replicator_link_ops,
+};
+
+static int __devinit replicator_probe(struct platform_device *pdev)
+{
+	int ret;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct replicator_drvdata *drvdata;
+	struct resource *res;
+	struct coresight_desc *desc;
+
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
+	}
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	drvdata->clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(drvdata->clk))
+		return PTR_ERR(drvdata->clk);
+
+	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+	if (ret)
+		return ret;
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_LINK;
+	desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_LINK_SPLIT;
+	desc->ops = &replicator_cs_ops;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
+
+	dev_info(dev, "REPLICATOR initialized\n");
+	return 0;
+}
+
+static int __devexit replicator_remove(struct platform_device *pdev)
+{
+	struct replicator_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	coresight_unregister(drvdata->csdev);
+	return 0;
+}
+
+static struct of_device_id replicator_match[] = {
+	{.compatible = "qcom,coresight-replicator"},
+	{}
+};
+
+static struct platform_driver replicator_driver = {
+	.probe          = replicator_probe,
+	.remove         = __devexit_p(replicator_remove),
+	.driver         = {
+		.name   = "coresight-replicator",
+		.owner	= THIS_MODULE,
+		.of_match_table = replicator_match,
+	},
+};
+
+static int __init replicator_init(void)
+{
+	return platform_driver_register(&replicator_driver);
+}
+module_init(replicator_init);
+
+static void __exit replicator_exit(void)
+{
+	platform_driver_unregister(&replicator_driver);
+}
+module_exit(replicator_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Replicator driver");
diff --git a/drivers/coresight/coresight-stm.c b/drivers/coresight/coresight-stm.c
index 6387947..e366918 100644
--- a/drivers/coresight/coresight-stm.c
+++ b/drivers/coresight/coresight-stm.c
@@ -22,22 +22,69 @@
 #include <linux/miscdevice.h>
 #include <linux/uaccess.h>
 #include <linux/slab.h>
+#include <linux/delay.h>
 #include <linux/clk.h>
+#include <linux/of_coresight.h>
 #include <linux/coresight.h>
 #include <linux/coresight-stm.h>
 #include <asm/unaligned.h>
 
 #include "coresight-priv.h"
 
-#define stm_writel(drvdata, val, off)	\
-			__raw_writel((val), drvdata->base + off)
-#define stm_readl(drvdata, val, off)	\
-			__raw_readl(drvdata->base + off)
+#define stm_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
+#define stm_readl(drvdata, off)		__raw_readl(drvdata->base + off)
+
+#define STM_LOCK(drvdata)						\
+do {									\
+	mb();								\
+	stm_writel(drvdata, 0x0, CORESIGHT_LAR);			\
+} while (0)
+#define STM_UNLOCK(drvdata)						\
+do {									\
+	stm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
+	mb();								\
+} while (0)
+
+#define STMDMASTARTR		(0xC04)
+#define STMDMASTOPR		(0xC08)
+#define STMDMASTATR		(0xC0C)
+#define STMDMACTLR		(0xC10)
+#define STMDMAIDR		(0xCFC)
+#define STMHEER			(0xD00)
+#define STMHETER		(0xD20)
+#define STMHEMCR		(0xD64)
+#define STMHEMASTR		(0xDF4)
+#define STMHEFEAT1R		(0xDF8)
+#define STMHEIDR		(0xDFC)
+#define STMSPER			(0xE00)
+#define STMSPTER		(0xE20)
+#define STMSPSCR		(0xE60)
+#define STMSPMSCR		(0xE64)
+#define STMSPOVERRIDER		(0xE68)
+#define STMSPMOVERRIDER		(0xE6C)
+#define STMSPTRIGCSR		(0xE70)
+#define STMTCSR			(0xE80)
+#define STMTSSTIMR		(0xE84)
+#define STMTSFREQR		(0xE8C)
+#define STMSYNCR		(0xE90)
+#define STMAUXCR		(0xE94)
+#define STMSPFEAT1R		(0xEA0)
+#define STMSPFEAT2R		(0xEA4)
+#define STMSPFEAT3R		(0xEA8)
+#define STMITTRIGGER		(0xEE8)
+#define STMITATBDATA0		(0xEEC)
+#define STMITATBCTR2		(0xEF0)
+#define STMITATBID		(0xEF4)
+#define STMITATBCTR0		(0xEF8)
 
 #define NR_STM_CHANNEL		(32)
 #define BYTES_PER_CHANNEL	(256)
+#define STM_TRACE_BUF_SIZE	(1024)
 
-enum {
+#define OST_START_TOKEN		(0x30)
+#define OST_VERSION		(0x1)
+
+enum stm_pkt_type {
 	STM_PKT_TYPE_DATA	= 0x98,
 	STM_PKT_TYPE_FLAG	= 0xE8,
 	STM_PKT_TYPE_TRIG	= 0xF8,
@@ -47,45 +94,24 @@
 	STM_OPTION_MARKED	= 0x10,
 };
 
-#define STM_TRACE_BUF_SIZE	(1024)
-
-#define OST_START_TOKEN		(0x30)
-#define OST_VERSION		(0x1)
-
-#define stm_channel_addr(ch)						\
-				(drvdata->chs.base + (ch * BYTES_PER_CHANNEL))
+#define stm_channel_addr(drvdata, ch)	(drvdata->chs.base +	\
+					(ch * BYTES_PER_CHANNEL))
 #define stm_channel_off(type, opts)	(type & ~opts)
 
-#define STM_LOCK()							\
-do {									\
-	mb();								\
-	stm_writel(drvdata, 0x0, CORESIGHT_LAR);			\
-} while (0)
-#define STM_UNLOCK()							\
-do {									\
-	stm_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
-	mb();								\
-} while (0)
-
-#define STMSPER		(0xE00)
-#define STMSPTER	(0xE20)
-#define STMTCSR		(0xE80)
-#define STMSYNCR	(0xE90)
-
 #ifdef CONFIG_MSM_QDSS_STM_DEFAULT_ENABLE
-static int stm_boot_enable = 1;
+static int boot_enable = 1;
 #else
-static int stm_boot_enable;
+static int boot_enable;
 #endif
 
 module_param_named(
-	stm_boot_enable, stm_boot_enable, int, S_IRUGO
+	boot_enable, boot_enable, int, S_IRUGO
 );
 
-static int stm_boot_nr_channel;
+static int boot_nr_channel;
 
 module_param_named(
-	stm_boot_nr_channel, stm_boot_nr_channel, int, S_IRUGO
+	boot_nr_channel, boot_nr_channel, int, S_IRUGO
 );
 
 struct channel_space {
@@ -95,99 +121,202 @@
 
 struct stm_drvdata {
 	void __iomem		*base;
-	bool			enabled;
-	struct qdss_source	*src;
 	struct device		*dev;
-	struct kobject		*kobj;
+	struct coresight_device	*csdev;
+	struct miscdevice	miscdev;
 	struct clk		*clk;
-	uint32_t		entity;
+	spinlock_t		spinlock;
 	struct channel_space	chs;
+	bool			enable;
+	uint32_t		entity;
 };
 
-static struct stm_drvdata *drvdata;
+static struct stm_drvdata *stmdrvdata;
 
-static void __stm_enable(void)
+static int stm_hwevent_isenable(struct stm_drvdata *drvdata)
 {
-	STM_UNLOCK();
+	int ret = 0;
 
-	stm_writel(drvdata, 0x80, STMSYNCR);
-	stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
-	stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
-	stm_writel(drvdata, 0x30003, STMTCSR);
+	spin_lock(&drvdata->spinlock);
+	if (drvdata->enable)
+		if (BVAL(stm_readl(drvdata, STMHEMCR), 0))
+			ret = stm_readl(drvdata, STMHEER) == 0 ? 0 : 1;
+	spin_unlock(&drvdata->spinlock);
 
-	STM_LOCK();
-}
-
-static int stm_enable(void)
-{
-	int ret;
-
-	if (drvdata->enabled) {
-		dev_err(drvdata->dev, "STM tracing already enabled\n");
-		ret = -EINVAL;
-		goto err;
-	}
-
-	ret = clk_prepare_enable(drvdata->clk);
-	if (ret)
-		goto err_clk;
-
-	ret = qdss_enable(drvdata->src);
-	if (ret)
-		goto err_qdss;
-
-	__stm_enable();
-
-	drvdata->enabled = true;
-
-	dev_info(drvdata->dev, "STM tracing enabled\n");
-	return 0;
-
-err_qdss:
-	clk_disable_unprepare(drvdata->clk);
-err_clk:
-err:
 	return ret;
 }
 
-static void __stm_disable(void)
+static void __stm_hwevent_enable(struct stm_drvdata *drvdata)
 {
-	STM_UNLOCK();
+	STM_UNLOCK(drvdata);
 
-	stm_writel(drvdata, 0x30000, STMTCSR);
+	stm_writel(drvdata, 0x0, STMHETER);
+	stm_writel(drvdata, 0xFFFFFFFF, STMHEER);
+	stm_writel(drvdata, 0x5, STMHEMCR);
+
+	STM_LOCK(drvdata);
+}
+
+static int stm_hwevent_enable(struct stm_drvdata *drvdata)
+{
+	int ret = 0;
+
+	spin_lock(&drvdata->spinlock);
+	if (drvdata->enable)
+		__stm_hwevent_enable(drvdata);
+	else
+		ret = -EINVAL;
+	spin_unlock(&drvdata->spinlock);
+
+	return ret;
+}
+
+static int stm_port_isenable(struct stm_drvdata *drvdata)
+{
+	int ret = 0;
+
+	spin_lock(&drvdata->spinlock);
+	if (drvdata->enable)
+		ret = stm_readl(drvdata, STMSPER) == 0 ? 0 : 1;
+	spin_unlock(&drvdata->spinlock);
+
+	return ret;
+}
+
+static void __stm_port_enable(struct stm_drvdata *drvdata)
+{
+	STM_UNLOCK(drvdata);
+
+	stm_writel(drvdata, 0xFFFFFFFF, STMSPTER);
+	stm_writel(drvdata, 0xFFFFFFFF, STMSPER);
+
+	STM_LOCK(drvdata);
+}
+
+static int stm_port_enable(struct stm_drvdata *drvdata)
+{
+	int ret = 0;
+
+	spin_lock(&drvdata->spinlock);
+	if (drvdata->enable)
+		__stm_port_enable(drvdata);
+	else
+		ret = -EINVAL;
+	spin_unlock(&drvdata->spinlock);
+
+	return ret;
+}
+
+static void __stm_enable(struct stm_drvdata *drvdata)
+{
+	__stm_hwevent_enable(drvdata);
+	__stm_port_enable(drvdata);
+
+	STM_UNLOCK(drvdata);
+
+	stm_writel(drvdata, 0x80, STMSYNCR);
+	/* SYNCEN is read-only and HWTEN is not implemented */
+	stm_writel(drvdata, 0x30003, STMTCSR);
+
+	STM_LOCK(drvdata);
+}
+
+static int stm_enable(struct coresight_device *csdev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	int ret;
+
+	ret = clk_prepare_enable(drvdata->clk);
+	if (ret)
+		return ret;
+
+	spin_lock(&drvdata->spinlock);
+	__stm_enable(drvdata);
+	drvdata->enable = true;
+	spin_unlock(&drvdata->spinlock);
+
+	dev_info(drvdata->dev, "STM tracing enabled\n");
+	return 0;
+}
+
+static void __stm_hwevent_disable(struct stm_drvdata *drvdata)
+{
+	STM_UNLOCK(drvdata);
+
+	stm_writel(drvdata, 0x0, STMHETER);
+	stm_writel(drvdata, 0x0, STMHEER);
+	stm_writel(drvdata, 0x0, STMHEMCR);
+
+	STM_LOCK(drvdata);
+}
+
+static void stm_hwevent_disable(struct stm_drvdata *drvdata)
+{
+	spin_lock(&drvdata->spinlock);
+	if (drvdata->enable)
+		__stm_hwevent_disable(drvdata);
+	spin_unlock(&drvdata->spinlock);
+}
+
+static void __stm_port_disable(struct stm_drvdata *drvdata)
+{
+	STM_UNLOCK(drvdata);
+
 	stm_writel(drvdata, 0x0, STMSPER);
 	stm_writel(drvdata, 0x0, STMSPTER);
 
-	STM_LOCK();
+	STM_LOCK(drvdata);
 }
 
-static int stm_disable(void)
+static void stm_port_disable(struct stm_drvdata *drvdata)
 {
-	int ret;
+	spin_lock(&drvdata->spinlock);
+	if (drvdata->enable)
+		__stm_port_disable(drvdata);
+	spin_unlock(&drvdata->spinlock);
+}
 
-	if (!drvdata->enabled) {
-		dev_err(drvdata->dev, "STM tracing already disabled\n");
-		ret = -EINVAL;
-		goto err;
-	}
+static void __stm_disable(struct stm_drvdata *drvdata)
+{
+	STM_UNLOCK(drvdata);
 
-	__stm_disable();
+	stm_writel(drvdata, 0x30000, STMTCSR);
 
-	drvdata->enabled = false;
+	STM_LOCK(drvdata);
 
-	qdss_disable(drvdata->src);
+	__stm_hwevent_disable(drvdata);
+	__stm_port_disable(drvdata);
+}
+
+static void stm_disable(struct coresight_device *csdev)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	spin_lock(&drvdata->spinlock);
+	__stm_disable(drvdata);
+	drvdata->enable = false;
+	spin_unlock(&drvdata->spinlock);
+
+	/* Wait for 100ms so that pending data has been written to HW */
+	msleep(100);
 
 	clk_disable_unprepare(drvdata->clk);
 
 	dev_info(drvdata->dev, "STM tracing disabled\n");
-	return 0;
-
-err:
-	return ret;
 }
 
+static const struct coresight_ops_source stm_source_ops = {
+	.enable		= stm_enable,
+	.disable	= stm_disable,
+};
+
+static const struct coresight_ops stm_cs_ops = {
+	.source_ops	= &stm_source_ops,
+};
+
 static uint32_t stm_channel_alloc(uint32_t off)
 {
+	struct stm_drvdata *drvdata = stmdrvdata;
 	uint32_t ch;
 
 	do {
@@ -201,6 +330,8 @@
 
 static void stm_channel_free(uint32_t ch)
 {
+	struct stm_drvdata *drvdata = stmdrvdata;
+
 	clear_bit(ch, drvdata->chs.bitmap);
 }
 
@@ -301,13 +432,14 @@
 static inline int __stm_trace(uint32_t options, uint8_t entity_id,
 			      uint8_t proto_id, const void *data, uint32_t size)
 {
+	struct stm_drvdata *drvdata = stmdrvdata;
 	int len = 0;
 	uint32_t ch;
 	unsigned long ch_addr;
 
 	/* allocate channel and get the channel address */
 	ch = stm_channel_alloc(0);
-	ch_addr = (unsigned long)stm_channel_addr(ch);
+	ch_addr = (unsigned long)stm_channel_addr(drvdata, ch);
 
 	/* send the ost header */
 	len += stm_trace_ost_header(ch_addr, options, entity_id, proto_id, data,
@@ -344,21 +476,25 @@
 int stm_trace(uint32_t options, uint8_t entity_id, uint8_t proto_id,
 			const void *data, uint32_t size)
 {
+	struct stm_drvdata *drvdata = stmdrvdata;
+
 	/* we don't support sizes more than 24bits (0 to 23) */
-	if (!(drvdata->enabled && (drvdata->entity & entity_id) &&
+	if (!(drvdata && drvdata->enable && (drvdata->entity & entity_id) &&
 	      (size < 0x1000000)))
 		return 0;
 
 	return __stm_trace(options, entity_id, proto_id, data, size);
 }
-EXPORT_SYMBOL(stm_trace);
+EXPORT_SYMBOL_GPL(stm_trace);
 
 static ssize_t stm_write(struct file *file, const char __user *data,
 			 size_t size, loff_t *ppos)
 {
+	struct stm_drvdata *drvdata = container_of(file->private_data,
+						   struct stm_drvdata, miscdev);
 	char *buf;
 
-	if (!drvdata->enabled)
+	if (!drvdata->enable)
 		return -EINVAL;
 
 	if (!(drvdata->entity & OST_ENTITY_DEV_NODE))
@@ -386,49 +522,81 @@
 
 static const struct file_operations stm_fops = {
 	.owner		= THIS_MODULE,
+	.open		= nonseekable_open,
 	.write		= stm_write,
 	.llseek		= no_llseek,
 };
 
-static struct miscdevice stm_misc = {
-	.name		= "msm_stm",
-	.minor		= MISC_DYNAMIC_MINOR,
-	.fops		= &stm_fops,
-};
-
-static ssize_t stm_show_enabled(struct device *dev,
-				struct device_attribute *attr, char *buf)
+static ssize_t stm_show_hwevent_enable(struct device *dev,
+				       struct device_attribute *attr, char *buf)
 {
-	unsigned long val = drvdata->enabled;
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = stm_hwevent_isenable(drvdata);
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
-static ssize_t stm_store_enabled(struct device *dev,
-				 struct device_attribute *attr,
-				const char *buf, size_t size)
+static ssize_t stm_store_hwevent_enable(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t size)
 {
-	int ret = 0;
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
+	int ret = 0;
 
 	if (sscanf(buf, "%lx", &val) != 1)
 		return -EINVAL;
 
 	if (val)
-		ret = stm_enable();
+		ret = stm_hwevent_enable(drvdata);
 	else
-		ret = stm_disable();
+		stm_hwevent_disable(drvdata);
 
 	if (ret)
 		return ret;
 	return size;
 }
-static DEVICE_ATTR(enabled, S_IRUGO | S_IWUSR, stm_show_enabled,
-		   stm_store_enabled);
+static DEVICE_ATTR(hwevent_enable, S_IRUGO | S_IWUSR, stm_show_hwevent_enable,
+		   stm_store_hwevent_enable);
+
+static ssize_t stm_show_port_enable(struct device *dev,
+				    struct device_attribute *attr, char *buf)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = stm_port_isenable(drvdata);
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t stm_store_port_enable(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t size)
+{
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+	int ret = 0;
+
+	if (sscanf(buf, "%lx", &val) != 1)
+		return -EINVAL;
+
+	if (val)
+		ret = stm_port_enable(drvdata);
+	else
+		stm_port_disable(drvdata);
+
+	if (ret)
+		return ret;
+	return size;
+}
+static DEVICE_ATTR(port_enable, S_IRUGO | S_IWUSR, stm_show_port_enable,
+		   stm_store_port_enable);
 
 static ssize_t stm_show_entity(struct device *dev,
 			       struct device_attribute *attr, char *buf)
 {
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val = drvdata->entity;
+
 	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
 }
 
@@ -436,6 +604,7 @@
 				struct device_attribute *attr,
 				const char *buf, size_t size)
 {
+	struct stm_drvdata *drvdata = dev_get_drvdata(dev->parent);
 	unsigned long val;
 
 	if (sscanf(buf, "%lx", &val) != 1)
@@ -447,167 +616,131 @@
 static DEVICE_ATTR(entity, S_IRUGO | S_IWUSR, stm_show_entity,
 		   stm_store_entity);
 
-static int __devinit stm_sysfs_init(void)
-{
-	int ret;
+static struct attribute *stm_attrs[] = {
+	&dev_attr_hwevent_enable.attr,
+	&dev_attr_port_enable.attr,
+	&dev_attr_entity.attr,
+	NULL,
+};
 
-	drvdata->kobj = kobject_create_and_add("stm", qdss_get_modulekobj());
-	if (!drvdata->kobj) {
-		dev_err(drvdata->dev, "failed to create STM sysfs kobject\n");
-		ret = -ENOMEM;
-		goto err_create;
-	}
+static struct attribute_group stm_attr_grp = {
+	.attrs = stm_attrs,
+};
 
-	ret = sysfs_create_file(drvdata->kobj, &dev_attr_enabled.attr);
-	if (ret) {
-		dev_err(drvdata->dev, "failed to create STM sysfs enabled attr\n");
-		goto err_file;
-	}
-
-	if (sysfs_create_file(drvdata->kobj, &dev_attr_entity.attr))
-		dev_err(drvdata->dev, "failed to create STM sysfs entity attr\n");
-
-	return 0;
-err_file:
-	kobject_put(drvdata->kobj);
-err_create:
-	return ret;
-}
-
-static void __devexit stm_sysfs_exit(void)
-{
-	sysfs_remove_file(drvdata->kobj, &dev_attr_entity.attr);
-	sysfs_remove_file(drvdata->kobj, &dev_attr_enabled.attr);
-	kobject_put(drvdata->kobj);
-}
+static const struct attribute_group *stm_attr_grps[] = {
+	&stm_attr_grp,
+	NULL,
+};
 
 static int __devinit stm_probe(struct platform_device *pdev)
 {
 	int ret;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct stm_drvdata *drvdata;
 	struct resource *res;
 	size_t res_size, bitmap_size;
+	struct coresight_desc *desc;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto err_kzalloc_drvdata;
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
 	}
 
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	/* Store the driver data pointer for use in exported functions */
+	stmdrvdata = drvdata;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -EINVAL;
-		goto err_res0;
-	}
+	if (!res)
+		return -ENODEV;
 
-	drvdata->base = ioremap_nocache(res->start, resource_size(res));
-	if (!drvdata->base) {
-		ret = -EINVAL;
-		goto err_ioremap0;
-	}
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-	if (!res) {
-		ret = -EINVAL;
-		goto err_res1;
-	}
+	if (!res)
+		return -ENODEV;
 
-	if (stm_boot_nr_channel) {
-		res_size = min((resource_size_t)(stm_boot_nr_channel *
+	if (boot_nr_channel) {
+		res_size = min((resource_size_t)(boot_nr_channel *
 				  BYTES_PER_CHANNEL), resource_size(res));
-		bitmap_size = stm_boot_nr_channel * sizeof(long);
+		bitmap_size = boot_nr_channel * sizeof(long);
 	} else {
 		res_size = min((resource_size_t)(NR_STM_CHANNEL *
 				 BYTES_PER_CHANNEL), resource_size(res));
 		bitmap_size = NR_STM_CHANNEL * sizeof(long);
 	}
+	drvdata->chs.base = devm_ioremap(dev, res->start, res_size);
+	if (!drvdata->chs.base)
+		return -ENOMEM;
+	drvdata->chs.bitmap = devm_kzalloc(dev, bitmap_size, GFP_KERNEL);
+	if (!drvdata->chs.bitmap)
+		return -ENOMEM;
 
-	drvdata->chs.bitmap = kzalloc(bitmap_size, GFP_KERNEL);
-	if (!drvdata->chs.bitmap) {
-		ret = -ENOMEM;
-		goto err_bitmap;
-	}
+	spin_lock_init(&drvdata->spinlock);
 
-	drvdata->chs.base = ioremap_nocache(res->start, res_size);
-	if (!drvdata->chs.base) {
-		ret = -EINVAL;
-		goto err_ioremap1;
-	}
-
-	drvdata->dev = &pdev->dev;
-
-	ret = misc_register(&stm_misc);
-	if (ret)
-		goto err_misc;
-
-	drvdata->src = qdss_get("msm_stm");
-	if (IS_ERR(drvdata->src)) {
-		ret = PTR_ERR(drvdata->src);
-		goto err_qdssget;
-	}
-
-	drvdata->clk = clk_get(drvdata->dev, "core_clk");
-	if (IS_ERR(drvdata->clk)) {
-		ret = PTR_ERR(drvdata->clk);
-		goto err_clk_get;
-	}
+	drvdata->clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(drvdata->clk))
+		return PTR_ERR(drvdata->clk);
 
 	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
 	if (ret)
-		goto err_clk_rate;
+		return ret;
 
 	drvdata->entity = OST_ENTITY_ALL;
 
-	ret = stm_sysfs_init();
-	if (ret)
-		goto err_sysfs;
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_SOURCE;
+	desc->subtype.source_subtype = CORESIGHT_DEV_SUBTYPE_SOURCE_SOFTWARE;
+	desc->ops = &stm_cs_ops;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->groups = stm_attr_grps;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
 
-	if (stm_boot_enable)
-		stm_enable();
+	drvdata->miscdev.name = ((struct coresight_platform_data *)
+				 (pdev->dev.platform_data))->name;
+	drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+	drvdata->miscdev.fops = &stm_fops;
+	ret = misc_register(&drvdata->miscdev);
+	if (ret)
+		goto err;
 
 	dev_info(drvdata->dev, "STM initialized\n");
+
+	if (boot_enable)
+		coresight_enable(drvdata->csdev);
+
 	return 0;
-
-err_sysfs:
-err_clk_rate:
-	clk_put(drvdata->clk);
-err_clk_get:
-	qdss_put(drvdata->src);
-err_qdssget:
-	misc_deregister(&stm_misc);
-err_misc:
-	iounmap(drvdata->chs.base);
-err_ioremap1:
-	kfree(drvdata->chs.bitmap);
-err_bitmap:
-err_res1:
-	iounmap(drvdata->base);
-err_ioremap0:
-err_res0:
-	kfree(drvdata);
-err_kzalloc_drvdata:
-
-	dev_err(drvdata->dev, "STM init failed\n");
+err:
+	coresight_unregister(drvdata->csdev);
 	return ret;
 }
 
 static int __devexit stm_remove(struct platform_device *pdev)
 {
-	if (drvdata->enabled)
-		stm_disable();
-	stm_sysfs_exit();
-	clk_put(drvdata->clk);
-	qdss_put(drvdata->src);
-	misc_deregister(&stm_misc);
-	iounmap(drvdata->chs.base);
-	kfree(drvdata->chs.bitmap);
-	iounmap(drvdata->base);
-	kfree(drvdata);
+	struct stm_drvdata *drvdata = platform_get_drvdata(pdev);
 
+	misc_deregister(&drvdata->miscdev);
+	coresight_unregister(drvdata->csdev);
 	return 0;
 }
 
 static struct of_device_id stm_match[] = {
-	{.compatible = "qcom,msm-stm"},
+	{.compatible = "arm,coresight-stm"},
 	{}
 };
 
@@ -615,7 +748,7 @@
 	.probe          = stm_probe,
 	.remove         = __devexit_p(stm_remove),
 	.driver         = {
-		.name   = "msm_stm",
+		.name   = "coresight-stm",
 		.owner	= THIS_MODULE,
 		.of_match_table = stm_match,
 	},
diff --git a/drivers/coresight/coresight-tmc.c b/drivers/coresight/coresight-tmc.c
new file mode 100644
index 0000000..1c85aff
--- /dev/null
+++ b/drivers/coresight/coresight-tmc.c
@@ -0,0 +1,790 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/uaccess.h>
+#include <linux/slab.h>
+#include <linux/memory_alloc.h>
+#include <linux/delay.h>
+#include <linux/spinlock.h>
+#include <linux/clk.h>
+#include <linux/of_coresight.h>
+#include <linux/coresight.h>
+#include <mach/memory.h>
+
+#include "coresight-priv.h"
+
+#define tmc_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
+#define tmc_readl(drvdata, off)		__raw_readl(drvdata->base + off)
+
+#define TMC_LOCK(drvdata)						\
+do {									\
+	mb();								\
+	tmc_writel(drvdata, 0x0, CORESIGHT_LAR);			\
+} while (0)
+#define TMC_UNLOCK(drvdata)						\
+do {									\
+	tmc_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
+	mb();								\
+} while (0)
+
+#define TMC_RSZ			(0x004)
+#define TMC_STS			(0x00C)
+#define TMC_RRD			(0x010)
+#define TMC_RRP			(0x014)
+#define TMC_RWP			(0x018)
+#define TMC_TRG			(0x01C)
+#define TMC_CTL			(0x020)
+#define TMC_RWD			(0x024)
+#define TMC_MODE		(0x028)
+#define TMC_LBUFLEVEL		(0x02C)
+#define TMC_CBUFLEVEL		(0x030)
+#define TMC_BUFWM		(0x034)
+#define TMC_RRPHI		(0x038)
+#define TMC_RWPHI		(0x03C)
+#define TMC_AXICTL		(0x110)
+#define TMC_DBALO		(0x118)
+#define TMC_DBAHI		(0x11C)
+#define TMC_FFSR		(0x300)
+#define TMC_FFCR		(0x304)
+#define TMC_PSCR		(0x308)
+#define TMC_ITMISCOP0		(0xEE0)
+#define TMC_ITTRFLIN		(0xEE8)
+#define TMC_ITATBDATA0		(0xEEC)
+#define TMC_ITATBCTR2		(0xEF0)
+#define TMC_ITATBCTR1		(0xEF4)
+#define TMC_ITATBCTR0		(0xEF8)
+
+#define BYTES_PER_WORD		4
+
+enum tmc_config_type {
+	TMC_CONFIG_TYPE_ETB,
+	TMC_CONFIG_TYPE_ETR,
+	TMC_CONFIG_TYPE_ETF,
+};
+
+enum tmc_mode {
+	TMC_MODE_CIRCULAR_BUFFER,
+	TMC_MODE_SOFTWARE_FIFO,
+	TMC_MODE_HARDWARE_FIFO,
+};
+
+enum tmc_mem_intf_width {
+	TMC_MEM_INTF_WIDTH_32BITS	= 0x2,
+	TMC_MEM_INTF_WIDTH_64BITS	= 0x3,
+	TMC_MEM_INTF_WIDTH_128BITS	= 0x4,
+	TMC_MEM_INTF_WIDTH_256BITS	= 0x5,
+};
+
+struct tmc_drvdata {
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	struct miscdevice	miscdev;
+	struct clk		*clk;
+	spinlock_t		spinlock;
+	int			read_count;
+	bool			reading;
+	char			*buf;
+	unsigned long		paddr;
+	void __iomem		*vaddr;
+	uint32_t		size;
+	bool			enable;
+	enum tmc_config_type	config_type;
+	uint32_t		trigger_cntr;
+};
+
+static void tmc_wait_for_ready(struct tmc_drvdata *drvdata)
+{
+	int count;
+
+	/* Ensure formatter, unformatter and hardware fifo are empty */
+	for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_STS), 2) != 1
+				&& count > 0; count--)
+		udelay(1);
+	WARN(count == 0, "timeout while waiting for TMC ready, TMC_STS: %#x\n",
+	     tmc_readl(drvdata, TMC_STS));
+}
+
+static void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
+{
+	int count;
+	uint32_t ffcr;
+
+	ffcr = tmc_readl(drvdata, TMC_FFCR);
+	ffcr |= BIT(12);
+	tmc_writel(drvdata, ffcr, TMC_FFCR);
+	ffcr |= BIT(6);
+	tmc_writel(drvdata, ffcr, TMC_FFCR);
+	/* Ensure flush completes */
+	for (count = TIMEOUT_US; BVAL(tmc_readl(drvdata, TMC_FFCR), 6) != 0
+				&& count > 0; count--)
+		udelay(1);
+	WARN(count == 0, "timeout while flushing TMC, TMC_FFCR: %#x\n",
+	     tmc_readl(drvdata, TMC_FFCR));
+
+	tmc_wait_for_ready(drvdata);
+}
+
+static void __tmc_enable(struct tmc_drvdata *drvdata)
+{
+	tmc_writel(drvdata, 0x1, TMC_CTL);
+}
+
+static void __tmc_disable(struct tmc_drvdata *drvdata)
+{
+	tmc_writel(drvdata, 0x0, TMC_CTL);
+}
+
+static void __tmc_etb_enable(struct tmc_drvdata *drvdata)
+{
+	/* Zero out the memory to help with debug */
+	memset(drvdata->buf, 0, drvdata->size);
+
+	TMC_UNLOCK(drvdata);
+
+	tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
+	tmc_writel(drvdata, 0x133, TMC_FFCR);
+	tmc_writel(drvdata, drvdata->trigger_cntr, TMC_TRG);
+	__tmc_enable(drvdata);
+
+	TMC_LOCK(drvdata);
+}
+
+static void __tmc_etr_enable(struct tmc_drvdata *drvdata)
+{
+	uint32_t axictl;
+
+	/* Zero out the memory to help with debug */
+	memset(drvdata->vaddr, 0, drvdata->size);
+
+	TMC_UNLOCK(drvdata);
+
+	tmc_writel(drvdata, drvdata->size / BYTES_PER_WORD, TMC_RSZ);
+	tmc_writel(drvdata, TMC_MODE_CIRCULAR_BUFFER, TMC_MODE);
+
+	axictl = tmc_readl(drvdata, TMC_AXICTL);
+	axictl |= (0xF << 8);
+	tmc_writel(drvdata, axictl, TMC_AXICTL);
+	axictl &= ~(0x1 << 7);
+	tmc_writel(drvdata, axictl, TMC_AXICTL);
+	axictl = (axictl & ~0x3) | 0x2;
+	tmc_writel(drvdata, axictl, TMC_AXICTL);
+
+	tmc_writel(drvdata, drvdata->paddr, TMC_DBALO);
+	tmc_writel(drvdata, 0x0, TMC_DBAHI);
+	tmc_writel(drvdata, 0x133, TMC_FFCR);
+	__tmc_enable(drvdata);
+
+	TMC_LOCK(drvdata);
+}
+
+static void __tmc_etf_enable(struct tmc_drvdata *drvdata)
+{
+	TMC_UNLOCK(drvdata);
+
+	tmc_writel(drvdata, TMC_MODE_HARDWARE_FIFO, TMC_MODE);
+	tmc_writel(drvdata, 0x3, TMC_FFCR);
+	tmc_writel(drvdata, 0x0, TMC_BUFWM);
+	__tmc_enable(drvdata);
+
+	TMC_LOCK(drvdata);
+}
+
+static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+{
+	int ret;
+	unsigned long flags;
+
+	ret = clk_prepare_enable(drvdata->clk);
+	if (ret)
+		return ret;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading) {
+		spin_unlock_irqrestore(&drvdata->spinlock, flags);
+		clk_disable_unprepare(drvdata->clk);
+		return -EBUSY;
+	}
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+		__tmc_etb_enable(drvdata);
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		__tmc_etr_enable(drvdata);
+	} else {
+		if (mode == TMC_MODE_CIRCULAR_BUFFER)
+			__tmc_etb_enable(drvdata);
+		else
+			__tmc_etf_enable(drvdata);
+	}
+	drvdata->enable = true;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC enabled\n");
+	return 0;
+}
+
+static int tmc_enable_sink(struct coresight_device *csdev)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	return tmc_enable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
+}
+
+static int tmc_enable_link(struct coresight_device *csdev, int inport,
+			   int outport)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	return tmc_enable(drvdata, TMC_MODE_HARDWARE_FIFO);
+}
+
+static void __tmc_etb_dump(struct tmc_drvdata *drvdata)
+{
+	enum tmc_mem_intf_width memwidth;
+	uint8_t memwords;
+	char *bufp;
+	uint32_t read_data;
+	int i;
+
+	memwidth = BMVAL(tmc_readl(drvdata, CORESIGHT_DEVID), 8, 10);
+	if (memwidth == TMC_MEM_INTF_WIDTH_32BITS)
+		memwords = 1;
+	else if (memwidth == TMC_MEM_INTF_WIDTH_64BITS)
+		memwords = 2;
+	else if (memwidth == TMC_MEM_INTF_WIDTH_128BITS)
+		memwords = 4;
+	else
+		memwords = 8;
+
+	bufp = drvdata->buf;
+	while (1) {
+		for (i = 0; i < memwords; i++) {
+			read_data = tmc_readl(drvdata, TMC_RRD);
+			if (read_data == 0xFFFFFFFF)
+				return;
+			memcpy(bufp, &read_data, BYTES_PER_WORD);
+			bufp += BYTES_PER_WORD;
+		}
+	}
+}
+
+static void __tmc_etb_disable(struct tmc_drvdata *drvdata)
+{
+	TMC_UNLOCK(drvdata);
+
+	tmc_flush_and_stop(drvdata);
+	__tmc_etb_dump(drvdata);
+	__tmc_disable(drvdata);
+
+	TMC_LOCK(drvdata);
+}
+
+static void __tmc_etr_dump(struct tmc_drvdata *drvdata)
+{
+	uint32_t rwp, rwphi;
+
+	rwp = tmc_readl(drvdata, TMC_RWP);
+	rwphi = tmc_readl(drvdata, TMC_RWPHI);
+
+	if (BVAL(tmc_readl(drvdata, TMC_STS), 0))
+		drvdata->buf = drvdata->vaddr + rwp;
+	else
+		drvdata->buf = drvdata->vaddr;
+}
+
+static void __tmc_etr_disable(struct tmc_drvdata *drvdata)
+{
+	TMC_UNLOCK(drvdata);
+
+	tmc_flush_and_stop(drvdata);
+	__tmc_etr_dump(drvdata);
+	__tmc_disable(drvdata);
+
+	TMC_LOCK(drvdata);
+}
+
+static void __tmc_etf_disable(struct tmc_drvdata *drvdata)
+{
+	TMC_UNLOCK(drvdata);
+
+	tmc_flush_and_stop(drvdata);
+	__tmc_disable(drvdata);
+
+	TMC_LOCK(drvdata);
+}
+
+static void tmc_disable(struct tmc_drvdata *drvdata, enum tmc_mode mode)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading)
+		goto out;
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+		__tmc_etb_disable(drvdata);
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		__tmc_etr_disable(drvdata);
+	} else {
+		if (mode == TMC_MODE_CIRCULAR_BUFFER)
+			__tmc_etb_disable(drvdata);
+		else
+			__tmc_etf_disable(drvdata);
+	}
+out:
+	drvdata->enable = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	clk_disable_unprepare(drvdata->clk);
+
+	dev_info(drvdata->dev, "TMC disabled\n");
+}
+
+static void tmc_disable_sink(struct coresight_device *csdev)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	tmc_disable(drvdata, TMC_MODE_CIRCULAR_BUFFER);
+}
+
+static void tmc_disable_link(struct coresight_device *csdev, int inport,
+			     int outport)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	tmc_disable(drvdata, TMC_MODE_HARDWARE_FIFO);
+}
+
+static void tmc_abort(struct coresight_device *csdev)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	unsigned long flags;
+	enum tmc_mode mode;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (drvdata->reading)
+		goto out0;
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+		__tmc_etb_disable(drvdata);
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		__tmc_etr_disable(drvdata);
+	} else {
+		mode = tmc_readl(drvdata, TMC_MODE);
+		if (mode == TMC_MODE_CIRCULAR_BUFFER)
+			__tmc_etb_disable(drvdata);
+		else
+			goto out1;
+	}
+out0:
+	drvdata->enable = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC aborted\n");
+	return;
+out1:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+}
+
+static const struct coresight_ops_sink tmc_sink_ops = {
+	.enable		= tmc_enable_sink,
+	.disable	= tmc_disable_sink,
+	.abort		= tmc_abort,
+};
+
+static const struct coresight_ops_link tmc_link_ops = {
+	.enable		= tmc_enable_link,
+	.disable	= tmc_disable_link,
+};
+
+static const struct coresight_ops tmc_etb_cs_ops = {
+	.sink_ops	= &tmc_sink_ops,
+};
+
+static const struct coresight_ops tmc_etr_cs_ops = {
+	.sink_ops	= &tmc_sink_ops,
+};
+
+static const struct coresight_ops tmc_etf_cs_ops = {
+	.sink_ops	= &tmc_sink_ops,
+	.link_ops	= &tmc_link_ops,
+};
+
+static int tmc_read_prepare(struct tmc_drvdata *drvdata)
+{
+	int ret;
+	unsigned long flags;
+	enum tmc_mode mode;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (!drvdata->enable)
+		goto out;
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+		__tmc_etb_disable(drvdata);
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		__tmc_etr_disable(drvdata);
+	} else {
+		mode = tmc_readl(drvdata, TMC_MODE);
+		if (mode == TMC_MODE_CIRCULAR_BUFFER) {
+			__tmc_etb_disable(drvdata);
+		} else {
+			ret = -ENODEV;
+			goto err;
+		}
+	}
+out:
+	drvdata->reading = true;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC read start\n");
+	return 0;
+err:
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+	return ret;
+}
+
+static void tmc_read_unprepare(struct tmc_drvdata *drvdata)
+{
+	unsigned long flags;
+	enum tmc_mode mode;
+
+	spin_lock_irqsave(&drvdata->spinlock, flags);
+	if (!drvdata->enable)
+		goto out;
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+		__tmc_etb_enable(drvdata);
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		__tmc_etr_enable(drvdata);
+	} else {
+		mode = tmc_readl(drvdata, TMC_MODE);
+		if (mode == TMC_MODE_CIRCULAR_BUFFER)
+			__tmc_etb_enable(drvdata);
+	}
+out:
+	drvdata->reading = false;
+	spin_unlock_irqrestore(&drvdata->spinlock, flags);
+
+	dev_info(drvdata->dev, "TMC read end\n");
+}
+
+static int tmc_open(struct inode *inode, struct file *file)
+{
+	struct tmc_drvdata *drvdata = container_of(file->private_data,
+						   struct tmc_drvdata, miscdev);
+	int ret = 0;
+
+	if (drvdata->read_count++)
+		goto out;
+
+	ret = tmc_read_prepare(drvdata);
+	if (ret)
+		return ret;
+out:
+	nonseekable_open(inode, file);
+
+	dev_dbg(drvdata->dev, "%s: successfully opened\n", __func__);
+	return 0;
+}
+
+static ssize_t tmc_read(struct file *file, char __user *data, size_t len,
+			loff_t *ppos)
+{
+	struct tmc_drvdata *drvdata = container_of(file->private_data,
+						   struct tmc_drvdata, miscdev);
+	char *bufp = drvdata->buf + *ppos;
+
+	if (*ppos + len > drvdata->size)
+		len = drvdata->size - *ppos;
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		if (bufp == (char *)(drvdata->vaddr + drvdata->size))
+			bufp = drvdata->vaddr;
+		if ((bufp + len) > (char *)(drvdata->vaddr + drvdata->size))
+			len = (char *)(drvdata->vaddr + drvdata->size) - bufp;
+	}
+
+	if (copy_to_user(data, bufp, len)) {
+		dev_dbg(drvdata->dev, "%s: copy_to_user failed\n", __func__);
+		return -EFAULT;
+	}
+
+	*ppos += len;
+
+	dev_dbg(drvdata->dev, "%s: %d bytes copied, %d bytes left\n",
+		__func__, len, (int) (drvdata->size - *ppos));
+	return len;
+}
+
+static int tmc_release(struct inode *inode, struct file *file)
+{
+	struct tmc_drvdata *drvdata = container_of(file->private_data,
+						   struct tmc_drvdata, miscdev);
+
+	if (--drvdata->read_count) {
+		if (drvdata->read_count < 0) {
+			WARN_ONCE(1, "mismatched close\n");
+			drvdata->read_count = 0;
+		}
+		goto out;
+	}
+
+	tmc_read_unprepare(drvdata);
+out:
+	dev_dbg(drvdata->dev, "%s: released\n", __func__);
+	return 0;
+}
+
+static const struct file_operations tmc_fops = {
+	.owner		= THIS_MODULE,
+	.open		= tmc_open,
+	.read		= tmc_read,
+	.release	= tmc_release,
+	.llseek		= no_llseek,
+};
+
+static ssize_t tmc_show_trigger_cntr(struct device *dev,
+				     struct device_attribute *attr, char *buf)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val = drvdata->trigger_cntr;
+
+	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
+}
+
+static ssize_t tmc_store_trigger_cntr(struct device *dev,
+				      struct device_attribute *attr,
+				      const char *buf, size_t size)
+{
+	struct tmc_drvdata *drvdata = dev_get_drvdata(dev->parent);
+	unsigned long val;
+
+	if (sscanf(buf, "%lx", &val) != 1)
+		return -EINVAL;
+
+	drvdata->trigger_cntr = val;
+	return size;
+}
+static DEVICE_ATTR(trigger_cntr, S_IRUGO | S_IWUSR, tmc_show_trigger_cntr,
+		   tmc_store_trigger_cntr);
+
+static struct attribute *tmc_attrs[] = {
+	&dev_attr_trigger_cntr.attr,
+	NULL,
+};
+
+static struct attribute_group tmc_attr_grp = {
+	.attrs = tmc_attrs,
+};
+
+static const struct attribute_group *tmc_etb_attr_grps[] = {
+	&tmc_attr_grp,
+	NULL,
+};
+
+static const struct attribute_group *tmc_etr_attr_grps[] = {
+	&tmc_attr_grp,
+	NULL,
+};
+
+static const struct attribute_group *tmc_etf_attr_grps[] = {
+	&tmc_attr_grp,
+	NULL,
+};
+
+static int __devinit tmc_probe(struct platform_device *pdev)
+{
+	int ret;
+	uint32_t devid;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct tmc_drvdata *drvdata;
+	struct resource *res;
+	struct coresight_desc *desc;
+
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
+	}
+
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res)
+		return -ENODEV;
+
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
+
+	spin_lock_init(&drvdata->spinlock);
+
+	drvdata->clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(drvdata->clk))
+		return PTR_ERR(drvdata->clk);
+
+	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
+	if (ret)
+		return ret;
+
+	ret = clk_prepare_enable(drvdata->clk);
+	if (ret)
+		return ret;
+
+	devid = tmc_readl(drvdata, CORESIGHT_DEVID);
+	drvdata->config_type = BMVAL(devid, 6, 7);
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR)
+		drvdata->size = SZ_1M;
+	else
+		drvdata->size = tmc_readl(drvdata, TMC_RSZ) * BYTES_PER_WORD;
+
+	clk_disable_unprepare(drvdata->clk);
+
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		drvdata->paddr = allocate_contiguous_ebi_nomap(drvdata->size,
+							       SZ_4K);
+		if (!drvdata->paddr)
+			return -ENOMEM;
+		drvdata->vaddr = devm_ioremap(dev, drvdata->paddr,
+					      drvdata->size);
+		if (!drvdata->vaddr) {
+			ret = -ENOMEM;
+			goto err0;
+		}
+		memset(drvdata->vaddr, 0, drvdata->size);
+	} else {
+		drvdata->buf = devm_kzalloc(dev, drvdata->size, GFP_KERNEL);
+		if (!drvdata->buf)
+			return -ENOMEM;
+	}
+
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc) {
+		ret = -ENOMEM;
+		goto err0;
+	}
+	if (drvdata->config_type == TMC_CONFIG_TYPE_ETB) {
+		desc->type = CORESIGHT_DEV_TYPE_SINK;
+		desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+		desc->ops = &tmc_etb_cs_ops;
+		desc->pdata = pdev->dev.platform_data;
+		desc->dev = &pdev->dev;
+		desc->groups = tmc_etb_attr_grps;
+		desc->owner = THIS_MODULE;
+		drvdata->csdev = coresight_register(desc);
+		if (IS_ERR(drvdata->csdev)) {
+			ret = PTR_ERR(drvdata->csdev);
+			goto err0;
+		}
+	} else if (drvdata->config_type == TMC_CONFIG_TYPE_ETR) {
+		desc->type = CORESIGHT_DEV_TYPE_SINK;
+		desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+		desc->ops = &tmc_etr_cs_ops;
+		desc->pdata = pdev->dev.platform_data;
+		desc->dev = &pdev->dev;
+		desc->groups = tmc_etr_attr_grps;
+		desc->owner = THIS_MODULE;
+		drvdata->csdev = coresight_register(desc);
+		if (IS_ERR(drvdata->csdev)) {
+			ret = PTR_ERR(drvdata->csdev);
+			goto err0;
+		}
+	} else {
+		desc->type = CORESIGHT_DEV_TYPE_LINKSINK;
+		desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_BUFFER;
+		desc->subtype.link_subtype = CORESIGHT_DEV_SUBTYPE_LINK_FIFO;
+		desc->ops = &tmc_etf_cs_ops;
+		desc->pdata = pdev->dev.platform_data;
+		desc->dev = &pdev->dev;
+		desc->groups = tmc_etf_attr_grps;
+		desc->owner = THIS_MODULE;
+		drvdata->csdev = coresight_register(desc);
+		if (IS_ERR(drvdata->csdev)) {
+			ret = PTR_ERR(drvdata->csdev);
+			goto err0;
+		}
+	}
+
+	drvdata->miscdev.name = ((struct coresight_platform_data *)
+				 (pdev->dev.platform_data))->name;
+	drvdata->miscdev.minor = MISC_DYNAMIC_MINOR;
+	drvdata->miscdev.fops = &tmc_fops;
+	ret = misc_register(&drvdata->miscdev);
+	if (ret)
+		goto err1;
+
+	dev_info(dev, "TMC initialized\n");
+	return 0;
+err1:
+	coresight_unregister(drvdata->csdev);
+err0:
+	free_contiguous_memory_by_paddr(drvdata->paddr);
+	return ret;
+}
+
+static int __devexit tmc_remove(struct platform_device *pdev)
+{
+	struct tmc_drvdata *drvdata = platform_get_drvdata(pdev);
+
+	misc_deregister(&drvdata->miscdev);
+	coresight_unregister(drvdata->csdev);
+	free_contiguous_memory_by_paddr(drvdata->paddr);
+	return 0;
+}
+
+static struct of_device_id tmc_match[] = {
+	{.compatible = "arm,coresight-tmc"},
+	{}
+};
+
+static struct platform_driver tmc_driver = {
+	.probe          = tmc_probe,
+	.remove         = __devexit_p(tmc_remove),
+	.driver         = {
+		.name   = "coresight-tmc",
+		.owner	= THIS_MODULE,
+		.of_match_table = tmc_match,
+	},
+};
+
+static int __init tmc_init(void)
+{
+	return platform_driver_register(&tmc_driver);
+}
+module_init(tmc_init);
+
+static void __exit tmc_exit(void)
+{
+	platform_driver_unregister(&tmc_driver);
+}
+module_exit(tmc_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("CoreSight Trace Memory Controller driver");
diff --git a/drivers/coresight/coresight-tpiu.c b/drivers/coresight/coresight-tpiu.c
index c0bcfdd..290ae7f 100644
--- a/drivers/coresight/coresight-tpiu.c
+++ b/drivers/coresight/coresight-tpiu.c
@@ -19,6 +19,7 @@
 #include <linux/err.h>
 #include <linux/slab.h>
 #include <linux/clk.h>
+#include <linux/of_coresight.h>
 #include <linux/coresight.h>
 
 #include "coresight-priv.h"
@@ -26,135 +27,182 @@
 #define tpiu_writel(drvdata, val, off)	__raw_writel((val), drvdata->base + off)
 #define tpiu_readl(drvdata, off)	__raw_readl(drvdata->base + off)
 
-#define TPIU_SUPP_PORTSZ				(0x000)
-#define TPIU_CURR_PORTSZ				(0x004)
-#define TPIU_SUPP_TRIGMODES				(0x100)
-#define TPIU_TRIG_CNTRVAL				(0x104)
-#define TPIU_TRIG_MULT					(0x108)
-#define TPIU_SUPP_TESTPATM				(0x200)
-#define TPIU_CURR_TESTPATM				(0x204)
-#define TPIU_TEST_PATREPCNTR				(0x208)
-#define TPIU_FFSR					(0x300)
-#define TPIU_FFCR					(0x304)
-#define TPIU_FSYNC_CNTR					(0x308)
-#define TPIU_EXTCTL_INPORT				(0x400)
-#define TPIU_EXTCTL_OUTPORT				(0x404)
-#define TPIU_ITTRFLINACK				(0xEE4)
-#define TPIU_ITTRFLIN					(0xEE8)
-#define TPIU_ITATBDATA0					(0xEEC)
-#define TPIU_ITATBCTR2					(0xEF0)
-#define TPIU_ITATBCTR1					(0xEF4)
-#define TPIU_ITATBCTR0					(0xEF8)
-
-
-#define TPIU_LOCK()							\
+#define TPIU_LOCK(drvdata)						\
 do {									\
 	mb();								\
 	tpiu_writel(drvdata, 0x0, CORESIGHT_LAR);			\
 } while (0)
-#define TPIU_UNLOCK()							\
+#define TPIU_UNLOCK(drvdata)						\
 do {									\
 	tpiu_writel(drvdata, CORESIGHT_UNLOCK, CORESIGHT_LAR);		\
 	mb();								\
 } while (0)
 
+#define TPIU_SUPP_PORTSZ	(0x000)
+#define TPIU_CURR_PORTSZ	(0x004)
+#define TPIU_SUPP_TRIGMODES	(0x100)
+#define TPIU_TRIG_CNTRVAL	(0x104)
+#define TPIU_TRIG_MULT		(0x108)
+#define TPIU_SUPP_TESTPATM	(0x200)
+#define TPIU_CURR_TESTPATM	(0x204)
+#define TPIU_TEST_PATREPCNTR	(0x208)
+#define TPIU_FFSR		(0x300)
+#define TPIU_FFCR		(0x304)
+#define TPIU_FSYNC_CNTR		(0x308)
+#define TPIU_EXTCTL_INPORT	(0x400)
+#define TPIU_EXTCTL_OUTPORT	(0x404)
+#define TPIU_ITTRFLINACK	(0xEE4)
+#define TPIU_ITTRFLIN		(0xEE8)
+#define TPIU_ITATBDATA0		(0xEEC)
+#define TPIU_ITATBCTR2		(0xEF0)
+#define TPIU_ITATBCTR1		(0xEF4)
+#define TPIU_ITATBCTR0		(0xEF8)
+
 struct tpiu_drvdata {
-	void __iomem	*base;
-	bool		enabled;
-	struct device	*dev;
-	struct clk	*clk;
+	void __iomem		*base;
+	struct device		*dev;
+	struct coresight_device	*csdev;
+	struct clk		*clk;
 };
 
-static struct tpiu_drvdata *drvdata;
-
-static void __tpiu_disable(void)
+static void __tpiu_enable(struct tpiu_drvdata *drvdata)
 {
-	TPIU_UNLOCK();
+	TPIU_UNLOCK(drvdata);
+
+	/* TODO: fill this up */
+
+	TPIU_LOCK(drvdata);
+}
+
+static int tpiu_enable(struct coresight_device *csdev)
+{
+	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+	int ret;
+
+	ret = clk_prepare_enable(drvdata->clk);
+	if (ret)
+		return ret;
+
+	__tpiu_enable(drvdata);
+
+	dev_info(drvdata->dev, "TPIU enabled\n");
+	return 0;
+}
+
+static void __tpiu_disable(struct tpiu_drvdata *drvdata)
+{
+	TPIU_UNLOCK(drvdata);
 
 	tpiu_writel(drvdata, 0x3000, TPIU_FFCR);
 	tpiu_writel(drvdata, 0x3040, TPIU_FFCR);
 
-	TPIU_LOCK();
+	TPIU_LOCK(drvdata);
 }
 
-void tpiu_disable(void)
+static void tpiu_disable(struct coresight_device *csdev)
 {
-	__tpiu_disable();
-	drvdata->enabled = false;
+	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	__tpiu_disable(drvdata);
+
+	clk_disable_unprepare(drvdata->clk);
+
 	dev_info(drvdata->dev, "TPIU disabled\n");
 }
 
+static void tpiu_abort(struct coresight_device *csdev)
+{
+	struct tpiu_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
+
+	__tpiu_disable(drvdata);
+
+	dev_info(drvdata->dev, "TPIU aborted\n");
+}
+
+static const struct coresight_ops_sink tpiu_sink_ops = {
+	.enable		= tpiu_enable,
+	.disable	= tpiu_disable,
+	.abort		= tpiu_abort,
+};
+
+static const struct coresight_ops tpiu_cs_ops = {
+	.sink_ops	= &tpiu_sink_ops,
+};
+
 static int __devinit tpiu_probe(struct platform_device *pdev)
 {
 	int ret;
+	struct device *dev = &pdev->dev;
+	struct coresight_platform_data *pdata;
+	struct tpiu_drvdata *drvdata;
 	struct resource *res;
+	struct coresight_desc *desc;
 
-	drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL);
-	if (!drvdata) {
-		ret = -ENOMEM;
-		goto err_kzalloc_drvdata;
+	if (pdev->dev.of_node) {
+		pdata = of_get_coresight_platform_data(dev, pdev->dev.of_node);
+		if (IS_ERR(pdata))
+			return PTR_ERR(pdata);
+		pdev->dev.platform_data = pdata;
 	}
 
+	drvdata = devm_kzalloc(dev, sizeof(*drvdata), GFP_KERNEL);
+	if (!drvdata)
+		return -ENOMEM;
+	drvdata->dev = &pdev->dev;
+	platform_set_drvdata(pdev, drvdata);
+
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-	if (!res) {
-		ret = -EINVAL;
-		goto err_res;
-	}
+	if (!res)
+		return -ENODEV;
 
-	drvdata->base = ioremap_nocache(res->start, resource_size(res));
-	if (!drvdata->base) {
-		ret = -EINVAL;
-		goto err_ioremap;
-	}
+	drvdata->base = devm_ioremap(dev, res->start, resource_size(res));
+	if (!drvdata->base)
+		return -ENOMEM;
 
-	drvdata->dev = &pdev->dev;
-
-	drvdata->clk = clk_get(drvdata->dev, "core_clk");
-	if (IS_ERR(drvdata->clk)) {
-		ret = PTR_ERR(drvdata->clk);
-		goto err_clk_get;
-	}
+	drvdata->clk = devm_clk_get(dev, "core_clk");
+	if (IS_ERR(drvdata->clk))
+		return PTR_ERR(drvdata->clk);
 
 	ret = clk_set_rate(drvdata->clk, CORESIGHT_CLK_RATE_TRACE);
 	if (ret)
-		goto err_clk_rate;
+		return ret;
 
-	/* Disable tpiu to support older targets that need this */
 	ret = clk_prepare_enable(drvdata->clk);
 	if (ret)
-		goto err_clk_enable;
-	__tpiu_disable();
+		return ret;
+
+	/* Disable tpiu to support older targets that need this */
+	__tpiu_disable(drvdata);
+
 	clk_disable_unprepare(drvdata->clk);
 
-	dev_info(drvdata->dev, "TPIU initialized\n");
-	return 0;
+	desc = devm_kzalloc(dev, sizeof(*desc), GFP_KERNEL);
+	if (!desc)
+		return -ENOMEM;
+	desc->type = CORESIGHT_DEV_TYPE_SINK;
+	desc->subtype.sink_subtype = CORESIGHT_DEV_SUBTYPE_SINK_PORT;
+	desc->ops = &tpiu_cs_ops;
+	desc->pdata = pdev->dev.platform_data;
+	desc->dev = &pdev->dev;
+	desc->owner = THIS_MODULE;
+	drvdata->csdev = coresight_register(desc);
+	if (IS_ERR(drvdata->csdev))
+		return PTR_ERR(drvdata->csdev);
 
-err_clk_enable:
-err_clk_rate:
-	clk_put(drvdata->clk);
-err_clk_get:
-	iounmap(drvdata->base);
-err_ioremap:
-err_res:
-	kfree(drvdata);
-err_kzalloc_drvdata:
-	dev_err(drvdata->dev, "TPIU init failed\n");
-	return ret;
+	dev_info(dev, "TPIU initialized\n");
+	return 0;
 }
 
 static int __devexit tpiu_remove(struct platform_device *pdev)
 {
-	if (drvdata->enabled)
-		tpiu_disable();
-	clk_put(drvdata->clk);
-	iounmap(drvdata->base);
-	kfree(drvdata);
+	struct tpiu_drvdata *drvdata = platform_get_drvdata(pdev);
 
+	coresight_unregister(drvdata->csdev);
 	return 0;
 }
 
 static struct of_device_id tpiu_match[] = {
-	{.compatible = "qcom,msm-tpiu"},
+	{.compatible = "arm,coresight-tpiu"},
 	{}
 };
 
@@ -162,7 +210,7 @@
 	.probe          = tpiu_probe,
 	.remove         = __devexit_p(tpiu_remove),
 	.driver         = {
-		.name   = "msm_tpiu",
+		.name   = "coresight-tpiu",
 		.owner	= THIS_MODULE,
 		.of_match_table = tpiu_match,
 	},
diff --git a/drivers/coresight/coresight.c b/drivers/coresight/coresight.c
index a17ac9a..f76d303 100644
--- a/drivers/coresight/coresight.c
+++ b/drivers/coresight/coresight.c
@@ -26,17 +26,13 @@
 
 #include "coresight-priv.h"
 
-
 #define NO_SINK		(-1)
-#define MAX_STR_LEN	(65535)
-
 
 static int curr_sink = NO_SINK;
 static LIST_HEAD(coresight_orph_conns);
 static LIST_HEAD(coresight_devs);
 static DEFINE_SEMAPHORE(coresight_mutex);
 
-
 static int coresight_find_link_inport(struct coresight_device *csdev)
 {
 	int i;
@@ -343,7 +339,7 @@
 	up(&coresight_mutex);
 	return ret;
 }
-EXPORT_SYMBOL(coresight_enable);
+EXPORT_SYMBOL_GPL(coresight_enable);
 
 void coresight_disable(struct coresight_device *csdev)
 {
@@ -366,7 +362,29 @@
 out:
 	up(&coresight_mutex);
 }
-EXPORT_SYMBOL(coresight_disable);
+EXPORT_SYMBOL_GPL(coresight_disable);
+
+void coresight_abort(void)
+{
+	struct coresight_device *cd;
+
+	if (down_trylock(&coresight_mutex)) {
+		pr_err("coresight: abort could not be processed\n");
+		return;
+	}
+	if (curr_sink == NO_SINK)
+		goto out;
+
+	list_for_each_entry(cd, &coresight_devs, dev_link) {
+		if (cd->id == curr_sink) {
+			if (cd->enable && cd->ops->sink_ops->abort)
+				cd->ops->sink_ops->abort(cd);
+		}
+	}
+out:
+	up(&coresight_mutex);
+}
+EXPORT_SYMBOL_GPL(coresight_abort);
 
 static ssize_t coresight_show_type(struct device *dev,
 				   struct device_attribute *attr, char *buf)
@@ -626,7 +644,7 @@
 err_kzalloc_csdev:
 	return ERR_PTR(ret);
 }
-EXPORT_SYMBOL(coresight_register);
+EXPORT_SYMBOL_GPL(coresight_register);
 
 void coresight_unregister(struct coresight_device *csdev)
 {
@@ -638,7 +656,7 @@
 		put_device(&csdev->dev);
 	}
 }
-EXPORT_SYMBOL(coresight_unregister);
+EXPORT_SYMBOL_GPL(coresight_unregister);
 
 static int __init coresight_init(void)
 {
@@ -653,300 +671,3 @@
 module_exit(coresight_exit);
 
 MODULE_LICENSE("GPL v2");
-/*
- * Exclusion rules for structure fields.
- *
- * S: qdss.sources_mutex protected.
- * I: qdss.sink_mutex protected.
- * C: qdss.clk_mutex protected.
- */
-struct qdss_ctx {
-	struct kobject			*modulekobj;
-	uint8_t				afamily;
-	struct list_head		sources;	/* S: sources list */
-	struct mutex			sources_mutex;
-	uint8_t				sink_count;	/* I: sink count */
-	struct mutex			sink_mutex;
-	uint8_t				max_clk;
-	struct clk			*clk;
-};
-
-static struct qdss_ctx qdss;
-
-/**
- * qdss_get - get the qdss source handle
- * @name: name of the qdss source
- *
- * Searches the sources list to get the qdss source handle for this source.
- *
- * CONTEXT:
- * Typically called from init or probe functions
- *
- * RETURNS:
- * pointer to struct qdss_source on success, %NULL on failure
- */
-struct qdss_source *qdss_get(const char *name)
-{
-	struct qdss_source *src, *source = NULL;
-
-	mutex_lock(&qdss.sources_mutex);
-	list_for_each_entry(src, &qdss.sources, link) {
-		if (src->name) {
-			if (strncmp(src->name, name, MAX_STR_LEN))
-				continue;
-			source = src;
-			break;
-		}
-	}
-	mutex_unlock(&qdss.sources_mutex);
-
-	return source ? source : ERR_PTR(-ENOENT);
-}
-EXPORT_SYMBOL(qdss_get);
-
-/**
- * qdss_put - release the qdss source handle
- * @name: name of the qdss source
- *
- * CONTEXT:
- * Typically called from driver remove or exit functions
- */
-void qdss_put(struct qdss_source *src)
-{
-}
-EXPORT_SYMBOL(qdss_put);
-
-/**
- * qdss_enable - enable qdss for the source
- * @src: handle for the source making the call
- *
- * Enables qdss block (relevant funnel ports and sink) if not already
- * enabled, otherwise increments the reference count
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- *
- * RETURNS:
- * 0 on success, non-zero on failure
- */
-int qdss_enable(struct qdss_source *src)
-{
-	if (!src)
-		return -EINVAL;
-
-	if (qdss.afamily) {
-		mutex_lock(&qdss.sink_mutex);
-		if (qdss.sink_count == 0) {
-			tpiu_disable();
-			/* enable ETB first to avoid losing any trace data */
-			etb_enable();
-		}
-		qdss.sink_count++;
-		mutex_unlock(&qdss.sink_mutex);
-	}
-
-	funnel_enable(0x0, src->fport_mask);
-	return 0;
-}
-EXPORT_SYMBOL(qdss_enable);
-
-/**
- * qdss_disable - disable qdss for the source
- * @src: handle for the source making the call
- *
- * Disables qdss block (relevant funnel ports and sink) if the reference count
- * is one, otherwise decrements the reference count
- *
- * CONTEXT:
- * Might sleep. Uses a mutex lock. Should be called from a non-atomic context.
- */
-void qdss_disable(struct qdss_source *src)
-{
-	if (!src)
-		return;
-
-	if (qdss.afamily) {
-		mutex_lock(&qdss.sink_mutex);
-		if (WARN(qdss.sink_count == 0, "qdss is unbalanced\n"))
-			goto out;
-		if (qdss.sink_count == 1) {
-			etb_dump();
-			etb_disable();
-		}
-		qdss.sink_count--;
-		mutex_unlock(&qdss.sink_mutex);
-	}
-
-	funnel_disable(0x0, src->fport_mask);
-	return;
-out:
-	mutex_unlock(&qdss.sink_mutex);
-}
-EXPORT_SYMBOL(qdss_disable);
-
-/**
- * qdss_disable_sink - force disable the current qdss sink(s)
- *
- * Force disable the current qdss sink(s) to stop the sink from accepting any
- * trace generated subsequent to this call. This function should only be used
- * as a way to stop the sink from getting polluted with trace data that is
- * uninteresting after an event of interest has occured.
- *
- * CONTEXT:
- * Can be called from atomic or non-atomic context.
- */
-void qdss_disable_sink(void)
-{
-	if (qdss.afamily) {
-		etb_dump();
-		etb_disable();
-	}
-}
-EXPORT_SYMBOL(qdss_disable_sink);
-
-struct kobject *qdss_get_modulekobj(void)
-{
-	return qdss.modulekobj;
-}
-
-#define QDSS_ATTR(name)						\
-static struct kobj_attribute name##_attr =				\
-		__ATTR(name, S_IRUGO | S_IWUSR, name##_show, name##_store)
-
-static ssize_t max_clk_store(struct kobject *kobj,
-			struct kobj_attribute *attr,
-			const char *buf, size_t n)
-{
-	unsigned long val;
-
-	if (sscanf(buf, "%lx", &val) != 1)
-		return -EINVAL;
-
-	qdss.max_clk = val;
-	return n;
-}
-static ssize_t max_clk_show(struct kobject *kobj,
-			struct kobj_attribute *attr,
-			char *buf)
-{
-	unsigned long val = qdss.max_clk;
-	return scnprintf(buf, PAGE_SIZE, "%#lx\n", val);
-}
-QDSS_ATTR(max_clk);
-
-static void __devinit qdss_add_sources(struct qdss_source *srcs, size_t num)
-{
-	mutex_lock(&qdss.sources_mutex);
-	while (num--) {
-		list_add_tail(&srcs->link, &qdss.sources);
-		srcs++;
-	}
-	mutex_unlock(&qdss.sources_mutex);
-}
-
-static int __init qdss_sysfs_init(void)
-{
-	int ret;
-
-	qdss.modulekobj = kset_find_obj(module_kset, KBUILD_MODNAME);
-	if (!qdss.modulekobj) {
-		pr_err("failed to find QDSS sysfs module kobject\n");
-		ret = -ENOENT;
-		goto err;
-	}
-
-	ret = sysfs_create_file(qdss.modulekobj, &max_clk_attr.attr);
-	if (ret) {
-		pr_err("failed to create QDSS sysfs max_clk attribute\n");
-		goto err;
-	}
-
-	return 0;
-err:
-	return ret;
-}
-
-static void __devexit qdss_sysfs_exit(void)
-{
-	sysfs_remove_file(qdss.modulekobj, &max_clk_attr.attr);
-}
-
-static int __devinit qdss_probe(struct platform_device *pdev)
-{
-	int ret = 0;
-	struct msm_qdss_platform_data *pdata;
-
-	mutex_init(&qdss.sources_mutex);
-	mutex_init(&qdss.sink_mutex);
-
-	INIT_LIST_HEAD(&qdss.sources);
-
-	pdata = pdev->dev.platform_data;
-	if (!pdata)
-		goto err_pdata;
-
-	qdss.afamily = pdata->afamily;
-	qdss_add_sources(pdata->src_table, pdata->size);
-
-	pr_info("QDSS arch initialized\n");
-	return 0;
-err_pdata:
-	mutex_destroy(&qdss.sink_mutex);
-	mutex_destroy(&qdss.sources_mutex);
-	pr_err("QDSS init failed\n");
-	return ret;
-}
-
-static int __devexit qdss_remove(struct platform_device *pdev)
-{
-	qdss_sysfs_exit();
-	mutex_destroy(&qdss.sink_mutex);
-	mutex_destroy(&qdss.sources_mutex);
-
-	return 0;
-}
-
-static struct of_device_id qdss_match[] = {
-	{.compatible = "qcom,msm-qdss"},
-	{}
-};
-
-static struct platform_driver qdss_driver = {
-	.probe          = qdss_probe,
-	.remove         = __devexit_p(qdss_remove),
-	.driver         = {
-		.name   = "msm_qdss",
-		.owner	= THIS_MODULE,
-		.of_match_table = qdss_match,
-	},
-};
-
-static int __init qdss_init(void)
-{
-	return platform_driver_register(&qdss_driver);
-}
-arch_initcall(qdss_init);
-
-static int __init qdss_module_init(void)
-{
-	int ret;
-
-	ret = qdss_sysfs_init();
-	if (ret)
-		goto err_sysfs;
-
-	pr_info("QDSS module initialized\n");
-	return 0;
-err_sysfs:
-	return ret;
-}
-module_init(qdss_module_init);
-
-static void __exit qdss_exit(void)
-{
-	platform_driver_unregister(&qdss_driver);
-}
-module_exit(qdss_exit);
-
-MODULE_LICENSE("GPL v2");
-MODULE_DESCRIPTION("Qualcomm Debug SubSystem Driver");
diff --git a/drivers/coresight/of_coresight.c b/drivers/coresight/of_coresight.c
new file mode 100644
index 0000000..5c2c525
--- /dev/null
+++ b/drivers/coresight/of_coresight.c
@@ -0,0 +1,99 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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/types.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/coresight.h>
+
+struct coresight_platform_data *of_get_coresight_platform_data(
+				struct device *dev, struct device_node *node)
+{
+	int i, ret = 0;
+	uint32_t outports_len = 0;
+	struct device_node *child_node;
+	struct coresight_platform_data *pdata;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata)
+		return ERR_PTR(-ENOMEM);
+
+	ret = of_property_read_u32(node, "coresight-id", &pdata->id);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = of_property_read_string(node, "coresight-name", &pdata->name);
+	if (ret)
+		return ERR_PTR(ret);
+
+	ret = of_property_read_u32(node, "coresight-nr-inports",
+				   &pdata->nr_inports);
+	if (ret)
+		return ERR_PTR(ret);
+
+	pdata->nr_outports = 0;
+	if (of_get_property(node, "coresight-outports", &outports_len))
+		pdata->nr_outports = outports_len/sizeof(uint32_t);
+
+	if (pdata->nr_outports) {
+		pdata->outports = devm_kzalloc(dev, pdata->nr_outports *
+					       sizeof(*pdata->outports),
+					       GFP_KERNEL);
+		if (!pdata->outports)
+			return ERR_PTR(-ENOMEM);
+
+		ret = of_property_read_u32_array(node, "coresight-outports",
+						 (u32 *)pdata->outports,
+						 pdata->nr_outports);
+		if (ret)
+			return ERR_PTR(ret);
+
+		pdata->child_ids = devm_kzalloc(dev, pdata->nr_outports *
+						sizeof(*pdata->child_ids),
+						GFP_KERNEL);
+		if (!pdata->child_ids)
+			return ERR_PTR(-ENOMEM);
+
+		for (i = 0; i < pdata->nr_outports; i++) {
+			child_node = of_parse_phandle(node,
+						      "coresight-child-list",
+						      i);
+			if (!child_node)
+				return ERR_PTR(-EINVAL);
+
+			ret = of_property_read_u32(child_node, "coresight-id",
+						   (u32 *)&pdata->child_ids[i]);
+			of_node_put(child_node);
+			if (ret)
+				return ERR_PTR(ret);
+		}
+
+		pdata->child_ports = devm_kzalloc(dev, pdata->nr_outports *
+						  sizeof(*pdata->child_ports),
+						  GFP_KERNEL);
+		if (!pdata->child_ports)
+			return ERR_PTR(-ENOMEM);
+
+		ret = of_property_read_u32_array(node, "coresight-child-ports",
+						 (u32 *)pdata->child_ports,
+						 pdata->nr_outports);
+		if (ret)
+			return ERR_PTR(ret);
+	}
+
+	pdata->default_sink = of_property_read_bool(node,
+						    "coresight-default-sink");
+	return pdata;
+}
+EXPORT_SYMBOL_GPL(of_get_coresight_platform_data);
diff --git a/drivers/gpio/gpio-msm-common.c b/drivers/gpio/gpio-msm-common.c
index bdb8171..46f6460 100644
--- a/drivers/gpio/gpio-msm-common.c
+++ b/drivers/gpio/gpio-msm-common.c
@@ -23,6 +23,7 @@
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/err.h>
+#include <linux/platform_device.h>
 
 #include <asm/mach/irq.h>
 
@@ -402,59 +403,6 @@
 	.irq_disable	= msm_gpio_irq_disable,
 };
 
-/*
- * This lock class tells lockdep that GPIO irqs are in a different
- * category than their parent, so it won't report false recursion.
- */
-static struct lock_class_key msm_gpio_lock_class;
-
-/* TODO: This should be a real platform_driver */
-static int __devinit msm_gpio_probe(void)
-{
-	int ret;
-#ifndef CONFIG_OF
-	int irq, i;
-#endif
-
-	spin_lock_init(&tlmm_lock);
-	bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
-	bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
-	bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
-	ret = gpiochip_add(&msm_gpio.gpio_chip);
-	if (ret < 0)
-		return ret;
-
-#ifndef CONFIG_OF
-	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
-		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
-		irq_set_lockdep_class(irq, &msm_gpio_lock_class);
-		irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
-					 handle_level_irq);
-		set_irq_flags(irq, IRQF_VALID);
-	}
-#endif
-	ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
-			IRQF_TRIGGER_HIGH, "msmgpio", NULL);
-	if (ret) {
-		pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
-				ret);
-		return ret;
-	}
-	return 0;
-}
-
-static int __devexit msm_gpio_remove(void)
-{
-	int ret = gpiochip_remove(&msm_gpio.gpio_chip);
-
-	if (ret < 0)
-		return ret;
-
-	irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
-
-	return 0;
-}
-
 #ifdef CONFIG_PM
 static int msm_gpio_suspend(void)
 {
@@ -518,22 +466,6 @@
 	.resume = msm_gpio_resume,
 };
 
-static int __init msm_gpio_init(void)
-{
-	msm_gpio_probe();
-	register_syscore_ops(&msm_gpio_syscore_ops);
-	return 0;
-}
-
-static void __exit msm_gpio_exit(void)
-{
-	unregister_syscore_ops(&msm_gpio_syscore_ops);
-	msm_gpio_remove();
-}
-
-postcore_initcall(msm_gpio_init);
-module_exit(msm_gpio_exit);
-
 static void msm_tlmm_set_field(const struct tlmm_field_cfg *configs,
 			       unsigned id, unsigned width, unsigned val)
 {
@@ -594,6 +526,89 @@
 }
 EXPORT_SYMBOL(msm_gpio_install_direct_irq);
 
+/*
+ * This lock class tells lockdep that GPIO irqs are in a different
+ * category than their parent, so it won't report false recursion.
+ */
+static struct lock_class_key msm_gpio_lock_class;
+
+static int __devinit msm_gpio_probe(struct platform_device *pdev)
+{
+	int ret;
+#ifndef CONFIG_OF
+	int irq, i;
+#endif
+	msm_gpio.gpio_chip.dev = &pdev->dev;
+	spin_lock_init(&tlmm_lock);
+	bitmap_zero(msm_gpio.enabled_irqs, NR_MSM_GPIOS);
+	bitmap_zero(msm_gpio.wake_irqs, NR_MSM_GPIOS);
+	bitmap_zero(msm_gpio.dual_edge_irqs, NR_MSM_GPIOS);
+	ret = gpiochip_add(&msm_gpio.gpio_chip);
+	if (ret < 0)
+		return ret;
+
+#ifndef CONFIG_OF
+	for (i = 0; i < msm_gpio.gpio_chip.ngpio; ++i) {
+		irq = msm_gpio_to_irq(&msm_gpio.gpio_chip, i);
+		irq_set_lockdep_class(irq, &msm_gpio_lock_class);
+		irq_set_chip_and_handler(irq, &msm_gpio_irq_chip,
+					 handle_level_irq);
+		set_irq_flags(irq, IRQF_VALID);
+	}
+#endif
+	ret = request_irq(TLMM_MSM_SUMMARY_IRQ, msm_summary_irq_handler,
+			IRQF_TRIGGER_HIGH, "msmgpio", NULL);
+	if (ret) {
+		pr_err("Request_irq failed for TLMM_MSM_SUMMARY_IRQ - %d\n",
+				ret);
+		return ret;
+	}
+	register_syscore_ops(&msm_gpio_syscore_ops);
+	return 0;
+}
+
+#ifdef CONFIG_OF
+static struct of_device_id msm_gpio_of_match[] __devinitdata = {
+	{.compatible = "qcom,msm-gpio", },
+	{ },
+};
+#endif
+
+static int __devexit msm_gpio_remove(struct platform_device *pdev)
+{
+	int ret;
+
+	unregister_syscore_ops(&msm_gpio_syscore_ops);
+	ret = gpiochip_remove(&msm_gpio.gpio_chip);
+	if (ret < 0)
+		return ret;
+	irq_set_handler(TLMM_MSM_SUMMARY_IRQ, NULL);
+
+	return 0;
+}
+
+static struct platform_driver msm_gpio_driver = {
+	.probe = msm_gpio_probe,
+	.remove = __devexit_p(msm_gpio_remove),
+	.driver = {
+		.name = "msmgpio",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(msm_gpio_of_match),
+	},
+};
+
+static void __exit msm_gpio_exit(void)
+{
+	platform_driver_unregister(&msm_gpio_driver);
+}
+module_exit(msm_gpio_exit);
+
+static int __init msm_gpio_init(void)
+{
+	return platform_driver_register(&msm_gpio_driver);
+}
+postcore_initcall(msm_gpio_init);
+
 #ifdef CONFIG_OF
 static int msm_gpio_irq_domain_xlate(struct irq_domain *d,
 				     struct device_node *controller,
diff --git a/drivers/gpio/qpnp-pin.c b/drivers/gpio/qpnp-pin.c
index bbcba81..ccbbd67 100644
--- a/drivers/gpio/qpnp-pin.c
+++ b/drivers/gpio/qpnp-pin.c
@@ -46,10 +46,10 @@
 
 /* mpp peripheral type and subtype values */
 #define Q_MPP_TYPE			0x11
-#define Q_MPP_SUBTYPE_4CH_NO_ANA_OUT	0x1
-#define Q_MPP_SUBTYPE_4CH_NO_SINK	0x2
-#define Q_MPP_SUBTYPE_4CH_FULL_FUNC	0x3
-#define Q_MPP_SUBTYPE_8CH_FULL_FUNC	0x7
+#define Q_MPP_SUBTYPE_4CH_NO_ANA_OUT	0x3
+#define Q_MPP_SUBTYPE_4CH_NO_SINK	0x5
+#define Q_MPP_SUBTYPE_4CH_FULL_FUNC	0x2
+#define Q_MPP_SUBTYPE_8CH_FULL_FUNC	0x4
 
 /* control register base address offsets */
 #define Q_REG_MODE_CTL			0x40
diff --git a/drivers/gpu/msm/Makefile b/drivers/gpu/msm/Makefile
index 6cdb5f1..c7ed329 100644
--- a/drivers/gpu/msm/Makefile
+++ b/drivers/gpu/msm/Makefile
@@ -35,6 +35,7 @@
 
 msm_z180-y += \
 	z180.o \
+	z180_postmortem.o \
 	z180_trace.o
 
 msm_kgsl_core-objs = $(msm_kgsl_core-y)
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index f7d1e59..6a894c8 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -32,8 +32,6 @@
 
 #include "adreno.h"
 #include "adreno_pm4types.h"
-#include "adreno_debugfs.h"
-#include "adreno_postmortem.h"
 
 #include "a2xx_reg.h"
 #include "a3xx_reg.h"
@@ -1639,7 +1637,7 @@
 		 * Trigger an automatic dump of the state to
 		 * the console
 		 */
-		adreno_postmortem_dump(device, 0);
+		kgsl_postmortem_dump(device, 0);
 
 		/*
 		 * Make a GPU snapshot.  For now, do it after the PM dump so we
@@ -2452,6 +2450,7 @@
 	.drawctxt_create = adreno_drawctxt_create,
 	.drawctxt_destroy = adreno_drawctxt_destroy,
 	.setproperty = adreno_setproperty,
+	.postmortem_dump = adreno_dump,
 };
 
 static struct platform_driver adreno_platform_driver = {
diff --git a/drivers/gpu/msm/adreno.h b/drivers/gpu/msm/adreno.h
index 279e7ed..b923049e 100644
--- a/drivers/gpu/msm/adreno.h
+++ b/drivers/gpu/msm/adreno.h
@@ -49,6 +49,8 @@
 #define ADRENO_DEFAULT_PWRSCALE_POLICY  NULL
 #endif
 
+void adreno_debugfs_init(struct kgsl_device *device);
+
 #define ADRENO_ISTORE_START 0x5000 /* Istore offset */
 
 #define ADRENO_NUM_CTX_SWITCH_ALLOWED_BEFORE_DRAW	50
@@ -166,6 +168,8 @@
 void adreno_regwrite(struct kgsl_device *device, unsigned int offsetwords,
 				unsigned int value);
 
+int adreno_dump(struct kgsl_device *device, int manual);
+
 struct kgsl_memdesc *adreno_find_region(struct kgsl_device *device,
 						unsigned int pt_base,
 						unsigned int gpuaddr,
diff --git a/drivers/gpu/msm/adreno_debugfs.c b/drivers/gpu/msm/adreno_debugfs.c
index e3c9a18..bb3da40 100644
--- a/drivers/gpu/msm/adreno_debugfs.c
+++ b/drivers/gpu/msm/adreno_debugfs.c
@@ -18,67 +18,11 @@
 #include <linux/io.h>
 
 #include "kgsl.h"
-#include "adreno_postmortem.h"
 #include "adreno.h"
 
 #include "a2xx_reg.h"
 
 unsigned int kgsl_cff_dump_enable;
-int adreno_pm_regs_enabled;
-int adreno_pm_ib_enabled;
-
-static struct dentry *pm_d_debugfs;
-
-static int pm_dump_set(void *data, u64 val)
-{
-	struct kgsl_device *device = data;
-
-	if (val) {
-		mutex_lock(&device->mutex);
-		adreno_postmortem_dump(device, 1);
-		mutex_unlock(&device->mutex);
-	}
-
-	return 0;
-}
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_dump_fops,
-			NULL,
-			pm_dump_set, "%llu\n");
-
-static int pm_regs_enabled_set(void *data, u64 val)
-{
-	adreno_pm_regs_enabled = val ? 1 : 0;
-	return 0;
-}
-
-static int pm_regs_enabled_get(void *data, u64 *val)
-{
-	*val = adreno_pm_regs_enabled;
-	return 0;
-}
-
-static int pm_ib_enabled_set(void *data, u64 val)
-{
-	adreno_pm_ib_enabled = val ? 1 : 0;
-	return 0;
-}
-
-static int pm_ib_enabled_get(void *data, u64 *val)
-{
-	*val = adreno_pm_ib_enabled;
-	return 0;
-}
-
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
-			pm_regs_enabled_get,
-			pm_regs_enabled_set, "%llu\n");
-
-DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
-			pm_ib_enabled_get,
-			pm_ib_enabled_set, "%llu\n");
-
 
 static int kgsl_cff_dump_enable_set(void *data, u64 val)
 {
@@ -116,23 +60,9 @@
 		&adreno_dev->wait_timeout);
 	debugfs_create_u32("ib_check", 0644, device->d_debugfs,
 			   &adreno_dev->ib_check_level);
-
 	/* By Default enable fast hang detection */
 	adreno_dev->fast_hang_detect = 1;
 	debugfs_create_u32("fast_hang_detect", 0644, device->d_debugfs,
 			   &adreno_dev->fast_hang_detect);
 
-	/* Create post mortem control files */
-
-	pm_d_debugfs = debugfs_create_dir("postmortem", device->d_debugfs);
-
-	if (IS_ERR(pm_d_debugfs))
-		return;
-
-	debugfs_create_file("dump",  0600, pm_d_debugfs, device,
-			    &pm_dump_fops);
-	debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
-			    &pm_regs_enabled_fops);
-	debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
-				    &pm_ib_enabled_fops);
 }
diff --git a/drivers/gpu/msm/adreno_debugfs.h b/drivers/gpu/msm/adreno_debugfs.h
deleted file mode 100644
index 5f8d89a..0000000
--- a/drivers/gpu/msm/adreno_debugfs.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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 __ADRENO_DEBUGFS_H
-#define __ADRENO_DEBUGFS_H
-
-#ifdef CONFIG_DEBUG_FS
-
-int adreno_debugfs_init(struct kgsl_device *device);
-
-extern int adreno_pm_regs_enabled;
-extern int adreno_pm_ib_enabled;
-
-static inline int is_adreno_pm_regs_enabled(void)
-{
-	return adreno_pm_regs_enabled;
-}
-
-static inline int is_adreno_pm_ib_enabled(void)
-{
-	return adreno_pm_ib_enabled;
-}
-
-#else
-static inline int adreno_debugfs_init(struct kgsl_device *device)
-{
-	return 0;
-}
-
-static inline int kgsl_pmregs_enabled(void)
-{
-	/* If debugfs is turned off, then always print registers */
-	return 1;
-}
-#endif
-
-#endif /* __ADRENO_DEBUGFS_H */
diff --git a/drivers/gpu/msm/adreno_postmortem.c b/drivers/gpu/msm/adreno_postmortem.c
index 3cc4bcf..2038c10 100644
--- a/drivers/gpu/msm/adreno_postmortem.c
+++ b/drivers/gpu/msm/adreno_postmortem.c
@@ -19,8 +19,6 @@
 #include "adreno.h"
 #include "adreno_pm4types.h"
 #include "adreno_ringbuffer.h"
-#include "adreno_postmortem.h"
-#include "adreno_debugfs.h"
 #include "kgsl_cffdump.h"
 #include "kgsl_pwrctrl.h"
 
@@ -678,7 +676,7 @@
 		"MH_INTERRUPT: MASK = %08X | STATUS   = %08X\n", r1, r2);
 }
 
-static int adreno_dump(struct kgsl_device *device)
+int adreno_dump(struct kgsl_device *device, int manual)
 {
 	unsigned int cp_ib1_base, cp_ib1_bufsz;
 	unsigned int cp_ib2_base, cp_ib2_bufsz;
@@ -834,7 +832,7 @@
 		cp_rb_base, cp_rb_rptr, cp_rb_wptr, read_idx);
 	adreno_dump_rb(device, rb_copy, num_item<<2, read_idx, rb_count);
 
-	if (is_adreno_pm_ib_enabled()) {
+	if (device->pm_ib_enabled) {
 		for (read_idx = NUM_DWORDS_OF_RINGBUFFER_HISTORY;
 			read_idx >= 0; --read_idx) {
 			uint32_t this_cmd = rb_copy[read_idx];
@@ -865,7 +863,7 @@
 	}
 
 	/* Dump the registers if the user asked for it */
-	if (is_adreno_pm_regs_enabled()) {
+	if (device->pm_regs_enabled) {
 		if (adreno_is_a20x(adreno_dev))
 			adreno_dump_regs(device, a200_registers,
 					a200_registers_count);
@@ -885,85 +883,3 @@
 end:
 	return result;
 }
-
-/**
- * adreno_postmortem_dump - Dump the current GPU state
- * @device - A pointer to the KGSL device to dump
- * @manual - A flag that indicates if this was a manually triggered
- *           dump (from debugfs).  If zero, then this is assumed to be a
- *           dump automaticlaly triggered from a hang
-*/
-
-int adreno_postmortem_dump(struct kgsl_device *device, int manual)
-{
-	bool saved_nap;
-	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
-
-	BUG_ON(device == NULL);
-
-	kgsl_cffdump_hang(device->id);
-
-	/* For a manual dump, make sure that the system is idle */
-
-	if (manual) {
-		if (device->active_cnt != 0) {
-			mutex_unlock(&device->mutex);
-			wait_for_completion(&device->suspend_gate);
-			mutex_lock(&device->mutex);
-		}
-
-		if (device->state == KGSL_STATE_ACTIVE)
-			kgsl_idle(device,  KGSL_TIMEOUT_DEFAULT);
-
-	}
-	KGSL_LOG_DUMP(device, "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X",
-			pwr->power_flags, pwr->active_pwrlevel);
-
-	KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
-		pwr->interval_timeout);
-
-	KGSL_LOG_DUMP(device, "GRP_CLK = %lu ",
-				  kgsl_get_clkrate(pwr->grp_clks[0]));
-
-	KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
-		kgsl_get_clkrate(pwr->ebi1_clk));
-
-	/* Disable the idle timer so we don't get interrupted */
-	del_timer_sync(&device->idle_timer);
-	mutex_unlock(&device->mutex);
-	flush_workqueue(device->work_queue);
-	mutex_lock(&device->mutex);
-
-	/* Turn off napping to make sure we have the clocks full
-	   attention through the following process */
-	saved_nap = device->pwrctrl.nap_allowed;
-	device->pwrctrl.nap_allowed = false;
-
-	/* Force on the clocks */
-	kgsl_pwrctrl_wake(device);
-
-	/* Disable the irq */
-	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
-
-	adreno_dump(device);
-
-	/* Restore nap mode */
-	device->pwrctrl.nap_allowed = saved_nap;
-
-	/* On a manual trigger, turn on the interrupts and put
-	   the clocks to sleep.  They will recover themselves
-	   on the next event.  For a hang, leave things as they
-	   are until recovery kicks in. */
-
-	if (manual) {
-		kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
-
-		/* try to go into a sleep mode until the next event */
-		kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
-		kgsl_pwrctrl_sleep(device);
-	}
-
-	KGSL_DRV_ERR(device, "Dump Finished\n");
-
-	return 0;
-}
diff --git a/drivers/gpu/msm/adreno_postmortem.h b/drivers/gpu/msm/adreno_postmortem.h
deleted file mode 100644
index b677800..0000000
--- a/drivers/gpu/msm/adreno_postmortem.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT 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 __ADRENO_POSTMORTEM_H
-#define __ADRENO_POSTMORTEM_H
-
-struct kgsl_device;
-
-int adreno_postmortem_dump(struct kgsl_device *device, int manual);
-
-#endif /* __ADRENO_POSTMORTEM_H */
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 49786ba..ca9e335 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -22,7 +22,6 @@
 #include "adreno.h"
 #include "adreno_pm4types.h"
 #include "adreno_ringbuffer.h"
-#include "adreno_debugfs.h"
 
 #include "a2xx_reg.h"
 #include "a3xx_reg.h"
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index 62e1521..3d83508 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -649,6 +649,7 @@
 					struct kgsl_device, display_off);
 	KGSL_PWR_WARN(device, "early suspend start\n");
 	mutex_lock(&device->mutex);
+	device->pwrctrl.restore_slumber = true;
 	kgsl_pwrctrl_request_state(device, KGSL_STATE_SLUMBER);
 	kgsl_pwrctrl_sleep(device);
 	mutex_unlock(&device->mutex);
@@ -677,7 +678,7 @@
 					struct kgsl_device, display_off);
 	KGSL_PWR_WARN(device, "late resume start\n");
 	mutex_lock(&device->mutex);
-	device->pwrctrl.restore_slumber = 0;
+	device->pwrctrl.restore_slumber = false;
 	if (device->pwrscale.policy == NULL)
 		kgsl_pwrctrl_pwrlevel_change(device, KGSL_PWRLEVEL_TURBO);
 	kgsl_pwrctrl_wake(device);
@@ -2176,7 +2177,7 @@
 static long kgsl_ioctl(struct file *filep, unsigned int cmd, unsigned long arg)
 {
 	struct kgsl_device_private *dev_priv = filep->private_data;
-	unsigned int nr = _IOC_NR(cmd);
+	unsigned int nr;
 	kgsl_ioctl_func_t func;
 	int lock, ret;
 	char ustack[64];
@@ -2192,6 +2193,8 @@
 	else if (cmd == IOCTL_KGSL_CMDSTREAM_READTIMESTAMP_OLD)
 		cmd = IOCTL_KGSL_CMDSTREAM_READTIMESTAMP;
 
+	nr = _IOC_NR(cmd);
+
 	if (cmd & (IOC_IN | IOC_OUT)) {
 		if (_IOC_SIZE(cmd) < sizeof(ustack))
 			uptr = ustack;
@@ -2216,7 +2219,20 @@
 	}
 
 	if (nr < ARRAY_SIZE(kgsl_ioctl_funcs) &&
-	    kgsl_ioctl_funcs[nr].func != NULL) {
+		kgsl_ioctl_funcs[nr].func != NULL) {
+
+		/*
+		 * Make sure that nobody tried to send us a malformed ioctl code
+		 * with a valid NR but bogus flags
+		 */
+
+		if (kgsl_ioctl_funcs[nr].cmd != cmd) {
+			KGSL_DRV_ERR(dev_priv->device,
+				"Malformed ioctl code %08x\n", cmd);
+			ret = -ENOIOCTLCMD;
+			goto done;
+		}
+
 		func = kgsl_ioctl_funcs[nr].func;
 		lock = kgsl_ioctl_funcs[nr].lock;
 	} else {
@@ -2570,6 +2586,83 @@
 }
 EXPORT_SYMBOL(kgsl_device_platform_probe);
 
+int kgsl_postmortem_dump(struct kgsl_device *device, int manual)
+{
+	bool saved_nap;
+	struct kgsl_pwrctrl *pwr = &device->pwrctrl;
+
+	BUG_ON(device == NULL);
+
+	kgsl_cffdump_hang(device->id);
+
+	/* For a manual dump, make sure that the system is idle */
+
+	if (manual) {
+		if (device->active_cnt != 0) {
+			mutex_unlock(&device->mutex);
+			wait_for_completion(&device->suspend_gate);
+			mutex_lock(&device->mutex);
+		}
+
+		if (device->state == KGSL_STATE_ACTIVE)
+			kgsl_idle(device,  KGSL_TIMEOUT_DEFAULT);
+
+	}
+	KGSL_LOG_DUMP(device, "|%s| Dump Started\n", device->name);
+	KGSL_LOG_DUMP(device, "POWER: FLAGS = %08lX | ACTIVE POWERLEVEL = %08X",
+			pwr->power_flags, pwr->active_pwrlevel);
+
+	KGSL_LOG_DUMP(device, "POWER: INTERVAL TIMEOUT = %08X ",
+		pwr->interval_timeout);
+
+	KGSL_LOG_DUMP(device, "GRP_CLK = %lu ",
+				  kgsl_get_clkrate(pwr->grp_clks[0]));
+
+	KGSL_LOG_DUMP(device, "BUS CLK = %lu ",
+		kgsl_get_clkrate(pwr->ebi1_clk));
+
+	/* Disable the idle timer so we don't get interrupted */
+	del_timer_sync(&device->idle_timer);
+	mutex_unlock(&device->mutex);
+	flush_workqueue(device->work_queue);
+	mutex_lock(&device->mutex);
+
+	/* Turn off napping to make sure we have the clocks full
+	   attention through the following process */
+	saved_nap = device->pwrctrl.nap_allowed;
+	device->pwrctrl.nap_allowed = false;
+
+	/* Force on the clocks */
+	kgsl_pwrctrl_wake(device);
+
+	/* Disable the irq */
+	kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_OFF);
+
+	/*Call the device specific postmortem dump function*/
+	device->ftbl->postmortem_dump(device, manual);
+
+	/* Restore nap mode */
+	device->pwrctrl.nap_allowed = saved_nap;
+
+	/* On a manual trigger, turn on the interrupts and put
+	   the clocks to sleep.  They will recover themselves
+	   on the next event.  For a hang, leave things as they
+	   are until recovery kicks in. */
+
+	if (manual) {
+		kgsl_pwrctrl_irq(device, KGSL_PWRFLAGS_ON);
+
+		/* try to go into a sleep mode until the next event */
+		kgsl_pwrctrl_request_state(device, KGSL_STATE_SLEEP);
+		kgsl_pwrctrl_sleep(device);
+	}
+
+	KGSL_LOG_DUMP(device, "|%s| Dump Finished\n", device->name);
+
+	return 0;
+}
+EXPORT_SYMBOL(kgsl_postmortem_dump);
+
 void kgsl_device_platform_remove(struct kgsl_device *device)
 {
 	kgsl_device_snapshot_close(device);
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 8a3345b..ac04c56 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -173,6 +173,7 @@
 #endif
 
 void kgsl_mem_entry_destroy(struct kref *kref);
+int kgsl_postmortem_dump(struct kgsl_device *device, int manual);
 
 struct kgsl_mem_entry *kgsl_get_mem_entry(unsigned int ptbase,
 		unsigned int gpuaddr, unsigned int size);
diff --git a/drivers/gpu/msm/kgsl_debugfs.c b/drivers/gpu/msm/kgsl_debugfs.c
index 328dd95..545d2b3 100644
--- a/drivers/gpu/msm/kgsl_debugfs.c
+++ b/drivers/gpu/msm/kgsl_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This 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,60 @@
 #define KGSL_LOG_LEVEL_MAX     7
 
 struct dentry *kgsl_debugfs_dir;
+static struct dentry *pm_d_debugfs;
+
+static int pm_dump_set(void *data, u64 val)
+{
+	struct kgsl_device *device = data;
+
+	if (val) {
+		mutex_lock(&device->mutex);
+		kgsl_postmortem_dump(device, 1);
+		mutex_unlock(&device->mutex);
+	}
+
+	return 0;
+}
+DEFINE_SIMPLE_ATTRIBUTE(pm_dump_fops,
+			NULL,
+			pm_dump_set, "%llu\n");
+
+static int pm_regs_enabled_set(void *data, u64 val)
+{
+	struct kgsl_device *device = data;
+	device->pm_regs_enabled = val ? 1 : 0;
+	return 0;
+}
+
+static int pm_regs_enabled_get(void *data, u64 *val)
+{
+	struct kgsl_device *device = data;
+	*val = device->pm_regs_enabled;
+	return 0;
+}
+
+static int pm_ib_enabled_set(void *data, u64 val)
+{
+	struct kgsl_device *device = data;
+	device->pm_ib_enabled = val ? 1 : 0;
+	return 0;
+}
+
+static int pm_ib_enabled_get(void *data, u64 *val)
+{
+	struct kgsl_device *device = data;
+	*val = device->pm_ib_enabled;
+	return 0;
+}
+
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_regs_enabled_fops,
+			pm_regs_enabled_get,
+			pm_regs_enabled_set, "%llu\n");
+
+DEFINE_SIMPLE_ATTRIBUTE(pm_ib_enabled_fops,
+			pm_ib_enabled_get,
+			pm_ib_enabled_set, "%llu\n");
 
 static inline int kgsl_log_set(unsigned int *log_val, void *data, u64 val)
 {
@@ -75,6 +129,21 @@
 				&mem_log_fops);
 	debugfs_create_file("log_level_pwr", 0644, device->d_debugfs, device,
 				&pwr_log_fops);
+
+	/* Create postmortem dump control files */
+
+	pm_d_debugfs = debugfs_create_dir("postmortem", device->d_debugfs);
+
+	if (IS_ERR(pm_d_debugfs))
+		return;
+
+	debugfs_create_file("dump",  0600, pm_d_debugfs, device,
+			    &pm_dump_fops);
+	debugfs_create_file("regs_enabled", 0644, pm_d_debugfs, device,
+			    &pm_regs_enabled_fops);
+	debugfs_create_file("ib_enabled", 0644, pm_d_debugfs, device,
+				    &pm_ib_enabled_fops);
+
 }
 
 void kgsl_core_debugfs_init(void)
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 0336a20..d0932ef 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -110,6 +110,7 @@
 	int (*setproperty) (struct kgsl_device *device,
 		enum kgsl_property_type type, void *value,
 		unsigned int sizebytes);
+	int (*postmortem_dump) (struct kgsl_device *device, int manual);
 };
 
 /* MH register values */
@@ -196,6 +197,10 @@
 	struct work_struct ts_expired_ws;
 	struct list_head events;
 	s64 on_time;
+
+	/* Postmortem Control switches */
+	int pm_regs_enabled;
+	int pm_ib_enabled;
 };
 
 void kgsl_timestamp_expired(struct work_struct *work);
diff --git a/drivers/gpu/msm/kgsl_mmu.c b/drivers/gpu/msm/kgsl_mmu.c
index c02274d..8e6c5c0 100644
--- a/drivers/gpu/msm/kgsl_mmu.c
+++ b/drivers/gpu/msm/kgsl_mmu.c
@@ -24,7 +24,6 @@
 #include "kgsl_mmu.h"
 #include "kgsl_device.h"
 #include "kgsl_sharedmem.h"
-#include "adreno_postmortem.h"
 
 #define KGSL_MMU_ALIGN_SHIFT    13
 #define KGSL_MMU_ALIGN_MASK     (~((1 << KGSL_MMU_ALIGN_SHIFT) - 1))
diff --git a/drivers/gpu/msm/kgsl_pwrctrl.c b/drivers/gpu/msm/kgsl_pwrctrl.c
index 6d4d4d3..4b5021d 100644
--- a/drivers/gpu/msm/kgsl_pwrctrl.c
+++ b/drivers/gpu/msm/kgsl_pwrctrl.c
@@ -800,14 +800,12 @@
 	case KGSL_STATE_ACTIVE:
 		if (!device->ftbl->isidle(device)) {
 			kgsl_pwrctrl_request_state(device, KGSL_STATE_NONE);
-			device->pwrctrl.restore_slumber = true;
 			return -EBUSY;
 		}
 		/* fall through */
 	case KGSL_STATE_NAP:
 	case KGSL_STATE_SLEEP:
 		del_timer_sync(&device->idle_timer);
-		device->pwrctrl.restore_slumber = true;
 		device->ftbl->suspend_context(device);
 		device->ftbl->stop(device);
 		_sleep_accounting(device);
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 3504dfc..9037f3c 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -25,9 +25,6 @@
 #define DRIVER_VERSION_MAJOR   3
 #define DRIVER_VERSION_MINOR   1
 
-#define Z180_DEVICE(device) \
-		KGSL_CONTAINER_OF(device, struct z180_device, dev)
-
 #define GSL_VGC_INT_MASK \
 	 (REG_VGC_IRQSTATUS__MH_MASK | \
 	  REG_VGC_IRQSTATUS__G2D_MASK | \
@@ -41,16 +38,12 @@
 #define VGV3_CONTROL_MARKADD_FSHIFT 0
 #define VGV3_CONTROL_MARKADD_FMASK 0xfff
 
-#define Z180_PACKET_SIZE 15
 #define Z180_MARKER_SIZE 10
 #define Z180_CALL_CMD     0x1000
 #define Z180_MARKER_CMD   0x8000
 #define Z180_STREAM_END_CMD 0x9000
 #define Z180_STREAM_PACKET 0x7C000176
 #define Z180_STREAM_PACKET_CALL 0x7C000275
-#define Z180_PACKET_COUNT 8
-#define Z180_RB_SIZE (Z180_PACKET_SIZE*Z180_PACKET_COUNT \
-			  *sizeof(uint32_t))
 
 #define NUMTEXUNITS             4
 #define TEXUNITREGCOUNT         25
@@ -846,6 +839,7 @@
 	else if (timeout == 0) {
 		status = -ETIMEDOUT;
 		kgsl_pwrctrl_set_state(device, KGSL_STATE_HUNG);
+		kgsl_postmortem_dump(device, 0);
 	} else
 		status = timeout;
 
@@ -936,6 +930,7 @@
 	.drawctxt_create = NULL,
 	.drawctxt_destroy = z180_drawctxt_destroy,
 	.ioctl = NULL,
+	.postmortem_dump = z180_dump,
 };
 
 static struct platform_device_id z180_id_table[] = {
diff --git a/drivers/gpu/msm/z180.h b/drivers/gpu/msm/z180.h
index e5c5ef3..6e81a9d 100644
--- a/drivers/gpu/msm/z180.h
+++ b/drivers/gpu/msm/z180.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2008-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2008-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -19,6 +19,13 @@
 #define DEVICE_2D0_NAME "kgsl-2d0"
 #define DEVICE_2D1_NAME "kgsl-2d1"
 
+#define Z180_PACKET_SIZE 15
+#define Z180_PACKET_COUNT 8
+#define Z180_RB_SIZE (Z180_PACKET_SIZE*Z180_PACKET_COUNT \
+			  *sizeof(uint32_t))
+#define Z180_DEVICE(device) \
+		KGSL_CONTAINER_OF(device, struct z180_device, dev)
+
 #define Z180_DEFAULT_PWRSCALE_POLICY  NULL
 
 struct z180_ringbuffer {
@@ -34,4 +41,6 @@
 	spinlock_t cmdwin_lock;
 };
 
+int z180_dump(struct kgsl_device *, int);
+
 #endif /* __Z180_H */
diff --git a/drivers/gpu/msm/z180_postmortem.c b/drivers/gpu/msm/z180_postmortem.c
new file mode 100644
index 0000000..a9b0c50
--- /dev/null
+++ b/drivers/gpu/msm/z180_postmortem.c
@@ -0,0 +1,229 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT 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 "kgsl.h"
+#include "kgsl_device.h"
+#include "z180.h"
+#include "z180_reg.h"
+
+#define Z180_STREAM_PACKET_CALL 0x7C000275
+
+/* Postmortem Dump formatted Output parameters */
+
+/* Number of Words per dump data line */
+#define WORDS_PER_LINE 8
+
+/* Number of spaces per dump data line */
+#define NUM_SPACES (WORDS_PER_LINE - 1)
+
+/*
+ * Output dump data is formatted as string, hence number of chars
+ * per line for line string allocation
+ */
+#define CHARS_PER_LINE  \
+	((WORDS_PER_LINE * (2*sizeof(unsigned int))) + NUM_SPACES + 1)
+
+/* Z180 registers (byte offsets) to be dumped */
+static const unsigned int regs_to_dump[] = {
+		ADDR_VGC_VERSION,
+		ADDR_VGC_SYSSTATUS,
+		ADDR_VGC_IRQSTATUS,
+		ADDR_VGC_IRQENABLE,
+		ADDR_VGC_IRQ_ACTIVE_CNT,
+		ADDR_VGC_CLOCKEN,
+		ADDR_VGC_MH_DATA_ADDR,
+		ADDR_VGC_GPR0,
+		ADDR_VGC_GPR1,
+		ADDR_VGC_BUSYCNT,
+		ADDR_VGC_FIFOFREE,
+};
+
+/**
+ * z180_dump_regs - Dumps all of Z180 external registers. Prints the word offset
+ * of the register in each output line.
+ * @device: kgsl_device pointer to the Z180 core
+ */
+static void z180_dump_regs(struct kgsl_device *device)
+{
+	unsigned int i;
+	unsigned int reg_val;
+
+	KGSL_LOG_DUMP(device, "Z180 Register Dump\n");
+	for (i = 0; i < ARRAY_SIZE(regs_to_dump); i++) {
+		kgsl_regread(device,
+				regs_to_dump[i]/sizeof(unsigned int), &reg_val);
+		KGSL_LOG_DUMP(device, "REG: %04X: %08X\n",
+				regs_to_dump[i]/sizeof(unsigned int), reg_val);
+	}
+}
+
+/**
+ * z180_dump_ringbuffer - Dumps the Z180 core's ringbuffer contents
+ * @device: kgsl_device pointer to the z180 core
+ */
+static void z180_dump_ringbuffer(struct kgsl_device *device)
+{
+	unsigned int rb_size;
+	unsigned int *rb_hostptr;
+	unsigned int rb_words;
+	unsigned int rb_gpuaddr;
+	struct z180_device *z180_dev = Z180_DEVICE(device);
+	unsigned int i;
+	char linebuf[CHARS_PER_LINE];
+
+	KGSL_LOG_DUMP(device, "Z180 ringbuffer dump\n");
+
+	rb_hostptr = (unsigned int *) z180_dev->ringbuffer.cmdbufdesc.hostptr;
+
+	rb_size = Z180_RB_SIZE;
+	rb_gpuaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr;
+
+	rb_words = rb_size/sizeof(unsigned int);
+
+	KGSL_LOG_DUMP(device, "ringbuffer size: %u\n", rb_size);
+
+	KGSL_LOG_DUMP(device, "rb_words: %d\n", rb_words);
+
+	for (i = 0; i < rb_words; i += WORDS_PER_LINE) {
+		hex_dump_to_buffer(rb_hostptr+i,
+				rb_size - i*sizeof(unsigned int),
+				WORDS_PER_LINE*sizeof(unsigned int),
+				sizeof(unsigned int), linebuf,
+				sizeof(linebuf), false);
+		KGSL_LOG_DUMP(device, "RB: %04X: %s\n",
+				rb_gpuaddr + i*sizeof(unsigned int), linebuf);
+	}
+}
+
+
+static void z180_dump_ib(struct kgsl_device *device)
+{
+	unsigned int rb_size;
+	unsigned int *rb_hostptr;
+	unsigned int rb_words;
+	unsigned int rb_gpuaddr;
+	unsigned int ib_gpuptr = 0;
+	unsigned int ib_size = 0;
+	void *ib_hostptr = NULL;
+	int rb_slot_num = -1;
+	struct z180_device *z180_dev = Z180_DEVICE(device);
+	struct kgsl_mem_entry *entry = NULL;
+	unsigned int pt_base;
+	unsigned int i;
+	unsigned int j;
+	char linebuf[CHARS_PER_LINE];
+	unsigned int current_ib_slot;
+	unsigned int len;
+	unsigned int rowsize;
+	KGSL_LOG_DUMP(device, "Z180 IB dump\n");
+
+	rb_hostptr = (unsigned int *) z180_dev->ringbuffer.cmdbufdesc.hostptr;
+
+	rb_size = Z180_RB_SIZE;
+	rb_gpuaddr = z180_dev->ringbuffer.cmdbufdesc.gpuaddr;
+
+	rb_words = rb_size/sizeof(unsigned int);
+
+	KGSL_LOG_DUMP(device, "Ringbuffer size (bytes): %u\n", rb_size);
+
+	KGSL_LOG_DUMP(device, "rb_words: %d\n", rb_words);
+
+	pt_base = kgsl_mmu_get_current_ptbase(&device->mmu);
+
+	/* Dump the current IB */
+	for (i = 0; i < rb_words; i++) {
+		if (rb_hostptr[i] == Z180_STREAM_PACKET_CALL) {
+
+			rb_slot_num++;
+			current_ib_slot =
+				z180_dev->current_timestamp % Z180_PACKET_COUNT;
+			if (rb_slot_num != current_ib_slot)
+				continue;
+
+			ib_gpuptr = rb_hostptr[i+1];
+
+			entry = kgsl_get_mem_entry(pt_base, ib_gpuptr, 1);
+
+			if (entry == NULL) {
+				KGSL_LOG_DUMP(device,
+				"IB mem entry not found for ringbuffer slot#: %d\n",
+				rb_slot_num);
+				continue;
+			}
+
+			ib_hostptr = kgsl_memdesc_map(&entry->memdesc);
+
+			if (ib_hostptr == NULL) {
+				KGSL_LOG_DUMP(device,
+				"Could not map IB to kernel memory, Ringbuffer Slot: %d\n",
+				rb_slot_num);
+				continue;
+			}
+
+			ib_size = entry->memdesc.size;
+			KGSL_LOG_DUMP(device,
+				"IB size: %dbytes, IB size in words: %d\n",
+				ib_size,
+				ib_size/sizeof(unsigned int));
+
+			for (j = 0; j < ib_size; j += WORDS_PER_LINE) {
+				len = ib_size - j*sizeof(unsigned int);
+				rowsize = WORDS_PER_LINE*sizeof(unsigned int);
+				hex_dump_to_buffer(ib_hostptr+j, len, rowsize,
+						sizeof(unsigned int), linebuf,
+						sizeof(linebuf), false);
+				KGSL_LOG_DUMP(device, "IB%d: %04X: %s\n",
+						rb_slot_num,
+						(rb_gpuaddr +
+						j*sizeof(unsigned int)),
+						linebuf);
+			}
+			KGSL_LOG_DUMP(device, "IB Dump Finished\n");
+		}
+	}
+}
+
+
+/**
+ * z180_dump - Dumps the Z180 ringbuffer and registers (and IBs if asked for)
+ * for postmortem
+ * analysis.
+ * @device: kgsl_device pointer to the Z180 core
+ */
+int z180_dump(struct kgsl_device *device, int manual)
+{
+	struct z180_device *z180_dev = Z180_DEVICE(device);
+
+	mb();
+
+	KGSL_LOG_DUMP(device, "Retired Timestamp: %d\n", z180_dev->timestamp);
+	KGSL_LOG_DUMP(device,
+			"Current Timestamp: %d\n", z180_dev->current_timestamp);
+
+	/* Dump ringbuffer */
+	z180_dump_ringbuffer(device);
+
+	/* Dump registers */
+	z180_dump_regs(device);
+
+	/* Dump IBs, if asked for */
+	if (device->pm_ib_enabled)
+		z180_dump_ib(device);
+
+	/* Get the stack trace if the dump was automatic */
+	if (!manual)
+		BUG_ON(1);
+
+	return 0;
+}
+
diff --git a/drivers/gpu/msm/z180_reg.h b/drivers/gpu/msm/z180_reg.h
index 5b6c001..07d60b9 100644
--- a/drivers/gpu/msm/z180_reg.h
+++ b/drivers/gpu/msm/z180_reg.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2002,2007-2011, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2002,2007-2012, Code Aurora Forum. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -45,5 +45,12 @@
 #define ADDR_VGV3_NEXTADDR               0x0075
 #define ADDR_VGV3_NEXTCMD                0x0076
 #define ADDR_VGV3_WRITEADDR              0x0072
+#define ADDR_VGC_VERSION				 0x400
+#define ADDR_VGC_SYSSTATUS				 0x410
+#define ADDR_VGC_CLOCKEN				 0x508
+#define ADDR_VGC_GPR0					 0x520
+#define ADDR_VGC_GPR1					 0x528
+#define ADDR_VGC_BUSYCNT				 0x530
+#define ADDR_VGC_FIFOFREE				 0x7c0
 
 #endif /* __Z180_REG_H */
diff --git a/drivers/hwmon/qpnp-adc-common.c b/drivers/hwmon/qpnp-adc-common.c
index e24eeaf..c122270 100644
--- a/drivers/hwmon/qpnp-adc-common.c
+++ b/drivers/hwmon/qpnp-adc-common.c
@@ -111,7 +111,7 @@
 	struct qpnp_vadc_amux *adc_channel_list;
 	struct qpnp_adc_properties *adc_prop;
 	struct qpnp_adc_amux_properties *amux_prop;
-	int count_adc_channel_list = 0, decimation, rc = 0;
+	int count_adc_channel_list = 0, decimation, rc = 0, i = 0;
 
 	if (!node)
 		return -EINVAL;
@@ -133,7 +133,7 @@
 		return -ENOMEM;
 	}
 	adc_channel_list = devm_kzalloc(&spmi->dev,
-		(sizeof(struct qpnp_vadc_amux) * count_adc_channel_list),
+		sizeof(struct qpnp_vadc_amux) * count_adc_channel_list,
 				GFP_KERNEL);
 	if (!adc_channel_list) {
 		dev_err(&spmi->dev, "Unable to allocate memory\n");
@@ -148,9 +148,12 @@
 		return -ENOMEM;
 	}
 
+	adc_qpnp->adc_channels = adc_channel_list;
+	adc_qpnp->amux_prop = amux_prop;
+
 	for_each_child_of_node(node, child) {
 		int channel_num, scaling, post_scaling, hw_settle_time;
-		int fast_avg_setup, calib_type, i = 0, rc;
+		int fast_avg_setup, calib_type, rc;
 		const char *calibration_param, *channel_name;
 
 		channel_name = of_get_property(child,
@@ -216,8 +219,6 @@
 		adc_channel_list[i].fast_avg_setup = fast_avg_setup;
 		i++;
 	}
-	adc_qpnp->adc_channels = adc_channel_list;
-	adc_qpnp->amux_prop = amux_prop;
 
 	/* Get the ADC VDD reference voltage and ADC bit resolution */
 	rc = of_property_read_u32(node, "qcom,adc-vdd-reference",
diff --git a/drivers/hwmon/qpnp-adc-current.c b/drivers/hwmon/qpnp-adc-current.c
index 95da3b9..b689255 100644
--- a/drivers/hwmon/qpnp-adc-current.c
+++ b/drivers/hwmon/qpnp-adc-current.c
@@ -142,7 +142,7 @@
 	int rc;
 
 	rc = spmi_ext_register_readl(iadc->adc->spmi->ctrl, iadc->adc->slave,
-		reg, data, 1);
+		(iadc->adc->offset + reg), data, 1);
 	if (rc < 0) {
 		pr_err("qpnp iadc read reg %d failed with %d\n", reg, rc);
 		return rc;
@@ -159,7 +159,7 @@
 
 	buf = &data;
 	rc = spmi_ext_register_writel(iadc->adc->spmi->ctrl, iadc->adc->slave,
-		reg, buf, 1);
+		(iadc->adc->offset + reg), buf, 1);
 	if (rc < 0) {
 		pr_err("qpnp iadc write reg %d failed with %d\n", reg, rc);
 		return rc;
diff --git a/drivers/hwmon/qpnp-adc-voltage.c b/drivers/hwmon/qpnp-adc-voltage.c
index 8d6d411..9e8a2e2 100644
--- a/drivers/hwmon/qpnp-adc-voltage.c
+++ b/drivers/hwmon/qpnp-adc-voltage.c
@@ -37,6 +37,7 @@
 #define QPNP_VADC_STATUS1_MEAS_INTERVAL_EN_STS			BIT(2)
 #define QPNP_VADC_STATUS1_REQ_STS				BIT(1)
 #define QPNP_VADC_STATUS1_EOC					BIT(0)
+#define QPNP_VADC_STATUS1_REQ_STS_EOC_MASK			0x3
 #define QPNP_VADC_STATUS2					0x9
 #define QPNP_VADC_STATUS2_CONV_SEQ_STATE				6
 #define QPNP_VADC_STATUS2_FIFO_NOT_EMPTY_FLAG			BIT(1)
@@ -112,7 +113,7 @@
 	int rc;
 
 	rc = spmi_ext_register_readl(vadc->adc->spmi->ctrl, vadc->adc->slave,
-		reg, data, 1);
+		(vadc->adc->offset + reg), data, 1);
 	if (rc < 0) {
 		pr_err("qpnp adc read reg %d failed with %d\n", reg, rc);
 		return rc;
@@ -130,7 +131,7 @@
 	buf = &data;
 
 	rc = spmi_ext_register_writel(vadc->adc->spmi->ctrl, vadc->adc->slave,
-		reg, buf, 1);
+		(vadc->adc->offset + reg), buf, 1);
 	if (rc < 0) {
 		pr_err("qpnp adc write reg %d failed with %d\n", reg, rc);
 		return rc;
@@ -200,61 +201,87 @@
 int32_t qpnp_vadc_configure(
 			struct qpnp_adc_amux_properties *chan_prop)
 {
+	struct qpnp_vadc_drv *vadc = qpnp_vadc;
 	u8 decimation = 0, conv_sequence = 0, conv_sequence_trig = 0;
+	u8 mode_ctrl = 0;
 	int rc = 0;
 
-	rc = qpnp_vadc_write_reg(QPNP_VADC_INT_EN_SET,
+	if (vadc->vadc_init_calib) {
+		/* Configure interrupt if calibration is complete */
+		rc = qpnp_vadc_write_reg(QPNP_VADC_INT_EN_SET,
 				QPNP_VADC_INT_EOC_BIT);
+		if (rc < 0) {
+			pr_err("Configure error for interrupt setup\n");
+			return rc;
+		}
+	}
+
+	/* Mode selection */
+	rc = qpnp_vadc_read_reg(QPNP_VADC_MODE_CTL, &mode_ctrl);
 	if (rc < 0) {
-		pr_err("qpnp adc configure error for interrupt setup\n");
+		pr_err("Mode configure read error\n");
+		return rc;
+	}
+	mode_ctrl |= chan_prop->mode_sel << QPNP_VADC_OP_MODE_SHIFT;
+	rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, mode_ctrl);
+	if (rc < 0) {
+		pr_err("Mode configure write error\n");
 		return rc;
 	}
 
-	rc = qpnp_vadc_write_reg(QPNP_VADC_MODE_CTL, chan_prop->mode_sel);
-	if (rc < 0) {
-		pr_err("qpnp adc configure error for mode selection\n");
+	rc = qpnp_vadc_enable(true);
+	if (rc)
 		return rc;
-	}
 
+	/* Channel selection */
 	rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_CH_SEL_CTL,
 						chan_prop->amux_channel);
 	if (rc < 0) {
-		pr_err("qpnp adc configure error for channel selection\n");
+		pr_err("Channel configure error\n");
 		return rc;
 	}
 
+	/* Digital parameter setup */
+	rc = qpnp_vadc_read_reg(QPNP_VADC_ADC_DIG_PARAM, &decimation);
+	if (rc < 0) {
+		pr_err("Digital parameter configure read error\n");
+		return rc;
+	}
 	decimation |= chan_prop->decimation <<
 				QPNP_VADC_ADC_DIG_DEC_RATIO_SEL_SHIFT;
 	rc = qpnp_vadc_write_reg(QPNP_VADC_ADC_DIG_PARAM, decimation);
 	if (rc < 0) {
-		pr_err("qpnp adc configure error for digital parameter setup\n");
+		pr_err("Digital parameter configure write error\n");
 		return rc;
 	}
 
+	/* HW settling time delay */
 	rc = qpnp_vadc_write_reg(QPNP_VADC_HW_SETTLE_DELAY,
 						chan_prop->hw_settle_time);
 	if (rc < 0) {
-		pr_err("qpnp adc configure error for hw settling time setup\n");
+		pr_err("HW settling time setup error\n");
 		return rc;
 	}
 
 	if (chan_prop->mode_sel == (ADC_OP_NORMAL_MODE <<
 					QPNP_VADC_OP_MODE_SHIFT)) {
+		/* Normal measurement mode */
 		rc = qpnp_vadc_write_reg(QPNP_VADC_FAST_AVG_CTL,
 						chan_prop->fast_avg_setup);
 		if (rc < 0) {
-			pr_err("qpnp adc fast averaging configure error\n");
+			pr_err("Fast averaging configure error\n");
 			return rc;
 		}
 	} else if (chan_prop->mode_sel == (ADC_OP_CONVERSION_SEQUENCER <<
 					QPNP_VADC_OP_MODE_SHIFT)) {
+		/* Conversion sequence mode */
 		conv_sequence = ((ADC_SEQ_HOLD_100US <<
 				QPNP_VADC_CONV_SEQ_HOLDOFF_SHIFT) |
 				ADC_CONV_SEQ_TIMEOUT_5MS);
 		rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_CTL,
 							conv_sequence);
 		if (rc < 0) {
-			pr_err("qpnp adc conversion sequence error\n");
+			pr_err("Conversion sequence error\n");
 			return rc;
 		}
 
@@ -264,14 +291,15 @@
 		rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_SEQ_TRIG_CTL,
 							conv_sequence_trig);
 		if (rc < 0) {
-			pr_err("qpnp adc conversion trigger error\n");
+			pr_err("Conversion trigger error\n");
 			return rc;
 		}
 	}
 
+	/* Request conversion */
 	rc = qpnp_vadc_write_reg(QPNP_VADC_CONV_REQ, QPNP_VADC_CONV_REQ_SET);
 	if (rc < 0) {
-		pr_err("qpnp adc request conversion failed\n");
+		pr_err("Request conversion failed\n");
 		return rc;
 	}
 
@@ -282,29 +310,34 @@
 static int32_t qpnp_vadc_read_conversion_result(int32_t *data)
 {
 	uint8_t rslt_lsb, rslt_msb;
-	int rc = 0;
+	int rc = 0, status = 0;
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_DATA0, &rslt_lsb);
-	if (rc < 0) {
-		pr_err("qpnp adc result read failed for data0 with %d\n", rc);
-		return rc;
+	status = qpnp_vadc_read_reg(QPNP_VADC_DATA0, &rslt_lsb);
+	if (status < 0) {
+		pr_err("qpnp adc result read failed for data0\n");
+		goto fail;
 	}
 
-	rc = qpnp_vadc_read_reg(QPNP_VADC_DATA1, &rslt_msb);
-	if (rc < 0) {
-		pr_err("qpnp adc result read failed for data1 with %d\n", rc);
-		return rc;
+	status = qpnp_vadc_read_reg(QPNP_VADC_DATA1, &rslt_msb);
+	if (status < 0) {
+		pr_err("qpnp adc result read failed for data1\n");
+		goto fail;
 	}
 
 	*data = (rslt_msb << 8) | rslt_lsb;
 
-	rc = qpnp_vadc_check_result(data);
-	if (rc < 0) {
+	status = qpnp_vadc_check_result(data);
+	if (status < 0) {
 		pr_err("VADC data check failed\n");
-		return rc;
+		goto fail;
 	}
 
-	return 0;
+fail:
+	rc = qpnp_vadc_enable(false);
+	if (rc)
+		return rc;
+
+	return status;
 }
 
 static int32_t qpnp_vadc_read_status(int mode_sel)
@@ -393,6 +426,7 @@
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
+		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
 	}
@@ -414,11 +448,13 @@
 		goto calib_fail;
 	}
 
+	status1 = 0;
 	while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
 					QPNP_VADC_STATUS1_EOC)) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
+		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
 	}
@@ -449,11 +485,13 @@
 		goto calib_fail;
 	}
 
+	status1 = 0;
 	while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
 					QPNP_VADC_STATUS1_EOC)) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
+		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
 	}
@@ -475,11 +513,13 @@
 		goto calib_fail;
 	}
 
+	status1 = 0;
 	while (status1 != (~QPNP_VADC_STATUS1_REQ_STS |
 					QPNP_VADC_STATUS1_EOC)) {
 		rc = qpnp_vadc_read_reg(QPNP_VADC_STATUS1, &status1);
 		if (rc < 0)
 			return rc;
+		status1 &= QPNP_VADC_STATUS1_REQ_STS_EOC_MASK;
 		usleep_range(QPNP_VADC_CONV_TIME_MIN,
 					QPNP_VADC_CONV_TIME_MAX);
 	}
@@ -508,7 +548,7 @@
 					struct qpnp_vadc_result *result)
 {
 	struct qpnp_vadc_drv *vadc = qpnp_vadc;
-	int rc, scale_type, amux_prescaling;
+	int rc = 0, scale_type, amux_prescaling;
 
 	if (!vadc->vadc_init_calib) {
 		rc = qpnp_vadc_calib_device();
@@ -521,10 +561,6 @@
 
 	mutex_lock(&vadc->adc->adc_lock);
 
-	rc = qpnp_vadc_enable(true);
-	if (rc)
-		goto fail_unlock;
-
 	vadc->adc->amux_prop->amux_channel = channel;
 	vadc->adc->amux_prop->decimation =
 			vadc->adc->adc_channels[channel].adc_decimation;
@@ -541,15 +577,15 @@
 						<< QPNP_VADC_OP_MODE_SHIFT);
 	else {
 		pr_err("Invalid trigger channel:%d\n", trigger_channel);
-		goto fail;
+		goto fail_unlock;
 	}
 
 	vadc->adc->amux_prop->trigger_channel = trigger_channel;
 
 	rc = qpnp_vadc_configure(vadc->adc->amux_prop);
 	if (rc) {
-		pr_info("qpnp vadc configure failed with %d\n", rc);
-		goto fail;
+		pr_err("qpnp vadc configure failed with %d\n", rc);
+		goto fail_unlock;
 	}
 
 	wait_for_completion(&vadc->adc->adc_rslt_completion);
@@ -557,13 +593,13 @@
 	if (trigger_channel < ADC_SEQ_NONE) {
 		rc = qpnp_vadc_read_status(vadc->adc->amux_prop->mode_sel);
 		if (rc)
-			pr_info("Conversion sequence timed out - %d\n", rc);
+			pr_debug("Conversion sequence timed out - %d\n", rc);
 	}
 
 	rc = qpnp_vadc_read_conversion_result(&result->adc_code);
 	if (rc) {
-		pr_info("qpnp vadc read adc code failed with %d\n", rc);
-		goto fail;
+		pr_err("qpnp vadc read adc code failed with %d\n", rc);
+		goto fail_unlock;
 	}
 
 	amux_prescaling = vadc->adc->adc_channels[channel].chan_path_prescaling;
@@ -576,17 +612,12 @@
 	scale_type = vadc->adc->adc_channels[channel].adc_scale_fn;
 	if (scale_type >= SCALE_NONE) {
 		rc = -EBADF;
-		goto fail;
+		goto fail_unlock;
 	}
 
 	vadc_scale_fn[scale_type].chan(result->adc_code,
 		vadc->adc->adc_prop, vadc->adc->amux_prop->chan_prop, result);
 
-fail:
-	rc = qpnp_vadc_enable(false);
-	if (rc)
-		pr_err("Disable ADC failed during configuration\n");
-
 fail_unlock:
 	mutex_unlock(&vadc->adc->adc_lock);
 
@@ -649,7 +680,7 @@
 
 	return 0;
 hwmon_err_sens:
-	pr_info("Init HWMON failed for qpnp_adc with %d\n", rc);
+	pr_err("Init HWMON failed for qpnp_adc with %d\n", rc);
 	return rc;
 }
 
diff --git a/drivers/input/misc/mpu3050.c b/drivers/input/misc/mpu3050.c
index 8b6e172..d3da652 100644
--- a/drivers/input/misc/mpu3050.c
+++ b/drivers/input/misc/mpu3050.c
@@ -40,6 +40,7 @@
 #include <linux/delay.h>
 #include <linux/slab.h>
 #include <linux/pm_runtime.h>
+#include <linux/gpio.h>
 #include <linux/input/mpu3050.h>
 #include <linux/regulator/consumer.h>
 
@@ -50,6 +51,8 @@
 #define MPU3050_MIN_VALUE	-32768
 #define MPU3050_MAX_VALUE	32767
 
+#define MPU3050_MIN_POLL_INTERVAL	1
+#define MPU3050_MAX_POLL_INTERVAL	250
 #define MPU3050_DEFAULT_POLL_INTERVAL	200
 #define MPU3050_DEFAULT_FS_RANGE	3
 
@@ -90,8 +93,10 @@
 #define MPU3050_DLPF_CFG_MASK		0x07
 /* INT_CFG */
 #define MPU3050_RAW_RDY_EN		0x01
-#define MPU3050_MPU_RDY_EN		0x02
-#define MPU3050_LATCH_INT_EN		0x04
+#define MPU3050_MPU_RDY_EN		0x04
+#define MPU3050_LATCH_INT_EN		0x20
+#define MPU3050_OPEN_DRAIN		0x40
+#define MPU3050_ACTIVE_LOW		0x80
 /* PWR_MGM */
 #define MPU3050_PWR_MGM_PLL_X		0x01
 #define MPU3050_PWR_MGM_PLL_Y		0x02
@@ -117,6 +122,7 @@
 	struct mpu3050_gyro_platform_data *platform_data;
 	struct delayed_work input_work;
 	u32    use_poll;
+	u32    poll_interval;
 };
 
 struct sensor_regulator {
@@ -190,6 +196,78 @@
 }
 
 /**
+ *	mpu3050_attr_get_polling_rate	-	get the sampling rate
+ */
+static ssize_t mpu3050_attr_get_polling_rate(struct device *dev,
+				struct device_attribute *attr,
+				char *buf)
+{
+	int val;
+	struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+	val = sensor ? sensor->poll_interval : 0;
+	return snprintf(buf, 8, "%d\n", val);
+}
+
+/**
+ *	mpu3050_attr_set_polling_rate	-	set the sampling rate
+ */
+static ssize_t mpu3050_attr_set_polling_rate(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct mpu3050_sensor *sensor = dev_get_drvdata(dev);
+	unsigned long interval_ms;
+
+	if (kstrtoul(buf, 10, &interval_ms))
+		return -EINVAL;
+	if ((interval_ms < MPU3050_MIN_POLL_INTERVAL) ||
+		(interval_ms > MPU3050_MAX_POLL_INTERVAL))
+		return -EINVAL;
+
+	if (sensor)
+		sensor->poll_interval = interval_ms;
+
+	/* Output frequency divider. The poll interval */
+	i2c_smbus_write_byte_data(sensor->client, MPU3050_SMPLRT_DIV,
+					interval_ms - 1);
+
+	return size;
+}
+
+static struct device_attribute attributes[] = {
+
+	__ATTR(pollrate_ms, 0666,
+		mpu3050_attr_get_polling_rate,
+		mpu3050_attr_set_polling_rate),
+};
+
+static int create_sysfs_interfaces(struct device *dev)
+{
+	int i;
+	int err;
+	for (i = 0; i < ARRAY_SIZE(attributes); i++) {
+		err = device_create_file(dev, attributes + i);
+		if (err)
+			goto error;
+	}
+	return 0;
+
+error:
+	for ( ; i >= 0; i--)
+		device_remove_file(dev, attributes + i);
+	dev_err(dev, "%s:Unable to create interface\n", __func__);
+	return err;
+}
+
+static int remove_sysfs_interfaces(struct device *dev)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(attributes); i++)
+		device_remove_file(dev, attributes + i);
+	return 0;
+}
+
+/**
  *	mpu3050_xyz_read_reg	-	read the axes values
  *	@buffer: provide register addr and get register
  *	@length: length of register
@@ -284,20 +362,20 @@
 	struct mpu3050_sensor *sensor = input_get_drvdata(input);
 	int error;
 
-	pm_runtime_get(sensor->dev);
+	pm_runtime_get_sync(sensor->dev);
 
 	/* Enable interrupts */
 	error = i2c_smbus_write_byte_data(sensor->client, MPU3050_INT_CFG,
-					  MPU3050_LATCH_INT_EN |
-					  MPU3050_RAW_RDY_EN |
-					  MPU3050_MPU_RDY_EN);
+					MPU3050_ACTIVE_LOW |
+					MPU3050_OPEN_DRAIN |
+					MPU3050_RAW_RDY_EN);
 	if (error < 0) {
 		pm_runtime_put(sensor->dev);
 		return error;
 	}
 	if (sensor->use_poll)
 		schedule_delayed_work(&sensor->input_work,
-			msecs_to_jiffies(MPU3050_DEFAULT_POLL_INTERVAL));
+			msecs_to_jiffies(sensor->poll_interval));
 
 	return 0;
 }
@@ -366,7 +444,7 @@
 
 	if (sensor->use_poll)
 		schedule_delayed_work(&sensor->input_work,
-			msecs_to_jiffies(MPU3050_DEFAULT_POLL_INTERVAL));
+			msecs_to_jiffies(sensor->poll_interval));
 }
 
 /**
@@ -399,7 +477,7 @@
 
 	/* Output frequency divider. The poll interval */
 	ret = i2c_smbus_write_byte_data(client, MPU3050_SMPLRT_DIV,
-					MPU3050_DEFAULT_POLL_INTERVAL - 1);
+					sensor->poll_interval - 1);
 	if (ret < 0)
 		return ret;
 
@@ -444,6 +522,18 @@
 	sensor->dev = &client->dev;
 	sensor->idev = idev;
 	sensor->platform_data = client->dev.platform_data;
+	i2c_set_clientdata(client, sensor);
+	if (sensor->platform_data) {
+		u32 interval = sensor->platform_data->poll_interval;
+
+		if ((interval < MPU3050_MIN_POLL_INTERVAL) ||
+			(interval > MPU3050_MAX_POLL_INTERVAL))
+			sensor->poll_interval = MPU3050_DEFAULT_POLL_INTERVAL;
+		else
+			sensor->poll_interval = interval;
+	} else {
+		sensor->poll_interval = MPU3050_DEFAULT_POLL_INTERVAL;
+	}
 
 	mpu3050_set_power_mode(client, 1);
 	msleep(10);
@@ -485,14 +575,34 @@
 		goto err_pm_set_suspended;
 
 	if (client->irq == 0) {
-		INIT_DELAYED_WORK(&sensor->input_work, mpu3050_input_work_fn);
 		sensor->use_poll = 1;
+		INIT_DELAYED_WORK(&sensor->input_work, mpu3050_input_work_fn);
 	} else {
 		sensor->use_poll = 0;
 
+		if (gpio_is_valid(sensor->platform_data->gpio_int)) {
+			/* configure interrupt gpio */
+			ret = gpio_request(sensor->platform_data->gpio_int,
+								"gyro_gpio_int");
+			if (ret) {
+				pr_err("%s: unable to request interrupt gpio %d\n",
+					__func__,
+					sensor->platform_data->gpio_int);
+				goto err_pm_set_suspended;
+			}
+
+			ret = gpio_direction_input(
+				sensor->platform_data->gpio_int);
+			if (ret) {
+				pr_err("%s: unable to set direction for gpio %d\n",
+				__func__, sensor->platform_data->gpio_int);
+				goto err_free_gpio;
+			}
+		}
+
 		error = request_threaded_irq(client->irq,
 				     NULL, mpu3050_interrupt_thread,
-				     IRQF_TRIGGER_RISING,
+				     IRQF_TRIGGER_FALLING,
 				     "mpu3050", sensor);
 		if (error) {
 			dev_err(&client->dev,
@@ -508,14 +618,26 @@
 		goto err_free_irq;
 	}
 
+	error = create_sysfs_interfaces(&client->dev);
+	if (error < 0) {
+		dev_err(&client->dev, "failed to create sysfs\n");
+		goto err_input_cleanup;
+	}
+
 	pm_runtime_enable(&client->dev);
 	pm_runtime_set_autosuspend_delay(&client->dev, MPU3050_AUTO_DELAY);
 
 	return 0;
 
+err_input_cleanup:
+	input_unregister_device(idev);
 err_free_irq:
 	if (client->irq > 0)
 		free_irq(client->irq, sensor);
+err_free_gpio:
+	if ((client->irq > 0) &&
+		(gpio_is_valid(sensor->platform_data->gpio_int)))
+		gpio_free(sensor->platform_data->gpio_int);
 err_pm_set_suspended:
 	pm_runtime_set_suspended(&client->dev);
 err_free_mem:
@@ -537,8 +659,12 @@
 	pm_runtime_disable(&client->dev);
 	pm_runtime_set_suspended(&client->dev);
 
-	free_irq(client->irq, sensor);
+	if (client->irq)
+		free_irq(client->irq, sensor);
+
+	remove_sysfs_interfaces(&client->dev);
 	input_unregister_device(sensor->idev);
+
 	kfree(sensor);
 
 	return 0;
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
index bd1ecfe..74a0dbe 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tsif.c
@@ -26,8 +26,8 @@
 #define DMX_TSIF_MAX_SECTION_FILTER_NUM	64
 
 /* When TSIF driver notifies demux that new packets are received */
-#define DMX_TSIF_PACKETS_IN_CHUNK_DEF		16
-#define DMX_TSIF_CHUNKS_IN_BUF			8
+#define DMX_TSIF_PACKETS_IN_CHUNK_DEF		512
+#define DMX_TSIF_CHUNKS_IN_BUF			16
 #define DMX_TSIF_TIME_LIMIT			10000
 
 /* TSIF_DRIVER_MODE: 3 means manual control from debugfs. use 1 normally. */
diff --git a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
index fd94e80..372c612 100644
--- a/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
+++ b/drivers/media/dvb/mpq/demux/mpq_dmx_plugin_tspp_v1.c
@@ -47,18 +47,20 @@
 
 #define TSPP_RAW_TTS_SIZE				192
 
-/* Size of single descriptor.
- * Assuming 20MBit/sec stream, with 200 packets
- * per descriptor there would be about 68 descriptors.
- * Meanning about 68 interrupts per second.
+/* Size of single descriptor. Using max descriptor size (170 packets).
+ * Assuming 20MBit/sec stream, with 170 packets
+ * per descriptor there would be about 82 descriptors,
+ * Meanning about 82 notifications per second.
  */
-#define TSPP_BUFFER_SIZE			(TSPP_RAW_TTS_SIZE * 200)
+#define MAX_BAM_DESCRIPTOR_SIZE		(32*1024 - 1)
+#define TSPP_BUFFER_SIZE			\
+	((MAX_BAM_DESCRIPTOR_SIZE / TSPP_RAW_TTS_SIZE) * TSPP_RAW_TTS_SIZE)
 
 /* Number of descriptors, total size: TSPP_BUFFER_SIZE*TSPP_BUFFER_COUNT */
-#define TSPP_BUFFER_COUNT				(16)
+#define TSPP_BUFFER_COUNT				(32)
 
 /* When TSPP notifies demux that new packets are received */
-#define TSPP_NOTIFICATION_SIZE			(TSPP_RAW_TTS_SIZE * 100)
+#define TSPP_NOTIFICATION_SIZE			1
 
 /* Channel timeout in msec */
 #define TSPP_CHANNEL_TIMEOUT			16
@@ -232,7 +234,7 @@
  * @channel_id: Channel with new TS packets
  * @user: user-data holding TSIF number
  */
-static void mpq_tspp_callback(u32 channel_id, void *user)
+static void mpq_tspp_callback(int channel_id, void *user)
 {
 	int tsif = (int)user;
 	struct work_struct *work;
diff --git a/drivers/media/video/msm_vidc/msm_smem.c b/drivers/media/video/msm_vidc/msm_smem.c
index 76e3592..ff12a5c 100644
--- a/drivers/media/video/msm_vidc/msm_smem.c
+++ b/drivers/media/video/msm_vidc/msm_smem.c
@@ -108,8 +108,6 @@
 	unsigned long iova = 0;
 	unsigned long buffer_size = 0;
 	int rc = 0;
-	if (size == 0)
-		goto skip_mem_alloc;
 	flags = flags | ION_HEAP(ION_CP_MM_HEAP_ID);
 	if (align < 4096)
 		align = 4096;
@@ -147,7 +145,6 @@
 fail_map:
 	ion_free(client->clnt, hndl);
 fail_shared_mem_alloc:
-skip_mem_alloc:
 	return rc;
 }
 
@@ -236,12 +233,15 @@
 	struct smem_client *client;
 	int rc = 0;
 	struct msm_smem *mem;
-
 	client = clt;
 	if (!client) {
 		pr_err("Invalid  client passed\n");
 		return NULL;
 	}
+	if (!size) {
+		pr_err("No need to allocate memory of size: %d\n", size);
+		return NULL;
+	}
 	mem = kzalloc(sizeof(*mem), GFP_KERNEL);
 	if (!mem) {
 		pr_err("Failed to allocate shared mem\n");
diff --git a/drivers/media/video/msm_vidc/msm_vdec.c b/drivers/media/video/msm_vidc/msm_vdec.c
index a683315..c87211a 100644
--- a/drivers/media/video/msm_vidc/msm_vdec.c
+++ b/drivers/media/video/msm_vidc/msm_vdec.c
@@ -440,15 +440,16 @@
 	if (fmt) {
 		f->fmt.pix_mp.pixelformat = fmt->fourcc;
 		if (inst->in_reconfig == true) {
-			inst->height = inst->reconfig_height;
-			inst->width = inst->reconfig_width;
+			inst->prop.height = inst->reconfig_height;
+			inst->prop.width = inst->reconfig_width;
 		}
-		f->fmt.pix_mp.height = inst->height;
-		f->fmt.pix_mp.width = inst->width;
+		f->fmt.pix_mp.height = inst->prop.height;
+		f->fmt.pix_mp.width = inst->prop.width;
 		f->fmt.pix_mp.num_planes = fmt->num_planes;
 		for (i = 0; i < fmt->num_planes; ++i) {
 			f->fmt.pix_mp.plane_fmt[i].sizeimage =
-			fmt->get_frame_size(i, inst->height, inst->width);
+			fmt->get_frame_size(i, inst->prop.height,
+				inst->prop.width);
 		}
 	} else {
 		pr_err("Buf type not recognized, type = %d\n",
@@ -584,7 +585,7 @@
 			*num_buffers = MIN_NUM_OUTPUT_BUFFERS;
 		for (i = 0; i < *num_planes; i++) {
 			sizes[i] = inst->fmts[OUTPUT_PORT]->get_frame_size(
-					i, inst->height, inst->width);
+					i, inst->prop.height, inst->prop.width);
 		}
 		break;
 	case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index f030163..14baf79 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -1201,7 +1201,7 @@
 	inst->fmts[OUTPUT_PORT] = &venc_formats[0];
 	inst->prop.height = DEFAULT_HEIGHT;
 	inst->prop.width = DEFAULT_WIDTH;
-	inst->prop.height = 30;
+	inst->prop.fps = 30;
 	return rc;
 }
 
diff --git a/drivers/media/video/msm_vidc/msm_vidc_common.c b/drivers/media/video/msm_vidc/msm_vidc_common.c
index 6835467..b07c63b 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_common.c
+++ b/drivers/media/video/msm_vidc/msm_vidc_common.c
@@ -1126,7 +1126,7 @@
 		pr_err("inst: %p is already in state: %d\n", inst, inst->state);
 		goto exit;
 	}
-	ocmem_sz = get_ocmem_requirement(inst->height, inst->width);
+	ocmem_sz = get_ocmem_requirement(inst->prop.height, inst->prop.width);
 	rc = msm_comm_alloc_ocmem(inst->core, ocmem_sz);
 	if (rc)
 		pr_warn("Failed to allocate OCMEM. Performance will be impacted\n");
@@ -1490,10 +1490,13 @@
 	struct list_head *ptr, *next;
 	struct vidc_buffer_addr_info buffer_info;
 	unsigned long flags;
+	struct hal_buffer_requirements *scratch_buf =
+		&inst->buff_req.buffer[HAL_BUFFER_INTERNAL_SCRATCH];
 	int i;
+
 	pr_debug("scratch: num = %d, size = %d\n",
-			inst->buff_req.buffer[6].buffer_count_actual,
-			inst->buff_req.buffer[6].buffer_size);
+			scratch_buf->buffer_count_actual,
+			scratch_buf->buffer_size);
 	spin_lock_irqsave(&inst->lock, flags);
 	if (!list_empty(&inst->internalbufs)) {
 		list_for_each_safe(ptr, next, &inst->internalbufs) {
@@ -1505,40 +1508,44 @@
 		}
 	}
 	spin_unlock_irqrestore(&inst->lock, flags);
-
-
-	for (i = 0; i < inst->buff_req.buffer[6].buffer_count_actual;
+	if (scratch_buf->buffer_size) {
+		for (i = 0; i < scratch_buf->buffer_count_actual;
 				i++) {
-		handle = msm_smem_alloc(inst->mem_client,
-				inst->buff_req.buffer[6].buffer_size, 1, 0,
+			handle = msm_smem_alloc(inst->mem_client,
+				scratch_buf->buffer_size, 1, 0,
 				inst->core->resources.io_map[NS_MAP].domain, 0);
-		if (!handle) {
-			pr_err("Failed to allocate scratch memory\n");
-			rc = -ENOMEM;
-			goto err_no_mem;
-		}
-		binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
-		if (!binfo) {
-			pr_err("Out of memory\n");
-			rc = -ENOMEM;
-			goto err_no_mem;
-		}
-		binfo->handle = handle;
-		spin_lock_irqsave(&inst->lock, flags);
-		list_add_tail(&binfo->list, &inst->internalbufs);
-		spin_unlock_irqrestore(&inst->lock, flags);
-		buffer_info.buffer_size =
-				inst->buff_req.buffer[6].buffer_size;
-		buffer_info.buffer_type = HAL_BUFFER_INTERNAL_SCRATCH;
-		buffer_info.num_buffers = 1;
-		buffer_info.align_device_addr = handle->device_addr;
-		rc = vidc_hal_session_set_buffers((void *) inst->session,
-				&buffer_info);
-		if (rc) {
-			pr_err("vidc_hal_session_set_buffers failed");
-			break;
+			if (!handle) {
+				pr_err("Failed to allocate scratch memory\n");
+				rc = -ENOMEM;
+				goto err_no_mem;
+			}
+			binfo = kzalloc(sizeof(*binfo), GFP_KERNEL);
+			if (!binfo) {
+				pr_err("Out of memory\n");
+				rc = -ENOMEM;
+				goto fail_kzalloc;
+			}
+			binfo->handle = handle;
+			buffer_info.buffer_size = scratch_buf->buffer_size;
+			buffer_info.buffer_type = HAL_BUFFER_INTERNAL_SCRATCH;
+			buffer_info.num_buffers = 1;
+			buffer_info.align_device_addr = handle->device_addr;
+			rc = vidc_hal_session_set_buffers(
+					(void *) inst->session,	&buffer_info);
+			if (rc) {
+				pr_err("vidc_hal_session_set_buffers failed");
+				goto fail_set_buffers;
+			}
+			spin_lock_irqsave(&inst->lock, flags);
+			list_add_tail(&binfo->list, &inst->internalbufs);
+			spin_unlock_irqrestore(&inst->lock, flags);
 		}
 	}
+	return rc;
+fail_set_buffers:
+	kfree(binfo);
+fail_kzalloc:
+	msm_smem_free(inst->mem_client, handle);
 err_no_mem:
 	return rc;
 }
diff --git a/drivers/media/video/msm_vidc/msm_vidc_internal.h b/drivers/media/video/msm_vidc/msm_vidc_internal.h
index 992f39c..8c11de8 100644
--- a/drivers/media/video/msm_vidc/msm_vidc_internal.h
+++ b/drivers/media/video/msm_vidc/msm_vidc_internal.h
@@ -201,8 +201,6 @@
 	int session_type;
 	void *session;
 	struct session_prop prop;
-	u32 width;
-	u32 height;
 	int state;
 	const struct msm_vidc_format *fmts[MAX_PORT_NUM];
 	struct vb2_queue vb2_bufq[MAX_PORT_NUM];
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index f1f1c69..9f2ead4 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -273,10 +273,10 @@
 
 #ifdef TOP_FIELD_FIX
 	writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
-	writel_iowmb(0x00030000 | vp_act->top_field << 0, VCAP_VP_CTRL);
+	writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
 #else
 	writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
-	writel_iowmb(0x00030000 | top_field, VCAP_VP_CTRL);
+	writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
 #endif
 	enable_irq(dev->vpirq->start);
 	writel_iowmb(irq, VCAP_VP_INT_CLEAR);
@@ -420,58 +420,84 @@
 
 int init_motion_buf(struct vcap_client_data *c_data)
 {
+	int rc;
 	struct vcap_dev *dev = c_data->dev;
-	void *buf;
-	unsigned long motion_base_addr;
-	uint32_t size = ((c_data->vp_out_fmt.width + 63) >> 6) *
+	struct ion_handle *handle = NULL;
+	unsigned long paddr, ionflag = 0;
+	void *vaddr;
+	size_t len;
+	size_t size = ((c_data->vp_out_fmt.width + 63) >> 6) *
 		((c_data->vp_out_fmt.height + 7) >> 3) * 16;
 
-	if (c_data->vid_vp_action.bufMotion) {
+	if (c_data->vid_vp_action.motionHandle) {
 		pr_err("Motion buffer has already been created");
 		return -ENOEXEC;
 	}
 
-	buf = kzalloc(size, GFP_KERNEL);
-	if (!buf)
+	handle = ion_alloc(dev->ion_client, size, SZ_4K,
+			ION_HEAP(ION_CP_MM_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: ion_alloc failed\n", __func__);
 		return -ENOMEM;
+	}
+	rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+	if (rc < 0) {
+		pr_err("%s: ion_phys failed\n", __func__);
+		ion_free(dev->ion_client, handle);
+		return rc;
+	}
 
-	c_data->vid_vp_action.bufMotion = buf;
-	motion_base_addr = virt_to_phys(buf);
-	writel_iowmb(motion_base_addr, VCAP_VP_MOTION_EST_ADDR);
+	rc = ion_handle_get_flags(dev->ion_client, handle, &ionflag);
+	if (rc) {
+		pr_err("%s: get flags ion handle failed\n", __func__);
+		ion_free(dev->ion_client, handle);
+		return rc;
+	}
+
+	vaddr = ion_map_kernel(dev->ion_client, handle, ionflag);
+	if (IS_ERR(vaddr)) {
+		pr_err("%s: Map motion buffer failed\n", __func__);
+		ion_free(dev->ion_client, handle);
+		rc = -ENOMEM;
+		return rc;
+	}
+
+	memset(vaddr, 0, size);
+	c_data->vid_vp_action.motionHandle = handle;
+
+	vaddr = NULL;
+	ion_unmap_kernel(dev->ion_client, handle);
+
+	writel_iowmb(paddr, VCAP_VP_MOTION_EST_ADDR);
 	return 0;
 }
 
 void deinit_motion_buf(struct vcap_client_data *c_data)
 {
 	struct vcap_dev *dev = c_data->dev;
-	void *buf;
-
-	if (!c_data->vid_vp_action.bufMotion) {
+	if (!c_data->vid_vp_action.motionHandle) {
 		pr_err("Motion buffer has not been created");
 		return;
 	}
 
-	buf = c_data->vid_vp_action.bufMotion;
-
 	writel_iowmb(0x00000000, VCAP_VP_MOTION_EST_ADDR);
-	c_data->vid_vp_action.bufMotion = NULL;
-	kfree(buf);
+	ion_free(dev->ion_client, c_data->vid_vp_action.motionHandle);
+	c_data->vid_vp_action.motionHandle = NULL;
 	return;
 }
 
 int init_nr_buf(struct vcap_client_data *c_data)
 {
 	struct vcap_dev *dev = c_data->dev;
-	struct nr_buffer *buf;
-	uint32_t frame_size, tot_size, rc;
+	struct ion_handle *handle = NULL;
+	size_t frame_size, tot_size, len;
+	unsigned long paddr;
+	int rc;
 
-	if (c_data->vid_vp_action.bufNR.vaddr) {
+	if (c_data->vid_vp_action.bufNR.nr_handle) {
 		pr_err("NR buffer has already been created");
 		return -ENOEXEC;
 	}
-	buf = &c_data->vid_vp_action.bufNR;
-	if (!buf)
-		return -ENOMEM;
 
 	frame_size = c_data->vp_in_fmt.width * c_data->vp_in_fmt.height;
 	if (c_data->vp_in_fmt.pixfmt == V4L2_PIX_FMT_NV16)
@@ -479,19 +505,30 @@
 	else
 		tot_size = frame_size / 2 * 3;
 
-	buf->vaddr = kzalloc(tot_size, GFP_KERNEL);
-	if (!buf->vaddr)
+	handle = ion_alloc(dev->ion_client, tot_size, SZ_4K,
+			ION_HEAP(ION_CP_MM_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: ion_alloc failed\n", __func__);
 		return -ENOMEM;
+	}
 
+	rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+	if (rc < 0) {
+		pr_err("%s: ion_phys failed\n", __func__);
+		ion_free(dev->ion_client, handle);
+		return rc;
+	}
+
+	c_data->vid_vp_action.bufNR.nr_handle = handle;
 	update_nr_value(c_data);
 
-	buf->paddr = virt_to_phys(buf->vaddr);
+	c_data->vid_vp_action.bufNR.paddr = paddr;
 	rc = readl_relaxed(VCAP_VP_NR_CONFIG2);
-	rc |= 0x02D00001;
+	rc |= (((c_data->vp_out_fmt.width / 16) << 20) | 0x1);
 	writel_relaxed(rc, VCAP_VP_NR_CONFIG2);
-	writel_relaxed(buf->paddr, VCAP_VP_NR_T2_Y_BASE_ADDR);
-	writel_relaxed(buf->paddr + frame_size, VCAP_VP_NR_T2_C_BASE_ADDR);
-	buf->nr_pos = NRT2_BUF;
+	writel_relaxed(paddr, VCAP_VP_NR_T2_Y_BASE_ADDR);
+	writel_relaxed(paddr + frame_size, VCAP_VP_NR_T2_C_BASE_ADDR);
+	c_data->vid_vp_action.bufNR.nr_pos = NRT2_BUF;
 	return 0;
 }
 
@@ -501,20 +538,19 @@
 	struct nr_buffer *buf;
 	uint32_t rc;
 
-	if (!c_data->vid_vp_action.bufNR.vaddr) {
+	if (!c_data->vid_vp_action.bufNR.nr_handle) {
 		pr_err("NR buffer has not been created");
 		return;
 	}
-
 	buf = &c_data->vid_vp_action.bufNR;
 
 	rc = readl_relaxed(VCAP_VP_NR_CONFIG2);
-	rc &= !(0x02D00001);
+	rc &= !(0x0FF00001);
 	writel_relaxed(rc, VCAP_VP_NR_CONFIG2);
 
-	kfree(buf->vaddr);
+	ion_free(dev->ion_client, buf->nr_handle);
+	buf->nr_handle = NULL;
 	buf->paddr = 0;
-	buf->vaddr = NULL;
 	return;
 }
 
@@ -592,18 +628,26 @@
 {
 	struct vcap_dev *dev = c_data->dev;
 	unsigned int width, height;
+	struct ion_handle *handle = NULL;
 	unsigned long paddr;
-	void *temp;
+	size_t len;
 	uint32_t reg;
 	int rc = 0;
 
 	dprintk(2, "%s: Start VP dummy event\n", __func__);
-	temp = kzalloc(0x1200, GFP_KERNEL);
-	if (!temp) {
-		pr_err("%s: Failed to alloc mem", __func__);
+	handle = ion_alloc(dev->ion_client, 0x1200, SZ_4K,
+			ION_HEAP(ION_CP_MM_HEAP_ID));
+	if (IS_ERR_OR_NULL(handle)) {
+		pr_err("%s: ion_alloc failed\n", __func__);
 		return -ENOMEM;
 	}
-	paddr = virt_to_phys(temp);
+
+	rc = ion_phys(dev->ion_client, handle, &paddr, &len);
+	if (rc < 0) {
+		pr_err("%s: ion_phys failed\n", __func__);
+		ion_free(dev->ion_client, handle);
+		return rc;
+	}
 
 	width = c_data->vp_out_fmt.width;
 	height = c_data->vp_out_fmt.height;
@@ -626,7 +670,7 @@
 
 	writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
 	writel_iowmb(0x00000000, VCAP_VP_CTRL);
-	writel_iowmb(0x00030000, VCAP_VP_CTRL);
+	writel_iowmb(0x00010000, VCAP_VP_CTRL);
 
 	enable_irq(dev->vpirq->start);
 	rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
@@ -650,7 +694,7 @@
 
 	c_data->vp_out_fmt.width = width;
 	c_data->vp_out_fmt.height = height;
-	kfree(temp);
+	ion_free(dev->ion_client, handle);
 
 	dprintk(2, "%s: Exit VP dummy event\n", __func__);
 	return rc;
@@ -748,10 +792,10 @@
 	writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
 #ifdef TOP_FIELD_FIX
 	writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
-	writel_iowmb(0x00030000 | vp_act->top_field << 0, VCAP_VP_CTRL);
+	writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
 #else
 	writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
-	writel_iowmb(0x00030000 | top_field, VCAP_VP_CTRL);
+	writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
 #endif
 	atomic_set(&c_data->dev->vp_enabled, 1);
 	enable_irq(dev->vpirq->start);
@@ -795,10 +839,10 @@
 	writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
 #ifdef TOP_FIELD_FIX
 	writel_iowmb(0x00000000 | vp_act->top_field << 0, VCAP_VP_CTRL);
-	writel_iowmb(0x00030000 | vp_act->top_field << 0, VCAP_VP_CTRL);
+	writel_iowmb(0x00010000 | vp_act->top_field << 0, VCAP_VP_CTRL);
 #else
 	writel_iowmb(0x00000000 | top_field, VCAP_VP_CTRL);
-	writel_iowmb(0x00030000 | top_field, VCAP_VP_CTRL);
+	writel_iowmb(0x00010000 | top_field, VCAP_VP_CTRL);
 #endif
 
 	atomic_set(&c_data->dev->vp_enabled, 1);
diff --git a/drivers/mfd/wcd9xxx-core.c b/drivers/mfd/wcd9xxx-core.c
index 6d82e11..05707fd 100644
--- a/drivers/mfd/wcd9xxx-core.c
+++ b/drivers/mfd/wcd9xxx-core.c
@@ -12,6 +12,7 @@
 
 #include <linux/kernel.h>
 #include <linux/module.h>
+#include <linux/of_gpio.h>
 #include <linux/slab.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/wcd9xxx/wcd9xxx-slimslave.h>
@@ -320,10 +321,12 @@
 
 	wcd9xxx_bring_up(wcd9xxx);
 
-	ret = wcd9xxx_irq_init(wcd9xxx);
-	if (ret) {
-		pr_err("IRQ initialization failed\n");
-		goto err;
+	if (wcd9xxx->irq != -1) {
+		ret = wcd9xxx_irq_init(wcd9xxx);
+		if (ret) {
+			pr_err("IRQ initialization failed\n");
+			goto err;
+		}
 	}
 
 	wcd9xxx->idbyte_0 = wcd9xxx_reg_read(wcd9xxx, WCD9XXX_A_CHIP_ID_BYTE_0);
@@ -497,10 +500,15 @@
 		goto err;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++)
-		wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
+	wcd9xxx->num_of_supplies = 0;
+	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+		if (pdata->regulator[i].name) {
+			wcd9xxx->supplies[i].supply = pdata->regulator[i].name;
+			wcd9xxx->num_of_supplies++;
+		}
+	}
 
-	ret = regulator_bulk_get(wcd9xxx->dev, ARRAY_SIZE(pdata->regulator),
+	ret = regulator_bulk_get(wcd9xxx->dev, wcd9xxx->num_of_supplies,
 				 wcd9xxx->supplies);
 	if (ret != 0) {
 		dev_err(wcd9xxx->dev, "Failed to get supplies: err = %d\n",
@@ -508,7 +516,7 @@
 		goto err_supplies;
 	}
 
-	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+	for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
 		ret = regulator_set_voltage(wcd9xxx->supplies[i].consumer,
 			pdata->regulator[i].min_uV, pdata->regulator[i].max_uV);
 		if (ret) {
@@ -528,7 +536,7 @@
 		}
 	}
 
-	ret = regulator_bulk_enable(ARRAY_SIZE(pdata->regulator),
+	ret = regulator_bulk_enable(wcd9xxx->num_of_supplies,
 				    wcd9xxx->supplies);
 	if (ret != 0) {
 		dev_err(wcd9xxx->dev, "Failed to enable supplies: err = %d\n",
@@ -538,13 +546,13 @@
 	return ret;
 
 err_configure:
-	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+	for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
 		regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
 			pdata->regulator[i].max_uV);
 		regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
 	}
 err_get:
-	regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+	regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
 err_supplies:
 	kfree(wcd9xxx->supplies);
 err:
@@ -556,14 +564,14 @@
 {
 	int i;
 
-	regulator_bulk_disable(ARRAY_SIZE(pdata->regulator),
+	regulator_bulk_disable(wcd9xxx->num_of_supplies,
 				    wcd9xxx->supplies);
-	for (i = 0; i < ARRAY_SIZE(pdata->regulator); i++) {
+	for (i = 0; i < wcd9xxx->num_of_supplies; i++) {
 		regulator_set_voltage(wcd9xxx->supplies[i].consumer, 0,
 			pdata->regulator[i].max_uV);
 		regulator_set_optimum_mode(wcd9xxx->supplies[i].consumer, 0);
 	}
-	regulator_bulk_free(ARRAY_SIZE(pdata->regulator), wcd9xxx->supplies);
+	regulator_bulk_free(wcd9xxx->num_of_supplies, wcd9xxx->supplies);
 	kfree(wcd9xxx->supplies);
 }
 
@@ -792,6 +800,252 @@
 	return 0;
 }
 
+#define CODEC_DT_MAX_PROP_SIZE   40
+static int wcd9xxx_dt_parse_vreg_info(struct device *dev,
+	struct wcd9xxx_regulator *vreg, const char *vreg_name)
+{
+	int len, ret = 0;
+	const __be32 *prop;
+	char prop_name[CODEC_DT_MAX_PROP_SIZE];
+	struct device_node *regnode = NULL;
+	u32 prop_val;
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE, "%s-supply",
+		vreg_name);
+	regnode = of_parse_phandle(dev->of_node, prop_name, 0);
+
+	if (!regnode) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+				prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+	vreg->name = vreg_name;
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+		"qcom,%s-voltage", vreg_name);
+	prop = of_get_property(dev->of_node, prop_name, &len);
+
+	if (!prop || (len != (2 * sizeof(__be32)))) {
+		dev_err(dev, "%s %s property\n",
+				prop ? "invalid format" : "no", prop_name);
+		return -ENODEV;
+	} else {
+		vreg->min_uV = be32_to_cpup(&prop[0]);
+		vreg->max_uV = be32_to_cpup(&prop[1]);
+	}
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,%s-current", vreg_name);
+
+	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+				prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+	vreg->optimum_uA = prop_val;
+
+	dev_info(dev, "%s: vol=[%d %d]uV, curr=[%d]uA\n", vreg->name,
+		vreg->min_uV, vreg->max_uV, vreg->optimum_uA);
+	return 0;
+}
+
+static int wcd9xxx_dt_parse_micbias_info(struct device *dev,
+	struct wcd9xxx_micbias_setting *micbias)
+{
+	int ret = 0;
+	char prop_name[CODEC_DT_MAX_PROP_SIZE];
+	u32 prop_val;
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias-ldoh-v");
+	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+	micbias->ldoh_v  =  (u8)prop_val;
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias-cfilt1-mv");
+	ret = of_property_read_u32(dev->of_node, prop_name,
+				   &micbias->cfilt1_mv);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias-cfilt2-mv");
+	ret = of_property_read_u32(dev->of_node, prop_name,
+				   &micbias->cfilt2_mv);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias-cfilt3-mv");
+	ret = of_property_read_u32(dev->of_node, prop_name,
+				   &micbias->cfilt3_mv);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias1-cfilt-sel");
+	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+	micbias->bias1_cfilt_sel = (u8)prop_val;
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias2-cfilt-sel");
+	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+	micbias->bias2_cfilt_sel = (u8)prop_val;
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias3-cfilt-sel");
+	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+	micbias->bias3_cfilt_sel = (u8)prop_val;
+
+	snprintf(prop_name, CODEC_DT_MAX_PROP_SIZE,
+			"qcom,cdc-micbias4-cfilt-sel");
+	ret = of_property_read_u32(dev->of_node, prop_name, &prop_val);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			prop_name, dev->of_node->full_name);
+		return -ENODEV;
+	}
+	micbias->bias4_cfilt_sel = (u8)prop_val;
+
+	dev_dbg(dev, "ldoh_v  %u cfilt1_mv %u cfilt2_mv %u cfilt3_mv %u",
+		(u32)micbias->ldoh_v, (u32)micbias->cfilt1_mv,
+		(u32)micbias->cfilt2_mv, (u32)micbias->cfilt3_mv);
+
+	dev_dbg(dev, "bias1_cfilt_sel %u bias2_cfilt_sel %u\n",
+		(u32)micbias->bias1_cfilt_sel, (u32)micbias->bias2_cfilt_sel);
+
+	dev_dbg(dev, "bias3_cfilt_sel %u bias4_cfilt_sel %u\n",
+		(u32)micbias->bias3_cfilt_sel, (u32)micbias->bias4_cfilt_sel);
+
+	return 0;
+}
+
+static int wcd9xxx_dt_parse_slim_interface_dev_info(struct device *dev,
+						struct slim_device *slim_ifd)
+{
+	int ret = 0;
+	struct property *prop;
+
+	ret = of_property_read_string(dev->of_node, "qcom,cdc-slim-ifd",
+				      &slim_ifd->name);
+	if (ret) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			"qcom,cdc-slim-ifd-dev", dev->of_node->full_name);
+		return -ENODEV;
+	}
+	prop = of_find_property(dev->of_node,
+			"qcom,cdc-slim-ifd-elemental-addr", NULL);
+	if (!prop) {
+		dev_err(dev, "Looking up %s property in node %s failed",
+			"qcom,cdc-slim-ifd-elemental-addr",
+			dev->of_node->full_name);
+		return -ENODEV;
+	} else if (prop->length != 6) {
+		dev_err(dev, "invalid codec slim ifd addr. addr length = %d\n",
+			      prop->length);
+		return -ENODEV;
+	}
+	memcpy(slim_ifd->e_addr, prop->value, 6);
+
+	return 0;
+}
+
+static char *taiko_supplies[] = {
+	"cdc-vdd-buck", "cdc-vdd-tx-h", "cdc-vdd-rx-h", "cdc-vddpx-1",
+	"cdc-vdd-a-1p2v", "cdc-vddcx-1", "cdc-vddcx-2",
+};
+
+static struct wcd9xxx_pdata *wcd9xxx_populate_dt_pdata(struct device *dev)
+{
+	struct wcd9xxx_pdata *pdata;
+	int ret, i;
+	char **codec_supplies;
+	u32 num_of_supplies = 0;
+
+	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+	if (!pdata) {
+		dev_err(dev,
+			"could not allocate memory for platform data\n");
+		return NULL;
+	}
+
+	if (!strcmp(dev_name(dev), "taiko-slim-pgd")) {
+		codec_supplies = taiko_supplies;
+		num_of_supplies = ARRAY_SIZE(taiko_supplies);
+	} else {
+		dev_err(dev, "%s unsupported device %s\n",
+				__func__, dev_name(dev));
+		goto err;
+	}
+
+	if (num_of_supplies > ARRAY_SIZE(pdata->regulator)) {
+		dev_err(dev, "%s: Num of supplies %u > max supported %u\n",
+		      __func__, num_of_supplies, ARRAY_SIZE(pdata->regulator));
+
+		goto err;
+	}
+
+	for (i = 0; i < num_of_supplies; i++) {
+		ret = wcd9xxx_dt_parse_vreg_info(dev, &pdata->regulator[i],
+			codec_supplies[i]);
+		if (ret)
+			goto err;
+	}
+
+	ret = wcd9xxx_dt_parse_micbias_info(dev, &pdata->micbias);
+	if (ret)
+		goto err;
+
+	pdata->reset_gpio = of_get_named_gpio(dev->of_node,
+				"qcom,cdc-reset-gpio", 0);
+	if (pdata->reset_gpio < 0) {
+		dev_err(dev, "Looking up %s property in node %s failed %d\n",
+			"qcom, cdc-reset-gpio", dev->of_node->full_name,
+			pdata->reset_gpio);
+		goto err;
+	}
+	pdata->irq = -1;
+
+	ret = wcd9xxx_dt_parse_slim_interface_dev_info(dev,
+			&pdata->slimbus_slave_device);
+	if (ret)
+		goto err;
+	return pdata;
+err:
+	devm_kfree(dev, pdata);
+	return NULL;
+}
+
 static int wcd9xxx_slim_probe(struct slim_device *slim)
 {
 	struct wcd9xxx *wcd9xxx;
@@ -799,8 +1053,15 @@
 	int ret = 0;
 	int sgla_retry_cnt;
 
-	dev_info(&slim->dev, "Initialized slim device %s\n", slim->name);
-	pdata = slim->dev.platform_data;
+	if (slim->dev.of_node) {
+		dev_info(&slim->dev, "Platform data from device tree\n");
+		pdata = wcd9xxx_populate_dt_pdata(&slim->dev);
+		slim->dev.platform_data = pdata;
+
+	} else {
+		dev_info(&slim->dev, "Platform data from board file\n");
+		pdata = slim->dev.platform_data;
+	}
 
 	if (!pdata) {
 		dev_err(&slim->dev, "Error, no platform data\n");
@@ -1103,7 +1364,7 @@
 };
 
 static const struct slim_device_id taiko_slimtest_id[] = {
-	{"taiko-slim", 0},
+	{"taiko-slim-pgd", 0},
 	{}
 };
 
diff --git a/drivers/mfd/wcd9xxx-slimslave.c b/drivers/mfd/wcd9xxx-slimslave.c
index 5f839a8..71c68ac 100644
--- a/drivers/mfd/wcd9xxx-slimslave.c
+++ b/drivers/mfd/wcd9xxx-slimslave.c
@@ -555,18 +555,18 @@
 			 __func__, i, ch_num[i], idx, i, sph[i], grph);
 	}
 
-	/* slim_disconnect_port */
-	ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
-	if (ret < 0) {
-		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
-		       __func__, ret);
-	}
 	/* slim_control_ch (REMOVE) */
 	ret = slim_control_ch(wcd9xxx->slim, grph, SLIM_CH_REMOVE, true);
 	if (ret < 0) {
 		pr_err("%s: slim_control_ch failed ret[%d]\n", __func__, ret);
 		goto err;
 	}
+	/* slim_disconnect_port */
+	ret = slim_disconnect_ports(wcd9xxx->slim, sph, ch_cnt);
+	if (ret < 0) {
+		pr_err("%s: slim_disconnect_ports failed ret[%d]\n",
+			 __func__, ret);
+	}
 	for (i = 0; i < ch_cnt; i++) {
 		idx = (ch_num[i] - BASE_CH_NUM - sh_ch.rx_port_start_offset);
 		rx[idx].grph = 0;
diff --git a/drivers/regulator/qpnp-regulator.c b/drivers/regulator/qpnp-regulator.c
index 8d592fb..0e836c7 100644
--- a/drivers/regulator/qpnp-regulator.c
+++ b/drivers/regulator/qpnp-regulator.c
@@ -268,8 +268,8 @@
 };
 
 static struct qpnp_voltage_range ftsmps_ranges[] = {
-	VOLTAGE_RANGE(0,   80000,  350000, 1355000,  5000),
-	VOLTAGE_RANGE(1,  160000, 1360000, 2710000, 10000),
+	VOLTAGE_RANGE(0,       0,  350000, 1275000,  5000),
+	VOLTAGE_RANGE(1,       0, 1280000, 2040000, 10000),
 };
 
 static struct qpnp_voltage_range boost_ranges[] = {
@@ -982,16 +982,26 @@
 static int qpnp_regulator_match(struct qpnp_regulator *vreg)
 {
 	const struct qpnp_regulator_mapping *mapping;
+	struct device_node *node = vreg->spmi_dev->dev.of_node;
 	int rc, i;
 	u8 raw_type[2], type, subtype;
+	u32 type_reg[2];
 
-	rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_TYPE, raw_type, 2);
-	if (rc) {
-		vreg_err(vreg, "could not read type register, rc=%d\n", rc);
-		return rc;
+	rc = of_property_read_u32_array(node, "qcom,force-type",
+								type_reg, 2);
+	if (!rc) {
+		type = type_reg[0];
+		subtype = type_reg[1];
+	} else {
+		rc = qpnp_vreg_read(vreg, QPNP_COMMON_REG_TYPE, raw_type, 2);
+		if (rc) {
+			vreg_err(vreg,
+				"could not read type register, rc=%d\n", rc);
+			return rc;
+		}
+		type = raw_type[0];
+		subtype = raw_type[1];
 	}
-	type = raw_type[0];
-	subtype = raw_type[1];
 
 	rc = -ENODEV;
 	for (i = 0; i < ARRAY_SIZE(supported_regulators); i++) {
diff --git a/drivers/thermal/Kconfig b/drivers/thermal/Kconfig
index b2d2f74..d082273 100644
--- a/drivers/thermal/Kconfig
+++ b/drivers/thermal/Kconfig
@@ -75,7 +75,7 @@
 
 config THERMAL_MONITOR
 	bool "Monitor thermal state and limit CPU Frequency"
-	depends on THERMAL_TSENS8960
+	depends on THERMAL_TSENS8960 || THERMAL_TSENS8974
 	depends on CPU_FREQ_MSM
 	default n
 	help
diff --git a/drivers/tty/n_smux.c b/drivers/tty/n_smux.c
index 32e52d0..1385e08 100644
--- a/drivers/tty/n_smux.c
+++ b/drivers/tty/n_smux.c
@@ -274,6 +274,7 @@
 	struct mutex mutex_lha0;
 
 	int is_initialized;
+	int platform_devs_registered;
 	int in_reset;
 	int ld_open_count;
 	struct tty_struct *tty;
@@ -3377,14 +3378,18 @@
 		/* re-register platform devices */
 		SMUX_DBG("%s: ssr - after power-up\n", __func__);
 		mutex_lock(&smux.mutex_lha0);
-		for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
-			SMUX_DBG("%s: register pdev '%s'\n",
+		if (smux.ld_open_count > 0
+				&& !smux.platform_devs_registered) {
+			for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+				SMUX_DBG("%s: register pdev '%s'\n",
 					__func__, smux_devs[i].name);
-			smux_devs[i].dev.release = smux_pdev_release;
-			tmp = platform_device_register(&smux_devs[i]);
-			if (tmp)
-				pr_err("%s: error %d registering device %s\n",
+				smux_devs[i].dev.release = smux_pdev_release;
+				tmp = platform_device_register(&smux_devs[i]);
+				if (tmp)
+					pr_err("%s: error %d registering device %s\n",
 					   __func__, tmp, smux_devs[i].name);
+			}
+			smux.platform_devs_registered = 1;
 		}
 		mutex_unlock(&smux.mutex_lha0);
 		return NOTIFY_DONE;
@@ -3396,30 +3401,34 @@
 	/* Cleanup channels */
 	smux_flush_workqueues();
 	mutex_lock(&smux.mutex_lha0);
-	smux_lch_purge();
-	if (smux.tty)
-		tty_driver_flush_buffer(smux.tty);
+	if (smux.ld_open_count > 0) {
+		smux_lch_purge();
+		if (smux.tty)
+			tty_driver_flush_buffer(smux.tty);
 
-	/* Unregister platform devices */
-	for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
-		SMUX_DBG("%s: unregister pdev '%s'\n",
-				__func__, smux_devs[i].name);
-		platform_device_unregister(&smux_devs[i]);
+		/* Unregister platform devices */
+		if (smux.platform_devs_registered) {
+			for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+				SMUX_DBG("%s: unregister pdev '%s'\n",
+						__func__, smux_devs[i].name);
+				platform_device_unregister(&smux_devs[i]);
+			}
+			smux.platform_devs_registered = 0;
+		}
+
+		/* Power-down UART */
+		spin_lock_irqsave(&smux.tx_lock_lha2, flags);
+		if (smux.power_state != SMUX_PWR_OFF) {
+			SMUX_PWR("%s: SSR - turning off UART\n", __func__);
+			smux.power_state = SMUX_PWR_OFF;
+			power_off_uart = 1;
+		}
+		smux.powerdown_enabled = 0;
+		spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
+
+		if (power_off_uart)
+			smux_uart_power_off_atomic();
 	}
-
-	/* Power-down UART */
-	spin_lock_irqsave(&smux.tx_lock_lha2, flags);
-	if (smux.power_state != SMUX_PWR_OFF) {
-		SMUX_PWR("%s: SSR - turning off UART\n", __func__);
-		smux.power_state = SMUX_PWR_OFF;
-		power_off_uart = 1;
-	}
-	smux.powerdown_enabled = 0;
-	spin_unlock_irqrestore(&smux.tx_lock_lha2, flags);
-
-	if (power_off_uart)
-		smux_uart_power_off_atomic();
-
 	smux.tx_activity_flag = 0;
 	smux.rx_activity_flag = 0;
 	smux.rx_state = SMUX_RX_IDLE;
@@ -3493,6 +3502,7 @@
 			pr_err("%s: error %d registering device %s\n",
 				   __func__, tmp, smux_devs[i].name);
 	}
+	smux.platform_devs_registered = 1;
 	mutex_unlock(&smux.mutex_lha0);
 	return 0;
 }
@@ -3519,10 +3529,13 @@
 	smux_lch_purge();
 
 	/* Unregister platform devices */
-	for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
-		SMUX_DBG("%s: unregister pdev '%s'\n",
-				__func__, smux_devs[i].name);
-		platform_device_unregister(&smux_devs[i]);
+	if (smux.platform_devs_registered) {
+		for (i = 0; i < ARRAY_SIZE(smux_devs); ++i) {
+			SMUX_DBG("%s: unregister pdev '%s'\n",
+					__func__, smux_devs[i].name);
+			platform_device_unregister(&smux_devs[i]);
+		}
+		smux.platform_devs_registered = 0;
 	}
 
 	/* Schedule UART power-up if it's down */
@@ -3668,6 +3681,7 @@
 	smux.ld_open_count = 0;
 	smux.in_reset = 0;
 	smux.is_initialized = 1;
+	smux.platform_devs_registered = 0;
 	smux_byte_loopback = 0;
 
 	spin_lock_init(&smux.tx_lock_lha2);
diff --git a/drivers/usb/gadget/f_rmnet.c b/drivers/usb/gadget/f_rmnet.c
index 414a7b9..1d0b6d4 100644
--- a/drivers/usb/gadget/f_rmnet.c
+++ b/drivers/usb/gadget/f_rmnet.c
@@ -607,6 +607,7 @@
 	struct usb_cdc_notification	*event;
 	unsigned long			flags;
 	int				ret;
+	struct rmnet_ctrl_pkt	*cpkt;
 
 	pr_debug("%s:dev:%p portno#%d\n", __func__, dev, dev->port_num);
 
@@ -633,6 +634,14 @@
 	ret = usb_ep_queue(dev->notify, dev->notify_req, GFP_ATOMIC);
 	if (ret) {
 		atomic_dec(&dev->notify_count);
+		spin_lock_irqsave(&dev->lock, flags);
+		cpkt = list_first_entry(&dev->cpkt_resp_q,
+					struct rmnet_ctrl_pkt, list);
+		if (cpkt) {
+			list_del(&cpkt->list);
+			rmnet_free_ctrl_pkt(cpkt);
+		}
+		spin_unlock_irqrestore(&dev->lock, flags);
 		pr_debug("ep enqueue error %d\n", ret);
 	}
 }
@@ -768,6 +777,8 @@
 {
 	struct f_rmnet *dev = req->context;
 	int status = req->status;
+	unsigned long		flags;
+	struct rmnet_ctrl_pkt	*cpkt;
 
 	pr_debug("%s: dev:%p port#%d\n", __func__, dev, dev->port_num);
 
@@ -790,6 +801,14 @@
 		status = usb_ep_queue(dev->notify, req, GFP_ATOMIC);
 		if (status) {
 			atomic_dec(&dev->notify_count);
+			spin_lock_irqsave(&dev->lock, flags);
+			cpkt = list_first_entry(&dev->cpkt_resp_q,
+						struct rmnet_ctrl_pkt, list);
+			if (cpkt) {
+				list_del(&cpkt->list);
+				rmnet_free_ctrl_pkt(cpkt);
+			}
+			spin_unlock_irqrestore(&dev->lock, flags);
 			pr_debug("ep enqueue error %d\n", status);
 		}
 		break;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 0e1267b..355990a 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -847,9 +847,13 @@
 
 	/* Ensure that above operation is completed before turning off clocks */
 	mb();
-	if (!motg->pdata->core_clk_always_on_workaround) {
+	/* Consider clocks on workaround flag only in case of bus suspend */
+	if (!(phy->state == OTG_STATE_B_PERIPHERAL &&
+		test_bit(A_BUS_SUSPEND, &motg->inputs)) ||
+	    !motg->pdata->core_clk_always_on_workaround) {
 		clk_disable_unprepare(motg->pclk);
 		clk_disable_unprepare(motg->core_clk);
+		motg->lpm_flags |= CLOCKS_DOWN;
 	}
 
 	/* usb phy no more require TCXO clock, hence vote for TCXO disable */
@@ -917,9 +921,10 @@
 		motg->lpm_flags &= ~XO_SHUTDOWN;
 	}
 
-	if (!motg->pdata->core_clk_always_on_workaround) {
+	if (motg->lpm_flags & CLOCKS_DOWN) {
 		clk_prepare_enable(motg->core_clk);
 		clk_prepare_enable(motg->pclk);
+		motg->lpm_flags &= ~CLOCKS_DOWN;
 	}
 
 	if (motg->lpm_flags & PHY_PWR_COLLAPSED) {
@@ -2726,10 +2731,14 @@
 		pr_debug("OTG IRQ: in LPM\n");
 		disable_irq_nosync(irq);
 		motg->async_int = 1;
-		if (atomic_read(&motg->pm_suspended))
+		if (atomic_read(&motg->pm_suspended)) {
 			motg->sm_work_pending = true;
-		else
+			if ((otg->phy->state == OTG_STATE_A_SUSPEND) ||
+				(otg->phy->state == OTG_STATE_A_WAIT_BCON))
+				set_bit(A_BUS_REQ, &motg->inputs);
+		} else {
 			pm_request_resume(otg->phy->dev);
+		}
 		return IRQ_HANDLED;
 	}
 
@@ -3388,7 +3397,7 @@
 
 static int __init msm_otg_probe(struct platform_device *pdev)
 {
-	int ret = 0;
+	int ret = 0, disable_lpm = 0;
 	struct resource *res;
 	struct msm_otg *motg;
 	struct usb_phy *phy;
@@ -3406,6 +3415,8 @@
 			dev_err(&pdev->dev, "devices setup failed\n");
 			return ret;
 		}
+		/* LPM not supported on targets using DT */
+		disable_lpm = 1;
 	} else if (!pdev->dev.platform_data) {
 		dev_err(&pdev->dev, "No platform data given. Bailing out\n");
 		return -ENODEV;
@@ -3661,7 +3672,8 @@
 
 	wake_lock(&motg->wlock);
 	pm_runtime_set_active(&pdev->dev);
-	pm_runtime_enable(&pdev->dev);
+	if (!disable_lpm)
+		pm_runtime_enable(&pdev->dev);
 
 	if (motg->pdata->bus_scale_table) {
 		motg->bus_perf_client =
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 46ef7b4..0976fc6 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1452,21 +1452,21 @@
 	len += ret;
 
 	if (len && (format & TOP_AND_BOTTOM))
-		ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+		ret = snprintf(buf + len, PAGE_SIZE - len, ":%s",
 			single_video_3d_format_2string(
 				format & TOP_AND_BOTTOM));
 	else
-		ret = snprintf(buf + len, PAGE_SIZE, "%s",
+		ret = snprintf(buf + len, PAGE_SIZE - len, "%s",
 			single_video_3d_format_2string(
 				format & TOP_AND_BOTTOM));
 	len += ret;
 
 	if (len && (format & SIDE_BY_SIDE_HALF))
-		ret = snprintf(buf + len, PAGE_SIZE, ":%s",
+		ret = snprintf(buf + len, PAGE_SIZE - len, ":%s",
 			single_video_3d_format_2string(
 				format & SIDE_BY_SIDE_HALF));
 	else
-		ret = snprintf(buf + len, PAGE_SIZE, "%s",
+		ret = snprintf(buf + len, PAGE_SIZE - len, "%s",
 			single_video_3d_format_2string(
 				format & SIDE_BY_SIDE_HALF));
 	len += ret;
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index ee73eea..d911b62 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -1510,10 +1510,13 @@
 
 #ifdef CONFIG_FB_MSM_NO_MDP_PIPE_CTRL
 
-static void mdp_clk_off(void)
+/*
+ * mdp_clk_disable_unprepare(void) called from thread context
+ */
+static void mdp_clk_disable_unprepare(void)
 {
 	mb();
-	vsync_clk_disable();
+	vsync_clk_disable_unprepare();
 
 	if (mdp_clk != NULL)
 		clk_disable_unprepare(mdp_clk);
@@ -1525,8 +1528,10 @@
 		clk_disable_unprepare(mdp_lut_clk);
 }
 
-
-static void mdp_clk_on(void)
+/*
+ * mdp_clk_prepare_enable(void) called from thread context
+ */
+static void mdp_clk_prepare_enable(void)
 {
 	if (mdp_clk != NULL)
 		clk_prepare_enable(mdp_clk);
@@ -1537,9 +1542,12 @@
 	if (mdp_lut_clk != NULL)
 		clk_prepare_enable(mdp_lut_clk);
 
-	vsync_clk_enable();
+	vsync_clk_prepare_enable();
 }
 
+/*
+ * mdp_clk_ctrl: called from thread context
+ */
 void mdp_clk_ctrl(int on)
 {
 	static int mdp_clk_cnt;
@@ -1547,13 +1555,13 @@
 	mutex_lock(&mdp_suspend_mutex);
 	if (on) {
 		if (mdp_clk_cnt == 0)
-			mdp_clk_on();
+			mdp_clk_prepare_enable();
 		mdp_clk_cnt++;
 	} else {
 		if (mdp_clk_cnt) {
 			mdp_clk_cnt--;
 			if (mdp_clk_cnt == 0)
-				mdp_clk_off();
+				mdp_clk_disable_unprepare();
 		}
 	}
 	mutex_unlock(&mdp_suspend_mutex);
@@ -2398,8 +2406,7 @@
 		if (!(mdp_pdata->cont_splash_enabled))
 			mdp4_hw_init();
 #else
-		if (!(mdp_pdata->cont_splash_enabled))
-			mdp_hw_init();
+		mdp_hw_init();
 #endif
 
 #ifdef CONFIG_FB_MSM_OVERLAY
@@ -2591,6 +2598,7 @@
 		else {
 			printk(KERN_ERR "Invalid Selection of destination panel\n");
 			rc = -ENODEV;
+			mdp_clk_ctrl(0);
 			goto mdp_probe_err;
 		}
 
@@ -2638,6 +2646,7 @@
 		else {
 			printk(KERN_ERR "Invalid Selection of destination panel\n");
 			rc = -ENODEV;
+			mdp_clk_ctrl(0);
 			goto mdp_probe_err;
 		}
 		INIT_WORK(&mfd->dma_update_worker,
@@ -2737,6 +2746,7 @@
 				pr_err("%s: writeback panel not supprted\n",
 					 __func__);
 				platform_device_put(msm_fb_dev);
+				mdp_clk_ctrl(0);
 				return -ENODEV;
 			}
 			pdata->on = mdp4_overlay_writeback_on;
diff --git a/drivers/video/msm/mdp.h b/drivers/video/msm/mdp.h
index 12bd1d4..76d06a0 100644
--- a/drivers/video/msm/mdp.h
+++ b/drivers/video/msm/mdp.h
@@ -831,8 +831,8 @@
 void mdp3_vsync_irq_disable(int intr, int term);
 
 #ifdef MDP_HW_VSYNC
-void vsync_clk_enable(void);
-void vsync_clk_disable(void);
+void vsync_clk_prepare_enable(void);
+void vsync_clk_disable_unprepare(void);
 void mdp_hw_vsync_clk_enable(struct msm_fb_data_type *mfd);
 void mdp_hw_vsync_clk_disable(struct msm_fb_data_type *mfd);
 void mdp_vsync_clk_disable(void);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 72e7c8f..767332a 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -665,24 +665,17 @@
 uint32 mdp4_rgb_igc_lut_cvt(uint32 ndx);
 void mdp4_vg_qseed_init(int);
 int mdp4_overlay_blt(struct fb_info *info, struct msmfb_overlay_blt *req);
-int mdp4_overlay_blt_offset(struct fb_info *info,
-					struct msmfb_overlay_blt *req);
-
 
 #ifdef CONFIG_FB_MSM_MIPI_DSI
-int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd);
-int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd);
+void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd);
+void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd);
 void mdp4_dsi_video_blt_start(struct msm_fb_data_type *mfd);
 void mdp4_dsi_video_blt_stop(struct msm_fb_data_type *mfd);
-void mdp4_dsi_overlay_blt(struct msm_fb_data_type *mfd,
-					struct msmfb_overlay_blt *req);
-int mdp4_dsi_overlay_blt_offset(struct msm_fb_data_type *mfd,
+void mdp4_dsi_cmd_overlay_blt(struct msm_fb_data_type *mfd,
 					struct msmfb_overlay_blt *req);
 
 void mdp4_dsi_video_overlay_blt(struct msm_fb_data_type *mfd,
 					struct msmfb_overlay_blt *req);
-int mdp4_dsi_video_overlay_blt_offset(struct msm_fb_data_type *mfd,
-					struct msmfb_overlay_blt *req);
 void mdp4_dsi_video_base_swap(int cndx, struct mdp4_overlay_pipe *pipe);
 
 #ifdef CONFIG_FB_MSM_MDP40
@@ -726,10 +719,9 @@
 	struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
 {
 }
-static inline int mdp4_dsi_video_overlay_blt_offset(
+static inline void mdp4_dsi_cmd_overlay_blt(
 	struct msm_fb_data_type *mfd, struct msmfb_overlay_blt *req)
 {
-	return -ENODEV;
 }
 static inline void mdp4_dsi_video_base_swap(int cndx,
 			struct mdp4_overlay_pipe *pipe)
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index ee4cb4e..9fe5214 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -154,7 +154,6 @@
 		pr_err("%s: Error, mixer=%d iommu fndx=%d\n",
 				__func__, mixer, flist->fndx);
 		mdp4_stat.iommu_drop++;
-		mutex_unlock(&iommu_mutex);
 		return;
 	}
 
@@ -476,14 +475,18 @@
 		dma2_cfg_reg |= DMA_PACK_PATTERN_RGB;
 
 
-	if (mfd->panel_info.bpp == 18) {
+	if ((mfd->panel_info.type == MIPI_CMD_PANEL) ||
+		(mfd->panel_info.type == MIPI_VIDEO_PANEL)) {
+		dma2_cfg_reg |= DMA_DSTC0G_8BITS |	/* 888 24BPP */
+		    DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
+	} else if (mfd->panel_info.bpp == 18) {
 		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 666 18BPP */
 		    DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
 	} else if (mfd->panel_info.bpp == 16) {
 		dma2_cfg_reg |= DMA_DSTC0G_6BITS |	/* 565 16BPP */
 		    DMA_DSTC1B_5BITS | DMA_DSTC2R_5BITS;
 	} else {
-		dma2_cfg_reg |= DMA_DSTC0G_8BITS |	/* 888 16BPP */
+		dma2_cfg_reg |= DMA_DSTC0G_8BITS |	/* 888 24BPP */
 		    DMA_DSTC1B_8BITS | DMA_DSTC2R_8BITS;
 	}
 
@@ -1663,6 +1666,12 @@
 
 	bspipe = ctrl->stage[mixer][MDP4_MIXER_STAGE_BASE];
 
+	/*
+	 * bspipe is clone here
+	 * get real pipe
+	 */
+	bspipe = mdp4_overlay_ndx2pipe(bspipe->pipe_ndx);
+
 	/* save original base layer */
 	ctrl->baselayer[mixer] = bspipe;
 
@@ -2091,17 +2100,18 @@
 	num = pipe->pipe_num;
 	ndx = pipe->pipe_ndx;
 	mixer = pipe->mixer_num;
-	iom = pipe->iommu;
 
 	mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
 
-	memset(pipe, 0, sizeof(*pipe));
+	iom = pipe->iommu;
 
+	memset(pipe, 0, sizeof(*pipe));
 	pipe->pipe_type = ptype;
 	pipe->pipe_num = num;
 	pipe->pipe_ndx = ndx;
 	pipe->mixer_num = mixer;
 	pipe->iommu = iom;
+
 }
 
 static int mdp4_overlay_validate_downscale(struct mdp_overlay *req,
@@ -2516,7 +2526,7 @@
 		return -EINTR;
 
 	if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
-		mdp4_dsi_overlay_blt(mfd, req);
+		mdp4_dsi_cmd_overlay_blt(mfd, req);
 	else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
 		mdp4_dsi_video_overlay_blt(mfd, req);
 	else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
@@ -2644,49 +2654,6 @@
 	}
 }
 
-static void mdp4_overlay_update_blt_mode(struct msm_fb_data_type *mfd)
-{
-	if (mfd->use_ov0_blt == mfd->ov0_blt_state)
-		return;
-
-	if (mfd->use_ov0_blt) {
-		if (mfd->panel_info.type == LCDC_PANEL ||
-		    mfd->panel_info.type == LVDS_PANEL)
-			mdp4_lcdc_overlay_blt_start(mfd);
-		else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
-			mdp4_dsi_video_blt_start(mfd);
-		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
-			mdp4_dsi_overlay_blt_start(mfd);
-		else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
-			mdp4_mddi_overlay_blt_start(mfd);
-	} else {
-		if (mfd->panel_info.type == LCDC_PANEL ||
-		    mfd->panel_info.type == LVDS_PANEL)
-			mdp4_lcdc_overlay_blt_stop(mfd);
-		else if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
-			mdp4_dsi_video_blt_stop(mfd);
-		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
-			mdp4_dsi_overlay_blt_stop(mfd);
-		else if (ctrl->panel_mode & MDP4_PANEL_MDDI)
-			mdp4_mddi_overlay_blt_stop(mfd);
-	}
-	mfd->ov0_blt_state = mfd->use_ov0_blt;
-}
-
-static void mdp4_overlay1_update_blt_mode(struct msm_fb_data_type *mfd)
-{
-	if (mfd->ov1_blt_state == mfd->use_ov1_blt)
-		return;
-	if (mfd->use_ov1_blt) {
-		mdp4_dtv_overlay_blt_start(mfd);
-		pr_debug("%s overlay1 writeback is enabled\n", __func__);
-	} else {
-		mdp4_dtv_overlay_blt_stop(mfd);
-		pr_debug("%s overlay1 writeback is disabled\n", __func__);
-	}
-	mfd->ov1_blt_state = mfd->use_ov1_blt;
-}
-
 static u32 mdp4_overlay_blt_enable(struct mdp_overlay *req,
 	struct msm_fb_data_type *mfd, uint32 perf_level)
 {
@@ -2914,12 +2881,10 @@
 		}
 
 		mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
-		mdp4_overlay_update_blt_mode(mfd);
 	} else {	/* mixer1, DTV, ATV */
 		if (ctrl->panel_mode & MDP4_PANEL_DTV) {
 			mdp4_overlay_dtv_unset(mfd, pipe);
 			mfd->use_ov1_blt &= ~(1 << (pipe->pipe_ndx-1));
-			mdp4_overlay1_update_blt_mode(mfd);
 		}
 	}
 
@@ -2950,16 +2915,22 @@
 
 int mdp4_overlay_vsync_ctrl(struct fb_info *info, int enable)
 {
+	int cmd;
+
+	if (enable)
+		cmd = 1;
+	else
+		cmd = 0;
+
 	if (!hdmi_prim_display && info->node == 0) {
 		if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO)
-			mdp4_dsi_video_vsync_ctrl(0, enable);
+			mdp4_dsi_video_vsync_ctrl(0, cmd);
 		else if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD)
-			mdp4_dsi_cmd_vsync_ctrl(0, enable);
+			mdp4_dsi_cmd_vsync_ctrl(0, cmd);
 		else if (ctrl->panel_mode & MDP4_PANEL_LCDC)
-			mdp4_lcdc_vsync_ctrl(0, enable);
-	} else if (hdmi_prim_display || info->node == 1) {
-		mdp4_dtv_vsync_ctrl(0, enable);
-	}
+			mdp4_lcdc_vsync_ctrl(0, cmd);
+	} else if (hdmi_prim_display || info->node == 1)
+		mdp4_dtv_vsync_ctrl(0, cmd);
 
 	return 0;
 }
@@ -3176,12 +3147,6 @@
 		}
 	}
 
-	if (mfd->use_ov0_blt)
-		mdp4_overlay_update_blt_mode(mfd);
-
-	if (mfd->use_ov1_blt)
-		mdp4_overlay1_update_blt_mode(mfd);
-
 	if (ctrl->panel_mode & MDP4_PANEL_MDDI)
 		goto mddi;
 
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 7998d8b..e1fa02e 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -39,7 +39,7 @@
 static int vsync_start_y_adjust = 4;
 
 #define MAX_CONTROLLER	1
-#define VSYNC_EXPIRE_TICK 2
+#define VSYNC_EXPIRE_TICK 4
 #define BACKLIGHT_MAX 4
 
 struct backlight {
@@ -54,24 +54,34 @@
 	int inited;
 	int update_ndx;
 	int expire_tick;
-	uint32 dmap_intr_tot;
+	int blt_wait;
+	u32 ov_koff;
+	u32 ov_done;
+	u32 dmap_koff;
+	u32 dmap_done;
 	uint32 rdptr_intr_tot;
 	uint32 rdptr_sirq_tot;
 	atomic_t suspend;
-	int dmap_wait_cnt;
 	int wait_vsync_cnt;
-	int commit_cnt;
+	int blt_change;
+	int blt_free;
+	int blt_end;
+	int fake_vsync;
 	struct mutex update_lock;
+	struct completion ov_comp;
 	struct completion dmap_comp;
 	struct completion vsync_comp;
-	spinlock_t dmap_spin_lock;
 	spinlock_t spin_lock;
+	struct msm_fb_data_type *mfd;
 	struct mdp4_overlay_pipe *base_pipe;
 	struct vsync_update vlist[2];
 	struct backlight blight;
-	int vsync_irq_enabled;
+	int vsync_enabled;
+	int clk_enabled;
+	int clk_control;
 	ktime_t vsync_time;
 	struct work_struct vsync_work;
+	struct work_struct clk_work;
 } vsync_ctrl_db[MAX_CONTROLLER];
 
 static void vsync_irq_enable(int intr, int term)
@@ -80,7 +90,6 @@
 
 	spin_lock_irqsave(&mdp_spin_lock, flag);
 	/* no need to clrear other interrupts for comamnd mode */
-	outp32(MDP_INTR_CLEAR, INTR_PRIMARY_RDPTR);
 	mdp_intr_mask |= intr;
 	outp32(MDP_INTR_ENABLE, mdp_intr_mask);
 	mdp_enable_irq(term);
@@ -161,30 +170,7 @@
 	return cnt;
 }
 
-void mdp4_blt_dmap_cfg(struct mdp4_overlay_pipe *pipe)
-{
-	uint32 off, addr;
-	int bpp;
-
-	if (pipe->ov_blt_addr == 0)
-		return;
-
-#ifdef BLT_RGB565
-	bpp = 2; /* overlay ouput is RGB565 */
-#else
-	bpp = 3; /* overlay ouput is RGB888 */
-#endif
-	off = 0;
-	if (pipe->blt_dmap_done & 0x01)
-		off = pipe->src_height * pipe->src_width * bpp;
-	addr = pipe->dma_blt_addr + off;
-
-	/* dmap */
-	MDP_OUTP(MDP_BASE + 0x90008, addr);
-}
-
-
-void mdp4_blt_overlay0_cfg(struct mdp4_overlay_pipe *pipe)
+static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe)
 {
 	uint32 off, addr;
 	int bpp;
@@ -199,7 +185,7 @@
 	bpp = 3; /* overlay ouput is RGB888 */
 #endif
 	off = 0;
-	if (pipe->blt_ov_done & 0x01)
+	if (pipe->ov_cnt & 0x01)
 		off = pipe->src_height * pipe->src_width * bpp;
 	addr = pipe->ov_blt_addr + off;
 	/* overlay 0 */
@@ -208,32 +194,91 @@
 	outpdw(overlay_base + 0x001c, addr);
 }
 
-static void vsync_commit_kickoff_dmap(struct mdp4_overlay_pipe *pipe)
+static void mdp4_dsi_cmd_blt_dmap_update(struct mdp4_overlay_pipe *pipe)
 {
-	if (mipi_dsi_ctrl_lock(1)) {
-		mdp4_stat.kickoff_dmap++;
-		pipe->blt_dmap_koff++;
-		vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
-		outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
-		mb();
-	}
+	uint32 off, addr;
+	int bpp;
+
+	if (pipe->ov_blt_addr == 0)
+		return;
+
+#ifdef BLT_RGB565
+	bpp = 2; /* overlay ouput is RGB565 */
+#else
+	bpp = 3; /* overlay ouput is RGB888 */
+#endif
+	off = 0;
+	if (pipe->dmap_cnt & 0x01)
+		off = pipe->src_height * pipe->src_width * bpp;
+	addr = pipe->dma_blt_addr + off;
+
+	/* dmap */
+	MDP_OUTP(MDP_BASE + 0x90008, addr);
 }
 
-static void vsync_commit_kickoff_ov0(struct mdp4_overlay_pipe *pipe, int blt)
+static void mdp4_dsi_cmd_wait4dmap(int cndx);
+static void mdp4_dsi_cmd_wait4ov(int cndx);
+
+static void mdp4_dsi_cmd_do_blt(struct msm_fb_data_type *mfd, int enable)
 {
-	int locked = 1;
+	unsigned long flags;
+	int cndx = 0;
+	struct vsycn_ctrl *vctrl;
+	struct mdp4_overlay_pipe *pipe;
+	int need_wait;
 
-	if (blt)
-		vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
-	else
-		locked = mipi_dsi_ctrl_lock(1);
+	vctrl = &vsync_ctrl_db[cndx];
+	pipe = vctrl->base_pipe;
 
-	if (locked) {
-		mdp4_stat.kickoff_ov0++;
-		pipe->blt_ov_koff++;
-		outpdw(MDP_BASE + 0x0004, 0); /* kickoff overlay engine */
-		mb();
+	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
+
+	if (mfd->ov0_wb_buf->write_addr == 0) {
+		pr_err("%s: no blt_base assigned\n", __func__);
+		return;
 	}
+
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
+	if (enable && pipe->ov_blt_addr == 0) {
+		vctrl->blt_change++;
+		if (vctrl->dmap_koff != vctrl->dmap_done) {
+			INIT_COMPLETION(vctrl->dmap_comp);
+			need_wait = 1;
+		}
+	} else if (enable == 0 && pipe->ov_blt_addr) {
+		vctrl->blt_change++;
+		if (vctrl->ov_koff != vctrl->dmap_done) {
+			INIT_COMPLETION(vctrl->dmap_comp);
+			need_wait = 1;
+		}
+	}
+	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+	if (need_wait)
+		mdp4_dsi_cmd_wait4dmap(0);
+
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
+	if (enable && pipe->ov_blt_addr == 0) {
+		pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
+		pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
+		pipe->ov_cnt = 0;
+		pipe->dmap_cnt = 0;
+		vctrl->ov_koff = vctrl->dmap_koff;
+		vctrl->ov_done = vctrl->dmap_done;
+		vctrl->blt_free = 0;
+		vctrl->blt_wait = 0;
+		vctrl->blt_end = 0;
+		mdp4_stat.blt_dsi_video++;
+	} else if (enable == 0 && pipe->ov_blt_addr) {
+		pipe->ov_blt_addr = 0;
+		pipe->dma_blt_addr =  0;
+		vctrl->blt_end = 1;
+		vctrl->blt_free = 4;	/* 4 commits to free wb buf */
+	}
+
+	pr_debug("%s: changed=%d enable=%d ov_blt_addr=%x\n", __func__,
+		vctrl->blt_change, enable, (int)pipe->ov_blt_addr);
+
+	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 }
 
 /*
@@ -266,95 +311,137 @@
 	pr_debug("%s: vndx=%d pipe_ndx=%d expire=%x pid=%d\n", __func__,
 		undx, pipe->pipe_ndx, vctrl->expire_tick, current->pid);
 
-	*pp = *pipe;	/* keep it */
+	*pp = *pipe;	/* clone it */
 	vp->update_cnt++;
 
-	if (vctrl->expire_tick == 0) {
-		mipi_dsi_clk_cfg(1);
-		mdp_clk_ctrl(1);
-		vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
-	}
-	vctrl->expire_tick = VSYNC_EXPIRE_TICK;
 	mutex_unlock(&vctrl->update_lock);
+	mdp4_stat.overlay_play[pipe->mixer_num]++;
 }
 
+static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe);
+
 int mdp4_dsi_cmd_pipe_commit(void)
 {
-
-	int  i, undx, cnt;
+	int  i, undx;
 	int mixer = 0;
 	struct vsycn_ctrl *vctrl;
 	struct vsync_update *vp;
 	struct mdp4_overlay_pipe *pipe;
 	unsigned long flags;
-	int diff;
+	int need_dmap_wait = 0;
+	int need_ov_wait = 0;
+	int cnt = 0;
 
 	vctrl = &vsync_ctrl_db[0];
+
 	mutex_lock(&vctrl->update_lock);
 	undx =  vctrl->update_ndx;
 	vp = &vctrl->vlist[undx];
 	pipe = vctrl->base_pipe;
 	mixer = pipe->mixer_num;
 
-	pr_debug("%s: vndx=%d cnt=%d expire=%x pid=%d\n", __func__,
-		undx, vp->update_cnt, vctrl->expire_tick, current->pid);
-
-	cnt = 0;
 	if (vp->update_cnt == 0) {
 		mutex_unlock(&vctrl->update_lock);
 		return cnt;
 	}
+
 	vctrl->update_ndx++;
 	vctrl->update_ndx &= 0x01;
-	vctrl->commit_cnt++;
-	vp->update_cnt = 0;	/* reset */
+	vp->update_cnt = 0;     /* reset */
+	if (vctrl->blt_free) {
+		vctrl->blt_free--;
+		if (vctrl->blt_free == 0)
+			mdp4_free_writeback_buf(vctrl->mfd, mixer);
+	}
 	mutex_unlock(&vctrl->update_lock);
 
+
 	mdp4_backlight_commit_level(vctrl);
 
 	/* free previous committed iommu back to pool */
 	mdp4_overlay_iommu_unmap_freelist(mixer);
 
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
+	if (pipe->ov_blt_addr) {
+		/* Blt */
+		if (vctrl->blt_wait)
+			need_dmap_wait = 1;
+		else if (vctrl->ov_koff != vctrl->ov_done) {
+			INIT_COMPLETION(vctrl->ov_comp);
+			need_ov_wait = 1;
+		}
+	} else {
+		/* direct out */
+		if (vctrl->dmap_koff != vctrl->dmap_done) {
+			INIT_COMPLETION(vctrl->dmap_comp);
+			pr_debug("%s: wait, ok=%d od=%d dk=%d dd=%d cpu=%d\n",
+			 __func__, vctrl->ov_koff, vctrl->ov_done,
+			vctrl->dmap_koff, vctrl->dmap_done, smp_processor_id());
+			need_dmap_wait = 1;
+		}
+	}
+	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+
+	if (need_dmap_wait) {
+		pr_debug("%s: wait4dmap\n", __func__);
+		mdp4_dsi_cmd_wait4dmap(0);
+	}
+
+	if (need_ov_wait) {
+		pr_debug("%s: wait4ov\n", __func__);
+		mdp4_dsi_cmd_wait4ov(0);
+	}
+
+	if (pipe->ov_blt_addr) {
+		if (vctrl->blt_end) {
+			vctrl->blt_end = 0;
+			pipe->ov_blt_addr = 0;
+			pipe->dma_blt_addr =  0;
+		}
+	}
+
+	if (vctrl->blt_change) {
+		mdp4_overlayproc_cfg(pipe);
+		mdp4_overlay_dmap_xy(pipe);
+		vctrl->blt_change = 0;
+	}
+
 	pipe = vp->plist;
 	for (i = 0; i < OVERLAY_PIPE_MAX; i++, pipe++) {
 		if (pipe->pipe_used) {
 			cnt++;
 			mdp4_overlay_vsync_commit(pipe);
 			/* free previous iommu to freelist
-			 * which will be freed at next
-			 * pipe_commit
-			 */
+			* which will be freed at next
+			* pipe_commit
+			*/
 			mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
 			pipe->pipe_used = 0; /* clear */
 		}
 	}
+
 	mdp4_mixer_stage_commit(mixer);
 
-
-	pr_debug("%s: intr=%d expire=%d cpu=%d\n", __func__,
-		vctrl->rdptr_intr_tot, vctrl->expire_tick, smp_processor_id());
-
-	spin_lock_irqsave(&vctrl->spin_lock, flags);
 	pipe = vctrl->base_pipe;
-	if (pipe->blt_changed) {
-		/* blt configurtion changed */
-		pipe->blt_changed = 0;
-		mdp4_overlayproc_cfg(pipe);
-		mdp4_overlay_dmap_xy(pipe);
-	}
-
+	spin_lock_irqsave(&vctrl->spin_lock, flags);
 	if (pipe->ov_blt_addr) {
-		diff = pipe->blt_ov_koff - pipe->blt_ov_done;
-		if (diff < 1) {
-			mdp4_blt_overlay0_cfg(pipe);
-			vsync_commit_kickoff_ov0(pipe, 1);
-		}
+		mdp4_dsi_cmd_blt_ov_update(pipe);
+		pipe->ov_cnt++;
+		vctrl->ov_koff++;
+		vsync_irq_enable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
 	} else {
-		vsync_commit_kickoff_ov0(pipe, 0);
+		vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+		vctrl->dmap_koff++;
 	}
-
+	pr_debug("%s: kickoff\n", __func__);
+	/* kickoff overlay engine */
+	mdp4_stat.kickoff_ov0++;
+	outpdw(MDP_BASE + 0x0004, 0);
+	mb(); /* make sure kickoff ececuted */
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 
+	mdp4_stat.overlay_commit[pipe->mixer_num]++;
+
 	return cnt;
 }
 
@@ -369,23 +456,15 @@
 
 	vctrl = &vsync_ctrl_db[cndx];
 
-	if (vctrl->vsync_irq_enabled == enable)
+	if (enable && vctrl->fake_vsync) {
+		vctrl->fake_vsync = 0;
+		schedule_work(&vctrl->vsync_work);
+	}
+
+	if (vctrl->vsync_enabled == enable)
 		return;
 
-	vctrl->vsync_irq_enabled = enable;
-
-	mutex_lock(&vctrl->update_lock);
-	if (enable) {
-		mipi_dsi_clk_cfg(1);
-		mdp_clk_ctrl(1);
-		vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
-	} else {
-		mipi_dsi_clk_cfg(0);
-		mdp_clk_ctrl(0);
-		vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
-		vctrl->expire_tick = 0;
-	}
-	mutex_unlock(&vctrl->update_lock);
+	vctrl->vsync_enabled = enable;
 }
 
 void mdp4_dsi_cmd_wait4vsync(int cndx, long long *vtime)
@@ -402,8 +481,10 @@
 	vctrl = &vsync_ctrl_db[cndx];
 	pipe = vctrl->base_pipe;
 
-	if (atomic_read(&vctrl->suspend) > 0)
+	if (atomic_read(&vctrl->suspend) > 0) {
+		*vtime = -1;
 		return;
+	}
 
 	spin_lock_irqsave(&vctrl->spin_lock, flags);
 	if (vctrl->wait_vsync_cnt == 0)
@@ -412,10 +493,44 @@
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 
 	wait_for_completion(&vctrl->vsync_comp);
+	mdp4_stat.wait4vsync0++;
 
 	*vtime = ktime_to_ns(vctrl->vsync_time);
 }
 
+static void mdp4_dsi_cmd_wait4dmap(int cndx)
+{
+	struct vsycn_ctrl *vctrl;
+
+	if (cndx >= MAX_CONTROLLER) {
+		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+		return;
+	}
+
+	vctrl = &vsync_ctrl_db[cndx];
+
+	if (atomic_read(&vctrl->suspend) > 0)
+		return;
+
+	wait_for_completion(&vctrl->dmap_comp);
+}
+
+static void mdp4_dsi_cmd_wait4ov(int cndx)
+{
+	struct vsycn_ctrl *vctrl;
+
+	if (cndx >= MAX_CONTROLLER) {
+		pr_err("%s: out or range: cndx=%d\n", __func__, cndx);
+		return;
+	}
+
+	vctrl = &vsync_ctrl_db[cndx];
+
+	if (atomic_read(&vctrl->suspend) > 0)
+		return;
+
+	wait_for_completion(&vctrl->ov_comp);
+}
 
 /*
  * primary_rdptr_isr:
@@ -427,10 +542,17 @@
 	struct vsycn_ctrl *vctrl;
 
 	vctrl = &vsync_ctrl_db[cndx];
-	pr_debug("%s: cpu=%d\n", __func__, smp_processor_id());
+	pr_debug("%s: ISR, cpu=%d\n", __func__, smp_processor_id());
 	vctrl->rdptr_intr_tot++;
 	vctrl->vsync_time = ktime_get();
 	schedule_work(&vctrl->vsync_work);
+
+	spin_lock(&vctrl->spin_lock);
+	if (vctrl->wait_vsync_cnt) {
+		complete(&vctrl->vsync_comp);
+		vctrl->wait_vsync_cnt = 0;
+	}
+	spin_unlock(&vctrl->spin_lock);
 }
 
 void mdp4_dmap_done_dsi_cmd(int cndx)
@@ -439,35 +561,34 @@
 	struct mdp4_overlay_pipe *pipe;
 	int diff;
 
-	vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
-
 	vctrl = &vsync_ctrl_db[cndx];
-	vctrl->dmap_intr_tot++;
 	pipe = vctrl->base_pipe;
 
-	if (pipe->ov_blt_addr == 0) {
-		mdp4_overlay_dma_commit(cndx);
-		return;
-	}
-
 	 /* blt enabled */
 	spin_lock(&vctrl->spin_lock);
-	pipe->blt_dmap_done++;
-	diff = pipe->blt_ov_done - pipe->blt_dmap_done;
-	spin_unlock(&vctrl->spin_lock);
-	pr_debug("%s: ov_done=%d dmap_done=%d ov_koff=%d dmap_koff=%d\n",
-			__func__, pipe->blt_ov_done, pipe->blt_dmap_done,
-				pipe->blt_ov_koff, pipe->blt_dmap_koff);
+	vsync_irq_disable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+	vctrl->dmap_done++;
+	diff = vctrl->ov_done - vctrl->dmap_done;
+	pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
+		__func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff,
+		vctrl->dmap_done, smp_processor_id());
+	complete_all(&vctrl->dmap_comp);
 	if (diff <= 0) {
-		if (pipe->blt_end) {
-			pipe->blt_end = 0;
-			pipe->ov_blt_addr = 0;
-			pipe->dma_blt_addr = 0;
-			pipe->blt_changed = 1;
-			pr_info("%s: BLT-END\n", __func__);
-		}
+		if (vctrl->blt_wait)
+			vctrl->blt_wait = 0;
+		spin_unlock(&vctrl->spin_lock);
+		return;
 	}
-	spin_unlock(&dsi_clk_lock);
+
+	/* kick dmap */
+	mdp4_dsi_cmd_blt_dmap_update(pipe);
+	pipe->dmap_cnt++;
+	mdp4_stat.kickoff_dmap++;
+	vctrl->dmap_koff++;
+	vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+	outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
+	mb(); /* make sure kickoff executed */
+	spin_unlock(&vctrl->spin_lock);
 }
 
 /*
@@ -479,30 +600,61 @@
 	struct mdp4_overlay_pipe *pipe;
 	int diff;
 
-	vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
-
 	vctrl = &vsync_ctrl_db[cndx];
 	pipe = vctrl->base_pipe;
 
 	spin_lock(&vctrl->spin_lock);
-	pipe->blt_ov_done++;
-	diff = pipe->blt_ov_done - pipe->blt_dmap_done;
-	spin_unlock(&vctrl->spin_lock);
+	vsync_irq_disable(INTR_OVERLAY0_DONE, MDP_OVERLAY0_TERM);
+	vctrl->ov_done++;
+	complete_all(&vctrl->ov_comp);
+	diff = vctrl->ov_done - vctrl->dmap_done;
 
-	pr_debug("%s: ov_done=%d dmap_done=%d ov_koff=%d dmap_koff=%d diff=%d\n",
-			__func__, pipe->blt_ov_done, pipe->blt_dmap_done,
-			pipe->blt_ov_koff, pipe->blt_dmap_koff, diff);
+	pr_debug("%s: ov_koff=%d ov_done=%d dmap_koff=%d dmap_done=%d cpu=%d\n",
+		__func__, vctrl->ov_koff, vctrl->ov_done, vctrl->dmap_koff,
+		vctrl->dmap_done, smp_processor_id());
 
 	if (pipe->ov_blt_addr == 0) {
 		/* blt disabled */
-		pr_debug("%s: NON-BLT\n", __func__);
+		spin_unlock(&vctrl->spin_lock);
 		return;
 	}
 
-	if (diff == 1) {
-		mdp4_blt_dmap_cfg(pipe);
-		vsync_commit_kickoff_dmap(pipe);
+	if (diff > 1) {
+		/*
+		 * two overlay_done and none dmap_done yet
+		 * let dmap_done kickoff dmap
+		 * and put pipe_commit to wait
+		 */
+		vctrl->blt_wait = 1;
+		pr_debug("%s: blt_wait set\n", __func__);
+		spin_unlock(&vctrl->spin_lock);
+		return;
 	}
+	mdp4_dsi_cmd_blt_dmap_update(pipe);
+	pipe->dmap_cnt++;
+	mdp4_stat.kickoff_dmap++;
+	vctrl->dmap_koff++;
+	vsync_irq_enable(INTR_DMA_P_DONE, MDP_DMAP_TERM);
+	outpdw(MDP_BASE + 0x000c, 0); /* kickoff dmap engine */
+	mb(); /* make sure kickoff executed */
+	spin_unlock(&vctrl->spin_lock);
+}
+
+static void clk_ctrl_work(struct work_struct *work)
+{
+	struct vsycn_ctrl *vctrl =
+		container_of(work, typeof(*vctrl), clk_work);
+
+	mutex_lock(&vctrl->update_lock);
+	if (vctrl->clk_control) {
+		if (vctrl->clk_enabled) {
+			mdp_clk_ctrl(0);
+			vctrl->clk_enabled = 0;
+			vctrl->fake_vsync = 1;
+		}
+	}
+
+	mutex_unlock(&vctrl->update_lock);
 }
 
 static void send_vsync_work(struct work_struct *work)
@@ -539,11 +691,12 @@
 	vctrl->blight.get = 0;
 	vctrl->blight.tot = 0;
 	mutex_init(&vctrl->update_lock);
-	init_completion(&vctrl->vsync_comp);
+	init_completion(&vctrl->ov_comp);
 	init_completion(&vctrl->dmap_comp);
+	init_completion(&vctrl->vsync_comp);
 	spin_lock_init(&vctrl->spin_lock);
-	spin_lock_init(&vctrl->dmap_spin_lock);
 	INIT_WORK(&vctrl->vsync_work, send_vsync_work);
+	INIT_WORK(&vctrl->clk_work, clk_ctrl_work);
 }
 
 void mdp4_primary_rdptr(void)
@@ -701,7 +854,7 @@
 	pipe->ov_blt_addr = 0;
 	pipe->dma_blt_addr = 0;
 
-	MDP_OUTP(MDP_BASE + 0x021c, 0x10); /* read pointer */
+	MDP_OUTP(MDP_BASE + 0x021c, 10); /* read pointer */
 
 	/*
 	 * configure dsi stream id
@@ -727,8 +880,6 @@
 
 	/* MDP cmd block disable */
 	mdp_clk_ctrl(0);
-
-	wmb();
 }
 
 /* 3D side by side */
@@ -751,7 +902,6 @@
 	if (pipe->pipe_used == 0 ||
 			pipe->mixer_stage != MDP4_MIXER_STAGE_BASE) {
 		pr_err("%s: NOT baselayer\n", __func__);
-		mutex_unlock(&mfd->dma->ov_mutex);
 		return;
 	}
 
@@ -809,78 +959,20 @@
 	mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
 }
 
-int mdp4_dsi_overlay_blt_start(struct msm_fb_data_type *mfd)
+void mdp4_dsi_cmd_blt_start(struct msm_fb_data_type *mfd)
 {
-	unsigned long flag;
-	int cndx = 0;
-	struct vsycn_ctrl *vctrl;
-	struct mdp4_overlay_pipe *pipe;
-
-	vctrl = &vsync_ctrl_db[cndx];
-	pipe = vctrl->base_pipe;
-
-	pr_debug("%s: blt_end=%d blt_addr=%x pid=%d\n",
-		 __func__, pipe->blt_end, (int)pipe->ov_blt_addr, current->pid);
-
-	mdp4_allocate_writeback_buf(mfd, MDP4_MIXER0);
-
-	if (mfd->ov0_wb_buf->write_addr == 0) {
-		pr_err("%s: no blt_base assigned\n", __func__);
-		return -EBUSY;
-	}
-
-	if (pipe->ov_blt_addr == 0) {
-		spin_lock_irqsave(&vctrl->spin_lock, flag);
-		pipe->blt_end = 0;
-		pipe->blt_cnt = 0;
-		pipe->blt_changed = 1;
-		pipe->ov_cnt = 0;
-		pipe->dmap_cnt = 0;
-		pipe->blt_ov_koff = 0;
-		pipe->blt_dmap_koff = 0;
-		pipe->blt_ov_done = 0;
-		pipe->blt_dmap_done = 0;
-		pipe->ov_blt_addr = mfd->ov0_wb_buf->write_addr;
-		pipe->dma_blt_addr = mfd->ov0_wb_buf->read_addr;
-		mdp4_stat.blt_dsi_cmd++;
-		spin_unlock_irqrestore(&vctrl->spin_lock, flag);
-		return 0;
-	}
-
-	return -EBUSY;
+	mdp4_dsi_cmd_do_blt(mfd, 1);
 }
 
-int mdp4_dsi_overlay_blt_stop(struct msm_fb_data_type *mfd)
+void mdp4_dsi_cmd_blt_stop(struct msm_fb_data_type *mfd)
 {
-	unsigned long flag;
-	int cndx = 0;
-	struct vsycn_ctrl *vctrl;
-	struct mdp4_overlay_pipe *pipe;
-
-	vctrl = &vsync_ctrl_db[cndx];
-	pipe = vctrl->base_pipe;
-
-	pr_info("%s: blt_end=%d blt_addr=%x pid=%d\n",
-		 __func__, pipe->blt_end, (int)pipe->ov_blt_addr, current->pid);
-
-	if ((pipe->blt_end == 0) && pipe->ov_blt_addr) {
-		spin_lock_irqsave(&vctrl->spin_lock, flag);
-		pipe->blt_end = 1;	/* mark as end */
-		spin_unlock_irqrestore(&vctrl->spin_lock, flag);
-		return 0;
-	}
-
-	return -EBUSY;
+	mdp4_dsi_cmd_do_blt(mfd, 0);
 }
 
-void mdp4_dsi_overlay_blt(struct msm_fb_data_type *mfd,
+void mdp4_dsi_cmd_overlay_blt(struct msm_fb_data_type *mfd,
 					struct msmfb_overlay_blt *req)
 {
-	if (req->enable)
-		mdp4_dsi_overlay_blt_start(mfd);
-	else if (req->enable == 0)
-		mdp4_dsi_overlay_blt_stop(mfd);
-
+	mdp4_dsi_cmd_do_blt(mfd, req->enable);
 }
 
 int mdp4_dsi_cmd_on(struct platform_device *pdev)
@@ -895,9 +987,11 @@
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
 	vctrl = &vsync_ctrl_db[cndx];
+	vctrl->mfd = mfd;
 	vctrl->dev = mfd->fbi->dev;
 
 	mdp_clk_ctrl(1);
+	vsync_irq_enable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
 
 	if (vctrl->base_pipe == NULL)
 		mdp4_overlay_update_dsi_cmd(mfd);
@@ -932,16 +1026,16 @@
 
 	atomic_set(&vctrl->suspend, 1);
 
-	/* make sure dsi clk is on so that
-	 * at panel_next_off() dsi panel can be shut off
-	 */
-	mipi_dsi_ahb_ctrl(1);
-	mipi_dsi_clk_enable();
+	mipi_dsi_cmd_backlight_tx(150);
 
 	mdp4_mixer_stage_down(pipe);
 	mdp4_overlay_pipe_free(pipe);
 	vctrl->base_pipe = NULL;
 
+	vctrl->fake_vsync = 1;
+
+	vsync_irq_disable(INTR_PRIMARY_RDPTR, MDP_PRIM_RDPTR_TERM);
+
 	pr_info("%s-:\n", __func__);
 
 	/*
@@ -984,12 +1078,14 @@
 	int cndx = 0;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	long long xx;
 
 	vctrl = &vsync_ctrl_db[cndx];
 
 	if (!mfd->panel_power_on)
 		return;
 
+	vctrl->clk_control = 0;
 	pipe = vctrl->base_pipe;
 	if (pipe == NULL) {
 		pr_err("%s: NO base pipe\n", __func__);
@@ -1001,5 +1097,19 @@
 		mdp4_overlay_setup_pipe_addr(mfd, pipe);
 		mdp4_dsi_cmd_pipe_queue(0, pipe);
 	}
+
+	if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
+
+		if (mfd->use_ov0_blt)
+			mdp4_dsi_cmd_do_blt(mfd, 1);
+		else
+			mdp4_dsi_cmd_do_blt(mfd, 0);
+
+		mfd->ov0_blt_state = mfd->use_ov0_blt;
+	}
+
 	mdp4_dsi_cmd_pipe_commit();
+	mdp4_dsi_cmd_wait4vsync(0, &xx);
+	vctrl->expire_tick = VSYNC_EXPIRE_TICK;
+	vctrl->clk_control = 1;
 }
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 9f1bfda..340faa2 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -997,6 +997,16 @@
 		mdp4_dsi_video_pipe_queue(0, pipe);
 	}
 
+	if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
+
+		if (mfd->use_ov0_blt)
+			mdp4_dsi_video_do_blt(mfd, 1);
+		else
+			mdp4_dsi_video_do_blt(mfd, 0);
+
+		mfd->ov0_blt_state = mfd->use_ov0_blt;
+	}
+
 	mdp4_dsi_video_pipe_commit();
 
 	if (pipe->ov_blt_addr)
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index e02e79c..d0d4f40 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -75,6 +75,7 @@
 	int blt_change;
 	int fake_vsync;
 	struct mutex update_lock;
+	struct completion ov_comp;
 	struct completion dmae_comp;
 	struct completion vsync_comp;
 	spinlock_t spin_lock;
@@ -160,6 +161,7 @@
 	*pp = *pipe;	/* keep it */
 	vp->update_cnt++;
 	mutex_unlock(&vctrl->update_lock);
+	mdp4_stat.overlay_play[pipe->mixer_num]++;
 }
 
 static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe);
@@ -198,6 +200,11 @@
 		if (pipe->pipe_used) {
 			cnt++;
 			mdp4_overlay_vsync_commit(pipe);
+			/* free previous iommu to freelist
+			* which will be freed at next
+			* pipe_commit
+			*/
+			mdp4_overlay_iommu_pipe_free(pipe->pipe_ndx, 0);
 			pipe->pipe_used = 0; /* clear */
 		}
 	}
@@ -216,10 +223,11 @@
 		outpdw(MDP_BASE + 0x0008, 0);
 	} else if (vctrl->dmae_intr_cnt == 0) {
 		/* schedule second phase update  at dmap */
-		vctrl->dmae_intr_cnt++;
+		INIT_COMPLETION(vctrl->dmae_comp);
 		vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
 	}
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
+	mdp4_stat.overlay_commit[pipe->mixer_num]++;
 
 	return cnt;
 }
@@ -285,7 +293,6 @@
 
 static void mdp4_dtv_wait4dmae(int cndx)
 {
-	unsigned long flags;
 	struct vsycn_ctrl *vctrl;
 
 	if (cndx >= MAX_CONTROLLER) {
@@ -298,19 +305,7 @@
 	if (atomic_read(&vctrl->suspend) > 0)
 		return;
 
-	spin_lock_irqsave(&vctrl->spin_lock, flags);
-	if (vctrl->dmae_wait_cnt == 0) {
-		INIT_COMPLETION(vctrl->dmae_comp);
-		if (vctrl->dmae_intr_cnt == 0) {
-			vctrl->dmae_intr_cnt++;
-			vsync_irq_enable(INTR_DMA_E_DONE, MDP_DMA_E_TERM);
-		}
-	}
-	vctrl->dmae_wait_cnt++;
-	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
-
 	wait_for_completion(&vctrl->dmae_comp);
-	pr_info("%s: pid=%d after wait\n", __func__, current->pid);
 }
 
 static void send_vsync_work(struct work_struct *work)
@@ -346,6 +341,8 @@
 	vctrl->update_ndx = 0;
 	mutex_init(&vctrl->update_lock);
 	init_completion(&vctrl->vsync_comp);
+	init_completion(&vctrl->ov_comp);
+	init_completion(&vctrl->dmae_comp);
 	atomic_set(&vctrl->suspend, 0);
 	spin_lock_init(&vctrl->spin_lock);
 	INIT_WORK(&vctrl->vsync_work, send_vsync_work);
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index cae523f..feba8b8 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -900,6 +900,16 @@
 		mdp4_lcdc_pipe_queue(0, pipe);
 	}
 
+	if (mfd->use_ov0_blt != mfd->ov0_blt_state) {
+
+		if (mfd->use_ov0_blt)
+			mdp4_lcdc_do_blt(mfd, 1);
+		else
+			mdp4_lcdc_do_blt(mfd, 0);
+
+		mfd->ov0_blt_state = mfd->use_ov0_blt;
+	}
+
 	mdp4_lcdc_pipe_commit();
 
 	if (pipe->ov_blt_addr)
diff --git a/drivers/video/msm/mdp_vsync.c b/drivers/video/msm/mdp_vsync.c
index 966b40d..cc350d3 100644
--- a/drivers/video/msm/mdp_vsync.c
+++ b/drivers/video/msm/mdp_vsync.c
@@ -74,14 +74,13 @@
 static uint32 vsync_cnt_cfg;
 
 
-
-void vsync_clk_enable()
+void vsync_clk_prepare_enable(void)
 {
 	if (mdp_vsync_clk)
 		clk_prepare_enable(mdp_vsync_clk);
 }
 
-void vsync_clk_disable()
+void vsync_clk_disable_unprepare(void)
 {
 	if (mdp_vsync_clk)
 		clk_disable_unprepare(mdp_vsync_clk);
diff --git a/drivers/video/msm/mipi_dsi.c b/drivers/video/msm/mipi_dsi.c
index b4fb930..f08a4e4 100644
--- a/drivers/video/msm/mipi_dsi.c
+++ b/drivers/video/msm/mipi_dsi.c
@@ -554,8 +554,10 @@
 	if (rc)
 		goto mipi_dsi_probe_err;
 
-	if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 103300000))
+	if ((dsi_pclk_rate < 3300000) || (dsi_pclk_rate > 223000000)) {
+		pr_err("%s: Pixel clock not supported\n", __func__);
 		dsi_pclk_rate = 35000000;
+	}
 	mipi->dsi_pclk_rate = dsi_pclk_rate;
 
 	/*
diff --git a/drivers/video/msm/mipi_dsi_host.c b/drivers/video/msm/mipi_dsi_host.c
index 4afffb0..39e2d6d 100644
--- a/drivers/video/msm/mipi_dsi_host.c
+++ b/drivers/video/msm/mipi_dsi_host.c
@@ -1151,15 +1151,11 @@
 
 	spin_lock_irqsave(&dsi_mdp_lock, flag);
 	dsi_mdp_busy = TRUE;
-	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
-
 	led_pwm1[1] = (unsigned char)(level);
 	tp = &dsi_tx_buf;
 	cmd = &backlight_cmd;
 	mipi_dsi_buf_init(&dsi_tx_buf);
 
-
-
 	if (tp->dmap) {
 		dma_unmap_single(&dsi_dev, tp->dmap, tp->len, DMA_TO_DEVICE);
 		tp->dmap = 0;
@@ -1180,10 +1176,6 @@
 	wmb();
 	MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01);	/* trigger */
 	wmb();
-
-	spin_lock_irqsave(&dsi_mdp_lock, flag);
-	dsi_mdp_busy = FALSE;
-	complete(&dsi_mdp_comp);
 	spin_unlock_irqrestore(&dsi_mdp_lock, flag);
 }
 
@@ -1383,6 +1375,8 @@
 int mipi_dsi_cmd_dma_tx(struct dsi_buf *tp)
 {
 
+	unsigned long flags;
+
 #ifdef DSI_HOST_DEBUG
 	int i;
 	char *bp;
@@ -1396,6 +1390,7 @@
 	pr_debug("\n");
 #endif
 
+	spin_lock_irqsave(&dsi_mdp_lock, flags);
 	tp->len += 3;
 	tp->len &= ~0x03;	/* multipled by 4 */
 
@@ -1410,6 +1405,7 @@
 	wmb();
 	MIPI_OUTP(MIPI_DSI_BASE + 0x08c, 0x01);	/* trigger */
 	wmb();
+	spin_unlock_irqrestore(&dsi_mdp_lock, flags);
 
 	wait_for_completion(&dsi_dma_comp);
 
@@ -1549,8 +1545,8 @@
 
 	if (isr & DSI_INTR_CMD_DMA_DONE) {
 		mipi_dsi_mdp_stat_inc(STAT_DSI_CMD);
-		complete(&dsi_dma_comp);
 		spin_lock(&dsi_mdp_lock);
+		complete(&dsi_dma_comp);
 		dsi_ctrl_lock = FALSE;
 		mipi_dsi_disable_irq_nosync();
 		spin_unlock(&dsi_mdp_lock);
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 18ec3f1..2c1f5b7 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -1772,8 +1772,7 @@
 	if (mfd->msmfb_no_update_notify_timer.function)
 		del_timer(&mfd->msmfb_no_update_notify_timer);
 
-	mfd->msmfb_no_update_notify_timer.expires =
-				jiffies + ((1000 * HZ) / 1000);
+	mfd->msmfb_no_update_notify_timer.expires = jiffies + (2 * HZ);
 	add_timer(&mfd->msmfb_no_update_notify_timer);
 	mutex_unlock(&msm_fb_notify_update_sem);
 
@@ -2961,8 +2960,7 @@
 	if (mfd->msmfb_no_update_notify_timer.function)
 		del_timer(&mfd->msmfb_no_update_notify_timer);
 
-	mfd->msmfb_no_update_notify_timer.expires =
-				jiffies + ((1000 * HZ) / 1000);
+	mfd->msmfb_no_update_notify_timer.expires = jiffies + (2 * HZ);
 	add_timer(&mfd->msmfb_no_update_notify_timer);
 	mutex_unlock(&msm_fb_notify_update_sem);
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
index 267e924..fade821 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_metadata.c
@@ -217,6 +217,7 @@
 	DDL_METADATA_ALIGNSIZE(suffix);
 	decoder->suffix = suffix;
 	output_buf_req->sz += suffix;
+	decoder->meta_data_offset = 0;
 	DDL_MSG_LOW("metadata output buf size : %d", suffix);
 }
 
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
index 2d3bee3..033457d 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_properties.c
@@ -1953,11 +1953,7 @@
 					DDL_TILE_MULTIPLY_FACTOR);
 		total_memory_size += component_mem_size;
 	} else {
-		if (decoding)
-			total_memory_size = frame_sz.scan_lines *
-						frame_sz.stride;
-		else
-			total_memory_size = frame_sz.height * frame_sz.stride;
+		total_memory_size = frame_sz.scan_lines * frame_sz.stride;
 		c_offset = DDL_ALIGN(total_memory_size,
 			DDL_LINEAR_MULTIPLY_FACTOR);
 		total_memory_size = c_offset + DDL_ALIGN(
diff --git a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
index d45de2d..d83cde8 100644
--- a/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
+++ b/drivers/video/msm/vidc/1080p/ddl/vcd_ddl_shared_mem.c
@@ -897,7 +897,7 @@
 				VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
 			break;
 		default:
-			DDL_MSG_ERROR("Incorrect Aspect Ratio.");
+			DDL_MSG_HIGH("Incorrect Aspect Ratio.");
 			aspect_ratio_info->par_width    = 1;
 			aspect_ratio_info->par_height   = 1;
 			break;
@@ -955,7 +955,7 @@
 				VIDC_SM_EXTENDED_PAR_HEIGHT_SHFT);
 			break;
 		default:
-			DDL_MSG_ERROR("Incorrect Aspect Ratio.");
+			DDL_MSG_HIGH("Incorrect Aspect Ratio.");
 			aspect_ratio_info->par_width    = 1;
 			aspect_ratio_info->par_height   = 1;
 			break;
diff --git a/drivers/video/msm/vidc/Kconfig b/drivers/video/msm/vidc/Kconfig
index 9ffcb15..7820e53 100644
--- a/drivers/video/msm/vidc/Kconfig
+++ b/drivers/video/msm/vidc/Kconfig
@@ -37,3 +37,7 @@
 	help
 	This option enables support for Video decoder.
 
+config MSM_VIDC_CONTENT_PROTECTION
+	bool "Enable Content Protection"
+	help
+	  Enable content protection feature for Video.
diff --git a/include/linux/coresight-stm.h b/include/linux/coresight-stm.h
index 20c4963..56a6cdf 100644
--- a/include/linux/coresight-stm.h
+++ b/include/linux/coresight-stm.h
@@ -14,12 +14,13 @@
 #define __MACH_STM_H
 
 enum {
-	OST_ENTITY_NONE			= 0x0,
-	OST_ENTITY_FTRACE_EVENTS	= 0x1,
-	OST_ENTITY_TRACE_PRINTK		= 0x2,
-	OST_ENTITY_TRACE_MARKER		= 0x4,
-	OST_ENTITY_DEV_NODE		= 0x8,
-	OST_ENTITY_ALL			= 0xF,
+	OST_ENTITY_NONE			= 0x00,
+	OST_ENTITY_FTRACE_EVENTS	= 0x01,
+	OST_ENTITY_TRACE_PRINTK		= 0x02,
+	OST_ENTITY_TRACE_MARKER		= 0x04,
+	OST_ENTITY_DEV_NODE		= 0x08,
+	OST_ENTITY_PRINTK		= 0x10,
+	OST_ENTITY_ALL			= 0x1F,
 };
 
 enum {
diff --git a/include/linux/coresight.h b/include/linux/coresight.h
index b6064a4..04fcd88 100644
--- a/include/linux/coresight.h
+++ b/include/linux/coresight.h
@@ -132,6 +132,7 @@
 struct coresight_ops_sink {
 	int (*enable)(struct coresight_device *csdev);
 	void (*disable)(struct coresight_device *csdev);
+	void (*abort)(struct coresight_device *csdev);
 };
 
 struct coresight_ops_link {
@@ -150,42 +151,21 @@
 	const struct coresight_ops_source *source_ops;
 };
 
-struct qdss_source {
-	struct list_head link;
-	const char *name;
-	uint32_t fport_mask;
-};
-
-struct msm_qdss_platform_data {
-	struct qdss_source *src_table;
-	size_t size;
-	uint8_t afamily;
-};
-
-
 #ifdef CONFIG_MSM_QDSS
-extern struct qdss_source *qdss_get(const char *name);
-extern void qdss_put(struct qdss_source *src);
-extern int qdss_enable(struct qdss_source *src);
-extern void qdss_disable(struct qdss_source *src);
-extern void qdss_disable_sink(void);
 extern struct coresight_device *
 coresight_register(struct coresight_desc *desc);
 extern void coresight_unregister(struct coresight_device *csdev);
 extern int coresight_enable(struct coresight_device *csdev);
 extern void coresight_disable(struct coresight_device *csdev);
+extern void coresight_abort(void);
 #else
-static inline struct qdss_source *qdss_get(const char *name) { return NULL; }
-static inline void qdss_put(struct qdss_source *src) {}
-static inline int qdss_enable(struct qdss_source *src) { return -ENOSYS; }
-static inline void qdss_disable(struct qdss_source *src) {}
-static inline void qdss_disable_sink(void) {}
 static inline struct coresight_device *
 coresight_register(struct coresight_desc *desc) { return NULL; }
 static inline void coresight_unregister(struct coresight_device *csdev) {}
 static inline int
 coresight_enable(struct coresight_device *csdev) { return -ENOSYS; }
 static inline void coresight_disable(struct coresight_device *csdev) {}
+static inline void coresight_abort(void) {}
 #endif
 
 #endif
diff --git a/include/linux/mfd/wcd9xxx/core.h b/include/linux/mfd/wcd9xxx/core.h
index 17be2cb..105c2cb 100644
--- a/include/linux/mfd/wcd9xxx/core.h
+++ b/include/linux/mfd/wcd9xxx/core.h
@@ -144,6 +144,7 @@
 	int (*write_dev)(struct wcd9xxx *wcd9xxx, unsigned short reg,
 			 int bytes, void *src, bool interface_reg);
 
+	u32 num_of_supplies;
 	struct regulator_bulk_data *supplies;
 
 	enum wcd9xxx_pm_state pm_state;
diff --git a/include/linux/mfd/wcd9xxx/pdata.h b/include/linux/mfd/wcd9xxx/pdata.h
index 1b7706b..e831f0b 100644
--- a/include/linux/mfd/wcd9xxx/pdata.h
+++ b/include/linux/mfd/wcd9xxx/pdata.h
@@ -125,7 +125,7 @@
 	unsigned int	hph_ocp_limit:3; /* Headphone OCP current limit */
 };
 
-#define MAX_REGULATOR	6
+#define MAX_REGULATOR	7
 /*
  *      format : TABLA_<POWER_SUPPLY_PIN_NAME>_CUR_MAX
  *
diff --git a/include/linux/of_coresight.h b/include/linux/of_coresight.h
new file mode 100644
index 0000000..47a05c9
--- /dev/null
+++ b/include/linux/of_coresight.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __LINUX_OF_CORESIGHT_H
+#define __LINUX_OF_CORESIGHT_H
+
+#ifdef CONFIG_OF
+extern struct coresight_platform_data *of_get_coresight_platform_data(
+				struct device *dev, struct device_node *node);
+#else
+static inline struct coresight_platform_data *of_get_coresight_platform_data(
+				struct device *dev, struct device_node *node)
+{
+	return NULL;
+}
+#endif
+
+#endif
diff --git a/include/linux/usb/msm_hsusb.h b/include/linux/usb/msm_hsusb.h
index 763e977..e731f97 100644
--- a/include/linux/usb/msm_hsusb.h
+++ b/include/linux/usb/msm_hsusb.h
@@ -363,6 +363,7 @@
 #define PHY_PWR_COLLAPSED		BIT(0)
 #define PHY_RETENTIONED			BIT(1)
 #define XO_SHUTDOWN			BIT(2)
+#define CLOCKS_DOWN			BIT(3)
 	int reset_counter;
 	unsigned long b_last_se0_sess;
 	unsigned long tmouts;
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index 390a843..cf99435 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -28,6 +28,7 @@
 #include <media/v4l2-common.h>
 #include <media/vcap_fmt.h>
 #include <mach/board.h>
+#include <mach/iommu_domains.h>
 
 #define to_client_data(val)     container_of(val, struct vcap_client_data, vfh)
 
@@ -94,7 +95,7 @@
 };
 
 struct nr_buffer {
-	void						*vaddr;
+	struct ion_handle			*nr_handle;
 	unsigned long				paddr;
 	enum nr_buf_pos				nr_pos;
 };
@@ -118,6 +119,7 @@
 
 	struct vcap_buffer      *bufOut;
 
+	struct ion_handle		*motionHandle;
 	void					*bufMotion;
 	struct nr_buffer		bufNR;
 	struct nr_param			nr_param;
diff --git a/include/net/bluetooth/sco.h b/include/net/bluetooth/sco.h
index 160e3f0..6d94c34 100644
--- a/include/net/bluetooth/sco.h
+++ b/include/net/bluetooth/sco.h
@@ -31,7 +31,7 @@
 #define SCO_DEFAULT_FLUSH_TO	0xFFFF
 
 #define SCO_CONN_TIMEOUT	(HZ * 40)
-#define SCO_DISCONN_TIMEOUT	(HZ * 2)
+#define SCO_DISCONN_TIMEOUT	(HZ * 20)
 #define SCO_CONN_IDLE_TIMEOUT	(HZ * 60)
 
 /* SCO socket address */
diff --git a/include/trace/ftrace.h b/include/trace/ftrace.h
index 7697249..5d675a7 100644
--- a/include/trace/ftrace.h
+++ b/include/trace/ftrace.h
@@ -17,6 +17,7 @@
  */
 
 #include <linux/ftrace_event.h>
+#include <linux/coresight-stm.h>
 
 /*
  * DECLARE_EVENT_CLASS can be used to add a generic function
@@ -544,9 +545,12 @@
 									\
 	{ assign; }							\
 									\
-	if (!filter_current_check_discard(buffer, event_call, entry, event)) \
+	if (!filter_current_check_discard(buffer, event_call, entry, event)) { \
+		stm_log(OST_ENTITY_FTRACE_EVENTS, entry,		\
+			sizeof(*entry) + __data_size);			\
 		trace_nowake_buffer_unlock_commit(buffer,		\
 						  event, irq_flags, pc); \
+	}								\
 }
 /*
  * The ftrace_test_probe is compiled out, it is only here as a build time check
diff --git a/kernel/printk.c b/kernel/printk.c
index 4cf4670..90dfdde 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -41,6 +41,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/rculist.h>
+#include <linux/coresight-stm.h>
 
 #include <asm/uaccess.h>
 
@@ -959,6 +960,8 @@
 		}
 	}
 
+	stm_log(OST_ENTITY_PRINTK, printk_buf, printed_len);
+
 	/*
 	 * Copy the output into log_buf. If the caller didn't provide
 	 * the appropriate log prefix, we insert them here
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 05970ea..b9d1a73 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -38,6 +38,7 @@
 #include <linux/poll.h>
 #include <linux/nmi.h>
 #include <linux/fs.h>
+#include <linux/coresight-stm.h>
 
 #include "trace.h"
 #include "trace_output.h"
@@ -1629,6 +1630,7 @@
 	memcpy(&entry->buf, trace_buf, len);
 	entry->buf[len] = '\0';
 	if (!filter_check_discard(call, entry, buffer, event)) {
+		stm_log(OST_ENTITY_TRACE_PRINTK, event, size);
 		ring_buffer_unlock_commit(buffer, event);
 		ftrace_trace_stack(buffer, irq_flags, 6, pc);
 	}
@@ -3826,6 +3828,7 @@
 	} else
 		entry->buf[cnt] = '\0';
 
+	stm_log(OST_ENTITY_TRACE_MARKER, event, size);
 	ring_buffer_unlock_commit(buffer, event);
 
 	written = cnt;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index f83c108..6e8500b 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2929,8 +2929,16 @@
 static inline void hci_sniff_subrate_evt(struct hci_dev *hdev, struct sk_buff *skb)
 {
 	struct hci_ev_sniff_subrate *ev = (void *) skb->data;
+	struct hci_conn *conn =
+		hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
 
 	BT_DBG("%s status %d", hdev->name, ev->status);
+	if (conn && (ev->max_rx_latency > hdev->sniff_max_interval)) {
+		BT_ERR("value of rx_latency:%d", ev->max_rx_latency);
+		hci_dev_lock(hdev);
+		hci_conn_enter_active_mode(conn, 1);
+		hci_dev_unlock(hdev);
+	}
 }
 
 static inline void hci_extended_inquiry_result_evt(struct hci_dev *hdev, struct sk_buff *skb)
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index 0a89c11..d80c0e3 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -95,12 +95,12 @@
 
 static struct device *hidp_get_device(struct hidp_session *session)
 {
-	bdaddr_t *src = &bt_sk(session->ctrl_sock->sk)->src;
-	bdaddr_t *dst = &bt_sk(session->ctrl_sock->sk)->dst;
+	bdaddr_t *dst = &session->bdaddr;
+
 	struct device *device = NULL;
 	struct hci_dev *hdev;
 
-	hdev = hci_get_route(dst, src);
+	hdev = hci_get_route(dst, BDADDR_ANY);
 	if (!hdev)
 		return NULL;
 
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index f090a77..9669d4a 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -394,6 +394,15 @@
 
 	case BT_CONNECTED:
 	case BT_CONFIG:
+		if (sco_pi(sk)->conn) {
+			sk->sk_state = BT_DISCONN;
+			sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
+			hci_conn_put(sco_pi(sk)->conn->hcon);
+			sco_pi(sk)->conn->hcon = NULL;
+		} else
+			sco_chan_del(sk, ECONNRESET);
+		break;
+
 	case BT_CONNECT:
 	case BT_DISCONN:
 		sco_chan_del(sk, ECONNRESET);
@@ -803,6 +812,9 @@
 		if (sock_flag(sk, SOCK_LINGER) && sk->sk_lingertime)
 			err = bt_sock_wait_state(sk, BT_CLOSED,
 							sk->sk_lingertime);
+		else
+			err = bt_sock_wait_state(sk, BT_CLOSED,
+							SCO_DISCONN_TIMEOUT);
 	}
 	release_sock(sk);
 	return err;
@@ -824,6 +836,11 @@
 		lock_sock(sk);
 		err = bt_sock_wait_state(sk, BT_CLOSED, sk->sk_lingertime);
 		release_sock(sk);
+	} else {
+		lock_sock(sk);
+		err = bt_sock_wait_state(sk, BT_CLOSED,
+							SCO_DISCONN_TIMEOUT);
+		release_sock(sk);
 	}
 
 	sock_orphan(sk);
@@ -857,7 +874,9 @@
 		conn->sk = NULL;
 		sco_pi(sk)->conn = NULL;
 		sco_conn_unlock(conn);
-		hci_conn_put(conn->hcon);
+
+		if (conn->hcon)
+			hci_conn_put(conn->hcon);
 	}
 
 	sk->sk_state = BT_CLOSED;
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 571e71c..4758829 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -35,6 +35,10 @@
 #include <linux/gpio.h>
 #include "wcd9310.h"
 
+static int cfilt_adjust_ms = 10;
+module_param(cfilt_adjust_ms, int, 0644);
+MODULE_PARM_DESC(cfilt_adjust_ms, "delay after adjusting cfilt voltage in ms");
+
 #define WCD9310_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_16000 |\
 			SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000 |\
 			SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_192000)
@@ -2240,26 +2244,26 @@
 	}
 	snd_soc_write(codec, TABLA_A_MBHC_SCALING_MUX_1, 0x84);
 
-	if (!tabla->no_mic_headset_override) {
-		if (mbhc_state == MBHC_STATE_POTENTIAL) {
-			pr_debug("%s recovering MBHC state macine\n", __func__);
-			tabla->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
-			/* set to max button press threshold */
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
-				      0x7F);
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
-				      0xFF);
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
-				      (TABLA_IS_1_X(tabla_core->version) ?
-				       0x07 : 0x7F));
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL,
-				      0xFF);
-			/* set to max */
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL,
-				      0x7F);
-			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL,
-				      0xFF);
-		}
+	if (tabla->no_mic_headset_override) {
+		pr_debug("%s setting button threshold to min", __func__);
+		/* set to min */
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL, 0x80);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0x00);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL, 0x80);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL, 0x00);
+	} else if (unlikely(mbhc_state == MBHC_STATE_POTENTIAL)) {
+		pr_debug("%s recovering MBHC state machine\n", __func__);
+		tabla->mbhc_state = MBHC_STATE_POTENTIAL_RECOVERY;
+		/* set to max button press threshold */
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL, 0x7F);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL, 0xFF);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B4_CTL,
+			      (TABLA_IS_1_X(tabla_core->version) ?
+			       0x07 : 0x7F));
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B3_CTL, 0xFF);
+		/* set to max */
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B6_CTL, 0x7F);
+		snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B5_CTL, 0xFF);
 	}
 
 	snd_soc_write(codec, TABLA_A_CDC_MBHC_EN_CTL, 0x1);
@@ -2479,11 +2483,11 @@
 			cfilt_k_val = tabla_find_k_value(
 						   tabla->pdata->micbias.ldoh_v,
 						   VDDIO_MICBIAS_MV);
-			usleep_range(10000, 10000);
 			snd_soc_update_bits(codec,
 					    tabla->mbhc_bias_regs.cfilt_val,
 					    0xFC, (cfilt_k_val << 2));
-			usleep_range(10000, 10000);
+			usleep_range(cfilt_adjust_ms * 1000,
+				     cfilt_adjust_ms * 1000);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
 				      tabla->mbhc_data.adj_v_ins_hu & 0xFF);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
@@ -2517,7 +2521,8 @@
 			snd_soc_update_bits(codec,
 					    tabla->mbhc_bias_regs.cfilt_val,
 					    0xFC, (cfilt_k_val << 2));
-			usleep_range(10000, 10000);
+			usleep_range(cfilt_adjust_ms * 1000,
+				     cfilt_adjust_ms * 1000);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B1_CTL,
 				      tabla->mbhc_data.v_ins_hu & 0xFF);
 			snd_soc_write(codec, TABLA_A_CDC_MBHC_VOLT_B2_CTL,
@@ -3878,11 +3883,22 @@
 		}
 	} else if (dai->id == AIF1_CAP || dai->id == AIF2_CAP ||
 		   dai->id == AIF3_CAP) {
-		for (i = 0; i < tx_num; i++) {
-			tabla->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
-			tabla->dai[dai->id - 1].ch_act = 0;
-			tabla->dai[dai->id - 1].ch_tot = tx_num;
+		tabla->dai[dai->id - 1].ch_tot = tx_num;
+		/* All channels are already active.
+		 * do not reset ch_act flag
+		 */
+		if ((tabla->dai[dai->id - 1].ch_tot != 0)
+			&& (tabla->dai[dai->id - 1].ch_act ==
+			tabla->dai[dai->id - 1].ch_tot)) {
+			pr_info("%s: ch_act = %d, ch_tot = %d\n", __func__,
+				tabla->dai[dai->id - 1].ch_act,
+				tabla->dai[dai->id - 1].ch_tot);
+			return 0;
 		}
+
+		tabla->dai[dai->id - 1].ch_act = 0;
+		for (i = 0; i < tx_num; i++)
+			tabla->dai[dai->id - 1].ch_num[i]  = tx_slot[i];
 	}
 	return 0;
 }
@@ -7766,9 +7782,15 @@
 
 	lbuf[cnt] = '\0';
 	buf = (char *)lbuf;
-	tabla->no_mic_headset_override = (*strsep(&buf, " ") == '0') ?
-					     false : true;
-	return rc;
+	TABLA_ACQUIRE_LOCK(tabla->codec_resource_lock);
+	tabla->no_mic_headset_override =
+	    (*strsep(&buf, " ") == '0') ? false : true;
+	if (tabla->no_mic_headset_override && tabla->mbhc_polling_active) {
+		tabla_codec_pause_hs_polling(tabla->codec);
+		tabla_codec_start_hs_polling(tabla->codec);
+	}
+	TABLA_RELEASE_LOCK(tabla->codec_resource_lock);
+	return cnt;
 }
 
 static ssize_t codec_mbhc_debug_read(struct file *file, char __user *buf,
diff --git a/sound/soc/codecs/wcd9320.c b/sound/soc/codecs/wcd9320.c
index 6da9166..01820eb 100644
--- a/sound/soc/codecs/wcd9320.c
+++ b/sound/soc/codecs/wcd9320.c
@@ -6817,18 +6817,21 @@
 	struct snd_soc_codec *codec = taiko->codec;
 	struct wcd9xxx_pdata *pdata = taiko->pdata;
 	int k1, k2, k3, rc = 0;
-	u8 leg_mode = pdata->amic_settings.legacy_mode;
-	u8 txfe_bypass = pdata->amic_settings.txfe_enable;
-	u8 txfe_buff = pdata->amic_settings.txfe_buff;
-	u8 flag = pdata->amic_settings.use_pdata;
+	u8 leg_mode, txfe_bypass, txfe_buff, flag;
 	u8 i = 0, j = 0;
 	u8 val_txfe = 0, value = 0;
 
 	if (!pdata) {
+		pr_err("%s: NULL pdata\n", __func__);
 		rc = -ENODEV;
 		goto done;
 	}
 
+	leg_mode = pdata->amic_settings.legacy_mode;
+	txfe_bypass = pdata->amic_settings.txfe_enable;
+	txfe_buff = pdata->amic_settings.txfe_buff;
+	flag = pdata->amic_settings.use_pdata;
+
 	/* Make sure settings are correct */
 	if ((pdata->micbias.ldoh_v > TAIKO_LDOH_2P85_V) ||
 	    (pdata->micbias.bias1_cfilt_sel > TAIKO_CFILT3_SEL) ||
diff --git a/sound/soc/msm/msm-pcm-routing.c b/sound/soc/msm/msm-pcm-routing.c
index da3d335..26dbb21 100644
--- a/sound/soc/msm/msm-pcm-routing.c
+++ b/sound/soc/msm/msm-pcm-routing.c
@@ -1782,6 +1782,7 @@
 	.put = msm_routing_set_srs_trumedia_control,
 	.private_value = ((unsigned long)&(struct soc_mixer_control)
 	{.reg = SND_SOC_NOPM,
+	.rreg = SND_SOC_NOPM,
 	.shift = 0,
 	.rshift = 0,
 	.max = 0xFFFFFFFF,
@@ -1801,6 +1802,7 @@
 	.put = msm_routing_set_srs_trumedia_control_HDMI,
 	.private_value = ((unsigned long)&(struct soc_mixer_control)
 	{.reg = SND_SOC_NOPM,
+	.rreg = SND_SOC_NOPM,
 	.shift = 0,
 	.rshift = 0,
 	.max = 0xFFFFFFFF,
@@ -1820,6 +1822,7 @@
 	.put = msm_routing_set_srs_trumedia_control_I2S,
 	.private_value = ((unsigned long)&(struct soc_mixer_control)
 	{.reg = SND_SOC_NOPM,
+	.rreg = SND_SOC_NOPM,
 	.shift = 0,
 	.rshift = 0,
 	.max = 0xFFFFFFFF,
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 3791f24..2a21dfa 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -36,10 +36,16 @@
 #define VOC_PATH_VOLTE_PASSIVE 2
 #define VOC_PATH_SGLTE_PASSIVE 3
 
-/* CVP CAL Size: 245760 = 240 * 1024 */
-#define CVP_CAL_SIZE 245760
-/* CVS CAL Size: 49152 = 48 * 1024 */
-#define CVS_CAL_SIZE 49152
+#define CAL_BUFFER_SIZE		4096
+#define NUM_CVP_CAL_BLOCKS	75
+#define NUM_CVS_CAL_BLOCKS	15
+#define CVP_CAL_SIZE		(NUM_CVP_CAL_BLOCKS * CAL_BUFFER_SIZE)
+#define CVS_CAL_SIZE		(NUM_CVS_CAL_BLOCKS * CAL_BUFFER_SIZE)
+#define VOICE_CAL_BUFFER_SIZE	(CVP_CAL_SIZE + CVS_CAL_SIZE)
+/* Total cal needed to support concurrent VOIP & VOLTE sessions */
+/* Due to memory map issue on Q6 separate memory has to be used */
+/* for VOIP & VOLTE  */
+#define TOTAL_VOICE_CAL_SIZE	(NUM_VOICE_CAL_BUFFERS * VOICE_CAL_BUFFER_SIZE)
 
 static struct common_data common;
 
@@ -198,6 +204,72 @@
 	return (session_id == common.voice[VOC_PATH_SGLTE_PASSIVE].session_id);
 }
 
+/* Only for memory allocated in the voice driver */
+/* which includes voip & volte */
+static int voice_get_cal_kernel_addr(int16_t session_id, int cal_type,
+					uint32_t *kvaddr)
+{
+	int	i, result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (kvaddr == NULL) {
+		pr_err("%s: NULL pointer sent to function\n", __func__);
+		result = -EINVAL;
+		goto done;
+	} else if (is_voip_session(session_id)) {
+		i = VOIP_CAL;
+	} else if (is_volte_session(session_id)) {
+		i = VOLTE_CAL;
+	} else {
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (common.voice_cal[i].cal_data[cal_type].kvaddr == 0) {
+		pr_err("%s: NULL pointer for session_id %d, type %d, cal_type %d\n",
+			__func__, session_id, i, cal_type);
+		result = -EFAULT;
+		goto done;
+	}
+
+	*kvaddr = common.voice_cal[i].cal_data[cal_type].kvaddr;
+done:
+	return result;
+}
+
+/* Only for memory allocated in the voice driver */
+/* which includes voip & volte */
+static int voice_get_cal_phys_addr(int16_t session_id, int cal_type,
+					uint32_t *paddr)
+{
+	int	i, result = 0;
+	pr_debug("%s\n", __func__);
+
+	if (paddr == NULL) {
+		pr_err("%s: NULL pointer sent to function\n", __func__);
+		result = -EINVAL;
+		goto done;
+	} else if (is_voip_session(session_id)) {
+		i = VOIP_CAL;
+	} else if (is_volte_session(session_id)) {
+		i = VOLTE_CAL;
+	} else {
+		result = -EINVAL;
+		goto done;
+	}
+
+	if (common.voice_cal[i].cal_data[cal_type].paddr == 0) {
+		pr_err("%s: No addr for session_id %d, type %d, cal_type %d\n",
+			__func__, session_id, i, cal_type);
+		result = -EFAULT;
+		goto done;
+	}
+
+	*paddr = common.voice_cal[i].cal_data[cal_type].paddr;
+done:
+	return result;
+}
+
 static int voice_apr_register(void)
 {
 	pr_debug("%s\n", __func__);
@@ -1237,7 +1309,8 @@
 	int ret = 0;
 	void *apr_cvs;
 	u16 cvs_handle;
-	uint32_t cal_paddr;
+	uint32_t cal_paddr = 0;
+	uint32_t cal_buf = 0;
 
 	/* get the cvs cal data */
 	get_all_vocstrm_cal(&cal_block);
@@ -1255,16 +1328,20 @@
 		return -EINVAL;
 	}
 
-	if (is_voip_session(v->session_id)) {
-		if (common.cvs_cal.buf) {
-			cal_paddr = common.cvs_cal.phy;
+	if (is_volte_session(v->session_id) ||
+			is_voip_session(v->session_id)) {
+		ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL,
+						&cal_paddr);
+		if (ret < 0)
+			return ret;
 
-			memcpy(common.cvs_cal.buf,
-				(void *) cal_block.cal_kvaddr,
-				cal_block.cal_size);
-		} else {
-			return -EINVAL;
-		}
+		ret = voice_get_cal_kernel_addr(v->session_id, CVS_CAL,
+						&cal_buf);
+		if (ret < 0)
+			return ret;
+
+		memcpy((void *)cal_buf, (void *)cal_block.cal_kvaddr,
+			cal_block.cal_size);
 	} else {
 		cal_paddr = cal_block.cal_paddr;
 	}
@@ -1364,7 +1441,7 @@
 	int ret = 0;
 	void *apr_cvp;
 	u16 cvp_handle;
-	uint32_t cal_paddr;
+	uint32_t cal_paddr = 0;
 
 	/* get all cvp cal data */
 	get_all_cvp_cal(&cal_block);
@@ -1382,14 +1459,16 @@
 		return -EINVAL;
 	}
 
-	if (is_voip_session(v->session_id)) {
-		if (common.cvp_cal.buf)
-			cal_paddr = common.cvp_cal.phy;
-		else
-			return -EINVAL;
+	if (is_volte_session(v->session_id) ||
+			is_voip_session(v->session_id)) {
+		ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+						&cal_paddr);
+		if (ret < 0)
+			return ret;
 	} else {
 		cal_paddr = cal_block.cal_paddr;
 	}
+
 	cvp_handle = voice_get_cvp_handle(v);
 
 	/* fill in the header */
@@ -1402,7 +1481,7 @@
 	cvp_map_mem_cmd.hdr.token = 0;
 	cvp_map_mem_cmd.hdr.opcode = VSS_ICOMMON_CMD_MAP_MEMORY;
 
-	pr_debug("%s, phy_addr:0x%x, mem_size:%d\n", __func__,
+	pr_debug("%s, phys_addr: 0x%x, mem_size: %d\n", __func__,
 		cal_paddr, cal_block.cal_size);
 	cvp_map_mem_cmd.vss_map_mem.phys_addr = cal_paddr;
 	cvp_map_mem_cmd.vss_map_mem.mem_size = cal_block.cal_size;
@@ -1435,7 +1514,7 @@
 	int ret = 0;
 	void *apr_cvp;
 	u16 cvp_handle;
-	uint32_t cal_paddr;
+	uint32_t cal_paddr = 0;
 
 	get_all_cvp_cal(&cal_block);
 	if (cal_block.cal_size == 0)
@@ -1452,10 +1531,15 @@
 		return -EINVAL;
 	}
 
-	if (is_voip_session(v->session_id))
-		cal_paddr = common.cvp_cal.phy;
-	else
+	if (is_volte_session(v->session_id) ||
+			is_voip_session(v->session_id)) {
+		ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+						&cal_paddr);
+		if (ret < 0)
+			return ret;
+	} else {
 		cal_paddr = cal_block.cal_paddr;
+	}
 
 	cvp_handle = voice_get_cvp_handle(v);
 
@@ -1497,7 +1581,7 @@
 	int ret = 0;
 	void *apr_cvs;
 	u16 cvs_handle;
-	uint32_t cal_paddr;
+	uint32_t cal_paddr = 0;
 
 	/* get all cvs cal data */
 	get_all_vocstrm_cal(&cal_block);
@@ -1515,11 +1599,12 @@
 		return -EINVAL;
 	}
 
-	if (is_voip_session(v->session_id)) {
-		if (common.cvs_cal.buf)
-			cal_paddr = common.cvs_cal.phy;
-		else
-			return -EINVAL;
+	if (is_volte_session(v->session_id) ||
+			is_voip_session(v->session_id)) {
+		ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL,
+						&cal_paddr);
+		if (ret < 0)
+			return ret;
 	} else {
 		cal_paddr = cal_block.cal_paddr;
 	}
@@ -1569,7 +1654,7 @@
 	int ret = 0;
 	void *apr_cvs;
 	u16 cvs_handle;
-	uint32_t cal_paddr;
+	uint32_t cal_paddr = 0;
 
 	get_all_vocstrm_cal(&cal_block);
 	if (cal_block.cal_size == 0)
@@ -1586,10 +1671,15 @@
 		return -EINVAL;
 	}
 
-	if (is_voip_session(v->session_id))
-		cal_paddr = common.cvs_cal.phy;
-	else
+	if (is_volte_session(v->session_id) ||
+			is_voip_session(v->session_id)) {
+		ret = voice_get_cal_phys_addr(v->session_id, CVS_CAL,
+						&cal_paddr);
+		if (ret < 0)
+			return ret;
+	} else {
 		cal_paddr = cal_block.cal_paddr;
+	}
 
 	cvs_handle = voice_get_cvs_handle(v);
 
@@ -1631,7 +1721,8 @@
 	int ret = 0;
 	void *apr_cvp;
 	u16 cvp_handle;
-	uint32_t cal_paddr;
+	uint32_t cal_paddr = 0;
+	uint32_t cal_buf = 0;
 
       /* get the cvp cal data */
 	get_all_vocproc_cal(&cal_block);
@@ -1649,16 +1740,20 @@
 		return -EINVAL;
 	}
 
-	if (is_voip_session(v->session_id)) {
-		if (common.cvp_cal.buf) {
-			cal_paddr = common.cvp_cal.phy;
+	if (is_volte_session(v->session_id) ||
+			is_voip_session(v->session_id)) {
+		ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+						&cal_paddr);
+		if (ret < 0)
+			return ret;
 
-			memcpy(common.cvp_cal.buf,
-				(void *)cal_block.cal_kvaddr,
-				cal_block.cal_size);
-		} else {
-			return -EINVAL;
-		}
+		ret = voice_get_cal_kernel_addr(v->session_id, CVP_CAL,
+						&cal_buf);
+		if (ret < 0)
+			return ret;
+
+		memcpy((void *)cal_buf, (void *)cal_block.cal_kvaddr,
+			cal_block.cal_size);
 	} else {
 		cal_paddr = cal_block.cal_paddr;
 	}
@@ -1759,7 +1854,8 @@
 	int ret = 0;
 	void *apr_cvp;
 	u16 cvp_handle;
-	uint32_t cal_paddr;
+	uint32_t cal_paddr = 0;
+	uint32_t cal_buf = 0;
 
 	/* get the cvp vol cal data */
 	get_all_vocvol_cal(&vol_block);
@@ -1779,16 +1875,21 @@
 		return -EINVAL;
 	}
 
-	if (is_voip_session(v->session_id)) {
-		if (common.cvp_cal.buf) {
-			cal_paddr = common.cvp_cal.phy + voc_block.cal_size;
+	if (is_volte_session(v->session_id) ||
+			is_voip_session(v->session_id)) {
+		ret = voice_get_cal_phys_addr(v->session_id, CVP_CAL,
+						&cal_paddr);
+		if (ret < 0)
+			return ret;
 
-			memcpy(common.cvp_cal.buf + voc_block.cal_size,
-				(void *) vol_block.cal_kvaddr,
-				vol_block.cal_size);
-		} else {
-			return -EINVAL;
-		}
+		cal_paddr += voc_block.cal_size;
+		ret = voice_get_cal_kernel_addr(v->session_id, CVP_CAL,
+						&cal_buf);
+		if (ret < 0)
+			return ret;
+
+		memcpy((void *)(cal_buf + voc_block.cal_size),
+			(void *)vol_block.cal_kvaddr, vol_block.cal_size);
 	} else {
 		cal_paddr = vol_block.cal_paddr;
 	}
@@ -3943,76 +4044,83 @@
 }
 
 
+static void voice_allocate_shared_memory(void)
+{
+	int			i, j, result;
+	int			offset = 0;
+	int			mem_len;
+	unsigned long		paddr;
+	void                    *kvptr;
+	pr_debug("%s\n", __func__);
+
+	common.ion_client = msm_ion_client_create(UINT_MAX, "q6voice_client");
+	if (IS_ERR_OR_NULL((void *)common.ion_client)) {
+		pr_err("%s: ION create client failed\n", __func__);
+		goto err;
+	}
+
+	common.ion_handle = ion_alloc(common.ion_client,
+				TOTAL_VOICE_CAL_SIZE,
+				SZ_4K, ION_HEAP(ION_AUDIO_HEAP_ID));
+	if (IS_ERR_OR_NULL((void *) common.ion_handle)) {
+		pr_err("%s: ION memory allocation failed\n",
+			__func__);
+		goto err_ion_client;
+	}
+
+	result = ion_phys(common.ion_client, common.ion_handle,
+			&paddr, (size_t *)&mem_len);
+	if (result) {
+		pr_err("%s: ION Get Physical failed, rc = %d\n",
+			__func__, result);
+		goto err_ion_handle;
+	}
+
+	kvptr = ion_map_kernel(common.ion_client,
+				common.ion_handle, 0);
+	if (IS_ERR_OR_NULL(kvptr)) {
+		pr_err("%s: ION memory mapping failed\n", __func__);
+		goto err_ion_handle;
+	}
+
+	/* Make all phys & buf point to the correct address */
+	for (i = 0; i < NUM_VOICE_CAL_BUFFERS; i++) {
+		for (j = 0; j < NUM_VOICE_CAL_TYPES; j++) {
+			common.voice_cal[i].cal_data[j].paddr =
+				(uint32_t)(paddr + offset);
+			common.voice_cal[i].cal_data[j].kvaddr =
+				(uint32_t)((uint8_t *)kvptr + offset);
+			if (j == CVP_CAL)
+				offset += CVP_CAL_SIZE;
+			else
+				offset += CVS_CAL_SIZE;
+
+			pr_debug("%s: kernel addr = 0x%x, phys addr = 0x%x\n",
+				__func__,
+				common.voice_cal[i].cal_data[j].kvaddr,
+				common.voice_cal[i].cal_data[j].paddr);
+		}
+	}
+
+	return;
+
+err_ion_handle:
+	ion_free(common.ion_client, common.ion_handle);
+err_ion_client:
+	ion_client_destroy(common.ion_client);
+err:
+	return;
+}
+
 static int __init voice_init(void)
 {
 	int rc = 0, i = 0;
-	int len;
 
 	memset(&common, 0, sizeof(struct common_data));
 
-	/* Allocate memory for VoIP calibration */
-	common.client = msm_ion_client_create(UINT_MAX, "voip_client");
-	if (IS_ERR_OR_NULL((void *)common.client)) {
-		pr_err("%s: ION create client for Voip failed\n", __func__);
-		goto cont;
-	}
-	common.cvp_cal.handle = ion_alloc(common.client, CVP_CAL_SIZE, SZ_4K,
-					  ION_HEAP(ION_AUDIO_HEAP_ID));
-	if (IS_ERR_OR_NULL((void *) common.cvp_cal.handle)) {
-		pr_err("%s: ION memory allocation for CVP failed\n",
-			__func__);
-		ion_client_destroy(common.client);
-		goto cont;
-	}
+	/* Allocate shared memory */
+	voice_allocate_shared_memory();
 
-	rc = ion_phys(common.client, common.cvp_cal.handle,
-		  (ion_phys_addr_t *)&common.cvp_cal.phy, (size_t *)&len);
-	if (rc) {
-		pr_err("%s: ION Get Physical for cvp failed, rc = %d\n",
-			__func__, rc);
-		ion_free(common.client, common.cvp_cal.handle);
-		ion_client_destroy(common.client);
-		goto cont;
-	}
-
-	common.cvp_cal.buf = ion_map_kernel(common.client,
-					common.cvp_cal.handle, 0);
-	if (IS_ERR_OR_NULL((void *) common.cvp_cal.buf)) {
-		pr_err("%s: ION memory mapping for cvp failed\n", __func__);
-		common.cvp_cal.buf = NULL;
-		ion_free(common.client, common.cvp_cal.handle);
-		ion_client_destroy(common.client);
-		goto cont;
-	}
-	memset((void *)common.cvp_cal.buf, 0, CVP_CAL_SIZE);
-
-	common.cvs_cal.handle = ion_alloc(common.client, CVS_CAL_SIZE, SZ_4K,
-					 ION_HEAP(ION_AUDIO_HEAP_ID));
-	if (IS_ERR_OR_NULL((void *) common.cvs_cal.handle)) {
-		pr_err("%s: ION memory allocation for CVS failed\n",
-			__func__);
-		goto cont;
-	}
-
-	rc = ion_phys(common.client, common.cvs_cal.handle,
-		  (ion_phys_addr_t *)&common.cvs_cal.phy, (size_t *)&len);
-	if (rc) {
-		pr_err("%s: ION Get Physical for cvs failed, rc = %d\n",
-			__func__, rc);
-		ion_free(common.client, common.cvs_cal.handle);
-		goto cont;
-	}
-
-	common.cvs_cal.buf = ion_map_kernel(common.client,
-					common.cvs_cal.handle, 0);
-	if (IS_ERR_OR_NULL((void *) common.cvs_cal.buf)) {
-		pr_err("%s: ION memory mapping for cvs failed\n", __func__);
-		common.cvs_cal.buf = NULL;
-		ion_free(common.client, common.cvs_cal.handle);
-		goto cont;
-	}
-	memset((void *)common.cvs_cal.buf, 0, CVS_CAL_SIZE);
-cont:
 	/* set default value */
 	common.default_mute_val = 0;  /* default is un-mute */
 	common.default_vol_val = 0;
diff --git a/sound/soc/msm/qdsp6/q6voice.h b/sound/soc/msm/qdsp6/q6voice.h
index 468aba8..1cb2878 100644
--- a/sound/soc/msm/qdsp6/q6voice.h
+++ b/sound/soc/msm/qdsp6/q6voice.h
@@ -22,6 +22,20 @@
 #define VOC_REC_DOWNLINK	0x01
 #define VOC_REC_BOTH		0x02
 
+/* Needed for VOIP & VOLTE support */
+/* Due to Q6 memory map issue */
+enum {
+	VOIP_CAL,
+	VOLTE_CAL,
+	NUM_VOICE_CAL_BUFFERS
+};
+
+enum {
+	CVP_CAL,
+	CVS_CAL,
+	NUM_VOICE_CAL_TYPES
+};
+
 struct voice_header {
 	uint32_t id;
 	uint32_t data_len;
@@ -913,9 +927,14 @@
 };
 
 struct cal_mem {
-	struct ion_handle *handle;
-	uint32_t phy;
-	void *buf;
+	/* Physical Address */
+	uint32_t paddr;
+	/* Kernel Virtual Address */
+	uint32_t kvaddr;
+};
+
+struct cal_data {
+	struct cal_mem	cal_data[NUM_VOICE_CAL_TYPES];
 };
 
 #define MAX_VOC_SESSIONS 4
@@ -934,9 +953,9 @@
 	/* APR to CVP in the Q6 */
 	void *apr_q6_cvp;
 
-	struct ion_client *client;
-	struct cal_mem cvp_cal;
-	struct cal_mem cvs_cal;
+	struct ion_client *ion_client;
+	struct ion_handle *ion_handle;
+	struct cal_data voice_cal[NUM_VOICE_CAL_BUFFERS];
 
 	struct mutex common_lock;
 
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index be2e0c5..2d2b333 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -700,7 +700,7 @@
 	if (perf_pmu__config(pmu, &attr, head_config))
 		return -EINVAL;
 
-	return add_event(list, idx, &attr, (char *) "pmu");
+	return add_event(list, idx, &attr, pmu->name);
 }
 
 void parse_events_update_lists(struct list_head *list_event,
diff --git a/tools/perf/util/parse-events.l b/tools/perf/util/parse-events.l
index 28e5548..4b3a3c9 100644
--- a/tools/perf/util/parse-events.l
+++ b/tools/perf/util/parse-events.l
@@ -64,7 +64,7 @@
 num_dec		[0-9]+
 num_hex		0x[a-fA-F0-9]+
 num_raw_hex	[a-fA-F0-9]+
-name		[a-zA-Z_*?][a-zA-Z0-9_*?]*
+name		[a-zA-Z_*?][a-zA-Z\-0-9_*?]*
 modifier_event	[ukhpGH]{1,8}
 modifier_bp	[rwx]