dm: core: Allow obtaining a node offset in the same tree
[platform/kernel/u-boot.git] / drivers / core / ofnode.c
index 42f3c09..b1ba8c5 100644 (file)
@@ -119,8 +119,8 @@ int ofnode_read_u32_index(ofnode node, const char *propname, int index,
                return of_read_u32_index(ofnode_to_np(node), propname, index,
                                         outp);
 
-       cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
-                          &len);
+       cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
+                          propname, &len);
        if (!cell) {
                debug("(not found)\n");
                return -EINVAL;
@@ -165,8 +165,8 @@ int ofnode_read_u64(ofnode node, const char *propname, u64 *outp)
        if (ofnode_is_np(node))
                return of_read_u64(ofnode_to_np(node), propname, outp);
 
-       cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
-                          &len);
+       cell = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
+                          propname, &len);
        if (!cell || len < sizeof(*cell)) {
                debug("(not found)\n");
                return -EINVAL;
@@ -217,7 +217,7 @@ const void *ofnode_read_prop(ofnode node, const char *propname, int *sizep)
                        len = prop->length;
                }
        } else {
-               val = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
+               val = fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
                                  propname, &len);
        }
        if (!val) {
@@ -268,7 +268,7 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
        debug("%s: %s: ", __func__, subnode_name);
 
        if (ofnode_is_np(node)) {
-               const struct device_node *np = ofnode_to_np(node);
+               struct device_node *np = ofnode_to_np(node);
 
                for (np = np->child; np; np = np->sibling) {
                        if (!strcmp(subnode_name, np->name))
@@ -276,9 +276,9 @@ ofnode ofnode_find_subnode(ofnode node, const char *subnode_name)
                }
                subnode = np_to_ofnode(np);
        } else {
-               int ooffset = fdt_subnode_offset(gd->fdt_blob,
+               int ooffset = fdt_subnode_offset(ofnode_to_fdt(node),
                                ofnode_to_offset(node), subnode_name);
-               subnode = offset_to_ofnode(ooffset);
+               subnode = noffset_to_ofnode(node, ooffset);
        }
        debug("%s\n", ofnode_valid(subnode) ?
              ofnode_get_name(subnode) : "<none>");
@@ -296,9 +296,20 @@ int ofnode_read_u32_array(ofnode node, const char *propname,
                return of_read_u32_array(ofnode_to_np(node), propname,
                                         out_values, sz);
        } else {
-               return fdtdec_get_int_array(gd->fdt_blob,
-                                           ofnode_to_offset(node), propname,
-                                           out_values, sz);
+               int ret;
+
+               ret = fdtdec_get_int_array(ofnode_to_fdt(node),
+                                          ofnode_to_offset(node), propname,
+                                          out_values, sz);
+
+               /* get the error right, but space is more important in SPL */
+               if (!IS_ENABLED(CONFIG_SPL_BUILD)) {
+                       if (ret == -FDT_ERR_NOTFOUND)
+                               return -EINVAL;
+                       else if (ret == -FDT_ERR_BADLAYOUT)
+                               return -EOVERFLOW;
+               }
+               return ret;
        }
 }
 
@@ -308,7 +319,7 @@ bool ofnode_is_enabled(ofnode node)
        if (ofnode_is_np(node)) {
                return of_device_is_available(ofnode_to_np(node));
        } else {
-               return fdtdec_get_is_enabled(gd->fdt_blob,
+               return fdtdec_get_is_enabled(ofnode_to_fdt(node),
                                             ofnode_to_offset(node));
        }
 }
@@ -319,8 +330,8 @@ ofnode ofnode_first_subnode(ofnode node)
        if (ofnode_is_np(node))
                return np_to_ofnode(node.np->child);
 
-       return offset_to_ofnode(
-               fdt_first_subnode(gd->fdt_blob, ofnode_to_offset(node)));
+       return noffset_to_ofnode(node,
+               fdt_first_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
 }
 
 ofnode ofnode_next_subnode(ofnode node)
@@ -329,8 +340,8 @@ ofnode ofnode_next_subnode(ofnode node)
        if (ofnode_is_np(node))
                return np_to_ofnode(node.np->sibling);
 
-       return offset_to_ofnode(
-               fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node)));
+       return noffset_to_ofnode(node,
+               fdt_next_subnode(ofnode_to_fdt(node), ofnode_to_offset(node)));
 }
 #endif /* !DM_INLINE_OFNODE */
 
@@ -342,7 +353,7 @@ ofnode ofnode_get_parent(ofnode node)
        if (ofnode_is_np(node))
                parent = np_to_ofnode(of_get_parent(ofnode_to_np(node)));
        else
-               parent.of_offset = fdt_parent_offset(gd->fdt_blob,
+               parent.of_offset = fdt_parent_offset(ofnode_to_fdt(node),
                                                     ofnode_to_offset(node));
 
        return parent;
@@ -356,9 +367,9 @@ const char *ofnode_get_name(ofnode node)
        }
 
        if (ofnode_is_np(node))
-               return strrchr(node.np->full_name, '/') + 1;
+               return node.np->name;
 
-       return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
+       return fdt_get_name(ofnode_to_fdt(node), ofnode_to_offset(node), NULL);
 }
 
 int ofnode_get_path(ofnode node, char *buf, int buflen)
@@ -375,7 +386,7 @@ int ofnode_get_path(ofnode node, char *buf, int buflen)
        } else {
                int res;
 
-               res = fdt_get_path(gd->fdt_blob, ofnode_to_offset(node), buf,
+               res = fdt_get_path(ofnode_to_fdt(node), ofnode_to_offset(node), buf,
                                   buflen);
                if (!res)
                        return res;
@@ -391,7 +402,7 @@ ofnode ofnode_get_by_phandle(uint phandle)
        ofnode node;
 
        if (of_live_active())
-               node = np_to_ofnode(of_find_node_by_phandle(phandle));
+               node = np_to_ofnode(of_find_node_by_phandle(NULL, phandle));
        else
                node.of_offset = fdt_node_offset_by_phandle(gd->fdt_blob,
                                                            phandle);
@@ -399,6 +410,20 @@ ofnode ofnode_get_by_phandle(uint phandle)
        return node;
 }
 
+ofnode oftree_get_by_phandle(oftree tree, uint phandle)
+{
+       ofnode node;
+
+       if (of_live_active())
+               node = np_to_ofnode(of_find_node_by_phandle(tree.np, phandle));
+       else
+               node.of_offset =
+                       fdt_node_offset_by_phandle(oftree_lookup_fdt(tree),
+                                                  phandle);
+
+       return node;
+}
+
 static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
                                               fdt_size_t *size, bool translate)
 {
@@ -431,7 +456,7 @@ static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
        } else {
                na = ofnode_read_simple_addr_cells(ofnode_get_parent(node));
                ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
-               return fdtdec_get_addr_size_fixed(gd->fdt_blob,
+               return fdtdec_get_addr_size_fixed(ofnode_to_fdt(node),
                                                  ofnode_to_offset(node), "reg",
                                                  index, na, ns, size,
                                                  translate);
@@ -479,7 +504,7 @@ int ofnode_stringlist_search(ofnode node, const char *property,
        } else {
                int ret;
 
-               ret = fdt_stringlist_search(gd->fdt_blob,
+               ret = fdt_stringlist_search(ofnode_to_fdt(node),
                                            ofnode_to_offset(node), property,
                                            string);
                if (ret == -FDT_ERR_NOTFOUND)
@@ -500,7 +525,8 @@ int ofnode_read_string_index(ofnode node, const char *property, int index,
        } else {
                int len;
 
-               *outp = fdt_stringlist_get(gd->fdt_blob, ofnode_to_offset(node),
+               *outp = fdt_stringlist_get(ofnode_to_fdt(node),
+                                          ofnode_to_offset(node),
                                           property, index, &len);
                if (len < 0)
                        return -EINVAL;
@@ -513,7 +539,7 @@ int ofnode_read_string_count(ofnode node, const char *property)
        if (ofnode_is_np(node)) {
                return of_property_count_strings(ofnode_to_np(node), property);
        } else {
-               return fdt_stringlist_count(gd->fdt_blob,
+               return fdt_stringlist_count(ofnode_to_fdt(node),
                                            ofnode_to_offset(node), property);
        }
 }
@@ -582,7 +608,7 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
                struct fdtdec_phandle_args args;
                int ret;
 
-               ret = fdtdec_parse_phandle_with_args(gd->fdt_blob,
+               ret = fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
                                                     ofnode_to_offset(node),
                                                     list_name, cells_name,
                                                     cell_count, index, &args);
@@ -601,7 +627,7 @@ int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
                return of_count_phandle_with_args(ofnode_to_np(node),
                                list_name, cells_name, cell_count);
        else
-               return fdtdec_parse_phandle_with_args(gd->fdt_blob,
+               return fdtdec_parse_phandle_with_args(ofnode_to_fdt(node),
                                ofnode_to_offset(node), list_name, cells_name,
                                cell_count, -1, NULL);
 }
@@ -776,11 +802,11 @@ const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
        if (ofnode_is_np(node))
                return of_get_property(ofnode_to_np(node), propname, lenp);
        else
-               return fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
+               return fdt_getprop(ofnode_to_fdt(node), ofnode_to_offset(node),
                                   propname, lenp);
 }
 
-int ofnode_get_first_property(ofnode node, struct ofprop *prop)
+int ofnode_first_property(ofnode node, struct ofprop *prop)
 {
        prop->node = node;
 
@@ -790,7 +816,7 @@ int ofnode_get_first_property(ofnode node, struct ofprop *prop)
                        return -FDT_ERR_NOTFOUND;
        } else {
                prop->offset =
-                       fdt_first_property_offset(gd->fdt_blob,
+                       fdt_first_property_offset(ofnode_to_fdt(node),
                                                  ofnode_to_offset(prop->node));
                if (prop->offset < 0)
                        return prop->offset;
@@ -799,7 +825,7 @@ int ofnode_get_first_property(ofnode node, struct ofprop *prop)
        return 0;
 }
 
-int ofnode_get_next_property(struct ofprop *prop)
+int ofnode_next_property(struct ofprop *prop)
 {
        if (ofnode_is_np(prop->node)) {
                prop->prop = of_get_next_property(ofnode_to_np(prop->node),
@@ -807,8 +833,9 @@ int ofnode_get_next_property(struct ofprop *prop)
                if (!prop->prop)
                        return -FDT_ERR_NOTFOUND;
        } else {
-               prop->offset = fdt_next_property_offset(gd->fdt_blob,
-                                                       prop->offset);
+               prop->offset =
+                       fdt_next_property_offset(ofnode_to_fdt(prop->node),
+                                                prop->offset);
                if (prop->offset  < 0)
                        return prop->offset;
        }
@@ -816,27 +843,18 @@ int ofnode_get_next_property(struct ofprop *prop)
        return 0;
 }
 
-const void *ofnode_get_property_by_prop(const struct ofprop *prop,
-                                       const char **propname, int *lenp)
+const void *ofprop_get_property(const struct ofprop *prop,
+                               const char **propname, int *lenp)
 {
        if (ofnode_is_np(prop->node))
                return of_get_property_by_prop(ofnode_to_np(prop->node),
                                               prop->prop, propname, lenp);
        else
-               return fdt_getprop_by_offset(gd->fdt_blob,
+               return fdt_getprop_by_offset(ofnode_to_fdt(prop->node),
                                             prop->offset,
                                             propname, lenp);
 }
 
-bool ofnode_is_available(ofnode node)
-{
-       if (ofnode_is_np(node))
-               return of_device_is_available(ofnode_to_np(node));
-       else
-               return fdtdec_get_is_enabled(gd->fdt_blob,
-                                            ofnode_to_offset(node));
-}
-
 fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
                                fdt_size_t *sizep)
 {
@@ -857,7 +875,7 @@ fdt_addr_t ofnode_get_addr_size(ofnode node, const char *property,
                else
                        return of_read_number(prop, na);
        } else {
-               return fdtdec_get_addr_size(gd->fdt_blob,
+               return fdtdec_get_addr_size(ofnode_to_fdt(node),
                                            ofnode_to_offset(node), property,
                                            sizep);
        }
@@ -876,7 +894,7 @@ const uint8_t *ofnode_read_u8_array_ptr(ofnode node, const char *propname,
                return (uint8_t *)prop;
 
        } else {
-               return fdtdec_locate_byte_array(gd->fdt_blob,
+               return fdtdec_locate_byte_array(ofnode_to_fdt(node),
                                ofnode_to_offset(node), propname, sz);
        }
 }
@@ -1012,10 +1030,10 @@ int ofnode_read_addr_cells(ofnode node)
        if (ofnode_is_np(node)) {
                return of_n_addr_cells(ofnode_to_np(node));
        } else {
-               int parent = fdt_parent_offset(gd->fdt_blob,
+               int parent = fdt_parent_offset(ofnode_to_fdt(node),
                                               ofnode_to_offset(node));
 
-               return fdt_address_cells(gd->fdt_blob, parent);
+               return fdt_address_cells(ofnode_to_fdt(node), parent);
        }
 }
 
@@ -1024,10 +1042,10 @@ int ofnode_read_size_cells(ofnode node)
        if (ofnode_is_np(node)) {
                return of_n_size_cells(ofnode_to_np(node));
        } else {
-               int parent = fdt_parent_offset(gd->fdt_blob,
+               int parent = fdt_parent_offset(ofnode_to_fdt(node),
                                               ofnode_to_offset(node));
 
-               return fdt_size_cells(gd->fdt_blob, parent);
+               return fdt_size_cells(ofnode_to_fdt(node), parent);
        }
 }
 
@@ -1036,7 +1054,8 @@ int ofnode_read_simple_addr_cells(ofnode node)
        if (ofnode_is_np(node))
                return of_simple_addr_cells(ofnode_to_np(node));
        else
-               return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
+               return fdt_address_cells(ofnode_to_fdt(node),
+                                        ofnode_to_offset(node));
 }
 
 int ofnode_read_simple_size_cells(ofnode node)
@@ -1044,7 +1063,8 @@ int ofnode_read_simple_size_cells(ofnode node)
        if (ofnode_is_np(node))
                return of_simple_size_cells(ofnode_to_np(node));
        else
-               return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
+               return fdt_size_cells(ofnode_to_fdt(node),
+                                     ofnode_to_offset(node));
 }
 
 bool ofnode_pre_reloc(ofnode node)
@@ -1081,7 +1101,8 @@ int ofnode_read_resource(ofnode node, uint index, struct resource *res)
                struct fdt_resource fres;
                int ret;
 
-               ret = fdt_get_resource(gd->fdt_blob, ofnode_to_offset(node),
+               ret = fdt_get_resource(ofnode_to_fdt(node),
+                                      ofnode_to_offset(node),
                                       "reg", index, &fres);
                if (ret < 0)
                        return -EINVAL;
@@ -1110,7 +1131,8 @@ u64 ofnode_translate_address(ofnode node, const fdt32_t *in_addr)
        if (ofnode_is_np(node))
                return of_translate_address(ofnode_to_np(node), in_addr);
        else
-               return fdt_translate_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
+               return fdt_translate_address(ofnode_to_fdt(node),
+                                            ofnode_to_offset(node), in_addr);
 }
 
 u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
@@ -1118,7 +1140,8 @@ u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
        if (ofnode_is_np(node))
                return of_translate_dma_address(ofnode_to_np(node), in_addr);
        else
-               return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
+               return fdt_translate_dma_address(ofnode_to_fdt(node),
+                                                ofnode_to_offset(node), in_addr);
 }
 
 int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
@@ -1126,7 +1149,8 @@ int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *si
        if (ofnode_is_np(node))
                return of_get_dma_range(ofnode_to_np(node), cpu, bus, size);
        else
-               return fdt_get_dma_range(gd->fdt_blob, ofnode_to_offset(node),
+               return fdt_get_dma_range(ofnode_to_fdt(node),
+                                        ofnode_to_offset(node),
                                         cpu, bus, size);
 }
 
@@ -1136,7 +1160,7 @@ int ofnode_device_is_compatible(ofnode node, const char *compat)
                return of_device_is_compatible(ofnode_to_np(node), compat,
                                               NULL, NULL);
        else
-               return !fdt_node_check_compatible(gd->fdt_blob,
+               return !fdt_node_check_compatible(ofnode_to_fdt(node),
                                                  ofnode_to_offset(node),
                                                  compat);
 }
@@ -1148,8 +1172,9 @@ ofnode ofnode_by_compatible(ofnode from, const char *compat)
                        (struct device_node *)ofnode_to_np(from), NULL,
                        compat));
        } else {
-               return offset_to_ofnode(fdt_node_offset_by_compatible(
-                               gd->fdt_blob, ofnode_to_offset(from), compat));
+               return noffset_to_ofnode(from,
+                       fdt_node_offset_by_compatible(ofnode_to_fdt(from),
+                                       ofnode_to_offset(from), compat));
        }
 }
 
@@ -1161,9 +1186,10 @@ ofnode ofnode_by_prop_value(ofnode from, const char *propname,
                        (struct device_node *)ofnode_to_np(from), propname,
                        propval, proplen));
        } else {
-               return offset_to_ofnode(fdt_node_offset_by_prop_value(
-                               gd->fdt_blob, ofnode_to_offset(from),
-                               propname, propval, proplen));
+               return noffset_to_ofnode(from,
+                        fdt_node_offset_by_prop_value(ofnode_to_fdt(from),
+                               ofnode_to_offset(from), propname, propval,
+                               proplen));
        }
 }
 
@@ -1171,9 +1197,9 @@ int ofnode_write_prop(ofnode node, const char *propname, const void *value,
                      int len)
 {
        if (of_live_active())
-               return of_write_prop(ofnode_to_npw(node), propname, len, value);
+               return of_write_prop(ofnode_to_np(node), propname, len, value);
        else
-               return fdt_setprop((void *)gd->fdt_blob, ofnode_to_offset(node),
+               return fdt_setprop(ofnode_to_fdt(node), ofnode_to_offset(node),
                                   propname, value, len);
 
        return 0;
@@ -1289,3 +1315,38 @@ phy_interface_t ofnode_read_phy_mode(ofnode node)
 
        return PHY_INTERFACE_MODE_NA;
 }
+
+int ofnode_add_subnode(ofnode node, const char *name, ofnode *subnodep)
+{
+       ofnode subnode;
+       int ret = 0;
+
+       assert(ofnode_valid(node));
+
+       if (ofnode_is_np(node)) {
+               struct device_node *np, *child;
+
+               np = (struct device_node *)ofnode_to_np(node);
+               ret = of_add_subnode(np, name, -1, &child);
+               if (ret && ret != -EEXIST)
+                       return ret;
+               subnode = np_to_ofnode(child);
+       } else {
+               void *fdt = ofnode_to_fdt(node);
+               int poffset = ofnode_to_offset(node);
+               int offset;
+
+               offset = fdt_add_subnode(fdt, poffset, name);
+               if (offset == -FDT_ERR_EXISTS) {
+                       offset = fdt_subnode_offset(fdt, poffset, name);
+                       ret = -EEXIST;
+               }
+               if (offset < 0)
+                       return -EINVAL;
+               subnode = noffset_to_ofnode(node, offset);
+       }
+
+       *subnodep = subnode;
+
+       return ret;     /* 0 or -EEXIST */
+}