Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Wolfram Sang and committed by
Wolfram Sang
4b1acc43 40ed1b4c

+78
+49
drivers/i2c/i2c-core.c
··· 24 24 (c) 2013 Wolfram Sang <wsa@the-dreams.de> 25 25 I2C ACPI code Copyright (C) 2014 Intel Corp 26 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 30 #include <linux/module.h> ··· 2911 2910 return res; 2912 2911 } 2913 2912 EXPORT_SYMBOL(i2c_smbus_xfer); 2913 + 2914 + int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb) 2915 + { 2916 + int ret; 2917 + 2918 + if (!client || !slave_cb) 2919 + return -EINVAL; 2920 + 2921 + if (!(client->flags & I2C_CLIENT_TEN)) { 2922 + /* Enforce stricter address checking */ 2923 + ret = i2c_check_addr_validity(client->addr); 2924 + if (ret) 2925 + return ret; 2926 + } 2927 + 2928 + if (!client->adapter->algo->reg_slave) 2929 + return -EOPNOTSUPP; 2930 + 2931 + client->slave_cb = slave_cb; 2932 + 2933 + i2c_lock_adapter(client->adapter); 2934 + ret = client->adapter->algo->reg_slave(client); 2935 + i2c_unlock_adapter(client->adapter); 2936 + 2937 + if (ret) 2938 + client->slave_cb = NULL; 2939 + 2940 + return ret; 2941 + } 2942 + EXPORT_SYMBOL_GPL(i2c_slave_register); 2943 + 2944 + int i2c_slave_unregister(struct i2c_client *client) 2945 + { 2946 + int ret; 2947 + 2948 + if (!client->adapter->algo->unreg_slave) 2949 + return -EOPNOTSUPP; 2950 + 2951 + i2c_lock_adapter(client->adapter); 2952 + ret = client->adapter->algo->unreg_slave(client); 2953 + i2c_unlock_adapter(client->adapter); 2954 + 2955 + if (ret == 0) 2956 + client->slave_cb = NULL; 2957 + 2958 + return ret; 2959 + } 2960 + EXPORT_SYMBOL_GPL(i2c_slave_unregister); 2914 2961 2915 2962 MODULE_AUTHOR("Simon G. Vogl <simon@tk.uni-linz.ac.at>"); 2916 2963 MODULE_DESCRIPTION("I2C-Bus main module");
+29
include/linux/i2c.h
··· 46 46 struct i2c_driver; 47 47 union i2c_smbus_data; 48 48 struct i2c_board_info; 49 + enum i2c_slave_event; 50 + typedef int (*i2c_slave_cb_t)(struct i2c_client *, enum i2c_slave_event, u8 *); 49 51 50 52 struct module; 51 53 ··· 211 209 * @irq: indicates the IRQ generated by this device (if any) 212 210 * @detected: member of an i2c_driver.clients list or i2c-core's 213 211 * userspace_devices list 212 + * @slave_cb: Callback when I2C slave mode of an adapter is used. The adapter 213 + * calls it to pass on slave events to the slave driver. 214 214 * 215 215 * An i2c_client identifies a single device (i.e. chip) connected to an 216 216 * i2c bus. The behaviour exposed to Linux is defined by the driver ··· 228 224 struct device dev; /* the device structure */ 229 225 int irq; /* irq issued by device */ 230 226 struct list_head detected; 227 + i2c_slave_cb_t slave_cb; /* callback for slave mode */ 231 228 }; 232 229 #define to_i2c_client(d) container_of(d, struct i2c_client, dev) 233 230 ··· 249 244 static inline void i2c_set_clientdata(struct i2c_client *dev, void *data) 250 245 { 251 246 dev_set_drvdata(&dev->dev, data); 247 + } 248 + 249 + /* I2C slave support */ 250 + 251 + enum i2c_slave_event { 252 + I2C_SLAVE_REQ_READ_START, 253 + I2C_SLAVE_REQ_READ_END, 254 + I2C_SLAVE_REQ_WRITE_START, 255 + I2C_SLAVE_REQ_WRITE_END, 256 + I2C_SLAVE_STOP, 257 + }; 258 + 259 + extern int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb); 260 + extern int i2c_slave_unregister(struct i2c_client *client); 261 + 262 + static inline int i2c_slave_event(struct i2c_client *client, 263 + enum i2c_slave_event event, u8 *val) 264 + { 265 + return client->slave_cb(client, event, val); 252 266 } 253 267 254 268 /** ··· 376 352 * into I2C transfers instead. 377 353 * @functionality: Return the flags that this algorithm/adapter pair supports 378 354 * from the I2C_FUNC_* flags. 355 + * @reg_slave: Register given client to I2C slave mode of this adapter 356 + * @unreg_slave: Unregister given client from I2C slave mode of this adapter 379 357 * 380 358 * The following structs are for those who like to implement new bus drivers: 381 359 * i2c_algorithm is the interface to a class of hardware solutions which can ··· 403 377 404 378 /* To determine what the adapter supports */ 405 379 u32 (*functionality) (struct i2c_adapter *); 380 + 381 + int (*reg_slave)(struct i2c_client *client); 382 + int (*unreg_slave)(struct i2c_client *client); 406 383 }; 407 384 408 385 /**