Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 6 Oct 2010 17:35:27 +0000 (UTC)
From:      Pyun YongHyeon <yongari@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r213485 - head/sys/dev/bge
Message-ID:  <201010061735.o96HZRwb012282@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: yongari
Date: Wed Oct  6 17:35:27 2010
New Revision: 213485
URL: http://svn.freebsd.org/changeset/base/213485

Log:
  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

Modified:
  head/sys/dev/bge/if_bge.c
  head/sys/dev/bge/if_bgereg.h

Modified: head/sys/dev/bge/if_bge.c
==============================================================================
--- head/sys/dev/bge/if_bge.c	Wed Oct  6 15:37:55 2010	(r213484)
+++ head/sys/dev/bge/if_bge.c	Wed Oct  6 17:35:27 2010	(r213485)
@@ -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);
 }
@@ -2502,6 +2492,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@WireSpeed for the 5700, 5906, or the
 	 * 5705 A0 and A1 chips.
@@ -2575,6 +2568,17 @@ 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;
+
 	/*
 	 * All controllers that are not 5755 or higher have 4GB
 	 * boundary DMA bug.

Modified: head/sys/dev/bge/if_bgereg.h
==============================================================================
--- head/sys/dev/bge/if_bgereg.h	Wed Oct  6 15:37:55 2010	(r213484)
+++ head/sys/dev/bge/if_bgereg.h	Wed Oct  6 17:35:27 2010	(r213485)
@@ -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 */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201010061735.o96HZRwb012282>