svn commit: r185750 - head/sys/dev/dc

Marius Strobl marius at FreeBSD.org
Sun Dec 7 15:02:38 PST 2008


Author: marius
Date: Sun Dec  7 23:02:37 2008
New Revision: 185750
URL: http://svn.freebsd.org/changeset/base/185750

Log:
  - According to the corresponding Linux, NetBSD and OpenSolaris
    drivers, there should be a 1us delay after every write when
    bit-banging the MII. Also insert barriers in order to ensure
    the intended ordering. These changes hopefully will solve the
    bus wedging occasionally experienced with DM9102A since r182461.
  - Deobfuscate dc_mii_readreg() a bit.

Modified:
  head/sys/dev/dc/if_dc.c
  head/sys/dev/dc/if_dcreg.h

Modified: head/sys/dev/dc/if_dc.c
==============================================================================
--- head/sys/dev/dc/if_dc.c	Sun Dec  7 22:49:47 2008	(r185749)
+++ head/sys/dev/dc/if_dc.c	Sun Dec  7 23:02:37 2008	(r185750)
@@ -607,15 +607,22 @@ dc_read_eeprom(struct dc_softc *sc, cadd
 static void
 dc_mii_writebit(struct dc_softc *sc, int bit)
 {
+	uint32_t reg;
 
-	if (bit)
-		CSR_WRITE_4(sc, DC_SIO,
-		    DC_SIO_ROMCTL_WRITE | DC_SIO_MII_DATAOUT);
-	else
-		CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
-
-	DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK);
-	DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK);
+	reg = DC_SIO_ROMCTL_WRITE | (bit != 0 ? DC_SIO_MII_DATAOUT : 0);
+	CSR_WRITE_4(sc, DC_SIO, reg);
+	CSR_BARRIER_4(sc, DC_SIO,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	DELAY(1);
+
+	CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
+	CSR_BARRIER_4(sc, DC_SIO,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	DELAY(1);
+	CSR_WRITE_4(sc, DC_SIO, reg);
+	CSR_BARRIER_4(sc, DC_SIO,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	DELAY(1);
 }
 
 /*
@@ -624,11 +631,22 @@ dc_mii_writebit(struct dc_softc *sc, int
 static int
 dc_mii_readbit(struct dc_softc *sc)
 {
+	uint32_t reg;
 
-	CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_READ | DC_SIO_MII_DIR);
-	CSR_READ_4(sc, DC_SIO);
-	DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK);
-	DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK);
+	reg = DC_SIO_ROMCTL_READ | DC_SIO_MII_DIR;
+	CSR_WRITE_4(sc, DC_SIO, reg);
+	CSR_BARRIER_4(sc, DC_SIO,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	DELAY(1);
+	(void)CSR_READ_4(sc, DC_SIO);
+	CSR_WRITE_4(sc, DC_SIO, reg | DC_SIO_MII_CLK);
+	CSR_BARRIER_4(sc, DC_SIO,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	DELAY(1);
+	CSR_WRITE_4(sc, DC_SIO, reg);
+	CSR_BARRIER_4(sc, DC_SIO,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	DELAY(1);
 	if (CSR_READ_4(sc, DC_SIO) & DC_SIO_MII_DATAIN)
 		return (1);
 
@@ -644,6 +662,9 @@ dc_mii_sync(struct dc_softc *sc)
 	int i;
 
 	CSR_WRITE_4(sc, DC_SIO, DC_SIO_ROMCTL_WRITE);
+	CSR_BARRIER_4(sc, DC_SIO,
+	    BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE);
+	DELAY(1);
 
 	for (i = 0; i < 32; i++)
 		dc_mii_writebit(sc, 1);
@@ -667,15 +688,13 @@ dc_mii_send(struct dc_softc *sc, u_int32
 static int
 dc_mii_readreg(struct dc_softc *sc, struct dc_mii_frame *frame)
 {
-	int i, ack;
+	int i;
 
 	/*
 	 * Set up frame for RX.
 	 */
 	frame->mii_stdelim = DC_MII_STARTDELIM;
 	frame->mii_opcode = DC_MII_READOP;
-	frame->mii_turnaround = 0;
-	frame->mii_data = 0;
 
 	/*
 	 * Sync the PHYs.
@@ -690,38 +709,28 @@ dc_mii_readreg(struct dc_softc *sc, stru
 	dc_mii_send(sc, frame->mii_phyaddr, 5);
 	dc_mii_send(sc, frame->mii_regaddr, 5);
 
-#ifdef notdef
-	/* Idle bit */
-	dc_mii_writebit(sc, 1);
-	dc_mii_writebit(sc, 0);
-#endif
-
-	/* Check for ack. */
-	ack = dc_mii_readbit(sc);
-
 	/*
-	 * Now try reading data bits. If the ack failed, we still
+	 * Now try reading data bits.  If the turnaround failed, we still
 	 * need to clock through 16 cycles to keep the PHY(s) in sync.
 	 */
-	if (ack) {
+	frame->mii_turnaround = dc_mii_readbit(sc);
+	if (frame->mii_turnaround != 0) {
 		for (i = 0; i < 16; i++)
 			dc_mii_readbit(sc);
 		goto fail;
 	}
-
 	for (i = 0x8000; i; i >>= 1) {
-		if (!ack) {
-			if (dc_mii_readbit(sc))
-				frame->mii_data |= i;
-		}
+		if (dc_mii_readbit(sc))
+			frame->mii_data |= i;
 	}
 
 fail:
 
+	/* Clock the idle bits. */
 	dc_mii_writebit(sc, 0);
 	dc_mii_writebit(sc, 0);
 
-	if (ack)
+	if (frame->mii_turnaround != 0)
 		return (1);
 	return (0);
 }
@@ -736,7 +745,6 @@ dc_mii_writereg(struct dc_softc *sc, str
 	/*
 	 * Set up frame for TX.
 	 */
-
 	frame->mii_stdelim = DC_MII_STARTDELIM;
 	frame->mii_opcode = DC_MII_WRITEOP;
 	frame->mii_turnaround = DC_MII_TURNAROUND;
@@ -753,7 +761,7 @@ dc_mii_writereg(struct dc_softc *sc, str
 	dc_mii_send(sc, frame->mii_turnaround, 2);
 	dc_mii_send(sc, frame->mii_data, 16);
 
-	/* Idle bit. */
+	/* Clock the idle bits. */
 	dc_mii_writebit(sc, 0);
 	dc_mii_writebit(sc, 0);
 

Modified: head/sys/dev/dc/if_dcreg.h
==============================================================================
--- head/sys/dev/dc/if_dcreg.h	Sun Dec  7 22:49:47 2008	(r185749)
+++ head/sys/dev/dc/if_dcreg.h	Sun Dec  7 23:02:37 2008	(r185750)
@@ -791,6 +791,9 @@ struct dc_softc {
 #define CSR_READ_4(sc, reg)		\
 	bus_space_read_4(sc->dc_btag, sc->dc_bhandle, reg)
 
+#define CSR_BARRIER_4(sc, reg, flags)		\
+	bus_space_barrier(sc->dc_btag, sc->dc_bhandle, reg, 4, flags)
+
 #define DC_TIMEOUT		1000
 #define ETHER_ALIGN		2
 


More information about the svn-src-all mailing list