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