diff options
| author | msaitoh <msaitoh@NetBSD.org> | 2019-11-25 05:35:26 +0000 |
|---|---|---|
| committer | msaitoh <msaitoh@NetBSD.org> | 2019-11-25 05:35:26 +0000 |
| commit | 4bb3b1494844d47872a97d902d63a01ec755fbc5 (patch) | |
| tree | a191ef358602b56d305401d5eeda76a6bb496674 /sys/dev | |
| parent | 087635b81632323b08019a5340b25c9eb860b261 (diff) | |
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 (limited to 'sys/dev')
| -rw-r--r-- | sys/dev/pci/if_bge.c | 105 |
1 files changed, 83 insertions, 22 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c index 60219cc4d1f..20f2a12b5dc 100644 --- a/sys/dev/pci/if_bge.c +++ b/sys/dev/pci/if_bge.c @@ -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 @@ bge_miibus_readreg(device_t dev, int phy, int reg, uint16_t *val) 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 @@ static int 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 @@ bge_miibus_writereg(device_t dev, int phy, int reg, uint16_t val) 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 @@ bge_miibus_writereg(device_t dev, int phy, int reg, uint16_t val) return ETIMEDOUT; } - return 0; + return rv; } static void @@ -3176,14 +3188,14 @@ bge_attach(device_t parent, device_t self, void *aux) 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_attach(device_t parent, device_t self, void *aux) 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 @@ bge_attach(device_t parent, device_t self, void *aux) 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 @@ bge_attach(device_t parent, device_t self, void *aux) 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,8 @@ bge_attach(device_t parent, device_t self, void *aux) /* 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 @@ -3886,18 +3912,53 @@ bge_attach(device_t parent, device_t self, void *aux) * if we get a conflict with the ASF firmware accessing * the PHY. */ - BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); - bge_asf_driver_up(sc); + 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 + * probe if ASF is running. Retry a couple of times + * if we get a conflict with the ASF firmware accessing + * the PHY. + */ + trys = 0; + BGE_CLRBIT(sc, BGE_MODE_CTL, BGE_MODECTL_STACKUP); 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, |
