diff options
author | Jonathan Gray <jsg@cvs.openbsd.org> | 2010-06-29 19:14:10 +0000 |
---|---|---|
committer | Jonathan Gray <jsg@cvs.openbsd.org> | 2010-06-29 19:14:10 +0000 |
commit | a414260538ba5ae94fcb51aa97991f7e7b115e49 (patch) | |
tree | 617c0e40fcfe3aef8780e79d908aa6c2e7c65fc9 | |
parent | 445287faf73687367ac7927cc5c65871207ba6bf (diff) |
More workarounds adapted from FreeBSD to make the 82577/82578 happy,
from Mike Belopuhov and me.
looks good reyk@ ok claudio@
-rw-r--r-- | sys/dev/pci/if_em_hw.c | 421 | ||||
-rw-r--r-- | sys/dev/pci/if_em_hw.h | 89 |
2 files changed, 489 insertions, 21 deletions
diff --git a/sys/dev/pci/if_em_hw.c b/sys/dev/pci/if_em_hw.c index 72abebe9b73..5a483ccc5e2 100644 --- a/sys/dev/pci/if_em_hw.c +++ b/sys/dev/pci/if_em_hw.c @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.c,v 1.52 2010/06/28 20:24:39 jsg Exp $ */ +/* $OpenBSD: if_em_hw.c,v 1.53 2010/06/29 19:14:09 jsg Exp $ */ /* * if_em_hw.c Shared functions for accessing and configuring the MAC */ @@ -164,8 +164,18 @@ static uint8_t em_calculate_mng_checksum(char *, uint32_t); static int32_t em_configure_kmrn_for_10_100(struct em_hw *, uint16_t); static int32_t em_configure_kmrn_for_1000(struct em_hw *); static int32_t em_set_pciex_completion_timeout(struct em_hw *hw); -int32_t em_hv_phy_workarounds_ich8lan(struct em_hw *); -int32_t em_configure_k1_ich8lan(struct em_hw *, boolean_t); +static int32_t em_set_mdio_slow_mode_hv(struct em_hw *); +int32_t em_hv_phy_workarounds_ich8lan(struct em_hw *); +int32_t em_link_stall_workaround_hv(struct em_hw *); +int32_t em_configure_k1_ich8lan(struct em_hw *, boolean_t); +int32_t em_access_phy_wakeup_reg_bm(struct em_hw *, uint32_t, + uint16_t *, boolean_t); +int32_t em_access_phy_debug_regs_hv(struct em_hw *, uint32_t, + uint16_t *, boolean_t); +int32_t em_access_phy_reg_hv(struct em_hw *, uint32_t, uint16_t *, + boolean_t); +int32_t em_oem_bits_config_pchlan(struct em_hw *, boolean_t); + /* IGP cable length table */ static const uint16_t @@ -1034,6 +1044,39 @@ em_init_hw(struct em_hw *hw) reg_data &= ~0x80000000; E1000_WRITE_REG(hw, STATUS, reg_data); } + + if (hw->mac_type == em_pchlan) { + /* + * The MAC-PHY interconnect may still be in SMBus mode + * after Sx->S0. Toggle the LANPHYPC Value bit to force + * the interconnect to PCIe mode, but only if there is no + * firmware present otherwise firmware will have done it. + */ + if ((E1000_READ_REG(hw, FWSM) & E1000_FWSM_FW_VALID) == 0) { + ctrl = E1000_READ_REG(hw, CTRL); + ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; + ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; + E1000_WRITE_REG(hw, CTRL, ctrl); + usec_delay(10); + ctrl &= ~E1000_CTRL_LANPHYPC_OVERRIDE; + E1000_WRITE_REG(hw, CTRL, ctrl); + msec_delay(50); + } + /* + * Reset the PHY before any acccess to it. Doing so, + * ensures that the PHY is in a known good state before + * we read/write PHY registers. The generic reset is + * sufficient here, because we haven't determined + * the PHY type yet. + */ + em_phy_reset(hw); + + /* Set MDIO slow mode before any other MDIO access */ + ret_val = em_set_mdio_slow_mode_hv(hw); + if (ret_val) + return ret_val; + } + /* Initialize Identification LED */ ret_val = em_id_led_init(hw); if (ret_val) { @@ -1145,6 +1188,19 @@ em_init_hw(struct em_hw *hw) hw->mac_type == em_pchlan) msec_delay(15); + /* + * 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. + * Reset the phy after disabling host wakeup to reset the Rx buffer. + */ + if (hw->phy_type == em_phy_82578) { + em_read_phy_reg(hw, PHY_REG(BM_WUC_PAGE, 1), + (uint16_t *)®_data); + ret_val = em_phy_reset(hw); + if (ret_val) + return ret_val; + } + /* Call a subroutine to configure the link and setup flow control. */ ret_val = em_setup_link(hw); @@ -1421,6 +1477,7 @@ em_setup_link(struct em_hw *hw) if (hw->phy_type == em_phy_82577 || hw->phy_type == em_phy_82578) { + E1000_WRITE_REG(hw, FCRTV_PCH, 0x1000); em_write_phy_reg(hw, PHY_REG(BM_PORT_CTRL_PAGE, 27), hw->fc_pause_time); } @@ -3366,6 +3423,12 @@ em_check_for_link(struct em_hw *hw) hw->icp_xxxx_is_link_up = (phy_data & MII_SR_LINK_STATUS) != 0; + if (hw->phy_type == em_phy_82578) { + ret_val = em_link_stall_workaround_hv(hw); + if (ret_val) + return ret_val; + } + if (phy_data & MII_SR_LINK_STATUS) { hw->get_link_status = FALSE; /* @@ -3898,6 +3961,201 @@ em_swfw_sync_release(struct em_hw *hw, uint16_t mask) em_put_hw_eeprom_semaphore(hw); } + +int32_t +em_access_phy_wakeup_reg_bm(struct em_hw *hw, uint32_t reg_addr, + uint16_t *phy_data, boolean_t read) +{ + int32_t ret_val; + uint16_t reg = BM_PHY_REG_NUM(reg_addr); + uint16_t phy_reg = 0; + + /* Gig must be disabled for MDIO accesses to page 800 */ + if ((hw->mac_type == em_pchlan) && + (!(E1000_READ_REG(hw, PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE))) + printf("Attempting to access page 800 while gig enabled.\n"); + + /* All operations in this function are phy address 1 */ + hw->phy_addr = 1; + + /* Set page 769 */ + em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_ENABLE_PAGE << PHY_PAGE_SHIFT)); + + ret_val = em_read_phy_reg_ex(hw, BM_WUC_ENABLE_REG, &phy_reg); + if (ret_val) { + printf("Could not read PHY page 769\n"); + goto out; + } + + /* First clear bit 4 to avoid a power state change */ + phy_reg &= ~(BM_WUC_HOST_WU_BIT); + ret_val = em_write_phy_reg_ex(hw, BM_WUC_ENABLE_REG, phy_reg); + if (ret_val) { + printf("Could not clear PHY page 769 bit 4\n"); + goto out; + } + + /* Write bit 2 = 1, and clear bit 4 to 769_17 */ + ret_val = em_write_phy_reg_ex(hw, BM_WUC_ENABLE_REG, + phy_reg | BM_WUC_ENABLE_BIT); + if (ret_val) { + printf("Could not write PHY page 769 bit 2\n"); + goto out; + } + + /* Select page 800 */ + ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_PAGE << PHY_PAGE_SHIFT)); + + /* Write the page 800 offset value using opcode 0x11 */ + ret_val = em_write_phy_reg_ex(hw, BM_WUC_ADDRESS_OPCODE, reg); + if (ret_val) { + printf("Could not write address opcode to page 800\n"); + goto out; + } + + if (read) + /* Read the page 800 value using opcode 0x12 */ + ret_val = em_read_phy_reg_ex(hw, BM_WUC_DATA_OPCODE, + phy_data); + else + /* Write the page 800 value using opcode 0x12 */ + ret_val = em_write_phy_reg_ex(hw, BM_WUC_DATA_OPCODE, + *phy_data); + + if (ret_val) { + printf("Could not access data value from page 800\n"); + goto out; + } + + /* + * Restore 769_17.2 to its original value + * Set page 769 + */ + em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (BM_WUC_ENABLE_PAGE << PHY_PAGE_SHIFT)); + + /* Clear 769_17.2 */ + ret_val = em_write_phy_reg_ex(hw, BM_WUC_ENABLE_REG, phy_reg); + if (ret_val) { + printf("Could not clear PHY page 769 bit 2\n"); + goto out; + } + +out: + return ret_val; +} + +int32_t +em_access_phy_debug_regs_hv(struct em_hw *hw, uint32_t reg_addr, + uint16_t *phy_data, boolean_t read) +{ + int32_t ret_val; + uint32_t addr_reg = 0; + uint32_t data_reg = 0; + + /* This takes care of the difference with desktop vs mobile phy */ + addr_reg = (hw->phy_type == em_phy_82578) ? + I82578_PHY_ADDR_REG : I82577_PHY_ADDR_REG; + data_reg = addr_reg + 1; + + /* All operations in this function are phy address 2 */ + hw->phy_addr = 2; + + /* masking with 0x3F to remove the page from offset */ + ret_val = em_write_phy_reg_ex(hw, addr_reg, (uint16_t)reg_addr & 0x3F); + if (ret_val) { + printf("Could not write PHY the HV address register\n"); + goto out; + } + + /* Read or write the data value next */ + if (read) + ret_val = em_read_phy_reg_ex(hw, data_reg, phy_data); + else + ret_val = em_write_phy_reg_ex(hw, data_reg, *phy_data); + + if (ret_val) { + printf("Could not read data value from HV data register\n"); + goto out; + } + +out: + return ret_val; +} + +/****************************************************************************** + * Reads or writes the value from a PHY register, if the value is on a specific + * non zero page, sets the page first. + * hw - Struct containing variables accessed by shared code + * reg_addr - address of the PHY register to read + *****************************************************************************/ +int32_t +em_access_phy_reg_hv(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data, + boolean_t read) +{ + uint32_t ret_val; + uint16_t swfw; + uint16_t page = BM_PHY_REG_PAGE(reg_addr); + uint16_t reg = BM_PHY_REG_NUM(reg_addr); + + DEBUGFUNC("em_access_phy_reg_hv"); + + swfw = E1000_SWFW_PHY0_SM; + + if (em_swfw_sync_acquire(hw, swfw)) + return -E1000_ERR_SWFW_SYNC; + + if (page == BM_WUC_PAGE) { + ret_val = em_access_phy_wakeup_reg_bm(hw, reg_addr, + phy_data, read); + goto release; + } + + if (page >= HV_INTC_FC_PAGE_START) + hw->phy_addr = 1; + else + hw->phy_addr = 2; + + 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 (!read && + (hw->phy_type == em_phy_82578) && + (hw->phy_revision >= 1) && + (hw->phy_addr == 2) && + ((MAX_PHY_REG_ADDRESS & reg) == 0) && + (*phy_data & (1 << 11))) { + uint16_t data2 = 0x7EFF; + + ret_val = em_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, + &data2, FALSE); + if (ret_val) + return ret_val; + } + + if (reg_addr > MAX_PHY_MULTI_PAGE_REG) { + ret_val = em_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, + (page << PHY_PAGE_SHIFT)); + if (ret_val) + return ret_val; + } + if (read) + ret_val = em_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg, + phy_data); + else + ret_val = em_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg, + *phy_data); +release: + em_swfw_sync_release(hw, swfw); + return ret_val; +} + /****************************************************************************** * Reads the value from a PHY register, if the value is on a specific non zero * page, sets the page first. @@ -3911,6 +4169,9 @@ em_read_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t *phy_data) uint16_t swfw; DEBUGFUNC("em_read_phy_reg"); + if (hw->mac_type == em_pchlan) + return (em_access_phy_reg_hv(hw, reg_addr, phy_data, TRUE)); + if ((hw->mac_type == em_80003es2lan) && (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { swfw = E1000_SWFW_PHY1_SM; @@ -4068,6 +4329,9 @@ em_write_phy_reg(struct em_hw *hw, uint32_t reg_addr, uint16_t phy_data) uint16_t swfw; DEBUGFUNC("em_write_phy_reg"); + if (hw->mac_type == em_pchlan) + return (em_access_phy_reg_hv(hw, reg_addr, &phy_data, FALSE)); + if ((hw->mac_type == em_80003es2lan) && (E1000_READ_REG(hw, STATUS) & E1000_STATUS_FUNC_1)) { swfw = E1000_SWFW_PHY1_SM; @@ -4354,6 +4618,63 @@ em_phy_hw_reset(struct em_hw *hw) return ret_val; } + +int32_t +em_oem_bits_config_pchlan(struct em_hw *hw, boolean_t d0_state) +{ + int32_t ret_val = E1000_SUCCESS; + uint32_t mac_reg; + uint16_t oem_reg; + uint16_t swfw = E1000_SWFW_PHY0_SM; + + if (hw->mac_type != em_pchlan) + return ret_val; + + ret_val = em_swfw_sync_acquire(hw, swfw); + if (ret_val) + return ret_val; + + mac_reg = E1000_READ_REG(hw, EXTCNF_CTRL); + if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) + goto out; + + mac_reg = E1000_READ_REG(hw, FEXTNVM); + if (!(mac_reg & FEXTNVM_SW_CONFIG_ICH8M)) + goto out; + + mac_reg = E1000_READ_REG(hw, PHY_CTRL); + + ret_val = em_read_phy_reg(hw, HV_OEM_BITS, &oem_reg); + if (ret_val) + goto out; + + oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU); + + if (d0_state) { + if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE) + oem_reg |= HV_OEM_BITS_GBE_DIS; + + if (mac_reg & E1000_PHY_CTRL_D0A_LPLU) + oem_reg |= HV_OEM_BITS_LPLU; + } else { + if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE) + oem_reg |= HV_OEM_BITS_GBE_DIS; + + if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU) + oem_reg |= HV_OEM_BITS_LPLU; + } + /* Restart auto-neg to activate the bits */ + if (!em_check_phy_reset_block(hw)) + oem_reg |= HV_OEM_BITS_RESTART_AN; + ret_val = em_write_phy_reg(hw, HV_OEM_BITS, oem_reg); + +out: + em_swfw_sync_release(hw, swfw); + + return ret_val; +} + + /****************************************************************************** * Resets the PHY * @@ -4398,8 +4719,20 @@ em_phy_reset(struct em_hw *hw) break; } + /* Allow time for h/w to get to a quiescent state after reset */ + msec_delay(10); + if (hw->phy_type == em_phy_igp || hw->phy_type == em_phy_igp_2) em_phy_init_script(hw); + else if (hw->mac_type == em_pchlan) { + ret_val = em_hv_phy_workarounds_ich8lan(hw); + if (ret_val) + return ret_val; + + ret_val = em_oem_bits_config_pchlan(hw, TRUE); + if (ret_val) + return ret_val; + } return E1000_SUCCESS; } @@ -6602,6 +6935,26 @@ em_clear_hw_cntrs(struct em_hw *hw) temp = E1000_READ_REG(hw, IAC); temp = E1000_READ_REG(hw, ICRXOC); + if (hw->phy_type == em_phy_82577 || + hw->phy_type == em_phy_82578) { + uint16_t phy_data; + + em_read_phy_reg(hw, HV_SCC_UPPER, &phy_data); + em_read_phy_reg(hw, HV_SCC_LOWER, &phy_data); + em_read_phy_reg(hw, HV_ECOL_UPPER, &phy_data); + em_read_phy_reg(hw, HV_ECOL_LOWER, &phy_data); + em_read_phy_reg(hw, HV_MCC_UPPER, &phy_data); + em_read_phy_reg(hw, HV_MCC_LOWER, &phy_data); + em_read_phy_reg(hw, HV_LATECOL_UPPER, &phy_data); + em_read_phy_reg(hw, HV_LATECOL_LOWER, &phy_data); + em_read_phy_reg(hw, HV_COLC_UPPER, &phy_data); + em_read_phy_reg(hw, HV_COLC_LOWER, &phy_data); + em_read_phy_reg(hw, HV_DC_UPPER, &phy_data); + em_read_phy_reg(hw, HV_DC_LOWER, &phy_data); + em_read_phy_reg(hw, HV_TNCRS_UPPER, &phy_data); + em_read_phy_reg(hw, HV_TNCRS_LOWER, &phy_data); + } + if (hw->mac_type == em_ich8lan || hw->mac_type == em_ich9lan || hw->mac_type == em_ich10lan || @@ -9122,7 +9475,8 @@ em_hv_phy_workarounds_ich8lan(struct em_hw *hw) swfw = E1000_SWFW_PHY0_SM; /* Set MDIO slow mode before any other MDIO access */ - if (hw->phy_type == em_phy_82577) { + if (hw->phy_type == em_phy_82577 || + hw->phy_type == em_phy_82578) { ret_val = em_set_mdio_slow_mode_hv(hw); if (ret_val) goto out; @@ -9200,10 +9554,10 @@ em_hv_phy_workarounds_ich8lan(struct em_hw *hw) * Workaround for OEM (GbE) not operating after reset - * restart AN (twice) */ - ret_val = em_write_phy_reg(hw, PHY_REG(768, 25), 0x0400); + ret_val = em_write_phy_reg(hw, PHY_REG(0, 25), 0x0400); if (ret_val) goto out; - ret_val = em_write_phy_reg(hw, PHY_REG(768, 25), 0x0400); + ret_val = em_write_phy_reg(hw, PHY_REG(0, 25), 0x0400); if (ret_val) goto out; } @@ -9233,6 +9587,61 @@ out: return ret_val; } + +/** + * em_link_stall_workaround_hv - Si workaround + * @hw: pointer to the HW structure + * + * This function works around a Si bug where the link partner can get + * a link up indication before the PHY does. If small packets are sent + * by the link partner they can be placed in the packet buffer without + * being properly accounted for by the PHY and will stall preventing + * further packets from being received. The workaround is to clear the + * packet buffer after the PHY detects link up. + **/ +int32_t +em_link_stall_workaround_hv(struct em_hw *hw) +{ + int32_t ret_val = E1000_SUCCESS; + uint16_t phy_data; + + if (hw->phy_type != em_phy_82578) + goto out; + + /* Do not apply workaround if in PHY loopback bit 14 set */ + em_read_phy_reg(hw, PHY_CTRL, &phy_data); + if (phy_data & E1000_PHY_CTRL_LOOPBACK) + goto out; + + /* check if link is up and at 1Gbps */ + ret_val = em_read_phy_reg(hw, BM_CS_STATUS, &phy_data); + if (ret_val) + goto out; + + phy_data &= BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_MASK; + + if (phy_data != (BM_CS_STATUS_LINK_UP | + BM_CS_STATUS_RESOLVED | + BM_CS_STATUS_SPEED_1000)) + goto out; + + msec_delay(200); + + /* flush the packets in the fifo buffer */ + ret_val = em_write_phy_reg(hw, HV_MUX_DATA_CTRL, + HV_MUX_DATA_CTRL_GEN_TO_MAC | HV_MUX_DATA_CTRL_FORCE_SPEED); + if (ret_val) + goto out; + + ret_val = em_write_phy_reg(hw, HV_MUX_DATA_CTRL, + HV_MUX_DATA_CTRL_GEN_TO_MAC); + +out: + return ret_val; +} + /** * e1000_configure_k1_ich8lan - Configure K1 power state * @hw: pointer to the HW structure diff --git a/sys/dev/pci/if_em_hw.h b/sys/dev/pci/if_em_hw.h index 28dc1146276..df22cb378c8 100644 --- a/sys/dev/pci/if_em_hw.h +++ b/sys/dev/pci/if_em_hw.h @@ -31,7 +31,7 @@ *******************************************************************************/ -/* $OpenBSD: if_em_hw.h,v 1.42 2010/06/28 20:24:39 jsg Exp $ */ +/* $OpenBSD: if_em_hw.h,v 1.43 2010/06/29 19:14:09 jsg Exp $ */ /* $FreeBSD: if_em_hw.h,v 1.15 2005/05/26 23:32:02 tackerman Exp $ */ /* if_em_hw.h @@ -1107,6 +1107,7 @@ struct em_ffvt_entry { #define E1000_WUPL 0x05900 /* Wakeup Packet Length - RW */ #define E1000_WUPM 0x05A00 /* Wakeup Packet Memory - RO A */ #define E1000_FFLT 0x05F00 /* Flexible Filter Length Table - RW Array */ +#define E1000_FCRTV_PCH 0x05F40 /* PCH Flow Control Refresh Timer Value */ #define E1000_CRC_OFFSET 0x05F50 /* CRC Offset Register */ #define E1000_HOST_IF 0x08800 /* Host Interface */ #define E1000_FFMT 0x09000 /* Flexible Filter Mask Table - RW Array */ @@ -1307,6 +1308,7 @@ struct em_ffvt_entry { #define E1000_82542_WUPL E1000_WUPL #define E1000_82542_WUPM E1000_WUPM #define E1000_82542_FFLT E1000_FFLT +#define E1000_82542_FCRTV_PCH E1000_FCRTV_PCH #define E1000_82542_TDFH 0x08010 #define E1000_82542_TDFT 0x08018 #define E1000_82542_FFMT E1000_FFMT @@ -1546,7 +1548,8 @@ struct em_hw { #define E1000_CTRL_D_UD_EN 0x00002000 /* Dock/Undock enable */ #define E1000_CTRL_D_UD_POLARITY 0x00004000 /* Defined polarity of Dock/Undock indication in SDP[0] */ #define E1000_CTRL_FORCE_PHY_RESET 0x00008000 /* Reset both PHY ports, through PHYRST_N pin */ -#define E1000_CTRL_EXT_LINK_EN 0x00010000 /* enable link status from external LINK_0 and LINK_1 pins */ +#define E1000_CTRL_LANPHYPC_OVERRIDE 0x00010000 /* SW control of LANPHYPC */ +#define E1000_CTRL_LANPHYPC_VALUE 0x00020000 /* SW value of LANPHYPC */ #define E1000_CTRL_EXT_PHYPDEN 0x00100000 #define E1000_CTRL_SWDPIN0 0x00040000 /* SWDPIN 0 value */ #define E1000_CTRL_SWDPIN1 0x00080000 /* SWDPIN 1 value */ @@ -1749,6 +1752,7 @@ struct em_hw { #define E1000_PHY_CTRL_NOND0A_GBE_DISABLE 0x00000008 #define E1000_PHY_CTRL_GBE_DISABLE 0x00000040 #define E1000_PHY_CTRL_B2B_EN 0x00000080 +#define E1000_PHY_CTRL_LOOPBACK 0x00004000 /* LED Control */ #define E1000_LEDCTL_LED0_MODE_MASK 0x0000000F @@ -2787,6 +2791,13 @@ struct em_host_command_info { #define I82577_PHY_CFG_ENABLE_CRS_ON_TX (1 << 15) #define I82577_PHY_CFG_ENABLE_DOWNSHIFT ((1 << 10) + (1 << 11)) +/* I82578 Specific Registers */ +#define I82578_PHY_ADDR_REG 29 + +/* I82578 Downshift settings (Extended PHY Specific Control Register) */ +#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 +#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C + /* PHY Control Register */ #define MII_CR_SPEED_SELECT_MSB 0x0040 /* bits 6,13: 10=1000, 01=100, 00=10 */ #define MII_CR_COLL_TEST_ENABLE 0x0080 /* Collision test enable */ @@ -3011,10 +3022,6 @@ struct em_host_command_info { #define M88E1000_EPSCR_TX_TIME_CTRL 0x0002 /* Add Delay */ #define M88E1000_EPSCR_RX_TIME_CTRL 0x0080 /* Add Delay */ -/* I82578 specific */ -#define I82578_EPSCR_DOWNSHIFT_ENABLE 0x0020 -#define I82578_EPSCR_DOWNSHIFT_COUNTER_MASK 0x001C - /* IGP01E1000 Specific Port Config Register - R/W */ #define IGP01E1000_PSCFR_AUTO_MDIX_PAR_DETECT 0x0010 #define IGP01E1000_PSCFR_PRE_EN 0x0020 @@ -3481,15 +3488,6 @@ union ich8_hws_flash_regacc { #define E1000_82542_IMC1 E1000_IMC1 #define E1000_82542_IMC2 E1000_IMC2 -/* OEM Bits Phy Register */ -#define HV_OEM_BITS PHY_REG(768, 25) -#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ -#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ -#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ - -#define HV_KMRN_MODE_CTRL PHY_REG(769, 16) -#define HV_KMRN_MDIO_SLOW 0x0400 - #define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */ #define E1000_NVM_K1_ENABLE 0x1 /* NVM Enable K1 bit */ @@ -3514,5 +3512,66 @@ union ich8_hws_flash_regacc { #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT 16 +/* Hanksville definitions */ +#define HV_INTC_FC_PAGE_START 768 + +#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) + +/* OEM Bits Phy Register */ +#define HV_OEM_BITS PHY_REG(768, 25) +#define HV_OEM_BITS_LPLU 0x0004 /* Low Power Link Up */ +#define HV_OEM_BITS_GBE_DIS 0x0040 /* Gigabit Disable */ +#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */ + +#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_KMRN_MODE_CTRL PHY_REG(769, 16) +#define HV_KMRN_MDIO_SLOW 0x0400 + +/* BM/HV Specific Registers */ +#define BM_PORT_CTRL_PAGE 769 +#define BM_PCIE_PAGE 770 +#define BM_WUC_PAGE 800 +#define BM_WUC_ADDRESS_OPCODE 0x11 +#define BM_WUC_DATA_OPCODE 0x12 +#define BM_WUC_ENABLE_PAGE BM_PORT_CTRL_PAGE +#define BM_WUC_ENABLE_REG 17 +#define BM_WUC_ENABLE_BIT (1 << 2) +#define BM_WUC_HOST_WU_BIT (1 << 4) + +/* BM PHY Copper Specific Status */ +#define BM_CS_STATUS 17 +#define BM_CS_STATUS_ENERGY_DETECT 0x0010 /* Energy Detect Status */ +#define BM_CS_STATUS_LINK_UP 0x0400 +#define BM_CS_STATUS_RESOLVED 0x0800 +#define BM_CS_STATUS_SPEED_MASK 0xC000 +#define BM_CS_STATUS_SPEED_1000 0x8000 + +#define PHY_UPPER_SHIFT 21 +#define BM_PHY_REG(page, reg) \ + (((reg) & MAX_PHY_REG_ADDRESS) |\ + (((page) & 0xFFFF) << PHY_PAGE_SHIFT) |\ + (((reg) & ~MAX_PHY_REG_ADDRESS) << (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT))) +#define BM_PHY_REG_PAGE(offset) \ + ((uint16_t)(((offset) >> PHY_PAGE_SHIFT) & 0xFFFF)) +#define BM_PHY_REG_NUM(offset) \ + ((uint16_t)(((offset) & MAX_PHY_REG_ADDRESS) |\ + (((offset) >> (PHY_UPPER_SHIFT - PHY_PAGE_SHIFT)) &\ + ~MAX_PHY_REG_ADDRESS))) #endif /* _EM_HW_H_ */ |