Skip to content

Commit

Permalink
regulator: as3711: Convert to use linear ranges
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Axel Lin authored and Mark Brown committed Jul 24, 2013
1 parent 3b2f64d commit 9234c63
Showing 1 changed file with 31 additions and 132 deletions.
163 changes: 31 additions & 132 deletions drivers/regulator/as3711-regulator.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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,
};
Expand All @@ -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 = {
Expand All @@ -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) \
Expand All @@ -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, \
}
Expand Down

0 comments on commit 9234c63

Please sign in to comment.