summaryrefslogtreecommitdiff
path: root/drivers/regulator
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/regulator')
-rw-r--r--drivers/regulator/Kconfig2
-rw-r--r--drivers/regulator/axp20x-regulator.c15
-rw-r--r--drivers/regulator/core.c30
-rw-r--r--drivers/regulator/da9063-regulator.c2
-rw-r--r--drivers/regulator/gpio-regulator.c2
-rw-r--r--drivers/regulator/helpers.c2
-rw-r--r--drivers/regulator/s2mps11.c28
-rw-r--r--drivers/regulator/tps65912-regulator.c613
8 files changed, 173 insertions, 521 deletions
diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig
index 91040ec8e242..c77dc08b1202 100644
--- a/drivers/regulator/Kconfig
+++ b/drivers/regulator/Kconfig
@@ -788,7 +788,7 @@ config REGULATOR_TPS65910
config REGULATOR_TPS65912
tristate "TI TPS65912 Power regulator"
- depends on (MFD_TPS65912_I2C || MFD_TPS65912_SPI)
+ depends on MFD_TPS65912
help
This driver supports TPS65912 voltage regulator chip.
diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c
index 214e815e98eb..514a5e8fdbab 100644
--- a/drivers/regulator/axp20x-regulator.c
+++ b/drivers/regulator/axp20x-regulator.c
@@ -157,7 +157,9 @@ static struct regulator_ops axp20x_ops_sw = {
static const struct regulator_linear_range axp20x_ldo4_ranges[] = {
REGULATOR_LINEAR_RANGE(1250000, 0x0, 0x0, 0),
REGULATOR_LINEAR_RANGE(1300000, 0x1, 0x8, 100000),
- REGULATOR_LINEAR_RANGE(2500000, 0x9, 0xf, 100000),
+ REGULATOR_LINEAR_RANGE(2500000, 0x9, 0x9, 0),
+ REGULATOR_LINEAR_RANGE(2700000, 0xa, 0xb, 100000),
+ REGULATOR_LINEAR_RANGE(3000000, 0xc, 0xf, 100000),
};
static const struct regulator_desc axp20x_regulators[] = {
@@ -215,10 +217,14 @@ static const struct regulator_desc axp22x_regulators[] = {
AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)),
AXP_DESC(AXP22X, ELDO3, "eldo3", "eldoin", 700, 3300, 100,
AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)),
- AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 1800, 3300, 100,
+ /* Note the datasheet only guarantees reliable operation up to
+ * 3.3V, this needs to be enforced via dts provided constraints */
+ AXP_DESC_IO(AXP22X, LDO_IO0, "ldo_io0", "ips", 700, 3800, 100,
AXP22X_LDO_IO0_V_OUT, 0x1f, AXP20X_GPIO0_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
- AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 1800, 3300, 100,
+ /* Note the datasheet only guarantees reliable operation up to
+ * 3.3V, this needs to be enforced via dts provided constraints */
+ AXP_DESC_IO(AXP22X, LDO_IO1, "ldo_io1", "ips", 700, 3800, 100,
AXP22X_LDO_IO1_V_OUT, 0x1f, AXP20X_GPIO1_CTRL, 0x07,
AXP22X_IO_ENABLED, AXP22X_IO_DISABLED),
AXP_DESC_FIXED(AXP22X, RTC_LDO, "rtc_ldo", "ips", 3000),
@@ -238,6 +244,7 @@ static int axp20x_set_dcdc_freq(struct platform_device *pdev, u32 dcdcfreq)
step = 75;
break;
case AXP221_ID:
+ case AXP223_ID:
min = 1800;
max = 4050;
def = 3000;
@@ -316,6 +323,7 @@ static int axp20x_set_dcdc_workmode(struct regulator_dev *rdev, int id, u32 work
break;
case AXP221_ID:
+ case AXP223_ID:
if (id < AXP22X_DCDC1 || id > AXP22X_DCDC5)
return -EINVAL;
@@ -354,6 +362,7 @@ static int axp20x_regulator_probe(struct platform_device *pdev)
nregulators = AXP20X_REG_ID_MAX;
break;
case AXP221_ID:
+ case AXP223_ID:
regulators = axp22x_regulators;
nregulators = AXP22X_REG_ID_MAX;
break;
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 881c37e61f75..6af38691ec48 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1168,17 +1168,6 @@ static int set_machine_constraints(struct regulator_dev *rdev,
}
}
- if (rdev->constraints->active_discharge && ops->set_active_discharge) {
- bool ad_state = (rdev->constraints->active_discharge ==
- REGULATOR_ACTIVE_DISCHARGE_ENABLE) ? true : false;
-
- ret = ops->set_active_discharge(rdev, ad_state);
- if (ret < 0) {
- rdev_err(rdev, "failed to set active discharge\n");
- return ret;
- }
- }
-
print_constraints(rdev);
return 0;
}
@@ -3858,6 +3847,11 @@ static void rdev_init_debugfs(struct regulator_dev *rdev)
&rdev->bypass_count);
}
+static int regulator_register_resolve_supply(struct device *dev, void *data)
+{
+ return regulator_resolve_supply(dev_to_rdev(dev));
+}
+
/**
* regulator_register - register regulator
* @regulator_desc: regulator to register
@@ -4004,8 +3998,11 @@ regulator_register(const struct regulator_desc *regulator_desc,
}
rdev_init_debugfs(rdev);
-out:
mutex_unlock(&regulator_list_mutex);
+
+ /* try to resolve regulators supply since a new one was registered */
+ class_for_each_device(&regulator_class, NULL, NULL,
+ regulator_register_resolve_supply);
kfree(config);
return rdev;
@@ -4016,15 +4013,16 @@ scrub:
regulator_ena_gpio_free(rdev);
device_unregister(&rdev->dev);
/* device core frees rdev */
- rdev = ERR_PTR(ret);
goto out;
wash:
regulator_ena_gpio_free(rdev);
clean:
kfree(rdev);
- rdev = ERR_PTR(ret);
- goto out;
+out:
+ mutex_unlock(&regulator_list_mutex);
+ kfree(config);
+ return ERR_PTR(ret);
}
EXPORT_SYMBOL_GPL(regulator_register);
@@ -4050,8 +4048,8 @@ void regulator_unregister(struct regulator_dev *rdev)
WARN_ON(rdev->open_count);
unset_regulator_supplies(rdev);
list_del(&rdev->list);
- mutex_unlock(&regulator_list_mutex);
regulator_ena_gpio_free(rdev);
+ mutex_unlock(&regulator_list_mutex);
device_unregister(&rdev->dev);
}
EXPORT_SYMBOL_GPL(regulator_unregister);
diff --git a/drivers/regulator/da9063-regulator.c b/drivers/regulator/da9063-regulator.c
index ed9e7e96f877..c6af343f54ea 100644
--- a/drivers/regulator/da9063-regulator.c
+++ b/drivers/regulator/da9063-regulator.c
@@ -900,4 +900,4 @@ module_exit(da9063_regulator_cleanup);
MODULE_AUTHOR("Krystian Garbaciak <krystian.garbaciak@diasemi.com>");
MODULE_DESCRIPTION("DA9063 regulators driver");
MODULE_LICENSE("GPL");
-MODULE_ALIAS("paltform:" DA9063_DRVNAME_REGULATORS);
+MODULE_ALIAS("platform:" DA9063_DRVNAME_REGULATORS);
diff --git a/drivers/regulator/gpio-regulator.c b/drivers/regulator/gpio-regulator.c
index a8718e98674a..83e89e5d4752 100644
--- a/drivers/regulator/gpio-regulator.c
+++ b/drivers/regulator/gpio-regulator.c
@@ -162,6 +162,8 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np,
of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+ if (config->enable_gpio == -EPROBE_DEFER)
+ return ERR_PTR(-EPROBE_DEFER);
/* Fetch GPIOs. - optional property*/
ret = of_gpio_count(np);
diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c
index b1e32e7482e9..bcf38fd5106a 100644
--- a/drivers/regulator/helpers.c
+++ b/drivers/regulator/helpers.c
@@ -460,7 +460,7 @@ int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
if (ret != 0)
return ret;
- *enable = val & rdev->desc->bypass_mask;
+ *enable = (val & rdev->desc->bypass_mask) == rdev->desc->bypass_val_on;
return 0;
}
diff --git a/drivers/regulator/s2mps11.c b/drivers/regulator/s2mps11.c
index d24e2c783dc5..6dfa3502e1f1 100644
--- a/drivers/regulator/s2mps11.c
+++ b/drivers/regulator/s2mps11.c
@@ -308,7 +308,7 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \
}
-#define regulator_desc_s2mps11_buck6_10(num, min, step) { \
+#define regulator_desc_s2mps11_buck67810(num, min, step) { \
.name = "BUCK"#num, \
.id = S2MPS11_BUCK##num, \
.ops = &s2mps11_buck_ops, \
@@ -324,6 +324,22 @@ static struct regulator_ops s2mps11_buck_ops = {
.enable_mask = S2MPS11_ENABLE_MASK \
}
+#define regulator_desc_s2mps11_buck9 { \
+ .name = "BUCK9", \
+ .id = S2MPS11_BUCK9, \
+ .ops = &s2mps11_buck_ops, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .min_uV = MIN_3000_MV, \
+ .uV_step = STEP_25_MV, \
+ .n_voltages = S2MPS11_BUCK9_N_VOLTAGES, \
+ .ramp_delay = S2MPS11_RAMP_DELAY, \
+ .vsel_reg = S2MPS11_REG_B9CTRL2, \
+ .vsel_mask = S2MPS11_BUCK9_VSEL_MASK, \
+ .enable_reg = S2MPS11_REG_B9CTRL1, \
+ .enable_mask = S2MPS11_ENABLE_MASK \
+}
+
static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_ldo(1, STEP_25_MV),
regulator_desc_s2mps11_ldo(2, STEP_50_MV),
@@ -368,11 +384,11 @@ static const struct regulator_desc s2mps11_regulators[] = {
regulator_desc_s2mps11_buck1_4(3),
regulator_desc_s2mps11_buck1_4(4),
regulator_desc_s2mps11_buck5,
- regulator_desc_s2mps11_buck6_10(6, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(7, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(8, MIN_600_MV, STEP_6_25_MV),
- regulator_desc_s2mps11_buck6_10(9, MIN_3000_MV, STEP_25_MV),
- regulator_desc_s2mps11_buck6_10(10, MIN_750_MV, STEP_12_5_MV),
+ regulator_desc_s2mps11_buck67810(6, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(7, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck67810(8, MIN_600_MV, STEP_6_25_MV),
+ regulator_desc_s2mps11_buck9,
+ regulator_desc_s2mps11_buck67810(10, MIN_750_MV, STEP_12_5_MV),
};
static struct regulator_ops s2mps14_reg_ops;
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c
index 9503d5481a52..a4921a70da55 100644
--- a/drivers/regulator/tps65912-regulator.c
+++ b/drivers/regulator/tps65912-regulator.c
@@ -1,541 +1,168 @@
/*
- * tps65912.c -- TI tps65912
+ * Regulator driver for TI TPS65912x PMICs
*
- * Copyright 2011 Texas Instruments Inc.
+ * Copyright (C) 2015 Texas Instruments Incorporated - http://www.ti.com/
+ * Andrew F. Davis <afd@ti.com>
*
- * Author: Margarita Olaya Cabrera <magi@slimlogic.co.uk>
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
*
- * 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 "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether expressed or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License version 2 for more details.
*
- * This driver is based on wm8350 implementation.
+ * Based on the TPS65218 driver and the previous TPS65912 driver by
+ * Margarita Olaya Cabrera <magi@slimlogic.co.uk>
*/
-#include <linux/kernel.h>
#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/err.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
-#include <linux/regulator/machine.h>
-#include <linux/slab.h>
-#include <linux/gpio.h>
-#include <linux/mfd/tps65912.h>
-
-/* DCDC's */
-#define TPS65912_REG_DCDC1 0
-#define TPS65912_REG_DCDC2 1
-#define TPS65912_REG_DCDC3 2
-#define TPS65912_REG_DCDC4 3
-
-/* LDOs */
-#define TPS65912_REG_LDO1 4
-#define TPS65912_REG_LDO2 5
-#define TPS65912_REG_LDO3 6
-#define TPS65912_REG_LDO4 7
-#define TPS65912_REG_LDO5 8
-#define TPS65912_REG_LDO6 9
-#define TPS65912_REG_LDO7 10
-#define TPS65912_REG_LDO8 11
-#define TPS65912_REG_LDO9 12
-#define TPS65912_REG_LDO10 13
-
-/* Number of step-down converters available */
-#define TPS65912_NUM_DCDC 4
-
-/* Number of LDO voltage regulators available */
-#define TPS65912_NUM_LDO 10
-/* Number of total regulators available */
-#define TPS65912_NUM_REGULATOR (TPS65912_NUM_DCDC + TPS65912_NUM_LDO)
-
-#define TPS65912_REG_ENABLED 0x80
-#define OP_SELREG_MASK 0x40
-#define OP_SELREG_SHIFT 6
-
-struct tps_info {
- const char *name;
-};
+#include <linux/mfd/tps65912.h>
-static struct tps_info tps65912_regs[] = {
- {
- .name = "DCDC1",
- },
- {
- .name = "DCDC2",
- },
- {
- .name = "DCDC3",
- },
- {
- .name = "DCDC4",
- },
- {
- .name = "LDO1",
- },
- {
- .name = "LDO2",
- },
- {
- .name = "LDO3",
- },
- {
- .name = "LDO4",
- },
- {
- .name = "LDO5",
- },
- {
- .name = "LDO6",
- },
- {
- .name = "LDO7",
- },
- {
- .name = "LDO8",
- },
- {
- .name = "LDO9",
- },
- {
- .name = "LDO10",
- },
-};
+enum tps65912_regulators { DCDC1, DCDC2, DCDC3, DCDC4, LDO1, LDO2, LDO3,
+ LDO4, LDO5, LDO6, LDO7, LDO8, LDO9, LDO10 };
+
+#define TPS65912_REGULATOR(_name, _id, _of_match, _ops, _vr, _er, _lr) \
+ [_id] = { \
+ .name = _name, \
+ .of_match = _of_match, \
+ .regulators_node = "regulators", \
+ .id = _id, \
+ .ops = &_ops, \
+ .n_voltages = 64, \
+ .type = REGULATOR_VOLTAGE, \
+ .owner = THIS_MODULE, \
+ .vsel_reg = _vr, \
+ .vsel_mask = 0x3f, \
+ .enable_reg = _er, \
+ .enable_mask = BIT(7), \
+ .volt_table = NULL, \
+ .linear_ranges = _lr, \
+ .n_linear_ranges = ARRAY_SIZE(_lr), \
+ }
-struct tps65912_reg {
- struct regulator_desc desc[TPS65912_NUM_REGULATOR];
- struct tps65912 *mfd;
- struct regulator_dev *rdev[TPS65912_NUM_REGULATOR];
- struct tps_info *info[TPS65912_NUM_REGULATOR];
- /* for read/write access */
- struct mutex io_lock;
- int mode;
- int (*get_ctrl_reg)(int);
- int dcdc_range[TPS65912_NUM_DCDC];
- int pwm_mode_reg;
- int eco_reg;
+static const struct regulator_linear_range tps65912_dcdc_ranges[] = {
+ REGULATOR_LINEAR_RANGE(500000, 0x0, 0x3f, 50000),
};
static const struct regulator_linear_range tps65912_ldo_ranges[] = {
- REGULATOR_LINEAR_RANGE(800000, 0, 32, 25000),
- REGULATOR_LINEAR_RANGE(1650000, 33, 60, 50000),
- REGULATOR_LINEAR_RANGE(3100000, 61, 63, 100000),
+ REGULATOR_LINEAR_RANGE(800000, 0x0, 0x20, 25000),
+ REGULATOR_LINEAR_RANGE(1650000, 0x21, 0x3c, 50000),
+ REGULATOR_LINEAR_RANGE(3100000, 0x3d, 0x3f, 100000),
};
-static int tps65912_get_range(struct tps65912_reg *pmic, int id)
-{
- struct tps65912 *mfd = pmic->mfd;
- int range;
-
- switch (id) {
- case TPS65912_REG_DCDC1:
- range = tps65912_reg_read(mfd, TPS65912_DCDC1_LIMIT);
- break;
- case TPS65912_REG_DCDC2:
- range = tps65912_reg_read(mfd, TPS65912_DCDC2_LIMIT);
- break;
- case TPS65912_REG_DCDC3:
- range = tps65912_reg_read(mfd, TPS65912_DCDC3_LIMIT);
- break;
- case TPS65912_REG_DCDC4:
- range = tps65912_reg_read(mfd, TPS65912_DCDC4_LIMIT);
- break;
- default:
- return 0;
- }
-
- if (range >= 0)
- range = (range & DCDC_LIMIT_RANGE_MASK)
- >> DCDC_LIMIT_RANGE_SHIFT;
-
- pmic->dcdc_range[id] = range;
- return range;
-}
-
-static unsigned long tps65912_vsel_to_uv_range0(u8 vsel)
-{
- unsigned long uv;
-
- uv = ((vsel * 12500) + 500000);
- return uv;
-}
-
-static unsigned long tps65912_vsel_to_uv_range1(u8 vsel)
-{
- unsigned long uv;
-
- uv = ((vsel * 12500) + 700000);
- return uv;
-}
-
-static unsigned long tps65912_vsel_to_uv_range2(u8 vsel)
-{
- unsigned long uv;
-
- uv = ((vsel * 25000) + 500000);
- return uv;
-}
-
-static unsigned long tps65912_vsel_to_uv_range3(u8 vsel)
-{
- unsigned long uv;
-
- if (vsel == 0x3f)
- uv = 3800000;
- else
- uv = ((vsel * 50000) + 500000);
-
- return uv;
-}
-
-static int tps65912_get_ctrl_register(int id)
-{
- if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4)
- return id * 3 + TPS65912_DCDC1_AVS;
- else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10)
- return id - TPS65912_REG_LDO5 + TPS65912_LDO5;
- else
- return -EINVAL;
-}
-
-static int tps65912_get_sel_register(struct tps65912_reg *pmic, int id)
-{
- struct tps65912 *mfd = pmic->mfd;
- int opvsel;
- u8 reg = 0;
-
- if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4) {
- opvsel = tps65912_reg_read(mfd, id * 3 + TPS65912_DCDC1_OP);
- if (opvsel & OP_SELREG_MASK)
- reg = id * 3 + TPS65912_DCDC1_AVS;
- else
- reg = id * 3 + TPS65912_DCDC1_OP;
- } else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10) {
- reg = id - TPS65912_REG_LDO5 + TPS65912_LDO5;
- } else {
- return -EINVAL;
- }
-
- return reg;
-}
-
-static int tps65912_get_mode_regiters(struct tps65912_reg *pmic, int id)
-{
- switch (id) {
- case TPS65912_REG_DCDC1:
- pmic->pwm_mode_reg = TPS65912_DCDC1_CTRL;
- pmic->eco_reg = TPS65912_DCDC1_AVS;
- break;
- case TPS65912_REG_DCDC2:
- pmic->pwm_mode_reg = TPS65912_DCDC2_CTRL;
- pmic->eco_reg = TPS65912_DCDC2_AVS;
- break;
- case TPS65912_REG_DCDC3:
- pmic->pwm_mode_reg = TPS65912_DCDC3_CTRL;
- pmic->eco_reg = TPS65912_DCDC3_AVS;
- break;
- case TPS65912_REG_DCDC4:
- pmic->pwm_mode_reg = TPS65912_DCDC4_CTRL;
- pmic->eco_reg = TPS65912_DCDC4_AVS;
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int tps65912_reg_is_enabled(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int reg, value, id = rdev_get_id(dev);
-
- if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
- return -EINVAL;
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- value = tps65912_reg_read(mfd, reg);
- if (value < 0)
- return value;
-
- return value & TPS65912_REG_ENABLED;
-}
-
-static int tps65912_reg_enable(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev);
- int reg;
-
- if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_LDO10)
- return -EINVAL;
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- return tps65912_set_bits(mfd, reg, TPS65912_REG_ENABLED);
-}
-
-static int tps65912_reg_disable(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev), reg;
-
- reg = pmic->get_ctrl_reg(id);
- if (reg < 0)
- return reg;
-
- return tps65912_clear_bits(mfd, reg, TPS65912_REG_ENABLED);
-}
-
-static int tps65912_set_mode(struct regulator_dev *dev, unsigned int mode)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int pwm_mode, eco, id = rdev_get_id(dev);
-
- tps65912_get_mode_regiters(pmic, id);
-
- pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
- eco = tps65912_reg_read(mfd, pmic->eco_reg);
-
- pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
- eco &= DCDC_AVS_ECO_MASK;
-
- switch (mode) {
- case REGULATOR_MODE_FAST:
- /* Verify if mode alredy set */
- if (pwm_mode && !eco)
- break;
- tps65912_set_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
- tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
- break;
- case REGULATOR_MODE_NORMAL:
- case REGULATOR_MODE_IDLE:
- if (!pwm_mode && !eco)
- break;
- tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
- tps65912_clear_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
- break;
- case REGULATOR_MODE_STANDBY:
- if (!pwm_mode && eco)
- break;
- tps65912_clear_bits(mfd, pmic->pwm_mode_reg, DCDCCTRL_DCDC_MODE_MASK);
- tps65912_set_bits(mfd, pmic->eco_reg, DCDC_AVS_ECO_MASK);
- break;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static unsigned int tps65912_get_mode(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int pwm_mode, eco, mode = 0, id = rdev_get_id(dev);
-
- tps65912_get_mode_regiters(pmic, id);
-
- pwm_mode = tps65912_reg_read(mfd, pmic->pwm_mode_reg);
- eco = tps65912_reg_read(mfd, pmic->eco_reg);
-
- pwm_mode &= DCDCCTRL_DCDC_MODE_MASK;
- eco &= DCDC_AVS_ECO_MASK;
-
- if (pwm_mode && !eco)
- mode = REGULATOR_MODE_FAST;
- else if (!pwm_mode && !eco)
- mode = REGULATOR_MODE_NORMAL;
- else if (!pwm_mode && eco)
- mode = REGULATOR_MODE_STANDBY;
-
- return mode;
-}
-
-static int tps65912_list_voltage(struct regulator_dev *dev, unsigned selector)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- int range, voltage = 0, id = rdev_get_id(dev);
-
- if (id > TPS65912_REG_DCDC4)
- return -EINVAL;
-
- range = pmic->dcdc_range[id];
-
- switch (range) {
- case 0:
- /* 0.5 - 1.2875V in 12.5mV steps */
- voltage = tps65912_vsel_to_uv_range0(selector);
- break;
- case 1:
- /* 0.7 - 1.4875V in 12.5mV steps */
- voltage = tps65912_vsel_to_uv_range1(selector);
- break;
- case 2:
- /* 0.5 - 2.075V in 25mV steps */
- voltage = tps65912_vsel_to_uv_range2(selector);
- break;
- case 3:
- /* 0.5 - 3.8V in 50mV steps */
- voltage = tps65912_vsel_to_uv_range3(selector);
- break;
- }
- return voltage;
-}
-
-static int tps65912_get_voltage_sel(struct regulator_dev *dev)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev);
- int reg, vsel;
-
- reg = tps65912_get_sel_register(pmic, id);
- if (reg < 0)
- return reg;
-
- vsel = tps65912_reg_read(mfd, reg);
- vsel &= 0x3F;
-
- return vsel;
-}
-
-static int tps65912_set_voltage_sel(struct regulator_dev *dev,
- unsigned selector)
-{
- struct tps65912_reg *pmic = rdev_get_drvdata(dev);
- struct tps65912 *mfd = pmic->mfd;
- int id = rdev_get_id(dev);
- int value;
- u8 reg;
-
- reg = tps65912_get_sel_register(pmic, id);
- value = tps65912_reg_read(mfd, reg);
- value &= 0xC0;
- return tps65912_reg_write(mfd, reg, selector | value);
-}
-
/* Operations permitted on DCDCx */
static struct regulator_ops tps65912_ops_dcdc = {
- .is_enabled = tps65912_reg_is_enabled,
- .enable = tps65912_reg_enable,
- .disable = tps65912_reg_disable,
- .set_mode = tps65912_set_mode,
- .get_mode = tps65912_get_mode,
- .get_voltage_sel = tps65912_get_voltage_sel,
- .set_voltage_sel = tps65912_set_voltage_sel,
- .list_voltage = tps65912_list_voltage,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
};
/* Operations permitted on LDOx */
static struct regulator_ops tps65912_ops_ldo = {
- .is_enabled = tps65912_reg_is_enabled,
- .enable = tps65912_reg_enable,
- .disable = tps65912_reg_disable,
- .get_voltage_sel = tps65912_get_voltage_sel,
- .set_voltage_sel = tps65912_set_voltage_sel,
- .list_voltage = regulator_list_voltage_linear_range,
- .map_voltage = regulator_map_voltage_linear_range,
+ .is_enabled = regulator_is_enabled_regmap,
+ .enable = regulator_enable_regmap,
+ .disable = regulator_disable_regmap,
+ .get_voltage_sel = regulator_get_voltage_sel_regmap,
+ .set_voltage_sel = regulator_set_voltage_sel_regmap,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+};
+
+static const struct regulator_desc regulators[] = {
+ TPS65912_REGULATOR("DCDC1", DCDC1, "dcdc1", tps65912_ops_dcdc,
+ TPS65912_DCDC1_OP, TPS65912_DCDC1_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("DCDC2", DCDC2, "dcdc2", tps65912_ops_dcdc,
+ TPS65912_DCDC2_OP, TPS65912_DCDC2_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("DCDC3", DCDC3, "dcdc3", tps65912_ops_dcdc,
+ TPS65912_DCDC3_OP, TPS65912_DCDC3_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("DCDC4", DCDC4, "dcdc4", tps65912_ops_dcdc,
+ TPS65912_DCDC4_OP, TPS65912_DCDC4_CTRL,
+ tps65912_dcdc_ranges),
+ TPS65912_REGULATOR("LDO1", LDO1, "ldo1", tps65912_ops_ldo,
+ TPS65912_LDO1_OP, TPS65912_LDO1_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO2", LDO2, "ldo2", tps65912_ops_ldo,
+ TPS65912_LDO2_OP, TPS65912_LDO2_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO3", LDO3, "ldo3", tps65912_ops_ldo,
+ TPS65912_LDO3_OP, TPS65912_LDO3_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO4", LDO4, "ldo4", tps65912_ops_ldo,
+ TPS65912_LDO4_OP, TPS65912_LDO4_AVS,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO5", LDO5, "ldo5", tps65912_ops_ldo,
+ TPS65912_LDO5, TPS65912_LDO5,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO6", LDO6, "ldo6", tps65912_ops_ldo,
+ TPS65912_LDO6, TPS65912_LDO6,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO7", LDO7, "ldo7", tps65912_ops_ldo,
+ TPS65912_LDO7, TPS65912_LDO7,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO8", LDO8, "ldo8", tps65912_ops_ldo,
+ TPS65912_LDO8, TPS65912_LDO8,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO9", LDO9, "ldo9", tps65912_ops_ldo,
+ TPS65912_LDO9, TPS65912_LDO9,
+ tps65912_ldo_ranges),
+ TPS65912_REGULATOR("LDO10", LDO10, "ldo10", tps65912_ops_ldo,
+ TPS65912_LDO10, TPS65912_LDO10,
+ tps65912_ldo_ranges),
};
-static int tps65912_probe(struct platform_device *pdev)
+static int tps65912_regulator_probe(struct platform_device *pdev)
{
- struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
+ struct tps65912 *tps = dev_get_drvdata(pdev->dev.parent);
struct regulator_config config = { };
- struct tps_info *info;
- struct regulator_init_data *reg_data;
struct regulator_dev *rdev;
- struct tps65912_reg *pmic;
- struct tps65912_board *pmic_plat_data;
int i;
- pmic_plat_data = dev_get_platdata(tps65912->dev);
- if (!pmic_plat_data)
- return -EINVAL;
+ platform_set_drvdata(pdev, tps);
- reg_data = pmic_plat_data->tps65912_pmic_init_data;
+ config.dev = &pdev->dev;
+ config.driver_data = tps;
+ config.dev->of_node = tps->dev->of_node;
+ config.regmap = tps->regmap;
- pmic = devm_kzalloc(&pdev->dev, sizeof(*pmic), GFP_KERNEL);
- if (!pmic)
- return -ENOMEM;
-
- mutex_init(&pmic->io_lock);
- pmic->mfd = tps65912;
- platform_set_drvdata(pdev, pmic);
-
- pmic->get_ctrl_reg = &tps65912_get_ctrl_register;
- info = tps65912_regs;
-
- for (i = 0; i < TPS65912_NUM_REGULATOR; i++, info++, reg_data++) {
- int range = 0;
- /* Register the regulators */
- pmic->info[i] = info;
-
- pmic->desc[i].name = info->name;
- pmic->desc[i].id = i;
- pmic->desc[i].n_voltages = 64;
- if (i > TPS65912_REG_DCDC4) {
- pmic->desc[i].ops = &tps65912_ops_ldo;
- pmic->desc[i].linear_ranges = tps65912_ldo_ranges;
- pmic->desc[i].n_linear_ranges =
- ARRAY_SIZE(tps65912_ldo_ranges);
- } else {
- pmic->desc[i].ops = &tps65912_ops_dcdc;
- }
- pmic->desc[i].type = REGULATOR_VOLTAGE;
- pmic->desc[i].owner = THIS_MODULE;
- range = tps65912_get_range(pmic, i);
-
- config.dev = tps65912->dev;
- config.init_data = reg_data;
- config.driver_data = pmic;
-
- rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+ for (i = 0; i < ARRAY_SIZE(regulators); i++) {
+ rdev = devm_regulator_register(&pdev->dev, &regulators[i],
&config);
if (IS_ERR(rdev)) {
- dev_err(tps65912->dev,
- "failed to register %s regulator\n",
+ dev_err(tps->dev, "failed to register %s regulator\n",
pdev->name);
return PTR_ERR(rdev);
}
-
- /* Save regulator for cleanup */
- pmic->rdev[i] = rdev;
}
+
return 0;
}
-static struct platform_driver tps65912_driver = {
+static const struct platform_device_id tps65912_regulator_id_table[] = {
+ { "tps65912-regulator", },
+ { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, tps65912_regulator_id_table);
+
+static struct platform_driver tps65912_regulator_driver = {
.driver = {
- .name = "tps65912-pmic",
+ .name = "tps65912-regulator",
},
- .probe = tps65912_probe,
+ .probe = tps65912_regulator_probe,
+ .id_table = tps65912_regulator_id_table,
};
+module_platform_driver(tps65912_regulator_driver);
-static int __init tps65912_init(void)
-{
- return platform_driver_register(&tps65912_driver);
-}
-subsys_initcall(tps65912_init);
-
-static void __exit tps65912_cleanup(void)
-{
- platform_driver_unregister(&tps65912_driver);
-}
-module_exit(tps65912_cleanup);
-
-MODULE_AUTHOR("Margarita Olaya Cabrera <magi@slimlogic.co.uk>");
+MODULE_AUTHOR("Andrew F. Davis <afd@ti.com>");
MODULE_DESCRIPTION("TPS65912 voltage regulator driver");
MODULE_LICENSE("GPL v2");
-MODULE_ALIAS("platform:tps65912-pmic");