Commit 9234c636 authored by Axel Lin's avatar Axel Lin Committed by Mark Brown

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: default avatarAxel Lin <axel.lin@ingics.com>
Signed-off-by: default avatarMark Brown <broonie@linaro.org>
parent 3b2f64d0
......@@ -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, \
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment