forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-02-20 ea08eeccae9297f7aabd2ef7f0c2517ac4549acc
kernel/drivers/regulator/helpers.c
....@@ -1,15 +1,9 @@
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
- */
1
+// SPDX-License-Identifier: GPL-2.0-or-later
2
+//
3
+// helpers.c -- Voltage/Current Regulator framework helper functions.
4
+//
5
+// Copyright 2007, 2008 Wolfson Microelectronics PLC.
6
+// Copyright 2008 SlimLogic Ltd.
137
148 #include <linux/kernel.h>
159 #include <linux/err.h>
....@@ -18,6 +12,8 @@
1812 #include <linux/regulator/consumer.h>
1913 #include <linux/regulator/driver.h>
2014 #include <linux/module.h>
15
+
16
+#include "internal.h"
2117
2218 /**
2319 * regulator_is_enabled_regmap - standard is_enabled() for regmap users
....@@ -102,6 +98,130 @@
10298 rdev->desc->enable_mask, val);
10399 }
104100 EXPORT_SYMBOL_GPL(regulator_disable_regmap);
101
+
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;
134
+ int ret;
135
+ unsigned int voltages = 0;
136
+ const struct linear_range *r = rdev->desc->linear_ranges;
137
+
138
+ if (!r)
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
+
156
+ voltages = linear_range_values_in_range_array(r, range);
157
+
158
+ return val + voltages;
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++) {
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
+
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);
105225
106226 /**
107227 * regulator_get_voltage_sel_regmap - standard get_voltage_sel for regmap users
....@@ -287,8 +407,10 @@
287407 int regulator_map_voltage_linear_range(struct regulator_dev *rdev,
288408 int min_uV, int max_uV)
289409 {
290
- const struct regulator_linear_range *range;
410
+ const struct linear_range *range;
291411 int ret = -EINVAL;
412
+ unsigned int sel;
413
+ bool found;
292414 int voltage, i;
293415
294416 if (!rdev->desc->n_linear_ranges) {
....@@ -297,44 +419,94 @@
297419 }
298420
299421 for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
300
- int linear_max_uV;
301
-
302422 range = &rdev->desc->linear_ranges[i];
303
- linear_max_uV = range->min_uV +
304
- (range->max_sel - range->min_sel) * range->uV_step;
305423
306
- if (!(min_uV <= linear_max_uV && max_uV >= range->min_uV))
424
+ ret = linear_range_get_selector_high(range, min_uV, &sel,
425
+ &found);
426
+ if (ret)
307427 continue;
428
+ ret = sel;
308429
309
- if (min_uV <= range->min_uV)
310
- min_uV = range->min_uV;
311
-
312
- /* range->uV_step == 0 means fixed voltage range */
313
- if (range->uV_step == 0) {
314
- ret = 0;
315
- } else {
316
- ret = DIV_ROUND_UP(min_uV - range->min_uV,
317
- range->uV_step);
318
- if (ret < 0)
319
- return ret;
320
- }
321
-
322
- ret += range->min_sel;
323
-
324
- break;
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
+ */
434
+ voltage = rdev->desc->ops->list_voltage(rdev, sel);
435
+ if (voltage >= min_uV && voltage <= max_uV)
436
+ break;
325437 }
326438
327439 if (i == rdev->desc->n_linear_ranges)
328440 return -EINVAL;
329441
330
- /* Map back into a voltage to verify we're still in bounds */
331
- voltage = rdev->desc->ops->list_voltage(rdev, ret);
332
- if (voltage < min_uV || voltage > max_uV)
442
+ return ret;
443
+}
444
+EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
445
+
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
+{
459
+ const struct linear_range *range;
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;
471
+ bool found;
472
+ unsigned int sel;
473
+
474
+ range = &rdev->desc->linear_ranges[i];
475
+ linear_max_uV = linear_range_get_max_value(range);
476
+
477
+ if (!(min_uV <= linear_max_uV && max_uV >= range->min)) {
478
+ selector += linear_range_values_in_range(range);
479
+ continue;
480
+ }
481
+
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;
487
+ }
488
+
489
+ ret = selector + sel - range->min_sel;
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)
499
+ selector += linear_range_values_in_range(range);
500
+ else
501
+ break;
502
+ }
503
+
504
+ if (i == rdev->desc->n_linear_ranges)
333505 return -EINVAL;
334506
335507 return ret;
336508 }
337
-EXPORT_SYMBOL_GPL(regulator_map_voltage_linear_range);
509
+EXPORT_SYMBOL_GPL(regulator_map_voltage_pickable_linear_range);
338510
339511 /**
340512 * regulator_list_voltage_linear - List voltages with simple calculation
....@@ -361,6 +533,86 @@
361533 EXPORT_SYMBOL_GPL(regulator_list_voltage_linear);
362534
363535 /**
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
+{
547
+ const struct linear_range *range;
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++) {
557
+ unsigned int sel_indexes;
558
+
559
+ range = &rdev->desc->linear_ranges[i];
560
+
561
+ sel_indexes = linear_range_values_in_range(range) - 1;
562
+
563
+ if (all_sels + sel_indexes >= selector) {
564
+ selector -= all_sels;
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);
576
+ }
577
+
578
+ all_sels += (sel_indexes + 1);
579
+ }
580
+
581
+ return -EINVAL;
582
+}
583
+EXPORT_SYMBOL_GPL(regulator_list_voltage_pickable_linear_range);
584
+
585
+/**
586
+ * regulator_desc_list_voltage_linear_range - List voltages for linear ranges
587
+ *
588
+ * @desc: Regulator desc for regulator which volatges are to be listed
589
+ * @selector: Selector to convert into a voltage
590
+ *
591
+ * Regulators with a series of simple linear mappings between voltages
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.
596
+ */
597
+int regulator_desc_list_voltage_linear_range(const struct regulator_desc *desc,
598
+ unsigned int selector)
599
+{
600
+ unsigned int val;
601
+ int ret;
602
+
603
+ BUG_ON(!desc->n_linear_ranges);
604
+
605
+ ret = linear_range_get_value_array(desc->linear_ranges,
606
+ desc->n_linear_ranges, selector,
607
+ &val);
608
+ if (ret)
609
+ return ret;
610
+
611
+ return val;
612
+}
613
+EXPORT_SYMBOL_GPL(regulator_desc_list_voltage_linear_range);
614
+
615
+/**
364616 * regulator_list_voltage_linear_range - List voltages for linear ranges
365617 *
366618 * @rdev: Regulator device
....@@ -373,27 +625,7 @@
373625 int regulator_list_voltage_linear_range(struct regulator_dev *rdev,
374626 unsigned int selector)
375627 {
376
- const struct regulator_linear_range *range;
377
- int i;
378
-
379
- if (!rdev->desc->n_linear_ranges) {
380
- BUG_ON(!rdev->desc->n_linear_ranges);
381
- return -EINVAL;
382
- }
383
-
384
- for (i = 0; i < rdev->desc->n_linear_ranges; i++) {
385
- range = &rdev->desc->linear_ranges[i];
386
-
387
- if (!(selector >= range->min_sel &&
388
- selector <= range->max_sel))
389
- continue;
390
-
391
- selector -= range->min_sel;
392
-
393
- return range->min_uV + (range->uV_step * selector);
394
- }
395
-
396
- return -EINVAL;
628
+ return regulator_desc_list_voltage_linear_range(rdev->desc, selector);
397629 }
398630 EXPORT_SYMBOL_GPL(regulator_list_voltage_linear_range);
399631
....@@ -528,3 +760,122 @@
528760 rdev->desc->active_discharge_mask, val);
529761 }
530762 EXPORT_SYMBOL_GPL(regulator_set_active_discharge_regmap);
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);
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);
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);