Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[e1000e] Basic 82579 support
Add support for 82579-based chips such as those found on Sandy Bridge
motherboards.  Based on d3738bb8203acf8552c3ec8b3447133fc0938ddd in
Linux.

Signed-off-by: Daniel Hokka Zakrisson <daniel@hozac.com>
Signed-off-by: Michael Brown <mcb30@ipxe.org>
  • Loading branch information
dhozac authored and mcb30 committed Apr 10, 2012
1 parent dcccb1f commit 0e4a5ca
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 15 deletions.
2 changes: 2 additions & 0 deletions src/drivers/net/e1000e/e1000e.h
Expand Up @@ -143,6 +143,7 @@ enum e1000_boards {
board_ich9lan,
board_ich10lan,
board_pchlan,
board_pch2lan,
board_82583,
};

Expand Down Expand Up @@ -300,6 +301,7 @@ extern void e1000e_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
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_disable_gig_wol_ich8lan(struct e1000_hw *hw);
extern s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable);

extern s32 e1000e_check_for_copper_link(struct e1000_hw *hw);
extern s32 e1000e_check_for_fiber_link(struct e1000_hw *hw);
Expand Down
2 changes: 2 additions & 0 deletions src/drivers/net/e1000e/e1000e_defines.h
Expand Up @@ -675,6 +675,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE 0x00000001
#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE 0x00000008
#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_SHIFT 16
#define E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK 0x0FFF0000
Expand Down Expand Up @@ -1261,6 +1262,7 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define BME1000_E_PHY_ID_R2 0x01410CB1
#define I82577_E_PHY_ID 0x01540050
#define I82578_E_PHY_ID 0x004DD040
#define I82579_E_PHY_ID 0x01540090
#define M88_VENDOR 0x0141

/* M88E1000 Specific Registers */
Expand Down
4 changes: 4 additions & 0 deletions src/drivers/net/e1000e/e1000e_hw.h
Expand Up @@ -85,6 +85,8 @@ struct e1000_hw;
#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_DC 0x10F0
#define E1000_DEV_ID_PCH2_LV_LM 0x1502
#define E1000_DEV_ID_PCH2_LV_V 0x1503
#define E1000_REVISION_0 0
#define E1000_REVISION_1 1
#define E1000_REVISION_2 2
Expand All @@ -109,6 +111,7 @@ enum e1000_mac_type {
e1000_ich9lan,
e1000_ich10lan,
e1000_pchlan,
e1000_pch2lan,
e1000_num_macs /* List is 1-based, so subtract 1 for true count. */
};

Expand Down Expand Up @@ -146,6 +149,7 @@ enum e1000_phy_type {
e1000_phy_bm,
e1000_phy_82578,
e1000_phy_82577,
e1000_phy_82579,
};

enum e1000_bus_type {
Expand Down
51 changes: 36 additions & 15 deletions src/drivers/net/e1000e/e1000e_ich8lan.c
Expand Up @@ -206,7 +206,7 @@ static s32 e1000e_init_phy_params_pchlan(struct e1000_hw *hw)
e1000e_get_phy_id(hw);
phy->type = e1000e_get_phy_type_from_id(phy->id);

if (phy->type == e1000_phy_82577) {
if (phy->type == e1000_phy_82577 || phy->type == e1000_phy_82579) {
phy->ops.check_polarity = e1000e_check_polarity_82577;
#if 0
phy->ops.force_speed_duplex =
Expand Down Expand Up @@ -449,6 +449,7 @@ static s32 e1000e_init_mac_params_ich8lan(struct e1000_hw *hw)
mac->ops.led_off = e1000e_led_off_ich8lan;
break;
case e1000_pchlan:
case e1000_pch2lan:
/* ID LED init */
mac->ops.id_led_init = e1000e_id_led_init_pchlan;
/* setup LED */
Expand All @@ -467,6 +468,14 @@ static s32 e1000e_init_mac_params_ich8lan(struct e1000_hw *hw)
if (mac->type == e1000_ich8lan)
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 E1000_SUCCESS;
}
Expand Down Expand Up @@ -577,6 +586,7 @@ void e1000e_init_function_pointers_ich8lan(struct e1000_hw *hw)
hw->phy.ops.init_params = e1000e_init_phy_params_ich8lan;
break;
case e1000_pchlan:
case e1000_pch2lan:
hw->phy.ops.init_params = e1000e_init_phy_params_pchlan;
break;
default:
Expand Down Expand Up @@ -765,7 +775,8 @@ static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw)
/* Check if SW needs to configure the PHY */
if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
(hw->device_id == E1000_DEV_ID_ICH8_IGP_M) ||
(hw->mac.type == e1000_pchlan))
(hw->mac.type == e1000_pchlan) ||
(hw->mac.type == e1000_pch2lan))
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
else
sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
Expand All @@ -777,13 +788,15 @@ static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw)
/* Wait for basic configuration completes before proceeding */
e1000e_lan_init_done_ich8lan(hw);

/*
* Make sure HW does not configure LCD from PHY
* extended configuration before SW configuration
*/
data = er32(EXTCNF_CTRL);
if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
goto out;
if (hw->mac.type != e1000_pch2lan) {
/*
* Make sure HW does not configure LCD from PHY
* extended configuration before SW configuration
*/
data = er32(EXTCNF_CTRL);
if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
goto out;
}

cnf_size = er32(EXTCNF_SIZE);
cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
Expand All @@ -795,7 +808,8 @@ static s32 e1000e_sw_lcd_config_ich8lan(struct e1000_hw *hw)
cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;

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
* OEM and LCD Write Enable bits are set in the NVM.
Expand Down Expand Up @@ -1006,16 +1020,18 @@ s32 e1000e_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
u32 mac_reg;
u16 oem_reg;

if (hw->mac.type != e1000_pchlan)
if (hw->mac.type != e1000_pchlan && hw->mac.type != e1000_pch2lan)
return ret_val;

ret_val = hw->phy.ops.acquire(hw);
if (ret_val)
return ret_val;

mac_reg = er32(EXTCNF_CTRL);
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
goto out;
if (hw->mac.type != e1000_pch2lan) {
mac_reg = er32(EXTCNF_CTRL);
if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
goto out;
}

mac_reg = er32(FEXTNVM);
if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
Expand Down Expand Up @@ -2573,7 +2589,7 @@ static s32 e1000e_reset_hw_ich8lan(struct e1000_hw *hw)
}
}
/* Dummy read to clear the phy wakeup bit after lcd reset */
if (hw->mac.type == e1000_pchlan)
if (hw->mac.type == e1000_pchlan || hw->mac.type == e1000_pch2lan)
e1e_rphy(hw, BM_WUC, &reg);

ret_val = e1000e_sw_lcd_config_ich8lan(hw);
Expand Down Expand Up @@ -2791,6 +2807,7 @@ static s32 e1000e_setup_link_ich8lan(struct e1000_hw *hw)

ew32(FCTTV, hw->fc.pause_time);
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) {
ret_val = e1e_wphy(hw,
PHY_REG(BM_PORT_CTRL_PAGE, 27),
Expand Down Expand Up @@ -2859,6 +2876,7 @@ static s32 e1000e_setup_copper_link_ich8lan(struct e1000_hw *hw)
goto out;
break;
case e1000_phy_82577:
case e1000_phy_82579:
ret_val = e1000e_copper_link_setup_82577(hw);
if (ret_val)
goto out;
Expand Down Expand Up @@ -3388,6 +3406,7 @@ static void e1000e_clear_hw_cntrs_ich8lan(struct e1000_hw *hw __unused)

/* Clear PHY statistics registers */
if ((hw->phy.type == e1000_phy_82578) ||
(hw->phy.type == e1000_phy_82579) ||
(hw->phy.type == e1000_phy_82577)) {
e1e_rphy(hw, HV_SCC_UPPER, &phy_data);
e1e_rphy(hw, HV_SCC_LOWER, &phy_data);
Expand Down Expand Up @@ -3434,6 +3453,8 @@ static struct pci_device_id e1000e_ich8lan_nics[] = {
PCI_ROM(0x8086, 0x10EB, "E1000_DEV_ID_PCH_M_HV_LC", "E1000_DEV_ID_PCH_M_HV_LC", board_pchlan),
PCI_ROM(0x8086, 0x10EF, "E1000_DEV_ID_PCH_D_HV_DM", "E1000_DEV_ID_PCH_D_HV_DM", board_pchlan),
PCI_ROM(0x8086, 0x10F0, "E1000_DEV_ID_PCH_D_HV_DC", "E1000_DEV_ID_PCH_D_HV_DC", board_pchlan),
PCI_ROM(0x8086, 0x1502, "E1000_DEV_ID_PCH2_LV_LM", "E1000_DEV_ID_PCH2_LV_LM", board_pch2lan),
PCI_ROM(0x8086, 0x1503, "E1000_DEV_ID_PCH2_LV_V", "E1000_DEV_ID_PCH2_LV_V", board_pch2lan),
};

struct pci_driver e1000e_ich8lan_driver __pci_driver = {
Expand Down
3 changes: 3 additions & 0 deletions src/drivers/net/e1000e/e1000e_ich8lan.h
Expand Up @@ -146,6 +146,9 @@ FILE_LICENCE ( GPL2_OR_LATER );
#define HV_SMB_ADDR_PEC_EN 0x0200
#define HV_SMB_ADDR_VALID 0x0080

/* PHY Power Management Control */
#define HV_PM_CTRL PHY_REG(770, 17)

/* Strapping Option Register - RO */
#define E1000_STRAP 0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK 0x00FE0000
Expand Down
17 changes: 17 additions & 0 deletions src/drivers/net/e1000e/e1000e_main.c
Expand Up @@ -279,6 +279,22 @@ static struct e1000_info e1000_pch_info = {
.get_variants = e1000e_get_variants_ich8lan,
};

static 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,
.pba = 26,
.max_hw_frame_size = DEFAULT_JUMBO,
.init_ops = e1000e_init_function_pointers_ich8lan,
.get_variants = e1000e_get_variants_ich8lan,
};

static const struct e1000_info *e1000_info_tbl[] = {
[board_82571] = &e1000_82571_info,
[board_82572] = &e1000_82572_info,
Expand All @@ -290,6 +306,7 @@ static const struct e1000_info *e1000_info_tbl[] = {
[board_ich9lan] = &e1000_ich9_info,
[board_ich10lan] = &e1000_ich10_info,
[board_pchlan] = &e1000_pch_info,
[board_pch2lan] = &e1000_pch2_info,
};

/* Low-level support routines */
Expand Down
3 changes: 3 additions & 0 deletions src/drivers/net/e1000e/e1000e_phy.c
Expand Up @@ -2332,6 +2332,9 @@ enum e1000_phy_type e1000e_get_phy_type_from_id(u32 phy_id)
case I82577_E_PHY_ID:
phy_type = e1000_phy_82577;
break;
case I82579_E_PHY_ID:
phy_type = e1000_phy_82579;
break;
default:
phy_type = e1000_phy_unknown;
break;
Expand Down

0 comments on commit 0e4a5ca

Please sign in to comment.