diff options
Diffstat (limited to 'sys/dev/stge')
-rw-r--r-- | sys/dev/stge/if_stge.c | 236 | ||||
-rw-r--r-- | sys/dev/stge/if_stgereg.h | 20 |
2 files changed, 50 insertions, 206 deletions
diff --git a/sys/dev/stge/if_stge.c b/sys/dev/stge/if_stge.c index 5058a4d..b18da27 100644 --- a/sys/dev/stge/if_stge.c +++ b/sys/dev/stge/if_stge.c @@ -67,6 +67,7 @@ __FBSDID("$FreeBSD$"); #include <sys/rman.h> #include <dev/mii/mii.h> +#include <dev/mii/mii_bitbang.h> #include <dev/mii/miivar.h> #include <dev/pci/pcireg.h> @@ -86,11 +87,11 @@ MODULE_DEPEND(stge, miibus, 1, 1, 1); /* * Devices supported by this driver. */ -static struct stge_product { +static const struct stge_product { uint16_t stge_vendorid; uint16_t stge_deviceid; const char *stge_name; -} stge_products[] = { +} const stge_products[] = { { VENDOR_SUNDANCETI, DEVICEID_SUNDANCETI_ST1023, "Sundance ST-1023 Gigabit Ethernet" }, @@ -160,10 +161,6 @@ static int stge_newbuf(struct stge_softc *, int); static __inline struct mbuf *stge_fixup_rx(struct stge_softc *, struct mbuf *); #endif -static void stge_mii_sync(struct stge_softc *); -static void stge_mii_send(struct stge_softc *, uint32_t, int); -static int stge_mii_readreg(struct stge_softc *, struct stge_mii_frame *); -static int stge_mii_writereg(struct stge_softc *, struct stge_mii_frame *); static int stge_miibus_readreg(device_t, int, int); static int stge_miibus_writereg(device_t, int, int, int); static void stge_miibus_statchg(device_t); @@ -185,6 +182,24 @@ static int sysctl_int_range(SYSCTL_HANDLER_ARGS, int, int); static int sysctl_hw_stge_rxint_nframe(SYSCTL_HANDLER_ARGS); static int sysctl_hw_stge_rxint_dmawait(SYSCTL_HANDLER_ARGS); +/* + * MII bit-bang glue + */ +static uint32_t stge_mii_bitbang_read(device_t); +static void stge_mii_bitbang_write(device_t, uint32_t); + +static const struct mii_bitbang_ops stge_mii_bitbang_ops = { + stge_mii_bitbang_read, + stge_mii_bitbang_write, + { + PC_MgmtData, /* MII_BIT_MDO */ + PC_MgmtData, /* MII_BIT_MDI */ + PC_MgmtClk, /* MII_BIT_MDC */ + PC_MgmtDir, /* MII_BIT_DIR_HOST_PHY */ + 0, /* MII_BIT_DIR_PHY_HOST */ + } +}; + static device_method_t stge_methods[] = { /* Device interface */ DEVMETHOD(device_probe, stge_probe), @@ -225,176 +240,40 @@ static struct resource_spec stge_res_spec_mem[] = { { -1, 0, 0 } }; -#define MII_SET(x) \ - CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) | (x)) -#define MII_CLR(x) \ - CSR_WRITE_1(sc, STGE_PhyCtrl, CSR_READ_1(sc, STGE_PhyCtrl) & ~(x)) - /* - * Sync the PHYs by setting data bit and strobing the clock 32 times. + * stge_mii_bitbang_read: [mii bit-bang interface function] + * + * Read the MII serial port for the MII bit-bang module. */ -static void -stge_mii_sync(struct stge_softc *sc) +static uint32_t +stge_mii_bitbang_read(device_t dev) { - int i; + struct stge_softc *sc; + uint32_t val; - MII_SET(PC_MgmtDir | PC_MgmtData); + sc = device_get_softc(dev); - for (i = 0; i < 32; i++) { - MII_SET(PC_MgmtClk); - DELAY(1); - MII_CLR(PC_MgmtClk); - DELAY(1); - } + val = CSR_READ_1(sc, STGE_PhyCtrl); + CSR_BARRIER(sc, STGE_PhyCtrl, 1, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); + return (val); } /* - * Clock a series of bits through the MII. + * stge_mii_bitbang_write: [mii big-bang interface function] + * + * Write the MII serial port for the MII bit-bang module. */ static void -stge_mii_send(struct stge_softc *sc, uint32_t bits, int cnt) -{ - int i; - - MII_CLR(PC_MgmtClk); - - for (i = (0x1 << (cnt - 1)); i; i >>= 1) { - if (bits & i) - MII_SET(PC_MgmtData); - else - MII_CLR(PC_MgmtData); - DELAY(1); - MII_CLR(PC_MgmtClk); - DELAY(1); - MII_SET(PC_MgmtClk); - } -} - -/* - * Read an PHY register through the MII. - */ -static int -stge_mii_readreg(struct stge_softc *sc, struct stge_mii_frame *frame) +stge_mii_bitbang_write(device_t dev, uint32_t val) { - int i, ack; - - /* - * Set up frame for RX. - */ - frame->mii_stdelim = STGE_MII_STARTDELIM; - frame->mii_opcode = STGE_MII_READOP; - frame->mii_turnaround = 0; - frame->mii_data = 0; - - CSR_WRITE_1(sc, STGE_PhyCtrl, 0 | sc->sc_PhyCtrl); - /* - * Turn on data xmit. - */ - MII_SET(PC_MgmtDir); - - stge_mii_sync(sc); - - /* - * Send command/address info. - */ - stge_mii_send(sc, frame->mii_stdelim, 2); - stge_mii_send(sc, frame->mii_opcode, 2); - stge_mii_send(sc, frame->mii_phyaddr, 5); - stge_mii_send(sc, frame->mii_regaddr, 5); - - /* Turn off xmit. */ - MII_CLR(PC_MgmtDir); - - /* Idle bit */ - MII_CLR((PC_MgmtClk | PC_MgmtData)); - DELAY(1); - MII_SET(PC_MgmtClk); - DELAY(1); - - /* Check for ack */ - MII_CLR(PC_MgmtClk); - DELAY(1); - ack = CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData; - MII_SET(PC_MgmtClk); - DELAY(1); - - /* - * Now try reading data bits. If the ack failed, we still - * need to clock through 16 cycles to keep the PHY(s) in sync. - */ - if (ack) { - for(i = 0; i < 16; i++) { - MII_CLR(PC_MgmtClk); - DELAY(1); - MII_SET(PC_MgmtClk); - DELAY(1); - } - goto fail; - } - - for (i = 0x8000; i; i >>= 1) { - MII_CLR(PC_MgmtClk); - DELAY(1); - if (!ack) { - if (CSR_READ_1(sc, STGE_PhyCtrl) & PC_MgmtData) - frame->mii_data |= i; - DELAY(1); - } - MII_SET(PC_MgmtClk); - DELAY(1); - } - -fail: - MII_CLR(PC_MgmtClk); - DELAY(1); - MII_SET(PC_MgmtClk); - DELAY(1); - - if (ack) - return(1); - return(0); -} - -/* - * Write to a PHY register through the MII. - */ -static int -stge_mii_writereg(struct stge_softc *sc, struct stge_mii_frame *frame) -{ - - /* - * Set up frame for TX. - */ - frame->mii_stdelim = STGE_MII_STARTDELIM; - frame->mii_opcode = STGE_MII_WRITEOP; - frame->mii_turnaround = STGE_MII_TURNAROUND; - - /* - * Turn on data output. - */ - MII_SET(PC_MgmtDir); - - stge_mii_sync(sc); - - stge_mii_send(sc, frame->mii_stdelim, 2); - stge_mii_send(sc, frame->mii_opcode, 2); - stge_mii_send(sc, frame->mii_phyaddr, 5); - stge_mii_send(sc, frame->mii_regaddr, 5); - stge_mii_send(sc, frame->mii_turnaround, 2); - stge_mii_send(sc, frame->mii_data, 16); - - /* Idle bit. */ - MII_SET(PC_MgmtClk); - DELAY(1); - MII_CLR(PC_MgmtClk); - DELAY(1); + struct stge_softc *sc; - /* - * Turn off xmit. - */ - MII_CLR(PC_MgmtDir); + sc = device_get_softc(dev); - return(0); + CSR_WRITE_1(sc, STGE_PhyCtrl, val); + CSR_BARRIER(sc, STGE_PhyCtrl, 1, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } /* @@ -406,8 +285,7 @@ static int stge_miibus_readreg(device_t dev, int phy, int reg) { struct stge_softc *sc; - struct stge_mii_frame frame; - int error; + int error, val; sc = device_get_softc(dev); @@ -418,21 +296,11 @@ stge_miibus_readreg(device_t dev, int phy, int reg) STGE_MII_UNLOCK(sc); return (error); } - bzero(&frame, sizeof(frame)); - frame.mii_phyaddr = phy; - frame.mii_regaddr = reg; STGE_MII_LOCK(sc); - error = stge_mii_readreg(sc, &frame); + val = mii_bitbang_readreg(dev, &stge_mii_bitbang_ops, phy, reg); STGE_MII_UNLOCK(sc); - - if (error != 0) { - /* Don't show errors for PHY probe request */ - if (reg != 1) - device_printf(sc->sc_dev, "phy read fail\n"); - return (0); - } - return (frame.mii_data); + return (val); } /* @@ -444,22 +312,12 @@ static int stge_miibus_writereg(device_t dev, int phy, int reg, int val) { struct stge_softc *sc; - struct stge_mii_frame frame; - int error; sc = device_get_softc(dev); - bzero(&frame, sizeof(frame)); - frame.mii_phyaddr = phy; - frame.mii_regaddr = reg; - frame.mii_data = val; - STGE_MII_LOCK(sc); - error = stge_mii_writereg(sc, &frame); + mii_bitbang_writereg(dev, &stge_mii_bitbang_ops, phy, reg, val); STGE_MII_UNLOCK(sc); - - if (error != 0) - device_printf(sc->sc_dev, "phy write fail\n"); return (0); } @@ -550,7 +408,7 @@ stge_read_eeprom(struct stge_softc *sc, int offset, uint16_t *data) static int stge_probe(device_t dev) { - struct stge_product *sp; + const struct stge_product *sp; int i; uint16_t vendor, devid; diff --git a/sys/dev/stge/if_stgereg.h b/sys/dev/stge/if_stgereg.h index 6ecbdf9..f14142a 100644 --- a/sys/dev/stge/if_stgereg.h +++ b/sys/dev/stge/if_stgereg.h @@ -99,6 +99,9 @@ #define CSR_READ_1(_sc, reg) \ bus_read_1((_sc)->sc_res[0], (reg)) +#define CSR_BARRIER(_sc, reg, length, flags) \ + bus_barrier((_sc)->sc_res[0], reg, length, flags) + /* * TC9021 buffer fragment descriptor. */ @@ -677,23 +680,6 @@ do { \ #define STGE_TIMEOUT 1000 -struct stge_mii_frame { - uint8_t mii_stdelim; - uint8_t mii_opcode; - uint8_t mii_phyaddr; - uint8_t mii_regaddr; - uint8_t mii_turnaround; - uint16_t mii_data; -}; - -/* - * MII constants - */ -#define STGE_MII_STARTDELIM 0x01 -#define STGE_MII_READOP 0x02 -#define STGE_MII_WRITEOP 0x01 -#define STGE_MII_TURNAROUND 0x02 - #define STGE_RESET_NONE 0x00 #define STGE_RESET_TX 0x01 #define STGE_RESET_RX 0x02 |