Merge changes I2ccd6ccc,I28d1077e,Ib83027b4 into msm-3.0
* changes:
msm: copper: Enable stub regulator driver
msm: copper: Add regulator devices for stub-regulator driver
regulator: Add stub regulator support
diff --git a/arch/arm/configs/msm-copper_defconfig b/arch/arm/configs/msm-copper_defconfig
index 0b89d45..e9479c6 100644
--- a/arch/arm/configs/msm-copper_defconfig
+++ b/arch/arm/configs/msm-copper_defconfig
@@ -104,6 +104,8 @@
# CONFIG_BATTERY_MSM is not set
# CONFIG_HWMON is not set
# CONFIG_MFD_SUPPORT is not set
+CONFIG_REGULATOR=y
+CONFIG_REGULATOR_STUB=y
CONFIG_ION=y
CONFIG_ION_MSM=y
CONFIG_FB=y
diff --git a/arch/arm/mach-msm/Makefile b/arch/arm/mach-msm/Makefile
index ebc236c..c4d2c54 100644
--- a/arch/arm/mach-msm/Makefile
+++ b/arch/arm/mach-msm/Makefile
@@ -260,7 +260,7 @@
obj-$(CONFIG_MACH_APQ8064_RUMI3) += board-8064-all.o board-8064-regulator.o
obj-$(CONFIG_ARCH_MSM9615) += board-9615.o devices-9615.o board-9615-regulator.o board-9615-gpiomux.o board-9615-storage.o
obj-$(CONFIG_ARCH_MSM9615) += clock-local.o clock-9615.o acpuclock-9615.o clock-rpm.o
-obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o
+obj-$(CONFIG_ARCH_MSMCOPPER) += board-copper.o board-dt.o board-copper-regulator.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/board-copper-regulator.c b/arch/arm/mach-msm/board-copper-regulator.c
new file mode 100644
index 0000000..a7f0eac
--- /dev/null
+++ b/arch/arm/mach-msm/board-copper-regulator.c
@@ -0,0 +1,322 @@
+/*
+ * Copyright (c) 2012, Code Aurora Forum. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/platform_device.h>
+#include <linux/regulator/stub-regulator.h>
+
+#define VREG_CONSUMERS(_name) \
+ static struct regulator_consumer_supply vreg_consumers_##_name[]
+
+/*
+ * Consumer specific regulator names:
+ * regulator name consumer dev_name
+ */
+VREG_CONSUMERS(S1B) = {
+ REGULATOR_SUPPLY("8841_s1", NULL),
+};
+VREG_CONSUMERS(S2B) = {
+ REGULATOR_SUPPLY("8841_s2", NULL),
+};
+VREG_CONSUMERS(S3B) = {
+ REGULATOR_SUPPLY("8841_s3", NULL),
+};
+VREG_CONSUMERS(S4B) = {
+ REGULATOR_SUPPLY("8841_s4", NULL),
+};
+VREG_CONSUMERS(S5B) = {
+ REGULATOR_SUPPLY("8841_s5", NULL),
+};
+VREG_CONSUMERS(S6B) = {
+ REGULATOR_SUPPLY("8841_s6", NULL),
+};
+VREG_CONSUMERS(S7B) = {
+ REGULATOR_SUPPLY("8841_s7", NULL),
+};
+VREG_CONSUMERS(S8B) = {
+ REGULATOR_SUPPLY("8841_s8", NULL),
+};
+VREG_CONSUMERS(S1) = {
+ REGULATOR_SUPPLY("8941_s1", NULL),
+};
+VREG_CONSUMERS(S2) = {
+ REGULATOR_SUPPLY("8941_s2", NULL),
+};
+VREG_CONSUMERS(S3) = {
+ REGULATOR_SUPPLY("8941_s3", NULL),
+};
+VREG_CONSUMERS(L1) = {
+ REGULATOR_SUPPLY("8941_l1", NULL),
+};
+VREG_CONSUMERS(L2) = {
+ REGULATOR_SUPPLY("8941_l2", NULL),
+};
+VREG_CONSUMERS(L3) = {
+ REGULATOR_SUPPLY("8941_l3", NULL),
+};
+VREG_CONSUMERS(L4) = {
+ REGULATOR_SUPPLY("8941_l4", NULL),
+};
+VREG_CONSUMERS(L5) = {
+ REGULATOR_SUPPLY("8941_l5", NULL),
+};
+VREG_CONSUMERS(L6) = {
+ REGULATOR_SUPPLY("8941_l6", NULL),
+};
+VREG_CONSUMERS(L7) = {
+ REGULATOR_SUPPLY("8941_l7", NULL),
+};
+VREG_CONSUMERS(L8) = {
+ REGULATOR_SUPPLY("8941_l8", NULL),
+};
+VREG_CONSUMERS(L9) = {
+ REGULATOR_SUPPLY("8941_l9", NULL),
+};
+VREG_CONSUMERS(L10) = {
+ REGULATOR_SUPPLY("8941_l10", NULL),
+};
+VREG_CONSUMERS(L11) = {
+ REGULATOR_SUPPLY("8941_l11", NULL),
+};
+VREG_CONSUMERS(L12) = {
+ REGULATOR_SUPPLY("8941_l12", NULL),
+};
+VREG_CONSUMERS(L13) = {
+ REGULATOR_SUPPLY("8941_l13", NULL),
+};
+VREG_CONSUMERS(L14) = {
+ REGULATOR_SUPPLY("8941_l14", NULL),
+};
+VREG_CONSUMERS(L15) = {
+ REGULATOR_SUPPLY("8941_l15", NULL),
+};
+VREG_CONSUMERS(L16) = {
+ REGULATOR_SUPPLY("8941_l16", NULL),
+};
+VREG_CONSUMERS(L17) = {
+ REGULATOR_SUPPLY("8941_l17", NULL),
+};
+VREG_CONSUMERS(L18) = {
+ REGULATOR_SUPPLY("8941_l18", NULL),
+};
+VREG_CONSUMERS(L19) = {
+ REGULATOR_SUPPLY("8941_l19", NULL),
+};
+VREG_CONSUMERS(L20) = {
+ REGULATOR_SUPPLY("8941_l20", NULL),
+};
+VREG_CONSUMERS(L21) = {
+ REGULATOR_SUPPLY("8941_l21", NULL),
+};
+VREG_CONSUMERS(L22) = {
+ REGULATOR_SUPPLY("8941_l22", NULL),
+};
+VREG_CONSUMERS(L23) = {
+ REGULATOR_SUPPLY("8941_l23", NULL),
+};
+VREG_CONSUMERS(L24) = {
+ REGULATOR_SUPPLY("8941_l24", NULL),
+};
+VREG_CONSUMERS(LVS1) = {
+ REGULATOR_SUPPLY("8941_lvs1", NULL),
+};
+VREG_CONSUMERS(LVS2) = {
+ REGULATOR_SUPPLY("8941_lvs2", NULL),
+};
+VREG_CONSUMERS(LVS3) = {
+ REGULATOR_SUPPLY("8941_lvs3", NULL),
+};
+
+#define PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, _modes, _ops, \
+ _always_on, _supply_regulator, _hpm_min, _system_uA) \
+ struct stub_regulator_pdata vreg_dev_##_id##_pdata __devinitdata = { \
+ .init_data = { \
+ .constraints = { \
+ .valid_modes_mask = _modes, \
+ .valid_ops_mask = _ops, \
+ .min_uV = _min_uV, \
+ .max_uV = _max_uV, \
+ .input_uV = _max_uV, \
+ .apply_uV = 0, \
+ .always_on = _always_on, \
+ .name = _name, \
+ }, \
+ .num_consumer_supplies = \
+ ARRAY_SIZE(vreg_consumers_##_id), \
+ .consumer_supplies = vreg_consumers_##_id, \
+ .supply_regulator = _supply_regulator, \
+ }, \
+ .hpm_min_load = _hpm_min, \
+ .system_uA = _system_uA, \
+ }
+
+#define PM8X41_LDO(_id, _name, _always_on, _min_uV, _max_uV, \
+ _supply_regulator, _hpm_min, _system_uA) \
+ PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
+ REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_DRMS, _always_on, \
+ _supply_regulator, _hpm_min, _system_uA)
+
+#define PM8X41_SMPS(_id, _name, _always_on, _min_uV, _max_uV, \
+ _supply_regulator, _hpm_min, _system_uA) \
+ PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL \
+ | REGULATOR_MODE_IDLE, REGULATOR_CHANGE_VOLTAGE | \
+ REGULATOR_CHANGE_STATUS | REGULATOR_CHANGE_MODE | \
+ REGULATOR_CHANGE_DRMS, _always_on, \
+ _supply_regulator, _hpm_min, _system_uA)
+
+#define PM8X41_FTSMPS(_id, _name, _always_on, _min_uV, _max_uV, \
+ _supply_regulator, _hpm_min, _system_uA) \
+ PM8X41_VREG_INIT(_id, _name, _min_uV, _max_uV, REGULATOR_MODE_NORMAL, \
+ REGULATOR_CHANGE_VOLTAGE | REGULATOR_CHANGE_STATUS \
+ | REGULATOR_CHANGE_MODE, _always_on, \
+ _supply_regulator, _hpm_min, _system_uA)
+
+#define PM8X41_VS(_id, _name, _always_on, _supply_regulator) \
+ PM8X41_VREG_INIT(_id, _name, 0, 0, 0, REGULATOR_CHANGE_STATUS, \
+ _always_on, _supply_regulator, 0, 0)
+
+/* PM8x41 regulator constraints */
+
+/* ID name a_on min_uV max_uV supply hpm_min sys_uA */
+PM8X41_SMPS(S1B, "8841_s1", 0, 900000, 1150000, NULL, 100000, 0);
+PM8X41_FTSMPS(S2B, "8841_s2", 0, 900000, 1150000, NULL, 100000, 0);
+PM8X41_SMPS(S3B, "8841_s3", 0, 1150000, 1150000, NULL, 100000, 0);
+PM8X41_FTSMPS(S4B, "8841_s4", 0, 900000, 900000, NULL, 100000, 0);
+PM8X41_FTSMPS(S5B, "8841_s5", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_FTSMPS(S6B, "8841_s6", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_FTSMPS(S7B, "8841_s7", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_FTSMPS(S8B, "8841_s8", 0, 850000, 1100000, NULL, 100000, 0);
+PM8X41_SMPS(S1, "8941_s1", 0, 1300000, 1300000, NULL, 100000, 0);
+PM8X41_SMPS(S2, "8941_s2", 0, 2150000, 2150000, NULL, 100000, 0);
+PM8X41_SMPS(S3, "8941_s3", 0, 1800000, 1800000, NULL, 100000, 0);
+PM8X41_LDO(L1, "8941_l1", 0, 1225000, 1225000, "8941_s1", 100000, 0);
+PM8X41_LDO(L2, "8941_l2", 0, 1200000, 1200000, "8941_s3", 5000, 0);
+PM8X41_LDO(L3, "8941_l3", 0, 1200000, 1200000, "8941_s1", 10000, 0);
+PM8X41_LDO(L4, "8941_l4", 0, 1150000, 1150000, "8941_s1", 10000, 0);
+PM8X41_LDO(L5, "8941_l5", 0, 1800000, 1800000, "8941_s2", 1000, 0);
+PM8X41_LDO(L6, "8941_l6", 0, 1800000, 1800000, "8941_s2", 10000, 0);
+PM8X41_LDO(L7, "8941_l7", 0, 1800000, 1800000, "8941_s2", 1000, 0);
+PM8X41_LDO(L8, "8941_l8", 0, 1800000, 1800000, NULL, 1000, 0);
+PM8X41_LDO(L9, "8941_l9", 0, 1800000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L10, "8941_l10", 0, 1800000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L11, "8941_l11", 0, 1250000, 1250000, "8941_s1", 10000, 0);
+PM8X41_LDO(L12, "8941_l12", 0, 1800000, 1800000, "8941_s2", 10000, 0);
+PM8X41_LDO(L13, "8941_l13", 0, 2950000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L14, "8941_l14", 0, 1800000, 1800000, "8941_s2", 10000, 0);
+PM8X41_LDO(L15, "8941_l15", 0, 2050000, 2050000, "8941_s2", 10000, 0);
+PM8X41_LDO(L16, "8941_l16", 0, 2700000, 2700000, NULL, 10000, 0);
+PM8X41_LDO(L17, "8941_l17", 0, 2850000, 2850000, NULL, 10000, 0);
+PM8X41_LDO(L18, "8941_l18", 0, 2850000, 2850000, NULL, 10000, 0);
+PM8X41_LDO(L19, "8941_l19", 0, 2900000, 2900000, NULL, 10000, 0);
+PM8X41_LDO(L20, "8941_l20", 0, 2950000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L21, "8941_l21", 0, 2950000, 2950000, NULL, 10000, 0);
+PM8X41_LDO(L22, "8941_l22", 0, 3000000, 3000000, NULL, 10000, 0);
+PM8X41_LDO(L23, "8941_l23", 0, 3000000, 3000000, NULL, 10000, 0);
+PM8X41_LDO(L24, "8941_l24", 0, 3075000, 3075000, NULL, 5000, 0);
+
+/* ID name a_on supply */
+PM8X41_VS(LVS1, "8941_lvs1", 0, "8941_s3");
+PM8X41_VS(LVS2, "8941_lvs2", 0, "8941_s3");
+PM8X41_VS(LVS3, "8941_lvs3", 0, "8941_s3");
+
+#define VREG_DEVICE(_name, _devid) \
+ vreg_device_##_name __devinitdata = \
+ { \
+ .name = STUB_REGULATOR_DRIVER_NAME, \
+ .id = _devid, \
+ .dev = { .platform_data = &vreg_dev_##_name##_pdata }, \
+ }
+
+static struct platform_device VREG_DEVICE(S1B, 0);
+static struct platform_device VREG_DEVICE(S2B, 1);
+static struct platform_device VREG_DEVICE(S3B, 3);
+static struct platform_device VREG_DEVICE(S4B, 4);
+static struct platform_device VREG_DEVICE(S5B, 5);
+static struct platform_device VREG_DEVICE(S6B, 6);
+static struct platform_device VREG_DEVICE(S7B, 7);
+static struct platform_device VREG_DEVICE(S8B, 8);
+static struct platform_device VREG_DEVICE(S1, 9);
+static struct platform_device VREG_DEVICE(S2, 10);
+static struct platform_device VREG_DEVICE(S3, 11);
+static struct platform_device VREG_DEVICE(L1, 12);
+static struct platform_device VREG_DEVICE(L2, 13);
+static struct platform_device VREG_DEVICE(L3, 14);
+static struct platform_device VREG_DEVICE(L4, 15);
+static struct platform_device VREG_DEVICE(L5, 16);
+static struct platform_device VREG_DEVICE(L6, 17);
+static struct platform_device VREG_DEVICE(L7, 18);
+static struct platform_device VREG_DEVICE(L8, 19);
+static struct platform_device VREG_DEVICE(L9, 20);
+static struct platform_device VREG_DEVICE(L10, 21);
+static struct platform_device VREG_DEVICE(L11, 22);
+static struct platform_device VREG_DEVICE(L12, 23);
+static struct platform_device VREG_DEVICE(L13, 24);
+static struct platform_device VREG_DEVICE(L14, 25);
+static struct platform_device VREG_DEVICE(L15, 26);
+static struct platform_device VREG_DEVICE(L16, 27);
+static struct platform_device VREG_DEVICE(L17, 28);
+static struct platform_device VREG_DEVICE(L18, 29);
+static struct platform_device VREG_DEVICE(L19, 30);
+static struct platform_device VREG_DEVICE(L20, 31);
+static struct platform_device VREG_DEVICE(L21, 32);
+static struct platform_device VREG_DEVICE(L22, 33);
+static struct platform_device VREG_DEVICE(L23, 34);
+static struct platform_device VREG_DEVICE(L24, 35);
+static struct platform_device VREG_DEVICE(LVS1, 36);
+static struct platform_device VREG_DEVICE(LVS2, 37);
+static struct platform_device VREG_DEVICE(LVS3, 38);
+
+struct platform_device *msm_copper_stub_regulator_devices[] __devinitdata = {
+ &vreg_device_S1B,
+ &vreg_device_S2B,
+ &vreg_device_S3B,
+ &vreg_device_S4B,
+ &vreg_device_S5B,
+ &vreg_device_S6B,
+ &vreg_device_S7B,
+ &vreg_device_S8B,
+ &vreg_device_S1,
+ &vreg_device_S2,
+ &vreg_device_S3,
+ &vreg_device_L1,
+ &vreg_device_L2,
+ &vreg_device_L3,
+ &vreg_device_L4,
+ &vreg_device_L5,
+ &vreg_device_L6,
+ &vreg_device_L7,
+ &vreg_device_L8,
+ &vreg_device_L9,
+ &vreg_device_L10,
+ &vreg_device_L11,
+ &vreg_device_L12,
+ &vreg_device_L13,
+ &vreg_device_L14,
+ &vreg_device_L15,
+ &vreg_device_L16,
+ &vreg_device_L17,
+ &vreg_device_L18,
+ &vreg_device_L19,
+ &vreg_device_L20,
+ &vreg_device_L21,
+ &vreg_device_L22,
+ &vreg_device_L23,
+ &vreg_device_L24,
+ &vreg_device_LVS1,
+ &vreg_device_LVS2,
+ &vreg_device_LVS3,
+};
+
+int msm_copper_stub_regulator_devices_len __devinitdata =
+ ARRAY_SIZE(msm_copper_stub_regulator_devices);
diff --git a/arch/arm/mach-msm/board-copper.c b/arch/arm/mach-msm/board-copper.c
index c30be16..97ea645 100644
--- a/arch/arm/mach-msm/board-copper.c
+++ b/arch/arm/mach-msm/board-copper.c
@@ -26,6 +26,7 @@
#ifdef CONFIG_ANDROID_PMEM
#include <linux/android_pmem.h>
#endif
+#include <linux/regulator/stub-regulator.h>
#include <asm/mach/map.h>
#include <asm/hardware/gic.h>
#include <mach/board.h>
@@ -39,6 +40,7 @@
#include <mach/msm_smd.h>
#include <mach/qpnp-int.h>
#include "clock.h"
+#include "devices.h"
#define MSM_KERNEL_EBI1_MEM_SIZE 0x280000
#ifdef CONFIG_FB_MSM_HDMI_AS_PRIMARY
@@ -357,6 +359,8 @@
platform_device_register(&ion_dev);
#endif
platform_device_register(&msm_device_smd_copper);
+ platform_add_devices(msm_copper_stub_regulator_devices,
+ msm_copper_stub_regulator_devices_len);
}
static struct of_device_id irq_match[] __initdata = {
diff --git a/arch/arm/mach-msm/devices.h b/arch/arm/mach-msm/devices.h
index 4371c23..2eb716a 100644
--- a/arch/arm/mach-msm/devices.h
+++ b/arch/arm/mach-msm/devices.h
@@ -324,5 +324,6 @@
extern struct platform_device msm_bus_8064_cpss_fpb;
extern struct platform_device mdm_8064_device;
-
extern struct platform_device msm_dsps_device_8064;
+extern struct platform_device *msm_copper_stub_regulator_devices[];
+extern int msm_copper_stub_regulator_devices_len;
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 49e0d0e..fb1a99f 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -344,5 +344,14 @@
chip. It is only supposed to be used when Linux on application
processor is the master in control of XO buffers.
+config REGULATOR_STUB
+ tristate "Stub Regulator"
+ help
+ This driver adds stub regulator support. The driver is absent of any
+ real hardware based implementation. It allows for clients to register
+ their regulator device constraints and use all of the standard
+ regulator interfaces. This is useful for bringing up new platforms
+ when the real hardware based implementation may not be yet available.
+ Clients can use the real regulator device names with proper
+ constraint checking while the real driver is being developed.
endif
-
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 5318cff..74b1f71 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -48,5 +48,6 @@
obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o
obj-$(CONFIG_REGULATOR_PM8058_XO) += pm8058-xo.o
obj-$(CONFIG_REGULATOR_PM8XXX) += pm8xxx-regulator.o
+obj-$(CONFIG_REGULATOR_STUB) += stub-regulator.o
ccflags-$(CONFIG_REGULATOR_DEBUG) += -DDEBUG
diff --git a/drivers/regulator/stub-regulator.c b/drivers/regulator/stub-regulator.c
new file mode 100644
index 0000000..afac80a
--- /dev/null
+++ b/drivers/regulator/stub-regulator.c
@@ -0,0 +1,232 @@
+/*
+ * 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 <linux/module.h>
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/stub-regulator.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/types.h>
+
+#define STUB_REGULATOR_MAX_NAME 40
+
+struct regulator_stub {
+ struct regulator_desc rdesc;
+ struct regulator_dev *rdev;
+ int voltage;
+ bool enabled;
+ int mode;
+ int hpm_min_load;
+ int system_uA;
+ char name[STUB_REGULATOR_MAX_NAME];
+};
+
+static int regulator_stub_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ vreg_priv->voltage = min_uV;
+ return 0;
+}
+
+static int regulator_stub_get_voltage(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ return vreg_priv->voltage;
+}
+
+static int regulator_stub_list_voltage(struct regulator_dev *rdev,
+ unsigned selector)
+{
+ struct regulation_constraints *constraints = rdev->constraints;
+
+ if (selector >= 2)
+ return -EINVAL;
+ else if (selector == 0)
+ return constraints->min_uV;
+ else
+ return constraints->max_uV;
+}
+
+static unsigned int regulator_stub_get_mode(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ return vreg_priv->mode;
+}
+
+static int regulator_stub_set_mode(struct regulator_dev *rdev,
+ unsigned int mode)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+
+ if (mode != REGULATOR_MODE_NORMAL && mode != REGULATOR_MODE_IDLE) {
+ dev_err(&rdev->dev, "%s: invalid mode requested %u\n",
+ __func__, mode);
+ return -EINVAL;
+ }
+ vreg_priv->mode = mode;
+ return 0;
+}
+
+static unsigned int regulator_stub_get_optimum_mode(struct regulator_dev *rdev,
+ int input_uV, int output_uV, int load_uA)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ unsigned int mode;
+
+ if (load_uA + vreg_priv->system_uA >= vreg_priv->hpm_min_load)
+ mode = REGULATOR_MODE_NORMAL;
+ else
+ mode = REGULATOR_MODE_IDLE;
+
+ return mode;
+}
+
+static int regulator_stub_enable(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ vreg_priv->enabled = true;
+ return 0;
+}
+
+static int regulator_stub_disable(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ vreg_priv->enabled = false;
+ return 0;
+}
+
+static int regulator_stub_is_enabled(struct regulator_dev *rdev)
+{
+ struct regulator_stub *vreg_priv = rdev_get_drvdata(rdev);
+ return vreg_priv->enabled;
+}
+
+/* Real regulator operations. */
+static struct regulator_ops regulator_stub_ops = {
+ .enable = regulator_stub_enable,
+ .disable = regulator_stub_disable,
+ .is_enabled = regulator_stub_is_enabled,
+ .set_voltage = regulator_stub_set_voltage,
+ .get_voltage = regulator_stub_get_voltage,
+ .list_voltage = regulator_stub_list_voltage,
+ .set_mode = regulator_stub_set_mode,
+ .get_mode = regulator_stub_get_mode,
+ .get_optimum_mode = regulator_stub_get_optimum_mode,
+};
+
+static void regulator_stub_cleanup(struct regulator_stub *vreg_priv)
+{
+ if (vreg_priv && vreg_priv->rdev)
+ regulator_unregister(vreg_priv->rdev);
+ kfree(vreg_priv);
+}
+
+static int __devinit regulator_stub_probe(struct platform_device *pdev)
+{
+ struct stub_regulator_pdata *vreg_pdata;
+ struct regulator_desc *rdesc;
+ struct regulator_stub *vreg_priv;
+ int rc;
+
+ vreg_pdata = pdev->dev.platform_data;
+ if (!vreg_pdata) {
+ dev_err(&pdev->dev, "%s: no platform data\n", __func__);
+ return -EINVAL;
+ }
+
+ vreg_priv = kzalloc(sizeof(*vreg_priv), GFP_KERNEL);
+ if (!vreg_priv) {
+ dev_err(&pdev->dev, "%s: Unable to allocate memory\n",
+ __func__);
+ return -ENOMEM;
+ }
+ dev_set_drvdata(&pdev->dev, vreg_priv);
+
+ rdesc = &vreg_priv->rdesc;
+ strncpy(vreg_priv->name, vreg_pdata->init_data.constraints.name,
+ STUB_REGULATOR_MAX_NAME);
+ rdesc->name = vreg_priv->name;
+ rdesc->ops = ®ulator_stub_ops;
+
+ /*
+ * Ensure that voltage set points are handled correctly for regulators
+ * which have a specified voltage constraint range, as well as those
+ * that do not.
+ */
+ if (vreg_pdata->init_data.constraints.min_uV == 0 &&
+ vreg_pdata->init_data.constraints.max_uV == 0)
+ rdesc->n_voltages = 0;
+ else
+ rdesc->n_voltages = 2;
+
+ rdesc->id = pdev->id;
+ rdesc->owner = THIS_MODULE;
+ rdesc->type = REGULATOR_VOLTAGE;
+ vreg_priv->system_uA = vreg_pdata->system_uA;
+ vreg_priv->hpm_min_load = vreg_pdata->hpm_min_load;
+
+ vreg_priv->rdev = regulator_register(rdesc, &pdev->dev,
+ &(vreg_pdata->init_data), vreg_priv);
+ if (IS_ERR(vreg_priv->rdev)) {
+ rc = PTR_ERR(vreg_priv->rdev);
+ vreg_priv->rdev = NULL;
+ dev_err(&pdev->dev, "%s: regulator_register failed\n",
+ __func__);
+ goto err_probe;
+ }
+
+ return 0;
+
+err_probe:
+ regulator_stub_cleanup(vreg_priv);
+ return rc;
+}
+
+static int __devexit regulator_stub_remove(struct platform_device *pdev)
+{
+ struct regulator_stub *vreg_priv = dev_get_drvdata(&pdev->dev);
+
+ regulator_stub_cleanup(vreg_priv);
+ return 0;
+}
+
+static struct platform_driver regulator_stub_driver = {
+ .probe = regulator_stub_probe,
+ .remove = __devexit_p(regulator_stub_remove),
+ .driver = {
+ .name = STUB_REGULATOR_DRIVER_NAME,
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init regulator_stub_init(void)
+{
+ return platform_driver_register(®ulator_stub_driver);
+}
+postcore_initcall(regulator_stub_init);
+
+static void __exit regulator_stub_exit(void)
+{
+ platform_driver_unregister(®ulator_stub_driver);
+}
+module_exit(regulator_stub_exit);
+
+MODULE_LICENSE("GPL v2");
+MODULE_DESCRIPTION("stub regulator driver");
+MODULE_VERSION("1.0");
+MODULE_ALIAS("platform: " STUB_REGULATOR_DRIVER_NAME);
diff --git a/include/linux/regulator/stub-regulator.h b/include/linux/regulator/stub-regulator.h
new file mode 100644
index 0000000..1119c51
--- /dev/null
+++ b/include/linux/regulator/stub-regulator.h
@@ -0,0 +1,33 @@
+/* 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 __STUB_REGULATOR_H__
+#define __STUB_REGULATOR_H__
+
+#include <linux/regulator/machine.h>
+
+#define STUB_REGULATOR_DRIVER_NAME "stub-regulator"
+
+/**
+ * struct stub_regulator_pdata - stub regulator device data
+ * @init_data: regulator constraints
+ * @hpm_min_load: minimum load in uA that will result in the regulator
+ * being set to high power mode
+ * @system_uA: current drawn from regulator not accounted for by any
+ * regulator framework consumer
+ */
+struct stub_regulator_pdata {
+ struct regulator_init_data init_data;
+ int hpm_min_load;
+ int system_uA;
+};
+#endif