- 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.
This commit is contained in:
marius 2008-12-07 23:02:37 +00:00
parent 7bc367aaa4
commit b5f6ffdd90
2 changed files with 44 additions and 33 deletions

View File

@ -607,15 +607,22 @@ dc_read_eeprom(struct dc_softc *sc, caddr_t dest, int off, int cnt, int be)
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);
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);
DC_SETBIT(sc, DC_SIO, DC_SIO_MII_CLK);
DC_CLRBIT(sc, DC_SIO, DC_SIO_MII_CLK);
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 bit)
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_t bits, int cnt)
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, struct dc_mii_frame *frame)
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, struct dc_mii_frame *frame)
/*
* 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, struct dc_mii_frame *frame)
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);

View File

@ -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