diff options
author | Axel Lin <axel.lin@gmail.com> | 2012-04-10 14:05:44 +0800 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2012-04-10 09:53:48 +0100 |
commit | 321d2abaca231dc3ce5d8f71c7f9d0e6ee5c0c24 (patch) | |
tree | a6d104291e8cf3a8eed8d262bf4145e23f5c3526 /drivers/regulator/s5m8767.c | |
parent | b920eb41a8241c54efbbd4f2ed6d074f497b0d9e (diff) | |
download | blackbird-op-linux-321d2abaca231dc3ce5d8f71c7f9d0e6ee5c0c24.tar.gz blackbird-op-linux-321d2abaca231dc3ce5d8f71c7f9d0e6ee5c0c24.zip |
regulator: Rework s5m8767_set_voltage to support both LDOs and BUCKs
s5m8767_set_voltage not only implement set_voltage callbacks for LDOs,
but also for BUCKs when s5m8767->buck_gpioindex is not set.
s5m8767_set_voltage_buck actually only for buck[2|3|4] when
s5m8767->buck_gpioindex is set.
Conditionally calling s5m8767_set_voltage in s5m8767_set_voltage_buck makes
the code hard to read.
I think merging s5m8767_set_voltage_buck and s5m8767_set_voltage actually
simplifies things. It's easy to use buck234_vol pointer to differentiate if
we need to control voltage for buck[2|3|4] by DVS GPIOs.
This patch reworks s5m8767_set_voltage to support both LDOx and BUCKx in all
cases.
Signed-off-by: Axel Lin <axel.lin@gmail.com>
Acked-by: Sangbeom Kim <sbkim73@samsung.com>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'drivers/regulator/s5m8767.c')
-rw-r--r-- | drivers/regulator/s5m8767.c | 143 |
1 files changed, 49 insertions, 94 deletions
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c index c4a584c268ce..245cc2da4fd4 100644 --- a/drivers/regulator/s5m8767.c +++ b/drivers/regulator/s5m8767.c @@ -355,14 +355,33 @@ static int s5m8767_convert_voltage_to_sel( return selector; } +static inline void s5m8767_set_high(struct s5m8767_info *s5m8767) +{ + int temp_index = s5m8767->buck_gpioindex; + + gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); + gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); + gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); +} + +static inline void s5m8767_set_low(struct s5m8767_info *s5m8767) +{ + int temp_index = s5m8767->buck_gpioindex; + + gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); + gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); + gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); +} + static int s5m8767_set_voltage(struct regulator_dev *rdev, int min_uV, int max_uV, unsigned *selector) { struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); const struct s5m_voltage_desc *desc; int reg_id = rdev_get_id(rdev); - int sel, reg, mask, ret; + int sel, reg, mask, ret = 0, old_index, index = 0; u8 val; + u8 *buck234_vol = NULL; switch (reg_id) { case S5M8767_LDO1 ... S5M8767_LDO28: @@ -370,6 +389,12 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, break; case S5M8767_BUCK1 ... S5M8767_BUCK6: mask = 0xff; + if (reg_id == S5M8767_BUCK2 && s5m8767->buck2_gpiodvs) + buck234_vol = &s5m8767->buck2_vol[0]; + else if (reg_id == S5M8767_BUCK3 && s5m8767->buck3_gpiodvs) + buck234_vol = &s5m8767->buck3_vol[0]; + else if (reg_id == S5M8767_BUCK4 && s5m8767->buck4_gpiodvs) + buck234_vol = &s5m8767->buck4_vol[0]; break; case S5M8767_BUCK7 ... S5M8767_BUCK8: return -EINVAL; @@ -386,102 +411,32 @@ static int s5m8767_set_voltage(struct regulator_dev *rdev, if (sel < 0) return sel; - ret = s5m8767_get_voltage_register(rdev, ®); - if (ret) - return ret; - - s5m_reg_read(s5m8767->iodev, reg, &val); - val &= ~mask; - val |= sel; - - ret = s5m_reg_write(s5m8767->iodev, reg, val); - *selector = sel; - - return ret; -} - -static inline void s5m8767_set_high(struct s5m8767_info *s5m8767) -{ - int temp_index = s5m8767->buck_gpioindex; - - gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); - gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); - gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); -} - -static inline void s5m8767_set_low(struct s5m8767_info *s5m8767) -{ - int temp_index = s5m8767->buck_gpioindex; - - gpio_set_value(s5m8767->buck_gpios[2], temp_index & 0x1); - gpio_set_value(s5m8767->buck_gpios[1], (temp_index >> 1) & 0x1); - gpio_set_value(s5m8767->buck_gpios[0], (temp_index >> 2) & 0x1); -} - -static int s5m8767_set_voltage_buck(struct regulator_dev *rdev, - int min_uV, int max_uV, unsigned *selector) -{ - struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev); - int reg_id = rdev_get_id(rdev); - const struct s5m_voltage_desc *desc; - int new_val, old_val, i = 0; - - if (reg_id < S5M8767_BUCK1 || reg_id > S5M8767_BUCK6) - return -EINVAL; - - switch (reg_id) { - case S5M8767_BUCK1: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); - case S5M8767_BUCK2 ... S5M8767_BUCK4: - break; - case S5M8767_BUCK5 ... S5M8767_BUCK6: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); - case S5M8767_BUCK9: - return s5m8767_set_voltage(rdev, min_uV, max_uV, selector); - } + /* buck234_vol != NULL means to control buck234 voltage via DVS GPIO */ + if (buck234_vol) { + while (*buck234_vol != sel) { + buck234_vol++; + index++; + } + old_index = s5m8767->buck_gpioindex; + s5m8767->buck_gpioindex = index; + + if (index > old_index) + s5m8767_set_high(s5m8767); + else + s5m8767_set_low(s5m8767); + } else { + ret = s5m8767_get_voltage_register(rdev, ®); + if (ret) + return ret; - desc = reg_voltage_map[reg_id]; - new_val = s5m8767_convert_voltage_to_sel(desc, min_uV, max_uV); - if (new_val < 0) - return new_val; + s5m_reg_read(s5m8767->iodev, reg, &val); + val = (val & ~mask) | sel; - switch (reg_id) { - case S5M8767_BUCK2: - if (s5m8767->buck2_gpiodvs) { - while (s5m8767->buck2_vol[i] != new_val) - i++; - } else - return s5m8767_set_voltage(rdev, min_uV, - max_uV, selector); - break; - case S5M8767_BUCK3: - if (s5m8767->buck3_gpiodvs) { - while (s5m8767->buck3_vol[i] != new_val) - i++; - } else - return s5m8767_set_voltage(rdev, min_uV, - max_uV, selector); - break; - case S5M8767_BUCK4: - if (s5m8767->buck3_gpiodvs) { - while (s5m8767->buck4_vol[i] != new_val) - i++; - } else - return s5m8767_set_voltage(rdev, min_uV, - max_uV, selector); - break; + ret = s5m_reg_write(s5m8767->iodev, reg, val); } - old_val = s5m8767->buck_gpioindex; - s5m8767->buck_gpioindex = i; - - if (i > old_val) - s5m8767_set_high(s5m8767); - else - s5m8767_set_low(s5m8767); - - *selector = new_val; - return 0; + *selector = sel; + return ret; } static int s5m8767_set_voltage_time_sel(struct regulator_dev *rdev, @@ -516,7 +471,7 @@ static struct regulator_ops s5m8767_buck_ops = { .enable = s5m8767_reg_enable, .disable = s5m8767_reg_disable, .get_voltage_sel = s5m8767_get_voltage_sel, - .set_voltage = s5m8767_set_voltage_buck, + .set_voltage = s5m8767_set_voltage, .set_voltage_time_sel = s5m8767_set_voltage_time_sel, }; |