Merge "mmc: msm_sdcc: don't return error if regulator info is not available"
diff --git a/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt b/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt
new file mode 100644
index 0000000..e5fd1b2
--- /dev/null
+++ b/Documentation/devicetree/bindings/arm/msm/qcom-wdog-debug.txt
@@ -0,0 +1,16 @@
+* Qualcomm's Watchdog Debug Image Controller
+
+The Qualcomm's Watchdog debug image controller is used for enabling/disabling of
+watchdog debug image feature.
+
+Required properties:
+- compatible : should be "qcom,msm-wdog-debug"
+- reg : base page aligned physical base address of the controller and length of
+	memory mapped region.
+
+Example:
+
+	qcom,msm-wdog-debug@fc401000 {
+		compatible = "qcom,msm-wdogi-debug";
+		reg = <0xfc401000 0x1000>;
+	};
diff --git a/Documentation/devicetree/bindings/iommu/msm_iommu.txt b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
index f5a2590..7a90cc0 100644
--- a/Documentation/devicetree/bindings/iommu/msm_iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/msm_iommu.txt
@@ -19,6 +19,19 @@
 Optional properties:
 - qcom,needs-alt-core-clk : boolean to enable the secondary core clock for
   access to the IOMMU configuration registers
+- qcom,iommu-bfb-regs : An array of unsigned 32-bit integers corresponding to
+  BFB register addresses that need to be configured for performance tuning
+  purposes. If this property is present, the qcom,iommu-bfb-data must also be
+  present. Register addresses are specified as an offset from the base of the
+  IOMMU hardware block. This property may be omitted if no BFB register
+  configuration needs to be done for a particular IOMMU hardware instance. The
+  registers specified by this property shall fall within the IOMMU
+  implementation-defined register region.
+- qcom,iommu-bfb-data : An array of unsigned 32-bit integers representing the
+  values to be programmed into the corresponding registers given by the
+  qcom,iommu-bfb-regs property. If this property is present, the
+  qcom,iommu-bfb-regs property shall also be present, and the lengths of both
+  properties shall be the same.
 
 Example:
 
@@ -26,6 +39,8 @@
                 compatible = "qcom,msm-smmu-v2";
                 reg = <0xfda64000 0x10000>;
 		vdd-supply = <&gdsc_iommu>;
+		qcom,iommu-bfb-regs = <0x204c 0x2050>;
+		qcom,iommu-bfb-data = <0xffff 0xffce>;
 
                 qcom,iommu-ctx@fda6c000 {
                         reg = <0xfda6c000 0x1000>;
diff --git a/arch/arm/boot/dts/mpq8092-iommu.dtsi b/arch/arm/boot/dts/mpq8092-iommu.dtsi
old mode 100755
new mode 100644
diff --git a/arch/arm/boot/dts/msm-pm8841.dtsi b/arch/arm/boot/dts/msm-pm8841.dtsi
index 069a248..ea83231 100644
--- a/arch/arm/boot/dts/msm-pm8841.dtsi
+++ b/arch/arm/boot/dts/msm-pm8841.dtsi
@@ -22,7 +22,7 @@
 		#address-cells = <1>;
 		#size-cells = <1>;
 
-		pm8841_mpps {
+		pm8841_mpps: mpps {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
 			gpio-controller;
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index d58a71d..f1e18cf 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -203,7 +203,7 @@
 			};
 		};
 
-		pm8941_gpios {
+		pm8941_gpios: gpios {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
 			gpio-controller;
@@ -393,7 +393,7 @@
 			};
 		};
 
-		pm8941_mpps {
+		pm8941_mpps: mpps {
 			spmi-dev-container;
 			compatible = "qcom,qpnp-pin";
 			gpio-controller;
diff --git a/arch/arm/boot/dts/msm8974-cdp.dts b/arch/arm/boot/dts/msm8974-cdp.dts
index 7aeb33c..aff0adc 100644
--- a/arch/arm/boot/dts/msm8974-cdp.dts
+++ b/arch/arm/boot/dts/msm8974-cdp.dts
@@ -168,3 +168,196 @@
 	cd-gpios = <&msmgpio 62 0x1>;
 	wp-gpios = <&pm8941_gpios 29 0x1>;
 };
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-gpio.dtsi b/arch/arm/boot/dts/msm8974-gpio.dtsi
deleted file mode 100644
index e298340..0000000
--- a/arch/arm/boot/dts/msm8974-gpio.dtsi
+++ /dev/null
@@ -1,214 +0,0 @@
-/* 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.
- */
-
-&spmi_bus {
-
-	qcom,pm8941@0 {
-
-		pm8941_gpios: pm8941_gpios {
-
-			gpio@c000 {
-			};
-
-			gpio@c100 {
-			};
-
-			gpio@c200 {
-				qcom,mode = <0>;
-				qcom,pull = <0>;
-				qcom,vin-sel = <2>;
-				qcom,select = <0>;
-			};
-
-			gpio@c300 {
-				qcom,mode = <0>;
-				qcom,pull = <0>;
-				qcom,vin-sel = <2>;
-				qcom,select = <0>;
-			};
-
-			gpio@c400 {
-				qcom,mode = <0>;
-				qcom,pull = <0>;
-				qcom,vin-sel = <2>;
-				qcom,select = <0>;
-			};
-
-			gpio@c500 {
-			};
-
-			gpio@c600 {
-			};
-
-			gpio@c700 {
-			};
-
-			gpio@c800 {
-			};
-
-			gpio@c900 {
-			};
-
-			gpio@ca00 {
-			};
-
-			gpio@cb00 {
-			};
-
-			gpio@cc00 {
-			};
-
-			gpio@cd00 {
-			};
-
-			gpio@ce00 {
-				qcom,mode = <1>;
-				qcom,output-type = <0>;
-				qcom,pull = <5>;
-				qcom,vin-sel = <2>;
-				qcom,out-strength = <3>;
-				qcom,src-select = <2>;
-				qcom,master-en = <1>;
-			};
-
-			gpio@cf00 {
-			};
-
-			gpio@d000 {
-			};
-
-			gpio@d100 {
-			};
-
-			gpio@d200 {
-				qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
-				qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
-				qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
-				qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
-				qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
-				qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
-				qcom,master-en = <1>;
-			};
-
-			gpio@d300 {
-			};
-
-			gpio@d400 {
-			};
-
-			gpio@d500 {
-			};
-
-			gpio@d600 {
-			};
-
-			gpio@d700 {
-			};
-
-			gpio@d800 {
-			};
-
-			gpio@d900 {
-			};
-
-			gpio@da00 {
-			};
-
-			gpio@db00 {
-			};
-
-			gpio@dc00 {
-				qcom,pull = <0>; /* set to default pull */
-				qcom,master-en = <1>;
-				qcom,vin-sel = <2>; /* select 1.8 V source */
-			};
-
-			gpio@dd00 {
-			};
-
-			gpio@de00 {
-			};
-
-			gpio@df00 {
-			};
-
-			gpio@e000 {
-			};
-
-			gpio@e100 {
-			};
-
-			gpio@e200 {
-			};
-
-			gpio@e300 {
-			};
-		};
-
-		pm8941_mpps: pm8941_mpps {
-
-			mpp@a000 {
-			};
-
-			mpp@a100 {
-			};
-
-			mpp@a200 {
-			};
-
-			mpp@a300 {
-			};
-
-			mpp@a400 {
-				/* SPI_ETH config */
-				qcom,mode = <1>; /* DIG_OUT */
-				qcom,output-type = <0>; /* CMOS */
-				qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-				qcom,src-select = <0>; /* CONSTANT */
-				qcom,master-en = <1>; /* ENABLE MPP */
-			};
-
-			mpp@a500 {
-				/* SPI_ETH_RST config */
-				qcom,mode = <1>; /* DIG_OUT */
-				qcom,output-type = <0>; /* CMOS */
-				qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
-				qcom,src-select = <0>; /* CONSTANT */
-				qcom,master-en = <1>; /* ENABLE MPP */
-			};
-
-			mpp@a600 {
-			};
-
-			mpp@a700 {
-			};
-		};
-	};
-
-	qcom,pm8841@4 {
-
-		pm8841_mpps: pm8841_mpps {
-
-			mpp@a000 {
-			};
-
-			mpp@a100 {
-			};
-
-			mpp@a200 {
-			};
-
-			mpp@a300 {
-			};
-		};
-	};
-};
diff --git a/arch/arm/boot/dts/msm8974-liquid.dts b/arch/arm/boot/dts/msm8974-liquid.dts
index 5de2d43..2abc1d5 100644
--- a/arch/arm/boot/dts/msm8974-liquid.dts
+++ b/arch/arm/boot/dts/msm8974-liquid.dts
@@ -24,4 +24,195 @@
 	};
 };
 
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
 
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974-mtp.dts b/arch/arm/boot/dts/msm8974-mtp.dts
index ed89368..e183d04 100644
--- a/arch/arm/boot/dts/msm8974-mtp.dts
+++ b/arch/arm/boot/dts/msm8974-mtp.dts
@@ -167,3 +167,196 @@
 	interrupt-names = "core_irq", "bam_irq", "status_irq";
 	cd-gpios = <&msmgpio 62 0x1>;
 };
+
+&pm8941_gpios {
+	gpio@c000 { /* GPIO 1 */
+	};
+
+	gpio@c100 { /* GPIO 2 */
+	};
+
+	gpio@c200 { /* GPIO 3 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c300 { /* GPIO 4 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c400 { /* GPIO 5 */
+		qcom,mode = <0>;
+		qcom,pull = <0>;
+		qcom,vin-sel = <2>;
+		qcom,select = <0>;
+	};
+
+	gpio@c500 { /* GPIO 6 */
+	};
+
+	gpio@c600 { /* GPIO 7 */
+	};
+
+	gpio@c700 { /* GPIO 8 */
+	};
+
+	gpio@c800 { /* GPIO 9 */
+	};
+
+	gpio@c900 { /* GPIO 10 */
+	};
+
+	gpio@ca00 { /* GPIO 11 */
+	};
+
+	gpio@cb00 { /* GPIO 12 */
+	};
+
+	gpio@cc00 { /* GPIO 13 */
+	};
+
+	gpio@cd00 { /* GPIO 14 */
+	};
+
+	gpio@ce00 { /* GPIO 15 */
+		qcom,mode = <1>;
+		qcom,output-type = <0>;
+		qcom,pull = <5>;
+		qcom,vin-sel = <2>;
+		qcom,out-strength = <3>;
+		qcom,src-select = <2>;
+		qcom,master-en = <1>;
+	};
+
+	gpio@cf00 { /* GPIO 16 */
+	};
+
+	gpio@d000 { /* GPIO 17 */
+	};
+
+	gpio@d100 { /* GPIO 18 */
+	};
+
+	gpio@d200 { /* GPIO 19 */
+		qcom,mode = <1>;		/* QPNP_PIN_MODE_DIG_OUT */
+		qcom,output-type = <0>;		/* QPNP_PIN_OUT_BUF_CMOS */
+		qcom,pull = <5>;		/* QPNP_PIN_PULL_NO */
+		qcom,vin-sel = <2>;		/* QPNP_PIN_VIN2 */
+		qcom,out-strength = <2>;	/* QPNP_PIN_OUT_STRENGTH_MED */
+		qcom,src-select = <0>;		/* QPNP_PIN_SEL_FUNC_CONSTANT */
+		qcom,master-en = <1>;
+	};
+
+	gpio@d300 { /* GPIO 20 */
+	};
+
+	gpio@d400 { /* GPIO 21 */
+	};
+
+	gpio@d500 { /* GPIO 22 */
+	};
+
+	gpio@d600 { /* GPIO 23 */
+	};
+
+	gpio@d700 { /* GPIO 24 */
+	};
+
+	gpio@d800 { /* GPIO 25 */
+	};
+
+	gpio@d900 { /* GPIO 26 */
+	};
+
+	gpio@da00 { /* GPIO 27 */
+	};
+
+	gpio@db00 { /* GPIO 28 */
+	};
+
+	gpio@dc00 { /* GPIO 29 */
+		qcom,pull = <0>; /* set to default pull */
+		qcom,master-en = <1>;
+		qcom,vin-sel = <2>; /* select 1.8 V source */
+	};
+
+	gpio@dd00 { /* GPIO 30 */
+	};
+
+	gpio@de00 { /* GPIO 31 */
+	};
+
+	gpio@df00 { /* GPIO 32 */
+	};
+
+	gpio@e000 { /* GPIO 33 */
+	};
+
+	gpio@e100 { /* GPIO 34 */
+	};
+
+	gpio@e200 { /* GPIO 35 */
+	};
+
+	gpio@e300 { /* GPIO 36 */
+	};
+};
+
+&pm8941_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+
+	mpp@a400 { /* MPP 5 */
+		/* SPI_ETH config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a500 { /* MPP 6 */
+		/* SPI_ETH_RST config */
+		qcom,mode = <1>; /* DIG_OUT */
+		qcom,output-type = <0>; /* CMOS */
+		qcom,vin-sel = <2>; /* PM8941_S3 1.8V > 1.6V */
+		qcom,src-select = <0>; /* CONSTANT */
+		qcom,master-en = <1>; /* ENABLE MPP */
+	};
+
+	mpp@a600 { /* MPP 7 */
+	};
+
+	mpp@a700 { /* MPP 8 */
+	};
+};
+
+&pm8841_mpps {
+
+	mpp@a000 { /* MPP 1 */
+	};
+
+	mpp@a100 { /* MPP 2 */
+	};
+
+	mpp@a200 { /* MPP 3 */
+	};
+
+	mpp@a300 { /* MPP 4 */
+	};
+};
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 9ed61ed..b992e86 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -239,6 +239,19 @@
 		qcom,bam-dma-res-pipes = <6>;
 	};
 
+	spi@f9966000 {
+		compatible = "qcom,spi-qup-v2";
+		cell-index = <7>;
+		reg = <0xf9966000 0x1000>;
+		interrupts = <0 104 0>;
+		spi-max-frequency = <19200000>;
+		#address-cells = <1>;
+		#size-cells = <0>;
+		gpios = <&msmgpio 56 0>, /* CLK  */
+			<&msmgpio 54 0>, /* MISO */
+			<&msmgpio 53 0>; /* MOSI */
+		cs-gpios = <&msmgpio 55 0>;
+	};
 
 	slim@fe12f000 {
 		cell-index = <1>;
@@ -1032,11 +1045,16 @@
 		reg = <0xfc834000 0x7000>;
 		interrupts = <0 29 1>;
 	};
+
+        qcom,msm-wdog-debug@fc401000 {
+               compatible = "qcom,msm-wdog-debug";
+               reg = <0xfc401000 0x1000>;
+        };
+
 };
 
 /include/ "msm-pm8x41-rpm-regulator.dtsi"
 /include/ "msm-pm8841.dtsi"
 /include/ "msm-pm8941.dtsi"
 /include/ "msm8974-regulator.dtsi"
-/include/ "msm8974-gpio.dtsi"
 /include/ "msm8974-clock.dtsi"
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index 77f2532..e39a72a 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -117,10 +117,9 @@
 		qcom,vctl-port = <0x0>;
 		qcom,phase-port = <0x1>;
 		qcom,saw2-spm-cmd-ret = [00 20 03 22 00 0f];
-		qcom,saw2-spm-cmd-gdhs = [00 20 32 0b 42 07 44 22 50 02 32 50
-				0f];
-		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 0b 42 07 01 b0 12 44 a0
-				50 02 32 a0 50 0f];
+		qcom,saw2-spm-cmd-gdhs = [00 20 32 42 07 44 22 50 02 32 50 0f];
+		qcom,saw2-spm-cmd-pc = [00 10 32 b0 11 42 07 01 b0 12 44
+				50 02 32 50 0f];
 	};
 
 	qcom,lpm-resources {
diff --git a/arch/arm/configs/msm8960-perf_defconfig b/arch/arm/configs/msm8960-perf_defconfig
index 3fdc804..45d52e4 100644
--- a/arch/arm/configs/msm8960-perf_defconfig
+++ b/arch/arm/configs/msm8960-perf_defconfig
@@ -506,3 +506,4 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CONTROL_TRACE=m
diff --git a/arch/arm/configs/msm8960_defconfig b/arch/arm/configs/msm8960_defconfig
index 4daaa12..465598f 100644
--- a/arch/arm/configs/msm8960_defconfig
+++ b/arch/arm/configs/msm8960_defconfig
@@ -524,3 +524,4 @@
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
 CONFIG_WCNSS_MEM_PRE_ALLOC=y
+CONFIG_CONTROL_TRACE=m
diff --git a/arch/arm/configs/msm8974-perf_defconfig b/arch/arm/configs/msm8974-perf_defconfig
index 47f9ba3..2f1833e 100644
--- a/arch/arm/configs/msm8974-perf_defconfig
+++ b/arch/arm/configs/msm8974-perf_defconfig
@@ -402,3 +402,4 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
diff --git a/arch/arm/configs/msm8974_defconfig b/arch/arm/configs/msm8974_defconfig
index f6e51af..1230fbe 100644
--- a/arch/arm/configs/msm8974_defconfig
+++ b/arch/arm/configs/msm8974_defconfig
@@ -398,7 +398,6 @@
 CONFIG_DEBUG_KMEMLEAK_DEFAULT_OFF=y
 # CONFIG_DEBUG_PREEMPT is not set
 CONFIG_DEBUG_SPINLOCK=y
-CONFIG_DEBUG_MUTEXES=y
 CONFIG_DEBUG_ATOMIC_SLEEP=y
 CONFIG_DEBUG_STACK_USAGE=y
 CONFIG_DEBUG_INFO=y
@@ -422,3 +421,4 @@
 CONFIG_CRYPTO_DEV_QCE=m
 CONFIG_CRYPTO_DEV_QCEDEV=m
 CONFIG_CRC_CCITT=y
+CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL=y
diff --git a/arch/arm/configs/msm9625_defconfig b/arch/arm/configs/msm9625_defconfig
index 4cb3f6b..364a1bf 100644
--- a/arch/arm/configs/msm9625_defconfig
+++ b/arch/arm/configs/msm9625_defconfig
@@ -146,11 +146,3 @@
 # CONFIG_CRYPTO_HW is not set
 CONFIG_CRC_CCITT=y
 CONFIG_LIBCRC32C=y
-CONFIG_MMC=y
-CONFIG_MMC_PERF_PROFILING=y
-CONFIG_MMC_CLKGATE=y
-CONFIG_MMC_PARANOID_SD_INIT=y
-CONFIG_MMC_BLOCK_MINORS=32
-CONFIG_MMC_TEST=m
-CONFIG_MMC_MSM=y
-CONFIG_MMC_MSM_SPS_SUPPORT=y
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index a551d3c..157f159 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -1903,7 +1903,7 @@
 
 config MSM_PIL_MODEM
 	tristate "Modem (ARM11) Boot Support"
-	depends on MSM_PIL
+	depends on MSM_PIL && MSM_SUBSYSTEM_RESTART
 	help
 	  Support for booting and shutting down ARM11 Modem processors.
 
@@ -2643,4 +2643,12 @@
 	 such as display backlight, vreg pin-ctrl, smps clock over the RPC
 	 interface. This support is required for MSMs on which the APPS
 	 does not have a direct access to the PMIC.
+
+config MSM_ENABLE_WDOG_DEBUG_CONTROL
+	bool "MSM Watchdog driver to disable debug Image"
+	help
+	 This driver supports the configuration of the GCC_WDOG_DEBUG register
+	 used to control debug image.
+	 This support is currently required for MSM8974 to disable debug image
+	 on PS HOLD reset
 endif
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index a2151d5..1b42d2d 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -65,6 +65,8 @@
 $(obj)/smd_rpc_sym.c: $(src)/smd_rpc_sym $(src)/mkrpcsym.pl
 	$(call if_changed,mkrpcsym)
 
+obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o
+
 obj-$(CONFIG_MSM_SCM) += scm.o scm-boot.o
 obj-$(CONFIG_MSM_SECURE_IO) += scm-io.o
 obj-$(CONFIG_MSM_PIL) += peripheral-loader.o
@@ -96,7 +98,6 @@
 ifdef CONFIG_DEBUG_FS
 obj-$(CONFIG_MSM_IPC_LOGGING) += ipc_logging_debug.o
 endif
-obj-$(CONFIG_MSM_SMD) += smd.o smd_debug.o remote_spinlock.o smd_private.o
 obj-y += socinfo.o
 ifndef CONFIG_ARCH_MSM8960
 ifndef CONFIG_ARCH_MSM8X60
@@ -194,7 +195,7 @@
 	obj-y += subsystem_notif.o
 	obj-y += subsystem_restart.o
 	obj-y += ramdump.o
-	obj-$(CONFIG_ARCH_MSM8X60) += modem-8660.o lpass-8660.o
+	obj-$(CONFIG_ARCH_MSM8X60) += lpass-8660.o
 endif
 obj-$(CONFIG_MSM_SYSMON_COMM) += sysmon.o
 obj-$(CONFIG_MSM_MODEM_8960) += modem-8960.o
@@ -288,7 +289,6 @@
 obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
 obj-$(CONFIG_ARCH_MSM8974) += krait-regulator.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
-obj-$(CONFIG_ARCH_MSM9625) += clock-local2.o clock-pll.o clock-9625.o clock-rpm.o clock-voter.o
 obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o acpuclock-8930aa.o
 obj-$(CONFIG_ARCH_MPQ8092) += board-8092.o board-8092-gpiomux.o
 obj-$(CONFIG_ARCH_MSM8226) += board-8226.o board-8226-gpiomux.o
@@ -384,6 +384,7 @@
 obj-$(CONFIG_MSM_RPC_USB) += rpc_hsusb.o rpc_fsusb.o
 obj-$(CONFIG_MSM_RPC_PMAPP) += rpc_pmapp.o
 
+obj-$(CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL) += wdog_debug.o
 
 ifdef CONFIG_MSM_CPR
 obj-$(CONFIG_DEBUG_FS) += msm_cpr-debug.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
index d0de62b..d10211bc 100644
--- a/arch/arm/mach-msm/acpuclock-8064.c
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -18,6 +18,7 @@
 #include <mach/msm_bus_board.h>
 #include <mach/msm_bus.h>
 
+#include "mach/socinfo.h"
 #include "acpuclock.h"
 #include "acpuclock-krait.h"
 
@@ -94,6 +95,10 @@
 	},
 };
 
+/*
+ * The correct maximum rate for 8064ab in 600 MHZ.
+ * We rely on the RPM rounding requests up here.
+*/
 static struct msm_bus_paths bw_level_tbl[] __initdata = {
 	[0] =  BW_MBPS(640), /* At least  80 MHz on bus. */
 	[1] = BW_MBPS(1064), /* At least 133 MHz on bus. */
@@ -110,7 +115,7 @@
 	.name = "acpuclk-8064",
 };
 
-static struct l2_level l2_freq_tbl[] __initdata __initdata = {
+static struct l2_level l2_freq_tbl[] __initdata = {
 	[0]  = { {  384000, PLL_8, 0, 0x00 }, 1050000, 1050000, 1 },
 	[1]  = { {  432000, HFPLL, 2, 0x20 }, 1050000, 1050000, 2 },
 	[2]  = { {  486000, HFPLL, 2, 0x24 }, 1050000, 1050000, 2 },
@@ -127,10 +132,12 @@
 	[13] = { { 1080000, HFPLL, 1, 0x28 }, 1150000, 1150000, 5 },
 	[14] = { { 1134000, HFPLL, 1, 0x2A }, 1150000, 1150000, 5 },
 	[15] = { { 1188000, HFPLL, 1, 0x2C }, 1150000, 1150000, 5 },
+	/* L2 Level 16 is for 8064ab only */
+	[16] = { { 1242000, HFPLL, 1, 0x2E }, 1150000, 1150000, 5 },
 	{ }
 };
 
-static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
+static struct acpu_level tbl_slow[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
 	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   975000 },
 	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   975000 },
@@ -156,7 +163,7 @@
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
+static struct acpu_level tbl_nom[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   900000 },
 	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   925000 },
 	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   925000 },
@@ -182,7 +189,7 @@
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
+static struct acpu_level tbl_fast[] __initdata = {
 	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   850000 },
 	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   875000 },
 	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   875000 },
@@ -208,12 +215,91 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 },
-[PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
-/* TODO: update the faster table when data is available */
-[PVS_FASTER]  = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct acpu_level tbl_slow_1p7[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
+	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   975000 },
+	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(6),  1000000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),  1000000 },
+	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(6),  1025000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),  1025000 },
+	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(6),  1075000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),  1075000 },
+	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(6),  1100000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),  1100000 },
+	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(6),  1125000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1125000 },
+	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1175000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1175000 },
+	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1200000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1200000 },
+	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(15), 1225000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1225000 },
+	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(15), 1237500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1237500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1250000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1250000 },
+	{ 1, {  1620000, HFPLL, 1, 0x3C }, L2(15), 1250000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1250000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level tbl_slow_2p0[] __initdata = {
+	{ 1, {   384000, PLL_8, 0, 0x00 }, L2(0),   950000 },
+	{ 0, {   432000, HFPLL, 2, 0x20 }, L2(6),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0x24 }, L2(6),   975000 },
+	{ 0, {   540000, HFPLL, 2, 0x28 }, L2(6),  1000000 },
+	{ 1, {   594000, HFPLL, 1, 0x16 }, L2(6),  1000000 },
+	{ 0, {   648000, HFPLL, 1, 0x18 }, L2(6),  1025000 },
+	{ 1, {   702000, HFPLL, 1, 0x1A }, L2(6),  1025000 },
+	{ 0, {   756000, HFPLL, 1, 0x1C }, L2(6),  1075000 },
+	{ 1, {   810000, HFPLL, 1, 0x1E }, L2(6),  1075000 },
+	{ 0, {   864000, HFPLL, 1, 0x20 }, L2(6),  1100000 },
+	{ 1, {   918000, HFPLL, 1, 0x22 }, L2(6),  1100000 },
+	{ 0, {   972000, HFPLL, 1, 0x24 }, L2(6),  1125000 },
+	{ 1, {  1026000, HFPLL, 1, 0x26 }, L2(6),  1125000 },
+	{ 0, {  1080000, HFPLL, 1, 0x28 }, L2(15), 1175000 },
+	{ 1, {  1134000, HFPLL, 1, 0x2A }, L2(15), 1175000 },
+	{ 0, {  1188000, HFPLL, 1, 0x2C }, L2(15), 1200000 },
+	{ 1, {  1242000, HFPLL, 1, 0x2E }, L2(15), 1200000 },
+	{ 0, {  1296000, HFPLL, 1, 0x30 }, L2(15), 1225000 },
+	{ 1, {  1350000, HFPLL, 1, 0x32 }, L2(15), 1225000 },
+	{ 0, {  1404000, HFPLL, 1, 0x34 }, L2(15), 1237500 },
+	{ 1, {  1458000, HFPLL, 1, 0x36 }, L2(15), 1237500 },
+	{ 1, {  1512000, HFPLL, 1, 0x38 }, L2(15), 1250000 },
+	{ 1, {  1566000, HFPLL, 1, 0x3A }, L2(15), 1250000 },
+	{ 1, {  1620000, HFPLL, 1, 0x3C }, L2(15), 1250000 },
+	{ 1, {  1674000, HFPLL, 1, 0x3E }, L2(15), 1250000 },
+	{ 1, {  1728000, HFPLL, 1, 0x40 }, L2(15), 1250000 },
+	{ 1, {  1782000, HFPLL, 1, 0x42 }, L2(15), 1250000 },
+	{ 1, {  1836000, HFPLL, 1, 0x44 }, L2(15), 1250000 },
+	{ 1, {  1890000, HFPLL, 1, 0x46 }, L2(15), 1250000 },
+	{ 1, {  1944000, HFPLL, 1, 0x48 }, L2(15), 1250000 },
+	{ 1, {  1998000, HFPLL, 1, 0x4A }, L2(15), 1250000 },
+	{ 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+	[0][PVS_SLOW]    = {tbl_slow, sizeof(tbl_slow),     0 },
+	[0][PVS_NOMINAL] = {tbl_nom,  sizeof(tbl_nom),  25000 },
+	[0][PVS_FAST]    = {tbl_fast, sizeof(tbl_fast), 25000 },
+	[0][PVS_FASTER]  = {tbl_fast, sizeof(tbl_fast), 25000 },
+
+	[1][0] = { tbl_slow_1p7, sizeof(tbl_slow_1p7),     0 },
+	[1][1] = { tbl_slow_1p7, sizeof(tbl_slow_1p7),     0 },
+	[1][2] = { tbl_slow_1p7, sizeof(tbl_slow_1p7),     0 },
+	[1][3] = { tbl_slow_1p7, sizeof(tbl_slow_1p7),     0 },
+	[1][4] = { tbl_slow_1p7, sizeof(tbl_slow_1p7),     0 },
+	[1][5] = { tbl_slow_1p7, sizeof(tbl_slow_1p7),     0 },
+	[1][6] = { tbl_slow_1p7, sizeof(tbl_slow_1p7),     0 },
+
+	[2][0] = { tbl_slow_2p0, sizeof(tbl_slow_2p0),     0 },
+	[2][1] = { tbl_slow_2p0, sizeof(tbl_slow_2p0),     0 },
+	[2][2] = { tbl_slow_2p0, sizeof(tbl_slow_2p0),     0 },
+	[2][3] = { tbl_slow_2p0, sizeof(tbl_slow_2p0),     0 },
+	[2][4] = { tbl_slow_2p0, sizeof(tbl_slow_2p0),     0 },
+	[2][5] = { tbl_slow_2p0, sizeof(tbl_slow_2p0),     0 },
+	[2][6] = { tbl_slow_2p0, sizeof(tbl_slow_2p0),     0 },
 };
 
 static struct acpuclk_krait_params acpuclk_8064_params __initdata = {
@@ -230,6 +316,12 @@
 
 static int __init acpuclk_8064_probe(struct platform_device *pdev)
 {
+	if (cpu_is_apq8064ab() ||
+		SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) {
+		acpuclk_8064_params.hfpll_data->low_vdd_l_max = 37;
+		acpuclk_8064_params.hfpll_data->nom_vdd_l_max = 74;
+	}
+
 	return acpuclk_krait_init(&pdev->dev, &acpuclk_8064_params);
 }
 
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index da49656..ac29cac 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -127,10 +127,10 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-	[PVS_SLOW]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl),     0 },
-	[PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
-	[PVS_FAST]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+	[0][PVS_SLOW]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl),     0 },
+	[0][PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
+	[0][PVS_FAST]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl), 25000 },
 };
 
 static struct acpuclk_krait_params acpuclk_8627_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index b4f2a1e..e46599a 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -213,10 +213,10 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 },
-[PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 },
+[0][PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
 };
 
 static struct acpuclk_krait_params acpuclk_8930_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8930aa.c b/arch/arm/mach-msm/acpuclock-8930aa.c
index bcb00ea..9d2b6fc 100644
--- a/arch/arm/mach-msm/acpuclock-8930aa.c
+++ b/arch/arm/mach-msm/acpuclock-8930aa.c
@@ -189,10 +189,10 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 },
-[PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 },
+[0][PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
 };
 
 static struct acpuclk_krait_params acpuclk_8930aa_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index cf6a6c2..d7d3edd 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -195,10 +195,10 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 },
-[PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),     0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom),  25000 },
+[0][PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast), 25000 },
 };
 
 static struct acpuclk_krait_params acpuclk_8960_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8960ab.c b/arch/arm/mach-msm/acpuclock-8960ab.c
index 91ccd37..ae1cd7b 100644
--- a/arch/arm/mach-msm/acpuclock-8960ab.c
+++ b/arch/arm/mach-msm/acpuclock-8960ab.c
@@ -135,10 +135,10 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
-[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),  0 },
-[PVS_NOMINAL] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),  0 },
-[PVS_FAST]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),  0 },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS] __initdata = {
+[0][PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),  0 },
+[0][PVS_NOMINAL] = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),  0 },
+[0][PVS_FAST]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow),  0 },
 };
 
 static struct acpuclk_krait_params acpuclk_8960ab_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 4a755bd..098f854 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -170,10 +170,10 @@
 	{ 0, { 0 } }
 };
 
-static struct pvs_table pvs_tables[NUM_PVS]  __initdata = {
-	[PVS_SLOW]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
-	[PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl)  },
-	[PVS_FAST]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+static struct pvs_table pvs_tables[NUM_SPEED_BINS][NUM_PVS]  __initdata = {
+	[0][PVS_SLOW]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+	[0][PVS_NOMINAL] = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
+	[0][PVS_FAST]    = { acpu_freq_tbl, sizeof(acpu_freq_tbl) },
 };
 
 static struct acpuclk_krait_params acpuclk_8974_params __initdata = {
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 79c01b2..57c4411 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -946,58 +946,68 @@
 	}
 }
 
-static int __init select_freq_plan(u32 pte_efuse_phys)
+static int __init get_speed_bin(u32 pte_efuse)
+{
+	uint32_t speed_bin;
+
+	speed_bin = pte_efuse & 0xF;
+	if (speed_bin == 0xF)
+		speed_bin = (pte_efuse >> 4) & 0xF;
+
+	if (speed_bin == 0xF) {
+		speed_bin = 0;
+		dev_warn(drv.dev, "SPEED BIN: Defaulting to %d\n", speed_bin);
+	} else {
+		dev_info(drv.dev, "SPEED BIN: %d\n", speed_bin);
+	}
+
+	return speed_bin;
+}
+
+static int __init get_pvs_bin(u32 pte_efuse)
+{
+	uint32_t pvs_bin;
+
+	pvs_bin = (pte_efuse >> 10) & 0x7;
+	if (pvs_bin == 0x7)
+		pvs_bin = (pte_efuse >> 13) & 0x7;
+
+	if (pvs_bin == 0x7) {
+		pvs_bin = 0;
+		dev_warn(drv.dev, "ACPU PVS: Defaulting to %d\n", pvs_bin);
+	} else {
+		dev_info(drv.dev, "ACPU PVS: %d\n", pvs_bin);
+	}
+
+	return pvs_bin;
+}
+
+static struct pvs_table * __init select_freq_plan(u32 pte_efuse_phys,
+			struct pvs_table (*pvs_tables)[NUM_PVS])
 {
 	void __iomem *pte_efuse;
-	u32 pte_efuse_val, pvs, tbl_idx;
-	char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
+	u32 pte_efuse_val, tbl_idx, bin_idx;
 
 	pte_efuse = ioremap(pte_efuse_phys, 4);
-	/* Select frequency tables. */
-	if (pte_efuse) {
-		pte_efuse_val = readl_relaxed(pte_efuse);
-		pvs = (pte_efuse_val >> 10) & 0x7;
-		iounmap(pte_efuse);
-		if (pvs == 0x7)
-			pvs = (pte_efuse_val >> 13) & 0x7;
-
-		switch (pvs) {
-		case 0x0:
-		case 0x7:
-			tbl_idx = PVS_SLOW;
-			break;
-		case 0x1:
-			tbl_idx = PVS_NOMINAL;
-			break;
-		case 0x3:
-			tbl_idx = PVS_FAST;
-			break;
-		case 0x4:
-			tbl_idx = PVS_FASTER;
-			break;
-		default:
-			tbl_idx = PVS_UNKNOWN;
-			break;
-		}
-	} else {
-		tbl_idx = PVS_UNKNOWN;
+	if (!pte_efuse) {
 		dev_err(drv.dev, "Unable to map QFPROM base\n");
-	}
-	if (tbl_idx == PVS_UNKNOWN) {
-		tbl_idx = PVS_SLOW;
-		dev_warn(drv.dev, "ACPU PVS: Defaulting to %s\n",
-			 pvs_names[tbl_idx]);
-	} else {
-		dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
+		return NULL;
 	}
 
-	return tbl_idx;
+	pte_efuse_val = readl_relaxed(pte_efuse);
+	iounmap(pte_efuse);
+
+	/* Select frequency tables. */
+	bin_idx = get_speed_bin(pte_efuse_val);
+	tbl_idx = get_pvs_bin(pte_efuse_val);
+
+	return &pvs_tables[bin_idx][tbl_idx];
 }
 
 static void __init drv_data_init(struct device *dev,
 				 const struct acpuclk_krait_params *params)
 {
-	int tbl_idx;
+	struct pvs_table *pvs;
 
 	drv.dev = dev;
 	drv.scalable = kmemdup(params->scalable, params->scalable_size,
@@ -1020,12 +1030,12 @@
 		GFP_KERNEL);
 	BUG_ON(!drv.bus_scale->usecase);
 
-	tbl_idx = select_freq_plan(params->pte_efuse_phys);
-	drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
-				    params->pvs_tables[tbl_idx].size,
-				    GFP_KERNEL);
+	pvs = select_freq_plan(params->pte_efuse_phys, params->pvs_tables);
+	BUG_ON(!pvs->table);
+
+	drv.acpu_freq_tbl = kmemdup(pvs->table, pvs->size, GFP_KERNEL);
 	BUG_ON(!drv.acpu_freq_tbl);
-	drv.boost_uv = params->pvs_tables[tbl_idx].boost_uv;
+	drv.boost_uv = pvs->boost_uv;
 
 	acpuclk_krait_data.power_collapse_khz = params->stby_khz;
 	acpuclk_krait_data.wait_for_irq_khz = params->stby_khz;
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index 84a5b5e..3fa10e3 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -46,14 +46,18 @@
  */
 enum pvs {
 	PVS_SLOW = 0,
-	PVS_NOMINAL,
-	PVS_FAST,
-	PVS_FASTER,
-	PVS_UNKNOWN,
-	NUM_PVS
+	PVS_NOMINAL = 1,
+	PVS_FAST = 3,
+	PVS_FASTER = 4,
+	NUM_PVS = 7
 };
 
 /**
+ * The maximum number of speed bins.
+ */
+#define NUM_SPEED_BINS (16)
+
+/**
  * enum scalables - IDs of frequency scalable hardware blocks.
  */
 enum scalables {
@@ -186,8 +190,8 @@
 	const bool has_droop_ctl;
 	const u32 droop_offset;
 	const u32 droop_val;
-	const u32 low_vdd_l_max;
-	const u32 nom_vdd_l_max;
+	u32 low_vdd_l_max;
+	u32 nom_vdd_l_max;
 	const u32 low_vco_l_max;
 	const int vdd[NUM_HFPLL_VDD];
 };
@@ -237,7 +241,7 @@
  * @scalable: Array of scalables.
  * @scalable_size: Size of @scalable.
  * @hfpll_data: HFPLL configuration data.
- * @pvs_tables: CPU frequency tables.
+ * @pvs_tables: 2D array of CPU frequency tables.
  * @l2_freq_tbl: L2 frequency table.
  * @l2_freq_tbl_size: Size of @l2_freq_tbl.
  * @pte_efuse_phys: Physical address of PTE EFUSE.
@@ -248,7 +252,7 @@
 	struct scalable *scalable;
 	size_t scalable_size;
 	struct hfpll_data *hfpll_data;
-	struct pvs_table *pvs_tables;
+	struct pvs_table (*pvs_tables)[NUM_PVS];
 	struct l2_level *l2_freq_tbl;
 	size_t l2_freq_tbl_size;
 	phys_addr_t pte_efuse_phys;
diff --git a/arch/arm/mach-msm/board-8064-gpiomux.c b/arch/arm/mach-msm/board-8064-gpiomux.c
index a08f45c..cb03d4b 100644
--- a/arch/arm/mach-msm/board-8064-gpiomux.c
+++ b/arch/arm/mach-msm/board-8064-gpiomux.c
@@ -31,6 +31,7 @@
 	.drv = GPIOMUX_DRV_8MA,
 	.func = GPIOMUX_FUNC_GPIO,
 };
+#endif
 
 /* The SPI configurations apply to GSBI 5*/
 static struct gpiomux_setting gpio_spi_config = {
@@ -60,6 +61,7 @@
 	.pull = GPIOMUX_PULL_UP,
 };
 
+#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 struct msm_gpiomux_config apq8064_ethernet_configs[] = {
 	{
 		.gpio = 43,
@@ -361,6 +363,22 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting audio_auxpcm[] = {
+/* Suspended state */
+	{
+		.func = GPIOMUX_FUNC_GPIO,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+/* Active state */
+	{
+		.func = GPIOMUX_FUNC_1,
+		.drv = GPIOMUX_DRV_2MA,
+		.pull = GPIOMUX_PULL_NONE,
+	},
+};
+
+
 static struct gpiomux_setting wcnss_5wire_suspend_cfg = {
 	.func = GPIOMUX_FUNC_GPIO,
 	.drv  = GPIOMUX_DRV_2MA,
@@ -682,7 +700,6 @@
 			[GPIOMUX_SUSPENDED] = &gsbi1_uart_config,
 		},
 	},
-#if defined(CONFIG_KS8851) || defined(CONFIG_KS8851_MODULE)
 	{
 		.gpio      = 51,		/* GSBI5 QUP SPI_DATA_MOSI */
 		.settings = {
@@ -713,7 +730,6 @@
 			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
 		},
 	},
-#endif
 	{
 		.gpio      = 30,		/* FP CS */
 		.settings = {
@@ -846,6 +862,37 @@
 	},
 };
 
+static struct msm_gpiomux_config mpq8064_audio_auxpcm_configs[] __initdata = {
+	{
+		.gpio = 43,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+			[GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+		},
+	},
+	{
+		.gpio = 44,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+			[GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+		},
+	},
+	{
+		.gpio = 45,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+			[GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+		},
+	},
+	{
+		.gpio = 46,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &audio_auxpcm[0],
+			[GPIOMUX_ACTIVE] = &audio_auxpcm[1],
+		},
+	},
+};
+
 /* External 3.3 V regulator enable */
 static struct msm_gpiomux_config apq8064_ext_regulator_configs[] __initdata = {
 	{
@@ -1527,6 +1574,10 @@
 
 	if (machine_is_mpq8064_cdp() || machine_is_mpq8064_hrd() ||
 		machine_is_mpq8064_dtv()) {
+
+		msm_gpiomux_install(mpq8064_audio_auxpcm_configs,
+			ARRAY_SIZE(mpq8064_audio_auxpcm_configs));
+
 		msm_gpiomux_install(mpq8064_spkr_i2s_config,
 			ARRAY_SIZE(mpq8064_spkr_i2s_config));
 	}
diff --git a/arch/arm/mach-msm/board-8064-gpu.c b/arch/arm/mach-msm/board-8064-gpu.c
index 122505e..68debff 100644
--- a/arch/arm/mach-msm/board-8064-gpu.c
+++ b/arch/arm/mach-msm/board-8064-gpu.c
@@ -251,11 +251,17 @@
 {
 	unsigned int version = socinfo_get_version();
 
-	if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
-		(SOCINFO_VERSION_MINOR(version) == 1))
-		kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 1);
-	else
-		kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 0);
+	if (cpu_is_apq8064ab())
+		kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 450000000;
+	if (SOCINFO_VERSION_MAJOR(version) == 2) {
+		kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 2);
+	} else {
+		if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
+				(SOCINFO_VERSION_MINOR(version) == 1))
+			kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 1);
+		else
+			kgsl_3d0_pdata.chipid = ADRENO_CHIPID(3, 2, 0, 0);
+	}
 
 	platform_device_register(&device_kgsl_3d0);
 }
diff --git a/arch/arm/mach-msm/board-8064-storage.c b/arch/arm/mach-msm/board-8064-storage.c
index c81a637..379d7ae 100644
--- a/arch/arm/mach-msm/board-8064-storage.c
+++ b/arch/arm/mach-msm/board-8064-storage.c
@@ -338,6 +338,11 @@
 		apq8064_add_sdcc(2, apq8064_sdc2_pdata);
 
 	if (apq8064_sdc3_pdata) {
+		if (machine_is_mpq8064_hrd() || machine_is_mpq8064_dtv()) {
+			apq8064_sdc3_pdata->uhs_caps &= ~(MMC_CAP_UHS_SDR12 |
+				MMC_CAP_UHS_SDR25 | MMC_CAP_UHS_DDR50 |
+				MMC_CAP_UHS_SDR50 | MMC_CAP_UHS_SDR104);
+		}
 		if (!machine_is_apq8064_cdp()) {
 			apq8064_sdc3_pdata->wpswitch_gpio = 0;
 			apq8064_sdc3_pdata->is_wpswitch_active_low = false;
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 1efc64b..2fd1a68 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -1769,6 +1769,27 @@
 	},
 };
 
+static struct msm_bus_vectors qseecom_enable_dfab_sfpb_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT0,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ab = 70000000UL,
+		.ib = 70000000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_ADM_PORT1,
+		.dst = MSM_BUS_SLAVE_GSBI1_UART,
+		.ab = 2480000000UL,
+		.ib = 2480000000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = (64 * 8) * 1000000UL,
+		.ab = (64 * 8) *  100000UL,
+	},
+};
+
 static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
 	{
 		ARRAY_SIZE(qseecom_clks_init_vectors),
@@ -1782,6 +1803,10 @@
 		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
 		qseecom_enable_sfpb_vectors,
 	},
+	{
+		ARRAY_SIZE(qseecom_enable_dfab_sfpb_vectors),
+		qseecom_enable_dfab_sfpb_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata qseecom_bus_pdata = {
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index b84e66e..ed876c0 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -1048,6 +1048,27 @@
 	},
 };
 
+static struct msm_bus_vectors qseecom_enable_dfab_sfpb_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) *  100000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) *  100000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = (64 * 8) * 1000000UL,
+		.ab = (64 * 8) *  100000UL,
+	},
+};
+
 static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
 	{
 		ARRAY_SIZE(qseecom_clks_init_vectors),
@@ -1061,6 +1082,10 @@
 		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
 		qseecom_enable_sfpb_vectors,
 	},
+	{
+		ARRAY_SIZE(qseecom_enable_dfab_sfpb_vectors),
+		qseecom_enable_dfab_sfpb_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata qseecom_bus_pdata = {
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index d93a4fa..947b53f 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -1113,6 +1113,27 @@
 	},
 };
 
+static struct msm_bus_vectors qseecom_enable_dfab_sfpb_vectors[] = {
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_EBI_CH0,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) *  100000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPS,
+		.dst = MSM_BUS_SLAVE_SPS,
+		.ib = (492 * 8) * 1000000UL,
+		.ab = (492 * 8) * 100000UL,
+	},
+	{
+		.src = MSM_BUS_MASTER_SPDM,
+		.dst = MSM_BUS_SLAVE_SPDM,
+		.ib = (64 * 8) * 1000000UL,
+		.ab = (64 * 8) *  100000UL,
+	},
+};
+
 static struct msm_bus_paths qseecom_hw_bus_scale_usecases[] = {
 	{
 		ARRAY_SIZE(qseecom_clks_init_vectors),
@@ -1126,6 +1147,10 @@
 		ARRAY_SIZE(qseecom_enable_sfpb_vectors),
 		qseecom_enable_sfpb_vectors,
 	},
+	{
+		ARRAY_SIZE(qseecom_enable_dfab_sfpb_vectors),
+		qseecom_enable_dfab_sfpb_vectors,
+	},
 };
 
 static struct msm_bus_scale_pdata qseecom_bus_pdata = {
diff --git a/arch/arm/mach-msm/board-8974-gpiomux.c b/arch/arm/mach-msm/board-8974-gpiomux.c
index 1577a2b..8568340 100644
--- a/arch/arm/mach-msm/board-8974-gpiomux.c
+++ b/arch/arm/mach-msm/board-8974-gpiomux.c
@@ -271,6 +271,30 @@
 			[GPIOMUX_SUSPENDED] = &gpio_uart_config,
 		},
 	},
+	{
+		.gpio      = 53,		/* BLSP2 QUP4 SPI_DATA_MOSI */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 54,		/* BLSP2 QUP4 SPI_DATA_MISO */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 56,		/* BLSP2 QUP4 SPI_CLK */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
+	{
+		.gpio      = 55,		/* BLSP2 QUP4 SPI_CS0_N */
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gpio_spi_config,
+		},
+	},
 };
 
 static struct msm_gpiomux_config msm8974_slimbus_config[] __initdata = {
diff --git a/arch/arm/mach-msm/board-9625.c b/arch/arm/mach-msm/board-9625.c
index 5f556fb..797f5f1 100644
--- a/arch/arm/mach-msm/board-9625.c
+++ b/arch/arm/mach-msm/board-9625.c
@@ -103,7 +103,7 @@
 		pr_err("%s: socinfo_init() failed\n", __func__);
 
 	msm9625_init_gpiomux();
-	msm_clock_init(&msm9625_clock_init_data);
+	msm_clock_init(&msm_dummy_clock_init_data);
 	of_platform_populate(NULL, of_default_bus_match_table,
 			msm9625_auxdata_lookup, NULL);
 }
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 2a51e66..13c4be2 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -841,7 +841,7 @@
 static void __init msm8625_reserve(void)
 {
 	msm7x27a_reserve();
-	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+	memblock_remove(MSM8625_CPU_PHYS, SZ_8);
 	memblock_remove(MSM8625_WARM_BOOT_PHYS, SZ_32);
 }
 
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index 205db58..ee13e04 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -5190,7 +5190,7 @@
 
 	int bahama_not_marimba = bahama_present();
 
-	if (bahama_not_marimba == -1) {
+	if (bahama_not_marimba < 0) {
 		printk(KERN_WARNING "%s: bahama_present: %d\n",
 				__func__, bahama_not_marimba);
 		return -ENODEV;
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index ed1fafc..ec8e438 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -812,7 +812,7 @@
 
 static void __init msm8625_reserve(void)
 {
-	memblock_remove(MSM8625_SECONDARY_PHYS, SZ_8);
+	memblock_remove(MSM8625_CPU_PHYS, SZ_8);
 	msm7627a_reserve();
 }
 
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index b60f693..2cd2cd4 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -1534,6 +1534,11 @@
 static CLK_SDC(sdc4_clk, 4, 3,  33000000,  67000000);
 static CLK_SDC(sdc5_clk, 5, 2,  33000000,  67000000);
 
+static unsigned long fmax_sdc1_8064v2[MAX_VDD_LEVELS] __initdata = {
+	[VDD_DIG_LOW]     = 100000000,
+	[VDD_DIG_NOMINAL] = 200000000,
+};
+
 #define F_TSIF_REF(f, s, d, m, n) \
 	{ \
 		.freq_hz = f, \
@@ -1907,6 +1912,7 @@
 	F_CE3(        0, gnd,   1),
 	F_CE3( 48000000, pll8,  8),
 	F_CE3(100000000, pll3, 12),
+	F_CE3(120000000, pll3, 10),
 	F_END
 };
 
@@ -1929,6 +1935,11 @@
 	},
 };
 
+static unsigned long fmax_ce3_8064v2[MAX_VDD_LEVELS] __initdata = {
+	[VDD_DIG_LOW]     =  57000000,
+	[VDD_DIG_NOMINAL] = 120000000,
+};
+
 static struct branch_clk ce3_core_clk = {
 	.b = {
 		.ctl_reg = CE3_CORE_CLK_CTL_REG,
@@ -3540,11 +3551,12 @@
 	F_GFX3D(145455000, pll2,  2, 11),
 	F_GFX3D(160000000, pll2,  1,  5),
 	F_GFX3D(177778000, pll2,  2,  9),
+	F_GFX3D(192000000, pll8,  1,  2),
 	F_GFX3D(200000000, pll2,  1,  4),
 	F_GFX3D(228571000, pll2,  2,  7),
 	F_GFX3D(266667000, pll2,  1,  3),
-	F_GFX3D(325000000, pll15, 1,  3),
 	F_GFX3D(400000000, pll2,  1,  2),
+	F_GFX3D(450000000, pll15, 1,  2),
 	F_END
 };
 
@@ -3570,6 +3582,12 @@
 	F_END
 };
 
+static unsigned long fmax_gfx3d_8064ab[MAX_VDD_LEVELS] __initdata = {
+	[VDD_DIG_LOW]     = 128000000,
+	[VDD_DIG_NOMINAL] = 325000000,
+	[VDD_DIG_HIGH]    = 450000000
+};
+
 static unsigned long fmax_gfx3d_8064[MAX_VDD_LEVELS] __initdata = {
 	[VDD_DIG_LOW]     = 128000000,
 	[VDD_DIG_NOMINAL] = 325000000,
@@ -4295,6 +4313,7 @@
 	F_VCODEC(133330000, pll2, 1,  6),
 	F_VCODEC(200000000, pll2, 1,  4),
 	F_VCODEC(228570000, pll2, 2,  7),
+	F_VCODEC(266670000, pll2, 1,  3),
 	F_END
 };
 
@@ -4325,6 +4344,12 @@
 	},
 };
 
+static unsigned long fmax_vcodec_8064v2[MAX_VDD_LEVELS] __initdata = {
+	[VDD_DIG_LOW]     = 100000000,
+	[VDD_DIG_NOMINAL] = 200000000,
+	[VDD_DIG_HIGH]    = 266670000,
+};
+
 #define F_VPE(f, s, d) \
 	{ \
 		.freq_hz = f, \
@@ -5065,6 +5090,8 @@
 		writel_relaxed(0x80|BVAL(5, 3, clk_sel), GCC_APCS_CLK_DIAG);
 		measure->sample_ticks = 0x4000;
 		measure->multiplier = 2;
+		if (cpu_is_krait_v3())
+			measure->multiplier = 8;
 		break;
 	default:
 		ret = -EPERM;
@@ -6302,7 +6329,7 @@
 		writel_relaxed(0x3C7097F9, AHB_EN2_REG);
 	}
 
-	if (cpu_is_apq8064())
+	if (cpu_is_apq8064() || cpu_is_apq8064ab())
 		rmwreg(0x00000001, AHB_EN3_REG, 0x00000001);
 
 	/* Deassert all locally-owned MM AHB resets. */
@@ -6325,7 +6352,7 @@
 	rmwreg(0x0027FCFF, MAXI_EN3_REG, 0x003FFFFF);
 	rmwreg(0x0027FCFF, MAXI_EN4_REG, 0x017FFFFF);
 
-	if (cpu_is_apq8064())
+	if (cpu_is_apq8064() || cpu_is_apq8064ab())
 		rmwreg(0x019FECFF, MAXI_EN5_REG, 0x01FFEFFF);
 	if (cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627())
 		rmwreg(0x000004FF, MAXI_EN5_REG, 0x00000FFF);
@@ -6363,7 +6390,8 @@
 	rmwreg(0x80FF0000, VFE_CC_REG,        0xE0FF4010);
 	rmwreg(0x800000FF, VFE_CC2_REG,       0xE00000FF);
 	rmwreg(0x80FF0000, VPE_CC_REG,        0xE0FF0010);
-	if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064()) {
+	if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064()
+		 || cpu_is_apq8064ab()) {
 		rmwreg(0x80FF0000, DSI2_BYTE_CC_REG,  0xE0FF0010);
 		rmwreg(0x80FF0000, DSI2_PIXEL_CC_REG, 0xE0FF0010);
 		rmwreg(0x80FF0000, JPEGD_CC_REG,      0xE0FF0010);
@@ -6381,7 +6409,7 @@
 		rmwreg(0x80FF0000, GFX2D0_CC_REG,     0xE0FF0010);
 		rmwreg(0x80FF0000, GFX2D1_CC_REG,     0xE0FF0010);
 	}
-	if (cpu_is_apq8064()) {
+	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 		rmwreg(0x00000000, TV_CC_REG,         0x00004010);
 		rmwreg(0x80FF0000, VCAP_CC_REG,       0xE0FF1010);
 	}
@@ -6392,7 +6420,7 @@
 	 * and wake-up value to max.
 	 */
 	rmwreg(0x0000004F, USB_HS1_HCLK_FS_REG, 0x0000007F);
-	if (cpu_is_apq8064()) {
+	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 		rmwreg(0x0000004F, USB_HS3_HCLK_FS_REG, 0x0000007F);
 		rmwreg(0x0000004F, USB_HS4_HCLK_FS_REG, 0x0000007F);
 	}
@@ -6414,7 +6442,8 @@
 
 	/* Source the dsi_byte_clks from the DSI PHY PLLs */
 	rmwreg(0x1, DSI1_BYTE_NS_REG, 0x7);
-	if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064())
+	if (cpu_is_msm8960ab() || cpu_is_msm8960() || cpu_is_apq8064()
+		|| cpu_is_apq8064ab())
 		rmwreg(0x2, DSI2_BYTE_NS_REG, 0x7);
 
 	/* Source the dsi1_esc_clk from the DSI1 PHY PLLs */
@@ -6424,7 +6453,7 @@
 	 * Source the sata_phy_ref_clk from PXO and set predivider of
 	 * sata_pmalive_clk to 1.
 	 */
-	if (cpu_is_apq8064()) {
+	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 		rmwreg(0, SATA_PHY_REF_CLK_CTL_REG, 0x1);
 		rmwreg(0, SATA_PMALIVE_CLK_CTL_REG, 0x3);
 	}
@@ -6433,7 +6462,7 @@
 	 * TODO: Programming below PLLs and prng_clk is temporary and
 	 *	 needs to be removed after bootloaders program them.
 	 */
-	if (cpu_is_apq8064()) {
+	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 		u32 is_pll_enabled;
 
 		/* Program pxo_src_clk to source from PXO */
@@ -6445,9 +6474,6 @@
 			/* Ref clk = 27MHz and program pll14 to 480MHz */
 			configure_sr_pll(&pll14_config, &pll14_regs, 1);
 
-		/* Program PLL15 to 975MHz with ref clk = 27MHz */
-		configure_sr_pll(&pll15_config, &pll15_regs, 0);
-
 		/* Check if PLL4 is active */
 		is_pll_enabled = readl_relaxed(LCC_PLL0_STATUS_REG) & BIT(16);
 		if (!is_pll_enabled)
@@ -6462,6 +6488,17 @@
 			writel_relaxed(0x2B, PRNG_CLK_NS_REG);
 	}
 
+	if (cpu_is_apq8064()) {
+		/* Program PLL15 to 975MHz with ref clk = 27MHz */
+		configure_sr_pll(&pll15_config, &pll15_regs, 0);
+	} else if (cpu_is_apq8064ab()) {
+		/* Program PLL15 to 900MHZ */
+		pll15_config.l = 0x21 | BVAL(31, 7, 0x620);
+		pll15_config.m = 0x1;
+		pll15_config.n = 0x3;
+		configure_sr_pll(&pll15_config, &pll15_regs, 0);
+	}
+
 	/*
 	 * Program PLL15 to 900MHz with ref clk = 27MHz and
 	 * only enable PLL main output.
@@ -6482,7 +6519,7 @@
 	/* Initialize clock registers. */
 	reg_init();
 
-	if (cpu_is_apq8064())
+	if (cpu_is_apq8064() || cpu_is_apq8064ab())
 		vdd_sr2_hdmi_pll.set_vdd = set_vdd_sr2_hdmi_pll_8064;
 
 	/* Detect PLL4 programmed for alternate 491.52MHz clock plan. */
@@ -6524,13 +6561,32 @@
 	}
 	/*
 	 * Change the freq tables for and voltage requirements for
-	 * clocks which differ between 8960 and 8064.
+	 * clocks which differ between chips.
 	 */
 	if (cpu_is_apq8064()) {
 		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
 
 		memcpy(gfx3d_clk.c.fmax, fmax_gfx3d_8064,
 		       sizeof(gfx3d_clk.c.fmax));
+	}
+	if (cpu_is_apq8064ab()) {
+		gfx3d_clk.freq_tbl = clk_tbl_gfx3d_8064;
+
+		memcpy(gfx3d_clk.c.fmax, fmax_gfx3d_8064ab,
+		       sizeof(gfx3d_clk.c.fmax));
+	}
+	if ((cpu_is_apq8064() &&
+		SOCINFO_VERSION_MAJOR(socinfo_get_version()) == 2) ||
+		cpu_is_apq8064ab()) {
+
+		memcpy(vcodec_clk.c.fmax, fmax_vcodec_8064v2,
+			sizeof(vcodec_clk.c.fmax));
+		memcpy(ce3_src_clk.c.fmax, fmax_ce3_8064v2,
+			sizeof(ce3_src_clk.c.fmax));
+		memcpy(sdc1_clk.c.fmax, fmax_sdc1_8064v2,
+			sizeof(sdc1_clk.c.fmax));
+	}
+	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 		memcpy(ijpeg_clk.c.fmax, fmax_ijpeg_8064,
 		       sizeof(ijpeg_clk.c.fmax));
 		memcpy(mdp_clk.c.fmax, fmax_mdp_8064,
@@ -6606,7 +6662,7 @@
 	clk_set_rate(&tsif_ref_clk.c, 105000);
 	clk_set_rate(&tssc_clk.c, 27000000);
 	clk_set_rate(&usb_hs1_xcvr_clk.c, 60000000);
-	if (cpu_is_apq8064()) {
+	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 		clk_set_rate(&usb_hs3_xcvr_clk.c, 60000000);
 		clk_set_rate(&usb_hs4_xcvr_clk.c, 60000000);
 	}
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index a64e6a5..10de231 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -2183,6 +2183,18 @@
 	},
 };
 
+struct branch_clk gcc_sys_noc_usb3_axi_clk = {
+	.cbcr_reg = SYS_NOC_USB3_AXI_CBCR,
+	.parent = &usb30_master_clk_src.c,
+	.has_sibling = 1,
+	.base = &virt_bases[GCC_BASE],
+	.c = {
+		.dbg_name = "gcc_sys_noc_usb3_axi_clk",
+		.ops = &clk_ops_branch,
+		CLK_INIT(gcc_sys_noc_usb3_axi_clk.c),
+	},
+};
+
 static struct branch_clk gcc_usb30_master_clk = {
 	.cbcr_reg = USB30_MASTER_CBCR,
 	.bcr_reg = USB_30_BCR,
@@ -2193,6 +2205,7 @@
 		.dbg_name = "gcc_usb30_master_clk",
 		.ops = &clk_ops_branch,
 		CLK_INIT(gcc_usb30_master_clk.c),
+		.depends = &gcc_sys_noc_usb3_axi_clk.c,
 	},
 };
 
@@ -2207,18 +2220,6 @@
 	},
 };
 
-struct branch_clk gcc_sys_noc_usb3_axi_clk = {
-	.cbcr_reg = SYS_NOC_USB3_AXI_CBCR,
-	.parent = &usb30_master_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_sys_noc_usb3_axi_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_sys_noc_usb3_axi_clk.c),
-	},
-};
-
 struct branch_clk gcc_usb30_sleep_clk = {
 	.cbcr_reg = USB30_SLEEP_CBCR,
 	.has_sibling = 1,
@@ -5039,6 +5040,7 @@
 	CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
 
 	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9967000.i2c"),
+	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f9966000.spi"),
 	CLK_LOOKUP("iface_clk", gcc_blsp2_ahb_clk.c, "f995e000.serial"),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup1_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup1_spi_apps_clk.c, ""),
@@ -5047,8 +5049,8 @@
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup3_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup3_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup4_i2c_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp2_qup4_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup5_i2c_apps_clk.c, "f9967000.i2c"),
+	CLK_LOOKUP("core_clk", gcc_blsp2_qup4_spi_apps_clk.c, "f9966000.spi"),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup5_spi_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup6_i2c_apps_clk.c, ""),
 	CLK_LOOKUP("core_clk", gcc_blsp2_qup6_spi_apps_clk.c, ""),
diff --git a/arch/arm/mach-msm/clock-9625.c b/arch/arm/mach-msm/clock-9625.c
deleted file mode 100644
index a07eebb..0000000
--- a/arch/arm/mach-msm/clock-9625.c
+++ /dev/null
@@ -1,2278 +0,0 @@
-/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 and
- * only version 2 as published by the Free Software Foundation.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/err.h>
-#include <linux/ctype.h>
-#include <linux/io.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/clk.h>
-
-#include <mach/clk.h>
-#include <mach/rpm-regulator-smd.h>
-#include <mach/socinfo.h>
-
-#include "clock-local2.h"
-#include "clock-pll.h"
-#include "clock-rpm.h"
-#include "clock-voter.h"
-#include "clock.h"
-
-enum {
-	GCC_BASE,
-	LPASS_BASE,
-	APCS_BASE,
-	APCS_PLL_BASE,
-	N_BASES,
-};
-
-static void __iomem *virt_bases[N_BASES];
-
-#define GCC_REG_BASE(x) (void __iomem *)(virt_bases[GCC_BASE] + (x))
-#define LPASS_REG_BASE(x) (void __iomem *)(virt_bases[LPASS_BASE] + (x))
-#define APCS_REG_BASE(x) (void __iomem *)(virt_bases[APCS_BASE] + (x))
-#define APCS_PLL_REG_BASE(x) (void __iomem *)(virt_bases[APCS_PLL_BASE] + (x))
-
-/* GCC registers */
-#define GPLL0_MODE_REG                 0x0000
-#define GPLL0_L_REG                    0x0004
-#define GPLL0_M_REG                    0x0008
-#define GPLL0_N_REG                    0x000C
-#define GPLL0_USER_CTL_REG             0x0010
-#define GPLL0_CONFIG_CTL_REG           0x0014
-#define GPLL0_TEST_CTL_REG             0x0018
-#define GPLL0_STATUS_REG               0x001C
-
-#define GPLL1_MODE_REG                 0x0040
-#define GPLL1_L_REG                    0x0044
-#define GPLL1_M_REG                    0x0048
-#define GPLL1_N_REG                    0x004C
-#define GPLL1_USER_CTL_REG             0x0050
-#define GPLL1_CONFIG_CTL_REG           0x0054
-#define GPLL1_TEST_CTL_REG             0x0058
-#define GPLL1_STATUS_REG               0x005C
-
-#define GCC_DEBUG_CLK_CTL_REG          0x1880
-#define CLOCK_FRQ_MEASURE_CTL_REG      0x1884
-#define CLOCK_FRQ_MEASURE_STATUS_REG   0x1888
-#define GCC_PLLTEST_PAD_CFG_REG        0x188C
-#define GCC_XO_DIV4_CBCR_REG           0x10C8
-#define APCS_GPLL_ENA_VOTE_REG         0x1480
-#define APCS_CLOCK_BRANCH_ENA_VOTE     0x1484
-#define APCS_CLOCK_SLEEP_ENA_VOTE      0x1488
-
-#define APCS_CLK_DIAG_REG              0x001C
-
-#define APCS_CPU_PLL_MODE_REG          0x0000
-#define APCS_CPU_PLL_L_REG             0x0004
-#define APCS_CPU_PLL_M_REG             0x0008
-#define APCS_CPU_PLL_N_REG             0x000C
-#define APCS_CPU_PLL_USER_CTL_REG      0x0010
-#define APCS_CPU_PLL_CONFIG_CTL_REG    0x0014
-#define APCS_CPU_PLL_TEST_CTL_REG      0x0018
-#define APCS_CPU_PLL_STATUS_REG        0x001C
-
-#define USB_HSIC_SYSTEM_CMD_RCGR       0x041C
-#define USB_HSIC_XCVR_FS_CMD_RCGR      0x0424
-#define USB_HSIC_CMD_RCGR              0x0440
-#define USB_HSIC_IO_CAL_CMD_RCGR       0x0458
-#define USB_HS_SYSTEM_CMD_RCGR         0x0490
-#define SDCC2_APPS_CMD_RCGR            0x0510
-#define SDCC3_APPS_CMD_RCGR            0x0550
-#define BLSP1_QUP1_SPI_APPS_CMD_RCGR   0x064C
-#define BLSP1_UART1_APPS_CMD_RCGR      0x068C
-#define BLSP1_QUP2_SPI_APPS_CMD_RCGR   0x06CC
-#define BLSP1_UART2_APPS_CMD_RCGR      0x070C
-#define BLSP1_QUP3_SPI_APPS_CMD_RCGR   0x074C
-#define BLSP1_UART3_APPS_CMD_RCGR      0x078C
-#define BLSP1_QUP4_SPI_APPS_CMD_RCGR   0x07CC
-#define BLSP1_UART4_APPS_CMD_RCGR      0x080C
-#define BLSP1_QUP5_SPI_APPS_CMD_RCGR   0x084C
-#define BLSP1_UART5_APPS_CMD_RCGR      0x088C
-#define BLSP1_QUP6_SPI_APPS_CMD_RCGR   0x08CC
-#define BLSP1_UART6_APPS_CMD_RCGR      0x090C
-#define PDM2_CMD_RCGR                  0x0CD0
-#define CE1_CMD_RCGR                   0x1050
-#define GP1_CMD_RCGR                   0x1904
-#define GP2_CMD_RCGR                   0x1944
-#define GP3_CMD_RCGR                   0x1984
-#define QPIC_CMD_RCGR                  0x1A50
-#define IPA_CMD_RCGR                   0x1A90
-
-#define USB_HS_HSIC_BCR           0x0400
-#define USB_HS_BCR                0x0480
-#define SDCC2_BCR                 0x0500
-#define SDCC3_BCR                 0x0540
-#define BLSP1_BCR                 0x05C0
-#define BLSP1_QUP1_BCR            0x0640
-#define BLSP1_UART1_BCR           0x0680
-#define BLSP1_QUP2_BCR            0x06C0
-#define BLSP1_UART2_BCR           0x0700
-#define BLSP1_QUP3_BCR            0x0740
-#define BLSP1_UART3_BCR           0x0780
-#define BLSP1_QUP4_BCR            0x07C0
-#define BLSP1_UART4_BCR           0x0800
-#define BLSP1_QUP5_BCR            0x0840
-#define BLSP1_UART5_BCR           0x0880
-#define BLSP1_QUP6_BCR            0x08C0
-#define BLSP1_UART6_BCR           0x0900
-#define PDM_BCR                   0x0CC0
-#define PRNG_BCR                  0x0D00
-#define BAM_DMA_BCR               0x0D40
-#define BOOT_ROM_BCR              0x0E00
-#define CE1_BCR                   0x1040
-#define QPIC_BCR                  0x1040
-#define IPA_BCR                   0x1A80
-
-
-#define SYS_NOC_IPA_AXI_CBCR                     0x0128
-#define USB_HSIC_AHB_CBCR                        0x0408
-#define USB_HSIC_SYSTEM_CBCR                     0x040C
-#define USB_HSIC_CBCR                            0x0410
-#define USB_HSIC_IO_CAL_CBCR                     0x0414
-#define USB_HSIC_XCVR_FS_CBCR                    0x042C
-#define USB_HS_SYSTEM_CBCR                       0x0484
-#define USB_HS_AHB_CBCR                          0x0488
-#define SDCC2_APPS_CBCR                          0x0504
-#define SDCC2_AHB_CBCR                           0x0508
-#define SDCC3_APPS_CBCR                          0x0544
-#define SDCC3_AHB_CBCR                           0x0548
-#define BLSP1_AHB_CBCR                           0x05C4
-#define BLSP1_QUP1_SPI_APPS_CBCR                 0x0644
-#define BLSP1_QUP1_I2C_APPS_CBCR                 0x0648
-#define BLSP1_UART1_APPS_CBCR                    0x0684
-#define BLSP1_UART1_SIM_CBCR                     0x0688
-#define BLSP1_QUP2_SPI_APPS_CBCR                 0x06C4
-#define BLSP1_QUP2_I2C_APPS_CBCR                 0x06C8
-#define BLSP1_UART2_APPS_CBCR                    0x0704
-#define BLSP1_UART2_SIM_CBCR                     0x0708
-#define BLSP1_QUP3_SPI_APPS_CBCR                 0x0744
-#define BLSP1_QUP3_I2C_APPS_CBCR                 0x0748
-#define BLSP1_UART3_APPS_CBCR                    0x0784
-#define BLSP1_UART3_SIM_CBCR                     0x0788
-#define BLSP1_QUP4_SPI_APPS_CBCR                 0x07C4
-#define BLSP1_QUP4_I2C_APPS_CBCR                 0x07C8
-#define BLSP1_UART4_APPS_CBCR                    0x0804
-#define BLSP1_UART4_SIM_CBCR                     0x0808
-#define BLSP1_QUP5_SPI_APPS_CBCR                 0x0844
-#define BLSP1_QUP5_I2C_APPS_CBCR                 0x0848
-#define BLSP1_UART5_APPS_CBCR                    0x0884
-#define BLSP1_UART5_SIM_CBCR                     0x0888
-#define BLSP1_QUP6_SPI_APPS_CBCR                 0x08C4
-#define BLSP1_QUP6_I2C_APPS_CBCR                 0x08C8
-#define BLSP1_UART6_APPS_CBCR                    0x0904
-#define BLSP1_UART6_SIM_CBCR                     0x0908
-#define BOOT_ROM_AHB_CBCR                        0x0E04
-#define PDM_AHB_CBCR                             0x0CC4
-#define PDM_XO4_CBCR                             0x0CC8
-#define PDM_AHB_CBCR                             0x0CC4
-#define PDM_XO4_CBCR                             0x0CC8
-#define PDM2_CBCR                                0x0CCC
-#define PRNG_AHB_CBCR                            0x0D04
-#define BAM_DMA_AHB_CBCR                         0x0D44
-#define MSG_RAM_AHB_CBCR                         0x0E44
-#define CE1_CBCR                                 0x1044
-#define CE1_AXI_CBCR                             0x1048
-#define CE1_AHB_CBCR                             0x104C
-#define GCC_AHB_CBCR                             0x10C0
-#define GP1_CBCR                                 0x1900
-#define GP2_CBCR                                 0x1940
-#define GP3_CBCR                                 0x1980
-#define QPIC_CBCR				 0x1A44
-#define QPIC_AHB_CBCR                            0x1A48
-#define IPA_CBCR                                 0x1A84
-#define IPA_CNOC_CBCR                            0x1A88
-#define IPA_SLEEP_CBCR                           0x1A8C
-
-/* LPASS registers */
-/* TODO: Needs to double check lpass regiserts after get the SWI for hw */
-#define LPAPLL_MODE_REG				0x0000
-#define LPAPLL_L_REG				0x0004
-#define LPAPLL_M_REG				0x0008
-#define LPAPLL_N_REG				0x000C
-#define LPAPLL_USER_CTL_REG			0x0010
-#define LPAPLL_CONFIG_CTL_REG			0x0014
-#define LPAPLL_TEST_CTL_REG			0x0018
-#define LPAPLL_STATUS_REG			0x001C
-
-#define LPASS_DEBUG_CLK_CTL_REG			0x29000
-#define LPASS_LPA_PLL_VOTE_APPS_REG		0x2000
-
-#define LPAIF_PRI_CMD_RCGR			0xB000
-#define LPAIF_SEC_CMD_RCGR			0xC000
-#define LPAIF_PCM0_CMD_RCGR			0xF000
-#define LPAIF_PCM1_CMD_RCGR			0x10000
-#define SLIMBUS_CMD_RCGR			0x12000
-#define LPAIF_PCMOE_CMD_RCGR			0x13000
-
-#define AUDIO_CORE_BCR				0x4000
-
-#define AUDIO_CORE_LPAIF_PRI_OSR_CBCR		0xB014
-#define AUDIO_CORE_LPAIF_PRI_IBIT_CBCR		0xB018
-#define AUDIO_CORE_LPAIF_PRI_EBIT_CBCR		0xB01C
-#define AUDIO_CORE_LPAIF_SEC_OSR_CBCR		0xC014
-#define AUDIO_CORE_LPAIF_SEC_IBIT_CBCR		0xC018
-#define AUDIO_CORE_LPAIF_SEC_EBIT_CBCR		0xC01C
-#define AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR		0xF014
-#define AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR		0xF018
-#define AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR		0x10014
-#define AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR		0x10018
-#define AUDIO_CORE_RESAMPLER_CORE_CBCR		0x11014
-#define AUDIO_CORE_RESAMPLER_LFABIF_CBCR	0x11018
-#define AUDIO_CORE_SLIMBUS_CORE_CBCR		0x12014
-#define AUDIO_CORE_SLIMBUS_LFABIF_CBCR		0x12018
-#define AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR	0x13014
-
-/* Mux source select values */
-#define cxo_source_val	0
-#define gpll0_source_val 1
-#define gpll1_hsic_source_val 4
-#define gnd_source_val	5
-#define cxo_lpass_source_val 0
-#define lpapll0_lpass_source_val 1
-#define gpll0_lpass_source_val 5
-
-#define F(f, s, div, m, n) \
-	{ \
-		.freq_hz = (f), \
-		.src_clk = &s##_clk_src.c, \
-		.m_val = (m), \
-		.n_val = ~((n)-(m)) * !!(n), \
-		.d_val = ~(n),\
-		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
-			| BVAL(10, 8, s##_source_val), \
-	}
-
-#define F_HSIC(f, s, div, m, n) \
-	{ \
-		.freq_hz = (f), \
-		.src_clk = &s##_clk_src.c, \
-		.m_val = (m), \
-		.n_val = ~((n)-(m)) * !!(n), \
-		.d_val = ~(n),\
-		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
-			| BVAL(10, 8, s##_hsic_source_val), \
-	}
-
-#define F_LPASS(f, s, div, m, n) \
-	{ \
-		.freq_hz = (f), \
-		.src_clk = &s##_clk_src.c, \
-		.m_val = (m), \
-		.n_val = ~((n)-(m)) * !!(n), \
-		.d_val = ~(n),\
-		.div_src_val = BVAL(4, 0, (int)(2*(div) - 1)) \
-			| BVAL(10, 8, s##_lpass_source_val), \
-	}
-
-
-#define VDD_DIG_FMAX_MAP1(l1, f1) \
-	.vdd_class = &vdd_dig, \
-	.fmax[VDD_DIG_##l1] = (f1)
-#define VDD_DIG_FMAX_MAP2(l1, f1, l2, f2) \
-	.vdd_class = &vdd_dig, \
-	.fmax[VDD_DIG_##l1] = (f1), \
-	.fmax[VDD_DIG_##l2] = (f2)
-#define VDD_DIG_FMAX_MAP3(l1, f1, l2, f2, l3, f3) \
-	.vdd_class = &vdd_dig, \
-	.fmax[VDD_DIG_##l1] = (f1), \
-	.fmax[VDD_DIG_##l2] = (f2), \
-	.fmax[VDD_DIG_##l3] = (f3)
-
-enum vdd_dig_levels {
-	VDD_DIG_NONE,
-	VDD_DIG_LOW,
-	VDD_DIG_NOMINAL,
-	VDD_DIG_HIGH
-};
-
-/* TODO: Add regulator set voltage APIs when support is available */
-static int set_vdd_dig(struct clk_vdd_class *vdd_class, int level)
-{
-	return 0;
-}
-
-static DEFINE_VDD_CLASS(vdd_dig, set_vdd_dig);
-
-/* TODO: Needs to confirm the below values */
-#define RPM_MISC_CLK_TYPE	0x306b6c63
-#define RPM_BUS_CLK_TYPE	0x316b6c63
-#define RPM_MEM_CLK_TYPE	0x326b6c63
-
-#define RPM_SMD_KEY_ENABLE	0x62616E45
-
-#define CXO_ID			0x0
-#define QDSS_ID			0x1
-#define RPM_SCALING_ENABLE_ID	0x2
-
-#define PNOC_ID		0x0
-#define SNOC_ID		0x1
-#define CNOC_ID		0x2
-
-#define BIMC_ID		0x0
-
-#define D0_ID		 1
-#define D1_ID		 2
-#define A0_ID		 3
-#define A1_ID		 4
-#define A2_ID		 5
-
-DEFINE_CLK_RPM_SMD_BRANCH(cxo_clk_src, cxo_a_clk_src,
-				RPM_MISC_CLK_TYPE, CXO_ID, 19200000);
-
-DEFINE_CLK_RPM_SMD(cnoc_clk, cnoc_a_clk, RPM_BUS_CLK_TYPE, CNOC_ID, NULL);
-DEFINE_CLK_RPM_SMD(pnoc_clk, pnoc_a_clk, RPM_BUS_CLK_TYPE, PNOC_ID, NULL);
-DEFINE_CLK_RPM_SMD(snoc_clk, snoc_a_clk, RPM_BUS_CLK_TYPE, SNOC_ID, NULL);
-
-DEFINE_CLK_RPM_SMD(bimc_clk, bimc_a_clk, RPM_MEM_CLK_TYPE, BIMC_ID, NULL);
-
-DEFINE_CLK_RPM_SMD_QDSS(qdss_clk, qdss_a_clk, RPM_MISC_CLK_TYPE, QDSS_ID);
-
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d0, cxo_d0_a, D0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_d1, cxo_d1_a, D1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a0, cxo_a0_a, A0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a1, cxo_a1_a, A1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER(cxo_a2, cxo_a2_a, A2_ID);
-
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d0_pin, cxo_d0_a_pin, D0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_d1_pin, cxo_d1_a_pin, D1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a0_pin, cxo_a0_a_pin, A0_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a1_pin, cxo_a1_a_pin, A1_ID);
-DEFINE_CLK_RPM_SMD_XO_BUFFER_PINCTRL(cxo_a2_pin, cxo_a2_a_pin, A2_ID);
-
-static struct pll_vote_clk gpll0_clk_src = {
-	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
-	.status_reg = (void __iomem *)GPLL0_STATUS_REG,
-	.status_mask = BIT(17),
-	.parent = &cxo_clk_src.c,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.rate = 600000000,
-		.dbg_name = "gpll0_clk_src",
-		.ops = &clk_ops_pll_vote,
-		CLK_INIT(gpll0_clk_src.c),
-	},
-};
-
-static struct pll_vote_clk lpapll0_clk_src = {
-	.en_reg = (void __iomem *)LPASS_LPA_PLL_VOTE_APPS_REG,
-	.en_mask = BIT(0),
-	.status_reg = (void __iomem *)LPAPLL_STATUS_REG,
-	.status_mask = BIT(17),
-	.parent = &cxo_clk_src.c,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.rate = 393216000,
-		.dbg_name = "lpapll0_clk_src",
-		.ops = &clk_ops_pll_vote,
-		CLK_INIT(lpapll0_clk_src.c),
-	},
-};
-
-static struct pll_vote_clk gpll1_clk_src = {
-	.en_reg = (void __iomem *)APCS_GPLL_ENA_VOTE_REG,
-	.en_mask = BIT(1),
-	.status_reg = (void __iomem *)GPLL1_STATUS_REG,
-	.status_mask = BIT(17),
-	.parent = &cxo_clk_src.c,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.rate = 480000000,
-		.dbg_name = "gpll1_clk_src",
-		.ops = &clk_ops_pll_vote,
-		CLK_INIT(gpll1_clk_src.c),
-	},
-};
-
-static struct pll_clk apcspll_clk_src = {
-	.mode_reg = (void __iomem *)APCS_CPU_PLL_MODE_REG,
-	.status_reg = (void __iomem *)APCS_CPU_PLL_STATUS_REG,
-	.parent = &cxo_clk_src.c,
-	.base = &virt_bases[APCS_PLL_BASE],
-	.c = {
-		.rate = 748800000,
-		.dbg_name = "apcspll_clk_src",
-		.ops = &clk_ops_local_pll,
-		CLK_INIT(apcspll_clk_src.c),
-	},
-};
-
-static DEFINE_CLK_VOTER(pnoc_msmbus_clk, &pnoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(snoc_msmbus_clk, &snoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(cnoc_msmbus_clk, &cnoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(pnoc_msmbus_a_clk, &pnoc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(snoc_msmbus_a_clk, &snoc_a_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(cnoc_msmbus_a_clk, &cnoc_a_clk.c, LONG_MAX);
-
-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(pnoc_sdcc2_clk, &pnoc_clk.c, LONG_MAX);
-static DEFINE_CLK_VOTER(pnoc_sdcc3_clk, &pnoc_clk.c, LONG_MAX);
-
-static DEFINE_CLK_VOTER(pnoc_sps_clk, &pnoc_clk.c, LONG_MAX);
-
-static struct clk_freq_tbl ftbl_gcc_ipa_clk[] = {
-	F( 50000000,    gpll0,   12,   0,   0),
-	F( 92310000,    gpll0,  6.5,   0,   0),
-	F(100000000,    gpll0,    6,   0,   0),
-	F_END
-};
-
-static struct rcg_clk ipa_clk_src = {
-	.cmd_rcgr_reg =  IPA_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_ipa_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "ipa_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
-		CLK_INIT(ipa_clk_src.c)
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_blsp1_qup1_6_spi_apps_clk[] = {
-	F(960000, cxo, 10, 1, 2),
-	F(4800000, cxo, 4, 0, 0),
-	F(9600000, cxo, 2, 0, 0),
-	F(15000000, gpll0, 10, 1, 4),
-	F(19200000, cxo, 1, 0, 0),
-	F(25000000, gpll0, 12, 1, 2),
-	F(50000000, gpll0, 12, 0, 0),
-	F_END
-};
-
-static struct rcg_clk blsp1_qup1_spi_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_QUP1_SPI_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_qup1_spi_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
-		CLK_INIT(blsp1_qup1_spi_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_qup2_spi_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_QUP2_SPI_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_qup2_spi_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
-		CLK_INIT(blsp1_qup2_spi_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_qup3_spi_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_QUP3_SPI_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_qup3_spi_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
-		CLK_INIT(blsp1_qup3_spi_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_qup4_spi_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_QUP4_SPI_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_qup4_spi_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
-		CLK_INIT(blsp1_qup4_spi_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_qup5_spi_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_QUP5_SPI_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_qup5_spi_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
-		CLK_INIT(blsp1_qup5_spi_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_qup6_spi_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_QUP6_SPI_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_qup1_6_spi_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_qup6_spi_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 25000000, NOMINAL, 50000000),
-		CLK_INIT(blsp1_qup6_spi_apps_clk_src.c)
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_blsp1_uart1_6_apps_clk[] = {
-	F(3686400, gpll0, 1, 96, 15625),
-	F(7372800, gpll0, 1, 192, 15625),
-	F(14745600, gpll0, 1, 384, 15625),
-	F(16000000, gpll0, 5, 2, 15),
-	F(19200000, cxo, 1, 0, 0),
-	F(24000000, gpll0, 5, 1, 5),
-	F(32000000, gpll0, 1, 4, 75),
-	F(40000000, gpll0, 15, 0, 0),
-	F(46400000, gpll0, 1, 29, 375),
-	F(48000000, gpll0, 12.5, 0, 0),
-	F(51200000, gpll0, 1, 32, 375),
-	F(56000000, gpll0, 1, 7, 75),
-	F(58982400, gpll0, 1, 1536, 15625),
-	F(60000000, gpll0, 10, 0, 0),
-	F_END
-};
-
-static struct rcg_clk blsp1_uart1_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_UART1_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_uart1_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
-		CLK_INIT(blsp1_uart1_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_uart2_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_UART2_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_uart2_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
-		CLK_INIT(blsp1_uart2_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_uart3_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_UART3_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_uart3_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
-		CLK_INIT(blsp1_uart3_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_uart4_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_UART4_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_uart4_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
-		CLK_INIT(blsp1_uart4_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_uart5_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_UART5_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_uart5_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
-		CLK_INIT(blsp1_uart5_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk blsp1_uart6_apps_clk_src = {
-	.cmd_rcgr_reg =  BLSP1_UART6_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_blsp1_uart1_6_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "blsp1_uart6_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 31580000, NOMINAL, 63160000),
-		CLK_INIT(blsp1_uart6_apps_clk_src.c)
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_ce1_clk[] = {
-	F(50000000, gpll0, 12, 0, 0),
-	F(100000000, gpll0, 6, 0, 0),
-	F_END
-};
-
-static struct rcg_clk ce1_clk_src = {
-	.cmd_rcgr_reg = CE1_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_gcc_ce1_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "ce1_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
-		CLK_INIT(ce1_clk_src.c),
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_gp_clk[] = {
-	F(19200000,  cxo,  1,   0,   0),
-	F_END
-};
-
-static struct rcg_clk gp1_clk_src = {
-	.cmd_rcgr_reg =  GP1_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_gp_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gp1_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
-		CLK_INIT(gp1_clk_src.c)
-	},
-};
-
-static struct rcg_clk gp2_clk_src = {
-	.cmd_rcgr_reg =  GP2_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_gp_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gp2_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
-		CLK_INIT(gp2_clk_src.c)
-	},
-};
-
-static struct rcg_clk gp3_clk_src = {
-	.cmd_rcgr_reg =  GP3_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_gp_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gp3_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
-		CLK_INIT(gp3_clk_src.c)
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_pdm2_clk[] = {
-	F(60000000,  gpll0,  10,   0,   0),
-	F_END
-};
-
-static struct rcg_clk pdm2_clk_src = {
-	.cmd_rcgr_reg = PDM2_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_gcc_pdm2_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "pdm2_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP1(LOW, 60000000),
-		CLK_INIT(pdm2_clk_src.c),
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_qpic_clk[] = {
-	F(50000000, gpll0, 12, 0, 0),
-	F(100000000, gpll0, 6, 0, 0),
-	F_END
-};
-
-static struct rcg_clk qpic_clk_src = {
-	.cmd_rcgr_reg =  QPIC_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_qpic_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "qpic_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
-		CLK_INIT(qpic_clk_src.c)
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_sdcc2_apps_clk[] = {
-	F(144000, cxo, 16, 3, 25),
-	F(400000, cxo, 12, 1, 4),
-	F(20000000, gpll0, 15, 1, 2),
-	F(25000000, gpll0, 12, 1, 2),
-	F(50000000, gpll0, 12, 0, 0),
-	F(100000000, gpll0, 6, 0, 0),
-	F(200000000, gpll0, 3, 0, 0),
-	F_END
-};
-
-static struct clk_freq_tbl ftbl_gcc_sdcc3_apps_clk[] = {
-	F(144000, cxo, 16, 3, 25),
-	F(400000, cxo, 12, 1, 4),
-	F(20000000, gpll0, 15, 1, 2),
-	F(25000000, gpll0, 12, 1, 2),
-	F(50000000, gpll0, 12, 0, 0),
-	F(100000000, gpll0, 6, 0, 0),
-	F_END
-};
-
-static struct rcg_clk sdcc2_apps_clk_src = {
-	.cmd_rcgr_reg =  SDCC2_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_sdcc2_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "sdcc2_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 100000000, NOMINAL, 200000000),
-		CLK_INIT(sdcc2_apps_clk_src.c)
-	},
-};
-
-static struct rcg_clk sdcc3_apps_clk_src = {
-	.cmd_rcgr_reg =  SDCC3_APPS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_gcc_sdcc3_apps_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "sdcc3_apps_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 50000000, NOMINAL, 100000000),
-		CLK_INIT(sdcc3_apps_clk_src.c)
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hs_system_clk[] = {
-	F(75000000, gpll0, 8, 0, 0),
-	F_END
-};
-
-static struct rcg_clk usb_hs_system_clk_src = {
-	.cmd_rcgr_reg = USB_HS_SYSTEM_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_gcc_usb_hs_system_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "usb_hs_system_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 37500000, NOMINAL, 75000000),
-		CLK_INIT(usb_hs_system_clk_src.c),
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_clk[] = {
-	F_HSIC(480000000, gpll1, 1, 0, 0),
-	F_END
-};
-
-static struct rcg_clk usb_hsic_clk_src = {
-	.cmd_rcgr_reg = USB_HSIC_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_gcc_usb_hsic_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "usb_hsic_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP1(LOW, 480000000),
-		CLK_INIT(usb_hsic_clk_src.c),
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_io_cal_clk[] = {
-	F(9600000, cxo, 2, 0, 0),
-	F_END
-};
-
-static struct rcg_clk usb_hsic_io_cal_clk_src = {
-	.cmd_rcgr_reg = USB_HSIC_IO_CAL_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_gcc_usb_hsic_io_cal_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "usb_hsic_io_cal_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP1(LOW, 9600000),
-		CLK_INIT(usb_hsic_io_cal_clk_src.c),
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_system_clk[] = {
-	F(75000000, gpll0, 8, 0, 0),
-	F_END
-};
-
-static struct rcg_clk usb_hsic_system_clk_src = {
-	.cmd_rcgr_reg = USB_HSIC_SYSTEM_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_gcc_usb_hsic_system_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "usb_hsic_system_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP2(LOW, 60000000, NOMINAL, 75000000),
-		CLK_INIT(usb_hsic_system_clk_src.c),
-	},
-};
-
-static struct clk_freq_tbl ftbl_gcc_usb_hsic_xcvr_fs_clk[] = {
-	F(60000000, gpll0, 10, 0, 0),
-	F_END
-};
-
-static struct rcg_clk usb_hsic_xcvr_fs_clk_src = {
-	.cmd_rcgr_reg = USB_HSIC_XCVR_FS_CMD_RCGR,
-	.set_rate = set_rate_hid,
-	.freq_tbl = ftbl_gcc_usb_hsic_xcvr_fs_clk,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "usb_hsic_xcvr_fs_clk_src",
-		.ops = &clk_ops_rcg,
-		VDD_DIG_FMAX_MAP1(LOW, 60000000),
-		CLK_INIT(usb_hsic_xcvr_fs_clk_src.c),
-	},
-};
-
-static struct local_vote_clk gcc_bam_dma_ahb_clk = {
-	.cbcr_reg = BAM_DMA_AHB_CBCR,
-	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
-	.en_mask = BIT(12),
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_bam_dma_ahb_clk",
-		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_bam_dma_ahb_clk.c),
-	},
-};
-
-static struct local_vote_clk gcc_blsp1_ahb_clk = {
-	.cbcr_reg = BLSP1_AHB_CBCR,
-	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
-	.en_mask = BIT(17),
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_ahb_clk",
-		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_blsp1_ahb_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup1_i2c_apps_clk = {
-	.cbcr_reg = BLSP1_QUP1_I2C_APPS_CBCR,
-	.parent = &cxo_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup1_i2c_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup1_i2c_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup1_spi_apps_clk = {
-	.cbcr_reg = BLSP1_QUP1_SPI_APPS_CBCR,
-	.parent = &blsp1_qup1_spi_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup1_spi_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup1_spi_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup2_i2c_apps_clk = {
-	.cbcr_reg = BLSP1_QUP2_I2C_APPS_CBCR,
-	.parent = &cxo_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup2_i2c_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup2_i2c_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup2_spi_apps_clk = {
-	.cbcr_reg = BLSP1_QUP2_SPI_APPS_CBCR,
-	.parent = &blsp1_qup2_spi_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup2_spi_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup2_spi_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup3_i2c_apps_clk = {
-	.cbcr_reg = BLSP1_QUP3_I2C_APPS_CBCR,
-	.parent = &cxo_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup3_i2c_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup3_i2c_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup3_spi_apps_clk = {
-	.cbcr_reg = BLSP1_QUP3_SPI_APPS_CBCR,
-	.parent = &blsp1_qup3_spi_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup3_spi_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup3_spi_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup4_i2c_apps_clk = {
-	.cbcr_reg = BLSP1_QUP4_I2C_APPS_CBCR,
-	.parent = &cxo_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup4_i2c_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup4_i2c_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup4_spi_apps_clk = {
-	.cbcr_reg = BLSP1_QUP4_SPI_APPS_CBCR,
-	.parent = &blsp1_qup4_spi_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup4_spi_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup4_spi_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup5_i2c_apps_clk = {
-	.cbcr_reg = BLSP1_QUP5_I2C_APPS_CBCR,
-	.parent = &cxo_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup5_i2c_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup5_i2c_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup5_spi_apps_clk = {
-	.cbcr_reg = BLSP1_QUP5_SPI_APPS_CBCR,
-	.parent = &blsp1_qup5_spi_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup5_spi_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup5_spi_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup6_i2c_apps_clk = {
-	.cbcr_reg = BLSP1_QUP6_I2C_APPS_CBCR,
-	.parent = &cxo_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup6_i2c_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup6_i2c_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_qup6_spi_apps_clk = {
-	.cbcr_reg = BLSP1_QUP6_SPI_APPS_CBCR,
-	.parent = &blsp1_qup6_spi_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_qup6_spi_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_qup6_spi_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_uart1_apps_clk = {
-	.cbcr_reg = BLSP1_UART1_APPS_CBCR,
-	.parent = &blsp1_uart1_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_uart1_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_uart1_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_uart2_apps_clk = {
-	.cbcr_reg = BLSP1_UART2_APPS_CBCR,
-	.parent = &blsp1_uart2_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_uart2_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_uart2_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_uart3_apps_clk = {
-	.cbcr_reg = BLSP1_UART3_APPS_CBCR,
-	.parent = &blsp1_uart3_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_uart3_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_uart3_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_uart4_apps_clk = {
-	.cbcr_reg = BLSP1_UART4_APPS_CBCR,
-	.parent = &blsp1_uart4_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_uart4_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_uart4_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_uart5_apps_clk = {
-	.cbcr_reg = BLSP1_UART5_APPS_CBCR,
-	.parent = &blsp1_uart5_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_uart5_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_uart5_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_blsp1_uart6_apps_clk = {
-	.cbcr_reg = BLSP1_UART6_APPS_CBCR,
-	.parent = &blsp1_uart6_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_blsp1_uart6_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_blsp1_uart6_apps_clk.c),
-	},
-};
-
-static struct local_vote_clk gcc_boot_rom_ahb_clk = {
-	.cbcr_reg = BOOT_ROM_AHB_CBCR,
-	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
-	.en_mask = BIT(10),
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_boot_rom_ahb_clk",
-		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_boot_rom_ahb_clk.c),
-	},
-};
-
-static struct local_vote_clk gcc_ce1_ahb_clk = {
-	.cbcr_reg = CE1_AHB_CBCR,
-	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
-	.en_mask = BIT(3),
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_ce1_ahb_clk",
-		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_ce1_ahb_clk.c),
-	},
-};
-
-static struct local_vote_clk gcc_ce1_axi_clk = {
-	.cbcr_reg = CE1_AXI_CBCR,
-	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
-	.en_mask = BIT(4),
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_ce1_axi_clk",
-		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_ce1_axi_clk.c),
-	},
-};
-
-static struct local_vote_clk gcc_ce1_clk = {
-	.cbcr_reg = CE1_CBCR,
-	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
-	.en_mask = BIT(5),
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_ce1_clk",
-		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_ce1_clk.c),
-	},
-};
-
-static struct branch_clk gcc_gp1_clk = {
-	.cbcr_reg = GP1_CBCR,
-	.parent = &gp1_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_gp1_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_gp1_clk.c),
-	},
-};
-
-static struct branch_clk gcc_gp2_clk = {
-	.cbcr_reg = GP2_CBCR,
-	.parent = &gp2_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_gp2_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_gp2_clk.c),
-	},
-};
-
-static struct branch_clk gcc_gp3_clk = {
-	.cbcr_reg = GP3_CBCR,
-	.parent = &gp3_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_gp3_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_gp3_clk.c),
-	},
-};
-
-static struct branch_clk gcc_ipa_clk = {
-	.cbcr_reg = IPA_CBCR,
-	.parent = &ipa_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_ipa_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_ipa_clk.c),
-	},
-};
-
-static struct branch_clk gcc_ipa_cnoc_clk = {
-	.cbcr_reg = IPA_CNOC_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_ipa_cnoc_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_ipa_cnoc_clk.c),
-	},
-};
-
-static struct branch_clk gcc_pdm2_clk = {
-	.cbcr_reg = PDM2_CBCR,
-	.parent = &pdm2_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_pdm2_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_pdm2_clk.c),
-	},
-};
-
-static struct branch_clk gcc_pdm_ahb_clk = {
-	.cbcr_reg = PDM_AHB_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_pdm_ahb_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_pdm_ahb_clk.c),
-	},
-};
-
-static struct local_vote_clk gcc_prng_ahb_clk = {
-	.cbcr_reg = PRNG_AHB_CBCR,
-	.vote_reg = APCS_CLOCK_BRANCH_ENA_VOTE,
-	.en_mask = BIT(13),
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_prng_ahb_clk",
-		.ops = &clk_ops_vote,
-		CLK_INIT(gcc_prng_ahb_clk.c),
-	},
-};
-
-static struct branch_clk gcc_qpic_ahb_clk = {
-	.cbcr_reg = QPIC_AHB_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_qpic_ahb_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_qpic_ahb_clk.c),
-	},
-};
-
-static struct branch_clk gcc_qpic_clk = {
-	.cbcr_reg = QPIC_CBCR,
-	.parent = &qpic_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_qpic_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_qpic_clk.c),
-	},
-};
-
-static struct branch_clk gcc_sdcc2_ahb_clk = {
-	.cbcr_reg = SDCC2_AHB_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_sdcc2_ahb_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_sdcc2_ahb_clk.c),
-	},
-};
-
-static struct branch_clk gcc_sdcc2_apps_clk = {
-	.cbcr_reg = SDCC2_APPS_CBCR,
-	.parent = &sdcc2_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_sdcc2_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_sdcc2_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_sdcc3_ahb_clk = {
-	.cbcr_reg = SDCC3_AHB_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_sdcc3_ahb_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_sdcc3_ahb_clk.c),
-	},
-};
-
-static struct branch_clk gcc_sdcc3_apps_clk = {
-	.cbcr_reg = SDCC3_APPS_CBCR,
-	.parent = &sdcc3_apps_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_sdcc3_apps_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_sdcc3_apps_clk.c),
-	},
-};
-
-static struct branch_clk gcc_sys_noc_ipa_axi_clk = {
-	.cbcr_reg = SYS_NOC_IPA_AXI_CBCR,
-	.parent = &ipa_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_sys_noc_ipa_axi_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_sys_noc_ipa_axi_clk.c),
-	},
-};
-
-static struct branch_clk gcc_usb_hs_ahb_clk = {
-	.cbcr_reg = USB_HS_AHB_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_usb_hs_ahb_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_usb_hs_ahb_clk.c),
-	},
-};
-
-static struct branch_clk gcc_usb_hs_system_clk = {
-	.cbcr_reg = USB_HS_SYSTEM_CBCR,
-	.bcr_reg = USB_HS_BCR,
-	.parent = &usb_hs_system_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_usb_hs_system_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_usb_hs_system_clk.c),
-	},
-};
-
-static struct branch_clk gcc_usb_hsic_ahb_clk = {
-	.cbcr_reg = USB_HSIC_AHB_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_usb_hsic_ahb_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_usb_hsic_ahb_clk.c),
-	},
-};
-
-static struct branch_clk gcc_usb_hsic_clk = {
-	.cbcr_reg = USB_HSIC_CBCR,
-	.parent = &usb_hsic_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_usb_hsic_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_usb_hsic_clk.c),
-	},
-};
-
-static struct branch_clk gcc_usb_hsic_io_cal_clk = {
-	.cbcr_reg = USB_HSIC_IO_CAL_CBCR,
-	.parent = &usb_hsic_io_cal_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_usb_hsic_io_cal_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_usb_hsic_io_cal_clk.c),
-	},
-};
-
-static struct branch_clk gcc_usb_hsic_system_clk = {
-	.cbcr_reg = USB_HSIC_SYSTEM_CBCR,
-	.bcr_reg = USB_HS_HSIC_BCR,
-	.parent = &usb_hsic_system_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_usb_hsic_system_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_usb_hsic_system_clk.c),
-	},
-};
-
-static struct branch_clk gcc_usb_hsic_xcvr_fs_clk = {
-	.cbcr_reg = USB_HSIC_XCVR_FS_CBCR,
-	.parent = &usb_hsic_xcvr_fs_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[GCC_BASE],
-	.c = {
-		.dbg_name = "gcc_usb_hsic_xcvr_fs_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(gcc_usb_hsic_xcvr_fs_clk.c),
-	},
-};
-
-/* LPASS clock data */
-static struct clk_freq_tbl ftbl_audio_core_lpaif_clock[] = {
-	F_LPASS(  512000, lpapll0, 16, 1, 48),
-	F_LPASS(  768000, lpapll0, 16, 1, 32),
-	F_LPASS( 1024000, lpapll0, 16, 1, 24),
-	F_LPASS( 1536000, lpapll0, 16, 1, 16),
-	F_LPASS( 2048000, lpapll0, 16, 1, 12),
-	F_LPASS( 3072000, lpapll0, 16, 1,  8),
-	F_LPASS( 4096000, lpapll0, 16, 1,  6),
-	F_LPASS( 6144000, lpapll0, 16, 1,  4),
-	F_LPASS( 8192000, lpapll0, 16, 1,  3),
-	F_LPASS(12288000, lpapll0, 16, 1,  2),
-	F_END
-};
-
-static struct rcg_clk audio_core_lpaif_pcmoe_clk_src = {
-	.cmd_rcgr_reg =  LPAIF_PCMOE_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_audio_core_lpaif_clock,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcmoe_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP1(LOW, 12290000),
-		CLK_INIT(audio_core_lpaif_pcmoe_clk_src.c)
-	},
-};
-
-static struct rcg_clk audio_core_lpaif_pri_clk_src = {
-	.cmd_rcgr_reg =  LPAIF_PRI_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_audio_core_lpaif_clock,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pri_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 9220000, NOMINAL, 18440000),
-		CLK_INIT(audio_core_lpaif_pri_clk_src.c)
-	},
-};
-
-static struct rcg_clk audio_core_lpaif_sec_clk_src = {
-	.cmd_rcgr_reg =  LPAIF_SEC_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_audio_core_lpaif_clock,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_sec_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 6140000, NOMINAL, 12290000),
-		CLK_INIT(audio_core_lpaif_sec_clk_src.c)
-	},
-};
-
-static struct clk_freq_tbl ftbl_audio_core_slimbus_core_clock[] = {
-	F_LPASS(26041000, lpapll0, 1, 10, 151),
-	F_END
-};
-
-static struct rcg_clk audio_core_slimbus_core_clk_src = {
-	.cmd_rcgr_reg =  SLIMBUS_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_audio_core_slimbus_core_clock,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_slimbus_core_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 13110000, NOMINAL, 26210000),
-		CLK_INIT(audio_core_slimbus_core_clk_src.c)
-	},
-};
-
-static struct rcg_clk audio_core_lpaif_pcm0_clk_src = {
-	.cmd_rcgr_reg =  LPAIF_PCM0_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_audio_core_lpaif_clock,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcm0_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8190000),
-		CLK_INIT(audio_core_lpaif_pcm0_clk_src.c)
-	},
-};
-
-static struct rcg_clk audio_core_lpaif_pcm1_clk_src = {
-	.cmd_rcgr_reg =  LPAIF_PCM1_CMD_RCGR,
-	.set_rate = set_rate_mnd,
-	.freq_tbl = ftbl_audio_core_lpaif_clock,
-	.current_freq = &rcg_dummy_freq,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcm1_clk_src",
-		.ops = &clk_ops_rcg_mnd,
-		VDD_DIG_FMAX_MAP2(LOW, 4100000, NOMINAL, 8190000),
-		CLK_INIT(audio_core_lpaif_pcm1_clk_src.c)
-	},
-};
-
-static struct branch_clk audio_core_slimbus_lfabif_clk = {
-	.cbcr_reg = AUDIO_CORE_SLIMBUS_LFABIF_CBCR,
-	.has_sibling = 1,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_slimbus_lfabif_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_slimbus_lfabif_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pcm_data_oe_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PCM_DATA_OE_CBCR,
-	.parent = &audio_core_lpaif_pcmoe_clk_src.c,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcm_data_oe_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pcm_data_oe_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_slimbus_core_clk = {
-	.cbcr_reg = AUDIO_CORE_SLIMBUS_CORE_CBCR,
-	.parent = &audio_core_slimbus_core_clk_src.c,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_slimbus_core_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_slimbus_core_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pri_ebit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_EBIT_CBCR,
-	.has_sibling = 0,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pri_ebit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pri_ebit_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pri_ibit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_IBIT_CBCR,
-	.parent = &audio_core_lpaif_pri_clk_src.c,
-	.has_sibling = 1,
-	.max_div = 15,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pri_ibit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pri_ibit_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pri_osr_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PRI_OSR_CBCR,
-	.parent = &audio_core_lpaif_pri_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pri_osr_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pri_osr_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ebit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_EBIT_CBCR,
-	.has_sibling = 0,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcm0_ebit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pcm0_ebit_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pcm0_ibit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PCM0_IBIT_CBCR,
-	.parent = &audio_core_lpaif_pcm0_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcm0_ibit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pcm0_ibit_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_sec_ebit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_EBIT_CBCR,
-	.has_sibling = 0,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_sec_ebit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_sec_ebit_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_sec_ibit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_IBIT_CBCR,
-	.parent = &audio_core_lpaif_sec_clk_src.c,
-	.has_sibling = 1,
-	.max_div = 15,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_sec_ibit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_sec_ibit_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_sec_osr_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_SEC_OSR_CBCR,
-	.parent = &audio_core_lpaif_sec_clk_src.c,
-	.has_sibling = 1,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_sec_osr_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_sec_osr_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ebit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PCM1_EBIT_CBCR,
-	.has_sibling = 0,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcm1_ebit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pcm1_ebit_clk.c),
-	},
-};
-
-static struct branch_clk audio_core_lpaif_pcm1_ibit_clk = {
-	.cbcr_reg = AUDIO_CORE_LPAIF_PCM1_IBIT_CBCR,
-	.parent = &audio_core_lpaif_pcm1_clk_src.c,
-	.has_sibling = 0,
-	.base = &virt_bases[LPASS_BASE],
-	.c = {
-		.dbg_name = "audio_core_lpaif_pcm1_ibit_clk",
-		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_pcm1_ibit_clk.c),
-	},
-};
-
-static DEFINE_CLK_MEASURE(a5_m_clk);
-
-#ifdef CONFIG_DEBUG_FS
-
-struct measure_mux_entry {
-	struct clk *c;
-	int base;
-	u32 debug_mux;
-};
-
-struct measure_mux_entry measure_mux[] = {
-	{&gcc_pdm_ahb_clk.c,			GCC_BASE, 0x00d0},
-	{&gcc_usb_hsic_xcvr_fs_clk.c,		GCC_BASE, 0x005d},
-	{&gcc_usb_hsic_system_clk.c,		GCC_BASE, 0x0059},
-	{&gcc_usb_hsic_io_cal_clk.c,		GCC_BASE, 0x005b},
-	{&gcc_sdcc3_ahb_clk.c,			GCC_BASE, 0x0079},
-	{&gcc_blsp1_qup5_i2c_apps_clk.c,	GCC_BASE, 0x009d},
-	{&gcc_blsp1_qup1_spi_apps_clk.c,	GCC_BASE, 0x008a},
-	{&gcc_blsp1_uart2_apps_clk.c,		GCC_BASE, 0x0091},
-	{&gcc_blsp1_qup4_spi_apps_clk.c,	GCC_BASE, 0x0098},
-	{&gcc_blsp1_qup3_spi_apps_clk.c,	GCC_BASE, 0x0093},
-	{&gcc_blsp1_qup6_i2c_apps_clk.c,	GCC_BASE, 0x00a2},
-	{&gcc_bam_dma_ahb_clk.c,		GCC_BASE, 0x00e0},
-	{&gcc_sdcc3_apps_clk.c,			GCC_BASE, 0x0078},
-	{&gcc_usb_hs_system_clk.c,		GCC_BASE, 0x0060},
-	{&gcc_blsp1_ahb_clk.c,			GCC_BASE, 0x0088},
-	{&gcc_blsp1_uart4_apps_clk.c,		GCC_BASE, 0x009a},
-	{&gcc_blsp1_qup2_spi_apps_clk.c,	GCC_BASE, 0x008e},
-	{&gcc_usb_hsic_ahb_clk.c,		GCC_BASE, 0x0058},
-	{&gcc_blsp1_uart3_apps_clk.c,		GCC_BASE, 0x0095},
-	{&gcc_ce1_axi_clk.c,			GCC_BASE, 0x0139},
-	{&gcc_blsp1_qup5_spi_apps_clk.c,	GCC_BASE, 0x009c},
-	{&gcc_usb_hs_ahb_clk.c,			GCC_BASE, 0x0061},
-	{&gcc_blsp1_qup6_spi_apps_clk.c,	GCC_BASE, 0x00a1},
-	{&gcc_prng_ahb_clk.c,			GCC_BASE, 0x00d8},
-	{&gcc_blsp1_qup3_i2c_apps_clk.c,	GCC_BASE, 0x0094},
-	{&gcc_usb_hsic_clk.c,			GCC_BASE, 0x005a},
-	{&gcc_blsp1_uart6_apps_clk.c,		GCC_BASE, 0x00a3},
-	{&gcc_sdcc2_apps_clk.c,			GCC_BASE, 0x0070},
-	{&gcc_blsp1_uart1_apps_clk.c,		GCC_BASE, 0x008c},
-	{&gcc_blsp1_qup4_i2c_apps_clk.c,	GCC_BASE, 0x0099},
-	{&gcc_boot_rom_ahb_clk.c,		GCC_BASE, 0x00f8},
-	{&gcc_ce1_ahb_clk.c,			GCC_BASE, 0x013a},
-	{&gcc_pdm2_clk.c,			GCC_BASE, 0x00d2},
-	{&gcc_blsp1_uart5_apps_clk.c,		GCC_BASE, 0x009e},
-	{&gcc_blsp1_qup2_i2c_apps_clk.c,	GCC_BASE, 0x0090},
-	{&gcc_blsp1_qup1_i2c_apps_clk.c,	GCC_BASE, 0x008b},
-	{&gcc_sdcc2_ahb_clk.c,			GCC_BASE, 0x0071},
-	{&gcc_ce1_clk.c,			GCC_BASE, 0x0138},
-	{&gcc_sys_noc_ipa_axi_clk.c,		GCC_BASE, 0x0007},
-
-	{&audio_core_lpaif_pcm_data_oe_clk.c,	LPASS_BASE, 0x0030},
-	{&audio_core_slimbus_core_clk.c,	LPASS_BASE, 0x003d},
-	{&audio_core_lpaif_pri_clk_src.c,	LPASS_BASE, 0x0017},
-	{&audio_core_lpaif_sec_clk_src.c,	LPASS_BASE, 0x0016},
-	{&audio_core_slimbus_core_clk_src.c,	LPASS_BASE, 0x0011},
-	{&audio_core_lpaif_pcm1_clk_src.c,	LPASS_BASE, 0x0012},
-	{&audio_core_lpaif_pcm0_clk_src.c,	LPASS_BASE, 0x0013},
-	{&audio_core_lpaif_pcmoe_clk_src.c,	LPASS_BASE, 0x000f},
-	{&audio_core_slimbus_lfabif_clk.c,	LPASS_BASE, 0x003e},
-
-	{&a5_m_clk,				APCS_BASE, 0x3},
-
-	{&dummy_clk,				N_BASES,    0x0000},
-};
-
-static int measure_clk_set_parent(struct clk *c, struct clk *parent)
-{
-	struct measure_clk *clk = to_measure_clk(c);
-	unsigned long flags;
-	u32 regval, clk_sel, i;
-
-	if (!parent)
-		return -EINVAL;
-
-	for (i = 0; i < (ARRAY_SIZE(measure_mux) - 1); i++)
-		if (measure_mux[i].c == parent)
-			break;
-
-	if (measure_mux[i].c == &dummy_clk)
-		return -EINVAL;
-
-	spin_lock_irqsave(&local_clock_reg_lock, flags);
-	/*
-	 * Program the test vector, measurement period (sample_ticks)
-	 * and scaling multiplier.
-	 */
-	clk->sample_ticks = 0x10000;
-	clk->multiplier = 1;
-
-	writel_relaxed(0, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
-	writel_relaxed(0, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
-	switch (measure_mux[i].base) {
-
-	case GCC_BASE:
-		clk_sel = measure_mux[i].debug_mux;
-		break;
-
-	case LPASS_BASE:
-		clk_sel = 0x161;
-		regval = BVAL(15, 0, measure_mux[i].debug_mux);
-		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
-
-		/* Activate debug clock output */
-		regval |= BIT(20);
-		writel_relaxed(regval, LPASS_REG_BASE(LPASS_DEBUG_CLK_CTL_REG));
-		break;
-
-	case APCS_BASE:
-		clk_sel = 0x16A;
-		regval = BVAL(5, 3, measure_mux[i].debug_mux);
-		writel_relaxed(regval, APCS_REG_BASE(APCS_CLK_DIAG_REG));
-
-		/* Activate debug clock output */
-		regval |= BIT(7);
-		writel_relaxed(regval, APCS_REG_BASE(APCS_CLK_DIAG_REG));
-		break;
-
-	default:
-		return -EINVAL;
-	}
-
-	/* Set debug mux clock index */
-	regval = BVAL(8, 0, clk_sel);
-	writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
-	/* Activate debug clock output */
-	regval |= BIT(16);
-	writel_relaxed(regval, GCC_REG_BASE(GCC_DEBUG_CLK_CTL_REG));
-
-	/* Make sure test vector is set before starting measurements. */
-	mb();
-	spin_unlock_irqrestore(&local_clock_reg_lock, flags);
-
-	return 0;
-}
-
-/* Sample clock for 'ticks' reference clock ticks. */
-static u32 run_measurement(unsigned ticks)
-{
-	/* Stop counters and set the XO4 counter start value. */
-	writel_relaxed(ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL_REG));
-
-	/* Wait for timer to become ready. */
-	while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
-			BIT(25)) != 0)
-		cpu_relax();
-
-	/* Run measurement and wait for completion. */
-	writel_relaxed(BIT(20)|ticks, GCC_REG_BASE(CLOCK_FRQ_MEASURE_CTL_REG));
-	while ((readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
-			BIT(25)) == 0)
-		cpu_relax();
-
-	/* Return measured ticks. */
-	return readl_relaxed(GCC_REG_BASE(CLOCK_FRQ_MEASURE_STATUS_REG)) &
-				BM(24, 0);
-}
-
-/*
- * Perform a hardware rate measurement for a given clock.
- * FOR DEBUG USE ONLY: Measurements take ~15 ms!
- */
-static unsigned long measure_clk_get_rate(struct clk *c)
-{
-	unsigned long flags;
-	u32 gcc_xo4_reg_backup;
-	u64 raw_count_short, raw_count_full;
-	struct measure_clk *clk = to_measure_clk(c);
-	unsigned ret;
-
-	ret = clk_prepare_enable(&cxo_clk_src.c);
-	if (ret) {
-		pr_warning("CXO clock failed to enable. Can't measure\n");
-		return 0;
-	}
-
-	spin_lock_irqsave(&local_clock_reg_lock, flags);
-
-	/* Enable CXO/4 and RINGOSC branch. */
-	gcc_xo4_reg_backup = readl_relaxed(GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
-	writel_relaxed(0x1, GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
-
-	/*
-	 * The ring oscillator counter will not reset if the measured clock
-	 * is not running.  To detect this, run a short measurement before
-	 * the full measurement.  If the raw results of the two are the same
-	 * then the clock must be off.
-	 */
-
-	/* Run a short measurement. (~1 ms) */
-	raw_count_short = run_measurement(0x1000);
-	/* Run a full measurement. (~14 ms) */
-	raw_count_full = run_measurement(clk->sample_ticks);
-
-	writel_relaxed(gcc_xo4_reg_backup, GCC_REG_BASE(GCC_XO_DIV4_CBCR_REG));
-
-	/* Return 0 if the clock is off. */
-	if (raw_count_full == raw_count_short) {
-		ret = 0;
-	} else {
-		/* Compute rate in Hz. */
-		raw_count_full = ((raw_count_full * 10) + 15) * 4800000;
-		do_div(raw_count_full, ((clk->sample_ticks * 10) + 35));
-		ret = (raw_count_full * clk->multiplier);
-	}
-	/*TODO: Confirm this is value is correct */
-	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);
-
-	return ret;
-}
-#else /* !CONFIG_DEBUG_FS */
-static int measure_clk_set_parent(struct clk *clk, struct clk *parent)
-{
-	return -EINVAL;
-}
-
-static unsigned long measure_clk_get_rate(struct clk *clk)
-{
-	return 0;
-}
-#endif /* CONFIG_DEBUG_FS */
-
-static struct clk_ops clk_ops_measure = {
-	.set_parent = measure_clk_set_parent,
-	.get_rate = measure_clk_get_rate,
-};
-
-static struct measure_clk measure_clk = {
-	.c = {
-		.dbg_name = "measure_clk",
-		.ops = &clk_ops_measure,
-		CLK_INIT(measure_clk.c),
-	},
-	.multiplier = 1,
-};
-
-static struct clk_lookup msm_clocks_9625[] = {
-	CLK_LOOKUP("xo",	cxo_clk_src.c,	""),
-	CLK_LOOKUP("measure",	measure_clk.c,	"debug"),
-
-	CLK_LOOKUP("pll0",	gpll0_clk_src.c, "f9010000.qcom,acpuclk"),
-	CLK_LOOKUP("pll14",	apcspll_clk_src.c, "f9010000.qcom,acpuclk"),
-
-	CLK_LOOKUP("dma_bam_pclk", gcc_bam_dma_ahb_clk.c, ""),
-	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "msm_serial_hsl.0"),
-	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "spi_qsd.1"),
-	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, "f9966000.i2c"),
-	CLK_LOOKUP("iface_clk", gcc_blsp1_ahb_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_i2c_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup1_spi_apps_clk.c, "spi_qsd.1"),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup2_i2c_apps_clk.c, "f9966000.i2c"),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup2_spi_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup3_i2c_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup3_spi_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup4_i2c_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup4_spi_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup5_i2c_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_qup5_spi_apps_clk.c, ""),
-	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_uart4_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_uart5_apps_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_blsp1_uart6_apps_clk.c, ""),
-
-	CLK_LOOKUP("core_clk", gcc_ce1_clk.c, ""),
-	CLK_LOOKUP("iface_clk", gcc_ce1_ahb_clk.c, ""),
-	CLK_LOOKUP("bus_clk", gcc_ce1_axi_clk.c, ""),
-
-	CLK_LOOKUP("core_clk", gcc_gp1_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_gp2_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_gp3_clk.c, ""),
-
-	CLK_LOOKUP("core_src_clk", ipa_clk_src.c, ""),
-	CLK_LOOKUP("core_clk", gcc_ipa_clk.c, ""),
-	CLK_LOOKUP("bus_clk",  gcc_sys_noc_ipa_axi_clk.c, ""),
-	CLK_LOOKUP("iface_clk",  gcc_ipa_cnoc_clk.c, ""),
-
-	CLK_LOOKUP("core_clk", gcc_pdm2_clk.c, ""),
-	CLK_LOOKUP("iface_clk", gcc_pdm_ahb_clk.c, ""),
-
-	CLK_LOOKUP("core_clk", gcc_qpic_clk.c, ""),
-	CLK_LOOKUP("iface_clk", gcc_qpic_ahb_clk.c, ""),
-
-	CLK_LOOKUP("iface_clk", gcc_sdcc2_ahb_clk.c, "f98a4000.qcom,sdcc"),
-	CLK_LOOKUP("core_clk", gcc_sdcc2_apps_clk.c, "f98a4000.qcom,sdcc"),
-	CLK_LOOKUP("bus_clk",  pnoc_sdcc2_clk.c, "f98a4000.qcom,sdcc"),
-	CLK_LOOKUP("iface_clk", gcc_sdcc3_ahb_clk.c, ""),
-	CLK_LOOKUP("core_clk", gcc_sdcc3_apps_clk.c, ""),
-	CLK_LOOKUP("bus_clk", pnoc_sdcc3_clk.c, ""),
-
-	CLK_LOOKUP("iface_clk", gcc_usb_hs_ahb_clk.c,     "f9a55000.usb"),
-	CLK_LOOKUP("core_clk", gcc_usb_hs_system_clk.c,   "f9a55000.usb"),
-	CLK_LOOKUP("iface_clk", gcc_usb_hsic_ahb_clk.c,	  "f9a15000.hsic"),
-	CLK_LOOKUP("phy_clk", gcc_usb_hsic_clk.c,	  "f9a15000.hsic"),
-	CLK_LOOKUP("cal_clk", gcc_usb_hsic_io_cal_clk.c,  "f9a15000.hsic"),
-	CLK_LOOKUP("core_clk", gcc_usb_hsic_system_clk.c, "f9a15000.hsic"),
-	CLK_LOOKUP("alt_core_clk", gcc_usb_hsic_xcvr_fs_clk.c,
-							  "f9a15000.hsic"),
-
-	/* LPASS clocks */
-	CLK_LOOKUP("core_clk", audio_core_slimbus_core_clk.c, "fe12f000.slim"),
-	CLK_LOOKUP("iface_clk", audio_core_slimbus_lfabif_clk.c, ""),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_pri_clk_src.c, ""),
-	CLK_LOOKUP("osr_clk", audio_core_lpaif_pri_osr_clk.c, ""),
-	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pri_ebit_clk.c, ""),
-	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pri_ibit_clk.c, ""),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_sec_clk_src.c, ""),
-	CLK_LOOKUP("osr_clk", audio_core_lpaif_sec_osr_clk.c, ""),
-	CLK_LOOKUP("ebit_clk", audio_core_lpaif_sec_ebit_clk.c, ""),
-	CLK_LOOKUP("ibit_clk", audio_core_lpaif_sec_ibit_clk.c, ""),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm0_clk_src.c, ""),
-	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm0_ebit_clk.c, ""),
-	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm0_ibit_clk.c, ""),
-	CLK_LOOKUP("core_clk", audio_core_lpaif_pcm1_clk_src.c, ""),
-	CLK_LOOKUP("ebit_clk", audio_core_lpaif_pcm1_ebit_clk.c, ""),
-	CLK_LOOKUP("ibit_clk", audio_core_lpaif_pcm1_ibit_clk.c, ""),
-	CLK_LOOKUP("core_oe_src_clk", audio_core_lpaif_pcmoe_clk_src.c, ""),
-	CLK_LOOKUP("core_oe_clk", audio_core_lpaif_pcm_data_oe_clk.c, ""),
-
-	/* RPM and voter clocks */
-	CLK_LOOKUP("bus_clk", snoc_clk.c, ""),
-	CLK_LOOKUP("bus_clk", pnoc_clk.c, ""),
-	CLK_LOOKUP("bus_clk", cnoc_clk.c, ""),
-	CLK_LOOKUP("mem_clk", bimc_clk.c, ""),
-	CLK_LOOKUP("bus_clk", snoc_a_clk.c, ""),
-	CLK_LOOKUP("bus_clk", pnoc_a_clk.c, ""),
-	CLK_LOOKUP("bus_clk", cnoc_a_clk.c, ""),
-	CLK_LOOKUP("mem_clk", bimc_a_clk.c, ""),
-
-	CLK_LOOKUP("bus_clk",	cnoc_msmbus_clk.c,	""),
-	CLK_LOOKUP("bus_a_clk",	cnoc_msmbus_a_clk.c,	""),
-	CLK_LOOKUP("bus_clk",	snoc_msmbus_clk.c,	""),
-	CLK_LOOKUP("bus_a_clk",	snoc_msmbus_a_clk.c,	""),
-	CLK_LOOKUP("bus_clk",	pnoc_msmbus_clk.c,	""),
-	CLK_LOOKUP("bus_a_clk",	pnoc_msmbus_a_clk.c,	""),
-	CLK_LOOKUP("mem_clk",	bimc_msmbus_clk.c,	""),
-	CLK_LOOKUP("mem_a_clk",	bimc_msmbus_a_clk.c,	""),
-
-	CLK_LOOKUP("dfab_clk", pnoc_sps_clk.c, "msm_sps"),
-
-	CLK_LOOKUP("a5_m_clk", a5_m_clk, ""),
-};
-
-static struct pll_config_regs gpll0_regs __initdata = {
-	.l_reg = (void __iomem *)GPLL0_L_REG,
-	.m_reg = (void __iomem *)GPLL0_M_REG,
-	.n_reg = (void __iomem *)GPLL0_N_REG,
-	.config_reg = (void __iomem *)GPLL0_USER_CTL_REG,
-	.mode_reg = (void __iomem *)GPLL0_MODE_REG,
-	.base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL0 at 600 MHz, main output enabled. */
-static struct pll_config gpll0_config __initdata = {
-	.l = 0x1f,
-	.m = 0x1,
-	.n = 0x4,
-	.vco_val = 0x0,
-	.vco_mask = BM(21, 20),
-	.pre_div_val = 0x0,
-	.pre_div_mask = BM(14, 12),
-	.post_div_val = 0x0,
-	.post_div_mask = BM(9, 8),
-	.mn_ena_val = BIT(24),
-	.mn_ena_mask = BIT(24),
-	.main_output_val = BIT(0),
-	.main_output_mask = BIT(0),
-};
-
-static struct pll_config_regs gpll1_regs __initdata = {
-	.l_reg = (void __iomem *)GPLL1_L_REG,
-	.m_reg = (void __iomem *)GPLL1_M_REG,
-	.n_reg = (void __iomem *)GPLL1_N_REG,
-	.config_reg = (void __iomem *)GPLL1_USER_CTL_REG,
-	.mode_reg = (void __iomem *)GPLL1_MODE_REG,
-	.base = &virt_bases[GCC_BASE],
-};
-
-/* GPLL1 at 480 MHz, main output enabled. */
-static struct pll_config gpll1_config __initdata = {
-	.l = 0x19,
-	.m = 0x0,
-	.n = 0x1,
-	.vco_val = 0x0,
-	.vco_mask = BM(21, 20),
-	.pre_div_val = 0x0,
-	.pre_div_mask = BM(14, 12),
-	.post_div_val = 0x0,
-	.post_div_mask = BM(9, 8),
-	.main_output_val = BIT(0),
-	.main_output_mask = BIT(0),
-};
-
-static struct pll_config_regs lpapll0_regs __initdata = {
-	.l_reg = (void __iomem *)LPAPLL_L_REG,
-	.m_reg = (void __iomem *)LPAPLL_M_REG,
-	.n_reg = (void __iomem *)LPAPLL_N_REG,
-	.config_reg = (void __iomem *)LPAPLL_USER_CTL_REG,
-	.mode_reg = (void __iomem *)LPAPLL_MODE_REG,
-	.base = &virt_bases[LPASS_BASE],
-};
-
-/* LPAPLL0 at 393.216 MHz, main output enabled. */
-static struct pll_config lpapll0_config __initdata = {
-	.l = 0x28,
-	.m = 0x18,
-	.n = 0x19,
-	.vco_val = 0x0,
-	.vco_mask = BM(21, 20),
-	.pre_div_val = 0x0,
-	.pre_div_mask = BM(14, 12),
-	.post_div_val = BVAL(9, 8, 0x1),
-	.post_div_mask = BM(9, 8),
-	.mn_ena_val = BIT(24),
-	.mn_ena_mask = BIT(24),
-	.main_output_val = BIT(0),
-	.main_output_mask = BIT(0),
-};
-
-static struct pll_config_regs apcspll_regs __initdata = {
-	.l_reg = (void __iomem *)APCS_CPU_PLL_L_REG,
-	.m_reg = (void __iomem *)APCS_CPU_PLL_M_REG,
-	.n_reg = (void __iomem *)APCS_CPU_PLL_N_REG,
-	.config_reg = (void __iomem *)APCS_CPU_PLL_USER_CTL_REG,
-	.mode_reg = (void __iomem *)APCS_CPU_PLL_MODE_REG,
-	.base = &virt_bases[APCS_PLL_BASE],
-};
-
-/* A5PLL with 998.4MHz */
-static struct pll_config apcspll_config __initdata = {
-	.l = 0x34,
-	.m = 0x0,
-	.n = 0x1,
-	.vco_val = 0x0,
-	.vco_mask = BM(21, 20),
-	.pre_div_val = 0x0,
-	.pre_div_mask = BM(14, 12),
-	.post_div_val = BVAL(9, 8, 0x0),
-	.post_div_mask = BM(9, 8),
-	.mn_ena_val = BIT(24),
-	.mn_ena_mask = BIT(24),
-	.main_output_val = BIT(0),
-	.main_output_mask = BIT(0),
-};
-
-#define PLL_AUX_OUTPUT_BIT 1
-#define PLL_AUX2_OUTPUT_BIT 2
-
-static void __init configure_apcs_pll(void)
-{
-	u32 regval;
-
-	configure_sr_hpm_lp_pll(&apcspll_config, &apcspll_regs, 0);
-	writel_relaxed(0x00141200,
-			APCS_PLL_REG_BASE(APCS_CPU_PLL_CONFIG_CTL_REG));
-	regval = readl_relaxed(APCS_PLL_REG_BASE(APCS_CPU_PLL_USER_CTL_REG));
-	regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
-	writel_relaxed(regval, APCS_PLL_REG_BASE(APCS_CPU_PLL_USER_CTL_REG));
-}
-
-static void __init reg_init(void)
-{
-	u32 regval;
-
-	if (!(readl_relaxed(GCC_REG_BASE(GPLL0_STATUS_REG))
-			& gpll0_clk_src.status_mask))
-		configure_sr_hpm_lp_pll(&gpll0_config, &gpll0_regs, 1);
-
-	if (!(readl_relaxed(GCC_REG_BASE(GPLL1_STATUS_REG))
-			& gpll1_clk_src.status_mask))
-		configure_sr_hpm_lp_pll(&gpll1_config, &gpll1_regs, 1);
-
-	configure_sr_hpm_lp_pll(&lpapll0_config, &lpapll0_regs, 1);
-
-	/* TODO: Remove A5 pll configuration once the bootloader is avaiable */
-	regval = readl_relaxed(APCS_PLL_REG_BASE(APCS_CPU_PLL_MODE_REG));
-	if ((regval & BM(2, 0)) != 0x7)
-		configure_apcs_pll();
-
-	/* TODO:
-	 * 1) do we need to turn on AUX2 output too?
-	 * 2) if need to vote off all sleep clocks
-	 */
-
-	/* Enable GPLL0's aux outputs. */
-	regval = readl_relaxed(GCC_REG_BASE(GPLL0_USER_CTL_REG));
-	regval |= BIT(PLL_AUX_OUTPUT_BIT) | BIT(PLL_AUX2_OUTPUT_BIT);
-	writel_relaxed(regval, GCC_REG_BASE(GPLL0_USER_CTL_REG));
-
-	/* Vote for GPLL0 to turn on. Needed by acpuclock. */
-	regval = readl_relaxed(GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
-	regval |= BIT(0);
-	writel_relaxed(regval, GCC_REG_BASE(APCS_GPLL_ENA_VOTE_REG));
-
-	/*
-	 * TODO: Confirm that no clocks need to be voted on in this sleep vote
-	 * register.
-	 */
-	writel_relaxed(0x0, GCC_REG_BASE(APCS_CLOCK_SLEEP_ENA_VOTE));
-}
-
-static void __init msm9625_clock_post_init(void)
-{
-	/*
-	 * Hold an active set vote for CXO; this is because CXO is expected
-	 * to remain on whenever CPUs aren't power collapsed.
-	 */
-	clk_prepare_enable(&cxo_a_clk_src.c);
-
-	/* TODO :FIXME */
-	clk_prepare_enable(&gcc_qpic_ahb_clk.c);
-
-	/* Set rates for single-rate clocks. */
-	clk_set_rate(&usb_hs_system_clk_src.c,
-			usb_hs_system_clk_src.freq_tbl[0].freq_hz);
-	clk_set_rate(&usb_hsic_clk_src.c,
-			usb_hsic_clk_src.freq_tbl[0].freq_hz);
-	clk_set_rate(&usb_hsic_io_cal_clk_src.c,
-			usb_hsic_io_cal_clk_src.freq_tbl[0].freq_hz);
-	clk_set_rate(&usb_hsic_system_clk_src.c,
-			usb_hsic_system_clk_src.freq_tbl[0].freq_hz);
-	clk_set_rate(&usb_hsic_xcvr_fs_clk_src.c,
-			usb_hsic_xcvr_fs_clk_src.freq_tbl[0].freq_hz);
-	clk_set_rate(&pdm2_clk_src.c, pdm2_clk_src.freq_tbl[0].freq_hz);
-	clk_set_rate(&audio_core_slimbus_core_clk_src.c,
-			audio_core_slimbus_core_clk_src.freq_tbl[0].freq_hz);
-}
-
-#define GCC_CC_PHYS		0xFC400000
-#define GCC_CC_SIZE		SZ_16K
-
-#define LPASS_CC_PHYS		0xFE000000
-#define LPASS_CC_SIZE		SZ_256K
-
-#define APCS_GCC_CC_PHYS	0xF9011000
-#define APCS_GCC_CC_SIZE	SZ_4K
-
-#define APCS_PLL_PHYS		0xF9008018
-#define APCS_PLL_SIZE		0x18
-
-static void __init msm9625_clock_pre_init(void)
-{
-	virt_bases[GCC_BASE] = ioremap(GCC_CC_PHYS, GCC_CC_SIZE);
-	if (!virt_bases[GCC_BASE])
-		panic("clock-9625: Unable to ioremap GCC memory!");
-
-	virt_bases[LPASS_BASE] = ioremap(LPASS_CC_PHYS, LPASS_CC_SIZE);
-	if (!virt_bases[LPASS_BASE])
-		panic("clock-9625: Unable to ioremap LPASS_CC memory!");
-
-	virt_bases[APCS_BASE] = ioremap(APCS_GCC_CC_PHYS, APCS_GCC_CC_SIZE);
-	if (!virt_bases[APCS_BASE])
-		panic("clock-9625: Unable to ioremap APCS_GCC_CC memory!");
-
-	virt_bases[APCS_PLL_BASE] = ioremap(APCS_PLL_PHYS, APCS_PLL_SIZE);
-	if (!virt_bases[APCS_PLL_BASE])
-		panic("clock-9625: Unable to ioremap APCS_PLL memory!");
-
-	clk_ops_local_pll.enable = sr_hpm_lp_pll_clk_enable;
-
-	reg_init();
-}
-
-/* TODO: Add vdd level unvote */
-static int __init msm9625_clock_late_init(void)
-{
-	return 0;
-}
-
-struct clock_init_data msm9625_clock_init_data __initdata = {
-	.table = msm_clocks_9625,
-	.size = ARRAY_SIZE(msm_clocks_9625),
-	.pre_init = msm9625_clock_pre_init,
-	.post_init = msm9625_clock_post_init,
-	.late_init = msm9625_clock_late_init,
-};
diff --git a/arch/arm/mach-msm/clock-debug.c b/arch/arm/mach-msm/clock-debug.c
index e942173..8bd4433 100644
--- a/arch/arm/mach-msm/clock-debug.c
+++ b/arch/arm/mach-msm/clock-debug.c
@@ -218,6 +218,28 @@
 	.release	= seq_release,
 };
 
+static int clock_parent_show(struct seq_file *m, void *unused)
+{
+	struct clk *clock = m->private;
+	struct clk *parent = clk_get_parent(clock);
+
+	seq_printf(m, "%s\n", (parent ? parent->dbg_name : "None"));
+
+	return 0;
+}
+
+static int clock_parent_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, clock_parent_show, inode->i_private);
+}
+
+static const struct file_operations clock_parent_fops = {
+	.open		= clock_parent_open,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+	.release	= seq_release,
+};
+
 static struct dentry *debugfs_base;
 static u32 debug_suspend;
 
@@ -274,6 +296,10 @@
 				S_IRUGO, clk_dir, clock, &fmax_rates_fops))
 			goto error;
 
+	if (!debugfs_create_file("parent", S_IRUGO, clk_dir, clock,
+				&clock_parent_fops))
+			goto error;
+
 	return 0;
 error:
 	debugfs_remove_recursive(clk_dir);
diff --git a/arch/arm/mach-msm/clock.c b/arch/arm/mach-msm/clock.c
index eead627..c30bd79 100644
--- a/arch/arm/mach-msm/clock.c
+++ b/arch/arm/mach-msm/clock.c
@@ -133,6 +133,18 @@
 	unvote_vdd_level(clk->vdd_class, level);
 }
 
+/* Returns true if the rate is valid without voting for it */
+static bool is_rate_valid(struct clk *clk, unsigned long rate)
+{
+	int level;
+
+	if (!clk->vdd_class)
+		return true;
+
+	level = find_vdd_level(clk, rate);
+	return level >= 0;
+}
+
 int clk_prepare(struct clk *clk)
 {
 	int ret = 0;
@@ -331,14 +343,16 @@
 		/* Enforce vdd requirements for target frequency. */
 		rc = vote_rate_vdd(clk, rate);
 		if (rc)
-			goto err_vote_vdd;
+			goto out;
 		rc = clk->ops->set_rate(clk, rate);
 		if (rc)
 			goto err_set_rate;
 		/* Release vdd requirements for starting frequency. */
 		unvote_rate_vdd(clk, start_rate);
-	} else {
+	} else if (is_rate_valid(clk, rate)) {
 		rc = clk->ops->set_rate(clk, rate);
+	} else {
+		rc = -EINVAL;
 	}
 
 	if (!rc)
@@ -349,7 +363,6 @@
 
 err_set_rate:
 	unvote_rate_vdd(clk, rate);
-err_vote_vdd:
 	goto out;
 }
 EXPORT_SYMBOL(clk_set_rate);
diff --git a/arch/arm/mach-msm/clock.h b/arch/arm/mach-msm/clock.h
index 8a75d390..48f897b 100644
--- a/arch/arm/mach-msm/clock.h
+++ b/arch/arm/mach-msm/clock.h
@@ -34,7 +34,6 @@
 };
 
 extern struct clock_init_data msm9615_clock_init_data;
-extern struct clock_init_data msm9625_clock_init_data;
 extern struct clock_init_data apq8064_clock_init_data;
 extern struct clock_init_data fsm9xxx_clock_init_data;
 extern struct clock_init_data msm7x01a_clock_init_data;
diff --git a/arch/arm/mach-msm/devices-iommu.c b/arch/arm/mach-msm/devices-iommu.c
index acf577e..6434a63 100644
--- a/arch/arm/mach-msm/devices-iommu.c
+++ b/arch/arm/mach-msm/devices-iommu.c
@@ -1017,13 +1017,13 @@
 				ARRAY_SIZE(msm_iommu_gfx2d_devs));
 	}
 
-	if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+	if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
 		platform_add_devices(msm_iommu_jpegd_devs,
 				ARRAY_SIZE(msm_iommu_jpegd_devs));
 		platform_add_devices(msm_iommu_adreno3xx_gfx_devs,
 				ARRAY_SIZE(msm_iommu_adreno3xx_gfx_devs));
 	}
-	if (cpu_is_apq8064())
+	if (cpu_is_apq8064() || cpu_is_apq8064ab())
 		platform_add_devices(msm_iommu_vcap_devs,
 				ARRAY_SIZE(msm_iommu_vcap_devs));
 
@@ -1039,14 +1039,14 @@
 				ARRAY_SIZE(msm_iommu_gfx2d_ctx_devs));
 	}
 
-	if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+	if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
 		platform_add_devices(msm_iommu_jpegd_ctx_devs,
 				ARRAY_SIZE(msm_iommu_jpegd_ctx_devs));
 
 		platform_add_devices(msm_iommu_adreno3xx_ctx_devs,
 				ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs));
 	}
-	if (cpu_is_apq8064())
+	if (cpu_is_apq8064() || cpu_is_apq8064ab())
 		platform_add_devices(msm_iommu_vcap_ctx_devs,
 			ARRAY_SIZE(msm_iommu_vcap_ctx_devs));
 
@@ -1081,12 +1081,12 @@
 		for (i = 0; i < ARRAY_SIZE(msm_iommu_jpegd_devs); i++)
 			platform_device_unregister(msm_iommu_jpegd_devs[i]);
 	}
-	if (cpu_is_apq8064()) {
+	if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 		for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_ctx_devs); i++)
 			platform_device_unregister(msm_iommu_vcap_ctx_devs[i]);
 	}
 
-	if (cpu_is_apq8064() || cpu_is_msm8960ab()) {
+	if (cpu_is_apq8064() || cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
 		for (i = 0; i < ARRAY_SIZE(msm_iommu_adreno3xx_ctx_devs);
 			   i++)
 			platform_device_unregister(
@@ -1097,7 +1097,7 @@
 			platform_device_unregister(
 				msm_iommu_jpegd_ctx_devs[i]);
 
-		if (cpu_is_apq8064()) {
+		if (cpu_is_apq8064() || cpu_is_apq8064ab()) {
 			for (i = 0; i < ARRAY_SIZE(msm_iommu_vcap_devs);
 			   i++)
 				platform_device_unregister(
diff --git a/arch/arm/mach-msm/devices-msm7x27a.c b/arch/arm/mach-msm/devices-msm7x27a.c
index 65dfc31..50ab26f 100644
--- a/arch/arm/mach-msm/devices-msm7x27a.c
+++ b/arch/arm/mach-msm/devices-msm7x27a.c
@@ -1664,12 +1664,13 @@
  * These are various Vdd levels supported by PMIC
  */
 static uint32_t msm_c2_pmic_mv[] __initdata = {
-	1300000, 1287500, 1275000, 1262500, 1250000,
-	1237500, 1225000, 1212500, 1200000, 1187500,
-	1175000, 1162500, 1150000, 1137500, 1125000,
-	1112500, 1100000, 1087500, 1075000, 1062500,
-	1050000, 1037500, 1025000, 1012500, 0, 0, 0,
-	0, 0, 0, 0, 1000,
+	1350000, 1337500, 1325000, 1312500, 1300000,
+	1287500, 1275000, 1262500, 1250000, 1237500,
+	1225000, 1212500, 1200000, 1187500, 1175000,
+	1162500, 1150000, 1137500, 1125000, 1112500,
+	1100000, 1087500, 1075000, 1062500, 0,
+	0,	 0,	  0,	   0,	    0,
+	0, 1050000,
 };
 
 /**
@@ -1709,9 +1710,9 @@
 			.step_quot = ~0,
 			.tgt_volt_offset = 0,
 			.turbo_Vmax = 1350000,
-			.turbo_Vmin = 950000,
+			.turbo_Vmin = 1100000,
 			.nom_Vmax = 1350000,
-			.nom_Vmin = 950000,
+			.nom_Vmin = 1100000,
 			.calibrated_uV = 1300000,
 	},
 };
@@ -1729,7 +1730,7 @@
 	uint32_t quot;
 
 	/* This formula is as per chip characterization data */
-	quot = max_quot - (((max_freq - new_freq) * 5) / 10);
+	quot = max_quot - (((max_freq - new_freq) * 7) / 10);
 
 	return quot;
 }
@@ -1749,7 +1750,7 @@
 
 static struct msm_cpr_config msm_cpr_pdata = {
 	.ref_clk_khz = 19200,
-	.delay_us = 25000,
+	.delay_us = 1000,
 	.irq_line = 0,
 	.cpr_mode_data = msm_cpr_mode_data,
 	.tgt_count_div_N = 1,
@@ -1757,7 +1758,7 @@
 	.ceiling = 40,
 	.sw_vlevel = 20,
 	.up_threshold = 1,
-	.dn_threshold = 2,
+	.dn_threshold = 4,
 	.up_margin = 0,
 	.dn_margin = 0,
 	.max_nom_freq = 700800,
@@ -1819,6 +1820,22 @@
 	 * enough to represent the value of maximum quot
 	 */
 	msm_cpr_pdata.max_quot = cpr_info->turbo_quot * 10 + 600;
+	/**
+	 * Fused Quot value for 1.2GHz on a 1.2GHz part is lower than
+	 * the quot value calculated using the scaling factor formula for
+	 * 1.2GHz when running on a 1.4GHz part. So, prop up the Quot for
+	 * a 1.2GHz part by a chip characterization recommended value.
+	 * Ditto for a 1.0GHz part.
+	 */
+	if (msm8625_cpu_id() == MSM8625A) {
+		msm_cpr_pdata.max_quot += 100;
+		if (msm_cpr_pdata.max_quot > 1400)
+			msm_cpr_pdata.max_quot = 1400;
+	} else if (msm8625_cpu_id() == MSM8625) {
+		msm_cpr_pdata.max_quot += 120;
+		if (msm_cpr_pdata.max_quot > 1350)
+			msm_cpr_pdata.max_quot = 1350;
+	}
 
 	/**
 	 * Bits 4:0 of pvs_fuse provide mapping to the safe boot up voltage.
diff --git a/arch/arm/mach-msm/devices-msm8x60.c b/arch/arm/mach-msm/devices-msm8x60.c
index 7bffd9b..b88fb50 100644
--- a/arch/arm/mach-msm/devices-msm8x60.c
+++ b/arch/arm/mach-msm/devices-msm8x60.c
@@ -210,6 +210,7 @@
 };
 
 #define MSM_MSS_REGS_PHYS 0x10200000
+#define MSM_MSS_WDOG_PHYS 0x10020000
 
 static struct resource msm_8660_modem_resources[] = {
 	{
@@ -217,6 +218,16 @@
 		.end    = MSM_MSS_REGS_PHYS + SZ_256 - 1,
 		.flags  = IORESOURCE_MEM,
 	},
+	{
+		.start	= MSM_MSS_WDOG_PHYS,
+		.end	= MSM_MSS_WDOG_PHYS + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= MARM_WDOG_EXPIRED,
+		.end	= MARM_WDOG_EXPIRED,
+		.flags	= IORESOURCE_IRQ,
+	},
 };
 
 struct platform_device msm_pil_modem = {
diff --git a/arch/arm/mach-msm/gss-8064.c b/arch/arm/mach-msm/gss-8064.c
index e528650..ba6af61 100644
--- a/arch/arm/mach-msm/gss-8064.c
+++ b/arch/arm/mach-msm/gss-8064.c
@@ -200,7 +200,7 @@
 {
 	int ret;
 
-	if (!cpu_is_apq8064())
+	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()))
 		return -ENODEV;
 
 	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
diff --git a/arch/arm/mach-msm/include/mach/iommu.h b/arch/arm/mach-msm/include/mach/iommu.h
index b14f145..f63af64 100644
--- a/arch/arm/mach-msm/include/mach/iommu.h
+++ b/arch/arm/mach-msm/include/mach/iommu.h
@@ -38,6 +38,8 @@
 /* Maximum number of SMT entries allowed by the system */
 #define MAX_NUM_SMR	128
 
+#define MAX_NUM_BFB_REGS	32
+
 /**
  * struct msm_iommu_dev - a single IOMMU hardware instance
  * name		Human-readable name given to this IOMMU HW instance
@@ -64,6 +66,17 @@
 	int mids[MAX_NUM_MIDS];
 };
 
+/**
+ * struct msm_iommu_bfb_settings - a set of IOMMU BFB tuning parameters
+ * regs		An array of register offsets to configure
+ * data		Values to write to corresponding registers
+ * length	Number of valid entries in the offset/val arrays
+ */
+struct msm_iommu_bfb_settings {
+	unsigned int regs[MAX_NUM_BFB_REGS];
+	unsigned int data[MAX_NUM_BFB_REGS];
+	int length;
+};
 
 /**
  * struct msm_iommu_drvdata - A single IOMMU hardware instance
@@ -76,6 +89,7 @@
  * @name:	Human-readable name of this IOMMU device
  * @gdsc:	Regulator needed to power this HW block (v2 only)
  * @nsmr:	Size of the SMT on this HW block (v2 only)
+ * @bfb_settings: Optional BFB performance tuning parameters
  *
  * A msm_iommu_drvdata holds the global driver data about a single piece
  * of an IOMMU hardware instance.
@@ -90,6 +104,7 @@
 	const char *name;
 	struct regulator *gdsc;
 	unsigned int nsmr;
+	struct msm_iommu_bfb_settings *bfb_settings;
 };
 
 /**
diff --git a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
index b01dbd8..c4991bf 100644
--- a/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
+++ b/arch/arm/mach-msm/include/mach/iommu_hw-v2.h
@@ -15,6 +15,8 @@
 
 #define CTX_SHIFT  12
 #define CTX_OFFSET 0x8000
+#define IMPLDEF_OFFSET	0x2000
+#define IMPLDEF_LENGTH	0xDFF
 
 #define GET_GLOBAL_REG(reg, base) (readl_relaxed((base) + (reg)))
 #define GET_CTX_REG(reg, base, ctx) \
diff --git a/arch/arm/mach-msm/include/mach/irqs-8625.h b/arch/arm/mach-msm/include/mach/irqs-8625.h
index 413a778..2ec0e21 100644
--- a/arch/arm/mach-msm/include/mach/irqs-8625.h
+++ b/arch/arm/mach-msm/include/mach/irqs-8625.h
@@ -87,6 +87,8 @@
 #define MSM8625_INT_CPR_IRQ0		(GIC_SPI_START + 32 + 25)
 #define MSM8625_INT_CPR_IRQ1		(GIC_SPI_START + 32 + 26)
 #define MSM8625_INT_CPR_IRQ2		(GIC_SPI_START + 32 + 27)
+#define MSM8625_INT_ACSR_MP_CORE_IPC2	(GIC_SPI_START + 32 + 28)
+#define MSM8625_INT_ACSR_MP_CORE_IPC3	(GIC_SPI_START + 32 + 29)
 
 #define MSM8625_INT_ADSP_A11_SMSM	MSM8625_INT_ADSP_A11
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_iomap.h b/arch/arm/mach-msm/include/mach/msm_iomap.h
index 6f925d4..8dbd29c 100644
--- a/arch/arm/mach-msm/include/mach/msm_iomap.h
+++ b/arch/arm/mach-msm/include/mach/msm_iomap.h
@@ -101,7 +101,7 @@
 #define MSM_DBG_IMEM_BASE	IOMEM(0xFB600000)	/*  4K */
 
 #define MSM_STRONGLY_ORDERED_PAGE	0xFA0F0000
-#define MSM8625_SECONDARY_PHYS		0x0FE00000
+#define MSM8625_CPU_PHYS		0x0FE00000
 
 
 #if defined(CONFIG_ARCH_MSM9615) || defined(CONFIG_ARCH_MSM7X27) \
diff --git a/arch/arm/mach-msm/include/mach/msm_smsm.h b/arch/arm/mach-msm/include/mach/msm_smsm.h
index be8f6c1..44b52b6 100644
--- a/arch/arm/mach-msm/include/mach/msm_smsm.h
+++ b/arch/arm/mach-msm/include/mach/msm_smsm.h
@@ -57,8 +57,7 @@
 #define SMSM_PWRC              0x00000200
 #define SMSM_TIMEWAIT          0x00000400
 #define SMSM_TIMEINIT          0x00000800
-#define SMSM_PWRC_EARLY_EXIT   0x00001000
-#define SMSM_LTE_COEX_AWAKE    0x00001000
+#define SMSM_PROC_AWAKE        0x00001000
 #define SMSM_WFPI              0x00002000
 #define SMSM_SLEEP             0x00004000
 #define SMSM_SLEEPEXIT         0x00008000
diff --git a/arch/arm/mach-msm/include/mach/socinfo.h b/arch/arm/mach-msm/include/mach/socinfo.h
index 546cbaf..225440c 100644
--- a/arch/arm/mach-msm/include/mach/socinfo.h
+++ b/arch/arm/mach-msm/include/mach/socinfo.h
@@ -89,6 +89,7 @@
 	MSM_CPU_7X25AA,
 	MSM_CPU_7X25AB,
 	MSM_CPU_8064,
+	MSM_CPU_8064AB,
 	MSM_CPU_8930,
 	MSM_CPU_8930AA,
 	MSM_CPU_7X27AA,
@@ -304,6 +305,15 @@
 #endif
 }
 
+static inline int cpu_is_apq8064ab(void)
+{
+#ifdef CONFIG_ARCH_APQ8064
+	return read_msm_cpu_type() == MSM_CPU_8064AB;
+#else
+	return 0;
+#endif
+}
+
 static inline int cpu_is_msm8930(void)
 {
 #ifdef CONFIG_ARCH_MSM8930
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index 74c1c4a..a785389 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -173,63 +173,29 @@
 
 struct reserve_info *reserve_info;
 
-static unsigned long stable_size(struct membank *mb,
-	unsigned long unstable_limit)
-{
-	unsigned long upper_limit = mb->start + mb->size;
-
-	if (!unstable_limit)
-		return mb->size;
-
-	/* Check for 32 bit roll-over */
-	if (upper_limit >= mb->start) {
-		/* If we didn't roll over we can safely make the check below */
-		if (upper_limit <= unstable_limit)
-			return mb->size;
-	}
-
-	if (mb->start >= unstable_limit)
-		return 0;
-	return unstable_limit - mb->start;
-}
-
-/* stable size of all memory banks contiguous to and below this one */
-static unsigned long total_stable_size(unsigned long bank)
-{
-	int i;
-	struct membank *mb = &meminfo.bank[bank];
-	int memtype = reserve_info->paddr_to_memtype(mb->start);
-	unsigned long size;
-
-	size = stable_size(mb, reserve_info->low_unstable_address);
-	for (i = bank - 1, mb = &meminfo.bank[bank - 1]; i >= 0; i--, mb--) {
-		if (mb->start + mb->size != (mb + 1)->start)
-			break;
-		if (reserve_info->paddr_to_memtype(mb->start) != memtype)
-			break;
-		size += stable_size(mb, reserve_info->low_unstable_address);
-	}
-	return size;
-}
-
+/**
+ * calculate_reserve_limits() - calculate reserve limits for all
+ * memtypes
+ *
+ * for each memtype in the reserve_info->memtype_reserve_table, sets
+ * the `limit' field to the largest size of any memblock of that
+ * memtype.
+ */
 static void __init calculate_reserve_limits(void)
 {
-	int i;
-	struct membank *mb;
+	struct memblock_region *mr;
 	int memtype;
 	struct memtype_reserve *mt;
-	unsigned long size;
 
-	for (i = 0, mb = &meminfo.bank[0]; i < meminfo.nr_banks; i++, mb++)  {
-		memtype = reserve_info->paddr_to_memtype(mb->start);
+	for_each_memblock(memory, mr) {
+		memtype = reserve_info->paddr_to_memtype(mr->base);
 		if (memtype == MEMTYPE_NONE) {
-			pr_warning("unknown memory type for bank at %lx\n",
-				(long unsigned int)mb->start);
+			pr_warning("unknown memory type for region at %lx\n",
+				(long unsigned int)mr->base);
 			continue;
 		}
 		mt = &reserve_info->memtype_reserve_table[memtype];
-		size = total_stable_size(i);
-		mt->limit = max(mt->limit, size);
+		mt->limit = max_t(unsigned long, mt->limit, mr->size);
 	}
 }
 
@@ -252,50 +218,38 @@
 
 static void __init reserve_memory_for_mempools(void)
 {
-	int i, memtype, membank_type;
+	int memtype, memreg_type;
 	struct memtype_reserve *mt;
-	struct membank *mb;
+	struct memblock_region *mr, *mr_candidate = NULL;
 	int ret;
-	unsigned long size;
 
 	mt = &reserve_info->memtype_reserve_table[0];
 	for (memtype = 0; memtype < MEMTYPE_MAX; memtype++, mt++) {
 		if (mt->flags & MEMTYPE_FLAGS_FIXED || !mt->size)
 			continue;
 
-		/* We know we will find memory bank(s) of the proper size
-		 * as we have limited the size of the memory pool for
-		 * each memory type to the largest total size of the memory
-		 * banks which are contiguous and of the correct memory type.
-		 * Choose the memory bank with the highest physical
+		/* Choose the memory block with the highest physical
 		 * address which is large enough, so that we will not
 		 * take memory from the lowest memory bank which the kernel
 		 * is in (and cause boot problems) and so that we might
 		 * be able to steal memory that would otherwise become
-		 * highmem. However, do not use unstable memory.
+		 * highmem.
 		 */
-		for (i = meminfo.nr_banks - 1; i >= 0; i--) {
-			mb = &meminfo.bank[i];
-			membank_type =
-				reserve_info->paddr_to_memtype(mb->start);
-			if (memtype != membank_type)
+		for_each_memblock(memory, mr) {
+			memreg_type =
+				reserve_info->paddr_to_memtype(mr->base);
+			if (memtype != memreg_type)
 				continue;
-			size = total_stable_size(i);
-			if (size >= mt->size) {
-				size = stable_size(mb,
-					reserve_info->low_unstable_address);
-				if (!size)
-					continue;
-				/* mt->size may be larger than size, all this
-				 * means is that we are carving the memory pool
-				 * out of multiple contiguous memory banks.
-				 */
-				mt->start = mb->start + (size - mt->size);
-				ret = memblock_remove(mt->start, mt->size);
-				BUG_ON(ret);
-				break;
-			}
+			if (mr->size >= mt->size
+				&& (mr_candidate == NULL
+					|| mr->base > mr_candidate->base))
+				mr_candidate = mr;
 		}
+		BUG_ON(mr_candidate == NULL);
+		/* bump mt up against the top of the region */
+		mt->start = mr_candidate->base + mr_candidate->size - mt->size;
+		ret = memblock_remove(mt->start, mt->size);
+		BUG_ON(ret);
 	}
 }
 
diff --git a/arch/arm/mach-msm/modem-8660.c b/arch/arm/mach-msm/modem-8660.c
deleted file mode 100644
index 096ed9c..0000000
--- a/arch/arm/mach-msm/modem-8660.c
+++ /dev/null
@@ -1,290 +0,0 @@
-/* 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/interrupt.h>
-#include <linux/reboot.h>
-#include <linux/workqueue.h>
-#include <linux/io.h>
-#include <linux/jiffies.h>
-#include <linux/stringify.h>
-#include <linux/delay.h>
-#include <linux/module.h>
-#include <linux/err.h>
-
-#include <mach/irqs.h>
-#include <mach/scm.h>
-#include <mach/peripheral-loader.h>
-#include <mach/subsystem_restart.h>
-#include <mach/subsystem_notif.h>
-
-#include "smd_private.h"
-#include "modem_notifier.h"
-#include "ramdump.h"
-
-#define MODEM_HWIO_MSS_RESET_ADDR       0x00902C48
-#define MODULE_NAME			"modem_8660"
-#define MODEM_WDOG_ENABLE		0x10020008
-#define MODEM_CLEANUP_DELAY_MS		20
-
-#define SUBSYS_FATAL_DEBUG
-
-#if defined(SUBSYS_FATAL_DEBUG)
-static void debug_crash_modem_fn(struct work_struct *);
-static int reset_modem;
-static int ignore_smsm_ack;
-
-static DECLARE_DELAYED_WORK(debug_crash_modem_work,
-				debug_crash_modem_fn);
-
-module_param(reset_modem, int, 0644);
-#endif
-
-static struct subsys_device *modem_8660_dev;
-
-/* Subsystem restart: Modem data, functions */
-static void *modem_ramdump_dev;
-static void modem_fatal_fn(struct work_struct *);
-static void modem_unlock_timeout(struct work_struct *work);
-static int modem_notif_handler(struct notifier_block *this,
-				unsigned long code,
-				void *_cmd);
-static DECLARE_WORK(modem_fatal_work, modem_fatal_fn);
-static DECLARE_DELAYED_WORK(modem_unlock_timeout_work,
-				modem_unlock_timeout);
-
-static struct notifier_block modem_notif_nb = {
-	.notifier_call = modem_notif_handler,
-};
-
-static void modem_unlock_timeout(struct work_struct *work)
-{
-	void __iomem *hwio_modem_reset_addr =
-			ioremap_nocache(MODEM_HWIO_MSS_RESET_ADDR, 8);
-	pr_crit("%s: Timeout waiting for modem to unlock.\n", MODULE_NAME);
-
-	/* Set MSS_MODEM_RESET to 0x0 since the unlock didn't work */
-	writel_relaxed(0x0, hwio_modem_reset_addr);
-	/* Write needs to go through before the modem is restarted. */
-	mb();
-	iounmap(hwio_modem_reset_addr);
-
-	subsystem_restart_dev(modem_8660_dev);
-	enable_irq(MARM_WDOG_EXPIRED);
-}
-
-static void modem_fatal_fn(struct work_struct *work)
-{
-	uint32_t modem_state;
-	uint32_t panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
-	uint32_t reset_smsm_states = SMSM_SYSTEM_REBOOT_USR |
-					SMSM_SYSTEM_PWRDWN_USR;
-
-	pr_err("%s: Watchdog bite received from modem!\n", MODULE_NAME);
-
-	modem_state = smsm_get_state(SMSM_MODEM_STATE);
-	pr_err("%s: Modem SMSM state = 0x%x!", MODULE_NAME, modem_state);
-
-	if (modem_state == 0 || modem_state & panic_smsm_states) {
-
-		subsystem_restart_dev(modem_8660_dev);
-		enable_irq(MARM_WDOG_EXPIRED);
-
-	} else if (modem_state & reset_smsm_states) {
-
-		pr_err("%s: User-invoked system reset/powerdown.",
-			MODULE_NAME);
-		kernel_restart(NULL);
-
-	} else {
-
-		int ret;
-		void *hwio_modem_reset_addr =
-				ioremap_nocache(MODEM_HWIO_MSS_RESET_ADDR, 8);
-
-		pr_err("%s: Modem AHB locked up.\n", MODULE_NAME);
-		pr_err("%s: Trying to free up modem!\n", MODULE_NAME);
-
-		writel_relaxed(0x3, hwio_modem_reset_addr);
-
-		/* If we are still alive after 6 seconds (allowing for
-		 * the 5-second-delayed-panic-reboot), modem is either
-		 * still wedged or SMSM didn't come through. Force panic
-		 * in that case.
-		*/
-		ret = schedule_delayed_work(&modem_unlock_timeout_work,
-					msecs_to_jiffies(6000));
-
-		iounmap(hwio_modem_reset_addr);
-	}
-}
-
-static int modem_notif_handler(struct notifier_block *this,
-				unsigned long code,
-				void *_cmd)
-{
-	if (code == MODEM_NOTIFIER_START_RESET) {
-		if (ignore_smsm_ack) {
-			ignore_smsm_ack = 0;
-			goto out;
-		}
-		pr_err("%s: Modem error fatal'ed.", MODULE_NAME);
-		subsystem_restart_dev(modem_8660_dev);
-	}
-out:
-	return NOTIFY_DONE;
-}
-
-static int modem_shutdown(const struct subsys_desc *crashed_subsys)
-{
-	void __iomem *modem_wdog_addr;
-
-	/* If the modem didn't already crash, setting SMSM_RESET
-	 * here will help flush caches etc. The ignore_smsm_ack
-	 * flag is set to ignore the SMSM_RESET notification
-	 * that is generated due to the modem settings its own
-	 * SMSM_RESET bit in response to the apps setting the
-	 * apps SMSM_RESET bit.
-	 */
-	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
-		ignore_smsm_ack = 1;
-		smsm_reset_modem(SMSM_RESET);
-	}
-
-	/* Disable the modem watchdog to allow clean modem bootup */
-	modem_wdog_addr = ioremap_nocache(MODEM_WDOG_ENABLE, 8);
-	writel_relaxed(0x0, modem_wdog_addr);
-
-	/*
-	 * The write above needs to go through before the modem is
-	 * powered up again (subsystem restart).
-	 */
-	mb();
-	iounmap(modem_wdog_addr);
-
-	/* Wait here to allow the modem to clean up caches etc. */
-	msleep(MODEM_CLEANUP_DELAY_MS);
-	pil_force_shutdown("modem");
-	disable_irq_nosync(MARM_WDOG_EXPIRED);
-
-
-
-	return 0;
-}
-
-static int modem_powerup(const struct subsys_desc *crashed_subsys)
-{
-	int ret;
-
-	ret = pil_force_boot("modem");
-	enable_irq(MARM_WDOG_EXPIRED);
-
-	return ret;
-}
-
-/* FIXME: Get address, size from PIL */
-static struct ramdump_segment modem_segments[] = {
-	{0x42F00000, 0x46000000 - 0x42F00000} };
-
-static int modem_ramdump(int enable, const struct subsys_desc *crashed_subsys)
-{
-	if (enable)
-		return do_ramdump(modem_ramdump_dev, modem_segments,
-			ARRAY_SIZE(modem_segments));
-	else
-		return 0;
-}
-
-static void modem_crash_shutdown(const struct subsys_desc *crashed_subsys)
-{
-	/* If modem hasn't already crashed, send SMSM_RESET. */
-	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
-		modem_unregister_notifier(&modem_notif_nb);
-		smsm_reset_modem(SMSM_RESET);
-	}
-
-	/* Wait to allow the modem to clean up caches etc. */
-	mdelay(5);
-}
-
-static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
-{
-	int ret;
-
-	ret = schedule_work(&modem_fatal_work);
-	disable_irq_nosync(MARM_WDOG_EXPIRED);
-
-	return IRQ_HANDLED;
-}
-
-static struct subsys_desc subsys_8660_modem = {
-	.name = "modem",
-	.shutdown = modem_shutdown,
-	.powerup = modem_powerup,
-	.ramdump = modem_ramdump,
-	.crash_shutdown = modem_crash_shutdown
-};
-
-static int __init modem_8660_init(void)
-{
-	int ret;
-
-	/* Need to listen for SMSM_RESET always */
-	modem_register_notifier(&modem_notif_nb);
-
-#if defined(SUBSYS_FATAL_DEBUG)
-	schedule_delayed_work(&debug_crash_modem_work, msecs_to_jiffies(5000));
-#endif
-
-	ret = request_irq(MARM_WDOG_EXPIRED, modem_wdog_bite_irq,
-			IRQF_TRIGGER_RISING, "modem_wdog", NULL);
-
-	if (ret < 0) {
-		pr_err("%s: Unable to request MARM_WDOG_EXPIRED irq.",
-			__func__);
-		goto out;
-	}
-
-	modem_ramdump_dev = create_ramdump_device("modem");
-
-	if (!modem_ramdump_dev) {
-		ret = -ENOMEM;
-		goto out;
-	}
-
-	modem_8660_dev = subsys_register(&subsys_8660_modem);
-	if (IS_ERR(modem_8660_dev))
-		ret = PTR_ERR(modem_8660_dev);
-out:
-	return ret;
-}
-
-static void __exit modem_8660_exit(void)
-{
-	subsys_unregister(modem_8660_dev);
-	free_irq(MARM_WDOG_EXPIRED, NULL);
-}
-
-#ifdef SUBSYS_FATAL_DEBUG
-static void debug_crash_modem_fn(struct work_struct *work)
-{
-	if (reset_modem == 1)
-		smsm_reset_modem(SMSM_RESET);
-
-	reset_modem = 0;
-	schedule_delayed_work(&debug_crash_modem_work, msecs_to_jiffies(1000));
-}
-#endif
-
-module_init(modem_8660_init);
-module_exit(modem_8660_exit);
-
diff --git a/arch/arm/mach-msm/modem-8960.c b/arch/arm/mach-msm/modem-8960.c
index f0a123b..83b3bc4 100644
--- a/arch/arm/mach-msm/modem-8960.c
+++ b/arch/arm/mach-msm/modem-8960.c
@@ -258,7 +258,7 @@
 {
 	int ret;
 
-	if (cpu_is_apq8064())
+	if (cpu_is_apq8064() || cpu_is_apq8064ab())
 		return -ENODEV;
 
 	ret = smsm_state_cb_register(SMSM_MODEM_STATE, SMSM_RESET,
diff --git a/arch/arm/mach-msm/msm_cpr.c b/arch/arm/mach-msm/msm_cpr.c
index 12f7d96..c00352d 100644
--- a/arch/arm/mach-msm/msm_cpr.c
+++ b/arch/arm/mach-msm/msm_cpr.c
@@ -1,5 +1,4 @@
-/*
- * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 and
@@ -54,6 +53,26 @@
 module_param(enable, bool, 0644);
 MODULE_PARM_DESC(enable, "CPR Enable");
 
+static int msm_cpr_debug_mask;
+module_param_named(
+	debug_mask, msm_cpr_debug_mask, int, S_IRUGO | S_IWUSR
+);
+
+enum {
+	/* configuration log */
+	MSM_CPR_DEBUG_CONFIG = BIT(0),
+	/* step up/down interrupt log */
+	MSM_CPR_DEBUG_STEPS = BIT(1),
+	/* cpu frequency notification log */
+	MSM_CPR_DEBUG_FREQ_TRANS = BIT(2),
+};\
+
+#define msm_cpr_debug(mask, message, ...) \
+	do { \
+		if ((mask) & msm_cpr_debug_mask) \
+			pr_info(message, ##__VA_ARGS__); \
+	} while (0)
+
 struct msm_cpr {
 	int curr_osc;
 	int cpr_mode;
@@ -65,7 +84,9 @@
 	unsigned int irq;
 	uint32_t cur_Vmin;
 	uint32_t cur_Vmax;
+	uint32_t prev_volt_uV;
 	struct mutex cpr_mutex;
+	spinlock_t cpr_lock;
 	struct regulator *vreg_cx;
 	const struct msm_cpr_config *config;
 	struct notifier_block freq_transition;
@@ -133,17 +154,17 @@
 /* Enable the CPR H/W Block */
 static void cpr_enable(struct msm_cpr *cpr)
 {
-	mutex_lock(&cpr->cpr_mutex);
+	spin_lock(&cpr->cpr_lock);
 	cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, ENABLE_CPR);
-	mutex_unlock(&cpr->cpr_mutex);
+	spin_unlock(&cpr->cpr_lock);
 }
 
 /* Disable the CPR H/W Block */
 static void cpr_disable(struct msm_cpr *cpr)
 {
-	mutex_lock(&cpr->cpr_mutex);
+	spin_lock(&cpr->cpr_lock);
 	cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
-	mutex_unlock(&cpr->cpr_mutex);
+	spin_unlock(&cpr->cpr_lock);
 }
 
 static int32_t cpr_poll_result(struct msm_cpr *cpr)
@@ -154,8 +175,7 @@
 	rc = readl_poll_timeout(cpr->base + RBCPR_RESULT_0, val, ~val & BUSY_M,
 				10, 1000);
 	if (rc)
-		pr_info("%s: RBCPR_RESULT_0 read error: %d\n",
-			 __func__, rc);
+		pr_err("RBCPR_RESULT_0 read error: %d\n", rc);
 	return rc;
 }
 
@@ -167,8 +187,7 @@
 	rc = readl_poll_timeout(cpr->base + RBIF_IRQ_STATUS, val, val & 0x1,
 				10, 1000);
 	if (rc)
-		pr_info("%s: RBCPR_IRQ_STATUS read error: %d\n",
-			 __func__, rc);
+		pr_err("RBCPR_IRQ_STATUS read error: %d\n", rc);
 	return rc;
 }
 
@@ -200,15 +219,16 @@
 	 */
 	level_uV = chip_data->turbo_Vmax -
 		(chip_data->tgt_volt_offset * cpr->vp->step_size);
-	pr_debug("tgt_volt_uV = %d\n", level_uV);
+	msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+		"tgt_volt_uV = %d\n", level_uV);
 
 	/* Call the PMIC specific routine to set the voltage */
 	rc = regulator_set_voltage(cpr->vreg_cx, level_uV, level_uV);
 	if (rc) {
-		pr_err("%s: Initial voltage set at %duV failed. %d\n",
-			__func__, level_uV, rc);
+		pr_err("Initial voltage set at %duV failed\n", level_uV);
 		return;
 	}
+
 	rc = regulator_enable(cpr->vreg_cx);
 	if (rc) {
 		pr_err("failed to enable %s, rc=%d\n", "vdd_cx", rc);
@@ -226,15 +246,13 @@
 	/* IRQ is already disabled */
 	rc = cpr_poll_result_done(cpr);
 	if (rc) {
-		pr_err("%s: Quot1: Exiting due to INT_DONE poll timeout\n",
-			__func__);
+		pr_err("Quot1: Exiting due to INT_DONE poll timeout\n");
 		return;
 	}
 
 	rc = cpr_poll_result(cpr);
 	if (rc) {
-		pr_err("%s: Quot1: Exiting due to BUSY poll timeout\n",
-			__func__);
+		pr_err("Quot1: Exiting due to BUSY poll timeout\n");
 		return;
 	}
 
@@ -242,14 +260,14 @@
 
 	/* Take second CPR measurement at a lower voltage to get QUOT2 */
 	level_uV -= 4 * cpr->vp->step_size;
-	pr_debug("tgt_volt_uV = %d\n", level_uV);
+	msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+		"tgt_volt_uV = %d\n", level_uV);
 
 	cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
 	/* Call the PMIC specific routine to set the voltage */
 	rc = regulator_set_voltage(cpr->vreg_cx, level_uV, level_uV);
 	if (rc) {
-		pr_err("%s: Voltage set at %duV failed. %d\n",
-			__func__, level_uV, rc);
+		pr_err("Voltage set at %duV failed\n", level_uV);
 		return;
 	}
 
@@ -259,15 +277,13 @@
 	/* cpr_write_reg(cpr, RBIF_CONT_NACK_CMD, 0x1); */
 	rc = cpr_poll_result_done(cpr);
 	if (rc) {
-		pr_err("%s: Quot2: Exiting due to INT_DONE poll timeout\n",
-			__func__);
+		pr_err("Quot2: Exiting due to INT_DONE poll timeout\n");
 		goto err_poll_result_done;
 	}
 	/* IRQ is already disabled */
 	rc = cpr_poll_result(cpr);
 	if (rc) {
-		pr_err("%s: Quot2: Exiting due to BUSY poll timeout\n",
-			__func__);
+		pr_err("Quot2: Exiting due to BUSY poll timeout\n");
 		goto err_poll_result;
 	}
 	quot2 = (cpr_read_reg(cpr, RBCPR_DEBUG1) & QUOT_SLOW_M) >> 12;
@@ -283,8 +299,8 @@
 			chip_data->step_quot > STEP_QUOT_MAX)
 		chip_data->step_quot = STEP_QUOT_MAX;
 
-	pr_info("%s: Step Quot is %d\n",
-			__func__, chip_data->step_quot);
+	msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+		"Step Quot is %d\n", chip_data->step_quot);
 	/* Disable the cpr */
 	cpr_modify_reg(cpr, RBCPR_CTL, LOOP_EN_M, DISABLE_CPR);
 
@@ -329,27 +345,31 @@
 static void
 cpr_up_event_handler(struct msm_cpr *cpr, uint32_t new_volt)
 {
-	int rc, set_volt_uV;
+	int set_volt_uV, rc;
 	struct msm_cpr_mode *chip_data;
 
 	chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
 
-	/**
-	 * FIXME: Need to handle a potential race condition between
-	 * freq switch handler and CPR interrupt handler here
-	 */
 	/* Set New PMIC voltage */
+	msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+		"current Vmin=%d Vmax=%d\n", cpr->cur_Vmin, cpr->cur_Vmax);
 	set_volt_uV = (new_volt < cpr->cur_Vmax ? new_volt
 				: cpr->cur_Vmax);
-	rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
-					set_volt_uV);
+
+	if (cpr->prev_volt_uV == set_volt_uV)
+		rc = regulator_sync_voltage(cpr->vreg_cx);
+	else
+		rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
+							set_volt_uV);
 	if (rc) {
-		pr_err("%s: Voltage set at %duV failed. %d\n",
-			__func__, set_volt_uV, rc);
+		pr_err("Unable to set_voltage = %d, rc(%d)\n", set_volt_uV, rc);
 		cpr_irq_clr_and_nack(cpr, BIT(4) | BIT(0));
 		return;
 	}
-	pr_info("(railway_voltage: %d uV)\n", set_volt_uV);
+
+	msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+		"(railway_voltage: %d uV)\n", set_volt_uV);
+	cpr->prev_volt_uV = set_volt_uV;
 
 	cpr->max_volt_set = (set_volt_uV == cpr->cur_Vmax) ? 1 : 0;
 
@@ -371,27 +391,29 @@
 static void
 cpr_dn_event_handler(struct msm_cpr *cpr, uint32_t new_volt)
 {
-	int rc, set_volt_uV;
+	int set_volt_uV, rc;
 	struct msm_cpr_mode *chip_data;
 
 	chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
 
-	/**
-	 * FIXME: Need to handle a potential race condition between
-	 * freq switch handler and CPR interrupt handler here
-	 */
 	/* Set New PMIC volt */
 	set_volt_uV = (new_volt > cpr->cur_Vmin ? new_volt
 				: cpr->cur_Vmin);
-	rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
-					set_volt_uV);
+
+	if (cpr->prev_volt_uV == set_volt_uV)
+		rc = regulator_sync_voltage(cpr->vreg_cx);
+	else
+		rc = regulator_set_voltage(cpr->vreg_cx, set_volt_uV,
+							set_volt_uV);
 	if (rc) {
-		pr_err("%s: Voltage at %duV failed %d\n",
-			__func__, set_volt_uV, rc);
+		pr_err("Unable to set_voltage = %d, rc(%d)\n", set_volt_uV, rc);
 		cpr_irq_clr_and_nack(cpr, BIT(2) | BIT(0));
 		return;
 	}
-	pr_info("(railway_voltage: %d uV)\n", set_volt_uV);
+
+	msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+		"(railway_voltage: %d uV)\n", set_volt_uV);
+	cpr->prev_volt_uV = set_volt_uV;
 
 	cpr->max_volt_set = 0;
 
@@ -415,7 +437,8 @@
 					SW_AUTO_CONT_NACK_DN_EN_M,
 					SW_AUTO_CONT_NACK_DN_EN);
 			cpr_irq_set(cpr, DOWN_INT, 0);
-			pr_debug("%s: DOWN_INT disabled\n", __func__);
+			msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+					"DOWN_INT disabled\n");
 		}
 	}
 	/* Acknowledge the Recommendation */
@@ -429,9 +452,18 @@
 
 	chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
 	error_step = cpr_read_reg(cpr, RBCPR_RESULT_0) >> 2;
-	error_step &= 0xF;
 
+	msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+		"RBCPR_RESULT_0 17:6=%d\n", (cpr_read_reg(cpr,
+				RBCPR_RESULT_0) >> 6) & 0xFFF);
+	msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+		"RBCPR_RESULT_0 Busy_b19=%d\n", (cpr_read_reg(cpr,
+				RBCPR_RESULT_0) >> 19) & 0x1);
+
+	error_step &= 0xF;
 	curr_volt = regulator_get_voltage(cpr->vreg_cx);
+	msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+		"Current voltage=%d\n", curr_volt);
 
 	if (action == UP) {
 		/* Clear IRQ, ACK and return if Vdd already at Vmax */
@@ -447,15 +479,29 @@
 		 */
 		if (error_step < (cpr->config->up_threshold +
 					cpr->config->up_margin)) {
-			pr_debug("UP_INT error step too small to set\n");
+			msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+				"UP_INT error step too small to set\n");
 			cpr_irq_clr_and_nack(cpr, BIT(4) | BIT(0));
 			return;
 		}
 
+		/**
+		 * As per chip characterization recommendation, add a step
+		 * to up error steps to increase system stability
+		 */
+		error_step += 1;
+
 		/* Calculte new PMIC voltage */
 		new_volt = curr_volt + (error_step * cpr->vp->step_size);
-		pr_debug("UP_INT: new_volt: %d\n", new_volt);
-		pr_info("(UP Voltage recommended by CPR: %d uV)\n", new_volt);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"UP_INT: new_volt: %d, error_step=%d\n",
+					new_volt, error_step);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"Current RBCPR_GCNT_TARGET(%d): = 0x%x\n",
+			cpr->curr_osc, readl_relaxed(cpr->base +
+			RBCPR_GCNT_TARGET(cpr->curr_osc)) & TARGET_M);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"(UP Voltage recommended by CPR: %d uV)\n", new_volt);
 		cpr_up_event_handler(cpr, new_volt);
 
 	} else if (action == DOWN) {
@@ -465,15 +511,35 @@
 		 */
 		if (error_step < (cpr->config->dn_threshold +
 					cpr->config->dn_margin)) {
-			pr_debug("DOWN_INT error_step too small to set\n");
+			msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+				"DOWN_INT error_step=%d is too small to set\n",
+								error_step);
 			cpr_irq_clr_and_nack(cpr, BIT(2) | BIT(0));
 			return;
 		}
 
+		/**
+		 * As per chip characterization recommendation, deduct 2 steps
+		 * from down error steps to decrease chances of getting closer
+		 * to the system level Vmin, thereby improving stability
+		 */
+		error_step -= 2;
+
+		/* Keep down step upto two per interrupt to avoid any spike */
+		if (error_step > 2)
+			error_step = 2;
+
 		/* Calculte new PMIC voltage */
 		new_volt = curr_volt - (error_step * cpr->vp->step_size);
-		pr_debug("DOWN_INT: new_volt: %d\n", new_volt);
-		pr_info("(DN Voltage recommended by CPR: %d uV)\n", new_volt);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"DOWN_INT: new_volt: %d, error_step=%d\n",
+			new_volt, error_step);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"Current RBCPR_GCNT_TARGET(%d): = 0x%x\n",
+			cpr->curr_osc, readl_relaxed(cpr->base +
+			RBCPR_GCNT_TARGET(cpr->curr_osc)) & TARGET_M);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"(DN Voltage recommended by CPR: %d uV)\n", new_volt);
 		cpr_dn_event_handler(cpr, new_volt);
 	}
 }
@@ -488,31 +554,36 @@
 
 	/* Following sequence of handling is as per each IRQ's priority */
 	if (reg_val & BIT(4)) {
-		pr_debug(" CPR:IRQ %d occured for UP Flag\n", irq);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"CPR:IRQ %d occured for UP Flag\n", irq);
 		cpr_set_vdd(cpr, UP);
 
 	} else if ((reg_val & BIT(2)) && !(ctl_reg & SW_AUTO_CONT_NACK_DN_EN)) {
-		pr_debug(" CPR:IRQ %d occured for Down Flag\n", irq);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"CPR:IRQ %d occured for Down Flag\n", irq);
 		cpr_set_vdd(cpr, DOWN);
 
 	} else if (reg_val & BIT(1)) {
-		pr_debug(" CPR:IRQ %d occured for Min Flag\n", irq);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"CPR:IRQ %d occured for Min Flag\n", irq);
 		cpr_irq_clr_and_nack(cpr, BIT(1) | BIT(0));
 
 	} else if (reg_val & BIT(5)) {
-		pr_debug(" CPR:IRQ %d occured for MAX Flag\n", irq);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"CPR:IRQ %d occured for MAX Flag\n", irq);
 		cpr_irq_clr_and_nack(cpr, BIT(5) | BIT(0));
 
 	} else if (reg_val & BIT(3)) {
 		/* SW_AUTO_CONT_ACK_EN is enabled */
-		pr_debug(" CPR:IRQ %d occured for Mid Flag\n", irq);
+		msm_cpr_debug(MSM_CPR_DEBUG_STEPS,
+			"CPR:IRQ %d occured for Mid Flag\n", irq);
 	}
 	return IRQ_HANDLED;
 }
 
 static void cpr_config(struct msm_cpr *cpr)
 {
-	uint32_t delay_count, cnt = 0, rc, tmp_uV;
+	uint32_t delay_count, cnt = 0, rc;
 	struct msm_cpr_mode *chip_data;
 
 	chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
@@ -543,11 +614,16 @@
 	 * for all the ring oscilators
 	 */
 	while (cnt < NUM_OSC) {
+		msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+			"Prog:cnt(%d) gcnt=0x%x quot=0x%x\n", cnt,
+			chip_data->ring_osc_data[cnt].gcnt,
+			chip_data->ring_osc_data[cnt].quot);
 		cpr_modify_reg(cpr, RBCPR_GCNT_TARGET(cnt),
 				(GCNT_M | TARGET_M),
 				(chip_data->ring_osc_data[cnt].gcnt << 12 |
 				chip_data->ring_osc_data[cnt].quot));
-		pr_debug("RBCPR_GCNT_TARGET(%d): = 0x%x\n", cnt,
+		msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+			"RBCPR_GCNT_TARGET(%d): = 0x%x\n", cnt,
 			readl_relaxed(cpr->base + RBCPR_GCNT_TARGET(cnt)));
 		cnt++;
 	}
@@ -555,16 +631,11 @@
 	/* Configure the step quot */
 	cpr_2pt_kv_analysis(cpr, chip_data);
 
-	/**
-	 * Call the PMIC specific routine to set the voltage
-	 * Set with an extra step since it helps as per
-	 * characterization data.
-	 */
-	chip_data->calibrated_uV +=  cpr->vp->step_size;
-	tmp_uV = chip_data->calibrated_uV;
-	rc = regulator_set_voltage(cpr->vreg_cx, tmp_uV, tmp_uV);
+	/* Call the PMIC specific routine to set the voltage */
+	rc = regulator_set_voltage(cpr->vreg_cx, chip_data->calibrated_uV,
+					chip_data->calibrated_uV);
 	if (rc)
-		pr_err("%s: Voltage set failed %d\n", __func__, rc);
+		pr_err("Voltage set failed %d\n", rc);
 
 	/*
 	 * Program the Timer Register for delay between CPR measurements
@@ -575,6 +646,11 @@
 					cpr->config->delay_us);
 	cpr_write_reg(cpr, RBCPR_TIMER_INTERVAL, delay_count);
 
+	/* Use Consecutive Down to avoid any interrupt due to spike */
+	cpr_write_reg(cpr, RBIF_TIMER_ADJUST, (0x2 << RBIF_CONS_DN_SHIFT));
+	msm_cpr_debug(MSM_CPR_DEBUG_CONFIG, "RBIF_TIMER_ADJUST: 0x%x\n",
+		readl_relaxed(cpr->base + RBIF_TIMER_ADJUST));
+
 	/* Enable the Timer */
 	cpr_modify_reg(cpr, RBCPR_CTL, TIMER_M, ENABLE_TIMER);
 
@@ -593,19 +669,23 @@
 
 	switch (val) {
 	case CPUFREQ_PRECHANGE:
-		pr_debug("pre freq change notification to cpr\n");
-
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"pre freq change notification to cpr\n");
 		/* Disable Measurement to stop generation of CPR IRQs */
 		cpr_disable(cpr);
 		/* Disable routing of IRQ to App */
 		cpr_irq_set(cpr, INT_MASK & ~MID_INT, 0);
 		disable_irq(cpr->irq);
 		cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
-		pr_debug("RBCPR_CTL: 0x%x\n",
+
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"RBCPR_CTL: 0x%x\n",
 			readl_relaxed(cpr->base + RBCPR_CTL));
-		pr_debug("RBIF_IRQ_STATUS: 0x%x\n",
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"RBIF_IRQ_STATUS: 0x%x\n",
 			cpr_read_reg(cpr, RBIF_IRQ_STATUS));
-		pr_debug("RBIF_IRQ_EN(0): 0x%x\n",
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"RBIF_IRQ_EN(0): 0x%x\n",
 			cpr_read_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line)));
 
 		cpr->prev_mode = cpr->cpr_mode;
@@ -634,12 +714,15 @@
 						new_freq / 1000);
 		cpr_modify_reg(cpr, RBCPR_GCNT_TARGET(cpr->curr_osc), TARGET_M,
 				quot);
-		pr_debug("RBCPR_GCNT_TARGET(%d): = 0x%x\n", cpr->curr_osc,
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"RBCPR_GCNT_TARGET(%d): = 0x%x\n", cpr->curr_osc,
 			readl_relaxed(cpr->base +
 					RBCPR_GCNT_TARGET(cpr->curr_osc)));
-		pr_debug("%s: new_freq: %d, set_freq: %d, quot: %d\n", __func__,
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"new_freq: %d, quot_freq: %d, quot: %d\n",
 			freqs->new, new_freq, quot);
-		pr_info("%s: PVS Voltage setting is: %d\n", __func__,
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"PVS Voltage setting is: %d\n",
 			regulator_get_voltage(cpr->vreg_cx));
 
 		enable_irq(cpr->irq);
@@ -656,18 +739,28 @@
 		if (ctl_reg & SW_AUTO_CONT_NACK_DN_EN)
 			cpr_modify_reg(cpr, RBCPR_CTL,
 				 SW_AUTO_CONT_NACK_DN_EN_M, 0);
-		pr_debug("RBIF_IRQ_EN(0): 0x%x\n",
+		if (cpr->max_volt_set)
+			cpr->max_volt_set = 0;
+
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"RBIF_IRQ_EN(0): 0x%x\n",
 			cpr_read_reg(cpr, RBIF_IRQ_EN(cpr->config->irq_line)));
-		pr_debug("RBCPR_CTL: 0x%x\n",
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"RBCPR_CTL: 0x%x\n",
 			readl_relaxed(cpr->base + RBCPR_CTL));
-		pr_debug("RBIF_IRQ_STATUS: 0x%x\n",
+		msm_cpr_debug(MSM_CPR_DEBUG_FREQ_TRANS,
+			"RBIF_IRQ_STATUS: 0x%x\n",
 			cpr_read_reg(cpr, RBIF_IRQ_STATUS));
+
+		/* Clear all the interrupts */
+		cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+
 		cpr_enable(cpr);
 		break;
 	default:
 		break;
 	}
-	return 0;
+	return NOTIFY_OK;
 }
 
 #ifdef CONFIG_PM
@@ -695,6 +788,9 @@
 	cpr_write_reg(cpr, RBCPR_CTL,
 		cpr_save_state.rbcpr_ctl);
 
+	/* Clear all the interrupts */
+	cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+
 	enable_irq(cpr->irq);
 	cpr_enable(cpr);
 
@@ -711,6 +807,9 @@
 	cpr_disable(cpr);
 	disable_irq(cpr->irq);
 
+	/* Clear all the interrupts */
+	cpr_write_reg(cpr, RBIF_IRQ_CLEAR, ALL_CPR_IRQ);
+
 	cpr_save_state.rbif_timer_interval =
 		cpr_read_reg(cpr, RBCPR_TIMER_INTERVAL);
 	cpr_save_state.rbif_int_en =
@@ -733,12 +832,18 @@
 
 void msm_cpr_pm_resume(void)
 {
+	if (!enable)
+		return;
+
 	msm_cpr_resume(&cpr_pdev->dev);
 }
 EXPORT_SYMBOL(msm_cpr_pm_resume);
 
 void msm_cpr_pm_suspend(void)
 {
+	if (!enable)
+		return;
+
 	msm_cpr_suspend(&cpr_pdev->dev);
 }
 EXPORT_SYMBOL(msm_cpr_pm_suspend);
@@ -746,14 +851,26 @@
 
 void msm_cpr_disable(void)
 {
-	struct msm_cpr *cpr = platform_get_drvdata(cpr_pdev);
+	struct msm_cpr *cpr;
+
+	if (!enable)
+		return;
+
+	cpr = platform_get_drvdata(cpr_pdev);
+
 	cpr_disable(cpr);
 }
 EXPORT_SYMBOL(msm_cpr_disable);
 
 void msm_cpr_enable(void)
 {
-	struct msm_cpr *cpr = platform_get_drvdata(cpr_pdev);
+	struct msm_cpr *cpr;
+
+	if (!enable)
+		return;
+
+	cpr = platform_get_drvdata(cpr_pdev);
+
 	cpr_enable(cpr);
 }
 EXPORT_SYMBOL(msm_cpr_enable);
@@ -772,12 +889,15 @@
 
 	if (!pdata) {
 		pr_err("CPR: Platform data is not available\n");
+		enable = false;
 		return -EIO;
 	}
 
 	cpr = devm_kzalloc(&pdev->dev, sizeof(struct msm_cpr), GFP_KERNEL);
-	if (!cpr)
+	if (!cpr) {
+		enable = false;
 		return -ENOMEM;
+	}
 
 	/* Initialize platform_data */
 	cpr->config = pdata;
@@ -820,7 +940,7 @@
 
 	cpr->vp = pdata->vp_data;
 
-	mutex_init(&cpr->cpr_mutex);
+	spin_lock_init(&cpr->cpr_lock);
 
 	/* Initialize the Voltage domain for CPR */
 	cpr->vreg_cx = regulator_get(&pdev->dev, "vddx_cx");
@@ -840,12 +960,15 @@
 	platform_set_drvdata(pdev, cpr);
 
 	chip_data = &cpr->config->cpr_mode_data[cpr->cpr_mode];
-	pr_info("CPR Platform Data (upside_steps: %d) (downside_steps: %d) ",
+	msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+		"CPR Platform Data (upside_steps: %d) (downside_steps: %d))",
 		cpr->config->up_threshold, cpr->config->dn_threshold);
-	pr_info("(nominal_voltage: %duV) (turbo_voltage: %duV)\n",
+	msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+		"(nominal_voltage: %duV) (turbo_voltage: %duV)\n",
 		cpr->config->cpr_mode_data[NORMAL_MODE].calibrated_uV,
 		cpr->config->cpr_mode_data[TURBO_MODE].calibrated_uV);
-	pr_info("(Current corner: TURBO) (gcnt_target: %d) (quot: %d)\n",
+	msm_cpr_debug(MSM_CPR_DEBUG_CONFIG,
+		"(Current corner: TURBO) (gcnt_target: %d) (quot: %d)\n",
 		chip_data->ring_osc_data[chip_data->ring_osc].gcnt,
 		chip_data->ring_osc_data[chip_data->ring_osc].quot);
 
@@ -880,6 +1003,8 @@
 	cpufreq_register_notifier(&cpr->freq_transition,
 					CPUFREQ_TRANSITION_NOTIFIER);
 
+	pr_info("MSM CPR driver successfully registered!\n");
+
 	return res;
 
 err_reg_get:
@@ -887,6 +1012,7 @@
 err_ioremap:
 	iounmap(base);
 out:
+	enable = false;
 	return res;
 }
 
@@ -901,7 +1027,6 @@
 	regulator_put(cpr->vreg_cx);
 	free_irq(cpr->irq, cpr);
 	iounmap(cpr->base);
-	mutex_destroy(&cpr->cpr_mutex);
 	platform_set_drvdata(pdev, NULL);
 
 	return 0;
diff --git a/arch/arm/mach-msm/msm_cpr.h b/arch/arm/mach-msm/msm_cpr.h
index e690c63..005d9b1 100644
--- a/arch/arm/mach-msm/msm_cpr.h
+++ b/arch/arm/mach-msm/msm_cpr.h
@@ -72,6 +72,9 @@
 #define SW_AUTO_CONT_ACK_EN	BIT(5)
 #define SW_AUTO_CONT_NACK_DN_EN	BIT(6)
 
+/* Shift Values */
+#define RBIF_CONS_DN_SHIFT (0x4)
+
 /* Test values for RBCPR RUMI Testing */
 #define GNT_CNT			0xC0
 #define TARGET			0xEFF
diff --git a/arch/arm/mach-msm/msm_xo.c b/arch/arm/mach-msm/msm_xo.c
index 2d61504..404b350 100644
--- a/arch/arm/mach-msm/msm_xo.c
+++ b/arch/arm/mach-msm/msm_xo.c
@@ -236,7 +236,7 @@
 	int needs_workaround = cpu_is_msm8960() || cpu_is_apq8064() ||
 			       cpu_is_msm8930() || cpu_is_msm8930aa() ||
 			       cpu_is_msm9615() || cpu_is_msm8627() ||
-			       cpu_is_msm8960ab();
+			       cpu_is_msm8960ab() || cpu_is_apq8064ab();
 
 	if (xo_voter->mode == mode)
 		return 0;
diff --git a/arch/arm/mach-msm/pil-modem.c b/arch/arm/mach-msm/pil-modem.c
index 8344496..ecb3800 100644
--- a/arch/arm/mach-msm/pil-modem.c
+++ b/arch/arm/mach-msm/pil-modem.c
@@ -19,11 +19,19 @@
 #include <linux/delay.h>
 #include <linux/err.h>
 #include <linux/clk.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/reboot.h>
 
 #include <mach/msm_iomap.h>
+#include <mach/subsystem_restart.h>
+#include <mach/msm_smsm.h>
+#include <mach/peripheral-loader.h>
 
+#include "modem_notifier.h"
 #include "peripheral-loader.h"
 #include "scm-pas.h"
+#include "ramdump.h"
 
 #define MARM_BOOT_CONTROL		0x0010
 #define MARM_RESET			(MSM_CLK_CTL_BASE + 0x2BD4)
@@ -46,12 +54,22 @@
 #define PLL_ENA_MARM			(MSM_CLK_CTL_BASE + 0x3500)
 #define PLL8_STATUS			(MSM_CLK_CTL_BASE + 0x3158)
 #define CLK_HALT_MSS_SMPSS_MISC_STATE	(MSM_CLK_CTL_BASE + 0x2FDC)
+#define MSS_MODEM_RESET			(MSM_CLK_CTL_BASE + 0x2C48)
 
 struct modem_data {
 	void __iomem *base;
+	void __iomem *wdog;
 	unsigned long start_addr;
 	struct pil_device *pil;
 	struct clk *xo;
+	struct notifier_block notifier;
+	int ignore_smsm_ack;
+	int irq;
+	struct subsys_device *subsys;
+	struct subsys_desc subsys_desc;
+	struct delayed_work unlock_work;
+	struct work_struct fatal_work;
+	struct ramdump_device *ramdump_dev;
 };
 
 static int make_modem_proxy_votes(struct pil_desc *pil)
@@ -161,7 +179,7 @@
 	return 0;
 }
 
-static int modem_shutdown(struct pil_desc *pil)
+static int modem_pil_shutdown(struct pil_desc *pil)
 {
 	u32 reg;
 
@@ -203,7 +221,7 @@
 static struct pil_reset_ops pil_modem_ops = {
 	.init_image = modem_init_image,
 	.auth_and_reset = modem_reset,
-	.shutdown = modem_shutdown,
+	.shutdown = modem_pil_shutdown,
 	.proxy_vote = make_modem_proxy_votes,
 	.proxy_unvote = remove_modem_proxy_votes,
 };
@@ -232,11 +250,166 @@
 	.proxy_unvote = remove_modem_proxy_votes,
 };
 
+static void modem_crash_shutdown(const struct subsys_desc *subsys)
+{
+	struct modem_data *drv;
+
+	/* If modem hasn't already crashed, send SMSM_RESET. */
+	drv = container_of(subsys, struct modem_data, subsys_desc);
+	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
+		modem_unregister_notifier(&drv->notifier);
+		smsm_reset_modem(SMSM_RESET);
+	}
+
+	/* Wait to allow the modem to clean up caches etc. */
+	mdelay(5);
+}
+
+static irqreturn_t modem_wdog_bite_irq(int irq, void *dev_id)
+{
+	struct modem_data *drv = dev_id;
+
+	schedule_work(&drv->fatal_work);
+	disable_irq_nosync(drv->irq);
+
+	return IRQ_HANDLED;
+}
+
+static void modem_unlock_timeout(struct work_struct *work)
+{
+	struct modem_data *drv;
+	struct delayed_work *dwork = to_delayed_work(work);
+
+	pr_crit("Timeout waiting for modem to unlock.\n");
+
+	drv = container_of(dwork, struct modem_data, unlock_work);
+	/* The unlock didn't work, clear the reset */
+	writel_relaxed(0x0, MSS_MODEM_RESET);
+	mb();
+
+	subsystem_restart_dev(drv->subsys);
+	enable_irq(drv->irq);
+}
+
+static void modem_fatal_fn(struct work_struct *work)
+{
+	u32 modem_state;
+	u32 panic_smsm_states = SMSM_RESET | SMSM_SYSTEM_DOWNLOAD;
+	u32 reset_smsm_states = SMSM_SYSTEM_REBOOT_USR | SMSM_SYSTEM_PWRDWN_USR;
+	struct modem_data *drv;
+
+	drv = container_of(work, struct modem_data, fatal_work);
+
+	pr_err("Watchdog bite received from modem!\n");
+
+	modem_state = smsm_get_state(SMSM_MODEM_STATE);
+	pr_err("Modem SMSM state = 0x%x!\n", modem_state);
+
+	if (modem_state == 0 || modem_state & panic_smsm_states) {
+		subsystem_restart_dev(drv->subsys);
+		enable_irq(drv->irq);
+	} else if (modem_state & reset_smsm_states) {
+		pr_err("User-invoked system reset/powerdown.");
+		kernel_restart(NULL);
+	} else {
+		unsigned long timeout = msecs_to_jiffies(6000);
+
+		pr_err("Modem AHB locked up. Trying to free up modem!\n");
+
+		writel_relaxed(0x3, MSS_MODEM_RESET);
+		/*
+		 * If we are still alive (allowing for the 5 second
+		 * delayed-panic-reboot), the modem is either still wedged or
+		 * SMSM didn't come through. Force panic in that case.
+		 */
+		schedule_delayed_work(&drv->unlock_work, timeout);
+	}
+}
+
+static int modem_notif_handler(struct notifier_block *nb, unsigned long code,
+				void *p)
+{
+	struct modem_data *drv = container_of(nb, struct modem_data, notifier);
+
+	if (code == MODEM_NOTIFIER_START_RESET) {
+		if (drv->ignore_smsm_ack) {
+			drv->ignore_smsm_ack = 0;
+		} else {
+			pr_err("Modem error fatal'ed.");
+			subsystem_restart_dev(drv->subsys);
+		}
+	}
+	return NOTIFY_DONE;
+}
+
+static int modem_shutdown(const struct subsys_desc *subsys)
+{
+	struct modem_data *drv;
+
+	drv = container_of(subsys, struct modem_data, subsys_desc);
+	/*
+	 * If the modem didn't already crash, setting SMSM_RESET here will help
+	 * flush caches etc. The ignore_smsm_ack flag is set to ignore the
+	 * SMSM_RESET notification that is generated due to the modem settings
+	 * its own SMSM_RESET bit in response to the apps setting the apps
+	 * SMSM_RESET bit.
+	 */
+	if (!(smsm_get_state(SMSM_MODEM_STATE) & SMSM_RESET)) {
+		drv->ignore_smsm_ack = 1;
+		smsm_reset_modem(SMSM_RESET);
+	}
+
+	/* Disable the modem watchdog to allow clean modem bootup */
+	writel_relaxed(0x0, drv->wdog + 0x8);
+	/*
+	 * The write above needs to go through before the modem is powered up
+	 * again.
+	 */
+	mb();
+	/* Wait here to allow the modem to clean up caches, etc. */
+	msleep(20);
+
+	pil_force_shutdown("modem");
+	disable_irq_nosync(drv->irq);
+
+	return 0;
+}
+
+static int modem_powerup(const struct subsys_desc *subsys)
+{
+	struct modem_data *drv;
+	int ret;
+
+	drv = container_of(subsys, struct modem_data, subsys_desc);
+	ret = pil_force_boot("modem");
+	enable_irq(drv->irq);
+
+	return ret;
+}
+
+/* FIXME: Get address, size from PIL */
+static struct ramdump_segment modem_segments[] = {
+	{ 0x42F00000, 0x46000000 - 0x42F00000 },
+};
+
+static int modem_ramdump(int enable, const struct subsys_desc *subsys)
+{
+	struct modem_data *drv;
+
+	drv = container_of(subsys, struct modem_data, subsys_desc);
+	if (enable)
+		return do_ramdump(drv->ramdump_dev, modem_segments,
+				ARRAY_SIZE(modem_segments));
+	else
+		return 0;
+}
+
 static int __devinit pil_modem_driver_probe(struct platform_device *pdev)
 {
 	struct modem_data *drv;
 	struct resource *res;
 	struct pil_desc *desc;
+	int ret;
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res)
@@ -247,6 +420,10 @@
 		return -ENOMEM;
 	platform_set_drvdata(pdev, drv);
 
+	drv->irq = platform_get_irq(pdev, 0);
+	if (drv->irq < 0)
+		return drv->irq;
+
 	drv->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
 	if (!drv->base)
 		return -ENOMEM;
@@ -259,6 +436,14 @@
 	if (!desc)
 		return -ENOMEM;
 
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+	if (!res)
+		return -EINVAL;
+
+	drv->wdog = devm_ioremap(&pdev->dev, res->start, resource_size(res));
+	if (!drv->wdog)
+		return -ENOMEM;
+
 	desc->name = "modem";
 	desc->depends_on = "q6";
 	desc->dev = &pdev->dev;
@@ -273,16 +458,61 @@
 		dev_info(&pdev->dev, "using non-secure boot\n");
 	}
 	drv->pil = msm_pil_register(desc);
-	if (IS_ERR(drv->pil)) {
+	if (IS_ERR(drv->pil))
 		return PTR_ERR(drv->pil);
+
+	drv->notifier.notifier_call = modem_notif_handler,
+	ret = modem_register_notifier(&drv->notifier);
+	if (ret)
+		goto err_notify;
+
+	drv->subsys_desc.name = "modem";
+	drv->subsys_desc.shutdown = modem_shutdown;
+	drv->subsys_desc.powerup = modem_powerup;
+	drv->subsys_desc.ramdump = modem_ramdump;
+	drv->subsys_desc.crash_shutdown = modem_crash_shutdown;
+
+	INIT_WORK(&drv->fatal_work, modem_fatal_fn);
+	INIT_DELAYED_WORK(&drv->unlock_work, modem_unlock_timeout);
+
+	drv->subsys = subsys_register(&drv->subsys_desc);
+	if (IS_ERR(drv->subsys)) {
+		ret = PTR_ERR(drv->subsys);
+		goto err_subsys;
 	}
+
+	drv->ramdump_dev = create_ramdump_device("modem");
+	if (!drv->ramdump_dev) {
+		ret = -ENOMEM;
+		goto err_ramdump;
+	}
+
+	ret = devm_request_irq(&pdev->dev, drv->irq, modem_wdog_bite_irq,
+			IRQF_TRIGGER_RISING, "modem_watchdog", drv);
+	if (ret)
+		goto err_irq;
 	return 0;
+
+err_irq:
+	destroy_ramdump_device(drv->ramdump_dev);
+err_ramdump:
+	subsys_unregister(drv->subsys);
+err_subsys:
+	modem_unregister_notifier(&drv->notifier);
+err_notify:
+	msm_pil_unregister(drv->pil);
+	return ret;
 }
 
 static int __devexit pil_modem_driver_exit(struct platform_device *pdev)
 {
 	struct modem_data *drv = platform_get_drvdata(pdev);
+
+	destroy_ramdump_device(drv->ramdump_dev);
+	subsys_unregister(drv->subsys);
+	modem_unregister_notifier(&drv->notifier);
 	msm_pil_unregister(drv->pil);
+
 	return 0;
 }
 
diff --git a/arch/arm/mach-msm/platsmp-8625.c b/arch/arm/mach-msm/platsmp-8625.c
index 700f966..e8f8c59 100644
--- a/arch/arm/mach-msm/platsmp-8625.c
+++ b/arch/arm/mach-msm/platsmp-8625.c
@@ -28,19 +28,28 @@
 #include <mach/msm_iomap.h>
 #include "pm.h"
 
-#define MSM_CORE1_RESET		0xA8600590
-#define MSM_CORE1_STATUS_MSK	0x02800000
+#define CORE_RESET_BASE		0xA8600590
+#define MSM_CORE_STATUS_MSK	0x02800000
 
 /*
  * control for which core is the next to come out of the secondary
  * boot "holding pen"
  */
-int pen_release = -1;
+volatile int pen_release = -1;
 
-static bool cold_boot_done;
+static DEFINE_PER_CPU(bool, cold_boot_done);
+
+struct per_cpu_data {
+	unsigned int reset_off;
+	unsigned int offset;
+	unsigned int ipc_irq;
+	void __iomem *reset_core_base;
+};
 
 static uint32_t *msm8625_boot_vector;
-static void __iomem *reset_core1_base;
+
+
+static struct per_cpu_data cpu_data[CONFIG_NR_CPUS];
 
 /*
  * Write pen_release in a way that is guaranteed to be visible to all
@@ -65,7 +74,8 @@
 /*
  * MP_CORE_IPC will be used to generate interrupt and can be used by either
  * of core.
- * To bring core1 out of GDFS we need to raise the SPI using the MP_CORE_IPC.
+ * To bring secondary cores out of GDFS we need to raise the SPI using the
+ * MP_CORE_IPC.
  */
 static void raise_clear_spi(unsigned int cpu, bool set)
 {
@@ -112,8 +122,8 @@
 
 	/* clear the IPC1(SPI-8) pending SPI */
 	if (power_collapsed) {
-		raise_clear_spi(1, false);
-		clear_pending_spi(MSM8625_INT_ACSR_MP_CORE_IPC1);
+		raise_clear_spi(cpu, false);
+		clear_pending_spi(cpu_data[cpu].ipc_irq);
 		power_collapsed = 0;
 	}
 
@@ -124,7 +134,7 @@
 	spin_unlock(&boot_lock);
 }
 
-static int  __cpuinit msm8625_release_secondary(void)
+static int  __cpuinit msm8625_release_secondary(unsigned int cpu)
 {
 	void __iomem *base_ptr;
 	int value = 0;
@@ -137,33 +147,35 @@
 	 */
 	timeout = jiffies + usecs_to_jiffies(20);
 	while (time_before(jiffies, timeout)) {
-		value = __raw_readl(MSM_CFG_CTL_BASE + 0x3c);
-		if ((value & MSM_CORE1_STATUS_MSK) ==
-				MSM_CORE1_STATUS_MSK)
+		value = __raw_readl(MSM_CFG_CTL_BASE + cpu_data[cpu].offset);
+		if ((value & MSM_CORE_STATUS_MSK) ==
+				MSM_CORE_STATUS_MSK)
 			break;
 			udelay(1);
 	}
 
 	if (!value) {
-		pr_err("Core 1 cannot be brought out of Reset!!!\n");
+		pr_err("Core %u cannot be brought out of Reset!!!\n", cpu);
 		return -ENODEV;
 	}
 
-	base_ptr = ioremap_nocache(MSM_CORE1_RESET, SZ_4);
+	base_ptr = ioremap_nocache(CORE_RESET_BASE +
+			cpu_data[cpu].reset_off, SZ_4);
 	if (!base_ptr)
 		return -ENODEV;
-	/* Reset core 1 out of reset */
+
+	/* Reset core out of reset */
 	__raw_writel(0x0, base_ptr);
 	mb();
 
-	reset_core1_base = base_ptr;
+	cpu_data[cpu].reset_core_base = base_ptr;
 
 	return 0;
 }
 
 void __iomem *core1_reset_base(void)
 {
-	return reset_core1_base;
+	return cpu_data[1].reset_core_base;
 }
 
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
@@ -172,12 +184,12 @@
 
 	preset_lpj = loops_per_jiffy;
 
-	if (cold_boot_done == false) {
-		if (msm8625_release_secondary()) {
-			pr_err("Failed to release secondary core\n");
+	if (per_cpu(cold_boot_done, cpu) == false) {
+		if (msm8625_release_secondary(cpu)) {
+			pr_err("Failed to release core %u\n", cpu);
 			return -ENODEV;
 		}
-		cold_boot_done = true;
+		per_cpu(cold_boot_done, cpu) = true;
 	}
 
 	/*
@@ -200,13 +212,13 @@
 	 * and branch to the address found there.
 	 *
 	 * power_collapsed is the flag which will be updated for Powercollapse.
-	 * Once we are out of PC, as Core1 will be in the state of GDFS which
-	 * needs to be brought out by raising an SPI.
+	 * Once we are out of PC, as secondary cores will be in the state of
+	 * GDFS which needs to be brought out by raising an SPI.
 	 */
 
 	if (power_collapsed) {
 		core1_gic_configure_and_raise();
-		raise_clear_spi(1, true);
+		raise_clear_spi(cpu, true);
 	} else {
 		gic_raise_softirq(cpumask_of(cpu), 1);
 	}
@@ -247,6 +259,34 @@
 	set_smp_cross_call(gic_raise_softirq);
 }
 
+static void per_cpu_data(unsigned int cpu, unsigned int off,
+	unsigned int off1, unsigned int irq)
+{
+	cpu_data[cpu].reset_off = off;
+	cpu_data[cpu].offset    = off1;
+	cpu_data[cpu].ipc_irq   = irq;
+}
+
+static void enable_boot_remapper(unsigned long bit, unsigned int off)
+{
+	int value;
+
+	/* Enable boot remapper address */
+	value = __raw_readl(MSM_CFG_CTL_BASE + off);
+	__raw_writel(value | bit, MSM_CFG_CTL_BASE + off) ;
+	mb();
+}
+
+static void remapper_address(unsigned long phys, unsigned int off)
+{
+	/*
+	 * Write the address of secondary startup into the
+	 * boot remapper register. The secondary CPU branches to this address.
+	 */
+	__raw_writel(phys, (MSM_CFG_CTL_BASE + off));
+	mb();
+}
+
 static void __init msm8625_boot_vector_init(uint32_t *boot_vector,
 		unsigned long entry)
 {
@@ -260,8 +300,8 @@
 
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int i, value;
-	void __iomem *second_ptr;
+	int i, cpu, value;
+	void __iomem *cpu_ptr;
 
 	/*
 	 * Initialise the present map, which describes the set of CPUs
@@ -272,25 +312,41 @@
 
 	scu_enable(scu_base_addr());
 
-	/*
-	 * Write the address of secondary startup into the
-	 * boot remapper register. The secondary CPU branches to this address.
-	 */
-	__raw_writel(MSM8625_SECONDARY_PHYS, (MSM_CFG_CTL_BASE + 0x34));
-	mb();
-
-	second_ptr = ioremap_nocache(MSM8625_SECONDARY_PHYS, SZ_8);
-	if (!second_ptr) {
-		pr_err("failed to ioremap for secondary core\n");
+	cpu_ptr = ioremap_nocache(MSM8625_CPU_PHYS, SZ_8);
+	if (!cpu_ptr) {
+		pr_err("failed to ioremap for secondary cores\n");
 		return;
 	}
 
-	msm8625_boot_vector_init(second_ptr,
+	msm8625_boot_vector_init(cpu_ptr,
 			virt_to_phys(msm_secondary_startup));
-	iounmap(second_ptr);
 
-	/* Enable boot remapper address: bit 26 for core1 */
-	value = __raw_readl(MSM_CFG_CTL_BASE + 0x30);
-	__raw_writel(value | (0x4 << 24), MSM_CFG_CTL_BASE + 0x30) ;
-	mb();
+	iounmap(cpu_ptr);
+
+	for_each_possible_cpu(cpu) {
+		switch (cpu) {
+		case 0:
+			break;
+		case 1:
+			remapper_address(MSM8625_CPU_PHYS, 0x34);
+			per_cpu_data(cpu, 0x0, 0x3c,
+					MSM8625_INT_ACSR_MP_CORE_IPC1);
+			enable_boot_remapper(BIT(26), 0x30);
+			break;
+		case 2:
+			remapper_address((MSM8625_CPU_PHYS >> 16), 0x4C);
+			per_cpu_data(cpu, 0x8, 0x50,
+					MSM8625_INT_ACSR_MP_CORE_IPC2);
+			enable_boot_remapper(BIT(25), 0x48);
+			break;
+		case 3:
+			value = __raw_readl(MSM_CFG_CTL_BASE + 0x4C);
+			remapper_address(value | MSM8625_CPU_PHYS, 0x4C);
+			per_cpu_data(cpu, 0xC, 0x50,
+					MSM8625_INT_ACSR_MP_CORE_IPC3);
+			enable_boot_remapper(BIT(26), 0x48);
+			break;
+		}
+
+	}
 }
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index f6ed1ea..aa05559 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -165,7 +165,8 @@
 		return krait_release_secondary_sim(0xf9088000, cpu);
 
 	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab())
+	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
+						cpu_is_apq8064ab())
 		return krait_release_secondary(0x02088000, cpu);
 
 	if (cpu_is_msm8974())
@@ -176,17 +177,9 @@
 }
 
 DEFINE_PER_CPU(int, cold_boot_done);
-static int cold_boot_flags[] = {
-	0,
-	SCM_FLAG_COLDBOOT_CPU1,
-	SCM_FLAG_COLDBOOT_CPU2,
-	SCM_FLAG_COLDBOOT_CPU3,
-};
 
 int __cpuinit boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
-	int ret;
-	unsigned int flag = 0;
 	unsigned long timeout;
 
 	pr_debug("Starting secondary CPU %d\n", cpu);
@@ -194,19 +187,8 @@
 	/* Set preset_lpj to avoid subsequent lpj recalculations */
 	preset_lpj = loops_per_jiffy;
 
-	if (cpu > 0 && cpu < ARRAY_SIZE(cold_boot_flags))
-		flag = cold_boot_flags[cpu];
-	else
-		__WARN();
-
 	if (per_cpu(cold_boot_done, cpu) == false) {
-		ret = scm_set_boot_addr(virt_to_phys(msm_secondary_startup),
-					flag);
-		if (ret == 0)
-			release_secondary(cpu);
-		else
-			printk(KERN_DEBUG "Failed to set secondary core boot "
-					  "address\n");
+		release_secondary(cpu);
 		per_cpu(cold_boot_done, cpu) = true;
 	}
 
@@ -274,6 +256,28 @@
 	set_smp_cross_call(gic_raise_softirq);
 }
 
+static int cold_boot_flags[] __initdata = {
+	0,
+	SCM_FLAG_COLDBOOT_CPU1,
+	SCM_FLAG_COLDBOOT_CPU2,
+	SCM_FLAG_COLDBOOT_CPU3,
+};
+
 void __init platform_smp_prepare_cpus(unsigned int max_cpus)
 {
+	int cpu, map;
+	unsigned int flags = 0;
+
+	for_each_present_cpu(cpu) {
+		map = cpu_logical_map(cpu);
+		if (map > ARRAY_SIZE(cold_boot_flags)) {
+			set_cpu_present(cpu, false);
+			__WARN();
+			continue;
+		}
+		flags |= cold_boot_flags[map];
+	}
+
+	if (scm_set_boot_addr(virt_to_phys(msm_secondary_startup), flags))
+		pr_warn("Failed to set CPU boot address\n");
 }
diff --git a/arch/arm/mach-msm/restart.c b/arch/arm/mach-msm/restart.c
index 5883b0c..2189747 100644
--- a/arch/arm/mach-msm/restart.c
+++ b/arch/arm/mach-msm/restart.c
@@ -36,6 +36,7 @@
 #include <mach/scm.h>
 #include "msm_watchdog.h"
 #include "timer.h"
+#include "wdog_debug.h"
 
 #define WDT0_RST	0x38
 #define WDT0_EN		0x40
@@ -250,8 +251,11 @@
 		__raw_writel(5*0x31F3, msm_tmr0_base + WDT0_BARK_TIME);
 		__raw_writel(0x31F3, msm_tmr0_base + WDT0_BITE_TIME);
 		__raw_writel(1, msm_tmr0_base + WDT0_EN);
-	} else
+	} else {
+		/* Needed for 8974: Reset GCC_WDOG_DEBUG register */
+		msm_disable_wdog_debug();
 		__raw_writel(0, MSM_MPM2_PSHOLD_BASE);
+	}
 
 	mdelay(10000);
 	printk(KERN_ERR "Restarting has failed\n");
diff --git a/arch/arm/mach-msm/rpm-smd.c b/arch/arm/mach-msm/rpm-smd.c
index a9d1ed8..7c31e76 100644
--- a/arch/arm/mach-msm/rpm-smd.c
+++ b/arch/arm/mach-msm/rpm-smd.c
@@ -149,8 +149,6 @@
 	uint32_t id_ack;
 };
 
-static int irq_process;
-
 LIST_HEAD(msm_rpm_ack_list);
 
 static void msm_rpm_notify_sleep_chain(struct rpm_message_header *hdr,
@@ -518,20 +516,18 @@
 	uint32_t msg_id;
 	int errno;
 	char buf[MAX_ERR_BUFFER_SIZE] = {0};
-	unsigned long flags;
 
-	while (smd_is_pkt_avail(msm_rpm_data.ch_info) && !irq_process) {
-		spin_lock_irqsave(&msm_rpm_data.smd_lock_read, flags);
+	if (!spin_trylock(&msm_rpm_data.smd_lock_read))
+		return;
+	while (smd_is_pkt_avail(msm_rpm_data.ch_info)) {
 		if (msm_rpm_read_smd_data(buf)) {
-			spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read,
-					flags);
 			break;
 		}
 		msg_id = msm_rpm_get_msg_id_from_ack(buf);
 		errno = msm_rpm_get_error_from_ack(buf);
 		msm_rpm_process_ack(msg_id, errno);
-		spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
 	}
+	spin_unlock(&msm_rpm_data.smd_lock_read);
 }
 
 #define DEBUG_PRINT_BUFFER_SIZE 512
@@ -783,7 +779,14 @@
 
 int msm_rpm_send_request(struct msm_rpm_request *handle)
 {
-	return msm_rpm_send_data(handle, MSM_RPM_MSG_REQUEST_TYPE, false);
+	int ret;
+	static DEFINE_MUTEX(send_mtx);
+
+	mutex_lock(&send_mtx);
+	ret = msm_rpm_send_data(handle, MSM_RPM_MSG_REQUEST_TYPE, false);
+	mutex_unlock(&send_mtx);
+
+	return ret;
 }
 EXPORT_SYMBOL(msm_rpm_send_request);
 
@@ -837,7 +840,6 @@
 		return 0;
 
 	spin_lock_irqsave(&msm_rpm_data.smd_lock_read, flags);
-	irq_process = true;
 
 	elem = msm_rpm_get_entry_from_msg_id(msg_id);
 
@@ -868,7 +870,6 @@
 	rc = elem->errno;
 	msm_rpm_free_list_entry(elem);
 wait_ack_cleanup:
-	irq_process = false;
 	spin_unlock_irqrestore(&msm_rpm_data.smd_lock_read, flags);
 	return rc;
 }
diff --git a/arch/arm/mach-msm/rpm_resources.c b/arch/arm/mach-msm/rpm_resources.c
index 3ab5a98..dfed3aa 100644
--- a/arch/arm/mach-msm/rpm_resources.c
+++ b/arch/arm/mach-msm/rpm_resources.c
@@ -1132,7 +1132,8 @@
 static int __init msm_rpmrs_l2_init(void)
 {
 	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab()) {
+	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
+						cpu_is_apq8064ab()) {
 
 		msm_pm_set_l2_flush_flag(0);
 
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index b228147..20ad72f 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -3513,7 +3513,7 @@
 static struct restart_notifier_block restart_notifiers[] = {
 	{SMD_MODEM, "modem", .nb.notifier_call = restart_notifier_cb},
 	{SMD_Q6, "lpass", .nb.notifier_call = restart_notifier_cb},
-	{SMD_WCNSS, "riva", .nb.notifier_call = restart_notifier_cb},
+	{SMD_WCNSS, "wcnss", .nb.notifier_call = restart_notifier_cb},
 	{SMD_DSPS, "dsps", .nb.notifier_call = restart_notifier_cb},
 	{SMD_MODEM, "gss", .nb.notifier_call = restart_notifier_cb},
 	{SMD_Q6, "adsp", .nb.notifier_call = restart_notifier_cb},
diff --git a/arch/arm/mach-msm/socinfo.c b/arch/arm/mach-msm/socinfo.c
index 86de130..ac077e9 100644
--- a/arch/arm/mach-msm/socinfo.c
+++ b/arch/arm/mach-msm/socinfo.c
@@ -286,6 +286,9 @@
 	/* 8092 IDs */
 	[146] = MSM_CPU_8092,
 
+	/* 8064AB IDs */
+	[153] = MSM_CPU_8064AB,
+
 	/* Uninitialized IDs are not known to run Linux.
 	   MSM_CPU_UNKNOWN is set to 0 to ensure these IDs are
 	   considered as unknown CPU. */
diff --git a/arch/arm/mach-msm/spm-v2.c b/arch/arm/mach-msm/spm-v2.c
index 1eab9bf..f0d3d06 100644
--- a/arch/arm/mach-msm/spm-v2.c
+++ b/arch/arm/mach-msm/spm-v2.c
@@ -179,7 +179,7 @@
 	}
 }
 
-static inline uint32_t msm_spm_drv_get_sts_curr_pmic_data(
+uint32_t msm_spm_drv_get_sts_curr_pmic_data(
 		struct msm_spm_driver_data *dev)
 {
 	if (dev->major == SAW2_MAJOR_2) {
diff --git a/arch/arm/mach-msm/spm.h b/arch/arm/mach-msm/spm.h
index e81e335..09ee26a 100644
--- a/arch/arm/mach-msm/spm.h
+++ b/arch/arm/mach-msm/spm.h
@@ -141,6 +141,13 @@
 int msm_spm_set_vdd(unsigned int cpu, unsigned int vlevel);
 
 /**
+ * msm_spm_get_vdd(): Get core voltage
+ * @cpu: core id
+ * @return: Returns encoded PMIC data.
+ */
+unsigned int msm_spm_get_vdd(unsigned int cpu);
+
+/**
  * msm_spm_turn_on_cpu_rail(): Power on cpu rail before turning on core
  * @cpu: core id
  */
@@ -239,6 +246,11 @@
 	return -ENOSYS;
 }
 
+static inline unsigned int msm_spm_get_vdd(unsigned int cpu)
+{
+	return 0;
+}
+
 static inline void msm_spm_reinit(void)
 {
 	/* empty */
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index b87b0f1..2cbed94 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -75,6 +75,15 @@
 }
 EXPORT_SYMBOL(msm_spm_set_vdd);
 
+unsigned int msm_spm_get_vdd(unsigned int cpu)
+{
+	struct msm_spm_device *dev;
+
+	dev = &per_cpu(msm_cpu_spm_device, cpu);
+	return msm_spm_drv_get_sts_curr_pmic_data(&dev->reg_data);
+}
+EXPORT_SYMBOL(msm_spm_get_vdd);
+
 static int msm_spm_dev_set_low_power_mode(struct msm_spm_device *dev,
 		unsigned int mode, bool notify_rpm)
 {
@@ -159,7 +168,8 @@
 	reg = saw_bases[cpu];
 
 	if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
-	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab()) {
+	    cpu_is_apq8064() || cpu_is_msm8627() || cpu_is_msm8960ab() ||
+						cpu_is_apq8064ab()) {
 		val = 0xA4;
 		reg += 0x14;
 		timeout = 512;
diff --git a/arch/arm/mach-msm/spm_driver.h b/arch/arm/mach-msm/spm_driver.h
index f272adb0..4cdfd33 100644
--- a/arch/arm/mach-msm/spm_driver.h
+++ b/arch/arm/mach-msm/spm_driver.h
@@ -35,6 +35,8 @@
 		uint32_t addr);
 int msm_spm_drv_set_vdd(struct msm_spm_driver_data *dev,
 		unsigned int vlevel);
+uint32_t msm_spm_drv_get_sts_curr_pmic_data(
+		struct msm_spm_driver_data *dev);
 int msm_spm_drv_write_seq_data(struct msm_spm_driver_data *dev,
 		uint8_t *cmd, uint32_t *offset);
 void msm_spm_drv_flush_seq_entry(struct msm_spm_driver_data *dev);
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index 668f4cc..b361d9d 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -966,7 +966,7 @@
 
 	if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
 	    cpu_is_msm8930() || cpu_is_msm8930aa() || cpu_is_msm8627() ||
-	    cpu_is_msm8960ab())
+	    cpu_is_msm8960ab() || cpu_is_apq8064ab())
 		__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
 
 	if (__get_cpu_var(first_boot)) {
@@ -1064,7 +1064,7 @@
 		dgt->flags |= MSM_CLOCK_FLAGS_UNSTABLE_COUNT;
 	} else if (cpu_is_msm8960() || cpu_is_apq8064() || cpu_is_msm8930() ||
 		   cpu_is_msm8930aa() || cpu_is_msm8627() ||
-		   cpu_is_msm8960ab()) {
+		   cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
 		global_timer_offset = MSM_TMR0_BASE - MSM_TMR_BASE;
 		dgt->freq = 6750000;
 		__raw_writel(DGT_CLK_CTL_DIV_4, MSM_TMR_BASE + DGT_CLK_CTL);
@@ -1127,7 +1127,7 @@
 		if (cpu_is_msm8x60() || cpu_is_msm8960() || cpu_is_apq8064() ||
 		    cpu_is_msm8930() || cpu_is_msm9615() || cpu_is_msm8625() ||
 		    cpu_is_msm8627() || cpu_is_msm8930aa() ||
-		    cpu_is_msm8960ab()) {
+		    cpu_is_msm8960ab() || cpu_is_apq8064ab()) {
 			clock->percpu_evt = alloc_percpu(struct clock_event_device *);
 			if (!clock->percpu_evt) {
 				pr_err("msm_timer_init: memory allocation "
diff --git a/arch/arm/mach-msm/wcnss-ssr-8960.c b/arch/arm/mach-msm/wcnss-ssr-8960.c
index f014df9..5516e30 100644
--- a/arch/arm/mach-msm/wcnss-ssr-8960.c
+++ b/arch/arm/mach-msm/wcnss-ssr-8960.c
@@ -186,7 +186,7 @@
 }
 
 static struct subsys_desc riva_8960 = {
-	.name = "riva",
+	.name = "wcnss",
 	.shutdown = riva_shutdown,
 	.powerup = riva_powerup,
 	.ramdump = riva_ramdump,
diff --git a/arch/arm/mach-msm/wdog_debug.c b/arch/arm/mach-msm/wdog_debug.c
new file mode 100644
index 0000000..82800cf
--- /dev/null
+++ b/arch/arm/mach-msm/wdog_debug.c
@@ -0,0 +1,149 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sched.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <mach/scm.h>
+#include <linux/slab.h>
+
+#define MODULE_NAME "wdog_debug"
+#define WDOG_DEBUG_EN 17
+#define GCC_WDOG_DEBUG_OFFSET 0x780
+
+struct msm_wdog_debug_data {
+	unsigned int __iomem phys_base;
+	size_t size;
+	void __iomem *base;
+	struct device *dev;
+};
+
+static struct msm_wdog_debug_data *wdog_data;
+
+void msm_disable_wdog_debug(void)
+{
+	unsigned long int value;
+
+	if (wdog_data == NULL)
+		return;
+	value = readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
+	value &= ~BIT(WDOG_DEBUG_EN);
+	writel_relaxed(value, wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
+}
+EXPORT_SYMBOL(msm_disable_wdog_debug);
+
+void msm_enable_wdog_debug(void)
+{
+	unsigned long int value;
+
+	if (wdog_data == NULL)
+		return;
+	value = readl_relaxed(wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
+	value |= BIT(WDOG_DEBUG_EN);
+	writel_relaxed(value, wdog_data->base + GCC_WDOG_DEBUG_OFFSET);
+}
+EXPORT_SYMBOL(msm_enable_wdog_debug);
+
+static int __devexit msm_wdog_debug_remove(struct platform_device *pdev)
+{
+	kfree(wdog_data);
+	wdog_data = NULL;
+	pr_info("MSM wdog_debug Exit - Deactivated\n");
+	return 0;
+}
+
+static int __devinit msm_wdog_debug_dt_to_pdata(struct platform_device *pdev,
+					struct msm_wdog_debug_data *pdata)
+{
+	struct resource *wdog_resource;
+
+	wdog_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!wdog_resource) {
+		dev_err(&pdev->dev, \
+		"%s cannot allocate resource for wdog_debug\n", \
+		 __func__);
+		return -ENXIO;
+	}
+	pdata->size = resource_size(wdog_resource);
+	pdata->phys_base = wdog_resource->start;
+	if (unlikely(!(devm_request_region(&pdev->dev, pdata->phys_base,
+					pdata->size, "msm-wdog-debug")))) {
+		dev_err(&pdev->dev, "%s cannot reserve wdog_debug region\n",
+								__func__);
+		return -ENXIO;
+	}
+	pdata->base  = devm_ioremap(&pdev->dev, pdata->phys_base,
+							pdata->size);
+	if (!pdata->base) {
+		dev_err(&pdev->dev, "%s cannot map wdog register space\n",
+				__func__);
+		return -ENXIO;
+	}
+
+	return 0;
+}
+
+static int __devinit msm_wdog_debug_probe(struct platform_device *pdev)
+{
+	int ret;
+	if (!pdev->dev.of_node)
+		return -ENODEV;
+	wdog_data = kzalloc(sizeof(struct msm_wdog_debug_data), GFP_KERNEL);
+	if (!wdog_data)
+		return -ENOMEM;
+	ret = msm_wdog_debug_dt_to_pdata(pdev, wdog_data);
+	if (ret)
+		goto err;
+	wdog_data->dev = &pdev->dev;
+	platform_set_drvdata(pdev, wdog_data);
+	msm_enable_wdog_debug();
+	return 0;
+err:
+	kzfree(wdog_data);
+	wdog_data = NULL;
+	return ret;
+}
+
+static struct of_device_id msm_wdog_debug_match_table[] = {
+	{ .compatible = "qcom,msm-wdog-debug" },
+	{}
+};
+
+static struct platform_driver msm_wdog_debug_driver = {
+	.probe = msm_wdog_debug_probe,
+	.remove = msm_wdog_debug_remove,
+	.driver = {
+		.name = MODULE_NAME,
+		.owner = THIS_MODULE,
+		.of_match_table = msm_wdog_debug_match_table,
+	},
+};
+
+static int __devinit wdog_debug_init(void)
+{
+	return platform_driver_register(&msm_wdog_debug_driver);
+}
+module_init(wdog_debug_init);
+
+static void __exit wdog_debug_exit(void)
+{
+	platform_driver_unregister(&msm_wdog_debug_driver);
+}
+module_exit(wdog_debug_exit);
+
+MODULE_DESCRIPTION("MSM Driver to disable debug Image");
+MODULE_LICENSE("GPL v2");
diff --git a/arch/arm/mach-msm/wdog_debug.h b/arch/arm/mach-msm/wdog_debug.h
new file mode 100644
index 0000000..920aa89
--- /dev/null
+++ b/arch/arm/mach-msm/wdog_debug.h
@@ -0,0 +1,24 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This 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 __WDOG_DEBUG_H
+#define __WDOG_DEBUG_H
+
+#ifdef CONFIG_MSM_ENABLE_WDOG_DEBUG_CONTROL
+void msm_enable_wdog_debug(void);
+void msm_disable_wdog_debug(void);
+#else
+void msm_enable_wdog_debug(void) { }
+void msm_disable_wdog_debug(void) { }
+#endif
+
+#endif
diff --git a/drivers/char/diag/Makefile b/drivers/char/diag/Makefile
index ea75ffd..6ecc970 100644
--- a/drivers/char/diag/Makefile
+++ b/drivers/char/diag/Makefile
@@ -2,4 +2,4 @@
 obj-$(CONFIG_DIAG_SDIO_PIPE) += diagfwd_sdio.o
 obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_hsic.o
 obj-$(CONFIG_DIAG_BRIDGE_CODE) += diagfwd_smux.o
-diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o
+diagchar-objs := diagchar_core.o diagchar_hdlc.o diagfwd.o diagmem.o diagfwd_cntl.o diag_dci.o diag_masks.o diag_debugfs.o
diff --git a/drivers/char/diag/diag_debugfs.c b/drivers/char/diag/diag_debugfs.c
new file mode 100644
index 0000000..ed0f08e
--- /dev/null
+++ b/drivers/char/diag/diag_debugfs.c
@@ -0,0 +1,305 @@
+/* Copyright (c) 2011-2012, The Linux Foundation. All rights reserved.
+ *
+ * This 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.
+ */
+
+#ifdef CONFIG_DEBUG_FS
+
+#include <linux/slab.h>
+#include <linux/debugfs.h>
+#include "diagchar.h"
+#include "diagfwd.h"
+
+#define DEBUG_BUF_SIZE	4096
+static struct dentry *diag_dbgfs_dent;
+static int diag_dbgfs_table_index;
+
+static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
+				      size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+		"modem ch: 0x%x\n"
+		"lpass ch: 0x%x\n"
+		"riva ch: 0x%x\n"
+		"dci ch: 0x%x\n"
+		"modem cntl_ch: 0x%x\n"
+		"lpass cntl_ch: 0x%x\n"
+		"riva cntl_ch: 0x%x\n"
+		"CPU Tools id: %d\n"
+		"Apps only: %d\n"
+		"Apps master: %d\n"
+		"Check Polling Response: %d\n"
+		"polling_reg_flag: %d\n"
+		"uses device tree: %d\n"
+		"in_busy_1: %d\n"
+		"in_busy_2: %d\n"
+		"in_busy_lpass_1: %d\n"
+		"in_busy_lpass_2: %d\n"
+		"in_busy_wcnss_1: %d\n"
+		"in_busy_wcnss_2: %d\n"
+		"in_busy_dci: %d\n"
+		"logging_mode: %d\n",
+		(unsigned int)driver->ch,
+		(unsigned int)driver->chlpass,
+		(unsigned int)driver->ch_wcnss,
+		(unsigned int)driver->ch_dci,
+		(unsigned int)driver->ch_cntl,
+		(unsigned int)driver->chlpass_cntl,
+		(unsigned int)driver->ch_wcnss_cntl,
+		chk_config_get_id(),
+		chk_apps_only(),
+		chk_apps_master(),
+		chk_polling_response(),
+		driver->polling_reg_flag,
+		driver->use_device_tree,
+		driver->in_busy_1,
+		driver->in_busy_2,
+		driver->in_busy_lpass_1,
+		driver->in_busy_lpass_2,
+		driver->in_busy_wcnss_1,
+		driver->in_busy_wcnss_2,
+		driver->in_busy_dci,
+		driver->logging_mode);
+
+#ifdef CONFIG_DIAG_OVER_USB
+	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+		"usb_connected: %d\n",
+		driver->usb_connected);
+#endif
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t diag_dbgfs_read_workpending(struct file *file,
+				char __user *ubuf, size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+		"Pending status for work_stucts:\n"
+		"diag_drain_work: %d\n"
+		"diag_read_smd_work: %d\n"
+		"diag_read_smd_cntl_work: %d\n"
+		"diag_read_smd_lpass_work: %d\n"
+		"diag_read_smd_lpass_cntl_work: %d\n"
+		"diag_read_smd_wcnss_work: %d\n"
+		"diag_read_smd_wcnss_cntl_work: %d\n"
+		"diag_modem_mask_update_work: %d\n"
+		"diag_lpass_mask_update_work: %d\n"
+		"diag_wcnss_mask_update_work: %d\n"
+		"diag_read_smd_dci_work: %d\n",
+		work_pending(&(driver->diag_drain_work)),
+		work_pending(&(driver->diag_read_smd_work)),
+		work_pending(&(driver->diag_read_smd_cntl_work)),
+		work_pending(&(driver->diag_read_smd_lpass_work)),
+		work_pending(&(driver->diag_read_smd_lpass_cntl_work)),
+		work_pending(&(driver->diag_read_smd_wcnss_work)),
+		work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
+		work_pending(&(driver->diag_modem_mask_update_work)),
+		work_pending(&(driver->diag_lpass_mask_update_work)),
+		work_pending(&(driver->diag_wcnss_mask_update_work)),
+		work_pending(&(driver->diag_read_smd_dci_work)));
+
+#ifdef CONFIG_DIAG_OVER_USB
+	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
+		"diag_proc_hdlc_work: %d\n"
+		"diag_read_work: %d\n",
+		work_pending(&(driver->diag_proc_hdlc_work)),
+		work_pending(&(driver->diag_read_work)));
+#endif
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+	kfree(buf);
+	return ret;
+}
+
+static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf,
+				     size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret = 0;
+	int i;
+	int bytes_remaining;
+	int bytes_in_buffer = 0;
+	int bytes_written;
+	int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
+
+	if (diag_dbgfs_table_index >= diag_max_reg) {
+		/* Done. Reset to prepare for future requests */
+		diag_dbgfs_table_index = 0;
+		return 0;
+	}
+
+	buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	bytes_remaining = buf_size;
+	for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
+		/* Do not process empty entries in the table */
+		if (driver->table[i].process_id == 0)
+			continue;
+
+		bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
+			"i: %3d, cmd_code: %4x, subsys_id: %4x, "
+			"client: %2d, cmd_code_lo: %4x, "
+			"cmd_code_hi: %4x, process_id: %5d\n",
+			i,
+			driver->table[i].cmd_code,
+			driver->table[i].subsys_id,
+			driver->table[i].client_id,
+			driver->table[i].cmd_code_lo,
+			driver->table[i].cmd_code_hi,
+			driver->table[i].process_id);
+
+		bytes_in_buffer += bytes_written;
+
+		/* Check if there is room to add another table entry */
+		bytes_remaining = buf_size - bytes_in_buffer;
+		if (bytes_remaining < bytes_written)
+			break;
+	}
+	diag_dbgfs_table_index = i;
+
+	*ppos = 0;
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
+
+	kfree(buf);
+	return ret;
+}
+
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
+				    size_t count, loff_t *ppos)
+{
+	char *buf;
+	int ret;
+
+	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
+	if (!buf) {
+		pr_err("diag: %s, Error allocating memory\n", __func__);
+		return -ENOMEM;
+	}
+
+	ret = scnprintf(buf, DEBUG_BUF_SIZE,
+		"hsic ch: %d\n"
+		"hsic_inited: %d\n"
+		"hsic enabled: %d\n"
+		"hsic_opened: %d\n"
+		"hsic_suspend: %d\n"
+		"in_busy_hsic_read_on_device: %d\n"
+		"in_busy_hsic_write: %d\n"
+		"count_hsic_pool: %d\n"
+		"count_hsic_write_pool: %d\n"
+		"diag_hsic_pool: %x\n"
+		"diag_hsic_write_pool: %x\n"
+		"write_len_mdm: %d\n"
+		"num_hsic_buf_tbl_entries: %d\n"
+		"usb_mdm_connected: %d\n"
+		"diag_read_mdm_work: %d\n"
+		"diag_read_hsic_work: %d\n"
+		"diag_disconnect_work: %d\n"
+		"diag_usb_read_complete_work: %d\n",
+		driver->hsic_ch,
+		driver->hsic_inited,
+		driver->hsic_device_enabled,
+		driver->hsic_device_opened,
+		driver->hsic_suspend,
+		driver->in_busy_hsic_read_on_device,
+		driver->in_busy_hsic_write,
+		driver->count_hsic_pool,
+		driver->count_hsic_write_pool,
+		(unsigned int)driver->diag_hsic_pool,
+		(unsigned int)driver->diag_hsic_write_pool,
+		driver->write_len_mdm,
+		driver->num_hsic_buf_tbl_entries,
+		driver->usb_mdm_connected,
+		work_pending(&(driver->diag_read_mdm_work)),
+		work_pending(&(driver->diag_read_hsic_work)),
+		work_pending(&(driver->diag_disconnect_work)),
+		work_pending(&(driver->diag_usb_read_complete_work)));
+
+	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
+
+	kfree(buf);
+	return ret;
+}
+
+const struct file_operations diag_dbgfs_hsic_ops = {
+	.read = diag_dbgfs_read_hsic,
+};
+#endif
+
+const struct file_operations diag_dbgfs_status_ops = {
+	.read = diag_dbgfs_read_status,
+};
+
+const struct file_operations diag_dbgfs_table_ops = {
+	.read = diag_dbgfs_read_table,
+};
+
+const struct file_operations diag_dbgfs_workpending_ops = {
+	.read = diag_dbgfs_read_workpending,
+};
+
+void diag_debugfs_init(void)
+{
+	diag_dbgfs_dent = debugfs_create_dir("diag", 0);
+	if (IS_ERR(diag_dbgfs_dent))
+		return;
+
+	debugfs_create_file("status", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_status_ops);
+
+	debugfs_create_file("table", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_table_ops);
+
+	debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_workpending_ops);
+
+#ifdef CONFIG_DIAG_BRIDGE_CODE
+	debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
+		&diag_dbgfs_hsic_ops);
+#endif
+
+	diag_dbgfs_table_index = 0;
+}
+
+void diag_debugfs_cleanup(void)
+{
+	if (diag_dbgfs_dent) {
+		debugfs_remove_recursive(diag_dbgfs_dent);
+		diag_dbgfs_dent = NULL;
+	}
+}
+#else
+void diag_debugfs_init(void) { }
+void diag_debugfs_cleanup(void) { }
+#endif
diff --git a/drivers/char/diag/diag_debugfs.h b/drivers/char/diag/diag_debugfs.h
new file mode 100644
index 0000000..4bc8b0f
--- /dev/null
+++ b/drivers/char/diag/diag_debugfs.h
@@ -0,0 +1,19 @@
+/* Copyright (c)2012, The Linux Foundation. All rights reserved.
+ *
+ * This 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 DIAG_DEBUGFS_H
+#define DIAG_DEBUGFS_H
+
+void diag_debugfs_init(void);
+void diag_debugfs_cleanup(void);
+
+#endif
diff --git a/drivers/char/diag/diag_masks.c b/drivers/char/diag/diag_masks.c
new file mode 100644
index 0000000..5316548
--- /dev/null
+++ b/drivers/char/diag/diag_masks.c
@@ -0,0 +1,790 @@
+/* Copyright (c) 2008-2012, The Linux Foundation. All rights reserved.
+ *
+ * This 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/slab.h>
+#include <linux/delay.h>
+#include <linux/diagchar.h>
+#include <linux/kmemleak.h>
+#include <linux/workqueue.h>
+#include "diagchar.h"
+#include "diagfwd_cntl.h"
+#include "diag_masks.h"
+
+int diag_event_config;
+int diag_event_num_bytes;
+
+#define ALL_EQUIP_ID		100
+#define ALL_SSID		-1
+#define MAX_SSID_PER_RANGE	100
+
+struct mask_info {
+	int equip_id;
+	int num_items;
+	int index;
+};
+
+#define CREATE_MSG_MASK_TBL_ROW(XX)					\
+do {									\
+	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX;			\
+	msg_mask_tbl_ptr += 4;						\
+	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST;		\
+	msg_mask_tbl_ptr += 4;						\
+	/* mimic the last entry as actual_last while creation */	\
+	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST;		\
+	msg_mask_tbl_ptr += 4;						\
+	/* increment by MAX_SSID_PER_RANGE cells */			\
+	msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int);		\
+} while (0)
+
+#define WAIT_FOR_SMD(num_delays, delay_time)		\
+do {							\
+	int count;					\
+	for (count = 0; count < (num_delays); count++)	\
+		udelay((delay_time));			\
+} while (0)
+
+static void diag_print_mask_table(void)
+{
+/* Enable this to print mask table when updated */
+#ifdef MASK_DEBUG
+	int first, last, actual_last;
+	uint8_t *ptr = driver->msg_masks;
+	int i = 0;
+	pr_info("diag: F3 message mask table\n");
+	while (*(uint32_t *)(ptr + 4)) {
+		first = *(uint32_t *)ptr;
+		ptr += 4;
+		last = *(uint32_t *)ptr;
+		ptr += 4;
+		actual_last = *(uint32_t *)ptr;
+		ptr += 4;
+		pr_info("diag: SSID %d, %d - %d\n", first, last, actual_last);
+		for (i = 0 ; i <= actual_last - first ; i++)
+			pr_info("diag: MASK:%x\n", *((uint32_t *)ptr + i));
+		ptr += MAX_SSID_PER_RANGE*4;
+	}
+#endif
+}
+
+void diag_create_msg_mask_table(void)
+{
+	uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
+
+	CREATE_MSG_MASK_TBL_ROW(0);
+	CREATE_MSG_MASK_TBL_ROW(1);
+	CREATE_MSG_MASK_TBL_ROW(2);
+	CREATE_MSG_MASK_TBL_ROW(3);
+	CREATE_MSG_MASK_TBL_ROW(4);
+	CREATE_MSG_MASK_TBL_ROW(5);
+	CREATE_MSG_MASK_TBL_ROW(6);
+	CREATE_MSG_MASK_TBL_ROW(7);
+	CREATE_MSG_MASK_TBL_ROW(8);
+	CREATE_MSG_MASK_TBL_ROW(9);
+	CREATE_MSG_MASK_TBL_ROW(10);
+	CREATE_MSG_MASK_TBL_ROW(11);
+	CREATE_MSG_MASK_TBL_ROW(12);
+	CREATE_MSG_MASK_TBL_ROW(13);
+	CREATE_MSG_MASK_TBL_ROW(14);
+	CREATE_MSG_MASK_TBL_ROW(15);
+	CREATE_MSG_MASK_TBL_ROW(16);
+	CREATE_MSG_MASK_TBL_ROW(17);
+	CREATE_MSG_MASK_TBL_ROW(18);
+	CREATE_MSG_MASK_TBL_ROW(19);
+	CREATE_MSG_MASK_TBL_ROW(20);
+	CREATE_MSG_MASK_TBL_ROW(21);
+	CREATE_MSG_MASK_TBL_ROW(22);
+	CREATE_MSG_MASK_TBL_ROW(23);
+}
+
+static void diag_set_msg_mask(int rt_mask)
+{
+	int first_ssid, last_ssid, i;
+	uint8_t *parse_ptr, *ptr = driver->msg_masks;
+
+	mutex_lock(&driver->diagchar_mutex);
+	while (*(uint32_t *)(ptr + 4)) {
+		first_ssid = *(uint32_t *)ptr;
+		ptr += 8; /* increment by 8 to skip 'last' */
+		last_ssid = *(uint32_t *)ptr;
+		ptr += 4;
+		parse_ptr = ptr;
+		pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
+		for (i = 0; i < last_ssid - first_ssid + 1; i++) {
+			*(int *)parse_ptr = rt_mask;
+			parse_ptr += 4;
+		}
+		ptr += MAX_SSID_PER_RANGE * 4;
+	}
+	mutex_unlock(&driver->diagchar_mutex);
+}
+
+static void diag_update_msg_mask(int start, int end , uint8_t *buf)
+{
+	int found = 0, first, last, actual_last;
+	uint8_t *actual_last_ptr;
+	uint8_t *ptr = driver->msg_masks;
+	uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
+	uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
+
+	mutex_lock(&driver->diagchar_mutex);
+
+	/* First SSID can be zero : So check that last is non-zero */
+	while (*(uint32_t *)(ptr + 4)) {
+		first = *(uint32_t *)ptr;
+		ptr += 4;
+		last = *(uint32_t *)ptr;
+		ptr += 4;
+		actual_last = *(uint32_t *)ptr;
+		actual_last_ptr = ptr;
+		ptr += 4;
+		if (start >= first && start <= actual_last) {
+			ptr += (start - first)*4;
+			if (end > actual_last) {
+				pr_info("diag: ssid range mismatch\n");
+				actual_last = end;
+				*(uint32_t *)(actual_last_ptr) = end;
+			}
+			if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
+					  (((end - start)+1)*4))) {
+				pr_debug("diag: update ssid start %d, end %d\n",
+								 start, end);
+				memcpy(ptr, buf , ((end - start)+1)*4);
+			} else
+				pr_alert("diag: Not enough space MSG_MASK\n");
+			found = 1;
+			break;
+		} else {
+			ptr += MAX_SSID_PER_RANGE*4;
+		}
+	}
+	/* Entry was not found - add new table */
+	if (!found) {
+		if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
+				  8 + ((end - start) + 1)*4)) {
+			memcpy(ptr, &(start) , 4);
+			ptr += 4;
+			memcpy(ptr, &(end), 4);
+			ptr += 4;
+			memcpy(ptr, &(end), 4); /* create actual_last entry */
+			ptr += 4;
+			pr_debug("diag: adding NEW ssid start %d, end %d\n",
+								 start, end);
+			memcpy(ptr, buf , ((end - start) + 1)*4);
+		} else
+			pr_alert("diag: Not enough buffer space for MSG_MASK\n");
+	}
+	mutex_unlock(&driver->diagchar_mutex);
+	diag_print_mask_table();
+}
+
+void diag_toggle_event_mask(int toggle)
+{
+	uint8_t *ptr = driver->event_masks;
+
+	mutex_lock(&driver->diagchar_mutex);
+	if (toggle)
+		memset(ptr, 0xFF, EVENT_MASK_SIZE);
+	else
+		memset(ptr, 0, EVENT_MASK_SIZE);
+	mutex_unlock(&driver->diagchar_mutex);
+}
+
+
+static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
+{
+	uint8_t *ptr = driver->event_masks;
+	uint8_t *temp = buf + 2;
+
+	mutex_lock(&driver->diagchar_mutex);
+	if (!toggle)
+		memset(ptr, 0 , EVENT_MASK_SIZE);
+	else
+		if (CHK_OVERFLOW(ptr, ptr,
+				 ptr+EVENT_MASK_SIZE, num_bytes))
+			memcpy(ptr, temp , num_bytes);
+		else
+			printk(KERN_CRIT "Not enough buffer space for EVENT_MASK\n");
+	mutex_unlock(&driver->diagchar_mutex);
+}
+
+static void diag_disable_log_mask(void)
+{
+	int i = 0;
+	struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
+
+	pr_debug("diag: disable log masks\n");
+	mutex_lock(&driver->diagchar_mutex);
+	for (i = 0; i < MAX_EQUIP_ID; i++) {
+		pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
+		if (!(parse_ptr->equip_id)) /* Reached a null entry */
+			break;
+		memset(driver->log_masks + parse_ptr->index, 0,
+			    (parse_ptr->num_items + 7)/8);
+		parse_ptr++;
+	}
+	mutex_unlock(&driver->diagchar_mutex);
+}
+
+int chk_equip_id_and_mask(int equip_id, uint8_t *buf)
+{
+	int i = 0, flag = 0, num_items, offset;
+	unsigned char *ptr_data;
+	struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
+
+	pr_debug("diag: received equip id = %d\n", equip_id);
+	/* Check if this is valid equipment ID */
+	for (i = 0; i < MAX_EQUIP_ID; i++) {
+		if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
+			offset = ptr->index;
+			num_items = ptr->num_items;
+			flag = 1;
+			break;
+		}
+		ptr++;
+	}
+	if (!flag)
+		return -EPERM;
+	ptr_data = driver->log_masks + offset;
+	memcpy(buf, ptr_data, (num_items+7)/8);
+	return 0;
+}
+
+static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
+{
+	uint8_t *temp = buf;
+	int i = 0;
+	unsigned char *ptr_data;
+	int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
+	struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
+
+	pr_debug("diag: received equip id = %d\n", equip_id);
+	mutex_lock(&driver->diagchar_mutex);
+	/* Check if we already know index of this equipment ID */
+	for (i = 0; i < MAX_EQUIP_ID; i++) {
+		if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
+			offset = ptr->index;
+			break;
+		}
+		if ((ptr->equip_id == 0) && (ptr->index == 0)) {
+			/* Reached a null entry */
+			ptr->equip_id = equip_id;
+			ptr->num_items = num_items;
+			ptr->index = driver->log_masks_length;
+			offset = driver->log_masks_length;
+			driver->log_masks_length += ((num_items+7)/8);
+			break;
+		}
+		ptr++;
+	}
+	ptr_data = driver->log_masks + offset;
+	if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
+					 + LOG_MASK_SIZE, (num_items+7)/8))
+		memcpy(ptr_data, temp , (num_items+7)/8);
+	else
+		pr_err("diag: Not enough buffer space for LOG_MASK\n");
+	mutex_unlock(&driver->diagchar_mutex);
+}
+
+void diag_modem_mask_update_fn(struct work_struct *work)
+{
+	diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
+					   ALL_SSID, MODEM_PROC);
+	diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
+	diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
+}
+
+void diag_lpass_mask_update_fn(struct work_struct *work)
+{
+	diag_send_msg_mask_update(driver->chlpass_cntl, ALL_SSID,
+						   ALL_SSID, LPASS_PROC);
+	diag_send_log_mask_update(driver->chlpass_cntl, ALL_EQUIP_ID);
+	diag_send_event_mask_update(driver->chlpass_cntl, diag_event_num_bytes);
+}
+
+void diag_wcnss_mask_update_fn(struct work_struct *work)
+{
+	diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
+						   ALL_SSID, WCNSS_PROC);
+	diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
+	diag_send_event_mask_update(driver->ch_wcnss_cntl,
+						 diag_event_num_bytes);
+}
+
+void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
+{
+	void *buf = driver->buf_log_mask_update;
+	int header_size = sizeof(struct diag_ctrl_log_mask);
+	struct mask_info *ptr = (struct mask_info *)driver->log_masks;
+	int i, size, wr_size = -ENOMEM, retry_count = 0;
+
+	mutex_lock(&driver->diag_cntl_mutex);
+	for (i = 0; i < MAX_EQUIP_ID; i++) {
+		size = (ptr->num_items+7)/8;
+		/* reached null entry */
+		if ((ptr->equip_id == 0) && (ptr->index == 0))
+			break;
+		driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
+		driver->log_mask->num_items = ptr->num_items;
+		driver->log_mask->data_len  = 11 + size;
+		driver->log_mask->stream_id = 1; /* 2, if dual stream */
+		driver->log_mask->status = 3; /* status for valid mask */
+		driver->log_mask->equip_id = ptr->equip_id;
+		driver->log_mask->log_mask_size = size;
+		/* send only desired update, NOT ALL */
+		if (equip_id == ALL_EQUIP_ID || equip_id ==
+					 driver->log_mask->equip_id) {
+			memcpy(buf, driver->log_mask, header_size);
+			memcpy(buf+header_size, driver->log_masks+ptr->index,
+									 size);
+			if (ch) {
+				while (retry_count < 3) {
+					wr_size = smd_write(ch, buf,
+							 header_size + size);
+					if (wr_size == -ENOMEM) {
+						retry_count++;
+						WAIT_FOR_SMD(5, 2000);
+					} else
+						break;
+				}
+				if (wr_size != header_size + size)
+					pr_err("diag: log mask update failed %d, tried %d",
+						wr_size, header_size + size);
+				else
+					pr_debug("diag: updated log equip ID %d,len %d\n",
+					driver->log_mask->equip_id,
+					driver->log_mask->log_mask_size);
+			} else
+				pr_err("diag: ch not valid for log update\n");
+		}
+		ptr++;
+	}
+	mutex_unlock(&driver->diag_cntl_mutex);
+}
+
+void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
+{
+	void *buf = driver->buf_event_mask_update;
+	int header_size = sizeof(struct diag_ctrl_event_mask);
+	int wr_size = -ENOMEM, retry_count = 0;
+
+	mutex_lock(&driver->diag_cntl_mutex);
+	if (num_bytes == 0) {
+		pr_debug("diag: event mask not set yet, so no update\n");
+		mutex_unlock(&driver->diag_cntl_mutex);
+		return;
+	}
+	/* send event mask update */
+	driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
+	driver->event_mask->data_len = 7 + num_bytes;
+	driver->event_mask->stream_id = 1; /* 2, if dual stream */
+	driver->event_mask->status = 3; /* status for valid mask */
+	driver->event_mask->event_config = diag_event_config; /* event config */
+	driver->event_mask->event_mask_size = num_bytes;
+	memcpy(buf, driver->event_mask, header_size);
+	memcpy(buf+header_size, driver->event_masks, num_bytes);
+	if (ch) {
+		while (retry_count < 3) {
+			wr_size = smd_write(ch, buf, header_size + num_bytes);
+			if (wr_size == -ENOMEM) {
+				retry_count++;
+				WAIT_FOR_SMD(5, 2000);
+			} else
+				break;
+		}
+		if (wr_size != header_size + num_bytes)
+			pr_err("diag: error writing event mask %d, tried %d\n",
+					 wr_size, header_size + num_bytes);
+	} else
+		pr_err("diag: ch not valid for event update\n");
+	mutex_unlock(&driver->diag_cntl_mutex);
+}
+
+void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
+						int updated_ssid_last, int proc)
+{
+	void *buf = driver->buf_msg_mask_update;
+	int first, last, actual_last, size = -ENOMEM, retry_count = 0;
+	int header_size = sizeof(struct diag_ctrl_msg_mask);
+	uint8_t *ptr = driver->msg_masks;
+
+	mutex_lock(&driver->diag_cntl_mutex);
+	while (*(uint32_t *)(ptr + 4)) {
+		first = *(uint32_t *)ptr;
+		ptr += 4;
+		last = *(uint32_t *)ptr;
+		ptr += 4;
+		actual_last = *(uint32_t *)ptr;
+		ptr += 4;
+		if ((updated_ssid_first >= first && updated_ssid_last <=
+			 actual_last) || (updated_ssid_first == ALL_SSID)) {
+			/* send f3 mask update */
+			driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
+			driver->msg_mask->msg_mask_size = actual_last -
+								 first + 1;
+			driver->msg_mask->data_len = 11 +
+					 4 * (driver->msg_mask->msg_mask_size);
+			driver->msg_mask->stream_id = 1; /* 2, if dual stream */
+			driver->msg_mask->status = 3; /* status valid mask */
+			driver->msg_mask->msg_mode = 0; /* Legcay mode */
+			driver->msg_mask->ssid_first = first;
+			driver->msg_mask->ssid_last = actual_last;
+			memcpy(buf, driver->msg_mask, header_size);
+			memcpy(buf+header_size, ptr,
+				 4 * (driver->msg_mask->msg_mask_size));
+			if (ch) {
+				while (retry_count < 3) {
+					size = smd_write(ch, buf, header_size +
+					 4*(driver->msg_mask->msg_mask_size));
+					if (size == -ENOMEM) {
+						retry_count++;
+						WAIT_FOR_SMD(5, 2000);
+					} else
+						break;
+				}
+				if (size != header_size +
+					 4*(driver->msg_mask->msg_mask_size))
+					pr_err("diag: proc %d, msg mask update fail %d, tried %d\n",
+						proc, size, (header_size +
+					4*(driver->msg_mask->msg_mask_size)));
+				else
+					pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
+						first, actual_last, proc);
+			} else
+				pr_err("diag: proc %d, ch invalid msg mask update\n",
+					proc);
+		}
+		ptr += MAX_SSID_PER_RANGE*4;
+	}
+	mutex_unlock(&driver->diag_cntl_mutex);
+}
+
+int diag_process_apps_masks(unsigned char *buf, int len)
+{
+	int packet_type = 1;
+	int i;
+	int ssid_first, ssid_last, ssid_range;
+	int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
+	uint8_t *rt_mask_ptr;
+	int equip_id, num_items;
+#if defined(CONFIG_DIAG_OVER_USB)
+	int payload_length;
+#endif
+
+	/* Set log masks */
+	if (*buf == 0x73 && *(int *)(buf+4) == 3) {
+		buf += 8;
+		/* Read Equip ID and pass as first param below*/
+		diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
+		diag_update_userspace_clients(LOG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (chk_apps_only()) {
+			driver->apps_rsp_buf[0] = 0x73;
+			*(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
+			*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
+			payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
+			for (i = 0; i < payload_length; i++)
+				*(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
+			if (driver->ch_cntl)
+				diag_send_log_mask_update(driver->ch_cntl,
+				*(int *)buf);
+			if (driver->chlpass_cntl)
+				diag_send_log_mask_update(driver->chlpass_cntl,
+				*(int *)buf);
+			if (driver->ch_wcnss_cntl)
+				diag_send_log_mask_update(driver->ch_wcnss_cntl,
+				*(int *)buf);
+			encode_rsp_and_send(12 + payload_length - 1);
+			return 0;
+		}
+#endif
+	} /* Get log masks */
+	else if (*buf == 0x73 && *(int *)(buf+4) == 4) {
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (!(driver->ch) && chk_apps_only()) {
+			equip_id = *(int *)(buf + 8);
+			num_items = *(int *)(buf + 12);
+			driver->apps_rsp_buf[0] = 0x73;
+			driver->apps_rsp_buf[1] = 0x0;
+			driver->apps_rsp_buf[2] = 0x0;
+			driver->apps_rsp_buf[3] = 0x0;
+			*(int *)(driver->apps_rsp_buf + 4) = 0x4;
+			if (!chk_equip_id_and_mask(equip_id,
+				driver->apps_rsp_buf+20))
+				*(int *)(driver->apps_rsp_buf + 8) = 0x0;
+			else
+				*(int *)(driver->apps_rsp_buf + 8) = 0x1;
+			*(int *)(driver->apps_rsp_buf + 12) = equip_id;
+			*(int *)(driver->apps_rsp_buf + 16) = num_items;
+			encode_rsp_and_send(20+(num_items+7)/8-1);
+			return 0;
+		}
+#endif
+	} /* Disable log masks */
+	else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
+		/* Disable mask for each log code */
+		diag_disable_log_mask();
+		diag_update_userspace_clients(LOG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (chk_apps_only()) {
+			driver->apps_rsp_buf[0] = 0x73;
+			driver->apps_rsp_buf[1] = 0x0;
+			driver->apps_rsp_buf[2] = 0x0;
+			driver->apps_rsp_buf[3] = 0x0;
+			*(int *)(driver->apps_rsp_buf + 4) = 0x0;
+			*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
+			if (driver->ch_cntl)
+				diag_send_log_mask_update(driver->ch_cntl,
+				ALL_EQUIP_ID);
+			if (driver->chlpass_cntl)
+				diag_send_log_mask_update(driver->chlpass_cntl,
+				ALL_EQUIP_ID);
+			if (driver->ch_wcnss_cntl)
+				diag_send_log_mask_update(driver->ch_wcnss_cntl,
+				ALL_EQUIP_ID);
+			encode_rsp_and_send(11);
+			return 0;
+		}
+#endif
+	} /* Get runtime message mask  */
+	else if ((*buf == 0x7d) && (*(buf+1) == 0x3)) {
+		ssid_first = *(uint16_t *)(buf + 2);
+		ssid_last = *(uint16_t *)(buf + 4);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (!(driver->ch) && chk_apps_only()) {
+			driver->apps_rsp_buf[0] = 0x7d;
+			driver->apps_rsp_buf[1] = 0x3;
+			*(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
+			*(uint16_t *)(driver->apps_rsp_buf+4) = ssid_last;
+			driver->apps_rsp_buf[6] = 0x1; /* Success Status */
+			driver->apps_rsp_buf[7] = 0x0;
+			rt_mask_ptr = driver->msg_masks;
+			while (*(uint32_t *)(rt_mask_ptr + 4)) {
+				rt_first_ssid = *(uint32_t *)rt_mask_ptr;
+				rt_mask_ptr += 8; /* +8 to skip 'last' */
+				rt_last_ssid = *(uint32_t *)rt_mask_ptr;
+				rt_mask_ptr += 4;
+				if (ssid_first == rt_first_ssid && ssid_last ==
+					rt_last_ssid) {
+					rt_mask_size = 4 * (rt_last_ssid -
+						rt_first_ssid + 1);
+					memcpy(driver->apps_rsp_buf+8,
+						rt_mask_ptr, rt_mask_size);
+					encode_rsp_and_send(8+rt_mask_size-1);
+					return 0;
+				}
+				rt_mask_ptr += MAX_SSID_PER_RANGE*4;
+			}
+		}
+#endif
+	} /* Set runtime message mask  */
+	else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
+		ssid_first = *(uint16_t *)(buf + 2);
+		ssid_last = *(uint16_t *)(buf + 4);
+		ssid_range = 4 * (ssid_last - ssid_first + 1);
+		pr_debug("diag: received mask update for ssid_first = %d, ssid_last = %d",
+			ssid_first, ssid_last);
+		diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
+		diag_update_userspace_clients(MSG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (chk_apps_only()) {
+			for (i = 0; i < 8 + ssid_range; i++)
+				*(driver->apps_rsp_buf + i) = *(buf+i);
+			*(driver->apps_rsp_buf + 6) = 0x1;
+			if (driver->ch_cntl)
+				diag_send_msg_mask_update(driver->ch_cntl,
+				ssid_first, ssid_last, MODEM_PROC);
+			if (driver->chlpass_cntl)
+				diag_send_msg_mask_update(driver->chlpass_cntl,
+				ssid_first, ssid_last, LPASS_PROC);
+			if (driver->ch_wcnss_cntl)
+				diag_send_msg_mask_update(driver->ch_wcnss_cntl,
+				ssid_first, ssid_last, WCNSS_PROC);
+			encode_rsp_and_send(8 + ssid_range - 1);
+			return 0;
+		}
+#endif
+	} /* Set ALL runtime message mask  */
+	else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
+		rt_mask = *(int *)(buf + 4);
+		diag_set_msg_mask(rt_mask);
+		diag_update_userspace_clients(MSG_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (chk_apps_only()) {
+			driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
+			driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
+			driver->apps_rsp_buf[2] = 1; /* success */
+			driver->apps_rsp_buf[3] = 0; /* rsvd */
+			*(int *)(driver->apps_rsp_buf + 4) = rt_mask;
+			/* send msg mask update to peripheral */
+			if (driver->ch_cntl)
+				diag_send_msg_mask_update(driver->ch_cntl,
+				ALL_SSID, ALL_SSID, MODEM_PROC);
+			if (driver->chlpass_cntl)
+				diag_send_msg_mask_update(driver->chlpass_cntl,
+				ALL_SSID, ALL_SSID, LPASS_PROC);
+			if (driver->ch_wcnss_cntl)
+				diag_send_msg_mask_update(driver->ch_wcnss_cntl,
+				ALL_SSID, ALL_SSID, WCNSS_PROC);
+			encode_rsp_and_send(7);
+			return 0;
+		}
+#endif
+	} else if (*buf == 0x82) {	/* event mask change */
+		buf += 4;
+		diag_event_num_bytes =  (*(uint16_t *)buf)/8+1;
+		diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
+		diag_update_userspace_clients(EVENT_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (chk_apps_only()) {
+			driver->apps_rsp_buf[0] = 0x82;
+			driver->apps_rsp_buf[1] = 0x0;
+			*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
+			*(uint16_t *)(driver->apps_rsp_buf + 4) =
+				EVENT_LAST_ID + 1;
+			memcpy(driver->apps_rsp_buf+6, driver->event_masks,
+				EVENT_LAST_ID/8+1);
+			if (driver->ch_cntl)
+				diag_send_event_mask_update(driver->ch_cntl,
+				diag_event_num_bytes);
+			if (driver->chlpass_cntl)
+				diag_send_event_mask_update(
+				driver->chlpass_cntl,
+				diag_event_num_bytes);
+			if (driver->ch_wcnss_cntl)
+				diag_send_event_mask_update(
+				driver->ch_wcnss_cntl, diag_event_num_bytes);
+			encode_rsp_and_send(6 + EVENT_LAST_ID/8);
+			return 0;
+		}
+#endif
+	} else if (*buf == 0x60) {
+		diag_event_config = *(buf+1);
+		diag_toggle_event_mask(*(buf+1));
+		diag_update_userspace_clients(EVENT_MASKS_TYPE);
+#if defined(CONFIG_DIAG_OVER_USB)
+		if (chk_apps_only()) {
+			driver->apps_rsp_buf[0] = 0x60;
+			driver->apps_rsp_buf[1] = 0x0;
+			driver->apps_rsp_buf[2] = 0x0;
+			if (driver->ch_cntl)
+				diag_send_event_mask_update(driver->ch_cntl,
+				diag_event_num_bytes);
+			if (driver->chlpass_cntl)
+				diag_send_event_mask_update(
+				driver->chlpass_cntl,
+				diag_event_num_bytes);
+			if (driver->ch_wcnss_cntl)
+				diag_send_event_mask_update(
+				driver->ch_wcnss_cntl, diag_event_num_bytes);
+			encode_rsp_and_send(2);
+			return 0;
+		}
+#endif
+	}
+
+	return  packet_type;
+}
+
+void diag_masks_init(void)
+{
+	if (driver->event_mask == NULL) {
+		driver->event_mask = kzalloc(sizeof(
+			struct diag_ctrl_event_mask), GFP_KERNEL);
+		if (driver->event_mask == NULL)
+			goto err;
+		kmemleak_not_leak(driver->event_mask);
+	}
+	if (driver->msg_mask == NULL) {
+		driver->msg_mask = kzalloc(sizeof(
+			struct diag_ctrl_msg_mask), GFP_KERNEL);
+		if (driver->msg_mask == NULL)
+			goto err;
+		kmemleak_not_leak(driver->msg_mask);
+	}
+	if (driver->log_mask == NULL) {
+		driver->log_mask = kzalloc(sizeof(
+			struct diag_ctrl_log_mask), GFP_KERNEL);
+		if (driver->log_mask == NULL)
+			goto err;
+		kmemleak_not_leak(driver->log_mask);
+	}
+
+	if (driver->buf_msg_mask_update == NULL) {
+		driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
+								 GFP_KERNEL);
+		if (driver->buf_msg_mask_update == NULL)
+			goto err;
+		kmemleak_not_leak(driver->buf_msg_mask_update);
+	}
+	if (driver->buf_log_mask_update == NULL) {
+		driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
+								 GFP_KERNEL);
+		if (driver->buf_log_mask_update == NULL)
+			goto err;
+		kmemleak_not_leak(driver->buf_log_mask_update);
+	}
+	if (driver->buf_event_mask_update == NULL) {
+		driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
+								 GFP_KERNEL);
+		if (driver->buf_event_mask_update == NULL)
+			goto err;
+		kmemleak_not_leak(driver->buf_event_mask_update);
+	}
+	if (driver->msg_masks == NULL) {
+		driver->msg_masks = kzalloc(MSG_MASK_SIZE, GFP_KERNEL);
+		if (driver->msg_masks == NULL)
+			goto err;
+		kmemleak_not_leak(driver->msg_masks);
+	}
+	diag_create_msg_mask_table();
+	diag_event_num_bytes = 0;
+	if (driver->log_masks == NULL) {
+		driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL);
+		if (driver->log_masks == NULL)
+			goto err;
+		kmemleak_not_leak(driver->log_masks);
+	}
+	driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
+	if (driver->event_masks == NULL) {
+		driver->event_masks = kzalloc(EVENT_MASK_SIZE, GFP_KERNEL);
+		if (driver->event_masks == NULL)
+			goto err;
+		kmemleak_not_leak(driver->event_masks);
+	}
+#ifdef CONFIG_DIAG_OVER_USB
+	INIT_WORK(&(driver->diag_modem_mask_update_work),
+						 diag_modem_mask_update_fn);
+	INIT_WORK(&(driver->diag_lpass_mask_update_work),
+						 diag_lpass_mask_update_fn);
+	INIT_WORK(&(driver->diag_wcnss_mask_update_work),
+						 diag_wcnss_mask_update_fn);
+#endif
+	return;
+err:
+	pr_err("diag: Could not initialize diag mask buffers");
+	kfree(driver->event_mask);
+	kfree(driver->log_mask);
+	kfree(driver->msg_mask);
+	kfree(driver->msg_masks);
+	kfree(driver->log_masks);
+	kfree(driver->event_masks);
+}
+
+void diag_masks_exit(void)
+{
+	kfree(driver->event_mask);
+	kfree(driver->log_mask);
+	kfree(driver->msg_mask);
+	kfree(driver->msg_masks);
+	kfree(driver->log_masks);
+	kfree(driver->event_masks);
+}
diff --git a/drivers/char/diag/diag_masks.h b/drivers/char/diag/diag_masks.h
new file mode 100644
index 0000000..bcf5bc2
--- /dev/null
+++ b/drivers/char/diag/diag_masks.h
@@ -0,0 +1,27 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * This 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 DIAG_MASKS_H
+#define DIAG_MASKS_H
+
+#include "diagfwd.h"
+
+int chk_equip_id_and_mask(int equip_id, uint8_t *buf);
+void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
+void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
+					 int ssid_last, int proc);
+void diag_send_log_mask_update(smd_channel_t *, int);
+int diag_process_apps_masks(unsigned char *buf, int len);
+void diag_masks_init(void);
+void diag_masks_exit(void);
+extern int diag_event_num_bytes;
+#endif
diff --git a/drivers/char/diag/diagchar_core.c b/drivers/char/diag/diagchar_core.c
index 814fe64..09da40c 100644
--- a/drivers/char/diag/diagchar_core.c
+++ b/drivers/char/diag/diagchar_core.c
@@ -37,6 +37,8 @@
 #include "diagfwd_smux.h"
 #endif
 #include <linux/timer.h>
+#include "diag_debugfs.h"
+#include "diag_masks.h"
 
 MODULE_DESCRIPTION("Diag Char Driver");
 MODULE_LICENSE("GPL v2");
@@ -1422,6 +1424,7 @@
 		diag_debugfs_init();
 		diagfwd_init();
 		diagfwd_cntl_init();
+		diag_masks_init();
 		driver->dci_state = diag_dci_init();
 		diag_sdio_fn(INIT);
 		diag_bridge_fn(INIT);
@@ -1457,6 +1460,7 @@
 	diagchar_cleanup();
 	diagfwd_exit();
 	diagfwd_cntl_exit();
+	diag_masks_exit();
 	diag_sdio_fn(EXIT);
 	diag_bridge_fn(EXIT);
 	return -1;
@@ -1470,6 +1474,7 @@
 	diagmem_exit(driver, POOL_TYPE_ALL);
 	diagfwd_exit();
 	diagfwd_cntl_exit();
+	diag_masks_exit();
 	diag_sdio_fn(EXIT);
 	diag_bridge_fn(EXIT);
 	diag_debugfs_cleanup();
diff --git a/drivers/char/diag/diagfwd.c b/drivers/char/diag/diagfwd.c
index 737edbf..a537bb3 100644
--- a/drivers/char/diag/diagfwd.c
+++ b/drivers/char/diag/diagfwd.c
@@ -39,63 +39,38 @@
 #include "diagfwd_sdio.h"
 #endif
 #include "diag_dci.h"
+#include "diag_masks.h"
 
 #define MODE_CMD		41
 #define RESET_ID		2
-#define ALL_EQUIP_ID		100
-#define ALL_SSID		-1
-#define MAX_SSID_PER_RANGE	100
 
 int diag_debug_buf_idx;
 unsigned char diag_debug_buf[1024];
 static unsigned int buf_tbl_size = 8; /*Number of entries in table of buffers */
 struct diag_master_table entry;
 smd_channel_t *ch_temp = NULL, *chlpass_temp = NULL, *ch_wcnss_temp = NULL;
-int diag_event_num_bytes;
-int diag_event_config;
 struct diag_send_desc_type send = { NULL, NULL, DIAG_STATE_START, 0 };
 struct diag_hdlc_dest_type enc = { NULL, NULL, 0 };
-struct mask_info {
-	int equip_id;
-	int num_items;
-	int index;
-};
 
-#define CREATE_MSG_MASK_TBL_ROW(XX)					\
-do {									\
-	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX;			\
-	msg_mask_tbl_ptr += 4;						\
-	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST;		\
-	msg_mask_tbl_ptr += 4;						\
-	/* mimic the last entry as actual_last while creation */	\
-	*(int *)(msg_mask_tbl_ptr) = MSG_SSID_ ## XX ## _LAST;		\
-	msg_mask_tbl_ptr += 4;						\
-	/* increment by MAX_SSID_PER_RANGE cells */			\
-	msg_mask_tbl_ptr += MAX_SSID_PER_RANGE * sizeof(int);		\
-} while (0)
-
-#define ENCODE_RSP_AND_SEND(buf_length)				\
-do {									\
-	send.state = DIAG_STATE_START;					\
-	send.pkt = driver->apps_rsp_buf;				\
-	send.last = (void *)(driver->apps_rsp_buf + buf_length);	\
-	send.terminate = 1;						\
-	if (!driver->in_busy_1) {					\
-		enc.dest = driver->buf_in_1;				\
-		enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);\
-		diag_hdlc_encode(&send, &enc);				\
-		driver->write_ptr_1->buf = driver->buf_in_1;		\
-		driver->write_ptr_1->length = (int)(enc.dest - \
-						(void *)(driver->buf_in_1)); \
-		driver->in_busy_1 = 1;					\
-		diag_device_write(driver->buf_in_1, MODEM_DATA, \
-						 driver->write_ptr_1); \
-		memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE);	\
-	}								\
-} while (0)
-
-#define CHK_OVERFLOW(bufStart, start, end, length) \
-((bufStart <= start) && (end - start >= length)) ? 1 : 0
+void encode_rsp_and_send(int buf_length)
+{
+	send.state = DIAG_STATE_START;
+	send.pkt = driver->apps_rsp_buf;
+	send.last = (void *)(driver->apps_rsp_buf + buf_length);
+	send.terminate = 1;
+	if (!driver->in_busy_1) {
+		enc.dest = driver->buf_in_1;
+		enc.dest_last = (void *)(driver->buf_in_1 + APPS_BUF_SIZE - 1);
+		diag_hdlc_encode(&send, &enc);
+		driver->write_ptr_1->buf = driver->buf_in_1;
+		driver->write_ptr_1->length = (int)(enc.dest -
+						(void *)(driver->buf_in_1));
+		driver->in_busy_1 = 1;
+		diag_device_write(driver->buf_in_1, MODEM_DATA,
+					driver->write_ptr_1);
+		memset(driver->apps_rsp_buf, '\0', APPS_BUF_SIZE);
+	}
+}
 
 /* Determine if this device uses a device tree */
 #ifdef CONFIG_OF
@@ -136,6 +111,7 @@
 		case MSM_CPU_8960AB:
 			return AO8960_TOOLS_ID;
 		case MSM_CPU_8064:
+		case MSM_CPU_8064AB:
 			return APQ8064_TOOLS_ID;
 		case MSM_CPU_8930:
 		case MSM_CPU_8930AA:
@@ -163,6 +139,7 @@
 	case MSM_CPU_8960:
 	case MSM_CPU_8960AB:
 	case MSM_CPU_8064:
+	case MSM_CPU_8064AB:
 	case MSM_CPU_8930:
 	case MSM_CPU_8930AA:
 	case MSM_CPU_8627:
@@ -185,7 +162,7 @@
 		return 1;
 	else if (cpu_is_msm8960() || cpu_is_msm8930() || cpu_is_msm8930aa() ||
 		cpu_is_msm9615() || cpu_is_apq8064() || cpu_is_msm8627() ||
-		cpu_is_msm8960ab())
+		cpu_is_msm8960ab() || cpu_is_apq8064ab())
 		return 1;
 	else
 		return 0;
@@ -559,248 +536,6 @@
 	}
 }
 
-static void diag_print_mask_table(void)
-{
-/* Enable this to print mask table when updated */
-#ifdef MASK_DEBUG
-	int first, last, actual_last;
-	uint8_t *ptr = driver->msg_masks;
-	int i = 0;
-	pr_info("diag: F3 message mask table\n");
-	while (*(uint32_t *)(ptr + 4)) {
-		first = *(uint32_t *)ptr;
-		ptr += 4;
-		last = *(uint32_t *)ptr;
-		ptr += 4;
-		actual_last = *(uint32_t *)ptr;
-		ptr += 4;
-		pr_info("diag: SSID %d, %d - %d\n", first, last, actual_last);
-		for (i = 0 ; i <= actual_last - first ; i++)
-			pr_info("diag: MASK:%x\n", *((uint32_t *)ptr + i));
-		ptr += MAX_SSID_PER_RANGE*4;
-	}
-#endif
-}
-
-void diag_create_msg_mask_table(void)
-{
-	uint8_t *msg_mask_tbl_ptr = driver->msg_masks;
-
-	CREATE_MSG_MASK_TBL_ROW(0);
-	CREATE_MSG_MASK_TBL_ROW(1);
-	CREATE_MSG_MASK_TBL_ROW(2);
-	CREATE_MSG_MASK_TBL_ROW(3);
-	CREATE_MSG_MASK_TBL_ROW(4);
-	CREATE_MSG_MASK_TBL_ROW(5);
-	CREATE_MSG_MASK_TBL_ROW(6);
-	CREATE_MSG_MASK_TBL_ROW(7);
-	CREATE_MSG_MASK_TBL_ROW(8);
-	CREATE_MSG_MASK_TBL_ROW(9);
-	CREATE_MSG_MASK_TBL_ROW(10);
-	CREATE_MSG_MASK_TBL_ROW(11);
-	CREATE_MSG_MASK_TBL_ROW(12);
-	CREATE_MSG_MASK_TBL_ROW(13);
-	CREATE_MSG_MASK_TBL_ROW(14);
-	CREATE_MSG_MASK_TBL_ROW(15);
-	CREATE_MSG_MASK_TBL_ROW(16);
-	CREATE_MSG_MASK_TBL_ROW(17);
-	CREATE_MSG_MASK_TBL_ROW(18);
-	CREATE_MSG_MASK_TBL_ROW(19);
-	CREATE_MSG_MASK_TBL_ROW(20);
-	CREATE_MSG_MASK_TBL_ROW(21);
-	CREATE_MSG_MASK_TBL_ROW(22);
-	CREATE_MSG_MASK_TBL_ROW(23);
-}
-
-static void diag_set_msg_mask(int rt_mask)
-{
-	int first_ssid, last_ssid, i;
-	uint8_t *parse_ptr, *ptr = driver->msg_masks;
-
-	mutex_lock(&driver->diagchar_mutex);
-	while (*(uint32_t *)(ptr + 4)) {
-		first_ssid = *(uint32_t *)ptr;
-		ptr += 8; /* increment by 8 to skip 'last' */
-		last_ssid = *(uint32_t *)ptr;
-		ptr += 4;
-		parse_ptr = ptr;
-		pr_debug("diag: updating range %d %d\n", first_ssid, last_ssid);
-		for (i = 0; i < last_ssid - first_ssid + 1; i++) {
-			*(int *)parse_ptr = rt_mask;
-			parse_ptr += 4;
-		}
-		ptr += MAX_SSID_PER_RANGE * 4;
-	}
-	mutex_unlock(&driver->diagchar_mutex);
-}
-
-static void diag_update_msg_mask(int start, int end , uint8_t *buf)
-{
-	int found = 0, first, last, actual_last;
-	uint8_t *actual_last_ptr;
-	uint8_t *ptr = driver->msg_masks;
-	uint8_t *ptr_buffer_start = &(*(driver->msg_masks));
-	uint8_t *ptr_buffer_end = &(*(driver->msg_masks)) + MSG_MASK_SIZE;
-
-	mutex_lock(&driver->diagchar_mutex);
-
-	/* First SSID can be zero : So check that last is non-zero */
-	while (*(uint32_t *)(ptr + 4)) {
-		first = *(uint32_t *)ptr;
-		ptr += 4;
-		last = *(uint32_t *)ptr;
-		ptr += 4;
-		actual_last = *(uint32_t *)ptr;
-		actual_last_ptr = ptr;
-		ptr += 4;
-		if (start >= first && start <= actual_last) {
-			ptr += (start - first)*4;
-			if (end > actual_last) {
-				pr_info("diag: ssid range mismatch\n");
-				actual_last = end;
-				*(uint32_t *)(actual_last_ptr) = end;
-			}
-			if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
-					  (((end - start)+1)*4))) {
-				pr_debug("diag: update ssid start %d, end %d\n",
-								 start, end);
-				memcpy(ptr, buf , ((end - start)+1)*4);
-			} else
-				pr_alert("diag: Not enough space MSG_MASK\n");
-			found = 1;
-			break;
-		} else {
-			ptr += MAX_SSID_PER_RANGE*4;
-		}
-	}
-	/* Entry was not found - add new table */
-	if (!found) {
-		if (CHK_OVERFLOW(ptr_buffer_start, ptr, ptr_buffer_end,
-				  8 + ((end - start) + 1)*4)) {
-			memcpy(ptr, &(start) , 4);
-			ptr += 4;
-			memcpy(ptr, &(end), 4);
-			ptr += 4;
-			memcpy(ptr, &(end), 4); /* create actual_last entry */
-			ptr += 4;
-			pr_debug("diag: adding NEW ssid start %d, end %d\n",
-								 start, end);
-			memcpy(ptr, buf , ((end - start) + 1)*4);
-		} else
-			pr_alert("diag: Not enough buffer space for MSG_MASK\n");
-	}
-	mutex_unlock(&driver->diagchar_mutex);
-	diag_print_mask_table();
-}
-
-void diag_toggle_event_mask(int toggle)
-{
-	uint8_t *ptr = driver->event_masks;
-
-	mutex_lock(&driver->diagchar_mutex);
-	if (toggle)
-		memset(ptr, 0xFF, EVENT_MASK_SIZE);
-	else
-		memset(ptr, 0, EVENT_MASK_SIZE);
-	mutex_unlock(&driver->diagchar_mutex);
-}
-
-static void diag_update_event_mask(uint8_t *buf, int toggle, int num_bytes)
-{
-	uint8_t *ptr = driver->event_masks;
-	uint8_t *temp = buf + 2;
-
-	mutex_lock(&driver->diagchar_mutex);
-	if (!toggle)
-		memset(ptr, 0 , EVENT_MASK_SIZE);
-	else
-		if (CHK_OVERFLOW(ptr, ptr,
-				 ptr+EVENT_MASK_SIZE, num_bytes))
-			memcpy(ptr, temp , num_bytes);
-		else
-			printk(KERN_CRIT "Not enough buffer space "
-					 "for EVENT_MASK\n");
-	mutex_unlock(&driver->diagchar_mutex);
-}
-
-static void diag_disable_log_mask(void)
-{
-	int i = 0;
-	struct mask_info *parse_ptr = (struct mask_info *)(driver->log_masks);
-
-	pr_debug("diag: disable log masks\n");
-	mutex_lock(&driver->diagchar_mutex);
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		pr_debug("diag: equip id %d\n", parse_ptr->equip_id);
-		if (!(parse_ptr->equip_id)) /* Reached a null entry */
-			break;
-		memset(driver->log_masks + parse_ptr->index, 0,
-			    (parse_ptr->num_items + 7)/8);
-		parse_ptr++;
-	}
-	mutex_unlock(&driver->diagchar_mutex);
-}
-
-int chk_equip_id_and_mask(int equip_id, uint8_t *buf)
-{
-	int i = 0, flag = 0, num_items, offset;
-	unsigned char *ptr_data;
-	struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
-
-	pr_debug("diag: received equip id = %d\n", equip_id);
-	/* Check if this is valid equipment ID */
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
-			offset = ptr->index;
-			num_items = ptr->num_items;
-			flag = 1;
-			break;
-		}
-		ptr++;
-	}
-	if (!flag)
-		return -EPERM;
-	ptr_data = driver->log_masks + offset;
-	memcpy(buf, ptr_data, (num_items+7)/8);
-	return 0;
-}
-
-static void diag_update_log_mask(int equip_id, uint8_t *buf, int num_items)
-{
-	uint8_t *temp = buf;
-	int i = 0;
-	unsigned char *ptr_data;
-	int offset = (sizeof(struct mask_info))*MAX_EQUIP_ID;
-	struct mask_info *ptr = (struct mask_info *)(driver->log_masks);
-
-	pr_debug("diag: received equip id = %d\n", equip_id);
-	mutex_lock(&driver->diagchar_mutex);
-	/* Check if we already know index of this equipment ID */
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		if ((ptr->equip_id == equip_id) && (ptr->index != 0)) {
-			offset = ptr->index;
-			break;
-		}
-		if ((ptr->equip_id == 0) && (ptr->index == 0)) {
-			/* Reached a null entry */
-			ptr->equip_id = equip_id;
-			ptr->num_items = num_items;
-			ptr->index = driver->log_masks_length;
-			offset = driver->log_masks_length;
-			driver->log_masks_length += ((num_items+7)/8);
-			break;
-		}
-		ptr++;
-	}
-	ptr_data = driver->log_masks + offset;
-	if (CHK_OVERFLOW(driver->log_masks, ptr_data, driver->log_masks
-					 + LOG_MASK_SIZE, (num_items+7)/8))
-		memcpy(ptr_data, temp , (num_items+7)/8);
-	else
-		pr_err("diag: Not enough buffer space for LOG_MASK\n");
-	mutex_unlock(&driver->diagchar_mutex);
-}
-
 static void diag_update_pkt_buffer(unsigned char *buf)
 {
 	unsigned char *ptr = driver->pkt_buf;
@@ -869,415 +604,21 @@
 	}
 }
 
-void diag_modem_mask_update_fn(struct work_struct *work)
-{
-	diag_send_msg_mask_update(driver->ch_cntl, ALL_SSID,
-					   ALL_SSID, MODEM_PROC);
-	diag_send_log_mask_update(driver->ch_cntl, ALL_EQUIP_ID);
-	diag_send_event_mask_update(driver->ch_cntl, diag_event_num_bytes);
-}
-
-void diag_lpass_mask_update_fn(struct work_struct *work)
-{
-	diag_send_msg_mask_update(driver->chlpass_cntl, ALL_SSID,
-						   ALL_SSID, LPASS_PROC);
-	diag_send_log_mask_update(driver->chlpass_cntl, ALL_EQUIP_ID);
-	diag_send_event_mask_update(driver->chlpass_cntl, diag_event_num_bytes);
-}
-
-void diag_wcnss_mask_update_fn(struct work_struct *work)
-{
-	diag_send_msg_mask_update(driver->ch_wcnss_cntl, ALL_SSID,
-						   ALL_SSID, WCNSS_PROC);
-	diag_send_log_mask_update(driver->ch_wcnss_cntl, ALL_EQUIP_ID);
-	diag_send_event_mask_update(driver->ch_wcnss_cntl,
-						 diag_event_num_bytes);
-}
-
-void diag_send_log_mask_update(smd_channel_t *ch, int equip_id)
-{
-	void *buf = driver->buf_log_mask_update;
-	int header_size = sizeof(struct diag_ctrl_log_mask);
-	struct mask_info *ptr = (struct mask_info *)driver->log_masks;
-	int i, size, wr_size = -ENOMEM, retry_count = 0, timer;
-
-	mutex_lock(&driver->diag_cntl_mutex);
-	for (i = 0; i < MAX_EQUIP_ID; i++) {
-		size = (ptr->num_items+7)/8;
-		/* reached null entry */
-		if ((ptr->equip_id == 0) && (ptr->index == 0))
-			break;
-		driver->log_mask->cmd_type = DIAG_CTRL_MSG_LOG_MASK;
-		driver->log_mask->num_items = ptr->num_items;
-		driver->log_mask->data_len  = 11 + size;
-		driver->log_mask->stream_id = 1; /* 2, if dual stream */
-		driver->log_mask->status = 3; /* status for valid mask */
-		driver->log_mask->equip_id = ptr->equip_id;
-		driver->log_mask->log_mask_size = size;
-		/* send only desired update, NOT ALL */
-		if (equip_id == ALL_EQUIP_ID || equip_id ==
-					 driver->log_mask->equip_id) {
-			memcpy(buf, driver->log_mask, header_size);
-			memcpy(buf+header_size, driver->log_masks+ptr->index,
-									 size);
-			if (ch) {
-				while (retry_count < 3) {
-					wr_size = smd_write(ch, buf,
-							 header_size + size);
-					if (wr_size == -ENOMEM) {
-						retry_count++;
-						for (timer = 0; timer < 5;
-								 timer++)
-							udelay(2000);
-					} else
-						break;
-				}
-				if (wr_size != header_size + size)
-					pr_err("diag: log mask update failed"
-				 " %d, tried %d", wr_size, header_size + size);
-				else
-					pr_debug("diag: updated log equip ID %d"
-					",len %d\n", driver->log_mask->equip_id,
-					 driver->log_mask->log_mask_size);
-			} else
-				pr_err("diag: ch not valid for log update\n");
-		}
-		ptr++;
-	}
-	mutex_unlock(&driver->diag_cntl_mutex);
-}
-
-void diag_send_event_mask_update(smd_channel_t *ch, int num_bytes)
-{
-	void *buf = driver->buf_event_mask_update;
-	int header_size = sizeof(struct diag_ctrl_event_mask);
-	int wr_size = -ENOMEM, retry_count = 0, timer;
-
-	mutex_lock(&driver->diag_cntl_mutex);
-	if (num_bytes == 0) {
-		pr_debug("diag: event mask not set yet, so no update\n");
-		mutex_unlock(&driver->diag_cntl_mutex);
-		return;
-	}
-	/* send event mask update */
-	driver->event_mask->cmd_type = DIAG_CTRL_MSG_EVENT_MASK;
-	driver->event_mask->data_len = 7 + num_bytes;
-	driver->event_mask->stream_id = 1; /* 2, if dual stream */
-	driver->event_mask->status = 3; /* status for valid mask */
-	driver->event_mask->event_config = diag_event_config; /* event config */
-	driver->event_mask->event_mask_size = num_bytes;
-	memcpy(buf, driver->event_mask, header_size);
-	memcpy(buf+header_size, driver->event_masks, num_bytes);
-	if (ch) {
-		while (retry_count < 3) {
-			wr_size = smd_write(ch, buf, header_size + num_bytes);
-			if (wr_size == -ENOMEM) {
-				retry_count++;
-				for (timer = 0; timer < 5; timer++)
-					udelay(2000);
-			} else
-				break;
-		}
-		if (wr_size != header_size + num_bytes)
-			pr_err("diag: error writing event mask %d, tried %d\n",
-					 wr_size, header_size + num_bytes);
-	} else
-		pr_err("diag: ch not valid for event update\n");
-	mutex_unlock(&driver->diag_cntl_mutex);
-}
-
-void diag_send_msg_mask_update(smd_channel_t *ch, int updated_ssid_first,
-						int updated_ssid_last, int proc)
-{
-	void *buf = driver->buf_msg_mask_update;
-	int first, last, actual_last, size = -ENOMEM, retry_count = 0, timer;
-	int header_size = sizeof(struct diag_ctrl_msg_mask);
-	uint8_t *ptr = driver->msg_masks;
-
-	mutex_lock(&driver->diag_cntl_mutex);
-	while (*(uint32_t *)(ptr + 4)) {
-		first = *(uint32_t *)ptr;
-		ptr += 4;
-		last = *(uint32_t *)ptr;
-		ptr += 4;
-		actual_last = *(uint32_t *)ptr;
-		ptr += 4;
-		if ((updated_ssid_first >= first && updated_ssid_last <=
-			 actual_last) || (updated_ssid_first == ALL_SSID)) {
-			/* send f3 mask update */
-			driver->msg_mask->cmd_type = DIAG_CTRL_MSG_F3_MASK;
-			driver->msg_mask->msg_mask_size = actual_last -
-								 first + 1;
-			driver->msg_mask->data_len = 11 +
-					 4 * (driver->msg_mask->msg_mask_size);
-			driver->msg_mask->stream_id = 1; /* 2, if dual stream */
-			driver->msg_mask->status = 3; /* status valid mask */
-			driver->msg_mask->msg_mode = 0; /* Legcay mode */
-			driver->msg_mask->ssid_first = first;
-			driver->msg_mask->ssid_last = actual_last;
-			memcpy(buf, driver->msg_mask, header_size);
-			memcpy(buf+header_size, ptr,
-				 4 * (driver->msg_mask->msg_mask_size));
-			if (ch) {
-				while (retry_count < 3) {
-					size = smd_write(ch, buf, header_size +
-					 4*(driver->msg_mask->msg_mask_size));
-					if (size == -ENOMEM) {
-						retry_count++;
-						for (timer = 0; timer < 5;
-								 timer++)
-							udelay(2000);
-					} else
-						break;
-				}
-				if (size != header_size +
-					 4*(driver->msg_mask->msg_mask_size))
-					pr_err("diag: proc %d, msg mask update "
-	 "fail %d, tried %d\n", proc, size,
-	 header_size + 4*(driver->msg_mask->msg_mask_size));
-				else
-					pr_debug("diag: sending mask update for ssid first %d, last %d on PROC %d\n",
-						first, actual_last, proc);
-			} else
-				pr_err("diag: proc %d, ch invalid msg mask"
-						 "update\n", proc);
-		}
-		ptr += MAX_SSID_PER_RANGE*4;
-	}
-	mutex_unlock(&driver->diag_cntl_mutex);
-}
-
 static int diag_process_apps_pkt(unsigned char *buf, int len)
 {
 	uint16_t subsys_cmd_code;
 	int subsys_id, ssid_first, ssid_last, ssid_range;
 	int packet_type = 1, i, cmd_code;
-	int rt_mask, rt_first_ssid, rt_last_ssid, rt_mask_size;
 	unsigned char *temp = buf;
-	uint8_t *rt_mask_ptr;
-	int data_type, equip_id, num_items;
+	int data_type;
 #if defined(CONFIG_DIAG_OVER_USB)
-	int payload_length;
 	unsigned char *ptr;
 #endif
 
-	/* Set log masks */
-	if (*buf == 0x73 && *(int *)(buf+4) == 3) {
-		buf += 8;
-		/* Read Equip ID and pass as first param below*/
-		diag_update_log_mask(*(int *)buf, buf+8, *(int *)(buf+4));
-		diag_update_userspace_clients(LOG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (chk_apps_only()) {
-			driver->apps_rsp_buf[0] = 0x73;
-			*(int *)(driver->apps_rsp_buf + 4) = 0x3; /* op. ID */
-			*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* success */
-			payload_length = 8 + ((*(int *)(buf + 4)) + 7)/8;
-			for (i = 0; i < payload_length; i++)
-				*(int *)(driver->apps_rsp_buf+12+i) = *(buf+i);
-			if (driver->ch_cntl)
-				diag_send_log_mask_update(driver->ch_cntl,
-								 *(int *)buf);
-			if (driver->chlpass_cntl)
-				diag_send_log_mask_update(driver->chlpass_cntl,
-								 *(int *)buf);
-			if (driver->ch_wcnss_cntl)
-				diag_send_log_mask_update(driver->ch_wcnss_cntl,
-								 *(int *)buf);
-			ENCODE_RSP_AND_SEND(12 + payload_length - 1);
-			return 0;
-		} else
-			buf = temp;
-#endif
-	} /* Get log masks */
-	else if (*buf == 0x73 && *(int *)(buf+4) == 4) {
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (!(driver->ch) && chk_apps_only()) {
-			equip_id = *(int *)(buf + 8);
-			num_items = *(int *)(buf + 12);
-			driver->apps_rsp_buf[0] = 0x73;
-			driver->apps_rsp_buf[1] = 0x0;
-			driver->apps_rsp_buf[2] = 0x0;
-			driver->apps_rsp_buf[3] = 0x0;
-			*(int *)(driver->apps_rsp_buf + 4) = 0x4;
-			if (!chk_equip_id_and_mask(equip_id,
-						 driver->apps_rsp_buf+20))
-				*(int *)(driver->apps_rsp_buf + 8) = 0x0;
-			else
-				*(int *)(driver->apps_rsp_buf + 8) = 0x1;
-			*(int *)(driver->apps_rsp_buf + 12) = equip_id;
-			*(int *)(driver->apps_rsp_buf + 16) = num_items;
-			ENCODE_RSP_AND_SEND(20+(num_items+7)/8-1);
-			return 0;
-		} else
-			buf = temp;
-#endif
-	} /* Disable log masks */
-	else if (*buf == 0x73 && *(int *)(buf+4) == 0) {
-		/* Disable mask for each log code */
-		diag_disable_log_mask();
-		diag_update_userspace_clients(LOG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (chk_apps_only()) {
-			driver->apps_rsp_buf[0] = 0x73;
-			driver->apps_rsp_buf[1] = 0x0;
-			driver->apps_rsp_buf[2] = 0x0;
-			driver->apps_rsp_buf[3] = 0x0;
-			*(int *)(driver->apps_rsp_buf + 4) = 0x0;
-			*(int *)(driver->apps_rsp_buf + 8) = 0x0; /* status */
-			if (driver->ch_cntl)
-				diag_send_log_mask_update(driver->ch_cntl,
-								 ALL_EQUIP_ID);
-			if (driver->chlpass_cntl)
-				diag_send_log_mask_update(driver->chlpass_cntl,
-								 ALL_EQUIP_ID);
-			if (driver->ch_wcnss_cntl)
-				diag_send_log_mask_update(driver->ch_wcnss_cntl,
-								 ALL_EQUIP_ID);
-			ENCODE_RSP_AND_SEND(11);
-			return 0;
-		}
-#endif
-	} /* Get runtime message mask  */
-	else if ((*buf == 0x7d) && (*(buf+1) == 0x3)) {
-		ssid_first = *(uint16_t *)(buf + 2);
-		ssid_last = *(uint16_t *)(buf + 4);
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (!(driver->ch) && chk_apps_only()) {
-			driver->apps_rsp_buf[0] = 0x7d;
-			driver->apps_rsp_buf[1] = 0x3;
-			*(uint16_t *)(driver->apps_rsp_buf+2) = ssid_first;
-			*(uint16_t *)(driver->apps_rsp_buf+4) = ssid_last;
-			driver->apps_rsp_buf[6] = 0x1; /* Success Status */
-			driver->apps_rsp_buf[7] = 0x0;
-			rt_mask_ptr = driver->msg_masks;
-			while (*(uint32_t *)(rt_mask_ptr + 4)) {
-				rt_first_ssid = *(uint32_t *)rt_mask_ptr;
-				rt_mask_ptr += 8; /* +8 to skip 'last' */
-				rt_last_ssid = *(uint32_t *)rt_mask_ptr;
-				rt_mask_ptr += 4;
-				if (ssid_first == rt_first_ssid && ssid_last ==
-								 rt_last_ssid) {
-					rt_mask_size = 4 * (rt_last_ssid -
-							 rt_first_ssid + 1);
-					memcpy(driver->apps_rsp_buf+8,
-						 rt_mask_ptr, rt_mask_size);
-					ENCODE_RSP_AND_SEND(8+rt_mask_size-1);
-					return 0;
-				}
-				rt_mask_ptr += MAX_SSID_PER_RANGE*4;
-			}
-		} else
-			buf = temp;
-#endif
-	} /* Set runtime message mask  */
-	else if ((*buf == 0x7d) && (*(buf+1) == 0x4)) {
-		ssid_first = *(uint16_t *)(buf + 2);
-		ssid_last = *(uint16_t *)(buf + 4);
-		ssid_range = 4 * (ssid_last - ssid_first + 1);
-		pr_debug("diag: received mask update for ssid_first = %d,"
-				" ssid_last = %d", ssid_first, ssid_last);
-		diag_update_msg_mask(ssid_first, ssid_last , buf + 8);
-		diag_update_userspace_clients(MSG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (chk_apps_only()) {
-			for (i = 0; i < 8 + ssid_range; i++)
-				*(driver->apps_rsp_buf + i) = *(buf+i);
-			*(driver->apps_rsp_buf + 6) = 0x1;
-			if (driver->ch_cntl)
-				diag_send_msg_mask_update(driver->ch_cntl,
-					 ssid_first, ssid_last, MODEM_PROC);
-			if (driver->chlpass_cntl)
-				diag_send_msg_mask_update(driver->chlpass_cntl,
-					 ssid_first, ssid_last, LPASS_PROC);
-			if (driver->ch_wcnss_cntl)
-				diag_send_msg_mask_update(driver->ch_wcnss_cntl,
-					 ssid_first, ssid_last, WCNSS_PROC);
-			ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
-			return 0;
-		} else
-			buf = temp;
-#endif
-	} /* Set ALL runtime message mask  */
-	else if ((*buf == 0x7d) && (*(buf+1) == 0x5)) {
-		rt_mask = *(int *)(buf + 4);
-		diag_set_msg_mask(rt_mask);
-		diag_update_userspace_clients(MSG_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (chk_apps_only()) {
-			driver->apps_rsp_buf[0] = 0x7d; /* cmd_code */
-			driver->apps_rsp_buf[1] = 0x5; /* set subcommand */
-			driver->apps_rsp_buf[2] = 1; /* success */
-			driver->apps_rsp_buf[3] = 0; /* rsvd */
-			*(int *)(driver->apps_rsp_buf + 4) = rt_mask;
-			/* send msg mask update to peripheral */
-			if (driver->ch_cntl)
-				diag_send_msg_mask_update(driver->ch_cntl,
-					 ALL_SSID, ALL_SSID, MODEM_PROC);
-			if (driver->chlpass_cntl)
-				diag_send_msg_mask_update(driver->chlpass_cntl,
-					 ALL_SSID, ALL_SSID, LPASS_PROC);
-			if (driver->ch_wcnss_cntl)
-				diag_send_msg_mask_update(driver->ch_wcnss_cntl,
-					 ALL_SSID, ALL_SSID, WCNSS_PROC);
-			ENCODE_RSP_AND_SEND(7);
-			return 0;
-		} else
-			buf = temp;
-#endif
-	} else if (*buf == 0x82) {	/* event mask change */
-		buf += 4;
-		diag_event_num_bytes =  (*(uint16_t *)buf)/8+1;
-		diag_update_event_mask(buf, 1, (*(uint16_t *)buf)/8+1);
-		diag_update_userspace_clients(EVENT_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (chk_apps_only()) {
-			driver->apps_rsp_buf[0] = 0x82;
-			driver->apps_rsp_buf[1] = 0x0;
-			*(uint16_t *)(driver->apps_rsp_buf + 2) = 0x0;
-			*(uint16_t *)(driver->apps_rsp_buf + 4) =
-							EVENT_LAST_ID + 1;
-			memcpy(driver->apps_rsp_buf+6, driver->event_masks,
-							 EVENT_LAST_ID/8+1);
-			if (driver->ch_cntl)
-				diag_send_event_mask_update(driver->ch_cntl,
-							 diag_event_num_bytes);
-			if (driver->chlpass_cntl)
-				diag_send_event_mask_update(
-						driver->chlpass_cntl,
-						diag_event_num_bytes);
-			if (driver->ch_wcnss_cntl)
-				diag_send_event_mask_update(
-				driver->ch_wcnss_cntl, diag_event_num_bytes);
-			ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
-			return 0;
-		} else
-			buf = temp;
-#endif
-	} else if (*buf == 0x60) {
-		diag_event_config = *(buf+1);
-		diag_toggle_event_mask(*(buf+1));
-		diag_update_userspace_clients(EVENT_MASKS_TYPE);
-#if defined(CONFIG_DIAG_OVER_USB)
-		if (chk_apps_only()) {
-			driver->apps_rsp_buf[0] = 0x60;
-			driver->apps_rsp_buf[1] = 0x0;
-			driver->apps_rsp_buf[2] = 0x0;
-			if (driver->ch_cntl)
-				diag_send_event_mask_update(driver->ch_cntl,
-							 diag_event_num_bytes);
-			if (driver->chlpass_cntl)
-				diag_send_event_mask_update(
-						driver->chlpass_cntl,
-						diag_event_num_bytes);
-			if (driver->ch_wcnss_cntl)
-				diag_send_event_mask_update(
-				driver->ch_wcnss_cntl, diag_event_num_bytes);
-			ENCODE_RSP_AND_SEND(2);
-			return 0;
-		}
-#endif
-	}
+	/* Check if the command is a supported mask command */
+	if (diag_process_apps_masks(buf, len) == 0)
+		return 0;
+
 	/* Check for registered clients and forward packet to apropriate proc */
 	cmd_code = (int)(*(char *)buf);
 	temp++;
@@ -1334,7 +675,7 @@
 		for (i = 0; i < 4; i++)
 			*(driver->apps_rsp_buf+i) = *(buf+i);
 		*(uint32_t *)(driver->apps_rsp_buf+4) = PKT_SIZE;
-		ENCODE_RSP_AND_SEND(7);
+		encode_rsp_and_send(7);
 		return 0;
 	}
 	/* Check for Apps Only & get event mask request */
@@ -1345,7 +686,7 @@
 		*(uint16_t *)(driver->apps_rsp_buf + 4) = EVENT_LAST_ID + 1;
 		for (i = 0; i < EVENT_LAST_ID/8 + 1; i++)
 			*(unsigned char *)(driver->apps_rsp_buf + 6 + i) = 0x0;
-		ENCODE_RSP_AND_SEND(6 + EVENT_LAST_ID/8);
+		encode_rsp_and_send(6 + EVENT_LAST_ID/8);
 		return 0;
 	}
 	/* Get log ID range & Check for Apps Only */
@@ -1370,7 +711,7 @@
 		*(int *)(driver->apps_rsp_buf + 64) = LOG_GET_ITEM_NUM(LOG_13);
 		*(int *)(driver->apps_rsp_buf + 68) = LOG_GET_ITEM_NUM(LOG_14);
 		*(int *)(driver->apps_rsp_buf + 72) = LOG_GET_ITEM_NUM(LOG_15);
-		ENCODE_RSP_AND_SEND(75);
+		encode_rsp_and_send(75);
 		return 0;
 	}
 	/* Respond to Get SSID Range request message */
@@ -1428,7 +769,7 @@
 		*(uint16_t *)(driver->apps_rsp_buf + 94) = MSG_SSID_21_LAST;
 		*(uint16_t *)(driver->apps_rsp_buf + 96) = MSG_SSID_22;
 		*(uint16_t *)(driver->apps_rsp_buf + 98) = MSG_SSID_22_LAST;
-		ENCODE_RSP_AND_SEND(99);
+		encode_rsp_and_send(99);
 		return 0;
 	}
 	/* Check for Apps Only Respond to Get Subsys Build mask */
@@ -1540,14 +881,14 @@
 				*(int *)(ptr + i) = msg_bld_masks_22[i/4];
 			break;
 		}
-		ENCODE_RSP_AND_SEND(8 + ssid_range - 1);
+		encode_rsp_and_send(8 + ssid_range - 1);
 		return 0;
 	}
 	/* Check for download command */
 	else if ((cpu_is_msm8x60() || chk_apps_master()) && (*buf == 0x3A)) {
 		/* send response back */
 		driver->apps_rsp_buf[0] = *buf;
-		ENCODE_RSP_AND_SEND(0);
+		encode_rsp_and_send(0);
 		msleep(5000);
 		/* call download API */
 		msm_set_restart_mode(RESTART_DLOAD);
@@ -1567,7 +908,7 @@
 			for (i = 0; i < 13; i++)
 				driver->apps_rsp_buf[i+3] = 0;
 
-			ENCODE_RSP_AND_SEND(15);
+			encode_rsp_and_send(15);
 			return 0;
 		}
 	}
@@ -1578,7 +919,7 @@
 			for (i = 0; i < 55; i++)
 				driver->apps_rsp_buf[i] = 0;
 
-			ENCODE_RSP_AND_SEND(54);
+			encode_rsp_and_send(54);
 			return 0;
 		}
 		/* respond to 0x7c command */
@@ -1591,12 +932,12 @@
 							 chk_config_get_id();
 			*(unsigned char *)(driver->apps_rsp_buf + 12) = '\0';
 			*(unsigned char *)(driver->apps_rsp_buf + 13) = '\0';
-			ENCODE_RSP_AND_SEND(13);
+			encode_rsp_and_send(13);
 			return 0;
 		}
 	}
 #endif
-		return packet_type;
+	return packet_type;
 }
 
 #ifdef CONFIG_DIAG_OVER_USB
@@ -1611,7 +952,7 @@
 	driver->apps_rsp_buf[0] = 0x13; /* error code 13 */
 	for (i = 0; i < index; i++)
 		driver->apps_rsp_buf[i+1] = *(driver->hdlc_buf+i);
-	ENCODE_RSP_AND_SEND(index - 3);
+	encode_rsp_and_send(index - 3);
 }
 #else
 static inline void diag_send_error_rsp(int index) {}
@@ -1994,27 +1335,6 @@
 	driver->use_device_tree = has_device_tree();
 	mutex_init(&driver->diag_cntl_mutex);
 
-	if (driver->event_mask == NULL) {
-		driver->event_mask = kzalloc(sizeof(
-			struct diag_ctrl_event_mask), GFP_KERNEL);
-		if (driver->event_mask == NULL)
-			goto err;
-		kmemleak_not_leak(driver->event_mask);
-	}
-	if (driver->msg_mask == NULL) {
-		driver->msg_mask = kzalloc(sizeof(
-			struct diag_ctrl_msg_mask), GFP_KERNEL);
-		if (driver->msg_mask == NULL)
-			goto err;
-		kmemleak_not_leak(driver->msg_mask);
-	}
-	if (driver->log_mask == NULL) {
-		driver->log_mask = kzalloc(sizeof(
-			struct diag_ctrl_log_mask), GFP_KERNEL);
-		if (driver->log_mask == NULL)
-			goto err;
-		kmemleak_not_leak(driver->log_mask);
-	}
 	if (driver->buf_in_1 == NULL) {
 		driver->buf_in_1 = kzalloc(IN_BUF_SIZE, GFP_KERNEL);
 		if (driver->buf_in_1 == NULL)
@@ -2051,28 +1371,6 @@
 			goto err;
 		kmemleak_not_leak(driver->buf_in_wcnss_2);
 	}
-
-	if (driver->buf_msg_mask_update == NULL) {
-		driver->buf_msg_mask_update = kzalloc(APPS_BUF_SIZE,
-								 GFP_KERNEL);
-		if (driver->buf_msg_mask_update == NULL)
-			goto err;
-		kmemleak_not_leak(driver->buf_msg_mask_update);
-	}
-	if (driver->buf_log_mask_update == NULL) {
-		driver->buf_log_mask_update = kzalloc(APPS_BUF_SIZE,
-								 GFP_KERNEL);
-		if (driver->buf_log_mask_update == NULL)
-			goto err;
-		kmemleak_not_leak(driver->buf_log_mask_update);
-	}
-	if (driver->buf_event_mask_update == NULL) {
-		driver->buf_event_mask_update = kzalloc(APPS_BUF_SIZE,
-								 GFP_KERNEL);
-		if (driver->buf_event_mask_update == NULL)
-			goto err;
-		kmemleak_not_leak(driver->buf_event_mask_update);
-	}
 	if (driver->usb_buf_out  == NULL &&
 	     (driver->usb_buf_out = kzalloc(USB_MAX_OUT_BUF,
 					 GFP_KERNEL)) == NULL)
@@ -2087,23 +1385,6 @@
 		if (driver->user_space_data == NULL)
 			goto err;
 	kmemleak_not_leak(driver->user_space_data);
-	if (driver->msg_masks == NULL
-	    && (driver->msg_masks = kzalloc(MSG_MASK_SIZE,
-					     GFP_KERNEL)) == NULL)
-		goto err;
-	kmemleak_not_leak(driver->msg_masks);
-	diag_create_msg_mask_table();
-	diag_event_num_bytes = 0;
-	if (driver->log_masks == NULL &&
-	    (driver->log_masks = kzalloc(LOG_MASK_SIZE, GFP_KERNEL)) == NULL)
-		goto err;
-	kmemleak_not_leak(driver->log_masks);
-	driver->log_masks_length = (sizeof(struct mask_info))*MAX_EQUIP_ID;
-	if (driver->event_masks == NULL &&
-	    (driver->event_masks = kzalloc(EVENT_MASK_SIZE,
-					    GFP_KERNEL)) == NULL)
-		goto err;
-	kmemleak_not_leak(driver->event_masks);
 	if (driver->client_map == NULL &&
 	    (driver->client_map = kzalloc
 	     ((driver->num_clients) * sizeof(struct diag_client_map),
@@ -2192,12 +1473,6 @@
 #ifdef CONFIG_DIAG_OVER_USB
 	INIT_WORK(&(driver->diag_proc_hdlc_work), diag_process_hdlc_fn);
 	INIT_WORK(&(driver->diag_read_work), diag_read_work_fn);
-	INIT_WORK(&(driver->diag_modem_mask_update_work),
-						 diag_modem_mask_update_fn);
-	INIT_WORK(&(driver->diag_lpass_mask_update_work),
-						 diag_lpass_mask_update_fn);
-	INIT_WORK(&(driver->diag_wcnss_mask_update_work),
-						 diag_wcnss_mask_update_fn);
 	driver->legacy_ch = usb_diag_open(DIAG_LEGACY, driver,
 			diag_usb_legacy_notifier);
 	if (IS_ERR(driver->legacy_ch)) {
@@ -2210,40 +1485,34 @@
 
 	return;
 err:
-		pr_err("diag: Could not initialize diag buffers");
-		kfree(driver->event_mask);
-		kfree(driver->log_mask);
-		kfree(driver->msg_mask);
-		kfree(driver->buf_in_1);
-		kfree(driver->buf_in_2);
-		kfree(driver->buf_in_lpass_1);
-		kfree(driver->buf_in_lpass_2);
-		kfree(driver->buf_in_wcnss_1);
-		kfree(driver->buf_in_wcnss_2);
-		kfree(driver->buf_msg_mask_update);
-		kfree(driver->buf_log_mask_update);
-		kfree(driver->buf_event_mask_update);
-		kfree(driver->usb_buf_out);
-		kfree(driver->hdlc_buf);
-		kfree(driver->msg_masks);
-		kfree(driver->log_masks);
-		kfree(driver->event_masks);
-		kfree(driver->client_map);
-		kfree(driver->buf_tbl);
-		kfree(driver->data_ready);
-		kfree(driver->table);
-		kfree(driver->pkt_buf);
-		kfree(driver->write_ptr_1);
-		kfree(driver->write_ptr_2);
-		kfree(driver->write_ptr_lpass_1);
-		kfree(driver->write_ptr_lpass_2);
-		kfree(driver->write_ptr_wcnss_1);
-		kfree(driver->write_ptr_wcnss_2);
-		kfree(driver->usb_read_ptr);
-		kfree(driver->apps_rsp_buf);
-		kfree(driver->user_space_data);
-		if (driver->diag_wq)
-			destroy_workqueue(driver->diag_wq);
+	pr_err("diag: Could not initialize diag buffers");
+	kfree(driver->buf_in_1);
+	kfree(driver->buf_in_2);
+	kfree(driver->buf_in_lpass_1);
+	kfree(driver->buf_in_lpass_2);
+	kfree(driver->buf_in_wcnss_1);
+	kfree(driver->buf_in_wcnss_2);
+	kfree(driver->buf_msg_mask_update);
+	kfree(driver->buf_log_mask_update);
+	kfree(driver->buf_event_mask_update);
+	kfree(driver->usb_buf_out);
+	kfree(driver->hdlc_buf);
+	kfree(driver->client_map);
+	kfree(driver->buf_tbl);
+	kfree(driver->data_ready);
+	kfree(driver->table);
+	kfree(driver->pkt_buf);
+	kfree(driver->write_ptr_1);
+	kfree(driver->write_ptr_2);
+	kfree(driver->write_ptr_lpass_1);
+	kfree(driver->write_ptr_lpass_2);
+	kfree(driver->write_ptr_wcnss_1);
+	kfree(driver->write_ptr_wcnss_2);
+	kfree(driver->usb_read_ptr);
+	kfree(driver->apps_rsp_buf);
+	kfree(driver->user_space_data);
+	if (driver->diag_wq)
+		destroy_workqueue(driver->diag_wq);
 }
 
 void diagfwd_exit(void)
@@ -2262,9 +1531,6 @@
 	platform_driver_unregister(&msm_smd_ch1_driver);
 	platform_driver_unregister(&msm_diag_dci_driver);
 	platform_driver_unregister(&diag_smd_lite_driver);
-	kfree(driver->event_mask);
-	kfree(driver->log_mask);
-	kfree(driver->msg_mask);
 	kfree(driver->buf_in_1);
 	kfree(driver->buf_in_2);
 	kfree(driver->buf_in_lpass_1);
@@ -2276,9 +1542,6 @@
 	kfree(driver->buf_event_mask_update);
 	kfree(driver->usb_buf_out);
 	kfree(driver->hdlc_buf);
-	kfree(driver->msg_masks);
-	kfree(driver->log_masks);
-	kfree(driver->event_masks);
 	kfree(driver->client_map);
 	kfree(driver->buf_tbl);
 	kfree(driver->data_ready);
diff --git a/drivers/char/diag/diagfwd.h b/drivers/char/diag/diagfwd.h
index cf7fda6..a0631d6 100644
--- a/drivers/char/diag/diagfwd.h
+++ b/drivers/char/diag/diagfwd.h
@@ -16,6 +16,9 @@
 #define NO_PROCESS	0
 #define NON_APPS_PROC	-1
 
+#define CHK_OVERFLOW(bufStart, start, end, length) \
+	((((bufStart) <= (start)) && ((end) - (start) >= (length))) ? 1 : 0)
+
 void diagfwd_init(void);
 void diagfwd_exit(void);
 void diag_process_hdlc(void *data, unsigned len);
@@ -31,11 +34,9 @@
 int chk_apps_only(void);
 int chk_apps_master(void);
 int chk_polling_response(void);
-void diag_send_event_mask_update(smd_channel_t *, int num_bytes);
-void diag_send_msg_mask_update(smd_channel_t *, int ssid_first,
-					 int ssid_last, int proc);
-void diag_send_log_mask_update(smd_channel_t *, int);
+void diag_update_userspace_clients(unsigned int type);
 void diag_update_sleeping_process(int process_id, int data_type);
+void encode_rsp_and_send(int buf_length);
 /* State for diag forwarding */
 #ifdef CONFIG_DIAG_OVER_USB
 int diagfwd_connect(void);
@@ -43,6 +44,5 @@
 #endif
 extern int diag_debug_buf_idx;
 extern unsigned char diag_debug_buf[1024];
-extern int diag_event_num_bytes;
 extern struct platform_driver msm_diag_dci_driver;
 #endif
diff --git a/drivers/char/diag/diagfwd_cntl.c b/drivers/char/diag/diagfwd_cntl.c
index 3bbd3fb..4848a1d 100644
--- a/drivers/char/diag/diagfwd_cntl.c
+++ b/drivers/char/diag/diagfwd_cntl.c
@@ -17,9 +17,6 @@
 #include "diagchar.h"
 #include "diagfwd.h"
 #include "diagfwd_cntl.h"
-#ifdef CONFIG_DEBUG_FS
-#include <linux/debugfs.h>
-#endif
 /* tracks which peripheral is undergoing SSR */
 static uint16_t reg_dirty;
 #define HDR_SIZ 8
@@ -365,291 +362,3 @@
 	kfree(driver->buf_in_lpass_cntl);
 	kfree(driver->buf_in_wcnss_cntl);
 }
-
-#ifdef CONFIG_DEBUG_FS
-#define DEBUG_BUF_SIZE	4096
-static struct dentry *diag_dbgfs_dent;
-static int diag_dbgfs_table_index;
-
-static ssize_t diag_dbgfs_read_status(struct file *file, char __user *ubuf,
-				      size_t count, loff_t *ppos)
-{
-	char *buf;
-	int ret;
-
-	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
-	if (!buf) {
-		pr_err("diag: %s, Error allocating memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
-		"modem ch: 0x%x\n"
-		"lpass ch: 0x%x\n"
-		"riva ch: 0x%x\n"
-		"dci ch: 0x%x\n"
-		"modem cntl_ch: 0x%x\n"
-		"lpass cntl_ch: 0x%x\n"
-		"riva cntl_ch: 0x%x\n"
-		"CPU Tools id: %d\n"
-		"Apps only: %d\n"
-		"Apps master: %d\n"
-		"Check Polling Response: %d\n"
-		"polling_reg_flag: %d\n"
-		"uses device tree: %d\n"
-		"in_busy_1: %d\n"
-		"in_busy_2: %d\n"
-		"in_busy_lpass_1: %d\n"
-		"in_busy_lpass_2: %d\n"
-		"in_busy_wcnss_1: %d\n"
-		"in_busy_wcnss_2: %d\n"
-		"in_busy_dci: %d\n"
-		"logging_mode: %d\n",
-		(unsigned int)driver->ch,
-		(unsigned int)driver->chlpass,
-		(unsigned int)driver->ch_wcnss,
-		(unsigned int)driver->ch_dci,
-		(unsigned int)driver->ch_cntl,
-		(unsigned int)driver->chlpass_cntl,
-		(unsigned int)driver->ch_wcnss_cntl,
-		chk_config_get_id(),
-		chk_apps_only(),
-		chk_apps_master(),
-		chk_polling_response(),
-		driver->polling_reg_flag,
-		driver->use_device_tree,
-		driver->in_busy_1,
-		driver->in_busy_2,
-		driver->in_busy_lpass_1,
-		driver->in_busy_lpass_2,
-		driver->in_busy_wcnss_1,
-		driver->in_busy_wcnss_2,
-		driver->in_busy_dci,
-		driver->logging_mode);
-
-#ifdef CONFIG_DIAG_OVER_USB
-	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
-		"usb_connected: %d\n",
-		driver->usb_connected);
-#endif
-	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
-
-	kfree(buf);
-	return ret;
-}
-
-static ssize_t diag_dbgfs_read_workpending(struct file *file,
-				char __user *ubuf, size_t count, loff_t *ppos)
-{
-	char *buf;
-	int ret;
-
-	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
-	if (!buf) {
-		pr_err("diag: %s, Error allocating memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
-		"Pending status for work_stucts:\n"
-		"diag_drain_work: %d\n"
-		"diag_read_smd_work: %d\n"
-		"diag_read_smd_cntl_work: %d\n"
-		"diag_read_smd_lpass_work: %d\n"
-		"diag_read_smd_lpass_cntl_work: %d\n"
-		"diag_read_smd_wcnss_work: %d\n"
-		"diag_read_smd_wcnss_cntl_work: %d\n"
-		"diag_modem_mask_update_work: %d\n"
-		"diag_lpass_mask_update_work: %d\n"
-		"diag_wcnss_mask_update_work: %d\n"
-		"diag_read_smd_dci_work: %d\n",
-		work_pending(&(driver->diag_drain_work)),
-		work_pending(&(driver->diag_read_smd_work)),
-		work_pending(&(driver->diag_read_smd_cntl_work)),
-		work_pending(&(driver->diag_read_smd_lpass_work)),
-		work_pending(&(driver->diag_read_smd_lpass_cntl_work)),
-		work_pending(&(driver->diag_read_smd_wcnss_work)),
-		work_pending(&(driver->diag_read_smd_wcnss_cntl_work)),
-		work_pending(&(driver->diag_modem_mask_update_work)),
-		work_pending(&(driver->diag_lpass_mask_update_work)),
-		work_pending(&(driver->diag_wcnss_mask_update_work)),
-		work_pending(&(driver->diag_read_smd_dci_work)));
-
-#ifdef CONFIG_DIAG_OVER_USB
-	ret += scnprintf(buf+ret, DEBUG_BUF_SIZE,
-		"diag_proc_hdlc_work: %d\n"
-		"diag_read_work: %d\n",
-		work_pending(&(driver->diag_proc_hdlc_work)),
-		work_pending(&(driver->diag_read_work)));
-#endif
-	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
-
-	kfree(buf);
-	return ret;
-}
-
-static ssize_t diag_dbgfs_read_table(struct file *file, char __user *ubuf,
-				     size_t count, loff_t *ppos)
-{
-	char *buf;
-	int ret = 0;
-	int i;
-	int bytes_remaining;
-	int bytes_in_buffer = 0;
-	int bytes_written;
-	int buf_size = (DEBUG_BUF_SIZE < count) ? DEBUG_BUF_SIZE : count;
-
-	if (diag_dbgfs_table_index >= diag_max_reg) {
-		/* Done. Reset to prepare for future requests */
-		diag_dbgfs_table_index = 0;
-		return 0;
-	}
-
-	buf = kzalloc(sizeof(char) * buf_size, GFP_KERNEL);
-	if (!buf) {
-		pr_err("diag: %s, Error allocating memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	bytes_remaining = buf_size;
-	for (i = diag_dbgfs_table_index; i < diag_max_reg; i++) {
-		/* Do not process empty entries in the table */
-		if (driver->table[i].process_id == 0)
-			continue;
-
-		bytes_written = scnprintf(buf+bytes_in_buffer, bytes_remaining,
-			"i: %3d, cmd_code: %4x, subsys_id: %4x, "
-			"client: %2d, cmd_code_lo: %4x, "
-			"cmd_code_hi: %4x, process_id: %5d\n",
-			i,
-			driver->table[i].cmd_code,
-			driver->table[i].subsys_id,
-			driver->table[i].client_id,
-			driver->table[i].cmd_code_lo,
-			driver->table[i].cmd_code_hi,
-			driver->table[i].process_id);
-
-		bytes_in_buffer += bytes_written;
-
-		/* Check if there is room to add another table entry */
-		bytes_remaining = buf_size - bytes_in_buffer;
-		if (bytes_remaining < bytes_written)
-			break;
-	}
-	diag_dbgfs_table_index = i;
-
-	*ppos = 0;
-	ret = simple_read_from_buffer(ubuf, count, ppos, buf, bytes_in_buffer);
-
-	kfree(buf);
-	return ret;
-}
-
-#ifdef CONFIG_DIAG_BRIDGE_CODE
-static ssize_t diag_dbgfs_read_hsic(struct file *file, char __user *ubuf,
-				    size_t count, loff_t *ppos)
-{
-	char *buf;
-	int ret;
-
-	buf = kzalloc(sizeof(char) * DEBUG_BUF_SIZE, GFP_KERNEL);
-	if (!buf) {
-		pr_err("diag: %s, Error allocating memory\n", __func__);
-		return -ENOMEM;
-	}
-
-	ret = scnprintf(buf, DEBUG_BUF_SIZE,
-		"hsic ch: %d\n"
-		"hsic_inited: %d\n"
-		"hsic enabled: %d\n"
-		"hsic_opened: %d\n"
-		"hsic_suspend: %d\n"
-		"in_busy_hsic_read_on_device: %d\n"
-		"in_busy_hsic_write: %d\n"
-		"count_hsic_pool: %d\n"
-		"count_hsic_write_pool: %d\n"
-		"diag_hsic_pool: %x\n"
-		"diag_hsic_write_pool: %x\n"
-		"write_len_mdm: %d\n"
-		"num_hsic_buf_tbl_entries: %d\n"
-		"usb_mdm_connected: %d\n"
-		"diag_read_mdm_work: %d\n"
-		"diag_read_hsic_work: %d\n"
-		"diag_disconnect_work: %d\n"
-		"diag_usb_read_complete_work: %d\n",
-		driver->hsic_ch,
-		driver->hsic_inited,
-		driver->hsic_device_enabled,
-		driver->hsic_device_opened,
-		driver->hsic_suspend,
-		driver->in_busy_hsic_read_on_device,
-		driver->in_busy_hsic_write,
-		driver->count_hsic_pool,
-		driver->count_hsic_write_pool,
-		(unsigned int)driver->diag_hsic_pool,
-		(unsigned int)driver->diag_hsic_write_pool,
-		driver->write_len_mdm,
-		driver->num_hsic_buf_tbl_entries,
-		driver->usb_mdm_connected,
-		work_pending(&(driver->diag_read_mdm_work)),
-		work_pending(&(driver->diag_read_hsic_work)),
-		work_pending(&(driver->diag_disconnect_work)),
-		work_pending(&(driver->diag_usb_read_complete_work)));
-
-	ret = simple_read_from_buffer(ubuf, count, ppos, buf, ret);
-
-	kfree(buf);
-	return ret;
-}
-
-const struct file_operations diag_dbgfs_hsic_ops = {
-	.read = diag_dbgfs_read_hsic,
-};
-#endif
-
-const struct file_operations diag_dbgfs_status_ops = {
-	.read = diag_dbgfs_read_status,
-};
-
-const struct file_operations diag_dbgfs_table_ops = {
-	.read = diag_dbgfs_read_table,
-};
-
-const struct file_operations diag_dbgfs_workpending_ops = {
-	.read = diag_dbgfs_read_workpending,
-};
-
-void diag_debugfs_init(void)
-{
-	diag_dbgfs_dent = debugfs_create_dir("diag", 0);
-	if (IS_ERR(diag_dbgfs_dent))
-		return;
-
-	debugfs_create_file("status", 0444, diag_dbgfs_dent, 0,
-		&diag_dbgfs_status_ops);
-
-	debugfs_create_file("table", 0444, diag_dbgfs_dent, 0,
-		&diag_dbgfs_table_ops);
-
-	debugfs_create_file("work_pending", 0444, diag_dbgfs_dent, 0,
-		&diag_dbgfs_workpending_ops);
-
-#ifdef CONFIG_DIAG_BRIDGE_CODE
-	debugfs_create_file("hsic", 0444, diag_dbgfs_dent, 0,
-		&diag_dbgfs_hsic_ops);
-#endif
-
-	diag_dbgfs_table_index = 0;
-}
-
-void diag_debugfs_cleanup(void)
-{
-	if (diag_dbgfs_dent) {
-		debugfs_remove_recursive(diag_dbgfs_dent);
-		diag_dbgfs_dent = NULL;
-	}
-}
-#else
-void diag_debugfs_init(void) { }
-void diag_debugfs_cleanup(void) { }
-#endif
diff --git a/drivers/char/diag/diagfwd_cntl.h b/drivers/char/diag/diagfwd_cntl.h
index e6f5352..8a0ec3f 100644
--- a/drivers/char/diag/diagfwd_cntl.h
+++ b/drivers/char/diag/diagfwd_cntl.h
@@ -88,7 +88,5 @@
 void diag_clean_modem_reg_fn(struct work_struct *);
 void diag_clean_lpass_reg_fn(struct work_struct *);
 void diag_clean_wcnss_reg_fn(struct work_struct *);
-void diag_debugfs_init(void);
-void diag_debugfs_cleanup(void);
 
 #endif
diff --git a/drivers/gpu/msm/a3xx_reg.h b/drivers/gpu/msm/a3xx_reg.h
index 05c7967..6a010a9 100644
--- a/drivers/gpu/msm/a3xx_reg.h
+++ b/drivers/gpu/msm/a3xx_reg.h
@@ -65,13 +65,17 @@
 #define A3XX_RBBM_INT_CLEAR_CMD 0x061
 #define A3XX_RBBM_INT_0_MASK 0x063
 #define A3XX_RBBM_INT_0_STATUS 0x064
+#define A3XX_RBBM_PERFCTR_CTL 0x80
 #define A3XX_RBBM_GPU_BUSY_MASKED 0x88
+#define A3XX_RBBM_PERFCTR_SP_7_LO 0xE0
+#define A3XX_RBBM_PERFCTR_SP_7_HI 0xE1
 #define A3XX_RBBM_RBBM_CTL 0x100
 #define A3XX_RBBM_RBBM_CTL 0x100
 #define A3XX_RBBM_PERFCTR_PWR_1_LO 0x0EC
 #define A3XX_RBBM_PERFCTR_PWR_1_HI 0x0ED
 #define A3XX_RBBM_DEBUG_BUS_CTL             0x111
 #define A3XX_RBBM_DEBUG_BUS_DATA_STATUS     0x112
+
 /* Following two are same as on A2XX, just in a different place */
 #define A3XX_CP_PFP_UCODE_ADDR 0x1C9
 #define A3XX_CP_PFP_UCODE_DATA 0x1CA
@@ -160,6 +164,7 @@
 #define A3XX_VPC_VPC_DEBUG_RAM_READ 0xE62
 #define A3XX_UCHE_CACHE_MODE_CONTROL_REG 0xE82
 #define A3XX_UCHE_CACHE_INVALIDATE0_REG 0xEA0
+#define A3XX_SP_PERFCOUNTER7_SELECT 0xECB
 #define A3XX_GRAS_CL_CLIP_CNTL 0x2040
 #define A3XX_GRAS_CL_GB_CLIP_ADJ 0x2044
 #define A3XX_GRAS_CL_VPORT_XOFFSET 0x2048
@@ -528,4 +533,7 @@
 /* RBBM_CLOCK_CTL default value */
 #define A3XX_RBBM_CLOCK_CTL_DEFAULT 0xBFFFFFFF
 
+/* COUNTABLE FOR SP PERFCOUNTER */
+#define SP_FS_FULL_ALU_INSTRUCTIONS    0x0E
+
 #endif
diff --git a/drivers/gpu/msm/adreno.c b/drivers/gpu/msm/adreno.c
index cf7f3ce..e0d40be 100644
--- a/drivers/gpu/msm/adreno.c
+++ b/drivers/gpu/msm/adreno.c
@@ -127,6 +127,8 @@
 	REG_CP_IB1_BUFSZ,
 	REG_CP_IB2_BASE,
 	REG_CP_IB2_BUFSZ,
+	0,
+	0
 };
 
 const unsigned int hang_detect_regs_count = ARRAY_SIZE(hang_detect_regs);
@@ -1233,6 +1235,12 @@
 	 */
 	hang_detect_regs[0] = adreno_dev->gpudev->reg_rbbm_status;
 
+	/* Add A3XX specific registers for hang detection */
+	if (adreno_is_a3xx(adreno_dev)) {
+		hang_detect_regs[6] = A3XX_RBBM_PERFCTR_SP_7_LO;
+		hang_detect_regs[7] = A3XX_RBBM_PERFCTR_SP_7_HI;
+	}
+
 	status = kgsl_mmu_start(device);
 	if (status)
 		goto error_clk_off;
@@ -2156,6 +2164,10 @@
 		return 0;
 
 	for (i = 0; i < hang_detect_regs_count; i++) {
+
+		if (hang_detect_regs[i] == 0)
+			continue;
+
 		adreno_regread(device, hang_detect_regs[i],
 					   &curr_reg_val[i]);
 		if (curr_reg_val[i] != prev_reg_val[i]) {
diff --git a/drivers/gpu/msm/adreno_a2xx.c b/drivers/gpu/msm/adreno_a2xx.c
index 2388fff..8de2c70 100644
--- a/drivers/gpu/msm/adreno_a2xx.c
+++ b/drivers/gpu/msm/adreno_a2xx.c
@@ -1749,9 +1749,6 @@
 	if (status & (CP_INT_CNTL__IB1_INT_MASK | CP_INT_CNTL__RB_INT_MASK)) {
 		queue_work(device->work_queue, &device->ts_expired_ws);
 		wake_up_interruptible_all(&device->wait_queue);
-		atomic_notifier_call_chain(&(device->ts_notifier_list),
-					   device->id,
-					   NULL);
 	}
 }
 
diff --git a/drivers/gpu/msm/adreno_a3xx.c b/drivers/gpu/msm/adreno_a3xx.c
index 7bf928f..104baf8 100644
--- a/drivers/gpu/msm/adreno_a3xx.c
+++ b/drivers/gpu/msm/adreno_a3xx.c
@@ -2587,9 +2587,6 @@
 
 	/* Schedule work to free mem and issue ibs */
 	queue_work(device->work_queue, &device->ts_expired_ws);
-
-	atomic_notifier_call_chain(&device->ts_notifier_list,
-				   device->id, NULL);
 }
 
 #define A3XX_IRQ_CALLBACK(_c) { .func = _c }
@@ -2836,6 +2833,17 @@
 		adreno_regwrite(device, A3XX_RB_GMEM_BASE_ADDR,
 			(unsigned int)(adreno_dev->ocmem_base >> 14));
 	}
+
+	/* Turn on performance counters */
+	adreno_regwrite(device, A3XX_RBBM_PERFCTR_CTL, 0x01);
+
+	/*
+	 * Set SP perfcounter 7 to count SP_FS_FULL_ALU_INSTRUCTIONS
+	 * we will use this to augment our hang detection
+	 */
+
+	adreno_regwrite(device, A3XX_SP_PERFCOUNTER7_SELECT,
+		SP_FS_FULL_ALU_INSTRUCTIONS);
 }
 
 /* Defined in adreno_a3xx_snapshot.c */
diff --git a/drivers/gpu/msm/adreno_ringbuffer.c b/drivers/gpu/msm/adreno_ringbuffer.c
index 1ff219b..0dd140b 100644
--- a/drivers/gpu/msm/adreno_ringbuffer.c
+++ b/drivers/gpu/msm/adreno_ringbuffer.c
@@ -503,7 +503,7 @@
 	 * support, we must use the global timestamp since issueibcmds
 	 * will be returning that one.
 	 */
-	if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
+	if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS)
 		context_id = context->id;
 
 	/* reserve space to temporarily turn off protected mode
@@ -518,7 +518,7 @@
 		total_sizedwords += 7;
 
 	total_sizedwords += 2; /* scratchpad ts for recovery */
-	if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
+	if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
 		total_sizedwords += 3; /* sop timestamp */
 		total_sizedwords += 4; /* eop timestamp */
 		total_sizedwords += 3; /* global timestamp without cache
@@ -591,7 +591,7 @@
 		GSL_RB_WRITE(ringcmds, rcmd_gpu, 0x00);
 	}
 
-	if (context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
+	if (context && context->flags & CTXT_FLAGS_PER_CONTEXT_TS) {
 		/* start-of-pipeline timestamp */
 		GSL_RB_WRITE(ringcmds, rcmd_gpu,
 			cp_type3_packet(CP_MEM_WRITE, 2));
@@ -902,6 +902,7 @@
 	unsigned int i;
 	struct adreno_context *drawctxt;
 	unsigned int start_index = 0;
+	int ret;
 
 	if (device->state & KGSL_STATE_HUNG)
 		return -EBUSY;
@@ -948,9 +949,15 @@
 		if (unlikely(adreno_dev->ib_check_level >= 1 &&
 		    !_parse_ibs(dev_priv, ibdesc[i].gpuaddr,
 				ibdesc[i].sizedwords))) {
-			kfree(link);
-			return -EINVAL;
+			ret = -EINVAL;
+			goto done;
 		}
+
+		if (ibdesc[i].sizedwords == 0) {
+			ret = -EINVAL;
+			goto done;
+		}
+
 		*cmds++ = CP_HDR_INDIRECT_BUFFER_PFD;
 		*cmds++ = ibdesc[i].gpuaddr;
 		*cmds++ = ibdesc[i].sizedwords;
@@ -972,7 +979,6 @@
 	KGSL_CMD_INFO(device, "<%d:0x%x> g %08x numibs %d\n",
 		context->id, *timestamp, (unsigned int)ibdesc, numibs);
 
-	kfree(link);
 
 #ifdef CONFIG_MSM_KGSL_CFF_DUMP
 	/*
@@ -982,13 +988,16 @@
 	 */
 	adreno_idle(device);
 #endif
+
 	/* If context hung and recovered then return error so that the
 	 * application may handle it */
-	if (drawctxt->flags & CTXT_FLAGS_GPU_HANG_RECOVERED)
-		return -EDEADLK;
-	else
-		return 0;
 
+	ret = (drawctxt->flags & CTXT_FLAGS_GPU_HANG_RECOVERED) ?
+		-EDEADLK : 0;
+
+done:
+	kfree(link);
+	return ret;
 }
 
 static int _find_start_of_cmd_seq(struct adreno_ringbuffer *rb,
diff --git a/drivers/gpu/msm/kgsl.c b/drivers/gpu/msm/kgsl.c
index ccc6119..664d519 100644
--- a/drivers/gpu/msm/kgsl.c
+++ b/drivers/gpu/msm/kgsl.c
@@ -507,24 +507,6 @@
 	return ret;
 }
 
-int kgsl_register_ts_notifier(struct kgsl_device *device,
-			      struct notifier_block *nb)
-{
-	BUG_ON(device == NULL);
-	return atomic_notifier_chain_register(&device->ts_notifier_list,
-					      nb);
-}
-EXPORT_SYMBOL(kgsl_register_ts_notifier);
-
-int kgsl_unregister_ts_notifier(struct kgsl_device *device,
-				struct notifier_block *nb)
-{
-	BUG_ON(device == NULL);
-	return atomic_notifier_chain_unregister(&device->ts_notifier_list,
-						nb);
-}
-EXPORT_SYMBOL(kgsl_unregister_ts_notifier);
-
 int kgsl_check_timestamp(struct kgsl_device *device,
 	struct kgsl_context *context, unsigned int timestamp)
 {
diff --git a/drivers/gpu/msm/kgsl_device.h b/drivers/gpu/msm/kgsl_device.h
index 2ca3a4f..dc597f5 100644
--- a/drivers/gpu/msm/kgsl_device.h
+++ b/drivers/gpu/msm/kgsl_device.h
@@ -155,7 +155,6 @@
 	struct kgsl_pwrctrl pwrctrl;
 	int open_count;
 
-	struct atomic_notifier_head ts_notifier_list;
 	struct mutex mutex;
 	uint32_t state;
 	uint32_t requested_state;
@@ -210,7 +209,6 @@
 	.hwaccess_gate = COMPLETION_INITIALIZER((_dev).hwaccess_gate),\
 	.suspend_gate = COMPLETION_INITIALIZER((_dev).suspend_gate),\
 	.recovery_gate = COMPLETION_INITIALIZER((_dev).recovery_gate),\
-	.ts_notifier_list = ATOMIC_NOTIFIER_INIT((_dev).ts_notifier_list),\
 	.idle_check_ws = __WORK_INITIALIZER((_dev).idle_check_ws,\
 			kgsl_idle_check),\
 	.ts_expired_ws  = __WORK_INITIALIZER((_dev).ts_expired_ws,\
@@ -374,12 +372,6 @@
 int kgsl_check_timestamp(struct kgsl_device *device,
 		struct kgsl_context *context, unsigned int timestamp);
 
-int kgsl_register_ts_notifier(struct kgsl_device *device,
-			      struct notifier_block *nb);
-
-int kgsl_unregister_ts_notifier(struct kgsl_device *device,
-				struct notifier_block *nb);
-
 int kgsl_device_platform_probe(struct kgsl_device *device);
 
 void kgsl_device_platform_remove(struct kgsl_device *device);
diff --git a/drivers/gpu/msm/kgsl_trace.h b/drivers/gpu/msm/kgsl_trace.h
index 81ab3fb..bba06bc 100644
--- a/drivers/gpu/msm/kgsl_trace.h
+++ b/drivers/gpu/msm/kgsl_trace.h
@@ -315,16 +315,18 @@
 	TP_STRUCT__entry(
 		__field(unsigned int, gpuaddr)
 		__field(unsigned int, size)
+		__field(unsigned int, tgid)
 	),
 
 	TP_fast_assign(
 		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
 		__entry->size = mem_entry->memdesc.size;
+		__entry->tgid = mem_entry->priv->pid;
 	),
 
 	TP_printk(
-		"gpuaddr=0x%08x size=%d",
-		__entry->gpuaddr, __entry->size
+		"gpuaddr=0x%08x size=%d tgid=%d",
+		__entry->gpuaddr, __entry->size, __entry->tgid
 	)
 );
 
@@ -339,6 +341,7 @@
 		__field(unsigned int, size)
 		__field(int, fd)
 		__field(int, type)
+		__field(unsigned int, tgid)
 	),
 
 	TP_fast_assign(
@@ -346,12 +349,13 @@
 		__entry->size = mem_entry->memdesc.size;
 		__entry->fd = fd;
 		__entry->type = mem_entry->memtype;
+		__entry->tgid = mem_entry->priv->pid;
 	),
 
 	TP_printk(
-		"gpuaddr=0x%08x size=%d type=%d fd=%d",
+		"gpuaddr=0x%08x size=%d type=%d fd=%d tgid=%d",
 		__entry->gpuaddr, __entry->size,
-		__entry->type, __entry->fd
+		__entry->type, __entry->fd, __entry->tgid
 	)
 );
 
@@ -366,17 +370,20 @@
 		__field(unsigned int, size)
 		__field(int, type)
 		__field(int, fd)
+		__field(unsigned int, tgid)
 	),
 
 	TP_fast_assign(
 		__entry->gpuaddr = mem_entry->memdesc.gpuaddr;
 		__entry->size = mem_entry->memdesc.size;
 		__entry->type = mem_entry->memtype;
+		__entry->tgid = mem_entry->priv->pid;
 	),
 
 	TP_printk(
-		"gpuaddr=0x%08x size=%d type=%d",
-		__entry->gpuaddr, __entry->size, __entry->type
+		"gpuaddr=0x%08x size=%d type=%d tgid=%d",
+		__entry->gpuaddr, __entry->size, __entry->type,
+		__entry->tgid
 	)
 );
 
diff --git a/drivers/gpu/msm/z180.c b/drivers/gpu/msm/z180.c
index 8ddc991..712bc60 100644
--- a/drivers/gpu/msm/z180.c
+++ b/drivers/gpu/msm/z180.c
@@ -212,10 +212,6 @@
 
 			queue_work(device->work_queue, &device->ts_expired_ws);
 			wake_up_interruptible(&device->wait_queue);
-
-			atomic_notifier_call_chain(
-				&(device->ts_notifier_list),
-				device->id, NULL);
 		}
 	}
 
diff --git a/drivers/input/misc/pmic8xxx-pwrkey.c b/drivers/input/misc/pmic8xxx-pwrkey.c
index 9f64cec..775e95d 100644
--- a/drivers/input/misc/pmic8xxx-pwrkey.c
+++ b/drivers/input/misc/pmic8xxx-pwrkey.c
@@ -178,10 +178,22 @@
 	pwrkey->key_press_irq = key_press_irq;
 	pwrkey->key_release_irq = key_release_irq;
 	pwrkey->pwr = pwr;
-	pwrkey->press = false;
 
 	platform_set_drvdata(pdev, pwrkey);
 
+	/* check power key status during boot */
+	err = pm8xxx_read_irq_stat(pdev->dev.parent, key_press_irq);
+	if (err < 0) {
+		dev_err(&pdev->dev, "reading irq status failed\n");
+		goto unreg_input_dev;
+	}
+	pwrkey->press = !!err;
+
+	if (pwrkey->press) {
+		input_report_key(pwrkey->pwr, KEY_POWER, 1);
+		input_sync(pwrkey->pwr);
+	}
+
 	err = request_any_context_irq(key_press_irq, pwrkey_press_irq,
 		IRQF_TRIGGER_RISING, "pmic8xxx_pwrkey_press", pwrkey);
 	if (err < 0) {
diff --git a/drivers/iommu/msm_iommu-v2.c b/drivers/iommu/msm_iommu-v2.c
index c7f6b82..f49d009 100644
--- a/drivers/iommu/msm_iommu-v2.c
+++ b/drivers/iommu/msm_iommu-v2.c
@@ -169,8 +169,10 @@
 	mb();
 }
 
-static void __program_iommu(void __iomem *base, int smt_size)
+static void __program_iommu(void __iomem *base, int smt_size,
+			    struct msm_iommu_bfb_settings *bfb_settings)
 {
+	int i;
 	__reset_iommu(base, smt_size);
 
 	SET_CR0_SMCFCFG(base, 1);
@@ -181,6 +183,12 @@
 	SET_CR0_GFIE(base, 1);
 	SET_CR0_GFRE(base, 1);
 	SET_CR0_CLIENTPD(base, 0);
+
+	if (bfb_settings)
+		for (i = 0; i < bfb_settings->length; i++)
+			SET_GLOBAL_REG(base, bfb_settings->regs[i],
+					     bfb_settings->data[i]);
+
 	mb();	/* Make sure writes complete before returning */
 }
 
@@ -200,6 +208,17 @@
 	mb();
 }
 
+static void __release_smg(void __iomem *base, int ctx, int smt_size)
+{
+	int i;
+
+	/* Invalidate any SMGs associated with this context */
+	for (i = 0; i < smt_size; i++)
+		if (GET_SMR_VALID(base, i) &&
+		    GET_S2CR_CBNDX(base, i) == ctx)
+			SET_SMR_VALID(base, i, 0);
+}
+
 static void __program_context(void __iomem *base, int ctx, int ncb,
 				phys_addr_t pgtable, int redirect,
 				u32 *sids, int len, int smt_size)
@@ -416,7 +435,8 @@
 	}
 
 	if (!msm_iommu_ctx_attached(dev->parent))
-		__program_iommu(iommu_drvdata->base, iommu_drvdata->nsmr);
+		__program_iommu(iommu_drvdata->base, iommu_drvdata->nsmr,
+				iommu_drvdata->bfb_settings);
 
 	__program_context(iommu_drvdata->base, ctx_drvdata->num,
 		iommu_drvdata->ncb, __pa(priv->pt.fl_table),
@@ -458,6 +478,9 @@
 		GET_CB_CONTEXTIDR_ASID(iommu_drvdata->base, ctx_drvdata->num));
 
 	__reset_context(iommu_drvdata->base, ctx_drvdata->num);
+	__release_smg(iommu_drvdata->base, ctx_drvdata->num,
+		      iommu_drvdata->nsmr);
+
 	__disable_clocks(iommu_drvdata);
 
 	regulator_disable(iommu_drvdata->gdsc);
diff --git a/drivers/iommu/msm_iommu_dev-v2.c b/drivers/iommu/msm_iommu_dev-v2.c
index 8c26f95..237d601 100644
--- a/drivers/iommu/msm_iommu_dev-v2.c
+++ b/drivers/iommu/msm_iommu_dev-v2.c
@@ -29,6 +29,66 @@
 #include <mach/iommu_hw-v2.h>
 #include <mach/iommu.h>
 
+static int msm_iommu_parse_bfb_settings(struct platform_device *pdev,
+				    struct msm_iommu_drvdata *drvdata)
+{
+	struct msm_iommu_bfb_settings *bfb_settings;
+	u32 nreg, nval;
+	int ret, i;
+
+	/*
+	 * It is not valid for a device to have the qcom,iommu-bfb-regs
+	 * property but not the qcom,iommu-bfb-data property, and vice versa.
+	 */
+	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-regs", &nreg)) {
+		if (of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-data",
+				    &nval))
+			return -EINVAL;
+		return 0;
+	}
+
+	if (!of_get_property(pdev->dev.of_node, "qcom,iommu-bfb-data", &nval))
+		return -EINVAL;
+
+	if (nreg >= sizeof(bfb_settings->regs))
+		return -EINVAL;
+
+	if (nval >= sizeof(bfb_settings->data))
+		return -EINVAL;
+
+	if (nval != nreg)
+		return -EINVAL;
+
+	bfb_settings = devm_kzalloc(&pdev->dev, sizeof(*bfb_settings),
+				    GFP_KERNEL);
+	if (!bfb_settings)
+		return -ENOMEM;
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+					 "qcom,iommu-bfb-regs",
+					 bfb_settings->regs,
+					 nreg / sizeof(*bfb_settings->regs));
+	if (ret)
+		return ret;
+
+	ret = of_property_read_u32_array(pdev->dev.of_node,
+					 "qcom,iommu-bfb-data",
+					 bfb_settings->data,
+					 nval / sizeof(*bfb_settings->data));
+	if (ret)
+		return ret;
+
+	bfb_settings->length = nreg / sizeof(*bfb_settings->regs);
+
+	for (i = 0; i < bfb_settings->length; i++)
+		if (bfb_settings->regs[i] < IMPLDEF_OFFSET ||
+		    bfb_settings->regs[i] >= IMPLDEF_OFFSET + IMPLDEF_LENGTH)
+			return -EINVAL;
+
+	drvdata->bfb_settings = bfb_settings;
+	return 0;
+}
+
 static int msm_iommu_parse_dt(struct platform_device *pdev,
 				struct msm_iommu_drvdata *drvdata)
 {
@@ -40,6 +100,10 @@
 	if (ret)
 		goto fail;
 
+	ret = msm_iommu_parse_bfb_settings(pdev, drvdata);
+	if (ret)
+		goto fail;
+
 	ret = of_property_read_u32(pdev->dev.of_node, "qcom,iommu-smt-size",
 				   &nsmr);
 	if (ret)
diff --git a/drivers/media/video/msm/msm.h b/drivers/media/video/msm/msm.h
index 2d9296c..17303dd 100644
--- a/drivers/media/video/msm/msm.h
+++ b/drivers/media/video/msm/msm.h
@@ -210,11 +210,13 @@
 	int dirty;
 	int node_type;
 	struct timeval timestamp;
+	uint32_t frame_id;
 };
 
 struct msm_cam_timestamp {
 	uint8_t present;
 	struct timeval timestamp;
+	uint32_t frame_id;
 };
 
 struct msm_cam_buf_map_info {
diff --git a/drivers/media/video/msm/msm_mctl_buf.c b/drivers/media/video/msm/msm_mctl_buf.c
index a3c7243..2919d23 100644
--- a/drivers/media/video/msm/msm_mctl_buf.c
+++ b/drivers/media/video/msm/msm_mctl_buf.c
@@ -434,7 +434,11 @@
 		D("%s Copying timestamp as %ld.%ld", __func__,
 			cam_ts->timestamp.tv_sec, cam_ts->timestamp.tv_usec);
 		buf->vidbuf.v4l2_buf.timestamp = cam_ts->timestamp;
+		buf->vidbuf.v4l2_buf.sequence  = cam_ts->frame_id;
 	}
+	D("%s Notify user about buffer %d image_mode %d frame_id %d", __func__,
+		buf->vidbuf.v4l2_buf.index, pcam_inst->image_mode,
+		buf->vidbuf.v4l2_buf.sequence);
 	vb2_buffer_done(&buf->vidbuf, VB2_BUF_STATE_DONE);
 	return 0;
 }
@@ -821,6 +825,7 @@
 		__func__, pcam_inst, frame->ch_paddr[0], ret_frame->dirty);
 	cam_ts.present = 1;
 	cam_ts.timestamp = ret_frame->timestamp;
+	cam_ts.frame_id   = ret_frame->frame_id;
 	if (ret_frame->dirty)
 		/* the frame is dirty, not going to disptach to app */
 		rc = msm_mctl_release_free_buf(pmctl, pcam_inst, frame);
diff --git a/drivers/media/video/msm/msm_mctl_pp.c b/drivers/media/video/msm/msm_mctl_pp.c
index a114b37..105426e 100644
--- a/drivers/media/video/msm/msm_mctl_pp.c
+++ b/drivers/media/video/msm/msm_mctl_pp.c
@@ -636,6 +636,9 @@
 	ret_frame.dirty = dirty;
 	ret_frame.node_type = 0;
 	ret_frame.timestamp = frame.timestamp;
+	ret_frame.frame_id   = frame.frame_id;
+	D("%s frame_id: %d buffer idx %d\n", __func__,
+		frame.frame_id, frame.buf_idx);
 	rc = msm_mctl_buf_done_pp(p_mctl, &buf_handle, &buf, &ret_frame);
 	return rc;
 }
diff --git a/drivers/media/video/msm/vfe/msm_vfe32.c b/drivers/media/video/msm/vfe/msm_vfe32.c
index 6e22388..db0db36 100644
--- a/drivers/media/video/msm/vfe/msm_vfe32.c
+++ b/drivers/media/video/msm/vfe/msm_vfe32.c
@@ -587,6 +587,25 @@
 	atomic_set(&share_ctrl->handle_common_irq, 1);
 }
 
+static void axi_clear_all_interrupts(struct vfe_share_ctrl_t *share_ctrl)
+{
+	atomic_set(&share_ctrl->handle_common_irq, 0);
+	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
+		share_ctrl->vfebase + VFE_IRQ_MASK_0);
+	msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
+		share_ctrl->vfebase + VFE_IRQ_MASK_1);
+
+	/* clear all pending interrupts*/
+	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
+		share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
+	msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
+		share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
+	/* Ensure the write order while writing
+	*to the command register using the barrier */
+	msm_camera_io_w_mb(1,
+		share_ctrl->vfebase + VFE_IRQ_CMD);
+}
+
 static void axi_disable_irq(struct vfe_share_ctrl_t *share_ctrl,
 	uint32_t mode)
 {
@@ -632,24 +651,6 @@
 		msm_camera_io_w(irq_mask, share_ctrl->vfebase +
 			VFE_IRQ_MASK_0);
 	}
-	/*Dont Disable for concurrent*/
-	if (share_ctrl->axi_ref_cnt == 1) {
-		atomic_set(&share_ctrl->handle_common_irq, 0);
-		msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-			share_ctrl->vfebase + VFE_IRQ_MASK_0);
-		msm_camera_io_w(VFE_DISABLE_ALL_IRQS,
-			share_ctrl->vfebase + VFE_IRQ_MASK_1);
-
-		/* clear all pending interrupts*/
-		msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-			share_ctrl->vfebase + VFE_IRQ_CLEAR_0);
-		msm_camera_io_w(VFE_CLEAR_ALL_IRQS,
-			share_ctrl->vfebase + VFE_IRQ_CLEAR_1);
-		/* Ensure the write order while writing
-		*to the command register using the barrier */
-		msm_camera_io_w_mb(1,
-			share_ctrl->vfebase + VFE_IRQ_CMD);
-	}
 }
 
 static void vfe32_stop(struct vfe32_ctrl_type *vfe32_ctrl)
@@ -5554,6 +5555,8 @@
 	axi_ctrl->share_ctrl->axi_ref_cnt--;
 	if (axi_ctrl->share_ctrl->axi_ref_cnt > 0)
 		return;
+
+	axi_clear_all_interrupts(axi_ctrl->share_ctrl);
 	axi_ctrl->share_ctrl->dual_enabled = 0;
 	disable_irq(axi_ctrl->vfeirq->start);
 	tasklet_kill(&axi_ctrl->vfe32_tasklet);
diff --git a/drivers/media/video/msm_wfd/enc-mfc-subdev.c b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
index 3292d78..09a5e32 100644
--- a/drivers/media/video/msm_wfd/enc-mfc-subdev.c
+++ b/drivers/media/video/msm_wfd/enc-mfc-subdev.c
@@ -2199,7 +2199,7 @@
 			if (rc)
 				WFD_MSG_ERR("Failed to free recon buffer\n");
 
-			if (IS_ERR_OR_NULL(
+			if (!IS_ERR_OR_NULL(
 				client_ctx->recon_buffer_ion_handle[i])) {
 				if (!inst->secure) {
 					ion_unmap_iommu(
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 7ac78cb..753171c 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1957,8 +1957,10 @@
 
 	/* init video device*/
 	vfd = video_device_alloc();
-	if (!vfd)
+	if (!vfd) {
+		ret = -ENOMEM;
 		goto deinit_vc;
+	}
 
 	*vfd = vcap_template;
 	vfd->v4l2_dev = &dev->v4l2_dev;
@@ -1972,6 +1974,7 @@
 
 	dev->vcap_wq = create_workqueue("vcap");
 	if (!dev->vcap_wq) {
+		ret = -ENOMEM;
 		pr_err("Could not create workqueue");
 		goto rel_vdev;
 	}
@@ -1979,6 +1982,8 @@
 	dev->ion_client = msm_ion_client_create(-1, "vcap");
 	if (IS_ERR((void *)dev->ion_client)) {
 		pr_err("could not get ion client");
+		ret = PTR_ERR(dev->ion_client);
+		dev->ion_client = NULL;
 		goto rel_vcap_wq;
 	}
 
diff --git a/drivers/misc/qseecom.c b/drivers/misc/qseecom.c
index 4840e64..bc8eccf 100644
--- a/drivers/misc/qseecom.c
+++ b/drivers/misc/qseecom.c
@@ -142,7 +142,6 @@
 static DEFINE_MUTEX(pil_access_lock);
 
 static DEFINE_MUTEX(qsee_bw_mutex);
-static DEFINE_MUTEX(qsee_sfpb_bw_mutex);
 static DEFINE_MUTEX(app_access_lock);
 
 static int qsee_bw_count;
@@ -1198,28 +1197,41 @@
 	case CLK_DFAB:
 		mutex_lock(&qsee_bw_mutex);
 		if (!qsee_bw_count) {
-			ret = msm_bus_scale_client_update_request(
-					qsee_perf_client, 1);
+			if (qsee_sfpb_bw_count > 0)
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 3);
+			else
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 1);
 			if (ret)
 				pr_err("DFAB Bandwidth req failed (%d)\n",
 								ret);
 			else
 				qsee_bw_count++;
+		} else {
+			qsee_bw_count++;
 		}
 		mutex_unlock(&qsee_bw_mutex);
 		break;
 	case CLK_SFPB:
-		mutex_lock(&qsee_sfpb_bw_mutex);
+		mutex_lock(&qsee_bw_mutex);
 		if (!qsee_sfpb_bw_count) {
-			ret = msm_bus_scale_client_update_request(
-					qsee_perf_client, 2);
+			if (qsee_bw_count > 0)
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 3);
+			else
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 2);
+
 			if (ret)
 				pr_err("SFPB Bandwidth req failed (%d)\n",
 								ret);
 			else
 				qsee_sfpb_bw_count++;
+		} else {
+			qsee_sfpb_bw_count++;
 		}
-		mutex_unlock(&qsee_sfpb_bw_mutex);
+		mutex_unlock(&qsee_bw_mutex);
 		break;
 	default:
 		pr_err("Clock type not defined\n");
@@ -1238,29 +1250,44 @@
 	switch (clk_type) {
 	case CLK_DFAB:
 		mutex_lock(&qsee_bw_mutex);
-		if (qsee_bw_count > 0) {
-			if (qsee_bw_count-- == 1) {
+		if (qsee_bw_count == 0) {
+			pr_err("Client error.Extra call to disable DFAB clk\n");
+			mutex_unlock(&qsee_bw_mutex);
+			return;
+		}
+
+		if ((qsee_bw_count > 0) && (qsee_bw_count-- == 1)) {
+			if (qsee_sfpb_bw_count > 0)
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 2);
+			else
 				ret = msm_bus_scale_client_update_request(
 						qsee_perf_client, 0);
-				if (ret)
-					pr_err("SFPB Bandwidth req fail (%d)\n",
+			if (ret)
+				pr_err("SFPB Bandwidth req fail (%d)\n",
 								ret);
-			}
 		}
 		mutex_unlock(&qsee_bw_mutex);
 		break;
 	case CLK_SFPB:
-		mutex_lock(&qsee_sfpb_bw_mutex);
-		if (qsee_sfpb_bw_count > 0) {
-			if (qsee_sfpb_bw_count-- == 1) {
+		mutex_lock(&qsee_bw_mutex);
+		if (qsee_sfpb_bw_count == 0) {
+			pr_err("Client error.Extra call to disable SFPB clk\n");
+			mutex_unlock(&qsee_bw_mutex);
+			return;
+		}
+		if ((qsee_sfpb_bw_count > 0) && (qsee_sfpb_bw_count-- == 1)) {
+			if (qsee_bw_count > 0)
+				ret = msm_bus_scale_client_update_request(
+						qsee_perf_client, 1);
+			else
 				ret = msm_bus_scale_client_update_request(
 						qsee_perf_client, 0);
-				if (ret)
-					pr_err("SFPB Bandwidth req fail (%d)\n",
+			if (ret)
+				pr_err("SFPB Bandwidth req fail (%d)\n",
 								ret);
-			}
 		}
-		mutex_unlock(&qsee_sfpb_bw_mutex);
+		mutex_unlock(&qsee_bw_mutex);
 		break;
 	default:
 		pr_err("Clock type not defined\n");
@@ -1697,7 +1724,6 @@
 		mutex_unlock(&pil_access_lock);
 	}
 	kfree(data);
-	qsee_disable_clock_vote(CLK_DFAB);
 
 	return ret;
 }
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index 7e144ed..595bc5d 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -1779,6 +1779,7 @@
 msmsdcc_irq(int irq, void *dev_id)
 {
 	struct msmsdcc_host	*host = dev_id;
+	struct mmc_host		*mmc = host->mmc;
 	u32			status;
 	int			ret = 0;
 	int			timer = 0;
@@ -1820,6 +1821,12 @@
 				 */
 				wake_lock(&host->sdio_wlock);
 			} else {
+				if (!mmc->card || !mmc_card_sdio(mmc->card)) {
+					WARN(1, "%s: SDCC core interrupt received for non-SDIO cards when SDCC clocks are off\n",
+					     mmc_hostname(mmc));
+					ret = 1;
+					break;
+				}
 				spin_unlock(&host->lock);
 				mmc_signal_sdio_irq(host->mmc);
 				spin_lock(&host->lock);
@@ -1848,6 +1855,12 @@
 #endif
 
 		if (status & MCI_SDIOINTROPE) {
+			if (!mmc->card || mmc_card_sdio(mmc->card)) {
+				WARN(1, "%s: SDIO interrupt received for non-SDIO card\n",
+					mmc_hostname(mmc));
+				ret = 1;
+				break;
+			}
 			if (host->sdcc_suspending)
 				wake_lock(&host->sdio_suspend_wlock);
 			spin_unlock(&host->lock);
@@ -2826,6 +2839,14 @@
 		msmsdcc_set_vdd_io_vol(host, VDD_IO_LOW, 0);
 		msmsdcc_update_io_pad_pwr_switch(host);
 		msmsdcc_setup_pins(host, false);
+		/*
+		 * Reset the mask to prevent hitting any pending interrupts
+		 * after powering up the card again.
+		 */
+		if (atomic_read(&host->clks_on)) {
+			writel_relaxed(0, host->base + MMCIMASK0);
+			mb();
+		}
 		break;
 	case MMC_POWER_UP:
 		/* writing PWR_UP bit is redundant */
diff --git a/drivers/net/ethernet/msm/msm_rmnet.c b/drivers/net/ethernet/msm/msm_rmnet.c
index 61df241..41ad8af 100644
--- a/drivers/net/ethernet/msm/msm_rmnet.c
+++ b/drivers/net/ethernet/msm/msm_rmnet.c
@@ -501,16 +501,10 @@
 static int __rmnet_close(struct net_device *dev)
 {
 	struct rmnet_private *p = netdev_priv(dev);
-	int rc;
-	unsigned long flags;
 
-	if (p->ch) {
-		rc = smd_close(p->ch);
-		spin_lock_irqsave(&p->lock, flags);
-		p->ch = 0;
-		spin_unlock_irqrestore(&p->lock, flags);
-		return rc;
-	} else
+	if (p->ch)
+		return 0;
+	else
 		return -EBADF;
 }
 
@@ -529,12 +523,9 @@
 
 static int rmnet_stop(struct net_device *dev)
 {
-	struct rmnet_private *p = netdev_priv(dev);
-
 	DBG0("[%s] rmnet_stop()\n", dev->name);
 
 	netif_stop_queue(dev);
-	tasklet_kill(&p->tsklt);
 
 	/* TODO: unload modem safely,
 	   currently, this causes unnecessary unloads */
diff --git a/drivers/thermal/msm8974-tsens.c b/drivers/thermal/msm8974-tsens.c
index 7169dc0..77cc1f9 100644
--- a/drivers/thermal/msm8974-tsens.c
+++ b/drivers/thermal/msm8974-tsens.c
@@ -10,6 +10,9 @@
  * GNU General Public License for more details.
  *
  */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/thermal.h>
@@ -743,8 +746,7 @@
 					IORESOURCE_MEM, "tsens_physical");
 	if (!tmdev->res_tsens_mem) {
 		pr_err("Could not get tsens physical address resource\n");
-		rc = -EINVAL;
-		goto fail_free_irq;
+		return -EINVAL;
 	}
 
 	tmdev->tsens_len = tmdev->res_tsens_mem->end -
@@ -754,8 +756,7 @@
 				tmdev->tsens_len, tmdev->res_tsens_mem->name);
 	if (!res_mem) {
 		pr_err("Request tsens physical memory region failed\n");
-		rc = -EINVAL;
-		goto fail_free_irq;
+		return -EINVAL;
 	}
 
 	tmdev->tsens_addr = ioremap(res_mem->start, tmdev->tsens_len);
@@ -805,9 +806,6 @@
 	if (tmdev->res_tsens_mem)
 		release_mem_region(tmdev->res_tsens_mem->start,
 					tmdev->tsens_len);
-fail_free_irq:
-	free_irq(tmdev->tsens_irq, tmdev);
-
 	return rc;
 }
 
@@ -827,8 +825,10 @@
 
 	tmdev->pdev = pdev;
 	rc = tsens_calib_sensors();
-	if (rc < 0)
+	if (rc < 0) {
+		pr_err("Calibration failed\n");
 		goto fail;
+	}
 
 	tsens_hw_init();
 
@@ -848,8 +848,7 @@
 	if (tmdev->res_tsens_mem)
 		release_mem_region(tmdev->res_tsens_mem->start,
 			tmdev->tsens_len);
-	free_irq(tmdev->tsens_irq, tmdev);
-	kfree(tmdev);
+	tmdev = NULL;
 
 	return rc;
 }
@@ -930,7 +929,6 @@
 				tmdev->tsens_len);
 	free_irq(tmdev->tsens_irq, tmdev);
 	platform_set_drvdata(pdev, NULL);
-	kfree(tmdev);
 
 	return 0;
 }
diff --git a/drivers/usb/gadget/ci13xxx_udc.c b/drivers/usb/gadget/ci13xxx_udc.c
index b8b7f68..0ace679 100644
--- a/drivers/usb/gadget/ci13xxx_udc.c
+++ b/drivers/usb/gadget/ci13xxx_udc.c
@@ -2661,6 +2661,7 @@
 
 	mEp->desc = NULL;
 	mEp->ep.desc = NULL;
+	mEp->ep.maxpacket = USHRT_MAX;
 
 	spin_unlock_irqrestore(mEp->lock, flags);
 	return retval;
@@ -3135,7 +3136,8 @@
 
 			mEp->ep.name      = mEp->name;
 			mEp->ep.ops       = &usb_ep_ops;
-			mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
+			mEp->ep.maxpacket =
+				k ? USHRT_MAX : CTRL_PAYLOAD_MAX;
 
 			INIT_LIST_HEAD(&mEp->qh.queue);
 			spin_unlock_irqrestore(udc->lock, flags);
diff --git a/drivers/usb/gadget/f_rmnet_smd.c b/drivers/usb/gadget/f_rmnet_smd.c
index b71f646..5e2c6ed 100644
--- a/drivers/usb/gadget/f_rmnet_smd.c
+++ b/drivers/usb/gadget/f_rmnet_smd.c
@@ -907,13 +907,14 @@
 		 * Register platform driver to be notified in case SMD channels
 		 * later becomes ready to be opened.
 		 */
-		ret = platform_driver_register(&dev->pdrv);
-		if (ret)
-			ERROR(cdev, "Platform driver %s register failed %d\n",
-					dev->pdrv.driver.name, ret);
-		else
-			dev->is_pdrv_used = 1;
-
+		if (!dev->is_pdrv_used) {
+			ret = platform_driver_register(&dev->pdrv);
+			if (ret)
+				ERROR(cdev, "pdrv %s register failed %d\n",
+						dev->pdrv.driver.name, ret);
+			else
+				dev->is_pdrv_used = 1;
+		}
 		return;
 	}
 	wait_event(dev->smd_ctl.wait, test_bit(CH_OPENED,
diff --git a/drivers/usb/otg/msm72k_otg.c b/drivers/usb/otg/msm72k_otg.c
index f62ae76..ca1b155 100644
--- a/drivers/usb/otg/msm72k_otg.c
+++ b/drivers/usb/otg/msm72k_otg.c
@@ -1229,7 +1229,7 @@
 static irqreturn_t msm_otg_irq(int irq, void *data)
 {
 	struct msm_otg *dev = data;
-	u32 otgsc, sts, pc, sts_mask;
+	u32 otgsc, sts, pc;
 	irqreturn_t ret = IRQ_HANDLED;
 	int work = 0;
 	enum usb_otg_state state;
@@ -1250,12 +1250,16 @@
 	otgsc = readl(USB_OTGSC);
 	sts = readl(USB_USBSTS);
 
-	sts_mask = (otgsc & OTGSC_INTR_MASK) >> 8;
-
-	if (!((otgsc & sts_mask) || (sts & STS_PCI))) {
+	/* At times during USB disconnect, hardware generates 1MSIS interrupt
+	 * during PHY reset, which leads to irq not handled error as IRQ_NONE
+	 * is notified. To workaround this issue, check for all the
+	 * OTG_INTR_STS_MASK bits and if set, clear them and notify IRQ_HANDLED.
+	 */
+	if (!((otgsc & OTGSC_INTR_STS_MASK) || (sts & STS_PCI))) {
 		ret = IRQ_NONE;
 		goto out;
 	}
+	writel_relaxed(otgsc, USB_OTGSC);
 
 	spin_lock_irqsave(&dev->lock, flags);
 	state = dev->phy.state;
@@ -1277,10 +1281,8 @@
 			set_bit(A_BUS_REQ, &dev->inputs);
 			clear_bit(ID, &dev->inputs);
 		}
-		writel(otgsc, USB_OTGSC);
 		work = 1;
 	} else if (otgsc & OTGSC_BSVIS) {
-		writel(otgsc, USB_OTGSC);
 		/* BSV interrupt comes when operating as an A-device
 		 * (VBUS on/off).
 		 * But, handle BSV when charger is removed from ACA in ID_A
@@ -1298,7 +1300,6 @@
 		work = 1;
 	} else if (otgsc & OTGSC_DPIS) {
 		pr_debug("DPIS detected\n");
-		writel(otgsc, USB_OTGSC);
 		set_bit(A_SRP_DET, &dev->inputs);
 		set_bit(A_BUS_REQ, &dev->inputs);
 		work = 1;
diff --git a/drivers/usb/otg/msm_otg.c b/drivers/usb/otg/msm_otg.c
index 60018bf..813fc94 100644
--- a/drivers/usb/otg/msm_otg.c
+++ b/drivers/usb/otg/msm_otg.c
@@ -77,6 +77,11 @@
 	USB_PHY_REG_LPM_OFF,
 };
 
+static char *override_phy_init;
+module_param(override_phy_init, charp, S_IRUGO|S_IWUSR);
+MODULE_PARM_DESC(override_phy_init,
+	"Override HSUSB PHY Init Settings");
+
 static DECLARE_COMPLETION(pmic_vbus_init);
 static struct msm_otg *the_msm_otg;
 static bool debug_aca_enabled;
@@ -384,12 +389,26 @@
 static void ulpi_init(struct msm_otg *motg)
 {
 	struct msm_otg_platform_data *pdata = motg->pdata;
-	int *seq = pdata->phy_init_seq;
+	int aseq[10];
+	int *seq = NULL;
+
+	if (override_phy_init) {
+		pr_debug("%s(): HUSB PHY Init:%s\n", __func__,
+				override_phy_init);
+		get_options(override_phy_init, ARRAY_SIZE(aseq), aseq);
+		seq = &aseq[1];
+	} else {
+		seq = pdata->phy_init_seq;
+	}
 
 	if (!seq)
 		return;
 
 	while (seq[0] >= 0) {
+		if (override_phy_init)
+			pr_debug("ulpi: write 0x%02x to 0x%02x\n",
+					seq[0], seq[1]);
+
 		dev_vdbg(motg->phy.dev, "ulpi: write 0x%02x to 0x%02x\n",
 				seq[0], seq[1]);
 		ulpi_write(&motg->phy, seq[0], seq[1]);
diff --git a/drivers/video/msm/Kconfig b/drivers/video/msm/Kconfig
index 54d7090..ed4c25d 100644
--- a/drivers/video/msm/Kconfig
+++ b/drivers/video/msm/Kconfig
@@ -820,14 +820,6 @@
 	---help---
 	  Support for DVI mode for MSM HDMI 1080p Panel
 
-config FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	depends on FB_MSM_HDMI_MSM_PANEL
-	bool "Use HDCP mode"
-	default y
-	---help---
-	  Support for HDCP mode for MSM HDMI 1080p Panel
-	  Choose to enable HDCP
-
 config FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	depends on FB_MSM_HDMI_MSM_PANEL
 	bool "Enable CEC"
diff --git a/drivers/video/msm/hdmi_msm.c b/drivers/video/msm/hdmi_msm.c
index 3b1610a..deef4ab 100644
--- a/drivers/video/msm/hdmi_msm.c
+++ b/drivers/video/msm/hdmi_msm.c
@@ -69,12 +69,7 @@
 
 static void hdmi_msm_dump_regs(const char *prefix);
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static void hdmi_msm_hdcp_enable(void);
-#else
-static inline void hdmi_msm_hdcp_enable(void) {}
-#endif
-
 static void hdmi_msm_turn_on(void);
 static int hdmi_msm_audio_off(void);
 static int hdmi_msm_read_edid(void);
@@ -678,7 +673,6 @@
 	case 0x00D8: return "ACR_48_1";
 	case 0x00E4: return "AUDIO_INFO0";
 	case 0x00E8: return "AUDIO_INFO1";
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	case 0x0110: return "HDCP_CTRL";
 	case 0x0114: return "HDCP_DEBUG_CTRL";
 	case 0x0118: return "HDCP_INT_CTRL";
@@ -693,7 +687,6 @@
 	case 0x014C: return "HDCP_RCVPORT_DATA5";
 	case 0x0150: return "HDCP_RCVPORT_DATA6";
 	case 0x0168: return "HDCP_RCVPORT_DATA12";
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 	case 0x01D0: return "AUDIO_CFG";
 	case 0x0208: return "USEC_REFTIMER";
 	case 0x020C: return "DDC_CTRL";
@@ -708,14 +701,10 @@
 	case 0x0250: return "HPD_INT_STATUS";
 	case 0x0254: return "HPD_INT_CTRL";
 	case 0x0258: return "HPD_CTRL";
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	case 0x025C: return "HDCP_ENTROPY_CTRL1";
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 	case 0x027C: return "DDC_REF";
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	case 0x0284: return "HDCP_SW_UPPER_AKSV";
 	case 0x0288: return "HDCP_SW_LOWER_AKSV";
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 	case 0x02B4: return "ACTIVE_H";
 	case 0x02B8: return "ACTIVE_V";
 	case 0x02BC: return "ACTIVE_V_F2";
@@ -784,7 +773,7 @@
 
 		DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
 		kobject_uevent(external_common_state->uevent_kobj, KOBJ_ONLINE);
-		if (!external_common_state->present_hdcp) {
+		if (!hdmi_msm_state->hdcp_enable) {
 			/* Send Audio for HDMI Compliance Cases*/
 			envp[0] = "HDCP_STATE=PASS";
 			envp[1] = NULL;
@@ -873,10 +862,13 @@
 }
 #endif
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static void hdcp_deauthenticate(void);
 static void hdmi_msm_hdcp_reauth_work(struct work_struct *work)
 {
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return;
+	}
 
 	/* Don't process recursive actions */
 	mutex_lock(&hdmi_msm_state_mutex);
@@ -894,17 +886,20 @@
 	 * Therefore, as surprising as it may sound do reauth
 	 * only if the device is HDCP-capable
 	 */
-	if (external_common_state->present_hdcp) {
-		hdcp_deauthenticate();
-		mutex_lock(&hdcp_auth_state_mutex);
-		hdmi_msm_state->reauth = TRUE;
-		mutex_unlock(&hdcp_auth_state_mutex);
-		mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
-	}
+	hdcp_deauthenticate();
+	mutex_lock(&hdcp_auth_state_mutex);
+	hdmi_msm_state->reauth = TRUE;
+	mutex_unlock(&hdcp_auth_state_mutex);
+	mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
 }
 
 static void hdmi_msm_hdcp_work(struct work_struct *work)
 {
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return;
+	}
+
 	/* Only re-enable if cable still connected */
 	mutex_lock(&external_common_state_hpd_mutex);
 	if (external_common_state->hpd_state &&
@@ -925,7 +920,111 @@
 		hdmi_msm_state->reauth = FALSE;
 	}
 }
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
+
+int hdmi_msm_process_hdcp_interrupts(void)
+{
+	int rc = -1;
+	uint32 hdcp_int_val;
+	char *envp[2];
+
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return -EINVAL;
+	}
+
+	/* HDCP_INT_CTRL[0x0118]
+	 *    [0] AUTH_SUCCESS_INT	[R]	HDCP Authentication Success
+	 *		interrupt status
+	 *    [1] AUTH_SUCCESS_ACK	[W]	Acknowledge bit for HDCP
+	 *		Authentication Success bit - write 1 to clear
+	 *    [2] AUTH_SUCCESS_MASK	[R/W]	Mask bit for HDCP Authentication
+	 *		Success interrupt - set to 1 to enable interrupt */
+	hdcp_int_val = HDMI_INP_ND(0x0118);
+	if ((hdcp_int_val & (1 << 2)) && (hdcp_int_val & (1 << 0))) {
+		/* AUTH_SUCCESS_INT */
+		HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 1)) & ~(1 << 0));
+		DEV_INFO("HDCP: AUTH_SUCCESS_INT received\n");
+		complete_all(&hdmi_msm_state->hdcp_success_done);
+		return 0;
+	}
+
+	/*    [4] AUTH_FAIL_INT		[R]	HDCP Authentication Lost
+	 *		interrupt Status
+	 *    [5] AUTH_FAIL_ACK		[W]	Acknowledge bit for HDCP
+	 *		Authentication Lost bit - write 1 to clear
+	 *    [6] AUTH_FAIL_MASK	[R/W]	Mask bit fo HDCP Authentication
+	 *		Lost interrupt set to 1 to enable interrupt
+	 *    [7] AUTH_FAIL_INFO_ACK	[W]	Acknowledge bit for HDCP
+	 *		Authentication Failure Info field - write 1 to clear */
+	if ((hdcp_int_val & (1 << 6)) && (hdcp_int_val & (1 << 4))) {
+		/* AUTH_FAIL_INT */
+		/* Clear and Disable */
+		uint32 link_status = HDMI_INP_ND(0x011C);
+		HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
+			& ~((1 << 6) | (1 << 4)));
+		DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
+			link_status);
+		if (hdmi_msm_state->full_auth_done) {
+			switch_set_state(&external_common_state->sdev, 0);
+			DEV_INFO("Hdmi state switched to %d: %s\n",
+				external_common_state->sdev.state,  __func__);
+
+			envp[0] = "HDCP_STATE=FAIL";
+			envp[1] = NULL;
+			DEV_INFO("HDMI HPD:QDSP OFF\n");
+			kobject_uevent_env(external_common_state->uevent_kobj,
+			KOBJ_CHANGE, envp);
+
+			mutex_lock(&hdcp_auth_state_mutex);
+			hdmi_msm_state->full_auth_done = FALSE;
+			mutex_unlock(&hdcp_auth_state_mutex);
+			/* Calling reauth only when authentication
+			 * is sucessful or else we always go into
+			 * the reauth loop. Also, No need to reauthenticate
+			 * if authentication failed because of cable disconnect
+			 */
+			if (((link_status & 0xF0) >> 4) != 0x7) {
+				DEV_DBG("Reauthenticate From %s HDCP FAIL INT ",
+					__func__);
+				queue_work(hdmi_work_queue,
+				    &hdmi_msm_state->hdcp_reauth_work);
+			} else {
+				DEV_INFO("HDCP: HDMI cable disconnected\n");
+			}
+		}
+
+		/* Clear AUTH_FAIL_INFO as well */
+		HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
+		return 0;
+	}
+
+	/*    [8] DDC_XFER_REQ_INT	[R]	HDCP DDC Transfer Request
+	 *		interrupt status
+	 *    [9] DDC_XFER_REQ_ACK	[W]	Acknowledge bit for HDCP DDC
+	 *		Transfer Request bit - write 1 to clear
+	 *   [10] DDC_XFER_REQ_MASK	[R/W]	Mask bit for HDCP DDC Transfer
+	 *		Request interrupt - set to 1 to enable interrupt */
+	if ((hdcp_int_val & (1 << 10)) && (hdcp_int_val & (1 << 8))) {
+		/* DDC_XFER_REQ_INT */
+		HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 9)) & ~(1 << 8));
+		if (!(hdcp_int_val & (1 << 12)))
+			return 0;
+	}
+	/*   [12] DDC_XFER_DONE_INT	[R]	HDCP DDC Transfer done interrupt
+	 *		status
+	 *   [13] DDC_XFER_DONE_ACK	[W]	Acknowledge bit for HDCP DDC
+	 *		Transfer done bit - write 1 to clear
+	 *   [14] DDC_XFER_DONE_MASK	[R/W]	Mask bit for HDCP DDC Transfer
+	 *		done interrupt - set to 1 to enable interrupt */
+	if ((hdcp_int_val & (1 << 14)) && (hdcp_int_val & (1 << 12))) {
+		/* DDC_XFER_DONE_INT */
+		HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 13)) & ~(1 << 12));
+		DEV_INFO("HDCP: DDC_XFER_DONE received\n");
+		return 0;
+	}
+
+	return rc;
+}
 
 static irqreturn_t hdmi_msm_isr(int irq, void *dev_id)
 {
@@ -936,10 +1035,6 @@
 #endif
 	uint32 ddc_int_ctrl;
 	uint32 audio_int_val;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	uint32 hdcp_int_val;
-	char *envp[2];
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 	static uint32 fifo_urun_int_occurred;
 	static uint32 sample_drop_int_occurred;
 	const uint32 occurrence_limit = 5;
@@ -1057,96 +1152,8 @@
 		return IRQ_HANDLED;
 	}
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	/* HDCP_INT_CTRL[0x0118]
-	 *    [0] AUTH_SUCCESS_INT	[R]	HDCP Authentication Success
-	 *		interrupt status
-	 *    [1] AUTH_SUCCESS_ACK	[W]	Acknowledge bit for HDCP
-	 *		Authentication Success bit - write 1 to clear
-	 *    [2] AUTH_SUCCESS_MASK	[R/W]	Mask bit for HDCP Authentication
-	 *		Success interrupt - set to 1 to enable interrupt */
-	hdcp_int_val = HDMI_INP_ND(0x0118);
-	if ((hdcp_int_val & (1 << 2)) && (hdcp_int_val & (1 << 0))) {
-		/* AUTH_SUCCESS_INT */
-		HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 1)) & ~(1 << 0));
-		DEV_INFO("HDCP: AUTH_SUCCESS_INT received\n");
-		complete_all(&hdmi_msm_state->hdcp_success_done);
+	if (!hdmi_msm_process_hdcp_interrupts())
 		return IRQ_HANDLED;
-	}
-	/*    [4] AUTH_FAIL_INT		[R]	HDCP Authentication Lost
-	 *		interrupt Status
-	 *    [5] AUTH_FAIL_ACK		[W]	Acknowledge bit for HDCP
-	 *		Authentication Lost bit - write 1 to clear
-	 *    [6] AUTH_FAIL_MASK	[R/W]	Mask bit fo HDCP Authentication
-	 *		Lost interrupt set to 1 to enable interrupt
-	 *    [7] AUTH_FAIL_INFO_ACK	[W]	Acknowledge bit for HDCP
-	 *		Authentication Failure Info field - write 1 to clear */
-	if ((hdcp_int_val & (1 << 6)) && (hdcp_int_val & (1 << 4))) {
-		/* AUTH_FAIL_INT */
-		/* Clear and Disable */
-		uint32 link_status = HDMI_INP_ND(0x011C);
-		HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 5))
-			& ~((1 << 6) | (1 << 4)));
-		DEV_INFO("HDCP: AUTH_FAIL_INT received, LINK0_STATUS=0x%08x\n",
-			link_status);
-		if (hdmi_msm_state->full_auth_done) {
-			switch_set_state(&external_common_state->sdev, 0);
-			DEV_INFO("Hdmi state switched to %d: %s\n",
-				external_common_state->sdev.state,  __func__);
-
-			envp[0] = "HDCP_STATE=FAIL";
-			envp[1] = NULL;
-			DEV_INFO("HDMI HPD:QDSP OFF\n");
-			kobject_uevent_env(external_common_state->uevent_kobj,
-			KOBJ_CHANGE, envp);
-
-			mutex_lock(&hdcp_auth_state_mutex);
-			hdmi_msm_state->full_auth_done = FALSE;
-			mutex_unlock(&hdcp_auth_state_mutex);
-			/* Calling reauth only when authentication
-			 * is sucessful or else we always go into
-			 * the reauth loop. Also, No need to reauthenticate
-			 * if authentication failed because of cable disconnect
-			 */
-			if (((link_status & 0xF0) >> 4) != 0x7) {
-				DEV_DBG("Reauthenticate From %s HDCP FAIL INT ",
-					__func__);
-				queue_work(hdmi_work_queue,
-				    &hdmi_msm_state->hdcp_reauth_work);
-			} else {
-				DEV_INFO("HDCP: HDMI cable disconnected\n");
-			}
-		}
-
-		/* Clear AUTH_FAIL_INFO as well */
-		HDMI_OUTP(0x0118, (hdcp_int_val | (1 << 7)));
-		return IRQ_HANDLED;
-	}
-	/*    [8] DDC_XFER_REQ_INT	[R]	HDCP DDC Transfer Request
-	 *		interrupt status
-	 *    [9] DDC_XFER_REQ_ACK	[W]	Acknowledge bit for HDCP DDC
-	 *		Transfer Request bit - write 1 to clear
-	 *   [10] DDC_XFER_REQ_MASK	[R/W]	Mask bit for HDCP DDC Transfer
-	 *		Request interrupt - set to 1 to enable interrupt */
-	if ((hdcp_int_val & (1 << 10)) && (hdcp_int_val & (1 << 8))) {
-		/* DDC_XFER_REQ_INT */
-		HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 9)) & ~(1 << 8));
-		if (!(hdcp_int_val & (1 << 12)))
-			return IRQ_HANDLED;
-	}
-	/*   [12] DDC_XFER_DONE_INT	[R]	HDCP DDC Transfer done interrupt
-	 *		status
-	 *   [13] DDC_XFER_DONE_ACK	[W]	Acknowledge bit for HDCP DDC
-	 *		Transfer done bit - write 1 to clear
-	 *   [14] DDC_XFER_DONE_MASK	[R/W]	Mask bit for HDCP DDC Transfer
-	 *		done interrupt - set to 1 to enable interrupt */
-	if ((hdcp_int_val & (1 << 14)) && (hdcp_int_val & (1 << 12))) {
-		/* DDC_XFER_DONE_INT */
-		HDMI_OUTP_ND(0x0118, (hdcp_int_val | (1 << 13)) & ~(1 << 12));
-		DEV_INFO("HDCP: DDC_XFER_DONE received\n");
-		return IRQ_HANDLED;
-	}
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	/* Process CEC Interrupt */
@@ -1305,7 +1312,7 @@
 		if (external_common_state->hdmi_sink == 0) {
 			/* HDMI_DVI_SEL */
 			reg_val |= 0x00000002;
-			if (external_common_state->present_hdcp)
+			if (hdmi_msm_state->hdcp_enable)
 				/* HDMI Encryption */
 				reg_val |= 0x00000004;
 			/* HDMI_CTRL */
@@ -1313,7 +1320,7 @@
 			/* HDMI_DVI_SEL */
 			reg_val &= ~0x00000002;
 		} else {
-			if (external_common_state->present_hdcp)
+			if (hdmi_msm_state->hdcp_enable)
 				/* HDMI_Encryption_ON */
 				reg_val |= 0x00000006;
 			else
@@ -1393,7 +1400,6 @@
 	return 0;
 }
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static int hdmi_msm_ddc_write(uint32 dev_addr, uint32 offset,
 	const uint8 *data_buf, uint32 data_len, const char *what)
 {
@@ -1589,7 +1595,6 @@
 error:
 	return status;
 }
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 static int hdmi_msm_ddc_read_retry(uint32 dev_addr, uint32 offset,
 	uint8 *data_buf, uint32 data_len, uint32 request_len, int retry,
@@ -2150,9 +2155,13 @@
 	return status;
 }
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static void hdcp_auth_info(uint32 auth_info)
 {
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return;
+	}
+
 	switch (auth_info) {
 	case 0:
 		DEV_INFO("%s: None", __func__);
@@ -2187,6 +2196,11 @@
 
 static void hdcp_key_state(uint32 key_state)
 {
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return;
+	}
+
 	switch (key_state) {
 	case 0:
 		DEV_WARN("%s: No HDCP Keys", __func__);
@@ -2230,6 +2244,11 @@
 {
 	int hdcp_link_status = HDMI_INP(0x011C);
 
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return;
+	}
+
 	/* Disable HDCP interrupts */
 	HDMI_OUTP(0x0118, 0x0);
 
@@ -2257,6 +2276,11 @@
 	int failure;
 	int nack0;
 
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return;
+	}
+
 	/*
 	 * Check for any DDC transfer failures
 	 * 0x0128 HDCP_DDC_STATUS
@@ -2367,6 +2391,11 @@
 	static uint8 buf[0xFF];
 	memset(buf, 0, sizeof(buf));
 
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return 0;
+	}
+
 	if (!is_part1_done) {
 		is_part1_done = TRUE;
 
@@ -2654,6 +2683,11 @@
 	int ret;
 	uint8 buf[4];
 
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return 0;
+	}
+
 	snprintf(what, sizeof(what), "V' H0");
 	ret = hdmi_msm_ddc_read(0x74, 0x20, buf, 4, 5, what, TRUE);
 	if (ret) {
@@ -2746,6 +2780,11 @@
 
 	boolean ksv_done = FALSE;
 
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return 0;
+	}
+
 	memset(buf, 0, sizeof(buf));
 	memset(kvs_fifo, 0, sizeof(kvs_fifo));
 
@@ -2938,6 +2977,12 @@
 {
 	int ret = 0;
 	int poll = 3000;
+
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return 0;
+	}
+
 	while (poll) {
 		/* 0x011C HDCP_LINK0_STATUS
 		    [30:28]  KEYS_STATE = 3 = "Valid"
@@ -2968,7 +3013,7 @@
 	uint32 found_repeater = 0x0;
 	char *envp[2];
 
-	if (!hdmi_msm_has_hdcp()) {
+	if (!hdmi_msm_state->hdcp_enable) {
 		DEV_INFO("%s: HDCP NOT ENABLED\n", __func__);
 		return;
 	}
@@ -3069,7 +3114,6 @@
 	DEV_INFO("Hdmi state switched to %d: %s\n",
 		external_common_state->sdev.state, __func__);
 }
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 static void hdmi_msm_video_setup(int video_format)
 {
@@ -3587,11 +3631,9 @@
 {
 	msm_hdmi_sample_rate = rate;
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	if (hdmi_msm_has_hdcp())
+	if (hdmi_msm_state->hdcp_enable)
 		hdcp_deauthenticate();
 	else
-#endif
 		hdmi_msm_turn_on();
 }
 EXPORT_SYMBOL(hdmi_msm_audio_sample_rate_reset);
@@ -4161,12 +4203,10 @@
 #endif
 	hdmi_msm_spd_infoframe_packetsetup();
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	if (hdmi_msm_state->reauth) {
+	if (hdmi_msm_state->hdcp_enable && hdmi_msm_state->reauth) {
 		hdmi_msm_hdcp_enable();
 		hdmi_msm_state->reauth = FALSE ;
 	}
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	/* re-initialize CEC if enabled */
@@ -4211,12 +4251,15 @@
 	}
 }
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 static void hdmi_msm_hdcp_timer(unsigned long data)
 {
+	if (!hdmi_msm_state->hdcp_enable) {
+		DEV_DBG("%s: HDCP not enabled\n", __func__);
+		return;
+	}
+
 	queue_work(hdmi_work_queue, &hdmi_msm_state->hdcp_work);
 }
-#endif
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 static void hdmi_msm_cec_read_timer_func(unsigned long data)
@@ -4381,12 +4424,14 @@
 		mutex_unlock(&external_common_state_hpd_mutex);
 		hdmi_msm_turn_on();
 
-		/* Kick off HDCP Authentication */
-		mutex_lock(&hdcp_auth_state_mutex);
-		hdmi_msm_state->reauth = FALSE;
-		hdmi_msm_state->full_auth_done = FALSE;
-		mutex_unlock(&hdcp_auth_state_mutex);
-		mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+		if (hdmi_msm_state->hdcp_enable) {
+			/* Kick off HDCP Authentication */
+			mutex_lock(&hdcp_auth_state_mutex);
+			hdmi_msm_state->reauth = FALSE;
+			hdmi_msm_state->full_auth_done = FALSE;
+			mutex_unlock(&hdcp_auth_state_mutex);
+			mod_timer(&hdmi_msm_state->hdcp_timer, jiffies + HZ/2);
+		}
 	} else
 		mutex_unlock(&external_common_state_hpd_mutex);
 
@@ -4410,16 +4455,14 @@
 		 external_common_state->sdev.state,  __func__);
 	if (on) {
 		hdmi_msm_read_edid();
-		if (hdmi_msm_has_hdcp())
-			hdmi_msm_state->reauth = FALSE ;
+		hdmi_msm_state->reauth = FALSE ;
 		/* Build EDID table */
 		hdmi_msm_turn_on();
 		DEV_INFO("HDMI HPD: CONNECTED: send ONLINE\n");
 		kobject_uevent(external_common_state->uevent_kobj,
 			       KOBJ_ONLINE);
-		hdmi_msm_hdcp_enable();
 		envp[0] = 0;
-		if (!hdmi_msm_has_hdcp()) {
+		if (!hdmi_msm_state->hdcp_enable) {
 			/* Send Audio for HDMI Compliance Cases*/
 			envp[0] = "HDCP_STATE=PASS";
 			envp[1] = NULL;
@@ -4429,6 +4472,8 @@
 			switch_set_state(&external_common_state->sdev, 1);
 			DEV_INFO("Hdmi state switched to %d: %s\n",
 				 external_common_state->sdev.state, __func__);
+		} else {
+			hdmi_msm_hdcp_enable();
 		}
 	} else {
 		DEV_INFO("HDMI HPD: DISCONNECTED: send OFFLINE\n");
@@ -4452,7 +4497,6 @@
 	if (!hdmi_msm_state->hdmi_app_clk)
 		return -ENODEV;
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	mutex_lock(&hdmi_msm_state_mutex);
 	if (hdmi_msm_state->hdcp_activating) {
 		hdmi_msm_state->panel_power_on = FALSE;
@@ -4461,13 +4505,10 @@
 		return 0;
 	}
 	mutex_unlock(&hdmi_msm_state_mutex);
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 	DEV_INFO("power: OFF (audio off, Reset Core)\n");
 	hdmi_msm_audio_off();
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
 	hdcp_deauthenticate();
-#endif
 	hdmi_msm_powerdown_phy();
 
 	hdmi_msm_state->panel_power_on = FALSE;
@@ -4479,6 +4520,28 @@
 	return hdmi_msm_state->is_mhl_enabled;
 }
 
+void hdmi_msm_config_hdcp_feature(void)
+{
+	if (hdcp_feature_on && hdmi_msm_has_hdcp()) {
+		init_timer(&hdmi_msm_state->hdcp_timer);
+		hdmi_msm_state->hdcp_timer.function = hdmi_msm_hdcp_timer;
+		hdmi_msm_state->hdcp_timer.data = (uint32)NULL;
+		hdmi_msm_state->hdcp_timer.expires = 0xffffffffL;
+
+		init_completion(&hdmi_msm_state->hdcp_success_done);
+		INIT_WORK(&hdmi_msm_state->hdcp_reauth_work,
+				hdmi_msm_hdcp_reauth_work);
+		INIT_WORK(&hdmi_msm_state->hdcp_work, hdmi_msm_hdcp_work);
+		hdmi_msm_state->hdcp_enable = TRUE;
+	} else {
+		del_timer(&hdmi_msm_state->hdcp_timer);
+		hdmi_msm_state->hdcp_enable = FALSE;
+	}
+	external_common_state->present_hdcp = hdmi_msm_state->hdcp_enable;
+	DEV_INFO("%s: HDCP Feature: %s\n", __func__,
+			hdmi_msm_state->hdcp_enable ? "Enabled" : "Disabled");
+}
+
 static int __devinit hdmi_msm_probe(struct platform_device *pdev)
 {
 	int rc;
@@ -4591,15 +4654,6 @@
 
 	hdmi_msm_state->hpd_state_timer.expires = 0xffffffffL;
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	init_timer(&hdmi_msm_state->hdcp_timer);
-	hdmi_msm_state->hdcp_timer.function =
-		hdmi_msm_hdcp_timer;
-	hdmi_msm_state->hdcp_timer.data = (uint32)NULL;
-
-	hdmi_msm_state->hdcp_timer.expires = 0xffffffffL;
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
-
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	init_timer(&hdmi_msm_state->cec_read_timer);
 	hdmi_msm_state->cec_read_timer.function =
@@ -4626,22 +4680,7 @@
 			goto error;
 	}
 
-	if (hdmi_msm_has_hdcp()) {
-		/* Don't Set Encryption in case of non HDCP builds */
-		external_common_state->present_hdcp = FALSE;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-		external_common_state->present_hdcp = TRUE;
-#endif
-	} else {
-		external_common_state->present_hdcp = FALSE;
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-		/*
-		 * If the device is not hdcp capable do
-		 * not start hdcp timer.
-		 */
-		del_timer(&hdmi_msm_state->hdcp_timer);
-#endif
-	}
+	hdmi_msm_config_hdcp_feature();
 
 	/* Initialize hdmi node and register with switch driver */
 	if (hdmi_prim_display)
@@ -4825,11 +4864,6 @@
 	hdmi_common_init_panel_info(&hdmi_msm_panel_data.panel_info);
 	init_completion(&hdmi_msm_state->ddc_sw_done);
 	INIT_WORK(&hdmi_msm_state->hpd_state_work, hdmi_msm_hpd_state_work);
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-	init_completion(&hdmi_msm_state->hdcp_success_done);
-	INIT_WORK(&hdmi_msm_state->hdcp_reauth_work, hdmi_msm_hdcp_reauth_work);
-	INIT_WORK(&hdmi_msm_state->hdcp_work, hdmi_msm_hdcp_work);
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	INIT_WORK(&hdmi_msm_state->cec_latch_detect_work,
@@ -4853,9 +4887,6 @@
 		" RELEASE"
 #endif
 		" AUDIO EDID HPD HDCP"
-#ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
-		":0"
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 		" DVI"
 #ifndef CONFIG_FB_MSM_HDMI_MSM_PANEL_DVI_SUPPORT
 		":0"
@@ -4885,6 +4916,15 @@
 		return rv;
 
 	pr_debug("%s: HDCP feature = %d\n", __func__, hdcp_feature_on);
+	if (hdmi_msm_state) {
+		if ((HDMI_INP(0x0250) & 0x2)) {
+			pr_err("%s: Unable to set HDCP feature", __func__);
+			pr_err("%s: HDMI panel is currently turned on",
+					__func__);
+		} else if (hdcp_feature_on != hdmi_msm_state->hdcp_enable) {
+			hdmi_msm_config_hdcp_feature();
+		}
+	}
 
 	return 0;
 }
diff --git a/drivers/video/msm/hdmi_msm.h b/drivers/video/msm/hdmi_msm.h
index 5d27412..20bd492 100644
--- a/drivers/video/msm/hdmi_msm.h
+++ b/drivers/video/msm/hdmi_msm.h
@@ -64,13 +64,12 @@
 	struct timer_list hpd_state_timer;
 	struct completion ddc_sw_done;
 
-#ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT
+	bool hdcp_enable;
 	boolean hdcp_activating;
 	boolean reauth ;
 	struct work_struct hdcp_reauth_work, hdcp_work;
 	struct completion hdcp_success_done;
 	struct timer_list hdcp_timer;
-#endif /* CONFIG_FB_MSM_HDMI_MSM_PANEL_HDCP_SUPPORT */
 
 #ifdef CONFIG_FB_MSM_HDMI_MSM_PANEL_CEC_SUPPORT
 	boolean cec_enabled;
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index c36e4b4..6c0d08d 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -184,7 +184,7 @@
 		base = 0x18000;
 		break;
 	case MDP_BLOCK_OVERLAY_2:
-		base = (mdp_rev >= MDP_REV_44) ? 0x88000 : 0;
+		base = (mdp_rev >= MDP_REV_43) ? 0x88000 : 0;
 		break;
 	default:
 		break;
@@ -2525,6 +2525,7 @@
 #endif
 	static int contSplash_update_done;
 	char *cp;
+	unsigned int mdp_r = 0;
 
 	if ((pdev->id == 0) && (pdev->num_resources > 0)) {
 		mdp_init_pdev = pdev;
@@ -2546,6 +2547,15 @@
 		}
 
 		mdp_rev = mdp_pdata->mdp_rev;
+		if (mdp_rev == MDP_REV_42) {
+			mdp_r = inpdw(MDP_BASE + 0x0);
+			mdp_r = ((mdp_r & 0x30000) >> 16);
+			if (mdp_r == 3) {
+				mdp_rev = MDP_REV_43;
+				mdp_pdata->mdp_rev = MDP_REV_43;
+			}
+		}
+
 		mdp_iommu_split_domain = mdp_pdata->mdp_iommu_split_domain;
 
 		rc = mdp_irq_clk_setup(pdev, mdp_pdata->cont_splash_enabled);
diff --git a/drivers/video/msm/mdp4.h b/drivers/video/msm/mdp4.h
index 005e87c..b7d4c32 100644
--- a/drivers/video/msm/mdp4.h
+++ b/drivers/video/msm/mdp4.h
@@ -349,7 +349,7 @@
 	uint32 ov_cnt;
 	uint32 dmap_cnt;
 	uint32 dmae_cnt;
-	uint32 blt_end;
+	uint32 blt_end;	/* used by mddi only */
 	uint32 blt_ov_koff;
 	uint32 blt_ov_done;
 	uint32 blt_dmap_koff;
@@ -543,12 +543,9 @@
 void mdp4_overlay0_done_dsi_cmd(int cndx);
 void mdp4_primary_rdptr(void);
 void mdp4_dsi_cmd_overlay(struct msm_fb_data_type *mfd);
-int mdp4_overlay_commit(struct fb_info *info, int mixer);
-int mdp4_dsi_video_pipe_commit(void);
-int mdp4_dsi_cmd_pipe_commit(void);
+int mdp4_lcdc_pipe_commit(int cndx, int wait);
+int mdp4_dtv_pipe_commit(int cndx, int wait);
 int mdp4_dsi_cmd_update_cnt(int cndx);
-int mdp4_lcdc_pipe_commit(void);
-int mdp4_dtv_pipe_commit(void);
 void mdp4_dsi_rdptr_init(int cndx);
 void mdp4_dsi_vsync_init(int cndx);
 void mdp4_lcdc_vsync_init(int cndx);
@@ -577,6 +574,7 @@
 int mdp4_overlay_play_wait(struct fb_info *info,
 	struct msmfb_overlay_data *req);
 int mdp4_overlay_play(struct fb_info *info, struct msmfb_overlay_data *req);
+int mdp4_overlay_commit(struct fb_info *info, int mixer);
 struct mdp4_overlay_pipe *mdp4_overlay_pipe_alloc(int ptype, int mixer);
 void mdp4_overlay_dma_commit(int mixer);
 void mdp4_overlay_vsync_commit(struct mdp4_overlay_pipe *pipe);
@@ -763,6 +761,8 @@
 void mdp4_dsi_video_wait4vsync(int cndx, long long *vtime);
 void mdp4_dsi_cmd_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
 void mdp4_dsi_video_pipe_queue(int cndx, struct mdp4_overlay_pipe *pipe);
+int mdp4_dsi_video_pipe_commit(int cndx, int wait);
+int mdp4_dsi_cmd_pipe_commit(int cndx, int wait);
 void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info, int enable);
 void mdp4_dsi_video_vsync_ctrl(struct fb_info *info, int enable);
 #ifdef CONFIG_FB_MSM_MDP303
@@ -812,6 +812,14 @@
 			struct mdp4_overlay_pipe *pipe)
 {
 }
+static inline int mdp4_dsi_video_pipe_commit(int cndx, int wait)
+{
+	return 0;
+}
+static inline int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
+{
+	return 0;
+}
 static inline void mdp4_dsi_cmd_vsync_ctrl(struct fb_info *info,
 				int enable)
 {
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index b154a3b..8f308c3 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -1992,7 +1992,8 @@
 		blend->bg_alpha = 0x0ff - s_pipe->alpha;
 		blend->fg_alpha = s_pipe->alpha;
 		blend->co3_sel = 1; /* use fg alpha */
-
+		pr_debug("%s: bg alpha %d, fg alpha %d\n",
+			__func__, blend->bg_alpha, blend->fg_alpha);
 		if (s_pipe->is_fg) {
 			if (s_pipe->alpha == 0xff) {
 				blend->solidfill = 1;
@@ -2008,10 +2009,9 @@
 						MDP4_BLEND_FG_ALPHA_FG_PIXEL;
 				else
 					blend->fg_alpha = 0xff;
+				blend->op |= MDP4_BLEND_BG_INV_ALPHA;
 			} else
 				blend->op = MDP4_BLEND_BG_ALPHA_FG_CONST;
-
-			blend->op |= MDP4_BLEND_BG_INV_ALPHA;
 		} else if (d_alpha) {
 			ptype = mdp4_overlay_format2type(s_pipe->src_format);
 			if (ptype == OVERLAY_TYPE_VIDEO) {
@@ -3464,8 +3464,7 @@
 		if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
 			/* cndx = 0 */
 			mdp4_dsi_cmd_pipe_queue(0, pipe);
-		}
-		if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+		} else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
 			/* cndx = 0 */
 			mdp4_dsi_video_pipe_queue(0, pipe);
 		} else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
@@ -3527,6 +3526,46 @@
 	return ret;
 }
 
+int mdp4_overlay_commit(struct fb_info *info, int mixer)
+{
+	struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+	if (mfd == NULL)
+		return -ENODEV;
+
+	if (!mfd->panel_power_on) /* suspended */
+		return -EINVAL;
+
+	if (mixer >= MDP4_MIXER_MAX)
+		return -EPERM;
+
+	mutex_lock(&mfd->dma->ov_mutex);
+
+	mdp4_overlay_mdp_perf_upd(mfd, 1);
+
+	if (mixer == MDP4_MIXER0) {
+		if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
+			/* cndx = 0 */
+			mdp4_dsi_cmd_pipe_commit(0, 1);
+		} else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
+			/* cndx = 0 */
+			mdp4_dsi_video_pipe_commit(0, 1);
+		} else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
+			/* cndx = 0 */
+			mdp4_lcdc_pipe_commit(0, 1);
+		}
+	} else if (mixer == MDP4_MIXER1) {
+		if (ctrl->panel_mode & MDP4_PANEL_DTV)
+			mdp4_dtv_pipe_commit(0, 1);
+	}
+
+	mdp4_overlay_mdp_perf_upd(mfd, 0);
+
+	mutex_unlock(&mfd->dma->ov_mutex);
+
+	return 0;
+}
+
 struct msm_iommu_ctx {
 	char *name;
 	int  domain;
diff --git a/drivers/video/msm/mdp4_overlay_dsi_cmd.c b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
index 488f2af..6fb9dc4 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_cmd.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_cmd.c
@@ -250,7 +250,7 @@
 
 static void mdp4_dsi_cmd_blt_ov_update(struct mdp4_overlay_pipe *pipe);
 
-int mdp4_dsi_cmd_pipe_commit(void)
+int mdp4_dsi_cmd_pipe_commit(int cndx, int wait)
 {
 	int  i, undx;
 	int mixer = 0;
@@ -377,6 +377,12 @@
 
 	mdp4_stat.overlay_commit[pipe->mixer_num]++;
 
+	if (wait) {
+		long long tick;
+
+		mdp4_dsi_cmd_wait4vsync(cndx, &tick);
+	}
+
 	return cnt;
 }
 
@@ -1016,6 +1022,8 @@
 	struct msm_fb_data_type *mfd;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	struct vsync_update *vp;
+	int undx;
 
 	pr_debug("%s+:\n", __func__);
 
@@ -1048,6 +1056,16 @@
 		mdp_clk_ctrl(0);
 	}
 
+	undx =  vctrl->update_ndx;
+	vp = &vctrl->vlist[undx];
+	if (vp->update_cnt) {
+		/*
+		 * pipe's iommu will be freed at next overlay play
+		 * and iommu_drop statistic will be increased by one
+		 */
+		vp->update_cnt = 0;     /* empty queue */
+	}
+
 	vctrl->clk_enabled = 0;
 	vctrl->vsync_enabled = 0;
 	vctrl->clk_control = 0;
@@ -1099,6 +1117,7 @@
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
 	unsigned long flags;
+	long long tick;
 
 	vctrl = &vsync_ctrl_db[cndx];
 
@@ -1139,8 +1158,10 @@
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 
 	mutex_lock(&mfd->dma->ov_mutex);
-	mdp4_dsi_cmd_pipe_commit();
+	mdp4_dsi_cmd_pipe_commit(cndx, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
 
+	mdp4_dsi_cmd_wait4vsync(cndx, &tick);
+
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 }
diff --git a/drivers/video/msm/mdp4_overlay_dsi_video.c b/drivers/video/msm/mdp4_overlay_dsi_video.c
index 6c9edb5..04f59f6 100644
--- a/drivers/video/msm/mdp4_overlay_dsi_video.c
+++ b/drivers/video/msm/mdp4_overlay_dsi_video.c
@@ -147,7 +147,7 @@
 static void mdp4_dsi_video_wait4dmap(int cndx);
 static void mdp4_dsi_video_wait4ov(int cndx);
 
-int mdp4_dsi_video_pipe_commit(void)
+int mdp4_dsi_video_pipe_commit(int cndx, int wait)
 {
 
 	int  i, undx;
@@ -159,7 +159,7 @@
 	unsigned long flags;
 	int cnt = 0;
 
-	vctrl = &vsync_ctrl_db[0];
+	vctrl = &vsync_ctrl_db[cndx];
 
 	mutex_lock(&vctrl->update_lock);
 	undx =  vctrl->update_ndx;
@@ -253,6 +253,13 @@
 
 	mdp4_stat.overlay_commit[pipe->mixer_num]++;
 
+	if (wait) {
+		if (pipe->ov_blt_addr)
+			mdp4_dsi_video_wait4ov(cndx);
+		else
+			mdp4_dsi_video_wait4dmap(cndx);
+	}
+
 	return cnt;
 }
 
@@ -682,8 +689,9 @@
 	struct msm_fb_data_type *mfd;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	struct vsync_update *vp;
 	unsigned long flags;
-	int need_wait = 0;
+	int undx, need_wait = 0;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 	vctrl = &vsync_ctrl_db[cndx];
@@ -716,6 +724,16 @@
 		vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
 	}
 
+	undx =  vctrl->update_ndx;
+	vp = &vctrl->vlist[undx];
+	if (vp->update_cnt) {
+		/*
+		 * pipe's iommu will be freed at next overlay play
+		 * and iommu_drop statistic will be increased by one
+		 */
+		vp->update_cnt = 0;     /* empty queue */
+	}
+
 	if (pipe) {
 		/* sanity check, free pipes besides base layer */
 		mdp4_overlay_unset_mixer(pipe->mixer_num);
@@ -1075,13 +1093,13 @@
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 
 	mutex_lock(&mfd->dma->ov_mutex);
-	mdp4_dsi_video_pipe_commit();
+	mdp4_dsi_video_pipe_commit(cndx, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
 
 	if (pipe->ov_blt_addr)
-		mdp4_dsi_video_wait4ov(0);
+		mdp4_dsi_video_wait4ov(cndx);
 	else
-		mdp4_dsi_video_wait4dmap(0);
+		mdp4_dsi_video_wait4dmap(cndx);
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 }
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index a89b5be..50f9eb0 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -165,7 +165,7 @@
 static void mdp4_dtv_blt_ov_update(struct mdp4_overlay_pipe *pipe);
 static void mdp4_dtv_wait4dmae(int cndx);
 
-int mdp4_dtv_pipe_commit(void)
+int mdp4_dtv_pipe_commit(int cndx, int wait)
 {
 
 	int  i, undx;
@@ -177,7 +177,7 @@
 	unsigned long flags;
 	int cnt = 0;
 
-	vctrl = &vsync_ctrl_db[0];
+	vctrl = &vsync_ctrl_db[cndx];
 	mutex_lock(&vctrl->update_lock);
 	undx =  vctrl->update_ndx;
 	vp = &vctrl->vlist[undx];
@@ -236,6 +236,9 @@
 	spin_unlock_irqrestore(&vctrl->spin_lock, flags);
 	mdp4_stat.overlay_commit[pipe->mixer_num]++;
 
+	if (wait)
+		mdp4_dtv_wait4dmae(cndx);
+
 	return cnt;
 }
 
@@ -594,8 +597,10 @@
 	struct msm_fb_data_type *mfd;
 	int ret = 0;
 	int cndx = 0;
+	int undx;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	struct vsync_update *vp;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 
@@ -641,6 +646,16 @@
 		vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
 	}
 
+	undx =  vctrl->update_ndx;
+	vp = &vctrl->vlist[undx];
+	if (vp->update_cnt) {
+		/*
+		 * pipe's iommu will be freed at next overlay play
+		 * and iommu_drop statistic will be increased by one
+		 */
+		vp->update_cnt = 0;     /* empty queue */
+	}
+
 	ret = panel_next_off(pdev);
 	mdp_footswitch_ctrl(FALSE);
 
@@ -1060,7 +1075,7 @@
 
 	mutex_lock(&mfd->dma->ov_mutex);
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
-	mdp4_dtv_pipe_commit();
+	mdp4_dtv_pipe_commit(cndx, 0);
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
 }
diff --git a/drivers/video/msm/mdp4_overlay_lcdc.c b/drivers/video/msm/mdp4_overlay_lcdc.c
index 78c69b8..8796334 100644
--- a/drivers/video/msm/mdp4_overlay_lcdc.c
+++ b/drivers/video/msm/mdp4_overlay_lcdc.c
@@ -152,7 +152,7 @@
 static void mdp4_lcdc_wait4dmap(int cndx);
 static void mdp4_lcdc_wait4ov(int cndx);
 
-int mdp4_lcdc_pipe_commit(void)
+int mdp4_lcdc_pipe_commit(int cndx, int wait)
 {
 
 	int  i, undx;
@@ -164,7 +164,7 @@
 	unsigned long flags;
 	int cnt = 0;
 
-	vctrl = &vsync_ctrl_db[0];
+	vctrl = &vsync_ctrl_db[cndx];
 
 	mutex_lock(&vctrl->update_lock);
 	undx =  vctrl->update_ndx;
@@ -257,6 +257,13 @@
 
 	mdp4_stat.overlay_commit[pipe->mixer_num]++;
 
+	if (wait) {
+		if (pipe->ov_blt_addr)
+			mdp4_lcdc_wait4ov(cndx);
+		else
+			mdp4_lcdc_wait4dmap(cndx);
+	}
+
 	return cnt;
 }
 
@@ -666,8 +673,9 @@
 	struct msm_fb_data_type *mfd;
 	struct vsycn_ctrl *vctrl;
 	struct mdp4_overlay_pipe *pipe;
+	struct vsync_update *vp;
 	unsigned long flags;
-	int need_wait = 0;
+	int undx, need_wait = 0;
 
 	mfd = (struct msm_fb_data_type *)platform_get_drvdata(pdev);
 	vctrl = &vsync_ctrl_db[cndx];
@@ -700,6 +708,16 @@
 		vsync_irq_disable(INTR_PRIMARY_VSYNC, MDP_PRIM_VSYNC_TERM);
 	}
 
+	undx =  vctrl->update_ndx;
+	vp = &vctrl->vlist[undx];
+	if (vp->update_cnt) {
+		/*
+		 * pipe's iommu will be freed at next overlay play
+		 * and iommu_drop statistic will be increased by one
+		 */
+		vp->update_cnt = 0;     /* empty queue */
+	}
+
 	if (pipe) {
 		/* sanity check, free pipes besides base layer */
 		mdp4_overlay_unset_mixer(pipe->mixer_num);
@@ -962,13 +980,13 @@
 	mdp4_overlay_mdp_perf_upd(mfd, 1);
 
 	mutex_lock(&mfd->dma->ov_mutex);
-	mdp4_lcdc_pipe_commit();
+	mdp4_lcdc_pipe_commit(cndx, 0);
 	mutex_unlock(&mfd->dma->ov_mutex);
 
 	if (pipe->ov_blt_addr)
-		mdp4_lcdc_wait4ov(0);
+		mdp4_lcdc_wait4ov(cndx);
 	else
-		mdp4_lcdc_wait4dmap(0);
+		mdp4_lcdc_wait4dmap(cndx);
 
 	mdp4_overlay_mdp_perf_upd(mfd, 0);
 }
diff --git a/drivers/video/msm/mdp4_util.c b/drivers/video/msm/mdp4_util.c
index 80ef22a..87921e6 100644
--- a/drivers/video/msm/mdp4_util.c
+++ b/drivers/video/msm/mdp4_util.c
@@ -110,21 +110,22 @@
 	.csc_data = {
 			(0),
 			{
-				0x0200, 0x0000, 0x0000,
-				0x0000, 0x0200, 0x0000,
-				0x0000, 0x0000, 0x0200,
+				0x0083, 0x0102, 0x0032,
+				0x1fb5, 0x1f6c, 0x00e1,
+				0x00e1, 0x1f45, 0x1fdc,
 			},
 			{
 				0x0, 0x0, 0x0,
 			},
 			{
-				0, 0, 0,
+				0x0010, 0x0080, 0x0080,
 			},
 			{
 				0, 0xff, 0, 0xff, 0, 0xff,
 			},
 			{
-				0, 0xff, 0, 0xff, 0, 0xff,
+				0x0010, 0x00eb, 0x0010,
+				0x00f0, 0x0010, 0x00f0,
 			},
 		},
 	},
@@ -133,21 +134,22 @@
 	.csc_data = {
 			(0),
 			{
-				0x0200, 0x0000, 0x0000,
-				0x0000, 0x0200, 0x0000,
-				0x0000, 0x0000, 0x0200,
+				0x0083, 0x0102, 0x0032,
+				0x1fb5, 0x1f6c, 0x00e1,
+				0x00e1, 0x1f45, 0x1fdc,
 			},
 			{
 				0x0, 0x0, 0x0,
 			},
 			{
-				0, 0, 0,
+				0x0010, 0x0080, 0x0080,
 			},
 			{
 				0, 0xff, 0, 0xff, 0, 0xff,
 			},
 			{
-				0, 0xff, 0, 0xff, 0, 0xff,
+				0x0010, 0x00eb, 0x0010,
+				0x00f0, 0x0010, 0x00f0,
 			},
 		},
 	},
@@ -176,7 +178,6 @@
 	},
 };
 
-
 unsigned is_mdp4_hw_reset(void)
 {
 	unsigned hw_reset = 0;
@@ -2138,7 +2139,7 @@
 		base = 0x1A000;
 		break;
 	case MDP_BLOCK_OVERLAY_2:
-		base = (mdp_rev >= MDP_REV_44) ? 0x8A000 : 0x0;
+		base = (mdp_rev >= MDP_REV_43) ? 0x8A000 : 0x0;
 		break;
 	case MDP_BLOCK_VG_1:
 		base = 0x24000;
@@ -2658,7 +2659,7 @@
 		break;
 
 	case MDP_BLOCK_OVERLAY_2:
-		valid = (mdp_rev >= MDP_REV_44) ? 1 : 0;
+		valid = (mdp_rev >= MDP_REV_43) ? 1 : 0;
 		break;
 
 	default:
diff --git a/drivers/video/msm/mdss/mdss_mdp_ctl.c b/drivers/video/msm/mdss/mdss_mdp_ctl.c
index 161f54a..5966989 100644
--- a/drivers/video/msm/mdss/mdss_mdp_ctl.c
+++ b/drivers/video/msm/mdss/mdss_mdp_ctl.c
@@ -351,6 +351,7 @@
 {
 	struct mdss_mdp_ctl *ctl;
 	u32 width, height;
+	int ret = 0;
 
 	if (!mfd)
 		return -ENODEV;
@@ -363,23 +364,30 @@
 		return -EINVAL;
 	}
 
-	ctl = mdss_mdp_ctl_alloc();
-
-	if (!ctl) {
-		pr_err("unable to allocate ctl\n");
-		return -ENOMEM;
+	if (!mfd->ctl) {
+		ctl = mdss_mdp_ctl_alloc();
+		if (!ctl) {
+			pr_err("unable to allocate ctl\n");
+			return -ENOMEM;
+		}
+		ctl->mfd = mfd;
+		mfd->ctl = ctl;
+	} else {
+		ctl = mfd->ctl;
 	}
 
-	ctl->mfd = mfd;
 	ctl->width = width;
 	ctl->height = height;
 	ctl->dst_format = mfd->panel_info.out_format;
 
-	ctl->mixer_left = mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
 	if (!ctl->mixer_left) {
-		pr_err("unable to allocate layer mixer\n");
-		mdss_mdp_ctl_free(ctl);
-		return -ENOMEM;
+		ctl->mixer_left =
+			mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+		if (!ctl->mixer_left) {
+			pr_err("unable to allocate layer mixer\n");
+			ret = -ENOMEM;
+			goto ctl_init_fail;
+		}
 	}
 
 	if (width > MAX_MIXER_WIDTH)
@@ -390,17 +398,20 @@
 	ctl->mixer_left->ctl = ctl;
 
 	if (width < ctl->width) {
-		ctl->mixer_right =
-			mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
-		if (!ctl->mixer_right) {
-			pr_err("unable to allocate right layer mixer\n");
-			mdss_mdp_mixer_free(ctl->mixer_left);
-			mdss_mdp_ctl_free(ctl);
-			return -ENOMEM;
+		if (ctl->mixer_right == NULL) {
+			ctl->mixer_right =
+				mdss_mdp_mixer_alloc(MDSS_MDP_MIXER_TYPE_INTF);
+			if (!ctl->mixer_right) {
+				pr_err("unable to allocate right mixer\n");
+				ret = -ENOMEM;
+				goto ctl_init_fail;
+			}
 		}
 		ctl->mixer_right->width = width;
 		ctl->mixer_right->height = height;
 		ctl->mixer_right->ctl = ctl;
+	} else if (ctl->mixer_right) {
+		mdss_mdp_mixer_free(ctl->mixer_right);
 	}
 
 	switch (mfd->panel_info.type) {
@@ -432,9 +443,8 @@
 		break;
 	default:
 		pr_err("unsupported panel type (%d)\n", mfd->panel_info.type);
-		mdss_mdp_ctl_free(ctl);
-		return -EINVAL;
-
+		ret = -EINVAL;
+		goto ctl_init_fail;
 	}
 
 	ctl->opmode |= (ctl->intf_num << 4);
@@ -444,9 +454,17 @@
 			       MDSS_MDP_CTL_OP_PACK_3D_H_ROW_INT;
 	}
 
-	mfd->ctl = ctl;
+ctl_init_fail:
+	if (IS_ERR_VALUE(ret)) {
+		if (ctl->mixer_left)
+			mdss_mdp_mixer_free(ctl->mixer_left);
+		if (ctl->mixer_right)
+			mdss_mdp_mixer_free(ctl->mixer_right);
+		mdss_mdp_ctl_free(ctl);
+		mfd->ctl = NULL;
+	}
 
-	return 0;
+	return ret;
 }
 
 static int mdss_mdp_ctl_destroy(struct msm_fb_data_type *mfd)
@@ -487,12 +505,11 @@
 		return -ENODEV;
 	}
 
-	if (!mfd->ctl) {
-		if (mdss_mdp_ctl_init(mfd)) {
-			pr_err("unable to initialize ctl\n");
-			return -ENODEV;
-		}
+	if (mdss_mdp_ctl_init(mfd)) {
+		pr_err("unable to initialize ctl\n");
+		return -ENODEV;
 	}
+
 	ctl = mfd->ctl;
 
 	if (ctl->power_on) {
diff --git a/drivers/video/msm/mdss/mdss_mdp_overlay.c b/drivers/video/msm/mdss/mdss_mdp_overlay.c
index f70ef91..f76b508 100644
--- a/drivers/video/msm/mdss/mdss_mdp_overlay.c
+++ b/drivers/video/msm/mdss/mdss_mdp_overlay.c
@@ -326,7 +326,6 @@
 	}
 
 	pipe->params_changed++;
-	pipe->play_cnt = 0;
 
 	req->id = pipe->ndx;
 
@@ -704,7 +703,6 @@
 	fbi = mfd->fbi;
 
 	if (fbi->fix.smem_len == 0) {
-		pr_warn("fb memory not allocated\n");
 		mdss_mdp_overlay_kickoff(mfd->ctl);
 		return;
 	}
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 9f05a6a..1994b1b 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -2961,6 +2961,19 @@
 	return ret;
 }
 
+static int msmfb_overlay_commit(struct fb_info *info, unsigned long *argp)
+{
+	int ret, ndx;
+
+	ret = copy_from_user(&ndx, argp, sizeof(ndx));
+	if (ret) {
+		pr_err("%s: ioctl failed\n", __func__);
+		return ret;
+	}
+
+	return mdp4_overlay_commit(info, ndx);
+}
+
 static int msmfb_overlay_play(struct fb_info *info, unsigned long *argp)
 {
 	int	ret;
@@ -3388,6 +3401,11 @@
 	case MSMFB_OVERLAY_UNSET:
 		ret = msmfb_overlay_unset(info, argp);
 		break;
+	case MSMFB_OVERLAY_COMMIT:
+		down(&msm_fb_ioctl_ppp_sem);
+		ret = msmfb_overlay_commit(info, argp);
+		up(&msm_fb_ioctl_ppp_sem);
+		break;
 	case MSMFB_OVERLAY_PLAY:
 		ret = msmfb_overlay_play(info, argp);
 		break;
diff --git a/include/linux/msm_mdp.h b/include/linux/msm_mdp.h
index 861084a..1cdc434 100644
--- a/include/linux/msm_mdp.h
+++ b/include/linux/msm_mdp.h
@@ -71,6 +71,8 @@
 #define MSMFB_OVERLAY_VSYNC_CTRL _IOW(MSMFB_IOCTL_MAGIC, 160, unsigned int)
 #define MSMFB_VSYNC_CTRL  _IOW(MSMFB_IOCTL_MAGIC, 161, unsigned int)
 #define MSMFB_METADATA_SET  _IOW(MSMFB_IOCTL_MAGIC, 162, struct msmfb_metadata)
+#define MSMFB_OVERLAY_COMMIT      _IOW(MSMFB_IOCTL_MAGIC, 163, unsigned int)
+
 #define FB_TYPE_3D_PANEL 0x10101010
 #define MDP_IMGTYPE2_START 0x10000
 #define MSMFB_DRIVER_VERSION	0xF9E8D701
diff --git a/include/media/vcap_fmt.h b/include/media/vcap_fmt.h
index 2641720..3b1bd7c2 100644
--- a/include/media/vcap_fmt.h
+++ b/include/media/vcap_fmt.h
@@ -13,6 +13,7 @@
 
 #ifndef VCAP_FMT_H
 #define VCAP_FMT_H
+#include <linux/videodev2.h>
 
 #define V4L2_BUF_TYPE_INTERLACED_IN_DECODER (V4L2_BUF_TYPE_PRIVATE)
 
diff --git a/sound/soc/msm/apq8064-i2s.c b/sound/soc/msm/apq8064-i2s.c
index 6b5314a..e309370 100644
--- a/sound/soc/msm/apq8064-i2s.c
+++ b/sound/soc/msm/apq8064-i2s.c
@@ -2690,7 +2690,8 @@
 
 static void __exit msm_audio_exit(void)
 {
-	if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
+	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
+				 (socinfo_get_id() == 130)) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/apq8064.c b/sound/soc/msm/apq8064.c
index c8cf681..b921df1 100644
--- a/sound/soc/msm/apq8064.c
+++ b/sound/soc/msm/apq8064.c
@@ -2101,7 +2101,8 @@
 {
 	int ret;
 	u32	version = socinfo_get_platform_version();
-	if (!cpu_is_apq8064() || (socinfo_get_id() == 130) ||
+	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
+		(socinfo_get_id() == 130) ||
 		(machine_is_apq8064_mtp() &&
 		(SOCINFO_VERSION_MINOR(version) == 1))) {
 		pr_info("%s: Not APQ8064 in SLIMBUS mode\n", __func__);
@@ -2141,7 +2142,8 @@
 
 static void __exit msm_audio_exit(void)
 {
-	if (!cpu_is_apq8064() || (socinfo_get_id() == 130)) {
+	if (!(cpu_is_apq8064() || cpu_is_apq8064ab()) ||
+				 (socinfo_get_id() == 130)) {
 		pr_err("%s: Not the right machine type\n", __func__);
 		return ;
 	}
diff --git a/sound/soc/msm/mpq8064.c b/sound/soc/msm/mpq8064.c
index 957b656..3cb7c58 100644
--- a/sound/soc/msm/mpq8064.c
+++ b/sound/soc/msm/mpq8064.c
@@ -45,6 +45,11 @@
 #define TOP_SPK_AMP_POS		0x4
 #define TOP_SPK_AMP_NEG		0x8
 
+#define GPIO_AUX_PCM_DOUT 43
+#define GPIO_AUX_PCM_DIN  44
+#define GPIO_AUX_PCM_SYNC 45
+#define GPIO_AUX_PCM_CLK  46
+
 #define TABLA_EXT_CLK_RATE 12288000
 
 #define TABLA_MBHC_DEF_BUTTONS 8
@@ -942,6 +947,78 @@
 	return ret;
 }
 
+static int mpq8064_auxpcm_be_params_fixup(struct snd_soc_pcm_runtime *rtd,
+					struct snd_pcm_hw_params *params)
+{
+	struct snd_interval *rate = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_RATE);
+
+	struct snd_interval *channels = hw_param_interval(params,
+					SNDRV_PCM_HW_PARAM_CHANNELS);
+
+	/* PCM only supports mono output with 8khz sample rate */
+	rate->min = rate->max = 8000;
+	channels->min = channels->max = 1;
+
+	return 0;
+}
+
+static int mpq8064_aux_pcm_get_gpios(void)
+{
+	int ret = 0;
+
+	pr_debug("%s\n", __func__);
+
+	ret = gpio_request(GPIO_AUX_PCM_DOUT, "AUX PCM DOUT");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM DOUT",
+				__func__, GPIO_AUX_PCM_DOUT);
+		goto fail_dout;
+	}
+
+	ret = gpio_request(GPIO_AUX_PCM_DIN, "AUX PCM DIN");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM DIN",
+				__func__, GPIO_AUX_PCM_DIN);
+		goto fail_din;
+	}
+
+	ret = gpio_request(GPIO_AUX_PCM_SYNC, "AUX PCM SYNC");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM SYNC",
+				__func__, GPIO_AUX_PCM_SYNC);
+		goto fail_sync;
+	}
+	ret = gpio_request(GPIO_AUX_PCM_CLK, "AUX PCM CLK");
+	if (ret < 0) {
+		pr_err("%s: Failed to request gpio(%d): AUX PCM CLK",
+				__func__, GPIO_AUX_PCM_CLK);
+		goto fail_clk;
+	}
+
+	return 0;
+
+fail_clk:
+	gpio_free(GPIO_AUX_PCM_SYNC);
+fail_sync:
+	gpio_free(GPIO_AUX_PCM_DIN);
+fail_din:
+	gpio_free(GPIO_AUX_PCM_DOUT);
+fail_dout:
+
+	return ret;
+}
+
+static int mpq8064_aux_pcm_free_gpios(void)
+{
+	gpio_free(GPIO_AUX_PCM_DIN);
+	gpio_free(GPIO_AUX_PCM_DOUT);
+	gpio_free(GPIO_AUX_PCM_SYNC);
+	gpio_free(GPIO_AUX_PCM_CLK);
+
+	return 0;
+}
+
 static int msm_startup(struct snd_pcm_substream *substream)
 {
 	pr_debug("%s(): substream = %s  stream = %d\n", __func__,
@@ -955,12 +1032,39 @@
 		 substream->name, substream->stream);
 }
 
+static int mpq8064_auxpcm_startup(struct snd_pcm_substream *substream)
+{
+	int ret = 0;
+
+	pr_debug("%s(): substream = %s\n", __func__, substream->name);
+	ret = mpq8064_aux_pcm_get_gpios();
+	if (ret < 0) {
+		pr_err("%s: Aux PCM GPIO request failed\n", __func__);
+		return -EINVAL;
+	}
+	return 0;
+}
+
+static void mpq8064_auxpcm_shutdown(struct snd_pcm_substream *substream)
+{
+
+	pr_debug("%s(): substream = %s\n", __func__, substream->name);
+	mpq8064_aux_pcm_free_gpios();
+}
+
+
 static struct snd_soc_ops msm_be_ops = {
 	.startup = msm_startup,
 	.hw_params = msm_hw_params,
 	.shutdown = msm_shutdown,
 };
 
+static struct snd_soc_ops mpq8064_auxpcm_be_ops = {
+	.startup = mpq8064_auxpcm_startup,
+	.shutdown = mpq8064_auxpcm_shutdown,
+};
+
+
 static int mpq8064_sec_i2s_rx_free_gpios(void)
 {
 	int	i;
@@ -1270,6 +1374,20 @@
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
 	},
+	{
+		.name = "AUXPCM Hostless",
+		.stream_name = "AUXPCM Hostless",
+		.cpu_dai_name	= "AUXPCM_HOSTLESS",
+		.platform_name	= "msm-pcm-hostless",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+				SND_SOC_DPCM_TRIGGER_POST},
+		.no_host_mode = SND_SOC_DAI_LINK_NO_HOST,
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1, /* dainlink has playback support */
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+	},
 	/* Secondary I2S RX Hostless */
 	{
 		.name = "SEC_I2S_RX Hostless",
@@ -1451,6 +1569,31 @@
 		.no_pcm = 1,
 		.be_id = MSM_BACKEND_DAI_AFE_PCM_TX,
 	},
+	/* AUX PCM Backend DAI Links */
+	{
+		.name = LPASS_BE_AUXPCM_RX,
+		.stream_name = "AUX PCM Playback",
+		.cpu_dai_name = "msm-dai-q6.2",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-rx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AUXPCM_RX,
+		.be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
+		.ops = &mpq8064_auxpcm_be_ops,
+		.ignore_pmdown_time = 1,
+	},
+	{
+		.name = LPASS_BE_AUXPCM_TX,
+		.stream_name = "AUX PCM Capture",
+		.cpu_dai_name = "msm-dai-q6.3",
+		.platform_name = "msm-pcm-routing",
+		.codec_name = "msm-stub-codec.1",
+		.codec_dai_name = "msm-stub-tx",
+		.no_pcm = 1,
+		.be_id = MSM_BACKEND_DAI_AUXPCM_TX,
+		.be_hw_params_fixup = mpq8064_auxpcm_be_params_fixup,
+	},
 };
 
 
diff --git a/sound/soc/msm/msm-compr-q6.c b/sound/soc/msm/msm-compr-q6.c
index 550a492..0b9d54f 100644
--- a/sound/soc/msm/msm-compr-q6.c
+++ b/sound/soc/msm/msm-compr-q6.c
@@ -551,9 +551,7 @@
 	prtd->enabled = 1;
 
 	if (compr->info.codec_param.codec.id ==
-			SND_AUDIOCODEC_AC3_PASS_THROUGH ||
-			compr->info.codec_param.codec.id ==
-			SND_AUDIOCODEC_DTS_PASS_THROUGH)
+			SND_AUDIOCODEC_PASS_THROUGH)
 		msm_pcm_routing_reg_psthr_stream(
 					soc_prtd->dai_link->be_id,
 					prtd->session_id, substream->stream,
@@ -768,9 +766,7 @@
 	q6asm_audio_client_buf_free_contiguous(dir,
 				prtd->audio_client);
 	if (compr->info.codec_param.codec.id ==
-			SND_AUDIOCODEC_AC3_PASS_THROUGH ||
-			compr->info.codec_param.codec.id ==
-			SND_AUDIOCODEC_DTS_PASS_THROUGH)
+			SND_AUDIOCODEC_PASS_THROUGH)
 		msm_pcm_routing_reg_psthr_stream(
 					soc_prtd->dai_link->be_id,
 					prtd->session_id, substream->stream,
diff --git a/sound/soc/msm/qdsp6/q6asm.c b/sound/soc/msm/qdsp6/q6asm.c
index b086b8e..6865871 100644
--- a/sound/soc/msm/qdsp6/q6asm.c
+++ b/sound/soc/msm/qdsp6/q6asm.c
@@ -798,6 +798,25 @@
 	return 0;
 }
 
+static int32_t is_no_wait_cmd_rsp(uint32_t opcode, uint32_t *cmd_type)
+{
+	if (opcode == APR_BASIC_RSP_RESULT) {
+		if (cmd_type != NULL) {
+			switch (cmd_type[0]) {
+			case ASM_SESSION_CMD_RUN:
+			case ASM_SESSION_CMD_PAUSE:
+			case ASM_DATA_CMD_EOS:
+				return 1;
+			default:
+				break;
+			}
+		} else
+			pr_err("%s: null pointer!", __func__);
+	} else if (opcode == ASM_DATA_CMDRSP_EOS)
+		return 1;
+
+	return 0;
+}
 
 static int32_t q6asm_callback(struct apr_client_data *data, void *priv)
 {
@@ -818,14 +837,16 @@
 			ac->session);
 		return -EINVAL;
 	}
-	if (atomic_read(&ac->nowait_cmd_cnt) > 0) {
+
+	payload = data->payload;
+	if ((atomic_read(&ac->nowait_cmd_cnt) > 0) &&
+		is_no_wait_cmd_rsp(data->opcode, payload)) {
 		pr_debug("%s: nowait_cmd_cnt %d\n",
 				__func__,
 				atomic_read(&ac->nowait_cmd_cnt));
 		atomic_dec(&ac->nowait_cmd_cnt);
 		wakeup_flag = 0;
 	}
-	payload = data->payload;
 
 	if (data->opcode == RESET_EVENTS) {
 		pr_debug("q6asm_callback: Reset event is received: %d %d apr[%p]\n",