summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/scan.c21
-rw-r--r--drivers/base/property.c246
-rw-r--r--include/acpi/acpi_bus.h17
-rw-r--r--include/linux/acpi.h26
-rw-r--r--include/linux/of.h22
-rw-r--r--include/linux/property.h70
6 files changed, 402 insertions, 0 deletions
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 3a8f66444532..9cb5cca3cfe3 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -1389,6 +1389,26 @@ int acpi_device_add(struct acpi_device *device,
1389 return result; 1389 return result;
1390} 1390}
1391 1391
1392struct acpi_device *acpi_get_next_child(struct device *dev,
1393 struct acpi_device *child)
1394{
1395 struct acpi_device *adev = ACPI_COMPANION(dev);
1396 struct list_head *head, *next;
1397
1398 if (!adev)
1399 return NULL;
1400
1401 head = &adev->children;
1402 if (list_empty(head))
1403 return NULL;
1404
1405 if (!child)
1406 return list_first_entry(head, struct acpi_device, node);
1407
1408 next = child->node.next;
1409 return next == head ? NULL : list_entry(next, struct acpi_device, node);
1410}
1411
1392/* -------------------------------------------------------------------------- 1412/* --------------------------------------------------------------------------
1393 Driver Management 1413 Driver Management
1394 -------------------------------------------------------------------------- */ 1414 -------------------------------------------------------------------------- */
@@ -2008,6 +2028,7 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle,
2008 device->device_type = type; 2028 device->device_type = type;
2009 device->handle = handle; 2029 device->handle = handle;
2010 device->parent = acpi_bus_get_parent(handle); 2030 device->parent = acpi_bus_get_parent(handle);
2031 device->fwnode.type = FWNODE_ACPI;
2011 acpi_set_device_status(device, sta); 2032 acpi_set_device_status(device, sta);
2012 acpi_device_get_busid(device); 2033 acpi_device_get_busid(device);
2013 acpi_set_pnp_ids(handle, &device->pnp, type); 2034 acpi_set_pnp_ids(handle, &device->pnp, type);
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 6a94ef6e83c9..c45845874d4f 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -31,6 +31,22 @@ bool device_property_present(struct device *dev, const char *propname)
31} 31}
32EXPORT_SYMBOL_GPL(device_property_present); 32EXPORT_SYMBOL_GPL(device_property_present);
33 33
34/**
35 * fwnode_property_present - check if a property of a firmware node is present
36 * @fwnode: Firmware node whose property to check
37 * @propname: Name of the property
38 */
39bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
40{
41 if (is_of_node(fwnode))
42 return of_property_read_bool(of_node(fwnode), propname);
43 else if (is_acpi_node(fwnode))
44 return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
45
46 return false;
47}
48EXPORT_SYMBOL_GPL(fwnode_property_present);
49
34#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ 50#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
35 (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ 51 (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
36 : of_property_count_elems_of_size((node), (propname), sizeof(type)) 52 : of_property_count_elems_of_size((node), (propname), sizeof(type))
@@ -183,3 +199,233 @@ int device_property_read_string(struct device *dev, const char *propname,
183 DEV_PROP_STRING, val, 1); 199 DEV_PROP_STRING, val, 1);
184} 200}
185EXPORT_SYMBOL_GPL(device_property_read_string); 201EXPORT_SYMBOL_GPL(device_property_read_string);
202
203#define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \
204({ \
205 int _ret_; \
206 if (is_of_node(_fwnode_)) \
207 _ret_ = OF_DEV_PROP_READ_ARRAY(of_node(_fwnode_), _propname_, \
208 _type_, _val_, _nval_); \
209 else if (is_acpi_node(_fwnode_)) \
210 _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \
211 _proptype_, _val_, _nval_); \
212 else \
213 _ret_ = -ENXIO; \
214 _ret_; \
215})
216
217/**
218 * fwnode_property_read_u8_array - return a u8 array property of firmware node
219 * @fwnode: Firmware node to get the property of
220 * @propname: Name of the property
221 * @val: The values are stored here
222 * @nval: Size of the @val array
223 *
224 * Read an array of u8 properties with @propname from @fwnode and stores them to
225 * @val if found.
226 *
227 * Return: %0 if the property was found (success),
228 * %-EINVAL if given arguments are not valid,
229 * %-ENODATA if the property does not have a value,
230 * %-EPROTO if the property is not an array of numbers,
231 * %-EOVERFLOW if the size of the property is not as expected,
232 * %-ENXIO if no suitable firmware interface is present.
233 */
234int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
235 const char *propname, u8 *val, size_t nval)
236{
237 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8,
238 val, nval);
239}
240EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
241
242/**
243 * fwnode_property_read_u16_array - return a u16 array property of firmware node
244 * @fwnode: Firmware node to get the property of
245 * @propname: Name of the property
246 * @val: The values are stored here
247 * @nval: Size of the @val array
248 *
249 * Read an array of u16 properties with @propname from @fwnode and store them to
250 * @val if found.
251 *
252 * Return: %0 if the property was found (success),
253 * %-EINVAL if given arguments are not valid,
254 * %-ENODATA if the property does not have a value,
255 * %-EPROTO if the property is not an array of numbers,
256 * %-EOVERFLOW if the size of the property is not as expected,
257 * %-ENXIO if no suitable firmware interface is present.
258 */
259int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
260 const char *propname, u16 *val, size_t nval)
261{
262 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16,
263 val, nval);
264}
265EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
266
267/**
268 * fwnode_property_read_u32_array - return a u32 array property of firmware node
269 * @fwnode: Firmware node to get the property of
270 * @propname: Name of the property
271 * @val: The values are stored here
272 * @nval: Size of the @val array
273 *
274 * Read an array of u32 properties with @propname from @fwnode store them to
275 * @val if found.
276 *
277 * Return: %0 if the property was found (success),
278 * %-EINVAL if given arguments are not valid,
279 * %-ENODATA if the property does not have a value,
280 * %-EPROTO if the property is not an array of numbers,
281 * %-EOVERFLOW if the size of the property is not as expected,
282 * %-ENXIO if no suitable firmware interface is present.
283 */
284int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
285 const char *propname, u32 *val, size_t nval)
286{
287 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32,
288 val, nval);
289}
290EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
291
292/**
293 * fwnode_property_read_u64_array - return a u64 array property firmware node
294 * @fwnode: Firmware node to get the property of
295 * @propname: Name of the property
296 * @val: The values are stored here
297 * @nval: Size of the @val array
298 *
299 * Read an array of u64 properties with @propname from @fwnode and store them to
300 * @val if found.
301 *
302 * Return: %0 if the property was found (success),
303 * %-EINVAL if given arguments are not valid,
304 * %-ENODATA if the property does not have a value,
305 * %-EPROTO if the property is not an array of numbers,
306 * %-EOVERFLOW if the size of the property is not as expected,
307 * %-ENXIO if no suitable firmware interface is present.
308 */
309int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
310 const char *propname, u64 *val, size_t nval)
311{
312 return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64,
313 val, nval);
314}
315EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
316
317/**
318 * fwnode_property_read_string_array - return string array property of a node
319 * @fwnode: Firmware node to get the property of
320 * @propname: Name of the property
321 * @val: The values are stored here
322 * @nval: Size of the @val array
323 *
324 * Read an string list property @propname from the given firmware node and store
325 * them to @val if found.
326 *
327 * Return: %0 if the property was found (success),
328 * %-EINVAL if given arguments are not valid,
329 * %-ENODATA if the property does not have a value,
330 * %-EPROTO if the property is not an array of strings,
331 * %-EOVERFLOW if the size of the property is not as expected,
332 * %-ENXIO if no suitable firmware interface is present.
333 */
334int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
335 const char *propname, const char **val,
336 size_t nval)
337{
338 if (is_of_node(fwnode))
339 return of_property_read_string_array(of_node(fwnode), propname,
340 val, nval);
341 else if (is_acpi_node(fwnode))
342 return acpi_dev_prop_read(acpi_node(fwnode), propname,
343 DEV_PROP_STRING, val, nval);
344
345 return -ENXIO;
346}
347EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
348
349/**
350 * fwnode_property_read_string - return a string property of a firmware node
351 * @fwnode: Firmware node to get the property of
352 * @propname: Name of the property
353 * @val: The value is stored here
354 *
355 * Read property @propname from the given firmware node and store the value into
356 * @val if found. The value is checked to be a string.
357 *
358 * Return: %0 if the property was found (success),
359 * %-EINVAL if given arguments are not valid,
360 * %-ENODATA if the property does not have a value,
361 * %-EPROTO or %-EILSEQ if the property is not a string,
362 * %-ENXIO if no suitable firmware interface is present.
363 */
364int fwnode_property_read_string(struct fwnode_handle *fwnode,
365 const char *propname, const char **val)
366{
367 if (is_of_node(fwnode))
368 return of_property_read_string(of_node(fwnode),propname, val);
369 else if (is_acpi_node(fwnode))
370 return acpi_dev_prop_read(acpi_node(fwnode), propname,
371 DEV_PROP_STRING, val, 1);
372
373 return -ENXIO;
374}
375EXPORT_SYMBOL_GPL(fwnode_property_read_string);
376
377/**
378 * device_get_next_child_node - Return the next child node handle for a device
379 * @dev: Device to find the next child node for.
380 * @child: Handle to one of the device's child nodes or a null handle.
381 */
382struct fwnode_handle *device_get_next_child_node(struct device *dev,
383 struct fwnode_handle *child)
384{
385 if (IS_ENABLED(CONFIG_OF) && dev->of_node) {
386 struct device_node *node;
387
388 node = of_get_next_available_child(dev->of_node, of_node(child));
389 if (node)
390 return &node->fwnode;
391 } else if (IS_ENABLED(CONFIG_ACPI)) {
392 struct acpi_device *node;
393
394 node = acpi_get_next_child(dev, acpi_node(child));
395 if (node)
396 return acpi_fwnode_handle(node);
397 }
398 return NULL;
399}
400EXPORT_SYMBOL_GPL(device_get_next_child_node);
401
402/**
403 * fwnode_handle_put - Drop reference to a device node
404 * @fwnode: Pointer to the device node to drop the reference to.
405 *
406 * This has to be used when terminating device_for_each_child_node() iteration
407 * with break or return to prevent stale device node references from being left
408 * behind.
409 */
410void fwnode_handle_put(struct fwnode_handle *fwnode)
411{
412 if (is_of_node(fwnode))
413 of_node_put(of_node(fwnode));
414}
415EXPORT_SYMBOL_GPL(fwnode_handle_put);
416
417/**
418 * device_get_child_node_count - return the number of child nodes for device
419 * @dev: Device to cound the child nodes for
420 */
421unsigned int device_get_child_node_count(struct device *dev)
422{
423 struct fwnode_handle *child;
424 unsigned int count = 0;
425
426 device_for_each_child_node(dev, child)
427 count++;
428
429 return count;
430}
431EXPORT_SYMBOL_GPL(device_get_child_node_count);
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index f59cbf860658..a361f43b1974 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -27,6 +27,7 @@
27#define __ACPI_BUS_H__ 27#define __ACPI_BUS_H__
28 28
29#include <linux/device.h> 29#include <linux/device.h>
30#include <linux/property.h>
30 31
31/* TBD: Make dynamic */ 32/* TBD: Make dynamic */
32#define ACPI_MAX_HANDLES 10 33#define ACPI_MAX_HANDLES 10
@@ -348,6 +349,7 @@ struct acpi_device_data {
348struct acpi_device { 349struct acpi_device {
349 int device_type; 350 int device_type;
350 acpi_handle handle; /* no handle for fixed hardware */ 351 acpi_handle handle; /* no handle for fixed hardware */
352 struct fwnode_handle fwnode;
351 struct acpi_device *parent; 353 struct acpi_device *parent;
352 struct list_head children; 354 struct list_head children;
353 struct list_head node; 355 struct list_head node;
@@ -372,6 +374,21 @@ struct acpi_device {
372 void (*remove)(struct acpi_device *); 374 void (*remove)(struct acpi_device *);
373}; 375};
374 376
377static inline bool is_acpi_node(struct fwnode_handle *fwnode)
378{
379 return fwnode && fwnode->type == FWNODE_ACPI;
380}
381
382static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
383{
384 return fwnode ? container_of(fwnode, struct acpi_device, fwnode) : NULL;
385}
386
387static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
388{
389 return &adev->fwnode;
390}
391
375static inline void *acpi_driver_data(struct acpi_device *d) 392static inline void *acpi_driver_data(struct acpi_device *d)
376{ 393{
377 return d->driver_data; 394 return d->driver_data;
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 38296d686c55..5b8802216a93 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -440,6 +440,23 @@ struct platform_device *acpi_create_platform_device(struct acpi_device *);
440#define ACPI_COMPANION_SET(dev, adev) do { } while (0) 440#define ACPI_COMPANION_SET(dev, adev) do { } while (0)
441#define ACPI_HANDLE(dev) (NULL) 441#define ACPI_HANDLE(dev) (NULL)
442 442
443struct fwnode_handle;
444
445static inline bool is_acpi_node(struct fwnode_handle *fwnode)
446{
447 return false;
448}
449
450static inline struct acpi_device *acpi_node(struct fwnode_handle *fwnode)
451{
452 return NULL;
453}
454
455static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev)
456{
457 return NULL;
458}
459
443static inline const char *acpi_dev_name(struct acpi_device *adev) 460static inline const char *acpi_dev_name(struct acpi_device *adev)
444{ 461{
445 return NULL; 462 return NULL;
@@ -681,6 +698,9 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
681 enum dev_prop_type proptype, void *val); 698 enum dev_prop_type proptype, void *val);
682int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, 699int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
683 enum dev_prop_type proptype, void *val, size_t nval); 700 enum dev_prop_type proptype, void *val, size_t nval);
701
702struct acpi_device *acpi_get_next_child(struct device *dev,
703 struct acpi_device *child);
684#else 704#else
685static inline int acpi_dev_get_property(struct acpi_device *adev, 705static inline int acpi_dev_get_property(struct acpi_device *adev,
686 const char *name, acpi_object_type type, 706 const char *name, acpi_object_type type,
@@ -725,6 +745,12 @@ static inline int acpi_dev_prop_read(struct acpi_device *adev,
725 return -ENXIO; 745 return -ENXIO;
726} 746}
727 747
748static inline struct acpi_device *acpi_get_next_child(struct device *dev,
749 struct acpi_device *child)
750{
751 return NULL;
752}
753
728#endif 754#endif
729 755
730#endif /*_LINUX_ACPI_H*/ 756#endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/of.h b/include/linux/of.h
index ce9f6a2b3532..cf79be1441d2 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -50,6 +50,7 @@ struct device_node {
50 const char *type; 50 const char *type;
51 phandle phandle; 51 phandle phandle;
52 const char *full_name; 52 const char *full_name;
53 struct fwnode_handle fwnode;
53 54
54 struct property *properties; 55 struct property *properties;
55 struct property *deadprops; /* removed properties */ 56 struct property *deadprops; /* removed properties */
@@ -80,6 +81,7 @@ extern struct kobj_type of_node_ktype;
80static inline void of_node_init(struct device_node *node) 81static inline void of_node_init(struct device_node *node)
81{ 82{
82 kobject_init(&node->kobj, &of_node_ktype); 83 kobject_init(&node->kobj, &of_node_ktype);
84 node->fwnode.type = FWNODE_OF;
83} 85}
84 86
85/* true when node is initialized */ 87/* true when node is initialized */
@@ -115,6 +117,16 @@ extern struct device_node *of_aliases;
115extern struct device_node *of_stdout; 117extern struct device_node *of_stdout;
116extern raw_spinlock_t devtree_lock; 118extern raw_spinlock_t devtree_lock;
117 119
120static inline bool is_of_node(struct fwnode_handle *fwnode)
121{
122 return fwnode && fwnode->type == FWNODE_OF;
123}
124
125static inline struct device_node *of_node(struct fwnode_handle *fwnode)
126{
127 return fwnode ? container_of(fwnode, struct device_node, fwnode) : NULL;
128}
129
118static inline bool of_have_populated_dt(void) 130static inline bool of_have_populated_dt(void)
119{ 131{
120 return of_allnodes != NULL; 132 return of_allnodes != NULL;
@@ -360,6 +372,16 @@ bool of_console_check(struct device_node *dn, char *name, int index);
360 372
361#else /* CONFIG_OF */ 373#else /* CONFIG_OF */
362 374
375static inline bool is_of_node(struct fwnode_handle *fwnode)
376{
377 return false;
378}
379
380static inline struct device_node *of_node(struct fwnode_handle *fwnode)
381{
382 return NULL;
383}
384
363static inline const char* of_node_full_name(const struct device_node *np) 385static inline const char* of_node_full_name(const struct device_node *np)
364{ 386{
365 return "<no-node>"; 387 return "<no-node>";
diff --git a/include/linux/property.h b/include/linux/property.h
index 9242fb0221ba..a6a3d98bd7e9 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -40,6 +40,46 @@ int device_property_read_string_array(struct device *dev, const char *propname,
40int device_property_read_string(struct device *dev, const char *propname, 40int device_property_read_string(struct device *dev, const char *propname,
41 const char **val); 41 const char **val);
42 42
43enum fwnode_type {
44 FWNODE_INVALID = 0,
45 FWNODE_OF,
46 FWNODE_ACPI,
47};
48
49struct fwnode_handle {
50 enum fwnode_type type;
51};
52
53bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname);
54int fwnode_property_read_u8_array(struct fwnode_handle *fwnode,
55 const char *propname, u8 *val,
56 size_t nval);
57int fwnode_property_read_u16_array(struct fwnode_handle *fwnode,
58 const char *propname, u16 *val,
59 size_t nval);
60int fwnode_property_read_u32_array(struct fwnode_handle *fwnode,
61 const char *propname, u32 *val,
62 size_t nval);
63int fwnode_property_read_u64_array(struct fwnode_handle *fwnode,
64 const char *propname, u64 *val,
65 size_t nval);
66int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
67 const char *propname, const char **val,
68 size_t nval);
69int fwnode_property_read_string(struct fwnode_handle *fwnode,
70 const char *propname, const char **val);
71
72struct fwnode_handle *device_get_next_child_node(struct device *dev,
73 struct fwnode_handle *child);
74
75#define device_for_each_child_node(dev, child) \
76 for (child = device_get_next_child_node(dev, NULL); child; \
77 child = device_get_next_child_node(dev, child))
78
79void fwnode_handle_put(struct fwnode_handle *fwnode);
80
81unsigned int device_get_child_node_count(struct device *dev);
82
43static inline bool device_property_read_bool(struct device *dev, 83static inline bool device_property_read_bool(struct device *dev,
44 const char *propname) 84 const char *propname)
45{ 85{
@@ -70,4 +110,34 @@ static inline int device_property_read_u64(struct device *dev,
70 return device_property_read_u64_array(dev, propname, val, 1); 110 return device_property_read_u64_array(dev, propname, val, 1);
71} 111}
72 112
113static inline bool fwnode_property_read_bool(struct fwnode_handle *fwnode,
114 const char *propname)
115{
116 return fwnode_property_present(fwnode, propname);
117}
118
119static inline int fwnode_property_read_u8(struct fwnode_handle *fwnode,
120 const char *propname, u8 *val)
121{
122 return fwnode_property_read_u8_array(fwnode, propname, val, 1);
123}
124
125static inline int fwnode_property_read_u16(struct fwnode_handle *fwnode,
126 const char *propname, u16 *val)
127{
128 return fwnode_property_read_u16_array(fwnode, propname, val, 1);
129}
130
131static inline int fwnode_property_read_u32(struct fwnode_handle *fwnode,
132 const char *propname, u32 *val)
133{
134 return fwnode_property_read_u32_array(fwnode, propname, val, 1);
135}
136
137static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode,
138 const char *propname, u64 *val)
139{
140 return fwnode_property_read_u64_array(fwnode, propname, val, 1);
141}
142
73#endif /* _LINUX_PROPERTY_H_ */ 143#endif /* _LINUX_PROPERTY_H_ */