aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/i2c/i2c-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/i2c/i2c-core.c')
-rw-r--r--drivers/i2c/i2c-core.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 229a89e84b0f..39d25a8cb1ad 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -24,6 +24,7 @@
24 (c) 2013 Wolfram Sang <wsa@the-dreams.de> 24 (c) 2013 Wolfram Sang <wsa@the-dreams.de>
25 I2C ACPI code Copyright (C) 2014 Intel Corp 25 I2C ACPI code Copyright (C) 2014 Intel Corp
26 Author: Lan Tianyu <tianyu.lan@intel.com> 26 Author: Lan Tianyu <tianyu.lan@intel.com>
27 I2C slave support (c) 2014 by Wolfram Sang <wsa@sang-engineering.com>
27 */ 28 */
28 29
29#include <linux/module.h> 30#include <linux/module.h>
@@ -261,7 +262,7 @@ acpi_i2c_space_handler(u32 function, acpi_physical_address command,
261 struct acpi_resource *ares; 262 struct acpi_resource *ares;
262 u32 accessor_type = function >> 16; 263 u32 accessor_type = function >> 16;
263 u8 action = function & ACPI_IO_MASK; 264 u8 action = function & ACPI_IO_MASK;
264 acpi_status ret = AE_OK; 265 acpi_status ret;
265 int status; 266 int status;
266 267
267 ret = acpi_buffer_to_resource(info->connection, info->length, &ares); 268 ret = acpi_buffer_to_resource(info->connection, info->length, &ares);
@@ -628,6 +629,17 @@ static int i2c_device_probe(struct device *dev)
628 if (!client) 629 if (!client)
629 return 0; 630 return 0;
630 631
632 if (!client->irq && dev->of_node) {
633 int irq = of_irq_get(dev->of_node, 0);
634
635 if (irq == -EPROBE_DEFER)
636 return irq;
637 if (irq < 0)
638 irq = 0;
639
640 client->irq = irq;
641 }
642
631 driver = to_i2c_driver(dev->driver); 643 driver = to_i2c_driver(dev->driver);
632 if (!driver->probe || !driver->id_table) 644 if (!driver->probe || !driver->id_table)
633 return -ENODEV; 645 return -ENODEV;
@@ -1401,7 +1413,6 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
1401 return ERR_PTR(-EINVAL); 1413 return ERR_PTR(-EINVAL);
1402 } 1414 }
1403 1415
1404 info.irq = irq_of_parse_and_map(node, 0);
1405 info.of_node = of_node_get(node); 1416 info.of_node = of_node_get(node);
1406 info.archdata = &dev_ad; 1417 info.archdata = &dev_ad;
1407 1418
@@ -1415,7 +1426,6 @@ static struct i2c_client *of_i2c_register_device(struct i2c_adapter *adap,
1415 dev_err(&adap->dev, "of_i2c: Failure registering %s\n", 1426 dev_err(&adap->dev, "of_i2c: Failure registering %s\n",
1416 node->full_name); 1427 node->full_name);
1417 of_node_put(node); 1428 of_node_put(node);
1418 irq_dispose_mapping(info.irq);
1419 return ERR_PTR(-EINVAL); 1429 return ERR_PTR(-EINVAL);
1420 } 1430 }
1421 return result; 1431 return result;
@@ -2962,6 +2972,54 @@ trace:
2962} 2972}
2963EXPORT_SYMBOL(i2c_smbus_xfer); 2973EXPORT_SYMBOL(i2c_smbus_xfer);
2964 2974
2975int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
2976{
2977 int ret;
2978
2979 if (!client || !slave_cb)
2980 return -EINVAL;
2981
2982 if (!(client->flags & I2C_CLIENT_TEN)) {
2983 /* Enforce stricter address checking */
2984 ret = i2c_check_addr_validity(client->addr);
2985 if (ret)
2986 return ret;
2987 }
2988
2989 if (!client->adapter->algo->reg_slave)
2990 return -EOPNOTSUPP;
2991
2992 client->slave_cb = slave_cb;
2993
2994 i2c_lock_adapter(client->adapter);
2995 ret = client->adapter->algo->reg_slave(client);
2996 i2c_unlock_adapter(client->adapter);
2997
2998 if (ret)
2999 client->slave_cb = NULL;
3000
3001 return ret;
3002}
3003EXPORT_SYMBOL_GPL(i2c_slave_register);
3004
3005int i2c_slave_unregister(struct i2c_client *client)
3006{
3007 int ret;
3008
3009 if (!client->adapter->algo->unreg_slave)
3010 return -EOPNOTSUPP;
3011
3012 i2c_lock_adapter(client->adapter);
3013 ret = client->adapter->algo->unreg_slave(client);
3014 i2c_unlock_adapter(client->adapter);
3015
3016 if (ret == 0)
3017 client->slave_cb = NULL;
3018
3019 return ret;
3020}
3021EXPORT_SYMBOL_GPL(i2c_slave_unregister);
3022
2965MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); 3023MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
2966MODULE_DESCRIPTION("I2C-Bus main module"); 3024MODULE_DESCRIPTION("I2C-Bus main module");
2967MODULE_LICENSE("GPL"); 3025MODULE_LICENSE("GPL");