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@xxxxxxxxxxxx> --- drivers/base/platform.c | 69 ++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 66 insertions(+), 3 deletions(-) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 9e9227e..8d64605 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -930,6 +930,56 @@ struct bus_type platform_bus_type = { }; EXPORT_SYMBOL_GPL(platform_bus_type); +static struct notifier_block platform_of_notifier; + +static int of_platform_notify(struct notifier_block *nb, + unsigned long action, void *arg) +{ + struct device_node *dn; + struct platform_device *pdev_parent, *pdev; + + if (action == OF_RECONFIG_DYNAMIC_CREATE_DEV) { + + dn = arg; + + /* verify that the parent is a bus */ + if (!of_match_node(of_default_bus_match_table, dn->parent)) + return NOTIFY_OK; /* not for us */ + + /* pdev_parent may be NULL when no bus platform device */ + pdev_parent = of_find_device_by_node(dn->parent); + pdev = of_platform_device_create(dn, NULL, + pdev_parent ? &pdev_parent->dev : NULL); + of_dev_put(pdev_parent); + + if (pdev == NULL) { + pr_err("%s: failed to create for '%s'\n", + __func__, dn->full_name); + /* of_platform_device_create tosses the error code */ + return notifier_from_errno(-EINVAL); + } + + } else if (action == OF_RECONFIG_DYNAMIC_DESTROY_DEV) { + + dn = arg; + + /* find our device by node */ + pdev = of_find_device_by_node(dn); + if (pdev == NULL) + return NOTIFY_OK; /* no? not meant for us */ + + /* unregister takes one ref away */ + platform_device_unregister(pdev); + + /* and put the reference of the find */ + of_dev_put(pdev); + + } else + return NOTIFY_OK; + + return NOTIFY_STOP; +} + int __init platform_bus_init(void) { int error; @@ -938,10 +988,23 @@ int __init platform_bus_init(void) error = device_register(&platform_bus); if (error) - return error; - error = bus_register(&platform_bus_type); + goto err_out; + + error = bus_register(&platform_bus_type); + if (error) + goto err_unreg_dev; + + platform_of_notifier.notifier_call = of_platform_notify; + error = of_reconfig_notifier_register(&platform_of_notifier); if (error) - device_unregister(&platform_bus); + goto err_unreg_bus; + + return 0; +err_unreg_bus: + bus_unregister(&platform_bus_type); +err_unreg_dev: + device_unregister(&platform_bus); +err_out: return error; } -- 1.7.12 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html