Date: Sun, 7 Dec 2008 23:02:37 +0000 (UTC) From: Marius Strobl <marius@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r185750 - head/sys/dev/dc Message-ID: <200812072302.mB7N2bkp038633@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
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
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200812072302.mB7N2bkp038633>