summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorwpaul <wpaul@FreeBSD.org>2004-06-09 16:01:59 +0000
committerwpaul <wpaul@FreeBSD.org>2004-06-09 16:01:59 +0000
commit0307fa34d7fc48a54789626544488fc902a7bca7 (patch)
tree49e6386cee85d545e66bf1d0f42b95b63b7ba045 /sys
parentc4569c02e5025d4378ac0eb232c0353bb7241b29 (diff)
downloadFreeBSD-src-0307fa34d7fc48a54789626544488fc902a7bca7.zip
FreeBSD-src-0307fa34d7fc48a54789626544488fc902a7bca7.tar.gz
Add some special case code to fix a problem with the BCM5704 in TBI (fiber)
mode. The 5704 apparently has some s00p3r s33kr1t registers for setting the advertisement of pause frame ability (i.e flow control) when in autoneg mode. If we don't set these registers correctly, we may not be able to negotiate a proper link with some switches. (Symptom is that the NIC reports the link as up (PCS synched) but no traffic can be exchanged.) PR: kern/67598
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/bge/if_bge.c33
-rw-r--r--sys/dev/bge/if_bgereg.h38
2 files changed, 71 insertions, 0 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index 0cc270c..3d082de 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -2382,6 +2382,7 @@ bge_attach(dev)
IFM_ETHER|IFM_1000_SX|IFM_FDX, 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.
@@ -2581,6 +2582,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);
+ }
+
DELAY(10000);
return;
@@ -2916,6 +2929,9 @@ bge_tick_locked(sc)
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);
printf("bge%d: gigabit link up\n", sc->bge_unit);
if (ifp->if_snd.ifq_head != NULL)
@@ -3312,6 +3328,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/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index 9893a1a..66e103c 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -525,6 +525,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
@@ -655,6 +659,40 @@
#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
OpenPOWER on IntegriCloud