]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge remote-tracking branch 'regulator/for-next'
authorThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:36:58 +0000 (14:36 +0200)
committerThierry Reding <treding@nvidia.com>
Thu, 24 Oct 2013 12:36:58 +0000 (14:36 +0200)
83 files changed:
Documentation/devicetree/bindings/regulator/as3722-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/da9210.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/palmas-pmic.txt
Documentation/devicetree/bindings/regulator/regulator.txt
Documentation/driver-model/devres.txt
arch/arm/mach-s3c64xx/mach-crag6410.c
drivers/mfd/arizona-core.c
drivers/mfd/mfd-core.c
drivers/regulator/88pm800.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500-ext.c
drivers/regulator/ad5398.c
drivers/regulator/anatop-regulator.c
drivers/regulator/arizona-ldo1.c
drivers/regulator/arizona-micsupp.c
drivers/regulator/as3711-regulator.c
drivers/regulator/as3722-regulator.c [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/da9055-regulator.c
drivers/regulator/da9063-regulator.c
drivers/regulator/da9210-regulator.c
drivers/regulator/devres.c [new file with mode: 0644]
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/helpers.c
drivers/regulator/internal.h [new file with mode: 0644]
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp872x.c
drivers/regulator/lp8788-buck.c
drivers/regulator/lp8788-ldo.c
drivers/regulator/max1586.c
drivers/regulator/max77686.c
drivers/regulator/max77693.c
drivers/regulator/max8649.c
drivers/regulator/max8660.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8925-regulator.c
drivers/regulator/max8973-regulator.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/of_regulator.c
drivers/regulator/palmas-regulator.c
drivers/regulator/pcap-regulator.c
drivers/regulator/pcf50633-regulator.c
drivers/regulator/rc5t583-regulator.c
drivers/regulator/s2mps11.c
drivers/regulator/s5m8767.c
drivers/regulator/stw481x-vmmc.c [new file with mode: 0644]
drivers/regulator/ti-abb-regulator.c
drivers/regulator/tps51632-regulator.c
drivers/regulator/tps6105x-regulator.c
drivers/regulator/tps62360-regulator.c
drivers/regulator/tps65023-regulator.c
drivers/regulator/tps6507x-regulator.c
drivers/regulator/tps65090-regulator.c
drivers/regulator/tps65217-regulator.c
drivers/regulator/tps6524x-regulator.c
drivers/regulator/tps6586x-regulator.c
drivers/regulator/tps65910-regulator.c
drivers/regulator/tps65912-regulator.c
drivers/regulator/tps80031-regulator.c
drivers/regulator/twl-regulator.c
drivers/regulator/vexpress.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8350-regulator.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
include/linux/mfd/core.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/machine.h

diff --git a/Documentation/devicetree/bindings/regulator/as3722-regulator.txt b/Documentation/devicetree/bindings/regulator/as3722-regulator.txt
new file mode 100644 (file)
index 0000000..caad0c8
--- /dev/null
@@ -0,0 +1,91 @@
+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;
+                       };
+                       ....
+               };
+       };
diff --git a/Documentation/devicetree/bindings/regulator/da9210.txt b/Documentation/devicetree/bindings/regulator/da9210.txt
new file mode 100644 (file)
index 0000000..f120f22
--- /dev/null
@@ -0,0 +1,21 @@
+* 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;
+       };
index 875639ae0606e1e6637cacd9ef35dfde9ec0399a..42e6b6bc48ff3b5cfe383cf7598ffb42bee5e286 100644 (file)
@@ -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>;
                };
index 2bd8f09787659269bb03847b3517cff2b52cfca9..e2c7f1e7251a3a16c922c50d10f8b8f50ee750cb 100644 (file)
@@ -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
index fcb34a5697eaa4ec2c44a46791b711d5a78f1c7b..3d9c2a766230a5d7d24164675a4bee3b4e67dd67 100644 (file)
@@ -283,6 +283,7 @@ REGULATOR
   devm_regulator_get()
   devm_regulator_put()
   devm_regulator_bulk_get()
+  devm_regulator_register()
 
 CLOCK
   devm_clk_get()
index eb8e5a1aca420005fa5e0988a099e51eb8ec6f94..f27ca3b89f4c4ccca96c707d5bc179f946e63ef9 100644 (file)
@@ -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 = {
index ba808b74423892bcca62881a0a0c1e8aeb002746..75e180ceecf3fac16f9a432ada482130624dfe01 100644 (file)
@@ -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)
index f421586f29fb09b02644ee8b05aa6777fb353835..adc8ea36e7c483e5f9ee05e1587d3fd1b6029719 100644 (file)
@@ -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:
index 3459f60dcfd1c7dfc67aa641edd49f697ffb8b94..d333f7eac106f1ae9cab88f0850f2fc4ca03c19f 100644 (file)
@@ -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[] = {
index 70230974468cb97ae9c76fe9fdb69ebc04e13560..f704d83c93c4a95fc729cc48c510611d4b5cd33f 100644 (file)
@@ -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,
 };
 
index dfe58096b374a22fbeb001a1f430cb6afb2d1461..ce785f481281d2532dca6514e07a304ccfcb7b04 100644 (file)
@@ -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
index 185cce246022d25f510ae5bd247a81acf3605882..01c597ea17441353dfbeded58ac2db4da7810bc8 100644 (file)
@@ -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
index 881159dfcb5e70fc3532d7a9ccc20cad99354459..f70a9bfa5ff2e9b4845d9493e3cbda9cb012e042 100644 (file)
@@ -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)
index 7d5eaa874b2da9337e387b1271bd2e38a3d25d2e..77b46d0b37a604fa31f7b90fb270d8ac59023e0c 100644 (file)
@@ -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;
index 02ff691cdb8b291b44ecc1569339a9251aa59987..29c0faaf8eba4e94f34d8848d91b7d0d85dea2ec 100644 (file)
@@ -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,
index b2b203cb6b2f9373a0d09f5773f3d912922614dd..48016a050d5fb9b9c19981075755bd3831be0652 100644 (file)
@@ -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",
        },
index 0d4a8ccbb53616275bda7d8f4ca817d8d68ad104..c734d098082641a814488a67c505b15d912958d7 100644 (file)
@@ -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");
index 81d8681c31959557fa78a7121d64e85c957e719b..4f6c2055f6b210436a5c1a9565b9f302ecdd21da 100644 (file)
@@ -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,
index e87536bf0bed038f09af9bc251c85d0b00fb6c97..724706a97dc40c5cf7e21d89f7c58bc2385f6226 100644 (file)
@@ -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,
index 8406cd745da29e6a60a76624d1199516d7d46121..c77a58478cca6b11ffd2c5a69990eddda1900230 100644 (file)
@@ -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)
diff --git a/drivers/regulator/as3722-regulator.c b/drivers/regulator/as3722-regulator.c
new file mode 100644 (file)
index 0000000..5917fe3
--- /dev/null
@@ -0,0 +1,908 @@
+/*
+ * Voltage regulator support for AMS AS3722 PMIC
+ *
+ * Copyright (C) 2013 ams
+ *
+ * Author: Florian Lobmaier <florian.lobmaier@ams.com>
+ * Author: Laxman Dewangan <ldewangan@nvidia.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
+ *
+ */
+
+#include <linux/err.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/mfd/as3722.h>
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/slab.h>
+
+/* Regulator IDs */
+enum as3722_regulators_id {
+       AS3722_REGULATOR_ID_SD0,
+       AS3722_REGULATOR_ID_SD1,
+       AS3722_REGULATOR_ID_SD2,
+       AS3722_REGULATOR_ID_SD3,
+       AS3722_REGULATOR_ID_SD4,
+       AS3722_REGULATOR_ID_SD5,
+       AS3722_REGULATOR_ID_SD6,
+       AS3722_REGULATOR_ID_LDO0,
+       AS3722_REGULATOR_ID_LDO1,
+       AS3722_REGULATOR_ID_LDO2,
+       AS3722_REGULATOR_ID_LDO3,
+       AS3722_REGULATOR_ID_LDO4,
+       AS3722_REGULATOR_ID_LDO5,
+       AS3722_REGULATOR_ID_LDO6,
+       AS3722_REGULATOR_ID_LDO7,
+       AS3722_REGULATOR_ID_LDO9,
+       AS3722_REGULATOR_ID_LDO10,
+       AS3722_REGULATOR_ID_LDO11,
+       AS3722_REGULATOR_ID_MAX,
+};
+
+struct as3722_register_mapping {
+       u8 regulator_id;
+       const char *name;
+       const char *sname;
+       u8 vsel_reg;
+       u8 vsel_mask;
+       int n_voltages;
+       u32 enable_reg;
+       u8 enable_mask;
+       u32 control_reg;
+       u8 mode_mask;
+       u32 sleep_ctrl_reg;
+       u8 sleep_ctrl_mask;
+};
+
+struct as3722_regulator_config_data {
+       struct regulator_init_data *reg_init;
+       bool enable_tracking;
+       int ext_control;
+};
+
+struct as3722_regulators {
+       struct device *dev;
+       struct as3722 *as3722;
+       struct regulator_dev *rdevs[AS3722_REGULATOR_ID_MAX];
+       struct regulator_desc desc[AS3722_REGULATOR_ID_MAX];
+       struct as3722_regulator_config_data
+                       reg_config_data[AS3722_REGULATOR_ID_MAX];
+};
+
+static const struct as3722_register_mapping as3722_reg_lookup[] = {
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD0,
+               .name = "as3722-sd0",
+               .vsel_reg = AS3722_SD0_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(0),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD0_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD0_CONTROL_REG,
+               .mode_mask = AS3722_SD0_MODE_FAST,
+               .n_voltages = AS3722_SD0_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD1,
+               .name = "as3722-sd1",
+               .vsel_reg = AS3722_SD1_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(1),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD1_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD1_CONTROL_REG,
+               .mode_mask = AS3722_SD1_MODE_FAST,
+               .n_voltages = AS3722_SD0_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD2,
+               .name = "as3722-sd2",
+               .sname = "vsup-sd2",
+               .vsel_reg = AS3722_SD2_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(2),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD2_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD23_CONTROL_REG,
+               .mode_mask = AS3722_SD2_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD3,
+               .name = "as3722-sd3",
+               .sname = "vsup-sd3",
+               .vsel_reg = AS3722_SD3_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(3),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL1_REG,
+               .sleep_ctrl_mask = AS3722_SD3_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD23_CONTROL_REG,
+               .mode_mask = AS3722_SD3_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD4,
+               .name = "as3722-sd4",
+               .sname = "vsup-sd4",
+               .vsel_reg = AS3722_SD4_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(4),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+               .sleep_ctrl_mask = AS3722_SD4_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD4_CONTROL_REG,
+               .mode_mask = AS3722_SD4_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD5,
+               .name = "as3722-sd5",
+               .sname = "vsup-sd5",
+               .vsel_reg = AS3722_SD5_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(5),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+               .sleep_ctrl_mask = AS3722_SD5_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD5_CONTROL_REG,
+               .mode_mask = AS3722_SD5_MODE_FAST,
+               .n_voltages = AS3722_SD2_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_SD6,
+               .name = "as3722-sd6",
+               .vsel_reg = AS3722_SD6_VOLTAGE_REG,
+               .vsel_mask = AS3722_SD_VSEL_MASK,
+               .enable_reg = AS3722_SD_CONTROL_REG,
+               .enable_mask = AS3722_SDn_CTRL(6),
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL2_REG,
+               .sleep_ctrl_mask = AS3722_SD6_EXT_ENABLE_MASK,
+               .control_reg = AS3722_SD6_CONTROL_REG,
+               .mode_mask = AS3722_SD6_MODE_FAST,
+               .n_voltages = AS3722_SD0_VSEL_MAX + 1,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO0,
+               .name = "as3722-ldo0",
+               .sname = "vin-ldo0",
+               .vsel_reg = AS3722_LDO0_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO0_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO0_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO0_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO0_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO1,
+               .name = "as3722-ldo1",
+               .sname = "vin-ldo1-6",
+               .vsel_reg = AS3722_LDO1_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO1_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO1_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO2,
+               .name = "as3722-ldo2",
+               .sname = "vin-ldo2-5-7",
+               .vsel_reg = AS3722_LDO2_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO2_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO2_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO3,
+               .name = "as3722-ldo3",
+               .name = "vin-ldo3-4",
+               .vsel_reg = AS3722_LDO3_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO3_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO3_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL3_REG,
+               .sleep_ctrl_mask = AS3722_LDO3_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO3_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO4,
+               .name = "as3722-ldo4",
+               .name = "vin-ldo3-4",
+               .vsel_reg = AS3722_LDO4_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO4_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO4_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO5,
+               .name = "as3722-ldo5",
+               .sname = "vin-ldo2-5-7",
+               .vsel_reg = AS3722_LDO5_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO5_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO5_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO6,
+               .name = "as3722-ldo6",
+               .sname = "vin-ldo1-6",
+               .vsel_reg = AS3722_LDO6_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO6_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO6_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO7,
+               .name = "as3722-ldo7",
+               .sname = "vin-ldo2-5-7",
+               .vsel_reg = AS3722_LDO7_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL0_REG,
+               .enable_mask = AS3722_LDO7_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL4_REG,
+               .sleep_ctrl_mask = AS3722_LDO7_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO9,
+               .name = "as3722-ldo9",
+               .sname = "vin-ldo9-10",
+               .vsel_reg = AS3722_LDO9_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL1_REG,
+               .enable_mask = AS3722_LDO9_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+               .sleep_ctrl_mask = AS3722_LDO9_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO10,
+               .name = "as3722-ldo10",
+               .sname = "vin-ldo9-10",
+               .vsel_reg = AS3722_LDO10_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL1_REG,
+               .enable_mask = AS3722_LDO10_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+               .sleep_ctrl_mask = AS3722_LDO10_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+       {
+               .regulator_id = AS3722_REGULATOR_ID_LDO11,
+               .name = "as3722-ldo11",
+               .sname = "vin-ldo11",
+               .vsel_reg = AS3722_LDO11_VOLTAGE_REG,
+               .vsel_mask = AS3722_LDO_VSEL_MASK,
+               .enable_reg = AS3722_LDOCONTROL1_REG,
+               .enable_mask = AS3722_LDO11_CTRL,
+               .sleep_ctrl_reg = AS3722_ENABLE_CTRL5_REG,
+               .sleep_ctrl_mask = AS3722_LDO11_EXT_ENABLE_MASK,
+               .n_voltages = AS3722_LDO_NUM_VOLT,
+       },
+};
+
+
+static const int as3722_ldo_current[] = { 150000, 300000 };
+static const int as3722_sd016_current[] = { 2500000, 3000000, 3500000 };
+
+static int as3722_current_to_index(int min_uA, int max_uA,
+               const int *curr_table, int n_currents)
+{
+       int i;
+
+       for (i = n_currents - 1; i >= 0; i--) {
+               if ((min_uA <= curr_table[i]) && (curr_table[i] <= max_uA))
+                       return i;
+       }
+       return -EINVAL;
+}
+
+static int as3722_ldo_get_current_limit(struct regulator_dev *rdev)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       u32 val;
+       int ret;
+
+       ret = as3722_read(as3722, as3722_reg_lookup[id].vsel_reg, &val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+                       as3722_reg_lookup[id].vsel_reg, ret);
+               return ret;
+       }
+       if (val & AS3722_LDO_ILIMIT_MASK)
+               return 300000;
+       return 150000;
+}
+
+static int as3722_ldo_set_current_limit(struct regulator_dev *rdev,
+               int min_uA, int max_uA)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       int ret;
+       u32 reg = 0;
+
+       ret = as3722_current_to_index(min_uA, max_uA, as3722_ldo_current,
+                               ARRAY_SIZE(as3722_ldo_current));
+       if (ret < 0) {
+               dev_err(as3722_regs->dev,
+                       "Current range min:max = %d:%d does not support\n",
+                       min_uA, max_uA);
+               return ret;
+       }
+       if (ret)
+               reg = AS3722_LDO_ILIMIT_BIT;
+       return as3722_update_bits(as3722, as3722_reg_lookup[id].vsel_reg,
+                       AS3722_LDO_ILIMIT_MASK, reg);
+}
+
+static struct regulator_ops as3722_ldo0_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo0_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static int as3722_ldo3_set_tracking_mode(struct as3722_regulators *as3722_reg,
+               int id, u8 mode)
+{
+       struct as3722 *as3722 = as3722_reg->as3722;
+
+       switch (mode) {
+       case AS3722_LDO3_MODE_PMOS:
+       case AS3722_LDO3_MODE_PMOS_TRACKING:
+       case AS3722_LDO3_MODE_NMOS:
+       case AS3722_LDO3_MODE_SWITCH:
+               return as3722_update_bits(as3722,
+                       as3722_reg_lookup[id].vsel_reg,
+                       AS3722_LDO3_MODE_MASK, mode);
+
+       default:
+               return -EINVAL;
+       }
+}
+
+static int as3722_ldo3_get_current_limit(struct regulator_dev *rdev)
+{
+       return 150000;
+}
+
+static struct regulator_ops as3722_ldo3_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+static struct regulator_ops as3722_ldo3_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_ldo3_get_current_limit,
+};
+
+static const struct regulator_linear_range as3722_ldo_ranges[] = {
+       REGULATOR_LINEAR_RANGE(825000, 0x01, 0x24, 25000),
+       REGULATOR_LINEAR_RANGE(1725000, 0x40, 0x7F, 25000),
+};
+
+static struct regulator_ops as3722_ldo_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static struct regulator_ops as3722_ldo_extcntrl_ops = {
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .get_current_limit = as3722_ldo_get_current_limit,
+       .set_current_limit = as3722_ldo_set_current_limit,
+};
+
+static unsigned int as3722_sd_get_mode(struct regulator_dev *rdev)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       u32 val;
+       int ret;
+
+       if (!as3722_reg_lookup[id].control_reg)
+               return -ENOTSUPP;
+
+       ret = as3722_read(as3722, as3722_reg_lookup[id].control_reg, &val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+                       as3722_reg_lookup[id].control_reg, ret);
+               return ret;
+       }
+
+       if (val & as3722_reg_lookup[id].mode_mask)
+               return REGULATOR_MODE_FAST;
+       else
+               return REGULATOR_MODE_NORMAL;
+}
+
+static int as3722_sd_set_mode(struct regulator_dev *rdev,
+               unsigned int mode)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       u8 id = rdev_get_id(rdev);
+       u8 val = 0;
+       int ret;
+
+       if (!as3722_reg_lookup[id].control_reg)
+               return -ERANGE;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = as3722_reg_lookup[id].mode_mask;
+       case REGULATOR_MODE_NORMAL: /* fall down */
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       ret = as3722_update_bits(as3722, as3722_reg_lookup[id].control_reg,
+                       as3722_reg_lookup[id].mode_mask, val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+                       as3722_reg_lookup[id].control_reg, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int as3722_sd016_get_current_limit(struct regulator_dev *rdev)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       u32 val, reg;
+       int mask;
+       int ret;
+
+       switch (id) {
+       case AS3722_REGULATOR_ID_SD0:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD1:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD6:
+               reg = AS3722_OVCURRENT_DEB_REG;
+               mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+               break;
+       default:
+               return -EINVAL;
+       }
+       ret = as3722_read(as3722, reg, &val);
+       if (ret < 0) {
+               dev_err(as3722_regs->dev, "Reg 0x%02x read failed: %d\n",
+                       reg, ret);
+               return ret;
+       }
+       val &= mask;
+       val >>= ffs(mask) - 1;
+       if (val == 3)
+               return -EINVAL;
+       return as3722_sd016_current[val];
+}
+
+static int as3722_sd016_set_current_limit(struct regulator_dev *rdev,
+               int min_uA, int max_uA)
+{
+       struct as3722_regulators *as3722_regs = rdev_get_drvdata(rdev);
+       struct as3722 *as3722 = as3722_regs->as3722;
+       int id = rdev_get_id(rdev);
+       int ret;
+       int val;
+       int mask;
+       u32 reg;
+
+       ret = as3722_current_to_index(min_uA, max_uA, as3722_sd016_current,
+                               ARRAY_SIZE(as3722_sd016_current));
+       if (ret < 0) {
+               dev_err(as3722_regs->dev,
+                       "Current range min:max = %d:%d does not support\n",
+                       min_uA, max_uA);
+               return ret;
+       }
+
+       switch (id) {
+       case AS3722_REGULATOR_ID_SD0:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD0_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD1:
+               reg = AS3722_OVCURRENT_REG;
+               mask = AS3722_OVCURRENT_SD1_TRIP_MASK;
+               break;
+       case AS3722_REGULATOR_ID_SD6:
+               reg = AS3722_OVCURRENT_DEB_REG;
+               mask = AS3722_OVCURRENT_SD6_TRIP_MASK;
+               break;
+       default:
+               return -EINVAL;
+       }
+       val = ret & mask;
+       val <<= ffs(mask) - 1;
+       return as3722_update_bits(as3722, reg, mask, val);
+}
+
+static const struct regulator_linear_range as3722_sd2345_ranges[] = {
+       REGULATOR_LINEAR_RANGE(612500, 0x01, 0x40, 12500),
+       REGULATOR_LINEAR_RANGE(1425000, 0x41, 0x70, 25000),
+       REGULATOR_LINEAR_RANGE(2650000, 0x71, 0x7F, 50000),
+};
+
+static struct regulator_ops as3722_sd016_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_sd016_get_current_limit,
+       .set_current_limit = as3722_sd016_set_current_limit,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd016_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear,
+       .map_voltage = regulator_map_voltage_linear,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_current_limit = as3722_sd016_get_current_limit,
+       .set_current_limit = as3722_sd016_set_current_limit,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_ops = {
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+       .list_voltage = regulator_list_voltage_linear_range,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static struct regulator_ops as3722_sd2345_extcntrl_ops = {
+       .list_voltage = regulator_list_voltage_linear_range,
+       .map_voltage = regulator_map_voltage_linear_range,
+       .set_voltage_sel = regulator_set_voltage_sel_regmap,
+       .get_voltage_sel = regulator_get_voltage_sel_regmap,
+       .get_mode = as3722_sd_get_mode,
+       .set_mode = as3722_sd_set_mode,
+};
+
+static int as3722_extreg_init(struct as3722_regulators *as3722_regs, int id,
+               int ext_pwr_ctrl)
+{
+       int ret;
+       unsigned int val;
+
+       if ((ext_pwr_ctrl < AS3722_EXT_CONTROL_ENABLE1) ||
+               (ext_pwr_ctrl > AS3722_EXT_CONTROL_ENABLE3))
+               return -EINVAL;
+
+       val =  ext_pwr_ctrl << (ffs(as3722_reg_lookup[id].sleep_ctrl_mask) - 1);
+       ret = as3722_update_bits(as3722_regs->as3722,
+                       as3722_reg_lookup[id].sleep_ctrl_reg,
+                       as3722_reg_lookup[id].sleep_ctrl_mask, val);
+       if (ret < 0)
+               dev_err(as3722_regs->dev, "Reg 0x%02x update failed: %d\n",
+                       as3722_reg_lookup[id].sleep_ctrl_reg, ret);
+       return ret;
+}
+
+static struct of_regulator_match as3722_regulator_matches[] = {
+       { .name = "sd0", },
+       { .name = "sd1", },
+       { .name = "sd2", },
+       { .name = "sd3", },
+       { .name = "sd4", },
+       { .name = "sd5", },
+       { .name = "sd6", },
+       { .name = "ldo0", },
+       { .name = "ldo1", },
+       { .name = "ldo2", },
+       { .name = "ldo3", },
+       { .name = "ldo4", },
+       { .name = "ldo5", },
+       { .name = "ldo6", },
+       { .name = "ldo7", },
+       { .name = "ldo9", },
+       { .name = "ldo10", },
+       { .name = "ldo11", },
+};
+
+static int as3722_get_regulator_dt_data(struct platform_device *pdev,
+               struct as3722_regulators *as3722_regs)
+{
+       struct device_node *np;
+       struct as3722_regulator_config_data *reg_config;
+       u32 prop;
+       int id;
+       int ret;
+
+       np = of_get_child_by_name(pdev->dev.parent->of_node, "regulators");
+       if (!np) {
+               dev_err(&pdev->dev, "Device is not having regulators node\n");
+               return -ENODEV;
+       }
+       pdev->dev.of_node = np;
+
+       ret = of_regulator_match(&pdev->dev, np, as3722_regulator_matches,
+                       ARRAY_SIZE(as3722_regulator_matches));
+       if (ret < 0) {
+               dev_err(&pdev->dev, "Parsing of regulator node failed: %d\n",
+                       ret);
+               return ret;
+       }
+
+       for (id = 0; id < ARRAY_SIZE(as3722_regulator_matches); ++id) {
+               struct device_node *reg_node;
+
+               reg_config = &as3722_regs->reg_config_data[id];
+               reg_config->reg_init = as3722_regulator_matches[id].init_data;
+               reg_node = as3722_regulator_matches[id].of_node;
+
+               if (!reg_config->reg_init || !reg_node)
+                       continue;
+
+               ret = of_property_read_u32(reg_node, "ams,ext-control", &prop);
+               if (!ret) {
+                       if (prop < 3)
+                               reg_config->ext_control = prop;
+                       else
+                               dev_warn(&pdev->dev,
+                                       "ext-control have invalid option: %u\n",
+                                       prop);
+               }
+               reg_config->enable_tracking =
+                       of_property_read_bool(reg_node, "ams,enable-tracking");
+       }
+       return 0;
+}
+
+static int as3722_regulator_probe(struct platform_device *pdev)
+{
+       struct as3722 *as3722 = dev_get_drvdata(pdev->dev.parent);
+       struct as3722_regulators *as3722_regs;
+       struct as3722_regulator_config_data *reg_config;
+       struct regulator_dev *rdev;
+       struct regulator_config config = { };
+       struct regulator_ops *ops;
+       int id;
+       int ret;
+
+       as3722_regs = devm_kzalloc(&pdev->dev, sizeof(*as3722_regs),
+                               GFP_KERNEL);
+       if (!as3722_regs)
+               return -ENOMEM;
+
+       as3722_regs->dev = &pdev->dev;
+       as3722_regs->as3722 = as3722;
+       platform_set_drvdata(pdev, as3722_regs);
+
+       ret = as3722_get_regulator_dt_data(pdev, as3722_regs);
+       if (ret < 0)
+               return ret;
+
+       config.dev = &pdev->dev;
+       config.driver_data = as3722_regs;
+       config.regmap = as3722->regmap;
+
+       for (id = 0; id < AS3722_REGULATOR_ID_MAX; id++) {
+               reg_config = &as3722_regs->reg_config_data[id];
+
+               as3722_regs->desc[id].name = as3722_reg_lookup[id].name;
+               as3722_regs->desc[id].supply_name = as3722_reg_lookup[id].sname;
+               as3722_regs->desc[id].id = as3722_reg_lookup[id].regulator_id;
+               as3722_regs->desc[id].n_voltages =
+                                       as3722_reg_lookup[id].n_voltages;
+               as3722_regs->desc[id].type = REGULATOR_VOLTAGE;
+               as3722_regs->desc[id].owner = THIS_MODULE;
+               as3722_regs->desc[id].enable_reg =
+                                       as3722_reg_lookup[id].enable_reg;
+               as3722_regs->desc[id].enable_mask =
+                                       as3722_reg_lookup[id].enable_mask;
+               as3722_regs->desc[id].vsel_reg = as3722_reg_lookup[id].vsel_reg;
+               as3722_regs->desc[id].vsel_mask =
+                                       as3722_reg_lookup[id].vsel_mask;
+               switch (id) {
+               case AS3722_REGULATOR_ID_LDO0:
+                       if (reg_config->ext_control)
+                               ops = &as3722_ldo0_extcntrl_ops;
+                       else
+                               ops = &as3722_ldo0_ops;
+                       as3722_regs->desc[id].min_uV = 825000;
+                       as3722_regs->desc[id].uV_step = 25000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       as3722_regs->desc[id].enable_time = 500;
+                       break;
+               case AS3722_REGULATOR_ID_LDO3:
+                       if (reg_config->ext_control)
+                               ops = &as3722_ldo3_extcntrl_ops;
+                       else
+                               ops = &as3722_ldo3_ops;
+                       as3722_regs->desc[id].min_uV = 620000;
+                       as3722_regs->desc[id].uV_step = 20000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       as3722_regs->desc[id].enable_time = 500;
+                       if (reg_config->enable_tracking) {
+                               ret = as3722_ldo3_set_tracking_mode(as3722_regs,
+                                       id, AS3722_LDO3_MODE_PMOS_TRACKING);
+                               if (ret < 0) {
+                                       dev_err(&pdev->dev,
+                                               "LDO3 tracking failed: %d\n",
+                                               ret);
+                                       return ret;
+                               }
+                       }
+                       break;
+               case AS3722_REGULATOR_ID_SD0:
+               case AS3722_REGULATOR_ID_SD1:
+               case AS3722_REGULATOR_ID_SD6:
+                       if (reg_config->ext_control)
+                               ops = &as3722_sd016_extcntrl_ops;
+                       else
+                               ops = &as3722_sd016_ops;
+                       as3722_regs->desc[id].min_uV = 610000;
+                       as3722_regs->desc[id].uV_step = 10000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       break;
+               case AS3722_REGULATOR_ID_SD2:
+               case AS3722_REGULATOR_ID_SD3:
+               case AS3722_REGULATOR_ID_SD4:
+               case AS3722_REGULATOR_ID_SD5:
+                       if (reg_config->ext_control)
+                               ops = &as3722_sd2345_extcntrl_ops;
+                       else
+                               ops = &as3722_sd2345_ops;
+                       as3722_regs->desc[id].linear_ranges =
+                                               as3722_sd2345_ranges;
+                       as3722_regs->desc[id].n_linear_ranges =
+                                       ARRAY_SIZE(as3722_sd2345_ranges);
+                       break;
+               default:
+                       if (reg_config->ext_control)
+                               ops = &as3722_ldo_extcntrl_ops;
+                       else
+                               ops = &as3722_ldo_ops;
+                       as3722_regs->desc[id].min_uV = 825000;
+                       as3722_regs->desc[id].uV_step = 25000;
+                       as3722_regs->desc[id].linear_min_sel = 1;
+                       as3722_regs->desc[id].enable_time = 500;
+                       as3722_regs->desc[id].linear_ranges = as3722_ldo_ranges;
+                       as3722_regs->desc[id].n_linear_ranges =
+                                               ARRAY_SIZE(as3722_ldo_ranges);
+                       break;
+               }
+               as3722_regs->desc[id].ops = ops;
+               config.init_data = reg_config->reg_init;
+               config.of_node = as3722_regulator_matches[id].of_node;
+               rdev = devm_regulator_register(&pdev->dev,
+                                       &as3722_regs->desc[id], &config);
+               if (IS_ERR(rdev)) {
+                       ret = PTR_ERR(rdev);
+                       dev_err(&pdev->dev, "regulator %d register failed %d\n",
+                               id, ret);
+                       return ret;
+               }
+
+               as3722_regs->rdevs[id] = rdev;
+               if (reg_config->ext_control) {
+                       ret = regulator_enable_regmap(rdev);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "Regulator %d enable failed: %d\n",
+                                       id, ret);
+                               return ret;
+                       }
+                       ret = as3722_extreg_init(as3722_regs, id,
+                                       reg_config->ext_control);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "AS3722 ext control failed: %d", ret);
+                               return ret;
+                       }
+               }
+       }
+       return 0;
+}
+
+static const struct of_device_id of_as3722_regulator_match[] = {
+       { .compatible = "ams,as3722-regulator", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_as3722_regulator_match);
+
+static struct platform_driver as3722_regulator_driver = {
+       .driver = {
+               .name = "as3722-regulator",
+               .owner = THIS_MODULE,
+               .of_match_table = of_as3722_regulator_match,
+       },
+       .probe = as3722_regulator_probe,
+};
+
+module_platform_driver(as3722_regulator_driver);
+
+MODULE_ALIAS("platform:as3722-regulator");
+MODULE_DESCRIPTION("AS3722 regulator driver");
+MODULE_AUTHOR("Florian Lobmaier <florian.lobmaier@ams.com>");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL");
index a01b8b3b70ca2fc3adb4e81d7f96358282115ba4..6382f0af353bc257e3ee6c3b545f75c0c1f2904e 100644 (file)
@@ -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 @@ overflow_err:
 
 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 @@ out:
  */
 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 @@ err:
 }
 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
index f06854cf8cf50739866386538668f4eb5acbc34a..b431ae357fcd310e062bcb3fdb0ffd864b2f0603 100644 (file)
@@ -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)
index 1e4d483f616373a6fb19b339ce6325be7c8a3b33..c427e42472e8d544ce11e0decc871b38405e8a06 100644 (file)
@@ -389,8 +389,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 +403,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,
index 77b53e5a231cabda9eaa915efa718ad9ce5e18f5..7f340206d329d452710a319deba4869a2d6c603b 100644 (file)
@@ -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,
index b9f2653e4ef90f315de25752fe24821a98497848..56727eb745df69171d77fac8313e6ea3ab2499ef 100644 (file)
@@ -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;
 }
 
index f0fe54b3897736327250d6dfe7a664369273df81..6f5ecbe1132e7da4f02496672578ef2301285767 100644 (file)
@@ -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,
 };
 
diff --git a/drivers/regulator/devres.c b/drivers/regulator/devres.c
new file mode 100644 (file)
index 0000000..f44818b
--- /dev/null
@@ -0,0 +1,415 @@
+/*
+ * 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);
index 70b7220c587faccd1e41548f6d5e9343b0233838..7ca3d9e3b0fe22e426fb5419d76b9a4089224c7f 100644 (file)
@@ -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,
 };
 
index 7610920014d789925368fd4316d35c1104fbf9ac..5ea64b94341c5f7a926b07d83536c9d4fe0dba32 100644 (file)
@@ -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;
 
index 98a98ffa7fe07d2bcb23f2c9cad593b416aaf203..04406a918c041b5773adcf9adf331eadf289caf4 100644 (file)
@@ -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;
index 6e30df14714bf15b944740c371d751413421ed3c..e221a271ba56601d12f5fc3d14a09db967a7d292 100644 (file)
@@ -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)
diff --git a/drivers/regulator/internal.h b/drivers/regulator/internal.h
new file mode 100644 (file)
index 0000000..84bbda1
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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
index 88c1a3acf563ebad5aa6301636961eda75528365..6e5da95fa025d4df8c8f3821230ec491be64bd22 100644 (file)
@@ -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,
 };
 
index 5a4604ee5ea593d33fa0e3412b36ff9baf6bae40..947c05ffe0ab9887899a871a1576936b01b8ba3a 100644 (file)
@@ -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);
 
index 2b84b727a3c498c6e22f97fe9d297d06ee1470c8..2e4734ff79fce29eaa2cab621b2e13cfa565a0da 100644 (file)
@@ -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 @@ err_dev:
        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,
 };
 
index 0b015f2a7fd9e3dd33c0928421f55441b1459467..948afc249e296005207c621d3d3bfbfb39b914e2 100644 (file)
@@ -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,
index 0527d87c6dd5adea8c7614ecc61f44fc8599f5f6..b9a29a29933fb8658e3a53202ceafcd41ae27c73 100644 (file)
@@ -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,
index 3a599ee0a456000b5058771e5a8325d76afca521..e242dd316d363bb7f4226f2abfdee051c4d095d3 100644 (file)
@@ -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,
index f563057e56904c868a5344a43e80e41e97ced60d..ae001ccf26f42d952bec37c2a821c250e2307b3c 100644 (file)
@@ -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,
 };
 
index ce4b96c15ebaaf37cb26daa2d4a51df68d1e31e3..feb20bf4ccab4b056003896773ae86dec5c7219e 100644 (file)
@@ -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,
 };
 
index 19c6f08eafd5bddfe5a626696bafcea8bf5f36ec..7f049c92ee52406bbbc7bd3e08573bdd89f25159 100644 (file)
@@ -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",
        },
index 144bcacd734dbe39e44801e411990e15a45d18eb..8d94d3d7f97f22336fb973d5659ed50b4a3e6a97 100644 (file)
@@ -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,
index 4568c15fa78dea0eafda170f64f9fc86db251faa..0c5fe6c6ac26eb22ba248c3b64bbe9c98129283b 100644 (file)
@@ -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)
index d80b5fa758ae5012585acb0a2e2b2947005177ce..759510789e71db39b0b287f9849cea88827d50c4 100644 (file)
@@ -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)
index 5b77ab7762e43c6915dc039e4f7a935a0a4d1adf..892aa1e5b96c65dc2d879be20b3bb97b290af67a 100644 (file)
@@ -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,
 };
 
index df20069f05375ae3bb7661f029119496fe7d8b21..2d618fc9c1af51da55ebce43be2e7c62db8c3eab 100644 (file)
@@ -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,
 };
 
index a4c53b2d1aaf5210482976fd97504485e90fd247..ae3f0656feb00c406ca438642c051a6453ab9171 100644 (file)
@@ -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,
 };
 
index 5ff99d2703db0db55e947be9cf88a6fca46c53cc..7f4a67edf780ed5ab8e007996fe3bcdfc51db2d8 100644 (file)
@@ -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,
 };
 
index 1037e07937cfba7080de781a0db63b42cb6db679..96c9f80d9550b28ceafdab692fe996588c6dd180 100644 (file)
@@ -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,
 };
 
index 7827384680d64a7f62b5e248d687953e5ca8ae7b..ea4f36f2cbe2f1e5432e594711fdb5d4c2c677c6 100644 (file)
@@ -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;
 }
 
 /**
index 7e2b165972e6edd6e3eee6b26478cb263db5d048..9c62b1d34685815c30be33d3157faa0b063d0c4d 100644 (file)
@@ -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)
index b49eaeedea849f5c380059417050bd9d75f2901e..3727b7d0e9ac3c1f633f801f715fdb1520d01fe8 100644 (file)
@@ -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)
index 0f3576d48abf9733cb87a27231f471ca263cade9..d7da1c15a6da447d699e080a4bfda259f734c5f0 100644 (file)
@@ -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)
index 5885b450459697bce78d8fd27b00c3e9468c79de..b58affb33143903d9044a8de2a614a8f20ee0e5f 100644 (file)
@@ -173,33 +173,16 @@ skip_ext_pwr_config:
                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)
index 5eba2ff8c0e86eff58bf5c48e77e4ad352f8b00a..333677d68d0ee31f784e76906bc930b592fc7257 100644 (file)
@@ -448,32 +448,16 @@ common_reg:
                        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,
 };
 
index c24448bc43cfb71658d88afea9779e2b47471495..2297fdf9ba7e6353fac764efe32c56c48c68ea8a 100644 (file)
@@ -910,33 +910,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 +935,6 @@ static struct platform_driver s5m8767_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s5m8767_pmic_probe,
-       .remove = s5m8767_pmic_remove,
        .id_table = s5m8767_pmic_id,
 };
 
diff --git a/drivers/regulator/stw481x-vmmc.c b/drivers/regulator/stw481x-vmmc.c
new file mode 100644 (file)
index 0000000..f78857b
--- /dev/null
@@ -0,0 +1,111 @@
+/*
+ * 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);
index 20c271d49dcbbd358e03d5140d05e9da4ca54952..b187b6bba7ad485a9a8d97ba248b0a70de89c5c8 100644 (file)
@@ -615,7 +615,7 @@ static int ti_abb_init_table(struct device *dev, struct ti_abb *abb,
                                        pname, *volt_table, vset_mask);
                        continue;
                }
-               info->vset = efuse_val & vset_mask >> __ffs(vset_mask);
+               info->vset = (efuse_val & vset_mask) >> __ffs(vset_mask);
                dev_dbg(dev, "[%d]v=%d vset=%x\n", i, *volt_table, info->vset);
 check_abb:
                switch (info->opp_sel) {
@@ -708,39 +708,31 @@ static int ti_abb_probe(struct platform_device *pdev)
        match = of_match_device(ti_abb_of_match, dev);
        if (!match) {
                /* We do not expect this to happen */
-               ret = -ENODEV;
                dev_err(dev, "%s: Unable to match device\n", __func__);
-               goto err;
+               return -ENODEV;
        }
        if (!match->data) {
-               ret = -EINVAL;
                dev_err(dev, "%s: Bad data in match\n", __func__);
-               goto err;
+               return -EINVAL;
        }
 
        abb = devm_kzalloc(dev, sizeof(struct ti_abb), GFP_KERNEL);
-       if (!abb) {
-               dev_err(dev, "%s: Unable to allocate ABB struct\n", __func__);
-               ret = -ENOMEM;
-               goto err;
-       }
+       if (!abb)
+               return -ENOMEM;
        abb->regs = match->data;
 
        /* Map ABB resources */
        pname = "base-address";
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
        abb->base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(abb->base)) {
-               ret = PTR_ERR(abb->base);
-               goto err;
-       }
+       if (IS_ERR(abb->base))
+               return PTR_ERR(abb->base);
 
        pname = "int-address";
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
        if (!res) {
                dev_err(dev, "Missing '%s' IO resource\n", pname);
-               ret = -ENODEV;
-               goto err;
+               return -ENODEV;
        }
        /*
         * We may have shared interrupt register offsets which are
@@ -750,8 +742,7 @@ static int ti_abb_probe(struct platform_device *pdev)
                                             resource_size(res));
        if (!abb->int_base) {
                dev_err(dev, "Unable to map '%s'\n", pname);
-               ret = -ENOMEM;
-               goto err;
+               return -ENOMEM;
        }
 
        /* Map Optional resources */
@@ -771,17 +762,19 @@ static int ti_abb_probe(struct platform_device *pdev)
                                               resource_size(res));
        if (!abb->efuse_base) {
                dev_err(dev, "Unable to map '%s'\n", pname);
-               ret = -ENOMEM;
-               goto err;
+               return -ENOMEM;
        }
 
        pname = "ldo-address";
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, pname);
-       abb->ldo_base = devm_ioremap_resource(dev, res);
-       if (IS_ERR(abb->ldo_base)) {
-               ret = PTR_ERR(abb->ldo_base);
-               goto err;
+       if (!res) {
+               dev_dbg(dev, "Missing '%s' IO resource\n", pname);
+               ret = -ENODEV;
+               goto skip_opt;
        }
+       abb->ldo_base = devm_ioremap_resource(dev, res);
+       if (IS_ERR(abb->ldo_base))
+               return PTR_ERR(abb->ldo_base);
 
        /* IF ldo_base is set, the following are mandatory */
        pname = "ti,ldovbb-override-mask";
@@ -790,12 +783,11 @@ static int ti_abb_probe(struct platform_device *pdev)
                                 &abb->ldovbb_override_mask);
        if (ret) {
                dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-               goto err;
+               return ret;
        }
        if (!abb->ldovbb_override_mask) {
                dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        pname = "ti,ldovbb-vset-mask";
@@ -804,12 +796,11 @@ static int ti_abb_probe(struct platform_device *pdev)
                                 &abb->ldovbb_vset_mask);
        if (ret) {
                dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-               goto err;
+               return ret;
        }
        if (!abb->ldovbb_vset_mask) {
                dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
 skip_opt:
@@ -819,31 +810,29 @@ skip_opt:
                                 &abb->txdone_mask);
        if (ret) {
                dev_err(dev, "Missing '%s' (%d)\n", pname, ret);
-               goto err;
+               return ret;
        }
        if (!abb->txdone_mask) {
                dev_err(dev, "Invalid property:'%s' set as 0!\n", pname);
-               ret = -EINVAL;
-               goto err;
+               return -EINVAL;
        }
 
        initdata = of_get_regulator_init_data(dev, pdev->dev.of_node);
        if (!initdata) {
-               ret = -ENOMEM;
                dev_err(dev, "%s: Unable to alloc regulator init data\n",
                        __func__);
-               goto err;
+               return -ENOMEM;
        }
 
        /* init ABB opp_sel table */
        ret = ti_abb_init_table(dev, abb, initdata);
        if (ret)
-               goto err;
+               return ret;
 
        /* init ABB timing */
        ret = ti_abb_init_timings(dev, abb);
        if (ret)
-               goto err;
+               return ret;
 
        desc = &abb->rdesc;
        desc->name = dev_name(dev);
@@ -861,12 +850,12 @@ skip_opt:
        config.driver_data = abb;
        config.of_node = pdev->dev.of_node;
 
-       rdev = regulator_register(desc, &config);
+       rdev = devm_regulator_register(dev, desc, &config);
        if (IS_ERR(rdev)) {
                ret = PTR_ERR(rdev);
                dev_err(dev, "%s: failed to register regulator(%d)\n",
                        __func__, ret);
-               goto err;
+               return ret;
        }
        platform_set_drvdata(pdev, rdev);
 
@@ -874,31 +863,12 @@ skip_opt:
        ti_abb_rmw(abb->regs->sr2_en_mask, 1, abb->regs->setup_reg, abb->base);
 
        return 0;
-
-err:
-       dev_err(dev, "%s: Failed to initialize(%d)\n", __func__, ret);
-       return ret;
-}
-
-/**
- * ti_abb_remove() - cleanups
- * @pdev: ABB platform device
- *
- * Return: 0
- */
-static int ti_abb_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-       return 0;
 }
 
 MODULE_ALIAS("platform:ti_abb");
 
 static struct platform_driver ti_abb_driver = {
        .probe = ti_abb_probe,
-       .remove = ti_abb_remove,
        .driver = {
                   .name = "ti_abb",
                   .owner = THIS_MODULE,
index 9392a7ca3d2dc6df9152cb1aeb13c776b856e253..b0a3f0917a27ea841f3fffefdda7b67b163e8168 100644 (file)
@@ -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,
 };
 
index ec9453ffb77fd561ec1c2d6c3591b7302bc16b5f..c1e33a3d397b6a62b88fc14e8e2fc0c1ae6a8ec2 100644 (file)
@@ -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)
index 0b7ebb1ebf859bb5d409c19114b4a89f40a094b1..c2c0185a2dcd07b5521924ff1fee3eae344d75a1 100644 (file)
@@ -476,7 +476,7 @@ static int tps62360_probe(struct i2c_client *client,
        config.of_node = client->dev.of_node;
 
        /* Register the regulators */
-       rdev = regulator_register(&tps->desc, &config);
+       rdev = devm_regulator_register(&client->dev, &tps->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(tps->dev,
                        "%s(): regulator register failed with err %s\n",
@@ -488,20 +488,6 @@ static int tps62360_probe(struct i2c_client *client,
        return 0;
 }
 
-/**
- * tps62360_remove - tps62360 driver i2c remove handler
- * @client: i2c driver client device structure
- *
- * Unregister TPS driver as an i2c client device driver
- */
-static int tps62360_remove(struct i2c_client *client)
-{
-       struct tps62360_chip *tps = i2c_get_clientdata(client);
-
-       regulator_unregister(tps->rdev);
-       return 0;
-}
-
 static void tps62360_shutdown(struct i2c_client *client)
 {
        struct tps62360_chip *tps = i2c_get_clientdata(client);
@@ -535,7 +521,6 @@ static struct i2c_driver tps62360_i2c_driver = {
                .of_match_table = of_match_ptr(tps62360_of_match),
        },
        .probe = tps62360_probe,
-       .remove = tps62360_remove,
        .shutdown = tps62360_shutdown,
        .id_table = tps62360_id,
 };
index a15263d4bdff8a2fbd433c1315291def0bf66917..3ef67a86115c9c09e0196915c17f745d0099bb31 100644 (file)
@@ -277,12 +277,12 @@ static int tps_65023_probe(struct i2c_client *client,
                config.regmap = tps->regmap;
 
                /* Register the regulators */
-               rdev = regulator_register(&tps->desc[i], &config);
+               rdev = devm_regulator_register(&client->dev, &tps->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(&client->dev, "failed to register %s\n",
                                id->name);
-                       error = PTR_ERR(rdev);
-                       goto fail;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
@@ -293,24 +293,10 @@ static int tps_65023_probe(struct i2c_client *client,
 
        /* Enable setting output voltage by I2C */
        regmap_update_bits(tps->regmap, TPS65023_REG_CON_CTRL2,
-                       TPS65023_REG_CTRL2_CORE_ADJ, TPS65023_REG_CTRL2_CORE_ADJ);
+                                       TPS65023_REG_CTRL2_CORE_ADJ,
+                                       TPS65023_REG_CTRL2_CORE_ADJ);
 
        return 0;
-
- fail:
-       while (--i >= 0)
-               regulator_unregister(tps->rdev[i]);
-       return error;
-}
-
-static int tps_65023_remove(struct i2c_client *client)
-{
-       struct tps_pmic *tps = i2c_get_clientdata(client);
-       int i;
-
-       for (i = 0; i < TPS65023_NUM_REGULATOR; i++)
-               regulator_unregister(tps->rdev[i]);
-       return 0;
 }
 
 static const struct tps_info tps65020_regs[] = {
@@ -430,7 +416,6 @@ static struct i2c_driver tps_65023_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps_65023_probe,
-       .remove = tps_65023_remove,
        .id_table = tps_65023_id,
 };
 
index 4117ff52dba185909cc3db4e3df9329d4ecadaa8..162a0fae20b317bd0b4899e07520a45f496e43c6 100644 (file)
@@ -508,13 +508,13 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
                        config.of_node = tps6507x_reg_matches[i].of_node;
                }
 
-               rdev = regulator_register(&tps->desc[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &tps->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps6507x_dev->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       error = PTR_ERR(rdev);
-                       goto fail;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
@@ -525,22 +525,6 @@ static int tps6507x_pmic_probe(struct platform_device *pdev)
        platform_set_drvdata(pdev, tps6507x_dev);
 
        return 0;
-
-fail:
-       while (--i >= 0)
-               regulator_unregister(tps->rdev[i]);
-       return error;
-}
-
-static int tps6507x_pmic_remove(struct platform_device *pdev)
-{
-       struct tps6507x_dev *tps6507x_dev = platform_get_drvdata(pdev);
-       struct tps6507x_pmic *tps = tps6507x_dev->pmic;
-       int i;
-
-       for (i = 0; i < TPS6507X_NUM_REGULATOR; i++)
-               regulator_unregister(tps->rdev[i]);
-       return 0;
 }
 
 static struct platform_driver tps6507x_pmic_driver = {
@@ -549,7 +533,6 @@ static struct platform_driver tps6507x_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6507x_pmic_probe,
-       .remove = tps6507x_pmic_remove,
 };
 
 static int __init tps6507x_pmic_init(void)
index c8e70451df38864ffbe2ffb3b9fb3d67817fedc4..676f75548f0028435b6795bc0371490c462a641e 100644 (file)
@@ -180,7 +180,7 @@ static struct tps65090_platform_data *tps65090_parse_dt_reg_data(
                return ERR_PTR(-ENOMEM);
        }
 
-       regulators = of_find_node_by_name(np, "regulators");
+       regulators = of_get_child_by_name(np, "regulators");
        if (!regulators) {
                dev_err(&pdev->dev, "regulator node not found\n");
                return ERR_PTR(-ENODEV);
@@ -279,7 +279,7 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
                                if (ret < 0) {
                                        dev_err(&pdev->dev,
                                                "failed disable ext control\n");
-                                       goto scrub;
+                                       return ret;
                                }
                        }
                }
@@ -296,12 +296,11 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
                else
                        config.of_node = NULL;
 
-               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 scrub;
+                       return PTR_ERR(rdev);
                }
                ri->rdev = rdev;
 
@@ -309,36 +308,13 @@ static int tps65090_regulator_probe(struct platform_device *pdev)
                if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data &&
                                tps_pdata->enable_ext_control) {
                        ret = tps65090_config_ext_control(ri, true);
-                       if (ret < 0) {
-                               /* Increment num to get unregister rdev */
-                               num++;
-                               goto scrub;
-                       }
+                       if (ret < 0)
+                               return ret;
                }
        }
 
        platform_set_drvdata(pdev, pmic);
        return 0;
-
-scrub:
-       while (--num >= 0) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return ret;
-}
-
-static int tps65090_regulator_remove(struct platform_device *pdev)
-{
-       struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
-       struct tps65090_regulator *ri;
-       int num;
-
-       for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
@@ -347,7 +323,6 @@ static struct platform_driver tps65090_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps65090_regulator_probe,
-       .remove         = tps65090_regulator_remove,
 };
 
 static int __init tps65090_regulator_init(void)
index 90861d68a0b002ee3f83b6529feed9884770ca9a..9ea1bf26bd137b4b4e33dcede0c6c1551ff6d79c 100644 (file)
@@ -52,25 +52,17 @@ static const unsigned int LDO1_VSEL_table[] = {
 };
 
 static const struct regulator_linear_range tps65217_uv1_ranges[] = {
-       { .min_uV = 900000, .max_uV = 1500000, .min_sel =  0, .max_sel = 24,
-         .uV_step = 25000 },
-       { .min_uV = 1550000, .max_uV = 1800000, .min_sel = 25, .max_sel = 30,
-         .uV_step = 50000 },
-       { .min_uV = 1850000, .max_uV = 2900000, .min_sel = 31, .max_sel = 52,
-         .uV_step = 50000 },
-       { .min_uV = 3000000, .max_uV = 3200000, .min_sel = 53, .max_sel = 55,
-         .uV_step = 100000 },
-       { .min_uV = 3300000, .max_uV = 3300000, .min_sel = 56, .max_sel = 62,
-         .uV_step = 0 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 24, 25000),
+       REGULATOR_LINEAR_RANGE(1550000, 25, 30, 50000),
+       REGULATOR_LINEAR_RANGE(1850000, 31, 52, 50000),
+       REGULATOR_LINEAR_RANGE(3000000, 53, 55, 100000),
+       REGULATOR_LINEAR_RANGE(3300000, 56, 62, 0),
 };
 
 static const struct regulator_linear_range tps65217_uv2_ranges[] = {
-       { .min_uV = 1500000, .max_uV = 1900000, .min_sel =  0, .max_sel = 8,
-         .uV_step = 50000 },
-       { .min_uV = 2000000, .max_uV = 2400000, .min_sel = 9, .max_sel = 13,
-         .uV_step = 100000 },
-       { .min_uV = 2450000, .max_uV = 3300000, .min_sel = 14, .max_sel = 31,
-         .uV_step = 50000 },
+       REGULATOR_LINEAR_RANGE(1500000, 0, 8, 50000),
+       REGULATOR_LINEAR_RANGE(2000000, 9, 13, 100000),
+       REGULATOR_LINEAR_RANGE(2450000, 14, 31, 50000),
 };
 
 static int tps65217_pmic_enable(struct regulator_dev *dev)
@@ -233,7 +225,7 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
        struct regulator_init_data *reg_data;
        struct regulator_dev *rdev;
        struct regulator_config config = { };
-       int i, ret;
+       int i;
 
        if (tps->dev->of_node)
                pdata = tps65217_parse_dt(pdev);
@@ -269,35 +261,18 @@ static int tps65217_regulator_probe(struct platform_device *pdev)
                if (tps->dev->of_node)
                        config.of_node = pdata->of_node[i];
 
-               rdev = regulator_register(&regulators[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &regulators[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps->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 */
                tps->rdev[i] = rdev;
        }
        return 0;
-
-err_unregister_regulator:
-       while (--i >= 0)
-               regulator_unregister(tps->rdev[i]);
-
-       return ret;
-}
-
-static int tps65217_regulator_remove(struct platform_device *pdev)
-{
-       struct tps65217 *tps = platform_get_drvdata(pdev);
-       unsigned int i;
-
-       for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
-               regulator_unregister(tps->rdev[i]);
-
-       return 0;
 }
 
 static struct platform_driver tps65217_regulator_driver = {
@@ -305,7 +280,6 @@ static struct platform_driver tps65217_regulator_driver = {
                .name = "tps65217-pmic",
        },
        .probe = tps65217_regulator_probe,
-       .remove = tps65217_regulator_remove,
 };
 
 static int __init tps65217_regulator_init(void)
index 62e8d28beabd7cc8ad51b2935e29b7d348e17438..9f6bfda711b73a6dae9cdc9b8be3b69b2f5e88cc 100644 (file)
@@ -577,21 +577,6 @@ static struct regulator_ops regulator_ops = {
        .get_current_limit      = get_current_limit,
 };
 
-static int pmic_remove(struct spi_device *spi)
-{
-       struct tps6524x *hw = spi_get_drvdata(spi);
-       int i;
-
-       if (!hw)
-               return 0;
-       for (i = 0; i < N_REGULATORS; i++) {
-               regulator_unregister(hw->rdev[i]);
-               hw->rdev[i] = NULL;
-       }
-       spi_set_drvdata(spi, NULL);
-       return 0;
-}
-
 static int pmic_probe(struct spi_device *spi)
 {
        struct tps6524x *hw;
@@ -599,7 +584,7 @@ static int pmic_probe(struct spi_device *spi)
        const struct supply_info *info = supply_info;
        struct regulator_init_data *init_data;
        struct regulator_config config = { };
-       int ret = 0, i;
+       int i;
 
        init_data = dev_get_platdata(dev);
        if (!init_data) {
@@ -632,24 +617,17 @@ static int pmic_probe(struct spi_device *spi)
                config.init_data = init_data;
                config.driver_data = hw;
 
-               hw->rdev[i] = regulator_register(&hw->desc[i], &config);
-               if (IS_ERR(hw->rdev[i])) {
-                       ret = PTR_ERR(hw->rdev[i]);
-                       hw->rdev[i] = NULL;
-                       goto fail;
-               }
+               hw->rdev[i] = devm_regulator_register(dev, &hw->desc[i],
+                                                     &config);
+               if (IS_ERR(hw->rdev[i]))
+                       return PTR_ERR(hw->rdev[i]);
        }
 
        return 0;
-
-fail:
-       pmic_remove(spi);
-       return ret;
 }
 
 static struct spi_driver pmic_driver = {
        .probe          = pmic_probe,
-       .remove         = pmic_remove,
        .driver         = {
                .name   = "tps6524x",
                .owner  = THIS_MODULE,
index 2c9155b66f09f914789c4afde4a8fd630ddd6eba..e8e3a8afd3e279be7c524b3599316be05f9606a9 100644 (file)
@@ -298,7 +298,7 @@ static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
        struct tps6586x_platform_data *pdata;
        int err;
 
-       regs = of_find_node_by_name(np, "regulators");
+       regs = of_get_child_by_name(np, "regulators");
        if (!regs) {
                dev_err(&pdev->dev, "regulator node not found\n");
                return NULL;
@@ -379,15 +379,14 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
                ri = find_regulator_info(id);
                if (!ri) {
                        dev_err(&pdev->dev, "invalid regulator ID specified\n");
-                       err = -EINVAL;
-                       goto fail;
+                       return -EINVAL;
                }
 
                err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
                if (err) {
                        dev_err(&pdev->dev,
                                "regulator %d preinit failed, e %d\n", id, err);
-                       goto fail;
+                       return err;
                }
 
                config.dev = pdev->dev.parent;
@@ -397,12 +396,12 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
                if (tps6586x_reg_matches)
                        config.of_node = tps6586x_reg_matches[id].of_node;
 
-               rdev[id] = regulator_register(&ri->desc, &config);
+               rdev[id] = devm_regulator_register(&pdev->dev, &ri->desc,
+                                                  &config);
                if (IS_ERR(rdev[id])) {
                        dev_err(&pdev->dev, "failed to register regulator %s\n",
                                        ri->desc.name);
-                       err = PTR_ERR(rdev[id]);
-                       goto fail;
+                       return PTR_ERR(rdev[id]);
                }
 
                if (reg_data) {
@@ -411,30 +410,13 @@ static int tps6586x_regulator_probe(struct platform_device *pdev)
                        if (err < 0) {
                                dev_err(&pdev->dev,
                                        "Slew rate config failed, e %d\n", err);
-                               regulator_unregister(rdev[id]);
-                               goto fail;
+                               return err;
                        }
                }
        }
 
        platform_set_drvdata(pdev, rdev);
        return 0;
-
-fail:
-       while (--id >= 0)
-               regulator_unregister(rdev[id]);
-       return err;
-}
-
-static int tps6586x_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev **rdev = platform_get_drvdata(pdev);
-       int id = TPS6586X_ID_MAX_REGULATOR;
-
-       while (--id >= 0)
-               regulator_unregister(rdev[id]);
-
-       return 0;
 }
 
 static struct platform_driver tps6586x_regulator_driver = {
@@ -443,7 +425,6 @@ static struct platform_driver tps6586x_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps6586x_regulator_probe,
-       .remove         = tps6586x_regulator_remove,
 };
 
 static int __init tps6586x_regulator_init(void)
index 45c16447744bb1bc303a4243a0aa281a3a6317b7..23f8d1ce877d4e133fc690b7055b4342841e4112 100644 (file)
@@ -481,7 +481,7 @@ static int tps65910_get_voltage_dcdc_sel(struct regulator_dev *dev)
 
        /* multiplier 0 == 1 but 2,3 normal */
        if (!mult)
-               mult=1;
+               mult = 1;
 
        if (sr) {
                /* normalise to valid range */
@@ -685,7 +685,7 @@ static int tps65910_list_voltage_dcdc(struct regulator_dev *dev,
        case TPS65910_REG_VDD2:
                mult = (selector / VDD1_2_NUM_VOLT_FINE) + 1;
                volt = VDD1_2_MIN_VOLT +
-                               (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;
+                       (selector % VDD1_2_NUM_VOLT_FINE) * VDD1_2_OFFSET;
                break;
        case TPS65911_REG_VDDCTRL:
                volt = VDDCTRL_MIN_VOLT + (selector * VDDCTRL_OFFSET);
@@ -703,7 +703,7 @@ static int tps65911_list_voltage(struct regulator_dev *dev, unsigned selector)
        struct tps65910_reg *pmic = rdev_get_drvdata(dev);
        int step_mv = 0, id = rdev_get_id(dev);
 
-       switch(id) {
+       switch (id) {
        case TPS65911_REG_LDO1:
        case TPS65911_REG_LDO2:
        case TPS65911_REG_LDO4:
@@ -982,7 +982,7 @@ static struct tps65910_board *tps65910_parse_dt_reg_data(
        }
 
        np = of_node_get(pdev->dev.parent->of_node);
-       regulators = of_find_node_by_name(np, "regulators");
+       regulators = of_get_child_by_name(np, "regulators");
        if (!regulators) {
                dev_err(&pdev->dev, "regulator node not found\n");
                return NULL;
@@ -1074,7 +1074,7 @@ static int tps65910_probe(struct platform_device *pdev)
        tps65910_reg_set_bits(pmic->mfd, TPS65910_DEVCTRL,
                                DEVCTRL_SR_CTL_I2C_SEL_MASK);
 
-       switch(tps65910_chip_id(tps65910)) {
+       switch (tps65910_chip_id(tps65910)) {
        case TPS65910:
                pmic->get_ctrl_reg = &tps65910_get_ctrl_register;
                pmic->num_regulators = ARRAY_SIZE(tps65910_regs);
@@ -1177,35 +1177,19 @@ static int tps65910_probe(struct platform_device *pdev)
                if (tps65910_reg_matches)
                        config.of_node = tps65910_reg_matches[i].of_node;
 
-               rdev = regulator_register(&pmic->desc[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps65910->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       err = PTR_ERR(rdev);
-                       goto err_unregister_regulator;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
                pmic->rdev[i] = rdev;
        }
        return 0;
-
-err_unregister_regulator:
-       while (--i >= 0)
-               regulator_unregister(pmic->rdev[i]);
-       return err;
-}
-
-static int tps65910_remove(struct platform_device *pdev)
-{
-       struct tps65910_reg *pmic = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < pmic->num_regulators; i++)
-               regulator_unregister(pmic->rdev[i]);
-
-       return 0;
 }
 
 static void tps65910_shutdown(struct platform_device *pdev)
@@ -1244,7 +1228,6 @@ static struct platform_driver tps65910_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65910_probe,
-       .remove = tps65910_remove,
        .shutdown = tps65910_shutdown,
 };
 
index 281e52ac64ba0e3caf66c0322bd23ac91455a8a4..9cafaa0f94555a1e8fef93b4c0171be0aaea969f 100644 (file)
@@ -119,12 +119,9 @@ struct tps65912_reg {
 };
 
 static const struct regulator_linear_range tps65912_ldo_ranges[] = {
-       { .min_uV = 800000, .max_uV = 1600000, .min_sel =  0, .max_sel = 32,
-         .uV_step = 25000 },
-       { .min_uV = 1650000, .max_uV = 3000000, .min_sel = 33, .max_sel = 60,
-         .uV_step = 50000 },
-       { .min_uV = 3100000, .max_uV = 3300000, .min_sel = 61, .max_sel = 63,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(800000, 0, 32, 25000),
+       REGULATOR_LINEAR_RANGE(1650000, 33, 60, 50000),
+       REGULATOR_LINEAR_RANGE(3100000, 61, 63, 100000),
 };
 
 static int tps65912_get_range(struct tps65912_reg *pmic, int id)
@@ -461,7 +458,7 @@ static int tps65912_probe(struct platform_device *pdev)
        struct regulator_dev *rdev;
        struct tps65912_reg *pmic;
        struct tps65912_board *pmic_plat_data;
-       int i, err;
+       int i;
 
        pmic_plat_data = dev_get_platdata(tps65912->dev);
        if (!pmic_plat_data)
@@ -504,34 +501,19 @@ static int tps65912_probe(struct platform_device *pdev)
                config.init_data = reg_data;
                config.driver_data = pmic;
 
-               rdev = regulator_register(&pmic->desc[i], &config);
+               rdev = devm_regulator_register(&pdev->dev, &pmic->desc[i],
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(tps65912->dev,
                                "failed to register %s regulator\n",
                                pdev->name);
-                       err = PTR_ERR(rdev);
-                       goto err;
+                       return PTR_ERR(rdev);
                }
 
                /* Save regulator for cleanup */
                pmic->rdev[i] = rdev;
        }
        return 0;
-
-err:
-       while (--i >= 0)
-               regulator_unregister(pmic->rdev[i]);
-       return err;
-}
-
-static int tps65912_remove(struct platform_device *pdev)
-{
-       struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < TPS65912_NUM_REGULATOR; i++)
-               regulator_unregister(tps65912_reg->rdev[i]);
-       return 0;
 }
 
 static struct platform_driver tps65912_driver = {
@@ -540,7 +522,6 @@ static struct platform_driver tps65912_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65912_probe,
-       .remove = tps65912_remove,
 };
 
 static int __init tps65912_init(void)
index 6511d0bfd8964ecba4861dfd30c91d727c39ef25..71f457a42623f602541ae5d69b90521d673c9e2b 100644 (file)
@@ -719,7 +719,7 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
                        if (ret < 0) {
                                dev_err(&pdev->dev,
                                        "regulator config failed, e %d\n", ret);
-                               goto fail;
+                               return ret;
                        }
 
                        ret = tps80031_power_req_config(pdev->dev.parent,
@@ -727,41 +727,22 @@ static int tps80031_regulator_probe(struct platform_device *pdev)
                        if (ret < 0) {
                                dev_err(&pdev->dev,
                                        "pwr_req config failed, err %d\n", ret);
-                               goto fail;
+                               return ret;
                        }
                }
-               rdev = regulator_register(&ri->rinfo->desc, &config);
+               rdev = devm_regulator_register(&pdev->dev, &ri->rinfo->desc,
+                                              &config);
                if (IS_ERR(rdev)) {
                        dev_err(&pdev->dev,
                                "register regulator failed %s\n",
                                        ri->rinfo->desc.name);
-                       ret = PTR_ERR(rdev);
-                       goto fail;
+                       return PTR_ERR(rdev);
                }
                ri->rdev = rdev;
        }
 
        platform_set_drvdata(pdev, pmic);
        return 0;
-fail:
-       while (--num >= 0) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return ret;
-}
-
-static int tps80031_regulator_remove(struct platform_device *pdev)
-{
-       struct tps80031_regulator *pmic = platform_get_drvdata(pdev);
-       struct tps80031_regulator *ri = NULL;
-       int num;
-
-       for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
-               ri = &pmic[num];
-               regulator_unregister(ri->rdev);
-       }
-       return 0;
 }
 
 static struct platform_driver tps80031_regulator_driver = {
@@ -770,7 +751,6 @@ static struct platform_driver tps80031_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = tps80031_regulator_probe,
-       .remove         = tps80031_regulator_remove,
 };
 
 static int __init tps80031_regulator_init(void)
index 78aae4cbb00424864fbad430fc55379a060065c5..8ebd785485c73ddceba4047facf3960192a2cdf2 100644 (file)
@@ -1188,7 +1188,7 @@ static int twlreg_probe(struct platform_device *pdev)
        config.driver_data = info;
        config.of_node = pdev->dev.of_node;
 
-       rdev = regulator_register(&info->desc, &config);
+       rdev = devm_regulator_register(&pdev->dev, &info->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "can't register %s, %ld\n",
                                info->desc.name, PTR_ERR(rdev));
@@ -1217,7 +1217,6 @@ static int twlreg_remove(struct platform_device *pdev)
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct twlreg_info *info = rdev->reg_data;
 
-       regulator_unregister(rdev);
        kfree(info);
        return 0;
 }
index 4668c7f8133d7ecff17261d0af3640bbe5ba5cf4..f3ae28a7e66371143b6be01c9640712533faf541 100644 (file)
@@ -96,7 +96,7 @@ static int vexpress_regulator_probe(struct platform_device *pdev)
        config.driver_data = reg;
        config.of_node = pdev->dev.of_node;
 
-       reg->regdev = regulator_register(&reg->desc, &config);
+       reg->regdev = devm_regulator_register(&pdev->dev, &reg->desc, &config);
        if (IS_ERR(reg->regdev)) {
                err = PTR_ERR(reg->regdev);
                goto error_regulator_register;
@@ -119,7 +119,6 @@ static int vexpress_regulator_remove(struct platform_device *pdev)
        struct vexpress_regulator *reg = platform_get_drvdata(pdev);
 
        vexpress_config_func_put(reg->func);
-       regulator_unregister(reg->regdev);
 
        return 0;
 }
index 11861cb861df04394ff1de205eb7896c9ab98f89..6823e6f2b88aa13fde26a00e75b5d4ed8a2ce2ea 100644 (file)
@@ -387,8 +387,9 @@ static struct regulator_ops wm831x_buckv_ops = {
  * Set up DVS control.  We just log errors since we can still run
  * (with reduced performance) if we fail.
  */
-static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
-                                           struct wm831x_buckv_pdata *pdata)
+static void wm831x_buckv_dvs_init(struct platform_device *pdev,
+                                 struct wm831x_dcdc *dcdc,
+                                 struct wm831x_buckv_pdata *pdata)
 {
        struct wm831x *wm831x = dcdc->wm831x;
        int ret;
@@ -402,9 +403,9 @@ static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
         */
        dcdc->dvs_gpio_state = pdata->dvs_init_state;
 
-       ret = gpio_request_one(pdata->dvs_gpio,
-                              dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
-                              "DCDC DVS");
+       ret = devm_gpio_request_one(&pdev->dev, pdata->dvs_gpio,
+                                   dcdc->dvs_gpio_state ? GPIOF_INIT_HIGH : 0,
+                                   "DCDC DVS");
        if (ret < 0) {
                dev_err(wm831x->dev, "Failed to get %s DVS GPIO: %d\n",
                        dcdc->name, ret);
@@ -513,7 +514,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
        dcdc->dvs_vsel = ret & WM831X_DC1_DVS_VSEL_MASK;
 
        if (pdata && pdata->dcdc[id])
-               wm831x_buckv_dvs_init(dcdc, pdata->dcdc[id]->driver_data);
+               wm831x_buckv_dvs_init(pdev, dcdc,
+                                     pdata->dcdc[id]->driver_data);
 
        config.dev = pdev->dev.parent;
        if (pdata)
@@ -521,7 +523,8 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -530,57 +533,35 @@ static int wm831x_buckv_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_uv_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_oc_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_oc_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request HC IRQ %d: %d\n",
                        irq, ret);
-               goto err_uv;
+               goto err;
        }
 
        platform_set_drvdata(pdev, dcdc);
 
        return 0;
 
-err_uv:
-       free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
-                dcdc);
-err_regulator:
-       regulator_unregister(dcdc->regulator);
 err:
-       if (dcdc->dvs_gpio)
-               gpio_free(dcdc->dvs_gpio);
        return ret;
 }
 
-static int wm831x_buckv_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-       struct wm831x *wm831x = dcdc->wm831x;
-
-       free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "HC")),
-                           dcdc);
-       free_irq(wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV")),
-                           dcdc);
-       regulator_unregister(dcdc->regulator);
-       if (dcdc->dvs_gpio)
-               gpio_free(dcdc->dvs_gpio);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_buckv_driver = {
        .probe = wm831x_buckv_probe,
-       .remove = wm831x_buckv_remove,
        .driver         = {
                .name   = "wm831x-buckv",
                .owner  = THIS_MODULE,
@@ -681,7 +662,8 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -690,38 +672,25 @@ static int wm831x_buckp_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name, dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_uv_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name, dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, dcdc);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(dcdc->regulator);
 err:
        return ret;
 }
 
-static int wm831x_buckp_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
-                           dcdc);
-       regulator_unregister(dcdc->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_buckp_driver = {
        .probe = wm831x_buckp_probe,
-       .remove = wm831x_buckp_remove,
        .driver         = {
                .name   = "wm831x-buckp",
                .owner  = THIS_MODULE,
@@ -813,7 +782,8 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register DCDC%d: %d\n",
@@ -822,39 +792,26 @@ static int wm831x_boostp_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_dcdc_uv_irq,
-                                  IRQF_TRIGGER_RISING, dcdc->name,
-                                  dcdc);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_dcdc_uv_irq,
+                                       IRQF_TRIGGER_RISING, dcdc->name,
+                                       dcdc);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, dcdc);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(dcdc->regulator);
 err:
        return ret;
 }
 
-static int wm831x_boostp_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(dcdc->wm831x, platform_get_irq_byname(pdev, "UV")),
-                dcdc);
-       regulator_unregister(dcdc->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_boostp_driver = {
        .probe = wm831x_boostp_probe,
-       .remove = wm831x_boostp_remove,
        .driver         = {
                .name   = "wm831x-boostp",
                .owner  = THIS_MODULE,
@@ -914,7 +871,8 @@ static int wm831x_epe_probe(struct platform_device *pdev)
        config.driver_data = dcdc;
        config.regmap = wm831x->regmap;
 
-       dcdc->regulator = regulator_register(&dcdc->desc, &config);
+       dcdc->regulator = devm_regulator_register(&pdev->dev, &dcdc->desc,
+                                                 &config);
        if (IS_ERR(dcdc->regulator)) {
                ret = PTR_ERR(dcdc->regulator);
                dev_err(wm831x->dev, "Failed to register EPE%d: %d\n",
@@ -930,18 +888,8 @@ err:
        return ret;
 }
 
-static int wm831x_epe_remove(struct platform_device *pdev)
-{
-       struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
-
-       regulator_unregister(dcdc->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_epe_driver = {
        .probe = wm831x_epe_probe,
-       .remove = wm831x_epe_remove,
        .driver         = {
                .name   = "wm831x-epe",
                .owner  = THIS_MODULE,
index 4eb373de1facc63a4041ebc2c2804de358363287..0339b886df5dbf2a6bde26111a0a4c6a60f58732 100644 (file)
@@ -194,7 +194,8 @@ static int wm831x_isink_probe(struct platform_device *pdev)
        config.init_data = pdata->isink[id];
        config.driver_data = isink;
 
-       isink->regulator = regulator_register(&isink->desc, &config);
+       isink->regulator = devm_regulator_register(&pdev->dev, &isink->desc,
+                                                  &config);
        if (IS_ERR(isink->regulator)) {
                ret = PTR_ERR(isink->regulator);
                dev_err(wm831x->dev, "Failed to register ISINK%d: %d\n",
@@ -203,38 +204,26 @@ static int wm831x_isink_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq(pdev, 0));
-       ret = request_threaded_irq(irq, NULL, wm831x_isink_irq,
-                                  IRQF_TRIGGER_RISING, isink->name, isink);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_isink_irq,
+                                       IRQF_TRIGGER_RISING, isink->name,
+                                       isink);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request ISINK IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, isink);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(isink->regulator);
 err:
        return ret;
 }
 
-static int wm831x_isink_remove(struct platform_device *pdev)
-{
-       struct wm831x_isink *isink = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(isink->wm831x, platform_get_irq(pdev, 0)), isink);
-
-       regulator_unregister(isink->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_isink_driver = {
        .probe = wm831x_isink_probe,
-       .remove = wm831x_isink_remove,
        .driver         = {
                .name   = "wm831x-isink",
                .owner  = THIS_MODULE,
index 2205fbc2c37b4cf9b917bafa5d1f583f7e767b49..46d6700467b57007fbb277283207cfbbc4456fc0 100644 (file)
@@ -63,10 +63,8 @@ static irqreturn_t wm831x_ldo_uv_irq(int irq, void *data)
  */
 
 static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1600000, .min_sel =  0, .max_sel = 14,
-         .uV_step =  50000 },
-       { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
+       REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
 };
 
 static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev,
@@ -279,7 +277,8 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
        config.driver_data = ldo;
        config.regmap = wm831x->regmap;
 
-       ldo->regulator = regulator_register(&ldo->desc, &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -288,39 +287,26 @@ static int wm831x_gp_ldo_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
-                                  IRQF_TRIGGER_RISING, ldo->name,
-                                  ldo);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_ldo_uv_irq,
+                                       IRQF_TRIGGER_RISING, ldo->name,
+                                       ldo);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, ldo);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(ldo->regulator);
 err:
        return ret;
 }
 
-static int wm831x_gp_ldo_remove(struct platform_device *pdev)
-{
-       struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(ldo->wm831x,
-                           platform_get_irq_byname(pdev, "UV")), ldo);
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_gp_ldo_driver = {
        .probe = wm831x_gp_ldo_probe,
-       .remove = wm831x_gp_ldo_remove,
        .driver         = {
                .name   = "wm831x-ldo",
                .owner  = THIS_MODULE,
@@ -332,10 +318,8 @@ static struct platform_driver wm831x_gp_ldo_driver = {
  */
 
 static const struct regulator_linear_range wm831x_aldo_ranges[] = {
-       { .min_uV = 1000000, .max_uV = 1600000, .min_sel =  0, .max_sel = 12,
-         .uV_step =  50000 },
-       { .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(1000000, 0, 12, 50000),
+       REGULATOR_LINEAR_RANGE(1700000, 13, 31, 100000),
 };
 
 static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev,
@@ -505,7 +489,8 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
        config.driver_data = ldo;
        config.regmap = wm831x->regmap;
 
-       ldo->regulator = regulator_register(&ldo->desc, &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -514,38 +499,25 @@ static int wm831x_aldo_probe(struct platform_device *pdev)
        }
 
        irq = wm831x_irq(wm831x, platform_get_irq_byname(pdev, "UV"));
-       ret = request_threaded_irq(irq, NULL, wm831x_ldo_uv_irq,
-                                  IRQF_TRIGGER_RISING, ldo->name, ldo);
+       ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                       wm831x_ldo_uv_irq,
+                                       IRQF_TRIGGER_RISING, ldo->name, ldo);
        if (ret != 0) {
                dev_err(&pdev->dev, "Failed to request UV IRQ %d: %d\n",
                        irq, ret);
-               goto err_regulator;
+               goto err;
        }
 
        platform_set_drvdata(pdev, ldo);
 
        return 0;
 
-err_regulator:
-       regulator_unregister(ldo->regulator);
 err:
        return ret;
 }
 
-static int wm831x_aldo_remove(struct platform_device *pdev)
-{
-       struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-       free_irq(wm831x_irq(ldo->wm831x, platform_get_irq_byname(pdev, "UV")),
-                ldo);
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_aldo_driver = {
        .probe = wm831x_aldo_probe,
-       .remove = wm831x_aldo_remove,
        .driver         = {
                .name   = "wm831x-aldo",
                .owner  = THIS_MODULE,
@@ -663,7 +635,8 @@ static int wm831x_alive_ldo_probe(struct platform_device *pdev)
        config.driver_data = ldo;
        config.regmap = wm831x->regmap;
 
-       ldo->regulator = regulator_register(&ldo->desc, &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev, &ldo->desc,
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm831x->dev, "Failed to register LDO%d: %d\n",
@@ -679,18 +652,8 @@ err:
        return ret;
 }
 
-static int wm831x_alive_ldo_remove(struct platform_device *pdev)
-{
-       struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
-
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm831x_alive_ldo_driver = {
        .probe = wm831x_alive_ldo_probe,
-       .remove = wm831x_alive_ldo_remove,
        .driver         = {
                .name   = "wm831x-alive-ldo",
                .owner  = THIS_MODULE,
index 61ca9292a42944229f9f52bc6f5b8943b6414b22..de7b9c73e3fa09f3b14db1c5d8949ca99a37c352 100644 (file)
@@ -543,10 +543,8 @@ static int wm8350_dcdc_set_suspend_mode(struct regulator_dev *rdev,
 }
 
 static const struct regulator_linear_range wm8350_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1650000, .min_sel =  0, .max_sel = 15,
-         .uV_step =  50000 },
-       { .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 15, 50000),
+       REGULATOR_LINEAR_RANGE(1800000, 16, 31, 100000),
 };
 
 static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV)
@@ -1206,7 +1204,8 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
        config.regmap = wm8350->regmap;
 
        /* register regulator */
-       rdev = regulator_register(&wm8350_reg[pdev->id], &config);
+       rdev = devm_regulator_register(&pdev->dev, &wm8350_reg[pdev->id],
+                                      &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "failed to register %s\n",
                        wm8350_reg[pdev->id].name);
@@ -1217,7 +1216,6 @@ static int wm8350_regulator_probe(struct platform_device *pdev)
        ret = wm8350_register_irq(wm8350, wm8350_reg[pdev->id].irq,
                                  pmic_uv_handler, 0, "UV", rdev);
        if (ret < 0) {
-               regulator_unregister(rdev);
                dev_err(&pdev->dev, "failed to register regulator %s IRQ\n",
                        wm8350_reg[pdev->id].name);
                return ret;
@@ -1233,8 +1231,6 @@ static int wm8350_regulator_remove(struct platform_device *pdev)
 
        wm8350_free_irq(wm8350, wm8350_reg[pdev->id].irq, rdev);
 
-       regulator_unregister(rdev);
-
        return 0;
 }
 
index 58f51bec13f25d2f47a488ca53fc1099bb683762..82d82900085199f738d1555059d396315da6520a 100644 (file)
 #include <linux/mfd/wm8400-private.h>
 
 static const struct regulator_linear_range wm8400_ldo_ranges[] = {
-       { .min_uV =  900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14,
-         .uV_step =  50000 },
-       { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31,
-         .uV_step = 100000 },
+       REGULATOR_LINEAR_RANGE(900000, 0, 14, 50000),
+       REGULATOR_LINEAR_RANGE(1700000, 15, 31, 100000),
 };
 
 static struct regulator_ops wm8400_ldo_ops = {
@@ -219,7 +217,8 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
        config.driver_data = wm8400;
        config.regmap = wm8400->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);
 
@@ -228,21 +227,11 @@ static int wm8400_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int wm8400_regulator_remove(struct platform_device *pdev)
-{
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
-
-       regulator_unregister(rdev);
-
-       return 0;
-}
-
 static struct platform_driver wm8400_regulator_driver = {
        .driver = {
                .name = "wm8400-regulator",
        },
        .probe = wm8400_regulator_probe,
-       .remove = wm8400_regulator_remove,
 };
 
 /**
index 5ee2a208457c2b58e46fb1f1d7a79e8b180c4a35..71c5911f2e7130b2114d19b7619a30e69672a94a 100644 (file)
@@ -165,7 +165,9 @@ static int wm8994_ldo_probe(struct platform_device *pdev)
                ldo->init_data = *pdata->ldo[id].init_data;
        }
 
-       ldo->regulator = regulator_register(&wm8994_ldo_desc[id], &config);
+       ldo->regulator = devm_regulator_register(&pdev->dev,
+                                                &wm8994_ldo_desc[id],
+                                                &config);
        if (IS_ERR(ldo->regulator)) {
                ret = PTR_ERR(ldo->regulator);
                dev_err(wm8994->dev, "Failed to register LDO%d: %d\n",
@@ -181,18 +183,8 @@ err:
        return ret;
 }
 
-static int wm8994_ldo_remove(struct platform_device *pdev)
-{
-       struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
-
-       regulator_unregister(ldo->regulator);
-
-       return 0;
-}
-
 static struct platform_driver wm8994_ldo_driver = {
        .probe = wm8994_ldo_probe,
-       .remove = wm8994_ldo_remove,
        .driver         = {
                .name   = "wm8994-ldo",
                .owner  = THIS_MODULE,
index cebe97ee98b86e1d6f6ef478ddf84693d8486d6b..7314fc4e6d2503b0e5e885c7ceccf0a873207ec0 100644 (file)
@@ -59,6 +59,12 @@ struct mfd_cell {
         * pm_runtime_no_callbacks().
         */
        bool                    pm_runtime_no_callbacks;
+
+       /* A list of regulator supplies that should be mapped to the MFD
+        * device rather than the child device when requested
+        */
+       const char              **parent_supplies;
+       int                     num_parent_supplies;
 };
 
 /*
index 27be915caa96465ebfe7068a3af499e976a0ddc1..e530681bea7049cfa818e66acea0bf863952d281 100644 (file)
@@ -146,6 +146,32 @@ struct regulator *__must_check devm_regulator_get_optional(struct device *dev,
 void regulator_put(struct regulator *regulator);
 void devm_regulator_put(struct regulator *regulator);
 
+int regulator_register_supply_alias(struct device *dev, const char *id,
+                                   struct device *alias_dev,
+                                   const char *alias_id);
+void regulator_unregister_supply_alias(struct device *dev, const char *id);
+
+int regulator_bulk_register_supply_alias(struct device *dev, const char **id,
+                                        struct device *alias_dev,
+                                        const char **alias_id, int num_id);
+void regulator_bulk_unregister_supply_alias(struct device *dev,
+                                           const char **id, int num_id);
+
+int devm_regulator_register_supply_alias(struct device *dev, const char *id,
+                                        struct device *alias_dev,
+                                        const char *alias_id);
+void devm_regulator_unregister_supply_alias(struct device *dev,
+                                           const char *id);
+
+int devm_regulator_bulk_register_supply_alias(struct device *dev,
+                                             const char **id,
+                                             struct device *alias_dev,
+                                             const char **alias_id,
+                                             int num_id);
+void devm_regulator_bulk_unregister_supply_alias(struct device *dev,
+                                                const char **id,
+                                                int num_id);
+
 /* regulator output control and status */
 int __must_check regulator_enable(struct regulator *regulator);
 int regulator_disable(struct regulator *regulator);
@@ -250,6 +276,59 @@ static inline void devm_regulator_put(struct regulator *regulator)
 {
 }
 
+static inline int regulator_register_supply_alias(struct device *dev,
+                                                 const char *id,
+                                                 struct device *alias_dev,
+                                                 const char *alias_id)
+{
+       return 0;
+}
+
+static inline void regulator_unregister_supply_alias(struct device *dev,
+                                                   const char *id)
+{
+}
+
+static inline int regulator_bulk_register_supply_alias(struct device *dev,
+                                                      const char **id,
+                                                      struct device *alias_dev,
+                                                      const char **alias_id,
+                                                      int num_id)
+{
+       return 0;
+}
+
+static inline void regulator_bulk_unregister_supply_alias(struct device *dev,
+                                                         const char **id,
+                                                         int num_id)
+{
+}
+
+static inline int devm_regulator_register_supply_alias(struct device *dev,
+                                                      const char *id,
+                                                      struct device *alias_dev,
+                                                      const char *alias_id)
+{
+       return 0;
+}
+
+static inline void devm_regulator_unregister_supply_alias(struct device *dev,
+                                                         const char *id)
+{
+}
+
+static inline int devm_regulator_bulk_register_supply_alias(
+               struct device *dev, const char **id, struct device *alias_dev,
+               const char **alias_id, int num_id)
+{
+       return 0;
+}
+
+static inline void devm_regulator_bulk_unregister_supply_alias(
+               struct device *dev, const char **id, int num_id)
+{
+}
+
 static inline int regulator_enable(struct regulator *regulator)
 {
        return 0;
index 9bdad43ad228a5501c2dc8b0e6cc77a6da8c7b30..9370e65348a40ba5a92620fbfe4cfed4305a3963 100644 (file)
@@ -46,19 +46,26 @@ enum regulator_status {
  * regulator_list_linear_range().
  *
  * @min_uV:  Lowest voltage in range
- * @max_uV:  Highest voltage in range
  * @min_sel: Lowest selector for range
  * @max_sel: Highest selector for range
  * @uV_step: Step size
  */
 struct regulator_linear_range {
        unsigned int min_uV;
-       unsigned int max_uV;
        unsigned int min_sel;
        unsigned int max_sel;
        unsigned int uV_step;
 };
 
+/* Initialize struct regulator_linear_range */
+#define REGULATOR_LINEAR_RANGE(_min_uV, _min_sel, _max_sel, _step_uV)  \
+{                                                                      \
+       .min_uV         = _min_uV,                                      \
+       .min_sel        = _min_sel,                                     \
+       .max_sel        = _max_sel,                                     \
+       .uV_step        = _step_uV,                                     \
+}
+
 /**
  * struct regulator_ops - regulator operations.
  *
@@ -209,6 +216,7 @@ enum regulator_type {
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
  * @uV_step: Voltage increase with each selector (if linear mapping)
  * @linear_min_sel: Minimal selector for starting linear mapping
+ * @fixed_uV: Fixed voltage of rails.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
  * @volt_table: Voltage mapping table (if table based mapping)
  *
@@ -241,6 +249,7 @@ struct regulator_desc {
        unsigned int min_uV;
        unsigned int uV_step;
        unsigned int linear_min_sel;
+       int fixed_uV;
        unsigned int ramp_delay;
 
        const struct regulator_linear_range *linear_ranges;
@@ -336,7 +345,12 @@ struct regulator_dev {
 struct regulator_dev *
 regulator_register(const struct regulator_desc *regulator_desc,
                   const struct regulator_config *config);
+struct regulator_dev *
+devm_regulator_register(struct device *dev,
+                       const struct regulator_desc *regulator_desc,
+                       const struct regulator_config *config);
 void regulator_unregister(struct regulator_dev *rdev);
+void devm_regulator_unregister(struct device *dev, struct regulator_dev *rdev);
 
 int regulator_notifier_call_chain(struct regulator_dev *rdev,
                                  unsigned long event, void *data);
index 999b20ce06cf349185f008388e12e64c70518196..730e638c55899ba9bfff37a045386af5ee0f5cfe 100644 (file)
@@ -95,6 +95,7 @@ struct regulator_state {
  * @initial_state: Suspend state to set by default.
  * @initial_mode: Mode to set at startup.
  * @ramp_delay: Time to settle down after voltage change (unit: uV/us)
+ * @enable_time: Turn-on time of the rails (unit: microseconds)
  */
 struct regulation_constraints {
 
@@ -129,6 +130,7 @@ struct regulation_constraints {
        unsigned int initial_mode;
 
        unsigned int ramp_delay;
+       unsigned int enable_time;
 
        /* constraint flags */
        unsigned always_on:1;   /* regulator never off when system is on */
@@ -193,15 +195,10 @@ int regulator_suspend_finish(void);
 
 #ifdef CONFIG_REGULATOR
 void regulator_has_full_constraints(void);
-void regulator_use_dummy_regulator(void);
 #else
 static inline void regulator_has_full_constraints(void)
 {
 }
-
-static inline void regulator_use_dummy_regulator(void)
-{
-}
 #endif
 
 #endif