Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev/mii Add support for BCM5709S (SerDes PHY) in brgphy(4).
details: https://anonhg.NetBSD.org/src/rev/0596000680c4
branches: trunk
changeset: 759448:0596000680c4
user: jym <jym%NetBSD.org@localhost>
date: Thu Dec 09 23:25:49 2010 +0000
description:
Add support for BCM5709S (SerDes PHY) in brgphy(4).
>From FreeBSD, via OpenBSD, with some minor adaptations.
No comments, no objections on tech-kern@.
The driver was tested on a Dell M710. Access was kindly provided by
Uwe Toenjes, whom I thank for this.
See also http://mail-index.netbsd.org/tech-kern/2010/12/01/msg009478.html
diffstat:
sys/dev/mii/brgphy.c | 250 ++++++++++++++++++++++++++++++++++++-----------
sys/dev/mii/brgphyreg.h | 126 ++++++++++++++++++++++++-
2 files changed, 315 insertions(+), 61 deletions(-)
diffs (truncated from 519 to 300 lines):
diff -r de9476df1634 -r 0596000680c4 sys/dev/mii/brgphy.c
--- a/sys/dev/mii/brgphy.c Thu Dec 09 23:14:06 2010 +0000
+++ b/sys/dev/mii/brgphy.c Thu Dec 09 23:25:49 2010 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: brgphy.c,v 1.56 2010/11/27 17:42:04 jym Exp $ */
+/* $NetBSD: brgphy.c,v 1.57 2010/12/09 23:25:49 jym Exp $ */
/*-
* Copyright (c) 1998, 1999, 2000, 2001 The NetBSD Foundation, Inc.
@@ -55,14 +55,14 @@
*/
/*
- * driver for the Broadcom BCM5400 Gig-E PHY.
+ * driver for the Broadcom BCM5400 and BCM5700 Gig-E PHYs.
*
* Programming information for this PHY was gleaned from FreeBSD
* (they were apparently able to get a datasheet from Broadcom).
*/
#include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.56 2010/11/27 17:42:04 jym Exp $");
+__KERNEL_RCSID(0, "$NetBSD: brgphy.c,v 1.57 2010/12/09 23:25:49 jym Exp $");
#include <sys/param.h>
#include <sys/systm.h>
@@ -81,9 +81,7 @@
#include <dev/mii/brgphyreg.h>
#include <dev/pci/if_bgereg.h>
-#if 0
#include <dev/pci/if_bnxreg.h>
-#endif
static int brgphymatch(device_t, cfdata_t, void *);
static void brgphyattach(device_t, device_t, void *);
@@ -182,6 +180,9 @@
{ MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709C,
MII_STR_BROADCOM2_BCM5709C },
+ { MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709S,
+ MII_STR_BROADCOM2_BCM5709S },
+
{ MII_OUI_BROADCOM2, MII_MODEL_BROADCOM2_BCM5709CAX,
MII_STR_BROADCOM2_BCM5709CAX },
@@ -249,26 +250,56 @@
if (sc->mii_capabilities & BMSR_EXTSTAT)
sc->mii_extcapabilities = PHY_READ(sc, MII_EXTSR);
- aprint_normal_dev(self, "");
- if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
- (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
- aprint_error("no media present");
- else
- mii_phy_add_media(sc);
- aprint_normal("\n");
if (device_is_a(parent, "bge")) {
bsc->sc_isbge = true;
dict = device_properties(parent);
if (!prop_dictionary_get_uint32(dict, "phyflags",
- &bsc->sc_bge_flags))
- aprint_error("failed to get phyflags");
+ &bsc->sc_bge_flags))
+ aprint_error_dev(self, "failed to get phyflags");
} else if (device_is_a(parent, "bnx")) {
bsc->sc_isbnx = true;
dict = device_properties(parent);
- prop_dictionary_get_uint32(dict, "phyflags",
- &bsc->sc_bnx_flags);
+ if (!prop_dictionary_get_uint32(dict, "phyflags",
+ &bsc->sc_bnx_flags))
+ aprint_error_dev(self, "failed to get phyflags");
}
+
+ aprint_normal_dev(self, "");
+ if ((sc->mii_capabilities & BMSR_MEDIAMASK) == 0 &&
+ (sc->mii_extcapabilities & EXTSR_MEDIAMASK) == 0)
+ aprint_error("no media present");
+ else {
+ if (sc->mii_flags & MIIF_HAVEFIBER) {
+ sc->mii_flags |= MIIF_NOISOLATE | MIIF_NOLOOP;
+
+ /*
+ * Set the proper bits for capabilities so that the
+ * correct media get selected by mii_phy_add_media()
+ */
+ sc->mii_capabilities |= BMSR_ANEG;
+ sc->mii_capabilities &= ~BMSR_100T4;
+ sc->mii_extcapabilities |= EXTSR_1000XFDX;
+
+ if (bsc->sc_isbnx) {
+ /*
+ * 2.5Gb support is a software enabled feature
+ * on the BCM5708S and BCM5709S controllers.
+ */
+#define ADD(m, c) ifmedia_add(&mii->mii_media, (m), (c), NULL)
+ if (bsc->sc_bnx_flags
+ & BNX_PHY_2_5G_CAPABLE_FLAG) {
+ ADD(IFM_MAKEWORD(IFM_ETHER, IFM_2500_SX,
+ IFM_FDX, sc->mii_inst), 0);
+ aprint_normal("2500baseSX-FDX, ");
+#undef ADD
+ }
+ }
+ }
+ mii_phy_add_media(sc);
+ }
+ aprint_normal("\n");
+
}
static int
@@ -399,14 +430,13 @@
{
struct mii_data *mii = sc->mii_pdata;
struct ifmedia_entry *ife = mii->mii_media.ifm_cur;
- int bmcr, auxsts, gtsr;
+ int bmcr, bmsr, auxsts, gtsr;
mii->mii_media_status = IFM_AVALID;
mii->mii_media_active = IFM_ETHER;
- auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
-
- if (auxsts & BRGPHY_AUXSTS_LINK)
+ bmsr = PHY_READ(sc, MII_BMSR) | PHY_READ(sc, MII_BMSR);
+ if (bmsr & BMSR_LINK)
mii->mii_media_status |= IFM_ACTIVE;
bmcr = PHY_READ(sc, MII_BMCR);
@@ -424,53 +454,95 @@
* The media status bits are only valid of autonegotiation
* has completed (or it's disabled).
*/
- if ((auxsts & BRGPHY_AUXSTS_ACOMP) == 0) {
+ if ((bmsr & BMSR_ACOMP) == 0) {
/* Erg, still trying, I guess... */
mii->mii_media_active |= IFM_NONE;
return;
}
- switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
- case BRGPHY_RES_1000FD:
- mii->mii_media_active |= IFM_1000_T|IFM_FDX;
- gtsr = PHY_READ(sc, MII_100T2SR);
- if (gtsr & GTSR_MS_RES)
- mii->mii_media_active |= IFM_ETH_MASTER;
- break;
+ if (sc->mii_mpd_model == MII_MODEL_BROADCOM2_BCM5709S) {
+
+ /* 5709S has its own general purpose status registers */
+
+ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
+ BRGPHY_BLOCK_ADDR_GP_STATUS);
+
+ auxsts = PHY_READ(sc, BRGPHY_GP_STATUS_TOP_ANEG_STATUS);
+
+ PHY_WRITE(sc, BRGPHY_BLOCK_ADDR,
+ BRGPHY_BLOCK_ADDR_COMBO_IEEE0);
- case BRGPHY_RES_1000HD:
- mii->mii_media_active |= IFM_1000_T;
- gtsr = PHY_READ(sc, MII_100T2SR);
- if (gtsr & GTSR_MS_RES)
- mii->mii_media_active |= IFM_ETH_MASTER;
- break;
+ switch (auxsts & BRGPHY_GP_STATUS_TOP_ANEG_SPEED_MASK) {
+ case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_10:
+ mii->mii_media_active |= IFM_10_FL;
+ break;
+ case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_100:
+ mii->mii_media_active |= IFM_100_FX;
+ break;
+ case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_1G:
+ mii->mii_media_active |= IFM_1000_SX;
+ break;
+ case BRGPHY_GP_STATUS_TOP_ANEG_SPEED_25G:
+ mii->mii_media_active |= IFM_2500_SX;
+ break;
+ default:
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ break;
+ }
- case BRGPHY_RES_100FD:
- mii->mii_media_active |= IFM_100_TX|IFM_FDX;
- break;
+ if (auxsts & BRGPHY_GP_STATUS_TOP_ANEG_FDX)
+ mii->mii_media_active |= IFM_FDX;
+ else
+ mii->mii_media_active |= IFM_HDX;
+
+ } else {
+ auxsts = PHY_READ(sc, BRGPHY_MII_AUXSTS);
- case BRGPHY_RES_100T4:
- mii->mii_media_active |= IFM_100_T4;
- break;
+ switch (auxsts & BRGPHY_AUXSTS_AN_RES) {
+ case BRGPHY_RES_1000FD:
+ mii->mii_media_active |= IFM_1000_T|IFM_FDX;
+ gtsr = PHY_READ(sc, MII_100T2SR);
+ if (gtsr & GTSR_MS_RES)
+ mii->mii_media_active |= IFM_ETH_MASTER;
+ break;
- case BRGPHY_RES_100HD:
- mii->mii_media_active |= IFM_100_TX;
- break;
+ case BRGPHY_RES_1000HD:
+ mii->mii_media_active |= IFM_1000_T;
+ gtsr = PHY_READ(sc, MII_100T2SR);
+ if (gtsr & GTSR_MS_RES)
+ mii->mii_media_active |= IFM_ETH_MASTER;
+ break;
+
+ case BRGPHY_RES_100FD:
+ mii->mii_media_active |= IFM_100_TX|IFM_FDX;
+ break;
- case BRGPHY_RES_10FD:
- mii->mii_media_active |= IFM_10_T|IFM_FDX;
- break;
+ case BRGPHY_RES_100T4:
+ mii->mii_media_active |= IFM_100_T4;
+ break;
+
+ case BRGPHY_RES_100HD:
+ mii->mii_media_active |= IFM_100_TX;
+ break;
- case BRGPHY_RES_10HD:
- mii->mii_media_active |= IFM_10_T;
- break;
+ case BRGPHY_RES_10FD:
+ mii->mii_media_active |= IFM_10_T|IFM_FDX;
+ break;
- default:
- mii->mii_media_active |= IFM_NONE;
- mii->mii_media_status = 0;
+ case BRGPHY_RES_10HD:
+ mii->mii_media_active |= IFM_10_T;
+ break;
+
+ default:
+ mii->mii_media_active |= IFM_NONE;
+ mii->mii_media_status = 0;
+ }
}
+
if (mii->mii_media_active & IFM_FDX)
mii->mii_media_active |= mii_phy_flowstatus(sc);
+
} else
mii->mii_media_active = ife->ifm_media;
}
@@ -482,18 +554,27 @@
brgphy_loop(sc);
PHY_RESET(sc);
+
ktcr = GTCR_ADV_1000TFDX|GTCR_ADV_1000THDX;
if (sc->mii_mpd_model == MII_MODEL_BROADCOM_BCM5701)
ktcr |= GTCR_MAN_MS|GTCR_ADV_MS;
PHY_WRITE(sc, MII_100T2CR, ktcr);
ktcr = PHY_READ(sc, MII_100T2CR);
DELAY(1000);
- anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
- if (sc->mii_flags & MIIF_DOPAUSE)
- anar |= ANAR_FC| ANAR_X_PAUSE_ASYM;
+ if (sc->mii_flags & MIIF_HAVEFIBER) {
+ anar = ANAR_X_FD | ANAR_X_HD;
+ if (sc->mii_flags & MIIF_DOPAUSE)
+ anar |= BRGPHY_SERDES_ANAR_BOTH_PAUSE;
+ } else {
+ anar = BMSR_MEDIA_TO_ANAR(sc->mii_capabilities) | ANAR_CSMA;
+ if (sc->mii_flags & MIIF_DOPAUSE)
+ anar |= ANAR_FC | ANAR_X_PAUSE_ASYM;
+ }
PHY_WRITE(sc, MII_ANAR, anar);
DELAY(1000);
+
+ /* Start autonegotiation */
PHY_WRITE(sc, MII_BMCR,
BMCR_AUTOEN | BMCR_STARTNEG);
PHY_WRITE(sc, BRGPHY_MII_IMR, 0xFF00);
@@ -593,11 +674,9 @@
}
#endif
}
+ /* Handle any bnx (NetXtreme II) workarounds. */
+ } else if (bsc->sc_isbnx) {
#if 0 /* not yet */
- /* Handle any bnx (NetXtreme II) workarounds. */
- } else if (sc->sc_isbnx) {
Home |
Main Index |
Thread Index |
Old Index