[POWERPC] ibmebus: Add device creation and bus probing based on of_device
The devtree root is now searched for devices matching a built-in whitelist during boot, so these devices appear on the bus from the beginning. It is still possible to manually add/remove devices to/from the bus by using the probe/remove sysfs interface. Also, when a device driver registers itself, the devtree is matched against its matchlist. Signed-off-by: Joachim Fenkes <fenkes@de.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
This commit is contained in:
parent
a988c0a627
commit
55347cc996
@ -51,6 +51,13 @@ static struct device ibmebus_bus_device = { /* fake "parent" device */
|
|||||||
|
|
||||||
struct bus_type ibmebus_bus_type;
|
struct bus_type ibmebus_bus_type;
|
||||||
|
|
||||||
|
/* These devices will automatically be added to the bus during init */
|
||||||
|
static struct of_device_id builtin_matches[] = {
|
||||||
|
{ .compatible = "IBM,lhca" },
|
||||||
|
{ .compatible = "IBM,lhea" },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
static void *ibmebus_alloc_coherent(struct device *dev,
|
static void *ibmebus_alloc_coherent(struct device *dev,
|
||||||
size_t size,
|
size_t size,
|
||||||
dma_addr_t *dma_handle,
|
dma_addr_t *dma_handle,
|
||||||
@ -125,6 +132,67 @@ static struct dma_mapping_ops ibmebus_dma_ops = {
|
|||||||
.dma_supported = ibmebus_dma_supported,
|
.dma_supported = ibmebus_dma_supported,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static int ibmebus_match_path(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
struct device_node *dn = to_of_device(dev)->node;
|
||||||
|
return (dn->full_name &&
|
||||||
|
(strcasecmp((char *)data, dn->full_name) == 0));
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ibmebus_match_node(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
return to_of_device(dev)->node == data;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ibmebus_create_device(struct device_node *dn)
|
||||||
|
{
|
||||||
|
struct of_device *dev;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
dev = of_device_alloc(dn, NULL, &ibmebus_bus_device);
|
||||||
|
if (!dev)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev->dev.bus = &ibmebus_bus_type;
|
||||||
|
dev->dev.archdata.dma_ops = &ibmebus_dma_ops;
|
||||||
|
|
||||||
|
ret = of_device_register(dev);
|
||||||
|
if (ret) {
|
||||||
|
of_device_free(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ibmebus_create_devices(const struct of_device_id *matches)
|
||||||
|
{
|
||||||
|
struct device_node *root, *child;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
root = of_find_node_by_path("/");
|
||||||
|
|
||||||
|
for (child = NULL; (child = of_get_next_child(root, child)); ) {
|
||||||
|
if (!of_match_node(matches, child))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (bus_find_device(&ibmebus_bus_type, NULL, child,
|
||||||
|
ibmebus_match_node))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ret = ibmebus_create_device(child);
|
||||||
|
if (ret) {
|
||||||
|
printk(KERN_ERR "%s: failed to create device (%i)",
|
||||||
|
__FUNCTION__, ret);
|
||||||
|
of_node_put(child);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
of_node_put(root);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
int ibmebus_register_driver(struct ibmebus_driver *drv)
|
int ibmebus_register_driver(struct ibmebus_driver *drv)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -173,18 +241,6 @@ static struct device_attribute ibmebus_dev_attrs[] = {
|
|||||||
__ATTR_NULL
|
__ATTR_NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
static int ibmebus_match_path(struct device *dev, void *data)
|
|
||||||
{
|
|
||||||
int rc;
|
|
||||||
struct device_node *dn =
|
|
||||||
of_node_get(to_ibmebus_dev(dev)->ofdev.node);
|
|
||||||
|
|
||||||
rc = (dn->full_name && (strcasecmp((char*)data, dn->full_name) == 0));
|
|
||||||
|
|
||||||
of_node_put(dn);
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *ibmebus_chomp(const char *in, size_t count)
|
static char *ibmebus_chomp(const char *in, size_t count)
|
||||||
{
|
{
|
||||||
char *out = kmalloc(count + 1, GFP_KERNEL);
|
char *out = kmalloc(count + 1, GFP_KERNEL);
|
||||||
@ -204,9 +260,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
|
|||||||
const char *buf, size_t count)
|
const char *buf, size_t count)
|
||||||
{
|
{
|
||||||
struct device_node *dn = NULL;
|
struct device_node *dn = NULL;
|
||||||
struct ibmebus_dev *dev;
|
|
||||||
char *path;
|
char *path;
|
||||||
ssize_t rc;
|
ssize_t rc = 0;
|
||||||
|
|
||||||
path = ibmebus_chomp(buf, count);
|
path = ibmebus_chomp(buf, count);
|
||||||
if (!path)
|
if (!path)
|
||||||
@ -221,9 +276,8 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if ((dn = of_find_node_by_path(path))) {
|
if ((dn = of_find_node_by_path(path))) {
|
||||||
/* dev = ibmebus_register_device_node(dn); */
|
rc = ibmebus_create_device(dn);
|
||||||
of_node_put(dn);
|
of_node_put(dn);
|
||||||
rc = IS_ERR(dev) ? PTR_ERR(dev) : count;
|
|
||||||
} else {
|
} else {
|
||||||
printk(KERN_WARNING "%s: no such device node: %s\n",
|
printk(KERN_WARNING "%s: no such device node: %s\n",
|
||||||
__FUNCTION__, path);
|
__FUNCTION__, path);
|
||||||
@ -232,7 +286,9 @@ static ssize_t ibmebus_store_probe(struct bus_type *bus,
|
|||||||
|
|
||||||
out:
|
out:
|
||||||
kfree(path);
|
kfree(path);
|
||||||
return rc;
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t ibmebus_store_remove(struct bus_type *bus,
|
static ssize_t ibmebus_store_remove(struct bus_type *bus,
|
||||||
@ -247,7 +303,7 @@ static ssize_t ibmebus_store_remove(struct bus_type *bus,
|
|||||||
|
|
||||||
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
|
if ((dev = bus_find_device(&ibmebus_bus_type, NULL, path,
|
||||||
ibmebus_match_path))) {
|
ibmebus_match_path))) {
|
||||||
/* ibmebus_unregister_device(dev); */
|
of_device_unregister(to_of_device(dev));
|
||||||
|
|
||||||
kfree(path);
|
kfree(path);
|
||||||
return count;
|
return count;
|
||||||
@ -267,6 +323,7 @@ static struct bus_attribute ibmebus_bus_attrs[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct bus_type ibmebus_bus_type = {
|
struct bus_type ibmebus_bus_type = {
|
||||||
|
.uevent = of_device_uevent,
|
||||||
.dev_attrs = ibmebus_dev_attrs,
|
.dev_attrs = ibmebus_dev_attrs,
|
||||||
.bus_attrs = ibmebus_bus_attrs
|
.bus_attrs = ibmebus_bus_attrs
|
||||||
};
|
};
|
||||||
@ -294,6 +351,13 @@ static int __init ibmebus_bus_init(void)
|
|||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
err = ibmebus_create_devices(builtin_matches);
|
||||||
|
if (err) {
|
||||||
|
device_unregister(&ibmebus_bus_device);
|
||||||
|
bus_unregister(&ibmebus_bus_type);
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
postcore_initcall(ibmebus_bus_init);
|
postcore_initcall(ibmebus_bus_init);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user