[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