提交 c6d65bf2 编写于 作者: L Linus Torvalds

Merge tag 'regulator-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator

Pull regulator updates from Mark Brown:
 "Lots of driver updates here plus some nice new core features, the main
  one being the first:

   - Enable support for providing a dummy regulator when we know that
     one must exist for the device to be functional.  This makes it much
     easier to add regulator support to drivers since we don't require
     that the machine integration for all systems using the device be
     updated to provide regulators.
   - Substantial reduction in the amount of busy waiting done while
     waiting for enables to complete.
   - Allow MFDs to distribute regulator supplies to child devices so we
     don't have to expose the internal structure of MFDs outside of the
     driver.
   - Managed registeration for regulators"

* tag 'regulator-v3.13' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (113 commits)
  regulator: s5m8767: Modify parsing method of the voltage table of buck2/3/4
  regulator: s5m8767: Modify parse_dt function to parse data related to ramp
  regulator: da9052: Revert se apply_[reg|bit] with regmap based voltage_sel operations
  mfd: arizona: Specify supply mappings for Arizona CODECs
  mfd: Allow mapping regulator supplies to MFD device from children
  regulator: core: Add ability to create a lookup alias for supply
  regulator: tps65910: Fix checkpatch issue
  regulator: tps65023: Fix checkpatch issue
  regulator: tps6105x: Fix checkpatch issue
  regulator: mc13783: Fix checkpatch issue
  regulator: max8997: Fix checkpatch issue
  regulator: lp3971: Fix checkpatch issue
  regulator: fixed: Fix checkpatch issue
  regulator: anatop: Fix checkpatch issue
  regulator: Add REGULATOR_LINEAR_RANGE macro
  regulator: Remove max_uV from struct regulator_linear_range
  regulator: ti-abb: Fix operator precedence typo
  regulator: tps65910: get regulators node from parent node only
  regulator: tps6586x: get regulators node from parent node only
  regulator: tps65090: get regulators node from parent node only
  ...
Regulator of AMS AS3722 PMIC.
Name of the regulator subnode must be "regulators".
Optional properties:
--------------------
The input supply of regulators are the optional properties on the
regulator node. The AS3722 is having 7 DCDC step-down regulators as
sd[0-6], 10 LDOs as ldo[0-7], ldo[9-11]. The input supply of these
regulators are provided through following properties:
vsup-sd2-supply: Input supply for SD2.
vsup-sd3-supply: Input supply for SD3.
vsup-sd4-supply: Input supply for SD4.
vsup-sd5-supply: Input supply for SD5.
vin-ldo0-supply: Input supply for LDO0.
vin-ldo1-6-supply: Input supply for LDO1 and LDO6.
vin-ldo2-5-7-supply: Input supply for LDO2, LDO5 and LDO7.
vin-ldo3-4-supply: Input supply for LDO3 and LDO4.
vin-ldo9-10-supply: Input supply for LDO9 and LDO10.
vin-ldo11-supply: Input supply for LDO11.
Optional nodes:
--------------
- regulators : Must contain a sub-node per regulator from the list below.
Each sub-node should contain the constraints and initialization
information for that regulator. See regulator.txt for a
description of standard properties for these sub-nodes.
Additional custom properties are listed below.
sd[0-6], ldo[0-7], ldo[9-11].
Optional sub-node properties:
----------------------------
ams,ext-control: External control of the rail. The option of
this properties will tell which external input is
controlling this rail. Valid values are 0, 1, 2 ad 3.
0: There is no external control of this rail.
1: Rail is controlled by ENABLE1 input pin.
2: Rail is controlled by ENABLE2 input pin.
3: Rail is controlled by ENABLE3 input pin.
ams,enable-tracking: Enable tracking with SD1, only supported
by LDO3.
Example:
-------
ams3722: ams3722 {
compatible = "ams,as3722";
reg = <0x40>;
...
regulators {
vsup-sd2-supply = <...>;
...
sd0 {
regulator-name = "vdd_cpu";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1400000>;
regulator-always-on;
ams,ext-control = <2>;
};
sd1 {
regulator-name = "vdd_core";
regulator-min-microvolt = <700000>;
regulator-max-microvolt = <1400000>;
regulator-always-on;
ams,ext-control = <1>;
};
sd2 {
regulator-name = "vddio_ddr";
regulator-min-microvolt = <1350000>;
regulator-max-microvolt = <1350000>;
regulator-always-on;
};
sd4 {
regulator-name = "avdd-hdmi-pex";
regulator-min-microvolt = <1050000>;
regulator-max-microvolt = <1050000>;
regulator-always-on;
};
sd5 {
regulator-name = "vdd-1v8";
regulator-min-microvolt = <1800000>;
regulator-max-microvolt = <1800000>;
regulator-always-on;
};
....
};
};
* Dialog Semiconductor DA9210 Voltage Regulator
Required properties:
- compatible: must be "diasemi,da9210"
- reg: the i2c slave address of the regulator. It should be 0x68.
Any standard regulator properties can be used to configure the single da9210
DCDC.
Example:
da9210@68 {
compatible = "diasemi,da9210";
reg = <0x68>;
regulator-min-microvolt = <900000>;
regulator-max-microvolt = <1000000>;
regulator-boot-on;
regulator-always-on;
};
......@@ -26,11 +26,17 @@ Optional nodes:
For ti,palmas-pmic - smps12, smps123, smps3 depending on OTP,
smps45, smps457, smps7 depending on variant, smps6, smps[8-9],
smps10_out2, smps10_out1, do[1-9], ldoln, ldousb.
smps10_out2, smps10_out1, ldo[1-9], ldoln, ldousb.
Optional sub-node properties:
ti,warm-reset - maintain voltage during warm reset(boolean)
ti,roof-floor - control voltage selection by pin(boolean)
ti,roof-floor - This takes as optional argument on platform supporting
the rail from desired external control. If there is no argument then
it will be assume that it is controlled by NSLEEP pin.
The valid value for external pins are:
ENABLE1 then 1,
ENABLE2 then 2 or
NSLEEP then 3.
ti,mode-sleep - mode to adopt in pmic sleep 0 - off, 1 - auto,
2 - eco, 3 - forced pwm
ti,smps-range - OTP has the wrong range set for the hardware so override
......@@ -61,7 +67,7 @@ pmic {
regulator-always-on;
regulator-boot-on;
ti,warm-reset;
ti,roof-floor;
ti,roof-floor = <1>; /* ENABLE1 control */
ti,mode-sleep = <0>;
ti,smps-range = <1>;
};
......
......@@ -14,6 +14,11 @@ Optional properties:
- regulator-ramp-delay: ramp delay for regulator(in uV/uS)
For hardwares which support disabling ramp rate, it should be explicitly
intialised to zero (regulator-ramp-delay = <0>) for disabling ramp delay.
- regulator-enable-ramp-delay: The time taken, in microseconds, for the supply
rail to reach the target voltage, plus/minus whatever tolerance the board
design requires. This property describes the total system ramp time
required due to the combination of internal ramping of the regulator itself,
and board design issues such as trace capacitance and load on the supply.
Deprecated properties:
- regulator-compatible: If a regulator chip contains multiple
......
......@@ -283,6 +283,7 @@ REGULATOR
devm_regulator_get()
devm_regulator_put()
devm_regulator_bulk_get()
devm_regulator_register()
CLOCK
devm_clk_get()
......
......@@ -310,10 +310,6 @@ static struct regulator_consumer_supply wallvdd_consumers[] = {
REGULATOR_SUPPLY("SPKVDDL", "spi0.1"),
REGULATOR_SUPPLY("SPKVDDR", "spi0.1"),
REGULATOR_SUPPLY("SPKVDDL", "wm5102-codec"),
REGULATOR_SUPPLY("SPKVDDR", "wm5102-codec"),
REGULATOR_SUPPLY("SPKVDDL", "wm5110-codec"),
REGULATOR_SUPPLY("SPKVDDR", "wm5110-codec"),
REGULATOR_SUPPLY("DC1VDD", "0-0034"),
REGULATOR_SUPPLY("DC2VDD", "0-0034"),
......@@ -653,14 +649,6 @@ static struct regulator_consumer_supply pvdd_1v8_consumers[] = {
REGULATOR_SUPPLY("DBVDD3", "spi0.1"),
REGULATOR_SUPPLY("LDOVDD", "spi0.1"),
REGULATOR_SUPPLY("CPVDD", "spi0.1"),
REGULATOR_SUPPLY("DBVDD2", "wm5102-codec"),
REGULATOR_SUPPLY("DBVDD3", "wm5102-codec"),
REGULATOR_SUPPLY("CPVDD", "wm5102-codec"),
REGULATOR_SUPPLY("DBVDD2", "wm5110-codec"),
REGULATOR_SUPPLY("DBVDD3", "wm5110-codec"),
REGULATOR_SUPPLY("CPVDD", "wm5110-codec"),
};
static struct regulator_init_data pvdd_1v8 = {
......
......@@ -569,13 +569,25 @@ static struct mfd_cell early_devs[] = {
{ .name = "arizona-ldo1" },
};
static const char *wm5102_supplies[] = {
"DBVDD2",
"DBVDD3",
"CPVDD",
"SPKVDDL",
"SPKVDDR",
};
static struct mfd_cell wm5102_devs[] = {
{ .name = "arizona-micsupp" },
{ .name = "arizona-extcon" },
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{ .name = "wm5102-codec" },
{
.name = "wm5102-codec",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
},
};
static struct mfd_cell wm5110_devs[] = {
......@@ -584,7 +596,17 @@ static struct mfd_cell wm5110_devs[] = {
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{ .name = "wm5110-codec" },
{
.name = "wm5110-codec",
.parent_supplies = wm5102_supplies,
.num_parent_supplies = ARRAY_SIZE(wm5102_supplies),
},
};
static const char *wm8997_supplies[] = {
"DBVDD2",
"CPVDD",
"SPKVDD",
};
static struct mfd_cell wm8997_devs[] = {
......@@ -593,7 +615,11 @@ static struct mfd_cell wm8997_devs[] = {
{ .name = "arizona-gpio" },
{ .name = "arizona-haptics" },
{ .name = "arizona-pwm" },
{ .name = "wm8997-codec" },
{
.name = "wm8997-codec",
.parent_supplies = wm8997_supplies,
.num_parent_supplies = ARRAY_SIZE(wm8997_supplies),
},
};
int arizona_dev_init(struct arizona *arizona)
......
......@@ -20,6 +20,7 @@
#include <linux/module.h>
#include <linux/irqdomain.h>
#include <linux/of.h>
#include <linux/regulator/consumer.h>
static struct device_type mfd_dev_type = {
.name = "mfd_device",
......@@ -99,6 +100,13 @@ static int mfd_add_device(struct device *parent, int id,
pdev->dev.dma_mask = parent->dma_mask;
pdev->dev.dma_parms = parent->dma_parms;
ret = devm_regulator_bulk_register_supply_alias(
&pdev->dev, cell->parent_supplies,
parent, cell->parent_supplies,
cell->num_parent_supplies);
if (ret < 0)
goto fail_res;
if (parent->of_node && cell->of_compatible) {
for_each_child_of_node(parent->of_node, np) {
if (of_device_is_compatible(np, cell->of_compatible)) {
......@@ -112,12 +120,12 @@ static int mfd_add_device(struct device *parent, int id,
ret = platform_device_add_data(pdev,
cell->platform_data, cell->pdata_size);
if (ret)
goto fail_res;
goto fail_alias;
}
ret = mfd_platform_add_cell(pdev, cell);
if (ret)
goto fail_res;
goto fail_alias;
for (r = 0; r < cell->num_resources; r++) {
res[r].name = cell->resources[r].name;
......@@ -152,17 +160,17 @@ static int mfd_add_device(struct device *parent, int id,
if (!cell->ignore_resource_conflicts) {
ret = acpi_check_resource_conflict(&res[r]);
if (ret)
goto fail_res;
goto fail_alias;
}
}
ret = platform_device_add_resources(pdev, res, cell->num_resources);
if (ret)
goto fail_res;
goto fail_alias;
ret = platform_device_add(pdev);
if (ret)
goto fail_res;
goto fail_alias;
if (cell->pm_runtime_no_callbacks)
pm_runtime_no_callbacks(&pdev->dev);
......@@ -171,6 +179,10 @@ static int mfd_add_device(struct device *parent, int id,
return 0;
fail_alias:
devm_regulator_bulk_unregister_supply_alias(&pdev->dev,
cell->parent_supplies,
cell->num_parent_supplies);
fail_res:
kfree(res);
fail_device:
......
......@@ -141,18 +141,14 @@ struct pm800_regulators {
/* Ranges are sorted in ascending order. */
static const struct regulator_linear_range buck1_volt_range[] = {
{ .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f,
.uV_step = 12500 },
{ .min_uV = 1600000, .max_uV = 1800000, .min_sel = 0x50,
.max_sel = 0x54, .uV_step = 50000 },
REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x54, 50000),
};
/* BUCK 2~5 have same ranges. */
static const struct regulator_linear_range buck2_5_volt_range[] = {
{ .min_uV = 600000, .max_uV = 1587500, .min_sel = 0, .max_sel = 0x4f,
.uV_step = 12500 },
{ .min_uV = 1600000, .max_uV = 3300000, .min_sel = 0x50,
.max_sel = 0x72, .uV_step = 50000 },
REGULATOR_LINEAR_RANGE(600000, 0, 0x4f, 12500),
REGULATOR_LINEAR_RANGE(1600000, 0x50, 0x72, 50000),
};
static const unsigned int ldo1_volt_table[] = {
......
......@@ -391,7 +391,8 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
else
config.regmap = chip->regmap_companion;
info->regulator = regulator_register(&info->desc, &config);
info->regulator = devm_regulator_register(&pdev->dev, &info->desc,
&config);
if (IS_ERR(info->regulator)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
......@@ -402,14 +403,6 @@ static int pm8607_regulator_probe(struct platform_device *pdev)
return 0;
}
static int pm8607_regulator_remove(struct platform_device *pdev)
{
struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
regulator_unregister(info->regulator);
return 0;
}
static struct platform_device_id pm8607_regulator_driver_ids[] = {
{
.name = "88pm860x-regulator",
......@@ -428,7 +421,6 @@ static struct platform_driver pm8607_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = pm8607_regulator_probe,
.remove = pm8607_regulator_remove,
.id_table = pm8607_regulator_driver_ids,
};
......
......@@ -28,16 +28,6 @@ config REGULATOR_DEBUG
help
Say yes here to enable debugging support.
config REGULATOR_DUMMY
bool "Provide a dummy regulator if regulator lookups fail"
help
If this option is enabled then when a regulator lookup fails
and the board has not specified that it has provided full
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.
config REGULATOR_FIXED_VOLTAGE
tristate "Fixed voltage regulator support"
help
......@@ -133,6 +123,14 @@ config REGULATOR_AS3711
This driver provides support for the voltage regulators on the
AS3711 PMIC
config REGULATOR_AS3722
tristate "AMS AS3722 PMIC Regulators"
depends on MFD_AS3722
help
This driver provides support for the voltage regulators on the
AS3722 PMIC. This will enable support for all the software
controllable DCDC/LDO regulators.
config REGULATOR_DA903X
tristate "Dialog Semiconductor DA9030/DA9034 regulators"
depends on PMIC_DA903X
......@@ -429,6 +427,14 @@ config REGULATOR_TI_ABB
on TI SoCs may be unstable without enabling this as it provides
device specific optimized bias to allow/optimize functionality.
config REGULATOR_STW481X_VMMC
bool "ST Microelectronics STW481X VMMC regulator"
depends on MFD_STW481X
default y if MFD_STW481X
help
This driver supports the internal VMMC regulator in the STw481x
PMIC chips.
config REGULATOR_TPS51632
tristate "TI TPS51632 Power Regulator"
depends on I2C
......
......@@ -3,7 +3,7 @@
#
obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o
obj-$(CONFIG_REGULATOR) += core.o dummy.o fixed-helper.o helpers.o devres.o
obj-$(CONFIG_OF) += of_regulator.o
obj-$(CONFIG_REGULATOR_FIXED_VOLTAGE) += fixed.o
obj-$(CONFIG_REGULATOR_VIRTUAL_CONSUMER) += virtual.o
......@@ -18,6 +18,7 @@ obj-$(CONFIG_REGULATOR_AD5398) += ad5398.o
obj-$(CONFIG_REGULATOR_ANATOP) += anatop-regulator.o
obj-$(CONFIG_REGULATOR_ARIZONA) += arizona-micsupp.o arizona-ldo1.o
obj-$(CONFIG_REGULATOR_AS3711) += as3711-regulator.o
obj-$(CONFIG_REGULATOR_AS3722) += as3722-regulator.o
obj-$(CONFIG_REGULATOR_DA903X) += da903x.o
obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
......@@ -56,6 +57,7 @@ obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
obj-$(CONFIG_REGULATOR_RC5T583) += rc5t583-regulator.o
obj-$(CONFIG_REGULATOR_S2MPS11) += s2mps11.o
obj-$(CONFIG_REGULATOR_S5M8767) += s5m8767.o
obj-$(CONFIG_REGULATOR_STW481X_VMMC) += stw481x-vmmc.o
obj-$(CONFIG_REGULATOR_TI_ABB) += ti-abb-regulator.o
obj-$(CONFIG_REGULATOR_TPS6105X) += tps6105x-regulator.o
obj-$(CONFIG_REGULATOR_TPS62360) += tps62360-regulator.o
......
......@@ -176,7 +176,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
config.driver_data = ri;
config.init_data = dev_get_platdata(&pdev->dev);
rdev = regulator_register(&ri->desc, &config);
rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
ri->desc.name);
......@@ -187,21 +187,12 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
return 0;
}
static int aat2870_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
regulator_unregister(rdev);
return 0;
}
static struct platform_driver aat2870_regulator_driver = {
.driver = {
.name = "aat2870-regulator",
.owner = THIS_MODULE,
},
.probe = aat2870_regulator_probe,
.remove = aat2870_regulator_remove,
};
static int __init aat2870_regulator_init(void)
......
......@@ -535,7 +535,7 @@ static int ab3100_regulator_register(struct platform_device *pdev,
config.dev = &pdev->dev;
config.driver_data = reg;
rdev = regulator_register(desc, &config);
rdev = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(rdev)) {
err = PTR_ERR(rdev);
dev_err(&pdev->dev,
......@@ -616,7 +616,6 @@ static int ab3100_regulators_remove(struct platform_device *pdev)
for (i = 0; i < AB3100_NUM_REGULATORS; i++) {
struct ab3100_regulator *reg = &ab3100_regulators[i];
regulator_unregister(reg->rdev);
reg->rdev = NULL;
}
return 0;
......
......@@ -413,16 +413,12 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev)
&pdata->ext_regulator[i];
/* register regulator with framework */
info->rdev = regulator_register(&info->desc, &config);
info->rdev = devm_regulator_register(&pdev->dev, &info->desc,
&config);
if (IS_ERR(info->rdev)) {
err = PTR_ERR(info->rdev);
dev_err(&pdev->dev, "failed to register regulator %s\n",
info->desc.name);
/* when we fail, un-register all earlier regulators */
while (--i >= 0) {
info = &ab8500_ext_regulator_info[i];
regulator_unregister(info->rdev);
}
return err;
}
......@@ -433,26 +429,8 @@ static int ab8500_ext_regulator_probe(struct platform_device *pdev)
return 0;
}
static int ab8500_ext_regulator_remove(struct platform_device *pdev)
{
int i;
for (i = 0; i < ARRAY_SIZE(ab8500_ext_regulator_info); i++) {
struct ab8500_ext_regulator_info *info = NULL;
info = &ab8500_ext_regulator_info[i];
dev_vdbg(rdev_get_dev(info->rdev),
"%s-remove\n", info->desc.name);
regulator_unregister(info->rdev);
}
return 0;
}
static struct platform_driver ab8500_ext_regulator_driver = {
.probe = ab8500_ext_regulator_probe,
.remove = ab8500_ext_regulator_remove,
.driver = {
.name = "ab8500-ext-regulator",
.owner = THIS_MODULE,
......
......@@ -219,7 +219,6 @@ static int ad5398_probe(struct i2c_client *client,
struct ad5398_chip_info *chip;
const struct ad5398_current_data_format *df =
(struct ad5398_current_data_format *)id->driver_data;
int ret;
if (!init_data)
return -EINVAL;
......@@ -240,33 +239,21 @@ static int ad5398_probe(struct i2c_client *client,
chip->current_offset = df->current_offset;
chip->current_mask = (chip->current_level - 1) << chip->current_offset;
chip->rdev = regulator_register(&ad5398_reg, &config);
chip->rdev = devm_regulator_register(&client->dev, &ad5398_reg,
&config);
if (IS_ERR(chip->rdev)) {
ret = PTR_ERR(chip->rdev);
dev_err(&client->dev, "failed to register %s %s\n",
id->name, ad5398_reg.name);
goto err;
return PTR_ERR(chip->rdev);
}
i2c_set_clientdata(client, chip);
dev_dbg(&client->dev, "%s regulator driver is registered.\n", id->name);
return 0;
err:
return ret;
}
static int ad5398_remove(struct i2c_client *client)
{
struct ad5398_chip_info *chip = i2c_get_clientdata(client);
regulator_unregister(chip->rdev);
return 0;
}
static struct i2c_driver ad5398_driver = {
.probe = ad5398_probe,
.remove = ad5398_remove,
.driver = {
.name = "ad5398",
},
......
......@@ -200,7 +200,7 @@ static int anatop_regulator_probe(struct platform_device *pdev)
config.regmap = sreg->anatop;
/* register regulator */
rdev = regulator_register(rdesc, &config);
rdev = devm_regulator_register(dev, rdesc, &config);
if (IS_ERR(rdev)) {
dev_err(dev, "failed to register %s\n",
rdesc->name);
......@@ -223,7 +223,6 @@ static int anatop_regulator_remove(struct platform_device *pdev)
struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
const char *name = sreg->name;
regulator_unregister(rdev);
kfree(name);
return 0;
......@@ -256,7 +255,7 @@ static void __exit anatop_regulator_exit(void)
}
module_exit(anatop_regulator_exit);
MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>, "
"Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
MODULE_AUTHOR("Nancy Chen <Nancy.Chen@freescale.com>");
MODULE_AUTHOR("Ying-Chun Liu (PaulLiu) <paul.liu@linaro.org>");
MODULE_DESCRIPTION("ANATOP Regulator driver");
MODULE_LICENSE("GPL v2");
......@@ -226,7 +226,7 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
else
config.init_data = &ldo1->init_data;
ldo1->regulator = regulator_register(desc, &config);
ldo1->regulator = devm_regulator_register(&pdev->dev, desc, &config);
if (IS_ERR(ldo1->regulator)) {
ret = PTR_ERR(ldo1->regulator);
dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
......@@ -239,18 +239,8 @@ static int arizona_ldo1_probe(struct platform_device *pdev)
return 0;
}
static int arizona_ldo1_remove(struct platform_device *pdev)
{
struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
regulator_unregister(ldo1->regulator);
return 0;
}
static struct platform_driver arizona_ldo1_driver = {
.probe = arizona_ldo1_probe,
.remove = arizona_ldo1_remove,
.driver = {
.name = "arizona-ldo1",
.owner = THIS_MODULE,
......
......@@ -225,7 +225,9 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
regmap_update_bits(arizona->regmap, ARIZONA_MIC_CHARGE_PUMP_1,
ARIZONA_CPMIC_BYPASS, 0);
micsupp->regulator = regulator_register(&arizona_micsupp, &config);
micsupp->regulator = devm_regulator_register(&pdev->dev,
&arizona_micsupp,
&config);
if (IS_ERR(micsupp->regulator)) {
ret = PTR_ERR(micsupp->regulator);
dev_err(arizona->dev, "Failed to register mic supply: %d\n",
......@@ -238,18 +240,8 @@ static int arizona_micsupp_probe(struct platform_device *pdev)
return 0;
}
static int arizona_micsupp_remove(struct platform_device *pdev)
{
struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
regulator_unregister(micsupp->regulator);
return 0;
}
static struct platform_driver arizona_micsupp_driver = {
.probe = arizona_micsupp_probe,
.remove = arizona_micsupp_remove,
.driver = {
.name = "arizona-micsupp",
.owner = THIS_MODULE,
......
......@@ -117,26 +117,19 @@ static struct regulator_ops as3711_dldo_ops = {
};
static const struct regulator_linear_range as3711_sd_ranges[] = {
{ .min_uV = 612500, .max_uV = 1400000,
.min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 },
{ .min_uV = 1425000, .max_uV = 2600000,
.min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 },
{ .min_uV = 2650000, .max_uV = 3350000,
.min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 },
REGULATOR_LINEAR_RANGE(612500, 0x1, 0x40, 12500),
REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7f, 50000),
};
static const struct regulator_linear_range as3711_aldo_ranges[] = {
{ .min_uV = 1200000, .max_uV = 1950000,
.min_sel = 0, .max_sel = 0xf, .uV_step = 50000 },
{ .min_uV = 1800000, .max_uV = 3300000,
.min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 },
REGULATOR_LINEAR_RANGE(1200000, 0, 0xf, 50000),
REGULATOR_LINEAR_RANGE(1800000, 0x10, 0x1f, 100000),
};
static const struct regulator_linear_range as3711_dldo_ranges[] = {
{ .min_uV = 900000, .max_uV = 1700000,
.min_sel = 0, .max_sel = 0x10, .uV_step = 50000 },
{ .min_uV = 1750000, .max_uV = 3300000,
.min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 },
REGULATOR_LINEAR_RANGE(900000, 0, 0x10, 50000),
REGULATOR_LINEAR_RANGE(1750000, 0x20, 0x3f, 50000),
};
#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \
......@@ -273,33 +266,16 @@ static int as3711_regulator_probe(struct platform_device *pdev)
config.regmap = as3711->regmap;
config.of_node = of_node[id];
rdev = regulator_register(&ri->desc, &config);
rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
ri->desc.name);
ret = PTR_ERR(rdev);
goto eregreg;
return PTR_ERR(rdev);
}
reg->rdev = rdev;
}
platform_set_drvdata(pdev, regs);
return 0;
eregreg:
while (--id >= 0)
regulator_unregister(regs[id].rdev);
return ret;
}
static int as3711_regulator_remove(struct platform_device *pdev)
{
struct as3711_regulator *regs = platform_get_drvdata(pdev);
int id;
for (id = 0; id < AS3711_REGULATOR_NUM; ++id)
regulator_unregister(regs[id].rdev);
return 0;
}
static struct platform_driver as3711_regulator_driver = {
......@@ -308,7 +284,6 @@ static struct platform_driver as3711_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = as3711_regulator_probe,
.remove = as3711_regulator_remove,
};
static int __init as3711_regulator_init(void)
......
此差异已折叠。
......@@ -36,6 +36,7 @@
#include <trace/events/regulator.h>
#include "dummy.h"
#include "internal.h"
#define rdev_crit(rdev, fmt, ...) \
pr_crit("%s: " fmt, rdev_get_name(rdev), ##__VA_ARGS__)
......@@ -52,8 +53,8 @@ static DEFINE_MUTEX(regulator_list_mutex);
static LIST_HEAD(regulator_list);
static LIST_HEAD(regulator_map_list);
static LIST_HEAD(regulator_ena_gpio_list);
static LIST_HEAD(regulator_supply_alias_list);
static bool has_full_constraints;
static bool board_wants_dummy_regulator;
static struct dentry *debugfs_root;
......@@ -83,22 +84,16 @@ struct regulator_enable_gpio {
};
/*
* struct regulator
* struct regulator_supply_alias
*
* One for each consumer device.
* Used to map lookups for a supply onto an alternative device.
*/
struct regulator {
struct device *dev;
struct regulator_supply_alias {
struct list_head list;
unsigned int always_on:1;
unsigned int bypass:1;
int uA_load;
int min_uV;
int max_uV;
char *supply_name;
struct device_attribute dev_attr;
struct regulator_dev *rdev;
struct dentry *debugfs;
struct device *src_dev;
const char *src_supply;
struct device *alias_dev;
const char *alias_supply;
};
static int _regulator_is_enabled(struct regulator_dev *rdev);
......@@ -923,6 +918,36 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
return 0;
}
static int machine_constraints_current(struct regulator_dev *rdev,
struct regulation_constraints *constraints)
{
struct regulator_ops *ops = rdev->desc->ops;
int ret;
if (!constraints->min_uA && !constraints->max_uA)
return 0;
if (constraints->min_uA > constraints->max_uA) {
rdev_err(rdev, "Invalid current constraints\n");
return -EINVAL;
}
if (!ops->set_current_limit || !ops->get_current_limit) {
rdev_warn(rdev, "Operation of current configuration missing\n");
return 0;
}
/* Set regulator current in constraints range */
ret = ops->set_current_limit(rdev, constraints->min_uA,
constraints->max_uA);
if (ret < 0) {
rdev_err(rdev, "Failed to set current constraint, %d\n", ret);
return ret;
}
return 0;
}
/**
* set_machine_constraints - sets regulator constraints
* @rdev: regulator source
......@@ -953,6 +978,10 @@ static int set_machine_constraints(struct regulator_dev *rdev,
if (ret != 0)
goto out;
ret = machine_constraints_current(rdev, rdev->constraints);
if (ret != 0)
goto out;
/* do we need to setup our suspend state */
if (rdev->constraints->initial_state) {
ret = suspend_prepare(rdev, rdev->constraints->initial_state);
......@@ -1186,11 +1215,39 @@ static struct regulator *create_regulator(struct regulator_dev *rdev,
static int _regulator_get_enable_time(struct regulator_dev *rdev)
{
if (rdev->constraints && rdev->constraints->enable_time)
return rdev->constraints->enable_time;
if (!rdev->desc->ops->enable_time)
return rdev->desc->enable_time;
return rdev->desc->ops->enable_time(rdev);
}
static struct regulator_supply_alias *regulator_find_supply_alias(
struct device *dev, const char *supply)
{
struct regulator_supply_alias *map;
list_for_each_entry(map, &regulator_supply_alias_list, list)
if (map->src_dev == dev && strcmp(map->src_supply, supply) == 0)
return map;
return NULL;
}
static void regulator_supply_alias(struct device **dev, const char **supply)
{
struct regulator_supply_alias *map;
map = regulator_find_supply_alias(*dev, *supply);
if (map) {
dev_dbg(*dev, "Mapping supply %s to %s,%s\n",
*supply, map->alias_supply,
dev_name(map->alias_dev));
*dev = map->alias_dev;
*supply = map->alias_supply;
}
}
static struct regulator_dev *regulator_dev_lookup(struct device *dev,
const char *supply,
int *ret)
......@@ -1200,6 +1257,8 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
struct regulator_map *map;
const char *devname = NULL;
regulator_supply_alias(&dev, &supply);
/* first do a dt based lookup */
if (dev && dev->of_node) {
node = of_get_regulator(dev, supply);
......@@ -1243,16 +1302,16 @@ static struct regulator_dev *regulator_dev_lookup(struct device *dev,
/* Internal regulator request function */
static struct regulator *_regulator_get(struct device *dev, const char *id,
bool exclusive)
bool exclusive, bool allow_dummy)
{
struct regulator_dev *rdev;
struct regulator *regulator = ERR_PTR(-EPROBE_DEFER);
const char *devname = NULL;
int ret = 0;
int ret = -EPROBE_DEFER;
if (id == NULL) {
pr_err("get() with no identifier\n");
return regulator;
return ERR_PTR(-EINVAL);
}
if (dev)
......@@ -1264,34 +1323,32 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
if (rdev)
goto found;
regulator = 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) {
regulator = ERR_PTR(ret);
if (ret && ret != -ENODEV) {
goto out;
}
if (board_wants_dummy_regulator) {
rdev = dummy_regulator_rdev;
goto found;
}
#ifdef CONFIG_REGULATOR_DUMMY
if (!devname)
devname = "deviceless";
/* If the board didn't flag that it was fully constrained then
* substitute in a dummy regulator so consumers can continue.
/*
* Assume that a regulator is physically present and enabled
* even if it isn't hooked up and just provide a dummy.
*/
if (!has_full_constraints) {
if (has_full_constraints && allow_dummy) {
pr_warn("%s supply %s not found, using dummy regulator\n",
devname, id);
rdev = dummy_regulator_rdev;
goto found;
} else {
dev_err(dev, "dummy supplies not allowed\n");
}
#endif
mutex_unlock(&regulator_list_mutex);
return regulator;
......@@ -1349,44 +1406,10 @@ static struct regulator *_regulator_get(struct device *dev, const char *id,
*/
struct regulator *regulator_get(struct device *dev, const char *id)
{
return _regulator_get(dev, id, false);
return _regulator_get(dev, id, false, true);
}
EXPORT_SYMBOL_GPL(regulator_get);
static void devm_regulator_release(struct device *dev, void *res)
{
regulator_put(*(struct regulator **)res);
}
/**
* devm_regulator_get - Resource managed regulator_get()
* @dev: device for regulator "consumer"
* @id: Supply name or regulator ID.
*
* Managed regulator_get(). Regulators returned from this function are
* automatically regulator_put() on driver detach. See regulator_get() for more
* information.
*/
struct regulator *devm_regulator_get(struct device *dev, const char *id)
{
struct regulator **ptr, *regulator;
ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
regulator = regulator_get(dev, id);
if (!IS_ERR(regulator)) {
*ptr = regulator;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return regulator;
}
EXPORT_SYMBOL_GPL(devm_regulator_get);
/**
* regulator_get_exclusive - obtain exclusive access to a regulator.
* @dev: device for regulator "consumer"
......@@ -1410,7 +1433,7 @@ EXPORT_SYMBOL_GPL(devm_regulator_get);
*/
struct regulator *regulator_get_exclusive(struct device *dev, const char *id)
{
return _regulator_get(dev, id, true);
return _regulator_get(dev, id, true, false);
}
EXPORT_SYMBOL_GPL(regulator_get_exclusive);
......@@ -1439,40 +1462,10 @@ EXPORT_SYMBOL_GPL(regulator_get_exclusive);
*/
struct regulator *regulator_get_optional(struct device *dev, const char *id)
{
return _regulator_get(dev, id, 0);
return _regulator_get(dev, id, false, false);
}
EXPORT_SYMBOL_GPL(regulator_get_optional);
/**
* devm_regulator_get_optional - Resource managed regulator_get_optional()
* @dev: device for regulator "consumer"
* @id: Supply name or regulator ID.
*
* Managed regulator_get_optional(). Regulators returned from this
* function are automatically regulator_put() on driver detach. See
* regulator_get_optional() for more information.
*/
struct regulator *devm_regulator_get_optional(struct device *dev,
const char *id)
{
struct regulator **ptr, *regulator;
ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
regulator = regulator_get_optional(dev, id);
if (!IS_ERR(regulator)) {
*ptr = regulator;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return regulator;
}
EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
/* Locks held by regulator_put() */
static void _regulator_put(struct regulator *regulator)
{
......@@ -1498,36 +1491,6 @@ static void _regulator_put(struct regulator *regulator)
module_put(rdev->owner);
}
/**
* devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
* @dev: device for regulator "consumer"
* @id: Supply name or regulator ID.
*
* Managed regulator_get_exclusive(). Regulators returned from this function
* are automatically regulator_put() on driver detach. See regulator_get() for
* more information.
*/
struct regulator *devm_regulator_get_exclusive(struct device *dev,
const char *id)
{
struct regulator **ptr, *regulator;
ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
regulator = _regulator_get(dev, id, 1);
if (!IS_ERR(regulator)) {
*ptr = regulator;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return regulator;
}
EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
/**
* regulator_put - "free" the regulator source
* @regulator: regulator source
......@@ -1544,34 +1507,133 @@ void regulator_put(struct regulator *regulator)
}
EXPORT_SYMBOL_GPL(regulator_put);
static int devm_regulator_match(struct device *dev, void *res, void *data)
/**
* regulator_register_supply_alias - Provide device alias for supply lookup
*
* @dev: device that will be given as the regulator "consumer"
* @id: Supply name or regulator ID
* @alias_dev: device that should be used to lookup the supply
* @alias_id: Supply name or regulator ID that should be used to lookup the
* supply
*
* All lookups for id on dev will instead be conducted for alias_id on
* alias_dev.
*/
int regulator_register_supply_alias(struct device *dev, const char *id,
struct device *alias_dev,
const char *alias_id)
{
struct regulator_supply_alias *map;
map = regulator_find_supply_alias(dev, id);
if (map)
return -EEXIST;
map = kzalloc(sizeof(struct regulator_supply_alias), GFP_KERNEL);
if (!map)
return -ENOMEM;
map->src_dev = dev;
map->src_supply = id;
map->alias_dev = alias_dev;
map->alias_supply = alias_id;
list_add(&map->list, &regulator_supply_alias_list);
pr_info("Adding alias for supply %s,%s -> %s,%s\n",
id, dev_name(dev), alias_id, dev_name(alias_dev));
return 0;
}
EXPORT_SYMBOL_GPL(regulator_register_supply_alias);
/**
* regulator_unregister_supply_alias - Remove device alias
*
* @dev: device that will be given as the regulator "consumer"
* @id: Supply name or regulator ID
*
* Remove a lookup alias if one exists for id on dev.
*/
void regulator_unregister_supply_alias(struct device *dev, const char *id)
{
struct regulator **r = res;
if (!r || !*r) {
WARN_ON(!r || !*r);
return 0;
struct regulator_supply_alias *map;
map = regulator_find_supply_alias(dev, id);
if (map) {
list_del(&map->list);
kfree(map);
}
return *r == data;
}
EXPORT_SYMBOL_GPL(regulator_unregister_supply_alias);
/**
* devm_regulator_put - Resource managed regulator_put()
* @regulator: regulator to free
* regulator_bulk_register_supply_alias - register multiple aliases
*
* @dev: device that will be given as the regulator "consumer"
* @id: List of supply names or regulator IDs
* @alias_dev: device that should be used to lookup the supply
* @alias_id: List of supply names or regulator IDs that should be used to
* lookup the supply
* @num_id: Number of aliases to register
*
* @return 0 on success, an errno on failure.
*
* Deallocate a regulator allocated with devm_regulator_get(). Normally
* this function will not need to be called and the resource management
* code will ensure that the resource is freed.
* This helper function allows drivers to register several supply
* aliases in one operation. If any of the aliases cannot be
* registered any aliases that were registered will be removed
* before returning to the caller.
*/
void devm_regulator_put(struct regulator *regulator)
int regulator_bulk_register_supply_alias(struct device *dev, const char **id,
struct device *alias_dev,
const char **alias_id,
int num_id)
{
int rc;
int i;
int ret;
for (i = 0; i < num_id; ++i) {
ret = regulator_register_supply_alias(dev, id[i], alias_dev,
alias_id[i]);
if (ret < 0)
goto err;
}
return 0;
err:
dev_err(dev,
"Failed to create supply alias %s,%s -> %s,%s\n",
id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
while (--i >= 0)
regulator_unregister_supply_alias(dev, id[i]);
return ret;
}
EXPORT_SYMBOL_GPL(regulator_bulk_register_supply_alias);
/**
* regulator_bulk_unregister_supply_alias - unregister multiple aliases
*
* @dev: device that will be given as the regulator "consumer"
* @id: List of supply names or regulator IDs
* @num_id: Number of aliases to unregister
*
* This helper function allows drivers to unregister several supply
* aliases in one operation.
*/
void regulator_bulk_unregister_supply_alias(struct device *dev,
const char **id,
int num_id)
{
int i;
rc = devres_release(regulator->dev, devm_regulator_release,
devm_regulator_match, regulator);
if (rc != 0)
WARN_ON(rc);
for (i = 0; i < num_id; ++i)
regulator_unregister_supply_alias(dev, id[i]);
}
EXPORT_SYMBOL_GPL(devm_regulator_put);
EXPORT_SYMBOL_GPL(regulator_bulk_unregister_supply_alias);
/* Manage enable GPIO list. Same GPIO pin can be shared among regulators */
static int regulator_ena_gpio_request(struct regulator_dev *rdev,
......@@ -1704,11 +1766,39 @@ static int _regulator_do_enable(struct regulator_dev *rdev)
* together. */
trace_regulator_enable_delay(rdev_get_name(rdev));
if (delay >= 1000) {
mdelay(delay / 1000);
udelay(delay % 1000);
} else if (delay) {
udelay(delay);
/*
* Delay for the requested amount of time as per the guidelines in:
*
* Documentation/timers/timers-howto.txt
*
* The assumption here is that regulators will never be enabled in
* atomic context and therefore sleeping functions can be used.
*/
if (delay) {
unsigned int ms = delay / 1000;
unsigned int us = delay % 1000;
if (ms > 0) {
/*
* For small enough values, handle super-millisecond
* delays in the usleep_range() call below.
*/
if (ms < 20)
us += ms * 1000;
else
msleep(ms);
}
/*
* Give the scheduler some room to coalesce with any other
* wakeup sources. For delays shorter than 10 us, don't even
* bother setting up high-resolution timers and just busy-
* loop.
*/
if (us >= 10)
usleep_range(us, us + 100);
else
udelay(us);
}
trace_regulator_enable_complete(rdev_get_name(rdev));
......@@ -2489,6 +2579,8 @@ static int _regulator_get_voltage(struct regulator_dev *rdev)
ret = rdev->desc->ops->get_voltage(rdev);
} else if (rdev->desc->ops->list_voltage) {
ret = rdev->desc->ops->list_voltage(rdev, 0);
} else if (rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1)) {
ret = rdev->desc->fixed_uV;
} else {
return -EINVAL;
}
......@@ -2912,52 +3004,6 @@ int regulator_bulk_get(struct device *dev, int num_consumers,
}
EXPORT_SYMBOL_GPL(regulator_bulk_get);
/**
* devm_regulator_bulk_get - managed get multiple regulator consumers
*
* @dev: Device to supply
* @num_consumers: Number of consumers to register
* @consumers: Configuration of consumers; clients are stored here.
*
* @return 0 on success, an errno on failure.
*
* This helper function allows drivers to get several regulator
* consumers in one operation with management, the regulators will
* automatically be freed when the device is unbound. If any of the
* regulators cannot be acquired then any regulators that were
* allocated will be freed before returning to the caller.
*/
int devm_regulator_bulk_get(struct device *dev, int num_consumers,
struct regulator_bulk_data *consumers)
{
int i;
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;
err:
for (i = 0; i < num_consumers && consumers[i].consumer; i++)
devm_regulator_put(consumers[i].consumer);
return ret;
}
EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
static void regulator_bulk_enable_async(void *data, async_cookie_t cookie)
{
struct regulator_bulk_data *bulk = data;
......@@ -3170,7 +3216,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->list_voltage && ops->list_voltage(rdev, 0) >= 0)) {
(ops->list_voltage && ops->list_voltage(rdev, 0) >= 0) ||
(rdev->desc->fixed_uV && (rdev->desc->n_voltages == 1))) {
status = device_create_file(dev, &dev_attr_microvolts);
if (status < 0)
return status;
......@@ -3613,22 +3660,6 @@ void regulator_has_full_constraints(void)
}
EXPORT_SYMBOL_GPL(regulator_has_full_constraints);
/**
* regulator_use_dummy_regulator - Provide a dummy regulator when none is found
*
* Calling this function will cause the regulator API to provide a
* dummy regulator to consumers if no physical regulator is found,
* allowing most consumers to proceed as though a regulator were
* configured. This allows systems such as those with software
* controllable regulators for the CPU core only to be brought up more
* readily.
*/
void regulator_use_dummy_regulator(void)
{
board_wants_dummy_regulator = true;
}
EXPORT_SYMBOL_GPL(regulator_use_dummy_regulator);
/**
* rdev_get_drvdata - get rdev regulator driver data
* @rdev: regulator
......
......@@ -253,10 +253,8 @@ static int da9034_set_dvc_voltage_sel(struct regulator_dev *rdev,
}
static const struct regulator_linear_range da9034_ldo12_ranges[] = {
{ .min_uV = 1700000, .max_uV = 2050000, .min_sel = 0, .max_sel = 7,
.uV_step = 50000 },
{ .min_uV = 2700000, .max_uV = 3050000, .min_sel = 8, .max_sel = 15,
.uV_step = 50000 },
REGULATOR_LINEAR_RANGE(1700000, 0, 7, 50000),
REGULATOR_LINEAR_RANGE(2700000, 8, 15, 50000),
};
static struct regulator_ops da903x_regulator_ldo_ops = {
......@@ -463,7 +461,7 @@ static int da903x_regulator_probe(struct platform_device *pdev)
config.init_data = dev_get_platdata(&pdev->dev);
config.driver_data = ri;
rdev = regulator_register(&ri->desc, &config);
rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
......@@ -474,21 +472,12 @@ static int da903x_regulator_probe(struct platform_device *pdev)
return 0;
}
static int da903x_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
regulator_unregister(rdev);
return 0;
}
static struct platform_driver da903x_regulator_driver = {
.driver = {
.name = "da903x-regulator",
.owner = THIS_MODULE,
},
.probe = da903x_regulator_probe,
.remove = da903x_regulator_remove,
};
static int __init da903x_regulator_init(void)
......
......@@ -70,6 +70,7 @@ struct da9052_regulator_info {
int step_uV;
int min_uV;
int max_uV;
unsigned char activate_bit;
};
struct da9052_regulator {
......@@ -209,6 +210,36 @@ static int da9052_map_voltage(struct regulator_dev *rdev,
return sel;
}
static int da9052_regulator_set_voltage_sel(struct regulator_dev *rdev,
unsigned int selector)
{
struct da9052_regulator *regulator = rdev_get_drvdata(rdev);
struct da9052_regulator_info *info = regulator->info;
int id = rdev_get_id(rdev);
int ret;
ret = da9052_reg_update(regulator->da9052, rdev->desc->vsel_reg,
rdev->desc->vsel_mask, selector);
if (ret < 0)
return ret;
/* Some LDOs and DCDCs are DVC controlled which requires enabling of
* the activate bit to implment the changes on the output.
*/
switch (id) {
case DA9052_ID_BUCK1:
case DA9052_ID_BUCK2:
case DA9052_ID_BUCK3:
case DA9052_ID_LDO2:
case DA9052_ID_LDO3:
ret = da9052_reg_update(regulator->da9052, DA9052_SUPPLY_REG,
info->activate_bit, info->activate_bit);
break;
}
return ret;
}
static struct regulator_ops da9052_dcdc_ops = {
.get_current_limit = da9052_dcdc_get_current_limit,
.set_current_limit = da9052_dcdc_set_current_limit,
......@@ -216,7 +247,7 @@ static struct regulator_ops da9052_dcdc_ops = {
.list_voltage = da9052_list_voltage,
.map_voltage = da9052_map_voltage,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_sel = da9052_regulator_set_voltage_sel,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
......@@ -226,7 +257,7 @@ static struct regulator_ops da9052_ldo_ops = {
.list_voltage = da9052_list_voltage,
.map_voltage = da9052_map_voltage,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.set_voltage_sel = da9052_regulator_set_voltage_sel,
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
......@@ -243,14 +274,13 @@ static struct regulator_ops da9052_ldo_ops = {
.owner = THIS_MODULE,\
.vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
.vsel_mask = (1 << (sbits)) - 1,\
.apply_reg = DA9052_SUPPLY_REG, \
.apply_bit = (abits), \
.enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
.enable_mask = 1 << (ebits),\
},\
.min_uV = (min) * 1000,\
.max_uV = (max) * 1000,\
.step_uV = (step) * 1000,\
.activate_bit = (abits),\
}
#define DA9052_DCDC(_id, step, min, max, sbits, ebits, abits) \
......@@ -264,14 +294,13 @@ static struct regulator_ops da9052_ldo_ops = {
.owner = THIS_MODULE,\
.vsel_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
.vsel_mask = (1 << (sbits)) - 1,\
.apply_reg = DA9052_SUPPLY_REG, \
.apply_bit = (abits), \
.enable_reg = DA9052_BUCKCORE_REG + DA9052_ID_##_id, \
.enable_mask = 1 << (ebits),\
},\
.min_uV = (min) * 1000,\
.max_uV = (max) * 1000,\
.step_uV = (step) * 1000,\
.activate_bit = (abits),\
}
static struct da9052_regulator_info da9052_regulator_info[] = {
......@@ -389,8 +418,9 @@ static int da9052_regulator_probe(struct platform_device *pdev)
#endif
}
regulator->rdev = regulator_register(&regulator->info->reg_desc,
&config);
regulator->rdev = devm_regulator_register(&pdev->dev,
&regulator->info->reg_desc,
&config);
if (IS_ERR(regulator->rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
regulator->info->reg_desc.name);
......@@ -402,17 +432,8 @@ static int da9052_regulator_probe(struct platform_device *pdev)
return 0;
}
static int da9052_regulator_remove(struct platform_device *pdev)
{
struct da9052_regulator *regulator = platform_get_drvdata(pdev);
regulator_unregister(regulator->rdev);
return 0;
}
static struct platform_driver da9052_regulator_driver = {
.probe = da9052_regulator_probe,
.remove = da9052_regulator_remove,
.driver = {
.name = "da9052-regulator",
.owner = THIS_MODULE,
......
......@@ -564,13 +564,13 @@ static int da9055_regulator_probe(struct platform_device *pdev)
if (ret < 0)
return ret;
regulator->rdev = regulator_register(&regulator->info->reg_desc,
&config);
regulator->rdev = devm_regulator_register(&pdev->dev,
&regulator->info->reg_desc,
&config);
if (IS_ERR(regulator->rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
regulator->info->reg_desc.name);
ret = PTR_ERR(regulator->rdev);
return ret;
return PTR_ERR(regulator->rdev);
}
/* Only LDO 5 and 6 has got the over current interrupt */
......@@ -588,32 +588,18 @@ static int da9055_regulator_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"Failed to request Regulator IRQ %d: %d\n",
irq, ret);
goto err_regulator;
return ret;
}
}
}
platform_set_drvdata(pdev, regulator);
return 0;
err_regulator:
regulator_unregister(regulator->rdev);
return ret;
}
static int da9055_regulator_remove(struct platform_device *pdev)
{
struct da9055_regulator *regulator = platform_get_drvdata(pdev);
regulator_unregister(regulator->rdev);
return 0;
}
static struct platform_driver da9055_regulator_driver = {
.probe = da9055_regulator_probe,
.remove = da9055_regulator_remove,
.driver = {
.name = "da9055-regulator",
.owner = THIS_MODULE,
......
......@@ -717,7 +717,7 @@ static int da9063_regulator_probe(struct platform_device *pdev)
{
struct da9063 *da9063 = dev_get_drvdata(pdev->dev.parent);
struct da9063_pdata *da9063_pdata = dev_get_platdata(da9063->dev);
struct of_regulator_match *da9063_reg_matches;
struct of_regulator_match *da9063_reg_matches = NULL;
struct da9063_regulators_pdata *regl_pdata;
const struct da9063_dev_model *model;
struct da9063_regulators *regulators;
......@@ -847,13 +847,13 @@ static int da9063_regulator_probe(struct platform_device *pdev)
if (da9063_reg_matches)
config.of_node = da9063_reg_matches[id].of_node;
config.regmap = da9063->regmap;
regl->rdev = regulator_register(&regl->desc, &config);
regl->rdev = devm_regulator_register(&pdev->dev, &regl->desc,
&config);
if (IS_ERR(regl->rdev)) {
dev_err(&pdev->dev,
"Failed to register %s regulator\n",
regl->desc.name);
ret = PTR_ERR(regl->rdev);
goto err;
return PTR_ERR(regl->rdev);
}
id++;
n++;
......@@ -862,9 +862,8 @@ static int da9063_regulator_probe(struct platform_device *pdev)
/* LDOs overcurrent event support */
irq = platform_get_irq_byname(pdev, "LDO_LIM");
if (irq < 0) {
ret = irq;
dev_err(&pdev->dev, "Failed to get IRQ.\n");
goto err;
return irq;
}
regulators->irq_ldo_lim = regmap_irq_get_virq(da9063->regmap_irq, irq);
......@@ -881,27 +880,15 @@ static int da9063_regulator_probe(struct platform_device *pdev)
}
return 0;
err:
/* Wind back regulators registeration */
while (--n >= 0)
regulator_unregister(regulators->regulator[n].rdev);
return ret;
}
static int da9063_regulator_remove(struct platform_device *pdev)
{
struct da9063_regulators *regulators = platform_get_drvdata(pdev);
struct da9063_regulator *regl;
free_irq(regulators->irq_ldo_lim, regulators);
free_irq(regulators->irq_uvov, regulators);
for (regl = &regulators->regulator[regulators->n_regulators - 1];
regl >= &regulators->regulator[0]; regl--)
regulator_unregister(regl->rdev);
return 0;
}
......
......@@ -25,6 +25,7 @@
#include <linux/slab.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/machine.h>
#include <linux/regulator/of_regulator.h>
#include <linux/regmap.h>
#include "da9210-regulator.h"
......@@ -126,7 +127,8 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct da9210 *chip;
struct da9210_pdata *pdata = i2c->dev.platform_data;
struct device *dev = &i2c->dev;
struct da9210_pdata *pdata = dev_get_platdata(dev);
struct regulator_dev *rdev = NULL;
struct regulator_config config = { };
int error;
......@@ -147,12 +149,13 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
}
config.dev = &i2c->dev;
if (pdata)
config.init_data = &pdata->da9210_constraints;
config.init_data = pdata ? &pdata->da9210_constraints :
of_get_regulator_init_data(dev, dev->of_node);
config.driver_data = chip;
config.regmap = chip->regmap;
config.of_node = dev->of_node;
rdev = regulator_register(&da9210_reg, &config);
rdev = devm_regulator_register(&i2c->dev, &da9210_reg, &config);
if (IS_ERR(rdev)) {
dev_err(&i2c->dev, "Failed to register DA9210 regulator\n");
return PTR_ERR(rdev);
......@@ -165,13 +168,6 @@ static int da9210_i2c_probe(struct i2c_client *i2c,
return 0;
}
static int da9210_i2c_remove(struct i2c_client *i2c)
{
struct da9210 *chip = i2c_get_clientdata(i2c);
regulator_unregister(chip->rdev);
return 0;
}
static const struct i2c_device_id da9210_i2c_id[] = {
{"da9210", 0},
{},
......@@ -185,7 +181,6 @@ static struct i2c_driver da9210_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = da9210_i2c_probe,
.remove = da9210_i2c_remove,
.id_table = da9210_i2c_id,
};
......
/*
* devres.c -- Voltage/Current Regulator framework devres implementation.
*
* Copyright 2013 Linaro Ltd
*
* 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.
*
*/
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/regulator/driver.h>
#include <linux/module.h>
#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);
}
static struct regulator *_devm_regulator_get(struct device *dev, const char *id,
int get_type)
{
struct regulator **ptr, *regulator;
ptr = devres_alloc(devm_regulator_release, sizeof(*ptr), GFP_KERNEL);
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);
}
if (!IS_ERR(regulator)) {
*ptr = regulator;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return regulator;
}
/**
* devm_regulator_get - Resource managed regulator_get()
* @dev: device for regulator "consumer"
* @id: Supply name or regulator ID.
*
* Managed regulator_get(). Regulators returned from this function are
* automatically regulator_put() on driver detach. See regulator_get() for more
* information.
*/
struct regulator *devm_regulator_get(struct device *dev, const char *id)
{
return _devm_regulator_get(dev, id, NORMAL_GET);
}
EXPORT_SYMBOL_GPL(devm_regulator_get);
/**
* devm_regulator_get_exclusive - Resource managed regulator_get_exclusive()
* @dev: device for regulator "consumer"
* @id: Supply name or regulator ID.
*
* Managed regulator_get_exclusive(). Regulators returned from this function
* are automatically regulator_put() on driver detach. See regulator_get() for
* more information.
*/
struct regulator *devm_regulator_get_exclusive(struct device *dev,
const char *id)
{
return _devm_regulator_get(dev, id, EXCLUSIVE_GET);
}
EXPORT_SYMBOL_GPL(devm_regulator_get_exclusive);
/**
* devm_regulator_get_optional - Resource managed regulator_get_optional()
* @dev: device for regulator "consumer"
* @id: Supply name or regulator ID.
*
* Managed regulator_get_optional(). Regulators returned from this
* function are automatically regulator_put() on driver detach. See
* regulator_get_optional() for more information.
*/
struct regulator *devm_regulator_get_optional(struct device *dev,
const char *id)
{
return _devm_regulator_get(dev, id, OPTIONAL_GET);
}
EXPORT_SYMBOL_GPL(devm_regulator_get_optional);
static int devm_regulator_match(struct device *dev, void *res, void *data)
{
struct regulator **r = res;
if (!r || !*r) {
WARN_ON(!r || !*r);
return 0;
}
return *r == data;
}
/**
* devm_regulator_put - Resource managed regulator_put()
* @regulator: regulator to free
*
* Deallocate a regulator allocated with devm_regulator_get(). Normally
* this function will not need to be called and the resource management
* code will ensure that the resource is freed.
*/
void devm_regulator_put(struct regulator *regulator)
{
int rc;
rc = devres_release(regulator->dev, devm_regulator_release,
devm_regulator_match, regulator);
if (rc != 0)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_regulator_put);
/**
* devm_regulator_bulk_get - managed get multiple regulator consumers
*
* @dev: Device to supply
* @num_consumers: Number of consumers to register
* @consumers: Configuration of consumers; clients are stored here.
*
* @return 0 on success, an errno on failure.
*
* This helper function allows drivers to get several regulator
* consumers in one operation with management, the regulators will
* automatically be freed when the device is unbound. If any of the
* regulators cannot be acquired then any regulators that were
* allocated will be freed before returning to the caller.
*/
int devm_regulator_bulk_get(struct device *dev, int num_consumers,
struct regulator_bulk_data *consumers)
{
int i;
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;
err:
for (i = 0; i < num_consumers && consumers[i].consumer; i++)
devm_regulator_put(consumers[i].consumer);
return ret;
}
EXPORT_SYMBOL_GPL(devm_regulator_bulk_get);
static void devm_rdev_release(struct device *dev, void *res)
{
regulator_unregister(*(struct regulator_dev **)res);
}
/**
* devm_regulator_register - Resource managed regulator_register()
* @regulator_desc: regulator to register
* @config: runtime configuration for regulator
*
* Called by regulator drivers to register a regulator. Returns a
* valid pointer to struct regulator_dev on success or an ERR_PTR() on
* error. The regulator will automatically be released when the device
* is unbound.
*/
struct regulator_dev *devm_regulator_register(struct device *dev,
const struct regulator_desc *regulator_desc,
const struct regulator_config *config)
{
struct regulator_dev **ptr, *rdev;
ptr = devres_alloc(devm_rdev_release, sizeof(*ptr),
GFP_KERNEL);
if (!ptr)
return ERR_PTR(-ENOMEM);
rdev = regulator_register(regulator_desc, config);
if (!IS_ERR(rdev)) {
*ptr = rdev;
devres_add(dev, ptr);
} else {
devres_free(ptr);
}
return rdev;
}
EXPORT_SYMBOL_GPL(devm_regulator_register);
static int devm_rdev_match(struct device *dev, void *res, void *data)
{
struct regulator_dev **r = res;
if (!r || !*r) {
WARN_ON(!r || !*r);
return 0;
}
return *r == data;
}
/**
* devm_regulator_unregister - Resource managed regulator_unregister()
* @regulator: regulator to free
*
* Unregister a regulator registered with devm_regulator_register().
* Normally this function will not need to be called and the resource
* management code will ensure that the resource is freed.
*/
void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev)
{
int rc;
rc = devres_release(dev, devm_rdev_release, devm_rdev_match, rdev);
if (rc != 0)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_regulator_unregister);
struct regulator_supply_alias_match {
struct device *dev;
const char *id;
};
static int devm_regulator_match_supply_alias(struct device *dev, void *res,
void *data)
{
struct regulator_supply_alias_match *match = res;
struct regulator_supply_alias_match *target = data;
return match->dev == target->dev && strcmp(match->id, target->id) == 0;
}
static void devm_regulator_destroy_supply_alias(struct device *dev, void *res)
{
struct regulator_supply_alias_match *match = res;
regulator_unregister_supply_alias(match->dev, match->id);
}
/**
* devm_regulator_register_supply_alias - Resource managed
* regulator_register_supply_alias()
*
* @dev: device that will be given as the regulator "consumer"
* @id: Supply name or regulator ID
* @alias_dev: device that should be used to lookup the supply
* @alias_id: Supply name or regulator ID that should be used to lookup the
* supply
*
* The supply alias will automatically be unregistered when the source
* device is unbound.
*/
int devm_regulator_register_supply_alias(struct device *dev, const char *id,
struct device *alias_dev,
const char *alias_id)
{
struct regulator_supply_alias_match *match;
int ret;
match = devres_alloc(devm_regulator_destroy_supply_alias,
sizeof(struct regulator_supply_alias_match),
GFP_KERNEL);
if (!match)
return -ENOMEM;
match->dev = dev;
match->id = id;
ret = regulator_register_supply_alias(dev, id, alias_dev, alias_id);
if (ret < 0) {
devres_free(match);
return ret;
}
devres_add(dev, match);
return 0;
}
EXPORT_SYMBOL_GPL(devm_regulator_register_supply_alias);
/**
* devm_regulator_unregister_supply_alias - Resource managed
* regulator_unregister_supply_alias()
*
* @dev: device that will be given as the regulator "consumer"
* @id: Supply name or regulator ID
*
* Unregister an alias registered with
* devm_regulator_register_supply_alias(). Normally this function
* will not need to be called and the resource management code
* will ensure that the resource is freed.
*/
void devm_regulator_unregister_supply_alias(struct device *dev, const char *id)
{
struct regulator_supply_alias_match match;
int rc;
match.dev = dev;
match.id = id;
rc = devres_release(dev, devm_regulator_destroy_supply_alias,
devm_regulator_match_supply_alias, &match);
if (rc != 0)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(devm_regulator_unregister_supply_alias);
/**
* devm_regulator_bulk_register_supply_alias - Managed register
* multiple aliases
*
* @dev: device that will be given as the regulator "consumer"
* @id: List of supply names or regulator IDs
* @alias_dev: device that should be used to lookup the supply
* @alias_id: List of supply names or regulator IDs that should be used to
* lookup the supply
* @num_id: Number of aliases to register
*
* @return 0 on success, an errno on failure.
*
* This helper function allows drivers to register several supply
* aliases in one operation, the aliases will be automatically
* unregisters when the source device is unbound. If any of the
* aliases cannot be registered any aliases that were registered
* will be removed before returning to the caller.
*/
int devm_regulator_bulk_register_supply_alias(struct device *dev,
const char **id,
struct device *alias_dev,
const char **alias_id,
int num_id)
{
int i;
int ret;
for (i = 0; i < num_id; ++i) {
ret = devm_regulator_register_supply_alias(dev, id[i],
alias_dev,
alias_id[i]);
if (ret < 0)
goto err;
}
return 0;
err:
dev_err(dev,
"Failed to create supply alias %s,%s -> %s,%s\n",
id[i], dev_name(dev), alias_id[i], dev_name(alias_dev));
while (--i >= 0)
devm_regulator_unregister_supply_alias(dev, id[i]);
return ret;
}
EXPORT_SYMBOL_GPL(devm_regulator_bulk_register_supply_alias);
/**
* devm_regulator_bulk_unregister_supply_alias - Managed unregister
* multiple aliases
*
* @dev: device that will be given as the regulator "consumer"
* @id: List of supply names or regulator IDs
* @num_id: Number of aliases to unregister
*
* Unregister aliases registered with
* devm_regulator_bulk_register_supply_alias(). Normally this function
* will not need to be called and the resource management code
* will ensure that the resource is freed.
*/
void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
const char **id,
int num_id)
{
int i;
for (i = 0; i < num_id; ++i)
devm_regulator_unregister_supply_alias(dev, id[i]);
}
EXPORT_SYMBOL_GPL(devm_regulator_bulk_unregister_supply_alias);
......@@ -218,9 +218,8 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
rdesc->vsel_mask = VSEL_NSEL_MASK;
rdesc->owner = THIS_MODULE;
di->rdev = regulator_register(&di->desc, config);
di->rdev = devm_regulator_register(di->dev, &di->desc, config);
return PTR_ERR_OR_ZERO(di->rdev);
}
static struct regmap_config fan53555_regmap_config = {
......@@ -291,14 +290,6 @@ static int fan53555_regulator_probe(struct i2c_client *client,
}
static int fan53555_regulator_remove(struct i2c_client *client)
{
struct fan53555_device_info *di = i2c_get_clientdata(client);
regulator_unregister(di->rdev);
return 0;
}
static const struct i2c_device_id fan53555_id[] = {
{"fan53555", -1},
{ },
......@@ -309,7 +300,6 @@ static struct i2c_driver fan53555_regulator_driver = {
.name = "fan53555-regulator",
},
.probe = fan53555_regulator_probe,
.remove = fan53555_regulator_remove,
.id_table = fan53555_id,
};
......
......@@ -34,7 +34,6 @@
struct fixed_voltage_data {
struct regulator_desc desc;
struct regulator_dev *dev;
int microvolts;
};
......@@ -108,30 +107,7 @@ of_get_fixed_voltage_config(struct device *dev)
return config;
}
static int fixed_voltage_get_voltage(struct regulator_dev *dev)
{
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
if (data->microvolts)
return data->microvolts;
else
return -EINVAL;
}
static int fixed_voltage_list_voltage(struct regulator_dev *dev,
unsigned selector)
{
struct fixed_voltage_data *data = rdev_get_drvdata(dev);
if (selector != 0)
return -EINVAL;
return data->microvolts;
}
static struct regulator_ops fixed_voltage_ops = {
.get_voltage = fixed_voltage_get_voltage,
.list_voltage = fixed_voltage_list_voltage,
};
static int reg_fixed_voltage_probe(struct platform_device *pdev)
......@@ -186,23 +162,21 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
if (config->microvolts)
drvdata->desc.n_voltages = 1;
drvdata->microvolts = config->microvolts;
drvdata->desc.fixed_uV = config->microvolts;
if (config->gpio >= 0)
cfg.ena_gpio = config->gpio;
cfg.ena_gpio_invert = !config->enable_high;
if (config->enabled_at_boot) {
if (config->enable_high) {
if (config->enable_high)
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
} else {
else
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
}
} else {
if (config->enable_high) {
if (config->enable_high)
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_LOW;
} else {
else
cfg.ena_gpio_flags |= GPIOF_OUT_INIT_HIGH;
}
}
if (config->gpio_is_open_drain)
cfg.ena_gpio_flags |= GPIOF_OPEN_DRAIN;
......@@ -222,7 +196,7 @@ static int reg_fixed_voltage_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, drvdata);
dev_dbg(&pdev->dev, "%s supplying %duV\n", drvdata->desc.name,
drvdata->microvolts);
drvdata->desc.fixed_uV);
return 0;
......
......@@ -283,7 +283,6 @@ static int gpio_regulator_probe(struct platform_device *pdev)
dev_err(&pdev->dev, "No regulator type set\n");
ret = -EINVAL;
goto err_memgpio;
break;
}
drvdata->nr_gpios = config->nr_gpios;
......
......@@ -284,9 +284,13 @@ int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
}
for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
int linear_max_uV;
range = &rdev->desc->linear_ranges[i];
linear_max_uV = range->min_uV +
(range->max_sel - range->min_sel) * range->uV_step;
if (!(min_uV <= range->max_uV && max_uV >= range->min_uV))
if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
continue;
if (min_uV <= range->min_uV)
......
/*
* internal.h -- Voltage/Current Regulator framework internal code
*
* Copyright 2007, 2008 Wolfson Microelectronics PLC.
* Copyright 2008 SlimLogic Ltd.
*
* Author: Liam Girdwood <lrg@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 as published by the
* Free Software Foundation; either version 2 of the License, or (at your
* option) any later version.
*
*/
#ifndef __REGULATOR_INTERNAL_H
#define __REGULATOR_INTERNAL_H
/*
* struct regulator
*
* One for each consumer device.
*/
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;
char *supply_name;
struct device_attribute dev_attr;
struct regulator_dev *rdev;
struct dentry *debugfs;
};
#endif
......@@ -112,7 +112,7 @@ static int isl6271a_probe(struct i2c_client *i2c,
struct regulator_config config = { };
struct regulator_init_data *init_data = dev_get_platdata(&i2c->dev);
struct isl_pmic *pmic;
int err, i;
int i;
if (!i2c_check_functionality(i2c->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
return -EIO;
......@@ -133,32 +133,17 @@ static int isl6271a_probe(struct i2c_client *i2c,
config.init_data = NULL;
config.driver_data = pmic;
pmic->rdev[i] = regulator_register(&isl_rd[i], &config);
pmic->rdev[i] = devm_regulator_register(&i2c->dev, &isl_rd[i],
&config);
if (IS_ERR(pmic->rdev[i])) {
dev_err(&i2c->dev, "failed to register %s\n", id->name);
err = PTR_ERR(pmic->rdev[i]);
goto error;
return PTR_ERR(pmic->rdev[i]);
}
}
i2c_set_clientdata(i2c, pmic);
return 0;
error:
while (--i >= 0)
regulator_unregister(pmic->rdev[i]);
return err;
}
static int isl6271a_remove(struct i2c_client *i2c)
{
struct isl_pmic *pmic = i2c_get_clientdata(i2c);
int i;
for (i = 0; i < 3; i++)
regulator_unregister(pmic->rdev[i]);
return 0;
}
static const struct i2c_device_id isl6271a_id[] = {
......@@ -174,7 +159,6 @@ static struct i2c_driver isl6271a_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = isl6271a_probe,
.remove = isl6271a_remove,
.id_table = isl6271a_id,
};
......
......@@ -474,8 +474,8 @@ static int lp3971_i2c_remove(struct i2c_client *i2c)
}
static const struct i2c_device_id lp3971_i2c_id[] = {
{ "lp3971", 0 },
{ }
{ "lp3971", 0 },
{ }
};
MODULE_DEVICE_TABLE(i2c, lp3971_i2c_id);
......
......@@ -785,7 +785,7 @@ static int lp872x_regulator_register(struct lp872x *lp)
struct regulator_desc *desc;
struct regulator_config cfg = { };
struct regulator_dev *rdev;
int i, ret;
int i;
for (i = 0; i < lp->num_regulators; i++) {
desc = (lp->chipid == LP8720) ? &lp8720_regulator_desc[i] :
......@@ -796,34 +796,16 @@ static int lp872x_regulator_register(struct lp872x *lp)
cfg.driver_data = lp;
cfg.regmap = lp->regmap;
rdev = regulator_register(desc, &cfg);
rdev = devm_regulator_register(lp->dev, desc, &cfg);
if (IS_ERR(rdev)) {
dev_err(lp->dev, "regulator register err");
ret = PTR_ERR(rdev);
goto err;
return PTR_ERR(rdev);
}
*(lp->regulators + i) = rdev;
}
return 0;
err:
while (--i >= 0) {
rdev = *(lp->regulators + i);
regulator_unregister(rdev);
}
return ret;
}
static void lp872x_regulator_unregister(struct lp872x *lp)
{
struct regulator_dev *rdev;
int i;
for (i = 0; i < lp->num_regulators; i++) {
rdev = *(lp->regulators + i);
regulator_unregister(rdev);
}
}
static const struct regmap_config lp872x_regmap_config = {
......@@ -979,14 +961,6 @@ static int lp872x_probe(struct i2c_client *cl, const struct i2c_device_id *id)
return ret;
}
static int lp872x_remove(struct i2c_client *cl)
{
struct lp872x *lp = i2c_get_clientdata(cl);
lp872x_regulator_unregister(lp);
return 0;
}
static const struct of_device_id lp872x_dt_ids[] = {
{ .compatible = "ti,lp8720", },
{ .compatible = "ti,lp8725", },
......@@ -1008,7 +982,6 @@ static struct i2c_driver lp872x_driver = {
.of_match_table = of_match_ptr(lp872x_dt_ids),
},
.probe = lp872x_probe,
.remove = lp872x_remove,
.id_table = lp872x_ids,
};
......
......@@ -515,7 +515,7 @@ static int lp8788_buck_probe(struct platform_device *pdev)
cfg.driver_data = buck;
cfg.regmap = lp->regmap;
rdev = regulator_register(&lp8788_buck_desc[id], &cfg);
rdev = devm_regulator_register(&pdev->dev, &lp8788_buck_desc[id], &cfg);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(&pdev->dev, "BUCK%d regulator register err = %d\n",
......@@ -529,18 +529,8 @@ static int lp8788_buck_probe(struct platform_device *pdev)
return 0;
}
static int lp8788_buck_remove(struct platform_device *pdev)
{
struct lp8788_buck *buck = platform_get_drvdata(pdev);
regulator_unregister(buck->regulator);
return 0;
}
static struct platform_driver lp8788_buck_driver = {
.probe = lp8788_buck_probe,
.remove = lp8788_buck_remove,
.driver = {
.name = LP8788_DEV_BUCK,
.owner = THIS_MODULE,
......
......@@ -543,7 +543,7 @@ static int lp8788_dldo_probe(struct platform_device *pdev)
cfg.driver_data = ldo;
cfg.regmap = lp->regmap;
rdev = regulator_register(&lp8788_dldo_desc[id], &cfg);
rdev = devm_regulator_register(&pdev->dev, &lp8788_dldo_desc[id], &cfg);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(&pdev->dev, "DLDO%d regulator register err = %d\n",
......@@ -557,18 +557,8 @@ static int lp8788_dldo_probe(struct platform_device *pdev)
return 0;
}
static int lp8788_dldo_remove(struct platform_device *pdev)
{
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
regulator_unregister(ldo->regulator);
return 0;
}
static struct platform_driver lp8788_dldo_driver = {
.probe = lp8788_dldo_probe,
.remove = lp8788_dldo_remove,
.driver = {
.name = LP8788_DEV_DLDO,
.owner = THIS_MODULE,
......@@ -603,7 +593,7 @@ static int lp8788_aldo_probe(struct platform_device *pdev)
cfg.driver_data = ldo;
cfg.regmap = lp->regmap;
rdev = regulator_register(&lp8788_aldo_desc[id], &cfg);
rdev = devm_regulator_register(&pdev->dev, &lp8788_aldo_desc[id], &cfg);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(&pdev->dev, "ALDO%d regulator register err = %d\n",
......@@ -617,18 +607,8 @@ static int lp8788_aldo_probe(struct platform_device *pdev)
return 0;
}
static int lp8788_aldo_remove(struct platform_device *pdev)
{
struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
regulator_unregister(ldo->regulator);
return 0;
}
static struct platform_driver lp8788_aldo_driver = {
.probe = lp8788_aldo_probe,
.remove = lp8788_aldo_remove,
.driver = {
.name = LP8788_DEV_ALDO,
.owner = THIS_MODULE,
......
......@@ -166,7 +166,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
struct max1586_platform_data *pdata = dev_get_platdata(&client->dev);
struct regulator_config config = { };
struct max1586_data *max1586;
int i, id, ret = -ENOMEM;
int i, id;
max1586 = devm_kzalloc(&client->dev, sizeof(struct max1586_data) +
sizeof(struct regulator_dev *) * (MAX1586_V6 + 1),
......@@ -193,7 +193,7 @@ static int max1586_pmic_probe(struct i2c_client *client,
continue;
if (id < MAX1586_V3 || id > MAX1586_V6) {
dev_err(&client->dev, "invalid regulator id %d\n", id);
goto err;
return -EINVAL;
}
if (id == MAX1586_V3) {
......@@ -207,33 +207,18 @@ static int max1586_pmic_probe(struct i2c_client *client,
config.init_data = pdata->subdevs[i].platform_data;
config.driver_data = max1586;
rdev[i] = regulator_register(&max1586_reg[id], &config);
rdev[i] = devm_regulator_register(&client->dev,
&max1586_reg[id], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(&client->dev, "failed to register %s\n",
max1586_reg[id].name);
goto err;
return PTR_ERR(rdev[i]);
}
}
i2c_set_clientdata(client, max1586);
dev_info(&client->dev, "Maxim 1586 regulator driver loaded\n");
return 0;
err:
while (--i >= 0)
regulator_unregister(rdev[i]);
return ret;
}
static int max1586_pmic_remove(struct i2c_client *client)
{
struct max1586_data *max1586 = i2c_get_clientdata(client);
int i;
for (i = 0; i <= MAX1586_V6; i++)
regulator_unregister(max1586->rdev[i]);
return 0;
}
static const struct i2c_device_id max1586_id[] = {
......@@ -244,7 +229,6 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
static struct i2c_driver max1586_pmic_driver = {
.probe = max1586_pmic_probe,
.remove = max1586_pmic_remove,
.driver = {
.name = "max1586",
.owner = THIS_MODULE,
......
......@@ -478,31 +478,15 @@ static int max77686_pmic_probe(struct platform_device *pdev)
config.of_node = pdata->regulators[i].of_node;
max77686->opmode[i] = regulators[i].enable_mask;
max77686->rdev[i] = regulator_register(&regulators[i], &config);
max77686->rdev[i] = devm_regulator_register(&pdev->dev,
&regulators[i], &config);
if (IS_ERR(max77686->rdev[i])) {
ret = PTR_ERR(max77686->rdev[i]);
dev_err(&pdev->dev,
"regulator init failed for %d\n", i);
max77686->rdev[i] = NULL;
goto err;
return PTR_ERR(max77686->rdev[i]);
}
}
return 0;
err:
while (--i >= 0)
regulator_unregister(max77686->rdev[i]);
return ret;
}
static int max77686_pmic_remove(struct platform_device *pdev)
{
struct max77686_data *max77686 = platform_get_drvdata(pdev);
int i;
for (i = 0; i < MAX77686_REGULATORS; i++)
regulator_unregister(max77686->rdev[i]);
return 0;
}
......@@ -518,7 +502,6 @@ static struct platform_driver max77686_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max77686_pmic_probe,
.remove = max77686_pmic_remove,
.id_table = max77686_pmic_id,
};
......
......@@ -230,7 +230,7 @@ static int max77693_pmic_probe(struct platform_device *pdev)
struct max77693_dev *iodev = dev_get_drvdata(pdev->dev.parent);
struct max77693_pmic_dev *max77693_pmic;
struct max77693_regulator_data *rdata = NULL;
int num_rdata, i, ret;
int num_rdata, i;
struct regulator_config config;
num_rdata = max77693_pmic_init_rdata(&pdev->dev, &rdata);
......@@ -266,35 +266,15 @@ static int max77693_pmic_probe(struct platform_device *pdev)
config.init_data = rdata[i].initdata;
config.of_node = rdata[i].of_node;
max77693_pmic->rdev[i] = regulator_register(&regulators[id],
&config);
max77693_pmic->rdev[i] = devm_regulator_register(&pdev->dev,
&regulators[id], &config);
if (IS_ERR(max77693_pmic->rdev[i])) {
ret = PTR_ERR(max77693_pmic->rdev[i]);
dev_err(max77693_pmic->dev,
"Failed to initialize regulator-%d\n", id);
max77693_pmic->rdev[i] = NULL;
goto err;
return PTR_ERR(max77693_pmic->rdev[i]);
}
}
return 0;
err:
while (--i >= 0)
regulator_unregister(max77693_pmic->rdev[i]);
return ret;
}
static int max77693_pmic_remove(struct platform_device *pdev)
{
struct max77693_pmic_dev *max77693_pmic = platform_get_drvdata(pdev);
struct regulator_dev **rdev = max77693_pmic->rdev;
int i;
for (i = 0; i < max77693_pmic->num_regulators; i++)
if (rdev[i])
regulator_unregister(rdev[i]);
return 0;
}
......@@ -311,7 +291,6 @@ static struct platform_driver max77693_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max77693_pmic_probe,
.remove = max77693_pmic_remove,
.id_table = max77693_pmic_id,
};
......
......@@ -234,7 +234,8 @@ static int max8649_regulator_probe(struct i2c_client *client,
config.driver_data = info;
config.regmap = info->regmap;
info->regulator = regulator_register(&dcdc_desc, &config);
info->regulator = devm_regulator_register(&client->dev, &dcdc_desc,
&config);
if (IS_ERR(info->regulator)) {
dev_err(info->dev, "failed to register regulator %s\n",
dcdc_desc.name);
......@@ -244,16 +245,6 @@ static int max8649_regulator_probe(struct i2c_client *client,
return 0;
}
static int max8649_regulator_remove(struct i2c_client *client)
{
struct max8649_regulator_info *info = i2c_get_clientdata(client);
if (info)
regulator_unregister(info->regulator);
return 0;
}
static const struct i2c_device_id max8649_id[] = {
{ "max8649", 0 },
{ }
......@@ -262,7 +253,6 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
static struct i2c_driver max8649_driver = {
.probe = max8649_regulator_probe,
.remove = max8649_regulator_remove,
.driver = {
.name = "max8649",
},
......
......@@ -439,7 +439,7 @@ static int max8660_probe(struct i2c_client *client,
for (i = 0; i < pdata->num_subdevs; i++) {
if (!pdata->subdevs[i].platform_data)
goto err_out;
return ret;
boot_on = pdata->subdevs[i].platform_data->constraints.boot_on;
......@@ -465,7 +465,7 @@ static int max8660_probe(struct i2c_client *client,
case MAX8660_V7:
if (type == MAX8661) {
dev_err(dev, "Regulator not on this chip!\n");
goto err_out;
return -EINVAL;
}
if (boot_on)
......@@ -475,7 +475,7 @@ static int max8660_probe(struct i2c_client *client,
default:
dev_err(dev, "invalid regulator %s\n",
pdata->subdevs[i].name);
goto err_out;
return ret;
}
}
......@@ -489,33 +489,18 @@ static int max8660_probe(struct i2c_client *client,
config.of_node = of_node[i];
config.driver_data = max8660;
rdev[i] = regulator_register(&max8660_reg[id], &config);
rdev[i] = devm_regulator_register(&client->dev,
&max8660_reg[id], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(dev, "failed to register %s\n",
dev_err(&client->dev, "failed to register %s\n",
max8660_reg[id].name);
goto err_unregister;
return PTR_ERR(rdev[i]);
}
}
i2c_set_clientdata(client, max8660);
return 0;
err_unregister:
while (--i >= 0)
regulator_unregister(rdev[i]);
err_out:
return ret;
}
static int max8660_remove(struct i2c_client *client)
{
struct max8660 *max8660 = i2c_get_clientdata(client);
int i;
for (i = 0; i < MAX8660_V_END; i++)
regulator_unregister(max8660->rdev[i]);
return 0;
}
static const struct i2c_device_id max8660_id[] = {
......@@ -527,7 +512,6 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
static struct i2c_driver max8660_driver = {
.probe = max8660_probe,
.remove = max8660_remove,
.driver = {
.name = "max8660",
.owner = THIS_MODULE,
......
......@@ -350,33 +350,17 @@ static int max8907_regulator_probe(struct platform_device *pdev)
pmic->desc[i].ops = &max8907_out5v_hwctl_ops;
}
pmic->rdev[i] = regulator_register(&pmic->desc[i], &config);
pmic->rdev[i] = devm_regulator_register(&pdev->dev,
&pmic->desc[i], &config);
if (IS_ERR(pmic->rdev[i])) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
pmic->desc[i].name);
ret = PTR_ERR(pmic->rdev[i]);
goto err_unregister_regulator;
return PTR_ERR(pmic->rdev[i]);
}
}
return 0;
err_unregister_regulator:
while (--i >= 0)
regulator_unregister(pmic->rdev[i]);
return ret;
}
static int max8907_regulator_remove(struct platform_device *pdev)
{
struct max8907_regulator *pmic = platform_get_drvdata(pdev);
int i;
for (i = 0; i < MAX8907_NUM_REGULATORS; i++)
regulator_unregister(pmic->rdev[i]);
return 0;
}
static struct platform_driver max8907_regulator_driver = {
......@@ -385,7 +369,6 @@ static struct platform_driver max8907_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = max8907_regulator_probe,
.remove = max8907_regulator_remove,
};
static int __init max8907_regulator_init(void)
......
......@@ -312,7 +312,7 @@ static int max8925_regulator_probe(struct platform_device *pdev)
if (pdata)
config.init_data = pdata;
rdev = regulator_register(&ri->desc, &config);
rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
ri->desc.name);
......@@ -323,22 +323,12 @@ static int max8925_regulator_probe(struct platform_device *pdev)
return 0;
}
static int max8925_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
regulator_unregister(rdev);
return 0;
}
static struct platform_driver max8925_regulator_driver = {
.driver = {
.name = "max8925-regulator",
.owner = THIS_MODULE,
},
.probe = max8925_regulator_probe,
.remove = max8925_regulator_remove,
};
static int __init max8925_regulator_init(void)
......
......@@ -467,7 +467,7 @@ static int max8973_probe(struct i2c_client *client,
config.regmap = max->regmap;
/* Register the regulators */
rdev = regulator_register(&max->desc, &config);
rdev = devm_regulator_register(&client->dev, &max->desc, &config);
if (IS_ERR(rdev)) {
ret = PTR_ERR(rdev);
dev_err(max->dev, "regulator register failed, err %d\n", ret);
......@@ -478,14 +478,6 @@ static int max8973_probe(struct i2c_client *client,
return 0;
}
static int max8973_remove(struct i2c_client *client)
{
struct max8973_chip *max = i2c_get_clientdata(client);
regulator_unregister(max->rdev);
return 0;
}
static const struct i2c_device_id max8973_id[] = {
{.name = "max8973",},
{},
......@@ -499,7 +491,6 @@ static struct i2c_driver max8973_i2c_driver = {
.owner = THIS_MODULE,
},
.probe = max8973_probe,
.remove = max8973_remove,
.id_table = max8973_id,
};
......
......@@ -690,8 +690,9 @@ static int max8997_set_voltage_buck(struct regulator_dev *rdev,
if (max8997->ignore_gpiodvs_side_effect == false)
return -EINVAL;
dev_warn(&rdev->dev, "MAX8997 GPIO-DVS Side Effect Warning: GPIO SET:"
" %d -> %d\n", max8997->buck125_gpioindex, tmp_idx);
dev_warn(&rdev->dev,
"MAX8997 GPIO-DVS Side Effect Warning: GPIO SET: %d -> %d\n",
max8997->buck125_gpioindex, tmp_idx);
out:
if (new_idx < 0 || new_val < 0)
......@@ -1081,7 +1082,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck1_voltage[i] +
buck1245_voltage_map_desc.step);
if (ret < 0)
goto err_out;
return ret;
max8997->buck2_vol[i] = ret =
max8997_get_voltage_proper_val(
......@@ -1090,7 +1091,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck2_voltage[i] +
buck1245_voltage_map_desc.step);
if (ret < 0)
goto err_out;
return ret;
max8997->buck5_vol[i] = ret =
max8997_get_voltage_proper_val(
......@@ -1099,7 +1100,7 @@ static int max8997_pmic_probe(struct platform_device *pdev)
pdata->buck5_voltage[i] +
buck1245_voltage_map_desc.step);
if (ret < 0)
goto err_out;
return ret;
if (max_buck1 < max8997->buck1_vol[i])
max_buck1 = max8997->buck1_vol[i];
......@@ -1143,24 +1144,23 @@ static int max8997_pmic_probe(struct platform_device *pdev)
!gpio_is_valid(pdata->buck125_gpios[1]) ||
!gpio_is_valid(pdata->buck125_gpios[2])) {
dev_err(&pdev->dev, "GPIO NOT VALID\n");
ret = -EINVAL;
goto err_out;
return -EINVAL;
}
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[0],
"MAX8997 SET1");
if (ret)
goto err_out;
return ret;
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[1],
"MAX8997 SET2");
if (ret)
goto err_out;
return ret;
ret = devm_gpio_request(&pdev->dev, pdata->buck125_gpios[2],
"MAX8997 SET3");
if (ret)
goto err_out;
return ret;
gpio_direction_output(pdata->buck125_gpios[0],
(max8997->buck125_gpioindex >> 2)
......@@ -1205,33 +1205,16 @@ static int max8997_pmic_probe(struct platform_device *pdev)
config.driver_data = max8997;
config.of_node = pdata->regulators[i].reg_node;
rdev[i] = regulator_register(&regulators[id], &config);
rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
&config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(max8997->dev, "regulator init failed for %d\n",
id);
rdev[i] = NULL;
goto err;
return PTR_ERR(rdev[i]);
}
}
return 0;
err:
while (--i >= 0)
regulator_unregister(rdev[i]);
err_out:
return ret;
}
static int max8997_pmic_remove(struct platform_device *pdev)
{
struct max8997_data *max8997 = platform_get_drvdata(pdev);
struct regulator_dev **rdev = max8997->rdev;
int i;
for (i = 0; i < max8997->num_regulators; i++)
regulator_unregister(rdev[i]);
return 0;
}
static const struct platform_device_id max8997_pmic_id[] = {
......@@ -1246,7 +1229,6 @@ static struct platform_driver max8997_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max8997_pmic_probe,
.remove = max8997_pmic_remove,
.id_table = max8997_pmic_id,
};
......
......@@ -790,16 +790,14 @@ static int max8998_pmic_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"MAX8998 SET1 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set1);
ret = -EIO;
goto err_out;
return -EIO;
}
/* Check if SET2 is not equal to 0 */
if (!pdata->buck1_set2) {
dev_err(&pdev->dev,
"MAX8998 SET2 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck1_set2);
ret = -EIO;
goto err_out;
return -EIO;
}
gpio_request(pdata->buck1_set1, "MAX8998 BUCK1_SET1");
......@@ -823,7 +821,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
ret = max8998_write_reg(i2c,
MAX8998_REG_BUCK1_VOLTAGE1 + v, i);
if (ret)
goto err_out;
return ret;
}
}
......@@ -833,8 +831,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
dev_err(&pdev->dev,
"MAX8998 SET3 GPIO defined as 0 !\n");
WARN_ON(!pdata->buck2_set3);
ret = -EIO;
goto err_out;
return -EIO;
}
gpio_request(pdata->buck2_set3, "MAX8998 BUCK2_SET3");
gpio_direction_output(pdata->buck2_set3,
......@@ -852,7 +849,7 @@ static int max8998_pmic_probe(struct platform_device *pdev)
ret = max8998_write_reg(i2c,
MAX8998_REG_BUCK2_VOLTAGE1 + v, i);
if (ret)
goto err_out;
return ret;
}
}
......@@ -875,33 +872,18 @@ static int max8998_pmic_probe(struct platform_device *pdev)
config.init_data = pdata->regulators[i].initdata;
config.driver_data = max8998;
rdev[i] = regulator_register(&regulators[index], &config);
rdev[i] = devm_regulator_register(&pdev->dev,
&regulators[index], &config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(max8998->dev, "regulator %s init failed (%d)\n",
regulators[index].name, ret);
rdev[i] = NULL;
goto err;
return ret;
}
}
return 0;
err:
while (--i >= 0)
regulator_unregister(rdev[i]);
err_out:
return ret;
}
static int max8998_pmic_remove(struct platform_device *pdev)
{
struct max8998_data *max8998 = platform_get_drvdata(pdev);
struct regulator_dev **rdev = max8998->rdev;
int i;
for (i = 0; i < max8998->num_regulators; i++)
regulator_unregister(rdev[i]);
return 0;
}
......@@ -918,7 +900,6 @@ static struct platform_driver max8998_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = max8998_pmic_probe,
.remove = max8998_pmic_remove,
.id_table = max8998_pmic_id,
};
......
......@@ -258,34 +258,34 @@ static struct mc13xxx_regulator mc13783_regulators[] = {
MC13783_FIXED_DEFINE(REG, VAUDIO, REGULATORMODE0, mc13783_vaudio_val),
MC13783_FIXED_DEFINE(REG, VIOHI, REGULATORMODE0, mc13783_viohi_val),
MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VIOLO, REGULATORMODE0, REGULATORSETTING0,
mc13783_violo_val),
MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VDIG, REGULATORMODE0, REGULATORSETTING0,
mc13783_vdig_val),
MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VGEN, REGULATORMODE0, REGULATORSETTING0,
mc13783_vgen_val),
MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VRFDIG, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfdig_val),
MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VRFREF, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfref_val),
MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VRFCP, REGULATORMODE0, REGULATORSETTING0,
mc13783_vrfcp_val),
MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VSIM, REGULATORMODE1, REGULATORSETTING0,
mc13783_vsim_val),
MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VESIM, REGULATORMODE1, REGULATORSETTING0,
mc13783_vesim_val),
MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0, \
MC13783_DEFINE_REGU(VCAM, REGULATORMODE1, REGULATORSETTING0,
mc13783_vcam_val),
MC13783_FIXED_DEFINE(REG, VRFBG, REGULATORMODE1, mc13783_vrfbg_val),
MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1, \
MC13783_DEFINE_REGU(VVIB, REGULATORMODE1, REGULATORSETTING1,
mc13783_vvib_val),
MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1, \
MC13783_DEFINE_REGU(VRF1, REGULATORMODE1, REGULATORSETTING1,
mc13783_vrf_val),
MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1, \
MC13783_DEFINE_REGU(VRF2, REGULATORMODE1, REGULATORSETTING1,
mc13783_vrf_val),
MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1, \
MC13783_DEFINE_REGU(VMMC1, REGULATORMODE1, REGULATORSETTING1,
mc13783_vmmc_val),
MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1, \
MC13783_DEFINE_REGU(VMMC2, REGULATORMODE1, REGULATORSETTING1,
mc13783_vmmc_val),
MC13783_GPO_DEFINE(REG, GPO1, POWERMISC, mc13783_gpo_val),
MC13783_GPO_DEFINE(REG, GPO2, POWERMISC, mc13783_gpo_val),
......@@ -400,7 +400,7 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
dev_get_platdata(&pdev->dev);
struct mc13xxx_regulator_init_data *mc13xxx_data;
struct regulator_config config = { };
int i, ret, num_regulators;
int i, num_regulators;
num_regulators = mc13xxx_get_num_regulators_dt(pdev);
......@@ -444,31 +444,15 @@ static int mc13783_regulator_probe(struct platform_device *pdev)
config.driver_data = priv;
config.of_node = node;
priv->regulators[i] = regulator_register(desc, &config);
priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
&config);
if (IS_ERR(priv->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
mc13783_regulators[i].desc.name);
ret = PTR_ERR(priv->regulators[i]);
goto err;
return PTR_ERR(priv->regulators[i]);
}
}
return 0;
err:
while (--i >= 0)
regulator_unregister(priv->regulators[i]);
return ret;
}
static int mc13783_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
int i;
for (i = 0; i < priv->num_regulators; i++)
regulator_unregister(priv->regulators[i]);
return 0;
}
......@@ -477,7 +461,6 @@ static struct platform_driver mc13783_regulator_driver = {
.name = "mc13783-regulator",
.owner = THIS_MODULE,
},
.remove = mc13783_regulator_remove,
.probe = mc13783_regulator_probe,
};
......
......@@ -611,43 +611,27 @@ static int mc13892_regulator_probe(struct platform_device *pdev)
config.driver_data = priv;
config.of_node = node;
priv->regulators[i] = regulator_register(desc, &config);
priv->regulators[i] = devm_regulator_register(&pdev->dev, desc,
&config);
if (IS_ERR(priv->regulators[i])) {
dev_err(&pdev->dev, "failed to register regulator %s\n",
mc13892_regulators[i].desc.name);
ret = PTR_ERR(priv->regulators[i]);
goto err;
return PTR_ERR(priv->regulators[i]);
}
}
return 0;
err:
while (--i >= 0)
regulator_unregister(priv->regulators[i]);
return ret;
err_unlock:
mc13xxx_unlock(mc13892);
return ret;
}
static int mc13892_regulator_remove(struct platform_device *pdev)
{
struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
int i;
for (i = 0; i < priv->num_regulators; i++)
regulator_unregister(priv->regulators[i]);
return 0;
}
static struct platform_driver mc13892_regulator_driver = {
.driver = {
.name = "mc13892-regulator",
.owner = THIS_MODULE,
},
.remove = mc13892_regulator_remove,
.probe = mc13892_regulator_probe,
};
......
......@@ -23,6 +23,8 @@ static void of_get_regulation_constraints(struct device_node *np,
const __be32 *min_uA, *max_uA, *ramp_delay;
struct property *prop;
struct regulation_constraints *constraints = &(*init_data)->constraints;
int ret;
u32 pval;
constraints->name = of_get_property(np, "regulator-name", NULL);
......@@ -73,6 +75,10 @@ static void of_get_regulation_constraints(struct device_node *np,
else
constraints->ramp_disable = true;
}
ret = of_property_read_u32(np, "regulator-enable-ramp-delay", &pval);
if (!ret)
constraints->enable_time = pval;
}
/**
......
......@@ -33,6 +33,7 @@ struct regs_info {
u8 vsel_addr;
u8 ctrl_addr;
u8 tstep_addr;
int sleep_id;
};
static const struct regs_info palmas_regs_info[] = {
......@@ -42,6 +43,7 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS12_VOLTAGE,
.ctrl_addr = PALMAS_SMPS12_CTRL,
.tstep_addr = PALMAS_SMPS12_TSTEP,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
},
{
.name = "SMPS123",
......@@ -49,12 +51,14 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS12_VOLTAGE,
.ctrl_addr = PALMAS_SMPS12_CTRL,
.tstep_addr = PALMAS_SMPS12_TSTEP,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS12,
},
{
.name = "SMPS3",
.sname = "smps3-in",
.vsel_addr = PALMAS_SMPS3_VOLTAGE,
.ctrl_addr = PALMAS_SMPS3_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS3,
},
{
.name = "SMPS45",
......@@ -62,6 +66,7 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS45_VOLTAGE,
.ctrl_addr = PALMAS_SMPS45_CTRL,
.tstep_addr = PALMAS_SMPS45_TSTEP,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
},
{
.name = "SMPS457",
......@@ -69,6 +74,7 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS45_VOLTAGE,
.ctrl_addr = PALMAS_SMPS45_CTRL,
.tstep_addr = PALMAS_SMPS45_TSTEP,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS45,
},
{
.name = "SMPS6",
......@@ -76,12 +82,14 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS6_VOLTAGE,
.ctrl_addr = PALMAS_SMPS6_CTRL,
.tstep_addr = PALMAS_SMPS6_TSTEP,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS6,
},
{
.name = "SMPS7",
.sname = "smps7-in",
.vsel_addr = PALMAS_SMPS7_VOLTAGE,
.ctrl_addr = PALMAS_SMPS7_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS7,
},
{
.name = "SMPS8",
......@@ -89,108 +97,128 @@ static const struct regs_info palmas_regs_info[] = {
.vsel_addr = PALMAS_SMPS8_VOLTAGE,
.ctrl_addr = PALMAS_SMPS8_CTRL,
.tstep_addr = PALMAS_SMPS8_TSTEP,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS8,
},
{
.name = "SMPS9",
.sname = "smps9-in",
.vsel_addr = PALMAS_SMPS9_VOLTAGE,
.ctrl_addr = PALMAS_SMPS9_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS9,
},
{
.name = "SMPS10_OUT2",
.sname = "smps10-in",
.ctrl_addr = PALMAS_SMPS10_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
},
{
.name = "SMPS10_OUT1",
.sname = "smps10-out2",
.ctrl_addr = PALMAS_SMPS10_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SMPS10,
},
{
.name = "LDO1",
.sname = "ldo1-in",
.vsel_addr = PALMAS_LDO1_VOLTAGE,
.ctrl_addr = PALMAS_LDO1_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO1,
},
{
.name = "LDO2",
.sname = "ldo2-in",
.vsel_addr = PALMAS_LDO2_VOLTAGE,
.ctrl_addr = PALMAS_LDO2_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO2,
},
{
.name = "LDO3",
.sname = "ldo3-in",
.vsel_addr = PALMAS_LDO3_VOLTAGE,
.ctrl_addr = PALMAS_LDO3_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO3,
},
{
.name = "LDO4",
.sname = "ldo4-in",
.vsel_addr = PALMAS_LDO4_VOLTAGE,
.ctrl_addr = PALMAS_LDO4_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO4,
},
{
.name = "LDO5",
.sname = "ldo5-in",
.vsel_addr = PALMAS_LDO5_VOLTAGE,
.ctrl_addr = PALMAS_LDO5_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO5,
},
{
.name = "LDO6",
.sname = "ldo6-in",
.vsel_addr = PALMAS_LDO6_VOLTAGE,
.ctrl_addr = PALMAS_LDO6_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO6,
},
{
.name = "LDO7",
.sname = "ldo7-in",
.vsel_addr = PALMAS_LDO7_VOLTAGE,
.ctrl_addr = PALMAS_LDO7_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO7,
},
{
.name = "LDO8",
.sname = "ldo8-in",
.vsel_addr = PALMAS_LDO8_VOLTAGE,
.ctrl_addr = PALMAS_LDO8_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO8,
},
{
.name = "LDO9",
.sname = "ldo9-in",
.vsel_addr = PALMAS_LDO9_VOLTAGE,
.ctrl_addr = PALMAS_LDO9_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDO9,
},
{
.name = "LDOLN",
.sname = "ldoln-in",
.vsel_addr = PALMAS_LDOLN_VOLTAGE,
.ctrl_addr = PALMAS_LDOLN_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDOLN,
},
{
.name = "LDOUSB",
.sname = "ldousb-in",
.vsel_addr = PALMAS_LDOUSB_VOLTAGE,
.ctrl_addr = PALMAS_LDOUSB_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_LDOUSB,
},
{
.name = "REGEN1",
.ctrl_addr = PALMAS_REGEN1_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_REGEN1,
},
{
.name = "REGEN2",
.ctrl_addr = PALMAS_REGEN2_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_REGEN2,
},
{
.name = "REGEN3",
.ctrl_addr = PALMAS_REGEN3_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_REGEN3,
},
{
.name = "SYSEN1",
.ctrl_addr = PALMAS_SYSEN1_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SYSEN1,
},
{
.name = "SYSEN2",
.ctrl_addr = PALMAS_SYSEN2_CTRL,
.sleep_id = PALMAS_EXTERNAL_REQSTR_ID_SYSEN2,
},
};
......@@ -478,6 +506,17 @@ static struct regulator_ops palmas_ops_smps = {
.set_ramp_delay = palmas_smps_set_ramp_delay,
};
static struct regulator_ops palmas_ops_ext_control_smps = {
.set_mode = palmas_set_mode_smps,
.get_mode = palmas_get_mode_smps,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = palmas_list_voltage_smps,
.map_voltage = palmas_map_voltage_smps,
.set_voltage_time_sel = palma_smps_set_voltage_smps_time_sel,
.set_ramp_delay = palmas_smps_set_ramp_delay,
};
static struct regulator_ops palmas_ops_smps10 = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
......@@ -513,12 +552,37 @@ static struct regulator_ops palmas_ops_ldo = {
.map_voltage = regulator_map_voltage_linear,
};
static struct regulator_ops palmas_ops_ext_control_ldo = {
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
.list_voltage = regulator_list_voltage_linear,
.map_voltage = regulator_map_voltage_linear,
};
static struct regulator_ops palmas_ops_extreg = {
.is_enabled = regulator_is_enabled_regmap,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
};
static struct regulator_ops palmas_ops_ext_control_extreg = {
};
static int palmas_regulator_config_external(struct palmas *palmas, int id,
struct palmas_reg_init *reg_init)
{
int sleep_id = palmas_regs_info[id].sleep_id;
int ret;
ret = palmas_ext_control_req_config(palmas, sleep_id,
reg_init->roof_floor, true);
if (ret < 0)
dev_err(palmas->dev,
"Ext control config for regulator %d failed %d\n",
id, ret);
return ret;
}
/*
* setup the hardware based sleep configuration of the SMPS/LDO regulators
* from the platform data. This is different to the software based control
......@@ -577,7 +641,22 @@ static int palmas_smps_init(struct palmas *palmas, int id,
return ret;
}
if (reg_init->roof_floor && (id != PALMAS_REG_SMPS10_OUT1) &&
(id != PALMAS_REG_SMPS10_OUT2)) {
/* Enable externally controlled regulator */
addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_smps_read(palmas, addr, &reg);
if (ret < 0)
return ret;
if (!(reg & PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK)) {
reg |= SMPS_CTRL_MODE_ON;
ret = palmas_smps_write(palmas, addr, reg);
if (ret < 0)
return ret;
}
return palmas_regulator_config_external(palmas, id, reg_init);
}
return 0;
}
......@@ -608,6 +687,20 @@ static int palmas_ldo_init(struct palmas *palmas, int id,
if (ret)
return ret;
if (reg_init->roof_floor) {
/* Enable externally controlled regulator */
addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_update_bits(palmas, PALMAS_LDO_BASE,
addr, PALMAS_LDO1_CTRL_MODE_ACTIVE,
PALMAS_LDO1_CTRL_MODE_ACTIVE);
if (ret < 0) {
dev_err(palmas->dev,
"LDO Register 0x%02x update failed %d\n",
addr, ret);
return ret;
}
return palmas_regulator_config_external(palmas, id, reg_init);
}
return 0;
}
......@@ -630,6 +723,21 @@ static int palmas_extreg_init(struct palmas *palmas, int id,
addr, ret);
return ret;
}
if (reg_init->roof_floor) {
/* Enable externally controlled regulator */
addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_update_bits(palmas, PALMAS_RESOURCE_BASE,
addr, PALMAS_REGEN1_CTRL_MODE_ACTIVE,
PALMAS_REGEN1_CTRL_MODE_ACTIVE);
if (ret < 0) {
dev_err(palmas->dev,
"Resource Register 0x%02x update failed %d\n",
addr, ret);
return ret;
}
return palmas_regulator_config_external(palmas, id, reg_init);
}
return 0;
}
......@@ -712,7 +820,7 @@ static void palmas_dt_to_pdata(struct device *dev,
int idx, ret;
node = of_node_get(node);
regulators = of_find_node_by_name(node, "regulators");
regulators = of_get_child_by_name(node, "regulators");
if (!regulators) {
dev_info(dev, "regulator node not found\n");
return;
......@@ -740,9 +848,35 @@ static void palmas_dt_to_pdata(struct device *dev,
of_property_read_bool(palmas_matches[idx].of_node,
"ti,warm-reset");
pdata->reg_init[idx]->roof_floor =
of_property_read_bool(palmas_matches[idx].of_node,
"ti,roof-floor");
ret = of_property_read_u32(palmas_matches[idx].of_node,
"ti,roof-floor", &prop);
/* EINVAL: Property not found */
if (ret != -EINVAL) {
int econtrol;
/* use default value, when no value is specified */
econtrol = PALMAS_EXT_CONTROL_NSLEEP;
if (!ret) {
switch (prop) {
case 1:
econtrol = PALMAS_EXT_CONTROL_ENABLE1;
break;
case 2:
econtrol = PALMAS_EXT_CONTROL_ENABLE2;
break;
case 3:
econtrol = PALMAS_EXT_CONTROL_NSLEEP;
break;
default:
WARN_ON(1);
dev_warn(dev,
"%s: Invalid roof-floor option: %u\n",
palmas_matches[idx].name, prop);
break;
}
}
pdata->reg_init[idx]->roof_floor = econtrol;
}
ret = of_property_read_u32(palmas_matches[idx].of_node,
"ti,mode-sleep", &prop);
......@@ -856,7 +990,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
if (ret < 0) {
dev_err(&pdev->dev,
"reading TSTEP reg failed: %d\n", ret);
goto err_unregister_regulator;
return ret;
}
pmic->desc[id].ramp_delay =
palmas_smps_ramp_delay[reg & 0x3];
......@@ -868,7 +1002,9 @@ static int palmas_regulators_probe(struct platform_device *pdev)
reg_init = pdata->reg_init[id];
ret = palmas_smps_init(palmas, id, reg_init);
if (ret)
goto err_unregister_regulator;
return ret;
} else {
reg_init = NULL;
}
/* Register the regulators */
......@@ -909,11 +1045,15 @@ static int palmas_regulators_probe(struct platform_device *pdev)
ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret)
goto err_unregister_regulator;
return ret;
if (reg & PALMAS_SMPS12_VOLTAGE_RANGE)
pmic->range[id] = 1;
pmic->desc[id].ops = &palmas_ops_smps;
if (reg_init && reg_init->roof_floor)
pmic->desc[id].ops =
&palmas_ops_ext_control_smps;
else
pmic->desc[id].ops = &palmas_ops_smps;
pmic->desc[id].n_voltages = PALMAS_SMPS_NUM_VOLTAGES;
pmic->desc[id].vsel_reg =
PALMAS_BASE_TO_REG(PALMAS_SMPS_BASE,
......@@ -925,7 +1065,7 @@ static int palmas_regulators_probe(struct platform_device *pdev)
addr = palmas_regs_info[id].ctrl_addr;
ret = palmas_smps_read(pmic->palmas, addr, &reg);
if (ret)
goto err_unregister_regulator;
return ret;
pmic->current_reg_mode[id] = reg &
PALMAS_SMPS12_CTRL_MODE_ACTIVE_MASK;
}
......@@ -941,13 +1081,13 @@ static int palmas_regulators_probe(struct platform_device *pdev)
pmic->desc[id].supply_name = palmas_regs_info[id].sname;
config.of_node = palmas_matches[id].of_node;
rdev = regulator_register(&pmic->desc[id], &config);
rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
pdev->name);
ret = PTR_ERR(rdev);
goto err_unregister_regulator;
return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
......@@ -956,6 +1096,10 @@ static int palmas_regulators_probe(struct platform_device *pdev)
/* Start this loop from the id left from previous loop */
for (; id < PALMAS_NUM_REGS; id++) {
if (pdata && pdata->reg_init[id])
reg_init = pdata->reg_init[id];
else
reg_init = NULL;
/* Miss out regulators which are not available due
* to alternate functions.
......@@ -969,7 +1113,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
if (id < PALMAS_REG_REGEN1) {
pmic->desc[id].n_voltages = PALMAS_LDO_NUM_VOLTAGES;
pmic->desc[id].ops = &palmas_ops_ldo;
if (reg_init && reg_init->roof_floor)
pmic->desc[id].ops =
&palmas_ops_ext_control_ldo;
else
pmic->desc[id].ops = &palmas_ops_ldo;
pmic->desc[id].min_uV = 900000;
pmic->desc[id].uV_step = 50000;
pmic->desc[id].linear_min_sel = 1;
......@@ -999,7 +1147,11 @@ static int palmas_regulators_probe(struct platform_device *pdev)
pmic->desc[id].enable_time = 2000;
} else {
pmic->desc[id].n_voltages = 1;
pmic->desc[id].ops = &palmas_ops_extreg;
if (reg_init && reg_init->roof_floor)
pmic->desc[id].ops =
&palmas_ops_ext_control_extreg;
else
pmic->desc[id].ops = &palmas_ops_extreg;
pmic->desc[id].enable_reg =
PALMAS_BASE_TO_REG(PALMAS_RESOURCE_BASE,
palmas_regs_info[id].ctrl_addr);
......@@ -1015,13 +1167,13 @@ static int palmas_regulators_probe(struct platform_device *pdev)
pmic->desc[id].supply_name = palmas_regs_info[id].sname;
config.of_node = palmas_matches[id].of_node;
rdev = regulator_register(&pmic->desc[id], &config);
rdev = devm_regulator_register(&pdev->dev, &pmic->desc[id],
&config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev,
"failed to register %s regulator\n",
pdev->name);
ret = PTR_ERR(rdev);
goto err_unregister_regulator;
return PTR_ERR(rdev);
}
/* Save regulator for cleanup */
......@@ -1037,31 +1189,14 @@ static int palmas_regulators_probe(struct platform_device *pdev)
else
ret = palmas_extreg_init(palmas,
id, reg_init);
if (ret) {
regulator_unregister(pmic->rdev[id]);
goto err_unregister_regulator;
}
if (ret)
return ret;
}
}
}
return 0;
err_unregister_regulator:
while (--id >= 0)
regulator_unregister(pmic->rdev[id]);
return ret;
}
static int palmas_regulators_remove(struct platform_device *pdev)
{
struct palmas_pmic *pmic = platform_get_drvdata(pdev);
int id;
for (id = 0; id < PALMAS_NUM_REGS; id++)
regulator_unregister(pmic->rdev[id]);
return 0;
}
static struct of_device_id of_palmas_match_tbl[] = {
......@@ -1083,7 +1218,6 @@ static struct platform_driver palmas_driver = {
.owner = THIS_MODULE,
},
.probe = palmas_regulators_probe,
.remove = palmas_regulators_remove,
};
static int __init palmas_init(void)
......
......@@ -246,7 +246,8 @@ static int pcap_regulator_probe(struct platform_device *pdev)
config.init_data = dev_get_platdata(&pdev->dev);
config.driver_data = pcap;
rdev = regulator_register(&pcap_regulators[pdev->id], &config);
rdev = devm_regulator_register(&pdev->dev, &pcap_regulators[pdev->id],
&config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
......@@ -255,22 +256,12 @@ static int pcap_regulator_probe(struct platform_device *pdev)
return 0;
}
static int pcap_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
regulator_unregister(rdev);
return 0;
}
static struct platform_driver pcap_regulator_driver = {
.driver = {
.name = "pcap-regulator",
.owner = THIS_MODULE,
},
.probe = pcap_regulator_probe,
.remove = pcap_regulator_remove,
};
static int __init pcap_regulator_init(void)
......
......@@ -90,7 +90,8 @@ static int pcf50633_regulator_probe(struct platform_device *pdev)
config.driver_data = pcf;
config.regmap = pcf->regmap;
rdev = regulator_register(&regulators[pdev->id], &config);
rdev = devm_regulator_register(&pdev->dev, &regulators[pdev->id],
&config);
if (IS_ERR(rdev))
return PTR_ERR(rdev);
......@@ -102,21 +103,11 @@ static int pcf50633_regulator_probe(struct platform_device *pdev)
return 0;
}
static int pcf50633_regulator_remove(struct platform_device *pdev)
{
struct regulator_dev *rdev = platform_get_drvdata(pdev);
regulator_unregister(rdev);
return 0;
}
static struct platform_driver pcf50633_regulator_driver = {
.driver = {
.name = "pcf50633-regltr",
},
.probe = pcf50633_regulator_probe,
.remove = pcf50633_regulator_remove,
};
static int __init pcf50633_regulator_init(void)
......
......@@ -173,33 +173,16 @@ static int rc5t583_regulator_probe(struct platform_device *pdev)
config.driver_data = reg;
config.regmap = rc5t583->regmap;
rdev = regulator_register(&ri->desc, &config);
rdev = devm_regulator_register(&pdev->dev, &ri->desc, &config);
if (IS_ERR(rdev)) {
dev_err(&pdev->dev, "Failed to register regulator %s\n",
ri->desc.name);
ret = PTR_ERR(rdev);
goto clean_exit;
return PTR_ERR(rdev);
}
reg->rdev = rdev;
}
platform_set_drvdata(pdev, regs);
return 0;
clean_exit:
while (--id >= 0)
regulator_unregister(regs[id].rdev);
return ret;
}
static int rc5t583_regulator_remove(struct platform_device *pdev)
{
struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
int id;
for (id = 0; id < RC5T583_REGULATOR_MAX; ++id)
regulator_unregister(regs[id].rdev);
return 0;
}
static struct platform_driver rc5t583_regulator_driver = {
......@@ -208,7 +191,6 @@ static struct platform_driver rc5t583_regulator_driver = {
.owner = THIS_MODULE,
},
.probe = rc5t583_regulator_probe,
.remove = rc5t583_regulator_remove,
};
static int __init rc5t583_regulator_init(void)
......
......@@ -448,32 +448,16 @@ static int s2mps11_pmic_probe(struct platform_device *pdev)
config.of_node = rdata[i].of_node;
}
s2mps11->rdev[i] = regulator_register(&regulators[i], &config);
s2mps11->rdev[i] = devm_regulator_register(&pdev->dev,
&regulators[i], &config);
if (IS_ERR(s2mps11->rdev[i])) {
ret = PTR_ERR(s2mps11->rdev[i]);
dev_err(&pdev->dev, "regulator init failed for %d\n",
i);
s2mps11->rdev[i] = NULL;
goto err;
return ret;
}
}
return 0;
err:
for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
regulator_unregister(s2mps11->rdev[i]);
return ret;
}
static int s2mps11_pmic_remove(struct platform_device *pdev)
{
struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
int i;
for (i = 0; i < S2MPS11_REGULATOR_MAX; i++)
regulator_unregister(s2mps11->rdev[i]);
return 0;
}
......@@ -489,7 +473,6 @@ static struct platform_driver s2mps11_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = s2mps11_pmic_probe,
.remove = s2mps11_pmic_remove,
.id_table = s2mps11_pmic_id,
};
......
......@@ -522,7 +522,7 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
struct device_node *pmic_np, *regulators_np, *reg_np;
struct sec_regulator_data *rdata;
struct sec_opmode_data *rmode;
unsigned int i, dvs_voltage_nr = 1, ret;
unsigned int i, dvs_voltage_nr = 8, ret;
pmic_np = iodev->dev->of_node;
if (!pmic_np) {
......@@ -586,15 +586,39 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
rmode++;
}
if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL))
if (of_get_property(pmic_np, "s5m8767,pmic-buck2-uses-gpio-dvs", NULL)) {
pdata->buck2_gpiodvs = true;
if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL))
if (of_property_read_u32_array(pmic_np,
"s5m8767,pmic-buck2-dvs-voltage",
pdata->buck2_voltage, dvs_voltage_nr)) {
dev_err(iodev->dev, "buck2 voltages not specified\n");
return -EINVAL;
}
}
if (of_get_property(pmic_np, "s5m8767,pmic-buck3-uses-gpio-dvs", NULL)) {
pdata->buck3_gpiodvs = true;
if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL))
if (of_property_read_u32_array(pmic_np,
"s5m8767,pmic-buck3-dvs-voltage",
pdata->buck3_voltage, dvs_voltage_nr)) {
dev_err(iodev->dev, "buck3 voltages not specified\n");
return -EINVAL;
}
}
if (of_get_property(pmic_np, "s5m8767,pmic-buck4-uses-gpio-dvs", NULL)) {
pdata->buck4_gpiodvs = true;
if (of_property_read_u32_array(pmic_np,
"s5m8767,pmic-buck4-dvs-voltage",
pdata->buck4_voltage, dvs_voltage_nr)) {
dev_err(iodev->dev, "buck4 voltages not specified\n");
return -EINVAL;
}
}
if (pdata->buck2_gpiodvs || pdata->buck3_gpiodvs ||
pdata->buck4_gpiodvs) {
ret = s5m8767_pmic_dt_parse_dvs_gpio(iodev, pdata, pmic_np);
......@@ -612,32 +636,26 @@ static int s5m8767_pmic_dt_parse_pdata(struct platform_device *pdev,
"invalid value for default dvs index, use 0\n");
}
}
dvs_voltage_nr = 8;
}
ret = s5m8767_pmic_dt_parse_ds_gpio(iodev, pdata, pmic_np);
if (ret)
return -EINVAL;
if (of_property_read_u32_array(pmic_np,
"s5m8767,pmic-buck2-dvs-voltage",
pdata->buck2_voltage, dvs_voltage_nr)) {
dev_err(iodev->dev, "buck2 voltages not specified\n");
return -EINVAL;
}
if (of_get_property(pmic_np, "s5m8767,pmic-buck2-ramp-enable", NULL))
pdata->buck2_ramp_enable = true;
if (of_property_read_u32_array(pmic_np,
"s5m8767,pmic-buck3-dvs-voltage",
pdata->buck3_voltage, dvs_voltage_nr)) {
dev_err(iodev->dev, "buck3 voltages not specified\n");
return -EINVAL;
}
if (of_get_property(pmic_np, "s5m8767,pmic-buck3-ramp-enable", NULL))
pdata->buck3_ramp_enable = true;
if (of_property_read_u32_array(pmic_np,
"s5m8767,pmic-buck4-dvs-voltage",
pdata->buck4_voltage, dvs_voltage_nr)) {
dev_err(iodev->dev, "buck4 voltages not specified\n");
return -EINVAL;
if (of_get_property(pmic_np, "s5m8767,pmic-buck4-ramp-enable", NULL))
pdata->buck4_ramp_enable = true;
if (pdata->buck2_ramp_enable || pdata->buck3_ramp_enable
|| pdata->buck4_ramp_enable) {
if (of_property_read_u32(pmic_np, "s5m8767,pmic-buck-ramp-delay",
&pdata->buck_ramp_delay))
pdata->buck_ramp_delay = 0;
}
return 0;
......@@ -910,33 +928,16 @@ static int s5m8767_pmic_probe(struct platform_device *pdev)
config.regmap = iodev->regmap;
config.of_node = pdata->regulators[i].reg_node;
rdev[i] = regulator_register(&regulators[id], &config);
rdev[i] = devm_regulator_register(&pdev->dev, &regulators[id],
&config);
if (IS_ERR(rdev[i])) {
ret = PTR_ERR(rdev[i]);
dev_err(s5m8767->dev, "regulator init failed for %d\n",
id);
rdev[i] = NULL;
goto err;
return ret;
}
}
return 0;
err:
for (i = 0; i < s5m8767->num_regulators; i++)
regulator_unregister(rdev[i]);
return ret;
}
static int s5m8767_pmic_remove(struct platform_device *pdev)
{
struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
struct regulator_dev **rdev = s5m8767->rdev;
int i;
for (i = 0; i < s5m8767->num_regulators; i++)
regulator_unregister(rdev[i]);
return 0;
}
......@@ -952,7 +953,6 @@ static struct platform_driver s5m8767_pmic_driver = {
.owner = THIS_MODULE,
},
.probe = s5m8767_pmic_probe,
.remove = s5m8767_pmic_remove,
.id_table = s5m8767_pmic_id,
};
......
/*
* Regulator driver for STw4810/STw4811 VMMC regulator.
*
* Copyright (C) 2013 ST-Ericsson SA
* Written on behalf of Linaro for ST-Ericsson
*
* Author: Linus Walleij <linus.walleij@linaro.org>
*
* License terms: GNU General Public License (GPL) version 2
*/
#include <linux/err.h>
#include <linux/init.h>
#include <linux/mfd/stw481x.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/regulator/driver.h>
#include <linux/regulator/of_regulator.h>
static const unsigned int stw481x_vmmc_voltages[] = {
1800000,
1800000,
2850000,
3000000,
1850000,
2600000,
2700000,
3300000,
};
static struct regulator_ops stw481x_vmmc_ops = {
.list_voltage = regulator_list_voltage_table,
.enable = regulator_enable_regmap,
.disable = regulator_disable_regmap,
.is_enabled = regulator_is_enabled_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
};
static struct regulator_desc vmmc_regulator = {
.name = "VMMC",
.id = 0,
.ops = &stw481x_vmmc_ops,
.type = REGULATOR_VOLTAGE,
.owner = THIS_MODULE,
.n_voltages = ARRAY_SIZE(stw481x_vmmc_voltages),
.volt_table = stw481x_vmmc_voltages,
.enable_time = 200, /* FIXME: look this up */
.enable_reg = STW_CONF1,
.enable_mask = STW_CONF1_PDN_VMMC,
.vsel_reg = STW_CONF1,
.vsel_mask = STW_CONF1_VMMC_MASK,
};
static int stw481x_vmmc_regulator_probe(struct platform_device *pdev)
{
struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
struct regulator_config config = { };
int ret;
/* First disable the external VMMC if it's active */
ret = regmap_update_bits(stw481x->map, STW_CONF2,
STW_CONF2_VMMC_EXT, 0);
if (ret) {
dev_err(&pdev->dev, "could not disable external VMMC\n");
return ret;
}
/* Register VMMC regulator */
config.dev = &pdev->dev;
config.driver_data = stw481x;
config.regmap = stw481x->map;
config.of_node = pdev->dev.of_node;
config.init_data = of_get_regulator_init_data(&pdev->dev,
pdev->dev.of_node);
stw481x->vmmc_regulator = regulator_register(&vmmc_regulator, &config);
if (IS_ERR(stw481x->vmmc_regulator)) {
dev_err(&pdev->dev,
"error initializing STw481x VMMC regulator\n");
return PTR_ERR(stw481x->vmmc_regulator);
}
dev_info(&pdev->dev, "initialized STw481x VMMC regulator\n");
return 0;
}
static int stw481x_vmmc_regulator_remove(struct platform_device *pdev)
{
struct stw481x *stw481x = dev_get_platdata(&pdev->dev);
regulator_unregister(stw481x->vmmc_regulator);
return 0;
}
static const struct of_device_id stw481x_vmmc_match[] = {
{ .compatible = "st,stw481x-vmmc", },
{},
};
static struct platform_driver stw481x_vmmc_regulator_driver = {
.driver = {
.name = "stw481x-vmmc-regulator",
.owner = THIS_MODULE,
.of_match_table = stw481x_vmmc_match,
},
.probe = stw481x_vmmc_regulator_probe,
.remove = stw481x_vmmc_regulator_remove,
};
module_platform_driver(stw481x_vmmc_regulator_driver);
......@@ -343,7 +343,7 @@ static int tps51632_probe(struct i2c_client *client,
config.regmap = tps->regmap;
config.of_node = client->dev.of_node;
rdev = regulator_register(&tps->desc, &config);
rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
if (IS_ERR(rdev)) {
dev_err(tps->dev, "regulator register failed\n");
return PTR_ERR(rdev);
......@@ -353,14 +353,6 @@ static int tps51632_probe(struct i2c_client *client,
return 0;
}
static int tps51632_remove(struct i2c_client *client)
{
struct tps51632_chip *tps = i2c_get_clientdata(client);
regulator_unregister(tps->rdev);
return 0;
}
static const struct i2c_device_id tps51632_id[] = {
{.name = "tps51632",},
{},
......@@ -375,7 +367,6 @@ static struct i2c_driver tps51632_i2c_driver = {
.of_match_table = of_match_ptr(tps51632_of_match),
},
.probe = tps51632_probe,
.remove = tps51632_remove,
.id_table = tps51632_id,
};
......
......@@ -137,7 +137,7 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
/* This instance is not set for regulator mode so bail out */
if (pdata->mode != TPS6105X_MODE_VOLTAGE) {
dev_info(&pdev->dev,
"chip not in voltage mode mode, exit probe \n");
"chip not in voltage mode mode, exit probe\n");
return 0;
}
......@@ -146,8 +146,9 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
config.driver_data = tps6105x;
/* Register regulator with framework */
tps6105x->regulator = regulator_register(&tps6105x_regulator_desc,
&config);
tps6105x->regulator = devm_regulator_register(&pdev->dev,
&tps6105x_regulator_desc,
&config);
if (IS_ERR(tps6105x->regulator)) {
ret = PTR_ERR(tps6105x->regulator);
dev_err(&tps6105x->client->dev,
......@@ -159,20 +160,12 @@ static int tps6105x_regulator_probe(struct platform_device *pdev)
return 0;
}
static int tps6105x_regulator_remove(struct platform_device *pdev)
{
struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
regulator_unregister(tps6105x->regulator);
return 0;
}
static struct platform_driver tps6105x_regulator_driver = {
.driver = {
.name = "tps6105x-regulator",
.owner = THIS_MODULE,
},
.probe = tps6105x_regulator_probe,
.remove = tps6105x_regulator_remove,
};
static __init int tps6105x_regulator_init(void)
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册