- Added support for BCM5709 and BCM5716.

MFC after:	2 weeks
This commit is contained in:
David Christensen 2008-06-13 01:20:29 +00:00
parent 7752e34d05
commit d75672d1c4

View File

@ -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);
PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr);
PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
/* Disable 1000BaseT advertisements. */
PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
/* 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);