Add support for IC Plus IP1001 PHY.

Tested by:	Stuart Fraser < stuart AT stuartfraser DOT net >
This commit is contained in:
Pyun YongHyeon 2008-04-05 00:52:07 +00:00
parent 5859ace94f
commit a76215ece3
3 changed files with 104 additions and 21 deletions

View File

@ -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);

View File

@ -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_ */

View File

@ -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