aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-04-03 10:05:11 -0400
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2015-04-03 17:23:51 -0400
commit16ba08d5c9ec44f89ec03c67ecf7a9c5e2d204fd (patch)
tree7a269ca24db329c53ada5e30fabc872d68c67164
parent97badf873ab60e841243b66133ff9eff2a46ef29 (diff)
device property: Introduce firmware node type for platform data
Introduce data structures and code allowing "built-in" properties to be associated with devices in such a way that they will be used by the device_property_* API if no proper firmware node (neither DT nor ACPI) is present for the given device. Each property is to be represented by a property_entry structure. An array of property_entry structures (terminated with a null entry) can be pointed to by the properties field of struct property_set that can be added as a firmware node to a struct device using device_add_property_set(). That will cause the device_property_* API to use that property_set as the source of properties if the given device does not have a DT node or an ACPI companion device object associated with it. Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Tested-by: Heikki Krogerus <heikki.krogerus@linux.intel.com> Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/base/property.c98
-rw-r--r--include/linux/fwnode.h1
-rw-r--r--include/linux/property.h33
3 files changed, 127 insertions, 5 deletions
diff --git a/drivers/base/property.c b/drivers/base/property.c
index 62787bc89a1d..6a3f7d8af341 100644
--- a/drivers/base/property.c
+++ b/drivers/base/property.c
@@ -10,10 +10,96 @@
10 * published by the Free Software Foundation. 10 * published by the Free Software Foundation.
11 */ 11 */
12 12
13#include <linux/property.h>
14#include <linux/export.h>
15#include <linux/acpi.h> 13#include <linux/acpi.h>
14#include <linux/export.h>
15#include <linux/kernel.h>
16#include <linux/of.h> 16#include <linux/of.h>
17#include <linux/property.h>
18
19/**
20 * device_add_property_set - Add a collection of properties to a device object.
21 * @dev: Device to add properties to.
22 * @pset: Collection of properties to add.
23 *
24 * Associate a collection of device properties represented by @pset with @dev
25 * as its secondary firmware node.
26 */
27void device_add_property_set(struct device *dev, struct property_set *pset)
28{
29 if (pset)
30 pset->fwnode.type = FWNODE_PDATA;
31
32 set_secondary_fwnode(dev, &pset->fwnode);
33}
34EXPORT_SYMBOL_GPL(device_add_property_set);
35
36static inline bool is_pset(struct fwnode_handle *fwnode)
37{
38 return fwnode && fwnode->type == FWNODE_PDATA;
39}
40
41static inline struct property_set *to_pset(struct fwnode_handle *fwnode)
42{
43 return is_pset(fwnode) ?
44 container_of(fwnode, struct property_set, fwnode) : NULL;
45}
46
47static struct property_entry *pset_prop_get(struct property_set *pset,
48 const char *name)
49{
50 struct property_entry *prop;
51
52 if (!pset || !pset->properties)
53 return NULL;
54
55 for (prop = pset->properties; prop->name; prop++)
56 if (!strcmp(name, prop->name))
57 return prop;
58
59 return NULL;
60}
61
62static int pset_prop_read_array(struct property_set *pset, const char *name,
63 enum dev_prop_type type, void *val, size_t nval)
64{
65 struct property_entry *prop;
66 unsigned int item_size;
67
68 prop = pset_prop_get(pset, name);
69 if (!prop)
70 return -ENODATA;
71
72 if (prop->type != type)
73 return -EPROTO;
74
75 if (!val)
76 return prop->nval;
77
78 if (prop->nval < nval)
79 return -EOVERFLOW;
80
81 switch (type) {
82 case DEV_PROP_U8:
83 item_size = sizeof(u8);
84 break;
85 case DEV_PROP_U16:
86 item_size = sizeof(u16);
87 break;
88 case DEV_PROP_U32:
89 item_size = sizeof(u32);
90 break;
91 case DEV_PROP_U64:
92 item_size = sizeof(u64);
93 break;
94 case DEV_PROP_STRING:
95 item_size = sizeof(const char *);
96 break;
97 default:
98 return -EINVAL;
99 }
100 memcpy(val, prop->value.raw_data, nval * item_size);
101 return 0;
102}
17 103
18static inline struct fwnode_handle *dev_fwnode(struct device *dev) 104static inline struct fwnode_handle *dev_fwnode(struct device *dev)
19{ 105{
@@ -46,7 +132,7 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname)
46 else if (is_acpi_node(fwnode)) 132 else if (is_acpi_node(fwnode))
47 return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL); 133 return !acpi_dev_prop_get(acpi_node(fwnode), propname, NULL);
48 134
49 return false; 135 return !!pset_prop_get(to_pset(fwnode), propname);
50} 136}
51EXPORT_SYMBOL_GPL(fwnode_property_present); 137EXPORT_SYMBOL_GPL(fwnode_property_present);
52 138
@@ -205,7 +291,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string);
205 _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \ 291 _ret_ = acpi_dev_prop_read(acpi_node(_fwnode_), _propname_, \
206 _proptype_, _val_, _nval_); \ 292 _proptype_, _val_, _nval_); \
207 else \ 293 else \
208 _ret_ = -ENXIO; \ 294 _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \
295 _proptype_, _val_, _nval_); \
209 _ret_; \ 296 _ret_; \
210}) 297})
211 298
@@ -344,7 +431,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode,
344 return acpi_dev_prop_read(acpi_node(fwnode), propname, 431 return acpi_dev_prop_read(acpi_node(fwnode), propname,
345 DEV_PROP_STRING, val, nval); 432 DEV_PROP_STRING, val, nval);
346 433
347 return -ENXIO; 434 return pset_prop_read_array(to_pset(fwnode), propname,
435 DEV_PROP_STRING, val, nval);
348} 436}
349EXPORT_SYMBOL_GPL(fwnode_property_read_string_array); 437EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
350 438
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h
index fc30b84b532a..0408545bce42 100644
--- a/include/linux/fwnode.h
+++ b/include/linux/fwnode.h
@@ -16,6 +16,7 @@ enum fwnode_type {
16 FWNODE_INVALID = 0, 16 FWNODE_INVALID = 0,
17 FWNODE_OF, 17 FWNODE_OF,
18 FWNODE_ACPI, 18 FWNODE_ACPI,
19 FWNODE_PDATA,
19}; 20};
20 21
21struct fwnode_handle { 22struct fwnode_handle {
diff --git a/include/linux/property.h b/include/linux/property.h
index 31dfd3db35d6..de8bdf417a35 100644
--- a/include/linux/property.h
+++ b/include/linux/property.h
@@ -131,4 +131,37 @@ static inline int fwnode_property_read_u64(struct fwnode_handle *fwnode,
131 return fwnode_property_read_u64_array(fwnode, propname, val, 1); 131 return fwnode_property_read_u64_array(fwnode, propname, val, 1);
132} 132}
133 133
134/**
135 * struct property_entry - "Built-in" device property representation.
136 * @name: Name of the property.
137 * @type: Type of the property.
138 * @nval: Number of items of type @type making up the value.
139 * @value: Value of the property (an array of @nval items of type @type).
140 */
141struct property_entry {
142 const char *name;
143 enum dev_prop_type type;
144 size_t nval;
145 union {
146 void *raw_data;
147 u8 *u8_data;
148 u16 *u16_data;
149 u32 *u32_data;
150 u64 *u64_data;
151 const char **str;
152 } value;
153};
154
155/**
156 * struct property_set - Collection of "built-in" device properties.
157 * @fwnode: Handle to be pointed to by the fwnode field of struct device.
158 * @properties: Array of properties terminated with a null entry.
159 */
160struct property_set {
161 struct fwnode_handle fwnode;
162 struct property_entry *properties;
163};
164
165void device_add_property_set(struct device *dev, struct property_set *pset);
166
134#endif /* _LINUX_PROPERTY_H_ */ 167#endif /* _LINUX_PROPERTY_H_ */