Added support for the 80003ES2LAN Gigabit Ethernet controller (copper).
authornatalie_p <natalie_p>
Wed, 14 Jun 2006 00:23:16 +0000 (00:23 +0000)
committernatalie_p <natalie_p>
Wed, 14 Jun 2006 00:23:16 +0000 (00:23 +0000)
Fixed the ring operation by increasing number of RX buffers, otherwise
the controller hangs on receive during multicast or any kind of heavy
traffic.

src/drivers/net/e1000.c
src/drivers/net/e1000_hw.h

index 76d73a4..9d8b43e 100644 (file)
@@ -87,11 +87,14 @@ typedef enum {
 
 #include "e1000_hw.h"
 
+#define RX_BUFS        8
+#define MAX_PACKET     2096
+
 /* NIC specific static variables go here */
 static struct e1000_hw hw;
 static char tx_pool[128 + 16];
 static char rx_pool[128 + 16];
-static char packet[2096];
+static char packets[MAX_PACKET * RX_BUFS];
 
 static struct e1000_tx_desc *tx_base;
 static struct e1000_rx_desc *rx_base;
@@ -215,6 +218,11 @@ e1000_set_phy_type(struct e1000_hw *hw)
        case IGP01E1000_I_PHY_ID:
                hw->phy_type = e1000_phy_igp;
                break;
+       case GG82563_E_PHY_ID:
+               if (hw->mac_type == e1000_80003es2lan) {
+                       hw->phy_type = e1000_phy_gg82563;
+                       break;
+               }
        default:
                /* Should never have loaded on this device */
                hw->phy_type = e1000_phy_undefined;
@@ -379,6 +387,9 @@ e1000_set_mac_type(struct e1000_hw *hw)
        case E1000_DEV_ID_82547GI:
                hw->mac_type = e1000_82547_rev_2;
                break;
+       case E1000_DEV_ID_80003ES2LAN_COPPER_DPT:
+               hw->mac_type = e1000_80003es2lan;
+               break;
        default:
                /* Should never have loaded on this device */
                return -E1000_ERR_MAC_TYPE;
@@ -640,6 +651,21 @@ e1000_init_hw(struct e1000_hw *hw)
                case e1000_82545_rev_3:
                case e1000_82546_rev_3:
                        break;
+               case e1000_80003es2lan:
+               {
+                       int32_t timeout = 200;
+                       while(timeout) {
+                               if (E1000_READ_REG(hw, EECD) & E1000_EECD_AUTO_RD) 
+                                       break;
+                               else mdelay(10);
+                               timeout--;
+                       }
+                       if(!timeout) {
+                               /* We don't want to continue accessing MAC registers. */
+                               return -E1000_ERR_RESET;
+                       }
+                       break;
+               }
                default:
                        if (hw->mac_type >= e1000_82543) {
                                /* See e1000_get_bus_info() of the Linux driver */
@@ -1001,6 +1027,159 @@ e1000_setup_fiber_serdes_link(struct e1000_hw *hw)
        return E1000_SUCCESS;
 }
 
+int32_t
+e1000_read_kmrn_reg(struct e1000_hw *hw,
+                       uint32_t reg_addr,
+                       uint16_t *data)
+{
+       uint32_t reg_val;
+       DEBUGFUNC("e1000_read_kmrn_reg");
+       
+       /* Write register address */
+       reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+                       E1000_KUMCTRLSTA_OFFSET) |
+                       E1000_KUMCTRLSTA_REN;
+       E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+       udelay(2);
+
+       /* Read the data returned */
+       reg_val = E1000_READ_REG(hw, KUMCTRLSTA);
+       *data = (uint16_t)reg_val;
+
+       return E1000_SUCCESS;
+}
+
+int32_t
+e1000_write_kmrn_reg(struct e1000_hw *hw,
+                       uint32_t reg_addr,
+                       uint16_t data)
+{
+       uint32_t reg_val;
+       DEBUGFUNC("e1000_write_kmrn_reg");
+
+       reg_val = ((reg_addr << E1000_KUMCTRLSTA_OFFSET_SHIFT) &
+                       E1000_KUMCTRLSTA_OFFSET) | data;
+       E1000_WRITE_REG(hw, KUMCTRLSTA, reg_val);
+       udelay(2);
+
+       return E1000_SUCCESS;
+}
+
+/********************************************************************
+* Copper link setup for e1000_phy_gg82563 series.
+*
+* hw - Struct containing variables accessed by shared code
+*********************************************************************/
+
+static int32_t
+e1000_copper_link_ggp_setup(struct e1000_hw *hw)
+{
+       int32_t ret_val;
+       uint16_t phy_data;
+       uint32_t reg_data;
+
+       DEBUGFUNC("e1000_copper_link_ggp_setup\n");
+
+       /* Enable CRS on TX for half-duplex operation. */
+       ret_val = e1000_read_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+                                    &phy_data);
+       if(ret_val)
+               return ret_val;
+
+       phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
+       /* Use 25MHz for both link down and 1000BASE-T for Tx clock */
+       phy_data |= GG82563_MSCR_TX_CLK_1000MBPS_25MHZ;
+
+       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
+                                      phy_data);
+       if(ret_val)
+               return ret_val;
+       /* Options:
+        *   MDI/MDI-X = 0 (default)
+        *   0 - Auto for all speeds
+        *   1 - MDI mode
+        *   2 - MDI-X mode
+        *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
+        */
+       ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL, &phy_data);
+       if(ret_val)
+               return ret_val;
+
+       phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
+
+       phy_data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
+
+       /* Options:
+        *   disable_polarity_correction = 0 (default)
+        *       Automatic Correction for Reversed Cable Polarity
+        *   0 - Disabled
+        *   1 - Enabled
+        */
+       phy_data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
+       ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
+
+       if(ret_val)
+               return ret_val;
+
+       /* SW Reset the PHY so all changes take effect */
+       ret_val = e1000_phy_reset(hw);
+       if (ret_val) {
+           DEBUGOUT("Error Resetting the PHY\n");
+           return ret_val;
+       }
+
+       if (hw->mac_type == e1000_80003es2lan) {
+               /* Bypass RX and TX FIFO's */
+               ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL,
+                                               E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS |
+                                               E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS);
+               if (ret_val)
+                               return ret_val;
+
+               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, &phy_data);
+               if (ret_val)
+                       ret_val;
+
+               phy_data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
+               ret_val = e1000_write_phy_reg(hw, GG82563_PHY_SPEC_CTRL_2, phy_data);
+
+               if (ret_val)
+                       return ret_val;
+
+               reg_data = E1000_READ_REG(hw, CTRL_EXT);
+               reg_data &= ~(E1000_CTRL_EXT_LINK_MODE_MASK);
+               E1000_WRITE_REG(hw, CTRL_EXT, reg_data);
+       
+               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+                                                       &phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               /* Enable Electrical Idle on the PHY */
+               phy_data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
+               ret_val = e1000_write_phy_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
+                                                       phy_data);
+       
+               if (ret_val)
+                       return ret_val;
+
+               ret_val = e1000_read_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                                       &phy_data);
+               if (ret_val)
+                       return ret_val;
+
+               /* Disable Pass False Carrier on the PHY */
+               phy_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
+
+               ret_val = e1000_write_phy_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
+                                                       phy_data);
+               if (ret_val)
+                       return ret_val;
+       }
+
+       return E1000_SUCCESS;
+}
+
 /******************************************************************************
 * Detects which PHY is present and the speed and duplex
 *
@@ -1017,6 +1196,33 @@ e1000_setup_copper_link(struct e1000_hw *hw)
        DEBUGFUNC("e1000_setup_copper_link");
        
        ctrl = E1000_READ_REG(hw, CTRL);
+
+       if(hw->mac_type == e1000_80003es2lan) {
+               uint16_t reg_data;
+               /* Set the mac to wait the maximum time between each
+                * iteration and increase the max iterations when
+                * polling the phy; this fixes erroneous timeouts at 10Mbps. */
+               ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 4), 0xFFFF);
+               if (ret_val)
+                       return ret_val;
+               ret_val = e1000_read_kmrn_reg(hw, GG82563_REG(0x34, 9), &reg_data);
+               if (ret_val)
+                       return ret_val;
+               reg_data |= 0x3F;
+               ret_val = e1000_write_kmrn_reg(hw, GG82563_REG(0x34, 9), reg_data);
+               if (ret_val)
+                       return ret_val;
+               ret_val = e1000_read_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+                                                                       &reg_data);
+               if (ret_val)
+                       return ret_val;
+               reg_data |= E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING;
+               ret_val = e1000_write_kmrn_reg(hw, E1000_KUMCTRLSTA_OFFSET_INB_CTRL,
+                                                                       reg_data);
+               if (ret_val)
+                       return ret_val;
+       }
+
        /* With 82543, we need to force speed and duplex on the MAC equal to what
         * the PHY speed and duplex configuration is. In addition, we need to
         * perform a hardware reset on the PHY to take it out of reset.
@@ -1038,6 +1244,12 @@ e1000_setup_copper_link(struct e1000_hw *hw)
        }
        DEBUGOUT1("Phy ID = %x \n", hw->phy_id);
 
+       if (hw->phy_type == e1000_phy_gg82563) {
+               ret_val = e1000_copper_link_ggp_setup(hw);
+               if(ret_val)
+                       return ret_val;
+       }
+
        if(hw->mac_type <= e1000_82543 ||
           hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 ||
 #if 0
@@ -1046,9 +1258,10 @@ e1000_setup_copper_link(struct e1000_hw *hw)
 
        if(!hw->phy_reset_disable) {
 #else
-          hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2) {
+          hw->mac_type == e1000_82541_rev_2 || hw->mac_type == e1000_82547_rev_2 || 
+                                               hw->mac_type == e1000_80003es2lan) {
 #endif
-       if (hw->phy_type == e1000_phy_igp) {
+       if (hw->phy_type == e1000_phy_igp || hw->phy_type == e1000_phy_gg82563) {
 
                if((ret_val = e1000_phy_reset(hw))) {
                        DEBUGOUT("Error Resetting the PHY\n");
@@ -2553,6 +2766,15 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_detect_gig_phy");
        
+       /* ESB-2 PHY reads require e1000_phy_gg82563 to be set because of a work-
+        * around that forces PHY page 0 to be set or the reads fail.  The rest of
+        * the code in this routine uses e1000_read_phy_reg to read the PHY ID.
+        * So for ESB-2 we need to have this set so our reads won't fail.  If the
+        * attached PHY is not a e1000_phy_gg82563, the routines below will figure
+        * this out as well. */
+       if (hw->mac_type == e1000_80003es2lan)
+               hw->phy_type = e1000_phy_gg82563;
+       
        /* Read the PHY ID Registers to identify which PHY is onboard. */
        if((ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high)))
                return ret_val;
@@ -2587,6 +2809,9 @@ e1000_detect_gig_phy(struct e1000_hw *hw)
        case e1000_82547_rev_2:
                if(hw->phy_id == IGP01E1000_I_PHY_ID) match = TRUE;
                break;
+       case e1000_80003es2lan:
+               if (hw->phy_id == GG82563_E_PHY_ID) match = TRUE;
+               break;
        default:
                DEBUGOUT1("Invalid MAC type %d\n", hw->mac_type);
                return -E1000_ERR_CONFIG;
@@ -3273,6 +3498,8 @@ e1000_reset(struct e1000_hw *hw)
 
        if(hw->mac_type < e1000_82547) {
                pba = E1000_PBA_48K;
+       } else if (hw->mac_type == e1000_80003es2lan) {
+               pba = E1000_PBA_38K;
        } else {
                pba = E1000_PBA_30K;
        }
@@ -3386,11 +3613,10 @@ e1000_io_write(struct e1000_hw *hw __unused, uint32_t port, uint32_t value)
 static void fill_rx (void)
 {
        struct e1000_rx_desc *rd;
-       rx_last = rx_tail;
        rd = rx_base + rx_tail;
-       rx_tail = (rx_tail + 1) % 8;
        memset (rd, 0, 16);
-       rd->buffer_addr = virt_to_bus(&packet);
+       rd->buffer_addr = virt_to_bus(&packets[MAX_PACKET*(rx_tail%RX_BUFS)]);
+       rx_tail = (rx_tail + 1) % 8;
        E1000_WRITE_REG (&hw, RDT, rx_tail);
 }
 
@@ -3398,6 +3624,7 @@ static void init_descriptor (void)
 {
        unsigned long ptr;
        unsigned long tctl;
+       int i;
 
        ptr = virt_to_phys(tx_pool);
        if (ptr & 0xf)
@@ -3458,7 +3685,8 @@ static void init_descriptor (void)
                E1000_RCTL_BAM | 
                E1000_RCTL_SZ_2048 | 
                E1000_RCTL_MPE);
-       fill_rx();
+       for (i = 0; i < RX_BUFS; i++)
+               fill_rx();
 }
 
 
@@ -3473,6 +3701,7 @@ e1000_poll (struct nic *nic, int retrieve)
        /* nic->packet should contain data on return */
        /* nic->packetlen should contain length of data */
        struct e1000_rx_desc *rd;
+       char *packet = &packets[MAX_PACKET*(rx_last%RX_BUFS)];
        uint32_t icr;
 
        rd = rx_base + rx_last;
@@ -3484,6 +3713,7 @@ e1000_poll (struct nic *nic, int retrieve)
        //      printf("recv: packet %! -> %! len=%d \n", packet+6, packet,rd->Length);
        memcpy (nic->packet, packet, rd->length);
        nic->packetlen = rd->length;
+       rx_last = (rx_last + 1) %8;
        fill_rx ();
 
        /* Acknowledge interrupt. */
@@ -3733,6 +3963,7 @@ PCI_ROM(0x8086, 0x1079, "e1000-82546gb-copper",        "Intel EtherExpressPro1000
 PCI_ROM(0x8086, 0x107a, "e1000-82546gb-fiber",      "Intel EtherExpressPro1000 82546GB Fiber"),
 PCI_ROM(0x8086, 0x107b, "e1000-82546gb-serdes",             "Intel EtherExpressPro1000 82546GB SERDES"),
 PCI_ROM(0x8086, 0x107c, "e1000-82541pi",            "Intel EtherExpressPro1000 82541PI"),
+PCI_ROM(0x8086, 0x1096, "e1000_80003es2lan",        "Intel EtherExpressPro1000 GB COPPER"),
 };
 
 static struct pci_driver e1000_driver __pci_driver = {
index 7c7f48f..4581694 100644 (file)
@@ -54,6 +54,7 @@ typedef enum {
     e1000_82541_rev_2,
     e1000_82547,
     e1000_82547_rev_2,
+    e1000_80003es2lan,
     e1000_num_macs
 } e1000_mac_type;
 
@@ -187,6 +188,7 @@ typedef enum {
 typedef enum {
     e1000_phy_m88 = 0,
     e1000_phy_igp,
+    e1000_phy_gg82563,
     e1000_phy_undefined = 0xFF
 } e1000_phy_type;
 
@@ -247,6 +249,7 @@ struct e1000_eeprom_info {
 #define E1000_ERR_PHY_TYPE 6
 #define E1000_ERR_NOLINK   7
 #define E1000_ERR_TIMEOUT  8
+#define E1000_ERR_RESET    9
 
 #define E1000_READ_REG_IO(a, reg) \
        e1000_read_reg_io((a), E1000_##reg)
@@ -284,6 +287,7 @@ struct e1000_eeprom_info {
 #define E1000_DEV_ID_82546GB_FIBER       0x107A
 #define E1000_DEV_ID_82546GB_SERDES      0x107B
 #define E1000_DEV_ID_82547EI             0x1019
+#define E1000_DEV_ID_80003ES2LAN_COPPER_DPT     0x1096
 
 #define NODE_ADDRESS_SIZE 6
 #define ETH_LENGTH_OF_ADDRESS 6
@@ -689,6 +693,7 @@ struct e1000_ffvt_entry {
 #define E1000_FFLT     0x05F00  /* Flexible Filter Length Table - RW Array */
 #define E1000_FFMT     0x09000  /* Flexible Filter Mask Table - RW Array */
 #define E1000_FFVT     0x09800  /* Flexible Filter Value Table - RW Array */
+#define E1000_KUMCTRLSTA 0x00034 /* MAC-PHY interface - RW */
 
 /* Register Set (82542)
  *
@@ -823,6 +828,7 @@ struct e1000_ffvt_entry {
 #define E1000_82542_TDFT     0x08018
 #define E1000_82542_FFMT     E1000_FFMT
 #define E1000_82542_FFVT     E1000_FFVT
+#define E1000_82542_KUMCTRLSTA E1000_KUMCTRLSTA
 
 /* Statistics counters collected by the MAC */
 struct e1000_hw_stats {
@@ -1059,6 +1065,7 @@ struct e1000_hw {
 #ifndef E1000_EEPROM_GRANT_ATTEMPTS
 #define E1000_EEPROM_GRANT_ATTEMPTS 1000 /* EEPROM # attempts to gain grant */
 #endif
+#define E1000_EECD_AUTO_RD   0x00000200  /* EEPROM Auto Read done */
 
 /* EEPROM Read */
 #define E1000_EERD_START      0x00000001 /* Start Read */
@@ -1284,6 +1291,7 @@ struct e1000_hw {
 #define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
 #define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
 #define E1000_TXDCTL_FULL_TX_DESC_WB 0x01010000 /* GRAN=1, WTHRESH=1 */
+#define E1000_TXDCTL_COUNT_DESC 0x00400000 /* Enable the counting of desc.still to be processed. */
 
 /* Transmit Configuration Word */
 #define E1000_TXCW_FD         0x00000020        /* TXCW full duplex */
@@ -1374,7 +1382,7 @@ struct e1000_hw {
 #define E1000_MANC_IPV6_EN       0x00000800 /* Enable IPv6 */
 #define E1000_MANC_SNAP_EN       0x00001000 /* Accept LLC/SNAP */
 #define E1000_MANC_ARP_EN        0x00002000 /* Enable ARP Request Filtering */
-#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery 
+#define E1000_MANC_NEIGHBOR_EN   0x00004000 /* Enable Neighbor Discovery
                                              * Filtering */
 #define E1000_MANC_TCO_RESET     0x00010000 /* TCO Reset Occurred */
 #define E1000_MANC_RCV_TCO_EN    0x00020000 /* Receive TCO Packets Enabled */
@@ -1394,6 +1402,32 @@ struct e1000_hw {
 
 #define E1000_MDALIGN          4096
 
+#define E1000_KUMCTRLSTA_MASK           0x0000FFFF
+#define E1000_KUMCTRLSTA_OFFSET         0x001F0000
+#define E1000_KUMCTRLSTA_OFFSET_SHIFT   16
+#define E1000_KUMCTRLSTA_REN            0x00200000
+
+#define E1000_KUMCTRLSTA_OFFSET_FIFO_CTRL      0x00000000
+#define E1000_KUMCTRLSTA_OFFSET_CTRL           0x00000001
+#define E1000_KUMCTRLSTA_OFFSET_INB_CTRL       0x00000002
+#define E1000_KUMCTRLSTA_OFFSET_DIAG           0x00000003
+#define E1000_KUMCTRLSTA_OFFSET_TIMEOUTS       0x00000004
+#define E1000_KUMCTRLSTA_OFFSET_INB_PARAM      0x00000009
+#define E1000_KUMCTRLSTA_OFFSET_HD_CTRL        0x00000010
+#define E1000_KUMCTRLSTA_OFFSET_M2P_SERDES     0x0000001E
+#define E1000_KUMCTRLSTA_OFFSET_M2P_MODES      0x0000001F
+
+/* FIFO Control */
+#define E1000_KUMCTRLSTA_FIFO_CTRL_RX_BYPASS   0x00000008
+#define E1000_KUMCTRLSTA_FIFO_CTRL_TX_BYPASS   0x00000800
+
+/* In-Band Control */
+#define E1000_KUMCTRLSTA_INB_CTRL_DIS_PADDING  0x00000010
+
+/* Half-Duplex Control */
+#define E1000_KUMCTRLSTA_HD_CTRL_10_100_DEFAULT 0x00000004
+#define E1000_KUMCTRLSTA_HD_CTRL_1000_DEFAULT  0x00000000
+
 /* EEPROM Commands - Microwire */
 #define EEPROM_READ_OPCODE_MICROWIRE  0x6  /* EEPROM read opcode */
 #define EEPROM_WRITE_OPCODE_MICROWIRE 0x5  /* EEPROM write opcode */
@@ -1533,6 +1567,7 @@ struct e1000_hw {
 #define E1000_PBA_22K 0x0016
 #define E1000_PBA_24K 0x0018
 #define E1000_PBA_30K 0x001E
+#define E1000_PBA_38K 0x0026
 #define E1000_PBA_40K 0x0028
 #define E1000_PBA_48K 0x0030    /* 48KB, default RX allocation */
 
@@ -2019,6 +2054,43 @@ struct e1000_hw {
 #define IGP01E1000_ANALOG_FUSE_FINE_1               0x0080
 #define IGP01E1000_ANALOG_FUSE_FINE_10              0x0500
 
+
+/* GG82563 PHY Specific Status Register (Page 0, Register 16 */
+#define GG82563_PSCR_POLARITY_REVERSAL_DISABLE  0x0002 /* 1=Polarity Reversal Disabled */
+#define GG82563_PSCR_POWER_DOWN                 0x0004 /* 1=Power Down */
+#define GG82563_PSCR_COPPER_TRANSMITER_DISABLE  0x0008 /* 1=Transmitter Disabled */
+#define GG82563_PSCR_CROSSOVER_MODE_MASK        0x0060
+#define GG82563_PSCR_CROSSOVER_MODE_MDI         0x0000 /* 00=Manual MDI configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_MDIX        0x0020 /* 01=Manual MDIX configuration */
+#define GG82563_PSCR_CROSSOVER_MODE_AUTO        0x0060 /* 11=Automatic crossover */
+
+/* PHY Specific Control Register 2 (Page 0, Register 26) */
+#define GG82563_PSCR2_REVERSE_AUTO_NEG              0x2000 /* 1=Reverse Auto-Negotiation */
+#define GG82563_PSCR2_TRANSMITER_TYPE_MASK          0x8000
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_B      0x0000 /* 0=Class B */
+#define GG82563_PSCR2_TRANSMITTER_TYPE_CLASS_A      0x8000 /* 1=Class A */
+
+/* MAC Specific Control Register (Page 2, Register 21) */
+/* Tx clock speed for Link Down and 1000BASE-T for the following speeds */
+#define GG82563_MSCR_TX_CLK_MASK                    0x0007
+#define GG82563_MSCR_TX_CLK_10MBPS_2_5MHZ           0x0004
+#define GG82563_MSCR_TX_CLK_100MBPS_25MHZ           0x0005
+#define GG82563_MSCR_TX_CLK_1000MBPS_2_5MHZ         0x0006
+#define GG82563_MSCR_TX_CLK_1000MBPS_25MHZ          0x0007
+#define GG82563_MSCR_ASSERT_CRS_ON_TX               0x0010 /* 1=Assert */
+
+/* Kumeran Mode Control Register (Page 193, Register 16) */
+#define GG82563_KMCR_PHY_LEDS_EN                    0x0020 /* 1=PHY LEDs, 0=Kumeran Inband LEDs */
+#define GG82563_KMCR_FORCE_LINK_UP                  0x0040 /* 1=Force Link Up */
+#define GG82563_KMCR_PASS_FALSE_CARRIER             0x0800
+
+/* Power Management Control Register (Page 193, Register 20) */
+#define GG82563_PMCR_ENABLE_ELECTRICAL_IDLE         0x0001 /* 1=Enalbe SERDES Electrical Idle */
+#define GG82563_PMCR_FORCE_POWER_STATE              0x0080 /* 1=Force Power State */
+
+/* In-Band Control Register (Page 194, Register 18) */
+#define GG82563_ICR_DIS_PADDING                     0x0010 /* Disable Padding Use */
+
 /* Bit definitions for valid PHY IDs. */
 #define M88E1000_E_PHY_ID  0x01410C50
 #define M88E1000_I_PHY_ID  0x01410C30
@@ -2027,6 +2099,7 @@ struct e1000_hw {
 #define M88E1000_12_PHY_ID M88E1000_E_PHY_ID
 #define M88E1000_14_PHY_ID M88E1000_E_PHY_ID
 #define M88E1011_I_REV_4   0x04
+#define GG82563_E_PHY_ID   0x01410CA0
 
 /* Miscellaneous PHY bit definitions. */
 #define PHY_PREAMBLE        0xFFFFFFFF
@@ -2055,4 +2128,35 @@ struct e1000_hw {
 #define AUTONEG_ADVERTISE_10_100_ALL    0x000F /* All 10/100 speeds*/
 #define AUTONEG_ADVERTISE_10_ALL        0x0003 /* 10Mbps Full & Half speeds*/
 
+#define GG82563_PAGE_SHIFT        5
+#define GG82563_REG(page, reg)    \
+        (((page) << GG82563_PAGE_SHIFT) | ((reg) & MAX_PHY_REG_ADDRESS))
+#define GG82563_MIN_ALT_REG       30
+
+/* GG82563 Specific Registers */
+#define GG82563_PHY_SPEC_CTRL           \
+        GG82563_REG(0, 16) /* PHY Specific Control */
+#define GG82563_PHY_SPEC_STATUS_2       \
+        GG82563_REG(0, 19) /* PHY Specific Status 2 */
+#define GG82563_PHY_SPEC_CTRL_2         \
+        GG82563_REG(0, 26) /* PHY Specific Control 2 */
+#define GG82563_PHY_MAC_SPEC_CTRL       \
+        GG82563_REG(2, 21) /* MAC Specific Control Register */
+#define GG82563_PHY_MAC_SPEC_CTRL_2     \
+        GG82563_REG(2, 26) /* MAC Specific Control 2 */
+
+/* Page 193 - Port Control Registers */
+#define GG82563_PHY_KMRN_MODE_CTRL   \
+        GG82563_REG(193, 16) /* Kumeran Mode Control */
+#define GG82563_PHY_DEVICE_ID           \
+        GG82563_REG(193, 19) /* Device ID */
+#define GG82563_PHY_PWR_MGMT_CTRL       \
+        GG82563_REG(193, 20) /* Power Management Control */
+
+/* Page 194 - KMRN Registers */
+#define GG82563_PHY_KMRN_CTRL           \
+        GG82563_REG(194, 17) /* Control */
+#define GG82563_PHY_INBAND_CTRL         \
+        GG82563_REG(194, 18) /* Inband Control */
+
 #endif /* _E1000_HW_H_ */