diff options
author | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 18:18:08 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-07-20 18:18:08 +0200 |
commit | 2cb7e714229681408e323852bed939989faf6991 (patch) | |
tree | 552b78fa5830a0337594f9fbab5f1dc0306e93cd | |
parent | Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/dto... (diff) | |
parent | Create drivers/of/platform.c (diff) | |
download | linux-2cb7e714229681408e323852bed939989faf6991.tar.xz linux-2cb7e714229681408e323852bed939989faf6991.zip |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfr/ofcons
* 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/sfr/ofcons:
Create drivers/of/platform.c
Create linux/of_platorm.h
[SPARC/64] Rename some functions like PowerPC
Begin consolidation of of_device.h
Begin to consolidate of_device.c
Consolidate of_find_node_by routines
Consolidate of_get_next_child
Consolidate of_get_parent
Consolidate of_find_property
Consolidate of_device_is_compatible
Start split out of common open firmware code
Split out common parts of prom.h
33 files changed, 846 insertions, 1483 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index d860b640a140..853c282da22e 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig @@ -92,6 +92,9 @@ config ARCH_MAY_HAVE_PC_FDC config PPC_OF def_bool y +config OF + def_bool y + config PPC_UDBG_16550 bool default n diff --git a/arch/powerpc/kernel/of_device.c b/arch/powerpc/kernel/of_device.c index a464d67248df..89b911e83c04 100644 --- a/arch/powerpc/kernel/of_device.c +++ b/arch/powerpc/kernel/of_device.c @@ -1,5 +1,6 @@ #include <linux/string.h> #include <linux/kernel.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> @@ -8,118 +9,6 @@ #include <asm/errno.h> #include <asm/of_device.h> -/** - * of_match_node - Tell if an device_node has a matching of_match structure - * @ids: array of of device match structures to search in - * @node: the of device structure to match against - * - * Low level utility function used by device matching. - */ -const struct of_device_id *of_match_node(const struct of_device_id *matches, - const struct device_node *node) -{ - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= node->name - && !strcmp(matches->name, node->name); - if (matches->type[0]) - match &= node->type - && !strcmp(matches->type, node->type); - if (matches->compatible[0]) - match &= of_device_is_compatible(node, - matches->compatible); - if (match) - return matches; - matches++; - } - return NULL; -} - -/** - * of_match_device - Tell if an of_device structure has a matching - * of_match structure - * @ids: array of of device match structures to search in - * @dev: the of device structure to match against - * - * Used by a driver to check whether an of_device present in the - * system is in its list of supported devices. - */ -const struct of_device_id *of_match_device(const struct of_device_id *matches, - const struct of_device *dev) -{ - if (!dev->node) - return NULL; - return of_match_node(matches, dev->node); -} - -struct of_device *of_dev_get(struct of_device *dev) -{ - struct device *tmp; - - if (!dev) - return NULL; - tmp = get_device(&dev->dev); - if (tmp) - return to_of_device(tmp); - else - return NULL; -} - -void of_dev_put(struct of_device *dev) -{ - if (dev) - put_device(&dev->dev); -} - -static ssize_t dev_show_devspec(struct device *dev, - struct device_attribute *attr, char *buf) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - return sprintf(buf, "%s", ofdev->node->full_name); -} - -static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); - -/** - * of_release_dev - free an of device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this of device are - * done. - */ -void of_release_dev(struct device *dev) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - of_node_put(ofdev->node); - kfree(ofdev); -} - -int of_device_register(struct of_device *ofdev) -{ - int rc; - - BUG_ON(ofdev->node == NULL); - - rc = device_register(&ofdev->dev); - if (rc) - return rc; - - return device_create_file(&ofdev->dev, &dev_attr_devspec); -} - -void of_device_unregister(struct of_device *ofdev) -{ - device_remove_file(&ofdev->dev, &dev_attr_devspec); - - device_unregister(&ofdev->dev); -} - - ssize_t of_device_get_modalias(struct of_device *ofdev, char *str, ssize_t len) { @@ -229,14 +118,5 @@ int of_device_uevent(struct device *dev, return 0; } - - -EXPORT_SYMBOL(of_match_node); -EXPORT_SYMBOL(of_match_device); -EXPORT_SYMBOL(of_device_register); -EXPORT_SYMBOL(of_device_unregister); -EXPORT_SYMBOL(of_dev_get); -EXPORT_SYMBOL(of_dev_put); -EXPORT_SYMBOL(of_release_dev); EXPORT_SYMBOL(of_device_uevent); EXPORT_SYMBOL(of_device_get_modalias); diff --git a/arch/powerpc/kernel/of_platform.c b/arch/powerpc/kernel/of_platform.c index 8ded4e7dc87e..f70e787d556f 100644 --- a/arch/powerpc/kernel/of_platform.c +++ b/arch/powerpc/kernel/of_platform.c @@ -55,94 +55,14 @@ static struct of_device_id of_default_bus_ids[] = { static atomic_t bus_no_reg_magic; -/* - * - * OF platform device type definition & base infrastructure - * - */ - -static int of_platform_bus_match(struct device *dev, struct device_driver *drv) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * of_drv = to_of_platform_driver(drv); - const struct of_device_id * matches = of_drv->match_table; - - if (!matches) - return 0; - - return of_match_device(matches, of_dev) != NULL; -} - -static int of_platform_device_probe(struct device *dev) -{ - int error = -ENODEV; - struct of_platform_driver *drv; - struct of_device *of_dev; - const struct of_device_id *match; - - drv = to_of_platform_driver(dev->driver); - of_dev = to_of_device(dev); - - if (!drv->probe) - return error; - - of_dev_get(of_dev); - - match = of_match_device(drv->match_table, of_dev); - if (match) - error = drv->probe(of_dev, match); - if (error) - of_dev_put(of_dev); - - return error; -} - -static int of_platform_device_remove(struct device *dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - - if (dev->driver && drv->remove) - drv->remove(of_dev); - return 0; -} - -static int of_platform_device_suspend(struct device *dev, pm_message_t state) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; -} - -static int of_platform_device_resume(struct device * dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; -} - struct bus_type of_platform_bus_type = { - .name = "of_platform", - .match = of_platform_bus_match, .uevent = of_device_uevent, - .probe = of_platform_device_probe, - .remove = of_platform_device_remove, - .suspend = of_platform_device_suspend, - .resume = of_platform_device_resume, }; EXPORT_SYMBOL(of_platform_bus_type); static int __init of_bus_driver_init(void) { - return bus_register(&of_platform_bus_type); + return of_bus_type_init(&of_platform_bus_type, "of_platform"); } postcore_initcall(of_bus_driver_init); diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c index 37ff99bd98b4..bdcd23d8d8b9 100644 --- a/arch/powerpc/kernel/prom.c +++ b/arch/powerpc/kernel/prom.c @@ -78,12 +78,9 @@ static struct boot_param_header *initial_boot_params __initdata; struct boot_param_header *initial_boot_params; #endif -static struct device_node *allnodes = NULL; +extern struct device_node *allnodes; /* temporary while merging */ -/* use when traversing tree through the allnext, child, sibling, - * or parent members of struct device_node. - */ -static DEFINE_RWLOCK(devtree_lock); +extern rwlock_t devtree_lock; /* temporary while merging */ /* export that to outside world */ struct device_node *of_chosen; @@ -1056,60 +1053,6 @@ void __init early_init_devtree(void *params) DBG(" <- early_init_devtree()\n"); } -int of_n_addr_cells(struct device_node* np) -{ - const int *ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#address-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #address-cells property for the root node, default to 1 */ - return 1; -} -EXPORT_SYMBOL(of_n_addr_cells); - -int of_n_size_cells(struct device_node* np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#size-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #size-cells property for the root node, default to 1 */ - return 1; -} -EXPORT_SYMBOL(of_n_size_cells); - -/** Checks if the given "compat" string matches one of the strings in - * the device's "compatible" property - */ -int of_device_is_compatible(const struct device_node *device, - const char *compat) -{ - const char* cp; - int cplen, l; - - cp = of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncasecmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} -EXPORT_SYMBOL(of_device_is_compatible); - /** * Indicates whether the root node has a given value in its @@ -1141,119 +1084,6 @@ EXPORT_SYMBOL(machine_is_compatible); *******/ /** - * of_find_node_by_name - Find a node by its "name" property - * @from: The node to start searching from or NULL, the node - * you pass will not be searched, only the next one - * will; typically, you pass what the previous call - * returned. of_node_put() will be called on it - * @name: The name string to match against - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_node_by_name(struct device_node *from, - const char *name) -{ - struct device_node *np; - - read_lock(&devtree_lock); - np = from ? from->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (np->name != NULL && strcasecmp(np->name, name) == 0 - && of_node_get(np)) - break; - of_node_put(from); - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_find_node_by_name); - -/** - * of_find_node_by_type - Find a node by its "device_type" property - * @from: The node to start searching from, or NULL to start searching - * the entire device tree. The node you pass will not be - * searched, only the next one will; typically, you pass - * what the previous call returned. of_node_put() will be - * called on from for you. - * @type: The type string to match against - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_node_by_type(struct device_node *from, - const char *type) -{ - struct device_node *np; - - read_lock(&devtree_lock); - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->type != 0 && strcasecmp(np->type, type) == 0 - && of_node_get(np)) - break; - of_node_put(from); - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_find_node_by_type); - -/** - * of_find_compatible_node - Find a node based on type and one of the - * tokens in its "compatible" property - * @from: The node to start searching from or NULL, the node - * you pass will not be searched, only the next one - * will; typically, you pass what the previous call - * returned. of_node_put() will be called on it - * @type: The type string to match "device_type" or NULL to ignore - * @compatible: The string to match to one of the tokens in the device - * "compatible" list. - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compatible) -{ - struct device_node *np; - - read_lock(&devtree_lock); - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcasecmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compatible) && of_node_get(np)) - break; - } - of_node_put(from); - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_find_compatible_node); - -/** - * of_find_node_by_path - Find a node matching a full OF path - * @path: The full path to match - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_find_node_by_path(const char *path) -{ - struct device_node *np = allnodes; - - read_lock(&devtree_lock); - for (; np != 0; np = np->allnext) { - if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0 - && of_node_get(np)) - break; - } - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_find_node_by_path); - -/** * of_find_node_by_phandle - Find a node given a phandle * @handle: phandle of the node to find * @@ -1298,51 +1128,6 @@ struct device_node *of_find_all_nodes(struct device_node *prev) EXPORT_SYMBOL(of_find_all_nodes); /** - * of_get_parent - Get a node's parent if any - * @node: Node to get parent - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_get_parent(const struct device_node *node) -{ - struct device_node *np; - - if (!node) - return NULL; - - read_lock(&devtree_lock); - np = of_node_get(node->parent); - read_unlock(&devtree_lock); - return np; -} -EXPORT_SYMBOL(of_get_parent); - -/** - * of_get_next_child - Iterate a node childs - * @node: parent node - * @prev: previous child of the parent node, or NULL to get first - * - * Returns a node pointer with refcount incremented, use - * of_node_put() on it when done. - */ -struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - read_lock(&devtree_lock); - next = prev ? prev->sibling : node->child; - for (; next != 0; next = next->sibling) - if (of_node_get(next)) - break; - of_node_put(prev); - read_unlock(&devtree_lock); - return next; -} -EXPORT_SYMBOL(of_get_next_child); - -/** * of_node_get - Increment refcount of a node * @node: Node to inc refcount, NULL is supported to * simplify writing of callers @@ -1543,37 +1328,6 @@ static int __init prom_reconfig_setup(void) __initcall(prom_reconfig_setup); #endif -struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp) -{ - struct property *pp; - - read_lock(&devtree_lock); - for (pp = np->properties; pp != 0; pp = pp->next) - if (strcmp(pp->name, name) == 0) { - if (lenp != 0) - *lenp = pp->length; - break; - } - read_unlock(&devtree_lock); - - return pp; -} -EXPORT_SYMBOL(of_find_property); - -/* - * Find a property with a given name for a given node - * and return the value. - */ -const void *of_get_property(const struct device_node *np, const char *name, - int *lenp) -{ - struct property *pp = of_find_property(np,name,lenp); - return pp ? pp->value : NULL; -} -EXPORT_SYMBOL(of_get_property); - /* * Add a property to a node */ diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index 603d83ad65c8..9d327ec59759 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig @@ -24,6 +24,9 @@ config GENERIC_ISA_DMA config ARCH_NO_VIRT_TO_BUS def_bool y +config OF + def_bool y + source "init/Kconfig" menu "General machine setup" diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index fd7f8cb668a3..7176040caba0 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c @@ -1,132 +1,13 @@ #include <linux/string.h> #include <linux/kernel.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/slab.h> - -#include <asm/errno.h> -#include <asm/of_device.h> - -/** - * of_match_device - Tell if an of_device structure has a matching - * of_match structure - * @ids: array of of device match structures to search in - * @dev: the of device structure to match against - * - * Used by a driver to check whether an of_device present in the - * system is in its list of supported devices. - */ -const struct of_device_id *of_match_device(const struct of_device_id *matches, - const struct of_device *dev) -{ - if (!dev->node) - return NULL; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= dev->node->name - && !strcmp(matches->name, dev->node->name); - if (matches->type[0]) - match &= dev->node->type - && !strcmp(matches->type, dev->node->type); - if (matches->compatible[0]) - match &= of_device_is_compatible(dev->node, - matches->compatible); - if (match) - return matches; - matches++; - } - return NULL; -} - -static int of_platform_bus_match(struct device *dev, struct device_driver *drv) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * of_drv = to_of_platform_driver(drv); - const struct of_device_id * matches = of_drv->match_table; - - if (!matches) - return 0; - - return of_match_device(matches, of_dev) != NULL; -} - -struct of_device *of_dev_get(struct of_device *dev) -{ - struct device *tmp; - - if (!dev) - return NULL; - tmp = get_device(&dev->dev); - if (tmp) - return to_of_device(tmp); - else - return NULL; -} - -void of_dev_put(struct of_device *dev) -{ - if (dev) - put_device(&dev->dev); -} - - -static int of_device_probe(struct device *dev) -{ - int error = -ENODEV; - struct of_platform_driver *drv; - struct of_device *of_dev; - const struct of_device_id *match; - - drv = to_of_platform_driver(dev->driver); - of_dev = to_of_device(dev); - - if (!drv->probe) - return error; - - of_dev_get(of_dev); - - match = of_match_device(drv->match_table, of_dev); - if (match) - error = drv->probe(of_dev, match); - if (error) - of_dev_put(of_dev); - - return error; -} - -static int of_device_remove(struct device *dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - - if (dev->driver && drv->remove) - drv->remove(of_dev); - return 0; -} - -static int of_device_suspend(struct device *dev, pm_message_t state) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; -} - -static int of_device_resume(struct device * dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; -} +#include <linux/errno.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> static int node_match(struct device *dev, void *data) { @@ -138,7 +19,7 @@ static int node_match(struct device *dev, void *data) struct of_device *of_find_device_by_node(struct device_node *dp) { - struct device *dev = bus_find_device(&of_bus_type, NULL, + struct device *dev = bus_find_device(&of_platform_bus_type, NULL, dp, node_match); if (dev) @@ -149,38 +30,17 @@ struct of_device *of_find_device_by_node(struct device_node *dp) EXPORT_SYMBOL(of_find_device_by_node); #ifdef CONFIG_PCI -struct bus_type ebus_bus_type = { - .name = "ebus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; +struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); #endif #ifdef CONFIG_SBUS -struct bus_type sbus_bus_type = { - .name = "sbus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; +struct bus_type sbus_bus_type; EXPORT_SYMBOL(sbus_bus_type); #endif -struct bus_type of_bus_type = { - .name = "of", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; -EXPORT_SYMBOL(of_bus_type); +struct bus_type of_platform_bus_type; +EXPORT_SYMBOL(of_platform_bus_type); static inline u64 of_read_addr(const u32 *cell, int size) { @@ -646,7 +506,7 @@ build_resources: build_device_resources(op, parent); op->dev.parent = parent; - op->dev.bus = &of_bus_type; + op->dev.bus = &of_platform_bus_type; if (!parent) strcpy(op->dev.bus_id, "root"); else @@ -690,14 +550,14 @@ static int __init of_bus_driver_init(void) { int err; - err = bus_register(&of_bus_type); + err = of_bus_type_init(&of_platform_bus_type, "of"); #ifdef CONFIG_PCI if (!err) - err = bus_register(&ebus_bus_type); + err = of_bus_type_init(&ebus_bus_type, "ebus"); #endif #ifdef CONFIG_SBUS if (!err) - err = bus_register(&sbus_bus_type); + err = of_bus_type_init(&sbus_bus_type, "sbus"); #endif if (!err) @@ -735,56 +595,6 @@ void of_unregister_driver(struct of_platform_driver *drv) driver_unregister(&drv->driver); } - -static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - return sprintf(buf, "%s", ofdev->node->full_name); -} - -static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); - -/** - * of_release_dev - free an of device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this of device are - * done. - */ -void of_release_dev(struct device *dev) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - - kfree(ofdev); -} - -int of_device_register(struct of_device *ofdev) -{ - int rc; - - BUG_ON(ofdev->node == NULL); - - rc = device_register(&ofdev->dev); - if (rc) - return rc; - - rc = device_create_file(&ofdev->dev, &dev_attr_devspec); - if (rc) - device_unregister(&ofdev->dev); - - return rc; -} - -void of_device_unregister(struct of_device *ofdev) -{ - device_remove_file(&ofdev->dev, &dev_attr_devspec); - device_unregister(&ofdev->dev); -} - struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id, struct device *parent, @@ -810,12 +620,6 @@ struct of_device* of_platform_device_create(struct device_node *np, return dev; } -EXPORT_SYMBOL(of_match_device); EXPORT_SYMBOL(of_register_driver); EXPORT_SYMBOL(of_unregister_driver); -EXPORT_SYMBOL(of_device_register); -EXPORT_SYMBOL(of_device_unregister); -EXPORT_SYMBOL(of_dev_get); -EXPORT_SYMBOL(of_dev_put); EXPORT_SYMBOL(of_platform_device_create); -EXPORT_SYMBOL(of_release_dev); diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index eed140b3c739..012f98346bcd 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c @@ -25,73 +25,9 @@ #include <asm/prom.h> #include <asm/oplib.h> -static struct device_node *allnodes; +extern struct device_node *allnodes; /* temporary while merging */ -/* use when traversing tree through the allnext, child, sibling, - * or parent members of struct device_node. - */ -static DEFINE_RWLOCK(devtree_lock); - -int of_device_is_compatible(const struct device_node *device, - const char *compat) -{ - const char* cp; - int cplen, l; - - cp = of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} -EXPORT_SYMBOL(of_device_is_compatible); - -struct device_node *of_get_parent(const struct device_node *node) -{ - struct device_node *np; - - if (!node) - return NULL; - - np = node->parent; - - return np; -} -EXPORT_SYMBOL(of_get_parent); - -struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - next = prev ? prev->sibling : node->child; - for (; next != 0; next = next->sibling) { - break; - } - - return next; -} -EXPORT_SYMBOL(of_get_next_child); - -struct device_node *of_find_node_by_path(const char *path) -{ - struct device_node *np = allnodes; - - for (; np != 0; np = np->allnext) { - if (np->full_name != 0 && strcmp(np->full_name, path) == 0) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_node_by_path); +extern rwlock_t devtree_lock; /* temporary while merging */ struct device_node *of_find_node_by_phandle(phandle handle) { @@ -105,81 +41,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); -struct device_node *of_find_node_by_name(struct device_node *from, - const char *name) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (np->name != NULL && strcmp(np->name, name) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_name); - -struct device_node *of_find_node_by_type(struct device_node *from, - const char *type) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->type != 0 && strcmp(np->type, type) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_type); - -struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compatible) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compatible)) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_compatible_node); - -struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp) -{ - struct property *pp; - - for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcasecmp(pp->name, name) == 0) { - if (lenp != 0) - *lenp = pp->length; - break; - } - } - return pp; -} -EXPORT_SYMBOL(of_find_property); - -/* - * Find a property with a given name for a given node - * and return the value. - */ -const void *of_get_property(const struct device_node *np, const char *name, - int *lenp) -{ - struct property *pp = of_find_property(np,name,lenp); - return pp ? pp->value : NULL; -} -EXPORT_SYMBOL(of_get_property); - int of_getintprop_default(struct device_node *np, const char *name, int def) { struct property *prop; @@ -193,36 +54,6 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); -int of_n_addr_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#address-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #address-cells property for the root node, default to 2 */ - return 2; -} -EXPORT_SYMBOL(of_n_addr_cells); - -int of_n_size_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#size-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #size-cells property for the root node, default to 1 */ - return 1; -} -EXPORT_SYMBOL(of_n_size_cells); - int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 7b4612da74a6..f2fdbb3664d3 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c @@ -354,7 +354,7 @@ static struct of_platform_driver clock_driver = { /* Probe for the mostek real time clock chip. */ static int __init clock_init(void) { - return of_register_driver(&clock_driver, &of_bus_type); + return of_register_driver(&clock_driver, &of_platform_bus_type); } /* Must be after subsys_initcall() so that busses are probed. Must diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index df6ee71894d1..f1cc55677ff2 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig @@ -65,6 +65,9 @@ config AUDIT_ARCH config ARCH_NO_VIRT_TO_BUS def_bool y +config OF + def_bool y + choice prompt "Kernel page size" default SPARC64_PAGE_SIZE_8KB diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index 826118ee53d5..7b379761e9f8 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c @@ -155,7 +155,7 @@ static struct of_platform_driver auxio_driver = { static int __init auxio_init(void) { - return of_register_driver(&auxio_driver, &of_bus_type); + return of_register_driver(&auxio_driver, &of_platform_bus_type); } /* Must be after subsys_initcall() so that busses are probed. Must diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 6676b93219dc..7b0dce9604ee 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c @@ -1,132 +1,13 @@ #include <linux/string.h> #include <linux/kernel.h> +#include <linux/of.h> #include <linux/init.h> #include <linux/module.h> #include <linux/mod_devicetable.h> #include <linux/slab.h> - -#include <asm/errno.h> -#include <asm/of_device.h> - -/** - * of_match_device - Tell if an of_device structure has a matching - * of_match structure - * @ids: array of of device match structures to search in - * @dev: the of device structure to match against - * - * Used by a driver to check whether an of_device present in the - * system is in its list of supported devices. - */ -const struct of_device_id *of_match_device(const struct of_device_id *matches, - const struct of_device *dev) -{ - if (!dev->node) - return NULL; - while (matches->name[0] || matches->type[0] || matches->compatible[0]) { - int match = 1; - if (matches->name[0]) - match &= dev->node->name - && !strcmp(matches->name, dev->node->name); - if (matches->type[0]) - match &= dev->node->type - && !strcmp(matches->type, dev->node->type); - if (matches->compatible[0]) - match &= of_device_is_compatible(dev->node, - matches->compatible); - if (match) - return matches; - matches++; - } - return NULL; -} - -static int of_platform_bus_match(struct device *dev, struct device_driver *drv) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * of_drv = to_of_platform_driver(drv); - const struct of_device_id * matches = of_drv->match_table; - - if (!matches) - return 0; - - return of_match_device(matches, of_dev) != NULL; -} - -struct of_device *of_dev_get(struct of_device *dev) -{ - struct device *tmp; - - if (!dev) - return NULL; - tmp = get_device(&dev->dev); - if (tmp) - return to_of_device(tmp); - else - return NULL; -} - -void of_dev_put(struct of_device *dev) -{ - if (dev) - put_device(&dev->dev); -} - - -static int of_device_probe(struct device *dev) -{ - int error = -ENODEV; - struct of_platform_driver *drv; - struct of_device *of_dev; - const struct of_device_id *match; - - drv = to_of_platform_driver(dev->driver); - of_dev = to_of_device(dev); - - if (!drv->probe) - return error; - - of_dev_get(of_dev); - - match = of_match_device(drv->match_table, of_dev); - if (match) - error = drv->probe(of_dev, match); - if (error) - of_dev_put(of_dev); - - return error; -} - -static int of_device_remove(struct device *dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - - if (dev->driver && drv->remove) - drv->remove(of_dev); - return 0; -} - -static int of_device_suspend(struct device *dev, pm_message_t state) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->suspend) - error = drv->suspend(of_dev, state); - return error; -} - -static int of_device_resume(struct device * dev) -{ - struct of_device * of_dev = to_of_device(dev); - struct of_platform_driver * drv = to_of_platform_driver(dev->driver); - int error = 0; - - if (dev->driver && drv->resume) - error = drv->resume(of_dev); - return error; -} +#include <linux/errno.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name) { @@ -163,7 +44,7 @@ static int node_match(struct device *dev, void *data) struct of_device *of_find_device_by_node(struct device_node *dp) { - struct device *dev = bus_find_device(&of_bus_type, NULL, + struct device *dev = bus_find_device(&of_platform_bus_type, NULL, dp, node_match); if (dev) @@ -174,48 +55,20 @@ struct of_device *of_find_device_by_node(struct device_node *dp) EXPORT_SYMBOL(of_find_device_by_node); #ifdef CONFIG_PCI -struct bus_type isa_bus_type = { - .name = "isa", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; +struct bus_type isa_bus_type; EXPORT_SYMBOL(isa_bus_type); -struct bus_type ebus_bus_type = { - .name = "ebus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; +struct bus_type ebus_bus_type; EXPORT_SYMBOL(ebus_bus_type); #endif #ifdef CONFIG_SBUS -struct bus_type sbus_bus_type = { - .name = "sbus", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; +struct bus_type sbus_bus_type; EXPORT_SYMBOL(sbus_bus_type); #endif -struct bus_type of_bus_type = { - .name = "of", - .match = of_platform_bus_match, - .probe = of_device_probe, - .remove = of_device_remove, - .suspend = of_device_suspend, - .resume = of_device_resume, -}; -EXPORT_SYMBOL(of_bus_type); +struct bus_type of_platform_bus_type; +EXPORT_SYMBOL(of_platform_bus_type); static inline u64 of_read_addr(const u32 *cell, int size) { @@ -933,7 +786,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp, op->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]); op->dev.parent = parent; - op->dev.bus = &of_bus_type; + op->dev.bus = &of_platform_bus_type; if (!parent) strcpy(op->dev.bus_id, "root"); else @@ -977,16 +830,16 @@ static int __init of_bus_driver_init(void) { int err; - err = bus_register(&of_bus_type); + err = of_bus_type_init(&of_platform_bus_type, "of"); #ifdef CONFIG_PCI if (!err) - err = bus_register(&isa_bus_type); + err = of_bus_type_init(&isa_bus_type, "isa"); if (!err) - err = bus_register(&ebus_bus_type); + err = of_bus_type_init(&ebus_bus_type, "ebus"); #endif #ifdef CONFIG_SBUS if (!err) - err = bus_register(&sbus_bus_type); + err = of_bus_type_init(&sbus_bus_type, "sbus"); #endif if (!err) @@ -1020,61 +873,13 @@ int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus) /* register with core */ return driver_register(&drv->driver); } +EXPORT_SYMBOL(of_register_driver); void of_unregister_driver(struct of_platform_driver *drv) { driver_unregister(&drv->driver); } - - -static ssize_t dev_show_devspec(struct device *dev, struct device_attribute *attr, char *buf) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - return sprintf(buf, "%s", ofdev->node->full_name); -} - -static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); - -/** - * of_release_dev - free an of device structure when all users of it are finished. - * @dev: device that's been disconnected - * - * Will be called only by the device core when all users of this of device are - * done. - */ -void of_release_dev(struct device *dev) -{ - struct of_device *ofdev; - - ofdev = to_of_device(dev); - - kfree(ofdev); -} - -int of_device_register(struct of_device *ofdev) -{ - int rc; - - BUG_ON(ofdev->node == NULL); - - rc = device_register(&ofdev->dev); - if (rc) - return rc; - - rc = device_create_file(&ofdev->dev, &dev_attr_devspec); - if (rc) - device_unregister(&ofdev->dev); - - return rc; -} - -void of_device_unregister(struct of_device *ofdev) -{ - device_remove_file(&ofdev->dev, &dev_attr_devspec); - device_unregister(&ofdev->dev); -} +EXPORT_SYMBOL(of_unregister_driver); struct of_device* of_platform_device_create(struct device_node *np, const char *bus_id, @@ -1100,13 +905,4 @@ struct of_device* of_platform_device_create(struct device_node *np, return dev; } - -EXPORT_SYMBOL(of_match_device); -EXPORT_SYMBOL(of_register_driver); -EXPORT_SYMBOL(of_unregister_driver); -EXPORT_SYMBOL(of_device_register); -EXPORT_SYMBOL(of_device_unregister); -EXPORT_SYMBOL(of_dev_get); -EXPORT_SYMBOL(of_dev_put); EXPORT_SYMBOL(of_platform_device_create); -EXPORT_SYMBOL(of_release_dev); diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 39f9f6494d4c..b00feb01c16f 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c @@ -112,6 +112,6 @@ static struct of_platform_driver power_driver = { void __init power_init(void) { - of_register_driver(&power_driver, &of_bus_type); + of_register_driver(&power_driver, &of_platform_bus_type); return; } diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 5d220302cd50..2b2017ce2267 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c @@ -30,73 +30,9 @@ #include <asm/upa.h> #include <asm/smp.h> -static struct device_node *allnodes; +extern struct device_node *allnodes; /* temporary while merging */ -/* use when traversing tree through the allnext, child, sibling, - * or parent members of struct device_node. - */ -static DEFINE_RWLOCK(devtree_lock); - -int of_device_is_compatible(const struct device_node *device, - const char *compat) -{ - const char* cp; - int cplen, l; - - cp = of_get_property(device, "compatible", &cplen); - if (cp == NULL) - return 0; - while (cplen > 0) { - if (strncmp(cp, compat, strlen(compat)) == 0) - return 1; - l = strlen(cp) + 1; - cp += l; - cplen -= l; - } - - return 0; -} -EXPORT_SYMBOL(of_device_is_compatible); - -struct device_node *of_get_parent(const struct device_node *node) -{ - struct device_node *np; - - if (!node) - return NULL; - - np = node->parent; - - return np; -} -EXPORT_SYMBOL(of_get_parent); - -struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev) -{ - struct device_node *next; - - next = prev ? prev->sibling : node->child; - for (; next != 0; next = next->sibling) { - break; - } - - return next; -} -EXPORT_SYMBOL(of_get_next_child); - -struct device_node *of_find_node_by_path(const char *path) -{ - struct device_node *np = allnodes; - - for (; np != 0; np = np->allnext) { - if (np->full_name != 0 && strcmp(np->full_name, path) == 0) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_node_by_path); +extern rwlock_t devtree_lock; /* temporary while merging */ struct device_node *of_find_node_by_phandle(phandle handle) { @@ -110,81 +46,6 @@ struct device_node *of_find_node_by_phandle(phandle handle) } EXPORT_SYMBOL(of_find_node_by_phandle); -struct device_node *of_find_node_by_name(struct device_node *from, - const char *name) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != NULL; np = np->allnext) - if (np->name != NULL && strcmp(np->name, name) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_name); - -struct device_node *of_find_node_by_type(struct device_node *from, - const char *type) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) - if (np->type != 0 && strcmp(np->type, type) == 0) - break; - - return np; -} -EXPORT_SYMBOL(of_find_node_by_type); - -struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compatible) -{ - struct device_node *np; - - np = from ? from->allnext : allnodes; - for (; np != 0; np = np->allnext) { - if (type != NULL - && !(np->type != 0 && strcmp(np->type, type) == 0)) - continue; - if (of_device_is_compatible(np, compatible)) - break; - } - - return np; -} -EXPORT_SYMBOL(of_find_compatible_node); - -struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp) -{ - struct property *pp; - - for (pp = np->properties; pp != 0; pp = pp->next) { - if (strcasecmp(pp->name, name) == 0) { - if (lenp != 0) - *lenp = pp->length; - break; - } - } - return pp; -} -EXPORT_SYMBOL(of_find_property); - -/* - * Find a property with a given name for a given node - * and return the value. - */ -const void *of_get_property(const struct device_node *np, const char *name, - int *lenp) -{ - struct property *pp = of_find_property(np,name,lenp); - return pp ? pp->value : NULL; -} -EXPORT_SYMBOL(of_get_property); - int of_getintprop_default(struct device_node *np, const char *name, int def) { struct property *prop; @@ -198,36 +59,6 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) } EXPORT_SYMBOL(of_getintprop_default); -int of_n_addr_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#address-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #address-cells property for the root node, default to 2 */ - return 2; -} -EXPORT_SYMBOL(of_n_addr_cells); - -int of_n_size_cells(struct device_node *np) -{ - const int* ip; - do { - if (np->parent) - np = np->parent; - ip = of_get_property(np, "#size-cells", NULL); - if (ip != NULL) - return *ip; - } while (np->parent); - /* No #size-cells property for the root node, default to 1 */ - return 1; -} -EXPORT_SYMBOL(of_n_size_cells); - int of_set_property(struct device_node *dp, const char *name, void *val, int len) { struct property **prevp; diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index 62e316ab1339..592ffcd57605 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c @@ -835,7 +835,7 @@ static int __init clock_init(void) return 0; } - return of_register_driver(&clock_driver, &of_bus_type); + return of_register_driver(&clock_driver, &of_platform_bus_type); } /* Must be after subsys_initcall() so that busses are probed. Must diff --git a/drivers/Kconfig b/drivers/Kconfig index 707650ab77a7..3e1c442deff9 100644 --- a/drivers/Kconfig +++ b/drivers/Kconfig @@ -8,6 +8,8 @@ source "drivers/connector/Kconfig" source "drivers/mtd/Kconfig" +source "drivers/of/Kconfig" + source "drivers/parport/Kconfig" source "drivers/pnp/Kconfig" diff --git a/drivers/Makefile b/drivers/Makefile index 0ea8e3237c0d..a9e4c5f922a0 100644 --- a/drivers/Makefile +++ b/drivers/Makefile @@ -86,3 +86,4 @@ obj-$(CONFIG_GENERIC_TIME) += clocksource/ obj-$(CONFIG_DMA_ENGINE) += dma/ obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_PPC_PS3) += ps3/ +obj-$(CONFIG_OF) += of/ diff --git a/drivers/of/Kconfig b/drivers/of/Kconfig new file mode 100644 index 000000000000..c03072b12f42 --- /dev/null +++ b/drivers/of/Kconfig @@ -0,0 +1,3 @@ +config OF_DEVICE + def_bool y + depends on OF && (SPARC || PPC_OF) diff --git a/drivers/of/Makefile b/drivers/of/Makefile new file mode 100644 index 000000000000..ab9be5d5255b --- /dev/null +++ b/drivers/of/Makefile @@ -0,0 +1,2 @@ +obj-y = base.o +obj-$(CONFIG_OF_DEVICE) += device.o platform.o diff --git a/drivers/of/base.c b/drivers/of/base.c new file mode 100644 index 000000000000..9377f3bc410a --- /dev/null +++ b/drivers/of/base.c @@ -0,0 +1,275 @@ +/* + * Procedures for creating, accessing and interpreting the device tree. + * + * Paul Mackerras August 1996. + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Adapted for 64bit PowerPC by Dave Engebretsen and Peter Bergner. + * {engebret|bergner}@us.ibm.com + * + * Adapted for sparc and sparc64 by David S. Miller davem@davemloft.net + * + * Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/module.h> +#include <linux/of.h> +#include <linux/spinlock.h> + +struct device_node *allnodes; + +/* use when traversing tree through the allnext, child, sibling, + * or parent members of struct device_node. + */ +DEFINE_RWLOCK(devtree_lock); + +int of_n_addr_cells(struct device_node *np) +{ + const int *ip; + + do { + if (np->parent) + np = np->parent; + ip = of_get_property(np, "#address-cells", NULL); + if (ip) + return *ip; + } while (np->parent); + /* No #address-cells property for the root node */ + return OF_ROOT_NODE_ADDR_CELLS_DEFAULT; +} +EXPORT_SYMBOL(of_n_addr_cells); + +int of_n_size_cells(struct device_node *np) +{ + const int *ip; + + do { + if (np->parent) + np = np->parent; + ip = of_get_property(np, "#size-cells", NULL); + if (ip) + return *ip; + } while (np->parent); + /* No #size-cells property for the root node */ + return OF_ROOT_NODE_SIZE_CELLS_DEFAULT; +} +EXPORT_SYMBOL(of_n_size_cells); + +struct property *of_find_property(const struct device_node *np, + const char *name, + int *lenp) +{ + struct property *pp; + + read_lock(&devtree_lock); + for (pp = np->properties; pp != 0; pp = pp->next) { + if (of_prop_cmp(pp->name, name) == 0) { + if (lenp != 0) + *lenp = pp->length; + break; + } + } + read_unlock(&devtree_lock); + + return pp; +} +EXPORT_SYMBOL(of_find_property); + +/* + * Find a property with a given name for a given node + * and return the value. + */ +const void *of_get_property(const struct device_node *np, const char *name, + int *lenp) +{ + struct property *pp = of_find_property(np, name, lenp); + + return pp ? pp->value : NULL; +} +EXPORT_SYMBOL(of_get_property); + +/** Checks if the given "compat" string matches one of the strings in + * the device's "compatible" property + */ +int of_device_is_compatible(const struct device_node *device, + const char *compat) +{ + const char* cp; + int cplen, l; + + cp = of_get_property(device, "compatible", &cplen); + if (cp == NULL) + return 0; + while (cplen > 0) { + if (of_compat_cmp(cp, compat, strlen(compat)) == 0) + return 1; + l = strlen(cp) + 1; + cp += l; + cplen -= l; + } + + return 0; +} +EXPORT_SYMBOL(of_device_is_compatible); + +/** + * of_get_parent - Get a node's parent if any + * @node: Node to get parent + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_get_parent(const struct device_node *node) +{ + struct device_node *np; + + if (!node) + return NULL; + + read_lock(&devtree_lock); + np = of_node_get(node->parent); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_get_parent); + +/** + * of_get_next_child - Iterate a node childs + * @node: parent node + * @prev: previous child of the parent node, or NULL to get first + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +{ + struct device_node *next; + + read_lock(&devtree_lock); + next = prev ? prev->sibling : node->child; + for (; next; next = next->sibling) + if (of_node_get(next)) + break; + of_node_put(prev); + read_unlock(&devtree_lock); + return next; +} +EXPORT_SYMBOL(of_get_next_child); + +/** + * of_find_node_by_path - Find a node matching a full OF path + * @path: The full path to match + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_path(const char *path) +{ + struct device_node *np = allnodes; + + read_lock(&devtree_lock); + for (; np; np = np->allnext) { + if (np->full_name && (of_node_cmp(np->full_name, path) == 0) + && of_node_get(np)) + break; + } + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_path); + +/** + * of_find_node_by_name - Find a node by its "name" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @name: The name string to match against + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np; np = np->allnext) + if (np->name && (of_node_cmp(np->name, name) == 0) + && of_node_get(np)) + break; + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_name); + +/** + * of_find_node_by_type - Find a node by its "device_type" property + * @from: The node to start searching from, or NULL to start searching + * the entire device tree. The node you pass will not be + * searched, only the next one will; typically, you pass + * what the previous call returned. of_node_put() will be + * called on from for you. + * @type: The type string to match against + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np; np = np->allnext) + if (np->type && (of_node_cmp(np->type, type) == 0) + && of_node_get(np)) + break; + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_node_by_type); + +/** + * of_find_compatible_node - Find a node based on type and one of the + * tokens in its "compatible" property + * @from: The node to start searching from or NULL, the node + * you pass will not be searched, only the next one + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @type: The type string to match "device_type" or NULL to ignore + * @compatible: The string to match to one of the tokens in the device + * "compatible" list. + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. + */ +struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +{ + struct device_node *np; + + read_lock(&devtree_lock); + np = from ? from->allnext : allnodes; + for (; np; np = np->allnext) { + if (type + && !(np->type && (of_node_cmp(np->type, type) == 0))) + continue; + if (of_device_is_compatible(np, compatible) && of_node_get(np)) + break; + } + of_node_put(from); + read_unlock(&devtree_lock); + return np; +} +EXPORT_SYMBOL(of_find_compatible_node); diff --git a/drivers/of/device.c b/drivers/of/device.c new file mode 100644 index 000000000000..6245f060fb77 --- /dev/null +++ b/drivers/of/device.c @@ -0,0 +1,131 @@ +#include <linux/string.h> +#include <linux/kernel.h> +#include <linux/of.h> +#include <linux/of_device.h> +#include <linux/init.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/slab.h> + +#include <asm/errno.h> + +/** + * of_match_node - Tell if an device_node has a matching of_match structure + * @ids: array of of device match structures to search in + * @node: the of device structure to match against + * + * Low level utility function used by device matching. + */ +const struct of_device_id *of_match_node(const struct of_device_id *matches, + const struct device_node *node) +{ + while (matches->name[0] || matches->type[0] || matches->compatible[0]) { + int match = 1; + if (matches->name[0]) + match &= node->name + && !strcmp(matches->name, node->name); + if (matches->type[0]) + match &= node->type + && !strcmp(matches->type, node->type); + if (matches->compatible[0]) + match &= of_device_is_compatible(node, + matches->compatible); + if (match) + return matches; + matches++; + } + return NULL; +} +EXPORT_SYMBOL(of_match_node); + +/** + * of_match_device - Tell if an of_device structure has a matching + * of_match structure + * @ids: array of of device match structures to search in + * @dev: the of device structure to match against + * + * Used by a driver to check whether an of_device present in the + * system is in its list of supported devices. + */ +const struct of_device_id *of_match_device(const struct of_device_id *matches, + const struct of_device *dev) +{ + if (!dev->node) + return NULL; + return of_match_node(matches, dev->node); +} +EXPORT_SYMBOL(of_match_device); + +struct of_device *of_dev_get(struct of_device *dev) +{ + struct device *tmp; + + if (!dev) + return NULL; + tmp = get_device(&dev->dev); + if (tmp) + return to_of_device(tmp); + else + return NULL; +} +EXPORT_SYMBOL(of_dev_get); + +void of_dev_put(struct of_device *dev) +{ + if (dev) + put_device(&dev->dev); +} +EXPORT_SYMBOL(of_dev_put); + +static ssize_t dev_show_devspec(struct device *dev, + struct device_attribute *attr, char *buf) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + return sprintf(buf, "%s", ofdev->node->full_name); +} + +static DEVICE_ATTR(devspec, S_IRUGO, dev_show_devspec, NULL); + +/** + * of_release_dev - free an of device structure when all users of it are finished. + * @dev: device that's been disconnected + * + * Will be called only by the device core when all users of this of device are + * done. + */ +void of_release_dev(struct device *dev) +{ + struct of_device *ofdev; + + ofdev = to_of_device(dev); + of_node_put(ofdev->node); + kfree(ofdev); +} +EXPORT_SYMBOL(of_release_dev); + +int of_device_register(struct of_device *ofdev) +{ + int rc; + + BUG_ON(ofdev->node == NULL); + + rc = device_register(&ofdev->dev); + if (rc) + return rc; + + rc = device_create_file(&ofdev->dev, &dev_attr_devspec); + if (rc) + device_unregister(&ofdev->dev); + + return rc; +} +EXPORT_SYMBOL(of_device_register); + +void of_device_unregister(struct of_device *ofdev) +{ + device_remove_file(&ofdev->dev, &dev_attr_devspec); + device_unregister(&ofdev->dev); +} +EXPORT_SYMBOL(of_device_unregister); diff --git a/drivers/of/platform.c b/drivers/of/platform.c new file mode 100644 index 000000000000..864f09fd9f86 --- /dev/null +++ b/drivers/of/platform.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * and Arnd Bergmann, IBM Corp. + * Merged from powerpc/kernel/of_platform.c and + * sparc{,64}/kernel/of_device.c by Stephen Rothwell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ +#include <linux/errno.h> +#include <linux/device.h> +#include <linux/of_device.h> +#include <linux/of_platform.h> + +static int of_platform_bus_match(struct device *dev, struct device_driver *drv) +{ + struct of_device *of_dev = to_of_device(dev); + struct of_platform_driver *of_drv = to_of_platform_driver(drv); + const struct of_device_id *matches = of_drv->match_table; + + if (!matches) + return 0; + + return of_match_device(matches, of_dev) != NULL; +} + +static int of_platform_device_probe(struct device *dev) +{ + int error = -ENODEV; + struct of_platform_driver *drv; + struct of_device *of_dev; + const struct of_device_id *match; + + drv = to_of_platform_driver(dev->driver); + of_dev = to_of_device(dev); + + if (!drv->probe) + return error; + + of_dev_get(of_dev); + + match = of_match_device(drv->match_table, of_dev); + if (match) + error = drv->probe(of_dev, match); + if (error) + of_dev_put(of_dev); + + return error; +} + +static int of_platform_device_remove(struct device *dev) +{ + struct of_device *of_dev = to_of_device(dev); + struct of_platform_driver *drv = to_of_platform_driver(dev->driver); + + if (dev->driver && drv->remove) + drv->remove(of_dev); + return 0; +} + +static int of_platform_device_suspend(struct device *dev, pm_message_t state) +{ + struct of_device *of_dev = to_of_device(dev); + struct of_platform_driver *drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->suspend) + error = drv->suspend(of_dev, state); + return error; +} + +static int of_platform_device_resume(struct device * dev) +{ + struct of_device *of_dev = to_of_device(dev); + struct of_platform_driver *drv = to_of_platform_driver(dev->driver); + int error = 0; + + if (dev->driver && drv->resume) + error = drv->resume(of_dev); + return error; +} + +int of_bus_type_init(struct bus_type *bus, const char *name) +{ + bus->name = name; + bus->match = of_platform_bus_match; + bus->probe = of_platform_device_probe; + bus->remove = of_platform_device_remove; + bus->suspend = of_platform_device_suspend; + bus->resume = of_platform_device_resume; + return bus_register(bus); +} diff --git a/include/asm-powerpc/of_device.h b/include/asm-powerpc/of_device.h index e9af49eb1aa8..ec2a8a2c737c 100644 --- a/include/asm-powerpc/of_device.h +++ b/include/asm-powerpc/of_device.h @@ -3,14 +3,12 @@ #ifdef __KERNEL__ #include <linux/device.h> -#include <linux/mod_devicetable.h> -#include <asm/prom.h> - +#include <linux/of.h> /* * The of_device is a kind of "base class" that is a superset of * struct device for use by devices attached to an OF node and - * probed using OF properties + * probed using OF properties. */ struct of_device { @@ -18,24 +16,14 @@ struct of_device u64 dma_mask; /* DMA mask */ struct device dev; /* Generic device interface */ }; -#define to_of_device(d) container_of(d, struct of_device, dev) - -extern const struct of_device_id *of_match_node( - const struct of_device_id *matches, const struct device_node *node); -extern const struct of_device_id *of_match_device( - const struct of_device_id *matches, const struct of_device *dev); - -extern struct of_device *of_dev_get(struct of_device *dev); -extern void of_dev_put(struct of_device *dev); - -extern int of_device_register(struct of_device *ofdev); -extern void of_device_unregister(struct of_device *ofdev); -extern void of_release_dev(struct device *dev); extern ssize_t of_device_get_modalias(struct of_device *ofdev, char *str, ssize_t len); extern int of_device_uevent(struct device *dev, char **envp, int num_envp, char *buffer, int buffer_size); +/* This is just here during the transition */ +#include <linux/of_device.h> + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_OF_DEVICE_H */ diff --git a/include/asm-powerpc/of_platform.h b/include/asm-powerpc/of_platform.h index 217eafb167e9..80e6fad28b4f 100644 --- a/include/asm-powerpc/of_platform.h +++ b/include/asm-powerpc/of_platform.h @@ -1,3 +1,5 @@ +#ifndef _ASM_POWERPC_OF_PLATFORM_H +#define _ASM_POWERPC_OF_PLATFORM_H /* * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. * <benh@kernel.crashing.org> @@ -9,37 +11,8 @@ * */ -#include <asm/of_device.h> - -/* - * The of_platform_bus_type is a bus type used by drivers that do not - * attach to a macio or similar bus but still use OF probing - * mechanism - */ -extern struct bus_type of_platform_bus_type; - -/* - * An of_platform_driver driver is attached to a basic of_device on - * the "platform bus" (of_platform_bus_type) - */ -struct of_platform_driver -{ - char *name; - struct of_device_id *match_table; - struct module *owner; - - int (*probe)(struct of_device* dev, - const struct of_device_id *match); - int (*remove)(struct of_device* dev); - - int (*suspend)(struct of_device* dev, pm_message_t state); - int (*resume)(struct of_device* dev); - int (*shutdown)(struct of_device* dev); - - struct device_driver driver; -}; -#define to_of_platform_driver(drv) \ - container_of(drv,struct of_platform_driver, driver) +/* This is just here during the transition */ +#include <linux/of_platform.h> /* Platform drivers register/unregister */ extern int of_register_platform_driver(struct of_platform_driver *drv); @@ -56,5 +29,6 @@ extern int of_platform_bus_probe(struct device_node *root, struct of_device_id *matches, struct device *parent); -extern struct of_device *of_find_device_by_node(struct device_node *np); extern struct of_device *of_find_device_by_phandle(phandle ph); + +#endif /* _ASM_POWERPC_OF_PLATFORM_H */ diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h index 1632baa17dc6..6e391c9894ce 100644 --- a/include/asm-powerpc/prom.h +++ b/include/asm-powerpc/prom.h @@ -21,6 +21,13 @@ #include <asm/irq.h> #include <asm/atomic.h> +#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 1 +#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 + +#define of_compat_cmp(s1, s2, l) strncasecmp((s1), (s2), (l)) +#define of_prop_cmp(s1, s2) strcmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcasecmp((s1), (s2)) + /* Definitions used by the flattened device tree */ #define OF_DT_HEADER 0xd00dfeed /* marker */ #define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */ @@ -97,10 +104,6 @@ struct device_node { extern struct device_node *of_chosen; -/* flag descriptions */ -#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ -#define OF_DETACHED 2 /* node has been detached from the device tree */ - static inline int of_node_check_flag(struct device_node *n, unsigned long flag) { return test_bit(flag, &n->_flags); @@ -120,31 +123,7 @@ static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_e } -/* New style node lookup */ -extern struct device_node *of_find_node_by_name(struct device_node *from, - const char *name); -#define for_each_node_by_name(dn, name) \ - for (dn = of_find_node_by_name(NULL, name); dn; \ - dn = of_find_node_by_name(dn, name)) -extern struct device_node *of_find_node_by_type(struct device_node *from, - const char *type); -#define for_each_node_by_type(dn, type) \ - for (dn = of_find_node_by_type(NULL, type); dn; \ - dn = of_find_node_by_type(dn, type)) -extern struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compat); -#define for_each_compatible_node(dn, type, compatible) \ - for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ - dn = of_find_compatible_node(dn, type, compatible)) -extern struct device_node *of_find_node_by_path(const char *path); -extern struct device_node *of_find_node_by_phandle(phandle handle); extern struct device_node *of_find_all_nodes(struct device_node *prev); -extern struct device_node *of_get_parent(const struct device_node *node); -extern struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev); -extern struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp); extern struct device_node *of_node_get(struct device_node *node); extern void of_node_put(struct device_node *node); @@ -166,17 +145,9 @@ extern void of_detach_node(const struct device_node *); extern void finish_device_tree(void); extern void unflatten_device_tree(void); extern void early_init_devtree(void *); -extern int of_device_is_compatible(const struct device_node *device, - const char *); #define device_is_compatible(d, c) of_device_is_compatible((d), (c)) extern int machine_is_compatible(const char *compat); -extern const void *of_get_property(const struct device_node *node, - const char *name, - int *lenp); -#define get_property(a, b, c) of_get_property((a), (b), (c)) extern void print_properties(struct device_node *node); -extern int of_n_addr_cells(struct device_node* np); -extern int of_n_size_cells(struct device_node* np); extern int prom_n_intr_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); extern int prom_add_property(struct device_node* np, struct property* prop); @@ -230,7 +201,6 @@ static inline unsigned long of_read_ulong(const u32 *cell, int size) /* Translate an OF address block into a CPU physical address */ -#define OF_BAD_ADDR ((u64)-1) extern u64 of_translate_address(struct device_node *np, const u32 *addr); /* Extract an address from a device, returns the region size and @@ -357,5 +327,11 @@ extern int of_irq_to_resource(struct device_node *dev, int index, */ extern void __iomem *of_iomap(struct device_node *device, int index); +/* + * NB: This is here while we transition from using asm/prom.h + * to linux/of.h + */ +#include <linux/of.h> + #endif /* __KERNEL__ */ #endif /* _POWERPC_PROM_H */ diff --git a/include/asm-sparc/of_device.h b/include/asm-sparc/of_device.h index 7cb00c1b09c6..e5f5aedc2293 100644 --- a/include/asm-sparc/of_device.h +++ b/include/asm-sparc/of_device.h @@ -3,13 +3,9 @@ #ifdef __KERNEL__ #include <linux/device.h> +#include <linux/of.h> #include <linux/mod_devicetable.h> #include <asm/openprom.h> -#include <asm/prom.h> - -extern struct bus_type ebus_bus_type; -extern struct bus_type sbus_bus_type; -extern struct bus_type of_bus_type; /* * The of_device is a kind of "base class" that is a superset of @@ -30,50 +26,13 @@ struct of_device int portid; int clock_freq; }; -#define to_of_device(d) container_of(d, struct of_device, dev) extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); -extern struct of_device *of_find_device_by_node(struct device_node *); - -extern const struct of_device_id *of_match_device( - const struct of_device_id *matches, const struct of_device *dev); - -extern struct of_device *of_dev_get(struct of_device *dev); -extern void of_dev_put(struct of_device *dev); - -/* - * An of_platform_driver driver is attached to a basic of_device on - * the ISA, EBUS, and SBUS busses on sparc64. - */ -struct of_platform_driver -{ - char *name; - struct of_device_id *match_table; - struct module *owner; - - int (*probe)(struct of_device* dev, const struct of_device_id *match); - int (*remove)(struct of_device* dev); - - int (*suspend)(struct of_device* dev, pm_message_t state); - int (*resume)(struct of_device* dev); - int (*shutdown)(struct of_device* dev); - - struct device_driver driver; -}; -#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) - -extern int of_register_driver(struct of_platform_driver *drv, - struct bus_type *bus); -extern void of_unregister_driver(struct of_platform_driver *drv); -extern int of_device_register(struct of_device *ofdev); -extern void of_device_unregister(struct of_device *ofdev); -extern struct of_device *of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent, - struct bus_type *bus); -extern void of_release_dev(struct device *dev); +/* These are just here during the transition */ +#include <linux/of_device.h> +#include <linux/of_platform.h> #endif /* __KERNEL__ */ #endif /* _ASM_SPARC_OF_DEVICE_H */ diff --git a/include/asm-sparc/of_platform.h b/include/asm-sparc/of_platform.h new file mode 100644 index 000000000000..64a230064ef2 --- /dev/null +++ b/include/asm-sparc/of_platform.h @@ -0,0 +1,32 @@ +#ifndef _ASM_SPARC_OF_PLATFORM_H +#define _ASM_SPARC_OF_PLATFORM_H +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * Modified for Sparc by merging parts of asm-sparc/of_device.h + * by Stephen Rothwell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +/* This is just here during the transition */ +#include <linux/of_platform.h> + +extern struct bus_type ebus_bus_type; +extern struct bus_type sbus_bus_type; +extern struct bus_type of_platform_bus_type; +#define of_bus_type of_platform_bus_type /* for compatibility */ + +extern int of_register_driver(struct of_platform_driver *drv, + struct bus_type *bus); +extern void of_unregister_driver(struct of_platform_driver *drv); +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus); + +#endif /* _ASM_SPARC_OF_PLATFORM_H */ diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h index 9ea105ebe2ff..db9feb75bd86 100644 --- a/include/asm-sparc/prom.h +++ b/include/asm-sparc/prom.h @@ -2,7 +2,6 @@ #define _SPARC_PROM_H #ifdef __KERNEL__ - /* * Definitions for talking to the Open Firmware PROM on * Power Macintosh computers. @@ -17,11 +16,17 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ - #include <linux/types.h> #include <linux/proc_fs.h> #include <asm/atomic.h> +#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 +#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 + +#define of_compat_cmp(s1, s2, l) strncmp((s1), (s2), (l)) +#define of_prop_cmp(s1, s2) strcasecmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcmp((s1), (s2)) + typedef u32 phandle; typedef u32 ihandle; @@ -55,53 +60,30 @@ struct device_node { unsigned int unique_id; }; -/* flag descriptions */ -#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ - #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) -#define OF_BAD_ADDR ((u64)-1) - -static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) -{ - dn->pde = de; -} - -extern struct device_node *of_find_node_by_name(struct device_node *from, - const char *name); -#define for_each_node_by_name(dn, name) \ - for (dn = of_find_node_by_name(NULL, name); dn; \ - dn = of_find_node_by_name(dn, name)) -extern struct device_node *of_find_node_by_type(struct device_node *from, - const char *type); -#define for_each_node_by_type(dn, type) \ - for (dn = of_find_node_by_type(NULL, type); dn; \ - dn = of_find_node_by_type(dn, type)) -extern struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compat); -extern struct device_node *of_find_node_by_path(const char *path); -extern struct device_node *of_find_node_by_phandle(phandle handle); -extern struct device_node *of_get_parent(const struct device_node *node); -extern struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev); -extern struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp); -extern int of_device_is_compatible(const struct device_node *device, - const char *); -extern const void *of_get_property(const struct device_node *node, - const char *name, - int *lenp); -#define get_property(node,name,lenp) of_get_property(node,name,lenp) extern int of_set_property(struct device_node *node, const char *name, void *val, int len); extern int of_getintprop_default(struct device_node *np, const char *name, int def); -extern int of_n_addr_cells(struct device_node *np); -extern int of_n_size_cells(struct device_node *np); extern void prom_build_devicetree(void); +/* 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) +{ +} + +/* + * NB: This is here while we transition from using asm/prom.h + * to linux/of.h + */ +#include <linux/of.h> + #endif /* __KERNEL__ */ #endif /* _SPARC_PROM_H */ diff --git a/include/asm-sparc64/of_device.h b/include/asm-sparc64/of_device.h index 60e9173c9acb..46d69b3223c5 100644 --- a/include/asm-sparc64/of_device.h +++ b/include/asm-sparc64/of_device.h @@ -3,14 +3,9 @@ #ifdef __KERNEL__ #include <linux/device.h> +#include <linux/of.h> #include <linux/mod_devicetable.h> #include <asm/openprom.h> -#include <asm/prom.h> - -extern struct bus_type isa_bus_type; -extern struct bus_type ebus_bus_type; -extern struct bus_type sbus_bus_type; -extern struct bus_type of_bus_type; /* * The of_device is a kind of "base class" that is a superset of @@ -31,50 +26,13 @@ struct of_device int portid; int clock_freq; }; -#define to_of_device(d) container_of(d, struct of_device, dev) extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); -extern struct of_device *of_find_device_by_node(struct device_node *); - -extern const struct of_device_id *of_match_device( - const struct of_device_id *matches, const struct of_device *dev); - -extern struct of_device *of_dev_get(struct of_device *dev); -extern void of_dev_put(struct of_device *dev); - -/* - * An of_platform_driver driver is attached to a basic of_device on - * the ISA, EBUS, and SBUS busses on sparc64. - */ -struct of_platform_driver -{ - char *name; - struct of_device_id *match_table; - struct module *owner; - - int (*probe)(struct of_device* dev, const struct of_device_id *match); - int (*remove)(struct of_device* dev); - - int (*suspend)(struct of_device* dev, pm_message_t state); - int (*resume)(struct of_device* dev); - int (*shutdown)(struct of_device* dev); - - struct device_driver driver; -}; -#define to_of_platform_driver(drv) container_of(drv,struct of_platform_driver, driver) - -extern int of_register_driver(struct of_platform_driver *drv, - struct bus_type *bus); -extern void of_unregister_driver(struct of_platform_driver *drv); -extern int of_device_register(struct of_device *ofdev); -extern void of_device_unregister(struct of_device *ofdev); -extern struct of_device *of_platform_device_create(struct device_node *np, - const char *bus_id, - struct device *parent, - struct bus_type *bus); -extern void of_release_dev(struct device *dev); +/* These are just here during the transition */ +#include <linux/of_device.h> +#include <linux/of_platform.h> #endif /* __KERNEL__ */ #endif /* _ASM_SPARC64_OF_DEVICE_H */ diff --git a/include/asm-sparc64/of_platform.h b/include/asm-sparc64/of_platform.h new file mode 100644 index 000000000000..f7c1f17c7d52 --- /dev/null +++ b/include/asm-sparc64/of_platform.h @@ -0,0 +1,33 @@ +#ifndef _ASM_SPARC64_OF_PLATFORM_H +#define _ASM_SPARC64_OF_PLATFORM_H +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * Modified for Sparc by merging parts of asm-sparc/of_device.h + * by Stephen Rothwell + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +/* This is just here during the transition */ +#include <linux/of_platform.h> + +extern struct bus_type isa_bus_type; +extern struct bus_type ebus_bus_type; +extern struct bus_type sbus_bus_type; +extern struct bus_type of_platform_bus_type; +#define of_bus_type of_platform_bus_type /* for compatibility */ + +extern int of_register_driver(struct of_platform_driver *drv, + struct bus_type *bus); +extern void of_unregister_driver(struct of_platform_driver *drv); +extern struct of_device *of_platform_device_create(struct device_node *np, + const char *bus_id, + struct device *parent, + struct bus_type *bus); + +#endif /* _ASM_SPARC64_OF_PLATFORM_H */ diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h index b4df3042add0..2b9e0d795faf 100644 --- a/include/asm-sparc64/prom.h +++ b/include/asm-sparc64/prom.h @@ -2,7 +2,6 @@ #define _SPARC64_PROM_H #ifdef __KERNEL__ - /* * Definitions for talking to the Open Firmware PROM on * Power Macintosh computers. @@ -17,11 +16,17 @@ * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ - #include <linux/types.h> #include <linux/proc_fs.h> #include <asm/atomic.h> +#define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 +#define OF_ROOT_NODE_SIZE_CELLS_DEFAULT 1 + +#define of_compat_cmp(s1, s2, l) strncmp((s1), (s2), (l)) +#define of_prop_cmp(s1, s2) strcasecmp((s1), (s2)) +#define of_node_cmp(s1, s2) strcmp((s1), (s2)) + typedef u32 phandle; typedef u32 ihandle; @@ -63,54 +68,31 @@ struct of_irq_controller { void *data; }; -/* flag descriptions */ -#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ - #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) -#define OF_BAD_ADDR ((u64)-1) - -static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) -{ - dn->pde = de; -} - -extern struct device_node *of_find_node_by_name(struct device_node *from, - const char *name); -#define for_each_node_by_name(dn, name) \ - for (dn = of_find_node_by_name(NULL, name); dn; \ - dn = of_find_node_by_name(dn, name)) -extern struct device_node *of_find_node_by_type(struct device_node *from, - const char *type); -#define for_each_node_by_type(dn, type) \ - for (dn = of_find_node_by_type(NULL, type); dn; \ - dn = of_find_node_by_type(dn, type)) -extern struct device_node *of_find_compatible_node(struct device_node *from, - const char *type, const char *compat); -extern struct device_node *of_find_node_by_path(const char *path); -extern struct device_node *of_find_node_by_phandle(phandle handle); extern struct device_node *of_find_node_by_cpuid(int cpuid); -extern struct device_node *of_get_parent(const struct device_node *node); -extern struct device_node *of_get_next_child(const struct device_node *node, - struct device_node *prev); -extern struct property *of_find_property(const struct device_node *np, - const char *name, - int *lenp); -extern int of_device_is_compatible(const struct device_node *device, - const char *); -extern const void *of_get_property(const struct device_node *node, - const char *name, - int *lenp); -#define get_property(node,name,lenp) of_get_property(node,name,lenp) extern int of_set_property(struct device_node *node, const char *name, void *val, int len); extern int of_getintprop_default(struct device_node *np, const char *name, int def); -extern int of_n_addr_cells(struct device_node *np); -extern int of_n_size_cells(struct device_node *np); extern void prom_build_devicetree(void); +/* 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) +{ +} + +/* + * NB: This is here while we transition from using asm/prom.h + * to linux/of.h + */ +#include <linux/of.h> + #endif /* __KERNEL__ */ #endif /* _SPARC64_PROM_H */ diff --git a/include/linux/of.h b/include/linux/of.h new file mode 100644 index 000000000000..47734ffd9745 --- /dev/null +++ b/include/linux/of.h @@ -0,0 +1,61 @@ +#ifndef _LINUX_OF_H +#define _LINUX_OF_H +/* + * Definitions for talking to the Open Firmware PROM on + * Power Macintosh and other computers. + * + * Copyright (C) 1996-2005 Paul Mackerras. + * + * Updates for PPC64 by Peter Bergner & David Engebretsen, IBM Corp. + * Updates for SPARC64 by David S. Miller + * Derived from PowerPC and Sparc prom.h files by Stephen Rothwell, IBM Corp. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + */ +#include <linux/types.h> + +#include <asm/bitops.h> +#include <asm/prom.h> + +/* flag descriptions */ +#define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ +#define OF_DETACHED 2 /* node has been detached from the device tree */ + +#define OF_BAD_ADDR ((u64)-1) + +extern struct device_node *of_find_node_by_name(struct device_node *from, + const char *name); +#define for_each_node_by_name(dn, name) \ + for (dn = of_find_node_by_name(NULL, name); dn; \ + dn = of_find_node_by_name(dn, name)) +extern struct device_node *of_find_node_by_type(struct device_node *from, + const char *type); +#define for_each_node_by_type(dn, type) \ + for (dn = of_find_node_by_type(NULL, type); dn; \ + dn = of_find_node_by_type(dn, type)) +extern struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compat); +#define for_each_compatible_node(dn, type, compatible) \ + for (dn = of_find_compatible_node(NULL, type, compatible); dn; \ + dn = of_find_compatible_node(dn, type, compatible)) +extern struct device_node *of_find_node_by_path(const char *path); +extern struct device_node *of_find_node_by_phandle(phandle handle); +extern struct device_node *of_get_parent(const struct device_node *node); +extern struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev); +extern struct property *of_find_property(const struct device_node *np, + const char *name, + int *lenp); +extern int of_device_is_compatible(const struct device_node *device, + const char *); +extern const void *of_get_property(const struct device_node *node, + const char *name, + int *lenp); +#define get_property(a, b, c) of_get_property((a), (b), (c)) +extern int of_n_addr_cells(struct device_node *np); +extern int of_n_size_cells(struct device_node *np); + +#endif /* _LINUX_OF_H */ diff --git a/include/linux/of_device.h b/include/linux/of_device.h new file mode 100644 index 000000000000..91bf84b9d144 --- /dev/null +++ b/include/linux/of_device.h @@ -0,0 +1,26 @@ +#ifndef _LINUX_OF_DEVICE_H +#define _LINUX_OF_DEVICE_H +#ifdef __KERNEL__ + +#include <linux/device.h> +#include <linux/of.h> +#include <linux/mod_devicetable.h> + +#include <asm/of_device.h> + +#define to_of_device(d) container_of(d, struct of_device, dev) + +extern const struct of_device_id *of_match_node( + const struct of_device_id *matches, const struct device_node *node); +extern const struct of_device_id *of_match_device( + const struct of_device_id *matches, const struct of_device *dev); + +extern struct of_device *of_dev_get(struct of_device *dev); +extern void of_dev_put(struct of_device *dev); + +extern int of_device_register(struct of_device *ofdev); +extern void of_device_unregister(struct of_device *ofdev); +extern void of_release_dev(struct device *dev); + +#endif /* __KERNEL__ */ +#endif /* _LINUX_OF_DEVICE_H */ diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h new file mode 100644 index 000000000000..5fd44e63fb26 --- /dev/null +++ b/include/linux/of_platform.h @@ -0,0 +1,57 @@ +#ifndef _LINUX_OF_PLATFORM_H +#define _LINUX_OF_PLATFORM_H +/* + * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. + * <benh@kernel.crashing.org> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version + * 2 of the License, or (at your option) any later version. + * + */ + +#include <linux/module.h> +#include <linux/device.h> +#include <linux/mod_devicetable.h> +#include <linux/pm.h> +#include <linux/of_device.h> + +/* + * The of_platform_bus_type is a bus type used by drivers that do not + * attach to a macio or similar bus but still use OF probing + * mechanism + */ +extern struct bus_type of_platform_bus_type; + +/* + * An of_platform_driver driver is attached to a basic of_device on + * the "platform bus" (of_platform_bus_type) (or ISA, EBUS and SBUS + * busses on sparc). + */ +struct of_platform_driver +{ + char *name; + struct of_device_id *match_table; + struct module *owner; + + int (*probe)(struct of_device* dev, + const struct of_device_id *match); + int (*remove)(struct of_device* dev); + + int (*suspend)(struct of_device* dev, pm_message_t state); + int (*resume)(struct of_device* dev); + int (*shutdown)(struct of_device* dev); + + struct device_driver driver; +}; +#define to_of_platform_driver(drv) \ + container_of(drv,struct of_platform_driver, driver) + +#include <asm/of_platform.h> + +extern struct of_device *of_find_device_by_node(struct device_node *np); + +extern int of_bus_type_init(struct bus_type *bus, const char *name); + +#endif /* _LINUX_OF_PLATFORM_H */ |