diff options
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/arizona-ldo1.c | 2 | ||||
-rw-r--r-- | drivers/regulator/axp20x-regulator.c | 12 | ||||
-rw-r--r-- | drivers/regulator/core.c | 40 | ||||
-rw-r--r-- | drivers/regulator/fixed.c | 46 | ||||
-rw-r--r-- | drivers/regulator/gpio-regulator.c | 9 | ||||
-rw-r--r-- | drivers/regulator/helpers.c | 6 | ||||
-rw-r--r-- | drivers/regulator/lp873x-regulator.c | 1 | ||||
-rw-r--r-- | drivers/regulator/max77620-regulator.c | 47 | ||||
-rw-r--r-- | drivers/regulator/stw481x-vmmc.c | 3 | ||||
-rw-r--r-- | drivers/regulator/tps6507x-regulator.c | 2 | ||||
-rw-r--r-- | drivers/regulator/tps65086-regulator.c | 51 |
11 files changed, 183 insertions, 36 deletions
diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index f7c88ff90c43..302b57cb89c6 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -130,6 +130,7 @@ static const struct regulator_desc arizona_ldo1_hc = { .uV_step = 50000, .n_voltages = 8, .enable_time = 1500, + .ramp_delay = 24000, .owner = THIS_MODULE, }; @@ -153,6 +154,7 @@ static const struct regulator_desc arizona_ldo1 = { .uV_step = 25000, .n_voltages = 13, .enable_time = 500, + .ramp_delay = 24000, .owner = THIS_MODULE, }; diff --git a/drivers/regulator/axp20x-regulator.c b/drivers/regulator/axp20x-regulator.c index 54382ef902c6..e6a512ebeae2 100644 --- a/drivers/regulator/axp20x-regulator.c +++ b/drivers/regulator/axp20x-regulator.c @@ -337,10 +337,18 @@ static const struct regulator_desc axp809_regulators[] = { AXP22X_ELDO2_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(1)), AXP_DESC(AXP809, ELDO3, "eldo3", "eldoin", 700, 3300, 100, AXP22X_ELDO3_V_OUT, 0x1f, AXP22X_PWR_OUT_CTRL2, BIT(2)), - AXP_DESC_IO(AXP809, LDO_IO0, "ldo_io0", "ips", 700, 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(AXP809, 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(AXP809, LDO_IO1, "ldo_io1", "ips", 700, 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(AXP809, 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(AXP809, RTC_LDO, "rtc_ldo", "ips", 1800), diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 67426c0477d3..04baac9a165b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -204,7 +204,7 @@ static struct device_node *of_get_regulator(struct device *dev, const char *supp regnode = of_parse_phandle(dev->of_node, prop_name, 0); if (!regnode) { - dev_dbg(dev, "Looking up %s property in node %s failed", + dev_dbg(dev, "Looking up %s property in node %s failed\n", prop_name, dev->of_node->full_name); return NULL; } @@ -293,7 +293,8 @@ static int regulator_check_current_limit(struct regulator_dev *rdev, } /* operating mode constraint check */ -static int regulator_mode_constrain(struct regulator_dev *rdev, int *mode) +static int regulator_mode_constrain(struct regulator_dev *rdev, + unsigned int *mode) { switch (*mode) { case REGULATOR_MODE_FAST: @@ -2754,7 +2755,7 @@ static int _regulator_set_voltage_time(struct regulator_dev *rdev, ramp_delay = rdev->desc->ramp_delay; if (ramp_delay == 0) { - rdev_warn(rdev, "ramp_delay not set\n"); + rdev_dbg(rdev, "ramp_delay not set\n"); return 0; } @@ -3359,6 +3360,39 @@ unsigned int regulator_get_mode(struct regulator *regulator) } EXPORT_SYMBOL_GPL(regulator_get_mode); +static int _regulator_get_error_flags(struct regulator_dev *rdev, + unsigned int *flags) +{ + int ret; + + mutex_lock(&rdev->mutex); + + /* sanity check */ + if (!rdev->desc->ops->get_error_flags) { + ret = -EINVAL; + goto out; + } + + ret = rdev->desc->ops->get_error_flags(rdev, flags); +out: + mutex_unlock(&rdev->mutex); + return ret; +} + +/** + * regulator_get_error_flags - get regulator error information + * @regulator: regulator source + * @flags: pointer to store error flags + * + * Get the current regulator error information. + */ +int regulator_get_error_flags(struct regulator *regulator, + unsigned int *flags) +{ + return _regulator_get_error_flags(regulator->rdev, flags); +} +EXPORT_SYMBOL_GPL(regulator_get_error_flags); + /** * regulator_set_load - set regulator load * @regulator: regulator source diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c index 988a7472c2ab..a43b0e8a438d 100644 --- a/drivers/regulator/fixed.c +++ b/drivers/regulator/fixed.c @@ -30,6 +30,9 @@ #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; @@ -94,6 +97,44 @@ 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 = { }; @@ -114,6 +155,11 @@ 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/gpio-regulator.c b/drivers/regulator/gpio-regulator.c index 83e89e5d4752..0fce06acfaec 100644 --- a/drivers/regulator/gpio-regulator.c +++ b/drivers/regulator/gpio-regulator.c @@ -162,8 +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); + if (config->enable_gpio < 0 && config->enable_gpio != -ENOENT) + return ERR_PTR(config->enable_gpio); /* Fetch GPIOs. - optional property*/ ret = of_gpio_count(np); @@ -190,8 +190,11 @@ of_get_gpio_regulator_config(struct device *dev, struct device_node *np, for (i = 0; i < config->nr_gpios; i++) { gpio = of_get_named_gpio(np, "gpios", i); - if (gpio < 0) + if (gpio < 0) { + if (gpio != -ENOENT) + return ERR_PTR(gpio); break; + } config->gpios[i].gpio = gpio; if (proplen > 0) { of_property_read_u32_index(np, "gpios-states", diff --git a/drivers/regulator/helpers.c b/drivers/regulator/helpers.c index bcf38fd5106a..379cdacc05d8 100644 --- a/drivers/regulator/helpers.c +++ b/drivers/regulator/helpers.c @@ -454,13 +454,17 @@ EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) { unsigned int val; + unsigned int val_on = rdev->desc->bypass_val_on; int ret; ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); if (ret != 0) return ret; - *enable = (val & rdev->desc->bypass_mask) == rdev->desc->bypass_val_on; + if (!val_on) + val_on = rdev->desc->bypass_mask; + + *enable = (val & rdev->desc->bypass_mask) == val_on; return 0; } diff --git a/drivers/regulator/lp873x-regulator.c b/drivers/regulator/lp873x-regulator.c index e504b9148226..70e3df653381 100644 --- a/drivers/regulator/lp873x-regulator.c +++ b/drivers/regulator/lp873x-regulator.c @@ -24,6 +24,7 @@ [_id] = { \ .desc = { \ .name = _name, \ + .supply_name = _of "-in", \ .id = _id, \ .of_match = of_match_ptr(_of), \ .regulators_node = of_match_ptr("regulators"),\ diff --git a/drivers/regulator/max77620-regulator.c b/drivers/regulator/max77620-regulator.c index a1b49a6d538f..d088a7c79e60 100644 --- a/drivers/regulator/max77620-regulator.c +++ b/drivers/regulator/max77620-regulator.c @@ -73,7 +73,6 @@ struct max77620_regulator_info { }; struct max77620_regulator_pdata { - struct regulator_init_data *reg_idata; int active_fps_src; int active_fps_pd_slot; int active_fps_pu_slot; @@ -81,6 +80,7 @@ struct max77620_regulator_pdata { int suspend_fps_pd_slot; int suspend_fps_pu_slot; int current_mode; + int power_ok; int ramp_rate_setting; }; @@ -351,11 +351,48 @@ static int max77620_set_slew_rate(struct max77620_regulator *pmic, int id, return 0; } +static int max77620_config_power_ok(struct max77620_regulator *pmic, int id) +{ + struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id]; + struct max77620_regulator_info *rinfo = pmic->rinfo[id]; + struct max77620_chip *chip = dev_get_drvdata(pmic->dev->parent); + u8 val, mask; + int ret; + + switch (chip->chip_id) { + case MAX20024: + if (rpdata->power_ok >= 0) { + if (rinfo->type == MAX77620_REGULATOR_TYPE_SD) + mask = MAX20024_SD_CFG1_MPOK_MASK; + else + mask = MAX20024_LDO_CFG2_MPOK_MASK; + + val = rpdata->power_ok ? mask : 0; + + ret = regmap_update_bits(pmic->rmap, rinfo->cfg_addr, + mask, val); + if (ret < 0) { + dev_err(pmic->dev, "Reg 0x%02x update failed %d\n", + rinfo->cfg_addr, ret); + return ret; + } + } + break; + + default: + break; + } + + return 0; +} + static int max77620_init_pmic(struct max77620_regulator *pmic, int id) { struct max77620_regulator_pdata *rpdata = &pmic->reg_pdata[id]; int ret; + max77620_config_power_ok(pmic, id); + /* Update power mode */ ret = max77620_regulator_get_power_mode(pmic, id); if (ret < 0) @@ -595,6 +632,12 @@ static int max77620_of_parse_cb(struct device_node *np, np, "maxim,suspend-fps-power-down-slot", &pval); rpdata->suspend_fps_pd_slot = (!ret) ? pval : -1; + ret = of_property_read_u32(np, "maxim,power-ok-control", &pval); + if (!ret) + rpdata->power_ok = pval; + else + rpdata->power_ok = -1; + ret = of_property_read_u32(np, "maxim,ramp-rate-setting", &pval); rpdata->ramp_rate_setting = (!ret) ? pval : 0; @@ -807,6 +850,8 @@ static int max77620_regulator_resume(struct device *dev) for (id = 0; id < MAX77620_NUM_REGS; id++) { reg_pdata = &pmic->reg_pdata[id]; + max77620_config_power_ok(pmic, id); + max77620_regulator_set_fps_slots(pmic, id, false); if (reg_pdata->active_fps_src < 0) continue; diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c index 7d2ae3e9e942..342f5da79975 100644 --- a/drivers/regulator/stw481x-vmmc.c +++ b/drivers/regulator/stw481x-vmmc.c @@ -47,7 +47,8 @@ static struct regulator_desc vmmc_regulator = { .volt_table = stw481x_vmmc_voltages, .enable_time = 200, /* FIXME: look this up */ .enable_reg = STW_CONF1, - .enable_mask = STW_CONF1_PDN_VMMC, + .enable_mask = STW_CONF1_PDN_VMMC | STW_CONF1_MMC_LS_STATUS, + .enable_val = STW_CONF1_PDN_VMMC, .vsel_reg = STW_CONF1, .vsel_mask = STW_CONF1_VMMC_MASK, }; diff --git a/drivers/regulator/tps6507x-regulator.c b/drivers/regulator/tps6507x-regulator.c index dad0bac09ecf..c179a3a221af 100644 --- a/drivers/regulator/tps6507x-regulator.c +++ b/drivers/regulator/tps6507x-regulator.c @@ -375,7 +375,7 @@ static struct tps6507x_board *tps6507x_parse_dt_reg_data( struct device_node *np = pdev->dev.parent->of_node; struct device_node *regulators; struct of_regulator_match *matches; - static struct regulator_init_data *reg_data; + struct regulator_init_data *reg_data; int idx = 0, count, ret; tps_board = devm_kzalloc(&pdev->dev, sizeof(*tps_board), diff --git a/drivers/regulator/tps65086-regulator.c b/drivers/regulator/tps65086-regulator.c index 33f389d583ef..ecb0371780af 100644 --- a/drivers/regulator/tps65086-regulator.c +++ b/drivers/regulator/tps65086-regulator.c @@ -71,7 +71,7 @@ struct tps65086_regulator { unsigned int decay_mask; }; -static const struct regulator_linear_range tps65086_buck126_10mv_ranges[] = { +static const struct regulator_linear_range tps65086_10mv_ranges[] = { REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0), REGULATOR_LINEAR_RANGE(410000, 0x1, 0x7F, 10000), }; @@ -82,7 +82,7 @@ static const struct regulator_linear_range tps65086_buck126_25mv_ranges[] = { REGULATOR_LINEAR_RANGE(1025000, 0x19, 0x7F, 25000), }; -static const struct regulator_linear_range tps65086_buck345_ranges[] = { +static const struct regulator_linear_range tps65086_buck345_25mv_ranges[] = { REGULATOR_LINEAR_RANGE(0, 0x0, 0x0, 0), REGULATOR_LINEAR_RANGE(425000, 0x1, 0x7F, 25000), }; @@ -125,27 +125,27 @@ static int tps65086_of_parse_cb(struct device_node *dev, static struct tps65086_regulator regulators[] = { TPS65086_REGULATOR("BUCK1", "buck1", BUCK1, 0x80, TPS65086_BUCK1CTRL, BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(0), - tps65086_buck126_10mv_ranges, TPS65086_BUCK1CTRL, + tps65086_10mv_ranges, TPS65086_BUCK1CTRL, BIT(0)), TPS65086_REGULATOR("BUCK2", "buck2", BUCK2, 0x80, TPS65086_BUCK2CTRL, BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(1), - tps65086_buck126_10mv_ranges, TPS65086_BUCK2CTRL, + tps65086_10mv_ranges, TPS65086_BUCK2CTRL, BIT(0)), TPS65086_REGULATOR("BUCK3", "buck3", BUCK3, 0x80, TPS65086_BUCK3VID, BUCK_VID_MASK, TPS65086_BUCK123CTRL, BIT(2), - tps65086_buck345_ranges, TPS65086_BUCK3DECAY, + tps65086_10mv_ranges, TPS65086_BUCK3DECAY, BIT(0)), TPS65086_REGULATOR("BUCK4", "buck4", BUCK4, 0x80, TPS65086_BUCK4VID, BUCK_VID_MASK, TPS65086_BUCK4CTRL, BIT(0), - tps65086_buck345_ranges, TPS65086_BUCK4VID, + tps65086_10mv_ranges, TPS65086_BUCK4VID, BIT(0)), TPS65086_REGULATOR("BUCK5", "buck5", BUCK5, 0x80, TPS65086_BUCK5VID, BUCK_VID_MASK, TPS65086_BUCK5CTRL, BIT(0), - tps65086_buck345_ranges, TPS65086_BUCK5CTRL, + tps65086_10mv_ranges, TPS65086_BUCK5CTRL, BIT(0)), TPS65086_REGULATOR("BUCK6", "buck6", BUCK6, 0x80, TPS65086_BUCK6VID, BUCK_VID_MASK, TPS65086_BUCK6CTRL, BIT(0), - tps65086_buck126_10mv_ranges, TPS65086_BUCK6CTRL, + tps65086_10mv_ranges, TPS65086_BUCK6CTRL, BIT(0)), TPS65086_REGULATOR("LDOA1", "ldoa1", LDOA1, 0xF, TPS65086_LDOA1CTRL, VDOA1_VID_MASK, TPS65086_LDOA1CTRL, BIT(0), @@ -162,18 +162,6 @@ static struct tps65086_regulator regulators[] = { TPS65086_SWITCH("VTT", "vtt", VTT, TPS65086_SWVTT_EN, BIT(4)), }; -static inline bool has_25mv_mode(int id) -{ - switch (id) { - case BUCK1: - case BUCK2: - case BUCK6: - return true; - default: - return false; - } -} - static int tps65086_of_parse_cb(struct device_node *dev, const struct regulator_desc *desc, struct regulator_config *config) @@ -181,12 +169,27 @@ static int tps65086_of_parse_cb(struct device_node *dev, int ret; /* Check for 25mV step mode */ - if (has_25mv_mode(desc->id) && - of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) { - regulators[desc->id].desc.linear_ranges = + if (of_property_read_bool(config->of_node, "ti,regulator-step-size-25mv")) { + switch (desc->id) { + case BUCK1: + case BUCK2: + case BUCK6: + regulators[desc->id].desc.linear_ranges = tps65086_buck126_25mv_ranges; - regulators[desc->id].desc.n_linear_ranges = + regulators[desc->id].desc.n_linear_ranges = ARRAY_SIZE(tps65086_buck126_25mv_ranges); + break; + case BUCK3: + case BUCK4: + case BUCK5: + regulators[desc->id].desc.linear_ranges = + tps65086_buck345_25mv_ranges; + regulators[desc->id].desc.n_linear_ranges = + ARRAY_SIZE(tps65086_buck345_25mv_ranges); + break; + default: + dev_warn(config->dev, "25mV step mode only valid for BUCK regulators\n"); + } } /* Check for decay mode */ |