aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/acpi/property.c178
-rw-r--r--drivers/base/Makefile2
-rw-r--r--drivers/base/property.c185
-rw-r--r--drivers/of/base.c33
-rw-r--r--include/linux/acpi.h32
-rw-r--r--include/linux/of.h12
-rw-r--r--include/linux/property.h73
7 files changed, 514 insertions, 1 deletions
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c
index c4a3e800e82c..2541b1fd1fa5 100644
--- a/drivers/acpi/property.c
+++ b/drivers/acpi/property.c
@@ -362,3 +362,181 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
362 return -EPROTO; 362 return -EPROTO;
363} 363}
364EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference); 364EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference);
365
366int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
367 void **valptr)
368{
369 return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY,
370 (const union acpi_object **)valptr);
371}
372
373int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
374 enum dev_prop_type proptype, void *val)
375{
376 const union acpi_object *obj;
377 int ret;
378
379 if (!val)
380 return -EINVAL;
381
382 if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
383 ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj);
384 if (ret)
385 return ret;
386
387 switch (proptype) {
388 case DEV_PROP_U8:
389 if (obj->integer.value > U8_MAX)
390 return -EOVERFLOW;
391 *(u8 *)val = obj->integer.value;
392 break;
393 case DEV_PROP_U16:
394 if (obj->integer.value > U16_MAX)
395 return -EOVERFLOW;
396 *(u16 *)val = obj->integer.value;
397 break;
398 case DEV_PROP_U32:
399 if (obj->integer.value > U32_MAX)
400 return -EOVERFLOW;
401 *(u32 *)val = obj->integer.value;
402 break;
403 default:
404 *(u64 *)val = obj->integer.value;
405 break;
406 }
407 } else if (proptype == DEV_PROP_STRING) {
408 ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj);
409 if (ret)
410 return ret;
411
412 *(char **)val = obj->string.pointer;
413 } else {
414 ret = -EINVAL;
415 }
416 return ret;
417}
418
419static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
420 size_t nval)
421{
422 int i;
423
424 for (i = 0; i < nval; i++) {
425 if (items[i].type != ACPI_TYPE_INTEGER)
426 return -EPROTO;
427 if (items[i].integer.value > U8_MAX)
428 return -EOVERFLOW;
429
430 val[i] = items[i].integer.value;
431 }
432 return 0;
433}
434
435static int acpi_copy_property_array_u16(const union acpi_object *items,
436 u16 *val, size_t nval)
437{
438 int i;
439
440 for (i = 0; i < nval; i++) {
441 if (items[i].type != ACPI_TYPE_INTEGER)
442 return -EPROTO;
443 if (items[i].integer.value > U16_MAX)
444 return -EOVERFLOW;
445
446 val[i] = items[i].integer.value;
447 }
448 return 0;
449}
450
451static int acpi_copy_property_array_u32(const union acpi_object *items,
452 u32 *val, size_t nval)
453{
454 int i;
455
456 for (i = 0; i < nval; i++) {
457 if (items[i].type != ACPI_TYPE_INTEGER)
458 return -EPROTO;
459 if (items[i].integer.value > U32_MAX)
460 return -EOVERFLOW;
461
462 val[i] = items[i].integer.value;
463 }
464 return 0;
465}
466
467static int acpi_copy_property_array_u64(const union acpi_object *items,
468 u64 *val, size_t nval)
469{
470 int i;
471
472 for (i = 0; i < nval; i++) {
473 if (items[i].type != ACPI_TYPE_INTEGER)
474 return -EPROTO;
475
476 val[i] = items[i].integer.value;
477 }
478 return 0;
479}
480
481static int acpi_copy_property_array_string(const union acpi_object *items,
482 char **val, size_t nval)
483{
484 int i;
485
486 for (i = 0; i < nval; i++) {
487 if (items[i].type != ACPI_TYPE_STRING)
488 return -EPROTO;
489
490 val[i] = items[i].string.pointer;
491 }
492 return 0;
493}
494
495int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
496 enum dev_prop_type proptype, void *val, size_t nval)
497{
498 const union acpi_object *obj;
499 const union acpi_object *items;
500 int ret;
501
502 if (val && nval == 1) {
503 ret = acpi_dev_prop_read_single(adev, propname, proptype, val);
504 if (!ret)
505 return ret;
506 }
507
508 ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj);
509 if (ret)
510 return ret;
511
512 if (!val)
513 return obj->package.count;
514 else if (nval <= 0)
515 return -EINVAL;
516
517 if (nval > obj->package.count)
518 return -EOVERFLOW;
519
520 items = obj->package.elements;
521 switch (proptype) {
522 case DEV_PROP_U8:
523 ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
524 break;
525 case DEV_PROP_U16:
526 ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
527 break;
528 case DEV_PROP_U32:
529 ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
530 break;
531 case DEV_PROP_U64:
532 ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
533 break;
534 case DEV_PROP_STRING:
535 ret = acpi_copy_property_array_string(items, (char **)val, nval);
536 break;
537 default:
538 ret = -EINVAL;
539 break;
540 }
541 return ret;
542}
diff --git a/drivers/base/Makefile b/drivers/base/Makefile
index 6922cd6850a2..53c3fe1aeb29 100644
--- a/drivers/base/Makefile
+++ b/drivers/base/Makefile
@@ -4,7 +4,7 @@ obj-y := component.o core.o bus.o dd.o syscore.o \
4 driver.o class.o platform.o \ 4 driver.o class.o platform.o \
5 cpu.o firmware.o init.o map.o devres.o \ 5 cpu.o firmware.o init.o map.o devres.o \
6 attribute_container.o transport_class.o \ 6 attribute_container.o transport_class.o \
7 topology.o container.o 7 topology.o container.o property.o
8obj-$(CONFIG_DEVTMPFS) += devtmpfs.o 8obj-$(CONFIG_DEVTMPFS) += devtmpfs.o
9obj-$(CONFIG_DMA_CMA) += dma-contiguous.o 9obj-$(CONFIG_DMA_CMA) += dma-contiguous.o
10obj-y += power/ 10obj-y += power/
diff --git a/drivers/base/property.c b/drivers/base/property.c
new file mode 100644
index 000000000000..6a94ef6e83c9
--- /dev/null
+++ b/drivers/base/property.c
@@ -0,0 +1,185 @@
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
13#include <linux/property.h>
14#include <linux/export.h>
15#include <linux/acpi.h>
16#include <linux/of.h>
17
18/**
19 * device_property_present - check if a property of a device is present
20 * @dev: Device whose property is being checked
21 * @propname: Name of the property
22 *
23 * Check if property @propname is present in the device firmware description.
24 */
25bool device_property_present(struct device *dev, const char *propname)
26{
27 if (IS_ENABLED(CONFIG_OF) && dev->of_node)
28 return of_property_read_bool(dev->of_node, propname);
29
30 return !acpi_dev_prop_get(ACPI_COMPANION(dev), propname, NULL);
31}
32EXPORT_SYMBOL_GPL(device_property_present);
33
34#define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \
35 (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \
36 : of_property_count_elems_of_size((node), (propname), sizeof(type))
37
38#define DEV_PROP_READ_ARRAY(_dev_, _propname_, _type_, _proptype_, _val_, _nval_) \
39 IS_ENABLED(CONFIG_OF) && _dev_->of_node ? \
40 (OF_DEV_PROP_READ_ARRAY(_dev_->of_node, _propname_, _type_, \
41 _val_, _nval_)) : \
42 acpi_dev_prop_read(ACPI_COMPANION(_dev_), _propname_, \
43 _proptype_, _val_, _nval_)
44
45/**
46 * device_property_read_u8_array - return a u8 array property of a device
47 * @dev: Device to get the property of
48 * @propname: Name of the property
49 * @val: The values are stored here
50 * @nval: Size of the @val array
51 *
52 * Function reads an array of u8 properties with @propname from the device
53 * firmware description and stores them to @val if found.
54 *
55 * Return: %0 if the property was found (success),
56 * %-EINVAL if given arguments are not valid,
57 * %-ENODATA if the property does not have a value,
58 * %-EPROTO if the property is not an array of numbers,
59 * %-EOVERFLOW if the size of the property is not as expected.
60 */
61int device_property_read_u8_array(struct device *dev, const char *propname,
62 u8 *val, size_t nval)
63{
64 return DEV_PROP_READ_ARRAY(dev, propname, u8, DEV_PROP_U8, val, nval);
65}
66EXPORT_SYMBOL_GPL(device_property_read_u8_array);
67
68/**
69 * device_property_read_u16_array - return a u16 array property of a device
70 * @dev: Device to get the property of
71 * @propname: Name of the property
72 * @val: The values are stored here
73 * @nval: Size of the @val array
74 *
75 * Function reads an array of u16 properties with @propname from the device
76 * firmware description and stores them to @val if found.
77 *
78 * Return: %0 if the property was found (success),
79 * %-EINVAL if given arguments are not valid,
80 * %-ENODATA if the property does not have a value,
81 * %-EPROTO if the property is not an array of numbers,
82 * %-EOVERFLOW if the size of the property is not as expected.
83 */
84int device_property_read_u16_array(struct device *dev, const char *propname,
85 u16 *val, size_t nval)
86{
87 return DEV_PROP_READ_ARRAY(dev, propname, u16, DEV_PROP_U16, val, nval);
88}
89EXPORT_SYMBOL_GPL(device_property_read_u16_array);
90
91/**
92 * device_property_read_u32_array - return a u32 array property of a device
93 * @dev: Device to get the property of
94 * @propname: Name of the property
95 * @val: The values are stored here
96 * @nval: Size of the @val array
97 *
98 * Function reads an array of u32 properties with @propname from the device
99 * firmware description and stores them to @val if found.
100 *
101 * Return: %0 if the property was found (success),
102 * %-EINVAL if given arguments are not valid,
103 * %-ENODATA if the property does not have a value,
104 * %-EPROTO if the property is not an array of numbers,
105 * %-EOVERFLOW if the size of the property is not as expected.
106 */
107int device_property_read_u32_array(struct device *dev, const char *propname,
108 u32 *val, size_t nval)
109{
110 return DEV_PROP_READ_ARRAY(dev, propname, u32, DEV_PROP_U32, val, nval);
111}
112EXPORT_SYMBOL_GPL(device_property_read_u32_array);
113
114/**
115 * device_property_read_u64_array - return a u64 array property of a device
116 * @dev: Device to get the property of
117 * @propname: Name of the property
118 * @val: The values are stored here
119 * @nval: Size of the @val array
120 *
121 * Function reads an array of u64 properties with @propname from the device
122 * firmware description and stores them to @val if found.
123 *
124 * Return: %0 if the property was found (success),
125 * %-EINVAL if given arguments are not valid,
126 * %-ENODATA if the property does not have a value,
127 * %-EPROTO if the property is not an array of numbers,
128 * %-EOVERFLOW if the size of the property is not as expected.
129 */
130int device_property_read_u64_array(struct device *dev, const char *propname,
131 u64 *val, size_t nval)
132{
133 return DEV_PROP_READ_ARRAY(dev, propname, u64, DEV_PROP_U64, val, nval);
134}
135EXPORT_SYMBOL_GPL(device_property_read_u64_array);
136
137/**
138 * device_property_read_string_array - return a string array property of device
139 * @dev: Device to get the property of
140 * @propname: Name of the property
141 * @val: The values are stored here
142 * @nval: Size of the @val array
143 *
144 * Function reads an array of string properties with @propname from the device
145 * firmware description and stores them to @val if found.
146 *
147 * Return: %0 if the property was found (success),
148 * %-EINVAL if given arguments are not valid,
149 * %-ENODATA if the property does not have a value,
150 * %-EPROTO or %-EILSEQ if the property is not an array of strings,
151 * %-EOVERFLOW if the size of the property is not as expected.
152 */
153int device_property_read_string_array(struct device *dev, const char *propname,
154 const char **val, size_t nval)
155{
156 return IS_ENABLED(CONFIG_OF) && dev->of_node ?
157 of_property_read_string_array(dev->of_node, propname, val, nval) :
158 acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
159 DEV_PROP_STRING, val, nval);
160}
161EXPORT_SYMBOL_GPL(device_property_read_string_array);
162
163/**
164 * device_property_read_string - return a string property of a device
165 * @dev: Device to get the property of
166 * @propname: Name of the property
167 * @val: The value is stored here
168 *
169 * Function reads property @propname from the device firmware description and
170 * stores the value into @val if found. The value is checked to be a string.
171 *
172 * Return: %0 if the property was found (success),
173 * %-EINVAL if given arguments are not valid,
174 * %-ENODATA if the property does not have a value,
175 * %-EPROTO or %-EILSEQ if the property type is not a string.
176 */
177int device_property_read_string(struct device *dev, const char *propname,
178 const char **val)
179{
180 return IS_ENABLED(CONFIG_OF) && dev->of_node ?
181 of_property_read_string(dev->of_node, propname, val) :
182 acpi_dev_prop_read(ACPI_COMPANION(dev), propname,
183 DEV_PROP_STRING, val, 1);
184}
185EXPORT_SYMBOL_GPL(device_property_read_string);
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 3823edf2d012..4c2ccde42427 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1250,6 +1250,39 @@ int of_property_read_u64(const struct device_node *np, const char *propname,
1250EXPORT_SYMBOL_GPL(of_property_read_u64); 1250EXPORT_SYMBOL_GPL(of_property_read_u64);
1251 1251
1252/** 1252/**
1253 * of_property_read_u64_array - Find and read an array of 64 bit integers
1254 * from a property.
1255 *
1256 * @np: device node from which the property value is to be read.
1257 * @propname: name of the property to be searched.
1258 * @out_values: pointer to return value, modified only if return value is 0.
1259 * @sz: number of array elements to read
1260 *
1261 * Search for a property in a device node and read 64-bit value(s) from
1262 * it. Returns 0 on success, -EINVAL if the property does not exist,
1263 * -ENODATA if property does not have a value, and -EOVERFLOW if the
1264 * property data isn't large enough.
1265 *
1266 * The out_values is modified only if a valid u64 value can be decoded.
1267 */
1268int of_property_read_u64_array(const struct device_node *np,
1269 const char *propname, u64 *out_values,
1270 size_t sz)
1271{
1272 const __be32 *val = of_find_property_value_of_size(np, propname,
1273 (sz * sizeof(*out_values)));
1274
1275 if (IS_ERR(val))
1276 return PTR_ERR(val);
1277
1278 while (sz--) {
1279 *out_values++ = of_read_number(val, 2);
1280 val += 2;
1281 }
1282 return 0;
1283}
1284
1285/**
1253 * of_property_read_string - Find and read a string from a property 1286 * of_property_read_string - Find and read a string from a property
1254 * @np: device node from which the property value is to be read. 1287 * @np: device node from which the property value is to be read.
1255 * @propname: name of the property to be searched. 1288 * @propname: name of the property to be searched.
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index dcdf8738898c..76d64d6a903a 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -28,6 +28,7 @@
28#include <linux/errno.h> 28#include <linux/errno.h>
29#include <linux/ioport.h> /* for struct resource */ 29#include <linux/ioport.h> /* for struct resource */
30#include <linux/device.h> 30#include <linux/device.h>
31#include <linux/property.h>
31 32
32#ifndef _LINUX 33#ifndef _LINUX
33#define _LINUX 34#define _LINUX
@@ -677,6 +678,13 @@ int acpi_dev_get_property_array(struct acpi_device *adev, const char *name,
677int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name, 678int acpi_dev_get_property_reference(struct acpi_device *adev, const char *name,
678 const char *cells_name, size_t index, 679 const char *cells_name, size_t index,
679 struct acpi_reference_args *args); 680 struct acpi_reference_args *args);
681
682int acpi_dev_prop_get(struct acpi_device *adev, const char *propname,
683 void **valptr);
684int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
685 enum dev_prop_type proptype, void *val);
686int acpi_dev_prop_read(struct acpi_device *adev, const char *propname,
687 enum dev_prop_type proptype, void *val, size_t nval);
680#else 688#else
681static inline int acpi_dev_get_property(struct acpi_device *adev, 689static inline int acpi_dev_get_property(struct acpi_device *adev,
682 const char *name, acpi_object_type type, 690 const char *name, acpi_object_type type,
@@ -697,6 +705,30 @@ static inline int acpi_dev_get_property_reference(struct acpi_device *adev,
697{ 705{
698 return -ENXIO; 706 return -ENXIO;
699} 707}
708
709static inline int acpi_dev_prop_get(struct acpi_device *adev,
710 const char *propname,
711 void **valptr)
712{
713 return -ENXIO;
714}
715
716static inline int acpi_dev_prop_read_single(struct acpi_device *adev,
717 const char *propname,
718 enum dev_prop_type proptype,
719 void *val)
720{
721 return -ENXIO;
722}
723
724static inline int acpi_dev_prop_read(struct acpi_device *adev,
725 const char *propname,
726 enum dev_prop_type proptype,
727 void *val, size_t nval)
728{
729 return -ENXIO;
730}
731
700#endif 732#endif
701 733
702#endif /*_LINUX_ACPI_H*/ 734#endif /*_LINUX_ACPI_H*/
diff --git a/include/linux/of.h b/include/linux/of.h
index 29f0adc5f3e4..ce9f6a2b3532 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -23,6 +23,7 @@
23#include <linux/spinlock.h> 23#include <linux/spinlock.h>
24#include <linux/topology.h> 24#include <linux/topology.h>
25#include <linux/notifier.h> 25#include <linux/notifier.h>
26#include <linux/property.h>
26 27
27#include <asm/byteorder.h> 28#include <asm/byteorder.h>
28#include <asm/errno.h> 29#include <asm/errno.h>
@@ -263,6 +264,10 @@ extern int of_property_read_u32_array(const struct device_node *np,
263 size_t sz); 264 size_t sz);
264extern int of_property_read_u64(const struct device_node *np, 265extern int of_property_read_u64(const struct device_node *np,
265 const char *propname, u64 *out_value); 266 const char *propname, u64 *out_value);
267extern int of_property_read_u64_array(const struct device_node *np,
268 const char *propname,
269 u64 *out_values,
270 size_t sz);
266 271
267extern int of_property_read_string(struct device_node *np, 272extern int of_property_read_string(struct device_node *np,
268 const char *propname, 273 const char *propname,
@@ -477,6 +482,13 @@ static inline int of_property_read_u32_array(const struct device_node *np,
477 return -ENOSYS; 482 return -ENOSYS;
478} 483}
479 484
485static inline int of_property_read_u64_array(const struct device_node *np,
486 const char *propname,
487 u64 *out_values, size_t sz)
488{
489 return -ENOSYS;
490}
491
480static inline int of_property_read_string(struct device_node *np, 492static inline int of_property_read_string(struct device_node *np,
481 const char *propname, 493 const char *propname,
482 const char **out_string) 494 const char **out_string)
diff --git a/include/linux/property.h b/include/linux/property.h
new file mode 100644
index 000000000000..9242fb0221ba
--- /dev/null
+++ b/include/linux/property.h
@@ -0,0 +1,73 @@
1/*
2 * property.h - 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
13#ifndef _LINUX_PROPERTY_H_
14#define _LINUX_PROPERTY_H_
15
16#include <linux/types.h>
17
18struct device;
19
20enum dev_prop_type {
21 DEV_PROP_U8,
22 DEV_PROP_U16,
23 DEV_PROP_U32,
24 DEV_PROP_U64,
25 DEV_PROP_STRING,
26 DEV_PROP_MAX,
27};
28
29bool device_property_present(struct device *dev, const char *propname);
30int device_property_read_u8_array(struct device *dev, const char *propname,
31 u8 *val, size_t nval);
32int device_property_read_u16_array(struct device *dev, const char *propname,
33 u16 *val, size_t nval);
34int device_property_read_u32_array(struct device *dev, const char *propname,
35 u32 *val, size_t nval);
36int device_property_read_u64_array(struct device *dev, const char *propname,
37 u64 *val, size_t nval);
38int device_property_read_string_array(struct device *dev, const char *propname,
39 const char **val, size_t nval);
40int device_property_read_string(struct device *dev, const char *propname,
41 const char **val);
42
43static inline bool device_property_read_bool(struct device *dev,
44 const char *propname)
45{
46 return device_property_present(dev, propname);
47}
48
49static inline int device_property_read_u8(struct device *dev,
50 const char *propname, u8 *val)
51{
52 return device_property_read_u8_array(dev, propname, val, 1);
53}
54
55static inline int device_property_read_u16(struct device *dev,
56 const char *propname, u16 *val)
57{
58 return device_property_read_u16_array(dev, propname, val, 1);
59}
60
61static inline int device_property_read_u32(struct device *dev,
62 const char *propname, u32 *val)
63{
64 return device_property_read_u32_array(dev, propname, val, 1);
65}
66
67static inline int device_property_read_u64(struct device *dev,
68 const char *propname, u64 *val)
69{
70 return device_property_read_u64_array(dev, propname, val, 1);
71}
72
73#endif /* _LINUX_PROPERTY_H_ */