Branch data Line data Source code
1 : : /*
2 : : * helpers.c -- Voltage/Current Regulator framework helper functions.
3 : : *
4 : : * Copyright 2007, 2008 Wolfson Microelectronics PLC.
5 : : * Copyright 2008 SlimLogic Ltd.
6 : : *
7 : : * This program is free software; you can redistribute it and/or modify it
8 : : * under the terms of the GNU General Public License as published by the
9 : : * Free Software Foundation; either version 2 of the License, or (at your
10 : : * option) any later version.
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 : : * regulator_is_enabled_regmap - standard is_enabled() for regmap users
24 : : *
25 : : * @rdev: regulator to operate on
26 : : *
27 : : * Regulators that use regmap for their register I/O can set the
28 : : * enable_reg and enable_mask fields in their descriptor and then use
29 : : * this as their is_enabled operation, saving some code.
30 : : */
31 : 0 : int 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 : : if (rdev->desc->enable_is_inverted)
41 : : return (val & rdev->desc->enable_mask) == 0;
42 : : else
43 : : return (val & rdev->desc->enable_mask) != 0;
44 : : }
45 : : EXPORT_SYMBOL_GPL(regulator_is_enabled_regmap);
46 : :
47 : : /**
48 : : * regulator_enable_regmap - standard enable() for regmap users
49 : : *
50 : : * @rdev: regulator to operate on
51 : : *
52 : : * Regulators that use regmap for their register I/O can set the
53 : : * enable_reg and enable_mask fields in their descriptor and then use
54 : : * this as their enable() operation, saving some code.
55 : : */
56 : 0 : int regulator_enable_regmap(struct regulator_dev *rdev)
57 : : {
58 : : unsigned int val;
59 : :
60 : : if (rdev->desc->enable_is_inverted)
61 : : val = 0;
62 : : else
63 : : val = rdev->desc->enable_mask;
64 : :
65 : 0 : return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
66 : : rdev->desc->enable_mask, val);
67 : : }
68 : : EXPORT_SYMBOL_GPL(regulator_enable_regmap);
69 : :
70 : : /**
71 : : * regulator_disable_regmap - standard disable() for regmap users
72 : : *
73 : : * @rdev: regulator to operate on
74 : : *
75 : : * Regulators that use regmap for their register I/O can set the
76 : : * enable_reg and enable_mask fields in their descriptor and then use
77 : : * this as their disable() operation, saving some code.
78 : : */
79 : 0 : int regulator_disable_regmap(struct regulator_dev *rdev)
80 : : {
81 : : unsigned int val;
82 : :
83 : : if (rdev->desc->enable_is_inverted)
84 : : val = rdev->desc->enable_mask;
85 : : else
86 : : val = 0;
87 : :
88 : 0 : return regmap_update_bits(rdev->regmap, rdev->desc->enable_reg,
89 : : rdev->desc->enable_mask, val);
90 : : }
91 : : EXPORT_SYMBOL_GPL(regulator_disable_regmap);
92 : :
93 : : /**
94 : : * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
95 : : *
96 : : * @rdev: regulator to operate on
97 : : *
98 : : * Regulators that use regmap for their register I/O can set the
99 : : * vsel_reg and vsel_mask fields in their descriptor and then use this
100 : : * as their get_voltage_vsel operation, saving some code.
101 : : */
102 : 0 : int regulator_get_voltage_sel_regmap(struct regulator_dev *rdev)
103 : : {
104 : : unsigned int val;
105 : : int ret;
106 : :
107 : : ret = regmap_read(rdev->regmap, rdev->desc->vsel_reg, &val);
108 : : if (ret != 0)
109 : : return ret;
110 : :
111 : : val &= rdev->desc->vsel_mask;
112 : : val >>= ffs(rdev->desc->vsel_mask) - 1;
113 : :
114 : : return val;
115 : : }
116 : : EXPORT_SYMBOL_GPL(regulator_get_voltage_sel_regmap);
117 : :
118 : : /**
119 : : * regulator_set_voltage_sel_regmap - standard set_voltage_sel for regmap users
120 : : *
121 : : * @rdev: regulator to operate on
122 : : * @sel: Selector to set
123 : : *
124 : : * Regulators that use regmap for their register I/O can set the
125 : : * vsel_reg and vsel_mask fields in their descriptor and then use this
126 : : * as their set_voltage_vsel operation, saving some code.
127 : : */
128 : 0 : int regulator_set_voltage_sel_regmap(struct regulator_dev *rdev, unsigned sel)
129 : : {
130 : : int ret;
131 : :
132 : 0 : sel <<= ffs(rdev->desc->vsel_mask) - 1;
133 : :
134 : : ret = regmap_update_bits(rdev->regmap, rdev->desc->vsel_reg,
135 : : rdev->desc->vsel_mask, sel);
136 : : if (ret)
137 : : return ret;
138 : :
139 : : if (rdev->desc->apply_bit)
140 : : ret = regmap_update_bits(rdev->regmap, rdev->desc->apply_reg,
141 : : rdev->desc->apply_bit,
142 : : rdev->desc->apply_bit);
143 : : return ret;
144 : : }
145 : : EXPORT_SYMBOL_GPL(regulator_set_voltage_sel_regmap);
146 : :
147 : : /**
148 : : * regulator_map_voltage_iterate - map_voltage() based on list_voltage()
149 : : *
150 : : * @rdev: Regulator to operate on
151 : : * @min_uV: Lower bound for voltage
152 : : * @max_uV: Upper bound for voltage
153 : : *
154 : : * Drivers implementing set_voltage_sel() and list_voltage() can use
155 : : * this as their map_voltage() operation. It will find a suitable
156 : : * voltage by calling list_voltage() until it gets something in bounds
157 : : * for the requested voltages.
158 : : */
159 : 0 : int regulator_map_voltage_iterate(struct regulator_dev *rdev,
160 : : int min_uV, int max_uV)
161 : : {
162 : : int best_val = INT_MAX;
163 : : int selector = 0;
164 : : int i, ret;
165 : :
166 : : /* Find the smallest voltage that falls within the specified
167 : : * range.
168 : : */
169 [ # # ]: 0 : for (i = 0; i < rdev->desc->n_voltages; i++) {
170 : 0 : ret = rdev->desc->ops->list_voltage(rdev, i);
171 [ # # ]: 0 : if (ret < 0)
172 : 0 : continue;
173 : :
174 [ # # ][ # # ]: 0 : if (ret < best_val && ret >= min_uV && ret <= max_uV) {
175 : : best_val = ret;
176 : : selector = i;
177 : : }
178 : : }
179 : :
180 [ # # ]: 0 : if (best_val != INT_MAX)
181 : 0 : return selector;
182 : : else
183 : : return -EINVAL;
184 : : }
185 : : EXPORT_SYMBOL_GPL(regulator_map_voltage_iterate);
186 : :
187 : : /**
188 : : * regulator_map_voltage_ascend - map_voltage() for ascendant voltage list
189 : : *
190 : : * @rdev: Regulator to operate on
191 : : * @min_uV: Lower bound for voltage
192 : : * @max_uV: Upper bound for voltage
193 : : *
194 : : * Drivers that have ascendant voltage list can use this as their
195 : : * map_voltage() operation.
196 : : */
197 : 0 : int regulator_map_voltage_ascend(struct regulator_dev *rdev,
198 : : int min_uV, int max_uV)
199 : : {
200 : : int i, ret;
201 : :
202 [ # # ]: 0 : for (i = 0; i < rdev->desc->n_voltages; i++) {
203 : 0 : ret = rdev->desc->ops->list_voltage(rdev, i);
204 [ # # ]: 0 : if (ret < 0)
205 : 0 : continue;
206 : :
207 [ # # ]: 0 : if (ret > max_uV)
208 : : break;
209 : :
210 [ # # ]: 0 : if (ret >= min_uV && ret <= max_uV)
211 : : return i;
212 : : }
213 : :
214 : : return -EINVAL;
215 : : }
216 : : EXPORT_SYMBOL_GPL(regulator_map_voltage_ascend);
217 : :
218 : : /**
219 : : * regulator_map_voltage_linear - map_voltage() for simple linear mappings
220 : : *
221 : : * @rdev: Regulator to operate on
222 : : * @min_uV: Lower bound for voltage
223 : : * @max_uV: Upper bound for voltage
224 : : *
225 : : * Drivers providing min_uV and uV_step in their regulator_desc can
226 : : * use this as their map_voltage() operation.
227 : : */
228 : 0 : int regulator_map_voltage_linear(struct regulator_dev *rdev,
229 : : int min_uV, int max_uV)
230 : : {
231 : : int ret, voltage;
232 : :
233 : : /* Allow uV_step to be 0 for fixed voltage */
234 [ # # ][ # # ]: 0 : if (rdev->desc->n_voltages == 1 && rdev->desc->uV_step == 0) {
235 [ # # ][ # # ]: 0 : if (min_uV <= rdev->desc->min_uV && rdev->desc->min_uV <= max_uV)
236 : : return 0;
237 : : else
238 : 0 : return -EINVAL;
239 : : }
240 : :
241 [ # # ]: 0 : if (!rdev->desc->uV_step) {
242 [ # # ]: 0 : BUG_ON(!rdev->desc->uV_step);
243 : : return -EINVAL;
244 : : }
245 : :
246 [ # # ]: 0 : if (min_uV < rdev->desc->min_uV)
247 : 0 : min_uV = rdev->desc->min_uV;
248 : :
249 : 0 : ret = DIV_ROUND_UP(min_uV - rdev->desc->min_uV, rdev->desc->uV_step);
250 [ # # ]: 0 : if (ret < 0)
251 : : return ret;
252 : :
253 : 0 : ret += rdev->desc->linear_min_sel;
254 : :
255 : : /* Map back into a voltage to verify we're still in bounds */
256 : 0 : voltage = rdev->desc->ops->list_voltage(rdev, ret);
257 [ # # ]: 0 : if (voltage < min_uV || voltage > max_uV)
258 : : return -EINVAL;
259 : :
260 : 0 : return ret;
261 : : }
262 : : EXPORT_SYMBOL_GPL(regulator_map_voltage_linear);
263 : :
264 : : /**
265 : : * regulator_map_voltage_linear - map_voltage() for multiple linear ranges
266 : : *
267 : : * @rdev: Regulator to operate on
268 : : * @min_uV: Lower bound for voltage
269 : : * @max_uV: Upper bound for voltage
270 : : *
271 : : * Drivers providing linear_ranges in their descriptor can use this as
272 : : * their map_voltage() callback.
273 : : */
274 : 0 : int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
275 : : int min_uV, int max_uV)
276 : : {
277 : : const struct regulator_linear_range *range;
278 : : int ret = -EINVAL;
279 : : int voltage, i;
280 : :
281 [ # # ]: 0 : if (!rdev->desc->n_linear_ranges) {
282 [ # # ]: 0 : BUG_ON(!rdev->desc->n_linear_ranges);
283 : : return -EINVAL;
284 : : }
285 : :
286 [ # # ]: 0 : for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
287 : : int linear_max_uV;
288 : :
289 : 0 : range = &rdev->desc->linear_ranges[i];
290 : 0 : linear_max_uV = range->min_uV +
291 : 0 : (range->max_sel - range->min_sel) * range->uV_step;
292 : :
293 [ # # ][ # # ]: 0 : if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
294 : 0 : continue;
295 : :
296 [ # # ]: 0 : if (min_uV <= range->min_uV)
297 : 0 : min_uV = range->min_uV;
298 : :
299 : : /* range->uV_step == 0 means fixed voltage range */
300 [ # # ]: 0 : if (range->uV_step == 0) {
301 : : ret = 0;
302 : : } else {
303 : 0 : ret = DIV_ROUND_UP(min_uV - range->min_uV,
304 : : range->uV_step);
305 [ # # ]: 0 : if (ret < 0)
306 : : return ret;
307 : : }
308 : :
309 : 0 : ret += range->min_sel;
310 : :
311 : 0 : break;
312 : : }
313 : :
314 [ # # ]: 0 : if (i == rdev->desc->n_linear_ranges)
315 : : return -EINVAL;
316 : :
317 : : /* Map back into a voltage to verify we're still in bounds */
318 : 0 : voltage = rdev->desc->ops->list_voltage(rdev, ret);
319 [ # # ]: 0 : if (voltage < min_uV || voltage > max_uV)
320 : : return -EINVAL;
321 : :
322 : 0 : return ret;
323 : : }
324 : : EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
325 : :
326 : : /**
327 : : * regulator_list_voltage_linear - List voltages with simple calculation
328 : : *
329 : : * @rdev: Regulator device
330 : : * @selector: Selector to convert into a voltage
331 : : *
332 : : * Regulators with a simple linear mapping between voltages and
333 : : * selectors can set min_uV and uV_step in the regulator descriptor
334 : : * and then use this function as their list_voltage() operation,
335 : : */
336 : 0 : int regulator_list_voltage_linear(struct regulator_dev *rdev,
337 : : unsigned int selector)
338 : : {
339 [ # # ]: 0 : if (selector >= rdev->desc->n_voltages)
340 : : return -EINVAL;
341 [ # # ]: 0 : if (selector < rdev->desc->linear_min_sel)
342 : : return 0;
343 : :
344 : 0 : selector -= rdev->desc->linear_min_sel;
345 : :
346 : 0 : return rdev->desc->min_uV + (rdev->desc->uV_step * selector);
347 : : }
348 : : EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
349 : :
350 : : /**
351 : : * regulator_list_voltage_linear_range - List voltages for linear ranges
352 : : *
353 : : * @rdev: Regulator device
354 : : * @selector: Selector to convert into a voltage
355 : : *
356 : : * Regulators with a series of simple linear mappings between voltages
357 : : * and selectors can set linear_ranges in the regulator descriptor and
358 : : * then use this function as their list_voltage() operation,
359 : : */
360 : 0 : int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
361 : : unsigned int selector)
362 : : {
363 : : const struct regulator_linear_range *range;
364 : : int i;
365 : :
366 [ # # ]: 0 : if (!rdev->desc->n_linear_ranges) {
367 [ # # ]: 0 : BUG_ON(!rdev->desc->n_linear_ranges);
368 : : return -EINVAL;
369 : : }
370 : :
371 [ # # ]: 0 : for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
372 : 0 : range = &rdev->desc->linear_ranges[i];
373 : :
374 [ # # ][ # # ]: 0 : if (!(selector >= range->min_sel &&
375 : 0 : selector <= range->max_sel))
376 : 0 : continue;
377 : :
378 : 0 : selector -= range->min_sel;
379 : :
380 : 0 : return range->min_uV + (range->uV_step * selector);
381 : : }
382 : :
383 : : return -EINVAL;
384 : : }
385 : : EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
386 : :
387 : : /**
388 : : * regulator_list_voltage_table - List voltages with table based mapping
389 : : *
390 : : * @rdev: Regulator device
391 : : * @selector: Selector to convert into a voltage
392 : : *
393 : : * Regulators with table based mapping between voltages and
394 : : * selectors can set volt_table in the regulator descriptor
395 : : * and then use this function as their list_voltage() operation.
396 : : */
397 : 0 : int regulator_list_voltage_table(struct regulator_dev *rdev,
398 : : unsigned int selector)
399 : : {
400 [ # # ]: 0 : if (!rdev->desc->volt_table) {
401 [ # # ]: 0 : BUG_ON(!rdev->desc->volt_table);
402 : : return -EINVAL;
403 : : }
404 : :
405 [ # # ]: 0 : if (selector >= rdev->desc->n_voltages)
406 : : return -EINVAL;
407 : :
408 : 0 : return rdev->desc->volt_table[selector];
409 : : }
410 : : EXPORT_SYMBOL_GPL(regulator_list_voltage_table);
411 : :
412 : : /**
413 : : * regulator_set_bypass_regmap - Default set_bypass() using regmap
414 : : *
415 : : * @rdev: device to operate on.
416 : : * @enable: state to set.
417 : : */
418 : 0 : int regulator_set_bypass_regmap(struct regulator_dev *rdev, bool enable)
419 : : {
420 : : unsigned int val;
421 : :
422 : : if (enable)
423 : : val = rdev->desc->bypass_mask;
424 : : else
425 : : val = 0;
426 : :
427 : 0 : return regmap_update_bits(rdev->regmap, rdev->desc->bypass_reg,
428 : : rdev->desc->bypass_mask, val);
429 : : }
430 : : EXPORT_SYMBOL_GPL(regulator_set_bypass_regmap);
431 : :
432 : : /**
433 : : * regulator_get_bypass_regmap - Default get_bypass() using regmap
434 : : *
435 : : * @rdev: device to operate on.
436 : : * @enable: current state.
437 : : */
438 : 0 : int regulator_get_bypass_regmap(struct regulator_dev *rdev, bool *enable)
439 : : {
440 : : unsigned int val;
441 : : int ret;
442 : :
443 : : ret = regmap_read(rdev->regmap, rdev->desc->bypass_reg, &val);
444 : : if (ret != 0)
445 : : return ret;
446 : :
447 : : *enable = val & rdev->desc->bypass_mask;
448 : :
449 : : return 0;
450 : : }
451 : : EXPORT_SYMBOL_GPL(regulator_get_bypass_regmap);
|