aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/regulator/as3711-regulator.c
diff options
context:
space:
mode:
authorAxel Lin <axel.lin@ingics.com>2013-07-16 04:34:39 -0400
committerMark Brown <broonie@linaro.org>2013-07-24 10:47:07 -0400
commit9234c636c52df48a3cf280428a1d04077eef21db (patch)
tree5dbacb315fa32dab50323844a07b81eb9e87b517 /drivers/regulator/as3711-regulator.c
parent3b2f64d00c46e1e4e9bd0bb9bb12619adac27a4b (diff)
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 3da6bd6950cf..8406cd745da2 100644
--- a/drivers/regulator/as3711-regulator.c
+++ b/drivers/regulator/as3711-regulator.c
@@ -30,102 +30,6 @@ struct as3711_regulator {
30 struct regulator_dev *rdev; 30 struct regulator_dev *rdev;
31}; 31};
32 32
33static int as3711_list_voltage_sd(struct regulator_dev *rdev,
34 unsigned int selector)
35{
36 if (selector >= rdev->desc->n_voltages)
37 return -EINVAL;
38
39 if (!selector)
40 return 0;
41 if (selector < 0x41)
42 return 600000 + selector * 12500;
43 if (selector < 0x71)
44 return 1400000 + (selector - 0x40) * 25000;
45 return 2600000 + (selector - 0x70) * 50000;
46}
47
48static int as3711_list_voltage_aldo(struct regulator_dev *rdev,
49 unsigned int selector)
50{
51 if (selector >= rdev->desc->n_voltages)
52 return -EINVAL;
53
54 if (selector < 0x10)
55 return 1200000 + selector * 50000;
56 return 1800000 + (selector - 0x10) * 100000;
57}
58
59static int as3711_list_voltage_dldo(struct regulator_dev *rdev,
60 unsigned int selector)
61{
62 if (selector >= rdev->desc->n_voltages ||
63 (selector > 0x10 && selector < 0x20))
64 return -EINVAL;
65
66 if (selector < 0x11)
67 return 900000 + selector * 50000;
68 return 1750000 + (selector - 0x20) * 50000;
69}
70
71static int as3711_bound_check(struct regulator_dev *rdev,
72 int *min_uV, int *max_uV)
73{
74 struct as3711_regulator *reg = rdev_get_drvdata(rdev);
75 struct as3711_regulator_info *info = reg->reg_info;
76
77 dev_dbg(&rdev->dev, "%s(), %d, %d, %d\n", __func__,
78 *min_uV, rdev->desc->min_uV, info->max_uV);
79
80 if (*max_uV < *min_uV ||
81 *min_uV > info->max_uV || rdev->desc->min_uV > *max_uV)
82 return -EINVAL;
83
84 if (rdev->desc->n_voltages == 1)
85 return 0;
86
87 if (*max_uV > info->max_uV)
88 *max_uV = info->max_uV;
89
90 if (*min_uV < rdev->desc->min_uV)
91 *min_uV = rdev->desc->min_uV;
92
93 return *min_uV;
94}
95
96static int as3711_sel_check(int min, int max, int bottom, int step)
97{
98 int sel, voltage;
99
100 /* Round up min, when dividing: keeps us within the range */
101 sel = DIV_ROUND_UP(min - bottom, step);
102 voltage = sel * step + bottom;
103 pr_debug("%s(): select %d..%d in %d+N*%d: %d\n", __func__,
104 min, max, bottom, step, sel);
105 if (voltage > max)
106 return -EINVAL;
107
108 return sel;
109}
110
111static int as3711_map_voltage_sd(struct regulator_dev *rdev,
112 int min_uV, int max_uV)
113{
114 int ret;
115
116 ret = as3711_bound_check(rdev, &min_uV, &max_uV);
117 if (ret <= 0)
118 return ret;
119
120 if (min_uV <= 1400000)
121 return as3711_sel_check(min_uV, max_uV, 600000, 12500);
122
123 if (min_uV <= 2600000)
124 return as3711_sel_check(min_uV, max_uV, 1400000, 25000) + 0x40;
125
126 return as3711_sel_check(min_uV, max_uV, 2600000, 50000) + 0x70;
127}
128
129/* 33/*
130 * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and 34 * The regulator API supports 4 modes of operataion: FAST, NORMAL, IDLE and
131 * STANDBY. We map them in the following way to AS3711 SD1-4 DCDC modes: 35 * 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)
180 return -EINVAL; 84 return -EINVAL;
181} 85}
182 86
183static int as3711_map_voltage_aldo(struct regulator_dev *rdev,
184 int min_uV, int max_uV)
185{
186 int ret;
187
188 ret = as3711_bound_check(rdev, &min_uV, &max_uV);
189 if (ret <= 0)
190 return ret;
191
192 if (min_uV <= 1800000)
193 return as3711_sel_check(min_uV, max_uV, 1200000, 50000);
194
195 return as3711_sel_check(min_uV, max_uV, 1800000, 100000) + 0x10;
196}
197
198static int as3711_map_voltage_dldo(struct regulator_dev *rdev,
199 int min_uV, int max_uV)
200{
201 int ret;
202
203 ret = as3711_bound_check(rdev, &min_uV, &max_uV);
204 if (ret <= 0)
205 return ret;
206
207 if (min_uV <= 1700000)
208 return as3711_sel_check(min_uV, max_uV, 900000, 50000);
209
210 return as3711_sel_check(min_uV, max_uV, 1750000, 50000) + 0x20;
211}
212
213static struct regulator_ops as3711_sd_ops = { 87static struct regulator_ops as3711_sd_ops = {
214 .is_enabled = regulator_is_enabled_regmap, 88 .is_enabled = regulator_is_enabled_regmap,
215 .enable = regulator_enable_regmap, 89 .enable = regulator_enable_regmap,
216 .disable = regulator_disable_regmap, 90 .disable = regulator_disable_regmap,
217 .get_voltage_sel = regulator_get_voltage_sel_regmap, 91 .get_voltage_sel = regulator_get_voltage_sel_regmap,
218 .set_voltage_sel = regulator_set_voltage_sel_regmap, 92 .set_voltage_sel = regulator_set_voltage_sel_regmap,
219 .list_voltage = as3711_list_voltage_sd, 93 .list_voltage = regulator_list_voltage_linear_range,
220 .map_voltage = as3711_map_voltage_sd, 94 .map_voltage = regulator_map_voltage_linear_range,
221 .get_mode = as3711_get_mode_sd, 95 .get_mode = as3711_get_mode_sd,
222 .set_mode = as3711_set_mode_sd, 96 .set_mode = as3711_set_mode_sd,
223}; 97};
@@ -228,8 +102,8 @@ static struct regulator_ops as3711_aldo_ops = {
228 .disable = regulator_disable_regmap, 102 .disable = regulator_disable_regmap,
229 .get_voltage_sel = regulator_get_voltage_sel_regmap, 103 .get_voltage_sel = regulator_get_voltage_sel_regmap,
230 .set_voltage_sel = regulator_set_voltage_sel_regmap, 104 .set_voltage_sel = regulator_set_voltage_sel_regmap,
231 .list_voltage = as3711_list_voltage_aldo, 105 .list_voltage = regulator_list_voltage_linear_range,
232 .map_voltage = as3711_map_voltage_aldo, 106 .map_voltage = regulator_map_voltage_linear_range,
233}; 107};
234 108
235static struct regulator_ops as3711_dldo_ops = { 109static struct regulator_ops as3711_dldo_ops = {
@@ -238,8 +112,31 @@ static struct regulator_ops as3711_dldo_ops = {
238 .disable = regulator_disable_regmap, 112 .disable = regulator_disable_regmap,
239 .get_voltage_sel = regulator_get_voltage_sel_regmap, 113 .get_voltage_sel = regulator_get_voltage_sel_regmap,
240 .set_voltage_sel = regulator_set_voltage_sel_regmap, 114 .set_voltage_sel = regulator_set_voltage_sel_regmap,
241 .list_voltage = as3711_list_voltage_dldo, 115 .list_voltage = regulator_list_voltage_linear_range,
242 .map_voltage = as3711_map_voltage_dldo, 116 .map_voltage = regulator_map_voltage_linear_range,
117};
118
119static const struct regulator_linear_range as3711_sd_ranges[] = {
120 { .min_uV = 612500, .max_uV = 1400000,
121 .min_sel = 0x1, .max_sel = 0x40, .uV_step = 12500 },
122 { .min_uV = 1425000, .max_uV = 2600000,
123 .min_sel = 0x41, .max_sel = 0x70, .uV_step = 25000 },
124 { .min_uV = 2650000, .max_uV = 3350000,
125 .min_sel = 0x71, .max_sel = 0x7f, .uV_step = 50000 },
126};
127
128static const struct regulator_linear_range as3711_aldo_ranges[] = {
129 { .min_uV = 1200000, .max_uV = 1950000,
130 .min_sel = 0, .max_sel = 0xf, .uV_step = 50000 },
131 { .min_uV = 1800000, .max_uV = 3300000,
132 .min_sel = 0x10, .max_sel = 0x1f, .uV_step = 100000 },
133};
134
135static const struct regulator_linear_range as3711_dldo_ranges[] = {
136 { .min_uV = 900000, .max_uV = 1700000,
137 .min_sel = 0, .max_sel = 0x10, .uV_step = 50000 },
138 { .min_uV = 1750000, .max_uV = 3300000,
139 .min_sel = 0x20, .max_sel = 0x3f, .uV_step = 50000 },
243}; 140};
244 141
245#define AS3711_REG(_id, _en_reg, _en_bit, _vmask, _vshift, _min_uV, _max_uV, _sfx) \ 142#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 = {
256 .enable_reg = AS3711_ ## _en_reg, \ 153 .enable_reg = AS3711_ ## _en_reg, \
257 .enable_mask = BIT(_en_bit), \ 154 .enable_mask = BIT(_en_bit), \
258 .min_uV = _min_uV, \ 155 .min_uV = _min_uV, \
156 .linear_ranges = as3711_ ## _sfx ## _ranges, \
157 .n_linear_ranges = ARRAY_SIZE(as3711_ ## _sfx ## _ranges), \
259 }, \ 158 }, \
260 .max_uV = _max_uV, \ 159 .max_uV = _max_uV, \
261} 160}