Merge tag 'u-boot-atmel-fixes-2020.04-a' of https://gitlab.denx.de/u-boot/custodians...
[oweals/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 <malloc.h>
12 #include <linux/libfdt.h>
13 #include <dm/of_access.h>
14 #include <dm/of_addr.h>
15 #include <dm/ofnode.h>
16 #include <linux/err.h>
17 #include <linux/ioport.h>
18
19 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
20 {
21         assert(ofnode_valid(node));
22         debug("%s: %s: ", __func__, propname);
23
24         if (ofnode_is_np(node)) {
25                 return of_read_u32(ofnode_to_np(node), propname, outp);
26         } else {
27                 const fdt32_t *cell;
28                 int len;
29
30                 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
31                                    propname, &len);
32                 if (!cell || len < sizeof(int)) {
33                         debug("(not found)\n");
34                         return -EINVAL;
35                 }
36                 *outp = fdt32_to_cpu(cell[0]);
37         }
38         debug("%#x (%d)\n", *outp, *outp);
39
40         return 0;
41 }
42
43 u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
44 {
45         assert(ofnode_valid(node));
46         ofnode_read_u32(node, propname, &def);
47
48         return def;
49 }
50
51 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
52 {
53         assert(ofnode_valid(node));
54         ofnode_read_u32(node, propname, (u32 *)&def);
55
56         return def;
57 }
58
59 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
60 {
61         const unaligned_fdt64_t *cell;
62         int len;
63
64         assert(ofnode_valid(node));
65         debug("%s: %s: ", __func__, propname);
66
67         if (ofnode_is_np(node))
68                 return of_read_u64(ofnode_to_np(node), propname, outp);
69
70         cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
71                            &len);
72         if (!cell || len < sizeof(*cell)) {
73                 debug("(not found)\n");
74                 return -EINVAL;
75         }
76         *outp = fdt64_to_cpu(cell[0]);
77         debug("%#llx (%lld)\n", (unsigned long long)*outp,
78               (unsigned long long)*outp);
79
80         return 0;
81 }
82
83 u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
84 {
85         assert(ofnode_valid(node));
86         ofnode_read_u64(node, propname, &def);
87
88         return def;
89 }
90
91 bool ofnode_read_bool(ofnode node, const char *propname)
92 {
93         const void *prop;
94
95         assert(ofnode_valid(node));
96         debug("%s: %s: ", __func__, propname);
97
98         prop = ofnode_get_property(node, propname, NULL);
99
100         debug("%s\n", prop ? "true" : "false");
101
102         return prop ? true : false;
103 }
104
105 const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
106 {
107         const char *val = NULL;
108         int len;
109
110         assert(ofnode_valid(node));
111         debug("%s: %s: ", __func__, propname);
112
113         if (ofnode_is_np(node)) {
114                 struct property *prop = of_find_property(
115                                 ofnode_to_np(node), propname, &len);
116
117                 if (prop) {
118                         val = prop->value;
119                         len = prop->length;
120                 }
121         } else {
122                 val = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
123                                   propname, &len);
124         }
125         if (!val) {
126                 debug("<not found>\n");
127                 if (sizep)
128                         *sizep = -FDT_ERR_NOTFOUND;
129                 return NULL;
130         }
131         if (sizep)
132                 *sizep = len;
133
134         return val;
135 }
136
137 const char *ofnode_read_string(ofnode node, const char *propname)
138 {
139         const char *str;
140         int len;
141
142         str = ofnode_read_prop(node, propname, &len);
143         if (!str)
144                 return NULL;
145
146         if (strnlen(str, len) >= len) {
147                 debug("<invalid>\n");
148                 return NULL;
149         }
150         debug("%s\n", str);
151
152         return str;
153 }
154
155 int ofnode_read_size(ofnode node, const char *propname)
156 {
157         int len;
158
159         if (!ofnode_read_prop(node, propname, &len))
160                 return -EINVAL;
161
162         return len;
163 }
164
165 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
166 {
167         ofnode subnode;
168
169         assert(ofnode_valid(node));
170         debug("%s: %s: ", __func__, subnode_name);
171
172         if (ofnode_is_np(node)) {
173                 const struct device_node *np = ofnode_to_np(node);
174
175                 for (np = np->child; np; np = np->sibling) {
176                         if (!strcmp(subnode_name, np->name))
177                                 break;
178                 }
179                 subnode = np_to_ofnode(np);
180         } else {
181                 int ooffset = fdt_subnode_offset(gd->fdt_blob,
182                                 ofnode_to_offset(node), subnode_name);
183                 subnode = offset_to_ofnode(ooffset);
184         }
185         debug("%s\n", ofnode_valid(subnode) ?
186               ofnode_get_name(subnode) : "<none>");
187
188         return subnode;
189 }
190
191 int ofnode_read_u32_array(ofnode node, const char *propname,
192                           u32 *out_values, size_t sz)
193 {
194         assert(ofnode_valid(node));
195         debug("%s: %s: ", __func__, propname);
196
197         if (ofnode_is_np(node)) {
198                 return of_read_u32_array(ofnode_to_np(node), propname,
199                                          out_values, sz);
200         } else {
201                 return fdtdec_get_int_array(gd->fdt_blob,
202                                             ofnode_to_offset(node), propname,
203                                             out_values, sz);
204         }
205 }
206
207 ofnode ofnode_first_subnode(ofnode node)
208 {
209         assert(ofnode_valid(node));
210         if (ofnode_is_np(node))
211                 return np_to_ofnode(node.np->child);
212
213         return offset_to_ofnode(
214                 fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node)));
215 }
216
217 ofnode ofnode_next_subnode(ofnode node)
218 {
219         assert(ofnode_valid(node));
220         if (ofnode_is_np(node))
221                 return np_to_ofnode(node.np->sibling);
222
223         return offset_to_ofnode(
224                 fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node)));
225 }
226
227 ofnode ofnode_get_parent(ofnode node)
228 {
229         ofnode parent;
230
231         assert(ofnode_valid(node));
232         if (ofnode_is_np(node))
233                 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
234         else
235                 parent.of_offset = fdt_parent_offset(gd->fdt_blob,
236                                                      ofnode_to_offset(node));
237
238         return parent;
239 }
240
241 const char *ofnode_get_name(ofnode node)
242 {
243         if (!ofnode_valid(node)) {
244                 debug("%s node not valid\n", __func__);
245                 return NULL;
246         }
247
248         if (ofnode_is_np(node))
249                 return strrchr(node.np->full_name, '/') + 1;
250
251         return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
252 }
253
254 ofnode ofnode_get_by_phandle(uint phandle)
255 {
256         ofnode node;
257
258         if (of_live_active())
259                 node = np_to_ofnode(of_find_node_by_phandle(phandle));
260         else
261                 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
262                                                             phandle);
263
264         return node;
265 }
266
267 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
268 {
269         int na, ns;
270
271         if (ofnode_is_np(node)) {
272                 const __be32 *prop_val;
273                 u64 size64;
274                 uint flags;
275
276                 prop_val = of_get_address(ofnode_to_np(node), index, &size64,
277                                           &flags);
278                 if (!prop_val)
279                         return FDT_ADDR_T_NONE;
280                 if (size)
281                         *size = size64;
282
283                 ns = of_n_size_cells(ofnode_to_np(node));
284
285                 if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
286                         return of_translate_address(ofnode_to_np(node), prop_val);
287                 } else {
288                         na = of_n_addr_cells(ofnode_to_np(node));
289                         return of_read_number(prop_val, na);
290                 }
291         } else {
292                 na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
293                 ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
294                 return fdtdec_get_addr_size_fixed(gd->fdt_blob,
295                                                   ofnode_to_offset(node), "reg",
296                                                   index, na, ns, size, true);
297         }
298
299         return FDT_ADDR_T_NONE;
300 }
301
302 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
303 {
304         fdt_size_t size;
305
306         return ofnode_get_addr_size_index(node, index, &size);
307 }
308
309 fdt_addr_t ofnode_get_addr(ofnode node)
310 {
311         return ofnode_get_addr_index(node, 0);
312 }
313
314 int ofnode_stringlist_search(ofnode node, const char *property,
315                              const char *string)
316 {
317         if (ofnode_is_np(node)) {
318                 return of_property_match_string(ofnode_to_np(node),
319                                                 property, string);
320         } else {
321                 int ret;
322
323                 ret = fdt_stringlist_search(gd->fdt_blob,
324                                             ofnode_to_offset(node), property,
325                                             string);
326                 if (ret == -FDT_ERR_NOTFOUND)
327                         return -ENODATA;
328                 else if (ret < 0)
329                         return -EINVAL;
330
331                 return ret;
332         }
333 }
334
335 int ofnode_read_string_index(ofnode node, const char *property, int index,
336                              const char **outp)
337 {
338         if (ofnode_is_np(node)) {
339                 return of_property_read_string_index(ofnode_to_np(node),
340                                                      property, index, outp);
341         } else {
342                 int len;
343
344                 *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
345                                            property, index, &len);
346                 if (len < 0)
347                         return -EINVAL;
348                 return 0;
349         }
350 }
351
352 int ofnode_read_string_count(ofnode node, const char *property)
353 {
354         if (ofnode_is_np(node)) {
355                 return of_property_count_strings(ofnode_to_np(node), property);
356         } else {
357                 return fdt_stringlist_count(gd->fdt_blob,
358                                             ofnode_to_offset(node), property);
359         }
360 }
361
362 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
363                                             struct ofnode_phandle_args *out)
364 {
365         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
366         out->node = offset_to_ofnode(in->node);
367         out->args_count = in->args_count;
368         memcpy(out->args, in->args, sizeof(out->args));
369 }
370
371 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
372                                         struct ofnode_phandle_args *out)
373 {
374         assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
375         out->node = np_to_ofnode(in->np);
376         out->args_count = in->args_count;
377         memcpy(out->args, in->args, sizeof(out->args));
378 }
379
380 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
381                                    const char *cells_name, int cell_count,
382                                    int index,
383                                    struct ofnode_phandle_args *out_args)
384 {
385         if (ofnode_is_np(node)) {
386                 struct of_phandle_args args;
387                 int ret;
388
389                 ret = of_parse_phandle_with_args(ofnode_to_np(node),
390                                                  list_name, cells_name, index,
391                                                  &args);
392                 if (ret)
393                         return ret;
394                 ofnode_from_of_phandle_args(&args, out_args);
395         } else {
396                 struct fdtdec_phandle_args args;
397                 int ret;
398
399                 ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
400                                                      ofnode_to_offset(node),
401                                                      list_name, cells_name,
402                                                      cell_count, index, &args);
403                 if (ret)
404                         return ret;
405                 ofnode_from_fdtdec_phandle_args(&args, out_args);
406         }
407
408         return 0;
409 }
410
411 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
412                                    const char *cells_name)
413 {
414         if (ofnode_is_np(node))
415                 return of_count_phandle_with_args(ofnode_to_np(node),
416                                 list_name, cells_name);
417         else
418                 return fdtdec_parse_phandle_with_args(gd->fdt_blob,
419                                 ofnode_to_offset(node), list_name, cells_name,
420                                 0, -1, NULL);
421 }
422
423 ofnode ofnode_path(const char *path)
424 {
425         if (of_live_active())
426                 return np_to_ofnode(of_find_node_by_path(path));
427         else
428                 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
429 }
430
431 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
432 {
433         ofnode chosen_node;
434
435         chosen_node = ofnode_path("/chosen");
436
437         return ofnode_read_prop(chosen_node, propname, sizep);
438 }
439
440 const char *ofnode_read_chosen_string(const char *propname)
441 {
442         return ofnode_read_chosen_prop(propname, NULL);
443 }
444
445 ofnode ofnode_get_chosen_node(const char *name)
446 {
447         const char *prop;
448
449         prop = ofnode_read_chosen_prop(name, NULL);
450         if (!prop)
451                 return ofnode_null();
452
453         return ofnode_path(prop);
454 }
455
456 static int decode_timing_property(ofnode node, const char *name,
457                                   struct timing_entry *result)
458 {
459         int length, ret = 0;
460
461         length = ofnode_read_size(node, name);
462         if (length < 0) {
463                 debug("%s: could not find property %s\n",
464                       ofnode_get_name(node), name);
465                 return length;
466         }
467
468         if (length == sizeof(u32)) {
469                 result->typ = ofnode_read_u32_default(node, name, 0);
470                 result->min = result->typ;
471                 result->max = result->typ;
472         } else {
473                 ret = ofnode_read_u32_array(node, name, &result->min, 3);
474         }
475
476         return ret;
477 }
478
479 int ofnode_decode_display_timing(ofnode parent, int index,
480                                  struct display_timing *dt)
481 {
482         int i;
483         ofnode timings, node;
484         u32 val = 0;
485         int ret = 0;
486
487         timings = ofnode_find_subnode(parent, "display-timings");
488         if (!ofnode_valid(timings))
489                 return -EINVAL;
490
491         i = 0;
492         ofnode_for_each_subnode(node, timings) {
493                 if (i++ == index)
494                         break;
495         }
496
497         if (!ofnode_valid(node))
498                 return -EINVAL;
499
500         memset(dt, 0, sizeof(*dt));
501
502         ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
503         ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
504         ret |= decode_timing_property(node, "hactive", &dt->hactive);
505         ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
506         ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
507         ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
508         ret |= decode_timing_property(node, "vactive", &dt->vactive);
509         ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
510         ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
511
512         dt->flags = 0;
513         val = ofnode_read_u32_default(node, "vsync-active", -1);
514         if (val != -1) {
515                 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
516                                 DISPLAY_FLAGS_VSYNC_LOW;
517         }
518         val = ofnode_read_u32_default(node, "hsync-active", -1);
519         if (val != -1) {
520                 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
521                                 DISPLAY_FLAGS_HSYNC_LOW;
522         }
523         val = ofnode_read_u32_default(node, "de-active", -1);
524         if (val != -1) {
525                 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
526                                 DISPLAY_FLAGS_DE_LOW;
527         }
528         val = ofnode_read_u32_default(node, "pixelclk-active", -1);
529         if (val != -1) {
530                 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
531                                 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
532         }
533
534         if (ofnode_read_bool(node, "interlaced"))
535                 dt->flags |= DISPLAY_FLAGS_INTERLACED;
536         if (ofnode_read_bool(node, "doublescan"))
537                 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
538         if (ofnode_read_bool(node, "doubleclk"))
539                 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
540
541         return ret;
542 }
543
544 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
545 {
546         if (ofnode_is_np(node))
547                 return of_get_property(ofnode_to_np(node), propname, lenp);
548         else
549                 return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
550                                    propname, lenp);
551 }
552
553 bool ofnode_is_available(ofnode node)
554 {
555         if (ofnode_is_np(node))
556                 return of_device_is_available(ofnode_to_np(node));
557         else
558                 return fdtdec_get_is_enabled(gd->fdt_blob,
559                                              ofnode_to_offset(node));
560 }
561
562 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
563                                 fdt_size_t *sizep)
564 {
565         if (ofnode_is_np(node)) {
566                 int na, ns;
567                 int psize;
568                 const struct device_node *np = ofnode_to_np(node);
569                 const __be32 *prop = of_get_property(np, property, &psize);
570
571                 if (!prop)
572                         return FDT_ADDR_T_NONE;
573                 na = of_n_addr_cells(np);
574                 ns = of_n_size_cells(np);
575                 *sizep = of_read_number(prop + na, ns);
576
577                 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
578                         return of_translate_address(np, prop);
579                 else
580                         return of_read_number(prop, na);
581         } else {
582                 return fdtdec_get_addr_size(gd->fdt_blob,
583                                             ofnode_to_offset(node), property,
584                                             sizep);
585         }
586 }
587
588 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
589                                         size_t sz)
590 {
591         if (ofnode_is_np(node)) {
592                 const struct device_node *np = ofnode_to_np(node);
593                 int psize;
594                 const __be32 *prop = of_get_property(np, propname, &psize);
595
596                 if (!prop || sz != psize)
597                         return NULL;
598                 return (uint8_t *)prop;
599
600         } else {
601                 return fdtdec_locate_byte_array(gd->fdt_blob,
602                                 ofnode_to_offset(node), propname, sz);
603         }
604 }
605
606 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
607                          const char *propname, struct fdt_pci_addr *addr)
608 {
609         const fdt32_t *cell;
610         int len;
611         int ret = -ENOENT;
612
613         debug("%s: %s: ", __func__, propname);
614
615         /*
616          * If we follow the pci bus bindings strictly, we should check
617          * the value of the node's parent node's #address-cells and
618          * #size-cells. They need to be 3 and 2 accordingly. However,
619          * for simplicity we skip the check here.
620          */
621         cell = ofnode_get_property(node, propname, &len);
622         if (!cell)
623                 goto fail;
624
625         if ((len % FDT_PCI_REG_SIZE) == 0) {
626                 int num = len / FDT_PCI_REG_SIZE;
627                 int i;
628
629                 for (i = 0; i < num; i++) {
630                         debug("pci address #%d: %08lx %08lx %08lx\n", i,
631                               (ulong)fdt32_to_cpu(cell[0]),
632                               (ulong)fdt32_to_cpu(cell[1]),
633                               (ulong)fdt32_to_cpu(cell[2]));
634                         if ((fdt32_to_cpu(*cell) & type) == type) {
635                                 addr->phys_hi = fdt32_to_cpu(cell[0]);
636                                 addr->phys_mid = fdt32_to_cpu(cell[1]);
637                                 addr->phys_lo = fdt32_to_cpu(cell[2]);
638                                 break;
639                         }
640
641                         cell += (FDT_PCI_ADDR_CELLS +
642                                  FDT_PCI_SIZE_CELLS);
643                 }
644
645                 if (i == num) {
646                         ret = -ENXIO;
647                         goto fail;
648                 }
649
650                 return 0;
651         }
652
653         ret = -EINVAL;
654
655 fail:
656         debug("(not found)\n");
657         return ret;
658 }
659
660 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
661 {
662         const char *list, *end;
663         int len;
664
665         list = ofnode_get_property(node, "compatible", &len);
666         if (!list)
667                 return -ENOENT;
668
669         end = list + len;
670         while (list < end) {
671                 len = strlen(list);
672                 if (len >= strlen("pciVVVV,DDDD")) {
673                         char *s = strstr(list, "pci");
674
675                         /*
676                          * check if the string is something like pciVVVV,DDDD.RR
677                          * or just pciVVVV,DDDD
678                          */
679                         if (s && s[7] == ',' &&
680                             (s[12] == '.' || s[12] == 0)) {
681                                 s += 3;
682                                 *vendor = simple_strtol(s, NULL, 16);
683
684                                 s += 5;
685                                 *device = simple_strtol(s, NULL, 16);
686
687                                 return 0;
688                         }
689                 }
690                 list += (len + 1);
691         }
692
693         return -ENOENT;
694 }
695
696 int ofnode_read_addr_cells(ofnode node)
697 {
698         if (ofnode_is_np(node))
699                 return of_n_addr_cells(ofnode_to_np(node));
700         else  /* NOTE: this call should walk up the parent stack */
701                 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
702 }
703
704 int ofnode_read_size_cells(ofnode node)
705 {
706         if (ofnode_is_np(node))
707                 return of_n_size_cells(ofnode_to_np(node));
708         else  /* NOTE: this call should walk up the parent stack */
709                 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
710 }
711
712 int ofnode_read_simple_addr_cells(ofnode node)
713 {
714         if (ofnode_is_np(node))
715                 return of_simple_addr_cells(ofnode_to_np(node));
716         else
717                 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
718 }
719
720 int ofnode_read_simple_size_cells(ofnode node)
721 {
722         if (ofnode_is_np(node))
723                 return of_simple_size_cells(ofnode_to_np(node));
724         else
725                 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
726 }
727
728 bool ofnode_pre_reloc(ofnode node)
729 {
730 #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
731         /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
732          * had property dm-pre-reloc or u-boot,dm-spl/tpl.
733          * They are removed in final dtb (fdtgrep 2nd pass)
734          */
735         return true;
736 #else
737         if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
738                 return true;
739         if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
740                 return true;
741
742         /*
743          * In regular builds individual spl and tpl handling both
744          * count as handled pre-relocation for later second init.
745          */
746         if (ofnode_read_bool(node, "u-boot,dm-spl") ||
747             ofnode_read_bool(node, "u-boot,dm-tpl"))
748                 return true;
749
750         return false;
751 #endif
752 }
753
754 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
755 {
756         if (ofnode_is_np(node)) {
757                 return of_address_to_resource(ofnode_to_np(node), index, res);
758         } else {
759                 struct fdt_resource fres;
760                 int ret;
761
762                 ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
763                                        "reg", index, &fres);
764                 if (ret < 0)
765                         return -EINVAL;
766                 memset(res, '\0', sizeof(*res));
767                 res->start = fres.start;
768                 res->end = fres.end;
769
770                 return 0;
771         }
772 }
773
774 int ofnode_read_resource_byname(ofnode node, const char *name,
775                                 struct resource *res)
776 {
777         int index;
778
779         index = ofnode_stringlist_search(node, "reg-names", name);
780         if (index < 0)
781                 return index;
782
783         return ofnode_read_resource(node, index, res);
784 }
785
786 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
787 {
788         if (ofnode_is_np(node))
789                 return of_translate_address(ofnode_to_np(node), in_addr);
790         else
791                 return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
792 }
793
794 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
795 {
796         if (ofnode_is_np(node))
797                 return of_translate_dma_address(ofnode_to_np(node), in_addr);
798         else
799                 return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
800 }
801
802 int ofnode_device_is_compatible(ofnode node, const char *compat)
803 {
804         if (ofnode_is_np(node))
805                 return of_device_is_compatible(ofnode_to_np(node), compat,
806                                                NULL, NULL);
807         else
808                 return !fdt_node_check_compatible(gd->fdt_blob,
809                                                   ofnode_to_offset(node),
810                                                   compat);
811 }
812
813 ofnode ofnode_by_compatible(ofnode from, const char *compat)
814 {
815         if (of_live_active()) {
816                 return np_to_ofnode(of_find_compatible_node(
817                         (struct device_node *)ofnode_to_np(from), NULL,
818                         compat));
819         } else {
820                 return offset_to_ofnode(fdt_node_offset_by_compatible(
821                                 gd->fdt_blob, ofnode_to_offset(from), compat));
822         }
823 }
824
825 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
826                             const void *propval, int proplen)
827 {
828         if (of_live_active()) {
829                 return np_to_ofnode(of_find_node_by_prop_value(
830                         (struct device_node *)ofnode_to_np(from), propname,
831                         propval, proplen));
832         } else {
833                 return offset_to_ofnode(fdt_node_offset_by_prop_value(
834                                 gd->fdt_blob, ofnode_to_offset(from),
835                                 propname, propval, proplen));
836         }
837 }
838
839 int ofnode_write_prop(ofnode node, const char *propname, int len,
840                       const void *value)
841 {
842         const struct device_node *np = ofnode_to_np(node);
843         struct property *pp;
844         struct property *pp_last = NULL;
845         struct property *new;
846
847         if (!of_live_active())
848                 return -ENOSYS;
849
850         if (!np)
851                 return -EINVAL;
852
853         for (pp = np->properties; pp; pp = pp->next) {
854                 if (strcmp(pp->name, propname) == 0) {
855                         /* Property exists -> change value */
856                         pp->value = (void *)value;
857                         pp->length = len;
858                         return 0;
859                 }
860                 pp_last = pp;
861         }
862
863         if (!pp_last)
864                 return -ENOENT;
865
866         /* Property does not exist -> append new property */
867         new = malloc(sizeof(struct property));
868         if (!new)
869                 return -ENOMEM;
870
871         new->name = strdup(propname);
872         if (!new->name) {
873                 free(new);
874                 return -ENOMEM;
875         }
876
877         new->value = (void *)value;
878         new->length = len;
879         new->next = NULL;
880
881         pp_last->next = new;
882
883         return 0;
884 }
885
886 int ofnode_write_string(ofnode node, const char *propname, const char *value)
887 {
888         if (!of_live_active())
889                 return -ENOSYS;
890
891         assert(ofnode_valid(node));
892
893         debug("%s: %s = %s", __func__, propname, value);
894
895         return ofnode_write_prop(node, propname, strlen(value) + 1, value);
896 }
897
898 int ofnode_set_enabled(ofnode node, bool value)
899 {
900         if (!of_live_active())
901                 return -ENOSYS;
902
903         assert(ofnode_valid(node));
904
905         if (value)
906                 return ofnode_write_string(node, "status", "okay");
907         else
908                 return ofnode_write_string(node, "status", "disabled");
909 }