dm: core: Expand integer-reading tests
[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(gd->fdt_blob, ofnode_to_offset(node), propname,
123                            &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(gd->fdt_blob, ofnode_to_offset(node), propname,
169                            &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(gd->fdt_blob, 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(gd->fdt_blob,
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(gd->fdt_blob,
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(gd->fdt_blob,
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(gd->fdt_blob, 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(gd->fdt_blob, 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(gd->fdt_blob,
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(gd->fdt_blob, 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(gd->fdt_blob, 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 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
414                                                fdt_size_t *size, bool translate)
415 {
416         int na, ns;
417
418         if (size)
419                 *size = FDT_SIZE_T_NONE;
420
421         if (ofnode_is_np(node)) {
422                 const __be32 *prop_val;
423                 u64 size64;
424                 uint flags;
425
426                 prop_val = of_get_address(ofnode_to_np(node), index, &size64,
427                                           &flags);
428                 if (!prop_val)
429                         return FDT_ADDR_T_NONE;
430
431                 if (size)
432                         *size = size64;
433
434                 ns = of_n_size_cells(ofnode_to_np(node));
435
436                 if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
437                         return of_translate_address(ofnode_to_np(node), prop_val);
438                 } else {
439                         na = of_n_addr_cells(ofnode_to_np(node));
440                         return of_read_number(prop_val, na);
441                 }
442         } else {
443                 na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
444                 ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
445                 return fdtdec_get_addr_size_fixed(gd->fdt_blob,
446                                                   ofnode_to_offset(node), "reg",
447                                                   index, na, ns, size,
448                                                   translate);
449         }
450 }
451
452 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
453 {
454         return __ofnode_get_addr_size_index(node, index, size, true);
455 }
456
457 fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
458                                               fdt_size_t *size)
459 {
460         return __ofnode_get_addr_size_index(node, index, size, false);
461 }
462
463 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
464 {
465         fdt_size_t size;
466
467         return ofnode_get_addr_size_index(node, index, &size);
468 }
469
470 fdt_addr_t ofnode_get_addr(ofnode node)
471 {
472         return ofnode_get_addr_index(node, 0);
473 }
474
475 fdt_size_t ofnode_get_size(ofnode node)
476 {
477         fdt_size_t size;
478
479         ofnode_get_addr_size_index(node, 0, &size);
480
481         return size;
482 }
483
484 int ofnode_stringlist_search(ofnode node, const char *property,
485                              const char *string)
486 {
487         if (ofnode_is_np(node)) {
488                 return of_property_match_string(ofnode_to_np(node),
489                                                 property, string);
490         } else {
491                 int ret;
492
493                 ret = fdt_stringlist_search(gd->fdt_blob,
494                                             ofnode_to_offset(node), property,
495                                             string);
496                 if (ret == -FDT_ERR_NOTFOUND)
497                         return -ENODATA;
498                 else if (ret < 0)
499                         return -EINVAL;
500
501                 return ret;
502         }
503 }
504
505 int ofnode_read_string_index(ofnode node, const char *property, int index,
506                              const char **outp)
507 {
508         if (ofnode_is_np(node)) {
509                 return of_property_read_string_index(ofnode_to_np(node),
510                                                      property, index, outp);
511         } else {
512                 int len;
513
514                 *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
515                                            property, index, &len);
516                 if (len < 0)
517                         return -EINVAL;
518                 return 0;
519         }
520 }
521
522 int ofnode_read_string_count(ofnode node, const char *property)
523 {
524         if (ofnode_is_np(node)) {
525                 return of_property_count_strings(ofnode_to_np(node), property);
526         } else {
527                 return fdt_stringlist_count(gd->fdt_blob,
528                                             ofnode_to_offset(node), property);
529         }
530 }
531
532 int ofnode_read_string_list(ofnode node, const char *property,
533                             const char ***listp)
534 {
535         const char **prop;
536         int count;
537         int i;
538
539         *listp = NULL;
540         count = ofnode_read_string_count(node, property);
541         if (count < 0)
542                 return count;
543         if (!count)
544                 return 0;
545
546         prop = calloc(count + 1, sizeof(char *));
547         if (!prop)
548                 return -ENOMEM;
549
550         for (i = 0; i < count; i++)
551                 ofnode_read_string_index(node, property, i, &prop[i]);
552         prop[count] = NULL;
553         *listp = prop;
554
555         return count;
556 }
557
558 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
559                                             struct ofnode_phandle_args *out)
560 {
561         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
562         out->node = offset_to_ofnode(in->node);
563         out->args_count = in->args_count;
564         memcpy(out->args, in->args, sizeof(out->args));
565 }
566
567 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
568                                         struct ofnode_phandle_args *out)
569 {
570         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
571         out->node = np_to_ofnode(in->np);
572         out->args_count = in->args_count;
573         memcpy(out->args, in->args, sizeof(out->args));
574 }
575
576 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
577                                    const char *cells_name, int cell_count,
578                                    int index,
579                                    struct ofnode_phandle_args *out_args)
580 {
581         if (ofnode_is_np(node)) {
582                 struct of_phandle_args args;
583                 int ret;
584
585                 ret = of_parse_phandle_with_args(ofnode_to_np(node),
586                                                  list_name, cells_name,
587                                                  cell_count, index,
588                                                  &args);
589                 if (ret)
590                         return ret;
591                 ofnode_from_of_phandle_args(&args, out_args);
592         } else {
593                 struct fdtdec_phandle_args args;
594                 int ret;
595
596                 ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
597                                                      ofnode_to_offset(node),
598                                                      list_name, cells_name,
599                                                      cell_count, index, &args);
600                 if (ret)
601                         return ret;
602                 ofnode_from_fdtdec_phandle_args(&args, out_args);
603         }
604
605         return 0;
606 }
607
608 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
609                                    const char *cells_name, int cell_count)
610 {
611         if (ofnode_is_np(node))
612                 return of_count_phandle_with_args(ofnode_to_np(node),
613                                 list_name, cells_name, cell_count);
614         else
615                 return fdtdec_parse_phandle_with_args(gd->fdt_blob,
616                                 ofnode_to_offset(node), list_name, cells_name,
617                                 cell_count, -1, NULL);
618 }
619
620 ofnode ofnode_path(const char *path)
621 {
622         if (of_live_active())
623                 return np_to_ofnode(of_find_node_by_path(path));
624         else
625                 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
626 }
627
628 ofnode ofnode_path_root(oftree tree, const char *path)
629 {
630         if (of_live_active())
631                 return np_to_ofnode(of_find_node_opts_by_path(tree.np, path,
632                                                               NULL));
633         else if (*path != '/' && tree.fdt != gd->fdt_blob)
634                 return ofnode_null();  /* Aliases only on control FDT */
635         else
636                 return offset_to_ofnode(fdt_path_offset(tree.fdt, path));
637 }
638
639 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
640 {
641         ofnode chosen_node;
642
643         chosen_node = ofnode_path("/chosen");
644
645         return ofnode_read_prop(chosen_node, propname, sizep);
646 }
647
648 const char *ofnode_read_chosen_string(const char *propname)
649 {
650         return ofnode_read_chosen_prop(propname, NULL);
651 }
652
653 ofnode ofnode_get_chosen_node(const char *name)
654 {
655         const char *prop;
656
657         prop = ofnode_read_chosen_prop(name, NULL);
658         if (!prop)
659                 return ofnode_null();
660
661         return ofnode_path(prop);
662 }
663
664 const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
665 {
666         ofnode node;
667
668         node = ofnode_path("/aliases");
669
670         return ofnode_read_prop(node, propname, sizep);
671 }
672
673 ofnode ofnode_get_aliases_node(const char *name)
674 {
675         const char *prop;
676
677         prop = ofnode_read_aliases_prop(name, NULL);
678         if (!prop)
679                 return ofnode_null();
680
681         debug("%s: node_path: %s\n", __func__, prop);
682
683         return ofnode_path(prop);
684 }
685
686 int ofnode_get_child_count(ofnode parent)
687 {
688         ofnode child;
689         int num = 0;
690
691         ofnode_for_each_subnode(child, parent)
692                 num++;
693
694         return num;
695 }
696
697 static int decode_timing_property(ofnode node, const char *name,
698                                   struct timing_entry *result)
699 {
700         int length, ret = 0;
701
702         length = ofnode_read_size(node, name);
703         if (length < 0) {
704                 debug("%s: could not find property %s\n",
705                       ofnode_get_name(node), name);
706                 return length;
707         }
708
709         if (length == sizeof(u32)) {
710                 result->typ = ofnode_read_u32_default(node, name, 0);
711                 result->min = result->typ;
712                 result->max = result->typ;
713         } else {
714                 ret = ofnode_read_u32_array(node, name, &result->min, 3);
715         }
716
717         return ret;
718 }
719
720 int ofnode_decode_display_timing(ofnode parent, int index,
721                                  struct display_timing *dt)
722 {
723         int i;
724         ofnode timings, node;
725         u32 val = 0;
726         int ret = 0;
727
728         timings = ofnode_find_subnode(parent, "display-timings");
729         if (!ofnode_valid(timings))
730                 return -EINVAL;
731
732         i = 0;
733         ofnode_for_each_subnode(node, timings) {
734                 if (i++ == index)
735                         break;
736         }
737
738         if (!ofnode_valid(node))
739                 return -EINVAL;
740
741         memset(dt, 0, sizeof(*dt));
742
743         ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
744         ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
745         ret |= decode_timing_property(node, "hactive", &dt->hactive);
746         ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
747         ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
748         ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
749         ret |= decode_timing_property(node, "vactive", &dt->vactive);
750         ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
751         ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
752
753         dt->flags = 0;
754         val = ofnode_read_u32_default(node, "vsync-active", -1);
755         if (val != -1) {
756                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
757                                 DISPLAY_FLAGS_VSYNC_LOW;
758         }
759         val = ofnode_read_u32_default(node, "hsync-active", -1);
760         if (val != -1) {
761                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
762                                 DISPLAY_FLAGS_HSYNC_LOW;
763         }
764         val = ofnode_read_u32_default(node, "de-active", -1);
765         if (val != -1) {
766                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
767                                 DISPLAY_FLAGS_DE_LOW;
768         }
769         val = ofnode_read_u32_default(node, "pixelclk-active", -1);
770         if (val != -1) {
771                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
772                                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
773         }
774
775         if (ofnode_read_bool(node, "interlaced"))
776                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
777         if (ofnode_read_bool(node, "doublescan"))
778                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
779         if (ofnode_read_bool(node, "doubleclk"))
780                 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
781
782         return ret;
783 }
784
785 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
786 {
787         if (ofnode_is_np(node))
788                 return of_get_property(ofnode_to_np(node), propname, lenp);
789         else
790                 return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
791                                    propname, lenp);
792 }
793
794 int ofnode_first_property(ofnode node, struct ofprop *prop)
795 {
796         prop->node = node;
797
798         if (ofnode_is_np(node)) {
799                 prop->prop = of_get_first_property(ofnode_to_np(prop->node));
800                 if (!prop->prop)
801                         return -FDT_ERR_NOTFOUND;
802         } else {
803                 prop->offset =
804                         fdt_first_property_offset(gd->fdt_blob,
805                                                   ofnode_to_offset(prop->node));
806                 if (prop->offset < 0)
807                         return prop->offset;
808         }
809
810         return 0;
811 }
812
813 int ofnode_next_property(struct ofprop *prop)
814 {
815         if (ofnode_is_np(prop->node)) {
816                 prop->prop = of_get_next_property(ofnode_to_np(prop->node),
817                                                   prop->prop);
818                 if (!prop->prop)
819                         return -FDT_ERR_NOTFOUND;
820         } else {
821                 prop->offset = fdt_next_property_offset(gd->fdt_blob,
822                                                         prop->offset);
823                 if (prop->offset  < 0)
824                         return prop->offset;
825         }
826
827         return 0;
828 }
829
830 const void *ofprop_get_property(const struct ofprop *prop,
831                                 const char **propname, int *lenp)
832 {
833         if (ofnode_is_np(prop->node))
834                 return of_get_property_by_prop(ofnode_to_np(prop->node),
835                                                prop->prop, propname, lenp);
836         else
837                 return fdt_getprop_by_offset(gd->fdt_blob,
838                                              prop->offset,
839                                              propname, lenp);
840 }
841
842 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
843                                 fdt_size_t *sizep)
844 {
845         if (ofnode_is_np(node)) {
846                 int na, ns;
847                 int psize;
848                 const struct device_node *np = ofnode_to_np(node);
849                 const __be32 *prop = of_get_property(np, property, &psize);
850
851                 if (!prop)
852                         return FDT_ADDR_T_NONE;
853                 na = of_n_addr_cells(np);
854                 ns = of_n_size_cells(np);
855                 *sizep = of_read_number(prop + na, ns);
856
857                 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
858                         return of_translate_address(np, prop);
859                 else
860                         return of_read_number(prop, na);
861         } else {
862                 return fdtdec_get_addr_size(gd->fdt_blob,
863                                             ofnode_to_offset(node), property,
864                                             sizep);
865         }
866 }
867
868 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
869                                         size_t sz)
870 {
871         if (ofnode_is_np(node)) {
872                 const struct device_node *np = ofnode_to_np(node);
873                 int psize;
874                 const __be32 *prop = of_get_property(np, propname, &psize);
875
876                 if (!prop || sz != psize)
877                         return NULL;
878                 return (uint8_t *)prop;
879
880         } else {
881                 return fdtdec_locate_byte_array(gd->fdt_blob,
882                                 ofnode_to_offset(node), propname, sz);
883         }
884 }
885
886 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
887                          const char *propname, struct fdt_pci_addr *addr)
888 {
889         const fdt32_t *cell;
890         int len;
891         int ret = -ENOENT;
892
893         debug("%s: %s: ", __func__, propname);
894
895         /*
896          * If we follow the pci bus bindings strictly, we should check
897          * the value of the node's parent node's #address-cells and
898          * #size-cells. They need to be 3 and 2 accordingly. However,
899          * for simplicity we skip the check here.
900          */
901         cell = ofnode_get_property(node, propname, &len);
902         if (!cell)
903                 goto fail;
904
905         if ((len % FDT_PCI_REG_SIZE) == 0) {
906                 int num = len / FDT_PCI_REG_SIZE;
907                 int i;
908
909                 for (i = 0; i < num; i++) {
910                         debug("pci address #%d: %08lx %08lx %08lx\n", i,
911                               (ulong)fdt32_to_cpu(cell[0]),
912                               (ulong)fdt32_to_cpu(cell[1]),
913                               (ulong)fdt32_to_cpu(cell[2]));
914                         if ((fdt32_to_cpu(*cell) & type) == type) {
915                                 addr->phys_hi = fdt32_to_cpu(cell[0]);
916                                 addr->phys_mid = fdt32_to_cpu(cell[1]);
917                                 addr->phys_lo = fdt32_to_cpu(cell[2]);
918                                 break;
919                         }
920
921                         cell += (FDT_PCI_ADDR_CELLS +
922                                  FDT_PCI_SIZE_CELLS);
923                 }
924
925                 if (i == num) {
926                         ret = -ENXIO;
927                         goto fail;
928                 }
929
930                 return 0;
931         }
932
933         ret = -EINVAL;
934
935 fail:
936         debug("(not found)\n");
937         return ret;
938 }
939
940 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
941 {
942         const char *list, *end;
943         int len;
944
945         list = ofnode_get_property(node, "compatible", &len);
946         if (!list)
947                 return -ENOENT;
948
949         end = list + len;
950         while (list < end) {
951                 len = strlen(list);
952                 if (len >= strlen("pciVVVV,DDDD")) {
953                         char *s = strstr(list, "pci");
954
955                         /*
956                          * check if the string is something like pciVVVV,DDDD.RR
957                          * or just pciVVVV,DDDD
958                          */
959                         if (s && s[7] == ',' &&
960                             (s[12] == '.' || s[12] == 0)) {
961                                 s += 3;
962                                 *vendor = simple_strtol(s, NULL, 16);
963
964                                 s += 5;
965                                 *device = simple_strtol(s, NULL, 16);
966
967                                 return 0;
968                         }
969                 }
970                 list += (len + 1);
971         }
972
973         return -ENOENT;
974 }
975
976 int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
977 {
978         const char *list, *end;
979         int len;
980
981         list = ofnode_get_property(node, "compatible", &len);
982
983         if (!list)
984                 return -ENOENT;
985
986         end = list + len;
987         while (list < end) {
988                 len = strlen(list);
989
990                 if (len >= strlen("ethernet-phy-idVVVV,DDDD")) {
991                         char *s = strstr(list, "ethernet-phy-id");
992
993                         /*
994                          * check if the string is something like
995                          * ethernet-phy-idVVVV,DDDD
996                          */
997                         if (s && s[19] == '.') {
998                                 s += strlen("ethernet-phy-id");
999                                 *vendor = simple_strtol(s, NULL, 16);
1000                                 s += 5;
1001                                 *device = simple_strtol(s, NULL, 16);
1002
1003                                 return 0;
1004                         }
1005                 }
1006                 list += (len + 1);
1007         }
1008
1009         return -ENOENT;
1010 }
1011
1012 int ofnode_read_addr_cells(ofnode node)
1013 {
1014         if (ofnode_is_np(node)) {
1015                 return of_n_addr_cells(ofnode_to_np(node));
1016         } else {
1017                 int parent = fdt_parent_offset(gd->fdt_blob,
1018                                                ofnode_to_offset(node));
1019
1020                 return fdt_address_cells(gd->fdt_blob, parent);
1021         }
1022 }
1023
1024 int ofnode_read_size_cells(ofnode node)
1025 {
1026         if (ofnode_is_np(node)) {
1027                 return of_n_size_cells(ofnode_to_np(node));
1028         } else {
1029                 int parent = fdt_parent_offset(gd->fdt_blob,
1030                                                ofnode_to_offset(node));
1031
1032                 return fdt_size_cells(gd->fdt_blob, parent);
1033         }
1034 }
1035
1036 int ofnode_read_simple_addr_cells(ofnode node)
1037 {
1038         if (ofnode_is_np(node))
1039                 return of_simple_addr_cells(ofnode_to_np(node));
1040         else
1041                 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
1042 }
1043
1044 int ofnode_read_simple_size_cells(ofnode node)
1045 {
1046         if (ofnode_is_np(node))
1047                 return of_simple_size_cells(ofnode_to_np(node));
1048         else
1049                 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
1050 }
1051
1052 bool ofnode_pre_reloc(ofnode node)
1053 {
1054 #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
1055         /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
1056          * had property dm-pre-reloc or u-boot,dm-spl/tpl.
1057          * They are removed in final dtb (fdtgrep 2nd pass)
1058          */
1059         return true;
1060 #else
1061         if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
1062                 return true;
1063         if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
1064                 return true;
1065
1066         /*
1067          * In regular builds individual spl and tpl handling both
1068          * count as handled pre-relocation for later second init.
1069          */
1070         if (ofnode_read_bool(node, "u-boot,dm-spl") ||
1071             ofnode_read_bool(node, "u-boot,dm-tpl"))
1072                 return true;
1073
1074         return false;
1075 #endif
1076 }
1077
1078 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
1079 {
1080         if (ofnode_is_np(node)) {
1081                 return of_address_to_resource(ofnode_to_np(node), index, res);
1082         } else {
1083                 struct fdt_resource fres;
1084                 int ret;
1085
1086                 ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
1087                                        "reg", index, &fres);
1088                 if (ret < 0)
1089                         return -EINVAL;
1090                 memset(res, '\0', sizeof(*res));
1091                 res->start = fres.start;
1092                 res->end = fres.end;
1093
1094                 return 0;
1095         }
1096 }
1097
1098 int ofnode_read_resource_byname(ofnode node, const char *name,
1099                                 struct resource *res)
1100 {
1101         int index;
1102
1103         index = ofnode_stringlist_search(node, "reg-names", name);
1104         if (index < 0)
1105                 return index;
1106
1107         return ofnode_read_resource(node, index, res);
1108 }
1109
1110 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
1111 {
1112         if (ofnode_is_np(node))
1113                 return of_translate_address(ofnode_to_np(node), in_addr);
1114         else
1115                 return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
1116 }
1117
1118 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
1119 {
1120         if (ofnode_is_np(node))
1121                 return of_translate_dma_address(ofnode_to_np(node), in_addr);
1122         else
1123                 return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
1124 }
1125
1126 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
1127 {
1128         if (ofnode_is_np(node))
1129                 return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
1130         else
1131                 return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node),
1132                                          cpu, bus, size);
1133 }
1134
1135 int ofnode_device_is_compatible(ofnode node, const char *compat)
1136 {
1137         if (ofnode_is_np(node))
1138                 return of_device_is_compatible(ofnode_to_np(node), compat,
1139                                                NULL, NULL);
1140         else
1141                 return !fdt_node_check_compatible(gd->fdt_blob,
1142                                                   ofnode_to_offset(node),
1143                                                   compat);
1144 }
1145
1146 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1147 {
1148         if (of_live_active()) {
1149                 return np_to_ofnode(of_find_compatible_node(
1150                         (struct device_node *)ofnode_to_np(from), NULL,
1151                         compat));
1152         } else {
1153                 return offset_to_ofnode(fdt_node_offset_by_compatible(
1154                                 gd->fdt_blob, ofnode_to_offset(from), compat));
1155         }
1156 }
1157
1158 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1159                             const void *propval, int proplen)
1160 {
1161         if (of_live_active()) {
1162                 return np_to_ofnode(of_find_node_by_prop_value(
1163                         (struct device_node *)ofnode_to_np(from), propname,
1164                         propval, proplen));
1165         } else {
1166                 return offset_to_ofnode(fdt_node_offset_by_prop_value(
1167                                 gd->fdt_blob, ofnode_to_offset(from),
1168                                 propname, propval, proplen));
1169         }
1170 }
1171
1172 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
1173                       int len)
1174 {
1175         if (of_live_active())
1176                 return of_write_prop(ofnode_to_np(node), propname, len, value);
1177         else
1178                 return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node),
1179                                    propname, value, len);
1180
1181         return 0;
1182 }
1183
1184 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1185 {
1186         assert(ofnode_valid(node));
1187
1188         debug("%s: %s = %s", __func__, propname, value);
1189
1190         return ofnode_write_prop(node, propname, value, strlen(value) + 1);
1191 }
1192
1193 int ofnode_write_u32(ofnode node, const char *propname, u32 value)
1194 {
1195         fdt32_t *val;
1196
1197         assert(ofnode_valid(node));
1198
1199         log_debug("%s = %x", propname, value);
1200         val = malloc(sizeof(*val));
1201         if (!val)
1202                 return -ENOMEM;
1203         *val = cpu_to_fdt32(value);
1204
1205         return ofnode_write_prop(node, propname, val, sizeof(value));
1206 }
1207
1208 int ofnode_set_enabled(ofnode node, bool value)
1209 {
1210         assert(ofnode_valid(node));
1211
1212         if (value)
1213                 return ofnode_write_string(node, "status", "okay");
1214         else
1215                 return ofnode_write_string(node, "status", "disabled");
1216 }
1217
1218 bool ofnode_conf_read_bool(const char *prop_name)
1219 {
1220         ofnode node;
1221
1222         node = ofnode_path("/config");
1223         if (!ofnode_valid(node))
1224                 return false;
1225
1226         return ofnode_read_bool(node, prop_name);
1227 }
1228
1229 int ofnode_conf_read_int(const char *prop_name, int default_val)
1230 {
1231         ofnode node;
1232
1233         node = ofnode_path("/config");
1234         if (!ofnode_valid(node))
1235                 return default_val;
1236
1237         return ofnode_read_u32_default(node, prop_name, default_val);
1238 }
1239
1240 const char *ofnode_conf_read_str(const char *prop_name)
1241 {
1242         ofnode node;
1243
1244         node = ofnode_path("/config");
1245         if (!ofnode_valid(node))
1246                 return NULL;
1247
1248         return ofnode_read_string(node, prop_name);
1249 }
1250
1251 ofnode ofnode_get_phy_node(ofnode node)
1252 {
1253         /* DT node properties that reference a PHY node */
1254         static const char * const phy_handle_str[] = {
1255                 "phy-handle", "phy", "phy-device",
1256         };
1257         struct ofnode_phandle_args args = {
1258                 .node = ofnode_null()
1259         };
1260         int i;
1261
1262         assert(ofnode_valid(node));
1263
1264         for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++)
1265                 if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i],
1266                                                     NULL, 0, 0, &args))
1267                         break;
1268
1269         return args.node;
1270 }
1271
1272 phy_interface_t ofnode_read_phy_mode(ofnode node)
1273 {
1274         const char *mode;
1275         int i;
1276
1277         assert(ofnode_valid(node));
1278
1279         mode = ofnode_read_string(node, "phy-mode");
1280         if (!mode)
1281                 mode = ofnode_read_string(node, "phy-connection-type");
1282
1283         if (!mode)
1284                 return PHY_INTERFACE_MODE_NA;
1285
1286         for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
1287                 if (!strcmp(mode, phy_interface_strings[i]))
1288                         return i;
1289
1290         debug("%s: Invalid PHY interface '%s'\n", __func__, mode);
1291
1292         return PHY_INTERFACE_MODE_NA;
1293 }
1294
1295 int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
1296 {
1297         ofnode subnode;
1298         int ret = 0;
1299
1300         assert(ofnode_valid(node));
1301
1302         if (ofnode_is_np(node)) {
1303                 struct device_node *np, *child;
1304
1305                 np = (struct device_node *)ofnode_to_np(node);
1306                 ret = of_add_subnode(np, name, -1, &child);
1307                 if (ret && ret != -EEXIST)
1308                         return ret;
1309                 subnode = np_to_ofnode(child);
1310         } else {
1311                 void *fdt = (void *)gd->fdt_blob;
1312                 int poffset = ofnode_to_offset(node);
1313                 int offset;
1314
1315                 offset = fdt_add_subnode(fdt, poffset, name);
1316                 if (offset == -FDT_ERR_EXISTS) {
1317                         offset = fdt_subnode_offset(fdt, poffset, name);
1318                         ret = -EEXIST;
1319                 }
1320                 if (offset < 0)
1321                         return -EINVAL;
1322                 subnode = offset_to_ofnode(offset);
1323         }
1324
1325         *subnodep = subnode;
1326
1327         return ret;     /* 0 or -EEXIST */
1328 }