diff options
-rw-r--r-- | Documentation/devicetree/bindings/arm/primecell.txt | 21 | ||||
-rw-r--r-- | drivers/of/platform.c | 71 |
2 files changed, 92 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/arm/primecell.txt b/Documentation/devicetree/bindings/arm/primecell.txt new file mode 100644 index 000000000000..1d5d7a870ec7 --- /dev/null +++ b/Documentation/devicetree/bindings/arm/primecell.txt | |||
@@ -0,0 +1,21 @@ | |||
1 | * ARM Primecell Peripherals | ||
2 | |||
3 | ARM, Ltd. Primecell peripherals have a standard id register that can be used to | ||
4 | identify the peripheral type, vendor, and revision. This value can be used for | ||
5 | driver matching. | ||
6 | |||
7 | Required properties: | ||
8 | |||
9 | - compatible : should be a specific value for peripheral and "arm,primecell" | ||
10 | |||
11 | Optional properties: | ||
12 | |||
13 | - arm,primecell-periphid : Value to override the h/w value with | ||
14 | |||
15 | Example: | ||
16 | |||
17 | serial@fff36000 { | ||
18 | compatible = "arm,pl011", "arm,primecell"; | ||
19 | arm,primecell-periphid = <0x00341011>; | ||
20 | }; | ||
21 | |||
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; |