Merge branch 'next' of git://git.infradead.org/users/vkoul/slave-dma
[pandora-kernel.git] / drivers / regulator / twl-regulator.c
index 9cdfc38..c739071 100644 (file)
@@ -12,7 +12,6 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/err.h>
-#include <linux/delay.h>
 #include <linux/platform_device.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
@@ -175,15 +174,14 @@ static int twl6030reg_is_enabled(struct regulator_dev *rdev)
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
        int                     grp = 0, val;
 
-       if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
-               grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
-       if (grp < 0)
-               return grp;
-
-       if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
+       if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS))) {
+               grp = twlreg_grp(rdev);
+               if (grp < 0)
+                       return grp;
                grp &= P1_GRP_6030;
-       else
+       } else {
                grp = 1;
+       }
 
        val = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_STATE);
        val = TWL6030_CFG_STATE_APP(val);
@@ -197,7 +195,7 @@ static int twl4030reg_enable(struct regulator_dev *rdev)
        int                     grp;
        int                     ret;
 
-       grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+       grp = twlreg_grp(rdev);
        if (grp < 0)
                return grp;
 
@@ -205,8 +203,6 @@ static int twl4030reg_enable(struct regulator_dev *rdev)
 
        ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_GRP, grp);
 
-       udelay(info->delay);
-
        return ret;
 }
 
@@ -217,17 +213,28 @@ static int twl6030reg_enable(struct regulator_dev *rdev)
        int                     ret;
 
        if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
-               grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+               grp = twlreg_grp(rdev);
        if (grp < 0)
                return grp;
 
        ret = twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_STATE,
                        grp << TWL6030_CFG_STATE_GRP_SHIFT |
                        TWL6030_CFG_STATE_ON);
+       return ret;
+}
 
-       udelay(info->delay);
+static int twl4030reg_enable_time(struct regulator_dev *rdev)
+{
+       struct twlreg_info      *info = rdev_get_drvdata(rdev);
 
-       return ret;
+       return info->delay;
+}
+
+static int twl6030reg_enable_time(struct regulator_dev *rdev)
+{
+       struct twlreg_info      *info = rdev_get_drvdata(rdev);
+
+       return info->delay;
 }
 
 static int twl4030reg_disable(struct regulator_dev *rdev)
@@ -236,7 +243,7 @@ static int twl4030reg_disable(struct regulator_dev *rdev)
        int                     grp;
        int                     ret;
 
-       grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+       grp = twlreg_grp(rdev);
        if (grp < 0)
                return grp;
 
@@ -348,7 +355,7 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
        int val;
 
        if (!(twl_class_is_6030() && (info->features & TWL6025_SUBCLASS)))
-               grp = twlreg_read(info, TWL_MODULE_PM_RECEIVER, VREG_GRP);
+               grp = twlreg_grp(rdev);
 
        if (grp < 0)
                return grp;
@@ -388,14 +395,12 @@ static int twl6030reg_set_mode(struct regulator_dev *rdev, unsigned mode)
  * VAUX3 at 3V is incorrectly listed in some TI manuals as unsupported.
  * TI are revising the twl5030/tps659x0 specs to support that 3.0V setting.
  */
-#ifdef CONFIG_TWL4030_ALLOW_UNSUPPORTED
-#define UNSUP_MASK     0x0000
-#else
 #define UNSUP_MASK     0x8000
-#endif
 
 #define UNSUP(x)       (UNSUP_MASK | (x))
-#define IS_UNSUP(x)    (UNSUP_MASK & (x))
+#define IS_UNSUP(info, x)                      \
+       ((UNSUP_MASK & (x)) &&                  \
+        !((info)->features & TWL4030_ALLOW_UNSUPPORTED))
 #define LDO_MV(x)      (~UNSUP_MASK & (x))
 
 
@@ -469,35 +474,16 @@ static int twl4030ldo_list_voltage(struct regulator_dev *rdev, unsigned index)
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
        int                     mV = info->table[index];
 
-       return IS_UNSUP(mV) ? 0 : (LDO_MV(mV) * 1000);
+       return IS_UNSUP(info, mV) ? 0 : (LDO_MV(mV) * 1000);
 }
 
 static int
-twl4030ldo_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
-                      unsigned *selector)
+twl4030ldo_set_voltage_sel(struct regulator_dev *rdev, unsigned selector)
 {
        struct twlreg_info      *info = rdev_get_drvdata(rdev);
-       int                     vsel;
 
-       for (vsel = 0; vsel < info->table_len; vsel++) {
-               int mV = info->table[vsel];
-               int uV;
-
-               if (IS_UNSUP(mV))
-                       continue;
-               uV = LDO_MV(mV) * 1000;
-
-               /* REVISIT for VAUX2, first match may not be best/lowest */
-
-               /* use the first in-range value */
-               if (min_uV <= uV && uV <= max_uV) {
-                       *selector = vsel;
-                       return twlreg_write(info, TWL_MODULE_PM_RECEIVER,
-                                                       VREG_VOLTAGE, vsel);
-               }
-       }
-
-       return -EDOM;
+       return twlreg_write(info, TWL_MODULE_PM_RECEIVER, VREG_VOLTAGE,
+                           selector);
 }
 
 static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
@@ -516,12 +502,13 @@ static int twl4030ldo_get_voltage(struct regulator_dev *rdev)
 static struct regulator_ops twl4030ldo_ops = {
        .list_voltage   = twl4030ldo_list_voltage,
 
-       .set_voltage    = twl4030ldo_set_voltage,
+       .set_voltage_sel = twl4030ldo_set_voltage_sel,
        .get_voltage    = twl4030ldo_get_voltage,
 
        .enable         = twl4030reg_enable,
        .disable        = twl4030reg_disable,
        .is_enabled     = twl4030reg_is_enabled,
+       .enable_time    = twl4030reg_enable_time,
 
        .set_mode       = twl4030reg_set_mode,
 
@@ -642,6 +629,7 @@ static struct regulator_ops twl6030ldo_ops = {
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
+       .enable_time    = twl6030reg_enable_time,
 
        .set_mode       = twl6030reg_set_mode,
 
@@ -675,6 +663,7 @@ static struct regulator_ops twl4030fixed_ops = {
        .enable         = twl4030reg_enable,
        .disable        = twl4030reg_disable,
        .is_enabled     = twl4030reg_is_enabled,
+       .enable_time    = twl4030reg_enable_time,
 
        .set_mode       = twl4030reg_set_mode,
 
@@ -689,6 +678,7 @@ static struct regulator_ops twl6030fixed_ops = {
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
+       .enable_time    = twl6030reg_enable_time,
 
        .set_mode       = twl6030reg_set_mode,
 
@@ -699,6 +689,7 @@ static struct regulator_ops twl6030_fixed_resource = {
        .enable         = twl6030reg_enable,
        .disable        = twl6030reg_disable,
        .is_enabled     = twl6030reg_is_enabled,
+       .enable_time    = twl6030reg_enable_time,
        .get_status     = twl6030reg_get_status,
 };
 
@@ -806,10 +797,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
                        vsel = 0;
                else if ((min_uV >= 600000) && (min_uV <= 1300000)) {
                        int calc_uV;
-                       vsel = (min_uV - 600000) / 125;
-                       if (vsel % 100)
-                               vsel += 100;
-                       vsel /= 100;
+                       vsel = DIV_ROUND_UP(min_uV - 600000, 12500);
                        vsel++;
                        calc_uV = twl6030smps_list_voltage(rdev, vsel);
                        if (calc_uV > max_uV)
@@ -836,10 +824,7 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
                        vsel = 0;
                else if ((min_uV >= 700000) && (min_uV <= 1420000)) {
                        int calc_uV;
-                       vsel = (min_uV - 700000) / 125;
-                       if (vsel % 100)
-                               vsel += 100;
-                       vsel /= 100;
+                       vsel = DIV_ROUND_UP(min_uV - 700000, 12500);
                        vsel++;
                        calc_uV = twl6030smps_list_voltage(rdev, vsel);
                        if (calc_uV > max_uV)
@@ -862,24 +847,18 @@ twl6030smps_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV,
                        return -EINVAL;
                break;
        case SMPS_EXTENDED_EN:
-               if (min_uV == 0)
+               if (min_uV == 0) {
                        vsel = 0;
-               else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
-                       vsel = (min_uV - 1852000) / 386;
-                       if (vsel % 100)
-                               vsel += 100;
-                       vsel /= 100;
+               } else if ((min_uV >= 1852000) && (max_uV <= 4013600)) {
+                       vsel = DIV_ROUND_UP(min_uV - 1852000, 38600);
                        vsel++;
                }
                break;
        case SMPS_OFFSET_EN|SMPS_EXTENDED_EN:
-               if (min_uV == 0)
+               if (min_uV == 0) {
                        vsel = 0;
-               else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
-                       vsel = (min_uV - 2161000) / 386;
-                       if (vsel % 100)
-                               vsel += 100;
-                       vsel /= 100;
+               } else if ((min_uV >= 2161000) && (max_uV <= 4321000)) {
+                       vsel = DIV_ROUND_UP(min_uV - 2161000, 38600);
                        vsel++;
                }
                break;
@@ -907,6 +886,7 @@ static struct regulator_ops twlsmps_ops = {
        .enable                 = twl6030reg_enable,
        .disable                = twl6030reg_disable,
        .is_enabled             = twl6030reg_is_enabled,
+       .enable_time            = twl6030reg_enable_time,
 
        .set_mode               = twl6030reg_set_mode,
 
@@ -1194,6 +1174,7 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
        struct regulator_dev            *rdev;
        struct twl_regulator_driver_data        *drvdata;
        const struct of_device_id       *match;
+       struct regulator_config         config = { };
 
        match = of_match_device(twl_of_match, &pdev->dev);
        if (match) {
@@ -1207,10 +1188,12 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
                initdata = pdev->dev.platform_data;
                for (i = 0, info = NULL; i < ARRAY_SIZE(twl_of_match); i++) {
                        info = twl_of_match[i].data;
-                       if (!info || info->desc.id != id)
-                               continue;
-                       break;
+                       if (info && info->desc.id == id)
+                               break;
                }
+               if (i == ARRAY_SIZE(twl_of_match))
+                       return -ENODEV;
+
                drvdata = initdata->driver_data;
                if (!drvdata)
                        return -EINVAL;
@@ -1273,8 +1256,12 @@ static int __devinit twlreg_probe(struct platform_device *pdev)
                break;
        }
 
-       rdev = regulator_register(&info->desc, &pdev->dev, initdata, info,
-                                                       pdev->dev.of_node);
+       config.dev = &pdev->dev;
+       config.init_data = initdata;
+       config.driver_data = info;
+       config.of_node = pdev->dev.of_node;
+
+       rdev = regulator_register(&info->desc, &config);
        if (IS_ERR(rdev)) {
                dev_err(&pdev->dev, "can't register %s, %ld\n",
                                info->desc.name, PTR_ERR(rdev));