summaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/Kconfig2
-rw-r--r--drivers/of/base.c130
-rw-r--r--drivers/of/fdt.c26
-rw-r--r--drivers/of/of_i2c.c2
-rw-r--r--drivers/of/of_mdio.c2
-rw-r--r--drivers/of/pdt.c12
6 files changed, 128 insertions, 46 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index dfba3e64d595..d37bfcf5a3a2 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -53,7 +53,7 @@ config OF_DEVICE
config OF_I2C
def_tristate I2C
- depends on I2C && !SPARC
+ depends on I2C
help
OpenFirmware I2C accessors
diff --git a/drivers/of/base.c b/drivers/of/base.c
index fa40402fe8d5..db8d211a0d05 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -45,7 +45,8 @@ struct alias_prop {
static LIST_HEAD(aliases_lookup);
-struct device_node *allnodes;
+struct device_node *of_allnodes;
+EXPORT_SYMBOL(of_allnodes);
struct device_node *of_chosen;
struct device_node *of_aliases;
@@ -199,7 +200,7 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
struct device_node *np;
read_lock(&devtree_lock);
- np = prev ? prev->allnext : allnodes;
+ np = prev ? prev->allnext : of_allnodes;
for (; np != NULL; np = np->allnext)
if (of_node_get(np))
break;
@@ -422,7 +423,7 @@ EXPORT_SYMBOL(of_get_child_by_name);
*/
struct device_node *of_find_node_by_path(const char *path)
{
- struct device_node *np = allnodes;
+ struct device_node *np = of_allnodes;
read_lock(&devtree_lock);
for (; np; np = np->allnext) {
@@ -452,7 +453,7 @@ struct device_node *of_find_node_by_name(struct device_node *from,
struct device_node *np;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext)
if (np->name && (of_node_cmp(np->name, name) == 0)
&& of_node_get(np))
@@ -481,7 +482,7 @@ struct device_node *of_find_node_by_type(struct device_node *from,
struct device_node *np;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext)
if (np->type && (of_node_cmp(np->type, type) == 0)
&& of_node_get(np))
@@ -512,7 +513,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
struct device_node *np;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
if (type
&& !(np->type && (of_node_cmp(np->type, type) == 0)))
@@ -545,7 +546,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
struct property *pp;
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
for (pp = np->properties; pp; pp = pp->next) {
if (of_prop_cmp(pp->name, prop_name) == 0) {
@@ -594,27 +595,35 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
EXPORT_SYMBOL(of_match_node);
/**
- * of_find_matching_node - Find a node based on an of_device_id match
- * table.
+ * of_find_matching_node_and_match - Find a node based on an of_device_id
+ * match table.
* @from: The node to start searching from or NULL, the node
* you pass will not be searched, only the next one
* will; typically, you pass what the previous call
* returned. of_node_put() will be called on it
* @matches: array of of device match structures to search in
+ * @match Updated to point at the matches entry which matched
*
* Returns a node pointer with refcount incremented, use
* of_node_put() on it when done.
*/
-struct device_node *of_find_matching_node(struct device_node *from,
- const struct of_device_id *matches)
+struct device_node *of_find_matching_node_and_match(struct device_node *from,
+ const struct of_device_id *matches,
+ const struct of_device_id **match)
{
struct device_node *np;
+ if (match)
+ *match = NULL;
+
read_lock(&devtree_lock);
- np = from ? from->allnext : allnodes;
+ np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
- if (of_match_node(matches, np) && of_node_get(np))
+ if (of_match_node(matches, np) && of_node_get(np)) {
+ if (match)
+ *match = matches;
break;
+ }
}
of_node_put(from);
read_unlock(&devtree_lock);
@@ -661,7 +670,7 @@ struct device_node *of_find_node_by_phandle(phandle handle)
struct device_node *np;
read_lock(&devtree_lock);
- for (np = allnodes; np; np = np->allnext)
+ for (np = of_allnodes; np; np = np->allnext)
if (np->phandle == handle)
break;
of_node_get(np);
@@ -671,12 +680,89 @@ struct device_node *of_find_node_by_phandle(phandle handle)
EXPORT_SYMBOL(of_find_node_by_phandle);
/**
+ * of_property_read_u8_array - Find and read an array of u8 from a property.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz: number of array elements to read
+ *
+ * Search for a property in a device node and read 8-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ * property = /bits/ 8 <0x50 0x60 0x70>;
+ *
+ * The out_value is modified only if a valid u8 value can be decoded.
+ */
+int of_property_read_u8_array(const struct device_node *np,
+ const char *propname, u8 *out_values, size_t sz)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ const u8 *val;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if ((sz * sizeof(*out_values)) > prop->length)
+ return -EOVERFLOW;
+
+ val = prop->value;
+ while (sz--)
+ *out_values++ = *val++;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u8_array);
+
+/**
+ * of_property_read_u16_array - Find and read an array of u16 from a property.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @out_value: pointer to return value, modified only if return value is 0.
+ * @sz: number of array elements to read
+ *
+ * Search for a property in a device node and read 16-bit value(s) from
+ * it. Returns 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * dts entry of array should be like:
+ * property = /bits/ 16 <0x5000 0x6000 0x7000>;
+ *
+ * The out_value is modified only if a valid u16 value can be decoded.
+ */
+int of_property_read_u16_array(const struct device_node *np,
+ const char *propname, u16 *out_values, size_t sz)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ const __be16 *val;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+ if ((sz * sizeof(*out_values)) > prop->length)
+ return -EOVERFLOW;
+
+ val = prop->value;
+ while (sz--)
+ *out_values++ = be16_to_cpup(val++);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u16_array);
+
+/**
* of_property_read_u32_array - Find and read an array of 32 bit integers
* from a property.
*
* @np: device node from which the property value is to be read.
* @propname: name of the property to be searched.
* @out_value: pointer to return value, modified only if return value is 0.
+ * @sz: number of array elements to read
*
* Search for a property in a device node and read 32-bit value(s) from
* it. Returns 0 on success, -EINVAL if the property does not exist,
@@ -893,8 +979,8 @@ EXPORT_SYMBOL_GPL(of_property_count_strings);
* Returns the device_node pointer with refcount incremented. Use
* of_node_put() on it when done.
*/
-struct device_node *
-of_parse_phandle(struct device_node *np, const char *phandle_name, int index)
+struct device_node *of_parse_phandle(const struct device_node *np,
+ const char *phandle_name, int index)
{
const __be32 *phandle;
int size;
@@ -939,7 +1025,7 @@ EXPORT_SYMBOL(of_parse_phandle);
* To get a device_node of the `node2' node you may call this:
* of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args);
*/
-int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
+int of_parse_phandle_with_args(const struct device_node *np, const char *list_name,
const char *cells_name, int index,
struct of_phandle_args *out_args)
{
@@ -1243,9 +1329,9 @@ int of_attach_node(struct device_node *np)
write_lock_irqsave(&devtree_lock, flags);
np->sibling = np->parent->child;
- np->allnext = allnodes;
+ np->allnext = of_allnodes;
np->parent->child = np;
- allnodes = np;
+ of_allnodes = np;
write_unlock_irqrestore(&devtree_lock, flags);
of_add_proc_dt_entry(np);
@@ -1303,11 +1389,11 @@ int of_detach_node(struct device_node *np)
return rc;
}
- if (allnodes == np)
- allnodes = np->allnext;
+ if (of_allnodes == np)
+ of_allnodes = np->allnext;
else {
struct device_node *prev;
- for (prev = allnodes;
+ for (prev = of_allnodes;
prev->allnext != np;
prev = prev->allnext)
;
diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c
index 91a375fb6ae6..808be06bb67e 100644
--- a/drivers/of/fdt.c
+++ b/drivers/of/fdt.c
@@ -186,6 +186,8 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
*/
fpsize = 1;
allocl = 2;
+ l = 1;
+ *pathp = '\0';
} else {
/* account for '/' and path size minus terminal 0
* already in 'l'
@@ -198,10 +200,10 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
np = unflatten_dt_alloc(&mem, sizeof(struct device_node) + allocl,
__alignof__(struct device_node));
if (allnextpp) {
+ char *fn;
memset(np, 0, sizeof(*np));
- np->full_name = ((char *)np) + sizeof(struct device_node);
+ np->full_name = fn = ((char *)np) + sizeof(*np);
if (new_format) {
- char *fn = np->full_name;
/* rebuild full path for new format */
if (dad && dad->parent) {
strcpy(fn, dad->full_name);
@@ -215,9 +217,9 @@ static unsigned long unflatten_dt_node(struct boot_param_header *blob,
fn += strlen(fn);
}
*(fn++) = '/';
- memcpy(fn, pathp, l);
- } else
- memcpy(np->full_name, pathp, l);
+ }
+ memcpy(fn, pathp, l);
+
prev_pp = &np->properties;
**allnextpp = np;
*allnextpp = &np->allnext;
@@ -459,7 +461,7 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
do {
u32 tag = be32_to_cpup((__be32 *)p);
- char *pathp;
+ const char *pathp;
p += 4;
if (tag == OF_DT_END_NODE) {
@@ -486,14 +488,8 @@ int __init of_scan_flat_dt(int (*it)(unsigned long node,
depth++;
pathp = (char *)p;
p = ALIGN(p + strlen(pathp) + 1, 4);
- if ((*pathp) == '/') {
- char *lp, *np;
- for (lp = NULL, np = pathp; *np; np++)
- if ((*np) == '/')
- lp = np+1;
- if (lp != NULL)
- pathp = lp;
- }
+ if (*pathp == '/')
+ pathp = kbasename(pathp);
rc = it(p, pathp, depth, data);
if (rc != 0)
break;
@@ -710,7 +706,7 @@ int __init early_init_dt_scan_chosen(unsigned long node, const char *uname,
*/
void __init unflatten_device_tree(void)
{
- __unflatten_device_tree(initial_boot_params, &allnodes,
+ __unflatten_device_tree(initial_boot_params, &of_allnodes,
early_init_dt_alloc_memory_arch);
/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c
index 3550f3bf4f92..b667264222cc 100644
--- a/drivers/of/of_i2c.c
+++ b/drivers/of/of_i2c.c
@@ -29,7 +29,7 @@ void of_i2c_register_devices(struct i2c_adapter *adap)
dev_dbg(&adap->dev, "of_i2c: walking child nodes\n");
- for_each_child_of_node(adap->dev.of_node, node) {
+ for_each_available_child_of_node(adap->dev.of_node, node) {
struct i2c_board_info info = {};
struct dev_archdata dev_ad = {};
const __be32 *addr;
diff --git a/drivers/of/of_mdio.c b/drivers/of/of_mdio.c
index 8e6c25f35040..83ca06f4312b 100644
--- a/drivers/of/of_mdio.c
+++ b/drivers/of/of_mdio.c
@@ -53,7 +53,7 @@ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np)
return rc;
/* Loop over the child nodes and register a phy_device for each one */
- for_each_child_of_node(np, child) {
+ for_each_available_child_of_node(np, child) {
const __be32 *paddr;
u32 addr;
int len;
diff --git a/drivers/of/pdt.c b/drivers/of/pdt.c
index 07cc1d678e4d..37b56fd716e6 100644
--- a/drivers/of/pdt.c
+++ b/drivers/of/pdt.c
@@ -241,15 +241,15 @@ void __init of_pdt_build_devicetree(phandle root_node, struct of_pdt_ops *ops)
BUG_ON(!ops);
of_pdt_prom_ops = ops;
- allnodes = of_pdt_create_node(root_node, NULL);
+ of_allnodes = of_pdt_create_node(root_node, NULL);
#if defined(CONFIG_SPARC)
- allnodes->path_component_name = "";
+ of_allnodes->path_component_name = "";
#endif
- allnodes->full_name = "/";
+ of_allnodes->full_name = "/";
- nextp = &allnodes->allnext;
- allnodes->child = of_pdt_build_tree(allnodes,
- of_pdt_prom_ops->getchild(allnodes->phandle), &nextp);
+ nextp = &of_allnodes->allnext;
+ of_allnodes->child = of_pdt_build_tree(of_allnodes,
+ of_pdt_prom_ops->getchild(of_allnodes->phandle), &nextp);
/* Get pointer to "/chosen" and "/aliasas" nodes for use everywhere */
of_alias_scan(kernel_tree_alloc);