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