diff --git a/sys/arch/arm/sunxi/sunxi_emac.c b/sys/arch/arm/sunxi/sunxi_emac.c index e1798c94a2cc..82ecb621746e 100644 --- a/sys/arch/arm/sunxi/sunxi_emac.c +++ b/sys/arch/arm/sunxi/sunxi_emac.c @@ -628,31 +628,6 @@ sunxi_emac_dump_regs(struct sunxi_emac_softc *sc) } #endif -static int -sunxi_emac_reset(struct sunxi_emac_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) { - aprint_debug_dev(sc->dev, "soft reset timed out\n"); -#ifdef SUNXI_EMAC_DEBUG - sunxi_emac_dump_regs(sc); -#endif - return ETIMEDOUT; - } - - return 0; -} - static int sunxi_emac_init_locked(struct sunxi_emac_softc *sc) { @@ -665,13 +640,6 @@ sunxi_emac_init_locked(struct sunxi_emac_softc *sc) if ((ifp->if_flags & IFF_RUNNING) != 0) return 0; - /* Soft reset EMAC core */ - sunxi_emac_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); - sunxi_emac_setup_rxfilter(sc); /* Configure DMA burst length and priorities */ @@ -1080,6 +1048,11 @@ sunxi_emac_setup_resources(struct sunxi_emac_softc *sc) return error; } if (sc->rst_ephy != NULL) { + /* + * U-Boot will leave the ephy reset de-asserted, and the soft + * reset will hang as a result. + */ + fdtbus_reset_assert(sc->rst_ephy); error = fdtbus_reset_deassert(sc->rst_ephy); if (error != 0) { aprint_error_dev(sc->dev, @@ -1189,6 +1162,37 @@ sunxi_emac_phy_reset(struct sunxi_emac_softc *sc) return 0; } +static int +sunxi_emac_reset(struct sunxi_emac_softc *sc) +{ + int retry; + + /* Reset PHY if necessary */ + if (sunxi_emac_phy_reset(sc) != 0) { + aprint_error_dev(sc->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) { + aprint_error_dev(sc->dev, "soft reset timed out\n"); +#ifdef SUNXI_EMAC_DEBUG + sunxi_emac_dump_regs(sc); +#endif + return ETIMEDOUT; + } + + return 0; +} + static int sunxi_emac_setup_dma(struct sunxi_emac_softc *sc) { @@ -1281,6 +1285,10 @@ sunxi_emac_setup_dma(struct sunxi_emac_softc *sc) 0, sc->rx.desc_map->dm_mapsize, BUS_DMASYNC_PREREAD|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; } @@ -1401,11 +1409,9 @@ sunxi_emac_attach(device_t parent, device_t self, void *aux) sunxi_emac_get_eaddr(sc, eaddr); aprint_normal_dev(self, "Ethernet address %s\n", ether_sprintf(eaddr)); - /* Reset PHY if necessary */ - if (sunxi_emac_phy_reset(sc) != 0) { - aprint_error_dev(self, "failed to reset PHY\n"); + /* Soft reset EMAC core */ + if (sunxi_emac_reset(sc) != 0) return; - } /* Setup DMA descriptors */ if (sunxi_emac_setup_dma(sc) != 0) {