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