Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/lliubbo...
[linux-2.6-block.git] / drivers / regulator / tps65912-regulator.c
index da00d88f94b7921b89384134d96a0d176cbfe999..b36799b1f530d0bf81484d471eea483c30a4914e 100644 (file)
@@ -114,10 +114,7 @@ struct tps65912_reg {
        struct mutex io_lock;
        int mode;
        int (*get_ctrl_reg)(int);
-       int dcdc1_range;
-       int dcdc2_range;
-       int dcdc3_range;
-       int dcdc4_range;
+       int dcdc_range[TPS65912_NUM_DCDC];
        int pwm_mode_reg;
        int eco_reg;
 };
@@ -125,46 +122,31 @@ struct tps65912_reg {
 static int tps65912_get_range(struct tps65912_reg *pmic, int id)
 {
        struct tps65912 *mfd = pmic->mfd;
-
-       if (id > TPS65912_REG_DCDC4)
-               return 0;
+       int range;
 
        switch (id) {
        case TPS65912_REG_DCDC1:
-               pmic->dcdc1_range = tps65912_reg_read(mfd,
-                                                       TPS65912_DCDC1_LIMIT);
-               if (pmic->dcdc1_range < 0)
-                       return pmic->dcdc1_range;
-               pmic->dcdc1_range = (pmic->dcdc1_range &
-                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
-               return pmic->dcdc1_range;
+               range = tps65912_reg_read(mfd, TPS65912_DCDC1_LIMIT);
+               break;
        case TPS65912_REG_DCDC2:
-               pmic->dcdc2_range = tps65912_reg_read(mfd,
-                                                       TPS65912_DCDC2_LIMIT);
-               if (pmic->dcdc2_range < 0)
-                       return pmic->dcdc2_range;
-               pmic->dcdc2_range = (pmic->dcdc2_range &
-                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
-               return pmic->dcdc2_range;
+               range = tps65912_reg_read(mfd, TPS65912_DCDC2_LIMIT);
+               break;
        case TPS65912_REG_DCDC3:
-               pmic->dcdc3_range = tps65912_reg_read(mfd,
-                                                       TPS65912_DCDC3_LIMIT);
-               if (pmic->dcdc3_range < 0)
-                       return pmic->dcdc3_range;
-               pmic->dcdc3_range = (pmic->dcdc3_range &
-                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
-               return pmic->dcdc3_range;
+               range = tps65912_reg_read(mfd, TPS65912_DCDC3_LIMIT);
+               break;
        case TPS65912_REG_DCDC4:
-               pmic->dcdc4_range = tps65912_reg_read(mfd,
-                                                       TPS65912_DCDC4_LIMIT);
-               if (pmic->dcdc4_range < 0)
-                       return pmic->dcdc4_range;
-               pmic->dcdc4_range = (pmic->dcdc4_range &
-                       DCDC_LIMIT_RANGE_MASK) >> DCDC_LIMIT_RANGE_SHIFT;
-               return pmic->dcdc4_range;
+               range = tps65912_reg_read(mfd, TPS65912_DCDC4_LIMIT);
+               break;
        default:
                return 0;
        }
+
+       if (range >= 0)
+               range = (range & DCDC_LIMIT_RANGE_MASK)
+                       >> DCDC_LIMIT_RANGE_SHIFT;
+
+       pmic->dcdc_range[id] = range;
+       return range;
 }
 
 static unsigned long tps65912_vsel_to_uv_range0(u8 vsel)
@@ -219,146 +201,30 @@ static unsigned long tps65912_vsel_to_uv_ldo(u8 vsel)
 
 static int tps65912_get_ctrl_register(int id)
 {
-       switch (id) {
-       case TPS65912_REG_DCDC1:
-               return TPS65912_DCDC1_AVS;
-       case TPS65912_REG_DCDC2:
-               return TPS65912_DCDC2_AVS;
-       case TPS65912_REG_DCDC3:
-               return TPS65912_DCDC3_AVS;
-       case TPS65912_REG_DCDC4:
-               return TPS65912_DCDC4_AVS;
-       case TPS65912_REG_LDO1:
-               return TPS65912_LDO1_AVS;
-       case TPS65912_REG_LDO2:
-               return TPS65912_LDO2_AVS;
-       case TPS65912_REG_LDO3:
-               return TPS65912_LDO3_AVS;
-       case TPS65912_REG_LDO4:
-               return TPS65912_LDO4_AVS;
-       case TPS65912_REG_LDO5:
-               return TPS65912_LDO5;
-       case TPS65912_REG_LDO6:
-               return TPS65912_LDO6;
-       case TPS65912_REG_LDO7:
-               return TPS65912_LDO7;
-       case TPS65912_REG_LDO8:
-               return TPS65912_LDO8;
-       case TPS65912_REG_LDO9:
-               return TPS65912_LDO9;
-       case TPS65912_REG_LDO10:
-               return TPS65912_LDO10;
-       default:
+       if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4)
+               return id * 3 + TPS65912_DCDC1_AVS;
+       else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10)
+               return id - TPS65912_REG_LDO5 + TPS65912_LDO5;
+       else
                return -EINVAL;
-       }
 }
 
-static int tps65912_get_dcdc_sel_register(struct tps65912_reg *pmic, int id)
+static int tps65912_get_sel_register(struct tps65912_reg *pmic, int id)
 {
        struct tps65912 *mfd = pmic->mfd;
-       int opvsel = 0, sr = 0;
+       int opvsel;
        u8 reg = 0;
 
-       if (id < TPS65912_REG_DCDC1 || id > TPS65912_REG_DCDC4)
-               return -EINVAL;
-
-       switch (id) {
-       case TPS65912_REG_DCDC1:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP);
-               sr = ((opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT);
-               if (sr)
-                       reg = TPS65912_DCDC1_AVS;
-               else
-                       reg = TPS65912_DCDC1_OP;
-               break;
-       case TPS65912_REG_DCDC2:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP);
-               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-               if (sr)
-                       reg = TPS65912_DCDC2_AVS;
-               else
-                       reg = TPS65912_DCDC2_OP;
-               break;
-       case TPS65912_REG_DCDC3:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP);
-               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-               if (sr)
-                       reg = TPS65912_DCDC3_AVS;
-               else
-                       reg = TPS65912_DCDC3_OP;
-               break;
-       case TPS65912_REG_DCDC4:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP);
-               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-               if (sr)
-                       reg = TPS65912_DCDC4_AVS;
+       if (id >= TPS65912_REG_DCDC1 && id <= TPS65912_REG_LDO4) {
+               opvsel = tps65912_reg_read(mfd, id * 3 + TPS65912_DCDC1_OP);
+               if (opvsel & OP_SELREG_MASK)
+                       reg = id * 3 + TPS65912_DCDC1_AVS;
                else
-                       reg = TPS65912_DCDC4_OP;
-               break;
-       }
-       return reg;
-}
-
-static int tps65912_get_ldo_sel_register(struct tps65912_reg *pmic, int id)
-{
-       struct tps65912 *mfd = pmic->mfd;
-       int opvsel = 0, sr = 0;
-       u8 reg = 0;
-
-       if (id < TPS65912_REG_LDO1 || id > TPS65912_REG_LDO10)
+                       reg = id * 3 + TPS65912_DCDC1_OP;
+       } else if (id >= TPS65912_REG_LDO5 && id <= TPS65912_REG_LDO10) {
+               reg = id - TPS65912_REG_LDO5 + TPS65912_LDO5;
+       } else {
                return -EINVAL;
-
-       switch (id) {
-       case TPS65912_REG_LDO1:
-               opvsel = tps65912_reg_read(mfd, TPS65912_LDO1_OP);
-               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-               if (sr)
-                       reg = TPS65912_LDO1_AVS;
-               else
-                       reg = TPS65912_LDO1_OP;
-               break;
-       case TPS65912_REG_LDO2:
-               opvsel = tps65912_reg_read(mfd, TPS65912_LDO2_OP);
-               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-               if (sr)
-                       reg = TPS65912_LDO2_AVS;
-               else
-                       reg = TPS65912_LDO2_OP;
-               break;
-       case TPS65912_REG_LDO3:
-               opvsel = tps65912_reg_read(mfd, TPS65912_LDO3_OP);
-               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-               if (sr)
-                       reg = TPS65912_LDO3_AVS;
-               else
-                       reg = TPS65912_LDO3_OP;
-               break;
-       case TPS65912_REG_LDO4:
-               opvsel = tps65912_reg_read(mfd, TPS65912_LDO4_OP);
-               sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-               if (sr)
-                       reg = TPS65912_LDO4_AVS;
-               else
-                       reg = TPS65912_LDO4_OP;
-               break;
-       case TPS65912_REG_LDO5:
-               reg = TPS65912_LDO5;
-               break;
-       case TPS65912_REG_LDO6:
-               reg = TPS65912_LDO6;
-               break;
-       case TPS65912_REG_LDO7:
-               reg = TPS65912_LDO7;
-               break;
-       case TPS65912_REG_LDO8:
-               reg = TPS65912_LDO8;
-               break;
-       case TPS65912_REG_LDO9:
-               reg = TPS65912_LDO9;
-               break;
-       case TPS65912_REG_LDO10:
-               reg = TPS65912_LDO10;
-               break;
        }
 
        return reg;
@@ -506,151 +372,83 @@ static unsigned int tps65912_get_mode(struct regulator_dev *dev)
        return mode;
 }
 
-static int tps65912_get_voltage_dcdc(struct regulator_dev *dev)
+static int tps65912_list_voltage_dcdc(struct regulator_dev *dev,
+                                       unsigned selector)
 {
        struct tps65912_reg *pmic = rdev_get_drvdata(dev);
-       struct tps65912 *mfd = pmic->mfd;
-       int id = rdev_get_id(dev), voltage = 0, range;
-       int opvsel = 0, avsel = 0, sr, vsel;
+       int range, voltage = 0, id = rdev_get_id(dev);
 
-       switch (id) {
-       case TPS65912_REG_DCDC1:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC1_OP);
-               avsel = tps65912_reg_read(mfd, TPS65912_DCDC1_AVS);
-               range = pmic->dcdc1_range;
-               break;
-       case TPS65912_REG_DCDC2:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC2_OP);
-               avsel = tps65912_reg_read(mfd, TPS65912_DCDC2_AVS);
-               range = pmic->dcdc2_range;
-               break;
-       case TPS65912_REG_DCDC3:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC3_OP);
-               avsel = tps65912_reg_read(mfd, TPS65912_DCDC3_AVS);
-               range = pmic->dcdc3_range;
-               break;
-       case TPS65912_REG_DCDC4:
-               opvsel = tps65912_reg_read(mfd, TPS65912_DCDC4_OP);
-               avsel = tps65912_reg_read(mfd, TPS65912_DCDC4_AVS);
-               range = pmic->dcdc4_range;
-               break;
-       default:
+       if (id > TPS65912_REG_DCDC4)
                return -EINVAL;
-       }
 
-       sr = (opvsel & OP_SELREG_MASK) >> OP_SELREG_SHIFT;
-       if (sr)
-               vsel = avsel;
-       else
-               vsel = opvsel;
-       vsel &= 0x3F;
+       range = pmic->dcdc_range[id];
 
        switch (range) {
        case 0:
                /* 0.5 - 1.2875V in 12.5mV steps */
-               voltage = tps65912_vsel_to_uv_range0(vsel);
+               voltage = tps65912_vsel_to_uv_range0(selector);
                break;
        case 1:
                /* 0.7 - 1.4875V in 12.5mV steps */
-               voltage = tps65912_vsel_to_uv_range1(vsel);
+               voltage = tps65912_vsel_to_uv_range1(selector);
                break;
        case 2:
                /* 0.5 - 2.075V in 25mV steps */
-               voltage = tps65912_vsel_to_uv_range2(vsel);
+               voltage = tps65912_vsel_to_uv_range2(selector);
                break;
        case 3:
                /* 0.5 - 3.8V in 50mV steps */
-               voltage = tps65912_vsel_to_uv_range3(vsel);
+               voltage = tps65912_vsel_to_uv_range3(selector);
                break;
        }
        return voltage;
 }
 
-static int tps65912_set_voltage_dcdc(struct regulator_dev *dev,
-                                               unsigned selector)
+static int tps65912_get_voltage_dcdc(struct regulator_dev *dev)
 {
        struct tps65912_reg *pmic = rdev_get_drvdata(dev);
        struct tps65912 *mfd = pmic->mfd;
        int id = rdev_get_id(dev);
-       int value;
-       u8 reg;
-
-       reg = tps65912_get_dcdc_sel_register(pmic, id);
-       value = tps65912_reg_read(mfd, reg);
-       value &= 0xC0;
-       return tps65912_reg_write(mfd, reg, selector | value);
-}
+       int reg, vsel;
 
-static int tps65912_get_voltage_ldo(struct regulator_dev *dev)
-{
-       struct tps65912_reg *pmic = rdev_get_drvdata(dev);
-       struct tps65912 *mfd = pmic->mfd;
-       int id = rdev_get_id(dev);
-       int vsel = 0;
-       u8 reg;
+       reg = tps65912_get_sel_register(pmic, id);
+       if (reg < 0)
+               return reg;
 
-       reg = tps65912_get_ldo_sel_register(pmic, id);
        vsel = tps65912_reg_read(mfd, reg);
        vsel &= 0x3F;
 
-       return tps65912_vsel_to_uv_ldo(vsel);
+       return tps65912_list_voltage_dcdc(dev, vsel);
 }
 
-static int tps65912_set_voltage_ldo(struct regulator_dev *dev,
-                                               unsigned selector)
+static int tps65912_set_voltage_sel(struct regulator_dev *dev,
+                                        unsigned selector)
 {
        struct tps65912_reg *pmic = rdev_get_drvdata(dev);
        struct tps65912 *mfd = pmic->mfd;
-       int id = rdev_get_id(dev), reg, value;
+       int id = rdev_get_id(dev);
+       int value;
+       u8 reg;
 
-       reg = tps65912_get_ldo_sel_register(pmic, id);
+       reg = tps65912_get_sel_register(pmic, id);
        value = tps65912_reg_read(mfd, reg);
        value &= 0xC0;
        return tps65912_reg_write(mfd, reg, selector | value);
 }
 
-static int tps65912_list_voltage_dcdc(struct regulator_dev *dev,
-                                       unsigned selector)
+static int tps65912_get_voltage_ldo(struct regulator_dev *dev)
 {
        struct tps65912_reg *pmic = rdev_get_drvdata(dev);
-       int range, voltage = 0, id = rdev_get_id(dev);
+       struct tps65912 *mfd = pmic->mfd;
+       int id = rdev_get_id(dev);
+       int vsel = 0;
+       u8 reg;
 
-       switch (id) {
-       case TPS65912_REG_DCDC1:
-               range = pmic->dcdc1_range;
-               break;
-       case TPS65912_REG_DCDC2:
-               range = pmic->dcdc2_range;
-               break;
-       case TPS65912_REG_DCDC3:
-               range = pmic->dcdc3_range;
-               break;
-       case TPS65912_REG_DCDC4:
-               range = pmic->dcdc4_range;
-               break;
-       default:
-               return -EINVAL;
-       }
+       reg = tps65912_get_sel_register(pmic, id);
+       vsel = tps65912_reg_read(mfd, reg);
+       vsel &= 0x3F;
 
-       switch (range) {
-       case 0:
-               /* 0.5 - 1.2875V in 12.5mV steps */
-               voltage = tps65912_vsel_to_uv_range0(selector);
-               break;
-       case 1:
-               /* 0.7 - 1.4875V in 12.5mV steps */
-               voltage = tps65912_vsel_to_uv_range1(selector);
-               break;
-       case 2:
-               /* 0.5 - 2.075V in 25mV steps */
-               voltage = tps65912_vsel_to_uv_range2(selector);
-               break;
-       case 3:
-               /* 0.5 - 3.8V in 50mV steps */
-               voltage = tps65912_vsel_to_uv_range3(selector);
-               break;
-       }
-       return voltage;
+       return tps65912_vsel_to_uv_ldo(vsel);
 }
 
 static int tps65912_list_voltage_ldo(struct regulator_dev *dev,
@@ -672,7 +470,7 @@ static struct regulator_ops tps65912_ops_dcdc = {
        .set_mode = tps65912_set_mode,
        .get_mode = tps65912_get_mode,
        .get_voltage = tps65912_get_voltage_dcdc,
-       .set_voltage_sel = tps65912_set_voltage_dcdc,
+       .set_voltage_sel = tps65912_set_voltage_sel,
        .list_voltage = tps65912_list_voltage_dcdc,
 };
 
@@ -682,7 +480,7 @@ static struct regulator_ops tps65912_ops_ldo = {
        .enable = tps65912_reg_enable,
        .disable = tps65912_reg_disable,
        .get_voltage = tps65912_get_voltage_ldo,
-       .set_voltage_sel = tps65912_set_voltage_ldo,
+       .set_voltage_sel = tps65912_set_voltage_sel,
        .list_voltage = tps65912_list_voltage_ldo,
 };
 
@@ -770,22 +568,12 @@ static struct platform_driver tps65912_driver = {
        .remove = __devexit_p(tps65912_remove),
 };
 
-/**
- * tps65912_init
- *
- * Module init function
- */
 static int __init tps65912_init(void)
 {
        return platform_driver_register(&tps65912_driver);
 }
 subsys_initcall(tps65912_init);
 
-/**
- * tps65912_cleanup
- *
- * Module exit function
- */
 static void __exit tps65912_cleanup(void)
 {
        platform_driver_unregister(&tps65912_driver);