summaryrefslogtreecommitdiffstats
path: root/drivers/of/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r--drivers/of/base.c77
1 files changed, 62 insertions, 15 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index c39da558d1..dcb5ccd018 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -149,6 +149,31 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np,
ap->alias, ap->stem, ap->id, np->full_name);
}
+static struct device_node *of_alias_resolve(struct device_node *root, struct property *pp)
+{
+ /* Skip those we do not want to proceed */
+ if (!of_prop_cmp(pp->name, "name") ||
+ !of_prop_cmp(pp->name, "phandle") ||
+ !of_prop_cmp(pp->name, "linux,phandle"))
+ return NULL;
+
+ return of_find_node_by_path_from(root, of_property_get_value(pp));
+}
+
+static int of_alias_id_parse(const char *start, int *len)
+{
+ const char *end = start + strlen(start);
+
+ /* walk the alias backwards to extract the id and work out
+ * the 'stem' string */
+ while (isdigit(*(end-1)) && end > start)
+ end--;
+
+ *len = end - start;
+
+ return simple_strtol(end, NULL, 10);
+}
+
/**
* of_alias_scan - Scan all properties of 'aliases' node
*
@@ -175,28 +200,15 @@ void of_alias_scan(void)
list_for_each_entry(pp, &of_aliases->properties, list) {
const char *start = pp->name;
- const char *end = start + strlen(start);
struct device_node *np;
struct alias_prop *ap;
int id, len;
- /* Skip those we do not want to proceed */
- if (!of_prop_cmp(pp->name, "name") ||
- !of_prop_cmp(pp->name, "phandle") ||
- !of_prop_cmp(pp->name, "linux,phandle"))
- continue;
-
- np = of_find_node_by_path(of_property_get_value(pp));
+ np = of_alias_resolve(root_node, pp);
if (!np)
continue;
- /* walk the alias backwards to extract the id and work out
- * the 'stem' string */
- while (isdigit(*(end-1)) && end > start)
- end--;
- len = end - start;
-
- id = simple_strtol(end, NULL, 10);
+ id = of_alias_id_parse(start, &len);
if (id < 0)
continue;
@@ -235,6 +247,41 @@ int of_alias_get_id(struct device_node *np, const char *stem)
}
EXPORT_SYMBOL_GPL(of_alias_get_id);
+int of_alias_get_id_from(struct device_node *root, struct device_node *np,
+ const char *stem)
+{
+ struct device_node *aliasnp, *entrynp;
+ struct property *pp;
+
+ if (!root)
+ return of_alias_get_id(np, stem);
+
+ aliasnp = of_find_node_by_path_from(root, "/aliases");
+ if (!aliasnp)
+ return -ENODEV;
+
+ for_each_property_of_node(aliasnp, pp) {
+ const char *start = pp->name;
+ int id, len;
+
+ entrynp = of_alias_resolve(root_node, pp);
+ if (entrynp != np)
+ continue;
+
+ id = of_alias_id_parse(start, &len);
+ if (id < 0)
+ continue;
+
+ if (strncasecmp(start, stem, len))
+ continue;
+
+ return id;
+ }
+
+ return -ENODEV;
+}
+EXPORT_SYMBOL_GPL(of_alias_get_id_from);
+
const char *of_alias_get(struct device_node *np)
{
struct alias_prop *app;