diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 10:34:56 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-03-21 10:34:56 -0700 |
| commit | d15d76448bb58c7832e954b6a8f1e301720b7866 (patch) | |
| tree | 7891c9e0779f5df33840be9cdba1f0331459e97c /drivers/regulator/tps65912-regulator.c | |
| parent | 0c2fe82a9b106f1c03719783134360586d718a69 (diff) | |
| parent | 4992fa1fd425f1934f503ffa96b68e235b89db9a (diff) | |
Merge tag 'regulator-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator
Pull regulator updates for 3.4 from Mark Brown:
"This has been a fairly quiet release from a regulator point of view,
the only real framework features added were devm support and a
convenience helper for setting up fixed voltage regulators.
We also added a couple of drivers (but will drop the BQ240022 driver
via the arm-soc tree as it's been replaced by the more generic
gpio-regulator driver) and Axel Lin continued his relentless and
generally awesome stream of fixes and cleanups."
* tag 'regulator-3.4' of git://git.kernel.org/pub/scm/linux/kernel/git/broonie/regulator: (93 commits)
regulator: Fix up a confusing dev_warn when DT lookup fails
regulator: Convert tps6507x to set_voltage_sel
regulator: Refactor tps6507x to use one tps6507x_pmic_ops for all LDOs and DCDCs
regulator: Make s5m8767_get_voltage_register always return correct register
regulator: s5m8767: Check pdata->buck[2|3|4]_gpiodvs earlier
regulator: tps65910: Provide settling time for DCDC voltage change
regulator: Add Anatop regulator driver
regulator: Simplify implementation of tps65912_get_voltage_dcdc
regulator: Use tps65912_set_voltage_sel for both DCDCx and LDOx
regulator: tps65910: Provide settling time for enabling rails
regulator: max8925: Use DIV_ROUND_UP macro
regulator: tps65912: Use simple equations to get register address
regulator: Fix the logic of tps65910_get_mode
regulator: Merge tps65217_pmic_ldo234_ops and tps65217_pmic_dcdc_ops to tps65217_pmic_ops
regulator: Use DIV_ROUND_CLOSEST in wm8350_isink_get_current
regulator: Use array to store dcdc_range settings for tps65912
regulator: Rename s5m8767_convert_voltage to s5m8767_convert_voltage_to_sel
regulator: tps6524x: Remove unneeded comment for N_REGULATORS
regulator: Rename set_voltage_sel callback function name to *_sel
regulator: Fix s5m8767_set_voltage_time_sel calculation value
...
Diffstat (limited to 'drivers/regulator/tps65912-regulator.c')
| -rw-r--r-- | drivers/regulator/tps65912-regulator.c | 340 |
1 files changed, 64 insertions, 276 deletions
diff --git a/drivers/regulator/tps65912-regulator.c b/drivers/regulator/tps65912-regulator.c index da00d88f94b7..b36799b1f530 100644 --- a/drivers/regulator/tps65912-regulator.c +++ b/drivers/regulator/tps65912-regulator.c @@ -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); |
