]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/blame - drivers/base/property.c
device property: Fix reading pset strings using array access functions
[mirror_ubuntu-jammy-kernel.git] / drivers / base / property.c
CommitLineData
b31384fa
RW
1/*
2 * property.c - Unified device property interface.
3 *
4 * Copyright (C) 2014, Intel Corporation
5 * Authors: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
6 * Mika Westerberg <mika.westerberg@linux.intel.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 */
12
b31384fa 13#include <linux/acpi.h>
16ba08d5
RW
14#include <linux/export.h>
15#include <linux/kernel.h>
b31384fa 16#include <linux/of.h>
05ca5560 17#include <linux/of_address.h>
07bb80d4 18#include <linux/of_graph.h>
16ba08d5 19#include <linux/property.h>
4c96b7dc
JL
20#include <linux/etherdevice.h>
21#include <linux/phy.h>
16ba08d5 22
f4d05266
HK
23struct property_set {
24 struct fwnode_handle fwnode;
bec84da8 25 const struct property_entry *properties;
f4d05266
HK
26};
27
61f5e294 28static inline bool is_pset_node(struct fwnode_handle *fwnode)
16ba08d5 29{
0224a4a3 30 return !IS_ERR_OR_NULL(fwnode) && fwnode->type == FWNODE_PDATA;
16ba08d5
RW
31}
32
61f5e294 33static inline struct property_set *to_pset_node(struct fwnode_handle *fwnode)
16ba08d5 34{
61f5e294 35 return is_pset_node(fwnode) ?
16ba08d5
RW
36 container_of(fwnode, struct property_set, fwnode) : NULL;
37}
38
bec84da8
DT
39static const struct property_entry *pset_prop_get(struct property_set *pset,
40 const char *name)
16ba08d5 41{
bec84da8 42 const struct property_entry *prop;
16ba08d5
RW
43
44 if (!pset || !pset->properties)
45 return NULL;
46
47 for (prop = pset->properties; prop->name; prop++)
48 if (!strcmp(name, prop->name))
49 return prop;
50
51 return NULL;
52}
53
bec84da8
DT
54static const void *pset_prop_find(struct property_set *pset,
55 const char *propname, size_t length)
16ba08d5 56{
bec84da8
DT
57 const struct property_entry *prop;
58 const void *pointer;
16ba08d5 59
318a1971
AS
60 prop = pset_prop_get(pset, propname);
61 if (!prop)
62 return ERR_PTR(-EINVAL);
66586bab
AS
63 if (prop->is_array)
64 pointer = prop->pointer.raw_data;
65 else
66 pointer = &prop->value.raw_data;
318a1971
AS
67 if (!pointer)
68 return ERR_PTR(-ENODATA);
69 if (length > prop->length)
70 return ERR_PTR(-EOVERFLOW);
71 return pointer;
72}
73
74static int pset_prop_read_u8_array(struct property_set *pset,
75 const char *propname,
76 u8 *values, size_t nval)
77{
bec84da8 78 const void *pointer;
318a1971
AS
79 size_t length = nval * sizeof(*values);
80
81 pointer = pset_prop_find(pset, propname, length);
82 if (IS_ERR(pointer))
83 return PTR_ERR(pointer);
84
85 memcpy(values, pointer, length);
86 return 0;
87}
88
89static int pset_prop_read_u16_array(struct property_set *pset,
90 const char *propname,
91 u16 *values, size_t nval)
92{
bec84da8 93 const void *pointer;
318a1971
AS
94 size_t length = nval * sizeof(*values);
95
96 pointer = pset_prop_find(pset, propname, length);
97 if (IS_ERR(pointer))
98 return PTR_ERR(pointer);
99
100 memcpy(values, pointer, length);
101 return 0;
102}
103
104static int pset_prop_read_u32_array(struct property_set *pset,
105 const char *propname,
106 u32 *values, size_t nval)
107{
bec84da8 108 const void *pointer;
318a1971
AS
109 size_t length = nval * sizeof(*values);
110
111 pointer = pset_prop_find(pset, propname, length);
112 if (IS_ERR(pointer))
113 return PTR_ERR(pointer);
114
115 memcpy(values, pointer, length);
116 return 0;
117}
118
119static int pset_prop_read_u64_array(struct property_set *pset,
120 const char *propname,
121 u64 *values, size_t nval)
122{
bec84da8 123 const void *pointer;
318a1971
AS
124 size_t length = nval * sizeof(*values);
125
126 pointer = pset_prop_find(pset, propname, length);
127 if (IS_ERR(pointer))
128 return PTR_ERR(pointer);
129
130 memcpy(values, pointer, length);
131 return 0;
132}
133
134static int pset_prop_count_elems_of_size(struct property_set *pset,
135 const char *propname, size_t length)
136{
bec84da8 137 const struct property_entry *prop;
318a1971
AS
138
139 prop = pset_prop_get(pset, propname);
16ba08d5 140 if (!prop)
16ba08d5 141 return -EINVAL;
318a1971
AS
142
143 return prop->length / length;
144}
145
146static int pset_prop_read_string_array(struct property_set *pset,
147 const char *propname,
148 const char **strings, size_t nval)
149{
0f194992 150 const struct property_entry *prop;
bec84da8 151 const void *pointer;
0f194992
SA
152 size_t array_len, length;
153
154 /* Find out the array length. */
155 prop = pset_prop_get(pset, propname);
156 if (!prop)
157 return -EINVAL;
158
159 if (!prop->is_array)
160 /* The array length for a non-array string property is 1. */
161 array_len = 1;
162 else
163 /* Find the length of an array. */
164 array_len = pset_prop_count_elems_of_size(pset, propname,
165 sizeof(const char *));
166
167 /* Return how many there are if strings is NULL. */
168 if (!strings)
169 return array_len;
170
171 array_len = min(nval, array_len);
172 length = array_len * sizeof(*strings);
318a1971
AS
173
174 pointer = pset_prop_find(pset, propname, length);
175 if (IS_ERR(pointer))
176 return PTR_ERR(pointer);
177
178 memcpy(strings, pointer, length);
0f194992 179
16ba08d5
RW
180 return 0;
181}
b31384fa 182
66586bab
AS
183static int pset_prop_read_string(struct property_set *pset,
184 const char *propname, const char **strings)
185{
bec84da8
DT
186 const struct property_entry *prop;
187 const char * const *pointer;
66586bab
AS
188
189 prop = pset_prop_get(pset, propname);
190 if (!prop)
191 return -EINVAL;
192 if (!prop->is_string)
193 return -EILSEQ;
194 if (prop->is_array) {
195 pointer = prop->pointer.str;
196 if (!pointer)
197 return -ENODATA;
198 } else {
199 pointer = &prop->value.str;
200 if (*pointer && strnlen(*pointer, prop->length) >= prop->length)
201 return -EILSEQ;
202 }
203
204 *strings = *pointer;
205 return 0;
206}
207
e44bb0cb 208struct fwnode_handle *dev_fwnode(struct device *dev)
9017f252
RW
209{
210 return IS_ENABLED(CONFIG_OF) && dev->of_node ?
211 &dev->of_node->fwnode : dev->fwnode;
212}
e44bb0cb 213EXPORT_SYMBOL_GPL(dev_fwnode);
b31384fa
RW
214
215/**
216 * device_property_present - check if a property of a device is present
217 * @dev: Device whose property is being checked
218 * @propname: Name of the property
219 *
220 * Check if property @propname is present in the device firmware description.
221 */
222bool device_property_present(struct device *dev, const char *propname)
223{
9017f252 224 return fwnode_property_present(dev_fwnode(dev), propname);
b31384fa
RW
225}
226EXPORT_SYMBOL_GPL(device_property_present);
227
362c0b30
AS
228static bool __fwnode_property_present(struct fwnode_handle *fwnode,
229 const char *propname)
8a0662d9
RW
230{
231 if (is_of_node(fwnode))
c181fb3e 232 return of_property_read_bool(to_of_node(fwnode), propname);
8a0662d9 233 else if (is_acpi_node(fwnode))
3a7a2ab8 234 return !acpi_node_prop_get(fwnode, propname, NULL);
61f5e294
AS
235 else if (is_pset_node(fwnode))
236 return !!pset_prop_get(to_pset_node(fwnode), propname);
e3f9e299 237 return false;
8a0662d9 238}
362c0b30
AS
239
240/**
241 * fwnode_property_present - check if a property of a firmware node is present
242 * @fwnode: Firmware node whose property to check
243 * @propname: Name of the property
244 */
245bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
246{
247 bool ret;
248
249 ret = __fwnode_property_present(fwnode, propname);
0d67e0fa
HK
250 if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
251 !IS_ERR_OR_NULL(fwnode->secondary))
362c0b30
AS
252 ret = __fwnode_property_present(fwnode->secondary, propname);
253 return ret;
254}
8a0662d9
RW
255EXPORT_SYMBOL_GPL(fwnode_property_present);
256
b31384fa
RW
257/**
258 * device_property_read_u8_array - return a u8 array property of a device
259 * @dev: Device to get the property of
260 * @propname: Name of the property
5c0acf3b 261 * @val: The values are stored here or %NULL to return the number of values
b31384fa
RW
262 * @nval: Size of the @val array
263 *
264 * Function reads an array of u8 properties with @propname from the device
265 * firmware description and stores them to @val if found.
266 *
5c0acf3b
AH
267 * Return: number of values if @val was %NULL,
268 * %0 if the property was found (success),
b31384fa
RW
269 * %-EINVAL if given arguments are not valid,
270 * %-ENODATA if the property does not have a value,
271 * %-EPROTO if the property is not an array of numbers,
272 * %-EOVERFLOW if the size of the property is not as expected.
4fa7508e 273 * %-ENXIO if no suitable firmware interface is present.
b31384fa
RW
274 */
275int device_property_read_u8_array(struct device *dev, const char *propname,
276 u8 *val, size_t nval)
277{
9017f252 278 return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);
b31384fa
RW
279}
280EXPORT_SYMBOL_GPL(device_property_read_u8_array);
281
282/**
283 * device_property_read_u16_array - return a u16 array property of a device
284 * @dev: Device to get the property of
285 * @propname: Name of the property
5c0acf3b 286 * @val: The values are stored here or %NULL to return the number of values
b31384fa
RW
287 * @nval: Size of the @val array
288 *
289 * Function reads an array of u16 properties with @propname from the device
290 * firmware description and stores them to @val if found.
291 *
5c0acf3b
AH
292 * Return: number of values if @val was %NULL,
293 * %0 if the property was found (success),
b31384fa
RW
294 * %-EINVAL if given arguments are not valid,
295 * %-ENODATA if the property does not have a value,
296 * %-EPROTO if the property is not an array of numbers,
297 * %-EOVERFLOW if the size of the property is not as expected.
4fa7508e 298 * %-ENXIO if no suitable firmware interface is present.
b31384fa
RW
299 */
300int device_property_read_u16_array(struct device *dev, const char *propname,
301 u16 *val, size_t nval)
302{
9017f252 303 return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);
b31384fa
RW
304}
305EXPORT_SYMBOL_GPL(device_property_read_u16_array);
306
307/**
308 * device_property_read_u32_array - return a u32 array property of a device
309 * @dev: Device to get the property of
310 * @propname: Name of the property
5c0acf3b 311 * @val: The values are stored here or %NULL to return the number of values
b31384fa
RW
312 * @nval: Size of the @val array
313 *
314 * Function reads an array of u32 properties with @propname from the device
315 * firmware description and stores them to @val if found.
316 *
5c0acf3b
AH
317 * Return: number of values if @val was %NULL,
318 * %0 if the property was found (success),
b31384fa
RW
319 * %-EINVAL if given arguments are not valid,
320 * %-ENODATA if the property does not have a value,
321 * %-EPROTO if the property is not an array of numbers,
322 * %-EOVERFLOW if the size of the property is not as expected.
4fa7508e 323 * %-ENXIO if no suitable firmware interface is present.
b31384fa
RW
324 */
325int device_property_read_u32_array(struct device *dev, const char *propname,
326 u32 *val, size_t nval)
327{
9017f252 328 return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);
b31384fa
RW
329}
330EXPORT_SYMBOL_GPL(device_property_read_u32_array);
331
332/**
333 * device_property_read_u64_array - return a u64 array property of a device
334 * @dev: Device to get the property of
335 * @propname: Name of the property
5c0acf3b 336 * @val: The values are stored here or %NULL to return the number of values
b31384fa
RW
337 * @nval: Size of the @val array
338 *
339 * Function reads an array of u64 properties with @propname from the device
340 * firmware description and stores them to @val if found.
341 *
5c0acf3b
AH
342 * Return: number of values if @val was %NULL,
343 * %0 if the property was found (success),
b31384fa
RW
344 * %-EINVAL if given arguments are not valid,
345 * %-ENODATA if the property does not have a value,
346 * %-EPROTO if the property is not an array of numbers,
347 * %-EOVERFLOW if the size of the property is not as expected.
4fa7508e 348 * %-ENXIO if no suitable firmware interface is present.
b31384fa
RW
349 */
350int device_property_read_u64_array(struct device *dev, const char *propname,
351 u64 *val, size_t nval)
352{
9017f252 353 return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);
b31384fa
RW
354}
355EXPORT_SYMBOL_GPL(device_property_read_u64_array);
356
357/**
358 * device_property_read_string_array - return a string array property of device
359 * @dev: Device to get the property of
360 * @propname: Name of the property
5c0acf3b 361 * @val: The values are stored here or %NULL to return the number of values
b31384fa
RW
362 * @nval: Size of the @val array
363 *
364 * Function reads an array of string properties with @propname from the device
365 * firmware description and stores them to @val if found.
366 *
5c0acf3b
AH
367 * Return: number of values if @val was %NULL,
368 * %0 if the property was found (success),
b31384fa
RW
369 * %-EINVAL if given arguments are not valid,
370 * %-ENODATA if the property does not have a value,
371 * %-EPROTO or %-EILSEQ if the property is not an array of strings,
372 * %-EOVERFLOW if the size of the property is not as expected.
4fa7508e 373 * %-ENXIO if no suitable firmware interface is present.
b31384fa
RW
374 */
375int device_property_read_string_array(struct device *dev, const char *propname,
376 const char **val, size_t nval)
377{
9017f252 378 return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);
b31384fa
RW
379}
380EXPORT_SYMBOL_GPL(device_property_read_string_array);
381
382/**
383 * device_property_read_string - return a string property of a device
384 * @dev: Device to get the property of
385 * @propname: Name of the property
386 * @val: The value is stored here
387 *
388 * Function reads property @propname from the device firmware description and
389 * stores the value into @val if found. The value is checked to be a string.
390 *
391 * Return: %0 if the property was found (success),
392 * %-EINVAL if given arguments are not valid,
393 * %-ENODATA if the property does not have a value,
394 * %-EPROTO or %-EILSEQ if the property type is not a string.
4fa7508e 395 * %-ENXIO if no suitable firmware interface is present.
b31384fa
RW
396 */
397int device_property_read_string(struct device *dev, const char *propname,
398 const char **val)
399{
9017f252 400 return fwnode_property_read_string(dev_fwnode(dev), propname, val);
b31384fa
RW
401}
402EXPORT_SYMBOL_GPL(device_property_read_string);
8a0662d9 403
3f5c8d31
MW
404/**
405 * device_property_match_string - find a string in an array and return index
406 * @dev: Device to get the property of
407 * @propname: Name of the property holding the array
408 * @string: String to look for
409 *
410 * Find a given string in a string array and if it is found return the
411 * index back.
412 *
413 * Return: %0 if the property was found (success),
414 * %-EINVAL if given arguments are not valid,
415 * %-ENODATA if the property does not have a value,
416 * %-EPROTO if the property is not an array of strings,
417 * %-ENXIO if no suitable firmware interface is present.
418 */
419int device_property_match_string(struct device *dev, const char *propname,
420 const char *string)
421{
422 return fwnode_property_match_string(dev_fwnode(dev), propname, string);
423}
424EXPORT_SYMBOL_GPL(device_property_match_string);
425
1d656fb7
AS
426#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
427 (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
9017f252
RW
428 : of_property_count_elems_of_size((node), (propname), sizeof(type))
429
318a1971
AS
430#define PSET_PROP_READ_ARRAY(node, propname, type, val, nval) \
431 (val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval)) \
432 : pset_prop_count_elems_of_size((node), (propname), sizeof(type))
433
362c0b30 434#define FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
1d656fb7
AS
435({ \
436 int _ret_; \
437 if (is_of_node(_fwnode_)) \
438 _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \
439 _type_, _val_, _nval_); \
440 else if (is_acpi_node(_fwnode_)) \
441 _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \
442 _val_, _nval_); \
61f5e294 443 else if (is_pset_node(_fwnode_)) \
318a1971
AS
444 _ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_, \
445 _type_, _val_, _nval_); \
1d656fb7
AS
446 else \
447 _ret_ = -ENXIO; \
448 _ret_; \
8a0662d9
RW
449})
450
362c0b30
AS
451#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
452({ \
453 int _ret_; \
454 _ret_ = FWNODE_PROP_READ(_fwnode_, _propname_, _type_, _proptype_, \
455 _val_, _nval_); \
0d67e0fa
HK
456 if (_ret_ == -EINVAL && !IS_ERR_OR_NULL(_fwnode_) && \
457 !IS_ERR_OR_NULL(_fwnode_->secondary)) \
362c0b30
AS
458 _ret_ = FWNODE_PROP_READ(_fwnode_->secondary, _propname_, _type_, \
459 _proptype_, _val_, _nval_); \
460 _ret_; \
461})
462
8a0662d9
RW
463/**
464 * fwnode_property_read_u8_array - return a u8 array property of firmware node
465 * @fwnode: Firmware node to get the property of
466 * @propname: Name of the property
5c0acf3b 467 * @val: The values are stored here or %NULL to return the number of values
8a0662d9
RW
468 * @nval: Size of the @val array
469 *
470 * Read an array of u8 properties with @propname from @fwnode and stores them to
471 * @val if found.
472 *
5c0acf3b
AH
473 * Return: number of values if @val was %NULL,
474 * %0 if the property was found (success),
8a0662d9
RW
475 * %-EINVAL if given arguments are not valid,
476 * %-ENODATA if the property does not have a value,
477 * %-EPROTO if the property is not an array of numbers,
478 * %-EOVERFLOW if the size of the property is not as expected,
479 * %-ENXIO if no suitable firmware interface is present.
480 */
481int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
482 const char *propname, u8 *val, size_t nval)
483{
484 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
485 val, nval);
486}
487EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
488
489/**
490 * fwnode_property_read_u16_array - return a u16 array property of firmware node
491 * @fwnode: Firmware node to get the property of
492 * @propname: Name of the property
5c0acf3b 493 * @val: The values are stored here or %NULL to return the number of values
8a0662d9
RW
494 * @nval: Size of the @val array
495 *
496 * Read an array of u16 properties with @propname from @fwnode and store them to
497 * @val if found.
498 *
5c0acf3b
AH
499 * Return: number of values if @val was %NULL,
500 * %0 if the property was found (success),
8a0662d9
RW
501 * %-EINVAL if given arguments are not valid,
502 * %-ENODATA if the property does not have a value,
503 * %-EPROTO if the property is not an array of numbers,
504 * %-EOVERFLOW if the size of the property is not as expected,
505 * %-ENXIO if no suitable firmware interface is present.
506 */
507int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
508 const char *propname, u16 *val, size_t nval)
509{
510 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
511 val, nval);
512}
513EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
514
515/**
516 * fwnode_property_read_u32_array - return a u32 array property of firmware node
517 * @fwnode: Firmware node to get the property of
518 * @propname: Name of the property
5c0acf3b 519 * @val: The values are stored here or %NULL to return the number of values
8a0662d9
RW
520 * @nval: Size of the @val array
521 *
522 * Read an array of u32 properties with @propname from @fwnode store them to
523 * @val if found.
524 *
5c0acf3b
AH
525 * Return: number of values if @val was %NULL,
526 * %0 if the property was found (success),
8a0662d9
RW
527 * %-EINVAL if given arguments are not valid,
528 * %-ENODATA if the property does not have a value,
529 * %-EPROTO if the property is not an array of numbers,
530 * %-EOVERFLOW if the size of the property is not as expected,
531 * %-ENXIO if no suitable firmware interface is present.
532 */
533int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
534 const char *propname, u32 *val, size_t nval)
535{
536 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
537 val, nval);
538}
539EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
540
541/**
542 * fwnode_property_read_u64_array - return a u64 array property firmware node
543 * @fwnode: Firmware node to get the property of
544 * @propname: Name of the property
5c0acf3b 545 * @val: The values are stored here or %NULL to return the number of values
8a0662d9
RW
546 * @nval: Size of the @val array
547 *
548 * Read an array of u64 properties with @propname from @fwnode and store them to
549 * @val if found.
550 *
5c0acf3b
AH
551 * Return: number of values if @val was %NULL,
552 * %0 if the property was found (success),
8a0662d9
RW
553 * %-EINVAL if given arguments are not valid,
554 * %-ENODATA if the property does not have a value,
555 * %-EPROTO if the property is not an array of numbers,
556 * %-EOVERFLOW if the size of the property is not as expected,
557 * %-ENXIO if no suitable firmware interface is present.
558 */
559int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
560 const char *propname, u64 *val, size_t nval)
561{
562 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
563 val, nval);
564}
565EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
566
362c0b30
AS
567static int __fwnode_property_read_string_array(struct fwnode_handle *fwnode,
568 const char *propname,
569 const char **val, size_t nval)
570{
571 if (is_of_node(fwnode))
572 return val ?
573 of_property_read_string_array(to_of_node(fwnode),
574 propname, val, nval) :
575 of_property_count_strings(to_of_node(fwnode), propname);
576 else if (is_acpi_node(fwnode))
577 return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
578 val, nval);
579 else if (is_pset_node(fwnode))
0f194992
SA
580 return pset_prop_read_string_array(to_pset_node(fwnode),
581 propname, val, nval);
362c0b30
AS
582 return -ENXIO;
583}
584
585static int __fwnode_property_read_string(struct fwnode_handle *fwnode,
586 const char *propname, const char **val)
587{
588 if (is_of_node(fwnode))
589 return of_property_read_string(to_of_node(fwnode), propname, val);
590 else if (is_acpi_node(fwnode))
591 return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
592 val, 1);
593 else if (is_pset_node(fwnode))
594 return pset_prop_read_string(to_pset_node(fwnode), propname, val);
595 return -ENXIO;
596}
597
8a0662d9
RW
598/**
599 * fwnode_property_read_string_array - return string array property of a node
600 * @fwnode: Firmware node to get the property of
601 * @propname: Name of the property
5c0acf3b 602 * @val: The values are stored here or %NULL to return the number of values
8a0662d9
RW
603 * @nval: Size of the @val array
604 *
605 * Read an string list property @propname from the given firmware node and store
606 * them to @val if found.
607 *
5c0acf3b
AH
608 * Return: number of values if @val was %NULL,
609 * %0 if the property was found (success),
8a0662d9
RW
610 * %-EINVAL if given arguments are not valid,
611 * %-ENODATA if the property does not have a value,
026b8217 612 * %-EPROTO or %-EILSEQ if the property is not an array of strings,
8a0662d9
RW
613 * %-EOVERFLOW if the size of the property is not as expected,
614 * %-ENXIO if no suitable firmware interface is present.
615 */
616int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
617 const char *propname, const char **val,
618 size_t nval)
619{
362c0b30
AS
620 int ret;
621
622 ret = __fwnode_property_read_string_array(fwnode, propname, val, nval);
0d67e0fa
HK
623 if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
624 !IS_ERR_OR_NULL(fwnode->secondary))
362c0b30
AS
625 ret = __fwnode_property_read_string_array(fwnode->secondary,
626 propname, val, nval);
627 return ret;
8a0662d9
RW
628}
629EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
630
631/**
632 * fwnode_property_read_string - return a string property of a firmware node
633 * @fwnode: Firmware node to get the property of
634 * @propname: Name of the property
635 * @val: The value is stored here
636 *
637 * Read property @propname from the given firmware node and store the value into
638 * @val if found. The value is checked to be a string.
639 *
640 * Return: %0 if the property was found (success),
641 * %-EINVAL if given arguments are not valid,
642 * %-ENODATA if the property does not have a value,
643 * %-EPROTO or %-EILSEQ if the property is not a string,
644 * %-ENXIO if no suitable firmware interface is present.
645 */
646int fwnode_property_read_string(struct fwnode_handle *fwnode,
647 const char *propname, const char **val)
648{
362c0b30
AS
649 int ret;
650
651 ret = __fwnode_property_read_string(fwnode, propname, val);
0d67e0fa
HK
652 if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
653 !IS_ERR_OR_NULL(fwnode->secondary))
362c0b30
AS
654 ret = __fwnode_property_read_string(fwnode->secondary,
655 propname, val);
656 return ret;
8a0662d9
RW
657}
658EXPORT_SYMBOL_GPL(fwnode_property_read_string);
659
3f5c8d31
MW
660/**
661 * fwnode_property_match_string - find a string in an array and return index
662 * @fwnode: Firmware node to get the property of
663 * @propname: Name of the property holding the array
664 * @string: String to look for
665 *
666 * Find a given string in a string array and if it is found return the
667 * index back.
668 *
669 * Return: %0 if the property was found (success),
670 * %-EINVAL if given arguments are not valid,
671 * %-ENODATA if the property does not have a value,
672 * %-EPROTO if the property is not an array of strings,
673 * %-ENXIO if no suitable firmware interface is present.
674 */
675int fwnode_property_match_string(struct fwnode_handle *fwnode,
676 const char *propname, const char *string)
677{
678 const char **values;
a7c1d0a9 679 int nval, ret;
3f5c8d31
MW
680
681 nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0);
682 if (nval < 0)
683 return nval;
684
f6740c18
AS
685 if (nval == 0)
686 return -ENODATA;
687
3f5c8d31
MW
688 values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
689 if (!values)
690 return -ENOMEM;
691
692 ret = fwnode_property_read_string_array(fwnode, propname, values, nval);
693 if (ret < 0)
694 goto out;
695
a7c1d0a9
AS
696 ret = match_string(values, nval, string);
697 if (ret < 0)
698 ret = -ENODATA;
3f5c8d31
MW
699out:
700 kfree(values);
701 return ret;
702}
703EXPORT_SYMBOL_GPL(fwnode_property_match_string);
704
2d479e1f
DT
705static int property_copy_string_array(struct property_entry *dst,
706 const struct property_entry *src)
13141e1c 707{
2d479e1f
DT
708 char **d;
709 size_t nval = src->length / sizeof(*d);
710 int i;
13141e1c 711
2d479e1f
DT
712 d = kcalloc(nval, sizeof(*d), GFP_KERNEL);
713 if (!d)
714 return -ENOMEM;
13141e1c 715
2d479e1f
DT
716 for (i = 0; i < nval; i++) {
717 d[i] = kstrdup(src->pointer.str[i], GFP_KERNEL);
718 if (!d[i] && src->pointer.str[i]) {
719 while (--i >= 0)
720 kfree(d[i]);
721 kfree(d);
722 return -ENOMEM;
13141e1c 723 }
13141e1c
MW
724 }
725
2d479e1f
DT
726 dst->pointer.raw_data = d;
727 return 0;
13141e1c
MW
728}
729
2d479e1f
DT
730static int property_entry_copy_data(struct property_entry *dst,
731 const struct property_entry *src)
13141e1c 732{
2d479e1f 733 int error;
13141e1c
MW
734
735 dst->name = kstrdup(src->name, GFP_KERNEL);
736 if (!dst->name)
737 return -ENOMEM;
738
739 if (src->is_array) {
2d479e1f
DT
740 if (!src->length) {
741 error = -ENODATA;
742 goto out_free_name;
743 }
f6740c18 744
13141e1c 745 if (src->is_string) {
2d479e1f
DT
746 error = property_copy_string_array(dst, src);
747 if (error)
748 goto out_free_name;
13141e1c
MW
749 } else {
750 dst->pointer.raw_data = kmemdup(src->pointer.raw_data,
751 src->length, GFP_KERNEL);
2d479e1f
DT
752 if (!dst->pointer.raw_data) {
753 error = -ENOMEM;
754 goto out_free_name;
755 }
13141e1c
MW
756 }
757 } else if (src->is_string) {
758 dst->value.str = kstrdup(src->value.str, GFP_KERNEL);
2d479e1f
DT
759 if (!dst->value.str && src->value.str) {
760 error = -ENOMEM;
761 goto out_free_name;
762 }
13141e1c
MW
763 } else {
764 dst->value.raw_data = src->value.raw_data;
765 }
766
767 dst->length = src->length;
768 dst->is_array = src->is_array;
769 dst->is_string = src->is_string;
770
771 return 0;
2d479e1f
DT
772
773out_free_name:
774 kfree(dst->name);
775 return error;
776}
777
778static void property_entry_free_data(const struct property_entry *p)
779{
780 size_t i, nval;
781
782 if (p->is_array) {
783 if (p->is_string && p->pointer.str) {
784 nval = p->length / sizeof(const char *);
785 for (i = 0; i < nval; i++)
786 kfree(p->pointer.str[i]);
787 }
788 kfree(p->pointer.raw_data);
789 } else if (p->is_string) {
790 kfree(p->value.str);
791 }
792 kfree(p->name);
793}
794
795/**
796 * property_entries_dup - duplicate array of properties
797 * @properties: array of properties to copy
798 *
799 * This function creates a deep copy of the given NULL-terminated array
800 * of property entries.
801 */
802struct property_entry *
803property_entries_dup(const struct property_entry *properties)
804{
805 struct property_entry *p;
806 int i, n = 0;
807
808 while (properties[n].name)
809 n++;
810
811 p = kcalloc(n + 1, sizeof(*p), GFP_KERNEL);
812 if (!p)
813 return ERR_PTR(-ENOMEM);
814
815 for (i = 0; i < n; i++) {
816 int ret = property_entry_copy_data(&p[i], &properties[i]);
817 if (ret) {
818 while (--i >= 0)
819 property_entry_free_data(&p[i]);
820 kfree(p);
821 return ERR_PTR(ret);
822 }
823 }
824
825 return p;
826}
827EXPORT_SYMBOL_GPL(property_entries_dup);
828
829/**
830 * property_entries_free - free previously allocated array of properties
831 * @properties: array of properties to destroy
832 *
833 * This function frees given NULL-terminated array of property entries,
834 * along with their data.
835 */
836void property_entries_free(const struct property_entry *properties)
837{
838 const struct property_entry *p;
839
840 for (p = properties; p->name; p++)
841 property_entry_free_data(p);
842
843 kfree(properties);
844}
845EXPORT_SYMBOL_GPL(property_entries_free);
846
847/**
848 * pset_free_set - releases memory allocated for copied property set
849 * @pset: Property set to release
850 *
851 * Function takes previously copied property set and releases all the
852 * memory allocated to it.
853 */
854static void pset_free_set(struct property_set *pset)
855{
856 if (!pset)
857 return;
858
859 property_entries_free(pset->properties);
860 kfree(pset);
13141e1c
MW
861}
862
863/**
864 * pset_copy_set - copies property set
865 * @pset: Property set to copy
866 *
867 * This function takes a deep copy of the given property set and returns
868 * pointer to the copy. Call device_free_property_set() to free resources
869 * allocated in this function.
870 *
871 * Return: Pointer to the new property set or error pointer.
872 */
873static struct property_set *pset_copy_set(const struct property_set *pset)
874{
2d479e1f 875 struct property_entry *properties;
13141e1c 876 struct property_set *p;
13141e1c
MW
877
878 p = kzalloc(sizeof(*p), GFP_KERNEL);
879 if (!p)
880 return ERR_PTR(-ENOMEM);
881
2d479e1f
DT
882 properties = property_entries_dup(pset->properties);
883 if (IS_ERR(properties)) {
13141e1c 884 kfree(p);
2d479e1f 885 return ERR_CAST(properties);
13141e1c
MW
886 }
887
2d479e1f 888 p->properties = properties;
13141e1c
MW
889 return p;
890}
891
892/**
f4d05266 893 * device_remove_properties - Remove properties from a device object.
13141e1c
MW
894 * @dev: Device whose properties to remove.
895 *
896 * The function removes properties previously associated to the device
f4d05266 897 * secondary firmware node with device_add_properties(). Memory allocated
13141e1c
MW
898 * to the properties will also be released.
899 */
f4d05266 900void device_remove_properties(struct device *dev)
13141e1c
MW
901{
902 struct fwnode_handle *fwnode;
903
904 fwnode = dev_fwnode(dev);
905 if (!fwnode)
906 return;
907 /*
908 * Pick either primary or secondary node depending which one holds
909 * the pset. If there is no real firmware node (ACPI/DT) primary
910 * will hold the pset.
911 */
0d67e0fa
HK
912 if (is_pset_node(fwnode)) {
913 set_primary_fwnode(dev, NULL);
13141e1c 914 pset_free_set(to_pset_node(fwnode));
0d67e0fa
HK
915 } else {
916 fwnode = fwnode->secondary;
917 if (!IS_ERR(fwnode) && is_pset_node(fwnode)) {
918 set_secondary_fwnode(dev, NULL);
919 pset_free_set(to_pset_node(fwnode));
920 }
921 }
13141e1c 922}
f4d05266 923EXPORT_SYMBOL_GPL(device_remove_properties);
13141e1c
MW
924
925/**
f4d05266 926 * device_add_properties - Add a collection of properties to a device object.
13141e1c 927 * @dev: Device to add properties to.
f4d05266 928 * @properties: Collection of properties to add.
13141e1c 929 *
f4d05266
HK
930 * Associate a collection of device properties represented by @properties with
931 * @dev as its secondary firmware node. The function takes a copy of
932 * @properties.
13141e1c 933 */
bec84da8
DT
934int device_add_properties(struct device *dev,
935 const struct property_entry *properties)
13141e1c 936{
f4d05266 937 struct property_set *p, pset;
13141e1c 938
f4d05266 939 if (!properties)
13141e1c
MW
940 return -EINVAL;
941
f4d05266
HK
942 pset.properties = properties;
943
944 p = pset_copy_set(&pset);
13141e1c
MW
945 if (IS_ERR(p))
946 return PTR_ERR(p);
947
948 p->fwnode.type = FWNODE_PDATA;
949 set_secondary_fwnode(dev, &p->fwnode);
950 return 0;
951}
f4d05266 952EXPORT_SYMBOL_GPL(device_add_properties);
13141e1c 953
23387258
SA
954/**
955 * fwnode_get_next_parent - Iterate to the node's parent
956 * @fwnode: Firmware whose parent is retrieved
957 *
958 * This is like fwnode_get_parent() except that it drops the refcount
959 * on the passed node, making it suitable for iterating through a
960 * node's parents.
961 *
962 * Returns a node pointer with refcount incremented, use
963 * fwnode_handle_node() on it when done.
964 */
965struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode)
966{
967 struct fwnode_handle *parent = fwnode_get_parent(fwnode);
968
969 fwnode_handle_put(fwnode);
970
971 return parent;
972}
973EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
974
afaf26fd
MW
975/**
976 * fwnode_get_parent - Return parent firwmare node
977 * @fwnode: Firmware whose parent is retrieved
978 *
979 * Return parent firmware node of the given node if possible or %NULL if no
980 * parent was available.
981 */
982struct fwnode_handle *fwnode_get_parent(struct fwnode_handle *fwnode)
983{
984 struct fwnode_handle *parent = NULL;
985
986 if (is_of_node(fwnode)) {
987 struct device_node *node;
988
989 node = of_get_parent(to_of_node(fwnode));
990 if (node)
991 parent = &node->fwnode;
992 } else if (is_acpi_node(fwnode)) {
993 parent = acpi_node_get_parent(fwnode);
994 }
995
996 return parent;
997}
998EXPORT_SYMBOL_GPL(fwnode_get_parent);
999
8a0662d9 1000/**
34055190
MW
1001 * fwnode_get_next_child_node - Return the next child node handle for a node
1002 * @fwnode: Firmware node to find the next child node for.
1003 * @child: Handle to one of the node's child nodes or a %NULL handle.
8a0662d9 1004 */
34055190 1005struct fwnode_handle *fwnode_get_next_child_node(struct fwnode_handle *fwnode,
8a0662d9
RW
1006 struct fwnode_handle *child)
1007{
34055190 1008 if (is_of_node(fwnode)) {
8a0662d9
RW
1009 struct device_node *node;
1010
34055190
MW
1011 node = of_get_next_available_child(to_of_node(fwnode),
1012 to_of_node(child));
8a0662d9
RW
1013 if (node)
1014 return &node->fwnode;
34055190
MW
1015 } else if (is_acpi_node(fwnode)) {
1016 return acpi_get_next_subnode(fwnode, child);
8a0662d9 1017 }
34055190 1018
8a0662d9
RW
1019 return NULL;
1020}
34055190
MW
1021EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
1022
1023/**
1024 * device_get_next_child_node - Return the next child node handle for a device
1025 * @dev: Device to find the next child node for.
1026 * @child: Handle to one of the device's child nodes or a null handle.
1027 */
1028struct fwnode_handle *device_get_next_child_node(struct device *dev,
1029 struct fwnode_handle *child)
1030{
1031 struct acpi_device *adev = ACPI_COMPANION(dev);
1032 struct fwnode_handle *fwnode = NULL;
1033
1034 if (dev->of_node)
1035 fwnode = &dev->of_node->fwnode;
1036 else if (adev)
1037 fwnode = acpi_fwnode_handle(adev);
1038
1039 return fwnode_get_next_child_node(fwnode, child);
1040}
8a0662d9
RW
1041EXPORT_SYMBOL_GPL(device_get_next_child_node);
1042
613e9721 1043/**
21ea73f5
MW
1044 * fwnode_get_named_child_node - Return first matching named child node handle
1045 * @fwnode: Firmware node to find the named child node for.
613e9721
AT
1046 * @childname: String to match child node name against.
1047 */
21ea73f5 1048struct fwnode_handle *fwnode_get_named_child_node(struct fwnode_handle *fwnode,
613e9721
AT
1049 const char *childname)
1050{
1051 struct fwnode_handle *child;
1052
1053 /*
21ea73f5 1054 * Find first matching named child node of this fwnode.
613e9721
AT
1055 * For ACPI this will be a data only sub-node.
1056 */
21ea73f5 1057 fwnode_for_each_child_node(fwnode, child) {
613e9721
AT
1058 if (is_of_node(child)) {
1059 if (!of_node_cmp(to_of_node(child)->name, childname))
1060 return child;
1061 } else if (is_acpi_data_node(child)) {
1062 if (acpi_data_node_match(child, childname))
1063 return child;
1064 }
1065 }
1066
1067 return NULL;
1068}
21ea73f5
MW
1069EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
1070
1071/**
1072 * device_get_named_child_node - Return first matching named child node handle
1073 * @dev: Device to find the named child node for.
1074 * @childname: String to match child node name against.
1075 */
1076struct fwnode_handle *device_get_named_child_node(struct device *dev,
1077 const char *childname)
1078{
1079 return fwnode_get_named_child_node(dev_fwnode(dev), childname);
1080}
613e9721
AT
1081EXPORT_SYMBOL_GPL(device_get_named_child_node);
1082
e7887c28
SA
1083/**
1084 * fwnode_handle_get - Obtain a reference to a device node
1085 * @fwnode: Pointer to the device node to obtain the reference to.
1086 */
1087void fwnode_handle_get(struct fwnode_handle *fwnode)
1088{
1089 if (is_of_node(fwnode))
1090 of_node_get(to_of_node(fwnode));
1091}
1092EXPORT_SYMBOL_GPL(fwnode_handle_get);
1093
8a0662d9
RW
1094/**
1095 * fwnode_handle_put - Drop reference to a device node
1096 * @fwnode: Pointer to the device node to drop the reference to.
1097 *
1098 * This has to be used when terminating device_for_each_child_node() iteration
1099 * with break or return to prevent stale device node references from being left
1100 * behind.
1101 */
1102void fwnode_handle_put(struct fwnode_handle *fwnode)
1103{
1104 if (is_of_node(fwnode))
c181fb3e 1105 of_node_put(to_of_node(fwnode));
8a0662d9
RW
1106}
1107EXPORT_SYMBOL_GPL(fwnode_handle_put);
1108
1109/**
1110 * device_get_child_node_count - return the number of child nodes for device
1111 * @dev: Device to cound the child nodes for
1112 */
1113unsigned int device_get_child_node_count(struct device *dev)
1114{
1115 struct fwnode_handle *child;
1116 unsigned int count = 0;
1117
1118 device_for_each_child_node(dev, child)
1119 count++;
1120
1121 return count;
1122}
1123EXPORT_SYMBOL_GPL(device_get_child_node_count);
05ca5560 1124
e5e55864
SS
1125bool device_dma_supported(struct device *dev)
1126{
1127 /* For DT, this is always supported.
1128 * For ACPI, this depends on CCA, which
1129 * is determined by the acpi_dma_supported().
1130 */
1131 if (IS_ENABLED(CONFIG_OF) && dev->of_node)
1132 return true;
1133
1134 return acpi_dma_supported(ACPI_COMPANION(dev));
1135}
1136EXPORT_SYMBOL_GPL(device_dma_supported);
1137
1138enum dev_dma_attr device_get_dma_attr(struct device *dev)
1139{
1140 enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED;
1141
1142 if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
1143 if (of_dma_is_coherent(dev->of_node))
1144 attr = DEV_DMA_COHERENT;
1145 else
1146 attr = DEV_DMA_NON_COHERENT;
1147 } else
1148 attr = acpi_get_dma_attr(ACPI_COMPANION(dev));
1149
1150 return attr;
1151}
1152EXPORT_SYMBOL_GPL(device_get_dma_attr);
1153
4c96b7dc 1154/**
2f710a3a 1155 * device_get_phy_mode - Get phy mode for given device
4c96b7dc
JL
1156 * @dev: Pointer to the given device
1157 *
1158 * The function gets phy interface string from property 'phy-mode' or
1159 * 'phy-connection-type', and return its index in phy_modes table, or errno in
1160 * error case.
1161 */
1162int device_get_phy_mode(struct device *dev)
1163{
1164 const char *pm;
1165 int err, i;
1166
1167 err = device_property_read_string(dev, "phy-mode", &pm);
1168 if (err < 0)
1169 err = device_property_read_string(dev,
1170 "phy-connection-type", &pm);
1171 if (err < 0)
1172 return err;
1173
1174 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
1175 if (!strcasecmp(pm, phy_modes(i)))
1176 return i;
1177
1178 return -ENODEV;
1179}
1180EXPORT_SYMBOL_GPL(device_get_phy_mode);
1181
1182static void *device_get_mac_addr(struct device *dev,
1183 const char *name, char *addr,
1184 int alen)
1185{
1186 int ret = device_property_read_u8_array(dev, name, addr, alen);
1187
2f710a3a 1188 if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr))
4c96b7dc
JL
1189 return addr;
1190 return NULL;
1191}
1192
1193/**
2f710a3a
JL
1194 * device_get_mac_address - Get the MAC for a given device
1195 * @dev: Pointer to the device
1196 * @addr: Address of buffer to store the MAC in
1197 * @alen: Length of the buffer pointed to by addr, should be ETH_ALEN
1198 *
1199 * Search the firmware node for the best MAC address to use. 'mac-address' is
4c96b7dc
JL
1200 * checked first, because that is supposed to contain to "most recent" MAC
1201 * address. If that isn't set, then 'local-mac-address' is checked next,
1202 * because that is the default address. If that isn't set, then the obsolete
1203 * 'address' is checked, just in case we're using an old device tree.
1204 *
1205 * Note that the 'address' property is supposed to contain a virtual address of
1206 * the register set, but some DTS files have redefined that property to be the
1207 * MAC address.
1208 *
1209 * All-zero MAC addresses are rejected, because those could be properties that
2f710a3a
JL
1210 * exist in the firmware tables, but were not updated by the firmware. For
1211 * example, the DTS could define 'mac-address' and 'local-mac-address', with
1212 * zero MAC addresses. Some older U-Boots only initialized 'local-mac-address'.
1213 * In this case, the real MAC is in 'local-mac-address', and 'mac-address'
1214 * exists but is all zeros.
4c96b7dc
JL
1215*/
1216void *device_get_mac_address(struct device *dev, char *addr, int alen)
1217{
5b902d6f 1218 char *res;
4c96b7dc 1219
5b902d6f
JG
1220 res = device_get_mac_addr(dev, "mac-address", addr, alen);
1221 if (res)
1222 return res;
1223
1224 res = device_get_mac_addr(dev, "local-mac-address", addr, alen);
1225 if (res)
1226 return res;
4c96b7dc
JL
1227
1228 return device_get_mac_addr(dev, "address", addr, alen);
1229}
1230EXPORT_SYMBOL(device_get_mac_address);
07bb80d4
MW
1231
1232/**
1233 * device_graph_get_next_endpoint - Get next endpoint firmware node
1234 * @fwnode: Pointer to the parent firmware node
1235 * @prev: Previous endpoint node or %NULL to get the first
1236 *
1237 * Returns an endpoint firmware node pointer or %NULL if no more endpoints
1238 * are available.
1239 */
1240struct fwnode_handle *
1241fwnode_graph_get_next_endpoint(struct fwnode_handle *fwnode,
1242 struct fwnode_handle *prev)
1243{
1244 struct fwnode_handle *endpoint = NULL;
1245
1246 if (is_of_node(fwnode)) {
1247 struct device_node *node;
1248
1249 node = of_graph_get_next_endpoint(to_of_node(fwnode),
1250 to_of_node(prev));
1251
1252 if (node)
1253 endpoint = &node->fwnode;
1254 } else if (is_acpi_node(fwnode)) {
1255 endpoint = acpi_graph_get_next_endpoint(fwnode, prev);
1256 if (IS_ERR(endpoint))
1257 endpoint = NULL;
1258 }
1259
1260 return endpoint;
1261
1262}
1263EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
1264
1265/**
1266 * fwnode_graph_get_remote_port_parent - Return fwnode of a remote device
1267 * @fwnode: Endpoint firmware node pointing to the remote endpoint
1268 *
1269 * Extracts firmware node of a remote device the @fwnode points to.
1270 */
1271struct fwnode_handle *
1272fwnode_graph_get_remote_port_parent(struct fwnode_handle *fwnode)
1273{
1274 struct fwnode_handle *parent = NULL;
1275
1276 if (is_of_node(fwnode)) {
1277 struct device_node *node;
1278
1279 node = of_graph_get_remote_port_parent(to_of_node(fwnode));
1280 if (node)
1281 parent = &node->fwnode;
1282 } else if (is_acpi_node(fwnode)) {
1283 int ret;
1284
1285 ret = acpi_graph_get_remote_endpoint(fwnode, &parent, NULL,
1286 NULL);
1287 if (ret)
1288 return NULL;
1289 }
1290
1291 return parent;
1292}
1293EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
1294
1295/**
1296 * fwnode_graph_get_remote_port - Return fwnode of a remote port
1297 * @fwnode: Endpoint firmware node pointing to the remote endpoint
1298 *
1299 * Extracts firmware node of a remote port the @fwnode points to.
1300 */
1301struct fwnode_handle *fwnode_graph_get_remote_port(struct fwnode_handle *fwnode)
1302{
1303 struct fwnode_handle *port = NULL;
1304
1305 if (is_of_node(fwnode)) {
1306 struct device_node *node;
1307
1308 node = of_graph_get_remote_port(to_of_node(fwnode));
1309 if (node)
1310 port = &node->fwnode;
1311 } else if (is_acpi_node(fwnode)) {
1312 int ret;
1313
1314 ret = acpi_graph_get_remote_endpoint(fwnode, NULL, &port, NULL);
1315 if (ret)
1316 return NULL;
1317 }
1318
1319 return port;
1320}
1321EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
1322
1323/**
1324 * fwnode_graph_get_remote_endpoint - Return fwnode of a remote endpoint
1325 * @fwnode: Endpoint firmware node pointing to the remote endpoint
1326 *
1327 * Extracts firmware node of a remote endpoint the @fwnode points to.
1328 */
1329struct fwnode_handle *
1330fwnode_graph_get_remote_endpoint(struct fwnode_handle *fwnode)
1331{
1332 struct fwnode_handle *endpoint = NULL;
1333
1334 if (is_of_node(fwnode)) {
1335 struct device_node *node;
1336
1337 node = of_parse_phandle(to_of_node(fwnode), "remote-endpoint",
1338 0);
1339 if (node)
1340 endpoint = &node->fwnode;
1341 } else if (is_acpi_node(fwnode)) {
1342 int ret;
1343
1344 ret = acpi_graph_get_remote_endpoint(fwnode, NULL, NULL,
1345 &endpoint);
1346 if (ret)
1347 return NULL;
1348 }
1349
1350 return endpoint;
1351}
1352EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
2bd5452d
SA
1353
1354/**
1355 * fwnode_graph_parse_endpoint - parse common endpoint node properties
1356 * @fwnode: pointer to endpoint fwnode_handle
1357 * @endpoint: pointer to the fwnode endpoint data structure
1358 *
1359 * Parse @fwnode representing a graph endpoint node and store the
1360 * information in @endpoint. The caller must hold a reference to
1361 * @fwnode.
1362 */
1363int fwnode_graph_parse_endpoint(struct fwnode_handle *fwnode,
1364 struct fwnode_endpoint *endpoint)
1365{
1366 struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
1367
1368 memset(endpoint, 0, sizeof(*endpoint));
1369
1370 endpoint->local_fwnode = fwnode;
1371
1372 if (is_acpi_node(port_fwnode)) {
1373 fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
1374 fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
1375 } else {
1376 fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port);
1377 fwnode_property_read_u32(fwnode, "reg", &endpoint->id);
1378 }
1379
1380 fwnode_handle_put(port_fwnode);
1381
1382 return 0;
1383}
1384EXPORT_SYMBOL(fwnode_graph_parse_endpoint);