Subject: Re: i2c 10-bit addressing
To: Garrett D'Amore <garrett_damore@tadpole.com>
From: Garrett D'Amore <garrett_damore@tadpole.com>
List: tech-kern
Date: 04/25/2006 13:55:20
This is a multi-part message in MIME format.
--------------000106030907080609000807
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Again, with diff -u for enhanced readability.  Sorry.

    -- Garrettt

Garrett D'Amore wrote:
> While working on a DDC driver, I wound up extending the I2C bit bang
> framework to support 10-bit addressing.  (This is because I was under
> the *false* impression that DDC addresses were 0xA0, rather than 0x50.)
>
> Anyway, I've got the code, and at least the *7-bit* support works.  I
> don't have any 10-bit ICs to test with.
>
> I'm attaching the patch, and if someone can test or wants to commit it
> (or wants me to commit) either do so or let me know.
>
>   
> ------------------------------------------------------------------------


--------------000106030907080609000807
Content-Type: text/plain;
 name="patch.i2c"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="patch.i2c"

Index: i2c_bitbang.c
===================================================================
RCS file: /cvsroot/src/sys/dev/i2c/i2c_bitbang.c,v
retrieving revision 1.3
diff -u -r1.3 i2c_bitbang.c
--- i2c_bitbang.c	5 Mar 2006 17:33:33 -0000	1.3
+++ i2c_bitbang.c	25 Apr 2006 20:54:23 -0000
@@ -88,16 +88,39 @@
 i2c_bitbang_initiate_xfer(void *v, i2c_addr_t addr, int flags,
     i2c_bitbang_ops_t ops)
 {
-	int i2caddr;
 
-	/* XXX Only support 7-bit addressing for now. */
-	if ((addr & 0x78) == 0x78)
-		return (EINVAL);
+	if (addr < 0x80) {
+		uint8_t i2caddr;
 
-	i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0);
+		/* disallow the 10-bit address prefix */
+		if ((addr & 0x78) == 0x78)
+			return EINVAL;
+		i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0);
+		(void) i2c_bitbang_send_start(v, flags, ops);
+
+		return (i2c_bitbang_write_byte(v, i2caddr,
+			    flags & ~I2C_F_STOP, ops));
+
+	} else if (addr < 0x400) {
+		uint16_t	i2caddr;
+		int		rv;
+
+		i2caddr = (addr << 1) | ((flags & I2C_F_READ) ? 1 : 0) |
+		    0xf000;
+
+		(void) i2c_bitbang_send_start(v, flags, ops);
+		rv = i2c_bitbang_write_byte(v, i2caddr >> 8,
+		    flags & ~I2C_F_STOP, ops);
+		/* did a slave ack the 10-bit prefix? */
+		if (rv != 0)
+			return rv;
+
+		/* send the lower 7-bits (+ read/write mode) */
+		return (i2c_bitbang_write_byte(v, i2caddr & 0xff,
+			    flags & ~I2C_F_STOP, ops));
 
-	(void) i2c_bitbang_send_start(v, flags, ops);
-	return (i2c_bitbang_write_byte(v, i2caddr, flags & ~I2C_F_STOP, ops));
+	} else
+		return EINVAL;
 }
 
 int

--------------000106030907080609000807--