aboutsummaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 11:56:38 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2013-07-03 11:56:38 -0700
commit76f7a102c0290d3e24703b6cd3716d5a594d6173 (patch)
tree93c1558d63f217bd48c5accc7347bab4b5526904 /drivers/regulator
parent92295f632cefbdf15d46e9ac5f0fc3cfade35259 (diff)
parent70083c4c8c60d9ddc188f51e0960574badc919af (diff)
Merge tag 'regulator-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown: "Very quiet release here, as well as the usual driver specific updates only a couple of new things: - New drivers for TI ABB LDOs and MAX77693 PMICs - Support for enabling bypass mode support via device tree" * tag 'regulator-v3.11' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (23 commits) regulator: max77693: Remove NULL test for rmatch[i].init_data regulator: max77693: Fix trivial typo regulator: ab8500-ext: Staticize local symbols regulator: max77693: Add max77693 regualtor driver. regulator: max8973: fix a typo in documentation regulator: max8973: initial DT support regulators: max8973: fix multiple instance support regulator: of: Added a property to indicate bypass mode support regulator: ti-abb: Convert to use devm_ioremap_resource regulator: tps62360: Fix crash in i2c_driver .probe regulator: ab8500: Provide supply names for the AUX regulators regulator: ab8500-ext: Enable for Device Tree regulator: ab8500-ext: Register as a device in its own right regulator: ab8500-ext: Provide a set_voltage call-back operation regulator: ab8500: Ensure AB8500 external registers are probed first regulator: core: add regulator_get_linear_step() regulator: lp397x: use devm_kzalloc() to make cleanup paths simpler regulator: lp872x: support the device tree feature regulator: Remove unnecessary include of linux/delay.h from regulator drivers regulator: isl6271a: Use NULL instead of 0 ...
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/88pm8607.c1
-rw-r--r--drivers/regulator/Kconfig19
-rw-r--r--drivers/regulator/Makefile4
-rw-r--r--drivers/regulator/ab8500-ext.c82
-rw-r--r--drivers/regulator/ab8500.c20
-rw-r--r--drivers/regulator/core.c15
-rw-r--r--drivers/regulator/isl6271a-regulator.c2
-rw-r--r--drivers/regulator/lp3971.c11
-rw-r--r--drivers/regulator/lp3972.c11
-rw-r--r--drivers/regulator/lp872x.c116
-rw-r--r--drivers/regulator/lp8755.c1
-rw-r--r--drivers/regulator/lp8788-buck.c1
-rw-r--r--drivers/regulator/lp8788-ldo.c2
-rw-r--r--drivers/regulator/max77686.c1
-rw-r--r--drivers/regulator/max77693.c322
-rw-r--r--drivers/regulator/max8925-regulator.c1
-rw-r--r--drivers/regulator/max8973-regulator.c49
-rw-r--r--drivers/regulator/mc13783-regulator.c2
-rw-r--r--drivers/regulator/mc13892-regulator.c2
-rw-r--r--drivers/regulator/of_regulator.c3
-rw-r--r--drivers/regulator/pcap-regulator.c1
-rw-r--r--drivers/regulator/pcf50633-regulator.c1
-rw-r--r--drivers/regulator/s2mps11.c1
-rw-r--r--drivers/regulator/ti-abb-regulator.c910
-rw-r--r--drivers/regulator/tps62360-regulator.c8
-rw-r--r--drivers/regulator/tps65217-regulator.c2
-rw-r--r--drivers/regulator/virtual.c2
-rw-r--r--drivers/regulator/wm831x-dcdc.c7
-rw-r--r--drivers/regulator/wm831x-isink.c2
-rw-r--r--drivers/regulator/wm831x-ldo.c2
-rw-r--r--drivers/regulator/wm8400-regulator.c1
-rw-r--r--drivers/regulator/wm8994-regulator.c2
32 files changed, 1514 insertions, 90 deletions
diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c
index 493948a38fc..8a7cb1f4304 100644
--- a/drivers/regulator/88pm8607.c
+++ b/drivers/regulator/88pm8607.c
@@ -406,7 +406,6 @@ static int pm8607_regulator_remove(struct platform_device *pdev)
{
struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
- platform_set_drvdata(pdev, NULL);
regulator_unregister(info->regulator);
return 0;
}
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 8bb26446037..f1e6ad98eeb 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -250,6 +250,15 @@ config REGULATOR_MAX77686
via I2C bus. The provided regulator is suitable for
Exynos-4 chips to control VARM and VINT voltages.
+config REGULATOR_MAX77693
+ tristate "Maxim MAX77693 regulator"
+ depends on MFD_MAX77693
+ help
+ This driver controls a Maxim 77693 regulator via I2C bus.
+ The regulators include two LDOs, 'SAFEOUT1', 'SAFEOUT2'
+ and one current regulator 'CHARGER'. This is suitable for
+ Exynos-4x12 chips.
+
config REGULATOR_PCAP
tristate "Motorola PCAP2 regulator driver"
depends on EZX_PCAP
@@ -472,6 +481,16 @@ config REGULATOR_TWL4030
This driver supports the voltage regulators provided by
this family of companion chips.
+config REGULATOR_TI_ABB
+ bool "TI Adaptive Body Bias on-chip LDO"
+ depends on ARCH_OMAP
+ help
+ Select this option to support Texas Instruments' on-chip Adaptive Body
+ Bias (ABB) LDO regulators. It is recommended that this option be
+ enabled on required TI SoC. Certain Operating Performance Points
+ on TI SoCs may be unstable without enabling this as it provides
+ device specific optimized bias to allow/optimize functionality.
+
config REGULATOR_VEXPRESS
tristate "Versatile Express regulators"
depends on VEXPRESS_CONFIG
diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile
index 47a34ff88f9..ba4a3cf3afe 100644
--- a/drivers/regulator/Makefile
+++ b/drivers/regulator/Makefile
@@ -12,7 +12,7 @@ obj-$(CONFIG_REGULATOR_USERSPACE_CONSUMER) += userspace-consumer.o
obj-$(CONFIG_REGULATOR_88PM8607) += 88pm8607.o
obj-$(CONFIG_REGULATOR_AAT2870) += aat2870-regulator.o
obj-$(CONFIG_REGULATOR_AB3100) += ab3100.o
-obj-$(CONFIG_REGULATOR_AB8500) += ab8500.o ab8500-ext.o
+obj-$(CONFIG_REGULATOR_AB8500) += ab8500-ext.o ab8500.o
obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
@@ -41,6 +41,7 @@ obj-$(CONFIG_REGULATOR_MAX8973) += max8973-regulator.o
obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o
obj-$(CONFIG_REGULATOR_MAX8998) += max8998.o
obj-$(CONFIG_REGULATOR_MAX77686) += max77686.o
+obj-$(CONFIG_REGULATOR_MAX77693) += max77693.o
obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
obj-$(CONFIG_REGULATOR_MC13XXX_CORE) += mc13xxx-regulator-core.o
@@ -63,6 +64,7 @@ obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
diff --git a/drivers/regulator/ab8500-ext.c b/drivers/regulator/ab8500-ext.c
index b4d45472aae..02ff691cdb8 100644
--- a/drivers/regulator/ab8500-ext.c
+++ b/drivers/regulator/ab8500-ext.c
@@ -16,9 +16,11 @@
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/module.h>
+#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
#include <linux/mfd/abx500.h>
#include <linux/mfd/abx500/ab8500.h>
#include <linux/regulator/ab8500.h>
@@ -229,6 +231,28 @@ static unsigned int ab8500_ext_regulator_get_mode(struct regulator_dev *rdev)
return ret;
}
+static int ab8500_ext_set_voltage(struct regulator_dev *rdev, int min_uV,
+ int max_uV, unsigned *selector)
+{
+ struct regulation_constraints *regu_constraints = rdev->constraints;
+
+ if (!regu_constraints) {
+ dev_err(rdev_get_dev(rdev), "No regulator constraints\n");
+ return -EINVAL;
+ }
+
+ if (regu_constraints->min_uV == min_uV &&
+ regu_constraints->max_uV == max_uV)
+ return 0;
+
+ dev_err(rdev_get_dev(rdev),
+ "Requested min %duV max %duV != constrained min %duV max %duV\n",
+ min_uV, max_uV,
+ regu_constraints->min_uV, regu_constraints->max_uV);
+
+ return -EINVAL;
+}
+
static int ab8500_ext_list_voltage(struct regulator_dev *rdev,
unsigned selector)
{
@@ -252,6 +276,7 @@ static struct regulator_ops ab8500_ext_regulator_ops = {
.is_enabled = ab8500_ext_regulator_is_enabled,
.set_mode = ab8500_ext_regulator_set_mode,
.get_mode = ab8500_ext_regulator_get_mode,
+ .set_voltage = ab8500_ext_set_voltage,
.list_voltage = ab8500_ext_list_voltage,
};
@@ -310,18 +335,37 @@ static struct ab8500_ext_regulator_info
},
};
-int ab8500_ext_regulator_init(struct platform_device *pdev)
+static struct of_regulator_match ab8500_ext_regulator_match[] = {
+ { .name = "ab8500_ext1", .driver_data = (void *) AB8500_EXT_SUPPLY1, },
+ { .name = "ab8500_ext2", .driver_data = (void *) AB8500_EXT_SUPPLY2, },
+ { .name = "ab8500_ext3", .driver_data = (void *) AB8500_EXT_SUPPLY3, },
+};
+
+static int ab8500_ext_regulator_probe(struct platform_device *pdev)
{
struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
struct ab8500_platform_data *ppdata;
struct ab8500_regulator_platform_data *pdata;
+ struct device_node *np = pdev->dev.of_node;
struct regulator_config config = { };
int i, err;
+ if (np) {
+ err = of_regulator_match(&pdev->dev, np,
+ ab8500_ext_regulator_match,
+ ARRAY_SIZE(ab8500_ext_regulator_match));
+ if (err < 0) {
+ dev_err(&pdev->dev,
+ "Error parsing regulator init data: %d\n", err);
+ return err;
+ }
+ }
+
if (!ab8500) {
dev_err(&pdev->dev, "null mfd parent\n");
return -EINVAL;
}
+
ppdata = dev_get_platdata(ab8500->dev);
if (!ppdata) {
dev_err(&pdev->dev, "null parent pdata\n");
@@ -362,8 +406,11 @@ int ab8500_ext_regulator_init(struct platform_device *pdev)
pdata->ext_regulator[i].driver_data;
config.dev = &pdev->dev;
- config.init_data = &pdata->ext_regulator[i];
config.driver_data = info;
+ config.of_node = ab8500_ext_regulator_match[i].of_node;
+ config.init_data = (np) ?
+ ab8500_ext_regulator_match[i].init_data :
+ &pdata->ext_regulator[i];
/* register regulator with framework */
info->rdev = regulator_register(&info->desc, &config);
@@ -386,7 +433,7 @@ int ab8500_ext_regulator_init(struct platform_device *pdev)
return 0;
}
-void ab8500_ext_regulator_exit(struct platform_device *pdev)
+static int ab8500_ext_regulator_remove(struct platform_device *pdev)
{
int i;
@@ -399,7 +446,36 @@ void ab8500_ext_regulator_exit(struct platform_device *pdev)
regulator_unregister(info->rdev);
}
+
+ return 0;
+}
+
+static struct platform_driver ab8500_ext_regulator_driver = {
+ .probe = ab8500_ext_regulator_probe,
+ .remove = ab8500_ext_regulator_remove,
+ .driver = {
+ .name = "ab8500-ext-regulator",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init ab8500_ext_regulator_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&ab8500_ext_regulator_driver);
+ if (ret)
+ pr_err("Failed to register ab8500 ext regulator: %d\n", ret);
+
+ return ret;
+}
+subsys_initcall(ab8500_ext_regulator_init);
+
+static void __exit ab8500_ext_regulator_exit(void)
+{
+ platform_driver_unregister(&ab8500_ext_regulator_driver);
}
+module_exit(ab8500_ext_regulator_exit);
MODULE_LICENSE("GPL v2");
MODULE_AUTHOR("Bengt Jonsson <bengt.g.jonsson@stericsson.com>");
diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c
index a19045ee0ec..603f192e84f 100644
--- a/drivers/regulator/ab8500.c
+++ b/drivers/regulator/ab8500.c
@@ -719,6 +719,7 @@ static struct ab8500_regulator_info
.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
.volt_table = ldo_vauxn_voltages,
.enable_time = 200,
+ .supply_name = "vin",
},
.load_lp_uA = 5000,
.update_bank = 0x04,
@@ -741,6 +742,7 @@ static struct ab8500_regulator_info
.n_voltages = ARRAY_SIZE(ldo_vauxn_voltages),
.volt_table = ldo_vauxn_voltages,
.enable_time = 200,
+ .supply_name = "vin",
},
.load_lp_uA = 5000,
.update_bank = 0x04,
@@ -763,6 +765,7 @@ static struct ab8500_regulator_info
.n_voltages = ARRAY_SIZE(ldo_vaux3_voltages),
.volt_table = ldo_vaux3_voltages,
.enable_time = 450,
+ .supply_name = "vin",
},
.load_lp_uA = 5000,
.update_bank = 0x04,
@@ -3156,22 +3159,12 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
return err;
}
- if (!is_ab8505(ab8500)) {
- /* register external regulators (before Vaux1, 2 and 3) */
- err = ab8500_ext_regulator_init(pdev);
- if (err)
- return err;
- }
-
/* register all regulators */
for (i = 0; i < abx500_regulator.info_size; i++) {
err = ab8500_regulator_register(pdev, &pdata->regulator[i],
i, NULL);
- if (err < 0) {
- if (!is_ab8505(ab8500))
- ab8500_ext_regulator_exit(pdev);
+ if (err < 0)
return err;
- }
}
return 0;
@@ -3180,7 +3173,6 @@ static int ab8500_regulator_probe(struct platform_device *pdev)
static int ab8500_regulator_remove(struct platform_device *pdev)
{
int i, err;
- struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
for (i = 0; i < abx500_regulator.info_size; i++) {
struct ab8500_regulator_info *info = NULL;
@@ -3192,10 +3184,6 @@ static int ab8500_regulator_remove(struct platform_device *pdev)
regulator_unregister(info->regulator);
}
- /* remove external regulators (after Vaux1, 2 and 3) */
- if (!is_ab8505(ab8500))
- ab8500_ext_regulator_exit(pdev);
-
/* remove regulator debug */
err = ab8500_regulator_debug_exit(pdev);
if (err)
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 815d6df8bd5..288c75abc19 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2138,6 +2138,21 @@ int regulator_list_voltage(struct regulator *regulator, unsigned selector)
EXPORT_SYMBOL_GPL(regulator_list_voltage);
/**
+ * regulator_get_linear_step - return the voltage step size between VSEL values
+ * @regulator: regulator source
+ *
+ * Returns the voltage step size between VSEL values for linear
+ * regulators, or return 0 if the regulator isn't a linear regulator.
+ */
+unsigned int regulator_get_linear_step(struct regulator *regulator)
+{
+ struct regulator_dev *rdev = regulator->rdev;
+
+ return rdev->desc->uV_step;
+}
+EXPORT_SYMBOL_GPL(regulator_get_linear_step);
+
+/**
* regulator_is_supported_voltage - check if a voltage range can be supported
*
* @regulator: Regulator to check.
diff --git a/drivers/regulator/isl6271a-regulator.c b/drivers/regulator/isl6271a-regulator.c
index d1e5bee2a26..b99c49b9aff 100644
--- a/drivers/regulator/isl6271a-regulator.c
+++ b/drivers/regulator/isl6271a-regulator.c
@@ -130,7 +130,7 @@ static int isl6271a_probe(struct i2c_client *i2c,
if (i == 0)
config.init_data = init_data;
else
- config.init_data = 0;
+ config.init_data = NULL;
config.driver_data = pmic;
pmic->rdev[i] = regulator_register(&isl_rd[i], &config);
diff --git a/drivers/regulator/lp3971.c b/drivers/regulator/lp3971.c
index d8af9e77331..3809b438160 100644
--- a/drivers/regulator/lp3971.c
+++ b/drivers/regulator/lp3971.c
@@ -434,7 +434,7 @@ static int lp3971_i2c_probe(struct i2c_client *i2c,
return -ENODEV;
}
- lp3971 = kzalloc(sizeof(struct lp3971), GFP_KERNEL);
+ lp3971 = devm_kzalloc(&i2c->dev, sizeof(struct lp3971), GFP_KERNEL);
if (lp3971 == NULL)
return -ENOMEM;
@@ -449,19 +449,15 @@ static int lp3971_i2c_probe(struct i2c_client *i2c,
ret = -ENODEV;
if (ret < 0) {
dev_err(&i2c->dev, "failed to detect device\n");
- goto err_detect;
+ return ret;
}
ret = setup_regulators(lp3971, pdata);
if (ret < 0)
- goto err_detect;
+ return ret;
i2c_set_clientdata(i2c, lp3971);
return 0;
-
-err_detect:
- kfree(lp3971);
- return ret;
}
static int lp3971_i2c_remove(struct i2c_client *i2c)
@@ -473,7 +469,6 @@ static int lp3971_i2c_remove(struct i2c_client *i2c)
regulator_unregister(lp3971->rdev[i]);
kfree(lp3971->rdev);
- kfree(lp3971);
return 0;
}
diff --git a/drivers/regulator/lp3972.c b/drivers/regulator/lp3972.c
index 61e4cf9edf6..573024039ca 100644
--- a/drivers/regulator/lp3972.c
+++ b/drivers/regulator/lp3972.c
@@ -528,7 +528,7 @@ static int lp3972_i2c_probe(struct i2c_client *i2c,
return -ENODEV;
}
- lp3972 = kzalloc(sizeof(struct lp3972), GFP_KERNEL);
+ lp3972 = devm_kzalloc(&i2c->dev, sizeof(struct lp3972), GFP_KERNEL);
if (!lp3972)
return -ENOMEM;
@@ -546,19 +546,15 @@ static int lp3972_i2c_probe(struct i2c_client *i2c,
}
if (ret < 0) {
dev_err(&i2c->dev, "failed to detect device. ret = %d\n", ret);
- goto err_detect;
+ return ret;
}
ret = setup_regulators(lp3972, pdata);
if (ret < 0)
- goto err_detect;
+ return ret;
i2c_set_clientdata(i2c, lp3972);
return 0;
-
-err_detect:
- kfree(lp3972);
- return ret;
}
static int lp3972_i2c_remove(struct i2c_client *i2c)
@@ -569,7 +565,6 @@ static int lp3972_i2c_remove(struct i2c_client *i2c)
for (i = 0; i < lp3972->num_regulators; i++)
regulator_unregister(lp3972->rdev[i]);
kfree(lp3972->rdev);
- kfree(lp3972);
return 0;
}
diff --git a/drivers/regulator/lp872x.c b/drivers/regulator/lp872x.c
index f5fc4a142cd..b16336bcd4d 100644
--- a/drivers/regulator/lp872x.c
+++ b/drivers/regulator/lp872x.c
@@ -18,6 +18,9 @@
#include <linux/regulator/lp872x.h>
#include <linux/regulator/driver.h>
#include <linux/platform_device.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
+#include <linux/regulator/of_regulator.h>
/* Registers : LP8720/8725 shared */
#define LP872X_GENERAL_CFG 0x00
@@ -723,8 +726,8 @@ static int lp872x_init_dvs(struct lp872x *lp)
gpio = dvs->gpio;
if (!gpio_is_valid(gpio)) {
- dev_err(lp->dev, "invalid gpio: %d\n", gpio);
- return -EINVAL;
+ dev_warn(lp->dev, "invalid gpio: %d\n", gpio);
+ goto set_default_dvs_mode;
}
pinstate = dvs->init_state;
@@ -829,6 +832,103 @@ static const struct regmap_config lp872x_regmap_config = {
.max_register = MAX_REGISTERS,
};
+#ifdef CONFIG_OF
+
+#define LP872X_VALID_OPMODE (REGULATOR_MODE_FAST | REGULATOR_MODE_NORMAL)
+
+static struct of_regulator_match lp8720_matches[] = {
+ { .name = "ldo1", .driver_data = (void *)LP8720_ID_LDO1, },
+ { .name = "ldo2", .driver_data = (void *)LP8720_ID_LDO2, },
+ { .name = "ldo3", .driver_data = (void *)LP8720_ID_LDO3, },
+ { .name = "ldo4", .driver_data = (void *)LP8720_ID_LDO4, },
+ { .name = "ldo5", .driver_data = (void *)LP8720_ID_LDO5, },
+ { .name = "buck", .driver_data = (void *)LP8720_ID_BUCK, },
+};
+
+static struct of_regulator_match lp8725_matches[] = {
+ { .name = "ldo1", .driver_data = (void *)LP8725_ID_LDO1, },
+ { .name = "ldo2", .driver_data = (void *)LP8725_ID_LDO2, },
+ { .name = "ldo3", .driver_data = (void *)LP8725_ID_LDO3, },
+ { .name = "ldo4", .driver_data = (void *)LP8725_ID_LDO4, },
+ { .name = "ldo5", .driver_data = (void *)LP8725_ID_LDO5, },
+ { .name = "lilo1", .driver_data = (void *)LP8725_ID_LILO1, },
+ { .name = "lilo2", .driver_data = (void *)LP8725_ID_LILO2, },
+ { .name = "buck1", .driver_data = (void *)LP8725_ID_BUCK1, },
+ { .name = "buck2", .driver_data = (void *)LP8725_ID_BUCK2, },
+};
+
+static struct lp872x_platform_data
+*lp872x_populate_pdata_from_dt(struct device *dev, enum lp872x_id which)
+{
+ struct device_node *np = dev->of_node;
+ struct lp872x_platform_data *pdata;
+ struct of_regulator_match *match;
+ struct regulator_init_data *d;
+ int num_matches;
+ int count;
+ int i;
+ u8 dvs_state;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata)
+ goto out;
+
+ of_property_read_u8(np, "ti,general-config", &pdata->general_config);
+ if (of_find_property(np, "ti,update-config", NULL))
+ pdata->update_config = true;
+
+ pdata->dvs = devm_kzalloc(dev, sizeof(struct lp872x_dvs), GFP_KERNEL);
+ if (!pdata->dvs)
+ goto out;
+
+ pdata->dvs->gpio = of_get_named_gpio(np, "ti,dvs-gpio", 0);
+ of_property_read_u8(np, "ti,dvs-vsel", (u8 *)&pdata->dvs->vsel);
+ of_property_read_u8(np, "ti,dvs-state", &dvs_state);
+ pdata->dvs->init_state = dvs_state ? DVS_HIGH : DVS_LOW;
+
+ if (of_get_child_count(np) == 0)
+ goto out;
+
+ switch (which) {
+ case LP8720:
+ match = lp8720_matches;
+ num_matches = ARRAY_SIZE(lp8720_matches);
+ break;
+ case LP8725:
+ match = lp8725_matches;
+ num_matches = ARRAY_SIZE(lp8725_matches);
+ break;
+ default:
+ goto out;
+ }
+
+ count = of_regulator_match(dev, np, match, num_matches);
+ if (count <= 0)
+ goto out;
+
+ for (i = 0; i < num_matches; i++) {
+ pdata->regulator_data[i].id = (int)match[i].driver_data;
+ pdata->regulator_data[i].init_data = match[i].init_data;
+
+ /* Operation mode configuration for buck/buck1/buck2 */
+ if (strncmp(match[i].name, "buck", 4))
+ continue;
+
+ d = pdata->regulator_data[i].init_data;
+ d->constraints.valid_modes_mask |= LP872X_VALID_OPMODE;
+ d->constraints.valid_ops_mask |= REGULATOR_CHANGE_MODE;
+ }
+out:
+ return pdata;
+}
+#else
+static struct lp872x_platform_data
+*lp872x_populate_pdata_from_dt(struct device *dev, enum lp872x_id which)
+{
+ return NULL;
+}
+#endif
+
static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
{
struct lp872x *lp;
@@ -838,6 +938,10 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
[LP8725] = LP8725_NUM_REGULATORS,
};
+ if (cl->dev.of_node)
+ cl->dev.platform_data = lp872x_populate_pdata_from_dt(&cl->dev,
+ (enum lp872x_id)id->driver_data);
+
lp = devm_kzalloc(&cl->dev, sizeof(struct lp872x), GFP_KERNEL);
if (!lp)
goto err_mem;
@@ -882,6 +986,13 @@ static int lp872x_remove(struct i2c_client *cl)
return 0;
}
+static const struct of_device_id lp872x_dt_ids[] = {
+ { .compatible = "ti,lp8720", },
+ { .compatible = "ti,lp8725", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, lp872x_dt_ids);
+
static const struct i2c_device_id lp872x_ids[] = {
{"lp8720", LP8720},
{"lp8725", LP8725},
@@ -893,6 +1004,7 @@ static struct i2c_driver lp872x_driver = {
.driver = {
.name = "lp872x",
.owner = THIS_MODULE,
+ .of_match_table = of_match_ptr(lp872x_dt_ids),
},
.probe = lp872x_probe,
.remove = lp872x_remove,
diff --git a/drivers/regulator/lp8755.c b/drivers/regulator/lp8755.c
index f0f6ea05065..d9e38b4c2ad 100644
--- a/drivers/regulator/lp8755.c
+++ b/drivers/regulator/lp8755.c
@@ -19,7 +19,6 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
#include <linux/regmap.h>
-#include <linux/delay.h>
#include <linux/uaccess.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
diff --git a/drivers/regulator/lp8788-buck.c b/drivers/regulator/lp8788-buck.c
index eb1e1e88ae5..0b015f2a7fd 100644
--- a/drivers/regulator/lp8788-buck.c
+++ b/drivers/regulator/lp8788-buck.c
@@ -533,7 +533,6 @@ static int lp8788_buck_remove(struct platform_device *pdev)
{
struct lp8788_buck *buck = platform_get_drvdata(pdev);
- platform_set_drvdata(pdev, NULL);
regulator_unregister(buck->regulator);
return 0;
diff --git a/drivers/regulator/lp8788-ldo.c b/drivers/regulator/lp8788-ldo.c
index 0ce2c4c194b..0527d87c6dd 100644
--- a/drivers/regulator/lp8788-ldo.c
+++ b/drivers/regulator/lp8788-ldo.c
@@ -561,7 +561,6 @@ static int lp8788_dldo_remove(struct platform_device *pdev)
{
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
- platform_set_drvdata(pdev, NULL);
regulator_unregister(ldo->regulator);
return 0;
@@ -622,7 +621,6 @@ static int lp8788_aldo_remove(struct platform_device *pdev)
{
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
- platform_set_drvdata(pdev, NULL);
regulator_unregister(ldo->regulator);
return 0;
diff --git a/drivers/regulator/max77686.c b/drivers/regulator/max77686.c
index 20935b1a6ed..f563057e569 100644
--- a/drivers/regulator/max77686.c
+++ b/drivers/regulator/max77686.c
@@ -24,7 +24,6 @@
#include <linux/kernel.h>
#include <linux/bug.h>
-#include <linux/delay.h>
#include <linux/err.h>
#include <linux/gpio.h>
#include <linux/slab.h>
diff --git a/drivers/regulator/max77693.c b/drivers/regulator/max77693.c
new file mode 100644
index 00000000000..ce4b96c15eb
--- /dev/null
+++ b/drivers/regulator/max77693.c
@@ -0,0 +1,322 @@
+/*
+ * max77693.c - Regulator driver for the Maxim 77693
+ *
+ * Copyright (C) 2013 Samsung Electronics
+ * Jonghwa Lee <jonghwa3.lee@samsung.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * This driver is based on max77686.c
+ */
+
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/platform_device.h>
+#include <linux/module.h>
+#include <linux/export.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/mfd/max77693.h>
+#include <linux/mfd/max77693-private.h>
+#include <linux/regulator/of_regulator.h>
+
+#define CHGIN_ILIM_STEP_20mA 20000
+
+struct max77693_pmic_dev {
+ struct device *dev;
+ struct max77693_dev *iodev;
+ int num_regulators;
+ struct regulator_dev **rdev;
+};
+
+/* CHARGER regulator ops */
+/* CHARGER regulator uses two bits for enabling */
+static int max77693_chg_is_enabled(struct regulator_dev *rdev)
+{
+ int ret;
+ u8 val;
+
+ ret = max77693_read_reg(rdev->regmap, rdev->desc->enable_reg, &val);
+ if (ret)
+ return ret;
+
+ return (val & rdev->desc->enable_mask) == rdev->desc->enable_mask;
+}
+
+/*
+ * CHARGER regulator - Min : 20mA, Max : 2580mA, step : 20mA
+ * 0x00, 0x01, 0x2, 0x03 = 60 mA
+ * 0x04 ~ 0x7E = (60 + (X - 3) * 20) mA
+ */
+static int max77693_chg_get_current_limit(struct regulator_dev *rdev)
+{
+ unsigned int chg_min_uA = rdev->constraints->min_uA;
+ unsigned int chg_max_uA = rdev->constraints->max_uA;
+ u8 reg, sel;
+ unsigned int val;
+ int ret;
+
+ ret = max77693_read_reg(rdev->regmap,
+ MAX77693_CHG_REG_CHG_CNFG_09, &reg);
+ if (ret < 0)
+ return ret;
+
+ sel = reg & CHG_CNFG_09_CHGIN_ILIM_MASK;
+
+ /* the first four codes for charger current are all 60mA */
+ if (sel <= 3)
+ sel = 0;
+ else
+ sel -= 3;
+
+ val = chg_min_uA + CHGIN_ILIM_STEP_20mA * sel;
+ if (val > chg_max_uA)
+ return -EINVAL;
+
+ return val;
+}
+
+static int max77693_chg_set_current_limit(struct regulator_dev *rdev,
+ int min_uA, int max_uA)
+{
+ unsigned int chg_min_uA = rdev->constraints->min_uA;
+ int sel = 0;
+
+ while (chg_min_uA + CHGIN_ILIM_STEP_20mA * sel < min_uA)
+ sel++;
+
+ if (chg_min_uA + CHGIN_ILIM_STEP_20mA * sel > max_uA)
+ return -EINVAL;
+
+ /* the first four codes for charger current are all 60mA */
+ sel += 3;
+
+ return max77693_write_reg(rdev->regmap,
+ MAX77693_CHG_REG_CHG_CNFG_09, sel);
+}
+/* end of CHARGER regulator ops */
+
+static const unsigned int max77693_safeout_table[] = {
+ 4850000,
+ 4900000,
+ 4950000,
+ 3300000,
+};