Add support for the BCM5401 and BCM5411 10/100/1000Mbps copper gigE PHYs.

This basically updates the brgphy driver to support 10/100 modes in
addition to 1000Mbps modes.
This commit is contained in:
Bill Paul 2001-09-04 22:00:33 +00:00
parent 64edff948b
commit e1968a0d2f
3 changed files with 79 additions and 26 deletions

View file

@ -44,6 +44,7 @@
#include <sys/socket.h>
#include <sys/bus.h>
#include <machine/clock.h>
#include <net/if.h>
#include <net/if_media.h>
@ -97,13 +98,25 @@ static int brgphy_probe(dev)
ma = device_get_ivars(dev);
if (MII_OUI(ma->mii_id1, ma->mii_id2) != MII_OUI_xxBROADCOM ||
MII_MODEL(ma->mii_id2) != MII_MODEL_xxBROADCOM_BCM5400)
return(ENXIO);
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5400) {
device_set_desc(dev, MII_STR_xxBROADCOM_BCM5400);
return(0);
}
device_set_desc(dev, MII_STR_xxBROADCOM_BCM5400);
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5401) {
device_set_desc(dev, MII_STR_xxBROADCOM_BCM5401);
return(0);
}
return(0);
if (MII_OUI(ma->mii_id1, ma->mii_id2) == MII_OUI_xxBROADCOM &&
MII_MODEL(ma->mii_id2) == MII_MODEL_xxBROADCOM_BCM5411) {
device_set_desc(dev, MII_STR_xxBROADCOM_BCM5411);
return(0);
}
return(ENXIO);
}
static int brgphy_attach(dev)
@ -140,10 +153,16 @@ static int brgphy_attach(dev)
mii_phy_reset(sc);
sc->mii_capabilities =
PHY_READ(sc, MII_BMSR) & ma->mii_capmask;
device_printf(dev, " ");
if (sc->mii_capabilities & BMSR_MEDIAMASK)
mii_add_media(mii, (sc->mii_capabilities & ~BMSR_ANEG),
sc->mii_inst);
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_TX, 0, sc->mii_inst),
BRGPHY_BMCR_FDX);
PRINT("1000baseTX");
PRINT(", 1000baseTX");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_1000_TX, IFM_FDX, sc->mii_inst), 0);
PRINT("1000baseTX-FDX");
ADD(IFM_MAKEWORD(IFM_ETHER, IFM_AUTO, 0, sc->mii_inst), 0);
@ -167,6 +186,7 @@ static int brgphy_detach(dev)
mii = device_get_softc(device_get_parent(dev));
if (sc->mii_flags & MIIF_DOINGAUTO)
untimeout(mii_phy_auto_timeout, sc, sc->mii_auto_ch);
sc->mii_dev = NULL;
LIST_REMOVE(sc, mii_list);
@ -179,7 +199,7 @@ brgphy_service(sc, mii, cmd)
int cmd;
{
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int reg;
int reg, speed;
switch (cmd) {
case MII_POLLSTAT:
@ -225,15 +245,25 @@ brgphy_service(sc, mii, cmd)
(void) brgphy_mii_phy_auto(sc, 1);
break;
case IFM_1000_TX:
speed = BRGPHY_S1000;
goto setit;
case IFM_100_TX:
speed = BRGPHY_S100;
goto setit;
case IFM_10_T:
speed = BRGPHY_S10;
setit:
if ((ife->ifm_media & IFM_GMASK) == IFM_FDX) {
PHY_WRITE(sc, BRGPHY_MII_BMCR,
BRGPHY_BMCR_FDX|BRGPHY_BMCR_SPD1);
BRGPHY_BMCR_FDX|speed);
} else {
PHY_WRITE(sc, BRGPHY_MII_BMCR,
BRGPHY_BMCR_SPD1);
PHY_WRITE(sc, BRGPHY_MII_BMCR, speed);
}
PHY_WRITE(sc, BRGPHY_MII_ANAR, BRGPHY_SEL_TYPE);
if (IFM_SUBTYPE(ife->ifm_media) != IFM_1000_TX)
break;
/*
* When settning the link manually, one side must
* be the master and the other the slave. However
@ -251,8 +281,6 @@ brgphy_service(sc, mii, cmd)
}
break;
case IFM_100_T4:
case IFM_100_TX:
case IFM_10_T:
default:
return (EINVAL);
}
@ -316,7 +344,8 @@ brgphy_status(sc)
struct mii_softc *sc;
{
struct mii_data *mii = sc->mii_pdata;
int bmsr, bmcr, anlpar;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
int bmsr, bmcr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
@ -337,20 +366,37 @@ brgphy_status(sc)
return;
}
mii->mii_media_active |= IFM_1000_TX;
anlpar = PHY_READ(sc, BRGPHY_MII_AUXSTS);
if ((anlpar & BRGPHY_AUXSTS_AN_RES) == BRGPHY_RES_1000FD)
mii->mii_media_active |= IFM_FDX;
if ((anlpar & BRGPHY_AUXSTS_AN_RES) == BRGPHY_RES_1000HD)
mii->mii_media_active |= IFM_HDX;
switch (PHY_READ(sc, BRGPHY_MII_AUXSTS) &
BRGPHY_AUXSTS_AN_RES) {
case BRGPHY_RES_1000FD:
mii->mii_media_active |= IFM_1000_TX | IFM_FDX;
break;
case BRGPHY_RES_1000HD:
mii->mii_media_active |= IFM_1000_TX | IFM_HDX;
break;
case BRGPHY_RES_100FD:
mii->mii_media_active |= IFM_100_TX | IFM_FDX;
break;
case BRGPHY_RES_100T4:
mii->mii_media_active |= IFM_100_T4;
break;
case BRGPHY_RES_100HD:
mii->mii_media_active |= IFM_100_TX | IFM_HDX;
break;
case BRGPHY_RES_10FD:
mii->mii_media_active |= IFM_10_T | IFM_FDX;
break;
case BRGPHY_RES_10HD:
mii->mii_media_active |= IFM_10_T | IFM_HDX;
break;
default:
mii->mii_media_active |= IFM_NONE;
break;
}
return;
}
mii->mii_media_active |= IFM_1000_TX;
if (bmcr & BRGPHY_BMCR_FDX)
mii->mii_media_active |= IFM_FDX;
else
mii->mii_media_active |= IFM_HDX;
mii->mii_media_active = ife->ifm_media;
return;
}

View file

@ -68,14 +68,14 @@
#define BRGPHY_MII_ANAR 0x04
#define BRGPHY_ANAR_NP 0x8000 /* Next page */
#define BRGPHY_ANAR_RF 0x2000 /* Remote fault */
#define BRGPHY_ANAR_ASP 0x0800 /* Asymetric Pause */
#define BRGPHY_ANAR_ASP 0x0800 /* Asymmetric Pause */
#define BRGPHY_ANAR_PC 0x0400 /* Pause capable */
#define BRGPHY_ANAR_SEL 0x001F /* selector field, 00001=Ethernet */
#define BRGPHY_MII_ANLPAR 0x05
#define BRGPHY_ANLPAR_NP 0x8000 /* Next page */
#define BRGPHY_ANLPAR_RF 0x2000 /* Remote fault */
#define BRGPHY_ANLPAR_ASP 0x0800 /* Asymetric Pause */
#define BRGPHY_ANLPAR_ASP 0x0800 /* Asymmetric Pause */
#define BRGPHY_ANLPAR_PC 0x0400 /* Pause capable */
#define BRGPHY_ANLPAR_SEL 0x001F /* selector field, 00001=Ethernet */
@ -183,6 +183,11 @@
#define BRGPHY_RES_1000FD 0x0700 /* 1000baseT full duplex */
#define BRGPHY_RES_1000HD 0x0600 /* 1000baseT half duplex */
#define BRGPHY_RES_100FD 0x0500 /* 100baseT full duplex */
#define BRGPHY_RES_100T4 0x0400 /* 100baseT4 */
#define BRGPHY_RES_100HD 0x0300 /* 100baseT half duplex */
#define BRGPHY_RES_10HD 0x0200 /* 10baseT full duplex */
#define BRGPHY_RES_10FD 0x0100 /* 10baseT half duplex */
#define BRGPHY_MII_ISR 0x1A /* interrupt status */
#define BRGPHY_ISR_PSERR 0x4000 /* Pair swap error */

View file

@ -105,6 +105,8 @@ model AMD 79c978 0x0039 Am79c978 HomePNA PHY
/* Broadcom Corp. PHYs. */
model BROADCOM 3c905Cphy 0x0017 3c905C 10/100 internal PHY
model xxBROADCOM BCM5400 0x0004 Broadcom 1000baseTX PHY
model xxBROADCOM BCM5401 0x0005 BCM5401 10/100/1000baseTX PHY
model xxBROADCOM BCM5411 0x0007 BCM5411 10/100/1000baseTX PHY
/* Davicom Semiconductor PHYs */
model xxDAVICOM DM9101 0x0000 DM9101 10/100 media interface