Commit f8974cb7 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'dt-for-linus' of git://git.secretlab.ca/git/linux-2.6

Pull core device tree changes for Linux v3.4 from Grant Likely:
 "This branch contains a minor documentation addition, a utility
  function for parsing string properties needed by some of the new ARM
  platforms, disables dynamic DT code that isn't used anywhere but on a
  few PPC machines, and exports DT node compatible data to userspace via
  UEVENT properties.  Nothing earth shattering here."

* tag 'dt-for-linus' of git://git.secretlab.ca/git/linux-2.6:
  of: Only compile OF_DYNAMIC on PowerPC pseries and iseries
  arm/dts: OMAP3: Add omap3evm and am335xevm support
  drivercore: Output common devicetree information in uevent
  of: Add of_property_match_string() to find index into a string list
parents c207f3a4 0f22dd39
...@@ -41,3 +41,9 @@ Boards: ...@@ -41,3 +41,9 @@ Boards:
- OMAP4 PandaBoard : Low cost community board - OMAP4 PandaBoard : Low cost community board
compatible = "ti,omap4-panda", "ti,omap4430" 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"
...@@ -31,6 +31,8 @@ consumer-a { ...@@ -31,6 +31,8 @@ consumer-a {
phandle-list-bad-phandle = <12345678 0 0>; phandle-list-bad-phandle = <12345678 0 0>;
phandle-list-bad-args = <&provider2 1 0>, phandle-list-bad-args = <&provider2 1 0>,
<&provider3 0>; <&provider3 0>;
empty-property;
unterminated-string = [40 41 42 43];
}; };
}; };
}; };
......
...@@ -713,7 +713,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = { ...@@ -713,7 +713,7 @@ static struct dev_pm_ops ibmebus_bus_dev_pm_ops = {
struct bus_type ibmebus_bus_type = { struct bus_type ibmebus_bus_type = {
.name = "ibmebus", .name = "ibmebus",
.uevent = of_device_uevent, .uevent = of_device_uevent_modalias,
.bus_attrs = ibmebus_bus_attrs, .bus_attrs = ibmebus_bus_attrs,
.match = ibmebus_bus_bus_match, .match = ibmebus_bus_bus_match,
.probe = ibmebus_bus_device_probe, .probe = ibmebus_bus_device_probe,
......
...@@ -26,6 +26,7 @@ config MPC86XADS ...@@ -26,6 +26,7 @@ config MPC86XADS
config MPC885ADS config MPC885ADS
bool "MPC885ADS" bool "MPC885ADS"
select CPM1 select CPM1
select OF_DYNAMIC
help help
Freescale Semiconductor MPC885 Application Development System (ADS). Freescale Semiconductor MPC885 Application Development System (ADS).
Also known as DUET. Also known as DUET.
......
config PPC_ISERIES config PPC_ISERIES
bool "IBM Legacy iSeries" bool "IBM Legacy iSeries"
depends on PPC64 && PPC_BOOK3S depends on PPC64 && PPC_BOOK3S
select OF_DYNAMIC
select PPC_SMP_MUXED_IPI select PPC_SMP_MUXED_IPI
select PPC_INDIRECT_PIO select PPC_INDIRECT_PIO
select PPC_INDIRECT_MMIO select PPC_INDIRECT_MMIO
......
...@@ -3,6 +3,7 @@ config PPC_PSERIES ...@@ -3,6 +3,7 @@ config PPC_PSERIES
bool "IBM pSeries & new (POWER5-based) iSeries" bool "IBM pSeries & new (POWER5-based) iSeries"
select HAVE_PCSPKR_PLATFORM select HAVE_PCSPKR_PLATFORM
select MPIC select MPIC
select OF_DYNAMIC
select PCI_MSI select PCI_MSI
select PPC_XICS select PPC_XICS
select PPC_ICP_NATIVE select PPC_ICP_NATIVE
......
...@@ -25,6 +25,7 @@ config PPC_CHROMA ...@@ -25,6 +25,7 @@ config PPC_CHROMA
bool "PowerEN PCIe Chroma Card" bool "PowerEN PCIe Chroma Card"
select EPAPR_BOOT select EPAPR_BOOT
select PPC_WSP select PPC_WSP
select OF_DYNAMIC
default y default y
endmenu endmenu
......
...@@ -18,6 +18,8 @@ ...@@ -18,6 +18,8 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/kdev_t.h> #include <linux/kdev_t.h>
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/genhd.h> #include <linux/genhd.h>
#include <linux/kallsyms.h> #include <linux/kallsyms.h>
#include <linux/mutex.h> #include <linux/mutex.h>
...@@ -267,6 +269,9 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, ...@@ -267,6 +269,9 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj,
if (dev->driver) if (dev->driver)
add_uevent_var(env, "DRIVER=%s", dev->driver->name); 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 */ /* have the bus specific function add its stuff */
if (dev->bus && dev->bus->uevent) { if (dev->bus && dev->bus->uevent) {
retval = dev->bus->uevent(dev, env); retval = dev->bus->uevent(dev, env);
......
...@@ -621,7 +621,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env) ...@@ -621,7 +621,7 @@ static int platform_uevent(struct device *dev, struct kobj_uevent_env *env)
int rc; int rc;
/* Some devices have extra OF data and an OF-style MODALIAS */ /* 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) if (rc != -ENODEV)
return rc; return rc;
......
...@@ -137,7 +137,7 @@ extern struct device_attribute macio_dev_attrs[]; ...@@ -137,7 +137,7 @@ extern struct device_attribute macio_dev_attrs[];
struct bus_type macio_bus_type = { struct bus_type macio_bus_type = {
.name = "macio", .name = "macio",
.match = macio_bus_match, .match = macio_bus_match,
.uevent = of_device_uevent, .uevent = of_device_uevent_modalias,
.probe = macio_device_probe, .probe = macio_device_probe,
.remove = macio_device_remove, .remove = macio_device_remove,
.shutdown = macio_device_shutdown, .shutdown = macio_device_shutdown,
......
...@@ -35,9 +35,10 @@ config OF_EARLY_FLATTREE ...@@ -35,9 +35,10 @@ config OF_EARLY_FLATTREE
config OF_PROMTREE config OF_PROMTREE
bool bool
# Hardly any platforms need this. It is safe to select, but only do so if you
# need it.
config OF_DYNAMIC config OF_DYNAMIC
def_bool y bool
depends on PPC_OF
config OF_ADDRESS config OF_ADDRESS
def_bool y def_bool y
......
...@@ -88,7 +88,7 @@ int of_n_size_cells(struct device_node *np) ...@@ -88,7 +88,7 @@ int of_n_size_cells(struct device_node *np)
} }
EXPORT_SYMBOL(of_n_size_cells); 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 * of_node_get - Increment refcount of a node
* @node: Node to inc refcount, NULL is supported to * @node: Node to inc refcount, NULL is supported to
...@@ -161,7 +161,7 @@ void of_node_put(struct device_node *node) ...@@ -161,7 +161,7 @@ void of_node_put(struct device_node *node)
kref_put(&node->kref, of_node_release); kref_put(&node->kref, of_node_release);
} }
EXPORT_SYMBOL(of_node_put); EXPORT_SYMBOL(of_node_put);
#endif /* !CONFIG_SPARC */ #endif /* CONFIG_OF_DYNAMIC */
struct property *of_find_property(const struct device_node *np, struct property *of_find_property(const struct device_node *np,
const char *name, const char *name,
...@@ -761,6 +761,42 @@ int of_property_read_string_index(struct device_node *np, const char *propname, ...@@ -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); 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 * of_property_count_strings - Find and return the number of strings from a
......
...@@ -128,39 +128,41 @@ ssize_t of_device_get_modalias(struct device *dev, char *str, ssize_t len) ...@@ -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 * 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; const char *compat;
int seen = 0, cplen, sl; int seen = 0, cplen, sl;
if ((!dev) || (!dev->of_node)) if ((!dev) || (!dev->of_node))
return -ENODEV; return;
if (add_uevent_var(env, "OF_NAME=%s", dev->of_node->name))
return -ENOMEM;
if (add_uevent_var(env, "OF_TYPE=%s", dev->of_node->type)) add_uevent_var(env, "OF_NAME=%s", dev->of_node->name);
return -ENOMEM; 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 /* Since the compatible field can contain pretty much anything
* it's not really legal to split it out with commas. We split it * it's not really legal to split it out with commas. We split it
* up using a number of environment variables instead. */ * up using a number of environment variables instead. */
compat = of_get_property(dev->of_node, "compatible", &cplen); compat = of_get_property(dev->of_node, "compatible", &cplen);
while (compat && *compat && cplen > 0) { while (compat && *compat && cplen > 0) {
if (add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat)) add_uevent_var(env, "OF_COMPATIBLE_%d=%s", seen, compat);
return -ENOMEM;
sl = strlen(compat) + 1; sl = strlen(compat) + 1;
compat += sl; compat += sl;
cplen -= sl; cplen -= sl;
seen++; seen++;
} }
add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen);
}
if (add_uevent_var(env, "OF_COMPATIBLE_N=%d", seen)) int of_device_uevent_modalias(struct device *dev, struct kobj_uevent_env *env)
return -ENOMEM; {
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=")) if (add_uevent_var(env, "MODALIAS="))
return -ENOMEM; return -ENOMEM;
......
...@@ -120,6 +120,34 @@ static void __init of_selftest_parse_phandle_with_args(void) ...@@ -120,6 +120,34 @@ static void __init of_selftest_parse_phandle_with_args(void)
pr_info("end - %s\n", passed_all ? "PASS" : "FAIL"); 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) static int __init of_selftest(void)
{ {
struct device_node *np; struct device_node *np;
...@@ -133,6 +161,7 @@ static int __init of_selftest(void) ...@@ -133,6 +161,7 @@ static int __init of_selftest(void)
pr_info("start of selftest - you will see error messages\n"); pr_info("start of selftest - you will see error messages\n");
of_selftest_parse_phandle_with_args(); of_selftest_parse_phandle_with_args();
of_selftest_property_match_string();
pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL"); pr_info("end of selftest - %s\n", selftest_passed ? "PASS" : "FAIL");
return 0; return 0;
} }
......
...@@ -72,19 +72,17 @@ struct of_phandle_args { ...@@ -72,19 +72,17 @@ struct of_phandle_args {
uint32_t args[MAX_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 */ /* Dummy ref counting routines - to be implemented later */
static inline struct device_node *of_node_get(struct device_node *node) static inline struct device_node *of_node_get(struct device_node *node)
{ {
return node; return node;
} }
static inline void of_node_put(struct device_node *node) static inline void of_node_put(struct device_node *node) { }
{ #endif /* !CONFIG_OF_DYNAMIC */
}
#else
extern struct device_node *of_node_get(struct device_node *node);
extern void of_node_put(struct device_node *node);
#endif
#ifdef CONFIG_OF #ifdef CONFIG_OF
...@@ -217,6 +215,9 @@ extern int of_property_read_string(struct device_node *np, ...@@ -217,6 +215,9 @@ extern int of_property_read_string(struct device_node *np,
extern int of_property_read_string_index(struct device_node *np, extern int of_property_read_string_index(struct device_node *np,
const char *propname, const char *propname,
int index, const char **output); 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, extern int of_property_count_strings(struct device_node *np,
const char *propname); const char *propname);
extern int of_device_is_compatible(const struct device_node *device, extern int of_device_is_compatible(const struct device_node *device,
......
...@@ -34,7 +34,8 @@ extern void of_device_unregister(struct platform_device *ofdev); ...@@ -34,7 +34,8 @@ extern void of_device_unregister(struct platform_device *ofdev);
extern ssize_t of_device_get_modalias(struct device *dev, extern ssize_t of_device_get_modalias(struct device *dev,
char *str, ssize_t len); 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) static inline void of_device_node_put(struct device *dev)
{ {
...@@ -49,7 +50,10 @@ static inline int of_driver_match_device(struct device *dev, ...@@ -49,7 +50,10 @@ static inline int of_driver_match_device(struct device *dev,
return 0; 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) struct kobj_uevent_env *env)
{ {
return -ENODEV; return -ENODEV;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment