diff options
author | David Christensen <davidch@FreeBSD.org> | 2008-06-13 01:20:29 +0000 |
---|---|---|
committer | David Christensen <davidch@FreeBSD.org> | 2008-06-13 01:20:29 +0000 |
commit | d75672d1c4829efdbe93f16a90a128e945387d9c (patch) | |
tree | 9281e82f252f18d1ba2cd4ccf9d011c6ddc9d5b3 /sys/dev/mii/brgphy.c | |
parent | 7752e34d054771eb05b6b1f64b93961781294bf5 (diff) | |
download | src-d75672d1c4829efdbe93f16a90a128e945387d9c.tar.gz src-d75672d1c4829efdbe93f16a90a128e945387d9c.zip |
- Added support for BCM5709 and BCM5716.
MFC after: 2 weeks
Notes
Notes:
svn path=/head/; revision=179772
Diffstat (limited to 'sys/dev/mii/brgphy.c')
-rw-r--r-- | sys/dev/mii/brgphy.c | 68 |
1 files changed, 59 insertions, 9 deletions
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index 87ecedb1f487..f8c38395e9eb 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -74,7 +74,7 @@ struct brgphy_softc { int serdes_flags; /* Keeps track of the serdes type used */ #define BRGPHY_5706S 0x0001 #define BRGPHY_5708S 0x0002 - int bce_phy_flags; /* PHY flags transferred from the MAC driver */ + int bce_phy_flags; /* PHY flags transferred from the MAC driver */ }; static device_method_t brgphy_methods[] = { @@ -231,7 +231,7 @@ brgphy_attach(device_t dev) bce_sc = ifp->if_softc; } - /* Todo: Need to add additional controllers such as 5787F */ + /* Todo: Need to add additional controllers such as 5906 & 5787F */ /* The 590x chips are 10/100 only. */ if (bge_sc && pci_get_vendor(bge_sc->bge_dev) == BCOM_VENDORID && @@ -245,6 +245,7 @@ brgphy_attach(device_t dev) brgphy_reset(sc); + /* Read the PHY's capabilities. */ sc->mii_capabilities = PHY_READ(sc, MII_BMSR) & ma->mii_capmask; if (sc->mii_capabilities & BMSR_EXTSTAT) sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR); @@ -281,7 +282,7 @@ brgphy_attach(device_t dev) ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_SX, IFM_FDX, sc->mii_inst), BRGPHY_S1000 | BRGPHY_BMCR_FDX); printf("1000baseSX-FDX, "); - /* 2.5G support is a software enabled feature on the 5708S */ + /* 2.5G support is a software enabled feature on the 5708S and 5709S. */ if (bce_sc && (bce_sc->bce_phy_flags & BCE_PHY_2_5G_CAPABLE_FLAG)) { ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX, IFM_FDX, sc->mii_inst), 0); printf("2500baseSX-FDX, "); @@ -425,12 +426,20 @@ brgphy_service_exit: return (error); } + +/****************************************************************************/ +/* Sets the PHY link speed. */ +/* */ +/* Returns: */ +/* None */ +/****************************************************************************/ static void brgphy_setmedia(struct mii_softc *sc, int media, int master) { struct brgphy_softc *bsc = (struct brgphy_softc *)sc; int bmcr = 0, gig; + /* Calculate the value for the BMCR register. */ switch (IFM_SUBTYPE(media)) { case IFM_2500_SX: break; @@ -446,6 +455,8 @@ brgphy_setmedia(struct mii_softc *sc, int media, int master) bmcr = BRGPHY_S10; break; } + + /* Calculate duplex settings for 1000BasetT/1000BaseX. */ if ((media & IFM_GMASK) == IFM_FDX) { bmcr |= BRGPHY_BMCR_FDX; gig = BRGPHY_1000CTL_AFD; @@ -453,18 +464,27 @@ brgphy_setmedia(struct mii_softc *sc, int media, int master) gig = BRGPHY_1000CTL_AHD; } + /* Force loopback to disconnect PHY for Ethernet medium. */ brgphy_enable_loopback(sc); + + /* Disable 1000BaseT advertisements. */ PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0); - PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr); + /* Disable 10/100 advertisements. */ PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE); + /* Write forced link speed. */ + PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr); + /* If 10/100 only then configuration is complete. */ if ((IFM_SUBTYPE(media) != IFM_1000_T) && (IFM_SUBTYPE(media) != IFM_1000_SX)) goto brgphy_setmedia_exit; + /* Set duplex speed advertisement for 1000BaseT/1000BaseX. */ PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig); + /* Restart auto-negotiation for 1000BaseT/1000BaseX. */ PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr | BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); + /* If not 5701 PHY then configuration is complete. */ if (bsc->mii_model != MII_MODEL_xxBROADCOM_BCM5701) goto brgphy_setmedia_exit; @@ -482,13 +502,19 @@ brgphy_setmedia(struct mii_softc *sc, int media, int master) PHY_WRITE(sc, BRGPHY_MII_1000CTL, gig | BRGPHY_1000CTL_MSE); } + brgphy_setmedia_exit: return; } -/* Set the media status based on the PHY settings. */ -/* IFM_FLAG0 = 0 (RX flow control disabled | 1 (enabled) */ -/* IFM_FLAG1 = 0 (TX flow control disabled | 1 (enabled) */ +/****************************************************************************/ +/* Set the media status based on the PHY settings. */ +/* IFM_FLAG0 = 0 (RX flow control disabled) | 1 (enabled) */ +/* IFM_FLAG1 = 0 (TX flow control disabled) | 1 (enabled) */ +/* */ +/* Returns: */ +/* None */ +/****************************************************************************/ static void brgphy_status(struct mii_softc *sc) { @@ -568,7 +594,6 @@ brgphy_status(struct mii_softc *sc) PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); xstat = PHY_READ(sc, BRGPHY_5708S_PG0_1000X_STAT1); - /* Todo: Create #defines for hard coded values */ switch (xstat & BRGPHY_5708S_PG0_1000X_STAT1_SPEED_MASK) { case BRGPHY_5708S_PG0_1000X_STAT1_SPEED_10: mii->mii_media_active |= IFM_10_FL; break; @@ -603,6 +628,7 @@ brgphy_status(struct mii_softc *sc) mii->mii_media_active |= IFM_FLAG0; } } + /* Todo: Add support for fiber settings too. */ #endif @@ -643,6 +669,7 @@ brgphy_mii_phy_auto(struct mii_softc *sc) } + /* Enable loopback to force the link down. */ static void brgphy_enable_loopback(struct mii_softc *sc) @@ -819,6 +846,20 @@ brgphy_fixup_jitter_bug(struct mii_softc *sc) PHY_WRITE(sc, dspcode[i].reg, dspcode[i].val); } + +static void +brgphy_fixup_disable_early_dac(struct mii_softc *sc) +{ + uint32_t val; + + PHY_WRITE(sc, BRGPHY_MII_DSP_ADDR_REG, 0x0f08); + val = PHY_READ(sc, BRGPHY_MII_DSP_RW_PORT); + val &= ~(1 << 8); + PHY_WRITE(sc, BRGPHY_MII_DSP_RW_PORT, val); + +} + + static void brgphy_ethernet_wirespeed(struct mii_softc *sc) { @@ -830,6 +871,7 @@ brgphy_ethernet_wirespeed(struct mii_softc *sc) PHY_WRITE(sc, BRGPHY_MII_AUXCTL, val | (1 << 15) | (1 << 4)); } + static void brgphy_jumbo_settings(struct mii_softc *sc, u_long mtu) { @@ -871,9 +913,10 @@ brgphy_reset(struct mii_softc *sc) struct bce_softc *bce_sc = NULL; struct ifnet *ifp; + /* Perform a standard PHY reset. */ mii_phy_reset(sc); - /* Handle any PHY specific procedures to finish the reset. */ + /* Handle any PHY specific procedures following the reset. */ switch (bsc->mii_oui) { case MII_OUI_BROADCOM: break; @@ -988,6 +1031,13 @@ brgphy_reset(struct mii_softc *sc) PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR,
BRGPHY_5708S_DIG_PG0); } + } else if (BCE_CHIP_NUM(bce_sc) == BCE_CHIP_NUM_5709) { + if ((BCE_CHIP_REV(bce_sc) == BCE_CHIP_REV_Ax) || + (BCE_CHIP_REV(bce_sc) == BCE_CHIP_REV_Bx)) + brgphy_fixup_disable_early_dac(sc); + + brgphy_jumbo_settings(sc, ifp->if_mtu); + brgphy_ethernet_wirespeed(sc); } else { brgphy_fixup_ber_bug(sc); brgphy_jumbo_settings(sc, ifp->if_mtu); |