aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/platform.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/platform.c')
-rw-r--r--drivers/of/platform.c196
1 files changed, 187 insertions, 9 deletions
diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 63d3cb73bdb..e75af391e28 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>
@@ -22,6 +23,14 @@
22#include <linux/of_platform.h> 23#include <linux/of_platform.h>
23#include <linux/platform_device.h> 24#include <linux/platform_device.h>
24 25
26const struct of_device_id of_default_bus_match_table[] = {
27 { .compatible = "simple-bus", },
28#ifdef CONFIG_ARM_AMBA
29 { .compatible = "arm,amba-bus", },
30#endif /* CONFIG_ARM_AMBA */
31 {} /* Empty terminated list */
32};
33
25static int of_dev_node_match(struct device *dev, void *data) 34static int of_dev_node_match(struct device *dev, void *data)
26{ 35{
27 return dev->of_node == data; 36 return dev->of_node == data;
@@ -168,17 +177,20 @@ struct platform_device *of_device_alloc(struct device_node *np,
168EXPORT_SYMBOL(of_device_alloc); 177EXPORT_SYMBOL(of_device_alloc);
169 178
170/** 179/**
171 * of_platform_device_create - Alloc, initialize and register an of_device 180 * of_platform_device_create_pdata - Alloc, initialize and register an of_device
172 * @np: pointer to node to create device for 181 * @np: pointer to node to create device for
173 * @bus_id: name to assign device 182 * @bus_id: name to assign device
183 * @platform_data: pointer to populate platform_data pointer with
174 * @parent: Linux device model parent device. 184 * @parent: Linux device model parent device.
175 * 185 *
176 * Returns pointer to created platform device, or NULL if a device was not 186 * Returns pointer to created platform device, or NULL if a device was not
177 * registered. Unavailable devices will not get registered. 187 * registered. Unavailable devices will not get registered.
178 */ 188 */
179struct platform_device *of_platform_device_create(struct device_node *np, 189struct platform_device *of_platform_device_create_pdata(
180 const char *bus_id, 190 struct device_node *np,
181 struct device *parent) 191 const char *bus_id,
192 void *platform_data,
193 struct device *parent)
182{ 194{
183 struct platform_device *dev; 195 struct platform_device *dev;
184 196
@@ -194,6 +206,7 @@ struct platform_device *of_platform_device_create(struct device_node *np,
194#endif 206#endif
195 dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); 207 dev->dev.coherent_dma_mask = DMA_BIT_MASK(32);
196 dev->dev.bus = &platform_bus_type; 208 dev->dev.bus = &platform_bus_type;
209 dev->dev.platform_data = platform_data;
197 210
198 /* We do not fill the DMA ops for platform devices by default. 211 /* We do not fill the DMA ops for platform devices by default.
199 * This is currently the responsibility of the platform code 212 * This is currently the responsibility of the platform code
@@ -207,8 +220,111 @@ struct platform_device *of_platform_device_create(struct device_node *np,
207 220
208 return dev; 221 return dev;
209} 222}
223
224/**
225 * of_platform_device_create - Alloc, initialize and register an of_device
226 * @np: pointer to node to create device for
227 * @bus_id: name to assign device
228 * @parent: Linux device model parent device.
229 *
230 * Returns pointer to created platform device, or NULL if a device was not
231 * registered. Unavailable devices will not get registered.
232 */
233struct platform_device *of_platform_device_create(struct device_node *np,
234 const char *bus_id,
235 struct device *parent)
236{
237 return of_platform_device_create_pdata(np, bus_id, NULL, parent);
238}
210EXPORT_SYMBOL(of_platform_device_create); 239EXPORT_SYMBOL(of_platform_device_create);
211 240
241#ifdef CONFIG_ARM_AMBA
242static struct amba_device *of_amba_device_create(struct device_node *node,
243 const char *bus_id,
244 void *platform_data,
245 struct device *parent)
246{
247 struct amba_device *dev;
248 const void *prop;
249 int i, ret;
250
251 pr_debug("Creating amba device %s\n", node->full_name);
252
253 if (!of_device_is_available(node))
254 return NULL;
255
256 dev = kzalloc(sizeof(*dev), GFP_KERNEL);
257 if (!dev)
258 return NULL;
259
260 /* setup generic device info */
261 dev->dev.coherent_dma_mask = ~0;
262 dev->dev.of_node = of_node_get(node);
263 dev->dev.parent = parent;
264 dev->dev.platform_data = platform_data;
265 if (bus_id)
266 dev_set_name(&dev->dev, "%s", bus_id);
267 else
268 of_device_make_bus_id(&dev->dev);
269
270 /* setup amba-specific device info */
271 dev->dma_mask = ~0;
272
273 /* Allow the HW Peripheral ID to be overridden */
274 prop = of_get_property(node, "arm,primecell-periphid", NULL);
275 if (prop)
276 dev->periphid = of_read_ulong(prop, 1);
277
278 /* Decode the IRQs and address ranges */
279 for (i = 0; i < AMBA_NR_IRQS; i++)
280 dev->irq[i] = irq_of_parse_and_map(node, i);
281
282 ret = of_address_to_resource(node, 0, &dev->res);
283 if (ret)
284 goto err_free;
285
286 ret = amba_device_register(dev, &iomem_resource);
287 if (ret)
288 goto err_free;
289
290 return dev;
291
292err_free:
293 kfree(dev);
294 return NULL;
295}
296#else /* CONFIG_ARM_AMBA */
297static struct amba_device *of_amba_device_create(struct device_node *node,
298 const char *bus_id,
299 void *platform_data,
300 struct device *parent)
301{
302 return NULL;
303}
304#endif /* CONFIG_ARM_AMBA */
305
306/**
307 * of_devname_lookup() - Given a device node, lookup the preferred Linux name
308 */
309static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *lookup,
310 struct device_node *np)
311{
312 struct resource res;
313 if (lookup) {
314 for(; lookup->name != NULL; lookup++) {
315 if (!of_device_is_compatible(np, lookup->compatible))
316 continue;
317 if (of_address_to_resource(np, 0, &res))
318 continue;
319 if (res.start != lookup->phys_addr)
320 continue;
321 pr_debug("%s: devname=%s\n", np->full_name, lookup->name);
322 return lookup;
323 }
324 }
325 return NULL;
326}
327
212/** 328/**
213 * of_platform_bus_create() - Create a device for a node and its children. 329 * of_platform_bus_create() - Create a device for a node and its children.
214 * @bus: device node of the bus to instantiate 330 * @bus: device node of the bus to instantiate
@@ -221,19 +337,41 @@ EXPORT_SYMBOL(of_platform_device_create);
221 */ 337 */
222static int of_platform_bus_create(struct device_node *bus, 338static int of_platform_bus_create(struct device_node *bus,
223 const struct of_device_id *matches, 339 const struct of_device_id *matches,
224 struct device *parent) 340 const struct of_dev_auxdata *lookup,
341 struct device *parent, bool strict)
225{ 342{
343 const struct of_dev_auxdata *auxdata;
226 struct device_node *child; 344 struct device_node *child;
227 struct platform_device *dev; 345 struct platform_device *dev;
346 const char *bus_id = NULL;
347 void *platform_data = NULL;
228 int rc = 0; 348 int rc = 0;
229 349
230 dev = of_platform_device_create(bus, NULL, parent); 350 /* Make sure it has a compatible property */
351 if (strict && (!of_get_property(bus, "compatible", NULL))) {
352 pr_debug("%s() - skipping %s, no compatible prop\n",
353 __func__, bus->full_name);
354 return 0;
355 }
356
357 auxdata = of_dev_lookup(lookup, bus);
358 if (auxdata) {
359 bus_id = auxdata->name;
360 platform_data = auxdata->platform_data;
361 }
362
363 if (of_device_is_compatible(bus, "arm,primecell")) {
364 of_amba_device_create(bus, bus_id, platform_data, parent);
365 return 0;
366 }
367
368 dev = of_platform_device_create_pdata(bus, bus_id, platform_data, parent);
231 if (!dev || !of_match_node(matches, bus)) 369 if (!dev || !of_match_node(matches, bus))
232 return 0; 370 return 0;
233 371
234 for_each_child_of_node(bus, child) { 372 for_each_child_of_node(bus, child) {
235 pr_debug(" create child: %s\n", child->full_name); 373 pr_debug(" create child: %s\n", child->full_name);
236 rc = of_platform_bus_create(child, matches, &dev->dev); 374 rc = of_platform_bus_create(child, matches, lookup, &dev->dev, strict);
237 if (rc) { 375 if (rc) {
238 of_node_put(child); 376 of_node_put(child);
239 break; 377 break;
@@ -267,11 +405,11 @@ int of_platform_bus_probe(struct device_node *root,
267 405
268 /* Do a self check of bus type, if there's a match, create children */ 406 /* Do a self check of bus type, if there's a match, create children */
269 if (of_match_node(matches, root)) { 407 if (of_match_node(matches, root)) {
270 rc = of_platform_bus_create(root, matches, parent); 408 rc = of_platform_bus_create(root, matches, NULL, parent, false);
271 } else for_each_child_of_node(root, child) { 409 } else for_each_child_of_node(root, child) {
272 if (!of_match_node(matches, child)) 410 if (!of_match_node(matches, child))
273 continue; 411 continue;
274 rc = of_platform_bus_create(child, matches, parent); 412 rc = of_platform_bus_create(child, matches, NULL, parent, false);
275 if (rc) 413 if (rc)
276 break; 414 break;
277 } 415 }
@@ -280,4 +418,44 @@ int of_platform_bus_probe(struct device_node *root,
280 return rc; 418 return rc;
281} 419}
282EXPORT_SYMBOL(of_platform_bus_probe); 420EXPORT_SYMBOL(of_platform_bus_probe);
421
422/**
423 * of_platform_populate() - Populate platform_devices from device tree data
424 * @root: parent of the first level to probe or NULL for the root of the tree
425 * @matches: match table, NULL to use the default
426 * @parent: parent to hook devices from, NULL for toplevel
427 *
428 * Similar to of_platform_bus_probe(), this function walks the device tree
429 * and creates devices from nodes. It differs in that it follows the modern
430 * convention of requiring all device nodes to have a 'compatible' property,
431 * and it is suitable for creating devices which are children of the root
432 * node (of_platform_bus_probe will only create children of the root which
433 * are selected by the @matches argument).
434 *
435 * New board support should be using this function instead of
436 * of_platform_bus_probe().
437 *
438 * Returns 0 on success, < 0 on failure.
439 */
440int of_platform_populate(struct device_node *root,
441 const struct of_device_id *matches,
442 const struct of_dev_auxdata *lookup,
443 struct device *parent)
444{
445 struct device_node *child;
446 int rc = 0;
447
448 root = root ? of_node_get(root) : of_find_node_by_path("/");
449 if (!root)
450 return -EINVAL;
451
452 for_each_child_of_node(root, child) {
453 rc = of_platform_bus_create(child, matches, lookup, parent, true);
454 if (rc)
455 break;
456 }
457
458 of_node_put(root);
459 return rc;
460}
283#endif /* !CONFIG_SPARC */ 461#endif /* !CONFIG_SPARC */