em/emx: Update to Intel em-7.2.4
authorSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 13 Apr 2012 09:09:10 +0000 (17:09 +0800)
committerSepherosa Ziehau <sephe@dragonflybsd.org>
Fri, 13 Apr 2012 10:35:12 +0000 (18:35 +0800)
- Fix the max frame length settings for 82583 chips
- Workaround 82574 specification update errata #20.

Local changes:
- For 82574 specification update errata #20 workaround, we don't
  disable ASPM L1.  Disabling ASPM L1 is said to be unnecessary
  in the specification update.

21 files changed:
sys/dev/netif/em/if_em.c
sys/dev/netif/emx/if_emx.c
sys/dev/netif/ig_hal/e1000_80003es2lan.c
sys/dev/netif/ig_hal/e1000_82540.c
sys/dev/netif/ig_hal/e1000_82541.c
sys/dev/netif/ig_hal/e1000_82542.c
sys/dev/netif/ig_hal/e1000_82543.c
sys/dev/netif/ig_hal/e1000_82571.c
sys/dev/netif/ig_hal/e1000_api.c
sys/dev/netif/ig_hal/e1000_defines.h
sys/dev/netif/ig_hal/e1000_hw.h
sys/dev/netif/ig_hal/e1000_ich8lan.c
sys/dev/netif/ig_hal/e1000_ich8lan.h
sys/dev/netif/ig_hal/e1000_mac.c
sys/dev/netif/ig_hal/e1000_mac.h
sys/dev/netif/ig_hal/e1000_manage.c
sys/dev/netif/ig_hal/e1000_nvm.c
sys/dev/netif/ig_hal/e1000_nvm.h
sys/dev/netif/ig_hal/e1000_phy.c
sys/dev/netif/ig_hal/e1000_phy.h
sys/dev/netif/ig_hal/e1000_regs.h

index 8ca6336..105f004 100644 (file)
 #include <dev/netif/em/if_em.h>
 
 #define EM_NAME        "Intel(R) PRO/1000 Network Connection "
-#define EM_VER " 7.1.7"
+#define EM_VER " 7.2.4"
 
 #define _EM_DEVICE(id, ret)    \
        { EM_VENDOR_ID, E1000_DEV_ID_##id, ret, EM_NAME #id EM_VER }
@@ -315,6 +315,7 @@ static void em_set_multi(struct adapter *);
 static void    em_update_link_status(struct adapter *);
 static void    em_smartspeed(struct adapter *);
 static void    em_set_itr(struct adapter *, uint32_t);
+static void    em_disable_aspm(struct adapter *);
 
 /* Hardware workarounds */
 static int     em_82547_fifo_workaround(struct adapter *, int);
@@ -1005,6 +1006,7 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
                case e1000_ich10lan:
                case e1000_pch2lan:
                case e1000_82574:
+               case e1000_82583:
                case e1000_80003es2lan:
                        max_frame_size = 9234;
                        break;
@@ -1015,7 +1017,6 @@ em_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr)
 
                /* Adapters that do not support jumbo frames */
                case e1000_82542:
-               case e1000_82583:
                case e1000_ich8lan:
                        max_frame_size = ETHER_MAX_LEN;
                        break;
@@ -2291,6 +2292,7 @@ em_reset(struct adapter *adapter)
        e1000_reset_hw(&adapter->hw);
        if (adapter->hw.mac.type >= e1000_82544)
                E1000_WRITE_REG(&adapter->hw, E1000_WUC, 0);
+       em_disable_aspm(adapter);
 
        if (e1000_init_hw(&adapter->hw) < 0) {
                device_printf(dev, "Hardware Initialization Failed\n");
@@ -3481,7 +3483,7 @@ em_disable_intr(struct adapter *adapter)
         */
        if (adapter->hw.mac.type == e1000_82542 &&
            adapter->hw.revision_id == E1000_REVISION_2)
-               clear &= ~E1000_IMC_RXSEQ;
+               clear &= ~E1000_ICR_RXSEQ;
        else if (adapter->hw.mac.type == e1000_82574)
                E1000_WRITE_REG(&adapter->hw, EM_EIAC, 0);
 
@@ -4111,3 +4113,40 @@ em_set_itr(struct adapter *adapter, uint32_t itr)
                }
        }
 }
+
+/*
+ * Disable the L0s, Errata #20
+ */
+static void
+em_disable_aspm(struct adapter *adapter)
+{
+       uint16_t link_cap, link_ctrl;
+       uint8_t pcie_ptr, reg;
+       device_t dev = adapter->dev;
+
+       switch (adapter->hw.mac.type) {
+       case e1000_82573:
+       case e1000_82574:
+       case e1000_82583:
+               break;
+
+       default:
+               return;
+       }
+
+       pcie_ptr = pci_get_pciecap_ptr(dev);
+       if (pcie_ptr == 0)
+               return;
+
+       link_cap = pci_read_config(dev, pcie_ptr + PCIER_LINKCAP, 2);
+       if ((link_cap & PCIEM_LNKCAP_ASPM_MASK) == 0)
+               return;
+
+       if (bootverbose)
+               if_printf(&adapter->arpcom.ac_if, "disable L0s\n");
+
+       reg = pcie_ptr + PCIER_LINKCTRL;
+       link_ctrl = pci_read_config(dev, reg, 2);
+       link_ctrl &= ~PCIEM_LNKCTL_ASPM_L0S;
+       pci_write_config(dev, reg, link_ctrl, 2);
+}
index fb71099..fe4d9f1 100644 (file)
@@ -226,6 +226,7 @@ static void emx_set_multi(struct emx_softc *);
 static void    emx_update_link_status(struct emx_softc *);
 static void    emx_smartspeed(struct emx_softc *);
 static void    emx_set_itr(struct emx_softc *, uint32_t);
+static void    emx_disable_aspm(struct emx_softc *);
 
 static void    emx_print_debug_info(struct emx_softc *);
 static void    emx_print_nvm_info(struct emx_softc *);
@@ -1754,6 +1755,7 @@ emx_reset(struct emx_softc *sc)
        /* Issue a global reset */
        e1000_reset_hw(&sc->hw);
        E1000_WRITE_REG(&sc->hw, E1000_WUC, 0);
+       emx_disable_aspm(sc);
 
        if (e1000_init_hw(&sc->hw) < 0) {
                device_printf(dev, "Hardware Initialization Failed\n");
@@ -3829,3 +3831,39 @@ emx_set_itr(struct emx_softc *sc, uint32_t itr)
                        E1000_WRITE_REG(&sc->hw, E1000_EITR_82574(i), itr);
        }
 }
+
+/*
+ * Disable the L0s, 82574L Errata #20
+ */
+static void
+emx_disable_aspm(struct emx_softc *sc)
+{
+       uint16_t link_cap, link_ctrl;
+       uint8_t pcie_ptr, reg;
+       device_t dev = sc->dev;
+
+       switch (sc->hw.mac.type) {
+       case e1000_82573:
+       case e1000_82574:
+               break;
+
+       default:
+               return;
+       }
+
+       pcie_ptr = pci_get_pciecap_ptr(dev);
+       if (pcie_ptr == 0)
+               return;
+
+       link_cap = pci_read_config(dev, pcie_ptr + PCIER_LINKCAP, 2);
+       if ((link_cap & PCIEM_LNKCAP_ASPM_MASK) == 0)
+               return;
+
+       if (bootverbose)
+               if_printf(&sc->arpcom.ac_if, "disable L0s\n");
+
+       reg = pcie_ptr + PCIER_LINKCTRL;
+       link_ctrl = pci_read_config(dev, reg, 2);
+       link_ctrl &= ~PCIEM_LNKCTL_ASPM_L0S;
+       pci_write_config(dev, reg, link_ctrl, 2);
+}
index fd96705..0655336 100644 (file)
@@ -82,8 +82,8 @@ static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
  * with a lower bound at "index" and the upper bound at
  * "index + 5".
  */
-static const u16 e1000_gg82563_cable_length_table[] =
-         { 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
+static const u16 e1000_gg82563_cable_length_table[] = {
+       0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
 #define GG82563_CABLE_LENGTH_TABLE_SIZE \
                 (sizeof(e1000_gg82563_cable_length_table) / \
                  sizeof(e1000_gg82563_cable_length_table[0]))
@@ -854,7 +854,7 @@ static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
  **/
 static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
 {
-       u32 ctrl, icr;
+       u32 ctrl;
        s32 ret_val;
 
        DEBUGFUNC("e1000_reset_hw_80003es2lan");
@@ -890,7 +890,7 @@ static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
 
        /* Clear any pending interrupt events. */
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
-       icr = E1000_READ_REG(hw, E1000_ICR);
+       E1000_READ_REG(hw, E1000_ICR);
 
        ret_val = e1000_check_alt_mac_addr_generic(hw);
 
@@ -909,6 +909,7 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
        struct e1000_mac_info *mac = &hw->mac;
        u32 reg_data;
        s32 ret_val;
+       u16 kum_reg_data;
        u16 i;
 
        DEBUGFUNC("e1000_init_hw_80003es2lan");
@@ -936,6 +937,13 @@ static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
        /* Setup link and flow control */
        ret_val = mac->ops.setup_link(hw);
 
+       /* Disable IBIST slave mode (far-end loopback) */
+       e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+                                       &kum_reg_data);
+       kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
+       e1000_write_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
+                                        kum_reg_data);
+
        /* Set the transmit descriptor write-back policy */
        reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
        reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
index a3d238f..4f60916 100644 (file)
@@ -269,7 +269,7 @@ void e1000_init_function_pointers_82540(struct e1000_hw *hw)
  **/
 static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
 {
-       u32 ctrl, icr, manc;
+       u32 ctrl, manc;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_reset_hw_82540");
@@ -314,7 +314,7 @@ static s32 e1000_reset_hw_82540(struct e1000_hw *hw)
        E1000_WRITE_REG(hw, E1000_MANC, manc);
 
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
-       icr = E1000_READ_REG(hw, E1000_ICR);
+       E1000_READ_REG(hw, E1000_ICR);
 
        return ret_val;
 }
index 838e285..58e34c4 100644 (file)
@@ -297,7 +297,7 @@ void e1000_init_function_pointers_82541(struct e1000_hw *hw)
  **/
 static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
 {
-       u32 ledctl, ctrl, icr, manc;
+       u32 ledctl, ctrl, manc;
 
        DEBUGFUNC("e1000_reset_hw_82541");
 
@@ -361,7 +361,7 @@ static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
        E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
 
        /* Clear any pending interrupt events. */
-       icr = E1000_READ_REG(hw, E1000_ICR);
+       E1000_READ_REG(hw, E1000_ICR);
 
        return E1000_SUCCESS;
 }
@@ -387,7 +387,7 @@ static s32 e1000_init_hw_82541(struct e1000_hw *hw)
                DEBUGOUT("Error initializing identification LED\n");
                /* This is not fatal and we should not stop init due to this */
        }
-        
+
        /* Storing the Speed Power Down  value for later use */
        ret_val = hw->phy.ops.read_reg(hw,
                                       IGP01E1000_GMII_FIFO,
index 2675d8e..49010ea 100644 (file)
@@ -191,7 +191,7 @@ static s32 e1000_reset_hw_82542(struct e1000_hw *hw)
 {
        struct e1000_bus_info *bus = &hw->bus;
        s32 ret_val = E1000_SUCCESS;
-       u32 ctrl, icr;
+       u32 ctrl;
 
        DEBUGFUNC("e1000_reset_hw_82542");
 
@@ -222,7 +222,7 @@ static s32 e1000_reset_hw_82542(struct e1000_hw *hw)
        msec_delay(2);
 
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
-       icr = E1000_READ_REG(hw, E1000_ICR);
+       E1000_READ_REG(hw, E1000_ICR);
 
        if (hw->revision_id == E1000_REVISION_2) {
                if (bus->pci_cmd_word & CMD_MEM_WRT_INVALIDATE)
index 069f40a..25ee873 100644 (file)
@@ -897,7 +897,7 @@ static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw)
  **/
 static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
 {
-       u32 ctrl, icr;
+       u32 ctrl;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_reset_hw_82543");
@@ -939,7 +939,7 @@ static s32 e1000_reset_hw_82543(struct e1000_hw *hw)
 
        /* Masking off and clearing any pending interrupts */
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
-       icr = E1000_READ_REG(hw, E1000_ICR);
+       E1000_READ_REG(hw, E1000_ICR);
 
        return ret_val;
 }
index 2eeef7d..0630951 100644 (file)
@@ -82,6 +82,10 @@ static s32  e1000_get_hw_semaphore_82573(struct e1000_hw *hw);
 static void e1000_put_hw_semaphore_82573(struct e1000_hw *hw);
 static s32  e1000_get_hw_semaphore_82574(struct e1000_hw *hw);
 static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw);
+static s32  e1000_set_d0_lplu_state_82574(struct e1000_hw *hw,
+                                          bool active);
+static s32  e1000_set_d3_lplu_state_82574(struct e1000_hw *hw,
+                                          bool active);
 static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
 static s32  e1000_write_nvm_eewr_82571(struct e1000_hw *hw, u16 offset,
                                        u16 words, u16 *data);
@@ -128,16 +132,6 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
                phy->ops.write_reg          = e1000_write_phy_reg_igp;
                phy->ops.acquire            = e1000_get_hw_semaphore_82571;
                phy->ops.release            = e1000_put_hw_semaphore_82571;
-
-               /* This uses above function pointers */
-               ret_val = e1000_get_phy_id_82571(hw);
-
-               /* Verify PHY ID */
-               if (phy->id != IGP01E1000_I_PHY_ID) {
-                       ret_val = -E1000_ERR_PHY;
-                       DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
-                       goto out;
-               }
                break;
        case e1000_82573:
                phy->type                   = e1000_phy_m88;
@@ -151,16 +145,6 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
                phy->ops.write_reg          = e1000_write_phy_reg_m88;
                phy->ops.acquire            = e1000_get_hw_semaphore_82571;
                phy->ops.release            = e1000_put_hw_semaphore_82571;
-
-               /* This uses above function pointers */
-               ret_val = e1000_get_phy_id_82571(hw);
-
-               /* Verify PHY ID */
-               if (phy->id != M88E1111_I_PHY_ID) {
-                       ret_val = -E1000_ERR_PHY;
-                       DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
-                       goto out;
-               }
                break;
        case e1000_82574:
        case e1000_82583:
@@ -175,22 +159,46 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
                phy->ops.write_reg          = e1000_write_phy_reg_bm2;
                phy->ops.acquire            = e1000_get_hw_semaphore_82574;
                phy->ops.release            = e1000_put_hw_semaphore_82574;
+               phy->ops.set_d0_lplu_state  = e1000_set_d0_lplu_state_82574;
+               phy->ops.set_d3_lplu_state  = e1000_set_d3_lplu_state_82574;
+               break;
+       default:
+               ret_val = -E1000_ERR_PHY;
+               goto out;
+               break;
+       }
+
+       /* This can only be done after all function pointers are setup. */
+       ret_val = e1000_get_phy_id_82571(hw);
+       if (ret_val) {
+               DEBUGOUT("Error getting PHY ID\n");
+               goto out;
+       }
 
-               /* This uses above function pointers */
-               ret_val = e1000_get_phy_id_82571(hw);
-               /* Verify PHY ID */
-               if (phy->id != BME1000_E_PHY_ID_R2) {
+       /* Verify phy id */
+       switch (hw->mac.type) {
+       case e1000_82571:
+       case e1000_82572:
+               if (phy->id != IGP01E1000_I_PHY_ID)
+                       ret_val = -E1000_ERR_PHY;
+               break;
+       case e1000_82573:
+               if (phy->id != M88E1111_I_PHY_ID)
+                       ret_val = -E1000_ERR_PHY;
+               break;
+       case e1000_82574:
+       case e1000_82583:
+               if (phy->id != BME1000_E_PHY_ID_R2)
                        ret_val = -E1000_ERR_PHY;
-                       DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
-                       goto out;
-               }
                break;
        default:
                ret_val = -E1000_ERR_PHY;
-               goto out;
                break;
        }
 
+       if (ret_val)
+               DEBUGOUT1("PHY ID unknown: type = 0x%08x\n", phy->id);
+
 out:
        return ret_val;
 }
@@ -353,8 +361,6 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
        mac->ops.read_mac_addr = e1000_read_mac_addr_82571;
        /* ID LED init */
        mac->ops.id_led_init = e1000_id_led_init_generic;
-       /* blink LED */
-       mac->ops.blink_led = e1000_blink_led_generic;
        /* setup LED */
        mac->ops.setup_led = e1000_setup_led_generic;
        /* cleanup LED */
@@ -370,6 +376,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
                mac->ops.set_lan_id = e1000_set_lan_id_single_port;
                mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
                mac->ops.led_on = e1000_led_on_generic;
+               mac->ops.blink_led = e1000_blink_led_generic;
 
                /* FWSM register */
                mac->has_fwsm = TRUE;
@@ -390,6 +397,7 @@ static s32 e1000_init_mac_params_82571(struct e1000_hw *hw)
        default:
                mac->ops.check_mng_mode = e1000_check_mng_mode_generic;
                mac->ops.led_on = e1000_led_on_generic;
+               mac->ops.blink_led = e1000_blink_led_generic;
 
                /* FWSM register */
                mac->has_fwsm = TRUE;
@@ -686,6 +694,62 @@ static void e1000_put_hw_semaphore_82574(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_set_d0_lplu_state_82574 - Set Low Power Linkup D0 state
+ *  @hw: pointer to the HW structure
+ *  @active: TRUE to enable LPLU, FALSE to disable
+ *
+ *  Sets the LPLU D0 state according to the active flag.
+ *  LPLU will not be activated unless the
+ *  device autonegotiation advertisement meets standards of
+ *  either 10 or 10/100 or 10/100/1000 at all duplexes.
+ *  This is a function pointer entry point only called by
+ *  PHY setup routines.
+ **/
+static s32 e1000_set_d0_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+       u16 data = E1000_READ_REG(hw, E1000_POEMB);
+
+       DEBUGFUNC("e1000_set_d0_lplu_state_82574");
+
+       if (active)
+               data |= E1000_PHY_CTRL_D0A_LPLU;
+       else
+               data &= ~E1000_PHY_CTRL_D0A_LPLU;
+
+       E1000_WRITE_REG(hw, E1000_POEMB, data);
+       return E1000_SUCCESS;
+}
+
+/**
+ *  e1000_set_d3_lplu_state_82574 - Sets low power link up state for D3
+ *  @hw: pointer to the HW structure
+ *  @active: boolean used to enable/disable lplu
+ *
+ *  The low power link up (lplu) state is set to the power management level D3
+ *  when active is TRUE, else clear lplu for D3. LPLU
+ *  is used during Dx states where the power conservation is most important.
+ *  During driver activity, SmartSpeed should be enabled so performance is
+ *  maintained.
+ **/
+static s32 e1000_set_d3_lplu_state_82574(struct e1000_hw *hw, bool active)
+{
+       u16 data = E1000_READ_REG(hw, E1000_POEMB);
+
+       DEBUGFUNC("e1000_set_d3_lplu_state_82574");
+
+       if (!active) {
+               data &= ~E1000_PHY_CTRL_NOND0A_LPLU;
+       } else if ((hw->phy.autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
+                  (hw->phy.autoneg_advertised == E1000_ALL_NOT_GIG) ||
+                  (hw->phy.autoneg_advertised == E1000_ALL_10_SPEED)) {
+               data |= E1000_PHY_CTRL_NOND0A_LPLU;
+       }
+
+       E1000_WRITE_REG(hw, E1000_POEMB, data);
+       return E1000_SUCCESS;
+}
+
+/**
  *  e1000_acquire_nvm_82571 - Request for access to the EEPROM
  *  @hw: pointer to the HW structure
  *
@@ -1032,7 +1096,7 @@ out:
  **/
 static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 {
-       u32 ctrl, ctrl_ext, icr;
+       u32 ctrl, ctrl_ext;
        s32 ret_val;
 
        DEBUGFUNC("e1000_reset_hw_82571");
@@ -1118,7 +1182,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
 
        /* Clear any pending interrupt events. */
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
-       icr = E1000_READ_REG(hw, E1000_ICR);
+       E1000_READ_REG(hw, E1000_ICR);
 
        if (hw->mac.type == e1000_82571) {
                /* Install any alternate MAC address into RAR0 */
@@ -1329,7 +1393,7 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
                 * apply workaround for hardware errata documented in errata
                 * docs Fixes issue where some error prone or unreliable PCIe
                 * completions are occurring, particularly with ASPM enabled.
-                * Without fix, issue can cause tx timeouts.
+                * Without fix, issue can cause Tx timeouts.
                 */
                reg = E1000_READ_REG(hw, E1000_GCR2);
                reg |= 1;
@@ -1460,7 +1524,7 @@ bool e1000_check_phy_82574(struct e1000_hw *hw)
                                       &receive_errors);
        if (ret_val)
                goto out;
-       if (receive_errors == E1000_RECEIVE_ERROR_MAX)  {
+       if (receive_errors == E1000_RECEIVE_ERROR_MAX) {
                ret_val = hw->phy.ops.read_reg(hw, E1000_BASE1000T_STATUS,
                                               &status_1kbt);
                if (ret_val)
@@ -1503,6 +1567,7 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
        default:
                break;
        }
+
        return e1000_setup_link_generic(hw);
 }
 
@@ -1638,7 +1703,7 @@ static s32 e1000_check_for_serdes_link_82571(struct e1000_hw *hw)
                         * auto-negotiation in the TXCW register and disable
                         * forced link in the Device Control register in an
                         * attempt to auto-negotiate with our link partner.
-                        * If the partner code word is null, stop forcing 
+                        * If the partner code word is null, stop forcing
                         * and restart auto negotiation.
                         */
                        if ((rxcw & E1000_RXCW_C) || !(rxcw & E1000_RXCW_CW))  {
index 9334901..3dae75d 100644 (file)
@@ -112,7 +112,6 @@ out:
        return ret_val;
 }
 
-
 /**
  *  e1000_set_mac_type - Sets MAC type
  *  @hw: pointer to the HW structure
@@ -254,7 +253,6 @@ s32 e1000_set_mac_type(struct e1000_hw *hw)
        case E1000_DEV_ID_ICH10_D_BM_LM:
        case E1000_DEV_ID_ICH10_D_BM_LF:
        case E1000_DEV_ID_ICH10_D_BM_V:
-       case E1000_DEV_ID_ICH10_HANKSVILLE:
                mac->type = e1000_ich10lan;
                break;
        case E1000_DEV_ID_PCH_D_HV_DM:
index 24fe608..eb2072e 100644 (file)
@@ -75,8 +75,8 @@
 #define E1000_WUFC_FLX3 0x00080000 /* Flexible Filter 3 Enable */
 #define E1000_WUFC_FLX4 0x00100000 /* Flexible Filter 4 Enable */
 #define E1000_WUFC_FLX5 0x00200000 /* Flexible Filter 5 Enable */
-#define E1000_WUFC_FLX6  0x00400000 /* Flexible Filter 6 Enable */
-#define E1000_WUFC_FLX7  0x00800000 /* Flexible Filter 7 Enable */
+#define E1000_WUFC_FLX6 0x00400000 /* Flexible Filter 6 Enable */
+#define E1000_WUFC_FLX7 0x00800000 /* Flexible Filter 7 Enable */
 #define E1000_WUFC_ALL_FILTERS_PHY_4 0x0000F0FF /*Mask for all wakeup filters*/
 #define E1000_WUFC_FLX_OFFSET_PHY 12 /* Offset to the Flexible Filters bits */
 #define E1000_WUFC_FLX_FILTERS_PHY_4 0x0000F000 /*Mask for 4 flexible filters*/
 #define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
 #define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
 #define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
+#define E1000_CTRL_EXT_LINK_MODE_OFFSET 22  /* Offset of the link mode field
+                                             * in Ctrl Ext register */
 #define E1000_CTRL_EXT_LINK_MODE_82580_MASK 0x01C00000 /*82580 bit 24:22*/
 #define E1000_CTRL_EXT_LINK_MODE_1000BASE_KX  0x00400000
 #define E1000_CTRL_EXT_LINK_MODE_GMII 0x00000000
 #define E1000_I2CCMD_READY            0x20000000
 #define E1000_I2CCMD_INTERRUPT_ENA    0x40000000
 #define E1000_I2CCMD_ERROR            0x80000000
+#define E1000_I2CCMD_SFP_DATA_ADDR(a) (0x0000 + (a))
+#define E1000_I2CCMD_SFP_DIAG_ADDR(a) (0x0100 + (a))
 #define E1000_MAX_SGMII_PHY_REG_ADDR  255
 #define E1000_I2CCMD_PHY_TIMEOUT      200
 
 #define E1000_RXD_SPC_CFI_MASK  0x1000  /* CFI is bit 12 */
 #define E1000_RXD_SPC_CFI_SHIFT 12
 
+#define E1000_RXDEXT_STATERR_LB    0x00040000
 #define E1000_RXDEXT_STATERR_CE    0x01000000
 #define E1000_RXDEXT_STATERR_SE    0x02000000
 #define E1000_RXDEXT_STATERR_SEQ   0x04000000
 #define E1000_RCTL_LBM_TCVR       0x000000C0    /* tcvr loopback mode */
 #define E1000_RCTL_DTYP_MASK      0x00000C00    /* Descriptor type mask */
 #define E1000_RCTL_DTYP_PS        0x00000400    /* Packet Split descriptor */
-#define E1000_RCTL_RDMTS_HALF     0x00000000    /* rx desc min thresh size */
-#define E1000_RCTL_RDMTS_QUAT     0x00000100    /* rx desc min thresh size */
-#define E1000_RCTL_RDMTS_EIGTH    0x00000200    /* rx desc min thresh size */
+#define E1000_RCTL_RDMTS_HALF     0x00000000    /* Rx desc min thresh size */
+#define E1000_RCTL_RDMTS_QUAT     0x00000100    /* Rx desc min thresh size */
+#define E1000_RCTL_RDMTS_EIGTH    0x00000200    /* Rx desc min thresh size */
 #define E1000_RCTL_MO_SHIFT       12            /* multicast offset shift */
 #define E1000_RCTL_MO_0           0x00000000    /* multicast offset 11:0 */
 #define E1000_RCTL_MO_1           0x00001000    /* multicast offset 12:1 */
 #define E1000_RCTL_MDR            0x00004000    /* multicast desc ring 0 */
 #define E1000_RCTL_BAM            0x00008000    /* broadcast enable */
 /* these buffer sizes are valid if E1000_RCTL_BSEX is 0 */
-#define E1000_RCTL_SZ_2048        0x00000000    /* rx buffer size 2048 */
-#define E1000_RCTL_SZ_1024        0x00010000    /* rx buffer size 1024 */
-#define E1000_RCTL_SZ_512         0x00020000    /* rx buffer size 512 */
-#define E1000_RCTL_SZ_256         0x00030000    /* rx buffer size 256 */
+#define E1000_RCTL_SZ_2048        0x00000000    /* Rx buffer size 2048 */
+#define E1000_RCTL_SZ_1024        0x00010000    /* Rx buffer size 1024 */
+#define E1000_RCTL_SZ_512         0x00020000    /* Rx buffer size 512 */
+#define E1000_RCTL_SZ_256         0x00030000    /* Rx buffer size 256 */
 /* these buffer sizes are valid if E1000_RCTL_BSEX is 1 */
-#define E1000_RCTL_SZ_16384       0x00010000    /* rx buffer size 16384 */
-#define E1000_RCTL_SZ_8192        0x00020000    /* rx buffer size 8192 */
-#define E1000_RCTL_SZ_4096        0x00030000    /* rx buffer size 4096 */
+#define E1000_RCTL_SZ_16384       0x00010000    /* Rx buffer size 16384 */
+#define E1000_RCTL_SZ_8192        0x00020000    /* Rx buffer size 8192 */
+#define E1000_RCTL_SZ_4096        0x00030000    /* Rx buffer size 4096 */
 #define E1000_RCTL_VFE            0x00040000    /* vlan filter enable */
 #define E1000_RCTL_CFIEN          0x00080000    /* canonical form enable */
 #define E1000_RCTL_CFI            0x00100000    /* canonical form indicator */
 
 /* Transmit Control */
 #define E1000_TCTL_RST    0x00000001    /* software reset */
-#define E1000_TCTL_EN     0x00000002    /* enable tx */
+#define E1000_TCTL_EN     0x00000002    /* enable Tx */
 #define E1000_TCTL_BCE    0x00000004    /* busy check enable */
 #define E1000_TCTL_PSP    0x00000008    /* pad short packets */
 #define E1000_TCTL_CT     0x00000ff0    /* collision threshold */
 #define E1000_ICR_TXDW          0x00000001 /* Transmit desc written back */
 #define E1000_ICR_TXQE          0x00000002 /* Transmit Queue empty */
 #define E1000_ICR_LSC           0x00000004 /* Link Status Change */
-#define E1000_ICR_RXSEQ         0x00000008 /* rx sequence error */
-#define E1000_ICR_RXDMT0        0x00000010 /* rx desc min. threshold (0) */
-#define E1000_ICR_RXO           0x00000040 /* rx overrun */
-#define E1000_ICR_RXT0          0x00000080 /* rx timer intr (ring 0) */
+#define E1000_ICR_RXSEQ         0x00000008 /* Rx sequence error */
+#define E1000_ICR_RXDMT0        0x00000010 /* Rx desc min. threshold (0) */
+#define E1000_ICR_RXO           0x00000040 /* Rx overrun */
+#define E1000_ICR_RXT0          0x00000080 /* Rx timer intr (ring 0) */
 #define E1000_ICR_VMMB          0x00000100 /* VM MB event */
 #define E1000_ICR_MDAC          0x00000200 /* MDIO access complete */
 #define E1000_ICR_RXCFG         0x00000400 /* Rx /c/ ordered set */
 /* PBA ECC Register */
 #define E1000_PBA_ECC_COUNTER_MASK  0xFFF00000 /* ECC counter mask */
 #define E1000_PBA_ECC_COUNTER_SHIFT 20         /* ECC counter shift value */
-#define E1000_PBA_ECC_CORR_EN      0x00000001 /* Enable ECC error correction */
-#define E1000_PBA_ECC_STAT_CLR      0x00000002 /* Clear ECC error counter */
-#define E1000_PBA_ECC_INT_EN     0x00000004 /* Enable ICR bit 5 on ECC error */
+#define E1000_PBA_ECC_CORR_EN   0x00000001 /* Enable ECC error correction */
+#define E1000_PBA_ECC_STAT_CLR  0x00000002 /* Clear ECC error counter */
+#define E1000_PBA_ECC_INT_EN    0x00000004 /* Enable ICR bit 5 on ECC error */
 
 /*
  * This defines the bits that are set in the Interrupt Mask
 #define E1000_IMS_TXQE      E1000_ICR_TXQE      /* Transmit Queue empty */
 #define E1000_IMS_LSC       E1000_ICR_LSC       /* Link Status Change */
 #define E1000_IMS_VMMB      E1000_ICR_VMMB      /* Mail box activity */
-#define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* rx sequence error */
-#define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
-#define E1000_IMS_RXO       E1000_ICR_RXO       /* rx overrun */
-#define E1000_IMS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
+#define E1000_IMS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */
+#define E1000_IMS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
+#define E1000_IMS_RXO       E1000_ICR_RXO       /* Rx overrun */
+#define E1000_IMS_RXT0      E1000_ICR_RXT0      /* Rx timer intr */
 #define E1000_IMS_MDAC      E1000_ICR_MDAC      /* MDIO access complete */
 #define E1000_IMS_RXCFG     E1000_ICR_RXCFG     /* Rx /c/ ordered set */
 #define E1000_IMS_GPI_EN0   E1000_ICR_GPI_EN0   /* GP Int 0 */
 #define E1000_IMS_OTHER         E1000_ICR_OTHER /* Other Interrupts */
 #define E1000_IMS_FER           E1000_ICR_FER /* Fatal Error */
 
-/* Interrupt Mask Clear */
-#define E1000_IMC_RXSEQ                E1000_ICR_RXSEQ /* rx sequence error */
-
 /* Interrupt Cause Set */
 #define E1000_ICS_TXDW      E1000_ICR_TXDW      /* Tx desc written back */
 #define E1000_ICS_TXQE      E1000_ICR_TXQE      /* Transmit Queue empty */
 #define E1000_ICS_LSC       E1000_ICR_LSC       /* Link Status Change */
-#define E1000_ICS_RXSEQ     E1000_ICR_RXSEQ     /* rx sequence error */
-#define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* rx desc min. threshold */
-#define E1000_ICS_RXO       E1000_ICR_RXO       /* rx overrun */
-#define E1000_ICS_RXT0      E1000_ICR_RXT0      /* rx timer intr */
+#define E1000_ICS_RXSEQ     E1000_ICR_RXSEQ     /* Rx sequence error */
+#define E1000_ICS_RXDMT0    E1000_ICR_RXDMT0    /* Rx desc min. threshold */
+#define E1000_ICS_RXO       E1000_ICR_RXO       /* Rx overrun */
+#define E1000_ICS_RXT0      E1000_ICR_RXT0      /* Rx timer intr */
 #define E1000_ICS_MDAC      E1000_ICR_MDAC      /* MDIO access complete */
 #define E1000_ICS_RXCFG     E1000_ICR_RXCFG     /* Rx /c/ ordered set */
 #define E1000_ICS_GPI_EN0   E1000_ICR_GPI_EN0   /* GP Int 0 */
 #define E1000_ICS_EPRST     E1000_ICR_EPRST
 
 /* Transmit Descriptor Control */
-#define E1000_TXDCTL_PTHRESH 0x0000003F /* TXDCTL Prefetch Threshold */
-#define E1000_TXDCTL_HTHRESH 0x00003F00 /* TXDCTL Host Threshold */
-#define E1000_TXDCTL_WTHRESH 0x003F0000 /* TXDCTL Writeback Threshold */
-#define E1000_TXDCTL_GRAN    0x01000000 /* TXDCTL Granularity */
-#define E1000_TXDCTL_LWTHRESH 0xFE000000 /* TXDCTL Low Threshold */
+#define E1000_TXDCTL_PTHRESH    0x0000003F /* TXDCTL Prefetch Threshold */
+#define E1000_TXDCTL_HTHRESH    0x00003F00 /* TXDCTL Host Threshold */
+#define E1000_TXDCTL_WTHRESH    0x003F0000 /* TXDCTL Writeback Threshold */
+#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_MAX_TX_DESC_PREFETCH 0x0100001F /* GRAN=1, PTHRESH=31 */
 /* Enable the counting of descriptors still to be processed. */
 #define E1000_RAH_AV  0x80000000        /* Receive descriptor valid */
 #define E1000_RAL_MAC_ADDR_LEN 4
 #define E1000_RAH_MAC_ADDR_LEN 2
-#define E1000_RAH_POOL_MASK 0x03FC0000
-#define E1000_RAH_POOL_1 0x00040000
+#define E1000_RAH_POOL_MASK     0x03FC0000
+#define E1000_RAH_POOL_SHIFT    18
+#define E1000_RAH_POOL_1        0x00040000
 
 /* Error Codes */
 #define E1000_SUCCESS      0
 #define E1000_RXCW_SYNCH      0x40000000        /* Receive config synch */
 #define E1000_RXCW_ANC        0x80000000        /* Auto-neg complete */
 
-#define E1000_TSYNCTXCTL_VALID    0x00000001 /* tx timestamp valid */
-#define E1000_TSYNCTXCTL_ENABLED  0x00000010 /* enable tx timestampping */
+#define E1000_TSYNCTXCTL_VALID    0x00000001 /* Tx timestamp valid */
+#define E1000_TSYNCTXCTL_ENABLED  0x00000010 /* enable Tx timestamping */
 
-#define E1000_TSYNCRXCTL_VALID      0x00000001 /* rx timestamp valid */
-#define E1000_TSYNCRXCTL_TYPE_MASK  0x0000000E /* rx type mask */
+#define E1000_TSYNCRXCTL_VALID      0x00000001 /* Rx timestamp valid */
+#define E1000_TSYNCRXCTL_TYPE_MASK  0x0000000E /* Rx type mask */
 #define E1000_TSYNCRXCTL_TYPE_L2_V2       0x00
 #define E1000_TSYNCRXCTL_TYPE_L4_V1       0x02
 #define E1000_TSYNCRXCTL_TYPE_L2_L4_V2    0x04
 #define E1000_TSYNCRXCTL_TYPE_ALL         0x08
 #define E1000_TSYNCRXCTL_TYPE_EVENT_V2    0x0A
-#define E1000_TSYNCRXCTL_ENABLED    0x00000010 /* enable rx timestampping */
+#define E1000_TSYNCRXCTL_ENABLED    0x00000010 /* enable Rx timestamping */
 
 #define E1000_TSYNCRXCFG_PTP_V1_CTRLT_MASK   0x000000FF
 #define E1000_TSYNCRXCFG_PTP_V1_SYNC_MESSAGE       0x00
 #define E1000_EECD_GNT       0x00000080 /* NVM Access Grant */
 #define E1000_EECD_PRES      0x00000100 /* NVM Present */
 #define E1000_EECD_SIZE      0x00000200 /* NVM Size (0=64 word 1=256 word) */
+#define E1000_EECD_BLOCKED   0x00008000 /* Bit banging access blocked flag */
+#define E1000_EECD_ABORT     0x00010000 /* NVM operation aborted flag */
+#define E1000_EECD_TIMEOUT   0x00020000 /* NVM read operation timeout flag */
+#define E1000_EECD_ERROR_CLR 0x00040000 /* NVM error status clear bit */
 /* NVM Addressing bits based on type 0=small, 1=large */
 #define E1000_EECD_ADDR_BITS 0x00000400
 #define E1000_EECD_TYPE      0x00002000 /* NVM Type (1-SPI, 0-Microwire) */
 #define NVM_FLASH_VERSION          0x0032
 #define NVM_ALT_MAC_ADDR_PTR       0x0037
 #define NVM_CHECKSUM_REG           0x003F
+#define NVM_COMPATIBILITY_REG_3    0x0003
+#define NVM_COMPATIBILITY_BIT_MASK 0x8000
 
 #define E1000_NVM_CFG_DONE_PORT_0  0x040000 /* MNG config cycle done */
 #define E1000_NVM_CFG_DONE_PORT_1  0x080000 /* ...for second port */
 /* Mask bits for fields in Word 0x24 of the NVM */
 #define NVM_WORD24_COM_MDIO         0x0008 /* MDIO interface shared */
 #define NVM_WORD24_EXT_MDIO         0x0004 /* MDIO accesses routed external */
+#define NVM_WORD24_LNK_MODE_OFFSET         8 /* Offset of Link Mode bits
+                                              * for 82575 up to Kawela */
+#define NVM_WORD24_82580_LNK_MODE_OFFSET   4 /* Offset of Link Mode bits
+                                              * Link Mode bits for 82580 up */
+
 
 /* Mask bits for fields in Word 0x0f of the NVM */
 #define NVM_WORD0F_PAUSE_MASK       0x3000
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X    0x0100
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_2X    0x0200
 #define M88E1000_EPSCR_SLAVE_DOWNSHIFT_3X    0x0300
-#define M88E1000_EPSCR_TX_CLK_2_5     0x0060 /* 2.5 MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_25      0x0070 /* 25  MHz TX_CLK */
-#define M88E1000_EPSCR_TX_CLK_0       0x0000 /* NO  TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_2_5       0x0060 /* 2.5 MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_25        0x0070 /* 25  MHz TX_CLK */
+#define M88E1000_EPSCR_TX_CLK_0         0x0000 /* NO  TX_CLK */
+
+/* M88E1111 Specific Registers */
+#define M88E1111_PHY_PAGE_SELECT1       0x16  /* for registers 0-28 */
+#define M88E1111_PHY_PAGE_SELECT2       0x1D  /* for registers 30-31 */
+
+/* M88E1111 page select register mask */
+#define M88E1111_PHY_PAGE_SELECT_MASK1  0xFF
+#define M88E1111_PHY_PAGE_SELECT_MASK2  0x3F
 
 
 /* M88EC018 Rev 2 specific DownShift settings */
 #define E1000_GEN_CTL_ADDRESS_SHIFT     8
 #define E1000_GEN_POLL_TIMEOUT          640
 
-
 /* DMA Coalescing register fields */
 #define E1000_DMACR_DMACWT_MASK         0x00003FFF /* DMA Coalescing
                                                     * Watchdog Timer */
-#define E1000_DMACR_DMACTHR_MASK        0x00FF0000 /* DMA Coalescing Receive
+#define E1000_DMACR_DMACTHR_MASK        0x00FF0000 /* DMA Coalescing Rx
                                                     * Threshold */
 #define E1000_DMACR_DMACTHR_SHIFT       16
 #define E1000_DMACR_DMAC_LX_MASK        0x30000000 /* Lx when no PCIe
 
 #define E1000_DMCTLX_TTLX_MASK          0x00000FFF /* Time to LX request */
 
-#define E1000_DMCRTRH_UTRESH_MASK       0x0007FFFF /* Receive Traffic Rate
+#define E1000_DMCRTRH_UTRESH_MASK       0x0007FFFF /* Rx Traffic Rate
                                                     * Threshold */
-#define E1000_DMCRTRH_LRPRCW            0x80000000 /* Rcv packet rate in
+#define E1000_DMCRTRH_LRPRCW            0x80000000 /* Rx packet rate in
                                                     * current window */
 
-#define E1000_DMCCNT_CCOUNT_MASK        0x01FFFFFF /* DMA Coal Rcv Traffic
+#define E1000_DMCCNT_CCOUNT_MASK        0x01FFFFFF /* DMA Coal Rx Traffic
                                                     * Current Cnt */
 
-#define E1000_FCRTC_RTH_COAL_MASK       0x0003FFF0 /* Flow ctrl Rcv Threshold
+#define E1000_FCRTC_RTH_COAL_MASK       0x0003FFF0 /* Flow ctrl Rx Threshold
                                                     * High val */
 #define E1000_FCRTC_RTH_COAL_SHIFT      4
 #define E1000_PCIEMISC_LX_DECISION      0x00000080 /* Lx power decision based
                                                       on DMA coal */
 
-
 #endif /* _E1000_DEFINES_H_ */
index 14daf0a..8595667 100644 (file)
@@ -123,7 +123,6 @@ struct e1000_hw;
 #define E1000_DEV_ID_ICH10_R_BM_LM            0x10CC
 #define E1000_DEV_ID_ICH10_R_BM_LF            0x10CD
 #define E1000_DEV_ID_ICH10_R_BM_V             0x10CE
-#define E1000_DEV_ID_ICH10_HANKSVILLE         0xF0FE
 #define E1000_DEV_ID_ICH10_D_BM_LM            0x10DE
 #define E1000_DEV_ID_ICH10_D_BM_LF            0x10DF
 #define E1000_DEV_ID_ICH10_D_BM_V             0x1525
@@ -615,6 +614,21 @@ struct e1000_mac_operations {
        s32  (*wait_autoneg)(struct e1000_hw *);
 };
 
+/*
+ * When to use various PHY register access functions:
+ *
+ *                 Func   Caller
+ *   Function      Does   Does    When to use
+ *   ~~~~~~~~~~~~  ~~~~~  ~~~~~~  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *   X_reg         L,P,A  n/a     for simple PHY reg accesses
+ *   X_reg_locked  P,A    L       for multiple accesses of different regs
+ *                                on different pages
+ *   X_reg_page    A      L,P     for multiple accesses of different regs
+ *                                on the same page
+ *
+ * Where X=[read|write], L=locking, P=sets page, A=register access
+ *
+ */
 struct e1000_phy_operations {
        s32  (*init_params)(struct e1000_hw *);
        s32  (*acquire)(struct e1000_hw *);
@@ -626,14 +640,17 @@ struct e1000_phy_operations {
        s32  (*get_cfg_done)(struct e1000_hw *hw);
        s32  (*get_cable_length)(struct e1000_hw *);
        s32  (*get_info)(struct e1000_hw *);
+       s32  (*set_page)(struct e1000_hw *, u16);
        s32  (*read_reg)(struct e1000_hw *, u32, u16 *);
        s32  (*read_reg_locked)(struct e1000_hw *, u32, u16 *);
+       s32  (*read_reg_page)(struct e1000_hw *, u32, u16 *);
        void (*release)(struct e1000_hw *);
        s32  (*reset)(struct e1000_hw *);
        s32  (*set_d0_lplu_state)(struct e1000_hw *, bool);
        s32  (*set_d3_lplu_state)(struct e1000_hw *, bool);
        s32  (*write_reg)(struct e1000_hw *, u32, u16);
        s32  (*write_reg_locked)(struct e1000_hw *, u32, u16);
+       s32  (*write_reg_page)(struct e1000_hw *, u32, u16);
        void (*power_up)(struct e1000_hw *);
        void (*power_down)(struct e1000_hw *);
 };
@@ -652,8 +669,8 @@ struct e1000_nvm_operations {
 
 struct e1000_mac_info {
        struct e1000_mac_operations ops;
-       u8 addr[6];
-       u8 perm_addr[6];
+       u8 addr[ETH_ADDR_LEN];
+       u8 perm_addr[ETH_ADDR_LEN];
 
        enum e1000_mac_type type;
 
@@ -797,7 +814,7 @@ struct e1000_shadow_ram {
        bool modified;
 };
 
-#define E1000_SHADOW_RAM_WORDS         2048
+#define E1000_SHADOW_RAM_WORDS  2048
 
 struct e1000_dev_spec_ich8lan {
        bool kmrn_lock_loss_workaround_enabled;
@@ -821,14 +838,14 @@ struct e1000_hw {
        struct e1000_host_mng_dhcp_cookie mng_cookie;
 
        union {
-               struct e1000_dev_spec_82541     _82541;
+               struct e1000_dev_spec_82541 _82541;
 #ifndef NO_82542_SUPPORT
-               struct e1000_dev_spec_82542     _82542;
+               struct e1000_dev_spec_82542 _82542;
 #endif
-               struct e1000_dev_spec_82543     _82543;
-               struct e1000_dev_spec_82571     _82571;
+               struct e1000_dev_spec_82543 _82543;
+               struct e1000_dev_spec_82571 _82571;
                struct e1000_dev_spec_80003es2lan _80003es2lan;
-               struct e1000_dev_spec_ich8lan   ich8lan;
+               struct e1000_dev_spec_ich8lan ich8lan;
        } dev_spec;
 
        u16 device_id;
@@ -851,6 +868,7 @@ void e1000_pci_clear_mwi(struct e1000_hw *hw);
 void e1000_pci_set_mwi(struct e1000_hw *hw);
 #endif
 s32  e1000_read_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
+s32  e1000_write_pcie_cap_reg(struct e1000_hw *hw, u32 reg, u16 *value);
 void e1000_read_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
 void e1000_write_pci_cfg(struct e1000_hw *hw, u32 reg, u16 *value);
 
index bf10e0d..5b7561c 100644 (file)
@@ -75,6 +75,9 @@ static void e1000_release_nvm_ich8lan(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
 static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
 static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
+static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw,
+                                              u8 *mc_addr_list,
+                                              u32 mc_addr_count);
 static s32  e1000_check_reset_block_ich8lan(struct e1000_hw *hw);
 static s32  e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw);
 static s32  e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
@@ -174,6 +177,21 @@ union ich8_hws_flash_regacc {
        u16 regval;
 };
 
+static void e1000_toggle_lanphypc_value_ich8lan(struct e1000_hw *hw)
+{
+       u32 ctrl;
+
+       DEBUGFUNC("e1000_toggle_lanphypc_value_ich8lan");
+
+       ctrl = E1000_READ_REG(hw, E1000_CTRL);
+       ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
+       ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+       usec_delay(10);
+       ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
+       E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+}
+
 /**
  *  e1000_init_phy_params_pchlan - Initialize PHY function pointers
  *  @hw: pointer to the HW structure
@@ -183,7 +201,7 @@ union ich8_hws_flash_regacc {
 static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
 {
        struct e1000_phy_info *phy = &hw->phy;
-       u32 ctrl, fwsm;
+       u32 fwsm;
        s32 ret_val = E1000_SUCCESS;
 
        DEBUGFUNC("e1000_init_phy_params_pchlan");
@@ -194,14 +212,17 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
        phy->ops.acquire              = e1000_acquire_swflag_ich8lan;
        phy->ops.check_reset_block    = e1000_check_reset_block_ich8lan;
        phy->ops.get_cfg_done         = e1000_get_cfg_done_ich8lan;
+       phy->ops.set_page             = e1000_set_page_igp;
        phy->ops.read_reg             = e1000_read_phy_reg_hv;
        phy->ops.read_reg_locked      = e1000_read_phy_reg_hv_locked;
+       phy->ops.read_reg_page        = e1000_read_phy_reg_page_hv;
        phy->ops.release              = e1000_release_swflag_ich8lan;
        phy->ops.reset                = e1000_phy_hw_reset_ich8lan;
        phy->ops.set_d0_lplu_state    = e1000_set_lplu_state_pchlan;
        phy->ops.set_d3_lplu_state    = e1000_set_lplu_state_pchlan;
        phy->ops.write_reg            = e1000_write_phy_reg_hv;
        phy->ops.write_reg_locked     = e1000_write_phy_reg_hv_locked;
+       phy->ops.write_reg_page       = e1000_write_phy_reg_page_hv;
        phy->ops.power_up             = e1000_power_up_phy_copper;
        phy->ops.power_down           = e1000_power_down_phy_copper_ich8lan;
        phy->autoneg_mask             = AUTONEG_ADVERTISE_SPEED_DEFAULT;
@@ -214,14 +235,8 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
         */
        fwsm = E1000_READ_REG(hw, E1000_FWSM);
        if (!(fwsm & E1000_ICH_FWSM_FW_VALID) &&
-           !(hw->phy.ops.check_reset_block(hw))) {
-               ctrl = E1000_READ_REG(hw, E1000_CTRL);
-               ctrl |=  E1000_CTRL_LANPHYPC_OVERRIDE;
-               ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
-               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
-               usec_delay(10);
-               ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
-               E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
+           !hw->phy.ops.check_reset_block(hw)) {
+               e1000_toggle_lanphypc_value_ich8lan(hw);
                msec_delay(50);
 
                /*
@@ -243,7 +258,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
                goto out;
 
        /* Ungate automatic PHY configuration on non-managed 82579 */
-       if ((hw->mac.type == e1000_pch2lan)  &&
+       if ((hw->mac.type == e1000_pch2lan) &&
            !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
                msec_delay(10);
                e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
@@ -471,7 +486,6 @@ out:
 static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_mac_info *mac = &hw->mac;
-       u16 pci_cfg;
 
        DEBUGFUNC("e1000_init_mac_params_ich8lan");
 
@@ -538,11 +552,11 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
        case e1000_pch2lan:
                mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES;
                mac->ops.rar_set = e1000_rar_set_pch2lan;
+               /* multicast address update for pch2 */
+               mac->ops.update_mc_addr_list =
+                       e1000_update_mc_addr_list_pch2lan;
                /* fall-through */
        case e1000_pchlan:
-               /* save PCH revision_id */
-               e1000_read_pci_cfg(hw, 0x2, &pci_cfg);
-               hw->revision_id = (u8)(pci_cfg &= 0x000F);
                /* check management mode */
                mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
                /* ID LED init */
@@ -649,16 +663,39 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
 
        mac->get_link_status = FALSE;
 
-       if (hw->phy.type == e1000_phy_82578) {
-               ret_val = e1000_link_stall_workaround_hv(hw);
-               if (ret_val)
-                       goto out;
-       }
-
-       if (hw->mac.type == e1000_pch2lan) {
+       switch (hw->mac.type) {
+       case e1000_pch2lan:
                ret_val = e1000_k1_workaround_lv(hw);
                if (ret_val)
                        goto out;
+               /* fall-thru */
+       case e1000_pchlan:
+               if (hw->phy.type == e1000_phy_82578) {
+                       ret_val = e1000_link_stall_workaround_hv(hw);
+                       if (ret_val)
+                               goto out;
+               }
+
+               /*
+                * Workaround for PCHx parts in half-duplex:
+                * Set the number of preambles removed from the packet
+                * when it is passed from the PHY to the MAC to prevent
+                * the MAC from misinterpreting the packet type.
+                */
+               if ((E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FD) !=
+                   E1000_STATUS_FD) {
+                       u16 preambles;
+
+                       hw->phy.ops.read_reg(hw, HV_KMRN_FIFO_CTRLSTA,
+                                            &preambles);
+                       preambles &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK;
+                       preambles |= (4 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT);
+                       hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA,
+                                             preambles);
+               }
+               break;
+       default:
+               break;
        }
 
        /*
@@ -738,6 +775,7 @@ void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
 static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_acquire_nvm_ich8lan");
+
        return E1000_SUCCESS;
 }
 
@@ -750,6 +788,7 @@ static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
 static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
 {
        DEBUGFUNC("e1000_release_nvm_ich8lan");
+
        return;
 }
 
@@ -805,6 +844,7 @@ static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
        }
 
 out:
+
        return ret_val;
 }
 
@@ -822,8 +862,13 @@ static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
        DEBUGFUNC("e1000_release_swflag_ich8lan");
 
        extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
-       extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
-       E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
+
+       if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) {
+               extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
+               E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
+       } else {
+               DEBUGOUT("Semaphore unexpectedly released by sw/fw/hw\n");
+       }
 
        return;
 }
@@ -927,6 +972,50 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
 }
 
 /**
+ *  e1000_update_mc_addr_list_pch2lan - Update Multicast addresses
+ *  @hw: pointer to the HW structure
+ *  @mc_addr_list: array of multicast addresses to program
+ *  @mc_addr_count: number of multicast addresses to program
+ *
+ *  Updates entire Multicast Table Array of the PCH2 MAC and PHY.
+ *  The caller must have a packed mc_addr_list of multicast addresses.
+ **/
+static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw,
+                                              u8 *mc_addr_list,
+                                              u32 mc_addr_count)
+{
+       u16 phy_reg = 0;
+       int i;
+       s32 ret_val;
+
+       DEBUGFUNC("e1000_update_mc_addr_list_pch2lan");
+
+       e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count);
+
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return;
+
+       ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+       if (ret_val)
+               goto release;
+
+       for (i = 0; i < hw->mac.mta_reg_count; i++) {
+               hw->phy.ops.write_reg_page(hw, BM_MTA(i),
+                                          (u16)(hw->mac.mta_shadow[i] &
+                                                0xFFFF));
+               hw->phy.ops.write_reg_page(hw, (BM_MTA(i) + 1),
+                                          (u16)((hw->mac.mta_shadow[i] >> 16) &
+                                                0xFFFF));
+       }
+
+       e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+release:
+       hw->phy.ops.release(hw);
+}
+
+/**
  *  e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
  *  @hw: pointer to the HW structure
  *
@@ -1307,20 +1396,6 @@ out:
 
 
 /**
- *  e1000_hv_phy_powerdown_workaround_ich8lan - Power down workaround on Sx
- *  @hw: pointer to the HW structure
- **/
-s32 e1000_hv_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
-{
-       DEBUGFUNC("e1000_hv_phy_powerdown_workaround_ich8lan");
-
-       if ((hw->phy.type != e1000_phy_82577) || (hw->revision_id > 2))
-               return E1000_SUCCESS;
-
-       return hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0444);
-}
-
-/**
  *  e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
  *  @hw:   pointer to the HW structure
  **/
@@ -1363,32 +1438,6 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
                        goto out;
        }
 
-       /* Hanksville M Phy init for IEEE. */
-       if ((hw->revision_id == 2) &&
-           (hw->phy.type == e1000_phy_82577) &&
-           ((hw->phy.revision == 2) || (hw->phy.revision == 3))) {
-               hw->phy.ops.write_reg(hw, 0x10, 0x8823);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0018);
-               hw->phy.ops.write_reg(hw, 0x10, 0x8824);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0016);
-               hw->phy.ops.write_reg(hw, 0x10, 0x8825);
-               hw->phy.ops.write_reg(hw, 0x11, 0x001A);
-               hw->phy.ops.write_reg(hw, 0x10, 0x888C);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0007);
-               hw->phy.ops.write_reg(hw, 0x10, 0x888D);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0007);
-               hw->phy.ops.write_reg(hw, 0x10, 0x888E);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0007);
-               hw->phy.ops.write_reg(hw, 0x10, 0x8827);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0001);
-               hw->phy.ops.write_reg(hw, 0x10, 0x8835);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0001);
-               hw->phy.ops.write_reg(hw, 0x10, 0x8834);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0001);
-               hw->phy.ops.write_reg(hw, 0x10, 0x8833);
-               hw->phy.ops.write_reg(hw, 0x11, 0x0002);
-       }
-
        if (((hw->phy.type == e1000_phy_82577) &&
             ((hw->phy.revision == 1) || (hw->phy.revision == 2))) ||
            ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) {
@@ -1398,26 +1447,12 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
                        goto out;
 
                /* Preamble tuning for SSC */
-               ret_val = hw->phy.ops.write_reg(hw, PHY_REG(770, 16), 0xA204);
+               ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204);
                if (ret_val)
                        goto out;
        }
 
        if (hw->phy.type == e1000_phy_82578) {
-               if (hw->revision_id < 3) {
-                       /* PHY config */
-                       ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x29,
-                                                       0x66C0);
-                       if (ret_val)
-                               goto out;
-
-                       /* PHY config */
-                       ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x1E,
-                                                       0xFFFF);
-                       if (ret_val)
-                               goto out;
-               }
-
                /*
                 * Return registers to default by doing a soft reset then
                 * writing 0x3140 to the control register.
@@ -1429,21 +1464,6 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
                }
        }
 
-       if ((hw->revision_id == 2) &&
-           (hw->phy.type == e1000_phy_82577) &&
-           ((hw->phy.revision == 2) || (hw->phy.revision == 3))) {
-               /*
-                * Workaround for OEM (GbE) not operating after reset -
-                * restart AN (twice)
-                */
-               ret_val = hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0400);
-               if (ret_val)
-                       goto out;
-               ret_val = hw->phy.ops.write_reg(hw, PHY_REG(768, 25), 0x0400);
-               if (ret_val)
-                       goto out;
-       }
-
        /* Select page 0 */
        ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
@@ -1467,13 +1487,11 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
        ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
                goto out;
-       ret_val = hw->phy.ops.read_reg_locked(hw,
-                                             PHY_REG(BM_PORT_CTRL_PAGE, 17),
+       ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG_REG,
                                              &phy_data);
        if (ret_val)
                goto release;
-       ret_val = hw->phy.ops.write_reg_locked(hw,
-                                              PHY_REG(BM_PORT_CTRL_PAGE, 17),
+       ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG_REG,
                                               phy_data & 0x00FF);
 release:
        hw->phy.ops.release(hw);
@@ -1488,19 +1506,38 @@ out:
 void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
 {
        u32 mac_reg;
-       u16 i;
+       u16 i, phy_reg = 0;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_copy_rx_addrs_to_phy_ich8lan");
 
+       ret_val = hw->phy.ops.acquire(hw);
+       if (ret_val)
+               return;
+       ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+       if (ret_val)
+               goto release;
+
        /* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */
        for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
                mac_reg = E1000_READ_REG(hw, E1000_RAL(i));
-               hw->phy.ops.write_reg(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
-               hw->phy.ops.write_reg(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
+               hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
+                                          (u16)(mac_reg & 0xFFFF));
+               hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
+                                          (u16)((mac_reg >> 16) & 0xFFFF));
+
                mac_reg = E1000_READ_REG(hw, E1000_RAH(i));
-               hw->phy.ops.write_reg(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
-               hw->phy.ops.write_reg(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
+               hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
+                                          (u16)(mac_reg & 0xFFFF));
+               hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
+                                          (u16)((mac_reg & E1000_RAH_AV)
+                                                >> 16));
        }
+
+       e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+
+release:
+       hw->phy.ops.release(hw);
 }
 
 static u32 e1000_calc_rx_da_crc(u8 mac[])
@@ -1536,7 +1573,8 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
 
        DEBUGFUNC("e1000_lv_jumbo_workaround_ich8lan");
 
-       if (hw->mac.type != e1000_pch2lan)
+       if ((hw->mac.type != e1000_pch2lan) &&
+           (hw->phy.type != e1000_phy_82579))
                goto out;
 
        /* disable Rx path while enabling/disabling workaround */
@@ -1758,7 +1796,7 @@ out:
 /**
  *  e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware
  *  @hw:   pointer to the HW structure
- *  @gate: boolean set to TRUE to gate, FALSE to un-gate
+ *  @gate: boolean set to TRUE to gate, FALSE to ungate
  *
  *  Gate/ungate the automatic PHY configuration via hardware; perform
  *  the configuration via software instead.
@@ -1784,34 +1822,6 @@ static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
 }
 
 /**
- *  e1000_hv_phy_tuning_workaround_ich8lan - This is a Phy tuning work around
- *  needed for Nahum3 + Hanksville testing, requested by HW team
- **/
-static s32 e1000_hv_phy_tuning_workaround_ich8lan(struct e1000_hw *hw)
-{
-       s32 ret_val = E1000_SUCCESS;
-
-       DEBUGFUNC("e1000_hv_phy_tuning_workaround_ich8lan");
-
-       ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431);
-       if (ret_val)
-               goto out;
-
-       ret_val = hw->phy.ops.write_reg(hw, PHY_REG(770, 16), 0xA204);
-       if (ret_val)
-               goto out;
-
-       ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x29, 0x66C0);
-       if (ret_val)
-               goto out;
-
-       ret_val = hw->phy.ops.write_reg(hw, (1 << 6) | 0x1E, 0xFFFF);
-
-out:
-       return ret_val;
-}
-
-/**
  *  e1000_lan_init_done_ich8lan - Check for PHY config completion
  *  @hw: pointer to the HW structure
  *
@@ -1878,16 +1888,13 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
                break;
        }
 
-       if (hw->device_id == E1000_DEV_ID_ICH10_HANKSVILLE) {
-               ret_val = e1000_hv_phy_tuning_workaround_ich8lan(hw);
-               if (ret_val)
-                       goto out;
+       /* Clear the host wakeup bit after lcd reset */
+       if (hw->mac.type >= e1000_pchlan) {
+               hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, &reg);
+               reg &= ~BM_WUC_HOST_WU_BIT;
+               hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, reg);
        }
 
-       /* Dummy read to clear the phy wakeup bit after lcd reset */
-       if (hw->mac.type >= e1000_pchlan)
-               hw->phy.ops.read_reg(hw, BM_WUC, &reg);
-
        /* Configure the LCD with the extended configuration region in NVM */
        ret_val = e1000_sw_lcd_config_ich8lan(hw);
        if (ret_val)
@@ -1896,11 +1903,26 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
        /* Configure the LCD with the OEM bits in NVM */
        ret_val = e1000_oem_bits_config_ich8lan(hw, TRUE);
 
-       /* Ungate automatic PHY configuration on non-managed 82579 */
-       if ((hw->mac.type == e1000_pch2lan) &&
-           !(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID)) {
-               msec_delay(10);
-               e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
+       if (hw->mac.type == e1000_pch2lan) {
+               /* Ungate automatic PHY configuration on non-managed 82579 */
+               if (!(E1000_READ_REG(hw, E1000_FWSM) &
+                   E1000_ICH_FWSM_FW_VALID)) {
+                       msec_delay(10);
+                       e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
+               }
+
+               /* Set EEE LPI Update Timer to 200usec */
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       goto out;
+               ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR,
+                                                      I82579_LPI_UPDATE_TIMER);
+               if (ret_val)
+                       goto release;
+               ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA,
+                                                      0x1387);
+release:
+               hw->phy.ops.release(hw);
        }
 
 out:
@@ -2308,7 +2330,6 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
 {
        union ich8_hws_flash_status hsfsts;
        s32 ret_val = -E1000_ERR_NVM;
-       s32 i = 0;
 
        DEBUGFUNC("e1000_flash_cycle_init_ich8lan");
 
@@ -2346,6 +2367,8 @@ static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
                E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
                ret_val = E1000_SUCCESS;
        } else {
+               s32 i;
+
                /*
                 * Otherwise poll for sometime so the current
                 * cycle has a chance to end before giving up.
@@ -3183,7 +3206,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
 {
        struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
        u16 reg;
-       u32 ctrl, icr, kab;
+       u32 ctrl, kab;
        s32 ret_val;
 
        DEBUGFUNC("e1000_reset_hw_ich8lan");
@@ -3253,9 +3276,6 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
        E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST));
        msec_delay(20);
 
-       if (!ret_val)
-               e1000_release_swflag_ich8lan(hw);
-
        if (ctrl & E1000_CTRL_PHY_RST) {
                ret_val = hw->phy.ops.get_cfg_done(hw);
                if (ret_val)
@@ -3275,7 +3295,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
                E1000_WRITE_REG(hw, E1000_CRC_OFFSET, 0x65656565);
 
        E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
-       icr = E1000_READ_REG(hw, E1000_ICR);
+       E1000_READ_REG(hw, E1000_ICR);
 
        kab = E1000_READ_REG(hw, E1000_KABGTXD);
        kab |= E1000_KABGTXD_BGSQLBIAS;
@@ -3324,11 +3344,13 @@ static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
 
        /*
         * The 82578 Rx buffer will stall if wakeup is enabled in host and
-        * the ME.  Reading the BM_WUC register will clear the host wakeup bit.
+        * the ME.  Disable wakeup by clearing the host wakeup bit.
         * Reset the phy after disabling host wakeup to reset the Rx buffer.
         */
        if (hw->phy.type == e1000_phy_82578) {
-               hw->phy.ops.read_reg(hw, BM_WUC, &i);
+               hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, &i);
+               i &= ~BM_WUC_HOST_WU_BIT;
+               hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, i);
                ret_val = e1000_phy_hw_reset_ich8lan(hw);
                if (ret_val)
                        return ret_val;
@@ -3650,7 +3672,7 @@ static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
 
        DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan");
 
-       if (!(dev_spec->kmrn_lock_loss_workaround_enabled))
+       if (!dev_spec->kmrn_lock_loss_workaround_enabled)
                goto out;
 
        /*
@@ -3826,22 +3848,21 @@ out:
 }
 
 /**
- *  e1000_disable_gig_wol_ich8lan - disable gig during WoL
+ *  e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
  *  @hw: pointer to the HW structure
  *
  *  During S0 to Sx transition, it is possible the link remains at gig
  *  instead of negotiating to a lower speed.  Before going to Sx, set
  *  'LPLU Enabled' and 'Gig Disable' to force link speed negotiation
- *  to a lower speed.
- *
- *  Should only be called for applicable parts.
+ *  to a lower speed.  For PCH and newer parts, the OEM bits PHY register
+ *  (LED, GbE disable and LPLU configurations) also needs to be written.
  **/
-void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
 {
        u32 phy_ctrl;
        s32 ret_val;
 
-       DEBUGFUNC("e1000_disable_gig_wol_ich8lan");
+       DEBUGFUNC("e1000_suspend_workarounds_ich8lan");
 
        phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
        phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU | E1000_PHY_CTRL_GBE_DISABLE;
@@ -3860,6 +3881,63 @@ void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw)
 }
 
 /**
+ *  e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
+ *  @hw: pointer to the HW structure
+ *
+ *  During Sx to S0 transitions on non-managed devices or managed devices
+ *  on which PHY resets are not blocked, if the PHY registers cannot be
+ *  accessed properly by the s/w toggle the LANPHYPC value to power cycle
+ *  the PHY.
+ **/
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
+{
+       u32 fwsm;
+
+       DEBUGFUNC("e1000_resume_workarounds_pchlan");
+
+       if (hw->mac.type != e1000_pch2lan)
+               return;
+
+       fwsm = E1000_READ_REG(hw, E1000_FWSM);
+       if (!(fwsm & E1000_ICH_FWSM_FW_VALID) ||
+           !hw->phy.ops.check_reset_block(hw)) {
+               u16 phy_id1, phy_id2;
+               s32 ret_val;
+
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val) {
+                       DEBUGOUT("Failed to acquire PHY semaphore in resume\n");
+                       return;
+               }
+
+               /* Test access to the PHY registers by reading the ID regs */
+               ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_id1);
+               if (ret_val)
+                       goto release;
+               ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_id2);
+               if (ret_val)
+                       goto release;
+
+               if (hw->phy.id == ((u32)(phy_id1 << 16) |
+                                  (u32)(phy_id2 & PHY_REVISION_MASK)))
+                       goto release;
+
+               e1000_toggle_lanphypc_value_ich8lan(hw);
+
+               hw->phy.ops.release(hw);
+               msec_delay(50);
+               hw->phy.ops.reset(hw);
+               msec_delay(50);
+               return;
+       }
+
+release:
+       hw->phy.ops.release(hw);
+       
+       return;
+}
+
+/**
  *  e1000_cleanup_led_ich8lan - Restore the default LED operation
  *  @hw: pointer to the HW structure
  *
@@ -4096,6 +4174,7 @@ static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
 static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
 {
        u16 phy_data;
+       s32 ret_val;
 
        DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan");
 
@@ -4119,20 +4198,29 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
        if ((hw->phy.type == e1000_phy_82578) ||
            (hw->phy.type == e1000_phy_82579) ||
            (hw->phy.type == e1000_phy_82577)) {
-               hw->phy.ops.read_reg(hw, HV_SCC_UPPER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_ECOL_UPPER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_ECOL_LOWER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_MCC_UPPER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_MCC_LOWER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_LATECOL_UPPER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_LATECOL_LOWER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_COLC_UPPER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_COLC_LOWER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_DC_UPPER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_DC_LOWER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_TNCRS_UPPER, &phy_data);
-               hw->phy.ops.read_reg(hw, HV_TNCRS_LOWER, &phy_data);
+               ret_val = hw->phy.ops.acquire(hw);
+               if (ret_val)
+                       return;
+               ret_val = hw->phy.ops.set_page(hw,
+                                              HV_STATS_PAGE << IGP_PAGE_SHIFT);
+               if (ret_val)
+                       goto release;
+               hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
+               hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
+release:
+               hw->phy.ops.release(hw);
        }
 }
 
index ca310ce..a5121d0 100644 (file)
 #define IGP3_PM_CTRL_FORCE_PWR_DOWN          0x0020
 
 /* PHY Wakeup Registers and defines */
+#define BM_PORT_GEN_CFG PHY_REG(BM_PORT_CTRL_PAGE, 17)
 #define BM_RCTL         PHY_REG(BM_WUC_PAGE, 0)
 #define BM_WUC          PHY_REG(BM_WUC_PAGE, 1)
 #define BM_WUFC         PHY_REG(BM_WUC_PAGE, 2)
 #define BM_RCTL_PMCF          0x0040          /* Pass MAC Control Frames */
 #define BM_RCTL_RFCE          0x0080          /* Rx Flow Control Enable */
 
-#define HV_LED_CONFIG          PHY_REG(768, 30) /* LED Configuration */
-#define HV_MUX_DATA_CTRL               PHY_REG(776, 16)
+#define HV_LED_CONFIG           PHY_REG(768, 30) /* LED Configuration */
+#define HV_MUX_DATA_CTRL        PHY_REG(776, 16)
 #define HV_MUX_DATA_CTRL_GEN_TO_MAC    0x0400
 #define HV_MUX_DATA_CTRL_FORCE_SPEED   0x0004
-#define HV_SCC_UPPER           PHY_REG(778, 16) /* Single Collision Count */
-#define HV_SCC_LOWER           PHY_REG(778, 17)
-#define HV_ECOL_UPPER          PHY_REG(778, 18) /* Excessive Collision Count */
-#define HV_ECOL_LOWER          PHY_REG(778, 19)
-#define HV_MCC_UPPER           PHY_REG(778, 20) /* Multiple Collision Count */
-#define HV_MCC_LOWER           PHY_REG(778, 21)
-#define HV_LATECOL_UPPER       PHY_REG(778, 23) /* Late Collision Count */
-#define HV_LATECOL_LOWER       PHY_REG(778, 24)
-#define HV_COLC_UPPER          PHY_REG(778, 25) /* Collision Count */
-#define HV_COLC_LOWER          PHY_REG(778, 26)
-#define HV_DC_UPPER            PHY_REG(778, 27) /* Defer Count */
-#define HV_DC_LOWER            PHY_REG(778, 28)
-#define HV_TNCRS_UPPER         PHY_REG(778, 29) /* Transmit with no CRS */
-#define HV_TNCRS_LOWER         PHY_REG(778, 30)
+#define HV_STATS_PAGE    778
+#define HV_SCC_UPPER     PHY_REG(HV_STATS_PAGE, 16) /* Single Collision Count */
+#define HV_SCC_LOWER     PHY_REG(HV_STATS_PAGE, 17)
+#define HV_ECOL_UPPER    PHY_REG(HV_STATS_PAGE, 18) /* Excessive Coll. Count */
+#define HV_ECOL_LOWER    PHY_REG(HV_STATS_PAGE, 19)
+#define HV_MCC_UPPER     PHY_REG(HV_STATS_PAGE, 20) /* Multiple Coll. Count */
+#define HV_MCC_LOWER     PHY_REG(HV_STATS_PAGE, 21)
+#define HV_LATECOL_UPPER PHY_REG(HV_STATS_PAGE, 23) /* Late Collision Count */
+#define HV_LATECOL_LOWER PHY_REG(HV_STATS_PAGE, 24)
+#define HV_COLC_UPPER    PHY_REG(HV_STATS_PAGE, 25) /* Collision Count */
+#define HV_COLC_LOWER    PHY_REG(HV_STATS_PAGE, 26)
+#define HV_DC_UPPER      PHY_REG(HV_STATS_PAGE, 27) /* Defer Count */
+#define HV_DC_LOWER      PHY_REG(HV_STATS_PAGE, 28)
+#define HV_TNCRS_UPPER   PHY_REG(HV_STATS_PAGE, 29) /* Transmit with no CRS */
+#define HV_TNCRS_LOWER   PHY_REG(HV_STATS_PAGE, 30)
 
 #define E1000_FCRTV_PCH     0x05F40 /* PCH Flow Control Refresh Timer Value */
 
 #define LCD_CFG_PHY_ADDR_BIT   0x0020 /* Phy address bit from LCD Config word */
 
 /* KMRN Mode Control */
-#define HV_KMRN_MODE_CTRL      PHY_REG(769, 16)
-#define HV_KMRN_MDIO_SLOW      0x0400
+#define HV_KMRN_MODE_CTRL       PHY_REG(769, 16)
+#define HV_KMRN_MDIO_SLOW       0x0400
+
+/* KMRN FIFO Control and Status */
+#define HV_KMRN_FIFO_CTRLSTA                  PHY_REG(770, 16)
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK    0x7000
+#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT   12
 
 /* PHY Power Management Control */
-#define HV_PM_CTRL             PHY_REG(770, 17)
+#define HV_PM_CTRL              PHY_REG(770, 17)
 
 #define SW_FLAG_TIMEOUT    1000 /* SW Semaphore flag timeout in milliseconds */
 
 /* PHY Low Power Idle Control */
-#define I82579_LPI_CTRL                        PHY_REG(772, 20)
-#define I82579_LPI_CTRL_ENABLE_MASK    0x6000
+#define I82579_LPI_CTRL         PHY_REG(772, 20)
+#define I82579_LPI_CTRL_ENABLE_MASK     0x6000
+
+/* EMI Registers */
+#define I82579_EMI_ADDR         0x10
+#define I82579_EMI_DATA         0x11
+#define I82579_LPI_UPDATE_TIMER 0x4805 /* in 40ns units + 40 ns base value */
 
 /*
  * Additional interrupts need to be handled for ICH family:
 #define E1000_RXDEXT_LINKSEC_ERROR_BAD_SIG      0x60000000
 
 /* Receive Address Initial CRC Calculation */
-#define E1000_PCH_RAICC(_n)    (0x05F50 + ((_n) * 4))
+#define E1000_PCH_RAICC(_n)     (0x05F50 + ((_n) * 4))
 
 void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
                                                  bool state);
 void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
 void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
-void e1000_disable_gig_wol_ich8lan(struct e1000_hw *hw);
+void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw);
+void e1000_resume_workarounds_pchlan(struct e1000_hw *hw);
 s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
 s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_config);
-s32 e1000_hv_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
 void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
 s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
 #endif
index 02a613c..4606dd3 100644 (file)
@@ -247,7 +247,7 @@ s32 e1000_get_bus_info_pcie_generic(struct e1000_hw *hw)
                        bus->speed = e1000_bus_speed_unknown;
                        break;
                }
-               
+
                bus->width = (enum e1000_bus_width)((pcie_link_status &
                                                PCIE_LINK_WIDTH_MASK) >>
                                               PCIE_LINK_WIDTH_SHIFT);
@@ -355,7 +355,7 @@ void e1000_write_vfta_generic(struct e1000_hw *hw, u32 offset, u32 value)
  *  @hw: pointer to the HW structure
  *  @rar_count: receive address registers
  *
- *  Setups the receive address registers by setting the base receive address
+ *  Setup the receive address registers by setting the base receive address
  *  register to the devices MAC address and clearing all the other receive
  *  address registers to 0.
  **/
@@ -804,7 +804,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
                        mac->autoneg_failed = 1;
                        goto out;
                }
-               DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+               DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
                /* Disable auto-negotiation in the TXCW register */
                E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -827,7 +827,7 @@ s32 e1000_check_for_fiber_link_generic(struct e1000_hw *hw)
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
                 */
-               DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+               DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
                E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
                E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -872,7 +872,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
                        mac->autoneg_failed = 1;
                        goto out;
                }
-               DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n");
+               DEBUGOUT("NOT Rx'ing /C/, disable AutoNeg and force link.\n");
 
                /* Disable auto-negotiation in the TXCW register */
                E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE));
@@ -895,7 +895,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
                 * and disable forced link in the Device Control register
                 * in an attempt to auto-negotiate with our link partner.
                 */
-               DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n");
+               DEBUGOUT("Rx'ing /C/, enable AutoNeg and stop forcing link.\n");
                E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw);
                E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU));
 
@@ -930,7 +930,7 @@ s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw)
                                if (!(rxcw & E1000_RXCW_IV)) {
                                        mac->serdes_has_link = TRUE;
                                        DEBUGOUT("SERDES: Link up - autoneg "
-                                          "completed successfully.\n");
+                                          "completed sucessfully.\n");
                                } else {
                                        mac->serdes_has_link = FALSE;
                                        DEBUGOUT("SERDES: Link down - invalid"
@@ -1492,7 +1492,7 @@ s32 e1000_config_fc_after_link_up_generic(struct e1000_hw *hw)
                         * of pause frames.  In this case, we had to advertise
                         * FULL flow control because we could not advertise Rx
                         * ONLY. Hence, we must now check to see if we need to
-                        * turn OFF  the TRANSMISSION of PAUSE frames.
+                        * turn OFF the TRANSMISSION of PAUSE frames.
                         */
                        if (hw->fc.requested_mode == e1000_fc_full) {
                                hw->fc.current_mode = e1000_fc_full;
index 9b3382f..e952335 100644 (file)
@@ -71,7 +71,7 @@ s32  e1000_id_led_init_generic(struct e1000_hw *hw);
 s32  e1000_led_on_generic(struct e1000_hw *hw);
 s32  e1000_led_off_generic(struct e1000_hw *hw);
 void e1000_update_mc_addr_list_generic(struct e1000_hw *hw,
-                                      u8 *mc_addr_list, u32 mc_addr_count);
+                                       u8 *mc_addr_list, u32 mc_addr_count);
 #ifndef NO_82542_SUPPORT
 s32  e1000_set_default_fc_generic(struct e1000_hw *hw);
 #endif
index 588e649..16a88b5 100644 (file)
@@ -34,8 +34,6 @@
 
 #include "e1000_api.h"
 
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
-
 /**
  *  e1000_calculate_checksum - Calculate checksum for buffer
  *  @buffer: pointer to EEPROM
@@ -47,7 +45,7 @@ static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
 static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
 {
        u32 i;
-       u8  sum = 0;
+       u8 sum = 0;
 
        DEBUGFUNC("e1000_calculate_checksum");
 
index ec26671..a970a66 100644 (file)
@@ -390,7 +390,6 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
        struct e1000_nvm_info *nvm = &hw->nvm;
        u32 eecd = E1000_READ_REG(hw, E1000_EECD);
        s32 ret_val = E1000_SUCCESS;
-       u16 timeout = 0;
        u8 spi_stat_reg;
 
        DEBUGFUNC("e1000_ready_nvm_eeprom");
@@ -404,11 +403,12 @@ static s32 e1000_ready_nvm_eeprom(struct e1000_hw *hw)
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
        } else
        if (nvm->type == e1000_nvm_eeprom_spi) {
+               u16 timeout = NVM_MAX_RETRY_SPI;
+
                /* Clear SK and CS */
                eecd &= ~(E1000_EECD_CS | E1000_EECD_SK);
                E1000_WRITE_REG(hw, E1000_EECD, eecd);
                usec_delay(1);
-               timeout = NVM_MAX_RETRY_SPI;
 
                /*
                 * Read "Status Register" repeatedly until the LSB is cleared.
@@ -790,7 +790,7 @@ out:
  *  Reads the product board assembly (PBA) number from the EEPROM and stores
  *  the value in pba_num.
  **/
-s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num, 
+s32 e1000_read_pba_string_generic(struct e1000_hw *hw, u8 *pba_num,
                                   u32 pba_num_size)
 {
        s32 ret_val;
index f43639b..4c261ba 100644 (file)
@@ -55,8 +55,6 @@ s32  e1000_read_nvm_eerd(struct e1000_hw *hw, u16 offset, u16 words,
                          u16 *data);
 s32  e1000_valid_led_default_generic(struct e1000_hw *hw, u16 *data);
 s32  e1000_validate_nvm_checksum_generic(struct e1000_hw *hw);
-s32  e1000_write_nvm_eewr(struct e1000_hw *hw, u16 offset,
-                          u16 words, u16 *data);
 s32  e1000_write_nvm_microwire(struct e1000_hw *hw, u16 offset,
                                u16 words, u16 *data);
 s32  e1000_write_nvm_spi(struct e1000_hw *hw, u16 offset, u16 words,
index 0831a1c..7d377e1 100644 (file)
 
 static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg);
 static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
-                                          u16 *data, bool read);
+                                          u16 *data, bool read, bool page_set);
 static u32 e1000_get_phy_addr_for_hv_page(u32 page);
 static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
                                           u16 *data, bool read);
 
 /* Cable length tables */
-static const u16 e1000_m88_cable_length_table[] =
-       0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
+static const u16 e1000_m88_cable_length_table[] = {
+       0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
 #define M88E1000_CABLE_LENGTH_TABLE_SIZE \
                 (sizeof(e1000_m88_cable_length_table) / \
                  sizeof(e1000_m88_cable_length_table[0]))
 
-static const u16 e1000_igp_2_cable_length_table[] =
-    { 0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21,
-      0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41,
-      6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61,
-      21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82,
-      40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104,
-      60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121,
-      83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124,
-      104, 109, 114, 118, 121, 124};
+static const u16 e1000_igp_2_cable_length_table[] = {
+       0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
+       6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
+       26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
+       44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
+       66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
+       87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
+       100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
+       124};
 #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
                 (sizeof(e1000_igp_2_cable_length_table) / \
                  sizeof(e1000_igp_2_cable_length_table[0]))
@@ -82,20 +82,33 @@ void e1000_init_phy_ops_generic(struct e1000_hw *hw)
        phy->ops.get_cfg_done = e1000_null_ops_generic;
        phy->ops.get_cable_length = e1000_null_ops_generic;
        phy->ops.get_info = e1000_null_ops_generic;
+       phy->ops.set_page = e1000_null_set_page;
        phy->ops.read_reg = e1000_null_read_reg;
        phy->ops.read_reg_locked = e1000_null_read_reg;
+       phy->ops.read_reg_page = e1000_null_read_reg;
        phy->ops.release = e1000_null_phy_generic;
        phy->ops.reset = e1000_null_ops_generic;
        phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
        phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
        phy->ops.write_reg = e1000_null_write_reg;
        phy->ops.write_reg_locked = e1000_null_write_reg;
+       phy->ops.write_reg_page = e1000_null_write_reg;
        phy->ops.power_up = e1000_null_phy_generic;
        phy->ops.power_down = e1000_null_phy_generic;
        phy->ops.cfg_on_link_up = e1000_null_ops_generic;
 }
 
 /**
+ *  e1000_null_set_page - No-op function, return 0
+ *  @hw: pointer to the HW structure
+ **/
+s32 e1000_null_set_page(struct e1000_hw *hw, u16 data)
+{
+       DEBUGFUNC("e1000_null_set_page");
+       return E1000_SUCCESS;
+}
+
+/**
  *  e1000_null_read_reg - No-op function, return 0
  *  @hw: pointer to the HW structure
  **/
@@ -255,10 +268,6 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
 
        E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-       /* Workaround for Si errata */
-       if ((hw->phy.type == e1000_phy_82577) && (hw->revision_id <= 2))
-               msec_delay(10);
-
        /*
         * Poll the ready bit to see if the MDI read completed
         * Increasing the time out as testing showed failures with
@@ -281,9 +290,9 @@ s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
                goto out;
        }
        *data = (u16) mdic;
-       
+
        /*
-        * Allow some time after each MDIC transaction to avoid 
+        * Allow some time after each MDIC transaction to avoid
         * reading duplicate data in the next MDIC transaction.
         */
        if (hw->mac.type == e1000_pch2lan)
@@ -326,10 +335,6 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
 
        E1000_WRITE_REG(hw, E1000_MDIC, mdic);
 
-       /* Workaround for Si errata */
-       if ((hw->phy.type == e1000_phy_82577) && (hw->revision_id <= 2))
-               msec_delay(10);
-
        /*
         * Poll the ready bit to see if the MDI read completed
         * Increasing the time out as testing showed failures with
@@ -353,7 +358,7 @@ s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
        }
 
        /*
-        * Allow some time after each MDIC transaction to avoid 
+        * Allow some time after each MDIC transaction to avoid
         * reading duplicate data in the next MDIC transaction.
         */
        if (hw->mac.type == e1000_pch2lan)
@@ -427,6 +432,26 @@ out:
 }
 
 /**
+ *  e1000_set_page_igp - Set page as on IGP-like PHY(s)
+ *  @hw: pointer to the HW structure
+ *  @page: page to set (shifted left when necessary)
+ *
+ *  Sets PHY page required for PHY register access.  Assumes semaphore is
+ *  already acquired.  Note, this function sets phy.addr to 1 so the caller
+ *  must set it appropriately (if necessary) after this function returns.
+ **/
+s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
+{
+       DEBUGFUNC("e1000_set_page_igp");
+
+       DEBUGOUT1("Setting page 0x%x\n", page);
+
+       hw->phy.addr = 1;
+
+       return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
+}
+
+/**
  *  __e1000_read_phy_reg_igp - Read igp PHY register
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read
@@ -742,7 +767,7 @@ s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
                }
        }
 
-       /* Enable CRS on TX. This must be set for half-duplex operation. */
+       /* Enable CRS on Tx. This must be set for half-duplex operation. */
        ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
        if (ret_val)
                goto out;
@@ -783,10 +808,9 @@ s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
        if (ret_val)
                goto out;
 
-       phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
        /* For BM PHY this bit is downshift enable */
-       if (phy->type == e1000_phy_bm)
-               phy_data &= ~M88E1000_PSCR_ASSERT_CRS_ON_TX;
+       if (phy->type != e1000_phy_bm)
+               phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
 
        /*
         * Options:
@@ -2055,11 +2079,12 @@ s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
        u16 phy_data, i, agc_value = 0;
        u16 cur_agc_index, max_agc_index = 0;
        u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
-       u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] =
-                                                        {IGP02E1000_PHY_AGC_A,
-                                                         IGP02E1000_PHY_AGC_B,
-                                                         IGP02E1000_PHY_AGC_C,
-                                                         IGP02E1000_PHY_AGC_D};
+       static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
+              IGP02E1000_PHY_AGC_A,
+              IGP02E1000_PHY_AGC_B,
+              IGP02E1000_PHY_AGC_C,
+              IGP02E1000_PHY_AGC_D
+       };
 
        DEBUGFUNC("e1000_get_cable_length_igp_2");
 
@@ -2576,7 +2601,7 @@ s32 e1000_determine_phy_address(struct e1000_hw *hw)
                         * If phy_type is valid, break - we found our
                         * PHY address
                         */
-                       if (phy_type  != e1000_phy_unknown) {
+                       if (phy_type != e1000_phy_unknown) {
                                ret_val = E1000_SUCCESS;
                                goto out;
                        }
@@ -2617,9 +2642,7 @@ static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
 s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
 {
        s32 ret_val;
-       u32 page_select = 0;
        u32 page = offset >> IGP_PAGE_SHIFT;
-       u32 page_shift = 0;
 
        DEBUGFUNC("e1000_write_phy_reg_bm");
 
@@ -2630,13 +2653,15 @@ s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
-                                                        FALSE);
+                                                        FALSE, FALSE);
                goto out;
        }
 
        hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               u32 page_shift, page_select;
+
                /*
                 * Page select is register 31 for phy address 1 and 22 for
                 * phy address 2 and 3. Page select is shifted only for
@@ -2678,9 +2703,7 @@ out:
 s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
 {
        s32 ret_val;
-       u32 page_select = 0;
        u32 page = offset >> IGP_PAGE_SHIFT;
-       u32 page_shift = 0;
 
        DEBUGFUNC("e1000_read_phy_reg_bm");
 
@@ -2691,13 +2714,15 @@ s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
-                                                        TRUE);
+                                                        TRUE, FALSE);
                goto out;
        }
 
        hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
 
        if (offset > MAX_PHY_MULTI_PAGE_REG) {
+               u32 page_shift, page_select;
+
                /*
                 * Page select is register 31 for phy address 1 and 22 for
                 * phy address 2 and 3. Page select is shifted only for
@@ -2740,7 +2765,7 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
        s32 ret_val;
        u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
 
-       DEBUGFUNC("e1000_write_phy_reg_bm2");
+       DEBUGFUNC("e1000_read_phy_reg_bm2");
 
        ret_val = hw->phy.ops.acquire(hw);
        if (ret_val)
@@ -2749,7 +2774,7 @@ s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
-                                                        TRUE);
+                                                        TRUE, FALSE);
                goto out;
        }
 
@@ -2795,7 +2820,7 @@ s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
                ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
-                                                        FALSE);
+                                                        FALSE, FALSE);
                goto out;
        }
 
@@ -2819,107 +2844,176 @@ out:
 }
 
 /**
- *  e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register
+ *  e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
  *  @hw: pointer to the HW structure
- *  @offset: register offset to be read or written
- *  @data: pointer to the data to read or write
- *  @read: determines if operation is read or write
+ *  @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
  *
- *  Acquires semaphore, if necessary, then reads the PHY register at offset
- *  and storing the retrieved information in data.  Release any acquired
- *  semaphores before exiting. Note that procedure to read the wakeup
- *  registers are different. It works as such:
- *  1) Set page 769, register 17, bit 2 = 1
- *  2) Set page to 800 for host (801 if we were manageability)
- *  3) Write the address using the address opcode (0x11)
- *  4) Read or write the data using the data opcode (0x12)
- *  5) Restore 769_17.2 to its original value
- *
- *  Assumes semaphore already acquired.
+ *  Assumes semaphore already acquired and phy_reg points to a valid memory
+ *  address to store contents of the BM_WUC_ENABLE_REG register.
  **/
-static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
-                                          u16 *data, bool read)
+s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
 {
        s32 ret_val;
-       u16 reg = BM_PHY_REG_NUM(offset);
-       u16 phy_reg = 0;
+       u16 temp;
 
-       DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
+       DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm");
 
-       /* Gig must be disabled for MDIO accesses to page 800 */
-       if ((hw->mac.type == e1000_pchlan) &&
-          (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
-               DEBUGOUT("Attempting to access page 800 while gig enabled.\n");
+       if (!phy_reg) {
+               ret_val = -E1000_ERR_PARAM;
+               goto out;
+       }
 
-       /* All operations in this function are phy address 1 */
+       /* All page select, port ctrl and wakeup registers use phy address 1 */
        hw->phy.addr = 1;
 
-       /* Set page 769 */
-       e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-                                (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
+       /* Select Port Control Registers page */
+       ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
+       if (ret_val) {
+               DEBUGOUT("Could not set Port Control page\n");
+               goto out;
+       }
 
-       ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg);
+       ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
        if (ret_val) {
-               DEBUGOUT("Could not read PHY page 769\n");
+               DEBUGOUT2("Could not read PHY register %d.%d\n",
+                         BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
                goto out;
        }
 
-       /* First clear bit 4 to avoid a power state change */
-       phy_reg &= ~(BM_WUC_HOST_WU_BIT);
-       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
+       /*
+        * Enable both PHY wakeup mode and Wakeup register page writes.
+        * Prevent a power state change by disabling ME and Host PHY wakeup.
+        */
+       temp = *phy_reg;
+       temp |= BM_WUC_ENABLE_BIT;
+       temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
+
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
        if (ret_val) {
-               DEBUGOUT("Could not clear PHY page 769 bit 4\n");
+               DEBUGOUT2("Could not write PHY register %d.%d\n",
+                         BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
                goto out;
        }
 
-       /* Write bit 2 = 1, and clear bit 4 to 769_17 */
-       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG,
-                                          phy_reg | BM_WUC_ENABLE_BIT);
+       /* Select Host Wakeup Registers page */
+       ret_val = e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+
+       /* caller now able to write registers on the Wakeup registers page */
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
+ *  @hw: pointer to the HW structure
+ *  @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
+ *
+ *  Restore BM_WUC_ENABLE_REG to its original value.
+ *
+ *  Assumes semaphore already acquired and *phy_reg is the contents of the
+ *  BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
+ *  caller.
+ **/
+s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
+{
+       s32 ret_val = E1000_SUCCESS;
+
+       DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm");
+
+       if (!phy_reg)
+               return -E1000_ERR_PARAM;
+
+       /* Select Port Control Registers page */
+       ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
        if (ret_val) {
-               DEBUGOUT("Could not write PHY page 769 bit 2\n");
+               DEBUGOUT("Could not set Port Control page\n");
                goto out;
        }
 
-       /* Select page 800 */
-       ret_val = e1000_write_phy_reg_mdic(hw,
-                                          IGP01E1000_PHY_PAGE_SELECT,
-                                          (BM_WUC_PAGE << IGP_PAGE_SHIFT));
+       /* Restore 769.17 to its original value */
+       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
+       if (ret_val)
+               DEBUGOUT2("Could not restore PHY register %d.%d\n",
+                         BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
+out:
+       return ret_val;
+}
+
+/**
+ *  e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to be read or written
+ *  @data: pointer to the data to read or write
+ *  @read: determines if operation is read or write
+ *  @page_set: BM_WUC_PAGE already set and access enabled
+ *
+ *  Read the PHY register at offset and store the retrieved information in
+ *  data, or write data to PHY register at offset.  Note the procedure to
+ *  access the PHY wakeup registers is different than reading the other PHY
+ *  registers. It works as such:
+ *  1) Set 769.17.2 (page 769, register 17, bit 2) = 1
+ *  2) Set page to 800 for host (801 if we were manageability)
+ *  3) Write the address using the address opcode (0x11)
+ *  4) Read or write the data using the data opcode (0x12)
+ *  5) Restore 769.17.2 to its original value
+ *
+ *  Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
+ *  step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
+ *
+ *  Assumes semaphore is already acquired.  When page_set==TRUE, assumes
+ *  the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
+ *  is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
+ **/
+static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
+                                          u16 *data, bool read, bool page_set)
+{
+       s32 ret_val;
+       u16 reg = BM_PHY_REG_NUM(offset);
+       u16 phy_reg = 0;
+
+       DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
+
+       /* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
+       if ((hw->mac.type == e1000_pchlan) &&
+          (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
+               DEBUGOUT1("Attempting to access page %d while gig enabled.\n",
+                         page);
+
+       if (!page_set) {
+               /* Enable access to PHY wakeup registers */
+               ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
+               if (ret_val) {
+                       DEBUGOUT("Could not enable PHY wakeup reg access\n");
+                       goto out;
+               }
+       }
+
+       DEBUGOUT2("Accessing PHY page %d reg 0x%x\n", page, reg);
 
-       /* Write the page 800 offset value using opcode 0x11 */
+       /* Write the Wakeup register page offset value using opcode 0x11 */
        ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
        if (ret_val) {
-               DEBUGOUT("Could not write address opcode to page 800\n");
+               DEBUGOUT1("Could not write address opcode to page %d\n", page);
                goto out;
        }
 
        if (read) {
-               /* Read the page 800 value using opcode 0x12 */
+               /* Read the Wakeup register page value using opcode 0x12 */
                ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
                                                  data);
        } else {
-               /* Write the page 800 value using opcode 0x12 */
+               /* Write the Wakeup register page value using opcode 0x12 */
                ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
                                                   *data);
        }
 
        if (ret_val) {
-               DEBUGOUT("Could not access data value from page 800\n");
+               DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg);
                goto out;
        }
 
-       /*
-        * Restore 769_17.2 to its original value
-        * Set page 769
-        */
-       e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT,
-                                (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT));
-
-       /* Clear 769_17.2 */
-       ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
-       if (ret_val) {
-               DEBUGOUT("Could not clear PHY page 769 bit 2\n");
-               goto out;
-       }
+       if (!page_set)
+               ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
 
 out:
        return ret_val;
@@ -2974,11 +3068,12 @@ void e1000_power_down_phy_copper(struct e1000_hw *hw)
  *  semaphore before exiting.
  **/
 static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
-                                   bool locked)
+                                   bool locked, bool page_set)
 {
        s32 ret_val;
        u16 page = BM_PHY_REG_PAGE(offset);
        u16 reg = BM_PHY_REG_NUM(offset);
+       u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
 
        DEBUGFUNC("__e1000_read_phy_reg_hv");
 
@@ -2990,8 +3085,8 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
 
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
-               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
-                                                        data, TRUE);
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
+                                                        TRUE, page_set);
                goto out;
        }
 
@@ -3001,26 +3096,25 @@ static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
                goto out;
        }
 
-       hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
-       if (page == HV_INTC_FC_PAGE_START)
-               page = 0;
+       if (!page_set) {
+               if (page == HV_INTC_FC_PAGE_START)
+                       page = 0;
 
-       if (reg > MAX_PHY_MULTI_PAGE_REG) {
-               u32 phy_addr = hw->phy.addr;
+               if (reg > MAX_PHY_MULTI_PAGE_REG) {
+                       /* Page is shifted left, PHY expects (page x 32) */
+                       ret_val = e1000_set_page_igp(hw,
+                                                    (page << IGP_PAGE_SHIFT));
 
-               hw->phy.addr = 1;
+                       hw->phy.addr = phy_addr;
 
-               /* Page is shifted left, PHY expects (page x 32) */
-               ret_val = e1000_write_phy_reg_mdic(hw,
-                                            IGP01E1000_PHY_PAGE_SELECT,
-                                            (page << IGP_PAGE_SHIFT));
-               hw->phy.addr = phy_addr;
-
-               if (ret_val)
-                       goto out;
+                       if (ret_val)
+                               goto out;
+               }
        }
 
+       DEBUGOUT3("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+                 page << IGP_PAGE_SHIFT, reg);
+
        ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
                                          data);
 out:
@@ -3042,7 +3136,7 @@ out:
  **/
 s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       return __e1000_read_phy_reg_hv(hw, offset, data, FALSE);
+       return __e1000_read_phy_reg_hv(hw, offset, data, FALSE, FALSE);
 }
 
 /**
@@ -3056,7 +3150,21 @@ s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
  **/
 s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
 {
-       return __e1000_read_phy_reg_hv(hw, offset, data, TRUE);
+       return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, FALSE);
+}
+
+/**
+ *  e1000_read_phy_reg_page_hv - Read HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Reads the PHY register at offset and stores the retrieved information
+ *  in data.  Assumes semaphore already acquired and page already set.
+ **/
+s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
+{
+       return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, TRUE);
 }
 
 /**
@@ -3070,11 +3178,12 @@ s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
  *  at the offset.  Release any acquired semaphores before exiting.
  **/
 static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
-                                    bool locked)
+                                    bool locked, bool page_set)
 {
        s32 ret_val;
        u16 page = BM_PHY_REG_PAGE(offset);
        u16 reg = BM_PHY_REG_NUM(offset);
+       u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
 
        DEBUGFUNC("__e1000_write_phy_reg_hv");
 
@@ -3086,8 +3195,8 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
 
        /* Page 800 works differently than the rest so it has its own func */
        if (page == BM_WUC_PAGE) {
-               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset,
-                                                        &data, FALSE);
+               ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
+                                                        FALSE, page_set);
                goto out;
        }
 
@@ -3097,44 +3206,44 @@ static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
                goto out;
        }
 
-       hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
-
-       if (page == HV_INTC_FC_PAGE_START)
-               page = 0;
+       if (!page_set) {
+               if (page == HV_INTC_FC_PAGE_START)
+                       page = 0;
 
-       /*
-        * Workaround MDIO accesses being disabled after entering IEEE Power
-        * Down (whenever bit 11 of the PHY Control register is set)
-        */
-       if ((hw->phy.type == e1000_phy_82578) &&
-           (hw->phy.revision >= 1) &&
-           (hw->phy.addr == 2) &&
-           ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
-           (data & (1 << 11))) {
-               u16 data2 = 0x7EFF;
-               ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3,
-                                                        &data2, FALSE);
-               if (ret_val)
-                       goto out;
-       }
-
-       if (reg > MAX_PHY_MULTI_PAGE_REG) {
-               u32 phy_addr = hw->phy.addr;
+               /*
+                * Workaround MDIO accesses being disabled after entering IEEE
+                * Power Down (when bit 11 of the PHY Control register is set)
+                */
+               if ((hw->phy.type == e1000_phy_82578) &&
+                   (hw->phy.revision >= 1) &&
+                   (hw->phy.addr == 2) &&
+                   ((MAX_PHY_REG_ADDRESS & reg) == 0) &&
+                   (data & (1 << 11))) {
+                       u16 data2 = 0x7EFF;
+                       ret_val = e1000_access_phy_debug_regs_hv(hw,
+                                                                (1 << 6) | 0x3,
+                                                                &data2, FALSE);
+                       if (ret_val)
+                               goto out;
+               }
 
-               hw->phy.addr = 1;
+               if (reg > MAX_PHY_MULTI_PAGE_REG) {
+                       /* Page is shifted left, PHY expects (page x 32) */
+                       ret_val = e1000_set_page_igp(hw,
+                                                    (page << IGP_PAGE_SHIFT));
 
-               /* Page is shifted left, PHY expects (page x 32) */
-               ret_val = e1000_write_phy_reg_mdic(hw,
-                                            IGP01E1000_PHY_PAGE_SELECT,
-                                            (page << IGP_PAGE_SHIFT));
-               hw->phy.addr = phy_addr;
+                       hw->phy.addr = phy_addr;
 
-               if (ret_val)
-                       goto out;
+                       if (ret_val)
+                               goto out;
+               }
        }
 
+       DEBUGOUT3("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
+                 page << IGP_PAGE_SHIFT, reg);
+
        ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
-                                         data);
+                                          data);
 
 out:
        if (!locked)
@@ -3154,7 +3263,7 @@ out:
  **/
 s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       return __e1000_write_phy_reg_hv(hw, offset, data, FALSE);
+       return __e1000_write_phy_reg_hv(hw, offset, data, FALSE, FALSE);
 }
 
 /**
@@ -3168,7 +3277,21 @@ s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
  **/
 s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
 {
-       return __e1000_write_phy_reg_hv(hw, offset, data, TRUE);
+       return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, FALSE);
+}
+
+/**
+ *  e1000_write_phy_reg_page_hv - Write HV PHY register
+ *  @hw: pointer to the HW structure
+ *  @offset: register offset to write to
+ *  @data: data to write at register offset
+ *
+ *  Writes the data to PHY register at the offset.  Assumes semaphore
+ *  already acquired and page already set.
+ **/
+s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
+{
+       return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, TRUE);
 }
 
 /**
@@ -3190,11 +3313,12 @@ static u32 e1000_get_phy_addr_for_hv_page(u32 page)
  *  @hw: pointer to the HW structure
  *  @offset: register offset to be read or written
  *  @data: pointer to the data to be read or written
- *  @read: determines if operation is read or written
+ *  @read: determines if operation is read or write
  *
  *  Reads the PHY register at offset and stores the retreived information
  *  in data.  Assumes semaphore already acquired.  Note that the procedure
- *  to read these regs uses the address port and data port to read/write.
+ *  to access these regs uses the address port and data port to read/write.
+ *  These accesses done with PHY address 2 and without using pages.
  **/
 static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
                                           u16 *data, bool read)
@@ -3216,7 +3340,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
        /* masking with 0x3F to remove the page from offset */
        ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
        if (ret_val) {
-               DEBUGOUT("Could not write PHY the HV address register\n");
+               DEBUGOUT("Could not write the Address Offset port register\n");
                goto out;
        }
 
@@ -3227,7 +3351,7 @@ static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
                ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data);
 
        if (ret_val) {
-               DEBUGOUT("Could not read data value from HV data register\n");
+               DEBUGOUT("Could not access the Data port register\n");
                goto out;
        }
 
index 2d151a0..1e1e847 100644 (file)
@@ -40,6 +40,7 @@ s32  e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data);
 void e1000_null_phy_generic(struct e1000_hw *hw);
 s32  e1000_null_lplu_state(struct e1000_hw *hw, bool active);
 s32  e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_null_set_page(struct e1000_hw *hw, u16 data);
 s32  e1000_check_downshift_generic(struct e1000_hw *hw);
 s32  e1000_check_polarity_m88(struct e1000_hw *hw);
 s32  e1000_check_polarity_igp(struct e1000_hw *hw);
@@ -65,6 +66,7 @@ s32  e1000_phy_hw_reset_generic(struct e1000_hw *hw);
 s32  e1000_phy_reset_dsp_generic(struct e1000_hw *hw);
 s32  e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_set_page_igp(struct e1000_hw *hw, u16 page);
 s32  e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data);
@@ -84,6 +86,8 @@ enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id);
 s32  e1000_determine_phy_address(struct e1000_hw *hw);
 s32  e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
+s32  e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg);
 s32  e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data);
 void e1000_power_up_phy_copper(struct e1000_hw *hw);
@@ -92,8 +96,10 @@ s32  e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data);
+s32  e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data);
 s32  e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data);
+s32  e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data);
 s32  e1000_link_stall_workaround_hv(struct e1000_hw *hw);
 s32  e1000_copper_link_setup_82577(struct e1000_hw *hw);
 s32  e1000_check_polarity_82577(struct e1000_hw *hw);
@@ -118,6 +124,7 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 
 /* BM/HV Specific Registers */
 #define BM_PORT_CTRL_PAGE                 769
+#define BM_PORT_GEN_CFG_REG               PHY_REG(BM_PORT_CTRL_PAGE, 17)
 #define BM_PCIE_PAGE                      770
 #define BM_WUC_PAGE                       800
 #define BM_WUC_ADDRESS_OPCODE             0x11
@@ -126,6 +133,7 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define BM_WUC_ENABLE_REG                 17
 #define BM_WUC_ENABLE_BIT                 (1 << 2)
 #define BM_WUC_HOST_WU_BIT                (1 << 4)
+#define BM_WUC_ME_WU_BIT                  (1 << 5)
 
 #define PHY_UPPER_SHIFT                   21
 #define BM_PHY_REG(page, reg) \
@@ -168,6 +176,12 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define I82577_DSTATUS_CABLE_LENGTH       0x03FC
 #define I82577_DSTATUS_CABLE_LENGTH_SHIFT 2
 
+/* 82580 PHY Power Management */
+#define E1000_82580_PHY_POWER_MGMT        0xE14
+#define E1000_82580_PM_SPD                0x0001 /* Smart Power Down */
+#define E1000_82580_PM_D0_LPLU            0x0002 /* For D0a states */
+#define E1000_82580_PM_D3_LPLU            0x0004 /* For all other states */
+
 /* BM PHY Copper Specific Control 1 */
 #define BM_CS_CTRL1                       16
 #define BM_CS_CTRL1_ENERGY_DETECT         0x0300 /* Enable Energy Detect */
@@ -232,6 +246,7 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define E1000_KMRNCTRLSTA_DIAG_OFFSET     0x3    /* Kumeran Diagnostic */
 #define E1000_KMRNCTRLSTA_TIMEOUTS        0x4    /* Kumeran Timeouts */
 #define E1000_KMRNCTRLSTA_INBAND_PARAM    0x9    /* Kumeran InBand Parameters */
+#define E1000_KMRNCTRLSTA_IBIST_DISABLE   0x0200 /* Kumeran IBIST Disable */
 #define E1000_KMRNCTRLSTA_DIAG_NELPBK     0x1000 /* Nearend Loopback mode */
 #define E1000_KMRNCTRLSTA_K1_CONFIG        0x7
 #define E1000_KMRNCTRLSTA_K1_ENABLE        0x0002
@@ -260,4 +275,28 @@ s32  e1000_get_cable_length_82577(struct e1000_hw *hw);
 #define IFE_PMC_FORCE_MDIX       0x0040 /* 1=force MDI-X, 0=force MDI */
 #define IFE_PMC_AUTO_MDIX        0x0080 /* 1=enable auto MDI/MDI-X, 0=disable */
 
+/* SFP modules ID memory locations */
+#define E1000_SFF_IDENTIFIER_OFFSET 0x00
+#define E1000_SFF_IDENTIFIER_SFF    0x02
+#define E1000_SFF_IDENTIFIER_SFP    0x03
+
+#define E1000_SFF_ETH_FLAGS_OFFSET  0x06
+/* Flags for SFP modules compatible with ETH up to 1Gb */
+struct sfp_e1000_flags {
+       u8 e1000_base_sx:1;
+       u8 e1000_base_lx:1;
+       u8 e1000_base_cx:1;
+       u8 e1000_base_t:1;
+       u8 e100_base_lx:1;
+       u8 e100_base_fx:1;
+       u8 e10_base_bx10:1;
+       u8 e10_base_px:1;
+};
+
+/* Vendor OUIs: format of OUI is 0x[byte0][byte1][byte2][00] */
+#define E1000_SFF_VENDOR_OUI_TYCO     0x00407600
+#define E1000_SFF_VENDOR_OUI_FTL      0x00906500
+#define E1000_SFF_VENDOR_OUI_AVAGO    0x00176A00
+#define E1000_SFF_VENDOR_OUI_INTEL    0x001B2100
+
 #endif
index afe2060..400358b 100644 (file)
@@ -81,6 +81,7 @@
 #define E1000_EXTCNF_CTRL  0x00F00  /* Extended Configuration Control */
 #define E1000_EXTCNF_SIZE  0x00F08  /* Extended Configuration Size */
 #define E1000_PHY_CTRL     0x00F10  /* PHY Control Register in CSR */
+#define E1000_POEMB        E1000_PHY_CTRL /* PHY OEM Bits */
 #define E1000_PBA      0x01000  /* Packet Buffer Allocation - RW */
 #define E1000_PBS      0x01008  /* Packet Buffer Size */
 #define E1000_EEMNGCTL 0x01010  /* MNG EEprom Control */
 #define E1000_DMCTXTH           0x03550 /* Transmit Threshold */
 #define E1000_DMCTLX            0x02514 /* Time to Lx Request */
 #define E1000_DMCRTRH           0x05DD0 /* Receive Packet Rate Threshold */
-#define E1000_DMCCNT            0x05DD4 /* Current RX Count */
+#define E1000_DMCCNT            0x05DD4 /* Current Rx Count */
 #define E1000_FCRTC             0x02170 /* Flow Control Rx high watermark */
 #define E1000_PCIEMISC          0x05BB8 /* PCIE misc config register */