[i2c] [Patch] High Speed I2c Support (core & dev changes)
Nishanth Menon
menon.nishanth at gmail.com
Thu Aug 24 06:33:53 CEST 2006
Greetings All,
This is in continuation of a old thread:
http://lists.lm-sensors.org/pipermail/lm-sensors/2005-June/012815.html
This is a draft patch, so looking for comments on the approach. the
patch is against the latest pulled from the svn repo.
This will also require changes for lm-sensors dump,detect and set.
Thanks and Regards,
Nishanth Menon
Patch to add support for High Speed I2C controllers to core and dev
Thread Ref:
http://lists.lm-sensors.org/pipermail/lm-sensors/2005-June/012815.html
Signed-off-by: Nishanth Menon <menon.nishanth at gmail.com>
--- i2c\kernel\i2c.h.orig 2006-08-23 22:46:16.000000000 -0500
+++ i2c\kernel\i2c.h 2006-08-23 22:48:06.000000000 -0500
@@ -381,6 +381,7 @@ struct i2c_msg {
__u16 flags;
#define I2C_M_TEN 0x10 /* we have a ten bit chip address */
#define I2C_M_RD 0x01
+#define I2C_M_HS 0x20
#define I2C_M_NOSTART 0x4000
#define I2C_M_REV_DIR_ADDR 0x2000
#define I2C_M_IGNORE_NAK 0x1000
@@ -398,6 +399,7 @@ struct i2c_msg {
#define I2C_FUNC_10BIT_ADDR 0x00000002
#define I2C_FUNC_PROTOCOL_MANGLING 0x00000004 /*
I2C_M_{REV_DIR_ADDR,NOSTART,..} */
#define I2C_FUNC_SMBUS_HWPEC_CALC 0x00000008 /* SMBus 2.0 */
+#define I2C_FUNC_HIGH_SPEED 0x00000010 /* High Speed Capable */
#define I2C_FUNC_SMBUS_BLOCK_PROC_CALL 0x00008000 /* SMBus 2.0 */
#define I2C_FUNC_SMBUS_QUICK 0x00010000
#define I2C_FUNC_SMBUS_READ_BYTE 0x00020000
@@ -488,6 +490,8 @@ union i2c_smbus_data {
#define I2C_RDWR 0x0707 /* Combined R/W transfer (one stop only)*/
#define I2C_PEC 0x0708 /* != 0 for SMBus PEC */
+#define I2C_HIGH_SPEED 0x0712 /* Set into high speed mode */
+
#define I2C_SMBUS 0x0720 /* SMBus-level access */
/* ----- I2C-DEV: char device interface stuff ------------------------- */
--- i2c\kernel\i2c-core.c.orig 2006-08-23 23:04:38.000000000 -0500
+++ i2c\kernel\i2c-core.c 2006-08-23 23:16:44.000000000 -0500
@@ -721,7 +721,15 @@ int i2c_master_send(struct i2c_client *c
if (client->adapter->algo->master_xfer) {
msg.addr = client->addr;
- msg.flags = client->flags & I2C_M_TEN;
+ msg.flags = client->flags & (I2C_M_TEN | I2C_M_HS);
+ /* Switch to Lower speed transfer if not compatible..
+ * we could use the get_func call but speed matters
+ */
+ if ((msg.flags & I2C_M_HS) && !(adap->flags & I2C_FUNC_HIGH_SPEED)) {
+ printk(KERN_DEBUG "i2c-core.o: I2C adapter %04x: I2C High speed
transfer switched to non HS transfer\n",
+ adap->id);
+ msg.flags &= ~I2C_M_HS;
+ }
msg.len = count;
msg.buf = (char *)buf;
@@ -750,7 +758,15 @@ int i2c_master_recv(struct i2c_client *c
int ret;
if (client->adapter->algo->master_xfer) {
msg.addr = client->addr;
- msg.flags = client->flags & I2C_M_TEN;
+ msg.flags = client->flags & (I2C_M_TEN | I2C_M_HS);
+ /* Switch to Lower speed transfer if not compatible..
+ * we could use the get_func call but speed matters
+ */
+ if ((msg.flags & I2C_M_HS) && !(adap->flags & I2C_FUNC_HIGH_SPEED)) {
+ printk(KERN_DEBUG "i2c-core.o: I2C adapter %04x: I2C High speed
transfer switched to non HS transfer\n",
+ adap->id);
+ msg.flags &= ~I2C_M_HS;
+ }
msg.flags |= I2C_M_RD;
msg.len = count;
msg.buf = buf;
@@ -1178,6 +1194,15 @@ static s32 i2c_smbus_xfer_emulated(struc
int i, len;
u8 partial_pec = 0;
+ /* Switch to Lower speed transfer if not compatible..
+ * we could use the get_func call but speed matters
+ */
+ if ((flags & I2C_M_HS) && !(adap->flags & I2C_FUNC_HIGH_SPEED)) {
+ printk(KERN_DEBUG "i2c-core.o: I2C adapter %04x: I2C High speed
transfer switched to non HS transfer\n",
+ adap->id);
+ msg[0].flags &= ~I2C_M_HS;
+ msg[1].flags &= ~I2C_M_HS;
+ }
msgbuf0[0] = command;
switch(size) {
case I2C_SMBUS_QUICK:
@@ -1352,7 +1377,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *
{
s32 res;
- flags &= I2C_M_TEN | I2C_CLIENT_PEC;
+ flags &= I2C_M_TEN | I2C_CLIENT_PEC | I2C_M_HS;
if (adap->algo->smbus_xfer) {
down(&adap->bus);
--- i2c\kernel\i2c-dev.c.orig 2006-08-23 23:18:44.000000000 -0500
+++ i2c\kernel\i2c-dev.c 2006-08-23 23:18:50.000000000 -0500
@@ -185,6 +185,12 @@ int i2cdev_ioctl (struct inode *inode, s
return -EBUSY;
client->addr = arg;
return 0;
+ case I2C_HIGH_SPEED:
+ if (arg)
+ client->flags |= I2C_M_HS;
+ else
+ client->flags &= ~I2C_M_HS;
+ return 0;
case I2C_TENBIT:
if (arg)
client->flags |= I2C_M_TEN;
More information about the i2c
mailing list