1
2
3
4
5
6
7
8
9
10#include <linux/acpi.h>
11#include <linux/export.h>
12#include <linux/kernel.h>
13#include <linux/of.h>
14#include <linux/of_address.h>
15#include <linux/of_graph.h>
16#include <linux/of_irq.h>
17#include <linux/property.h>
18#include <linux/phy.h>
19
20struct fwnode_handle *dev_fwnode(struct device *dev)
21{
22 return IS_ENABLED(CONFIG_OF) && dev->of_node ?
23 of_fwnode_handle(dev->of_node) : dev->fwnode;
24}
25EXPORT_SYMBOL_GPL(dev_fwnode);
26
27
28
29
30
31
32
33
34bool device_property_present(struct device *dev, const char *propname)
35{
36 return fwnode_property_present(dev_fwnode(dev), propname);
37}
38EXPORT_SYMBOL_GPL(device_property_present);
39
40
41
42
43
44
45bool fwnode_property_present(const struct fwnode_handle *fwnode,
46 const char *propname)
47{
48 bool ret;
49
50 ret = fwnode_call_bool_op(fwnode, property_present, propname);
51 if (ret == false && !IS_ERR_OR_NULL(fwnode) &&
52 !IS_ERR_OR_NULL(fwnode->secondary))
53 ret = fwnode_call_bool_op(fwnode->secondary, property_present,
54 propname);
55 return ret;
56}
57EXPORT_SYMBOL_GPL(fwnode_property_present);
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77int device_property_read_u8_array(struct device *dev, const char *propname,
78 u8 *val, size_t nval)
79{
80 return fwnode_property_read_u8_array(dev_fwnode(dev), propname, val, nval);
81}
82EXPORT_SYMBOL_GPL(device_property_read_u8_array);
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102int device_property_read_u16_array(struct device *dev, const char *propname,
103 u16 *val, size_t nval)
104{
105 return fwnode_property_read_u16_array(dev_fwnode(dev), propname, val, nval);
106}
107EXPORT_SYMBOL_GPL(device_property_read_u16_array);
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127int device_property_read_u32_array(struct device *dev, const char *propname,
128 u32 *val, size_t nval)
129{
130 return fwnode_property_read_u32_array(dev_fwnode(dev), propname, val, nval);
131}
132EXPORT_SYMBOL_GPL(device_property_read_u32_array);
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152int device_property_read_u64_array(struct device *dev, const char *propname,
153 u64 *val, size_t nval)
154{
155 return fwnode_property_read_u64_array(dev_fwnode(dev), propname, val, nval);
156}
157EXPORT_SYMBOL_GPL(device_property_read_u64_array);
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177int device_property_read_string_array(struct device *dev, const char *propname,
178 const char **val, size_t nval)
179{
180 return fwnode_property_read_string_array(dev_fwnode(dev), propname, val, nval);
181}
182EXPORT_SYMBOL_GPL(device_property_read_string_array);
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199int device_property_read_string(struct device *dev, const char *propname,
200 const char **val)
201{
202 return fwnode_property_read_string(dev_fwnode(dev), propname, val);
203}
204EXPORT_SYMBOL_GPL(device_property_read_string);
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221int device_property_match_string(struct device *dev, const char *propname,
222 const char *string)
223{
224 return fwnode_property_match_string(dev_fwnode(dev), propname, string);
225}
226EXPORT_SYMBOL_GPL(device_property_match_string);
227
228static int fwnode_property_read_int_array(const struct fwnode_handle *fwnode,
229 const char *propname,
230 unsigned int elem_size, void *val,
231 size_t nval)
232{
233 int ret;
234
235 ret = fwnode_call_int_op(fwnode, property_read_int_array, propname,
236 elem_size, val, nval);
237 if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
238 !IS_ERR_OR_NULL(fwnode->secondary))
239 ret = fwnode_call_int_op(
240 fwnode->secondary, property_read_int_array, propname,
241 elem_size, val, nval);
242
243 return ret;
244}
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264int fwnode_property_read_u8_array(const struct fwnode_handle *fwnode,
265 const char *propname, u8 *val, size_t nval)
266{
267 return fwnode_property_read_int_array(fwnode, propname, sizeof(u8),
268 val, nval);
269}
270EXPORT_SYMBOL_GPL(fwnode_property_read_u8_array);
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290int fwnode_property_read_u16_array(const struct fwnode_handle *fwnode,
291 const char *propname, u16 *val, size_t nval)
292{
293 return fwnode_property_read_int_array(fwnode, propname, sizeof(u16),
294 val, nval);
295}
296EXPORT_SYMBOL_GPL(fwnode_property_read_u16_array);
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316int fwnode_property_read_u32_array(const struct fwnode_handle *fwnode,
317 const char *propname, u32 *val, size_t nval)
318{
319 return fwnode_property_read_int_array(fwnode, propname, sizeof(u32),
320 val, nval);
321}
322EXPORT_SYMBOL_GPL(fwnode_property_read_u32_array);
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342int fwnode_property_read_u64_array(const struct fwnode_handle *fwnode,
343 const char *propname, u64 *val, size_t nval)
344{
345 return fwnode_property_read_int_array(fwnode, propname, sizeof(u64),
346 val, nval);
347}
348EXPORT_SYMBOL_GPL(fwnode_property_read_u64_array);
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368int fwnode_property_read_string_array(const struct fwnode_handle *fwnode,
369 const char *propname, const char **val,
370 size_t nval)
371{
372 int ret;
373
374 ret = fwnode_call_int_op(fwnode, property_read_string_array, propname,
375 val, nval);
376 if (ret == -EINVAL && !IS_ERR_OR_NULL(fwnode) &&
377 !IS_ERR_OR_NULL(fwnode->secondary))
378 ret = fwnode_call_int_op(fwnode->secondary,
379 property_read_string_array, propname,
380 val, nval);
381 return ret;
382}
383EXPORT_SYMBOL_GPL(fwnode_property_read_string_array);
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400int fwnode_property_read_string(const struct fwnode_handle *fwnode,
401 const char *propname, const char **val)
402{
403 int ret = fwnode_property_read_string_array(fwnode, propname, val, 1);
404
405 return ret < 0 ? ret : 0;
406}
407EXPORT_SYMBOL_GPL(fwnode_property_read_string);
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424int fwnode_property_match_string(const struct fwnode_handle *fwnode,
425 const char *propname, const char *string)
426{
427 const char **values;
428 int nval, ret;
429
430 nval = fwnode_property_read_string_array(fwnode, propname, NULL, 0);
431 if (nval < 0)
432 return nval;
433
434 if (nval == 0)
435 return -ENODATA;
436
437 values = kcalloc(nval, sizeof(*values), GFP_KERNEL);
438 if (!values)
439 return -ENOMEM;
440
441 ret = fwnode_property_read_string_array(fwnode, propname, values, nval);
442 if (ret < 0)
443 goto out;
444
445 ret = match_string(values, nval, string);
446 if (ret < 0)
447 ret = -ENODATA;
448out:
449 kfree(values);
450 return ret;
451}
452EXPORT_SYMBOL_GPL(fwnode_property_match_string);
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476int fwnode_property_get_reference_args(const struct fwnode_handle *fwnode,
477 const char *prop, const char *nargs_prop,
478 unsigned int nargs, unsigned int index,
479 struct fwnode_reference_args *args)
480{
481 int ret;
482
483 ret = fwnode_call_int_op(fwnode, get_reference_args, prop, nargs_prop,
484 nargs, index, args);
485
486 if (ret < 0 && !IS_ERR_OR_NULL(fwnode) &&
487 !IS_ERR_OR_NULL(fwnode->secondary))
488 ret = fwnode_call_int_op(fwnode->secondary, get_reference_args,
489 prop, nargs_prop, nargs, index, args);
490
491 return ret;
492}
493EXPORT_SYMBOL_GPL(fwnode_property_get_reference_args);
494
495
496
497
498
499
500
501
502
503
504
505
506struct fwnode_handle *fwnode_find_reference(const struct fwnode_handle *fwnode,
507 const char *name,
508 unsigned int index)
509{
510 struct fwnode_reference_args args;
511 int ret;
512
513 ret = fwnode_property_get_reference_args(fwnode, name, NULL, 0, index,
514 &args);
515 return ret ? ERR_PTR(ret) : args.fwnode;
516}
517EXPORT_SYMBOL_GPL(fwnode_find_reference);
518
519
520
521
522
523
524
525const char *fwnode_get_name(const struct fwnode_handle *fwnode)
526{
527 return fwnode_call_ptr_op(fwnode, get_name);
528}
529EXPORT_SYMBOL_GPL(fwnode_get_name);
530
531
532
533
534
535
536
537
538const char *fwnode_get_name_prefix(const struct fwnode_handle *fwnode)
539{
540 return fwnode_call_ptr_op(fwnode, get_name_prefix);
541}
542
543
544
545
546
547
548
549
550struct fwnode_handle *fwnode_get_parent(const struct fwnode_handle *fwnode)
551{
552 return fwnode_call_ptr_op(fwnode, get_parent);
553}
554EXPORT_SYMBOL_GPL(fwnode_get_parent);
555
556
557
558
559
560
561
562
563
564
565
566
567struct fwnode_handle *fwnode_get_next_parent(struct fwnode_handle *fwnode)
568{
569 struct fwnode_handle *parent = fwnode_get_parent(fwnode);
570
571 fwnode_handle_put(fwnode);
572
573 return parent;
574}
575EXPORT_SYMBOL_GPL(fwnode_get_next_parent);
576
577
578
579
580
581
582
583
584
585
586
587
588struct device *fwnode_get_next_parent_dev(struct fwnode_handle *fwnode)
589{
590 struct device *dev;
591
592 fwnode_handle_get(fwnode);
593 do {
594 fwnode = fwnode_get_next_parent(fwnode);
595 if (!fwnode)
596 return NULL;
597 dev = get_dev_from_fwnode(fwnode);
598 } while (!dev);
599 fwnode_handle_put(fwnode);
600 return dev;
601}
602
603
604
605
606
607
608
609unsigned int fwnode_count_parents(const struct fwnode_handle *fwnode)
610{
611 struct fwnode_handle *__fwnode;
612 unsigned int count;
613
614 __fwnode = fwnode_get_parent(fwnode);
615
616 for (count = 0; __fwnode; count++)
617 __fwnode = fwnode_get_next_parent(__fwnode);
618
619 return count;
620}
621EXPORT_SYMBOL_GPL(fwnode_count_parents);
622
623
624
625
626
627
628
629
630
631
632
633
634
635struct fwnode_handle *fwnode_get_nth_parent(struct fwnode_handle *fwnode,
636 unsigned int depth)
637{
638 unsigned int i;
639
640 fwnode_handle_get(fwnode);
641
642 for (i = 0; i < depth && fwnode; i++)
643 fwnode = fwnode_get_next_parent(fwnode);
644
645 return fwnode;
646}
647EXPORT_SYMBOL_GPL(fwnode_get_nth_parent);
648
649
650
651
652
653
654
655
656
657
658
659bool fwnode_is_ancestor_of(struct fwnode_handle *test_ancestor,
660 struct fwnode_handle *test_child)
661{
662 if (!test_ancestor)
663 return false;
664
665 fwnode_handle_get(test_child);
666 while (test_child) {
667 if (test_child == test_ancestor) {
668 fwnode_handle_put(test_child);
669 return true;
670 }
671 test_child = fwnode_get_next_parent(test_child);
672 }
673 return false;
674}
675
676
677
678
679
680
681struct fwnode_handle *
682fwnode_get_next_child_node(const struct fwnode_handle *fwnode,
683 struct fwnode_handle *child)
684{
685 return fwnode_call_ptr_op(fwnode, get_next_child_node, child);
686}
687EXPORT_SYMBOL_GPL(fwnode_get_next_child_node);
688
689
690
691
692
693
694
695struct fwnode_handle *
696fwnode_get_next_available_child_node(const struct fwnode_handle *fwnode,
697 struct fwnode_handle *child)
698{
699 struct fwnode_handle *next_child = child;
700
701 if (!fwnode)
702 return NULL;
703
704 do {
705 next_child = fwnode_get_next_child_node(fwnode, next_child);
706 if (!next_child)
707 return NULL;
708 } while (!fwnode_device_is_available(next_child));
709
710 return next_child;
711}
712EXPORT_SYMBOL_GPL(fwnode_get_next_available_child_node);
713
714
715
716
717
718
719struct fwnode_handle *device_get_next_child_node(struct device *dev,
720 struct fwnode_handle *child)
721{
722 const struct fwnode_handle *fwnode = dev_fwnode(dev);
723 struct fwnode_handle *next;
724
725
726 next = fwnode_get_next_child_node(fwnode, child);
727 if (next)
728 return next;
729
730
731 if (fwnode && !IS_ERR_OR_NULL(fwnode->secondary))
732 next = fwnode_get_next_child_node(fwnode->secondary, child);
733
734 return next;
735}
736EXPORT_SYMBOL_GPL(device_get_next_child_node);
737
738
739
740
741
742
743struct fwnode_handle *
744fwnode_get_named_child_node(const struct fwnode_handle *fwnode,
745 const char *childname)
746{
747 return fwnode_call_ptr_op(fwnode, get_named_child_node, childname);
748}
749EXPORT_SYMBOL_GPL(fwnode_get_named_child_node);
750
751
752
753
754
755
756struct fwnode_handle *device_get_named_child_node(struct device *dev,
757 const char *childname)
758{
759 return fwnode_get_named_child_node(dev_fwnode(dev), childname);
760}
761EXPORT_SYMBOL_GPL(device_get_named_child_node);
762
763
764
765
766
767
768
769struct fwnode_handle *fwnode_handle_get(struct fwnode_handle *fwnode)
770{
771 if (!fwnode_has_op(fwnode, get))
772 return fwnode;
773
774 return fwnode_call_ptr_op(fwnode, get);
775}
776EXPORT_SYMBOL_GPL(fwnode_handle_get);
777
778
779
780
781
782
783
784
785
786void fwnode_handle_put(struct fwnode_handle *fwnode)
787{
788 fwnode_call_void_op(fwnode, put);
789}
790EXPORT_SYMBOL_GPL(fwnode_handle_put);
791
792
793
794
795
796
797
798
799bool fwnode_device_is_available(const struct fwnode_handle *fwnode)
800{
801 if (!fwnode_has_op(fwnode, device_is_available))
802 return true;
803
804 return fwnode_call_bool_op(fwnode, device_is_available);
805}
806EXPORT_SYMBOL_GPL(fwnode_device_is_available);
807
808
809
810
811
812unsigned int device_get_child_node_count(struct device *dev)
813{
814 struct fwnode_handle *child;
815 unsigned int count = 0;
816
817 device_for_each_child_node(dev, child)
818 count++;
819
820 return count;
821}
822EXPORT_SYMBOL_GPL(device_get_child_node_count);
823
824bool device_dma_supported(struct device *dev)
825{
826 const struct fwnode_handle *fwnode = dev_fwnode(dev);
827
828
829
830
831
832 if (is_of_node(fwnode))
833 return true;
834
835 return acpi_dma_supported(to_acpi_device_node(fwnode));
836}
837EXPORT_SYMBOL_GPL(device_dma_supported);
838
839enum dev_dma_attr device_get_dma_attr(struct device *dev)
840{
841 const struct fwnode_handle *fwnode = dev_fwnode(dev);
842 enum dev_dma_attr attr = DEV_DMA_NOT_SUPPORTED;
843
844 if (is_of_node(fwnode)) {
845 if (of_dma_is_coherent(to_of_node(fwnode)))
846 attr = DEV_DMA_COHERENT;
847 else
848 attr = DEV_DMA_NON_COHERENT;
849 } else
850 attr = acpi_get_dma_attr(to_acpi_device_node(fwnode));
851
852 return attr;
853}
854EXPORT_SYMBOL_GPL(device_get_dma_attr);
855
856
857
858
859
860
861
862
863
864int fwnode_get_phy_mode(struct fwnode_handle *fwnode)
865{
866 const char *pm;
867 int err, i;
868
869 err = fwnode_property_read_string(fwnode, "phy-mode", &pm);
870 if (err < 0)
871 err = fwnode_property_read_string(fwnode,
872 "phy-connection-type", &pm);
873 if (err < 0)
874 return err;
875
876 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
877 if (!strcasecmp(pm, phy_modes(i)))
878 return i;
879
880 return -ENODEV;
881}
882EXPORT_SYMBOL_GPL(fwnode_get_phy_mode);
883
884
885
886
887
888
889
890
891
892int device_get_phy_mode(struct device *dev)
893{
894 return fwnode_get_phy_mode(dev_fwnode(dev));
895}
896EXPORT_SYMBOL_GPL(device_get_phy_mode);
897
898
899
900
901
902
903
904
905void __iomem *fwnode_iomap(struct fwnode_handle *fwnode, int index)
906{
907 if (IS_ENABLED(CONFIG_OF_ADDRESS) && is_of_node(fwnode))
908 return of_iomap(to_of_node(fwnode), index);
909
910 return NULL;
911}
912EXPORT_SYMBOL(fwnode_iomap);
913
914
915
916
917
918
919
920
921
922int fwnode_irq_get(const struct fwnode_handle *fwnode, unsigned int index)
923{
924 struct resource res;
925 int ret;
926
927 if (is_of_node(fwnode))
928 return of_irq_get(to_of_node(fwnode), index);
929
930 ret = acpi_irq_get(ACPI_HANDLE_FWNODE(fwnode), index, &res);
931 if (ret)
932 return ret;
933
934 return res.start;
935}
936EXPORT_SYMBOL(fwnode_irq_get);
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952int fwnode_irq_get_byname(const struct fwnode_handle *fwnode, const char *name)
953{
954 int index;
955
956 if (!name)
957 return -EINVAL;
958
959 index = fwnode_property_match_string(fwnode, "interrupt-names", name);
960 if (index < 0)
961 return index;
962
963 return fwnode_irq_get(fwnode, index);
964}
965EXPORT_SYMBOL(fwnode_irq_get_byname);
966
967
968
969
970
971
972
973
974
975struct fwnode_handle *
976fwnode_graph_get_next_endpoint(const struct fwnode_handle *fwnode,
977 struct fwnode_handle *prev)
978{
979 const struct fwnode_handle *parent;
980 struct fwnode_handle *ep;
981
982
983
984
985
986
987 if (prev)
988 parent = fwnode_graph_get_port_parent(prev);
989 else
990 parent = fwnode;
991
992 ep = fwnode_call_ptr_op(parent, graph_get_next_endpoint, prev);
993
994 if (IS_ERR_OR_NULL(ep) &&
995 !IS_ERR_OR_NULL(parent) && !IS_ERR_OR_NULL(parent->secondary))
996 ep = fwnode_graph_get_next_endpoint(parent->secondary, NULL);
997
998 return ep;
999}
1000EXPORT_SYMBOL_GPL(fwnode_graph_get_next_endpoint);
1001
1002
1003
1004
1005
1006
1007
1008struct fwnode_handle *
1009fwnode_graph_get_port_parent(const struct fwnode_handle *endpoint)
1010{
1011 struct fwnode_handle *port, *parent;
1012
1013 port = fwnode_get_parent(endpoint);
1014 parent = fwnode_call_ptr_op(port, graph_get_port_parent);
1015
1016 fwnode_handle_put(port);
1017
1018 return parent;
1019}
1020EXPORT_SYMBOL_GPL(fwnode_graph_get_port_parent);
1021
1022
1023
1024
1025
1026
1027
1028struct fwnode_handle *
1029fwnode_graph_get_remote_port_parent(const struct fwnode_handle *fwnode)
1030{
1031 struct fwnode_handle *endpoint, *parent;
1032
1033 endpoint = fwnode_graph_get_remote_endpoint(fwnode);
1034 parent = fwnode_graph_get_port_parent(endpoint);
1035
1036 fwnode_handle_put(endpoint);
1037
1038 return parent;
1039}
1040EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port_parent);
1041
1042
1043
1044
1045
1046
1047
1048struct fwnode_handle *
1049fwnode_graph_get_remote_port(const struct fwnode_handle *fwnode)
1050{
1051 return fwnode_get_next_parent(fwnode_graph_get_remote_endpoint(fwnode));
1052}
1053EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_port);
1054
1055
1056
1057
1058
1059
1060
1061struct fwnode_handle *
1062fwnode_graph_get_remote_endpoint(const struct fwnode_handle *fwnode)
1063{
1064 return fwnode_call_ptr_op(fwnode, graph_get_remote_endpoint);
1065}
1066EXPORT_SYMBOL_GPL(fwnode_graph_get_remote_endpoint);
1067
1068static bool fwnode_graph_remote_available(struct fwnode_handle *ep)
1069{
1070 struct fwnode_handle *dev_node;
1071 bool available;
1072
1073 dev_node = fwnode_graph_get_remote_port_parent(ep);
1074 available = fwnode_device_is_available(dev_node);
1075 fwnode_handle_put(dev_node);
1076
1077 return available;
1078}
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100struct fwnode_handle *
1101fwnode_graph_get_endpoint_by_id(const struct fwnode_handle *fwnode,
1102 u32 port, u32 endpoint, unsigned long flags)
1103{
1104 struct fwnode_handle *ep, *best_ep = NULL;
1105 unsigned int best_ep_id = 0;
1106 bool endpoint_next = flags & FWNODE_GRAPH_ENDPOINT_NEXT;
1107 bool enabled_only = !(flags & FWNODE_GRAPH_DEVICE_DISABLED);
1108
1109 fwnode_graph_for_each_endpoint(fwnode, ep) {
1110 struct fwnode_endpoint fwnode_ep = { 0 };
1111 int ret;
1112
1113 if (enabled_only && !fwnode_graph_remote_available(ep))
1114 continue;
1115
1116 ret = fwnode_graph_parse_endpoint(ep, &fwnode_ep);
1117 if (ret < 0)
1118 continue;
1119
1120 if (fwnode_ep.port != port)
1121 continue;
1122
1123 if (fwnode_ep.id == endpoint)
1124 return ep;
1125
1126 if (!endpoint_next)
1127 continue;
1128
1129
1130
1131
1132
1133
1134 if (fwnode_ep.id < endpoint ||
1135 (best_ep && best_ep_id < fwnode_ep.id))
1136 continue;
1137
1138 fwnode_handle_put(best_ep);
1139 best_ep = fwnode_handle_get(ep);
1140 best_ep_id = fwnode_ep.id;
1141 }
1142
1143 return best_ep;
1144}
1145EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_by_id);
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156unsigned int fwnode_graph_get_endpoint_count(struct fwnode_handle *fwnode,
1157 unsigned long flags)
1158{
1159 struct fwnode_handle *ep;
1160 unsigned int count = 0;
1161
1162 fwnode_graph_for_each_endpoint(fwnode, ep) {
1163 if (flags & FWNODE_GRAPH_DEVICE_DISABLED ||
1164 fwnode_graph_remote_available(ep))
1165 count++;
1166 }
1167
1168 return count;
1169}
1170EXPORT_SYMBOL_GPL(fwnode_graph_get_endpoint_count);
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181int fwnode_graph_parse_endpoint(const struct fwnode_handle *fwnode,
1182 struct fwnode_endpoint *endpoint)
1183{
1184 memset(endpoint, 0, sizeof(*endpoint));
1185
1186 return fwnode_call_int_op(fwnode, graph_parse_endpoint, endpoint);
1187}
1188EXPORT_SYMBOL(fwnode_graph_parse_endpoint);
1189
1190const void *device_get_match_data(struct device *dev)
1191{
1192 return fwnode_call_ptr_op(dev_fwnode(dev), device_get_match_data, dev);
1193}
1194EXPORT_SYMBOL_GPL(device_get_match_data);
1195
1196static void *
1197fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
1198 void *data, devcon_match_fn_t match)
1199{
1200 struct fwnode_handle *node;
1201 struct fwnode_handle *ep;
1202 void *ret;
1203
1204 fwnode_graph_for_each_endpoint(fwnode, ep) {
1205 node = fwnode_graph_get_remote_port_parent(ep);
1206 if (!fwnode_device_is_available(node)) {
1207 fwnode_handle_put(node);
1208 continue;
1209 }
1210
1211 ret = match(node, con_id, data);
1212 fwnode_handle_put(node);
1213 if (ret) {
1214 fwnode_handle_put(ep);
1215 return ret;
1216 }
1217 }
1218 return NULL;
1219}
1220
1221static void *
1222fwnode_devcon_match(struct fwnode_handle *fwnode, const char *con_id,
1223 void *data, devcon_match_fn_t match)
1224{
1225 struct fwnode_handle *node;
1226 void *ret;
1227 int i;
1228
1229 for (i = 0; ; i++) {
1230 node = fwnode_find_reference(fwnode, con_id, i);
1231 if (IS_ERR(node))
1232 break;
1233
1234 ret = match(node, NULL, data);
1235 fwnode_handle_put(node);
1236 if (ret)
1237 return ret;
1238 }
1239
1240 return NULL;
1241}
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254void *fwnode_connection_find_match(struct fwnode_handle *fwnode,
1255 const char *con_id, void *data,
1256 devcon_match_fn_t match)
1257{
1258 void *ret;
1259
1260 if (!fwnode || !match)
1261 return NULL;
1262
1263 ret = fwnode_graph_devcon_match(fwnode, con_id, data, match);
1264 if (ret)
1265 return ret;
1266
1267 return fwnode_devcon_match(fwnode, con_id, data, match);
1268}
1269EXPORT_SYMBOL_GPL(fwnode_connection_find_match);
1270