Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 19 Dec 2006 07:57:12 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 111931 for review
Message-ID:  <200612190757.kBJ7vCq3058570@repoman.freebsd.org>

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

Change 111931 by imp@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);
 }



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