PERFORCE change 111366 for review

Warner Losh imp at FreeBSD.org
Sat Dec 9 20:41:37 PST 2006


http://perforce.freebsd.org/chv.cgi?CH=111366

Change 111366 by imp at imp_lighthouse on 2006/12/10 04:41:02

	Fixes for writing a single byte to IIC as well as robust detection
	of NACK bit in SR indicating no ACK from the transfer.  This
	is useful when probing the bus.
	
	Many of these changes were from tisco based on his experience with
	the Atmel sample code and the AT91SAM7 processors he's used in
	the past.  These tweaks are somewhat underdocumented in the AT91RM9200
	processor manual, but also appear to be hinted at in the errata.
	
	As far as I can tell, nothing breaks when we do this, but I've only
	tested on my KB9202 board.
	
	Submitted by:	tisco

Affected files ...

.. //depot/projects/arm/src/sys/arm/at91/at91_twi.c#38 edit

Differences ...

==== //depot/projects/arm/src/sys/arm/at91/at91_twi.c#38 (text+ko) ====

@@ -226,7 +226,8 @@
 	int counter = 100000;
 	uint32_t sr;
 
-	while (!((sr = RD4(sc, TWI_SR)) & bit) && counter-- > 0)
+	while (!((sr = RD4(sc, TWI_SR)) & bit) && counter-- > 0 &&
+	    !(sr & TWI_SR_NACK))
 		continue;
 	if (counter <= 0)
 		err = EBUSY;
@@ -300,6 +301,7 @@
 	int i, len, err;
 	uint32_t rdwr;
 	uint8_t *buf;
+	uint32_t sr;
 
 	sc = device_get_softc(dev);
 	err = 0;
@@ -318,24 +320,35 @@
 		WR4(sc, TWI_MMR, TWI_MMR_DADR(msgs[i].slave) | rdwr);
 		len = msgs[i].len;
 		buf = msgs[i].buf;
-		if (len != 0 && buf == NULL)
+		/* zero byte transfers aren't allowed */
+		if (len == 0 || buf == NULL)
 			return (EINVAL);
-		WR4(sc, TWI_CR, TWI_CR_START);
+		if (len == 1)
+			WR4(sc, TWI_CR, TWI_CR_START | TWI_CR_STOP);
+		else
+			WR4(sc, TWI_CR, TWI_CR_START);
 		if (msgs[i].flags & IIC_M_RD) {
-			while (len--) {
-				if (len == 0)
-					WR4(sc, TWI_CR, TWI_CR_STOP);
-				if ((err = at91_twi_wait(sc, TWI_SR_RXRDY)))
-					goto out;
-				*buf++ = RD4(sc, TWI_RHR) & 0xff;
+			sr = RD4(sc, TWI_SR);
+			while (!(sr & TWI_SR_TXCOMP)) {
+				sr = RD4(sc, TWI_SR);
+				if ((sr = RD4(sc, TWI_SR)) & TWI_SR_RXRDY) {
+					len--;
+					*buf++ = RD4(sc, TWI_RHR) & 0xff;
+					if (len == 0 && msgs[i].len != 1)
+						WR4(sc, TWI_CR, TWI_CR_STOP);
+				}
+			}
+			if (sr & TWI_SR_NACK) {
+				err = EADDRNOTAVAIL;
+				goto out;
 			}
 		} else {
 			while (len--) {
-				WR4(sc, TWI_THR, *buf++);
-				if (len == 0)
+				if (len == 0 && msgs[i].len != 1)
 					WR4(sc, TWI_CR, TWI_CR_STOP);
 				if ((err = at91_twi_wait(sc, TWI_SR_TXRDY)))
 					goto out;
+				WR4(sc, TWI_THR, *buf++);
 			}
 		}
 		if ((err = at91_twi_wait(sc, TWI_SR_TXCOMP)))


More information about the p4-projects mailing list