Merge "ASoC: msm: Fix crash during FM recording." into msm-3.4
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
index 35385d3..4129f7f 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-levels.txt
@@ -18,7 +18,11 @@
 - qcom,vdd-mem-upper-bound: The upper bound value of mem voltage in uV
 - qcom,vdd-mem-lower-bound: The lower bound value of mem voltage in uV
 - qcom,vdd-dig-upper-bound: The upper bound value of dig voltage in uV
+                            or an RBCPR (Rapid Bridge Core Power Reduction)
+                            corner voltage.
 - qcom,vdd-dig-lower-bound: The lower bound value of dig voltage in uV
+                            or an RBCPR (Rapid Bridge Core Power Reduction)
+                            corner voltage.
 - qcom,latency-us: The latency in handling the interrupt if this level was
 	chosen, in uSec
 - qcom,ss-power: The steady state power expelled when the processor is in this
@@ -37,8 +41,8 @@
 		qcom,l2 = <3>;          /* ACTIVE */
 		qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 		qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-		qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
-		qcom,vdd-dig-lower-bound = <950000>;  /* ACTIVE */
+		qcom,vdd-dig-upper-bound = <5>; /* MAX */
+		qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
 		qcom,latency-us = <100>;
 		qcom,ss-power = <650>;
 		qcom,energy-overhead = <801>;
diff --git a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
index 9ff43a1..b16d40f 100644
--- a/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
+++ b/Documentation/devicetree/bindings/arm/msm/lpm-resources.txt
@@ -13,19 +13,20 @@
 
 - compatible: "qcom,lpm-resources"
 - reg: The numeric level id
-- qcom,name: The name of the low power resource.
-- qcom,type: The string represeting the type of resource used
-             like smps or pxo.
+- qcom,name: The name of the low power resource represented
+             as a string.
+- qcom,type: The type of resource used like smps or pxo
+             represented as a hex value.
 - qcom,id: The id representing a device within a resource type.
 - qcom,key: The key is the specific attribute of the resource being
-            monitored.
+            monitored represented as a hex value.
 
 Example:
             qcom,lpm-resources@0 {
                         reg = <0x0>;
                         qcom,name = "vdd-dig";
-                        qcom,type = "smpb\0";
+                        qcom,type = <0x62706d73>;   /* "smpb" */
                         qcom,id = <0x02>;
-                        qcom,key = "uv\0\0";
+                        qcom,key = <0x6e726f63>;   /* "corn" */
                 };
 
diff --git a/Documentation/devicetree/bindings/cache/msm_cache_erp.txt b/Documentation/devicetree/bindings/cache/msm_cache_erp.txt
new file mode 100644
index 0000000..400b299
--- /dev/null
+++ b/Documentation/devicetree/bindings/cache/msm_cache_erp.txt
@@ -0,0 +1,16 @@
+* Qualcomm Krait L1 / L2 cache error reporting driver
+
+Required properties:
+- compatible: Should be "qcom,cache_erp"
+- interrupts: Should contain the L1/CPU error interrupt number and
+  the L2 cache interrupt number
+- interrupt-names: Should contain the interrupt names "l1_irq" and
+  "l2_irq"
+
+Example:
+	qcom,cache_erp {
+		compatible = "qcom,cache_erp";
+		interrupts = <1 9 0>, <0 2 0>;
+		interrupt-names = "l1_irq", "l2_irq";
+	};
+
diff --git a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
index 35ac0ec..a8de90f 100644
--- a/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
+++ b/Documentation/devicetree/bindings/mmc/msm_sdcc.txt
@@ -35,6 +35,15 @@
 	- qcom,sdcc-<supply>-current_level - specifies load levels for supply in lpm or
 	high power mode (hpm). Should be specified in pairs (lpm, hpm), units uA.
 
+	- gpios - specifies gpios assigned for sdcc slot.
+	- qcom,sdcc-gpio-names -  a list of strings that map in order to the list of gpios
+	A slot has either gpios or dedicated tlmm pins as represented below.
+	- qcom,sdcc-pad-pull-on - Active pull configuration for sdc tlmm pins
+	- qcom,sdcc-pad-pull-off - Suspend pull configuration for sdc tlmm pins.
+	- qcom,sdcc-pad-drv-on - Active drive strength configuration for sdc tlmm pins.
+	- qcom,sdcc-pad-drv-off - Suspend drive strength configuration for sdc tlmm pins.
+	Tlmm pins are specified as <clk cmd data>
+
 Example:
 
 	qcom,sdcc@f9600000 {
diff --git a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
index b6086e7..16a5c77 100644
--- a/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
+++ b/Documentation/devicetree/bindings/sound/qcom-audio-dev.txt
@@ -18,6 +18,12 @@
 
  - compatible : "qcom,msm-pcm-lpa"
 
+* msm-compr-dsp
+
+Required properties:
+
+ - compatible : "qcom,msm-compr-dsp"
+
 * msm-voip-dsp
 
 Required properties:
@@ -95,6 +101,10 @@
                 compatible = "qcom,msm-pcm-lpa";
         };
 
+        qcom,msm-compr-dsp {
+                compatible = "qcom,msm-compr-dsp";
+        };
+
         qcom,msm-voip-dsp {
                 compatible = "qcom,msm-voip-dsp";
         };
@@ -119,12 +129,12 @@
                 qcom,msm-cpudai-auxpcm-pcm-clk-rate = <2048000>;
 
                 qcom,msm-auxpcm-rx {
-			qcom,msm-auxpcm-dev-id = <4106>;
+                        qcom,msm-auxpcm-dev-id = <4106>;
                         compatible = "qcom,msm-auxpcm-dev";
                 };
 
                 qcom,msm-auxpcm-tx {
-			qcom,msm-auxpcm-dev-id = <4107>;
+                        qcom,msm-auxpcm-dev-id = <4107>;
                         compatible = "qcom,msm-auxpcm-dev";
                 };
         };
diff --git a/arch/arm/boot/dts/msm-pm8941.dtsi b/arch/arm/boot/dts/msm-pm8941.dtsi
index f462a1e..6737e89 100644
--- a/arch/arm/boot/dts/msm-pm8941.dtsi
+++ b/arch/arm/boot/dts/msm-pm8941.dtsi
@@ -315,6 +315,23 @@
 				status = "disabled";
 			};
 		};
+
+		qcom,pm8941_rtc {
+			spmi-dev-container;
+			compatible = "qcom,qpnp-rtc";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			qcom,qpnp-rtc-write = <0>;
+			qcom,qpnp-rtc-alarm-pwrup = <0>;
+
+			qcom,pm8941_rtc_rw@6000 {
+				reg = <0x6000 0x100>;
+			};
+			qcom,pm8941_rtc_alarm@6100 {
+				reg = <0x6100 0x100>;
+				interrupts = <0x0 0x61 0x1>;
+			};
+		};
 	};
 
 	qcom,pm8941@1 {
diff --git a/arch/arm/boot/dts/msm8974.dtsi b/arch/arm/boot/dts/msm8974.dtsi
index 2eb8216..edb86be 100644
--- a/arch/arm/boot/dts/msm8974.dtsi
+++ b/arch/arm/boot/dts/msm8974.dtsi
@@ -76,7 +76,7 @@
 	};
 
 	qcom,sdcc@f9824000 {
-		cell-index = <1>;
+		cell-index = <1>; /* SDC1 eMMC slot */
 		compatible = "qcom,msm-sdcc";
 		reg = <0xf9824000 0x1000>;
 		interrupts = <0 123 0>;
@@ -90,6 +90,11 @@
 		qcom,sdcc-vdd-io-voltage_level = <1800000 1800000>;
 		qcom,sdcc-vdd-io-current_level = <250 154000>;
 
+		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
 		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
 		qcom,sdcc-sup-voltages = <2950 2950>;
 		qcom,sdcc-bus-width = <8>;
@@ -98,7 +103,7 @@
 	};
 
 	qcom,sdcc@f98a4000 {
-		cell-index = <2>;
+		cell-index = <2>; /* SDC2 SD card slot */
 		compatible = "qcom,msm-sdcc";
 		reg = <0xf98a4000 0x1000>;
 		interrupts = <0 125 0>;
@@ -113,6 +118,11 @@
 		qcom,sdcc-vdd-io-voltage_level = <1800000 2950000>;
 		qcom,sdcc-vdd-io-current_level = <6 22000>;
 
+		qcom,sdcc-pad-pull-on = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-pull-off = <0x0 0x3 0x3>; /* no-pull, pull-up, pull-up */
+		qcom,sdcc-pad-drv-on = <0x7 0x4 0x4>; /* 16mA, 10mA, 10mA */
+		qcom,sdcc-pad-drv-off = <0x0 0x0 0x0>; /* 2mA, 2mA, 2mA */
+
 		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000 200000000>;
 		qcom,sdcc-sup-voltages = <2950 2950>;
 		qcom,sdcc-bus-width = <4>;
@@ -122,11 +132,19 @@
 	};
 
 	qcom,sdcc@f9864000 {
-		cell-index = <3>;
+		cell-index = <3>; /* SDC3 SDIO slot */
 		compatible = "qcom,msm-sdcc";
 		reg = <0xf9864000 0x1000>;
 		interrupts = <0 127 0>;
 
+		gpios = <&msmgpio 40 0>, /* CLK */
+			<&msmgpio 39 0>, /* CMD */
+			<&msmgpio 38 0>, /* DATA0 */
+			<&msmgpio 37 0>, /* DATA1 */
+			<&msmgpio 36 0>, /* DATA2 */
+			<&msmgpio 35 0>; /* DATA3 */
+		qcom,sdcc-gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
 		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
 		qcom,sdcc-sup-voltages = <1800 1800>;
 		qcom,sdcc-bus-width = <4>;
@@ -135,11 +153,19 @@
 	};
 
 	qcom,sdcc@f98e4000 {
-		cell-index = <4>;
+		cell-index = <4>; /* SDC4 SDIO slot */
 		compatible = "qcom,msm-sdcc";
 		reg = <0xf98e4000 0x1000>;
 		interrupts = <0 129 0>;
 
+		gpios = <&msmgpio 93 0>, /* CLK */
+			<&msmgpio 91 0>, /* CMD */
+			<&msmgpio 96 0>, /* DATA0 */
+			<&msmgpio 95 0>, /* DATA1 */
+			<&msmgpio 94 0>, /* DATA2 */
+			<&msmgpio 92 0>; /* DATA3 */
+		qcom,sdcc-gpio-names = "CLK", "CMD", "DAT0", "DAT1", "DAT2", "DAT3";
+
 		qcom,sdcc-clk-rates = <400000 25000000 50000000 100000000>;
 		qcom,sdcc-sup-voltages = <1800 1800>;
 		qcom,sdcc-bus-width = <4>;
@@ -352,6 +378,10 @@
 		compatible = "qcom,msm-pcm-lpa";
 	};
 
+	qcom,msm-compr-dsp {
+		compatible = "qcom,msm-compr-dsp";
+	};
+
 	qcom,msm-voip-dsp {
 		compatible = "qcom,msm-voip-dsp";
 	};
@@ -449,7 +479,7 @@
 
 		partition@E0000 {
 			reg = <0x120000 0x20000>;
-			qcom,ocmem-part-name = "blast";
+			qcom,ocmem-part-name = "other_os";
 			qcom,ocmem-part-min = <0x20000>;
 		};
 
diff --git a/arch/arm/boot/dts/msm8974_pm.dtsi b/arch/arm/boot/dts/msm8974_pm.dtsi
index 6f12e31c..aab2722 100644
--- a/arch/arm/boot/dts/msm8974_pm.dtsi
+++ b/arch/arm/boot/dts/msm8974_pm.dtsi
@@ -140,25 +140,25 @@
 		qcom,lpm-resources@0 {
 			reg = <0x0>;
 			qcom,name = "vdd-dig";
-			qcom,type = "smpb\0";
+			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x02>;
-			qcom,key = "uv\0\0";
+			qcom,key = <0x6e726f63>;	/* "corn" */
 		};
 
 		qcom,lpm-resources@1 {
 			reg = <0x1>;
 			qcom,name = "vdd-mem";
-			qcom,type = "smpb\0";
+			qcom,type = <0x62706d73>;	/* "smpb" */
 			qcom,id = <0x01>;
-			qcom,key = "uv\0\0";
+			qcom,key = <0x7675>;		/* "uv" */
 		};
 
 		qcom,lpm-resources@2 {
 			reg = <0x2>;
 			qcom,name = "pxo";
-			qcom,type = "clk0\0";
+			qcom,type = <0x306b6c63>;	/* "clk0" */
 			qcom,id = <0x00>;
-			qcom,key = "Enab";
+			qcom,key = <0x62616e45>;	/* "Enab" */
 		};
 	};
 
@@ -174,8 +174,8 @@
 			qcom,l2 = <3>;          /* ACTIVE */
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-dig-lower-bound = <950000>;  /* ACTIVE */
+			qcom,vdd-dig-upper-bound = <5>; /* MAX */
+			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
 			qcom,latency-us = <100>;
 			qcom,ss-power = <650>;
 			qcom,energy-overhead = <801>;
@@ -189,8 +189,8 @@
 			qcom,l2 = <3>;          /* ACTIVE */
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-dig-lower-bound = <950000>;  /* ACTIVE */
+			qcom,vdd-dig-upper-bound = <5>; /* MAX */
+			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
 			qcom,latency-us = <2000>;
 			qcom,ss-power = <200>;
 			qcom,energy-overhead = <576000>;
@@ -204,8 +204,8 @@
 			qcom,l2 = <1>;          /* GDHS */
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-dig-lower-bound = <950000>;  /* ACTIVE */
+			qcom,vdd-dig-upper-bound = <5>; /* MAX */
+			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
 			qcom,latency-us = <8500>;
 			qcom,ss-power = <51>;
 			qcom,energy-overhead = <1122000>;
@@ -219,8 +219,8 @@
 			qcom,l2 = <0>;          /* OFF */
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-dig-lower-bound = <950000>;  /* ACTIVE */
+			qcom,vdd-dig-upper-bound = <5>; /* MAX */
+			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
 			qcom,latency-us = <9000>;
 			qcom,ss-power = <51>;
 			qcom,energy-overhead = <1130300>;
@@ -234,8 +234,8 @@
 			qcom,l2 = <0>;          /* OFF */
 			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <950000>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <750000>;  /* RETENTION HIGH */
+			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
+			qcom,vdd-dig-lower-bound = <2>;  /* RETENTION HIGH */
 			qcom,latency-us = <10000>;
 			qcom,ss-power = <51>;
 			qcom,energy-overhead = <1130300>;
@@ -249,8 +249,8 @@
 			qcom,l2 = <1>;          /* GDHS */
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-dig-lower-bound = <950000>;  /* ACTIVE */
+			qcom,vdd-dig-upper-bound = <5>; /* MAX */
+			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
 			qcom,latency-us = <12000>;
 			qcom,ss-power = <14>;
 			qcom,energy-overhead = <2205900>;
@@ -264,8 +264,8 @@
 			qcom,l2 = <0>;          /* OFF */
 			qcom,vdd-mem-upper-bound = <1150000>; /* MAX */
 			qcom,vdd-mem-lower-bound = <1050000>; /* ACTIVE */
-			qcom,vdd-dig-upper-bound = <1150000>; /* MAX */
-			qcom,vdd-dig-lower-bound = <950000>;  /* ACTIVE */
+			qcom,vdd-dig-upper-bound = <5>; /* MAX */
+			qcom,vdd-dig-lower-bound = <3>;  /* ACTIVE */
 			qcom,latency-us = <18000>;
 			qcom,ss-power = <12>;
 			qcom,energy-overhead = <2364250>;
@@ -279,8 +279,8 @@
 			qcom,l2 = <0>;          /* OFF */
 			qcom,vdd-mem-upper-bound = <1050000>; /* ACTIVE */
 			qcom,vdd-mem-lower-bound = <750000>;  /* RETENTION HIGH */
-			qcom,vdd-dig-upper-bound = <950000>;  /* ACTIVE */
-			qcom,vdd-dig-lower-bound = <750000>;  /* RETIONTION HIGH */
+			qcom,vdd-dig-upper-bound = <3>;  /* ACTIVE */
+			qcom,vdd-dig-lower-bound = <2>;  /* RETIONTION HIGH */
 			qcom,latency-us = <23500>;
 			qcom,ss-power = <10>;
 			qcom,energy-overhead = <2667000>;
@@ -294,8 +294,8 @@
 			qcom,l2 = <0>;          /* OFF */
 			qcom,vdd-mem-upper-bound = <750000>; /* RETENTION HIGH */
 			qcom,vdd-mem-lower-bound = <750000>; /* RETENTION LOW */
-			qcom,vdd-dig-upper-bound = <750000>; /* RETENTION HIGH */
-			qcom,vdd-dig-lower-bound = <500000>; /* RETENTION LOW */
+			qcom,vdd-dig-upper-bound = <2>; /* RETENTION HIGH */
+			qcom,vdd-dig-lower-bound = <0>; /* RETENTION LOW */
 			qcom,latency-us = <29700>;
 			qcom,ss-power = <5>;
 			qcom,energy-overhead = <2867000>;
diff --git a/arch/arm/common/gic.c b/arch/arm/common/gic.c
index 88c4862..bbd6c63 100644
--- a/arch/arm/common/gic.c
+++ b/arch/arm/common/gic.c
@@ -47,6 +47,8 @@
 #include <asm/hardware/gic.h>
 #include <asm/system.h>
 
+#include <mach/socinfo.h>
+
 union gic_base {
 	void __iomem *common_base;
 	void __percpu __iomem **percpu_base;
@@ -56,6 +58,7 @@
 	unsigned int irq_offset;
 	union gic_base dist_base;
 	union gic_base cpu_base;
+	bool need_access_lock;
 #ifdef CONFIG_CPU_PM
 	u32 saved_spi_enable[DIV_ROUND_UP(1020, 32)];
 	u32 saved_spi_conf[DIV_ROUND_UP(1020, 16)];
@@ -207,14 +210,8 @@
 {
 	unsigned int i;
 	void __iomem *base = gic_data_dist_base(gic);
-#ifdef CONFIG_ARCH_MSM8625
-	unsigned long flags;
-#endif
 
 	for (i = 0; i * 32 < gic->max_irq; i++) {
-#ifdef CONFIG_ARCH_MSM8625
-		raw_spin_lock_irqsave(&irq_controller_lock, flags);
-#endif
 		gic->enabled_irqs[i]
 			= readl_relaxed(base + GIC_DIST_ENABLE_SET + i * 4);
 		/* disable all of them */
@@ -222,9 +219,6 @@
 		/* enable the wakeup set */
 		writel_relaxed(gic->wakeup_irqs[i],
 			base + GIC_DIST_ENABLE_SET + i * 4);
-#ifdef CONFIG_ARCH_MSM8625
-		raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
-#endif
 	}
 	mb();
 	return 0;
@@ -305,18 +299,19 @@
 
 static void gic_eoi_irq(struct irq_data *d)
 {
+	struct gic_chip_data *gic = irq_data_get_irq_chip_data(d);
+
 	if (gic_arch_extn.irq_eoi) {
 		raw_spin_lock(&irq_controller_lock);
 		gic_arch_extn.irq_eoi(d);
 		raw_spin_unlock(&irq_controller_lock);
 	}
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_lock(&irq_controller_lock);
-#endif
+
+	if (gic->need_access_lock)
+		raw_spin_lock(&irq_controller_lock);
 	writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_unlock(&irq_controller_lock);
-#endif
+	if (gic->need_access_lock)
+		raw_spin_unlock(&irq_controller_lock);
 }
 
 static int gic_set_type(struct irq_data *d, unsigned int type)
@@ -435,13 +430,11 @@
 	void __iomem *cpu_base = gic_data_cpu_base(gic);
 
 	do {
-#ifdef CONFIG_ARCH_MSM8625
-		raw_spin_lock(&irq_controller_lock);
-#endif
+		if (gic->need_access_lock)
+			raw_spin_lock(&irq_controller_lock);
 		irqstat = readl_relaxed(cpu_base + GIC_CPU_INTACK);
-#ifdef CONFIG_ARCH_MSM8625
-		raw_spin_unlock(&irq_controller_lock);
-#endif
+		if (gic->need_access_lock)
+			raw_spin_unlock(&irq_controller_lock);
 		irqnr = irqstat & ~0x1c00;
 
 		if (likely(irqnr > 15 && irqnr < 1021)) {
@@ -450,13 +443,11 @@
 			continue;
 		}
 		if (irqnr < 16) {
-#ifdef CONFIG_ARCH_MSM8625
-			raw_spin_lock(&irq_controller_lock);
-#endif
+			if (gic->need_access_lock)
+				raw_spin_lock(&irq_controller_lock);
 			writel_relaxed(irqstat, cpu_base + GIC_CPU_EOI);
-#ifdef CONFIG_ARCH_MSM8625
-			raw_spin_unlock(&irq_controller_lock);
-#endif
+			if (gic->need_access_lock)
+				raw_spin_unlock(&irq_controller_lock);
 #ifdef CONFIG_SMP
 			handle_IPI(irqnr, regs);
 #endif
@@ -583,9 +574,8 @@
 	 * Deal with the banked PPI and SGI interrupts - disable all
 	 * PPI interrupts, ensure all SGI interrupts are enabled.
 	 */
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_lock(&irq_controller_lock);
-#endif
+	if (gic->need_access_lock)
+		raw_spin_lock(&irq_controller_lock);
 	writel_relaxed(0xffff0000, dist_base + GIC_DIST_ENABLE_CLEAR);
 	writel_relaxed(0x0000ffff, dist_base + GIC_DIST_ENABLE_SET);
 
@@ -605,9 +595,8 @@
 		writel_relaxed(0xF, base + GIC_CPU_CTRL);
 	else
 		writel_relaxed(1, base + GIC_CPU_CTRL);
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_unlock(&irq_controller_lock);
-#endif
+	if (gic->need_access_lock)
+		raw_spin_unlock(&irq_controller_lock);
     mb();
 }
 
@@ -883,6 +872,10 @@
 	BUG_ON(gic_nr >= MAX_GIC_NR);
 
 	gic = &gic_data[gic_nr];
+	if (cpu_is_msm8625() &&
+			(SOCINFO_VERSION_MAJOR(socinfo_get_version()) <= 1))
+		gic->need_access_lock = true;
+
 #ifdef CONFIG_GIC_NON_BANKED
 	if (percpu_offset) { /* Frankein-GIC without banked registers... */
 		unsigned int cpu;
@@ -967,9 +960,8 @@
 	int cpu;
 	unsigned long sgir;
 	unsigned long map = 0;
-#ifdef CONFIG_ARCH_MSM8625
-	unsigned long flags;
-#endif
+	unsigned long flags = 0;
+	struct gic_chip_data *gic = &gic_data[0];
 
 	/* Convert our logical CPU mask into a physical one. */
 	for_each_cpu(cpu, mask)
@@ -985,16 +977,12 @@
 	 */
 	dsb();
 
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_lock_irqsave(&irq_controller_lock, flags);
-#endif
+	if (gic->need_access_lock)
+		raw_spin_lock_irqsave(&irq_controller_lock, flags);
 	/* this always happens on GIC0 */
-
-	writel_relaxed(sgir,
-			gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
-#ifdef CONFIG_ARCH_MSM8625
-	raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
-#endif
+	writel_relaxed(sgir, gic_data_dist_base(gic) + GIC_DIST_SOFTINT);
+	if (gic->need_access_lock)
+		raw_spin_unlock_irqrestore(&irq_controller_lock, flags);
 	mb();
 }
 #endif
@@ -1151,7 +1139,7 @@
 }
 #endif
 
-void msm_gic_save(bool modem_wake, int from_idle)
+void msm_gic_save(void)
 {
 	unsigned int i;
 	struct gic_chip_data *gic = &gic_data[0];
diff --git a/arch/arm/include/asm/hardware/gic.h b/arch/arm/include/asm/hardware/gic.h
index 5078148..ad12bcd 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/arch/arm/include/asm/hardware/gic.h
@@ -60,7 +60,7 @@
 }
 void gic_set_irq_secure(unsigned int irq);
 
-void msm_gic_save(bool modem_wake, int from_idle);
+void msm_gic_save(void);
 void msm_gic_restore(void);
 void core1_gic_configure_and_raise(void);
 #endif
diff --git a/arch/arm/include/asm/spinlock.h b/arch/arm/include/asm/spinlock.h
index 582c9b3..94aa75e 100644
--- a/arch/arm/include/asm/spinlock.h
+++ b/arch/arm/include/asm/spinlock.h
@@ -7,6 +7,8 @@
 
 #include <asm/processor.h>
 
+extern int msm_krait_need_wfe_fixup;
+
 /*
  * sev and wfe are ARMv6K extensions.  Uniprocessor ARMv6 may not have the K
  * extensions, so when running on UP, we have to patch these instructions away.
@@ -21,25 +23,42 @@
 #ifdef CONFIG_THUMB2_KERNEL
 #define SEV		ALT_SMP("sev.w", "nop.w")
 /*
- * For Thumb-2, special care is needed to ensure that the conditional WFE
- * instruction really does assemble to exactly 4 bytes (as required by
- * the SMP_ON_UP fixup code).   By itself "wfene" might cause the
- * assembler to insert a extra (16-bit) IT instruction, depending on the
- * presence or absence of neighbouring conditional instructions.
- *
- * To avoid this unpredictableness, an approprite IT is inserted explicitly:
- * the assembler won't change IT instructions which are explicitly present
- * in the input.
+ * Both instructions given to the ALT_SMP macro need to be the same size, to
+ * allow the SMP_ON_UP fixups to function correctly. Hence the explicit encoding
+ * specifications.
  */
-#define WFE(cond)	ALT_SMP(		\
-	"it " cond "\n\t"			\
-	"wfe" cond ".n",			\
-						\
+#define WFE()		ALT_SMP(		\
+	"wfe.w",				\
 	"nop.w"					\
 )
 #else
 #define SEV		ALT_SMP("sev", "nop")
-#define WFE(cond)	ALT_SMP("wfe" cond, "nop")
+#define WFE()		ALT_SMP("wfe", "nop")
+#endif
+
+/*
+ * The fixup involves disabling interrupts during execution of the WFE
+ * instruction. This could potentially lead to deadlock if a thread is trying
+ * to acquire a spinlock which is being released from an interrupt context.
+ */
+#ifdef CONFIG_MSM_KRAIT_WFE_FIXUP
+#define WFE_SAFE(fixup, tmp) 				\
+"	mrs	" tmp ", cpsr\n"			\
+"	cmp	" fixup ", #0\n"			\
+"	wfeeq\n"					\
+"	beq	10f\n"					\
+"	cpsid	if\n"					\
+"	mrc	p15, 7, " fixup ", c15, c0, 5\n"	\
+"	bic	" fixup ", " fixup ", #0x10000\n"	\
+"	mcr	p15, 7, " fixup ", c15, c0, 5\n"	\
+"	isb\n"						\
+"	wfe\n"						\
+"	orr	" fixup ", " fixup ", #0x10000\n"	\
+"	mcr	p15, 7, " fixup ", c15, c0, 5\n"	\
+"	isb\n"						\
+"10:	msr	cpsr_cf, " tmp "\n"
+#else
+#define WFE_SAFE(fixup, tmp)	"	wfe\n"
 #endif
 
 static inline void dsb_sev(void)
@@ -79,17 +98,19 @@
 
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
-	unsigned long tmp;
+	unsigned long tmp, fixup = msm_krait_need_wfe_fixup;
 
 	__asm__ __volatile__(
-"1:	ldrex	%0, [%1]\n"
-"	teq	%0, #0\n"
-	WFE("ne")
-"	strexeq	%0, %2, [%1]\n"
-"	teqeq	%0, #0\n"
+"1:	ldrex	%[tmp], [%[lock]]\n"
+"	teq	%[tmp], #0\n"
+"	beq	2f\n"
+	WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
+"	strexeq	%[tmp], %[bit0], [%[lock]]\n"
+"	teqeq	%[tmp], #0\n"
 "	bne	1b"
-	: "=&r" (tmp)
-	: "r" (&lock->lock), "r" (1)
+	: [tmp] "=&r" (tmp), [fixup] "+r" (fixup)
+	: [lock] "r" (&lock->lock), [bit0] "r" (1)
 	: "cc");
 
 	smp_mb();
@@ -155,6 +176,7 @@
 static inline void arch_spin_lock(arch_spinlock_t *lock)
 {
 	unsigned long tmp, ticket, next_ticket;
+	unsigned long fixup = msm_krait_need_wfe_fixup;
 
 	/* Grab the next ticket and wait for it to be "served" */
 	__asm__ __volatile__(
@@ -166,12 +188,15 @@
 "	uxth	%[ticket], %[ticket]\n"
 "2:\n"
 #ifdef CONFIG_CPU_32v6K
-"	wfene\n"
+"	beq	3f\n"
+	WFE_SAFE("%[fixup]", "%[tmp]")
+"3:\n"
 #endif
 "	ldr	%[tmp], [%[lockaddr]]\n"
 "	cmp	%[ticket], %[tmp], lsr #16\n"
 "	bne	2b"
-	: [ticket]"=&r" (ticket), [tmp]"=&r" (tmp), [next_ticket]"=&r" (next_ticket)
+	: [ticket]"=&r" (ticket), [tmp]"=&r" (tmp),
+	  [next_ticket]"=&r" (next_ticket), [fixup]"+r" (fixup)
 	: [lockaddr]"r" (&lock->lock), [val1]"r" (1)
 	: "cc");
 	smp_mb();
@@ -220,13 +245,16 @@
 
 static inline void arch_spin_unlock_wait(arch_spinlock_t *lock)
 {
-	unsigned long ticket;
+	unsigned long ticket, tmp, fixup = msm_krait_need_wfe_fixup;
 
 	/* Wait for now_serving == next_ticket */
 	__asm__ __volatile__(
 #ifdef CONFIG_CPU_32v6K
 "	cmpne	%[lockaddr], %[lockaddr]\n"
-"1:	wfene\n"
+"1:\n"
+"	beq	2f\n"
+	WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
 #else
 "1:\n"
 #endif
@@ -235,7 +263,8 @@
 "	uxth	%[ticket], %[ticket]\n"
 "	cmp	%[ticket], #0\n"
 "	bne	1b"
-	: [ticket]"=&r" (ticket)
+	: [ticket]"=&r" (ticket), [tmp]"=&r" (tmp),
+	  [fixup]"+r" (fixup)
 	: [lockaddr]"r" (&lock->lock)
 	: "cc");
 }
@@ -263,17 +292,19 @@
 
 static inline void arch_write_lock(arch_rwlock_t *rw)
 {
-	unsigned long tmp;
+	unsigned long tmp, fixup = msm_krait_need_wfe_fixup;
 
 	__asm__ __volatile__(
-"1:	ldrex	%0, [%1]\n"
-"	teq	%0, #0\n"
-	WFE("ne")
-"	strexeq	%0, %2, [%1]\n"
-"	teq	%0, #0\n"
+"1:	ldrex	%[tmp], [%[lock]]\n"
+"	teq	%[tmp], #0\n"
+"	beq	2f\n"
+	WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
+"	strexeq	%[tmp], %[bit31], [%[lock]]\n"
+"	teq	%[tmp], #0\n"
 "	bne	1b"
-	: "=&r" (tmp)
-	: "r" (&rw->lock), "r" (0x80000000)
+	: [tmp] "=&r" (tmp), [fixup] "+r" (fixup)
+	: [lock] "r" (&rw->lock), [bit31] "r" (0x80000000)
 	: "cc");
 
 	smp_mb();
@@ -329,17 +360,19 @@
  */
 static inline void arch_read_lock(arch_rwlock_t *rw)
 {
-	unsigned long tmp, tmp2;
+	unsigned long tmp, tmp2, fixup = msm_krait_need_wfe_fixup;
 
 	__asm__ __volatile__(
-"1:	ldrex	%0, [%2]\n"
-"	adds	%0, %0, #1\n"
-"	strexpl	%1, %0, [%2]\n"
-	WFE("mi")
-"	rsbpls	%0, %1, #0\n"
+"1:	ldrex	%[tmp], [%[lock]]\n"
+"	adds	%[tmp], %[tmp], #1\n"
+"	strexpl	%[tmp2], %[tmp], [%[lock]]\n"
+"	bpl	2f\n"
+	WFE_SAFE("%[fixup]", "%[tmp]")
+"2:\n"
+"	rsbpls	%[tmp], %[tmp2], #0\n"
 "	bmi	1b"
-	: "=&r" (tmp), "=&r" (tmp2)
-	: "r" (&rw->lock)
+	: [tmp] "=&r" (tmp), [tmp2] "=&r" (tmp2), [fixup] "+r" (fixup)
+	: [lock] "r" (&rw->lock)
 	: "cc");
 
 	smp_mb();
diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index a8f2858..7d767c3 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -185,6 +185,7 @@
 		INIT_SETUP(16)
 		INIT_CALLS
 		CON_INITCALL
+		COMPAT_EXPORTS
 		SECURITY_INITCALL
 		INIT_RAM_FS
 	}
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index c23bc10..5e7965e 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -172,6 +172,7 @@
 	select HOLES_IN_ZONE if SPARSEMEM
 	select MSM_RUN_QUEUE_STATS
 	select ARM_HAS_SG_CHAIN
+	select MSM_KRAIT_WFE_FIXUP
 
 config ARCH_MSM8930
 	bool "MSM8930"
@@ -203,6 +204,7 @@
 	select MSM_PM8X60 if PM
 	select HOLES_IN_ZONE if SPARSEMEM
 	select ARM_HAS_SG_CHAIN
+	select MSM_KRAIT_WFE_FIXUP
 
 config ARCH_APQ8064
 	bool "APQ8064"
@@ -229,6 +231,7 @@
 	select MIGHT_HAVE_PCI
 	select ARCH_SUPPORTS_MSI
 	select ARM_HAS_SG_CHAIN
+	select MSM_KRAIT_WFE_FIXUP
 
 config ARCH_MSM8974
 	bool "MSM8974"
@@ -370,6 +373,9 @@
 	select MSM_SMP
 	bool
 
+config  MSM_KRAIT_WFE_FIXUP
+	bool
+
 config  ARCH_MSM_CORTEX_A5
 	bool
 	select HAVE_HW_BRKPT_RESERVED_RW_ACCESS
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index 5cd93dc..4c020e3 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -23,6 +23,7 @@
 endif
 
 obj-y += acpuclock.o
+obj-$(CONFIG_ARCH_MSM_KRAIT) += acpuclock-krait.o
 obj-$(CONFIG_ARCH_MSM7X27) += acpuclock-7627.o clock-pll.o
 obj-$(CONFIG_ARCH_MSM_SCORPION) += pmu.o
 obj-$(CONFIG_ARCH_MSM_SCORPIONMP) += perf_event_msm_l2.o
@@ -269,6 +270,7 @@
 obj-$(CONFIG_ARCH_MSM8960) += saw-regulator.o
 obj-$(CONFIG_ARCH_MSM8960) += devices-8960.o
 obj-$(CONFIG_ARCH_APQ8064) += devices-8960.o devices-8064.o
+obj-$(CONFIG_ARCH_APQ8064) += acpuclock-8064.o
 board-8960-all-objs += board-8960.o board-8960-camera.o board-8960-display.o board-8960-pmic.o board-8960-storage.o board-8960-gpiomux.o
 board-8930-all-objs += board-8930.o board-8930-camera.o board-8930-display.o board-8930-pmic.o board-8930-storage.o board-8930-gpiomux.o devices-8930.o board-8930-gpu.o
 board-8064-all-objs += board-8064.o board-8064-pmic.o board-8064-storage.o board-8064-gpiomux.o board-8064-camera.o board-8064-display.o board-8064-gpu.o
@@ -291,11 +293,11 @@
 obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o board-9615-display.o
 obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o clock-pll.o
 obj-$(CONFIG_ARCH_MSM8974) += board-8974.o board-dt.o board-8974-regulator.o board-8974-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8974) += acpuclock-krait.o acpuclock-8974.o
+obj-$(CONFIG_ARCH_MSM8974) += acpuclock-8974.o
 obj-$(CONFIG_ARCH_MSM8974) += clock-local2.o clock-pll.o clock-8974.o clock-rpm.o clock-voter.o
 obj-$(CONFIG_ARCH_MSM8974) += gdsc.o
 obj-$(CONFIG_ARCH_MSM9625) += board-9625.o board-9625-gpiomux.o
-obj-$(CONFIG_ARCH_MSM8930) += acpuclock-krait.o acpuclock-8930.o acpuclock-8627.o
+obj-$(CONFIG_ARCH_MSM8930) += acpuclock-8930.o acpuclock-8627.o
 
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire.o board-sapphire-gpio.o
 obj-$(CONFIG_MACH_SAPPHIRE) += board-sapphire-keypad.o board-sapphire-panel.o
@@ -337,7 +339,7 @@
 obj-$(CONFIG_ARCH_MSM8X60) += board-msm8x60-vcm.o
 endif
 obj-$(CONFIG_MSM_OCMEM) += ocmem.o ocmem_allocator.o ocmem_notifier.o
-obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o
+obj-$(CONFIG_MSM_OCMEM) += ocmem_sched.o ocmem_api.o ocmem_rdm.o
 
 obj-$(CONFIG_ARCH_MSM7X27) += gpiomux-7x27.o gpiomux-v1.o gpiomux.o
 obj-$(CONFIG_ARCH_MSM7X30) += gpiomux-7x30.o gpiomux-v1.o gpiomux.o
diff --git a/arch/arm/mach-msm/acpuclock-8064.c b/arch/arm/mach-msm/acpuclock-8064.c
new file mode 100644
index 0000000..d46d268
--- /dev/null
+++ b/arch/arm/mach-msm/acpuclock-8064.c
@@ -0,0 +1,242 @@
+/*
+ * Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <mach/rpm-regulator.h>
+#include <mach/msm_bus_board.h>
+#include <mach/msm_bus.h>
+
+#include "acpuclock.h"
+#include "acpuclock-krait.h"
+
+static struct hfpll_data hfpll_data __initdata = {
+	.mode_offset = 0x00,
+	.l_offset = 0x08,
+	.m_offset = 0x0C,
+	.n_offset = 0x10,
+	.config_offset = 0x04,
+	.config_val = 0x7845C665,
+	.has_droop_ctl = true,
+	.droop_offset = 0x14,
+	.droop_val = 0x0108C000,
+	.low_vdd_l_max = 40,
+	.vdd[HFPLL_VDD_NONE] = 0,
+	.vdd[HFPLL_VDD_LOW]  = 945000,
+	.vdd[HFPLL_VDD_NOM]  = 1050000,
+};
+
+static struct scalable scalable[] __initdata = {
+	[CPU0] = {
+		.hfpll_phys_base = 0x00903200,
+		.aux_clk_sel_phys = 0x02088014,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x4501,
+		.vreg[VREG_CORE] = { "krait0", 1300000, 1740000 },
+		.vreg[VREG_MEM]  = { "krait0_mem", 1150000 },
+		.vreg[VREG_DIG]  = { "krait0_dig", 1150000 },
+		.vreg[VREG_HFPLL_A] = { "krait0_hfpll", 1800000 },
+	},
+	[CPU1] = {
+		.hfpll_phys_base = 0x00903240,
+		.aux_clk_sel_phys = 0x02098014,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x5501,
+		.vreg[VREG_CORE] = { "krait1", 1300000, 1740000 },
+		.vreg[VREG_MEM]  = { "krait1_mem", 1150000 },
+		.vreg[VREG_DIG]  = { "krait1_dig", 1150000 },
+		.vreg[VREG_HFPLL_A] = { "krait1_hfpll", 1800000 },
+	},
+	[CPU2] = {
+		.hfpll_phys_base = 0x00903280,
+		.aux_clk_sel_phys = 0x020A8014,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x6501,
+		.vreg[VREG_CORE] = { "krait2", 1300000, 1740000 },
+		.vreg[VREG_MEM]  = { "krait2_mem", 1150000 },
+		.vreg[VREG_DIG]  = { "krait2_dig", 1150000 },
+		.vreg[VREG_HFPLL_A] = { "krait2_hfpll", 1800000 },
+	},
+	[CPU3] = {
+		.hfpll_phys_base = 0x009032C0,
+		.aux_clk_sel_phys = 0x020B8014,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x7501,
+		.vreg[VREG_CORE] = { "krait3", 1300000, 1740000 },
+		.vreg[VREG_MEM]  = { "krait3_mem", 1150000 },
+		.vreg[VREG_DIG]  = { "krait3_dig", 1150000 },
+		.vreg[VREG_HFPLL_A] = { "krait3_hfpll", 1800000 },
+	},
+	[L2] = {
+		.hfpll_phys_base = 0x00903300,
+		.aux_clk_sel_phys = 0x02011028,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x0500,
+		.vreg[VREG_HFPLL_A] = { "l2_hfpll", 1800000 },
+	},
+};
+
+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. */
+	[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
+	[3] = BW_MBPS(2128), /* At least 266 MHz on bus. */
+	[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
+	[5] = BW_MBPS(4264), /* At least 533 MHz on bus. */
+};
+
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
+	.usecase = bw_level_tbl,
+	.num_usecases = ARRAY_SIZE(bw_level_tbl),
+	.active_only = 1,
+	.name = "acpuclk-8064",
+};
+
+static struct l2_level l2_freq_tbl[] __initdata __initdata = {
+	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 }, 1050000, 1050000, 0 },
+	[1]  = { {  384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
+	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
+	[3]  = { {  486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
+	[4]  = { {  540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
+	[5]  = { {  594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
+	[6]  = { {  648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
+	[7]  = { {  702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
+	[8]  = { {  756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
+	[9]  = { {  810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
+	[10] = { {  864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
+	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 5 },
+	[12] = { {  972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 5 },
+	[13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 5 },
+	[14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 5 },
+	[15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 5 },
+};
+
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   975000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   975000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),  1000000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),  1000000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),  1025000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),  1025000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1075000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1075000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1100000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1100000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1125000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1125000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   925000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   925000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   950000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   950000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   975000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   975000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1025000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1025000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1050000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1050000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1075000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1075000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1125000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1125000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1150000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1150000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1175000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1175000 },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1187500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1187500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1200000 },
+	{ 0, { 0 } }
+};
+
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
+	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   850000 },
+	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   850000 },
+	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   875000 },
+	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   875000 },
+	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   900000 },
+	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   900000 },
+	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   925000 },
+	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   925000 },
+	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),   975000 },
+	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),   975000 },
+	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1000000 },
+	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1000000 },
+	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1025000 },
+	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1025000 },
+	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1075000 },
+	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1075000 },
+	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1100000 },
+	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1100000 },
+	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1125000 },
+	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1125000 },
+	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1137500 },
+	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1137500 },
+	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1150000 },
+	{ 0, { 0 } }
+};
+
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+	[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+	[PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom)  },
+	[PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+	/* TODO: update the faster table when data is available */
+	[PVS_FASTER]  = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+};
+
+static struct acpuclk_krait_params acpuclk_8064_params __initdata = {
+	.scalable = scalable,
+	.scalable_size = sizeof(scalable),
+	.hfpll_data = &hfpll_data,
+	.pvs_tables = pvs_tables,
+	.l2_freq_tbl = l2_freq_tbl,
+	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
+	.bus_scale = &bus_scale_data,
+	.qfprom_phys_base = 0x00700000,
+};
+
+static int __init acpuclk_8064_probe(struct platform_device *pdev)
+{
+	return acpuclk_krait_init(&pdev->dev, &acpuclk_8064_params);
+}
+
+static struct platform_driver acpuclk_8064_driver = {
+	.driver = {
+		.name = "acpuclk-8064",
+		.owner = THIS_MODULE,
+	},
+};
+
+static int __init acpuclk_8064_init(void)
+{
+	return platform_driver_probe(&acpuclk_8064_driver,
+				     acpuclk_8064_probe);
+}
+device_initcall(acpuclk_8064_init);
diff --git a/arch/arm/mach-msm/acpuclock-8627.c b/arch/arm/mach-msm/acpuclock-8627.c
index 45f2096..8060803 100644
--- a/arch/arm/mach-msm/acpuclock-8627.c
+++ b/arch/arm/mach-msm/acpuclock-8627.c
@@ -27,7 +27,7 @@
 #define LVL_NOM		RPM_VREG_CORNER_NOMINAL
 #define LVL_HIGH	RPM_VREG_CORNER_HIGH
 
-static struct hfpll_data hfpll_data = {
+static struct hfpll_data hfpll_data __initdata = {
 	.mode_offset = 0x00,
 	.l_offset = 0x08,
 	.m_offset = 0x0C,
@@ -43,10 +43,9 @@
 	.vdd[HFPLL_VDD_NOM]  = LVL_NOM,
 };
 
-static struct scalable scalable[] = {
+static struct scalable scalable[] __initdata = {
 	[CPU0] = {
 		.hfpll_phys_base = 0x00903200,
-		.hfpll_data = &hfpll_data,
 		.aux_clk_sel_phys = 0x02088014,
 		.aux_clk_sel = 3,
 		.l2cpmr_iaddr = 0x4501,
@@ -57,7 +56,6 @@
 	},
 	[CPU1] = {
 		.hfpll_phys_base = 0x00903300,
-		.hfpll_data = &hfpll_data,
 		.aux_clk_sel_phys = 0x02098014,
 		.aux_clk_sel = 3,
 		.l2cpmr_iaddr = 0x5501,
@@ -68,7 +66,6 @@
 	},
 	[L2] = {
 		.hfpll_phys_base = 0x00903400,
-		.hfpll_data = &hfpll_data,
 		.aux_clk_sel_phys = 0x02011028,
 		.aux_clk_sel = 3,
 		.l2cpmr_iaddr = 0x0500,
@@ -76,7 +73,7 @@
 	},
 };
 
-static struct msm_bus_paths bw_level_tbl[] = {
+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. */
 	[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
@@ -84,7 +81,7 @@
 	[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
 };
 
-static struct msm_bus_scale_pdata bus_scale_data = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
 	.usecase = bw_level_tbl,
 	.num_usecases = ARRAY_SIZE(bw_level_tbl),
 	.active_only = 1,
@@ -92,8 +89,7 @@
 };
 
 /* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
-#define L2(x) (&l2_freq_tbl[(x)])
-static struct l2_level l2_freq_tbl[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
 	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 },  LVL_NOM, 1050000, 0 },
 	[1]  = { {  384000, PLL_8, 0, 2, 0x00 },  LVL_NOM, 1050000, 1 },
 	[2]  = { {  432000, HFPLL, 2, 0, 0x20 },  LVL_NOM, 1050000, 1 },
@@ -110,7 +106,7 @@
 };
 
 /* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl[] = {
+static struct acpu_level acpu_freq_tbl[] __initdata = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
 	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(5),   925000 },
@@ -127,14 +123,20 @@
 	{ 0, { 0 } }
 };
 
-static struct acpuclk_krait_params acpuclk_8627_params = {
+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 acpuclk_krait_params acpuclk_8627_params __initdata = {
 	.scalable = scalable,
-	.pvs_acpu_freq_tbl[PVS_SLOW] = acpu_freq_tbl,
-	.pvs_acpu_freq_tbl[PVS_NOMINAL] = acpu_freq_tbl,
-	.pvs_acpu_freq_tbl[PVS_FAST] = acpu_freq_tbl,
+	.scalable_size = sizeof(scalable),
+	.hfpll_data = &hfpll_data,
+	.pvs_tables = pvs_tables,
 	.l2_freq_tbl = l2_freq_tbl,
-	.l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl),
-	.bus_scale_data = &bus_scale_data,
+	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
+	.bus_scale = &bus_scale_data,
 	.qfprom_phys_base = 0x00700000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8930.c b/arch/arm/mach-msm/acpuclock-8930.c
index d60b4eb..d04ce03 100644
--- a/arch/arm/mach-msm/acpuclock-8930.c
+++ b/arch/arm/mach-msm/acpuclock-8930.c
@@ -27,7 +27,7 @@
 #define LVL_NOM		RPM_VREG_CORNER_NOMINAL
 #define LVL_HIGH	RPM_VREG_CORNER_HIGH
 
-static struct hfpll_data hfpll_data = {
+static struct hfpll_data hfpll_data __initdata = {
 	.mode_offset = 0x00,
 	.l_offset = 0x08,
 	.m_offset = 0x0C,
@@ -43,10 +43,9 @@
 	.vdd[HFPLL_VDD_NOM]  = LVL_NOM,
 };
 
-static struct scalable scalable[] = {
+static struct scalable scalable[] __initdata = {
 	[CPU0] = {
 		.hfpll_phys_base = 0x00903200,
-		.hfpll_data = &hfpll_data,
 		.aux_clk_sel_phys = 0x02088014,
 		.aux_clk_sel = 3,
 		.l2cpmr_iaddr = 0x4501,
@@ -57,7 +56,6 @@
 	},
 	[CPU1] = {
 		.hfpll_phys_base = 0x00903300,
-		.hfpll_data = &hfpll_data,
 		.aux_clk_sel_phys = 0x02098014,
 		.aux_clk_sel = 3,
 		.l2cpmr_iaddr = 0x5501,
@@ -68,7 +66,6 @@
 	},
 	[L2] = {
 		.hfpll_phys_base = 0x00903400,
-		.hfpll_data = &hfpll_data,
 		.aux_clk_sel_phys = 0x02011028,
 		.aux_clk_sel = 3,
 		.l2cpmr_iaddr = 0x0500,
@@ -76,7 +73,7 @@
 	},
 };
 
-static struct msm_bus_paths bw_level_tbl[] = {
+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. */
 	[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
@@ -87,7 +84,7 @@
 	[7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
 };
 
-static struct msm_bus_scale_pdata bus_scale_data = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
 	.usecase = bw_level_tbl,
 	.num_usecases = ARRAY_SIZE(bw_level_tbl),
 	.active_only = 1,
@@ -95,8 +92,7 @@
 };
 
 /* TODO: Update vdd_dig, vdd_mem and bw when data is available. */
-#define L2(x) (&l2_freq_tbl[(x)])
-static struct l2_level l2_freq_tbl[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
 	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 },  LVL_NOM, 1050000, 0 },
 	[1]  = { {  384000, PLL_8, 0, 2, 0x00 },  LVL_NOM, 1050000, 1 },
 	[2]  = { {  432000, HFPLL, 2, 0, 0x20 },  LVL_NOM, 1050000, 2 },
@@ -116,7 +112,7 @@
 	[16] = { { 1188000, HFPLL, 1, 0, 0x2C }, LVL_HIGH, 1150000, 7 },
 };
 
-static struct acpu_level acpu_freq_tbl_slow[] = {
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
 	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   975000 },
@@ -137,7 +133,7 @@
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_nom[] = {
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   925000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   925000 },
 	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   950000 },
@@ -158,7 +154,7 @@
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_fast[] = {
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
 	{ 1, {   432000, HFPLL, 2, 0, 0x20 }, L2(6),   900000 },
@@ -179,14 +175,20 @@
 	{ 0, { 0 } }
 };
 
-static struct acpuclk_krait_params acpuclk_8930_params = {
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+	[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+	[PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom)  },
+	[PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
+};
+
+static struct acpuclk_krait_params acpuclk_8930_params __initdata = {
 	.scalable = scalable,
-	.pvs_acpu_freq_tbl[PVS_SLOW] = acpu_freq_tbl_slow,
-	.pvs_acpu_freq_tbl[PVS_NOMINAL] = acpu_freq_tbl_nom,
-	.pvs_acpu_freq_tbl[PVS_FAST] = acpu_freq_tbl_fast,
+	.scalable_size = sizeof(scalable),
+	.hfpll_data = &hfpll_data,
+	.pvs_tables = pvs_tables,
 	.l2_freq_tbl = l2_freq_tbl,
-	.l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl),
-	.bus_scale_data = &bus_scale_data,
+	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
+	.bus_scale = &bus_scale_data,
 	.qfprom_phys_base = 0x00700000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-8960.c b/arch/arm/mach-msm/acpuclock-8960.c
index 8947c9f..8623c2b 100644
--- a/arch/arm/mach-msm/acpuclock-8960.c
+++ b/arch/arm/mach-msm/acpuclock-8960.c
@@ -1,4 +1,5 @@
-/* Copyright (c) 2011-2012, Code Aurora Forum. All rights reserved.
+/*
+ * 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
@@ -10,318 +11,66 @@
  * GNU General Public License for more details.
  */
 
-#define pr_fmt(fmt) "%s: " fmt, __func__
-
 #include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/init.h>
-#include <linux/io.h>
-#include <linux/delay.h>
-#include <linux/mutex.h>
-#include <linux/err.h>
-#include <linux/errno.h>
-#include <linux/cpufreq.h>
-#include <linux/cpu.h>
-#include <linux/regulator/consumer.h>
 #include <linux/platform_device.h>
-
-#include <asm/mach-types.h>
-#include <asm/cpu.h>
-
-#include <mach/board.h>
-#include <mach/msm_iomap.h>
 #include <mach/rpm-regulator.h>
-#include <mach/msm_bus.h>
 #include <mach/msm_bus_board.h>
-#include <mach/socinfo.h>
-#include <mach/msm-krait-l2-accessors.h>
-#include <mach/rpm-regulator.h>
+#include <mach/msm_bus.h>
 
 #include "acpuclock.h"
-#include "pm.h"
+#include "acpuclock-krait.h"
 
-/*
- * Source IDs.
- * These must be negative to not overlap with the source IDs
- * used by the 8x60 local clock driver.
- */
-#define PLL_8			 0
-#define HFPLL			-1
-#define QSB			-2
-
-/* Mux source selects. */
-#define PRI_SRC_SEL_SEC_SRC	0
-#define PRI_SRC_SEL_HFPLL	1
-#define PRI_SRC_SEL_HFPLL_DIV2	2
-#define SEC_SRC_SEL_QSB		0
-#define SEC_SRC_SEL_AUX		2
-
-/* HFPLL registers offsets. */
-#define HFPLL_MODE		0x00
-#define HFPLL_CONFIG_CTL	0x04
-#define HFPLL_L_VAL		0x08
-#define HFPLL_M_VAL		0x0C
-#define HFPLL_N_VAL		0x10
-#define HFPLL_DROOP_CTL		0x14
-
-/* CP15 L2 indirect addresses. */
-#define L2CPMR_IADDR		0x500
-#define L2CPUCPMR_IADDR		0x501
-
-#define STBY_KHZ		1
-
-#define HFPLL_LOW_VDD_PLL_L_MAX	0x28
-
-#define SECCLKAGD		BIT(4)
-
-/* PTE EFUSE register. */
-#define QFPROM_PTE_EFUSE_ADDR	(MSM_QFPROM_BASE + 0x00C0)
-
-/* Corner type vreg VDD values */
-#define LVL_NONE	RPM_VREG_CORNER_NONE
-#define LVL_LOW	RPM_VREG_CORNER_LOW
-#define LVL_NOM	RPM_VREG_CORNER_NOMINAL
-#define LVL_HIGH	RPM_VREG_CORNER_HIGH
-
-enum scalables {
-	CPU0 = 0,
-	CPU1,
-	CPU2,
-	CPU3,
-	L2,
-	NUM_SCALABLES
+static struct hfpll_data hfpll_data __initdata = {
+	.mode_offset = 0x00,
+	.l_offset = 0x08,
+	.m_offset = 0x0C,
+	.n_offset = 0x10,
+	.config_offset = 0x04,
+	.config_val = 0x7845C665,
+	.has_droop_ctl = true,
+	.droop_offset = 0x14,
+	.droop_val = 0x0108C000,
+	.low_vdd_l_max = 40,
+	.vdd[HFPLL_VDD_NONE] = 0,
+	.vdd[HFPLL_VDD_LOW]  = 850000,
+	.vdd[HFPLL_VDD_NOM]  = 1050000,
 };
 
-enum vregs {
-	VREG_CORE,
-	VREG_MEM,
-	VREG_DIG,
-	VREG_HFPLL_A,
-	VREG_HFPLL_B,
-	NUM_VREG
-};
-
-enum hfpll_vdd_levels {
-	HFPLL_VDD_NONE,
-	HFPLL_VDD_LOW,
-	HFPLL_VDD_NOM
-};
-
-enum pvs {
-	PVS_SLOW,
-	PVS_NOM,
-	PVS_FAST,
-	PVS_FASTER,
-	NUM_PVS
-};
-
-struct vreg {
-	const char name[15];
-	const unsigned int max_vdd;
-	const int rpm_vreg_voter;
-	const int rpm_vreg_id;
-	struct regulator *reg;
-	unsigned int cur_vdd;
-};
-
-struct core_speed {
-	unsigned int		khz;
-	int			src;
-	unsigned int		pri_src_sel;
-	unsigned int		sec_src_sel;
-	unsigned int		pll_l_val;
-};
-
-struct l2_level {
-	struct core_speed	speed;
-	unsigned int		vdd_dig;
-	unsigned int		vdd_mem;
-	unsigned int		bw_level;
-};
-
-struct acpu_level {
-	unsigned int		use_for_scaling;
-	struct core_speed	speed;
-	struct l2_level		*l2_level;
-	unsigned int		vdd_core;
-};
-
-struct scalable {
-	void * __iomem const hfpll_base;
-	void * __iomem const aux_clk_sel;
-	const uint32_t l2cpmr_iaddr;
-	struct core_speed *current_speed;
-	struct l2_level *l2_vote;
-	struct vreg vreg[NUM_VREG];
-	unsigned int *hfpll_vdd_tbl;
-	bool regulators_initialized;
-	bool clocks_initialized;
-};
-
-static unsigned int hfpll_vdd_tbl_8960[] = {
-	[HFPLL_VDD_NONE] = 0,
-	[HFPLL_VDD_LOW]  = 850000,
-	[HFPLL_VDD_NOM]  = 1050000
-};
-
-static unsigned int hfpll_vdd_tbl_8064[] = {
-	[HFPLL_VDD_NONE] = 0,
-	[HFPLL_VDD_LOW]  = 945000,
-	[HFPLL_VDD_NOM]  = 1050000
-};
-
-static struct scalable scalable_8960[] = {
+static struct scalable scalable[] __initdata = {
 	[CPU0] = {
-			.hfpll_base      = MSM_HFPLL_BASE + 0x200,
-			.aux_clk_sel     = MSM_ACC0_BASE  + 0x014,
-			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait0",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll0_s8", 2100000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll0_l23", 1800000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_L23 },
-		},
+		.hfpll_phys_base = 0x00903200,
+		.aux_clk_sel_phys = 0x02088014,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x4501,
+		.vreg[VREG_CORE] = { "krait0", 1300000, 3200000 },
+		.vreg[VREG_MEM]  = { "krait0_mem", 1150000 },
+		.vreg[VREG_DIG]  = { "krait0_dig", 1150000 },
+		.vreg[VREG_HFPLL_A] = { "krait0_s8", 2050000 },
+		.vreg[VREG_HFPLL_B] = { "krait0_l23", 1800000 },
+	},
 	[CPU1] = {
-			.hfpll_base      = MSM_HFPLL_BASE + 0x300,
-			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
-			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_A] = { "hfpll1_s8", 2100000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll1_l23", 1800000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_L23 },
-		},
+		.hfpll_phys_base = 0x00903300,
+		.aux_clk_sel_phys = 0x02098014,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x5501,
+		.vreg[VREG_CORE] = { "krait1", 1300000, 3200000 },
+		.vreg[VREG_MEM]  = { "krait1_mem", 1150000 },
+		.vreg[VREG_DIG]  = { "krait1_dig", 1150000 },
+		.vreg[VREG_HFPLL_A] = { "krait1_s8", 2050000 },
+		.vreg[VREG_HFPLL_B] = { "krait1_l23", 1800000 },
+	},
 	[L2] = {
-			.hfpll_base   = MSM_HFPLL_BASE    + 0x400,
-			.hfpll_vdd_tbl = hfpll_vdd_tbl_8960,
-			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
-			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_A] = { "hfpll_l2_s8", 2100000,
-					     RPM_VREG_VOTER6,
-					     RPM_VREG_ID_PM8921_S8 },
-			.vreg[VREG_HFPLL_B] = { "hfpll_l2_l23", 1800000,
-					     RPM_VREG_VOTER6,
-					     RPM_VREG_ID_PM8921_L23 },
-		},
+		.hfpll_phys_base = 0x00903400,
+		.aux_clk_sel_phys = 0x02011028,
+		.aux_clk_sel = 3,
+		.l2cpmr_iaddr = 0x0500,
+		.vreg[VREG_HFPLL_A] = { "l2_s8", 2050000 },
+		.vreg[VREG_HFPLL_B] = { "l2_l23", 1800000 },
+	},
 };
 
-static DEFINE_MUTEX(driver_lock);
-static DEFINE_SPINLOCK(l2_lock);
-
-static struct scalable scalable_8064[] = {
-	[CPU0] = {
-			.hfpll_base      = MSM_HFPLL_BASE + 0x200,
-			.aux_clk_sel     = MSM_ACC0_BASE  + 0x014,
-			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait0",     1300000 },
-			.vreg[VREG_MEM]  = { "krait0_mem", 1150000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait0_dig", 1150000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll0", 1800000,
-					     RPM_VREG_VOTER1,
-					     RPM_VREG_ID_PM8921_LVS7 },
-		},
-	[CPU1] = {
-			.hfpll_base      = MSM_HFPLL_BASE + 0x240,
-			.aux_clk_sel     = MSM_ACC1_BASE  + 0x014,
-			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait1",     1300000 },
-			.vreg[VREG_MEM]  = { "krait1_mem", 1150000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait1_dig", 1150000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll1", 1800000,
-					     RPM_VREG_VOTER2,
-					     RPM_VREG_ID_PM8921_LVS7 },
-		},
-	[CPU2] = {
-			.hfpll_base      = MSM_HFPLL_BASE + 0x280,
-			.aux_clk_sel     = MSM_ACC2_BASE  + 0x014,
-			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait2",     1300000 },
-			.vreg[VREG_MEM]  = { "krait2_mem", 1150000,
-					     RPM_VREG_VOTER4,
-					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait2_dig", 1150000,
-					     RPM_VREG_VOTER4,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll2", 1800000,
-					     RPM_VREG_VOTER4,
-					     RPM_VREG_ID_PM8921_LVS7 },
-		},
-	[CPU3] = {
-			.hfpll_base      = MSM_HFPLL_BASE + 0x2C0,
-			.aux_clk_sel     = MSM_ACC3_BASE  + 0x014,
-			.l2cpmr_iaddr    = L2CPUCPMR_IADDR,
-			.vreg[VREG_CORE] = { "krait3",     1300000 },
-			.vreg[VREG_MEM]  = { "krait3_mem", 1150000,
-					     RPM_VREG_VOTER5,
-					     RPM_VREG_ID_PM8921_L24 },
-			.vreg[VREG_DIG]  = { "krait3_dig", 1150000,
-					     RPM_VREG_VOTER5,
-					     RPM_VREG_ID_PM8921_S3 },
-			.vreg[VREG_HFPLL_B] = { "hfpll3", 1800000,
-					     RPM_VREG_VOTER5,
-					     RPM_VREG_ID_PM8921_LVS7 },
-		},
-	[L2] = {
-			.hfpll_base   = MSM_HFPLL_BASE    + 0x300,
-			.hfpll_vdd_tbl = hfpll_vdd_tbl_8064,
-			.aux_clk_sel  = MSM_APCS_GCC_BASE + 0x028,
-			.l2cpmr_iaddr = L2CPMR_IADDR,
-			.vreg[VREG_HFPLL_B] = { "hfpll_l2", 1800000,
-					     RPM_VREG_VOTER6,
-					     RPM_VREG_ID_PM8921_LVS7 },
-		},
-};
-
-static struct l2_level *l2_freq_tbl;
-static struct acpu_level *acpu_freq_tbl;
-static int l2_freq_tbl_size;
-static struct scalable *scalable;
-#define SCALABLE_TO_CPU(sc) ((sc) - scalable)
-
-/* Instantaneous bandwidth requests in MB/s. */
-#define BW_MBPS(_bw) \
-	{ \
-		.vectors = (struct msm_bus_vectors[]){ \
-			{\
-				.src = MSM_BUS_MASTER_AMPSS_M0, \
-				.dst = MSM_BUS_SLAVE_EBI_CH0, \
-				.ib = (_bw) * 1000000UL, \
-				.ab = (_bw) *  100000UL, \
-			}, \
-			{ \
-				.src = MSM_BUS_MASTER_AMPSS_M1, \
-				.dst = MSM_BUS_SLAVE_EBI_CH0, \
-				.ib = (_bw) * 1000000UL, \
-				.ab = (_bw) *  100000UL, \
-			}, \
-		}, \
-		.num_paths = 2, \
-	}
-static struct msm_bus_paths bw_level_tbl[] = {
+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. */
 	[2] = BW_MBPS(1600), /* At least 200 MHz on bus. */
@@ -329,70 +78,16 @@
 	[4] = BW_MBPS(3200), /* At least 400 MHz on bus. */
 	[5] = BW_MBPS(3600), /* At least 450 MHz on bus. */
 	[6] = BW_MBPS(3936), /* At least 492 MHz on bus. */
-	[7] = BW_MBPS(4264), /* At least 533 MHz on bus. */
 };
 
-static struct msm_bus_scale_pdata bus_client_pdata = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
 	.usecase = bw_level_tbl,
 	.num_usecases = ARRAY_SIZE(bw_level_tbl),
 	.active_only = 1,
-	.name = "acpuclock",
+	.name = "acpuclk-8960",
 };
 
-static uint32_t bus_perf_client;
-
-/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
-#define L2(x) (&l2_freq_tbl_8960_kraitv1[(x)])
-static struct l2_level l2_freq_tbl_8960_kraitv1[] = {
-	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 }, 1050000, 1050000, 0 },
-	[1]  = { {  384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
-	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 1 },
-	[3]  = { {  486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 1 },
-	[4]  = { {  540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 1 },
-	[5]  = { {  594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
-	[6]  = { {  648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 2 },
-	[7]  = { {  702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 2 },
-	[8]  = { {  756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 2 },
-	[9]  = { {  810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 3 },
-	[10] = { {  864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 3 },
-	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 3 },
-};
-
-static struct acpu_level acpu_freq_tbl_8960_kraitv1_slow[] = {
-	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
-	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
-	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   925000 },
-	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   925000 },
-	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   937500 },
-	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   962500 },
-	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),   987500 },
-	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),  1000000 },
-	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11), 1025000 },
-	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1062500 },
-	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1062500 },
-	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1087500 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8960_kraitv1_nom_fast[] = {
-	{ 0, {STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   862500 },
-	{ 1, {  384000, PLL_8, 0, 2, 0x00 }, L2(1),   862500 },
-	{ 1, {  432000, HFPLL, 2, 0, 0x20 }, L2(6),   862500 },
-	{ 1, {  486000, HFPLL, 2, 0, 0x24 }, L2(6),   887500 },
-	{ 1, {  540000, HFPLL, 2, 0, 0x28 }, L2(6),   900000 },
-	{ 1, {  594000, HFPLL, 1, 0, 0x16 }, L2(6),   925000 },
-	{ 1, {  648000, HFPLL, 1, 0, 0x18 }, L2(6),   925000 },
-	{ 1, {  702000, HFPLL, 1, 0, 0x1A }, L2(6),   937500 },
-	{ 1, {  756000, HFPLL, 1, 0, 0x1C }, L2(11),  962500 },
-	{ 1, {  810000, HFPLL, 1, 0, 0x1E }, L2(11), 1012500 },
-	{ 1, {  864000, HFPLL, 1, 0, 0x20 }, L2(11), 1025000 },
-	{ 1, {  918000, HFPLL, 1, 0, 0x22 }, L2(11), 1025000 },
-	{ 0, { 0 } }
-};
-
-#undef L2
-#define L2(x) (&l2_freq_tbl_8960_kraitv2[(x)])
-static struct l2_level l2_freq_tbl_8960_kraitv2[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
 	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 }, 1050000, 1050000, 0 },
 	[1]  = { {  384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
 	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
@@ -415,7 +110,7 @@
 	[19] = { { 1350000, HFPLL, 1, 0, 0x32 }, 1150000, 1150000, 6 },
 };
 
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_slow[] = {
+static struct acpu_level acpu_freq_tbl_slow[] __initdata = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
 	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   975000 },
@@ -442,7 +137,7 @@
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_nom[] = {
+static struct acpu_level acpu_freq_tbl_nom[] __initdata = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
 	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   925000 },
@@ -469,7 +164,7 @@
 	{ 0, { 0 } }
 };
 
-static struct acpu_level acpu_freq_tbl_8960_kraitv2_fast[] = {
+static struct acpu_level acpu_freq_tbl_fast[] __initdata = {
 	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   850000 },
 	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   850000 },
 	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   875000 },
@@ -496,935 +191,26 @@
 	{ 0, { 0 } }
 };
 
-/* TODO: Update vdd_dig and vdd_mem when voltage data is available. */
-#undef L2
-#define L2(x) (&l2_freq_tbl_8064[(x)])
-static struct l2_level l2_freq_tbl_8064[] = {
-	[0]  = { {STBY_KHZ, QSB,   0, 0, 0x00 }, 1050000, 1050000, 0 },
-	[1]  = { {  384000, PLL_8, 0, 2, 0x00 }, 1050000, 1050000, 1 },
-	[2]  = { {  432000, HFPLL, 2, 0, 0x20 }, 1050000, 1050000, 2 },
-	[3]  = { {  486000, HFPLL, 2, 0, 0x24 }, 1050000, 1050000, 2 },
-	[4]  = { {  540000, HFPLL, 2, 0, 0x28 }, 1050000, 1050000, 2 },
-	[5]  = { {  594000, HFPLL, 1, 0, 0x16 }, 1050000, 1050000, 2 },
-	[6]  = { {  648000, HFPLL, 1, 0, 0x18 }, 1050000, 1050000, 4 },
-	[7]  = { {  702000, HFPLL, 1, 0, 0x1A }, 1050000, 1050000, 4 },
-	[8]  = { {  756000, HFPLL, 1, 0, 0x1C }, 1150000, 1150000, 4 },
-	[9]  = { {  810000, HFPLL, 1, 0, 0x1E }, 1150000, 1150000, 4 },
-	[10] = { {  864000, HFPLL, 1, 0, 0x20 }, 1150000, 1150000, 4 },
-	[11] = { {  918000, HFPLL, 1, 0, 0x22 }, 1150000, 1150000, 7 },
-	[12] = { {  972000, HFPLL, 1, 0, 0x24 }, 1150000, 1150000, 7 },
-	[13] = { { 1026000, HFPLL, 1, 0, 0x26 }, 1150000, 1150000, 7 },
-	[14] = { { 1080000, HFPLL, 1, 0, 0x28 }, 1150000, 1150000, 7 },
-	[15] = { { 1134000, HFPLL, 1, 0, 0x2A }, 1150000, 1150000, 7 },
+static struct pvs_table pvs_tables[NUM_PVS] __initdata = {
+	[PVS_SLOW]    = { acpu_freq_tbl_slow, sizeof(acpu_freq_tbl_slow) },
+	[PVS_NOMINAL] = { acpu_freq_tbl_nom,  sizeof(acpu_freq_tbl_nom)  },
+	[PVS_FAST]    = { acpu_freq_tbl_fast, sizeof(acpu_freq_tbl_fast) },
 };
 
-/* TODO: Update core voltages when data is available. */
-static struct acpu_level acpu_freq_tbl_8064_slow[] = {
-	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   950000 },
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   950000 },
-	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   975000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   975000 },
-	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),  1000000 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),  1000000 },
-	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),  1025000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),  1025000 },
-	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1075000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1075000 },
-	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1100000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1100000 },
-	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1125000 },
-	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1125000 },
-	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1175000 },
-	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1175000 },
-	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1200000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1200000 },
-	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1225000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1225000 },
-	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1237500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1237500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1250000 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8064_nom[] = {
-	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   900000 },
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   900000 },
-	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   925000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   925000 },
-	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   950000 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   950000 },
-	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   975000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   975000 },
-	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),  1025000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),  1025000 },
-	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1050000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1050000 },
-	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1075000 },
-	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1075000 },
-	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1125000 },
-	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1125000 },
-	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1150000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1150000 },
-	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1175000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1175000 },
-	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1187500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1187500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1200000 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level acpu_freq_tbl_8064_fast[] = {
-	{ 0, { STBY_KHZ, QSB,   0, 0, 0x00 }, L2(0),   850000 },
-	{ 1, {   384000, PLL_8, 0, 2, 0x00 }, L2(1),   850000 },
-	{ 0, {   432000, HFPLL, 2, 0, 0x20 }, L2(7),   875000 },
-	{ 1, {   486000, HFPLL, 2, 0, 0x24 }, L2(7),   875000 },
-	{ 0, {   540000, HFPLL, 2, 0, 0x28 }, L2(7),   900000 },
-	{ 1, {   594000, HFPLL, 1, 0, 0x16 }, L2(7),   900000 },
-	{ 0, {   648000, HFPLL, 1, 0, 0x18 }, L2(7),   925000 },
-	{ 1, {   702000, HFPLL, 1, 0, 0x1A }, L2(7),   925000 },
-	{ 0, {   756000, HFPLL, 1, 0, 0x1C }, L2(7),   975000 },
-	{ 1, {   810000, HFPLL, 1, 0, 0x1E }, L2(7),   975000 },
-	{ 0, {   864000, HFPLL, 1, 0, 0x20 }, L2(7),  1000000 },
-	{ 1, {   918000, HFPLL, 1, 0, 0x22 }, L2(7),  1000000 },
-	{ 0, {   972000, HFPLL, 1, 0, 0x24 }, L2(7),  1025000 },
-	{ 1, {  1026000, HFPLL, 1, 0, 0x26 }, L2(7),  1025000 },
-	{ 0, {  1080000, HFPLL, 1, 0, 0x28 }, L2(15), 1075000 },
-	{ 1, {  1134000, HFPLL, 1, 0, 0x2A }, L2(15), 1075000 },
-	{ 0, {  1188000, HFPLL, 1, 0, 0x2C }, L2(15), 1100000 },
-	{ 1, {  1242000, HFPLL, 1, 0, 0x2E }, L2(15), 1100000 },
-	{ 0, {  1296000, HFPLL, 1, 0, 0x30 }, L2(15), 1125000 },
-	{ 1, {  1350000, HFPLL, 1, 0, 0x32 }, L2(15), 1125000 },
-	{ 0, {  1404000, HFPLL, 1, 0, 0x34 }, L2(15), 1137500 },
-	{ 1, {  1458000, HFPLL, 1, 0, 0x36 }, L2(15), 1137500 },
-	{ 1, {  1512000, HFPLL, 1, 0, 0x38 }, L2(15), 1150000 },
-	{ 0, { 0 } }
-};
-
-static struct acpu_level *acpu_freq_tbl_8960_v1[NUM_PVS] __initdata = {
-	[PVS_SLOW] = acpu_freq_tbl_8960_kraitv1_slow,
-	[PVS_NOM] = acpu_freq_tbl_8960_kraitv1_nom_fast,
-	[PVS_FAST] = acpu_freq_tbl_8960_kraitv1_nom_fast,
-};
-
-static struct acpu_level *acpu_freq_tbl_8960_v2[NUM_PVS] __initdata = {
-	[PVS_SLOW] = acpu_freq_tbl_8960_kraitv2_slow,
-	[PVS_NOM] = acpu_freq_tbl_8960_kraitv2_nom,
-	[PVS_FAST] = acpu_freq_tbl_8960_kraitv2_fast,
-};
-
-/* TODO: update the faster table when data is available */
-static struct acpu_level *acpu_freq_tbl_8064[NUM_PVS] __initdata = {
-	[PVS_SLOW] = acpu_freq_tbl_8064_slow,
-	[PVS_NOM] = acpu_freq_tbl_8064_nom,
-	[PVS_FAST] = acpu_freq_tbl_8064_fast,
-	[PVS_FASTER] = acpu_freq_tbl_8064_fast,
-};
-
-static struct acpu_level *max_acpu_level;
-
-static unsigned long acpuclk_8960_get_rate(int cpu)
-{
-	return scalable[cpu].current_speed->khz;
-}
-
-/* Get the selected source on primary MUX. */
-static int get_pri_clk_src(struct scalable *sc)
-{
-	uint32_t regval;
-
-	regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
-	return regval & 0x3;
-}
-
-/* Set the selected source on primary MUX. */
-static void set_pri_clk_src(struct scalable *sc, uint32_t pri_src_sel)
-{
-	uint32_t regval;
-
-	regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
-	regval &= ~0x3;
-	regval |= (pri_src_sel & 0x3);
-	set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-	/* Wait for switch to complete. */
-	mb();
-	udelay(1);
-}
-
-/* Get the selected source on secondary MUX. */
-static int get_sec_clk_src(struct scalable *sc)
-{
-	uint32_t regval;
-
-	regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
-	return (regval >> 2) & 0x3;
-}
-
-/* Set the selected source on secondary MUX. */
-static void set_sec_clk_src(struct scalable *sc, uint32_t sec_src_sel)
-{
-	uint32_t regval;
-
-	/* Disable secondary source clock gating during switch. */
-	regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
-	regval |= SECCLKAGD;
-	set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
-	/* Program the MUX. */
-	regval &= ~(0x3 << 2);
-	regval |= ((sec_src_sel & 0x3) << 2);
-	set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
-	/* Wait for switch to complete. */
-	mb();
-	udelay(1);
-
-	/* Re-enable secondary source clock gating. */
-	regval &= ~SECCLKAGD;
-	set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-}
-
-/* Enable an already-configured HFPLL. */
-static void hfpll_enable(struct scalable *sc, bool skip_regulators)
-{
-	int rc;
-
-	if (!skip_regulators) {
-		if (cpu_is_msm8960()) {
-			rc = rpm_vreg_set_voltage(
-					sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
-					sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
-					2050000,
-					sc->vreg[VREG_HFPLL_A].max_vdd, 0);
-			if (rc)
-				pr_err("%s regulator enable failed (%d)\n",
-					sc->vreg[VREG_HFPLL_A].name, rc);
-		}
-		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
-				sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 1800000,
-				sc->vreg[VREG_HFPLL_B].max_vdd, 0);
-		if (rc)
-			pr_err("%s regulator enable failed (%d)\n",
-				sc->vreg[VREG_HFPLL_B].name, rc);
-	}
-	/* Disable PLL bypass mode. */
-	writel_relaxed(0x2, sc->hfpll_base + HFPLL_MODE);
-
-	/*
-	 * H/W requires a 5us delay between disabling the bypass and
-	 * de-asserting the reset. Delay 10us just to be safe.
-	 */
-	mb();
-	udelay(10);
-
-	/* De-assert active-low PLL reset. */
-	writel_relaxed(0x6, sc->hfpll_base + HFPLL_MODE);
-
-	/* Wait for PLL to lock. */
-	mb();
-	udelay(60);
-
-	/* Enable PLL output. */
-	writel_relaxed(0x7, sc->hfpll_base + HFPLL_MODE);
-}
-
-/* Disable a HFPLL for power-savings or while its being reprogrammed. */
-static void hfpll_disable(struct scalable *sc, bool skip_regulators)
-{
-	int rc;
-
-	/*
-	 * Disable the PLL output, disable test mode, enable
-	 * the bypass mode, and assert the reset.
-	 */
-	writel_relaxed(0, sc->hfpll_base + HFPLL_MODE);
-
-	if (!skip_regulators) {
-		rc = rpm_vreg_set_voltage(sc->vreg[VREG_HFPLL_B].rpm_vreg_id,
-				sc->vreg[VREG_HFPLL_B].rpm_vreg_voter, 0,
-				0, 0);
-		if (rc)
-			pr_err("%s regulator enable failed (%d)\n",
-				sc->vreg[VREG_HFPLL_B].name, rc);
-
-		if (cpu_is_msm8960()) {
-			rc = rpm_vreg_set_voltage(
-					sc->vreg[VREG_HFPLL_A].rpm_vreg_id,
-					sc->vreg[VREG_HFPLL_A].rpm_vreg_voter,
-					0, 0, 0);
-			if (rc)
-				pr_err("%s regulator enable failed (%d)\n",
-					sc->vreg[VREG_HFPLL_A].name, rc);
-		}
-	}
-}
-
-/* Program the HFPLL rate. Assumes HFPLL is already disabled. */
-static void hfpll_set_rate(struct scalable *sc, struct core_speed *tgt_s)
-{
-	writel_relaxed(tgt_s->pll_l_val, sc->hfpll_base + HFPLL_L_VAL);
-}
-
-/* Return the L2 speed that should be applied. */
-static struct l2_level *compute_l2_level(struct scalable *sc,
-					 struct l2_level *vote_l)
-{
-	struct l2_level *new_l;
-	int cpu;
-
-	/* Bounds check. */
-	BUG_ON(vote_l >= (l2_freq_tbl + l2_freq_tbl_size));
-
-	/* Find max L2 speed vote. */
-	sc->l2_vote = vote_l;
-	new_l = l2_freq_tbl;
-	for_each_present_cpu(cpu)
-		new_l = max(new_l, scalable[cpu].l2_vote);
-
-	return new_l;
-}
-
-/* Update the bus bandwidth request. */
-static void set_bus_bw(unsigned int bw)
-{
-	int ret;
-
-	/* Bounds check. */
-	if (bw >= ARRAY_SIZE(bw_level_tbl)) {
-		pr_err("invalid bandwidth request (%d)\n", bw);
-		return;
-	}
-
-	/* Update bandwidth if request has changed. This may sleep. */
-	ret = msm_bus_scale_client_update_request(bus_perf_client, bw);
-	if (ret)
-		pr_err("bandwidth request failed (%d)\n", ret);
-}
-
-/* Set the CPU or L2 clock speed. */
-static void set_speed(struct scalable *sc, struct core_speed *tgt_s,
-		      enum setrate_reason reason)
-{
-	struct core_speed *strt_s = sc->current_speed;
-
-	if (tgt_s == strt_s)
-		return;
-
-	if (strt_s->src == HFPLL && tgt_s->src == HFPLL) {
-		/*
-		 * Move to an always-on source running at a frequency that does
-		 * not require an elevated CPU voltage. PLL8 is used here.
-		 */
-		set_sec_clk_src(sc, SEC_SRC_SEL_AUX);
-		set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
-
-		/* Program CPU HFPLL. */
-		hfpll_disable(sc, 1);
-		hfpll_set_rate(sc, tgt_s);
-		hfpll_enable(sc, 1);
-
-		/* Move CPU to HFPLL source. */
-		set_pri_clk_src(sc, tgt_s->pri_src_sel);
-	} else if (strt_s->src == HFPLL && tgt_s->src != HFPLL) {
-		/*
-		 * If responding to CPU_DEAD we must be running on another CPU.
-		 * Therefore, we can't access the downed CPU's clock MUX CP15
-		 * registers from here and can't change clock sources. If the
-		 * CPU is collapsed, however, it is still safe to turn off the
-		 * PLL without switching the MUX away from it.
-		 */
-		if (reason != SETRATE_HOTPLUG || sc == &scalable[L2]) {
-			set_sec_clk_src(sc, tgt_s->sec_src_sel);
-			set_pri_clk_src(sc, tgt_s->pri_src_sel);
-			hfpll_disable(sc, 0);
-		} else if (reason == SETRATE_HOTPLUG
-			   && msm_pm_verify_cpu_pc(SCALABLE_TO_CPU(sc))) {
-			hfpll_disable(sc, 0);
-		}
-	} else if (strt_s->src != HFPLL && tgt_s->src == HFPLL) {
-		/*
-		 * If responding to CPU_UP_PREPARE, we can't change CP15
-		 * registers for the CPU that's coming up since we're not
-		 * running on that CPU.  That's okay though, since the MUX
-		 * source was not changed on the way down, either.
-		 */
-		if (reason != SETRATE_HOTPLUG || sc == &scalable[L2]) {
-			hfpll_set_rate(sc, tgt_s);
-			hfpll_enable(sc, 0);
-			set_pri_clk_src(sc, tgt_s->pri_src_sel);
-		} else if (reason == SETRATE_HOTPLUG
-			   && msm_pm_verify_cpu_pc(SCALABLE_TO_CPU(sc))) {
-			/* PLL was disabled during hot-unplug. Re-enable it. */
-			hfpll_set_rate(sc, tgt_s);
-			hfpll_enable(sc, 0);
-		}
-	} else {
-		if (reason != SETRATE_HOTPLUG || sc == &scalable[L2])
-			set_sec_clk_src(sc, tgt_s->sec_src_sel);
-	}
-
-	sc->current_speed = tgt_s;
-}
-
-/* Apply any per-cpu voltage increases. */
-static int increase_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
-			unsigned int vdd_dig, enum setrate_reason reason)
-{
-	struct scalable *sc = &scalable[cpu];
-	int rc = 0;
-
-	/*
-	 * Increase vdd_mem active-set before vdd_dig.
-	 * vdd_mem should be >= vdd_dig.
-	 */
-	if (vdd_mem > sc->vreg[VREG_MEM].cur_vdd) {
-		rc = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
-				sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
-				sc->vreg[VREG_MEM].max_vdd, 0);
-		if (rc) {
-			pr_err("%s increase failed (%d)\n",
-				sc->vreg[VREG_MEM].name, rc);
-			return rc;
-		}
-		 sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
-	}
-
-	/* Increase vdd_dig active-set vote. */
-	if (vdd_dig > sc->vreg[VREG_DIG].cur_vdd) {
-		rc = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
-				sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
-				sc->vreg[VREG_DIG].max_vdd, 0);
-		if (rc) {
-			pr_err("%s increase failed (%d)\n",
-				sc->vreg[VREG_DIG].name, rc);
-			return rc;
-		}
-		sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
-	}
-
-	/*
-	 * Update per-CPU core voltage. Don't do this for the hotplug path for
-	 * which it should already be correct. Attempting to set it is bad
-	 * because we don't know what CPU we are running on at this point, but
-	 * the CPU regulator API requires we call it from the affected CPU.
-	 */
-	if (vdd_core > sc->vreg[VREG_CORE].cur_vdd
-						&& reason != SETRATE_HOTPLUG) {
-		rc = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
-					   sc->vreg[VREG_CORE].max_vdd);
-		if (rc) {
-			pr_err("%s increase failed (%d)\n",
-				sc->vreg[VREG_CORE].name, rc);
-			return rc;
-		}
-		sc->vreg[VREG_CORE].cur_vdd = vdd_core;
-	}
-
-	return rc;
-}
-
-/* Apply any per-cpu voltage decreases. */
-static void decrease_vdd(int cpu, unsigned int vdd_core, unsigned int vdd_mem,
-			 unsigned int vdd_dig, enum setrate_reason reason)
-{
-	struct scalable *sc = &scalable[cpu];
-	int ret;
-
-	/*
-	 * Update per-CPU core voltage. This must be called on the CPU
-	 * that's being affected. Don't do this in the hotplug remove path,
-	 * where the rail is off and we're executing on the other CPU.
-	 */
-	if (vdd_core < sc->vreg[VREG_CORE].cur_vdd
-					&& reason != SETRATE_HOTPLUG) {
-		ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
-					    sc->vreg[VREG_CORE].max_vdd);
-		if (ret) {
-			pr_err("%s decrease failed (%d)\n",
-			       sc->vreg[VREG_CORE].name, ret);
-			return;
-		}
-		sc->vreg[VREG_CORE].cur_vdd = vdd_core;
-	}
-
-	/* Decrease vdd_dig active-set vote. */
-	if (vdd_dig < sc->vreg[VREG_DIG].cur_vdd) {
-		ret = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
-				sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
-				sc->vreg[VREG_DIG].max_vdd, 0);
-		if (ret) {
-			pr_err("%s decrease failed (%d)\n",
-				sc->vreg[VREG_DIG].name, ret);
-			return;
-		}
-		sc->vreg[VREG_DIG].cur_vdd = vdd_dig;
-	}
-
-	/*
-	 * Decrease vdd_mem active-set after vdd_dig.
-	 * vdd_mem should be >= vdd_dig.
-	 */
-	if (vdd_mem < sc->vreg[VREG_MEM].cur_vdd) {
-		ret = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
-				sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
-				sc->vreg[VREG_MEM].max_vdd, 0);
-		if (ret) {
-			pr_err("%s decrease failed (%d)\n",
-				sc->vreg[VREG_MEM].name, ret);
-			return;
-		}
-		 sc->vreg[VREG_MEM].cur_vdd = vdd_mem;
-	}
-}
-
-static unsigned int calculate_vdd_mem(struct acpu_level *tgt)
-{
-	return tgt->l2_level->vdd_mem;
-}
-
-static unsigned int calculate_vdd_dig(struct acpu_level *tgt)
-{
-	unsigned int pll_vdd_dig;
-
-	if (tgt->l2_level->speed.src != HFPLL)
-		pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_NONE];
-	else if (tgt->l2_level->speed.pll_l_val > HFPLL_LOW_VDD_PLL_L_MAX)
-		pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_NOM];
-	else
-		pll_vdd_dig = scalable[L2].hfpll_vdd_tbl[HFPLL_VDD_LOW];
-
-	return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
-}
-
-static unsigned int calculate_vdd_core(struct acpu_level *tgt)
-{
-	return tgt->vdd_core;
-}
-
-/* Set the CPU's clock rate and adjust the L2 rate, if appropriate. */
-static int acpuclk_8960_set_rate(int cpu, unsigned long rate,
-				 enum setrate_reason reason)
-{
-	struct core_speed *strt_acpu_s, *tgt_acpu_s;
-	struct l2_level *tgt_l2_l;
-	struct acpu_level *tgt;
-	unsigned int vdd_mem, vdd_dig, vdd_core;
-	unsigned long flags;
-	int rc = 0;
-
-	if (cpu > num_possible_cpus())
-		return -EINVAL;
-
-	if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
-		mutex_lock(&driver_lock);
-
-	strt_acpu_s = scalable[cpu].current_speed;
-
-	/* Return early if rate didn't change. */
-	if (rate == strt_acpu_s->khz)
-		goto out;
-
-	/* Find target frequency. */
-	for (tgt = acpu_freq_tbl; tgt->speed.khz != 0; tgt++) {
-		if (tgt->speed.khz == rate) {
-			tgt_acpu_s = &tgt->speed;
-			break;
-		}
-	}
-	if (tgt->speed.khz == 0) {
-		rc = -EINVAL;
-		goto out;
-	}
-
-	/* Calculate voltage requirements for the current CPU. */
-	vdd_mem  = calculate_vdd_mem(tgt);
-	vdd_dig  = calculate_vdd_dig(tgt);
-	vdd_core = calculate_vdd_core(tgt);
-
-	/* Increase VDD levels if needed. */
-	if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG) {
-		rc = increase_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
-		if (rc)
-			goto out;
-	}
-
-	pr_debug("Switching from ACPU%d rate %u KHz -> %u KHz\n",
-		cpu, strt_acpu_s->khz, tgt_acpu_s->khz);
-
-	/* Set the CPU speed. */
-	set_speed(&scalable[cpu], tgt_acpu_s, reason);
-
-	/*
-	 * Update the L2 vote and apply the rate change. A spinlock is
-	 * necessary to ensure L2 rate is calulated and set atomically,
-	 * even if acpuclk_8960_set_rate() is called from an atomic context
-	 * and the driver_lock mutex is not acquired.
-	 */
-	spin_lock_irqsave(&l2_lock, flags);
-	tgt_l2_l = compute_l2_level(&scalable[cpu], tgt->l2_level);
-	set_speed(&scalable[L2], &tgt_l2_l->speed, reason);
-	spin_unlock_irqrestore(&l2_lock, flags);
-
-	/* Nothing else to do for power collapse or SWFI. */
-	if (reason == SETRATE_PC || reason == SETRATE_SWFI)
-		goto out;
-
-	/* Update bus bandwith request. */
-	set_bus_bw(tgt_l2_l->bw_level);
-
-	/* Drop VDD levels if we can. */
-	decrease_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
-
-	pr_debug("ACPU%d speed change complete\n", cpu);
-
-out:
-	if (reason == SETRATE_CPUFREQ || reason == SETRATE_HOTPLUG)
-		mutex_unlock(&driver_lock);
-	return rc;
-}
-
-/* Initialize a HFPLL at a given rate and enable it. */
-static void __cpuinit hfpll_init(struct scalable *sc, struct core_speed *tgt_s)
-{
-	pr_debug("Initializing HFPLL%d\n", sc - scalable);
-
-	/* Disable the PLL for re-programming. */
-	hfpll_disable(sc, 1);
-
-	/* Configure PLL parameters for integer mode. */
-	writel_relaxed(0x7845C665, sc->hfpll_base + HFPLL_CONFIG_CTL);
-	writel_relaxed(0, sc->hfpll_base + HFPLL_M_VAL);
-	writel_relaxed(1, sc->hfpll_base + HFPLL_N_VAL);
-
-	/* Program droop controller. */
-	writel_relaxed(0x0108C000, sc->hfpll_base + HFPLL_DROOP_CTL);
-
-	/* Set an initial rate and enable the PLL. */
-	hfpll_set_rate(sc, tgt_s);
-	hfpll_enable(sc, 0);
-}
-
-/* Voltage regulator initialization. */
-static void __cpuinit regulator_init(int cpu, struct acpu_level *lvl)
-{
-	int ret;
-	struct scalable *sc = &scalable[cpu];
-	unsigned int vdd_mem, vdd_dig, vdd_core;
-
-	vdd_mem = calculate_vdd_mem(lvl);
-	vdd_dig = calculate_vdd_dig(lvl);
-
-	/* Set initial vdd_mem vote. */
-	ret = rpm_vreg_set_voltage(sc->vreg[VREG_MEM].rpm_vreg_id,
-			sc->vreg[VREG_MEM].rpm_vreg_voter, vdd_mem,
-			sc->vreg[VREG_MEM].max_vdd, 0);
-	if (ret) {
-		pr_err("%s initialization failed (%d)\n",
-			sc->vreg[VREG_MEM].name, ret);
-		BUG();
-	}
-	sc->vreg[VREG_MEM].cur_vdd  = vdd_mem;
-
-	/* Set initial vdd_dig vote. */
-	ret = rpm_vreg_set_voltage(sc->vreg[VREG_DIG].rpm_vreg_id,
-			sc->vreg[VREG_DIG].rpm_vreg_voter, vdd_dig,
-			sc->vreg[VREG_DIG].max_vdd, 0);
-	if (ret) {
-		pr_err("%s initialization failed (%d)\n",
-			sc->vreg[VREG_DIG].name, ret);
-		BUG();
-	}
-	sc->vreg[VREG_DIG].cur_vdd  = vdd_dig;
-
-	/* Setup Krait CPU regulators and initial core voltage. */
-	sc->vreg[VREG_CORE].reg = regulator_get(NULL,
-				  sc->vreg[VREG_CORE].name);
-	if (IS_ERR(sc->vreg[VREG_CORE].reg)) {
-		pr_err("regulator_get(%s) failed (%ld)\n",
-		       sc->vreg[VREG_CORE].name,
-		       PTR_ERR(sc->vreg[VREG_CORE].reg));
-		BUG();
-	}
-	vdd_core = calculate_vdd_core(lvl);
-	ret = regulator_set_voltage(sc->vreg[VREG_CORE].reg, vdd_core,
-				    sc->vreg[VREG_CORE].max_vdd);
-	if (ret) {
-		pr_err("%s initialization failed (%d)\n",
-			sc->vreg[VREG_CORE].name, ret);
-		BUG();
-	}
-	sc->vreg[VREG_CORE].cur_vdd = vdd_core;
-	ret = regulator_enable(sc->vreg[VREG_CORE].reg);
-	if (ret) {
-		pr_err("regulator_enable(%s) failed (%d)\n",
-		       sc->vreg[VREG_CORE].name, ret);
-		BUG();
-	}
-	sc->regulators_initialized = true;
-}
-
-/* Set initial rate for a given core. */
-static void __cpuinit init_clock_sources(struct scalable *sc,
-				      struct core_speed *tgt_s)
-{
-	uint32_t regval;
-
-	/* Select PLL8 as AUX source input to the secondary MUX. */
-	writel_relaxed(0x3, sc->aux_clk_sel);
-
-	/* Switch away from the HFPLL while it's re-initialized. */
-	set_sec_clk_src(sc, SEC_SRC_SEL_AUX);
-	set_pri_clk_src(sc, PRI_SRC_SEL_SEC_SRC);
-	hfpll_init(sc, tgt_s);
-
-	/* Set PRI_SRC_SEL_HFPLL_DIV2 divider to div-2. */
-	regval = get_l2_indirect_reg(sc->l2cpmr_iaddr);
-	regval &= ~(0x3 << 6);
-	set_l2_indirect_reg(sc->l2cpmr_iaddr, regval);
-
-	/* Switch to the target clock source. */
-	set_sec_clk_src(sc, tgt_s->sec_src_sel);
-	set_pri_clk_src(sc, tgt_s->pri_src_sel);
-	sc->current_speed = tgt_s;
-}
-
-static void __cpuinit per_cpu_init(void *data)
-{
-	int cpu = smp_processor_id();
-
-	init_clock_sources(&scalable[cpu], &max_acpu_level->speed);
-	scalable[cpu].l2_vote = max_acpu_level->l2_level;
-	scalable[cpu].clocks_initialized = true;
-}
-
-/* Register with bus driver. */
-static void __init bus_init(unsigned int init_bw)
-{
-	int ret;
-
-	bus_perf_client = msm_bus_scale_register_client(&bus_client_pdata);
-	if (!bus_perf_client) {
-		pr_err("unable to register bus client\n");
-		BUG();
-	}
-
-	ret = msm_bus_scale_client_update_request(bus_perf_client, init_bw);
-	if (ret)
-		pr_err("initial bandwidth request failed (%d)\n", ret);
-}
-
-#ifdef CONFIG_CPU_FREQ_MSM
-static struct cpufreq_frequency_table freq_table[NR_CPUS][30];
-
-static void __init cpufreq_table_init(void)
-{
-	int cpu;
-
-	for_each_possible_cpu(cpu) {
-		int i, freq_cnt = 0;
-		/* Construct the freq_table tables from acpu_freq_tbl. */
-		for (i = 0; acpu_freq_tbl[i].speed.khz != 0
-				&& freq_cnt < ARRAY_SIZE(*freq_table); i++) {
-			if (acpu_freq_tbl[i].use_for_scaling) {
-				freq_table[cpu][freq_cnt].index = freq_cnt;
-				freq_table[cpu][freq_cnt].frequency
-					= acpu_freq_tbl[i].speed.khz;
-				freq_cnt++;
-			}
-		}
-		/* freq_table not big enough to store all usable freqs. */
-		BUG_ON(acpu_freq_tbl[i].speed.khz != 0);
-
-		freq_table[cpu][freq_cnt].index = freq_cnt;
-		freq_table[cpu][freq_cnt].frequency = CPUFREQ_TABLE_END;
-
-		pr_info("CPU%d: %d scaling frequencies supported.\n",
-			cpu, freq_cnt);
-
-		/* Register table with CPUFreq. */
-		cpufreq_frequency_table_get_attr(freq_table[cpu], cpu);
-	}
-}
-#else
-static void __init cpufreq_table_init(void) {}
-#endif
-
-#define HOT_UNPLUG_KHZ STBY_KHZ
-static int __cpuinit acpuclock_cpu_callback(struct notifier_block *nfb,
-					    unsigned long action, void *hcpu)
-{
-	static int prev_khz[NR_CPUS];
-	static int prev_pri_src[NR_CPUS];
-	static int prev_sec_src[NR_CPUS];
-	int cpu = (int)hcpu;
-
-	switch (action) {
-	case CPU_DYING:
-	case CPU_DYING_FROZEN:
-		/*
-		 * On Krait v1 and 8064v1, the primary and secondary muxes must
-		 * be set to QSB before L2 power collapse and restored after.
-		 */
-		if (cpu_is_krait_v1() || cpu_is_apq8064()) {
-			prev_sec_src[cpu] = get_sec_clk_src(&scalable[cpu]);
-			prev_pri_src[cpu] = get_pri_clk_src(&scalable[cpu]);
-			set_sec_clk_src(&scalable[cpu], SEC_SRC_SEL_QSB);
-			set_pri_clk_src(&scalable[cpu], PRI_SRC_SEL_SEC_SRC);
-		}
-		break;
-	case CPU_DEAD:
-	case CPU_DEAD_FROZEN:
-		prev_khz[cpu] = acpuclk_8960_get_rate(cpu);
-		/* Fall through. */
-	case CPU_UP_CANCELED:
-	case CPU_UP_CANCELED_FROZEN:
-		if (scalable[cpu].clocks_initialized)
-			acpuclk_8960_set_rate(cpu, HOT_UNPLUG_KHZ,
-					      SETRATE_HOTPLUG);
-		break;
-	case CPU_UP_PREPARE:
-	case CPU_UP_PREPARE_FROZEN:
-		if (scalable[cpu].clocks_initialized)
-			acpuclk_8960_set_rate(cpu, prev_khz[cpu],
-					      SETRATE_HOTPLUG);
-		if (!scalable[cpu].regulators_initialized)
-			regulator_init(cpu, max_acpu_level);
-		break;
-	case CPU_STARTING:
-	case CPU_STARTING_FROZEN:
-		if (!scalable[cpu].clocks_initialized) {
-			per_cpu_init(NULL);
-		} else if (cpu_is_krait_v1() || cpu_is_apq8064()) {
-			set_sec_clk_src(&scalable[cpu], prev_sec_src[cpu]);
-			set_pri_clk_src(&scalable[cpu], prev_pri_src[cpu]);
-		}
-		break;
-	default:
-		break;
-	}
-
-	return NOTIFY_OK;
-}
-
-static struct notifier_block __cpuinitdata acpuclock_cpu_notifier = {
-	.notifier_call = acpuclock_cpu_callback,
-};
-
-static const int krait_needs_vmin(void)
-{
-	switch (read_cpuid_id()) {
-	case 0x511F04D0:
-	case 0x511F04D1:
-	case 0x510F06F0:
-		return 1;
-	default:
-		return 0;
-	};
-}
-
-static void kraitv2_apply_vmin(struct acpu_level *tbl)
-{
-	for (; tbl->speed.khz != 0; tbl++)
-		if (tbl->vdd_core < 1150000)
-			tbl->vdd_core = 1150000;
-}
-
-static enum pvs __init get_pvs(void)
-{
-	uint32_t pte_efuse, pvs;
-
-	pte_efuse = readl_relaxed(QFPROM_PTE_EFUSE_ADDR);
-	pvs = (pte_efuse >> 10) & 0x7;
-	if (pvs == 0x7)
-		pvs = (pte_efuse >> 13) & 0x7;
-
-	switch (pvs) {
-	case 0x0:
-	case 0x7:
-		pr_info("ACPU PVS: Slow\n");
-		return PVS_SLOW;
-	case 0x1:
-		pr_info("ACPU PVS: Nominal\n");
-		return PVS_NOM;
-	case 0x3:
-		pr_info("ACPU PVS: Fast\n");
-		return PVS_FAST;
-	case 0x4:
-		if (cpu_is_apq8064()) {
-			pr_info("ACPU PVS: Faster\n");
-			return  PVS_FASTER;
-		}
-	default:
-		pr_warn("ACPU PVS: Unknown. Defaulting to slow\n");
-		return PVS_SLOW;
-	}
-}
-
-static void __init select_freq_plan(void)
-{
-	struct acpu_level *l;
-
-	/* Select frequency tables. */
-	if (cpu_is_msm8960()) {
-		enum pvs pvs_id = get_pvs();
-
-		scalable = scalable_8960;
-		if (cpu_is_krait_v1()) {
-			acpu_freq_tbl = acpu_freq_tbl_8960_v1[pvs_id];
-			l2_freq_tbl = l2_freq_tbl_8960_kraitv1;
-			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv1);
-		} else {
-			acpu_freq_tbl = acpu_freq_tbl_8960_v2[pvs_id];
-			l2_freq_tbl = l2_freq_tbl_8960_kraitv2;
-			l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8960_kraitv2);
-		}
-	} else if (cpu_is_apq8064()) {
-		enum pvs pvs_id = get_pvs();
-
-		scalable = scalable_8064;
-		acpu_freq_tbl = acpu_freq_tbl_8064[pvs_id];
-		l2_freq_tbl = l2_freq_tbl_8064;
-		l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl_8064);
-	} else {
-		BUG();
-	}
-	BUG_ON(!acpu_freq_tbl);
-	if (krait_needs_vmin())
-		kraitv2_apply_vmin(acpu_freq_tbl);
-
-	/* Find the max supported scaling frequency. */
-	for (l = acpu_freq_tbl; l->speed.khz != 0; l++)
-		if (l->use_for_scaling)
-			max_acpu_level = l;
-	BUG_ON(!max_acpu_level);
-	pr_info("Max ACPU freq: %u KHz\n", max_acpu_level->speed.khz);
-}
-
-static struct acpuclk_data acpuclk_8960_data = {
-	.set_rate = acpuclk_8960_set_rate,
-	.get_rate = acpuclk_8960_get_rate,
-	.power_collapse_khz = STBY_KHZ,
-	.wait_for_irq_khz = STBY_KHZ,
+static struct acpuclk_krait_params acpuclk_8960_params __initdata = {
+	.scalable = scalable,
+	.scalable_size = sizeof(scalable),
+	.hfpll_data = &hfpll_data,
+	.pvs_tables = pvs_tables,
+	.l2_freq_tbl = l2_freq_tbl,
+	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
+	.bus_scale = &bus_scale_data,
+	.qfprom_phys_base = 0x00700000,
 };
 
 static int __init acpuclk_8960_probe(struct platform_device *pdev)
 {
-	int cpu;
-
-	select_freq_plan();
-
-	for_each_online_cpu(cpu)
-		regulator_init(cpu, max_acpu_level);
-	bus_init(max_acpu_level->l2_level->bw_level);
-
-	init_clock_sources(&scalable[L2], &max_acpu_level->l2_level->speed);
-	on_each_cpu(per_cpu_init, NULL, true);
-
-	cpufreq_table_init();
-
-	acpuclk_register(&acpuclk_8960_data);
-	register_hotcpu_notifier(&acpuclock_cpu_notifier);
-
-	return 0;
+	return acpuclk_krait_init(&pdev->dev, &acpuclk_8960_params);
 }
 
 static struct platform_driver acpuclk_8960_driver = {
diff --git a/arch/arm/mach-msm/acpuclock-8974.c b/arch/arm/mach-msm/acpuclock-8974.c
index 8cf9c2b..9ed038b 100644
--- a/arch/arm/mach-msm/acpuclock-8974.c
+++ b/arch/arm/mach-msm/acpuclock-8974.c
@@ -28,21 +28,7 @@
 #define LVL_NOM		RPM_REGULATOR_CORNER_NORMAL
 #define LVL_HIGH	RPM_REGULATOR_CORNER_SUPER_TURBO
 
-static struct hfpll_data hfpll_data_cpu = {
-	.mode_offset = 0x00,
-	.l_offset = 0x04,
-	.m_offset = 0x08,
-	.n_offset = 0x0C,
-	.config_offset = 0x14,
-	/* TODO: Verify magic number for 8974 when available. */
-	.config_val = 0x7845C665,
-	.low_vdd_l_max = 52,
-	.vdd[HFPLL_VDD_NONE] = 0,
-	.vdd[HFPLL_VDD_LOW]  = 810000,
-	.vdd[HFPLL_VDD_NOM]  = 900000,
-};
-
-static struct hfpll_data hfpll_data_l2 = {
+static struct hfpll_data hfpll_data __initdata = {
 	.mode_offset = 0x00,
 	.l_offset = 0x04,
 	.m_offset = 0x08,
@@ -56,10 +42,9 @@
 	.vdd[HFPLL_VDD_NOM]  = LVL_NOM,
 };
 
-static struct scalable scalable[] = {
+static struct scalable scalable[] __initdata = {
 	[CPU0] = {
 		.hfpll_phys_base = 0xF908A000,
-		.hfpll_data = &hfpll_data_cpu,
 		.l2cpmr_iaddr = 0x4501,
 		.vreg[VREG_CORE] = { "krait0",     1050000, 3200000 },
 		.vreg[VREG_MEM]  = { "krait0_mem", 1050000 },
@@ -69,7 +54,6 @@
 	},
 	[CPU1] = {
 		.hfpll_phys_base = 0xF909A000,
-		.hfpll_data = &hfpll_data_cpu,
 		.l2cpmr_iaddr = 0x5501,
 		.vreg[VREG_CORE] = { "krait1",     1050000, 3200000 },
 		.vreg[VREG_MEM]  = { "krait1_mem", 1050000 },
@@ -79,7 +63,6 @@
 	},
 	[CPU2] = {
 		.hfpll_phys_base = 0xF90AA000,
-		.hfpll_data = &hfpll_data_cpu,
 		.l2cpmr_iaddr = 0x6501,
 		.vreg[VREG_CORE] = { "krait2",     1050000, 3200000 },
 		.vreg[VREG_MEM]  = { "krait2_mem", 1050000 },
@@ -89,7 +72,6 @@
 	},
 	[CPU3] = {
 		.hfpll_phys_base = 0xF90BA000,
-		.hfpll_data = &hfpll_data_cpu,
 		.l2cpmr_iaddr = 0x7501,
 		.vreg[VREG_CORE] = { "krait3",     1050000, 3200000 },
 		.vreg[VREG_MEM]  = { "krait3_mem", 1050000 },
@@ -99,14 +81,13 @@
 	},
 	[L2] = {
 		.hfpll_phys_base = 0xF9016000,
-		.hfpll_data = &hfpll_data_l2,
 		.l2cpmr_iaddr = 0x0500,
 		.vreg[VREG_HFPLL_A] = { "l2_hfpll_a", 2150000 },
 		.vreg[VREG_HFPLL_B] = { "l2_hfpll_b", 1800000 },
 	},
 };
 
-static struct msm_bus_paths bw_level_tbl[] = {
+static struct msm_bus_paths bw_level_tbl[] __initdata = {
 	[0] =  BW_MBPS(400), /* At least  50 MHz on bus. */
 	[1] =  BW_MBPS(800), /* At least 100 MHz on bus. */
 	[2] = BW_MBPS(1334), /* At least 167 MHz on bus. */
@@ -114,15 +95,14 @@
 	[4] = BW_MBPS(3200), /* At least 333 MHz on bus. */
 };
 
-static struct msm_bus_scale_pdata bus_scale_data = {
+static struct msm_bus_scale_pdata bus_scale_data __initdata = {
 	.usecase = bw_level_tbl,
 	.num_usecases = ARRAY_SIZE(bw_level_tbl),
 	.active_only = 1,
 	.name = "acpuclk-8974",
 };
 
-#define L2(x) (&l2_freq_tbl[(x)])
-static struct l2_level l2_freq_tbl[] = {
+static struct l2_level l2_freq_tbl[] __initdata = {
 	[0]  = { {STBY_KHZ, QSB,   0, 0,   0 }, LVL_LOW, 1050000, 0 },
 	[1]  = { {  300000, PLL_0, 0, 2,   0 }, LVL_LOW, 1050000, 2 },
 	[2]  = { {  384000, HFPLL, 2, 0,  40 }, LVL_NOM, 1050000, 2 },
@@ -137,7 +117,7 @@
 	[11] = { { 1036800, HFPLL, 1, 0,  54 }, LVL_NOM, 1050000, 4 },
 };
 
-static struct acpu_level acpu_freq_tbl[] = {
+static struct acpu_level acpu_freq_tbl[] __initdata = {
 	{ 0, {STBY_KHZ, QSB,   0, 0,   0 }, L2(0),  1050000 },
 	{ 1, {  300000, PLL_0, 0, 2,   0 }, L2(1),  1050000 },
 	{ 1, {  384000, HFPLL, 2, 0,  40 }, L2(2),  1050000 },
@@ -153,14 +133,20 @@
 	{ 0, { 0 } }
 };
 
-static struct acpuclk_krait_params acpuclk_8974_params = {
+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 acpuclk_krait_params acpuclk_8974_params __initdata = {
 	.scalable = scalable,
-	.pvs_acpu_freq_tbl[PVS_SLOW] = acpu_freq_tbl,
-	.pvs_acpu_freq_tbl[PVS_NOMINAL] = acpu_freq_tbl,
-	.pvs_acpu_freq_tbl[PVS_FAST] = acpu_freq_tbl,
+	.scalable_size = sizeof(scalable),
+	.hfpll_data = &hfpll_data,
+	.pvs_tables = pvs_tables,
 	.l2_freq_tbl = l2_freq_tbl,
-	.l2_freq_tbl_size = ARRAY_SIZE(l2_freq_tbl),
-	.bus_scale_data = &bus_scale_data,
+	.l2_freq_tbl_size = sizeof(l2_freq_tbl),
+	.bus_scale = &bus_scale_data,
 	.qfprom_phys_base = 0xFC4A8000,
 };
 
diff --git a/arch/arm/mach-msm/acpuclock-krait.c b/arch/arm/mach-msm/acpuclock-krait.c
index 8bd54e3..fd43f57 100644
--- a/arch/arm/mach-msm/acpuclock-krait.c
+++ b/arch/arm/mach-msm/acpuclock-krait.c
@@ -57,7 +57,9 @@
 	const struct acpu_level *max_acpu_lvl;
 	const struct l2_level *l2_freq_tbl;
 	struct scalable *scalable;
+	struct hfpll_data *hfpll_data;
 	u32 bus_perf_client;
+	struct msm_bus_scale_pdata *bus_scale;
 	struct device *dev;
 } drv;
 
@@ -130,7 +132,7 @@
 	}
 
 	/* Disable PLL bypass mode. */
-	writel_relaxed(0x2, sc->hfpll_base + sc->hfpll_data->mode_offset);
+	writel_relaxed(0x2, sc->hfpll_base + drv.hfpll_data->mode_offset);
 
 	/*
 	 * H/W requires a 5us delay between disabling the bypass and
@@ -140,14 +142,14 @@
 	udelay(10);
 
 	/* De-assert active-low PLL reset. */
-	writel_relaxed(0x6, sc->hfpll_base + sc->hfpll_data->mode_offset);
+	writel_relaxed(0x6, sc->hfpll_base + drv.hfpll_data->mode_offset);
 
 	/* Wait for PLL to lock. */
 	mb();
 	udelay(60);
 
 	/* Enable PLL output. */
-	writel_relaxed(0x7, sc->hfpll_base + sc->hfpll_data->mode_offset);
+	writel_relaxed(0x7, sc->hfpll_base + drv.hfpll_data->mode_offset);
 }
 
 /* Disable a HFPLL for power-savings or while it's being reprogrammed. */
@@ -157,7 +159,7 @@
 	 * Disable the PLL output, disable test mode, enable the bypass mode,
 	 * and assert the reset.
 	 */
-	writel_relaxed(0, sc->hfpll_base + sc->hfpll_data->mode_offset);
+	writel_relaxed(0, sc->hfpll_base + drv.hfpll_data->mode_offset);
 
 	if (!skip_regulators) {
 		/* Remove voltage votes required by the HFPLL. */
@@ -170,19 +172,17 @@
 static void hfpll_set_rate(struct scalable *sc, const struct core_speed *tgt_s)
 {
 	writel_relaxed(tgt_s->pll_l_val,
-		sc->hfpll_base + sc->hfpll_data->l_offset);
+		sc->hfpll_base + drv.hfpll_data->l_offset);
 }
 
 /* Return the L2 speed that should be applied. */
-static const struct l2_level *compute_l2_level(struct scalable *sc,
-					       const struct l2_level *vote_l)
+static unsigned int compute_l2_level(struct scalable *sc, unsigned int vote_l)
 {
-	const struct l2_level *new_l;
+	unsigned int new_l = 0;
 	int cpu;
 
 	/* Find max L2 speed vote. */
 	sc->l2_vote = vote_l;
-	new_l = drv.l2_freq_tbl;
 	for_each_present_cpu(cpu)
 		new_l = max(new_l, drv.scalable[cpu].l2_vote);
 
@@ -350,23 +350,23 @@
 
 static int calculate_vdd_mem(const struct acpu_level *tgt)
 {
-	return tgt->l2_level->vdd_mem;
+	return drv.l2_freq_tbl[tgt->l2_level].vdd_mem;
 }
 
 static int calculate_vdd_dig(const struct acpu_level *tgt)
 {
 	int pll_vdd_dig;
-	const int *hfpll_vdd = drv.scalable[L2].hfpll_data->vdd;
-	const u32 low_vdd_l_max = drv.scalable[L2].hfpll_data->low_vdd_l_max;
+	const int *hfpll_vdd = drv.hfpll_data->vdd;
+	const u32 low_vdd_l_max = drv.hfpll_data->low_vdd_l_max;
 
-	if (tgt->l2_level->speed.src != HFPLL)
+	if (drv.l2_freq_tbl[tgt->l2_level].speed.src != HFPLL)
 		pll_vdd_dig = hfpll_vdd[HFPLL_VDD_NONE];
-	else if (tgt->l2_level->speed.pll_l_val > low_vdd_l_max)
+	else if (drv.l2_freq_tbl[tgt->l2_level].speed.pll_l_val > low_vdd_l_max)
 		pll_vdd_dig = hfpll_vdd[HFPLL_VDD_NOM];
 	else
 		pll_vdd_dig = hfpll_vdd[HFPLL_VDD_LOW];
 
-	return max(tgt->l2_level->vdd_dig, pll_vdd_dig);
+	return max(drv.l2_freq_tbl[tgt->l2_level].vdd_dig, pll_vdd_dig);
 }
 
 static int calculate_vdd_core(const struct acpu_level *tgt)
@@ -379,8 +379,8 @@
 				  enum setrate_reason reason)
 {
 	const struct core_speed *strt_acpu_s, *tgt_acpu_s;
-	const struct l2_level *tgt_l2_l;
 	const struct acpu_level *tgt;
+	int tgt_l2_l;
 	int vdd_mem, vdd_dig, vdd_core;
 	unsigned long flags;
 	int rc = 0;
@@ -436,7 +436,7 @@
 	 */
 	spin_lock_irqsave(&l2_lock, flags);
 	tgt_l2_l = compute_l2_level(&drv.scalable[cpu], tgt->l2_level);
-	set_speed(&drv.scalable[L2], &tgt_l2_l->speed);
+	set_speed(&drv.scalable[L2], &drv.l2_freq_tbl[tgt_l2_l].speed);
 	spin_unlock_irqrestore(&l2_lock, flags);
 
 	/* Nothing else to do for power collapse or SWFI. */
@@ -444,7 +444,7 @@
 		goto out;
 
 	/* Update bus bandwith request. */
-	set_bus_bw(tgt_l2_l->bw_level);
+	set_bus_bw(drv.l2_freq_tbl[tgt_l2_l].bw_level);
 
 	/* Drop VDD levels if we can. */
 	decrease_vdd(cpu, vdd_core, vdd_mem, vdd_dig, reason);
@@ -467,15 +467,15 @@
 	hfpll_disable(sc, true);
 
 	/* Configure PLL parameters for integer mode. */
-	writel_relaxed(sc->hfpll_data->config_val,
-		       sc->hfpll_base + sc->hfpll_data->config_offset);
-	writel_relaxed(0, sc->hfpll_base + sc->hfpll_data->m_offset);
-	writel_relaxed(1, sc->hfpll_base + sc->hfpll_data->n_offset);
+	writel_relaxed(drv.hfpll_data->config_val,
+		       sc->hfpll_base + drv.hfpll_data->config_offset);
+	writel_relaxed(0, sc->hfpll_base + drv.hfpll_data->m_offset);
+	writel_relaxed(1, sc->hfpll_base + drv.hfpll_data->n_offset);
 
 	/* Program droop controller, if supported */
-	if (sc->hfpll_data->has_droop_ctl)
-		writel_relaxed(sc->hfpll_data->droop_val,
-			       sc->hfpll_base + sc->hfpll_data->droop_offset);
+	if (drv.hfpll_data->has_droop_ctl)
+		writel_relaxed(drv.hfpll_data->droop_val,
+			       sc->hfpll_base + drv.hfpll_data->droop_offset);
 
 	/* Set an initial rate and enable the PLL. */
 	hfpll_set_rate(sc, tgt_s);
@@ -679,18 +679,18 @@
 }
 
 /* Register with bus driver. */
-static void __init bus_init(struct msm_bus_scale_pdata *bus_scale_data)
+static void __init bus_init(void)
 {
 	int ret;
 
-	drv.bus_perf_client = msm_bus_scale_register_client(bus_scale_data);
+	drv.bus_perf_client = msm_bus_scale_register_client(drv.bus_scale);
 	if (!drv.bus_perf_client) {
 		dev_err(drv.dev, "unable to register bus client\n");
 		BUG();
 	}
 
 	ret = msm_bus_scale_client_update_request(drv.bus_perf_client,
-					drv.max_acpu_lvl->l2_level->bw_level);
+			drv.l2_freq_tbl[drv.max_acpu_lvl->l2_level].bw_level);
 	if (ret)
 		dev_err(drv.dev, "initial bandwidth req failed (%d)\n", ret);
 }
@@ -792,13 +792,11 @@
 			tbl->vdd_core = 1150000;
 }
 
-static void __init select_freq_plan(struct acpu_level *const *pvs_tbl,
-				    u32 qfprom_phys)
+static int __init select_freq_plan(u32 qfprom_phys)
 {
-	const struct acpu_level *l;
 	void __iomem *qfprom_base;
 	u32 pte_efuse, pvs, tbl_idx;
-	char *pvs_names[] = { "Slow", "Nominal", "Fast", "Unknown" };
+	char *pvs_names[] = { "Slow", "Nominal", "Fast", "Faster", "Unknown" };
 
 	qfprom_base = ioremap(qfprom_phys, SZ_256);
 	/* Select frequency tables. */
@@ -820,6 +818,9 @@
 		case 0x3:
 			tbl_idx = PVS_FAST;
 			break;
+		case 0x4:
+			tbl_idx = PVS_FASTER;
+			break;
 		default:
 			tbl_idx = PVS_UNKNOWN;
 			break;
@@ -828,24 +829,29 @@
 		tbl_idx = PVS_UNKNOWN;
 		dev_err(drv.dev, "Unable to map QFPROM base\n");
 	}
-	dev_info(drv.dev, "ACPU PVS: %s\n", pvs_names[tbl_idx]);
 	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]);
 	}
-	drv.acpu_freq_tbl = pvs_tbl[tbl_idx];
 
-	if (krait_needs_vmin())
-		krait_apply_vmin(drv.acpu_freq_tbl);
+	return tbl_idx;
+}
 
-	/* Find the max supported scaling frequency. */
-	for (l = drv.acpu_freq_tbl; l->speed.khz != 0; l++)
+static const struct acpu_level __init *find_max_acpu_lvl(struct acpu_level *tbl)
+{
+	struct acpu_level *l, *max_lvl = NULL;
+
+	for (l = tbl; l->speed.khz != 0; l++)
 		if (l->use_for_scaling)
-			drv.max_acpu_lvl = l;
-	BUG_ON(!drv.max_acpu_lvl);
-	dev_info(drv.dev, "Max ACPU freq: %lu KHz\n",
-		 drv.max_acpu_lvl->speed.khz);
+			max_lvl = l;
+
+	BUG_ON(!max_lvl);
+	dev_info(drv.dev, "Max CPU freq: %lu KHz\n", max_lvl->speed.khz);
+
+	return max_lvl;
 }
 
 static struct acpuclk_data acpuclk_krait_data = {
@@ -855,20 +861,51 @@
 	.wait_for_irq_khz = STBY_KHZ,
 };
 
-int __init acpuclk_krait_init(struct device *dev,
-			      const struct acpuclk_krait_params *params)
+static void __init drv_data_init(struct device *dev,
+				 const struct acpuclk_krait_params *params)
 {
-	struct scalable *l2;
+	int tbl_idx;
+
+	drv.dev = dev;
+	drv.scalable = kmemdup(params->scalable, params->scalable_size,
+				GFP_KERNEL);
+	BUG_ON(!drv.scalable);
+
+	drv.hfpll_data = kmemdup(params->hfpll_data, sizeof(*drv.hfpll_data),
+				GFP_KERNEL);
+	BUG_ON(!drv.hfpll_data);
+
+	drv.l2_freq_tbl = kmemdup(params->l2_freq_tbl, params->l2_freq_tbl_size,
+				GFP_KERNEL);
+	BUG_ON(!drv.l2_freq_tbl);
+
+	drv.bus_scale = kmemdup(params->bus_scale, sizeof(*drv.bus_scale),
+				GFP_KERNEL);
+	BUG_ON(!drv.bus_scale);
+	drv.bus_scale->usecase = kmemdup(drv.bus_scale->usecase,
+		drv.bus_scale->num_usecases * sizeof(*drv.bus_scale->usecase),
+		GFP_KERNEL);
+	BUG_ON(!drv.bus_scale->usecase);
+
+	tbl_idx = select_freq_plan(params->qfprom_phys_base);
+	drv.acpu_freq_tbl = kmemdup(params->pvs_tables[tbl_idx].table,
+				    params->pvs_tables[tbl_idx].size,
+				    GFP_KERNEL);
+	BUG_ON(!drv.acpu_freq_tbl);
+
+	drv.max_acpu_lvl = find_max_acpu_lvl(drv.acpu_freq_tbl);
+}
+
+static void __init hw_init(void)
+{
+	struct scalable *l2 = &drv.scalable[L2];
 	int cpu, rc;
 
-	drv.scalable = params->scalable;
-	drv.l2_freq_tbl = params->l2_freq_tbl;
-	drv.dev = dev;
+	if (krait_needs_vmin())
+		krait_apply_vmin(drv.acpu_freq_tbl);
 
-	select_freq_plan(params->pvs_acpu_freq_tbl, params->qfprom_phys_base);
-	bus_init(params->bus_scale_data);
+	bus_init();
 
-	l2 = &drv.scalable[L2];
 	l2->hfpll_base = ioremap(l2->hfpll_phys_base, SZ_32);
 	BUG_ON(!l2->hfpll_base);
 
@@ -878,17 +915,23 @@
 	rc = rpm_regulator_init(l2, VREG_HFPLL_B,
 				l2->vreg[VREG_HFPLL_B].max_vdd, false);
 	BUG_ON(rc);
-
-	rc = init_clock_sources(l2, &drv.max_acpu_lvl->l2_level->speed);
+	rc = init_clock_sources(l2,
+			&drv.l2_freq_tbl[drv.max_acpu_lvl->l2_level].speed);
 	BUG_ON(rc);
 
 	for_each_online_cpu(cpu) {
 		rc = per_cpu_init(cpu);
 		BUG_ON(rc);
 	}
+}
+
+int __init acpuclk_krait_init(struct device *dev,
+			      const struct acpuclk_krait_params *params)
+{
+	drv_data_init(dev, params);
+	hw_init();
 
 	cpufreq_table_init();
-
 	acpuclk_register(&acpuclk_krait_data);
 	register_hotcpu_notifier(&acpuclk_cpu_notifier);
 
diff --git a/arch/arm/mach-msm/acpuclock-krait.h b/arch/arm/mach-msm/acpuclock-krait.h
index f121548..f92aaf3 100644
--- a/arch/arm/mach-msm/acpuclock-krait.h
+++ b/arch/arm/mach-msm/acpuclock-krait.h
@@ -15,7 +15,7 @@
 #define __ARCH_ARM_MACH_MSM_ACPUCLOCK_KRAIT_H
 
 #define STBY_KHZ		1
-
+#define L2(x) (x)
 #define BW_MBPS(_bw) \
 	{ \
 		.vectors = (struct msm_bus_vectors[]){ \
@@ -50,6 +50,7 @@
 	PVS_SLOW = 0,
 	PVS_NOMINAL,
 	PVS_FAST,
+	PVS_FASTER,
 	PVS_UNKNOWN,
 	NUM_PVS
 };
@@ -146,7 +147,7 @@
 struct acpu_level {
 	const int use_for_scaling;
 	const struct core_speed speed;
-	const struct l2_level *l2_level;
+	const unsigned int l2_level;
 	int vdd_core;
 };
 
@@ -162,7 +163,7 @@
  * @droop_offset: Droop controller register offset from base address.
  * @droop_val: Value to initialize the @config_offset register to.
  * @low_vdd_l_max: Maximum "L" value supported at HFPLL_VDD_LOW.
- * @vdd: voltage requirements for each VDD level.
+ * @vdd: voltage requirements for each VDD level for the L2 PLL.
  */
 struct hfpll_data {
 	const u32 mode_offset;
@@ -185,7 +186,6 @@
  * @aux_clk_sel_phys: Physical address of auxiliary MUX.
  * @aux_clk_sel: Auxiliary mux input to select at boot.
  * @l2cpmr_iaddr: Indirect address of the CPMR MUX/divider CP15 register.
- * @hfpll_data: Descriptive data of HFPLL hardware.
  * @cur_speed: Pointer to currently-set speed.
  * @l2_vote: L2 performance level vote associate with the current CPU speed.
  * @vreg: Array of voltage regulators needed by the scalable.
@@ -197,29 +197,42 @@
 	const phys_addr_t aux_clk_sel_phys;
 	const u32 aux_clk_sel;
 	const u32 l2cpmr_iaddr;
-	const struct hfpll_data *hfpll_data;
 	const struct core_speed *cur_speed;
-	const struct l2_level *l2_vote;
+	unsigned int l2_vote;
 	struct vreg vreg[NUM_VREG];
 	bool initialized;
 };
 
 /**
+ * struct pvs_table - CPU performance level table and size.
+ * @table: CPU performance level table
+ * @size: sizeof(@table)
+ */
+struct pvs_table {
+	struct acpu_level *table;
+	size_t size;
+};
+
+/**
  * struct acpuclk_krait_params - SoC specific driver parameters.
  * @scalable: Array of scalables.
- * @pvs_acpu_freq_tbl: Array of CPU frequency tables.
+ * @scalable_size: Size of @scalable.
+ * @hfpll_data: HFPLL configuration data.
+ * @pvs_tables: CPU frequency tables.
  * @l2_freq_tbl: L2 frequency table.
- * @l2_freq_tbl_size: Number of rows in @l2_freq_tbl.
+ * @l2_freq_tbl_size: Size of @l2_freq_tbl.
  * @qfprom_phys_base: Physical base address of QFPROM.
- * @bus_scale_data: MSM bus driver parameters.
+ * @bus_scale: MSM bus driver parameters.
  */
 struct acpuclk_krait_params {
 	struct scalable *scalable;
-	struct acpu_level *pvs_acpu_freq_tbl[NUM_PVS];
-	const struct l2_level *l2_freq_tbl;
-	const size_t l2_freq_tbl_size;
-	const phys_addr_t qfprom_phys_base;
-	struct msm_bus_scale_pdata *bus_scale_data;
+	size_t scalable_size;
+	struct hfpll_data *hfpll_data;
+	struct pvs_table *pvs_tables;
+	struct l2_level *l2_freq_tbl;
+	size_t l2_freq_tbl_size;
+	phys_addr_t qfprom_phys_base;
+	struct msm_bus_scale_pdata *bus_scale;
 };
 
 /**
diff --git a/arch/arm/mach-msm/board-8064-regulator.c b/arch/arm/mach-msm/board-8064-regulator.c
index 29416de..a84cb39 100644
--- a/arch/arm/mach-msm/board-8064-regulator.c
+++ b/arch/arm/mach-msm/board-8064-regulator.c
@@ -179,11 +179,11 @@
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
-	REGULATOR_SUPPLY("krait0",		NULL),
+	REGULATOR_SUPPLY("krait0",		"acpuclk-8064"),
 };
 VREG_CONSUMERS(S6) = {
 	REGULATOR_SUPPLY("8921_s6",		NULL),
-	REGULATOR_SUPPLY("krait1",		NULL),
+	REGULATOR_SUPPLY("krait1",		"acpuclk-8064"),
 };
 VREG_CONSUMERS(S7) = {
 	REGULATOR_SUPPLY("8921_s7",		NULL),
@@ -237,11 +237,11 @@
 };
 VREG_CONSUMERS(8821_S0) = {
 	REGULATOR_SUPPLY("8821_s0",		NULL),
-	REGULATOR_SUPPLY("krait2",		NULL),
+	REGULATOR_SUPPLY("krait2",		"acpuclk-8064"),
 };
 VREG_CONSUMERS(8821_S1) = {
 	REGULATOR_SUPPLY("8821_s1",		NULL),
-	REGULATOR_SUPPLY("krait3",		NULL),
+	REGULATOR_SUPPLY("krait3",		"acpuclk-8064"),
 };
 VREG_CONSUMERS(EXT_5V) = {
 	REGULATOR_SUPPLY("ext_5v",		NULL),
@@ -606,10 +606,37 @@
 int msm8064_pm8921_regulator_pdata_len __devinitdata =
 	ARRAY_SIZE(msm8064_pm8921_regulator_pdata);
 
+#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
+	{ \
+		.vreg_id = RPM_VREG_ID_PM8921_##_id, \
+		.sleep_also = _sleep_also, \
+		.voter = _voter, \
+		.supply = _supply, \
+		.dev_name = _dev_name, \
+	}
+static struct rpm_regulator_consumer_mapping
+	      msm_rpm_regulator_consumer_mapping[] __devinitdata = {
+	RPM_REG_MAP(LVS7, 0, 1, "krait0_hfpll", "acpuclk-8064"),
+	RPM_REG_MAP(LVS7, 0, 2, "krait1_hfpll", "acpuclk-8064"),
+	RPM_REG_MAP(LVS7, 0, 4, "krait2_hfpll", "acpuclk-8064"),
+	RPM_REG_MAP(LVS7, 0, 5, "krait3_hfpll", "acpuclk-8064"),
+	RPM_REG_MAP(LVS7, 0, 6, "l2_hfpll",     "acpuclk-8064"),
+	RPM_REG_MAP(L24,  0, 1, "krait0_mem",   "acpuclk-8064"),
+	RPM_REG_MAP(L24,  0, 2, "krait1_mem",   "acpuclk-8064"),
+	RPM_REG_MAP(L24,  0, 4, "krait2_mem",   "acpuclk-8064"),
+	RPM_REG_MAP(L24,  0, 5, "krait3_mem",   "acpuclk-8064"),
+	RPM_REG_MAP(S3,   0, 1, "krait0_dig",   "acpuclk-8064"),
+	RPM_REG_MAP(S3,   0, 2, "krait1_dig",   "acpuclk-8064"),
+	RPM_REG_MAP(S3,   0, 4, "krait2_dig",   "acpuclk-8064"),
+	RPM_REG_MAP(S3,   0, 5, "krait3_dig",   "acpuclk-8064"),
+};
+
 struct rpm_regulator_platform_data apq8064_rpm_regulator_pdata __devinitdata = {
 	.init_data		= apq8064_rpm_regulator_init_data,
 	.num_regulators		= ARRAY_SIZE(apq8064_rpm_regulator_init_data),
 	.version		= RPM_VREG_VERSION_8960,
 	.vreg_id_vdd_mem	= RPM_VREG_ID_PM8921_L24,
 	.vreg_id_vdd_dig	= RPM_VREG_ID_PM8921_S3,
+	.consumer_map		= msm_rpm_regulator_consumer_mapping,
+	.consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
 };
diff --git a/arch/arm/mach-msm/board-8064.c b/arch/arm/mach-msm/board-8064.c
index 1f59909..3e07833 100644
--- a/arch/arm/mach-msm/board-8064.c
+++ b/arch/arm/mach-msm/board-8064.c
@@ -2049,12 +2049,6 @@
 	},
 };
 
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
-	.base_addr = MSM_ACC0_BASE + 0x08,
-	.cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
-	.mask = 1UL << 13,
-};
-
 static void __init apq8064_init_buses(void)
 {
 	msm_bus_rpm_set_mt_mask();
@@ -2160,7 +2154,7 @@
 };
 
 static struct platform_device *common_devices[] __initdata = {
-	&msm8960_device_acpuclk,
+	&apq8064_device_acpuclk,
 	&apq8064_device_dmov,
 	&apq8064_device_qup_spi_gsbi5,
 	&apq8064_device_ext_5v_vreg,
@@ -2965,7 +2959,6 @@
 	msm_spm_init(msm_spm_data, ARRAY_SIZE(msm_spm_data));
 	msm_spm_l2_init(msm_spm_l2_data);
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 	apq8064_epm_adc_init();
 }
 
diff --git a/arch/arm/mach-msm/board-8930-display.c b/arch/arm/mach-msm/board-8930-display.c
index 739dc85..292c031 100644
--- a/arch/arm/mach-msm/board-8930-display.c
+++ b/arch/arm/mach-msm/board-8930-display.c
@@ -131,6 +131,7 @@
  * appropriate function.
  */
 #define DISP_RST_GPIO 58
+#define DISP_3D_2D_MODE 1
 static int mipi_dsi_cdp_panel_power(int on)
 {
 	static struct regulator *reg_l8, *reg_l23, *reg_l2;
@@ -183,6 +184,19 @@
 			gpio_free(DISP_RST_GPIO);
 			return -ENODEV;
 		}
+		rc = gpio_request(DISP_3D_2D_MODE, "disp_3d_2d");
+		if (rc) {
+			pr_err("request gpio DISP_3D_2D_MODE failed, rc=%d\n",
+				 rc);
+			gpio_free(DISP_3D_2D_MODE);
+			return -ENODEV;
+			}
+		rc = gpio_direction_output(DISP_3D_2D_MODE, 0);
+		if (rc) {
+			pr_err("gpio_direction_output failed for %d gpio rc=%d\n",
+			DISP_3D_2D_MODE, rc);
+			return -ENODEV;
+			}
 		dsi_power_on = true;
 	}
 	if (on) {
@@ -222,6 +236,8 @@
 		gpio_set_value(DISP_RST_GPIO, 0);
 		usleep(20);
 		gpio_set_value(DISP_RST_GPIO, 1);
+		gpio_set_value(DISP_3D_2D_MODE, 1);
+		usleep(20);
 	} else {
 
 		gpio_set_value(DISP_RST_GPIO, 0);
@@ -256,6 +272,8 @@
 			pr_err("set_optimum_mode l2 failed, rc=%d\n", rc);
 			return -EINVAL;
 		}
+		gpio_set_value(DISP_3D_2D_MODE, 0);
+		usleep(20);
 	}
 	return 0;
 }
diff --git a/arch/arm/mach-msm/board-8930-gpu.c b/arch/arm/mach-msm/board-8930-gpu.c
index 105a5aa..bd343c1 100644
--- a/arch/arm/mach-msm/board-8930-gpu.c
+++ b/arch/arm/mach-msm/board-8930-gpu.c
@@ -162,8 +162,8 @@
 {
 	unsigned int version = socinfo_get_version();
 
-	if (cpu_is_msm8627())
-		kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 400000000;
+	if (cpu_is_msm8930aa())
+		kgsl_3d0_pdata.pwrlevel[0].gpu_freq = 450000000;
 
 	if ((SOCINFO_VERSION_MAJOR(version) == 1) &&
 		(SOCINFO_VERSION_MINOR(version) == 2))
diff --git a/arch/arm/mach-msm/board-8930.c b/arch/arm/mach-msm/board-8930.c
index 88c0924..d7a077c 100644
--- a/arch/arm/mach-msm/board-8930.c
+++ b/arch/arm/mach-msm/board-8930.c
@@ -2401,12 +2401,6 @@
 	.mode = MSM_PM_BOOT_CONFIG_TZ,
 };
 
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
-	.base_addr = MSM_ACC0_BASE + 0x08,
-	.cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
-	.mask = 1UL << 13,
-};
-
 #ifdef CONFIG_I2C
 #define I2C_SURF 1
 #define I2C_FFA  (1 << 1)
@@ -2603,7 +2597,6 @@
 		ARRAY_SIZE(msm_slim_devices));
 	change_memory_power = &msm8930_change_memory_power;
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 
 	if (PLATFORM_IS_CHARM25())
 		platform_add_devices(mdm_devices, ARRAY_SIZE(mdm_devices));
diff --git a/arch/arm/mach-msm/board-8960-gpiomux.c b/arch/arm/mach-msm/board-8960-gpiomux.c
index 53e7c9e..5851990 100644
--- a/arch/arm/mach-msm/board-8960-gpiomux.c
+++ b/arch/arm/mach-msm/board-8960-gpiomux.c
@@ -76,6 +76,18 @@
 	.pull = GPIOMUX_PULL_NONE,
 };
 
+static struct gpiomux_setting gsbi8_uartdm_active_cfg = {
+	.func = GPIOMUX_FUNC_1,
+	.drv = GPIOMUX_DRV_8MA,
+	.pull = GPIOMUX_PULL_NONE,
+};
+
+static struct gpiomux_setting gsbi8_uartdm_suspended_cfg = {
+	.func = GPIOMUX_FUNC_GPIO,
+	.drv = GPIOMUX_DRV_2MA,
+	.pull = GPIOMUX_PULL_DOWN,
+};
+
 static struct gpiomux_setting gsbi9_active_cfg = {
 	.func = GPIOMUX_FUNC_2,
 	.drv = GPIOMUX_DRV_8MA,
@@ -310,6 +322,37 @@
 	},
 };
 #endif
+/* GSBI8 UART GPIOs for Atheros Bluetooth */
+static struct msm_gpiomux_config msm8960_gsbi8_uartdm_configs[] = {
+	{
+		.gpio = 34,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+		}
+	},
+	{
+		.gpio = 35,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+		}
+	},
+	{
+		.gpio = 36,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+		}
+	},
+	{
+		.gpio = 37,
+		.settings = {
+			[GPIOMUX_SUSPENDED] = &gsbi8_uartdm_suspended_cfg,
+			[GPIOMUX_ACTIVE] = &gsbi8_uartdm_active_cfg,
+		}
+	},
+};
 
 static struct msm_gpiomux_config msm8960_fusion_gsbi_configs[] = {
 	{
@@ -988,6 +1031,10 @@
 	msm_gpiomux_install(msm8960_mdp_vsync_configs,
 			ARRAY_SIZE(msm8960_mdp_vsync_configs));
 
+	if (socinfo_get_platform_subtype() != PLATFORM_SUBTYPE_SGLTE)
+		msm_gpiomux_install(msm8960_gsbi8_uartdm_configs,
+			ARRAY_SIZE(msm8960_gsbi8_uartdm_configs));
+
 	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE)
 		msm_gpiomux_install(msm8960_gsbi8_uart_configs,
 			ARRAY_SIZE(msm8960_gsbi8_uart_configs));
diff --git a/arch/arm/mach-msm/board-8960-regulator.c b/arch/arm/mach-msm/board-8960-regulator.c
index 650ac28..6ad44d8 100644
--- a/arch/arm/mach-msm/board-8960-regulator.c
+++ b/arch/arm/mach-msm/board-8960-regulator.c
@@ -181,11 +181,11 @@
 };
 VREG_CONSUMERS(S5) = {
 	REGULATOR_SUPPLY("8921_s5",		NULL),
-	REGULATOR_SUPPLY("krait0",		NULL),
+	REGULATOR_SUPPLY("krait0",		"acpuclk-8960"),
 };
 VREG_CONSUMERS(S6) = {
 	REGULATOR_SUPPLY("8921_s6",		NULL),
-	REGULATOR_SUPPLY("krait1",		NULL),
+	REGULATOR_SUPPLY("krait1",		"acpuclk-8960"),
 };
 VREG_CONSUMERS(S7) = {
 	REGULATOR_SUPPLY("8921_s7",		NULL),
@@ -561,10 +561,34 @@
 int msm_pm8921_regulator_pdata_len __devinitdata =
 	ARRAY_SIZE(msm_pm8921_regulator_pdata);
 
+#define RPM_REG_MAP(_id, _sleep_also, _voter, _supply, _dev_name) \
+	{ \
+		.vreg_id = RPM_VREG_ID_PM8921_##_id, \
+		.sleep_also = _sleep_also, \
+		.voter = _voter, \
+		.supply = _supply, \
+		.dev_name = _dev_name, \
+	}
+static struct rpm_regulator_consumer_mapping
+	      msm_rpm_regulator_consumer_mapping[] __devinitdata = {
+	RPM_REG_MAP(L23, 0, 1, "krait0_l23", "acpuclk-8960"),
+	RPM_REG_MAP(L23, 0, 2, "krait1_l23", "acpuclk-8960"),
+	RPM_REG_MAP(L23, 0, 6, "l2_l23",     "acpuclk-8960"),
+	RPM_REG_MAP(L24, 0, 1, "krait0_mem", "acpuclk-8960"),
+	RPM_REG_MAP(L24, 0, 2, "krait1_mem", "acpuclk-8960"),
+	RPM_REG_MAP(S3,  0, 1, "krait0_dig", "acpuclk-8960"),
+	RPM_REG_MAP(S3,  0, 2, "krait1_dig", "acpuclk-8960"),
+	RPM_REG_MAP(S8,  0, 1, "krait0_s8",  "acpuclk-8960"),
+	RPM_REG_MAP(S8,  0, 2, "krait1_s8",  "acpuclk-8960"),
+	RPM_REG_MAP(S8,  0, 6, "l2_s8",      "acpuclk-8960"),
+};
+
 struct rpm_regulator_platform_data msm_rpm_regulator_pdata __devinitdata = {
 	.init_data		= msm_rpm_regulator_init_data,
 	.num_regulators		= ARRAY_SIZE(msm_rpm_regulator_init_data),
 	.version		= RPM_VREG_VERSION_8960,
 	.vreg_id_vdd_mem	= RPM_VREG_ID_PM8921_L24,
 	.vreg_id_vdd_dig	= RPM_VREG_ID_PM8921_S3,
+	.consumer_map		= msm_rpm_regulator_consumer_mapping,
+	.consumer_map_len = ARRAY_SIZE(msm_rpm_regulator_consumer_mapping),
 };
diff --git a/arch/arm/mach-msm/board-8960.c b/arch/arm/mach-msm/board-8960.c
index 0fcaf78..d56bdbd 100644
--- a/arch/arm/mach-msm/board-8960.c
+++ b/arch/arm/mach-msm/board-8960.c
@@ -2321,12 +2321,6 @@
 	.src_clk_rate = 24000000,
 };
 
-static struct msm_pm_sleep_status_data msm_pm_slp_sts_data = {
-	.base_addr = MSM_ACC0_BASE + 0x08,
-	.cpu_offset = MSM_ACC1_BASE - MSM_ACC0_BASE,
-	.mask = 1UL << 13,
-};
-
 static struct ks8851_pdata spi_eth_pdata = {
 	.irq_gpio = KS8851_IRQ_GPIO,
 	.rst_gpio = KS8851_RST_GPIO,
@@ -2462,7 +2456,36 @@
 static struct msm_serial_hs_platform_data msm_uart_dm9_pdata = {
 	.gpio_config	= configure_uart_gpios,
 };
+
+static int configure_gsbi8_uart_gpios(int on)
+{
+	int ret = 0, i;
+	int uart_gpios[] = {34, 35, 36, 37};
+
+	for (i = 0; i < ARRAY_SIZE(uart_gpios); i++) {
+		if (on) {
+			ret = gpio_request(uart_gpios[i], NULL);
+			if (ret) {
+				pr_err("%s: unable to request uart gpio[%d]\n",
+						__func__, uart_gpios[i]);
+				break;
+			}
+		} else {
+			gpio_free(uart_gpios[i]);
+		}
+	}
+
+	if (ret && on && i)
+		for (; i >= 0; i--)
+			gpio_free(uart_gpios[i]);
+	return ret;
+}
+
+static struct msm_serial_hs_platform_data msm_uart_dm8_pdata = {
+	.gpio_config	= configure_gsbi8_uart_gpios,
+};
 #else
+static struct msm_serial_hs_platform_data msm_uart_dm8_pdata;
 static struct msm_serial_hs_platform_data msm_uart_dm9_pdata;
 #endif
 
@@ -3047,7 +3070,6 @@
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 }
 
 static void __init msm8960_rumi3_init(void)
@@ -3077,7 +3099,6 @@
 	slim_register_board_info(msm_slim_devices,
 		ARRAY_SIZE(msm_slim_devices));
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 }
 
 static void __init msm8960_cdp_init(void)
@@ -3143,6 +3164,11 @@
 		platform_device_register(&msm_device_uart_dm9);
 	}
 
+	/* For 8960 Standalone External Bluetooth Interface */
+	if (socinfo_get_platform_subtype() != PLATFORM_SUBTYPE_SGLTE) {
+		msm_device_uart_dm8.dev.platform_data = &msm_uart_dm8_pdata;
+		platform_device_register(&msm_device_uart_dm8);
+	}
 	platform_add_devices(common_devices, ARRAY_SIZE(common_devices));
 	msm8960_pm8921_gpio_mpp_init();
 	platform_add_devices(cdp_devices, ARRAY_SIZE(cdp_devices));
@@ -3161,7 +3187,6 @@
 	msm8960_init_dsps();
 	change_memory_power = &msm8960_change_memory_power;
 	BUG_ON(msm_pm_boot_init(&msm_pm_boot_pdata));
-	msm_pm_init_sleep_status_data(&msm_pm_slp_sts_data);
 	if (socinfo_get_platform_subtype() == PLATFORM_SUBTYPE_SGLTE) {
 		mdm_sglte_device.dev.platform_data = &sglte_platform_data;
 		platform_device_register(&mdm_sglte_device);
diff --git a/arch/arm/mach-msm/board-8974.c b/arch/arm/mach-msm/board-8974.c
index 7562c83..6b46a2f 100644
--- a/arch/arm/mach-msm/board-8974.c
+++ b/arch/arm/mach-msm/board-8974.c
@@ -383,6 +383,7 @@
 static void __init msm_8974_early_memory(void)
 {
 	reserve_info = &msm_8974_reserve_info;
+	of_scan_flat_dt(dt_scan_for_memory_reserve, msm_8974_reserve_table);
 }
 
 void __init msm_8974_reserve(void)
diff --git a/arch/arm/mach-msm/board-msm7x27a.c b/arch/arm/mach-msm/board-msm7x27a.c
index 7db4bda..ba4e098 100644
--- a/arch/arm/mach-msm/board-msm7x27a.c
+++ b/arch/arm/mach-msm/board-msm7x27a.c
@@ -48,7 +48,6 @@
 #include <mach/msm_battery.h>
 #include <linux/smsc911x.h>
 #include <linux/atmel_maxtouch.h>
-#include <linux/fmem.h>
 #include <linux/msm_adc.h>
 #include <linux/ion.h>
 #include "devices.h"
@@ -448,9 +447,6 @@
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
 	.cached = 1,
 	.memory_type = MEMTYPE_EBI1,
-	.request_region = request_fmem_c_region,
-	.release_region = release_fmem_c_region,
-	.reusable = 1,
 };
 
 static struct platform_device android_pmem_adsp_device = {
@@ -778,14 +774,6 @@
 static void msm7x27a_cfg_uart2dm_serial(void) { }
 #endif
 
-static struct fmem_platform_data fmem_pdata;
-
-static struct platform_device fmem_device = {
-	.name = "fmem",
-	.id = 1,
-	.dev = { .platform_data = &fmem_pdata },
-};
-
 static struct platform_device *rumi_sim_devices[] __initdata = {
 	&msm_device_dmov,
 	&msm_device_smd,
@@ -823,7 +811,6 @@
 	&android_pmem_device,
 	&android_pmem_adsp_device,
 	&android_pmem_audio_device,
-	&fmem_device,
 	&msm_device_nand,
 	&msm_device_snd,
 	&msm_device_adspdec,
@@ -966,32 +953,10 @@
 {
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	unsigned int i;
-	unsigned int reusable_count = 0;
-
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_mdp_size;
 	android_pmem_audio_pdata.size = pmem_audio_size;
 
-	fmem_pdata.size = 0;
-	fmem_pdata.align = PAGE_SIZE;
-
-	/* Find pmem devices that should use FMEM (reusable) memory.
-	 */
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
-		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
-		if (!reusable_count && pdata->reusable)
-			fmem_pdata.size += pdata->size;
-
-		reusable_count += (pdata->reusable) ? 1 : 0;
-
-		if (pdata->reusable && reusable_count > 1) {
-			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
-				__func__, pdata->name);
-			pdata->reusable = 0;
-		}
-	}
 #endif
 #endif
 }
diff --git a/arch/arm/mach-msm/board-qrd7627a.c b/arch/arm/mach-msm/board-qrd7627a.c
index bd73b70..a694557 100644
--- a/arch/arm/mach-msm/board-qrd7627a.c
+++ b/arch/arm/mach-msm/board-qrd7627a.c
@@ -31,7 +31,6 @@
 #include <linux/memblock.h>
 #include <linux/input/ft5x06_ts.h>
 #include <linux/msm_adc.h>
-#include <linux/fmem.h>
 #include <linux/regulator/msm-gpio-regulator.h>
 #include <linux/ion.h>
 #include <asm/mach/mmc.h>
@@ -394,9 +393,6 @@
 	.allocator_type = PMEM_ALLOCATORTYPE_BITMAP,
 	.cached = 1,
 	.memory_type = MEMTYPE_EBI1,
-	.request_region = request_fmem_c_region,
-	.release_region = release_fmem_c_region,
-	.reusable = 1,
 };
 
 static struct platform_device android_pmem_adsp_device = {
@@ -639,14 +635,6 @@
 	},
 };
 
-static struct fmem_platform_data fmem_pdata;
-
-static struct platform_device fmem_device = {
-	.name = "fmem",
-	.id = 1,
-	.dev = { .platform_data = &fmem_pdata },
-};
-
 #define GPIO_VREG_INIT(_id, _reg_name, _gpio_label, _gpio, _active_low) \
 	[GPIO_VREG_ID_##_id] = { \
 		.init_data = { \
@@ -717,7 +705,6 @@
 	&asoc_msm_dai0,
 	&asoc_msm_dai1,
 	&msm_adc_device,
-	&fmem_device,
 #ifdef CONFIG_ION_MSM
 	&ion_dev,
 #endif
@@ -858,32 +845,9 @@
 {
 #ifdef CONFIG_ANDROID_PMEM
 #ifndef CONFIG_MSM_MULTIMEDIA_USE_ION
-	unsigned int i;
-	unsigned int reusable_count = 0;
-
 	android_pmem_adsp_pdata.size = pmem_adsp_size;
 	android_pmem_pdata.size = pmem_mdp_size;
 	android_pmem_audio_pdata.size = pmem_audio_size;
-
-	fmem_pdata.size = 0;
-	fmem_pdata.align = PAGE_SIZE;
-
-	/* Find pmem devices that should use FMEM (reusable) memory.
-	 */
-	for (i = 0; i < ARRAY_SIZE(pmem_pdata_array); ++i) {
-		struct android_pmem_platform_data *pdata = pmem_pdata_array[i];
-
-		if (!reusable_count && pdata->reusable)
-			fmem_pdata.size += pdata->size;
-
-		reusable_count += (pdata->reusable) ? 1 : 0;
-
-		if (pdata->reusable && reusable_count > 1) {
-			pr_err("%s: Too many PMEM devices specified as reusable. PMEM device %s was not configured as reusable.\n",
-				__func__, pdata->name);
-			pdata->reusable = 0;
-		}
-	}
 #endif
 #endif
 }
diff --git a/arch/arm/mach-msm/cache_erp.c b/arch/arm/mach-msm/cache_erp.c
index c3302ec..8a73c84 100644
--- a/arch/arm/mach-msm/cache_erp.c
+++ b/arch/arm/mach-msm/cache_erp.c
@@ -253,22 +253,11 @@
 	int print_regs = cesr & CESR_PRINT_MASK;
 	int log_event = cesr & CESR_LOG_EVENT_MASK;
 
-	void *const saw_bases[] = {
-		MSM_SAW0_BASE,
-		MSM_SAW1_BASE,
-		MSM_SAW2_BASE,
-		MSM_SAW3_BASE,
-	};
-
 	if (print_regs) {
 		pr_alert("L1 / TLB Error detected on CPU %d!\n", cpu);
 		pr_alert("\tCESR      = 0x%08x\n", cesr);
 		pr_alert("\tCPU speed = %lu\n", acpuclk_get_rate(cpu));
 		pr_alert("\tMIDR      = 0x%08x\n", read_cpuid_id());
-		pr_alert("\tPTE fuses = 0x%08x\n",
-					readl_relaxed(MSM_QFPROM_BASE + 0xC0));
-		pr_alert("\tPMIC_VREG = 0x%08x\n",
-					readl_relaxed(saw_bases[cpu] + 0x14));
 	}
 
 	if (cesr & CESR_DCTPE) {
@@ -550,12 +539,18 @@
 	return 0;
 }
 
+static struct of_device_id cache_erp_match_table[] = {
+	{	.compatible = "qcom,cache_erp",	},
+	{}
+};
+
 static struct platform_driver msm_cache_erp_driver = {
 	.probe = msm_cache_erp_probe,
 	.remove = msm_cache_erp_remove,
 	.driver = {
 		.name = MODULE_NAME,
 		.owner = THIS_MODULE,
+		.of_match_table = cache_erp_match_table,
 	},
 };
 
diff --git a/arch/arm/mach-msm/clock-8960.c b/arch/arm/mach-msm/clock-8960.c
index e87dd14..56b774d 100644
--- a/arch/arm/mach-msm/clock-8960.c
+++ b/arch/arm/mach-msm/clock-8960.c
@@ -5508,7 +5508,10 @@
 	CLK_LOOKUP("core_clk",		gsbi5_uart_clk.c, "msm_serial_hsl.0"),
 	CLK_LOOKUP("core_clk",		gsbi6_uart_clk.c, "msm_serial_hs.0"),
 	CLK_LOOKUP("core_clk",		gsbi7_uart_clk.c,	""),
+	/* used on 8960 SGLTE for console */
 	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c, "msm_serial_hsl.1"),
+	/* used on 8960 standalone with Atheros Bluetooth */
+	CLK_LOOKUP("core_clk",		gsbi8_uart_clk.c, "msm_serial_hs.2"),
 	CLK_LOOKUP("core_clk",		gsbi9_uart_clk.c, "msm_serial_hs.1"),
 	CLK_LOOKUP("core_clk",		gsbi10_uart_clk.c,	""),
 	CLK_LOOKUP("core_clk",		gsbi11_uart_clk.c,	""),
@@ -5560,7 +5563,10 @@
 	CLK_LOOKUP("iface_clk",		gsbi5_p_clk.c,	"msm_serial_hsl.0"),
 	CLK_LOOKUP("iface_clk",		gsbi6_p_clk.c,  "msm_serial_hs.0"),
 	CLK_LOOKUP("iface_clk",		gsbi7_p_clk.c,		""),
+	/* used on 8960 SGLTE for serial console */
 	CLK_LOOKUP("iface_clk",		gsbi8_p_clk.c,	"msm_serial_hsl.1"),
+	/* used on 8960 standalone with Atheros Bluetooth */
+	CLK_LOOKUP("iface_clk",		gsbi8_p_clk.c,	"msm_serial_hs.2"),
 	CLK_LOOKUP("iface_clk",		gsbi9_p_clk.c,  "msm_serial_hs.1"),
 	CLK_LOOKUP("iface_clk",		gsbi10_p_clk.c,		"qup_i2c.10"),
 	CLK_LOOKUP("iface_clk",		gsbi11_p_clk.c,		""),
diff --git a/arch/arm/mach-msm/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 48f16b0..6b58257 100644
--- a/arch/arm/mach-msm/clock-8974.c
+++ b/arch/arm/mach-msm/clock-8974.c
@@ -2115,6 +2115,7 @@
 
 static struct branch_clk gcc_usb30_master_clk = {
 	.cbcr_reg = USB30_MASTER_CBCR,
+	.bcr_reg = USB_30_BCR,
 	.parent = &usb30_master_clk_src.c,
 	.has_sibling = 1,
 	.base = &virt_bases[GCC_BASE],
@@ -2149,6 +2150,7 @@
 
 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,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
@@ -2171,6 +2173,7 @@
 
 static struct branch_clk gcc_usb_hsic_clk = {
 	.cbcr_reg = USB_HSIC_CBCR,
+	.bcr_reg = USB_HS_HSIC_BCR,
 	.parent = &usb_hsic_clk_src.c,
 	.base = &virt_bases[GCC_BASE],
 	.c = {
@@ -3987,9 +3990,9 @@
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
-		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+		.dbg_name = "audio_core_lpaif_codec_spkr_osr_clk",
 		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+		CLK_INIT(audio_core_lpaif_codec_spkr_osr_clk.c),
 	},
 };
 
@@ -3998,9 +4001,9 @@
 	.has_sibling = 1,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
-		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+		.dbg_name = "audio_core_lpaif_codec_spkr_ebit_clk",
 		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+		CLK_INIT(audio_core_lpaif_codec_spkr_ebit_clk.c),
 	},
 };
 
@@ -4011,9 +4014,9 @@
 	.max_div = 15,
 	.base = &virt_bases[LPASS_BASE],
 	.c = {
-		.dbg_name = "audio_core_lpaif_codec_spkr_clk_src",
+		.dbg_name = "audio_core_lpaif_codec_spkr_ibit_clk",
 		.ops = &clk_ops_branch,
-		CLK_INIT(audio_core_lpaif_codec_spkr_clk_src.c),
+		CLK_INIT(audio_core_lpaif_codec_spkr_ibit_clk.c),
 	},
 };
 
diff --git a/arch/arm/mach-msm/devices-8064.c b/arch/arm/mach-msm/devices-8064.c
index 8a41a7c..aa67690 100644
--- a/arch/arm/mach-msm/devices-8064.c
+++ b/arch/arm/mach-msm/devices-8064.c
@@ -852,6 +852,11 @@
 	},
 };
 
+struct platform_device apq8064_device_acpuclk = {
+	.name		= "acpuclk-8064",
+	.id		= -1,
+};
+
 #define SHARED_IMEM_TZ_BASE 0x2a03f720
 static struct resource tzlog_resources[] = {
 	{
diff --git a/arch/arm/mach-msm/devices-8960.c b/arch/arm/mach-msm/devices-8960.c
index d74d4aa..9a0c2d7 100644
--- a/arch/arm/mach-msm/devices-8960.c
+++ b/arch/arm/mach-msm/devices-8960.c
@@ -292,6 +292,52 @@
 		.coherent_dma_mask	= DMA_BIT_MASK(32),
 	},
 };
+
+/* GSBI 8 used into UARTDM Mode */
+static struct resource msm_uart_dm8_resources[] = {
+	{
+		.start	= MSM_UART8DM_PHYS,
+		.end	= MSM_UART8DM_PHYS + PAGE_SIZE - 1,
+		.name	= "uartdm_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= GSBI8_UARTDM_IRQ,
+		.end	= GSBI8_UARTDM_IRQ,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{
+		.start	= MSM_GSBI8_PHYS,
+		.end	= MSM_GSBI8_PHYS + 4 - 1,
+		.name	= "gsbi_resource",
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= DMOV_HSUART_GSBI8_TX_CHAN,
+		.end	= DMOV_HSUART_GSBI8_RX_CHAN,
+		.name	= "uartdm_channels",
+		.flags	= IORESOURCE_DMA,
+	},
+	{
+		.start	= DMOV_HSUART_GSBI8_TX_CRCI,
+		.end	= DMOV_HSUART_GSBI8_RX_CRCI,
+		.name	= "uartdm_crci",
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static u64 msm_uart_dm8_dma_mask = DMA_BIT_MASK(32);
+struct platform_device msm_device_uart_dm8 = {
+	.name	= "msm_serial_hs",
+	.id	= 2,
+	.num_resources	= ARRAY_SIZE(msm_uart_dm8_resources),
+	.resource	= msm_uart_dm8_resources,
+	.dev	= {
+		.dma_mask		= &msm_uart_dm8_dma_mask,
+		.coherent_dma_mask	= DMA_BIT_MASK(32),
+	},
+};
+
 /*
  * GSBI 9 used into UARTDM Mode
  * For 8960 Fusion 2.2 Primary IPC
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 2207e3c..daf70a8 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -53,6 +53,7 @@
 extern struct platform_device msm_device_uart_dm12;
 extern struct platform_device *msm_device_uart_gsbi9;
 extern struct platform_device msm_device_uart_dm6;
+extern struct platform_device msm_device_uart_dm8;
 extern struct platform_device msm_device_uart_dm9;
 
 extern struct platform_device msm8960_device_uart_gsbi2;
@@ -419,6 +420,7 @@
 extern struct platform_device msm7x27a_device_acpuclk;
 extern struct platform_device msm7x27aa_device_acpuclk;
 extern struct platform_device msm7x30_device_acpuclk;
+extern struct platform_device apq8064_device_acpuclk;
 extern struct platform_device msm8625_device_acpuclk;
 extern struct platform_device msm8627_device_acpuclk;
 extern struct platform_device msm8x50_device_acpuclk;
diff --git a/arch/arm/mach-msm/include/mach/dma.h b/arch/arm/mach-msm/include/mach/dma.h
index 381ea12..6a389de 100644
--- a/arch/arm/mach-msm/include/mach/dma.h
+++ b/arch/arm/mach-msm/include/mach/dma.h
@@ -188,6 +188,12 @@
 #define DMOV_HSUART_GSBI6_RX_CHAN	8
 #define DMOV_HSUART_GSBI6_RX_CRCI	11
 
+#define DMOV_HSUART_GSBI8_TX_CHAN	7
+#define DMOV_HSUART_GSBI8_TX_CRCI	10
+
+#define DMOV_HSUART_GSBI8_RX_CHAN	8
+#define DMOV_HSUART_GSBI8_RX_CRCI	9
+
 #define DMOV_HSUART_GSBI9_TX_CHAN	4
 #define DMOV_HSUART_GSBI9_TX_CRCI	13
 
diff --git a/arch/arm/mach-msm/include/mach/memory.h b/arch/arm/mach-msm/include/mach/memory.h
index 2596364..bf92f7d 100644
--- a/arch/arm/mach-msm/include/mach/memory.h
+++ b/arch/arm/mach-msm/include/mach/memory.h
@@ -118,6 +118,23 @@
 	(virt) - MEMBANK0_PAGE_OFFSET + MEMBANK0_PHYS_OFFSET)
 #endif
 
+/*
+ * Need a temporary unique variable that no one will ever see to
+ * hold the compat string. Line number gives this easily.
+ * Need another layer of indirection to get __LINE__ to expand
+ * properly as opposed to appending and ending up with
+ * __compat___LINE__
+ */
+#define __CONCAT(a, b)	___CONCAT(a, b)
+#define ___CONCAT(a, b)	a ## b
+
+#define EXPORT_COMPAT(com)	\
+static char *__CONCAT(__compat_, __LINE__)  __used \
+	__attribute((__section__(".exportcompat.init"))) = com
+
+extern char *__compat_exports_start[];
+extern char *__compat_exports_end[];
+
 #endif
 
 #if defined CONFIG_ARCH_MSM_SCORPION || defined CONFIG_ARCH_MSM_KRAIT
@@ -135,4 +152,5 @@
 
 #ifndef CONFIG_ARCH_MSM7X27
 #define CONSISTENT_DMA_SIZE	(SZ_1M * 14)
+
 #endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memory_dump.h b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
new file mode 100644
index 0000000..3b8c9fd
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/msm_memory_dump.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __MSM_MEMORY_DUMP_H
+#define __MSM_MEMORY_DUMP_H
+
+#include <linux/types.h>
+
+enum dump_client_type {
+	MSM_CPU_CTXT = 0,
+	MSM_CACHE,
+	MSM_OCMEM,
+	MSM_ETB,
+	MSM_ETM,
+	MSM_TMC,
+	MAX_NUM_CLIENTS,
+};
+
+struct msm_client_dump {
+	enum dump_client_type id;
+	unsigned long start_addr;
+	unsigned long end_addr;
+};
+
+struct msm_dump_table {
+	u32 version;
+	u32 num_entries;
+	struct msm_client_dump client_entries[MAX_NUM_CLIENTS];
+};
+
+struct msm_memory_dump {
+	unsigned long dump_table_phys;
+	struct msm_dump_table *dump_table_ptr;
+};
+
+#define TABLE_MAJOR(val)	(val >> 20)
+#define TABLE_MINOR(val)	(val & 0xFFFFF)
+#define MK_TABLE(ma, mi)	((ma << 20) | mi)
+
+#ifndef CONFIG_MSM_MEMORY_DUMP
+static inline int msm_dump_table_register(struct msm_client_dump *entry)
+{
+	return -EIO;
+}
+#else
+int msm_dump_table_register(struct msm_client_dump *client_entry);
+#endif
+#endif
diff --git a/arch/arm/mach-msm/include/mach/msm_memtypes.h b/arch/arm/mach-msm/include/mach/msm_memtypes.h
index 7afb38d..5ca5861 100644
--- a/arch/arm/mach-msm/include/mach/msm_memtypes.h
+++ b/arch/arm/mach-msm/include/mach/msm_memtypes.h
@@ -66,5 +66,8 @@
 
 extern struct reserve_info *reserve_info;
 
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+					int depth, void *data);
+
 unsigned long __init reserve_memory_for_fmem(unsigned long, unsigned long);
 #endif
diff --git a/arch/arm/mach-msm/include/mach/ocmem.h b/arch/arm/mach-msm/include/mach/ocmem.h
index 927624d..415f8ed 100644
--- a/arch/arm/mach-msm/include/mach/ocmem.h
+++ b/arch/arm/mach-msm/include/mach/ocmem.h
@@ -22,7 +22,7 @@
 
 /* Maximum number of slots in DM */
 #define OCMEM_MAX_CHUNKS 32
-#define MIN_CHUNK_SIZE (SZ_1K/8)
+#define MIN_CHUNK_SIZE 128
 
 struct ocmem_notifier;
 
@@ -61,7 +61,7 @@
 	/* IMEM Clients */
 	OCMEM_LP_AUDIO,
 	OCMEM_SENSORS,
-	OCMEM_BLAST,
+	OCMEM_OTHER_OS,
 	OCMEM_CLIENT_MAX,
 };
 
@@ -108,8 +108,13 @@
 int ocmem_shrink(int client_id, struct ocmem_buf *buf,
 			unsigned long new_size);
 
-int ocmem_expand(int client_id, struct ocmem_buf *buf,
-			unsigned long new_size);
+/* Transfer APIs */
+int ocmem_map(int client_id, struct ocmem_buf *buffer,
+			struct ocmem_map_list *list);
+
+
+int ocmem_unmap(int client_id, struct ocmem_buf *buffer,
+			struct ocmem_map_list *list);
 
 /* Priority Enforcement APIs */
 int ocmem_evict(int client_id);
diff --git a/arch/arm/mach-msm/include/mach/ocmem_priv.h b/arch/arm/mach-msm/include/mach/ocmem_priv.h
index 64c9ffe..70b5a45 100644
--- a/arch/arm/mach-msm/include/mach/ocmem_priv.h
+++ b/arch/arm/mach-msm/include/mach/ocmem_priv.h
@@ -20,12 +20,13 @@
 #include "ocmem.h"
 #include <mach/msm_iomap.h>
 #include <asm/io.h>
+#include <linux/platform_device.h>
 
 #define OCMEM_PHYS_BASE 0xFEC00000
 #define OCMEM_PHYS_SIZE 0x180000
 
-#define TO_OCMEM 0x1
-#define TO_DDR 0x2
+#define TO_OCMEM 0x0
+#define TO_DDR 0x1
 
 struct ocmem_zone;
 
@@ -38,7 +39,7 @@
 	int owner;
 	int active_regions;
 	int max_regions;
-	struct list_head region_list;
+	struct list_head req_list;
 	unsigned long z_start;
 	unsigned long z_end;
 	unsigned long z_head;
@@ -78,12 +79,24 @@
 	bool interleaved;
 };
 
+struct ocmem_eviction_data {
+	struct completion completion;
+	struct list_head victim_list;
+	struct list_head req_list;
+	struct work_struct work;
+	int prio;
+	int pending;
+	bool passive;
+};
+
 struct ocmem_req {
 	struct rw_semaphore rw_sem;
 	/* Chain in sched queue */
 	struct list_head sched_list;
 	/* Chain in zone list */
 	struct list_head zone_list;
+	/* Chain in eviction list */
+	struct list_head eviction_list;
 	int owner;
 	int prio;
 	uint32_t req_id;
@@ -100,6 +113,7 @@
 	unsigned long req_start;
 	unsigned long req_end;
 	unsigned long req_sz;
+	struct ocmem_eviction_data *edata;
 };
 
 struct ocmem_handle {
@@ -150,13 +164,20 @@
 
 int ocmem_notifier_init(void);
 int check_notifier(int);
+const char *get_name(int);
+int check_id(int);
 int dispatch_notification(int, enum ocmem_notif_type, struct ocmem_buf *);
 
 int ocmem_sched_init(void);
+int ocmem_rdm_init(struct platform_device *);
 int process_allocate(int, struct ocmem_handle *, unsigned long, unsigned long,
 			unsigned long, bool, bool);
 int process_free(int, struct ocmem_handle *);
-int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *,
-			int direction);
+int process_xfer(int, struct ocmem_handle *, struct ocmem_map_list *, int);
+int process_evict(int);
+int process_restore(int);
+int process_shrink(int, struct ocmem_handle *, unsigned long);
+int ocmem_rdm_transfer(int, struct ocmem_map_list *,
+				unsigned long, int);
 unsigned long process_quota(int);
 #endif
diff --git a/arch/arm/mach-msm/lpm_levels.c b/arch/arm/mach-msm/lpm_levels.c
index e65f71c..ea368ae 100644
--- a/arch/arm/mach-msm/lpm_levels.c
+++ b/arch/arm/mach-msm/lpm_levels.c
@@ -49,8 +49,8 @@
 static void msm_lpm_exit_sleep(void *limits, bool from_idle,
 		bool notify_rpm, bool collapsed)
 {
-	/* TODO */
-	return;
+	msm_lpmrs_exit_sleep((struct msm_rpmrs_limits *)limits,
+				from_idle, notify_rpm, collapsed);
 }
 
 void msm_lpm_show_resources(void)
diff --git a/arch/arm/mach-msm/lpm_resources.c b/arch/arm/mach-msm/lpm_resources.c
index f57f974..e5be352 100644
--- a/arch/arm/mach-msm/lpm_resources.c
+++ b/arch/arm/mach-msm/lpm_resources.c
@@ -18,14 +18,14 @@
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/cpu.h>
-#include <mach/mpm.h>
 #include <linux/notifier.h>
 #include <linux/hrtimer.h>
 #include <linux/tick.h>
+#include <mach/mpm.h>
+#include <mach/rpm-smd.h>
 #include "spm.h"
 #include "lpm_resources.h"
 #include "rpm-notifier.h"
-#include <mach/rpm-smd.h>
 #include "idle.h"
 
 /*Debug Definitions*/
@@ -243,6 +243,7 @@
 					uint32_t key, uint8_t *value)
 {
 	int ret = 0;
+	int msg_id;
 
 	if (!handle)
 		return ret;
@@ -255,10 +256,18 @@
 		return ret;
 	}
 
-	ret = msm_rpm_send_request_noirq(handle);
-	if (ret < 0) {
+	msg_id = msm_rpm_send_request_noirq(handle);
+	if (!msg_id) {
 		pr_err("%s: Error sending RPM request key %u, handle 0x%x\n",
 				__func__, key, (unsigned int)handle);
+		ret = -EIO;
+		return ret;
+	}
+
+	ret = msm_rpm_wait_for_ack(msg_id);
+	if (ret < 0) {
+		pr_err("%s: Couldn't get ACK from RPM for Msg %d Error %d",
+				__func__, msg_id, ret);
 		return ret;
 	}
 	if (msm_lpm_debug_mask & MSM_LPMRS_DEBUG_RPM)
@@ -666,12 +675,14 @@
 	return ret;
 }
 
-void msm_lpmrs_exit_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
-		bool from_idle, bool notify_rpm)
+void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+		bool from_idle, bool notify_rpm, bool collapsed)
 {
 	/* MPM exit sleep
 	if (msm_lpm_use_mpm(limits))
 		msm_mpm_exit_sleep(from_idle);*/
+
+	msm_spm_l2_set_low_power_mode(MSM_SPM_MODE_DISABLED, notify_rpm);
 }
 
 static int msm_lpm_cpu_callback(struct notifier_block *cpu_nb,
diff --git a/arch/arm/mach-msm/lpm_resources.h b/arch/arm/mach-msm/lpm_resources.h
index 9973fbf..bc06d7b 100644
--- a/arch/arm/mach-msm/lpm_resources.h
+++ b/arch/arm/mach-msm/lpm_resources.h
@@ -83,14 +83,14 @@
 
 /**
  * msm_lpmrs_exit_sleep() - Exit sleep, reset the MPM and L2 mode.
- * @ sclk_count - Sleep Clock count.
  * @ limits: pointer to resource limits of the most recent low power mode.
  * @from_idle: bool to determine if this call being made as a part of
  *             idle power collapse.
  * @notify_rpm: bool that informs if this is an RPM notified power collapse.
+ * @collapsed: bool that informs if the Krait was power collapsed.
  */
-void msm_lpmrs_exit_sleep(uint32_t sclk_count, struct msm_rpmrs_limits *limits,
-	bool from_idle, bool notify_rpm);
+void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+	bool from_idle, bool notify_rpm, bool collapsed);
 /**
  * msm_lpmrs_module_init() - Init function that parses the device tree to
  * get the low power resource attributes and registers with RPM driver for
@@ -112,9 +112,8 @@
 	return 0;
 }
 
-static inline void msm_lpmrs_exit_sleep(uint32_t sclk_count,
-		struct msm_rpmrs_limits *limits, bool from_idle,
-		bool notify_rpm)
+static inline void msm_lpmrs_exit_sleep(struct msm_rpmrs_limits *limits,
+	bool from_idle, bool notify_rpm, bool collapsed)
 {
 	return;
 }
diff --git a/arch/arm/mach-msm/memory.c b/arch/arm/mach-msm/memory.c
index a1b21c5..63c2d3a 100644
--- a/arch/arm/mach-msm/memory.c
+++ b/arch/arm/mach-msm/memory.c
@@ -37,6 +37,7 @@
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include <linux/sched.h>
+#include <linux/of_fdt.h>
 
 /* fixme */
 #include <asm/tlbflush.h>
@@ -381,3 +382,117 @@
 {
 	return fmem_set_state(FMEM_T_STATE);
 }
+
+static char * const memtype_names[] = {
+	[MEMTYPE_SMI_KERNEL] = "SMI_KERNEL",
+	[MEMTYPE_SMI]	= "SMI",
+	[MEMTYPE_EBI0] = "EBI0",
+	[MEMTYPE_EBI1] = "EBI1",
+};
+
+static int reserve_memory_type(char *mem_name,
+				struct memtype_reserve *reserve_table,
+				int size)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(memtype_names); i++) {
+		if (memtype_names[i] && strcmp(mem_name,
+				memtype_names[i]) == 0) {
+			reserve_table[i].size += size;
+			return 0;
+		}
+	}
+
+	pr_err("Could not find memory type %s\n", mem_name);
+	return -EINVAL;
+}
+
+static int check_for_compat(unsigned long node)
+{
+	char **start = __compat_exports_start;
+
+	for ( ; start < __compat_exports_end; start++)
+		if (of_flat_dt_is_compatible(node, *start))
+			return 1;
+
+	return 0;
+}
+
+int __init dt_scan_for_memory_reserve(unsigned long node, const char *uname,
+		int depth, void *data)
+{
+	char *memory_name_prop;
+	unsigned int *memory_remove_prop;
+	unsigned long memory_name_prop_length;
+	unsigned long memory_remove_prop_length;
+	unsigned long memory_size_prop_length;
+	unsigned int *memory_size_prop;
+	unsigned int memory_size;
+	unsigned int memory_start;
+	int ret;
+
+	memory_name_prop = of_get_flat_dt_prop(node,
+						"qcom,memory-reservation-type",
+						&memory_name_prop_length);
+	memory_remove_prop = of_get_flat_dt_prop(node,
+						"qcom,memblock-remove",
+						&memory_remove_prop_length);
+
+	if (memory_name_prop || memory_remove_prop) {
+		if (!check_for_compat(node))
+			goto out;
+	} else {
+		goto out;
+	}
+
+	if (memory_name_prop) {
+		if (strnlen(memory_name_prop, memory_name_prop_length) == 0) {
+			WARN(1, "Memory name was malformed\n");
+			goto mem_remove;
+		}
+
+		memory_size_prop = of_get_flat_dt_prop(node,
+						"qcom,memory-reservation-size",
+						&memory_size_prop_length);
+
+		if (memory_size_prop &&
+		    (memory_size_prop_length == sizeof(unsigned int))) {
+			memory_size = be32_to_cpu(*memory_size_prop);
+
+			if (reserve_memory_type(memory_name_prop,
+						data, memory_size) == 0)
+				pr_info("%s reserved %s size %x\n",
+					uname, memory_name_prop, memory_size);
+			else
+				WARN(1, "Node %s reserve failed\n",
+						uname);
+		} else {
+			WARN(1, "Node %s specified bad/nonexistent size\n",
+					uname);
+		}
+	}
+
+mem_remove:
+
+	if (memory_remove_prop) {
+		if (memory_remove_prop_length != (2*sizeof(unsigned int))) {
+			WARN(1, "Memory remove malformed\n");
+			goto out;
+		}
+
+		memory_start = be32_to_cpu(memory_remove_prop[0]);
+		memory_size = be32_to_cpu(memory_remove_prop[1]);
+
+		ret = memblock_remove(memory_start, memory_size);
+		if (ret)
+			WARN(1, "Failed to remove memory %x-%x\n",
+				memory_start, memory_start+memory_size);
+		else
+			pr_info("Node %s removed memory %x-%x\n", uname,
+				memory_start, memory_start+memory_size);
+	}
+
+out:
+	return 0;
+}
diff --git a/arch/arm/mach-msm/mpm-8625.c b/arch/arm/mach-msm/mpm-8625.c
index 954e5cc..3c219be 100644
--- a/arch/arm/mach-msm/mpm-8625.c
+++ b/arch/arm/mach-msm/mpm-8625.c
@@ -221,7 +221,7 @@
 		/* save the contents of GIC CPU interface and Distributor
 		 * Disable all the Interrupts, if we enter from idle pc
 		 */
-		msm_gic_save(modem_wake, from_idle);
+		msm_gic_save();
 		irq_set_irq_type(MSM8625_INT_A9_M2A_6, IRQF_TRIGGER_RISING);
 		enable_irq(MSM8625_INT_A9_M2A_6);
 		pr_debug("%s going for sleep now\n", __func__);
diff --git a/arch/arm/mach-msm/msm-krait-l2-accessors.c b/arch/arm/mach-msm/msm-krait-l2-accessors.c
index 3d341e3..41a2490 100644
--- a/arch/arm/mach-msm/msm-krait-l2-accessors.c
+++ b/arch/arm/mach-msm/msm-krait-l2-accessors.c
@@ -14,19 +14,83 @@
 #include <linux/spinlock.h>
 #include <linux/module.h>
 #include <asm/mach-types.h>
+#include <asm/cputype.h>
 
 DEFINE_RAW_SPINLOCK(l2_access_lock);
 
+#define L2CPMR		0x500
+#define L2CPUCPMR	0x501
+#define L2CPUVRF8	0x708
+#define CPUNDX_MASK	(0x7 << 12)
+
+/*
+ * For Krait versions found in APQ8064v1.x, save L2CPUVRF8 before
+ * L2CPMR or L2CPUCPMR writes and restore it after to work around an
+ * issue where L2CPUVRF8 becomes corrupt.
+ */
+static bool l2cpuvrf8_needs_fix(u32 reg_addr)
+{
+	switch (read_cpuid_id()) {
+	case 0x510F06F0: /* KR28M4A10  */
+	case 0x510F06F1: /* KR28M4A10B */
+	case 0x510F06F2: /* KR28M4A11  */
+		break;
+	default:
+		return false;
+	};
+
+	switch (reg_addr & ~CPUNDX_MASK) {
+	case L2CPMR:
+	case L2CPUCPMR:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static u32 l2cpuvrf8_fix_save(u32 reg_addr, u32 *l2cpuvrf8_val)
+{
+	u32 l2cpuvrf8_addr = L2CPUVRF8 | (reg_addr & CPUNDX_MASK);
+
+	mb();
+	asm volatile ("mcr     p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+		      "isb\n\t"
+		      "mrc     p15, 3, %[l2cpdr],   c15, c0, 7\n\t"
+			: [l2cpdr]"=r" (*l2cpuvrf8_val)
+			: [l2cpselr]"r" (l2cpuvrf8_addr)
+	);
+
+	return l2cpuvrf8_addr;
+}
+
+static void l2cpuvrf8_fix_restore(u32 l2cpuvrf8_addr, u32 l2cpuvrf8_val)
+{
+	mb();
+	asm volatile ("mcr     p15, 3, %[l2cpselr], c15, c0, 6\n\t"
+		      "isb\n\t"
+		      "mcr     p15, 3, %[l2cpdr],   c15, c0, 7\n\t"
+		      "isb\n\t"
+			:
+			: [l2cpselr]"r" (l2cpuvrf8_addr),
+			  [l2cpdr]"r" (l2cpuvrf8_val)
+	);
+}
+
 u32 set_get_l2_indirect_reg(u32 reg_addr, u32 val)
 {
 	unsigned long flags;
+	u32 uninitialized_var(l2cpuvrf8_val), l2cpuvrf8_addr = 0;
 	u32 ret_val;
+
 	/* CP15 registers are not emulated on RUMI3. */
 	if (machine_is_msm8960_rumi3())
 		return 0;
 
 	raw_spin_lock_irqsave(&l2_access_lock, flags);
 
+	if (l2cpuvrf8_needs_fix(reg_addr))
+		l2cpuvrf8_addr = l2cpuvrf8_fix_save(reg_addr, &l2cpuvrf8_val);
+
 	mb();
 	asm volatile ("mcr     p15, 3, %[l2cpselr], c15, c0, 6\n\t"
 		      "isb\n\t"
@@ -36,6 +100,10 @@
 			: [l2cpdr_read]"=r" (ret_val)
 			: [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
 	);
+
+	if (l2cpuvrf8_addr)
+		l2cpuvrf8_fix_restore(l2cpuvrf8_addr, l2cpuvrf8_val);
+
 	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
 
 	return ret_val;
@@ -45,11 +113,17 @@
 void set_l2_indirect_reg(u32 reg_addr, u32 val)
 {
 	unsigned long flags;
+	u32 uninitialized_var(l2cpuvrf8_val), l2cpuvrf8_addr = 0;
+
 	/* CP15 registers are not emulated on RUMI3. */
 	if (machine_is_msm8960_rumi3())
 		return;
 
 	raw_spin_lock_irqsave(&l2_access_lock, flags);
+
+	if (l2cpuvrf8_needs_fix(reg_addr))
+		l2cpuvrf8_addr = l2cpuvrf8_fix_save(reg_addr, &l2cpuvrf8_val);
+
 	mb();
 	asm volatile ("mcr     p15, 3, %[l2cpselr], c15, c0, 6\n\t"
 		      "isb\n\t"
@@ -58,6 +132,10 @@
 			:
 			: [l2cpselr]"r" (reg_addr), [l2cpdr]"r" (val)
 	);
+
+	if (l2cpuvrf8_addr)
+		l2cpuvrf8_fix_restore(l2cpuvrf8_addr, l2cpuvrf8_val);
+
 	raw_spin_unlock_irqrestore(&l2_access_lock, flags);
 }
 EXPORT_SYMBOL(set_l2_indirect_reg);
diff --git a/arch/arm/mach-msm/msm_memory_dump.c b/arch/arm/mach-msm/msm_memory_dump.c
new file mode 100644
index 0000000..4f48a0d
--- /dev/null
+++ b/arch/arm/mach-msm/msm_memory_dump.c
@@ -0,0 +1,78 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include <asm/cacheflush.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/notifier.h>
+#include <linux/export.h>
+#include <mach/msm_iomap.h>
+#include <mach/msm_memory_dump.h>
+
+
+/*TODO: Needs to be set to correct value */
+#define DUMP_TABLE_OFFSET	0x20
+#define MSM_DUMP_TABLE_VERSION	MK_TABLE(1, 0)
+
+static struct msm_memory_dump mem_dump_data;
+
+static int msm_memory_dump_panic(struct notifier_block *this,
+				unsigned long event, void *ptr)
+{
+	writel_relaxed(0, MSM_IMEM_BASE + DUMP_TABLE_OFFSET);
+	return 0;
+}
+
+static struct notifier_block msm_memory_dump_blk = {
+	.notifier_call  = msm_memory_dump_panic,
+};
+
+int msm_dump_table_register(struct msm_client_dump *client_entry)
+{
+	struct msm_client_dump *entry;
+	struct msm_dump_table *table = mem_dump_data.dump_table_ptr;
+
+	if (!table || table->num_entries >= MAX_NUM_CLIENTS)
+		return -EINVAL;
+	entry = &table->client_entries[table->num_entries];
+	entry->id = client_entry->id;
+	entry->start_addr = client_entry->start_addr;
+	entry->end_addr = client_entry->end_addr;
+	table->num_entries++;
+	/* flush cache */
+	dmac_flush_range(table, table + sizeof(struct msm_dump_table));
+	return 0;
+}
+EXPORT_SYMBOL(msm_dump_table_register);
+
+static int __init init_memory_dump(void)
+{
+	struct msm_dump_table *table;
+
+	mem_dump_data.dump_table_ptr = kzalloc(sizeof(struct msm_dump_table),
+						GFP_KERNEL);
+	if (!mem_dump_data.dump_table_ptr) {
+		printk(KERN_ERR "unable to allocate memory for dump table\n");
+		return -ENOMEM;
+	}
+	table = mem_dump_data.dump_table_ptr;
+	table->version = MSM_DUMP_TABLE_VERSION;
+	mem_dump_data.dump_table_phys = virt_to_phys(table);
+	/* TODO: Need to write physical address of table to IMEM */
+	atomic_notifier_chain_register(&panic_notifier_list,
+						&msm_memory_dump_blk);
+	printk(KERN_INFO "MSM Memory Dump table set up\n");
+	return 0;
+}
+
+early_initcall(init_memory_dump);
+
diff --git a/arch/arm/mach-msm/msm_smem_iface.c b/arch/arm/mach-msm/msm_smem_iface.c
new file mode 100644
index 0000000..b09fda5
--- /dev/null
+++ b/arch/arm/mach-msm/msm_smem_iface.c
@@ -0,0 +1,44 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include "msm_smem_iface.h"
+
+/**
+ * mem_get_cpr_info() - Copy Core Power Reduction (CPR) driver specific
+ *			data from Shared memory (SMEM).
+ * @cpr_info - Pointer to CPR data. Memory to be allocated and freed by
+ *             calling function.
+ *
+ * Copy CPR specific data from SMEM to cpr_info.
+ */
+
+void msm_smem_get_cpr_info(struct cpr_info_type *cpr_info)
+{
+	struct boot_info_for_apps *boot_info;
+	struct cpr_info_type *temp_cpr_info;
+	uint32_t smem_boot_info_size;
+
+	boot_info = smem_get_entry(SMEM_BOOT_INFO_FOR_APPS,
+					&smem_boot_info_size);
+	BUG_ON(!boot_info);
+	if (smem_boot_info_size < sizeof(struct boot_info_for_apps)) {
+		pr_err("%s: Shared boot info data structure too small!\n",
+			__func__);
+		BUG();
+	} else {
+		pr_debug("%s: Shared boot info available.\n", __func__);
+	}
+	temp_cpr_info = (struct cpr_info_type *) &(boot_info->cpr_info);
+	cpr_info->ring_osc = temp_cpr_info->ring_osc;
+	cpr_info->turbo_quot = temp_cpr_info->turbo_quot;
+	cpr_info->pvs_fuse = temp_cpr_info->pvs_fuse;
+}
diff --git a/arch/arm/mach-msm/msm_smem_iface.h b/arch/arm/mach-msm/msm_smem_iface.h
new file mode 100644
index 0000000..2da0232
--- /dev/null
+++ b/arch/arm/mach-msm/msm_smem_iface.h
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
+#define __ARCH_ARM_MACH_MSM_SMEM_IFACE_H
+
+#include <mach/msm_smsm.h>
+#include "smd_private.h"
+
+#define MAX_KEY_EVENTS 10
+#define MAX_SEC_KEY_PAYLOAD 32
+
+struct boot_shared_ssd_status_info {
+	uint32_t update_status;  /* To check if process is successful or not */
+	uint32_t bl_error_code;  /* To indicate error code in bootloader */
+};
+
+struct boot_symmetric_key_info {
+	uint32_t key_len; /* Encrypted Symmetric Key Length */
+	uint32_t iv_len;  /* Initialization Vector Length */
+	uint8_t  key[MAX_SEC_KEY_PAYLOAD]; /* Encrypted Symmetric Key */
+	uint8_t  iv[MAX_SEC_KEY_PAYLOAD]; /* Initialization Vector */
+};
+
+struct cpr_info_type {
+	uint8_t ring_osc;         /* CPR FUSE [0]: TURBO RO SEL BIT */
+	uint8_t turbo_quot;        /* CPRFUSE[1:7] : TURBO QUOT*/
+	uint8_t pvs_fuse;         /* TURBO PVS FUSE */
+};
+
+struct boot_info_for_apps {
+	uint32_t apps_image_start_addr; /* apps image start address */
+	uint32_t boot_flags; /* bit mask of upto 32 flags */
+	struct boot_shared_ssd_status_info ssd_status_info; /* SSD status */
+	struct boot_symmetric_key_info key_info;
+	uint16_t boot_keys_pressed[MAX_KEY_EVENTS]; /* Log of key presses */
+	uint32_t timetick; /* Modem tick timer value before apps out of reset */
+	struct cpr_info_type cpr_info;
+	uint8_t PAD[25];
+};
+
+void msm_smem_get_cpr_info(struct cpr_info_type *cpr_info);
+
+#endif /* __ARCH_ARM_MACH_MSM_SMEM_IFACE_H */
diff --git a/arch/arm/mach-msm/ocmem.c b/arch/arm/mach-msm/ocmem.c
index a233080..753f6fb 100644
--- a/arch/arm/mach-msm/ocmem.c
+++ b/arch/arm/mach-msm/ocmem.c
@@ -30,8 +30,9 @@
 */
 
 #define OCMEM_REGION_CTL_BASE 0xFDD0003C
-#define OCMEM_REGION_CTL_SIZE 0xC
+#define OCMEM_REGION_CTL_SIZE 0xFD0
 #define REGION_ENABLE 0x00003333
+#define GRAPHICS_REGION_CTL (0x17F000)
 
 struct ocmem_partition {
 	const char *name;
@@ -55,6 +56,7 @@
 static struct ocmem_plat_data *ocmem_pdata;
 
 #define CLIENT_NAME_MAX 10
+
 /* Must be in sync with enum ocmem_client */
 static const char *client_names[OCMEM_CLIENT_MAX] = {
 	"graphics",
@@ -64,7 +66,7 @@
 	"voice",
 	"lp_audio",
 	"sensors",
-	"blast",
+	"other_os",
 };
 
 struct ocmem_quota_table {
@@ -85,7 +87,7 @@
 	{ "voice", OCMEM_VOICE,  0x0, 0x0, 0x0, 0 },
 	{ "hp_audio", OCMEM_HP_AUDIO, 0x0, 0x0, 0x0, 0},
 	{ "lp_audio", OCMEM_LP_AUDIO, 0x80000, 0xA0000, 0xA0000, 0},
-	{ "blast", OCMEM_BLAST, 0x120000, 0x20000, 0x20000, 0},
+	{ "other_os", OCMEM_OTHER_OS, 0x120000, 0x20000, 0x20000, 0},
 	{ "sensors", OCMEM_SENSORS, 0x140000, 0x40000, 0x40000, 0},
 };
 
@@ -99,6 +101,18 @@
 	return -EINVAL;
 }
 
+int check_id(int id)
+{
+	return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
+}
+
+const char *get_name(int id)
+{
+	if (!check_id(id))
+		return NULL;
+	return client_names[id];
+}
+
 inline unsigned long phys_to_offset(unsigned long addr)
 {
 	if (!ocmem_pdata)
@@ -455,7 +469,7 @@
 		zone->owner = part->id;
 		zone->active_regions = 0;
 		zone->max_regions = 0;
-		INIT_LIST_HEAD(&zone->region_list);
+		INIT_LIST_HEAD(&zone->req_list);
 		zone->z_ops = z_ops;
 		if (part->p_tail) {
 			z_ops->allocate = allocate_tail;
@@ -519,6 +533,13 @@
 	writel_relaxed(REGION_ENABLE, ocmem_region_vbase);
 	writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 4);
 	writel_relaxed(REGION_ENABLE, ocmem_region_vbase + 8);
+	/* Enable the ocmem graphics mpU as a workaround in Virtio */
+	/* This will be programmed by TZ after TZ support is integrated */
+	writel_relaxed(GRAPHICS_REGION_CTL, ocmem_region_vbase + 0xFCC);
+
+	if (ocmem_rdm_init(pdev))
+		return -EBUSY;
+
 	dev_dbg(dev, "initialized successfully\n");
 	return 0;
 }
diff --git a/arch/arm/mach-msm/ocmem_api.c b/arch/arm/mach-msm/ocmem_api.c
index bed13de..bb32fca 100644
--- a/arch/arm/mach-msm/ocmem_api.c
+++ b/arch/arm/mach-msm/ocmem_api.c
@@ -13,10 +13,8 @@
 #include <linux/slab.h>
 #include <mach/ocmem_priv.h>
 
-static inline int check_id(int id)
-{
-	return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
-}
+static DEFINE_MUTEX(ocmem_eviction_lock);
+static DECLARE_BITMAP(evicted, OCMEM_CLIENT_MAX);
 
 static struct ocmem_handle *generate_handle(void)
 {
@@ -61,6 +59,24 @@
 	return 0;
 }
 
+static int __ocmem_shrink(int id, struct ocmem_buf *buf, unsigned long len)
+{
+	int ret = 0;
+	struct ocmem_handle *handle = buffer_to_handle(buf);
+
+	if (!handle)
+		return -EINVAL;
+
+	mutex_lock(&handle->handle_mutex);
+	ret = process_shrink(id, handle, len);
+	mutex_unlock(&handle->handle_mutex);
+
+	if (ret)
+		return -EINVAL;
+
+	return 0;
+}
+
 static struct ocmem_buf *__ocmem_allocate_range(int id, unsigned long min,
 		unsigned long max, unsigned long step, bool block, bool wait)
 {
@@ -218,6 +234,15 @@
 	return __ocmem_free(client_id, buffer);
 }
 
+int ocmem_shrink(int client_id, struct ocmem_buf *buffer, unsigned long len)
+{
+	if (!buffer)
+		return -EINVAL;
+	if (len >= buffer->len)
+		return -EINVAL;
+	return __ocmem_shrink(client_id, buffer, len);
+}
+
 int pre_validate_chunk_list(struct ocmem_map_list *list)
 {
 	int i = 0;
@@ -236,8 +261,12 @@
 
 	for (i = 0; i < list->num_chunks; i++) {
 		if (!chunks[i].ddr_paddr ||
-			chunks[i].size < MIN_CHUNK_SIZE)
+			chunks[i].size < MIN_CHUNK_SIZE ||
+			!IS_ALIGNED(chunks[i].size, MIN_CHUNK_SIZE)) {
+			pr_err("Invalid ocmem chunk at index %d (p: %lx, size %lx)\n",
+					i, chunks[i].ddr_paddr, chunks[i].size);
 			return -EINVAL;
+		}
 	}
 	return 0;
 }
@@ -265,7 +294,7 @@
 		return -EINVAL;
 	}
 
-	if (!pre_validate_chunk_list(list))
+	if (pre_validate_chunk_list(list) != 0)
 		return -EINVAL;
 
 	handle = buffer_to_handle(buffer);
@@ -303,14 +332,10 @@
 		return -EINVAL;
 	}
 
-	if (!pre_validate_chunk_list(list))
+	if (pre_validate_chunk_list(list) != 0)
 		return -EINVAL;
 
 	handle = buffer_to_handle(buffer);
-
-	if (!handle)
-		return -EINVAL;
-
 	mutex_lock(&handle->handle_mutex);
 	ret = process_xfer(client_id, handle, list, TO_DDR);
 	mutex_unlock(&handle->handle_mutex);
@@ -325,3 +350,52 @@
 	}
 	return process_quota(client_id);
 }
+
+/* Synchronous eviction/restore calls */
+/* Only a single eviction or restoration is allowed */
+/* Evictions/Restorations cannot be concurrent with other maps */
+int ocmem_evict(int client_id)
+{
+	int ret = 0;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&ocmem_eviction_lock);
+	if (test_bit(client_id, evicted)) {
+		pr_err("ocmem: Previous eviction was not restored by %d\n",
+			client_id);
+		mutex_unlock(&ocmem_eviction_lock);
+		return -EINVAL;
+	}
+
+	ret = process_evict(client_id);
+	if (ret == 0)
+		set_bit(client_id, evicted);
+
+	mutex_unlock(&ocmem_eviction_lock);
+	return ret;
+}
+
+int ocmem_restore(int client_id)
+{
+	int ret = 0;
+
+	if (!check_id(client_id)) {
+		pr_err("ocmem: Invalid client id: %d\n", client_id);
+		return -EINVAL;
+	}
+
+	mutex_lock(&ocmem_eviction_lock);
+	if (!test_bit(client_id, evicted)) {
+		pr_err("ocmem: No previous eviction by %d\n", client_id);
+		mutex_unlock(&ocmem_eviction_lock);
+		return -EINVAL;
+	}
+	ret = process_restore(client_id);
+	clear_bit(client_id, evicted);
+	mutex_unlock(&ocmem_eviction_lock);
+	return ret;
+}
diff --git a/arch/arm/mach-msm/ocmem_notifier.c b/arch/arm/mach-msm/ocmem_notifier.c
index 4754f44..9fbcd73 100644
--- a/arch/arm/mach-msm/ocmem_notifier.c
+++ b/arch/arm/mach-msm/ocmem_notifier.c
@@ -24,11 +24,6 @@
 	unsigned listeners;
 } notifiers[OCMEM_CLIENT_MAX];
 
-static int check_id(int id)
-{
-	return (id < OCMEM_CLIENT_MAX && id >= OCMEM_GRAPHICS);
-}
-
 int check_notifier(int id)
 {
 	int ret = 0;
diff --git a/arch/arm/mach-msm/ocmem_rdm.c b/arch/arm/mach-msm/ocmem_rdm.c
new file mode 100644
index 0000000..6b93d04
--- /dev/null
+++ b/arch/arm/mach-msm/ocmem_rdm.c
@@ -0,0 +1,238 @@
+/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/mm.h>
+#include <linux/rbtree.h>
+#include <linux/genalloc.h>
+#include <linux/of.h>
+#include <linux/io.h>
+#include <linux/platform_device.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/delay.h>
+#include <linux/interrupt.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <mach/ocmem_priv.h>
+
+#define RDM_MAX_ENTRIES 32
+#define RDM_MAX_CLIENTS 2
+
+/* Data Mover Parameters */
+#define DM_BLOCK_128 0x0
+#define DM_BLOCK_256 0x1
+#define DM_BR_ID_LPASS 0x0
+#define DM_BR_ID_GPS 0x1
+
+#define DM_INTR_CLR (0x8)
+#define DM_INTR_MASK (0xC)
+#define DM_GEN_STATUS (0x10)
+#define DM_STATUS (0x14)
+#define DM_CTRL (0x1000)
+#define DM_TBL_BASE (0x1010)
+#define DM_TBL_IDX(x) ((x) * 0x18)
+#define DM_TBL_n(x) (DM_TBL_BASE + (DM_TBL_IDX(x)))
+#define DM_TBL_n_offset(x) DM_TBL_n(x)
+#define DM_TBL_n_size(x) (DM_TBL_n(x)+0x4)
+#define DM_TBL_n_paddr(x) (DM_TBL_n(x)+0x8)
+#define DM_TBL_n_ctrl(x) (DM_TBL_n(x)+0x10)
+
+#define BR_CTRL (0x0)
+#define BR_CLIENT_BASE (0x4)
+#define BR_CLIENT_n_IDX(x) ((x) * 0x4)
+#define BR_CLIENT_n_ctrl(x) (BR_CLIENT_BASE + (BR_CLIENT_n_IDX(x)))
+#define BR_STATUS (0x14)
+/* 16 entries per client are supported */
+/* Use entries 0 - 15 for client0 */
+#define BR_CLIENT0_MASK	(0x1000)
+/* Use entries 16- 31 for client1 */
+#define BR_CLIENT1_MASK	(0x2010)
+
+#define BR_TBL_BASE (0x40)
+#define BR_TBL_IDX(x) ((x) * 0x18)
+#define BR_TBL_n(x) (BR_TBL_BASE + (BR_TBL_IDX(x)))
+#define BR_TBL_n_offset(x) BR_TBL_n(x)
+#define BR_TBL_n_size(x) (BR_TBL_n(x)+0x4)
+#define BR_TBL_n_paddr(x) (BR_TBL_n(x)+0x8)
+#define BR_TBL_n_ctrl(x) (BR_TBL_n(x)+0x10)
+
+/* Constants and Shifts */
+#define BR_TBL_ENTRY_ENABLE 0x1
+#define BR_TBL_START 0x0
+#define BR_TBL_END 0x8
+#define BR_RW_SHIFT 0x2
+
+#define DM_TBL_START 0x10
+#define DM_TBL_END 0x18
+#define DM_CLIENT_SHIFT 0x8
+#define DM_BR_ID_SHIFT 0x4
+#define DM_BR_BLK_SHIFT 0x1
+#define DM_DIR_SHIFT 0x0
+
+#define DM_DONE 0x1
+#define DM_INTR_ENABLE 0x0
+#define DM_INTR_DISABLE 0x1
+
+static void *br_base;
+static void *dm_base;
+
+static atomic_t dm_pending;
+static wait_queue_head_t dm_wq;
+/* Shadow tables for debug purposes */
+struct ocmem_br_table {
+	unsigned int offset;
+	unsigned int size;
+	unsigned int ddr_low;
+	unsigned int ddr_high;
+	unsigned int ctrl;
+} br_table[RDM_MAX_ENTRIES];
+
+/* DM Table replicates an entire BR table */
+/* Note: There are more than 1 BRs in the system */
+struct ocmem_dm_table {
+	unsigned int offset;
+	unsigned int size;
+	unsigned int ddr_low;
+	unsigned int ddr_high;
+	unsigned int ctrl;
+} dm_table[RDM_MAX_ENTRIES];
+
+/* Wrapper that will shadow these values later */
+static int ocmem_read(void *at)
+{
+	return readl_relaxed(at);
+}
+
+/* Wrapper that will shadow these values later */
+static int ocmem_write(unsigned long val, void *at)
+{
+	writel_relaxed(val, at);
+	return 0;
+}
+
+static inline int client_ctrl_id(int id)
+{
+	return (id == OCMEM_SENSORS) ? 1 : 0;
+}
+
+static inline int client_slot_start(int id)
+{
+
+	return client_ctrl_id(id) * 16;
+}
+
+static irqreturn_t ocmem_dm_irq_handler(int irq, void *dev_id)
+{
+	atomic_set(&dm_pending, 0);
+	ocmem_write(DM_INTR_DISABLE, dm_base + DM_INTR_CLR);
+	wake_up_interruptible(&dm_wq);
+	return IRQ_HANDLED;
+}
+
+/* Lock during transfers */
+int ocmem_rdm_transfer(int id, struct ocmem_map_list *clist,
+			unsigned long start, int direction)
+{
+	int num_chunks = clist->num_chunks;
+	int slot = client_slot_start(id);
+	int table_start = 0;
+	int table_end = 0;
+	int br_ctrl = 0;
+	int br_id = 0;
+	int dm_ctrl = 0;
+	int i = 0;
+	int j = 0;
+	int status = 0;
+
+	for (i = 0, j = slot; i < num_chunks; i++, j++) {
+
+		struct ocmem_chunk *chunk = &clist->chunks[i];
+		int sz = chunk->size;
+		int paddr = chunk->ddr_paddr;
+		int tbl_n_ctrl = 0;
+
+		tbl_n_ctrl |= BR_TBL_ENTRY_ENABLE;
+		if (chunk->ro)
+			tbl_n_ctrl |= (1 << BR_RW_SHIFT);
+
+		/* Table Entry n of BR and DM */
+		ocmem_write(start, br_base + BR_TBL_n_offset(j));
+		ocmem_write(sz, br_base + BR_TBL_n_size(j));
+		ocmem_write(paddr, br_base + BR_TBL_n_paddr(j));
+		ocmem_write(tbl_n_ctrl, br_base + BR_TBL_n_ctrl(j));
+
+		ocmem_write(start, dm_base + DM_TBL_n_offset(j));
+		ocmem_write(sz, dm_base + DM_TBL_n_size(j));
+		ocmem_write(paddr, dm_base + DM_TBL_n_paddr(j));
+		ocmem_write(tbl_n_ctrl, dm_base + DM_TBL_n_ctrl(j));
+
+		start += sz;
+	}
+
+	br_id = client_ctrl_id(id);
+	table_start = slot;
+	table_end = slot + num_chunks - 1;
+	br_ctrl |= (table_start << BR_TBL_START);
+	br_ctrl |= (table_end << BR_TBL_END);
+
+	ocmem_write(br_ctrl, (br_base + BR_CLIENT_n_ctrl(br_id)));
+	/* Enable BR */
+	ocmem_write(0x1, br_base + BR_CTRL);
+
+	/* Compute DM Control Value */
+	dm_ctrl |= (table_start << DM_TBL_START);
+	dm_ctrl |= (table_end << DM_TBL_END);
+
+	dm_ctrl |= (DM_BR_ID_LPASS << DM_BR_ID_SHIFT);
+	dm_ctrl |= (DM_BLOCK_256 << DM_BR_BLK_SHIFT);
+	dm_ctrl |= (direction << DM_DIR_SHIFT);
+
+	status = ocmem_read(dm_base + DM_STATUS);
+	pr_debug("Transfer status before %x\n", status);
+	atomic_set(&dm_pending, 1);
+	/* Trigger DM */
+	ocmem_write(dm_ctrl, dm_base + DM_CTRL);
+	pr_debug("ocmem: rdm: dm_ctrl %x br_ctrl %x\n", dm_ctrl, br_ctrl);
+
+	wait_event_interruptible(dm_wq,
+		atomic_read(&dm_pending) == 0);
+
+	return 0;
+}
+
+int ocmem_rdm_init(struct platform_device *pdev)
+{
+
+	struct ocmem_plat_data *pdata = NULL;
+	int rc = 0;
+
+	pdata = platform_get_drvdata(pdev);
+
+	br_base = pdata->br_base;
+	dm_base = pdata->dm_base;
+
+	rc = devm_request_irq(&pdev->dev, pdata->dm_irq, ocmem_dm_irq_handler,
+				IRQF_TRIGGER_RISING, "ocmem_dm_irq", pdata);
+
+	if (rc) {
+		dev_err(&pdev->dev, "Failed to request dm irq");
+		return -EINVAL;
+	}
+
+	init_waitqueue_head(&dm_wq);
+	/* enable dm interrupts */
+	ocmem_write(DM_INTR_ENABLE, dm_base + DM_INTR_MASK);
+	return 0;
+}
diff --git a/arch/arm/mach-msm/ocmem_sched.c b/arch/arm/mach-msm/ocmem_sched.c
index 10a267c..f6d066d 100644
--- a/arch/arm/mach-msm/ocmem_sched.c
+++ b/arch/arm/mach-msm/ocmem_sched.c
@@ -54,7 +54,7 @@
 	MIN_PRIO = 0x0,
 	NO_PRIO = MIN_PRIO,
 	PRIO_SENSORS = 0x1,
-	PRIO_BLAST = 0x1,
+	PRIO_OTHER_OS = 0x1,
 	PRIO_LP_AUDIO = 0x1,
 	PRIO_HP_AUDIO = 0x2,
 	PRIO_VOICE = 0x3,
@@ -75,6 +75,21 @@
 */
 #define SCHED_DELAY 10
 
+static struct list_head rdm_queue;
+static struct mutex rdm_mutex;
+static struct workqueue_struct *ocmem_rdm_wq;
+static struct workqueue_struct *ocmem_eviction_wq;
+
+static struct ocmem_eviction_data *evictions[OCMEM_CLIENT_MAX];
+
+struct ocmem_rdm_work {
+	int id;
+	struct ocmem_map_list *list;
+	struct ocmem_handle *handle;
+	int direction;
+	struct work_struct work;
+};
+
 /* OCMEM Operational modes */
 enum ocmem_client_modes {
 	OCMEM_PERFORMANCE = 1,
@@ -107,7 +122,7 @@
 	{OCMEM_VOICE, PRIO_VOICE, OCMEM_PASSIVE, OCMEM_BLOCKED},
 	{OCMEM_LP_AUDIO, PRIO_LP_AUDIO, OCMEM_LOW_POWER, OCMEM_SYSNOC},
 	{OCMEM_SENSORS, PRIO_SENSORS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
-	{OCMEM_BLAST, PRIO_BLAST, OCMEM_LOW_POWER, OCMEM_SYSNOC},
+	{OCMEM_OTHER_OS, PRIO_OTHER_OS, OCMEM_LOW_POWER, OCMEM_SYSNOC},
 };
 
 static struct rb_root sched_tree;
@@ -119,6 +134,8 @@
 	struct rb_node region_rb;
 	/* Hash map of requests */
 	struct idr region_idr;
+	/* Chain in eviction list */
+	struct list_head eviction_list;
 	unsigned long r_start;
 	unsigned long r_end;
 	unsigned long r_sz;
@@ -244,6 +261,7 @@
 	if (!p)
 		return NULL;
 	idr_init(&p->region_idr);
+	INIT_LIST_HEAD(&p->eviction_list);
 	p->r_start = p->r_end = p->r_sz = 0x0;
 	p->max_prio = NO_PRIO;
 	return p;
@@ -461,10 +479,14 @@
 {
 	int rc = 0;
 
+	down_write(&req->rw_sem);
+
 	mutex_lock(&sched_mutex);
 	rc = __sched_map(req);
 	mutex_unlock(&sched_mutex);
 
+	up_write(&req->rw_sem);
+
 	if (rc == OP_FAIL)
 		return -EINVAL;
 
@@ -475,10 +497,14 @@
 {
 	int rc = 0;
 
+	down_write(&req->rw_sem);
+
 	mutex_lock(&sched_mutex);
 	rc = __sched_unmap(req);
 	mutex_unlock(&sched_mutex);
 
+	up_write(&req->rw_sem);
+
 	if (rc == OP_FAIL)
 		return -EINVAL;
 
@@ -713,6 +739,104 @@
 }
 
 /* Must be called with sched_mutex held */
+static int __sched_shrink(struct ocmem_req *req, unsigned long new_sz)
+{
+	int owner = req->owner;
+	int ret = 0;
+
+	struct ocmem_req *matched_req = NULL;
+	struct ocmem_region *matched_region = NULL;
+	struct ocmem_region *region = NULL;
+	unsigned long alloc_addr = 0x0;
+
+	struct ocmem_zone *zone = get_zone(owner);
+
+	BUG_ON(!zone);
+
+	/* The shrink should not be called for zero size */
+	BUG_ON(new_sz == 0);
+
+	matched_region = find_region_match(req->req_start, req->req_end);
+	matched_req = find_req_match(req->req_id, matched_region);
+
+	if (!matched_region || !matched_req)
+		goto invalid_op_error;
+	if (matched_req != req)
+		goto invalid_op_error;
+
+
+	ret = zone->z_ops->free(zone,
+		matched_req->req_start, matched_req->req_sz);
+
+	if (ret < 0) {
+		pr_err("Zone Allocation operation failed\n");
+		goto internal_error;
+	}
+
+	alloc_addr = zone->z_ops->allocate(zone, new_sz);
+
+	if (alloc_addr < 0) {
+		pr_err("Zone Allocation operation failed\n");
+		goto internal_error;
+	}
+
+	/* Detach the region from the interval tree */
+	/* This is to guarantee that the change in size
+	 * causes the tree to be rebalanced if required */
+
+	detach_req(matched_region, req);
+	if (req_count(matched_region) == 0) {
+		remove_region(matched_region);
+		region = matched_region;
+	} else {
+		region = create_region();
+		if (!region) {
+			pr_err("ocmem: Unable to create region\n");
+			goto internal_error;
+		}
+	}
+	/* update the request */
+	req->req_start = alloc_addr;
+	req->req_sz = new_sz;
+	req->req_end = alloc_addr + req->req_sz;
+
+	if (req_count(region) == 0) {
+		remove_region(matched_region);
+		destroy_region(matched_region);
+	}
+
+	/* update request state */
+	SET_STATE(req, R_MUST_GROW);
+	SET_STATE(req, R_MUST_MAP);
+	req->op = SCHED_MAP;
+
+	/* attach the request to the region */
+	attach_req(region, req);
+	populate_region(region, req);
+	update_region_prio(region);
+
+	/* update the tree with new region */
+	if (insert_region(region)) {
+		pr_err("ocmem: Failed to insert the region\n");
+		zone->z_ops->free(zone, alloc_addr, new_sz);
+		detach_req(region, req);
+		update_region_prio(region);
+		/* req will be destroyed by the caller */
+		goto region_error;
+	}
+	return OP_COMPLETE;
+
+region_error:
+	destroy_region(region);
+internal_error:
+	pr_err("ocmem: shrink: Failed\n");
+	return OP_FAIL;
+invalid_op_error:
+	pr_err("ocmem: shrink: Failed to find matching region\n");
+	return OP_FAIL;
+}
+
+/* Must be called with sched_mutex held */
 static int __sched_allocate(struct ocmem_req *req, bool can_block,
 				bool can_wait)
 {
@@ -906,12 +1030,6 @@
 	return req;
 }
 
-int process_xfer(int id, struct ocmem_handle *handle,
-		struct ocmem_map_list *list, int direction)
-{
-
-	return 0;
-}
 
 unsigned long process_quota(int id)
 {
@@ -989,6 +1107,35 @@
 	return 0;
 }
 
+static int do_shrink(struct ocmem_req *req, unsigned long shrink_size)
+{
+
+	int rc = 0;
+	struct ocmem_buf *buffer = NULL;
+
+	down_write(&req->rw_sem);
+	buffer = req->buffer;
+
+	/* Take the scheduler mutex */
+	mutex_lock(&sched_mutex);
+	rc = __sched_shrink(req, shrink_size);
+	mutex_unlock(&sched_mutex);
+
+	if (rc == OP_FAIL)
+		goto err_op_fail;
+
+	else if (rc == OP_COMPLETE) {
+		buffer->addr = device_address(req->owner, req->req_start);
+		buffer->len = req->req_sz;
+	}
+
+	up_write(&req->rw_sem);
+	return 0;
+err_op_fail:
+	up_write(&req->rw_sem);
+	return -EINVAL;
+}
+
 static void ocmem_sched_wk_func(struct work_struct *work);
 DECLARE_DELAYED_WORK(ocmem_sched_thread, ocmem_sched_wk_func);
 
@@ -1076,6 +1223,250 @@
 	return 0;
 }
 
+static void ocmem_rdm_worker(struct work_struct *work)
+{
+	int offset = 0;
+	int rc = 0;
+	int event;
+	struct ocmem_rdm_work *work_data = container_of(work,
+				struct ocmem_rdm_work, work);
+	int id = work_data->id;
+	struct ocmem_map_list *list = work_data->list;
+	int direction = work_data->direction;
+	struct ocmem_handle *handle = work_data->handle;
+	struct ocmem_req *req = handle_to_req(handle);
+	struct ocmem_buf *buffer = handle_to_buffer(handle);
+
+	down_write(&req->rw_sem);
+	offset = phys_to_offset(req->req_start);
+	rc = ocmem_rdm_transfer(id, list, offset, direction);
+	if (work_data->direction == TO_OCMEM)
+		event = (rc == 0) ? OCMEM_MAP_DONE : OCMEM_MAP_FAIL;
+	else
+		event = (rc == 0) ? OCMEM_UNMAP_DONE : OCMEM_UNMAP_FAIL;
+
+	up_write(&req->rw_sem);
+	kfree(work_data);
+	dispatch_notification(id, event, buffer);
+}
+
+int queue_transfer(struct ocmem_req *req, struct ocmem_handle *handle,
+			struct ocmem_map_list *list, int direction)
+{
+	struct ocmem_rdm_work *work_data = NULL;
+
+	down_write(&req->rw_sem);
+
+	work_data = kzalloc(sizeof(struct ocmem_rdm_work), GFP_ATOMIC);
+	if (!work_data)
+		BUG();
+
+	work_data->handle = handle;
+	work_data->list = list;
+	work_data->id = req->owner;
+	work_data->direction = direction;
+	INIT_WORK(&work_data->work, ocmem_rdm_worker);
+	up_write(&req->rw_sem);
+	queue_work(ocmem_rdm_wq, &work_data->work);
+	return 0;
+}
+
+int process_xfer_out(int id, struct ocmem_handle *handle,
+			struct ocmem_map_list *list)
+{
+	struct ocmem_req *req = NULL;
+	int rc = 0;
+
+	req = handle_to_req(handle);
+
+	if (!req)
+		return -EINVAL;
+
+	if (!is_mapped(req)) {
+		pr_err("Buffer is not already mapped\n");
+		goto transfer_out_error;
+	}
+
+	rc = process_unmap(req, req->req_start, req->req_end);
+	if (rc < 0) {
+		pr_err("Unmapping the buffer failed\n");
+		goto transfer_out_error;
+	}
+
+	rc = queue_transfer(req, handle, list, TO_DDR);
+
+	if (rc < 0) {
+		pr_err("Failed to queue rdm transfer to DDR\n");
+		goto transfer_out_error;
+	}
+
+	return 0;
+
+transfer_out_error:
+	return -EINVAL;
+}
+
+int process_xfer_in(int id, struct ocmem_handle *handle,
+			struct ocmem_map_list *list)
+{
+	struct ocmem_req *req = NULL;
+	int rc = 0;
+
+	req = handle_to_req(handle);
+
+	if (!req)
+		return -EINVAL;
+
+	if (is_mapped(req)) {
+		pr_err("Buffer is already mapped\n");
+		goto transfer_in_error;
+	}
+
+	rc = process_map(req, req->req_start, req->req_end);
+	if (rc < 0) {
+		pr_err("Mapping the buffer failed\n");
+		goto transfer_in_error;
+	}
+
+	rc = queue_transfer(req, handle, list, TO_OCMEM);
+
+	if (rc < 0) {
+		pr_err("Failed to queue rdm transfer to OCMEM\n");
+		goto transfer_in_error;
+	}
+
+	return 0;
+transfer_in_error:
+	return -EINVAL;
+}
+
+int process_shrink(int id, struct ocmem_handle *handle, unsigned long size)
+{
+	struct ocmem_req *req = NULL;
+	struct ocmem_buf *buffer = NULL;
+	struct ocmem_eviction_data *edata = NULL;
+	int rc = 0;
+
+	if (is_blocked(id)) {
+		pr_err("Client %d cannot request free\n", id);
+		return -EINVAL;
+	}
+
+	req = handle_to_req(handle);
+	buffer = handle_to_buffer(handle);
+
+	if (!req)
+		return -EINVAL;
+
+	if (req->req_start != core_address(id, buffer->addr)) {
+		pr_err("Invalid buffer handle passed for shrink\n");
+		return -EINVAL;
+	}
+
+	edata = req->edata;
+
+	if (is_tcm(req->owner))
+		do_unmap(req);
+
+	if (size == 0) {
+		pr_info("req %p being shrunk to zero\n", req);
+		rc = do_free(req);
+		if (rc < 0)
+			return -EINVAL;
+	} else {
+		rc = do_shrink(req, size);
+		if (rc < 0)
+			return -EINVAL;
+	}
+
+	edata->pending--;
+	if (edata->pending == 0) {
+		pr_debug("All regions evicted");
+		complete(&edata->completion);
+	}
+
+	return 0;
+}
+
+int process_xfer(int id, struct ocmem_handle *handle,
+		struct ocmem_map_list *list, int direction)
+{
+	int rc = 0;
+
+	if (is_tcm(id)) {
+		WARN(1, "Mapping operation is invalid for client\n");
+		return -EINVAL;
+	}
+
+	if (direction == TO_DDR)
+		rc = process_xfer_out(id, handle, list);
+	else if (direction == TO_OCMEM)
+		rc = process_xfer_in(id, handle, list);
+	return rc;
+}
+
+int ocmem_eviction_thread(struct work_struct *work)
+{
+	return 0;
+}
+
+int process_evict(int id)
+{
+	struct ocmem_eviction_data *edata = NULL;
+	int prio = ocmem_client_table[id].priority;
+	struct rb_node *rb_node = NULL;
+	struct ocmem_req *req = NULL;
+	struct ocmem_buf buffer;
+	int j = 0;
+
+	edata = kzalloc(sizeof(struct ocmem_eviction_data), GFP_ATOMIC);
+
+	INIT_LIST_HEAD(&edata->victim_list);
+	INIT_LIST_HEAD(&edata->req_list);
+	edata->prio = prio;
+	edata->pending = 0;
+	edata->passive = 1;
+	evictions[id] = edata;
+
+	mutex_lock(&sched_mutex);
+
+	for (rb_node = rb_first(&sched_tree); rb_node;
+				rb_node = rb_next(rb_node)) {
+		struct ocmem_region *tmp_region = NULL;
+		tmp_region = rb_entry(rb_node, struct ocmem_region, region_rb);
+		if (tmp_region->max_prio < prio) {
+			for (j = id - 1; j > NO_PRIO; j--) {
+				req = find_req_match(j, tmp_region);
+				if (req) {
+					pr_info("adding %p to eviction list\n",
+							tmp_region);
+					list_add_tail(
+						&tmp_region->eviction_list,
+						&edata->victim_list);
+					list_add_tail(
+						&req->eviction_list,
+						&edata->req_list);
+					edata->pending++;
+					req->edata = edata;
+					buffer.addr = req->req_start;
+					buffer.len = 0x0;
+					dispatch_notification(req->owner,
+						OCMEM_ALLOC_SHRINK, &buffer);
+				}
+			}
+		} else {
+			pr_info("skipping %p from eviction\n", tmp_region);
+		}
+	}
+	mutex_unlock(&sched_mutex);
+	pr_debug("Waiting for all regions to be shrunk\n");
+	if (edata->pending > 0) {
+		init_completion(&edata->completion);
+		wait_for_completion(&edata->completion);
+	}
+	return 0;
+}
+
 static int do_allocate(struct ocmem_req *req, bool can_block, bool can_wait)
 {
 	int rc = 0;
@@ -1113,6 +1504,31 @@
 	return -EINVAL;
 }
 
+int process_restore(int id)
+{
+	struct ocmem_req *req = NULL;
+	struct ocmem_req *next = NULL;
+	struct ocmem_eviction_data *edata = evictions[id];
+
+	if (!edata)
+		return 0;
+
+	list_for_each_entry_safe(req, next, &edata->req_list, eviction_list)
+	{
+		if (req) {
+			pr_debug("ocmem: Fetched evicted request %p\n",
+								req);
+			list_del(&req->sched_list);
+			req->op = SCHED_ALLOCATE;
+			sched_enqueue(req);
+		}
+	}
+	kfree(edata);
+	evictions[id] = NULL;
+	pr_debug("Restore all evicted regions\n");
+	ocmem_schedule_pending();
+	return 0;
+}
 
 int process_allocate(int id, struct ocmem_handle *handle,
 			unsigned long min, unsigned long max,
@@ -1185,6 +1601,7 @@
 
 	rc = do_allocate(req, true, false);
 
+
 	if (rc < 0)
 		goto do_allocate_error;
 
@@ -1251,5 +1668,13 @@
 	for (i = MIN_PRIO; i < MAX_OCMEM_PRIO; i++)
 		INIT_LIST_HEAD(&sched_queue[i]);
 
+	mutex_init(&rdm_mutex);
+	INIT_LIST_HEAD(&rdm_queue);
+	ocmem_rdm_wq = alloc_workqueue("ocmem_rdm_wq", 0, 0);
+	if (!ocmem_rdm_wq)
+		return -ENOMEM;
+	ocmem_eviction_wq = alloc_workqueue("ocmem_eviction_wq", 0, 0);
+	if (!ocmem_eviction_wq)
+		return -ENOMEM;
 	return 0;
 }
diff --git a/arch/arm/mach-msm/pm-8x60.c b/arch/arm/mach-msm/pm-8x60.c
index 42616c6..e203667 100644
--- a/arch/arm/mach-msm/pm-8x60.c
+++ b/arch/arm/mach-msm/pm-8x60.c
@@ -24,7 +24,6 @@
 #include <linux/smp.h>
 #include <linux/suspend.h>
 #include <linux/tick.h>
-#include <linux/delay.h>
 #include <mach/msm_iomap.h>
 #include <mach/socinfo.h>
 #include <mach/system.h>
@@ -799,28 +798,6 @@
 	return 0;
 }
 
-static struct msm_pm_sleep_status_data *msm_pm_slp_sts;
-
-static DEFINE_PER_CPU_SHARED_ALIGNED(enum msm_pm_sleep_mode,
-		msm_pm_last_slp_mode);
-
-bool msm_pm_verify_cpu_pc(unsigned int cpu)
-{
-	enum msm_pm_sleep_mode mode = per_cpu(msm_pm_last_slp_mode, cpu);
-
-	if (msm_pm_slp_sts) {
-		int acc_sts = __raw_readl(msm_pm_slp_sts->base_addr
-					+ cpu * msm_pm_slp_sts->cpu_offset);
-
-		if ((acc_sts & msm_pm_slp_sts->mask) &&
-			((mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE) ||
-			 (mode == MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE)))
-			return true;
-	}
-
-	return false;
-}
-
 void msm_pm_cpu_enter_lowpower(unsigned int cpu)
 {
 	int i;
@@ -836,54 +813,14 @@
 	if (MSM_PM_DEBUG_HOTPLUG & msm_pm_debug_mask)
 		pr_notice("CPU%u: %s: shutting down cpu\n", cpu, __func__);
 
-	if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE]) {
-		per_cpu(msm_pm_last_slp_mode, cpu)
-			= MSM_PM_SLEEP_MODE_POWER_COLLAPSE;
+	if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE])
 		msm_pm_power_collapse(false);
-	} else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE]) {
-		per_cpu(msm_pm_last_slp_mode, cpu)
-			= MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE;
+	else if (allow[MSM_PM_SLEEP_MODE_POWER_COLLAPSE_STANDALONE])
 		msm_pm_power_collapse_standalone(false);
-	} else if (allow[MSM_PM_SLEEP_MODE_RETENTION]) {
-		per_cpu(msm_pm_last_slp_mode, cpu)
-			= MSM_PM_SLEEP_MODE_RETENTION;
+	else if (allow[MSM_PM_SLEEP_MODE_RETENTION])
 		msm_pm_retention();
-	} else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT]) {
-		per_cpu(msm_pm_last_slp_mode, cpu)
-			= MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT;
+	else if (allow[MSM_PM_SLEEP_MODE_WAIT_FOR_INTERRUPT])
 		msm_pm_swfi();
-	} else
-		per_cpu(msm_pm_last_slp_mode, cpu) = MSM_PM_SLEEP_MODE_NR;
-}
-
-int msm_pm_wait_cpu_shutdown(unsigned int cpu)
-{
-
-	int timeout = 10;
-
-	if (!msm_pm_slp_sts)
-		return 0;
-
-	while (timeout--) {
-
-		/*
-		 * Check for the SPM of the core being hotplugged to set
-		 * its sleep state.The SPM sleep state indicates that the
-		 * core has been power collapsed.
-		 */
-
-		int acc_sts = __raw_readl(msm_pm_slp_sts->base_addr
-					+ cpu * msm_pm_slp_sts->cpu_offset);
-		mb();
-
-		if (acc_sts & msm_pm_slp_sts->mask)
-			return 0;
-
-		usleep(100);
-	}
-	pr_warn("%s(): Timed out waiting for CPU %u SPM to enter sleep state",
-			__func__, cpu);
-	return -EBUSY;
 }
 
 static int msm_pm_enter(suspend_state_t state)
@@ -980,12 +917,6 @@
 /******************************************************************************
  * Initialization routine
  *****************************************************************************/
-void __init msm_pm_init_sleep_status_data(
-		struct msm_pm_sleep_status_data *data)
-{
-	msm_pm_slp_sts = data;
-}
-
 void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops)
 {
 	if (ops)
diff --git a/arch/arm/mach-msm/pm.h b/arch/arm/mach-msm/pm.h
index 70d54da..c722ff6 100644
--- a/arch/arm/mach-msm/pm.h
+++ b/arch/arm/mach-msm/pm.h
@@ -70,12 +70,6 @@
 
 extern struct msm_pm_platform_data msm_pm_sleep_modes[];
 
-struct msm_pm_sleep_status_data {
-	void *base_addr;
-	uint32_t cpu_offset;
-	uint32_t mask;
-};
-
 struct msm_pm_sleep_ops {
 	void *(*lowest_limits)(bool from_idle,
 			enum msm_pm_sleep_mode sleep_mode, uint32_t latency_us,
@@ -93,19 +87,11 @@
 int msm_pm_idle_enter(enum msm_pm_sleep_mode sleep_mode);
 void msm_pm_cpu_enter_lowpower(unsigned int cpu);
 
-void __init msm_pm_init_sleep_status_data(
-		struct msm_pm_sleep_status_data *sleep_data);
-
-
 #ifdef CONFIG_MSM_PM8X60
 void msm_pm_set_rpm_wakeup_irq(unsigned int irq);
-int msm_pm_wait_cpu_shutdown(unsigned int cpu);
-bool msm_pm_verify_cpu_pc(unsigned int cpu);
 void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops);
 #else
 static inline void msm_pm_set_rpm_wakeup_irq(unsigned int irq) {}
-static inline int msm_pm_wait_cpu_shutdown(unsigned int cpu) { return 0; }
-static inline bool msm_pm_verify_cpu_pc(unsigned int cpu) { return true; }
 static inline void msm_pm_set_sleep_ops(struct msm_pm_sleep_ops *ops) {}
 #endif
 #ifdef CONFIG_HOTPLUG_CPU
diff --git a/arch/arm/mach-msm/qdsp6v2/apr.c b/arch/arm/mach-msm/qdsp6v2/apr.c
index 2403c02..a0bfb27 100644
--- a/arch/arm/mach-msm/qdsp6v2/apr.c
+++ b/arch/arm/mach-msm/qdsp6v2/apr.c
@@ -372,10 +372,14 @@
 	if (q6.state == APR_Q6_NOIMG) {
 		q6.pil = pil_get("q6");
 		if (IS_ERR(q6.pil)) {
-			rc = PTR_ERR(q6.pil);
-			pr_err("APR: Unable to load q6 image, error:%d\n", rc);
-			mutex_unlock(&q6.lock);
-			return svc;
+			q6.pil = pil_get("adsp");
+			if (IS_ERR(q6.pil)) {
+				rc = PTR_ERR(q6.pil);
+				pr_err("APR: Unable to load q6 image, error:%d\n",
+									 rc);
+				mutex_unlock(&q6.lock);
+				return svc;
+			}
 		}
 		q6.state = APR_Q6_LOADED;
 	}
diff --git a/arch/arm/mach-msm/rpm_log.c b/arch/arm/mach-msm/rpm_log.c
index 3ed55da..4835cef 100644
--- a/arch/arm/mach-msm/rpm_log.c
+++ b/arch/arm/mach-msm/rpm_log.c
@@ -115,13 +115,11 @@
 			continue;
 		}
 		/*
-		 * Ensure that the reported buffer size is within limits of
-		 * known maximum size and that all indices are 4 byte aligned.
-		 * These conditions are required to interact with a ULog buffer
+		 * Ensure that all indices are 4 byte aligned.
+		 * This conditions is required to interact with a ULog buffer
 		 * properly.
 		 */
-		if (tail_idx - head_idx > pdata->log_len ||
-		    !IS_ALIGNED((tail_idx | head_idx | *read_idx), 4))
+		if (!IS_ALIGNED((tail_idx | head_idx | *read_idx), 4))
 			break;
 
 		msg_len = msm_rpm_log_read(pdata, MSM_RPM_LOG_PAGE_BUFFER,
diff --git a/arch/arm/mach-msm/smd.c b/arch/arm/mach-msm/smd.c
index 54512ab..948dbbb 100644
--- a/arch/arm/mach-msm/smd.c
+++ b/arch/arm/mach-msm/smd.c
@@ -559,7 +559,11 @@
 	 * on DEM-based targets.  Grabbing a wakelock in this case will
 	 * abort the power-down sequencing.
 	 */
-	smsm_cb_snapshot(0);
+	if (smsm_info.intr_mask &&
+	    (__raw_readl(SMSM_INTR_MASK_ADDR(smsm_entry, SMSM_APPS))
+				& notify_mask)) {
+		smsm_cb_snapshot(0);
+	}
 }
 
 void smd_diag(void)
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 32f61f5..b6fb52a 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -32,6 +32,7 @@
 #include <asm/sizes.h>
 #include <asm/tlb.h>
 #include <asm/fixmap.h>
+#include <asm/cputype.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -40,6 +41,8 @@
 
 static unsigned long phys_initrd_start __initdata = 0;
 static unsigned long phys_initrd_size __initdata = 0;
+int msm_krait_need_wfe_fixup;
+EXPORT_SYMBOL(msm_krait_need_wfe_fixup);
 
 static int __init early_initrd(char *p)
 {
@@ -916,3 +919,17 @@
 
 __setup("keepinitrd", keepinitrd_setup);
 #endif
+
+#ifdef CONFIG_MSM_KRAIT_WFE_FIXUP
+static int __init msm_krait_wfe_init(void)
+{
+	unsigned int val, midr;
+	midr = read_cpuid_id() & 0xffffff00;
+	if ((midr == 0x511f0400) || (midr == 0x510f0600)) {
+		asm volatile("mrc p15, 7, %0, c15, c0, 5" : "=r" (val));
+		msm_krait_need_wfe_fixup = (val & 0x10000) ? 1 : 0;
+	}
+	return 0;
+}
+pure_initcall(msm_krait_wfe_init);
+#endif
diff --git a/drivers/input/misc/lis3dh_acc.c b/drivers/input/misc/lis3dh_acc.c
new file mode 100644
index 0000000..af96d3f
--- /dev/null
+++ b/drivers/input/misc/lis3dh_acc.c
@@ -0,0 +1,1589 @@
+/******************** (C) COPYRIGHT 2010 STMicroelectronics ********************
+ *
+ * File Name          : lis3dh_acc.c
+ * Authors            : MSH - Motion Mems BU - Application Team
+ *		      : Matteo Dameno (matteo.dameno@st.com)
+ *		      : Carmine Iascone (carmine.iascone@st.com)
+ *                    : Samuel Huo (samuel.huo@st.com)
+ * Version            : V.1.1.0
+ * Date               : 07/10/2012
+ * Description        : LIS3DH accelerometer sensor driver
+ *
+ *******************************************************************************
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+ * OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+ * PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+ * AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+ * INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+ * CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+ * INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+ *
+ * THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+ *
+ ******************************************************************************
+ Revision 1.0.0 05/11/09
+ First Release;
+ Revision 1.0.3 22/01/2010
+  Linux K&R Compliant Release;
+ Revision 1.0.5 16/08/2010
+  modified _get_acceleration_data function;
+  modified _update_odr function;
+  manages 2 interrupts;
+ Revision 1.0.6 15/11/2010
+  supports sysfs;
+  no more support for ioctl;
+ Revision 1.0.7 26/11/2010
+  checks for availability of interrupts pins
+  correction on FUZZ and FLAT values;
+ Revision 1.0.8 2010/Apr/01
+  corrects a bug in interrupt pin management in 1.0.7
+ Revision 1.0.9 07/25/2011
+  Romove several unused functions,add 5ms delay in init,change sysfs attributes.
+ Revision 1.1.0 07/10/2012
+  To replace some deprecated functions for 3.4 kernel;
+  To pass the checkpatch's formatting requirement;
+  To add regulator request;
+
+ ******************************************************************************/
+
+#include	<linux/err.h>
+#include	<linux/errno.h>
+#include	<linux/delay.h>
+#include	<linux/fs.h>
+#include	<linux/i2c.h>
+#include	<linux/input.h>
+#include	<linux/uaccess.h>
+#include	<linux/workqueue.h>
+#include	<linux/irq.h>
+#include	<linux/gpio.h>
+#include	<linux/interrupt.h>
+#include	<linux/slab.h>
+#include	<linux/pm.h>
+#include	<linux/input/lis3dh.h>
+#include	<linux/module.h>
+#include	<linux/regulator/consumer.h>
+
+
+#define	DEBUG	1
+
+#define	G_MAX		16000
+
+
+#define SENSITIVITY_2G		1	/**	mg/LSB	*/
+#define SENSITIVITY_4G		2	/**	mg/LSB	*/
+#define SENSITIVITY_8G		4	/**	mg/LSB	*/
+#define SENSITIVITY_16G		12	/**	mg/LSB	*/
+
+
+
+
+/* Accelerometer Sensor Operating Mode */
+#define LIS3DH_ACC_ENABLE	0x01
+#define LIS3DH_ACC_DISABLE	0x00
+
+#define	HIGH_RESOLUTION		0x08
+
+#define	AXISDATA_REG		0x28
+#define WHOAMI_LIS3DH_ACC	0x33	/*	Expected content for WAI */
+
+/*	CONTROL REGISTERS	*/
+#define WHO_AM_I		0x0F	/*	WhoAmI register		*/
+#define	TEMP_CFG_REG		0x1F	/*	temper sens control reg	*/
+/* ctrl 1: ODR3 ODR2 ODR ODR0 LPen Zenable Yenable Zenable */
+#define	CTRL_REG1		0x20	/*	control reg 1		*/
+#define	CTRL_REG2		0x21	/*	control reg 2		*/
+#define	CTRL_REG3		0x22	/*	control reg 3		*/
+#define	CTRL_REG4		0x23	/*	control reg 4		*/
+#define	CTRL_REG5		0x24	/*	control reg 5		*/
+#define	CTRL_REG6		0x25	/*	control reg 6		*/
+
+#define	FIFO_CTRL_REG		0x2E	/*	FiFo control reg	*/
+
+#define	INT_CFG1		0x30	/*	interrupt 1 config	*/
+#define	INT_SRC1		0x31	/*	interrupt 1 source	*/
+#define	INT_THS1		0x32	/*	interrupt 1 threshold	*/
+#define	INT_DUR1		0x33	/*	interrupt 1 duration	*/
+
+
+#define	TT_CFG			0x38	/*	tap config		*/
+#define	TT_SRC			0x39	/*	tap source		*/
+#define	TT_THS			0x3A	/*	tap threshold		*/
+#define	TT_LIM			0x3B	/*	tap time limit		*/
+#define	TT_TLAT			0x3C	/*	tap time latency	*/
+#define	TT_TW			0x3D	/*	tap time window		*/
+/*	end CONTROL REGISTRES	*/
+
+
+#define ENABLE_HIGH_RESOLUTION	1
+
+#define LIS3DH_ACC_PM_OFF		0x00
+#define LIS3DH_ACC_ENABLE_ALL_AXES	0x07
+
+
+#define PMODE_MASK			0x08
+#define ODR_MASK			0XF0
+
+#define ODR1		0x10  /* 1Hz output data rate */
+#define ODR10		0x20  /* 10Hz output data rate */
+#define ODR25		0x30  /* 25Hz output data rate */
+#define ODR50		0x40  /* 50Hz output data rate */
+#define ODR100		0x50  /* 100Hz output data rate */
+#define ODR200		0x60  /* 200Hz output data rate */
+#define ODR400		0x70  /* 400Hz output data rate */
+#define ODR1250		0x90  /* 1250Hz output data rate */
+
+
+
+#define	IA			0x40
+#define	ZH			0x20
+#define	ZL			0x10
+#define	YH			0x08
+#define	YL			0x04
+#define	XH			0x02
+#define	XL			0x01
+/* */
+/* CTRL REG BITS*/
+#define	CTRL_REG3_I1_AOI1	0x40
+#define	CTRL_REG6_I2_TAPEN	0x80
+#define	CTRL_REG6_HLACTIVE	0x02
+/* */
+#define NO_MASK			0xFF
+#define INT1_DURATION_MASK	0x7F
+#define	INT1_THRESHOLD_MASK	0x7F
+#define TAP_CFG_MASK		0x3F
+#define	TAP_THS_MASK		0x7F
+#define	TAP_TLIM_MASK		0x7F
+#define	TAP_TLAT_MASK		NO_MASK
+#define	TAP_TW_MASK		NO_MASK
+
+
+/* TAP_SOURCE_REG BIT */
+#define	DTAP			0x20
+#define	STAP			0x10
+#define	SIGNTAP			0x08
+#define	ZTAP			0x04
+#define	YTAP			0x02
+#define	XTAZ			0x01
+
+
+#define	FUZZ			0
+#define	FLAT			0
+#define	I2C_RETRY_DELAY		5
+#define	I2C_RETRIES		5
+#define	I2C_AUTO_INCREMENT	0x80
+
+/* RESUME STATE INDICES */
+#define	RES_CTRL_REG1		0
+#define	RES_CTRL_REG2		1
+#define	RES_CTRL_REG3		2
+#define	RES_CTRL_REG4		3
+#define	RES_CTRL_REG5		4
+#define	RES_CTRL_REG6		5
+
+#define	RES_INT_CFG1		6
+#define	RES_INT_THS1		7
+#define	RES_INT_DUR1		8
+
+#define	RES_TT_CFG		9
+#define	RES_TT_THS		10
+#define	RES_TT_LIM		11
+#define	RES_TT_TLAT		12
+#define	RES_TT_TW		13
+
+#define	RES_TEMP_CFG_REG	14
+#define	RES_REFERENCE_REG	15
+#define	RES_FIFO_CTRL_REG	16
+
+#define	RESUME_ENTRIES		17
+/* end RESUME STATE INDICES */
+
+
+struct {
+	unsigned int cutoff_ms;
+	unsigned int mask;
+} lis3dh_acc_odr_table[] = {
+		{    1, ODR1250 },
+		{    3, ODR400  },
+		{    5, ODR200  },
+		{   10, ODR100  },
+		{   20, ODR50   },
+		{   40, ODR25   },
+		{  100, ODR10   },
+		{ 1000, ODR1    },
+};
+
+struct lis3dh_acc_data {
+	struct i2c_client *client;
+	struct lis3dh_acc_platform_data *pdata;
+
+	struct mutex lock;
+	struct delayed_work input_work;
+
+	struct input_dev *input_dev;
+
+	int hw_initialized;
+	/* hw_working=-1 means not tested yet */
+	int hw_working;
+	atomic_t enabled;
+	int on_before_suspend;
+
+	u8 sensitivity;
+
+	u8 resume_state[RESUME_ENTRIES];
+
+	int irq1;
+	struct work_struct irq1_work;
+	struct workqueue_struct *irq1_work_queue;
+	int irq2;
+	struct work_struct irq2_work;
+	struct workqueue_struct *irq2_work_queue;
+
+#ifdef DEBUG
+	u8 reg_addr;
+#endif
+};
+
+struct sensor_regulator {
+	struct regulator *vreg;
+	const char *name;
+	u32	min_uV;
+	u32	max_uV;
+};
+
+struct sensor_regulator lis3dh_acc_vreg[] = {
+	{NULL, "vdd", 1700000, 3600000},
+	{NULL, "vddio", 1700000, 3600000},
+};
+
+static int lis3dh_acc_config_regulator(struct lis3dh_acc_data *acc, bool on)
+{
+	int rc = 0, i;
+	int num_reg = sizeof(lis3dh_acc_vreg) / sizeof(struct sensor_regulator);
+
+	if (on) {
+		for (i = 0; i < num_reg; i++) {
+			lis3dh_acc_vreg[i].vreg =
+				regulator_get(&acc->client->dev,
+				lis3dh_acc_vreg[i].name);
+			if (IS_ERR(lis3dh_acc_vreg[i].vreg)) {
+				rc = PTR_ERR(lis3dh_acc_vreg[i].vreg);
+				pr_err("%s:regulator get failed rc=%d\n",
+								__func__, rc);
+				goto error_vdd;
+			}
+
+			if (regulator_count_voltages(
+				lis3dh_acc_vreg[i].vreg) > 0) {
+				rc = regulator_set_voltage(
+					lis3dh_acc_vreg[i].vreg,
+					lis3dh_acc_vreg[i].min_uV,
+					lis3dh_acc_vreg[i].max_uV);
+				if (rc) {
+					pr_err("%s: set voltage failed rc=%d\n",
+					__func__, rc);
+					regulator_put(lis3dh_acc_vreg[i].vreg);
+					goto error_vdd;
+				}
+			}
+
+			rc = regulator_enable(lis3dh_acc_vreg[i].vreg);
+			if (rc) {
+				pr_err("%s: regulator_enable failed rc =%d\n",
+					__func__, rc);
+				if (regulator_count_voltages(
+					lis3dh_acc_vreg[i].vreg) > 0) {
+					regulator_set_voltage(
+						lis3dh_acc_vreg[i].vreg, 0,
+						lis3dh_acc_vreg[i].max_uV);
+				}
+				regulator_put(lis3dh_acc_vreg[i].vreg);
+				goto error_vdd;
+			}
+		}
+		return rc;
+	} else {
+		i = num_reg;
+	}
+
+error_vdd:
+	while (--i >= 0) {
+		if (regulator_count_voltages(lis3dh_acc_vreg[i].vreg) > 0) {
+			regulator_set_voltage(lis3dh_acc_vreg[i].vreg, 0,
+						lis3dh_acc_vreg[i].max_uV);
+		}
+		regulator_disable(lis3dh_acc_vreg[i].vreg);
+		regulator_put(lis3dh_acc_vreg[i].vreg);
+	}
+	return rc;
+}
+
+static int lis3dh_acc_i2c_read(struct lis3dh_acc_data *acc,
+				u8 *buf, int len)
+{
+	int err;
+	int tries = 0;
+
+	struct i2c_msg	msgs[] = {
+		{
+			.addr = acc->client->addr,
+			.flags = acc->client->flags & I2C_M_TEN,
+			.len = 1,
+			.buf = buf,
+		},
+		{
+			.addr = acc->client->addr,
+			.flags = (acc->client->flags & I2C_M_TEN) | I2C_M_RD,
+			.len = len,
+			.buf = buf,
+		},
+	};
+
+	do {
+		err = i2c_transfer(acc->client->adapter, msgs, 2);
+		if (err != 2)
+			msleep_interruptible(I2C_RETRY_DELAY);
+	} while ((err != 2) && (++tries < I2C_RETRIES));
+
+	if (err != 2) {
+		dev_err(&acc->client->dev, "read transfer error\n");
+		err = -EIO;
+	} else {
+		err = 0;
+	}
+
+	return err;
+}
+
+static int lis3dh_acc_i2c_write(struct lis3dh_acc_data *acc, u8 *buf, int len)
+{
+	int err;
+	int tries = 0;
+
+	struct i2c_msg msgs[] = {
+		{
+		 .addr = acc->client->addr,
+			.flags = acc->client->flags & I2C_M_TEN,
+		 .len = len + 1,
+		 .buf = buf,
+		 },
+	};
+
+	do {
+		err = i2c_transfer(acc->client->adapter, msgs, 1);
+		if (err != 1)
+			msleep_interruptible(I2C_RETRY_DELAY);
+	} while ((err != 1) && (++tries < I2C_RETRIES));
+
+	if (err != 1) {
+		dev_err(&acc->client->dev, "write transfer error\n");
+		err = -EIO;
+	} else {
+		err = 0;
+	}
+
+	return err;
+}
+
+static int lis3dh_acc_hw_init(struct lis3dh_acc_data *acc)
+{
+	int err = -1;
+	u8 buf[7];
+
+	printk(KERN_INFO "%s: hw init start\n", LIS3DH_ACC_DEV_NAME);
+
+	buf[0] = WHO_AM_I;
+	err = lis3dh_acc_i2c_read(acc, buf, 1);
+	if (err < 0) {
+		dev_warn(&acc->client->dev,
+		"Error reading WHO_AM_I: is device available/working?\n");
+		goto err_firstread;
+	} else
+		acc->hw_working = 1;
+	if (buf[0] != WHOAMI_LIS3DH_ACC) {
+		dev_err(&acc->client->dev,
+		"device unknown. Expected: 0x%x, Replies: 0x%x\n",
+		WHOAMI_LIS3DH_ACC, buf[0]);
+		err = -1; /* choose the right coded error */
+		goto err_unknown_device;
+	}
+
+	buf[0] = CTRL_REG1;
+	buf[1] = acc->resume_state[RES_CTRL_REG1];
+	err = lis3dh_acc_i2c_write(acc, buf, 1);
+	if (err < 0)
+		goto err_resume_state;
+
+	buf[0] = TEMP_CFG_REG;
+	buf[1] = acc->resume_state[RES_TEMP_CFG_REG];
+	err = lis3dh_acc_i2c_write(acc, buf, 1);
+	if (err < 0)
+		goto err_resume_state;
+
+	buf[0] = FIFO_CTRL_REG;
+	buf[1] = acc->resume_state[RES_FIFO_CTRL_REG];
+	err = lis3dh_acc_i2c_write(acc, buf, 1);
+	if (err < 0)
+		goto err_resume_state;
+
+	buf[0] = (I2C_AUTO_INCREMENT | TT_THS);
+	buf[1] = acc->resume_state[RES_TT_THS];
+	buf[2] = acc->resume_state[RES_TT_LIM];
+	buf[3] = acc->resume_state[RES_TT_TLAT];
+	buf[4] = acc->resume_state[RES_TT_TW];
+	err = lis3dh_acc_i2c_write(acc, buf, 4);
+	if (err < 0)
+		goto err_resume_state;
+	buf[0] = TT_CFG;
+	buf[1] = acc->resume_state[RES_TT_CFG];
+	err = lis3dh_acc_i2c_write(acc, buf, 1);
+	if (err < 0)
+		goto err_resume_state;
+
+	buf[0] = (I2C_AUTO_INCREMENT | INT_THS1);
+	buf[1] = acc->resume_state[RES_INT_THS1];
+	buf[2] = acc->resume_state[RES_INT_DUR1];
+	err = lis3dh_acc_i2c_write(acc, buf, 2);
+	if (err < 0)
+		goto err_resume_state;
+	buf[0] = INT_CFG1;
+	buf[1] = acc->resume_state[RES_INT_CFG1];
+	err = lis3dh_acc_i2c_write(acc, buf, 1);
+	if (err < 0)
+		goto err_resume_state;
+
+
+	buf[0] = (I2C_AUTO_INCREMENT | CTRL_REG2);
+	buf[1] = acc->resume_state[RES_CTRL_REG2];
+	buf[2] = acc->resume_state[RES_CTRL_REG3];
+	buf[3] = acc->resume_state[RES_CTRL_REG4];
+	buf[4] = acc->resume_state[RES_CTRL_REG5];
+	buf[5] = acc->resume_state[RES_CTRL_REG6];
+	err = lis3dh_acc_i2c_write(acc, buf, 5);
+	if (err < 0)
+		goto err_resume_state;
+
+	acc->hw_initialized = 1;
+	printk(KERN_INFO "%s: hw init done\n", LIS3DH_ACC_DEV_NAME);
+	return 0;
+
+err_firstread:
+	acc->hw_working = 0;
+err_unknown_device:
+err_resume_state:
+	acc->hw_initialized = 0;
+	dev_err(&acc->client->dev, "hw init error 0x%x,0x%x: %d\n", buf[0],
+			buf[1], err);
+	return err;
+}
+
+static void lis3dh_acc_device_power_off(struct lis3dh_acc_data *acc)
+{
+	int err;
+	u8 buf[2] = { CTRL_REG1, LIS3DH_ACC_PM_OFF };
+
+	err = lis3dh_acc_i2c_write(acc, buf, 1);
+	if (err < 0)
+		dev_err(&acc->client->dev, "soft power off failed: %d\n", err);
+
+	if (acc->pdata->gpio_int1)
+		disable_irq_nosync(acc->irq1);
+	if (acc->pdata->gpio_int2)
+		disable_irq_nosync(acc->irq2);
+
+	lis3dh_acc_config_regulator(acc, false);
+
+	if (acc->hw_initialized) {
+		if (acc->pdata->gpio_int1)
+			disable_irq_nosync(acc->irq1);
+		if (acc->pdata->gpio_int2)
+			disable_irq_nosync(acc->irq2);
+		acc->hw_initialized = 0;
+	}
+}
+
+static int lis3dh_acc_device_power_on(struct lis3dh_acc_data *acc)
+{
+	int err = -1;
+
+	err = lis3dh_acc_config_regulator(acc, true);
+	if (err < 0) {
+		dev_err(&acc->client->dev,
+				"power_on failed: %d\n", err);
+		return err;
+	}
+
+	if (acc->pdata->gpio_int1 >= 0)
+		enable_irq(acc->irq1);
+	if (acc->pdata->gpio_int2 >= 0)
+		enable_irq(acc->irq2);
+
+	msleep(20);
+
+	if (!acc->hw_initialized) {
+		err = lis3dh_acc_hw_init(acc);
+		if (acc->hw_working == 1 && err < 0) {
+			lis3dh_acc_device_power_off(acc);
+			return err;
+		}
+	}
+
+	if (acc->hw_initialized) {
+		if (acc->pdata->gpio_int1 >= 0)
+			enable_irq(acc->irq1);
+		if (acc->pdata->gpio_int2 >= 0)
+			enable_irq(acc->irq2);
+	}
+	return 0;
+}
+
+static irqreturn_t lis3dh_acc_isr1(int irq, void *dev)
+{
+	struct lis3dh_acc_data *acc = dev;
+
+	disable_irq_nosync(irq);
+	queue_work(acc->irq1_work_queue, &acc->irq1_work);
+#ifdef DEBUG
+	printk(KERN_INFO "%s: isr1 queued\n", LIS3DH_ACC_DEV_NAME);
+#endif
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t lis3dh_acc_isr2(int irq, void *dev)
+{
+	struct lis3dh_acc_data *acc = dev;
+
+	disable_irq_nosync(irq);
+	queue_work(acc->irq2_work_queue, &acc->irq2_work);
+#ifdef DEBUG
+	printk(KERN_INFO "%s: isr2 queued\n", LIS3DH_ACC_DEV_NAME);
+#endif
+	return IRQ_HANDLED;
+}
+
+static void lis3dh_acc_irq1_work_func(struct work_struct *work)
+{
+
+	struct lis3dh_acc_data *acc =
+	container_of(work, struct lis3dh_acc_data, irq1_work);
+	/* TODO  add interrupt service procedure.
+		 ie:lis3dh_acc_get_int1_source(acc); */
+	;
+	/*  */
+	printk(KERN_INFO "%s: IRQ1 triggered\n", LIS3DH_ACC_DEV_NAME);
+	goto exit;
+exit:
+	enable_irq(acc->irq1);
+}
+
+static void lis3dh_acc_irq2_work_func(struct work_struct *work)
+{
+
+	struct lis3dh_acc_data *acc =
+	container_of(work, struct lis3dh_acc_data, irq2_work);
+	/* TODO  add interrupt service procedure.
+		 ie:lis3dh_acc_get_tap_source(acc); */
+	;
+	/*  */
+	printk(KERN_INFO "%s: IRQ2 triggered\n", LIS3DH_ACC_DEV_NAME);
+	goto exit;
+exit:
+	enable_irq(acc->irq2);
+}
+
+int lis3dh_acc_update_g_range(struct lis3dh_acc_data *acc, u8 new_g_range)
+{
+	int err = -1;
+
+	u8 sensitivity;
+	u8 buf[2];
+	u8 updated_val;
+	u8 init_val;
+	u8 new_val;
+	u8 mask = LIS3DH_ACC_FS_MASK | HIGH_RESOLUTION;
+
+	switch (new_g_range) {
+	case LIS3DH_ACC_G_2G:
+
+		sensitivity = SENSITIVITY_2G;
+		break;
+	case LIS3DH_ACC_G_4G:
+
+		sensitivity = SENSITIVITY_4G;
+		break;
+	case LIS3DH_ACC_G_8G:
+
+		sensitivity = SENSITIVITY_8G;
+		break;
+	case LIS3DH_ACC_G_16G:
+
+		sensitivity = SENSITIVITY_16G;
+		break;
+	default:
+		dev_err(&acc->client->dev, "invalid g range requested: %u\n",
+				new_g_range);
+		return -EINVAL;
+	}
+
+	if (atomic_read(&acc->enabled)) {
+		/* Updates configuration register 4,
+		* which contains g range setting */
+		buf[0] = CTRL_REG4;
+		err = lis3dh_acc_i2c_read(acc, buf, 1);
+		if (err < 0)
+			goto error;
+		init_val = buf[0];
+		acc->resume_state[RES_CTRL_REG4] = init_val;
+		new_val = new_g_range | HIGH_RESOLUTION;
+		updated_val = ((mask & new_val) | ((~mask) & init_val));
+		buf[1] = updated_val;
+		buf[0] = CTRL_REG4;
+		err = lis3dh_acc_i2c_write(acc, buf, 1);
+		if (err < 0)
+			goto error;
+		acc->resume_state[RES_CTRL_REG4] = updated_val;
+		acc->sensitivity = sensitivity;
+	}
+
+
+	return err;
+error:
+	dev_err(&acc->client->dev, "update g range failed 0x%x,0x%x: %d\n",
+			buf[0], buf[1], err);
+
+	return err;
+}
+
+int lis3dh_acc_update_odr(struct lis3dh_acc_data *acc, int poll_interval_ms)
+{
+	int err = -1;
+	int i;
+	u8 config[2];
+
+	/* Following, looks for the longest possible odr interval scrolling the
+	 * odr_table vector from the end (shortest interval) backward (longest
+	 * interval), to support the poll_interval requested by the system.
+	 * It must be the longest interval lower then the poll interval.*/
+	for (i = ARRAY_SIZE(lis3dh_acc_odr_table) - 1; i >= 0; i--) {
+		if (lis3dh_acc_odr_table[i].cutoff_ms <= poll_interval_ms)
+			break;
+	}
+	config[1] = lis3dh_acc_odr_table[i].mask;
+
+	config[1] |= LIS3DH_ACC_ENABLE_ALL_AXES;
+
+	/* If device is currently enabled, we need to write new
+	 *  configuration out to it */
+	if (atomic_read(&acc->enabled)) {
+		config[0] = CTRL_REG1;
+		err = lis3dh_acc_i2c_write(acc, config, 1);
+		if (err < 0)
+			goto error;
+		acc->resume_state[RES_CTRL_REG1] = config[1];
+	}
+
+	return err;
+
+error:
+	dev_err(&acc->client->dev, "update odr failed 0x%x,0x%x: %d\n",
+			config[0], config[1], err);
+
+	return err;
+}
+
+
+
+static int lis3dh_acc_register_write(struct lis3dh_acc_data *acc, u8 *buf,
+		u8 reg_address, u8 new_value)
+{
+	int err = -1;
+
+	/* Sets configuration register at reg_address
+	 *  NOTE: this is a straight overwrite  */
+		buf[0] = reg_address;
+		buf[1] = new_value;
+		err = lis3dh_acc_i2c_write(acc, buf, 1);
+		if (err < 0)
+			return err;
+	return err;
+}
+
+static int lis3dh_acc_get_acceleration_data(struct lis3dh_acc_data *acc,
+		int *xyz)
+{
+	int err = -1;
+	/* Data bytes from hardware xL, xH, yL, yH, zL, zH */
+	u8 acc_data[6];
+	/* x,y,z hardware data */
+	s16 hw_d[3] = { 0 };
+
+	acc_data[0] = (I2C_AUTO_INCREMENT | AXISDATA_REG);
+	err = lis3dh_acc_i2c_read(acc, acc_data, 6);
+	if (err < 0)
+		return err;
+
+	hw_d[0] = (((s16) ((acc_data[1] << 8) | acc_data[0])) >> 4);
+	hw_d[1] = (((s16) ((acc_data[3] << 8) | acc_data[2])) >> 4);
+	hw_d[2] = (((s16) ((acc_data[5] << 8) | acc_data[4])) >> 4);
+
+	hw_d[0] = hw_d[0] * acc->sensitivity;
+	hw_d[1] = hw_d[1] * acc->sensitivity;
+	hw_d[2] = hw_d[2] * acc->sensitivity;
+
+
+	xyz[0] = ((acc->pdata->negate_x) ? (-hw_d[acc->pdata->axis_map_x])
+		   : (hw_d[acc->pdata->axis_map_x]));
+	xyz[1] = ((acc->pdata->negate_y) ? (-hw_d[acc->pdata->axis_map_y])
+		   : (hw_d[acc->pdata->axis_map_y]));
+	xyz[2] = ((acc->pdata->negate_z) ? (-hw_d[acc->pdata->axis_map_z])
+		   : (hw_d[acc->pdata->axis_map_z]));
+
+	#ifdef DEBUG
+	/*
+		printk(KERN_INFO "%s read x=%d, y=%d, z=%d\n",
+			LIS3DH_ACC_DEV_NAME, xyz[0], xyz[1], xyz[2]);
+	*/
+	#endif
+	return err;
+}
+
+static void lis3dh_acc_report_values(struct lis3dh_acc_data *acc,
+					int *xyz)
+{
+	input_report_abs(acc->input_dev, ABS_X, xyz[0]);
+	input_report_abs(acc->input_dev, ABS_Y, xyz[1]);
+	input_report_abs(acc->input_dev, ABS_Z, xyz[2]);
+	input_sync(acc->input_dev);
+}
+
+static int lis3dh_acc_enable(struct lis3dh_acc_data *acc)
+{
+	int err;
+
+	if (!atomic_cmpxchg(&acc->enabled, 0, 1)) {
+		err = lis3dh_acc_device_power_on(acc);
+		if (err < 0) {
+			atomic_set(&acc->enabled, 0);
+			return err;
+		}
+		schedule_delayed_work(&acc->input_work,
+			msecs_to_jiffies(acc->pdata->poll_interval));
+	}
+
+	return 0;
+}
+
+static int lis3dh_acc_disable(struct lis3dh_acc_data *acc)
+{
+	if (atomic_cmpxchg(&acc->enabled, 1, 0)) {
+		cancel_delayed_work_sync(&acc->input_work);
+		lis3dh_acc_device_power_off(acc);
+	}
+
+	return 0;
+}
+
+
+static ssize_t read_single_reg(struct device *dev, char *buf, u8 reg)
+{
+	ssize_t ret;
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	int err;
+
+	u8 data = reg;
+	err = lis3dh_acc_i2c_read(acc, &data, 1);
+	if (err < 0)
+		return err;
+	ret = snprintf(buf, 4, "0x%02x\n", data);
+	return ret;
+
+}
+
+static int write_reg(struct device *dev, const char *buf, u8 reg,
+		u8 mask, int resumeIndex)
+{
+	int err = -1;
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	u8 x[2];
+	u8 new_val;
+	unsigned long val;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+
+	new_val = ((u8) val & mask);
+	x[0] = reg;
+	x[1] = new_val;
+	err = lis3dh_acc_register_write(acc, x, reg, new_val);
+	if (err < 0)
+		return err;
+	acc->resume_state[resumeIndex] = new_val;
+	return err;
+}
+
+static ssize_t attr_get_polling_rate(struct device *dev,
+				     struct device_attribute *attr,
+				     char *buf)
+{
+	int val;
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	mutex_lock(&acc->lock);
+	val = acc->pdata->poll_interval;
+	mutex_unlock(&acc->lock);
+	return snprintf(buf, 8, "%d\n", val);
+}
+
+static ssize_t attr_set_polling_rate(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t size)
+{
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	unsigned long interval_ms;
+
+	if (kstrtoul(buf, 10, &interval_ms))
+		return -EINVAL;
+	if (!interval_ms)
+		return -EINVAL;
+	mutex_lock(&acc->lock);
+	acc->pdata->poll_interval = interval_ms;
+	lis3dh_acc_update_odr(acc, interval_ms);
+	mutex_unlock(&acc->lock);
+	return size;
+}
+
+static ssize_t attr_get_range(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	char val;
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	char range = 2;
+	mutex_lock(&acc->lock);
+	val = acc->pdata->g_range ;
+	switch (val) {
+	case LIS3DH_ACC_G_2G:
+		range = 2;
+		break;
+	case LIS3DH_ACC_G_4G:
+		range = 4;
+		break;
+	case LIS3DH_ACC_G_8G:
+		range = 8;
+		break;
+	case LIS3DH_ACC_G_16G:
+		range = 16;
+		break;
+	}
+	mutex_unlock(&acc->lock);
+	return snprintf(buf, 4, "%d\n", range);
+}
+
+static ssize_t attr_set_range(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t size)
+{
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	unsigned long val;
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+	mutex_lock(&acc->lock);
+	acc->pdata->g_range = val;
+	lis3dh_acc_update_g_range(acc, val);
+	mutex_unlock(&acc->lock);
+	return size;
+}
+
+static ssize_t attr_get_enable(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	int val = atomic_read(&acc->enabled);
+	return snprintf(buf, sizeof(val) + 2, "%d\n", val);
+}
+
+static ssize_t attr_set_enable(struct device *dev,
+			       struct device_attribute *attr,
+			       const char *buf, size_t size)
+{
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	unsigned long val;
+
+	if (kstrtoul(buf, 10, &val))
+		return -EINVAL;
+
+	if (val)
+		lis3dh_acc_enable(acc);
+	else
+		lis3dh_acc_disable(acc);
+
+	return size;
+}
+
+static ssize_t attr_set_intconfig1(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, INT_CFG1, NO_MASK, RES_INT_CFG1);
+}
+
+static ssize_t attr_get_intconfig1(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, INT_CFG1);
+}
+
+static ssize_t attr_set_duration1(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, INT_DUR1, INT1_DURATION_MASK, RES_INT_DUR1);
+}
+
+static ssize_t attr_get_duration1(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, INT_DUR1);
+}
+
+static ssize_t attr_set_thresh1(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, INT_THS1, INT1_THRESHOLD_MASK, RES_INT_THS1);
+}
+
+static ssize_t attr_get_thresh1(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, INT_THS1);
+}
+
+static ssize_t attr_get_source1(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	return read_single_reg(dev, buf, INT_SRC1);
+}
+
+static ssize_t attr_set_click_cfg(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, TT_CFG, TAP_CFG_MASK, RES_TT_CFG);
+}
+
+static ssize_t attr_get_click_cfg(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+
+	return read_single_reg(dev, buf, TT_CFG);
+}
+
+static ssize_t attr_get_click_source(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, TT_SRC);
+}
+
+static ssize_t attr_set_click_ths(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, TT_THS, TAP_THS_MASK, RES_TT_THS);
+}
+
+static ssize_t attr_get_click_ths(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, TT_THS);
+}
+
+static ssize_t attr_set_click_tlim(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, TT_LIM, TAP_TLIM_MASK, RES_TT_LIM);
+}
+
+static ssize_t attr_get_click_tlim(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, TT_LIM);
+}
+
+static ssize_t attr_set_click_tlat(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, TT_TLAT, TAP_TLAT_MASK, RES_TT_TLAT);
+}
+
+static ssize_t attr_get_click_tlat(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, TT_TLAT);
+}
+
+static ssize_t attr_set_click_tw(struct device *dev,
+		struct device_attribute *attr,	const char *buf, size_t size)
+{
+	return write_reg(dev, buf, TT_TLAT, TAP_TW_MASK, RES_TT_TLAT);
+}
+
+static ssize_t attr_get_click_tw(struct device *dev,
+		struct device_attribute *attr,	char *buf)
+{
+	return read_single_reg(dev, buf, TT_TLAT);
+}
+
+
+#ifdef DEBUG
+/* PAY ATTENTION: These DEBUG funtions don't manage resume_state */
+static ssize_t attr_reg_set(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	int rc;
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	u8 x[2];
+	unsigned long val;
+
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	mutex_lock(&acc->lock);
+	x[0] = acc->reg_addr;
+	mutex_unlock(&acc->lock);
+	x[1] = val;
+	rc = lis3dh_acc_i2c_write(acc, x, 1);
+	/*TODO: error need to be managed */
+	return size;
+}
+
+static ssize_t attr_reg_get(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	ssize_t ret;
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	int rc;
+	u8 data;
+
+	mutex_lock(&acc->lock);
+	data = acc->reg_addr;
+	mutex_unlock(&acc->lock);
+	rc = lis3dh_acc_i2c_read(acc, &data, 1);
+	/* TODO: error need to be managed */
+	ret = snprintf(buf, 8, "0x%02x\n", data);
+	return ret;
+}
+
+static ssize_t attr_addr_set(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t size)
+{
+	struct lis3dh_acc_data *acc = dev_get_drvdata(dev);
+	unsigned long val;
+	if (kstrtoul(buf, 16, &val))
+		return -EINVAL;
+	mutex_lock(&acc->lock);
+	acc->reg_addr = val;
+	mutex_unlock(&acc->lock);
+	return size;
+}
+#endif
+
+static struct device_attribute attributes[] = {
+
+	__ATTR(pollrate_ms, 0666, attr_get_polling_rate,
+			attr_set_polling_rate),
+	__ATTR(range, 0666, attr_get_range, attr_set_range),
+	__ATTR(enable, 0666, attr_get_enable, attr_set_enable),
+	__ATTR(int1_config, 0666, attr_get_intconfig1, attr_set_intconfig1),
+	__ATTR(int1_duration, 0666, attr_get_duration1, attr_set_duration1),
+	__ATTR(int1_threshold, 0666, attr_get_thresh1, attr_set_thresh1),
+	__ATTR(int1_source, 0444, attr_get_source1, NULL),
+	__ATTR(click_config, 0666, attr_get_click_cfg, attr_set_click_cfg),
+	__ATTR(click_source, 0444, attr_get_click_source, NULL),
+	__ATTR(click_threshold, 0666, attr_get_click_ths, attr_set_click_ths),
+	__ATTR(click_timelimit, 0666, attr_get_click_tlim,
+			attr_set_click_tlim),
+	__ATTR(click_timelatency, 0666, attr_get_click_tlat,
+							attr_set_click_tlat),
+	__ATTR(click_timewindow, 0666, attr_get_click_tw, attr_set_click_tw),
+
+#ifdef DEBUG
+	__ATTR(reg_value, 0666, attr_reg_get, attr_reg_set),
+	__ATTR(reg_addr, 0222, NULL, attr_addr_set),
+#endif
+};
+
+static int create_sysfs_interfaces(struct device *dev)
+{
+	int i;
+	int err;
+	for (i = 0; i < ARRAY_SIZE(attributes); i++) {
+		err = device_create_file(dev, attributes + i);
+		if (err)
+			goto error;
+	}
+	return 0;
+
+error:
+	for ( ; i >= 0; i--)
+		device_remove_file(dev, attributes + i);
+	dev_err(dev, "%s:Unable to create interface\n", __func__);
+	return err;
+}
+
+static int remove_sysfs_interfaces(struct device *dev)
+{
+	int i;
+	for (i = 0; i < ARRAY_SIZE(attributes); i++)
+		device_remove_file(dev, attributes + i);
+	return 0;
+}
+
+static void lis3dh_acc_input_work_func(struct work_struct *work)
+{
+	struct lis3dh_acc_data *acc;
+
+	int xyz[3] = { 0 };
+	int err;
+
+	acc = container_of((struct delayed_work *)work,
+			struct lis3dh_acc_data,	input_work);
+
+	mutex_lock(&acc->lock);
+	err = lis3dh_acc_get_acceleration_data(acc, xyz);
+	if (err < 0)
+		dev_err(&acc->client->dev, "get_acceleration_data failed\n");
+	else
+		lis3dh_acc_report_values(acc, xyz);
+
+	schedule_delayed_work(&acc->input_work, msecs_to_jiffies(
+			acc->pdata->poll_interval));
+	mutex_unlock(&acc->lock);
+}
+
+int lis3dh_acc_input_open(struct input_dev *input)
+{
+	struct lis3dh_acc_data *acc = input_get_drvdata(input);
+
+	return lis3dh_acc_enable(acc);
+}
+
+void lis3dh_acc_input_close(struct input_dev *dev)
+{
+	struct lis3dh_acc_data *acc = input_get_drvdata(dev);
+
+	lis3dh_acc_disable(acc);
+}
+
+static int lis3dh_acc_validate_pdata(struct lis3dh_acc_data *acc)
+{
+	acc->pdata->poll_interval = max(acc->pdata->poll_interval,
+			acc->pdata->min_interval);
+
+	if (acc->pdata->axis_map_x > 2 ||
+		acc->pdata->axis_map_y > 2 ||
+		 acc->pdata->axis_map_z > 2) {
+		dev_err(&acc->client->dev,
+			"invalid axis_map value x:%u y:%u z%u\n",
+			acc->pdata->axis_map_x,
+			acc->pdata->axis_map_y, acc->pdata->axis_map_z);
+		return -EINVAL;
+	}
+
+	/* Only allow 0 and 1 for negation boolean flag */
+	if (acc->pdata->negate_x > 1 || acc->pdata->negate_y > 1
+			|| acc->pdata->negate_z > 1) {
+		dev_err(&acc->client->dev,
+			"invalid negate value x:%u y:%u z:%u\n",
+			acc->pdata->negate_x,
+			acc->pdata->negate_y, acc->pdata->negate_z);
+		return -EINVAL;
+	}
+
+	/* Enforce minimum polling interval */
+	if (acc->pdata->poll_interval < acc->pdata->min_interval) {
+		dev_err(&acc->client->dev, "minimum poll interval violated\n");
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int lis3dh_acc_input_init(struct lis3dh_acc_data *acc)
+{
+	int err;
+
+	INIT_DELAYED_WORK(&acc->input_work, lis3dh_acc_input_work_func);
+	acc->input_dev = input_allocate_device();
+	if (!acc->input_dev) {
+		err = -ENOMEM;
+		dev_err(&acc->client->dev, "input device allocation failed\n");
+		goto err0;
+	}
+
+	acc->input_dev->open = lis3dh_acc_input_open;
+	acc->input_dev->close = lis3dh_acc_input_close;
+	acc->input_dev->name = LIS3DH_ACC_DEV_NAME;
+	acc->input_dev->id.bustype = BUS_I2C;
+	acc->input_dev->dev.parent = &acc->client->dev;
+
+	input_set_drvdata(acc->input_dev, acc);
+
+	set_bit(EV_ABS, acc->input_dev->evbit);
+	/*	next is used for interruptA sources data if the case */
+	set_bit(ABS_MISC, acc->input_dev->absbit);
+	/*	next is used for interruptB sources data if the case */
+	set_bit(ABS_WHEEL, acc->input_dev->absbit);
+
+	input_set_abs_params(acc->input_dev, ABS_X, -G_MAX, G_MAX, FUZZ, FLAT);
+	input_set_abs_params(acc->input_dev, ABS_Y, -G_MAX, G_MAX, FUZZ, FLAT);
+	input_set_abs_params(acc->input_dev, ABS_Z, -G_MAX, G_MAX, FUZZ, FLAT);
+	/*	next is used for interruptA sources data if the case */
+	input_set_abs_params(acc->input_dev, ABS_MISC, INT_MIN, INT_MAX, 0, 0);
+	/*	next is used for interruptB sources data if the case */
+	input_set_abs_params(acc->input_dev, ABS_WHEEL, INT_MIN, INT_MAX, 0, 0);
+
+
+	err = input_register_device(acc->input_dev);
+	if (err) {
+		dev_err(&acc->client->dev,
+				"unable to register input device %s\n",
+				acc->input_dev->name);
+		goto err1;
+	}
+
+	return 0;
+
+err1:
+	input_free_device(acc->input_dev);
+err0:
+	return err;
+}
+
+static void lis3dh_acc_input_cleanup(struct lis3dh_acc_data *acc)
+{
+	input_unregister_device(acc->input_dev);
+	input_free_device(acc->input_dev);
+}
+
+static int lis3dh_acc_probe(struct i2c_client *client,
+		const struct i2c_device_id *id)
+{
+
+	struct lis3dh_acc_data *acc;
+
+	int err = -1;
+
+	pr_info("%s: probe start.\n", LIS3DH_ACC_DEV_NAME);
+
+	if (client->dev.platform_data == NULL) {
+		dev_err(&client->dev, "platform data is NULL. exiting.\n");
+		err = -ENODEV;
+		goto exit_check_functionality_failed;
+	}
+
+	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+		dev_err(&client->dev, "client not i2c capable\n");
+		err = -ENODEV;
+		goto exit_check_functionality_failed;
+	}
+
+	/*
+	if (!i2c_check_functionality(client->adapter,
+					I2C_FUNC_SMBUS_BYTE |
+					I2C_FUNC_SMBUS_BYTE_DATA |
+					I2C_FUNC_SMBUS_WORD_DATA)) {
+		dev_err(&client->dev, "client not smb-i2c capable:2\n");
+		err = -EIO;
+		goto exit_check_functionality_failed;
+	}
+
+
+	if (!i2c_check_functionality(client->adapter,
+						I2C_FUNC_SMBUS_I2C_BLOCK)) {
+		dev_err(&client->dev, "client not smb-i2c capable:3\n");
+		err = -EIO;
+		goto exit_check_functionality_failed;
+	}
+	*/
+
+	acc = kzalloc(sizeof(struct lis3dh_acc_data), GFP_KERNEL);
+	if (acc == NULL) {
+		err = -ENOMEM;
+		dev_err(&client->dev,
+				"failed to allocate memory for module data: "
+					"%d\n", err);
+		goto exit_check_functionality_failed;
+	}
+
+
+	mutex_init(&acc->lock);
+	mutex_lock(&acc->lock);
+
+	acc->client = client;
+	i2c_set_clientdata(client, acc);
+
+	acc->pdata = kmalloc(sizeof(*acc->pdata), GFP_KERNEL);
+	if (acc->pdata == NULL) {
+		err = -ENOMEM;
+		dev_err(&client->dev,
+				"failed to allocate memory for pdata: %d\n",
+				err);
+		goto err_mutexunlock;
+	}
+
+	memcpy(acc->pdata, client->dev.platform_data, sizeof(*acc->pdata));
+
+	err = lis3dh_acc_validate_pdata(acc);
+	if (err < 0) {
+		dev_err(&client->dev, "failed to validate platform data\n");
+		goto exit_kfree_pdata;
+	}
+
+
+	if (acc->pdata->init) {
+		err = acc->pdata->init();
+		if (err < 0) {
+			dev_err(&client->dev, "init failed: %d\n", err);
+			goto err_pdata_init;
+		}
+	}
+
+	if (acc->pdata->gpio_int1 >= 0) {
+		acc->irq1 = gpio_to_irq(acc->pdata->gpio_int1);
+		printk(KERN_INFO "%s: %s has set irq1 to irq: %d\n",
+			LIS3DH_ACC_DEV_NAME, __func__, acc->irq1);
+		printk(KERN_INFO "%s: %s has mapped irq1 on gpio: %d\n",
+			LIS3DH_ACC_DEV_NAME, __func__,
+			acc->pdata->gpio_int1);
+	}
+
+	if (acc->pdata->gpio_int2 >= 0) {
+		acc->irq2 = gpio_to_irq(acc->pdata->gpio_int2);
+		printk(KERN_INFO "%s: %s has set irq2 to irq: %d\n",
+			LIS3DH_ACC_DEV_NAME, __func__, acc->irq2);
+		printk(KERN_INFO "%s: %s has mapped irq2 on gpio: %d\n",
+			LIS3DH_ACC_DEV_NAME, __func__,
+			acc->pdata->gpio_int2);
+	}
+
+	memset(acc->resume_state, 0, ARRAY_SIZE(acc->resume_state));
+
+	acc->resume_state[RES_CTRL_REG1] = LIS3DH_ACC_ENABLE_ALL_AXES;
+	acc->resume_state[RES_CTRL_REG2] = 0x00;
+	acc->resume_state[RES_CTRL_REG3] = 0x00;
+	acc->resume_state[RES_CTRL_REG4] = 0x00;
+	acc->resume_state[RES_CTRL_REG5] = 0x00;
+	acc->resume_state[RES_CTRL_REG6] = 0x00;
+
+	acc->resume_state[RES_TEMP_CFG_REG] = 0x00;
+	acc->resume_state[RES_FIFO_CTRL_REG] = 0x00;
+	acc->resume_state[RES_INT_CFG1] = 0x00;
+	acc->resume_state[RES_INT_THS1] = 0x00;
+	acc->resume_state[RES_INT_DUR1] = 0x00;
+
+	acc->resume_state[RES_TT_CFG] = 0x00;
+	acc->resume_state[RES_TT_THS] = 0x00;
+	acc->resume_state[RES_TT_LIM] = 0x00;
+	acc->resume_state[RES_TT_TLAT] = 0x00;
+	acc->resume_state[RES_TT_TW] = 0x00;
+
+	err = lis3dh_acc_device_power_on(acc);
+	if (err < 0) {
+		dev_err(&client->dev, "power on failed: %d\n", err);
+		goto err_pdata_init;
+	}
+
+	atomic_set(&acc->enabled, 1);
+
+	err = lis3dh_acc_update_g_range(acc, acc->pdata->g_range);
+	if (err < 0) {
+		dev_err(&client->dev, "update_g_range failed\n");
+		goto  err_power_off;
+	}
+
+	err = lis3dh_acc_update_odr(acc, acc->pdata->poll_interval);
+	if (err < 0) {
+		dev_err(&client->dev, "update_odr failed\n");
+		goto  err_power_off;
+	}
+
+	err = lis3dh_acc_input_init(acc);
+	if (err < 0) {
+		dev_err(&client->dev, "input init failed\n");
+		goto err_power_off;
+	}
+
+
+	err = create_sysfs_interfaces(&client->dev);
+	if (err < 0) {
+		dev_err(&client->dev,
+		   "device LIS3DH_ACC_DEV_NAME sysfs register failed\n");
+		goto err_input_cleanup;
+	}
+
+	lis3dh_acc_device_power_off(acc);
+
+	/* As default, do not report information */
+	atomic_set(&acc->enabled, 0);
+
+	if (acc->pdata->gpio_int1 >= 0) {
+		INIT_WORK(&acc->irq1_work, lis3dh_acc_irq1_work_func);
+		acc->irq1_work_queue =
+			create_singlethread_workqueue("lis3dh_acc_wq1");
+		if (!acc->irq1_work_queue) {
+			err = -ENOMEM;
+			dev_err(&client->dev,
+					"cannot create work queue1: %d\n", err);
+			goto err_remove_sysfs_int;
+		}
+		err = request_irq(acc->irq1, lis3dh_acc_isr1,
+				IRQF_TRIGGER_RISING, "lis3dh_acc_irq1", acc);
+		if (err < 0) {
+			dev_err(&client->dev, "request irq1 failed: %d\n", err);
+			goto err_destoyworkqueue1;
+		}
+		disable_irq_nosync(acc->irq1);
+	}
+
+	if (acc->pdata->gpio_int2 >= 0) {
+		INIT_WORK(&acc->irq2_work, lis3dh_acc_irq2_work_func);
+		acc->irq2_work_queue =
+			create_singlethread_workqueue("lis3dh_acc_wq2");
+		if (!acc->irq2_work_queue) {
+			err = -ENOMEM;
+			dev_err(&client->dev,
+					"cannot create work queue2: %d\n", err);
+			goto err_free_irq1;
+		}
+		err = request_irq(acc->irq2, lis3dh_acc_isr2,
+				IRQF_TRIGGER_RISING, "lis3dh_acc_irq2", acc);
+		if (err < 0) {
+			dev_err(&client->dev, "request irq2 failed: %d\n", err);
+			goto err_destoyworkqueue2;
+		}
+		disable_irq_nosync(acc->irq2);
+	}
+
+
+
+	mutex_unlock(&acc->lock);
+
+	dev_info(&client->dev, "%s: probed\n", LIS3DH_ACC_DEV_NAME);
+
+	return 0;
+
+err_destoyworkqueue2:
+	if (acc->pdata->gpio_int2 >= 0)
+		destroy_workqueue(acc->irq2_work_queue);
+err_free_irq1:
+	free_irq(acc->irq1, acc);
+err_destoyworkqueue1:
+	if (acc->pdata->gpio_int1 >= 0)
+		destroy_workqueue(acc->irq1_work_queue);
+err_remove_sysfs_int:
+	remove_sysfs_interfaces(&client->dev);
+err_input_cleanup:
+	lis3dh_acc_input_cleanup(acc);
+err_power_off:
+	lis3dh_acc_device_power_off(acc);
+err_pdata_init:
+	if (acc->pdata->exit)
+		acc->pdata->exit();
+exit_kfree_pdata:
+	kfree(acc->pdata);
+err_mutexunlock:
+	mutex_unlock(&acc->lock);
+	kfree(acc);
+exit_check_functionality_failed:
+	printk(KERN_ERR "%s: Driver Init failed\n", LIS3DH_ACC_DEV_NAME);
+	return err;
+}
+
+static int __devexit lis3dh_acc_remove(struct i2c_client *client)
+{
+	struct lis3dh_acc_data *acc = i2c_get_clientdata(client);
+
+	if (acc->pdata->gpio_int1 >= 0) {
+		free_irq(acc->irq1, acc);
+		gpio_free(acc->pdata->gpio_int1);
+		destroy_workqueue(acc->irq1_work_queue);
+	}
+
+	if (acc->pdata->gpio_int2 >= 0) {
+		free_irq(acc->irq2, acc);
+		gpio_free(acc->pdata->gpio_int2);
+		destroy_workqueue(acc->irq2_work_queue);
+	}
+
+	lis3dh_acc_input_cleanup(acc);
+	lis3dh_acc_device_power_off(acc);
+	remove_sysfs_interfaces(&client->dev);
+
+	if (acc->pdata->exit)
+		acc->pdata->exit();
+	kfree(acc->pdata);
+	kfree(acc);
+
+	return 0;
+}
+
+#ifdef CONFIG_PM
+static int lis3dh_acc_resume(struct i2c_client *client)
+{
+	struct lis3dh_acc_data *acc = i2c_get_clientdata(client);
+
+	if (acc->on_before_suspend)
+		return lis3dh_acc_enable(acc);
+	return 0;
+}
+
+static int lis3dh_acc_suspend(struct i2c_client *client, pm_message_t mesg)
+{
+	struct lis3dh_acc_data *acc = i2c_get_clientdata(client);
+
+	acc->on_before_suspend = atomic_read(&acc->enabled);
+	return lis3dh_acc_disable(acc);
+}
+#else
+#define lis3dh_acc_suspend	NULL
+#define lis3dh_acc_resume	NULL
+#endif /* CONFIG_PM */
+
+static const struct i2c_device_id lis3dh_acc_id[]
+		= { { LIS3DH_ACC_DEV_NAME, 0 }, { }, };
+
+MODULE_DEVICE_TABLE(i2c, lis3dh_acc_id);
+
+static struct i2c_driver lis3dh_acc_driver = {
+	.driver = {
+			.owner = THIS_MODULE,
+			.name = LIS3DH_ACC_DEV_NAME,
+		  },
+	.probe = lis3dh_acc_probe,
+	.remove = __devexit_p(lis3dh_acc_remove),
+	.suspend = lis3dh_acc_suspend,
+	.resume = lis3dh_acc_resume,
+	.id_table = lis3dh_acc_id,
+};
+
+static int __init lis3dh_acc_init(void)
+{
+	printk(KERN_INFO "%s accelerometer driver: init\n",
+						LIS3DH_ACC_DEV_NAME);
+	return i2c_add_driver(&lis3dh_acc_driver);
+}
+
+static void __exit lis3dh_acc_exit(void)
+{
+#ifdef DEBUG
+	printk(KERN_INFO "%s accelerometer driver exit\n",
+						LIS3DH_ACC_DEV_NAME);
+#endif /* DEBUG */
+	i2c_del_driver(&lis3dh_acc_driver);
+	return;
+}
+
+module_init(lis3dh_acc_init);
+module_exit(lis3dh_acc_exit);
+
+MODULE_DESCRIPTION("lis3dh digital accelerometer sysfs driver");
+MODULE_AUTHOR("Matteo Dameno, Carmine Iascone, Samuel Huo, STMicroelectronics");
+MODULE_LICENSE("GPL");
+
diff --git a/drivers/leds/leds-pm8xxx.c b/drivers/leds/leds-pm8xxx.c
index 3261037..04041e4 100644
--- a/drivers/leds/leds-pm8xxx.c
+++ b/drivers/leds/leds-pm8xxx.c
@@ -323,12 +323,17 @@
 }
 
 static void
-led_rgb_set(struct pm8xxx_led_data *led, enum led_brightness value)
+led_rgb_write(struct pm8xxx_led_data *led, u16 addr, enum led_brightness value)
 {
 	int rc;
 	u8 val, mask;
 
-	rc = pm8xxx_readb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL2, &val);
+	if (led->id != PM8XXX_ID_RGB_LED_BLUE &&
+		led->id != PM8XXX_ID_RGB_LED_RED &&
+		led->id != PM8XXX_ID_RGB_LED_GREEN)
+		return;
+
+	rc = pm8xxx_readb(led->dev->parent, addr, &val);
 	if (rc) {
 		dev_err(led->cdev.dev, "can't read rgb ctrl register rc=%d\n",
 							rc);
@@ -354,12 +359,24 @@
 	else
 		val &= ~mask;
 
-	rc = pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL2, val);
+	rc = pm8xxx_writeb(led->dev->parent, addr, val);
 	if (rc < 0)
 		dev_err(led->cdev.dev, "can't set rgb led %d level rc=%d\n",
 			 led->id, rc);
 }
 
+static void
+led_rgb_set(struct pm8xxx_led_data *led, enum led_brightness value)
+{
+	if (value) {
+		led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1, value);
+		led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL2, value);
+	} else {
+		led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL2, value);
+		led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1, value);
+	}
+}
+
 static int pm8xxx_led_pwm_work(struct pm8xxx_led_data *led)
 {
 	int duty_us;
@@ -369,12 +386,23 @@
 		duty_us = (led->pwm_period_us * led->cdev.brightness) /
 								LED_FULL;
 		rc = pwm_config(led->pwm_dev, duty_us, led->pwm_period_us);
-		if (led->cdev.brightness)
+		if (led->cdev.brightness) {
+			led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+				led->cdev.brightness);
 			rc = pwm_enable(led->pwm_dev);
-		else
+		} else {
 			pwm_disable(led->pwm_dev);
+			led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+				led->cdev.brightness);
+		}
 	} else {
+		if (led->cdev.brightness)
+			led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+				led->cdev.brightness);
 		rc = pm8xxx_pwm_lut_enable(led->pwm_dev, led->cdev.brightness);
+		if (!led->cdev.brightness)
+			led_rgb_write(led, SSBI_REG_ADDR_RGB_CNTL1,
+				led->cdev.brightness);
 	}
 
 	return rc;
@@ -658,35 +686,6 @@
 	return 0;
 }
 
-static int __devinit init_rgb_led(struct pm8xxx_led_data *led)
-{
-	int rc;
-	u8 val;
-
-	rc = pm8xxx_readb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL1, &val);
-	if (rc) {
-		dev_err(led->cdev.dev, "can't read rgb ctrl1 register rc=%d\n",
-							rc);
-		return rc;
-	}
-
-	switch (led->id) {
-	case PM8XXX_ID_RGB_LED_RED:
-		val |= PM8XXX_DRV_RGB_RED_LED;
-		break;
-	case PM8XXX_ID_RGB_LED_GREEN:
-		val |= PM8XXX_DRV_RGB_GREEN_LED;
-		break;
-	case PM8XXX_ID_RGB_LED_BLUE:
-		val |= PM8XXX_DRV_RGB_BLUE_LED;
-		break;
-	default:
-		return -EINVAL;
-	}
-
-	return pm8xxx_writeb(led->dev->parent, SSBI_REG_ADDR_RGB_CNTL1, val);
-}
-
 static int __devinit get_init_value(struct pm8xxx_led_data *led, u8 *val)
 {
 	int rc, offset;
@@ -717,12 +716,6 @@
 	case PM8XXX_ID_RGB_LED_RED:
 	case PM8XXX_ID_RGB_LED_GREEN:
 	case PM8XXX_ID_RGB_LED_BLUE:
-		rc = init_rgb_led(led);
-		if (rc) {
-			dev_err(led->cdev.dev, "can't initialize rgb rc=%d\n",
-								rc);
-			return rc;
-		}
 		addr = SSBI_REG_ADDR_RGB_CNTL1;
 		break;
 	default:
diff --git a/drivers/media/dvb/dvb-core/demux.h b/drivers/media/dvb/dvb-core/demux.h
index 9ad79e9..071d209 100644
--- a/drivers/media/dvb/dvb-core/demux.h
+++ b/drivers/media/dvb/dvb-core/demux.h
@@ -168,6 +168,7 @@
 struct dmx_ts_feed {
 	int is_filtering; /* Set to non-zero when filtering in progress */
 	struct dmx_demux *parent; /* Back-pointer */
+	const struct dvb_ringbuffer *buffer;
 	void *priv; /* Pointer to private data of the API client */
 	int (*set) (struct dmx_ts_feed *feed,
 		    u16 pid,
@@ -184,6 +185,8 @@
 			struct dmx_buffer_status *dmx_buffer_status);
 	int (*data_ready_cb)(struct dmx_ts_feed *feed,
 			dmx_ts_data_ready_cb callback);
+	int (*notify_data_read)(struct dmx_ts_feed *feed,
+			u32 bytes_num);
 };
 
 /*--------------------------------------------------------------------------*/
@@ -195,6 +198,7 @@
 	u8 filter_mask [DMX_MAX_FILTER_SIZE];
 	u8 filter_mode [DMX_MAX_FILTER_SIZE];
 	struct dmx_section_feed* parent; /* Back-pointer */
+	const struct dvb_ringbuffer *buffer;
 	void* priv; /* Pointer to private data of the API client */
 };
 
@@ -227,6 +231,8 @@
 	int (*stop_filtering) (struct dmx_section_feed* feed);
 	int (*data_ready_cb)(struct dmx_section_feed *feed,
 			dmx_section_data_ready_cb callback);
+	int (*notify_data_read)(struct dmx_section_filter *filter,
+			u32 bytes_num);
 };
 
 /*--------------------------------------------------------------------------*/
diff --git a/drivers/media/dvb/dvb-core/dmxdev.c b/drivers/media/dvb/dvb-core/dmxdev.c
index 433e796..8353f6f 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.c
+++ b/drivers/media/dvb/dvb-core/dmxdev.c
@@ -60,6 +60,35 @@
 	return dvb_ringbuffer_write(buf, src, len);
 }
 
+static inline void dvb_dmxdev_notify_data_read(struct dmxdev_filter *filter,
+					int bytes_read)
+{
+	if (!filter)
+		return;
+
+	if (filter->type == DMXDEV_TYPE_SEC) {
+		if (filter->feed.sec->notify_data_read)
+			filter->feed.sec->notify_data_read(
+						filter->filter.sec,
+						bytes_read);
+	} else {
+		struct dmxdev_feed *feed;
+
+		/*
+		 * All feeds of same demux-handle share the same output
+		 * buffer, it is enough to notify on the buffer status
+		 * on one of the feeds
+		 */
+		feed = list_first_entry(&filter->feed.ts,
+					struct dmxdev_feed, next);
+
+		if (feed->ts->notify_data_read)
+			feed->ts->notify_data_read(
+						feed->ts,
+						bytes_read);
+	}
+}
+
 static inline u32 dvb_dmxdev_advance_event_idx(u32 index)
 {
 	index++;
@@ -460,6 +489,7 @@
 		}
 		dvb_ringbuffer_init(&dmxdev->dvr_buffer, mem, DVR_BUFFER_SIZE);
 		dvb_dmxdev_flush_events(&dmxdev->dvr_output_events);
+		dmxdev->dvr_feeds_count = 0;
 
 		dvbdev->readers--;
 	} else if (!dvbdev->writers) {
@@ -719,9 +749,22 @@
 				      buf, count, ppos);
 
 	if (res > 0) {
+		dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, res);
 		spin_lock_irq(&dmxdev->lock);
 		dvb_dmxdev_update_events(&dmxdev->dvr_output_events, res);
 		spin_unlock_irq(&dmxdev->lock);
+	} else if (res == -EOVERFLOW) {
+		/*
+		 * When buffer overflowed, demux-dev flushed the
+		 * buffer and marked the buffer in error state.
+		 * Data from underlying driver is discarded until
+		 * user gets notified that buffer has overflowed.
+		 * Now that the user is notified, notify underlying
+		 * driver that data was flushed from output buffer.
+		 */
+		dvb_dmxdev_notify_data_read(dmxdev->dvr_feed,
+			dmxdev->dvr_flush_data_len);
+		dmxdev->dvr_flush_data_len = 0;
 	}
 
 	return res;
@@ -873,8 +916,20 @@
 
 	res = dvb_dmxdev_remove_event(&dmxdev->dvr_output_events, event);
 
-	if (event->type == DMX_EVENT_BUFFER_OVERFLOW)
+	if (event->type == DMX_EVENT_BUFFER_OVERFLOW) {
+		/*
+		 * When buffer overflowed, demux-dev flushed the
+		 * buffer and marked the buffer in error state.
+		 * Data from underlying driver is discarded until
+		 * user gets notified that buffer has overflowed.
+		 * Now that the user is notified, notify underlying
+		 * driver that data was flushed from output buffer.
+		 */
+		dvb_dmxdev_notify_data_read(dmxdev->dvr_feed,
+			dmxdev->dvr_flush_data_len);
+		dmxdev->dvr_flush_data_len = 0;
 		dmxdev->dvr_buffer.error = 0;
+	}
 
 	spin_unlock_irq(&dmxdev->lock);
 
@@ -899,7 +954,23 @@
 	spin_lock_irq(lock);
 
 	dmx_buffer_status->error = buf->error;
-	buf->error = 0;
+	if (buf->error) {
+		if (buf->error == -EOVERFLOW) {
+			/*
+			 * When buffer overflowed, demux-dev flushed the
+			 * buffer and marked the buffer in error state.
+			 * Data from underlying driver is discarded until
+			 * user gets notified that buffer has overflowed.
+			 * Now that the user is notified, notify underlying
+			 * driver that data was flushed from output buffer.
+			 */
+			dvb_dmxdev_notify_data_read(dmxdev->dvr_feed,
+				dmxdev->dvr_flush_data_len);
+			dmxdev->dvr_flush_data_len = 0;
+		}
+
+		buf->error = 0;
+	}
 
 	dmx_buffer_status->fullness = dvb_ringbuffer_avail(buf);
 	dmx_buffer_status->free_bytes = dvb_ringbuffer_free(buf);
@@ -931,6 +1002,7 @@
 
 	DVB_RINGBUFFER_SKIP(&dmxdev->dvr_buffer, bytes_count);
 
+	dvb_dmxdev_notify_data_read(dmxdev->dvr_feed, bytes_count);
 	spin_lock_irq(&dmxdev->lock);
 	dvb_dmxdev_update_events(&dmxdev->dvr_output_events, bytes_count);
 	spin_unlock_irq(&dmxdev->lock);
@@ -1183,27 +1255,39 @@
 		struct dmxdev_feed *feed;
 		int ret;
 
-		/* Ask for status of decoder's buffer from underlying HW */
-		list_for_each_entry(feed, &dmxdevfilter->feed.ts,
-							next) {
-			if (feed->ts->get_decoder_buff_status)
-				ret = feed->ts->get_decoder_buff_status(
-						feed->ts,
-						dmx_buffer_status);
-			else
-				ret = -ENODEV;
+		/* Only one feed should be in the list in case of decoder */
+		feed = list_first_entry(&dmxdevfilter->feed.ts,
+					struct dmxdev_feed, next);
 
-			/*
-			 * There should not be more than one ts feed
-			 * in the list as this is DECODER feed.
-			 */
-			spin_unlock_irq(&dmxdevfilter->dev->lock);
-			return ret;
-		}
+		/* Ask for status of decoder's buffer from underlying HW */
+		if (feed->ts->get_decoder_buff_status)
+			ret = feed->ts->get_decoder_buff_status(
+					feed->ts,
+					dmx_buffer_status);
+		else
+			ret = -ENODEV;
+
+		spin_unlock_irq(&dmxdevfilter->dev->lock);
+		return ret;
 	}
 
 	dmx_buffer_status->error = buf->error;
-	buf->error = 0;
+	if (buf->error) {
+		if (buf->error == -EOVERFLOW) {
+			/*
+			 * When buffer overflowed, demux-dev flushed the
+			 * buffer and marked the buffer in error state.
+			 * Data from underlying driver is discarded until
+			 * user gets notified that buffer has overflowed.
+			 * Now that the user is notified, notify underlying
+			 * driver that data was flushed from output buffer.
+			 */
+			dvb_dmxdev_notify_data_read(dmxdevfilter,
+				dmxdevfilter->flush_data_len);
+			dmxdevfilter->flush_data_len = 0;
+		}
+		buf->error = 0;
+	}
 
 	dmx_buffer_status->fullness = dvb_ringbuffer_avail(buf);
 	dmx_buffer_status->free_bytes = dvb_ringbuffer_free(buf);
@@ -1234,6 +1318,7 @@
 
 	DVB_RINGBUFFER_SKIP(&dmxdevfilter->buffer, bytes_count);
 
+	dvb_dmxdev_notify_data_read(dmxdevfilter, bytes_count);
 	spin_lock_irq(&dmxdevfilter->dev->lock);
 	dvb_dmxdev_update_events(&dmxdevfilter->events, bytes_count);
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
@@ -1252,8 +1337,20 @@
 
 	res = dvb_dmxdev_remove_event(&dmxdevfilter->events, event);
 
-	if (event->type == DMX_EVENT_BUFFER_OVERFLOW)
+	if (event->type == DMX_EVENT_BUFFER_OVERFLOW) {
+		/*
+		 * When buffer overflowed, demux-dev flushed the
+		 * buffer and marked the buffer in error state.
+		 * Data from underlying driver is discarded until
+		 * user gets notified that buffer has overflowed.
+		 * Now that the user is notified, notify underlying
+		 * driver that data was flushed from output buffer.
+		 */
+		dvb_dmxdev_notify_data_read(dmxdevfilter,
+			dmxdevfilter->flush_data_len);
+		dmxdevfilter->flush_data_len = 0;
 		dmxdevfilter->buffer.error = 0;
+	}
 
 	spin_unlock_irq(&dmxdevfilter->dev->lock);
 
@@ -1334,6 +1431,8 @@
 					      buffer2_len);
 
 	if (ret < 0) {
+		dmxdevfilter->flush_data_len =
+			dvb_ringbuffer_avail(&dmxdevfilter->buffer);
 		dvb_dmxdev_flush_output(&dmxdevfilter->buffer,
 			&dmxdevfilter->events);
 		dmxdevfilter->buffer.error = ret;
@@ -1372,6 +1471,7 @@
 	struct dmxdev_events_queue *events;
 	struct dmx_filter_event event;
 	int ret;
+	u32 *flush_data_len;
 
 	spin_lock(&dmxdevfilter->dev->lock);
 	if (dmxdevfilter->params.pes.output == DMX_OUT_DECODER) {
@@ -1383,9 +1483,11 @@
 	    || dmxdevfilter->params.pes.output == DMX_OUT_TSDEMUX_TAP) {
 		buffer = &dmxdevfilter->buffer;
 		events = &dmxdevfilter->events;
+		flush_data_len = &dmxdevfilter->flush_data_len;
 	} else {
 		buffer = &dmxdevfilter->dev->dvr_buffer;
 		events = &dmxdevfilter->dev->dvr_output_events;
+		flush_data_len = &dmxdevfilter->dev->dvr_flush_data_len;
 	}
 
 	if (buffer->error) {
@@ -1435,6 +1537,8 @@
 			ret = dvb_dmxdev_buffer_write(buffer, buffer2,
 								buffer2_len);
 		if (ret < 0) {
+			*flush_data_len =
+				dvb_ringbuffer_avail(&dmxdevfilter->buffer);
 			dvb_dmxdev_flush_output(buffer, events);
 			buffer->error = ret;
 
@@ -1507,6 +1611,8 @@
 
 	if ((DMX_OVERRUN_ERROR == dmx_data_ready->status) ||
 		(dmx_data_ready->data_length > free)) {
+		dmxdevfilter->flush_data_len =
+			dvb_ringbuffer_avail(&dmxdevfilter->buffer);
 		dvb_dmxdev_flush_output(&dmxdevfilter->buffer,
 				&dmxdevfilter->events);
 
@@ -1548,6 +1654,7 @@
 	struct dvb_ringbuffer *buffer;
 	struct dmxdev_events_queue *events;
 	struct dmx_filter_event event;
+	u32 *flush_data_len;
 	int free;
 
 	spin_lock(&dmxdevfilter->dev->lock);
@@ -1560,9 +1667,11 @@
 	if (dmxdevfilter->params.pes.output != DMX_OUT_TS_TAP) {
 		buffer = &dmxdevfilter->buffer;
 		events = &dmxdevfilter->events;
+		flush_data_len = &dmxdevfilter->flush_data_len;
 	} else {
 		buffer = &dmxdevfilter->dev->dvr_buffer;
 		events = &dmxdevfilter->dev->dvr_output_events;
+		flush_data_len = &dmxdevfilter->dev->dvr_flush_data_len;
 	}
 
 	if (dmx_data_ready->status == DMX_OK_PCR) {
@@ -1592,6 +1701,8 @@
 
 	if ((DMX_OVERRUN_ERROR == dmx_data_ready->status) ||
 		(dmx_data_ready->data_length > free)) {
+		*flush_data_len =
+				dvb_ringbuffer_avail(&dmxdevfilter->buffer);
 		dvb_dmxdev_flush_output(buffer, events);
 
 		dprintk("dmxdev: buffer overflow\n");
@@ -1761,6 +1872,12 @@
 	case DMXDEV_TYPE_PES:
 		dvb_dmxdev_feed_stop(dmxdevfilter);
 		demux = dmxdevfilter->dev->demux;
+		if (dmxdevfilter->params.pes.output == DMX_OUT_TS_TAP) {
+			dmxdevfilter->dev->dvr_feeds_count--;
+			if (!dmxdevfilter->dev->dvr_feeds_count)
+				dmxdevfilter->dev->dvr_feed = NULL;
+		}
+
 		list_for_each_entry(feed, &dmxdevfilter->feed.ts, next) {
 			demux->release_ts_feed(demux, feed->ts);
 			feed->ts = NULL;
@@ -1844,6 +1961,15 @@
 	tsfeed = feed->ts;
 	tsfeed->priv = filter;
 
+	if (filter->params.pes.output == DMX_OUT_TS_TAP) {
+		tsfeed->buffer = &dmxdev->dvr_buffer;
+		if (!dmxdev->dvr_feeds_count)
+			dmxdev->dvr_feed = filter;
+		dmxdev->dvr_feeds_count++;
+	} else {
+		tsfeed->buffer = &filter->buffer;
+	}
+
 	if (tsfeed->data_ready_cb) {
 		ret = tsfeed->data_ready_cb(tsfeed, dvb_dmxdev_ts_event_cb);
 
@@ -1979,6 +2105,7 @@
 		}
 
 		(*secfilter)->priv = filter;
+		(*secfilter)->buffer = &filter->buffer;
 
 		memcpy(&((*secfilter)->filter_value[3]),
 		       &(para->filter.filter[1]), DMX_FILTER_SIZE - 1);
@@ -2278,9 +2405,22 @@
 					    buf, count, ppos);
 
 	if (ret > 0) {
+		dvb_dmxdev_notify_data_read(dmxdevfilter, ret);
 		spin_lock_irq(&dmxdevfilter->dev->lock);
 		dvb_dmxdev_update_events(&dmxdevfilter->events, ret);
 		spin_unlock_irq(&dmxdevfilter->dev->lock);
+	} else if (ret == -EOVERFLOW) {
+		/*
+		 * When buffer overflowed, demux-dev flushed the
+		 * buffer and marked the buffer in error state.
+		 * Data from underlying driver is discarded until
+		 * user gets notified that buffer has overflowed.
+		 * Now that the user is notified, notify underlying
+		 * driver that data was flushed from output buffer.
+		 */
+		dvb_dmxdev_notify_data_read(dmxdevfilter->dev->dvr_feed,
+			dmxdevfilter->flush_data_len);
+		dmxdevfilter->flush_data_len = 0;
 	}
 
 	mutex_unlock(&dmxdevfilter->mutex);
diff --git a/drivers/media/dvb/dvb-core/dmxdev.h b/drivers/media/dvb/dvb-core/dmxdev.h
index 6fa7054..9fd900e 100644
--- a/drivers/media/dvb/dvb-core/dmxdev.h
+++ b/drivers/media/dvb/dvb-core/dmxdev.h
@@ -113,6 +113,7 @@
 	enum dmxdev_state state;
 	struct dmxdev *dev;
 	struct dvb_ringbuffer buffer;
+	u32 flush_data_len;
 
 	struct mutex mutex;
 
@@ -153,6 +154,9 @@
 
 	struct dvb_ringbuffer dvr_buffer;
 	struct dmxdev_events_queue dvr_output_events;
+	struct dmxdev_filter *dvr_feed;
+	u32 dvr_flush_data_len;
+	int dvr_feeds_count;
 
 	struct dvb_ringbuffer dvr_input_buffer;
 	struct workqueue_struct *dvr_input_workqueue;
diff --git a/drivers/media/dvb/dvb-core/dvb_demux.c b/drivers/media/dvb/dvb-core/dvb_demux.c
index 0be6a22..0bdf6cb 100644
--- a/drivers/media/dvb/dvb-core/dvb_demux.c
+++ b/drivers/media/dvb/dvb-core/dvb_demux.c
@@ -1137,6 +1137,7 @@
 	(*ts_feed)->set_indexing_params = dmx_ts_set_indexing_params;
 	(*ts_feed)->get_decoder_buff_status = dmx_ts_feed_decoder_buff_status;
 	(*ts_feed)->data_ready_cb = dmx_ts_feed_data_ready_cb;
+	(*ts_feed)->notify_data_read = NULL;
 
 	if (!(feed->filter = dvb_dmx_filter_alloc(demux))) {
 		feed->state = DMX_STATE_FREE;
@@ -1434,6 +1435,7 @@
 	(*feed)->stop_filtering = dmx_section_feed_stop_filtering;
 	(*feed)->release_filter = dmx_section_feed_release_filter;
 	(*feed)->data_ready_cb = dmx_section_feed_data_ready_cb;
+	(*feed)->notify_data_read = NULL;
 
 	mutex_unlock(&dvbdmx->mutex);
 	return 0;
diff --git a/drivers/media/video/msm/gemini/msm_gemini_sync.c b/drivers/media/video/msm/gemini/msm_gemini_sync.c
index e878329..97bb611 100644
--- a/drivers/media/video/msm/gemini/msm_gemini_sync.c
+++ b/drivers/media/video/msm/gemini/msm_gemini_sync.c
@@ -218,6 +218,7 @@
 		return -EAGAIN;
 	}
 
+	memset(&ctrl_cmd, 0, sizeof(struct msm_gemini_ctrl_cmd));
 	ctrl_cmd.type = buf_p->vbuf.type;
 	kfree(buf_p);
 
diff --git a/drivers/media/video/msm/msm.c b/drivers/media/video/msm/msm.c
index 3222f905..29aba08 100644
--- a/drivers/media/video/msm/msm.c
+++ b/drivers/media/video/msm/msm.c
@@ -888,7 +888,10 @@
 			goto msm_cam_server_begin_session_failed;
 		}
 		pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
-
+		if (!pmctl) {
+			pr_err("%s mctl ptr is null ", __func__);
+			goto msm_cam_server_begin_session_failed;
+		}
 #ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
 		pmctl->client = msm_ion_client_create(-1, "camera");
 		kref_init(&pmctl->refcount);
diff --git a/drivers/media/video/msm/msm_mctl.c b/drivers/media/video/msm/msm_mctl.c
index 4bbc47c..fd5591c 100644
--- a/drivers/media/video/msm/msm_mctl.c
+++ b/drivers/media/video/msm/msm_mctl.c
@@ -437,7 +437,7 @@
 	/* open sub devices - once only*/
 	if (!p_mctl->opencnt) {
 		struct msm_sensor_csi_info csi_info;
-		uint32_t csid_version;
+		uint32_t csid_version = 0;
 		wake_lock(&p_mctl->wake_lock);
 
 		csid_core = camdev->csid_core;
@@ -1327,6 +1327,10 @@
 	WARN_ON(pctx != f->private_data);
 
 	pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s mctl ptr is null ", __func__);
+		return -EINVAL;
+	}
 	if (!pcam_inst->vbqueue_initialized) {
 		pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE);
@@ -1351,6 +1355,10 @@
 	WARN_ON(pctx != f->private_data);
 
 	pmctl = msm_cam_server_get_mctl(pcam->mctl_handle);
+	if (!pmctl) {
+		pr_err("%s mctl ptr is null ", __func__);
+		return -EINVAL;
+	}
 	if (!pcam_inst->vbqueue_initialized) {
 		pmctl->mctl_vbqueue_init(pcam_inst, &pcam_inst->vid_bufq,
 					V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
diff --git a/drivers/media/video/msm/msm_vfe32.c b/drivers/media/video/msm/msm_vfe32.c
index 38179e6..aa2b19d 100644
--- a/drivers/media/video/msm/msm_vfe32.c
+++ b/drivers/media/video/msm/msm_vfe32.c
@@ -4754,7 +4754,8 @@
 
 	return rc;
 clk_enable_failed:
-	regulator_disable(axi_ctrl->fs_vfe);
+	if (axi_ctrl->fs_vfe)
+		regulator_disable(axi_ctrl->fs_vfe);
 fs_failed:
 	iounmap(axi_ctrl->share_ctrl->vfebase);
 	axi_ctrl->share_ctrl->vfebase = NULL;
@@ -4932,12 +4933,14 @@
 		pr_err("%s: base address unmapped\n", __func__);
 		return -EFAULT;
 	}
+	memset(&cfgcmd, 0, sizeof(struct msm_vfe_cfg_cmd));
 	if (NULL != arg) {
 		if (copy_from_user(&cfgcmd, arg, sizeof(cfgcmd))) {
 			ERR_COPY_FROM_USER();
 			return -EFAULT;
 		}
 	}
+	memset(&vfecmd, 0, sizeof(struct msm_isp_cmd));
 	if (NULL != cfgcmd.value) {
 		if (copy_from_user(&vfecmd,
 				(void __user *)(cfgcmd.value),
diff --git a/drivers/media/video/msm/msm_vpe.c b/drivers/media/video/msm/msm_vpe.c
index 58fc153..5990ca7 100644
--- a/drivers/media/video/msm/msm_vpe.c
+++ b/drivers/media/video/msm/msm_vpe.c
@@ -545,7 +545,8 @@
 	return rc;
 
 vpe_clk_failed:
-	regulator_disable(vpe_ctrl->fs_vpe);
+	if (vpe_ctrl->fs_vpe)
+		regulator_disable(vpe_ctrl->fs_vpe);
 vpe_fs_failed:
 	disable_irq(vpe_ctrl->vpeirq->start);
 	vpe_ctrl->state = VPE_STATE_IDLE;
diff --git a/drivers/media/video/msm/server/msm_cam_server.c b/drivers/media/video/msm/server/msm_cam_server.c
index 715b4e7..deab77b 100644
--- a/drivers/media/video/msm/server/msm_cam_server.c
+++ b/drivers/media/video/msm/server/msm_cam_server.c
@@ -1783,7 +1783,7 @@
 			 * the individual irq lookup table.... */
 			irq_req->irq_idx =
 				get_irq_idx_from_camhw_idx(irq_req->cam_hw_idx);
-			if (irq_req->cam_hw_idx < 0) {
+			if (irq_req->irq_idx < 0) {
 				pr_err("%s Invalid hw index %d ", __func__,
 					irq_req->cam_hw_idx);
 				return -EINVAL;
diff --git a/drivers/media/video/msm_vidc/msm_venc.c b/drivers/media/video/msm_vidc/msm_venc.c
index 64a0516..72c6685 100644
--- a/drivers/media/video/msm_vidc/msm_venc.c
+++ b/drivers/media/video/msm_vidc/msm_venc.c
@@ -63,6 +63,30 @@
 	"Model 2",
 	NULL
 };
+
+static const char *const h263_level[] = {
+	"1.0",
+	"2.0",
+	"3.0",
+	"4.0",
+	"4.5",
+	"5.0",
+	"6.0",
+	"7.0",
+};
+
+static const char *const h263_profile[] = {
+	"Baseline",
+	"H320 Coding",
+	"Backward Compatible",
+	"ISWV2",
+	"ISWV3",
+	"High Compression",
+	"Internet",
+	"Interlace",
+	"High Latency",
+};
+
 static const struct msm_vidc_ctrl msm_venc_ctrls[] = {
 	{
 		.id = V4L2_CID_MPEG_VIDC_VIDEO_FRAME_RATE,
@@ -212,10 +236,48 @@
 		.minimum = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
 		.maximum = V4L2_MPEG_VIDEO_H264_LEVEL_5_1,
 		.default_value = V4L2_MPEG_VIDEO_H264_LEVEL_1_0,
-		.step = 1,
+		.step = 0,
 		.menu_skip_mask = 0,
 	},
 	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE,
+		.name = "H263 Profile",
+		.type = V4L2_CTRL_TYPE_MENU,
+		.minimum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+		.maximum = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY,
+		.default_value = V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE,
+		.menu_skip_mask = ~(
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY)
+		),
+		.qmenu = h263_profile,
+	},
+	{
+		.id = V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL,
+		.name = "H263 Level",
+		.type = V4L2_CTRL_TYPE_MENU,
+		.minimum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+		.maximum = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0,
+		.default_value = V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0,
+		.menu_skip_mask = ~(
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0) |
+		(1 << V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0)
+		),
+		.qmenu = h263_level,
+	},
+	{
 		.id = V4L2_CID_MPEG_VIDC_VIDEO_ROTATION,
 		.name = "Rotation",
 		.type = V4L2_CTRL_TYPE_MENU,
@@ -410,8 +472,11 @@
 	venc_h264_profile_level = {HAL_H264_PROFILE_BASELINE,
 		HAL_H264_LEVEL_1};
 static struct hal_profile_level
-	venc_mpeg4_profile_level = {HAL_H264_PROFILE_BASELINE,
-		HAL_H264_LEVEL_1};
+	venc_mpeg4_profile_level = {HAL_MPEG4_PROFILE_SIMPLE,
+		HAL_MPEG4_LEVEL_0};
+static struct hal_profile_level
+	venc_h263_profile_level = {HAL_H263_PROFILE_BASELINE,
+				HAL_H263_LEVEL_10};
 static struct hal_h264_entropy_control
 	venc_h264_entropy_control = {HAL_H264_ENTROPY_CAVLC,
 		HAL_H264_CABAC_MODEL_0};
@@ -904,6 +969,84 @@
 		pr_debug("\nLevel: %d\n",
 			   profile_level.level);
 		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_H263_PROFILE:
+		property_id =
+			HAL_PARAM_PROFILE_LEVEL_CURRENT;
+
+		switch (control.value) {
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BASELINE:
+			control.value = HAL_H263_PROFILE_BASELINE;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_H320CODING:
+			control.value = HAL_H263_PROFILE_H320CODING;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_BACKWARDCOMPATIBLE:
+			control.value = HAL_H263_PROFILE_BACKWARDCOMPATIBLE;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV2:
+			control.value = HAL_H263_PROFILE_ISWV2;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_ISWV3:
+			control.value = HAL_H263_PROFILE_ISWV3;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHCOMPRESSION:
+			control.value = HAL_H263_PROFILE_HIGHCOMPRESSION;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERNET:
+			control.value = HAL_H263_PROFILE_INTERNET;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_INTERLACE:
+			control.value = HAL_H263_PROFILE_INTERLACE;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_PROFILE_HIGHLATENCY:
+			control.value = HAL_H263_PROFILE_HIGHLATENCY;
+			break;
+		default:
+			break;
+		}
+		profile_level.profile = control.value;
+		venc_h263_profile_level.profile = control.value;
+		profile_level.level = venc_h263_profile_level.level;
+		pdata = &profile_level;
+		break;
+	case V4L2_CID_MPEG_VIDC_VIDEO_H263_LEVEL:
+		property_id =
+			HAL_PARAM_PROFILE_LEVEL_CURRENT;
+
+		switch (control.value) {
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_1_0:
+			control.value = HAL_H263_LEVEL_10;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_2_0:
+			control.value = HAL_H263_LEVEL_20;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_3_0:
+			control.value = HAL_H263_LEVEL_30;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_0:
+			control.value = HAL_H263_LEVEL_40;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_4_5:
+			control.value = HAL_H263_LEVEL_45;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_5_0:
+			control.value = HAL_H263_LEVEL_50;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_6_0:
+			control.value = HAL_H263_LEVEL_60;
+			break;
+		case V4L2_MPEG_VIDC_VIDEO_H263_LEVEL_7_0:
+			control.value = HAL_H263_LEVEL_70;
+			break;
+		default:
+			break;
+		}
+
+		profile_level.level = control.value;
+		venc_h263_profile_level.level = control.value;
+		profile_level.profile = venc_h263_profile_level.profile;
+		pdata = &profile_level;
+		break;
 	case V4L2_CID_MPEG_VIDC_VIDEO_ROTATION:
 		property_id =
 			HAL_CONFIG_VPE_OPERATIONS;
diff --git a/drivers/media/video/vcap_v4l2.c b/drivers/media/video/vcap_v4l2.c
index 98e2fd9..01e1201 100644
--- a/drivers/media/video/vcap_v4l2.c
+++ b/drivers/media/video/vcap_v4l2.c
@@ -1113,7 +1113,6 @@
 {
 	struct vcap_client_data *c_data = to_client_data(file->private_data);
 	struct vcap_dev *dev = c_data->dev;
-	unsigned long flags;
 	int rc;
 	unsigned long rate;
 	long rate_rc;
@@ -1126,14 +1125,14 @@
 
 	switch (c_data->op_mode) {
 	case VC_VCAP_OP:
-		spin_lock_irqsave(&dev->dev_slock, flags);
+		mutex_lock(&dev->dev_mutex);
 		if (dev->vc_resource) {
 			pr_err("VCAP Err: %s: VC resource taken", __func__);
-			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			mutex_unlock(&dev->dev_mutex);
 			return -EBUSY;
 		}
 		dev->vc_resource = 1;
-		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		mutex_unlock(&dev->dev_mutex);
 
 		c_data->dev->vc_client = c_data;
 
@@ -1179,14 +1178,14 @@
 			goto free_res;
 		break;
 	case VP_VCAP_OP:
-		spin_lock_irqsave(&dev->dev_slock, flags);
+		mutex_lock(&dev->dev_mutex);
 		if (dev->vp_resource) {
 			pr_err("VCAP Err: %s: VP resource taken", __func__);
-			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			mutex_unlock(&dev->dev_mutex);
 			return -EBUSY;
 		}
 		dev->vp_resource = 1;
-		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		mutex_unlock(&dev->dev_mutex);
 		c_data->dev->vp_client = c_data;
 
 		rate = 160000000;
@@ -1240,16 +1239,16 @@
 			goto s_on_deinit_nr_buf;
 		break;
 	case VC_AND_VP_VCAP_OP:
-		spin_lock_irqsave(&dev->dev_slock, flags);
+		mutex_lock(&dev->dev_mutex);
 		if (dev->vc_resource || dev->vp_resource) {
 			pr_err("VCAP Err: %s: VC/VP resource taken",
 				__func__);
-			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			mutex_unlock(&dev->dev_mutex);
 			return -EBUSY;
 		}
 		dev->vc_resource = 1;
 		dev->vp_resource = 1;
-		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		mutex_unlock(&dev->dev_mutex);
 		c_data->dev->vc_client = c_data;
 		c_data->dev->vp_client = c_data;
 
@@ -1347,7 +1346,7 @@
 s_on_deinit_m_buf:
 	deinit_motion_buf(c_data);
 free_res:
-	spin_lock_irqsave(&dev->dev_slock, flags);
+	mutex_lock(&dev->dev_mutex);
 	if (c_data->op_mode == VC_VCAP_OP) {
 		dev->vc_resource = 0;
 		c_data->dev->vc_client = NULL;
@@ -1360,7 +1359,7 @@
 		dev->vc_resource = 0;
 		dev->vp_resource = 0;
 	}
-	spin_unlock_irqrestore(&dev->dev_slock, flags);
+	mutex_unlock(&dev->dev_mutex);
 	return rc;
 }
 
@@ -1381,7 +1380,6 @@
 int streamoff_work(struct vcap_client_data *c_data)
 {
 	struct vcap_dev *dev = c_data->dev;
-	unsigned long flags;
 	int rc;
 	switch (c_data->op_mode) {
 	case VC_VCAP_OP:
@@ -1390,14 +1388,14 @@
 				__func__);
 			return -EBUSY;
 		}
-		spin_lock_irqsave(&dev->dev_slock, flags);
+		mutex_lock(&dev->dev_mutex);
 		if (!dev->vc_resource) {
 			pr_err("VCAP Err: %s: VC res not acquired", __func__);
-			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			mutex_unlock(&dev->dev_mutex);
 			return -EBUSY;
 		}
 		dev->vc_resource = 0;
-		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		mutex_unlock(&dev->dev_mutex);
 		rc = vb2_streamoff(&c_data->vc_vidq,
 				V4L2_BUF_TYPE_VIDEO_CAPTURE);
 		if (rc >= 0) {
@@ -1406,19 +1404,24 @@
 		}
 		return rc;
 	case VP_VCAP_OP:
+		if (!dev->vp_dummy_complete) {
+			pr_err("VCAP Err: %s: VP dummy read not complete",
+				__func__);
+			return -EINVAL;
+		}
 		if (c_data != dev->vp_client) {
 			pr_err("VCAP Err: %s: VP held by other client",
 				__func__);
 			return -EBUSY;
 		}
-		spin_lock_irqsave(&dev->dev_slock, flags);
+		mutex_lock(&dev->dev_mutex);
 		if (!dev->vp_resource) {
 			pr_err("VCAP Err: %s: VP res not acquired", __func__);
-			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			mutex_unlock(&dev->dev_mutex);
 			return -EBUSY;
 		}
 		dev->vp_resource = 0;
-		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		mutex_unlock(&dev->dev_mutex);
 		rc = streamoff_validate_q(&c_data->vp_in_vidq);
 		if (rc < 0)
 			return rc;
@@ -1444,21 +1447,26 @@
 		atomic_set(&c_data->dev->vp_enabled, 0);
 		return rc;
 	case VC_AND_VP_VCAP_OP:
+		if (!dev->vp_dummy_complete) {
+			pr_err("VCAP Err: %s: VP dummy read not complete",
+				__func__);
+			return -EINVAL;
+		}
 		if (c_data != dev->vp_client || c_data != dev->vc_client) {
 			pr_err("VCAP Err: %s: VC/VP held by other client",
 				__func__);
 			return -EBUSY;
 		}
-		spin_lock_irqsave(&dev->dev_slock, flags);
+		mutex_lock(&dev->dev_mutex);
 		if (!(dev->vc_resource || dev->vp_resource)) {
 			pr_err("VCAP Err: %s: VC or VP res not acquired",
 				__func__);
-			spin_unlock_irqrestore(&dev->dev_slock, flags);
+			mutex_unlock(&dev->dev_mutex);
 			return -EBUSY;
 		}
 		dev->vc_resource = 0;
 		dev->vp_resource = 0;
-		spin_unlock_irqrestore(&dev->dev_slock, flags);
+		mutex_unlock(&dev->dev_mutex);
 		rc = streamoff_validate_q(&c_data->vc_vidq);
 		if (rc < 0)
 			return rc;
@@ -1562,10 +1570,11 @@
 	struct vcap_dev *dev = video_drvdata(file);
 	struct vcap_client_data *c_data;
 	struct vb2_queue *q;
-	unsigned long flags;
 	int ret;
-	c_data = kzalloc(sizeof(*c_data), GFP_KERNEL);
 	if (!dev)
+		return -EINVAL;
+	c_data = kzalloc(sizeof(*c_data), GFP_KERNEL);
+	if (!c_data)
 		return -ENOMEM;
 
 	c_data->dev = dev;
@@ -1619,22 +1628,33 @@
 	v4l2_fh_init(&c_data->vfh, dev->vfd);
 	v4l2_fh_add(&c_data->vfh);
 
-	spin_lock_irqsave(&dev->dev_slock, flags);
+	mutex_lock(&dev->dev_mutex);
 	atomic_inc(&dev->open_clients);
 	ret = atomic_read(&dev->open_clients);
-	spin_unlock_irqrestore(&dev->dev_slock, flags);
 	if (ret == 1) {
 		ret = vcap_enable(dev, dev->ddev, 54860000);
 		if (ret < 0) {
 			pr_err("Err: %s: Power on vcap failed", __func__);
+			mutex_unlock(&dev->dev_mutex);
+			goto vcap_power_failed;
+		}
+
+		ret = vp_dummy_event(c_data);
+		if (ret < 0) {
+			pr_err("Err: %s: Dummy Event failed", __func__);
+			mutex_unlock(&dev->dev_mutex);
+			vcap_disable(dev);
 			goto vcap_power_failed;
 		}
 	}
+	mutex_unlock(&dev->dev_mutex);
 
 	file->private_data = &c_data->vfh;
 	return 0;
 
 vcap_power_failed:
+	atomic_dec(&dev->open_clients);
+
 	v4l2_fh_del(&c_data->vfh);
 	v4l2_fh_exit(&c_data->vfh);
 	vb2_queue_release(&c_data->vp_out_vidq);
@@ -1651,7 +1671,6 @@
 {
 	struct vcap_dev *dev = video_drvdata(file);
 	struct vcap_client_data *c_data = to_client_data(file->private_data);
-	unsigned long flags;
 	int ret;
 
 	if (c_data == NULL)
@@ -1660,12 +1679,14 @@
 	if (c_data->streaming)
 		streamoff_work(c_data);
 
-	spin_lock_irqsave(&dev->dev_slock, flags);
+	mutex_lock(&dev->dev_mutex);
 	atomic_dec(&dev->open_clients);
 	ret = atomic_read(&dev->open_clients);
-	spin_unlock_irqrestore(&dev->dev_slock, flags);
-	if (ret == 0)
+	mutex_unlock(&dev->dev_mutex);
+	if (ret == 0) {
 		vcap_disable(dev);
+		dev->vp_dummy_complete = false;
+	}
 	v4l2_fh_del(&c_data->vfh);
 	v4l2_fh_exit(&c_data->vfh);
 	vb2_queue_release(&c_data->vp_out_vidq);
@@ -1908,7 +1929,8 @@
 	atomic_set(&dev->vp_enabled, 0);
 	atomic_set(&dev->open_clients, 0);
 	dev->ddev = &pdev->dev;
-	spin_lock_init(&dev->dev_slock);
+	mutex_init(&dev->dev_mutex);
+	init_waitqueue_head(&dev->vp_dummy_waitq);
 	vcap_disable(dev);
 
 	dprintk(1, "Exit probe succesfully");
diff --git a/drivers/media/video/vcap_vp.c b/drivers/media/video/vcap_vp.c
index be1b4ff..b73185d 100644
--- a/drivers/media/video/vcap_vp.c
+++ b/drivers/media/video/vcap_vp.c
@@ -261,6 +261,12 @@
 	int rc;
 
 	irq = readl_relaxed(VCAP_VP_INT_STATUS);
+	if (dev->vp_dummy_event == true) {
+		writel_relaxed(irq, VCAP_VP_INT_CLEAR);
+		dev->vp_dummy_complete = true;
+		wake_up(&dev->vp_dummy_waitq);
+		return IRQ_HANDLED;
+	}
 
 	if (irq & 0x02000000) {
 		v4l2_evt.type = V4L2_EVENT_PRIVATE_START +
@@ -434,6 +440,8 @@
 		return -ENOEXEC;
 	}
 	buf = &c_data->vid_vp_action.bufNR;
+	if (!buf)
+		return -ENOMEM;
 
 	frame_size = c_data->vp_in_fmt.width * c_data->vp_in_fmt.height;
 	if (c_data->vp_in_fmt.pixfmt == V4L2_PIX_FMT_NV16)
@@ -442,7 +450,7 @@
 		tot_size = frame_size / 2 * 3;
 
 	buf->vaddr = kzalloc(tot_size, GFP_KERNEL);
-	if (!buf)
+	if (!buf->vaddr)
 		return -ENOMEM;
 
 	buf->paddr = virt_to_phys(buf->vaddr);
@@ -478,6 +486,74 @@
 	return;
 }
 
+int vp_dummy_event(struct vcap_client_data *c_data)
+{
+	struct vcap_dev *dev = c_data->dev;
+	unsigned int width, height;
+	unsigned long paddr;
+	void *temp;
+	uint32_t reg;
+	int rc = 0;
+
+	dprintk(2, "%s: Start VP dummy event\n", __func__);
+	temp = kzalloc(0x1200, GFP_KERNEL);
+	if (!temp) {
+		pr_err("%s: Failed to alloc mem", __func__);
+		return -ENOMEM;
+	}
+	paddr = virt_to_phys(temp);
+
+	width = c_data->vp_out_fmt.width;
+	height = c_data->vp_out_fmt.height;
+
+	c_data->vp_out_fmt.width = 0x3F;
+	c_data->vp_out_fmt.height = 0x16;
+
+	config_vp_format(c_data);
+	writel_relaxed(paddr, VCAP_VP_T1_Y_BASE_ADDR);
+	writel_relaxed(paddr + 0x2C0, VCAP_VP_T1_C_BASE_ADDR);
+	writel_relaxed(paddr + 0x440, VCAP_VP_T2_Y_BASE_ADDR);
+	writel_relaxed(paddr + 0x700, VCAP_VP_T2_C_BASE_ADDR);
+	writel_relaxed(paddr + 0x880, VCAP_VP_OUT_Y_BASE_ADDR);
+	writel_relaxed(paddr + 0xB40, VCAP_VP_OUT_C_BASE_ADDR);
+	writel_iowmb(paddr + 0x1100, VCAP_VP_MOTION_EST_ADDR);
+	writel_relaxed(4 << 20 | 0x2 << 4, VCAP_VP_IN_CONFIG);
+	writel_relaxed(4 << 20 | 0x1 << 4, VCAP_VP_OUT_CONFIG);
+
+	dev->vp_dummy_event = true;
+
+	writel_relaxed(0x01100101, VCAP_VP_INTERRUPT_ENABLE);
+	writel_iowmb(0x00000000, VCAP_VP_CTRL);
+	writel_iowmb(0x00030000, VCAP_VP_CTRL);
+
+	enable_irq(dev->vpirq->start);
+	rc = wait_event_interruptible_timeout(dev->vp_dummy_waitq,
+		dev->vp_dummy_complete, msecs_to_jiffies(50));
+	if (!rc && !dev->vp_dummy_complete) {
+		pr_err("%s: VP dummy event timeout", __func__);
+		rc = -ETIME;
+		writel_iowmb(0x00000000, VCAP_VP_CTRL);
+
+		writel_iowmb(0x00000001, VCAP_VP_SW_RESET);
+		writel_iowmb(0x00000000, VCAP_VP_SW_RESET);
+		dev->vp_dummy_complete = false;
+	}
+
+	writel_relaxed(0x00000000, VCAP_VP_INTERRUPT_ENABLE);
+	disable_irq(dev->vpirq->start);
+	dev->vp_dummy_event = false;
+
+	reg = readl_relaxed(VCAP_OFFSET(0x0D94));
+	writel_relaxed(reg, VCAP_OFFSET(0x0D9C));
+
+	c_data->vp_out_fmt.width = width;
+	c_data->vp_out_fmt.height = height;
+	kfree(temp);
+
+	dprintk(2, "%s: Exit VP dummy event\n", __func__);
+	return rc;
+}
+
 int kickoff_vp(struct vcap_client_data *c_data)
 {
 	struct vcap_dev *dev;
diff --git a/drivers/media/video/vcap_vp.h b/drivers/media/video/vcap_vp.h
index 5415e54..5c32903 100644
--- a/drivers/media/video/vcap_vp.h
+++ b/drivers/media/video/vcap_vp.h
@@ -100,5 +100,6 @@
 void deinit_nr_buf(struct vcap_client_data *c_data);
 int kickoff_vp(struct vcap_client_data *c_data);
 int continue_vp(struct vcap_client_data *c_data);
+int vp_dummy_event(struct vcap_client_data *c_data);
 
 #endif
diff --git a/drivers/mfd/pm8821-irq.c b/drivers/mfd/pm8821-irq.c
index 2dcc792..ff68c08 100644
--- a/drivers/mfd/pm8821-irq.c
+++ b/drivers/mfd/pm8821-irq.c
@@ -22,6 +22,7 @@
 #include <linux/mfd/pm8xxx/pm8821-irq.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
+#include <mach/mpm.h>
 
 #define PM8821_TOTAL_IRQ_MASTERS	2
 #define PM8821_BLOCKS_PER_MASTER	7
@@ -31,7 +32,7 @@
 #define PM8821_IRQ_MASK_REG_OFFSET	0x08
 #define SSBI_REG_ADDR_IRQ_MASTER0	0x30
 #define SSBI_REG_ADDR_IRQ_MASTER1	0xB0
-
+#define MPM_PIN_FOR_8821_IRQ		7
 #define SSBI_REG_ADDR_IRQ_IT_STATUS(master_base, block) (master_base + block)
 
 /*
@@ -410,8 +411,12 @@
 							devirq, rc);
 			kfree(chip);
 			return ERR_PTR(rc);
-		} else
+		} else{
 			irq_set_irq_wake(devirq, 1);
+			msm_mpm_set_pin_wake(MPM_PIN_FOR_8821_IRQ, 1);
+			msm_mpm_set_pin_type(MPM_PIN_FOR_8821_IRQ,
+				pdata->irq_trigger_flag);
+		}
 	}
 
 	return chip;
diff --git a/drivers/mfd/pm8xxx-spk.c b/drivers/mfd/pm8xxx-spk.c
index 297ddfa..2de70f4 100644
--- a/drivers/mfd/pm8xxx-spk.c
+++ b/drivers/mfd/pm8xxx-spk.c
@@ -162,7 +162,10 @@
 	val = pm8xxx_spk_read(PM8XXX_SPK_CTL1_REG_OFF);
 	if (val < 0)
 		return val;
-	val |= (enable << 3);
+	if (enable)
+		val |= (1 << 3);
+	else
+		val &= ~(1 << 3);
 	ret = pm8xxx_spk_write(PM8XXX_SPK_CTL1_REG_OFF, val);
 	if (!ret)
 		ret = pm8xxx_spk_bank_write(addr, 6, PWM_EN_MASK);
diff --git a/drivers/mmc/host/msm_sdcc.c b/drivers/mmc/host/msm_sdcc.c
index d833707..08f5ab9 100644
--- a/drivers/mmc/host/msm_sdcc.c
+++ b/drivers/mmc/host/msm_sdcc.c
@@ -20,6 +20,7 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 #include <linux/of.h>
+#include <linux/of_gpio.h>
 #include <linux/device.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
@@ -2092,7 +2093,14 @@
 
 	if (mrq->data && (mrq->data->flags & MMC_DATA_WRITE)) {
 		if (is_auto_prog_done(host)) {
-			if (!mrq->stop)
+			/*
+			 * Auto-prog done will be enabled for following cases:
+			 * mrq->sbc	|	mrq->stop
+			 * _____________|________________
+			 *	True	|	Don't care
+			 *	False	|	False (CMD24, ACMD25 use case)
+			 */
+			if (mrq->sbc || !mrq->stop)
 				host->curr.wait_for_auto_prog_done = true;
 		} else {
 			if ((mrq->cmd->opcode == SD_IO_RW_EXTENDED) ||
@@ -2529,6 +2537,12 @@
 
 	curr = host->plat->pin_data->gpio_data;
 	for (i = 0; i < curr->size; i++) {
+		if (!gpio_is_valid(curr->gpio[i].no)) {
+			rc = -EINVAL;
+			pr_err("%s: Invalid gpio = %d\n",
+				mmc_hostname(host->mmc), curr->gpio[i].no);
+			goto free_gpios;
+		}
 		if (enable) {
 			if (curr->gpio[i].is_always_on &&
 				curr->gpio[i].is_enabled)
@@ -2553,7 +2567,7 @@
 	goto out;
 
 free_gpios:
-	for (; i >= 0; i--) {
+	for (i--; i >= 0; i--) {
 		gpio_free(curr->gpio[i].no);
 		curr->gpio[i].is_enabled = false;
 	}
@@ -4778,6 +4792,298 @@
 	spin_unlock_irqrestore(&host->lock, flags);
 }
 
+/*
+ * msmsdcc_dt_get_array - Wrapper fn to read an array of 32 bit integers
+ *
+ * @dev:	device node from which the property value is to be read.
+ * @prop_name:	name of the property to be searched.
+ * @out_array:	filled array returned to caller
+ * @len:	filled array size returned to caller
+ * @size:	expected size of the array
+ *
+ * If expected "size" doesn't match with "len" an error is returned. If
+ * expected size is zero, the length of actual array is returned provided
+ * return value is zero.
+ *
+ * RETURNS:
+ * zero on success, negative error if failed.
+ */
+static int msmsdcc_dt_get_array(struct device *dev, const char *prop_name,
+		u32 **out_array, int *len, int size)
+{
+	int ret = 0;
+	u32 *array = NULL;
+	struct device_node *np = dev->of_node;
+
+	if (of_get_property(np, prop_name, len)) {
+		size_t sz;
+		sz = *len = *len / sizeof(*array);
+
+		if (sz > 0 && !(size > 0 && (sz != size))) {
+			array = devm_kzalloc(dev, sz * sizeof(*array),
+					GFP_KERNEL);
+			if (!array) {
+				dev_err(dev, "%s: no memory\n", prop_name);
+				ret = -ENOMEM;
+				goto out;
+			}
+
+			ret = of_property_read_u32_array(np, prop_name,
+					array, sz);
+			if (ret < 0) {
+				dev_err(dev, "%s: error reading array %d\n",
+						prop_name, ret);
+				goto out;
+			}
+		} else {
+			dev_err(dev, "%s invalid size\n", prop_name);
+			ret = -EINVAL;
+			goto out;
+		}
+	} else {
+		dev_err(dev, "%s not specified\n", prop_name);
+		ret = -EINVAL;
+		goto out;
+	}
+	*out_array = array;
+out:
+	if (ret)
+		*len = 0;
+	return ret;
+}
+
+static int msmsdcc_dt_get_pad_pull_info(struct device *dev, int id,
+		struct msm_mmc_pad_pull_data **pad_pull_data)
+{
+	int ret = 0, base = 0, len, i;
+	u32 *tmp;
+	struct msm_mmc_pad_pull_data *pull_data;
+	struct msm_mmc_pad_pull *pull;
+
+	switch (id) {
+	case 1:
+		base = TLMM_PULL_SDC1_CLK;
+		break;
+	case 2:
+		base = TLMM_PULL_SDC2_CLK;
+		break;
+	case 3:
+		base = TLMM_PULL_SDC3_CLK;
+		break;
+	case 4:
+		base = TLMM_PULL_SDC4_CLK;
+		break;
+	default:
+		dev_err(dev, "%s: Invalid slot id\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	pull_data = devm_kzalloc(dev, sizeof(struct msm_mmc_pad_pull_data),
+			GFP_KERNEL);
+	if (!pull_data) {
+		dev_err(dev, "No memory msm_mmc_pad_pull_data\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	pull_data->size = 3; /* array size for clk, cmd, data */
+
+	/* Allocate on, off configs for clk, cmd, data */
+	pull = devm_kzalloc(dev, 2 * pull_data->size *\
+			sizeof(struct msm_mmc_pad_pull), GFP_KERNEL);
+	if (!pull) {
+		dev_err(dev, "No memory for msm_mmc_pad_pull\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	pull_data->on = pull;
+	pull_data->off = pull + pull_data->size;
+
+	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-pull-on",
+			&tmp, &len, pull_data->size);
+	if (!ret) {
+		for (i = 0; i < len; i++) {
+			pull_data->on[i].no = base + i;
+			pull_data->on[i].val = tmp[i];
+			dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+					i, pull_data->on[i].val);
+		}
+	} else {
+		goto err;
+	}
+
+	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-pull-off",
+			&tmp, &len, pull_data->size);
+	if (!ret) {
+		for (i = 0; i < len; i++) {
+			pull_data->off[i].no = base + i;
+			pull_data->off[i].val = tmp[i];
+			dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+					i, pull_data->off[i].val);
+		}
+	} else {
+		goto err;
+	}
+
+	*pad_pull_data = pull_data;
+err:
+	return ret;
+}
+
+static int msmsdcc_dt_get_pad_drv_info(struct device *dev, int id,
+		struct msm_mmc_pad_drv_data **pad_drv_data)
+{
+	int ret = 0, base = 0, len, i;
+	u32 *tmp;
+	struct msm_mmc_pad_drv_data *drv_data;
+	struct msm_mmc_pad_drv *drv;
+
+	switch (id) {
+	case 1:
+		base = TLMM_HDRV_SDC1_CLK;
+		break;
+	case 2:
+		base = TLMM_HDRV_SDC2_CLK;
+		break;
+	case 3:
+		base = TLMM_HDRV_SDC3_CLK;
+		break;
+	case 4:
+		base = TLMM_HDRV_SDC4_CLK;
+		break;
+	default:
+		dev_err(dev, "%s: Invalid slot id\n", __func__);
+		ret = -EINVAL;
+		goto err;
+	}
+
+	drv_data = devm_kzalloc(dev, sizeof(struct msm_mmc_pad_drv_data),
+			GFP_KERNEL);
+	if (!drv_data) {
+		dev_err(dev, "No memory for msm_mmc_pad_drv_data\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	drv_data->size = 3; /* array size for clk, cmd, data */
+
+	/* Allocate on, off configs for clk, cmd, data */
+	drv = devm_kzalloc(dev, 2 * drv_data->size *\
+			sizeof(struct msm_mmc_pad_drv), GFP_KERNEL);
+	if (!drv) {
+		dev_err(dev, "No memory msm_mmc_pad_drv\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+	drv_data->on = drv;
+	drv_data->off = drv + drv_data->size;
+
+	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-drv-on",
+			&tmp, &len, drv_data->size);
+	if (!ret) {
+		for (i = 0; i < len; i++) {
+			drv_data->on[i].no = base + i;
+			drv_data->on[i].val = tmp[i];
+			dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+					i, drv_data->on[i].val);
+		}
+	} else {
+		goto err;
+	}
+
+	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-pad-drv-off",
+			&tmp, &len, drv_data->size);
+	if (!ret) {
+		for (i = 0; i < len; i++) {
+			drv_data->off[i].no = base + i;
+			drv_data->off[i].val = tmp[i];
+			dev_dbg(dev, "%s: val[%d]=0x%x\n", __func__,
+					i, drv_data->off[i].val);
+		}
+	} else {
+		goto err;
+	}
+
+	*pad_drv_data = drv_data;
+err:
+	return ret;
+}
+
+static int msmsdcc_dt_parse_gpio_info(struct device *dev,
+		struct mmc_platform_data *pdata)
+{
+	int ret = 0, id = 0, cnt, i;
+	struct msm_mmc_pin_data *pin_data;
+	struct device_node *np = dev->of_node;
+
+	pin_data = devm_kzalloc(dev, sizeof(*pin_data), GFP_KERNEL);
+	if (!pin_data) {
+		dev_err(dev, "No memory for pin_data\n");
+		ret = -ENOMEM;
+		goto err;
+	}
+
+	cnt = of_gpio_count(np);
+	if (cnt > 0) {
+		pin_data->is_gpio = true;
+
+		pin_data->gpio_data = devm_kzalloc(dev,
+				sizeof(struct msm_mmc_gpio_data), GFP_KERNEL);
+		if (!pin_data->gpio_data) {
+			dev_err(dev, "No memory for gpio_data\n");
+			ret = -ENOMEM;
+			goto err;
+		}
+		pin_data->gpio_data->size = cnt;
+		pin_data->gpio_data->gpio = devm_kzalloc(dev,
+				cnt * sizeof(struct msm_mmc_gpio), GFP_KERNEL);
+		if (!pin_data->gpio_data->gpio) {
+			dev_err(dev, "No memory for gpio\n");
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		for (i = 0; i < cnt; i++) {
+			const char *name = NULL;
+			char result[32];
+			pin_data->gpio_data->gpio[i].no = of_get_gpio(np, i);
+			of_property_read_string_index(np,
+					"qcom,sdcc-gpio-names", i, &name);
+
+			snprintf(result, 32, "%s-%s",
+					dev_name(dev), name ? name : "?");
+			pin_data->gpio_data->gpio[i].name = result;
+			dev_dbg(dev, "%s: gpio[%s] = %d\n", __func__,
+					pin_data->gpio_data->gpio[i].name,
+					pin_data->gpio_data->gpio[i].no);
+		}
+	} else {
+		pin_data->pad_data = devm_kzalloc(dev,
+				sizeof(struct msm_mmc_pad_data), GFP_KERNEL);
+		if (!pin_data->pad_data) {
+			dev_err(dev, "No memory for pin_data->pad_data\n");
+			ret = -ENOMEM;
+			goto err;
+		}
+
+		of_property_read_u32(np, "cell-index", &id);
+
+		ret = msmsdcc_dt_get_pad_pull_info(dev, id,
+				&pin_data->pad_data->pull);
+		if (ret)
+			goto err;
+		ret = msmsdcc_dt_get_pad_drv_info(dev, id,
+				&pin_data->pad_data->drv);
+		if (ret)
+			goto err;
+	}
+
+	pdata->pin_data = pin_data;
+err:
+	if (ret)
+		dev_err(dev, "%s failed with err %d\n", __func__, ret);
+	return ret;
+}
+
 #define MAX_PROP_SIZE 32
 static int msmsdcc_dt_parse_vreg_info(struct device *dev,
 		struct msm_mmc_reg_data **vreg_data, const char *vreg_name)
@@ -4867,29 +5173,10 @@
 		pdata->mmc_bus_width = 0;
 	}
 
-	if (of_get_property(np, "qcom,sdcc-sup-voltages", &sup_volt_len)) {
-		size_t sz;
-		sz = sup_volt_len / sizeof(*sup_voltages);
-		if (sz > 0) {
-			sup_voltages = devm_kzalloc(dev,
-					sz * sizeof(*sup_voltages), GFP_KERNEL);
-			if (!sup_voltages) {
-				dev_err(dev, "No memory for supported voltage\n");
-				goto err;
-			}
-
-			ret = of_property_read_u32_array(np,
-				"qcom,sdcc-sup-voltages", sup_voltages, sz);
-			if (ret < 0) {
-				dev_err(dev, "error while reading voltage"
-						"ranges %d\n", ret);
-				goto err;
-			}
-		} else {
-			dev_err(dev, "No supported voltages\n");
-			goto err;
-		}
-		for (i = 0; i < sz; i += 2) {
+	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-sup-voltages",
+			&sup_voltages, &sup_volt_len, 0);
+	if (!ret) {
+		for (i = 0; i < sup_volt_len; i += 2) {
 			u32 mask;
 
 			mask = mmc_vddrange_to_ocrmask(sup_voltages[i],
@@ -4899,37 +5186,13 @@
 			pdata->ocr_mask |= mask;
 		}
 		dev_dbg(dev, "OCR mask=0x%x\n", pdata->ocr_mask);
-	} else {
-		dev_err(dev, "Supported voltage range not specified\n");
 	}
 
-	if (of_get_property(np, "qcom,sdcc-clk-rates", &clk_table_len)) {
-		size_t sz;
-		sz = clk_table_len / sizeof(*clk_table);
-
-		if (sz > 0) {
-			clk_table = devm_kzalloc(dev, sz * sizeof(*clk_table),
-					GFP_KERNEL);
-			if (!clk_table) {
-				dev_err(dev, "No memory for clock table\n");
-				goto err;
-			}
-
-			ret = of_property_read_u32_array(np,
-				"qcom,sdcc-clk-rates", clk_table, sz);
-			if (ret < 0) {
-				dev_err(dev, "error while reading clk"
-						"table %d\n", ret);
-				goto err;
-			}
-		} else {
-			dev_err(dev, "clk_table not specified\n");
-			goto err;
-		}
+	ret = msmsdcc_dt_get_array(dev, "qcom,sdcc-clk-rates",
+			&clk_table, &clk_table_len, 0);
+	if (!ret) {
 		pdata->sup_clk_table = clk_table;
-		pdata->sup_clk_cnt = sz;
-	} else {
-		dev_err(dev, "Supported clock rates not specified\n");
+		pdata->sup_clk_cnt = clk_table_len;
 	}
 
 	pdata->vreg_data = devm_kzalloc(dev,
@@ -4947,6 +5210,9 @@
 			&pdata->vreg_data->vdd_io_data, "vdd-io"))
 		goto err;
 
+	if (msmsdcc_dt_parse_gpio_info(dev, pdata))
+		goto err;
+
 	len = of_property_count_strings(np, "qcom,sdcc-bus-speed-mode");
 
 	for (i = 0; i < len; i++) {
diff --git a/drivers/slimbus/slimbus.c b/drivers/slimbus/slimbus.c
index 36414e0..8cef99e 100644
--- a/drivers/slimbus/slimbus.c
+++ b/drivers/slimbus/slimbus.c
@@ -2778,6 +2778,9 @@
 			}
 			if (slc->def > 0)
 				slc->def--;
+			/* Disconnect source port to free it up */
+			if (SLIM_HDL_TO_LA(slc->srch) == sb->laddr)
+				slc->srch = 0;
 			if (slc->def == 0)
 				ret = add_pending_ch(&sb->mark_removal, chan);
 			if (ret)
diff --git a/drivers/tty/serial/msm_serial_hs.c b/drivers/tty/serial/msm_serial_hs.c
index 083ed19..1904706 100644
--- a/drivers/tty/serial/msm_serial_hs.c
+++ b/drivers/tty/serial/msm_serial_hs.c
@@ -174,7 +174,7 @@
 #define UARTDM_TX_BUF_SIZE UART_XMIT_SIZE
 #define UARTDM_RX_BUF_SIZE 512
 #define RETRY_TIMEOUT 5
-#define UARTDM_NR 2
+#define UARTDM_NR 5
 
 static struct dentry *debug_base;
 static struct msm_hs_port q_uart_port[UARTDM_NR];
diff --git a/drivers/video/msm/external_common.c b/drivers/video/msm/external_common.c
index 36c8749..9f301fe 100644
--- a/drivers/video/msm/external_common.c
+++ b/drivers/video/msm/external_common.c
@@ -1858,6 +1858,9 @@
 	/* EDID_BLOCK_SIZE[0x80] Each page size in the EDID ROM */
 	uint8 edid_buf[0x80 * 4];
 
+	external_common_state->pt_scan_info = 0;
+	external_common_state->it_scan_info = 0;
+	external_common_state->ce_scan_info = 0;
 	external_common_state->preferred_video_format = 0;
 	external_common_state->present_3d = 0;
 	memset(&external_common_state->disp_mode_list, 0,
diff --git a/drivers/video/msm/mdp4_overlay.c b/drivers/video/msm/mdp4_overlay.c
index d045e69..703d65d 100644
--- a/drivers/video/msm/mdp4_overlay.c
+++ b/drivers/video/msm/mdp4_overlay.c
@@ -2558,17 +2558,19 @@
 	struct msm_fb_data_type *mfd, uint32 perf_level)
 {
 	u32 clk_rate = mfd->panel_info.clk_rate;
-	u32 pull_mode = 0, use_blt = 0;
+	u32 blt_chq_req  = 0, use_blt = 0;
 
-	if (mfd->panel_info.type == MIPI_VIDEO_PANEL)
+	if ((mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
+		 (mfd->panel_info.type == MIPI_CMD_PANEL))
 		clk_rate = (&mfd->panel_info.mipi)->dsi_pclk_rate;
 
 	if ((mfd->panel_info.type == LCDC_PANEL) ||
 	    (mfd->panel_info.type == MIPI_VIDEO_PANEL) ||
-	    (mfd->panel_info.type == DTV_PANEL))
-		pull_mode = 1;
+	    (mfd->panel_info.type == DTV_PANEL) ||
+	    (mfd->panel_info.type == MIPI_CMD_PANEL))
+		blt_chq_req = 1;
 
-	if (pull_mode && (req->src_rect.h > req->dst_rect.h ||
+	if (blt_chq_req && (req->src_rect.h > req->dst_rect.h ||
 		req->src_rect.w > req->dst_rect.w)) {
 		if (mdp4_overlay_validate_downscale(req, mfd, perf_level,
 			clk_rate))
@@ -2798,10 +2800,15 @@
 		mdp4_mixer_stage_down(pipe);
 
 		if (pipe->mixer_num == MDP4_MIXER0) {
+			mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
+			mdp4_overlay_update_blt_mode(mfd);
 #ifdef CONFIG_FB_MSM_MIPI_DSI
 			if (ctrl->panel_mode & MDP4_PANEL_DSI_CMD) {
-				if (mfd->panel_power_on)
+				if (mfd->panel_power_on) {
 					mdp4_dsi_cmd_overlay_restore();
+					mdp4_dsi_cmd_dma_busy_wait(mfd);
+					mdp4_dsi_blt_dmap_busy_wait(mfd);
+				}
 			} else if (ctrl->panel_mode & MDP4_PANEL_DSI_VIDEO) {
 				pipe->flags &= ~MDP_OV_PLAY_NOWAIT;
 				if (mfd->panel_power_on)
@@ -2810,8 +2817,11 @@
 			}
 #else
 			if (ctrl->panel_mode & MDP4_PANEL_MDDI) {
-				if (mfd->panel_power_on)
+				if (mfd->panel_power_on) {
 					mdp4_mddi_overlay_restore();
+					mdp4_mddi_dma_busy_wait(mfd);
+					mdp4_mddi_blt_dmap_busy_wait(mfd);
+				}
 			}
 #endif
 			else if (ctrl->panel_mode & MDP4_PANEL_LCDC) {
@@ -2819,8 +2829,6 @@
 				if (mfd->panel_power_on)
 					mdp4_overlay_lcdc_vsync_push(mfd, pipe);
 			}
-			mfd->use_ov0_blt &= ~(1 << (pipe->pipe_ndx-1));
-			mdp4_overlay_update_blt_mode(mfd);
 			if (!mfd->use_ov0_blt)
 				mdp4_free_writeback_buf(mfd, MDP4_MIXER0);
 		} else {	/* mixer1, DTV, ATV */
diff --git a/drivers/video/msm/mdp4_overlay_dtv.c b/drivers/video/msm/mdp4_overlay_dtv.c
index b90812f..b9d6037 100644
--- a/drivers/video/msm/mdp4_overlay_dtv.c
+++ b/drivers/video/msm/mdp4_overlay_dtv.c
@@ -698,11 +698,7 @@
 	struct mdp4_overlay_pipe *pipe;
 	if (!mfd->panel_power_on)
 		return;
-	if (!dtv_pipe) {
-		pr_debug("%s: no mixer1 base layer pipe allocated!\n",
-			 __func__);
-		return;
-	}
+
 	mutex_lock(&mfd->dma->ov_mutex);
 	if (dtv_pipe == NULL) {
 		if (mdp4_overlay_dtv_set(mfd, NULL)) {
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 36cbbbd..176f56b 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -642,6 +642,12 @@
 	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
+	if (hdmi_prim_display) {
+		MSM_FB_INFO("%s: hdmi primary handles early suspend only\n",
+			__func__);
+		return 0;
+	}
+
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
@@ -667,6 +673,12 @@
 	struct msm_fb_panel_data *pdata = NULL;
 	int ret = 0;
 
+	if (hdmi_prim_display) {
+		MSM_FB_INFO("%s: hdmi primary handles early resume only\n",
+			__func__);
+		return 0;
+	}
+
 	if ((!mfd) || (mfd->key != MFD_KEY))
 		return 0;
 
@@ -691,7 +703,8 @@
 	.runtime_suspend = msm_fb_runtime_suspend,
 	.runtime_resume = msm_fb_runtime_resume,
 	.runtime_idle = msm_fb_runtime_idle,
-#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL))
+#if (defined(CONFIG_SUSPEND) && defined(CONFIG_FB_MSM_HDMI_MSM_PANEL) && \
+	!defined(CONFIG_FB_MSM_HDMI_AS_PRIMARY))
 	.suspend = msm_fb_ext_suspend,
 	.resume = msm_fb_ext_resume,
 #endif
@@ -725,7 +738,9 @@
 static void msmfb_early_suspend(struct early_suspend *h)
 {
 	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						    early_suspend);
+						early_suspend);
+	struct msm_fb_panel_data *pdata = NULL;
+
 #if defined(CONFIG_FB_MSM_MDP303)
 	/*
 	* For MDP with overlay, set framebuffer with black pixels
@@ -743,12 +758,37 @@
 	}
 #endif
 	msm_fb_suspend_sub(mfd);
+
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+	if (hdmi_prim_display &&
+		(mfd->panel_info.type == HDMI_PANEL ||
+		 mfd->panel_info.type == DTV_PANEL)) {
+		/* Turn off the HPD circuitry */
+		if (pdata->power_ctrl) {
+			MSM_FB_INFO("%s: Turning off HPD circuitry\n",
+				__func__);
+			pdata->power_ctrl(FALSE);
+		}
+	}
 }
 
 static void msmfb_early_resume(struct early_suspend *h)
 {
 	struct msm_fb_data_type *mfd = container_of(h, struct msm_fb_data_type,
-						    early_suspend);
+						early_suspend);
+	struct msm_fb_panel_data *pdata = NULL;
+
+	pdata = (struct msm_fb_panel_data *)mfd->pdev->dev.platform_data;
+	if (hdmi_prim_display &&
+		(mfd->panel_info.type == HDMI_PANEL ||
+		 mfd->panel_info.type == DTV_PANEL)) {
+		/* Turn on the HPD circuitry */
+		if (pdata->power_ctrl) {
+			MSM_FB_INFO("%s: Turning on HPD circuitry\n", __func__);
+			pdata->power_ctrl(TRUE);
+		}
+	}
+
 	msm_fb_resume_sub(mfd);
 }
 #endif
@@ -1435,7 +1475,7 @@
 	ret = 0;
 
 #ifdef CONFIG_HAS_EARLYSUSPEND
-	if (mfd->panel_info.type != DTV_PANEL) {
+	if (hdmi_prim_display || mfd->panel_info.type != DTV_PANEL) {
 		mfd->early_suspend.suspend = msmfb_early_suspend;
 		mfd->early_suspend.resume = msmfb_early_resume;
 		mfd->early_suspend.level = EARLY_SUSPEND_LEVEL_DISABLE_FB - 2;
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8aeadf6..6af2a3e 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -645,6 +645,11 @@
 		*(.security_initcall.init)				\
 		VMLINUX_SYMBOL(__security_initcall_end) = .;
 
+#define COMPAT_EXPORTS							\
+		VMLINUX_SYMBOL(__compat_exports_start) = .;		\
+		*(.exportcompat.init)					\
+		VMLINUX_SYMBOL(__compat_exports_end) = .;
+
 #ifdef CONFIG_BLK_DEV_INITRD
 #define INIT_RAM_FS							\
 	. = ALIGN(4);							\
diff --git a/include/linux/input/lis3dh.h b/include/linux/input/lis3dh.h
new file mode 100644
index 0000000..f081b06
--- /dev/null
+++ b/include/linux/input/lis3dh.h
@@ -0,0 +1,85 @@
+
+/******************** (C) COPYRIGHT 2010 STMicroelectronics ********************
+*
+* File Name          : lis3dh_misc.h
+* Authors            : MH - C&I BU - Application Team
+*		     : Matteo Dameno (matteo.dameno@st.com)
+*		     : Carmine Iascone (carmine.iascone@st.com)
+*                    : Samuel Huo (samuel.huo@st.com)
+* Version            : V 1.1.0
+* Date               : 07/10/2012
+*
+********************************************************************************
+*
+* This program is free software; you can redistribute it and/or modify
+* it under the terms of the GNU General Public License version 2 as
+* published by the Free Software Foundation.
+*
+* THE PRESENT SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES
+* OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED, FOR THE SOLE
+* PURPOSE TO SUPPORT YOUR APPLICATION DEVELOPMENT.
+* AS A RESULT, STMICROELECTRONICS SHALL NOT BE HELD LIABLE FOR ANY DIRECT,
+* INDIRECT OR CONSEQUENTIAL DAMAGES WITH RESPECT TO ANY CLAIMS ARISING FROM THE
+* CONTENT OF SUCH SOFTWARE AND/OR THE USE MADE BY CUSTOMERS OF THE CODING
+* INFORMATION CONTAINED HEREIN IN CONNECTION WITH THEIR PRODUCTS.
+*
+* THIS SOFTWARE IS SPECIFICALLY DESIGNED FOR EXCLUSIVE USE WITH ST PARTS.
+*
+*******************************************************************************/
+
+#ifndef	__LIS3DH_H__
+#define	__LIS3DH_H__
+
+
+#define SAD0L			0x00
+#define SAD0H			0x01
+#define LIS3DH_ACC_I2C_SADROOT	0x0C
+#define LIS3DH_ACC_I2C_SAD_L	((LIS3DH_ACC_I2C_SADROOT<<1)|SAD0L)
+#define LIS3DH_ACC_I2C_SAD_H	((LIS3DH_ACC_I2C_SADROOT<<1)|SAD0H)
+#define	LIS3DH_ACC_DEV_NAME	"lis3dh_acc"
+
+
+/************************************************/
+/*	Accelerometer defines section		*/
+/************************************************/
+
+/* Accelerometer Sensor Full Scale */
+#define	LIS3DH_ACC_FS_MASK		0x30
+#define LIS3DH_ACC_G_2G			0x00
+#define LIS3DH_ACC_G_4G			0x10
+#define LIS3DH_ACC_G_8G			0x20
+#define LIS3DH_ACC_G_16G		0x30
+
+
+#ifdef	__KERNEL__
+struct lis3dh_acc_platform_data {
+	int poll_interval;
+	int min_interval;
+
+	u8 g_range;
+
+	u8 axis_map_x;
+	u8 axis_map_y;
+	u8 axis_map_z;
+
+	u8 negate_x;
+	u8 negate_y;
+	u8 negate_z;
+
+	int (*init)(void);
+	void (*exit)(void);
+	int (*power_on)(void);
+	int (*power_off)(void);
+
+	/* set gpio_int[1,2] either to the choosen gpio pin number or to -EINVAL
+	 * if leaved unconnected
+	 */
+	int gpio_int1;
+	int gpio_int2;
+};
+#endif	/* __KERNEL__ */
+
+#endif	/* __LIS3DH_H__ */
+
+
+
diff --git a/include/media/vcap_v4l2.h b/include/media/vcap_v4l2.h
index f7d1e6b..9719aa6 100644
--- a/include/media/vcap_v4l2.h
+++ b/include/media/vcap_v4l2.h
@@ -158,10 +158,13 @@
 	atomic_t			    vc_enabled;
 	atomic_t			    vp_enabled;
 
-	spinlock_t				dev_slock;
+	struct mutex			dev_mutex;
 	atomic_t			    open_clients;
 	bool					vc_resource;
 	bool					vp_resource;
+	bool					vp_dummy_event;
+	bool					vp_dummy_complete;
+	wait_queue_head_t		vp_dummy_waitq;
 
 	struct workqueue_struct	*vcap_wq;
 	struct vp_work_t		vp_work;
diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h
index eb89f4b..3526e29 100644
--- a/include/net/bluetooth/hci.h
+++ b/include/net/bluetooth/hci.h
@@ -1334,6 +1334,15 @@
 	__u8	 data[0];
 } __packed;
 
+#define HCI_EV_LE_CONN_UPDATE_COMPLETE	0x03
+struct hci_ev_le_conn_update_complete {
+	__u8     status;
+	__le16   handle;
+	__le16   interval;
+	__le16   latency;
+	__le16   supervision_timeout;
+} __packed;
+
 #define HCI_EV_LE_LTK_REQ		0x05
 struct hci_ev_le_ltk_req {
 	__le16	handle;
diff --git a/include/net/bluetooth/hci_core.h b/include/net/bluetooth/hci_core.h
index 47b856c..22428c1 100644
--- a/include/net/bluetooth/hci_core.h
+++ b/include/net/bluetooth/hci_core.h
@@ -1033,6 +1033,8 @@
 int mgmt_connectable(u16 index, u8 connectable);
 int mgmt_new_key(u16 index, struct link_key *key, u8 bonded);
 int mgmt_connected(u16 index, bdaddr_t *bdaddr, u8 le);
+int mgmt_le_conn_params(u16 index, bdaddr_t *bdaddr, u16 interval,
+						u16 latency, u16 timeout);
 int mgmt_disconnected(u16 index, bdaddr_t *bdaddr);
 int mgmt_disconnect_failed(u16 index);
 int mgmt_connect_failed(u16 index, bdaddr_t *bdaddr, u8 status);
diff --git a/include/net/bluetooth/mgmt.h b/include/net/bluetooth/mgmt.h
index e34c425..3048339 100644
--- a/include/net/bluetooth/mgmt.h
+++ b/include/net/bluetooth/mgmt.h
@@ -379,3 +379,11 @@
 	bdaddr_t	bdaddr;
 	__s8			rssi;
 } __packed;
+
+#define MGMT_EV_LE_CONN_PARAMS		0xF000
+struct mgmt_ev_le_conn_params {
+	bdaddr_t bdaddr;
+	__u16 interval;
+	__u16 latency;
+	__u16 timeout;
+} __packed;
diff --git a/lib/spinlock_debug.c b/lib/spinlock_debug.c
index c1906e4..d0ec4f3 100644
--- a/lib/spinlock_debug.c
+++ b/lib/spinlock_debug.c
@@ -118,10 +118,6 @@
 		/* lockup suspected: */
 		if (print_once) {
 			print_once = 0;
-			printk(KERN_EMERG "BUG: spinlock lockup on CPU#%d, "
-					"%s/%d, %ps\n",
-				raw_smp_processor_id(), current->comm,
-				task_pid_nr(current), lock);
 			spin_dump(lock, "lockup");
 #ifdef CONFIG_SMP
 			trigger_all_cpu_backtrace();
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index eb5a0cc..f83c108 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -3191,6 +3191,10 @@
 	conn->state = BT_CONNECTED;
 	conn->disc_timeout = HCI_DISCONN_TIMEOUT;
 	mgmt_connected(hdev->id, &ev->bdaddr, 1);
+	mgmt_le_conn_params(hdev->id, &ev->bdaddr,
+			__le16_to_cpu(ev->interval),
+			__le16_to_cpu(ev->latency),
+			__le16_to_cpu(ev->supervision_timeout));
 
 	hci_conn_hold(conn);
 	hci_conn_hold_device(conn);
@@ -3202,6 +3206,37 @@
 	hci_dev_unlock(hdev);
 }
 
+static inline void hci_le_conn_update_complete_evt(struct hci_dev *hdev,
+							struct sk_buff *skb)
+{
+	struct hci_ev_le_conn_update_complete *ev = (void *) skb->data;
+	struct hci_conn *conn;
+
+	BT_DBG("%s status %d", hdev->name, ev->status);
+
+	hci_dev_lock(hdev);
+
+	conn = hci_conn_hash_lookup_handle(hdev,
+				__le16_to_cpu(ev->handle));
+	if (conn == NULL) {
+		BT_ERR("Unknown connection update");
+		goto unlock;
+	}
+
+	if (ev->status) {
+		BT_ERR("Connection update unsuccessful");
+		goto unlock;
+	}
+
+	mgmt_le_conn_params(hdev->id, &conn->dst,
+			__le16_to_cpu(ev->interval),
+			__le16_to_cpu(ev->latency),
+			__le16_to_cpu(ev->supervision_timeout));
+
+unlock:
+	hci_dev_unlock(hdev);
+}
+
 static inline void hci_le_ltk_request_evt(struct hci_dev *hdev,
 						struct sk_buff *skb)
 {
@@ -3271,6 +3306,10 @@
 		hci_le_conn_complete_evt(hdev, skb);
 		break;
 
+	case HCI_EV_LE_CONN_UPDATE_COMPLETE:
+		hci_le_conn_update_complete_evt(hdev, skb);
+		break;
+
 	case HCI_EV_LE_LTK_REQ:
 		hci_le_ltk_request_evt(hdev, skb);
 		break;
diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c
index dce8491..72234c1 100644
--- a/net/bluetooth/mgmt.c
+++ b/net/bluetooth/mgmt.c
@@ -2633,6 +2633,20 @@
 	return mgmt_event(MGMT_EV_CONNECTED, index, &ev, sizeof(ev), NULL);
 }
 
+int mgmt_le_conn_params(u16 index, bdaddr_t *bdaddr, u16 interval,
+						u16 latency, u16 timeout)
+{
+	struct mgmt_ev_le_conn_params ev;
+
+	bacpy(&ev.bdaddr, bdaddr);
+	ev.interval = interval;
+	ev.latency = latency;
+	ev.timeout = timeout;
+
+	return mgmt_event(MGMT_EV_LE_CONN_PARAMS, index, &ev, sizeof(ev),
+									NULL);
+}
+
 static void disconnect_rsp(struct pending_cmd *cmd, void *data)
 {
 	struct mgmt_cp_disconnect *cp = cmd->param;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 6bbb34b..276ff71 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -711,10 +711,6 @@
 invalid_key:
 	hcon->sec_req = FALSE;
 
-	/* Switch to Pairing Connection Parameters */
-	hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL, SMP_MAX_CONN_INTERVAL,
-			SMP_MAX_CONN_LATENCY, SMP_SUPERVISION_TIMEOUT);
-
 	skb_pull(skb, sizeof(*rp));
 
 	memset(&cp, 0, sizeof(cp));
@@ -776,11 +772,6 @@
 	if (hcon->link_mode & HCI_LM_MASTER) {
 		struct smp_cmd_pairing cp;
 
-		/* Switch to Pairing Connection Parameters */
-		hci_le_conn_update(hcon, SMP_MIN_CONN_INTERVAL,
-				SMP_MAX_CONN_INTERVAL, SMP_MAX_CONN_LATENCY,
-				SMP_SUPERVISION_TIMEOUT);
-
 		build_pairing_cmd(conn, &cp, NULL, authreq);
 		hcon->preq[0] = SMP_CMD_PAIRING_REQ;
 		memcpy(&hcon->preq[1], &cp, sizeof(cp));
diff --git a/sound/soc/codecs/wcd9304.c b/sound/soc/codecs/wcd9304.c
index 70d9fa9..bbf1b89 100644
--- a/sound/soc/codecs/wcd9304.c
+++ b/sound/soc/codecs/wcd9304.c
@@ -848,14 +848,14 @@
 
 	if (enable) {
 		sitar->adc_count++;
-		snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS, 0xE0, 0xE0);
-
+		snd_soc_update_bits(codec, SITAR_A_CDC_CLK_OTHR_CTL,
+				0x02, 0x02);
 	} else {
 		sitar->adc_count--;
 		if (!sitar->adc_count) {
 			if (!sitar->mbhc_polling_active)
-				snd_soc_update_bits(codec, SITAR_A_TX_COM_BIAS,
-					0xE0, 0x0);
+				snd_soc_update_bits(codec,
+					SITAR_A_CDC_CLK_OTHR_CTL, 0xE0, 0x0);
 		}
 	}
 }
diff --git a/sound/soc/codecs/wcd9310.c b/sound/soc/codecs/wcd9310.c
index 3164a9b..68892c1 100644
--- a/sound/soc/codecs/wcd9310.c
+++ b/sound/soc/codecs/wcd9310.c
@@ -7312,14 +7312,13 @@
 }
 EXPORT_SYMBOL_GPL(tabla_hs_detect);
 
-static unsigned long slimbus_value;
-
 static irqreturn_t tabla_slimbus_irq(int irq, void *data)
 {
 	struct tabla_priv *priv = data;
 	struct snd_soc_codec *codec = priv->codec;
 	struct tabla_priv *tabla_p = snd_soc_codec_get_drvdata(codec);
 	int i, j, port_id, k, ch_mask_temp;
+	unsigned long slimbus_value;
 	u8 val;
 
 	for (i = 0; i < WCD9XXX_SLIM_NUM_PORT_REG; i++) {
@@ -7352,7 +7351,8 @@
 			}
 		}
 		wcd9xxx_interface_reg_write(codec->control_data,
-			TABLA_SLIM_PGD_PORT_INT_CLR0 + i, 0xFF);
+			TABLA_SLIM_PGD_PORT_INT_CLR0 + i, slimbus_value);
+		val = 0x0;
 	}
 
 	return IRQ_HANDLED;
diff --git a/sound/soc/msm/msm8930.c b/sound/soc/msm/msm8930.c
index a0cad55..374e875 100644
--- a/sound/soc/msm/msm8930.c
+++ b/sound/soc/msm/msm8930.c
@@ -877,7 +877,7 @@
 		.name = "MSM8930 Media2",
 		.stream_name = "MultiMedia2",
 		.cpu_dai_name	= "MultiMedia2",
-		.platform_name  = "msm-pcm-dsp",
+		.platform_name  = "msm-multi-ch-pcm-dsp",
 		.dynamic = 1,
 		.codec_dai_name = "snd-soc-dummy-dai",
 		.codec_name = "snd-soc-dummy",
diff --git a/sound/soc/msm/msm8974.c b/sound/soc/msm/msm8974.c
index b110250..9c57161 100644
--- a/sound/soc/msm/msm8974.c
+++ b/sound/soc/msm/msm8974.c
@@ -678,6 +678,21 @@
 		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA3,
 	},
 	{
+		.name = "MSM8974 Compr",
+		.stream_name = "COMPR",
+		.cpu_dai_name	= "MultiMedia4",
+		.platform_name  = "msm-compr-dsp",
+		.dynamic = 1,
+		.trigger = {SND_SOC_DPCM_TRIGGER_POST,
+			 SND_SOC_DPCM_TRIGGER_POST},
+		.codec_dai_name = "snd-soc-dummy-dai",
+		.codec_name = "snd-soc-dummy",
+		.ignore_suspend = 1,
+		.ignore_pmdown_time = 1,
+		 /* this dainlink has playback support */
+		.be_id = MSM_FRONTEND_DAI_MULTIMEDIA4,
+	},
+	{
 		.name = "AUXPCM Hostless",
 		.stream_name = "AUXPCM Hostless",
 		.cpu_dai_name   = "AUXPCM_HOSTLESS",
diff --git a/sound/soc/msm/qdsp6/q6voice.c b/sound/soc/msm/qdsp6/q6voice.c
index 1cf32aa..3791f24 100644
--- a/sound/soc/msm/qdsp6/q6voice.c
+++ b/sound/soc/msm/qdsp6/q6voice.c
@@ -2344,6 +2344,9 @@
 	/* send stop voice cmd */
 	voice_send_stop_voice_cmd(v);
 
+	/* Clear mute setting */
+	v->dev_tx.mute = common.default_mute_val;
+
 	/* detach VOCPROC and wait for response from mvm */
 	mvm_d_vocproc_cmd.hdr.hdr_field = APR_HDR_FIELD(APR_MSG_TYPE_SEQ_CMD,
 						APR_HDR_LEN(APR_HDR_SIZE),
@@ -3106,7 +3109,9 @@
 
 	v->dev_tx.mute = mute;
 
-	if (v->voc_state == VOC_RUN)
+	if ((v->voc_state == VOC_RUN) ||
+	    (v->voc_state == VOC_CHANGE) ||
+	    (v->voc_state == VOC_STANDBY))
 		ret = voice_send_mute_cmd(v);
 
 	mutex_unlock(&v->lock);
@@ -3312,7 +3317,9 @@
 
 	v->dev_rx.volume = vol_idx;
 
-	if (v->voc_state == VOC_RUN)
+	if ((v->voc_state == VOC_RUN) ||
+	    (v->voc_state == VOC_CHANGE) ||
+	    (v->voc_state == VOC_STANDBY))
 		ret = voice_send_vol_index_cmd(v);
 
 	mutex_unlock(&v->lock);
@@ -3501,6 +3508,15 @@
 			pr_err("setup voice failed\n");
 			goto fail;
 		}
+
+		ret = voice_send_vol_index_cmd(v);
+		if (ret < 0)
+			pr_err("voice volume failed\n");
+
+		ret = voice_send_mute_cmd(v);
+		if (ret < 0)
+			pr_err("voice mute failed\n");
+
 		ret = voice_send_start_voice_cmd(v);
 		if (ret < 0) {
 			pr_err("start voice failed\n");
@@ -3998,7 +4014,7 @@
 	memset((void *)common.cvs_cal.buf, 0, CVS_CAL_SIZE);
 cont:
 	/* set default value */
-	common.default_mute_val = 1;  /* default is mute */
+	common.default_mute_val = 0;  /* default is un-mute */
 	common.default_vol_val = 0;
 	common.default_sample_val = 8000;
 
diff --git a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
index 7723934..360744a 100644
--- a/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
+++ b/sound/soc/msm/qdsp6v2/msm-compr-q6-v2.c
@@ -621,7 +621,11 @@
 
 static __devinit int msm_compr_probe(struct platform_device *pdev)
 {
-	pr_info("%s: dev name %s\n", __func__, dev_name(&pdev->dev));
+	if (pdev->dev.of_node)
+		dev_set_name(&pdev->dev, "%s", "msm-compr-dsp");
+
+	dev_info(&pdev->dev, "%s: dev name %s\n",
+			 __func__, dev_name(&pdev->dev));
 	return snd_soc_register_platform(&pdev->dev,
 				   &msm_soc_platform);
 }
@@ -632,10 +636,17 @@
 	return 0;
 }
 
+static const struct of_device_id msm_compr_dt_match[] = {
+	{.compatible = "qcom,msm-compr-dsp"},
+	{}
+};
+MODULE_DEVICE_TABLE(of, msm_compr_dt_match);
+
 static struct platform_driver msm_compr_driver = {
 	.driver = {
 		.name = "msm-compr-dsp",
 		.owner = THIS_MODULE,
+		.of_match_table = msm_compr_dt_match,
 	},
 	.probe = msm_compr_probe,
 	.remove = __devexit_p(msm_compr_remove),
diff --git a/sound/soc/msm/qdsp6v2/q6adm.c b/sound/soc/msm/qdsp6v2/q6adm.c
index 691ca21..aed6273 100644
--- a/sound/soc/msm/qdsp6v2/q6adm.c
+++ b/sound/soc/msm/qdsp6v2/q6adm.c
@@ -433,7 +433,7 @@
 	mmap_regions->hdr.dest_port = 0;
 	mmap_regions->hdr.token = 0;
 	mmap_regions->hdr.opcode = ADM_CMD_SHARED_MEM_MAP_REGIONS;
-	mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL & 0x00ff;
+	mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL & 0x00ff;
 	mmap_regions->num_regions = bufcnt & 0x00ff;
 	mmap_regions->property_flag = 0x00;
 
diff --git a/sound/soc/msm/qdsp6v2/q6afe.c b/sound/soc/msm/qdsp6v2/q6afe.c
index 5b30e8e..4875a69 100644
--- a/sound/soc/msm/qdsp6v2/q6afe.c
+++ b/sound/soc/msm/qdsp6v2/q6afe.c
@@ -867,7 +867,7 @@
 	mregion->hdr.dest_port = 0;
 	mregion->hdr.token = 0;
 	mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
-	mregion->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+	mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
 	mregion->num_regions = 1;
 	mregion->property_flag = 0x00;
 	/* Todo */
@@ -946,7 +946,7 @@
 	mregion->hdr.dest_port = 0;
 	mregion->hdr.token = 0;
 	mregion->hdr.opcode = AFE_SERVICE_CMD_SHARED_MEM_MAP_REGIONS;
-	mregion->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+	mregion->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
 	mregion->num_regions = 1;
 	mregion->property_flag = 0x00;
 
diff --git a/sound/soc/msm/qdsp6v2/q6asm.c b/sound/soc/msm/qdsp6v2/q6asm.c
index 0bb88e8..a3af263 100644
--- a/sound/soc/msm/qdsp6v2/q6asm.c
+++ b/sound/soc/msm/qdsp6v2/q6asm.c
@@ -2265,7 +2265,7 @@
 	q6asm_add_mmaphdr(ac, &mmap_regions->hdr, cmd_size,
 			TRUE, ((ac->session << 8) | dir));
 	mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
-	mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+	mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
 	mmap_regions->num_regions = bufcnt & 0x00ff;
 	mmap_regions->property_flag = 0x00;
 	payload = ((u8 *) mmap_region_cmd +
@@ -2408,7 +2408,7 @@
 		mmap_regions, ((ac->session << 8) | dir));
 
 	mmap_regions->hdr.opcode = ASM_CMD_SHARED_MEM_MAP_REGIONS;
-	mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_EBI_POOL;
+	mmap_regions->mem_pool_id = ADSP_MEMORY_MAP_SHMEM8_4K_POOL;
 	mmap_regions->num_regions = 1; /*bufcnt & 0x00ff; */
 	mmap_regions->property_flag = 0x00;
 	pr_debug("map_regions->nregions = %d\n", mmap_regions->num_regions);