Add support for the SMsC LAN83C183 PHY, which actually probes as a

Seeq 84220.

Also add an 84220-specific work-around for some braindamage (at least
in the PHY I'm working with) where the PHY always comes out of reset
isolated, regardless of the previous state of the BMCR_ISO bit. This
happens even if the PHY has address zero, which is contrary to the
part's datasheet...

The work-around is only applied if we notice BMCR_ISO is set when it
should be clear following reset. The fix is to wait 30mS and clear
it manually. (The change doesn't stick if it's cleared sooner than this)
This commit is contained in:
scw 2002-08-26 11:13:13 +00:00
parent 9bcd736b9d
commit ce2ec9e63e
1 changed files with 47 additions and 3 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: sqphy.c,v 1.27 2002/07/03 06:25:53 simonb Exp $ */
/* $NetBSD: sqphy.c,v 1.28 2002/08/26 11:13:13 scw Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@ -72,7 +72,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: sqphy.c,v 1.27 2002/07/03 06:25:53 simonb Exp $");
__KERNEL_RCSID(0, "$NetBSD: sqphy.c,v 1.28 2002/08/26 11:13:13 scw Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@ -100,11 +100,16 @@ struct cfattach sqphy_ca = {
int sqphy_service(struct mii_softc *, struct mii_data *, int);
void sqphy_status(struct mii_softc *);
void sqphy_84220_reset(struct mii_softc *);
const struct mii_phy_funcs sqphy_funcs = {
sqphy_service, sqphy_status, mii_phy_reset,
};
const struct mii_phy_funcs sqphy_84220_funcs = {
sqphy_service, sqphy_status, sqphy_84220_reset,
};
const struct mii_phydesc sqphys[] = {
{ MII_OUI_SEEQ, MII_MODEL_SEEQ_80220,
MII_STR_SEEQ_80220 },
@ -112,6 +117,9 @@ const struct mii_phydesc sqphys[] = {
{ MII_OUI_SEEQ, MII_MODEL_SEEQ_80225,
MII_STR_SEEQ_80225 },
{ MII_OUI_SEEQ, MII_MODEL_SEEQ_84220,
MII_STR_SEEQ_84220 },
{ 0, 0,
NULL },
};
@ -140,11 +148,21 @@ sqphyattach(struct device *parent, struct device *self, void *aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_funcs = &sqphy_funcs;
sc->mii_pdata = mii;
sc->mii_flags = ma->mii_flags;
sc->mii_anegticks = 5;
switch (MII_MODEL(ma->mii_id2)) {
case MII_MODEL_SEEQ_84220:
sc->mii_funcs = &sqphy_84220_funcs;
printf("%s: using Seeq 84220 isolate/reset hack\n",
sc->mii_dev.dv_xname);
break;
default:
sc->mii_funcs = &sqphy_funcs;
}
PHY_RESET(sc);
sc->mii_capabilities =
@ -265,3 +283,29 @@ sqphy_status(struct mii_softc *sc)
} else
mii->mii_media_active = ife->ifm_media;
}
void
sqphy_84220_reset(struct mii_softc *sc)
{
int reg;
mii_phy_reset(sc);
/*
* This PHY sometimes insists on coming out of reset isolated,
* even when the MDA[0-3] pins are pulled high (to indicate
* PHY address 0), contrary to the device's datasheet.
*
* Morever, simply clearing BMCR_ISO here isn't enough; the
* change won't stick until about 30mS *after* the PHY has
* been reset.
*
* This sucks.
*/
if ((sc->mii_inst == 0 || (sc->mii_flags & MIIF_NOISOLATE)) &&
((reg = PHY_READ(sc, MII_BMCR)) & BMCR_ISO) != 0) {
delay(30000);
PHY_WRITE(sc, MII_BMCR, reg & ~BMCR_ISO);
}
}