summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorChristian Weisgerber <naddy@cvs.openbsd.org>2009-08-08 17:12:41 +0000
committerChristian Weisgerber <naddy@cvs.openbsd.org>2009-08-08 17:12:41 +0000
commit21fe3c800fbf51817964c5f919277f3285cf07a3 (patch)
tree19820e338c83ff08a5a1a7d9a44ca2cf03a45e51 /sys/dev
parent23a993a7b5abf5fef84b39473385089038f025c8 (diff)
Add support for the IC Plus IP1001 GigE PHY. From FreeBSD, via Brad.
Tested by jasper@ with a IP1000A PHY to make sure it doesn't break existing model.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/mii/ipgphy.c113
-rw-r--r--sys/dev/mii/ipgphyreg.h48
2 files changed, 123 insertions, 38 deletions
diff --git a/sys/dev/mii/ipgphy.c b/sys/dev/mii/ipgphy.c
index 3683ccca528..aa2bda16185 100644
--- a/sys/dev/mii/ipgphy.c
+++ b/sys/dev/mii/ipgphy.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipgphy.c,v 1.11 2009/07/30 10:26:23 sthen Exp $ */
+/* $OpenBSD: ipgphy.c,v 1.12 2009/08/08 17:12:40 naddy Exp $ */
/*-
* Copyright (c) 2006, Pyun YongHyeon <yongari@FreeBSD.org>
@@ -29,7 +29,7 @@
*/
/*
- * 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>
@@ -80,6 +80,8 @@ const struct mii_phy_funcs ipgphy_funcs = {
static const struct mii_phydesc ipgphys[] = {
{ MII_OUI_ICPLUS, MII_MODEL_ICPLUS_IP1000A,
MII_STR_ICPLUS_IP1000A },
+ { MII_OUI_ICPLUS, MII_MODEL_ICPLUS_IP1001,
+ MII_STR_ICPLUS_IP1001 },
{ 0,
NULL },
@@ -110,6 +112,7 @@ ipgphy_attach(struct device *parent, struct device *self, void *aux)
sc->mii_inst = mii->mii_instance;
sc->mii_phy = ma->mii_phyno;
sc->mii_funcs = &ipgphy_funcs;
+ sc->mii_model = MII_MODEL(ma->mii_id2);
sc->mii_pdata = mii;
sc->mii_flags |= MIIF_NOISOLATE;
@@ -245,7 +248,7 @@ done:
* Only retry autonegotiation every mii_anegticks seconds.
*/
if (sc->mii_ticks <= sc->mii_anegticks)
- return (0);
+ break;
sc->mii_ticks = 0;
ipgphy_mii_phy_auto(sc);
@@ -264,6 +267,7 @@ void
ipgphy_status(struct mii_softc *sc)
{
struct mii_data *mii = sc->mii_pdata;
+ struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
uint32_t bmsr, bmcr, stat;
mii->mii_media_status = IFM_AVALID;
@@ -271,63 +275,99 @@ ipgphy_status(struct mii_softc *sc)
bmsr = PHY_READ(sc, IPGPHY_MII_BMSR) |
PHY_READ(sc, IPGPHY_MII_BMSR);
- if ((bmsr & IPGPHY_BMSR_LINK) != 0)
+ if (bmsr & IPGPHY_BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, IPGPHY_MII_BMCR);
- if ((bmcr & IPGPHY_BMCR_LOOP) != 0)
+ if (bmcr & IPGPHY_BMCR_LOOP)
mii->mii_media_active |= IFM_LOOP;
- if ((bmcr & IPGPHY_BMCR_AUTOEN) != 0) {
+ if (bmcr & IPGPHY_BMCR_AUTOEN) {
if ((bmsr & IPGPHY_BMSR_ANEGCOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
- }
- 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 (sc->mii_model == MII_MODEL_ICPLUS_IP1001) {
+ stat = PHY_READ(sc, IPGPHY_LSR);
+ switch (stat & IPGPHY_LSR_SPEED_MASK) {
+ case IPGPHY_LSR_SPEED_10:
+ mii->mii_media_active |= IFM_10_T;
+ break;
+ case IPGPHY_LSR_SPEED_100:
+ mii->mii_media_active |= IFM_100_TX;
+ break;
+ case IPGPHY_LSR_SPEED_1000:
+ mii->mii_media_active |= IFM_1000_T;
+ break;
+ default:
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+ if (stat & IPGPHY_LSR_FULL_DUPLEX)
+ 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;
+ default:
+ mii->mii_media_active |= IFM_NONE;
+ return;
+ }
+
+ if (stat & PC_PhyDuplexStatus)
+ mii->mii_media_active |= IFM_FDX;
+ else
+ mii->mii_media_active |= IFM_HDX;
+ }
- if ((stat & PC_PhyDuplexStatus) != 0)
- mii->mii_media_active |= mii_phy_flowstatus(sc) | IFM_FDX;
- else
- mii->mii_media_active |= IFM_HDX;
+ if (mii->mii_media_active & IFM_FDX)
+ mii->mii_media_active |= mii_phy_flowstatus(sc);
- stat = PHY_READ(sc, IPGPHY_MII_1000SR);
- if ((IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) &&
- stat & IPGPHY_1000SR_MASTER)
- mii->mii_media_active |= IFM_ETH_MASTER;
+ if (IFM_SUBTYPE(mii->mii_media_active) == IFM_1000_T) {
+ if (PHY_READ(sc, IPGPHY_MII_1000SR) &
+ IPGPHY_1000SR_MASTER)
+ mii->mii_media_active |= IFM_ETH_MASTER;
+ }
+ } else
+ mii->mii_media_active = ife->ifm_media;
}
int
ipgphy_mii_phy_auto(struct mii_softc *sc)
{
- uint32_t reg;
+ uint32_t reg = 0;
+
+ if (sc->mii_model == MII_MODEL_ICPLUS_IP1001)
+ reg = PHY_READ(sc, IPGPHY_MII_ANAR);
- reg = IPGPHY_ANAR_10T | IPGPHY_ANAR_10T_FDX |
+ reg |= IPGPHY_ANAR_10T | IPGPHY_ANAR_10T_FDX |
IPGPHY_ANAR_100TX | IPGPHY_ANAR_100TX_FDX;
if (sc->mii_flags & MIIF_DOPAUSE)
reg |= IPGPHY_ANAR_PAUSE | IPGPHY_ANAR_APAUSE;
- PHY_WRITE(sc, IPGPHY_MII_ANAR, reg);
+ PHY_WRITE(sc, IPGPHY_MII_ANAR, reg | IPGPHY_ANAR_CSMA);
+
reg = IPGPHY_1000CR_1000T | IPGPHY_1000CR_1000T_FDX;
reg |= IPGPHY_1000CR_MASTER;
PHY_WRITE(sc, IPGPHY_MII_1000CR, reg);
+
PHY_WRITE(sc, IPGPHY_MII_BMCR, (IPGPHY_BMCR_FDX |
IPGPHY_BMCR_AUTOEN | IPGPHY_BMCR_STARTNEG));
@@ -351,8 +391,8 @@ ipgphy_load_dspcode(struct mii_softc *sc)
void
ipgphy_reset(struct mii_softc *sc)
{
+ struct ifnet *ifp = sc->mii_pdata->mii_ifp;
struct stge_softc *stge_sc;
- struct ifnet *ifp;
uint32_t reg;
mii_phy_reset(sc);
@@ -362,9 +402,8 @@ ipgphy_reset(struct mii_softc *sc)
reg &= ~(IPGPHY_BMCR_AUTOEN | IPGPHY_BMCR_FDX);
PHY_WRITE(sc, MII_BMCR, reg);
- ifp = sc->mii_pdata->mii_ifp;
-
- if (strcmp(ifp->if_xname, "stge") == 0) {
+ if (sc->mii_model == MII_MODEL_ICPLUS_IP1000A &&
+ strcmp(ifp->if_xname, "stge") == 0) {
stge_sc = ifp->if_softc;
if (stge_sc->sc_rev >= 0x40 && stge_sc->sc_rev <= 0x4e)
ipgphy_load_dspcode(sc);
diff --git a/sys/dev/mii/ipgphyreg.h b/sys/dev/mii/ipgphyreg.h
index 8da5b0979c9..64bacb0591e 100644
--- a/sys/dev/mii/ipgphyreg.h
+++ b/sys/dev/mii/ipgphyreg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: ipgphyreg.h,v 1.1 2006/07/12 19:05:50 brad Exp $ */
+/* $OpenBSD: ipgphyreg.h,v 1.2 2009/08/08 17:12:40 naddy Exp $ */
/*-
* Copyright (c) 2006, Pyun YongHyeon
@@ -62,6 +62,7 @@
/* Autonegotiation advertisement register */
#define IPGPHY_MII_ANAR 0x04
+#define IPGPHY_ANAR_CSMA 0x0001
#define IPGPHY_ANAR_10T 0x0020
#define IPGPHY_ANAR_10T_FDX 0x0040
#define IPGPHY_ANAR_100TX 0x0080
@@ -139,4 +140,49 @@
#define IPGPHY_EXTSTS_1000X 0x4000
#define IPGPHY_EXTSTS_1000X_FDX 0x8000
+/* PHY specific control & status register. IP1001 only. */
+#define IPGPHY_SCSR 0x10
+#define IPGPHY_SCSR_RXPHASE_SEL 0x0001
+#define IPGPHY_SCSR_TXPHASE_SEL 0x0002
+#define IPGPHY_SCSR_REPEATOR_MODE 0x0004
+#define IPGPHY_SCSR_RESERVED1_DEF 0x0008
+#define IPGPHY_SCSR_RXCLK_DRV_MASK 0x0060
+#define IPGPHY_SCSR_RXCLK_DRV_DEF 0x0040
+#define IPGPHY_SCSR_RXD_DRV_MASK 0x0180
+#define IPGPHY_SCSR_RXD_DRV_DEF 0x0100
+#define IPGPHY_SCSR_JABBER_ENB 0x0200
+#define IPGPHY_SCSR_HEART_BEAT_ENB 0x0400
+#define IPGPHY_SCSR_DOWNSHIFT_ENB 0x0800
+#define IPGPHY_SCSR_RESERVED2_DEF 0x1000
+#define IPGPHY_SCSR_LED_DRV_4MA 0x0000
+#define IPGPHY_SCSR_LED_DRV_8MA 0x2000
+#define IPGPHY_SCSR_LED_MODE_MASK 0xC000
+#define IPGPHY_SCSR_LED_MODE_DEF 0x0000
+
+/* PHY link status register. IP1001 only. */
+#define IPGPHY_LSR 0x11
+#define IPGPHY_LSR_JABBER_DET 0x0200
+#define IPGPHY_LSR_APS_SLEEP 0x0400
+#define IPGPHY_LSR_MDIX 0x0800
+#define IPGPHY_LSR_FULL_DUPLEX 0x1000
+#define IPGPHY_LSR_SPEED_10 0x0000
+#define IPGPHY_LSR_SPEED_100 0x2000
+#define IPGPHY_LSR_SPEED_1000 0x4000
+#define IPGPHY_LSR_SPEED_MASK 0x6000
+#define IPGPHY_LSR_LINKUP 0x8000
+
+/* PHY specific control register 2. IP1001 only. */
+#define IPGPHY_SCR
+#define IPGPHY_SCR_SEW_RATE_MASK 0x0003
+#define IPGPHY_SCR_SEW_RATE_DEF 0x0003
+#define IPGPHY_SCR_AUTO_XOVER 0x0004
+#define IPGPHY_SCR_SPEED_10_100_ENB 0x0040
+#define IPGPHY_SCR_FIFO_LATENCY_2 0x0000
+#define IPGPHY_SCR_FIFO_LATENCY_3 0x0080
+#define IPGPHY_SCR_FIFO_LATENCY_4 0x0100
+#define IPGPHY_SCR_FIFO_LATENCY_5 0x0180
+#define IPGPHY_SCR_MDIX_ENB 0x0200
+#define IPGPHY_SCR_RESERVED_DEF 0x0400
+#define IPGPHY_SCR_APS_ON 0x0800
+
#endif /* _DEV_MII_IPGPHYREG_H_ */