Merge tag 'ti-v2021.10-rc2' of https://source.denx.de/u-boot/custodians/u-boot-ti
[platform/kernel/u-boot.git] / drivers / core / ofnode.c
index 96a5dd2..701b23e 100644 (file)
@@ -8,6 +8,7 @@
 #include <dm.h>
 #include <fdtdec.h>
 #include <fdt_support.h>
+#include <log.h>
 #include <malloc.h>
 #include <linux/libfdt.h>
 #include <dm/of_access.h>
 #include <dm/ofnode.h>
 #include <linux/err.h>
 #include <linux/ioport.h>
+#include <asm/global_data.h>
+
+bool ofnode_name_eq(ofnode node, const char *name)
+{
+       const char *node_name;
+       size_t len;
+
+       assert(ofnode_valid(node));
+
+       node_name = ofnode_get_name(node);
+       len = strchrnul(node_name, '@') - node_name;
+
+       return (strlen(name) == len) && !strncmp(node_name, name, len);
+}
 
 int ofnode_read_u32(ofnode node, const char *propname, u32 *outp)
 {
+       return ofnode_read_u32_index(node, propname, 0, outp);
+}
+
+u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
+{
+       assert(ofnode_valid(node));
+       ofnode_read_u32_index(node, propname, 0, &def);
+
+       return def;
+}
+
+int ofnode_read_u32_index(ofnode node, const char *propname, int index,
+                         u32 *outp)
+{
+       const fdt32_t *cell;
+       int len;
+
        assert(ofnode_valid(node));
        debug("%s: %s: ", __func__, propname);
 
-       if (ofnode_is_np(node)) {
-               return of_read_u32(ofnode_to_np(node), propname, outp);
-       } else {
-               const fdt32_t *cell;
-               int len;
+       if (ofnode_is_np(node))
+               return of_read_u32_index(ofnode_to_np(node), propname, index,
+                                        outp);
 
-               cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node),
-                                  propname, &len);
-               if (!cell || len < sizeof(int)) {
-                       debug("(not found)\n");
-                       return -EINVAL;
-               }
-               *outp = fdt32_to_cpu(cell[0]);
+       cell = fdt_getprop(gd->fdt_blob, ofnode_to_offset(node), propname,
+                          &len);
+       if (!cell) {
+               debug("(not found)\n");
+               return -EINVAL;
+       }
+
+       if (len < (sizeof(int) * (index + 1))) {
+               debug("(not large enough)\n");
+               return -EOVERFLOW;
        }
+
+       *outp = fdt32_to_cpu(cell[index]);
        debug("%#x (%d)\n", *outp, *outp);
 
        return 0;
 }
 
-u32 ofnode_read_u32_default(ofnode node, const char *propname, u32 def)
+u32 ofnode_read_u32_index_default(ofnode node, const char *propname, int index,
+                                 u32 def)
 {
        assert(ofnode_valid(node));
-       ofnode_read_u32(node, propname, &def);
+       ofnode_read_u32_index(node, propname, index, &def);
 
        return def;
 }
@@ -204,6 +240,17 @@ int ofnode_read_u32_array(ofnode node, const char *propname,
        }
 }
 
+#if !CONFIG_IS_ENABLED(DM_INLINE_OFNODE)
+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,
+                                            ofnode_to_offset(node));
+       }
+}
+
 ofnode ofnode_first_subnode(ofnode node)
 {
        assert(ofnode_valid(node));
@@ -223,6 +270,7 @@ ofnode ofnode_next_subnode(ofnode node)
        return offset_to_ofnode(
                fdt_next_subnode(gd->fdt_blob, ofnode_to_offset(node)));
 }
+#endif /* !DM_INLINE_OFNODE */
 
 ofnode ofnode_get_parent(ofnode node)
 {
@@ -251,6 +299,31 @@ const char *ofnode_get_name(ofnode node)
        return fdt_get_name(gd->fdt_blob, ofnode_to_offset(node), NULL);
 }
 
+int ofnode_get_path(ofnode node, char *buf, int buflen)
+{
+       assert(ofnode_valid(node));
+
+       if (ofnode_is_np(node)) {
+               if (strlen(node.np->full_name) >= buflen)
+                       return -ENOSPC;
+
+               strcpy(buf, node.np->full_name);
+
+               return 0;
+       } else {
+               int res;
+
+               res = fdt_get_path(gd->fdt_blob, ofnode_to_offset(node), buf,
+                                  buflen);
+               if (!res)
+                       return res;
+               else if (res == -FDT_ERR_NOSPACE)
+                       return -ENOSPC;
+               else
+                       return -EINVAL;
+       }
+}
+
 ofnode ofnode_get_by_phandle(uint phandle)
 {
        ofnode node;
@@ -264,10 +337,14 @@ ofnode ofnode_get_by_phandle(uint phandle)
        return node;
 }
 
-fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
+static fdt_addr_t __ofnode_get_addr_size_index(ofnode node, int index,
+                                              fdt_size_t *size, bool translate)
 {
        int na, ns;
 
+       if (size)
+               *size = FDT_SIZE_T_NONE;
+
        if (ofnode_is_np(node)) {
                const __be32 *prop_val;
                u64 size64;
@@ -277,12 +354,13 @@ fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
                                          &flags);
                if (!prop_val)
                        return FDT_ADDR_T_NONE;
+
                if (size)
                        *size = size64;
 
                ns = of_n_size_cells(ofnode_to_np(node));
 
-               if (IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
+               if (translate && IS_ENABLED(CONFIG_OF_TRANSLATE) && ns > 0) {
                        return of_translate_address(ofnode_to_np(node), prop_val);
                } else {
                        na = of_n_addr_cells(ofnode_to_np(node));
@@ -293,10 +371,20 @@ fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
                ns = ofnode_read_simple_size_cells(ofnode_get_parent(node));
                return fdtdec_get_addr_size_fixed(gd->fdt_blob,
                                                  ofnode_to_offset(node), "reg",
-                                                 index, na, ns, size, true);
+                                                 index, na, ns, size,
+                                                 translate);
        }
+}
+
+fdt_addr_t ofnode_get_addr_size_index(ofnode node, int index, fdt_size_t *size)
+{
+       return __ofnode_get_addr_size_index(node, index, size, true);
+}
 
-       return FDT_ADDR_T_NONE;
+fdt_addr_t ofnode_get_addr_size_index_notrans(ofnode node, int index,
+                                             fdt_size_t *size)
+{
+       return __ofnode_get_addr_size_index(node, index, size, false);
 }
 
 fdt_addr_t ofnode_get_addr_index(ofnode node, int index)
@@ -311,6 +399,15 @@ fdt_addr_t ofnode_get_addr(ofnode node)
        return ofnode_get_addr_index(node, 0);
 }
 
+fdt_size_t ofnode_get_size(ofnode node)
+{
+       fdt_size_t size;
+
+       ofnode_get_addr_size_index(node, 0, &size);
+
+       return size;
+}
+
 int ofnode_stringlist_search(ofnode node, const char *property,
                             const char *string)
 {
@@ -387,7 +484,8 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
                int ret;
 
                ret = of_parse_phandle_with_args(ofnode_to_np(node),
-                                                list_name, cells_name, index,
+                                                list_name, cells_name,
+                                                cell_count, index,
                                                 &args);
                if (ret)
                        return ret;
@@ -409,15 +507,15 @@ int ofnode_parse_phandle_with_args(ofnode node, const char *list_name,
 }
 
 int ofnode_count_phandle_with_args(ofnode node, const char *list_name,
-                                  const char *cells_name)
+                                  const char *cells_name, int cell_count)
 {
        if (ofnode_is_np(node))
                return of_count_phandle_with_args(ofnode_to_np(node),
-                               list_name, cells_name);
+                               list_name, cells_name, cell_count);
        else
                return fdtdec_parse_phandle_with_args(gd->fdt_blob,
                                ofnode_to_offset(node), list_name, cells_name,
-                               0, -1, NULL);
+                               cell_count, -1, NULL);
 }
 
 ofnode ofnode_path(const char *path)
@@ -453,6 +551,39 @@ ofnode ofnode_get_chosen_node(const char *name)
        return ofnode_path(prop);
 }
 
+const void *ofnode_read_aliases_prop(const char *propname, int *sizep)
+{
+       ofnode node;
+
+       node = ofnode_path("/aliases");
+
+       return ofnode_read_prop(node, propname, sizep);
+}
+
+ofnode ofnode_get_aliases_node(const char *name)
+{
+       const char *prop;
+
+       prop = ofnode_read_aliases_prop(name, NULL);
+       if (!prop)
+               return ofnode_null();
+
+       debug("%s: node_path: %s\n", __func__, prop);
+
+       return ofnode_path(prop);
+}
+
+int ofnode_get_child_count(ofnode parent)
+{
+       ofnode child;
+       int num = 0;
+
+       ofnode_for_each_subnode(child, parent)
+               num++;
+
+       return num;
+}
+
 static int decode_timing_property(ofnode node, const char *name,
                                  struct timing_entry *result)
 {
@@ -550,6 +681,54 @@ const void *ofnode_get_property(ofnode node, const char *propname, int *lenp)
                                   propname, lenp);
 }
 
+int ofnode_get_first_property(ofnode node, struct ofprop *prop)
+{
+       prop->node = node;
+
+       if (ofnode_is_np(node)) {
+               prop->prop = of_get_first_property(ofnode_to_np(prop->node));
+               if (!prop->prop)
+                       return -FDT_ERR_NOTFOUND;
+       } else {
+               prop->offset =
+                       fdt_first_property_offset(gd->fdt_blob,
+                                                 ofnode_to_offset(prop->node));
+               if (prop->offset < 0)
+                       return prop->offset;
+       }
+
+       return 0;
+}
+
+int ofnode_get_next_property(struct ofprop *prop)
+{
+       if (ofnode_is_np(prop->node)) {
+               prop->prop = of_get_next_property(ofnode_to_np(prop->node),
+                                                 prop->prop);
+               if (!prop->prop)
+                       return -FDT_ERR_NOTFOUND;
+       } else {
+               prop->offset = fdt_next_property_offset(gd->fdt_blob,
+                                                       prop->offset);
+               if (prop->offset  < 0)
+                       return prop->offset;
+       }
+
+       return 0;
+}
+
+const void *ofnode_get_property_by_prop(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,
+                                            prop->offset,
+                                            propname, lenp);
+}
+
 bool ofnode_is_available(ofnode node)
 {
        if (ofnode_is_np(node))
@@ -695,18 +874,26 @@ int ofnode_read_pci_vendev(ofnode node, u16 *vendor, u16 *device)
 
 int ofnode_read_addr_cells(ofnode node)
 {
-       if (ofnode_is_np(node))
+       if (ofnode_is_np(node)) {
                return of_n_addr_cells(ofnode_to_np(node));
-       else  /* NOTE: this call should walk up the parent stack */
-               return fdt_address_cells(gd->fdt_blob, ofnode_to_offset(node));
+       } else {
+               int parent = fdt_parent_offset(gd->fdt_blob,
+                                              ofnode_to_offset(node));
+
+               return fdt_address_cells(gd->fdt_blob, parent);
+       }
 }
 
 int ofnode_read_size_cells(ofnode node)
 {
-       if (ofnode_is_np(node))
+       if (ofnode_is_np(node)) {
                return of_n_size_cells(ofnode_to_np(node));
-       else  /* NOTE: this call should walk up the parent stack */
-               return fdt_size_cells(gd->fdt_blob, ofnode_to_offset(node));
+       } else {
+               int parent = fdt_parent_offset(gd->fdt_blob,
+                                              ofnode_to_offset(node));
+
+               return fdt_size_cells(gd->fdt_blob, parent);
+       }
 }
 
 int ofnode_read_simple_addr_cells(ofnode node)
@@ -799,6 +986,15 @@ u64 ofnode_translate_dma_address(ofnode node, const fdt32_t *in_addr)
                return fdt_translate_dma_address(gd->fdt_blob, ofnode_to_offset(node), in_addr);
 }
 
+int ofnode_get_dma_range(ofnode node, phys_addr_t *cpu, dma_addr_t *bus, u64 *size)
+{
+       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),
+                                        cpu, bus, size);
+}
+
 int ofnode_device_is_compatible(ofnode node, const char *compat)
 {
        if (ofnode_is_np(node))