diff options
author | Grant Likely <grant.likely@secretlab.ca> | 2011-06-21 12:59:34 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@secretlab.ca> | 2011-06-21 13:02:37 -0400 |
commit | 5de1540b7bc4c23470f86add1e517be41e7fefe2 (patch) | |
tree | a1c18d1ec0b7009966f114565424e9bbb31da1c1 /drivers/of/platform.c | |
parent | 29d4f8a4974aacf46b028fa92f9dd3ffdba3e614 (diff) |
drivers/amba: create devices from device tree
Add a function to create amba_devices (i.e. primecell peripherals)
from device tree nodes. The device tree scanning is done by the
of_platform_populate() function which can call of_amba_device_create
based on a match table entry.
Nodes with a "arm,primecell-periphid" property can override the h/w
peripheral id value.
Based on the original work by Jeremy Kerr.
Signed-off-by: Jeremy Kerr <jeremy.kerr@canonical.com>
Acked-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
[grant.likely: add Jeremy's original s-o-b line, changes from review
comments, and moved all code to drivers/of/platform.c]
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Diffstat (limited to 'drivers/of/platform.c')
-rw-r--r-- | drivers/of/platform.c | 71 |
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 1f4a5d3af76e..4192ddc62638 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -13,6 +13,7 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/amba/bus.h> | ||
16 | #include <linux/device.h> | 17 | #include <linux/device.h> |
17 | #include <linux/dma-mapping.h> | 18 | #include <linux/dma-mapping.h> |
18 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
@@ -217,6 +218,71 @@ struct platform_device *of_platform_device_create(struct device_node *np, | |||
217 | } | 218 | } |
218 | EXPORT_SYMBOL(of_platform_device_create); | 219 | EXPORT_SYMBOL(of_platform_device_create); |
219 | 220 | ||
221 | #ifdef CONFIG_ARM_AMBA | ||
222 | static struct amba_device *of_amba_device_create(struct device_node *node, | ||
223 | const char *bus_id, | ||
224 | void *platform_data, | ||
225 | struct device *parent) | ||
226 | { | ||
227 | struct amba_device *dev; | ||
228 | const void *prop; | ||
229 | int i, ret; | ||
230 | |||
231 | pr_debug("Creating amba device %s\n", node->full_name); | ||
232 | |||
233 | if (!of_device_is_available(node)) | ||
234 | return NULL; | ||
235 | |||
236 | dev = kzalloc(sizeof(*dev), GFP_KERNEL); | ||
237 | if (!dev) | ||
238 | return NULL; | ||
239 | |||
240 | /* setup generic device info */ | ||
241 | dev->dev.coherent_dma_mask = ~0; | ||
242 | dev->dev.of_node = of_node_get(node); | ||
243 | dev->dev.parent = parent; | ||
244 | dev->dev.platform_data = platform_data; | ||
245 | if (bus_id) | ||
246 | dev_set_name(&dev->dev, "%s", bus_id); | ||
247 | else | ||
248 | of_device_make_bus_id(&dev->dev); | ||
249 | |||
250 | /* setup amba-specific device info */ | ||
251 | dev->dma_mask = ~0; | ||
252 | |||
253 | /* Allow the HW Peripheral ID to be overridden */ | ||
254 | prop = of_get_property(node, "arm,primecell-periphid", NULL); | ||
255 | if (prop) | ||
256 | dev->periphid = of_read_ulong(prop, 1); | ||
257 | |||
258 | /* Decode the IRQs and address ranges */ | ||
259 | for (i = 0; i < AMBA_NR_IRQS; i++) | ||
260 | dev->irq[i] = irq_of_parse_and_map(node, i); | ||
261 | |||
262 | ret = of_address_to_resource(node, 0, &dev->res); | ||
263 | if (ret) | ||
264 | goto err_free; | ||
265 | |||
266 | ret = amba_device_register(dev, &iomem_resource); | ||
267 | if (ret) | ||
268 | goto err_free; | ||
269 | |||
270 | return dev; | ||
271 | |||
272 | err_free: | ||
273 | kfree(dev); | ||
274 | return NULL; | ||
275 | } | ||
276 | #else /* CONFIG_ARM_AMBA */ | ||
277 | static struct amba_device *of_amba_device_create(struct device_node *node, | ||
278 | const char *bus_id, | ||
279 | void *platform_data, | ||
280 | struct device *parent) | ||
281 | { | ||
282 | return NULL; | ||
283 | } | ||
284 | #endif /* CONFIG_ARM_AMBA */ | ||
285 | |||
220 | /** | 286 | /** |
221 | * of_platform_bus_create() - Create a device for a node and its children. | 287 | * of_platform_bus_create() - Create a device for a node and its children. |
222 | * @bus: device node of the bus to instantiate | 288 | * @bus: device node of the bus to instantiate |
@@ -242,6 +308,11 @@ static int of_platform_bus_create(struct device_node *bus, | |||
242 | return 0; | 308 | return 0; |
243 | } | 309 | } |
244 | 310 | ||
311 | if (of_device_is_compatible(bus, "arm,primecell")) { | ||
312 | of_amba_device_create(bus, NULL, NULL, parent); | ||
313 | return 0; | ||
314 | } | ||
315 | |||
245 | dev = of_platform_device_create(bus, NULL, parent); | 316 | dev = of_platform_device_create(bus, NULL, parent); |
246 | if (!dev || !of_match_node(matches, bus)) | 317 | if (!dev || !of_match_node(matches, bus)) |
247 | return 0; | 318 | return 0; |