1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/ctype.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/spinlock.h>
24#include <linux/slab.h>
25#include <linux/proc_fs.h>
26
27
28
29
30
31
32
33
34
35
36
37
38struct alias_prop {
39 struct list_head link;
40 const char *alias;
41 struct device_node *np;
42 int id;
43 char stem[0];
44};
45
46static LIST_HEAD(aliases_lookup);
47
48struct device_node *allnodes;
49struct device_node *of_chosen;
50struct device_node *of_aliases;
51
52static DEFINE_MUTEX(of_aliases_mutex);
53
54
55
56
57DEFINE_RWLOCK(devtree_lock);
58
59int of_n_addr_cells(struct device_node *np)
60{
61 const __be32 *ip;
62
63 do {
64 if (np->parent)
65 np = np->parent;
66 ip = of_get_property(np, "#address-cells", NULL);
67 if (ip)
68 return be32_to_cpup(ip);
69 } while (np->parent);
70
71 return OF_ROOT_NODE_ADDR_CELLS_DEFAULT;
72}
73EXPORT_SYMBOL(of_n_addr_cells);
74
75int of_n_size_cells(struct device_node *np)
76{
77 const __be32 *ip;
78
79 do {
80 if (np->parent)
81 np = np->parent;
82 ip = of_get_property(np, "#size-cells", NULL);
83 if (ip)
84 return be32_to_cpup(ip);
85 } while (np->parent);
86
87 return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
88}
89EXPORT_SYMBOL(of_n_size_cells);
90
91#if defined(CONFIG_OF_DYNAMIC)
92
93
94
95
96
97
98
99struct device_node *of_node_get(struct device_node *node)
100{
101 if (node)
102 kref_get(&node->kref);
103 return node;
104}
105EXPORT_SYMBOL(of_node_get);
106
107static inline struct device_node *kref_to_device_node(struct kref *kref)
108{
109 return container_of(kref, struct device_node, kref);
110}
111
112
113
114
115
116
117
118
119static void of_node_release(struct kref *kref)
120{
121 struct device_node *node = kref_to_device_node(kref);
122 struct property *prop = node->properties;
123
124
125 if (!of_node_check_flag(node, OF_DETACHED)) {
126 pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
127 dump_stack();
128 kref_init(&node->kref);
129 return;
130 }
131
132 if (!of_node_check_flag(node, OF_DYNAMIC))
133 return;
134
135 while (prop) {
136 struct property *next = prop->next;
137 kfree(prop->name);
138 kfree(prop->value);
139 kfree(prop);
140 prop = next;
141
142 if (!prop) {
143 prop = node->deadprops;
144 node->deadprops = NULL;
145 }
146 }
147 kfree(node->full_name);
148 kfree(node->data);
149 kfree(node);
150}
151
152
153
154
155
156
157
158void of_node_put(struct device_node *node)
159{
160 if (node)
161 kref_put(&node->kref, of_node_release);
162}
163EXPORT_SYMBOL(of_node_put);
164#endif
165
166struct property *of_find_property(const struct device_node *np,
167 const char *name,
168 int *lenp)
169{
170 struct property *pp;
171
172 if (!np)
173 return NULL;
174
175 read_lock(&devtree_lock);
176 for (pp = np->properties; pp; pp = pp->next) {
177 if (of_prop_cmp(pp->name, name) == 0) {
178 if (lenp)
179 *lenp = pp->length;
180 break;
181 }
182 }
183 read_unlock(&devtree_lock);
184
185 return pp;
186}
187EXPORT_SYMBOL(of_find_property);
188
189
190
191
192
193
194
195
196
197struct device_node *of_find_all_nodes(struct device_node *prev)
198{
199 struct device_node *np;
200
201 read_lock(&devtree_lock);
202 np = prev ? prev->allnext : allnodes;
203 for (; np != NULL; np = np->allnext)
204 if (of_node_get(np))
205 break;
206 of_node_put(prev);
207 read_unlock(&devtree_lock);
208 return np;
209}
210EXPORT_SYMBOL(of_find_all_nodes);
211
212
213
214
215
216const void *of_get_property(const struct device_node *np, const char *name,
217 int *lenp)
218{
219 struct property *pp = of_find_property(np, name, lenp);
220
221 return pp ? pp->value : NULL;
222}
223EXPORT_SYMBOL(of_get_property);
224
225
226
227
228int of_device_is_compatible(const struct device_node *device,
229 const char *compat)
230{
231 const char* cp;
232 int cplen, l;
233
234 cp = of_get_property(device, "compatible", &cplen);
235 if (cp == NULL)
236 return 0;
237 while (cplen > 0) {
238 if (of_compat_cmp(cp, compat, strlen(compat)) == 0)
239 return 1;
240 l = strlen(cp) + 1;
241 cp += l;
242 cplen -= l;
243 }
244
245 return 0;
246}
247EXPORT_SYMBOL(of_device_is_compatible);
248
249
250
251
252
253
254
255
256int of_machine_is_compatible(const char *compat)
257{
258 struct device_node *root;
259 int rc = 0;
260
261 root = of_find_node_by_path("/");
262 if (root) {
263 rc = of_device_is_compatible(root, compat);
264 of_node_put(root);
265 }
266 return rc;
267}
268EXPORT_SYMBOL(of_machine_is_compatible);
269
270
271
272
273
274
275
276
277
278int of_device_is_available(const struct device_node *device)
279{
280 const char *status;
281 int statlen;
282
283 status = of_get_property(device, "status", &statlen);
284 if (status == NULL)
285 return 1;
286
287 if (statlen > 0) {
288 if (!strcmp(status, "okay") || !strcmp(status, "ok"))
289 return 1;
290 }
291
292 return 0;
293}
294EXPORT_SYMBOL(of_device_is_available);
295
296
297
298
299
300
301
302
303struct device_node *of_get_parent(const struct device_node *node)
304{
305 struct device_node *np;
306
307 if (!node)
308 return NULL;
309
310 read_lock(&devtree_lock);
311 np = of_node_get(node->parent);
312 read_unlock(&devtree_lock);
313 return np;
314}
315EXPORT_SYMBOL(of_get_parent);
316
317
318
319
320
321
322
323
324
325
326
327
328struct device_node *of_get_next_parent(struct device_node *node)
329{
330 struct device_node *parent;
331
332 if (!node)
333 return NULL;
334
335 read_lock(&devtree_lock);
336 parent = of_node_get(node->parent);
337 of_node_put(node);
338 read_unlock(&devtree_lock);
339 return parent;
340}
341
342
343
344
345
346
347
348
349
350struct device_node *of_get_next_child(const struct device_node *node,
351 struct device_node *prev)
352{
353 struct device_node *next;
354
355 read_lock(&devtree_lock);
356 next = prev ? prev->sibling : node->child;
357 for (; next; next = next->sibling)
358 if (of_node_get(next))
359 break;
360 of_node_put(prev);
361 read_unlock(&devtree_lock);
362 return next;
363}
364EXPORT_SYMBOL(of_get_next_child);
365
366
367
368
369
370
371
372
373
374struct device_node *of_get_next_available_child(const struct device_node *node,
375 struct device_node *prev)
376{
377 struct device_node *next;
378
379 read_lock(&devtree_lock);
380 next = prev ? prev->sibling : node->child;
381 for (; next; next = next->sibling) {
382 if (!of_device_is_available(next))
383 continue;
384 if (of_node_get(next))
385 break;
386 }
387 of_node_put(prev);
388 read_unlock(&devtree_lock);
389 return next;
390}
391EXPORT_SYMBOL(of_get_next_available_child);
392
393
394
395
396
397
398
399
400struct device_node *of_find_node_by_path(const char *path)
401{
402 struct device_node *np = allnodes;
403
404 read_lock(&devtree_lock);
405 for (; np; np = np->allnext) {
406 if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
407 && of_node_get(np))
408 break;
409 }
410 read_unlock(&devtree_lock);
411 return np;
412}
413EXPORT_SYMBOL(of_find_node_by_path);
414
415
416
417
418
419
420
421
422
423
424
425
426struct device_node *of_find_node_by_name(struct device_node *from,
427 const char *name)
428{
429 struct device_node *np;
430
431 read_lock(&devtree_lock);
432 np = from ? from->allnext : allnodes;
433 for (; np; np = np->allnext)
434 if (np->name && (of_node_cmp(np->name, name) == 0)
435 && of_node_get(np))
436 break;
437 of_node_put(from);
438 read_unlock(&devtree_lock);
439 return np;
440}
441EXPORT_SYMBOL(of_find_node_by_name);
442
443
444
445
446
447
448
449
450
451
452
453
454
455struct device_node *of_find_node_by_type(struct device_node *from,
456 const char *type)
457{
458 struct device_node *np;
459
460 read_lock(&devtree_lock);
461 np = from ? from->allnext : allnodes;
462 for (; np; np = np->allnext)
463 if (np->type && (of_node_cmp(np->type, type) == 0)
464 && of_node_get(np))
465 break;
466 of_node_put(from);
467 read_unlock(&devtree_lock);
468 return np;
469}
470EXPORT_SYMBOL(of_find_node_by_type);
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486struct device_node *of_find_compatible_node(struct device_node *from,
487 const char *type, const char *compatible)
488{
489 struct device_node *np;
490
491 read_lock(&devtree_lock);
492 np = from ? from->allnext : allnodes;
493 for (; np; np = np->allnext) {
494 if (type
495 && !(np->type && (of_node_cmp(np->type, type) == 0)))
496 continue;
497 if (of_device_is_compatible(np, compatible) && of_node_get(np))
498 break;
499 }
500 of_node_put(from);
501 read_unlock(&devtree_lock);
502 return np;
503}
504EXPORT_SYMBOL(of_find_compatible_node);
505
506
507
508
509
510
511
512
513
514
515
516
517
518struct device_node *of_find_node_with_property(struct device_node *from,
519 const char *prop_name)
520{
521 struct device_node *np;
522 struct property *pp;
523
524 read_lock(&devtree_lock);
525 np = from ? from->allnext : allnodes;
526 for (; np; np = np->allnext) {
527 for (pp = np->properties; pp; pp = pp->next) {
528 if (of_prop_cmp(pp->name, prop_name) == 0) {
529 of_node_get(np);
530 goto out;
531 }
532 }
533 }
534out:
535 of_node_put(from);
536 read_unlock(&devtree_lock);
537 return np;
538}
539EXPORT_SYMBOL(of_find_node_with_property);
540
541
542
543
544
545
546
547
548const struct of_device_id *of_match_node(const struct of_device_id *matches,
549 const struct device_node *node)
550{
551 if (!matches)
552 return NULL;
553
554 while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
555 int match = 1;
556 if (matches->name[0])
557 match &= node->name
558 && !strcmp(matches->name, node->name);
559 if (matches->type[0])
560 match &= node->type
561 && !strcmp(matches->type, node->type);
562 if (matches->compatible[0])
563 match &= of_device_is_compatible(node,
564 matches->compatible);
565 if (match)
566 return matches;
567 matches++;
568 }
569 return NULL;
570}
571EXPORT_SYMBOL(of_match_node);
572
573
574
575
576
577
578
579
580
581
582
583
584
585struct device_node *of_find_matching_node(struct device_node *from,
586 const struct of_device_id *matches)
587{
588 struct device_node *np;
589
590 read_lock(&devtree_lock);
591 np = from ? from->allnext : allnodes;
592 for (; np; np = np->allnext) {
593 if (of_match_node(matches, np) && of_node_get(np))
594 break;
595 }
596 of_node_put(from);
597 read_unlock(&devtree_lock);
598 return np;
599}
600EXPORT_SYMBOL(of_find_matching_node);
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615int of_modalias_node(struct device_node *node, char *modalias, int len)
616{
617 const char *compatible, *p;
618 int cplen;
619
620 compatible = of_get_property(node, "compatible", &cplen);
621 if (!compatible || strlen(compatible) > cplen)
622 return -ENODEV;
623 p = strchr(compatible, ',');
624 strlcpy(modalias, p ? p + 1 : compatible, len);
625 return 0;
626}
627EXPORT_SYMBOL_GPL(of_modalias_node);
628
629
630
631
632
633
634
635
636struct device_node *of_find_node_by_phandle(phandle handle)
637{
638 struct device_node *np;
639
640 read_lock(&devtree_lock);
641 for (np = allnodes; np; np = np->allnext)
642 if (np->phandle == handle)
643 break;
644 of_node_get(np);
645 read_unlock(&devtree_lock);
646 return np;
647}
648EXPORT_SYMBOL(of_find_node_by_phandle);
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665int of_property_read_u32_array(const struct device_node *np,
666 const char *propname, u32 *out_values,
667 size_t sz)
668{
669 struct property *prop = of_find_property(np, propname, NULL);
670 const __be32 *val;
671
672 if (!prop)
673 return -EINVAL;
674 if (!prop->value)
675 return -ENODATA;
676 if ((sz * sizeof(*out_values)) > prop->length)
677 return -EOVERFLOW;
678
679 val = prop->value;
680 while (sz--)
681 *out_values++ = be32_to_cpup(val++);
682 return 0;
683}
684EXPORT_SYMBOL_GPL(of_property_read_u32_array);
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699int of_property_read_u64(const struct device_node *np, const char *propname,
700 u64 *out_value)
701{
702 struct property *prop = of_find_property(np, propname, NULL);
703
704 if (!prop)
705 return -EINVAL;
706 if (!prop->value)
707 return -ENODATA;
708 if (sizeof(*out_value) > prop->length)
709 return -EOVERFLOW;
710 *out_value = of_read_number(prop->value, 2);
711 return 0;
712}
713EXPORT_SYMBOL_GPL(of_property_read_u64);
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730int of_property_read_string(struct device_node *np, const char *propname,
731 const char **out_string)
732{
733 struct property *prop = of_find_property(np, propname, NULL);
734 if (!prop)
735 return -EINVAL;
736 if (!prop->value)
737 return -ENODATA;
738 if (strnlen(prop->value, prop->length) >= prop->length)
739 return -EILSEQ;
740 *out_string = prop->value;
741 return 0;
742}
743EXPORT_SYMBOL_GPL(of_property_read_string);
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763int of_property_read_string_index(struct device_node *np, const char *propname,
764 int index, const char **output)
765{
766 struct property *prop = of_find_property(np, propname, NULL);
767 int i = 0;
768 size_t l = 0, total = 0;
769 const char *p;
770
771 if (!prop)
772 return -EINVAL;
773 if (!prop->value)
774 return -ENODATA;
775 if (strnlen(prop->value, prop->length) >= prop->length)
776 return -EILSEQ;
777
778 p = prop->value;
779
780 for (i = 0; total < prop->length; total += l, p += l) {
781 l = strlen(p) + 1;
782 if (i++ == index) {
783 *output = p;
784 return 0;
785 }
786 }
787 return -ENODATA;
788}
789EXPORT_SYMBOL_GPL(of_property_read_string_index);
790
791
792
793
794
795
796
797
798
799
800int of_property_match_string(struct device_node *np, const char *propname,
801 const char *string)
802{
803 struct property *prop = of_find_property(np, propname, NULL);
804 size_t l;
805 int i;
806 const char *p, *end;
807
808 if (!prop)
809 return -EINVAL;
810 if (!prop->value)
811 return -ENODATA;
812
813 p = prop->value;
814 end = p + prop->length;
815
816 for (i = 0; p < end; i++, p += l) {
817 l = strlen(p) + 1;
818 if (p + l > end)
819 return -EILSEQ;
820 pr_debug("comparing %s with %s\n", string, p);
821 if (strcmp(string, p) == 0)
822 return i;
823 }
824 return -ENODATA;
825}
826EXPORT_SYMBOL_GPL(of_property_match_string);
827
828
829
830
831
832
833
834
835
836
837
838
839
840int of_property_count_strings(struct device_node *np, const char *propname)
841{
842 struct property *prop = of_find_property(np, propname, NULL);
843 int i = 0;
844 size_t l = 0, total = 0;
845 const char *p;
846
847 if (!prop)
848 return -EINVAL;
849 if (!prop->value)
850 return -ENODATA;
851 if (strnlen(prop->value, prop->length) >= prop->length)
852 return -EILSEQ;
853
854 p = prop->value;
855
856 for (i = 0; total < prop->length; total += l, p += l, i++)
857 l = strlen(p) + 1;
858
859 return i;
860}
861EXPORT_SYMBOL_GPL(of_property_count_strings);
862
863
864
865
866
867
868
869
870
871
872
873struct device_node *
874of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
875{
876 const __be32 *phandle;
877 int size;
878
879 phandle = of_get_property(np, phandle_name, &size);
880 if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
881 return NULL;
882
883 return of_find_node_by_phandle(be32_to_cpup(phandle + index));
884}
885EXPORT_SYMBOL(of_parse_phandle);
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
920 const char *cells_name, int index,
921 struct of_phandle_args *out_args)
922{
923 const __be32 *list, *list_end;
924 int size, cur_index = 0;
925 uint32_t count = 0;
926 struct device_node *node = NULL;
927 phandle phandle;
928
929
930 list = of_get_property(np, list_name, &size);
931 if (!list)
932 return -ENOENT;
933 list_end = list + size / sizeof(*list);
934
935
936 while (list < list_end) {
937 count = 0;
938
939
940
941
942
943 phandle = be32_to_cpup(list++);
944 if (phandle) {
945
946
947
948
949 node = of_find_node_by_phandle(phandle);
950 if (!node) {
951 pr_err("%s: could not find phandle\n",
952 np->full_name);
953 break;
954 }
955 if (of_property_read_u32(node, cells_name, &count)) {
956 pr_err("%s: could not get %s for %s\n",
957 np->full_name, cells_name,
958 node->full_name);
959 break;
960 }
961
962
963
964
965
966 if (list + count > list_end) {
967 pr_err("%s: arguments longer than property\n",
968 np->full_name);
969 break;
970 }
971 }
972
973
974
975
976
977
978
979 if (cur_index == index) {
980 if (!phandle)
981 return -ENOENT;
982
983 if (out_args) {
984 int i;
985 if (WARN_ON(count > MAX_PHANDLE_ARGS))
986 count = MAX_PHANDLE_ARGS;
987 out_args->np = node;
988 out_args->args_count = count;
989 for (i = 0; i < count; i++)
990 out_args->args[i] = be32_to_cpup(list++);
991 }
992 return 0;
993 }
994
995 of_node_put(node);
996 node = NULL;
997 list += count;
998 cur_index++;
999 }
1000
1001
1002 if (node)
1003 of_node_put(node);
1004 return -EINVAL;
1005}
1006EXPORT_SYMBOL(of_parse_phandle_with_args);
1007
1008
1009
1010
1011int prom_add_property(struct device_node *np, struct property *prop)
1012{
1013 struct property **next;
1014 unsigned long flags;
1015
1016 prop->next = NULL;
1017 write_lock_irqsave(&devtree_lock, flags);
1018 next = &np->properties;
1019 while (*next) {
1020 if (strcmp(prop->name, (*next)->name) == 0) {
1021
1022 write_unlock_irqrestore(&devtree_lock, flags);
1023 return -1;
1024 }
1025 next = &(*next)->next;
1026 }
1027 *next = prop;
1028 write_unlock_irqrestore(&devtree_lock, flags);
1029
1030#ifdef CONFIG_PROC_DEVICETREE
1031
1032 if (np->pde)
1033 proc_device_tree_add_prop(np->pde, prop);
1034#endif
1035
1036 return 0;
1037}
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047int prom_remove_property(struct device_node *np, struct property *prop)
1048{
1049 struct property **next;
1050 unsigned long flags;
1051 int found = 0;
1052
1053 write_lock_irqsave(&devtree_lock, flags);
1054 next = &np->properties;
1055 while (*next) {
1056 if (*next == prop) {
1057
1058 *next = prop->next;
1059 prop->next = np->deadprops;
1060 np->deadprops = prop;
1061 found = 1;
1062 break;
1063 }
1064 next = &(*next)->next;
1065 }
1066 write_unlock_irqrestore(&devtree_lock, flags);
1067
1068 if (!found)
1069 return -ENODEV;
1070
1071#ifdef CONFIG_PROC_DEVICETREE
1072
1073 if (np->pde)
1074 proc_device_tree_remove_prop(np->pde, prop);
1075#endif
1076
1077 return 0;
1078}
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089int prom_update_property(struct device_node *np,
1090 struct property *newprop)
1091{
1092 struct property **next, *oldprop;
1093 unsigned long flags;
1094 int found = 0;
1095
1096 if (!newprop->name)
1097 return -EINVAL;
1098
1099 oldprop = of_find_property(np, newprop->name, NULL);
1100 if (!oldprop)
1101 return prom_add_property(np, newprop);
1102
1103 write_lock_irqsave(&devtree_lock, flags);
1104 next = &np->properties;
1105 while (*next) {
1106 if (*next == oldprop) {
1107
1108 newprop->next = oldprop->next;
1109 *next = newprop;
1110 oldprop->next = np->deadprops;
1111 np->deadprops = oldprop;
1112 found = 1;
1113 break;
1114 }
1115 next = &(*next)->next;
1116 }
1117 write_unlock_irqrestore(&devtree_lock, flags);
1118
1119 if (!found)
1120 return -ENODEV;
1121
1122#ifdef CONFIG_PROC_DEVICETREE
1123
1124 if (np->pde)
1125 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1126#endif
1127
1128 return 0;
1129}
1130
1131#if defined(CONFIG_OF_DYNAMIC)
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143void of_attach_node(struct device_node *np)
1144{
1145 unsigned long flags;
1146
1147 write_lock_irqsave(&devtree_lock, flags);
1148 np->sibling = np->parent->child;
1149 np->allnext = allnodes;
1150 np->parent->child = np;
1151 allnodes = np;
1152 write_unlock_irqrestore(&devtree_lock, flags);
1153}
1154
1155
1156
1157
1158
1159
1160
1161void of_detach_node(struct device_node *np)
1162{
1163 struct device_node *parent;
1164 unsigned long flags;
1165
1166 write_lock_irqsave(&devtree_lock, flags);
1167
1168 parent = np->parent;
1169 if (!parent)
1170 goto out_unlock;
1171
1172 if (allnodes == np)
1173 allnodes = np->allnext;
1174 else {
1175 struct device_node *prev;
1176 for (prev = allnodes;
1177 prev->allnext != np;
1178 prev = prev->allnext)
1179 ;
1180 prev->allnext = np->allnext;
1181 }
1182
1183 if (parent->child == np)
1184 parent->child = np->sibling;
1185 else {
1186 struct device_node *prevsib;
1187 for (prevsib = np->parent->child;
1188 prevsib->sibling != np;
1189 prevsib = prevsib->sibling)
1190 ;
1191 prevsib->sibling = np->sibling;
1192 }
1193
1194 of_node_set_flag(np, OF_DETACHED);
1195
1196out_unlock:
1197 write_unlock_irqrestore(&devtree_lock, flags);
1198}
1199#endif
1200
1201static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1202 int id, const char *stem, int stem_len)
1203{
1204 ap->np = np;
1205 ap->id = id;
1206 strncpy(ap->stem, stem, stem_len);
1207 ap->stem[stem_len] = 0;
1208 list_add_tail(&ap->link, &aliases_lookup);
1209 pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
1210 ap->alias, ap->stem, ap->id, of_node_full_name(np));
1211}
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1224{
1225 struct property *pp;
1226
1227 of_chosen = of_find_node_by_path("/chosen");
1228 if (of_chosen == NULL)
1229 of_chosen = of_find_node_by_path("/chosen@0");
1230 of_aliases = of_find_node_by_path("/aliases");
1231 if (!of_aliases)
1232 return;
1233
1234 for_each_property_of_node(of_aliases, pp) {
1235 const char *start = pp->name;
1236 const char *end = start + strlen(start);
1237 struct device_node *np;
1238 struct alias_prop *ap;
1239 int id, len;
1240
1241
1242 if (!strcmp(pp->name, "name") ||
1243 !strcmp(pp->name, "phandle") ||
1244 !strcmp(pp->name, "linux,phandle"))
1245 continue;
1246
1247 np = of_find_node_by_path(pp->value);
1248 if (!np)
1249 continue;
1250
1251
1252
1253 while (isdigit(*(end-1)) && end > start)
1254 end--;
1255 len = end - start;
1256
1257 if (kstrtoint(end, 10, &id) < 0)
1258 continue;
1259
1260
1261 ap = dt_alloc(sizeof(*ap) + len + 1, 4);
1262 if (!ap)
1263 continue;
1264 ap->alias = start;
1265 of_alias_add(ap, np, id, start, len);
1266 }
1267}
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277int of_alias_get_id(struct device_node *np, const char *stem)
1278{
1279 struct alias_prop *app;
1280 int id = -ENODEV;
1281
1282 mutex_lock(&of_aliases_mutex);
1283 list_for_each_entry(app, &aliases_lookup, link) {
1284 if (strcmp(app->stem, stem) != 0)
1285 continue;
1286
1287 if (np == app->np) {
1288 id = app->id;
1289 break;
1290 }
1291 }
1292 mutex_unlock(&of_aliases_mutex);
1293
1294 return id;
1295}
1296EXPORT_SYMBOL_GPL(of_alias_get_id);
1297
1298const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
1299 u32 *pu)
1300{
1301 const void *curv = cur;
1302
1303 if (!prop)
1304 return NULL;
1305
1306 if (!cur) {
1307 curv = prop->value;
1308 goto out_val;
1309 }
1310
1311 curv += sizeof(*cur);
1312 if (curv >= prop->value + prop->length)
1313 return NULL;
1314
1315out_val:
1316 *pu = be32_to_cpup(curv);
1317 return curv;
1318}
1319EXPORT_SYMBOL_GPL(of_prop_next_u32);
1320
1321const char *of_prop_next_string(struct property *prop, const char *cur)
1322{
1323 const void *curv = cur;
1324
1325 if (!prop)
1326 return NULL;
1327
1328 if (!cur)
1329 return prop->value;
1330
1331 curv += strlen(cur) + 1;
1332 if (curv >= prop->value + prop->length)
1333 return NULL;
1334
1335 return curv;
1336}
1337EXPORT_SYMBOL_GPL(of_prop_next_string);
1338