- 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:
parent
7bc367aaa4
commit
b5f6ffdd90
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user