From 1d2bfa591d1b1cd4235b94c4f908f77e9df93256 Mon Sep 17 00:00:00 2001 From: briggs Date: Sun, 2 Nov 2003 01:42:28 +0000 Subject: [PATCH] Implement a separate nsphy_reset(). There are two reasons for this: 1) This PHY can take an inordinate amount of time to reset if media is attached. Under fairly normal circumstances, up to near one second. This is because it appears to go through an implicit autonegotiation cycle as part of the reset. 2) During reset and autonegotiation, the BMCR will clear the reset bit before the process is complete. It will return 0 until the process is complete and it's safe to access the PHY again. This gets the on-board pcnet + nsphy ethernet working properly for me on an IBM PC Server/325. Fixes PR/16346. --- sys/dev/mii/nsphy.c | 46 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/sys/dev/mii/nsphy.c b/sys/dev/mii/nsphy.c index 25b83b772f85..423c3afe5c7a 100644 --- a/sys/dev/mii/nsphy.c +++ b/sys/dev/mii/nsphy.c @@ -1,4 +1,4 @@ -/* $NetBSD: nsphy.c,v 1.39 2003/04/29 01:49:34 thorpej Exp $ */ +/* $NetBSD: nsphy.c,v 1.40 2003/11/02 01:42:28 briggs Exp $ */ /*- * Copyright (c) 1998, 1999, 2000 The NetBSD Foundation, Inc. @@ -72,7 +72,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: nsphy.c,v 1.39 2003/04/29 01:49:34 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: nsphy.c,v 1.40 2003/11/02 01:42:28 briggs Exp $"); #include #include @@ -98,9 +98,10 @@ CFATTACH_DECL(nsphy, sizeof(struct mii_softc), int nsphy_service(struct mii_softc *, struct mii_data *, int); void nsphy_status(struct mii_softc *); +void nsphy_reset(struct mii_softc *sc); const struct mii_phy_funcs nsphy_funcs = { - nsphy_service, nsphy_status, mii_phy_reset, + nsphy_service, nsphy_status, nsphy_reset, }; const struct mii_phydesc nsphys[] = { @@ -326,3 +327,42 @@ nsphy_status(struct mii_softc *sc) } else mii->mii_media_active = ife->ifm_media; } + +void +nsphy_reset(struct mii_softc *sc) +{ + int reg, i; + + if (sc->mii_flags & MIIF_NOISOLATE) + reg = BMCR_RESET; + else + reg = BMCR_RESET | BMCR_ISO; + PHY_WRITE(sc, MII_BMCR, reg); + + /* + * Give it a little time to settle in case we just got power. + * The DP83840A data sheet suggests that a soft reset not happen + * within 500us of power being applied. Be conservative. + */ + delay(1000); + + /* + * Wait another 2s for it to complete. + * This is only a little overkill as under normal circumstances + * the PHY can take up to 1s to complete reset. + * This is also a bit odd because after a reset, the BMCR will + * clear the reset bit and simply reports 0 even though the reset + * is not yet complete. + */ + for (i = 0; i < 1000; i++) { + reg = PHY_READ(sc, MII_BMCR); + if (reg && ((reg & BMCR_RESET) == 0)) + break; + delay(2000); + } + + if (sc->mii_inst != 0 && ((sc->mii_flags & MIIF_NOISOLATE) == 0)) { + PHY_WRITE(sc, MII_BMCR, reg | BMCR_ISO); + } +} +