mirror of
https://github.com/opnsense/src.git
synced 2026-04-21 14:17:06 -04:00
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:
parent
64edff948b
commit
e1968a0d2f
3 changed files with 79 additions and 26 deletions
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Reference in a new issue