#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 }
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);
case e1000_ich10lan:
case e1000_pch2lan:
case e1000_82574:
+ case e1000_82583:
case e1000_80003es2lan:
max_frame_size = 9234;
break;
/* Adapters that do not support jumbo frames */
case e1000_82542:
- case e1000_82583:
case e1000_ich8lan:
max_frame_size = ETHER_MAX_LEN;
break;
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");
*/
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);
}
}
}
+
+/*
+ * 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);
+}
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 *);
/* 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");
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);
+}
* 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]))
**/
static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
{
- u32 ctrl, icr;
+ u32 ctrl;
s32 ret_val;
DEBUGFUNC("e1000_reset_hw_80003es2lan");
/* 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);
struct e1000_mac_info *mac = &hw->mac;
u32 reg_data;
s32 ret_val;
+ u16 kum_reg_data;
u16 i;
DEBUGFUNC("e1000_init_hw_80003es2lan");
/* 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) |
**/
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");
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;
}
**/
static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
{
- u32 ledctl, ctrl, icr, manc;
+ u32 ledctl, ctrl, manc;
DEBUGFUNC("e1000_reset_hw_82541");
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;
}
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,
{
struct e1000_bus_info *bus = &hw->bus;
s32 ret_val = E1000_SUCCESS;
- u32 ctrl, icr;
+ u32 ctrl;
DEBUGFUNC("e1000_reset_hw_82542");
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)
**/
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");
/* 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;
}
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);
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;
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:
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;
}
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 */
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;
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;
}
/**
+ * 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
*
**/
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");
/* 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 */
* 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;
&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)
default:
break;
}
+
return e1000_setup_link_generic(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)) {
return ret_val;
}
-
/**
* e1000_set_mac_type - Sets MAC type
* @hw: pointer to the HW structure
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:
#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_ */
#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
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 *);
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 *);
};
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;
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;
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;
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);
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);
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
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");
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;
*/
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);
/*
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);
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");
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 */
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;
}
/*
static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_acquire_nvm_ich8lan");
+
return E1000_SUCCESS;
}
static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
{
DEBUGFUNC("e1000_release_nvm_ich8lan");
+
return;
}
}
out:
+
return ret_val;
}
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;
}
}
/**
+ * 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
*
/**
- * 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
**/
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))) {
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.
}
}
- 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)
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);
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[])
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 */
/**
* 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.
}
/**
- * 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
*
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 &= ~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, ®);
-
/* Configure the LCD with the extended configuration region in NVM */
ret_val = e1000_sw_lcd_config_ich8lan(hw);
if (ret_val)
/* 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:
{
union ich8_hws_flash_status hsfsts;
s32 ret_val = -E1000_ERR_NVM;
- s32 i = 0;
DEBUGFUNC("e1000_flash_cycle_init_ich8lan");
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.
{
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");
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)
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;
/*
* 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;
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;
/*
}
/**
- * 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;
}
/**
+ * 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
*
static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
{
u16 phy_data;
+ s32 ret_val;
DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan");
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);
}
}
#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
bus->speed = e1000_bus_speed_unknown;
break;
}
-
+
bus->width = (enum e1000_bus_width)((pcie_link_status &
PCIE_LINK_WIDTH_MASK) >>
PCIE_LINK_WIDTH_SHIFT);
* @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.
**/
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));
* 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));
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));
* 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));
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"
* 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;
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
#include "e1000_api.h"
-static u8 e1000_calculate_checksum(u8 *buffer, u32 length);
-
/**
* e1000_calculate_checksum - Calculate checksum for buffer
* @buffer: pointer to EEPROM
static u8 e1000_calculate_checksum(u8 *buffer, u32 length)
{
u32 i;
- u8 sum = 0;
+ u8 sum = 0;
DEBUGFUNC("e1000_calculate_checksum");
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");
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.
* 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;
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,
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]))
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
**/
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
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)
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
}
/*
- * 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)
}
/**
+ * 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
}
}
- /* 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;
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:
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");
* 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;
}
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");
/* 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
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");
/* 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
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)
/* 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;
}
/* 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;
}
}
/**
- * 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;
* 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");
/* 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;
}
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:
**/
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);
}
/**
**/
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);
}
/**
* 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");
/* 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;
}
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)
**/
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);
}
/**
**/
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);
}
/**
* @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)
/* 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;
}
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;
}
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);
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);
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);
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);
/* 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
#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) \
#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 */
#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
#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
#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 */