diff options
Diffstat (limited to 'freebsd/sys/dev/mii/brgphy.c')
-rw-r--r-- | freebsd/sys/dev/mii/brgphy.c | 93 |
1 files changed, 54 insertions, 39 deletions
diff --git a/freebsd/sys/dev/mii/brgphy.c b/freebsd/sys/dev/mii/brgphy.c index 5633413c..bd80e61e 100644 --- a/freebsd/sys/dev/mii/brgphy.c +++ b/freebsd/sys/dev/mii/brgphy.c @@ -87,7 +87,7 @@ static device_method_t brgphy_methods[] = { DEVMETHOD(device_attach, brgphy_attach), DEVMETHOD(device_detach, mii_phy_detach), DEVMETHOD(device_shutdown, bus_generic_shutdown), - { 0, 0 } + DEVMETHOD_END }; static devclass_t brgphy_devclass; @@ -144,6 +144,10 @@ static const struct mii_phydesc brgphys[] = { MII_PHY_DESC(xxBROADCOM_ALT1, BCM5761), MII_PHY_DESC(xxBROADCOM_ALT1, BCM5709S), MII_PHY_DESC(xxBROADCOM_ALT2, BCM5717C), + MII_PHY_DESC(xxBROADCOM_ALT2, BCM5719C), + MII_PHY_DESC(xxBROADCOM_ALT2, BCM5720C), + MII_PHY_DESC(xxBROADCOM_ALT2, BCM57765), + MII_PHY_DESC(xxBROADCOM_ALT2, BCM57780), MII_PHY_DESC(BROADCOM2, BCM5906), MII_PHY_END }; @@ -215,16 +219,20 @@ brgphy_attach(device_t dev) bsc->mii_model = MII_MODEL(ma->mii_id2); bsc->mii_rev = MII_REV(ma->mii_id2); bsc->serdes_flags = 0; + ifp = sc->mii_pdata->mii_ifp; if (bootverbose) device_printf(dev, "OUI 0x%06x, model 0x%04x, rev. %d\n", bsc->mii_oui, bsc->mii_model, bsc->mii_rev); + /* Find the MAC driver associated with this PHY. */ + if (strcmp(ifp->if_dname, "bge") == 0) + bge_sc = ifp->if_softc; + else if (strcmp(ifp->if_dname, "bce") == 0) + bce_sc = ifp->if_softc; + /* Handle any special cases based on the PHY ID */ switch (bsc->mii_oui) { - case MII_OUI_BROADCOM: - case MII_OUI_BROADCOM2: - break; case MII_OUI_xxBROADCOM: switch (bsc->mii_model) { case MII_MODEL_xxBROADCOM_BCM5706: @@ -244,7 +252,8 @@ brgphy_attach(device_t dev) sc->mii_flags |= MIIF_HAVEFIBER; } break; - } break; + } + break; case MII_OUI_xxBROADCOM_ALT1: switch (bsc->mii_model) { case MII_MODEL_xxBROADCOM_ALT1_BCM5708S: @@ -252,25 +261,19 @@ brgphy_attach(device_t dev) sc->mii_flags |= MIIF_HAVEFIBER; break; case MII_MODEL_xxBROADCOM_ALT1_BCM5709S: - bsc->serdes_flags |= BRGPHY_5709S; + /* + * XXX + * 5720S and 5709S shares the same PHY id. + * Assume 5720S PHY if parent device is bge(4). + */ + if (bge_sc != NULL) + bsc->serdes_flags |= BRGPHY_5708S; + else + bsc->serdes_flags |= BRGPHY_5709S; sc->mii_flags |= MIIF_HAVEFIBER; break; } break; - case MII_OUI_xxBROADCOM_ALT2: - /* No special handling yet. */ - break; - default: - device_printf(dev, "Unrecognized OUI for PHY!\n"); - } - - ifp = sc->mii_pdata->mii_ifp; - - /* Find the MAC driver associated with this PHY. */ - if (strcmp(ifp->if_dname, "bge") == 0) { - bge_sc = ifp->if_softc; - } else if (strcmp(ifp->if_dname, "bce") == 0) { - bce_sc = ifp->if_softc; } brgphy_reset(sc); @@ -400,8 +403,6 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) sc->mii_media_status != mii->mii_media_status || cmd == MII_MEDIACHG) { switch (bsc->mii_oui) { - case MII_OUI_BROADCOM: - break; case MII_OUI_xxBROADCOM: switch (bsc->mii_model) { case MII_MODEL_xxBROADCOM_BCM5400: @@ -419,8 +420,6 @@ brgphy_service(struct mii_softc *sc, struct mii_data *mii, int cmd) break; } break; - case MII_OUI_xxBROADCOM_ALT1: - break; } } mii_phy_update(sc, cmd); @@ -454,7 +453,7 @@ brgphy_setmedia(struct mii_softc *sc, int media) break; } - if ((media & IFM_GMASK) == IFM_FDX) { + if ((media & IFM_FDX) != 0) { bmcr |= BRGPHY_BMCR_FDX; gig = BRGPHY_1000CTL_AFD; } else { @@ -637,6 +636,11 @@ brgphy_mii_phy_auto(struct mii_softc *sc, int media) (sc->mii_flags & MIIF_FORCEPAUSE) != 0) anar |= BRGPHY_ANAR_PC | BRGPHY_ANAR_ASP; PHY_WRITE(sc, BRGPHY_MII_ANAR, anar); + ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD; + if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701) + ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC; + PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr); + PHY_READ(sc, BRGPHY_MII_1000CTL); } else { anar = BRGPHY_SERDES_ANAR_FDX | BRGPHY_SERDES_ANAR_HDX; if ((media & IFM_FLOW) != 0 || @@ -645,12 +649,6 @@ brgphy_mii_phy_auto(struct mii_softc *sc, int media) PHY_WRITE(sc, BRGPHY_SERDES_ANAR, anar); } - ktcr = BRGPHY_1000CTL_AFD | BRGPHY_1000CTL_AHD; - if (bsc->mii_model == MII_MODEL_xxBROADCOM_BCM5701) - ktcr |= BRGPHY_1000CTL_MSE | BRGPHY_1000CTL_MSC; - PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr); - ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL); - PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG); PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00); @@ -913,15 +911,25 @@ brgphy_reset(struct mii_softc *sc) struct bge_softc *bge_sc = NULL; struct bce_softc *bce_sc = NULL; struct ifnet *ifp; - int val; + int i, val; + + /* + * Perform a reset. Note that at least some Broadcom PHYs default to + * being powered down as well as isolated after a reset but don't work + * if one or both of these bits are cleared. However, they just work + * fine if both bits remain set, so we don't use mii_phy_reset() here. + */ + PHY_WRITE(sc, BRGPHY_MII_BMCR, BRGPHY_BMCR_RESET); - /* Perform a standard PHY reset. */ - mii_phy_reset(sc); + /* Wait 100ms for it to complete. */ + for (i = 0; i < 100; i++) { + if ((PHY_READ(sc, BRGPHY_MII_BMCR) & BRGPHY_BMCR_RESET) == 0) + break; + DELAY(1000); + } /* Handle any PHY specific procedures following the reset. */ switch (bsc->mii_oui) { - case MII_OUI_BROADCOM: - break; case MII_OUI_xxBROADCOM: switch (bsc->mii_model) { case MII_MODEL_xxBROADCOM_BCM5400: @@ -939,8 +947,14 @@ brgphy_reset(struct mii_softc *sc) break; } break; - case MII_OUI_xxBROADCOM_ALT1: case MII_OUI_xxBROADCOM_ALT2: + switch (bsc->mii_model) { + case MII_MODEL_xxBROADCOM_ALT2_BCM5717C: + case MII_MODEL_xxBROADCOM_ALT2_BCM5719C: + case MII_MODEL_xxBROADCOM_ALT2_BCM5720C: + case MII_MODEL_xxBROADCOM_ALT2_BCM57765: + return; + } break; } @@ -968,9 +982,10 @@ brgphy_reset(struct mii_softc *sc) if (bge_sc->bge_phy_flags & BGE_PHY_JITTER_BUG) brgphy_fixup_jitter_bug(sc); - brgphy_jumbo_settings(sc, ifp->if_mtu); + if (bge_sc->bge_flags & BGE_FLAG_JUMBO) + brgphy_jumbo_settings(sc, ifp->if_mtu); - if (bge_sc->bge_phy_flags & BGE_PHY_WIRESPEED) + if ((bge_sc->bge_phy_flags & BGE_PHY_NO_WIRESPEED) == 0) brgphy_ethernet_wirespeed(sc); /* Enable Link LED on Dell boxes */ |