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
400
401
402
403
404struct device_node *of_get_child_by_name(const struct device_node *node,
405 const char *name)
406{
407 struct device_node *child;
408
409 for_each_child_of_node(node, child)
410 if (child->name && (of_node_cmp(child->name, name) == 0))
411 break;
412 return child;
413}
414EXPORT_SYMBOL(of_get_child_by_name);
415
416
417
418
419
420
421
422
423struct device_node *of_find_node_by_path(const char *path)
424{
425 struct device_node *np = allnodes;
426
427 read_lock(&devtree_lock);
428 for (; np; np = np->allnext) {
429 if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
430 && of_node_get(np))
431 break;
432 }
433 read_unlock(&devtree_lock);
434 return np;
435}
436EXPORT_SYMBOL(of_find_node_by_path);
437
438
439
440
441
442
443
444
445
446
447
448
449struct device_node *of_find_node_by_name(struct device_node *from,
450 const char *name)
451{
452 struct device_node *np;
453
454 read_lock(&devtree_lock);
455 np = from ? from->allnext : allnodes;
456 for (; np; np = np->allnext)
457 if (np->name && (of_node_cmp(np->name, name) == 0)
458 && of_node_get(np))
459 break;
460 of_node_put(from);
461 read_unlock(&devtree_lock);
462 return np;
463}
464EXPORT_SYMBOL(of_find_node_by_name);
465
466
467
468
469
470
471
472
473
474
475
476
477
478struct device_node *of_find_node_by_type(struct device_node *from,
479 const char *type)
480{
481 struct device_node *np;
482
483 read_lock(&devtree_lock);
484 np = from ? from->allnext : allnodes;
485 for (; np; np = np->allnext)
486 if (np->type && (of_node_cmp(np->type, type) == 0)
487 && of_node_get(np))
488 break;
489 of_node_put(from);
490 read_unlock(&devtree_lock);
491 return np;
492}
493EXPORT_SYMBOL(of_find_node_by_type);
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509struct device_node *of_find_compatible_node(struct device_node *from,
510 const char *type, const char *compatible)
511{
512 struct device_node *np;
513
514 read_lock(&devtree_lock);
515 np = from ? from->allnext : allnodes;
516 for (; np; np = np->allnext) {
517 if (type
518 && !(np->type && (of_node_cmp(np->type, type) == 0)))
519 continue;
520 if (of_device_is_compatible(np, compatible) && of_node_get(np))
521 break;
522 }
523 of_node_put(from);
524 read_unlock(&devtree_lock);
525 return np;
526}
527EXPORT_SYMBOL(of_find_compatible_node);
528
529
530
531
532
533
534
535
536
537
538
539
540
541struct device_node *of_find_node_with_property(struct device_node *from,
542 const char *prop_name)
543{
544 struct device_node *np;
545 struct property *pp;
546
547 read_lock(&devtree_lock);
548 np = from ? from->allnext : allnodes;
549 for (; np; np = np->allnext) {
550 for (pp = np->properties; pp; pp = pp->next) {
551 if (of_prop_cmp(pp->name, prop_name) == 0) {
552 of_node_get(np);
553 goto out;
554 }
555 }
556 }
557out:
558 of_node_put(from);
559 read_unlock(&devtree_lock);
560 return np;
561}
562EXPORT_SYMBOL(of_find_node_with_property);
563
564
565
566
567
568
569
570
571const struct of_device_id *of_match_node(const struct of_device_id *matches,
572 const struct device_node *node)
573{
574 if (!matches)
575 return NULL;
576
577 while (matches->name[0] || matches->type[0] || matches->compatible[0]) {
578 int match = 1;
579 if (matches->name[0])
580 match &= node->name
581 && !strcmp(matches->name, node->name);
582 if (matches->type[0])
583 match &= node->type
584 && !strcmp(matches->type, node->type);
585 if (matches->compatible[0])
586 match &= of_device_is_compatible(node,
587 matches->compatible);
588 if (match)
589 return matches;
590 matches++;
591 }
592 return NULL;
593}
594EXPORT_SYMBOL(of_match_node);
595
596
597
598
599
600
601
602
603
604
605
606
607
608struct device_node *of_find_matching_node(struct device_node *from,
609 const struct of_device_id *matches)
610{
611 struct device_node *np;
612
613 read_lock(&devtree_lock);
614 np = from ? from->allnext : allnodes;
615 for (; np; np = np->allnext) {
616 if (of_match_node(matches, np) && of_node_get(np))
617 break;
618 }
619 of_node_put(from);
620 read_unlock(&devtree_lock);
621 return np;
622}
623EXPORT_SYMBOL(of_find_matching_node);
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638int of_modalias_node(struct device_node *node, char *modalias, int len)
639{
640 const char *compatible, *p;
641 int cplen;
642
643 compatible = of_get_property(node, "compatible", &cplen);
644 if (!compatible || strlen(compatible) > cplen)
645 return -ENODEV;
646 p = strchr(compatible, ',');
647 strlcpy(modalias, p ? p + 1 : compatible, len);
648 return 0;
649}
650EXPORT_SYMBOL_GPL(of_modalias_node);
651
652
653
654
655
656
657
658
659struct device_node *of_find_node_by_phandle(phandle handle)
660{
661 struct device_node *np;
662
663 read_lock(&devtree_lock);
664 for (np = allnodes; np; np = np->allnext)
665 if (np->phandle == handle)
666 break;
667 of_node_get(np);
668 read_unlock(&devtree_lock);
669 return np;
670}
671EXPORT_SYMBOL(of_find_node_by_phandle);
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688int of_property_read_u32_array(const struct device_node *np,
689 const char *propname, u32 *out_values,
690 size_t sz)
691{
692 struct property *prop = of_find_property(np, propname, NULL);
693 const __be32 *val;
694
695 if (!prop)
696 return -EINVAL;
697 if (!prop->value)
698 return -ENODATA;
699 if ((sz * sizeof(*out_values)) > prop->length)
700 return -EOVERFLOW;
701
702 val = prop->value;
703 while (sz--)
704 *out_values++ = be32_to_cpup(val++);
705 return 0;
706}
707EXPORT_SYMBOL_GPL(of_property_read_u32_array);
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722int of_property_read_u64(const struct device_node *np, const char *propname,
723 u64 *out_value)
724{
725 struct property *prop = of_find_property(np, propname, NULL);
726
727 if (!prop)
728 return -EINVAL;
729 if (!prop->value)
730 return -ENODATA;
731 if (sizeof(*out_value) > prop->length)
732 return -EOVERFLOW;
733 *out_value = of_read_number(prop->value, 2);
734 return 0;
735}
736EXPORT_SYMBOL_GPL(of_property_read_u64);
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753int of_property_read_string(struct device_node *np, const char *propname,
754 const char **out_string)
755{
756 struct property *prop = of_find_property(np, propname, NULL);
757 if (!prop)
758 return -EINVAL;
759 if (!prop->value)
760 return -ENODATA;
761 if (strnlen(prop->value, prop->length) >= prop->length)
762 return -EILSEQ;
763 *out_string = prop->value;
764 return 0;
765}
766EXPORT_SYMBOL_GPL(of_property_read_string);
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786int of_property_read_string_index(struct device_node *np, const char *propname,
787 int index, const char **output)
788{
789 struct property *prop = of_find_property(np, propname, NULL);
790 int i = 0;
791 size_t l = 0, total = 0;
792 const char *p;
793
794 if (!prop)
795 return -EINVAL;
796 if (!prop->value)
797 return -ENODATA;
798 if (strnlen(prop->value, prop->length) >= prop->length)
799 return -EILSEQ;
800
801 p = prop->value;
802
803 for (i = 0; total < prop->length; total += l, p += l) {
804 l = strlen(p) + 1;
805 if (i++ == index) {
806 *output = p;
807 return 0;
808 }
809 }
810 return -ENODATA;
811}
812EXPORT_SYMBOL_GPL(of_property_read_string_index);
813
814
815
816
817
818
819
820
821
822
823int of_property_match_string(struct device_node *np, const char *propname,
824 const char *string)
825{
826 struct property *prop = of_find_property(np, propname, NULL);
827 size_t l;
828 int i;
829 const char *p, *end;
830
831 if (!prop)
832 return -EINVAL;
833 if (!prop->value)
834 return -ENODATA;
835
836 p = prop->value;
837 end = p + prop->length;
838
839 for (i = 0; p < end; i++, p += l) {
840 l = strlen(p) + 1;
841 if (p + l > end)
842 return -EILSEQ;
843 pr_debug("comparing %s with %s\n", string, p);
844 if (strcmp(string, p) == 0)
845 return i;
846 }
847 return -ENODATA;
848}
849EXPORT_SYMBOL_GPL(of_property_match_string);
850
851
852
853
854
855
856
857
858
859
860
861
862
863int of_property_count_strings(struct device_node *np, const char *propname)
864{
865 struct property *prop = of_find_property(np, propname, NULL);
866 int i = 0;
867 size_t l = 0, total = 0;
868 const char *p;
869
870 if (!prop)
871 return -EINVAL;
872 if (!prop->value)
873 return -ENODATA;
874 if (strnlen(prop->value, prop->length) >= prop->length)
875 return -EILSEQ;
876
877 p = prop->value;
878
879 for (i = 0; total < prop->length; total += l, p += l, i++)
880 l = strlen(p) + 1;
881
882 return i;
883}
884EXPORT_SYMBOL_GPL(of_property_count_strings);
885
886
887
888
889
890
891
892
893
894
895
896struct device_node *
897of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
898{
899 const __be32 *phandle;
900 int size;
901
902 phandle = of_get_property(np, phandle_name, &size);
903 if ((!phandle) || (size < sizeof(*phandle) * (index + 1)))
904 return NULL;
905
906 return of_find_node_by_phandle(be32_to_cpup(phandle + index));
907}
908EXPORT_SYMBOL(of_parse_phandle);
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
943 const char *cells_name, int index,
944 struct of_phandle_args *out_args)
945{
946 const __be32 *list, *list_end;
947 int size, cur_index = 0;
948 uint32_t count = 0;
949 struct device_node *node = NULL;
950 phandle phandle;
951
952
953 list = of_get_property(np, list_name, &size);
954 if (!list)
955 return -ENOENT;
956 list_end = list + size / sizeof(*list);
957
958
959 while (list < list_end) {
960 count = 0;
961
962
963
964
965
966 phandle = be32_to_cpup(list++);
967 if (phandle) {
968
969
970
971
972 node = of_find_node_by_phandle(phandle);
973 if (!node) {
974 pr_err("%s: could not find phandle\n",
975 np->full_name);
976 break;
977 }
978 if (of_property_read_u32(node, cells_name, &count)) {
979 pr_err("%s: could not get %s for %s\n",
980 np->full_name, cells_name,
981 node->full_name);
982 break;
983 }
984
985
986
987
988
989 if (list + count > list_end) {
990 pr_err("%s: arguments longer than property\n",
991 np->full_name);
992 break;
993 }
994 }
995
996
997
998
999
1000
1001
1002 if (cur_index == index) {
1003 if (!phandle)
1004 return -ENOENT;
1005
1006 if (out_args) {
1007 int i;
1008 if (WARN_ON(count > MAX_PHANDLE_ARGS))
1009 count = MAX_PHANDLE_ARGS;
1010 out_args->np = node;
1011 out_args->args_count = count;
1012 for (i = 0; i < count; i++)
1013 out_args->args[i] = be32_to_cpup(list++);
1014 }
1015 return 0;
1016 }
1017
1018 of_node_put(node);
1019 node = NULL;
1020 list += count;
1021 cur_index++;
1022 }
1023
1024
1025 if (node)
1026 of_node_put(node);
1027 return -EINVAL;
1028}
1029EXPORT_SYMBOL(of_parse_phandle_with_args);
1030
1031
1032
1033
1034int prom_add_property(struct device_node *np, struct property *prop)
1035{
1036 struct property **next;
1037 unsigned long flags;
1038
1039 prop->next = NULL;
1040 write_lock_irqsave(&devtree_lock, flags);
1041 next = &np->properties;
1042 while (*next) {
1043 if (strcmp(prop->name, (*next)->name) == 0) {
1044
1045 write_unlock_irqrestore(&devtree_lock, flags);
1046 return -1;
1047 }
1048 next = &(*next)->next;
1049 }
1050 *next = prop;
1051 write_unlock_irqrestore(&devtree_lock, flags);
1052
1053#ifdef CONFIG_PROC_DEVICETREE
1054
1055 if (np->pde)
1056 proc_device_tree_add_prop(np->pde, prop);
1057#endif
1058
1059 return 0;
1060}
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070int prom_remove_property(struct device_node *np, struct property *prop)
1071{
1072 struct property **next;
1073 unsigned long flags;
1074 int found = 0;
1075
1076 write_lock_irqsave(&devtree_lock, flags);
1077 next = &np->properties;
1078 while (*next) {
1079 if (*next == prop) {
1080
1081 *next = prop->next;
1082 prop->next = np->deadprops;
1083 np->deadprops = prop;
1084 found = 1;
1085 break;
1086 }
1087 next = &(*next)->next;
1088 }
1089 write_unlock_irqrestore(&devtree_lock, flags);
1090
1091 if (!found)
1092 return -ENODEV;
1093
1094#ifdef CONFIG_PROC_DEVICETREE
1095
1096 if (np->pde)
1097 proc_device_tree_remove_prop(np->pde, prop);
1098#endif
1099
1100 return 0;
1101}
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112int prom_update_property(struct device_node *np,
1113 struct property *newprop)
1114{
1115 struct property **next, *oldprop;
1116 unsigned long flags;
1117 int found = 0;
1118
1119 if (!newprop->name)
1120 return -EINVAL;
1121
1122 oldprop = of_find_property(np, newprop->name, NULL);
1123 if (!oldprop)
1124 return prom_add_property(np, newprop);
1125
1126 write_lock_irqsave(&devtree_lock, flags);
1127 next = &np->properties;
1128 while (*next) {
1129 if (*next == oldprop) {
1130
1131 newprop->next = oldprop->next;
1132 *next = newprop;
1133 oldprop->next = np->deadprops;
1134 np->deadprops = oldprop;
1135 found = 1;
1136 break;
1137 }
1138 next = &(*next)->next;
1139 }
1140 write_unlock_irqrestore(&devtree_lock, flags);
1141
1142 if (!found)
1143 return -ENODEV;
1144
1145#ifdef CONFIG_PROC_DEVICETREE
1146
1147 if (np->pde)
1148 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1149#endif
1150
1151 return 0;
1152}
1153
1154#if defined(CONFIG_OF_DYNAMIC)
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166void of_attach_node(struct device_node *np)
1167{
1168 unsigned long flags;
1169
1170 write_lock_irqsave(&devtree_lock, flags);
1171 np->sibling = np->parent->child;
1172 np->allnext = allnodes;
1173 np->parent->child = np;
1174 allnodes = np;
1175 write_unlock_irqrestore(&devtree_lock, flags);
1176}
1177
1178
1179
1180
1181
1182
1183
1184void of_detach_node(struct device_node *np)
1185{
1186 struct device_node *parent;
1187 unsigned long flags;
1188
1189 write_lock_irqsave(&devtree_lock, flags);
1190
1191 parent = np->parent;
1192 if (!parent)
1193 goto out_unlock;
1194
1195 if (allnodes == np)
1196 allnodes = np->allnext;
1197 else {
1198 struct device_node *prev;
1199 for (prev = allnodes;
1200 prev->allnext != np;
1201 prev = prev->allnext)
1202 ;
1203 prev->allnext = np->allnext;
1204 }
1205
1206 if (parent->child == np)
1207 parent->child = np->sibling;
1208 else {
1209 struct device_node *prevsib;
1210 for (prevsib = np->parent->child;
1211 prevsib->sibling != np;
1212 prevsib = prevsib->sibling)
1213 ;
1214 prevsib->sibling = np->sibling;
1215 }
1216
1217 of_node_set_flag(np, OF_DETACHED);
1218
1219out_unlock:
1220 write_unlock_irqrestore(&devtree_lock, flags);
1221}
1222#endif
1223
1224static void of_alias_add(struct alias_prop *ap, struct device_node *np,
1225 int id, const char *stem, int stem_len)
1226{
1227 ap->np = np;
1228 ap->id = id;
1229 strncpy(ap->stem, stem, stem_len);
1230 ap->stem[stem_len] = 0;
1231 list_add_tail(&ap->link, &aliases_lookup);
1232 pr_debug("adding DT alias:%s: stem=%s id=%i node=%s\n",
1233 ap->alias, ap->stem, ap->id, of_node_full_name(np));
1234}
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align))
1247{
1248 struct property *pp;
1249
1250 of_chosen = of_find_node_by_path("/chosen");
1251 if (of_chosen == NULL)
1252 of_chosen = of_find_node_by_path("/chosen@0");
1253 of_aliases = of_find_node_by_path("/aliases");
1254 if (!of_aliases)
1255 return;
1256
1257 for_each_property_of_node(of_aliases, pp) {
1258 const char *start = pp->name;
1259 const char *end = start + strlen(start);
1260 struct device_node *np;
1261 struct alias_prop *ap;
1262 int id, len;
1263
1264
1265 if (!strcmp(pp->name, "name") ||
1266 !strcmp(pp->name, "phandle") ||
1267 !strcmp(pp->name, "linux,phandle"))
1268 continue;
1269
1270 np = of_find_node_by_path(pp->value);
1271 if (!np)
1272 continue;
1273
1274
1275
1276 while (isdigit(*(end-1)) && end > start)
1277 end--;
1278 len = end - start;
1279
1280 if (kstrtoint(end, 10, &id) < 0)
1281 continue;
1282
1283
1284 ap = dt_alloc(sizeof(*ap) + len + 1, 4);
1285 if (!ap)
1286 continue;
1287 ap->alias = start;
1288 of_alias_add(ap, np, id, start, len);
1289 }
1290}
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300int of_alias_get_id(struct device_node *np, const char *stem)
1301{
1302 struct alias_prop *app;
1303 int id = -ENODEV;
1304
1305 mutex_lock(&of_aliases_mutex);
1306 list_for_each_entry(app, &aliases_lookup, link) {
1307 if (strcmp(app->stem, stem) != 0)
1308 continue;
1309
1310 if (np == app->np) {
1311 id = app->id;
1312 break;
1313 }
1314 }
1315 mutex_unlock(&of_aliases_mutex);
1316
1317 return id;
1318}
1319EXPORT_SYMBOL_GPL(of_alias_get_id);
1320
1321const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
1322 u32 *pu)
1323{
1324 const void *curv = cur;
1325
1326 if (!prop)
1327 return NULL;
1328
1329 if (!cur) {
1330 curv = prop->value;
1331 goto out_val;
1332 }
1333
1334 curv += sizeof(*cur);
1335 if (curv >= prop->value + prop->length)
1336 return NULL;
1337
1338out_val:
1339 *pu = be32_to_cpup(curv);
1340 return curv;
1341}
1342EXPORT_SYMBOL_GPL(of_prop_next_u32);
1343
1344const char *of_prop_next_string(struct property *prop, const char *cur)
1345{
1346 const void *curv = cur;
1347
1348 if (!prop)
1349 return NULL;
1350
1351 if (!cur)
1352 return prop->value;
1353
1354 curv += strlen(cur) + 1;
1355 if (curv >= prop->value + prop->length)
1356 return NULL;
1357
1358 return curv;
1359}
1360EXPORT_SYMBOL_GPL(of_prop_next_string);
1361