+// SPDX-License-Identifier: GPL-2.0+
/*
* Originally from Linux v4.9
* Paul Mackerras August 1996.
*
* This file follows drivers/of/base.c with functions in the same order as the
* Linux version.
- *
- * SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
-#include <libfdt.h>
+#include <log.h>
+#include <malloc.h>
+#include <linux/bug.h>
+#include <linux/libfdt.h>
#include <dm/of_access.h>
#include <linux/ctype.h>
#include <linux/err.h>
return OF_ROOT_NODE_SIZE_CELLS_DEFAULT;
}
+int of_simple_addr_cells(const struct device_node *np)
+{
+ const __be32 *ip;
+
+ ip = of_get_property(np, "#address-cells", NULL);
+ if (ip)
+ return be32_to_cpup(ip);
+
+ /* Return a default of 2 to match fdt_address_cells()*/
+ return 2;
+}
+
+int of_simple_size_cells(const struct device_node *np)
+{
+ const __be32 *ip;
+
+ ip = of_get_property(np, "#size-cells", NULL);
+ if (ip)
+ return be32_to_cpup(ip);
+
+ /* Return a default of 2 to match fdt_size_cells()*/
+ return 2;
+}
+
struct property *of_find_property(const struct device_node *np,
const char *name, int *lenp)
{
return pp ? pp->value : NULL;
}
+const struct property *of_get_first_property(const struct device_node *np)
+{
+ if (!np)
+ return NULL;
+
+ return np->properties;
+}
+
+const struct property *of_get_next_property(const struct device_node *np,
+ const struct property *property)
+{
+ if (!np)
+ return NULL;
+
+ return property->next;
+}
+
+const void *of_get_property_by_prop(const struct device_node *np,
+ const struct property *property,
+ const char **name,
+ int *lenp)
+{
+ if (!np || !property)
+ return NULL;
+ if (name)
+ *name = property->name;
+ if (lenp)
+ *lenp = property->length;
+
+ return property->value;
+}
+
static const char *of_prop_next_string(struct property *prop, const char *cur)
{
const void *curv = cur;
return NULL;
next = prev ? prev->sibling : node->child;
+ /*
+ * coverity[dead_error_line : FALSE]
+ * Dead code here since our current implementation of of_node_get()
+ * always returns NULL (Coverity CID 163245). But we leave it as is
+ * since we may want to implement get/put later.
+ */
for (; next; next = next->sibling)
if (of_node_get(next))
break;
return np;
}
+static int of_device_has_prop_value(const struct device_node *device,
+ const char *propname, const void *propval,
+ int proplen)
+{
+ struct property *prop = of_find_property(device, propname, NULL);
+
+ if (!prop || !prop->value || prop->length != proplen)
+ return 0;
+ return !memcmp(prop->value, propval, proplen);
+}
+
+struct device_node *of_find_node_by_prop_value(struct device_node *from,
+ const char *propname,
+ const void *propval, int proplen)
+{
+ struct device_node *np;
+
+ for_each_of_allnodes_from(from, np) {
+ if (of_device_has_prop_value(np, propname, propval, proplen) &&
+ of_node_get(np))
+ break;
+ }
+ of_node_put(from);
+
+ return np;
+}
+
struct device_node *of_find_node_by_phandle(phandle handle)
{
struct device_node *np;
}
int of_read_u32(const struct device_node *np, const char *propname, u32 *outp)
+{
+ return of_read_u32_index(np, propname, 0, outp);
+}
+
+int of_read_u32_array(const struct device_node *np, const char *propname,
+ u32 *out_values, size_t sz)
+{
+ const __be32 *val;
+
+ debug("%s: %s: ", __func__, propname);
+ val = of_find_property_value_of_size(np, propname,
+ sz * sizeof(*out_values));
+
+ if (IS_ERR(val))
+ return PTR_ERR(val);
+
+ debug("size %zd\n", sz);
+ while (sz--)
+ *out_values++ = be32_to_cpup(val++);
+
+ return 0;
+}
+
+int of_read_u32_index(const struct device_node *np, const char *propname,
+ int index, u32 *outp)
{
const __be32 *val;
debug("%s: %s: ", __func__, propname);
if (!np)
return -EINVAL;
- val = of_find_property_value_of_size(np, propname, sizeof(*outp));
+
+ val = of_find_property_value_of_size(np, propname,
+ sizeof(*outp) * (index + 1));
if (IS_ERR(val)) {
debug("(not found)\n");
return PTR_ERR(val);
}
- *outp = be32_to_cpup(val);
+ *outp = be32_to_cpup(val + index);
debug("%#x (%d)\n", *outp, *outp);
return 0;
}
-int of_read_u32_array(const struct device_node *np, const char *propname,
- u32 *out_values, size_t sz)
+int of_read_u64(const struct device_node *np, const char *propname, u64 *outp)
{
- const __be32 *val;
+ const __be64 *val;
debug("%s: %s: ", __func__, propname);
- val = of_find_property_value_of_size(np, propname,
- sz * sizeof(*out_values));
-
- if (IS_ERR(val))
+ if (!np)
+ return -EINVAL;
+ val = of_find_property_value_of_size(np, propname, sizeof(*outp));
+ if (IS_ERR(val)) {
+ debug("(not found)\n");
return PTR_ERR(val);
+ }
- debug("size %zd\n", sz);
- while (sz--)
- *out_values++ = be32_to_cpup(val++);
+ *outp = be64_to_cpup(val);
+ debug("%#llx (%lld)\n", (unsigned long long)*outp,
+ (unsigned long long)*outp);
return 0;
}
{
const __be32 *list, *list_end;
int rc = 0, cur_index = 0;
- uint32_t count = 0;
+ uint32_t count;
struct device_node *node = NULL;
phandle phandle;
int size;
index, out_args);
}
+int of_count_phandle_with_args(const struct device_node *np,
+ const char *list_name, const char *cells_name)
+{
+ return __of_parse_phandle_with_args(np, list_name, cells_name, 0,
+ -1, NULL);
+}
+
static void of_alias_add(struct alias_prop *ap, struct device_node *np,
int id, const char *stem, int stem_len)
{
return id;
}
+int of_alias_get_highest_id(const char *stem)
+{
+ struct alias_prop *app;
+ int id = -1;
+
+ mutex_lock(&of_mutex);
+ list_for_each_entry(app, &aliases_lookup, link) {
+ if (strcmp(app->stem, stem) != 0)
+ continue;
+
+ if (app->id > id)
+ id = app->id;
+ }
+ mutex_unlock(&of_mutex);
+
+ return id;
+}
+
struct device_node *of_get_stdout(void)
{
return of_stdout;