summaryrefslogtreecommitdiffstats
path: root/drivers/regulator/as3711-regulator.c
diff options
context:
space:
mode:
authorAxel Lin <axel.lin@ingics.com>2013-07-16 16:34:39 +0800
committerMark Brown <broonie@linaro.org>2013-07-24 15:47:07 +0100
commit9234c636c52df48a3cf280428a1d04077eef21db (patch)
tree5dbacb315fa32dab50323844a07b81eb9e87b517 /drivers/regulator/as3711-regulator.c
parent3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b (diff)
downloadop-kernel-dev-9234c636c52df48a3cf280428a1d04077eef21db.zip
op-kernel-dev-9234c636c52df48a3cf280428a1d04077eef21db.tar.gz
regulator: as3711: Convert to use linear ranges
The SD, ALDO, and DLDO vlotage tables are composed of linear ranges. This patch converts as3711 to use newly introduced helpers for multiple linear ranges. Below is the voltage table on datasheet: SD: 00h: DC/DC powered down 01h-40h: Volt = 0.6V + sdx_vsel * 12.5mV 41h-70h: Volt = 1.4V + (sdx_vsel - 40h) * 25mV 71h-7Fh: Volt = 2.6V + (sdx_vsel - 70h) * 50mV ALDO: 0h-0Fh: 1.2V + ldox_vsel * 50mV 10h-1Fh: 1.8V + (ldox_vsel - 10h) * 100mV DLDO: 00h-10h: Volt = 0.9V + ldox_vsel * 50mV 11h-1fh: Do not use 20h-3fh: Volt = 1.75V + (ldox_vsel - 20h) * 50mV Note, when convert to use linear ranges APIs, the equation for SD needs below adjustment because the linear ranges APIs wiil substract range->min_sel when apply the equation. SD ( the equation to be used with linear ranges APIs ) 01h-40h: Volt = 0.6125V + (sdx_vsel - 1h) * 12.5mV 41h-70h: Volt = 1.425V + (sdx_vsel - 41h) * 25mV 71h-7Fh: Volt = 2.650V + (sdx_vsel - 71h) * 50mV Signed-off-by: Axel Lin <axel.lin@ingics.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Diffstat (limited to 'drivers/regulator/as3711-regulator.c')
-rw-r--r--drivers/regulator/as3711-regulator.c163
1 files changed, 31 insertions, 132 deletions
diff --git a/drivers/regulator/as3711-regulator.c b/drivers/regulator/as3711-regulator.c
index 3da6bd6..8406cd7 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -30,102 +30,6 @@ struct as3711_regulator {
struct regulator_dev *rdev;
};
-static int as3711_list_voltage_sd(struct regulator_dev *rdev,
- unsigned int selector)
-{
- if (selector >= rdev->desc->n_voltages)
- return -EINVAL;
-
- if (!selector)
- return 0;
- if (selector < 0x41)
- return 600000 + selector * 12500;
- if (selector < 0x71)
- return 1400000 + (selector - 0x40) * 25000;
- return 2600000 + (selector - 0x70) * 50000;
-}
-
-static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
- unsigned int selector)
-{
- if (selector >= rdev->desc->n_voltages)
- return -EINVAL;
-
- if (selector < 0x10)
- return 1200000 + selector * 50000;
- return 1800000 + (selector - 0x10) * 100000;
-}
-
-static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
- unsigned int selector)
-{
- if (selector >= rdev->desc->n_voltages ||
- (selector > 0x10 && selector < 0x20))
- return -EINVAL;
-
- if (selector < 0x11)
- return 900000 + selector * 50000;
- return 1750000 + (selector - 0x20) * 50000;
-}
-
-static int as3711_bound_check(struct regulator_dev *rdev,
- int *min_uV, int *max_uV)
-{
- struct as3711_regulator *reg = rdev_get_drvdata(rdev);
- struct as3711_regulator_info *info = reg->reg_info;
-
- dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
- *min_uV, rdev->desc->min_uV, info->max_uV);
-
- if (*max_uV < *min_uV ||
- *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
- return -EINVAL;
-
- if (rdev->desc->n_voltages == 1)
- return 0;
-
- if (*max_uV > info->max_uV)
- *max_uV = info->max_uV;
-
- if (*min_uV < rdev->desc->min_uV)
- *min_uV = rdev->desc->min_uV;
-
- return *min_uV;
-}
-
-static int as3711_sel_check(int min, int max, int bottom, int step)
-{
- int sel, voltage;
-
- /* Round up min, when dividing: keeps us within the range */
- sel = DIV_ROUND_UP(min - bottom, step);
- voltage = sel * step + bottom;
- pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
- min, max, bottom, step, sel);
- if (voltage > max)
- return -EINVAL;
-
- return sel;
-}
-
-static int as3711_map_voltage_sd(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- int ret;
-
- ret = as3711_bound_check(rdev, &min_uV, &max_uV);
- if (ret <= 0)
- return ret;
-
- if (min_uV <= 1400000)
- return as3711_sel_check(min_uV, max_uV, 600000, 12500);
-
- if (min_uV <= 2600000)
- return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
-
- return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
-}
-
/*
* The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
* STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes:
@@ -180,44 +84,14 @@ static unsigned int as3711_get_mode_sd(struct regulator_dev *rdev)
return -EINVAL;
}
-static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- int ret;
-
- ret = as3711_bound_check(rdev, &min_uV, &max_uV);
- if (ret <= 0)
- return ret;
-
- if (min_uV <= 1800000)
- return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
-
- return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
-}
-
-static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
- int min_uV, int max_uV)
-{
- int ret;
-
- ret = as3711_bound_check(rdev, &min_uV, &max_uV);
- if (ret <= 0)
- return ret;
-
- if (min_uV <= 1700000)
- return as3711_sel_check(min_uV, max_uV, 900000, 50000);
-
- return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
-}
-
static struct regulator_ops as3711_sd_ops = {
.is_enabled = regulator_is_enabled_regmap,
.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 = as3711_list_voltage_sd,
- .map_voltage = as3711_map_voltage_sd,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
.get_mode = as3711_get_mode_sd,
.set_mode = as3711_set_mode_sd,
};
@@ -228,8 +102,8 @@ static struct regulator_ops as3711_aldo_ops = {
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .list_voltage = as3711_list_voltage_aldo,
- .map_voltage = as3711_map_voltage_aldo,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
};
static struct regulator_ops as3711_dldo_ops = {
@@ -238,8 +112,31 @@ static struct regulator_ops as3711_dldo_ops = {
.disable = regulator_disable_regmap,
.get_voltage_sel = regulator_get_voltage_sel_regmap,
.set_voltage_sel = regulator_set_voltage_sel_regmap,
- .list_voltage = as3711_list_voltage_dldo,
- .map_voltage = as3711_map_voltage_dldo,
+ .list_voltage = regulator_list_voltage_linear_range,
+ .map_voltage = regulator_map_voltage_linear_range,
+};
+
+static const struct regulator_linear_range as3711_sd_ranges[] = {
+ { .min_uV = 612500, .max_uV = 1400000,
+ .min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 },
+ { .min_uV = 1425000, .max_uV = 2600000,
+ .min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 },
+ { .min_uV = 2650000, .max_uV = 3350000,
+ .min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 },
+};
+
+static const struct regulator_linear_range as3711_aldo_ranges[] = {
+ { .min_uV = 1200000, .max_uV = 1950000,
+ .min_sel = 0, .max_sel = 0xf, .uV_step = 50000 },
+ { .min_uV = 1800000, .max_uV = 3300000,
+ .min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 },
+};
+
+static const struct regulator_linear_range as3711_dldo_ranges[] = {
+ { .min_uV = 900000, .max_uV = 1700000,
+ .min_sel = 0, .max_sel = 0x10, .uV_step = 50000 },
+ { .min_uV = 1750000, .max_uV = 3300000,
+ .min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 },
};
#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \
@@ -256,6 +153,8 @@ static struct regulator_ops as3711_dldo_ops = {
.enable_reg = AS3711_ ## _en_reg, \
.enable_mask = BIT(_en_bit), \
.min_uV = _min_uV, \
+ .linear_ranges = as3711_ ## _sfx ## _ranges, \
+ .n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges), \
}, \
.max_uV = _max_uV, \
}
OpenPOWER on IntegriCloud