diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-09-30 20:18:32 -0400 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2015-09-30 20:18:32 -0400 |
commit | 233782495f161341a82aa933b42b35c94077bd65 (patch) | |
tree | d1c41d11cd7662c85667005643f6dc1aa2289799 | |
parent | 9ffecb10283508260936b96022d4ee43a7798b4c (diff) | |
parent | 3f4232ee8b53cf2266d227af299aa511d2d91d11 (diff) |
Merge branch 'device-properties' into acpi-init
-rw-r--r-- | drivers/acpi/device_sysfs.c | 120 | ||||
-rw-r--r-- | drivers/acpi/property.c | 420 | ||||
-rw-r--r-- | drivers/acpi/scan.c | 20 | ||||
-rw-r--r-- | drivers/base/property.c | 88 | ||||
-rw-r--r-- | drivers/dma/acpi-dma.c | 25 | ||||
-rw-r--r-- | drivers/gpio/gpiolib-acpi.c | 153 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.c | 3 | ||||
-rw-r--r-- | drivers/gpio/gpiolib.h | 10 | ||||
-rw-r--r-- | include/acpi/acpi_bus.h | 33 | ||||
-rw-r--r-- | include/linux/acpi.h | 70 | ||||
-rw-r--r-- | include/linux/fwnode.h | 1 | ||||
-rw-r--r-- | include/linux/property.h | 4 |
12 files changed, 753 insertions, 194 deletions
diff --git a/drivers/acpi/device_sysfs.c b/drivers/acpi/device_sysfs.c index 4ab4582e586b..707cf6213bc2 100644 --- a/drivers/acpi/device_sysfs.c +++ b/drivers/acpi/device_sysfs.c | |||
@@ -26,6 +26,106 @@ | |||
26 | 26 | ||
27 | #include "internal.h" | 27 | #include "internal.h" |
28 | 28 | ||
29 | static ssize_t acpi_object_path(acpi_handle handle, char *buf) | ||
30 | { | ||
31 | struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
32 | int result; | ||
33 | |||
34 | result = acpi_get_name(handle, ACPI_FULL_PATHNAME, &path); | ||
35 | if (result) | ||
36 | return result; | ||
37 | |||
38 | result = sprintf(buf, "%s\n", (char*)path.pointer); | ||
39 | kfree(path.pointer); | ||
40 | return result; | ||
41 | } | ||
42 | |||
43 | struct acpi_data_node_attr { | ||
44 | struct attribute attr; | ||
45 | ssize_t (*show)(struct acpi_data_node *, char *); | ||
46 | ssize_t (*store)(struct acpi_data_node *, const char *, size_t count); | ||
47 | }; | ||
48 | |||
49 | #define DATA_NODE_ATTR(_name) \ | ||
50 | static struct acpi_data_node_attr data_node_##_name = \ | ||
51 | __ATTR(_name, 0444, data_node_show_##_name, NULL) | ||
52 | |||
53 | static ssize_t data_node_show_path(struct acpi_data_node *dn, char *buf) | ||
54 | { | ||
55 | return acpi_object_path(dn->handle, buf); | ||
56 | } | ||
57 | |||
58 | DATA_NODE_ATTR(path); | ||
59 | |||
60 | static struct attribute *acpi_data_node_default_attrs[] = { | ||
61 | &data_node_path.attr, | ||
62 | NULL | ||
63 | }; | ||
64 | |||
65 | #define to_data_node(k) container_of(k, struct acpi_data_node, kobj) | ||
66 | #define to_attr(a) container_of(a, struct acpi_data_node_attr, attr) | ||
67 | |||
68 | static ssize_t acpi_data_node_attr_show(struct kobject *kobj, | ||
69 | struct attribute *attr, char *buf) | ||
70 | { | ||
71 | struct acpi_data_node *dn = to_data_node(kobj); | ||
72 | struct acpi_data_node_attr *dn_attr = to_attr(attr); | ||
73 | |||
74 | return dn_attr->show ? dn_attr->show(dn, buf) : -ENXIO; | ||
75 | } | ||
76 | |||
77 | static const struct sysfs_ops acpi_data_node_sysfs_ops = { | ||
78 | .show = acpi_data_node_attr_show, | ||
79 | }; | ||
80 | |||
81 | static void acpi_data_node_release(struct kobject *kobj) | ||
82 | { | ||
83 | struct acpi_data_node *dn = to_data_node(kobj); | ||
84 | complete(&dn->kobj_done); | ||
85 | } | ||
86 | |||
87 | static struct kobj_type acpi_data_node_ktype = { | ||
88 | .sysfs_ops = &acpi_data_node_sysfs_ops, | ||
89 | .default_attrs = acpi_data_node_default_attrs, | ||
90 | .release = acpi_data_node_release, | ||
91 | }; | ||
92 | |||
93 | static void acpi_expose_nondev_subnodes(struct kobject *kobj, | ||
94 | struct acpi_device_data *data) | ||
95 | { | ||
96 | struct list_head *list = &data->subnodes; | ||
97 | struct acpi_data_node *dn; | ||
98 | |||
99 | if (list_empty(list)) | ||
100 | return; | ||
101 | |||
102 | list_for_each_entry(dn, list, sibling) { | ||
103 | int ret; | ||
104 | |||
105 | init_completion(&dn->kobj_done); | ||
106 | ret = kobject_init_and_add(&dn->kobj, &acpi_data_node_ktype, | ||
107 | kobj, dn->name); | ||
108 | if (ret) | ||
109 | acpi_handle_err(dn->handle, "Failed to expose (%d)\n", ret); | ||
110 | else | ||
111 | acpi_expose_nondev_subnodes(&dn->kobj, &dn->data); | ||
112 | } | ||
113 | } | ||
114 | |||
115 | static void acpi_hide_nondev_subnodes(struct acpi_device_data *data) | ||
116 | { | ||
117 | struct list_head *list = &data->subnodes; | ||
118 | struct acpi_data_node *dn; | ||
119 | |||
120 | if (list_empty(list)) | ||
121 | return; | ||
122 | |||
123 | list_for_each_entry_reverse(dn, list, sibling) { | ||
124 | acpi_hide_nondev_subnodes(&dn->data); | ||
125 | kobject_put(&dn->kobj); | ||
126 | } | ||
127 | } | ||
128 | |||
29 | /** | 129 | /** |
30 | * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent | 130 | * create_pnp_modalias - Create hid/cid(s) string for modalias and uevent |
31 | * @acpi_dev: ACPI device object. | 131 | * @acpi_dev: ACPI device object. |
@@ -323,20 +423,12 @@ static ssize_t acpi_device_adr_show(struct device *dev, | |||
323 | } | 423 | } |
324 | static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL); | 424 | static DEVICE_ATTR(adr, 0444, acpi_device_adr_show, NULL); |
325 | 425 | ||
326 | static ssize_t | 426 | static ssize_t acpi_device_path_show(struct device *dev, |
327 | acpi_device_path_show(struct device *dev, struct device_attribute *attr, char *buf) { | 427 | struct device_attribute *attr, char *buf) |
428 | { | ||
328 | struct acpi_device *acpi_dev = to_acpi_device(dev); | 429 | struct acpi_device *acpi_dev = to_acpi_device(dev); |
329 | struct acpi_buffer path = {ACPI_ALLOCATE_BUFFER, NULL}; | ||
330 | int result; | ||
331 | |||
332 | result = acpi_get_name(acpi_dev->handle, ACPI_FULL_PATHNAME, &path); | ||
333 | if (result) | ||
334 | goto end; | ||
335 | 430 | ||
336 | result = sprintf(buf, "%s\n", (char*)path.pointer); | 431 | return acpi_object_path(acpi_dev->handle, buf); |
337 | kfree(path.pointer); | ||
338 | end: | ||
339 | return result; | ||
340 | } | 432 | } |
341 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); | 433 | static DEVICE_ATTR(path, 0444, acpi_device_path_show, NULL); |
342 | 434 | ||
@@ -475,6 +567,8 @@ int acpi_device_setup_files(struct acpi_device *dev) | |||
475 | &dev_attr_real_power_state); | 567 | &dev_attr_real_power_state); |
476 | } | 568 | } |
477 | 569 | ||
570 | acpi_expose_nondev_subnodes(&dev->dev.kobj, &dev->data); | ||
571 | |||
478 | end: | 572 | end: |
479 | return result; | 573 | return result; |
480 | } | 574 | } |
@@ -485,6 +579,8 @@ end: | |||
485 | */ | 579 | */ |
486 | void acpi_device_remove_files(struct acpi_device *dev) | 580 | void acpi_device_remove_files(struct acpi_device *dev) |
487 | { | 581 | { |
582 | acpi_hide_nondev_subnodes(&dev->data); | ||
583 | |||
488 | if (dev->flags.power_manageable) { | 584 | if (dev->flags.power_manageable) { |
489 | device_remove_file(&dev->dev, &dev_attr_power_state); | 585 | device_remove_file(&dev->dev, &dev_attr_power_state); |
490 | if (dev->power.flags.power_resources) | 586 | if (dev->power.flags.power_resources) |
diff --git a/drivers/acpi/property.c b/drivers/acpi/property.c index 6d99450549c5..14654435c295 100644 --- a/drivers/acpi/property.c +++ b/drivers/acpi/property.c | |||
@@ -19,11 +19,126 @@ | |||
19 | 19 | ||
20 | #include "internal.h" | 20 | #include "internal.h" |
21 | 21 | ||
22 | static int acpi_data_get_property_array(struct acpi_device_data *data, | ||
23 | const char *name, | ||
24 | acpi_object_type type, | ||
25 | const union acpi_object **obj); | ||
26 | |||
22 | /* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ | 27 | /* ACPI _DSD device properties UUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */ |
23 | static const u8 prp_uuid[16] = { | 28 | static const u8 prp_uuid[16] = { |
24 | 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, | 29 | 0x14, 0xd8, 0xff, 0xda, 0xba, 0x6e, 0x8c, 0x4d, |
25 | 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 | 30 | 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01 |
26 | }; | 31 | }; |
32 | /* ACPI _DSD data subnodes UUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */ | ||
33 | static const u8 ads_uuid[16] = { | ||
34 | 0xe6, 0xe3, 0xb8, 0xdb, 0x86, 0x58, 0xa6, 0x4b, | ||
35 | 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b | ||
36 | }; | ||
37 | |||
38 | static bool acpi_enumerate_nondev_subnodes(acpi_handle scope, | ||
39 | const union acpi_object *desc, | ||
40 | struct acpi_device_data *data); | ||
41 | static bool acpi_extract_properties(const union acpi_object *desc, | ||
42 | struct acpi_device_data *data); | ||
43 | |||
44 | static bool acpi_nondev_subnode_ok(acpi_handle scope, | ||
45 | const union acpi_object *link, | ||
46 | struct list_head *list) | ||
47 | { | ||
48 | struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; | ||
49 | struct acpi_data_node *dn; | ||
50 | acpi_handle handle; | ||
51 | acpi_status status; | ||
52 | |||
53 | dn = kzalloc(sizeof(*dn), GFP_KERNEL); | ||
54 | if (!dn) | ||
55 | return false; | ||
56 | |||
57 | dn->name = link->package.elements[0].string.pointer; | ||
58 | dn->fwnode.type = FWNODE_ACPI_DATA; | ||
59 | INIT_LIST_HEAD(&dn->data.subnodes); | ||
60 | |||
61 | status = acpi_get_handle(scope, link->package.elements[1].string.pointer, | ||
62 | &handle); | ||
63 | if (ACPI_FAILURE(status)) | ||
64 | goto fail; | ||
65 | |||
66 | status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf, | ||
67 | ACPI_TYPE_PACKAGE); | ||
68 | if (ACPI_FAILURE(status)) | ||
69 | goto fail; | ||
70 | |||
71 | if (acpi_extract_properties(buf.pointer, &dn->data)) | ||
72 | dn->handle = handle; | ||
73 | |||
74 | if (acpi_enumerate_nondev_subnodes(scope, buf.pointer, &dn->data)) | ||
75 | dn->handle = handle; | ||
76 | |||
77 | if (dn->handle) { | ||
78 | dn->data.pointer = buf.pointer; | ||
79 | list_add_tail(&dn->sibling, list); | ||
80 | return true; | ||
81 | } | ||
82 | |||
83 | acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n"); | ||
84 | |||
85 | fail: | ||
86 | ACPI_FREE(buf.pointer); | ||
87 | kfree(dn); | ||
88 | return false; | ||
89 | } | ||
90 | |||
91 | static int acpi_add_nondev_subnodes(acpi_handle scope, | ||
92 | const union acpi_object *links, | ||
93 | struct list_head *list) | ||
94 | { | ||
95 | bool ret = false; | ||
96 | int i; | ||
97 | |||
98 | for (i = 0; i < links->package.count; i++) { | ||
99 | const union acpi_object *link; | ||
100 | |||
101 | link = &links->package.elements[i]; | ||
102 | /* Only two elements allowed, both must be strings. */ | ||
103 | if (link->package.count == 2 | ||
104 | && link->package.elements[0].type == ACPI_TYPE_STRING | ||
105 | && link->package.elements[1].type == ACPI_TYPE_STRING | ||
106 | && acpi_nondev_subnode_ok(scope, link, list)) | ||
107 | ret = true; | ||
108 | } | ||
109 | |||
110 | return ret; | ||
111 | } | ||
112 | |||
113 | static bool acpi_enumerate_nondev_subnodes(acpi_handle scope, | ||
114 | const union acpi_object *desc, | ||
115 | struct acpi_device_data *data) | ||
116 | { | ||
117 | int i; | ||
118 | |||
119 | /* Look for the ACPI data subnodes UUID. */ | ||
120 | for (i = 0; i < desc->package.count; i += 2) { | ||
121 | const union acpi_object *uuid, *links; | ||
122 | |||
123 | uuid = &desc->package.elements[i]; | ||
124 | links = &desc->package.elements[i + 1]; | ||
125 | |||
126 | /* | ||
127 | * The first element must be a UUID and the second one must be | ||
128 | * a package. | ||
129 | */ | ||
130 | if (uuid->type != ACPI_TYPE_BUFFER || uuid->buffer.length != 16 | ||
131 | || links->type != ACPI_TYPE_PACKAGE) | ||
132 | break; | ||
133 | |||
134 | if (memcmp(uuid->buffer.pointer, ads_uuid, sizeof(ads_uuid))) | ||
135 | continue; | ||
136 | |||
137 | return acpi_add_nondev_subnodes(scope, links, &data->subnodes); | ||
138 | } | ||
139 | |||
140 | return false; | ||
141 | } | ||
27 | 142 | ||
28 | static bool acpi_property_value_ok(const union acpi_object *value) | 143 | static bool acpi_property_value_ok(const union acpi_object *value) |
29 | { | 144 | { |
@@ -81,8 +196,8 @@ static void acpi_init_of_compatible(struct acpi_device *adev) | |||
81 | const union acpi_object *of_compatible; | 196 | const union acpi_object *of_compatible; |
82 | int ret; | 197 | int ret; |
83 | 198 | ||
84 | ret = acpi_dev_get_property_array(adev, "compatible", ACPI_TYPE_STRING, | 199 | ret = acpi_data_get_property_array(&adev->data, "compatible", |
85 | &of_compatible); | 200 | ACPI_TYPE_STRING, &of_compatible); |
86 | if (ret) { | 201 | if (ret) { |
87 | ret = acpi_dev_get_property(adev, "compatible", | 202 | ret = acpi_dev_get_property(adev, "compatible", |
88 | ACPI_TYPE_STRING, &of_compatible); | 203 | ACPI_TYPE_STRING, &of_compatible); |
@@ -100,34 +215,13 @@ static void acpi_init_of_compatible(struct acpi_device *adev) | |||
100 | adev->flags.of_compatible_ok = 1; | 215 | adev->flags.of_compatible_ok = 1; |
101 | } | 216 | } |
102 | 217 | ||
103 | void acpi_init_properties(struct acpi_device *adev) | 218 | static bool acpi_extract_properties(const union acpi_object *desc, |
219 | struct acpi_device_data *data) | ||
104 | { | 220 | { |
105 | struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; | ||
106 | bool acpi_of = false; | ||
107 | struct acpi_hardware_id *hwid; | ||
108 | const union acpi_object *desc; | ||
109 | acpi_status status; | ||
110 | int i; | 221 | int i; |
111 | 222 | ||
112 | /* | ||
113 | * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in | ||
114 | * Device Tree compatible properties for this device. | ||
115 | */ | ||
116 | list_for_each_entry(hwid, &adev->pnp.ids, list) { | ||
117 | if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) { | ||
118 | acpi_of = true; | ||
119 | break; | ||
120 | } | ||
121 | } | ||
122 | |||
123 | status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf, | ||
124 | ACPI_TYPE_PACKAGE); | ||
125 | if (ACPI_FAILURE(status)) | ||
126 | goto out; | ||
127 | |||
128 | desc = buf.pointer; | ||
129 | if (desc->package.count % 2) | 223 | if (desc->package.count % 2) |
130 | goto fail; | 224 | return false; |
131 | 225 | ||
132 | /* Look for the device properties UUID. */ | 226 | /* Look for the device properties UUID. */ |
133 | for (i = 0; i < desc->package.count; i += 2) { | 227 | for (i = 0; i < desc->package.count; i += 2) { |
@@ -154,18 +248,50 @@ void acpi_init_properties(struct acpi_device *adev) | |||
154 | if (!acpi_properties_format_valid(properties)) | 248 | if (!acpi_properties_format_valid(properties)) |
155 | break; | 249 | break; |
156 | 250 | ||
157 | adev->data.pointer = buf.pointer; | 251 | data->properties = properties; |
158 | adev->data.properties = properties; | 252 | return true; |
253 | } | ||
159 | 254 | ||
160 | if (acpi_of) | 255 | return false; |
161 | acpi_init_of_compatible(adev); | 256 | } |
257 | |||
258 | void acpi_init_properties(struct acpi_device *adev) | ||
259 | { | ||
260 | struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; | ||
261 | struct acpi_hardware_id *hwid; | ||
262 | acpi_status status; | ||
263 | bool acpi_of = false; | ||
264 | |||
265 | INIT_LIST_HEAD(&adev->data.subnodes); | ||
162 | 266 | ||
267 | /* | ||
268 | * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in | ||
269 | * Device Tree compatible properties for this device. | ||
270 | */ | ||
271 | list_for_each_entry(hwid, &adev->pnp.ids, list) { | ||
272 | if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) { | ||
273 | acpi_of = true; | ||
274 | break; | ||
275 | } | ||
276 | } | ||
277 | |||
278 | status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf, | ||
279 | ACPI_TYPE_PACKAGE); | ||
280 | if (ACPI_FAILURE(status)) | ||
163 | goto out; | 281 | goto out; |
282 | |||
283 | if (acpi_extract_properties(buf.pointer, &adev->data)) { | ||
284 | adev->data.pointer = buf.pointer; | ||
285 | if (acpi_of) | ||
286 | acpi_init_of_compatible(adev); | ||
164 | } | 287 | } |
288 | if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer, &adev->data)) | ||
289 | adev->data.pointer = buf.pointer; | ||
165 | 290 | ||
166 | fail: | 291 | if (!adev->data.pointer) { |
167 | dev_dbg(&adev->dev, "Returned _DSD data is not valid, skipping\n"); | 292 | acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n"); |
168 | ACPI_FREE(buf.pointer); | 293 | ACPI_FREE(buf.pointer); |
294 | } | ||
169 | 295 | ||
170 | out: | 296 | out: |
171 | if (acpi_of && !adev->flags.of_compatible_ok) | 297 | if (acpi_of && !adev->flags.of_compatible_ok) |
@@ -173,8 +299,25 @@ void acpi_init_properties(struct acpi_device *adev) | |||
173 | ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n"); | 299 | ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n"); |
174 | } | 300 | } |
175 | 301 | ||
302 | static void acpi_destroy_nondev_subnodes(struct list_head *list) | ||
303 | { | ||
304 | struct acpi_data_node *dn, *next; | ||
305 | |||
306 | if (list_empty(list)) | ||
307 | return; | ||
308 | |||
309 | list_for_each_entry_safe_reverse(dn, next, list, sibling) { | ||
310 | acpi_destroy_nondev_subnodes(&dn->data.subnodes); | ||
311 | wait_for_completion(&dn->kobj_done); | ||
312 | list_del(&dn->sibling); | ||
313 | ACPI_FREE((void *)dn->data.pointer); | ||
314 | kfree(dn); | ||
315 | } | ||
316 | } | ||
317 | |||
176 | void acpi_free_properties(struct acpi_device *adev) | 318 | void acpi_free_properties(struct acpi_device *adev) |
177 | { | 319 | { |
320 | acpi_destroy_nondev_subnodes(&adev->data.subnodes); | ||
178 | ACPI_FREE((void *)adev->data.pointer); | 321 | ACPI_FREE((void *)adev->data.pointer); |
179 | adev->data.of_compatible = NULL; | 322 | adev->data.of_compatible = NULL; |
180 | adev->data.pointer = NULL; | 323 | adev->data.pointer = NULL; |
@@ -182,8 +325,8 @@ void acpi_free_properties(struct acpi_device *adev) | |||
182 | } | 325 | } |
183 | 326 | ||
184 | /** | 327 | /** |
185 | * acpi_dev_get_property - return an ACPI property with given name | 328 | * acpi_data_get_property - return an ACPI property with given name |
186 | * @adev: ACPI device to get property | 329 | * @data: ACPI device deta object to get the property from |
187 | * @name: Name of the property | 330 | * @name: Name of the property |
188 | * @type: Expected property type | 331 | * @type: Expected property type |
189 | * @obj: Location to store the property value (if not %NULL) | 332 | * @obj: Location to store the property value (if not %NULL) |
@@ -192,26 +335,27 @@ void acpi_free_properties(struct acpi_device *adev) | |||
192 | * object at the location pointed to by @obj if found. | 335 | * object at the location pointed to by @obj if found. |
193 | * | 336 | * |
194 | * Callers must not attempt to free the returned objects. These objects will be | 337 | * Callers must not attempt to free the returned objects. These objects will be |
195 | * freed by the ACPI core automatically during the removal of @adev. | 338 | * freed by the ACPI core automatically during the removal of @data. |
196 | * | 339 | * |
197 | * Return: %0 if property with @name has been found (success), | 340 | * Return: %0 if property with @name has been found (success), |
198 | * %-EINVAL if the arguments are invalid, | 341 | * %-EINVAL if the arguments are invalid, |
199 | * %-ENODATA if the property doesn't exist, | 342 | * %-ENODATA if the property doesn't exist, |
200 | * %-EPROTO if the property value type doesn't match @type. | 343 | * %-EPROTO if the property value type doesn't match @type. |
201 | */ | 344 | */ |
202 | int acpi_dev_get_property(struct acpi_device *adev, const char *name, | 345 | static int acpi_data_get_property(struct acpi_device_data *data, |
203 | acpi_object_type type, const union acpi_object **obj) | 346 | const char *name, acpi_object_type type, |
347 | const union acpi_object **obj) | ||
204 | { | 348 | { |
205 | const union acpi_object *properties; | 349 | const union acpi_object *properties; |
206 | int i; | 350 | int i; |
207 | 351 | ||
208 | if (!adev || !name) | 352 | if (!data || !name) |
209 | return -EINVAL; | 353 | return -EINVAL; |
210 | 354 | ||
211 | if (!adev->data.pointer || !adev->data.properties) | 355 | if (!data->pointer || !data->properties) |
212 | return -ENODATA; | 356 | return -ENODATA; |
213 | 357 | ||
214 | properties = adev->data.properties; | 358 | properties = data->properties; |
215 | for (i = 0; i < properties->package.count; i++) { | 359 | for (i = 0; i < properties->package.count; i++) { |
216 | const union acpi_object *propname, *propvalue; | 360 | const union acpi_object *propname, *propvalue; |
217 | const union acpi_object *property; | 361 | const union acpi_object *property; |
@@ -232,11 +376,50 @@ int acpi_dev_get_property(struct acpi_device *adev, const char *name, | |||
232 | } | 376 | } |
233 | return -ENODATA; | 377 | return -ENODATA; |
234 | } | 378 | } |
379 | |||
380 | /** | ||
381 | * acpi_dev_get_property - return an ACPI property with given name. | ||
382 | * @adev: ACPI device to get the property from. | ||
383 | * @name: Name of the property. | ||
384 | * @type: Expected property type. | ||
385 | * @obj: Location to store the property value (if not %NULL). | ||
386 | */ | ||
387 | int acpi_dev_get_property(struct acpi_device *adev, const char *name, | ||
388 | acpi_object_type type, const union acpi_object **obj) | ||
389 | { | ||
390 | return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL; | ||
391 | } | ||
235 | EXPORT_SYMBOL_GPL(acpi_dev_get_property); | 392 | EXPORT_SYMBOL_GPL(acpi_dev_get_property); |
236 | 393 | ||
394 | static struct acpi_device_data *acpi_device_data_of_node(struct fwnode_handle *fwnode) | ||
395 | { | ||
396 | if (fwnode->type == FWNODE_ACPI) { | ||
397 | struct acpi_device *adev = to_acpi_device_node(fwnode); | ||
398 | return &adev->data; | ||
399 | } else if (fwnode->type == FWNODE_ACPI_DATA) { | ||
400 | struct acpi_data_node *dn = to_acpi_data_node(fwnode); | ||
401 | return &dn->data; | ||
402 | } | ||
403 | return NULL; | ||
404 | } | ||
405 | |||
406 | /** | ||
407 | * acpi_node_prop_get - return an ACPI property with given name. | ||
408 | * @fwnode: Firmware node to get the property from. | ||
409 | * @propname: Name of the property. | ||
410 | * @valptr: Location to store a pointer to the property value (if not %NULL). | ||
411 | */ | ||
412 | int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, | ||
413 | void **valptr) | ||
414 | { | ||
415 | return acpi_data_get_property(acpi_device_data_of_node(fwnode), | ||
416 | propname, ACPI_TYPE_ANY, | ||
417 | (const union acpi_object **)valptr); | ||
418 | } | ||
419 | |||
237 | /** | 420 | /** |
238 | * acpi_dev_get_property_array - return an ACPI array property with given name | 421 | * acpi_data_get_property_array - return an ACPI array property with given name |
239 | * @adev: ACPI device to get property | 422 | * @adev: ACPI data object to get the property from |
240 | * @name: Name of the property | 423 | * @name: Name of the property |
241 | * @type: Expected type of array elements | 424 | * @type: Expected type of array elements |
242 | * @obj: Location to store a pointer to the property value (if not NULL) | 425 | * @obj: Location to store a pointer to the property value (if not NULL) |
@@ -245,7 +428,7 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property); | |||
245 | * ACPI object at the location pointed to by @obj if found. | 428 | * ACPI object at the location pointed to by @obj if found. |
246 | * | 429 | * |
247 | * Callers must not attempt to free the returned objects. Those objects will be | 430 | * Callers must not attempt to free the returned objects. Those objects will be |
248 | * freed by the ACPI core automatically during the removal of @adev. | 431 | * freed by the ACPI core automatically during the removal of @data. |
249 | * | 432 | * |
250 | * Return: %0 if array property (package) with @name has been found (success), | 433 | * Return: %0 if array property (package) with @name has been found (success), |
251 | * %-EINVAL if the arguments are invalid, | 434 | * %-EINVAL if the arguments are invalid, |
@@ -253,14 +436,15 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property); | |||
253 | * %-EPROTO if the property is not a package or the type of its elements | 436 | * %-EPROTO if the property is not a package or the type of its elements |
254 | * doesn't match @type. | 437 | * doesn't match @type. |
255 | */ | 438 | */ |
256 | int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, | 439 | static int acpi_data_get_property_array(struct acpi_device_data *data, |
257 | acpi_object_type type, | 440 | const char *name, |
258 | const union acpi_object **obj) | 441 | acpi_object_type type, |
442 | const union acpi_object **obj) | ||
259 | { | 443 | { |
260 | const union acpi_object *prop; | 444 | const union acpi_object *prop; |
261 | int ret, i; | 445 | int ret, i; |
262 | 446 | ||
263 | ret = acpi_dev_get_property(adev, name, ACPI_TYPE_PACKAGE, &prop); | 447 | ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop); |
264 | if (ret) | 448 | if (ret) |
265 | return ret; | 449 | return ret; |
266 | 450 | ||
@@ -275,12 +459,11 @@ int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, | |||
275 | 459 | ||
276 | return 0; | 460 | return 0; |
277 | } | 461 | } |
278 | EXPORT_SYMBOL_GPL(acpi_dev_get_property_array); | ||
279 | 462 | ||
280 | /** | 463 | /** |
281 | * acpi_dev_get_property_reference - returns handle to the referenced object | 464 | * acpi_data_get_property_reference - returns handle to the referenced object |
282 | * @adev: ACPI device to get property | 465 | * @data: ACPI device data object containing the property |
283 | * @name: Name of the property | 466 | * @propname: Name of the property |
284 | * @index: Index of the reference to return | 467 | * @index: Index of the reference to return |
285 | * @args: Location to store the returned reference with optional arguments | 468 | * @args: Location to store the returned reference with optional arguments |
286 | * | 469 | * |
@@ -294,16 +477,16 @@ EXPORT_SYMBOL_GPL(acpi_dev_get_property_array); | |||
294 | * | 477 | * |
295 | * Return: %0 on success, negative error code on failure. | 478 | * Return: %0 on success, negative error code on failure. |
296 | */ | 479 | */ |
297 | int acpi_dev_get_property_reference(struct acpi_device *adev, | 480 | static int acpi_data_get_property_reference(struct acpi_device_data *data, |
298 | const char *name, size_t index, | 481 | const char *propname, size_t index, |
299 | struct acpi_reference_args *args) | 482 | struct acpi_reference_args *args) |
300 | { | 483 | { |
301 | const union acpi_object *element, *end; | 484 | const union acpi_object *element, *end; |
302 | const union acpi_object *obj; | 485 | const union acpi_object *obj; |
303 | struct acpi_device *device; | 486 | struct acpi_device *device; |
304 | int ret, idx = 0; | 487 | int ret, idx = 0; |
305 | 488 | ||
306 | ret = acpi_dev_get_property(adev, name, ACPI_TYPE_ANY, &obj); | 489 | ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj); |
307 | if (ret) | 490 | if (ret) |
308 | return ret; | 491 | return ret; |
309 | 492 | ||
@@ -378,17 +561,27 @@ int acpi_dev_get_property_reference(struct acpi_device *adev, | |||
378 | 561 | ||
379 | return -EPROTO; | 562 | return -EPROTO; |
380 | } | 563 | } |
381 | EXPORT_SYMBOL_GPL(acpi_dev_get_property_reference); | ||
382 | 564 | ||
383 | int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, | 565 | /** |
384 | void **valptr) | 566 | * acpi_node_get_property_reference - get a handle to the referenced object. |
567 | * @fwnode: Firmware node to get the property from. | ||
568 | * @propname: Name of the property. | ||
569 | * @index: Index of the reference to return. | ||
570 | * @args: Location to store the returned reference with optional arguments. | ||
571 | */ | ||
572 | int acpi_node_get_property_reference(struct fwnode_handle *fwnode, | ||
573 | const char *name, size_t index, | ||
574 | struct acpi_reference_args *args) | ||
385 | { | 575 | { |
386 | return acpi_dev_get_property(adev, propname, ACPI_TYPE_ANY, | 576 | struct acpi_device_data *data = acpi_device_data_of_node(fwnode); |
387 | (const union acpi_object **)valptr); | 577 | |
578 | return data ? acpi_data_get_property_reference(data, name, index, args) : -EINVAL; | ||
388 | } | 579 | } |
580 | EXPORT_SYMBOL_GPL(acpi_node_get_property_reference); | ||
389 | 581 | ||
390 | int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, | 582 | static int acpi_data_prop_read_single(struct acpi_device_data *data, |
391 | enum dev_prop_type proptype, void *val) | 583 | const char *propname, |
584 | enum dev_prop_type proptype, void *val) | ||
392 | { | 585 | { |
393 | const union acpi_object *obj; | 586 | const union acpi_object *obj; |
394 | int ret; | 587 | int ret; |
@@ -397,7 +590,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, | |||
397 | return -EINVAL; | 590 | return -EINVAL; |
398 | 591 | ||
399 | if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { | 592 | if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) { |
400 | ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_INTEGER, &obj); | 593 | ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj); |
401 | if (ret) | 594 | if (ret) |
402 | return ret; | 595 | return ret; |
403 | 596 | ||
@@ -422,7 +615,7 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, | |||
422 | break; | 615 | break; |
423 | } | 616 | } |
424 | } else if (proptype == DEV_PROP_STRING) { | 617 | } else if (proptype == DEV_PROP_STRING) { |
425 | ret = acpi_dev_get_property(adev, propname, ACPI_TYPE_STRING, &obj); | 618 | ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj); |
426 | if (ret) | 619 | if (ret) |
427 | return ret; | 620 | return ret; |
428 | 621 | ||
@@ -433,6 +626,12 @@ int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, | |||
433 | return ret; | 626 | return ret; |
434 | } | 627 | } |
435 | 628 | ||
629 | int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, | ||
630 | enum dev_prop_type proptype, void *val) | ||
631 | { | ||
632 | return adev ? acpi_data_prop_read_single(&adev->data, propname, proptype, val) : -EINVAL; | ||
633 | } | ||
634 | |||
436 | static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val, | 635 | static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val, |
437 | size_t nval) | 636 | size_t nval) |
438 | { | 637 | { |
@@ -509,20 +708,22 @@ static int acpi_copy_property_array_string(const union acpi_object *items, | |||
509 | return 0; | 708 | return 0; |
510 | } | 709 | } |
511 | 710 | ||
512 | int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, | 711 | static int acpi_data_prop_read(struct acpi_device_data *data, |
513 | enum dev_prop_type proptype, void *val, size_t nval) | 712 | const char *propname, |
713 | enum dev_prop_type proptype, | ||
714 | void *val, size_t nval) | ||
514 | { | 715 | { |
515 | const union acpi_object *obj; | 716 | const union acpi_object *obj; |
516 | const union acpi_object *items; | 717 | const union acpi_object *items; |
517 | int ret; | 718 | int ret; |
518 | 719 | ||
519 | if (val && nval == 1) { | 720 | if (val && nval == 1) { |
520 | ret = acpi_dev_prop_read_single(adev, propname, proptype, val); | 721 | ret = acpi_data_prop_read_single(data, propname, proptype, val); |
521 | if (!ret) | 722 | if (!ret) |
522 | return ret; | 723 | return ret; |
523 | } | 724 | } |
524 | 725 | ||
525 | ret = acpi_dev_get_property_array(adev, propname, ACPI_TYPE_ANY, &obj); | 726 | ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj); |
526 | if (ret) | 727 | if (ret) |
527 | return ret; | 728 | return ret; |
528 | 729 | ||
@@ -558,3 +759,84 @@ int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, | |||
558 | } | 759 | } |
559 | return ret; | 760 | return ret; |
560 | } | 761 | } |
762 | |||
763 | int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, | ||
764 | enum dev_prop_type proptype, void *val, size_t nval) | ||
765 | { | ||
766 | return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL; | ||
767 | } | ||
768 | |||
769 | /** | ||
770 | * acpi_node_prop_read - retrieve the value of an ACPI property with given name. | ||
771 | * @fwnode: Firmware node to get the property from. | ||
772 | * @propname: Name of the property. | ||
773 | * @proptype: Expected property type. | ||
774 | * @val: Location to store the property value (if not %NULL). | ||
775 | * @nval: Size of the array pointed to by @val. | ||
776 | * | ||
777 | * If @val is %NULL, return the number of array elements comprising the value | ||
778 | * of the property. Otherwise, read at most @nval values to the array at the | ||
779 | * location pointed to by @val. | ||
780 | */ | ||
781 | int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname, | ||
782 | enum dev_prop_type proptype, void *val, size_t nval) | ||
783 | { | ||
784 | return acpi_data_prop_read(acpi_device_data_of_node(fwnode), | ||
785 | propname, proptype, val, nval); | ||
786 | } | ||
787 | |||
788 | /** | ||
789 | * acpi_get_next_subnode - Return the next child node handle for a device. | ||
790 | * @dev: Device to find the next child node for. | ||
791 | * @child: Handle to one of the device's child nodes or a null handle. | ||
792 | */ | ||
793 | struct fwnode_handle *acpi_get_next_subnode(struct device *dev, | ||
794 | struct fwnode_handle *child) | ||
795 | { | ||
796 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
797 | struct list_head *head, *next; | ||
798 | |||
799 | if (!adev) | ||
800 | return NULL; | ||
801 | |||
802 | if (!child || child->type == FWNODE_ACPI) { | ||
803 | head = &adev->children; | ||
804 | if (list_empty(head)) | ||
805 | goto nondev; | ||
806 | |||
807 | if (child) { | ||
808 | adev = to_acpi_device_node(child); | ||
809 | next = adev->node.next; | ||
810 | if (next == head) { | ||
811 | child = NULL; | ||
812 | goto nondev; | ||
813 | } | ||
814 | adev = list_entry(next, struct acpi_device, node); | ||
815 | } else { | ||
816 | adev = list_first_entry(head, struct acpi_device, node); | ||
817 | } | ||
818 | return acpi_fwnode_handle(adev); | ||
819 | } | ||
820 | |||
821 | nondev: | ||
822 | if (!child || child->type == FWNODE_ACPI_DATA) { | ||
823 | struct acpi_data_node *dn; | ||
824 | |||
825 | head = &adev->data.subnodes; | ||
826 | if (list_empty(head)) | ||
827 | return NULL; | ||
828 | |||
829 | if (child) { | ||
830 | dn = to_acpi_data_node(child); | ||
831 | next = dn->sibling.next; | ||
832 | if (next == head) | ||
833 | return NULL; | ||
834 | |||
835 | dn = list_entry(next, struct acpi_data_node, sibling); | ||
836 | } else { | ||
837 | dn = list_first_entry(head, struct acpi_data_node, sibling); | ||
838 | } | ||
839 | return &dn->fwnode; | ||
840 | } | ||
841 | return NULL; | ||
842 | } | ||
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 01136b879038..d1ce377db3e9 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c | |||
@@ -695,26 +695,6 @@ int acpi_device_add(struct acpi_device *device, | |||
695 | return result; | 695 | return result; |
696 | } | 696 | } |
697 | 697 | ||
698 | struct acpi_device *acpi_get_next_child(struct device *dev, | ||
699 | struct acpi_device *child) | ||
700 | { | ||
701 | struct acpi_device *adev = ACPI_COMPANION(dev); | ||
702 | struct list_head *head, *next; | ||
703 | |||
704 | if (!adev) | ||
705 | return NULL; | ||
706 | |||
707 | head = &adev->children; | ||
708 | if (list_empty(head)) | ||
709 | return NULL; | ||
710 | |||
711 | if (!child) | ||
712 | return list_first_entry(head, struct acpi_device, node); | ||
713 | |||
714 | next = child->node.next; | ||
715 | return next == head ? NULL : list_entry(next, struct acpi_device, node); | ||
716 | } | ||
717 | |||
718 | /* -------------------------------------------------------------------------- | 698 | /* -------------------------------------------------------------------------- |
719 | Device Enumeration | 699 | Device Enumeration |
720 | -------------------------------------------------------------------------- */ | 700 | -------------------------------------------------------------------------- */ |
diff --git a/drivers/base/property.c b/drivers/base/property.c index 2d75366c61e0..de40623bbd8a 100644 --- a/drivers/base/property.c +++ b/drivers/base/property.c | |||
@@ -134,7 +134,7 @@ bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname) | |||
134 | if (is_of_node(fwnode)) | 134 | if (is_of_node(fwnode)) |
135 | return of_property_read_bool(to_of_node(fwnode), propname); | 135 | return of_property_read_bool(to_of_node(fwnode), propname); |
136 | else if (is_acpi_node(fwnode)) | 136 | else if (is_acpi_node(fwnode)) |
137 | return !acpi_dev_prop_get(to_acpi_node(fwnode), propname, NULL); | 137 | return !acpi_node_prop_get(fwnode, propname, NULL); |
138 | 138 | ||
139 | return !!pset_prop_get(to_pset(fwnode), propname); | 139 | return !!pset_prop_get(to_pset(fwnode), propname); |
140 | } | 140 | } |
@@ -287,6 +287,28 @@ int device_property_read_string(struct device *dev, const char *propname, | |||
287 | } | 287 | } |
288 | EXPORT_SYMBOL_GPL(device_property_read_string); | 288 | EXPORT_SYMBOL_GPL(device_property_read_string); |
289 | 289 | ||
290 | /** | ||
291 | * device_property_match_string - find a string in an array and return index | ||
292 | * @dev: Device to get the property of | ||
293 | * @propname: Name of the property holding the array | ||
294 | * @string: String to look for | ||
295 | * | ||
296 | * Find a given string in a string array and if it is found return the | ||
297 | * index back. | ||
298 | * | ||
299 | * Return: %0 if the property was found (success), | ||
300 | * %-EINVAL if given arguments are not valid, | ||
301 | * %-ENODATA if the property does not have a value, | ||
302 | * %-EPROTO if the property is not an array of strings, | ||
303 | * %-ENXIO if no suitable firmware interface is present. | ||
304 | */ | ||
305 | int device_property_match_string(struct device *dev, const char *propname, | ||
306 | const char *string) | ||
307 | { | ||
308 | return fwnode_property_match_string(dev_fwnode(dev), propname, string); | ||
309 | } | ||
310 | EXPORT_SYMBOL_GPL(device_property_match_string); | ||
311 | |||
290 | #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ | 312 | #define OF_DEV_PROP_READ_ARRAY(node, propname, type, val, nval) \ |
291 | (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ | 313 | (val) ? of_property_read_##type##_array((node), (propname), (val), (nval)) \ |
292 | : of_property_count_elems_of_size((node), (propname), sizeof(type)) | 314 | : of_property_count_elems_of_size((node), (propname), sizeof(type)) |
@@ -298,8 +320,8 @@ EXPORT_SYMBOL_GPL(device_property_read_string); | |||
298 | _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \ | 320 | _ret_ = OF_DEV_PROP_READ_ARRAY(to_of_node(_fwnode_), _propname_, \ |
299 | _type_, _val_, _nval_); \ | 321 | _type_, _val_, _nval_); \ |
300 | else if (is_acpi_node(_fwnode_)) \ | 322 | else if (is_acpi_node(_fwnode_)) \ |
301 | _ret_ = acpi_dev_prop_read(to_acpi_node(_fwnode_), _propname_, \ | 323 | _ret_ = acpi_node_prop_read(_fwnode_, _propname_, _proptype_, \ |
302 | _proptype_, _val_, _nval_); \ | 324 | _val_, _nval_); \ |
303 | else if (is_pset(_fwnode_)) \ | 325 | else if (is_pset(_fwnode_)) \ |
304 | _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \ | 326 | _ret_ = pset_prop_read_array(to_pset(_fwnode_), _propname_, \ |
305 | _proptype_, _val_, _nval_); \ | 327 | _proptype_, _val_, _nval_); \ |
@@ -440,8 +462,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode, | |||
440 | propname, val, nval) : | 462 | propname, val, nval) : |
441 | of_property_count_strings(to_of_node(fwnode), propname); | 463 | of_property_count_strings(to_of_node(fwnode), propname); |
442 | else if (is_acpi_node(fwnode)) | 464 | else if (is_acpi_node(fwnode)) |
443 | return acpi_dev_prop_read(to_acpi_node(fwnode), propname, | 465 | return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, |
444 | DEV_PROP_STRING, val, nval); | 466 | val, nval); |
445 | else if (is_pset(fwnode)) | 467 | else if (is_pset(fwnode)) |
446 | return pset_prop_read_array(to_pset(fwnode), propname, | 468 | return pset_prop_read_array(to_pset(fwnode), propname, |
447 | DEV_PROP_STRING, val, nval); | 469 | DEV_PROP_STRING, val, nval); |
@@ -470,8 +492,8 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode, | |||
470 | if (is_of_node(fwnode)) | 492 | if (is_of_node(fwnode)) |
471 | return of_property_read_string(to_of_node(fwnode), propname, val); | 493 | return of_property_read_string(to_of_node(fwnode), propname, val); |
472 | else if (is_acpi_node(fwnode)) | 494 | else if (is_acpi_node(fwnode)) |
473 | return acpi_dev_prop_read(to_acpi_node(fwnode), propname, | 495 | return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING, |
474 | DEV_PROP_STRING, val, 1); | 496 | val, 1); |
475 | 497 | ||
476 | return pset_prop_read_array(to_pset(fwnode), propname, | 498 | return pset_prop_read_array(to_pset(fwnode), propname, |
477 | DEV_PROP_STRING, val, 1); | 499 | DEV_PROP_STRING, val, 1); |
@@ -479,6 +501,52 @@ int fwnode_property_read_string(struct fwnode_handle *fwnode, | |||
479 | EXPORT_SYMBOL_GPL(fwnode_property_read_string); | 501 | EXPORT_SYMBOL_GPL(fwnode_property_read_string); |
480 | 502 | ||
481 | /** | 503 | /** |
504 | * fwnode_property_match_string - find a string in an array and return index | ||
505 | * @fwnode: Firmware node to get the property of | ||
506 | * @propname: Name of the property holding the array | ||
507 | * @string: String to look for | ||
508 | * | ||
509 | * Find a given string in a string array and if it is found return the | ||
510 | * index back. | ||
511 | * | ||
512 | * Return: %0 if the property was found (success), | ||
513 | * %-EINVAL if given arguments are not valid, | ||
514 | * %-ENODATA if the property does not have a value, | ||
515 | * %-EPROTO if the property is not an array of strings, | ||
516 | * %-ENXIO if no suitable firmware interface is present. | ||
517 | */ | ||
518 | int fwnode_property_match_string(struct fwnode_handle *fwnode, | ||
519 | const char *propname, const char *string) | ||
520 | { | ||
521 | const char **values; | ||
522 | int nval, ret, i; | ||
523 | |||
524 | nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0); | ||
525 | if (nval < 0) | ||
526 | return nval; | ||
527 | |||
528 | values = kcalloc(nval, sizeof(*values), GFP_KERNEL); | ||
529 | if (!values) | ||
530 | return -ENOMEM; | ||
531 | |||
532 | ret = fwnode_property_read_string_array(fwnode, propname, values, nval); | ||
533 | if (ret < 0) | ||
534 | goto out; | ||
535 | |||
536 | ret = -ENODATA; | ||
537 | for (i = 0; i < nval; i++) { | ||
538 | if (!strcmp(values[i], string)) { | ||
539 | ret = i; | ||
540 | break; | ||
541 | } | ||
542 | } | ||
543 | out: | ||
544 | kfree(values); | ||
545 | return ret; | ||
546 | } | ||
547 | EXPORT_SYMBOL_GPL(fwnode_property_match_string); | ||
548 | |||
549 | /** | ||
482 | * device_get_next_child_node - Return the next child node handle for a device | 550 | * device_get_next_child_node - Return the next child node handle for a device |
483 | * @dev: Device to find the next child node for. | 551 | * @dev: Device to find the next child node for. |
484 | * @child: Handle to one of the device's child nodes or a null handle. | 552 | * @child: Handle to one of the device's child nodes or a null handle. |
@@ -493,11 +561,7 @@ struct fwnode_handle *device_get_next_child_node(struct device *dev, | |||
493 | if (node) | 561 | if (node) |
494 | return &node->fwnode; | 562 | return &node->fwnode; |
495 | } else if (IS_ENABLED(CONFIG_ACPI)) { | 563 | } else if (IS_ENABLED(CONFIG_ACPI)) { |
496 | struct acpi_device *node; | 564 | return acpi_get_next_subnode(dev, child); |
497 | |||
498 | node = acpi_get_next_child(dev, to_acpi_node(child)); | ||
499 | if (node) | ||
500 | return acpi_fwnode_handle(node); | ||
501 | } | 565 | } |
502 | return NULL; | 566 | return NULL; |
503 | } | 567 | } |
diff --git a/drivers/dma/acpi-dma.c b/drivers/dma/acpi-dma.c index 5a635646e05c..981a38fc4cb8 100644 --- a/drivers/dma/acpi-dma.c +++ b/drivers/dma/acpi-dma.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/ioport.h> | 21 | #include <linux/ioport.h> |
22 | #include <linux/acpi.h> | 22 | #include <linux/acpi.h> |
23 | #include <linux/acpi_dma.h> | 23 | #include <linux/acpi_dma.h> |
24 | #include <linux/property.h> | ||
24 | 25 | ||
25 | static LIST_HEAD(acpi_dma_list); | 26 | static LIST_HEAD(acpi_dma_list); |
26 | static DEFINE_MUTEX(acpi_dma_lock); | 27 | static DEFINE_MUTEX(acpi_dma_lock); |
@@ -413,21 +414,29 @@ EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_index); | |||
413 | * translate the names "tx" and "rx" here based on the most common case where | 414 | * translate the names "tx" and "rx" here based on the most common case where |
414 | * the first FixedDMA descriptor is TX and second is RX. | 415 | * the first FixedDMA descriptor is TX and second is RX. |
415 | * | 416 | * |
417 | * If the device has "dma-names" property the FixedDMA descriptor indices | ||
418 | * are retrieved based on those. Otherwise the function falls back using | ||
419 | * hardcoded indices. | ||
420 | * | ||
416 | * Return: | 421 | * Return: |
417 | * Pointer to appropriate dma channel on success or an error pointer. | 422 | * Pointer to appropriate dma channel on success or an error pointer. |
418 | */ | 423 | */ |
419 | struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev, | 424 | struct dma_chan *acpi_dma_request_slave_chan_by_name(struct device *dev, |
420 | const char *name) | 425 | const char *name) |
421 | { | 426 | { |
422 | size_t index; | 427 | int index; |
423 | 428 | ||
424 | if (!strcmp(name, "tx")) | 429 | index = device_property_match_string(dev, "dma-names", name); |
425 | index = 0; | 430 | if (index < 0) { |
426 | else if (!strcmp(name, "rx")) | 431 | if (!strcmp(name, "tx")) |
427 | index = 1; | 432 | index = 0; |
428 | else | 433 | else if (!strcmp(name, "rx")) |
429 | return ERR_PTR(-ENODEV); | 434 | index = 1; |
435 | else | ||
436 | return ERR_PTR(-ENODEV); | ||
437 | } | ||
430 | 438 | ||
439 | dev_dbg(dev, "found DMA channel \"%s\" at index %d\n", name, index); | ||
431 | return acpi_dma_request_slave_chan_by_index(dev, index); | 440 | return acpi_dma_request_slave_chan_by_index(dev, index); |
432 | } | 441 | } |
433 | EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name); | 442 | EXPORT_SYMBOL_GPL(acpi_dma_request_slave_chan_by_name); |
diff --git a/drivers/gpio/gpiolib-acpi.c b/drivers/gpio/gpiolib-acpi.c index 143a9bdbaa53..69a83626f1ae 100644 --- a/drivers/gpio/gpiolib-acpi.c +++ b/drivers/gpio/gpiolib-acpi.c | |||
@@ -389,6 +389,8 @@ struct acpi_gpio_lookup { | |||
389 | struct acpi_gpio_info info; | 389 | struct acpi_gpio_info info; |
390 | int index; | 390 | int index; |
391 | int pin_index; | 391 | int pin_index; |
392 | bool active_low; | ||
393 | struct acpi_device *adev; | ||
392 | struct gpio_desc *desc; | 394 | struct gpio_desc *desc; |
393 | int n; | 395 | int n; |
394 | }; | 396 | }; |
@@ -425,6 +427,65 @@ static int acpi_find_gpio(struct acpi_resource *ares, void *data) | |||
425 | return 1; | 427 | return 1; |
426 | } | 428 | } |
427 | 429 | ||
430 | static int acpi_gpio_resource_lookup(struct acpi_gpio_lookup *lookup, | ||
431 | struct acpi_gpio_info *info) | ||
432 | { | ||
433 | struct list_head res_list; | ||
434 | int ret; | ||
435 | |||
436 | INIT_LIST_HEAD(&res_list); | ||
437 | |||
438 | ret = acpi_dev_get_resources(lookup->adev, &res_list, acpi_find_gpio, | ||
439 | lookup); | ||
440 | if (ret < 0) | ||
441 | return ret; | ||
442 | |||
443 | acpi_dev_free_resource_list(&res_list); | ||
444 | |||
445 | if (!lookup->desc) | ||
446 | return -ENOENT; | ||
447 | |||
448 | if (info) { | ||
449 | *info = lookup->info; | ||
450 | if (lookup->active_low) | ||
451 | info->active_low = lookup->active_low; | ||
452 | } | ||
453 | return 0; | ||
454 | } | ||
455 | |||
456 | static int acpi_gpio_property_lookup(struct fwnode_handle *fwnode, | ||
457 | const char *propname, int index, | ||
458 | struct acpi_gpio_lookup *lookup) | ||
459 | { | ||
460 | struct acpi_reference_args args; | ||
461 | int ret; | ||
462 | |||
463 | memset(&args, 0, sizeof(args)); | ||
464 | ret = acpi_node_get_property_reference(fwnode, propname, index, &args); | ||
465 | if (ret) { | ||
466 | struct acpi_device *adev = to_acpi_device_node(fwnode); | ||
467 | |||
468 | if (!adev) | ||
469 | return ret; | ||
470 | |||
471 | if (!acpi_get_driver_gpio_data(adev, propname, index, &args)) | ||
472 | return ret; | ||
473 | } | ||
474 | /* | ||
475 | * The property was found and resolved, so need to lookup the GPIO based | ||
476 | * on returned args. | ||
477 | */ | ||
478 | lookup->adev = args.adev; | ||
479 | if (args.nargs >= 2) { | ||
480 | lookup->index = args.args[0]; | ||
481 | lookup->pin_index = args.args[1]; | ||
482 | /* 3rd argument, if present is used to specify active_low. */ | ||
483 | if (args.nargs >= 3) | ||
484 | lookup->active_low = !!args.args[2]; | ||
485 | } | ||
486 | return 0; | ||
487 | } | ||
488 | |||
428 | /** | 489 | /** |
429 | * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources | 490 | * acpi_get_gpiod_by_index() - get a GPIO descriptor from device resources |
430 | * @adev: pointer to a ACPI device to get GPIO from | 491 | * @adev: pointer to a ACPI device to get GPIO from |
@@ -452,8 +513,6 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, | |||
452 | struct acpi_gpio_info *info) | 513 | struct acpi_gpio_info *info) |
453 | { | 514 | { |
454 | struct acpi_gpio_lookup lookup; | 515 | struct acpi_gpio_lookup lookup; |
455 | struct list_head resource_list; | ||
456 | bool active_low = false; | ||
457 | int ret; | 516 | int ret; |
458 | 517 | ||
459 | if (!adev) | 518 | if (!adev) |
@@ -463,58 +522,64 @@ struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, | |||
463 | lookup.index = index; | 522 | lookup.index = index; |
464 | 523 | ||
465 | if (propname) { | 524 | if (propname) { |
466 | struct acpi_reference_args args; | ||
467 | |||
468 | dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); | 525 | dev_dbg(&adev->dev, "GPIO: looking up %s\n", propname); |
469 | 526 | ||
470 | memset(&args, 0, sizeof(args)); | 527 | ret = acpi_gpio_property_lookup(acpi_fwnode_handle(adev), |
471 | ret = acpi_dev_get_property_reference(adev, propname, | 528 | propname, index, &lookup); |
472 | index, &args); | 529 | if (ret) |
473 | if (ret) { | 530 | return ERR_PTR(ret); |
474 | bool found = acpi_get_driver_gpio_data(adev, propname, | ||
475 | index, &args); | ||
476 | if (!found) | ||
477 | return ERR_PTR(ret); | ||
478 | } | ||
479 | 531 | ||
480 | /* | 532 | dev_dbg(&adev->dev, "GPIO: _DSD returned %s %d %d %u\n", |
481 | * The property was found and resolved so need to | 533 | dev_name(&lookup.adev->dev), lookup.index, |
482 | * lookup the GPIO based on returned args instead. | 534 | lookup.pin_index, lookup.active_low); |
483 | */ | ||
484 | adev = args.adev; | ||
485 | if (args.nargs >= 2) { | ||
486 | lookup.index = args.args[0]; | ||
487 | lookup.pin_index = args.args[1]; | ||
488 | /* | ||
489 | * 3rd argument, if present is used to | ||
490 | * specify active_low. | ||
491 | */ | ||
492 | if (args.nargs >= 3) | ||
493 | active_low = !!args.args[2]; | ||
494 | } | ||
495 | |||
496 | dev_dbg(&adev->dev, "GPIO: _DSD returned %s %zd %llu %llu %llu\n", | ||
497 | dev_name(&adev->dev), args.nargs, | ||
498 | args.args[0], args.args[1], args.args[2]); | ||
499 | } else { | 535 | } else { |
500 | dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); | 536 | dev_dbg(&adev->dev, "GPIO: looking up %d in _CRS\n", index); |
537 | lookup.adev = adev; | ||
501 | } | 538 | } |
502 | 539 | ||
503 | INIT_LIST_HEAD(&resource_list); | 540 | ret = acpi_gpio_resource_lookup(&lookup, info); |
504 | ret = acpi_dev_get_resources(adev, &resource_list, acpi_find_gpio, | 541 | return ret ? ERR_PTR(ret) : lookup.desc; |
505 | &lookup); | 542 | } |
506 | if (ret < 0) | 543 | |
507 | return ERR_PTR(ret); | 544 | /** |
545 | * acpi_node_get_gpiod() - get a GPIO descriptor from ACPI resources | ||
546 | * @fwnode: pointer to an ACPI firmware node to get the GPIO information from | ||
547 | * @propname: Property name of the GPIO | ||
548 | * @index: index of GpioIo/GpioInt resource (starting from %0) | ||
549 | * @info: info pointer to fill in (optional) | ||
550 | * | ||
551 | * If @fwnode is an ACPI device object, call %acpi_get_gpiod_by_index() for it. | ||
552 | * Otherwise (ie. it is a data-only non-device object), use the property-based | ||
553 | * GPIO lookup to get to the GPIO resource with the relevant information and use | ||
554 | * that to obtain the GPIO descriptor to return. | ||
555 | */ | ||
556 | struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, | ||
557 | const char *propname, int index, | ||
558 | struct acpi_gpio_info *info) | ||
559 | { | ||
560 | struct acpi_gpio_lookup lookup; | ||
561 | struct acpi_device *adev; | ||
562 | int ret; | ||
508 | 563 | ||
509 | acpi_dev_free_resource_list(&resource_list); | 564 | adev = to_acpi_device_node(fwnode); |
565 | if (adev) | ||
566 | return acpi_get_gpiod_by_index(adev, propname, index, info); | ||
510 | 567 | ||
511 | if (lookup.desc && info) { | 568 | if (!is_acpi_data_node(fwnode)) |
512 | *info = lookup.info; | 569 | return ERR_PTR(-ENODEV); |
513 | if (active_low) | 570 | |
514 | info->active_low = active_low; | 571 | if (!propname) |
515 | } | 572 | return ERR_PTR(-EINVAL); |
573 | |||
574 | memset(&lookup, 0, sizeof(lookup)); | ||
575 | lookup.index = index; | ||
576 | |||
577 | ret = acpi_gpio_property_lookup(fwnode, propname, index, &lookup); | ||
578 | if (ret) | ||
579 | return ERR_PTR(ret); | ||
516 | 580 | ||
517 | return lookup.desc ? lookup.desc : ERR_PTR(-ENOENT); | 581 | ret = acpi_gpio_resource_lookup(&lookup, info); |
582 | return ret ? ERR_PTR(ret) : lookup.desc; | ||
518 | } | 583 | } |
519 | 584 | ||
520 | /** | 585 | /** |
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c index 5db3445552b1..c52a70f3d0a8 100644 --- a/drivers/gpio/gpiolib.c +++ b/drivers/gpio/gpiolib.c | |||
@@ -2093,8 +2093,7 @@ struct gpio_desc *fwnode_get_named_gpiod(struct fwnode_handle *fwnode, | |||
2093 | } else if (is_acpi_node(fwnode)) { | 2093 | } else if (is_acpi_node(fwnode)) { |
2094 | struct acpi_gpio_info info; | 2094 | struct acpi_gpio_info info; |
2095 | 2095 | ||
2096 | desc = acpi_get_gpiod_by_index(to_acpi_node(fwnode), propname, 0, | 2096 | desc = acpi_node_get_gpiod(fwnode, propname, 0, &info); |
2097 | &info); | ||
2098 | if (!IS_ERR(desc)) | 2097 | if (!IS_ERR(desc)) |
2099 | active_low = info.active_low; | 2098 | active_low = info.active_low; |
2100 | } | 2099 | } |
diff --git a/drivers/gpio/gpiolib.h b/drivers/gpio/gpiolib.h index bf343004b008..e69c7157cdad 100644 --- a/drivers/gpio/gpiolib.h +++ b/drivers/gpio/gpiolib.h | |||
@@ -42,6 +42,9 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip); | |||
42 | struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, | 42 | struct gpio_desc *acpi_get_gpiod_by_index(struct acpi_device *adev, |
43 | const char *propname, int index, | 43 | const char *propname, int index, |
44 | struct acpi_gpio_info *info); | 44 | struct acpi_gpio_info *info); |
45 | struct gpio_desc *acpi_node_get_gpiod(struct fwnode_handle *fwnode, | ||
46 | const char *propname, int index, | ||
47 | struct acpi_gpio_info *info); | ||
45 | 48 | ||
46 | int acpi_gpio_count(struct device *dev, const char *con_id); | 49 | int acpi_gpio_count(struct device *dev, const char *con_id); |
47 | #else | 50 | #else |
@@ -60,7 +63,12 @@ acpi_get_gpiod_by_index(struct acpi_device *adev, const char *propname, | |||
60 | { | 63 | { |
61 | return ERR_PTR(-ENOSYS); | 64 | return ERR_PTR(-ENOSYS); |
62 | } | 65 | } |
63 | 66 | static inline struct gpio_desc * | |
67 | acpi_node_get_gpiod(struct fwnode_handle *fwnode, const char *propname, | ||
68 | int index, struct acpi_gpio_info *info) | ||
69 | { | ||
70 | return ERR_PTR(-ENXIO); | ||
71 | } | ||
64 | static inline int acpi_gpio_count(struct device *dev, const char *con_id) | 72 | static inline int acpi_gpio_count(struct device *dev, const char *con_id) |
65 | { | 73 | { |
66 | return -ENODEV; | 74 | return -ENODEV; |
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index 5ba8fb64f664..e234725eadc7 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h | |||
@@ -343,6 +343,7 @@ struct acpi_device_data { | |||
343 | const union acpi_object *pointer; | 343 | const union acpi_object *pointer; |
344 | const union acpi_object *properties; | 344 | const union acpi_object *properties; |
345 | const union acpi_object *of_compatible; | 345 | const union acpi_object *of_compatible; |
346 | struct list_head subnodes; | ||
346 | }; | 347 | }; |
347 | 348 | ||
348 | struct acpi_gpio_mapping; | 349 | struct acpi_gpio_mapping; |
@@ -378,6 +379,17 @@ struct acpi_device { | |||
378 | void (*remove)(struct acpi_device *); | 379 | void (*remove)(struct acpi_device *); |
379 | }; | 380 | }; |
380 | 381 | ||
382 | /* Non-device subnode */ | ||
383 | struct acpi_data_node { | ||
384 | const char *name; | ||
385 | acpi_handle handle; | ||
386 | struct fwnode_handle fwnode; | ||
387 | struct acpi_device_data data; | ||
388 | struct list_head sibling; | ||
389 | struct kobject kobj; | ||
390 | struct completion kobj_done; | ||
391 | }; | ||
392 | |||
381 | static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent) | 393 | static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent) |
382 | { | 394 | { |
383 | bool ret = false; | 395 | bool ret = false; |
@@ -413,15 +425,32 @@ static inline bool acpi_check_dma(struct acpi_device *adev, bool *coherent) | |||
413 | 425 | ||
414 | static inline bool is_acpi_node(struct fwnode_handle *fwnode) | 426 | static inline bool is_acpi_node(struct fwnode_handle *fwnode) |
415 | { | 427 | { |
428 | return fwnode && (fwnode->type == FWNODE_ACPI | ||
429 | || fwnode->type == FWNODE_ACPI_DATA); | ||
430 | } | ||
431 | |||
432 | static inline bool is_acpi_device_node(struct fwnode_handle *fwnode) | ||
433 | { | ||
416 | return fwnode && fwnode->type == FWNODE_ACPI; | 434 | return fwnode && fwnode->type == FWNODE_ACPI; |
417 | } | 435 | } |
418 | 436 | ||
419 | static inline struct acpi_device *to_acpi_node(struct fwnode_handle *fwnode) | 437 | static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode) |
420 | { | 438 | { |
421 | return is_acpi_node(fwnode) ? | 439 | return is_acpi_device_node(fwnode) ? |
422 | container_of(fwnode, struct acpi_device, fwnode) : NULL; | 440 | container_of(fwnode, struct acpi_device, fwnode) : NULL; |
423 | } | 441 | } |
424 | 442 | ||
443 | static inline bool is_acpi_data_node(struct fwnode_handle *fwnode) | ||
444 | { | ||
445 | return fwnode && fwnode->type == FWNODE_ACPI_DATA; | ||
446 | } | ||
447 | |||
448 | static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode) | ||
449 | { | ||
450 | return is_acpi_data_node(fwnode) ? | ||
451 | container_of(fwnode, struct acpi_data_node, fwnode) : NULL; | ||
452 | } | ||
453 | |||
425 | static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) | 454 | static inline struct fwnode_handle *acpi_fwnode_handle(struct acpi_device *adev) |
426 | { | 455 | { |
427 | return &adev->fwnode; | 456 | return &adev->fwnode; |
diff --git a/include/linux/acpi.h b/include/linux/acpi.h index 7235c4851460..865d948c60e6 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h | |||
@@ -49,7 +49,7 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) | |||
49 | return adev ? adev->handle : NULL; | 49 | return adev ? adev->handle : NULL; |
50 | } | 50 | } |
51 | 51 | ||
52 | #define ACPI_COMPANION(dev) to_acpi_node((dev)->fwnode) | 52 | #define ACPI_COMPANION(dev) to_acpi_device_node((dev)->fwnode) |
53 | #define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \ | 53 | #define ACPI_COMPANION_SET(dev, adev) set_primary_fwnode(dev, (adev) ? \ |
54 | acpi_fwnode_handle(adev) : NULL) | 54 | acpi_fwnode_handle(adev) : NULL) |
55 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) | 55 | #define ACPI_HANDLE(dev) acpi_device_handle(ACPI_COMPANION(dev)) |
@@ -69,7 +69,7 @@ static inline acpi_handle acpi_device_handle(struct acpi_device *adev) | |||
69 | 69 | ||
70 | static inline bool has_acpi_companion(struct device *dev) | 70 | static inline bool has_acpi_companion(struct device *dev) |
71 | { | 71 | { |
72 | return is_acpi_node(dev->fwnode); | 72 | return is_acpi_device_node(dev->fwnode); |
73 | } | 73 | } |
74 | 74 | ||
75 | static inline void acpi_preset_companion(struct device *dev, | 75 | static inline void acpi_preset_companion(struct device *dev, |
@@ -461,7 +461,22 @@ static inline bool is_acpi_node(struct fwnode_handle *fwnode) | |||
461 | return false; | 461 | return false; |
462 | } | 462 | } |
463 | 463 | ||
464 | static inline struct acpi_device *to_acpi_node(struct fwnode_handle *fwnode) | 464 | static inline bool is_acpi_device_node(struct fwnode_handle *fwnode) |
465 | { | ||
466 | return false; | ||
467 | } | ||
468 | |||
469 | static inline struct acpi_device *to_acpi_device_node(struct fwnode_handle *fwnode) | ||
470 | { | ||
471 | return NULL; | ||
472 | } | ||
473 | |||
474 | static inline bool is_acpi_data_node(struct fwnode_handle *fwnode) | ||
475 | { | ||
476 | return false; | ||
477 | } | ||
478 | |||
479 | static inline struct acpi_data_node *to_acpi_data_node(struct fwnode_handle *fwnode) | ||
465 | { | 480 | { |
466 | return NULL; | 481 | return NULL; |
467 | } | 482 | } |
@@ -743,22 +758,21 @@ struct acpi_reference_args { | |||
743 | #ifdef CONFIG_ACPI | 758 | #ifdef CONFIG_ACPI |
744 | int acpi_dev_get_property(struct acpi_device *adev, const char *name, | 759 | int acpi_dev_get_property(struct acpi_device *adev, const char *name, |
745 | acpi_object_type type, const union acpi_object **obj); | 760 | acpi_object_type type, const union acpi_object **obj); |
746 | int acpi_dev_get_property_array(struct acpi_device *adev, const char *name, | 761 | int acpi_node_get_property_reference(struct fwnode_handle *fwnode, |
747 | acpi_object_type type, | 762 | const char *name, size_t index, |
748 | const union acpi_object **obj); | 763 | struct acpi_reference_args *args); |
749 | int acpi_dev_get_property_reference(struct acpi_device *adev, | 764 | |
750 | const char *name, size_t index, | 765 | int acpi_node_prop_get(struct fwnode_handle *fwnode, const char *propname, |
751 | struct acpi_reference_args *args); | 766 | void **valptr); |
752 | |||
753 | int acpi_dev_prop_get(struct acpi_device *adev, const char *propname, | ||
754 | void **valptr); | ||
755 | int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, | 767 | int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname, |
756 | enum dev_prop_type proptype, void *val); | 768 | enum dev_prop_type proptype, void *val); |
769 | int acpi_node_prop_read(struct fwnode_handle *fwnode, const char *propname, | ||
770 | enum dev_prop_type proptype, void *val, size_t nval); | ||
757 | int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, | 771 | int acpi_dev_prop_read(struct acpi_device *adev, const char *propname, |
758 | enum dev_prop_type proptype, void *val, size_t nval); | 772 | enum dev_prop_type proptype, void *val, size_t nval); |
759 | 773 | ||
760 | struct acpi_device *acpi_get_next_child(struct device *dev, | 774 | struct fwnode_handle *acpi_get_next_subnode(struct device *dev, |
761 | struct acpi_device *child); | 775 | struct fwnode_handle *subnode); |
762 | #else | 776 | #else |
763 | static inline int acpi_dev_get_property(struct acpi_device *adev, | 777 | static inline int acpi_dev_get_property(struct acpi_device *adev, |
764 | const char *name, acpi_object_type type, | 778 | const char *name, acpi_object_type type, |
@@ -766,16 +780,17 @@ static inline int acpi_dev_get_property(struct acpi_device *adev, | |||
766 | { | 780 | { |
767 | return -ENXIO; | 781 | return -ENXIO; |
768 | } | 782 | } |
769 | static inline int acpi_dev_get_property_array(struct acpi_device *adev, | 783 | |
770 | const char *name, | 784 | static inline int acpi_node_get_property_reference(struct fwnode_handle *fwnode, |
771 | acpi_object_type type, | 785 | const char *name, const char *cells_name, |
772 | const union acpi_object **obj) | 786 | size_t index, struct acpi_reference_args *args) |
773 | { | 787 | { |
774 | return -ENXIO; | 788 | return -ENXIO; |
775 | } | 789 | } |
776 | static inline int acpi_dev_get_property_reference(struct acpi_device *adev, | 790 | |
777 | const char *name, const char *cells_name, | 791 | static inline int acpi_node_prop_get(struct fwnode_handle *fwnode, |
778 | size_t index, struct acpi_reference_args *args) | 792 | const char *propname, |
793 | void **valptr) | ||
779 | { | 794 | { |
780 | return -ENXIO; | 795 | return -ENXIO; |
781 | } | 796 | } |
@@ -795,6 +810,14 @@ static inline int acpi_dev_prop_read_single(struct acpi_device *adev, | |||
795 | return -ENXIO; | 810 | return -ENXIO; |
796 | } | 811 | } |
797 | 812 | ||
813 | static inline int acpi_node_prop_read(struct fwnode_handle *fwnode, | ||
814 | const char *propname, | ||
815 | enum dev_prop_type proptype, | ||
816 | void *val, size_t nval) | ||
817 | { | ||
818 | return -ENXIO; | ||
819 | } | ||
820 | |||
798 | static inline int acpi_dev_prop_read(struct acpi_device *adev, | 821 | static inline int acpi_dev_prop_read(struct acpi_device *adev, |
799 | const char *propname, | 822 | const char *propname, |
800 | enum dev_prop_type proptype, | 823 | enum dev_prop_type proptype, |
@@ -803,12 +826,11 @@ static inline int acpi_dev_prop_read(struct acpi_device *adev, | |||
803 | return -ENXIO; | 826 | return -ENXIO; |
804 | } | 827 | } |
805 | 828 | ||
806 | static inline struct acpi_device *acpi_get_next_child(struct device *dev, | 829 | static inline struct fwnode_handle *acpi_get_next_subnode(struct device *dev, |
807 | struct acpi_device *child) | 830 | struct fwnode_handle *subnode) |
808 | { | 831 | { |
809 | return NULL; | 832 | return NULL; |
810 | } | 833 | } |
811 | |||
812 | #endif | 834 | #endif |
813 | 835 | ||
814 | #endif /*_LINUX_ACPI_H*/ | 836 | #endif /*_LINUX_ACPI_H*/ |
diff --git a/include/linux/fwnode.h b/include/linux/fwnode.h index 0408545bce42..b08d6ba5c1e6 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_ACPI_DATA, | ||
19 | FWNODE_PDATA, | 20 | FWNODE_PDATA, |
20 | }; | 21 | }; |
21 | 22 | ||
diff --git a/include/linux/property.h b/include/linux/property.h index a59c6ee566c2..463de52fe891 100644 --- a/include/linux/property.h +++ b/include/linux/property.h | |||
@@ -40,6 +40,8 @@ int device_property_read_string_array(struct device *dev, const char *propname, | |||
40 | const char **val, size_t nval); | 40 | const char **val, size_t nval); |
41 | int device_property_read_string(struct device *dev, const char *propname, | 41 | int device_property_read_string(struct device *dev, const char *propname, |
42 | const char **val); | 42 | const char **val); |
43 | int device_property_match_string(struct device *dev, | ||
44 | const char *propname, const char *string); | ||
43 | 45 | ||
44 | bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname); | 46 | bool fwnode_property_present(struct fwnode_handle *fwnode, const char *propname); |
45 | int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, | 47 | int fwnode_property_read_u8_array(struct fwnode_handle *fwnode, |
@@ -59,6 +61,8 @@ int fwnode_property_read_string_array(struct fwnode_handle *fwnode, | |||
59 | size_t nval); | 61 | size_t nval); |
60 | int fwnode_property_read_string(struct fwnode_handle *fwnode, | 62 | int fwnode_property_read_string(struct fwnode_handle *fwnode, |
61 | const char *propname, const char **val); | 63 | const char *propname, const char **val); |
64 | int fwnode_property_match_string(struct fwnode_handle *fwnode, | ||
65 | const char *propname, const char *string); | ||
62 | 66 | ||
63 | struct fwnode_handle *device_get_next_child_node(struct device *dev, | 67 | struct fwnode_handle *device_get_next_child_node(struct device *dev, |
64 | struct fwnode_handle *child); | 68 | struct fwnode_handle *child); |