Author: kevans Date: Wed Jan 16 14:42:33 2019 New Revision: 343095 URL: https://svnweb.freebsd.org/changeset/base/343095
Log: awg: Move MAC soft reset to awg_init_locked to avoid soft reset timeout From NetBSD: Since the MAC can get stuck in reset state with no link, ignore reset timeouts and continue with initializing the device. Fixes "soft reset timeout" issue at boot with no network cable plugged in. awg_init may be called multiple times throughout normal interface usage, so the tx/rx descriptor base address registers must be written after each MAC reset and are moved as such. This problem has been observed on FreeBSD, H3/H2+ devices with an internal PHY (includes OrangePi R1, OrangePi One at least). Reviewed by: manu, ganbold Obtained from: NetBSD MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D18844 Modified: head/sys/arm/allwinner/if_awg.c Modified: head/sys/arm/allwinner/if_awg.c ============================================================================== --- head/sys/arm/allwinner/if_awg.c Wed Jan 16 12:33:06 2019 (r343094) +++ head/sys/arm/allwinner/if_awg.c Wed Jan 16 14:42:33 2019 (r343095) @@ -750,6 +750,31 @@ awg_disable_intr(struct awg_softc *sc) WR4(sc, EMAC_INT_EN, 0); } +static int +awg_reset(struct awg_softc *sc) +{ + int retry; + + /* Soft reset all registers and logic */ + WR4(sc, EMAC_BASIC_CTL_1, BASIC_CTL_SOFT_RST); + + /* Wait for soft reset bit to self-clear */ + for (retry = SOFT_RST_RETRY; retry > 0; retry--) { + if ((RD4(sc, EMAC_BASIC_CTL_1) & BASIC_CTL_SOFT_RST) == 0) + break; + DELAY(10); + } + if (retry == 0) { + device_printf(sc->dev, "soft reset timed out\n"); +#ifdef AWG_DEBUG + awg_dump_regs(sc->dev); +#endif + return (ETIMEDOUT); + } + + return (0); +} + static void awg_init_locked(struct awg_softc *sc) { @@ -765,6 +790,12 @@ awg_init_locked(struct awg_softc *sc) if (if_getdrvflags(ifp) & IFF_DRV_RUNNING) return; + awg_reset(sc); + + /* Write transmit and receive descriptor base address registers */ + WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr); + WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr); + awg_setup_rxfilter(sc); /* Configure DMA burst length and priorities */ @@ -1653,40 +1684,6 @@ awg_phy_reset(device_t dev) return (0); } -static int -awg_reset(device_t dev) -{ - struct awg_softc *sc; - int retry; - - sc = device_get_softc(dev); - - /* Reset PHY if necessary */ - if (awg_phy_reset(dev) != 0) { - device_printf(dev, "failed to reset PHY\n"); - return (ENXIO); - } - - /* Soft reset all registers and logic */ - WR4(sc, EMAC_BASIC_CTL_1, BASIC_CTL_SOFT_RST); - - /* Wait for soft reset bit to self-clear */ - for (retry = SOFT_RST_RETRY; retry > 0; retry--) { - if ((RD4(sc, EMAC_BASIC_CTL_1) & BASIC_CTL_SOFT_RST) == 0) - break; - DELAY(10); - } - if (retry == 0) { - device_printf(dev, "soft reset timed out\n"); -#ifdef AWG_DEBUG - awg_dump_regs(dev); -#endif - return (ETIMEDOUT); - } - - return (0); -} - static void awg_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int error) { @@ -1840,10 +1837,6 @@ awg_setup_dma(device_t dev) bus_dmamap_sync(sc->rx.desc_tag, sc->rx.desc_map, BUS_DMASYNC_PREWRITE); - /* Write transmit and receive descriptor base address registers */ - WR4(sc, EMAC_TX_DMA_LIST, sc->tx.desc_ring_paddr); - WR4(sc, EMAC_RX_DMA_LIST, sc->rx.desc_ring_paddr); - return (0); } @@ -1888,10 +1881,12 @@ awg_attach(device_t dev) /* Read MAC address before resetting the chip */ awg_get_eaddr(dev, eaddr); - /* Soft reset EMAC core */ - error = awg_reset(dev); - if (error != 0) + /* Reset PHY if necessary */ + error = awg_phy_reset(dev); + if (error != 0) { + device_printf(dev, "failed to reset PHY\n"); return (error); + } /* Setup DMA descriptors */ error = awg_setup_dma(dev); _______________________________________________ svn-src-head@freebsd.org mailing list https://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"