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