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 ether...@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 */
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to