aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPantelis Antoniou <pantelis.antoniou@konsulko.com>2014-10-28 16:36:03 -0400
committerGrant Likely <grant.likely@linaro.org>2014-11-25 10:35:35 -0500
commitea7513bbc04170f1cbf42953187a4d8b731c71c4 (patch)
treeeae2d5fe9a96b50e45c447249b82f55983df8094
parenta430a3455f2c48995e06b359a82a1109a419e9ef (diff)
i2c/of: Add OF_RECONFIG notifier handler
CONFIG_OF_DYNAMIC enables runtime changes to the device tree which in turn may trigger addition or removal of devices from Linux. Add an OF_RECONFIG notifier handler to receive tree change events and to creating or destroy i2c devices as required. Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com> [grant.likely: clean up #ifdefs and drop unneeded error handling] Signed-off-by: Grant Likely <grant.likely@linaro.org> Reviewed-by: Wolfram Sang <wsa@the-dreams.de> Cc: Rob Herring <robh+dt@kernel.org> Cc: linux-i2c@vger.kernel.org
-rw-r--r--drivers/i2c/i2c-core.c52
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 15ba6185dba5..d8afd3f28ca4 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1951,6 +1951,52 @@ void i2c_clients_command(struct i2c_adapter *adap, unsigned int cmd, void *arg)
1951} 1951}
1952EXPORT_SYMBOL(i2c_clients_command); 1952EXPORT_SYMBOL(i2c_clients_command);
1953 1953
1954#if IS_ENABLED(CONFIG_OF_DYNAMIC)
1955static int of_i2c_notify(struct notifier_block *nb, unsigned long action,
1956 void *arg)
1957{
1958 struct of_reconfig_data *rd = arg;
1959 struct i2c_adapter *adap;
1960 struct i2c_client *client;
1961
1962 switch (of_reconfig_get_state_change(action, rd)) {
1963 case OF_RECONFIG_CHANGE_ADD:
1964 adap = of_find_i2c_adapter_by_node(rd->dn->parent);
1965 if (adap == NULL)
1966 return NOTIFY_OK; /* not for us */
1967
1968 client = of_i2c_register_device(adap, rd->dn);
1969 put_device(&adap->dev);
1970
1971 if (IS_ERR(client)) {
1972 pr_err("%s: failed to create for '%s'\n",
1973 __func__, rd->dn->full_name);
1974 return notifier_from_errno(PTR_ERR(client));
1975 }
1976 break;
1977 case OF_RECONFIG_CHANGE_REMOVE:
1978 /* find our device by node */
1979 client = of_find_i2c_device_by_node(rd->dn);
1980 if (client == NULL)
1981 return NOTIFY_OK; /* no? not meant for us */
1982
1983 /* unregister takes one ref away */
1984 i2c_unregister_device(client);
1985
1986 /* and put the reference of the find */
1987 put_device(&client->dev);
1988 break;
1989 }
1990
1991 return NOTIFY_OK;
1992}
1993static struct notifier_block i2c_of_notifier = {
1994 .notifier_call = of_i2c_notify,
1995};
1996#else
1997extern struct notifier_block i2c_of_notifier;
1998#endif /* CONFIG_OF_DYNAMIC */
1999
1954static int __init i2c_init(void) 2000static int __init i2c_init(void)
1955{ 2001{
1956 int retval; 2002 int retval;
@@ -1968,6 +2014,10 @@ static int __init i2c_init(void)
1968 retval = i2c_add_driver(&dummy_driver); 2014 retval = i2c_add_driver(&dummy_driver);
1969 if (retval) 2015 if (retval)
1970 goto class_err; 2016 goto class_err;
2017
2018 if (IS_ENABLED(CONFIG_OF_DYNAMIC))
2019 WARN_ON(of_reconfig_notifier_register(&i2c_of_notifier));
2020
1971 return 0; 2021 return 0;
1972 2022
1973class_err: 2023class_err:
@@ -1981,6 +2031,8 @@ bus_err:
1981 2031
1982static void __exit i2c_exit(void) 2032static void __exit i2c_exit(void)
1983{ 2033{
2034 if (IS_ENABLED(CONFIG_OF_DYNAMIC))
2035 WARN_ON(of_reconfig_notifier_unregister(&i2c_of_notifier));
1984 i2c_del_driver(&dummy_driver); 2036 i2c_del_driver(&dummy_driver);
1985#ifdef CONFIG_I2C_COMPAT 2037#ifdef CONFIG_I2C_COMPAT
1986 class_compat_unregister(i2c_adapter_compat_class); 2038 class_compat_unregister(i2c_adapter_compat_class);