summaryrefslogtreecommitdiffstats
path: root/drivers/regulator
diff options
context:
space:
mode:
authorLaxman Dewangan <ldewangan@nvidia.com>2012-10-09 15:19:02 +0530
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-10-17 22:21:21 +0900
commitf329b1755b475f64f0472cda1ae9602e092f6f05 (patch)
tree3580b525f7626d063bf93e4a1370056f1e605b84 /drivers/regulator
parent3a81ef8c27cea5c749a45765da4e06a7af75be2b (diff)
downloadlinux-f329b1755b475f64f0472cda1ae9602e092f6f05.tar.gz
linux-f329b1755b475f64f0472cda1ae9602e092f6f05.tar.bz2
linux-f329b1755b475f64f0472cda1ae9602e092f6f05.zip
regulator: tps65090: add external control support for DCDC
The TPS65090's DCDC output can also be enable/disable through the external digital input signal. Add support for enable/disable either through register access via I2C or through external control inputs. The external control inputs can be driven through GPIOs also and hence adding support for passing the GPIO number. Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/tps65090-regulator.c77
1 files changed, 57 insertions, 20 deletions
diff --git a/drivers/regulator/tps65090-regulator.c b/drivers/regulator/tps65090-regulator.c
index 0732d9ba3f40..412413838e12 100644
--- a/drivers/regulator/tps65090-regulator.c
+++ b/drivers/regulator/tps65090-regulator.c
@@ -18,6 +18,7 @@
#include <linux/module.h>
#include <linux/init.h>
+#include <linux/gpio.h>
#include <linux/slab.h>
#include <linux/err.h>
#include <linux/platform_device.h>
@@ -31,10 +32,13 @@ struct tps65090_regulator {
struct regulator_dev *rdev;
};
-static struct regulator_ops tps65090_ops = {
- .enable = regulator_enable_regmap,
- .disable = regulator_disable_regmap,
- .is_enabled = regulator_is_enabled_regmap,
+static struct regulator_ops tps65090_ext_control_ops = {
+};
+
+static struct regulator_ops tps65090_reg_contol_ops = {
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .is_enabled = regulator_is_enabled_regmap,
};
static struct regulator_ops tps65090_ldo_ops = {
@@ -53,16 +57,16 @@ static struct regulator_ops tps65090_ldo_ops = {
}
static struct regulator_desc tps65090_regulator_desc[] = {
- tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_ops),
- tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_ops),
- tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_ops),
- tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_ops),
- tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_ops),
- tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_ops),
- tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_ops),
- tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_ops),
- tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_ops),
- tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_ops),
+ tps65090_REG_DESC(DCDC1, "vsys1", 0x0C, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(DCDC2, "vsys2", 0x0D, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(DCDC3, "vsys3", 0x0E, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET1, "infet1", 0x0F, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET2, "infet2", 0x10, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET3, "infet3", 0x11, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET4, "infet4", 0x12, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET5, "infet5", 0x13, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET6, "infet6", 0x14, tps65090_reg_contol_ops),
+ tps65090_REG_DESC(FET7, "infet7", 0x15, tps65090_reg_contol_ops),
tps65090_REG_DESC(LDO1, "vsys_l1", 0, tps65090_ldo_ops),
tps65090_REG_DESC(LDO2, "vsys_l2", 0, tps65090_ldo_ops),
};
@@ -118,6 +122,22 @@ static int __devinit tps65090_regulator_disable_ext_control(
return tps65090_config_ext_control(ri, false);
}
+static void __devinit tps65090_configure_regulator_config(
+ struct tps65090_regulator_plat_data *tps_pdata,
+ struct regulator_config *config)
+{
+ if (gpio_is_valid(tps_pdata->gpio)) {
+ int gpio_flag = GPIOF_OUT_INIT_LOW;
+
+ if (tps_pdata->reg_init_data->constraints.always_on ||
+ tps_pdata->reg_init_data->constraints.boot_on)
+ gpio_flag = GPIOF_OUT_INIT_HIGH;
+
+ config->ena_gpio = tps_pdata->gpio;
+ config->ena_gpio_flags = gpio_flag;
+ }
+}
+
static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
{
struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
@@ -154,18 +174,24 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
/*
* TPS5090 DCDC support the control from external digital input.
- * It may be possible that during boot, the external control is
- * enabled. Disabling external control for DCDC.
+ * Configure it as per platform data.
*/
if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
- ret = tps65090_regulator_disable_ext_control(
+ if (tps_pdata->enable_ext_control) {
+ tps65090_configure_regulator_config(
+ tps_pdata, &config);
+ ri->desc->ops = &tps65090_ext_control_ops;
+ } else {
+ ret = tps65090_regulator_disable_ext_control(
ri, tps_pdata);
- if (ret < 0) {
- dev_err(&pdev->dev,
+ if (ret < 0) {
+ dev_err(&pdev->dev,
"failed disable ext control\n");
- goto scrub;
+ goto scrub;
+ }
}
}
+
config.dev = &pdev->dev;
config.driver_data = ri;
config.regmap = tps65090_mfd->rmap;
@@ -182,6 +208,17 @@ static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
goto scrub;
}
ri->rdev = rdev;
+
+ /* Enable external control if it is require */
+ if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
+ tps_pdata->enable_ext_control) {
+ ret = tps65090_config_ext_control(ri, true);
+ if (ret < 0) {
+ /* Increment num to get unregister rdev */
+ num++;
+ goto scrub;
+ }
+ }
}
platform_set_drvdata(pdev, pmic);