brgphy: Bring in changes from OpenBSD
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 16 Aug 2011 09:45:30 +0000 (17:45 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Tue, 16 Aug 2011 14:16:17 +0000 (22:16 +0800)
- Link status is now detected using BMSR
- Extra link status detection based on AUXSTS is used for 5906
- Shuffle 5906 EPHY setting around
- brgphy_loop() is not necessary to start auto-negotiation

sys/dev/netif/mii_layer/brgphy.c
sys/dev/netif/mii_layer/brgphyreg.h

index 7e18e93..2d8ea22 100644 (file)
@@ -323,10 +323,11 @@ setit:
 
                /*
                 * Check to see if we have link.  If we do, we don't
-                * need to restart the autonegotiation process.
+                * need to restart the autonegotiation process.  Read
+                * the BMSR twice in case it's latched.
                 */
-               reg = PHY_READ(sc, BRGPHY_MII_AUXSTS);
-               if (reg & BRGPHY_AUXSTS_LINK) {
+               reg = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+               if (reg & BMSR_LINK) {
                        sc->mii_ticks = 0;
                        break;
                }
@@ -336,7 +337,7 @@ setit:
                 */
                if (++sc->mii_ticks <= sc->mii_anegticks)
                        break;
-               
+
                sc->mii_ticks = 0;
                brgphy_mii_phy_auto(sc);
                break;
@@ -373,13 +374,13 @@ static void
 brgphy_status(struct mii_softc *sc)
 {
        struct mii_data *mii = sc->mii_pdata;
-       int bmcr, aux;
+       int bmcr, bmsr;
 
        mii->mii_media_status = IFM_AVALID;
        mii->mii_media_active = IFM_ETHER;
 
-       aux = PHY_READ(sc, BRGPHY_MII_AUXSTS);
-       if (aux & BRGPHY_AUXSTS_LINK)
+       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);
@@ -387,13 +388,17 @@ brgphy_status(struct mii_softc *sc)
                mii->mii_media_active |= IFM_LOOP;
 
        if (bmcr & BRGPHY_BMCR_AUTOEN) {
-               if ((PHY_READ(sc, BRGPHY_MII_BMSR) & BRGPHY_BMSR_ACOMP) == 0) {
+               int auxsts;
+
+               if ((bmsr & BRGPHY_BMSR_ACOMP) == 0) {
                        /* Erg, still trying, I guess... */
                        mii->mii_media_active |= IFM_NONE;
                        return;
                }
 
-               switch (aux & BRGPHY_AUXSTS_AN_RES) {
+               auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
+
+               switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
                case BRGPHY_RES_1000FD:
                        mii->mii_media_active |= IFM_1000_T | IFM_FDX;
                        break;
@@ -416,6 +421,13 @@ brgphy_status(struct mii_softc *sc)
                        mii->mii_media_active |= IFM_10_T | IFM_HDX;
                        break;
                default:
+                       if (sc->mii_model == MII_MODEL_BROADCOM2_BCM5906) {
+                               mii->mii_media_active |= (auxsts &
+                                   BRGPHY_RES_100) ? IFM_100_TX : IFM_10_T;
+                               mii->mii_media_active |= (auxsts &
+                                   BRGPHY_RES_FULL) ? IFM_FDX : IFM_HDX;
+                               break;
+                       }
                        mii->mii_media_active |= IFM_NONE;
                        break;
                }
@@ -428,19 +440,21 @@ brgphy_status(struct mii_softc *sc)
 static void
 brgphy_mii_phy_auto(struct mii_softc *sc)
 {
-       int ktcr = 0;
+       int ktcr;
 
-       brgphy_loop(sc);
        brgphy_reset(sc);
+
+       PHY_WRITE(sc, BRGPHY_MII_ANAR,
+           BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA);
+       DELAY(1000);
+
        ktcr = BRGPHY_1000CTL_AFD|BRGPHY_1000CTL_AHD;
        if (sc->mii_model == MII_MODEL_xxBROADCOM_BCM5701)
                ktcr |= BRGPHY_1000CTL_MSE|BRGPHY_1000CTL_MSC;
        PHY_WRITE(sc, BRGPHY_MII_1000CTL, ktcr);
        ktcr = PHY_READ(sc, BRGPHY_MII_1000CTL);
        DELAY(1000);
-       PHY_WRITE(sc, BRGPHY_MII_ANAR,
-           BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA);
-       DELAY(1000);
+
        PHY_WRITE(sc, BRGPHY_MII_BMCR,
            BRGPHY_BMCR_AUTOEN | BRGPHY_BMCR_STARTNEG);
        PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
@@ -517,6 +531,10 @@ brgphy_reset(struct mii_softc *sc)
                /* Set Jumbo frame settings in the PHY. */
                brgphy_jumbo_settings(sc, ifp->if_mtu);
 
+               /* Adjust output voltage */
+               if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5906)
+                       PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12);
+
                /* Enable Ethernet@Wirespeed */
                if (bge_sc->bge_flags & BGE_FLAG_ETH_WIRESPEED)
                        brgphy_eth_wirespeed(sc);
@@ -527,10 +545,6 @@ brgphy_reset(struct mii_softc *sc)
                        PHY_READ(sc, BRGPHY_MII_PHY_EXTCTL)
                                & ~BRGPHY_PHY_EXTCTL_3_LED);
                }
-
-               /* Adjust output voltage (From Linux driver) */
-               if (bge_sc->bge_asicrev == BGE_ASICREV_BCM5906)
-                       PHY_WRITE(sc, BRGPHY_MII_EPHY_PTEST, 0x12);
        } else if (strncmp(ifp->if_xname, "bce", 3) == 0) {
                struct bce_softc *bce_sc = ifp->if_softc;
 
index 01be6d2..0e7a472 100644 (file)
 #define BRGPHY_RES_100HD       0x0300  /* 100baseT half duplex */
 #define BRGPHY_RES_10FD                0x0200  /* 10baseT full duplex */
 #define BRGPHY_RES_10HD                0x0100  /* 10baseT half duplex */
+/* 5906 */
+#define BRGPHY_RES_100         0x0008  /* 100baseT */
+#define BRGPHY_RES_FULL                0x0001  /* full duplex */
 
 #define BRGPHY_MII_ISR         0x1A    /* interrupt status */
 #define BRGPHY_ISR_PSERR       0x4000  /* Pair swap error */