diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 08:58:47 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-10-01 08:58:47 -0700 |
commit | aae6f989c6e97ff8197717fa4d032ad4eba091a7 (patch) | |
tree | 3908e2748a91045688a4778872785b8b0660d073 /drivers | |
parent | b34e5f55a1e6667a800280fc4045632c139b4e4e (diff) | |
parent | 6a2027abd2048f7f7fdcc6e11ff10b3d9b0d0899 (diff) |
Merge tag 'regulator-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates from Mark Brown:
- Support for putting regulators into bypass mode where they simply
switch their input to the output (mainly used for low power
retention).
- A new API for setting voltages based on a voltage plus tolerance
rather than an explicit voltage range.
- Lots of cleanups and API updates from Axel Lin.
- New driver for MAX8907.
* tag 'regulator-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (71 commits)
regulator: arizona-ldo: Remove top voltage
regulator: tps6586x: remove regulator-compatible from DT docs
regulator: tps65217.txt: remove regulator-compatible from DT docs
regulator: deprecate regulator-compatible DT property
regulator: fan53555: remove vsel_max not used
regulator: aat2870: Don't explicitly initialise the first field
extcon: arizona: Use bypass mode for MICVDD
regulator: wm831x-ldo: Add bypass support
regulator: arizona-micsupp: Support get/set bypass
regulator: arizona-ldo: Support get/set bypass
regulator: core: Provide regmap get/set bypass operations
regulator: core: Support bypass mode
regulator: Fairchild fan53555 support
regulator: twl: Remove another unused variable warning
regulator: core: Try using the parent device for the default regmap
regulator: core: Fast path non-deferred disables
regulator: core: Report microvolts in sysfs even with only list_voltage()
regulator: tps6586x: add support for SYS rail
regulator: lp872x: remove unnecessary function
regulator: lp872x: fix NULL pointer access problem
...
Diffstat (limited to 'drivers')
32 files changed, 1250 insertions, 491 deletions
diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 427a289f32a..6c19833ed2d 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -434,6 +434,11 @@ static int __devinit arizona_extcon_probe(struct platform_device *pdev) regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, ARIZONA_JD1_ENA, ARIZONA_JD1_ENA); + ret = regulator_allow_bypass(info->micvdd, true); + if (ret != 0) + dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", + ret); + pm_runtime_put(&pdev->dev); return 0; diff --git a/drivers/mfd/tps6586x.c b/drivers/mfd/tps6586x.c index 5f58370ccf5..345960ca2fd 100644 --- a/drivers/mfd/tps6586x.c +++ b/drivers/mfd/tps6586x.c @@ -25,6 +25,7 @@ #include <linux/i2c.h> #include <linux/regmap.h> #include <linux/regulator/of_regulator.h> +#include <linux/regulator/machine.h> #include <linux/mfd/core.h> #include <linux/mfd/tps6586x.h> @@ -346,6 +347,7 @@ failed: #ifdef CONFIG_OF static struct of_regulator_match tps6586x_matches[] = { + { .name = "sys", .driver_data = (void *)TPS6586X_ID_SYS }, { .name = "sm0", .driver_data = (void *)TPS6586X_ID_SM_0 }, { .name = "sm1", .driver_data = (void *)TPS6586X_ID_SM_1 }, { .name = "sm2", .driver_data = (void *)TPS6586X_ID_SM_2 }, @@ -369,6 +371,7 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien struct tps6586x_platform_data *pdata; struct tps6586x_subdev_info *devs; struct device_node *regs; + const char *sys_rail_name = NULL; unsigned int count; unsigned int i, j; int err; @@ -391,12 +394,22 @@ static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *clien return NULL; for (i = 0, j = 0; i < num && j < count; i++) { + struct regulator_init_data *reg_idata; + if (!tps6586x_matches[i].init_data) continue; + reg_idata = tps6586x_matches[i].init_data; devs[j].name = "tps6586x-regulator"; devs[j].platform_data = tps6586x_matches[i].init_data; devs[j].id = (int)tps6586x_matches[i].driver_data; + if (devs[j].id == TPS6586X_ID_SYS) + sys_rail_name = reg_idata->constraints.name; + + if ((devs[j].id == TPS6586X_ID_LDO_5) || + (devs[j].id == TPS6586X_ID_LDO_RTC)) + reg_idata->supply_regulator = sys_rail_name; + devs[j].of_node = tps6586x_matches[i].of_node; j++; } diff --git a/drivers/regulator/Kconfig b/drivers/regulator/Kconfig index 4e932cc695e..e98a5e7827d 100644 --- a/drivers/regulator/Kconfig +++ b/drivers/regulator/Kconfig @@ -33,9 +33,8 @@ config REGULATOR_DUMMY help If this option is enabled then when a regulator lookup fails and the board has not specified that it has provided full - constraints then the regulator core will provide an always - enabled dummy regulator will be provided, allowing consumer - drivers to continue. + constraints the regulator core will provide an always + enabled dummy regulator, allowing consumer drivers to continue. A warning will be generated when this substitution is done. @@ -50,11 +49,11 @@ config REGULATOR_VIRTUAL_CONSUMER tristate "Virtual regulator consumer support" help This driver provides a virtual consumer for the voltage and - current regulator API which provides sysfs controls for - configuring the supplies requested. This is mainly useful - for test purposes. + current regulator API which provides sysfs controls for + configuring the supplies requested. This is mainly useful + for test purposes. - If unsure, say no. + If unsure, say no. config REGULATOR_USERSPACE_CONSUMER tristate "Userspace regulator consumer support" @@ -63,7 +62,7 @@ config REGULATOR_USERSPACE_CONSUMER from user space. Userspace consumer driver provides ability to control power supplies for such devices. - If unsure, say no. + If unsure, say no. config REGULATOR_GPIO tristate "GPIO regulator support" @@ -110,6 +109,17 @@ config REGULATOR_DA9052 This driver supports the voltage regulators of DA9052-BC and DA9053-AA/Bx PMIC. +config REGULATOR_FAN53555 + tristate "Fairchild FAN53555 Regulator" + depends on I2C + select REGMAP_I2C + help + This driver supports Fairchild FAN53555 Digitally Programmable + TinyBuck Regulator. The FAN53555 is a step-down switching voltage + regulator that delivers a digitally programmable output from an + input voltage supply of 2.5V to 5.5V. The output voltage is + programmed through an I2C interface. + config REGULATOR_ANATOP tristate "Freescale i.MX on-chip ANATOP LDO regulators" depends on MFD_ANATOP @@ -172,6 +182,14 @@ config REGULATOR_MAX8660 This driver controls a Maxim 8660/8661 voltage output regulator via I2C bus. +config REGULATOR_MAX8907 + tristate "Maxim 8907 voltage regulator" + depends on MFD_MAX8907 + help + This driver controls a Maxim 8907 voltage output regulator + via I2C bus. The provided regulator is suitable for Tegra + chip to control Step-Down DC-DC and LDOs. + config REGULATOR_MAX8925 tristate "Maxim MAX8925 Power Management IC" depends on MFD_MAX8925 @@ -247,7 +265,7 @@ config REGULATOR_LP8788 config REGULATOR_PCF50633 tristate "NXP PCF50633 regulator driver" - depends on MFD_PCF50633 + depends on MFD_PCF50633 help Say Y here to support the voltage regulators and convertors on PCF50633 @@ -416,7 +434,7 @@ config REGULATOR_WM8350 depends on MFD_WM8350 help This driver provides support for the voltage and current regulators - of the WM8350 AudioPlus PMIC. + of the WM8350 AudioPlus PMIC. config REGULATOR_WM8400 tristate "Wolfson Microelectronics WM8400 AudioPlus PMIC" diff --git a/drivers/regulator/Makefile b/drivers/regulator/Makefile index 3342615cf25..e431eed8a87 100644 --- a/drivers/regulator/Makefile +++ b/drivers/regulator/Makefile @@ -20,6 +20,7 @@ obj-$(CONFIG_REGULATOR_DA903X) += da903x.o obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o +obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o obj-$(CONFIG_REGULATOR_GPIO) += gpio-regulator.o obj-$(CONFIG_REGULATOR_ISL6271A) += isl6271a-regulator.o obj-$(CONFIG_REGULATOR_LP3971) += lp3971.o @@ -30,6 +31,7 @@ obj-$(CONFIG_REGULATOR_LP8788) += lp8788-ldo.o obj-$(CONFIG_REGULATOR_MAX1586) += max1586.o obj-$(CONFIG_REGULATOR_MAX8649) += max8649.o obj-$(CONFIG_REGULATOR_MAX8660) += max8660.o +obj-$(CONFIG_REGULATOR_MAX8907) += max8907-regulator.o obj-$(CONFIG_REGULATOR_MAX8925) += max8925-regulator.o obj-$(CONFIG_REGULATOR_MAX8952) += max8952.o obj-$(CONFIG_REGULATOR_MAX8997) += max8997.o diff --git a/drivers/regulator/aat2870-regulator.c b/drivers/regulator/aat2870-regulator.c index 6f45bfd22e8..167c93f2198 100644 --- a/drivers/regulator/aat2870-regulator.c +++ b/drivers/regulator/aat2870-regulator.c @@ -162,7 +162,7 @@ static struct aat2870_regulator *aat2870_get_regulator(int id) static int aat2870_regulator_probe(struct platform_device *pdev) { struct aat2870_regulator *ri; - struct regulator_config config = { 0 }; + struct regulator_config config = { }; struct regulator_dev *rdev; ri = aat2870_get_regulator(pdev->id); diff --git a/drivers/regulator/ab3100.c b/drivers/regulator/ab3100.c index c151fd5d8c9..65ad2b36ce3 100644 --- a/drivers/regulator/ab3100.c +++ b/drivers/regulator/ab3100.c @@ -347,17 +347,11 @@ static int ab3100_get_voltage_regulator_external(struct regulator_dev *reg) return abreg->plfdata->external_voltage; } -static int ab3100_get_fixed_voltage_regulator(struct regulator_dev *reg) -{ - return reg->desc->min_uV; -} - static struct regulator_ops regulator_ops_fixed = { .list_voltage = regulator_list_voltage_linear, .enable = ab3100_enable_regulator, .disable = ab3100_disable_regulator, .is_enabled = ab3100_is_enabled_regulator, - .get_voltage = ab3100_get_fixed_voltage_regulator, }; static struct regulator_ops regulator_ops_variable = { diff --git a/drivers/regulator/ab8500.c b/drivers/regulator/ab8500.c index 10f2f4d4d19..e3d1d063025 100644 --- a/drivers/regulator/ab8500.c +++ b/drivers/regulator/ab8500.c @@ -37,6 +37,7 @@ * @voltage_bank: bank to control regulator voltage * @voltage_reg: register to control regulator voltage * @voltage_mask: mask to control regulator voltage + * @voltage_shift: shift to control regulator voltage * @delay: startup/set voltage delay in us */ struct ab8500_regulator_info { @@ -50,6 +51,7 @@ struct ab8500_regulator_info { u8 voltage_bank; u8 voltage_reg; u8 voltage_mask; + u8 voltage_shift; unsigned int delay; }; @@ -195,17 +197,14 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev) } dev_vdbg(rdev_get_dev(rdev), - "%s-get_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x," - " 0x%x\n", - info->desc.name, info->voltage_bank, info->voltage_reg, - info->voltage_mask, regval); + "%s-get_voltage (bank, reg, mask, shift, value): " + "0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n", + info->desc.name, info->voltage_bank, + info->voltage_reg, info->voltage_mask, + info->voltage_shift, regval); - /* vintcore has a different layout */ val = regval & info->voltage_mask; - if (info->desc.id == AB8500_LDO_INTCORE) - return val >> 0x3; - else - return val; + return val >> info->voltage_shift; } static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, @@ -221,7 +220,7 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, } /* set the registers for the request */ - regval = (u8)selector; + regval = (u8)selector << info->voltage_shift; ret = abx500_mask_and_set_register_interruptible(info->dev, info->voltage_bank, info->voltage_reg, info->voltage_mask, regval); @@ -238,13 +237,6 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev, return ret; } -static int ab8500_regulator_enable_time(struct regulator_dev *rdev) -{ - struct ab8500_regulator_info *info = rdev_get_drvdata(rdev); - - return info->delay; -} - static int ab8500_regulator_set_voltage_time_sel(struct regulator_dev *rdev, unsigned int old_sel, unsigned int new_sel) @@ -261,22 +253,14 @@ static struct regulator_ops ab8500_regulator_ops = { .get_voltage_sel = ab8500_regulator_get_voltage_sel, .set_voltage_sel = ab8500_regulator_set_voltage_sel, .list_voltage = regulator_list_voltage_table, - .enable_time = ab8500_regulator_enable_time, .set_voltage_time_sel = ab8500_regulator_set_voltage_time_sel, }; -static int ab8500_fixed_get_voltage(struct regulator_dev *rdev) -{ - return rdev->desc->min_uV; -} - static struct regulator_ops ab8500_regulator_fixed_ops = { .enable = ab8500_regulator_enable, .disable = ab8500_regulator_disable, .is_enabled = ab8500_regulator_is_enabled, - .get_voltage = ab8500_fixed_get_voltage, .list_voltage = regulator_list_voltage_linear, - .enable_time = ab8500_regulator_enable_time, }; static struct ab8500_regulator_info @@ -358,6 +342,7 @@ static struct ab8500_regulator_info .voltage_bank = 0x03, .voltage_reg = 0x80, .voltage_mask = 0x38, + .voltage_shift = 3, }, /* @@ -374,6 +359,7 @@ static struct ab8500_regulator_info .owner = THIS_MODULE, .n_voltages = 1, .min_uV = 2000000, + .enable_time = 10000, }, .delay = 10000, .update_bank = 0x03, diff --git a/drivers/regulator/arizona-ldo1.c b/drivers/regulator/arizona-ldo1.c index c8f95c07adb..d184aa35abc 100644 --- a/drivers/regulator/arizona-ldo1.c +++ b/drivers/regulator/arizona-ldo1.c @@ -39,6 +39,8 @@ static struct regulator_ops arizona_ldo1_ops = { .map_voltage = regulator_map_voltage_linear, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, }; static const struct regulator_desc arizona_ldo1 = { @@ -49,9 +51,11 @@ static const struct regulator_desc arizona_ldo1 = { .vsel_reg = ARIZONA_LDO1_CONTROL_1, .vsel_mask = ARIZONA_LDO1_VSEL_MASK, + .bypass_reg = ARIZONA_LDO1_CONTROL_1, + .bypass_mask = ARIZONA_LDO1_BYPASS, .min_uV = 900000, .uV_step = 50000, - .n_voltages = 7, + .n_voltages = 6, .owner = THIS_MODULE, }; diff --git a/drivers/regulator/arizona-micsupp.c b/drivers/regulator/arizona-micsupp.c index 450a069aa9b..d9b1f82cc5b 100644 --- a/drivers/regulator/arizona-micsupp.c +++ b/drivers/regulator/arizona-micsupp.c @@ -82,6 +82,9 @@ static struct regulator_ops arizona_micsupp_ops = { .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, + + .get_bypass = regulator_get_bypass_regmap, + .set_bypass = regulator_set_bypass_regmap, }; static const struct regulator_desc arizona_micsupp = { @@ -95,6 +98,8 @@ static const struct regulator_desc arizona_micsupp = { .vsel_mask = ARIZONA_LDO2_VSEL_MASK, .enable_reg = ARIZONA_MIC_CHARGE_PUMP_1, .enable_mask = ARIZONA_CPMIC_ENA, + .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1, + .bypass_mask = ARIZONA_CPMIC_BYPASS, .owner = THIS_MODULE, }; diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 48385318175..2e0352dc26b 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -77,6 +77,7 @@ struct regulator { struct device *dev; struct list_head list; unsigned int always_on:1; + unsigned int bypass:1; int uA_load; int min_uV; int max_uV; @@ -394,6 +395,9 @@ static ssize_t regulator_status_show(struct device *dev, case REGULATOR_STATUS_STANDBY: label = "standby"; break; + case REGULATOR_STATUS_BYPASS: + label = "bypass"; + break; case REGULATOR_STATUS_UNDEFINED: label = "undefined"; break; @@ -585,6 +589,27 @@ static ssize_t regulator_suspend_standby_state_show(struct device *dev, static DEVICE_ATTR(suspend_standby_state, 0444, regulator_suspend_standby_state_show, NULL); +static ssize_t regulator_bypass_show(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct regulator_dev *rdev = dev_get_drvdata(dev); + const char *report; + bool bypass; + int ret; + + ret = rdev->desc->ops->get_bypass(rdev, &bypass); + + if (ret != 0) + report = "unknown"; + else if (bypass) + report = "enabled"; + else + report = "disabled"; + + return sprintf(buf, "%s\n", report); +} +static DEVICE_ATTR(bypass, 0444, + regulator_bypass_show, NULL); /* * These are the only attributes are present for all regulators. @@ -778,6 +803,9 @@ static void print_constraints(struct regulator_dev *rdev) if (constraints->valid_modes_mask & REGULATOR_MODE_STANDBY) count += sprintf(buf + count, "standby"); + if (!count) + sprintf(buf, "no parameters"); + rdev_info(rdev, "%s\n", buf); if ((constraints->min_uV != constraints->max_uV) && @@ -974,6 +1002,7 @@ static int set_supply(struct regulator_dev *rdev, err = -ENOMEM; return err; } + supply_rdev->open_count++; return 0; } @@ -1720,6 +1749,9 @@ int regulator_disable_deferred(struct regulator *regulator, int ms) if (regulator->always_on) return 0; + if (!ms) + return regulator_disable(regulator); + mutex_lock(&rdev->mutex); rdev->deferred_disables++; mutex_unlock(&rdev->mutex); @@ -2178,9 +2210,12 @@ static int _regulator_do_set_voltage(struct regulator_dev *rdev, } } - if (ret == 0 && best_val >= 0) + if (ret == 0 && best_val >= 0) { + unsigned long data = best_val; + _notifier_call_chain(rdev, REGULATOR_EVENT_VOLTAGE_CHANGE, - (void *)best_val); + (void *)data); + } trace_regulator_set_voltage_complete(rdev_get_name(rdev), best_val); @@ -2291,8 +2326,8 @@ int regulator_set_voltage_time(struct regulator *regulator, EXPORT_SYMBOL_GPL(regulator_set_voltage_time); /** - *regulator_set_voltage_time_sel - get raise/fall time - * @regulator: regulator source + * regulator_set_voltage_time_sel - get raise/fall time + * @rdev: regulator source device * @old_selector: selector for starting voltage * @new_selector: selector for target voltage * @@ -2388,6 +2423,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev) ret = rdev->desc->ops->list_voltage(rdev, sel); } else if (rdev->desc->ops->get_voltage) { ret = rdev->desc->ops->get_voltage(rdev); + } else if (rdev->desc->ops->list_voltage) { + ret = rdev->desc->ops->list_voltage(rdev, 0); } else { return -EINVAL; } @@ -2674,6 +2711,100 @@ out: EXPORT_SYMBOL_GPL(regulator_set_optimum_mode); /** + * regulator_set_bypass_regmap - Default set_bypass() using regmap + * + * @rdev: device to operate on. + * @enable: state to set. + */ +int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) +{ + unsigned int val; + + if (enable) + val = rdev->desc->bypass_mask; + else + val = 0; + + return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, + rdev->desc->bypass_mask, val); +} +EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); + +/** + * regulator_get_bypass_regmap - Default get_bypass() using regmap + * + * @rdev: device to operate on. + * @enable: current state. + */ +int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) +{ + unsigned int val; + int ret; + + ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); + if (ret != 0) + return ret; + + *enable = val & rdev->desc->bypass_mask; + + return 0; +} +EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); + +/** + * regulator_allow_bypass - allow the regulator to go into bypass mode + * + * @regulator: Regulator to configure + * @allow: enable or disable bypass mode + * + * Allow the regulator to go into bypass mode if all other consumers + * for the regulator also enable bypass mode and the machine + * constraints allow this. Bypass mode means that the regulator is + * simply passing the input directly to the output with no regulation. + */ +int regulator_allow_bypass(struct regulator *regulator, bool enable) +{ + struct regulator_dev *rdev = regulator->rdev; + int ret = 0; + + if (!rdev->desc->ops->set_bypass) + return 0; + + if (rdev->constraints && + !(rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_BYPASS)) + return 0; + + mutex_lock(&rdev->mutex); + + if (enable && !regulator->bypass) { + rdev->bypass_count++; + + if (rdev->bypass_count == rdev->open_count) { + ret = rdev->desc->ops->set_bypass(rdev, enable); + if (ret != 0) + rdev->bypass_count--; + } + + } else if (!enable && regulator->bypass) { + rdev->bypass_count--; + + if (rdev->bypass_count != rdev->open_count) { + ret = rdev->desc->ops->set_bypass(rdev, enable); + if (ret != 0) + rdev->bypass_count++; + } + } + + if (ret == 0) + regulator->bypass = enable; + + mutex_unlock(&rdev->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(regulator_allow_bypass); + +/** * regulator_register_notifier - register regulator event notifier * @regulator: regulator source * @nb: notifier block @@ -3011,7 +3142,8 @@ static int add_regulator_attributes(struct regulator_dev *rdev) /* some attributes need specific methods to be displayed */ if ((ops->get_voltage && ops->get_voltage(rdev) >= 0) || - (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0)) { + (ops->get_voltage_sel && ops->get_voltage_sel(rdev) >= 0) || + (ops->list_voltage && ops->list_voltage(rdev, 0) >= 0)) { status = device_create_file(dev, &dev_attr_microvolts); if (status < 0) return status; @@ -3036,6 +3168,11 @@ static int add_regulator_attributes(struct regulator_dev *rdev) if (status < 0) return status; } + if (ops->get_bypass) { + status = device_create_file(dev, &dev_attr_bypass); + if (status < 0) + return status; + } /* some attributes are type-specific */ if (rdev->desc->type == REGULATOR_CURRENT) { @@ -3124,6 +3261,8 @@ static void rdev_init_debugfs(struct regulator_dev *rdev) &rdev->use_count); debugfs_create_u32("open_count", 0444, rdev->debugfs, &rdev->open_count); + debugfs_create_u32("bypass_count", 0444, rdev->debugfs, + &rdev->bypass_count); } /** @@ -3189,8 +3328,10 @@ regulator_register(const struct regulator_desc *regulator_desc, rdev->desc = regulator_desc; if (config->regmap) rdev->regmap = config->regmap; - else + else if (dev_get_regmap(dev, NULL)) rdev->regmap = dev_get_regmap(dev, NULL); + else if (dev->parent) + rdev->regmap = dev_get_regmap(dev->parent, NULL); INIT_LIST_HEAD(&rdev->consumer_list); INIT_LIST_HEAD(&rdev->list); BLOCKING_INIT_NOTIFIER_HEAD(&rdev->notifier); diff --git a/drivers/regulator/da9052-regulator.c b/drivers/regulator/da9052-regulator.c index 903299cf15c..27355b1199e 100644 --- a/drivers/regulator/da9052-regulator.c +++ b/drivers/regulator/da9052-regulator.c @@ -133,8 +133,8 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA, max_uA < da9052_current_limits[row][DA9052_MIN_UA]) return -EINVAL; - for (i = 0; i < DA9052_CURRENT_RANGE; i++) { - if (min_uA <= da9052_current_limits[row][i]) { + for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) { + if (da9052_current_limits[row][i] <= max_uA) { reg_val = i; break; } diff --git a/drivers/regulator/dummy.c b/drivers/regulator/dummy.c index 86f655c7f7a..03a1d7c11ef 100644 --- a/drivers/regulator/dummy.c +++ b/drivers/regulator/dummy.c @@ -30,7 +30,7 @@ static struct regulator_init_data dummy_initdata; static struct regulator_ops dummy_ops; static struct regulator_desc dummy_desc = { - .name = "dummy", + .name = "regulator-dummy", .id = -1, .type = REGULATOR_VOLTAGE, .owner = THIS_MODULE, diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c new file mode 100644 index 00000000000..339f4d732e9 --- /dev/null +++ b/drivers/regulator/fan53555.c @@ -0,0 +1,322 @@ +/* + * FAN53555 Fairchild Digitally Programmable TinyBuck Regulator Driver. + * + * Supported Part Numbers: + * FAN53555UC00X/01X/03X/04X/05X + * + * Copyright (c) 2012 Marvell Technology Ltd. + * Yunfan Zhang <yfzhang@marvell.com> + * + * This package 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. + * + */ +#include <linux/module.h> +#include <linux/param.h> +#include <linux/err.h> +#include <linux/platform_device.h> +#include <linux/regulator/driver.h> +#include <linux/regulator/machine.h> +#include <linux/i2c.h> +#include <linux/slab.h> +#include <linux/regmap.h> +#include <linux/regulator/fan53555.h> + +/* Voltage setting */ +#define FAN53555_VSEL0 0x00 +#define FAN53555_VSEL1 0x01 +/* Control register */ +#define FAN53555_CONTROL 0x02 +/* IC Type */ +#define FAN53555_ID1 0x03 +/* IC mask version */ +#define FAN53555_ID2 0x04 +/* Monitor register */ +#define FAN53555_MONITOR 0x05 + +/* VSEL bit definitions */ +#define VSEL_BUCK_EN (1 << 7) +#define VSEL_MODE (1 << 6) +#define VSEL_NSEL_MASK 0x3F +/* Chip ID and Verison */ +#define DIE_ID 0x0F /* ID1 */ +#define DIE_REV 0x0F /* ID2 */ +/* Control bit definitions */ +#define CTL_OUTPUT_DISCHG (1 << 7) +#define CTL_SLEW_MASK (0x7 << 4) +#define CTL_SLEW_SHIFT 4 +#define CTL_RESET (1 << 2) + +#define FAN53555_NVOLTAGES 64 /* Numbers of voltages */ + +/* IC Type */ +enum { + FAN53555_CHIP_ID_00 = 0, + FAN53555_CHIP_ID_01, + FAN53555_CHIP_ID_02, + FAN53555_CHIP_ID_03, + FAN53555_CHIP_ID_04, + FAN53555_CHIP_ID_05, +}; + +struct fan53555_device_info { + struct regmap *regmap; + struct device *dev; + struct regulator_desc desc; + struct regulator_dev *rdev; + struct regulator_init_data *regulator; + /* IC Type and Rev */ + int chip_id; + int chip_rev; + /* Voltage setting register */ + unsigned int vol_reg; + unsigned int sleep_reg; + /* Voltage range and step(linear) */ + unsigned int vsel_min; + unsigned int vsel_step; + /* Voltage slew rate limiting */ + unsigned int slew_rate; + /* Sleep voltage cache */ + unsigned int sleep_vol_cache; +}; + +static int fan53555_set_suspend_voltage(struct regulator_dev *rdev, int uV) +{ + struct fan53555_device_info *di = rdev_get_drvdata(rdev); + int ret; + + if (di->sleep_vol_cache == uV) + return 0; + ret = regulator_map_voltage_linear(rdev, uV, uV); + if (ret < 0) + return -EINVAL; + ret = regmap_update_bits(di->regmap, di->sleep_reg, + VSEL_NSEL_MASK, ret); |