aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWolfram Sang <wsa+renesas@sang-engineering.com>2014-11-18 11:04:53 -0500
committerWolfram Sang <wsa@the-dreams.de>2014-12-11 16:25:53 -0500
commit4b1acc43331d6c716c331a61477660dc20c8b59c (patch)
treebf4138594b8e48384972f56c499c895ec9fe0de5
parent40ed1b4caf76e27807a49d42a41f43e8393a7607 (diff)
i2c: core changes for slave support
Finally(!), make Linux support being an I2C slave. Most of the existing infrastructure is reused. We mainly add i2c_slave_register/unregister() calls which tells i2c bus drivers to activate the slave mode. Then, they also get a callback to report slave events to. Signed-off-by: Wolfram Sang <wsa+renesas@sang-engineering.com> Signed-off-by: Wolfram Sang <wsa@the-dreams.de>
-rw-r--r--drivers/i2c/i2c-core.c49
-rw-r--r--include/linux/i2c.h29
2 files changed, 78 insertions, 0 deletions
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index 3105bd273f70..c09d06bf4d9b 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>
@@ -2911,6 +2912,54 @@ trace:
2911} 2912}
2912EXPORT_SYMBOL(i2c_smbus_xfer); 2913EXPORT_SYMBOL(i2c_smbus_xfer);
2913 2914
2915int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb)
2916{
2917 int ret;
2918
2919 if (!client || !slave_cb)
2920 return -EINVAL;
2921
2922 if (!(client->flags & I2C_CLIENT_TEN)) {
2923 /* Enforce stricter address checking */
2924 ret = i2c_check_addr_validity(client->addr);
2925 if (ret)
2926 return ret;
2927 }
2928
2929 if (!client->adapter->algo->reg_slave)
2930 return -EOPNOTSUPP;
2931
2932 client->slave_cb = slave_cb;
2933
2934 i2c_lock_adapter(client->adapter);
2935 ret = client->adapter->algo->reg_slave(client);
2936 i2c_unlock_adapter(client->adapter);
2937
2938 if (ret)
2939 client->slave_cb = NULL;
2940
2941 return ret;
2942}
2943EXPORT_SYMBOL_GPL(i2c_slave_register);
2944
2945int i2c_slave_unregister(struct i2c_client *client)
2946{
2947 int ret;
2948
2949 if (!client->adapter->algo->unreg_slave)
2950 return -EOPNOTSUPP;
2951
2952 i2c_lock_adapter(client->adapter);
2953 ret = client->adapter->algo->unreg_slave(client);
2954 i2c_unlock_adapter(client->adapter);
2955
2956 if (ret == 0)
2957 client->slave_cb = NULL;
2958
2959 return ret;
2960}
2961EXPORT_SYMBOL_GPL(i2c_slave_unregister);
2962
2914MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); 2963MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>");
2915MODULE_DESCRIPTION("I2C-Bus main module"); 2964MODULE_DESCRIPTION("I2C-Bus main module");
2916MODULE_LICENSE("GPL"); 2965MODULE_LICENSE("GPL");
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index b556e0ab946f..a720d9921b47 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -46,6 +46,8 @@ struct i2c_client;
46struct i2c_driver; 46struct i2c_driver;
47union i2c_smbus_data; 47union i2c_smbus_data;
48struct i2c_board_info; 48struct i2c_board_info;
49enum i2c_slave_event;
50typedef int (*i2c_slave_cb_t)(struct i2c_client *, enum i2c_slave_event, u8 *);
49 51
50struct module; 52struct module;
51 53
@@ -209,6 +211,8 @@ struct i2c_driver {
209 * @irq: indicates the IRQ generated by this device (if any) 211 * @irq: indicates the IRQ generated by this device (if any)
210 * @detected: member of an i2c_driver.clients list or i2c-core's 212 * @detected: member of an i2c_driver.clients list or i2c-core's
211 * userspace_devices list 213 * userspace_devices list
214 * @slave_cb: Callback when I2C slave mode of an adapter is used. The adapter
215 * calls it to pass on slave events to the slave driver.
212 * 216 *
213 * An i2c_client identifies a single device (i.e. chip) connected to an 217 * An i2c_client identifies a single device (i.e. chip) connected to an
214 * i2c bus. The behaviour exposed to Linux is defined by the driver 218 * i2c bus. The behaviour exposed to Linux is defined by the driver
@@ -224,6 +228,7 @@ struct i2c_client {
224 struct device dev; /* the device structure */ 228 struct device dev; /* the device structure */
225 int irq; /* irq issued by device */ 229 int irq; /* irq issued by device */
226 struct list_head detected; 230 struct list_head detected;
231 i2c_slave_cb_t slave_cb; /* callback for slave mode */
227}; 232};
228#define to_i2c_client(d) container_of(d, struct i2c_client, dev) 233#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
229 234
@@ -246,6 +251,25 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
246 dev_set_drvdata(&dev->dev, data); 251 dev_set_drvdata(&dev->dev, data);
247} 252}
248 253
254/* I2C slave support */
255
256enum i2c_slave_event {
257 I2C_SLAVE_REQ_READ_START,
258 I2C_SLAVE_REQ_READ_END,
259 I2C_SLAVE_REQ_WRITE_START,
260 I2C_SLAVE_REQ_WRITE_END,
261 I2C_SLAVE_STOP,
262};
263
264extern int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb);
265extern int i2c_slave_unregister(struct i2c_client *client);
266
267static inline int i2c_slave_event(struct i2c_client *client,
268 enum i2c_slave_event event, u8 *val)
269{
270 return client->slave_cb(client, event, val);
271}
272
249/** 273/**
250 * struct i2c_board_info - template for device creation 274 * struct i2c_board_info - template for device creation
251 * @type: chip type, to initialize i2c_client.name 275 * @type: chip type, to initialize i2c_client.name
@@ -352,6 +376,8 @@ i2c_register_board_info(int busnum, struct i2c_board_info const *info,
352 * into I2C transfers instead. 376 * into I2C transfers instead.
353 * @functionality: Return the flags that this algorithm/adapter pair supports 377 * @functionality: Return the flags that this algorithm/adapter pair supports
354 * from the I2C_FUNC_* flags. 378 * from the I2C_FUNC_* flags.
379 * @reg_slave: Register given client to I2C slave mode of this adapter
380 * @unreg_slave: Unregister given client from I2C slave mode of this adapter
355 * 381 *
356 * The following structs are for those who like to implement new bus drivers: 382 * The following structs are for those who like to implement new bus drivers:
357 * i2c_algorithm is the interface to a class of hardware solutions which can 383 * i2c_algorithm is the interface to a class of hardware solutions which can
@@ -377,6 +403,9 @@ struct i2c_algorithm {
377 403
378 /* To determine what the adapter supports */ 404 /* To determine what the adapter supports */
379 u32 (*functionality) (struct i2c_adapter *); 405 u32 (*functionality) (struct i2c_adapter *);
406
407 int (*reg_slave)(struct i2c_client *client);
408 int (*unreg_slave)(struct i2c_client *client);
380}; 409};
381 410
382/** 411/**