1 // SPDX-License-Identifier: GPL-2.0+
3 * Copyright (c) 2017 Google, Inc
7 #define LOG_CATEGORY LOGC_DT
11 #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>
20 #include <linux/err.h>
21 #include <linux/ioport.h>
22 #include <asm/global_data.h>
24 DECLARE_GLOBAL_DATA_PTR;
26 #if CONFIG_IS_ENABLED(OFNODE_MULTI_TREE)
27 static void *oftree_list[CONFIG_OFNODE_MULTI_TREE_MAX];
28 static int oftree_count;
30 void oftree_reset(void)
32 if (gd->flags & GD_FLG_RELOC) {
34 oftree_list[oftree_count++] = (void *)gd->fdt_blob;
38 static int oftree_find(const void *fdt)
42 for (i = 0; i < oftree_count; i++) {
43 if (fdt == oftree_list[i])
50 static int check_tree_count(void)
52 if (oftree_count == CONFIG_OFNODE_MULTI_TREE_MAX) {
53 log_warning("Too many registered device trees (max %d)\n",
54 CONFIG_OFNODE_MULTI_TREE_MAX);
61 static oftree oftree_ensure(void *fdt)
66 if (of_live_active()) {
67 struct device_node *root;
70 ret = unflatten_device_tree(fdt, &root);
72 log_err("Failed to create live tree: err=%d\n", ret);
75 tree = oftree_from_np(root);
80 if (gd->flags & GD_FLG_RELOC) {
83 if (check_tree_count())
86 if (fdt_check_header(fdt)) {
87 log_err("Invalid device tree blob header\n");
91 /* register the new tree */
94 log_debug("oftree: registered tree %d: %p\n", i, fdt);
97 if (fdt != gd->fdt_blob) {
98 log_debug("Only the control FDT can be accessed before relocation\n");
108 int oftree_new(oftree *treep)
110 oftree tree = oftree_null();
113 if (of_live_active()) {
114 struct device_node *root;
116 ret = of_live_create_empty(&root);
118 return log_msg_ret("liv", ret);
119 tree = oftree_from_np(root);
121 const int size = 4096;
124 ret = check_tree_count();
126 return log_msg_ret("fla", ret);
128 /* register the new tree with a small size */
131 return log_msg_ret("fla", -ENOMEM);
132 ret = fdt_create_empty_tree(fdt, size);
134 return log_msg_ret("fla", -EINVAL);
135 oftree_list[oftree_count++] = fdt;
143 void oftree_dispose(oftree tree)
145 if (of_live_active())
146 of_live_free(tree.np);
149 void *ofnode_lookup_fdt(ofnode node)
151 if (gd->flags & GD_FLG_RELOC) {
152 uint i = OFTREE_TREE_ID(node.of_offset);
154 if (i >= oftree_count) {
155 log_debug("Invalid tree ID %x\n", i);
159 return oftree_list[i];
161 return (void *)gd->fdt_blob;
165 void *ofnode_to_fdt(ofnode node)
168 if (of_live_active())
171 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && ofnode_valid(node))
172 return ofnode_lookup_fdt(node);
174 /* Use the control FDT by default */
175 return (void *)gd->fdt_blob;
179 * ofnode_to_offset() - convert an ofnode to a flat DT offset
181 * This cannot be called if the reference contains a node pointer.
183 * @node: Reference containing offset (possibly invalid)
184 * Return: DT offset (can be -1)
186 int ofnode_to_offset(ofnode node)
189 if (of_live_active())
192 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && node.of_offset >= 0)
193 return OFTREE_OFFSET(node.of_offset);
195 return node.of_offset;
198 oftree oftree_from_fdt(void *fdt)
202 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE))
203 return oftree_ensure(fdt);
206 if (of_live_active())
207 return oftree_null();
215 * noffset_to_ofnode() - convert a DT offset to an ofnode
217 * @other_node: Node in the same tree to use as a reference
218 * @of_offset: DT offset (either valid, or -1)
219 * Return: reference to the associated DT offset
221 ofnode noffset_to_ofnode(ofnode other_node, int of_offset)
225 if (of_live_active())
227 else if (!CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) || of_offset < 0 ||
228 !ofnode_valid(other_node))
229 node.of_offset = of_offset;
231 node.of_offset = OFTREE_MAKE_NODE(other_node.of_offset,
237 #else /* !OFNODE_MULTI_TREE */
239 static inline int oftree_find(const void *fdt)
244 int oftree_new(oftree *treep)
249 #endif /* OFNODE_MULTI_TREE */
251 int oftree_to_fdt(oftree tree, struct abuf *buf)
255 if (of_live_active()) {
256 ret = of_live_flatten(ofnode_to_np(oftree_root(tree)), buf);
258 return log_msg_ret("flt", ret);
260 void *fdt = oftree_lookup_fdt(tree);
263 abuf_set(buf, fdt, fdt_totalsize(fdt));
270 * ofnode_from_tree_offset() - get an ofnode from a tree offset (flat tree)
272 * Looks up the tree and returns an ofnode with the correct of_offset (i.e.
273 * containing the tree ID).
275 * If @offset is < 0 then this returns an ofnode with that offset and no tree
278 * @tree: tree to check
279 * @offset: offset within that tree (can be < 0)
280 * @return node for that offset, with the correct ID
282 static ofnode ofnode_from_tree_offset(oftree tree, int offset)
286 if (CONFIG_IS_ENABLED(OFNODE_MULTI_TREE) && offset >= 0) {
287 int tree_id = oftree_find(tree.fdt);
290 return ofnode_null();
291 node.of_offset = OFTREE_NODE(tree_id, offset);
293 node.of_offset = offset;
299 bool ofnode_name_eq(ofnode node, const char *name)
301 const char *node_name;
304 assert(ofnode_valid(node));
306 node_name = ofnode_get_name(node);
307 len = strchrnul(node_name, '@') - node_name;
309 return (strlen(name) == len) && !strncmp(node_name, name, len);
312 bool ofnode_name_eq_unit(ofnode node, const char *name)
314 const char *node_name, *p;
317 assert(ofnode_valid(node));
319 node_name = ofnode_get_name(node);
321 /* check the whole name */
322 if (!strcmp(node_name, name))
325 /* if @name has no unit address, try the node name without it */
327 p = strchr(node_name, '@');
328 if (p && !strchr(name, '@') && len == p - node_name &&
329 !strncmp(node_name, name, len))
335 int ofnode_read_u8(ofnode node, const char *propname, u8 *outp)
340 assert(ofnode_valid(node));
341 log_debug("%s: %s: ", __func__, propname);
343 if (ofnode_is_np(node))
344 return of_read_u8(ofnode_to_np(node), propname, outp);
346 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
348 if (!cell || len < sizeof(*cell)) {
349 log_debug("(not found)\n");
353 log_debug("%#x (%u)\n", *outp, *outp);
358 u8 ofnode_read_u8_default(ofnode node, const char *propname, u8 def)
360 assert(ofnode_valid(node));
361 ofnode_read_u8(node, propname, &def);
366 int ofnode_read_u16(ofnode node, const char *propname, u16 *outp)
371 assert(ofnode_valid(node));
372 log_debug("%s: %s: ", __func__, propname);
374 if (ofnode_is_np(node))
375 return of_read_u16(ofnode_to_np(node), propname, outp);
377 cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
379 if (!cell || len < sizeof(*cell)) {
380 log_debug("(not found)\n");
383 *outp = be16_to_cpup(cell);
384 log_debug("%#x (%u)\n", *outp, *outp);
389 u16 ofnode_read_u16_default(ofnode node, const char *propname, u16 def)
391 assert(ofnode_valid(node));
392 ofnode_read_u16(node, propname, &def);
397 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
399 return ofnode_read_u32_index(node, propname, 0, outp);
402 u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
404 assert(ofnode_valid(node));
405 ofnode_read_u32_index(node, propname, 0, &def);
410 int ofnode_read_u32_index(ofnode node, const char *propname, int index,
416 assert(ofnode_valid(node));
417 log_debug("%s: %s: ", __func__, propname);
419 if (ofnode_is_np(node))
420 return of_read_u32_index(ofnode_to_np(node), propname, index,
423 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
426 log_debug("(not found)\n");
430 if (len < (sizeof(int) * (index + 1))) {
431 log_debug("(not large enough)\n");
435 *outp = fdt32_to_cpu(cell[index]);
436 log_debug("%#x (%u)\n", *outp, *outp);
441 int ofnode_read_u64_index(ofnode node, const char *propname, int index,
447 assert(ofnode_valid(node));
449 if (ofnode_is_np(node))
450 return of_read_u64_index(ofnode_to_np(node), propname, index,
453 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
456 log_debug("(not found)\n");
460 if (len < (sizeof(u64) * (index + 1))) {
461 log_debug("(not large enough)\n");
465 *outp = fdt64_to_cpu(cell[index]);
466 log_debug("%#llx (%llu)\n", *outp, *outp);
471 u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
474 assert(ofnode_valid(node));
475 ofnode_read_u32_index(node, propname, index, &def);
480 int ofnode_read_s32_default(ofnode node, const char *propname, s32 def)
482 assert(ofnode_valid(node));
483 ofnode_read_u32(node, propname, (u32 *)&def);
488 int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
490 const unaligned_fdt64_t *cell;
493 assert(ofnode_valid(node));
494 log_debug("%s: %s: ", __func__, propname);
496 if (ofnode_is_np(node))
497 return of_read_u64(ofnode_to_np(node), propname, outp);
499 cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
501 if (!cell || len < sizeof(*cell)) {
502 log_debug("(not found)\n");
505 *outp = fdt64_to_cpu(cell[0]);
506 log_debug("%#llx (%llu)\n", (unsigned long long)*outp,
507 (unsigned long long)*outp);
512 u64 ofnode_read_u64_default(ofnode node, const char *propname, u64 def)
514 assert(ofnode_valid(node));
515 ofnode_read_u64(node, propname, &def);
520 bool ofnode_read_bool(ofnode node, const char *propname)
524 assert(ofnode_valid(node));
525 log_debug("%s: %s: ", __func__, propname);
527 prop = ofnode_has_property(node, propname);
529 log_debug("%s\n", prop ? "true" : "false");
531 return prop ? true : false;
534 const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
536 const char *val = NULL;
539 assert(ofnode_valid(node));
540 log_debug("%s: %s: ", __func__, propname);
542 if (ofnode_is_np(node)) {
543 struct property *prop = of_find_property(
544 ofnode_to_np(node), propname, &len);
551 val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
555 log_debug("<not found>\n");
557 *sizep = -FDT_ERR_NOTFOUND;
566 const char *ofnode_read_string(ofnode node, const char *propname)
571 str = ofnode_read_prop(node, propname, &len);
575 if (strnlen(str, len) >= len) {
576 dm_warn("<invalid>\n");
579 log_debug("%s\n", str);
584 int ofnode_read_size(ofnode node, const char *propname)
588 if (!ofnode_read_prop(node, propname, &len))
594 ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
598 assert(ofnode_valid(node));
599 log_debug("%s: %s: ", __func__, subnode_name);
601 if (ofnode_is_np(node)) {
602 subnode = ofnode_find_subnode_unit(node, subnode_name);
604 /* special case to avoid code-size increase */
605 int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
606 ofnode_to_offset(node), subnode_name);
607 subnode = noffset_to_ofnode(node, ooffset);
609 log_debug("%s\n", ofnode_valid(subnode) ?
610 ofnode_get_name(subnode) : "<none>");
615 ofnode ofnode_find_subnode_unit(ofnode node, const char *subnode_name)
617 ofnode subnode, found = ofnode_null();
619 assert(ofnode_valid(node));
620 log_debug("%s: ", subnode_name);
622 ofnode_for_each_subnode(subnode, node) {
623 if (ofnode_name_eq_unit(subnode, subnode_name)) {
629 log_debug("%s\n", ofnode_valid(found) ?
630 ofnode_get_name(found) : "<none>");
635 int ofnode_read_u32_array(ofnode node, const char *propname,
636 u32 *out_values, size_t sz)
638 assert(ofnode_valid(node));
639 log_debug("%s: %s: ", __func__, propname);
641 if (ofnode_is_np(node)) {
642 return of_read_u32_array(ofnode_to_np(node), propname,
647 ret = fdtdec_get_int_array(ofnode_to_fdt(node),
648 ofnode_to_offset(node), propname,
651 /* get the error right, but space is more important in SPL */
652 if (!IS_ENABLED(CONFIG_XPL_BUILD)) {
653 if (ret == -FDT_ERR_NOTFOUND)
655 else if (ret == -FDT_ERR_BADLAYOUT)
662 #if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
663 bool ofnode_is_enabled(ofnode node)
665 if (ofnode_is_np(node)) {
666 return of_device_is_available(ofnode_to_np(node));
668 return fdtdec_get_is_enabled(ofnode_to_fdt(node),
669 ofnode_to_offset(node));
673 ofnode ofnode_first_subnode(ofnode node)
675 assert(ofnode_valid(node));
676 if (ofnode_is_np(node))
677 return np_to_ofnode(node.np->child);
679 return noffset_to_ofnode(node,
680 fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
683 ofnode ofnode_next_subnode(ofnode node)
685 assert(ofnode_valid(node));
686 if (ofnode_is_np(node))
687 return np_to_ofnode(node.np->sibling);
689 return noffset_to_ofnode(node,
690 fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
692 #endif /* !DM_INLINE_OFNODE */
694 ofnode ofnode_get_parent(ofnode node)
698 assert(ofnode_valid(node));
699 if (ofnode_is_np(node))
700 parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
702 parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node),
703 ofnode_to_offset(node));
708 const char *ofnode_get_name(ofnode node)
710 if (!ofnode_valid(node)) {
711 dm_warn("%s node not valid\n", __func__);
715 if (ofnode_is_np(node))
716 return node.np->name;
718 return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL);
721 int ofnode_get_path(ofnode node, char *buf, int buflen)
723 assert(ofnode_valid(node));
725 if (ofnode_is_np(node)) {
726 if (strlen(node.np->full_name) >= buflen)
729 strcpy(buf, node.np->full_name);
735 res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf,
739 else if (res == -FDT_ERR_NOSPACE)
746 ofnode ofnode_get_by_phandle(uint phandle)
750 if (of_live_active())
751 node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle));
753 node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
759 ofnode oftree_get_by_phandle(oftree tree, uint phandle)
763 if (of_live_active())
764 node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle));
766 node = ofnode_from_tree_offset(tree,
767 fdt_node_offset_by_phandle(oftree_lookup_fdt(tree),
773 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
774 fdt_size_t *size, bool translate)
779 *size = FDT_SIZE_T_NONE;
781 if (ofnode_is_np(node)) {
782 const __be32 *prop_val;
786 prop_val = of_get_address(ofnode_to_np(node), index, &size64,
789 return FDT_ADDR_T_NONE;
794 ns = of_n_size_cells(ofnode_to_np(node));
796 if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
797 return of_translate_address(ofnode_to_np(node), prop_val);
799 na = of_n_addr_cells(ofnode_to_np(node));
800 return of_read_number(prop_val, na);
803 ofnode parent = ofnode_get_parent(node);
804 na = ofnode_read_simple_addr_cells(parent);
805 ns = ofnode_read_simple_size_cells(parent);
806 return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node),
807 ofnode_to_offset(node), "reg",
813 fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
815 return __ofnode_get_addr_size_index(node, index, size, true);
818 fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
821 return __ofnode_get_addr_size_index(node, index, size, false);
824 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
828 return ofnode_get_addr_size_index(node, index, &size);
831 fdt_addr_t ofnode_get_addr(ofnode node)
833 return ofnode_get_addr_index(node, 0);
836 fdt_size_t ofnode_get_size(ofnode node)
840 ofnode_get_addr_size_index(node, 0, &size);
845 int ofnode_stringlist_search(ofnode node, const char *property,
848 if (ofnode_is_np(node)) {
849 return of_property_match_string(ofnode_to_np(node),
854 ret = fdt_stringlist_search(ofnode_to_fdt(node),
855 ofnode_to_offset(node), property,
857 if (ret == -FDT_ERR_NOTFOUND)
866 int ofnode_read_string_index(ofnode node, const char *property, int index,
869 if (ofnode_is_np(node)) {
870 return of_property_read_string_index(ofnode_to_np(node),
871 property, index, outp);
875 *outp = fdt_stringlist_get(ofnode_to_fdt(node),
876 ofnode_to_offset(node),
877 property, index, &len);
884 int ofnode_read_string_count(ofnode node, const char *property)
886 if (ofnode_is_np(node)) {
887 return of_property_count_strings(ofnode_to_np(node), property);
889 return fdt_stringlist_count(ofnode_to_fdt(node),
890 ofnode_to_offset(node), property);
894 int ofnode_read_string_list(ofnode node, const char *property,
902 count = ofnode_read_string_count(node, property);
908 prop = calloc(count + 1, sizeof(char *));
912 for (i = 0; i < count; i++)
913 ofnode_read_string_index(node, property, i, &prop[i]);
920 ofnode ofnode_parse_phandle(ofnode node, const char *phandle_name,
925 if (ofnode_is_np(node)) {
926 struct device_node *np;
928 np = of_parse_phandle(ofnode_to_np(node), phandle_name,
931 return ofnode_null();
933 phandle = np_to_ofnode(np);
935 struct fdtdec_phandle_args args;
937 if (fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
938 ofnode_to_offset(node),
941 return ofnode_null();
943 phandle = offset_to_ofnode(args.node);
949 ofnode oftree_parse_phandle(oftree tree, ofnode node, const char *phandle_name,
954 if (ofnode_is_np(node)) {
955 struct device_node *np;
957 np = of_root_parse_phandle(tree.np, ofnode_to_np(node),
958 phandle_name, index);
960 return ofnode_null();
962 phandle = np_to_ofnode(np);
964 struct fdtdec_phandle_args args;
966 if (fdtdec_parse_phandle_with_args(tree.fdt,
967 ofnode_to_offset(node),
970 return ofnode_null();
972 phandle = noffset_to_ofnode(node, args.node);
978 static void ofnode_from_fdtdec_phandle_args(ofnode node, struct fdtdec_phandle_args *in,
979 struct ofnode_phandle_args *out)
981 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
982 out->node = noffset_to_ofnode(node, in->node);
983 out->args_count = in->args_count;
984 memcpy(out->args, in->args, sizeof(out->args));
987 static void ofnode_from_of_phandle_args(struct of_phandle_args *in,
988 struct ofnode_phandle_args *out)
990 assert(OF_MAX_PHANDLE_ARGS == MAX_PHANDLE_ARGS);
991 out->node = np_to_ofnode(in->np);
992 out->args_count = in->args_count;
993 memcpy(out->args, in->args, sizeof(out->args));
996 int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
997 const char *cells_name, int cell_count,
999 struct ofnode_phandle_args *out_args)
1001 if (ofnode_is_np(node)) {
1002 struct of_phandle_args args;
1005 ret = of_parse_phandle_with_args(ofnode_to_np(node),
1006 list_name, cells_name,
1011 ofnode_from_of_phandle_args(&args, out_args);
1013 struct fdtdec_phandle_args args;
1016 ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
1017 ofnode_to_offset(node),
1018 list_name, cells_name,
1019 cell_count, index, &args);
1022 ofnode_from_fdtdec_phandle_args(node, &args, out_args);
1028 int oftree_parse_phandle_with_args(oftree tree, ofnode node, const char *list_name,
1029 const char *cells_name, int cell_count,
1031 struct ofnode_phandle_args *out_args)
1033 if (ofnode_is_np(node)) {
1034 struct of_phandle_args args;
1037 ret = of_root_parse_phandle_with_args(tree.np,
1039 list_name, cells_name,
1044 ofnode_from_of_phandle_args(&args, out_args);
1046 struct fdtdec_phandle_args args;
1049 ret = fdtdec_parse_phandle_with_args(tree.fdt,
1050 ofnode_to_offset(node),
1051 list_name, cells_name,
1052 cell_count, index, &args);
1055 ofnode_from_fdtdec_phandle_args(node, &args, out_args);
1061 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
1062 const char *cells_name, int cell_count)
1064 if (ofnode_is_np(node))
1065 return of_count_phandle_with_args(ofnode_to_np(node),
1066 list_name, cells_name, cell_count);
1068 return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
1069 ofnode_to_offset(node), list_name, cells_name,
1070 cell_count, -1, NULL);
1073 int oftree_count_phandle_with_args(oftree tree, ofnode node, const char *list_name,
1074 const char *cells_name, int cell_count)
1076 if (ofnode_is_np(node))
1077 return of_root_count_phandle_with_args(tree.np, ofnode_to_np(node),
1078 list_name, cells_name, cell_count);
1080 return fdtdec_parse_phandle_with_args(tree.fdt,
1081 ofnode_to_offset(node), list_name, cells_name,
1082 cell_count, -1, NULL);
1085 ofnode ofnode_path(const char *path)
1087 if (of_live_active())
1088 return np_to_ofnode(of_find_node_by_path(path));
1090 return offset_to_ofnode(fdt_path_offset(gd->fdt_blob, path));
1093 ofnode oftree_root(oftree tree)
1095 if (of_live_active()) {
1096 return np_to_ofnode(tree.np);
1098 return ofnode_from_tree_offset(tree, 0);
1102 ofnode oftree_path(oftree tree, const char *path)
1104 if (of_live_active()) {
1105 return np_to_ofnode(of_find_node_opts_by_path(tree.np, path,
1107 } else if (*path != '/' && tree.fdt != gd->fdt_blob) {
1108 return ofnode_null(); /* Aliases only on control FDT */
1110 int offset = fdt_path_offset(tree.fdt, path);
1112 return ofnode_from_tree_offset(tree, offset);
1116 const void *ofnode_read_chosen_prop(const char *propname, int *sizep)
1120 chosen_node = ofnode_path("/chosen");
1122 return ofnode_read_prop(chosen_node, propname, sizep);
1125 const char *ofnode_read_chosen_string(const char *propname)
1127 return ofnode_read_chosen_prop(propname, NULL);
1130 ofnode ofnode_get_chosen_node(const char *name)
1134 prop = ofnode_read_chosen_prop(name, NULL);
1136 return ofnode_null();
1138 return ofnode_path(prop);
1141 int ofnode_read_baud(void)
1143 const char *str, *p;
1146 str = ofnode_read_chosen_string("stdout-path");
1150 /* Parse string serial0:115200n8 */
1151 p = strchr(str, ':');
1155 baud = dectoul(p + 1, NULL);
1159 const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
1163 node = ofnode_path("/aliases");
1165 return ofnode_read_prop(node, propname, sizep);
1168 ofnode ofnode_get_aliases_node(const char *name)
1172 prop = ofnode_read_aliases_prop(name, NULL);
1174 return ofnode_null();
1176 log_debug("%s: node_path: %s\n", __func__, prop);
1178 return ofnode_path(prop);
1181 int ofnode_get_child_count(ofnode parent)
1186 ofnode_for_each_subnode(child, parent)
1192 static int decode_timing_property(ofnode node, const char *name,
1193 struct timing_entry *result)
1195 int length, ret = 0;
1197 length = ofnode_read_size(node, name);
1199 dm_warn("%s: could not find property %s\n",
1200 ofnode_get_name(node), name);
1204 if (length == sizeof(u32)) {
1205 result->typ = ofnode_read_u32_default(node, name, 0);
1206 result->min = result->typ;
1207 result->max = result->typ;
1209 ret = ofnode_read_u32_array(node, name, &result->min, 3);
1215 int ofnode_decode_display_timing(ofnode parent, int index,
1216 struct display_timing *dt)
1219 ofnode timings, node;
1223 timings = ofnode_find_subnode(parent, "display-timings");
1224 if (!ofnode_valid(timings))
1228 ofnode_for_each_subnode(node, timings) {
1233 if (!ofnode_valid(node))
1236 memset(dt, 0, sizeof(*dt));
1238 ret |= decode_timing_property(node, "hback-porch", &dt->hback_porch);
1239 ret |= decode_timing_property(node, "hfront-porch", &dt->hfront_porch);
1240 ret |= decode_timing_property(node, "hactive", &dt->hactive);
1241 ret |= decode_timing_property(node, "hsync-len", &dt->hsync_len);
1242 ret |= decode_timing_property(node, "vback-porch", &dt->vback_porch);
1243 ret |= decode_timing_property(node, "vfront-porch", &dt->vfront_porch);
1244 ret |= decode_timing_property(node, "vactive", &dt->vactive);
1245 ret |= decode_timing_property(node, "vsync-len", &dt->vsync_len);
1246 ret |= decode_timing_property(node, "clock-frequency", &dt->pixelclock);
1249 val = ofnode_read_u32_default(node, "vsync-active", -1);
1251 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
1252 DISPLAY_FLAGS_VSYNC_LOW;
1254 val = ofnode_read_u32_default(node, "hsync-active", -1);
1256 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
1257 DISPLAY_FLAGS_HSYNC_LOW;
1259 val = ofnode_read_u32_default(node, "de-active", -1);
1261 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
1262 DISPLAY_FLAGS_DE_LOW;
1264 val = ofnode_read_u32_default(node, "pixelclk-active", -1);
1266 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
1267 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
1270 if (ofnode_read_bool(node, "interlaced"))
1271 dt->flags |= DISPLAY_FLAGS_INTERLACED;
1272 if (ofnode_read_bool(node, "doublescan"))
1273 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
1274 if (ofnode_read_bool(node, "doubleclk"))
1275 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
1280 int ofnode_decode_panel_timing(ofnode parent,
1281 struct display_timing *dt)
1287 timings = ofnode_find_subnode(parent, "panel-timing");
1288 if (!ofnode_valid(timings))
1290 memset(dt, 0, sizeof(*dt));
1291 ret |= decode_timing_property(timings, "hback-porch", &dt->hback_porch);
1292 ret |= decode_timing_property(timings, "hfront-porch", &dt->hfront_porch);
1293 ret |= decode_timing_property(timings, "hactive", &dt->hactive);
1294 ret |= decode_timing_property(timings, "hsync-len", &dt->hsync_len);
1295 ret |= decode_timing_property(timings, "vback-porch", &dt->vback_porch);
1296 ret |= decode_timing_property(timings, "vfront-porch", &dt->vfront_porch);
1297 ret |= decode_timing_property(timings, "vactive", &dt->vactive);
1298 ret |= decode_timing_property(timings, "vsync-len", &dt->vsync_len);
1299 ret |= decode_timing_property(timings, "clock-frequency", &dt->pixelclock);
1301 if (!ofnode_read_u32(timings, "vsync-active", &val)) {
1302 dt->flags |= val ? DISPLAY_FLAGS_VSYNC_HIGH :
1303 DISPLAY_FLAGS_VSYNC_LOW;
1305 if (!ofnode_read_u32(timings, "hsync-active", &val)) {
1306 dt->flags |= val ? DISPLAY_FLAGS_HSYNC_HIGH :
1307 DISPLAY_FLAGS_HSYNC_LOW;
1309 if (!ofnode_read_u32(timings, "de-active", &val)) {
1310 dt->flags |= val ? DISPLAY_FLAGS_DE_HIGH :
1311 DISPLAY_FLAGS_DE_LOW;
1313 if (!ofnode_read_u32(timings, "pixelclk-active", &val)) {
1314 dt->flags |= val ? DISPLAY_FLAGS_PIXDATA_POSEDGE :
1315 DISPLAY_FLAGS_PIXDATA_NEGEDGE;
1317 if (ofnode_read_bool(timings, "interlaced"))
1318 dt->flags |= DISPLAY_FLAGS_INTERLACED;
1319 if (ofnode_read_bool(timings, "doublescan"))
1320 dt->flags |= DISPLAY_FLAGS_DOUBLESCAN;
1321 if (ofnode_read_bool(timings, "doubleclk"))
1322 dt->flags |= DISPLAY_FLAGS_DOUBLECLK;
1327 const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
1329 if (ofnode_is_np(node))
1330 return of_get_property(ofnode_to_np(node), propname, lenp);
1332 return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1336 bool ofnode_has_property(ofnode node, const char *propname)
1338 if (ofnode_is_np(node))
1339 return of_find_property(ofnode_to_np(node), propname, NULL);
1341 return ofnode_get_property(node, propname, NULL);
1344 int ofnode_first_property(ofnode node, struct ofprop *prop)
1348 if (ofnode_is_np(node)) {
1349 prop->prop = of_get_first_property(ofnode_to_np(prop->node));
1351 return -FDT_ERR_NOTFOUND;
1354 fdt_first_property_offset(ofnode_to_fdt(node),
1355 ofnode_to_offset(prop->node));
1356 if (prop->offset < 0)
1357 return prop->offset;
1363 int ofnode_next_property(struct ofprop *prop)
1365 if (ofnode_is_np(prop->node)) {
1366 prop->prop = of_get_next_property(ofnode_to_np(prop->node),
1369 return -FDT_ERR_NOTFOUND;
1372 fdt_next_property_offset(ofnode_to_fdt(prop->node),
1374 if (prop->offset < 0)
1375 return prop->offset;
1381 const void *ofprop_get_property(const struct ofprop *prop,
1382 const char **propname, int *lenp)
1384 if (ofnode_is_np(prop->node))
1385 return of_get_property_by_prop(ofnode_to_np(prop->node),
1386 prop->prop, propname, lenp);
1388 return fdt_getprop_by_offset(ofnode_to_fdt(prop->node),
1393 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
1396 if (ofnode_is_np(node)) {
1399 const struct device_node *np = ofnode_to_np(node);
1400 const __be32 *prop = of_get_property(np, property, &psize);
1403 return FDT_ADDR_T_NONE;
1404 na = of_n_addr_cells(np);
1405 ns = of_n_size_cells(np);
1406 *sizep = of_read_number(prop + na, ns);
1408 if (CONFIG_IS_ENABLED(OF_TRANSLATE) && ns > 0)
1409 return of_translate_address(np, prop);
1411 return of_read_number(prop, na);
1413 return fdtdec_get_addr_size(ofnode_to_fdt(node),
1414 ofnode_to_offset(node), property,
1419 const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
1422 if (ofnode_is_np(node)) {
1423 const struct device_node *np = ofnode_to_np(node);
1425 const __be32 *prop = of_get_property(np, propname, &psize);
1427 if (!prop || sz != psize)
1429 return (uint8_t *)prop;
1432 return fdtdec_locate_byte_array(ofnode_to_fdt(node),
1433 ofnode_to_offset(node), propname, sz);
1437 int ofnode_read_pci_addr(ofnode node, enum fdt_pci_space type,
1438 const char *propname, struct fdt_pci_addr *addr,
1441 const fdt32_t *cell;
1445 log_debug("%s: %s: ", __func__, propname);
1448 * If we follow the pci bus bindings strictly, we should check
1449 * the value of the node's parent node's #address-cells and
1450 * #size-cells. They need to be 3 and 2 accordingly. However,
1451 * for simplicity we skip the check here.
1453 cell = ofnode_get_property(node, propname, &len);
1457 if ((len % FDT_PCI_REG_SIZE) == 0) {
1458 int num = len / FDT_PCI_REG_SIZE;
1461 for (i = 0; i < num; i++) {
1462 log_debug("pci address #%d: %08lx %08lx %08lx\n", i,
1463 (ulong)fdt32_to_cpu(cell[0]),
1464 (ulong)fdt32_to_cpu(cell[1]),
1465 (ulong)fdt32_to_cpu(cell[2]));
1466 if ((fdt32_to_cpu(*cell) & type) == type) {
1467 const unaligned_fdt64_t *ptr;
1469 addr->phys_hi = fdt32_to_cpu(cell[0]);
1470 addr->phys_mid = fdt32_to_cpu(cell[1]);
1471 addr->phys_lo = fdt32_to_cpu(cell[2]);
1472 ptr = (const unaligned_fdt64_t *)(cell + 3);
1474 *size = fdt64_to_cpu(*ptr);
1478 cell += FDT_PCI_ADDR_CELLS + FDT_PCI_SIZE_CELLS;
1492 log_debug("(not found)\n");
1496 int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
1498 const char *list, *end;
1501 list = ofnode_get_property(node, "compatible", &len);
1506 while (list < end) {
1508 if (len >= strlen("pciVVVV,DDDD")) {
1509 char *s = strstr(list, "pci");
1512 * check if the string is something like pciVVVV,DDDD.RR
1513 * or just pciVVVV,DDDD
1515 if (s && s[7] == ',' &&
1516 (s[12] == '.' || s[12] == 0)) {
1518 *vendor = simple_strtol(s, NULL, 16);
1521 *device = simple_strtol(s, NULL, 16);
1532 int ofnode_read_eth_phy_id(ofnode node, u16 *vendor, u16 *device)
1534 const char *list, *end;
1537 list = ofnode_get_property(node, "compatible", &len);
1543 while (list < end) {
1546 if (len >= strlen("ethernet-phy-idVVVV.DDDD")) {
1547 char *s = strstr(list, "ethernet-phy-id");
1550 * check if the string is something like
1551 * ethernet-phy-idVVVV.DDDD
1553 if (s && s[19] == '.') {
1554 s += strlen("ethernet-phy-id");
1555 *vendor = simple_strtol(s, NULL, 16);
1557 *device = simple_strtol(s, NULL, 16);
1568 int ofnode_read_addr_cells(ofnode node)
1570 if (ofnode_is_np(node)) {
1571 return of_n_addr_cells(ofnode_to_np(node));
1573 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1574 ofnode_to_offset(node));
1576 return fdt_address_cells(ofnode_to_fdt(node), parent);
1580 int ofnode_read_size_cells(ofnode node)
1582 if (ofnode_is_np(node)) {
1583 return of_n_size_cells(ofnode_to_np(node));
1585 int parent = fdt_parent_offset(ofnode_to_fdt(node),
1586 ofnode_to_offset(node));
1588 return fdt_size_cells(ofnode_to_fdt(node), parent);
1592 int ofnode_read_simple_addr_cells(ofnode node)
1594 if (ofnode_is_np(node))
1595 return of_simple_addr_cells(ofnode_to_np(node));
1597 return fdt_address_cells(ofnode_to_fdt(node),
1598 ofnode_to_offset(node));
1601 int ofnode_read_simple_size_cells(ofnode node)
1603 if (ofnode_is_np(node))
1604 return of_simple_size_cells(ofnode_to_np(node));
1606 return fdt_size_cells(ofnode_to_fdt(node),
1607 ofnode_to_offset(node));
1610 bool ofnode_pre_reloc(ofnode node)
1612 #if defined(CONFIG_XPL_BUILD) || defined(CONFIG_TPL_BUILD)
1613 /* for SPL and TPL the remaining nodes after the fdtgrep 1st pass
1614 * had property bootph-all or bootph-pre-sram/bootph-pre-ram.
1615 * They are removed in final dtb (fdtgrep 2nd pass)
1619 if (ofnode_read_bool(node, "bootph-all"))
1621 if (ofnode_read_bool(node, "bootph-some-ram"))
1625 * In regular builds individual spl and tpl handling both
1626 * count as handled pre-relocation for later second init.
1628 if (ofnode_read_bool(node, "bootph-pre-ram") ||
1629 ofnode_read_bool(node, "bootph-pre-sram"))
1630 return gd->flags & GD_FLG_RELOC;
1632 if (IS_ENABLED(CONFIG_OF_TAG_MIGRATE)) {
1633 /* detect and handle old tags */
1634 if (ofnode_read_bool(node, "u-boot,dm-pre-reloc") ||
1635 ofnode_read_bool(node, "u-boot,dm-pre-proper") ||
1636 ofnode_read_bool(node, "u-boot,dm-spl") ||
1637 ofnode_read_bool(node, "u-boot,dm-tpl") ||
1638 ofnode_read_bool(node, "u-boot,dm-vpl")) {
1639 gd->flags |= GD_FLG_OF_TAG_MIGRATE;
1648 int ofnode_read_resource(ofnode node, uint index, struct resource *res)
1650 if (ofnode_is_np(node)) {
1651 return of_address_to_resource(ofnode_to_np(node), index, res);
1653 struct fdt_resource fres;
1656 ret = fdt_get_resource(ofnode_to_fdt(node),
1657 ofnode_to_offset(node),
1658 "reg", index, &fres);
1661 memset(res, '\0', sizeof(*res));
1662 res->start = fres.start;
1663 res->end = fres.end;
1669 int ofnode_read_resource_byname(ofnode node, const char *name,
1670 struct resource *res)
1674 index = ofnode_stringlist_search(node, "reg-names", name);
1678 return ofnode_read_resource(node, index, res);
1681 u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
1683 if (ofnode_is_np(node))
1684 return of_translate_address(ofnode_to_np(node), in_addr);
1686 return fdt_translate_address(ofnode_to_fdt(node),
1687 ofnode_to_offset(node), in_addr);
1690 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
1692 if (ofnode_is_np(node))
1693 return of_translate_dma_address(ofnode_to_np(node), in_addr);
1695 return fdt_translate_dma_address(ofnode_to_fdt(node),
1696 ofnode_to_offset(node), in_addr);
1699 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
1701 if (ofnode_is_np(node))
1702 return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
1704 return fdt_get_dma_range(ofnode_to_fdt(node),
1705 ofnode_to_offset(node),
1709 int ofnode_device_is_compatible(ofnode node, const char *compat)
1711 if (ofnode_is_np(node))
1712 return of_device_is_compatible(ofnode_to_np(node), compat,
1715 return !fdt_node_check_compatible(ofnode_to_fdt(node),
1716 ofnode_to_offset(node),
1720 ofnode ofnode_by_compatible(ofnode from, const char *compat)
1722 if (of_live_active()) {
1723 return np_to_ofnode(of_find_compatible_node(
1724 (struct device_node *)ofnode_to_np(from), NULL,
1727 return noffset_to_ofnode(from,
1728 fdt_node_offset_by_compatible(ofnode_to_fdt(from),
1729 ofnode_to_offset(from), compat));
1733 ofnode ofnode_by_prop_value(ofnode from, const char *propname,
1734 const void *propval, int proplen)
1736 if (of_live_active()) {
1737 return np_to_ofnode(of_find_node_by_prop_value(
1738 (struct device_node *)ofnode_to_np(from), propname,
1741 return noffset_to_ofnode(from,
1742 fdt_node_offset_by_prop_value(ofnode_to_fdt(from),
1743 ofnode_to_offset(from), propname, propval,
1748 int ofnode_write_prop(ofnode node, const char *propname, const void *value,
1753 if (of_live_active()) {
1757 newval = malloc(len);
1759 return log_ret(-ENOMEM);
1760 memcpy(newval, value, len);
1763 ret = of_write_prop(ofnode_to_np(node), propname, len, value);
1768 ret = fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1769 propname, value, len);
1771 return ret == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL;
1777 int ofnode_write_string(ofnode node, const char *propname, const char *value)
1779 assert(ofnode_valid(node));
1781 log_debug("%s: %s = %s", __func__, propname, value);
1783 return ofnode_write_prop(node, propname, value, strlen(value) + 1,
1787 int ofnode_write_u32(ofnode node, const char *propname, u32 value)
1791 assert(ofnode_valid(node));
1793 log_debug("%s = %x", propname, value);
1794 val = malloc(sizeof(*val));
1797 *val = cpu_to_fdt32(value);
1799 return ofnode_write_prop(node, propname, val, sizeof(value), true);
1802 int ofnode_write_u64(ofnode node, const char *propname, u64 value)
1806 assert(ofnode_valid(node));
1808 log_debug("%s = %llx", propname, (unsigned long long)value);
1809 val = malloc(sizeof(*val));
1812 *val = cpu_to_fdt64(value);
1814 return ofnode_write_prop(node, propname, val, sizeof(value), true);
1817 int ofnode_write_bool(ofnode node, const char *propname, bool value)
1820 return ofnode_write_prop(node, propname, NULL, 0, false);
1822 return ofnode_delete_prop(node, propname);
1825 int ofnode_delete_prop(ofnode node, const char *propname)
1827 if (ofnode_is_np(node)) {
1828 struct property *prop;
1831 prop = of_find_property(ofnode_to_np(node), propname, &len);
1833 return of_remove_property(ofnode_to_np(node), prop);
1836 return fdt_delprop(ofnode_to_fdt(node), ofnode_to_offset(node),
1841 int ofnode_set_enabled(ofnode node, bool value)
1843 assert(ofnode_valid(node));
1846 return ofnode_write_string(node, "status", "okay");
1848 return ofnode_write_string(node, "status", "disabled");
1851 bool ofnode_conf_read_bool(const char *prop_name)
1855 node = ofnode_path("/config");
1856 if (!ofnode_valid(node))
1859 return ofnode_read_bool(node, prop_name);
1862 int ofnode_conf_read_int(const char *prop_name, int default_val)
1866 node = ofnode_path("/config");
1867 if (!ofnode_valid(node))
1870 return ofnode_read_u32_default(node, prop_name, default_val);
1873 const char *ofnode_conf_read_str(const char *prop_name)
1877 node = ofnode_path("/config");
1878 if (!ofnode_valid(node))
1881 return ofnode_read_string(node, prop_name);
1884 bool ofnode_options_read_bool(const char *prop_name)
1888 uboot = ofnode_path("/options/u-boot");
1889 if (!ofnode_valid(uboot))
1892 return ofnode_read_bool(uboot, prop_name);
1895 int ofnode_options_read_int(const char *prop_name, int default_val)
1899 uboot = ofnode_path("/options/u-boot");
1900 if (!ofnode_valid(uboot))
1903 return ofnode_read_u32_default(uboot, prop_name, default_val);
1906 const char *ofnode_options_read_str(const char *prop_name)
1910 uboot = ofnode_path("/options/u-boot");
1911 if (!ofnode_valid(uboot))
1914 return ofnode_read_string(uboot, prop_name);
1917 int ofnode_options_get_by_phandle(const char *prop_name, ofnode *nodep)
1921 uboot = ofnode_path("/options/u-boot");
1922 if (!ofnode_valid(uboot))
1925 *nodep = ofnode_parse_phandle(uboot, prop_name, 0);
1926 if (!ofnode_valid(*nodep))
1932 int ofnode_read_bootscript_address(u64 *bootscr_address, u64 *bootscr_offset)
1937 *bootscr_address = 0;
1938 *bootscr_offset = 0;
1940 uboot = ofnode_path("/options/u-boot");
1941 if (!ofnode_valid(uboot)) {
1942 dm_warn("%s: Missing /u-boot node\n", __func__);
1946 ret = ofnode_read_u64(uboot, "bootscr-address", bootscr_address);
1948 ret = ofnode_read_u64(uboot, "bootscr-ram-offset",
1957 int ofnode_read_bootscript_flash(u64 *bootscr_flash_offset,
1958 u64 *bootscr_flash_size)
1963 *bootscr_flash_offset = 0;
1964 *bootscr_flash_size = 0;
1966 uboot = ofnode_path("/options/u-boot");
1967 if (!ofnode_valid(uboot)) {
1968 dm_warn("%s: Missing /u-boot node\n", __func__);
1972 ret = ofnode_read_u64(uboot, "bootscr-flash-offset",
1973 bootscr_flash_offset);
1977 ret = ofnode_read_u64(uboot, "bootscr-flash-size",
1978 bootscr_flash_size);
1982 if (!bootscr_flash_size) {
1983 dm_warn("bootscr-flash-size is zero. Ignoring properties!\n");
1984 *bootscr_flash_offset = 0;
1991 ofnode ofnode_get_phy_node(ofnode node)
1993 /* DT node properties that reference a PHY node */
1994 static const char * const phy_handle_str[] = {
1995 "phy-handle", "phy", "phy-device",
1997 struct ofnode_phandle_args args = {
1998 .node = ofnode_null()
2002 assert(ofnode_valid(node));
2004 for (i = 0; i < ARRAY_SIZE(phy_handle_str); i++)
2005 if (!ofnode_parse_phandle_with_args(node, phy_handle_str[i],
2012 phy_interface_t ofnode_read_phy_mode(ofnode node)
2017 assert(ofnode_valid(node));
2019 mode = ofnode_read_string(node, "phy-mode");
2021 mode = ofnode_read_string(node, "phy-connection-type");
2024 return PHY_INTERFACE_MODE_NA;
2026 for (i = 0; i < PHY_INTERFACE_MODE_MAX; i++)
2027 if (!strcmp(mode, phy_interface_strings[i]))
2030 dm_warn("%s: Invalid PHY interface '%s'\n", __func__, mode);
2032 return PHY_INTERFACE_MODE_NA;
2035 int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
2040 assert(ofnode_valid(node));
2042 if (ofnode_is_np(node)) {
2043 struct device_node *np, *child;
2045 np = (struct device_node *)ofnode_to_np(node);
2046 ret = of_add_subnode(np, name, -1, &child);
2047 if (ret && ret != -EEXIST)
2049 subnode = np_to_ofnode(child);
2051 void *fdt = ofnode_to_fdt(node);
2052 int poffset = ofnode_to_offset(node);
2055 offset = fdt_add_subnode(fdt, poffset, name);
2056 if (offset == -FDT_ERR_EXISTS) {
2057 offset = fdt_subnode_offset(fdt, poffset, name);
2061 return offset == -FDT_ERR_NOSPACE ? -ENOSPC : -EINVAL;
2062 subnode = noffset_to_ofnode(node, offset);
2065 *subnodep = subnode;
2067 return ret; /* 0 or -EEXIST */
2070 int ofnode_delete(ofnode *nodep)
2072 ofnode node = *nodep;
2075 assert(ofnode_valid(node));
2076 if (ofnode_is_np(node)) {
2077 ret = of_remove_node(ofnode_to_np(node));
2079 void *fdt = ofnode_to_fdt(node);
2080 int offset = ofnode_to_offset(node);
2082 ret = fdt_del_node(fdt, offset);
2088 *nodep = ofnode_null();
2093 int ofnode_copy_props(ofnode dst, ofnode src)
2097 ofnode_for_each_prop(prop, src) {
2102 val = ofprop_get_property(&prop, &name, &len);
2104 log_debug("Cannot read prop (err=%d)\n", len);
2105 return log_msg_ret("get", -EINVAL);
2107 ret = ofnode_write_prop(dst, name, val, len, true);
2109 log_debug("Cannot write prop (err=%d)\n", ret);
2110 return log_msg_ret("wr", -EINVAL);
2117 int ofnode_copy_node(ofnode dst_parent, const char *name, ofnode src,
2123 ret = ofnode_add_subnode(dst_parent, name, &node);
2127 return log_msg_ret("add", ret);
2129 ret = ofnode_copy_props(node, src);
2131 return log_msg_ret("cpy", ret);