msm: rpm-regulator: add RPM regulator support for MSM8930

MSM8930 boards utilize the new PMIC PM8038.  Add a new
rpm-regulator data file which defines all of the regulators
available via the RPM for MSM8930 boards.

The regulator definitions describe both the physical properties of
the regulators and the RPM interface format used for each type of
regulator.

Change-Id: If4bdbaf3f6d22b905bf7334d681410fcddff9b7b
Signed-off-by: David Collins <collinsd@codeaurora.org>
diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index a698d43..f08bfb7 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -170,6 +170,7 @@
 	select MSM_SCM if SMP
 	select MSM_DIRECT_SCLK_ACCESS
 	select REGULATOR
+	select MSM_RPM_REGULATOR
 	select MSM_RPM
 	select MSM_XO
 	select MSM_QDSP6_APR
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index eb02ac3..234fb53 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -180,6 +180,7 @@
 obj-$(CONFIG_ARCH_MSM8X60) += rpm-regulator-8660.o
 obj-$(CONFIG_ARCH_MSM8960) += rpm-regulator-8960.o
 obj-$(CONFIG_ARCH_MSM9615) += rpm-regulator-9615.o
+obj-$(CONFIG_ARCH_MSM8930) += rpm-regulator-8930.o
 endif
 
 ifdef CONFIG_MSM_SUBSYSTEM_RESTART
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
new file mode 100644
index 0000000..9e654ed
--- /dev/null
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator-8930.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8930_H
+#define __ARCH_ARM_MACH_MSM_INCLUDE_MACH_RPM_REGULATOR_8930_H
+
+/* Pin control input signals. */
+#define RPM_VREG_PIN_CTRL_PM8038_D1	0x01
+#define RPM_VREG_PIN_CTRL_PM8038_A0	0x02
+#define RPM_VREG_PIN_CTRL_PM8038_A1	0x04
+#define RPM_VREG_PIN_CTRL_PM8038_A2	0x08
+
+/**
+ * enum rpm_vreg_pin_fn_8930 - RPM regulator pin function choices
+ * %RPM_VREG_PIN_FN_8930_DONT_CARE:	do not care about pin control state of
+ *					the regulator; allow another master
+ *					processor to specify pin control
+ * %RPM_VREG_PIN_FN_8930_ENABLE:	pin control switches between disable and
+ *					enable
+ * %RPM_VREG_PIN_FN_8930_MODE:		pin control switches between LPM and HPM
+ * %RPM_VREG_PIN_FN_8930_SLEEP_B:	regulator is forced into LPM when
+ *					sleep_b signal is asserted
+ * %RPM_VREG_PIN_FN_8930_NONE:		do not use pin control for the regulator
+ *					and do not allow another master to
+ *					request pin control
+ *
+ * The pin function specified in platform data corresponds to the active state
+ * pin function value.  Pin function will be NONE until a consumer requests
+ * pin control to be enabled.
+ */
+enum rpm_vreg_pin_fn_8930 {
+	RPM_VREG_PIN_FN_8930_DONT_CARE,
+	RPM_VREG_PIN_FN_8930_ENABLE,
+	RPM_VREG_PIN_FN_8930_MODE,
+	RPM_VREG_PIN_FN_8930_SLEEP_B,
+	RPM_VREG_PIN_FN_8930_NONE,
+};
+
+/**
+ * enum rpm_vreg_force_mode_8930 - RPM regulator force mode choices
+ * %RPM_VREG_FORCE_MODE_8930_PIN_CTRL:	allow pin control usage
+ * %RPM_VREG_FORCE_MODE_8930_NONE:	do not force any mode
+ * %RPM_VREG_FORCE_MODE_8930_LPM:	force into low power mode
+ * %RPM_VREG_FORCE_MODE_8930_AUTO:	allow regulator to automatically select
+ *					its own mode based on realtime current
+ *					draw (only available for SMPS
+ *					regulators)
+ * %RPM_VREG_FORCE_MODE_8930_HPM:	force into high power mode
+ * %RPM_VREG_FORCE_MODE_8930_BYPASS:	set regulator to use bypass mode, i.e.
+ *					to act as a switch and not regulate
+ *					(only available for LDO regulators)
+ *
+ * Force mode is used to override aggregation with other masters and to set
+ * special operating modes.
+ */
+enum rpm_vreg_force_mode_8930 {
+	RPM_VREG_FORCE_MODE_8930_PIN_CTRL = 0,
+	RPM_VREG_FORCE_MODE_8930_NONE = 0,
+	RPM_VREG_FORCE_MODE_8930_LPM,
+	RPM_VREG_FORCE_MODE_8930_AUTO,		/* SMPS only */
+	RPM_VREG_FORCE_MODE_8930_HPM,
+	RPM_VREG_FORCE_MODE_8930_BYPASS,	/* LDO only */
+};
+
+/**
+ * enum rpm_vreg_power_mode_8930 - power mode for SMPS regulators
+ * %RPM_VREG_POWER_MODE_8930_HYSTERETIC: Use hysteretic mode for HPM and when
+ *					 usage goes high in AUTO
+ * %RPM_VREG_POWER_MODE_8930_PWM:	 Use PWM mode for HPM and when usage
+ *					 goes high in AUTO
+ */
+enum rpm_vreg_power_mode_8930 {
+	RPM_VREG_POWER_MODE_8930_HYSTERETIC,
+	RPM_VREG_POWER_MODE_8930_PWM,
+};
+
+/**
+ * enum rpm_vreg_id - RPM regulator ID numbers (both real and pin control)
+ */
+enum rpm_vreg_id_8930 {
+	RPM_VREG_ID_PM8038_L1,
+	RPM_VREG_ID_PM8038_L2,
+	RPM_VREG_ID_PM8038_L3,
+	RPM_VREG_ID_PM8038_L4,
+	RPM_VREG_ID_PM8038_L5,
+	RPM_VREG_ID_PM8038_L6,
+	RPM_VREG_ID_PM8038_L7,
+	RPM_VREG_ID_PM8038_L8,
+	RPM_VREG_ID_PM8038_L9,
+	RPM_VREG_ID_PM8038_L10,
+	RPM_VREG_ID_PM8038_L11,
+	RPM_VREG_ID_PM8038_L12,
+	RPM_VREG_ID_PM8038_L14,
+	RPM_VREG_ID_PM8038_L15,
+	RPM_VREG_ID_PM8038_L16,
+	RPM_VREG_ID_PM8038_L17,
+	RPM_VREG_ID_PM8038_L18,
+	RPM_VREG_ID_PM8038_L19,
+	RPM_VREG_ID_PM8038_L20,
+	RPM_VREG_ID_PM8038_L21,
+	RPM_VREG_ID_PM8038_L22,
+	RPM_VREG_ID_PM8038_L23,
+	RPM_VREG_ID_PM8038_L24,
+	RPM_VREG_ID_PM8038_L26,
+	RPM_VREG_ID_PM8038_L27,
+	RPM_VREG_ID_PM8038_S1,
+	RPM_VREG_ID_PM8038_S2,
+	RPM_VREG_ID_PM8038_S3,
+	RPM_VREG_ID_PM8038_S4,
+	RPM_VREG_ID_PM8038_S5,
+	RPM_VREG_ID_PM8038_S6,
+	RPM_VREG_ID_PM8038_LVS1,
+	RPM_VREG_ID_PM8038_LVS2,
+	RPM_VREG_ID_PM8038_MAX_REAL = RPM_VREG_ID_PM8038_LVS2,
+
+	/* The following are IDs for regulator devices to enable pin control. */
+	RPM_VREG_ID_PM8038_L2_PC,
+	RPM_VREG_ID_PM8038_L3_PC,
+	RPM_VREG_ID_PM8038_L4_PC,
+	RPM_VREG_ID_PM8038_L5_PC,
+	RPM_VREG_ID_PM8038_L6_PC,
+	RPM_VREG_ID_PM8038_L7_PC,
+	RPM_VREG_ID_PM8038_L8_PC,
+	RPM_VREG_ID_PM8038_L9_PC,
+	RPM_VREG_ID_PM8038_L10_PC,
+	RPM_VREG_ID_PM8038_L11_PC,
+	RPM_VREG_ID_PM8038_L12_PC,
+	RPM_VREG_ID_PM8038_L14_PC,
+	RPM_VREG_ID_PM8038_L15_PC,
+	RPM_VREG_ID_PM8038_L17_PC,
+	RPM_VREG_ID_PM8038_L18_PC,
+	RPM_VREG_ID_PM8038_L21_PC,
+	RPM_VREG_ID_PM8038_L22_PC,
+	RPM_VREG_ID_PM8038_L23_PC,
+	RPM_VREG_ID_PM8038_L26_PC,
+	RPM_VREG_ID_PM8038_S1_PC,
+	RPM_VREG_ID_PM8038_S2_PC,
+	RPM_VREG_ID_PM8038_S3_PC,
+	RPM_VREG_ID_PM8038_S4_PC,
+	RPM_VREG_ID_PM8038_LVS1_PC,
+	RPM_VREG_ID_PM8038_LVS2_PC,
+	RPM_VREG_ID_PM8038_MAX = RPM_VREG_ID_PM8038_LVS2_PC,
+};
+
+/* Minimum high power mode loads in uA. */
+#define RPM_VREG_8930_LDO_50_HPM_MIN_LOAD		5000
+#define RPM_VREG_8930_LDO_150_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_LDO_300_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_LDO_600_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_LDO_1200_HPM_MIN_LOAD		10000
+#define RPM_VREG_8930_SMPS_1500_HPM_MIN_LOAD		100000
+#define RPM_VREG_8930_SMPS_2000_HPM_MIN_LOAD		100000
+
+#endif
diff --git a/arch/arm/mach-msm/include/mach/rpm-regulator.h b/arch/arm/mach-msm/include/mach/rpm-regulator.h
index 1095078..0d113ac 100644
--- a/arch/arm/mach-msm/include/mach/rpm-regulator.h
+++ b/arch/arm/mach-msm/include/mach/rpm-regulator.h
@@ -21,6 +21,7 @@
 #include <mach/rpm-regulator-8960.h>
 #include <mach/rpm-regulator-9615.h>
 #include <mach/rpm-regulator-copper.h>
+#include <mach/rpm-regulator-8930.h>
 
 /**
  * enum rpm_vreg_version - supported RPM regulator versions
@@ -29,7 +30,8 @@
 	RPM_VREG_VERSION_8660,
 	RPM_VREG_VERSION_8960,
 	RPM_VREG_VERSION_9615,
-	RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_9615,
+	RPM_VREG_VERSION_8930,
+	RPM_VREG_VERSION_MAX = RPM_VREG_VERSION_8930,
 };
 
 #define RPM_VREG_PIN_CTRL_NONE		0x00
diff --git a/arch/arm/mach-msm/rpm-regulator-8930.c b/arch/arm/mach-msm/rpm-regulator-8930.c
new file mode 100644
index 0000000..22595ec
--- /dev/null
+++ b/arch/arm/mach-msm/rpm-regulator-8930.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) "%s: " fmt, __func__
+
+#include "rpm-regulator-private.h"
+
+/* RPM regulator request formats */
+static struct rpm_vreg_parts ldo_parts = {
+	.request_len	= 2,
+	.uV		= REQUEST_MEMBER(0, 0x007FFFFF,  0),
+	.pd		= REQUEST_MEMBER(0, 0x00800000, 23),
+	.pc		= REQUEST_MEMBER(0, 0x0F000000, 24),
+	.pf		= REQUEST_MEMBER(0, 0xF0000000, 28),
+	.ip		= REQUEST_MEMBER(1, 0x000003FF,  0),
+	.ia		= REQUEST_MEMBER(1, 0x000FFC00, 10),
+	.fm		= REQUEST_MEMBER(1, 0x00700000, 20),
+};
+
+static struct rpm_vreg_parts smps_parts = {
+	.request_len	= 2,
+	.uV		= REQUEST_MEMBER(0, 0x007FFFFF,  0),
+	.pd		= REQUEST_MEMBER(0, 0x00800000, 23),
+	.pc		= REQUEST_MEMBER(0, 0x0F000000, 24),
+	.pf		= REQUEST_MEMBER(0, 0xF0000000, 28),
+	.ip		= REQUEST_MEMBER(1, 0x000003FF,  0),
+	.ia		= REQUEST_MEMBER(1, 0x000FFC00, 10),
+	.fm		= REQUEST_MEMBER(1, 0x00700000, 20),
+	.pm		= REQUEST_MEMBER(1, 0x00800000, 23),
+	.freq		= REQUEST_MEMBER(1, 0x1F000000, 24),
+	.freq_clk_src	= REQUEST_MEMBER(1, 0x60000000, 29),
+};
+
+static struct rpm_vreg_parts switch_parts = {
+	.request_len	= 1,
+	.enable_state	= REQUEST_MEMBER(0, 0x00000001,  0),
+	.pd		= REQUEST_MEMBER(0, 0x00000002,  1),
+	.pc		= REQUEST_MEMBER(0, 0x0000003C,  2),
+	.pf		= REQUEST_MEMBER(0, 0x000003C0,  6),
+	.hpm		= REQUEST_MEMBER(0, 0x00000C00, 10),
+};
+
+/* Physically available PMIC regulator voltage setpoint ranges */
+static struct vreg_range pldo_ranges[] = {
+	VOLTAGE_RANGE( 750000, 1487500, 12500),
+	VOLTAGE_RANGE(1500000, 3075000, 25000),
+	VOLTAGE_RANGE(3100000, 4900000, 50000),
+};
+
+static struct vreg_range nldo_ranges[] = {
+	VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static struct vreg_range nldo1200_ranges[] = {
+	VOLTAGE_RANGE( 375000,  743750,  6250),
+	VOLTAGE_RANGE( 750000, 1537500, 12500),
+};
+
+static struct vreg_range smps_ranges[] = {
+	VOLTAGE_RANGE( 375000,  737500, 12500),
+	VOLTAGE_RANGE( 750000, 1487500, 12500),
+	VOLTAGE_RANGE(1500000, 3075000, 25000),
+};
+
+static struct vreg_range ftsmps_ranges[] = {
+	VOLTAGE_RANGE( 350000,  650000, 50000),
+	VOLTAGE_RANGE( 700000, 1400000, 12500),
+	VOLTAGE_RANGE(1500000, 3300000, 50000),
+};
+
+static struct vreg_set_points pldo_set_points = SET_POINTS(pldo_ranges);
+static struct vreg_set_points nldo_set_points = SET_POINTS(nldo_ranges);
+static struct vreg_set_points nldo1200_set_points = SET_POINTS(nldo1200_ranges);
+static struct vreg_set_points smps_set_points = SET_POINTS(smps_ranges);
+static struct vreg_set_points ftsmps_set_points = SET_POINTS(ftsmps_ranges);
+
+static struct vreg_set_points *all_set_points[] = {
+	&pldo_set_points,
+	&nldo_set_points,
+	&nldo1200_set_points,
+	&smps_set_points,
+	&ftsmps_set_points,
+};
+
+#define LDO(_id, _name, _name_pc, _ranges, _hpm_min_load) \
+	[RPM_VREG_ID_PM8038_##_id] = { \
+		.req = { \
+			[0] = { .id = MSM_RPM_ID_PM8038_##_id##_0, }, \
+			[1] = { .id = MSM_RPM_ID_PM8038_##_id##_1, }, \
+		}, \
+		.hpm_min_load  = RPM_VREG_8930_##_hpm_min_load##_HPM_MIN_LOAD, \
+		.type		 = RPM_REGULATOR_TYPE_LDO, \
+		.set_points	 = &_ranges##_set_points, \
+		.part		 = &ldo_parts, \
+		.id		 = RPM_VREG_ID_PM8038_##_id, \
+		.rdesc.name	 = _name, \
+		.rdesc_pc.name	 = _name_pc, \
+	}
+
+#define SMPS(_id, _name, _name_pc, _ranges, _hpm_min_load) \
+	[RPM_VREG_ID_PM8038_##_id] = { \
+		.req = { \
+			[0] = { .id = MSM_RPM_ID_PM8038_##_id##_0, }, \
+			[1] = { .id = MSM_RPM_ID_PM8038_##_id##_1, }, \
+		}, \
+		.hpm_min_load  = RPM_VREG_8930_##_hpm_min_load##_HPM_MIN_LOAD, \
+		.type		 = RPM_REGULATOR_TYPE_SMPS, \
+		.set_points	 = &_ranges##_set_points, \
+		.part		 = &smps_parts, \
+		.id		 = RPM_VREG_ID_PM8038_##_id, \
+		.rdesc.name	 = _name, \
+		.rdesc_pc.name	 = _name_pc, \
+	}
+
+#define LVS(_id, _name, _name_pc) \
+	[RPM_VREG_ID_PM8038_##_id] = { \
+		.req = { \
+			[0] = { .id = MSM_RPM_ID_PM8038_##_id, }, \
+			[1] = { .id = -1, }, \
+		}, \
+		.type		 = RPM_REGULATOR_TYPE_VS, \
+		.part		 = &switch_parts, \
+		.id		 = RPM_VREG_ID_PM8038_##_id, \
+		.rdesc.name	 = _name, \
+		.rdesc_pc.name	 = _name_pc, \
+	}
+
+static struct vreg vregs[] = {
+	LDO(L1,   "8038_l1",   NULL,          nldo1200, LDO_1200),
+	LDO(L2,   "8038_l2",   "8038_l2_pc",  nldo,     LDO_150),
+	LDO(L3,   "8038_l3",   "8038_l3_pc",  pldo,     LDO_50),
+	LDO(L4,   "8038_l4",   "8038_l4_pc",  pldo,     LDO_50),
+	LDO(L5,   "8038_l5",   "8038_l5_pc",  pldo,     LDO_600),
+	LDO(L6,   "8038_l6",   "8038_l6_pc",  pldo,     LDO_600),
+	LDO(L7,   "8038_l7",   "8038_l7_pc",  pldo,     LDO_600),
+	LDO(L8,   "8038_l8",   "8038_l8_pc",  pldo,     LDO_300),
+	LDO(L9,   "8038_l9",   "8038_l9_pc",  pldo,     LDO_300),
+	LDO(L10,  "8038_l10",  "8038_l10_pc", pldo,     LDO_600),
+	LDO(L11,  "8038_l11",  "8038_l11_pc", pldo,     LDO_600),
+	LDO(L12,  "8038_l12",  "8038_l12_pc", nldo,     LDO_300),
+	LDO(L14,  "8038_l14",  "8038_l14_pc", pldo,     LDO_50),
+	LDO(L15,  "8038_l15",  "8038_l15_pc", pldo,     LDO_150),
+	LDO(L16,  "8038_l16",  NULL,          nldo1200, LDO_1200),
+	LDO(L17,  "8038_l17",  "8038_l17_pc", pldo,     LDO_150),
+	LDO(L18,  "8038_l18",  "8038_l18_pc", pldo,     LDO_50),
+	LDO(L19,  "8038_l19",  NULL,          nldo1200, LDO_1200),
+	LDO(L20,  "8038_l20",  NULL,          nldo1200, LDO_1200),
+	LDO(L21,  "8038_l21",  "8038_l21_pc", pldo,     LDO_150),
+	LDO(L22,  "8038_l22",  "8038_l22_pc", pldo,     LDO_50),
+	LDO(L23,  "8038_l23",  "8038_l23_pc", pldo,     LDO_50),
+	LDO(L24,  "8038_l24",  NULL,          nldo1200, LDO_1200),
+	LDO(L26,  "8038_l26",  "8038_l26_pc", nldo,     LDO_150),
+	LDO(L27,  "8038_l27",  NULL,          nldo1200, LDO_1200),
+
+	SMPS(S1,  "8038_s1",   "8038_s1_pc",  smps,     SMPS_1500),
+	SMPS(S2,  "8038_s2",   "8038_s2_pc",  smps,     SMPS_1500),
+	SMPS(S3,  "8038_s3",   "8038_s3_pc",  smps,     SMPS_1500),
+	SMPS(S4,  "8038_s4",   "8038_s4_pc",  smps,     SMPS_1500),
+	SMPS(S5,  "8038_s5",   NULL,          ftsmps,   SMPS_2000),
+	SMPS(S6,  "8038_s6",   NULL,          ftsmps,   SMPS_2000),
+
+	LVS(LVS1, "8038_lvs1", "8038_lvs1_pc"),
+	LVS(LVS2, "8038_lvs2", "8038_lvs2_pc"),
+};
+
+static const char *pin_func_label[] = {
+	[RPM_VREG_PIN_FN_8930_DONT_CARE]	= "don't care",
+	[RPM_VREG_PIN_FN_8930_ENABLE]		= "on/off",
+	[RPM_VREG_PIN_FN_8930_MODE]		= "HPM/LPM",
+	[RPM_VREG_PIN_FN_8930_SLEEP_B]		= "sleep_b",
+	[RPM_VREG_PIN_FN_8930_NONE]		= "none",
+};
+
+static const char *force_mode_label[] = {
+	[RPM_VREG_FORCE_MODE_8930_NONE]		= "none",
+	[RPM_VREG_FORCE_MODE_8930_LPM]		= "LPM",
+	[RPM_VREG_FORCE_MODE_8930_AUTO]		= "auto",
+	[RPM_VREG_FORCE_MODE_8930_HPM]		= "HPM",
+	[RPM_VREG_FORCE_MODE_8930_BYPASS]	= "BYP",
+};
+
+static const char *power_mode_label[] = {
+	[RPM_VREG_POWER_MODE_8930_HYSTERETIC]	= "HYS",
+	[RPM_VREG_POWER_MODE_8930_PWM]		= "PWM",
+};
+
+static const char *pin_control_label[] = {
+	" D1",
+	" A0",
+	" A1",
+	" A2",
+};
+
+static int is_real_id(int id)
+{
+	return (id >= 0) && (id <= RPM_VREG_ID_PM8038_MAX_REAL);
+}
+
+static int pc_id_to_real_id(int id)
+{
+	int real_id = 0;
+
+	if (id >= RPM_VREG_ID_PM8038_L2_PC && id <= RPM_VREG_ID_PM8038_L15_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L2_PC;
+	else if (id >= RPM_VREG_ID_PM8038_L17_PC
+			&& id <= RPM_VREG_ID_PM8038_L18_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L17_PC
+				+ RPM_VREG_ID_PM8038_L17;
+	else if (id >= RPM_VREG_ID_PM8038_L21_PC
+			&& id <= RPM_VREG_ID_PM8038_L23_PC)
+		real_id = id - RPM_VREG_ID_PM8038_L21_PC
+				+ RPM_VREG_ID_PM8038_L21;
+	else if (id == RPM_VREG_ID_PM8038_L26_PC)
+		real_id = RPM_VREG_ID_PM8038_L26;
+	else if (id >= RPM_VREG_ID_PM8038_S1_PC
+			&& id <= RPM_VREG_ID_PM8038_S4_PC)
+		real_id = id - RPM_VREG_ID_PM8038_S1_PC
+				+ RPM_VREG_ID_PM8038_S1;
+	else if (id >= RPM_VREG_ID_PM8038_LVS1_PC
+			&& id <= RPM_VREG_ID_PM8038_LVS2_PC)
+		real_id = id - RPM_VREG_ID_PM8038_LVS1_PC
+				+ RPM_VREG_ID_PM8038_LVS1;
+
+	return real_id;
+}
+
+static struct vreg_config config = {
+	.vregs			= vregs,
+	.vregs_len		= ARRAY_SIZE(vregs),
+
+	.vreg_id_min		= RPM_VREG_ID_PM8038_L1,
+	.vreg_id_max		= RPM_VREG_ID_PM8038_MAX,
+
+	.pin_func_none		= RPM_VREG_PIN_FN_8930_NONE,
+	.pin_func_sleep_b	= RPM_VREG_PIN_FN_8930_SLEEP_B,
+
+	.mode_lpm		= REGULATOR_MODE_IDLE,
+	.mode_hpm		= REGULATOR_MODE_NORMAL,
+
+	.set_points		= all_set_points,
+	.set_points_len		= ARRAY_SIZE(all_set_points),
+
+	.label_pin_ctrl		= pin_control_label,
+	.label_pin_ctrl_len	= ARRAY_SIZE(pin_control_label),
+	.label_pin_func		= pin_func_label,
+	.label_pin_func_len	= ARRAY_SIZE(pin_func_label),
+	.label_force_mode	= force_mode_label,
+	.label_force_mode_len	= ARRAY_SIZE(force_mode_label),
+	.label_power_mode	= power_mode_label,
+	.label_power_mode_len	= ARRAY_SIZE(power_mode_label),
+
+	.is_real_id		= is_real_id,
+	.pc_id_to_real_id	= pc_id_to_real_id,
+};
+
+struct vreg_config *get_config_8930(void)
+{
+	return &config;
+}
diff --git a/arch/arm/mach-msm/rpm-regulator-private.h b/arch/arm/mach-msm/rpm-regulator-private.h
index ff127d9..88b52ea 100644
--- a/arch/arm/mach-msm/rpm-regulator-private.h
+++ b/arch/arm/mach-msm/rpm-regulator-private.h
@@ -144,7 +144,7 @@
 #define MICRO_TO_MILLI(uV)			((uV) / 1000)
 #define MILLI_TO_MICRO(mV)			((mV) * 1000)
 
-#if defined(CONFIG_ARCH_MSM8X60)
+#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM8X60)
 struct vreg_config *get_config_8660(void);
 #else
 static inline struct vreg_config *get_config_8660(void)
@@ -153,7 +153,8 @@
 }
 #endif
 
-#if defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064)
+#if defined(CONFIG_MSM_RPM_REGULATOR) && \
+	(defined(CONFIG_ARCH_MSM8960) || defined(CONFIG_ARCH_APQ8064))
 struct vreg_config *get_config_8960(void);
 #else
 static inline struct vreg_config *get_config_8960(void)
@@ -162,7 +163,7 @@
 }
 #endif
 
-#if defined(CONFIG_ARCH_MSM9615)
+#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM9615)
 struct vreg_config *get_config_9615(void);
 #else
 static inline struct vreg_config *get_config_9615(void)
@@ -171,4 +172,13 @@
 }
 #endif
 
+#if defined(CONFIG_MSM_RPM_REGULATOR) && defined(CONFIG_ARCH_MSM8930)
+struct vreg_config *get_config_8930(void);
+#else
+static inline struct vreg_config *get_config_8930(void)
+{
+	return NULL;
+}
+#endif
+
 #endif
diff --git a/arch/arm/mach-msm/rpm-regulator.c b/arch/arm/mach-msm/rpm-regulator.c
index e2ebbd4..946d31b 100644
--- a/arch/arm/mach-msm/rpm-regulator.c
+++ b/arch/arm/mach-msm/rpm-regulator.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2010-2011, Code Aurora Forum. All rights reserved.
+ * Copyright (c) 2010-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
@@ -46,6 +46,7 @@
 	[RPM_VREG_VERSION_8660] = get_config_8660,
 	[RPM_VREG_VERSION_8960] = get_config_8960,
 	[RPM_VREG_VERSION_9615] = get_config_9615,
+	[RPM_VREG_VERSION_8930] = get_config_8930,
 };
 
 #define SET_PART(_vreg, _part, _val) \