ACPI: property: Read buffer properties as integers
[linux-2.6-block.git] / drivers / acpi / property.c
CommitLineData
d2912cb1 1// SPDX-License-Identifier: GPL-2.0-only
ffdcd955
MW
2/*
3 * ACPI device specific properties support.
4 *
5 * Copyright (C) 2014, Intel Corporation
6 * All rights reserved.
7 *
8 * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
9 * Darren Hart <dvhart@linux.intel.com>
10 * Rafael J. Wysocki <rafael.j.wysocki@intel.com>
ffdcd955
MW
11 */
12
13#include <linux/acpi.h>
14#include <linux/device.h>
15#include <linux/export.h>
16
17#include "internal.h"
18
99a85464 19static int acpi_data_get_property_array(const struct acpi_device_data *data,
3a7a2ab8
RW
20 const char *name,
21 acpi_object_type type,
22 const union acpi_object **obj);
23
617654aa
MW
24/*
25 * The GUIDs here are made equivalent to each other in order to avoid extra
26 * complexity in the properties handling code, with the caveat that the
27 * kernel will accept certain combinations of GUID and properties that are
28 * not defined without a warning. For instance if any of the properties
29 * from different GUID appear in a property list of another, it will be
30 * accepted by the kernel. Firmware validation tools should catch these.
31 */
5f5e4890
MW
32static const guid_t prp_guids[] = {
33 /* ACPI _DSD device properties GUID: daffd814-6eba-4d8c-8a91-bc9bbf4aa301 */
3689d3d6 34 GUID_INIT(0xdaffd814, 0x6eba, 0x4d8c,
5f5e4890 35 0x8a, 0x91, 0xbc, 0x9b, 0xbf, 0x4a, 0xa3, 0x01),
26ad34d5
MW
36 /* Hotplug in D3 GUID: 6211e2c0-58a3-4af3-90e1-927a4e0c55a4 */
37 GUID_INIT(0x6211e2c0, 0x58a3, 0x4af3,
38 0x90, 0xe1, 0x92, 0x7a, 0x4e, 0x0c, 0x55, 0xa4),
617654aa
MW
39 /* External facing port GUID: efcc06cc-73ac-4bc3-bff0-76143807c389 */
40 GUID_INIT(0xefcc06cc, 0x73ac, 0x4bc3,
41 0xbf, 0xf0, 0x76, 0x14, 0x38, 0x07, 0xc3, 0x89),
dfda2041
MW
42 /* Thunderbolt GUID for IMR_VALID: c44d002f-69f9-4e7d-a904-a7baabdf43f7 */
43 GUID_INIT(0xc44d002f, 0x69f9, 0x4e7d,
44 0xa9, 0x04, 0xa7, 0xba, 0xab, 0xdf, 0x43, 0xf7),
45 /* Thunderbolt GUID for WAKE_SUPPORTED: 6c501103-c189-4296-ba72-9bf5a26ebe5d */
46 GUID_INIT(0x6c501103, 0xc189, 0x4296,
47 0xba, 0x72, 0x9b, 0xf5, 0xa2, 0x6e, 0xbe, 0x5d),
df4f9bc4
DB
48 /* Storage device needs D3 GUID: 5025030f-842f-4ab4-a561-99a5189762d0 */
49 GUID_INIT(0x5025030f, 0x842f, 0x4ab4,
50 0xa5, 0x61, 0x99, 0xa5, 0x18, 0x97, 0x62, 0xd0),
5f5e4890
MW
51};
52
5f21f305 53/* ACPI _DSD data subnodes GUID: dbb8e3e6-5886-4ba6-8795-1319f52a966b */
3689d3d6
AS
54static const guid_t ads_guid =
55 GUID_INIT(0xdbb8e3e6, 0x5886, 0x4ba6,
56 0x87, 0x95, 0x13, 0x19, 0xf5, 0x2a, 0x96, 0x6b);
445b0eb0 57
103e10c6
SA
58static const guid_t buffer_prop_guid =
59 GUID_INIT(0xedb12dd0, 0x363d, 0x4085,
60 0xa3, 0xd2, 0x49, 0x52, 0x2c, 0xa1, 0x60, 0xc4);
61
445b0eb0 62static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
103e10c6 63 union acpi_object *desc,
dfa672fb
MW
64 struct acpi_device_data *data,
65 struct fwnode_handle *parent);
103e10c6
SA
66static bool acpi_extract_properties(acpi_handle handle,
67 union acpi_object *desc,
445b0eb0
RW
68 struct acpi_device_data *data);
69
103e10c6 70static bool acpi_nondev_subnode_extract(union acpi_object *desc,
99db5ff7
RW
71 acpi_handle handle,
72 const union acpi_object *link,
dfa672fb
MW
73 struct list_head *list,
74 struct fwnode_handle *parent)
445b0eb0 75{
445b0eb0 76 struct acpi_data_node *dn;
99db5ff7 77 bool result;
445b0eb0
RW
78
79 dn = kzalloc(sizeof(*dn), GFP_KERNEL);
80 if (!dn)
81 return false;
82
83 dn->name = link->package.elements[0].string.pointer;
01bb86b3 84 fwnode_init(&dn->fwnode, &acpi_data_fwnode_ops);
dfa672fb 85 dn->parent = parent;
5f5e4890 86 INIT_LIST_HEAD(&dn->data.properties);
445b0eb0
RW
87 INIT_LIST_HEAD(&dn->data.subnodes);
88
103e10c6 89 result = acpi_extract_properties(handle, desc, &dn->data);
445b0eb0 90
99db5ff7
RW
91 if (handle) {
92 acpi_handle scope;
93 acpi_status status;
445b0eb0 94
99db5ff7
RW
95 /*
96 * The scope for the subnode object lookup is the one of the
97 * namespace node (device) containing the object that has
98 * returned the package. That is, it's the scope of that
99 * object's parent.
100 */
101 status = acpi_get_parent(handle, &scope);
102 if (ACPI_SUCCESS(status)
dfa672fb
MW
103 && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data,
104 &dn->fwnode))
99db5ff7 105 result = true;
dfa672fb
MW
106 } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data,
107 &dn->fwnode)) {
99db5ff7
RW
108 result = true;
109 }
445b0eb0 110
99db5ff7 111 if (result) {
263b4c1a 112 dn->handle = handle;
99db5ff7 113 dn->data.pointer = desc;
445b0eb0
RW
114 list_add_tail(&dn->sibling, list);
115 return true;
116 }
117
99db5ff7 118 kfree(dn);
445b0eb0 119 acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n");
99db5ff7
RW
120 return false;
121}
122
123static bool acpi_nondev_subnode_data_ok(acpi_handle handle,
124 const union acpi_object *link,
dfa672fb
MW
125 struct list_head *list,
126 struct fwnode_handle *parent)
99db5ff7
RW
127{
128 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
129 acpi_status status;
130
131 status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf,
132 ACPI_TYPE_PACKAGE);
133 if (ACPI_FAILURE(status))
134 return false;
135
dfa672fb
MW
136 if (acpi_nondev_subnode_extract(buf.pointer, handle, link, list,
137 parent))
99db5ff7 138 return true;
445b0eb0 139
445b0eb0 140 ACPI_FREE(buf.pointer);
445b0eb0
RW
141 return false;
142}
143
99db5ff7
RW
144static bool acpi_nondev_subnode_ok(acpi_handle scope,
145 const union acpi_object *link,
dfa672fb
MW
146 struct list_head *list,
147 struct fwnode_handle *parent)
99db5ff7
RW
148{
149 acpi_handle handle;
150 acpi_status status;
151
152 if (!scope)
153 return false;
154
155 status = acpi_get_handle(scope, link->package.elements[1].string.pointer,
156 &handle);
157 if (ACPI_FAILURE(status))
158 return false;
159
dfa672fb 160 return acpi_nondev_subnode_data_ok(handle, link, list, parent);
99db5ff7
RW
161}
162
85140ef2 163static bool acpi_add_nondev_subnodes(acpi_handle scope,
103e10c6 164 union acpi_object *links,
85140ef2
SA
165 struct list_head *list,
166 struct fwnode_handle *parent)
445b0eb0
RW
167{
168 bool ret = false;
169 int i;
170
171 for (i = 0; i < links->package.count; i++) {
103e10c6 172 union acpi_object *link, *desc;
99db5ff7
RW
173 acpi_handle handle;
174 bool result;
445b0eb0
RW
175
176 link = &links->package.elements[i];
99db5ff7
RW
177 /* Only two elements allowed. */
178 if (link->package.count != 2)
179 continue;
180
181 /* The first one must be a string. */
182 if (link->package.elements[0].type != ACPI_TYPE_STRING)
183 continue;
184
185 /* The second one may be a string, a reference or a package. */
186 switch (link->package.elements[1].type) {
187 case ACPI_TYPE_STRING:
dfa672fb
MW
188 result = acpi_nondev_subnode_ok(scope, link, list,
189 parent);
99db5ff7
RW
190 break;
191 case ACPI_TYPE_LOCAL_REFERENCE:
192 handle = link->package.elements[1].reference.handle;
dfa672fb
MW
193 result = acpi_nondev_subnode_data_ok(handle, link, list,
194 parent);
99db5ff7
RW
195 break;
196 case ACPI_TYPE_PACKAGE:
197 desc = &link->package.elements[1];
dfa672fb
MW
198 result = acpi_nondev_subnode_extract(desc, NULL, link,
199 list, parent);
99db5ff7
RW
200 break;
201 default:
202 result = false;
203 break;
204 }
205 ret = ret || result;
445b0eb0
RW
206 }
207
208 return ret;
209}
210
211static bool acpi_enumerate_nondev_subnodes(acpi_handle scope,
103e10c6 212 union acpi_object *desc,
dfa672fb
MW
213 struct acpi_device_data *data,
214 struct fwnode_handle *parent)
445b0eb0
RW
215{
216 int i;
217
3689d3d6 218 /* Look for the ACPI data subnodes GUID. */
445b0eb0 219 for (i = 0; i < desc->package.count; i += 2) {
103e10c6
SA
220 const union acpi_object *guid;
221 union acpi_object *links;
445b0eb0 222
3689d3d6 223 guid = &desc->package.elements[i];
445b0eb0
RW
224 links = &desc->package.elements[i + 1];
225
226 /*
3689d3d6 227 * The first element must be a GUID and the second one must be
445b0eb0
RW
228 * a package.
229 */
3689d3d6
AS
230 if (guid->type != ACPI_TYPE_BUFFER ||
231 guid->buffer.length != 16 ||
232 links->type != ACPI_TYPE_PACKAGE)
445b0eb0
RW
233 break;
234
3689d3d6 235 if (!guid_equal((guid_t *)guid->buffer.pointer, &ads_guid))
445b0eb0
RW
236 continue;
237
dfa672fb
MW
238 return acpi_add_nondev_subnodes(scope, links, &data->subnodes,
239 parent);
445b0eb0
RW
240 }
241
242 return false;
243}
ffdcd955
MW
244
245static bool acpi_property_value_ok(const union acpi_object *value)
246{
247 int j;
248
249 /*
250 * The value must be an integer, a string, a reference, or a package
251 * whose every element must be an integer, a string, or a reference.
252 */
253 switch (value->type) {
254 case ACPI_TYPE_INTEGER:
255 case ACPI_TYPE_STRING:
256 case ACPI_TYPE_LOCAL_REFERENCE:
257 return true;
258
259 case ACPI_TYPE_PACKAGE:
260 for (j = 0; j < value->package.count; j++)
261 switch (value->package.elements[j].type) {
262 case ACPI_TYPE_INTEGER:
263 case ACPI_TYPE_STRING:
264 case ACPI_TYPE_LOCAL_REFERENCE:
265 continue;
266
267 default:
268 return false;
269 }
270
271 return true;
272 }
273 return false;
274}
275
276static bool acpi_properties_format_valid(const union acpi_object *properties)
277{
278 int i;
279
280 for (i = 0; i < properties->package.count; i++) {
281 const union acpi_object *property;
282
283 property = &properties->package.elements[i];
284 /*
285 * Only two elements allowed, the first one must be a string and
286 * the second one has to satisfy certain conditions.
287 */
288 if (property->package.count != 2
289 || property->package.elements[0].type != ACPI_TYPE_STRING
290 || !acpi_property_value_ok(&property->package.elements[1]))
291 return false;
292 }
293 return true;
294}
295
733e6251
MW
296static void acpi_init_of_compatible(struct acpi_device *adev)
297{
298 const union acpi_object *of_compatible;
733e6251
MW
299 int ret;
300
3a7a2ab8
RW
301 ret = acpi_data_get_property_array(&adev->data, "compatible",
302 ACPI_TYPE_STRING, &of_compatible);
733e6251
MW
303 if (ret) {
304 ret = acpi_dev_get_property(adev, "compatible",
305 ACPI_TYPE_STRING, &of_compatible);
306 if (ret) {
5c53b262
RW
307 if (adev->parent
308 && adev->parent->flags.of_compatible_ok)
309 goto out;
310
733e6251
MW
311 return;
312 }
313 }
314 adev->data.of_compatible = of_compatible;
5c53b262
RW
315
316 out:
317 adev->flags.of_compatible_ok = 1;
733e6251
MW
318}
319
5f5e4890
MW
320static bool acpi_is_property_guid(const guid_t *guid)
321{
322 int i;
323
324 for (i = 0; i < ARRAY_SIZE(prp_guids); i++) {
325 if (guid_equal(guid, &prp_guids[i]))
326 return true;
327 }
328
329 return false;
330}
331
332struct acpi_device_properties *
333acpi_data_add_props(struct acpi_device_data *data, const guid_t *guid,
103e10c6 334 union acpi_object *properties)
5f5e4890
MW
335{
336 struct acpi_device_properties *props;
337
338 props = kzalloc(sizeof(*props), GFP_KERNEL);
339 if (props) {
340 INIT_LIST_HEAD(&props->list);
341 props->guid = guid;
342 props->properties = properties;
343 list_add_tail(&props->list, &data->properties);
344 }
345
346 return props;
347}
348
1d52f109
SA
349static void acpi_nondev_subnode_tag(acpi_handle handle, void *context)
350{
351}
352
353static void acpi_untie_nondev_subnodes(struct acpi_device_data *data)
354{
355 struct acpi_data_node *dn;
356
357 list_for_each_entry(dn, &data->subnodes, sibling) {
358 acpi_detach_data(dn->handle, acpi_nondev_subnode_tag);
359
360 acpi_untie_nondev_subnodes(&dn->data);
361 }
362}
363
364static bool acpi_tie_nondev_subnodes(struct acpi_device_data *data)
365{
366 struct acpi_data_node *dn;
367
368 list_for_each_entry(dn, &data->subnodes, sibling) {
369 acpi_status status;
370 bool ret;
371
372 status = acpi_attach_data(dn->handle, acpi_nondev_subnode_tag, dn);
373 if (ACPI_FAILURE(status)) {
374 acpi_handle_err(dn->handle, "Can't tag data node\n");
375 return false;
376 }
377
378 ret = acpi_tie_nondev_subnodes(&dn->data);
379 if (!ret)
380 return ret;
381 }
382
383 return true;
384}
385
103e10c6
SA
386static void acpi_data_add_buffer_props(acpi_handle handle,
387 struct acpi_device_data *data,
388 union acpi_object *properties)
389{
390 struct acpi_device_properties *props;
391 union acpi_object *package;
392 size_t alloc_size;
393 unsigned int i;
394 u32 *count;
395
396 if (check_mul_overflow((size_t)properties->package.count,
397 sizeof(*package) + sizeof(void *),
398 &alloc_size) ||
399 check_add_overflow(sizeof(*props) + sizeof(*package), alloc_size,
400 &alloc_size)) {
401 acpi_handle_warn(handle,
402 "can't allocate memory for %u buffer props",
403 properties->package.count);
404 return;
405 }
406
407 props = kvzalloc(alloc_size, GFP_KERNEL);
408 if (!props)
409 return;
410
411 props->guid = &buffer_prop_guid;
412 props->bufs = (void *)(props + 1);
413 props->properties = (void *)(props->bufs + properties->package.count);
414
415 /* Outer package */
416 package = props->properties;
417 package->type = ACPI_TYPE_PACKAGE;
418 package->package.elements = package + 1;
419 count = &package->package.count;
420 *count = 0;
421
422 /* Inner packages */
423 package++;
424
425 for (i = 0; i < properties->package.count; i++) {
426 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
427 union acpi_object *property = &properties->package.elements[i];
428 union acpi_object *prop, *obj, *buf_obj;
429 acpi_status status;
430
431 if (property->type != ACPI_TYPE_PACKAGE ||
432 property->package.count != 2) {
433 acpi_handle_warn(handle,
434 "buffer property %u has %u entries\n",
435 i, property->package.count);
436 continue;
437 }
438
439 prop = &property->package.elements[0];
440 obj = &property->package.elements[1];
441
442 if (prop->type != ACPI_TYPE_STRING ||
443 obj->type != ACPI_TYPE_STRING) {
444 acpi_handle_warn(handle,
445 "wrong object types %u and %u\n",
446 prop->type, obj->type);
447 continue;
448 }
449
450 status = acpi_evaluate_object_typed(handle, obj->string.pointer,
451 NULL, &buf,
452 ACPI_TYPE_BUFFER);
453 if (ACPI_FAILURE(status)) {
454 acpi_handle_warn(handle,
455 "can't evaluate \"%*pE\" as buffer\n",
456 obj->string.length,
457 obj->string.pointer);
458 continue;
459 }
460
461 package->type = ACPI_TYPE_PACKAGE;
462 package->package.elements = prop;
463 package->package.count = 2;
464
465 buf_obj = buf.pointer;
466
467 /* Replace the string object with a buffer object */
468 obj->type = ACPI_TYPE_BUFFER;
469 obj->buffer.length = buf_obj->buffer.length;
470 obj->buffer.pointer = buf_obj->buffer.pointer;
471
472 props->bufs[i] = buf.pointer;
473 package++;
474 (*count)++;
475 }
476
477 if (*count)
478 list_add(&props->list, &data->properties);
479 else
480 kvfree(props);
481}
482
483static bool acpi_extract_properties(acpi_handle scope, union acpi_object *desc,
bd8191cc 484 struct acpi_device_data *data)
ffdcd955 485{
ffdcd955
MW
486 int i;
487
ffdcd955 488 if (desc->package.count % 2)
bd8191cc 489 return false;
ffdcd955 490
3689d3d6 491 /* Look for the device properties GUID. */
ffdcd955 492 for (i = 0; i < desc->package.count; i += 2) {
103e10c6
SA
493 const union acpi_object *guid;
494 union acpi_object *properties;
ffdcd955 495
3689d3d6 496 guid = &desc->package.elements[i];
ffdcd955
MW
497 properties = &desc->package.elements[i + 1];
498
499 /*
3689d3d6 500 * The first element must be a GUID and the second one must be
ffdcd955
MW
501 * a package.
502 */
3689d3d6
AS
503 if (guid->type != ACPI_TYPE_BUFFER ||
504 guid->buffer.length != 16 ||
505 properties->type != ACPI_TYPE_PACKAGE)
ffdcd955
MW
506 break;
507
103e10c6
SA
508 if (guid_equal((guid_t *)guid->buffer.pointer,
509 &buffer_prop_guid)) {
510 acpi_data_add_buffer_props(scope, data, properties);
511 continue;
512 }
513
5f5e4890 514 if (!acpi_is_property_guid((guid_t *)guid->buffer.pointer))
ffdcd955
MW
515 continue;
516
517 /*
3689d3d6 518 * We found the matching GUID. Now validate the format of the
ffdcd955
MW
519 * package immediately following it.
520 */
521 if (!acpi_properties_format_valid(properties))
5f5e4890 522 continue;
ffdcd955 523
5f5e4890
MW
524 acpi_data_add_props(data, (const guid_t *)guid->buffer.pointer,
525 properties);
bd8191cc 526 }
733e6251 527
5f5e4890 528 return !list_empty(&data->properties);
bd8191cc 529}
5c53b262 530
bd8191cc
RW
531void acpi_init_properties(struct acpi_device *adev)
532{
533 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER };
534 struct acpi_hardware_id *hwid;
535 acpi_status status;
536 bool acpi_of = false;
537
5f5e4890 538 INIT_LIST_HEAD(&adev->data.properties);
445b0eb0
RW
539 INIT_LIST_HEAD(&adev->data.subnodes);
540
75fc70e0
LW
541 if (!adev->handle)
542 return;
543
bd8191cc
RW
544 /*
545 * Check if ACPI_DT_NAMESPACE_HID is present and inthat case we fill in
546 * Device Tree compatible properties for this device.
547 */
548 list_for_each_entry(hwid, &adev->pnp.ids, list) {
549 if (!strcmp(hwid->id, ACPI_DT_NAMESPACE_HID)) {
550 acpi_of = true;
551 break;
552 }
ffdcd955
MW
553 }
554
bd8191cc
RW
555 status = acpi_evaluate_object_typed(adev->handle, "_DSD", NULL, &buf,
556 ACPI_TYPE_PACKAGE);
557 if (ACPI_FAILURE(status))
558 goto out;
559
103e10c6 560 if (acpi_extract_properties(adev->handle, buf.pointer, &adev->data)) {
bd8191cc
RW
561 adev->data.pointer = buf.pointer;
562 if (acpi_of)
563 acpi_init_of_compatible(adev);
445b0eb0 564 }
dfa672fb
MW
565 if (acpi_enumerate_nondev_subnodes(adev->handle, buf.pointer,
566 &adev->data, acpi_fwnode_handle(adev)))
445b0eb0
RW
567 adev->data.pointer = buf.pointer;
568
1d52f109
SA
569 if (!adev->data.pointer ||
570 !acpi_tie_nondev_subnodes(&adev->data)) {
571 acpi_untie_nondev_subnodes(&adev->data);
bd8191cc
RW
572 acpi_handle_debug(adev->handle, "Invalid _DSD data, skipping\n");
573 ACPI_FREE(buf.pointer);
574 }
5c53b262
RW
575
576 out:
577 if (acpi_of && !adev->flags.of_compatible_ok)
578 acpi_handle_info(adev->handle,
ee892094 579 ACPI_DT_NAMESPACE_HID " requires 'compatible' property\n");
899596e0
LW
580
581 if (!adev->data.pointer)
582 acpi_extract_apple_properties(adev);
ffdcd955
MW
583}
584
3bd561e1
SA
585static void acpi_free_device_properties(struct list_head *list)
586{
587 struct acpi_device_properties *props, *tmp;
588
589 list_for_each_entry_safe(props, tmp, list, list) {
103e10c6
SA
590 u32 i;
591
3bd561e1 592 list_del(&props->list);
103e10c6
SA
593 /* Buffer data properties were separately allocated */
594 if (props->bufs)
595 for (i = 0; i < props->properties->package.count; i++)
596 ACPI_FREE(props->bufs[i]);
597 kvfree(props);
3bd561e1
SA
598 }
599}
600
445b0eb0
RW
601static void acpi_destroy_nondev_subnodes(struct list_head *list)
602{
603 struct acpi_data_node *dn, *next;
604
605 if (list_empty(list))
606 return;
607
608 list_for_each_entry_safe_reverse(dn, next, list, sibling) {
609 acpi_destroy_nondev_subnodes(&dn->data.subnodes);
263b4c1a 610 wait_for_completion(&dn->kobj_done);
445b0eb0
RW
611 list_del(&dn->sibling);
612 ACPI_FREE((void *)dn->data.pointer);
3bd561e1 613 acpi_free_device_properties(&dn->data.properties);
445b0eb0
RW
614 kfree(dn);
615 }
616}
617
ffdcd955
MW
618void acpi_free_properties(struct acpi_device *adev)
619{
1d52f109 620 acpi_untie_nondev_subnodes(&adev->data);
445b0eb0 621 acpi_destroy_nondev_subnodes(&adev->data.subnodes);
ffdcd955 622 ACPI_FREE((void *)adev->data.pointer);
733e6251 623 adev->data.of_compatible = NULL;
ffdcd955 624 adev->data.pointer = NULL;
3bd561e1 625 acpi_free_device_properties(&adev->data.properties);
ffdcd955
MW
626}
627
628/**
3a7a2ab8
RW
629 * acpi_data_get_property - return an ACPI property with given name
630 * @data: ACPI device deta object to get the property from
ffdcd955
MW
631 * @name: Name of the property
632 * @type: Expected property type
633 * @obj: Location to store the property value (if not %NULL)
634 *
635 * Look up a property with @name and store a pointer to the resulting ACPI
636 * object at the location pointed to by @obj if found.
637 *
638 * Callers must not attempt to free the returned objects. These objects will be
3a7a2ab8 639 * freed by the ACPI core automatically during the removal of @data.
ffdcd955
MW
640 *
641 * Return: %0 if property with @name has been found (success),
642 * %-EINVAL if the arguments are invalid,
3c60f114 643 * %-EINVAL if the property doesn't exist,
ffdcd955
MW
644 * %-EPROTO if the property value type doesn't match @type.
645 */
99a85464 646static int acpi_data_get_property(const struct acpi_device_data *data,
3a7a2ab8
RW
647 const char *name, acpi_object_type type,
648 const union acpi_object **obj)
ffdcd955 649{
5f5e4890 650 const struct acpi_device_properties *props;
ffdcd955 651
3a7a2ab8 652 if (!data || !name)
ffdcd955
MW
653 return -EINVAL;
654
5f5e4890 655 if (!data->pointer || list_empty(&data->properties))
3c60f114 656 return -EINVAL;
ffdcd955 657
5f5e4890
MW
658 list_for_each_entry(props, &data->properties, list) {
659 const union acpi_object *properties;
660 unsigned int i;
ffdcd955 661
5f5e4890
MW
662 properties = props->properties;
663 for (i = 0; i < properties->package.count; i++) {
664 const union acpi_object *propname, *propvalue;
665 const union acpi_object *property;
666
667 property = &properties->package.elements[i];
ffdcd955 668
5f5e4890
MW
669 propname = &property->package.elements[0];
670 propvalue = &property->package.elements[1];
ffdcd955 671
5f5e4890
MW
672 if (!strcmp(name, propname->string.pointer)) {
673 if (type != ACPI_TYPE_ANY &&
674 propvalue->type != type)
675 return -EPROTO;
676 if (obj)
677 *obj = propvalue;
ffdcd955 678
5f5e4890
MW
679 return 0;
680 }
ffdcd955
MW
681 }
682 }
3c60f114 683 return -EINVAL;
ffdcd955 684}
3a7a2ab8
RW
685
686/**
687 * acpi_dev_get_property - return an ACPI property with given name.
688 * @adev: ACPI device to get the property from.
689 * @name: Name of the property.
690 * @type: Expected property type.
691 * @obj: Location to store the property value (if not %NULL).
692 */
99a85464 693int acpi_dev_get_property(const struct acpi_device *adev, const char *name,
3a7a2ab8
RW
694 acpi_object_type type, const union acpi_object **obj)
695{
696 return adev ? acpi_data_get_property(&adev->data, name, type, obj) : -EINVAL;
697}
ffdcd955
MW
698EXPORT_SYMBOL_GPL(acpi_dev_get_property);
699
99a85464
SA
700static const struct acpi_device_data *
701acpi_device_data_of_node(const struct fwnode_handle *fwnode)
3a7a2ab8 702{
db3e50f3 703 if (is_acpi_device_node(fwnode)) {
99a85464 704 const struct acpi_device *adev = to_acpi_device_node(fwnode);
3a7a2ab8 705 return &adev->data;
9978f446
AS
706 }
707 if (is_acpi_data_node(fwnode)) {
99a85464 708 const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
3a7a2ab8
RW
709 return &dn->data;
710 }
711 return NULL;
712}
713
ffdcd955 714/**
3a7a2ab8
RW
715 * acpi_node_prop_get - return an ACPI property with given name.
716 * @fwnode: Firmware node to get the property from.
717 * @propname: Name of the property.
718 * @valptr: Location to store a pointer to the property value (if not %NULL).
719 */
99a85464
SA
720int acpi_node_prop_get(const struct fwnode_handle *fwnode,
721 const char *propname, void **valptr)
3a7a2ab8
RW
722{
723 return acpi_data_get_property(acpi_device_data_of_node(fwnode),
724 propname, ACPI_TYPE_ANY,
725 (const union acpi_object **)valptr);
726}
727
728/**
729 * acpi_data_get_property_array - return an ACPI array property with given name
c82ff99e 730 * @data: ACPI data object to get the property from
ffdcd955
MW
731 * @name: Name of the property
732 * @type: Expected type of array elements
733 * @obj: Location to store a pointer to the property value (if not NULL)
734 *
735 * Look up an array property with @name and store a pointer to the resulting
736 * ACPI object at the location pointed to by @obj if found.
737 *
738 * Callers must not attempt to free the returned objects. Those objects will be
3a7a2ab8 739 * freed by the ACPI core automatically during the removal of @data.
ffdcd955
MW
740 *
741 * Return: %0 if array property (package) with @name has been found (success),
742 * %-EINVAL if the arguments are invalid,
3c60f114 743 * %-EINVAL if the property doesn't exist,
ffdcd955
MW
744 * %-EPROTO if the property is not a package or the type of its elements
745 * doesn't match @type.
746 */
99a85464 747static int acpi_data_get_property_array(const struct acpi_device_data *data,
3a7a2ab8
RW
748 const char *name,
749 acpi_object_type type,
750 const union acpi_object **obj)
ffdcd955
MW
751{
752 const union acpi_object *prop;
753 int ret, i;
754
3a7a2ab8 755 ret = acpi_data_get_property(data, name, ACPI_TYPE_PACKAGE, &prop);
ffdcd955
MW
756 if (ret)
757 return ret;
758
759 if (type != ACPI_TYPE_ANY) {
760 /* Check that all elements are of correct type. */
761 for (i = 0; i < prop->package.count; i++)
762 if (prop->package.elements[i].type != type)
763 return -EPROTO;
764 }
765 if (obj)
766 *obj = prop;
767
768 return 0;
769}
ffdcd955 770
4eb0c3bf
SA
771static struct fwnode_handle *
772acpi_fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
773 const char *childname)
774{
775 struct fwnode_handle *child;
ee48cef6
HK
776
777 fwnode_for_each_child_node(fwnode, child) {
778 if (is_acpi_data_node(child)) {
779 if (acpi_data_node_match(child, childname))
780 return child;
781 continue;
782 }
783
cbdd865a
HK
784 if (!strncmp(acpi_device_bid(to_acpi_device_node(child)),
785 childname, ACPI_NAMESEG_SIZE))
4eb0c3bf 786 return child;
ee48cef6 787 }
4eb0c3bf
SA
788
789 return NULL;
790}
791
1aef25d9
SA
792static int acpi_get_ref_args(struct fwnode_reference_args *args,
793 struct fwnode_handle *ref_fwnode,
794 const union acpi_object **element,
795 const union acpi_object *end, size_t num_args)
796{
797 u32 nargs = 0, i;
798
799 /*
800 * Find the referred data extension node under the
801 * referred device node.
802 */
803 for (; *element < end && (*element)->type == ACPI_TYPE_STRING;
804 (*element)++) {
805 const char *child_name = (*element)->string.pointer;
806
807 ref_fwnode = acpi_fwnode_get_named_child_node(ref_fwnode, child_name);
808 if (!ref_fwnode)
809 return -EINVAL;
810 }
811
812 /*
813 * Assume the following integer elements are all args. Stop counting on
814 * the first reference or end of the package arguments. In case of
815 * neither reference, nor integer, return an error, we can't parse it.
816 */
817 for (i = 0; (*element) + i < end && i < num_args; i++) {
818 acpi_object_type type = (*element)[i].type;
819
820 if (type == ACPI_TYPE_LOCAL_REFERENCE)
821 break;
822
823 if (type == ACPI_TYPE_INTEGER)
824 nargs++;
825 else
826 return -EINVAL;
827 }
828
829 if (nargs > NR_FWNODE_REFERENCE_ARGS)
830 return -EINVAL;
831
832 if (args) {
833 args->fwnode = ref_fwnode;
834 args->nargs = nargs;
835 for (i = 0; i < nargs; i++)
836 args->args[i] = (*element)[i].integer.value;
837 }
838
839 (*element) += nargs;
840
841 return 0;
842}
843
ffdcd955 844/**
b60e4ea4
MW
845 * __acpi_node_get_property_reference - returns handle to the referenced object
846 * @fwnode: Firmware node to get the property from
504a3374 847 * @propname: Name of the property
ffdcd955 848 * @index: Index of the reference to return
b60e4ea4 849 * @num_args: Maximum number of arguments after each reference
ffdcd955
MW
850 * @args: Location to store the returned reference with optional arguments
851 *
852 * Find property with @name, verifify that it is a package containing at least
853 * one object reference and if so, store the ACPI device object pointer to the
60ba032e
RW
854 * target object in @args->adev. If the reference includes arguments, store
855 * them in the @args->args[] array.
ffdcd955 856 *
60ba032e
RW
857 * If there's more than one reference in the property value package, @index is
858 * used to select the one to return.
ffdcd955 859 *
b60e4ea4
MW
860 * It is possible to leave holes in the property value set like in the
861 * example below:
862 *
863 * Package () {
864 * "cs-gpios",
865 * Package () {
866 * ^GPIO, 19, 0, 0,
867 * ^GPIO, 20, 0, 0,
868 * 0,
869 * ^GPIO, 21, 0, 0,
870 * }
871 * }
872 *
c343bc2c
SA
873 * Calling this function with index %2 or index %3 return %-ENOENT. If the
874 * property does not contain any more values %-ENOENT is returned. The NULL
875 * entry must be single integer and preferably contain value %0.
b60e4ea4 876 *
ffdcd955
MW
877 * Return: %0 on success, negative error code on failure.
878 */
99a85464 879int __acpi_node_get_property_reference(const struct fwnode_handle *fwnode,
b60e4ea4 880 const char *propname, size_t index, size_t num_args,
977d5ad3 881 struct fwnode_reference_args *args)
ffdcd955
MW
882{
883 const union acpi_object *element, *end;
884 const union acpi_object *obj;
99a85464 885 const struct acpi_device_data *data;
ffdcd955
MW
886 struct acpi_device *device;
887 int ret, idx = 0;
888
b60e4ea4
MW
889 data = acpi_device_data_of_node(fwnode);
890 if (!data)
c343bc2c 891 return -ENOENT;
b60e4ea4 892
504a3374 893 ret = acpi_data_get_property(data, propname, ACPI_TYPE_ANY, &obj);
ffdcd955 894 if (ret)
51858a27 895 return ret == -EINVAL ? -ENOENT : -EINVAL;
ffdcd955 896
88af7bbd
SA
897 switch (obj->type) {
898 case ACPI_TYPE_LOCAL_REFERENCE:
899 /* Plain single reference without arguments. */
60ba032e 900 if (index)
babc92da 901 return -ENOENT;
ffdcd955 902
99ece713
RW
903 device = acpi_fetch_acpi_dev(obj->reference.handle);
904 if (!device)
905 return -EINVAL;
ffdcd955 906
977d5ad3 907 args->fwnode = acpi_fwnode_handle(device);
ffdcd955
MW
908 args->nargs = 0;
909 return 0;
88af7bbd
SA
910 case ACPI_TYPE_PACKAGE:
911 /*
912 * If it is not a single reference, then it is a package of
913 * references followed by number of ints as follows:
914 *
915 * Package () { REF, INT, REF, INT, INT }
916 *
917 * The index argument is then used to determine which reference
918 * the caller wants (along with the arguments).
919 */
920 break;
921 default:
922 return -EINVAL;
ffdcd955
MW
923 }
924
51858a27
SA
925 if (index >= obj->package.count)
926 return -ENOENT;
ffdcd955
MW
927
928 element = obj->package.elements;
929 end = element + obj->package.count;
930
931 while (element < end) {
88af7bbd
SA
932 switch (element->type) {
933 case ACPI_TYPE_LOCAL_REFERENCE:
99ece713
RW
934 device = acpi_fetch_acpi_dev(element->reference.handle);
935 if (!device)
c343bc2c 936 return -EINVAL;
b60e4ea4 937
b60e4ea4
MW
938 element++;
939
1aef25d9
SA
940 ret = acpi_get_ref_args(idx == index ? args : NULL,
941 acpi_fwnode_handle(device),
942 &element, end, num_args);
943 if (ret < 0)
944 return ret;
ffdcd955 945
1aef25d9 946 if (idx == index)
b60e4ea4 947 return 0;
b60e4ea4 948
88af7bbd
SA
949 break;
950 case ACPI_TYPE_INTEGER:
b60e4ea4
MW
951 if (idx == index)
952 return -ENOENT;
953 element++;
88af7bbd
SA
954 break;
955 default:
c343bc2c 956 return -EINVAL;
ffdcd955
MW
957 }
958
b60e4ea4 959 idx++;
ffdcd955
MW
960 }
961
c343bc2c 962 return -ENOENT;
504a3374 963}
b60e4ea4 964EXPORT_SYMBOL_GPL(__acpi_node_get_property_reference);
b31384fa 965
99a85464 966static int acpi_data_prop_read_single(const struct acpi_device_data *data,
3a7a2ab8
RW
967 const char *propname,
968 enum dev_prop_type proptype, void *val)
b31384fa
RW
969{
970 const union acpi_object *obj;
971 int ret;
972
b31384fa 973 if (proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64) {
3a7a2ab8 974 ret = acpi_data_get_property(data, propname, ACPI_TYPE_INTEGER, &obj);
b31384fa
RW
975 if (ret)
976 return ret;
977
978 switch (proptype) {
979 case DEV_PROP_U8:
980 if (obj->integer.value > U8_MAX)
981 return -EOVERFLOW;
e1e6bd29
RW
982
983 if (val)
984 *(u8 *)val = obj->integer.value;
985
b31384fa
RW
986 break;
987 case DEV_PROP_U16:
988 if (obj->integer.value > U16_MAX)
989 return -EOVERFLOW;
e1e6bd29
RW
990
991 if (val)
992 *(u16 *)val = obj->integer.value;
993
b31384fa
RW
994 break;
995 case DEV_PROP_U32:
996 if (obj->integer.value > U32_MAX)
997 return -EOVERFLOW;
e1e6bd29
RW
998
999 if (val)
1000 *(u32 *)val = obj->integer.value;
1001
b31384fa
RW
1002 break;
1003 default:
e1e6bd29
RW
1004 if (val)
1005 *(u64 *)val = obj->integer.value;
1006
b31384fa
RW
1007 break;
1008 }
e1e6bd29
RW
1009
1010 if (!val)
1011 return 1;
b31384fa 1012 } else if (proptype == DEV_PROP_STRING) {
3a7a2ab8 1013 ret = acpi_data_get_property(data, propname, ACPI_TYPE_STRING, &obj);
b31384fa
RW
1014 if (ret)
1015 return ret;
1016
e1e6bd29
RW
1017 if (val)
1018 *(char **)val = obj->string.pointer;
b0b027ce
SA
1019
1020 return 1;
b31384fa
RW
1021 } else {
1022 ret = -EINVAL;
1023 }
1024 return ret;
1025}
1026
92304413
SA
1027#define acpi_copy_property_array_uint(items, val, nval) \
1028 ({ \
1029 typeof(items) __items = items; \
1030 typeof(val) __val = val; \
1031 typeof(nval) __nval = nval; \
1032 size_t i; \
1033 int ret = 0; \
1034 \
1035 for (i = 0; i < __nval; i++) { \
369af6bf
SA
1036 if (__items->type == ACPI_TYPE_BUFFER) { \
1037 __val[i] = __items->buffer.pointer[i]; \
1038 continue; \
1039 } \
92304413
SA
1040 if (__items[i].type != ACPI_TYPE_INTEGER) { \
1041 ret = -EPROTO; \
1042 break; \
1043 } \
1044 if (__items[i].integer.value > _Generic(__val, \
1045 u8: U8_MAX, \
1046 u16: U16_MAX, \
1047 u32: U32_MAX, \
1048 u64: U64_MAX, \
1049 default: 0U)) { \
1050 ret = -EOVERFLOW; \
1051 break; \
1052 } \
1053 \
1054 __val[i] = __items[i].integer.value; \
1055 } \
1056 ret; \
1057 })
b31384fa
RW
1058
1059static int acpi_copy_property_array_string(const union acpi_object *items,
1060 char **val, size_t nval)
1061{
1062 int i;
1063
1064 for (i = 0; i < nval; i++) {
1065 if (items[i].type != ACPI_TYPE_STRING)
1066 return -EPROTO;
1067
1068 val[i] = items[i].string.pointer;
1069 }
b0b027ce 1070 return nval;
b31384fa
RW
1071}
1072
99a85464 1073static int acpi_data_prop_read(const struct acpi_device_data *data,
3a7a2ab8
RW
1074 const char *propname,
1075 enum dev_prop_type proptype,
1076 void *val, size_t nval)
b31384fa
RW
1077{
1078 const union acpi_object *obj;
1079 const union acpi_object *items;
1080 int ret;
1081
e1e6bd29 1082 if (nval == 1 || !val) {
3a7a2ab8 1083 ret = acpi_data_prop_read_single(data, propname, proptype, val);
e1e6bd29
RW
1084 /*
1085 * The overflow error means that the property is there and it is
1086 * single-value, but its type does not match, so return.
1087 */
1088 if (ret >= 0 || ret == -EOVERFLOW)
b31384fa 1089 return ret;
e1e6bd29
RW
1090
1091 /*
1092 * Reading this property as a single-value one failed, but its
1093 * value may still be represented as one-element array, so
1094 * continue.
1095 */
b31384fa
RW
1096 }
1097
3a7a2ab8 1098 ret = acpi_data_get_property_array(data, propname, ACPI_TYPE_ANY, &obj);
369af6bf
SA
1099 if (ret && proptype >= DEV_PROP_U8 && proptype <= DEV_PROP_U64)
1100 ret = acpi_data_get_property(data, propname, ACPI_TYPE_BUFFER,
1101 &obj);
b31384fa
RW
1102 if (ret)
1103 return ret;
1104
369af6bf
SA
1105 if (!val) {
1106 if (obj->type == ACPI_TYPE_BUFFER)
1107 return obj->buffer.length;
1108
b31384fa 1109 return obj->package.count;
369af6bf 1110 }
b31384fa 1111
369af6bf
SA
1112 switch (proptype) {
1113 case DEV_PROP_STRING:
1114 break;
1115 case DEV_PROP_U8 ... DEV_PROP_U64:
1116 if (obj->type == ACPI_TYPE_BUFFER) {
1117 if (nval > obj->buffer.length)
1118 return -EOVERFLOW;
1119 break;
1120 }
1121 fallthrough;
1122 default:
1123 if (nval > obj->package.count)
1124 return -EOVERFLOW;
1125 break;
1126 }
9978f446 1127 if (nval == 0)
7dc59dc9 1128 return -EINVAL;
b31384fa 1129
369af6bf
SA
1130 if (obj->type != ACPI_TYPE_BUFFER)
1131 items = obj->package.elements;
1132 else
1133 items = obj;
7dc59dc9 1134
b31384fa
RW
1135 switch (proptype) {
1136 case DEV_PROP_U8:
92304413 1137 ret = acpi_copy_property_array_uint(items, (u8 *)val, nval);
b31384fa
RW
1138 break;
1139 case DEV_PROP_U16:
92304413 1140 ret = acpi_copy_property_array_uint(items, (u16 *)val, nval);
b31384fa
RW
1141 break;
1142 case DEV_PROP_U32:
92304413 1143 ret = acpi_copy_property_array_uint(items, (u32 *)val, nval);
b31384fa
RW
1144 break;
1145 case DEV_PROP_U64:
92304413 1146 ret = acpi_copy_property_array_uint(items, (u64 *)val, nval);
b31384fa
RW
1147 break;
1148 case DEV_PROP_STRING:
b0b027ce
SA
1149 ret = acpi_copy_property_array_string(
1150 items, (char **)val,
1151 min_t(u32, nval, obj->package.count));
b31384fa
RW
1152 break;
1153 default:
1154 ret = -EINVAL;
1155 break;
1156 }
1157 return ret;
1158}
3a7a2ab8 1159
3a7a2ab8
RW
1160/**
1161 * acpi_node_prop_read - retrieve the value of an ACPI property with given name.
1162 * @fwnode: Firmware node to get the property from.
1163 * @propname: Name of the property.
1164 * @proptype: Expected property type.
1165 * @val: Location to store the property value (if not %NULL).
1166 * @nval: Size of the array pointed to by @val.
1167 *
1168 * If @val is %NULL, return the number of array elements comprising the value
1169 * of the property. Otherwise, read at most @nval values to the array at the
1170 * location pointed to by @val.
1171 */
325aa816
AS
1172static int acpi_node_prop_read(const struct fwnode_handle *fwnode,
1173 const char *propname, enum dev_prop_type proptype,
1174 void *val, size_t nval)
3a7a2ab8
RW
1175{
1176 return acpi_data_prop_read(acpi_device_data_of_node(fwnode),
1177 propname, proptype, val, nval);
1178}
504a3374
RW
1179
1180/**
34055190
MW
1181 * acpi_get_next_subnode - Return the next child node handle for a fwnode
1182 * @fwnode: Firmware node to find the next child node for.
504a3374
RW
1183 * @child: Handle to one of the device's child nodes or a null handle.
1184 */
37ba983c 1185struct fwnode_handle *acpi_get_next_subnode(const struct fwnode_handle *fwnode,
504a3374
RW
1186 struct fwnode_handle *child)
1187{
01c1da28 1188 const struct acpi_device *adev = to_acpi_device_node(fwnode);
01c1da28
SA
1189 const struct list_head *head;
1190 struct list_head *next;
504a3374 1191
9978f446 1192 if ((!child || is_acpi_device_node(child)) && adev) {
0c0bceb7
SA
1193 struct acpi_device *child_adev;
1194
9978f446 1195 head = &adev->children;
504a3374
RW
1196 if (list_empty(head))
1197 goto nondev;
1198
1199 if (child) {
0c0bceb7
SA
1200 adev = to_acpi_device_node(child);
1201 next = adev->node.next;
504a3374
RW
1202 if (next == head) {
1203 child = NULL;
1204 goto nondev;
1205 }
01c1da28 1206 child_adev = list_entry(next, struct acpi_device, node);
504a3374 1207 } else {
01c1da28
SA
1208 child_adev = list_first_entry(head, struct acpi_device,
1209 node);
504a3374 1210 }
01c1da28 1211 return acpi_fwnode_handle(child_adev);
504a3374
RW
1212 }
1213
1214 nondev:
db3e50f3 1215 if (!child || is_acpi_data_node(child)) {
01c1da28 1216 const struct acpi_data_node *data = to_acpi_data_node(fwnode);
504a3374
RW
1217 struct acpi_data_node *dn;
1218
23583f77
PLB
1219 /*
1220 * We can have a combination of device and data nodes, e.g. with
1221 * hierarchical _DSD properties. Make sure the adev pointer is
1222 * restored before going through data nodes, otherwise we will
1223 * be looking for data_nodes below the last device found instead
1224 * of the common fwnode shared by device_nodes and data_nodes.
1225 */
1226 adev = to_acpi_device_node(fwnode);
0c0bceb7
SA
1227 if (adev)
1228 head = &adev->data.subnodes;
34055190
MW
1229 else if (data)
1230 head = &data->data.subnodes;
1231 else
1232 return NULL;
1233
504a3374
RW
1234 if (list_empty(head))
1235 return NULL;
1236
1237 if (child) {
1238 dn = to_acpi_data_node(child);
1239 next = dn->sibling.next;
1240 if (next == head)
1241 return NULL;
1242
1243 dn = list_entry(next, struct acpi_data_node, sibling);
1244 } else {
1245 dn = list_first_entry(head, struct acpi_data_node, sibling);
1246 }
1247 return &dn->fwnode;
1248 }
1249 return NULL;
1250}
dfa672fb
MW
1251
1252/**
1253 * acpi_node_get_parent - Return parent fwnode of this fwnode
1254 * @fwnode: Firmware node whose parent to get
1255 *
1256 * Returns parent node of an ACPI device or data firmware node or %NULL if
1257 * not available.
1258 */
985e9ece
SA
1259static struct fwnode_handle *
1260acpi_node_get_parent(const struct fwnode_handle *fwnode)
dfa672fb
MW
1261{
1262 if (is_acpi_data_node(fwnode)) {
1263 /* All data nodes have parent pointer so just return that */
1264 return to_acpi_data_node(fwnode)->parent;
9978f446
AS
1265 }
1266 if (is_acpi_device_node(fwnode)) {
9054fc6d 1267 struct device *dev = to_acpi_device_node(fwnode)->dev.parent;
dfa672fb 1268
9054fc6d
SA
1269 if (dev)
1270 return acpi_fwnode_handle(to_acpi_device(dev));
dfa672fb
MW
1271 }
1272
1273 return NULL;
1274}
79389a83 1275
18f1e58d
SA
1276/*
1277 * Return true if the node is an ACPI graph node. Called on either ports
1278 * or endpoints.
1279 */
1280static bool is_acpi_graph_node(struct fwnode_handle *fwnode,
1281 const char *str)
1282{
1283 unsigned int len = strlen(str);
1284 const char *name;
1285
1286 if (!len || !is_acpi_data_node(fwnode))
1287 return false;
1288
1289 name = to_acpi_data_node(fwnode)->name;
1290
1291 return (fwnode_property_present(fwnode, "reg") &&
1292 !strncmp(name, str, len) && name[len] == '@') ||
1293 fwnode_property_present(fwnode, str);
1294}
1295
79389a83
MW
1296/**
1297 * acpi_graph_get_next_endpoint - Get next endpoint ACPI firmware node
1298 * @fwnode: Pointer to the parent firmware node
1299 * @prev: Previous endpoint node or %NULL to get the first
1300 *
1301 * Looks up next endpoint ACPI firmware node below a given @fwnode. Returns
0ef74786
SA
1302 * %NULL if there is no next endpoint or in case of error. In case of success
1303 * the next endpoint is returned.
79389a83 1304 */
0ef74786 1305static struct fwnode_handle *acpi_graph_get_next_endpoint(
37ba983c 1306 const struct fwnode_handle *fwnode, struct fwnode_handle *prev)
79389a83
MW
1307{
1308 struct fwnode_handle *port = NULL;
1309 struct fwnode_handle *endpoint;
1310
1311 if (!prev) {
1312 do {
1313 port = fwnode_get_next_child_node(fwnode, port);
18f1e58d
SA
1314 /*
1315 * The names of the port nodes begin with "port@"
1316 * followed by the number of the port node and they also
1317 * have a "reg" property that also has the number of the
1318 * port node. For compatibility reasons a node is also
1319 * recognised as a port node from the "port" property.
1320 */
1321 if (is_acpi_graph_node(port, "port"))
79389a83
MW
1322 break;
1323 } while (port);
1324 } else {
1325 port = fwnode_get_parent(prev);
1326 }
1327
1328 if (!port)
1329 return NULL;
1330
1331 endpoint = fwnode_get_next_child_node(port, prev);
1332 while (!endpoint) {
1333 port = fwnode_get_next_child_node(fwnode, port);
1334 if (!port)
1335 break;
18f1e58d 1336 if (is_acpi_graph_node(port, "port"))
79389a83
MW
1337 endpoint = fwnode_get_next_child_node(port, NULL);
1338 }
1339
18f1e58d
SA
1340 /*
1341 * The names of the endpoint nodes begin with "endpoint@" followed by
1342 * the number of the endpoint node and they also have a "reg" property
1343 * that also has the number of the endpoint node. For compatibility
1344 * reasons a node is also recognised as an endpoint node from the
1345 * "endpoint" property.
1346 */
1347 if (!is_acpi_graph_node(endpoint, "endpoint"))
0ef74786 1348 return NULL;
79389a83
MW
1349
1350 return endpoint;
1351}
1352
1353/**
1354 * acpi_graph_get_child_prop_value - Return a child with a given property value
1355 * @fwnode: device fwnode
1356 * @prop_name: The name of the property to look for
1357 * @val: the desired property value
1358 *
1359 * Return the port node corresponding to a given port number. Returns
1360 * the child node on success, NULL otherwise.
1361 */
1362static struct fwnode_handle *acpi_graph_get_child_prop_value(
37ba983c
SA
1363 const struct fwnode_handle *fwnode, const char *prop_name,
1364 unsigned int val)
79389a83
MW
1365{
1366 struct fwnode_handle *child;
1367
1368 fwnode_for_each_child_node(fwnode, child) {
1369 u32 nr;
1370
b5212f57 1371 if (fwnode_property_read_u32(child, prop_name, &nr))
79389a83
MW
1372 continue;
1373
1374 if (val == nr)
1375 return child;
1376 }
1377
1378 return NULL;
1379}
1380
1381
1382/**
3a2650a8 1383 * acpi_graph_get_remote_endpoint - Parses and returns remote end of an endpoint
1de359d8 1384 * @__fwnode: Endpoint firmware node pointing to a remote device
79389a83 1385 *
0ef74786 1386 * Returns the remote endpoint corresponding to @__fwnode. NULL on error.
79389a83 1387 */
0ef74786
SA
1388static struct fwnode_handle *
1389acpi_graph_get_remote_endpoint(const struct fwnode_handle *__fwnode)
79389a83 1390{
37ba983c 1391 struct fwnode_handle *fwnode;
79389a83 1392 unsigned int port_nr, endpoint_nr;
977d5ad3 1393 struct fwnode_reference_args args;
79389a83
MW
1394 int ret;
1395
1396 memset(&args, 0, sizeof(args));
37ba983c 1397 ret = acpi_node_get_property_reference(__fwnode, "remote-endpoint", 0,
79389a83
MW
1398 &args);
1399 if (ret)
0ef74786 1400 return NULL;
79389a83 1401
6561eb3d 1402 /* Direct endpoint reference? */
977d5ad3 1403 if (!is_acpi_device_node(args.fwnode))
6561eb3d 1404 return args.nargs ? NULL : args.fwnode;
977d5ad3 1405
79389a83
MW
1406 /*
1407 * Always require two arguments with the reference: port and
1408 * endpoint indices.
1409 */
1410 if (args.nargs != 2)
0ef74786 1411 return NULL;
79389a83 1412
977d5ad3 1413 fwnode = args.fwnode;
79389a83
MW
1414 port_nr = args.args[0];
1415 endpoint_nr = args.args[1];
1416
79389a83 1417 fwnode = acpi_graph_get_child_prop_value(fwnode, "port", port_nr);
79389a83 1418
18f1e58d 1419 return acpi_graph_get_child_prop_value(fwnode, "endpoint", endpoint_nr);
79389a83 1420}
3708184a 1421
37ba983c 1422static bool acpi_fwnode_device_is_available(const struct fwnode_handle *fwnode)
2294b3af
SA
1423{
1424 if (!is_acpi_device_node(fwnode))
1425 return false;
1426
1427 return acpi_device_is_present(to_acpi_device_node(fwnode));
1428}
1429
55dcbc05
SA
1430static const void *
1431acpi_fwnode_device_get_match_data(const struct fwnode_handle *fwnode,
1432 const struct device *dev)
1433{
1434 return acpi_device_get_match_data(dev);
1435}
1436
8c756a0a
SA
1437static bool acpi_fwnode_device_dma_supported(const struct fwnode_handle *fwnode)
1438{
1439 return acpi_dma_supported(to_acpi_device_node(fwnode));
1440}
1441
1442static enum dev_dma_attr
1443acpi_fwnode_device_get_dma_attr(const struct fwnode_handle *fwnode)
1444{
1445 return acpi_get_dma_attr(to_acpi_device_node(fwnode));
1446}
1447
37ba983c 1448static bool acpi_fwnode_property_present(const struct fwnode_handle *fwnode,
3708184a
SA
1449 const char *propname)
1450{
1451 return !acpi_node_prop_get(fwnode, propname, NULL);
1452}
1453
37ba983c
SA
1454static int
1455acpi_fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
1456 const char *propname,
1457 unsigned int elem_size, void *val,
1458 size_t nval)
3708184a
SA
1459{
1460 enum dev_prop_type type;
1461
1462 switch (elem_size) {
1463 case sizeof(u8):
1464 type = DEV_PROP_U8;
1465 break;
1466 case sizeof(u16):
1467 type = DEV_PROP_U16;
1468 break;
1469 case sizeof(u32):
1470 type = DEV_PROP_U32;
1471 break;
1472 case sizeof(u64):
1473 type = DEV_PROP_U64;
1474 break;
1475 default:
1476 return -ENXIO;
1477 }
1478
1479 return acpi_node_prop_read(fwnode, propname, type, val, nval);
1480}
1481
37ba983c
SA
1482static int
1483acpi_fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
1484 const char *propname, const char **val,
1485 size_t nval)
3708184a
SA
1486{
1487 return acpi_node_prop_read(fwnode, propname, DEV_PROP_STRING,
1488 val, nval);
1489}
1490
3e3119d3
SA
1491static int
1492acpi_fwnode_get_reference_args(const struct fwnode_handle *fwnode,
1493 const char *prop, const char *nargs_prop,
1494 unsigned int args_count, unsigned int index,
1495 struct fwnode_reference_args *args)
1496{
977d5ad3
SA
1497 return __acpi_node_get_property_reference(fwnode, prop, index,
1498 args_count, args);
3e3119d3
SA
1499}
1500
bc0500c1
SA
1501static const char *acpi_fwnode_get_name(const struct fwnode_handle *fwnode)
1502{
1503 const struct acpi_device *adev;
1504 struct fwnode_handle *parent;
1505
1506 /* Is this the root node? */
1507 parent = fwnode_get_parent(fwnode);
1508 if (!parent)
1509 return "\\";
1510
1511 fwnode_handle_put(parent);
1512
1513 if (is_acpi_data_node(fwnode)) {
1514 const struct acpi_data_node *dn = to_acpi_data_node(fwnode);
1515
1516 return dn->name;
1517 }
1518
1519 adev = to_acpi_device_node(fwnode);
1520 if (WARN_ON(!adev))
1521 return NULL;
1522
1523 return acpi_device_bid(adev);
1524}
1525
e7e242bc
SA
1526static const char *
1527acpi_fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
1528{
1529 struct fwnode_handle *parent;
1530
1531 /* Is this the root node? */
1532 parent = fwnode_get_parent(fwnode);
1533 if (!parent)
1534 return "";
1535
1536 /* Is this 2nd node from the root? */
1537 parent = fwnode_get_next_parent(parent);
1538 if (!parent)
1539 return "";
1540
1541 fwnode_handle_put(parent);
1542
1543 /* ACPI device or data node. */
1544 return ".";
1545}
1546
37ba983c
SA
1547static struct fwnode_handle *
1548acpi_fwnode_get_parent(struct fwnode_handle *fwnode)
1549{
1550 return acpi_node_get_parent(fwnode);
1551}
1552
1553static int acpi_fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
3b27d00e
SA
1554 struct fwnode_endpoint *endpoint)
1555{
1556 struct fwnode_handle *port_fwnode = fwnode_get_parent(fwnode);
1557
1558 endpoint->local_fwnode = fwnode;
1559
18f1e58d
SA
1560 if (fwnode_property_read_u32(port_fwnode, "reg", &endpoint->port))
1561 fwnode_property_read_u32(port_fwnode, "port", &endpoint->port);
1562 if (fwnode_property_read_u32(fwnode, "reg", &endpoint->id))
1563 fwnode_property_read_u32(fwnode, "endpoint", &endpoint->id);
3b27d00e
SA
1564
1565 return 0;
1566}
1567
99c63707
SA
1568static int acpi_fwnode_irq_get(const struct fwnode_handle *fwnode,
1569 unsigned int index)
1570{
1571 struct resource res;
1572 int ret;
1573
1574 ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
1575 if (ret)
1576 return ret;
1577
1578 return res.start;
1579}
1580
db3e50f3
SA
1581#define DECLARE_ACPI_FWNODE_OPS(ops) \
1582 const struct fwnode_operations ops = { \
1583 .device_is_available = acpi_fwnode_device_is_available, \
146b4dbb 1584 .device_get_match_data = acpi_fwnode_device_get_match_data, \
8c756a0a
SA
1585 .device_dma_supported = \
1586 acpi_fwnode_device_dma_supported, \
1587 .device_get_dma_attr = acpi_fwnode_device_get_dma_attr, \
db3e50f3
SA
1588 .property_present = acpi_fwnode_property_present, \
1589 .property_read_int_array = \
1590 acpi_fwnode_property_read_int_array, \
1591 .property_read_string_array = \
1592 acpi_fwnode_property_read_string_array, \
1593 .get_parent = acpi_node_get_parent, \
1594 .get_next_child_node = acpi_get_next_subnode, \
1595 .get_named_child_node = acpi_fwnode_get_named_child_node, \
bc0500c1 1596 .get_name = acpi_fwnode_get_name, \
e7e242bc 1597 .get_name_prefix = acpi_fwnode_get_name_prefix, \
3e3119d3 1598 .get_reference_args = acpi_fwnode_get_reference_args, \
db3e50f3 1599 .graph_get_next_endpoint = \
0ef74786 1600 acpi_graph_get_next_endpoint, \
db3e50f3 1601 .graph_get_remote_endpoint = \
0ef74786 1602 acpi_graph_get_remote_endpoint, \
37ba983c 1603 .graph_get_port_parent = acpi_fwnode_get_parent, \
db3e50f3 1604 .graph_parse_endpoint = acpi_fwnode_graph_parse_endpoint, \
99c63707 1605 .irq_get = acpi_fwnode_irq_get, \
db3e50f3
SA
1606 }; \
1607 EXPORT_SYMBOL_GPL(ops)
1608
1609DECLARE_ACPI_FWNODE_OPS(acpi_device_fwnode_ops);
1610DECLARE_ACPI_FWNODE_OPS(acpi_data_fwnode_ops);
1611const struct fwnode_operations acpi_static_fwnode_ops;
9e987b70
JH
1612
1613bool is_acpi_device_node(const struct fwnode_handle *fwnode)
1614{
1615 return !IS_ERR_OR_NULL(fwnode) &&
1616 fwnode->ops == &acpi_device_fwnode_ops;
1617}
1618EXPORT_SYMBOL(is_acpi_device_node);
1619
1620bool is_acpi_data_node(const struct fwnode_handle *fwnode)
1621{
1622 return !IS_ERR_OR_NULL(fwnode) && fwnode->ops == &acpi_data_fwnode_ops;
1623}
1624EXPORT_SYMBOL(is_acpi_data_node);