summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoryongari <yongari@FreeBSD.org>2010-10-06 17:35:27 +0000
committeryongari <yongari@FreeBSD.org>2010-10-06 17:35:27 +0000
commit5a1ba87cd39233c29c6d2e2b90b55950703c54d4 (patch)
tree59bf37df005e79504c90867921f2ee93bcdf0a68
parent0ec5ea82890bcfadf0ab42368ce8bef795a5d2d0 (diff)
downloadFreeBSD-src-5a1ba87cd39233c29c6d2e2b90b55950703c54d4.zip
FreeBSD-src-5a1ba87cd39233c29c6d2e2b90b55950703c54d4.tar.gz
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
-rw-r--r--sys/dev/bge/if_bge.c82
-rw-r--r--sys/dev/bge/if_bgereg.h51
2 files changed, 94 insertions, 39 deletions
diff --git a/sys/dev/bge/if_bge.c b/sys/dev/bge/if_bge.c
index d2e47bc..1359bce 100644
--- a/sys/dev/bge/if_bge.c
+++ b/sys/dev/bge/if_bge.c
@@ -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, int reg)
"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 phy, int reg, int val)
(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 phy, int reg, int val)
}
}
- 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.
diff --git a/sys/dev/bge/if_bgereg.h b/sys/dev/bge/if_bgereg.h
index b17ff5a..3cf151e 100644
--- a/sys/dev/bge/if_bgereg.h
+++ b/sys/dev/bge/if_bgereg.h
@@ -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 */
OpenPOWER on IntegriCloud