|
|
@@ -1951,6 +1951,52 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
|
|
|
}
|
|
|
EXPORT_SYMBOL(i2c_clients_command);
|
|
|
|
|
|
+#if IS_ENABLED(CONFIG_OF_DYNAMIC)
|
|
|
+static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
|
|
|
+ void *arg)
|
|
|
+{
|
|
|
+ struct of_reconfig_data *rd = arg;
|
|
|
+ struct i2c_adapter *adap;
|
|
|
+ struct i2c_client *client;
|
|
|
+
|
|
|
+ switch (of_reconfig_get_state_change(action, rd)) {
|
|
|
+ case OF_RECONFIG_CHANGE_ADD:
|
|
|
+ adap = of_find_i2c_adapter_by_node(rd->dn->parent);
|
|
|
+ if (adap == NULL)
|
|
|
+ return NOTIFY_OK; /* not for us */
|
|
|
+
|
|
|
+ client = of_i2c_register_device(adap, rd->dn);
|
|
|
+ put_device(&adap->dev);
|
|
|
+
|
|
|
+ if (IS_ERR(client)) {
|
|
|
+ pr_err("%s: failed to create for '%s'\n",
|
|
|
+ __func__, rd->dn->full_name);
|
|
|
+ return notifier_from_errno(PTR_ERR(client));
|
|
|
+ }
|
|
|
+ break;
|
|
|
+ case OF_RECONFIG_CHANGE_REMOVE:
|
|
|
+ /* find our device by node */
|
|
|
+ client = of_find_i2c_device_by_node(rd->dn);
|
|
|
+ if (client == NULL)
|
|
|
+ return NOTIFY_OK; /* no? not meant for us */
|
|
|
+
|
|
|
+ /* unregister takes one ref away */
|
|
|
+ i2c_unregister_device(client);
|
|
|
+
|
|
|
+ /* and put the reference of the find */
|
|
|
+ put_device(&client->dev);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+
|
|
|
+ return NOTIFY_OK;
|
|
|
+}
|
|
|
+static struct notifier_block i2c_of_notifier = {
|
|
|
+ .notifier_call = of_i2c_notify,
|
|
|
+};
|
|
|
+#else
|
|
|
+extern struct notifier_block i2c_of_notifier;
|
|
|
+#endif /* CONFIG_OF_DYNAMIC */
|
|
|
+
|
|
|
static int __init i2c_init(void)
|
|
|
{
|
|
|
int retval;
|
|
|
@@ -1968,6 +2014,10 @@ static int __init i2c_init(void)
|
|
|
retval = i2c_add_driver(&dummy_driver);
|
|
|
if (retval)
|
|
|
goto class_err;
|
|
|
+
|
|
|
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
|
|
|
+ WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier));
|
|
|
+
|
|
|
return 0;
|
|
|
|
|
|
class_err:
|
|
|
@@ -1981,6 +2031,8 @@ static int __init i2c_init(void)
|
|
|
|
|
|
static void __exit i2c_exit(void)
|
|
|
{
|
|
|
+ if (IS_ENABLED(CONFIG_OF_DYNAMIC))
|
|
|
+ WARN_ON(of_reconfig_notifier_unregister(&i2c_of_notifier));
|
|
|
i2c_del_driver(&dummy_driver);
|
|
|
#ifdef CONFIG_I2C_COMPAT
|
|
|
class_compat_unregister(i2c_adapter_compat_class);
|