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