Commit | Line | Data |
---|---|---|
2874c5fd | 1 | // SPDX-License-Identifier: GPL-2.0-or-later |
f2c6203f MB |
2 | // |
3 | // helpers.c -- Voltage/Current Regulator framework helper functions. | |
4 | // | |
5 | // Copyright 2007, 2008 Wolfson Microelectronics PLC. | |
6 | // Copyright 2008 SlimLogic Ltd. | |
c4a54b8d MB |
7 | |
8 | #include <linux/kernel.h> | |
9 | #include <linux/err.h> | |
10 | #include <linux/delay.h> | |
11 | #include <linux/regmap.h> | |
12 | #include <linux/regulator/consumer.h> | |
13 | #include <linux/regulator/driver.h> | |
14 | #include <linux/module.h> | |
15 | ||
16 | /** | |
17 | * regulator_is_enabled_regmap - standard is_enabled() for regmap users | |
18 | * | |
19 | * @rdev: regulator to operate on | |
20 | * | |
21 | * Regulators that use regmap for their register I/O can set the | |
22 | * enable_reg and enable_mask fields in their descriptor and then use | |
23 | * this as their is_enabled operation, saving some code. | |
24 | */ | |
25 | int regulator_is_enabled_regmap(struct regulator_dev *rdev) | |
26 | { | |
27 | unsigned int val; | |
28 | int ret; | |
29 | ||
30 | ret = regmap_read(rdev->regmap, rdev->desc->enable_reg, &val); | |
31 | if (ret != 0) | |
32 | return ret; | |
33 | ||
ca5d1b35 CC |
34 | val &= rdev->desc->enable_mask; |
35 | ||
36 | if (rdev->desc->enable_is_inverted) { | |
37 | if (rdev->desc->enable_val) | |
38 | return val != rdev->desc->enable_val; | |
39 | return val == 0; | |
40 | } else { | |
41 | if (rdev->desc->enable_val) | |
42 | return val == rdev->desc->enable_val; | |
43 | return val != 0; | |
44 | } | |
c4a54b8d MB |
45 | } |
46 | EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap); | |
47 | ||
48 | /** | |
49 | * regulator_enable_regmap - standard enable() for regmap users | |
50 | * | |
51 | * @rdev: regulator to operate on | |
52 | * | |
53 | * Regulators that use regmap for their register I/O can set the | |
54 | * enable_reg and enable_mask fields in their descriptor and then use | |
55 | * this as their enable() operation, saving some code. | |
56 | */ | |
57 | int regulator_enable_regmap(struct regulator_dev *rdev) | |
58 | { | |
59 | unsigned int val; | |
60 | ||
ca5d1b35 CC |
61 | if (rdev->desc->enable_is_inverted) { |
62 | val = rdev->desc->disable_val; | |
63 | } else { | |
64 | val = rdev->desc->enable_val; | |
65 | if (!val) | |
66 | val = rdev->desc->enable_mask; | |
67 | } | |
c4a54b8d MB |
68 | |
69 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | |
70 | rdev->desc->enable_mask, val); | |
71 | } | |
72 | EXPORT_SYMBOL_GPL(regulator_enable_regmap); | |
73 | ||
74 | /** | |
75 | * regulator_disable_regmap - standard disable() for regmap users | |
76 | * | |
77 | * @rdev: regulator to operate on | |
78 | * | |
79 | * Regulators that use regmap for their register I/O can set the | |
80 | * enable_reg and enable_mask fields in their descriptor and then use | |
81 | * this as their disable() operation, saving some code. | |
82 | */ | |
83 | int regulator_disable_regmap(struct regulator_dev *rdev) | |
84 | { | |
85 | unsigned int val; | |
86 | ||
ca5d1b35 CC |
87 | if (rdev->desc->enable_is_inverted) { |
88 | val = rdev->desc->enable_val; | |
89 | if (!val) | |
90 | val = rdev->desc->enable_mask; | |
91 | } else { | |
92 | val = rdev->desc->disable_val; | |
93 | } | |
c4a54b8d MB |
94 | |
95 | return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg, | |
96 | rdev->desc->enable_mask, val); | |
97 | } | |
98 | EXPORT_SYMBOL_GPL(regulator_disable_regmap); | |
99 | ||
18e4b55f MV |
100 | static int regulator_range_selector_to_index(struct regulator_dev *rdev, |
101 | unsigned int rval) | |
102 | { | |
103 | int i; | |
104 | ||
105 | if (!rdev->desc->linear_range_selectors) | |
106 | return -EINVAL; | |
107 | ||
108 | rval &= rdev->desc->vsel_range_mask; | |
109 | ||
110 | for (i = 0; i < rdev->desc->n_linear_ranges; i++) { | |
111 | if (rdev->desc->linear_range_selectors[i] == rval) | |
112 | return i; | |
113 | } | |
114 | return -EINVAL; | |
115 | } | |
116 | ||
117 | /** | |
118 | * regulator_get_voltage_sel_pickable_regmap - pickable range get_voltage_sel | |
119 | * | |
120 | * @rdev: regulator to operate on | |
121 | * | |
122 | * Regulators that use regmap for their register I/O and use pickable | |
123 | * ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask | |
124 | * fields in their descriptor and then use this as their get_voltage_vsel | |
125 | * operation, saving some code. | |
126 | */ | |
127 | int regulator_get_voltage_sel_pickable_regmap(struct regulator_dev *rdev) | |
128 | { | |
129 | unsigned int r_val; | |
130 | int range; | |
131 | unsigned int val; | |
132 | int ret, i; | |
133 | unsigned int voltages_in_range = 0; | |
134 | ||
135 | if (!rdev->desc->linear_ranges) | |
136 | return -EINVAL; | |
137 | ||
138 | ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); | |
139 | if (ret != 0) | |
140 | return ret; | |
141 | ||
142 | ret = regmap_read(rdev->regmap, rdev->desc->vsel_range_reg, &r_val); | |
143 | if (ret != 0) | |
144 | return ret; | |
145 | ||
146 | val &= rdev->desc->vsel_mask; | |
147 | val >>= ffs(rdev->desc->vsel_mask) - 1; | |
148 | ||
149 | range = regulator_range_selector_to_index(rdev, r_val); | |
150 | if (range < 0) | |
151 | return -EINVAL; | |
152 | ||
153 | for (i = 0; i < range; i++) | |
154 | voltages_in_range += (rdev->desc->linear_ranges[i].max_sel - | |
155 | rdev->desc->linear_ranges[i].min_sel) + 1; | |
156 | ||
157 | return val + voltages_in_range; | |
158 | } | |
159 | EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_pickable_regmap); | |
160 | ||
161 | /** | |
162 | * regulator_set_voltage_sel_pickable_regmap - pickable range set_voltage_sel | |
163 | * | |
164 | * @rdev: regulator to operate on | |
165 | * @sel: Selector to set | |
166 | * | |
167 | * Regulators that use regmap for their register I/O and use pickable | |
168 | * ranges can set the vsel_reg, vsel_mask, vsel_range_reg and vsel_range_mask | |
169 | * fields in their descriptor and then use this as their set_voltage_vsel | |
170 | * operation, saving some code. | |
171 | */ | |
172 | int regulator_set_voltage_sel_pickable_regmap(struct regulator_dev *rdev, | |
173 | unsigned int sel) | |
174 | { | |
175 | unsigned int range; | |
176 | int ret, i; | |
177 | unsigned int voltages_in_range = 0; | |
178 | ||
179 | for (i = 0; i < rdev->desc->n_linear_ranges; i++) { | |
180 | voltages_in_range = (rdev->desc->linear_ranges[i].max_sel - | |
181 | rdev->desc->linear_ranges[i].min_sel) + 1; | |
182 | if (sel < voltages_in_range) | |
183 | break; | |
184 | sel -= voltages_in_range; | |
185 | } | |
186 | ||
187 | if (i == rdev->desc->n_linear_ranges) | |
188 | return -EINVAL; | |
189 | ||
190 | sel <<= ffs(rdev->desc->vsel_mask) - 1; | |
191 | sel += rdev->desc->linear_ranges[i].min_sel; | |
192 | ||
193 | range = rdev->desc->linear_range_selectors[i]; | |
194 | ||
195 | if (rdev->desc->vsel_reg == rdev->desc->vsel_range_reg) { | |
196 | ret = regmap_update_bits(rdev->regmap, | |
197 | rdev->desc->vsel_reg, | |
198 | rdev->desc->vsel_range_mask | | |
199 | rdev->desc->vsel_mask, sel | range); | |
200 | } else { | |
201 | ret = regmap_update_bits(rdev->regmap, | |
202 | rdev->desc->vsel_range_reg, | |
203 | rdev->desc->vsel_range_mask, range); | |
204 | if (ret) | |
205 | return ret; | |
206 | ||
207 | ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, | |
208 | rdev->desc->vsel_mask, sel); | |
209 | } | |
210 | ||
211 | if (ret) | |
212 | return ret; | |
213 | ||
214 | if (rdev->desc->apply_bit) | |
215 | ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, | |
216 | rdev->desc->apply_bit, | |
217 | rdev->desc->apply_bit); | |
218 | return ret; | |
219 | } | |
220 | EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_pickable_regmap); | |
221 | ||
c4a54b8d MB |
222 | /** |
223 | * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users | |
224 | * | |
225 | * @rdev: regulator to operate on | |
226 | * | |
227 | * Regulators that use regmap for their register I/O can set the | |
228 | * vsel_reg and vsel_mask fields in their descriptor and then use this | |
229 | * as their get_voltage_vsel operation, saving some code. | |
230 | */ | |
231 | int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev) | |
232 | { | |
233 | unsigned int val; | |
234 | int ret; | |
235 | ||
236 | ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val); | |
237 | if (ret != 0) | |
238 | return ret; | |
239 | ||
240 | val &= rdev->desc->vsel_mask; | |
241 | val >>= ffs(rdev->desc->vsel_mask) - 1; | |
242 | ||
243 | return val; | |
244 | } | |
245 | EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap); | |
246 | ||
247 | /** | |
248 | * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users | |
249 | * | |
250 | * @rdev: regulator to operate on | |
251 | * @sel: Selector to set | |
252 | * | |
253 | * Regulators that use regmap for their register I/O can set the | |
254 | * vsel_reg and vsel_mask fields in their descriptor and then use this | |
255 | * as their set_voltage_vsel operation, saving some code. | |
256 | */ | |
257 | int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel) | |
258 | { | |
259 | int ret; | |
260 | ||
261 | sel <<= ffs(rdev->desc->vsel_mask) - 1; | |
262 | ||
263 | ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg, | |
264 | rdev->desc->vsel_mask, sel); | |
265 | if (ret) | |
266 | return ret; | |
267 | ||
268 | if (rdev->desc->apply_bit) | |
269 | ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg, | |
270 | rdev->desc->apply_bit, | |
271 | rdev->desc->apply_bit); | |
272 | return ret; | |
273 | } | |
274 | EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap); | |
275 | ||
276 | /** | |
277 | * regulator_map_voltage_iterate - map_voltage() based on list_voltage() | |
278 | * | |
279 | * @rdev: Regulator to operate on | |
280 | * @min_uV: Lower bound for voltage | |
281 | * @max_uV: Upper bound for voltage | |
282 | * | |
283 | * Drivers implementing set_voltage_sel() and list_voltage() can use | |
284 | * this as their map_voltage() operation. It will find a suitable | |
285 | * voltage by calling list_voltage() until it gets something in bounds | |
286 | * for the requested voltages. | |
287 | */ | |
288 | int regulator_map_voltage_iterate(struct regulator_dev *rdev, | |
289 | int min_uV, int max_uV) | |
290 | { | |
291 | int best_val = INT_MAX; | |
292 | int selector = 0; | |
293 | int i, ret; | |
294 | ||
295 | /* Find the smallest voltage that falls within the specified | |
296 | * range. | |
297 | */ | |
298 | for (i = 0; i < rdev->desc->n_voltages; i++) { | |
299 | ret = rdev->desc->ops->list_voltage(rdev, i); | |
300 | if (ret < 0) | |
301 | continue; | |
302 | ||
303 | if (ret < best_val && ret >= min_uV && ret <= max_uV) { | |
304 | best_val = ret; | |
305 | selector = i; | |
306 | } | |
307 | } | |
308 | ||
309 | if (best_val != INT_MAX) | |
310 | return selector; | |
311 | else | |
312 | return -EINVAL; | |
313 | } | |
314 | EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate); | |
315 | ||
316 | /** | |
317 | * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list | |
318 | * | |
319 | * @rdev: Regulator to operate on | |
320 | * @min_uV: Lower bound for voltage | |
321 | * @max_uV: Upper bound for voltage | |
322 | * | |
323 | * Drivers that have ascendant voltage list can use this as their | |
324 | * map_voltage() operation. | |
325 | */ | |
326 | int regulator_map_voltage_ascend(struct regulator_dev *rdev, | |
327 | int min_uV, int max_uV) | |
328 | { | |
329 | int i, ret; | |
330 | ||
331 | for (i = 0; i < rdev->desc->n_voltages; i++) { | |
332 | ret = rdev->desc->ops->list_voltage(rdev, i); | |
333 | if (ret < 0) | |
334 | continue; | |
335 | ||
336 | if (ret > max_uV) | |
337 | break; | |
338 | ||
339 | if (ret >= min_uV && ret <= max_uV) | |
340 | return i; | |
341 | } | |
342 | ||
343 | return -EINVAL; | |
344 | } | |
345 | EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend); | |
346 | ||
347 | /** | |
348 | * regulator_map_voltage_linear - map_voltage() for simple linear mappings | |
349 | * | |
350 | * @rdev: Regulator to operate on | |
351 | * @min_uV: Lower bound for voltage | |
352 | * @max_uV: Upper bound for voltage | |
353 | * | |
354 | * Drivers providing min_uV and uV_step in their regulator_desc can | |
355 | * use this as their map_voltage() operation. | |
356 | */ | |
357 | int regulator_map_voltage_linear(struct regulator_dev *rdev, | |
358 | int min_uV, int max_uV) | |
359 | { | |
360 | int ret, voltage; | |
361 | ||
362 | /* Allow uV_step to be 0 for fixed voltage */ | |
363 | if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) { | |
364 | if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV) | |
365 | return 0; | |
366 | else | |
367 | return -EINVAL; | |
368 | } | |
369 | ||
370 | if (!rdev->desc->uV_step) { | |
371 | BUG_ON(!rdev->desc->uV_step); | |
372 | return -EINVAL; | |
373 | } | |
374 | ||
375 | if (min_uV < rdev->desc->min_uV) | |
376 | min_uV = rdev->desc->min_uV; | |
377 | ||
378 | ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step); | |
379 | if (ret < 0) | |
380 | return ret; | |
381 | ||
382 | ret += rdev->desc->linear_min_sel; | |
383 | ||
384 | /* Map back into a voltage to verify we're still in bounds */ | |
385 | voltage = rdev->desc->ops->list_voltage(rdev, ret); | |
386 | if (voltage < min_uV || voltage > max_uV) | |
387 | return -EINVAL; | |
388 | ||
389 | return ret; | |
390 | } | |
391 | EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); | |
392 | ||
393 | /** | |
43343f8d | 394 | * regulator_map_voltage_linear_range - map_voltage() for multiple linear ranges |
c4a54b8d MB |
395 | * |
396 | * @rdev: Regulator to operate on | |
397 | * @min_uV: Lower bound for voltage | |
398 | * @max_uV: Upper bound for voltage | |
399 | * | |
400 | * Drivers providing linear_ranges in their descriptor can use this as | |
401 | * their map_voltage() callback. | |
402 | */ | |
403 | int regulator_map_voltage_linear_range(struct regulator_dev *rdev, | |
404 | int min_uV, int max_uV) | |
405 | { | |
406 | const struct regulator_linear_range *range; | |
407 | int ret = -EINVAL; | |
408 | int voltage, i; | |
409 | ||
410 | if (!rdev->desc->n_linear_ranges) { | |
411 | BUG_ON(!rdev->desc->n_linear_ranges); | |
412 | return -EINVAL; | |
413 | } | |
414 | ||
415 | for (i = 0; i < rdev->desc->n_linear_ranges; i++) { | |
e277e656 AL |
416 | int linear_max_uV; |
417 | ||
c4a54b8d | 418 | range = &rdev->desc->linear_ranges[i]; |
e277e656 AL |
419 | linear_max_uV = range->min_uV + |
420 | (range->max_sel - range->min_sel) * range->uV_step; | |
c4a54b8d | 421 | |
e277e656 | 422 | if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV)) |
c4a54b8d MB |
423 | continue; |
424 | ||
425 | if (min_uV <= range->min_uV) | |
426 | min_uV = range->min_uV; | |
427 | ||
428 | /* range->uV_step == 0 means fixed voltage range */ | |
429 | if (range->uV_step == 0) { | |
430 | ret = 0; | |
431 | } else { | |
432 | ret = DIV_ROUND_UP(min_uV - range->min_uV, | |
433 | range->uV_step); | |
434 | if (ret < 0) | |
435 | return ret; | |
436 | } | |
437 | ||
438 | ret += range->min_sel; | |
439 | ||
e7d80b6b MV |
440 | /* |
441 | * Map back into a voltage to verify we're still in bounds. | |
442 | * If we are not, then continue checking rest of the ranges. | |
443 | */ | |
444 | voltage = rdev->desc->ops->list_voltage(rdev, ret); | |
445 | if (voltage >= min_uV && voltage <= max_uV) | |
446 | break; | |
c4a54b8d MB |
447 | } |
448 | ||
449 | if (i == rdev->desc->n_linear_ranges) | |
450 | return -EINVAL; | |
451 | ||
c4a54b8d MB |
452 | return ret; |
453 | } | |
454 | EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range); | |
455 | ||
18e4b55f MV |
456 | /** |
457 | * regulator_map_voltage_pickable_linear_range - map_voltage, pickable ranges | |
458 | * | |
459 | * @rdev: Regulator to operate on | |
460 | * @min_uV: Lower bound for voltage | |
461 | * @max_uV: Upper bound for voltage | |
462 | * | |
463 | * Drivers providing pickable linear_ranges in their descriptor can use | |
464 | * this as their map_voltage() callback. | |
465 | */ | |
466 | int regulator_map_voltage_pickable_linear_range(struct regulator_dev *rdev, | |
467 | int min_uV, int max_uV) | |
468 | { | |
469 | const struct regulator_linear_range *range; | |
470 | int ret = -EINVAL; | |
471 | int voltage, i; | |
472 | unsigned int selector = 0; | |
473 | ||
474 | if (!rdev->desc->n_linear_ranges) { | |
475 | BUG_ON(!rdev->desc->n_linear_ranges); | |
476 | return -EINVAL; | |
477 | } | |
478 | ||
479 | for (i = 0; i < rdev->desc->n_linear_ranges; i++) { | |
480 | int linear_max_uV; | |
481 | ||
482 | range = &rdev->desc->linear_ranges[i]; | |
483 | linear_max_uV = range->min_uV + | |
484 | (range->max_sel - range->min_sel) * range->uV_step; | |
485 | ||
486 | if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV)) { | |
487 | selector += (range->max_sel - range->min_sel + 1); | |
488 | continue; | |
489 | } | |
490 | ||
491 | if (min_uV <= range->min_uV) | |
492 | min_uV = range->min_uV; | |
493 | ||
494 | /* range->uV_step == 0 means fixed voltage range */ | |
495 | if (range->uV_step == 0) { | |
496 | ret = 0; | |
497 | } else { | |
498 | ret = DIV_ROUND_UP(min_uV - range->min_uV, | |
499 | range->uV_step); | |
500 | if (ret < 0) | |
501 | return ret; | |
502 | } | |
503 | ||
504 | ret += selector; | |
505 | ||
506 | voltage = rdev->desc->ops->list_voltage(rdev, ret); | |
507 | ||
508 | /* | |
509 | * Map back into a voltage to verify we're still in bounds. | |
510 | * We may have overlapping voltage ranges. Hence we don't | |
511 | * exit but retry until we have checked all ranges. | |
512 | */ | |
513 | if (voltage < min_uV || voltage > max_uV) | |
514 | selector += (range->max_sel - range->min_sel + 1); | |
515 | else | |
516 | break; | |
517 | } | |
518 | ||
519 | if (i == rdev->desc->n_linear_ranges) | |
520 | return -EINVAL; | |
521 | ||
522 | return ret; | |
523 | } | |
524 | EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range); | |
525 | ||
d295f767 AL |
526 | /** |
527 | * regulator_list_voltage_linear - List voltages with simple calculation | |
528 | * | |
529 | * @rdev: Regulator device | |
530 | * @selector: Selector to convert into a voltage | |
531 | * | |
532 | * Regulators with a simple linear mapping between voltages and | |
533 | * selectors can set min_uV and uV_step in the regulator descriptor | |
534 | * and then use this function as their list_voltage() operation, | |
535 | */ | |
536 | int regulator_list_voltage_linear(struct regulator_dev *rdev, | |
537 | unsigned int selector) | |
538 | { | |
539 | if (selector >= rdev->desc->n_voltages) | |
540 | return -EINVAL; | |
541 | if (selector < rdev->desc->linear_min_sel) | |
542 | return 0; | |
543 | ||
544 | selector -= rdev->desc->linear_min_sel; | |
545 | ||
546 | return rdev->desc->min_uV + (rdev->desc->uV_step * selector); | |
547 | } | |
548 | EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); | |
549 | ||
18e4b55f MV |
550 | /** |
551 | * regulator_list_voltage_pickable_linear_range - pickable range list voltages | |
552 | * | |
553 | * @rdev: Regulator device | |
554 | * @selector: Selector to convert into a voltage | |
555 | * | |
556 | * list_voltage() operation, intended to be used by drivers utilizing pickable | |
557 | * ranges helpers. | |
558 | */ | |
559 | int regulator_list_voltage_pickable_linear_range(struct regulator_dev *rdev, | |
560 | unsigned int selector) | |
561 | { | |
562 | const struct regulator_linear_range *range; | |
563 | int i; | |
564 | unsigned int all_sels = 0; | |
565 | ||
566 | if (!rdev->desc->n_linear_ranges) { | |
567 | BUG_ON(!rdev->desc->n_linear_ranges); | |
568 | return -EINVAL; | |
569 | } | |
570 | ||
571 | for (i = 0; i < rdev->desc->n_linear_ranges; i++) { | |
572 | unsigned int sels_in_range; | |
573 | ||
574 | range = &rdev->desc->linear_ranges[i]; | |
575 | ||
576 | sels_in_range = range->max_sel - range->min_sel; | |
577 | ||
578 | if (all_sels + sels_in_range >= selector) { | |
579 | selector -= all_sels; | |
580 | return range->min_uV + (range->uV_step * selector); | |
581 | } | |
582 | ||
583 | all_sels += (sels_in_range + 1); | |
584 | } | |
585 | ||
586 | return -EINVAL; | |
587 | } | |
588 | EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range); | |
589 | ||
d295f767 | 590 | /** |
6a47b4da | 591 | * regulator_desc_list_voltage_linear_range - List voltages for linear ranges |
d295f767 | 592 | * |
6a47b4da | 593 | * @desc: Regulator desc for regulator which volatges are to be listed |
d295f767 AL |
594 | * @selector: Selector to convert into a voltage |
595 | * | |
596 | * Regulators with a series of simple linear mappings between voltages | |
6a47b4da MV |
597 | * and selectors who have set linear_ranges in the regulator descriptor |
598 | * can use this function prior regulator registration to list voltages. | |
599 | * This is useful when voltages need to be listed during device-tree | |
600 | * parsing. | |
d295f767 | 601 | */ |
6a47b4da MV |
602 | int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc, |
603 | unsigned int selector) | |
d295f767 AL |
604 | { |
605 | const struct regulator_linear_range *range; | |
606 | int i; | |
607 | ||
6a47b4da MV |
608 | if (!desc->n_linear_ranges) { |
609 | BUG_ON(!desc->n_linear_ranges); | |
d295f767 AL |
610 | return -EINVAL; |
611 | } | |
612 | ||
6a47b4da MV |
613 | for (i = 0; i < desc->n_linear_ranges; i++) { |
614 | range = &desc->linear_ranges[i]; | |
d295f767 AL |
615 | |
616 | if (!(selector >= range->min_sel && | |
617 | selector <= range->max_sel)) | |
618 | continue; | |
619 | ||
620 | selector -= range->min_sel; | |
621 | ||
622 | return range->min_uV + (range->uV_step * selector); | |
623 | } | |
624 | ||
625 | return -EINVAL; | |
626 | } | |
6a47b4da MV |
627 | EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range); |
628 | ||
629 | /** | |
630 | * regulator_list_voltage_linear_range - List voltages for linear ranges | |
631 | * | |
632 | * @rdev: Regulator device | |
633 | * @selector: Selector to convert into a voltage | |
634 | * | |
635 | * Regulators with a series of simple linear mappings between voltages | |
636 | * and selectors can set linear_ranges in the regulator descriptor and | |
637 | * then use this function as their list_voltage() operation, | |
638 | */ | |
639 | int regulator_list_voltage_linear_range(struct regulator_dev *rdev, | |
640 | unsigned int selector) | |
641 | { | |
642 | return regulator_desc_list_voltage_linear_range(rdev->desc, selector); | |
643 | } | |
d295f767 AL |
644 | EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range); |
645 | ||
646 | /** | |
647 | * regulator_list_voltage_table - List voltages with table based mapping | |
648 | * | |
649 | * @rdev: Regulator device | |
650 | * @selector: Selector to convert into a voltage | |
651 | * | |
652 | * Regulators with table based mapping between voltages and | |
653 | * selectors can set volt_table in the regulator descriptor | |
654 | * and then use this function as their list_voltage() operation. | |
655 | */ | |
656 | int regulator_list_voltage_table(struct regulator_dev *rdev, | |
657 | unsigned int selector) | |
658 | { | |
659 | if (!rdev->desc->volt_table) { | |
660 | BUG_ON(!rdev->desc->volt_table); | |
661 | return -EINVAL; | |
662 | } | |
663 | ||
664 | if (selector >= rdev->desc->n_voltages) | |
665 | return -EINVAL; | |
666 | ||
667 | return rdev->desc->volt_table[selector]; | |
668 | } | |
669 | EXPORT_SYMBOL_GPL(regulator_list_voltage_table); | |
670 | ||
c4a54b8d MB |
671 | /** |
672 | * regulator_set_bypass_regmap - Default set_bypass() using regmap | |
673 | * | |
674 | * @rdev: device to operate on. | |
675 | * @enable: state to set. | |
676 | */ | |
677 | int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable) | |
678 | { | |
679 | unsigned int val; | |
680 | ||
ca5d1b35 CC |
681 | if (enable) { |
682 | val = rdev->desc->bypass_val_on; | |
683 | if (!val) | |
684 | val = rdev->desc->bypass_mask; | |
685 | } else { | |
686 | val = rdev->desc->bypass_val_off; | |
687 | } | |
c4a54b8d MB |
688 | |
689 | return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg, | |
690 | rdev->desc->bypass_mask, val); | |
691 | } | |
692 | EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap); | |
693 | ||
a7a453f5 CK |
694 | /** |
695 | * regulator_set_soft_start_regmap - Default set_soft_start() using regmap | |
696 | * | |
697 | * @rdev: device to operate on. | |
698 | */ | |
699 | int regulator_set_soft_start_regmap(struct regulator_dev *rdev) | |
700 | { | |
701 | unsigned int val; | |
702 | ||
703 | val = rdev->desc->soft_start_val_on; | |
704 | if (!val) | |
705 | val = rdev->desc->soft_start_mask; | |
706 | ||
707 | return regmap_update_bits(rdev->regmap, rdev->desc->soft_start_reg, | |
708 | rdev->desc->soft_start_mask, val); | |
709 | } | |
710 | EXPORT_SYMBOL_GPL(regulator_set_soft_start_regmap); | |
711 | ||
f7d37bc3 CK |
712 | /** |
713 | * regulator_set_pull_down_regmap - Default set_pull_down() using regmap | |
714 | * | |
715 | * @rdev: device to operate on. | |
716 | */ | |
717 | int regulator_set_pull_down_regmap(struct regulator_dev *rdev) | |
718 | { | |
719 | unsigned int val; | |
720 | ||
721 | val = rdev->desc->pull_down_val_on; | |
722 | if (!val) | |
723 | val = rdev->desc->pull_down_mask; | |
724 | ||
725 | return regmap_update_bits(rdev->regmap, rdev->desc->pull_down_reg, | |
726 | rdev->desc->pull_down_mask, val); | |
727 | } | |
728 | EXPORT_SYMBOL_GPL(regulator_set_pull_down_regmap); | |
729 | ||
c4a54b8d MB |
730 | /** |
731 | * regulator_get_bypass_regmap - Default get_bypass() using regmap | |
732 | * | |
733 | * @rdev: device to operate on. | |
734 | * @enable: current state. | |
735 | */ | |
736 | int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable) | |
737 | { | |
738 | unsigned int val; | |
85b03744 | 739 | unsigned int val_on = rdev->desc->bypass_val_on; |
c4a54b8d MB |
740 | int ret; |
741 | ||
742 | ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val); | |
743 | if (ret != 0) | |
744 | return ret; | |
745 | ||
85b03744 CK |
746 | if (!val_on) |
747 | val_on = rdev->desc->bypass_mask; | |
748 | ||
749 | *enable = (val & rdev->desc->bypass_mask) == val_on; | |
c4a54b8d MB |
750 | |
751 | return 0; | |
752 | } | |
753 | EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap); | |
354794da LD |
754 | |
755 | /** | |
756 | * regulator_set_active_discharge_regmap - Default set_active_discharge() | |
757 | * using regmap | |
758 | * | |
759 | * @rdev: device to operate on. | |
760 | * @enable: state to set, 0 to disable and 1 to enable. | |
761 | */ | |
762 | int regulator_set_active_discharge_regmap(struct regulator_dev *rdev, | |
763 | bool enable) | |
764 | { | |
765 | unsigned int val; | |
766 | ||
767 | if (enable) | |
768 | val = rdev->desc->active_discharge_on; | |
769 | else | |
770 | val = rdev->desc->active_discharge_off; | |
771 | ||
772 | return regmap_update_bits(rdev->regmap, | |
773 | rdev->desc->active_discharge_reg, | |
774 | rdev->desc->active_discharge_mask, val); | |
775 | } | |
776 | EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap); | |
a32e0c77 AL |
777 | |
778 | /** | |
779 | * regulator_set_current_limit_regmap - set_current_limit for regmap users | |
780 | * | |
781 | * @rdev: regulator to operate on | |
782 | * @min_uA: Lower bound for current limit | |
783 | * @max_uA: Upper bound for current limit | |
784 | * | |
785 | * Regulators that use regmap for their register I/O can set curr_table, | |
786 | * csel_reg and csel_mask fields in their descriptor and then use this | |
787 | * as their set_current_limit operation, saving some code. | |
788 | */ | |
789 | int regulator_set_current_limit_regmap(struct regulator_dev *rdev, | |
790 | int min_uA, int max_uA) | |
791 | { | |
792 | unsigned int n_currents = rdev->desc->n_current_limits; | |
793 | int i, sel = -1; | |
794 | ||
795 | if (n_currents == 0) | |
796 | return -EINVAL; | |
797 | ||
798 | if (rdev->desc->curr_table) { | |
799 | const unsigned int *curr_table = rdev->desc->curr_table; | |
800 | bool ascend = curr_table[n_currents - 1] > curr_table[0]; | |
801 | ||
802 | /* search for closest to maximum */ | |
803 | if (ascend) { | |
804 | for (i = n_currents - 1; i >= 0; i--) { | |
805 | if (min_uA <= curr_table[i] && | |
806 | curr_table[i] <= max_uA) { | |
807 | sel = i; | |
808 | break; | |
809 | } | |
810 | } | |
811 | } else { | |
812 | for (i = 0; i < n_currents; i++) { | |
813 | if (min_uA <= curr_table[i] && | |
814 | curr_table[i] <= max_uA) { | |
815 | sel = i; | |
816 | break; | |
817 | } | |
818 | } | |
819 | } | |
820 | } | |
821 | ||
822 | if (sel < 0) | |
823 | return -EINVAL; | |
824 | ||
825 | sel <<= ffs(rdev->desc->csel_mask) - 1; | |
826 | ||
827 | return regmap_update_bits(rdev->regmap, rdev->desc->csel_reg, | |
828 | rdev->desc->csel_mask, sel); | |
829 | } | |
830 | EXPORT_SYMBOL_GPL(regulator_set_current_limit_regmap); | |
831 | ||
832 | /** | |
833 | * regulator_get_current_limit_regmap - get_current_limit for regmap users | |
834 | * | |
835 | * @rdev: regulator to operate on | |
836 | * | |
837 | * Regulators that use regmap for their register I/O can set the | |
838 | * csel_reg and csel_mask fields in their descriptor and then use this | |
839 | * as their get_current_limit operation, saving some code. | |
840 | */ | |
841 | int regulator_get_current_limit_regmap(struct regulator_dev *rdev) | |
842 | { | |
843 | unsigned int val; | |
844 | int ret; | |
845 | ||
846 | ret = regmap_read(rdev->regmap, rdev->desc->csel_reg, &val); | |
847 | if (ret != 0) | |
848 | return ret; | |
849 | ||
850 | val &= rdev->desc->csel_mask; | |
851 | val >>= ffs(rdev->desc->csel_mask) - 1; | |
852 | ||
853 | if (rdev->desc->curr_table) { | |
854 | if (val >= rdev->desc->n_current_limits) | |
855 | return -EINVAL; | |
856 | ||
857 | return rdev->desc->curr_table[val]; | |
858 | } | |
859 | ||
860 | return -EINVAL; | |
861 | } | |
862 | EXPORT_SYMBOL_GPL(regulator_get_current_limit_regmap); | |
d0087e72 BG |
863 | |
864 | /** | |
865 | * regulator_bulk_set_supply_names - initialize the 'supply' fields in an array | |
866 | * of regulator_bulk_data structs | |
867 | * | |
868 | * @consumers: array of regulator_bulk_data entries to initialize | |
869 | * @supply_names: array of supply name strings | |
870 | * @num_supplies: number of supply names to initialize | |
871 | * | |
872 | * Note: the 'consumers' array must be the size of 'num_supplies'. | |
873 | */ | |
874 | void regulator_bulk_set_supply_names(struct regulator_bulk_data *consumers, | |
875 | const char *const *supply_names, | |
876 | unsigned int num_supplies) | |
877 | { | |
878 | unsigned int i; | |
879 | ||
880 | for (i = 0; i < num_supplies; i++) | |
881 | consumers[i].supply = supply_names[i]; | |
882 | } | |
883 | EXPORT_SYMBOL_GPL(regulator_bulk_set_supply_names); |