1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2017 Google, Inc
4 * Written by Simon Glass <sjg@chromium.org>
7 #define LOG_CATEGORY LOGC_DT
12 #include <fdt_support.h>
15 #include <linux/libfdt.h>
16 #include <dm/of_access.h>
17 #include <dm/of_addr.h>
18 #include <dm/ofnode.h>
19 #include <linux/err.h>
20 #include <linux/ioport.h>
21 #include <asm/global_data.h>
23 DECLARE_GLOBAL_DATA_PTR;
25 #if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)
26 static void *oftree_list[CONFIG_OFNODE_MULTI_TREE_MAX];
27 static int oftree_count;
29 void oftree_reset(void)
31 if (gd->flags & GD_FLG_RELOC) {
33 oftree_list[oftree_count++] = (void *)gd->fdt_blob;
37 static int oftree_find(const void *fdt)
41 for (i = 0; i < oftree_count; i++) {
42 if (fdt == oftree_list[i])
49 static oftree oftree_ensure(void *fdt)
54 if (gd->flags & GD_FLG_RELOC) {
57 if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) {
58 log_warning("Too many registered device trees (max %d)\n",
59 CONFIG_OFNODE_MULTI_TREE_MAX);
63 /* register the new tree */
66 log_debug("oftree: registered tree %d: %p\n", i, fdt);
69 if (fdt != gd->fdt_blob) {
70 log_debug("Cannot only access control FDT before relocation\n");
80 void *ofnode_lookup_fdt(ofnode node)
82 if (gd->flags & GD_FLG_RELOC) {
83 uint i = OFTREE_TREE_ID(node.of_offset);
85 if (i > oftree_count) {
86 log_debug("Invalid tree ID %x\n", i);
90 return oftree_list[i];
92 return (void *)gd->fdt_blob;
96 void *ofnode_to_fdt(ofnode node)
102 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && ofnode_valid(node))
103 return ofnode_lookup_fdt(node);
105 /* Use the control FDT by default */
106 return (void *)gd->fdt_blob;
110 * ofnode_to_offset() - convert an ofnode to a flat DT offset
112 * This cannot be called if the reference contains a node pointer.
114 * @node: Reference containing offset (possibly invalid)
115 * Return: DT offset (can be -1)
117 int ofnode_to_offset(ofnode node)
120 if (of_live_active())
123 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && node.of_offset >= 0)
124 return OFTREE_OFFSET(node.of_offset);
126 return node.of_offset;
129 oftree oftree_from_fdt(void *fdt)
133 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE))
134 return oftree_ensure(fdt);
142 * noffset_to_ofnode() - convert a DT offset to an ofnode
144 * @other_node: Node in the same tree to use as a reference
145 * @of_offset: DT offset (either valid, or -1)
146 * Return: reference to the associated DT offset
148 ofnode noffset_to_ofnode(ofnode other_node, int of_offset)
152 if (of_live_active())
154 else if (!CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || of_offset < 0 ||
155 !ofnode_valid(other_node))
156 node.of_offset = of_offset;
158 node.of_offset = OFTREE_MAKE_NODE(other_node.of_offset,
164 #else /* !OFNODE_MULTI_TREE */
166 static inline int oftree_find(const void *fdt)
171 #endif /* OFNODE_MULTI_TREE */
174 * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree)
176 * Looks up the tree and returns an ofnode with the correct of_offset (i.e.
177 * containing the tree ID).
179 * If @offset is < 0 then this returns an ofnode with that offset and no tree
182 * @tree: tree to check
183 * @offset: offset within that tree (can be < 0)
184 * @return node for that offset, with the correct ID
186 static ofnode ofnode_from_tree_offset(oftree tree, int offset)
190 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && offset >= 0) {
191 int tree_id = oftree_find(tree.fdt);
194 return ofnode_null();
195 node.of_offset = OFTREE_NODE(tree_id, offset);
197 node.of_offset = offset;
203 bool ofnode_name_eq(ofnode node, const char *name)
205 const char *node_name;
208 assert(ofnode_valid(node));
210 node_name = ofnode_get_name(node);
211 len = strchrnul(node_name, '@') - node_name;
213 return (strlen(name) == len) && !strncmp(node_name, name, len);
216 int ofnode_read_u8(ofnode node, const char *propname, u8 *outp)
221 assert(ofnode_valid(node));
222 debug("%s: %s: ", __func__, propname);
224 if (ofnode_is_np(node))
225 return of_read_u8(ofnode_to_np(node), propname, outp);
227 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
229 if (!cell || len < sizeof(*cell)) {
230 debug("(not found)\n");
234 debug("%#x (%d)\n", *outp, *outp);
239 u8 ofnode_read_u8_default(ofnode node, const char *propname, u8 def)
241 assert(ofnode_valid(node));
242 ofnode_read_u8(node, propname, &def);
247 int ofnode_read_u16(ofnode node, const char *propname, u16 *outp)
252 assert(ofnode_valid(node));
253 debug("%s: %s: ", __func__, propname);
255 if (ofnode_is_np(node))
256 return of_read_u16(ofnode_to_np(node), propname, outp);
258 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
260 if (!cell || len < sizeof(*cell)) {
261 debug("(not found)\n");
264 *outp = be16_to_cpup(cell);
265 debug("%#x (%d)\n", *outp, *outp);
270 u16 ofnode_read_u16_default(ofnode node, const char *propname, u16 def)
272 assert(ofnode_valid(node));
273 ofnode_read_u16(node, propname, &def);
278 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
280 return ofnode_read_u32_index(node, propname, 0, outp);
283 u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
285 assert(ofnode_valid(node));
286 ofnode_read_u32_index(node, propname, 0, &def);
291 int ofnode_read_u32_index(ofnode node, const char *propname, int index,
297 assert(ofnode_valid(node));
298 debug("%s: %s: ", __func__, propname);
300 if (ofnode_is_np(node))
301 return of_read_u32_index(ofnode_to_np(node), propname, index,
304 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
307 debug("(not found)\n");
311 if (len < (sizeof(int) * (index + 1))) {
312 debug("(not large enough)\n");
316 *outp = fdt32_to_cpu(cell[index]);
317 debug("%#x (%d)\n", *outp, *outp);
322 u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
325 assert(ofnode_valid(node));
326 ofnode_read_u32_index(node, propname, index, &def);
331 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
333 assert(ofnode_valid(node));
334 ofnode_read_u32(node, propname, (u32 *)&def);
339 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
341 const unaligned_fdt64_t *cell;
344 assert(ofnode_valid(node));
345 debug("%s: %s: ", __func__, propname);
347 if (ofnode_is_np(node))
348 return of_read_u64(ofnode_to_np(node), propname, outp);
350 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
352 if (!cell || len < sizeof(*cell)) {
353 debug("(not found)\n");
356 *outp = fdt64_to_cpu(cell[0]);
357 debug("%#llx (%lld)\n", (unsigned long long)*outp,
358 (unsigned long long)*outp);
363 u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
365 assert(ofnode_valid(node));
366 ofnode_read_u64(node, propname, &def);
371 bool ofnode_read_bool(ofnode node, const char *propname)
375 assert(ofnode_valid(node));
376 debug("%s: %s: ", __func__, propname);
378 prop = ofnode_get_property(node, propname, NULL);
380 debug("%s\n", prop ? "true" : "false");
382 return prop ? true : false;
385 const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
387 const char *val = NULL;
390 assert(ofnode_valid(node));
391 debug("%s: %s: ", __func__, propname);
393 if (ofnode_is_np(node)) {
394 struct property *prop = of_find_property(
395 ofnode_to_np(node), propname, &len);
402 val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
406 debug("<not found>\n");
408 *sizep = -FDT_ERR_NOTFOUND;
417 const char *ofnode_read_string(ofnode node, const char *propname)
422 str = ofnode_read_prop(node, propname, &len);
426 if (strnlen(str, len) >= len) {
427 debug("<invalid>\n");
435 int ofnode_read_size(ofnode node, const char *propname)
439 if (!ofnode_read_prop(node, propname, &len))
445 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
449 assert(ofnode_valid(node));
450 debug("%s: %s: ", __func__, subnode_name);
452 if (ofnode_is_np(node)) {
453 struct device_node *np = ofnode_to_np(node);
455 for (np = np->child; np; np = np->sibling) {
456 if (!strcmp(subnode_name, np->name))
459 subnode = np_to_ofnode(np);
461 int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
462 ofnode_to_offset(node), subnode_name);
463 subnode = noffset_to_ofnode(node, ooffset);
465 debug("%s\n", ofnode_valid(subnode) ?
466 ofnode_get_name(subnode) : "<none>");
471 int ofnode_read_u32_array(ofnode node, const char *propname,
472 u32 *out_values, size_t sz)
474 assert(ofnode_valid(node));
475 debug("%s: %s: ", __func__, propname);
477 if (ofnode_is_np(node)) {
478 return of_read_u32_array(ofnode_to_np(node), propname,
483 ret = fdtdec_get_int_array(ofnode_to_fdt(node),
484 ofnode_to_offset(node), propname,
487 /* get the error right, but space is more important in SPL */
488 if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
489 if (ret == -FDT_ERR_NOTFOUND)
491 else if (ret == -FDT_ERR_BADLAYOUT)
498 #if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
499 bool ofnode_is_enabled(ofnode node)
501 if (ofnode_is_np(node)) {
502 return of_device_is_available(ofnode_to_np(node));
504 return fdtdec_get_is_enabled(ofnode_to_fdt(node),
505 ofnode_to_offset(node));
509 ofnode ofnode_first_subnode(ofnode node)
511 assert(ofnode_valid(node));
512 if (ofnode_is_np(node))
513 return np_to_ofnode(node.np->child);
515 return noffset_to_ofnode(node,
516 fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
519 ofnode ofnode_next_subnode(ofnode node)
521 assert(ofnode_valid(node));
522 if (ofnode_is_np(node))
523 return np_to_ofnode(node.np->sibling);
525 return noffset_to_ofnode(node,
526 fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
528 #endif /* !DM_INLINE_OFNODE */
530 ofnode ofnode_get_parent(ofnode node)
534 assert(ofnode_valid(node));
535 if (ofnode_is_np(node))
536 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
538 parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node),
539 ofnode_to_offset(node));
544 const char *ofnode_get_name(ofnode node)
546 if (!ofnode_valid(node)) {
547 debug("%s node not valid\n", __func__);
551 if (ofnode_is_np(node))
552 return node.np->name;
554 return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL);
557 int ofnode_get_path(ofnode node, char *buf, int buflen)
559 assert(ofnode_valid(node));
561 if (ofnode_is_np(node)) {
562 if (strlen(node.np->full_name) >= buflen)
565 strcpy(buf, node.np->full_name);
571 res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf,
575 else if (res == -FDT_ERR_NOSPACE)
582 ofnode ofnode_get_by_phandle(uint phandle)
586 if (of_live_active())
587 node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle));
589 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
595 ofnode oftree_get_by_phandle(oftree tree, uint phandle)
599 if (of_live_active())
600 node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle));
602 node = ofnode_from_tree_offset(tree,
603 fdt_node_offset_by_phandle(oftree_lookup_fdt(tree),
609 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
610 fdt_size_t *size, bool translate)
615 *size = FDT_SIZE_T_NONE;
617 if (ofnode_is_np(node)) {
618 const __be32 *prop_val;
622 prop_val = of_get_address(ofnode_to_np(node), index, &size64,
625 return FDT_ADDR_T_NONE;
630 ns = of_n_size_cells(ofnode_to_np(node));
632 if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
633 return of_translate_address(ofnode_to_np(node), prop_val);
635 na = of_n_addr_cells(ofnode_to_np(node));
636 return of_read_number(prop_val, na);
639 na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
640 ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
641 return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node),
642 ofnode_to_offset(node), "reg",
648 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
650 return __ofnode_get_addr_size_index(node, index, size, true);
653 fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
656 return __ofnode_get_addr_size_index(node, index, size, false);
659 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
663 return ofnode_get_addr_size_index(node, index, &size);
666 fdt_addr_t ofnode_get_addr(ofnode node)
668 return ofnode_get_addr_index(node, 0);
671 fdt_size_t ofnode_get_size(ofnode node)
675 ofnode_get_addr_size_index(node, 0, &size);
680 int ofnode_stringlist_search(ofnode node, const char *property,
683 if (ofnode_is_np(node)) {
684 return of_property_match_string(ofnode_to_np(node),
689 ret = fdt_stringlist_search(ofnode_to_fdt(node),
690 ofnode_to_offset(node), property,
692 if (ret == -FDT_ERR_NOTFOUND)
701 int ofnode_read_string_index(ofnode node, const char *property, int index,
704 if (ofnode_is_np(node)) {
705 return of_property_read_string_index(ofnode_to_np(node),
706 property, index, outp);
710 *outp = fdt_stringlist_get(ofnode_to_fdt(node),
711 ofnode_to_offset(node),
712 property, index, &len);
719 int ofnode_read_string_count(ofnode node, const char *property)
721 if (ofnode_is_np(node)) {
722 return of_property_count_strings(ofnode_to_np(node), property);
724 return fdt_stringlist_count(ofnode_to_fdt(node),
725 ofnode_to_offset(node), property);
729 int ofnode_read_string_list(ofnode node, const char *property,
737 count = ofnode_read_string_count(node, property);
743 prop = calloc(count + 1, sizeof(char *));
747 for (i = 0; i < count; i++)
748 ofnode_read_string_index(node, property, i, &prop[i]);
755 static void ofnode_from_fdtdec_phandle_args(struct fdtdec_phandle_args *in,
756 struct ofnode_phandle_args *out)
758 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
759 out->node = offset_to_ofnode(in->node);
760 out->args_count = in->args_count;
761 memcpy(out->args, in->args, sizeof(out->args));
764 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
765 struct ofnode_phandle_args *out)
767 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
768 out->node = np_to_ofnode(in->np);
769 out->args_count = in->args_count;
770 memcpy(out->args, in->args, sizeof(out->args));
773 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
774 const char *cells_name, int cell_count,
776 struct ofnode_phandle_args *out_args)
778 if (ofnode_is_np(node)) {
779 struct of_phandle_args args;
782 ret = of_parse_phandle_with_args(ofnode_to_np(node),
783 list_name, cells_name,
788 ofnode_from_of_phandle_args(&args, out_args);
790 struct fdtdec_phandle_args args;
793 ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
794 ofnode_to_offset(node),
795 list_name, cells_name,
796 cell_count, index, &args);
799 ofnode_from_fdtdec_phandle_args(&args, out_args);
805 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
806 const char *cells_name, int cell_count)
808 if (ofnode_is_np(node))
809 return of_count_phandle_with_args(ofnode_to_np(node),
810 list_name, cells_name, cell_count);
812 return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
813 ofnode_to_offset(node), list_name, cells_name,
814 cell_count, -1, NULL);
817 ofnode ofnode_path(const char *path)
819 if (of_live_active())
820 return np_to_ofnode(of_find_node_by_path(path));
822 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
825 ofnode oftree_root(oftree tree)
827 if (of_live_active()) {
828 return np_to_ofnode(tree.np);
830 return ofnode_from_tree_offset(tree, 0);
834 ofnode oftree_path(oftree tree, const char *path)
836 if (of_live_active()) {
837 return np_to_ofnode(of_find_node_opts_by_path(tree.np, path,
839 } else if (*path != '/' && tree.fdt != gd->fdt_blob) {
840 return ofnode_null(); /* Aliases only on control FDT */
842 int offset = fdt_path_offset(tree.fdt, path);
844 return ofnode_from_tree_offset(tree, offset);
848 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
852 chosen_node = ofnode_path("/chosen");
854 return ofnode_read_prop(chosen_node, propname, sizep);
857 const char *ofnode_read_chosen_string(const char *propname)
859 return ofnode_read_chosen_prop(propname, NULL);
862 ofnode ofnode_get_chosen_node(const char *name)
866 prop = ofnode_read_chosen_prop(name, NULL);
868 return ofnode_null();
870 return ofnode_path(prop);
873 const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
877 node = ofnode_path("/aliases");
879 return ofnode_read_prop(node, propname, sizep);
882 ofnode ofnode_get_aliases_node(const char *name)
886 prop = ofnode_read_aliases_prop(name, NULL);
888 return ofnode_null();
890 debug("%s: node_path: %s\n", __func__, prop);
892 return ofnode_path(prop);
895 int ofnode_get_child_count(ofnode parent)
900 ofnode_for_each_subnode(child, parent)
906 static int decode_timing_property(ofnode node, const char *name,
907 struct timing_entry *result)
911 length = ofnode_read_size(node, name);
913 debug("%s: could not find property %s\n",
914 ofnode_get_name(node), name);
918 if (length == sizeof(u32)) {
919 result->typ = ofnode_read_u32_default(node, name, 0);
920 result->min = result->typ;
921 result->max = result->typ;
923 ret = ofnode_read_u32_array(node, name, &result->min, 3);
929 int ofnode_decode_display_timing(ofnode parent, int index,
930 struct display_timing *dt)
933 ofnode timings, node;
937 timings = ofnode_find_subnode(parent, "display-timings");
938 if (!ofnode_valid(timings))
942 ofnode_for_each_subnode(node, timings) {
947 if (!ofnode_valid(node))
950 memset(dt, 0, sizeof(*dt));
952 ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
953 ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
954 ret |= decode_timing_property(node, "hactive", &dt->hactive);
955 ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
956 ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
957 ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
958 ret |= decode_timing_property(node, "vactive", &dt->vactive);
959 ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
960 ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
963 val = ofnode_read_u32_default(node, "vsync-active", -1);
965 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
966 DISPLAY_FLAGS_VSYNC_LOW;
968 val = ofnode_read_u32_default(node, "hsync-active", -1);
970 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
971 DISPLAY_FLAGS_HSYNC_LOW;
973 val = ofnode_read_u32_default(node, "de-active", -1);
975 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
976 DISPLAY_FLAGS_DE_LOW;
978 val = ofnode_read_u32_default(node, "pixelclk-active", -1);
980 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
981 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
984 if (ofnode_read_bool(node, "interlaced"))
985 dt->flags |= DISPLAY_FLAGS_INTERLACED;
986 if (ofnode_read_bool(node, "doublescan"))
987 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
988 if (ofnode_read_bool(node, "doubleclk"))
989 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
994 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
996 if (ofnode_is_np(node))
997 return of_get_property(ofnode_to_np(node), propname, lenp);
999 return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1003 int ofnode_first_property(ofnode node, struct ofprop *prop)
1007 if (ofnode_is_np(node)) {
1008 prop->prop = of_get_first_property(ofnode_to_np(prop->node));
1010 return -FDT_ERR_NOTFOUND;
1013 fdt_first_property_offset(ofnode_to_fdt(node),
1014 ofnode_to_offset(prop->node));
1015 if (prop->offset < 0)
1016 return prop->offset;
1022 int ofnode_next_property(struct ofprop *prop)
1024 if (ofnode_is_np(prop->node)) {
1025 prop->prop = of_get_next_property(ofnode_to_np(prop->node),
1028 return -FDT_ERR_NOTFOUND;
1031 fdt_next_property_offset(ofnode_to_fdt(prop->node),
1033 if (prop->offset < 0)
1034 return prop->offset;
1040 const void *ofprop_get_property(const struct ofprop *prop,
1041 const char **propname, int *lenp)
1043 if (ofnode_is_np(prop->node))
1044 return of_get_property_by_prop(ofnode_to_np(prop->node),
1045 prop->prop, propname, lenp);
1047 return fdt_getprop_by_offset(ofnode_to_fdt(prop->node),
1052 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
1055 if (ofnode_is_np(node)) {
1058 const struct device_node *np = ofnode_to_np(node);
1059 const __be32 *prop = of_get_property(np, property, &psize);
1062 return FDT_ADDR_T_NONE;
1063 na = of_n_addr_cells(np);
1064 ns = of_n_size_cells(np);
1065 *sizep = of_read_number(prop + na, ns);
1067 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
1068 return of_translate_address(np, prop);
1070 return of_read_number(prop, na);
1072 return fdtdec_get_addr_size(ofnode_to_fdt(node),
1073 ofnode_to_offset(node), property,
1078 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
1081 if (ofnode_is_np(node)) {
1082 const struct device_node *np = ofnode_to_np(node);
1084 const __be32 *prop = of_get_property(np, propname, &psize);
1086 if (!prop || sz != psize)
1088 return (uint8_t *)prop;
1091 return fdtdec_locate_byte_array(ofnode_to_fdt(node),
1092 ofnode_to_offset(node), propname, sz);
1096 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
1097 const char *propname, struct fdt_pci_addr *addr)
1099 const fdt32_t *cell;
1103 debug("%s: %s: ", __func__, propname);
1106 * If we follow the pci bus bindings strictly, we should check
1107 * the value of the node's parent node's #address-cells and
1108 * #size-cells. They need to be 3 and 2 accordingly. However,
1109 * for simplicity we skip the check here.
1111 cell = ofnode_get_property(node, propname, &len);
1115 if ((len % FDT_PCI_REG_SIZE) == 0) {
1116 int num = len / FDT_PCI_REG_SIZE;
1119 for (i = 0; i < num; i++) {
1120 debug("pci address #%d: %08lx %08lx %08lx\n", i,
1121 (ulong)fdt32_to_cpu(cell[0]),
1122 (ulong)fdt32_to_cpu(cell[1]),
1123 (ulong)fdt32_to_cpu(cell[2]));
1124 if ((fdt32_to_cpu(*cell) & type) == type) {
1125 addr->phys_hi = fdt32_to_cpu(cell[0]);
1126 addr->phys_mid = fdt32_to_cpu(cell[1]);
1127 addr->phys_lo = fdt32_to_cpu(cell[2]);
1131 cell += (FDT_PCI_ADDR_CELLS +
1132 FDT_PCI_SIZE_CELLS);
1146 debug("(not found)\n");
1150 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
1152 const char *list, *end;
1155 list = ofnode_get_property(node, "compatible", &len);
1160 while (list < end) {
1162 if (len >= strlen("pciVVVV,DDDD")) {
1163 char *s = strstr(list, "pci");
1166 * check if the string is something like pciVVVV,DDDD.RR
1167 * or just pciVVVV,DDDD
1169 if (s && s[7] == ',' &&
1170 (s[12] == '.' || s[12] == 0)) {
1172 *vendor = simple_strtol(s, NULL, 16);
1175 *device = simple_strtol(s, NULL, 16);
1186 int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
1188 const char *list, *end;
1191 list = ofnode_get_property(node, "compatible", &len);
1197 while (list < end) {
1200 if (len >= strlen("ethernet-phy-idVVVV,DDDD")) {
1201 char *s = strstr(list, "ethernet-phy-id");
1204 * check if the string is something like
1205 * ethernet-phy-idVVVV,DDDD
1207 if (s && s[19] == '.') {
1208 s += strlen("ethernet-phy-id");
1209 *vendor = simple_strtol(s, NULL, 16);
1211 *device = simple_strtol(s, NULL, 16);
1222 int ofnode_read_addr_cells(ofnode node)
1224 if (ofnode_is_np(node)) {
1225 return of_n_addr_cells(ofnode_to_np(node));
1227 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1228 ofnode_to_offset(node));
1230 return fdt_address_cells(ofnode_to_fdt(node), parent);
1234 int ofnode_read_size_cells(ofnode node)
1236 if (ofnode_is_np(node)) {
1237 return of_n_size_cells(ofnode_to_np(node));
1239 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1240 ofnode_to_offset(node));
1242 return fdt_size_cells(ofnode_to_fdt(node), parent);
1246 int ofnode_read_simple_addr_cells(ofnode node)
1248 if (ofnode_is_np(node))
1249 return of_simple_addr_cells(ofnode_to_np(node));
1251 return fdt_address_cells(ofnode_to_fdt(node),
1252 ofnode_to_offset(node));
1255 int ofnode_read_simple_size_cells(ofnode node)
1257 if (ofnode_is_np(node))
1258 return of_simple_size_cells(ofnode_to_np(node));
1260 return fdt_size_cells(ofnode_to_fdt(node),
1261 ofnode_to_offset(node));
1264 bool ofnode_pre_reloc(ofnode node)
1266 #if defined(CONFIG_SPL_BUILD) || defined(CONFIG_TPL_BUILD)
1267 /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
1268 * had property dm-pre-reloc or u-boot,dm-spl/tpl.
1269 * They are removed in final dtb (fdtgrep 2nd pass)
1273 if (ofnode_read_bool(node, "u-boot,dm-pre-reloc"))
1275 if (ofnode_read_bool(node, "u-boot,dm-pre-proper"))
1279 * In regular builds individual spl and tpl handling both
1280 * count as handled pre-relocation for later second init.
1282 if (ofnode_read_bool(node, "u-boot,dm-spl") ||
1283 ofnode_read_bool(node, "u-boot,dm-tpl"))
1290 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
1292 if (ofnode_is_np(node)) {
1293 return of_address_to_resource(ofnode_to_np(node), index, res);
1295 struct fdt_resource fres;
1298 ret = fdt_get_resource(ofnode_to_fdt(node),
1299 ofnode_to_offset(node),
1300 "reg", index, &fres);
1303 memset(res, '\0', sizeof(*res));
1304 res->start = fres.start;
1305 res->end = fres.end;
1311 int ofnode_read_resource_byname(ofnode node, const char *name,
1312 struct resource *res)
1316 index = ofnode_stringlist_search(node, "reg-names", name);
1320 return ofnode_read_resource(node, index, res);
1323 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
1325 if (ofnode_is_np(node))
1326 return of_translate_address(ofnode_to_np(node), in_addr);
1328 return fdt_translate_address(ofnode_to_fdt(node),
1329 ofnode_to_offset(node), in_addr);
1332 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
1334 if (ofnode_is_np(node))
1335 return of_translate_dma_address(ofnode_to_np(node), in_addr);
1337 return fdt_translate_dma_address(ofnode_to_fdt(node),
1338 ofnode_to_offset(node), in_addr);
1341 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
1343 if (ofnode_is_np(node))
1344 return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
1346 return fdt_get_dma_range(ofnode_to_fdt(node),
1347 ofnode_to_offset(node),
1351 int ofnode_device_is_compatible(ofnode node, const char *compat)
1353 if (ofnode_is_np(node))
1354 return of_device_is_compatible(ofnode_to_np(node), compat,
1357 return !fdt_node_check_compatible(ofnode_to_fdt(node),
1358 ofnode_to_offset(node),
1362 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1364 if (of_live_active()) {
1365 return np_to_ofnode(of_find_compatible_node(
1366 (struct device_node *)ofnode_to_np(from), NULL,
1369 return noffset_to_ofnode(from,
1370 fdt_node_offset_by_compatible(ofnode_to_fdt(from),
1371 ofnode_to_offset(from), compat));
1375 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1376 const void *propval, int proplen)
1378 if (of_live_active()) {
1379 return np_to_ofnode(of_find_node_by_prop_value(
1380 (struct device_node *)ofnode_to_np(from), propname,
1383 return noffset_to_ofnode(from,
1384 fdt_node_offset_by_prop_value(ofnode_to_fdt(from),
1385 ofnode_to_offset(from), propname, propval,
1390 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
1393 if (of_live_active()) {
1398 newval = malloc(len);
1400 return log_ret(-ENOMEM);
1401 memcpy(newval, value, len);
1404 ret = of_write_prop(ofnode_to_np(node), propname, len, value);
1409 return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1410 propname, value, len);
1414 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1416 assert(ofnode_valid(node));
1418 debug("%s: %s = %s", __func__, propname, value);
1420 return ofnode_write_prop(node, propname, value, strlen(value) + 1,
1424 int ofnode_write_u32(ofnode node, const char *propname, u32 value)
1428 assert(ofnode_valid(node));
1430 log_debug("%s = %x", propname, value);
1431 val = malloc(sizeof(*val));
1434 *val = cpu_to_fdt32(value);
1436 return ofnode_write_prop(node, propname, val, sizeof(value), false);
1439 int ofnode_set_enabled(ofnode node, bool value)
1441 assert(ofnode_valid(node));
1444 return ofnode_write_string(node, "status", "okay");
1446 return ofnode_write_string(node, "status", "disabled");
1449 bool ofnode_conf_read_bool(const char *prop_name)
1453 node = ofnode_path("/config");
1454 if (!ofnode_valid(node))
1457 return ofnode_read_bool(node, prop_name);
1460 int ofnode_conf_read_int(const char *prop_name, int default_val)
1464 node = ofnode_path("/config");
1465 if (!ofnode_valid(node))
1468 return ofnode_read_u32_default(node, prop_name, default_val);
1471 const char *ofnode_conf_read_str(const char *prop_name)
1475 node = ofnode_path("/config");
1476 if (!ofnode_valid(node))
1479 return ofnode_read_string(node, prop_name);
1482 ofnode ofnode_get_phy_node(ofnode node)
1484 /* DT node properties that reference a PHY node */
1485 static const char * const phy_handle_str[] = {
1486 "phy-handle", "phy", "phy-device",
1488 struct ofnode_phandle_args args = {
1489 .node = ofnode_null()
1493 assert(ofnode_valid(node));
1495 for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++)
1496 if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i],
1503 phy_interface_t ofnode_read_phy_mode(ofnode node)
1508 assert(ofnode_valid(node));
1510 mode = ofnode_read_string(node, "phy-mode");
1512 mode = ofnode_read_string(node, "phy-connection-type");
1515 return PHY_INTERFACE_MODE_NA;
1517 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
1518 if (!strcmp(mode, phy_interface_strings[i]))
1521 debug("%s: Invalid PHY interface '%s'\n", __func__, mode);
1523 return PHY_INTERFACE_MODE_NA;
1526 int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
1531 assert(ofnode_valid(node));
1533 if (ofnode_is_np(node)) {
1534 struct device_node *np, *child;
1536 np = (struct device_node *)ofnode_to_np(node);
1537 ret = of_add_subnode(np, name, -1, &child);
1538 if (ret && ret != -EEXIST)
1540 subnode = np_to_ofnode(child);
1542 void *fdt = ofnode_to_fdt(node);
1543 int poffset = ofnode_to_offset(node);
1546 offset = fdt_add_subnode(fdt, poffset, name);
1547 if (offset == -FDT_ERR_EXISTS) {
1548 offset = fdt_subnode_offset(fdt, poffset, name);
1553 subnode = noffset_to_ofnode(node, offset);
1556 *subnodep = subnode;
1558 return ret; /* 0 or -EEXIST */