diff options
author | wpaul <wpaul@FreeBSD.org> | 2001-09-04 22:00:33 +0000 |
---|---|---|
committer | wpaul <wpaul@FreeBSD.org> | 2001-09-04 22:00:33 +0000 |
commit | 618942d5c6f6067e982237c33ae8f3c685cbfb8f (patch) | |
tree | 01140771021371fa8e87d6aeab2664d0c70f17aa /sys/dev/mii | |
parent | a073ff8672ddffa6502e583bf162b12e84154e98 (diff) | |
download | FreeBSD-src-618942d5c6f6067e982237c33ae8f3c685cbfb8f.zip FreeBSD-src-618942d5c6f6067e982237c33ae8f3c685cbfb8f.tar.gz |
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.
Diffstat (limited to 'sys/dev/mii')
-rw-r--r-- | sys/dev/mii/brgphy.c | 94 | ||||
-rw-r--r-- | sys/dev/mii/brgphyreg.h | 9 | ||||
-rw-r--r-- | sys/dev/mii/miidevs | 2 |
3 files changed, 79 insertions, 26 deletions
diff --git a/sys/dev/mii/brgphy.c b/sys/dev/mii/brgphy.c index 38febae..8a7909c 100644 --- a/sys/dev/mii/brgphy.c +++ b/sys/dev/mii/brgphy.c @@ -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; } diff --git a/sys/dev/mii/brgphyreg.h b/sys/dev/mii/brgphyreg.h index ce289cd..f86f2ce 100644 --- a/sys/dev/mii/brgphyreg.h +++ b/sys/dev/mii/brgphyreg.h @@ -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 */ diff --git a/sys/dev/mii/miidevs b/sys/dev/mii/miidevs index 9dba1b8..5a3e9f6 100644 --- a/sys/dev/mii/miidevs +++ b/sys/dev/mii/miidevs @@ -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 |