Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci Modify PHY initialization code. This change fix ...



details:   https://anonhg.NetBSD.org/src/rev/aa1506923099
branches:  trunk
changeset: 846624:aa1506923099
user:      msaitoh <msaitoh%NetBSD.org@localhost>
date:      Mon Nov 25 05:35:26 2019 +0000

description:
Modify PHY initialization code. This change fix a bug that SK-9D21 doesn't
detect MII PHY.
 - Add error check to bge_miibus_writereg().
 - Change return value of bge_miibus_readreg() when a read error occurred.
   It also add error message using with aprint_debug_dev(). This error occurs
   on some devices while detecting MII devices.
 - Move the location of BGE_MI_MODE register's initialization to next to
   bge_chipinit().
 - Set BGE_MAC_MODE before calling ifmedia_init() and/or mii_attach().
 - Add retry code for mii_attach() failed. Same as FreeBSD.

diffstat:

 sys/dev/pci/if_bge.c |  105 ++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 83 insertions(+), 22 deletions(-)

diffs (212 lines):

diff -r a94b30b13a57 -r aa1506923099 sys/dev/pci/if_bge.c
--- a/sys/dev/pci/if_bge.c      Mon Nov 25 05:18:59 2019 +0000
+++ b/sys/dev/pci/if_bge.c      Mon Nov 25 05:35:26 2019 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: if_bge.c,v 1.341 2019/11/25 05:18:59 msaitoh Exp $     */
+/*     $NetBSD: if_bge.c,v 1.342 2019/11/25 05:35:26 msaitoh Exp $     */
 
 /*
  * Copyright (c) 2001 Wind River Systems
@@ -79,7 +79,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.341 2019/11/25 05:18:59 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_bge.c,v 1.342 2019/11/25 05:35:26 msaitoh Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -1113,9 +1113,11 @@
        if (i == BGE_TIMEOUT) {
                aprint_error_dev(sc->bge_dev, "PHY read timed out\n");
                rv = ETIMEDOUT;
-       } else if ((data & BGE_MICOMM_READFAIL) != 0)
-               rv = -1;
-       else
+       } else if ((data & BGE_MICOMM_READFAIL) != 0) {
+               /* XXX This error occurs on some devices while attaching. */
+               aprint_debug_dev(sc->bge_dev, "PHY read I/O error\n");
+               rv = EIO;
+       } else
                *val = data & BGE_MICOMM_DATA;
 
        if (autopoll & BGE_MIMODE_AUTOPOLL) {
@@ -1133,7 +1135,8 @@
 bge_miibus_writereg(device_t dev, int phy, int reg, uint16_t val)
 {
        struct bge_softc *sc = device_private(dev);
-       uint32_t autopoll;
+       uint32_t data, autopoll;
+       int rv = 0;
        int i;
 
        if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5906 &&
@@ -1156,13 +1159,22 @@
 
        for (i = 0; i < BGE_TIMEOUT; i++) {
                delay(10);
-               if (!(CSR_READ_4(sc, BGE_MI_COMM) & BGE_MICOMM_BUSY)) {
+               data = CSR_READ_4(sc, BGE_MI_COMM);
+               if (!(data & BGE_MICOMM_BUSY)) {
                        delay(5);
-                       CSR_READ_4(sc, BGE_MI_COMM);
+                       data = CSR_READ_4(sc, BGE_MI_COMM);
                        break;
                }
        }
 
+       if (i == BGE_TIMEOUT) {
+               aprint_error_dev(sc->bge_dev, "PHY write timed out\n");
+               rv = ETIMEDOUT;
+       } else if ((data & BGE_MICOMM_READFAIL) != 0) {
+               aprint_error_dev(sc->bge_dev, "PHY write I/O error\n");
+               rv = EIO;
+       }
+
        if (autopoll & BGE_MIMODE_AUTOPOLL) {
                BGE_STS_SETBIT(sc, BGE_STS_AUTOPOLL);
                BGE_SETBIT_FLUSH(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
@@ -1176,7 +1188,7 @@
                return ETIMEDOUT;
        }
 
-       return 0;
+       return rv;
 }
 
 static void
@@ -3176,14 +3188,14 @@
        uint32_t                command;
        struct ifnet            *ifp;
        struct mii_data * const mii = &sc->bge_mii;
-       uint32_t                misccfg, mimode;
+       uint32_t                misccfg, mimode, macmode;
        void *                  kva;
        u_char                  eaddr[ETHER_ADDR_LEN];
        pcireg_t                memtype, subid, reg;
        bus_addr_t              memaddr;
        uint32_t                pm_ctl;
        bool                    no_seeprom;
-       int                     capmask;
+       int                     capmask, trys;
        int                     mii_flags;
        int                     map_flags;
        char intrbuf[PCI_INTRSTR_LEN];
@@ -3427,15 +3439,6 @@
            BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM57780)
                sc->bge_flags |= BGEF_CPMU_PRESENT;
 
-       /* Set MI_MODE */
-       mimode = BGE_MIMODE_PHYADDR(sc->bge_phy_addr);
-       if ((sc->bge_flags & BGEF_CPMU_PRESENT) != 0)
-               mimode |= BGE_MIMODE_500KHZ_CONST;
-       else
-               mimode |= BGE_MIMODE_BASE;
-       CSR_WRITE_4(sc, BGE_MI_MODE, mimode);
-       DELAY(80);
-
        /*
         * When using the BCM5701 in PCI-X mode, data corruption has
         * been observed in the first few bytes of some received packets.
@@ -3680,6 +3683,21 @@
                return;
        }
 
+       if (BGE_ASICREV(sc->bge_chipid) == BGE_ASICREV_BCM5700) {
+               BGE_SETBIT_FLUSH(sc, BGE_MISC_LOCAL_CTL,
+                   BGE_MLC_MISCIO_OUT1 | BGE_MLC_MISCIO_OUTEN1);
+               DELAY(100);
+       }
+
+       /* Set MI_MODE */
+       mimode = BGE_MIMODE_PHYADDR(sc->bge_phy_addr);
+       if ((sc->bge_flags & BGEF_CPMU_PRESENT) != 0)
+               mimode |= BGE_MIMODE_500KHZ_CONST;
+       else
+               mimode |= BGE_MIMODE_BASE;
+       CSR_WRITE_4_FLUSH(sc, BGE_MI_MODE, mimode);
+       DELAY(80);
+
        /*
         * Get station address from the EEPROM.
         */
@@ -3866,8 +3884,14 @@
        prop_dictionary_set_uint32(dict, "phyflags", sc->bge_phy_flags);
        prop_dictionary_set_uint32(dict, "chipid", sc->bge_chipid);
 
+       macmode = CSR_READ_4(sc, BGE_MAC_MODE);
+       macmode &= ~BGE_MACMODE_PORTMODE;
        /* Initialize ifmedia structures. */
        if (sc->bge_flags & BGEF_FIBER_TBI) {
+               CSR_WRITE_4_FLUSH(sc, BGE_MAC_MODE,
+                   macmode | BGE_PORTMODE_TBI);
+               DELAY(40);
+
                sc->ethercom.ec_ifmedia = &sc->bge_ifmedia;
                ifmedia_init(&sc->bge_ifmedia, IFM_IMASK, bge_ifmedia_upd,
                    bge_ifmedia_sts);
@@ -3879,6 +3903,22 @@
                /* Pretend the user requested this setting */
                sc->bge_ifmedia.ifm_media = sc->bge_ifmedia.ifm_cur->ifm_media;
        } else {
+               uint16_t phyreg;
+               int rv;
+               /*
+                * Do transceiver setup and tell the firmware the
+                * driver is down so we can try to get access the
+                * probe if ASF is running.  Retry a couple of times
+                * if we get a conflict with the ASF firmware accessing
+                * the PHY.
+                */
+               if (sc->bge_flags & BGEF_FIBER_MII)
+                       macmode |= BGE_PORTMODE_GMII;
+               else
+                       macmode |= BGE_PORTMODE_MII;
+               CSR_WRITE_4_FLUSH(sc, BGE_MAC_MODE, macmode);
+               DELAY(40);
+
                /*
                 * Do transceiver setup and tell the firmware the
                 * driver is down so we can try to get access the
@@ -3886,18 +3926,39 @@
                 * if we get a conflict with the ASF firmware accessing
                 * the PHY.
                 */
+               trys = 0;
                BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP);
-               bge_asf_driver_up(sc);
-
                sc->ethercom.ec_mii = mii;
                ifmedia_init(&mii->mii_media, 0, bge_ifmedia_upd,
                             bge_ifmedia_sts);
                mii_flags = MIIF_DOPAUSE;
                if (sc->bge_flags & BGEF_FIBER_MII)
                        mii_flags |= MIIF_HAVEFIBER;
+again:
+               bge_asf_driver_up(sc);
+               rv = bge_miibus_readreg(sc->bge_dev, sc->bge_phy_addr,
+                   MII_BMCR, &phyreg);
+               if ((rv != 0) || ((phyreg & BMCR_PDOWN) != 0)) {
+                       int i;
+
+                       bge_miibus_writereg(sc->bge_dev, sc->bge_phy_addr,
+                           MII_BMCR, BMCR_RESET);
+                       /* Wait up to 500ms for it to complete. */
+                       for (i = 0; i < 500; i++) {
+                               bge_miibus_readreg(sc->bge_dev,
+                                   sc->bge_phy_addr, MII_BMCR, &phyreg);
+                               if ((phyreg & BMCR_RESET) == 0)
+                                       break;
+                               DELAY(1000);
+                       }
+               }
+
                mii_attach(sc->bge_dev, mii, capmask, sc->bge_phy_addr,
                    MII_OFFSET_ANY, mii_flags);
 
+               if (LIST_EMPTY(&mii->mii_phys) && (trys++ < 4))
+                       goto again;
+
                if (LIST_EMPTY(&mii->mii_phys)) {
                        aprint_error_dev(sc->bge_dev, "no PHY found!\n");
                        ifmedia_add(&mii->mii_media, IFM_ETHER | IFM_MANUAL,



Home | Main Index | Thread Index | Old Index