PERFORCE change 111931 for review

Warner Losh imp at FreeBSD.org
Mon Dec 18 23:57:19 PST 2006


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

Change 111931 by imp at imp_lighthouse on 2006/12/19 07:57:09

	Fix two major bugs, and a bunch of nits:
	o Eliminate an extra, redundant reading off the sr.
	o If we don't read enough bytes, don't pretend that we did.  Instead,
	  return an error.  Maybe we should give an indication of how many
	  bytes were read in this case, but for now we just return the error.
	o When we encounter an error, use the big hammer of software reset
	  to fix.  This may not be entirely necessary but seems to help
	  solve problems we see when reading after there's been an error.
	o Return ENXIO for NACK.  Lame error message, but follows existing
	  practice.
	o Use #defines for clock speeds rather than hard coding numbers.
	
	# this makes it possible to read from existent and then non-existent
	# devices in a tight loop w/o occasional data corruption of many
	# flavors.

Affected files ...

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

Differences ...

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

@@ -45,6 +45,10 @@
 #include <dev/iicbus/iicbus.h>
 #include "iicbus_if.h"
 
+#define TWI_SLOW_CLOCK		 1500
+#define TWI_FAST_CLOCK 		45000
+#define TWI_FASTEST_CLOCK	90000
+
 struct at91_twi_softc
 {
 	device_t dev;			/* Myself */
@@ -123,7 +127,7 @@
 		AT91_TWI_LOCK_DESTROY(sc);
 		goto out;
 	}
-	sc->cwgr = TWI_CWGR_CKDIV(8 * AT91C_MASTER_CLOCK / 90000) |
+	sc->cwgr = TWI_CWGR_CKDIV(8 * AT91C_MASTER_CLOCK / TWI_FASTEST_CLOCK) |
 	    TWI_CWGR_CHDIV(TWI_CWGR_DIV(TWI_DEF_CLK)) |
 	    TWI_CWGR_CLDIV(TWI_CWGR_DIV(TWI_DEF_CLK));
 	WR4(sc, TWI_CR, TWI_CR_SWRST);
@@ -232,7 +236,7 @@
 	if (counter <= 0)
 		err = EBUSY;
 	else if (sr & TWI_SR_NACK)
-		err = EADDRNOTAVAIL;
+		err = ENXIO;		// iic nack convention
 	return (err);
 }
 
@@ -252,17 +256,17 @@
 	 */
 	switch (speed) {
 	case IIC_SLOW:
-		clk = 1500;
+		clk = TWI_SLOW_CLOCK;
 		break;
 
 	case IIC_FAST:
-		clk = 45000;
+		clk = TWI_FAST_CLOCK;
 		break;
 
 	case IIC_UNKNOWN:
 	case IIC_FASTEST:
 	default:
-		clk = 90000;
+		clk = TWI_FASTEST_CLOCK;
 		break;
 	}
 	sc->cwgr = TWI_CWGR_CKDIV(1) | TWI_CWGR_CHDIV(TWI_CWGR_DIV(clk)) |
@@ -332,7 +336,6 @@
 		if (msgs[i].flags & IIC_M_RD) {
 			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;
@@ -340,8 +343,8 @@
 						WR4(sc, TWI_CR, TWI_CR_STOP);
 				}
 			}
-			if (sr & TWI_SR_NACK) {
-				err = EADDRNOTAVAIL;
+			if (len > 0 || (sr & TWI_SR_NACK)) {
+				err = ENXIO;		// iic nack convention
 				goto out;
 			}
 		} else {
@@ -357,8 +360,11 @@
 			break;
 	}
 out:;
-	if (err)
-		WR4(sc, TWI_CR, TWI_CR_STOP);
+	if (err) {
+		WR4(sc, TWI_CR, TWI_CR_SWRST);
+		WR4(sc, TWI_CR, TWI_CR_MSEN | TWI_CR_SVDIS);
+		WR4(sc, TWI_CWGR, sc->cwgr);
+	}
 	AT91_TWI_UNLOCK(sc);
 	return (err);
 }


More information about the p4-projects mailing list