diff options
author | Laxman Dewangan <ldewangan@nvidia.com> | 2012-12-14 12:00:27 +0530 |
---|---|---|
committer | Simone Willett <swillett@nvidia.com> | 2012-12-20 15:03:55 -0800 |
commit | 4274f7b8af6a97fbda84ec4ffc6a779b1e4a0ff1 (patch) | |
tree | c07e5847f572b0bcf39bb47c41b34a678c75e3c7 /drivers/regulator | |
parent | d9bdf71b4a13858efaf9668dadc7bb63fb2fb031 (diff) |
regulator: tps51632: add support for change control mode
TPS51632 output can be control through register write via i2c or
through input pwm signal.
Adding support for switching the control mode to I2C or PWM
dynamically.
Change-Id: I57d72eff5c819a2b84f25ba82482bb9723c2c452
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: http://git-master/r/171310
Reviewed-on: http://git-master/r/172701
Diffstat (limited to 'drivers/regulator')
-rw-r--r-- | drivers/regulator/tps51632-regulator.c | 58 |
1 files changed, 48 insertions, 10 deletions
diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index 0ab48eb1dea0..af6188f69457 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -104,6 +104,7 @@ static int tps51632_dcdc_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct tps51632_chip *tps = rdev_get_drvdata(rdev); + unsigned int reg = TPS51632_VOLTAGE_SELECT_REG; int vsel; int ret; @@ -116,7 +117,10 @@ static int tps51632_dcdc_set_voltage(struct regulator_dev *rdev, if (selector) *selector = (vsel & TPS51632_VOUT_MASK); - ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel); + if (tps->pwm_enabled) + reg = TPS51632_VOLTAGE_BASE_REG; + + ret = regmap_write(tps->regmap, reg, vsel); if (ret < 0) dev_err(tps->dev, "reg write failed, err %d\n", ret); return ret; @@ -148,11 +152,47 @@ static int tps51632_dcdc_set_voltage_time_sel(struct regulator_dev *rdev, return DIV_ROUND_UP(abs(old_uV - new_uV), tps->change_uv_per_us); } +static int tps51632_dcdc_set_control_mode(struct regulator_dev *rdev, + unsigned int mode) +{ + struct tps51632_chip *tps = rdev_get_drvdata(rdev); + int ret; + + if (mode == REGULATOR_CONTROL_MODE_I2C) + ret = regmap_update_bits(tps->regmap, + TPS51632_DVFS_CONTROL_REG, TPS51632_DVFS_PWMEN, 0); + else if (mode == REGULATOR_CONTROL_MODE_PWM) + ret = regmap_update_bits(tps->regmap, + TPS51632_DVFS_CONTROL_REG, TPS51632_DVFS_PWMEN, + TPS51632_DVFS_PWMEN); + else + return -EINVAL; + + if (ret < 0) { + dev_err(tps->dev, "DVFS reg write failed, err %d\n", ret); + return ret; + } + tps->pwm_enabled = (mode == REGULATOR_CONTROL_MODE_PWM); + return ret; +} + +static unsigned int tps51632_dcdc_get_control_mode(struct regulator_dev *rdev) +{ + struct tps51632_chip *tps = rdev_get_drvdata(rdev); + + if (tps->pwm_enabled) + return REGULATOR_CONTROL_MODE_PWM; + return REGULATOR_CONTROL_MODE_I2C; +} + + static struct regulator_ops tps51632_dcdc_ops = { .get_voltage_sel = tps51632_dcdc_get_voltage_sel, .set_voltage = tps51632_dcdc_set_voltage, .list_voltage = tps51632_dcdc_list_voltage, .set_voltage_time_sel = tps51632_dcdc_set_voltage_time_sel, + .set_control_mode = tps51632_dcdc_set_control_mode, + .get_control_mode = tps51632_dcdc_get_control_mode, }; static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps, @@ -166,15 +206,13 @@ static int __devinit tps51632_init_dcdc(struct tps51632_chip *tps, if (pdata->enable_pwm) { control |= TPS51632_DVFS_PWMEN; tps->pwm_enabled = pdata->enable_pwm; - vsel = DIV_ROUND_UP(pdata->base_voltage_uV - - TPS51632_MIN_VOLATGE, TPS51632_VOLATGE_STEP) + 0x19; - 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; - } + } + vsel = DIV_ROUND_UP(pdata->base_voltage_uV - + TPS51632_MIN_VOLATGE, TPS51632_VOLATGE_STEP) + 0x19; + 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; |