diff options
Diffstat (limited to 'sys/dev/e1000/e1000_82575.c')
-rw-r--r-- | sys/dev/e1000/e1000_82575.c | 195 |
1 files changed, 110 insertions, 85 deletions
diff --git a/sys/dev/e1000/e1000_82575.c b/sys/dev/e1000/e1000_82575.c index 75fe0a4..a04e3fa 100644 --- a/sys/dev/e1000/e1000_82575.c +++ b/sys/dev/e1000/e1000_82575.c @@ -1,6 +1,6 @@ /****************************************************************************** - Copyright (c) 2001-2011, Intel Corporation + Copyright (c) 2001-2012, Intel Corporation All rights reserved. Redistribution and use in source and binary forms, with or without @@ -38,9 +38,12 @@ * 82575GB Gigabit Network Connection * 82576 Gigabit Network Connection * 82576 Quad Port Gigabit Mezzanine Adapter + * 82580 Gigabit Network Connection + * I350 Gigabit Network Connection */ #include "e1000_api.h" +#include "e1000_i210.h" static s32 e1000_init_phy_params_82575(struct e1000_hw *hw); static s32 e1000_init_mac_params_82575(struct e1000_hw *hw); @@ -162,6 +165,9 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) DEBUGFUNC("e1000_init_phy_params_82575"); + phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic; + phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic; + if (hw->phy.media_type != e1000_media_type_copper) { phy->type = e1000_phy_none; goto out; @@ -195,12 +201,22 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) { phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; - } else if (hw->mac.type >= e1000_82580) { - phy->ops.read_reg = e1000_read_phy_reg_82580; - phy->ops.write_reg = e1000_write_phy_reg_82580; } else { - phy->ops.read_reg = e1000_read_phy_reg_igp; - phy->ops.write_reg = e1000_write_phy_reg_igp; + switch (hw->mac.type) { + case e1000_82580: + case e1000_i350: + phy->ops.read_reg = e1000_read_phy_reg_82580; + phy->ops.write_reg = e1000_write_phy_reg_82580; + break; + case e1000_i210: + case e1000_i211: + phy->ops.read_reg = e1000_read_phy_reg_gs40g; + phy->ops.write_reg = e1000_write_phy_reg_gs40g; + break; + default: + phy->ops.read_reg = e1000_read_phy_reg_igp; + phy->ops.write_reg = e1000_write_phy_reg_igp; + } } /* Set phy->phy_addr and phy->id. */ @@ -245,6 +261,15 @@ static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; break; + case I210_I_PHY_ID: + phy->type = e1000_phy_i210; + phy->ops.check_polarity = e1000_check_polarity_m88; + phy->ops.get_info = e1000_get_phy_info_m88; + phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; + phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; + phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; + phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; + break; default: ret_val = -E1000_ERR_PHY; goto out; @@ -281,28 +306,32 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) size = 15; nvm->word_size = 1 << size; - nvm->opcode_bits = 8; - nvm->delay_usec = 1; - switch (nvm->override) { - case e1000_nvm_override_spi_large: - nvm->page_size = 32; - nvm->address_bits = 16; - break; - case e1000_nvm_override_spi_small: - nvm->page_size = 8; - nvm->address_bits = 8; - break; - default: - nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; - nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8; - break; - } - - nvm->type = e1000_nvm_eeprom_spi; - - if (nvm->word_size == (1 << 15)) - nvm->page_size = 128; + if (hw->mac.type < e1000_i210) { + nvm->opcode_bits = 8; + nvm->delay_usec = 1; + + switch (nvm->override) { + case e1000_nvm_override_spi_large: + nvm->page_size = 32; + nvm->address_bits = 16; + break; + case e1000_nvm_override_spi_small: + nvm->page_size = 8; + nvm->address_bits = 8; + break; + default: + nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; + nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? + 16 : 8; + break; + } + if (nvm->word_size == (1 << 15)) + nvm->page_size = 128; + nvm->type = e1000_nvm_eeprom_spi; + } else { + nvm->type = e1000_nvm_flash_hw; + } /* Function Pointers */ nvm->ops.acquire = e1000_acquire_nvm_82575; nvm->ops.release = e1000_release_nvm_82575; @@ -316,7 +345,7 @@ s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) nvm->ops.update = e1000_update_nvm_checksum_generic; nvm->ops.valid_led_default = e1000_valid_led_default_82575; - /* override genric family function pointers for specific descendants */ + /* override generic family function pointers for specific descendants */ switch (hw->mac.type) { case e1000_82580: nvm->ops.validate = e1000_validate_nvm_checksum_82580; @@ -368,8 +397,7 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->has_fwsm = TRUE; /* ARC supported; valid only if manageability features are enabled. */ mac->arc_subsystem_valid = - (E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK) - ? TRUE : FALSE; + !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); /* Function pointers */ @@ -394,8 +422,6 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; /* check for link */ mac->ops.check_for_link = e1000_check_for_link_82575; - /* receive address register setting */ - mac->ops.rar_set = e1000_rar_set_generic; /* read mac address */ mac->ops.read_mac_addr = e1000_read_mac_addr_82575; /* configure collision distance */ @@ -428,6 +454,13 @@ static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; /* link info */ mac->ops.get_link_up_info = e1000_get_link_up_info_82575; + /* acquire SW_FW sync */ + mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575; + mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575; + if (mac->type >= e1000_i210) { + mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210; + mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210; + } /* set lan id for port to determine which phy lock to use */ hw->mac.ops.set_lan_id(hw); @@ -470,7 +503,7 @@ static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) else if (hw->bus.func == E1000_FUNC_3) mask = E1000_SWFW_PHY3_SM; - return e1000_acquire_swfw_sync_82575(hw, mask); + return hw->mac.ops.acquire_swfw_sync(hw, mask); } /** @@ -492,7 +525,7 @@ static void e1000_release_phy_82575(struct e1000_hw *hw) else if (hw->bus.func == E1000_FUNC_3) mask = E1000_SWFW_PHY3_SM; - e1000_release_swfw_sync_82575(hw, mask); + hw->mac.ops.release_swfw_sync(hw, mask); } /** @@ -796,7 +829,7 @@ static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; - u16 data; + u32 data; DEBUGFUNC("e1000_set_d0_lplu_state_82580"); @@ -844,7 +877,7 @@ s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) { struct e1000_phy_info *phy = &hw->phy; s32 ret_val = E1000_SUCCESS; - u16 data; + u32 data; DEBUGFUNC("e1000_set_d3_lplu_state_82580"); @@ -918,11 +951,7 @@ static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) } - switch (hw->mac.type) { - default: - ret_val = e1000_acquire_nvm_generic(hw); - } - + ret_val = e1000_acquire_nvm_generic(hw); if (ret_val) e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); @@ -941,10 +970,8 @@ static void e1000_release_nvm_82575(struct e1000_hw *hw) { DEBUGFUNC("e1000_release_nvm_82575"); - switch (hw->mac.type) { - default: - e1000_release_nvm_generic(hw); - } + e1000_release_nvm_generic(hw); + e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); } @@ -1058,7 +1085,7 @@ static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) DEBUGOUT("MNG configuration cycle has not completed.\n"); /* If EEPROM is not marked present, init the PHY manually */ - if (((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) && + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && (hw->phy.type == e1000_phy_igp_3)) e1000_phy_init_script_igp3(hw); @@ -1115,6 +1142,7 @@ static s32 e1000_check_for_link_82575(struct e1000_hw *hw) * continue to check for link. */ hw->mac.get_link_status = !hw->mac.serdes_has_link; + } else { ret_val = e1000_check_for_copper_link_generic(hw); } @@ -1168,11 +1196,6 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); - /* Set up defaults for the return values of this function */ - mac->serdes_has_link = FALSE; - *speed = 0; - *duplex = 0; - /* * Read the PCS Status register for link state. For non-copper mode, * the status register is not accurate. The PCS status register is @@ -1181,11 +1204,9 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT); /* - * The link up bit determines when link is up on autoneg. The sync ok - * gets set once both sides sync up and agree upon link. Stable link - * can be determined by checking for both link up and link sync ok + * The link up bit determines when link is up on autoneg. */ - if ((pcs & E1000_PCS_LSTS_LINK_OK) && (pcs & E1000_PCS_LSTS_SYNK_OK)) { + if (pcs & E1000_PCS_LSTS_LINK_OK) { mac->serdes_has_link = TRUE; /* Detect and store PCS speed */ @@ -1201,6 +1222,10 @@ static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, *duplex = FULL_DUPLEX; else *duplex = HALF_DUPLEX; + } else { + mac->serdes_has_link = FALSE; + *speed = 0; + *duplex = 0; } return E1000_SUCCESS; @@ -1293,7 +1318,7 @@ static s32 e1000_reset_hw_82575(struct e1000_hw *hw) } /* If EEPROM is not present, run manual init scripts */ - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) e1000_reset_init_script_82575(hw); /* Clear any pending interrupt events. */ @@ -1396,6 +1421,7 @@ static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) } } switch (hw->phy.type) { + case e1000_phy_i210: case e1000_phy_m88: if (hw->phy.id == I347AT4_E_PHY_ID || hw->phy.id == M88E1112_E_PHY_ID || @@ -1605,31 +1631,28 @@ static s32 e1000_get_media_type_82575(struct e1000_hw *hw) } /* Read Init Control Word #3*/ hw->nvm.ops.read(hw, init_ctrl_wd_3_offset, 1, &init_ctrl_wd_3); + + /* + * Align link mode bits to + * their CTRL_EXT location. + */ current_link_mode = init_ctrl_wd_3; + current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET - + init_ctrl_wd_3_bit_offset); + current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK; + /* * Switch to CSR for all but internal PHY. */ - if ((init_ctrl_wd_3 << (E1000_CTRL_EXT_LINK_MODE_OFFSET - - init_ctrl_wd_3_bit_offset)) != - E1000_CTRL_EXT_LINK_MODE_GMII) { - current_link_mode = ctrl_ext; - init_ctrl_wd_3_bit_offset = - E1000_CTRL_EXT_LINK_MODE_OFFSET; - } + if (current_link_mode != E1000_CTRL_EXT_LINK_MODE_GMII) + /* Take link mode from CSR */ + current_link_mode = ctrl_ext & + E1000_CTRL_EXT_LINK_MODE_MASK; } else { /* Take link mode from CSR */ - current_link_mode = ctrl_ext; - init_ctrl_wd_3_bit_offset = E1000_CTRL_EXT_LINK_MODE_OFFSET; + current_link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; } - /* - * Align link mode bits to - * their CTRL_EXT location. - */ - current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET - - init_ctrl_wd_3_bit_offset); - current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK; - switch (current_link_mode) { case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: @@ -2331,7 +2354,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) msec_delay(10); /* Determine whether or not a global dev reset is requested */ - if (global_device_reset && e1000_acquire_swfw_sync_82575(hw, + if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw, swmbsw_mask)) global_device_reset = FALSE; @@ -2359,7 +2382,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) } /* If EEPROM is not present, run manual init scripts */ - if ((E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) == 0) + if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) e1000_reset_init_script_82575(hw); /* clear global device reset status bit */ @@ -2378,7 +2401,7 @@ static s32 e1000_reset_hw_82580(struct e1000_hw *hw) /* Release semaphore */ if (global_device_reset) - e1000_release_swfw_sync_82575(hw, swmbsw_mask); + hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); return ret_val; } @@ -2538,7 +2561,7 @@ static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) goto out; } - if ((nvm_data & NVM_COMPATIBILITY_BIT_MASK) == 0) { + if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { /* set compatibility bit to validate checksums appropriately */ nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, @@ -2737,6 +2760,7 @@ s32 e1000_set_i2c_bb(struct e1000_hw *hw) * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to read + * @dev_addr: device address * @data: value read * * Performs byte read operation over I2C interface at @@ -2750,14 +2774,14 @@ s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, u32 retry = 1; u16 swfw_mask = 0; - bool nack = 1; + bool nack = TRUE; DEBUGFUNC("e1000_read_i2c_byte_generic"); swfw_mask = E1000_SWFW_PHY0_SM; do { - if (e1000_acquire_swfw_sync_82575(hw, swfw_mask) + if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { status = E1000_ERR_SWFW_SYNC; goto read_byte_out; @@ -2805,7 +2829,7 @@ s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, break; fail: - e1000_release_swfw_sync_82575(hw, swfw_mask); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); msec_delay(100); e1000_i2c_bus_clear(hw); retry++; @@ -2816,7 +2840,7 @@ fail: } while (retry < max_retry); - e1000_release_swfw_sync_82575(hw, swfw_mask); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); read_byte_out: @@ -2827,6 +2851,7 @@ read_byte_out: * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C * @hw: pointer to hardware structure * @byte_offset: byte offset to write + * @dev_addr: device address * @data: value to write * * Performs byte write operation over I2C interface at @@ -2844,7 +2869,7 @@ s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, swfw_mask = E1000_SWFW_PHY0_SM; - if (e1000_acquire_swfw_sync_82575(hw, swfw_mask) != E1000_SUCCESS) { + if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { status = E1000_ERR_SWFW_SYNC; goto write_byte_out; } @@ -2888,7 +2913,7 @@ fail: DEBUGOUT("I2C byte write error.\n"); } while (retry < max_retry); - e1000_release_swfw_sync_82575(hw, swfw_mask); + hw->mac.ops.release_swfw_sync(hw, swfw_mask); write_byte_out: @@ -3020,7 +3045,7 @@ static s32 e1000_get_i2c_ack(struct e1000_hw *hw) u32 i = 0; u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); u32 timeout = 10; - bool ack = 1; + bool ack = TRUE; DEBUGFUNC("e1000_get_i2c_ack"); @@ -3040,7 +3065,7 @@ static s32 e1000_get_i2c_ack(struct e1000_hw *hw) return E1000_ERR_I2C; ack = e1000_get_i2c_data(&i2cctl); - if (ack == 1) { + if (ack) { DEBUGOUT("I2C ack was not received.\n"); status = E1000_ERR_I2C; } |