Commit | Line | Data |
---|---|---|
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> |
16ba08d5 RW |
17 | #include <linux/property.h> |
18 | ||
19 | /** | |
20 | * device_add_property_set - Add a collection of properties to a device object. | |
21 | * @dev: Device to add properties to. | |
22 | * @pset: Collection of properties to add. | |
23 | * | |
24 | * Associate a collection of device properties represented by @pset with @dev | |
25 | * as its secondary firmware node. | |
26 | */ | |
27 | void device_add_property_set(struct device *dev, struct property_set *pset) | |
28 | { | |
29 | if (pset) | |
30 | pset->fwnode.type = FWNODE_PDATA; | |
31 | ||
32 | set_secondary_fwnode(dev, &pset->fwnode); | |
33 | } | |
34 | EXPORT_SYMBOL_GPL(device_add_property_set); | |
35 | ||
36 | static inline bool is_pset(struct fwnode_handle *fwnode) | |
37 | { | |
38 | return fwnode && fwnode->type == FWNODE_PDATA; | |
39 | } | |
40 | ||
41 | static inline struct property_set *to_pset(struct fwnode_handle *fwnode) | |
42 | { | |
43 | return is_pset(fwnode) ? | |
44 | container_of(fwnode, struct property_set, fwnode) : NULL; | |
45 | } | |
46 | ||
47 | static struct property_entry *pset_prop_get(struct property_set *pset, | |
48 | const char *name) | |
49 | { | |
50 | struct property_entry *prop; | |
51 | ||
52 | if (!pset || !pset->properties) | |
53 | return NULL; | |
54 | ||
55 | for (prop = pset->properties; prop->name; prop++) | |
56 | if (!strcmp(name, prop->name)) | |
57 | return prop; | |
58 | ||
59 | return NULL; | |
60 | } | |
61 | ||
62 | static int pset_prop_read_array(struct property_set *pset, const char *name, | |
63 | enum dev_prop_type type, void *val, size_t nval) | |
64 | { | |
65 | struct property_entry *prop; | |
66 | unsigned int item_size; | |
67 | ||
68 | prop = pset_prop_get(pset, name); | |
69 | if (!prop) | |
70 | return -ENODATA; | |
71 | ||
72 | if (prop->type != type) | |
73 | return -EPROTO; | |
74 | ||
75 | if (!val) | |
76 | return prop->nval; | |
77 | ||
78 | if (prop->nval < nval) | |
79 | return -EOVERFLOW; | |
80 | ||
81 | switch (type) { | |
82 | case DEV_PROP_U8: | |
83 | item_size = sizeof(u8); | |
84 | break; | |
85 | case DEV_PROP_U16: | |
86 | item_size = sizeof(u16); | |
87 | break; | |
88 | case DEV_PROP_U32: | |
89 | item_size = sizeof(u32); | |
90 | break; | |
91 | case DEV_PROP_U64: | |
92 | item_size = sizeof(u64); | |
93 | break; | |
94 | case DEV_PROP_STRING: | |
95 | item_size = sizeof(const char *); | |
96 | break; | |
97 | default: | |
98 | return -EINVAL; | |
99 | } | |
100 | memcpy(val, prop->value.raw_data, nval * item_size); | |
101 | return 0; | |
102 | } | |
b31384fa | 103 | |
9017f252 RW |
104 | static inline struct fwnode_handle *dev_fwnode(struct device *dev) |
105 | { | |
106 | return IS_ENABLED(CONFIG_OF) && dev->of_node ? | |
107 | &dev->of_node->fwnode : dev->fwnode; | |
108 | } | |
b31384fa RW |
109 | |
110 | /** | |
111 | * device_property_present - check if a property of a device is present | |
112 | * @dev: Device whose property is being checked | |
113 | * @propname: Name of the property | |
114 | * | |
115 | * Check if property @propname is present in the device firmware description. | |
116 | */ | |
117 | bool device_property_present(struct device *dev, const char *propname) | |
118 | { | |
9017f252 | 119 | return fwnode_property_present(dev_fwnode(dev), propname); |
b31384fa RW |
120 | } |
121 | EXPORT_SYMBOL_GPL(device_property_present); | |
122 | ||
8a0662d9 RW |
123 | /** |
124 | * fwnode_property_present - check if a property of a firmware node is present | |
125 | * @fwnode: Firmware node whose property to check | |
126 | * @propname: Name of the property | |
127 | */ | |
128 | bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) | |
129 | { | |
130 | if (is_of_node(fwnode)) | |
131 | return of_property_read_bool(of_node(fwnode), propname); | |
132 | else if (is_acpi_node(fwnode)) | |
133 | return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); | |
134 | ||
16ba08d5 | 135 | return !!pset_prop_get(to_pset(fwnode), propname); |
8a0662d9 RW |
136 | } |
137 | EXPORT_SYMBOL_GPL(fwnode_property_present); | |
138 | ||
b31384fa RW |
139 | /** |
140 | * device_property_read_u8_array - return a u8 array property of a device | |
141 | * @dev: Device to get the property of | |
142 | * @propname: Name of the property | |
5c0acf3b | 143 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
144 | * @nval: Size of the @val array |
145 | * | |
146 | * Function reads an array of u8 properties with @propname from the device | |
147 | * firmware description and stores them to @val if found. | |
148 | * | |
5c0acf3b AH |
149 | * Return: number of values if @val was %NULL, |
150 | * %0 if the property was found (success), | |
b31384fa RW |
151 | * %-EINVAL if given arguments are not valid, |
152 | * %-ENODATA if the property does not have a value, | |
153 | * %-EPROTO if the property is not an array of numbers, | |
154 | * %-EOVERFLOW if the size of the property is not as expected. | |
155 | */ | |
156 | int device_property_read_u8_array(struct device *dev, const char *propname, | |
157 | u8 *val, size_t nval) | |
158 | { | |
9017f252 | 159 | return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
160 | } |
161 | EXPORT_SYMBOL_GPL(device_property_read_u8_array); | |
162 | ||
163 | /** | |
164 | * device_property_read_u16_array - return a u16 array property of a device | |
165 | * @dev: Device to get the property of | |
166 | * @propname: Name of the property | |
5c0acf3b | 167 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
168 | * @nval: Size of the @val array |
169 | * | |
170 | * Function reads an array of u16 properties with @propname from the device | |
171 | * firmware description and stores them to @val if found. | |
172 | * | |
5c0acf3b AH |
173 | * Return: number of values if @val was %NULL, |
174 | * %0 if the property was found (success), | |
b31384fa RW |
175 | * %-EINVAL if given arguments are not valid, |
176 | * %-ENODATA if the property does not have a value, | |
177 | * %-EPROTO if the property is not an array of numbers, | |
178 | * %-EOVERFLOW if the size of the property is not as expected. | |
179 | */ | |
180 | int device_property_read_u16_array(struct device *dev, const char *propname, | |
181 | u16 *val, size_t nval) | |
182 | { | |
9017f252 | 183 | return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
184 | } |
185 | EXPORT_SYMBOL_GPL(device_property_read_u16_array); | |
186 | ||
187 | /** | |
188 | * device_property_read_u32_array - return a u32 array property of a device | |
189 | * @dev: Device to get the property of | |
190 | * @propname: Name of the property | |
5c0acf3b | 191 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
192 | * @nval: Size of the @val array |
193 | * | |
194 | * Function reads an array of u32 properties with @propname from the device | |
195 | * firmware description and stores them to @val if found. | |
196 | * | |
5c0acf3b AH |
197 | * Return: number of values if @val was %NULL, |
198 | * %0 if the property was found (success), | |
b31384fa RW |
199 | * %-EINVAL if given arguments are not valid, |
200 | * %-ENODATA if the property does not have a value, | |
201 | * %-EPROTO if the property is not an array of numbers, | |
202 | * %-EOVERFLOW if the size of the property is not as expected. | |
203 | */ | |
204 | int device_property_read_u32_array(struct device *dev, const char *propname, | |
205 | u32 *val, size_t nval) | |
206 | { | |
9017f252 | 207 | return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
208 | } |
209 | EXPORT_SYMBOL_GPL(device_property_read_u32_array); | |
210 | ||
211 | /** | |
212 | * device_property_read_u64_array - return a u64 array property of a device | |
213 | * @dev: Device to get the property of | |
214 | * @propname: Name of the property | |
5c0acf3b | 215 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
216 | * @nval: Size of the @val array |
217 | * | |
218 | * Function reads an array of u64 properties with @propname from the device | |
219 | * firmware description and stores them to @val if found. | |
220 | * | |
5c0acf3b AH |
221 | * Return: number of values if @val was %NULL, |
222 | * %0 if the property was found (success), | |
b31384fa RW |
223 | * %-EINVAL if given arguments are not valid, |
224 | * %-ENODATA if the property does not have a value, | |
225 | * %-EPROTO if the property is not an array of numbers, | |
226 | * %-EOVERFLOW if the size of the property is not as expected. | |
227 | */ | |
228 | int device_property_read_u64_array(struct device *dev, const char *propname, | |
229 | u64 *val, size_t nval) | |
230 | { | |
9017f252 | 231 | return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
232 | } |
233 | EXPORT_SYMBOL_GPL(device_property_read_u64_array); | |
234 | ||
235 | /** | |
236 | * device_property_read_string_array - return a string array property of device | |
237 | * @dev: Device to get the property of | |
238 | * @propname: Name of the property | |
5c0acf3b | 239 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
240 | * @nval: Size of the @val array |
241 | * | |
242 | * Function reads an array of string properties with @propname from the device | |
243 | * firmware description and stores them to @val if found. | |
244 | * | |
5c0acf3b AH |
245 | * Return: number of values if @val was %NULL, |
246 | * %0 if the property was found (success), | |
b31384fa RW |
247 | * %-EINVAL if given arguments are not valid, |
248 | * %-ENODATA if the property does not have a value, | |
249 | * %-EPROTO or %-EILSEQ if the property is not an array of strings, | |
250 | * %-EOVERFLOW if the size of the property is not as expected. | |
251 | */ | |
252 | int device_property_read_string_array(struct device *dev, const char *propname, | |
253 | const char **val, size_t nval) | |
254 | { | |
9017f252 | 255 | return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
256 | } |
257 | EXPORT_SYMBOL_GPL(device_property_read_string_array); | |
258 | ||
259 | /** | |
260 | * device_property_read_string - return a string property of a device | |
261 | * @dev: Device to get the property of | |
262 | * @propname: Name of the property | |
263 | * @val: The value is stored here | |
264 | * | |
265 | * Function reads property @propname from the device firmware description and | |
266 | * stores the value into @val if found. The value is checked to be a string. | |
267 | * | |
268 | * Return: %0 if the property was found (success), | |
269 | * %-EINVAL if given arguments are not valid, | |
270 | * %-ENODATA if the property does not have a value, | |
271 | * %-EPROTO or %-EILSEQ if the property type is not a string. | |
272 | */ | |
273 | int device_property_read_string(struct device *dev, const char *propname, | |
274 | const char **val) | |
275 | { | |
9017f252 | 276 | return fwnode_property_read_string(dev_fwnode(dev), propname, val); |
b31384fa RW |
277 | } |
278 | EXPORT_SYMBOL_GPL(device_property_read_string); | |
8a0662d9 | 279 | |
9017f252 RW |
280 | #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ |
281 | (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ | |
282 | : of_property_count_elems_of_size((node), (propname), sizeof(type)) | |
283 | ||
8a0662d9 RW |
284 | #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ |
285 | ({ \ | |
286 | int _ret_; \ | |
287 | if (is_of_node(_fwnode_)) \ | |
288 | _ret_ = OF_DEV_PROP_READ_ARRAY(of_node(_fwnode_), _propname_, \ | |
289 | _type_, _val_, _nval_); \ | |
290 | else if (is_acpi_node(_fwnode_)) \ | |
291 | _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \ | |
292 | _proptype_, _val_, _nval_); \ | |
293 | else \ | |
16ba08d5 RW |
294 | _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \ |
295 | _proptype_, _val_, _nval_); \ | |
8a0662d9 RW |
296 | _ret_; \ |
297 | }) | |
298 | ||
299 | /** | |
300 | * fwnode_property_read_u8_array - return a u8 array property of firmware node | |
301 | * @fwnode: Firmware node to get the property of | |
302 | * @propname: Name of the property | |
5c0acf3b | 303 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
304 | * @nval: Size of the @val array |
305 | * | |
306 | * Read an array of u8 properties with @propname from @fwnode and stores them to | |
307 | * @val if found. | |
308 | * | |
5c0acf3b AH |
309 | * Return: number of values if @val was %NULL, |
310 | * %0 if the property was found (success), | |
8a0662d9 RW |
311 | * %-EINVAL if given arguments are not valid, |
312 | * %-ENODATA if the property does not have a value, | |
313 | * %-EPROTO if the property is not an array of numbers, | |
314 | * %-EOVERFLOW if the size of the property is not as expected, | |
315 | * %-ENXIO if no suitable firmware interface is present. | |
316 | */ | |
317 | int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, | |
318 | const char *propname, u8 *val, size_t nval) | |
319 | { | |
320 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8, | |
321 | val, nval); | |
322 | } | |
323 | EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array); | |
324 | ||
325 | /** | |
326 | * fwnode_property_read_u16_array - return a u16 array property of firmware node | |
327 | * @fwnode: Firmware node to get the property of | |
328 | * @propname: Name of the property | |
5c0acf3b | 329 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
330 | * @nval: Size of the @val array |
331 | * | |
332 | * Read an array of u16 properties with @propname from @fwnode and store them to | |
333 | * @val if found. | |
334 | * | |
5c0acf3b AH |
335 | * Return: number of values if @val was %NULL, |
336 | * %0 if the property was found (success), | |
8a0662d9 RW |
337 | * %-EINVAL if given arguments are not valid, |
338 | * %-ENODATA if the property does not have a value, | |
339 | * %-EPROTO if the property is not an array of numbers, | |
340 | * %-EOVERFLOW if the size of the property is not as expected, | |
341 | * %-ENXIO if no suitable firmware interface is present. | |
342 | */ | |
343 | int fwnode_property_read_u16_array(struct fwnode_handle *fwnode, | |
344 | const char *propname, u16 *val, size_t nval) | |
345 | { | |
346 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16, | |
347 | val, nval); | |
348 | } | |
349 | EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array); | |
350 | ||
351 | /** | |
352 | * fwnode_property_read_u32_array - return a u32 array property of firmware node | |
353 | * @fwnode: Firmware node to get the property of | |
354 | * @propname: Name of the property | |
5c0acf3b | 355 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
356 | * @nval: Size of the @val array |
357 | * | |
358 | * Read an array of u32 properties with @propname from @fwnode store them to | |
359 | * @val if found. | |
360 | * | |
5c0acf3b AH |
361 | * Return: number of values if @val was %NULL, |
362 | * %0 if the property was found (success), | |
8a0662d9 RW |
363 | * %-EINVAL if given arguments are not valid, |
364 | * %-ENODATA if the property does not have a value, | |
365 | * %-EPROTO if the property is not an array of numbers, | |
366 | * %-EOVERFLOW if the size of the property is not as expected, | |
367 | * %-ENXIO if no suitable firmware interface is present. | |
368 | */ | |
369 | int fwnode_property_read_u32_array(struct fwnode_handle *fwnode, | |
370 | const char *propname, u32 *val, size_t nval) | |
371 | { | |
372 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32, | |
373 | val, nval); | |
374 | } | |
375 | EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array); | |
376 | ||
377 | /** | |
378 | * fwnode_property_read_u64_array - return a u64 array property firmware node | |
379 | * @fwnode: Firmware node to get the property of | |
380 | * @propname: Name of the property | |
5c0acf3b | 381 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
382 | * @nval: Size of the @val array |
383 | * | |
384 | * Read an array of u64 properties with @propname from @fwnode and store them to | |
385 | * @val if found. | |
386 | * | |
5c0acf3b AH |
387 | * Return: number of values if @val was %NULL, |
388 | * %0 if the property was found (success), | |
8a0662d9 RW |
389 | * %-EINVAL if given arguments are not valid, |
390 | * %-ENODATA if the property does not have a value, | |
391 | * %-EPROTO if the property is not an array of numbers, | |
392 | * %-EOVERFLOW if the size of the property is not as expected, | |
393 | * %-ENXIO if no suitable firmware interface is present. | |
394 | */ | |
395 | int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, | |
396 | const char *propname, u64 *val, size_t nval) | |
397 | { | |
398 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64, | |
399 | val, nval); | |
400 | } | |
401 | EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array); | |
402 | ||
403 | /** | |
404 | * fwnode_property_read_string_array - return string array property of a node | |
405 | * @fwnode: Firmware node to get the property of | |
406 | * @propname: Name of the property | |
5c0acf3b | 407 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
408 | * @nval: Size of the @val array |
409 | * | |
410 | * Read an string list property @propname from the given firmware node and store | |
411 | * them to @val if found. | |
412 | * | |
5c0acf3b AH |
413 | * Return: number of values if @val was %NULL, |
414 | * %0 if the property was found (success), | |
8a0662d9 RW |
415 | * %-EINVAL if given arguments are not valid, |
416 | * %-ENODATA if the property does not have a value, | |
417 | * %-EPROTO if the property is not an array of strings, | |
418 | * %-EOVERFLOW if the size of the property is not as expected, | |
419 | * %-ENXIO if no suitable firmware interface is present. | |
420 | */ | |
421 | int fwnode_property_read_string_array(struct fwnode_handle *fwnode, | |
422 | const char *propname, const char **val, | |
423 | size_t nval) | |
424 | { | |
425 | if (is_of_node(fwnode)) | |
f42712a9 RW |
426 | return val ? |
427 | of_property_read_string_array(of_node(fwnode), propname, | |
428 | val, nval) : | |
429 | of_property_count_strings(of_node(fwnode), propname); | |
8a0662d9 RW |
430 | else if (is_acpi_node(fwnode)) |
431 | return acpi_dev_prop_read(acpi_node(fwnode), propname, | |
432 | DEV_PROP_STRING, val, nval); | |
433 | ||
16ba08d5 RW |
434 | return pset_prop_read_array(to_pset(fwnode), propname, |
435 | DEV_PROP_STRING, val, nval); | |
8a0662d9 RW |
436 | } |
437 | EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); | |
438 | ||
439 | /** | |
440 | * fwnode_property_read_string - return a string property of a firmware node | |
441 | * @fwnode: Firmware node to get the property of | |
442 | * @propname: Name of the property | |
443 | * @val: The value is stored here | |
444 | * | |
445 | * Read property @propname from the given firmware node and store the value into | |
446 | * @val if found. The value is checked to be a string. | |
447 | * | |
448 | * Return: %0 if the property was found (success), | |
449 | * %-EINVAL if given arguments are not valid, | |
450 | * %-ENODATA if the property does not have a value, | |
451 | * %-EPROTO or %-EILSEQ if the property is not a string, | |
452 | * %-ENXIO if no suitable firmware interface is present. | |
453 | */ | |
454 | int fwnode_property_read_string(struct fwnode_handle *fwnode, | |
455 | const char *propname, const char **val) | |
456 | { | |
457 | if (is_of_node(fwnode)) | |
7036cd46 | 458 | return of_property_read_string(of_node(fwnode), propname, val); |
8a0662d9 RW |
459 | else if (is_acpi_node(fwnode)) |
460 | return acpi_dev_prop_read(acpi_node(fwnode), propname, | |
461 | DEV_PROP_STRING, val, 1); | |
462 | ||
463 | return -ENXIO; | |
464 | } | |
465 | EXPORT_SYMBOL_GPL(fwnode_property_read_string); | |
466 | ||
467 | /** | |
468 | * device_get_next_child_node - Return the next child node handle for a device | |
469 | * @dev: Device to find the next child node for. | |
470 | * @child: Handle to one of the device's child nodes or a null handle. | |
471 | */ | |
472 | struct fwnode_handle *device_get_next_child_node(struct device *dev, | |
473 | struct fwnode_handle *child) | |
474 | { | |
475 | if (IS_ENABLED(CONFIG_OF) && dev->of_node) { | |
476 | struct device_node *node; | |
477 | ||
478 | node = of_get_next_available_child(dev->of_node, of_node(child)); | |
479 | if (node) | |
480 | return &node->fwnode; | |
481 | } else if (IS_ENABLED(CONFIG_ACPI)) { | |
482 | struct acpi_device *node; | |
483 | ||
484 | node = acpi_get_next_child(dev, acpi_node(child)); | |
485 | if (node) | |
486 | return acpi_fwnode_handle(node); | |
487 | } | |
488 | return NULL; | |
489 | } | |
490 | EXPORT_SYMBOL_GPL(device_get_next_child_node); | |
491 | ||
492 | /** | |
493 | * fwnode_handle_put - Drop reference to a device node | |
494 | * @fwnode: Pointer to the device node to drop the reference to. | |
495 | * | |
496 | * This has to be used when terminating device_for_each_child_node() iteration | |
497 | * with break or return to prevent stale device node references from being left | |
498 | * behind. | |
499 | */ | |
500 | void fwnode_handle_put(struct fwnode_handle *fwnode) | |
501 | { | |
502 | if (is_of_node(fwnode)) | |
503 | of_node_put(of_node(fwnode)); | |
504 | } | |
505 | EXPORT_SYMBOL_GPL(fwnode_handle_put); | |
506 | ||
507 | /** | |
508 | * device_get_child_node_count - return the number of child nodes for device | |
509 | * @dev: Device to cound the child nodes for | |
510 | */ | |
511 | unsigned int device_get_child_node_count(struct device *dev) | |
512 | { | |
513 | struct fwnode_handle *child; | |
514 | unsigned int count = 0; | |
515 | ||
516 | device_for_each_child_node(dev, child) | |
517 | count++; | |
518 | ||
519 | return count; | |
520 | } | |
521 | EXPORT_SYMBOL_GPL(device_get_child_node_count); |