Skip to content

Commit 4b1acc4

Browse files
Wolfram SangWolfram Sang
authored andcommitted
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 <[email protected]> Signed-off-by: Wolfram Sang <[email protected]>
1 parent 40ed1b4 commit 4b1acc4

File tree

2 files changed

+78
-0
lines changed

2 files changed

+78
-0
lines changed

drivers/i2c/i2c-core.c

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
(c) 2013 Wolfram Sang <[email protected]>
2525
I2C ACPI code Copyright (C) 2014 Intel Corp
2626
Author: Lan Tianyu <[email protected]>
27+
I2C slave support (c) 2014 by Wolfram Sang <[email protected]>
2728
*/
2829

2930
#include <linux/module.h>
@@ -2911,6 +2912,54 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
29112912
}
29122913
EXPORT_SYMBOL(i2c_smbus_xfer);
29132914

2915+
int 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+
}
2943+
EXPORT_SYMBOL_GPL(i2c_slave_register);
2944+
2945+
int 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+
}
2961+
EXPORT_SYMBOL_GPL(i2c_slave_unregister);
2962+
29142963
MODULE_AUTHOR("Simon G. Vogl <[email protected]>");
29152964
MODULE_DESCRIPTION("I2C-Bus main module");
29162965
MODULE_LICENSE("GPL");

include/linux/i2c.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ struct i2c_client;
4646
struct i2c_driver;
4747
union i2c_smbus_data;
4848
struct i2c_board_info;
49+
enum i2c_slave_event;
50+
typedef int (*i2c_slave_cb_t)(struct i2c_client *, enum i2c_slave_event, u8 *);
4951

5052
struct module;
5153

@@ -209,6 +211,8 @@ struct i2c_driver {
209211
* @irq: indicates the IRQ generated by this device (if any)
210212
* @detected: member of an i2c_driver.clients list or i2c-core's
211213
* 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.
212216
*
213217
* An i2c_client identifies a single device (i.e. chip) connected to an
214218
* i2c bus. The behaviour exposed to Linux is defined by the driver
@@ -224,6 +228,7 @@ struct i2c_client {
224228
struct device dev; /* the device structure */
225229
int irq; /* irq issued by device */
226230
struct list_head detected;
231+
i2c_slave_cb_t slave_cb; /* callback for slave mode */
227232
};
228233
#define to_i2c_client(d) container_of(d, struct i2c_client, dev)
229234

@@ -246,6 +251,25 @@ static inline void i2c_set_clientdata(struct i2c_client *dev, void *data)
246251
dev_set_drvdata(&dev->dev, data);
247252
}
248253

254+
/* I2C slave support */
255+
256+
enum 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+
264+
extern int i2c_slave_register(struct i2c_client *client, i2c_slave_cb_t slave_cb);
265+
extern int i2c_slave_unregister(struct i2c_client *client);
266+
267+
static 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+
249273
/**
250274
* struct i2c_board_info - template for device creation
251275
* @type: chip type, to initialize i2c_client.name
@@ -352,6 +376,8 @@ i2c_register_board_info(int busnum, struct i2c_board_info const *info,
352376
* into I2C transfers instead.
353377
* @functionality: Return the flags that this algorithm/adapter pair supports
354378
* 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
355381
*
356382
* The following structs are for those who like to implement new bus drivers:
357383
* i2c_algorithm is the interface to a class of hardware solutions which can
@@ -377,6 +403,9 @@ struct i2c_algorithm {
377403

378404
/* To determine what the adapter supports */
379405
u32 (*functionality) (struct i2c_adapter *);
406+
407+
int (*reg_slave)(struct i2c_client *client);
408+
int (*unreg_slave)(struct i2c_client *client);
380409
};
381410

382411
/**

0 commit comments

Comments
 (0)