Merge branch 'next' of https://gitlab.denx.de/u-boot/custodians/u-boot-riscv into...
[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                 const 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 strrchr(node.np->full_name, '/') + 1;
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(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_get_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_get_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 *ofnode_get_property_by_prop(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 bool ofnode_is_available(ofnode node)
832 {
833         if (ofnode_is_np(node))
834                 return of_device_is_available(ofnode_to_np(node));
835         else
836                 return fdtdec_get_is_enabled(gd->fdt_blob,
837                                              ofnode_to_offset(node));
838 }
839
840 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
841                                 fdt_size_t *sizep)
842 {
843         if (ofnode_is_np(node)) {
844                 int na, ns;
845                 int psize;
846                 const struct device_node *np = ofnode_to_np(node);
847                 const __be32 *prop = of_get_property(np, property, &psize);
848
849                 if (!prop)
850                         return FDT_ADDR_T_NONE;
851                 na = of_n_addr_cells(np);
852                 ns = of_n_size_cells(np);
853                 *sizep = of_read_number(prop + na, ns);
854
855                 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
856                         return of_translate_address(np, prop);
857                 else
858                         return of_read_number(prop, na);
859         } else {
860                 return fdtdec_get_addr_size(gd->fdt_blob,
861                                             ofnode_to_offset(node), property,
862                                             sizep);
863         }
864 }
865
866 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
867                                         size_t sz)
868 {
869         if (ofnode_is_np(node)) {
870                 const struct device_node *np = ofnode_to_np(node);
871                 int psize;
872                 const __be32 *prop = of_get_property(np, propname, &psize);
873
874                 if (!prop || sz != psize)
875                         return NULL;
876                 return (uint8_t *)prop;
877
878         } else {
879                 return fdtdec_locate_byte_array(gd->fdt_blob,
880                                 ofnode_to_offset(node), propname, sz);
881         }
882 }
883
884 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
885                          const char *propname, struct fdt_pci_addr *addr)
886 {
887         const fdt32_t *cell;
888         int len;
889         int ret = -ENOENT;
890
891         debug("%s: %s: ", __func__, propname);
892
893         /*
894          * If we follow the pci bus bindings strictly, we should check
895          * the value of the node's parent node's #address-cells and
896          * #size-cells. They need to be 3 and 2 accordingly. However,
897          * for simplicity we skip the check here.
898          */
899         cell = ofnode_get_property(node, propname, &len);
900         if (!cell)
901                 goto fail;
902
903         if ((len % FDT_PCI_REG_SIZE) == 0) {
904                 int num = len / FDT_PCI_REG_SIZE;
905                 int i;
906
907                 for (i = 0; i < num; i++) {
908                         debug("pci address #%d: %08lx %08lx %08lx\n", i,
909                               (ulong)fdt32_to_cpu(cell[0]),
910                               (ulong)fdt32_to_cpu(cell[1]),
911                               (ulong)fdt32_to_cpu(cell[2]));
912                         if ((fdt32_to_cpu(*cell) & type) == type) {
913                                 addr->phys_hi = fdt32_to_cpu(cell[0]);
914                                 addr->phys_mid = fdt32_to_cpu(cell[1]);
915                                 addr->phys_lo = fdt32_to_cpu(cell[2]);
916                                 break;
917                         }
918
919                         cell += (FDT_PCI_ADDR_CELLS +
920                                  FDT_PCI_SIZE_CELLS);
921                 }
922
923                 if (i == num) {
924                         ret = -ENXIO;
925                         goto fail;
926                 }
927
928                 return 0;
929         }
930
931         ret = -EINVAL;
932
933 fail:
934         debug("(not found)\n");
935         return ret;
936 }
937
938 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
939 {
940         const char *list, *end;
941         int len;
942
943         list = ofnode_get_property(node, "compatible", &len);
944         if (!list)
945                 return -ENOENT;
946
947         end = list + len;
948         while (list < end) {
949                 len = strlen(list);
950                 if (len >= strlen("pciVVVV,DDDD")) {
951                         char *s = strstr(list, "pci");
952
953                         /*
954                          * check if the string is something like pciVVVV,DDDD.RR
955                          * or just pciVVVV,DDDD
956                          */
957                         if (s && s[7] == ',' &&
958                             (s[12] == '.' || s[12] == 0)) {
959                                 s += 3;
960                                 *vendor = simple_strtol(s, NULL, 16);
961
962                                 s += 5;
963                                 *device = simple_strtol(s, NULL, 16);
964
965                                 return 0;
966                         }
967                 }
968                 list += (len + 1);
969         }
970
971         return -ENOENT;
972 }
973
974 int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
975 {
976         const char *list, *end;
977         int len;
978
979         list = ofnode_get_property(node, "compatible", &len);
980
981         if (!list)
982                 return -ENOENT;
983
984         end = list + len;
985         while (list < end) {
986                 len = strlen(list);
987
988                 if (len >= strlen("ethernet-phy-idVVVV,DDDD")) {
989                         char *s = strstr(list, "ethernet-phy-id");
990
991                         /*
992                          * check if the string is something like
993                          * ethernet-phy-idVVVV,DDDD
994                          */
995                         if (s && s[19] == '.') {
996                                 s += strlen("ethernet-phy-id");
997                                 *vendor = simple_strtol(s, NULL, 16);
998                                 s += 5;
999                                 *device = simple_strtol(s, NULL, 16);
1000
1001                                 return 0;
1002                         }
1003                 }
1004                 list += (len + 1);
1005         }
1006
1007         return -ENOENT;
1008 }
1009
1010 int ofnode_read_addr_cells(ofnode node)
1011 {
1012         if (ofnode_is_np(node)) {
1013                 return of_n_addr_cells(ofnode_to_np(node));
1014         } else {
1015                 int parent = fdt_parent_offset(gd->fdt_blob,
1016                                                ofnode_to_offset(node));
1017
1018                 return fdt_address_cells(gd->fdt_blob, parent);
1019         }
1020 }
1021
1022 int ofnode_read_size_cells(ofnode node)
1023 {
1024         if (ofnode_is_np(node)) {
1025                 return of_n_size_cells(ofnode_to_np(node));
1026         } else {
1027                 int parent = fdt_parent_offset(gd->fdt_blob,
1028                                                ofnode_to_offset(node));
1029
1030                 return fdt_size_cells(gd->fdt_blob, parent);
1031         }
1032 }
1033
1034 int ofnode_read_simple_addr_cells(ofnode node)
1035 {
1036         if (ofnode_is_np(node))
1037                 return of_simple_addr_cells(ofnode_to_np(node));
1038         else
1039                 return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
1040 }
1041
1042 int ofnode_read_simple_size_cells(ofnode node)
1043 {
1044         if (ofnode_is_np(node))
1045                 return of_simple_size_cells(ofnode_to_np(node));
1046         else
1047                 return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
1048 }
1049
1050 bool ofnode_pre_reloc(ofnode node)
1051 {
1052 #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
1053         /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
1054          * had property dm-pre-reloc or u-boot,dm-spl/tpl.
1055          * They are removed in final dtb (fdtgrep 2nd pass)
1056          */
1057         return true;
1058 #else
1059         if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
1060                 return true;
1061         if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
1062                 return true;
1063
1064         /*
1065          * In regular builds individual spl and tpl handling both
1066          * count as handled pre-relocation for later second init.
1067          */
1068         if (ofnode_read_bool(node, "u-boot,dm-spl") ||
1069             ofnode_read_bool(node, "u-boot,dm-tpl"))
1070                 return true;
1071
1072         return false;
1073 #endif
1074 }
1075
1076 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
1077 {
1078         if (ofnode_is_np(node)) {
1079                 return of_address_to_resource(ofnode_to_np(node), index, res);
1080         } else {
1081                 struct fdt_resource fres;
1082                 int ret;
1083
1084                 ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
1085                                        "reg", index, &fres);
1086                 if (ret < 0)
1087                         return -EINVAL;
1088                 memset(res, '\0', sizeof(*res));
1089                 res->start = fres.start;
1090                 res->end = fres.end;
1091
1092                 return 0;
1093         }
1094 }
1095
1096 int ofnode_read_resource_byname(ofnode node, const char *name,
1097                                 struct resource *res)
1098 {
1099         int index;
1100
1101         index = ofnode_stringlist_search(node, "reg-names", name);
1102         if (index < 0)
1103                 return index;
1104
1105         return ofnode_read_resource(node, index, res);
1106 }
1107
1108 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
1109 {
1110         if (ofnode_is_np(node))
1111                 return of_translate_address(ofnode_to_np(node), in_addr);
1112         else
1113                 return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
1114 }
1115
1116 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
1117 {
1118         if (ofnode_is_np(node))
1119                 return of_translate_dma_address(ofnode_to_np(node), in_addr);
1120         else
1121                 return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
1122 }
1123
1124 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
1125 {
1126         if (ofnode_is_np(node))
1127                 return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
1128         else
1129                 return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node),
1130                                          cpu, bus, size);
1131 }
1132
1133 int ofnode_device_is_compatible(ofnode node, const char *compat)
1134 {
1135         if (ofnode_is_np(node))
1136                 return of_device_is_compatible(ofnode_to_np(node), compat,
1137                                                NULL, NULL);
1138         else
1139                 return !fdt_node_check_compatible(gd->fdt_blob,
1140                                                   ofnode_to_offset(node),
1141                                                   compat);
1142 }
1143
1144 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1145 {
1146         if (of_live_active()) {
1147                 return np_to_ofnode(of_find_compatible_node(
1148                         (struct device_node *)ofnode_to_np(from), NULL,
1149                         compat));
1150         } else {
1151                 return offset_to_ofnode(fdt_node_offset_by_compatible(
1152                                 gd->fdt_blob, ofnode_to_offset(from), compat));
1153         }
1154 }
1155
1156 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1157                             const void *propval, int proplen)
1158 {
1159         if (of_live_active()) {
1160                 return np_to_ofnode(of_find_node_by_prop_value(
1161                         (struct device_node *)ofnode_to_np(from), propname,
1162                         propval, proplen));
1163         } else {
1164                 return offset_to_ofnode(fdt_node_offset_by_prop_value(
1165                                 gd->fdt_blob, ofnode_to_offset(from),
1166                                 propname, propval, proplen));
1167         }
1168 }
1169
1170 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
1171                       int len)
1172 {
1173         if (of_live_active())
1174                 return of_write_prop(ofnode_to_npw(node), propname, len, value);
1175         else
1176                 return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node),
1177                                    propname, value, len);
1178
1179         return 0;
1180 }
1181
1182 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1183 {
1184         assert(ofnode_valid(node));
1185
1186         debug("%s: %s = %s", __func__, propname, value);
1187
1188         return ofnode_write_prop(node, propname, value, strlen(value) + 1);
1189 }
1190
1191 int ofnode_write_u32(ofnode node, const char *propname, u32 value)
1192 {
1193         fdt32_t *val;
1194
1195         assert(ofnode_valid(node));
1196
1197         log_debug("%s = %x", propname, value);
1198         val = malloc(sizeof(*val));
1199         if (!val)
1200                 return -ENOMEM;
1201         *val = cpu_to_fdt32(value);
1202
1203         return ofnode_write_prop(node, propname, val, sizeof(value));
1204 }
1205
1206 int ofnode_set_enabled(ofnode node, bool value)
1207 {
1208         assert(ofnode_valid(node));
1209
1210         if (value)
1211                 return ofnode_write_string(node, "status", "okay");
1212         else
1213                 return ofnode_write_string(node, "status", "disabled");
1214 }
1215
1216 bool ofnode_conf_read_bool(const char *prop_name)
1217 {
1218         ofnode node;
1219
1220         node = ofnode_path("/config");
1221         if (!ofnode_valid(node))
1222                 return false;
1223
1224         return ofnode_read_bool(node, prop_name);
1225 }
1226
1227 int ofnode_conf_read_int(const char *prop_name, int default_val)
1228 {
1229         ofnode node;
1230
1231         node = ofnode_path("/config");
1232         if (!ofnode_valid(node))
1233                 return default_val;
1234
1235         return ofnode_read_u32_default(node, prop_name, default_val);
1236 }
1237
1238 const char *ofnode_conf_read_str(const char *prop_name)
1239 {
1240         ofnode node;
1241
1242         node = ofnode_path("/config");
1243         if (!ofnode_valid(node))
1244                 return NULL;
1245
1246         return ofnode_read_string(node, prop_name);
1247 }
1248
1249 ofnode ofnode_get_phy_node(ofnode node)
1250 {
1251         /* DT node properties that reference a PHY node */
1252         static const char * const phy_handle_str[] = {
1253                 "phy-handle", "phy", "phy-device",
1254         };
1255         struct ofnode_phandle_args args = {
1256                 .node = ofnode_null()
1257         };
1258         int i;
1259
1260         assert(ofnode_valid(node));
1261
1262         for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++)
1263                 if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i],
1264                                                     NULL, 0, 0, &args))
1265                         break;
1266
1267         return args.node;
1268 }
1269
1270 phy_interface_t ofnode_read_phy_mode(ofnode node)
1271 {
1272         const char *mode;
1273         int i;
1274
1275         assert(ofnode_valid(node));
1276
1277         mode = ofnode_read_string(node, "phy-mode");
1278         if (!mode)
1279                 mode = ofnode_read_string(node, "phy-connection-type");
1280
1281         if (!mode)
1282                 return PHY_INTERFACE_MODE_NA;
1283
1284         for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
1285                 if (!strcmp(mode, phy_interface_strings[i]))
1286                         return i;
1287
1288         debug("%s: Invalid PHY interface '%s'\n", __func__, mode);
1289
1290         return PHY_INTERFACE_MODE_NA;
1291 }