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