summaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-02-08 09:03:59 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2018-02-08 09:03:59 +0100
commit0fae783beefc4ea6f201d517bcfe9dd1bd02f38b (patch)
treee3154839464d550a4a2c03c49e8bd4bef8eb50a1 /drivers/of
parent490a3c496454cea131dbd5edadbe7d7cfce4cfa8 (diff)
parentabd0cea544372324656bf35b30b4cc6cd3b80317 (diff)
downloadbarebox-0fae783beefc4ea6f201d517bcfe9dd1bd02f38b.tar.gz
barebox-0fae783beefc4ea6f201d517bcfe9dd1bd02f38b.tar.xz
Merge branch 'for-next/of'
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/base.c107
-rw-r--r--drivers/of/fdt.c36
2 files changed, 120 insertions, 23 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 23e5e22ffe..152dbe7a4f 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -129,6 +129,11 @@ struct property *of_find_property(const struct device_node *np,
}
EXPORT_SYMBOL(of_find_property);
+const void *of_property_get_value(struct property *pp)
+{
+ return pp->value ? pp->value : pp->value_const;
+}
+
static void of_alias_add(struct alias_prop *ap, struct device_node *np,
int id, const char *stem, int stem_len)
{
@@ -178,7 +183,7 @@ void of_alias_scan(void)
!of_prop_cmp(pp->name, "linux,phandle"))
continue;
- np = of_find_node_by_path(pp->value);
+ np = of_find_node_by_path(of_property_get_value(pp));
if (!np)
continue;
@@ -374,7 +379,10 @@ const void *of_get_property(const struct device_node *np, const char *name,
{
struct property *pp = of_find_property(np, name, lenp);
- return pp ? pp->value : NULL;
+ if (!pp)
+ return NULL;
+
+ return of_property_get_value(pp);
}
EXPORT_SYMBOL(of_get_property);
@@ -678,19 +686,21 @@ EXPORT_SYMBOL(of_match);
* property data isn't large enough.
*
*/
-static void *of_find_property_value_of_size(const struct device_node *np,
+static const void *of_find_property_value_of_size(const struct device_node *np,
const char *propname, u32 len)
{
struct property *prop = of_find_property(np, propname, NULL);
+ const void *value;
if (!prop)
return ERR_PTR(-EINVAL);
- if (!prop->value)
+ value = of_property_get_value(prop);
+ if (!value)
return ERR_PTR(-ENODATA);
if (len > prop->length)
return ERR_PTR(-EOVERFLOW);
- return prop->value;
+ return value;
}
/**
@@ -867,13 +877,16 @@ int of_property_read_string(struct device_node *np, const char *propname,
const char **out_string)
{
struct property *prop = of_find_property(np, propname, NULL);
+ const void *value;
+
if (!prop)
return -EINVAL;
- if (!prop->value)
+ value = of_property_get_value(prop);
+ if (!value)
return -ENODATA;
- if (strnlen(prop->value, prop->length) >= prop->length)
+ if (strnlen(value, prop->length) >= prop->length)
return -EILSEQ;
- *out_string = prop->value;
+ *out_string = value;
return 0;
}
EXPORT_SYMBOL_GPL(of_property_read_string);
@@ -903,15 +916,17 @@ int of_property_read_string_index(struct device_node *np, const char *propname,
int i = 0;
size_t l = 0, total = 0;
const char *p;
+ const void *value;
if (!prop)
return -EINVAL;
- if (!prop->value)
+ value = of_property_get_value(prop);
+ if (!value)
return -ENODATA;
- if (strnlen(prop->value, prop->length) >= prop->length)
+ if (strnlen(value, prop->length) >= prop->length)
return -EILSEQ;
- p = prop->value;
+ p = value;
for (i = 0; total < prop->length; total += l, p += l) {
l = strlen(p) + 1;
@@ -943,10 +958,11 @@ int of_property_match_string(struct device_node *np, const char *propname,
if (!prop)
return -EINVAL;
- if (!prop->value)
+
+ p = of_property_get_value(prop);
+ if (!p)
return -ENODATA;
- p = prop->value;
end = p + prop->length;
for (i = 0; p < end; i++, p += l) {
@@ -979,15 +995,17 @@ int of_property_count_strings(struct device_node *np, const char *propname)
int i = 0;
size_t l = 0, total = 0;
const char *p;
+ const void *value;
if (!prop)
return -EINVAL;
- if (!prop->value)
+ value = of_property_get_value(prop);
+ if (!value)
return -ENODATA;
- if (strnlen(prop->value, prop->length) >= prop->length)
+ if (strnlen(value, prop->length) >= prop->length)
return -EILSEQ;
- p = prop->value;
+ p = value;
for (i = 0; total < prop->length; total += l, p += l, i++)
l = strlen(p) + 1;
@@ -1000,17 +1018,20 @@ const __be32 *of_prop_next_u32(struct property *prop, const __be32 *cur,
u32 *pu)
{
const void *curv = cur;
+ const void *value;
if (!prop)
return NULL;
+ value = of_property_get_value(prop);
+
if (!cur) {
- curv = prop->value;
+ curv = value;
goto out_val;
}
curv += sizeof(*cur);
- if (curv >= prop->value + prop->length)
+ if (curv >= value + prop->length)
return NULL;
out_val:
@@ -1022,15 +1043,18 @@ EXPORT_SYMBOL_GPL(of_prop_next_u32);
const char *of_prop_next_string(struct property *prop, const char *cur)
{
const void *curv = cur;
+ const void *value;
if (!prop)
return NULL;
+ value = of_property_get_value(prop);
+
if (!cur)
- return prop->value;
+ return value;
curv += strlen(cur) + 1;
- if (curv >= prop->value + prop->length)
+ if (curv >= value + prop->length)
return NULL;
return curv;
@@ -1777,7 +1801,7 @@ void of_print_nodes(struct device_node *node, int indent)
printf("%s", p->name);
if (p->length) {
printf(" = ");
- of_print_property(p->value, p->length);
+ of_print_property(of_property_get_value(p), p->length);
}
printf(";\n");
}
@@ -1817,6 +1841,18 @@ struct device_node *of_new_node(struct device_node *parent, const char *name)
return node;
}
+/**
+ * of_new_property - Add a new property to a node
+ * @node: device node to which the property is added
+ * @name: Name of the new property
+ * @data: Value of the property (can be NULL)
+ * @len: Length of the value
+ *
+ * This adds a new property to a device node. @data is copied and no longer needed
+ * after calling this function.
+ *
+ * Return: A pointer to the new property
+ */
struct property *of_new_property(struct device_node *node, const char *name,
const void *data, int len)
{
@@ -1835,6 +1871,35 @@ struct property *of_new_property(struct device_node *node, const char *name,
return prop;
}
+/**
+ * of_new_property_const - Add a new property to a node
+ * @node: device node to which the property is added
+ * @name: Name of the new property
+ * @data: Value of the property (can be NULL)
+ * @len: Length of the value
+ *
+ * This adds a new property to a device node. @data is used directly in the
+ * property and must be valid until the property is deleted again or set to
+ * another value. Normally you shouldn't use this function, use of_new_property()
+ * instead.
+ *
+ * Return: A pointer to the new property
+ */
+struct property *of_new_property_const(struct device_node *node, const char *name,
+ const void *data, int len)
+{
+ struct property *prop;
+
+ prop = xzalloc(sizeof(*prop));
+ prop->name = xstrdup(name);
+ prop->length = len;
+ prop->value_const = data;
+
+ list_add_tail(&prop->list, &node->properties);
+
+ return prop;
+}
+
void of_delete_property(struct property *pp)
{
if (!pp)
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 614e136de6..1edb35f3d6 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -117,7 +117,7 @@ static int of_unflatten_reservemap(struct device_node *root,
* Parse a flat device tree binary blob and return a pointer to the
* unflattened tree.
*/
-struct device_node *of_unflatten_dtb(const void *infdt)
+struct device_node *__of_unflatten_dtb(const void *infdt, bool constprops)
{
const void *nodep; /* property node pointer */
uint32_t tag; /* tag */
@@ -221,7 +221,11 @@ struct device_node *of_unflatten_dtb(const void *infdt)
goto err;
}
- p = of_new_property(node, name, nodep, len);
+ if (constprops)
+ p = of_new_property_const(node, name, nodep, len);
+ else
+ p = of_new_property(node, name, nodep, len);
+
if (!strcmp(name, "phandle") && len == 4)
node->phandle = be32_to_cpup(p->value);
@@ -255,6 +259,34 @@ err:
return ERR_PTR(ret);
}
+/**
+ * of_unflatten_dtb - unflatten a dtb binary blob
+ * @infdt - the fdt blob to unflatten
+ *
+ * Parse a flat device tree binary blob and return a pointer to the unflattened
+ * tree. The tree must be freed after use with of_delete_node().
+ */
+struct device_node *of_unflatten_dtb(const void *infdt)
+{
+ return __of_unflatten_dtb(infdt, false);
+}
+
+/**
+ * of_unflatten_dtb_const - unflatten a dtb binary blob
+ * @infdt - the fdt blob to unflatten
+ *
+ * Parse a flat device tree binary blob and return a pointer to the unflattened
+ * tree. The tree must be freed after use with of_delete_node(). Unlike the
+ * above version this function uses the property data directly from the input
+ * flattened tree instead of copying the data, thus @infdt must be valid for the
+ * whole lifetime of the returned tree. This is normally not what you want, so
+ * use of_unflatten_dtb() instead.
+ */
+struct device_node *of_unflatten_dtb_const(const void *infdt)
+{
+ return __of_unflatten_dtb(infdt, true);
+}
+
struct fdt {
void *dt;
uint32_t dt_nextofs;