[RFC PATCH] drivers/amba: probe via device tree reworked
Grant Likely
grant.likely at secretlab.ca
Thu May 19 04:47:53 EST 2011
On Wed, May 18, 2011 at 01:14:47PM -0500, Rob Herring wrote:
> From: Rob Herring <rob.herring at calxeda.com>
>
> This reworks the original amba bus device tree probing to be more inline with
> how platform bus probing via device tree is done using a match table.
You should also mention that this patch builds on the code currently
in devicetree/test on git://git.secretlab.ca/git/linux-2.6. Otherwise
people will be very confused about what this applies to.
> The amba bus code doesn't support creation of parent devices, so a flat tree
> is created even if the device tree contains a heirarchy of devices.
Hmmm, why do you say this? The code doesn't currently set the parent
pointer, but nothing prevents a caller of amba_device_register() from
setting the parent pointer before it is registered. I also don't see
anything in the amba bus code that assume it must all be flat in the
driver model. What bit am I missing?
> Cc: Jeremy Kerr <jeremy.kerr at canonical.com>
> Cc: Grant Likely <grant.likely at secretlab.ca>
> Signed-off-by: Rob Herring <rob.herring at calxeda.com>
> ---
> drivers/amba/bus.c | 84 +++++++++++++++++++++++++++++++++++++++++-----
> include/linux/amba/bus.h | 4 ++-
> 2 files changed, 78 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
> index ed5c49d..4e46b54 100644
> --- a/drivers/amba/bus.c
> +++ b/drivers/amba/bus.c
> @@ -7,6 +7,7 @@
> * it under the terms of the GNU General Public License version 2 as
> * published by the Free Software Foundation.
> */
> +#define DEBUG
I assume this was left in by accident.
> #include <linux/module.h>
> #include <linux/init.h>
> #include <linux/device.h>
> @@ -797,7 +798,7 @@ EXPORT_SYMBOL(amba_request_regions);
> EXPORT_SYMBOL(amba_release_regions);
>
> #ifdef CONFIG_OF
> -static int of_amba_device_create(struct device_node *node,struct device *parent)
> +static struct amba_device *of_amba_device_create(struct device_node *node,struct device *parent)
> {
> struct amba_device *dev;
> const void *prop;
> @@ -805,7 +806,7 @@ static int of_amba_device_create(struct device_node *node,struct device *parent)
>
> dev = kzalloc(sizeof(*dev), GFP_KERNEL);
> if (!dev)
> - return -ENOMEM;
> + return NULL;
>
> /* setup generic device info */
> dev->dev.coherent_dma_mask = ~0;
> @@ -839,22 +840,87 @@ static int of_amba_device_create(struct device_node *node,struct device *parent)
> "probed value (0x%08x) don't agree.",
> of_read_ulong(prop, 1), dev->periphid);
>
> - return 0;
> + return dev;
>
> err_free:
> kfree(dev);
> - return ret;
> + return NULL;
> +}
> +
> +/**
> + * of_amba_bus_create() - Create a device for a node and its children.
> + * @bus: device node of the bus to instantiate
> + * @matches: match table for bus nodes
> + * disallow recursive creation of child buses
> + * @parent: parent for new device, or NULL for top level.
> + *
> + * Recursively create devices for all the child nodes.
> + */
> +static int of_amba_bus_create(struct device_node *bus,
> + const struct of_device_id *matches,
> + struct device *parent, bool strict)
> +{
> + struct device_node *child;
> + struct amba_device *dev = NULL;
> + int rc = 0;
> +
> + /* Make sure it has a compatible property */
> + if (strict && (!of_get_property(bus, "compatible", NULL))) {
> + pr_debug("%s() - skipping %s, no compatible prop\n",
> + __func__, bus->full_name);
> + return 0;
> + }
The whole 'strict' thing was to work around some poor ideas originally
implemented in the powerpc version. Don't duplicate that logic, just
assume strict is always true...`
> +
> + if (of_device_is_compatible(bus, "arm,amba-device"))
> + dev = of_amba_device_create(bus, parent);
The AMBA bus itself should be a platform_device, and should be the
parent for all the child nodes.
> + else if (!of_match_node(matches, bus))
> + return 0;
> +
> + for_each_child_of_node(bus, child) {
> + pr_debug(" create child: %s\n", child->full_name);
> + rc = of_amba_bus_create(child, matches, parent, strict);
> + if (rc) {
> + of_node_put(child);
> + break;
> + }
> + }
> + return rc;
> }
>
> -void of_amba_bus_populate(struct device_node *node, struct device *parent)
> +/**
> + * of_amba_bus_probe() - Probe the device-tree for amba buses
> + * @root: parent of the first level to probe or NULL for the root of the tree
> + * @matches: match table for bus nodes
> + * @parent: parent to hook devices from, NULL for toplevel
> + *
> + * Note that children of the provided root are not instantiated as devices
> + * unless the specified root itself matches the bus list and is not NULL.
> + */
> +int of_amba_bus_probe(struct device_node *root,
> + const struct of_device_id *matches,
> + struct device *parent)
Don't follow the of_platform_bus_probe() pattern. It's subtly broken
(or at least confusing). Follow the of_platform_populate()
pattern instead (in devicetree/test, and has been posted to the list).
> {
> + int rc = 0;
> struct device_node *child;
>
> - for_each_child_of_node(node, child) {
> - if (of_device_is_compatible(child, "arm,amba-device"))
> - of_amba_device_create(child, parent);
> + root = root ? of_node_get(root) : of_find_node_by_path("/");
> + if (!root)
> + return -EINVAL;
> +
> + /* Do a self check of bus type, if there's a match, create children */
> + if (of_match_node(matches, root)) {
> + rc = of_amba_bus_create(root, matches, parent, false);
> + } else for_each_child_of_node(root, child) {
> + if (!of_match_node(matches, child))
> + continue;
> + rc = of_amba_bus_create(child, matches, parent, false);
> + if (rc)
> + break;
> }
> +
> + of_node_put(root);
> + return rc;
> }
> -EXPORT_SYMBOL(of_amba_bus_populate);
> +EXPORT_SYMBOL(of_amba_bus_probe);
>
> #endif /* CONFIG_OF */
> diff --git a/include/linux/amba/bus.h b/include/linux/amba/bus.h
> index cb17dfd..6df9535 100644
> --- a/include/linux/amba/bus.h
> +++ b/include/linux/amba/bus.h
> @@ -96,7 +96,9 @@ void amba_release_regions(struct amba_device *);
>
> #ifdef CONFIG_OF
> struct device_node;
> -void of_amba_bus_populate(struct device_node *node, struct device *parent);
> +int of_amba_bus_probe(struct device_node *root,
> + const struct of_device_id *matches,
> + struct device *parent);
> #endif
>
> #endif
> --
> 1.7.4.1
>
More information about the devicetree-discuss
mailing list