"Das U-Boot" Source Tree
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Copyright (c) 2017 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
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
24DECLARE_GLOBAL_DATA_PTR;
25
26#if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)
27static void *oftree_list[CONFIG_OFNODE_MULTI_TREE_MAX];
28static int oftree_count;
29
30void 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
38static 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
50static 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
61static 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
108int 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
143void oftree_dispose(oftree tree)
144{
145 if (of_live_active())
146 of_live_free(tree.np);
147}
148
149void *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
165void *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 */
186int 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
198oftree 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 */
221ofnode 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
239static inline int oftree_find(const void *fdt)
240{
241 return 0;
242}
243
244int oftree_new(oftree *treep)
245{
246 return -ENOSYS;
247}
248
249#endif /* OFNODE_MULTI_TREE */
250
251int 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 */
282static 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
299bool 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
312bool 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
335int 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
358u8 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
366int 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
389u16 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
397int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
398{
399 return ofnode_read_u32_index(node, propname, 0, outp);
400}
401
402u32 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
410int 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
441int 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
471u32 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
480int 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
488int 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
512u64 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
520bool 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
534const 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
566const 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
584int 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
594ofnode 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
615ofnode 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
635int 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)
663bool 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
673ofnode 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
683ofnode 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
694ofnode 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
708const 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
721int 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
746ofnode 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
759ofnode 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
773static 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
813fdt_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
818fdt_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
824fdt_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
831fdt_addr_t ofnode_get_addr(ofnode node)
832{
833 return ofnode_get_addr_index(node, 0);
834}
835
836fdt_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
845int 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
866int 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
884int 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
894int 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
920ofnode 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
949ofnode 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
978static 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
987static 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
996int 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
1028int 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
1061int 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
1073int 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
1085ofnode 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
1093ofnode 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
1102ofnode 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
1116const 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
1125const char *ofnode_read_chosen_string(const char *propname)
1126{
1127 return ofnode_read_chosen_prop(propname, NULL);
1128}
1129
1130ofnode 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
1141int 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
1159const 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
1168ofnode 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
1181int 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
1192static 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
1215int 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
1280int 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
1327const 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
1336bool 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
1344int 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
1363int 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
1381const 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
1393fdt_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
1419const 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
1437int 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
1491fail:
1492 log_debug("(not found)\n");
1493 return ret;
1494}
1495
1496int 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
1532int 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
1568int 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
1580int 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
1592int 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
1601int 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
1610bool 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
1648int 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
1669int 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
1681u64 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
1690u64 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
1699int 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
1709int 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
1720ofnode 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
1733ofnode 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
1748int 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
1777int 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
1787int 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
1802int 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
1817int 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
1825int 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
1841int 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
1851bool 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
1862int 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
1873const 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
1884bool 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
1895int 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
1906const 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
1917int 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
1932int 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
1957int 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
1991ofnode 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
2012phy_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
2035int 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
2070int 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
2093int 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
2117int 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}