svn commit: r214704 - stable/8/sys/dev/bge

Pyun YongHyeon yongari at FreeBSD.org
Tue Nov 2 23:35:09 UTC 2010


Author: yongari
Date: Tue Nov  2 23:35:08 2010
New Revision: 214704
URL: http://svn.freebsd.org/changeset/base/214704

Log:
  MFC r213485,213710,213812:
  r213485:
    Overhaul MII register access routine and remove unnecessary
    BGE_MI_MODE register accesses. Previously bge(4) used to read
    BGE_MI_MODE register to detect whether it needs to disable
    autopolling feature or not. Because we don't touch autopolling in
    other part of driver there is no reason to read BGE_MI_MODE
    register given that we know default value in advance. In order to
    achieve the goal, check whether the controller has CPMU(Central
    Power Mangement Unit) capability. If controller has CPMU feature,
    use 500KHz MII management interface(mdio/mdc) frequency regardless
    core clock frequency. Otherwise use default MII clock. While I'm
    here, add CPMU register definition.
  
    In bge_miibus_readreg(), rearrange code a bit and remove goto
    statement. In bge_miibus_writereg(), make sure to restore
    autopolling even if MII write failed. The delay time inserted after
    accessing BGE_MI_MODE register increased from 40us to 80us.
  
    The default PHY address is now stored in softc. All PHYs supported
    by bge(4) currently uses PHY address 1 but it will be changed when
    we add newer controllers. This change will make it easier to change
    default PHY address depending on PHY models.
  
    Submitted by:	davidch
  
  r213710:
    Remove one last reference of BGE_MI_MODE register for auto polling.
    Previously bge(4) always enabled auto polling for non-BGE_FLAG_TBI
    controllers. With this change, auto polling is not used anymore so
    polling through mii(4) was introduced.
  
    Reviewed by:	davidch
  
  r213812:
    Fix a regression introduced in r213710. r213710 removed the use of
    auto polling such that it made all controllers obtain link status
    information from the state of the LNKRDY input signal. Broadcom
    recommends disabling auto polling such that driver should rely on
    PHY interrupts for link status change indications. Unfortunately it
    seems some controllers(BCM5703, BCM5704 and BCM5705) have PHY
    related issues so Linux took other approach to workaround it.
    bge(4) didn't follow that and it used to enable auto polling to
    workaround it. Restore this old behavior for BCM5700 family
    controllers and BCM5705 to use auto polling. For BCM5700 and
    BCM5701, it seems it does not need to enable auto polling but I
    restored it for safety.
    Special thanks to marius who tried lots of patches with patience.
  
    Reported by:	marius
    Tested by:	marius

Modified:
  stable/8/sys/dev/bge/if_bge.c
  stable/8/sys/dev/bge/if_bgereg.h
Directory Properties:
  stable/8/sys/   (props changed)
  stable/8/sys/amd64/include/xen/   (props changed)
  stable/8/sys/cddl/contrib/opensolaris/   (props changed)
  stable/8/sys/contrib/dev/acpica/   (props changed)
  stable/8/sys/contrib/pf/   (props changed)
  stable/8/sys/dev/xen/xenpci/   (props changed)

Modified: stable/8/sys/dev/bge/if_bge.c
==============================================================================
--- stable/8/sys/dev/bge/if_bge.c	Tue Nov  2 23:26:07 2010	(r214703)
+++ stable/8/sys/dev/bge/if_bge.c	Tue Nov  2 23:35:08 2010	(r214704)
@@ -768,38 +768,34 @@ static int
 bge_miibus_readreg(device_t dev, int phy, int reg)
 {
 	struct bge_softc *sc;
-	uint32_t val, autopoll;
+	uint32_t val;
 	int i;
 
 	sc = device_get_softc(dev);
 
-	/*
-	 * Broadcom's own driver always assumes the internal
-	 * PHY is at GMII address 1. On some chips, the PHY responds
-	 * to accesses at all addresses, which could cause us to
-	 * bogusly attach the PHY 32 times at probe type. Always
-	 * restricting the lookup to address 1 is simpler than
-	 * trying to figure out which chips revisions should be
-	 * special-cased.
-	 */
-	if (phy != 1)
+	/* Prevent the probe from finding incorrect devices. */
+	if (phy != sc->bge_phy_addr)
 		return (0);
 
-	/* Reading with autopolling on may trigger PCI errors */
-	autopoll = CSR_READ_4(sc, BGE_MI_MODE);
-	if (autopoll & BGE_MIMODE_AUTOPOLL) {
-		BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
-		DELAY(40);
+	/* Clear the autopoll bit if set, otherwise may trigger PCI errors. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE,
+		    sc->bge_mi_mode & ~BGE_MIMODE_AUTOPOLL);
+		DELAY(80);
 	}
 
 	CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_READ | BGE_MICOMM_BUSY |
 	    BGE_MIPHY(phy) | BGE_MIREG(reg));
 
+	/* Poll for the PHY register access to complete. */
 	for (i = 0; i < BGE_TIMEOUT; i++) {
 		DELAY(10);
 		val = CSR_READ_4(sc, BGE_MI_COMM);
-		if (!(val & BGE_MICOMM_BUSY))
+		if ((val & BGE_MICOMM_BUSY) == 0) {
+			DELAY(5);
+			val = CSR_READ_4(sc, BGE_MI_COMM);
 			break;
+		}
 	}
 
 	if (i == BGE_TIMEOUT) {
@@ -807,16 +803,12 @@ bge_miibus_readreg(device_t dev, int phy
 		    "PHY read timed out (phy %d, reg %d, val 0x%08x)\n",
 		    phy, reg, val);
 		val = 0;
-		goto done;
 	}
 
-	DELAY(5);
-	val = CSR_READ_4(sc, BGE_MI_COMM);
-
-done:
-	if (autopoll & BGE_MIMODE_AUTOPOLL) {
-		BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
-		DELAY(40);
+	/* Restore the autopoll bit if necessary. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode);
+		DELAY(80);
 	}
 
 	if (val & BGE_MICOMM_READFAIL)
@@ -829,7 +821,6 @@ static int
 bge_miibus_writereg(device_t dev, int phy, int reg, int val)
 {
 	struct bge_softc *sc;
-	uint32_t autopoll;
 	int i;
 
 	sc = device_get_softc(dev);
@@ -838,11 +829,11 @@ bge_miibus_writereg(device_t dev, int ph
 	    (reg == BRGPHY_MII_1000CTL || reg == BRGPHY_MII_AUXCTL))
 		return (0);
 
-	/* Reading with autopolling on may trigger PCI errors */
-	autopoll = CSR_READ_4(sc, BGE_MI_MODE);
-	if (autopoll & BGE_MIMODE_AUTOPOLL) {
-		BGE_CLRBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
-		DELAY(40);
+	/* Clear the autopoll bit if set, otherwise may trigger PCI errors. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE,
+		    sc->bge_mi_mode & ~BGE_MIMODE_AUTOPOLL);
+		DELAY(80);
 	}
 
 	CSR_WRITE_4(sc, BGE_MI_COMM, BGE_MICMD_WRITE | BGE_MICOMM_BUSY |
@@ -857,17 +848,16 @@ bge_miibus_writereg(device_t dev, int ph
 		}
 	}
 
-	if (i == BGE_TIMEOUT) {
+	/* Restore the autopoll bit if necessary. */
+	if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
+		CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode);
+		DELAY(80);
+	}
+
+	if (i == BGE_TIMEOUT)
 		device_printf(sc->bge_dev,
 		    "PHY write timed out (phy %d, reg %d, val %d)\n",
 		    phy, reg, val);
-		return (0);
-	}
-
-	if (autopoll & BGE_MIMODE_AUTOPOLL) {
-		BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL);
-		DELAY(40);
-	}
 
 	return (0);
 }
@@ -1918,11 +1908,17 @@ bge_blockinit(struct bge_softc *sc)
 	    BGE_MACSTAT_LINK_CHANGED);
 	CSR_WRITE_4(sc, BGE_MI_STS, 0);
 
-	/* Enable PHY auto polling (for MII/GMII only) */
+	/*
+	 * Enable attention when the link has changed state for
+	 * devices that use auto polling.
+	 */
 	if (sc->bge_flags & BGE_FLAG_TBI) {
 		CSR_WRITE_4(sc, BGE_MI_STS, BGE_MISTS_LINK);
 	} else {
-		BGE_SETBIT(sc, BGE_MI_MODE, BGE_MIMODE_AUTOPOLL | (10 << 16));
+		if (sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) {
+			CSR_WRITE_4(sc, BGE_MI_MODE, sc->bge_mi_mode);
+			DELAY(80);
+		}
 		if (sc->bge_asicrev == BGE_ASICREV_BCM5700 &&
 		    sc->bge_chipid != BGE_CHIPID_BCM5700_B2)
 			CSR_WRITE_4(sc, BGE_MAC_EVT_ENB,
@@ -2502,6 +2498,9 @@ bge_attach(device_t dev)
 	sc->bge_asicrev = BGE_ASICREV(sc->bge_chipid);
 	sc->bge_chiprev = BGE_CHIPREV(sc->bge_chipid);
 
+	/* Set default PHY address. */
+	sc->bge_phy_addr = 1;
+
 	/*
 	 * Don't enable Ethernet at WireSpeed for the 5700, 5906, or the
 	 * 5705 A0 and A1 chips.
@@ -2575,6 +2574,20 @@ bge_attach(device_t dev)
 			sc->bge_phy_flags |= BGE_PHY_BER_BUG;
 	}
 
+	/* Identify the chips that use an CPMU. */
+	if (sc->bge_asicrev == BGE_ASICREV_BCM5784 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5761 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM5785 ||
+	    sc->bge_asicrev == BGE_ASICREV_BCM57780)
+		sc->bge_flags |= BGE_FLAG_CPMU_PRESENT;
+	if ((sc->bge_flags & BGE_FLAG_CPMU_PRESENT) != 0)
+		sc->bge_mi_mode = BGE_MIMODE_500KHZ_CONST;
+	else
+		sc->bge_mi_mode = BGE_MIMODE_BASE;
+	/* Enable auto polling for BCM570[0-5]. */
+	if (BGE_IS_5700_FAMILY(sc) || sc->bge_asicrev == BGE_ASICREV_BCM5705)
+		sc->bge_mi_mode |= BGE_MIMODE_AUTOPOLL;
+
 	/*
 	 * All controllers that are not 5755 or higher have 4GB
 	 * boundary DMA bug.
@@ -4948,7 +4961,7 @@ bge_link_upd(struct bge_softc *sc)
 				if_printf(sc->bge_ifp, "link DOWN\n");
 			if_link_state_change(sc->bge_ifp, LINK_STATE_DOWN);
 		}
-	} else if (CSR_READ_4(sc, BGE_MI_MODE) & BGE_MIMODE_AUTOPOLL) {
+	} else if ((sc->bge_mi_mode & BGE_MIMODE_AUTOPOLL) != 0) {
 		/*
 		 * Some broken BCM chips have BGE_STATFLAG_LINKSTATE_CHANGED bit
 		 * in status word always set. Workaround this bug by reading
@@ -4976,9 +4989,17 @@ bge_link_upd(struct bge_softc *sc)
 		}
 	} else {
 		/*
-		 * Discard link events for MII/GMII controllers
-		 * if MI auto-polling is disabled.
+		 * For controllers that call mii_tick, we have to poll
+		 * link status.
 		 */
+		mii = device_get_softc(sc->bge_miibus);
+		mii_pollstat(mii);
+		if (!sc->bge_link && mii->mii_media_status & IFM_ACTIVE &&
+		    IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) {
+			bge_miibus_statchg(sc->bge_dev);
+			sc->bge_link = 1;
+		} else
+			sc->bge_link = 0;
 	}
 
 	/* Clear the attention. */

Modified: stable/8/sys/dev/bge/if_bgereg.h
==============================================================================
--- stable/8/sys/dev/bge/if_bgereg.h	Tue Nov  2 23:26:07 2010	(r214703)
+++ stable/8/sys/dev/bge/if_bgereg.h	Tue Nov  2 23:35:08 2010	(r214704)
@@ -863,9 +863,12 @@
 #define	BGE_MISTS_LINK			0x00000001
 #define	BGE_MISTS_10MBPS		0x00000002
 
+#define	BGE_MIMODE_CLK_10MHZ		0x00000001
 #define	BGE_MIMODE_SHORTPREAMBLE	0x00000002
 #define	BGE_MIMODE_AUTOPOLL		0x00000010
 #define	BGE_MIMODE_CLKCNT		0x001F0000
+#define	BGE_MIMODE_500KHZ_CONST		0x00008000
+#define	BGE_MIMODE_BASE			0x000C0000
 
 
 /*
@@ -1221,6 +1224,51 @@
 /* Receive List Selector Status register */
 #define	BGE_RXLSSTAT_ERROR		0x00000004
 
+#define	BGE_CPMU_CTRL			0x3600
+#define	BGE_CPMU_LSPD_10MB_CLK		0x3604
+#define	BGE_CPMU_LSPD_1000MB_CLK	0x360C
+#define	BGE_CPMU_LNK_AWARE_PWRMD	0x3610
+#define	BGE_CPMU_HST_ACC		0x361C
+#define	BGE_CPMU_CLCK_STAT		0x3630
+#define	BGE_CPMU_MUTEX_REQ		0x365C
+#define	BGE_CPMU_MUTEX_GNT		0x3660
+#define	BGE_CPMU_PHY_STRAP		0x3664
+
+/* Central Power Management Unit (CPMU) register */
+#define	BGE_CPMU_CTRL_LINK_IDLE_MODE	0x00000200
+#define	BGE_CPMU_CTRL_LINK_AWARE_MODE	0x00000400
+#define	BGE_CPMU_CTRL_LINK_SPEED_MODE	0x00004000
+#define	BGE_CPMU_CTRL_GPHY_10MB_RXONLY	0x00010000
+
+/* Link Speed 10MB/No Link Power Mode Clock Policy register */
+#define	BGE_CPMU_LSPD_10MB_MACCLK_MASK	0x001F0000
+#define	BGE_CPMU_LSPD_10MB_MACCLK_6_25	0x00130000
+
+/* Link Speed 1000MB Power Mode Clock Policy register */
+#define	BGE_CPMU_LSPD_1000MB_MACCLK_62_5	0x00000000
+#define	BGE_CPMU_LSPD_1000MB_MACCLK_12_5	0x00110000
+#define	BGE_CPMU_LSPD_1000MB_MACCLK_MASK	0x001F0000
+
+/* Link Aware Power Mode Clock Policy register */
+#define	BGE_CPMU_LNK_AWARE_MACCLK_MASK	0x001F0000
+#define	BGE_CPMU_LNK_AWARE_MACCLK_6_25	0x00130000
+
+#define	BGE_CPMU_HST_ACC_MACCLK_MASK	0x001F0000
+#define	BGE_CPMU_HST_ACC_MACCLK_6_25	0x00130000
+
+/* CPMU Clock Status register */
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_MASK	0x001F0000
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_62_5	0x00000000
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_12_5	0x00110000
+#define	BGE_CPMU_CLCK_STAT_MAC_CLCK_6_25	0x00130000
+
+/* CPMU Mutex Request register */
+#define	BGE_CPMU_MUTEX_REQ_DRIVER	0x00001000
+#define	BGE_CPMU_MUTEX_GNT_DRIVER	0x00001000
+
+/* CPMU GPHY Strap register */
+#define	BGE_CPMU_PHY_STRAP_IS_SERDES	0x00000020
+
 /*
  * Mbuf Cluster Free registers (has nothing to do with BSD mbufs)
  */
@@ -2665,6 +2713,7 @@ struct bge_softc {
 #define	BGE_FLAG_JUMBO		0x00000002
 #define	BGE_FLAG_EADDR		0x00000008
 #define	BGE_FLAG_MII_SERDES	0x00000010
+#define	BGE_FLAG_CPMU_PRESENT	0x00000020
 #define	BGE_FLAG_MSI		0x00000100
 #define	BGE_FLAG_PCIX		0x00000200
 #define	BGE_FLAG_PCIE		0x00000400
@@ -2707,7 +2756,9 @@ struct bge_softc {
 	uint32_t		bge_rx_max_coal_bds;
 	uint32_t		bge_tx_max_coal_bds;
 	uint32_t		bge_tx_buf_ratio;
+	uint32_t		bge_mi_mode;
 	int			bge_if_flags;
+	int			bge_phy_addr;
 	int			bge_txcnt;
 	int			bge_link;	/* link state */
 	int			bge_link_evt;	/* pending link event */


More information about the svn-src-all mailing list