diff options
-rw-r--r-- | drivers/regulator/anatop-regulator.c | 28 | ||||
-rw-r--r-- | drivers/regulator/core.c | 6 | ||||
-rw-r--r-- | drivers/regulator/da9055-regulator.c | 55 | ||||
-rw-r--r-- | drivers/regulator/palmas-regulator.c | 37 | ||||
-rw-r--r-- | drivers/regulator/pcf50633-regulator.c | 176 | ||||
-rw-r--r-- | drivers/regulator/tps51632-regulator.c | 15 | ||||
-rw-r--r-- | include/linux/regulator/driver.h | 2 |
7 files changed, 63 insertions, 256 deletions
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c index 1aa5246c79d9..0199eeea63b1 100644 --- a/drivers/regulator/anatop-regulator.c +++ b/drivers/regulator/anatop-regulator.c @@ -48,36 +48,21 @@ static int anatop_regmap_set_voltage_sel(struct regulator_dev *reg, unsigned selector) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - u32 val, mask; if (!anatop_reg->control_reg) return -ENOTSUPP; - val = anatop_reg->min_bit_val + selector; - dev_dbg(®->dev, "%s: calculated val %d\n", __func__, val); - mask = ((1 << anatop_reg->vol_bit_width) - 1) << - anatop_reg->vol_bit_shift; - val <<= anatop_reg->vol_bit_shift; - regmap_update_bits(anatop_reg->anatop, anatop_reg->control_reg, - mask, val); - - return 0; + return regulator_set_voltage_sel_regmap(reg, selector); } static int anatop_regmap_get_voltage_sel(struct regulator_dev *reg) { struct anatop_regulator *anatop_reg = rdev_get_drvdata(reg); - u32 val, mask; if (!anatop_reg->control_reg) return -ENOTSUPP; - regmap_read(anatop_reg->anatop, anatop_reg->control_reg, &val); - mask = ((1 << anatop_reg->vol_bit_width) - 1) << - anatop_reg->vol_bit_shift; - val = (val & mask) >> anatop_reg->vol_bit_shift; - - return val - anatop_reg->min_bit_val; + return regulator_get_voltage_sel_regmap(reg); } static struct regulator_ops anatop_rops = { @@ -158,15 +143,20 @@ static int anatop_regulator_probe(struct platform_device *pdev) goto anatop_probe_end; } - rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) - / 25000 + 1; + rdesc->n_voltages = (sreg->max_voltage - sreg->min_voltage) / 25000 + 1 + + sreg->min_bit_val; rdesc->min_uV = sreg->min_voltage; rdesc->uV_step = 25000; + rdesc->linear_min_sel = sreg->min_bit_val; + rdesc->vsel_reg = sreg->control_reg; + rdesc->vsel_mask = ((1 << sreg->vol_bit_width) - 1) << + sreg->vol_bit_shift; config.dev = &pdev->dev; config.init_data = initdata; config.driver_data = sreg; config.of_node = pdev->dev.of_node; + config.regmap = sreg->anatop; /* register regulator */ rdev = regulator_register(rdesc, &config); diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c index 35c149bb2ad3..cd1b201c91e2 100644 --- a/drivers/regulator/core.c +++ b/drivers/regulator/core.c @@ -1924,6 +1924,10 @@ int regulator_list_voltage_linear(struct regulator_dev *rdev, { if (selector >= rdev->desc->n_voltages) return -EINVAL; + if (selector < rdev->desc->linear_min_sel) + return 0; + + selector -= rdev->desc->linear_min_sel; return rdev->desc->min_uV + (rdev->desc->uV_step * selector); } @@ -2152,6 +2156,8 @@ int regulator_map_voltage_linear(struct regulator_dev *rdev, if (ret < 0) return ret; + ret += rdev->desc->linear_min_sel; + /* Map back into a voltage to verify we're still in bounds */ voltage = rdev->desc->ops->list_voltage(rdev, ret); if (voltage < min_uV || voltage > max_uV) diff --git a/drivers/regulator/da9055-regulator.c b/drivers/regulator/da9055-regulator.c index db59ce7534cd..a4b9cb8c4317 100644 --- a/drivers/regulator/da9055-regulator.c +++ b/drivers/regulator/da9055-regulator.c @@ -57,7 +57,6 @@ struct da9055_volt_reg { int reg_a; int reg_b; int sl_shift; - int v_offset; int v_mask; int v_shift; }; @@ -201,41 +200,6 @@ static int da9055_buck_set_current_limit(struct regulator_dev *rdev, int min_uA, return -EINVAL; } -static int da9055_list_voltage(struct regulator_dev *rdev, unsigned selector) -{ - struct da9055_regulator *regulator = rdev_get_drvdata(rdev); - struct da9055_regulator_info *info = regulator->info; - - if (selector >= rdev->desc->n_voltages) - return -EINVAL; - - if (selector < info->volt.v_offset) - return 0; - - selector -= info->volt.v_offset; - return rdev->desc->min_uV + (rdev->desc->uV_step * selector); -} - -static int da9055_map_voltage(struct regulator_dev *rdev, int min_uV, - int max_uV) -{ - struct da9055_regulator *regulator = rdev_get_drvdata(rdev); - struct da9055_regulator_info *info = regulator->info; - int sel, voltage; - - if (min_uV < rdev->desc->min_uV) - min_uV = rdev->desc->min_uV; - - sel = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); - sel += info->volt.v_offset; - - voltage = da9055_list_voltage(rdev, sel); - if (voltage < min_uV || voltage > max_uV) - return -EINVAL; - - return sel; -} - static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev) { struct da9055_regulator *regulator = rdev_get_drvdata(rdev); @@ -264,10 +228,7 @@ static int da9055_regulator_get_voltage_sel(struct regulator_dev *rdev) return ret; sel = (ret & volt.v_mask); - if (sel <= volt.v_offset) - return 0; - else - return sel; + return sel; } static int da9055_regulator_set_voltage_sel(struct regulator_dev *rdev, @@ -328,7 +289,7 @@ static int da9055_regulator_set_suspend_voltage(struct regulator_dev *rdev, return ret; } - ret = da9055_map_voltage(rdev, uV, uV); + ret = regulator_map_voltage_linear(rdev, uV, uV); if (ret < 0) return ret; @@ -371,8 +332,8 @@ static struct regulator_ops da9055_buck_ops = { .get_voltage_sel = da9055_regulator_get_voltage_sel, .set_voltage_sel = da9055_regulator_set_voltage_sel, - .list_voltage = da9055_list_voltage, - .map_voltage = da9055_map_voltage, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -389,8 +350,8 @@ static struct regulator_ops da9055_ldo_ops = { .get_voltage_sel = da9055_regulator_get_voltage_sel, .set_voltage_sel = da9055_regulator_set_voltage_sel, - .list_voltage = da9055_list_voltage, - .map_voltage = da9055_map_voltage, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .is_enabled = regulator_is_enabled_regmap, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, @@ -414,6 +375,7 @@ static struct regulator_ops da9055_ldo_ops = { .enable_mask = 1, \ .min_uV = (min) * 1000,\ .uV_step = (step) * 1000,\ + .linear_min_sel = (voffset),\ .owner = THIS_MODULE,\ },\ .conf = {\ @@ -425,7 +387,6 @@ static struct regulator_ops da9055_ldo_ops = { .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \ .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ .sl_shift = 7,\ - .v_offset = (voffset),\ .v_mask = (1 << (vbits)) - 1,\ .v_shift = (vbits),\ },\ @@ -443,6 +404,7 @@ static struct regulator_ops da9055_ldo_ops = { .enable_mask = 1,\ .min_uV = (min) * 1000,\ .uV_step = (step) * 1000,\ + .linear_min_sel = (voffset),\ .owner = THIS_MODULE,\ },\ .conf = {\ @@ -454,7 +416,6 @@ static struct regulator_ops da9055_ldo_ops = { .reg_a = DA9055_REG_VBCORE_A + DA9055_ID_##_id, \ .reg_b = DA9055_REG_VBCORE_B + DA9055_ID_##_id, \ .sl_shift = 7,\ - .v_offset = (voffset),\ .v_mask = (1 << (vbits)) - 1,\ .v_shift = (vbits),\ },\ diff --git a/drivers/regulator/palmas-regulator.c b/drivers/regulator/palmas-regulator.c index 3d445929cc80..fd27a43a9fbc 100644 --- a/drivers/regulator/palmas-regulator.c +++ b/drivers/regulator/palmas-regulator.c @@ -436,44 +436,14 @@ static int palmas_is_enabled_ldo(struct regulator_dev *dev) return !!(reg); } -static int palmas_list_voltage_ldo(struct regulator_dev *dev, - unsigned selector) -{ - if (!selector) - return 0; - - /* voltage is 0.85V + (selector * 0.05v) */ - return 850000 + (selector * 50000); -} - -static int palmas_map_voltage_ldo(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - int ret, voltage; - - if (min_uV == 0) - return 0; - - if (min_uV < 900000) - min_uV = 900000; - ret = DIV_ROUND_UP(min_uV - 900000, 50000) + 1; - - /* Map back into a voltage to verify we're still in bounds */ - voltage = palmas_list_voltage_ldo(rdev, ret); - if (voltage < min_uV || voltage > max_uV) - return -EINVAL; - - return ret; -} - static struct regulator_ops palmas_ops_ldo = { .is_enabled = palmas_is_enabled_ldo, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, .set_voltage_sel = regulator_set_voltage_sel_regmap, - .list_voltage = palmas_list_voltage_ldo, - .map_voltage = palmas_map_voltage_ldo, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, }; /* @@ -821,6 +791,9 @@ static int palmas_probe(struct platform_device *pdev) pmic->desc[id].type = REGULATOR_VOLTAGE; pmic->desc[id].owner = THIS_MODULE; + pmic->desc[id].min_uV = 900000; + pmic->desc[id].uV_step = 50000; + pmic->desc[id].linear_min_sel = 1; pmic->desc[id].vsel_reg = PALMAS_BASE_TO_REG(PALMAS_LDO_BASE, palmas_regs_info[id].vsel_addr); pmic->desc[id].vsel_mask = PALMAS_LDO1_VOLTAGE_VSEL_MASK; diff --git a/drivers/regulator/pcf50633-regulator.c b/drivers/regulator/pcf50633-regulator.c index d776f518aa0d..534075e13d6d 100644 --- a/drivers/regulator/pcf50633-regulator.c +++ b/drivers/regulator/pcf50633-regulator.c @@ -24,12 +24,15 @@ #include <linux/mfd/pcf50633/core.h> #include <linux/mfd/pcf50633/pmic.h> -#define PCF50633_REGULATOR(_name, _id, _n) \ +#define PCF50633_REGULATOR(_name, _id, _min_uV, _uV_step, _min_sel, _n) \ { \ .name = _name, \ .id = PCF50633_REGULATOR_##_id, \ .ops = &pcf50633_regulator_ops, \ .n_voltages = _n, \ + .min_uV = _min_uV, \ + .uV_step = _uV_step, \ + .linear_min_sel = _min_sel, \ .type = REGULATOR_VOLTAGE, \ .owner = THIS_MODULE, \ .vsel_reg = PCF50633_REG_##_id##OUT, \ @@ -38,162 +41,39 @@ .enable_mask = PCF50633_REGULATOR_ON, \ } -/* Bits from voltage value */ -static u8 auto_voltage_bits(unsigned int millivolts) -{ - if (millivolts < 1800) - return 0x2f; - if (millivolts > 3800) - return 0xff; - - millivolts -= 625; - - return millivolts / 25; -} - -static u8 down_voltage_bits(unsigned int millivolts) -{ - if (millivolts < 625) - return 0; - else if (millivolts > 3000) - return 0xff; - - millivolts -= 625; - - return millivolts / 25; -} - -static u8 ldo_voltage_bits(unsigned int millivolts) -{ - if (millivolts < 900) - return 0; - else if (millivolts > 3600) - return 0x1f; - - millivolts -= 900; - return millivolts / 100; -} - -/* Obtain voltage value from bits */ -static unsigned int auto_voltage_value(u8 bits) -{ - /* AUTOOUT: 00000000 to 00101110 are reserved. - * Return 0 for bits in reserved range, which means this selector code - * can't be used on this system */ - if (bits < 0x2f) - return 0; - - return 625 + (bits * 25); -} - - -static unsigned int down_voltage_value(u8 bits) -{ - return 625 + (bits * 25); -} - - -static unsigned int ldo_voltage_value(u8 bits) -{ - bits &= 0x1f; - - return 900 + (bits * 100); -} - -static int pcf50633_regulator_map_voltage(struct regulator_dev *rdev, - int min_uV, int max_uV) -{ - struct pcf50633 *pcf; - int regulator_id, millivolts; - u8 volt_bits; - - pcf = rdev_get_drvdata(rdev); - - regulator_id = rdev_get_id(rdev); - if (regulator_id >= PCF50633_NUM_REGULATORS) - return -EINVAL; - - millivolts = min_uV / 1000; - - switch (regulator_id) { - case PCF50633_REGULATOR_AUTO: - volt_bits = auto_voltage_bits(millivolts); - break; - case PCF50633_REGULATOR_DOWN1: - case PCF50633_REGULATOR_DOWN2: - volt_bits = down_voltage_bits(millivolts); - break; - case PCF50633_REGULATOR_LDO1: - case PCF50633_REGULATOR_LDO2: - case PCF50633_REGULATOR_LDO3: - case PCF50633_REGULATOR_LDO4: - case PCF50633_REGULATOR_LDO5: - case PCF50633_REGULATOR_LDO6: - case PCF50633_REGULATOR_HCLDO: - case PCF50633_REGULATOR_MEMLDO: - volt_bits = ldo_voltage_bits(millivolts); - break; - default: - return -EINVAL; - } - - return volt_bits; -} - -static int pcf50633_regulator_list_voltage(struct regulator_dev *rdev, - unsigned int index) -{ - int regulator_id = rdev_get_id(rdev); - - int millivolts; - - switch (regulator_id) { - case PCF50633_REGULATOR_AUTO: - millivolts = auto_voltage_value(index); - break; - case PCF50633_REGULATOR_DOWN1: - case PCF50633_REGULATOR_DOWN2: - millivolts = down_voltage_value(index); - break; - case PCF50633_REGULATOR_LDO1: - case PCF50633_REGULATOR_LDO2: - case PCF50633_REGULATOR_LDO3: - case PCF50633_REGULATOR_LDO4: - case PCF50633_REGULATOR_LDO5: - case PCF50633_REGULATOR_LDO6: - case PCF50633_REGULATOR_HCLDO: - case PCF50633_REGULATOR_MEMLDO: - millivolts = ldo_voltage_value(index); - break; - default: - return -EINVAL; - } - - return millivolts * 1000; -} - static struct regulator_ops pcf50633_regulator_ops = { .set_voltage_sel = regulator_set_voltage_sel_regmap, .get_voltage_sel = regulator_get_voltage_sel_regmap, - .list_voltage = pcf50633_regulator_list_voltage, - .map_voltage = pcf50633_regulator_map_voltage, + .list_voltage = regulator_list_voltage_linear, + .map_voltage = regulator_map_voltage_linear, .enable = regulator_enable_regmap, .disable = regulator_disable_regmap, .is_enabled = regulator_is_enabled_regmap, }; static const struct regulator_desc regulators[] = { - [PCF50633_REGULATOR_AUTO] = PCF50633_REGULATOR("auto", AUTO, 128), - [PCF50633_REGULATOR_DOWN1] = PCF50633_REGULATOR("down1", DOWN1, 96), - [PCF50633_REGULATOR_DOWN2] = PCF50633_REGULATOR("down2", DOWN2, 96), - [PCF50633_REGULATOR_LDO1] = PCF50633_REGULATOR("ldo1", LDO1, 28), - [PCF50633_REGULATOR_LDO2] = PCF50633_REGULATOR("ldo2", LDO2, 28), - [PCF50633_REGULATOR_LDO3] = PCF50633_REGULATOR("ldo3", LDO3, 28), - [PCF50633_REGULATOR_LDO4] = PCF50633_REGULATOR("ldo4", LDO4, 28), - [PCF50633_REGULATOR_LDO5] = PCF50633_REGULATOR("ldo5", LDO5, 28), - [PCF50633_REGULATOR_LDO6] = PCF50633_REGULATOR("ldo6", LDO6, 28), - [PCF50633_REGULATOR_HCLDO] = PCF50633_REGULATOR("hcldo", HCLDO, 28), - [PCF50633_REGULATOR_MEMLDO] = PCF50633_REGULATOR("memldo", MEMLDO, 28), + [PCF50633_REGULATOR_AUTO] = + PCF50633_REGULATOR("auto", AUTO, 1800000, 25000, 0x2f, 128), + [PCF50633_REGULATOR_DOWN1] = + PCF50633_REGULATOR("down1", DOWN1, 625000, 25000, 0, 96), + [PCF50633_REGULATOR_DOWN2] = + PCF50633_REGULATOR("down2", DOWN2, 625000, 25000, 0, 96), + [PCF50633_REGULATOR_LDO1] = + PCF50633_REGULATOR("ldo1", LDO1, 900000, 100000, 0, 28), + [PCF50633_REGULATOR_LDO2] = + PCF50633_REGULATOR("ldo2", LDO2, 900000, 100000, 0, 28), + [PCF50633_REGULATOR_LDO3] = + PCF50633_REGULATOR("ldo3", LDO3, 900000, 100000, 0, 28), + [PCF50633_REGULATOR_LDO4] = + PCF50633_REGULATOR("ldo4", LDO4, 900000, 100000, 0, 28), + [PCF50633_REGULATOR_LDO5] = + PCF50633_REGULATOR("ldo5", LDO5, 900000, 100000, 0, 28), + [PCF50633_REGULATOR_LDO6] = + PCF50633_REGULATOR("ldo6", LDO6, 900000, 100000, 0, 28), + [PCF50633_REGULATOR_HCLDO] = + PCF50633_REGULATOR("hcldo", HCLDO, 900000, 100000, 0, 28), + [PCF50633_REGULATOR_MEMLDO] = + PCF50633_REGULATOR("memldo", MEMLDO, 900000, 100000, 0, 28), }; static int pcf50633_regulator_probe(struct platform_device *pdev) diff --git a/drivers/regulator/tps51632-regulator.c b/drivers/regulator/tps51632-regulator.c index a9c3a4a6cca0..523b1e5e0b4c 100644 --- a/drivers/regulator/tps51632-regulator.c +++ b/drivers/regulator/tps51632-regulator.c @@ -106,29 +106,23 @@ static int tps51632_dcdc_get_voltage_sel(struct regulator_dev *rdev) } vsel = data & TPS51632_VOUT_MASK; - - if (vsel < TPS51632_MIN_VSEL) - return 0; - else - return vsel - TPS51632_MIN_VSEL; + return vsel; } static int tps51632_dcdc_set_voltage_sel(struct regulator_dev *rdev, unsigned selector) { struct tps51632_chip *tps = rdev_get_drvdata(rdev); - int vsel; int ret; unsigned int reg = TPS51632_VOLTAGE_SELECT_REG; if (tps->enable_pwm_dvfs) reg = TPS51632_VOLTAGE_BASE_REG; - vsel = selector + TPS51632_MIN_VSEL; - if (vsel > TPS51632_MAX_VSEL) + if (selector > TPS51632_MAX_VSEL) return -EINVAL; - ret = regmap_write(tps->regmap, TPS51632_VOLTAGE_SELECT_REG, vsel); + ret = regmap_write(tps->regmap, reg, selector); if (ret < 0) dev_err(tps->dev, "reg write failed, err %d\n", ret); return ret; @@ -254,7 +248,8 @@ static int tps51632_probe(struct i2c_client *client, tps->desc.ramp_delay = TPS51632_DEFAULT_RAMP_DELAY; tps->desc.min_uV = TPS51632_MIN_VOLATGE; tps->desc.uV_step = TPS51632_VOLATGE_STEP_10mV; - tps->desc.n_voltages = (TPS51632_MAX_VSEL - TPS51632_MIN_VSEL) + 1; + tps->desc.linear_min_sel = TPS51632_MIN_VSEL; + tps->desc.n_voltages = TPS51632_MAX_VSEL + 1; tps->desc.ops = &tps51632_dcdc_ops; tps->desc.type = REGULATOR_VOLTAGE; tps->desc.owner = THIS_MODULE; diff --git a/include/linux/regulator/driver.h b/include/linux/regulator/driver.h index f2b72b230b9b..d10bb0f39c5e 100644 --- a/include/linux/regulator/driver.h +++ b/include/linux/regulator/driver.h @@ -187,6 +187,7 @@ enum regulator_type { * * @min_uV: Voltage given by the lowest selector (if linear mapping) * @uV_step: Voltage increase with each selector (if linear mapping) + * @linear_min_sel: Minimal selector for starting linear mapping * @ramp_delay: Time to settle down after voltage change (unit: uV/us) * @volt_table: Voltage mapping table (if table based mapping) * @@ -210,6 +211,7 @@ struct regulator_desc { unsigned int min_uV; unsigned int uV_step; + unsigned int linear_min_sel; unsigned int ramp_delay; const unsigned int *volt_table; |