Commit d3738bb8 authored by Bruce Allan's avatar Bruce Allan Committed by David S. Miller

e1000e: initial support for 82579 LOMs

Signed-off-by: default avatarBruce Allan <bruce.w.allan@intel.com>
Tested-by: default avatarJeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent eb7700dc
...@@ -359,6 +359,7 @@ ...@@ -359,6 +359,7 @@
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001 #define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008 #define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
#define E1000_EXTCNF_CTRL_SWFLAG 0x00000020 #define E1000_EXTCNF_CTRL_SWFLAG 0x00000020
#define E1000_EXTCNF_CTRL_GATE_PHY_CFG 0x00000080
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK 0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16 #define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT 16
#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000 #define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000
...@@ -714,6 +715,7 @@ ...@@ -714,6 +715,7 @@
#define BME1000_E_PHY_ID_R2 0x01410CB1 #define BME1000_E_PHY_ID_R2 0x01410CB1
#define I82577_E_PHY_ID 0x01540050 #define I82577_E_PHY_ID 0x01540050
#define I82578_E_PHY_ID 0x004DD040 #define I82578_E_PHY_ID 0x004DD040
#define I82579_E_PHY_ID 0x01540090
/* M88E1000 Specific Registers */ /* M88E1000 Specific Registers */
#define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */ #define M88E1000_PHY_SPEC_CTRL 0x10 /* PHY Specific Control Register */
......
...@@ -164,6 +164,7 @@ enum e1000_boards { ...@@ -164,6 +164,7 @@ enum e1000_boards {
board_ich9lan, board_ich9lan,
board_ich10lan, board_ich10lan,
board_pchlan, board_pchlan,
board_pch2lan,
}; };
struct e1000_queue_stats { struct e1000_queue_stats {
...@@ -477,6 +478,7 @@ extern struct e1000_info e1000_ich8_info; ...@@ -477,6 +478,7 @@ extern struct e1000_info e1000_ich8_info;
extern struct e1000_info e1000_ich9_info; extern struct e1000_info e1000_ich9_info;
extern struct e1000_info e1000_ich10_info; extern struct e1000_info e1000_ich10_info;
extern struct e1000_info e1000_pch_info; extern struct e1000_info e1000_pch_info;
extern struct e1000_info e1000_pch2_info;
extern struct e1000_info e1000_es2_info; extern struct e1000_info e1000_es2_info;
extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num); extern s32 e1000e_read_pba_num(struct e1000_hw *hw, u32 *pba_num);
...@@ -495,6 +497,8 @@ extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw); ...@@ -495,6 +497,8 @@ extern void e1000e_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw); extern void e1000e_gig_downshift_workaround_ich8lan(struct e1000_hw *hw);
extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw); extern void e1000e_disable_gig_wol_ich8lan(struct e1000_hw *hw);
extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable); extern s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);
extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);
extern void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw);
extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw); extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw); extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
......
...@@ -880,6 +880,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data) ...@@ -880,6 +880,7 @@ static int e1000_reg_test(struct e1000_adapter *adapter, u64 *data)
switch (mac->type) { switch (mac->type) {
case e1000_ich10lan: case e1000_ich10lan:
case e1000_pchlan: case e1000_pchlan:
case e1000_pch2lan:
mask |= (1 << 18); mask |= (1 << 18);
break; break;
default: default:
...@@ -1321,6 +1322,17 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter) ...@@ -1321,6 +1322,17 @@ static int e1000_integrated_phy_loopback(struct e1000_adapter *adapter)
/* Workaround: K1 must be disabled for stable 1Gbps operation */ /* Workaround: K1 must be disabled for stable 1Gbps operation */
e1000_configure_k1_ich8lan(hw, false); e1000_configure_k1_ich8lan(hw, false);
break; break;
case e1000_phy_82579:
/* Disable PHY energy detect power down */
e1e_rphy(hw, PHY_REG(0, 21), &phy_reg);
e1e_wphy(hw, PHY_REG(0, 21), phy_reg & ~(1 << 3));
/* Disable full chip energy detect */
e1e_rphy(hw, PHY_REG(776, 18), &phy_reg);
e1e_wphy(hw, PHY_REG(776, 18), phy_reg | 1);
/* Enable loopback on the PHY */
#define I82577_PHY_LBK_CTRL 19
e1e_wphy(hw, I82577_PHY_LBK_CTRL, 0x8001);
break;
default: default:
break; break;
} }
...@@ -1878,6 +1890,7 @@ static int e1000_phys_id(struct net_device *netdev, u32 data) ...@@ -1878,6 +1890,7 @@ static int e1000_phys_id(struct net_device *netdev, u32 data)
if ((hw->phy.type == e1000_phy_ife) || if ((hw->phy.type == e1000_phy_ife) ||
(hw->mac.type == e1000_pchlan) || (hw->mac.type == e1000_pchlan) ||
(hw->mac.type == e1000_pch2lan) ||
(hw->mac.type == e1000_82583) || (hw->mac.type == e1000_82583) ||
(hw->mac.type == e1000_82574)) { (hw->mac.type == e1000_82574)) {
INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task); INIT_WORK(&adapter->led_blink_task, e1000e_led_blink_task);
......
...@@ -217,7 +217,10 @@ enum e1e_registers { ...@@ -217,7 +217,10 @@ enum e1e_registers {
E1000_SWSM = 0x05B50, /* SW Semaphore */ E1000_SWSM = 0x05B50, /* SW Semaphore */
E1000_FWSM = 0x05B54, /* FW Semaphore */ E1000_FWSM = 0x05B54, /* FW Semaphore */
E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */ E1000_SWSM2 = 0x05B58, /* Driver-only SW semaphore */
E1000_CRC_OFFSET = 0x05F50, /* CRC Offset register */ E1000_FFLT_DBG = 0x05F04, /* Debug Register */
E1000_PCH_RAICC_BASE = 0x05F50, /* Receive Address Initial CRC */
#define E1000_PCH_RAICC(_n) (E1000_PCH_RAICC_BASE + ((_n) * 4))
#define E1000_CRC_OFFSET E1000_PCH_RAICC_BASE
E1000_HICR = 0x08F00, /* Host Interface Control */ E1000_HICR = 0x08F00, /* Host Interface Control */
}; };
...@@ -303,13 +306,14 @@ enum e1e_registers { ...@@ -303,13 +306,14 @@ enum e1e_registers {
#define E1000_KMRNCTRLSTA_OFFSET 0x001F0000 #define E1000_KMRNCTRLSTA_OFFSET 0x001F0000
#define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16 #define E1000_KMRNCTRLSTA_OFFSET_SHIFT 16
#define E1000_KMRNCTRLSTA_REN 0x00200000 #define E1000_KMRNCTRLSTA_REN 0x00200000
#define E1000_KMRNCTRLSTA_CTRL_OFFSET 0x1 /* Kumeran Control */
#define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */ #define E1000_KMRNCTRLSTA_DIAG_OFFSET 0x3 /* Kumeran Diagnostic */
#define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */ #define E1000_KMRNCTRLSTA_TIMEOUTS 0x4 /* Kumeran Timeouts */
#define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */ #define E1000_KMRNCTRLSTA_INBAND_PARAM 0x9 /* Kumeran InBand Parameters */
#define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */ #define E1000_KMRNCTRLSTA_DIAG_NELPBK 0x1000 /* Nearend Loopback mode */
#define E1000_KMRNCTRLSTA_K1_CONFIG 0x7 #define E1000_KMRNCTRLSTA_K1_CONFIG 0x7
#define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E #define E1000_KMRNCTRLSTA_K1_ENABLE 0x140E
#define E1000_KMRNCTRLSTA_K1_DISABLE 0x1400 #define E1000_KMRNCTRLSTA_HD_CTRL 0x0002
#define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10 #define IFE_PHY_EXTENDED_STATUS_CONTROL 0x10
#define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */ #define IFE_PHY_SPECIAL_CONTROL 0x11 /* 100BaseTx PHY Special Control */
...@@ -387,6 +391,8 @@ enum e1e_registers { ...@@ -387,6 +391,8 @@ enum e1e_registers {
#define E1000_DEV_ID_PCH_M_HV_LC 0x10EB #define E1000_DEV_ID_PCH_M_HV_LC 0x10EB
#define E1000_DEV_ID_PCH_D_HV_DM 0x10EF #define E1000_DEV_ID_PCH_D_HV_DM 0x10EF
#define E1000_DEV_ID_PCH_D_HV_DC 0x10F0 #define E1000_DEV_ID_PCH_D_HV_DC 0x10F0
#define E1000_DEV_ID_PCH2_LV_LM 0x1502
#define E1000_DEV_ID_PCH2_LV_V 0x1503
#define E1000_REVISION_4 4 #define E1000_REVISION_4 4
...@@ -406,6 +412,7 @@ enum e1000_mac_type { ...@@ -406,6 +412,7 @@ enum e1000_mac_type {
e1000_ich9lan, e1000_ich9lan,
e1000_ich10lan, e1000_ich10lan,
e1000_pchlan, e1000_pchlan,
e1000_pch2lan,
}; };
enum e1000_media_type { enum e1000_media_type {
...@@ -442,6 +449,7 @@ enum e1000_phy_type { ...@@ -442,6 +449,7 @@ enum e1000_phy_type {
e1000_phy_bm, e1000_phy_bm,
e1000_phy_82578, e1000_phy_82578,
e1000_phy_82577, e1000_phy_82577,
e1000_phy_82579,
}; };
enum e1000_bus_width { enum e1000_bus_width {
......
...@@ -52,6 +52,8 @@ ...@@ -52,6 +52,8 @@
* 82577LC Gigabit Network Connection * 82577LC Gigabit Network Connection
* 82578DM Gigabit Network Connection * 82578DM Gigabit Network Connection
* 82578DC Gigabit Network Connection * 82578DC Gigabit Network Connection
* 82579LM Gigabit Network Connection
* 82579V Gigabit Network Connection
*/ */
#include "e1000.h" #include "e1000.h"
...@@ -126,6 +128,9 @@ ...@@ -126,6 +128,9 @@
#define HV_SMB_ADDR_PEC_EN 0x0200 #define HV_SMB_ADDR_PEC_EN 0x0200
#define HV_SMB_ADDR_VALID 0x0080 #define HV_SMB_ADDR_VALID 0x0080
/* PHY Power Management Control */
#define HV_PM_CTRL PHY_REG(770, 17)
/* Strapping Option Register - RO */ /* Strapping Option Register - RO */
#define E1000_STRAP 0x0000C #define E1000_STRAP 0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000 #define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
...@@ -279,13 +284,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ...@@ -279,13 +284,13 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
phy->ops.power_down = e1000_power_down_phy_copper_ich8lan; phy->ops.power_down = e1000_power_down_phy_copper_ich8lan;
phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
/*
* The MAC-PHY interconnect may still be in SMBus mode
* after Sx->S0. If the manageability engine (ME) is
* disabled, then toggle the LANPHYPC Value bit to force
* the interconnect to PCIe mode.
*/
if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) { if (!(er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) {
/*
* 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.
*/
ctrl = er32(CTRL); ctrl = er32(CTRL);
ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE; ctrl |= E1000_CTRL_LANPHYPC_OVERRIDE;
ctrl &= ~E1000_CTRL_LANPHYPC_VALUE; ctrl &= ~E1000_CTRL_LANPHYPC_VALUE;
...@@ -326,6 +331,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw) ...@@ -326,6 +331,7 @@ static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
switch (phy->type) { switch (phy->type) {
case e1000_phy_82577: case e1000_phy_82577:
case e1000_phy_82579:
phy->ops.check_polarity = e1000_check_polarity_82577; phy->ops.check_polarity = e1000_check_polarity_82577;
phy->ops.force_speed_duplex = phy->ops.force_speed_duplex =
e1000_phy_force_speed_duplex_82577; e1000_phy_force_speed_duplex_82577;
...@@ -530,6 +536,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) ...@@ -530,6 +536,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
mac->ops.led_off = e1000_led_off_ich8lan; mac->ops.led_off = e1000_led_off_ich8lan;
break; break;
case e1000_pchlan: case e1000_pchlan:
case e1000_pch2lan:
/* check management mode */ /* check management mode */
mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan; mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
/* ID LED init */ /* ID LED init */
...@@ -550,6 +557,14 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter) ...@@ -550,6 +557,14 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_adapter *adapter)
if (mac->type == e1000_ich8lan) if (mac->type == e1000_ich8lan)
e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true); e1000e_set_kmrn_lock_loss_workaround_ich8lan(hw, true);
/* Disable PHY configuration by hardware, config by software */
if (mac->type == e1000_pch2lan) {
u32 extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
ew32(EXTCNF_CTRL, extcnf_ctrl);
}
return 0; return 0;
} }
...@@ -653,10 +668,19 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter) ...@@ -653,10 +668,19 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)
if (rc) if (rc)
return rc; return rc;
if (hw->mac.type == e1000_pchlan) switch (hw->mac.type) {
rc = e1000_init_phy_params_pchlan(hw); case e1000_ich8lan:
else case e1000_ich9lan:
case e1000_ich10lan:
rc = e1000_init_phy_params_ich8lan(hw); rc = e1000_init_phy_params_ich8lan(hw);
break;
case e1000_pchlan:
case e1000_pch2lan:
rc = e1000_init_phy_params_pchlan(hw);
break;
default:
break;
}
if (rc) if (rc)
return rc; return rc;
...@@ -861,6 +885,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) ...@@ -861,6 +885,7 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
} }
/* Fall-thru */ /* Fall-thru */
case e1000_pchlan: case e1000_pchlan:
case e1000_pch2lan:
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M; sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
break; break;
default: default:
...@@ -880,8 +905,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) ...@@ -880,8 +905,10 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
* extended configuration before SW configuration * extended configuration before SW configuration
*/ */
data = er32(EXTCNF_CTRL); data = er32(EXTCNF_CTRL);
if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE) if (!(hw->mac.type == e1000_pch2lan)) {
goto out; if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
goto out;
}
cnf_size = er32(EXTCNF_SIZE); cnf_size = er32(EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK; cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
...@@ -893,7 +920,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw) ...@@ -893,7 +920,8 @@ static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT; cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) && if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
(hw->mac.type == e1000_pchlan)) { ((hw->mac.type == e1000_pchlan) ||
(hw->mac.type == e1000_pch2lan))) {
/* /*
* HW configures the SMBus address and LEDs when the * HW configures the SMBus address and LEDs when the
* OEM and LCD Write Enable bits are set in the NVM. * OEM and LCD Write Enable bits are set in the NVM.
...@@ -1100,16 +1128,18 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state) ...@@ -1100,16 +1128,18 @@ static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
u32 mac_reg; u32 mac_reg;
u16 oem_reg; u16 oem_reg;
if (hw->mac.type != e1000_pchlan) if ((hw->mac.type != e1000_pch2lan) && (hw->mac.type != e1000_pchlan))
return ret_val; return ret_val;
ret_val = hw->phy.ops.acquire(hw); ret_val = hw->phy.ops.acquire(hw);
if (ret_val) if (ret_val)
return ret_val; return ret_val;
mac_reg = er32(EXTCNF_CTRL); if (!(hw->mac.type == e1000_pch2lan)) {
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) mac_reg = er32(EXTCNF_CTRL);
goto out; if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
goto out;
}
mac_reg = er32(FEXTNVM); mac_reg = er32(FEXTNVM);
if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M)) if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
...@@ -1249,6 +1279,243 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw) ...@@ -1249,6 +1279,243 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
return ret_val; return ret_val;
} }
/**
* e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY
* @hw: pointer to the HW structure
**/
void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
{
u32 mac_reg;
u16 i;
/* 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 = er32(RAL(i));
e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
mac_reg = er32(RAH(i));
e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0x8000));
}
}
static u32 e1000_calc_rx_da_crc(u8 mac[])
{
u32 poly = 0xEDB88320; /* Polynomial for 802.3 CRC calculation */
u32 i, j, mask, crc;
crc = 0xffffffff;
for (i = 0; i < 6; i++) {
crc = crc ^ mac[i];
for (j = 8; j > 0; j--) {
mask = (crc & 1) * (-1);
crc = (crc >> 1) ^ (poly & mask);
}
}
return ~crc;
}
/**
* e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation
* with 82579 PHY
* @hw: pointer to the HW structure
* @enable: flag to enable/disable workaround when enabling/disabling jumbos
**/
s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
{
s32 ret_val = 0;
u16 phy_reg, data;
u32 mac_reg;
u16 i;
if (hw->mac.type != e1000_pch2lan)
goto out;
/* disable Rx path while enabling/disabling workaround */
e1e_rphy(hw, PHY_REG(769, 20), &phy_reg);
ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg | (1 << 14));
if (ret_val)
goto out;
if (enable) {
/*
* Write Rx addresses (rar_entry_count for RAL/H, +4 for
* SHRAL/H) and initial CRC values to the MAC
*/
for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) {
u8 mac_addr[ETH_ALEN] = {0};
u32 addr_high, addr_low;
addr_high = er32(RAH(i));
if (!(addr_high & E1000_RAH_AV))
continue;
addr_low = er32(RAL(i));
mac_addr[0] = (addr_low & 0xFF);
mac_addr[1] = ((addr_low >> 8) & 0xFF);
mac_addr[2] = ((addr_low >> 16) & 0xFF);
mac_addr[3] = ((addr_low >> 24) & 0xFF);
mac_addr[4] = (addr_high & 0xFF);
mac_addr[5] = ((addr_high >> 8) & 0xFF);
ew32(PCH_RAICC(i),
e1000_calc_rx_da_crc(mac_addr));
}
/* Write Rx addresses to the PHY */
e1000_copy_rx_addrs_to_phy_ich8lan(hw);
/* Enable jumbo frame workaround in the MAC */
mac_reg = er32(FFLT_DBG);
mac_reg &= ~(1 << 14);
mac_reg |= (7 << 15);
ew32(FFLT_DBG, mac_reg);
mac_reg = er32(RCTL);
mac_reg |= E1000_RCTL_SECRC;
ew32(RCTL, mac_reg);
ret_val = e1000e_read_kmrn_reg(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
&data);
if (ret_val)
goto out;
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
data | (1 << 0));
if (ret_val)
goto out;
ret_val = e1000e_read_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
&data);
if (ret_val)
goto out;
data &= ~(0xF << 8);
data |= (0xB << 8);
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
data);
if (ret_val)
goto out;
/* Enable jumbo frame workaround in the PHY */
e1e_rphy(hw, PHY_REG(769, 20), &data);
ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
if (ret_val)
goto out;
e1e_rphy(hw, PHY_REG(769, 23), &data);
data &= ~(0x7F << 5);
data |= (0x37 << 5);
ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
if (ret_val)
goto out;
e1e_rphy(hw, PHY_REG(769, 16), &data);
data &= ~(1 << 13);
data |= (1 << 12);
ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
if (ret_val)
goto out;
e1e_rphy(hw, PHY_REG(776, 20), &data);
data &= ~(0x3FF << 2);
data |= (0x1A << 2);
ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
if (ret_val)
goto out;
ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0xFE00);
if (ret_val)
goto out;
e1e_rphy(hw, HV_PM_CTRL, &data);
ret_val = e1e_wphy(hw, HV_PM_CTRL, data | (1 << 10));
if (ret_val)
goto out;
} else {
/* Write MAC register values back to h/w defaults */
mac_reg = er32(FFLT_DBG);
mac_reg &= ~(0xF << 14);
ew32(FFLT_DBG, mac_reg);
mac_reg = er32(RCTL);
mac_reg &= ~E1000_RCTL_SECRC;
ew32(FFLT_DBG, mac_reg);
ret_val = e1000e_read_kmrn_reg(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
&data);
if (ret_val)
goto out;
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_CTRL_OFFSET,
data & ~(1 << 0));
if (ret_val)
goto out;
ret_val = e1000e_read_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
&data);
if (ret_val)
goto out;
data &= ~(0xF << 8);
data |= (0xB << 8);
ret_val = e1000e_write_kmrn_reg(hw,
E1000_KMRNCTRLSTA_HD_CTRL,
data);
if (ret_val)
goto out;
/* Write PHY register values back to h/w defaults */
e1e_rphy(hw, PHY_REG(769, 20), &data);
ret_val = e1e_wphy(hw, PHY_REG(769, 20), data & ~(1 << 14));
if (ret_val)
goto out;
e1e_rphy(hw, PHY_REG(769, 23), &data);
data &= ~(0x7F << 5);
ret_val = e1e_wphy(hw, PHY_REG(769, 23), data);
if (ret_val)
goto out;
e1e_rphy(hw, PHY_REG(769, 16), &data);
data &= ~(1 << 12);
data |= (1 << 13);
ret_val = e1e_wphy(hw, PHY_REG(769, 16), data);
if (ret_val)
goto out;
e1e_rphy(hw, PHY_REG(776, 20), &data);
data &= ~(0x3FF << 2);
data |= (0x8 << 2);
ret_val = e1e_wphy(hw, PHY_REG(776, 20), data);
if (ret_val)
goto out;
ret_val = e1e_wphy(hw, PHY_REG(776, 23), 0x7E00);
if (ret_val)
goto out;
e1e_rphy(hw, HV_PM_CTRL, &data);
ret_val = e1e_wphy(hw, HV_PM_CTRL, data & ~(1 << 10));
if (ret_val)
goto out;
}
/* re-enable Rx path after enabling/disabling workaround */
ret_val = e1e_wphy(hw, PHY_REG(769, 20), phy_reg & ~(1 << 14));
out:
return ret_val;
}
/**
* e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be
* done after every PHY reset.
**/
static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
{
s32 ret_val = 0;
if (hw->mac.type != e1000_pch2lan)
goto out;
/* Set MDIO slow mode before any other MDIO access */
ret_val = e1000_set_mdio_slow_mode_hv(hw);
out:
return ret_val;
}
/** /**
* e1000_lan_init_done_ich8lan - Check for PHY config completion * e1000_lan_init_done_ich8lan - Check for PHY config completion
* @hw: pointer to the HW structure * @hw: pointer to the HW structure
...@@ -1300,12 +1567,17 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw) ...@@ -1300,12 +1567,17 @@ static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
if (ret_val) if (ret_val)
goto out; goto out;
break; break;
case e1000_pch2lan:
ret_val = e1000_lv_phy_workarounds_ich8lan(hw);
if (ret_val)
goto out;
break;
default: default:
break; break;
} }
/* Dummy read to clear the phy wakeup bit after lcd reset */ /* Dummy read to clear the phy wakeup bit after lcd reset */
if (hw->mac.type == e1000_pchlan) if (hw->mac.type >= e1000_pchlan)
e1e_rphy(hw, BM_WUC, &reg); e1e_rphy(hw, BM_WUC, &reg);
/* Configure the LCD with the extended configuration region in NVM */ /* Configure the LCD with the extended configuration region in NVM */
...@@ -2829,6 +3101,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw) ...@@ -2829,6 +3101,7 @@ static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
ew32(FCTTV, hw->fc.pause_time); ew32(FCTTV, hw->fc.pause_time);
if ((hw->phy.type == e1000_phy_82578) || if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) { (hw->phy.type == e1000_phy_82577)) {
ew32(FCRTV_PCH, hw->fc.refresh_time); ew32(FCRTV_PCH, hw->fc.refresh_time);
...@@ -2892,6 +3165,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw) ...@@ -2892,6 +3165,7 @@ static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
return ret_val; return ret_val;
break; break;
case e1000_phy_82577: case e1000_phy_82577:
case e1000_phy_82579:
ret_val = e1000_copper_link_setup_82577(hw); ret_val = e1000_copper_link_setup_82577(hw);
if (ret_val) if (ret_val)
return ret_val; return ret_val;
...@@ -3399,6 +3673,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw) ...@@ -3399,6 +3673,7 @@ static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
/* Clear PHY statistics registers */ /* Clear PHY statistics registers */
if ((hw->phy.type == e1000_phy_82578) || if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) { (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_UPPER, &phy_data);
hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data); hw->phy.ops.read_reg(hw, HV_SCC_LOWER, &phy_data);
...@@ -3534,3 +3809,22 @@ struct e1000_info e1000_pch_info = { ...@@ -3534,3 +3809,22 @@ struct e1000_info e1000_pch_info = {
.phy_ops = &ich8_phy_ops, .phy_ops = &ich8_phy_ops,
.nvm_ops = &ich8_nvm_ops, .nvm_ops = &ich8_nvm_ops,
}; };
struct e1000_info e1000_pch2_info = {
.mac = e1000_pch2lan,
.flags = FLAG_IS_ICH
| FLAG_HAS_WOL
| FLAG_RX_CSUM_ENABLED
| FLAG_HAS_CTRLEXT_ON_LOAD
| FLAG_HAS_AMT
| FLAG_HAS_FLASH
| FLAG_HAS_JUMBO_FRAMES
| FLAG_APME_IN_WUC,
.flags2 = FLAG2_HAS_PHY_STATS,
.pba = 18,
.max_hw_frame_size = DEFAULT_JUMBO,
.get_variants = e1000_get_variants_ich8lan,
.mac_ops = &ich8_mac_ops,
.phy_ops = &ich8_phy_ops,
.nvm_ops = &ich8_nvm_ops,
};
...@@ -67,6 +67,7 @@ static const struct e1000_info *e1000_info_tbl[] = { ...@@ -67,6 +67,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
[board_ich9lan] = &e1000_ich9_info, [board_ich9lan] = &e1000_ich9_info,
[board_ich10lan] = &e1000_ich10_info, [board_ich10lan] = &e1000_ich10_info,
[board_pchlan] = &e1000_pch_info, [board_pchlan] = &e1000_pch_info,
[board_pch2lan] = &e1000_pch2_info,
}; };
struct e1000_reg_info { struct e1000_reg_info {
...@@ -2723,6 +2724,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter) ...@@ -2723,6 +2724,16 @@ static void e1000_setup_rctl(struct e1000_adapter *adapter)
e1e_wphy(hw, 22, phy_data); e1e_wphy(hw, 22, phy_data);
} }
/* Workaround Si errata on 82579 - configure jumbo frame flow */
if (hw->mac.type == e1000_pch2lan) {
s32 ret_val;
if (rctl & E1000_RCTL_LPE)
ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, true);
else
ret_val = e1000_lv_jumbo_workaround_ich8lan(hw, false);
}
/* Setup buffer sizes */ /* Setup buffer sizes */
rctl &= ~E1000_RCTL_SZ_4096; rctl &= ~E1000_RCTL_SZ_4096;
rctl |= E1000_RCTL_BSEX; rctl |= E1000_RCTL_BSEX;
...@@ -3118,7 +3129,27 @@ void e1000e_reset(struct e1000_adapter *adapter) ...@@ -3118,7 +3129,27 @@ void e1000e_reset(struct e1000_adapter *adapter)
* with ERT support assuming ERT set to E1000_ERT_2048), or * with ERT support assuming ERT set to E1000_ERT_2048), or
* - the full Rx FIFO size minus one full frame * - the full Rx FIFO size minus one full frame
*/ */
if (hw->mac.type == e1000_pchlan) { if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
fc->pause_time = 0xFFFF;
else
fc->pause_time = E1000_FC_PAUSE_TIME;
fc->send_xon = 1;
fc->current_mode = fc->requested_mode;
switch (hw->mac.type) {
default:
if ((adapter->flags & FLAG_HAS_ERT) &&
(adapter->netdev->mtu > ETH_DATA_LEN))
hwm = min(((pba << 10) * 9 / 10),
((pba << 10) - (E1000_ERT_2048 << 3)));
else
hwm = min(((pba << 10) * 9 / 10),
((pba << 10) - adapter->max_frame_size));
fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
fc->low_water = fc->high_water - 8;
break;
case e1000_pchlan:
/* /*
* Workaround PCH LOM adapter hangs with certain network * Workaround PCH LOM adapter hangs with certain network
* loads. If hangs persist, try disabling Tx flow control. * loads. If hangs persist, try disabling Tx flow control.
...@@ -3131,26 +3162,15 @@ void e1000e_reset(struct e1000_adapter *adapter) ...@@ -3131,26 +3162,15 @@ void e1000e_reset(struct e1000_adapter *adapter)
fc->low_water = 0x3000; fc->low_water = 0x3000;
} }
fc->refresh_time = 0x1000; fc->refresh_time = 0x1000;
} else { break;
if ((adapter->flags & FLAG_HAS_ERT) && case e1000_pch2lan:
(adapter->netdev->mtu > ETH_DATA_LEN)) fc->high_water = 0x05C20;
hwm = min(((pba << 10) * 9 / 10), fc->low_water = 0x05048;
((pba << 10) - (E1000_ERT_2048 << 3))); fc->pause_time = 0x0650;
else fc->refresh_time = 0x0400;
hwm = min(((pba << 10) * 9 / 10), break;
((pba << 10) - adapter->max_frame_size));
fc->high_water = hwm & E1000_FCRTH_RTH; /* 8-byte granularity */
fc->low_water = fc->high_water - 8;
} }
if (adapter->flags & FLAG_DISABLE_FC_PAUSE_TIME)
fc->pause_time = 0xFFFF;
else
fc->pause_time = E1000_FC_PAUSE_TIME;
fc->send_xon = 1;
fc->current_mode = fc->requested_mode;
/* Allow time for pending master requests to run */ /* Allow time for pending master requests to run */
mac->ops.reset_hw(hw); mac->ops.reset_hw(hw);
...@@ -4918,14 +4938,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc) ...@@ -4918,14 +4938,7 @@ static int e1000_init_phy_wakeup(struct e1000_adapter *adapter, u32 wufc)
int retval = 0; int retval = 0;
/* copy MAC RARs to PHY RARs */ /* copy MAC RARs to PHY RARs */
for (i = 0; i < adapter->hw.mac.rar_entry_count; i++) { e1000_copy_rx_addrs_to_phy_ich8lan(hw);
mac_reg = er32(RAL(i));
e1e_wphy(hw, BM_RAR_L(i), (u16)(mac_reg & 0xFFFF));
e1e_wphy(hw, BM_RAR_M(i), (u16)((mac_reg >> 16) & 0xFFFF));
mac_reg = er32(RAH(i));
e1e_wphy(hw, BM_RAR_H(i), (u16)(mac_reg & 0xFFFF));
e1e_wphy(hw, BM_RAR_CTRL(i), (u16)((mac_reg >> 16) & 0xFFFF));
}
/* copy MAC MTA to PHY MTA */ /* copy MAC MTA to PHY MTA */
for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) { for (i = 0; i < adapter->hw.mac.mta_reg_count; i++) {
...@@ -5976,6 +5989,9 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = { ...@@ -5976,6 +5989,9 @@ static DEFINE_PCI_DEVICE_TABLE(e1000_pci_tbl) = {
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DM), board_pchlan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan }, { PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH_D_HV_DC), board_pchlan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_LM), board_pch2lan },
{ PCI_VDEVICE(INTEL, E1000_DEV_ID_PCH2_LV_V), board_pch2lan },
{ } /* terminate list */ { } /* terminate list */
}; };
MODULE_DEVICE_TABLE(pci, e1000_pci_tbl); MODULE_DEVICE_TABLE(pci, e1000_pci_tbl);
......
...@@ -2319,6 +2319,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id) ...@@ -2319,6 +2319,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
case I82577_E_PHY_ID: case I82577_E_PHY_ID:
phy_type = e1000_phy_82577; phy_type = e1000_phy_82577;
break; break;
case I82579_E_PHY_ID:
phy_type = e1000_phy_82579;
break;
default: default:
phy_type = e1000_phy_unknown; phy_type = e1000_phy_unknown;
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment