summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authordavidch <davidch@FreeBSD.org>2008-06-13 01:20:29 +0000
committerdavidch <davidch@FreeBSD.org>2008-06-13 01:20:29 +0000
commitd2be8fbeee531573c7493c8eecfe9a6abeab1cbe (patch)
tree9281e82f252f18d1ba2cd4ccf9d011c6ddc9d5b3 /sys/dev
parent21569896cfb669ae5ec09c9a90c4a59b1023a9e2 (diff)
downloadFreeBSD-src-d2be8fbeee531573c7493c8eecfe9a6abeab1cbe.zip
FreeBSD-src-d2be8fbeee531573c7493c8eecfe9a6abeab1cbe.tar.gz
- Added support for BCM5709 and BCM5716.
MFC after: 2 weeks
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/mii/brgphy.c68
1 files changed, 59 insertions, 9 deletions
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c
index 87ecedb..f8c3839 100644
--- a/sys/dev/mii/brgphy.c
+++ b/sys/dev/mii/brgphy.c
@@ -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);
+
+ /* Disable 1000BaseT advertisements. */
PHY_WRITE(sc, BRGPHY_MII_1000CTL, 0);
- PHY_WRITE(sc, BRGPHY_MII_BMCR, bmcr);
+ /* 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);
OpenPOWER on IntegriCloud