Merge tag 'xilinx-for-v2023.01-rc3' of https://source.denx.de/u-boot/custodians/u...
[platform/kernel/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 <sjg@chromium.org>
5  */
6
7 #define LOG_CATEGORY    LOGC_DT
8
9 #include <common.h>
10 #include <dm.h>
11 #include <fdtdec.h>
12 #include <fdt_support.h>
13 #include <log.h>
14 #include <malloc.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 <linux/err.h>
20 #include <linux/ioport.h>
21 #include <asm/global_data.h>
22
23 DECLARE_GLOBAL_DATA_PTR;
24
25 #if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)
26 static void *oftree_list[CONFIG_OFNODE_MULTI_TREE_MAX];
27 static int oftree_count;
28
29 void oftree_reset(void)
30 {
31         if (gd->flags & GD_FLG_RELOC) {
32                 oftree_count = 0;
33                 oftree_list[oftree_count++] = (void *)gd->fdt_blob;
34         }
35 }
36
37 static int oftree_find(const void *fdt)
38 {
39         int i;
40
41         for (i = 0; i < oftree_count; i++) {
42                 if (fdt == oftree_list[i])
43                         return i;
44         }
45
46         return -1;
47 }
48
49 static oftree oftree_ensure(void *fdt)
50 {
51         oftree tree;
52         int i;
53
54         if (gd->flags & GD_FLG_RELOC) {
55                 i = oftree_find(fdt);
56                 if (i == -1) {
57                         if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) {
58                                 log_warning("Too many registered device trees (max %d)\n",
59                                             CONFIG_OFNODE_MULTI_TREE_MAX);
60                                 return oftree_null();
61                         }
62
63                         /* register the new tree */
64                         i = oftree_count++;
65                         oftree_list[i] = fdt;
66                         log_debug("oftree: registered tree %d: %p\n", i, fdt);
67                 }
68         } else {
69                 if (fdt != gd->fdt_blob) {
70                         log_debug("Cannot only access control FDT before relocation\n");
71                         return oftree_null();
72                 }
73         }
74
75         tree.fdt = fdt;
76
77         return tree;
78 }
79
80 void *ofnode_lookup_fdt(ofnode node)
81 {
82         if (gd->flags & GD_FLG_RELOC) {
83                 uint i = OFTREE_TREE_ID(node.of_offset);
84
85                 if (i > oftree_count) {
86                         log_debug("Invalid tree ID %x\n", i);
87                         return NULL;
88                 }
89
90                 return oftree_list[i];
91         } else {
92                 return (void *)gd->fdt_blob;
93         }
94 }
95
96 void *ofnode_to_fdt(ofnode node)
97 {
98 #ifdef OF_CHECKS
99         if (of_live_active())
100                 return NULL;
101 #endif
102         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && ofnode_valid(node))
103                 return ofnode_lookup_fdt(node);
104
105         /* Use the control FDT by default */
106         return (void *)gd->fdt_blob;
107 }
108
109 /**
110  * ofnode_to_offset() - convert an ofnode to a flat DT offset
111  *
112  * This cannot be called if the reference contains a node pointer.
113  *
114  * @node: Reference containing offset (possibly invalid)
115  * Return: DT offset (can be -1)
116  */
117 int ofnode_to_offset(ofnode node)
118 {
119 #ifdef OF_CHECKS
120         if (of_live_active())
121                 return -1;
122 #endif
123         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && node.of_offset >= 0)
124                 return OFTREE_OFFSET(node.of_offset);
125
126         return node.of_offset;
127 }
128
129 oftree oftree_from_fdt(void *fdt)
130 {
131         oftree tree;
132
133         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE))
134                 return oftree_ensure(fdt);
135
136         tree.fdt = fdt;
137
138         return tree;
139 }
140
141 /**
142  * noffset_to_ofnode() - convert a DT offset to an ofnode
143  *
144  * @other_node: Node in the same tree to use as a reference
145  * @of_offset: DT offset (either valid, or -1)
146  * Return: reference to the associated DT offset
147  */
148 ofnode noffset_to_ofnode(ofnode other_node, int of_offset)
149 {
150         ofnode node;
151
152         if (of_live_active())
153                 node.np = NULL;
154         else if (!CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || of_offset < 0 ||
155                  !ofnode_valid(other_node))
156                 node.of_offset = of_offset;
157         else
158                 node.of_offset = OFTREE_MAKE_NODE(other_node.of_offset,
159                                                   of_offset);
160
161         return node;
162 }
163
164 #else /* !OFNODE_MULTI_TREE */
165
166 static inline int oftree_find(const void *fdt)
167 {
168         return 0;
169 }
170
171 #endif /* OFNODE_MULTI_TREE */
172
173 /**
174  * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree)
175  *
176  * Looks up the tree and returns an ofnode with the correct of_offset (i.e.
177  * containing the tree ID).
178  *
179  * If @offset is < 0 then this returns an ofnode with that offset and no tree
180  * ID.
181  *
182  * @tree: tree to check
183  * @offset: offset within that tree (can be < 0)
184  * @return node for that offset, with the correct ID
185  */
186 static ofnode ofnode_from_tree_offset(oftree tree, int offset)
187 {
188         ofnode node;
189
190         if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && offset >= 0) {
191                 int tree_id = oftree_find(tree.fdt);
192
193                 if (tree_id == -1)
194                         return ofnode_null();
195                 node.of_offset = OFTREE_NODE(tree_id, offset);
196         } else {
197                 node.of_offset = offset;
198         }
199
200         return node;
201 }
202
203 bool ofnode_name_eq(ofnode node, const char *name)
204 {
205         const char *node_name;
206         size_t len;
207
208         assert(ofnode_valid(node));
209
210         node_name = ofnode_get_name(node);
211         len = strchrnul(node_name, '@') - node_name;
212
213         return (strlen(name) == len) && !strncmp(node_name, name, len);
214 }
215
216 int ofnode_read_u8(ofnode node, const char *propname, u8 *outp)
217 {
218         const u8 *cell;
219         int len;
220
221         assert(ofnode_valid(node));
222         debug("%s: %s: ", __func__, propname);
223
224         if (ofnode_is_np(node))
225                 return of_read_u8(ofnode_to_np(node), propname, outp);
226
227         cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
228                            &len);
229         if (!cell || len < sizeof(*cell)) {
230                 debug("(not found)\n");
231                 return -EINVAL;
232         }
233         *outp = *cell;
234         debug("%#x (%d)\n", *outp, *outp);
235
236         return 0;
237 }
238
239 u8 ofnode_read_u8_default(ofnode node, const char *propname, u8 def)
240 {
241         assert(ofnode_valid(node));
242         ofnode_read_u8(node, propname, &def);
243
244         return def;
245 }
246
247 int ofnode_read_u16(ofnode node, const char *propname, u16 *outp)
248 {
249         const fdt16_t *cell;
250         int len;
251
252         assert(ofnode_valid(node));
253         debug("%s: %s: ", __func__, propname);
254
255         if (ofnode_is_np(node))
256                 return of_read_u16(ofnode_to_np(node), propname, outp);
257
258         cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
259                            &len);
260         if (!cell || len < sizeof(*cell)) {
261                 debug("(not found)\n");
262                 return -EINVAL;
263         }
264         *outp = be16_to_cpup(cell);
265         debug("%#x (%d)\n", *outp, *outp);
266
267         return 0;
268 }
269
270 u16 ofnode_read_u16_default(ofnode node, const char *propname, u16 def)
271 {
272         assert(ofnode_valid(node));
273         ofnode_read_u16(node, propname, &def);
274
275         return def;
276 }
277
278 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
279 {
280         return ofnode_read_u32_index(node, propname, 0, outp);
281 }
282
283 u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
284 {
285         assert(ofnode_valid(node));
286         ofnode_read_u32_index(node, propname, 0, &def);
287
288         return def;
289 }
290
291 int ofnode_read_u32_index(ofnode node, const char *propname, int index,
292                           u32 *outp)
293 {
294         const fdt32_t *cell;
295         int len;
296
297         assert(ofnode_valid(node));
298         debug("%s: %s: ", __func__, propname);
299
300         if (ofnode_is_np(node))
301                 return of_read_u32_index(ofnode_to_np(node), propname, index,
302                                          outp);
303
304         cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
305                            propname, &len);
306         if (!cell) {
307                 debug("(not found)\n");
308                 return -EINVAL;
309         }
310
311         if (len < (sizeof(int) * (index + 1))) {
312                 debug("(not large enough)\n");
313                 return -EOVERFLOW;
314         }
315
316         *outp = fdt32_to_cpu(cell[index]);
317         debug("%#x (%d)\n", *outp, *outp);
318
319         return 0;
320 }
321
322 u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
323                                   u32 def)
324 {
325         assert(ofnode_valid(node));
326         ofnode_read_u32_index(node, propname, index, &def);
327
328         return def;
329 }
330
331 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
332 {
333         assert(ofnode_valid(node));
334         ofnode_read_u32(node, propname, (u32 *)&def);
335
336         return def;
337 }
338
339 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
340 {
341         const unaligned_fdt64_t *cell;
342         int len;
343
344         assert(ofnode_valid(node));
345         debug("%s: %s: ", __func__, propname);
346
347         if (ofnode_is_np(node))
348                 return of_read_u64(ofnode_to_np(node), propname, outp);
349
350         cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
351                            propname, &len);
352         if (!cell || len < sizeof(*cell)) {
353                 debug("(not found)\n");
354                 return -EINVAL;
355         }
356         *outp = fdt64_to_cpu(cell[0]);
357         debug("%#llx (%lld)\n", (unsigned long long)*outp,
358               (unsigned long long)*outp);
359
360         return 0;
361 }
362
363 u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
364 {
365         assert(ofnode_valid(node));
366         ofnode_read_u64(node, propname, &def);
367
368         return def;
369 }
370
371 bool ofnode_read_bool(ofnode node, const char *propname)
372 {
373         const void *prop;
374
375         assert(ofnode_valid(node));
376         debug("%s: %s: ", __func__, propname);
377
378         prop = ofnode_get_property(node, propname, NULL);
379
380         debug("%s\n", prop ? "true" : "false");
381
382         return prop ? true : false;
383 }
384
385 const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
386 {
387         const char *val = NULL;
388         int len;
389
390         assert(ofnode_valid(node));
391         debug("%s: %s: ", __func__, propname);
392
393         if (ofnode_is_np(node)) {
394                 struct property *prop = of_find_property(
395                                 ofnode_to_np(node), propname, &len);
396
397                 if (prop) {
398                         val = prop->value;
399                         len = prop->length;
400                 }
401         } else {
402                 val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
403                                   propname, &len);
404         }
405         if (!val) {
406                 debug("<not found>\n");
407                 if (sizep)
408                         *sizep = -FDT_ERR_NOTFOUND;
409                 return NULL;
410         }
411         if (sizep)
412                 *sizep = len;
413
414         return val;
415 }
416
417 const char *ofnode_read_string(ofnode node, const char *propname)
418 {
419         const char *str;
420         int len;
421
422         str = ofnode_read_prop(node, propname, &len);
423         if (!str)
424                 return NULL;
425
426         if (strnlen(str, len) >= len) {
427                 debug("<invalid>\n");
428                 return NULL;
429         }
430         debug("%s\n", str);
431
432         return str;
433 }
434
435 int ofnode_read_size(ofnode node, const char *propname)
436 {
437         int len;
438
439         if (!ofnode_read_prop(node, propname, &len))
440                 return -EINVAL;
441
442         return len;
443 }
444
445 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
446 {
447         ofnode subnode;
448
449         assert(ofnode_valid(node));
450         debug("%s: %s: ", __func__, subnode_name);
451
452         if (ofnode_is_np(node)) {
453                 struct device_node *np = ofnode_to_np(node);
454
455                 for (np = np->child; np; np = np->sibling) {
456                         if (!strcmp(subnode_name, np->name))
457                                 break;
458                 }
459                 subnode = np_to_ofnode(np);
460         } else {
461                 int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
462                                 ofnode_to_offset(node), subnode_name);
463                 subnode = noffset_to_ofnode(node, ooffset);
464         }
465         debug("%s\n", ofnode_valid(subnode) ?
466               ofnode_get_name(subnode) : "<none>");
467
468         return subnode;
469 }
470
471 int ofnode_read_u32_array(ofnode node, const char *propname,
472                           u32 *out_values, size_t sz)
473 {
474         assert(ofnode_valid(node));
475         debug("%s: %s: ", __func__, propname);
476
477         if (ofnode_is_np(node)) {
478                 return of_read_u32_array(ofnode_to_np(node), propname,
479                                          out_values, sz);
480         } else {
481                 int ret;
482
483                 ret = fdtdec_get_int_array(ofnode_to_fdt(node),
484                                            ofnode_to_offset(node), propname,
485                                            out_values, sz);
486
487                 /* get the error right, but space is more important in SPL */
488                 if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
489                         if (ret == -FDT_ERR_NOTFOUND)
490                                 return -EINVAL;
491                         else if (ret == -FDT_ERR_BADLAYOUT)
492                                 return -EOVERFLOW;
493                 }
494                 return ret;
495         }
496 }
497
498 #if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
499 bool ofnode_is_enabled(ofnode node)
500 {
501         if (ofnode_is_np(node)) {
502                 return of_device_is_available(ofnode_to_np(node));
503         } else {
504                 return fdtdec_get_is_enabled(ofnode_to_fdt(node),
505                                              ofnode_to_offset(node));
506         }
507 }
508
509 ofnode ofnode_first_subnode(ofnode node)
510 {
511         assert(ofnode_valid(node));
512         if (ofnode_is_np(node))
513                 return np_to_ofnode(node.np->child);
514
515         return noffset_to_ofnode(node,
516                 fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
517 }
518
519 ofnode ofnode_next_subnode(ofnode node)
520 {
521         assert(ofnode_valid(node));
522         if (ofnode_is_np(node))
523                 return np_to_ofnode(node.np->sibling);
524
525         return noffset_to_ofnode(node,
526                 fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
527 }
528 #endif /* !DM_INLINE_OFNODE */
529
530 ofnode ofnode_get_parent(ofnode node)
531 {
532         ofnode parent;
533
534         assert(ofnode_valid(node));
535         if (ofnode_is_np(node))
536                 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
537         else
538                 parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node),
539                                                      ofnode_to_offset(node));
540
541         return parent;
542 }
543
544 const char *ofnode_get_name(ofnode node)
545 {
546         if (!ofnode_valid(node)) {
547                 debug("%s node not valid\n", __func__);
548                 return NULL;
549         }
550
551         if (ofnode_is_np(node))
552                 return node.np->name;
553
554         return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL);
555 }
556
557 int ofnode_get_path(ofnode node, char *buf, int buflen)
558 {
559         assert(ofnode_valid(node));
560
561         if (ofnode_is_np(node)) {
562                 if (strlen(node.np->full_name) >= buflen)
563                         return -ENOSPC;
564
565                 strcpy(buf, node.np->full_name);
566
567                 return 0;
568         } else {
569                 int res;
570
571                 res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf,
572                                    buflen);
573                 if (!res)
574                         return res;
575                 else if (res == -FDT_ERR_NOSPACE)
576                         return -ENOSPC;
577                 else
578                         return -EINVAL;
579         }
580 }
581
582 ofnode ofnode_get_by_phandle(uint phandle)
583 {
584         ofnode node;
585
586         if (of_live_active())
587                 node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle));
588         else
589                 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
590                                                             phandle);
591
592         return node;
593 }
594
595 ofnode oftree_get_by_phandle(oftree tree, uint phandle)
596 {
597         ofnode node;
598
599         if (of_live_active())
600                 node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle));
601         else
602                 node = ofnode_from_tree_offset(tree,
603                         fdt_node_offset_by_phandle(oftree_lookup_fdt(tree),
604                                                    phandle));
605
606         return node;
607 }
608
609 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
610                                                fdt_size_t *size, bool translate)
611 {
612         int na, ns;
613
614         if (size)
615                 *size = FDT_SIZE_T_NONE;
616
617         if (ofnode_is_np(node)) {
618                 const __be32 *prop_val;
619                 u64 size64;
620                 uint flags;
621
622                 prop_val = of_get_address(ofnode_to_np(node), index, &size64,
623                                           &flags);
624                 if (!prop_val)
625                         return FDT_ADDR_T_NONE;
626
627                 if (size)
628                         *size = size64;
629
630                 ns = of_n_size_cells(ofnode_to_np(node));
631
632                 if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
633                         return of_translate_address(ofnode_to_np(node), prop_val);
634                 } else {
635                         na = of_n_addr_cells(ofnode_to_np(node));
636                         return of_read_number(prop_val, na);
637                 }
638         } else {
639                 na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
640                 ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
641                 return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node),
642                                                   ofnode_to_offset(node), "reg",
643                                                   index, na, ns, size,
644                                                   translate);
645         }
646 }
647
648 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
649 {
650         return __ofnode_get_addr_size_index(node, index, size, true);
651 }
652
653 fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
654                                               fdt_size_t *size)
655 {
656         return __ofnode_get_addr_size_index(node, index, size, false);
657 }
658
659 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
660 {
661         fdt_size_t size;
662
663         return ofnode_get_addr_size_index(node, index, &size);
664 }
665
666 fdt_addr_t ofnode_get_addr(ofnode node)
667 {
668         return ofnode_get_addr_index(node, 0);
669 }
670
671 fdt_size_t ofnode_get_size(ofnode node)
672 {
673         fdt_size_t size;
674
675         ofnode_get_addr_size_index(node, 0, &size);
676
677         return size;
678 }
679
680 int ofnode_stringlist_search(ofnode node, const char *property,
681                              const char *string)
682 {
683         if (ofnode_is_np(node)) {
684                 return of_property_match_string(ofnode_to_np(node),
685                                                 property, string);
686         } else {
687                 int ret;
688
689                 ret = fdt_stringlist_search(ofnode_to_fdt(node),
690                                             ofnode_to_offset(node), property,
691                                             string);
692                 if (ret == -FDT_ERR_NOTFOUND)
693                         return -ENODATA;
694                 else if (ret < 0)
695                         return -EINVAL;
696
697                 return ret;
698         }
699 }
700
701 int ofnode_read_string_index(ofnode node, const char *property, int index,
702                              const char **outp)
703 {
704         if (ofnode_is_np(node)) {
705                 return of_property_read_string_index(ofnode_to_np(node),
706                                                      property, index, outp);
707         } else {
708                 int len;
709
710                 *outp = fdt_stringlist_get(ofnode_to_fdt(node),
711                                            ofnode_to_offset(node),
712                                            property, index, &len);
713                 if (len < 0)
714                         return -EINVAL;
715                 return 0;
716         }
717 }
718
719 int ofnode_read_string_count(ofnode node, const char *property)
720 {
721         if (ofnode_is_np(node)) {
722                 return of_property_count_strings(ofnode_to_np(node), property);
723         } else {
724                 return fdt_stringlist_count(ofnode_to_fdt(node),
725                                             ofnode_to_offset(node), property);
726         }
727 }
728
729 int ofnode_read_string_list(ofnode node, const char *property,
730                             const char ***listp)
731 {
732         const char **prop;
733         int count;
734         int i;
735
736         *listp = NULL;
737         count = ofnode_read_string_count(node, property);
738         if (count < 0)
739                 return count;
740         if (!count)
741                 return 0;
742
743         prop = calloc(count + 1, sizeof(char *));
744         if (!prop)
745                 return -ENOMEM;
746
747         for (i = 0; i < count; i++)
748                 ofnode_read_string_index(node, property, i, &prop[i]);
749         prop[count] = NULL;
750         *listp = prop;
751
752         return count;
753 }
754
755 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
756                                             struct ofnode_phandle_args *out)
757 {
758         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
759         out->node = offset_to_ofnode(in->node);
760         out->args_count = in->args_count;
761         memcpy(out->args, in->args, sizeof(out->args));
762 }
763
764 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
765                                         struct ofnode_phandle_args *out)
766 {
767         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
768         out->node = np_to_ofnode(in->np);
769         out->args_count = in->args_count;
770         memcpy(out->args, in->args, sizeof(out->args));
771 }
772
773 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
774                                    const char *cells_name, int cell_count,
775                                    int index,
776                                    struct ofnode_phandle_args *out_args)
777 {
778         if (ofnode_is_np(node)) {
779                 struct of_phandle_args args;
780                 int ret;
781
782                 ret = of_parse_phandle_with_args(ofnode_to_np(node),
783                                                  list_name, cells_name,
784                                                  cell_count, index,
785                                                  &args);
786                 if (ret)
787                         return ret;
788                 ofnode_from_of_phandle_args(&args, out_args);
789         } else {
790                 struct fdtdec_phandle_args args;
791                 int ret;
792
793                 ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
794                                                      ofnode_to_offset(node),
795                                                      list_name, cells_name,
796                                                      cell_count, index, &args);
797                 if (ret)
798                         return ret;
799                 ofnode_from_fdtdec_phandle_args(&args, out_args);
800         }
801
802         return 0;
803 }
804
805 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
806                                    const char *cells_name, int cell_count)
807 {
808         if (ofnode_is_np(node))
809                 return of_count_phandle_with_args(ofnode_to_np(node),
810                                 list_name, cells_name, cell_count);
811         else
812                 return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
813                                 ofnode_to_offset(node), list_name, cells_name,
814                                 cell_count, -1, NULL);
815 }
816
817 ofnode ofnode_path(const char *path)
818 {
819         if (of_live_active())
820                 return np_to_ofnode(of_find_node_by_path(path));
821         else
822                 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
823 }
824
825 ofnode oftree_root(oftree tree)
826 {
827         if (of_live_active()) {
828                 return np_to_ofnode(tree.np);
829         } else {
830                 return ofnode_from_tree_offset(tree, 0);
831         }
832 }
833
834 ofnode oftree_path(oftree tree, const char *path)
835 {
836         if (of_live_active()) {
837                 return np_to_ofnode(of_find_node_opts_by_path(tree.np, path,
838                                                               NULL));
839         } else if (*path != '/' && tree.fdt != gd->fdt_blob) {
840                 return ofnode_null();  /* Aliases only on control FDT */
841         } else {
842                 int offset = fdt_path_offset(tree.fdt, path);
843
844                 return ofnode_from_tree_offset(tree, offset);
845         }
846 }
847
848 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
849 {
850         ofnode chosen_node;
851
852         chosen_node = ofnode_path("/chosen");
853
854         return ofnode_read_prop(chosen_node, propname, sizep);
855 }
856
857 const char *ofnode_read_chosen_string(const char *propname)
858 {
859         return ofnode_read_chosen_prop(propname, NULL);
860 }
861
862 ofnode ofnode_get_chosen_node(const char *name)
863 {
864         const char *prop;
865
866         prop = ofnode_read_chosen_prop(name, NULL);
867         if (!prop)
868                 return ofnode_null();
869
870         return ofnode_path(prop);
871 }
872
873 const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
874 {
875         ofnode node;
876
877         node = ofnode_path("/aliases");
878
879         return ofnode_read_prop(node, propname, sizep);
880 }
881
882 ofnode ofnode_get_aliases_node(const char *name)
883 {
884         const char *prop;
885
886         prop = ofnode_read_aliases_prop(name, NULL);
887         if (!prop)
888                 return ofnode_null();
889
890         debug("%s: node_path: %s\n", __func__, prop);
891
892         return ofnode_path(prop);
893 }
894
895 int ofnode_get_child_count(ofnode parent)
896 {
897         ofnode child;
898         int num = 0;
899
900         ofnode_for_each_subnode(child, parent)
901                 num++;
902
903         return num;
904 }
905
906 static int decode_timing_property(ofnode node, const char *name,
907                                   struct timing_entry *result)
908 {
909         int length, ret = 0;
910
911         length = ofnode_read_size(node, name);
912         if (length < 0) {
913                 debug("%s: could not find property %s\n",
914                       ofnode_get_name(node), name);
915                 return length;
916         }
917
918         if (length == sizeof(u32)) {
919                 result->typ = ofnode_read_u32_default(node, name, 0);
920                 result->min = result->typ;
921                 result->max = result->typ;
922         } else {
923                 ret = ofnode_read_u32_array(node, name, &result->min, 3);
924         }
925
926         return ret;
927 }
928
929 int ofnode_decode_display_timing(ofnode parent, int index,
930                                  struct display_timing *dt)
931 {
932         int i;
933         ofnode timings, node;
934         u32 val = 0;
935         int ret = 0;
936
937         timings = ofnode_find_subnode(parent, "display-timings");
938         if (!ofnode_valid(timings))
939                 return -EINVAL;
940
941         i = 0;
942         ofnode_for_each_subnode(node, timings) {
943                 if (i++ == index)
944                         break;
945         }
946
947         if (!ofnode_valid(node))
948                 return -EINVAL;
949
950         memset(dt, 0, sizeof(*dt));
951
952         ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
953         ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
954         ret |= decode_timing_property(node, "hactive", &dt->hactive);
955         ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
956         ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
957         ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
958         ret |= decode_timing_property(node, "vactive", &dt->vactive);
959         ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
960         ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
961
962         dt->flags = 0;
963         val = ofnode_read_u32_default(node, "vsync-active", -1);
964         if (val != -1) {
965                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
966                                 DISPLAY_FLAGS_VSYNC_LOW;
967         }
968         val = ofnode_read_u32_default(node, "hsync-active", -1);
969         if (val != -1) {
970                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
971                                 DISPLAY_FLAGS_HSYNC_LOW;
972         }
973         val = ofnode_read_u32_default(node, "de-active", -1);
974         if (val != -1) {
975                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
976                                 DISPLAY_FLAGS_DE_LOW;
977         }
978         val = ofnode_read_u32_default(node, "pixelclk-active", -1);
979         if (val != -1) {
980                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
981                                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
982         }
983
984         if (ofnode_read_bool(node, "interlaced"))
985                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
986         if (ofnode_read_bool(node, "doublescan"))
987                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
988         if (ofnode_read_bool(node, "doubleclk"))
989                 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
990
991         return ret;
992 }
993
994 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
995 {
996         if (ofnode_is_np(node))
997                 return of_get_property(ofnode_to_np(node), propname, lenp);
998         else
999                 return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1000                                    propname, lenp);
1001 }
1002
1003 int ofnode_first_property(ofnode node, struct ofprop *prop)
1004 {
1005         prop->node = node;
1006
1007         if (ofnode_is_np(node)) {
1008                 prop->prop = of_get_first_property(ofnode_to_np(prop->node));
1009                 if (!prop->prop)
1010                         return -FDT_ERR_NOTFOUND;
1011         } else {
1012                 prop->offset =
1013                         fdt_first_property_offset(ofnode_to_fdt(node),
1014                                                   ofnode_to_offset(prop->node));
1015                 if (prop->offset < 0)
1016                         return prop->offset;
1017         }
1018
1019         return 0;
1020 }
1021
1022 int ofnode_next_property(struct ofprop *prop)
1023 {
1024         if (ofnode_is_np(prop->node)) {
1025                 prop->prop = of_get_next_property(ofnode_to_np(prop->node),
1026                                                   prop->prop);
1027                 if (!prop->prop)
1028                         return -FDT_ERR_NOTFOUND;
1029         } else {
1030                 prop->offset =
1031                         fdt_next_property_offset(ofnode_to_fdt(prop->node),
1032                                                  prop->offset);
1033                 if (prop->offset  < 0)
1034                         return prop->offset;
1035         }
1036
1037         return 0;
1038 }
1039
1040 const void *ofprop_get_property(const struct ofprop *prop,
1041                                 const char **propname, int *lenp)
1042 {
1043         if (ofnode_is_np(prop->node))
1044                 return of_get_property_by_prop(ofnode_to_np(prop->node),
1045                                                prop->prop, propname, lenp);
1046         else
1047                 return fdt_getprop_by_offset(ofnode_to_fdt(prop->node),
1048                                              prop->offset,
1049                                              propname, lenp);
1050 }
1051
1052 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
1053                                 fdt_size_t *sizep)
1054 {
1055         if (ofnode_is_np(node)) {
1056                 int na, ns;
1057                 int psize;
1058                 const struct device_node *np = ofnode_to_np(node);
1059                 const __be32 *prop = of_get_property(np, property, &psize);
1060
1061                 if (!prop)
1062                         return FDT_ADDR_T_NONE;
1063                 na = of_n_addr_cells(np);
1064                 ns = of_n_size_cells(np);
1065                 *sizep = of_read_number(prop + na, ns);
1066
1067                 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
1068                         return of_translate_address(np, prop);
1069                 else
1070                         return of_read_number(prop, na);
1071         } else {
1072                 return fdtdec_get_addr_size(ofnode_to_fdt(node),
1073                                             ofnode_to_offset(node), property,
1074                                             sizep);
1075         }
1076 }
1077
1078 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
1079                                         size_t sz)
1080 {
1081         if (ofnode_is_np(node)) {
1082                 const struct device_node *np = ofnode_to_np(node);
1083                 int psize;
1084                 const __be32 *prop = of_get_property(np, propname, &psize);
1085
1086                 if (!prop || sz != psize)
1087                         return NULL;
1088                 return (uint8_t *)prop;
1089
1090         } else {
1091                 return fdtdec_locate_byte_array(ofnode_to_fdt(node),
1092                                 ofnode_to_offset(node), propname, sz);
1093         }
1094 }
1095
1096 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
1097                          const char *propname, struct fdt_pci_addr *addr)
1098 {
1099         const fdt32_t *cell;
1100         int len;
1101         int ret = -ENOENT;
1102
1103         debug("%s: %s: ", __func__, propname);
1104
1105         /*
1106          * If we follow the pci bus bindings strictly, we should check
1107          * the value of the node's parent node's #address-cells and
1108          * #size-cells. They need to be 3 and 2 accordingly. However,
1109          * for simplicity we skip the check here.
1110          */
1111         cell = ofnode_get_property(node, propname, &len);
1112         if (!cell)
1113                 goto fail;
1114
1115         if ((len % FDT_PCI_REG_SIZE) == 0) {
1116                 int num = len / FDT_PCI_REG_SIZE;
1117                 int i;
1118
1119                 for (i = 0; i < num; i++) {
1120                         debug("pci address #%d: %08lx %08lx %08lx\n", i,
1121                               (ulong)fdt32_to_cpu(cell[0]),
1122                               (ulong)fdt32_to_cpu(cell[1]),
1123                               (ulong)fdt32_to_cpu(cell[2]));
1124                         if ((fdt32_to_cpu(*cell) & type) == type) {
1125                                 addr->phys_hi = fdt32_to_cpu(cell[0]);
1126                                 addr->phys_mid = fdt32_to_cpu(cell[1]);
1127                                 addr->phys_lo = fdt32_to_cpu(cell[2]);
1128                                 break;
1129                         }
1130
1131                         cell += (FDT_PCI_ADDR_CELLS +
1132                                  FDT_PCI_SIZE_CELLS);
1133                 }
1134
1135                 if (i == num) {
1136                         ret = -ENXIO;
1137                         goto fail;
1138                 }
1139
1140                 return 0;
1141         }
1142
1143         ret = -EINVAL;
1144
1145 fail:
1146         debug("(not found)\n");
1147         return ret;
1148 }
1149
1150 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
1151 {
1152         const char *list, *end;
1153         int len;
1154
1155         list = ofnode_get_property(node, "compatible", &len);
1156         if (!list)
1157                 return -ENOENT;
1158
1159         end = list + len;
1160         while (list < end) {
1161                 len = strlen(list);
1162                 if (len >= strlen("pciVVVV,DDDD")) {
1163                         char *s = strstr(list, "pci");
1164
1165                         /*
1166                          * check if the string is something like pciVVVV,DDDD.RR
1167                          * or just pciVVVV,DDDD
1168                          */
1169                         if (s && s[7] == ',' &&
1170                             (s[12] == '.' || s[12] == 0)) {
1171                                 s += 3;
1172                                 *vendor = simple_strtol(s, NULL, 16);
1173
1174                                 s += 5;
1175                                 *device = simple_strtol(s, NULL, 16);
1176
1177                                 return 0;
1178                         }
1179                 }
1180                 list += (len + 1);
1181         }
1182
1183         return -ENOENT;
1184 }
1185
1186 int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
1187 {
1188         const char *list, *end;
1189         int len;
1190
1191         list = ofnode_get_property(node, "compatible", &len);
1192
1193         if (!list)
1194                 return -ENOENT;
1195
1196         end = list + len;
1197         while (list < end) {
1198                 len = strlen(list);
1199
1200                 if (len >= strlen("ethernet-phy-idVVVV.DDDD")) {
1201                         char *s = strstr(list, "ethernet-phy-id");
1202
1203                         /*
1204                          * check if the string is something like
1205                          * ethernet-phy-idVVVV.DDDD
1206                          */
1207                         if (s && s[19] == '.') {
1208                                 s += strlen("ethernet-phy-id");
1209                                 *vendor = simple_strtol(s, NULL, 16);
1210                                 s += 5;
1211                                 *device = simple_strtol(s, NULL, 16);
1212
1213                                 return 0;
1214                         }
1215                 }
1216                 list += (len + 1);
1217         }
1218
1219         return -ENOENT;
1220 }
1221
1222 int ofnode_read_addr_cells(ofnode node)
1223 {
1224         if (ofnode_is_np(node)) {
1225                 return of_n_addr_cells(ofnode_to_np(node));
1226         } else {
1227                 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1228                                                ofnode_to_offset(node));
1229
1230                 return fdt_address_cells(ofnode_to_fdt(node), parent);
1231         }
1232 }
1233
1234 int ofnode_read_size_cells(ofnode node)
1235 {
1236         if (ofnode_is_np(node)) {
1237                 return of_n_size_cells(ofnode_to_np(node));
1238         } else {
1239                 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1240                                                ofnode_to_offset(node));
1241
1242                 return fdt_size_cells(ofnode_to_fdt(node), parent);
1243         }
1244 }
1245
1246 int ofnode_read_simple_addr_cells(ofnode node)
1247 {
1248         if (ofnode_is_np(node))
1249                 return of_simple_addr_cells(ofnode_to_np(node));
1250         else
1251                 return fdt_address_cells(ofnode_to_fdt(node),
1252                                          ofnode_to_offset(node));
1253 }
1254
1255 int ofnode_read_simple_size_cells(ofnode node)
1256 {
1257         if (ofnode_is_np(node))
1258                 return of_simple_size_cells(ofnode_to_np(node));
1259         else
1260                 return fdt_size_cells(ofnode_to_fdt(node),
1261                                       ofnode_to_offset(node));
1262 }
1263
1264 bool ofnode_pre_reloc(ofnode node)
1265 {
1266 #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
1267         /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
1268          * had property dm-pre-reloc or u-boot,dm-spl/tpl.
1269          * They are removed in final dtb (fdtgrep 2nd pass)
1270          */
1271         return true;
1272 #else
1273         if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
1274                 return true;
1275         if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
1276                 return true;
1277
1278         /*
1279          * In regular builds individual spl and tpl handling both
1280          * count as handled pre-relocation for later second init.
1281          */
1282         if (ofnode_read_bool(node, "u-boot,dm-spl") ||
1283             ofnode_read_bool(node, "u-boot,dm-tpl"))
1284                 return true;
1285
1286         return false;
1287 #endif
1288 }
1289
1290 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
1291 {
1292         if (ofnode_is_np(node)) {
1293                 return of_address_to_resource(ofnode_to_np(node), index, res);
1294         } else {
1295                 struct fdt_resource fres;
1296                 int ret;
1297
1298                 ret = fdt_get_resource(ofnode_to_fdt(node),
1299                                        ofnode_to_offset(node),
1300                                        "reg", index, &fres);
1301                 if (ret < 0)
1302                         return -EINVAL;
1303                 memset(res, '\0', sizeof(*res));
1304                 res->start = fres.start;
1305                 res->end = fres.end;
1306
1307                 return 0;
1308         }
1309 }
1310
1311 int ofnode_read_resource_byname(ofnode node, const char *name,
1312                                 struct resource *res)
1313 {
1314         int index;
1315
1316         index = ofnode_stringlist_search(node, "reg-names", name);
1317         if (index < 0)
1318                 return index;
1319
1320         return ofnode_read_resource(node, index, res);
1321 }
1322
1323 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
1324 {
1325         if (ofnode_is_np(node))
1326                 return of_translate_address(ofnode_to_np(node), in_addr);
1327         else
1328                 return fdt_translate_address(ofnode_to_fdt(node),
1329                                              ofnode_to_offset(node), in_addr);
1330 }
1331
1332 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
1333 {
1334         if (ofnode_is_np(node))
1335                 return of_translate_dma_address(ofnode_to_np(node), in_addr);
1336         else
1337                 return fdt_translate_dma_address(ofnode_to_fdt(node),
1338                                                  ofnode_to_offset(node), in_addr);
1339 }
1340
1341 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
1342 {
1343         if (ofnode_is_np(node))
1344                 return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
1345         else
1346                 return fdt_get_dma_range(ofnode_to_fdt(node),
1347                                          ofnode_to_offset(node),
1348                                          cpu, bus, size);
1349 }
1350
1351 int ofnode_device_is_compatible(ofnode node, const char *compat)
1352 {
1353         if (ofnode_is_np(node))
1354                 return of_device_is_compatible(ofnode_to_np(node), compat,
1355                                                NULL, NULL);
1356         else
1357                 return !fdt_node_check_compatible(ofnode_to_fdt(node),
1358                                                   ofnode_to_offset(node),
1359                                                   compat);
1360 }
1361
1362 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1363 {
1364         if (of_live_active()) {
1365                 return np_to_ofnode(of_find_compatible_node(
1366                         (struct device_node *)ofnode_to_np(from), NULL,
1367                         compat));
1368         } else {
1369                 return noffset_to_ofnode(from,
1370                         fdt_node_offset_by_compatible(ofnode_to_fdt(from),
1371                                         ofnode_to_offset(from), compat));
1372         }
1373 }
1374
1375 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1376                             const void *propval, int proplen)
1377 {
1378         if (of_live_active()) {
1379                 return np_to_ofnode(of_find_node_by_prop_value(
1380                         (struct device_node *)ofnode_to_np(from), propname,
1381                         propval, proplen));
1382         } else {
1383                 return noffset_to_ofnode(from,
1384                          fdt_node_offset_by_prop_value(ofnode_to_fdt(from),
1385                                 ofnode_to_offset(from), propname, propval,
1386                                 proplen));
1387         }
1388 }
1389
1390 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
1391                       int len, bool copy)
1392 {
1393         if (of_live_active()) {
1394                 void *newval;
1395                 int ret;
1396
1397                 if (copy) {
1398                         newval = malloc(len);
1399                         if (!newval)
1400                                 return log_ret(-ENOMEM);
1401                         memcpy(newval, value, len);
1402                         value = newval;
1403                 }
1404                 ret = of_write_prop(ofnode_to_np(node), propname, len, value);
1405                 if (ret && copy)
1406                         free(newval);
1407                 return ret;
1408         } else {
1409                 return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1410                                    propname, value, len);
1411         }
1412 }
1413
1414 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1415 {
1416         assert(ofnode_valid(node));
1417
1418         debug("%s: %s = %s", __func__, propname, value);
1419
1420         return ofnode_write_prop(node, propname, value, strlen(value) + 1,
1421                                  false);
1422 }
1423
1424 int ofnode_write_u32(ofnode node, const char *propname, u32 value)
1425 {
1426         fdt32_t *val;
1427
1428         assert(ofnode_valid(node));
1429
1430         log_debug("%s = %x", propname, value);
1431         val = malloc(sizeof(*val));
1432         if (!val)
1433                 return -ENOMEM;
1434         *val = cpu_to_fdt32(value);
1435
1436         return ofnode_write_prop(node, propname, val, sizeof(value), false);
1437 }
1438
1439 int ofnode_set_enabled(ofnode node, bool value)
1440 {
1441         assert(ofnode_valid(node));
1442
1443         if (value)
1444                 return ofnode_write_string(node, "status", "okay");
1445         else
1446                 return ofnode_write_string(node, "status", "disabled");
1447 }
1448
1449 bool ofnode_conf_read_bool(const char *prop_name)
1450 {
1451         ofnode node;
1452
1453         node = ofnode_path("/config");
1454         if (!ofnode_valid(node))
1455                 return false;
1456
1457         return ofnode_read_bool(node, prop_name);
1458 }
1459
1460 int ofnode_conf_read_int(const char *prop_name, int default_val)
1461 {
1462         ofnode node;
1463
1464         node = ofnode_path("/config");
1465         if (!ofnode_valid(node))
1466                 return default_val;
1467
1468         return ofnode_read_u32_default(node, prop_name, default_val);
1469 }
1470
1471 const char *ofnode_conf_read_str(const char *prop_name)
1472 {
1473         ofnode node;
1474
1475         node = ofnode_path("/config");
1476         if (!ofnode_valid(node))
1477                 return NULL;
1478
1479         return ofnode_read_string(node, prop_name);
1480 }
1481
1482 ofnode ofnode_get_phy_node(ofnode node)
1483 {
1484         /* DT node properties that reference a PHY node */
1485         static const char * const phy_handle_str[] = {
1486                 "phy-handle", "phy", "phy-device",
1487         };
1488         struct ofnode_phandle_args args = {
1489                 .node = ofnode_null()
1490         };
1491         int i;
1492
1493         assert(ofnode_valid(node));
1494
1495         for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++)
1496                 if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i],
1497                                                     NULL, 0, 0, &args))
1498                         break;
1499
1500         return args.node;
1501 }
1502
1503 phy_interface_t ofnode_read_phy_mode(ofnode node)
1504 {
1505         const char *mode;
1506         int i;
1507
1508         assert(ofnode_valid(node));
1509
1510         mode = ofnode_read_string(node, "phy-mode");
1511         if (!mode)
1512                 mode = ofnode_read_string(node, "phy-connection-type");
1513
1514         if (!mode)
1515                 return PHY_INTERFACE_MODE_NA;
1516
1517         for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
1518                 if (!strcmp(mode, phy_interface_strings[i]))
1519                         return i;
1520
1521         debug("%s: Invalid PHY interface '%s'\n", __func__, mode);
1522
1523         return PHY_INTERFACE_MODE_NA;
1524 }
1525
1526 int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
1527 {
1528         ofnode subnode;
1529         int ret = 0;
1530
1531         assert(ofnode_valid(node));
1532
1533         if (ofnode_is_np(node)) {
1534                 struct device_node *np, *child;
1535
1536                 np = (struct device_node *)ofnode_to_np(node);
1537                 ret = of_add_subnode(np, name, -1, &child);
1538                 if (ret && ret != -EEXIST)
1539                         return ret;
1540                 subnode = np_to_ofnode(child);
1541         } else {
1542                 void *fdt = ofnode_to_fdt(node);
1543                 int poffset = ofnode_to_offset(node);
1544                 int offset;
1545
1546                 offset = fdt_add_subnode(fdt, poffset, name);
1547                 if (offset == -FDT_ERR_EXISTS) {
1548                         offset = fdt_subnode_offset(fdt, poffset, name);
1549                         ret = -EEXIST;
1550                 }
1551                 if (offset < 0)
1552                         return -EINVAL;
1553                 subnode = noffset_to_ofnode(node, offset);
1554         }
1555
1556         *subnodep = subnode;
1557
1558         return ret;     /* 0 or -EEXIST */
1559 }
1560
1561 int ofnode_copy_props(ofnode src, ofnode dst)
1562 {
1563         struct ofprop prop;
1564
1565         ofnode_for_each_prop(prop, src) {
1566                 const char *name;
1567                 const char *val;
1568                 int len, ret;
1569
1570                 val = ofprop_get_property(&prop, &name, &len);
1571                 if (!val) {
1572                         log_debug("Cannot read prop (err=%d)\n", len);
1573                         return log_msg_ret("get", -EINVAL);
1574                 }
1575                 ret = ofnode_write_prop(dst, name, val, len, true);
1576                 if (ret) {
1577                         log_debug("Cannot write prop (err=%d)\n", ret);
1578                         return log_msg_ret("wr", -EINVAL);
1579                 }
1580         }
1581
1582         return 0;
1583 }