summaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/Kconfig5
-rw-r--r--drivers/of/base.c40
-rw-r--r--drivers/of/device.c30
-rw-r--r--drivers/of/selftest.c29
4 files changed, 86 insertions, 18 deletions
diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig
index fa666a93540..8e84ce9765a 100644
--- a/drivers/of/Kconfig
+++ b/drivers/of/Kconfig
@@ -35,9 +35,10 @@ config OF_EARLY_FLATTREE
config OF_PROMTREE
bool
+# Hardly any platforms need this. It is safe to select, but only do so if you
+# need it.
config OF_DYNAMIC
- def_bool y
- depends on PPC_OF
+ bool
config OF_ADDRESS
def_bool y
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 133908a6fd8..58064498694 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -88,7 +88,7 @@ int of_n_size_cells(struct device_node *np)
}
EXPORT_SYMBOL(of_n_size_cells);
-#if !defined(CONFIG_SPARC) /* SPARC doesn't do ref counting (yet) */
+#if defined(CONFIG_OF_DYNAMIC)
/**
* of_node_get - Increment refcount of a node
* @node: Node to inc refcount, NULL is supported to
@@ -161,7 +161,7 @@ void of_node_put(struct device_node *node)
kref_put(&node->kref, of_node_release);
}
EXPORT_SYMBOL(of_node_put);
-#endif /* !CONFIG_SPARC */
+#endif /* CONFIG_OF_DYNAMIC */
struct property *of_find_property(const struct device_node *np,
const char *name,
@@ -761,6 +761,42 @@ int of_property_read_string_index(struct device_node *np, const char *propname,
}
EXPORT_SYMBOL_GPL(of_property_read_string_index);
+/**
+ * of_property_match_string() - Find string in a list and return index
+ * @np: pointer to node containing string list property
+ * @propname: string list property name
+ * @string: pointer to string to search for in string list
+ *
+ * This function searches a string list property and returns the index
+ * of a specific string value.
+ */
+int of_property_match_string(struct device_node *np, const char *propname,
+ const char *string)
+{
+ struct property *prop = of_find_property(np, propname, NULL);
+ size_t l;
+ int i;
+ const char *p, *end;
+
+ if (!prop)
+ return -EINVAL;
+ if (!prop->value)
+ return -ENODATA;
+
+ p = prop->value;
+ end = p + prop->length;
+
+ for (i = 0; p < end; i++, p += l) {
+ l = strlen(p) + 1;
+ if (p + l > end)
+ return -EILSEQ;
+ pr_debug("comparing %s with %s\n", string, p);
+ if (strcmp(string, p) == 0)
+ return i; /* Found it; return index */
+ }
+ return -ENODATA;
+}
+EXPORT_SYMBOL_GPL(of_property_match_string);
/**
* of_property_count_strings - Find and return the number of strings from a
diff --git a/drivers/of/device.c b/drivers/of/device.c
index 62b4b32ac88..4c74e4fc5a5 100644
--- a/drivers/of/device.c
+++ b/drivers/of/device.c
@@ -128,39 +128,41 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len)
/**
* of_device_uevent - Display OF related uevent information
*/
-int of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
+void of_device_uevent(struct device *dev, struct kobj_uevent_env *env)
{
const char *compat;
int seen = 0, cplen, sl;
if ((!dev) || (!dev->of_node))
- return -ENODEV;
-
- if (add_uevent_var(env, "OF_NAME=%s", dev->of_node->name))
- return -ENOMEM;
+ return;
- if (add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type))
- return -ENOMEM;
+ add_uevent_var(env, "OF_NAME=%s", dev->of_node->name);
+ add_uevent_var(env, "OF_FULLNAME=%s", dev->of_node->full_name);
+ if (dev->of_node->type && strcmp("<NULL>", dev->of_node->type) != 0)
+ add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type);
/* Since the compatible field can contain pretty much anything
* it's not really legal to split it out with commas. We split it
* up using a number of environment variables instead. */
-
compat = of_get_property(dev->of_node, "compatible", &cplen);
while (compat && *compat && cplen > 0) {
- if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat))
- return -ENOMEM;
-
+ add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
sl = strlen(compat) + 1;
compat += sl;
cplen -= sl;
seen++;
}
+ add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
+}
- if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen))
- return -ENOMEM;
+int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
+{
+ int sl;
+
+ if ((!dev) || (!dev->of_node))
+ return -ENODEV;
- /* modalias is trickier, we add it in 2 steps */
+ /* Devicetree modalias is tricky, we add it in 2 steps */
if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM;
diff --git a/drivers/of/selftest.c b/drivers/of/selftest.c
index 9d2b4803a9d..f24ffd7088d 100644
--- a/drivers/of/selftest.c
+++ b/drivers/of/selftest.c
@@ -120,6 +120,34 @@ static void __init of_selftest_parse_phandle_with_args(void)
pr_info("end - %s\n", passed_all ? "PASS" : "FAIL");
}
+static void __init of_selftest_property_match_string(void)
+{
+ struct device_node *np;
+ int rc;
+
+ pr_info("start\n");
+ np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-a");
+ if (!np) {
+ pr_err("No testcase data in device tree\n");
+ return;
+ }
+
+ rc = of_property_match_string(np, "phandle-list-names", "first");
+ selftest(rc == 0, "first expected:0 got:%i\n", rc);
+ rc = of_property_match_string(np, "phandle-list-names", "second");
+ selftest(rc == 1, "second expected:0 got:%i\n", rc);
+ rc = of_property_match_string(np, "phandle-list-names", "third");
+ selftest(rc == 2, "third expected:0 got:%i\n", rc);
+ rc = of_property_match_string(np, "phandle-list-names", "fourth");
+ selftest(rc == -ENODATA, "unmatched string; rc=%i", rc);
+ rc = of_property_match_string(np, "missing-property", "blah");
+ selftest(rc == -EINVAL, "missing property; rc=%i", rc);
+ rc = of_property_match_string(np, "empty-property", "blah");
+ selftest(rc == -ENODATA, "empty property; rc=%i", rc);
+ rc = of_property_match_string(np, "unterminated-string", "blah");
+ selftest(rc == -EILSEQ, "unterminated string; rc=%i", rc);
+}
+
static int __init of_selftest(void)
{
struct device_node *np;
@@ -133,6 +161,7 @@ static int __init of_selftest(void)
pr_info("start of selftest - you will see error messages\n");
of_selftest_parse_phandle_with_args();
+ of_selftest_property_match_string();
pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
return 0;
}