]> Git Repo - u-boot.git/blob - drivers/core/ofnode.c
Merge branch 'master' of https://source.denx.de/u-boot/custodians/u-boot-sh
[u-boot.git] / drivers / core / ofnode.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2017 Google, Inc
4  * Written by Simon Glass <[email protected]>
5  */
6
7 #define LOG_CATEGORY    LOGC_DT
8
9 #include <dm.h>
10 #include <fdtdec.h>
11 #include <fdt_support.h>
12 #include <log.h>
13 #include <malloc.h>
14 #include <of_live.h>
15 #include <linux/libfdt.h>
16 #include <dm/of_access.h>
17 #include <dm/of_addr.h>
18 #include <dm/ofnode.h>
19 #include <dm/util.h>
20 #include <linux/err.h>
21 #include <linux/ioport.h>
22 #include <asm/global_data.h>
23
24 DECLARE_GLOBAL_DATA_PTR;
25
26 #if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)
27 static void *oftree_list[CONFIG_OFNODE_MULTI_TREE_MAX];
28 static int oftree_count;
29
30 void oftree_reset(void)
31 {
32         if (gd->flags & GD_FLG_RELOC) {
33                 oftree_count = 0;
34                 oftree_list[oftree_count++] = (void *)gd->fdt_blob;
35         }
36 }
37
38 static int oftree_find(const void *fdt)
39 {
40         int i;
41
42         for (i = 0; i < oftree_count; i++) {
43                 if (fdt == oftree_list[i])
44                         return i;
45         }
46
47         return -1;
48 }
49
50 static int check_tree_count(void)
51 {
52         if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) {
53                 log_warning("Too many registered device trees (max %d)\n",
54                             CONFIG_OFNODE_MULTI_TREE_MAX);
55                 return -E2BIG;
56         }
57
58         return 0;
59 }
60
61 static oftree oftree_ensure(void *fdt)
62 {
63         oftree tree;
64         int i;
65
66         if (of_live_active()) {
67                 struct device_node *root;
68                 int ret;
69
70                 ret = unflatten_device_tree(fdt, &root);
71                 if (ret) {
72                         log_err("Failed to create live tree: err=%d\n", ret);
73                         return oftree_null();
74                 }
75                 tree = oftree_from_np(root);
76
77                 return tree;
78         }
79
80         if (gd->flags & GD_FLG_RELOC) {
81                 i = oftree_find(fdt);
82                 if (i == -1) {
83                         if (check_tree_count())
84                                 return oftree_null();
85
86                         if (fdt_check_header(fdt)) {
87                                 log_err("Invalid device tree blob header\n");
88                                 return oftree_null();
89                         }
90
91                         /* register the new tree */
92                         i = oftree_count++;
93                         oftree_list[i] = fdt;
94                         log_debug("oftree: registered tree %d: %p\n", i, fdt);
95                 }
96         } else {
97                 if (fdt != gd->fdt_blob) {
98                         log_debug("Only the control FDT can be accessed before relocation\n");
99                         return oftree_null();
100                 }
101         }
102
103         tree.fdt = fdt;
104
105         return tree;
106 }
107
108 int oftree_new(oftree *treep)
109 {
110         oftree tree = oftree_null();
111         int ret;
112
113         if (of_live_active()) {
114                 struct device_node *root;
115
116                 ret = of_live_create_empty(&root);
117                 if (ret)
118                         return log_msg_ret("liv", ret);
119                 tree = oftree_from_np(root);
120         } else {
121                 const int size = 4096;
122                 void *fdt;
123
124                 ret = check_tree_count();
125                 if (ret)
126                         return log_msg_ret("fla", ret);
127
128                 /* register the new tree with a small size */
129                 fdt = malloc(size);
130                 if (!fdt)
131                         return log_msg_ret("fla", -ENOMEM);
132                 ret = fdt_create_empty_tree(fdt, size);
133                 if (ret)
134                         return log_msg_ret("fla", -EINVAL);
135                 oftree_list[oftree_count++] = fdt;
136                 tree.fdt = fdt;
137         }
138         *treep = tree;
139
140         return 0;
141 }
142
143 void oftree_dispose(oftree tree)
144 {
145         if (of_live_active())
146                 of_live_free(tree.np);
147 }
148
149 void *ofnode_lookup_fdt(ofnode node)
150 {
151         if (gd->flags & GD_FLG_RELOC) {
152                 uint i = OFTREE_TREE_ID(node.of_offset);
153
154                 if (i >= oftree_count) {
155                         log_debug("Invalid tree ID %x\n", i);
156                         return NULL;
157                 }
158
159                 return oftree_list[i];
160         } else {
161                 return (void *)gd->fdt_blob;
162         }
163 }
164
165 void *ofnode_to_fdt(ofnode node)
166 {
167 #ifdef OF_CHECKS
168         if (of_live_active())
169                 return NULL;
170 #endif
171         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && ofnode_valid(node))
172                 return ofnode_lookup_fdt(node);
173
174         /* Use the control FDT by default */
175         return (void *)gd->fdt_blob;
176 }
177
178 /**
179  * ofnode_to_offset() - convert an ofnode to a flat DT offset
180  *
181  * This cannot be called if the reference contains a node pointer.
182  *
183  * @node: Reference containing offset (possibly invalid)
184  * Return: DT offset (can be -1)
185  */
186 int ofnode_to_offset(ofnode node)
187 {
188 #ifdef OF_CHECKS
189         if (of_live_active())
190                 return -1;
191 #endif
192         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && node.of_offset >= 0)
193                 return OFTREE_OFFSET(node.of_offset);
194
195         return node.of_offset;
196 }
197
198 oftree oftree_from_fdt(void *fdt)
199 {
200         oftree tree;
201
202         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE))
203                 return oftree_ensure(fdt);
204
205 #ifdef OF_CHECKS
206         if (of_live_active())
207                 return oftree_null();
208 #endif
209         tree.fdt = fdt;
210
211         return tree;
212 }
213
214 /**
215  * noffset_to_ofnode() - convert a DT offset to an ofnode
216  *
217  * @other_node: Node in the same tree to use as a reference
218  * @of_offset: DT offset (either valid, or -1)
219  * Return: reference to the associated DT offset
220  */
221 ofnode noffset_to_ofnode(ofnode other_node, int of_offset)
222 {
223         ofnode node;
224
225         if (of_live_active())
226                 node.np = NULL;
227         else if (!CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || of_offset < 0 ||
228                  !ofnode_valid(other_node))
229                 node.of_offset = of_offset;
230         else
231                 node.of_offset = OFTREE_MAKE_NODE(other_node.of_offset,
232                                                   of_offset);
233
234         return node;
235 }
236
237 #else /* !OFNODE_MULTI_TREE */
238
239 static inline int oftree_find(const void *fdt)
240 {
241         return 0;
242 }
243
244 int oftree_new(oftree *treep)
245 {
246         return -ENOSYS;
247 }
248
249 #endif /* OFNODE_MULTI_TREE */
250
251 int oftree_to_fdt(oftree tree, struct abuf *buf)
252 {
253         int ret;
254
255         if (of_live_active()) {
256                 ret = of_live_flatten(ofnode_to_np(oftree_root(tree)), buf);
257                 if (ret)
258                         return log_msg_ret("flt", ret);
259         } else {
260                 void *fdt = oftree_lookup_fdt(tree);
261
262                 abuf_init(buf);
263                 abuf_set(buf, fdt, fdt_totalsize(fdt));
264         }
265
266         return 0;
267 }
268
269 /**
270  * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree)
271  *
272  * Looks up the tree and returns an ofnode with the correct of_offset (i.e.
273  * containing the tree ID).
274  *
275  * If @offset is < 0 then this returns an ofnode with that offset and no tree
276  * ID.
277  *
278  * @tree: tree to check
279  * @offset: offset within that tree (can be < 0)
280  * @return node for that offset, with the correct ID
281  */
282 static ofnode ofnode_from_tree_offset(oftree tree, int offset)
283 {
284         ofnode node;
285
286         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && offset >= 0) {
287                 int tree_id = oftree_find(tree.fdt);
288
289                 if (tree_id == -1)
290                         return ofnode_null();
291                 node.of_offset = OFTREE_NODE(tree_id, offset);
292         } else {
293                 node.of_offset = offset;
294         }
295
296         return node;
297 }
298
299 bool ofnode_name_eq(ofnode node, const char *name)
300 {
301         const char *node_name;
302         size_t len;
303
304         assert(ofnode_valid(node));
305
306         node_name = ofnode_get_name(node);
307         len = strchrnul(node_name, '@') - node_name;
308
309         return (strlen(name) == len) && !strncmp(node_name, name, len);
310 }
311
312 bool ofnode_name_eq_unit(ofnode node, const char *name)
313 {
314         const char *node_name, *p;
315         int len;
316
317         assert(ofnode_valid(node));
318
319         node_name = ofnode_get_name(node);
320
321         /* check the whole name */
322         if (!strcmp(node_name, name))
323                 return true;
324
325         /* if @name has no unit address, try the node name without it */
326         len = strlen(name);
327         p = strchr(node_name, '@');
328         if (p && !strchr(name, '@') && len == p - node_name &&
329             !strncmp(node_name, name, len))
330                 return true;
331
332         return false;
333 }
334
335 int ofnode_read_u8(ofnode node, const char *propname, u8 *outp)
336 {
337         const u8 *cell;
338         int len;
339
340         assert(ofnode_valid(node));
341         log_debug("%s: %s: ", __func__, propname);
342
343         if (ofnode_is_np(node))
344                 return of_read_u8(ofnode_to_np(node), propname, outp);
345
346         cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
347                            &len);
348         if (!cell || len < sizeof(*cell)) {
349                 log_debug("(not found)\n");
350                 return -EINVAL;
351         }
352         *outp = *cell;
353         log_debug("%#x (%u)\n", *outp, *outp);
354
355         return 0;
356 }
357
358 u8 ofnode_read_u8_default(ofnode node, const char *propname, u8 def)
359 {
360         assert(ofnode_valid(node));
361         ofnode_read_u8(node, propname, &def);
362
363         return def;
364 }
365
366 int ofnode_read_u16(ofnode node, const char *propname, u16 *outp)
367 {
368         const fdt16_t *cell;
369         int len;
370
371         assert(ofnode_valid(node));
372         log_debug("%s: %s: ", __func__, propname);
373
374         if (ofnode_is_np(node))
375                 return of_read_u16(ofnode_to_np(node), propname, outp);
376
377         cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
378                            &len);
379         if (!cell || len < sizeof(*cell)) {
380                 log_debug("(not found)\n");
381                 return -EINVAL;
382         }
383         *outp = be16_to_cpup(cell);
384         log_debug("%#x (%u)\n", *outp, *outp);
385
386         return 0;
387 }
388
389 u16 ofnode_read_u16_default(ofnode node, const char *propname, u16 def)
390 {
391         assert(ofnode_valid(node));
392         ofnode_read_u16(node, propname, &def);
393
394         return def;
395 }
396
397 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
398 {
399         return ofnode_read_u32_index(node, propname, 0, outp);
400 }
401
402 u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
403 {
404         assert(ofnode_valid(node));
405         ofnode_read_u32_index(node, propname, 0, &def);
406
407         return def;
408 }
409
410 int ofnode_read_u32_index(ofnode node, const char *propname, int index,
411                           u32 *outp)
412 {
413         const fdt32_t *cell;
414         int len;
415
416         assert(ofnode_valid(node));
417         log_debug("%s: %s: ", __func__, propname);
418
419         if (ofnode_is_np(node))
420                 return of_read_u32_index(ofnode_to_np(node), propname, index,
421                                          outp);
422
423         cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
424                            propname, &len);
425         if (!cell) {
426                 log_debug("(not found)\n");
427                 return -EINVAL;
428         }
429
430         if (len < (sizeof(int) * (index + 1))) {
431                 log_debug("(not large enough)\n");
432                 return -EOVERFLOW;
433         }
434
435         *outp = fdt32_to_cpu(cell[index]);
436         log_debug("%#x (%u)\n", *outp, *outp);
437
438         return 0;
439 }
440
441 int ofnode_read_u64_index(ofnode node, const char *propname, int index,
442                           u64 *outp)
443 {
444         const fdt64_t *cell;
445         int len;
446
447         assert(ofnode_valid(node));
448
449         if (ofnode_is_np(node))
450                 return of_read_u64_index(ofnode_to_np(node), propname, index,
451                                          outp);
452
453         cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
454                            propname, &len);
455         if (!cell) {
456                 log_debug("(not found)\n");
457                 return -EINVAL;
458         }
459
460         if (len < (sizeof(u64) * (index + 1))) {
461                 log_debug("(not large enough)\n");
462                 return -EOVERFLOW;
463         }
464
465         *outp = fdt64_to_cpu(cell[index]);
466         log_debug("%#llx (%llu)\n", *outp, *outp);
467
468         return 0;
469 }
470
471 u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
472                                   u32 def)
473 {
474         assert(ofnode_valid(node));
475         ofnode_read_u32_index(node, propname, index, &def);
476
477         return def;
478 }
479
480 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
481 {
482         assert(ofnode_valid(node));
483         ofnode_read_u32(node, propname, (u32 *)&def);
484
485         return def;
486 }
487
488 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
489 {
490         const unaligned_fdt64_t *cell;
491         int len;
492
493         assert(ofnode_valid(node));
494         log_debug("%s: %s: ", __func__, propname);
495
496         if (ofnode_is_np(node))
497                 return of_read_u64(ofnode_to_np(node), propname, outp);
498
499         cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
500                            propname, &len);
501         if (!cell || len < sizeof(*cell)) {
502                 log_debug("(not found)\n");
503                 return -EINVAL;
504         }
505         *outp = fdt64_to_cpu(cell[0]);
506         log_debug("%#llx (%llu)\n", (unsigned long long)*outp,
507                   (unsigned long long)*outp);
508
509         return 0;
510 }
511
512 u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
513 {
514         assert(ofnode_valid(node));
515         ofnode_read_u64(node, propname, &def);
516
517         return def;
518 }
519
520 bool ofnode_read_bool(ofnode node, const char *propname)
521 {
522         bool prop;
523
524         assert(ofnode_valid(node));
525         log_debug("%s: %s: ", __func__, propname);
526
527         prop = ofnode_has_property(node, propname);
528
529         log_debug("%s\n", prop ? "true" : "false");
530
531         return prop ? true : false;
532 }
533
534 const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
535 {
536         const char *val = NULL;
537         int len;
538
539         assert(ofnode_valid(node));
540         log_debug("%s: %s: ", __func__, propname);
541
542         if (ofnode_is_np(node)) {
543                 struct property *prop = of_find_property(
544                                 ofnode_to_np(node), propname, &len);
545
546                 if (prop) {
547                         val = prop->value;
548                         len = prop->length;
549                 }
550         } else {
551                 val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
552                                   propname, &len);
553         }
554         if (!val) {
555                 log_debug("<not found>\n");
556                 if (sizep)
557                         *sizep = -FDT_ERR_NOTFOUND;
558                 return NULL;
559         }
560         if (sizep)
561                 *sizep = len;
562
563         return val;
564 }
565
566 const char *ofnode_read_string(ofnode node, const char *propname)
567 {
568         const char *str;
569         int len;
570
571         str = ofnode_read_prop(node, propname, &len);
572         if (!str)
573                 return NULL;
574
575         if (strnlen(str, len) >= len) {
576                 dm_warn("<invalid>\n");
577                 return NULL;
578         }
579         log_debug("%s\n", str);
580
581         return str;
582 }
583
584 int ofnode_read_size(ofnode node, const char *propname)
585 {
586         int len;
587
588         if (!ofnode_read_prop(node, propname, &len))
589                 return -EINVAL;
590
591         return len;
592 }
593
594 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
595 {
596         ofnode subnode;
597
598         assert(ofnode_valid(node));
599         log_debug("%s: %s: ", __func__, subnode_name);
600
601         if (ofnode_is_np(node)) {
602                 subnode = ofnode_find_subnode_unit(node, subnode_name);
603         } else {
604                 /* special case to avoid code-size increase */
605                 int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
606                                 ofnode_to_offset(node), subnode_name);
607                 subnode = noffset_to_ofnode(node, ooffset);
608         }
609         log_debug("%s\n", ofnode_valid(subnode) ?
610                   ofnode_get_name(subnode) : "<none>");
611
612         return subnode;
613 }
614
615 ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name)
616 {
617         ofnode subnode, found = ofnode_null();
618
619         assert(ofnode_valid(node));
620         log_debug("%s: ", subnode_name);
621
622         ofnode_for_each_subnode(subnode, node) {
623                 if (ofnode_name_eq_unit(subnode, subnode_name)) {
624                         found = subnode;
625                         break;
626                 }
627         }
628
629         log_debug("%s\n", ofnode_valid(found) ?
630                   ofnode_get_name(found) : "<none>");
631
632         return found;
633 }
634
635 int ofnode_read_u32_array(ofnode node, const char *propname,
636                           u32 *out_values, size_t sz)
637 {
638         assert(ofnode_valid(node));
639         log_debug("%s: %s: ", __func__, propname);
640
641         if (ofnode_is_np(node)) {
642                 return of_read_u32_array(ofnode_to_np(node), propname,
643                                          out_values, sz);
644         } else {
645                 int ret;
646
647                 ret = fdtdec_get_int_array(ofnode_to_fdt(node),
648                                            ofnode_to_offset(node), propname,
649                                            out_values, sz);
650
651                 /* get the error right, but space is more important in SPL */
652                 if (!IS_ENABLED(CONFIG_XPL_BUILD)) {
653                         if (ret == -FDT_ERR_NOTFOUND)
654                                 return -EINVAL;
655                         else if (ret == -FDT_ERR_BADLAYOUT)
656                                 return -EOVERFLOW;
657                 }
658                 return ret;
659         }
660 }
661
662 #if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
663 bool ofnode_is_enabled(ofnode node)
664 {
665         if (ofnode_is_np(node)) {
666                 return of_device_is_available(ofnode_to_np(node));
667         } else {
668                 return fdtdec_get_is_enabled(ofnode_to_fdt(node),
669                                              ofnode_to_offset(node));
670         }
671 }
672
673 ofnode ofnode_first_subnode(ofnode node)
674 {
675         assert(ofnode_valid(node));
676         if (ofnode_is_np(node))
677                 return np_to_ofnode(node.np->child);
678
679         return noffset_to_ofnode(node,
680                 fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
681 }
682
683 ofnode ofnode_next_subnode(ofnode node)
684 {
685         assert(ofnode_valid(node));
686         if (ofnode_is_np(node))
687                 return np_to_ofnode(node.np->sibling);
688
689         return noffset_to_ofnode(node,
690                 fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
691 }
692 #endif /* !DM_INLINE_OFNODE */
693
694 ofnode ofnode_get_parent(ofnode node)
695 {
696         ofnode parent;
697
698         assert(ofnode_valid(node));
699         if (ofnode_is_np(node))
700                 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
701         else
702                 parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node),
703                                                      ofnode_to_offset(node));
704
705         return parent;
706 }
707
708 const char *ofnode_get_name(ofnode node)
709 {
710         if (!ofnode_valid(node)) {
711                 dm_warn("%s node not valid\n", __func__);
712                 return NULL;
713         }
714
715         if (ofnode_is_np(node))
716                 return node.np->name;
717
718         return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL);
719 }
720
721 int ofnode_get_path(ofnode node, char *buf, int buflen)
722 {
723         assert(ofnode_valid(node));
724
725         if (ofnode_is_np(node)) {
726                 if (strlen(node.np->full_name) >= buflen)
727                         return -ENOSPC;
728
729                 strcpy(buf, node.np->full_name);
730
731                 return 0;
732         } else {
733                 int res;
734
735                 res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf,
736                                    buflen);
737                 if (!res)
738                         return res;
739                 else if (res == -FDT_ERR_NOSPACE)
740                         return -ENOSPC;
741                 else
742                         return -EINVAL;
743         }
744 }
745
746 ofnode ofnode_get_by_phandle(uint phandle)
747 {
748         ofnode node;
749
750         if (of_live_active())
751                 node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle));
752         else
753                 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
754                                                             phandle);
755
756         return node;
757 }
758
759 ofnode oftree_get_by_phandle(oftree tree, uint phandle)
760 {
761         ofnode node;
762
763         if (of_live_active())
764                 node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle));
765         else
766                 node = ofnode_from_tree_offset(tree,
767                         fdt_node_offset_by_phandle(oftree_lookup_fdt(tree),
768                                                    phandle));
769
770         return node;
771 }
772
773 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
774                                                fdt_size_t *size, bool translate)
775 {
776         int na, ns;
777
778         if (size)
779                 *size = FDT_SIZE_T_NONE;
780
781         if (ofnode_is_np(node)) {
782                 const __be32 *prop_val;
783                 u64 size64;
784                 uint flags;
785
786                 prop_val = of_get_address(ofnode_to_np(node), index, &size64,
787                                           &flags);
788                 if (!prop_val)
789                         return FDT_ADDR_T_NONE;
790
791                 if (size)
792                         *size = size64;
793
794                 ns = of_n_size_cells(ofnode_to_np(node));
795
796                 if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
797                         return of_translate_address(ofnode_to_np(node), prop_val);
798                 } else {
799                         na = of_n_addr_cells(ofnode_to_np(node));
800                         return of_read_number(prop_val, na);
801                 }
802         } else {
803                 ofnode parent = ofnode_get_parent(node);
804                 na = ofnode_read_simple_addr_cells(parent);
805                 ns = ofnode_read_simple_size_cells(parent);
806                 return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node),
807                                                   ofnode_to_offset(node), "reg",
808                                                   index, na, ns, size,
809                                                   translate);
810         }
811 }
812
813 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
814 {
815         return __ofnode_get_addr_size_index(node, index, size, true);
816 }
817
818 fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
819                                               fdt_size_t *size)
820 {
821         return __ofnode_get_addr_size_index(node, index, size, false);
822 }
823
824 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
825 {
826         fdt_size_t size;
827
828         return ofnode_get_addr_size_index(node, index, &size);
829 }
830
831 fdt_addr_t ofnode_get_addr(ofnode node)
832 {
833         return ofnode_get_addr_index(node, 0);
834 }
835
836 fdt_size_t ofnode_get_size(ofnode node)
837 {
838         fdt_size_t size;
839
840         ofnode_get_addr_size_index(node, 0, &size);
841
842         return size;
843 }
844
845 int ofnode_stringlist_search(ofnode node, const char *property,
846                              const char *string)
847 {
848         if (ofnode_is_np(node)) {
849                 return of_property_match_string(ofnode_to_np(node),
850                                                 property, string);
851         } else {
852                 int ret;
853
854                 ret = fdt_stringlist_search(ofnode_to_fdt(node),
855                                             ofnode_to_offset(node), property,
856                                             string);
857                 if (ret == -FDT_ERR_NOTFOUND)
858                         return -ENODATA;
859                 else if (ret < 0)
860                         return -EINVAL;
861
862                 return ret;
863         }
864 }
865
866 int ofnode_read_string_index(ofnode node, const char *property, int index,
867                              const char **outp)
868 {
869         if (ofnode_is_np(node)) {
870                 return of_property_read_string_index(ofnode_to_np(node),
871                                                      property, index, outp);
872         } else {
873                 int len;
874
875                 *outp = fdt_stringlist_get(ofnode_to_fdt(node),
876                                            ofnode_to_offset(node),
877                                            property, index, &len);
878                 if (len < 0)
879                         return -EINVAL;
880                 return 0;
881         }
882 }
883
884 int ofnode_read_string_count(ofnode node, const char *property)
885 {
886         if (ofnode_is_np(node)) {
887                 return of_property_count_strings(ofnode_to_np(node), property);
888         } else {
889                 return fdt_stringlist_count(ofnode_to_fdt(node),
890                                             ofnode_to_offset(node), property);
891         }
892 }
893
894 int ofnode_read_string_list(ofnode node, const char *property,
895                             const char ***listp)
896 {
897         const char **prop;
898         int count;
899         int i;
900
901         *listp = NULL;
902         count = ofnode_read_string_count(node, property);
903         if (count < 0)
904                 return count;
905         if (!count)
906                 return 0;
907
908         prop = calloc(count + 1, sizeof(char *));
909         if (!prop)
910                 return -ENOMEM;
911
912         for (i = 0; i < count; i++)
913                 ofnode_read_string_index(node, property, i, &prop[i]);
914         prop[count] = NULL;
915         *listp = prop;
916
917         return count;
918 }
919
920 ofnode ofnode_parse_phandle(ofnode node, const char *phandle_name,
921                             int index)
922 {
923         ofnode phandle;
924
925         if (ofnode_is_np(node)) {
926                 struct device_node *np;
927
928                 np = of_parse_phandle(ofnode_to_np(node), phandle_name,
929                                       index);
930                 if (!np)
931                         return ofnode_null();
932
933                 phandle = np_to_ofnode(np);
934         } else {
935                 struct fdtdec_phandle_args args;
936
937                 if (fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
938                                                    ofnode_to_offset(node),
939                                                    phandle_name, NULL,
940                                                    0, index, &args))
941                         return ofnode_null();
942
943                 phandle = offset_to_ofnode(args.node);
944         }
945
946         return phandle;
947 }
948
949 ofnode oftree_parse_phandle(oftree tree, ofnode node, const char *phandle_name,
950                             int index)
951 {
952         ofnode phandle;
953
954         if (ofnode_is_np(node)) {
955                 struct device_node *np;
956
957                 np = of_root_parse_phandle(tree.np, ofnode_to_np(node),
958                                            phandle_name, index);
959                 if (!np)
960                         return ofnode_null();
961
962                 phandle = np_to_ofnode(np);
963         } else {
964                 struct fdtdec_phandle_args args;
965
966                 if (fdtdec_parse_phandle_with_args(tree.fdt,
967                                                    ofnode_to_offset(node),
968                                                    phandle_name, NULL,
969                                                    0, index, &args))
970                         return ofnode_null();
971
972                 phandle = noffset_to_ofnode(node, args.node);
973         }
974
975         return phandle;
976 }
977
978 static void ofnode_from_fdtdec_phandle_args(ofnode node, struct fdtdec_phandle_args *in,
979                                             struct ofnode_phandle_args *out)
980 {
981         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
982         out->node = noffset_to_ofnode(node, in->node);
983         out->args_count = in->args_count;
984         memcpy(out->args, in->args, sizeof(out->args));
985 }
986
987 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
988                                         struct ofnode_phandle_args *out)
989 {
990         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
991         out->node = np_to_ofnode(in->np);
992         out->args_count = in->args_count;
993         memcpy(out->args, in->args, sizeof(out->args));
994 }
995
996 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
997                                    const char *cells_name, int cell_count,
998                                    int index,
999                                    struct ofnode_phandle_args *out_args)
1000 {
1001         if (ofnode_is_np(node)) {
1002                 struct of_phandle_args args;
1003                 int ret;
1004
1005                 ret = of_parse_phandle_with_args(ofnode_to_np(node),
1006                                                  list_name, cells_name,
1007                                                  cell_count, index,
1008                                                  &args);
1009                 if (ret)
1010                         return ret;
1011                 ofnode_from_of_phandle_args(&args, out_args);
1012         } else {
1013                 struct fdtdec_phandle_args args;
1014                 int ret;
1015
1016                 ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
1017                                                      ofnode_to_offset(node),
1018                                                      list_name, cells_name,
1019                                                      cell_count, index, &args);
1020                 if (ret)
1021                         return ret;
1022                 ofnode_from_fdtdec_phandle_args(node, &args, out_args);
1023         }
1024
1025         return 0;
1026 }
1027
1028 int oftree_parse_phandle_with_args(oftree tree, ofnode node, const char *list_name,
1029                                    const char *cells_name, int cell_count,
1030                                    int index,
1031                                    struct ofnode_phandle_args *out_args)
1032 {
1033         if (ofnode_is_np(node)) {
1034                 struct of_phandle_args args;
1035                 int ret;
1036
1037                 ret = of_root_parse_phandle_with_args(tree.np,
1038                                                       ofnode_to_np(node),
1039                                                       list_name, cells_name,
1040                                                       cell_count, index,
1041                                                       &args);
1042                 if (ret)
1043                         return ret;
1044                 ofnode_from_of_phandle_args(&args, out_args);
1045         } else {
1046                 struct fdtdec_phandle_args args;
1047                 int ret;
1048
1049                 ret = fdtdec_parse_phandle_with_args(tree.fdt,
1050                                                      ofnode_to_offset(node),
1051                                                      list_name, cells_name,
1052                                                      cell_count, index, &args);
1053                 if (ret)
1054                         return ret;
1055                 ofnode_from_fdtdec_phandle_args(node, &args, out_args);
1056         }
1057
1058         return 0;
1059 }
1060
1061 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
1062                                    const char *cells_name, int cell_count)
1063 {
1064         if (ofnode_is_np(node))
1065                 return of_count_phandle_with_args(ofnode_to_np(node),
1066                                 list_name, cells_name, cell_count);
1067         else
1068                 return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
1069                                 ofnode_to_offset(node), list_name, cells_name,
1070                                 cell_count, -1, NULL);
1071 }
1072
1073 int oftree_count_phandle_with_args(oftree tree, ofnode node, const char *list_name,
1074                                    const char *cells_name, int cell_count)
1075 {
1076         if (ofnode_is_np(node))
1077                 return of_root_count_phandle_with_args(tree.np, ofnode_to_np(node),
1078                                 list_name, cells_name, cell_count);
1079         else
1080                 return fdtdec_parse_phandle_with_args(tree.fdt,
1081                                 ofnode_to_offset(node), list_name, cells_name,
1082                                 cell_count, -1, NULL);
1083 }
1084
1085 ofnode ofnode_path(const char *path)
1086 {
1087         if (of_live_active())
1088                 return np_to_ofnode(of_find_node_by_path(path));
1089         else
1090                 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
1091 }
1092
1093 ofnode oftree_root(oftree tree)
1094 {
1095         if (of_live_active()) {
1096                 return np_to_ofnode(tree.np);
1097         } else {
1098                 return ofnode_from_tree_offset(tree, 0);
1099         }
1100 }
1101
1102 ofnode oftree_path(oftree tree, const char *path)
1103 {
1104         if (of_live_active()) {
1105                 return np_to_ofnode(of_find_node_opts_by_path(tree.np, path,
1106                                                               NULL));
1107         } else if (*path != '/' && tree.fdt != gd->fdt_blob) {
1108                 return ofnode_null();  /* Aliases only on control FDT */
1109         } else {
1110                 int offset = fdt_path_offset(tree.fdt, path);
1111
1112                 return ofnode_from_tree_offset(tree, offset);
1113         }
1114 }
1115
1116 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
1117 {
1118         ofnode chosen_node;
1119
1120         chosen_node = ofnode_path("/chosen");
1121
1122         return ofnode_read_prop(chosen_node, propname, sizep);
1123 }
1124
1125 const char *ofnode_read_chosen_string(const char *propname)
1126 {
1127         return ofnode_read_chosen_prop(propname, NULL);
1128 }
1129
1130 ofnode ofnode_get_chosen_node(const char *name)
1131 {
1132         const char *prop;
1133
1134         prop = ofnode_read_chosen_prop(name, NULL);
1135         if (!prop)
1136                 return ofnode_null();
1137
1138         return ofnode_path(prop);
1139 }
1140
1141 int ofnode_read_baud(void)
1142 {
1143         const char *str, *p;
1144         u32 baud;
1145
1146         str = ofnode_read_chosen_string("stdout-path");
1147         if (!str)
1148                 return -EINVAL;
1149
1150         /* Parse string serial0:115200n8 */
1151         p = strchr(str, ':');
1152         if (!p)
1153                 return -EINVAL;
1154
1155         baud = dectoul(p + 1, NULL);
1156         return baud;
1157 }
1158
1159 const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
1160 {
1161         ofnode node;
1162
1163         node = ofnode_path("/aliases");
1164
1165         return ofnode_read_prop(node, propname, sizep);
1166 }
1167
1168 ofnode ofnode_get_aliases_node(const char *name)
1169 {
1170         const char *prop;
1171
1172         prop = ofnode_read_aliases_prop(name, NULL);
1173         if (!prop)
1174                 return ofnode_null();
1175
1176         log_debug("%s: node_path: %s\n", __func__, prop);
1177
1178         return ofnode_path(prop);
1179 }
1180
1181 int ofnode_get_child_count(ofnode parent)
1182 {
1183         ofnode child;
1184         int num = 0;
1185
1186         ofnode_for_each_subnode(child, parent)
1187                 num++;
1188
1189         return num;
1190 }
1191
1192 static int decode_timing_property(ofnode node, const char *name,
1193                                   struct timing_entry *result)
1194 {
1195         int length, ret = 0;
1196
1197         length = ofnode_read_size(node, name);
1198         if (length < 0) {
1199                 dm_warn("%s: could not find property %s\n",
1200                         ofnode_get_name(node), name);
1201                 return length;
1202         }
1203
1204         if (length == sizeof(u32)) {
1205                 result->typ = ofnode_read_u32_default(node, name, 0);
1206                 result->min = result->typ;
1207                 result->max = result->typ;
1208         } else {
1209                 ret = ofnode_read_u32_array(node, name, &result->min, 3);
1210         }
1211
1212         return ret;
1213 }
1214
1215 int ofnode_decode_display_timing(ofnode parent, int index,
1216                                  struct display_timing *dt)
1217 {
1218         int i;
1219         ofnode timings, node;
1220         u32 val = 0;
1221         int ret = 0;
1222
1223         timings = ofnode_find_subnode(parent, "display-timings");
1224         if (!ofnode_valid(timings))
1225                 return -EINVAL;
1226
1227         i = 0;
1228         ofnode_for_each_subnode(node, timings) {
1229                 if (i++ == index)
1230                         break;
1231         }
1232
1233         if (!ofnode_valid(node))
1234                 return -EINVAL;
1235
1236         memset(dt, 0, sizeof(*dt));
1237
1238         ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
1239         ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
1240         ret |= decode_timing_property(node, "hactive", &dt->hactive);
1241         ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
1242         ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
1243         ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
1244         ret |= decode_timing_property(node, "vactive", &dt->vactive);
1245         ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
1246         ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
1247
1248         dt->flags = 0;
1249         val = ofnode_read_u32_default(node, "vsync-active", -1);
1250         if (val != -1) {
1251                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
1252                                 DISPLAY_FLAGS_VSYNC_LOW;
1253         }
1254         val = ofnode_read_u32_default(node, "hsync-active", -1);
1255         if (val != -1) {
1256                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
1257                                 DISPLAY_FLAGS_HSYNC_LOW;
1258         }
1259         val = ofnode_read_u32_default(node, "de-active", -1);
1260         if (val != -1) {
1261                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
1262                                 DISPLAY_FLAGS_DE_LOW;
1263         }
1264         val = ofnode_read_u32_default(node, "pixelclk-active", -1);
1265         if (val != -1) {
1266                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
1267                                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
1268         }
1269
1270         if (ofnode_read_bool(node, "interlaced"))
1271                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
1272         if (ofnode_read_bool(node, "doublescan"))
1273                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
1274         if (ofnode_read_bool(node, "doubleclk"))
1275                 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
1276
1277         return ret;
1278 }
1279
1280 int ofnode_decode_panel_timing(ofnode parent,
1281                                struct display_timing *dt)
1282 {
1283         ofnode timings;
1284         u32 val = 0;
1285         int ret = 0;
1286
1287         timings = ofnode_find_subnode(parent, "panel-timing");
1288         if (!ofnode_valid(timings))
1289                 return -EINVAL;
1290         memset(dt, 0, sizeof(*dt));
1291         ret |= decode_timing_property(timings, "hback-porch", &dt->hback_porch);
1292         ret |= decode_timing_property(timings, "hfront-porch", &dt->hfront_porch);
1293         ret |= decode_timing_property(timings, "hactive", &dt->hactive);
1294         ret |= decode_timing_property(timings, "hsync-len", &dt->hsync_len);
1295         ret |= decode_timing_property(timings, "vback-porch", &dt->vback_porch);
1296         ret |= decode_timing_property(timings, "vfront-porch", &dt->vfront_porch);
1297         ret |= decode_timing_property(timings, "vactive", &dt->vactive);
1298         ret |= decode_timing_property(timings, "vsync-len", &dt->vsync_len);
1299         ret |= decode_timing_property(timings, "clock-frequency", &dt->pixelclock);
1300         dt->flags = 0;
1301         if (!ofnode_read_u32(timings, "vsync-active", &val)) {
1302                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
1303                     DISPLAY_FLAGS_VSYNC_LOW;
1304         }
1305         if (!ofnode_read_u32(timings, "hsync-active", &val)) {
1306                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
1307                     DISPLAY_FLAGS_HSYNC_LOW;
1308         }
1309         if (!ofnode_read_u32(timings, "de-active", &val)) {
1310                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
1311                     DISPLAY_FLAGS_DE_LOW;
1312         }
1313         if (!ofnode_read_u32(timings, "pixelclk-active", &val)) {
1314                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
1315                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
1316         }
1317         if (ofnode_read_bool(timings, "interlaced"))
1318                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
1319         if (ofnode_read_bool(timings, "doublescan"))
1320                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
1321         if (ofnode_read_bool(timings, "doubleclk"))
1322                 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
1323
1324         return ret;
1325 }
1326
1327 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
1328 {
1329         if (ofnode_is_np(node))
1330                 return of_get_property(ofnode_to_np(node), propname, lenp);
1331         else
1332                 return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1333                                    propname, lenp);
1334 }
1335
1336 bool ofnode_has_property(ofnode node, const char *propname)
1337 {
1338         if (ofnode_is_np(node))
1339                 return of_find_property(ofnode_to_np(node), propname, NULL);
1340         else
1341                 return ofnode_get_property(node, propname, NULL);
1342 }
1343
1344 int ofnode_first_property(ofnode node, struct ofprop *prop)
1345 {
1346         prop->node = node;
1347
1348         if (ofnode_is_np(node)) {
1349                 prop->prop = of_get_first_property(ofnode_to_np(prop->node));
1350                 if (!prop->prop)
1351                         return -FDT_ERR_NOTFOUND;
1352         } else {
1353                 prop->offset =
1354                         fdt_first_property_offset(ofnode_to_fdt(node),
1355                                                   ofnode_to_offset(prop->node));
1356                 if (prop->offset < 0)
1357                         return prop->offset;
1358         }
1359
1360         return 0;
1361 }
1362
1363 int ofnode_next_property(struct ofprop *prop)
1364 {
1365         if (ofnode_is_np(prop->node)) {
1366                 prop->prop = of_get_next_property(ofnode_to_np(prop->node),
1367                                                   prop->prop);
1368                 if (!prop->prop)
1369                         return -FDT_ERR_NOTFOUND;
1370         } else {
1371                 prop->offset =
1372                         fdt_next_property_offset(ofnode_to_fdt(prop->node),
1373                                                  prop->offset);
1374                 if (prop->offset  < 0)
1375                         return prop->offset;
1376         }
1377
1378         return 0;
1379 }
1380
1381 const void *ofprop_get_property(const struct ofprop *prop,
1382                                 const char **propname, int *lenp)
1383 {
1384         if (ofnode_is_np(prop->node))
1385                 return of_get_property_by_prop(ofnode_to_np(prop->node),
1386                                                prop->prop, propname, lenp);
1387         else
1388                 return fdt_getprop_by_offset(ofnode_to_fdt(prop->node),
1389                                              prop->offset,
1390                                              propname, lenp);
1391 }
1392
1393 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
1394                                 fdt_size_t *sizep)
1395 {
1396         if (ofnode_is_np(node)) {
1397                 int na, ns;
1398                 int psize;
1399                 const struct device_node *np = ofnode_to_np(node);
1400                 const __be32 *prop = of_get_property(np, property, &psize);
1401
1402                 if (!prop)
1403                         return FDT_ADDR_T_NONE;
1404                 na = of_n_addr_cells(np);
1405                 ns = of_n_size_cells(np);
1406                 *sizep = of_read_number(prop + na, ns);
1407
1408                 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
1409                         return of_translate_address(np, prop);
1410                 else
1411                         return of_read_number(prop, na);
1412         } else {
1413                 return fdtdec_get_addr_size(ofnode_to_fdt(node),
1414                                             ofnode_to_offset(node), property,
1415                                             sizep);
1416         }
1417 }
1418
1419 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
1420                                         size_t sz)
1421 {
1422         if (ofnode_is_np(node)) {
1423                 const struct device_node *np = ofnode_to_np(node);
1424                 int psize;
1425                 const __be32 *prop = of_get_property(np, propname, &psize);
1426
1427                 if (!prop || sz != psize)
1428                         return NULL;
1429                 return (uint8_t *)prop;
1430
1431         } else {
1432                 return fdtdec_locate_byte_array(ofnode_to_fdt(node),
1433                                 ofnode_to_offset(node), propname, sz);
1434         }
1435 }
1436
1437 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
1438                          const char *propname, struct fdt_pci_addr *addr,
1439                          fdt_size_t *size)
1440 {
1441         const fdt32_t *cell;
1442         int len;
1443         int ret = -ENOENT;
1444
1445         log_debug("%s: %s: ", __func__, propname);
1446
1447         /*
1448          * If we follow the pci bus bindings strictly, we should check
1449          * the value of the node's parent node's #address-cells and
1450          * #size-cells. They need to be 3 and 2 accordingly. However,
1451          * for simplicity we skip the check here.
1452          */
1453         cell = ofnode_get_property(node, propname, &len);
1454         if (!cell)
1455                 goto fail;
1456
1457         if ((len % FDT_PCI_REG_SIZE) == 0) {
1458                 int num = len / FDT_PCI_REG_SIZE;
1459                 int i;
1460
1461                 for (i = 0; i < num; i++) {
1462                         log_debug("pci address #%d: %08lx %08lx %08lx\n", i,
1463                                   (ulong)fdt32_to_cpu(cell[0]),
1464                                   (ulong)fdt32_to_cpu(cell[1]),
1465                                   (ulong)fdt32_to_cpu(cell[2]));
1466                         if ((fdt32_to_cpu(*cell) & type) == type) {
1467                                 const unaligned_fdt64_t *ptr;
1468
1469                                 addr->phys_hi = fdt32_to_cpu(cell[0]);
1470                                 addr->phys_mid = fdt32_to_cpu(cell[1]);
1471                                 addr->phys_lo = fdt32_to_cpu(cell[2]);
1472                                 ptr = (const unaligned_fdt64_t *)(cell + 3);
1473                                 if (size)
1474                                         *size = fdt64_to_cpu(*ptr);
1475                                 break;
1476                         }
1477
1478                         cell += FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS;
1479                 }
1480
1481                 if (i == num) {
1482                         ret = -ENXIO;
1483                         goto fail;
1484                 }
1485
1486                 return 0;
1487         }
1488
1489         ret = -EINVAL;
1490
1491 fail:
1492         log_debug("(not found)\n");
1493         return ret;
1494 }
1495
1496 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
1497 {
1498         const char *list, *end;
1499         int len;
1500
1501         list = ofnode_get_property(node, "compatible", &len);
1502         if (!list)
1503                 return -ENOENT;
1504
1505         end = list + len;
1506         while (list < end) {
1507                 len = strlen(list);
1508                 if (len >= strlen("pciVVVV,DDDD")) {
1509                         char *s = strstr(list, "pci");
1510
1511                         /*
1512                          * check if the string is something like pciVVVV,DDDD.RR
1513                          * or just pciVVVV,DDDD
1514                          */
1515                         if (s && s[7] == ',' &&
1516                             (s[12] == '.' || s[12] == 0)) {
1517                                 s += 3;
1518                                 *vendor = simple_strtol(s, NULL, 16);
1519
1520                                 s += 5;
1521                                 *device = simple_strtol(s, NULL, 16);
1522
1523                                 return 0;
1524                         }
1525                 }
1526                 list += (len + 1);
1527         }
1528
1529         return -ENOENT;
1530 }
1531
1532 int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
1533 {
1534         const char *list, *end;
1535         int len;
1536
1537         list = ofnode_get_property(node, "compatible", &len);
1538
1539         if (!list)
1540                 return -ENOENT;
1541
1542         end = list + len;
1543         while (list < end) {
1544                 len = strlen(list);
1545
1546                 if (len >= strlen("ethernet-phy-idVVVV.DDDD")) {
1547                         char *s = strstr(list, "ethernet-phy-id");
1548
1549                         /*
1550                          * check if the string is something like
1551                          * ethernet-phy-idVVVV.DDDD
1552                          */
1553                         if (s && s[19] == '.') {
1554                                 s += strlen("ethernet-phy-id");
1555                                 *vendor = simple_strtol(s, NULL, 16);
1556                                 s += 5;
1557                                 *device = simple_strtol(s, NULL, 16);
1558
1559                                 return 0;
1560                         }
1561                 }
1562                 list += (len + 1);
1563         }
1564
1565         return -ENOENT;
1566 }
1567
1568 int ofnode_read_addr_cells(ofnode node)
1569 {
1570         if (ofnode_is_np(node)) {
1571                 return of_n_addr_cells(ofnode_to_np(node));
1572         } else {
1573                 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1574                                                ofnode_to_offset(node));
1575
1576                 return fdt_address_cells(ofnode_to_fdt(node), parent);
1577         }
1578 }
1579
1580 int ofnode_read_size_cells(ofnode node)
1581 {
1582         if (ofnode_is_np(node)) {
1583                 return of_n_size_cells(ofnode_to_np(node));
1584         } else {
1585                 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1586                                                ofnode_to_offset(node));
1587
1588                 return fdt_size_cells(ofnode_to_fdt(node), parent);
1589         }
1590 }
1591
1592 int ofnode_read_simple_addr_cells(ofnode node)
1593 {
1594         if (ofnode_is_np(node))
1595                 return of_simple_addr_cells(ofnode_to_np(node));
1596         else
1597                 return fdt_address_cells(ofnode_to_fdt(node),
1598                                          ofnode_to_offset(node));
1599 }
1600
1601 int ofnode_read_simple_size_cells(ofnode node)
1602 {
1603         if (ofnode_is_np(node))
1604                 return of_simple_size_cells(ofnode_to_np(node));
1605         else
1606                 return fdt_size_cells(ofnode_to_fdt(node),
1607                                       ofnode_to_offset(node));
1608 }
1609
1610 bool ofnode_pre_reloc(ofnode node)
1611 {
1612 #if defined(CONFIG_XPL_BUILD) || defined(CONFIG_TPL_BUILD)
1613         /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
1614          * had property bootph-all or bootph-pre-sram/bootph-pre-ram.
1615          * They are removed in final dtb (fdtgrep 2nd pass)
1616          */
1617         return true;
1618 #else
1619         if (ofnode_read_bool(node, "bootph-all"))
1620                 return true;
1621         if (ofnode_read_bool(node, "bootph-some-ram"))
1622                 return true;
1623
1624         /*
1625          * In regular builds individual spl and tpl handling both
1626          * count as handled pre-relocation for later second init.
1627          */
1628         if (ofnode_read_bool(node, "bootph-pre-ram") ||
1629             ofnode_read_bool(node, "bootph-pre-sram"))
1630                 return gd->flags & GD_FLG_RELOC;
1631
1632         if (IS_ENABLED(CONFIG_OF_TAG_MIGRATE)) {
1633                 /* detect and handle old tags */
1634                 if (ofnode_read_bool(node, "u-boot,dm-pre-reloc") ||
1635                     ofnode_read_bool(node, "u-boot,dm-pre-proper") ||
1636                     ofnode_read_bool(node, "u-boot,dm-spl") ||
1637                     ofnode_read_bool(node, "u-boot,dm-tpl") ||
1638                     ofnode_read_bool(node, "u-boot,dm-vpl")) {
1639                         gd->flags |= GD_FLG_OF_TAG_MIGRATE;
1640                         return true;
1641                 }
1642         }
1643
1644         return false;
1645 #endif
1646 }
1647
1648 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
1649 {
1650         if (ofnode_is_np(node)) {
1651                 return of_address_to_resource(ofnode_to_np(node), index, res);
1652         } else {
1653                 struct fdt_resource fres;
1654                 int ret;
1655
1656                 ret = fdt_get_resource(ofnode_to_fdt(node),
1657                                        ofnode_to_offset(node),
1658                                        "reg", index, &fres);
1659                 if (ret < 0)
1660                         return -EINVAL;
1661                 memset(res, '\0', sizeof(*res));
1662                 res->start = fres.start;
1663                 res->end = fres.end;
1664
1665                 return 0;
1666         }
1667 }
1668
1669 int ofnode_read_resource_byname(ofnode node, const char *name,
1670                                 struct resource *res)
1671 {
1672         int index;
1673
1674         index = ofnode_stringlist_search(node, "reg-names", name);
1675         if (index < 0)
1676                 return index;
1677
1678         return ofnode_read_resource(node, index, res);
1679 }
1680
1681 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
1682 {
1683         if (ofnode_is_np(node))
1684                 return of_translate_address(ofnode_to_np(node), in_addr);
1685         else
1686                 return fdt_translate_address(ofnode_to_fdt(node),
1687                                              ofnode_to_offset(node), in_addr);
1688 }
1689
1690 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
1691 {
1692         if (ofnode_is_np(node))
1693                 return of_translate_dma_address(ofnode_to_np(node), in_addr);
1694         else
1695                 return fdt_translate_dma_address(ofnode_to_fdt(node),
1696                                                  ofnode_to_offset(node), in_addr);
1697 }
1698
1699 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
1700 {
1701         if (ofnode_is_np(node))
1702                 return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
1703         else
1704                 return fdt_get_dma_range(ofnode_to_fdt(node),
1705                                          ofnode_to_offset(node),
1706                                          cpu, bus, size);
1707 }
1708
1709 int ofnode_device_is_compatible(ofnode node, const char *compat)
1710 {
1711         if (ofnode_is_np(node))
1712                 return of_device_is_compatible(ofnode_to_np(node), compat,
1713                                                NULL, NULL);
1714         else
1715                 return !fdt_node_check_compatible(ofnode_to_fdt(node),
1716                                                   ofnode_to_offset(node),
1717                                                   compat);
1718 }
1719
1720 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1721 {
1722         if (of_live_active()) {
1723                 return np_to_ofnode(of_find_compatible_node(
1724                         (struct device_node *)ofnode_to_np(from), NULL,
1725                         compat));
1726         } else {
1727                 return noffset_to_ofnode(from,
1728                         fdt_node_offset_by_compatible(ofnode_to_fdt(from),
1729                                         ofnode_to_offset(from), compat));
1730         }
1731 }
1732
1733 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1734                             const void *propval, int proplen)
1735 {
1736         if (of_live_active()) {
1737                 return np_to_ofnode(of_find_node_by_prop_value(
1738                         (struct device_node *)ofnode_to_np(from), propname,
1739                         propval, proplen));
1740         } else {
1741                 return noffset_to_ofnode(from,
1742                          fdt_node_offset_by_prop_value(ofnode_to_fdt(from),
1743                                 ofnode_to_offset(from), propname, propval,
1744                                 proplen));
1745         }
1746 }
1747
1748 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
1749                       int len, bool copy)
1750 {
1751         int ret;
1752
1753         if (of_live_active()) {
1754                 void *newval;
1755
1756                 if (copy) {
1757                         newval = malloc(len);
1758                         if (!newval)
1759                                 return log_ret(-ENOMEM);
1760                         memcpy(newval, value, len);
1761                         value = newval;
1762                 }
1763                 ret = of_write_prop(ofnode_to_np(node), propname, len, value);
1764                 if (ret && copy)
1765                         free(newval);
1766                 return ret;
1767         } else {
1768                 ret = fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1769                                   propname, value, len);
1770                 if (ret)
1771                         return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL;
1772
1773                 return 0;
1774         }
1775 }
1776
1777 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1778 {
1779         assert(ofnode_valid(node));
1780
1781         log_debug("%s: %s = %s", __func__, propname, value);
1782
1783         return ofnode_write_prop(node, propname, value, strlen(value) + 1,
1784                                  false);
1785 }
1786
1787 int ofnode_write_u32(ofnode node, const char *propname, u32 value)
1788 {
1789         fdt32_t *val;
1790
1791         assert(ofnode_valid(node));
1792
1793         log_debug("%s = %x", propname, value);
1794         val = malloc(sizeof(*val));
1795         if (!val)
1796                 return -ENOMEM;
1797         *val = cpu_to_fdt32(value);
1798
1799         return ofnode_write_prop(node, propname, val, sizeof(value), true);
1800 }
1801
1802 int ofnode_write_u64(ofnode node, const char *propname, u64 value)
1803 {
1804         fdt64_t *val;
1805
1806         assert(ofnode_valid(node));
1807
1808         log_debug("%s = %llx", propname, (unsigned long long)value);
1809         val = malloc(sizeof(*val));
1810         if (!val)
1811                 return -ENOMEM;
1812         *val = cpu_to_fdt64(value);
1813
1814         return ofnode_write_prop(node, propname, val, sizeof(value), true);
1815 }
1816
1817 int ofnode_write_bool(ofnode node, const char *propname, bool value)
1818 {
1819         if (value)
1820                 return ofnode_write_prop(node, propname, NULL, 0, false);
1821         else
1822                 return ofnode_delete_prop(node, propname);
1823 }
1824
1825 int ofnode_delete_prop(ofnode node, const char *propname)
1826 {
1827         if (ofnode_is_np(node)) {
1828                 struct property *prop;
1829                 int len;
1830
1831                 prop = of_find_property(ofnode_to_np(node), propname, &len);
1832                 if (prop)
1833                         return of_remove_property(ofnode_to_np(node), prop);
1834                 return 0;
1835         } else {
1836                 return fdt_delprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1837                                    propname);
1838         }
1839 }
1840
1841 int ofnode_set_enabled(ofnode node, bool value)
1842 {
1843         assert(ofnode_valid(node));
1844
1845         if (value)
1846                 return ofnode_write_string(node, "status", "okay");
1847         else
1848                 return ofnode_write_string(node, "status", "disabled");
1849 }
1850
1851 bool ofnode_conf_read_bool(const char *prop_name)
1852 {
1853         ofnode node;
1854
1855         node = ofnode_path("/config");
1856         if (!ofnode_valid(node))
1857                 return false;
1858
1859         return ofnode_read_bool(node, prop_name);
1860 }
1861
1862 int ofnode_conf_read_int(const char *prop_name, int default_val)
1863 {
1864         ofnode node;
1865
1866         node = ofnode_path("/config");
1867         if (!ofnode_valid(node))
1868                 return default_val;
1869
1870         return ofnode_read_u32_default(node, prop_name, default_val);
1871 }
1872
1873 const char *ofnode_conf_read_str(const char *prop_name)
1874 {
1875         ofnode node;
1876
1877         node = ofnode_path("/config");
1878         if (!ofnode_valid(node))
1879                 return NULL;
1880
1881         return ofnode_read_string(node, prop_name);
1882 }
1883
1884 bool ofnode_options_read_bool(const char *prop_name)
1885 {
1886         ofnode uboot;
1887
1888         uboot = ofnode_path("/options/u-boot");
1889         if (!ofnode_valid(uboot))
1890                 return false;
1891
1892         return ofnode_read_bool(uboot, prop_name);
1893 }
1894
1895 int ofnode_options_read_int(const char *prop_name, int default_val)
1896 {
1897         ofnode uboot;
1898
1899         uboot = ofnode_path("/options/u-boot");
1900         if (!ofnode_valid(uboot))
1901                 return default_val;
1902
1903         return ofnode_read_u32_default(uboot, prop_name, default_val);
1904 }
1905
1906 const char *ofnode_options_read_str(const char *prop_name)
1907 {
1908         ofnode uboot;
1909
1910         uboot = ofnode_path("/options/u-boot");
1911         if (!ofnode_valid(uboot))
1912                 return NULL;
1913
1914         return ofnode_read_string(uboot, prop_name);
1915 }
1916
1917 int ofnode_options_get_by_phandle(const char *prop_name, ofnode *nodep)
1918 {
1919         ofnode uboot;
1920
1921         uboot = ofnode_path("/options/u-boot");
1922         if (!ofnode_valid(uboot))
1923                 return -EINVAL;
1924
1925         *nodep = ofnode_parse_phandle(uboot, prop_name, 0);
1926         if (!ofnode_valid(*nodep))
1927                 return -EINVAL;
1928
1929         return 0;
1930 }
1931
1932 int ofnode_read_bootscript_address(u64 *bootscr_address, u64 *bootscr_offset)
1933 {
1934         int ret;
1935         ofnode uboot;
1936
1937         *bootscr_address = 0;
1938         *bootscr_offset = 0;
1939
1940         uboot = ofnode_path("/options/u-boot");
1941         if (!ofnode_valid(uboot)) {
1942                 dm_warn("%s: Missing /u-boot node\n", __func__);
1943                 return -EINVAL;
1944         }
1945
1946         ret = ofnode_read_u64(uboot, "bootscr-address", bootscr_address);
1947         if (ret) {
1948                 ret = ofnode_read_u64(uboot, "bootscr-ram-offset",
1949                                       bootscr_offset);
1950                 if (ret)
1951                         return -EINVAL;
1952         }
1953
1954         return 0;
1955 }
1956
1957 int ofnode_read_bootscript_flash(u64 *bootscr_flash_offset,
1958                                  u64 *bootscr_flash_size)
1959 {
1960         int ret;
1961         ofnode uboot;
1962
1963         *bootscr_flash_offset = 0;
1964         *bootscr_flash_size = 0;
1965
1966         uboot = ofnode_path("/options/u-boot");
1967         if (!ofnode_valid(uboot)) {
1968                 dm_warn("%s: Missing /u-boot node\n", __func__);
1969                 return -EINVAL;
1970         }
1971
1972         ret = ofnode_read_u64(uboot, "bootscr-flash-offset",
1973                               bootscr_flash_offset);
1974         if (ret)
1975                 return -EINVAL;
1976
1977         ret = ofnode_read_u64(uboot, "bootscr-flash-size",
1978                               bootscr_flash_size);
1979         if (ret)
1980                 return -EINVAL;
1981
1982         if (!bootscr_flash_size) {
1983                 dm_warn("bootscr-flash-size is zero. Ignoring properties!\n");
1984                 *bootscr_flash_offset = 0;
1985                 return -EINVAL;
1986         }
1987
1988         return 0;
1989 }
1990
1991 ofnode ofnode_get_phy_node(ofnode node)
1992 {
1993         /* DT node properties that reference a PHY node */
1994         static const char * const phy_handle_str[] = {
1995                 "phy-handle", "phy", "phy-device",
1996         };
1997         struct ofnode_phandle_args args = {
1998                 .node = ofnode_null()
1999         };
2000         int i;
2001
2002         assert(ofnode_valid(node));
2003
2004         for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++)
2005                 if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i],
2006                                                     NULL, 0, 0, &args))
2007                         break;
2008
2009         return args.node;
2010 }
2011
2012 phy_interface_t ofnode_read_phy_mode(ofnode node)
2013 {
2014         const char *mode;
2015         int i;
2016
2017         assert(ofnode_valid(node));
2018
2019         mode = ofnode_read_string(node, "phy-mode");
2020         if (!mode)
2021                 mode = ofnode_read_string(node, "phy-connection-type");
2022
2023         if (!mode)
2024                 return PHY_INTERFACE_MODE_NA;
2025
2026         for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
2027                 if (!strcmp(mode, phy_interface_strings[i]))
2028                         return i;
2029
2030         dm_warn("%s: Invalid PHY interface '%s'\n", __func__, mode);
2031
2032         return PHY_INTERFACE_MODE_NA;
2033 }
2034
2035 int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
2036 {
2037         ofnode subnode;
2038         int ret = 0;
2039
2040         assert(ofnode_valid(node));
2041
2042         if (ofnode_is_np(node)) {
2043                 struct device_node *np, *child;
2044
2045                 np = (struct device_node *)ofnode_to_np(node);
2046                 ret = of_add_subnode(np, name, -1, &child);
2047                 if (ret && ret != -EEXIST)
2048                         return ret;
2049                 subnode = np_to_ofnode(child);
2050         } else {
2051                 void *fdt = ofnode_to_fdt(node);
2052                 int poffset = ofnode_to_offset(node);
2053                 int offset;
2054
2055                 offset = fdt_add_subnode(fdt, poffset, name);
2056                 if (offset == -FDT_ERR_EXISTS) {
2057                         offset = fdt_subnode_offset(fdt, poffset, name);
2058                         ret = -EEXIST;
2059                 }
2060                 if (offset < 0)
2061                         return offset == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL;
2062                 subnode = noffset_to_ofnode(node, offset);
2063         }
2064
2065         *subnodep = subnode;
2066
2067         return ret;     /* 0 or -EEXIST */
2068 }
2069
2070 int ofnode_delete(ofnode *nodep)
2071 {
2072         ofnode node = *nodep;
2073         int ret;
2074
2075         assert(ofnode_valid(node));
2076         if (ofnode_is_np(node)) {
2077                 ret = of_remove_node(ofnode_to_np(node));
2078         } else {
2079                 void *fdt = ofnode_to_fdt(node);
2080                 int offset = ofnode_to_offset(node);
2081
2082                 ret = fdt_del_node(fdt, offset);
2083                 if (ret)
2084                         ret = -EFAULT;
2085         }
2086         if (ret)
2087                 return ret;
2088         *nodep = ofnode_null();
2089
2090         return 0;
2091 }
2092
2093 int ofnode_copy_props(ofnode dst, ofnode src)
2094 {
2095         struct ofprop prop;
2096
2097         ofnode_for_each_prop(prop, src) {
2098                 const char *name;
2099                 const char *val;
2100                 int len, ret;
2101
2102                 val = ofprop_get_property(&prop, &name, &len);
2103                 if (!val) {
2104                         log_debug("Cannot read prop (err=%d)\n", len);
2105                         return log_msg_ret("get", -EINVAL);
2106                 }
2107                 ret = ofnode_write_prop(dst, name, val, len, true);
2108                 if (ret) {
2109                         log_debug("Cannot write prop (err=%d)\n", ret);
2110                         return log_msg_ret("wr", -EINVAL);
2111                 }
2112         }
2113
2114         return 0;
2115 }
2116
2117 int ofnode_copy_node(ofnode dst_parent, const char *name, ofnode src,
2118                      ofnode *nodep)
2119 {
2120         ofnode node;
2121         int ret;
2122
2123         ret = ofnode_add_subnode(dst_parent, name, &node);
2124         if (ret) {
2125                 if (ret == -EEXIST)
2126                         *nodep = node;
2127                 return log_msg_ret("add", ret);
2128         }
2129         ret = ofnode_copy_props(node, src);
2130         if (ret)
2131                 return log_msg_ret("cpy", ret);
2132         *nodep = node;
2133
2134         return 0;
2135 }
This page took 0.150711 seconds and 4 git commands to generate.