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