1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * OF helpers for regulator framework |
4 | * |
5 | * Copyright (C) 2011 Texas Instruments, Inc. |
6 | * Rajendra Nayak <rnayak@ti.com> |
7 | */ |
8 | |
9 | #include <linux/module.h> |
10 | #include <linux/slab.h> |
11 | #include <linux/of.h> |
12 | #include <linux/regulator/machine.h> |
13 | #include <linux/regulator/driver.h> |
14 | #include <linux/regulator/of_regulator.h> |
15 | |
16 | #include "internal.h" |
17 | |
18 | static const char *const regulator_states[PM_SUSPEND_MAX + 1] = { |
19 | [PM_SUSPEND_STANDBY] = "regulator-state-standby" , |
20 | [PM_SUSPEND_MEM] = "regulator-state-mem" , |
21 | [PM_SUSPEND_MAX] = "regulator-state-disk" , |
22 | }; |
23 | |
24 | static void fill_limit(int *limit, int val) |
25 | { |
26 | if (val) |
27 | if (val == 1) |
28 | *limit = REGULATOR_NOTIF_LIMIT_ENABLE; |
29 | else |
30 | *limit = val; |
31 | else |
32 | *limit = REGULATOR_NOTIF_LIMIT_DISABLE; |
33 | } |
34 | |
35 | static void of_get_regulator_prot_limits(struct device_node *np, |
36 | struct regulation_constraints *constraints) |
37 | { |
38 | u32 pval; |
39 | int i; |
40 | static const char *const props[] = { |
41 | "regulator-oc-%s-microamp" , |
42 | "regulator-ov-%s-microvolt" , |
43 | "regulator-temp-%s-kelvin" , |
44 | "regulator-uv-%s-microvolt" , |
45 | }; |
46 | struct notification_limit *limits[] = { |
47 | &constraints->over_curr_limits, |
48 | &constraints->over_voltage_limits, |
49 | &constraints->temp_limits, |
50 | &constraints->under_voltage_limits, |
51 | }; |
52 | bool set[4] = {0}; |
53 | |
54 | /* Protection limits: */ |
55 | for (i = 0; i < ARRAY_SIZE(props); i++) { |
56 | char prop[255]; |
57 | bool found; |
58 | int j; |
59 | static const char *const lvl[] = { |
60 | "protection" , "error" , "warn" |
61 | }; |
62 | int *l[] = { |
63 | &limits[i]->prot, &limits[i]->err, &limits[i]->warn, |
64 | }; |
65 | |
66 | for (j = 0; j < ARRAY_SIZE(lvl); j++) { |
67 | snprintf(buf: prop, size: 255, fmt: props[i], lvl[j]); |
68 | found = !of_property_read_u32(np, propname: prop, out_value: &pval); |
69 | if (found) |
70 | fill_limit(limit: l[j], val: pval); |
71 | set[i] |= found; |
72 | } |
73 | } |
74 | constraints->over_current_detection = set[0]; |
75 | constraints->over_voltage_detection = set[1]; |
76 | constraints->over_temp_detection = set[2]; |
77 | constraints->under_voltage_detection = set[3]; |
78 | } |
79 | |
80 | static int of_get_regulation_constraints(struct device *dev, |
81 | struct device_node *np, |
82 | struct regulator_init_data **init_data, |
83 | const struct regulator_desc *desc) |
84 | { |
85 | struct regulation_constraints *constraints = &(*init_data)->constraints; |
86 | struct regulator_state *suspend_state; |
87 | struct device_node *suspend_np; |
88 | unsigned int mode; |
89 | int ret, i, len; |
90 | int n_phandles; |
91 | u32 pval; |
92 | |
93 | n_phandles = of_count_phandle_with_args(np, list_name: "regulator-coupled-with" , |
94 | NULL); |
95 | n_phandles = max(n_phandles, 0); |
96 | |
97 | constraints->name = of_get_property(node: np, name: "regulator-name" , NULL); |
98 | |
99 | if (!of_property_read_u32(np, propname: "regulator-min-microvolt" , out_value: &pval)) |
100 | constraints->min_uV = pval; |
101 | |
102 | if (!of_property_read_u32(np, propname: "regulator-max-microvolt" , out_value: &pval)) |
103 | constraints->max_uV = pval; |
104 | |
105 | /* Voltage change possible? */ |
106 | if (constraints->min_uV != constraints->max_uV) |
107 | constraints->valid_ops_mask |= REGULATOR_CHANGE_VOLTAGE; |
108 | |
109 | /* Do we have a voltage range, if so try to apply it? */ |
110 | if (constraints->min_uV && constraints->max_uV) |
111 | constraints->apply_uV = true; |
112 | |
113 | if (!of_property_read_u32(np, propname: "regulator-microvolt-offset" , out_value: &pval)) |
114 | constraints->uV_offset = pval; |
115 | if (!of_property_read_u32(np, propname: "regulator-min-microamp" , out_value: &pval)) |
116 | constraints->min_uA = pval; |
117 | if (!of_property_read_u32(np, propname: "regulator-max-microamp" , out_value: &pval)) |
118 | constraints->max_uA = pval; |
119 | |
120 | if (!of_property_read_u32(np, propname: "regulator-input-current-limit-microamp" , |
121 | out_value: &pval)) |
122 | constraints->ilim_uA = pval; |
123 | |
124 | /* Current change possible? */ |
125 | if (constraints->min_uA != constraints->max_uA) |
126 | constraints->valid_ops_mask |= REGULATOR_CHANGE_CURRENT; |
127 | |
128 | constraints->boot_on = of_property_read_bool(np, propname: "regulator-boot-on" ); |
129 | constraints->always_on = of_property_read_bool(np, propname: "regulator-always-on" ); |
130 | if (!constraints->always_on) /* status change should be possible. */ |
131 | constraints->valid_ops_mask |= REGULATOR_CHANGE_STATUS; |
132 | |
133 | constraints->pull_down = of_property_read_bool(np, propname: "regulator-pull-down" ); |
134 | constraints->system_critical = of_property_read_bool(np, |
135 | propname: "system-critical-regulator" ); |
136 | |
137 | if (of_property_read_bool(np, propname: "regulator-allow-bypass" )) |
138 | constraints->valid_ops_mask |= REGULATOR_CHANGE_BYPASS; |
139 | |
140 | if (of_property_read_bool(np, propname: "regulator-allow-set-load" )) |
141 | constraints->valid_ops_mask |= REGULATOR_CHANGE_DRMS; |
142 | |
143 | ret = of_property_read_u32(np, propname: "regulator-ramp-delay" , out_value: &pval); |
144 | if (!ret) { |
145 | if (pval) |
146 | constraints->ramp_delay = pval; |
147 | else |
148 | constraints->ramp_disable = true; |
149 | } |
150 | |
151 | ret = of_property_read_u32(np, propname: "regulator-settling-time-us" , out_value: &pval); |
152 | if (!ret) |
153 | constraints->settling_time = pval; |
154 | |
155 | ret = of_property_read_u32(np, propname: "regulator-settling-time-up-us" , out_value: &pval); |
156 | if (!ret) |
157 | constraints->settling_time_up = pval; |
158 | if (constraints->settling_time_up && constraints->settling_time) { |
159 | pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-up-us'\n" , |
160 | np); |
161 | constraints->settling_time_up = 0; |
162 | } |
163 | |
164 | ret = of_property_read_u32(np, propname: "regulator-settling-time-down-us" , |
165 | out_value: &pval); |
166 | if (!ret) |
167 | constraints->settling_time_down = pval; |
168 | if (constraints->settling_time_down && constraints->settling_time) { |
169 | pr_warn("%pOFn: ambiguous configuration for settling time, ignoring 'regulator-settling-time-down-us'\n" , |
170 | np); |
171 | constraints->settling_time_down = 0; |
172 | } |
173 | |
174 | ret = of_property_read_u32(np, propname: "regulator-enable-ramp-delay" , out_value: &pval); |
175 | if (!ret) |
176 | constraints->enable_time = pval; |
177 | |
178 | ret = of_property_read_u32(np, propname: "regulator-uv-survival-time-ms" , out_value: &pval); |
179 | if (!ret) |
180 | constraints->uv_less_critical_window_ms = pval; |
181 | else |
182 | constraints->uv_less_critical_window_ms = |
183 | REGULATOR_DEF_UV_LESS_CRITICAL_WINDOW_MS; |
184 | |
185 | constraints->soft_start = of_property_read_bool(np, |
186 | propname: "regulator-soft-start" ); |
187 | ret = of_property_read_u32(np, propname: "regulator-active-discharge" , out_value: &pval); |
188 | if (!ret) { |
189 | constraints->active_discharge = |
190 | (pval) ? REGULATOR_ACTIVE_DISCHARGE_ENABLE : |
191 | REGULATOR_ACTIVE_DISCHARGE_DISABLE; |
192 | } |
193 | |
194 | if (!of_property_read_u32(np, propname: "regulator-initial-mode" , out_value: &pval)) { |
195 | if (desc && desc->of_map_mode) { |
196 | mode = desc->of_map_mode(pval); |
197 | if (mode == REGULATOR_MODE_INVALID) |
198 | pr_err("%pOFn: invalid mode %u\n" , np, pval); |
199 | else |
200 | constraints->initial_mode = mode; |
201 | } else { |
202 | pr_warn("%pOFn: mapping for mode %d not defined\n" , |
203 | np, pval); |
204 | } |
205 | } |
206 | |
207 | len = of_property_count_elems_of_size(np, propname: "regulator-allowed-modes" , |
208 | elem_size: sizeof(u32)); |
209 | if (len > 0) { |
210 | if (desc && desc->of_map_mode) { |
211 | for (i = 0; i < len; i++) { |
212 | ret = of_property_read_u32_index(np, |
213 | propname: "regulator-allowed-modes" , index: i, out_value: &pval); |
214 | if (ret) { |
215 | pr_err("%pOFn: couldn't read allowed modes index %d, ret=%d\n" , |
216 | np, i, ret); |
217 | break; |
218 | } |
219 | mode = desc->of_map_mode(pval); |
220 | if (mode == REGULATOR_MODE_INVALID) |
221 | pr_err("%pOFn: invalid regulator-allowed-modes element %u\n" , |
222 | np, pval); |
223 | else |
224 | constraints->valid_modes_mask |= mode; |
225 | } |
226 | if (constraints->valid_modes_mask) |
227 | constraints->valid_ops_mask |
228 | |= REGULATOR_CHANGE_MODE; |
229 | } else { |
230 | pr_warn("%pOFn: mode mapping not defined\n" , np); |
231 | } |
232 | } |
233 | |
234 | if (!of_property_read_u32(np, propname: "regulator-system-load" , out_value: &pval)) |
235 | constraints->system_load = pval; |
236 | |
237 | if (n_phandles) { |
238 | constraints->max_spread = devm_kzalloc(dev, |
239 | size: sizeof(*constraints->max_spread) * n_phandles, |
240 | GFP_KERNEL); |
241 | |
242 | if (!constraints->max_spread) |
243 | return -ENOMEM; |
244 | |
245 | of_property_read_u32_array(np, propname: "regulator-coupled-max-spread" , |
246 | out_values: constraints->max_spread, sz: n_phandles); |
247 | } |
248 | |
249 | if (!of_property_read_u32(np, propname: "regulator-max-step-microvolt" , |
250 | out_value: &pval)) |
251 | constraints->max_uV_step = pval; |
252 | |
253 | constraints->over_current_protection = of_property_read_bool(np, |
254 | propname: "regulator-over-current-protection" ); |
255 | |
256 | of_get_regulator_prot_limits(np, constraints); |
257 | |
258 | for (i = 0; i < ARRAY_SIZE(regulator_states); i++) { |
259 | switch (i) { |
260 | case PM_SUSPEND_MEM: |
261 | suspend_state = &constraints->state_mem; |
262 | break; |
263 | case PM_SUSPEND_MAX: |
264 | suspend_state = &constraints->state_disk; |
265 | break; |
266 | case PM_SUSPEND_STANDBY: |
267 | suspend_state = &constraints->state_standby; |
268 | break; |
269 | case PM_SUSPEND_ON: |
270 | case PM_SUSPEND_TO_IDLE: |
271 | default: |
272 | continue; |
273 | } |
274 | |
275 | suspend_np = of_get_child_by_name(node: np, name: regulator_states[i]); |
276 | if (!suspend_np) |
277 | continue; |
278 | if (!suspend_state) { |
279 | of_node_put(node: suspend_np); |
280 | continue; |
281 | } |
282 | |
283 | if (!of_property_read_u32(np: suspend_np, propname: "regulator-mode" , |
284 | out_value: &pval)) { |
285 | if (desc && desc->of_map_mode) { |
286 | mode = desc->of_map_mode(pval); |
287 | if (mode == REGULATOR_MODE_INVALID) |
288 | pr_err("%pOFn: invalid mode %u\n" , |
289 | np, pval); |
290 | else |
291 | suspend_state->mode = mode; |
292 | } else { |
293 | pr_warn("%pOFn: mapping for mode %d not defined\n" , |
294 | np, pval); |
295 | } |
296 | } |
297 | |
298 | if (of_property_read_bool(np: suspend_np, |
299 | propname: "regulator-on-in-suspend" )) |
300 | suspend_state->enabled = ENABLE_IN_SUSPEND; |
301 | else if (of_property_read_bool(np: suspend_np, |
302 | propname: "regulator-off-in-suspend" )) |
303 | suspend_state->enabled = DISABLE_IN_SUSPEND; |
304 | |
305 | if (!of_property_read_u32(np: suspend_np, |
306 | propname: "regulator-suspend-min-microvolt" , out_value: &pval)) |
307 | suspend_state->min_uV = pval; |
308 | |
309 | if (!of_property_read_u32(np: suspend_np, |
310 | propname: "regulator-suspend-max-microvolt" , out_value: &pval)) |
311 | suspend_state->max_uV = pval; |
312 | |
313 | if (!of_property_read_u32(np: suspend_np, |
314 | propname: "regulator-suspend-microvolt" , out_value: &pval)) |
315 | suspend_state->uV = pval; |
316 | else /* otherwise use min_uV as default suspend voltage */ |
317 | suspend_state->uV = suspend_state->min_uV; |
318 | |
319 | if (of_property_read_bool(np: suspend_np, |
320 | propname: "regulator-changeable-in-suspend" )) |
321 | suspend_state->changeable = true; |
322 | |
323 | if (i == PM_SUSPEND_MEM) |
324 | constraints->initial_state = PM_SUSPEND_MEM; |
325 | |
326 | of_node_put(node: suspend_np); |
327 | suspend_state = NULL; |
328 | suspend_np = NULL; |
329 | } |
330 | |
331 | return 0; |
332 | } |
333 | |
334 | /** |
335 | * of_get_regulator_init_data - extract regulator_init_data structure info |
336 | * @dev: device requesting for regulator_init_data |
337 | * @node: regulator device node |
338 | * @desc: regulator description |
339 | * |
340 | * Populates regulator_init_data structure by extracting data from device |
341 | * tree node, returns a pointer to the populated structure or NULL if memory |
342 | * alloc fails. |
343 | */ |
344 | struct regulator_init_data *of_get_regulator_init_data(struct device *dev, |
345 | struct device_node *node, |
346 | const struct regulator_desc *desc) |
347 | { |
348 | struct regulator_init_data *init_data; |
349 | |
350 | if (!node) |
351 | return NULL; |
352 | |
353 | init_data = devm_kzalloc(dev, size: sizeof(*init_data), GFP_KERNEL); |
354 | if (!init_data) |
355 | return NULL; /* Out of memory? */ |
356 | |
357 | if (of_get_regulation_constraints(dev, np: node, init_data: &init_data, desc)) |
358 | return NULL; |
359 | |
360 | return init_data; |
361 | } |
362 | EXPORT_SYMBOL_GPL(of_get_regulator_init_data); |
363 | |
364 | struct devm_of_regulator_matches { |
365 | struct of_regulator_match *matches; |
366 | unsigned int num_matches; |
367 | }; |
368 | |
369 | static void devm_of_regulator_put_matches(struct device *dev, void *res) |
370 | { |
371 | struct devm_of_regulator_matches *devm_matches = res; |
372 | int i; |
373 | |
374 | for (i = 0; i < devm_matches->num_matches; i++) |
375 | of_node_put(node: devm_matches->matches[i].of_node); |
376 | } |
377 | |
378 | /** |
379 | * of_regulator_match - extract multiple regulator init data from device tree. |
380 | * @dev: device requesting the data |
381 | * @node: parent device node of the regulators |
382 | * @matches: match table for the regulators |
383 | * @num_matches: number of entries in match table |
384 | * |
385 | * This function uses a match table specified by the regulator driver to |
386 | * parse regulator init data from the device tree. @node is expected to |
387 | * contain a set of child nodes, each providing the init data for one |
388 | * regulator. The data parsed from a child node will be matched to a regulator |
389 | * based on either the deprecated property regulator-compatible if present, |
390 | * or otherwise the child node's name. Note that the match table is modified |
391 | * in place and an additional of_node reference is taken for each matched |
392 | * regulator. |
393 | * |
394 | * Returns the number of matches found or a negative error code on failure. |
395 | */ |
396 | int of_regulator_match(struct device *dev, struct device_node *node, |
397 | struct of_regulator_match *matches, |
398 | unsigned int num_matches) |
399 | { |
400 | unsigned int count = 0; |
401 | unsigned int i; |
402 | const char *name; |
403 | struct device_node *child; |
404 | struct devm_of_regulator_matches *devm_matches; |
405 | |
406 | if (!dev || !node) |
407 | return -EINVAL; |
408 | |
409 | devm_matches = devres_alloc(devm_of_regulator_put_matches, |
410 | sizeof(struct devm_of_regulator_matches), |
411 | GFP_KERNEL); |
412 | if (!devm_matches) |
413 | return -ENOMEM; |
414 | |
415 | devm_matches->matches = matches; |
416 | devm_matches->num_matches = num_matches; |
417 | |
418 | devres_add(dev, res: devm_matches); |
419 | |
420 | for (i = 0; i < num_matches; i++) { |
421 | struct of_regulator_match *match = &matches[i]; |
422 | match->init_data = NULL; |
423 | match->of_node = NULL; |
424 | } |
425 | |
426 | for_each_child_of_node(node, child) { |
427 | name = of_get_property(node: child, |
428 | name: "regulator-compatible" , NULL); |
429 | if (!name) |
430 | name = child->name; |
431 | for (i = 0; i < num_matches; i++) { |
432 | struct of_regulator_match *match = &matches[i]; |
433 | if (match->of_node) |
434 | continue; |
435 | |
436 | if (strcmp(match->name, name)) |
437 | continue; |
438 | |
439 | match->init_data = |
440 | of_get_regulator_init_data(dev, child, |
441 | match->desc); |
442 | if (!match->init_data) { |
443 | dev_err(dev, |
444 | "failed to parse DT for regulator %pOFn\n" , |
445 | child); |
446 | of_node_put(node: child); |
447 | return -EINVAL; |
448 | } |
449 | match->of_node = of_node_get(node: child); |
450 | count++; |
451 | break; |
452 | } |
453 | } |
454 | |
455 | return count; |
456 | } |
457 | EXPORT_SYMBOL_GPL(of_regulator_match); |
458 | |
459 | static struct |
460 | device_node *regulator_of_get_init_node(struct device *dev, |
461 | const struct regulator_desc *desc) |
462 | { |
463 | struct device_node *search, *child; |
464 | const char *name; |
465 | |
466 | if (!dev->of_node || !desc->of_match) |
467 | return NULL; |
468 | |
469 | if (desc->regulators_node) { |
470 | search = of_get_child_by_name(node: dev->of_node, |
471 | name: desc->regulators_node); |
472 | } else { |
473 | search = of_node_get(node: dev->of_node); |
474 | |
475 | if (!strcmp(desc->of_match, search->name)) |
476 | return search; |
477 | } |
478 | |
479 | if (!search) { |
480 | dev_dbg(dev, "Failed to find regulator container node '%s'\n" , |
481 | desc->regulators_node); |
482 | return NULL; |
483 | } |
484 | |
485 | for_each_available_child_of_node(search, child) { |
486 | name = of_get_property(node: child, name: "regulator-compatible" , NULL); |
487 | if (!name) { |
488 | if (!desc->of_match_full_name) |
489 | name = child->name; |
490 | else |
491 | name = child->full_name; |
492 | } |
493 | |
494 | if (!strcmp(desc->of_match, name)) { |
495 | of_node_put(node: search); |
496 | /* |
497 | * 'of_node_get(child)' is already performed by the |
498 | * for_each loop. |
499 | */ |
500 | return child; |
501 | } |
502 | } |
503 | |
504 | of_node_put(node: search); |
505 | |
506 | return NULL; |
507 | } |
508 | |
509 | struct regulator_init_data *regulator_of_get_init_data(struct device *dev, |
510 | const struct regulator_desc *desc, |
511 | struct regulator_config *config, |
512 | struct device_node **node) |
513 | { |
514 | struct device_node *child; |
515 | struct regulator_init_data *init_data = NULL; |
516 | |
517 | child = regulator_of_get_init_node(dev: config->dev, desc); |
518 | if (!child) |
519 | return NULL; |
520 | |
521 | init_data = of_get_regulator_init_data(dev, child, desc); |
522 | if (!init_data) { |
523 | dev_err(dev, "failed to parse DT for regulator %pOFn\n" , child); |
524 | goto error; |
525 | } |
526 | |
527 | if (desc->of_parse_cb) { |
528 | int ret; |
529 | |
530 | ret = desc->of_parse_cb(child, desc, config); |
531 | if (ret) { |
532 | if (ret == -EPROBE_DEFER) { |
533 | of_node_put(node: child); |
534 | return ERR_PTR(error: -EPROBE_DEFER); |
535 | } |
536 | dev_err(dev, |
537 | "driver callback failed to parse DT for regulator %pOFn\n" , |
538 | child); |
539 | goto error; |
540 | } |
541 | } |
542 | |
543 | *node = child; |
544 | |
545 | return init_data; |
546 | |
547 | error: |
548 | of_node_put(node: child); |
549 | |
550 | return NULL; |
551 | } |
552 | |
553 | struct regulator_dev *of_find_regulator_by_node(struct device_node *np) |
554 | { |
555 | struct device *dev; |
556 | |
557 | dev = class_find_device_by_of_node(class: ®ulator_class, np); |
558 | |
559 | return dev ? dev_to_rdev(dev) : NULL; |
560 | } |
561 | |
562 | /* |
563 | * Returns number of regulators coupled with rdev. |
564 | */ |
565 | int of_get_n_coupled(struct regulator_dev *rdev) |
566 | { |
567 | struct device_node *node = rdev->dev.of_node; |
568 | int n_phandles; |
569 | |
570 | n_phandles = of_count_phandle_with_args(np: node, |
571 | list_name: "regulator-coupled-with" , |
572 | NULL); |
573 | |
574 | return (n_phandles > 0) ? n_phandles : 0; |
575 | } |
576 | |
577 | /* Looks for "to_find" device_node in src's "regulator-coupled-with" property */ |
578 | static bool of_coupling_find_node(struct device_node *src, |
579 | struct device_node *to_find, |
580 | int *index) |
581 | { |
582 | int n_phandles, i; |
583 | bool found = false; |
584 | |
585 | n_phandles = of_count_phandle_with_args(np: src, |
586 | list_name: "regulator-coupled-with" , |
587 | NULL); |
588 | |
589 | for (i = 0; i < n_phandles; i++) { |
590 | struct device_node *tmp = of_parse_phandle(np: src, |
591 | phandle_name: "regulator-coupled-with" , index: i); |
592 | |
593 | if (!tmp) |
594 | break; |
595 | |
596 | /* found */ |
597 | if (tmp == to_find) |
598 | found = true; |
599 | |
600 | of_node_put(node: tmp); |
601 | |
602 | if (found) { |
603 | *index = i; |
604 | break; |
605 | } |
606 | } |
607 | |
608 | return found; |
609 | } |
610 | |
611 | /** |
612 | * of_check_coupling_data - Parse rdev's coupling properties and check data |
613 | * consistency |
614 | * @rdev: pointer to regulator_dev whose data is checked |
615 | * |
616 | * Function checks if all the following conditions are met: |
617 | * - rdev's max_spread is greater than 0 |
618 | * - all coupled regulators have the same max_spread |
619 | * - all coupled regulators have the same number of regulator_dev phandles |
620 | * - all regulators are linked to each other |
621 | * |
622 | * Returns true if all conditions are met. |
623 | */ |
624 | bool of_check_coupling_data(struct regulator_dev *rdev) |
625 | { |
626 | struct device_node *node = rdev->dev.of_node; |
627 | int n_phandles = of_get_n_coupled(rdev); |
628 | struct device_node *c_node; |
629 | int index; |
630 | int i; |
631 | bool ret = true; |
632 | |
633 | /* iterate over rdev's phandles */ |
634 | for (i = 0; i < n_phandles; i++) { |
635 | int max_spread = rdev->constraints->max_spread[i]; |
636 | int c_max_spread, c_n_phandles; |
637 | |
638 | if (max_spread <= 0) { |
639 | dev_err(&rdev->dev, "max_spread value invalid\n" ); |
640 | return false; |
641 | } |
642 | |
643 | c_node = of_parse_phandle(np: node, |
644 | phandle_name: "regulator-coupled-with" , index: i); |
645 | |
646 | if (!c_node) |
647 | ret = false; |
648 | |
649 | c_n_phandles = of_count_phandle_with_args(np: c_node, |
650 | list_name: "regulator-coupled-with" , |
651 | NULL); |
652 | |
653 | if (c_n_phandles != n_phandles) { |
654 | dev_err(&rdev->dev, "number of coupled reg phandles mismatch\n" ); |
655 | ret = false; |
656 | goto clean; |
657 | } |
658 | |
659 | if (!of_coupling_find_node(src: c_node, to_find: node, index: &index)) { |
660 | dev_err(&rdev->dev, "missing 2-way linking for coupled regulators\n" ); |
661 | ret = false; |
662 | goto clean; |
663 | } |
664 | |
665 | if (of_property_read_u32_index(np: c_node, propname: "regulator-coupled-max-spread" , |
666 | index, out_value: &c_max_spread)) { |
667 | ret = false; |
668 | goto clean; |
669 | } |
670 | |
671 | if (c_max_spread != max_spread) { |
672 | dev_err(&rdev->dev, |
673 | "coupled regulators max_spread mismatch\n" ); |
674 | ret = false; |
675 | goto clean; |
676 | } |
677 | |
678 | clean: |
679 | of_node_put(node: c_node); |
680 | if (!ret) |
681 | break; |
682 | } |
683 | |
684 | return ret; |
685 | } |
686 | |
687 | /** |
688 | * of_parse_coupled_regulator() - Get regulator_dev pointer from rdev's property |
689 | * @rdev: Pointer to regulator_dev, whose DTS is used as a source to parse |
690 | * "regulator-coupled-with" property |
691 | * @index: Index in phandles array |
692 | * |
693 | * Returns the regulator_dev pointer parsed from DTS. If it has not been yet |
694 | * registered, returns NULL |
695 | */ |
696 | struct regulator_dev *of_parse_coupled_regulator(struct regulator_dev *rdev, |
697 | int index) |
698 | { |
699 | struct device_node *node = rdev->dev.of_node; |
700 | struct device_node *c_node; |
701 | struct regulator_dev *c_rdev; |
702 | |
703 | c_node = of_parse_phandle(np: node, phandle_name: "regulator-coupled-with" , index); |
704 | if (!c_node) |
705 | return NULL; |
706 | |
707 | c_rdev = of_find_regulator_by_node(np: c_node); |
708 | |
709 | of_node_put(node: c_node); |
710 | |
711 | return c_rdev; |
712 | } |
713 | |
714 | /* |
715 | * Check if name is a supply name according to the '*-supply' pattern |
716 | * return 0 if false |
717 | * return length of supply name without the -supply |
718 | */ |
719 | static int is_supply_name(const char *name) |
720 | { |
721 | int strs, i; |
722 | |
723 | strs = strlen(name); |
724 | /* string need to be at minimum len(x-supply) */ |
725 | if (strs < 8) |
726 | return 0; |
727 | for (i = strs - 6; i > 0; i--) { |
728 | /* find first '-' and check if right part is supply */ |
729 | if (name[i] != '-') |
730 | continue; |
731 | if (strcmp(name + i + 1, "supply" ) != 0) |
732 | return 0; |
733 | return i; |
734 | } |
735 | return 0; |
736 | } |
737 | |
738 | /* |
739 | * of_regulator_bulk_get_all - get multiple regulator consumers |
740 | * |
741 | * @dev: Device to supply |
742 | * @np: device node to search for consumers |
743 | * @consumers: Configuration of consumers; clients are stored here. |
744 | * |
745 | * @return number of regulators on success, an errno on failure. |
746 | * |
747 | * This helper function allows drivers to get several regulator |
748 | * consumers in one operation. If any of the regulators cannot be |
749 | * acquired then any regulators that were allocated will be freed |
750 | * before returning to the caller. |
751 | */ |
752 | int of_regulator_bulk_get_all(struct device *dev, struct device_node *np, |
753 | struct regulator_bulk_data **consumers) |
754 | { |
755 | int num_consumers = 0; |
756 | struct regulator *tmp; |
757 | struct property *prop; |
758 | int i, n = 0, ret; |
759 | char name[64]; |
760 | |
761 | *consumers = NULL; |
762 | |
763 | /* |
764 | * first pass: get numbers of xxx-supply |
765 | * second pass: fill consumers |
766 | */ |
767 | restart: |
768 | for_each_property_of_node(np, prop) { |
769 | i = is_supply_name(name: prop->name); |
770 | if (i == 0) |
771 | continue; |
772 | if (!*consumers) { |
773 | num_consumers++; |
774 | continue; |
775 | } else { |
776 | memcpy(name, prop->name, i); |
777 | name[i] = '\0'; |
778 | tmp = regulator_get(dev, id: name); |
779 | if (IS_ERR(ptr: tmp)) { |
780 | ret = -EINVAL; |
781 | goto error; |
782 | } |
783 | (*consumers)[n].consumer = tmp; |
784 | n++; |
785 | continue; |
786 | } |
787 | } |
788 | if (*consumers) |
789 | return num_consumers; |
790 | if (num_consumers == 0) |
791 | return 0; |
792 | *consumers = kmalloc_array(n: num_consumers, |
793 | size: sizeof(struct regulator_bulk_data), |
794 | GFP_KERNEL); |
795 | if (!*consumers) |
796 | return -ENOMEM; |
797 | goto restart; |
798 | |
799 | error: |
800 | while (--n >= 0) |
801 | regulator_put(regulator: consumers[n]->consumer); |
802 | return ret; |
803 | } |
804 | EXPORT_SYMBOL_GPL(of_regulator_bulk_get_all); |
805 | |