summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2001-09-04 22:00:33 +0000
committerwpaul <wpaul@FreeBSD.org>2001-09-04 22:00:33 +0000
commit618942d5c6f6067e982237c33ae8f3c685cbfb8f (patch)
tree01140771021371fa8e87d6aeab2664d0c70f17aa /sys
parenta073ff8672ddffa6502e583bf162b12e84154e98 (diff)
downloadFreeBSD-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')
-rw-r--r--sys/dev/mii/brgphy.c94
-rw-r--r--sys/dev/mii/brgphyreg.h9
-rw-r--r--sys/dev/mii/miidevs2
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
OpenPOWER on IntegriCloud