On 2010/04/06 21:26, Brad wrote:
> 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.

Has anyone tested this on an R610 or R210?


> 
> 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