Please test the following diff if you have a system utilizing the BCM5709S chipset. This diff adds support for the fiber PHY coupled with the BCM5709S controller.
Index: pci/if_bnx.c =================================================================== RCS file: /cvs/src/sys/dev/pci/if_bnx.c,v retrieving revision 1.86 diff -u -p -r1.86 if_bnx.c --- pci/if_bnx.c 23 Nov 2009 10:54:43 -0000 1.86 +++ pci/if_bnx.c 28 Mar 2010 21:45:11 -0000 @@ -42,6 +42,7 @@ __FBSDID("$FreeBSD: src/sys/dev/bce/if_b * BCM5708C B1, B2 * BCM5708S B1, B2 * BCM5709C A1, C0 + * BCM5709S A1, C0 * BCM5716 C0 * * The following controllers are not supported by this driver: @@ -50,7 +51,7 @@ __FBSDID("$FreeBSD: src/sys/dev/bce/if_b * BCM5708C A0, B0 * BCM5708S A0, B0 * BCM5709C A0 B0, B1, B2 (pre-production) - * BCM5709S A0, A1, B0, B1, B2, C0 (pre-production) + * BCM5709S A0, B0, B1, B2 (pre-production) */ #include <dev/pci/if_bnxreg.h> @@ -340,6 +341,7 @@ int bnx_nvram_write(struct bnx_softc *, /* */ /****************************************************************************/ void bnx_get_media(struct bnx_softc *); +void bnx_init_media(struct bnx_softc *); int bnx_dma_alloc(struct bnx_softc *); void bnx_dma_free(struct bnx_softc *); void bnx_release_resources(struct bnx_softc *); @@ -905,6 +907,9 @@ bnx_attachhook(void *xsc) sc->bnx_mii.mii_writereg = bnx_miibus_write_reg; sc->bnx_mii.mii_statchg = bnx_miibus_statchg; + /* Handle any special PHY initialization for SerDes PHYs. */ + bnx_init_media(sc); + /* Look for our PHY. */ ifmedia_init(&sc->bnx_mii.mii_media, 0, bnx_ifmedia_upd, bnx_ifmedia_sts); @@ -1120,6 +1125,16 @@ bnx_miibus_read_reg(struct device *dev, return(0); } + /* + * The BCM5709S PHY is an IEEE Clause 45 PHY + * with special mappings to work with IEEE + * Clause 22 register accesses. + */ + if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { + if (reg >= MII_BMCR && reg <= MII_ANLPRNP) + reg += 0x10; + } + if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { val = REG_RD(sc, BNX_EMAC_MDIO_MODE); val &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; @@ -1199,6 +1214,16 @@ bnx_miibus_write_reg(struct device *dev, "val = 0x%04X\n", __FUNCTION__, phy, (u_int16_t) reg & 0xffff, (u_int16_t) val & 0xffff); + /* + * The BCM5709S PHY is an IEEE Clause 45 PHY + * with special mappings to work with IEEE + * Clause 22 register accesses. + */ + if ((sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) != 0) { + if (reg >= MII_BMCR && reg <= MII_ANLPRNP) + reg += 0x10; + } + if (sc->bnx_phy_flags & BNX_PHY_INT_MODE_AUTO_POLLING_FLAG) { val1 = REG_RD(sc, BNX_EMAC_MDIO_MODE); val1 &= ~BNX_EMAC_MDIO_MODE_AUTO_POLL; @@ -2179,6 +2204,7 @@ bnx_get_media(struct bnx_softc *sc) DBPRINT(sc, BNX_INFO_LOAD, "BCM5709 s/w configured for SerDes.\n"); sc->bnx_phy_flags |= BNX_PHY_SERDES_FLAG; + break; default: DBPRINT(sc, BNX_INFO_LOAD, "BCM5709 s/w configured for Copper.\n"); @@ -2191,6 +2217,7 @@ bnx_get_media(struct bnx_softc *sc) DBPRINT(sc, BNX_INFO_LOAD, "BCM5709 s/w configured for SerDes.\n"); sc->bnx_phy_flags |= BNX_PHY_SERDES_FLAG; + break; default: DBPRINT(sc, BNX_INFO_LOAD, "BCM5709 s/w configured for Copper.\n"); @@ -2202,6 +2229,14 @@ bnx_get_media(struct bnx_softc *sc) if (sc->bnx_phy_flags && BNX_PHY_SERDES_FLAG) { sc->bnx_flags |= BNX_NO_WOL_FLAG; + + if (BNX_CHIP_NUM(sc) == BNX_CHIP_NUM_5709) + sc->bnx_phy_flags |= BNX_PHY_IEEE_CLAUSE_45_FLAG; + + /* + * The BCM5708S, BCM5709S, and BCM5716S controllers use a + * separate PHY for SerDes. + */ if (BNX_CHIP_NUM(sc) != BNX_CHIP_NUM_5706) { sc->bnx_phy_addr = 2; val = REG_RD_IND(sc, sc->bnx_shmem_base + @@ -2219,6 +2254,36 @@ bnx_get_media(struct bnx_softc *sc) bnx_get_media_exit: DBPRINT(sc, (BNX_INFO_LOAD | BNX_INFO_PHY), "Using PHY address %d.\n", sc->bnx_phy_addr); +} + +/****************************************************************************/ +/* Performs PHY initialization required before MII drivers access the */ +/* device. */ +/* */ +/* Returns: */ +/* Nothing. */ +/****************************************************************************/ +void +bnx_init_media(struct bnx_softc *sc) +{ + if (sc->bnx_phy_flags & BNX_PHY_IEEE_CLAUSE_45_FLAG) { + /* + * Configure the BCM5709S / BCM5716S PHYs to use traditional + * IEEE Clause 22 method. Otherwise we have no way to attach + * the PHY to the mii(4) layer. PHY specific configuration + * is done by the mii(4) layer. + */ + + /* Select auto-negotiation MMD of the PHY. */ + bnx_miibus_write_reg(&sc->bnx_dev, sc->bnx_phy_addr, + BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_ADDR_EXT); + + bnx_miibus_write_reg(&sc->bnx_dev, sc->bnx_phy_addr, + BRGPHY_ADDR_EXT, BRGPHY_ADDR_EXT_AN_MMD); + + bnx_miibus_write_reg(&sc->bnx_dev, sc->bnx_phy_addr, + BRGPHY_BLOCK_ADDR, BRGPHY_BLOCK_ADDR_COMBO_IEEE0); + } } /****************************************************************************/ Index: pci/if_bnxreg.h =================================================================== RCS file: /cvs/src/sys/dev/pci/if_bnxreg.h,v retrieving revision 1.34 diff -u -p -r1.34 if_bnxreg.h --- pci/if_bnxreg.h 23 Nov 2009 10:54:43 -0000 1.34 +++ pci/if_bnxreg.h 28 Mar 2010 23:59:31 -0000 @@ -4803,6 +4803,7 @@ struct bnx_softc { #define BNX_PHY_INT_MODE_MASK_FLAG 0x300 #define BNX_PHY_INT_MODE_AUTO_POLLING_FLAG 0x100 #define BNX_PHY_INT_MODE_LINK_READY_FLAG 0x200 +#define BNX_PHY_IEEE_CLAUSE_45_FLAG 0x400 /* Values that need to be shared with the PHY driver. */ u_int32_t bnx_shared_hw_cfg; Index: mii/brgphy.c =================================================================== RCS file: /cvs/src/sys/dev/mii/brgphy.c,v retrieving revision 1.91 diff -u -p -r1.91 brgphy.c --- mii/brgphy.c 6 Apr 2010 20:20:52 -0000 1.91 +++ mii/brgphy.c 7 Apr 2010 00:18:21 -0000 @@ -81,6 +81,7 @@ int brgphy_service(struct mii_softc *, s 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_ 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 }, @@ -161,6 +166,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, @@ -219,6 +226,8 @@ brgphy_attach(struct device *parent, str 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 @@ -609,6 +618,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) { @@ -792,6 +859,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) Index: mii/brgphyreg.h =================================================================== RCS file: /cvs/src/sys/dev/mii/brgphyreg.h,v retrieving revision 1.13 diff -u -p -r1.13 brgphyreg.h --- mii/brgphyreg.h 8 Nov 2008 03:03:50 -0000 1.13 +++ mii/brgphyreg.h 30 Mar 2010 00:16:57 -0000 @@ -369,6 +369,61 @@ /* End: PHY register values for the 5708S SerDes PHY */ /*******************************************************/ +/*******************************************************/ +/* Begin: PHY register values for the 5709S SerDes PHY */ +/*******************************************************/ + +/* 5709S SerDes "General Purpose Status" Registers */ +#define BRGPHY_BLOCK_ADDR_GP_STATUS 0x8120 +#define BRGPHY_GP_STATUS_TOP_ANEG_STATUS 0x1B +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK 0x3F00 +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10 0x0000 +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100 0x0100 +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G 0x0200 +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G 0x0300 +#define BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1GKX 0x0D00 +#define BRGPHY_GP_STATUS_TOP_ANEG_FDX 0x0008 +#define BRGPHY_GP_STATUS_TOP_ANEG_LINK_UP 0x0004 +#define BRGPHY_GP_STATUS_TOP_ANEG_CL73_COMP 0x0001 + +/* 5709S SerDes "SerDes Digital" Registers */ +#define BRGPHY_BLOCK_ADDR_SERDES_DIG 0x8300 +#define BRGPHY_SERDES_DIG_1000X_CTL1 0x0010 +#define BRGPHY_SD_DIG_1000X_CTL1_AUTODET 0x0010 +#define BRGPHY_SD_DIG_1000X_CTL1_FIBER 0x0001 + +/* 5709S SerDes "Over 1G" Registers */ +#define BRGPHY_BLOCK_ADDR_OVER_1G 0x8320 +#define BRGPHY_OVER_1G_UNFORMAT_PG1 0x19 + +/* 5709S SerDes "Multi-Rate Backplane Ethernet" Registers */ +#define BRGPHY_BLOCK_ADDR_MRBE 0x8350 +#define BRGPHY_MRBE_MSG_PG5_NP 0x10 +#define BRGPHY_MRBE_MSG_PG5_NP_MBRE 0x0001 +#define BRGPHY_MRBE_MSG_PG5_NP_T2 0x0001 + +/* 5709S SerDes "IEEE Clause 73 User B0" Registers */ +#define BRGPHY_BLOCK_ADDR_CL73_USER_B0 0x8370 +#define BRGPHY_CL73_USER_B0_MBRE_CTL1 0x12 +#define BRGPHY_CL73_USER_B0_MBRE_CTL1_NP_AFT_BP 0x2000 +#define BRGPHY_CL73_USER_B0_MBRE_CTL1_STA_MGR 0x4000 +#define BRGPHY_CL73_USER_B0_MBRE_CTL1_ANEG 0x8000 + +/* 5709S SerDes "IEEE Clause 73 User B0" Registers */ +#define BRGPHY_BLOCK_ADDR_ADDR_EXT 0xFFD0 + +/* 5709S SerDes "Combo IEEE 0" Registers */ +#define BRGPHY_BLOCK_ADDR_COMBO_IEEE0 0xFFE0 + +#define BRGPHY_ADDR_EXT 0x1E +#define BRGPHY_BLOCK_ADDR 0x1F + +#define BRGPHY_ADDR_EXT_AN_MMD 0x3800 + +/*******************************************************/ +/* End: PHY register values for the 5709S SerDes PHY */ +/*******************************************************/ + #define BRGPHY_INTRS \ ~(BRGPHY_IMR_LNK_CHG|BRGPHY_IMR_LSP_CHG|BRGPHY_IMR_DUP_CHG) -- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.