Commit eca2a654b8e9b45680f75f77b716b483f1ecffce
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
Merge remote-tracking branch 'regulator/topic/linear-range' into regulator-helpers
Showing 6 changed files Side-by-side Diff
drivers/regulator/core.c
... | ... | @@ -2084,6 +2084,43 @@ |
2084 | 2084 | EXPORT_SYMBOL_GPL(regulator_list_voltage_linear); |
2085 | 2085 | |
2086 | 2086 | /** |
2087 | + * regulator_list_voltage_linear_range - List voltages for linear ranges | |
2088 | + * | |
2089 | + * @rdev: Regulator device | |
2090 | + * @selector: Selector to convert into a voltage | |
2091 | + * | |
2092 | + * Regulators with a series of simple linear mappings between voltages | |
2093 | + * and selectors can set linear_ranges in the regulator descriptor and | |
2094 | + * then use this function as their list_voltage() operation, | |
2095 | + */ | |
2096 | +int regulator_list_voltage_linear_range(struct regulator_dev *rdev, | |
2097 | + unsigned int selector) | |
2098 | +{ | |
2099 | + const struct regulator_linear_range *range; | |
2100 | + int i; | |
2101 | + | |
2102 | + if (!rdev->desc->n_linear_ranges) { | |
2103 | + BUG_ON(!rdev->desc->n_linear_ranges); | |
2104 | + return -EINVAL; | |
2105 | + } | |
2106 | + | |
2107 | + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { | |
2108 | + range = &rdev->desc->linear_ranges[i]; | |
2109 | + | |
2110 | + if (!(selector >= range->min_sel && | |
2111 | + selector <= range->max_sel)) | |
2112 | + continue; | |
2113 | + | |
2114 | + selector -= range->min_sel; | |
2115 | + | |
2116 | + return range->min_uV + (range->uV_step * selector); | |
2117 | + } | |
2118 | + | |
2119 | + return -EINVAL; | |
2120 | +} | |
2121 | +EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range); | |
2122 | + | |
2123 | +/** | |
2087 | 2124 | * regulator_list_voltage_table - List voltages with table based mapping |
2088 | 2125 | * |
2089 | 2126 | * @rdev: Regulator device |
... | ... | @@ -2372,6 +2409,64 @@ |
2372 | 2409 | return ret; |
2373 | 2410 | } |
2374 | 2411 | EXPORT_SYMBOL_GPL(regulator_map_voltage_linear); |
2412 | + | |
2413 | +/** | |
2414 | + * regulator_map_voltage_linear - map_voltage() for multiple linear ranges | |
2415 | + * | |
2416 | + * @rdev: Regulator to operate on | |
2417 | + * @min_uV: Lower bound for voltage | |
2418 | + * @max_uV: Upper bound for voltage | |
2419 | + * | |
2420 | + * Drivers providing linear_ranges in their descriptor can use this as | |
2421 | + * their map_voltage() callback. | |
2422 | + */ | |
2423 | +int regulator_map_voltage_linear_range(struct regulator_dev *rdev, | |
2424 | + int min_uV, int max_uV) | |
2425 | +{ | |
2426 | + const struct regulator_linear_range *range; | |
2427 | + int ret = -EINVAL; | |
2428 | + int voltage, i; | |
2429 | + | |
2430 | + if (!rdev->desc->n_linear_ranges) { | |
2431 | + BUG_ON(!rdev->desc->n_linear_ranges); | |
2432 | + return -EINVAL; | |
2433 | + } | |
2434 | + | |
2435 | + for (i = 0; i < rdev->desc->n_linear_ranges; i++) { | |
2436 | + range = &rdev->desc->linear_ranges[i]; | |
2437 | + | |
2438 | + if (!(min_uV <= range->max_uV && max_uV >= range->min_uV)) | |
2439 | + continue; | |
2440 | + | |
2441 | + if (min_uV <= range->min_uV) | |
2442 | + min_uV = range->min_uV; | |
2443 | + | |
2444 | + /* range->uV_step == 0 means fixed voltage range */ | |
2445 | + if (range->uV_step == 0) { | |
2446 | + ret = 0; | |
2447 | + } else { | |
2448 | + ret = DIV_ROUND_UP(min_uV - range->min_uV, | |
2449 | + range->uV_step); | |
2450 | + if (ret < 0) | |
2451 | + return ret; | |
2452 | + } | |
2453 | + | |
2454 | + ret += range->min_sel; | |
2455 | + | |
2456 | + break; | |
2457 | + } | |
2458 | + | |
2459 | + if (i == rdev->desc->n_linear_ranges) | |
2460 | + return -EINVAL; | |
2461 | + | |
2462 | + /* Map back into a voltage to verify we're still in bounds */ | |
2463 | + voltage = rdev->desc->ops->list_voltage(rdev, ret); | |
2464 | + if (voltage < min_uV || voltage > max_uV) | |
2465 | + return -EINVAL; | |
2466 | + | |
2467 | + return ret; | |
2468 | +} | |
2469 | +EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range); | |
2375 | 2470 | |
2376 | 2471 | static int _regulator_do_set_voltage(struct regulator_dev *rdev, |
2377 | 2472 | int min_uV, int max_uV) |
drivers/regulator/da903x.c
... | ... | @@ -252,40 +252,13 @@ |
252 | 252 | return ret; |
253 | 253 | } |
254 | 254 | |
255 | -static int da9034_map_ldo12_voltage(struct regulator_dev *rdev, | |
256 | - int min_uV, int max_uV) | |
257 | -{ | |
258 | - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); | |
259 | - int sel; | |
255 | +static const struct regulator_linear_range da9034_ldo12_ranges[] = { | |
256 | + { .min_uV = 1700000, .max_uV = 2050000, .min_sel = 0, .max_sel = 7, | |
257 | + .uV_step = 50000 }, | |
258 | + { .min_uV = 2700000, .max_uV = 3050000, .min_sel = 8, .max_sel = 15, | |
259 | + .uV_step = 50000 }, | |
260 | +}; | |
260 | 261 | |
261 | - if (check_range(info, min_uV, max_uV)) { | |
262 | - pr_err("invalid voltage range (%d, %d) uV\n", min_uV, max_uV); | |
263 | - return -EINVAL; | |
264 | - } | |
265 | - | |
266 | - sel = DIV_ROUND_UP(min_uV - info->desc.min_uV, info->desc.uV_step); | |
267 | - sel = (sel >= 20) ? sel - 12 : ((sel > 7) ? 8 : sel); | |
268 | - | |
269 | - return sel; | |
270 | -} | |
271 | - | |
272 | -static int da9034_list_ldo12_voltage(struct regulator_dev *rdev, | |
273 | - unsigned selector) | |
274 | -{ | |
275 | - struct da903x_regulator_info *info = rdev_get_drvdata(rdev); | |
276 | - int volt; | |
277 | - | |
278 | - if (selector >= 8) | |
279 | - volt = 2700000 + rdev->desc->uV_step * (selector - 8); | |
280 | - else | |
281 | - volt = rdev->desc->min_uV + rdev->desc->uV_step * selector; | |
282 | - | |
283 | - if (volt > info->max_uV) | |
284 | - return -EINVAL; | |
285 | - | |
286 | - return volt; | |
287 | -} | |
288 | - | |
289 | 262 | static struct regulator_ops da903x_regulator_ldo_ops = { |
290 | 263 | .set_voltage_sel = da903x_set_voltage_sel, |
291 | 264 | .get_voltage_sel = da903x_get_voltage_sel, |
... | ... | @@ -332,8 +305,8 @@ |
332 | 305 | static struct regulator_ops da9034_regulator_ldo12_ops = { |
333 | 306 | .set_voltage_sel = da903x_set_voltage_sel, |
334 | 307 | .get_voltage_sel = da903x_get_voltage_sel, |
335 | - .list_voltage = da9034_list_ldo12_voltage, | |
336 | - .map_voltage = da9034_map_ldo12_voltage, | |
308 | + .list_voltage = regulator_list_voltage_linear_range, | |
309 | + .map_voltage = regulator_map_voltage_linear_range, | |
337 | 310 | .enable = da903x_enable, |
338 | 311 | .disable = da903x_disable, |
339 | 312 | .is_enabled = da903x_is_enabled, |
... | ... | @@ -476,6 +449,8 @@ |
476 | 449 | if (ri->desc.id == DA9034_ID_LDO12) { |
477 | 450 | ri->desc.ops = &da9034_regulator_ldo12_ops; |
478 | 451 | ri->desc.n_voltages = 16; |
452 | + ri->desc.linear_ranges = da9034_ldo12_ranges; | |
453 | + ri->desc.n_linear_ranges = ARRAY_SIZE(da9034_ldo12_ranges); | |
479 | 454 | } |
480 | 455 | |
481 | 456 | if (ri->desc.id == DA9030_ID_LDO14) |
drivers/regulator/wm831x-ldo.c
... | ... | @@ -62,42 +62,13 @@ |
62 | 62 | * General purpose LDOs |
63 | 63 | */ |
64 | 64 | |
65 | -#define WM831X_GP_LDO_SELECTOR_LOW 0xe | |
66 | -#define WM831X_GP_LDO_MAX_SELECTOR 0x1f | |
65 | +static const struct regulator_linear_range wm831x_gp_ldo_ranges[] = { | |
66 | + { .min_uV = 900000, .max_uV = 1650000, .min_sel = 0, .max_sel = 14, | |
67 | + .uV_step = 50000 }, | |
68 | + { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31, | |
69 | + .uV_step = 100000 }, | |
70 | +}; | |
67 | 71 | |
68 | -static int wm831x_gp_ldo_list_voltage(struct regulator_dev *rdev, | |
69 | - unsigned int selector) | |
70 | -{ | |
71 | - /* 0.9-1.6V in 50mV steps */ | |
72 | - if (selector <= WM831X_GP_LDO_SELECTOR_LOW) | |
73 | - return 900000 + (selector * 50000); | |
74 | - /* 1.7-3.3V in 100mV steps */ | |
75 | - if (selector <= WM831X_GP_LDO_MAX_SELECTOR) | |
76 | - return 1600000 + ((selector - WM831X_GP_LDO_SELECTOR_LOW) | |
77 | - * 100000); | |
78 | - return -EINVAL; | |
79 | -} | |
80 | - | |
81 | -static int wm831x_gp_ldo_map_voltage(struct regulator_dev *rdev, | |
82 | - int min_uV, int max_uV) | |
83 | -{ | |
84 | - int volt, vsel; | |
85 | - | |
86 | - if (min_uV < 900000) | |
87 | - vsel = 0; | |
88 | - else if (min_uV < 1700000) | |
89 | - vsel = ((min_uV - 900000) / 50000); | |
90 | - else | |
91 | - vsel = ((min_uV - 1700000) / 100000) | |
92 | - + WM831X_GP_LDO_SELECTOR_LOW + 1; | |
93 | - | |
94 | - volt = wm831x_gp_ldo_list_voltage(rdev, vsel); | |
95 | - if (volt < min_uV || volt > max_uV) | |
96 | - return -EINVAL; | |
97 | - | |
98 | - return vsel; | |
99 | -} | |
100 | - | |
101 | 72 | static int wm831x_gp_ldo_set_suspend_voltage(struct regulator_dev *rdev, |
102 | 73 | int uV) |
103 | 74 | { |
... | ... | @@ -105,7 +76,7 @@ |
105 | 76 | struct wm831x *wm831x = ldo->wm831x; |
106 | 77 | int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; |
107 | 78 | |
108 | - sel = wm831x_gp_ldo_map_voltage(rdev, uV, uV); | |
79 | + sel = regulator_map_voltage_linear_range(rdev, uV, uV); | |
109 | 80 | if (sel < 0) |
110 | 81 | return sel; |
111 | 82 | |
... | ... | @@ -230,8 +201,8 @@ |
230 | 201 | |
231 | 202 | |
232 | 203 | static struct regulator_ops wm831x_gp_ldo_ops = { |
233 | - .list_voltage = wm831x_gp_ldo_list_voltage, | |
234 | - .map_voltage = wm831x_gp_ldo_map_voltage, | |
204 | + .list_voltage = regulator_list_voltage_linear_range, | |
205 | + .map_voltage = regulator_map_voltage_linear_range, | |
235 | 206 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
236 | 207 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
237 | 208 | .set_suspend_voltage = wm831x_gp_ldo_set_suspend_voltage, |
... | ... | @@ -290,7 +261,7 @@ |
290 | 261 | |
291 | 262 | ldo->desc.id = id; |
292 | 263 | ldo->desc.type = REGULATOR_VOLTAGE; |
293 | - ldo->desc.n_voltages = WM831X_GP_LDO_MAX_SELECTOR + 1; | |
264 | + ldo->desc.n_voltages = 32; | |
294 | 265 | ldo->desc.ops = &wm831x_gp_ldo_ops; |
295 | 266 | ldo->desc.owner = THIS_MODULE; |
296 | 267 | ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
... | ... | @@ -299,6 +270,8 @@ |
299 | 270 | ldo->desc.enable_mask = 1 << id; |
300 | 271 | ldo->desc.bypass_reg = ldo->base; |
301 | 272 | ldo->desc.bypass_mask = WM831X_LDO1_SWI; |
273 | + ldo->desc.linear_ranges = wm831x_gp_ldo_ranges; | |
274 | + ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_gp_ldo_ranges); | |
302 | 275 | |
303 | 276 | config.dev = pdev->dev.parent; |
304 | 277 | if (pdata) |
305 | 278 | |
... | ... | @@ -358,44 +331,13 @@ |
358 | 331 | * Analogue LDOs |
359 | 332 | */ |
360 | 333 | |
334 | +static const struct regulator_linear_range wm831x_aldo_ranges[] = { | |
335 | + { .min_uV = 1000000, .max_uV = 1650000, .min_sel = 0, .max_sel = 12, | |
336 | + .uV_step = 50000 }, | |
337 | + { .min_uV = 1700000, .max_uV = 3500000, .min_sel = 13, .max_sel = 31, | |
338 | + .uV_step = 100000 }, | |
339 | +}; | |
361 | 340 | |
362 | -#define WM831X_ALDO_SELECTOR_LOW 0xc | |
363 | -#define WM831X_ALDO_MAX_SELECTOR 0x1f | |
364 | - | |
365 | -static int wm831x_aldo_list_voltage(struct regulator_dev *rdev, | |
366 | - unsigned int selector) | |
367 | -{ | |
368 | - /* 1-1.6V in 50mV steps */ | |
369 | - if (selector <= WM831X_ALDO_SELECTOR_LOW) | |
370 | - return 1000000 + (selector * 50000); | |
371 | - /* 1.7-3.5V in 100mV steps */ | |
372 | - if (selector <= WM831X_ALDO_MAX_SELECTOR) | |
373 | - return 1600000 + ((selector - WM831X_ALDO_SELECTOR_LOW) | |
374 | - * 100000); | |
375 | - return -EINVAL; | |
376 | -} | |
377 | - | |
378 | -static int wm831x_aldo_map_voltage(struct regulator_dev *rdev, | |
379 | - int min_uV, int max_uV) | |
380 | -{ | |
381 | - int volt, vsel; | |
382 | - | |
383 | - if (min_uV < 1000000) | |
384 | - vsel = 0; | |
385 | - else if (min_uV < 1700000) | |
386 | - vsel = ((min_uV - 1000000) / 50000); | |
387 | - else | |
388 | - vsel = ((min_uV - 1700000) / 100000) | |
389 | - + WM831X_ALDO_SELECTOR_LOW + 1; | |
390 | - | |
391 | - volt = wm831x_aldo_list_voltage(rdev, vsel); | |
392 | - if (volt < min_uV || volt > max_uV) | |
393 | - return -EINVAL; | |
394 | - | |
395 | - return vsel; | |
396 | - | |
397 | -} | |
398 | - | |
399 | 341 | static int wm831x_aldo_set_suspend_voltage(struct regulator_dev *rdev, |
400 | 342 | int uV) |
401 | 343 | { |
... | ... | @@ -403,7 +345,7 @@ |
403 | 345 | struct wm831x *wm831x = ldo->wm831x; |
404 | 346 | int sel, reg = ldo->base + WM831X_LDO_SLEEP_CONTROL; |
405 | 347 | |
406 | - sel = wm831x_aldo_map_voltage(rdev, uV, uV); | |
348 | + sel = regulator_map_voltage_linear_range(rdev, uV, uV); | |
407 | 349 | if (sel < 0) |
408 | 350 | return sel; |
409 | 351 | |
... | ... | @@ -486,8 +428,8 @@ |
486 | 428 | } |
487 | 429 | |
488 | 430 | static struct regulator_ops wm831x_aldo_ops = { |
489 | - .list_voltage = wm831x_aldo_list_voltage, | |
490 | - .map_voltage = wm831x_aldo_map_voltage, | |
431 | + .list_voltage = regulator_list_voltage_linear_range, | |
432 | + .map_voltage = regulator_map_voltage_linear_range, | |
491 | 433 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
492 | 434 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
493 | 435 | .set_suspend_voltage = wm831x_aldo_set_suspend_voltage, |
... | ... | @@ -545,7 +487,9 @@ |
545 | 487 | |
546 | 488 | ldo->desc.id = id; |
547 | 489 | ldo->desc.type = REGULATOR_VOLTAGE; |
548 | - ldo->desc.n_voltages = WM831X_ALDO_MAX_SELECTOR + 1; | |
490 | + ldo->desc.n_voltages = 32; | |
491 | + ldo->desc.linear_ranges = wm831x_aldo_ranges; | |
492 | + ldo->desc.n_linear_ranges = ARRAY_SIZE(wm831x_aldo_ranges); | |
549 | 493 | ldo->desc.ops = &wm831x_aldo_ops; |
550 | 494 | ldo->desc.owner = THIS_MODULE; |
551 | 495 | ldo->desc.vsel_reg = ldo->base + WM831X_LDO_ON_CONTROL; |
drivers/regulator/wm8350-regulator.c
... | ... | @@ -542,42 +542,13 @@ |
542 | 542 | return 0; |
543 | 543 | } |
544 | 544 | |
545 | -static int wm8350_ldo_list_voltage(struct regulator_dev *rdev, | |
546 | - unsigned selector) | |
547 | -{ | |
548 | - if (selector > WM8350_LDO1_VSEL_MASK) | |
549 | - return -EINVAL; | |
545 | +static const struct regulator_linear_range wm8350_ldo_ranges[] = { | |
546 | + { .min_uV = 900000, .max_uV = 1750000, .min_sel = 0, .max_sel = 15, | |
547 | + .uV_step = 50000 }, | |
548 | + { .min_uV = 1800000, .max_uV = 3300000, .min_sel = 16, .max_sel = 31, | |
549 | + .uV_step = 100000 }, | |
550 | +}; | |
550 | 551 | |
551 | - if (selector < 16) | |
552 | - return (selector * 50000) + 900000; | |
553 | - else | |
554 | - return ((selector - 16) * 100000) + 1800000; | |
555 | -} | |
556 | - | |
557 | -static int wm8350_ldo_map_voltage(struct regulator_dev *rdev, int min_uV, | |
558 | - int max_uV) | |
559 | -{ | |
560 | - int volt, sel; | |
561 | - int min_mV = min_uV / 1000; | |
562 | - int max_mV = max_uV / 1000; | |
563 | - | |
564 | - if (min_mV < 900 || min_mV > 3300) | |
565 | - return -EINVAL; | |
566 | - if (max_mV < 900 || max_mV > 3300) | |
567 | - return -EINVAL; | |
568 | - | |
569 | - if (min_mV < 1800) /* step size is 50mV < 1800mV */ | |
570 | - sel = DIV_ROUND_UP(min_uV - 900, 50); | |
571 | - else /* step size is 100mV > 1800mV */ | |
572 | - sel = DIV_ROUND_UP(min_uV - 1800, 100) + 16; | |
573 | - | |
574 | - volt = wm8350_ldo_list_voltage(rdev, sel); | |
575 | - if (volt < min_uV || volt > max_uV) | |
576 | - return -EINVAL; | |
577 | - | |
578 | - return sel; | |
579 | -} | |
580 | - | |
581 | 552 | static int wm8350_ldo_set_suspend_voltage(struct regulator_dev *rdev, int uV) |
582 | 553 | { |
583 | 554 | struct wm8350 *wm8350 = rdev_get_drvdata(rdev); |
... | ... | @@ -603,7 +574,7 @@ |
603 | 574 | return -EINVAL; |
604 | 575 | } |
605 | 576 | |
606 | - sel = wm8350_ldo_map_voltage(rdev, uV, uV); | |
577 | + sel = regulator_map_voltage_linear_range(rdev, uV, uV); | |
607 | 578 | if (sel < 0) |
608 | 579 | return -EINVAL; |
609 | 580 | |
610 | 581 | |
... | ... | @@ -998,10 +969,10 @@ |
998 | 969 | }; |
999 | 970 | |
1000 | 971 | static struct regulator_ops wm8350_ldo_ops = { |
1001 | - .map_voltage = wm8350_ldo_map_voltage, | |
972 | + .map_voltage = regulator_map_voltage_linear_range, | |
1002 | 973 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
1003 | 974 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
1004 | - .list_voltage = wm8350_ldo_list_voltage, | |
975 | + .list_voltage = regulator_list_voltage_linear_range, | |
1005 | 976 | .enable = regulator_enable_regmap, |
1006 | 977 | .disable = regulator_disable_regmap, |
1007 | 978 | .is_enabled = regulator_is_enabled_regmap, |
... | ... | @@ -1108,6 +1079,8 @@ |
1108 | 1079 | .irq = WM8350_IRQ_UV_LDO1, |
1109 | 1080 | .type = REGULATOR_VOLTAGE, |
1110 | 1081 | .n_voltages = WM8350_LDO1_VSEL_MASK + 1, |
1082 | + .linear_ranges = wm8350_ldo_ranges, | |
1083 | + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), | |
1111 | 1084 | .vsel_reg = WM8350_LDO1_CONTROL, |
1112 | 1085 | .vsel_mask = WM8350_LDO1_VSEL_MASK, |
1113 | 1086 | .enable_reg = WM8350_DCDC_LDO_REQUESTED, |
... | ... | @@ -1121,6 +1094,8 @@ |
1121 | 1094 | .irq = WM8350_IRQ_UV_LDO2, |
1122 | 1095 | .type = REGULATOR_VOLTAGE, |
1123 | 1096 | .n_voltages = WM8350_LDO2_VSEL_MASK + 1, |
1097 | + .linear_ranges = wm8350_ldo_ranges, | |
1098 | + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), | |
1124 | 1099 | .vsel_reg = WM8350_LDO2_CONTROL, |
1125 | 1100 | .vsel_mask = WM8350_LDO2_VSEL_MASK, |
1126 | 1101 | .enable_reg = WM8350_DCDC_LDO_REQUESTED, |
... | ... | @@ -1134,6 +1109,8 @@ |
1134 | 1109 | .irq = WM8350_IRQ_UV_LDO3, |
1135 | 1110 | .type = REGULATOR_VOLTAGE, |
1136 | 1111 | .n_voltages = WM8350_LDO3_VSEL_MASK + 1, |
1112 | + .linear_ranges = wm8350_ldo_ranges, | |
1113 | + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), | |
1137 | 1114 | .vsel_reg = WM8350_LDO3_CONTROL, |
1138 | 1115 | .vsel_mask = WM8350_LDO3_VSEL_MASK, |
1139 | 1116 | .enable_reg = WM8350_DCDC_LDO_REQUESTED, |
... | ... | @@ -1147,6 +1124,8 @@ |
1147 | 1124 | .irq = WM8350_IRQ_UV_LDO4, |
1148 | 1125 | .type = REGULATOR_VOLTAGE, |
1149 | 1126 | .n_voltages = WM8350_LDO4_VSEL_MASK + 1, |
1127 | + .linear_ranges = wm8350_ldo_ranges, | |
1128 | + .n_linear_ranges = ARRAY_SIZE(wm8350_ldo_ranges), | |
1150 | 1129 | .vsel_reg = WM8350_LDO4_CONTROL, |
1151 | 1130 | .vsel_mask = WM8350_LDO4_VSEL_MASK, |
1152 | 1131 | .enable_reg = WM8350_DCDC_LDO_REQUESTED, |
drivers/regulator/wm8400-regulator.c
... | ... | @@ -19,47 +19,21 @@ |
19 | 19 | #include <linux/regulator/driver.h> |
20 | 20 | #include <linux/mfd/wm8400-private.h> |
21 | 21 | |
22 | -static int wm8400_ldo_list_voltage(struct regulator_dev *dev, | |
23 | - unsigned selector) | |
24 | -{ | |
25 | - if (selector > WM8400_LDO1_VSEL_MASK) | |
26 | - return -EINVAL; | |
22 | +static const struct regulator_linear_range wm8400_ldo_ranges[] = { | |
23 | + { .min_uV = 900000, .max_uV = 1600000, .min_sel = 0, .max_sel = 14, | |
24 | + .uV_step = 50000 }, | |
25 | + { .min_uV = 1700000, .max_uV = 3300000, .min_sel = 15, .max_sel = 31, | |
26 | + .uV_step = 100000 }, | |
27 | +}; | |
27 | 28 | |
28 | - if (selector < 15) | |
29 | - return 900000 + (selector * 50000); | |
30 | - else | |
31 | - return 1700000 + ((selector - 15) * 100000); | |
32 | -} | |
33 | - | |
34 | -static int wm8400_ldo_map_voltage(struct regulator_dev *dev, | |
35 | - int min_uV, int max_uV) | |
36 | -{ | |
37 | - u16 val; | |
38 | - int volt; | |
39 | - | |
40 | - if (min_uV < 900000 || min_uV > 3300000) | |
41 | - return -EINVAL; | |
42 | - | |
43 | - if (min_uV < 1700000) /* Steps of 50mV from 900mV; */ | |
44 | - val = DIV_ROUND_UP(min_uV - 900000, 50000); | |
45 | - else /* Steps of 100mV from 1700mV */ | |
46 | - val = DIV_ROUND_UP(min_uV - 1700000, 100000) + 15; | |
47 | - | |
48 | - volt = wm8400_ldo_list_voltage(dev, val); | |
49 | - if (volt < min_uV || volt > max_uV) | |
50 | - return -EINVAL; | |
51 | - | |
52 | - return val; | |
53 | -} | |
54 | - | |
55 | 29 | static struct regulator_ops wm8400_ldo_ops = { |
56 | 30 | .is_enabled = regulator_is_enabled_regmap, |
57 | 31 | .enable = regulator_enable_regmap, |
58 | 32 | .disable = regulator_disable_regmap, |
59 | - .list_voltage = wm8400_ldo_list_voltage, | |
33 | + .list_voltage = regulator_list_voltage_linear_range, | |
60 | 34 | .get_voltage_sel = regulator_get_voltage_sel_regmap, |
61 | 35 | .set_voltage_sel = regulator_set_voltage_sel_regmap, |
62 | - .map_voltage = wm8400_ldo_map_voltage, | |
36 | + .map_voltage = regulator_map_voltage_linear_range, | |
63 | 37 | }; |
64 | 38 | |
65 | 39 | static unsigned int wm8400_dcdc_get_mode(struct regulator_dev *dev) |
... | ... | @@ -155,6 +129,8 @@ |
155 | 129 | .enable_reg = WM8400_LDO1_CONTROL, |
156 | 130 | .enable_mask = WM8400_LDO1_ENA, |
157 | 131 | .n_voltages = WM8400_LDO1_VSEL_MASK + 1, |
132 | + .linear_ranges = wm8400_ldo_ranges, | |
133 | + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), | |
158 | 134 | .vsel_reg = WM8400_LDO1_CONTROL, |
159 | 135 | .vsel_mask = WM8400_LDO1_VSEL_MASK, |
160 | 136 | .type = REGULATOR_VOLTAGE, |
... | ... | @@ -167,6 +143,8 @@ |
167 | 143 | .enable_reg = WM8400_LDO2_CONTROL, |
168 | 144 | .enable_mask = WM8400_LDO2_ENA, |
169 | 145 | .n_voltages = WM8400_LDO2_VSEL_MASK + 1, |
146 | + .linear_ranges = wm8400_ldo_ranges, | |
147 | + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), | |
170 | 148 | .type = REGULATOR_VOLTAGE, |
171 | 149 | .vsel_reg = WM8400_LDO2_CONTROL, |
172 | 150 | .vsel_mask = WM8400_LDO2_VSEL_MASK, |
... | ... | @@ -179,6 +157,8 @@ |
179 | 157 | .enable_reg = WM8400_LDO3_CONTROL, |
180 | 158 | .enable_mask = WM8400_LDO3_ENA, |
181 | 159 | .n_voltages = WM8400_LDO3_VSEL_MASK + 1, |
160 | + .linear_ranges = wm8400_ldo_ranges, | |
161 | + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), | |
182 | 162 | .vsel_reg = WM8400_LDO3_CONTROL, |
183 | 163 | .vsel_mask = WM8400_LDO3_VSEL_MASK, |
184 | 164 | .type = REGULATOR_VOLTAGE, |
... | ... | @@ -191,6 +171,8 @@ |
191 | 171 | .enable_reg = WM8400_LDO4_CONTROL, |
192 | 172 | .enable_mask = WM8400_LDO4_ENA, |
193 | 173 | .n_voltages = WM8400_LDO4_VSEL_MASK + 1, |
174 | + .linear_ranges = wm8400_ldo_ranges, | |
175 | + .n_linear_ranges = ARRAY_SIZE(wm8400_ldo_ranges), | |
194 | 176 | .vsel_reg = WM8400_LDO4_CONTROL, |
195 | 177 | .vsel_mask = WM8400_LDO4_VSEL_MASK, |
196 | 178 | .type = REGULATOR_VOLTAGE, |
include/linux/regulator/driver.h
... | ... | @@ -40,6 +40,24 @@ |
40 | 40 | }; |
41 | 41 | |
42 | 42 | /** |
43 | + * Specify a range of voltages for regulator_map_linar_range() and | |
44 | + * regulator_list_linear_range(). | |
45 | + * | |
46 | + * @min_uV: Lowest voltage in range | |
47 | + * @max_uV: Highest voltage in range | |
48 | + * @min_sel: Lowest selector for range | |
49 | + * @max_sel: Highest selector for range | |
50 | + * @uV_step: Step size | |
51 | + */ | |
52 | +struct regulator_linear_range { | |
53 | + unsigned int min_uV; | |
54 | + unsigned int max_uV; | |
55 | + unsigned int min_sel; | |
56 | + unsigned int max_sel; | |
57 | + unsigned int uV_step; | |
58 | +}; | |
59 | + | |
60 | +/** | |
43 | 61 | * struct regulator_ops - regulator operations. |
44 | 62 | * |
45 | 63 | * @enable: Configure the regulator as enabled. |
... | ... | @@ -223,6 +241,9 @@ |
223 | 241 | unsigned int linear_min_sel; |
224 | 242 | unsigned int ramp_delay; |
225 | 243 | |
244 | + const struct regulator_linear_range *linear_ranges; | |
245 | + int n_linear_ranges; | |
246 | + | |
226 | 247 | const unsigned int *volt_table; |
227 | 248 | |
228 | 249 | unsigned int vsel_reg; |
229 | 250 | |
... | ... | @@ -326,10 +347,14 @@ |
326 | 347 | |
327 | 348 | int regulator_list_voltage_linear(struct regulator_dev *rdev, |
328 | 349 | unsigned int selector); |
350 | +int regulator_list_voltage_linear_range(struct regulator_dev *rdev, | |
351 | + unsigned int selector); | |
329 | 352 | int regulator_list_voltage_table(struct regulator_dev *rdev, |
330 | 353 | unsigned int selector); |
331 | 354 | int regulator_map_voltage_linear(struct regulator_dev *rdev, |
332 | 355 | int min_uV, int max_uV); |
356 | +int regulator_map_voltage_linear_range(struct regulator_dev *rdev, | |
357 | + int min_uV, int max_uV); | |
333 | 358 | int regulator_map_voltage_iterate(struct regulator_dev *rdev, |
334 | 359 | int min_uV, int max_uV); |
335 | 360 | int regulator_map_voltage_ascend(struct regulator_dev *rdev, |