NET: Add Ethernet 1000BASE-X support for PPC4xx
authorLarry Johnson <lrj@arlinx.com>
Thu, 1 Nov 2007 13:46:50 +0000 (08:46 -0500)
committerBen Warren <bwarren@qstreams.com>
Tue, 6 Nov 2007 15:25:33 +0000 (10:25 -0500)
This patch adds support for 1000BASE-X to functions "miiphy_speed ()" and
"miiphy_duplex()".  It also adds function "miiphy_is_1000base_x ()", which
returns non-zero iff the PHY registers are configured for 1000BASE-X.  The
"mii info" command is modified to distinguish between 1000BASE-T and -X.

Signed-off-by: Larry Johnson <lrj@acm.org>
Signed-off-by: Ben Warren <bwarren@qstreams.com>
common/cmd_mii.c
common/miiphyutil.c
include/miiphy.h

index 72e11d54425097d4eec8e790597803a3aa42be8c..3b4dc8ae09874f3efd9b78dd1615858af13ae265 100644 (file)
@@ -112,9 +112,11 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
                                        "OUI = 0x%04X, "
                                        "Model = 0x%02X, "
                                        "Rev = 0x%02X, "
-                                       "%3dbaseT, %s\n",
+                                       "%3dbase%s, %s\n",
                                        j, oui, model, rev,
                                        miiphy_speed (devname, j),
+                                       miiphy_is_1000base_x (devname, j)
+                                               ? "X" : "T",
                                        (miiphy_duplex (devname, j) == FULL)
                                                ? "FDX" : "HDX");
                        }
@@ -496,9 +498,11 @@ int do_mii (cmd_tbl_t * cmdtp, int flag, int argc, char *argv[])
                                        "OUI = 0x%04X, "
                                        "Model = 0x%02X, "
                                        "Rev = 0x%02X, "
-                                       "%3dbaseT, %s\n",
+                                       "%3dbase%s, %s\n",
                                        j, oui, model, rev,
                                        miiphy_speed (devname, j),
+                                       miiphy_is_1000base_x (devname, j)
+                                               ? "X" : "T",
                                        (miiphy_duplex (devname, j) == FULL)
                                                ? "FDX" : "HDX");
                        }
index 58ebc5ec2c141369e18bf2e587a7c23f65b07771..281f0b29e3bc1c006e312ee6188e9892b7ef5ab5 100644 (file)
@@ -344,101 +344,136 @@ int miiphy_reset (char *devname, unsigned char addr)
 
 /*****************************************************************************
  *
- * Determine the ethernet speed (10/100).
+ * Determine the ethernet speed (10/100/1000).  Return 10 on error.
  */
 int miiphy_speed (char *devname, unsigned char addr)
 {
-       unsigned short reg;
+       u16 bmcr, anlpar;
 
 #if defined(CONFIG_PHY_GIGE)
-       if (miiphy_read (devname, addr, PHY_1000BTSR, &reg)) {
-               printf ("PHY 1000BT Status read failed\n");
-       } else {
-               if (reg != 0xFFFF) {
-                       if ((reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))
-                           != 0) {
-                               return (_1000BASET);
-                       }
-               }
+       u16 btsr;
+
+       /*
+        * Check for 1000BASE-X.  If it is supported, then assume that the speed
+        * is 1000.
+        */
+       if (miiphy_is_1000base_x (devname, addr)) {
+               return _1000BASET;
+       }
+       /*
+        * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
+        */
+       /* Check for 1000BASE-T. */
+       if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
+               printf ("PHY 1000BT status");
+               goto miiphy_read_failed;
+       }
+       if (btsr != 0xFFFF &&
+           (btsr & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
+               return _1000BASET;
        }
 #endif /* CONFIG_PHY_GIGE */
 
        /* Check Basic Management Control Register first. */
-       if (miiphy_read (devname, addr, PHY_BMCR, &reg)) {
-               puts ("PHY speed read failed, assuming 10bT\n");
-               return (_10BASET);
+       if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
+               printf ("PHY speed");
+               goto miiphy_read_failed;
        }
        /* Check if auto-negotiation is on. */
-       if ((reg & PHY_BMCR_AUTON) != 0) {
+       if (bmcr & PHY_BMCR_AUTON) {
                /* Get auto-negotiation results. */
-               if (miiphy_read (devname, addr, PHY_ANLPAR, &reg)) {
-                       puts ("PHY AN speed read failed, assuming 10bT\n");
-                       return (_10BASET);
-               }
-               if ((reg & PHY_ANLPAR_100) != 0) {
-                       return (_100BASET);
-               } else {
-                       return (_10BASET);
+               if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
+                       printf ("PHY AN speed");
+                       goto miiphy_read_failed;
                }
+               return (anlpar & PHY_ANLPAR_100) ? _100BASET : _10BASET;
        }
        /* Get speed from basic control settings. */
-       else if (reg & PHY_BMCR_100MB) {
-               return (_100BASET);
-       } else {
-               return (_10BASET);
-       }
+       return (bmcr & PHY_BMCR_100MB) ? _100BASET : _10BASET;
 
+      miiphy_read_failed:
+       printf (" read failed, assuming 10BASE-T\n");
+       return _10BASET;
 }
 
 /*****************************************************************************
  *
- * Determine full/half duplex.
+ * Determine full/half duplex.  Return half on error.
  */
 int miiphy_duplex (char *devname, unsigned char addr)
 {
-       unsigned short reg;
+       u16 bmcr, anlpar;
 
 #if defined(CONFIG_PHY_GIGE)
-       if (miiphy_read (devname, addr, PHY_1000BTSR, &reg)) {
-               printf ("PHY 1000BT Status read failed\n");
-       } else {
-               if ((reg != 0xFFFF) &&
-                   (reg & (PHY_1000BTSR_1000FD | PHY_1000BTSR_1000HD))) {
-                       if ((reg & PHY_1000BTSR_1000FD) != 0) {
-                               return (FULL);
-                       } else {
-                               return (HALF);
-                       }
+       u16 btsr;
+
+       /* Check for 1000BASE-X. */
+       if (miiphy_is_1000base_x (devname, addr)) {
+               /* 1000BASE-X */
+               if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
+                       printf ("1000BASE-X PHY AN duplex");
+                       goto miiphy_read_failed;
+               }
+       }
+       /*
+        * No 1000BASE-X, so assume 1000BASE-T/100BASE-TX/10BASE-T register set.
+        */
+       /* Check for 1000BASE-T. */
+       if (miiphy_read (devname, addr, PHY_1000BTSR, &btsr)) {
+               printf ("PHY 1000BT status");
+               goto miiphy_read_failed;
+       }
+       if (btsr != 0xFFFF) {
+               if (btsr & PHY_1000BTSR_1000FD) {
+                       return FULL;
+               } else if (btsr & PHY_1000BTSR_1000HD) {
+                       return HALF;
                }
        }
 #endif /* CONFIG_PHY_GIGE */
 
        /* Check Basic Management Control Register first. */
-       if (miiphy_read (devname, addr, PHY_BMCR, &reg)) {
-               puts ("PHY duplex read failed, assuming half duplex\n");
-               return (HALF);
+       if (miiphy_read (devname, addr, PHY_BMCR, &bmcr)) {
+               puts ("PHY duplex");
+               goto miiphy_read_failed;
        }
        /* Check if auto-negotiation is on. */
-       if ((reg & PHY_BMCR_AUTON) != 0) {
+       if (bmcr & PHY_BMCR_AUTON) {
                /* Get auto-negotiation results. */
-               if (miiphy_read (devname, addr, PHY_ANLPAR, &reg)) {
-                       puts ("PHY AN duplex read failed, assuming half duplex\n");
-                       return (HALF);
-               }
-
-               if ((reg & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) {
-                       return (FULL);
-               } else {
-                       return (HALF);
+               if (miiphy_read (devname, addr, PHY_ANLPAR, &anlpar)) {
+                       puts ("PHY AN duplex");
+                       goto miiphy_read_failed;
                }
+               return (anlpar & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) ?
+                   FULL : HALF;
        }
        /* Get speed from basic control settings. */
-       else if (reg & PHY_BMCR_DPLX) {
-               return (FULL);
-       } else {
-               return (HALF);
-       }
+       return (bmcr & PHY_BMCR_DPLX) ? FULL : HALF;
+
+      miiphy_read_failed:
+       printf (" read failed, assuming half duplex\n");
+       return HALF;
+}
 
+/*****************************************************************************
+ *
+ * Return 1 if PHY supports 1000BASE-X, 0 if PHY supports 10BASE-T/100BASE-TX/
+ * 1000BASE-T, or on error.
+ */
+int miiphy_is_1000base_x (char *devname, unsigned char addr)
+{
+#if defined(CONFIG_PHY_GIGE)
+       u16 exsr;
+
+       if (miiphy_read (devname, addr, PHY_EXSR, &exsr)) {
+               printf ("PHY extended status read failed, assuming no "
+                       "1000BASE-X\n");
+               return 0;
+       }
+       return 0 != (exsr & (PHY_EXSR_1000XF | PHY_EXSR_1000XH));
+#else
+       return 0;
+#endif
 }
 
 #ifdef CFG_FAULT_ECHO_LINK_DOWN
index 42f2ad0c96774f7e01ae1a3e6b68207c61a99727..5518a0a89c217af215a1cc4f192280fb527f57ed 100644 (file)
@@ -41,6 +41,7 @@ int miiphy_info (char *devname, unsigned char addr, unsigned int *oui,
 int miiphy_reset (char *devname, unsigned char addr);
 int miiphy_speed (char *devname, unsigned char addr);
 int miiphy_duplex (char *devname, unsigned char addr);
+int miiphy_is_1000base_x (char *devname, unsigned char addr);
 #ifdef CFG_FAULT_ECHO_LINK_DOWN
 int miiphy_link (char *devname, unsigned char addr);
 #endif
@@ -85,6 +86,7 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_ANLPNP             0x08
 #define PHY_1000BTCR           0x09
 #define PHY_1000BTSR           0x0A
+#define PHY_EXSR               0x0F
 #define PHY_PHYSTS             0x10
 #define PHY_MIPSCR             0x11
 #define PHY_MIPGSR             0x12
@@ -118,6 +120,7 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_BMSR_100TXH                0x2000
 #define PHY_BMSR_10TF          0x1000
 #define PHY_BMSR_10TH          0x0800
+#define PHY_BMSR_EXT_STAT      0x0100
 #define PHY_BMSR_PRE_SUP       0x0040
 #define PHY_BMSR_AUTN_COMP     0x0020
 #define PHY_BMSR_RF            0x0010
@@ -130,17 +133,30 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_ANLPAR_NP          0x8000
 #define PHY_ANLPAR_ACK         0x4000
 #define PHY_ANLPAR_RF          0x2000
+#define PHY_ANLPAR_ASYMP       0x0800
+#define PHY_ANLPAR_PAUSE       0x0400
 #define PHY_ANLPAR_T4          0x0200
 #define PHY_ANLPAR_TXFD                0x0100
 #define PHY_ANLPAR_TX          0x0080
 #define PHY_ANLPAR_10FD                0x0040
 #define PHY_ANLPAR_10          0x0020
 #define PHY_ANLPAR_100         0x0380  /* we can run at 100 */
+/* phy ANLPAR 1000BASE-X */
+#define PHY_X_ANLPAR_NP                0x8000
+#define PHY_X_ANLPAR_ACK       0x4000
+#define PHY_X_ANLPAR_RF_MASK   0x3000
+#define PHY_X_ANLPAR_PAUSE_MASK        0x0180
+#define PHY_X_ANLPAR_HD                0x0040
+#define PHY_X_ANLPAR_FD                0x0020
 
 #define PHY_ANLPAR_PSB_MASK    0x001f
 #define PHY_ANLPAR_PSB_802_3   0x0001
 #define PHY_ANLPAR_PSB_802_9   0x0002
 
+/* phy 1000BTCR */
+#define PHY_1000BTCR_1000FD    0x0200
+#define PHY_1000BTCR_1000HD    0x0100
+
 /* phy 1000BTSR */
 #define PHY_1000BTSR_MSCF      0x8000
 #define PHY_1000BTSR_MSCR      0x4000
@@ -149,4 +165,10 @@ int bb_miiphy_write (char *devname, unsigned char addr,
 #define PHY_1000BTSR_1000FD    0x0800
 #define PHY_1000BTSR_1000HD    0x0400
 
+/* phy EXSR */
+#define PHY_EXSR_1000XF                0x8000
+#define PHY_EXSR_1000XH                0x4000
+#define PHY_EXSR_1000TF                0x2000
+#define PHY_EXSR_1000TH                0x1000
+
 #endif