1
2
3
4
5
6
7
8
9
10
11
12
13
14#include <linux/kernel.h>
15#include <linux/err.h>
16#include <linux/delay.h>
17#include <linux/regmap.h>
18#include <linux/regulator/consumer.h>
19#include <linux/regulator/driver.h>
20#include <linux/module.h>
21
22
23
24
25
26
27
28
29
30
31int regulator_is_enabled_regmap(struct regulator_dev *rdev)
32{
33 unsigned int val;
34 int ret;
35
36 ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val);
37 if (ret != 0)
38 return ret;
39
40 val &= rdev->desc->enable_mask;
41
42 if (rdev->desc->enable_is_inverted) {
43 if (rdev->desc->enable_val)
44 return val != rdev->desc->enable_val;
45 return val == 0;
46 } else {
47 if (rdev->desc->enable_val)
48 return val == rdev->desc->enable_val;
49 return val != 0;
50 }
51}
52EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
53
54
55
56
57
58
59
60
61
62
63int regulator_enable_regmap(struct regulator_dev *rdev)
64{
65 unsigned int val;
66
67 if (rdev->desc->enable_is_inverted) {
68 val = rdev->desc->disable_val;
69 } else {
70 val = rdev->desc->enable_val;
71 if (!val)
72 val = rdev->desc->enable_mask;
73 }
74
75 return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
76 rdev->desc->enable_mask, val);
77}
78EXPORT_SYMBOL_GPL(regulator_enable_regmap);
79
80
81
82
83
84
85
86
87
88
89int regulator_disable_regmap(struct regulator_dev *rdev)
90{
91 unsigned int val;
92
93 if (rdev->desc->enable_is_inverted) {
94 val = rdev->desc->enable_val;
95 if (!val)
96 val = rdev->desc->enable_mask;
97 } else {
98 val = rdev->desc->disable_val;
99 }
100
101 return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
102 rdev->desc->enable_mask, val);
103}
104EXPORT_SYMBOL_GPL(regulator_disable_regmap);
105
106
107
108
109
110
111
112
113
114
115int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
116{
117 unsigned int val;
118 int ret;
119
120 ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
121 if (ret != 0)
122 return ret;
123
124 val &= rdev->desc->vsel_mask;
125 val >>= ffs(rdev->desc->vsel_mask) - 1;
126
127 return val;
128}
129EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
130
131
132
133
134
135
136
137
138
139
140
141int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
142{
143 int ret;
144
145 sel <<= ffs(rdev->desc->vsel_mask) - 1;
146
147 ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
148 rdev->desc->vsel_mask, sel);
149 if (ret)
150 return ret;
151
152 if (rdev->desc->apply_bit)
153 ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
154 rdev->desc->apply_bit,
155 rdev->desc->apply_bit);
156 return ret;
157}
158EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
159
160
161
162
163
164
165
166
167
168
169
170
171
172int regulator_map_voltage_iterate(struct regulator_dev *rdev,
173 int min_uV, int max_uV)
174{
175 int best_val = INT_MAX;
176 int selector = 0;
177 int i, ret;
178
179
180
181
182 for (i = 0; i < rdev->desc->n_voltages; i++) {
183 ret = rdev->desc->ops->list_voltage(rdev, i);
184 if (ret < 0)
185 continue;
186
187 if (ret < best_val && ret >= min_uV && ret <= max_uV) {
188 best_val = ret;
189 selector = i;
190 }
191 }
192
193 if (best_val != INT_MAX)
194 return selector;
195 else
196 return -EINVAL;
197}
198EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
199
200
201
202
203
204
205
206
207
208
209
210int regulator_map_voltage_ascend(struct regulator_dev *rdev,
211 int min_uV, int max_uV)
212{
213 int i, ret;
214
215 for (i = 0; i < rdev->desc->n_voltages; i++) {
216 ret = rdev->desc->ops->list_voltage(rdev, i);
217 if (ret < 0)
218 continue;
219
220 if (ret > max_uV)
221 break;
222
223 if (ret >= min_uV && ret <= max_uV)
224 return i;
225 }
226
227 return -EINVAL;
228}
229EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);
230
231
232
233
234
235
236
237
238
239
240
241int regulator_map_voltage_linear(struct regulator_dev *rdev,
242 int min_uV, int max_uV)
243{
244 int ret, voltage;
245
246
247 if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
248 if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
249 return 0;
250 else
251 return -EINVAL;
252 }
253
254 if (!rdev->desc->uV_step) {
255 BUG_ON(!rdev->desc->uV_step);
256 return -EINVAL;
257 }
258
259 if (min_uV < rdev->desc->min_uV)
260 min_uV = rdev->desc->min_uV;
261
262 ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
263 if (ret < 0)
264 return ret;
265
266 ret += rdev->desc->linear_min_sel;
267
268
269 voltage = rdev->desc->ops->list_voltage(rdev, ret);
270 if (voltage < min_uV || voltage > max_uV)
271 return -EINVAL;
272
273 return ret;
274}
275EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
276
277
278
279
280
281
282
283
284
285
286
287int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
288 int min_uV, int max_uV)
289{
290 const struct regulator_linear_range *range;
291 int ret = -EINVAL;
292 int voltage, i;
293
294 if (!rdev->desc->n_linear_ranges) {
295 BUG_ON(!rdev->desc->n_linear_ranges);
296 return -EINVAL;
297 }
298
299 for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
300 int linear_max_uV;
301
302 range = &rdev->desc->linear_ranges[i];
303 linear_max_uV = range->min_uV +
304 (range->max_sel - range->min_sel) * range->uV_step;
305
306 if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
307 continue;
308
309 if (min_uV <= range->min_uV)
310 min_uV = range->min_uV;
311
312
313 if (range->uV_step == 0) {
314 ret = 0;
315 } else {
316 ret = DIV_ROUND_UP(min_uV - range->min_uV,
317 range->uV_step);
318 if (ret < 0)
319 return ret;
320 }
321
322 ret += range->min_sel;
323
324 break;
325 }
326
327 if (i == rdev->desc->n_linear_ranges)
328 return -EINVAL;
329
330
331 voltage = rdev->desc->ops->list_voltage(rdev, ret);
332 if (voltage < min_uV || voltage > max_uV)
333 return -EINVAL;
334
335 return ret;
336}
337EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
338
339
340
341
342
343
344
345
346
347
348
349int regulator_list_voltage_linear(struct regulator_dev *rdev,
350 unsigned int selector)
351{
352 if (selector >= rdev->desc->n_voltages)
353 return -EINVAL;
354 if (selector < rdev->desc->linear_min_sel)
355 return 0;
356
357 selector -= rdev->desc->linear_min_sel;
358
359 return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
360}
361EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
362
363
364
365
366
367
368
369
370
371
372
373int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
374 unsigned int selector)
375{
376 const struct regulator_linear_range *range;
377 int i;
378
379 if (!rdev->desc->n_linear_ranges) {
380 BUG_ON(!rdev->desc->n_linear_ranges);
381 return -EINVAL;
382 }
383
384 for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
385 range = &rdev->desc->linear_ranges[i];
386
387 if (!(selector >= range->min_sel &&
388 selector <= range->max_sel))
389 continue;
390
391 selector -= range->min_sel;
392
393 return range->min_uV + (range->uV_step * selector);
394 }
395
396 return -EINVAL;
397}
398EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
399
400
401
402
403
404
405
406
407
408
409
410int regulator_list_voltage_table(struct regulator_dev *rdev,
411 unsigned int selector)
412{
413 if (!rdev->desc->volt_table) {
414 BUG_ON(!rdev->desc->volt_table);
415 return -EINVAL;
416 }
417
418 if (selector >= rdev->desc->n_voltages)
419 return -EINVAL;
420
421 return rdev->desc->volt_table[selector];
422}
423EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
424
425
426
427
428
429
430
431int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
432{
433 unsigned int val;
434
435 if (enable) {
436 val = rdev->desc->bypass_val_on;
437 if (!val)
438 val = rdev->desc->bypass_mask;
439 } else {
440 val = rdev->desc->bypass_val_off;
441 }
442
443 return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
444 rdev->desc->bypass_mask, val);
445}
446EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
447
448
449
450
451
452
453
454int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
455{
456 unsigned int val;
457 int ret;
458
459 ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
460 if (ret != 0)
461 return ret;
462
463 *enable = val & rdev->desc->bypass_mask;
464
465 return 0;
466}
467EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
468