Skip to content

Commit

Permalink
e1000e: add support for new 82574L part
Browse files Browse the repository at this point in the history
This new part has the same feature set as previous parts with the addition
of MSI-X support.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
  • Loading branch information
Bruce Allan authored and Jeff Garzik committed Sep 3, 2008
1 parent f4187b5 commit 4662e82
Show file tree
Hide file tree
Showing 11 changed files with 738 additions and 77 deletions.
153 changes: 140 additions & 13 deletions drivers/net/e1000e/82571.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
* 82573V Gigabit Ethernet Controller (Copper)
* 82573E Gigabit Ethernet Controller (Copper)
* 82573L Gigabit Ethernet Controller
* 82574L Gigabit Network Connection
*/

#include <linux/netdevice.h>
Expand All @@ -54,6 +55,8 @@

#define E1000_GCR_L1_ACT_WITHOUT_L0S_RX 0x08000000

#define E1000_NVM_INIT_CTRL2_MNGM 0x6000 /* Manageability Operation Mode mask */

static s32 e1000_get_phy_id_82571(struct e1000_hw *hw);
static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw);
static s32 e1000_setup_fiber_serdes_link_82571(struct e1000_hw *hw);
Expand All @@ -63,6 +66,8 @@ static s32 e1000_fix_nvm_checksum_82571(struct e1000_hw *hw);
static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw);
static s32 e1000_setup_link_82571(struct e1000_hw *hw);
static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw);
static bool e1000_check_mng_mode_82574(struct e1000_hw *hw);
static s32 e1000_led_on_82574(struct e1000_hw *hw);

/**
* e1000_init_phy_params_82571 - Init PHY func ptrs.
Expand Down Expand Up @@ -92,6 +97,9 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
case e1000_82573:
phy->type = e1000_phy_m88;
break;
case e1000_82574:
phy->type = e1000_phy_bm;
break;
default:
return -E1000_ERR_PHY;
break;
Expand All @@ -111,6 +119,10 @@ static s32 e1000_init_phy_params_82571(struct e1000_hw *hw)
if (phy->id != M88E1111_I_PHY_ID)
return -E1000_ERR_PHY;
break;
case e1000_82574:
if (phy->id != BME1000_E_PHY_ID_R2)
return -E1000_ERR_PHY;
break;
default:
return -E1000_ERR_PHY;
break;
Expand Down Expand Up @@ -150,6 +162,7 @@ static s32 e1000_init_nvm_params_82571(struct e1000_hw *hw)

switch (hw->mac.type) {
case e1000_82573:
case e1000_82574:
if (((eecd >> 15) & 0x3) == 0x3) {
nvm->type = e1000_nvm_flash_hw;
nvm->word_size = 2048;
Expand Down Expand Up @@ -245,6 +258,17 @@ static s32 e1000_init_mac_params_82571(struct e1000_adapter *adapter)
break;
}

switch (hw->mac.type) {
case e1000_82574:
func->check_mng_mode = e1000_check_mng_mode_82574;
func->led_on = e1000_led_on_82574;
break;
default:
func->check_mng_mode = e1000e_check_mng_mode_generic;
func->led_on = e1000e_led_on_generic;
break;
}

return 0;
}

Expand Down Expand Up @@ -330,6 +354,8 @@ static s32 e1000_get_variants_82571(struct e1000_adapter *adapter)
static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
{
struct e1000_phy_info *phy = &hw->phy;
s32 ret_val;
u16 phy_id = 0;

switch (hw->mac.type) {
case e1000_82571:
Expand All @@ -345,6 +371,20 @@ static s32 e1000_get_phy_id_82571(struct e1000_hw *hw)
case e1000_82573:
return e1000e_get_phy_id(hw);
break;
case e1000_82574:
ret_val = e1e_rphy(hw, PHY_ID1, &phy_id);
if (ret_val)
return ret_val;

phy->id = (u32)(phy_id << 16);
udelay(20);
ret_val = e1e_rphy(hw, PHY_ID2, &phy_id);
if (ret_val)
return ret_val;

phy->id |= (u32)(phy_id);
phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
break;
default:
return -E1000_ERR_PHY;
break;
Expand Down Expand Up @@ -421,7 +461,7 @@ static s32 e1000_acquire_nvm_82571(struct e1000_hw *hw)
if (ret_val)
return ret_val;

if (hw->mac.type != e1000_82573)
if (hw->mac.type != e1000_82573 && hw->mac.type != e1000_82574)
ret_val = e1000e_acquire_nvm(hw);

if (ret_val)
Expand Down Expand Up @@ -461,6 +501,7 @@ static s32 e1000_write_nvm_82571(struct e1000_hw *hw, u16 offset, u16 words,

switch (hw->mac.type) {
case e1000_82573:
case e1000_82574:
ret_val = e1000_write_nvm_eewr_82571(hw, offset, words, data);
break;
case e1000_82571:
Expand Down Expand Up @@ -735,7 +776,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Must acquire the MDIO ownership before MAC reset.
* Ownership defaults to firmware after a reset.
*/
if (hw->mac.type == e1000_82573) {
if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
extcnf_ctrl = er32(EXTCNF_CTRL);
extcnf_ctrl |= E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP;

Expand Down Expand Up @@ -776,7 +817,7 @@ static s32 e1000_reset_hw_82571(struct e1000_hw *hw)
* Need to wait for Phy configuration completion before accessing
* NVM and Phy.
*/
if (hw->mac.type == e1000_82573)
if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574)
msleep(25);

/* Clear any pending interrupt events. */
Expand Down Expand Up @@ -843,7 +884,7 @@ static s32 e1000_init_hw_82571(struct e1000_hw *hw)
ew32(TXDCTL(0), reg_data);

/* ...for both queues. */
if (mac->type != e1000_82573) {
if (mac->type != e1000_82573 && mac->type != e1000_82574) {
reg_data = er32(TXDCTL(1));
reg_data = (reg_data & ~E1000_TXDCTL_WTHRESH) |
E1000_TXDCTL_FULL_TX_DESC_WB |
Expand Down Expand Up @@ -918,19 +959,28 @@ static void e1000_initialize_hw_bits_82571(struct e1000_hw *hw)
}

/* Device Control */
if (hw->mac.type == e1000_82573) {
if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
reg = er32(CTRL);
reg &= ~(1 << 29);
ew32(CTRL, reg);
}

/* Extended Device Control */
if (hw->mac.type == e1000_82573) {
if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
reg = er32(CTRL_EXT);
reg &= ~(1 << 23);
reg |= (1 << 22);
ew32(CTRL_EXT, reg);
}

/* PCI-Ex Control Register */
if (hw->mac.type == e1000_82574) {
reg = er32(GCR);
reg |= (1 << 22);
ew32(GCR, reg);
}

return;
}

/**
Expand All @@ -947,7 +997,7 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
u32 vfta_offset = 0;
u32 vfta_bit_in_reg = 0;

if (hw->mac.type == e1000_82573) {
if (hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) {
if (hw->mng_cookie.vlan_id != 0) {
/*
* The VFTA is a 4096b bit-field, each identifying
Expand Down Expand Up @@ -975,6 +1025,48 @@ void e1000e_clear_vfta(struct e1000_hw *hw)
}
}

/**
* e1000_check_mng_mode_82574 - Check manageability is enabled
* @hw: pointer to the HW structure
*
* Reads the NVM Initialization Control Word 2 and returns true
* (>0) if any manageability is enabled, else false (0).
**/
static bool e1000_check_mng_mode_82574(struct e1000_hw *hw)
{
u16 data;

e1000_read_nvm(hw, NVM_INIT_CONTROL2_REG, 1, &data);
return (data & E1000_NVM_INIT_CTRL2_MNGM) != 0;
}

/**
* e1000_led_on_82574 - Turn LED on
* @hw: pointer to the HW structure
*
* Turn LED on.
**/
static s32 e1000_led_on_82574(struct e1000_hw *hw)
{
u32 ctrl;
u32 i;

ctrl = hw->mac.ledctl_mode2;
if (!(E1000_STATUS_LU & er32(STATUS))) {
/*
* If no link, then turn LED on by setting the invert bit
* for each LED that's "on" (0x0E) in ledctl_mode2.
*/
for (i = 0; i < 4; i++)
if (((hw->mac.ledctl_mode2 >> (i * 8)) & 0xFF) ==
E1000_LEDCTL_MODE_LED_ON)
ctrl |= (E1000_LEDCTL_LED0_IVRT << (i * 8));
}
ew32(LEDCTL, ctrl);

return 0;
}

/**
* e1000_update_mc_addr_list_82571 - Update Multicast addresses
* @hw: pointer to the HW structure
Expand Down Expand Up @@ -1018,7 +1110,8 @@ static s32 e1000_setup_link_82571(struct e1000_hw *hw)
* the default flow control setting, so we explicitly
* set it to full.
*/
if (hw->mac.type == e1000_82573)
if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
hw->fc.type == e1000_fc_default)
hw->fc.type = e1000_fc_full;

return e1000e_setup_link(hw);
Expand All @@ -1045,6 +1138,7 @@ static s32 e1000_setup_copper_link_82571(struct e1000_hw *hw)

switch (hw->phy.type) {
case e1000_phy_m88:
case e1000_phy_bm:
ret_val = e1000e_copper_link_setup_m88(hw);
break;
case e1000_phy_igp_2:
Expand Down Expand Up @@ -1114,11 +1208,10 @@ static s32 e1000_valid_led_default_82571(struct e1000_hw *hw, u16 *data)
return ret_val;
}

if (hw->mac.type == e1000_82573 &&
if ((hw->mac.type == e1000_82573 || hw->mac.type == e1000_82574) &&
*data == ID_LED_RESERVED_F746)
*data = ID_LED_DEFAULT_82573;
else if (*data == ID_LED_RESERVED_0000 ||
*data == ID_LED_RESERVED_FFFF)
else if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
*data = ID_LED_DEFAULT;

return 0;
Expand Down Expand Up @@ -1265,13 +1358,13 @@ static void e1000_clear_hw_cntrs_82571(struct e1000_hw *hw)
}

static struct e1000_mac_operations e82571_mac_ops = {
.mng_mode_enab = E1000_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT,
/* .check_mng_mode: mac type dependent */
/* .check_for_link: media type dependent */
.cleanup_led = e1000e_cleanup_led_generic,
.clear_hw_cntrs = e1000_clear_hw_cntrs_82571,
.get_bus_info = e1000e_get_bus_info_pcie,
/* .get_link_up_info: media type dependent */
.led_on = e1000e_led_on_generic,
/* .led_on: mac type dependent */
.led_off = e1000e_led_off_generic,
.update_mc_addr_list = e1000_update_mc_addr_list_82571,
.reset_hw = e1000_reset_hw_82571,
Expand Down Expand Up @@ -1312,6 +1405,22 @@ static struct e1000_phy_operations e82_phy_ops_m88 = {
.write_phy_reg = e1000e_write_phy_reg_m88,
};

static struct e1000_phy_operations e82_phy_ops_bm = {
.acquire_phy = e1000_get_hw_semaphore_82571,
.check_reset_block = e1000e_check_reset_block_generic,
.commit_phy = e1000e_phy_sw_reset,
.force_speed_duplex = e1000e_phy_force_speed_duplex_m88,
.get_cfg_done = e1000e_get_cfg_done,
.get_cable_length = e1000e_get_cable_length_m88,
.get_phy_info = e1000e_get_phy_info_m88,
.read_phy_reg = e1000e_read_phy_reg_bm2,
.release_phy = e1000_put_hw_semaphore_82571,
.reset_phy = e1000e_phy_hw_reset_generic,
.set_d0_lplu_state = e1000_set_d0_lplu_state_82571,
.set_d3_lplu_state = e1000e_set_d3_lplu_state,
.write_phy_reg = e1000e_write_phy_reg_bm2,
};

static struct e1000_nvm_operations e82571_nvm_ops = {
.acquire_nvm = e1000_acquire_nvm_82571,
.read_nvm = e1000e_read_nvm_eerd,
Expand Down Expand Up @@ -1375,3 +1484,21 @@ struct e1000_info e1000_82573_info = {
.nvm_ops = &e82571_nvm_ops,
};

struct e1000_info e1000_82574_info = {
.mac = e1000_82574,
.flags = FLAG_HAS_HW_VLAN_FILTER
| FLAG_HAS_MSIX
| FLAG_HAS_JUMBO_FRAMES
| FLAG_HAS_WOL
| FLAG_APME_IN_CTRL3
| FLAG_RX_CSUM_ENABLED
| FLAG_HAS_SMART_POWER_DOWN
| FLAG_HAS_AMT
| FLAG_HAS_CTRLEXT_ON_LOAD,
.pba = 20,
.get_variants = e1000_get_variants_82571,
.mac_ops = &e82571_mac_ops,
.phy_ops = &e82_phy_ops_bm,
.nvm_ops = &e82571_nvm_ops,
};

13 changes: 13 additions & 0 deletions drivers/net/e1000e/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,11 @@
#define E1000_CTRL_EXT_RO_DIS 0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES 0x00C00000
#define E1000_CTRL_EXT_EIAME 0x01000000
#define E1000_CTRL_EXT_DRV_LOAD 0x10000000 /* Driver loaded bit for FW */
#define E1000_CTRL_EXT_IAME 0x08000000 /* Interrupt acknowledge Auto-mask */
#define E1000_CTRL_EXT_INT_TIMER_CLR 0x20000000 /* Clear Interrupt timers after IMS clear */
#define E1000_CTRL_EXT_PBA_CLR 0x80000000 /* PBA Clear */

/* Receive Descriptor bit definitions */
#define E1000_RXD_STAT_DD 0x01 /* Descriptor Done */
Expand Down Expand Up @@ -299,6 +301,7 @@
#define E1000_RXCSUM_IPPCSE 0x00001000 /* IP payload checksum enable */

/* Header split receive */
#define E1000_RFCTL_ACK_DIS 0x00001000
#define E1000_RFCTL_EXTEN 0x00008000
#define E1000_RFCTL_IPV6_EX_DIS 0x00010000
#define E1000_RFCTL_NEW_IPV6_EXT_DIS 0x00020000
Expand Down Expand Up @@ -363,6 +366,11 @@
#define E1000_ICR_RXDMT0 0x00000010 /* Rx desc min. threshold (0) */
#define E1000_ICR_RXT0 0x00000080 /* Rx timer intr (ring 0) */
#define E1000_ICR_INT_ASSERTED 0x80000000 /* If this bit asserted, the driver should claim the interrupt */
#define E1000_ICR_RXQ0 0x00100000 /* Rx Queue 0 Interrupt */
#define E1000_ICR_RXQ1 0x00200000 /* Rx Queue 1 Interrupt */
#define E1000_ICR_TXQ0 0x00400000 /* Tx Queue 0 Interrupt */
#define E1000_ICR_TXQ1 0x00800000 /* Tx Queue 1 Interrupt */
#define E1000_ICR_OTHER 0x01000000 /* Other Interrupts */

/*
* This defines the bits that are set in the Interrupt Mask
Expand All @@ -386,6 +394,11 @@
#define E1000_IMS_RXSEQ E1000_ICR_RXSEQ /* Rx sequence error */
#define E1000_IMS_RXDMT0 E1000_ICR_RXDMT0 /* Rx desc min. threshold */
#define E1000_IMS_RXT0 E1000_ICR_RXT0 /* Rx timer intr */
#define E1000_IMS_RXQ0 E1000_ICR_RXQ0 /* Rx Queue 0 Interrupt */
#define E1000_IMS_RXQ1 E1000_ICR_RXQ1 /* Rx Queue 1 Interrupt */
#define E1000_IMS_TXQ0 E1000_ICR_TXQ0 /* Tx Queue 0 Interrupt */
#define E1000_IMS_TXQ1 E1000_ICR_TXQ1 /* Tx Queue 1 Interrupt */
#define E1000_IMS_OTHER E1000_ICR_OTHER /* Other Interrupts */

/* Interrupt Cause Set */
#define E1000_ICS_LSC E1000_ICR_LSC /* Link Status Change */
Expand Down
Loading

0 comments on commit 4662e82

Please sign in to comment.