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.

Reply via email to