diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/88pm800.c | 4 | ||||
-rw-r--r-- | drivers/regulator/88pm8607.c | 4 | ||||
-rw-r--r-- | drivers/regulator/aat2870-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/act8945a-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/axp20x-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/core.c | 160 | ||||
-rw-r--r-- | drivers/regulator/devres.c | 66 | ||||
-rw-r--r-- | drivers/regulator/fixed.c | 46 | ||||
-rw-r--r-- | drivers/regulator/internal.h | 10 | ||||
-rw-r--r-- | drivers/regulator/tps65086-regulator.c | 10 | ||||
-rw-r--r-- | drivers/regulator/twl6030-regulator.c | 2 |
11 files changed, 136 insertions, 172 deletions
diff --git a/drivers/regulator/88pm800.c b/drivers/regulator/88pm800.c index a62a89674fb5..89bbd6e8bad1 100644 --- a/drivers/regulator/88pm800.c +++ b/drivers/regulator/88pm800.c @@ -180,7 +180,7 @@ static int pm800_get_current_limit(struct regulator_dev *rdev) return info->max_ua; } -static struct regulator_ops pm800_volt_range_ops = { +static const struct regulator_ops pm800_volt_range_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .set_voltage_sel = regulator_set_voltage_sel_regmap, @@ -191,7 +191,7 @@ static struct regulator_ops pm800_volt_range_ops = { .get_current_limit = pm800_get_current_limit, }; -static struct regulator_ops pm800_volt_table_ops = { +static const struct regulator_ops pm800_volt_table_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_iterate, .set_voltage_sel = regulator_set_voltage_sel_regmap, diff --git a/drivers/regulator/88pm8607.c b/drivers/regulator/88pm8607.c index b100a63ff3b3..fd86446e499b 100644 --- a/drivers/regulator/88pm8607.c +++ b/drivers/regulator/88pm8607.c @@ -220,7 +220,7 @@ static int pm8607_list_voltage(struct regulator_dev *rdev, unsigned index) return ret; } -static struct regulator_ops pm8607_regulator_ops = { +static const struct regulator_ops pm8607_regulator_ops = { .list_voltage = pm8607_list_voltage, .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, @@ -229,7 +229,7 @@ static struct regulator_ops pm8607_regulator_ops = { .is_enabled = regulator_is_enabled_regmap, }; -static struct regulator_ops pm8606_preg_ops = { +static const struct regulator_ops pm8606_preg_ops = { .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 9dfabda8f478..afc5b5900181 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -97,7 +97,7 @@ static int aat2870_ldo_is_enabled(struct regulator_dev *rdev) return val & ri->enable_mask ? 1 : 0; } -static struct regulator_ops aat2870_ldo_ops = { +static const struct regulator_ops aat2870_ldo_ops = { .list_voltage = regulator_list_voltage_table, .map_voltage = regulator_map_voltage_ascend, .set_voltage_sel = aat2870_ldo_set_voltage_sel, diff --git a/drivers/regulator/act8945a-regulator.c b/drivers/regulator/act8945a-regulator.c index 441864b9fece..43fda8b4455a 100644 --- a/drivers/regulator/act8945a-regulator.c +++ b/drivers/regulator/act8945a-regulator.c @@ -69,7 +69,7 @@ static const struct regulator_linear_range act8945a_voltage_ranges[] = { REGULATOR_LINEAR_RANGE(2400000, 48, 63, 100000), }; -static struct regulator_ops act8945a_ops = { +static const struct regulator_ops act8945a_ops = { .list_voltage = regulator_list_voltage_linear_range, .map_voltage = regulator_map_voltage_linear_range, .get_voltage_sel = regulator_get_voltage_sel_regmap, diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index e6a512ebeae2..a3ade9e4ef47 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -272,7 +272,7 @@ static const struct regulator_desc axp806_regulators[] = { 64, AXP806_DCDCD_V_CTRL, 0x3f, AXP806_PWR_OUT_CTRL1, BIT(3)), AXP_DESC(AXP806, DCDCE, "dcdce", "vine", 1100, 3400, 100, - AXP806_DCDCB_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)), + AXP806_DCDCE_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(4)), AXP_DESC(AXP806, ALDO1, "aldo1", "aldoin", 700, 3300, 100, AXP806_ALDO1_V_CTRL, 0x1f, AXP806_PWR_OUT_CTRL1, BIT(5)), AXP_DESC(AXP806, ALDO2, "aldo2", "aldoin", 700, 3400, 100, diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 04baac9a165b..6ea646466a07 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1455,12 +1455,14 @@ static struct regulator_dev *regulator_lookup_by_name(const char *name) * lookup could succeed in the future. * * If successful, returns a struct regulator_dev that corresponds to the name - * @supply and with the embedded struct device refcount incremented by one, - * or NULL on failure. The refcount must be dropped by calling put_device(). + * @supply and with the embedded struct device refcount incremented by one. + * The refcount must be dropped by calling put_device(). + * On failure one of the following ERR-PTR-encoded values is returned: + * -ENODEV if lookup fails permanently, -EPROBE_DEFER if lookup could succeed + * in the future. */ static struct regulator_dev *regulator_dev_lookup(struct device *dev, - const char *supply, - int *ret) + const char *supply) { struct regulator_dev *r; struct device_node *node; @@ -1476,16 +1478,12 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, r = of_find_regulator_by_node(node); if (r) return r; - *ret = -EPROBE_DEFER; - return NULL; - } else { + /* - * If we couldn't even get the node then it's - * not just that the device didn't register - * yet, there's no node and we'll never - * succeed. + * We have a node, but there is no device. + * assume it has not registered yet. */ - *ret = -ENODEV; + return ERR_PTR(-EPROBE_DEFER); } } @@ -1506,13 +1504,16 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev, if (strcmp(map->supply, supply) == 0 && get_device(&map->regulator->dev)) { - mutex_unlock(®ulator_list_mutex); - return map->regulator; + r = map->regulator; + break; } } mutex_unlock(®ulator_list_mutex); - return NULL; + if (r) + return r; + + return ERR_PTR(-ENODEV); } static int regulator_resolve_supply(struct regulator_dev *rdev) @@ -1529,8 +1530,10 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) if (rdev->supply) return 0; - r = regulator_dev_lookup(dev, rdev->supply_name, &ret); - if (!r) { + r = regulator_dev_lookup(dev, rdev->supply_name); + if (IS_ERR(r)) { + ret = PTR_ERR(r); + if (ret == -ENODEV) { /* * No supply was specified for this regulator and @@ -1580,69 +1583,72 @@ static int regulator_resolve_supply(struct regulator_dev *rdev) } /* Internal regulator request function */ -static struct regulator *_regulator_get(struct device *dev, const char *id, - bool exclusive, bool allow_dummy) +struct regulator *_regulator_get(struct device *dev, const char *id, + enum regulator_get_type get_type) { struct regulator_dev *rdev; - struct regulator *regulator = ERR_PTR(-EPROBE_DEFER); - const char *devname = NULL; + struct regulator *regulator; + const char *devname = dev ? dev_name(dev) : "deviceless"; int ret; + if (get_type >= MAX_GET_TYPE) { + dev_err(dev, "invalid type %d in %s\n", get_type, __func__); + return ERR_PTR(-EINVAL); + } + if (id == NULL) { pr_err("get() with no identifier\n"); return ERR_PTR(-EINVAL); } - if (dev) - devname = dev_name(dev); - - if (have_full_constraints()) - ret = -ENODEV; - else - ret = -EPROBE_DEFER; - - rdev = regulator_dev_lookup(dev, id, &ret); - if (rdev) - goto found; + rdev = regulator_dev_lookup(dev, id); + if (IS_ERR(rdev)) { + ret = PTR_ERR(rdev); - regulator = ERR_PTR(ret); + /* + * If regulator_dev_lookup() fails with error other + * than -ENODEV our job here is done, we simply return it. + */ + if (ret != -ENODEV) + return ERR_PTR(ret); - /* - * If we have return value from dev_lookup fail, we do not expect to - * succeed, so, quit with appropriate error value - */ - if (ret && ret != -ENODEV) - return regulator; + if (!have_full_constraints()) { + dev_warn(dev, + "incomplete constraints, dummy supplies not allowed\n"); + return ERR_PTR(-ENODEV); + } - if (!devname) - devname = "deviceless"; + switch (get_type) { + case NORMAL_GET: + /* + * Assume that a regulator is physically present and + * enabled, even if it isn't hooked up, and just + * provide a dummy. + */ + dev_warn(dev, + "%s supply %s not found, using dummy regulator\n", + devname, id); + rdev = dummy_regulator_rdev; + get_device(&rdev->dev); + break; - /* - * Assume that a regulator is physically present and enabled - * even if it isn't hooked up and just provide a dummy. - */ - if (have_full_constraints() && allow_dummy) { - pr_warn("%s supply %s not found, using dummy regulator\n", - devname, id); + case EXCLUSIVE_GET: + dev_warn(dev, + "dummy supplies not allowed for exclusive requests\n"); + /* fall through */ - rdev = dummy_regulator_rdev; - get_device(&rdev->dev); - goto found; - /* Don't log an error when called from regulator_get_optional() */ - } else if (!have_full_constraints() || exclusive) { - dev_warn(dev, "dummy supplies not allowed\n"); + default: + return ERR_PTR(-ENODEV); + } } - return regulator; - -found: if (rdev->exclusive) { regulator = ERR_PTR(-EPERM); put_device(&rdev->dev); return regulator; } - if (exclusive && rdev->open_count) { + if (get_type == EXCLUSIVE_GET && rdev->open_count) { regulator = ERR_PTR(-EBUSY); put_device(&rdev->dev); return regulator; @@ -1656,6 +1662,7 @@ found: } if (!try_module_get(rdev->owner)) { + regulator = ERR_PTR(-EPROBE_DEFER); put_device(&rdev->dev); return regulator; } @@ -1669,7 +1676,7 @@ found: } rdev->open_count++; - if (exclusive) { + if (get_type == EXCLUSIVE_GET) { rdev->exclusive = 1; ret = _regulator_is_enabled(rdev); @@ -1697,7 +1704,7 @@ found: */ struct regulator *regulator_get(struct device *dev, const char *id) { - return _regulator_get(dev, id, false, true); + return _regulator_get(dev, id, NORMAL_GET); } EXPORT_SYMBOL_GPL(regulator_get); @@ -1724,7 +1731,7 @@ EXPORT_SYMBOL_GPL(regulator_get); */ struct regulator *regulator_get_exclusive(struct device *dev, const char *id) { - return _regulator_get(dev, id, true, false); + return _regulator_get(dev, id, EXCLUSIVE_GET); } EXPORT_SYMBOL_GPL(regulator_get_exclusive); @@ -1750,7 +1757,7 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive); */ struct regulator *regulator_get_optional(struct device *dev, const char *id) { - return _regulator_get(dev, id, false, false); + return _regulator_get(dev, id, OPTIONAL_GET); } EXPORT_SYMBOL_GPL(regulator_get_optional); @@ -3660,7 +3667,7 @@ err: for (++i; i < num_consumers; ++i) { r = regulator_enable(consumers[i].consumer); if (r != 0) - pr_err("Failed to reename %s: %d\n", + pr_err("Failed to re-enable %s: %d\n", consumers[i].supply, r); } @@ -3686,21 +3693,17 @@ int regulator_bulk_force_disable(int num_consumers, struct regulator_bulk_data *consumers) { int i; - int ret; + int ret = 0; - for (i = 0; i < num_consumers; i++) + for (i = 0; i < num_consumers; i++) { consumers[i].ret = regulator_force_disable(consumers[i].consumer); - for (i = 0; i < num_consumers; i++) { - if (consumers[i].ret != 0) { + /* Store first error for reporting */ + if (consumers[i].ret && !ret) ret = consumers[i].ret; - goto out; - } } - return 0; -out: return ret; } EXPORT_SYMBOL_GPL(regulator_bulk_force_disable); @@ -4391,12 +4394,13 @@ static void regulator_summary_show_subtree(struct seq_file *s, seq_puts(s, "\n"); list_for_each_entry(consumer, &rdev->consumer_list, list) { - if (consumer->dev->class == ®ulator_class) + if (consumer->dev && consumer->dev->class == ®ulator_class) continue; seq_printf(s, "%*s%-*s ", (level + 1) * 3 + 1, "", - 30 - (level + 1) * 3, dev_name(consumer->dev)); + 30 - (level + 1) * 3, + consumer->dev ? dev_name(consumer->dev) : "deviceless"); switch (rdev->desc->type) { case REGULATOR_VOLTAGE: @@ -4540,6 +4544,16 @@ static int __init regulator_init_complete(void) if (of_have_populated_dt()) has_full_constraints = true; + /* + * Regulators may had failed to resolve their input supplies + * when were registered, either because the input supply was + * not registered yet or because its parent device was not + * bound yet. So attempt to resolve the input supplies for + * pending regulators before trying to disable unused ones. + */ + class_for_each_device(®ulator_class, NULL, NULL, + regulator_register_resolve_supply); + /* If we have a full configuration then disable any regulators * we have permission to change the status for and which are * not in use or always_on. This is effectively the default diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c index 6ec1d400adae..784e3bf32210 100644 --- a/drivers/regulator/devres.c +++ b/drivers/regulator/devres.c @@ -19,12 +19,6 @@ #include "internal.h" -enum { - NORMAL_GET, - EXCLUSIVE_GET, - OPTIONAL_GET, -}; - static void devm_regulator_release(struct device *dev, void *res) { regulator_put(*(struct regulator **)res); @@ -39,20 +33,7 @@ static struct regulator *_devm_regulator_get(struct device *dev, const char *id, if (!ptr) return ERR_PTR(-ENOMEM); - switch (get_type) { - case NORMAL_GET: - regulator = regulator_get(dev, id); - break; - case EXCLUSIVE_GET: - regulator = regulator_get_exclusive(dev, id); - break; - case OPTIONAL_GET: - regulator = regulator_get_optional(dev, id); - break; - default: - regulator = ERR_PTR(-EINVAL); - } - + regulator = _regulator_get(dev, id, get_type); if (!IS_ERR(regulator)) { *ptr = regulator; devres_add(dev, ptr); @@ -139,6 +120,18 @@ void devm_regulator_put(struct regulator *regulator) } EXPORT_SYMBOL_GPL(devm_regulator_put); +struct regulator_bulk_devres { + struct regulator_bulk_data *consumers; + int num_consumers; +}; + +static void devm_regulator_bulk_release(struct device *dev, void *res) +{ + struct regulator_bulk_devres *devres = res; + + regulator_bulk_free(devres->num_consumers, devres->consumers); +} + /** * devm_regulator_bulk_get - managed get multiple regulator consumers * @@ -157,29 +150,22 @@ EXPORT_SYMBOL_GPL(devm_regulator_put); int devm_regulator_bulk_get(struct device *dev, int num_consumers, struct regulator_bulk_data *consumers) { - int i; + struct regulator_bulk_devres *devres; int ret; - for (i = 0; i < num_consumers; i++) - consumers[i].consumer = NULL; - - for (i = 0; i < num_consumers; i++) { - consumers[i].consumer = devm_regulator_get(dev, - consumers[i].supply); - if (IS_ERR(consumers[i].consumer)) { - ret = PTR_ERR(consumers[i].consumer); - dev_err(dev, "Failed to get supply '%s': %d\n", - consumers[i].supply, ret); - consumers[i].consumer = NULL; - goto err; - } - } - - return 0; + devres = devres_alloc(devm_regulator_bulk_release, + sizeof(*devres), GFP_KERNEL); + if (!devres) + return -ENOMEM; -err: - for (i = 0; i < num_consumers && consumers[i].consumer; i++) - devm_regulator_put(consumers[i].consumer); + ret = regulator_bulk_get(dev, num_consumers, consumers); + if (!ret) { + devres->consumers = consumers; + devres->num_consumers = num_consumers; + devres_add(dev, devres); + } else { + devres_free(devres); + } return ret; } diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index a43b0e8a438d..988a7472c2ab 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -30,9 +30,6 @@ #include <linux/of_gpio.h> #include <linux/regulator/of_regulator.h> #include <linux/regulator/machine.h> -#include <linux/acpi.h> -#include <linux/property.h> -#include <linux/gpio/consumer.h> struct fixed_voltage_data { struct regulator_desc desc; @@ -97,44 +94,6 @@ of_get_fixed_voltage_config(struct device *dev, return config; } -/** - * acpi_get_fixed_voltage_config - extract fixed_voltage_config structure info - * @dev: device requesting for fixed_voltage_config - * @desc: regulator description - * - * Populates fixed_voltage_config structure by extracting data through ACPI - * interface, returns a pointer to the populated structure of NULL if memory - * alloc fails. - */ -static struct fixed_voltage_config * -acpi_get_fixed_voltage_config(struct device *dev, - const struct regulator_desc *desc) -{ - struct fixed_voltage_config *config; - const char *supply_name; - struct gpio_desc *gpiod; - int ret; - - config = devm_kzalloc(dev, sizeof(*config), GFP_KERNEL); - if (!config) - return ERR_PTR(-ENOMEM); - - ret = device_property_read_string(dev, "supply-name", &supply_name); - if (!ret) - config->supply_name = supply_name; - - gpiod = gpiod_get(dev, "gpio", GPIOD_ASIS); - if (IS_ERR(gpiod)) - return ERR_PTR(-ENODEV); - - config->gpio = desc_to_gpio(gpiod); - config->enable_high = device_property_read_bool(dev, - "enable-active-high"); - gpiod_put(gpiod); - - return config; -} - static struct regulator_ops fixed_voltage_ops = { }; @@ -155,11 +114,6 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev) &drvdata->desc); if (IS_ERR(config)) return PTR_ERR(config); - } else if (ACPI_HANDLE(&pdev->dev)) { - config = acpi_get_fixed_voltage_config(&pdev->dev, - &drvdata->desc); - if (IS_ERR(config)) - return PTR_ERR(config); } else { config = dev_get_platdata(&pdev->dev); } diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h index c74ac8734023..1dd575b28564 100644 --- a/drivers/regulator/internal.h +++ b/drivers/regulator/internal.h @@ -51,4 +51,14 @@ regulator_of_get_init_data(struct device *dev, } #endif +enum regulator_get_type { + NORMAL_GET, + EXCLUSIVE_GET, + OPTIONAL_GET, + MAX_GET_TYPE +}; + +struct regulator *_regulator_get(struct device *dev, const char *id, + enum regulator_get_type get_type); + #endif diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c index ecb0371780af..45e96e154690 100644 --- a/drivers/regulator/tps65086-regulator.c +++ b/drivers/regulator/tps65086-regulator.c @@ -157,19 +157,19 @@ static struct tps65086_regulator regulators[] = { VDOA23_VID_MASK, TPS65086_LDOA3CTRL, BIT(0), tps65086_ldoa23_ranges, 0, 0), TPS65086_SWITCH("SWA1", "swa1", SWA1, TPS65086_SWVTT_EN, BIT(5)), - TPS65086_SWITCH("SWB1", "swa2", SWB1, TPS65086_SWVTT_EN, BIT(6)), - TPS65086_SWITCH("SWB2", "swa3", SWB2, TPS65086_SWVTT_EN, BIT(7)), + TPS65086_SWITCH("SWB1", "swb1", SWB1, TPS65086_SWVTT_EN, BIT(6)), + TPS65086_SWITCH("SWB2", "swb2", SWB2, TPS65086_SWVTT_EN, BIT(7)), TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)), }; -static int tps65086_of_parse_cb(struct device_node *dev, +static int tps65086_of_parse_cb(struct device_node *node, const struct regulator_desc *desc, struct regulator_config *config) { int ret; /* Check for 25mV step mode */ - if (of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) { + if (of_property_read_bool(node, "ti,regulator-step-size-25mv")) { switch (desc->id) { case BUCK1: case BUCK2: @@ -193,7 +193,7 @@ static int tps65086_of_parse_cb(struct device_node *dev, } /* Check for decay mode */ - if (desc->id <= BUCK6 && of_property_read_bool(config->of_node, "ti,regulator-decay")) { + if (desc->id <= BUCK6 && of_property_read_bool(node, "ti,regulator-decay")) { ret = regmap_write_bits(config->regmap, regulators[desc->id].decay_reg, regulators[desc->id].decay_mask, diff --git a/drivers/regulator/twl6030-regulator.c b/drivers/regulator/twl6030-regulator.c index 4864b9d742c0..716191046a70 100644 --- a/drivers/regulator/twl6030-regulator.c +++ b/drivers/regulator/twl6030-regulator.c @@ -452,7 +452,7 @@ static int twl6030smps_map_voltage(struct regulator_dev *rdev, int min_uV, vsel = 62; else if ((min_uV > 1800000) && (min_uV <= 1900000)) vsel = 61; - else if ((min_uV > 1350000) && (min_uV <= 1800000)) + else if ((min_uV > 1500000) && (min_uV <= 1800000)) vsel = 60; else if ((min_uV > 1350000) && (min_uV <= 1500000)) vsel = 59; |