Add support for IC Plus IP1001 PHY.
Tested by: Stuart Fraser < stuart AT stuartfraser DOT net >
This commit is contained in:
parent
5859ace94f
commit
a76215ece3
@ -30,7 +30,7 @@
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
/*
|
||||
* Driver for the IC Plus IP1000A 10/100/1000 PHY.
|
||||
* Driver for the IC Plus IP1000A/IP1001 10/100/1000 PHY.
|
||||
*/
|
||||
|
||||
#include <sys/param.h>
|
||||
@ -57,6 +57,12 @@ __FBSDID("$FreeBSD$");
|
||||
static int ip1000phy_probe(device_t);
|
||||
static int ip1000phy_attach(device_t);
|
||||
|
||||
struct ip1000phy_softc {
|
||||
struct mii_softc mii_sc;
|
||||
int model;
|
||||
int revision;
|
||||
};
|
||||
|
||||
static device_method_t ip1000phy_methods[] = {
|
||||
/* device interface */
|
||||
DEVMETHOD(device_probe, ip1000phy_probe),
|
||||
@ -82,6 +88,7 @@ static int ip1000phy_mii_phy_auto(struct mii_softc *);
|
||||
|
||||
static const struct mii_phydesc ip1000phys[] = {
|
||||
MII_PHY_DESC(ICPLUS, IP1000A),
|
||||
MII_PHY_DESC(ICPLUS, IP1001),
|
||||
MII_PHY_END
|
||||
};
|
||||
|
||||
@ -95,11 +102,13 @@ ip1000phy_probe(device_t dev)
|
||||
static int
|
||||
ip1000phy_attach(device_t dev)
|
||||
{
|
||||
struct ip1000phy_softc *isc;
|
||||
struct mii_softc *sc;
|
||||
struct mii_attach_args *ma;
|
||||
struct mii_data *mii;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
isc = device_get_softc(dev);
|
||||
sc = &isc->mii_sc;
|
||||
ma = device_get_ivars(dev);
|
||||
sc->mii_dev = device_get_parent(dev);
|
||||
mii = device_get_softc(sc->mii_dev);
|
||||
@ -114,6 +123,9 @@ ip1000phy_attach(device_t dev)
|
||||
|
||||
mii->mii_instance++;
|
||||
|
||||
isc->model = MII_MODEL(ma->mii_id2);
|
||||
isc->revision = MII_REV(ma->mii_id2);
|
||||
|
||||
device_printf(dev, " ");
|
||||
|
||||
#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
|
||||
@ -302,10 +314,13 @@ ip1000phy_service(struct mii_softc *sc, struct mii_data *mii, int cmd)
|
||||
static void
|
||||
ip1000phy_status(struct mii_softc *sc)
|
||||
{
|
||||
struct ip1000phy_softc *isc;
|
||||
struct mii_data *mii = sc->mii_pdata;
|
||||
uint32_t bmsr, bmcr, stat;
|
||||
uint32_t ar, lpar;
|
||||
|
||||
isc = (struct ip1000phy_softc *)sc;
|
||||
|
||||
mii->mii_media_status = IFM_AVALID;
|
||||
mii->mii_media_active = IFM_ETHER;
|
||||
|
||||
@ -326,25 +341,44 @@ ip1000phy_status(struct mii_softc *sc)
|
||||
}
|
||||
}
|
||||
|
||||
stat = PHY_READ(sc, STGE_PhyCtrl);
|
||||
switch (PC_LinkSpeed(stat)) {
|
||||
case PC_LinkSpeed_Down:
|
||||
mii->mii_media_active |= IFM_NONE;
|
||||
return;
|
||||
case PC_LinkSpeed_10:
|
||||
mii->mii_media_active |= IFM_10_T;
|
||||
break;
|
||||
case PC_LinkSpeed_100:
|
||||
mii->mii_media_active |= IFM_100_TX;
|
||||
break;
|
||||
case PC_LinkSpeed_1000:
|
||||
mii->mii_media_active |= IFM_1000_T;
|
||||
break;
|
||||
if (isc->model == MII_MODEL_ICPLUS_IP1001) {
|
||||
stat = PHY_READ(sc, IP1000PHY_LSR);
|
||||
switch (stat & IP1000PHY_LSR_SPEED_MASK) {
|
||||
case IP1000PHY_LSR_SPEED_10:
|
||||
mii->mii_media_active |= IFM_10_T;
|
||||
break;
|
||||
case IP1000PHY_LSR_SPEED_100:
|
||||
mii->mii_media_active |= IFM_100_TX;
|
||||
break;
|
||||
case IP1000PHY_LSR_SPEED_1000:
|
||||
mii->mii_media_active |= IFM_1000_T;
|
||||
break;
|
||||
}
|
||||
if ((stat & IP1000PHY_LSR_FULL_DUPLEX) != 0)
|
||||
mii->mii_media_active |= IFM_FDX;
|
||||
else
|
||||
mii->mii_media_active |= IFM_HDX;
|
||||
} else {
|
||||
stat = PHY_READ(sc, STGE_PhyCtrl);
|
||||
switch (PC_LinkSpeed(stat)) {
|
||||
case PC_LinkSpeed_Down:
|
||||
mii->mii_media_active |= IFM_NONE;
|
||||
return;
|
||||
case PC_LinkSpeed_10:
|
||||
mii->mii_media_active |= IFM_10_T;
|
||||
break;
|
||||
case PC_LinkSpeed_100:
|
||||
mii->mii_media_active |= IFM_100_TX;
|
||||
break;
|
||||
case PC_LinkSpeed_1000:
|
||||
mii->mii_media_active |= IFM_1000_T;
|
||||
break;
|
||||
}
|
||||
if ((stat & PC_PhyDuplexStatus) != 0)
|
||||
mii->mii_media_active |= IFM_FDX;
|
||||
else
|
||||
mii->mii_media_active |= IFM_HDX;
|
||||
}
|
||||
if ((stat & PC_PhyDuplexStatus) != 0)
|
||||
mii->mii_media_active |= IFM_FDX;
|
||||
else
|
||||
mii->mii_media_active |= IFM_HDX;
|
||||
|
||||
ar = PHY_READ(sc, IP1000PHY_MII_ANAR);
|
||||
lpar = PHY_READ(sc, IP1000PHY_MII_ANLPAR);
|
||||
@ -410,10 +444,12 @@ ip1000phy_load_dspcode(struct mii_softc *sc)
|
||||
static void
|
||||
ip1000phy_reset(struct mii_softc *sc)
|
||||
{
|
||||
struct ip1000phy_softc *isc;
|
||||
struct stge_softc *stge_sc;
|
||||
struct mii_data *mii;
|
||||
uint32_t reg;
|
||||
|
||||
isc = (struct ip1000phy_softc *)sc;
|
||||
mii_phy_reset(sc);
|
||||
|
||||
/* clear autoneg/full-duplex as we don't want it after reset */
|
||||
@ -426,7 +462,8 @@ ip1000phy_reset(struct mii_softc *sc)
|
||||
* XXX There should be more general way to pass PHY specific
|
||||
* data via mii interface.
|
||||
*/
|
||||
if (strcmp(mii->mii_ifp->if_dname, "stge") == 0) {
|
||||
if (isc->model == MII_MODEL_ICPLUS_IP1000A &&
|
||||
strcmp(mii->mii_ifp->if_dname, "stge") == 0) {
|
||||
stge_sc = mii->mii_ifp->if_softc;
|
||||
if (stge_sc->sc_rev >= 0x40 && stge_sc->sc_rev <= 0x4e)
|
||||
ip1000phy_load_dspcode(sc);
|
||||
|
@ -138,4 +138,49 @@
|
||||
#define IP1000PHY_EXTSTS_1000X 0x4000
|
||||
#define IP1000PHY_EXTSTS_1000X_FDX 0x8000
|
||||
|
||||
/* PHY specific control & status register. IP1001 only. */
|
||||
#define IP1000PHY_SCSR 0x10
|
||||
#define IP1000PHY_SCSR_RXPHASE_SEL 0x0001
|
||||
#define IP1000PHY_SCSR_TXPHASE_SEL 0x0002
|
||||
#define IP1000PHY_SCSR_REPEATOR_MODE 0x0004
|
||||
#define IP1000PHY_SCSR_RESERVED1_DEF 0x0008
|
||||
#define IP1000PHY_SCSR_RXCLK_DRV_MASK 0x0060
|
||||
#define IP1000PHY_SCSR_RXCLK_DRV_DEF 0x0040
|
||||
#define IP1000PHY_SCSR_RXD_DRV_MASK 0x0180
|
||||
#define IP1000PHY_SCSR_RXD_DRV_DEF 0x0100
|
||||
#define IP1000PHY_SCSR_JABBER_ENB 0x0200
|
||||
#define IP1000PHY_SCSR_HEART_BEAT_ENB 0x0400
|
||||
#define IP1000PHY_SCSR_DOWNSHIFT_ENB 0x0800
|
||||
#define IP1000PHY_SCSR_RESERVED2_DEF 0x1000
|
||||
#define IP1000PHY_SCSR_LED_DRV_4MA 0x0000
|
||||
#define IP1000PHY_SCSR_LED_DRV_8MA 0x2000
|
||||
#define IP1000PHY_SCSR_LED_MODE_MASK 0xC000
|
||||
#define IP1000PHY_SCSR_LED_MODE_DEF 0x0000
|
||||
|
||||
/* PHY link status register. IP1001 only. */
|
||||
#define IP1000PHY_LSR 0x11
|
||||
#define IP1000PHY_LSR_JABBER_DET 0x0200
|
||||
#define IP1000PHY_LSR_APS_SLEEP 0x0400
|
||||
#define IP1000PHY_LSR_MDIX 0x0800
|
||||
#define IP1000PHY_LSR_FULL_DUPLEX 0x1000
|
||||
#define IP1000PHY_LSR_SPEED_10 0x0000
|
||||
#define IP1000PHY_LSR_SPEED_100 0x2000
|
||||
#define IP1000PHY_LSR_SPEED_1000 0x4000
|
||||
#define IP1000PHY_LSR_SPEED_MASK 0x6000
|
||||
#define IP1000PHY_LSR_LINKUP 0x8000
|
||||
|
||||
/* PHY specific control register 2. IP1001 only. */
|
||||
#define IP1000PHY_SCR
|
||||
#define IP1000PHY_SCR_SEW_RATE_MASK 0x0003
|
||||
#define IP1000PHY_SCR_SEW_RATE_DEF 0x0003
|
||||
#define IP1000PHY_SCR_AUTO_XOVER 0x0004
|
||||
#define IP1000PHY_SCR_SPEED_10_100_ENB 0x0040
|
||||
#define IP1000PHY_SCR_FIFO_LATENCY_2 0x0000
|
||||
#define IP1000PHY_SCR_FIFO_LATENCY_3 0x0080
|
||||
#define IP1000PHY_SCR_FIFO_LATENCY_4 0x0100
|
||||
#define IP1000PHY_SCR_FIFO_LATENCY_5 0x0180
|
||||
#define IP1000PHY_SCR_MDIX_ENB 0x0200
|
||||
#define IP1000PHY_SCR_RESERVED_DEF 0x0400
|
||||
#define IP1000PHY_SCR_APS_ON 0x0800
|
||||
|
||||
#endif /* _DEV_MII_IP1000PHYREG_H_ */
|
||||
|
@ -159,6 +159,7 @@ model xxICS 1893 0x0004 ICS1893 10/100 media interface
|
||||
/* IC Plus Corp. PHYs */
|
||||
model ICPLUS IP101 0x0005 IC Plus 10/100 PHY
|
||||
model ICPLUS IP1000A 0x0008 IC Plus 10/100/1000 media interface
|
||||
model ICPLUS IP1001 0x0019 IC Plus IP1001 10/100/1000 media interface
|
||||
|
||||
/* Intel PHYs */
|
||||
model xxINTEL I82553AB 0x0000 i83553 10/100 media interface
|
||||
|
Loading…
Reference in New Issue
Block a user