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