From 7aff0fe33033fc75b61446ba29d38b1b1354af9f Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Mon, 12 Dec 2011 09:25:58 -0700 Subject: of: Add of_property_match_string() to find index into a string list Add a helper function for finding the index of a string in a string list property. This helper is useful for bindings that use a separate *-name property for attaching names to tuples in another property such as 'reg' or 'gpios'. Signed-off-by: Grant Likely diff --git a/arch/arm/boot/dts/testcases/tests-phandle.dtsi b/arch/arm/boot/dts/testcases/tests-phandle.dtsi index ec0c4e6..0007d3c 100644 --- a/arch/arm/boot/dts/testcases/tests-phandle.dtsi +++ b/arch/arm/boot/dts/testcases/tests-phandle.dtsi @@ -31,6 +31,8 @@ phandle-list-bad-phandle = <12345678 0 0>; phandle-list-bad-args = <&provider2 1 0>, <&provider3 0>; + empty-property; + unterminated-string = [40 41 42 43]; }; }; }; diff --git a/drivers/of/base.c b/drivers/of/base.c index 133908a..13ba728 100644 --- a/drivers/of/base.c +++ b/drivers/of/base.c @@ -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/selftest.c b/drivers/of/selftest.c index 9d2b480..f24ffd7 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; } diff --git a/include/linux/of.h b/include/linux/of.h index a75a831..5a4a3ad 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -217,6 +217,9 @@ extern int of_property_read_string(struct device_node *np, extern int of_property_read_string_index(struct device_node *np, const char *propname, int index, const char **output); +extern int of_property_match_string(struct device_node *np, + const char *propname, + const char *string); extern int of_property_count_strings(struct device_node *np, const char *propname); extern int of_device_is_compatible(const struct device_node *device, -- cgit v0.10.2 From 07d57a32fb6eb2da017796e038682f817a4f685e Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 1 Feb 2012 11:22:22 -0700 Subject: drivercore: Output common devicetree information in uevent When userspace needs to find a specific device, it currently isn't easy to resolve a /sys/devices/ path from a specific device tree node. Nor is it easy to obtain the compatible list for devices. This patch generalizes the code that inserts OF_* values into the uevent device attribute so that any device that is attached to an OF node will have that information exported to userspace. Without this patch only platform devices and some powerpc-specific busses have access to this data. The original function also creates a MODALIAS property for the compatible list, but that code has not been generalized into the common case because it has the potential to break module loading on a lot of bus types. Bus types are still responsible for their own MODALIAS properties. Boot tested on ARM and compile tested on PowerPC and SPARC. Signed-off-by: Grant Likely Acked-by: Greg Kroah-Hartman Cc: Tobias Klauser Cc: Frederic Lambert Cc: Rob Herring Cc: Mark Brown Cc: "David S. Miller" Cc: Benjamin Herrenschmidt diff --git a/arch/powerpc/kernel/ibmebus.c b/arch/powerpc/kernel/ibmebus.c index d39ae60..79bb282 100644 --- a/arch/powerpc/kernel/ibmebus.c +++ b/arch/powerpc/kernel/ibmebus.c @@ -713,7 +713,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = { struct bus_type ibmebus_bus_type = { .name = "ibmebus", - .uevent = of_device_uevent, + .uevent = of_device_uevent_modalias, .bus_attrs = ibmebus_bus_attrs, .match = ibmebus_bus_bus_match, .probe = ibmebus_bus_device_probe, diff --git a/drivers/base/core.c b/drivers/base/core.c index 4a67cc0..28d8c21 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -18,6 +18,8 @@ #include #include #include +#include +#include #include #include #include @@ -267,6 +269,9 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, if (dev->driver) add_uevent_var(env, "DRIVER=%s", dev->driver->name); + /* Add common DT information about the device */ + of_device_uevent(dev, env); + /* have the bus specific function add its stuff */ if (dev->bus && dev->bus->uevent) { retval = dev->bus->uevent(dev, env); diff --git a/drivers/base/platform.c b/drivers/base/platform.c index f0c605e..a1a7225 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -621,7 +621,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) int rc; /* Some devices have extra OF data and an OF-style MODALIAS */ - rc = of_device_uevent(dev,env); + rc = of_device_uevent_modalias(dev,env); if (rc != -ENODEV) return rc; diff --git a/drivers/macintosh/macio_asic.c b/drivers/macintosh/macio_asic.c index 4daf9e5..20e5c2c 100644 --- a/drivers/macintosh/macio_asic.c +++ b/drivers/macintosh/macio_asic.c @@ -137,7 +137,7 @@ extern struct device_attribute macio_dev_attrs[]; struct bus_type macio_bus_type = { .name = "macio", .match = macio_bus_match, - .uevent = of_device_uevent, + .uevent = of_device_uevent_modalias, .probe = macio_device_probe, .remove = macio_device_remove, .shutdown = macio_device_shutdown, diff --git a/drivers/of/device.c b/drivers/of/device.c index 62b4b32..4c74e4f 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("", 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/include/linux/of_device.h b/include/linux/of_device.h index ae56384..cbc4214 100644 --- a/include/linux/of_device.h +++ b/include/linux/of_device.h @@ -34,7 +34,8 @@ extern void of_device_unregister(struct platform_device *ofdev); extern ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len); -extern int of_device_uevent(struct device *dev, struct kobj_uevent_env *env); +extern void of_device_uevent(struct device *dev, struct kobj_uevent_env *env); +extern int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env); static inline void of_device_node_put(struct device *dev) { @@ -49,7 +50,10 @@ static inline int of_driver_match_device(struct device *dev, return 0; } -static inline int of_device_uevent(struct device *dev, +static inline void of_device_uevent(struct device *dev, + struct kobj_uevent_env *env) { } + +static inline int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env) { return -ENODEV; -- cgit v0.10.2 From 5411972995b27a9074062b6d8e106fc15bd1cd44 Mon Sep 17 00:00:00 2001 From: Vaibhav Hiremath Date: Wed, 1 Feb 2012 11:57:00 +0530 Subject: arm/dts: OMAP3: Add omap3evm and am335xevm support TI's OMAP3EVM and AM335xEVM are software development boards available for OMAP35x(AM/DM37x) and AM335x devices respectively; and these devices are considered under omap3 family. Signed-off-by: Vaibhav Hiremath Cc: Benoit Cousson Cc: Grant Likely Cc: Tony Lindgren Signed-off-by: Grant Likely diff --git a/Documentation/devicetree/bindings/arm/omap/omap.txt b/Documentation/devicetree/bindings/arm/omap/omap.txt index dbdab40..ce78498 100644 --- a/Documentation/devicetree/bindings/arm/omap/omap.txt +++ b/Documentation/devicetree/bindings/arm/omap/omap.txt @@ -41,3 +41,9 @@ Boards: - OMAP4 PandaBoard : Low cost community board compatible = "ti,omap4-panda", "ti,omap4430" + +- OMAP3 EVM : Software Developement Board for OMAP35x, AM/DM37x + compatible = "ti,omap3-evm", "ti,omap3" + +- AM335X EVM : Software Developement Board for AM335x + compatible = "ti,am335x-evm", "ti,am33xx", "ti,omap3" -- cgit v0.10.2 From 0f22dd395fc473cee252b9af50249b8e0f32fde7 Mon Sep 17 00:00:00 2001 From: Grant Likely Date: Wed, 15 Feb 2012 20:38:40 -0700 Subject: of: Only compile OF_DYNAMIC on PowerPC pseries and iseries Only two architectures use the OF node reference counting and reclaim bits. There is no need to compile it for the rest of the PowerPC platforms or for any of the other architectures. This patch makes iseries and pseries select CONFIG_OF_DYNAMIC, and makes it default to off for everything else. It is still safe to turn on CONFIG_OF_DYNAMIC on all architectures, it just isn't necessary. v2: Also select OF_DYNAMIC for PPC_CHROMA and MPC885ADS as reported by Michael Meuling Signed-off-by: Grant Likely Acked-by: David S. Miller Acked-by: Benjamin Herrenschmidt Acked-by: Jimi Xenidis (for PPC_CHROMA bug fix) Cc: Rob Herring diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index ee56a9e..1fb0b3c 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig @@ -26,6 +26,7 @@ config MPC86XADS config MPC885ADS bool "MPC885ADS" select CPM1 + select OF_DYNAMIC help Freescale Semiconductor MPC885 Application Development System (ADS). Also known as DUET. diff --git a/arch/powerpc/platforms/iseries/Kconfig b/arch/powerpc/platforms/iseries/Kconfig index b57cda3..63835e0 100644 --- a/arch/powerpc/platforms/iseries/Kconfig +++ b/arch/powerpc/platforms/iseries/Kconfig @@ -1,6 +1,7 @@ config PPC_ISERIES bool "IBM Legacy iSeries" depends on PPC64 && PPC_BOOK3S + select OF_DYNAMIC select PPC_SMP_MUXED_IPI select PPC_INDIRECT_PIO select PPC_INDIRECT_MMIO diff --git a/arch/powerpc/platforms/pseries/Kconfig b/arch/powerpc/platforms/pseries/Kconfig index ae7b6d4..1114f8f 100644 --- a/arch/powerpc/platforms/pseries/Kconfig +++ b/arch/powerpc/platforms/pseries/Kconfig @@ -3,6 +3,7 @@ config PPC_PSERIES bool "IBM pSeries & new (POWER5-based) iSeries" select HAVE_PCSPKR_PLATFORM select MPIC + select OF_DYNAMIC select PCI_MSI select PPC_XICS select PPC_ICP_NATIVE diff --git a/arch/powerpc/platforms/wsp/Kconfig b/arch/powerpc/platforms/wsp/Kconfig index 57d22a2..79d2225 100644 --- a/arch/powerpc/platforms/wsp/Kconfig +++ b/arch/powerpc/platforms/wsp/Kconfig @@ -25,6 +25,7 @@ config PPC_CHROMA bool "PowerEN PCIe Chroma Card" select EPAPR_BOOT select PPC_WSP + select OF_DYNAMIC default y endmenu diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig index 268163d..6ea51dc 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 13ba728..5806449 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, diff --git a/include/linux/of.h b/include/linux/of.h index 5a4a3ad..533603e 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -72,19 +72,17 @@ struct of_phandle_args { uint32_t args[MAX_PHANDLE_ARGS]; }; -#if defined(CONFIG_SPARC) || !defined(CONFIG_OF) +#ifdef CONFIG_OF_DYNAMIC +extern struct device_node *of_node_get(struct device_node *node); +extern void of_node_put(struct device_node *node); +#else /* CONFIG_OF_DYNAMIC */ /* Dummy ref counting routines - to be implemented later */ static inline struct device_node *of_node_get(struct device_node *node) { return node; } -static inline void of_node_put(struct device_node *node) -{ -} -#else -extern struct device_node *of_node_get(struct device_node *node); -extern void of_node_put(struct device_node *node); -#endif +static inline void of_node_put(struct device_node *node) { } +#endif /* !CONFIG_OF_DYNAMIC */ #ifdef CONFIG_OF -- cgit v0.10.2