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
This commit is contained in:
Linus Torvalds 2007-07-20 09:18:08 -07:00
commit 2cb7e71422
33 changed files with 846 additions and 1483 deletions

View File

@ -92,6 +92,9 @@ config ARCH_MAY_HAVE_PC_FDC
config PPC_OF config PPC_OF
def_bool y def_bool y
config OF
def_bool y
config PPC_UDBG_16550 config PPC_UDBG_16550
bool bool
default n default n

View File

@ -1,5 +1,6 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
@ -8,118 +9,6 @@
#include <asm/errno.h> #include <asm/errno.h>
#include <asm/of_device.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, ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len) char *str, ssize_t len)
{ {
@ -229,14 +118,5 @@ int of_device_uevent(struct device *dev,
return 0; 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_uevent);
EXPORT_SYMBOL(of_device_get_modalias); EXPORT_SYMBOL(of_device_get_modalias);

View File

@ -55,94 +55,14 @@ static struct of_device_id of_default_bus_ids[] = {
static atomic_t bus_no_reg_magic; 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 = { struct bus_type of_platform_bus_type = {
.name = "of_platform",
.match = of_platform_bus_match,
.uevent = of_device_uevent, .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); EXPORT_SYMBOL(of_platform_bus_type);
static int __init of_bus_driver_init(void) 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); postcore_initcall(of_bus_driver_init);

View File

@ -78,12 +78,9 @@ static struct boot_param_header *initial_boot_params __initdata;
struct boot_param_header *initial_boot_params; struct boot_param_header *initial_boot_params;
#endif #endif
static struct device_node *allnodes = NULL; extern struct device_node *allnodes; /* temporary while merging */
/* use when traversing tree through the allnext, child, sibling, extern rwlock_t devtree_lock; /* temporary while merging */
* or parent members of struct device_node.
*/
static DEFINE_RWLOCK(devtree_lock);
/* export that to outside world */ /* export that to outside world */
struct device_node *of_chosen; struct device_node *of_chosen;
@ -1056,60 +1053,6 @@ void __init early_init_devtree(void *params)
DBG(" <- early_init_devtree()\n"); 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 * Indicates whether the root node has a given value in its
@ -1140,119 +1083,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 * of_find_node_by_phandle - Find a node given a phandle
* @handle: phandle of the node to find * @handle: phandle of the node to find
@ -1297,51 +1127,6 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
} }
EXPORT_SYMBOL(of_find_all_nodes); 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 * of_node_get - Increment refcount of a node
* @node: Node to inc refcount, NULL is supported to * @node: Node to inc refcount, NULL is supported to
@ -1543,37 +1328,6 @@ static int __init prom_reconfig_setup(void)
__initcall(prom_reconfig_setup); __initcall(prom_reconfig_setup);
#endif #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 * Add a property to a node
*/ */

View File

@ -24,6 +24,9 @@ config GENERIC_ISA_DMA
config ARCH_NO_VIRT_TO_BUS config ARCH_NO_VIRT_TO_BUS
def_bool y def_bool y
config OF
def_bool y
source "init/Kconfig" source "init/Kconfig"
menu "General machine setup" menu "General machine setup"

View File

@ -1,132 +1,13 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h>
#include <asm/errno.h> #include <linux/of_device.h>
#include <asm/of_device.h> #include <linux/of_platform.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;
}
static int node_match(struct device *dev, void *data) 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 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); dp, node_match);
if (dev) 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); EXPORT_SYMBOL(of_find_device_by_node);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct bus_type ebus_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,
};
EXPORT_SYMBOL(ebus_bus_type); EXPORT_SYMBOL(ebus_bus_type);
#endif #endif
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
struct bus_type sbus_bus_type = { 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,
};
EXPORT_SYMBOL(sbus_bus_type); EXPORT_SYMBOL(sbus_bus_type);
#endif #endif
struct bus_type of_bus_type = { struct bus_type of_platform_bus_type;
.name = "of", EXPORT_SYMBOL(of_platform_bus_type);
.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);
static inline u64 of_read_addr(const u32 *cell, int size) static inline u64 of_read_addr(const u32 *cell, int size)
{ {
@ -646,7 +506,7 @@ static struct of_device * __init scan_one_device(struct device_node *dp,
build_device_resources(op, parent); build_device_resources(op, parent);
op->dev.parent = parent; op->dev.parent = parent;
op->dev.bus = &of_bus_type; op->dev.bus = &of_platform_bus_type;
if (!parent) if (!parent)
strcpy(op->dev.bus_id, "root"); strcpy(op->dev.bus_id, "root");
else else
@ -690,14 +550,14 @@ static int __init of_bus_driver_init(void)
{ {
int err; int err;
err = bus_register(&of_bus_type); err = of_bus_type_init(&of_platform_bus_type, "of");
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
if (!err) if (!err)
err = bus_register(&ebus_bus_type); err = of_bus_type_init(&ebus_bus_type, "ebus");
#endif #endif
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
if (!err) if (!err)
err = bus_register(&sbus_bus_type); err = of_bus_type_init(&sbus_bus_type, "sbus");
#endif #endif
if (!err) if (!err)
@ -735,56 +595,6 @@ void of_unregister_driver(struct of_platform_driver *drv)
driver_unregister(&drv->driver); 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, struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id, const char *bus_id,
struct device *parent, struct device *parent,
@ -810,12 +620,6 @@ struct of_device* of_platform_device_create(struct device_node *np,
return dev; return dev;
} }
EXPORT_SYMBOL(of_match_device);
EXPORT_SYMBOL(of_register_driver); EXPORT_SYMBOL(of_register_driver);
EXPORT_SYMBOL(of_unregister_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_platform_device_create);
EXPORT_SYMBOL(of_release_dev);

View File

@ -25,73 +25,9 @@
#include <asm/prom.h> #include <asm/prom.h>
#include <asm/oplib.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, extern rwlock_t devtree_lock; /* temporary while merging */
* 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);
struct device_node *of_find_node_by_phandle(phandle handle) 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); 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) int of_getintprop_default(struct device_node *np, const char *name, int def)
{ {
struct property *prop; 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); 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) int of_set_property(struct device_node *dp, const char *name, void *val, int len)
{ {
struct property **prevp; struct property **prevp;

View File

@ -354,7 +354,7 @@ static struct of_platform_driver clock_driver = {
/* Probe for the mostek real time clock chip. */ /* Probe for the mostek real time clock chip. */
static int __init clock_init(void) 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 /* Must be after subsys_initcall() so that busses are probed. Must

View File

@ -65,6 +65,9 @@ config AUDIT_ARCH
config ARCH_NO_VIRT_TO_BUS config ARCH_NO_VIRT_TO_BUS
def_bool y def_bool y
config OF
def_bool y
choice choice
prompt "Kernel page size" prompt "Kernel page size"
default SPARC64_PAGE_SIZE_8KB default SPARC64_PAGE_SIZE_8KB

View File

@ -155,7 +155,7 @@ static struct of_platform_driver auxio_driver = {
static int __init auxio_init(void) 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 /* Must be after subsys_initcall() so that busses are probed. Must

View File

@ -1,132 +1,13 @@
#include <linux/string.h> #include <linux/string.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/of.h>
#include <linux/init.h> #include <linux/init.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/errno.h>
#include <asm/errno.h> #include <linux/of_device.h>
#include <asm/of_device.h> #include <linux/of_platform.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;
}
void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name) 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 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); dp, node_match);
if (dev) 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); EXPORT_SYMBOL(of_find_device_by_node);
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
struct bus_type isa_bus_type = { 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,
};
EXPORT_SYMBOL(isa_bus_type); EXPORT_SYMBOL(isa_bus_type);
struct bus_type ebus_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,
};
EXPORT_SYMBOL(ebus_bus_type); EXPORT_SYMBOL(ebus_bus_type);
#endif #endif
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
struct bus_type sbus_bus_type = { 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,
};
EXPORT_SYMBOL(sbus_bus_type); EXPORT_SYMBOL(sbus_bus_type);
#endif #endif
struct bus_type of_bus_type = { struct bus_type of_platform_bus_type;
.name = "of", EXPORT_SYMBOL(of_platform_bus_type);
.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);
static inline u64 of_read_addr(const u32 *cell, int size) 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->irqs[i] = build_one_device_irq(op, parent, op->irqs[i]);
op->dev.parent = parent; op->dev.parent = parent;
op->dev.bus = &of_bus_type; op->dev.bus = &of_platform_bus_type;
if (!parent) if (!parent)
strcpy(op->dev.bus_id, "root"); strcpy(op->dev.bus_id, "root");
else else
@ -977,16 +830,16 @@ static int __init of_bus_driver_init(void)
{ {
int err; int err;
err = bus_register(&of_bus_type); err = of_bus_type_init(&of_platform_bus_type, "of");
#ifdef CONFIG_PCI #ifdef CONFIG_PCI
if (!err) if (!err)
err = bus_register(&isa_bus_type); err = of_bus_type_init(&isa_bus_type, "isa");
if (!err) if (!err)
err = bus_register(&ebus_bus_type); err = of_bus_type_init(&ebus_bus_type, "ebus");
#endif #endif
#ifdef CONFIG_SBUS #ifdef CONFIG_SBUS
if (!err) if (!err)
err = bus_register(&sbus_bus_type); err = of_bus_type_init(&sbus_bus_type, "sbus");
#endif #endif
if (!err) if (!err)
@ -1020,61 +873,13 @@ int of_register_driver(struct of_platform_driver *drv, struct bus_type *bus)
/* register with core */ /* register with core */
return driver_register(&drv->driver); return driver_register(&drv->driver);
} }
EXPORT_SYMBOL(of_register_driver);
void of_unregister_driver(struct of_platform_driver *drv) void of_unregister_driver(struct of_platform_driver *drv)
{ {
driver_unregister(&drv->driver); driver_unregister(&drv->driver);
} }
EXPORT_SYMBOL(of_unregister_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, struct of_device* of_platform_device_create(struct device_node *np,
const char *bus_id, const char *bus_id,
@ -1100,13 +905,4 @@ struct of_device* of_platform_device_create(struct device_node *np,
return dev; 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_platform_device_create);
EXPORT_SYMBOL(of_release_dev);

View File

@ -112,6 +112,6 @@ static struct of_platform_driver power_driver = {
void __init power_init(void) void __init power_init(void)
{ {
of_register_driver(&power_driver, &of_bus_type); of_register_driver(&power_driver, &of_platform_bus_type);
return; return;
} }

View File

@ -30,73 +30,9 @@
#include <asm/upa.h> #include <asm/upa.h>
#include <asm/smp.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, extern rwlock_t devtree_lock; /* temporary while merging */
* 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);
struct device_node *of_find_node_by_phandle(phandle handle) 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); 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) int of_getintprop_default(struct device_node *np, const char *name, int def)
{ {
struct property *prop; 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); 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) int of_set_property(struct device_node *dp, const char *name, void *val, int len)
{ {
struct property **prevp; struct property **prevp;

View File

@ -835,7 +835,7 @@ static int __init clock_init(void)
return 0; 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 /* Must be after subsys_initcall() so that busses are probed. Must

View File

@ -8,6 +8,8 @@ source "drivers/connector/Kconfig"
source "drivers/mtd/Kconfig" source "drivers/mtd/Kconfig"
source "drivers/of/Kconfig"
source "drivers/parport/Kconfig" source "drivers/parport/Kconfig"
source "drivers/pnp/Kconfig" source "drivers/pnp/Kconfig"

View File

@ -86,3 +86,4 @@ obj-$(CONFIG_GENERIC_TIME) += clocksource/
obj-$(CONFIG_DMA_ENGINE) += dma/ obj-$(CONFIG_DMA_ENGINE) += dma/
obj-$(CONFIG_HID) += hid/ obj-$(CONFIG_HID) += hid/
obj-$(CONFIG_PPC_PS3) += ps3/ obj-$(CONFIG_PPC_PS3) += ps3/
obj-$(CONFIG_OF) += of/

3
drivers/of/Kconfig Normal file
View File

@ -0,0 +1,3 @@
config OF_DEVICE
def_bool y
depends on OF && (SPARC || PPC_OF)

2
drivers/of/Makefile Normal file
View File

@ -0,0 +1,2 @@
obj-y = base.o
obj-$(CONFIG_OF_DEVICE) += device.o platform.o

275
drivers/of/base.c Normal file
View File

@ -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);

131
drivers/of/device.c Normal file
View File

@ -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);

96
drivers/of/platform.c Normal file
View File

@ -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);
}

View File

@ -3,14 +3,12 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/device.h> #include <linux/device.h>
#include <linux/mod_devicetable.h> #include <linux/of.h>
#include <asm/prom.h>
/* /*
* The of_device is a kind of "base class" that is a superset of * 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 * struct device for use by devices attached to an OF node and
* probed using OF properties * probed using OF properties.
*/ */
struct of_device struct of_device
{ {
@ -18,24 +16,14 @@ struct of_device
u64 dma_mask; /* DMA mask */ u64 dma_mask; /* DMA mask */
struct device dev; /* Generic device interface */ 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, extern ssize_t of_device_get_modalias(struct of_device *ofdev,
char *str, ssize_t len); char *str, ssize_t len);
extern int of_device_uevent(struct device *dev, extern int of_device_uevent(struct device *dev,
char **envp, int num_envp, char *buffer, int buffer_size); 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 /* __KERNEL__ */
#endif /* _ASM_POWERPC_OF_DEVICE_H */ #endif /* _ASM_POWERPC_OF_DEVICE_H */

View File

@ -1,3 +1,5 @@
#ifndef _ASM_POWERPC_OF_PLATFORM_H
#define _ASM_POWERPC_OF_PLATFORM_H
/* /*
* Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp. * Copyright (C) 2006 Benjamin Herrenschmidt, IBM Corp.
* <benh@kernel.crashing.org> * <benh@kernel.crashing.org>
@ -9,37 +11,8 @@
* *
*/ */
#include <asm/of_device.h> /* This is just here during the transition */
#include <linux/of_platform.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)
/* Platform drivers register/unregister */ /* Platform drivers register/unregister */
extern int of_register_platform_driver(struct of_platform_driver *drv); 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 of_device_id *matches,
struct device *parent); 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); extern struct of_device *of_find_device_by_phandle(phandle ph);
#endif /* _ASM_POWERPC_OF_PLATFORM_H */

View File

@ -21,6 +21,13 @@
#include <asm/irq.h> #include <asm/irq.h>
#include <asm/atomic.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 */ /* Definitions used by the flattened device tree */
#define OF_DT_HEADER 0xd00dfeed /* marker */ #define OF_DT_HEADER 0xd00dfeed /* marker */
#define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */ #define OF_DT_BEGIN_NODE 0x1 /* Start of node, full name */
@ -97,10 +104,6 @@ struct device_node {
extern struct device_node *of_chosen; 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) static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
{ {
return test_bit(flag, &n->_flags); 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_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 struct device_node *of_node_get(struct device_node *node);
extern void of_node_put(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 finish_device_tree(void);
extern void unflatten_device_tree(void); extern void unflatten_device_tree(void);
extern void early_init_devtree(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)) #define device_is_compatible(d, c) of_device_is_compatible((d), (c))
extern int machine_is_compatible(const char *compat); 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 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 int prom_n_intr_cells(struct device_node* np);
extern void prom_get_irq_senses(unsigned char *senses, int off, int max); 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); 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 /* 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); extern u64 of_translate_address(struct device_node *np, const u32 *addr);
/* Extract an address from a device, returns the region size and /* 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); 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 /* __KERNEL__ */
#endif /* _POWERPC_PROM_H */ #endif /* _POWERPC_PROM_H */

View File

@ -3,13 +3,9 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/device.h> #include <linux/device.h>
#include <linux/of.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <asm/openprom.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 * The of_device is a kind of "base class" that is a superset of
@ -30,50 +26,13 @@ struct of_device
int portid; int portid;
int clock_freq; 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 __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 void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
extern struct of_device *of_find_device_by_node(struct device_node *); /* These are just here during the transition */
#include <linux/of_device.h>
extern const struct of_device_id *of_match_device( #include <linux/of_platform.h>
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);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_SPARC_OF_DEVICE_H */ #endif /* _ASM_SPARC_OF_DEVICE_H */

View File

@ -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 */

View File

@ -2,7 +2,6 @@
#define _SPARC_PROM_H #define _SPARC_PROM_H
#ifdef __KERNEL__ #ifdef __KERNEL__
/* /*
* Definitions for talking to the Open Firmware PROM on * Definitions for talking to the Open Firmware PROM on
* Power Macintosh computers. * Power Macintosh computers.
@ -17,11 +16,17 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <asm/atomic.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 phandle;
typedef u32 ihandle; typedef u32 ihandle;
@ -55,53 +60,30 @@ struct device_node {
unsigned int unique_id; 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_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
#define OF_MARK_DYNAMIC(x) set_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_set_property(struct device_node *node, const char *name, void *val, int len);
extern int of_getintprop_default(struct device_node *np, extern int of_getintprop_default(struct device_node *np,
const char *name, const char *name,
int def); 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); 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 /* __KERNEL__ */
#endif /* _SPARC_PROM_H */ #endif /* _SPARC_PROM_H */

View File

@ -3,14 +3,9 @@
#ifdef __KERNEL__ #ifdef __KERNEL__
#include <linux/device.h> #include <linux/device.h>
#include <linux/of.h>
#include <linux/mod_devicetable.h> #include <linux/mod_devicetable.h>
#include <asm/openprom.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 * The of_device is a kind of "base class" that is a superset of
@ -31,50 +26,13 @@ struct of_device
int portid; int portid;
int clock_freq; 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 __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 void of_iounmap(struct resource *res, void __iomem *base, unsigned long size);
extern struct of_device *of_find_device_by_node(struct device_node *); /* These are just here during the transition */
#include <linux/of_device.h>
extern const struct of_device_id *of_match_device( #include <linux/of_platform.h>
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);
#endif /* __KERNEL__ */ #endif /* __KERNEL__ */
#endif /* _ASM_SPARC64_OF_DEVICE_H */ #endif /* _ASM_SPARC64_OF_DEVICE_H */

View File

@ -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 */

View File

@ -2,7 +2,6 @@
#define _SPARC64_PROM_H #define _SPARC64_PROM_H
#ifdef __KERNEL__ #ifdef __KERNEL__
/* /*
* Definitions for talking to the Open Firmware PROM on * Definitions for talking to the Open Firmware PROM on
* Power Macintosh computers. * Power Macintosh computers.
@ -17,11 +16,17 @@
* as published by the Free Software Foundation; either version * as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version. * 2 of the License, or (at your option) any later version.
*/ */
#include <linux/types.h> #include <linux/types.h>
#include <linux/proc_fs.h> #include <linux/proc_fs.h>
#include <asm/atomic.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 phandle;
typedef u32 ihandle; typedef u32 ihandle;
@ -63,54 +68,31 @@ struct of_irq_controller {
void *data; 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_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
#define OF_MARK_DYNAMIC(x) set_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_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_set_property(struct device_node *node, const char *name, void *val, int len);
extern int of_getintprop_default(struct device_node *np, extern int of_getintprop_default(struct device_node *np,
const char *name, const char *name,
int def); 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); 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 /* __KERNEL__ */
#endif /* _SPARC64_PROM_H */ #endif /* _SPARC64_PROM_H */

61
include/linux/of.h Normal file
View File

@ -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 */

26
include/linux/of_device.h Normal file
View File

@ -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 */

View File

@ -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 */