Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 10 Dec 2006 04:41:36 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 111366 for review
Message-ID:  <200612100441.kBA4faGE069138@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=111366

Change 111366 by imp@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)))



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200612100441.kBA4faGE069138>