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