]>
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> |
05ca5560 | 17 | #include <linux/of_address.h> |
16ba08d5 | 18 | #include <linux/property.h> |
4c96b7dc JL |
19 | #include <linux/etherdevice.h> |
20 | #include <linux/phy.h> | |
16ba08d5 RW |
21 | |
22 | /** | |
23 | * device_add_property_set - Add a collection of properties to a device object. | |
24 | * @dev: Device to add properties to. | |
25 | * @pset: Collection of properties to add. | |
26 | * | |
27 | * Associate a collection of device properties represented by @pset with @dev | |
28 | * as its secondary firmware node. | |
29 | */ | |
30 | void device_add_property_set(struct device *dev, struct property_set *pset) | |
31 | { | |
ecc87eed AS |
32 | if (!pset) |
33 | return; | |
16ba08d5 | 34 | |
ecc87eed | 35 | pset->fwnode.type = FWNODE_PDATA; |
16ba08d5 RW |
36 | set_secondary_fwnode(dev, &pset->fwnode); |
37 | } | |
38 | EXPORT_SYMBOL_GPL(device_add_property_set); | |
39 | ||
61f5e294 | 40 | static inline bool is_pset_node(struct fwnode_handle *fwnode) |
16ba08d5 RW |
41 | { |
42 | return fwnode && fwnode->type == FWNODE_PDATA; | |
43 | } | |
44 | ||
61f5e294 | 45 | static inline struct property_set *to_pset_node(struct fwnode_handle *fwnode) |
16ba08d5 | 46 | { |
61f5e294 | 47 | return is_pset_node(fwnode) ? |
16ba08d5 RW |
48 | container_of(fwnode, struct property_set, fwnode) : NULL; |
49 | } | |
50 | ||
51 | static struct property_entry *pset_prop_get(struct property_set *pset, | |
52 | const char *name) | |
53 | { | |
54 | struct property_entry *prop; | |
55 | ||
56 | if (!pset || !pset->properties) | |
57 | return NULL; | |
58 | ||
59 | for (prop = pset->properties; prop->name; prop++) | |
60 | if (!strcmp(name, prop->name)) | |
61 | return prop; | |
62 | ||
63 | return NULL; | |
64 | } | |
65 | ||
318a1971 AS |
66 | static void *pset_prop_find(struct property_set *pset, const char *propname, |
67 | size_t length) | |
16ba08d5 RW |
68 | { |
69 | struct property_entry *prop; | |
318a1971 | 70 | void *pointer; |
16ba08d5 | 71 | |
318a1971 AS |
72 | prop = pset_prop_get(pset, propname); |
73 | if (!prop) | |
74 | return ERR_PTR(-EINVAL); | |
66586bab AS |
75 | if (prop->is_array) |
76 | pointer = prop->pointer.raw_data; | |
77 | else | |
78 | pointer = &prop->value.raw_data; | |
318a1971 AS |
79 | if (!pointer) |
80 | return ERR_PTR(-ENODATA); | |
81 | if (length > prop->length) | |
82 | return ERR_PTR(-EOVERFLOW); | |
83 | return pointer; | |
84 | } | |
85 | ||
86 | static int pset_prop_read_u8_array(struct property_set *pset, | |
87 | const char *propname, | |
88 | u8 *values, size_t nval) | |
89 | { | |
90 | void *pointer; | |
91 | size_t length = nval * sizeof(*values); | |
92 | ||
93 | pointer = pset_prop_find(pset, propname, length); | |
94 | if (IS_ERR(pointer)) | |
95 | return PTR_ERR(pointer); | |
96 | ||
97 | memcpy(values, pointer, length); | |
98 | return 0; | |
99 | } | |
100 | ||
101 | static int pset_prop_read_u16_array(struct property_set *pset, | |
102 | const char *propname, | |
103 | u16 *values, size_t nval) | |
104 | { | |
105 | void *pointer; | |
106 | size_t length = nval * sizeof(*values); | |
107 | ||
108 | pointer = pset_prop_find(pset, propname, length); | |
109 | if (IS_ERR(pointer)) | |
110 | return PTR_ERR(pointer); | |
111 | ||
112 | memcpy(values, pointer, length); | |
113 | return 0; | |
114 | } | |
115 | ||
116 | static int pset_prop_read_u32_array(struct property_set *pset, | |
117 | const char *propname, | |
118 | u32 *values, size_t nval) | |
119 | { | |
120 | void *pointer; | |
121 | size_t length = nval * sizeof(*values); | |
122 | ||
123 | pointer = pset_prop_find(pset, propname, length); | |
124 | if (IS_ERR(pointer)) | |
125 | return PTR_ERR(pointer); | |
126 | ||
127 | memcpy(values, pointer, length); | |
128 | return 0; | |
129 | } | |
130 | ||
131 | static int pset_prop_read_u64_array(struct property_set *pset, | |
132 | const char *propname, | |
133 | u64 *values, size_t nval) | |
134 | { | |
135 | void *pointer; | |
136 | size_t length = nval * sizeof(*values); | |
137 | ||
138 | pointer = pset_prop_find(pset, propname, length); | |
139 | if (IS_ERR(pointer)) | |
140 | return PTR_ERR(pointer); | |
141 | ||
142 | memcpy(values, pointer, length); | |
143 | return 0; | |
144 | } | |
145 | ||
146 | static int pset_prop_count_elems_of_size(struct property_set *pset, | |
147 | const char *propname, size_t length) | |
148 | { | |
149 | struct property_entry *prop; | |
150 | ||
151 | prop = pset_prop_get(pset, propname); | |
16ba08d5 | 152 | if (!prop) |
16ba08d5 | 153 | return -EINVAL; |
318a1971 AS |
154 | |
155 | return prop->length / length; | |
156 | } | |
157 | ||
158 | static int pset_prop_read_string_array(struct property_set *pset, | |
159 | const char *propname, | |
160 | const char **strings, size_t nval) | |
161 | { | |
162 | void *pointer; | |
163 | size_t length = nval * sizeof(*strings); | |
164 | ||
165 | pointer = pset_prop_find(pset, propname, length); | |
166 | if (IS_ERR(pointer)) | |
167 | return PTR_ERR(pointer); | |
168 | ||
169 | memcpy(strings, pointer, length); | |
16ba08d5 RW |
170 | return 0; |
171 | } | |
b31384fa | 172 | |
66586bab AS |
173 | static int pset_prop_read_string(struct property_set *pset, |
174 | const char *propname, const char **strings) | |
175 | { | |
176 | struct property_entry *prop; | |
177 | const char **pointer; | |
178 | ||
179 | prop = pset_prop_get(pset, propname); | |
180 | if (!prop) | |
181 | return -EINVAL; | |
182 | if (!prop->is_string) | |
183 | return -EILSEQ; | |
184 | if (prop->is_array) { | |
185 | pointer = prop->pointer.str; | |
186 | if (!pointer) | |
187 | return -ENODATA; | |
188 | } else { | |
189 | pointer = &prop->value.str; | |
190 | if (*pointer && strnlen(*pointer, prop->length) >= prop->length) | |
191 | return -EILSEQ; | |
192 | } | |
193 | ||
194 | *strings = *pointer; | |
195 | return 0; | |
196 | } | |
197 | ||
9017f252 RW |
198 | static inline struct fwnode_handle *dev_fwnode(struct device *dev) |
199 | { | |
200 | return IS_ENABLED(CONFIG_OF) && dev->of_node ? | |
201 | &dev->of_node->fwnode : dev->fwnode; | |
202 | } | |
b31384fa RW |
203 | |
204 | /** | |
205 | * device_property_present - check if a property of a device is present | |
206 | * @dev: Device whose property is being checked | |
207 | * @propname: Name of the property | |
208 | * | |
209 | * Check if property @propname is present in the device firmware description. | |
210 | */ | |
211 | bool device_property_present(struct device *dev, const char *propname) | |
212 | { | |
9017f252 | 213 | return fwnode_property_present(dev_fwnode(dev), propname); |
b31384fa RW |
214 | } |
215 | EXPORT_SYMBOL_GPL(device_property_present); | |
216 | ||
8a0662d9 RW |
217 | /** |
218 | * fwnode_property_present - check if a property of a firmware node is present | |
219 | * @fwnode: Firmware node whose property to check | |
220 | * @propname: Name of the property | |
221 | */ | |
222 | bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) | |
223 | { | |
224 | if (is_of_node(fwnode)) | |
c181fb3e | 225 | return of_property_read_bool(to_of_node(fwnode), propname); |
8a0662d9 | 226 | else if (is_acpi_node(fwnode)) |
3a7a2ab8 | 227 | return !acpi_node_prop_get(fwnode, propname, NULL); |
61f5e294 AS |
228 | else if (is_pset_node(fwnode)) |
229 | return !!pset_prop_get(to_pset_node(fwnode), propname); | |
e3f9e299 | 230 | return false; |
8a0662d9 RW |
231 | } |
232 | EXPORT_SYMBOL_GPL(fwnode_property_present); | |
233 | ||
b31384fa RW |
234 | /** |
235 | * device_property_read_u8_array - return a u8 array property of a device | |
236 | * @dev: Device to get the property of | |
237 | * @propname: Name of the property | |
5c0acf3b | 238 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
239 | * @nval: Size of the @val array |
240 | * | |
241 | * Function reads an array of u8 properties with @propname from the device | |
242 | * firmware description and stores them to @val if found. | |
243 | * | |
5c0acf3b AH |
244 | * Return: number of values if @val was %NULL, |
245 | * %0 if the property was found (success), | |
b31384fa RW |
246 | * %-EINVAL if given arguments are not valid, |
247 | * %-ENODATA if the property does not have a value, | |
248 | * %-EPROTO if the property is not an array of numbers, | |
249 | * %-EOVERFLOW if the size of the property is not as expected. | |
4fa7508e | 250 | * %-ENXIO if no suitable firmware interface is present. |
b31384fa RW |
251 | */ |
252 | int device_property_read_u8_array(struct device *dev, const char *propname, | |
253 | u8 *val, size_t nval) | |
254 | { | |
9017f252 | 255 | return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
256 | } |
257 | EXPORT_SYMBOL_GPL(device_property_read_u8_array); | |
258 | ||
259 | /** | |
260 | * device_property_read_u16_array - return a u16 array property of a device | |
261 | * @dev: Device to get the property of | |
262 | * @propname: Name of the property | |
5c0acf3b | 263 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
264 | * @nval: Size of the @val array |
265 | * | |
266 | * Function reads an array of u16 properties with @propname from the device | |
267 | * firmware description and stores them to @val if found. | |
268 | * | |
5c0acf3b AH |
269 | * Return: number of values if @val was %NULL, |
270 | * %0 if the property was found (success), | |
b31384fa RW |
271 | * %-EINVAL if given arguments are not valid, |
272 | * %-ENODATA if the property does not have a value, | |
273 | * %-EPROTO if the property is not an array of numbers, | |
274 | * %-EOVERFLOW if the size of the property is not as expected. | |
4fa7508e | 275 | * %-ENXIO if no suitable firmware interface is present. |
b31384fa RW |
276 | */ |
277 | int device_property_read_u16_array(struct device *dev, const char *propname, | |
278 | u16 *val, size_t nval) | |
279 | { | |
9017f252 | 280 | return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
281 | } |
282 | EXPORT_SYMBOL_GPL(device_property_read_u16_array); | |
283 | ||
284 | /** | |
285 | * device_property_read_u32_array - return a u32 array property of a device | |
286 | * @dev: Device to get the property of | |
287 | * @propname: Name of the property | |
5c0acf3b | 288 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
289 | * @nval: Size of the @val array |
290 | * | |
291 | * Function reads an array of u32 properties with @propname from the device | |
292 | * firmware description and stores them to @val if found. | |
293 | * | |
5c0acf3b AH |
294 | * Return: number of values if @val was %NULL, |
295 | * %0 if the property was found (success), | |
b31384fa RW |
296 | * %-EINVAL if given arguments are not valid, |
297 | * %-ENODATA if the property does not have a value, | |
298 | * %-EPROTO if the property is not an array of numbers, | |
299 | * %-EOVERFLOW if the size of the property is not as expected. | |
4fa7508e | 300 | * %-ENXIO if no suitable firmware interface is present. |
b31384fa RW |
301 | */ |
302 | int device_property_read_u32_array(struct device *dev, const char *propname, | |
303 | u32 *val, size_t nval) | |
304 | { | |
9017f252 | 305 | return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
306 | } |
307 | EXPORT_SYMBOL_GPL(device_property_read_u32_array); | |
308 | ||
309 | /** | |
310 | * device_property_read_u64_array - return a u64 array property of a device | |
311 | * @dev: Device to get the property of | |
312 | * @propname: Name of the property | |
5c0acf3b | 313 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
314 | * @nval: Size of the @val array |
315 | * | |
316 | * Function reads an array of u64 properties with @propname from the device | |
317 | * firmware description and stores them to @val if found. | |
318 | * | |
5c0acf3b AH |
319 | * Return: number of values if @val was %NULL, |
320 | * %0 if the property was found (success), | |
b31384fa RW |
321 | * %-EINVAL if given arguments are not valid, |
322 | * %-ENODATA if the property does not have a value, | |
323 | * %-EPROTO if the property is not an array of numbers, | |
324 | * %-EOVERFLOW if the size of the property is not as expected. | |
4fa7508e | 325 | * %-ENXIO if no suitable firmware interface is present. |
b31384fa RW |
326 | */ |
327 | int device_property_read_u64_array(struct device *dev, const char *propname, | |
328 | u64 *val, size_t nval) | |
329 | { | |
9017f252 | 330 | return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
331 | } |
332 | EXPORT_SYMBOL_GPL(device_property_read_u64_array); | |
333 | ||
334 | /** | |
335 | * device_property_read_string_array - return a string array property of device | |
336 | * @dev: Device to get the property of | |
337 | * @propname: Name of the property | |
5c0acf3b | 338 | * @val: The values are stored here or %NULL to return the number of values |
b31384fa RW |
339 | * @nval: Size of the @val array |
340 | * | |
341 | * Function reads an array of string properties with @propname from the device | |
342 | * firmware description and stores them to @val if found. | |
343 | * | |
5c0acf3b AH |
344 | * Return: number of values if @val was %NULL, |
345 | * %0 if the property was found (success), | |
b31384fa RW |
346 | * %-EINVAL if given arguments are not valid, |
347 | * %-ENODATA if the property does not have a value, | |
348 | * %-EPROTO or %-EILSEQ if the property is not an array of strings, | |
349 | * %-EOVERFLOW if the size of the property is not as expected. | |
4fa7508e | 350 | * %-ENXIO if no suitable firmware interface is present. |
b31384fa RW |
351 | */ |
352 | int device_property_read_string_array(struct device *dev, const char *propname, | |
353 | const char **val, size_t nval) | |
354 | { | |
9017f252 | 355 | return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval); |
b31384fa RW |
356 | } |
357 | EXPORT_SYMBOL_GPL(device_property_read_string_array); | |
358 | ||
359 | /** | |
360 | * device_property_read_string - return a string property of a device | |
361 | * @dev: Device to get the property of | |
362 | * @propname: Name of the property | |
363 | * @val: The value is stored here | |
364 | * | |
365 | * Function reads property @propname from the device firmware description and | |
366 | * stores the value into @val if found. The value is checked to be a string. | |
367 | * | |
368 | * Return: %0 if the property was found (success), | |
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 type is not a string. | |
4fa7508e | 372 | * %-ENXIO if no suitable firmware interface is present. |
b31384fa RW |
373 | */ |
374 | int device_property_read_string(struct device *dev, const char *propname, | |
375 | const char **val) | |
376 | { | |
9017f252 | 377 | return fwnode_property_read_string(dev_fwnode(dev), propname, val); |
b31384fa RW |
378 | } |
379 | EXPORT_SYMBOL_GPL(device_property_read_string); | |
8a0662d9 | 380 | |
3f5c8d31 MW |
381 | /** |
382 | * device_property_match_string - find a string in an array and return index | |
383 | * @dev: Device to get the property of | |
384 | * @propname: Name of the property holding the array | |
385 | * @string: String to look for | |
386 | * | |
387 | * Find a given string in a string array and if it is found return the | |
388 | * index back. | |
389 | * | |
390 | * Return: %0 if the property was found (success), | |
391 | * %-EINVAL if given arguments are not valid, | |
392 | * %-ENODATA if the property does not have a value, | |
393 | * %-EPROTO if the property is not an array of strings, | |
394 | * %-ENXIO if no suitable firmware interface is present. | |
395 | */ | |
396 | int device_property_match_string(struct device *dev, const char *propname, | |
397 | const char *string) | |
398 | { | |
399 | return fwnode_property_match_string(dev_fwnode(dev), propname, string); | |
400 | } | |
401 | EXPORT_SYMBOL_GPL(device_property_match_string); | |
402 | ||
1d656fb7 AS |
403 | #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ |
404 | (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ | |
9017f252 RW |
405 | : of_property_count_elems_of_size((node), (propname), sizeof(type)) |
406 | ||
318a1971 AS |
407 | #define PSET_PROP_READ_ARRAY(node, propname, type, val, nval) \ |
408 | (val) ? pset_prop_read_##type##_array((node), (propname), (val), (nval)) \ | |
409 | : pset_prop_count_elems_of_size((node), (propname), sizeof(type)) | |
410 | ||
1d656fb7 AS |
411 | #define FWNODE_PROP_READ_ARRAY(_fwnode_, _propname_, _type_, _proptype_, _val_, _nval_) \ |
412 | ({ \ | |
413 | int _ret_; \ | |
414 | if (is_of_node(_fwnode_)) \ | |
415 | _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \ | |
416 | _type_, _val_, _nval_); \ | |
417 | else if (is_acpi_node(_fwnode_)) \ | |
418 | _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \ | |
419 | _val_, _nval_); \ | |
61f5e294 | 420 | else if (is_pset_node(_fwnode_)) \ |
318a1971 AS |
421 | _ret_ = PSET_PROP_READ_ARRAY(to_pset_node(_fwnode_), _propname_, \ |
422 | _type_, _val_, _nval_); \ | |
1d656fb7 AS |
423 | else \ |
424 | _ret_ = -ENXIO; \ | |
425 | _ret_; \ | |
8a0662d9 RW |
426 | }) |
427 | ||
428 | /** | |
429 | * fwnode_property_read_u8_array - return a u8 array property of firmware node | |
430 | * @fwnode: Firmware node to get the property of | |
431 | * @propname: Name of the property | |
5c0acf3b | 432 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
433 | * @nval: Size of the @val array |
434 | * | |
435 | * Read an array of u8 properties with @propname from @fwnode and stores them to | |
436 | * @val if found. | |
437 | * | |
5c0acf3b AH |
438 | * Return: number of values if @val was %NULL, |
439 | * %0 if the property was found (success), | |
8a0662d9 RW |
440 | * %-EINVAL if given arguments are not valid, |
441 | * %-ENODATA if the property does not have a value, | |
442 | * %-EPROTO if the property is not an array of numbers, | |
443 | * %-EOVERFLOW if the size of the property is not as expected, | |
444 | * %-ENXIO if no suitable firmware interface is present. | |
445 | */ | |
446 | int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, | |
447 | const char *propname, u8 *val, size_t nval) | |
448 | { | |
449 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u8, DEV_PROP_U8, | |
450 | val, nval); | |
451 | } | |
452 | EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array); | |
453 | ||
454 | /** | |
455 | * fwnode_property_read_u16_array - return a u16 array property of firmware node | |
456 | * @fwnode: Firmware node to get the property of | |
457 | * @propname: Name of the property | |
5c0acf3b | 458 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
459 | * @nval: Size of the @val array |
460 | * | |
461 | * Read an array of u16 properties with @propname from @fwnode and store them to | |
462 | * @val if found. | |
463 | * | |
5c0acf3b AH |
464 | * Return: number of values if @val was %NULL, |
465 | * %0 if the property was found (success), | |
8a0662d9 RW |
466 | * %-EINVAL if given arguments are not valid, |
467 | * %-ENODATA if the property does not have a value, | |
468 | * %-EPROTO if the property is not an array of numbers, | |
469 | * %-EOVERFLOW if the size of the property is not as expected, | |
470 | * %-ENXIO if no suitable firmware interface is present. | |
471 | */ | |
472 | int fwnode_property_read_u16_array(struct fwnode_handle *fwnode, | |
473 | const char *propname, u16 *val, size_t nval) | |
474 | { | |
475 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u16, DEV_PROP_U16, | |
476 | val, nval); | |
477 | } | |
478 | EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array); | |
479 | ||
480 | /** | |
481 | * fwnode_property_read_u32_array - return a u32 array property of firmware node | |
482 | * @fwnode: Firmware node to get the property of | |
483 | * @propname: Name of the property | |
5c0acf3b | 484 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
485 | * @nval: Size of the @val array |
486 | * | |
487 | * Read an array of u32 properties with @propname from @fwnode store them to | |
488 | * @val if found. | |
489 | * | |
5c0acf3b AH |
490 | * Return: number of values if @val was %NULL, |
491 | * %0 if the property was found (success), | |
8a0662d9 RW |
492 | * %-EINVAL if given arguments are not valid, |
493 | * %-ENODATA if the property does not have a value, | |
494 | * %-EPROTO if the property is not an array of numbers, | |
495 | * %-EOVERFLOW if the size of the property is not as expected, | |
496 | * %-ENXIO if no suitable firmware interface is present. | |
497 | */ | |
498 | int fwnode_property_read_u32_array(struct fwnode_handle *fwnode, | |
499 | const char *propname, u32 *val, size_t nval) | |
500 | { | |
501 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u32, DEV_PROP_U32, | |
502 | val, nval); | |
503 | } | |
504 | EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array); | |
505 | ||
506 | /** | |
507 | * fwnode_property_read_u64_array - return a u64 array property firmware node | |
508 | * @fwnode: Firmware node to get the property of | |
509 | * @propname: Name of the property | |
5c0acf3b | 510 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
511 | * @nval: Size of the @val array |
512 | * | |
513 | * Read an array of u64 properties with @propname from @fwnode and store them to | |
514 | * @val if found. | |
515 | * | |
5c0acf3b AH |
516 | * Return: number of values if @val was %NULL, |
517 | * %0 if the property was found (success), | |
8a0662d9 RW |
518 | * %-EINVAL if given arguments are not valid, |
519 | * %-ENODATA if the property does not have a value, | |
520 | * %-EPROTO if the property is not an array of numbers, | |
521 | * %-EOVERFLOW if the size of the property is not as expected, | |
522 | * %-ENXIO if no suitable firmware interface is present. | |
523 | */ | |
524 | int fwnode_property_read_u64_array(struct fwnode_handle *fwnode, | |
525 | const char *propname, u64 *val, size_t nval) | |
526 | { | |
527 | return FWNODE_PROP_READ_ARRAY(fwnode, propname, u64, DEV_PROP_U64, | |
528 | val, nval); | |
529 | } | |
530 | EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array); | |
531 | ||
532 | /** | |
533 | * fwnode_property_read_string_array - return string array property of a node | |
534 | * @fwnode: Firmware node to get the property of | |
535 | * @propname: Name of the property | |
5c0acf3b | 536 | * @val: The values are stored here or %NULL to return the number of values |
8a0662d9 RW |
537 | * @nval: Size of the @val array |
538 | * | |
539 | * Read an string list property @propname from the given firmware node and store | |
540 | * them to @val if found. | |
541 | * | |
5c0acf3b AH |
542 | * Return: number of values if @val was %NULL, |
543 | * %0 if the property was found (success), | |
8a0662d9 RW |
544 | * %-EINVAL if given arguments are not valid, |
545 | * %-ENODATA if the property does not have a value, | |
546 | * %-EPROTO if the property is not an array of strings, | |
547 | * %-EOVERFLOW if the size of the property is not as expected, | |
548 | * %-ENXIO if no suitable firmware interface is present. | |
549 | */ | |
550 | int fwnode_property_read_string_array(struct fwnode_handle *fwnode, | |
551 | const char *propname, const char **val, | |
552 | size_t nval) | |
553 | { | |
554 | if (is_of_node(fwnode)) | |
f42712a9 | 555 | return val ? |
c181fb3e AS |
556 | of_property_read_string_array(to_of_node(fwnode), |
557 | propname, val, nval) : | |
558 | of_property_count_strings(to_of_node(fwnode), propname); | |
8a0662d9 | 559 | else if (is_acpi_node(fwnode)) |
3a7a2ab8 RW |
560 | return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, |
561 | val, nval); | |
61f5e294 | 562 | else if (is_pset_node(fwnode)) |
318a1971 AS |
563 | return val ? |
564 | pset_prop_read_string_array(to_pset_node(fwnode), | |
565 | propname, val, nval) : | |
566 | pset_prop_count_elems_of_size(to_pset_node(fwnode), | |
567 | propname, | |
568 | sizeof(const char *)); | |
4fa7508e | 569 | return -ENXIO; |
8a0662d9 RW |
570 | } |
571 | EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); | |
572 | ||
573 | /** | |
574 | * fwnode_property_read_string - return a string property of a firmware node | |
575 | * @fwnode: Firmware node to get the property of | |
576 | * @propname: Name of the property | |
577 | * @val: The value is stored here | |
578 | * | |
579 | * Read property @propname from the given firmware node and store the value into | |
580 | * @val if found. The value is checked to be a string. | |
581 | * | |
582 | * Return: %0 if the property was found (success), | |
583 | * %-EINVAL if given arguments are not valid, | |
584 | * %-ENODATA if the property does not have a value, | |
585 | * %-EPROTO or %-EILSEQ if the property is not a string, | |
586 | * %-ENXIO if no suitable firmware interface is present. | |
587 | */ | |
588 | int fwnode_property_read_string(struct fwnode_handle *fwnode, | |
589 | const char *propname, const char **val) | |
590 | { | |
591 | if (is_of_node(fwnode)) | |
c181fb3e | 592 | return of_property_read_string(to_of_node(fwnode), propname, val); |
8a0662d9 | 593 | else if (is_acpi_node(fwnode)) |
3a7a2ab8 RW |
594 | return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, |
595 | val, 1); | |
61f5e294 | 596 | else if (is_pset_node(fwnode)) |
66586bab | 597 | return pset_prop_read_string(to_pset_node(fwnode), propname, val); |
e3f9e299 | 598 | return -ENXIO; |
8a0662d9 RW |
599 | } |
600 | EXPORT_SYMBOL_GPL(fwnode_property_read_string); | |
601 | ||
3f5c8d31 MW |
602 | /** |
603 | * fwnode_property_match_string - find a string in an array and return index | |
604 | * @fwnode: Firmware node to get the property of | |
605 | * @propname: Name of the property holding the array | |
606 | * @string: String to look for | |
607 | * | |
608 | * Find a given string in a string array and if it is found return the | |
609 | * index back. | |
610 | * | |
611 | * Return: %0 if the property was found (success), | |
612 | * %-EINVAL if given arguments are not valid, | |
613 | * %-ENODATA if the property does not have a value, | |
614 | * %-EPROTO if the property is not an array of strings, | |
615 | * %-ENXIO if no suitable firmware interface is present. | |
616 | */ | |
617 | int fwnode_property_match_string(struct fwnode_handle *fwnode, | |
618 | const char *propname, const char *string) | |
619 | { | |
620 | const char **values; | |
621 | int nval, ret, i; | |
622 | ||
623 | nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0); | |
624 | if (nval < 0) | |
625 | return nval; | |
626 | ||
627 | values = kcalloc(nval, sizeof(*values), GFP_KERNEL); | |
628 | if (!values) | |
629 | return -ENOMEM; | |
630 | ||
631 | ret = fwnode_property_read_string_array(fwnode, propname, values, nval); | |
632 | if (ret < 0) | |
633 | goto out; | |
634 | ||
635 | ret = -ENODATA; | |
636 | for (i = 0; i < nval; i++) { | |
637 | if (!strcmp(values[i], string)) { | |
638 | ret = i; | |
639 | break; | |
640 | } | |
641 | } | |
642 | out: | |
643 | kfree(values); | |
644 | return ret; | |
645 | } | |
646 | EXPORT_SYMBOL_GPL(fwnode_property_match_string); | |
647 | ||
8a0662d9 RW |
648 | /** |
649 | * device_get_next_child_node - Return the next child node handle for a device | |
650 | * @dev: Device to find the next child node for. | |
651 | * @child: Handle to one of the device's child nodes or a null handle. | |
652 | */ | |
653 | struct fwnode_handle *device_get_next_child_node(struct device *dev, | |
654 | struct fwnode_handle *child) | |
655 | { | |
656 | if (IS_ENABLED(CONFIG_OF) && dev->of_node) { | |
657 | struct device_node *node; | |
658 | ||
c181fb3e | 659 | node = of_get_next_available_child(dev->of_node, to_of_node(child)); |
8a0662d9 RW |
660 | if (node) |
661 | return &node->fwnode; | |
662 | } else if (IS_ENABLED(CONFIG_ACPI)) { | |
504a3374 | 663 | return acpi_get_next_subnode(dev, child); |
8a0662d9 RW |
664 | } |
665 | return NULL; | |
666 | } | |
667 | EXPORT_SYMBOL_GPL(device_get_next_child_node); | |
668 | ||
669 | /** | |
670 | * fwnode_handle_put - Drop reference to a device node | |
671 | * @fwnode: Pointer to the device node to drop the reference to. | |
672 | * | |
673 | * This has to be used when terminating device_for_each_child_node() iteration | |
674 | * with break or return to prevent stale device node references from being left | |
675 | * behind. | |
676 | */ | |
677 | void fwnode_handle_put(struct fwnode_handle *fwnode) | |
678 | { | |
679 | if (is_of_node(fwnode)) | |
c181fb3e | 680 | of_node_put(to_of_node(fwnode)); |
8a0662d9 RW |
681 | } |
682 | EXPORT_SYMBOL_GPL(fwnode_handle_put); | |
683 | ||
684 | /** | |
685 | * device_get_child_node_count - return the number of child nodes for device | |
686 | * @dev: Device to cound the child nodes for | |
687 | */ | |
688 | unsigned int device_get_child_node_count(struct device *dev) | |
689 | { | |
690 | struct fwnode_handle *child; | |
691 | unsigned int count = 0; | |
692 | ||
693 | device_for_each_child_node(dev, child) | |
694 | count++; | |
695 | ||
696 | return count; | |
697 | } | |
698 | EXPORT_SYMBOL_GPL(device_get_child_node_count); | |
05ca5560 | 699 | |
e5e55864 SS |
700 | bool device_dma_supported(struct device *dev) |
701 | { | |
702 | /* For DT, this is always supported. | |
703 | * For ACPI, this depends on CCA, which | |
704 | * is determined by the acpi_dma_supported(). | |
705 | */ | |
706 | if (IS_ENABLED(CONFIG_OF) && dev->of_node) | |
707 | return true; | |
708 | ||
709 | return acpi_dma_supported(ACPI_COMPANION(dev)); | |
710 | } | |
711 | EXPORT_SYMBOL_GPL(device_dma_supported); | |
712 | ||
713 | enum dev_dma_attr device_get_dma_attr(struct device *dev) | |
714 | { | |
715 | enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED; | |
716 | ||
717 | if (IS_ENABLED(CONFIG_OF) && dev->of_node) { | |
718 | if (of_dma_is_coherent(dev->of_node)) | |
719 | attr = DEV_DMA_COHERENT; | |
720 | else | |
721 | attr = DEV_DMA_NON_COHERENT; | |
722 | } else | |
723 | attr = acpi_get_dma_attr(ACPI_COMPANION(dev)); | |
724 | ||
725 | return attr; | |
726 | } | |
727 | EXPORT_SYMBOL_GPL(device_get_dma_attr); | |
728 | ||
4c96b7dc | 729 | /** |
2f710a3a | 730 | * device_get_phy_mode - Get phy mode for given device |
4c96b7dc JL |
731 | * @dev: Pointer to the given device |
732 | * | |
733 | * The function gets phy interface string from property 'phy-mode' or | |
734 | * 'phy-connection-type', and return its index in phy_modes table, or errno in | |
735 | * error case. | |
736 | */ | |
737 | int device_get_phy_mode(struct device *dev) | |
738 | { | |
739 | const char *pm; | |
740 | int err, i; | |
741 | ||
742 | err = device_property_read_string(dev, "phy-mode", &pm); | |
743 | if (err < 0) | |
744 | err = device_property_read_string(dev, | |
745 | "phy-connection-type", &pm); | |
746 | if (err < 0) | |
747 | return err; | |
748 | ||
749 | for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++) | |
750 | if (!strcasecmp(pm, phy_modes(i))) | |
751 | return i; | |
752 | ||
753 | return -ENODEV; | |
754 | } | |
755 | EXPORT_SYMBOL_GPL(device_get_phy_mode); | |
756 | ||
757 | static void *device_get_mac_addr(struct device *dev, | |
758 | const char *name, char *addr, | |
759 | int alen) | |
760 | { | |
761 | int ret = device_property_read_u8_array(dev, name, addr, alen); | |
762 | ||
2f710a3a | 763 | if (ret == 0 && alen == ETH_ALEN && is_valid_ether_addr(addr)) |
4c96b7dc JL |
764 | return addr; |
765 | return NULL; | |
766 | } | |
767 | ||
768 | /** | |
2f710a3a JL |
769 | * device_get_mac_address - Get the MAC for a given device |
770 | * @dev: Pointer to the device | |
771 | * @addr: Address of buffer to store the MAC in | |
772 | * @alen: Length of the buffer pointed to by addr, should be ETH_ALEN | |
773 | * | |
774 | * Search the firmware node for the best MAC address to use. 'mac-address' is | |
4c96b7dc JL |
775 | * checked first, because that is supposed to contain to "most recent" MAC |
776 | * address. If that isn't set, then 'local-mac-address' is checked next, | |
777 | * because that is the default address. If that isn't set, then the obsolete | |
778 | * 'address' is checked, just in case we're using an old device tree. | |
779 | * | |
780 | * Note that the 'address' property is supposed to contain a virtual address of | |
781 | * the register set, but some DTS files have redefined that property to be the | |
782 | * MAC address. | |
783 | * | |
784 | * All-zero MAC addresses are rejected, because those could be properties that | |
2f710a3a JL |
785 | * exist in the firmware tables, but were not updated by the firmware. For |
786 | * example, the DTS could define 'mac-address' and 'local-mac-address', with | |
787 | * zero MAC addresses. Some older U-Boots only initialized 'local-mac-address'. | |
788 | * In this case, the real MAC is in 'local-mac-address', and 'mac-address' | |
789 | * exists but is all zeros. | |
4c96b7dc JL |
790 | */ |
791 | void *device_get_mac_address(struct device *dev, char *addr, int alen) | |
792 | { | |
5b902d6f | 793 | char *res; |
4c96b7dc | 794 | |
5b902d6f JG |
795 | res = device_get_mac_addr(dev, "mac-address", addr, alen); |
796 | if (res) | |
797 | return res; | |
798 | ||
799 | res = device_get_mac_addr(dev, "local-mac-address", addr, alen); | |
800 | if (res) | |
801 | return res; | |
4c96b7dc JL |
802 | |
803 | return device_get_mac_addr(dev, "address", addr, alen); | |
804 | } | |
805 | EXPORT_SYMBOL(device_get_mac_address); |