diff options
Diffstat (limited to 'sys/dev/mii/brgphy.c')
-rw-r--r-- | sys/dev/mii/brgphy.c | 119 |
1 files changed, 118 insertions, 1 deletions
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index b28da263e35..a7582be86e1 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -1,4 +1,4 @@ -/* $OpenBSD: brgphy.c,v 1.92 2010/04/09 22:01:37 sthen Exp $ */ +/* $OpenBSD: brgphy.c,v 1.93 2010/05/24 21:23:23 sthen Exp $ */ /* * Copyright (c) 2000 @@ -81,6 +81,7 @@ int brgphy_service(struct mii_softc *, struct mii_data *, int); void brgphy_copper_status(struct mii_softc *); void brgphy_fiber_status(struct mii_softc *); void brgphy_5708s_status(struct mii_softc *); +void brgphy_5709s_status(struct mii_softc *); int brgphy_mii_phy_auto(struct mii_softc *); void brgphy_loop(struct mii_softc *); void brgphy_reset(struct mii_softc *); @@ -108,6 +109,10 @@ const struct mii_phy_funcs brgphy_5708s_funcs = { brgphy_service, brgphy_5708s_status, brgphy_reset, }; +const struct mii_phy_funcs brgphy_5709s_funcs = { + brgphy_service, brgphy_5709s_status, brgphy_reset, +}; + static const struct mii_phydesc brgphys[] = { { MII_OUI_xxBROADCOM, MII_MODEL_xxBROADCOM_BCM5400, MII_STR_xxBROADCOM_BCM5400 }, @@ -165,6 +170,8 @@ static const struct mii_phydesc brgphys[] = { MII_STR_xxBROADCOM2_BCM5708S }, { MII_OUI_xxBROADCOM2, MII_MODEL_xxBROADCOM2_BCM5709C, MII_STR_xxBROADCOM2_BCM5709C }, + { MII_OUI_xxBROADCOM2, MII_MODEL_xxBROADCOM2_BCM5709S, + MII_STR_xxBROADCOM2_BCM5709S }, { MII_OUI_xxBROADCOM2, MII_MODEL_xxBROADCOM2_BCM5709CAX, MII_STR_xxBROADCOM2_BCM5709CAX }, { MII_OUI_xxBROADCOM3, MII_MODEL_xxBROADCOM3_BCM57780, @@ -223,6 +230,8 @@ brgphy_attach(struct device *parent, struct device *self, void *aux) if (strcmp(devname, "bnx") == 0) { if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5708) sc->mii_funcs = &brgphy_5708s_funcs; + else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709) + sc->mii_funcs = &brgphy_5709s_funcs; else sc->mii_funcs = &brgphy_fiber_funcs; } else @@ -613,6 +622,64 @@ brgphy_5708s_status(struct mii_softc *sc) mii->mii_media_active = ife->ifm_media; } +void +brgphy_5709s_status(struct mii_softc *sc) +{ + struct mii_data *mii = sc->mii_pdata; + struct ifmedia_entry *ife = mii->mii_media.ifm_cur; + int bmcr, bmsr; + + mii->mii_media_status = IFM_AVALID; + mii->mii_media_active = IFM_ETHER; + + bmsr = PHY_READ(sc, BRGPHY_MII_BMSR) | PHY_READ(sc, BRGPHY_MII_BMSR); + if (bmsr & BRGPHY_BMSR_LINK) + mii->mii_media_status |= IFM_ACTIVE; + + bmcr = PHY_READ(sc, BRGPHY_MII_BMCR); + if (bmcr & BRGPHY_BMCR_LOOP) + mii->mii_media_active |= IFM_LOOP; + + if (bmcr & BRGPHY_BMCR_AUTOEN) { + int xstat; + + if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) { + /* Erg, still trying, I guess... */ + mii->mii_media_active |= IFM_NONE; + return; + } + + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, + BRGPHY_BLOCK_ADDR_GP_STATUS); + + xstat = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS); + + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, + BRGPHY_BLOCK_ADDR_COMBO_IEEE0); + + switch (xstat & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) { + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10: + mii->mii_media_active |= IFM_10_FL; + break; + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100: + mii->mii_media_active |= IFM_100_FX; + break; + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G: + mii->mii_media_active |= IFM_1000_SX; + break; + case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G: + mii->mii_media_active |= IFM_2500_SX; + break; + } + + if (xstat & BRGPHY_GP_STATUS_TOP_ANEG_FDX) + mii->mii_media_active |= IFM_FDX; + else + mii->mii_media_active |= IFM_HDX; + } else + mii->mii_media_active = ife->ifm_media; +} + int brgphy_mii_phy_auto(struct mii_softc *sc) { @@ -796,6 +863,56 @@ brgphy_reset(struct mii_softc *sc) PHY_WRITE(sc, BRGPHY_5708S_BLOCK_ADDR, BRGPHY_5708S_DIG_PG0); } + } else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709 && + sc->mii_flags & MIIF_HAVEFIBER) { + /* Select the SerDes Digital block of the AN MMD. */ + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, + BRGPHY_BLOCK_ADDR_SERDES_DIG); + + PHY_WRITE(sc, BRGPHY_SERDES_DIG_1000X_CTL1, + (PHY_READ(sc, BRGPHY_SERDES_DIG_1000X_CTL1) & + ~BRGPHY_SD_DIG_1000X_CTL1_AUTODET) | + BRGPHY_SD_DIG_1000X_CTL1_FIBER); + + if (bnx_sc->bnx_phy_flags & BNX_PHY_2_5G_CAPABLE_FLAG) { + /* Select the Over 1G block of the AN MMD. */ + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, + BRGPHY_BLOCK_ADDR_OVER_1G); + + /* + * Enable autoneg "Next Page" to advertise + * 2.5G support. + */ + PHY_WRITE(sc, BRGPHY_OVER_1G_UNFORMAT_PG1, + PHY_READ(sc, BRGPHY_OVER_1G_UNFORMAT_PG1) | + BRGPHY_5708S_ANEG_NXT_PG_XMIT1_25G); + } + + /* + * Select the Multi-Rate Backplane Ethernet block of + * the AN MMD. + */ + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, + BRGPHY_BLOCK_ADDR_MRBE); + + /* Enable MRBE speed autoneg. */ + PHY_WRITE(sc, BRGPHY_MRBE_MSG_PG5_NP, + PHY_READ(sc, BRGPHY_MRBE_MSG_PG5_NP) | + BRGPHY_MRBE_MSG_PG5_NP_MBRE | + BRGPHY_MRBE_MSG_PG5_NP_T2); + + /* Select the Clause 73 User B0 block of the AN MMD. */ + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, + BRGPHY_BLOCK_ADDR_CL73_USER_B0); + + /* Enable MRBE speed autoneg. */ + PHY_WRITE(sc, BRGPHY_CL73_USER_B0_MBRE_CTL1, + BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP | + BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR | + BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG); + + PHY_WRITE(sc, BRGPHY_BLOCK_ADDR, + BRGPHY_BLOCK_ADDR_COMBO_IEEE0); } else if (BNX_CHIP_NUM(bnx_sc) == BNX_CHIP_NUM_5709) { if (BNX_CHIP_REV(bnx_sc) == BNX_CHIP_REV_Ax || BNX_CHIP_REV(bnx_sc) == BNX_CHIP_REV_Bx) |