summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/dev/pci/if_bge.c48
-rw-r--r--sys/dev/pci/if_bgereg.h39
2 files changed, 83 insertions, 4 deletions
diff --git a/sys/dev/pci/if_bge.c b/sys/dev/pci/if_bge.c
index 11d06ca2f53..2a0add69a1f 100644
--- a/sys/dev/pci/if_bge.c
+++ b/sys/dev/pci/if_bge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bge.c,v 1.34 2004/10/31 06:59:25 brad Exp $ */
+/* $OpenBSD: if_bge.c,v 1.35 2004/11/11 18:35:41 brad Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
* Copyright (c) 1997, 1998, 1999, 2001
@@ -1769,6 +1769,7 @@ bge_attach(parent, self, aux)
0, NULL);
ifmedia_add(&sc->bge_ifmedia, IFM_ETHER|IFM_AUTO, 0, NULL);
ifmedia_set(&sc->bge_ifmedia, IFM_ETHER|IFM_AUTO);
+ sc->bge_ifmedia.ifm_media = sc->bge_ifmedia.ifm_cur->ifm_media;
} else {
/*
* Do transceiver setup.
@@ -1956,6 +1957,18 @@ bge_reset(sc)
CSR_WRITE_4(sc, BGE_MAC_MODE, 0);
+ /*
+ * The 5704 in TBI mode apparently needs some special
+ * adjustment to insure the SERDES drive level is set
+ * to 1.2V.
+ */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5704 && sc->bge_tbi) {
+ uint32_t serdescfg;
+ serdescfg = CSR_READ_4(sc, BGE_SERDES_CFG);
+ serdescfg = (serdescfg & ~0xFFF) | 0x880;
+ CSR_WRITE_4(sc, BGE_SERDES_CFG, serdescfg);
+ }
+
/* XXX: Broadcom Linux driver. */
if (sc->bge_pcie && sc->bge_chipid != BGE_CHIPID_BCM5750_A0) {
uint32_t v;
@@ -2155,7 +2168,7 @@ bge_intr(xsc)
{
struct bge_softc *sc;
struct ifnet *ifp;
- u_int32_t status;
+ u_int32_t status, mimode;
sc = xsc;
ifp = &sc->arpcom.ac_if;
@@ -2213,10 +2226,19 @@ bge_intr(xsc)
* that sometimes appear on fiber NICs during
* periods of heavy traffic. (There should be no
* effect on copper NICs).
+ *
+ * If we do have a copper NIC (bge_tbi == 0) then
+ * check that the AUTOPOLL bit is set before
+ * processing the event as a real link change.
+ * Turning AUTOPOLL on and off in the MII read/write
+ * functions will often trigger a link status
+ * interrupt for no reason.
*/
status = CSR_READ_4(sc, BGE_MAC_STS);
+ mimode = CSR_READ_4(sc, BGE_MI_MODE);
if (!(status & (BGE_MACSTAT_PORT_DECODE_ERROR |
- BGE_MACSTAT_MI_COMPLETE))) {
+ BGE_MACSTAT_MI_COMPLETE)) && (!sc->bge_tbi &&
+ (mimode & BGE_MIMODE_AUTOPOLL))) {
sc->bge_link = 0;
timeout_del(&sc->bge_timeout);
bge_tick(sc);
@@ -2278,6 +2300,9 @@ bge_tick(xsc)
if (CSR_READ_4(sc, BGE_MAC_STS) &
BGE_MACSTAT_TBI_PCS_SYNCHED) {
sc->bge_link++;
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5704)
+ BGE_CLRBIT(sc, BGE_MAC_MODE,
+ BGE_MACMODE_TBI_SEND_CFGS);
CSR_WRITE_4(sc, BGE_MAC_STS, 0xFFFFFFFF);
if (!IFQ_IS_EMPTY(&ifp->if_snd))
bge_start(ifp);
@@ -2655,6 +2680,23 @@ bge_ifmedia_upd(ifp)
return(EINVAL);
switch(IFM_SUBTYPE(ifm->ifm_media)) {
case IFM_AUTO:
+ /*
+ * The BCM5704 ASIC appears to have a special
+ * mechanism for programming the autoneg
+ * advertisement registers in TBI mode.
+ */
+ if (sc->bge_asicrev == BGE_ASICREV_BCM5704) {
+ uint32_t sgdig;
+ CSR_WRITE_4(sc, BGE_TX_TBI_AUTONEG, 0);
+ sgdig = CSR_READ_4(sc, BGE_SGDIG_CFG);
+ sgdig |= BGE_SGDIGCFG_AUTO|
+ BGE_SGDIGCFG_PAUSE_CAP|
+ BGE_SGDIGCFG_ASYM_PAUSE;
+ CSR_WRITE_4(sc, BGE_SGDIG_CFG,
+ sgdig|BGE_SGDIGCFG_SEND);
+ DELAY(5);
+ CSR_WRITE_4(sc, BGE_SGDIG_CFG, sgdig);
+ }
break;
case IFM_1000_SX:
if ((ifm->ifm_media & IFM_GMASK) == IFM_FDX) {
diff --git a/sys/dev/pci/if_bgereg.h b/sys/dev/pci/if_bgereg.h
index e780dfc4a12..dea71d0c3fa 100644
--- a/sys/dev/pci/if_bgereg.h
+++ b/sys/dev/pci/if_bgereg.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_bgereg.h,v 1.12 2004/10/31 06:59:25 brad Exp $ */
+/* $OpenBSD: if_bgereg.h,v 1.13 2004/11/11 18:35:41 brad Exp $ */
/*
* Copyright (c) 2001 Wind River Systems
* Copyright (c) 1997, 1998, 1999, 2001
@@ -529,6 +529,10 @@
#define BGE_RX_BD_RULES_CTL15 0x04F8
#define BGE_RX_BD_RULES_MASKVAL15 0x04FC
#define BGE_RX_RULES_CFG 0x0500
+#define BGE_SERDES_CFG 0x0590
+#define BGE_SERDES_STS 0x0594
+#define BGE_SGDIG_CFG 0x05B0
+#define BGE_SGDIG_STS 0x05B4
#define BGE_RX_STATS 0x0800
#define BGE_TX_STATS 0x0880
@@ -659,6 +663,39 @@
#define BGE_RXRULEMASK_VALUE 0x0000FFFF
#define BGE_RXRULEMASK_MASKVAL 0xFFFF0000
+/* SERDES configuration register */
+#define BGE_SERDESCFG_RXR 0x00000007 /* phase interpolator */
+#define BGE_SERDESCFG_RXG 0x00000018 /* rx gain setting */
+#define BGE_SERDESCFG_RXEDGESEL 0x00000040 /* rising/falling egde */
+#define BGE_SERDESCFG_TX_BIAS 0x00000380 /* TXDAC bias setting */
+#define BGE_SERDESCFG_IBMAX 0x00000400 /* bias current +25% */
+#define BGE_SERDESCFG_IBMIN 0x00000800 /* bias current -25% */
+#define BGE_SERDESCFG_TXMODE 0x00001000
+#define BGE_SERDESCFG_TXEDGESEL 0x00002000 /* rising/falling edge */
+#define BGE_SERDESCFG_MODE 0x00004000 /* TXCP/TXCN disabled */
+#define BGE_SERDESCFG_PLLTEST 0x00008000 /* PLL test mode */
+#define BGE_SERDESCFG_CDET 0x00010000 /* comma detect enable */
+#define BGE_SERDESCFG_TBILOOP 0x00020000 /* local loopback */
+#define BGE_SERDESCFG_REMLOOP 0x00040000 /* remote loopback */
+#define BGE_SERDESCFG_INVPHASE 0x00080000 /* Reverse 125Mhz clock */
+#define BGE_SERDESCFG_12REGCTL 0x00300000 /* 1.2v regulator ctl */
+#define BGE_SERDESCFG_REGCTL 0x00C00000 /* regulator ctl (2.5v) */
+
+/* SERDES status register */
+#define BGE_SERDESSTS_RXSTAT 0x0000000F /* receive status bits */
+#define BGE_SERDESSTS_CDET 0x00000010 /* comma code detected */
+
+/* SGDIG config (not documented) */
+#define BGE_SGDIGCFG_PAUSE_CAP 0x00000800
+#define BGE_SGDIGCFG_ASYM_PAUSE 0x00001000
+#define BGE_SGDIGCFG_SEND 0x40000000
+#define BGE_SGDIGCFG_AUTO 0x80000000
+
+/* SGDIG status (not documented) */
+#define BGE_SGDIGSTS_PAUSE_CAP 0x00080000
+#define BGE_SGDIGSTS_ASYM_PAUSE 0x00100000
+#define BGE_SGDIGSTS_DONE 0x00000002
+
/* MI communication register */
#define BGE_MICOMM_DATA 0x0000FFFF
#define BGE_MICOMM_REG 0x001F0000