regulator: regulator driver for Palmas series chips
[linux-2.6.git] / drivers / regulator / tps62360-regulator.c
index bc58365..dca2c88 100644 (file)
@@ -46,6 +46,8 @@
 #define REG_RAMPCTRL           6
 #define REG_CHIPID             8
 
+#define FORCE_PWM_ENABLE       BIT(7)
+
 enum chips {TPS62360, TPS62361, TPS62362, TPS62363};
 
 #define TPS62360_BASE_VOLTAGE  770000
@@ -66,7 +68,6 @@ struct tps62360_chip {
        int voltage_base;
        u8 voltage_reg_mask;
        bool en_internal_pulldn;
-       bool en_force_pwm;
        bool en_discharge;
        bool valid_gpios;
        int lru_index[4];
@@ -210,36 +211,80 @@ static int tps62360_set_voltage_time_sel(struct regulator_dev *rdev,
        return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us);
 }
 
-static struct regulator_ops tps62360_dcdc_ops = {
-       .get_voltage_sel        = tps62360_dcdc_get_voltage_sel,
-       .set_voltage            = tps62360_dcdc_set_voltage,
-       .list_voltage           = tps62360_dcdc_list_voltage,
-       .set_voltage_time_sel   = tps62360_set_voltage_time_sel,
-};
-
-static int __devinit tps62360_init_force_pwm(struct tps62360_chip *tps,
-       struct tps62360_regulator_platform_data *pdata,
-       int vset_id)
+static int tps62360_set_mode(struct regulator_dev *rdev, unsigned int mode)
 {
+       struct tps62360_chip *tps = rdev_get_drvdata(rdev);
+       int i;
+       int val;
        int ret;
-       int bit = 0;
 
-       if (pdata->en_force_pwm)
-               bit = BIT(7);
+       /* Enable force PWM mode in FAST mode only. */
+       switch (mode) {
+       case REGULATOR_MODE_FAST:
+               val = FORCE_PWM_ENABLE;
+               break;
 
-       ret = regmap_update_bits(tps->regmap, REG_VSET0 + vset_id, BIT(7), bit);
-       if (ret < 0)
-               dev_err(tps->dev,
-                       "%s(): register %d update failed with err %d\n",
-                       __func__, REG_VSET0 + vset_id, ret);
+       case REGULATOR_MODE_NORMAL:
+               val = 0;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       if (!tps->valid_gpios) {
+               ret = regmap_update_bits(tps->regmap,
+                       REG_VSET0 + tps->curr_vset_id, FORCE_PWM_ENABLE, val);
+               if (ret < 0)
+                       dev_err(tps->dev,
+                               "%s(): register %d update failed with err %d\n",
+                               __func__, REG_VSET0 + tps->curr_vset_id, ret);
+               return ret;
+       }
+
+       /* If gpios are valid then all register set need to be control */
+       for (i = 0; i < 4; ++i) {
+               ret = regmap_update_bits(tps->regmap,
+                                       REG_VSET0 + i, FORCE_PWM_ENABLE, val);
+               if (ret < 0) {
+                       dev_err(tps->dev,
+                               "%s(): register %d update failed with err %d\n",
+                               __func__, REG_VSET0 + i, ret);
+                       return ret;
+               }
+       }
        return ret;
 }
 
+static unsigned int tps62360_get_mode(struct regulator_dev *rdev)
+{
+       struct tps62360_chip *tps = rdev_get_drvdata(rdev);
+       unsigned int data;
+       int ret;
+
+       ret = regmap_read(tps->regmap, REG_VSET0 + tps->curr_vset_id, &data);
+       if (ret < 0) {
+               dev_err(tps->dev, "%s(): register %d read failed with err %d\n",
+                       __func__, REG_VSET0 + tps->curr_vset_id, ret);
+               return ret;
+       }
+       return (data & FORCE_PWM_ENABLE) ?
+                               REGULATOR_MODE_FAST : REGULATOR_MODE_NORMAL;
+}
+
+static struct regulator_ops tps62360_dcdc_ops = {
+       .get_voltage_sel        = tps62360_dcdc_get_voltage_sel,
+       .set_voltage            = tps62360_dcdc_set_voltage,
+       .list_voltage           = tps62360_dcdc_list_voltage,
+       .set_voltage_time_sel   = tps62360_set_voltage_time_sel,
+       .set_mode               = tps62360_set_mode,
+       .get_mode               = tps62360_get_mode,
+};
+
 static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
                struct tps62360_regulator_platform_data *pdata)
 {
        int ret;
-       int i;
        unsigned int ramp_ctrl;
 
        /* Initialize internal pull up/down control */
@@ -254,19 +299,6 @@ static int __devinit tps62360_init_dcdc(struct tps62360_chip *tps,
                return ret;
        }
 
-       /* Initialize force PWM mode */
-       if (tps->valid_gpios) {
-               for (i = 0; i < 4; ++i) {
-                       ret = tps62360_init_force_pwm(tps, pdata, i);
-                       if (ret < 0)
-                               return ret;
-               }
-       } else {
-               ret = tps62360_init_force_pwm(tps, pdata, tps->curr_vset_id);
-               if (ret < 0)
-                       return ret;
-       }
-
        /* Reset output discharge path to reduce power consumption */
        ret = regmap_update_bits(tps->regmap, REG_RAMPCTRL, BIT(2), 0);
        if (ret < 0) {
@@ -321,7 +353,6 @@ static int __devinit tps62360_probe(struct i2c_client *client,
                return -ENOMEM;
        }
 
-       tps->en_force_pwm = pdata->en_force_pwm;
        tps->en_discharge = pdata->en_discharge;
        tps->en_internal_pulldn = pdata->en_internal_pulldn;
        tps->vsel0_gpio = pdata->vsel0_gpio;
@@ -409,7 +440,7 @@ static int __devinit tps62360_probe(struct i2c_client *client,
 
        /* Register the regulators */
        rdev = regulator_register(&tps->desc, &client->dev,
-                               &pdata->reg_init_data, tps);
+                               &pdata->reg_init_data, tps, NULL);
        if (IS_ERR(rdev)) {
                dev_err(tps->dev,
                        "%s(): regulator register failed with err %s\n",