diff options
| author | Pantelis Antoniou <pantelis.antoniou@konsulko.com> | 2014-10-28 16:36:01 -0400 |
|---|---|---|
| committer | Grant Likely <grant.likely@linaro.org> | 2014-11-24 17:25:06 -0500 |
| commit | 801d728c10db4b28e01590b46bf1f0df930760cc (patch) | |
| tree | 152e49c3417aa84cb204faefb50f0e0c23eb1867 | |
| parent | f5242e5a883bf1c1aba6bfd87b85e7dda0e62191 (diff) | |
of/reconfig: Add OF_DYNAMIC notifier for platform_bus_type
Add OF notifier handler needed for creating/destroying platform devices
according to dynamic runtime changes in the DT live tree.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Grant Likely <grant.likely@linaro.org>
| -rw-r--r-- | drivers/base/platform.c | 1 | ||||
| -rw-r--r-- | drivers/of/platform.c | 55 | ||||
| -rw-r--r-- | include/linux/of_platform.h | 6 |
3 files changed, 62 insertions, 0 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index b2afc29403f9..233ececd15a3 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
| @@ -1006,6 +1006,7 @@ int __init platform_bus_init(void) | |||
| 1006 | error = bus_register(&platform_bus_type); | 1006 | error = bus_register(&platform_bus_type); |
| 1007 | if (error) | 1007 | if (error) |
| 1008 | device_unregister(&platform_bus); | 1008 | device_unregister(&platform_bus); |
| 1009 | of_platform_register_reconfig_notifier(); | ||
| 1009 | return error; | 1010 | return error; |
| 1010 | } | 1011 | } |
| 1011 | 1012 | ||
diff --git a/drivers/of/platform.c b/drivers/of/platform.c index 656cccf0e680..cd87a36495be 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c | |||
| @@ -550,4 +550,59 @@ void of_platform_depopulate(struct device *parent) | |||
| 550 | } | 550 | } |
| 551 | EXPORT_SYMBOL_GPL(of_platform_depopulate); | 551 | EXPORT_SYMBOL_GPL(of_platform_depopulate); |
| 552 | 552 | ||
| 553 | #ifdef CONFIG_OF_DYNAMIC | ||
| 554 | static int of_platform_notify(struct notifier_block *nb, | ||
| 555 | unsigned long action, void *arg) | ||
| 556 | { | ||
| 557 | struct of_reconfig_data *rd = arg; | ||
| 558 | struct platform_device *pdev_parent, *pdev; | ||
| 559 | bool children_left; | ||
| 560 | |||
| 561 | switch (of_reconfig_get_state_change(action, rd)) { | ||
| 562 | case OF_RECONFIG_CHANGE_ADD: | ||
| 563 | /* verify that the parent is a bus */ | ||
| 564 | if (!of_node_check_flag(rd->dn->parent, OF_POPULATED_BUS)) | ||
| 565 | return NOTIFY_OK; /* not for us */ | ||
| 566 | |||
| 567 | /* pdev_parent may be NULL when no bus platform device */ | ||
| 568 | pdev_parent = of_find_device_by_node(rd->dn->parent); | ||
| 569 | pdev = of_platform_device_create(rd->dn, NULL, | ||
| 570 | pdev_parent ? &pdev_parent->dev : NULL); | ||
| 571 | of_dev_put(pdev_parent); | ||
| 572 | |||
| 573 | if (pdev == NULL) { | ||
| 574 | pr_err("%s: failed to create for '%s'\n", | ||
| 575 | __func__, rd->dn->full_name); | ||
| 576 | /* of_platform_device_create tosses the error code */ | ||
| 577 | return notifier_from_errno(-EINVAL); | ||
| 578 | } | ||
| 579 | break; | ||
| 580 | |||
| 581 | case OF_RECONFIG_CHANGE_REMOVE: | ||
| 582 | /* find our device by node */ | ||
| 583 | pdev = of_find_device_by_node(rd->dn); | ||
| 584 | if (pdev == NULL) | ||
| 585 | return NOTIFY_OK; /* no? not meant for us */ | ||
| 586 | |||
| 587 | /* unregister takes one ref away */ | ||
| 588 | of_platform_device_destroy(&pdev->dev, &children_left); | ||
| 589 | |||
| 590 | /* and put the reference of the find */ | ||
| 591 | of_dev_put(pdev); | ||
| 592 | break; | ||
| 593 | } | ||
| 594 | |||
| 595 | return NOTIFY_OK; | ||
| 596 | } | ||
| 597 | |||
| 598 | static struct notifier_block platform_of_notifier = { | ||
| 599 | .notifier_call = of_platform_notify, | ||
| 600 | }; | ||
| 601 | |||
| 602 | void of_platform_register_reconfig_notifier(void) | ||
| 603 | { | ||
| 604 | WARN_ON(of_reconfig_notifier_register(&platform_of_notifier)); | ||
| 605 | } | ||
| 606 | #endif /* CONFIG_OF_DYNAMIC */ | ||
| 607 | |||
| 553 | #endif /* CONFIG_OF_ADDRESS */ | 608 | #endif /* CONFIG_OF_ADDRESS */ |
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h index c2b0627a2317..8a860f096c35 100644 --- a/include/linux/of_platform.h +++ b/include/linux/of_platform.h | |||
| @@ -84,4 +84,10 @@ static inline int of_platform_populate(struct device_node *root, | |||
| 84 | static inline void of_platform_depopulate(struct device *parent) { } | 84 | static inline void of_platform_depopulate(struct device *parent) { } |
| 85 | #endif | 85 | #endif |
| 86 | 86 | ||
| 87 | #ifdef CONFIG_OF_DYNAMIC | ||
| 88 | extern void of_platform_register_reconfig_notifier(void); | ||
| 89 | #else | ||
| 90 | static inline void of_platform_register_reconfig_notifier(void) { } | ||
| 91 | #endif | ||
| 92 | |||
| 87 | #endif /* _LINUX_OF_PLATFORM_H */ | 93 | #endif /* _LINUX_OF_PLATFORM_H */ |
