diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/platform.c | 143 |
1 files changed, 143 insertions, 0 deletions
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 7dacc1ebe91e..d9c81e93bdd0 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/module.h> | 15 | #include <linux/module.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/dma-mapping.h> | ||
17 | #include <linux/of_device.h> | 18 | #include <linux/of_device.h> |
18 | #include <linux/of_platform.h> | 19 | #include <linux/of_platform.h> |
19 | 20 | ||
@@ -396,3 +397,145 @@ void of_unregister_driver(struct of_platform_driver *drv) | |||
396 | driver_unregister(&drv->driver); | 397 | driver_unregister(&drv->driver); |
397 | } | 398 | } |
398 | EXPORT_SYMBOL(of_unregister_driver); | 399 | EXPORT_SYMBOL(of_unregister_driver); |
400 | |||
401 | #if !defined(CONFIG_SPARC) | ||
402 | /* | ||
403 | * The following routines scan a subtree and registers a device for | ||
404 | * each applicable node. | ||
405 | * | ||
406 | * Note: sparc doesn't use these routines because it has a different | ||
407 | * mechanism for creating devices from device tree nodes. | ||
408 | */ | ||
409 | |||
410 | /** | ||
411 | * of_platform_device_create - Alloc, initialize and register an of_device | ||
412 | * @np: pointer to node to create device for | ||
413 | * @bus_id: name to assign device | ||
414 | * @parent: Linux device model parent device. | ||
415 | */ | ||
416 | struct of_device *of_platform_device_create(struct device_node *np, | ||
417 | const char *bus_id, | ||
418 | struct device *parent) | ||
419 | { | ||
420 | struct of_device *dev; | ||
421 | |||
422 | dev = of_device_alloc(np, bus_id, parent); | ||
423 | if (!dev) | ||
424 | return NULL; | ||
425 | |||
426 | dev->archdata.dma_mask = 0xffffffffUL; | ||
427 | dev->dev.coherent_dma_mask = DMA_BIT_MASK(32); | ||
428 | dev->dev.bus = &of_platform_bus_type; | ||
429 | |||
430 | /* We do not fill the DMA ops for platform devices by default. | ||
431 | * This is currently the responsibility of the platform code | ||
432 | * to do such, possibly using a device notifier | ||
433 | */ | ||
434 | |||
435 | if (of_device_register(dev) != 0) { | ||
436 | of_device_free(dev); | ||
437 | return NULL; | ||
438 | } | ||
439 | |||
440 | return dev; | ||
441 | } | ||
442 | EXPORT_SYMBOL(of_platform_device_create); | ||
443 | |||
444 | /** | ||
445 | * of_platform_bus_create - Create an OF device for a bus node and all its | ||
446 | * children. Optionally recursively instantiate matching busses. | ||
447 | * @bus: device node of the bus to instantiate | ||
448 | * @matches: match table, NULL to use the default, OF_NO_DEEP_PROBE to | ||
449 | * disallow recursive creation of child busses | ||
450 | */ | ||
451 | static int of_platform_bus_create(const struct device_node *bus, | ||
452 | const struct of_device_id *matches, | ||
453 | struct device *parent) | ||
454 | { | ||
455 | struct device_node *child; | ||
456 | struct of_device *dev; | ||
457 | int rc = 0; | ||
458 | |||
459 | for_each_child_of_node(bus, child) { | ||
460 | pr_debug(" create child: %s\n", child->full_name); | ||
461 | dev = of_platform_device_create(child, NULL, parent); | ||
462 | if (dev == NULL) | ||
463 | rc = -ENOMEM; | ||
464 | else if (!of_match_node(matches, child)) | ||
465 | continue; | ||
466 | if (rc == 0) { | ||
467 | pr_debug(" and sub busses\n"); | ||
468 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
469 | } | ||
470 | if (rc) { | ||
471 | of_node_put(child); | ||
472 | break; | ||
473 | } | ||
474 | } | ||
475 | return rc; | ||
476 | } | ||
477 | |||
478 | /** | ||
479 | * of_platform_bus_probe - Probe the device-tree for platform busses | ||
480 | * @root: parent of the first level to probe or NULL for the root of the tree | ||
481 | * @matches: match table, NULL to use the default | ||
482 | * @parent: parent to hook devices from, NULL for toplevel | ||
483 | * | ||
484 | * Note that children of the provided root are not instantiated as devices | ||
485 | * unless the specified root itself matches the bus list and is not NULL. | ||
486 | */ | ||
487 | int of_platform_bus_probe(struct device_node *root, | ||
488 | const struct of_device_id *matches, | ||
489 | struct device *parent) | ||
490 | { | ||
491 | struct device_node *child; | ||
492 | struct of_device *dev; | ||
493 | int rc = 0; | ||
494 | |||
495 | if (matches == NULL) | ||
496 | matches = of_default_bus_ids; | ||
497 | if (matches == OF_NO_DEEP_PROBE) | ||
498 | return -EINVAL; | ||
499 | if (root == NULL) | ||
500 | root = of_find_node_by_path("/"); | ||
501 | else | ||
502 | of_node_get(root); | ||
503 | |||
504 | pr_debug("of_platform_bus_probe()\n"); | ||
505 | pr_debug(" starting at: %s\n", root->full_name); | ||
506 | |||
507 | /* Do a self check of bus type, if there's a match, create | ||
508 | * children | ||
509 | */ | ||
510 | if (of_match_node(matches, root)) { | ||
511 | pr_debug(" root match, create all sub devices\n"); | ||
512 | dev = of_platform_device_create(root, NULL, parent); | ||
513 | if (dev == NULL) { | ||
514 | rc = -ENOMEM; | ||
515 | goto bail; | ||
516 | } | ||
517 | pr_debug(" create all sub busses\n"); | ||
518 | rc = of_platform_bus_create(root, matches, &dev->dev); | ||
519 | goto bail; | ||
520 | } | ||
521 | for_each_child_of_node(root, child) { | ||
522 | if (!of_match_node(matches, child)) | ||
523 | continue; | ||
524 | |||
525 | pr_debug(" match: %s\n", child->full_name); | ||
526 | dev = of_platform_device_create(child, NULL, parent); | ||
527 | if (dev == NULL) | ||
528 | rc = -ENOMEM; | ||
529 | else | ||
530 | rc = of_platform_bus_create(child, matches, &dev->dev); | ||
531 | if (rc) { | ||
532 | of_node_put(child); | ||
533 | break; | ||
534 | } | ||
535 | } | ||
536 | bail: | ||
537 | of_node_put(root); | ||
538 | return rc; | ||
539 | } | ||
540 | EXPORT_SYMBOL(of_platform_bus_probe); | ||
541 | #endif /* !CONFIG_SPARC */ | ||