diff options
Diffstat (limited to 'freebsd/sys/dev/smc/if_smc.c')
-rw-r--r-- | freebsd/sys/dev/smc/if_smc.c | 150 |
1 files changed, 61 insertions, 89 deletions
diff --git a/freebsd/sys/dev/smc/if_smc.c b/freebsd/sys/dev/smc/if_smc.c index 236eb546..2f4e0f1e 100644 --- a/freebsd/sys/dev/smc/if_smc.c +++ b/freebsd/sys/dev/smc/if_smc.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); #include <dev/smc/if_smcvar.h> #include <dev/mii/mii.h> +#include <dev/mii/mii_bitbang.h> #include <dev/mii/miivar.h> #define SMC_LOCK(sc) mtx_lock(&(sc)->smc_mtx) @@ -125,11 +126,33 @@ static timeout_t smc_watchdog; static poll_handler_t smc_poll; #endif +/* + * MII bit-bang glue + */ +static uint32_t smc_mii_bitbang_read(device_t); +static void smc_mii_bitbang_write(device_t, uint32_t); + +static const struct mii_bitbang_ops smc_mii_bitbang_ops = { + smc_mii_bitbang_read, + smc_mii_bitbang_write, + { + MGMT_MDO, /* MII_BIT_MDO */ + MGMT_MDI, /* MII_BIT_MDI */ + MGMT_MCLK, /* MII_BIT_MDC */ + MGMT_MDOE, /* MII_BIT_DIR_HOST_PHY */ + 0, /* MII_BIT_DIR_PHY_HOST */ + } +}; + static __inline void smc_select_bank(struct smc_softc *sc, uint16_t bank) { + bus_barrier(sc->smc_reg, BSR, 2, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); bus_write_2(sc->smc_reg, BSR, bank & BSR_BANK_MASK); + bus_barrier(sc->smc_reg, BSR, 2, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } /* Never call this when not in bank 2. */ @@ -145,35 +168,35 @@ smc_mmu_wait(struct smc_softc *sc) } static __inline uint8_t -smc_read_1(struct smc_softc *sc, bus_addr_t offset) +smc_read_1(struct smc_softc *sc, bus_size_t offset) { return (bus_read_1(sc->smc_reg, offset)); } static __inline void -smc_write_1(struct smc_softc *sc, bus_addr_t offset, uint8_t val) +smc_write_1(struct smc_softc *sc, bus_size_t offset, uint8_t val) { bus_write_1(sc->smc_reg, offset, val); } static __inline uint16_t -smc_read_2(struct smc_softc *sc, bus_addr_t offset) +smc_read_2(struct smc_softc *sc, bus_size_t offset) { return (bus_read_2(sc->smc_reg, offset)); } static __inline void -smc_write_2(struct smc_softc *sc, bus_addr_t offset, uint16_t val) +smc_write_2(struct smc_softc *sc, bus_size_t offset, uint16_t val) { bus_write_2(sc->smc_reg, offset, val); } static __inline void -smc_read_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap, +smc_read_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap, bus_size_t count) { @@ -181,13 +204,21 @@ smc_read_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap, } static __inline void -smc_write_multi_2(struct smc_softc *sc, bus_addr_t offset, uint16_t *datap, +smc_write_multi_2(struct smc_softc *sc, bus_size_t offset, uint16_t *datap, bus_size_t count) { bus_write_multi_2(sc->smc_reg, offset, datap, count); } +static __inline void +smc_barrier(struct smc_softc *sc, bus_size_t offset, bus_size_t length, + int flags) +{ + + bus_barrier(sc->smc_reg, offset, length, flags); +} + int smc_probe(device_t dev) { @@ -540,6 +571,7 @@ smc_task_tx(void *context, int pending) struct smc_softc *sc; struct mbuf *m, *m0; u_int packet, len; + int last_len; uint8_t *data; (void)pending; @@ -592,16 +624,18 @@ smc_task_tx(void *context, int pending) * Push the data out to the device. */ data = NULL; + last_len = 0; for (; m != NULL; m = m->m_next) { data = mtod(m, uint8_t *); smc_write_multi_2(sc, DATA0, (uint16_t *)data, m->m_len / 2); + last_len = m->m_len; } /* * Push out the control byte and and the odd byte if needed. */ if ((len & 1) != 0 && data != NULL) - smc_write_2(sc, DATA0, (CTRL_ODD << 8) | data[m->m_len - 1]); + smc_write_2(sc, DATA0, (CTRL_ODD << 8) | data[last_len - 1]); else smc_write_2(sc, DATA0, 0); @@ -899,70 +933,43 @@ smc_task_intr(void *context, int pending) SMC_UNLOCK(sc); } -static u_int -smc_mii_readbits(struct smc_softc *sc, int nbits) +static uint32_t +smc_mii_bitbang_read(device_t dev) { - u_int mgmt, mask, val; + struct smc_softc *sc; + uint32_t val; + + sc = device_get_softc(dev); SMC_ASSERT_LOCKED(sc); KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3, - ("%s: smc_mii_readbits called with bank %d (!= 3)", + ("%s: smc_mii_bitbang_read called with bank %d (!= 3)", device_get_nameunit(sc->smc_dev), smc_read_2(sc, BSR) & BSR_BANK_MASK)); - /* - * Set up the MGMT (aka MII) register. - */ - mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO); - smc_write_2(sc, MGMT, mgmt); - - /* - * Read the bits in. - */ - for (mask = 1 << (nbits - 1), val = 0; mask; mask >>= 1) { - if (smc_read_2(sc, MGMT) & MGMT_MDI) - val |= mask; - - smc_write_2(sc, MGMT, mgmt); - DELAY(1); - smc_write_2(sc, MGMT, mgmt | MGMT_MCLK); - DELAY(1); - } + val = smc_read_2(sc, MGMT); + smc_barrier(sc, MGMT, 2, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); return (val); } static void -smc_mii_writebits(struct smc_softc *sc, u_int val, int nbits) +smc_mii_bitbang_write(device_t dev, uint32_t val) { - u_int mgmt, mask; + struct smc_softc *sc; + + sc = device_get_softc(dev); SMC_ASSERT_LOCKED(sc); KASSERT((smc_read_2(sc, BSR) & BSR_BANK_MASK) == 3, - ("%s: smc_mii_writebits called with bank %d (!= 3)", + ("%s: smc_mii_bitbang_write called with bank %d (!= 3)", device_get_nameunit(sc->smc_dev), smc_read_2(sc, BSR) & BSR_BANK_MASK)); - /* - * Set up the MGMT (aka MII) register). - */ - mgmt = smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO); - mgmt |= MGMT_MDOE; - - /* - * Push the bits out. - */ - for (mask = 1 << (nbits - 1); mask; mask >>= 1) { - if (val & mask) - mgmt |= MGMT_MDO; - else - mgmt &= ~MGMT_MDO; - - smc_write_2(sc, MGMT, mgmt); - DELAY(1); - smc_write_2(sc, MGMT, mgmt | MGMT_MCLK); - DELAY(1); - } + smc_write_2(sc, MGMT, val); + smc_barrier(sc, MGMT, 2, + BUS_SPACE_BARRIER_READ | BUS_SPACE_BARRIER_WRITE); } int @@ -977,26 +984,7 @@ smc_miibus_readreg(device_t dev, int phy, int reg) smc_select_bank(sc, 3); - /* - * Send out the idle pattern. - */ - smc_mii_writebits(sc, 0xffffffff, 32); - - /* - * Start code + read opcode + phy address + phy register - */ - smc_mii_writebits(sc, 6 << 10 | phy << 5 | reg, 14); - - /* - * Turnaround + data - */ - val = smc_mii_readbits(sc, 18); - - /* - * Reset the MDIO interface. - */ - smc_write_2(sc, MGMT, - smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO)); + val = mii_bitbang_readreg(dev, &smc_mii_bitbang_ops, phy, reg); SMC_UNLOCK(sc); return (val); @@ -1013,23 +1001,7 @@ smc_miibus_writereg(device_t dev, int phy, int reg, int data) smc_select_bank(sc, 3); - /* - * Send idle pattern. - */ - smc_mii_writebits(sc, 0xffffffff, 32); - - /* - * Start code + write opcode + phy address + phy register + turnaround - * + data. - */ - smc_mii_writebits(sc, 5 << 28 | phy << 23 | reg << 18 | 2 << 16 | data, - 32); - - /* - * Reset MDIO interface. - */ - smc_write_2(sc, MGMT, - smc_read_2(sc, MGMT) & ~(MGMT_MCLK | MGMT_MDOE | MGMT_MDO)); + mii_bitbang_writereg(dev, &smc_mii_bitbang_ops, phy, reg, data); SMC_UNLOCK(sc); return (0); |