]> git.openfabrics.org - ~shefty/rdma-dev.git/commitdiff
Merge remote-tracking branch 'regulator/topic/max1586' into regulator-next
authorMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 10 Dec 2012 03:42:58 +0000 (12:42 +0900)
committerMark Brown <broonie@opensource.wolfsonmicro.com>
Mon, 10 Dec 2012 03:42:58 +0000 (12:42 +0900)
79 files changed:
Documentation/devicetree/bindings/regulator/gpio-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/max8925-regulator.txt [new file with mode: 0644]
Documentation/devicetree/bindings/regulator/vexpress.txt [new file with mode: 0644]
drivers/mfd/Kconfig
drivers/mfd/tps6586x.c
drivers/mfd/wm5102-tables.c
drivers/regulator/88pm8607.c
drivers/regulator/Kconfig
drivers/regulator/Makefile
drivers/regulator/aat2870-regulator.c
drivers/regulator/ab3100.c
drivers/regulator/ab8500.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 [new file with mode: 0644]
drivers/regulator/core.c
drivers/regulator/da903x.c
drivers/regulator/da9052-regulator.c
drivers/regulator/da9055-regulator.c [new file with mode: 0644]
drivers/regulator/db8500-prcmu.c
drivers/regulator/dbx500-prcmu.c
drivers/regulator/dummy.c
drivers/regulator/fan53555.c
drivers/regulator/fixed.c
drivers/regulator/gpio-regulator.c
drivers/regulator/isl6271a-regulator.c
drivers/regulator/lp3971.c
drivers/regulator/lp3972.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/max8649.c
drivers/regulator/max8660.c
drivers/regulator/max8907-regulator.c
drivers/regulator/max8925-regulator.c
drivers/regulator/max8952.c
drivers/regulator/max8997.c
drivers/regulator/max8998.c
drivers/regulator/mc13783-regulator.c
drivers/regulator/mc13892-regulator.c
drivers/regulator/mc13xxx-regulator-core.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/tps51632-regulator.c [new file with mode: 0644]
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 [new file with mode: 0644]
drivers/regulator/twl-regulator.c
drivers/regulator/vexpress.c [new file with mode: 0644]
drivers/regulator/virtual.c
drivers/regulator/wm831x-dcdc.c
drivers/regulator/wm831x-isink.c
drivers/regulator/wm831x-ldo.c
drivers/regulator/wm8400-regulator.c
drivers/regulator/wm8994-regulator.c
include/linux/mfd/arizona/registers.h
include/linux/mfd/da9055/pdata.h
include/linux/mfd/tps65090.h
include/linux/mfd/tps6586x.h
include/linux/regulator/consumer.h
include/linux/regulator/driver.h
include/linux/regulator/tps51632-regulator.h [new file with mode: 0644]
include/linux/regulator/tps65090-regulator.h [deleted file]

diff --git a/Documentation/devicetree/bindings/regulator/gpio-regulator.txt b/Documentation/devicetree/bindings/regulator/gpio-regulator.txt
new file mode 100644 (file)
index 0000000..63c6598
--- /dev/null
@@ -0,0 +1,37 @@
+GPIO controlled regulators
+
+Required properties:
+- compatible           : Must be "regulator-gpio".
+- states               : Selection of available voltages and GPIO configs.
+                          if there are no states, then use a fixed regulator
+
+Optional properties:
+- enable-gpio          : GPIO to use to enable/disable the regulator.
+- gpios                        : GPIO group used to control voltage.
+- startup-delay-us     : Startup time in microseconds.
+- enable-active-high   : Polarity of GPIO is active high (default is low).
+
+Any property defined as part of the core regulator binding defined in
+regulator.txt can also be used.
+
+Example:
+
+       mmciv: gpio-regulator {
+               compatible = "regulator-gpio";
+
+               regulator-name = "mmci-gpio-supply";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <2600000>;
+               regulator-boot-on;
+
+               enable-gpio = <&gpio0 23 0x4>;
+               gpios = <&gpio0 24 0x4
+                        &gpio0 25 0x4>;
+               states = <1800000 0x3
+                         2200000 0x2
+                         2600000 0x1
+                         2900000 0x0>;
+
+               startup-delay-us = <100000>;
+               enable-active-high;
+       };
diff --git a/Documentation/devicetree/bindings/regulator/max8925-regulator.txt b/Documentation/devicetree/bindings/regulator/max8925-regulator.txt
new file mode 100644 (file)
index 0000000..0057695
--- /dev/null
@@ -0,0 +1,40 @@
+Max8925 Voltage regulators
+
+Required nodes:
+-nodes:
+  - SDV1 for SDV SDV1
+  - SDV2 for SDV SDV2
+  - SDV3 for SDV SDV3
+  - LDO1 for LDO LDO1
+  - LDO2 for LDO LDO2
+  - LDO3 for LDO LDO3
+  - LDO4 for LDO LDO4
+  - LDO5 for LDO LDO5
+  - LDO6 for LDO LDO6
+  - LDO7 for LDO LDO7
+  - LDO8 for LDO LDO8
+  - LDO9 for LDO LDO9
+  - LDO10 for LDO LDO10
+  - LDO11 for LDO LDO11
+  - LDO12 for LDO LDO12
+  - LDO13 for LDO LDO13
+  - LDO14 for LDO LDO14
+  - LDO15 for LDO LDO15
+  - LDO16 for LDO LDO16
+  - LDO17 for LDO LDO17
+  - LDO18 for LDO LDO18
+  - LDO19 for LDO LDO19
+  - LDO20 for LDO LDO20
+
+Optional properties:
+- Any optional property defined in bindings/regulator/regulator.txt
+
+Example:
+
+       SDV1 {
+               regulator-min-microvolt = <637500>;
+               regulator-max-microvolt = <1425000>;
+               regulator-boot-on;
+               regulator-always-on;
+       };
+
diff --git a/Documentation/devicetree/bindings/regulator/vexpress.txt b/Documentation/devicetree/bindings/regulator/vexpress.txt
new file mode 100644 (file)
index 0000000..d775f72
--- /dev/null
@@ -0,0 +1,32 @@
+Versatile Express voltage regulators
+------------------------------------
+
+Requires node properties:
+- "compatible" value: "arm,vexpress-volt"
+- "arm,vexpress-sysreg,func" when controlled via vexpress-sysreg
+  (see Documentation/devicetree/bindings/arm/vexpress-sysreg.txt
+  for more details)
+
+Required regulator properties:
+- "regulator-name"
+- "regulator-always-on"
+
+Optional regulator properties:
+- "regulator-min-microvolt"
+- "regulator-max-microvolt"
+
+See Documentation/devicetree/bindings/regulator/regulator.txt
+for more details about the regulator properties.
+
+When no "regulator-[min|max]-microvolt" properties are defined,
+the device is treated as fixed (or rather "read-only") regulator.
+
+Example:
+       volt@0 {
+               compatible = "arm,vexpress-volt";
+               arm,vexpress-sysreg,func = <2 0>;
+               regulator-name = "Cores";
+               regulator-min-microvolt = <800000>;
+               regulator-max-microvolt = <1050000>;
+               regulator-always-on;
+       };
index acab3ef8a310efb611ccb30868c7f85474807d86..05acef8c764119f22d26855aedce7c0cf4081815 100644 (file)
@@ -201,7 +201,6 @@ config MFD_TPS6586X
        depends on I2C=y && GENERIC_HARDIRQS
        select MFD_CORE
        select REGMAP_I2C
-       depends on REGULATOR
        help
          If you say yes here you get support for the TPS6586X series of
          Power Management chips.
index 4674643687736679c69d74a337b1a0701f54f0bc..9d67bd92edf8d39bce86130e547ab0c4e8010090 100644 (file)
@@ -24,8 +24,6 @@
 #include <linux/err.h>
 #include <linux/i2c.h>
 #include <linux/regmap.h>
-#include <linux/regulator/of_regulator.h>
-#include <linux/regulator/machine.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps6586x.h>
@@ -98,6 +96,9 @@ static struct mfd_cell tps6586x_cell[] = {
        {
                .name = "tps6586x-gpio",
        },
+       {
+               .name = "tps6586x-pmic",
+       },
        {
                .name = "tps6586x-rtc",
        },
@@ -350,80 +351,19 @@ failed:
 }
 
 #ifdef CONFIG_OF
-static struct of_regulator_match tps6586x_matches[] = {
-       { .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     },
-       { .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
-       { .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
-       { .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
-       { .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
-       { .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
-       { .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
-       { .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
-       { .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
-       { .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
-       { .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
-       { .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
-       { .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
-       { .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
-       { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
-};
-
 static struct tps6586x_platform_data *tps6586x_parse_dt(struct i2c_client *client)
 {
-       const unsigned int num = ARRAY_SIZE(tps6586x_matches);
        struct device_node *np = client->dev.of_node;
        struct tps6586x_platform_data *pdata;
-       struct tps6586x_subdev_info *devs;
-       struct device_node *regs;
-       const char *sys_rail_name = NULL;
-       unsigned int count;
-       unsigned int i, j;
-       int err;
-
-       regs = of_find_node_by_name(np, "regulators");
-       if (!regs)
-               return NULL;
-
-       err = of_regulator_match(&client->dev, regs, tps6586x_matches, num);
-       if (err < 0) {
-               of_node_put(regs);
-               return NULL;
-       }
-
-       of_node_put(regs);
-       count = err;
-
-       devs = devm_kzalloc(&client->dev, count * sizeof(*devs), GFP_KERNEL);
-       if (!devs)
-               return NULL;
-
-       for (i = 0, j = 0; i < num && j < count; i++) {
-               struct regulator_init_data *reg_idata;
-
-               if (!tps6586x_matches[i].init_data)
-                       continue;
-
-               reg_idata  = tps6586x_matches[i].init_data;
-               devs[j].name = "tps6586x-regulator";
-               devs[j].platform_data = tps6586x_matches[i].init_data;
-               devs[j].id = (int)tps6586x_matches[i].driver_data;
-               if (devs[j].id == TPS6586X_ID_SYS)
-                       sys_rail_name = reg_idata->constraints.name;
-
-               if ((devs[j].id == TPS6586X_ID_LDO_5) ||
-                       (devs[j].id == TPS6586X_ID_LDO_RTC))
-                       reg_idata->supply_regulator = sys_rail_name;
-
-               devs[j].of_node = tps6586x_matches[i].of_node;
-               j++;
-       }
 
        pdata = devm_kzalloc(&client->dev, sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
+       if (!pdata) {
+               dev_err(&client->dev, "Memory allocation failed\n");
                return NULL;
+       }
 
-       pdata->num_subdevs = count;
-       pdata->subdevs = devs;
+       pdata->num_subdevs = 0;
+       pdata->subdevs = NULL;
        pdata->gpio_base = -1;
        pdata->irq_base = -1;
        pdata->pm_off = of_property_read_bool(np, "ti,system-power-controller");
index 01b9255ed6310cf9f984d4177fc59b9e21b6348e..b829a5710ddcaa39356aabf46f4f2aec05d25f05 100644 (file)
@@ -775,6 +775,7 @@ static const struct reg_default wm5102_reg_default[] = {
        { 0x00000154, 0x0000 },   /* R340   - Rate Estimator 3 */ 
        { 0x00000155, 0x0000 },   /* R341   - Rate Estimator 4 */ 
        { 0x00000156, 0x0000 },   /* R342   - Rate Estimator 5 */ 
+       { 0x00000161, 0x0000 },   /* R353   - Dynamic Frequency Scaling 1 */ 
        { 0x00000171, 0x0000 },   /* R369   - FLL1 Control 1 */ 
        { 0x00000172, 0x0008 },   /* R370   - FLL1 Control 2 */ 
        { 0x00000173, 0x0018 },   /* R371   - FLL1 Control 3 */ 
@@ -1564,6 +1565,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_RATE_ESTIMATOR_3:
        case ARIZONA_RATE_ESTIMATOR_4:
        case ARIZONA_RATE_ESTIMATOR_5:
+       case ARIZONA_DYNAMIC_FREQUENCY_SCALING_1:
        case ARIZONA_FLL1_CONTROL_1:
        case ARIZONA_FLL1_CONTROL_2:
        case ARIZONA_FLL1_CONTROL_3:
@@ -1596,6 +1598,7 @@ static bool wm5102_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_FLL2_GPIO_CLOCK:
        case ARIZONA_MIC_CHARGE_PUMP_1:
        case ARIZONA_LDO1_CONTROL_1:
+       case ARIZONA_LDO1_CONTROL_2:
        case ARIZONA_LDO2_CONTROL_1:
        case ARIZONA_MIC_BIAS_CTRL_1:
        case ARIZONA_MIC_BIAS_CTRL_2:
index 1c5ab0172ea282c73b0835d07be67e4172a8a6af..2b557119adad4b11d63ec345c96b425183e691f3 100644 (file)
@@ -394,7 +394,7 @@ static int pm8607_regulator_dt_init(struct platform_device *pdev,
 #define pm8607_regulator_dt_init(x, y, z)      (-1)
 #endif
 
-static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
+static int pm8607_regulator_probe(struct platform_device *pdev)
 {
        struct pm860x_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct pm8607_regulator_info *info = NULL;
@@ -454,7 +454,7 @@ static int __devinit pm8607_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pm8607_regulator_remove(struct platform_device *pdev)
+static int pm8607_regulator_remove(struct platform_device *pdev)
 {
        struct pm8607_regulator_info *info = platform_get_drvdata(pdev);
 
@@ -481,7 +481,7 @@ static struct platform_driver pm8607_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = pm8607_regulator_probe,
-       .remove         = __devexit_p(pm8607_regulator_remove),
+       .remove         = pm8607_regulator_remove,
        .id_table       = pm8607_regulator_driver_ids,
 };
 
index 67d47b59a66d878c9188afaaa62b92f255d657bb..e5ce11847befef9dc59d90621533d2bd79923013 100644 (file)
@@ -109,6 +109,16 @@ config REGULATOR_DA9052
          This driver supports the voltage regulators of DA9052-BC and
          DA9053-AA/Bx PMIC.
 
+config REGULATOR_DA9055
+       tristate "Dialog Semiconductor DA9055 regulators"
+       depends on MFD_DA9055
+       help
+         Say y here to support the BUCKs and LDOs regulators found on
+         Dialog Semiconductor DA9055 PMIC.
+
+         This driver can also be built as a module. If so, the module
+         will be called da9055-regulator.
+
 config REGULATOR_FAN53555
        tristate "Fairchild FAN53555 Regulator"
        depends on I2C
@@ -335,6 +345,17 @@ config REGULATOR_PALMAS
          on the muxing. This is handled automatically in the driver by
          reading the mux info from OTP.
 
+config REGULATOR_TPS51632
+       tristate "TI TPS51632 Power Regulator"
+       depends on I2C
+       select REGMAP_I2C
+       help
+         This driver supports TPS51632 voltage regulator chip.
+         The TPS51632 is 3-2-1 Phase D-Cap+ Step Down Driverless Controller
+         with Serial VID control and DVFS.
+         The voltage output can be configure through I2C interface or PWM
+         interface.
+
 config REGULATOR_TPS6105X
        tristate "TI TPS6105X Power regulators"
        depends on TPS6105X
@@ -415,6 +436,15 @@ config REGULATOR_TPS65912
        help
            This driver supports TPS65912 voltage regulator chip.
 
+config REGULATOR_TPS80031
+       tristate "TI TPS80031/TPS80032 power regualtor driver"
+       depends on MFD_TPS80031
+       help
+         TPS80031/ TPS80032 Fully Integrated Power Management with Power
+         Path and Battery Charger. It has 5 configurable step-down
+         converters, 11 general purpose LDOs, VBUS generator and digital
+         output to control regulators.
+
 config REGULATOR_TWL4030
        bool "TI TWL4030/TWL5030/TWL6030/TPS659x0 PMIC"
        depends on TWL4030_CORE
@@ -422,6 +452,13 @@ config REGULATOR_TWL4030
          This driver supports the voltage regulators provided by
          this family of companion chips.
 
+config REGULATOR_VEXPRESS
+       tristate "Versatile Express regulators"
+       depends on VEXPRESS_CONFIG
+       help
+         This driver provides support for voltage regulators available
+         on the ARM Ltd's Versatile Express platform.
+
 config REGULATOR_WM831X
        tristate "Wolfson Microelectronics WM831x PMIC regulators"
        depends on MFD_WM831X
@@ -450,5 +487,12 @@ config REGULATOR_WM8994
          This driver provides support for the voltage regulators on the
          WM8994 CODEC.
 
+config REGULATOR_AS3711
+       tristate "AS3711 PMIC"
+       depends on MFD_AS3711
+       help
+         This driver provides support for the voltage regulators on the
+         AS3711 PMIC
+
 endif
 
index e431eed8a8782f2f49fc1869365b76929dc52001..73bfb873d4b8e60c6d3e3ce1da3087980eddb5ff 100644 (file)
@@ -16,8 +16,10 @@ obj-$(CONFIG_REGULATOR_AB8500)       += ab8500.o
 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_DA903X) += da903x.o
 obj-$(CONFIG_REGULATOR_DA9052) += da9052-regulator.o
+obj-$(CONFIG_REGULATOR_DA9055) += da9055-regulator.o
 obj-$(CONFIG_REGULATOR_DBX500_PRCMU) += dbx500-prcmu.o
 obj-$(CONFIG_REGULATOR_DB8500_PRCMU) += db8500-prcmu.o
 obj-$(CONFIG_REGULATOR_FAN53555) += fan53555.o
@@ -41,6 +43,7 @@ obj-$(CONFIG_REGULATOR_MC13783) += mc13783-regulator.o
 obj-$(CONFIG_REGULATOR_MC13892) += mc13892-regulator.o
 obj-$(CONFIG_REGULATOR_MC13XXX_CORE) +=  mc13xxx-regulator-core.o
 obj-$(CONFIG_REGULATOR_PALMAS) += palmas-regulator.o
+obj-$(CONFIG_REGULATOR_TPS51632) += tps51632-regulator.o
 obj-$(CONFIG_REGULATOR_PCAP) += pcap-regulator.o
 obj-$(CONFIG_REGULATOR_PCF50633) += pcf50633-regulator.o
 obj-$(CONFIG_REGULATOR_RC5T583)  += rc5t583-regulator.o
@@ -56,7 +59,9 @@ obj-$(CONFIG_REGULATOR_TPS6524X) += tps6524x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS6586X) += tps6586x-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65910) += tps65910-regulator.o
 obj-$(CONFIG_REGULATOR_TPS65912) += tps65912-regulator.o
+obj-$(CONFIG_REGULATOR_TPS80031) += tps80031-regulator.o
 obj-$(CONFIG_REGULATOR_TWL4030) += twl-regulator.o
+obj-$(CONFIG_REGULATOR_VEXPRESS) += vexpress.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-dcdc.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-isink.o
 obj-$(CONFIG_REGULATOR_WM831X) += wm831x-ldo.o
index 167c93f21981a0178a9bd9d47ba879604ed7fb4a..8b5876356db97da46cd5ac0dd59dccb4b2521361 100644 (file)
@@ -187,7 +187,7 @@ static int aat2870_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit aat2870_regulator_remove(struct platform_device *pdev)
+static int aat2870_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -201,7 +201,7 @@ static struct platform_driver aat2870_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = aat2870_regulator_probe,
-       .remove = __devexit_p(aat2870_regulator_remove),
+       .remove = aat2870_regulator_remove,
 };
 
 static int __init aat2870_regulator_init(void)
index df4ad8927f0ce88257cb70db8fdfed535f8d17f2..111ec69a3e9454a40fa96091e4a7bc679cfa5dd1 100644 (file)
@@ -494,7 +494,7 @@ ab3100_regulator_desc[AB3100_NUM_REGULATORS] = {
  * for all the different regulators.
  */
 
-static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
+static int ab3100_regulators_probe(struct platform_device *pdev)
 {
        struct ab3100_platform_data *plfdata = pdev->dev.platform_data;
        struct regulator_config config = { };
@@ -571,7 +571,7 @@ static int __devinit ab3100_regulators_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit ab3100_regulators_remove(struct platform_device *pdev)
+static int ab3100_regulators_remove(struct platform_device *pdev)
 {
        int i;
 
@@ -589,7 +589,7 @@ static struct platform_driver ab3100_regulators_driver = {
                .owner = THIS_MODULE,
        },
        .probe = ab3100_regulators_probe,
-       .remove = __devexit_p(ab3100_regulators_remove),
+       .remove = ab3100_regulators_remove,
 };
 
 static __init int ab3100_regulators_init(void)
index e3d1d063025a45b12179e0712ea0d2599bfcb21c..09014f38a9481f8afb630ce8a5c5fdb513100380 100644 (file)
@@ -641,7 +641,7 @@ static struct ab8500_reg_init ab8500_reg_init[] = {
        REG_INIT(AB8500_REGUCTRLDISCH2,         0x04, 0x44, 0x16),
 };
 
-static __devinit int
+static int
 ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
 {
        int err;
@@ -676,7 +676,7 @@ ab8500_regulator_init_registers(struct platform_device *pdev, int id, int value)
        return 0;
 }
 
-static __devinit int ab8500_regulator_register(struct platform_device *pdev,
+static int ab8500_regulator_register(struct platform_device *pdev,
                                        struct regulator_init_data *init_data,
                                        int id,
                                        struct device_node *np)
@@ -735,7 +735,7 @@ static struct of_regulator_match ab8500_regulator_matches[] = {
        { .name = "ab8500_ldo_ana",     .driver_data = (void *) AB8500_LDO_ANA, },
 };
 
-static __devinit int
+static int
 ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
 {
        int err, i;
@@ -751,7 +751,7 @@ ab8500_regulator_of_probe(struct platform_device *pdev, struct device_node *np)
        return 0;
 }
 
-static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
+static int ab8500_regulator_probe(struct platform_device *pdev)
 {
        struct ab8500 *ab8500 = dev_get_drvdata(pdev->dev.parent);
        struct ab8500_platform_data *pdata;
@@ -817,7 +817,7 @@ static __devinit int ab8500_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
+static int ab8500_regulator_remove(struct platform_device *pdev)
 {
        int i;
 
@@ -836,7 +836,7 @@ static __devexit int ab8500_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver ab8500_regulator_driver = {
        .probe = ab8500_regulator_probe,
-       .remove = __devexit_p(ab8500_regulator_remove),
+       .remove = ab8500_regulator_remove,
        .driver         = {
                .name   = "ab8500-regulator",
                .owner  = THIS_MODULE,
index f123f7e3b7525acd164ed639e022f25dc46711cf..6b981b5faa7015c53f10a463d7a53097edeab075 100644 (file)
@@ -211,7 +211,7 @@ static const struct i2c_device_id ad5398_id[] = {
 };
 MODULE_DEVICE_TABLE(i2c, ad5398_id);
 
-static int __devinit ad5398_probe(struct i2c_client *client,
+static int ad5398_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct regulator_init_data *init_data = client->dev.platform_data;
@@ -256,7 +256,7 @@ err:
        return ret;
 }
 
-static int __devexit ad5398_remove(struct i2c_client *client)
+static int ad5398_remove(struct i2c_client *client)
 {
        struct ad5398_chip_info *chip = i2c_get_clientdata(client);
 
@@ -266,7 +266,7 @@ static int __devexit ad5398_remove(struct i2c_client *client)
 
 static struct i2c_driver ad5398_driver = {
        .probe = ad5398_probe,
-       .remove = __devexit_p(ad5398_remove),
+       .remove = ad5398_remove,
        .driver         = {
                .name   = "ad5398",
        },
index 1af97686f4448864d92b7dbfdf58e79c883edbb8..1aa5246c79d90741a0ad56f8aacca2203e2f82f0 100644 (file)
@@ -87,7 +87,7 @@ static struct regulator_ops anatop_rops = {
        .map_voltage = regulator_map_voltage_linear,
 };
 
-static int __devinit anatop_regulator_probe(struct platform_device *pdev)
+static int anatop_regulator_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct device_node *np = dev->of_node;
@@ -186,7 +186,7 @@ anatop_probe_end:
        return ret;
 }
 
-static int __devexit anatop_regulator_remove(struct platform_device *pdev)
+static int anatop_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct anatop_regulator *sreg = rdev_get_drvdata(rdev);
@@ -210,7 +210,7 @@ static struct platform_driver anatop_regulator_driver = {
                .of_match_table = of_anatop_regulator_match_tbl,
        },
        .probe  = anatop_regulator_probe,
-       .remove = __devexit_p(anatop_regulator_remove),
+       .remove = anatop_regulator_remove,
 };
 
 static int __init anatop_regulator_init(void)
index d184aa35abcb45a91795aeed9de35ad8f7d1a75a..ed7beec53af85505b49815d97d94947d0d311efb 100644 (file)
@@ -34,6 +34,108 @@ struct arizona_ldo1 {
        struct regulator_init_data init_data;
 };
 
+static int arizona_ldo1_hc_list_voltage(struct regulator_dev *rdev,
+                                       unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (selector == rdev->desc->n_voltages - 1)
+               return 1800000;
+       else
+               return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+
+static int arizona_ldo1_hc_map_voltage(struct regulator_dev *rdev,
+                                      int min_uV, int max_uV)
+{
+       int sel;
+
+       sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+       if (sel >= rdev->desc->n_voltages)
+               sel = rdev->desc->n_voltages - 1;
+
+       return sel;
+}
+
+static int arizona_ldo1_hc_set_voltage_sel(struct regulator_dev *rdev,
+                                          unsigned sel)
+{
+       struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+       struct regmap *regmap = ldo->arizona->regmap;
+       unsigned int val;
+       int ret;
+
+       if (sel == rdev->desc->n_voltages - 1)
+               val = ARIZONA_LDO1_HI_PWR;
+       else
+               val = 0;
+
+       ret = regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_2,
+                                ARIZONA_LDO1_HI_PWR, val);
+       if (ret != 0)
+               return ret;
+
+       ret = regmap_update_bits(regmap, ARIZONA_DYNAMIC_FREQUENCY_SCALING_1,
+                                ARIZONA_SUBSYS_MAX_FREQ, val);
+       if (ret != 0)
+               return ret;
+
+       if (val)
+               return 0;
+
+       val = sel << ARIZONA_LDO1_VSEL_SHIFT;
+
+       return regmap_update_bits(regmap, ARIZONA_LDO1_CONTROL_1,
+                                 ARIZONA_LDO1_VSEL_MASK, val);
+}
+
+static int arizona_ldo1_hc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct arizona_ldo1 *ldo = rdev_get_drvdata(rdev);
+       struct regmap *regmap = ldo->arizona->regmap;
+       unsigned int val;
+       int ret;
+
+       ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_2, &val);
+       if (ret != 0)
+               return ret;
+
+       if (val & ARIZONA_LDO1_HI_PWR)
+               return rdev->desc->n_voltages - 1;
+
+       ret = regmap_read(regmap, ARIZONA_LDO1_CONTROL_1, &val);
+       if (ret != 0)
+               return ret;
+
+       return (val & ARIZONA_LDO1_VSEL_MASK) >> ARIZONA_LDO1_VSEL_SHIFT;
+}
+
+static struct regulator_ops arizona_ldo1_hc_ops = {
+       .list_voltage = arizona_ldo1_hc_list_voltage,
+       .map_voltage = arizona_ldo1_hc_map_voltage,
+       .get_voltage_sel = arizona_ldo1_hc_get_voltage_sel,
+       .set_voltage_sel = arizona_ldo1_hc_set_voltage_sel,
+       .get_bypass = regulator_get_bypass_regmap,
+       .set_bypass = regulator_set_bypass_regmap,
+};
+
+static const struct regulator_desc arizona_ldo1_hc = {
+       .name = "LDO1",
+       .supply_name = "LDOVDD",
+       .type = REGULATOR_VOLTAGE,
+       .ops = &arizona_ldo1_hc_ops,
+
+       .bypass_reg = ARIZONA_LDO1_CONTROL_1,
+       .bypass_mask = ARIZONA_LDO1_BYPASS,
+       .min_uV = 900000,
+       .uV_step = 50000,
+       .n_voltages = 8,
+       .enable_time = 500,
+
+       .owner = THIS_MODULE,
+};
+
 static struct regulator_ops arizona_ldo1_ops = {
        .list_voltage = regulator_list_voltage_linear,
        .map_voltage = regulator_map_voltage_linear,
@@ -55,11 +157,22 @@ static const struct regulator_desc arizona_ldo1 = {
        .bypass_mask = ARIZONA_LDO1_BYPASS,
        .min_uV = 900000,
        .uV_step = 50000,
-       .n_voltages = 6,
+       .n_voltages = 7,
+       .enable_time = 500,
 
        .owner = THIS_MODULE,
 };
 
+static const struct regulator_init_data arizona_ldo1_dvfs = {
+       .constraints = {
+               .min_uV = 1200000,
+               .max_uV = 1800000,
+               .valid_ops_mask = REGULATOR_CHANGE_STATUS |
+                                 REGULATOR_CHANGE_VOLTAGE,
+       },
+       .num_consumer_supplies = 1,
+};
+
 static const struct regulator_init_data arizona_ldo1_default = {
        .constraints = {
                .valid_ops_mask = REGULATOR_CHANGE_STATUS,
@@ -67,9 +180,10 @@ static const struct regulator_init_data arizona_ldo1_default = {
        .num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
+static int arizona_ldo1_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
+       const struct regulator_desc *desc;
        struct regulator_config config = { };
        struct arizona_ldo1 *ldo1;
        int ret;
@@ -87,7 +201,17 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
         * default init_data for it.  This will be overridden with
         * platform data if provided.
         */
-       ldo1->init_data = arizona_ldo1_default;
+       switch (arizona->type) {
+       case WM5102:
+               desc = &arizona_ldo1_hc;
+               ldo1->init_data = arizona_ldo1_dvfs;
+               break;
+       default:
+               desc = &arizona_ldo1;
+               ldo1->init_data = arizona_ldo1_default;
+               break;
+       }
+
        ldo1->init_data.consumer_supplies = &ldo1->supply;
        ldo1->supply.supply = "DCVDD";
        ldo1->supply.dev_name = dev_name(arizona->dev);
@@ -102,7 +226,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
        else
                config.init_data = &ldo1->init_data;
 
-       ldo1->regulator = regulator_register(&arizona_ldo1, &config);
+       ldo1->regulator = regulator_register(desc, &config);
        if (IS_ERR(ldo1->regulator)) {
                ret = PTR_ERR(ldo1->regulator);
                dev_err(arizona->dev, "Failed to register LDO1 supply: %d\n",
@@ -115,7 +239,7 @@ static __devinit int arizona_ldo1_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
+static int arizona_ldo1_remove(struct platform_device *pdev)
 {
        struct arizona_ldo1 *ldo1 = platform_get_drvdata(pdev);
 
@@ -126,7 +250,7 @@ static __devexit int arizona_ldo1_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_ldo1_driver = {
        .probe = arizona_ldo1_probe,
-       .remove = __devexit_p(arizona_ldo1_remove),
+       .remove = arizona_ldo1_remove,
        .driver         = {
                .name   = "arizona-ldo1",
                .owner  = THIS_MODULE,
index d9b1f82cc5bd80939206025432f2602072dfe244..a6d040cbf8ac1dade86099eb0a71df4c2f94c4c8 100644 (file)
@@ -101,6 +101,8 @@ static const struct regulator_desc arizona_micsupp = {
        .bypass_reg = ARIZONA_MIC_CHARGE_PUMP_1,
        .bypass_mask = ARIZONA_CPMIC_BYPASS,
 
+       .enable_time = 3000,
+
        .owner = THIS_MODULE,
 };
 
@@ -115,7 +117,7 @@ static const struct regulator_init_data arizona_micsupp_default = {
        .num_consumer_supplies = 1,
 };
 
-static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
+static int arizona_micsupp_probe(struct platform_device *pdev)
 {
        struct arizona *arizona = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -166,7 +168,7 @@ static __devinit int arizona_micsupp_probe(struct platform_device *pdev)
        return 0;
 }
 
-static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
+static int arizona_micsupp_remove(struct platform_device *pdev)
 {
        struct arizona_micsupp *micsupp = platform_get_drvdata(pdev);
 
@@ -177,7 +179,7 @@ static __devexit int arizona_micsupp_remove(struct platform_device *pdev)
 
 static struct platform_driver arizona_micsupp_driver = {
        .probe = arizona_micsupp_probe,
-       .remove = __devexit_p(arizona_micsupp_remove),
+       .remove = arizona_micsupp_remove,
        .driver         = {
                .name   = "arizona-micsupp",
                .owner  = THIS_MODULE,
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
new file mode 100644 (file)
index 0000000..2f1341d
--- /dev/null
@@ -0,0 +1,369 @@
+/*
+ * AS3711 PMIC regulator driver, using DCDC Step Down and LDO supplies
+ *
+ * Copyright (C) 2012 Renesas Electronics Corporation
+ * Author: Guennadi Liakhovetski, <g.liakhovetski@gmx.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the version 2 of the GNU General Public License as
+ * published by the Free Software Foundation
+ */
+
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/mfd/as3711.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/slab.h>
+
+struct as3711_regulator_info {
+       struct regulator_desc   desc;
+       unsigned int            max_uV;
+};
+
+struct as3711_regulator {
+       struct as3711_regulator_info *reg_info;
+       struct regulator_dev *rdev;
+};
+
+static int as3711_list_voltage_sd(struct regulator_dev *rdev,
+                                 unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (!selector)
+               return 0;
+       if (selector < 0x41)
+               return 600000 + selector * 12500;
+       if (selector < 0x71)
+               return 1400000 + (selector - 0x40) * 25000;
+       return 2600000 + (selector - 0x70) * 50000;
+}
+
+static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
+                                   unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (selector < 0x10)
+               return 1200000 + selector * 50000;
+       return 1800000 + (selector - 0x10) * 100000;
+}
+
+static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
+                                   unsigned int selector)
+{
+       if (selector >= rdev->desc->n_voltages ||
+           (selector > 0x10 && selector < 0x20))
+               return -EINVAL;
+
+       if (selector < 0x11)
+               return 900000 + selector * 50000;
+       return 1750000 + (selector - 0x20) * 50000;
+}
+
+static int as3711_bound_check(struct regulator_dev *rdev,
+                             int *min_uV, int *max_uV)
+{
+       struct as3711_regulator *reg = rdev_get_drvdata(rdev);
+       struct as3711_regulator_info *info = reg->reg_info;
+
+       dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
+               *min_uV, rdev->desc->min_uV, info->max_uV);
+
+       if (*max_uV < *min_uV ||
+           *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
+               return -EINVAL;
+
+       if (rdev->desc->n_voltages == 1)
+               return 0;
+
+       if (*max_uV > info->max_uV)
+               *max_uV = info->max_uV;
+
+       if (*min_uV < rdev->desc->min_uV)
+               *min_uV = rdev->desc->min_uV;
+
+       return *min_uV;
+}
+
+static int as3711_sel_check(int min, int max, int bottom, int step)
+{
+       int sel, voltage;
+
+       /* Round up min, when dividing: keeps us within the range */
+       sel = DIV_ROUND_UP(min - bottom, step);
+       voltage = sel * step + bottom;
+       pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
+              min, max, bottom, step, sel);
+       if (voltage > max)
+               return -EINVAL;
+
+       return sel;
+}
+
+static int as3711_map_voltage_sd(struct regulator_dev *rdev,
+                                int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1400000)
+               return as3711_sel_check(min_uV, max_uV, 600000, 12500);
+
+       if (min_uV <= 2600000)
+               return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
+
+       return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
+}
+
+/*
+ * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
+ * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
+ * FAST:       sdX_fast=1
+ * NORMAL:     low_noise=1
+ * IDLE:       low_noise=0
+ */
+
+static int as3711_set_mode_sd(struct regulator_dev *rdev, unsigned int mode)
+{
+       unsigned int fast_bit = rdev->desc->enable_mask,
+               low_noise_bit = fast_bit << 4;
+       u8 val;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = fast_bit | low_noise_bit;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = low_noise_bit;
+               break;
+       case REGULATOR_MODE_IDLE:
+               val = 0;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return regmap_update_bits(rdev->regmap, AS3711_SD_CONTROL_1,
+                                 low_noise_bit | fast_bit, val);
+}
+
+static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
+{
+       unsigned int fast_bit = rdev->desc->enable_mask,
+               low_noise_bit = fast_bit << 4, mask = fast_bit | low_noise_bit;
+       unsigned int val;
+       int ret = regmap_read(rdev->regmap, AS3711_SD_CONTROL_1, &val);
+
+       if (ret < 0)
+               return ret;
+
+       if ((val & mask) == mask)
+               return REGULATOR_MODE_FAST;
+
+       if ((val & mask) == low_noise_bit)
+               return REGULATOR_MODE_NORMAL;
+
+       if (!(val & mask))
+               return REGULATOR_MODE_IDLE;
+
+       return -EINVAL;
+}
+
+static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1800000)
+               return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
+
+       return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
+}
+
+static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
+                                 int min_uV, int max_uV)
+{
+       int ret;
+
+       ret = as3711_bound_check(rdev, &min_uV, &max_uV);
+       if (ret <= 0)
+               return ret;
+
+       if (min_uV <= 1700000)
+               return as3711_sel_check(min_uV, max_uV, 900000, 50000);
+
+       return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
+}
+
+static struct regulator_ops as3711_sd_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_sd,
+       .map_voltage            = as3711_map_voltage_sd,
+       .get_mode               = as3711_get_mode_sd,
+       .set_mode               = as3711_set_mode_sd,
+};
+
+static struct regulator_ops as3711_aldo_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_aldo,
+       .map_voltage            = as3711_map_voltage_aldo,
+};
+
+static struct regulator_ops as3711_dldo_ops = {
+       .is_enabled             = regulator_is_enabled_regmap,
+       .enable                 = regulator_enable_regmap,
+       .disable                = regulator_disable_regmap,
+       .get_voltage_sel        = regulator_get_voltage_sel_regmap,
+       .set_voltage_sel        = regulator_set_voltage_sel_regmap,
+       .list_voltage           = as3711_list_voltage_dldo,
+       .map_voltage            = as3711_map_voltage_dldo,
+};
+
+#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx)     \
+       [AS3711_REGULATOR_ ## _id] = {                                                  \
+       .desc = {                                                                       \
+               .name = "as3711-regulator-" # _id,                                      \
+               .id = AS3711_REGULATOR_ ## _id,                                         \
+               .n_voltages = (_vmask + 1),                                             \
+               .ops = &as3711_ ## _sfx ## _ops,                                        \
+               .type = REGULATOR_VOLTAGE,                                              \
+               .owner = THIS_MODULE,                                                   \
+               .vsel_reg = AS3711_ ## _id ## _VOLTAGE,                                 \
+               .vsel_mask = _vmask << _vshift,                                         \
+               .enable_reg = AS3711_ ## _en_reg,                                       \
+               .enable_mask = BIT(_en_bit),                                            \
+               .min_uV = _min_uV,                                                      \
+       },                                                                              \
+       .max_uV = _max_uV,                                                              \
+}
+
+static struct as3711_regulator_info as3711_reg_info[] = {
+       AS3711_REG(SD_1, SD_CONTROL, 0, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_2, SD_CONTROL, 1, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_3, SD_CONTROL, 2, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(SD_4, SD_CONTROL, 3, 0x7f, 0, 612500, 3350000, sd),
+       AS3711_REG(LDO_1, LDO_1_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+       AS3711_REG(LDO_2, LDO_2_VOLTAGE, 7, 0x1f, 0, 1200000, 3300000, aldo),
+       AS3711_REG(LDO_3, LDO_3_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_4, LDO_4_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_5, LDO_5_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_6, LDO_6_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_7, LDO_7_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       AS3711_REG(LDO_8, LDO_8_VOLTAGE, 7, 0x3f, 0, 900000, 3300000, dldo),
+       /* StepUp output voltage depends on supplying regulator */
+};
+
+#define AS3711_REGULATOR_NUM ARRAY_SIZE(as3711_reg_info)
+
+static int as3711_regulator_probe(struct platform_device *pdev)
+{
+       struct as3711_regulator_pdata *pdata = dev_get_platdata(&pdev->dev);
+       struct as3711 *as3711 = dev_get_drvdata(pdev->dev.parent);
+       struct regulator_init_data *reg_data;
+       struct regulator_config config = {.dev = &pdev->dev,};
+       struct as3711_regulator *reg = NULL;
+       struct as3711_regulator *regs;
+       struct regulator_dev *rdev;
+       struct as3711_regulator_info *ri;
+       int ret;
+       int id;
+
+       if (!pdata)
+               dev_dbg(&pdev->dev, "No platform data...\n");
+
+       regs = devm_kzalloc(&pdev->dev, AS3711_REGULATOR_NUM *
+                       sizeof(struct as3711_regulator), GFP_KERNEL);
+       if (!regs) {
+               dev_err(&pdev->dev, "Memory allocation failed exiting..\n");
+               return -ENOMEM;
+       }
+
+       for (id = 0, ri = as3711_reg_info; id < AS3711_REGULATOR_NUM; ++id, ri++) {
+               reg_data = pdata ? pdata->init_data[id] : NULL;
+
+               /* No need to register if there is no regulator data */
+               if (!ri->desc.name)
+                       continue;
+
+               reg = &regs[id];
+               reg->reg_info = ri;
+
+               config.init_data = reg_data;
+               config.driver_data = reg;
+               config.regmap = as3711->regmap;
+
+               rdev = regulator_register(&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;
+               }
+               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 = {
+       .driver = {
+               .name   = "as3711-regulator",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = as3711_regulator_probe,
+       .remove         = as3711_regulator_remove,
+};
+
+static int __init as3711_regulator_init(void)
+{
+       return platform_driver_register(&as3711_regulator_driver);
+}
+subsys_initcall(as3711_regulator_init);
+
+static void __exit as3711_regulator_exit(void)
+{
+       platform_driver_unregister(&as3711_regulator_driver);
+}
+module_exit(as3711_regulator_exit);
+
+MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>");
+MODULE_DESCRIPTION("AS3711 regulator driver");
+MODULE_ALIAS("platform:as3711-regulator");
+MODULE_LICENSE("GPL v2");
index e872c8be080ed427a2e546efffee50c12acdd9fe..35c149bb2ad36a662f2eb8e13b6c2dab44b8b584 100644 (file)
@@ -199,8 +199,11 @@ static int regulator_check_consumers(struct regulator_dev *rdev,
                        *min_uV = regulator->min_uV;
        }
 
-       if (*min_uV > *max_uV)
+       if (*min_uV > *max_uV) {
+               dev_err(regulator->dev, "Restricting voltage, %u-%uuV\n",
+                       regulator->min_uV, regulator->max_uV);
                return -EINVAL;
+       }
 
        return 0;
 }
@@ -880,7 +883,9 @@ static int machine_constraints_voltage(struct regulator_dev *rdev,
 
                /* final: [min_uV..max_uV] valid iff constraints valid */
                if (max_uV < min_uV) {
-                       rdev_err(rdev, "unsupportable voltage constraints\n");
+                       rdev_err(rdev,
+                                "unsupportable voltage constraints %u-%uuV\n",
+                                min_uV, max_uV);
                        return -EINVAL;
                }
 
@@ -1866,6 +1871,28 @@ int regulator_is_enabled(struct regulator *regulator)
 }
 EXPORT_SYMBOL_GPL(regulator_is_enabled);
 
+/**
+ * regulator_can_change_voltage - check if regulator can change voltage
+ * @regulator: regulator source
+ *
+ * Returns positive if the regulator driver backing the source/client
+ * can change its voltage, false otherwise. Usefull for detecting fixed
+ * or dummy regulators and disabling voltage change logic in the client
+ * driver.
+ */
+int regulator_can_change_voltage(struct regulator *regulator)
+{
+       struct regulator_dev    *rdev = regulator->rdev;
+
+       if (rdev->constraints &&
+           rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE &&
+           rdev->desc->n_voltages > 1)
+               return 1;
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(regulator_can_change_voltage);
+
 /**
  * regulator_count_voltages - count regulator_list_voltage() selectors
  * @regulator: regulator source
@@ -1985,6 +2012,11 @@ int regulator_is_supported_voltage(struct regulator *regulator,
                        return ret;
        }
 
+       /* Any voltage within constrains range is fine? */
+       if (rdev->desc->continuous_voltage_range)
+               return min_uV >= rdev->constraints->min_uV &&
+                               max_uV <= rdev->constraints->max_uV;
+
        ret = regulator_count_voltages(regulator);
        if (ret < 0)
                return ret;
index 36c5b92fe0af26487cb093234800d534061c41f6..2afa5730f324ba1ef1bb068b5f63c79e41c11a8f 100644 (file)
@@ -460,7 +460,7 @@ static inline struct da903x_regulator_info *find_regulator_info(int id)
        return NULL;
 }
 
-static int __devinit da903x_regulator_probe(struct platform_device *pdev)
+static int da903x_regulator_probe(struct platform_device *pdev)
 {
        struct da903x_regulator_info *ri = NULL;
        struct regulator_dev *rdev;
@@ -499,7 +499,7 @@ static int __devinit da903x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit da903x_regulator_remove(struct platform_device *pdev)
+static int da903x_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -513,7 +513,7 @@ static struct platform_driver da903x_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = da903x_regulator_probe,
-       .remove         = __devexit_p(da903x_regulator_remove),
+       .remove         = da903x_regulator_remove,
 };
 
 static int __init da903x_regulator_init(void)
index 27355b1199e571ed090f24c5799dce5511d2cc94..d0963090442d220f69ebecb8c6dbbf22866b62f8 100644 (file)
@@ -129,17 +129,17 @@ static int da9052_dcdc_set_current_limit(struct regulator_dev *rdev, int min_uA,
        else if (offset == 0)
                row = 1;
 
-       if (min_uA > da9052_current_limits[row][DA9052_MAX_UA] ||
-           max_uA < da9052_current_limits[row][DA9052_MIN_UA])
-               return -EINVAL;
-
        for (i = DA9052_CURRENT_RANGE - 1; i >= 0; i--) {
-               if (da9052_current_limits[row][i] <= max_uA) {
+               if ((min_uA <= da9052_current_limits[row][i]) &&
+                   (da9052_current_limits[row][i] <= max_uA)) {
                        reg_val = i;
                        break;
                }
        }
 
+       if (i < 0)
+               return -EINVAL;
+
        /* Determine the even or odd position of the buck current limit
         * register field
        */
@@ -365,7 +365,7 @@ static inline struct da9052_regulator_info *find_regulator_info(u8 chip_id,
        return NULL;
 }
 
-static int __devinit da9052_regulator_probe(struct platform_device *pdev)
+static int da9052_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_config config = { };
        struct da9052_regulator *regulator;
@@ -430,7 +430,7 @@ static int __devinit da9052_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit da9052_regulator_remove(struct platform_device *pdev)
+static int da9052_regulator_remove(struct platform_device *pdev)
 {
        struct da9052_regulator *regulator = platform_get_drvdata(pdev);
 
@@ -440,7 +440,7 @@ static int __devexit da9052_regulator_remove(struct platform_device *pdev)
 
 static struct platform_driver da9052_regulator_driver = {
        .probe = da9052_regulator_probe,
-       .remove = __devexit_p(da9052_regulator_remove),
+       .remove = da9052_regulator_remove,
        .driver = {
                .name = "da9052-regulator",
                .owner = THIS_MODULE,
diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c
new file mode 100644 (file)
index 0000000..db59ce7
--- /dev/null
@@ -0,0 +1,680 @@
+/*
+* Regulator driver for DA9055 PMIC
+*
+* Copyright(c) 2012 Dialog Semiconductor Ltd.
+*
+* Author: David Dajun Chen <dchen@diasemi.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.
+*
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/gpio.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+
+#include <linux/mfd/da9055/core.h>
+#include <linux/mfd/da9055/reg.h>
+#include <linux/mfd/da9055/pdata.h>
+
+#define DA9055_MIN_UA          0
+#define DA9055_MAX_UA          3
+
+#define DA9055_LDO_MODE_SYNC   0
+#define DA9055_LDO_MODE_SLEEP  1
+
+#define DA9055_BUCK_MODE_SLEEP 1
+#define DA9055_BUCK_MODE_SYNC  2
+#define DA9055_BUCK_MODE_AUTO  3
+
+/* DA9055 REGULATOR IDs */
+#define DA9055_ID_BUCK1        0
+#define DA9055_ID_BUCK2        1
+#define DA9055_ID_LDO1         2
+#define DA9055_ID_LDO2         3
+#define DA9055_ID_LDO3         4
+#define DA9055_ID_LDO4         5
+#define DA9055_ID_LDO5         6
+#define DA9055_ID_LDO6         7
+
+/* DA9055 BUCK current limit */
+static const int da9055_current_limits[] = { 500000, 600000, 700000, 800000 };
+
+struct da9055_conf_reg {
+       int reg;
+       int sel_mask;
+       int en_mask;
+};
+
+struct da9055_volt_reg {
+       int reg_a;
+       int reg_b;
+       int sl_shift;
+       int v_offset;
+       int v_mask;
+       int v_shift;
+};
+
+struct da9055_mode_reg {
+       int reg;
+       int mask;
+       int shift;
+};
+
+struct da9055_regulator_info {
+       struct regulator_desc reg_desc;
+       struct da9055_conf_reg conf;
+       struct da9055_volt_reg volt;
+       struct da9055_mode_reg mode;
+};
+
+struct da9055_regulator {
+       struct da9055 *da9055;
+       struct da9055_regulator_info *info;
+       struct regulator_dev *rdev;
+       enum gpio_select reg_rselect;
+};
+
+static unsigned int da9055_buck_get_mode(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret, mode = 0;
+
+       ret = da9055_reg_read(regulator->da9055, info->mode.reg);
+       if (ret < 0)
+               return ret;
+
+       switch ((ret & info->mode.mask) >> info->mode.shift) {
+       case DA9055_BUCK_MODE_SYNC:
+               mode = REGULATOR_MODE_FAST;
+               break;
+       case DA9055_BUCK_MODE_AUTO:
+               mode = REGULATOR_MODE_NORMAL;
+               break;
+       case DA9055_BUCK_MODE_SLEEP:
+               mode = REGULATOR_MODE_STANDBY;
+               break;
+       }
+
+       return mode;
+}
+
+static int da9055_buck_set_mode(struct regulator_dev *rdev,
+                                       unsigned int mode)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int val = 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = DA9055_BUCK_MODE_SYNC << info->mode.shift;
+               break;
+       case REGULATOR_MODE_NORMAL:
+               val = DA9055_BUCK_MODE_AUTO << info->mode.shift;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               val = DA9055_BUCK_MODE_SLEEP << info->mode.shift;
+               break;
+       }
+
+       return da9055_reg_update(regulator->da9055, info->mode.reg,
+                                info->mode.mask, val);
+}
+
+static unsigned int da9055_ldo_get_mode(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       ret = da9055_reg_read(regulator->da9055, info->volt.reg_b);
+       if (ret < 0)
+               return ret;
+
+       if (ret >> info->volt.sl_shift)
+               return REGULATOR_MODE_STANDBY;
+       else
+               return REGULATOR_MODE_NORMAL;
+}
+
+static int da9055_ldo_set_mode(struct regulator_dev *rdev, unsigned int mode)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       struct da9055_volt_reg volt = info->volt;
+       int val = 0;
+
+       switch (mode) {
+       case REGULATOR_MODE_NORMAL:
+       case REGULATOR_MODE_FAST:
+               val = DA9055_LDO_MODE_SYNC;
+               break;
+       case REGULATOR_MODE_STANDBY:
+               val = DA9055_LDO_MODE_SLEEP;
+               break;
+       }
+
+       return da9055_reg_update(regulator->da9055, volt.reg_b,
+                                1 << volt.sl_shift,
+                                val << volt.sl_shift);
+}
+
+static int da9055_buck_get_current_limit(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       ret = da9055_reg_read(regulator->da9055, DA9055_REG_BUCK_LIM);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->mode.mask;
+       return da9055_current_limits[ret >> info->mode.shift];
+}
+
+static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA,
+                                        int max_uA)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int i;
+
+       for (i = ARRAY_SIZE(da9055_current_limits) - 1; i >= 0; i--) {
+               if ((min_uA <= da9055_current_limits[i]) &&
+                   (da9055_current_limits[i] <= max_uA))
+                       return da9055_reg_update(regulator->da9055,
+                                                DA9055_REG_BUCK_LIM,
+                                                info->mode.mask,
+                                                i << info->mode.shift);
+       }
+
+       return -EINVAL;
+}
+
+static int da9055_list_voltage(struct regulator_dev *rdev, unsigned selector)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+
+       if (selector >= rdev->desc->n_voltages)
+               return -EINVAL;
+
+       if (selector < info->volt.v_offset)
+               return 0;
+
+       selector -= info->volt.v_offset;
+       return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
+}
+
+static int da9055_map_voltage(struct regulator_dev *rdev, int min_uV,
+                             int max_uV)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int sel, voltage;
+
+       if (min_uV < rdev->desc->min_uV)
+               min_uV = rdev->desc->min_uV;
+
+       sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
+       sel += info->volt.v_offset;
+
+       voltage = da9055_list_voltage(rdev, sel);
+       if (voltage < min_uV || voltage > max_uV)
+               return -EINVAL;
+
+       return sel;
+}
+
+static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       struct da9055_volt_reg volt = info->volt;
+       int ret, sel;
+
+       /*
+        * There are two voltage register set A & B for voltage ramping but
+        * either one of then can be active therefore we first determine
+        * the active register set.
+        */
+       ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->conf.sel_mask;
+
+       /* Get the voltage for the active register set A/B */
+       if (ret == DA9055_REGUALTOR_SET_A)
+               ret = da9055_reg_read(regulator->da9055, volt.reg_a);
+       else
+               ret = da9055_reg_read(regulator->da9055, volt.reg_b);
+
+       if (ret < 0)
+               return ret;
+
+       sel = (ret & volt.v_mask);
+       if (sel <= volt.v_offset)
+               return 0;
+       else
+               return sel;
+}
+
+static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev,
+                                           unsigned int selector)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       /*
+        * Regulator register set A/B is not selected through GPIO therefore
+        * we use default register set A for voltage ramping.
+        */
+       if (regulator->reg_rselect == NO_GPIO) {
+               /* Select register set A */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_A);
+               if (ret < 0)
+                       return ret;
+
+               /* Set the voltage */
+               return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+                                        info->volt.v_mask, selector);
+       }
+
+       /*
+        * Here regulator register set A/B is selected through GPIO.
+        * Therefore we first determine the selected register set A/B and
+        * then set the desired voltage for that register set A/B.
+        */
+       ret = da9055_reg_read(regulator->da9055, info->conf.reg);
+       if (ret < 0)
+               return ret;
+
+       ret &= info->conf.sel_mask;
+
+       /* Set the voltage */
+       if (ret == DA9055_REGUALTOR_SET_A)
+               return da9055_reg_update(regulator->da9055, info->volt.reg_a,
+                                        info->volt.v_mask, selector);
+       else
+               return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+                                        info->volt.v_mask, selector);
+}
+
+static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev,
+                                               int uV)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+       int ret;
+
+       /* Select register set B for suspend voltage ramping. */
+       if (regulator->reg_rselect == NO_GPIO) {
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_B);
+               if (ret < 0)
+                       return ret;
+       }
+
+       ret = da9055_map_voltage(rdev, uV, uV);
+       if (ret < 0)
+               return ret;
+
+       return da9055_reg_update(regulator->da9055, info->volt.reg_b,
+                                info->volt.v_mask, ret);
+}
+
+static int da9055_suspend_enable(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+
+       /* Select register set B for voltage ramping. */
+       if (regulator->reg_rselect == NO_GPIO)
+               return da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_B);
+       else
+               return 0;
+}
+
+static int da9055_suspend_disable(struct regulator_dev *rdev)
+{
+       struct da9055_regulator *regulator = rdev_get_drvdata(rdev);
+       struct da9055_regulator_info *info = regulator->info;
+
+       /* Diselect register set B. */
+       if (regulator->reg_rselect == NO_GPIO)
+               return da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       info->conf.sel_mask, DA9055_SEL_REG_A);
+       else
+               return 0;
+}
+
+static struct regulator_ops da9055_buck_ops = {
+       .get_mode = da9055_buck_get_mode,
+       .set_mode = da9055_buck_set_mode,
+
+       .get_current_limit = da9055_buck_get_current_limit,
+       .set_current_limit = da9055_buck_set_current_limit,
+
+       .get_voltage_sel = da9055_regulator_get_voltage_sel,
+       .set_voltage_sel = da9055_regulator_set_voltage_sel,
+       .list_voltage = da9055_list_voltage,
+       .map_voltage = da9055_map_voltage,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+
+       .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+       .set_suspend_enable = da9055_suspend_enable,
+       .set_suspend_disable = da9055_suspend_disable,
+       .set_suspend_mode = da9055_buck_set_mode,
+};
+
+static struct regulator_ops da9055_ldo_ops = {
+       .get_mode = da9055_ldo_get_mode,
+       .set_mode = da9055_ldo_set_mode,
+
+       .get_voltage_sel = da9055_regulator_get_voltage_sel,
+       .set_voltage_sel = da9055_regulator_set_voltage_sel,
+       .list_voltage = da9055_list_voltage,
+       .map_voltage = da9055_map_voltage,
+       .is_enabled = regulator_is_enabled_regmap,
+       .enable = regulator_enable_regmap,
+       .disable = regulator_disable_regmap,
+
+       .set_suspend_voltage = da9055_regulator_set_suspend_voltage,
+       .set_suspend_enable = da9055_suspend_enable,
+       .set_suspend_disable = da9055_suspend_disable,
+       .set_suspend_mode = da9055_ldo_set_mode,
+
+};
+
+#define DA9055_LDO(_id, step, min, max, vbits, voffset) \
+{\
+       .reg_desc = {\
+               .name = #_id,\
+               .ops = &da9055_ldo_ops,\
+               .type = REGULATOR_VOLTAGE,\
+               .id = DA9055_ID_##_id,\
+               .n_voltages = (max - min) / step + 1 + (voffset), \
+               .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .enable_mask = 1, \
+               .min_uV = (min) * 1000,\
+               .uV_step = (step) * 1000,\
+               .owner = THIS_MODULE,\
+       },\
+       .conf = {\
+               .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .sel_mask = (1 << 4),\
+               .en_mask = 1,\
+       },\
+       .volt = {\
+               .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+               .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+               .sl_shift = 7,\
+               .v_offset = (voffset),\
+               .v_mask = (1 << (vbits)) - 1,\
+               .v_shift = (vbits),\
+       },\
+}
+
+#define DA9055_BUCK(_id, step, min, max, vbits, voffset, mbits, sbits) \
+{\
+       .reg_desc = {\
+               .name = #_id,\
+               .ops = &da9055_buck_ops,\
+               .type = REGULATOR_VOLTAGE,\
+               .id = DA9055_ID_##_id,\
+               .n_voltages = (max - min) / step + 1 + (voffset), \
+               .enable_reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .enable_mask = 1,\
+               .min_uV = (min) * 1000,\
+               .uV_step = (step) * 1000,\
+               .owner = THIS_MODULE,\
+       },\
+       .conf = {\
+               .reg = DA9055_REG_BCORE_CONT + DA9055_ID_##_id, \
+               .sel_mask = (1 << 4),\
+               .en_mask = 1,\
+       },\
+       .volt = {\
+               .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \
+               .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \
+               .sl_shift = 7,\
+               .v_offset = (voffset),\
+               .v_mask = (1 << (vbits)) - 1,\
+               .v_shift = (vbits),\
+       },\
+       .mode = {\
+               .reg = DA9055_REG_BCORE_MODE,\
+               .mask = (mbits),\
+               .shift = (sbits),\
+       },\
+}
+
+static struct da9055_regulator_info da9055_regulator_info[] = {
+       DA9055_BUCK(BUCK1, 25, 725, 2075, 6, 9, 0xc, 2),
+       DA9055_BUCK(BUCK2, 25, 925, 2500, 6, 0, 3, 0),
+       DA9055_LDO(LDO1, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO2, 50, 900, 3300, 6, 3),
+       DA9055_LDO(LDO3, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO4, 50, 900, 3300, 6, 2),
+       DA9055_LDO(LDO5, 50, 900, 2750, 6, 2),
+       DA9055_LDO(LDO6, 20, 900, 3300, 7, 0),
+};
+
+/*
+ * Configures regulator to be controlled either through GPIO 1 or 2.
+ * GPIO can control regulator state and/or select the regulator register
+ * set A/B for voltage ramping.
+ */
+static __devinit int da9055_gpio_init(struct da9055_regulator *regulator,
+                                     struct regulator_config *config,
+                                     struct da9055_pdata *pdata, int id)
+{
+       struct da9055_regulator_info *info = regulator->info;
+       int ret = 0;
+
+       if (pdata->gpio_ren && pdata->gpio_ren[id]) {
+               char name[18];
+               int gpio_mux = pdata->gpio_ren[id];
+
+               config->ena_gpio = pdata->ena_gpio[id];
+               config->ena_gpio_flags = GPIOF_OUT_INIT_HIGH;
+               config->ena_gpio_invert = 1;
+
+               /*
+                * GPI pin is muxed with regulator to control the
+                * regulator state.
+                */
+               sprintf(name, "DA9055 GPI %d", gpio_mux);
+               ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+                                           name);
+               if (ret < 0)
+                       goto err;
+
+               /*
+                * Let the regulator know that its state is controlled
+                * through GPI.
+                */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       DA9055_E_GPI_MASK,
+                                       pdata->reg_ren[id]
+                                       << DA9055_E_GPI_SHIFT);
+               if (ret < 0)
+                       goto err;
+       }
+
+       if (pdata->gpio_rsel && pdata->gpio_rsel[id]) {
+               char name[18];
+               int gpio_mux = pdata->gpio_rsel[id];
+
+               regulator->reg_rselect = pdata->reg_rsel[id];
+
+               /*
+                * GPI pin is muxed with regulator to select the
+                * regulator register set A/B for voltage ramping.
+                */
+               sprintf(name, "DA9055 GPI %d", gpio_mux);
+               ret = devm_gpio_request_one(config->dev, gpio_mux, GPIOF_DIR_IN,
+                                           name);
+               if (ret < 0)
+                       goto err;
+
+               /*
+                * Let the regulator know that its register set A/B
+                * will be selected through GPI for voltage ramping.
+                */
+               ret = da9055_reg_update(regulator->da9055, info->conf.reg,
+                                       DA9055_V_GPI_MASK,
+                                       pdata->reg_rsel[id]
+                                       << DA9055_V_GPI_SHIFT);
+       }
+
+err:
+       return ret;
+}
+
+static irqreturn_t da9055_ldo5_6_oc_irq(int irq, void *data)
+{
+       struct da9055_regulator *regulator = data;
+
+       regulator_notifier_call_chain(regulator->rdev,
+                                     REGULATOR_EVENT_OVER_CURRENT, NULL);
+
+       return IRQ_HANDLED;
+}
+
+static inline struct da9055_regulator_info *find_regulator_info(int id)
+{
+       struct da9055_regulator_info *info;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(da9055_regulator_info); i++) {
+               info = &da9055_regulator_info[i];
+               if (info->reg_desc.id == id)
+                       return info;
+       }
+
+       return NULL;
+}
+
+static int __devinit da9055_regulator_probe(struct platform_device *pdev)
+{
+       struct regulator_config config = { };
+       struct da9055_regulator *regulator;
+       struct da9055 *da9055 = dev_get_drvdata(pdev->dev.parent);
+       struct da9055_pdata *pdata = da9055->dev->platform_data;
+       int ret, irq;
+
+       if (pdata == NULL || pdata->regulators[pdev->id] == NULL)
+               return -ENODEV;
+
+       regulator = devm_kzalloc(&pdev->dev, sizeof(struct da9055_regulator),
+                                GFP_KERNEL);
+       if (!regulator)
+               return -ENOMEM;
+
+       regulator->info = find_regulator_info(pdev->id);
+       if (regulator->info == NULL) {
+               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+               return -EINVAL;
+       }
+
+       regulator->da9055 = da9055;
+       config.dev = &pdev->dev;
+       config.driver_data = regulator;
+       config.regmap = da9055->regmap;
+
+       if (pdata && pdata->regulators)
+               config.init_data = pdata->regulators[pdev->id];
+
+       ret = da9055_gpio_init(regulator, &config, pdata, pdev->id);
+       if (ret < 0)
+               return ret;
+
+       regulator->rdev = regulator_register(&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;
+       }
+
+       /* Only LDO 5 and 6 has got the over current interrupt */
+       if (pdev->id == DA9055_ID_LDO5 || pdev->id ==  DA9055_ID_LDO6) {
+               irq = platform_get_irq_byname(pdev, "REGULATOR");
+               irq = regmap_irq_get_virq(da9055->irq_data, irq);
+               ret = devm_request_threaded_irq(&pdev->dev, irq, NULL,
+                                               da9055_ldo5_6_oc_irq,
+                                               IRQF_TRIGGER_HIGH |
+                                               IRQF_ONESHOT |
+                                               IRQF_PROBE_SHARED,
+                                               pdev->name, regulator);
+               if (ret != 0) {
+                       if (ret != -EBUSY) {
+                               dev_err(&pdev->dev,
+                               "Failed to request Regulator IRQ %d: %d\n",
+                               irq, ret);
+                               goto err_regulator;
+                       }
+               }
+       }
+
+       platform_set_drvdata(pdev, regulator);
+
+       return 0;
+
+err_regulator:
+       regulator_unregister(regulator->rdev);
+       return ret;
+}
+
+static int __devexit 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 = __devexit_p(da9055_regulator_remove),
+       .driver = {
+               .name = "da9055-regulator",
+               .owner = THIS_MODULE,
+       },
+};
+
+static int __init da9055_regulator_init(void)
+{
+       return platform_driver_register(&da9055_regulator_driver);
+}
+subsys_initcall(da9055_regulator_init);
+
+static void __exit da9055_regulator_exit(void)
+{
+       platform_driver_unregister(&da9055_regulator_driver);
+}
+module_exit(da9055_regulator_exit);
+
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_DESCRIPTION("Power Regulator driver for Dialog DA9055 PMIC");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9055-regulator");
index 359f8d18fc3f35f03f0314661aba33def33846f7..219d162b651e3c75f2077517e5b3e0b69c28100f 100644 (file)
@@ -412,7 +412,7 @@ dbx500_regulator_info[DB8500_NUM_REGULATORS] = {
        },
 };
 
-static __devinit int db8500_regulator_register(struct platform_device *pdev,
+static int db8500_regulator_register(struct platform_device *pdev,
                                        struct regulator_init_data *init_data,
                                        int id,
                                        struct device_node *np)
@@ -474,7 +474,7 @@ static struct of_regulator_match db8500_regulator_matches[] = {
        { .name = "db8500_esram34_ret",   .driver_data = (void *) DB8500_REGULATOR_SWITCH_ESRAM34RET, },
 };
 
-static __devinit int
+static int
 db8500_regulator_of_probe(struct platform_device *pdev,
                        struct device_node *np)
 {
@@ -491,7 +491,7 @@ db8500_regulator_of_probe(struct platform_device *pdev,
        return 0;
 }
 
-static int __devinit db8500_regulator_probe(struct platform_device *pdev)
+static int db8500_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_init_data *db8500_init_data =
                                        dev_get_platdata(&pdev->dev);
index f2e5ecdc586424ba1f92947ee5c31f1ce3268cad..261f3d2299bc0a5d2d074824211172be7a6b8448 100644 (file)
@@ -173,7 +173,7 @@ int __attribute__((weak)) dbx500_regulator_testcase(
        return 0;
 }
 
-int __devinit
+int
 ux500_regulator_debug_init(struct platform_device *pdev,
        struct dbx500_regulator_info *regulator_info,
        int num_regulators)
@@ -230,7 +230,7 @@ exit_no_debugfs:
        return -ENOMEM;
 }
 
-int __devexit ux500_regulator_debug_exit(void)
+int ux500_regulator_debug_exit(void)
 {
        debugfs_remove_recursive(rdebug.dir);
        kfree(rdebug.state_after_suspend);
index 03a1d7c11ef2b5c9ce0d07c91517673cf83d30bb..df9f42524abb3fd1164f61e7bee4065985d59d24 100644 (file)
@@ -37,7 +37,7 @@ static struct regulator_desc dummy_desc = {
        .ops = &dummy_ops,
 };
 
-static int __devinit dummy_regulator_probe(struct platform_device *pdev)
+static int dummy_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_config config = { };
        int ret;
index 339f4d732e973e5c4ca543d869da368af80a90c3..9165b0c40ed32a6b4e8a851e5c81f9b1f68f8be0 100644 (file)
@@ -230,7 +230,7 @@ static struct regmap_config fan53555_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit fan53555_regulator_probe(struct i2c_client *client,
+static int fan53555_regulator_probe(struct i2c_client *client,
                                const struct i2c_device_id *id)
 {
        struct fan53555_device_info *di;
@@ -293,7 +293,7 @@ static int __devinit fan53555_regulator_probe(struct i2c_client *client,
 
 }
 
-static int __devexit fan53555_regulator_remove(struct i2c_client *client)
+static int fan53555_regulator_remove(struct i2c_client *client)
 {
        struct fan53555_device_info *di = i2c_get_clientdata(client);
 
@@ -311,7 +311,7 @@ static struct i2c_driver fan53555_regulator_driver = {
                .name = "fan53555-regulator",
        },
        .probe = fan53555_regulator_probe,
-       .remove = __devexit_p(fan53555_regulator_remove),
+       .remove = fan53555_regulator_remove,
        .id_table = fan53555_id,
 };
 
index 185468c4d38fcbe691c7842ca9a0f50068ca5e25..48d5b7608b00bd519cbb4c2434721335c91fa4d4 100644 (file)
@@ -134,7 +134,7 @@ static struct regulator_ops fixed_voltage_ops = {
        .list_voltage = fixed_voltage_list_voltage,
 };
 
-static int __devinit reg_fixed_voltage_probe(struct platform_device *pdev)
+static int reg_fixed_voltage_probe(struct platform_device *pdev)
 {
        struct fixed_voltage_config *config;
        struct fixed_voltage_data *drvdata;
@@ -234,7 +234,7 @@ err:
        return ret;
 }
 
-static int __devexit reg_fixed_voltage_remove(struct platform_device *pdev)
+static int reg_fixed_voltage_remove(struct platform_device *pdev)
 {
        struct fixed_voltage_data *drvdata = platform_get_drvdata(pdev);
 
@@ -255,7 +255,7 @@ MODULE_DEVICE_TABLE(of, fixed_of_match);
 
 static struct platform_driver regulator_fixed_voltage_driver = {
        .probe          = reg_fixed_voltage_probe,
-       .remove         = __devexit_p(reg_fixed_voltage_remove),
+       .remove         = reg_fixed_voltage_remove,
        .driver         = {
                .name           = "reg-fixed-voltage",
                .owner          = THIS_MODULE,
index 8b5944f2d7d1ddd36e82e92d786770e469743dfe..2cfd9d3079e80ede35a5c61ff8314b820e8e2800 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/regulator/gpio-regulator.h>
 #include <linux/gpio.h>
 #include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_gpio.h>
 
 struct gpio_regulator_data {
        struct regulator_desc desc;
@@ -129,18 +132,108 @@ static struct regulator_ops gpio_regulator_voltage_ops = {
        .list_voltage = gpio_regulator_list_voltage,
 };
 
+struct gpio_regulator_config *
+of_get_gpio_regulator_config(struct device *dev, struct device_node *np)
+{
+       struct gpio_regulator_config *config;
+       struct property *prop;
+       const char *regtype;
+       int proplen, gpio, i;
+
+       config = devm_kzalloc(dev,
+                       sizeof(struct gpio_regulator_config),
+                       GFP_KERNEL);
+       if (!config)
+               return ERR_PTR(-ENOMEM);
+
+       config->init_data = of_get_regulator_init_data(dev, np);
+       if (!config->init_data)
+               return ERR_PTR(-EINVAL);
+
+       config->supply_name = config->init_data->constraints.name;
+
+       if (of_property_read_bool(np, "enable-active-high"))
+               config->enable_high = true;
+
+       if (of_property_read_bool(np, "enable-at-boot"))
+               config->enabled_at_boot = true;
+
+       of_property_read_u32(np, "startup-delay-us", &config->startup_delay);
+
+       config->enable_gpio = of_get_named_gpio(np, "enable-gpio", 0);
+
+       /* Fetch GPIOs. */
+       for (i = 0; ; i++)
+               if (of_get_named_gpio(np, "gpios", i) < 0)
+                       break;
+       config->nr_gpios = i;
+
+       config->gpios = devm_kzalloc(dev,
+                               sizeof(struct gpio) * config->nr_gpios,
+                               GFP_KERNEL);
+       if (!config->gpios)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; config->nr_gpios; i++) {
+               gpio = of_get_named_gpio(np, "gpios", i);
+               if (gpio < 0)
+                       break;
+               config->gpios[i].gpio = gpio;
+       }
+
+       /* Fetch states. */
+       prop = of_find_property(np, "states", NULL);
+       if (!prop) {
+               dev_err(dev, "No 'states' property found\n");
+               return ERR_PTR(-EINVAL);
+       }
+
+       proplen = prop->length / sizeof(int);
+
+       config->states = devm_kzalloc(dev,
+                               sizeof(struct gpio_regulator_state)
+                               * (proplen / 2),
+                               GFP_KERNEL);
+       if (!config->states)
+               return ERR_PTR(-ENOMEM);
+
+       for (i = 0; i < proplen / 2; i++) {
+               config->states[i].value =
+                       be32_to_cpup((int *)prop->value + (i * 2));
+               config->states[i].gpios =
+                       be32_to_cpup((int *)prop->value + (i * 2 + 1));
+       }
+       config->nr_states = i;
+
+       of_property_read_string(np, "regulator-type", &regtype);
+
+       if (!strncmp("voltage", regtype, 7))
+               config->type = REGULATOR_VOLTAGE;
+       else if (!strncmp("current", regtype, 7))
+               config->type = REGULATOR_CURRENT;
+
+       return config;
+}
+
 static struct regulator_ops gpio_regulator_current_ops = {
        .get_current_limit = gpio_regulator_get_value,
        .set_current_limit = gpio_regulator_set_current_limit,
 };
 
-static int __devinit gpio_regulator_probe(struct platform_device *pdev)
+static int gpio_regulator_probe(struct platform_device *pdev)
 {
        struct gpio_regulator_config *config = pdev->dev.platform_data;
+       struct device_node *np = pdev->dev.of_node;
        struct gpio_regulator_data *drvdata;
        struct regulator_config cfg = { };
        int ptr, ret, state;
 
+       if (np) {
+               config = of_get_gpio_regulator_config(&pdev->dev, np);
+               if (IS_ERR(config))
+                       return PTR_ERR(config);
+       }
+
        drvdata = devm_kzalloc(&pdev->dev, sizeof(struct gpio_regulator_data),
                               GFP_KERNEL);
        if (drvdata == NULL) {
@@ -215,6 +308,7 @@ static int __devinit gpio_regulator_probe(struct platform_device *pdev)
        cfg.dev = &pdev->dev;
        cfg.init_data = config->init_data;
        cfg.driver_data = drvdata;
+       cfg.of_node = np;
 
        if (config->enable_gpio >= 0)
                cfg.ena_gpio = config->enable_gpio;
@@ -254,7 +348,7 @@ err:
        return ret;
 }
 
-static int __devexit gpio_regulator_remove(struct platform_device *pdev)
+static int gpio_regulator_remove(struct platform_device *pdev)
 {
        struct gpio_regulator_data *drvdata = platform_get_drvdata(pdev);
 
@@ -270,12 +364,20 @@ static int __devexit gpio_regulator_remove(struct platform_device *pdev)
        return 0;
 }
 
+#if defined(CONFIG_OF)
+static const struct of_device_id regulator_gpio_of_match[] __devinitconst = {
+       { .compatible = "regulator-gpio", },
+       {},
+};
+#endif
+
 static struct platform_driver gpio_regulator_driver = {
        .probe          = gpio_regulator_probe,
-       .remove         = __devexit_p(gpio_regulator_remove),
+       .remove         = gpio_regulator_remove,
        .driver         = {
                .name           = "gpio-regulator",
                .owner          = THIS_MODULE,
+               .of_match_table = of_match_ptr(regulator_gpio_of_match),
        },
 };
 
index d8ecf49a5777e383876aae1f5894adc43d0bf741..d1e5bee2a26b210685290f7bb98d0a5138315a87 100644 (file)
@@ -106,7 +106,7 @@ static const struct regulator_desc isl_rd[] = {
        },
 };
 
-static int __devinit isl6271a_probe(struct i2c_client *i2c,
+static int isl6271a_probe(struct i2c_client *i2c,
                                     const struct i2c_device_id *id)
 {
        struct regulator_config config = { };
@@ -151,7 +151,7 @@ error:
        return err;
 }
 
-static int __devexit isl6271a_remove(struct i2c_client *i2c)
+static int isl6271a_remove(struct i2c_client *i2c)
 {
        struct isl_pmic *pmic = i2c_get_clientdata(i2c);
        int i;
@@ -174,7 +174,7 @@ static struct i2c_driver isl6271a_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = isl6271a_probe,
-       .remove = __devexit_p(isl6271a_remove),
+       .remove = isl6271a_remove,
        .id_table = isl6271a_id,
 };
 
index 7c6e3b8ff484ad03ab60fd25d07f74d80395a65f..5f68ff11a2985bb6519d0b5d4f2a8c1e89ce9e05 100644 (file)
@@ -386,7 +386,7 @@ static int lp3971_set_bits(struct lp3971 *lp3971, u8 reg, u16 mask, u16 val)
        return ret;
 }
 
-static int __devinit setup_regulators(struct lp3971 *lp3971,
+static int setup_regulators(struct lp3971 *lp3971,
                                      struct lp3971_platform_data *pdata)
 {
        int i, err;
@@ -429,7 +429,7 @@ err_nomem:
        return err;
 }
 
-static int __devinit lp3971_i2c_probe(struct i2c_client *i2c,
+static int lp3971_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct lp3971 *lp3971;
@@ -472,7 +472,7 @@ err_detect:
        return ret;
 }
 
-static int __devexit lp3971_i2c_remove(struct i2c_client *i2c)
+static int lp3971_i2c_remove(struct i2c_client *i2c)
 {
        struct lp3971 *lp3971 = i2c_get_clientdata(i2c);
        int i;
@@ -498,7 +498,7 @@ static struct i2c_driver lp3971_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3971_i2c_probe,
-       .remove   = __devexit_p(lp3971_i2c_remove),
+       .remove   = lp3971_i2c_remove,
        .id_table = lp3971_i2c_id,
 };
 
index 3cdc755d9b225774aabf25a1101f4aeeae591cec..69c42c318b87c5506a4f1c9548bf1a303ddc3ae3 100644 (file)
@@ -481,7 +481,7 @@ static const struct regulator_desc regulators[] = {
        },
 };
 
-static int __devinit setup_regulators(struct lp3972 *lp3972,
+static int setup_regulators(struct lp3972 *lp3972,
        struct lp3972_platform_data *pdata)
 {
        int i, err;
@@ -523,7 +523,7 @@ err_nomem:
        return err;
 }
 
-static int __devinit lp3972_i2c_probe(struct i2c_client *i2c,
+static int lp3972_i2c_probe(struct i2c_client *i2c,
                            const struct i2c_device_id *id)
 {
        struct lp3972 *lp3972;
@@ -569,7 +569,7 @@ err_detect:
        return ret;
 }
 
-static int __devexit lp3972_i2c_remove(struct i2c_client *i2c)
+static int lp3972_i2c_remove(struct i2c_client *i2c)
 {
        struct lp3972 *lp3972 = i2c_get_clientdata(i2c);
        int i;
@@ -594,7 +594,7 @@ static struct i2c_driver lp3972_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe    = lp3972_i2c_probe,
-       .remove   = __devexit_p(lp3972_i2c_remove),
+       .remove   = lp3972_i2c_remove,
        .id_table = lp3972_i2c_id,
 };
 
index 708f4b6a17dcb02ee45b26223db11fc78b3319e3..9289ead715cab59d749c56222f605195051395db 100644 (file)
@@ -893,7 +893,7 @@ err_dev:
        return ret;
 }
 
-static int __devexit lp872x_remove(struct i2c_client *cl)
+static int lp872x_remove(struct i2c_client *cl)
 {
        struct lp872x *lp = i2c_get_clientdata(cl);
 
@@ -914,7 +914,7 @@ static struct i2c_driver lp872x_driver = {
                .owner = THIS_MODULE,
        },
        .probe = lp872x_probe,
-       .remove = __devexit_p(lp872x_remove),
+       .remove = lp872x_remove,
        .id_table = lp872x_ids,
 };
 
index ba3e0aa402de84a67cfcb3ac15ee8c0555f2eb1b..aef3f2b0c5ea433e45647f1c10a7a429d416a234 100644 (file)
@@ -429,18 +429,6 @@ static struct regulator_desc lp8788_buck_desc[] = {
        },
 };
 
-static int _gpio_request(struct lp8788_buck *buck, int gpio, char *name)
-{
-       struct device *dev = buck->lp->dev;
-
-       if (!gpio_is_valid(gpio)) {
-               dev_err(dev, "invalid gpio: %d\n", gpio);
-               return -EINVAL;
-       }
-
-       return devm_gpio_request_one(dev, gpio, DVS_LOW, name);
-}
-
 static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
                                enum lp8788_buck_id id)
 {
@@ -452,7 +440,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
        switch (id) {
        case BUCK1:
                gpio = pdata->buck1_dvs->gpio;
-               ret = _gpio_request(buck, gpio, b1_name);
+               ret = devm_gpio_request_one(buck->lp->dev, gpio, DVS_LOW,
+                                           b1_name);
                if (ret)
                        return ret;
 
@@ -461,7 +450,8 @@ static int lp8788_dvs_gpio_request(struct lp8788_buck *buck,
        case BUCK2:
                for (i = 0 ; i < LP8788_NUM_BUCK2_DVS ; i++) {
                        gpio = pdata->buck2_dvs->gpio[i];
-                       ret = _gpio_request(buck, gpio, b2_name[i]);
+                       ret = devm_gpio_request_one(buck->lp->dev, gpio,
+                                                   DVS_LOW, b2_name[i]);
                        if (ret)
                                return ret;
                }
@@ -504,7 +494,7 @@ set_default_dvs_mode:
                                  default_dvs_mode[id]);
 }
 
-static __devinit int lp8788_buck_probe(struct platform_device *pdev)
+static int lp8788_buck_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -542,7 +532,7 @@ static __devinit int lp8788_buck_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_buck_remove(struct platform_device *pdev)
+static int lp8788_buck_remove(struct platform_device *pdev)
 {
        struct lp8788_buck *buck = platform_get_drvdata(pdev);
 
@@ -554,7 +544,7 @@ static int __devexit lp8788_buck_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_buck_driver = {
        .probe = lp8788_buck_probe,
-       .remove = __devexit_p(lp8788_buck_remove),
+       .remove = lp8788_buck_remove,
        .driver = {
                .name = LP8788_DEV_BUCK,
                .owner = THIS_MODULE,
index 6796eeb47dc6f65b1997f75cacc1f04cb8e7d6cf..3792741708ce65b4b0bbb3449643baef4a21b22c 100644 (file)
@@ -126,7 +126,7 @@ struct lp8788_ldo {
 };
 
 /* DLDO 1, 2, 3, 9 voltage table */
-const int lp8788_dldo1239_vtbl[] = {
+static const int lp8788_dldo1239_vtbl[] = {
        1800000, 1900000, 2000000, 2100000, 2200000, 2300000, 2400000, 2500000,
        2600000, 2700000, 2800000, 2900000, 3000000, 2850000, 2850000, 2850000,
        2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000, 2850000,
@@ -662,14 +662,6 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
                [EN_DLDO7]   = LP8788_EN_SEL_DLDO7_M,
                [EN_DLDO911] = LP8788_EN_SEL_DLDO911_M,
        };
-       u8 val[] = {
-               [EN_ALDO1]   = 0 << 5,
-               [EN_ALDO234] = 0 << 4,
-               [EN_ALDO5]   = 0 << 3,
-               [EN_ALDO7]   = 0 << 2,
-               [EN_DLDO7]   = 0 << 1,
-               [EN_DLDO911] = 0 << 0,
-       };
 
        switch (id) {
        case DLDO7:
@@ -708,11 +700,10 @@ static int lp8788_config_ldo_enable_mode(struct lp8788_ldo *ldo,
        return ret;
 
 set_default_ldo_enable_mode:
-       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id],
-                               val[enable_id]);
+       return lp8788_update_bits(lp, LP8788_EN_SEL, en_mask[enable_id], 0);
 }
 
-static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
+static int lp8788_dldo_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -749,7 +740,7 @@ static __devinit int lp8788_dldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
+static int lp8788_dldo_remove(struct platform_device *pdev)
 {
        struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -761,14 +752,14 @@ static int __devexit lp8788_dldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_dldo_driver = {
        .probe = lp8788_dldo_probe,
-       .remove = __devexit_p(lp8788_dldo_remove),
+       .remove = lp8788_dldo_remove,
        .driver = {
                .name = LP8788_DEV_DLDO,
                .owner = THIS_MODULE,
        },
 };
 
-static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
+static int lp8788_aldo_probe(struct platform_device *pdev)
 {
        struct lp8788 *lp = dev_get_drvdata(pdev->dev.parent);
        int id = pdev->id;
@@ -805,7 +796,7 @@ static __devinit int lp8788_aldo_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
+static int lp8788_aldo_remove(struct platform_device *pdev)
 {
        struct lp8788_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -817,7 +808,7 @@ static int __devexit lp8788_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver lp8788_aldo_driver = {
        .probe = lp8788_aldo_probe,
-       .remove = __devexit_p(lp8788_aldo_remove),
+       .remove = lp8788_aldo_remove,
        .driver = {
                .name = LP8788_DEV_ALDO,
                .owner = THIS_MODULE,
index ed2d3912efde22cfd043ef8e022dd3a6af074753..8c5a54f541b50964567ba739a128b0ae59ec286a 100644 (file)
@@ -159,7 +159,7 @@ static struct regulator_desc max1586_reg[] = {
        },
 };
 
-static int __devinit max1586_pmic_probe(struct i2c_client *client,
+static int max1586_pmic_probe(struct i2c_client *client,
                                        const struct i2c_device_id *i2c_id)
 {
        struct regulator_dev **rdev;
@@ -226,7 +226,7 @@ err:
        return ret;
 }
 
-static int __devexit max1586_pmic_remove(struct i2c_client *client)
+static int max1586_pmic_remove(struct i2c_client *client)
 {
        struct max1586_data *max1586 = i2c_get_clientdata(client);
        int i;
@@ -245,7 +245,7 @@ MODULE_DEVICE_TABLE(i2c, max1586_id);
 
 static struct i2c_driver max1586_pmic_driver = {
        .probe = max1586_pmic_probe,
-       .remove = __devexit_p(max1586_pmic_remove),
+       .remove = max1586_pmic_remove,
        .driver         = {
                .name   = "max1586",
                .owner  = THIS_MODULE,
index 2a67d08658add7dfcabbc1c00d4a0a02b9b70a0d..cb99e9031a64242427283975cefce6a0b83191e8 100644 (file)
@@ -280,7 +280,7 @@ static int max77686_pmic_dt_parse_pdata(struct max77686_dev *iodev,
 }
 #endif /* CONFIG_OF */
 
-static __devinit int max77686_pmic_probe(struct platform_device *pdev)
+static int max77686_pmic_probe(struct platform_device *pdev)
 {
        struct max77686_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max77686_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -337,7 +337,7 @@ err:
        return ret;
 }
 
-static int __devexit max77686_pmic_remove(struct platform_device *pdev)
+static int max77686_pmic_remove(struct platform_device *pdev)
 {
        struct max77686_data *max77686 = platform_get_drvdata(pdev);
        int i;
@@ -360,7 +360,7 @@ static struct platform_driver max77686_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max77686_pmic_probe,
-       .remove = __devexit_p(max77686_pmic_remove),
+       .remove = max77686_pmic_remove,
        .id_table = max77686_pmic_id,
 };
 
index 9d540cd02dab5f4de264dc35599322b773d6c484..3ca14380f22db06aba4338544cf62967d48fa900 100644 (file)
@@ -176,7 +176,7 @@ static struct regmap_config max8649_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit max8649_regulator_probe(struct i2c_client *client,
+static int max8649_regulator_probe(struct i2c_client *client,
                                             const struct i2c_device_id *id)
 {
        struct max8649_platform_data *pdata = client->dev.platform_data;
@@ -271,7 +271,7 @@ static int __devinit max8649_regulator_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit max8649_regulator_remove(struct i2c_client *client)
+static int max8649_regulator_remove(struct i2c_client *client)
 {
        struct max8649_regulator_info *info = i2c_get_clientdata(client);
 
@@ -291,7 +291,7 @@ MODULE_DEVICE_TABLE(i2c, max8649_id);
 
 static struct i2c_driver max8649_driver = {
        .probe          = max8649_regulator_probe,
-       .remove         = __devexit_p(max8649_regulator_remove),
+       .remove         = max8649_regulator_remove,
        .driver         = {
                .name   = "max8649",
        },
index 8d531742f593616d1145fef2aa00fd22e13f4b32..4d7c635c36c2d6cc92b1ecd8fafb9d533213ae21 100644 (file)
@@ -305,7 +305,7 @@ static const struct regulator_desc max8660_reg[] = {
        },
 };
 
-static int __devinit max8660_probe(struct i2c_client *client,
+static int max8660_probe(struct i2c_client *client,
                                   const struct i2c_device_id *i2c_id)
 {
        struct regulator_dev **rdev;
@@ -420,7 +420,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8660_remove(struct i2c_client *client)
+static int max8660_remove(struct i2c_client *client)
 {
        struct max8660 *max8660 = i2c_get_clientdata(client);
        int i;
@@ -440,7 +440,7 @@ MODULE_DEVICE_TABLE(i2c, max8660_id);
 
 static struct i2c_driver max8660_driver = {
        .probe = max8660_probe,
-       .remove = __devexit_p(max8660_remove),
+       .remove = max8660_remove,
        .driver         = {
                .name   = "max8660",
                .owner  = THIS_MODULE,
index af7607515ab951e2b688b31e0a1cffef8b8bc396..d1a77512d83e69501c2a4a3a3e8c3f09b75f7ba6 100644 (file)
@@ -275,7 +275,7 @@ static inline struct device_node *match_of_node(int index)
 }
 #endif
 
-static __devinit int max8907_regulator_probe(struct platform_device *pdev)
+static int max8907_regulator_probe(struct platform_device *pdev)
 {
        struct max8907 *max8907 = dev_get_drvdata(pdev->dev.parent);
        struct max8907_platform_data *pdata = dev_get_platdata(max8907->dev);
@@ -368,7 +368,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static __devexit int max8907_regulator_remove(struct platform_device *pdev)
+static int max8907_regulator_remove(struct platform_device *pdev)
 {
        struct max8907_regulator *pmic = platform_get_drvdata(pdev);
        int i;
@@ -385,7 +385,7 @@ static struct platform_driver max8907_regulator_driver = {
                   .owner = THIS_MODULE,
                   },
        .probe = max8907_regulator_probe,
-       .remove = __devexit_p(max8907_regulator_remove),
+       .remove = max8907_regulator_remove,
 };
 
 static int __init max8907_regulator_init(void)
index 9bb0be37495f417d65728720f2d13217d51962d5..446a854455535b4603fa2584f09498b0e557cc0e 100644 (file)
@@ -17,6 +17,8 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/max8925.h>
+#include <linux/of.h>
+#include <linux/regulator/of_regulator.h>
 
 #define SD1_DVM_VMIN           850000
 #define SD1_DVM_VMAX           1000000
@@ -187,6 +189,34 @@ static struct regulator_ops max8925_regulator_ldo_ops = {
        .enable_reg     = MAX8925_LDOCTL##_id,                  \
 }
 
+#ifdef CONFIG_OF
+static struct of_regulator_match max8925_regulator_matches[] = {
+       { .name = "SDV1",},
+       { .name = "SDV2",},
+       { .name = "SDV3",},
+       { .name = "LDO1",},
+       { .name = "LDO2",},
+       { .name = "LDO3",},
+       { .name = "LDO4",},
+       { .name = "LDO5",},
+       { .name = "LDO6",},
+       { .name = "LDO7",},
+       { .name = "LDO8",},
+       { .name = "LDO9",},
+       { .name = "LDO10",},
+       { .name = "LDO11",},
+       { .name = "LDO12",},
+       { .name = "LDO13",},
+       { .name = "LDO14",},
+       { .name = "LDO15",},
+       { .name = "LDO16",},
+       { .name = "LDO17",},
+       { .name = "LDO18",},
+       { .name = "LDO19",},
+       { .name = "LDO20",},
+};
+#endif
+
 static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_SDV(1, 637.5, 1425, 12.5),
        MAX8925_SDV(2,   650, 2225,   25),
@@ -214,7 +244,37 @@ static struct max8925_regulator_info max8925_regulator_info[] = {
        MAX8925_LDO(20, 750, 3900, 50),
 };
 
-static int __devinit max8925_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static int max8925_regulator_dt_init(struct platform_device *pdev,
+                                   struct max8925_regulator_info *info,
+                                   struct regulator_config *config,
+                                   int ridx)
+{
+       struct device_node *nproot, *np;
+       int rcount;
+       nproot = pdev->dev.parent->of_node;
+       if (!nproot)
+               return -ENODEV;
+       np = of_find_node_by_name(nproot, "regulators");
+       if (!np) {
+               dev_err(&pdev->dev, "failed to find regulators node\n");
+               return -ENODEV;
+       }
+
+       rcount = of_regulator_match(&pdev->dev, np,
+                               &max8925_regulator_matches[ridx], 1);
+       if (rcount < 0)
+               return -ENODEV;
+       config->init_data =     max8925_regulator_matches[ridx].init_data;
+       config->of_node = max8925_regulator_matches[ridx].of_node;
+
+       return 0;
+}
+#else
+#define max8925_regulator_dt_init(w, x, y, z)  (-1)
+#endif
+
+static int max8925_regulator_probe(struct platform_device *pdev)
 {
        struct max8925_chip *chip = dev_get_drvdata(pdev->dev.parent);
        struct regulator_init_data *pdata = pdev->dev.platform_data;
@@ -222,7 +282,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        struct max8925_regulator_info *ri;
        struct resource *res;
        struct regulator_dev *rdev;
-       int i;
+       int i, regulator_idx;
 
        res = platform_get_resource(pdev, IORESOURCE_REG, 0);
        if (!res) {
@@ -231,9 +291,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        }
        for (i = 0; i < ARRAY_SIZE(max8925_regulator_info); i++) {
                ri = &max8925_regulator_info[i];
-               if (ri->vol_reg == res->start)
+               if (ri->vol_reg == res->start) {
+                       regulator_idx = i;
                        break;
+               }
        }
+
        if (i == ARRAY_SIZE(max8925_regulator_info)) {
                dev_err(&pdev->dev, "Failed to find regulator %llu\n",
                        (unsigned long long)res->start);
@@ -243,9 +306,12 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        ri->chip = chip;
 
        config.dev = &pdev->dev;
-       config.init_data = pdata;
        config.driver_data = ri;
 
+       if (max8925_regulator_dt_init(pdev, ri, &config, regulator_idx))
+               if (pdata)
+                       config.init_data = pdata;
+
        rdev = regulator_register(&ri->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "failed to register regulator %s\n",
@@ -257,7 +323,7 @@ static int __devinit max8925_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit max8925_regulator_remove(struct platform_device *pdev)
+static int max8925_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -273,7 +339,7 @@ static struct platform_driver max8925_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = max8925_regulator_probe,
-       .remove         = __devexit_p(max8925_regulator_remove),
+       .remove         = max8925_regulator_remove,
 };
 
 static int __init max8925_regulator_init(void)
index 355ca7bad9d59a9583cdda44ee986ced030ab5fa..fc7935a19e3a143f996aeeb4879d4d8ba75f0e9b 100644 (file)
@@ -126,7 +126,7 @@ static const struct regulator_desc regulator = {
        .owner          = THIS_MODULE,
 };
 
-static int __devinit max8952_pmic_probe(struct i2c_client *client,
+static int max8952_pmic_probe(struct i2c_client *client,
                const struct i2c_device_id *i2c_id)
 {
        struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
@@ -247,7 +247,7 @@ static int __devinit max8952_pmic_probe(struct i2c_client *client,
        return 0;
 }
 
-static int __devexit max8952_pmic_remove(struct i2c_client *client)
+static int max8952_pmic_remove(struct i2c_client *client)
 {
        struct max8952_data *max8952 = i2c_get_clientdata(client);
        struct max8952_platform_data *pdata = max8952->pdata;
@@ -268,7 +268,7 @@ MODULE_DEVICE_TABLE(i2c, max8952_ids);
 
 static struct i2c_driver max8952_pmic_driver = {
        .probe          = max8952_pmic_probe,
-       .remove         = __devexit_p(max8952_pmic_remove),
+       .remove         = max8952_pmic_remove,
        .driver         = {
                .name   = "max8952",
        },
index e39a0c7260dca5b7fe13098dbfd06d98c4b0b3e5..cea9ec9093ebfda708119e1c54f961fd92f8443e 100644 (file)
@@ -933,7 +933,7 @@ static struct regulator_desc regulators[] = {
                                  max8997_charger_fixedstate_ops),
 };
 
-static __devinit int max8997_pmic_probe(struct platform_device *pdev)
+static int max8997_pmic_probe(struct platform_device *pdev)
 {
        struct max8997_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max8997_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -1120,7 +1120,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8997_pmic_remove(struct platform_device *pdev)
+static int max8997_pmic_remove(struct platform_device *pdev)
 {
        struct max8997_data *max8997 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = max8997->rdev;
@@ -1143,7 +1143,7 @@ static struct platform_driver max8997_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8997_pmic_probe,
-       .remove = __devexit_p(max8997_pmic_remove),
+       .remove = max8997_pmic_remove,
        .id_table = max8997_pmic_id,
 };
 
index 5dfa920ff0c8873c91e8c02176af4d722f3c3659..b821d08eb64ae84b643f2cfe93cd0764738d21c9 100644 (file)
@@ -633,7 +633,7 @@ static struct regulator_desc regulators[] = {
        }
 };
 
-static __devinit int max8998_pmic_probe(struct platform_device *pdev)
+static int max8998_pmic_probe(struct platform_device *pdev)
 {
        struct max8998_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct max8998_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -818,7 +818,7 @@ err_out:
        return ret;
 }
 
-static int __devexit max8998_pmic_remove(struct platform_device *pdev)
+static int max8998_pmic_remove(struct platform_device *pdev)
 {
        struct max8998_data *max8998 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = max8998->rdev;
@@ -842,7 +842,7 @@ static struct platform_driver max8998_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = max8998_pmic_probe,
-       .remove = __devexit_p(max8998_pmic_remove),
+       .remove = max8998_pmic_remove,
        .id_table = max8998_pmic_id,
 };
 
index 0801a6d0c122e7e7b94e75b797497728ef2a7d36..c46c6705cd74538af5b30c2c112cde1cedad4df2 100644 (file)
@@ -392,7 +392,7 @@ static struct regulator_ops mc13783_gpo_regulator_ops = {
        .set_voltage = mc13xxx_fixed_regulator_set_voltage,
 };
 
-static int __devinit mc13783_regulator_probe(struct platform_device *pdev)
+static int mc13783_regulator_probe(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv;
        struct mc13xxx *mc13783 = dev_get_drvdata(pdev->dev.parent);
@@ -445,7 +445,7 @@ err:
        return ret;
 }
 
-static int __devexit mc13783_regulator_remove(struct platform_device *pdev)
+static int mc13783_regulator_remove(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
        struct mc13xxx_regulator_platform_data *pdata =
@@ -465,7 +465,7 @@ static struct platform_driver mc13783_regulator_driver = {
                .name   = "mc13783-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove         = __devexit_p(mc13783_regulator_remove),
+       .remove         = mc13783_regulator_remove,
        .probe          = mc13783_regulator_probe,
 };
 
index 1fa63812f7ace6070dcfda38a14cd5aab0466b69..0d84b1f33199ca5251c425ba898ffad4296da88f 100644 (file)
@@ -486,7 +486,7 @@ static unsigned int mc13892_vcam_get_mode(struct regulator_dev *rdev)
 }
 
 
-static int __devinit mc13892_regulator_probe(struct platform_device *pdev)
+static int mc13892_regulator_probe(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv;
        struct mc13xxx *mc13892 = dev_get_drvdata(pdev->dev.parent);
@@ -588,7 +588,7 @@ err_unlock:
        return ret;
 }
 
-static int __devexit mc13892_regulator_remove(struct platform_device *pdev)
+static int mc13892_regulator_remove(struct platform_device *pdev)
 {
        struct mc13xxx_regulator_priv *priv = platform_get_drvdata(pdev);
        int i;
@@ -606,7 +606,7 @@ static struct platform_driver mc13892_regulator_driver = {
                .name   = "mc13892-regulator",
                .owner  = THIS_MODULE,
        },
-       .remove = __devexit_p(mc13892_regulator_remove),
+       .remove = mc13892_regulator_remove,
        .probe  = mc13892_regulator_probe,
 };
 
index 88cbb832d555207b4e7fc124aa05b4afcbcbb3f1..4ed89c6541100e838e8d6c3afb5aea3e0ad5bebf 100644 (file)
@@ -162,7 +162,7 @@ struct regulator_ops mc13xxx_fixed_regulator_ops = {
 EXPORT_SYMBOL_GPL(mc13xxx_fixed_regulator_ops);
 
 #ifdef CONFIG_OF
-int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
+int mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 {
        struct device_node *parent, *child;
        int num = 0;
@@ -179,7 +179,7 @@ int __devinit mc13xxx_get_num_regulators_dt(struct platform_device *pdev)
 }
 EXPORT_SYMBOL_GPL(mc13xxx_get_num_regulators_dt);
 
-struct mc13xxx_regulator_init_data * __devinit mc13xxx_parse_regulators_dt(
+struct mc13xxx_regulator_init_data *mc13xxx_parse_regulators_dt(
        struct platform_device *pdev, struct mc13xxx_regulator *regulators,
        int num_regulators)
 {
index 07aee694ba92abc4c8eab282b519a89dbff69ff1..3d445929cc80d8d6f9bbb199b0ceadb205edba0e 100644 (file)
@@ -595,7 +595,7 @@ static struct of_regulator_match palmas_matches[] = {
        { .name = "ldousb", },
 };
 
-static void __devinit palmas_dt_to_pdata(struct device *dev,
+static void palmas_dt_to_pdata(struct device *dev,
                struct device_node *node,
                struct palmas_pmic_platform_data *pdata)
 {
@@ -663,7 +663,7 @@ static void __devinit palmas_dt_to_pdata(struct device *dev,
 }
 
 
-static __devinit int palmas_probe(struct platform_device *pdev)
+static int palmas_probe(struct platform_device *pdev)
 {
        struct palmas *palmas = dev_get_drvdata(pdev->dev.parent);
        struct palmas_pmic_platform_data *pdata = pdev->dev.platform_data;
@@ -868,7 +868,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static int __devexit palmas_remove(struct platform_device *pdev)
+static int palmas_remove(struct platform_device *pdev)
 {
        struct palmas_pmic *pmic = platform_get_drvdata(pdev);
        int id;
@@ -890,7 +890,7 @@ static struct platform_driver palmas_driver = {
                .owner = THIS_MODULE,
        },
        .probe = palmas_probe,
-       .remove = __devexit_p(palmas_remove),
+       .remove = palmas_remove,
 };
 
 static int __init palmas_init(void)
index 68777acc099fb6da2d0d4f1428b11ef1d704f9a3..4899342f1fc12cba02790a094c4be82f5ec30b15 100644 (file)
@@ -236,7 +236,7 @@ static const struct regulator_desc pcap_regulators[] = {
        VREG(VAUX4), VREG(VSIM), VREG(VSIM2), VREG(VVIB), VREG(SW1), VREG(SW2),
 };
 
-static int __devinit pcap_regulator_probe(struct platform_device *pdev)
+static int pcap_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_dev *rdev;
        void *pcap = dev_get_drvdata(pdev->dev.parent);
@@ -255,7 +255,7 @@ static int __devinit pcap_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pcap_regulator_remove(struct platform_device *pdev)
+static int pcap_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -271,7 +271,7 @@ static struct platform_driver pcap_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe  = pcap_regulator_probe,
-       .remove = __devexit_p(pcap_regulator_remove),
+       .remove = pcap_regulator_remove,
 };
 
 static int __init pcap_regulator_init(void)
index 092e5cb848a1e3b0e30736bf6fe08823220f77aa..d776f518aa0dc0a41259844dacd98bd5d92a377c 100644 (file)
@@ -196,7 +196,7 @@ static const struct regulator_desc regulators[] = {
        [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28),
 };
 
-static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
+static int pcf50633_regulator_probe(struct platform_device *pdev)
 {
        struct regulator_dev *rdev;
        struct pcf50633 *pcf;
@@ -222,7 +222,7 @@ static int __devinit pcf50633_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit pcf50633_regulator_remove(struct platform_device *pdev)
+static int pcf50633_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -237,7 +237,7 @@ static struct platform_driver pcf50633_regulator_driver = {
                .name = "pcf50633-regltr",
        },
        .probe = pcf50633_regulator_probe,
-       .remove = __devexit_p(pcf50633_regulator_remove),
+       .remove = pcf50633_regulator_remove,
 };
 
 static int __init pcf50633_regulator_init(void)
index 8bf4e8c9de9a2a811622ff0e8986a8fea9de2735..9e6f78694bf16d66d13e9ea95e160ed631603742 100644 (file)
@@ -119,7 +119,7 @@ static struct rc5t583_regulator_info rc5t583_reg_info[RC5T583_REGULATOR_MAX] = {
        RC5T583_REG(LDO9, LDOEN1, 1, LDODIS1, 1, 0x7F, 900, 3400, 25000, 133),
 };
 
-static int __devinit rc5t583_regulator_probe(struct platform_device *pdev)
+static int rc5t583_regulator_probe(struct platform_device *pdev)
 {
        struct rc5t583 *rc5t583 = dev_get_drvdata(pdev->dev.parent);
        struct rc5t583_platform_data *pdata = dev_get_platdata(rc5t583->dev);
@@ -198,7 +198,7 @@ clean_exit:
        return ret;
 }
 
-static int __devexit rc5t583_regulator_remove(struct platform_device *pdev)
+static int rc5t583_regulator_remove(struct platform_device *pdev)
 {
        struct rc5t583_regulator *regs = platform_get_drvdata(pdev);
        int id;
@@ -214,7 +214,7 @@ static struct platform_driver rc5t583_regulator_driver = {
                .owner  = THIS_MODULE,
        },
        .probe          = rc5t583_regulator_probe,
-       .remove         = __devexit_p(rc5t583_regulator_remove),
+       .remove         = rc5t583_regulator_remove,
 };
 
 static int __init rc5t583_regulator_init(void)
index 926f9c8f2facde5b415b0e4bdc71b5fd2dc53fe6..85fc086c1319c871570ffe6ef4379ed5e2b19641 100644 (file)
@@ -231,7 +231,7 @@ static struct regulator_desc regulators[] = {
        regulator_desc_buck10,
 };
 
-static __devinit int s2mps11_pmic_probe(struct platform_device *pdev)
+static int s2mps11_pmic_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -307,7 +307,7 @@ err:
        return ret;
 }
 
-static int __devexit s2mps11_pmic_remove(struct platform_device *pdev)
+static int s2mps11_pmic_remove(struct platform_device *pdev)
 {
        struct s2mps11_info *s2mps11 = platform_get_drvdata(pdev);
        int i;
@@ -330,7 +330,7 @@ static struct platform_driver s2mps11_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s2mps11_pmic_probe,
-       .remove = __devexit_p(s2mps11_pmic_remove),
+       .remove = s2mps11_pmic_remove,
        .id_table = s2mps11_pmic_id,
 };
 
index abe64a32aedf3a4b38ee05ea7c59849b4959642c..2b822bec3c2decf898d22371d67918c5d85db10e 100644 (file)
@@ -499,7 +499,7 @@ static struct regulator_desc regulators[] = {
        s5m8767_regulator_desc(BUCK9),
 };
 
-static __devinit int s5m8767_pmic_probe(struct platform_device *pdev)
+static int s5m8767_pmic_probe(struct platform_device *pdev)
 {
        struct sec_pmic_dev *iodev = dev_get_drvdata(pdev->dev.parent);
        struct sec_platform_data *pdata = dev_get_platdata(iodev->dev);
@@ -773,7 +773,7 @@ err:
        return ret;
 }
 
-static int __devexit s5m8767_pmic_remove(struct platform_device *pdev)
+static int s5m8767_pmic_remove(struct platform_device *pdev)
 {
        struct s5m8767_info *s5m8767 = platform_get_drvdata(pdev);
        struct regulator_dev **rdev = s5m8767->rdev;
@@ -798,7 +798,7 @@ static struct platform_driver s5m8767_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = s5m8767_pmic_probe,
-       .remove = __devexit_p(s5m8767_pmic_remove),
+       .remove = s5m8767_pmic_remove,
        .id_table = s5m8767_pmic_id,
 };
 
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c
new file mode 100644 (file)
index 0000000..a9c3a4a
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * tps51632-regulator.c -- TI TPS51632
+ *
+ * Regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down Driverless
+ * Controller with serial VID control and DVFS.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; 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/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/tps51632-regulator.h>
+#include <linux/slab.h>
+
+/* Register definitions */
+#define TPS51632_VOLTAGE_SELECT_REG            0x0
+#define TPS51632_VOLTAGE_BASE_REG              0x1
+#define TPS51632_OFFSET_REG                    0x2
+#define TPS51632_IMON_REG                      0x3
+#define TPS51632_VMAX_REG                      0x4
+#define TPS51632_DVFS_CONTROL_REG              0x5
+#define TPS51632_POWER_STATE_REG               0x6
+#define TPS51632_SLEW_REGS                     0x7
+#define TPS51632_FAULT_REG                     0x14
+
+#define TPS51632_MAX_REG                       0x15
+
+#define TPS51632_VOUT_MASK                     0x7F
+#define TPS51632_VOUT_OFFSET_MASK              0x1F
+#define TPS51632_VMAX_MASK                     0x7F
+#define TPS51632_VMAX_LOCK                     0x80
+
+/* TPS51632_DVFS_CONTROL_REG */
+#define TPS51632_DVFS_PWMEN                    0x1
+#define TPS51632_DVFS_STEP_20                  0x2
+#define TPS51632_DVFS_VMAX_PG                  0x4
+#define TPS51632_DVFS_PWMRST                   0x8
+#define TPS51632_DVFS_OCA_EN                   0x10
+#define TPS51632_DVFS_FCCM                     0x20
+
+/* TPS51632_POWER_STATE_REG */
+#define TPS51632_POWER_STATE_MASK              0x03
+#define TPS51632_POWER_STATE_MULTI_PHASE_CCM   0x0
+#define TPS51632_POWER_STATE_SINGLE_PHASE_CCM  0x1
+#define TPS51632_POWER_STATE_SINGLE_PHASE_DCM  0x2
+
+#define TPS51632_MIN_VOLATGE                   500000
+#define TPS51632_MAX_VOLATGE                   1520000
+#define TPS51632_VOLATGE_STEP_10mV             10000
+#define TPS51632_VOLATGE_STEP_20mV             20000
+#define TPS51632_MAX_VSEL                      0x7F
+#define TPS51632_MIN_VSEL                      0x19
+#define TPS51632_DEFAULT_RAMP_DELAY            6000
+#define TPS51632_VOLT_VSEL(uV)                                 \
+               (DIV_ROUND_UP(uV - TPS51632_MIN_VOLATGE,        \
+                       TPS51632_VOLATGE_STEP_10mV) +           \
+                       TPS51632_MIN_VSEL)
+
+/* TPS51632 chip information */
+struct tps51632_chip {
+       struct device *dev;
+       struct regulator_desc desc;
+       struct regulator_dev *rdev;
+       struct regmap *regmap;
+       bool enable_pwm_dvfs;
+};
+
+static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+       int vsel;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       ret = regmap_read(tps->regmap, reg, &data);
+       if (ret < 0) {
+               dev_err(tps->dev, "reg read failed, err %d\n", ret);
+               return ret;
+       }
+
+       vsel = data & TPS51632_VOUT_MASK;
+
+       if (vsel < TPS51632_MIN_VSEL)
+               return 0;
+       else
+               return vsel - TPS51632_MIN_VSEL;
+}
+
+static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned selector)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int vsel;
+       int ret;
+       unsigned int reg = TPS51632_VOLTAGE_SELECT_REG;
+
+       if (tps->enable_pwm_dvfs)
+               reg = TPS51632_VOLTAGE_BASE_REG;
+
+       vsel = selector + TPS51632_MIN_VSEL;
+       if (vsel > TPS51632_MAX_VSEL)
+               return -EINVAL;
+
+       ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel);
+       if (ret < 0)
+               dev_err(tps->dev, "reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static int tps51632_dcdc_set_ramp_delay(struct regulator_dev *rdev,
+               int ramp_delay)
+{
+       struct tps51632_chip *tps = rdev_get_drvdata(rdev);
+       int bit = ramp_delay/6000;
+       int ret;
+
+       if (bit)
+               bit--;
+       ret = regmap_write(tps->regmap, TPS51632_SLEW_REGS, BIT(bit));
+       if (ret < 0)
+               dev_err(tps->dev, "SLEW reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static struct regulator_ops tps51632_dcdc_ops = {
+       .get_voltage_sel        = tps51632_dcdc_get_voltage_sel,
+       .set_voltage_sel        = tps51632_dcdc_set_voltage_sel,
+       .list_voltage           = regulator_list_voltage_linear,
+       .set_voltage_time_sel   = regulator_set_voltage_time_sel,
+       .set_ramp_delay         = tps51632_dcdc_set_ramp_delay,
+};
+
+static int tps51632_init_dcdc(struct tps51632_chip *tps,
+               struct tps51632_regulator_platform_data *pdata)
+{
+       int ret;
+       uint8_t control = 0;
+       int vsel;
+
+       if (!pdata->enable_pwm_dvfs)
+               goto skip_pwm_config;
+
+       control |= TPS51632_DVFS_PWMEN;
+       tps->enable_pwm_dvfs = pdata->enable_pwm_dvfs;
+       vsel = TPS51632_VOLT_VSEL(pdata->base_voltage_uV);
+       ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_BASE_REG, vsel);
+       if (ret < 0) {
+               dev_err(tps->dev, "BASE reg write failed, err %d\n", ret);
+               return ret;
+       }
+
+       if (pdata->dvfs_step_20mV)
+               control |= TPS51632_DVFS_STEP_20;
+
+       if (pdata->max_voltage_uV) {
+               unsigned int vmax;
+               /**
+                * TPS51632 hw behavior: VMAX register can be write only
+                * once as it get locked after first write. The lock get
+                * reset only when device is power-reset.
+                * Write register only when lock bit is not enabled.
+                */
+               ret = regmap_read(tps->regmap, TPS51632_VMAX_REG, &vmax);
+               if (ret < 0) {
+                       dev_err(tps->dev, "VMAX read failed, err %d\n", ret);
+                       return ret;
+               }
+               if (!(vmax & TPS51632_VMAX_LOCK)) {
+                       vsel = TPS51632_VOLT_VSEL(pdata->max_voltage_uV);
+                       ret = regmap_write(tps->regmap, TPS51632_VMAX_REG,
+                                       vsel);
+                       if (ret < 0) {
+                               dev_err(tps->dev,
+                                       "VMAX write failed, err %d\n", ret);
+                               return ret;
+                       }
+               }
+       }
+
+skip_pwm_config:
+       ret = regmap_write(tps->regmap, TPS51632_DVFS_CONTROL_REG, control);
+       if (ret < 0)
+               dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret);
+       return ret;
+}
+
+static bool rd_wr_reg(struct device *dev, unsigned int reg)
+{
+       if ((reg >= 0x8) && (reg <= 0x10))
+               return false;
+       return true;
+}
+
+static const struct regmap_config tps51632_regmap_config = {
+       .reg_bits               = 8,
+       .val_bits               = 8,
+       .writeable_reg          = rd_wr_reg,
+       .readable_reg           = rd_wr_reg,
+       .max_register           = TPS51632_MAX_REG - 1,
+       .cache_type             = REGCACHE_RBTREE,
+};
+
+static int tps51632_probe(struct i2c_client *client,
+                               const struct i2c_device_id *id)
+{
+       struct tps51632_regulator_platform_data *pdata;
+       struct regulator_dev *rdev;
+       struct tps51632_chip *tps;
+       int ret;
+       struct regulator_config config = { };
+
+       pdata = client->dev.platform_data;
+       if (!pdata) {
+               dev_err(&client->dev, "No Platform data\n");
+               return -EINVAL;
+       }
+
+       tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
+       if (!tps) {
+               dev_err(&client->dev, "Memory allocation failed\n");
+               return -ENOMEM;
+       }
+
+       tps->dev = &client->dev;
+       tps->desc.name = id->name;
+       tps->desc.id = 0;
+       tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY;
+       tps->desc.min_uV = TPS51632_MIN_VOLATGE;
+       tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV;
+       tps->desc.n_voltages = (TPS51632_MAX_VSEL - TPS51632_MIN_VSEL) + 1;
+       tps->desc.ops = &tps51632_dcdc_ops;
+       tps->desc.type = REGULATOR_VOLTAGE;
+       tps->desc.owner = THIS_MODULE;
+
+       tps->regmap = devm_regmap_init_i2c(client, &tps51632_regmap_config);
+       if (IS_ERR(tps->regmap)) {
+               ret = PTR_ERR(tps->regmap);
+               dev_err(&client->dev, "regmap init failed, err %d\n", ret);
+               return ret;
+       }
+       i2c_set_clientdata(client, tps);
+
+       ret = tps51632_init_dcdc(tps, pdata);
+       if (ret < 0) {
+               dev_err(tps->dev, "Init failed, err = %d\n", ret);
+               return ret;
+       }
+
+       /* Register the regulators */
+       config.dev = &client->dev;
+       config.init_data = pdata->reg_init_data;
+       config.driver_data = tps;
+       config.regmap = tps->regmap;
+       config.of_node = client->dev.of_node;
+
+       rdev = regulator_register(&tps->desc, &config);
+       if (IS_ERR(rdev)) {
+               dev_err(tps->dev, "regulator register failed\n");
+               return PTR_ERR(rdev);
+       }
+
+       tps->rdev = rdev;
+       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",},
+       {},
+};
+
+MODULE_DEVICE_TABLE(i2c, tps51632_id);
+
+static struct i2c_driver tps51632_i2c_driver = {
+       .driver = {
+               .name = "tps51632",
+               .owner = THIS_MODULE,
+       },
+       .probe = tps51632_probe,
+       .remove = tps51632_remove,
+       .id_table = tps51632_id,
+};
+
+static int __init tps51632_init(void)
+{
+       return i2c_add_driver(&tps51632_i2c_driver);
+}
+subsys_initcall(tps51632_init);
+
+static void __exit tps51632_cleanup(void)
+{
+       i2c_del_driver(&tps51632_i2c_driver);
+}
+module_exit(tps51632_cleanup);
+
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_DESCRIPTION("TPS51632 voltage regulator driver");
+MODULE_LICENSE("GPL v2");
index 1378409efaec70170b8a3c70eeb09e1402abec33..ec9453ffb77fd561ec1c2d6c3591b7302bc16b5f 100644 (file)
@@ -127,7 +127,7 @@ static const struct regulator_desc tps6105x_regulator_desc = {
 /*
  * Registers the chip as a voltage regulator
  */
-static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
+static int tps6105x_regulator_probe(struct platform_device *pdev)
 {
        struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
        struct tps6105x_platform_data *pdata = tps6105x->pdata;
@@ -159,7 +159,7 @@ static int __devinit tps6105x_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit tps6105x_regulator_remove(struct platform_device *pdev)
+static int tps6105x_regulator_remove(struct platform_device *pdev)
 {
        struct tps6105x *tps6105x = dev_get_platdata(&pdev->dev);
        regulator_unregister(tps6105x->regulator);
@@ -172,7 +172,7 @@ static struct platform_driver tps6105x_regulator_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6105x_regulator_probe,
-       .remove = __devexit_p(tps6105x_regulator_remove),
+       .remove = tps6105x_regulator_remove,
 };
 
 static __init int tps6105x_regulator_init(void)
index 68729a7c8709fbcbc8e88e8cf99924afc2e69f18..acbd63fde4153fb7ffe9cf3a8b22dd25aad43383 100644 (file)
@@ -243,7 +243,7 @@ static struct regulator_ops tps62360_dcdc_ops = {
        .get_mode               = tps62360_get_mode,
 };
 
-static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
+static int tps62360_init_dcdc(struct tps62360_chip *tps,
                struct tps62360_regulator_platform_data *pdata)
 {
        int ret;
@@ -339,7 +339,7 @@ static const struct of_device_id tps62360_of_match[] = {
 MODULE_DEVICE_TABLE(of, tps62360_of_match);
 #endif
 
-static int __devinit tps62360_probe(struct i2c_client *client,
+static int tps62360_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        struct regulator_config config = { };
@@ -490,7 +490,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
  *
  * Unregister TPS driver as an i2c client device driver
  */
-static int __devexit tps62360_remove(struct i2c_client *client)
+static int tps62360_remove(struct i2c_client *client)
 {
        struct tps62360_chip *tps = i2c_get_clientdata(client);
 
@@ -531,7 +531,7 @@ static struct i2c_driver tps62360_i2c_driver = {
                .of_match_table = of_match_ptr(tps62360_of_match),
        },
        .probe = tps62360_probe,
-       .remove = __devexit_p(tps62360_remove),
+       .remove = tps62360_remove,
        .shutdown = tps62360_shutdown,
        .id_table = tps62360_id,
 };
index 6998d579d07b424891a79d09e62406a6b7e38d74..9b9af6d889c83214b06e9aa6b54767ede61289b1 100644 (file)
@@ -219,7 +219,7 @@ static struct regmap_config tps65023_regmap_config = {
        .val_bits = 8,
 };
 
-static int __devinit tps_65023_probe(struct i2c_client *client,
+static int tps_65023_probe(struct i2c_client *client,
                                     const struct i2c_device_id *id)
 {
        const struct tps_driver_data *drv_data = (void *)id->driver_data;
@@ -319,7 +319,7 @@ static int __devinit tps_65023_probe(struct i2c_client *client,
        return error;
 }
 
-static int __devexit tps_65023_remove(struct i2c_client *client)
+static int tps_65023_remove(struct i2c_client *client)
 {
        struct tps_pmic *tps = i2c_get_clientdata(client);
        int i;
@@ -446,7 +446,7 @@ static struct i2c_driver tps_65023_i2c_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps_65023_probe,
-       .remove = __devexit_p(tps_65023_remove),
+       .remove = tps_65023_remove,
        .id_table = tps_65023_id,
 };
 
index 07d01ccdf308fdf2a6871ce60f6d60f380d4060c..0233cfb5656058a57ccd0dce40591701c16ce8b6 100644 (file)
@@ -356,7 +356,7 @@ static struct regulator_ops tps6507x_pmic_ops = {
        .list_voltage = regulator_list_voltage_table,
 };
 
-static __devinit int tps6507x_pmic_probe(struct platform_device *pdev)
+static int tps6507x_pmic_probe(struct platform_device *pdev)
 {
        struct tps6507x_dev *tps6507x_dev = dev_get_drvdata(pdev->dev.parent);
        struct tps_info *info = &tps6507x_pmic_regs[0];
@@ -439,7 +439,7 @@ fail:
        return error;
 }
 
-static int __devexit tps6507x_pmic_remove(struct platform_device *pdev)
+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;
@@ -456,7 +456,7 @@ static struct platform_driver tps6507x_pmic_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps6507x_pmic_probe,
-       .remove = __devexit_p(tps6507x_pmic_remove),
+       .remove = tps6507x_pmic_remove,
 };
 
 static int __init tps6507x_pmic_init(void)
index 001ad554ac62634c6a77897ffc9a92cf641c2abf..3974a992220f2c963f824d907d6ba0f44aaac799 100644 (file)
 
 #include <linux/module.h>
 #include <linux/init.h>
+#include <linux/gpio.h>
 #include <linux/slab.h>
 #include <linux/err.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65090.h>
-#include <linux/regulator/tps65090-regulator.h>
 
 struct tps65090_regulator {
-       int             id;
-       /* used by regulator core */
-       struct regulator_desc   desc;
-
-       /* Device */
        struct device           *dev;
+       struct regulator_desc   *desc;
+       struct regulator_dev    *rdev;
+};
+
+static struct regulator_ops tps65090_ext_control_ops = {
+};
+
+static struct regulator_ops tps65090_reg_contol_ops = {
+       .enable         = regulator_enable_regmap,
+       .disable        = regulator_disable_regmap,
+       .is_enabled     = regulator_is_enabled_regmap,
 };
 
-static struct regulator_ops tps65090_ops = {
-       .enable = regulator_enable_regmap,
-       .disable = regulator_disable_regmap,
-       .is_enabled = regulator_is_enabled_regmap,
+static struct regulator_ops tps65090_ldo_ops = {
 };
 
-#define tps65090_REG(_id)                              \
+#define tps65090_REG_DESC(_id, _sname, _en_reg, _ops)  \
 {                                                      \
-       .id             = TPS65090_ID_##_id,            \
-       .desc = {                                       \
-               .name = tps65090_rails(_id),            \
-               .id = TPS65090_ID_##_id,                \
-               .ops = &tps65090_ops,                   \
-               .type = REGULATOR_VOLTAGE,              \
-               .owner = THIS_MODULE,                   \
-               .enable_reg = (TPS65090_ID_##_id) + 12, \
-               .enable_mask = BIT(0),                  \
-       },                                              \
+       .name = "TPS65090_RAILS"#_id,                   \
+       .supply_name = _sname,                          \
+       .id = TPS65090_REGULATOR_##_id,                 \
+       .ops = &_ops,                                   \
+       .enable_reg = _en_reg,                          \
+       .enable_mask = BIT(0),                          \
+       .type = REGULATOR_VOLTAGE,                      \
+       .owner = THIS_MODULE,                           \
 }
 
-static struct tps65090_regulator TPS65090_regulator[] = {
-       tps65090_REG(DCDC1),
-       tps65090_REG(DCDC2),
-       tps65090_REG(DCDC3),
-       tps65090_REG(FET1),
-       tps65090_REG(FET2),
-       tps65090_REG(FET3),
-       tps65090_REG(FET4),
-       tps65090_REG(FET5),
-       tps65090_REG(FET6),
-       tps65090_REG(FET7),
+static struct regulator_desc tps65090_regulator_desc[] = {
+       tps65090_REG_DESC(DCDC1, "vsys1",   0x0C, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC2, "vsys2",   0x0D, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(DCDC3, "vsys3",   0x0E, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET1,  "infet1",  0x0F, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET2,  "infet2",  0x10, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET3,  "infet3",  0x11, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET4,  "infet4",  0x12, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET5,  "infet5",  0x13, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET6,  "infet6",  0x14, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(FET7,  "infet7",  0x15, tps65090_reg_contol_ops),
+       tps65090_REG_DESC(LDO1,  "vsys_l1", 0,    tps65090_ldo_ops),
+       tps65090_REG_DESC(LDO2,  "vsys_l2", 0,    tps65090_ldo_ops),
 };
 
-static inline struct tps65090_regulator *find_regulator_info(int id)
+static inline bool is_dcdc(int id)
 {
-       struct tps65090_regulator *ri;
-       int i;
+       switch (id) {
+       case TPS65090_REGULATOR_DCDC1:
+       case TPS65090_REGULATOR_DCDC2:
+       case TPS65090_REGULATOR_DCDC3:
+               return true;
+       default:
+               return false;
+       }
+}
+
+static int tps65090_config_ext_control(
+       struct tps65090_regulator *ri, bool enable)
+{
+       int ret;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       if (enable)
+               ret = tps65090_set_bits(parent, reg_en_reg, 1);
+       else
+               ret =  tps65090_clr_bits(parent, reg_en_reg, 1);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in updating reg 0x%x\n", reg_en_reg);
+       return ret;
+}
+
+static int tps65090_regulator_disable_ext_control(
+               struct tps65090_regulator *ri,
+               struct tps65090_regulator_plat_data *tps_pdata)
+{
+       int ret = 0;
+       struct device *parent = ri->dev->parent;
+       unsigned int reg_en_reg = ri->desc->enable_reg;
+
+       /*
+        * First enable output for internal control if require.
+        * And then disable external control.
+        */
+       if (tps_pdata->reg_init_data->constraints.always_on ||
+                       tps_pdata->reg_init_data->constraints.boot_on) {
+               ret =  tps65090_set_bits(parent, reg_en_reg, 0);
+               if (ret < 0) {
+                       dev_err(ri->dev, "Error in set reg 0x%x\n", reg_en_reg);
+                       return ret;
+               }
+       }
+       return tps65090_config_ext_control(ri, false);
+}
+
+static void tps65090_configure_regulator_config(
+               struct tps65090_regulator_plat_data *tps_pdata,
+               struct regulator_config *config)
+{
+       if (gpio_is_valid(tps_pdata->gpio)) {
+               int gpio_flag = GPIOF_OUT_INIT_LOW;
+
+               if (tps_pdata->reg_init_data->constraints.always_on ||
+                               tps_pdata->reg_init_data->constraints.boot_on)
+                       gpio_flag = GPIOF_OUT_INIT_HIGH;
 
-       for (i = 0; i < ARRAY_SIZE(TPS65090_regulator); i++) {
-               ri = &TPS65090_regulator[i];
-               if (ri->desc.id == id)
-                       return ri;
+               config->ena_gpio = tps_pdata->gpio;
+               config->ena_gpio_flags = gpio_flag;
        }
-       return NULL;
 }
 
-static int __devinit tps65090_regulator_probe(struct platform_device *pdev)
+static int tps65090_regulator_probe(struct platform_device *pdev)
 {
        struct tps65090 *tps65090_mfd = dev_get_drvdata(pdev->dev.parent);
        struct tps65090_regulator *ri = NULL;
        struct regulator_config config = { };
        struct regulator_dev *rdev;
-       struct tps65090_regulator_platform_data *tps_pdata;
-       int id = pdev->id;
+       struct tps65090_regulator_plat_data *tps_pdata;
+       struct tps65090_regulator *pmic;
+       struct tps65090_platform_data *tps65090_pdata;
+       int num;
+       int ret;
 
-       dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
+       dev_dbg(&pdev->dev, "Probing regulator\n");
 
-       ri = find_regulator_info(id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
+       tps65090_pdata = dev_get_platdata(pdev->dev.parent);
+       if (!tps65090_pdata) {
+               dev_err(&pdev->dev, "Platform data missing\n");
                return -EINVAL;
        }
-       tps_pdata = pdev->dev.platform_data;
-       ri->dev = &pdev->dev;
-
-       config.dev = &pdev->dev;
-       config.init_data = &tps_pdata->regulator;
-       config.driver_data = ri;
-       config.regmap = tps65090_mfd->rmap;
-
-       rdev = regulator_register(&ri->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
+
+       pmic = devm_kzalloc(&pdev->dev, TPS65090_REGULATOR_MAX * sizeof(*pmic),
+                       GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
+       }
+
+       for (num = 0; num < TPS65090_REGULATOR_MAX; num++) {
+               tps_pdata = tps65090_pdata->reg_pdata[num];
+
+               ri = &pmic[num];
+               ri->dev = &pdev->dev;
+               ri->desc = &tps65090_regulator_desc[num];
+
+               /*
+                * TPS5090 DCDC support the control from external digital input.
+                * Configure it as per platform data.
+                */
+               if (tps_pdata && is_dcdc(num) && tps_pdata->reg_init_data) {
+                       if (tps_pdata->enable_ext_control) {
+                               tps65090_configure_regulator_config(
+                                               tps_pdata, &config);
+                               ri->desc->ops = &tps65090_ext_control_ops;
+                       } else {
+                               ret = tps65090_regulator_disable_ext_control(
+                                               ri, tps_pdata);
+                               if (ret < 0) {
+                                       dev_err(&pdev->dev,
+                                               "failed disable ext control\n");
+                                       goto scrub;
+                               }
+                       }
+               }
+
+               config.dev = &pdev->dev;
+               config.driver_data = ri;
+               config.regmap = tps65090_mfd->rmap;
+               if (tps_pdata)
+                       config.init_data = tps_pdata->reg_init_data;
+               else
+                       config.init_data = NULL;
+
+               rdev = regulator_register(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;
+               }
+               ri->rdev = rdev;
+
+               /* Enable external control if it is require */
+               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;
+                       }
+               }
        }
 
-       platform_set_drvdata(pdev, rdev);
+       platform_set_drvdata(pdev, pmic);
        return 0;
+
+scrub:
+       while (--num >= 0) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
+       return ret;
 }
 
-static int __devexit tps65090_regulator_remove(struct platform_device *pdev)
+static int tps65090_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct tps65090_regulator *pmic = platform_get_drvdata(pdev);
+       struct tps65090_regulator *ri;
+       int num;
 
-       regulator_unregister(rdev);
+       for (num = 0; num < TPS65090_REGULATOR_MAX; ++num) {
+               ri = &pmic[num];
+               regulator_unregister(ri->rdev);
+       }
        return 0;
 }
 
 static struct platform_driver tps65090_regulator_driver = {
        .driver = {
-               .name   = "tps65090-regulator",
+               .name   = "tps65090-pmic",
                .owner  = THIS_MODULE,
        },
        .probe          = tps65090_regulator_probe,
-       .remove         = __devexit_p(tps65090_regulator_remove),
+       .remove         = tps65090_regulator_remove,
 };
 
 static int __init tps65090_regulator_init(void)
index ab00cab905b730459c6e752907f1139aaec9ee57..73dce76641265590179cb2440e75ad71ffd722d0 100644 (file)
@@ -332,7 +332,7 @@ static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
 }
 #endif
 
-static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
+static int tps65217_regulator_probe(struct platform_device *pdev)
 {
        struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
        struct tps65217_board *pdata = dev_get_platdata(tps->dev);
@@ -397,7 +397,7 @@ err_unregister_regulator:
        return ret;
 }
 
-static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
+static int tps65217_regulator_remove(struct platform_device *pdev)
 {
        struct tps65217 *tps = platform_get_drvdata(pdev);
        unsigned int i;
@@ -415,7 +415,7 @@ static struct platform_driver tps65217_regulator_driver = {
                .name = "tps65217-pmic",
        },
        .probe = tps65217_regulator_probe,
-       .remove = __devexit_p(tps65217_regulator_remove),
+       .remove = tps65217_regulator_remove,
 };
 
 static int __init tps65217_regulator_init(void)
index 058d2f2675e902c8d2856b83b3ee5a6b4c7c5503..843ee0a9bb92ce2a23e7a2209590b99cfa13e76c 100644 (file)
@@ -592,7 +592,7 @@ static int pmic_remove(struct spi_device *spi)
        return 0;
 }
 
-static int __devinit pmic_probe(struct spi_device *spi)
+static int pmic_probe(struct spi_device *spi)
 {
        struct tps6524x *hw;
        struct device *dev = &spi->dev;
@@ -649,7 +649,7 @@ fail:
 
 static struct spi_driver pmic_driver = {
        .probe          = pmic_probe,
-       .remove         = __devexit_p(pmic_remove),
+       .remove         = pmic_remove,
        .driver         = {
                .name   = "tps6524x",
                .owner  = THIS_MODULE,
index ce1e7cb8d513f13a8463a84b2de39d1a61cb180c..9ce44109f2aaddf8af175972fb562faf8f06ed96 100644 (file)
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
+#include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
 #include <linux/mfd/tps6586x.h>
 
 /* supply control and voltage setting  */
@@ -255,10 +257,10 @@ static inline int tps6586x_regulator_preinit(struct device *parent,
                                 1 << ri->enable_bit[1]);
 }
 
-static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
+static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev,
+                       int id, struct regulator_init_data *p)
 {
        struct device *parent = pdev->dev.parent;
-       struct regulator_init_data *p = pdev->dev.platform_data;
        struct tps6586x_settings *setting = p->driver_data;
        uint8_t reg;
 
@@ -269,7 +271,7 @@ static int tps6586x_regulator_set_slew_rate(struct platform_device *pdev)
                return 0;
 
        /* only SM0 and SM1 can have the slew rate settings */
-       switch (pdev->id) {
+       switch (id) {
        case TPS6586X_ID_SM_0:
                reg = TPS6586X_SM0SL;
                break;
@@ -298,58 +300,185 @@ static inline struct tps6586x_regulator *find_regulator_info(int id)
        return NULL;
 }
 
-static int __devinit tps6586x_regulator_probe(struct platform_device *pdev)
+#ifdef CONFIG_OF
+static struct of_regulator_match tps6586x_matches[] = {
+       { .name = "sys",     .driver_data = (void *)TPS6586X_ID_SYS     },
+       { .name = "sm0",     .driver_data = (void *)TPS6586X_ID_SM_0    },
+       { .name = "sm1",     .driver_data = (void *)TPS6586X_ID_SM_1    },
+       { .name = "sm2",     .driver_data = (void *)TPS6586X_ID_SM_2    },
+       { .name = "ldo0",    .driver_data = (void *)TPS6586X_ID_LDO_0   },
+       { .name = "ldo1",    .driver_data = (void *)TPS6586X_ID_LDO_1   },
+       { .name = "ldo2",    .driver_data = (void *)TPS6586X_ID_LDO_2   },
+       { .name = "ldo3",    .driver_data = (void *)TPS6586X_ID_LDO_3   },
+       { .name = "ldo4",    .driver_data = (void *)TPS6586X_ID_LDO_4   },
+       { .name = "ldo5",    .driver_data = (void *)TPS6586X_ID_LDO_5   },
+       { .name = "ldo6",    .driver_data = (void *)TPS6586X_ID_LDO_6   },
+       { .name = "ldo7",    .driver_data = (void *)TPS6586X_ID_LDO_7   },
+       { .name = "ldo8",    .driver_data = (void *)TPS6586X_ID_LDO_8   },
+       { .name = "ldo9",    .driver_data = (void *)TPS6586X_ID_LDO_9   },
+       { .name = "ldo_rtc", .driver_data = (void *)TPS6586X_ID_LDO_RTC },
+};
+
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+               struct platform_device *pdev,
+               struct of_regulator_match **tps6586x_reg_matches)
+{
+       const unsigned int num = ARRAY_SIZE(tps6586x_matches);
+       struct device_node *np = pdev->dev.parent->of_node;
+       struct device_node *regs;
+       const char *sys_rail = NULL;
+       unsigned int i;
+       struct tps6586x_platform_data *pdata;
+       int err;
+
+       regs = of_find_node_by_name(np, "regulators");
+       if (!regs) {
+               dev_err(&pdev->dev, "regulator node not found\n");
+               return NULL;
+       }
+
+       err = of_regulator_match(&pdev->dev, regs, tps6586x_matches, num);
+       if (err < 0) {
+               dev_err(&pdev->dev, "Regulator match failed, e %d\n", err);
+               of_node_put(regs);
+               return NULL;
+       }
+
+       of_node_put(regs);
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata) {
+               dev_err(&pdev->dev, "Memory alloction failed\n");
+               return NULL;
+       }
+
+       for (i = 0; i < num; i++) {
+               int id;
+               if (!tps6586x_matches[i].init_data)
+                       continue;
+
+               pdata->reg_init_data[i] = tps6586x_matches[i].init_data;
+               id = (int)tps6586x_matches[i].driver_data;
+               if (id == TPS6586X_ID_SYS)
+                       sys_rail = pdata->reg_init_data[i]->constraints.name;
+
+               if ((id == TPS6586X_ID_LDO_5) || (id == TPS6586X_ID_LDO_RTC))
+                       pdata->reg_init_data[i]->supply_regulator = sys_rail;
+       }
+       *tps6586x_reg_matches = tps6586x_matches;
+       return pdata;
+}
+#else
+static struct tps6586x_platform_data *tps6586x_parse_regulator_dt(
+               struct platform_device *pdev,
+               struct of_regulator_match **tps6586x_reg_matches)
+{
+       *tps6586x_reg_matches = NULL;
+       return NULL;
+}
+#endif
+
+static int tps6586x_regulator_probe(struct platform_device *pdev)
 {
        struct tps6586x_regulator *ri = NULL;
        struct regulator_config config = { };
-       struct regulator_dev *rdev;
-       int id = pdev->id;
+       struct regulator_dev **rdev;
+       struct regulator_init_data *reg_data;
+       struct tps6586x_platform_data *pdata;
+       struct of_regulator_match *tps6586x_reg_matches = NULL;
+       int id;
        int err;
 
        dev_dbg(&pdev->dev, "Probing regulator %d\n", id);
 
-       ri = find_regulator_info(id);
-       if (ri == NULL) {
-               dev_err(&pdev->dev, "invalid regulator ID specified\n");
-               return -EINVAL;
-       }
+       pdata = dev_get_platdata(pdev->dev.parent);
+       if ((!pdata) && (pdev->dev.parent->of_node))
+               pdata = tps6586x_parse_regulator_dt(pdev,
+                                       &tps6586x_reg_matches);
 
-       err = tps6586x_regulator_preinit(pdev->dev.parent, ri);
-       if (err)
-               return err;
+       if (!pdata) {
+               dev_err(&pdev->dev, "Platform data not available, exiting\n");
+               return -ENODEV;
+       }
 
-       config.dev = pdev->dev.parent;
-       config.of_node = pdev->dev.of_node;
-       config.init_data = pdev->dev.platform_data;
-       config.driver_data = ri;
+       rdev = devm_kzalloc(&pdev->dev, TPS6586X_ID_MAX_REGULATOR *
+                               sizeof(*rdev), GFP_KERNEL);
+       if (!rdev) {
+               dev_err(&pdev->dev, "Mmemory alloc failed\n");
+               return -ENOMEM;
+       }
 
-       rdev = regulator_register(&ri->desc, &config);
-       if (IS_ERR(rdev)) {
-               dev_err(&pdev->dev, "failed to register regulator %s\n",
-                               ri->desc.name);
-               return PTR_ERR(rdev);
+       for (id = 0; id < TPS6586X_ID_MAX_REGULATOR; ++id) {
+               reg_data = pdata->reg_init_data[id];
+
+               ri = find_regulator_info(id);
+               if (!ri) {
+                       dev_err(&pdev->dev, "invalid regulator ID specified\n");
+                       err = -EINVAL;
+                       goto fail;
+               }
+
+               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;
+               }
+
+               config.dev = pdev->dev.parent;
+               config.init_data = reg_data;
+               config.driver_data = ri;
+
+               if (tps6586x_reg_matches)
+                       config.of_node = tps6586x_reg_matches[id].of_node;
+
+               rdev[id] = regulator_register(&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;
+               }
+
+               if (reg_data) {
+                       err = tps6586x_regulator_set_slew_rate(pdev, id,
+                                       reg_data);
+                       if (err < 0) {
+                               dev_err(&pdev->dev,
+                                       "Slew rate config failed, e %d\n", err);
+                               regulator_unregister(rdev[id]);
+                               goto fail;
+                       }
+               }
        }
 
        platform_set_drvdata(pdev, rdev);
+       return 0;
 
-       return tps6586x_regulator_set_slew_rate(pdev);
+fail:
+       while (--id >= 0)
+               regulator_unregister(rdev[id]);
+       return err;
 }
 
-static int __devexit tps6586x_regulator_remove(struct platform_device *pdev)
+static int tps6586x_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct regulator_dev **rdev = platform_get_drvdata(pdev);
+       int id = TPS6586X_ID_MAX_REGULATOR;
+
+       while (--id >= 0)
+               regulator_unregister(rdev[id]);
 
-       regulator_unregister(rdev);
        return 0;
 }
 
 static struct platform_driver tps6586x_regulator_driver = {
        .driver = {
-               .name   = "tps6586x-regulator",
+               .name   = "tps6586x-pmic",
                .owner  = THIS_MODULE,
        },
        .probe          = tps6586x_regulator_probe,
-       .remove         = __devexit_p(tps6586x_regulator_remove),
+       .remove         = tps6586x_regulator_remove,
 };
 
 static int __init tps6586x_regulator_init(void)
index 793adda560c3c3364c2053cdb152974fc2a2f02b..6b77bbf32ebcf7db26e1b1d85d05268efd7fa1eb 100644 (file)
@@ -1026,7 +1026,7 @@ static inline struct tps65910_board *tps65910_parse_dt_reg_data(
 }
 #endif
 
-static __devinit int tps65910_probe(struct platform_device *pdev)
+static int tps65910_probe(struct platform_device *pdev)
 {
        struct tps65910 *tps65910 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -1184,7 +1184,7 @@ err_unregister_regulator:
        return err;
 }
 
-static int __devexit tps65910_remove(struct platform_device *pdev)
+static int tps65910_remove(struct platform_device *pdev)
 {
        struct tps65910_reg *pmic = platform_get_drvdata(pdev);
        int i;
@@ -1231,7 +1231,7 @@ static struct platform_driver tps65910_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65910_probe,
-       .remove = __devexit_p(tps65910_remove),
+       .remove = tps65910_remove,
        .shutdown = tps65910_shutdown,
 };
 
index 18b2a1dcb4b5d6ba189fa74dfe4c8f2d23fbe1d8..17e994e47dc139c3117a8affe76eef64b5e092e1 100644 (file)
@@ -459,7 +459,7 @@ static struct regulator_ops tps65912_ops_ldo = {
        .list_voltage = tps65912_list_voltage,
 };
 
-static __devinit int tps65912_probe(struct platform_device *pdev)
+static int tps65912_probe(struct platform_device *pdev)
 {
        struct tps65912 *tps65912 = dev_get_drvdata(pdev->dev.parent);
        struct regulator_config config = { };
@@ -525,7 +525,7 @@ err:
        return err;
 }
 
-static int __devexit tps65912_remove(struct platform_device *pdev)
+static int tps65912_remove(struct platform_device *pdev)
 {
        struct tps65912_reg *tps65912_reg = platform_get_drvdata(pdev);
        int i;
@@ -541,7 +541,7 @@ static struct platform_driver tps65912_driver = {
                .owner = THIS_MODULE,
        },
        .probe = tps65912_probe,
-       .remove = __devexit_p(tps65912_remove),
+       .remove = tps65912_remove,
 };
 
 static int __init tps65912_init(void)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
new file mode 100644 (file)
index 0000000..127d175
--- /dev/null
@@ -0,0 +1,793 @@
+/*
+ * tps80031-regulator.c -- TI TPS80031 regulator driver.
+ *
+ * Regulator driver for TITPS80031/TPS80032 Fully Integrated Power
+ * Management with Power Path and Battery Charger.
+ *
+ * Copyright (c) 2012, NVIDIA Corporation.
+ *
+ * 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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any kind,
+ * whether express or implied; 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/delay.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/mfd/tps80031.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/slab.h>
+
+/* Flags for DCDC Voltage reading */
+#define DCDC_OFFSET_EN         BIT(0)
+#define DCDC_EXTENDED_EN       BIT(1)
+#define TRACK_MODE_ENABLE      BIT(2)
+
+#define SMPS_MULTOFFSET_VIO    BIT(1)
+#define SMPS_MULTOFFSET_SMPS1  BIT(3)
+#define SMPS_MULTOFFSET_SMPS2  BIT(4)
+#define SMPS_MULTOFFSET_SMPS3  BIT(6)
+#define SMPS_MULTOFFSET_SMPS4  BIT(0)
+
+#define SMPS_CMD_MASK          0xC0
+#define SMPS_VSEL_MASK         0x3F
+#define LDO_VSEL_MASK          0x1F
+#define LDO_TRACK_VSEL_MASK    0x3F
+
+#define MISC2_LDOUSB_IN_VSYS   BIT(4)
+#define MISC2_LDOUSB_IN_PMID   BIT(3)
+#define MISC2_LDOUSB_IN_MASK   0x18
+
+#define MISC2_LDO3_SEL_VIB_VAL BIT(0)
+#define MISC2_LDO3_SEL_VIB_MASK        0x1
+
+#define BOOST_HW_PWR_EN                BIT(5)
+#define BOOST_HW_PWR_EN_MASK   BIT(5)
+
+#define OPA_MODE_EN            BIT(6)
+#define OPA_MODE_EN_MASK       BIT(6)
+
+#define USB_VBUS_CTRL_SET      0x04
+#define USB_VBUS_CTRL_CLR      0x05
+#define VBUS_DISCHRG           0x20
+
+struct tps80031_regulator_info {
+       /* Regulator register address.*/
+       u8              trans_reg;
+       u8              state_reg;
+       u8              force_reg;
+       u8              volt_reg;
+       u8              volt_id;
+
+       /*Power request bits */
+       int             preq_bit;
+
+       /* used by regulator core */
+       struct regulator_desc   desc;
+
+};
+
+struct tps80031_regulator {
+       struct device                   *dev;
+       struct regulator_dev            *rdev;
+       struct tps80031_regulator_info  *rinfo;
+
+       u8                              device_flags;
+       unsigned int                    config_flags;
+       unsigned int                    ext_ctrl_flag;
+};
+
+static inline struct device *to_tps80031_dev(struct regulator_dev *rdev)
+{
+       return rdev_get_dev(rdev)->parent->parent;
+}
+
+static int tps80031_reg_is_enabled(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       u8 reg_val;
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return true;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                               &reg_val);
+       if (ret < 0) {
+               dev_err(&rdev->dev, "Reg 0x%02x read failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+               return ret;
+       }
+       return ((reg_val & TPS80031_STATE_MASK) == TPS80031_STATE_ON);
+}
+
+static int tps80031_reg_enable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return 0;
+
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                       TPS80031_STATE_ON, TPS80031_STATE_MASK);
+       if (ret < 0) {
+               dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int tps80031_reg_disable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       if (ri->ext_ctrl_flag & TPS80031_EXT_PWR_REQ)
+               return 0;
+
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->state_reg,
+                       TPS80031_STATE_OFF, TPS80031_STATE_MASK);
+       if (ret < 0)
+               dev_err(&rdev->dev, "Reg 0x%02x update failed, err = %d\n",
+                       ri->rinfo->state_reg, ret);
+       return ret;
+}
+
+/* DCDC voltages for the selector of 58 to 63 */
+static int tps80031_dcdc_voltages[4][5] = {
+       { 1350, 1500, 1800, 1900, 2100},
+       { 1350, 1500, 1800, 1900, 2100},
+       { 2084, 2315, 2778, 2932, 3241},
+       { 4167, 2315, 2778, 2932, 3241},
+};
+
+static int tps80031_dcdc_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       int volt_index = ri->device_flags & 0x3;
+
+       if (sel == 0)
+               return 0;
+       else if (sel < 58)
+               return regulator_list_voltage_linear(rdev, sel - 1);
+       else
+               return tps80031_dcdc_voltages[volt_index][sel - 58] * 1000;
+}
+
+static int tps80031_dcdc_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned vsel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+       u8 reg_val;
+
+       if (ri->rinfo->force_reg) {
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                                               ri->rinfo->force_reg, &reg_val);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                               ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+               if (!(reg_val & SMPS_CMD_MASK)) {
+                       ret = tps80031_update(parent, ri->rinfo->volt_id,
+                               ri->rinfo->force_reg, vsel, SMPS_VSEL_MASK);
+                       if (ret < 0)
+                               dev_err(ri->dev,
+                                       "reg 0x%02x update failed, e = %d\n",
+                                       ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+       }
+       ret = tps80031_update(parent, ri->rinfo->volt_id,
+                       ri->rinfo->volt_reg, vsel, SMPS_VSEL_MASK);
+       if (ret < 0)
+               dev_err(ri->dev, "reg 0x%02x update failed, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+       return ret;
+}
+
+static int tps80031_dcdc_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       uint8_t vsel = 0;
+       int ret;
+
+       if (ri->rinfo->force_reg) {
+               ret = tps80031_read(parent, ri->rinfo->volt_id,
+                                               ri->rinfo->force_reg, &vsel);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                                       ri->rinfo->force_reg, ret);
+                       return ret;
+               }
+
+               if (!(vsel & SMPS_CMD_MASK))
+                       return vsel & SMPS_VSEL_MASK;
+       }
+       ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, &vsel);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+               return ret;
+       }
+       return vsel & SMPS_VSEL_MASK;
+}
+
+static int tps80031_ldo_set_voltage_sel(struct regulator_dev *rdev,
+               unsigned sel)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       /* Check for valid setting for TPS80031 or TPS80032-ES1.0 */
+       if ((ri->rinfo->desc.id == TPS80031_REGULATOR_LDO2) &&
+                       (ri->device_flags & TRACK_MODE_ENABLE)) {
+               unsigned nvsel = (sel) & 0x1F;
+               if (((tps80031_get_chip_info(parent) == TPS80031) ||
+                       ((tps80031_get_chip_info(parent) == TPS80032) &&
+                       (tps80031_get_pmu_version(parent) == 0x0))) &&
+                       ((nvsel == 0x0) || (nvsel >= 0x19 && nvsel <= 0x1F))) {
+                               dev_err(ri->dev,
+                                       "Invalid sel %d in track mode LDO2\n",
+                                       nvsel);
+                               return -EINVAL;
+               }
+       }
+
+       ret = tps80031_write(parent, ri->rinfo->volt_id,
+                       ri->rinfo->volt_reg, sel);
+       if (ret < 0)
+               dev_err(ri->dev, "Error in writing reg 0x%02x, e = %d\n",
+                       ri->rinfo->volt_reg, ret);
+       return ret;
+}
+
+static int tps80031_ldo_get_voltage_sel(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       uint8_t vsel;
+       int ret;
+
+       ret = tps80031_read(parent, ri->rinfo->volt_id,
+                               ri->rinfo->volt_reg, &vsel);
+       if (ret < 0) {
+               dev_err(ri->dev, "Error in writing the Voltage register\n");
+               return ret;
+       }
+       return vsel & rdev->desc->vsel_mask;
+}
+
+static int tps80031_ldo_list_voltage(struct regulator_dev *rdev, unsigned sel)
+{
+       if (sel == 0)
+               return 0;
+       else
+               return regulator_list_voltage_linear(rdev, sel - 1);
+}
+
+static int tps80031_vbus_is_enabled(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret = -EIO;
+       uint8_t ctrl1 = 0;
+       uint8_t ctrl3 = 0;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+                       TPS80031_CHARGERUSB_CTRL1, &ctrl1);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, &ctrl3);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+       if ((ctrl1 & OPA_MODE_EN) && (ctrl3 & BOOST_HW_PWR_EN))
+               return 1;
+       return ret;
+}
+
+static int tps80031_vbus_enable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret;
+
+       ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL1, OPA_MODE_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                                       TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+
+       ret = tps80031_set_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x read failed, e = %d\n",
+                       TPS80031_CHARGERUSB_CTRL3, ret);
+               return ret;
+       }
+       return ret;
+}
+
+static int tps80031_vbus_disable(struct regulator_dev *rdev)
+{
+       struct tps80031_regulator *ri = rdev_get_drvdata(rdev);
+       struct device *parent = to_tps80031_dev(rdev);
+       int ret = 0;
+
+       if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+               ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+                       USB_VBUS_CTRL_SET, VBUS_DISCHRG);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+                               USB_VBUS_CTRL_SET, ret);
+                       return ret;
+               }
+       }
+
+       ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+                       TPS80031_CHARGERUSB_CTRL1,  OPA_MODE_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+                               TPS80031_CHARGERUSB_CTRL1, ret);
+               return ret;
+       }
+
+       ret = tps80031_clr_bits(parent, TPS80031_SLAVE_ID2,
+                               TPS80031_CHARGERUSB_CTRL3, BOOST_HW_PWR_EN);
+       if (ret < 0) {
+               dev_err(ri->dev, "reg 0x%02x clearbit failed, e = %d\n",
+                               TPS80031_CHARGERUSB_CTRL3, ret);
+               return ret;
+       }
+
+       mdelay(DIV_ROUND_UP(ri->rinfo->desc.enable_time, 1000));
+       if (ri->config_flags & TPS80031_VBUS_DISCHRG_EN_PDN) {
+               ret = tps80031_write(parent, TPS80031_SLAVE_ID2,
+                       USB_VBUS_CTRL_CLR, VBUS_DISCHRG);
+               if (ret < 0) {
+                       dev_err(ri->dev, "reg 0x%02x write failed, e = %d\n",
+                                       USB_VBUS_CTRL_CLR, ret);
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+static struct regulator_ops tps80031_dcdc_ops = {
+       .list_voltage           = tps80031_dcdc_list_voltage,
+       .set_voltage_sel        = tps80031_dcdc_set_voltage_sel,
+       .get_voltage_sel        = tps80031_dcdc_get_voltage_sel,
+       .enable         = tps80031_reg_enable,
+       .disable        = tps80031_reg_disable,
+       .is_enabled     = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_ldo_ops = {
+       .list_voltage           = tps80031_ldo_list_voltage,
+       .set_voltage_sel        = tps80031_ldo_set_voltage_sel,
+       .get_voltage_sel        = tps80031_ldo_get_voltage_sel,
+       .enable                 = tps80031_reg_enable,
+       .disable                = tps80031_reg_disable,
+       .is_enabled             = tps80031_reg_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_sw_ops = {
+       .enable         = tps80031_vbus_enable,
+       .disable        = tps80031_vbus_disable,
+       .is_enabled     = tps80031_vbus_is_enabled,
+};
+
+static struct regulator_ops tps80031_vbus_hw_ops = {
+};
+
+static struct regulator_ops tps80031_ext_reg_ops = {
+       .enable         = tps80031_reg_enable,
+       .disable        = tps80031_reg_disable,
+       .is_enabled     = tps80031_reg_is_enabled,
+};
+
+/* Non-exiting default definition for some register */
+#define TPS80031_SMPS3_CFG_FORCE       0
+#define TPS80031_SMPS4_CFG_FORCE       0
+
+#define TPS80031_VBUS_CFG_TRANS                0
+#define TPS80031_VBUS_CFG_STATE                0
+
+#define TPS80031_REG_SMPS(_id, _volt_id, _pbit)        \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .force_reg = TPS80031_##_id##_CFG_FORCE,                \
+       .volt_reg = TPS80031_##_id##_CFG_VOLTAGE,               \
+       .volt_id = TPS80031_SLAVE_##_volt_id,                   \
+       .preq_bit = _pbit,                                      \
+       .desc = {                                               \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .n_voltages = 63,                               \
+               .ops = &tps80031_dcdc_ops,                      \
+               .type = REGULATOR_VOLTAGE,                      \
+               .owner = THIS_MODULE,                           \
+               .enable_time = 500,                             \
+       },                                                      \
+}
+
+#define TPS80031_REG_LDO(_id, _preq_bit)                       \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .volt_reg = TPS80031_##_id##_CFG_VOLTAGE,               \
+       .volt_id = TPS80031_SLAVE_ID1,                          \
+       .preq_bit = _preq_bit,                                  \
+       .desc = {                                               \
+               .owner = THIS_MODULE,                           \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .ops = &tps80031_ldo_ops,                       \
+               .type = REGULATOR_VOLTAGE,                      \
+               .min_uV = 1000000,                              \
+               .uV_step = 100000,                              \
+               .n_voltages = 25,                               \
+               .vsel_mask = LDO_VSEL_MASK,                     \
+               .enable_time = 500,                             \
+       },                                                      \
+}
+
+#define TPS80031_REG_FIXED(_id, max_mV, _ops, _delay, _pbit)   \
+{                                                              \
+       .trans_reg = TPS80031_##_id##_CFG_TRANS,                \
+       .state_reg = TPS80031_##_id##_CFG_STATE,                \
+       .volt_id = TPS80031_SLAVE_ID1,                          \
+       .preq_bit = _pbit,                                      \
+       .desc = {                                               \
+               .name = "tps80031_"#_id,                        \
+               .id = TPS80031_REGULATOR_##_id,                 \
+               .n_voltages = 2,                                \
+               .ops = &_ops,                                   \
+               .type = REGULATOR_VOLTAGE,                      \
+               .owner = THIS_MODULE,                           \
+               .enable_time = _delay,                          \
+       },                                                      \
+}
+
+static struct tps80031_regulator_info tps80031_rinfo[TPS80031_REGULATOR_MAX] = {
+       TPS80031_REG_SMPS(VIO,   ID0, 4),
+       TPS80031_REG_SMPS(SMPS1, ID0, 0),
+       TPS80031_REG_SMPS(SMPS2, ID0, 1),
+       TPS80031_REG_SMPS(SMPS3, ID1, 2),
+       TPS80031_REG_SMPS(SMPS4, ID1, 3),
+       TPS80031_REG_LDO(VANA,   -1),
+       TPS80031_REG_LDO(LDO1,   8),
+       TPS80031_REG_LDO(LDO2,   9),
+       TPS80031_REG_LDO(LDO3,   10),
+       TPS80031_REG_LDO(LDO4,   11),
+       TPS80031_REG_LDO(LDO5,   12),
+       TPS80031_REG_LDO(LDO6,   13),
+       TPS80031_REG_LDO(LDO7,   14),
+       TPS80031_REG_LDO(LDOLN,  15),
+       TPS80031_REG_LDO(LDOUSB, 5),
+       TPS80031_REG_FIXED(VBUS,   5000, tps80031_vbus_hw_ops, 100000, -1),
+       TPS80031_REG_FIXED(REGEN1, 3300, tps80031_ext_reg_ops, 0, 16),
+       TPS80031_REG_FIXED(REGEN2, 3300, tps80031_ext_reg_ops, 0, 17),
+       TPS80031_REG_FIXED(SYSEN,  3300, tps80031_ext_reg_ops, 0, 18),
+};
+
+static int tps80031_power_req_config(struct device *parent,
+               struct tps80031_regulator *ri,
+               struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+       int ret = 0;
+
+       if (ri->rinfo->preq_bit < 0)
+               goto skip_pwr_req_config;
+
+       ret = tps80031_ext_power_req_config(parent, ri->ext_ctrl_flag,
+                       ri->rinfo->preq_bit, ri->rinfo->state_reg,
+                       ri->rinfo->trans_reg);
+       if (ret < 0) {
+               dev_err(ri->dev, "ext powerreq config failed, err = %d\n", ret);
+               return ret;
+       }
+
+skip_pwr_req_config:
+       if (tps80031_pdata->ext_ctrl_flag & TPS80031_PWR_ON_ON_SLEEP) {
+               ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               ri->rinfo->trans_reg, TPS80031_TRANS_SLEEP_ON,
+                               TPS80031_TRANS_SLEEP_MASK);
+               if (ret < 0) {
+                       dev_err(ri->dev, "Reg 0x%02x update failed, e %d\n",
+                                       ri->rinfo->trans_reg, ret);
+                       return ret;
+               }
+       }
+       return ret;
+}
+
+static int tps80031_regulator_config(struct device *parent,
+               struct tps80031_regulator *ri,
+               struct tps80031_regulator_platform_data *tps80031_pdata)
+{
+       int ret = 0;
+
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_LDOUSB:
+               if (ri->config_flags & (TPS80031_USBLDO_INPUT_VSYS |
+                       TPS80031_USBLDO_INPUT_PMID)) {
+                       unsigned val = 0;
+                       if (ri->config_flags & TPS80031_USBLDO_INPUT_VSYS)
+                               val = MISC2_LDOUSB_IN_VSYS;
+                       else
+                               val = MISC2_LDOUSB_IN_PMID;
+
+                       ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               TPS80031_MISC2, val,
+                               MISC2_LDOUSB_IN_MASK);
+                       if (ret < 0) {
+                               dev_err(ri->dev,
+                                       "LDOUSB config failed, e= %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       case TPS80031_REGULATOR_LDO3:
+               if (ri->config_flags & TPS80031_LDO3_OUTPUT_VIB) {
+                       ret = tps80031_update(parent, TPS80031_SLAVE_ID1,
+                               TPS80031_MISC2, MISC2_LDO3_SEL_VIB_VAL,
+                               MISC2_LDO3_SEL_VIB_MASK);
+                       if (ret < 0) {
+                               dev_err(ri->dev,
+                                       "LDO3 config failed, e = %d\n", ret);
+                               return ret;
+                       }
+               }
+               break;
+
+       case TPS80031_REGULATOR_VBUS:
+               /* Provide SW control Ops if VBUS is SW control */
+               if (!(ri->config_flags & TPS80031_VBUS_SW_ONLY))
+                       ri->rinfo->desc.ops = &tps80031_vbus_sw_ops;
+               break;
+       default:
+               break;
+       }
+
+       /* Configure Active state to ON, SLEEP to OFF and OFF_state to OFF */
+       ret = tps80031_update(parent, TPS80031_SLAVE_ID1, ri->rinfo->trans_reg,
+               TPS80031_TRANS_ACTIVE_ON | TPS80031_TRANS_SLEEP_OFF |
+               TPS80031_TRANS_OFF_OFF, TPS80031_TRANS_ACTIVE_MASK |
+               TPS80031_TRANS_SLEEP_MASK | TPS80031_TRANS_OFF_MASK);
+       if (ret < 0) {
+               dev_err(ri->dev, "trans reg update failed, e %d\n", ret);
+               return ret;
+       }
+
+       return ret;
+}
+
+static int check_smps_mode_mult(struct device *parent,
+       struct tps80031_regulator *ri)
+{
+       int mult_offset;
+       int ret;
+       u8 smps_offset;
+       u8 smps_mult;
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+                       TPS80031_SMPS_OFFSET, &smps_offset);
+       if (ret < 0) {
+               dev_err(parent, "Error in reading smps offset register\n");
+               return ret;
+       }
+
+       ret = tps80031_read(parent, TPS80031_SLAVE_ID1,
+                       TPS80031_SMPS_MULT, &smps_mult);
+       if (ret < 0) {
+               dev_err(parent, "Error in reading smps mult register\n");
+               return ret;
+       }
+
+       switch (ri->rinfo->desc.id) {
+       case TPS80031_REGULATOR_VIO:
+               mult_offset = SMPS_MULTOFFSET_VIO;
+               break;
+       case TPS80031_REGULATOR_SMPS1:
+               mult_offset = SMPS_MULTOFFSET_SMPS1;
+               break;
+       case TPS80031_REGULATOR_SMPS2:
+               mult_offset = SMPS_MULTOFFSET_SMPS2;
+               break;
+       case TPS80031_REGULATOR_SMPS3:
+               mult_offset = SMPS_MULTOFFSET_SMPS3;
+               break;
+       case TPS80031_REGULATOR_SMPS4:
+               mult_offset = SMPS_MULTOFFSET_SMPS4;
+               break;
+       case TPS80031_REGULATOR_LDO2:
+               ri->device_flags = smps_mult & BIT(5) ? TRACK_MODE_ENABLE : 0;
+               /* TRACK mode the ldo2 varies from 600mV to 1300mV */
+               if (ri->device_flags & TRACK_MODE_ENABLE) {
+                       ri->rinfo->desc.min_uV = 600000;
+                       ri->rinfo->desc.uV_step = 12500;
+                       ri->rinfo->desc.n_voltages = 57;
+                       ri->rinfo->desc.vsel_mask = LDO_TRACK_VSEL_MASK;
+               }
+               return 0;
+       default:
+               return 0;
+       }
+
+       ri->device_flags = (smps_offset & mult_offset) ? DCDC_OFFSET_EN : 0;
+       ri->device_flags |= (smps_mult & mult_offset) ? DCDC_EXTENDED_EN : 0;
+       switch (ri->device_flags) {
+       case 0:
+               ri->rinfo->desc.min_uV = 607700;
+               ri->rinfo->desc.uV_step = 12660;
+               break;
+       case DCDC_OFFSET_EN:
+               ri->rinfo->desc.min_uV = 700000;
+               ri->rinfo->desc.uV_step = 12500;
+               break;
+       case DCDC_EXTENDED_EN:
+               ri->rinfo->desc.min_uV = 1852000;
+               ri->rinfo->desc.uV_step = 38600;
+               break;
+       case DCDC_OFFSET_EN | DCDC_EXTENDED_EN:
+               ri->rinfo->desc.min_uV = 2161000;
+               ri->rinfo->desc.uV_step = 38600;
+               break;
+       }
+       return 0;
+}
+
+static int tps80031_regulator_probe(struct platform_device *pdev)
+{
+       struct tps80031_platform_data *pdata;
+       struct tps80031_regulator_platform_data *tps_pdata;
+       struct tps80031_regulator_info *rinfo;
+       struct tps80031_regulator *ri;
+       struct tps80031_regulator *pmic;
+       struct regulator_dev *rdev;
+       struct regulator_config config = { };
+       int ret;
+       int num;
+
+       pdata = dev_get_platdata(pdev->dev.parent);
+
+       if (!pdata) {
+               dev_err(&pdev->dev, "No platform data\n");
+               return -EINVAL;
+       }
+
+       pmic = devm_kzalloc(&pdev->dev,
+                       TPS80031_REGULATOR_MAX * sizeof(*pmic), GFP_KERNEL);
+       if (!pmic) {
+               dev_err(&pdev->dev, "mem alloc for pmic failed\n");
+               return -ENOMEM;
+       }
+
+       for (num = 0; num < TPS80031_REGULATOR_MAX; ++num) {
+               tps_pdata = pdata->regulator_pdata[num];
+               rinfo = &tps80031_rinfo[num];
+               ri = &pmic[num];
+               ri->rinfo = rinfo;
+               ri->dev = &pdev->dev;
+
+               check_smps_mode_mult(pdev->dev.parent, ri);
+               config.dev = &pdev->dev;
+               config.init_data = NULL;
+               config.driver_data = ri;
+               if (tps_pdata) {
+                       config.init_data = tps_pdata->reg_init_data;
+                       ri->config_flags = tps_pdata->config_flags;
+                       ri->ext_ctrl_flag = tps_pdata->ext_ctrl_flag;
+                       ret = tps80031_regulator_config(pdev->dev.parent,
+                                       ri, tps_pdata);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "regulator config failed, e %d\n", ret);
+                               goto fail;
+                       }
+
+                       ret = tps80031_power_req_config(pdev->dev.parent,
+                                       ri, tps_pdata);
+                       if (ret < 0) {
+                               dev_err(&pdev->dev,
+                                       "pwr_req config failed, err %d\n", ret);
+                               goto fail;
+                       }
+               }
+               rdev = regulator_register(&ri->rinfo->desc, &config);
+               if (IS_ERR_OR_NULL(rdev)) {
+                       dev_err(&pdev->dev,
+                               "register regulator failed %s\n",
+                                       ri->rinfo->desc.name);
+                       ret = PTR_ERR(rdev);
+                       goto fail;
+               }
+               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 = {
+       .driver = {
+               .name   = "tps80031-pmic",
+               .owner  = THIS_MODULE,
+       },
+       .probe          = tps80031_regulator_probe,
+       .remove         = tps80031_regulator_remove,
+};
+
+static int __init tps80031_regulator_init(void)
+{
+       return platform_driver_register(&tps80031_regulator_driver);
+}
+subsys_initcall(tps80031_regulator_init);
+
+static void __exit tps80031_regulator_exit(void)
+{
+       platform_driver_unregister(&tps80031_regulator_driver);
+}
+module_exit(tps80031_regulator_exit);
+
+MODULE_ALIAS("platform:tps80031-regulator");
+MODULE_DESCRIPTION("Regulator Driver for TI TPS80031 PMIC");
+MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
+MODULE_LICENSE("GPL v2");
index 7eb986a4074678cb58118577544a10838b8a185a..493c8c6a241f41b1820786b993b342816002bc1c 100644 (file)
@@ -1116,7 +1116,7 @@ static const struct of_device_id twl_of_match[] __devinitconst = {
 };
 MODULE_DEVICE_TABLE(of, twl_of_match);
 
-static int __devinit twlreg_probe(struct platform_device *pdev)
+static int twlreg_probe(struct platform_device *pdev)
 {
        int                             i, id;
        struct twlreg_info              *info;
@@ -1241,7 +1241,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit twlreg_remove(struct platform_device *pdev)
+static int twlreg_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
        struct twlreg_info *info = rdev->reg_data;
@@ -1255,7 +1255,7 @@ MODULE_ALIAS("platform:twl_reg");
 
 static struct platform_driver twlreg_driver = {
        .probe          = twlreg_probe,
-       .remove         = __devexit_p(twlreg_remove),
+       .remove         = twlreg_remove,
        /* NOTE: short name, to work around driver model truncation of
         * "twl_regulator.12" (and friends) to "twl_regulator.1".
         */
diff --git a/drivers/regulator/vexpress.c b/drivers/regulator/vexpress.c
new file mode 100644 (file)
index 0000000..4668c7f
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * 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.
+ *
+ * Copyright (C) 2012 ARM Limited
+ */
+
+#define DRVNAME "vexpress-regulator"
+#define pr_fmt(fmt) DRVNAME ": " fmt
+
+#include <linux/device.h>
+#include <linux/err.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/regulator/driver.h>
+#include <linux/regulator/machine.h>
+#include <linux/regulator/of_regulator.h>
+#include <linux/vexpress.h>
+
+struct vexpress_regulator {
+       struct regulator_desc desc;
+       struct regulator_dev *regdev;
+       struct vexpress_config_func *func;
+};
+
+static int vexpress_regulator_get_voltage(struct regulator_dev *regdev)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+       u32 uV;
+       int err = vexpress_config_read(reg->func, 0, &uV);
+
+       return err ? err : uV;
+}
+
+static int vexpress_regulator_set_voltage(struct regulator_dev *regdev,
+               int min_uV, int max_uV, unsigned *selector)
+{
+       struct vexpress_regulator *reg = rdev_get_drvdata(regdev);
+
+       return vexpress_config_write(reg->func, 0, min_uV);
+}
+
+static struct regulator_ops vexpress_regulator_ops_ro = {
+       .get_voltage = vexpress_regulator_get_voltage,
+};
+
+static struct regulator_ops vexpress_regulator_ops = {
+       .get_voltage = vexpress_regulator_get_voltage,
+       .set_voltage = vexpress_regulator_set_voltage,
+};
+
+static int vexpress_regulator_probe(struct platform_device *pdev)
+{
+       int err;
+       struct vexpress_regulator *reg;
+       struct regulator_init_data *init_data;
+       struct regulator_config config = { };
+
+       reg = devm_kzalloc(&pdev->dev, sizeof(*reg), GFP_KERNEL);
+       if (!reg) {
+               err = -ENOMEM;
+               goto error_kzalloc;
+       }
+
+       reg->func = vexpress_config_func_get_by_dev(&pdev->dev);
+       if (!reg->func) {
+               err = -ENXIO;
+               goto error_get_func;
+       }
+
+       reg->desc.name = dev_name(&pdev->dev);
+       reg->desc.type = REGULATOR_VOLTAGE;
+       reg->desc.owner = THIS_MODULE;
+       reg->desc.continuous_voltage_range = true;
+
+       init_data = of_get_regulator_init_data(&pdev->dev, pdev->dev.of_node);
+       if (!init_data) {
+               err = -EINVAL;
+               goto error_get_regulator_init_data;
+       }
+
+       init_data->constraints.apply_uV = 0;
+       if (init_data->constraints.min_uV && init_data->constraints.max_uV)
+               reg->desc.ops = &vexpress_regulator_ops;
+       else
+               reg->desc.ops = &vexpress_regulator_ops_ro;
+
+       config.dev = &pdev->dev;
+       config.init_data = init_data;
+       config.driver_data = reg;
+       config.of_node = pdev->dev.of_node;
+
+       reg->regdev = regulator_register(&reg->desc, &config);
+       if (IS_ERR(reg->regdev)) {
+               err = PTR_ERR(reg->regdev);
+               goto error_regulator_register;
+       }
+
+       platform_set_drvdata(pdev, reg);
+
+       return 0;
+
+error_regulator_register:
+error_get_regulator_init_data:
+       vexpress_config_func_put(reg->func);
+error_get_func:
+error_kzalloc:
+       return err;
+}
+
+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;
+}
+
+static struct of_device_id vexpress_regulator_of_match[] = {
+       { .compatible = "arm,vexpress-volt", },
+       { }
+};
+
+static struct platform_driver vexpress_regulator_driver = {
+       .probe = vexpress_regulator_probe,
+       .remove = vexpress_regulator_remove,
+       .driver = {
+               .name = DRVNAME,
+               .owner = THIS_MODULE,
+               .of_match_table = vexpress_regulator_of_match,
+       },
+};
+
+module_platform_driver(vexpress_regulator_driver);
+
+MODULE_AUTHOR("Pawel Moll <pawel.moll@arm.com>");
+MODULE_DESCRIPTION("Versatile Express regulator");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:vexpress-regulator");
index c038e74225381ea760f9e3984d62eb802af86814..01c66e9712a4aa236ba36ed409abbbce51cd66f2 100644 (file)
@@ -285,7 +285,7 @@ static const struct attribute_group regulator_virtual_attr_group = {
        .attrs  = regulator_virtual_attributes,
 };
 
-static int __devinit regulator_virtual_probe(struct platform_device *pdev)
+static int regulator_virtual_probe(struct platform_device *pdev)
 {
        char *reg_id = pdev->dev.platform_data;
        struct virtual_consumer_data *drvdata;
@@ -321,7 +321,7 @@ static int __devinit regulator_virtual_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit regulator_virtual_remove(struct platform_device *pdev)
+static int regulator_virtual_remove(struct platform_device *pdev)
 {
        struct virtual_consumer_data *drvdata = platform_get_drvdata(pdev);
 
@@ -337,7 +337,7 @@ static int __devexit regulator_virtual_remove(struct platform_device *pdev)
 
 static struct platform_driver regulator_virtual_consumer_driver = {
        .probe          = regulator_virtual_probe,
-       .remove         = __devexit_p(regulator_virtual_remove),
+       .remove         = regulator_virtual_remove,
        .driver         = {
                .name           = "reg-virt-consumer",
                .owner          = THIS_MODULE,
index 782c228a19bd503ccda868ac67f46cce7fbba2e7..bce25658e12eed041634ec513aab391636b47b83 100644 (file)
@@ -290,7 +290,7 @@ static int wm831x_buckv_set_voltage_sel(struct regulator_dev *rdev,
        if (vsel > dcdc->dvs_vsel) {
                ret = wm831x_set_bits(wm831x, dvs_reg,
                                      WM831X_DC1_DVS_VSEL_MASK,
-                                     dcdc->dvs_vsel);
+                                     vsel);
                if (ret == 0)
                        dcdc->dvs_vsel = vsel;
                else
@@ -387,7 +387,7 @@ 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 __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
+static void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
                                            struct wm831x_buckv_pdata *pdata)
 {
        struct wm831x *wm831x = dcdc->wm831x;
@@ -448,7 +448,7 @@ static __devinit void wm831x_buckv_dvs_init(struct wm831x_dcdc *dcdc,
        }
 }
 
-static __devinit int wm831x_buckv_probe(struct platform_device *pdev)
+static int wm831x_buckv_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -562,7 +562,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
+static int wm831x_buckv_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
        struct wm831x *wm831x = dcdc->wm831x;
@@ -582,7 +582,7 @@ static __devexit int wm831x_buckv_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckv_driver = {
        .probe = wm831x_buckv_probe,
-       .remove = __devexit_p(wm831x_buckv_remove),
+       .remove = wm831x_buckv_remove,
        .driver         = {
                .name   = "wm831x-buckv",
                .owner  = THIS_MODULE,
@@ -623,7 +623,7 @@ static struct regulator_ops wm831x_buckp_ops = {
        .set_suspend_mode = wm831x_dcdc_set_suspend_mode,
 };
 
-static __devinit int wm831x_buckp_probe(struct platform_device *pdev)
+static int wm831x_buckp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -710,7 +710,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
+static int wm831x_buckp_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -725,7 +725,7 @@ static __devexit int wm831x_buckp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_buckp_driver = {
        .probe = wm831x_buckp_probe,
-       .remove = __devexit_p(wm831x_buckp_remove),
+       .remove = wm831x_buckp_remove,
        .driver         = {
                .name   = "wm831x-buckp",
                .owner  = THIS_MODULE,
@@ -771,7 +771,7 @@ static struct regulator_ops wm831x_boostp_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_boostp_probe(struct platform_device *pdev)
+static int wm831x_boostp_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -845,7 +845,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
+static int wm831x_boostp_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -860,7 +860,7 @@ static __devexit int wm831x_boostp_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_boostp_driver = {
        .probe = wm831x_boostp_probe,
-       .remove = __devexit_p(wm831x_boostp_remove),
+       .remove = wm831x_boostp_remove,
        .driver         = {
                .name   = "wm831x-boostp",
                .owner  = THIS_MODULE,
@@ -883,7 +883,7 @@ static struct regulator_ops wm831x_epe_ops = {
        .get_status = wm831x_dcdc_get_status,
 };
 
-static __devinit int wm831x_epe_probe(struct platform_device *pdev)
+static int wm831x_epe_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -936,7 +936,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_epe_remove(struct platform_device *pdev)
+static int wm831x_epe_remove(struct platform_device *pdev)
 {
        struct wm831x_dcdc *dcdc = platform_get_drvdata(pdev);
 
@@ -948,7 +948,7 @@ static __devexit int wm831x_epe_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_epe_driver = {
        .probe = wm831x_epe_probe,
-       .remove = __devexit_p(wm831x_epe_remove),
+       .remove = wm831x_epe_remove,
        .driver         = {
                .name   = "wm831x-epe",
                .owner  = THIS_MODULE,
index 2646a1902b33fe6287ee4bfea055c5c0d952fba5..68586ee3e1cb18197f64ea68d7cbee9e963408fc 100644 (file)
@@ -148,7 +148,7 @@ static irqreturn_t wm831x_isink_irq(int irq, void *data)
 }
 
 
-static __devinit int wm831x_isink_probe(struct platform_device *pdev)
+static int wm831x_isink_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -221,7 +221,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_isink_remove(struct platform_device *pdev)
+static int wm831x_isink_remove(struct platform_device *pdev)
 {
        struct wm831x_isink *isink = platform_get_drvdata(pdev);
 
@@ -236,7 +236,7 @@ static __devexit int wm831x_isink_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_isink_driver = {
        .probe = wm831x_isink_probe,
-       .remove = __devexit_p(wm831x_isink_remove),
+       .remove = wm831x_isink_remove,
        .driver         = {
                .name   = "wm831x-isink",
                .owner  = THIS_MODULE,
index c2dc03993dc7011d5ce9c87726cea6f25579d8c3..1ec379a9a95c88807c9987b23568e892b14bdc1a 100644 (file)
@@ -247,7 +247,7 @@ static struct regulator_ops wm831x_gp_ldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_gp_ldo_probe(struct platform_device *pdev)
+static int wm831x_gp_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -334,7 +334,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
+static int wm831x_gp_ldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -349,7 +349,7 @@ static __devexit int wm831x_gp_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_gp_ldo_driver = {
        .probe = wm831x_gp_ldo_probe,
-       .remove = __devexit_p(wm831x_gp_ldo_remove),
+       .remove = wm831x_gp_ldo_remove,
        .driver         = {
                .name   = "wm831x-ldo",
                .owner  = THIS_MODULE,
@@ -504,7 +504,7 @@ static struct regulator_ops wm831x_aldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_aldo_probe(struct platform_device *pdev)
+static int wm831x_aldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -590,7 +590,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
+static int wm831x_aldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -603,7 +603,7 @@ static __devexit int wm831x_aldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_aldo_driver = {
        .probe = wm831x_aldo_probe,
-       .remove = __devexit_p(wm831x_aldo_remove),
+       .remove = wm831x_aldo_remove,
        .driver         = {
                .name   = "wm831x-aldo",
                .owner  = THIS_MODULE,
@@ -660,7 +660,7 @@ static struct regulator_ops wm831x_alive_ldo_ops = {
        .disable = regulator_disable_regmap,
 };
 
-static __devinit int wm831x_alive_ldo_probe(struct platform_device *pdev)
+static int wm831x_alive_ldo_probe(struct platform_device *pdev)
 {
        struct wm831x *wm831x = dev_get_drvdata(pdev->dev.parent);
        struct wm831x_pdata *pdata = wm831x->dev->platform_data;
@@ -737,7 +737,7 @@ err:
        return ret;
 }
 
-static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
+static int wm831x_alive_ldo_remove(struct platform_device *pdev)
 {
        struct wm831x_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -748,7 +748,7 @@ static __devexit int wm831x_alive_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm831x_alive_ldo_driver = {
        .probe = wm831x_alive_ldo_probe,
-       .remove = __devexit_p(wm831x_alive_ldo_remove),
+       .remove = wm831x_alive_ldo_remove,
        .driver         = {
                .name   = "wm831x-alive-ldo",
                .owner  = THIS_MODULE,
index 27c746ef06364d2f02e95b8928ed748a31de6b1d..c6a32ea80b9d2aa063408f6ac38d11622253f477 100644 (file)
@@ -226,7 +226,7 @@ static struct regulator_desc regulators[] = {
        },
 };
 
-static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
+static int wm8400_regulator_probe(struct platform_device *pdev)
 {
        struct wm8400 *wm8400 = container_of(pdev, struct wm8400, regulators[pdev->id]);
        struct regulator_config config = { };
@@ -246,7 +246,7 @@ static int __devinit wm8400_regulator_probe(struct platform_device *pdev)
        return 0;
 }
 
-static int __devexit wm8400_regulator_remove(struct platform_device *pdev)
+static int wm8400_regulator_remove(struct platform_device *pdev)
 {
        struct regulator_dev *rdev = platform_get_drvdata(pdev);
 
@@ -261,7 +261,7 @@ static struct platform_driver wm8400_regulator_driver = {
                .name = "wm8400-regulator",
        },
        .probe = wm8400_regulator_probe,
-       .remove = __devexit_p(wm8400_regulator_remove),
+       .remove = wm8400_regulator_remove,
 };
 
 /**
index 86bb48db149ed3d2bb1285f9dd4a24fb28a531f2..6ff872342648cc2cacbf23565826715b0d3bbff7 100644 (file)
@@ -99,7 +99,7 @@ static const struct regulator_desc wm8994_ldo_desc[] = {
        },
 };
 
-static __devinit int wm8994_ldo_probe(struct platform_device *pdev)
+static int wm8994_ldo_probe(struct platform_device *pdev)
 {
        struct wm8994 *wm8994 = dev_get_drvdata(pdev->dev.parent);
        struct wm8994_pdata *pdata = wm8994->dev->platform_data;
@@ -142,7 +142,7 @@ err:
        return ret;
 }
 
-static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
+static int wm8994_ldo_remove(struct platform_device *pdev)
 {
        struct wm8994_ldo *ldo = platform_get_drvdata(pdev);
 
@@ -155,7 +155,7 @@ static __devexit int wm8994_ldo_remove(struct platform_device *pdev)
 
 static struct platform_driver wm8994_ldo_driver = {
        .probe = wm8994_ldo_probe,
-       .remove = __devexit_p(wm8994_ldo_remove),
+       .remove = wm8994_ldo_remove,
        .driver         = {
                .name   = "wm8994-ldo",
                .owner  = THIS_MODULE,
index 7671a287dfee4f592e909c15bcc0c14cac47bb7a..ba26e99c388d0a7f6105ce9181cdc0f94e42736a 100644 (file)
@@ -76,6 +76,7 @@
 #define ARIZONA_RATE_ESTIMATOR_3                 0x154
 #define ARIZONA_RATE_ESTIMATOR_4                 0x155
 #define ARIZONA_RATE_ESTIMATOR_5                 0x156
+#define ARIZONA_DYNAMIC_FREQUENCY_SCALING_1      0x161
 #define ARIZONA_FLL1_CONTROL_1                   0x171
 #define ARIZONA_FLL1_CONTROL_2                   0x172
 #define ARIZONA_FLL1_CONTROL_3                   0x173
 #define ARIZONA_FLL2_GPIO_CLOCK                  0x1AA
 #define ARIZONA_MIC_CHARGE_PUMP_1                0x200
 #define ARIZONA_LDO1_CONTROL_1                   0x210
+#define ARIZONA_LDO1_CONTROL_2                   0x212
 #define ARIZONA_LDO2_CONTROL_1                   0x213
 #define ARIZONA_MIC_BIAS_CTRL_1                  0x218
 #define ARIZONA_MIC_BIAS_CTRL_2                  0x219
 #define ARIZONA_SAMPLE_RATE_DETECT_D_SHIFT            0  /* SAMPLE_RATE_DETECT_D - [4:0] */
 #define ARIZONA_SAMPLE_RATE_DETECT_D_WIDTH            5  /* SAMPLE_RATE_DETECT_D - [4:0] */
 
+/*
+ * R353 (0x161) - Dynamic Frequency Scaling 1
+ */
+#define ARIZONA_SUBSYS_MAX_FREQ                  0x0001  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_SHIFT                 0  /* SUBSYS_MAX_FREQ */
+#define ARIZONA_SUBSYS_MAX_FREQ_WIDTH                 1  /* SUBSYS_MAX_FREQ */
+
 /*
  * R369 (0x171) - FLL1 Control 1
  */
 #define ARIZONA_LDO1_ENA_SHIFT                        0  /* LDO1_ENA */
 #define ARIZONA_LDO1_ENA_WIDTH                        1  /* LDO1_ENA */
 
+/*
+ * R530 (0x212) - LDO1 Control 2
+ */
+#define ARIZONA_LDO1_HI_PWR                      0x0001  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_SHIFT                     0  /* LDO1_HI_PWR */
+#define ARIZONA_LDO1_HI_PWR_WIDTH                     1  /* LDO1_HI_PWR */
+
 /*
  * R531 (0x213) - LDO2 Control 1
  */
index 147293b4471d6811248388c3932e89e65a3b844b..f87a6c172a917f860976e90a62ddd8c790e4266e 100644 (file)
@@ -25,8 +25,29 @@ struct da9055_pdata {
        int gpio_base;
 
        struct regulator_init_data *regulators[DA9055_MAX_REGULATORS];
-       bool reset_enable;              /* Enable RTC in RESET Mode */
-       enum gpio_select *gpio_rsel;    /* Select regulator set thru GPIO 1/2 */
-       enum gpio_select *gpio_ren;     /* Enable regulator thru GPIO 1/2 */
+       /* Enable RTC in RESET Mode */
+       bool reset_enable;
+       /*
+        * GPI muxed pin to control
+        * regulator state A/B, 0 if not available.
+        */
+       int *gpio_ren;
+       /*
+        * GPI muxed pin to control
+        * regulator set, 0 if not available.
+        */
+       int *gpio_rsel;
+       /*
+        * Regulator mode control bits value (GPI offset) that
+        * that controls the regulator state, 0 if not available.
+        */
+       enum gpio_select *reg_ren;
+       /*
+        * Regulator mode control bits value (GPI offset) that
+        * controls the regulator set A/B, 0 if  not available.
+        */
+       enum gpio_select *reg_rsel;
+       /* GPIOs to enable regulator, 0 if not available */
+       int *ena_gpio;
 };
 #endif /* __DA9055_PDATA_H */
index 6bc31d854626b26f62994f0810a143ee00027e17..804e280c1e1d9a2a18157b377bfef9f622834cc7 100644 (file)
 
 #include <linux/irq.h>
 
+/* TPS65090 Regulator ID */
+enum {
+       TPS65090_REGULATOR_DCDC1,
+       TPS65090_REGULATOR_DCDC2,
+       TPS65090_REGULATOR_DCDC3,
+       TPS65090_REGULATOR_FET1,
+       TPS65090_REGULATOR_FET2,
+       TPS65090_REGULATOR_FET3,
+       TPS65090_REGULATOR_FET4,
+       TPS65090_REGULATOR_FET5,
+       TPS65090_REGULATOR_FET6,
+       TPS65090_REGULATOR_FET7,
+       TPS65090_REGULATOR_LDO1,
+       TPS65090_REGULATOR_LDO2,
+
+       /* Last entry for maximum ID */
+       TPS65090_REGULATOR_MAX,
+};
+
 struct tps65090 {
        struct mutex            lock;
        struct device           *dev;
@@ -41,10 +60,26 @@ struct tps65090_subdev_info {
        void            *platform_data;
 };
 
+/*
+ * struct tps65090_regulator_plat_data
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_ext_control: Enable extrenal control or not. Only available for
+ *     DCDC1, DCDC2 and DCDC3.
+ * @gpio: Gpio number if external control is enabled and controlled through
+ *     gpio.
+ */
+struct tps65090_regulator_plat_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_ext_control;
+       int gpio;
+};
+
 struct tps65090_platform_data {
        int irq_base;
        int num_subdevs;
        struct tps65090_subdev_info *subdevs;
+       struct tps65090_regulator_plat_data *reg_pdata[TPS65090_REGULATOR_MAX];
 };
 
 /*
index 2dd123194958afe1551c63d30cc16dc200410f1e..f8da0e152567059e0d0928c844e70dda7a94cc4a 100644 (file)
@@ -29,6 +29,7 @@ enum {
        TPS6586X_ID_LDO_8,
        TPS6586X_ID_LDO_9,
        TPS6586X_ID_LDO_RTC,
+       TPS6586X_ID_MAX_REGULATOR,
 };
 
 enum {
@@ -79,6 +80,8 @@ struct tps6586x_platform_data {
        int gpio_base;
        int irq_base;
        bool pm_off;
+
+       struct regulator_init_data *reg_init_data[TPS6586X_ID_MAX_REGULATOR];
 };
 
 /*
index c43cd3556b1f5b789bae79de586f7e85a4cafacc..5d0f7c10bef1cb1ae86574b1c170574732cb5a77 100644 (file)
@@ -160,6 +160,7 @@ int regulator_bulk_force_disable(int num_consumers,
 void regulator_bulk_free(int num_consumers,
                         struct regulator_bulk_data *consumers);
 
+int regulator_can_change_voltage(struct regulator *regulator);
 int regulator_count_voltages(struct regulator *regulator);
 int regulator_list_voltage(struct regulator *regulator, unsigned selector);
 int regulator_is_supported_voltage(struct regulator *regulator,
index 7932a3bf21bdba89f84275b7b990bcaa3a5773b0..f2b72b230b9ba495965c1b5fa4ddd1d619e10608 100644 (file)
@@ -181,6 +181,8 @@ enum regulator_type {
  * @type: Indicates if the regulator is a voltage or current regulator.
  * @owner: Module providing the regulator, used for refcounting.
  *
+ * @continuous_voltage_range: Indicates if the regulator can set any
+ *                            voltage within constrains range.
  * @n_voltages: Number of selectors available for ops.list_voltage().
  *
  * @min_uV: Voltage given by the lowest selector (if linear mapping)
@@ -199,6 +201,7 @@ struct regulator_desc {
        const char *name;
        const char *supply_name;
        int id;
+       bool continuous_voltage_range;
        unsigned n_voltages;
        struct regulator_ops *ops;
        int irq;
diff --git a/include/linux/regulator/tps51632-regulator.h b/include/linux/regulator/tps51632-regulator.h
new file mode 100644 (file)
index 0000000..d00841e
--- /dev/null
@@ -0,0 +1,47 @@
+/*
+ * tps51632-regulator.h -- TPS51632 regulator
+ *
+ * Interface for regulator driver for TPS51632 3-2-1 Phase D-Cap Step Down
+ * Driverless Controller with serial VID control and DVFS.
+ *
+ * Copyright (C) 2012 NVIDIA Corporation
+
+ * 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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef __LINUX_REGULATOR_TPS51632_H
+#define __LINUX_REGULATOR_TPS51632_H
+
+/*
+ * struct tps51632_regulator_platform_data - tps51632 regulator platform data.
+ *
+ * @reg_init_data: The regulator init data.
+ * @enable_pwm_dvfs: Enable PWM DVFS or not.
+ * @dvfs_step_20mV: Step for DVFS is 20mV or 10mV.
+ * @max_voltage_uV: Maximum possible voltage in PWM-DVFS mode.
+ * @base_voltage_uV: Base voltage when PWM-DVFS enabled.
+ */
+struct tps51632_regulator_platform_data {
+       struct regulator_init_data *reg_init_data;
+       bool enable_pwm_dvfs;
+       bool dvfs_step_20mV;
+       int max_voltage_uV;
+       int base_voltage_uV;
+};
+
+#endif /* __LINUX_REGULATOR_TPS51632_H */
diff --git a/include/linux/regulator/tps65090-regulator.h b/include/linux/regulator/tps65090-regulator.h
deleted file mode 100644 (file)
index 0fa04b6..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * Regulator driver interface for TI TPS65090 PMIC family
- *
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
-
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
-
- * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __REGULATOR_TPS65090_H
-#define __REGULATOR_TPS65090_H
-
-#include <linux/regulator/machine.h>
-
-#define tps65090_rails(_name) "tps65090_"#_name
-
-enum {
-       TPS65090_ID_DCDC1,
-       TPS65090_ID_DCDC2,
-       TPS65090_ID_DCDC3,
-       TPS65090_ID_FET1,
-       TPS65090_ID_FET2,
-       TPS65090_ID_FET3,
-       TPS65090_ID_FET4,
-       TPS65090_ID_FET5,
-       TPS65090_ID_FET6,
-       TPS65090_ID_FET7,
-};
-
-/*
- * struct tps65090_regulator_platform_data
- *
- * @regulator: The regulator init data.
- * @slew_rate_uV_per_us: Slew rate microvolt per microsec.
- */
-
-struct tps65090_regulator_platform_data {
-       struct regulator_init_data regulator;
-};
-
-#endif /* __REGULATOR_TPS65090_H */