Merge "ASOC: msm: Add device tree specific changes in compressed driver" into msm-3.4
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/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..59e285b 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
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.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-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 f044533..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,
@@ -3076,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)
@@ -3106,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)
@@ -3195,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/clock-8974.c b/arch/arm/mach-msm/clock-8974.c
index 48f16b0..5124bd5 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 = {
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.h b/arch/arm/mach-msm/devices.h
index 5d2771e..daf70a8 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -420,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/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/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/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/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);