cw1200: drop useless LIST_HEAD
[linux-2.6-block.git] / drivers / acpi / property.c
CommitLineData
ffdcd955
MW
1/*
2 * ACPI device specific properties support.
3 *
4 * Copyright (C) 2014, Intel Corporation
5 * All rights reserved.
6 *
7 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
8 * Darren Hart <dvhart@linux.intel.com>
9 * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2 as
13 * published by the Free Software Foundation.
14 */
15
16#include <linux/acpi.h>
17#include <linux/device.h>
18#include <linux/export.h>
19
20#include "internal.h"
21
99a85464 22static int acpi_data_get_property_array(const struct acpi_device_data *data,
3a7a2ab8
RW
23 const char *name,
24 acpi_object_type type,
25 const union acpi_object **obj);
26
617654aa
MW
27/*
28 * The GUIDs here are made equivalent to each other in order to avoid extra
29 * complexity in the properties handling code, with the caveat that the
30 * kernel will accept certain combinations of GUID and properties that are
31 * not defined without a warning. For instance if any of the properties
32 * from different GUID appear in a property list of another, it will be
33 * accepted by the kernel. Firmware validation tools should catch these.
34 */
5f5e4890
MW
35static const guid_t prp_guids[] = {
36 /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
3689d3d6 37 GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
5f5e4890 38 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
26ad34d5
MW
39 /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */
40 GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
41 0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
617654aa
MW
42 /* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */
43 GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
44 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
5f5e4890
MW
45};
46
3689d3d6
AS
47static const guid_t ads_guid =
48 GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
49 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
445b0eb0
RW
50
51static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
52 const union acpi_object *desc,
dfa672fb
MW
53 struct acpi_device_data *data,
54 struct fwnode_handle *parent);
445b0eb0
RW
55static bool acpi_extract_properties(const union acpi_object *desc,
56 struct acpi_device_data *data);
57
99db5ff7
RW
58static bool acpi_nondev_subnode_extract(const union acpi_object *desc,
59 acpi_handle handle,
60 const union acpi_object *link,
dfa672fb
MW
61 struct list_head *list,
62 struct fwnode_handle *parent)
445b0eb0 63{
445b0eb0 64 struct acpi_data_node *dn;
99db5ff7 65 bool result;
445b0eb0
RW
66
67 dn = kzalloc(sizeof(*dn), GFP_KERNEL);
68 if (!dn)
69 return false;
70
71 dn->name = link->package.elements[0].string.pointer;
db3e50f3 72 dn->fwnode.ops = &acpi_data_fwnode_ops;
dfa672fb 73 dn->parent = parent;
5f5e4890 74 INIT_LIST_HEAD(&dn->data.properties);
445b0eb0
RW
75 INIT_LIST_HEAD(&dn->data.subnodes);
76
99db5ff7 77 result = acpi_extract_properties(desc, &dn->data);
445b0eb0 78
99db5ff7
RW
79 if (handle) {
80 acpi_handle scope;
81 acpi_status status;
445b0eb0 82
99db5ff7
RW
83 /*
84 * The scope for the subnode object lookup is the one of the
85 * namespace node (device) containing the object that has
86 * returned the package. That is, it's the scope of that
87 * object's parent.
88 */
89 status = acpi_get_parent(handle, &scope);
90 if (ACPI_SUCCESS(status)
dfa672fb
MW
91 && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
92 &dn->fwnode))
99db5ff7 93 result = true;
dfa672fb
MW
94 } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
95 &dn->fwnode)) {
99db5ff7
RW
96 result = true;
97 }
445b0eb0 98
99db5ff7 99 if (result) {
263b4c1a 100 dn->handle = handle;
99db5ff7 101 dn->data.pointer = desc;
445b0eb0
RW
102 list_add_tail(&dn->sibling, list);
103 return true;
104 }
105
99db5ff7 106 kfree(dn);
445b0eb0 107 acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
99db5ff7
RW
108 return false;
109}
110
111static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
112 const union acpi_object *link,
dfa672fb
MW
113 struct list_head *list,
114 struct fwnode_handle *parent)
99db5ff7
RW
115{
116 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
117 acpi_status status;
118
119 status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
120 ACPI_TYPE_PACKAGE);
121 if (ACPI_FAILURE(status))
122 return false;
123
dfa672fb
MW
124 if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
125 parent))
99db5ff7 126 return true;
445b0eb0 127
445b0eb0 128 ACPI_FREE(buf.pointer);
445b0eb0
RW
129 return false;
130}
131
99db5ff7
RW
132static bool acpi_nondev_subnode_ok(acpi_handle scope,
133 const union acpi_object *link,
dfa672fb
MW
134 struct list_head *list,
135 struct fwnode_handle *parent)
99db5ff7
RW
136{
137 acpi_handle handle;
138 acpi_status status;
139
140 if (!scope)
141 return false;
142
143 status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
144 &handle);
145 if (ACPI_FAILURE(status))
146 return false;
147
dfa672fb 148 return acpi_nondev_subnode_data_ok(handle, link, list, parent);
99db5ff7
RW
149}
150
445b0eb0
RW
151static int acpi_add_nondev_subnodes(acpi_handle scope,
152 const union acpi_object *links,
dfa672fb
MW
153 struct list_head *list,
154 struct fwnode_handle *parent)
445b0eb0
RW
155{
156 bool ret = false;
157 int i;
158
159 for (i = 0; i < links->package.count; i++) {
99db5ff7
RW
160 const union acpi_object *link, *desc;
161 acpi_handle handle;
162 bool result;
445b0eb0
RW
163
164 link = &links->package.elements[i];
99db5ff7
RW
165 /* Only two elements allowed. */
166 if (link->package.count != 2)
167 continue;
168
169 /* The first one must be a string. */
170 if (link->package.elements[0].type != ACPI_TYPE_STRING)
171 continue;
172
173 /* The second one may be a string, a reference or a package. */
174 switch (link->package.elements[1].type) {
175 case ACPI_TYPE_STRING:
dfa672fb
MW
176 result = acpi_nondev_subnode_ok(scope, link, list,
177 parent);
99db5ff7
RW
178 break;
179 case ACPI_TYPE_LOCAL_REFERENCE:
180 handle = link->package.elements[1].reference.handle;
dfa672fb
MW
181 result = acpi_nondev_subnode_data_ok(handle, link, list,
182 parent);
99db5ff7
RW
183 break;
184 case ACPI_TYPE_PACKAGE:
185 desc = &link->package.elements[1];
dfa672fb
MW
186 result = acpi_nondev_subnode_extract(desc, NULL, link,
187 list, parent);
99db5ff7
RW
188 break;
189 default:
190 result = false;
191 break;
192 }
193 ret = ret || result;
445b0eb0
RW
194 }
195
196 return ret;
197}
198
199static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
200 const union acpi_object *desc,
dfa672fb
MW
201 struct acpi_device_data *data,
202 struct fwnode_handle *parent)
445b0eb0
RW
203{
204 int i;
205
3689d3d6 206 /* Look for the ACPI data subnodes GUID. */
445b0eb0 207 for (i = 0; i < desc->package.count; i += 2) {
3689d3d6 208 const union acpi_object *guid, *links;
445b0eb0 209
3689d3d6 210 guid = &desc->package.elements[i];
445b0eb0
RW
211 links = &desc->package.elements[i + 1];
212
213 /*
3689d3d6 214 * The first element must be a GUID and the second one must be
445b0eb0
RW
215 * a package.
216 */
3689d3d6
AS
217 if (guid->type != ACPI_TYPE_BUFFER ||
218 guid->buffer.length != 16 ||
219 links->type != ACPI_TYPE_PACKAGE)
445b0eb0
RW
220 break;
221
3689d3d6 222 if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
445b0eb0
RW
223 continue;
224
dfa672fb
MW
225 return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
226 parent);
445b0eb0
RW
227 }
228
229 return false;
230}
ffdcd955
MW
231
232static bool acpi_property_value_ok(const union acpi_object *value)
233{
234 int j;
235
236 /*
237 * The value must be an integer, a string, a reference, or a package
238 * whose every element must be an integer, a string, or a reference.
239 */
240 switch (value->type) {
241 case ACPI_TYPE_INTEGER:
242 case ACPI_TYPE_STRING:
243 case ACPI_TYPE_LOCAL_REFERENCE:
244 return true;
245
246 case ACPI_TYPE_PACKAGE:
247 for (j = 0; j < value->package.count; j++)
248 switch (value->package.elements[j].type) {
249 case ACPI_TYPE_INTEGER:
250 case ACPI_TYPE_STRING:
251 case ACPI_TYPE_LOCAL_REFERENCE:
252 continue;
253
254 default:
255 return false;
256 }
257
258 return true;
259 }
260 return false;
261}
262
263static bool acpi_properties_format_valid(const union acpi_object *properties)
264{
265 int i;
266
267 for (i = 0; i < properties->package.count; i++) {
268 const union acpi_object *property;
269
270 property = &properties->package.elements[i];
271 /*
272 * Only two elements allowed, the first one must be a string and
273 * the second one has to satisfy certain conditions.
274 */
275 if (property->package.count != 2
276 || property->package.elements[0].type != ACPI_TYPE_STRING
277 || !acpi_property_value_ok(&property->package.elements[1]))
278 return false;
279 }
280 return true;
281}
282
733e6251
MW
283static void acpi_init_of_compatible(struct acpi_device *adev)
284{
285 const union acpi_object *of_compatible;
733e6251
MW
286 int ret;
287
3a7a2ab8
RW
288 ret = acpi_data_get_property_array(&adev->data, "compatible",
289 ACPI_TYPE_STRING, &of_compatible);
733e6251
MW
290 if (ret) {
291 ret = acpi_dev_get_property(adev, "compatible",
292 ACPI_TYPE_STRING, &of_compatible);
293 if (ret) {
5c53b262
RW
294 if (adev->parent
295 && adev->parent->flags.of_compatible_ok)
296 goto out;
297
733e6251
MW
298 return;
299 }
300 }
301 adev->data.of_compatible = of_compatible;
5c53b262
RW
302
303 out:
304 adev->flags.of_compatible_ok = 1;
733e6251
MW
305}
306
5f5e4890
MW
307static bool acpi_is_property_guid(const guid_t *guid)
308{
309 int i;
310
311 for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
312 if (guid_equal(guid, &prp_guids[i]))
313 return true;
314 }
315
316 return false;
317}
318
319struct acpi_device_properties *
320acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
321 const union acpi_object *properties)
322{
323 struct acpi_device_properties *props;
324
325 props = kzalloc(sizeof(*props), GFP_KERNEL);
326 if (props) {
327 INIT_LIST_HEAD(&props->list);
328 props->guid = guid;
329 props->properties = properties;
330 list_add_tail(&props->list, &data->properties);
331 }
332
333 return props;
334}
335
bd8191cc
RW
336static bool acpi_extract_properties(const union acpi_object *desc,
337 struct acpi_device_data *data)
ffdcd955 338{
ffdcd955
MW
339 int i;
340
ffdcd955 341 if (desc->package.count % 2)
bd8191cc 342 return false;
ffdcd955 343
3689d3d6 344 /* Look for the device properties GUID. */
ffdcd955 345 for (i = 0; i < desc->package.count; i += 2) {
3689d3d6 346 const union acpi_object *guid, *properties;
ffdcd955 347
3689d3d6 348 guid = &desc->package.elements[i];
ffdcd955
MW
349 properties = &desc->package.elements[i + 1];
350
351 /*
3689d3d6 352 * The first element must be a GUID and the second one must be
ffdcd955
MW
353 * a package.
354 */
3689d3d6
AS
355 if (guid->type != ACPI_TYPE_BUFFER ||
356 guid->buffer.length != 16 ||
357 properties->type != ACPI_TYPE_PACKAGE)
ffdcd955
MW
358 break;
359
5f5e4890 360 if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
ffdcd955
MW
361 continue;
362
363 /*
3689d3d6 364 * We found the matching GUID. Now validate the format of the
ffdcd955
MW
365 * package immediately following it.
366 */
367 if (!acpi_properties_format_valid(properties))
5f5e4890 368 continue;
ffdcd955 369
5f5e4890
MW
370 acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
371 properties);
bd8191cc 372 }
733e6251 373
5f5e4890 374 return !list_empty(&data->properties);
bd8191cc 375}
5c53b262 376
bd8191cc
RW
377void acpi_init_properties(struct acpi_device *adev)
378{
379 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
380 struct acpi_hardware_id *hwid;
381 acpi_status status;
382 bool acpi_of = false;
383
5f5e4890 384 INIT_LIST_HEAD(&adev->data.properties);
445b0eb0
RW
385 INIT_LIST_HEAD(&adev->data.subnodes);
386
75fc70e0
LW
387 if (!adev->handle)
388 return;
389
bd8191cc
RW
390 /*
391 * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
392 * Device Tree compatible properties for this device.
393 */
394 list_for_each_entry(hwid, &adev->pnp.ids, list) {
395 if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
396 acpi_of = true;
397 break;
398 }
ffdcd955
MW
399 }
400
bd8191cc
RW
401 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
402 ACPI_TYPE_PACKAGE);
403 if (ACPI_FAILURE(status))
404 goto out;
405
406 if (acpi_extract_properties(buf.pointer, &adev->data)) {
407 adev->data.pointer = buf.pointer;
408 if (acpi_of)
409 acpi_init_of_compatible(adev);
445b0eb0 410 }
dfa672fb
MW
411 if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
412 &adev->data, acpi_fwnode_handle(adev)))
445b0eb0
RW
413 adev->data.pointer = buf.pointer;
414
415 if (!adev->data.pointer) {
bd8191cc
RW
416 acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
417 ACPI_FREE(buf.pointer);
418 }
5c53b262
RW
419
420 out:
421 if (acpi_of && !adev->flags.of_compatible_ok)
422 acpi_handle_info(adev->handle,
ee892094 423 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
899596e0
LW
424
425 if (!adev->data.pointer)
426 acpi_extract_apple_properties(adev);
ffdcd955
MW
427}
428
445b0eb0
RW
429static void acpi_destroy_nondev_subnodes(struct list_head *list)
430{
431 struct acpi_data_node *dn, *next;
432
433 if (list_empty(list))
434 return;
435
436 list_for_each_entry_safe_reverse(dn, next, list, sibling) {
437 acpi_destroy_nondev_subnodes(&dn->data.subnodes);
263b4c1a 438 wait_for_completion(&dn->kobj_done);
445b0eb0
RW
439 list_del(&dn->sibling);
440 ACPI_FREE((void *)dn->data.pointer);
441 kfree(dn);
442 }
443}
444
ffdcd955
MW
445void acpi_free_properties(struct acpi_device *adev)
446{
5f5e4890
MW
447 struct acpi_device_properties *props, *tmp;
448
445b0eb0 449 acpi_destroy_nondev_subnodes(&adev->data.subnodes);
ffdcd955 450 ACPI_FREE((void *)adev->data.pointer);
733e6251 451 adev->data.of_compatible = NULL;
ffdcd955 452 adev->data.pointer = NULL;
5f5e4890
MW
453 list_for_each_entry_safe(props, tmp, &adev->data.properties, list) {
454 list_del(&props->list);
455 kfree(props);
456 }
ffdcd955
MW
457}
458
459/**
3a7a2ab8
RW
460 * acpi_data_get_property - return an ACPI property with given name
461 * @data: ACPI device deta object to get the property from
ffdcd955
MW
462 * @name: Name of the property
463 * @type: Expected property type
464 * @obj: Location to store the property value (if not %NULL)
465 *
466 * Look up a property with @name and store a pointer to the resulting ACPI
467 * object at the location pointed to by @obj if found.
468 *
469 * Callers must not attempt to free the returned objects. These objects will be
3a7a2ab8 470 * freed by the ACPI core automatically during the removal of @data.
ffdcd955
MW
471 *
472 * Return: %0 if property with @name has been found (success),
473 * %-EINVAL if the arguments are invalid,
3c60f114 474 * %-EINVAL if the property doesn't exist,
ffdcd955
MW
475 * %-EPROTO if the property value type doesn't match @type.
476 */
99a85464 477static int acpi_data_get_property(const struct acpi_device_data *data,
3a7a2ab8
RW
478 const char *name, acpi_object_type type,
479 const union acpi_object **obj)
ffdcd955 480{
5f5e4890 481 const struct acpi_device_properties *props;
ffdcd955 482
3a7a2ab8 483 if (!data || !name)
ffdcd955
MW
484 return -EINVAL;
485
5f5e4890 486 if (!data->pointer || list_empty(&data->properties))
3c60f114 487 return -EINVAL;
ffdcd955 488
5f5e4890
MW
489 list_for_each_entry(props, &data->properties, list) {
490 const union acpi_object *properties;
491 unsigned int i;
ffdcd955 492
5f5e4890
MW
493 properties = props->properties;
494 for (i = 0; i < properties->package.count; i++) {
495 const union acpi_object *propname, *propvalue;
496 const union acpi_object *property;
497
498 property = &properties->package.elements[i];
ffdcd955 499
5f5e4890
MW
500 propname = &property->package.elements[0];
501 propvalue = &property->package.elements[1];
ffdcd955 502
5f5e4890
MW
503 if (!strcmp(name, propname->string.pointer)) {
504 if (type != ACPI_TYPE_ANY &&
505 propvalue->type != type)
506 return -EPROTO;
507 if (obj)
508 *obj = propvalue;
ffdcd955 509
5f5e4890
MW
510 return 0;
511 }
ffdcd955
MW
512 }
513 }
3c60f114 514 return -EINVAL;
ffdcd955 515}
3a7a2ab8
RW
516
517/**
518 * acpi_dev_get_property - return an ACPI property with given name.
519 * @adev: ACPI device to get the property from.
520 * @name: Name of the property.
521 * @type: Expected property type.
522 * @obj: Location to store the property value (if not %NULL).
523 */
99a85464 524int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
3a7a2ab8
RW
525 acpi_object_type type, const union acpi_object **obj)
526{
527 return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
528}
ffdcd955
MW
529EXPORT_SYMBOL_GPL(acpi_dev_get_property);
530
99a85464
SA
531static const struct acpi_device_data *
532acpi_device_data_of_node(const struct fwnode_handle *fwnode)
3a7a2ab8 533{
db3e50f3 534 if (is_acpi_device_node(fwnode)) {
99a85464 535 const struct acpi_device *adev = to_acpi_device_node(fwnode);
3a7a2ab8 536 return &adev->data;
db3e50f3 537 } else if (is_acpi_data_node(fwnode)) {
99a85464 538 const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
3a7a2ab8
RW
539 return &dn->data;
540 }
541 return NULL;
542}
543
ffdcd955 544/**
3a7a2ab8
RW
545 * acpi_node_prop_get - return an ACPI property with given name.
546 * @fwnode: Firmware node to get the property from.
547 * @propname: Name of the property.
548 * @valptr: Location to store a pointer to the property value (if not %NULL).
549 */
99a85464
SA
550int acpi_node_prop_get(const struct fwnode_handle *fwnode,
551 const char *propname, void **valptr)
3a7a2ab8
RW
552{
553 return acpi_data_get_property(acpi_device_data_of_node(fwnode),
554 propname, ACPI_TYPE_ANY,
555 (const union acpi_object **)valptr);
556}
557
558/**
559 * acpi_data_get_property_array - return an ACPI array property with given name
560 * @adev: ACPI data object to get the property from
ffdcd955
MW
561 * @name: Name of the property
562 * @type: Expected type of array elements
563 * @obj: Location to store a pointer to the property value (if not NULL)
564 *
565 * Look up an array property with @name and store a pointer to the resulting
566 * ACPI object at the location pointed to by @obj if found.
567 *
568 * Callers must not attempt to free the returned objects. Those objects will be
3a7a2ab8 569 * freed by the ACPI core automatically during the removal of @data.
ffdcd955
MW
570 *
571 * Return: %0 if array property (package) with @name has been found (success),
572 * %-EINVAL if the arguments are invalid,
3c60f114 573 * %-EINVAL if the property doesn't exist,
ffdcd955
MW
574 * %-EPROTO if the property is not a package or the type of its elements
575 * doesn't match @type.
576 */
99a85464 577static int acpi_data_get_property_array(const struct acpi_device_data *data,
3a7a2ab8
RW
578 const char *name,
579 acpi_object_type type,
580 const union acpi_object **obj)
ffdcd955
MW
581{
582 const union acpi_object *prop;
583 int ret, i;
584
3a7a2ab8 585 ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
ffdcd955
MW
586 if (ret)
587 return ret;
588
589 if (type != ACPI_TYPE_ANY) {
590 /* Check that all elements are of correct type. */
591 for (i = 0; i < prop->package.count; i++)
592 if (prop->package.elements[i].type != type)
593 return -EPROTO;
594 }
595 if (obj)
596 *obj = prop;
597
598 return 0;
599}
ffdcd955 600
4eb0c3bf
SA
601static struct fwnode_handle *
602acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
603 const char *childname)
604{
605 struct fwnode_handle *child;
606
607 /*
608 * Find first matching named child node of this fwnode.
609 * For ACPI this will be a data only sub-node.
610 */
611 fwnode_for_each_child_node(fwnode, child)
612 if (acpi_data_node_match(child, childname))
613 return child;
614
615 return NULL;
616}
617
ffdcd955 618/**
b60e4ea4
MW
619 * __acpi_node_get_property_reference - returns handle to the referenced object
620 * @fwnode: Firmware node to get the property from
504a3374 621 * @propname: Name of the property
ffdcd955 622 * @index: Index of the reference to return
b60e4ea4 623 * @num_args: Maximum number of arguments after each reference
ffdcd955
MW
624 * @args: Location to store the returned reference with optional arguments
625 *
626 * Find property with @name, verifify that it is a package containing at least
627 * one object reference and if so, store the ACPI device object pointer to the
60ba032e
RW
628 * target object in @args->adev. If the reference includes arguments, store
629 * them in the @args->args[] array.
ffdcd955 630 *
60ba032e
RW
631 * If there's more than one reference in the property value package, @index is
632 * used to select the one to return.
ffdcd955 633 *
b60e4ea4
MW
634 * It is possible to leave holes in the property value set like in the
635 * example below:
636 *
637 * Package () {
638 * "cs-gpios",
639 * Package () {
640 * ^GPIO, 19, 0, 0,
641 * ^GPIO, 20, 0, 0,
642 * 0,
643 * ^GPIO, 21, 0, 0,
644 * }
645 * }
646 *
c343bc2c
SA
647 * Calling this function with index %2 or index %3 return %-ENOENT. If the
648 * property does not contain any more values %-ENOENT is returned. The NULL
649 * entry must be single integer and preferably contain value %0.
b60e4ea4 650 *
ffdcd955
MW
651 * Return: %0 on success, negative error code on failure.
652 */
99a85464 653int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
b60e4ea4 654 const char *propname, size_t index, size_t num_args,
977d5ad3 655 struct fwnode_reference_args *args)
ffdcd955
MW
656{
657 const union acpi_object *element, *end;
658 const union acpi_object *obj;
99a85464 659 const struct acpi_device_data *data;
ffdcd955
MW
660 struct acpi_device *device;
661 int ret, idx = 0;
662
b60e4ea4
MW
663 data = acpi_device_data_of_node(fwnode);
664 if (!data)
c343bc2c 665 return -ENOENT;
b60e4ea4 666
504a3374 667 ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
ffdcd955 668 if (ret)
51858a27 669 return ret == -EINVAL ? -ENOENT : -EINVAL;
ffdcd955
MW
670
671 /*
672 * The simplest case is when the value is a single reference. Just
673 * return that reference then.
674 */
675 if (obj->type == ACPI_TYPE_LOCAL_REFERENCE) {
60ba032e 676 if (index)
ffdcd955
MW
677 return -EINVAL;
678
679 ret = acpi_bus_get_device(obj->reference.handle, &device);
680 if (ret)
51858a27 681 return ret == -ENODEV ? -EINVAL : ret;
ffdcd955 682
977d5ad3 683 args->fwnode = acpi_fwnode_handle(device);
ffdcd955
MW
684 args->nargs = 0;
685 return 0;
686 }
687
688 /*
689 * If it is not a single reference, then it is a package of
690 * references followed by number of ints as follows:
691 *
692 * Package () { REF, INT, REF, INT, INT }
693 *
694 * The index argument is then used to determine which reference
695 * the caller wants (along with the arguments).
696 */
51858a27
SA
697 if (obj->type != ACPI_TYPE_PACKAGE)
698 return -EINVAL;
699 if (index >= obj->package.count)
700 return -ENOENT;
ffdcd955
MW
701
702 element = obj->package.elements;
703 end = element + obj->package.count;
704
705 while (element < end) {
706 u32 nargs, i;
707
b60e4ea4 708 if (element->type == ACPI_TYPE_LOCAL_REFERENCE) {
4eb0c3bf
SA
709 struct fwnode_handle *ref_fwnode;
710
b60e4ea4
MW
711 ret = acpi_bus_get_device(element->reference.handle,
712 &device);
713 if (ret)
c343bc2c 714 return -EINVAL;
b60e4ea4
MW
715
716 nargs = 0;
717 element++;
718
4eb0c3bf
SA
719 /*
720 * Find the referred data extension node under the
721 * referred device node.
722 */
723 for (ref_fwnode = acpi_fwnode_handle(device);
724 element < end && element->type == ACPI_TYPE_STRING;
725 element++) {
726 ref_fwnode = acpi_fwnode_get_named_child_node(
727 ref_fwnode, element->string.pointer);
728 if (!ref_fwnode)
729 return -EINVAL;
730 }
731
b60e4ea4
MW
732 /* assume following integer elements are all args */
733 for (i = 0; element + i < end && i < num_args; i++) {
734 int type = element[i].type;
735
736 if (type == ACPI_TYPE_INTEGER)
737 nargs++;
738 else if (type == ACPI_TYPE_LOCAL_REFERENCE)
739 break;
740 else
c343bc2c 741 return -EINVAL;
b60e4ea4 742 }
ffdcd955 743
977d5ad3 744 if (nargs > NR_FWNODE_REFERENCE_ARGS)
c343bc2c 745 return -EINVAL;
ffdcd955 746
b60e4ea4 747 if (idx == index) {
4eb0c3bf 748 args->fwnode = ref_fwnode;
b60e4ea4
MW
749 args->nargs = nargs;
750 for (i = 0; i < nargs; i++)
751 args->args[i] = element[i].integer.value;
ffdcd955 752
b60e4ea4
MW
753 return 0;
754 }
755
756 element += nargs;
757 } else if (element->type == ACPI_TYPE_INTEGER) {
758 if (idx == index)
759 return -ENOENT;
760 element++;
761 } else {
c343bc2c 762 return -EINVAL;
ffdcd955
MW
763 }
764
b60e4ea4 765 idx++;
ffdcd955
MW
766 }
767
c343bc2c 768 return -ENOENT;
504a3374 769}
b60e4ea4 770EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
b31384fa 771
99a85464 772static int acpi_data_prop_read_single(const struct acpi_device_data *data,
3a7a2ab8
RW
773 const char *propname,
774 enum dev_prop_type proptype, void *val)
b31384fa
RW
775{
776 const union acpi_object *obj;
777 int ret;
778
779 if (!val)
780 return -EINVAL;
781
782 if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
3a7a2ab8 783 ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
b31384fa
RW
784 if (ret)
785 return ret;
786
787 switch (proptype) {
788 case DEV_PROP_U8:
789 if (obj->integer.value > U8_MAX)
790 return -EOVERFLOW;
791 *(u8 *)val = obj->integer.value;
792 break;
793 case DEV_PROP_U16:
794 if (obj->integer.value > U16_MAX)
795 return -EOVERFLOW;
796 *(u16 *)val = obj->integer.value;
797 break;
798 case DEV_PROP_U32:
799 if (obj->integer.value > U32_MAX)
800 return -EOVERFLOW;
801 *(u32 *)val = obj->integer.value;
802 break;
803 default:
804 *(u64 *)val = obj->integer.value;
805 break;
806 }
807 } else if (proptype == DEV_PROP_STRING) {
3a7a2ab8 808 ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
b31384fa
RW
809 if (ret)
810 return ret;
811
812 *(char **)val = obj->string.pointer;
b0b027ce
SA
813
814 return 1;
b31384fa
RW
815 } else {
816 ret = -EINVAL;
817 }
818 return ret;
819}
820
3a7a2ab8
RW
821int acpi_dev_prop_read_single(struct acpi_device *adev, const char *propname,
822 enum dev_prop_type proptype, void *val)
823{
b0b027ce
SA
824 int ret;
825
826 if (!adev)
827 return -EINVAL;
828
829 ret = acpi_data_prop_read_single(&adev->data, propname, proptype, val);
830 if (ret < 0 || proptype != ACPI_TYPE_STRING)
831 return ret;
832 return 0;
3a7a2ab8
RW
833}
834
b31384fa
RW
835static int acpi_copy_property_array_u8(const union acpi_object *items, u8 *val,
836 size_t nval)
837{
838 int i;
839
840 for (i = 0; i < nval; i++) {
841 if (items[i].type != ACPI_TYPE_INTEGER)
842 return -EPROTO;
843 if (items[i].integer.value > U8_MAX)
844 return -EOVERFLOW;
845
846 val[i] = items[i].integer.value;
847 }
848 return 0;
849}
850
851static int acpi_copy_property_array_u16(const union acpi_object *items,
852 u16 *val, size_t nval)
853{
854 int i;
855
856 for (i = 0; i < nval; i++) {
857 if (items[i].type != ACPI_TYPE_INTEGER)
858 return -EPROTO;
859 if (items[i].integer.value > U16_MAX)
860 return -EOVERFLOW;
861
862 val[i] = items[i].integer.value;
863 }
864 return 0;
865}
866
867static int acpi_copy_property_array_u32(const union acpi_object *items,
868 u32 *val, size_t nval)
869{
870 int i;
871
872 for (i = 0; i < nval; i++) {
873 if (items[i].type != ACPI_TYPE_INTEGER)
874 return -EPROTO;
875 if (items[i].integer.value > U32_MAX)
876 return -EOVERFLOW;
877
878 val[i] = items[i].integer.value;
879 }
880 return 0;
881}
882
883static int acpi_copy_property_array_u64(const union acpi_object *items,
884 u64 *val, size_t nval)
885{
886 int i;
887
888 for (i = 0; i < nval; i++) {
889 if (items[i].type != ACPI_TYPE_INTEGER)
890 return -EPROTO;
891
892 val[i] = items[i].integer.value;
893 }
894 return 0;
895}
896
897static int acpi_copy_property_array_string(const union acpi_object *items,
898 char **val, size_t nval)
899{
900 int i;
901
902 for (i = 0; i < nval; i++) {
903 if (items[i].type != ACPI_TYPE_STRING)
904 return -EPROTO;
905
906 val[i] = items[i].string.pointer;
907 }
b0b027ce 908 return nval;
b31384fa
RW
909}
910
99a85464 911static int acpi_data_prop_read(const struct acpi_device_data *data,
3a7a2ab8
RW
912 const char *propname,
913 enum dev_prop_type proptype,
914 void *val, size_t nval)
b31384fa
RW
915{
916 const union acpi_object *obj;
917 const union acpi_object *items;
918 int ret;
919
920 if (val && nval == 1) {
3a7a2ab8 921 ret = acpi_data_prop_read_single(data, propname, proptype, val);
b0b027ce 922 if (ret >= 0)
b31384fa
RW
923 return ret;
924 }
925
3a7a2ab8 926 ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
b31384fa
RW
927 if (ret)
928 return ret;
929
930 if (!val)
931 return obj->package.count;
b31384fa 932
b0b027ce 933 if (proptype != DEV_PROP_STRING && nval > obj->package.count)
b31384fa 934 return -EOVERFLOW;
7dc59dc9
AS
935 else if (nval <= 0)
936 return -EINVAL;
b31384fa
RW
937
938 items = obj->package.elements;
7dc59dc9 939
b31384fa
RW
940 switch (proptype) {
941 case DEV_PROP_U8:
942 ret = acpi_copy_property_array_u8(items, (u8 *)val, nval);
943 break;
944 case DEV_PROP_U16:
945 ret = acpi_copy_property_array_u16(items, (u16 *)val, nval);
946 break;
947 case DEV_PROP_U32:
948 ret = acpi_copy_property_array_u32(items, (u32 *)val, nval);
949 break;
950 case DEV_PROP_U64:
951 ret = acpi_copy_property_array_u64(items, (u64 *)val, nval);
952 break;
953 case DEV_PROP_STRING:
b0b027ce
SA
954 ret = acpi_copy_property_array_string(
955 items, (char **)val,
956 min_t(u32, nval, obj->package.count));
b31384fa
RW
957 break;
958 default:
959 ret = -EINVAL;
960 break;
961 }
962 return ret;
963}
3a7a2ab8 964
99a85464 965int acpi_dev_prop_read(const struct acpi_device *adev, const char *propname,
3a7a2ab8
RW
966 enum dev_prop_type proptype, void *val, size_t nval)
967{
968 return adev ? acpi_data_prop_read(&adev->data, propname, proptype, val, nval) : -EINVAL;
969}
970
971/**
972 * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
973 * @fwnode: Firmware node to get the property from.
974 * @propname: Name of the property.
975 * @proptype: Expected property type.
976 * @val: Location to store the property value (if not %NULL).
977 * @nval: Size of the array pointed to by @val.
978 *
979 * If @val is %NULL, return the number of array elements comprising the value
980 * of the property. Otherwise, read at most @nval values to the array at the
981 * location pointed to by @val.
982 */
99a85464
SA
983int acpi_node_prop_read(const struct fwnode_handle *fwnode,
984 const char *propname, enum dev_prop_type proptype,
985 void *val, size_t nval)
3a7a2ab8
RW
986{
987 return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
988 propname, proptype, val, nval);
989}
504a3374
RW
990
991/**
34055190
MW
992 * acpi_get_next_subnode - Return the next child node handle for a fwnode
993 * @fwnode: Firmware node to find the next child node for.
504a3374
RW
994 * @child: Handle to one of the device's child nodes or a null handle.
995 */
37ba983c 996struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
504a3374
RW
997 struct fwnode_handle *child)
998{
01c1da28 999 const struct acpi_device *adev = to_acpi_device_node(fwnode);
01c1da28
SA
1000 const struct list_head *head;
1001 struct list_head *next;
504a3374 1002
db3e50f3 1003 if (!child || is_acpi_device_node(child)) {
0c0bceb7
SA
1004 struct acpi_device *child_adev;
1005
34055190
MW
1006 if (adev)
1007 head = &adev->children;
1008 else
1009 goto nondev;
1010
504a3374
RW
1011 if (list_empty(head))
1012 goto nondev;
1013
1014 if (child) {
0c0bceb7
SA
1015 adev = to_acpi_device_node(child);
1016 next = adev->node.next;
504a3374
RW
1017 if (next == head) {
1018 child = NULL;
1019 goto nondev;
1020 }
01c1da28 1021 child_adev = list_entry(next, struct acpi_device, node);
504a3374 1022 } else {
01c1da28
SA
1023 child_adev = list_first_entry(head, struct acpi_device,
1024 node);
504a3374 1025 }
01c1da28 1026 return acpi_fwnode_handle(child_adev);
504a3374
RW
1027 }
1028
1029 nondev:
db3e50f3 1030 if (!child || is_acpi_data_node(child)) {
01c1da28 1031 const struct acpi_data_node *data = to_acpi_data_node(fwnode);
504a3374
RW
1032 struct acpi_data_node *dn;
1033
0c0bceb7
SA
1034 if (adev)
1035 head = &adev->data.subnodes;
34055190
MW
1036 else if (data)
1037 head = &data->data.subnodes;
1038 else
1039 return NULL;
1040
504a3374
RW
1041 if (list_empty(head))
1042 return NULL;
1043
1044 if (child) {
1045 dn = to_acpi_data_node(child);
1046 next = dn->sibling.next;
1047 if (next == head)
1048 return NULL;
1049
1050 dn = list_entry(next, struct acpi_data_node, sibling);
1051 } else {
1052 dn = list_first_entry(head, struct acpi_data_node, sibling);
1053 }
1054 return &dn->fwnode;
1055 }
1056 return NULL;
1057}
dfa672fb
MW
1058
1059/**
1060 * acpi_node_get_parent - Return parent fwnode of this fwnode
1061 * @fwnode: Firmware node whose parent to get
1062 *
1063 * Returns parent node of an ACPI device or data firmware node or %NULL if
1064 * not available.
1065 */
37ba983c 1066struct fwnode_handle *acpi_node_get_parent(const struct fwnode_handle *fwnode)
dfa672fb
MW
1067{
1068 if (is_acpi_data_node(fwnode)) {
1069 /* All data nodes have parent pointer so just return that */
1070 return to_acpi_data_node(fwnode)->parent;
1071 } else if (is_acpi_device_node(fwnode)) {
1072 acpi_handle handle, parent_handle;
1073
1074 handle = to_acpi_device_node(fwnode)->handle;
1075 if (ACPI_SUCCESS(acpi_get_parent(handle, &parent_handle))) {
1076 struct acpi_device *adev;
1077
1078 if (!acpi_bus_get_device(parent_handle, &adev))
1079 return acpi_fwnode_handle(adev);
1080 }
1081 }
1082
1083 return NULL;
1084}
79389a83 1085
18f1e58d
SA
1086/*
1087 * Return true if the node is an ACPI graph node. Called on either ports
1088 * or endpoints.
1089 */
1090static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
1091 const char *str)
1092{
1093 unsigned int len = strlen(str);
1094 const char *name;
1095
1096 if (!len || !is_acpi_data_node(fwnode))
1097 return false;
1098
1099 name = to_acpi_data_node(fwnode)->name;
1100
1101 return (fwnode_property_present(fwnode, "reg") &&
1102 !strncmp(name, str, len) && name[len] == '@') ||
1103 fwnode_property_present(fwnode, str);
1104}
1105
79389a83
MW
1106/**
1107 * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node
1108 * @fwnode: Pointer to the parent firmware node
1109 * @prev: Previous endpoint node or %NULL to get the first
1110 *
1111 * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns
0ef74786
SA
1112 * %NULL if there is no next endpoint or in case of error. In case of success
1113 * the next endpoint is returned.
79389a83 1114 */
0ef74786 1115static struct fwnode_handle *acpi_graph_get_next_endpoint(
37ba983c 1116 const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
79389a83
MW
1117{
1118 struct fwnode_handle *port = NULL;
1119 struct fwnode_handle *endpoint;
1120
1121 if (!prev) {
1122 do {
1123 port = fwnode_get_next_child_node(fwnode, port);
18f1e58d
SA
1124 /*
1125 * The names of the port nodes begin with "port@"
1126 * followed by the number of the port node and they also
1127 * have a "reg" property that also has the number of the
1128 * port node. For compatibility reasons a node is also
1129 * recognised as a port node from the "port" property.
1130 */
1131 if (is_acpi_graph_node(port, "port"))
79389a83
MW
1132 break;
1133 } while (port);
1134 } else {
1135 port = fwnode_get_parent(prev);
1136 }
1137
1138 if (!port)
1139 return NULL;
1140
1141 endpoint = fwnode_get_next_child_node(port, prev);
1142 while (!endpoint) {
1143 port = fwnode_get_next_child_node(fwnode, port);
1144 if (!port)
1145 break;
18f1e58d 1146 if (is_acpi_graph_node(port, "port"))
79389a83
MW
1147 endpoint = fwnode_get_next_child_node(port, NULL);
1148 }
1149
18f1e58d
SA
1150 /*
1151 * The names of the endpoint nodes begin with "endpoint@" followed by
1152 * the number of the endpoint node and they also have a "reg" property
1153 * that also has the number of the endpoint node. For compatibility
1154 * reasons a node is also recognised as an endpoint node from the
1155 * "endpoint" property.
1156 */
1157 if (!is_acpi_graph_node(endpoint, "endpoint"))
0ef74786 1158 return NULL;
79389a83
MW
1159
1160 return endpoint;
1161}
1162
1163/**
1164 * acpi_graph_get_child_prop_value - Return a child with a given property value
1165 * @fwnode: device fwnode
1166 * @prop_name: The name of the property to look for
1167 * @val: the desired property value
1168 *
1169 * Return the port node corresponding to a given port number. Returns
1170 * the child node on success, NULL otherwise.
1171 */
1172static struct fwnode_handle *acpi_graph_get_child_prop_value(
37ba983c
SA
1173 const struct fwnode_handle *fwnode, const char *prop_name,
1174 unsigned int val)
79389a83
MW
1175{
1176 struct fwnode_handle *child;
1177
1178 fwnode_for_each_child_node(fwnode, child) {
1179 u32 nr;
1180
b5212f57 1181 if (fwnode_property_read_u32(child, prop_name, &nr))
79389a83
MW
1182 continue;
1183
1184 if (val == nr)
1185 return child;
1186 }
1187
1188 return NULL;
1189}
1190
1191
1192/**
1193 * acpi_graph_get_remote_enpoint - Parses and returns remote end of an endpoint
1194 * @fwnode: Endpoint firmware node pointing to a remote device
79389a83
MW
1195 * @endpoint: Firmware node of remote endpoint is filled here if not %NULL
1196 *
0ef74786 1197 * Returns the remote endpoint corresponding to @__fwnode. NULL on error.
79389a83 1198 */
0ef74786
SA
1199static struct fwnode_handle *
1200acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
79389a83 1201{
37ba983c 1202 struct fwnode_handle *fwnode;
79389a83 1203 unsigned int port_nr, endpoint_nr;
977d5ad3 1204 struct fwnode_reference_args args;
79389a83
MW
1205 int ret;
1206
1207 memset(&args, 0, sizeof(args));
37ba983c 1208 ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
79389a83
MW
1209 &args);
1210 if (ret)
0ef74786 1211 return NULL;
79389a83 1212
6561eb3d 1213 /* Direct endpoint reference? */
977d5ad3 1214 if (!is_acpi_device_node(args.fwnode))
6561eb3d 1215 return args.nargs ? NULL : args.fwnode;
977d5ad3 1216
79389a83
MW
1217 /*
1218 * Always require two arguments with the reference: port and
1219 * endpoint indices.
1220 */
1221 if (args.nargs != 2)
0ef74786 1222 return NULL;
79389a83 1223
977d5ad3 1224 fwnode = args.fwnode;
79389a83
MW
1225 port_nr = args.args[0];
1226 endpoint_nr = args.args[1];
1227
79389a83 1228 fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
79389a83 1229
18f1e58d 1230 return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
79389a83 1231}
3708184a 1232
37ba983c 1233static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
2294b3af
SA
1234{
1235 if (!is_acpi_device_node(fwnode))
1236 return false;
1237
1238 return acpi_device_is_present(to_acpi_device_node(fwnode));
1239}
1240
37ba983c 1241static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
3708184a
SA
1242 const char *propname)
1243{
1244 return !acpi_node_prop_get(fwnode, propname, NULL);
1245}
1246
37ba983c
SA
1247static int
1248acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
1249 const char *propname,
1250 unsigned int elem_size, void *val,
1251 size_t nval)
3708184a
SA
1252{
1253 enum dev_prop_type type;
1254
1255 switch (elem_size) {
1256 case sizeof(u8):
1257 type = DEV_PROP_U8;
1258 break;
1259 case sizeof(u16):
1260 type = DEV_PROP_U16;
1261 break;
1262 case sizeof(u32):
1263 type = DEV_PROP_U32;
1264 break;
1265 case sizeof(u64):
1266 type = DEV_PROP_U64;
1267 break;
1268 default:
1269 return -ENXIO;
1270 }
1271
1272 return acpi_node_prop_read(fwnode, propname, type, val, nval);
1273}
1274
37ba983c
SA
1275static int
1276acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
1277 const char *propname, const char **val,
1278 size_t nval)
3708184a
SA
1279{
1280 return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
1281 val, nval);
1282}
1283
3e3119d3
SA
1284static int
1285acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
1286 const char *prop, const char *nargs_prop,
1287 unsigned int args_count, unsigned int index,
1288 struct fwnode_reference_args *args)
1289{
977d5ad3
SA
1290 return __acpi_node_get_property_reference(fwnode, prop, index,
1291 args_count, args);
3e3119d3
SA
1292}
1293
37ba983c
SA
1294static struct fwnode_handle *
1295acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
1296{
1297 return acpi_node_get_parent(fwnode);
1298}
1299
1300static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
3b27d00e
SA
1301 struct fwnode_endpoint *endpoint)
1302{
1303 struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
1304
1305 endpoint->local_fwnode = fwnode;
1306
18f1e58d
SA
1307 if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
1308 fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
1309 if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
1310 fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
3b27d00e
SA
1311
1312 return 0;
1313}
1314
67dcc26d 1315static const void *
146b4dbb
SK
1316acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
1317 const struct device *dev)
1318{
29d5325a 1319 return acpi_device_get_match_data(dev);
146b4dbb
SK
1320}
1321
db3e50f3
SA
1322#define DECLARE_ACPI_FWNODE_OPS(ops) \
1323 const struct fwnode_operations ops = { \
1324 .device_is_available = acpi_fwnode_device_is_available, \
146b4dbb 1325 .device_get_match_data = acpi_fwnode_device_get_match_data, \
db3e50f3
SA
1326 .property_present = acpi_fwnode_property_present, \
1327 .property_read_int_array = \
1328 acpi_fwnode_property_read_int_array, \
1329 .property_read_string_array = \
1330 acpi_fwnode_property_read_string_array, \
1331 .get_parent = acpi_node_get_parent, \
1332 .get_next_child_node = acpi_get_next_subnode, \
1333 .get_named_child_node = acpi_fwnode_get_named_child_node, \
3e3119d3 1334 .get_reference_args = acpi_fwnode_get_reference_args, \
db3e50f3 1335 .graph_get_next_endpoint = \
0ef74786 1336 acpi_graph_get_next_endpoint, \
db3e50f3 1337 .graph_get_remote_endpoint = \
0ef74786 1338 acpi_graph_get_remote_endpoint, \
37ba983c 1339 .graph_get_port_parent = acpi_fwnode_get_parent, \
db3e50f3
SA
1340 .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
1341 }; \
1342 EXPORT_SYMBOL_GPL(ops)
1343
1344DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
1345DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
1346const struct fwnode_operations acpi_static_fwnode_ops;
9e987b70
JH
1347
1348bool is_acpi_device_node(const struct fwnode_handle *fwnode)
1349{
1350 return !IS_ERR_OR_NULL(fwnode) &&
1351 fwnode->ops == &acpi_device_fwnode_ops;
1352}
1353EXPORT_SYMBOL(is_acpi_device_node);
1354
1355bool is_acpi_data_node(const struct fwnode_handle *fwnode)
1356{
1357 return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
1358}
1359EXPORT_SYMBOL(is_acpi_data_node);