mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
Core device tree changes for Linux v3.4
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. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.11 (GNU/Linux) iQIcBAABAgAGBQJPZ2KDAAoJEEFnBt12D9kBBSgP/1i4AcqErPl1Syuviai+ro0h gbQaV1qvCAHQz8YkzzGmEKUPiXGC5Qtqf/rbwIJMa+UwVgGMZaIn3HVS8lO+z5N/ SExkBAdMJPvUZQui5ZaCEtBCUSxF8cTFxXxBLQdaDGVNtli17fmhK+XeBbLAaY3H sZo0/GKzKIo7MdFnuRSRkHPP5SpX9QQEoXc//mWJAPIytX8oqGLwW0cT+8g6g11A 17IHM59Lr6hh6g9BMh3BCsulISPKqKDeHgVWgWu9Eq97EEvh9fSnTGQQMmhcCpwY diELtnbXVtM3h2ZCQSdXgiJ3BwiQn76mXqGwrNzXyPh1Tznq7l/GUZIC2bh6tpjG UJ3PyfDKcl2d6lVkPm5d2FdepW0CYeS4sNZCglbItjFHTpxwMftGqwl5H7L/7kYh MyKEYRlCyZbIqIm+OjgdMK/lN7yVJJdHgsjddZV940Stk4emjtBYC7YzBm2r/sk9 7I2RQ9TEyicnGAJ0QBd/DaZSMbsjSCHxiryX8JQd0BOGdFWn/kKO0Wfm0Xc0yCs1 /Y1ODio1r/frs30gazyTBWjrTErnOanD9ijvEzW/gJpaJZi1WNfFFhTwYQcgQ16A B5R088ry5tx0BDxsBN8/cL5EHmisNqFvYbDUMdC5IVmcVfc8OxijQkjpe1zNhpaS mCHQjbNfKfRSIq3XmpFV =kK/B -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
f8974cb713
@ -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"
|
||||
|
@ -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];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -25,6 +25,7 @@ config PPC_CHROMA
|
||||
bool "PowerEN PCIe Chroma Card"
|
||||
select EPAPR_BOOT
|
||||
select PPC_WSP
|
||||
select OF_DYNAMIC
|
||||
default y
|
||||
|
||||
endmenu
|
||||
|
@ -18,6 +18,8 @@
|
||||
#include <linux/string.h>
|
||||
#include <linux/kdev_t.h>
|
||||
#include <linux/notifier.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/genhd.h>
|
||||
#include <linux/kallsyms.h>
|
||||
#include <linux/mutex.h>
|
||||
@ -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);
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
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))
|
||||
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;
|
||||
|
||||
/* modalias is trickier, we add it in 2 steps */
|
||||
if ((!dev) || (!dev->of_node))
|
||||
return -ENODEV;
|
||||
|
||||
/* Devicetree modalias is tricky, we add it in 2 steps */
|
||||
if (add_uevent_var(env, "MODALIAS="))
|
||||
return -ENOMEM;
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
@ -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,
|
||||
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,
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user