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