Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0+
2 : : /*
3 : : * drivers/of/property.c - Procedures for accessing and interpreting
4 : : * Devicetree properties and graphs.
5 : : *
6 : : * Initially created by copying procedures from drivers/of/base.c. This
7 : : * file contains the OF property as well as the OF graph interface
8 : : * functions.
9 : : *
10 : : * Paul Mackerras August 1996.
11 : : * Copyright (C) 1996-2005 Paul Mackerras.
12 : : *
13 : : * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner.
14 : : * {engebret|bergner}@us.ibm.com
15 : : *
16 : : * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net
17 : : *
18 : : * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
19 : : * Grant Likely.
20 : : */
21 : :
22 : : #define pr_fmt(fmt) "OF: " fmt
23 : :
24 : : #include <linux/of.h>
25 : : #include <linux/of_device.h>
26 : : #include <linux/of_graph.h>
27 : : #include <linux/string.h>
28 : :
29 : : #include "of_private.h"
30 : :
31 : : /**
32 : : * of_property_count_elems_of_size - Count the number of elements in a property
33 : : *
34 : : * @np: device node from which the property value is to be read.
35 : : * @propname: name of the property to be searched.
36 : : * @elem_size: size of the individual element
37 : : *
38 : : * Search for a property in a device node and count the number of elements of
39 : : * size elem_size in it. Returns number of elements on sucess, -EINVAL if the
40 : : * property does not exist or its length does not match a multiple of elem_size
41 : : * and -ENODATA if the property does not have a value.
42 : : */
43 : 828 : int of_property_count_elems_of_size(const struct device_node *np,
44 : : const char *propname, int elem_size)
45 : : {
46 : 828 : struct property *prop = of_find_property(np, propname, NULL);
47 : :
48 [ - + ]: 828 : if (!prop)
49 : : return -EINVAL;
50 [ # # ]: 0 : if (!prop->value)
51 : : return -ENODATA;
52 : :
53 [ # # ]: 0 : if (prop->length % elem_size != 0) {
54 : 0 : pr_err("size of %s in node %pOF is not a multiple of %d\n",
55 : : propname, np, elem_size);
56 : 0 : return -EINVAL;
57 : : }
58 : :
59 : 0 : return prop->length / elem_size;
60 : : }
61 : : EXPORT_SYMBOL_GPL(of_property_count_elems_of_size);
62 : :
63 : : /**
64 : : * of_find_property_value_of_size
65 : : *
66 : : * @np: device node from which the property value is to be read.
67 : : * @propname: name of the property to be searched.
68 : : * @min: minimum allowed length of property value
69 : : * @max: maximum allowed length of property value (0 means unlimited)
70 : : * @len: if !=NULL, actual length is written to here
71 : : *
72 : : * Search for a property in a device node and valid the requested size.
73 : : * Returns the property value on success, -EINVAL if the property does not
74 : : * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the
75 : : * property data is too small or too large.
76 : : *
77 : : */
78 : 276552 : static void *of_find_property_value_of_size(const struct device_node *np,
79 : : const char *propname, u32 min, u32 max, size_t *len)
80 : : {
81 : 276552 : struct property *prop = of_find_property(np, propname, NULL);
82 : :
83 [ + + ]: 276552 : if (!prop)
84 : : return ERR_PTR(-EINVAL);
85 [ + - ]: 224595 : if (!prop->value)
86 : : return ERR_PTR(-ENODATA);
87 [ + + ]: 224595 : if (prop->length < min)
88 : : return ERR_PTR(-EOVERFLOW);
89 [ - + # # ]: 220662 : if (max && prop->length > max)
90 : : return ERR_PTR(-EOVERFLOW);
91 : :
92 [ + + ]: 220662 : if (len)
93 : 180297 : *len = prop->length;
94 : :
95 : 220662 : return prop->value;
96 : : }
97 : :
98 : : /**
99 : : * of_property_read_u32_index - Find and read a u32 from a multi-value property.
100 : : *
101 : : * @np: device node from which the property value is to be read.
102 : : * @propname: name of the property to be searched.
103 : : * @index: index of the u32 in the list of values
104 : : * @out_value: pointer to return value, modified only if no error.
105 : : *
106 : : * Search for a property in a device node and read nth 32-bit value from
107 : : * it. Returns 0 on success, -EINVAL if the property does not exist,
108 : : * -ENODATA if property does not have a value, and -EOVERFLOW if the
109 : : * property data isn't large enough.
110 : : *
111 : : * The out_value is modified only if a valid u32 value can be decoded.
112 : : */
113 : 47403 : int of_property_read_u32_index(const struct device_node *np,
114 : : const char *propname,
115 : : u32 index, u32 *out_value)
116 : : {
117 : 47403 : const u32 *val = of_find_property_value_of_size(np, propname,
118 : : ((index + 1) * sizeof(*out_value)),
119 : : 0,
120 : : NULL);
121 : :
122 [ + + ]: 47403 : if (IS_ERR(val))
123 : 7245 : return PTR_ERR(val);
124 : :
125 : 80316 : *out_value = be32_to_cpup(((__be32 *)val) + index);
126 : 40158 : return 0;
127 : : }
128 : : EXPORT_SYMBOL_GPL(of_property_read_u32_index);
129 : :
130 : : /**
131 : : * of_property_read_u64_index - Find and read a u64 from a multi-value property.
132 : : *
133 : : * @np: device node from which the property value is to be read.
134 : : * @propname: name of the property to be searched.
135 : : * @index: index of the u64 in the list of values
136 : : * @out_value: pointer to return value, modified only if no error.
137 : : *
138 : : * Search for a property in a device node and read nth 64-bit value from
139 : : * it. Returns 0 on success, -EINVAL if the property does not exist,
140 : : * -ENODATA if property does not have a value, and -EOVERFLOW if the
141 : : * property data isn't large enough.
142 : : *
143 : : * The out_value is modified only if a valid u64 value can be decoded.
144 : : */
145 : 0 : int of_property_read_u64_index(const struct device_node *np,
146 : : const char *propname,
147 : : u32 index, u64 *out_value)
148 : : {
149 : 0 : const u64 *val = of_find_property_value_of_size(np, propname,
150 : : ((index + 1) * sizeof(*out_value)),
151 : : 0, NULL);
152 : :
153 [ # # ]: 0 : if (IS_ERR(val))
154 : 0 : return PTR_ERR(val);
155 : :
156 : 0 : *out_value = be64_to_cpup(((__be64 *)val) + index);
157 : 0 : return 0;
158 : : }
159 : : EXPORT_SYMBOL_GPL(of_property_read_u64_index);
160 : :
161 : : /**
162 : : * of_property_read_variable_u8_array - Find and read an array of u8 from a
163 : : * property, with bounds on the minimum and maximum array size.
164 : : *
165 : : * @np: device node from which the property value is to be read.
166 : : * @propname: name of the property to be searched.
167 : : * @out_values: pointer to return value, modified only if return value is 0.
168 : : * @sz_min: minimum number of array elements to read
169 : : * @sz_max: maximum number of array elements to read, if zero there is no
170 : : * upper limit on the number of elements in the dts entry but only
171 : : * sz_min will be read.
172 : : *
173 : : * Search for a property in a device node and read 8-bit value(s) from
174 : : * it. Returns number of elements read on success, -EINVAL if the property
175 : : * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
176 : : * if the property data is smaller than sz_min or longer than sz_max.
177 : : *
178 : : * dts entry of array should be like:
179 : : * property = /bits/ 8 <0x50 0x60 0x70>;
180 : : *
181 : : * The out_values is modified only if a valid u8 value can be decoded.
182 : : */
183 : 0 : int of_property_read_variable_u8_array(const struct device_node *np,
184 : : const char *propname, u8 *out_values,
185 : : size_t sz_min, size_t sz_max)
186 : : {
187 : : size_t sz, count;
188 : 0 : const u8 *val = of_find_property_value_of_size(np, propname,
189 : : (sz_min * sizeof(*out_values)),
190 : : (sz_max * sizeof(*out_values)),
191 : : &sz);
192 : :
193 [ # # ]: 0 : if (IS_ERR(val))
194 : 0 : return PTR_ERR(val);
195 : :
196 [ # # ]: 0 : if (!sz_max)
197 : 0 : sz = sz_min;
198 : : else
199 : : sz /= sizeof(*out_values);
200 : :
201 : 0 : count = sz;
202 [ # # ]: 0 : while (count--)
203 : 0 : *out_values++ = *val++;
204 : :
205 : 0 : return sz;
206 : : }
207 : : EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array);
208 : :
209 : : /**
210 : : * of_property_read_variable_u16_array - Find and read an array of u16 from a
211 : : * property, with bounds on the minimum and maximum array size.
212 : : *
213 : : * @np: device node from which the property value is to be read.
214 : : * @propname: name of the property to be searched.
215 : : * @out_values: pointer to return value, modified only if return value is 0.
216 : : * @sz_min: minimum number of array elements to read
217 : : * @sz_max: maximum number of array elements to read, if zero there is no
218 : : * upper limit on the number of elements in the dts entry but only
219 : : * sz_min will be read.
220 : : *
221 : : * Search for a property in a device node and read 16-bit value(s) from
222 : : * it. Returns number of elements read on success, -EINVAL if the property
223 : : * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
224 : : * if the property data is smaller than sz_min or longer than sz_max.
225 : : *
226 : : * dts entry of array should be like:
227 : : * property = /bits/ 16 <0x5000 0x6000 0x7000>;
228 : : *
229 : : * The out_values is modified only if a valid u16 value can be decoded.
230 : : */
231 : 0 : int of_property_read_variable_u16_array(const struct device_node *np,
232 : : const char *propname, u16 *out_values,
233 : : size_t sz_min, size_t sz_max)
234 : : {
235 : : size_t sz, count;
236 : 0 : const __be16 *val = of_find_property_value_of_size(np, propname,
237 : : (sz_min * sizeof(*out_values)),
238 : : (sz_max * sizeof(*out_values)),
239 : : &sz);
240 : :
241 [ # # ]: 0 : if (IS_ERR(val))
242 : 0 : return PTR_ERR(val);
243 : :
244 [ # # ]: 0 : if (!sz_max)
245 : 0 : sz = sz_min;
246 : : else
247 : 0 : sz /= sizeof(*out_values);
248 : :
249 : 0 : count = sz;
250 [ # # ]: 0 : while (count--)
251 : 0 : *out_values++ = be16_to_cpup(val++);
252 : :
253 : 0 : return sz;
254 : : }
255 : : EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array);
256 : :
257 : : /**
258 : : * of_property_read_variable_u32_array - Find and read an array of 32 bit
259 : : * integers from a property, with bounds on the minimum and maximum array size.
260 : : *
261 : : * @np: device node from which the property value is to be read.
262 : : * @propname: name of the property to be searched.
263 : : * @out_values: pointer to return value, modified only if return value is 0.
264 : : * @sz_min: minimum number of array elements to read
265 : : * @sz_max: maximum number of array elements to read, if zero there is no
266 : : * upper limit on the number of elements in the dts entry but only
267 : : * sz_min will be read.
268 : : *
269 : : * Search for a property in a device node and read 32-bit value(s) from
270 : : * it. Returns number of elements read on success, -EINVAL if the property
271 : : * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
272 : : * if the property data is smaller than sz_min or longer than sz_max.
273 : : *
274 : : * The out_values is modified only if a valid u32 value can be decoded.
275 : : */
276 : 228942 : int of_property_read_variable_u32_array(const struct device_node *np,
277 : : const char *propname, u32 *out_values,
278 : : size_t sz_min, size_t sz_max)
279 : : {
280 : : size_t sz, count;
281 : 228942 : const __be32 *val = of_find_property_value_of_size(np, propname,
282 : : (sz_min * sizeof(*out_values)),
283 : : (sz_max * sizeof(*out_values)),
284 : : &sz);
285 : :
286 [ + + ]: 228942 : if (IS_ERR(val))
287 : 48645 : return PTR_ERR(val);
288 : :
289 [ + - ]: 180297 : if (!sz_max)
290 : 180297 : sz = sz_min;
291 : : else
292 : 0 : sz /= sizeof(*out_values);
293 : :
294 : 180297 : count = sz;
295 [ + + ]: 541098 : while (count--)
296 : 361008 : *out_values++ = be32_to_cpup(val++);
297 : :
298 : 180297 : return sz;
299 : : }
300 : : EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array);
301 : :
302 : : /**
303 : : * of_property_read_u64 - Find and read a 64 bit integer from a property
304 : : * @np: device node from which the property value is to be read.
305 : : * @propname: name of the property to be searched.
306 : : * @out_value: pointer to return value, modified only if return value is 0.
307 : : *
308 : : * Search for a property in a device node and read a 64-bit value from
309 : : * it. Returns 0 on success, -EINVAL if the property does not exist,
310 : : * -ENODATA if property does not have a value, and -EOVERFLOW if the
311 : : * property data isn't large enough.
312 : : *
313 : : * The out_value is modified only if a valid u64 value can be decoded.
314 : : */
315 : 207 : int of_property_read_u64(const struct device_node *np, const char *propname,
316 : : u64 *out_value)
317 : : {
318 : 207 : const __be32 *val = of_find_property_value_of_size(np, propname,
319 : : sizeof(*out_value),
320 : : 0,
321 : : NULL);
322 : :
323 [ + - ]: 207 : if (IS_ERR(val))
324 : 0 : return PTR_ERR(val);
325 : :
326 : 207 : *out_value = of_read_number(val, 2);
327 : 207 : return 0;
328 : : }
329 : : EXPORT_SYMBOL_GPL(of_property_read_u64);
330 : :
331 : : /**
332 : : * of_property_read_variable_u64_array - Find and read an array of 64 bit
333 : : * integers from a property, with bounds on the minimum and maximum array size.
334 : : *
335 : : * @np: device node from which the property value is to be read.
336 : : * @propname: name of the property to be searched.
337 : : * @out_values: pointer to return value, modified only if return value is 0.
338 : : * @sz_min: minimum number of array elements to read
339 : : * @sz_max: maximum number of array elements to read, if zero there is no
340 : : * upper limit on the number of elements in the dts entry but only
341 : : * sz_min will be read.
342 : : *
343 : : * Search for a property in a device node and read 64-bit value(s) from
344 : : * it. Returns number of elements read on success, -EINVAL if the property
345 : : * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW
346 : : * if the property data is smaller than sz_min or longer than sz_max.
347 : : *
348 : : * The out_values is modified only if a valid u64 value can be decoded.
349 : : */
350 : 0 : int of_property_read_variable_u64_array(const struct device_node *np,
351 : : const char *propname, u64 *out_values,
352 : : size_t sz_min, size_t sz_max)
353 : : {
354 : : size_t sz, count;
355 : 0 : const __be32 *val = of_find_property_value_of_size(np, propname,
356 : : (sz_min * sizeof(*out_values)),
357 : : (sz_max * sizeof(*out_values)),
358 : : &sz);
359 : :
360 [ # # ]: 0 : if (IS_ERR(val))
361 : 0 : return PTR_ERR(val);
362 : :
363 [ # # ]: 0 : if (!sz_max)
364 : 0 : sz = sz_min;
365 : : else
366 : 0 : sz /= sizeof(*out_values);
367 : :
368 : 0 : count = sz;
369 [ # # ]: 0 : while (count--) {
370 : 0 : *out_values++ = of_read_number(val, 2);
371 : 0 : val += 2;
372 : : }
373 : :
374 : 0 : return sz;
375 : : }
376 : : EXPORT_SYMBOL_GPL(of_property_read_variable_u64_array);
377 : :
378 : : /**
379 : : * of_property_read_string - Find and read a string from a property
380 : : * @np: device node from which the property value is to be read.
381 : : * @propname: name of the property to be searched.
382 : : * @out_string: pointer to null terminated return string, modified only if
383 : : * return value is 0.
384 : : *
385 : : * Search for a property in a device tree node and retrieve a null
386 : : * terminated string value (pointer to data, not a copy). Returns 0 on
387 : : * success, -EINVAL if the property does not exist, -ENODATA if property
388 : : * does not have a value, and -EILSEQ if the string is not null-terminated
389 : : * within the length of the property data.
390 : : *
391 : : * The out_string pointer is modified only if a valid string can be decoded.
392 : : */
393 : 5175 : int of_property_read_string(const struct device_node *np, const char *propname,
394 : : const char **out_string)
395 : : {
396 : 5175 : const struct property *prop = of_find_property(np, propname, NULL);
397 [ + + ]: 5175 : if (!prop)
398 : : return -EINVAL;
399 [ + - ]: 3933 : if (!prop->value)
400 : : return -ENODATA;
401 [ + - ]: 3933 : if (strnlen(prop->value, prop->length) >= prop->length)
402 : : return -EILSEQ;
403 : 3933 : *out_string = prop->value;
404 : 3933 : return 0;
405 : : }
406 : : EXPORT_SYMBOL_GPL(of_property_read_string);
407 : :
408 : : /**
409 : : * of_property_match_string() - Find string in a list and return index
410 : : * @np: pointer to node containing string list property
411 : : * @propname: string list property name
412 : : * @string: pointer to string to search for in string list
413 : : *
414 : : * This function searches a string list property and returns the index
415 : : * of a specific string value.
416 : : */
417 : 44505 : int of_property_match_string(const struct device_node *np, const char *propname,
418 : : const char *string)
419 : : {
420 : 44505 : const struct property *prop = of_find_property(np, propname, NULL);
421 : : size_t l;
422 : : int i;
423 : : const char *p, *end;
424 : :
425 [ + + ]: 44505 : if (!prop)
426 : : return -EINVAL;
427 [ + - ]: 6003 : if (!prop->value)
428 : : return -ENODATA;
429 : :
430 : : p = prop->value;
431 : 6003 : end = p + prop->length;
432 : :
433 [ + + ]: 34362 : for (i = 0; p < end; i++, p += l) {
434 : 32292 : l = strnlen(p, end - p) + 1;
435 [ + - ]: 32292 : if (p + l > end)
436 : : return -EILSEQ;
437 : : pr_debug("comparing %s with %s\n", string, p);
438 [ + + ]: 32292 : if (strcmp(string, p) == 0)
439 : 3933 : return i; /* Found it; return index */
440 : : }
441 : : return -ENODATA;
442 : : }
443 : : EXPORT_SYMBOL_GPL(of_property_match_string);
444 : :
445 : : /**
446 : : * of_property_read_string_helper() - Utility helper for parsing string properties
447 : : * @np: device node from which the property value is to be read.
448 : : * @propname: name of the property to be searched.
449 : : * @out_strs: output array of string pointers.
450 : : * @sz: number of array elements to read.
451 : : * @skip: Number of strings to skip over at beginning of list.
452 : : *
453 : : * Don't call this function directly. It is a utility helper for the
454 : : * of_property_read_string*() family of functions.
455 : : */
456 : 18837 : int of_property_read_string_helper(const struct device_node *np,
457 : : const char *propname, const char **out_strs,
458 : : size_t sz, int skip)
459 : : {
460 : 18837 : const struct property *prop = of_find_property(np, propname, NULL);
461 : : int l = 0, i = 0;
462 : : const char *p, *end;
463 : :
464 [ + + ]: 18837 : if (!prop)
465 : : return -EINVAL;
466 [ + - ]: 7659 : if (!prop->value)
467 : : return -ENODATA;
468 : : p = prop->value;
469 : 7659 : end = p + prop->length;
470 : :
471 [ + + + + : 41607 : for (i = 0; p < end && (!out_strs || i < skip + sz); i++, p += l) {
+ + ]
472 : 33948 : l = strnlen(p, end - p) + 1;
473 [ + - ]: 33948 : if (p + l > end)
474 : : return -EILSEQ;
475 [ + + ]: 33948 : if (out_strs && i >= skip)
476 : 7245 : *out_strs++ = p;
477 : : }
478 : 7659 : i -= skip;
479 [ + - ]: 7659 : return i <= 0 ? -ENODATA : i;
480 : : }
481 : : EXPORT_SYMBOL_GPL(of_property_read_string_helper);
482 : :
483 : 8694 : const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
484 : : u32 *pu)
485 : : {
486 : : const void *curv = cur;
487 : :
488 [ - + ]: 8694 : if (!prop)
489 : : return NULL;
490 : :
491 [ # # ]: 0 : if (!cur) {
492 : 0 : curv = prop->value;
493 : 0 : goto out_val;
494 : : }
495 : :
496 : 0 : curv += sizeof(*cur);
497 [ # # ]: 0 : if (curv >= prop->value + prop->length)
498 : : return NULL;
499 : :
500 : : out_val:
501 : 0 : *pu = be32_to_cpup(curv);
502 : 0 : return curv;
503 : : }
504 : : EXPORT_SYMBOL_GPL(of_prop_next_u32);
505 : :
506 : 2700296 : const char *of_prop_next_string(struct property *prop, const char *cur)
507 : : {
508 : : const void *curv = cur;
509 : :
510 [ + + ]: 2700296 : if (!prop)
511 : : return NULL;
512 : :
513 [ + + ]: 2261437 : if (!cur)
514 : 1072659 : return prop->value;
515 : :
516 : 1188778 : curv += strlen(cur) + 1;
517 [ + + ]: 1188778 : if (curv >= prop->value + prop->length)
518 : : return NULL;
519 : :
520 : 128332 : return curv;
521 : : }
522 : : EXPORT_SYMBOL_GPL(of_prop_next_string);
523 : :
524 : : /**
525 : : * of_graph_parse_endpoint() - parse common endpoint node properties
526 : : * @node: pointer to endpoint device_node
527 : : * @endpoint: pointer to the OF endpoint data structure
528 : : *
529 : : * The caller should hold a reference to @node.
530 : : */
531 : 0 : int of_graph_parse_endpoint(const struct device_node *node,
532 : : struct of_endpoint *endpoint)
533 : : {
534 : 0 : struct device_node *port_node = of_get_parent(node);
535 : :
536 [ # # # # ]: 0 : WARN_ONCE(!port_node, "%s(): endpoint %pOF has no parent node\n",
537 : : __func__, node);
538 : :
539 : 0 : memset(endpoint, 0, sizeof(*endpoint));
540 : :
541 : 0 : endpoint->local_node = node;
542 : : /*
543 : : * It doesn't matter whether the two calls below succeed.
544 : : * If they don't then the default value 0 is used.
545 : : */
546 : 0 : of_property_read_u32(port_node, "reg", &endpoint->port);
547 : 0 : of_property_read_u32(node, "reg", &endpoint->id);
548 : :
549 : 0 : of_node_put(port_node);
550 : :
551 : 0 : return 0;
552 : : }
553 : : EXPORT_SYMBOL(of_graph_parse_endpoint);
554 : :
555 : : /**
556 : : * of_graph_get_port_by_id() - get the port matching a given id
557 : : * @parent: pointer to the parent device node
558 : : * @id: id of the port
559 : : *
560 : : * Return: A 'port' node pointer with refcount incremented. The caller
561 : : * has to use of_node_put() on it when done.
562 : : */
563 : 0 : struct device_node *of_graph_get_port_by_id(struct device_node *parent, u32 id)
564 : : {
565 : : struct device_node *node, *port;
566 : :
567 : 0 : node = of_get_child_by_name(parent, "ports");
568 [ # # ]: 0 : if (node)
569 : : parent = node;
570 : :
571 [ # # ]: 0 : for_each_child_of_node(parent, port) {
572 : 0 : u32 port_id = 0;
573 : :
574 [ # # ]: 0 : if (!of_node_name_eq(port, "port"))
575 : 0 : continue;
576 : : of_property_read_u32(port, "reg", &port_id);
577 [ # # ]: 0 : if (id == port_id)
578 : : break;
579 : : }
580 : :
581 : 0 : of_node_put(node);
582 : :
583 : 0 : return port;
584 : : }
585 : : EXPORT_SYMBOL(of_graph_get_port_by_id);
586 : :
587 : : /**
588 : : * of_graph_get_next_endpoint() - get next endpoint node
589 : : * @parent: pointer to the parent device node
590 : : * @prev: previous endpoint node, or NULL to get first
591 : : *
592 : : * Return: An 'endpoint' node pointer with refcount incremented. Refcount
593 : : * of the passed @prev node is decremented.
594 : : */
595 : 0 : struct device_node *of_graph_get_next_endpoint(const struct device_node *parent,
596 : : struct device_node *prev)
597 : : {
598 : : struct device_node *endpoint;
599 : : struct device_node *port;
600 : :
601 [ # # ]: 0 : if (!parent)
602 : : return NULL;
603 : :
604 : : /*
605 : : * Start by locating the port node. If no previous endpoint is specified
606 : : * search for the first port node, otherwise get the previous endpoint
607 : : * parent port node.
608 : : */
609 [ # # ]: 0 : if (!prev) {
610 : : struct device_node *node;
611 : :
612 : 0 : node = of_get_child_by_name(parent, "ports");
613 [ # # ]: 0 : if (node)
614 : : parent = node;
615 : :
616 : 0 : port = of_get_child_by_name(parent, "port");
617 : 0 : of_node_put(node);
618 : :
619 [ # # ]: 0 : if (!port) {
620 : 0 : pr_err("graph: no port node found in %pOF\n", parent);
621 : 0 : return NULL;
622 : : }
623 : : } else {
624 : 0 : port = of_get_parent(prev);
625 [ # # # # : 0 : if (WARN_ONCE(!port, "%s(): endpoint %pOF has no parent node\n",
# # ]
626 : : __func__, prev))
627 : : return NULL;
628 : : }
629 : :
630 : : while (1) {
631 : : /*
632 : : * Now that we have a port node, get the next endpoint by
633 : : * getting the next child. If the previous endpoint is NULL this
634 : : * will return the first child.
635 : : */
636 : 0 : endpoint = of_get_next_child(port, prev);
637 [ # # ]: 0 : if (endpoint) {
638 : 0 : of_node_put(port);
639 : 0 : return endpoint;
640 : : }
641 : :
642 : : /* No more endpoints under this port, try the next one. */
643 : : prev = NULL;
644 : :
645 : : do {
646 : 0 : port = of_get_next_child(parent, port);
647 [ # # ]: 0 : if (!port)
648 : : return NULL;
649 [ # # ]: 0 : } while (!of_node_name_eq(port, "port"));
650 : : }
651 : : }
652 : : EXPORT_SYMBOL(of_graph_get_next_endpoint);
653 : :
654 : : /**
655 : : * of_graph_get_endpoint_by_regs() - get endpoint node of specific identifiers
656 : : * @parent: pointer to the parent device node
657 : : * @port_reg: identifier (value of reg property) of the parent port node
658 : : * @reg: identifier (value of reg property) of the endpoint node
659 : : *
660 : : * Return: An 'endpoint' node pointer which is identified by reg and at the same
661 : : * is the child of a port node identified by port_reg. reg and port_reg are
662 : : * ignored when they are -1. Use of_node_put() on the pointer when done.
663 : : */
664 : 0 : struct device_node *of_graph_get_endpoint_by_regs(
665 : : const struct device_node *parent, int port_reg, int reg)
666 : : {
667 : : struct of_endpoint endpoint;
668 : : struct device_node *node = NULL;
669 : :
670 [ # # ]: 0 : for_each_endpoint_of_node(parent, node) {
671 : 0 : of_graph_parse_endpoint(node, &endpoint);
672 [ # # # # : 0 : if (((port_reg == -1) || (endpoint.port == port_reg)) &&
# # ]
673 [ # # ]: 0 : ((reg == -1) || (endpoint.id == reg)))
674 : 0 : return node;
675 : : }
676 : :
677 : : return NULL;
678 : : }
679 : : EXPORT_SYMBOL(of_graph_get_endpoint_by_regs);
680 : :
681 : : /**
682 : : * of_graph_get_remote_endpoint() - get remote endpoint node
683 : : * @node: pointer to a local endpoint device_node
684 : : *
685 : : * Return: Remote endpoint node associated with remote endpoint node linked
686 : : * to @node. Use of_node_put() on it when done.
687 : : */
688 : 0 : struct device_node *of_graph_get_remote_endpoint(const struct device_node *node)
689 : : {
690 : : /* Get remote endpoint node. */
691 : 0 : return of_parse_phandle(node, "remote-endpoint", 0);
692 : : }
693 : : EXPORT_SYMBOL(of_graph_get_remote_endpoint);
694 : :
695 : : /**
696 : : * of_graph_get_port_parent() - get port's parent node
697 : : * @node: pointer to a local endpoint device_node
698 : : *
699 : : * Return: device node associated with endpoint node linked
700 : : * to @node. Use of_node_put() on it when done.
701 : : */
702 : 0 : struct device_node *of_graph_get_port_parent(struct device_node *node)
703 : : {
704 : : unsigned int depth;
705 : :
706 [ # # ]: 0 : if (!node)
707 : : return NULL;
708 : :
709 : : /*
710 : : * Preserve usecount for passed in node as of_get_next_parent()
711 : : * will do of_node_put() on it.
712 : : */
713 : 0 : of_node_get(node);
714 : :
715 : : /* Walk 3 levels up only if there is 'ports' node. */
716 [ # # ]: 0 : for (depth = 3; depth && node; depth--) {
717 : 0 : node = of_get_next_parent(node);
718 [ # # # # ]: 0 : if (depth == 2 && !of_node_name_eq(node, "ports"))
719 : : break;
720 : : }
721 : 0 : return node;
722 : : }
723 : : EXPORT_SYMBOL(of_graph_get_port_parent);
724 : :
725 : : /**
726 : : * of_graph_get_remote_port_parent() - get remote port's parent node
727 : : * @node: pointer to a local endpoint device_node
728 : : *
729 : : * Return: Remote device node associated with remote endpoint node linked
730 : : * to @node. Use of_node_put() on it when done.
731 : : */
732 : 0 : struct device_node *of_graph_get_remote_port_parent(
733 : : const struct device_node *node)
734 : : {
735 : : struct device_node *np, *pp;
736 : :
737 : : /* Get remote endpoint node. */
738 : : np = of_graph_get_remote_endpoint(node);
739 : :
740 : 0 : pp = of_graph_get_port_parent(np);
741 : :
742 : 0 : of_node_put(np);
743 : :
744 : 0 : return pp;
745 : : }
746 : : EXPORT_SYMBOL(of_graph_get_remote_port_parent);
747 : :
748 : : /**
749 : : * of_graph_get_remote_port() - get remote port node
750 : : * @node: pointer to a local endpoint device_node
751 : : *
752 : : * Return: Remote port node associated with remote endpoint node linked
753 : : * to @node. Use of_node_put() on it when done.
754 : : */
755 : 0 : struct device_node *of_graph_get_remote_port(const struct device_node *node)
756 : : {
757 : : struct device_node *np;
758 : :
759 : : /* Get remote endpoint node. */
760 : : np = of_graph_get_remote_endpoint(node);
761 [ # # ]: 0 : if (!np)
762 : : return NULL;
763 : 0 : return of_get_next_parent(np);
764 : : }
765 : : EXPORT_SYMBOL(of_graph_get_remote_port);
766 : :
767 : 0 : int of_graph_get_endpoint_count(const struct device_node *np)
768 : : {
769 : : struct device_node *endpoint;
770 : : int num = 0;
771 : :
772 [ # # ]: 0 : for_each_endpoint_of_node(np, endpoint)
773 : 0 : num++;
774 : :
775 : 0 : return num;
776 : : }
777 : : EXPORT_SYMBOL(of_graph_get_endpoint_count);
778 : :
779 : : /**
780 : : * of_graph_get_remote_node() - get remote parent device_node for given port/endpoint
781 : : * @node: pointer to parent device_node containing graph port/endpoint
782 : : * @port: identifier (value of reg property) of the parent port node
783 : : * @endpoint: identifier (value of reg property) of the endpoint node
784 : : *
785 : : * Return: Remote device node associated with remote endpoint node linked
786 : : * to @node. Use of_node_put() on it when done.
787 : : */
788 : 0 : struct device_node *of_graph_get_remote_node(const struct device_node *node,
789 : : u32 port, u32 endpoint)
790 : : {
791 : : struct device_node *endpoint_node, *remote;
792 : :
793 : 0 : endpoint_node = of_graph_get_endpoint_by_regs(node, port, endpoint);
794 [ # # ]: 0 : if (!endpoint_node) {
795 : : pr_debug("no valid endpoint (%d, %d) for node %pOF\n",
796 : : port, endpoint, node);
797 : : return NULL;
798 : : }
799 : :
800 : 0 : remote = of_graph_get_remote_port_parent(endpoint_node);
801 : 0 : of_node_put(endpoint_node);
802 [ # # ]: 0 : if (!remote) {
803 : : pr_debug("no valid remote node\n");
804 : : return NULL;
805 : : }
806 : :
807 [ # # ]: 0 : if (!of_device_is_available(remote)) {
808 : : pr_debug("not available for remote node\n");
809 : 0 : of_node_put(remote);
810 : 0 : return NULL;
811 : : }
812 : :
813 : : return remote;
814 : : }
815 : : EXPORT_SYMBOL(of_graph_get_remote_node);
816 : :
817 : 0 : static struct fwnode_handle *of_fwnode_get(struct fwnode_handle *fwnode)
818 : : {
819 [ # # # # ]: 0 : return of_fwnode_handle(of_node_get(to_of_node(fwnode)));
820 : : }
821 : :
822 : 0 : static void of_fwnode_put(struct fwnode_handle *fwnode)
823 : : {
824 [ # # ]: 0 : of_node_put(to_of_node(fwnode));
825 : 0 : }
826 : :
827 : 0 : static bool of_fwnode_device_is_available(const struct fwnode_handle *fwnode)
828 : : {
829 [ # # ]: 0 : return of_device_is_available(to_of_node(fwnode));
830 : : }
831 : :
832 : 7866 : static bool of_fwnode_property_present(const struct fwnode_handle *fwnode,
833 : : const char *propname)
834 : : {
835 [ + - ]: 15732 : return of_property_read_bool(to_of_node(fwnode), propname);
836 : : }
837 : :
838 : 1242 : static int of_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
839 : : const char *propname,
840 : : unsigned int elem_size, void *val,
841 : : size_t nval)
842 : : {
843 [ + - ]: 1242 : const struct device_node *node = to_of_node(fwnode);
844 : :
845 [ - + ]: 1242 : if (!val)
846 : 0 : return of_property_count_elems_of_size(node, propname,
847 : : elem_size);
848 : :
849 [ - - + - : 1242 : switch (elem_size) {
- ]
850 : : case sizeof(u8):
851 : 0 : return of_property_read_u8_array(node, propname, val, nval);
852 : : case sizeof(u16):
853 : 0 : return of_property_read_u16_array(node, propname, val, nval);
854 : : case sizeof(u32):
855 : 1242 : return of_property_read_u32_array(node, propname, val, nval);
856 : : case sizeof(u64):
857 : 0 : return of_property_read_u64_array(node, propname, val, nval);
858 : : }
859 : :
860 : : return -ENXIO;
861 : : }
862 : :
863 : : static int
864 : 1449 : of_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
865 : : const char *propname, const char **val,
866 : : size_t nval)
867 : : {
868 [ + - ]: 1449 : const struct device_node *node = to_of_node(fwnode);
869 : :
870 : 1449 : return val ?
871 [ + + ]: 1449 : of_property_read_string_array(node, propname, val, nval) :
872 : : of_property_count_strings(node, propname);
873 : : }
874 : :
875 : : static struct fwnode_handle *
876 : 0 : of_fwnode_get_parent(const struct fwnode_handle *fwnode)
877 : : {
878 [ # # # # ]: 0 : return of_fwnode_handle(of_get_parent(to_of_node(fwnode)));
879 : : }
880 : :
881 : : static struct fwnode_handle *
882 : 1242 : of_fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
883 : : struct fwnode_handle *child)
884 : : {
885 [ + - + + : 2484 : return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode),
+ + ]
886 : : to_of_node(child)));
887 : : }
888 : :
889 : : static struct fwnode_handle *
890 : 0 : of_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
891 : : const char *childname)
892 : : {
893 [ # # ]: 0 : const struct device_node *node = to_of_node(fwnode);
894 : : struct device_node *child;
895 : :
896 [ # # ]: 0 : for_each_available_child_of_node(node, child)
897 [ # # ]: 0 : if (of_node_name_eq(child, childname))
898 [ # # ]: 0 : return of_fwnode_handle(child);
899 : :
900 : : return NULL;
901 : : }
902 : :
903 : : static int
904 : 0 : of_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
905 : : const char *prop, const char *nargs_prop,
906 : : unsigned int nargs, unsigned int index,
907 : : struct fwnode_reference_args *args)
908 : : {
909 : : struct of_phandle_args of_args;
910 : : unsigned int i;
911 : : int ret;
912 : :
913 [ # # ]: 0 : if (nargs_prop)
914 [ # # ]: 0 : ret = of_parse_phandle_with_args(to_of_node(fwnode), prop,
915 : : nargs_prop, index, &of_args);
916 : : else
917 [ # # ]: 0 : ret = of_parse_phandle_with_fixed_args(to_of_node(fwnode), prop,
918 : : nargs, index, &of_args);
919 [ # # ]: 0 : if (ret < 0)
920 : : return ret;
921 [ # # ]: 0 : if (!args)
922 : : return 0;
923 : :
924 : 0 : args->nargs = of_args.args_count;
925 [ # # ]: 0 : args->fwnode = of_fwnode_handle(of_args.np);
926 : :
927 [ # # ]: 0 : for (i = 0; i < NR_FWNODE_REFERENCE_ARGS; i++)
928 [ # # ]: 0 : args->args[i] = i < of_args.args_count ? of_args.args[i] : 0;
929 : :
930 : : return 0;
931 : : }
932 : :
933 : : static struct fwnode_handle *
934 : 0 : of_fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
935 : : struct fwnode_handle *prev)
936 : : {
937 [ # # # # : 0 : return of_fwnode_handle(of_graph_get_next_endpoint(to_of_node(fwnode),
# # ]
938 : : to_of_node(prev)));
939 : : }
940 : :
941 : : static struct fwnode_handle *
942 : 0 : of_fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
943 : : {
944 [ # # # # ]: 0 : return of_fwnode_handle(
945 : : of_graph_get_remote_endpoint(to_of_node(fwnode)));
946 : : }
947 : :
948 : : static struct fwnode_handle *
949 : 0 : of_fwnode_graph_get_port_parent(struct fwnode_handle *fwnode)
950 : : {
951 : : struct device_node *np;
952 : :
953 : : /* Get the parent of the port */
954 [ # # ]: 0 : np = of_get_parent(to_of_node(fwnode));
955 [ # # ]: 0 : if (!np)
956 : : return NULL;
957 : :
958 : : /* Is this the "ports" node? If not, it's the port parent. */
959 [ # # ]: 0 : if (!of_node_name_eq(np, "ports"))
960 [ # # ]: 0 : return of_fwnode_handle(np);
961 : :
962 [ # # ]: 0 : return of_fwnode_handle(of_get_next_parent(np));
963 : : }
964 : :
965 : 0 : static int of_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
966 : : struct fwnode_endpoint *endpoint)
967 : : {
968 [ # # ]: 0 : const struct device_node *node = to_of_node(fwnode);
969 : 0 : struct device_node *port_node = of_get_parent(node);
970 : :
971 : 0 : endpoint->local_fwnode = fwnode;
972 : :
973 : 0 : of_property_read_u32(port_node, "reg", &endpoint->port);
974 : 0 : of_property_read_u32(node, "reg", &endpoint->id);
975 : :
976 : 0 : of_node_put(port_node);
977 : :
978 : 0 : return 0;
979 : : }
980 : :
981 : : static const void *
982 : 0 : of_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
983 : : const struct device *dev)
984 : : {
985 : 0 : return of_device_get_match_data(dev);
986 : : }
987 : :
988 : : const struct fwnode_operations of_fwnode_ops = {
989 : : .get = of_fwnode_get,
990 : : .put = of_fwnode_put,
991 : : .device_is_available = of_fwnode_device_is_available,
992 : : .device_get_match_data = of_fwnode_device_get_match_data,
993 : : .property_present = of_fwnode_property_present,
994 : : .property_read_int_array = of_fwnode_property_read_int_array,
995 : : .property_read_string_array = of_fwnode_property_read_string_array,
996 : : .get_parent = of_fwnode_get_parent,
997 : : .get_next_child_node = of_fwnode_get_next_child_node,
998 : : .get_named_child_node = of_fwnode_get_named_child_node,
999 : : .get_reference_args = of_fwnode_get_reference_args,
1000 : : .graph_get_next_endpoint = of_fwnode_graph_get_next_endpoint,
1001 : : .graph_get_remote_endpoint = of_fwnode_graph_get_remote_endpoint,
1002 : : .graph_get_port_parent = of_fwnode_graph_get_port_parent,
1003 : : .graph_parse_endpoint = of_fwnode_graph_parse_endpoint,
1004 : : };
1005 : : EXPORT_SYMBOL_GPL(of_fwnode_ops);
|