]> Pileus Git - ~andy/linux/blobdiff - drivers/regulator/ab8500.c
Merge remote-tracking branch 'regulator/topic/lp8788' into v3.9-rc8
[~andy/linux] / drivers / regulator / ab8500.c
index 5fd3b34274cc9665f1453a323e53545596f7392a..f6656b8c28b606f49cbecc8d47a63d9d61832a47 100644 (file)
@@ -61,7 +61,6 @@ struct ab8500_shared_mode {
  * @voltage_bank: bank to control regulator voltage
  * @voltage_reg: register to control regulator voltage
  * @voltage_mask: mask to control regulator voltage
- * @voltage_shift: shift to control regulator voltage
  */
 struct ab8500_regulator_info {
        struct device           *dev;
@@ -83,13 +82,11 @@ struct ab8500_regulator_info {
        u8 voltage_bank;
        u8 voltage_reg;
        u8 voltage_mask;
-       u8 voltage_shift;
        struct {
                u8 voltage_limit;
                u8 voltage_bank;
                u8 voltage_reg;
                u8 voltage_mask;
-               u8 voltage_shift;
        } expand_register;
 };
 
@@ -348,11 +345,8 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
                                     unsigned int mode)
 {
        int ret = 0;
-       u8 bank;
-       u8 reg;
-       u8 mask;
-       u8 val;
-       bool dmr = false; /* Dedicated mode register */
+       u8 bank, reg, mask, val;
+       bool lp_mode_req = false;
        struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
 
        if (info == NULL) {
@@ -360,66 +354,54 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
                return -EINVAL;
        }
 
-       if (info->shared_mode) {
-               /*
-                * Special case where mode is shared between two regulators.
-                */
-               struct ab8500_shared_mode *sm = info->shared_mode;
-               mutex_lock(&shared_mode_mutex);
-
-               if (mode == REGULATOR_MODE_IDLE) {
-                       sm->lp_mode_req = true; /* Low power mode requested */
-                       if (!((sm->shared_regulator)->
-                             shared_mode->lp_mode_req)) {
-                               mutex_unlock(&shared_mode_mutex);
-                               return 0; /* Other regulator prevent LP mode */
-                       }
-               } else {
-                       sm->lp_mode_req = false;
-               }
-       }
-
        if (info->mode_mask) {
-               /* Dedicated register for handling mode */
-
-               dmr = true;
-
-               switch (mode) {
-               case REGULATOR_MODE_NORMAL:
-                       val = info->mode_val_normal;
-                       break;
-               case REGULATOR_MODE_IDLE:
-                       val = info->mode_val_idle;
-                       break;
-               default:
-                       ret = -EINVAL;
-                       goto out_unlock;
-               }
-
                bank = info->mode_bank;
                reg = info->mode_reg;
                mask = info->mode_mask;
        } else {
-               /* Mode register same as enable register */
+               bank = info->update_bank;
+               reg = info->update_reg;
+               mask = info->update_mask;
+       }
+
+       if (info->shared_mode)
+               mutex_lock(&shared_mode_mutex);
+
+       switch (mode) {
+       case REGULATOR_MODE_NORMAL:
+               if (info->shared_mode)
+                       lp_mode_req = false;
 
-               switch (mode) {
-               case REGULATOR_MODE_NORMAL:
+               if (info->mode_mask)
+                       val = info->mode_val_normal;
+               else
                        val = info->update_val_normal;
-                       break;
-               case REGULATOR_MODE_IDLE:
-                       val = info->update_val_idle;
-                       break;
-               default:
-                       ret = -EINVAL;
-                       goto out_unlock;
+               break;
+       case REGULATOR_MODE_IDLE:
+               if (info->shared_mode) {
+                       struct ab8500_regulator_info *shared_regulator;
+
+                       shared_regulator = info->shared_mode->shared_regulator;
+                       if (!shared_regulator->shared_mode->lp_mode_req) {
+                               /* Other regulator prevent LP mode */
+                               info->shared_mode->lp_mode_req = true;
+                               goto out_unlock;
+                       }
+
+                       lp_mode_req = true;
                }
 
-               bank = info->update_bank;
-               reg = info->update_reg;
-               mask = info->update_mask;
+               if (info->mode_mask)
+                       val = info->mode_val_idle;
+               else
+                       val = info->update_val_idle;
+               break;
+       default:
+               ret = -EINVAL;
+               goto out_unlock;
        }
 
-       if (dmr || ab8500_regulator_is_enabled(rdev)) {
+       if (info->mode_mask || ab8500_regulator_is_enabled(rdev)) {
                ret = abx500_mask_and_set_register_interruptible(info->dev,
                        bank, reg, mask, val);
                if (ret < 0) {
@@ -435,9 +417,12 @@ static int ab8500_regulator_set_mode(struct regulator_dev *rdev,
                        mask, val);
        }
 
-       if (!dmr)
+       if (!info->mode_mask)
                info->update_val = val;
 
+       if (info->shared_mode)
+               info->shared_mode->lp_mode_req = lp_mode_req;
+
 out_unlock:
        if (info->shared_mode)
                mutex_unlock(&shared_mode_mutex);
@@ -493,7 +478,7 @@ static unsigned int ab8500_regulator_get_mode(struct regulator_dev *rdev)
 
 static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
 {
-       int ret, val;
+       int ret, voltage_shift;
        struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
        u8 regval;
 
@@ -502,6 +487,8 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
                return -EINVAL;
        }
 
+       voltage_shift = ffs(info->voltage_mask) - 1;
+
        ret = abx500_get_register_interruptible(info->dev,
                        info->voltage_bank, info->voltage_reg, &regval);
        if (ret < 0) {
@@ -515,15 +502,14 @@ static int ab8500_regulator_get_voltage_sel(struct regulator_dev *rdev)
                "0x%x, 0x%x, 0x%x, 0x%x, 0x%x\n",
                info->desc.name, info->voltage_bank,
                info->voltage_reg, info->voltage_mask,
-               info->voltage_shift, regval);
+               voltage_shift, regval);
 
-       val = regval & info->voltage_mask;
-       return val >> info->voltage_shift;
+       return (regval & info->voltage_mask) >> voltage_shift;
 }
 
 static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev)
 {
-       int ret;
+       int ret, voltage_shift;
        struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
        u8 regval, regval_expand;
 
@@ -563,13 +549,15 @@ static int ab8540_aux3_regulator_get_voltage_sel(struct regulator_dev *rdev)
                 info->desc.name, info->voltage_bank, info->voltage_reg,
                 info->voltage_mask, regval);
 
-       return (regval & info->voltage_mask) >> info->voltage_shift;
+       voltage_shift = ffs(info->voltage_mask) - 1;
+
+       return (regval & info->voltage_mask) >> voltage_shift;
 }
 
 static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
                                            unsigned selector)
 {
-       int ret;
+       int ret, voltage_shift;
        struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
        u8 regval;
 
@@ -578,8 +566,10 @@ static int ab8500_regulator_set_voltage_sel(struct regulator_dev *rdev,
                return -EINVAL;
        }
 
+       voltage_shift = ffs(info->voltage_mask) - 1;
+
        /* set the registers for the request */
-       regval = (u8)selector << info->voltage_shift;
+       regval = (u8)selector << voltage_shift;
        ret = abx500_mask_and_set_register_interruptible(info->dev,
                        info->voltage_bank, info->voltage_reg,
                        info->voltage_mask, regval);
@@ -601,39 +591,54 @@ static int ab8540_aux3_regulator_set_voltage_sel(struct regulator_dev *rdev,
 {
        int ret;
        struct ab8500_regulator_info *info = rdev_get_drvdata(rdev);
-       u8 regval;
+       u8 regval, regval_expand;
 
        if (info == NULL) {
                dev_err(rdev_get_dev(rdev), "regulator info null pointer\n");
                return -EINVAL;
        }
 
-       if (selector >= info->expand_register.voltage_limit) {
-               /* Vaux3 bit4 has different layout */
-               regval = (u8)selector << info->expand_register.voltage_shift;
+       if (selector < info->expand_register.voltage_limit) {
+               int voltage_shift = ffs(info->voltage_mask) - 1;
+
+               regval = (u8)selector << voltage_shift;
                ret = abx500_mask_and_set_register_interruptible(info->dev,
-                                       info->expand_register.voltage_bank,
-                                       info->expand_register.voltage_reg,
-                                       info->expand_register.voltage_mask,
-                                       regval);
+                                       info->voltage_bank, info->voltage_reg,
+                                       info->voltage_mask, regval);
+               if (ret < 0) {
+                       dev_err(rdev_get_dev(rdev),
+                               "couldn't set voltage reg for regulator\n");
+                       return ret;
+               }
+
+               dev_vdbg(rdev_get_dev(rdev),
+                        "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
+                        info->desc.name, info->voltage_bank, info->voltage_reg,
+                        info->voltage_mask, regval);
+
+               regval_expand = 0;
        } else {
-               /* set the registers for the request */
-               regval = (u8)selector << info->voltage_shift;
-               ret = abx500_mask_and_set_register_interruptible(info->dev,
-                               info->voltage_bank, info->voltage_reg,
-                               info->voltage_mask, regval);
+               regval_expand = info->expand_register.voltage_mask;
        }
-       if (ret < 0)
+
+       ret = abx500_mask_and_set_register_interruptible(info->dev,
+                               info->expand_register.voltage_bank,
+                               info->expand_register.voltage_reg,
+                               info->expand_register.voltage_mask,
+                               regval_expand);
+       if (ret < 0) {
                dev_err(rdev_get_dev(rdev),
-                       "couldn't set voltage reg for regulator\n");
+                       "couldn't set expand voltage reg for regulator\n");
+               return ret;
+       }
 
        dev_vdbg(rdev_get_dev(rdev),
-                       "%s-set_voltage (bank, reg, mask, value): 0x%x, 0x%x, 0x%x,"
-                       " 0x%x\n",
-                       info->desc.name, info->voltage_bank, info->voltage_reg,
-                       info->voltage_mask, regval);
+                "%s-set_voltage expand (bank, reg, mask, value): 0x%x, 0x%x, 0x%x, 0x%x\n",
+                info->desc.name, info->expand_register.voltage_bank,
+                info->expand_register.voltage_reg,
+                info->expand_register.voltage_mask, regval_expand);
 
-       return ret;
+       return 0;
 }
 
 static struct regulator_ops ab8500_regulator_volt_mode_ops = {
@@ -791,7 +796,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x03,
                .voltage_reg            = 0x80,
                .voltage_mask           = 0x38,
-               .voltage_shift          = 3,
        },
 
        /*
@@ -1066,7 +1070,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x03,
                .voltage_reg            = 0x80,
                .voltage_mask           = 0x38,
-               .voltage_shift          = 3,
        },
 
        /*
@@ -1127,7 +1130,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x01,
                .voltage_reg            = 0x57,
                .voltage_mask           = 0x70,
-               .voltage_shift          = 4,
        },
        [AB8505_LDO_ANAMIC1] = {
                .desc = {
@@ -1327,7 +1329,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x03,
                .voltage_reg            = 0x80,
                .voltage_mask           = 0x38,
-               .voltage_shift          = 3,
        },
 
        /*
@@ -1531,7 +1532,6 @@ static struct ab8500_regulator_info
                        .voltage_bank           = 0x04,
                        .voltage_reg            = 0x01,
                        .voltage_mask           = 0x10,
-                       .voltage_shift          = 1,
                }
        },
        [AB8540_LDO_AUX4] = {
@@ -1623,7 +1623,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x03,
                .voltage_reg            = 0x80,
                .voltage_mask           = 0x38,
-               .voltage_shift          = 3,
        },
 
        /*
@@ -1725,7 +1724,6 @@ static struct ab8500_regulator_info
                .voltage_bank           = 0x03,
                .voltage_reg            = 0x83,
                .voltage_mask           = 0xc0,
-               .voltage_shift          = 6,
        },
 
        /*