162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* Copyright(c) 1999 - 2006 Intel Corporation. */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci/* e1000_hw.c 562306a36Sopenharmony_ci * Shared functions for accessing and configuring the MAC 662306a36Sopenharmony_ci */ 762306a36Sopenharmony_ci 862306a36Sopenharmony_ci#include "e1000.h" 962306a36Sopenharmony_ci 1062306a36Sopenharmony_cistatic s32 e1000_check_downshift(struct e1000_hw *hw); 1162306a36Sopenharmony_cistatic s32 e1000_check_polarity(struct e1000_hw *hw, 1262306a36Sopenharmony_ci e1000_rev_polarity *polarity); 1362306a36Sopenharmony_cistatic void e1000_clear_hw_cntrs(struct e1000_hw *hw); 1462306a36Sopenharmony_cistatic void e1000_clear_vfta(struct e1000_hw *hw); 1562306a36Sopenharmony_cistatic s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, 1662306a36Sopenharmony_ci bool link_up); 1762306a36Sopenharmony_cistatic s32 e1000_config_fc_after_link_up(struct e1000_hw *hw); 1862306a36Sopenharmony_cistatic s32 e1000_detect_gig_phy(struct e1000_hw *hw); 1962306a36Sopenharmony_cistatic s32 e1000_get_auto_rd_done(struct e1000_hw *hw); 2062306a36Sopenharmony_cistatic s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, 2162306a36Sopenharmony_ci u16 *max_length); 2262306a36Sopenharmony_cistatic s32 e1000_get_phy_cfg_done(struct e1000_hw *hw); 2362306a36Sopenharmony_cistatic s32 e1000_id_led_init(struct e1000_hw *hw); 2462306a36Sopenharmony_cistatic void e1000_init_rx_addrs(struct e1000_hw *hw); 2562306a36Sopenharmony_cistatic s32 e1000_phy_igp_get_info(struct e1000_hw *hw, 2662306a36Sopenharmony_ci struct e1000_phy_info *phy_info); 2762306a36Sopenharmony_cistatic s32 e1000_phy_m88_get_info(struct e1000_hw *hw, 2862306a36Sopenharmony_ci struct e1000_phy_info *phy_info); 2962306a36Sopenharmony_cistatic s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active); 3062306a36Sopenharmony_cistatic s32 e1000_wait_autoneg(struct e1000_hw *hw); 3162306a36Sopenharmony_cistatic void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value); 3262306a36Sopenharmony_cistatic s32 e1000_set_phy_type(struct e1000_hw *hw); 3362306a36Sopenharmony_cistatic void e1000_phy_init_script(struct e1000_hw *hw); 3462306a36Sopenharmony_cistatic s32 e1000_setup_copper_link(struct e1000_hw *hw); 3562306a36Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw); 3662306a36Sopenharmony_cistatic s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw); 3762306a36Sopenharmony_cistatic s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw); 3862306a36Sopenharmony_cistatic s32 e1000_config_mac_to_phy(struct e1000_hw *hw); 3962306a36Sopenharmony_cistatic void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl); 4062306a36Sopenharmony_cistatic void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl); 4162306a36Sopenharmony_cistatic void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count); 4262306a36Sopenharmony_cistatic u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw); 4362306a36Sopenharmony_cistatic s32 e1000_phy_reset_dsp(struct e1000_hw *hw); 4462306a36Sopenharmony_cistatic s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, 4562306a36Sopenharmony_ci u16 words, u16 *data); 4662306a36Sopenharmony_cistatic s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset, 4762306a36Sopenharmony_ci u16 words, u16 *data); 4862306a36Sopenharmony_cistatic s32 e1000_spi_eeprom_ready(struct e1000_hw *hw); 4962306a36Sopenharmony_cistatic void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd); 5062306a36Sopenharmony_cistatic void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd); 5162306a36Sopenharmony_cistatic void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count); 5262306a36Sopenharmony_cistatic s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, 5362306a36Sopenharmony_ci u16 phy_data); 5462306a36Sopenharmony_cistatic s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, 5562306a36Sopenharmony_ci u16 *phy_data); 5662306a36Sopenharmony_cistatic u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count); 5762306a36Sopenharmony_cistatic s32 e1000_acquire_eeprom(struct e1000_hw *hw); 5862306a36Sopenharmony_cistatic void e1000_release_eeprom(struct e1000_hw *hw); 5962306a36Sopenharmony_cistatic void e1000_standby_eeprom(struct e1000_hw *hw); 6062306a36Sopenharmony_cistatic s32 e1000_set_vco_speed(struct e1000_hw *hw); 6162306a36Sopenharmony_cistatic s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw); 6262306a36Sopenharmony_cistatic s32 e1000_set_phy_mode(struct e1000_hw *hw); 6362306a36Sopenharmony_cistatic s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, 6462306a36Sopenharmony_ci u16 *data); 6562306a36Sopenharmony_cistatic s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, 6662306a36Sopenharmony_ci u16 *data); 6762306a36Sopenharmony_ci 6862306a36Sopenharmony_ci/* IGP cable length table */ 6962306a36Sopenharmony_cistatic const 7062306a36Sopenharmony_ciu16 e1000_igp_cable_length_table[IGP01E1000_AGC_LENGTH_TABLE_SIZE] = { 7162306a36Sopenharmony_ci 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 7262306a36Sopenharmony_ci 5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 7362306a36Sopenharmony_ci 25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40, 7462306a36Sopenharmony_ci 40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60, 7562306a36Sopenharmony_ci 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90, 7662306a36Sopenharmony_ci 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 7762306a36Sopenharmony_ci 100, 7862306a36Sopenharmony_ci 100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 7962306a36Sopenharmony_ci 110, 110, 8062306a36Sopenharmony_ci 110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 8162306a36Sopenharmony_ci 120, 120 8262306a36Sopenharmony_ci}; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_cistatic DEFINE_MUTEX(e1000_eeprom_lock); 8562306a36Sopenharmony_cistatic DEFINE_SPINLOCK(e1000_phy_lock); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/** 8862306a36Sopenharmony_ci * e1000_set_phy_type - Set the phy type member in the hw struct. 8962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_cistatic s32 e1000_set_phy_type(struct e1000_hw *hw) 9262306a36Sopenharmony_ci{ 9362306a36Sopenharmony_ci if (hw->mac_type == e1000_undefined) 9462306a36Sopenharmony_ci return -E1000_ERR_PHY_TYPE; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci switch (hw->phy_id) { 9762306a36Sopenharmony_ci case M88E1000_E_PHY_ID: 9862306a36Sopenharmony_ci case M88E1000_I_PHY_ID: 9962306a36Sopenharmony_ci case M88E1011_I_PHY_ID: 10062306a36Sopenharmony_ci case M88E1111_I_PHY_ID: 10162306a36Sopenharmony_ci case M88E1118_E_PHY_ID: 10262306a36Sopenharmony_ci hw->phy_type = e1000_phy_m88; 10362306a36Sopenharmony_ci break; 10462306a36Sopenharmony_ci case IGP01E1000_I_PHY_ID: 10562306a36Sopenharmony_ci if (hw->mac_type == e1000_82541 || 10662306a36Sopenharmony_ci hw->mac_type == e1000_82541_rev_2 || 10762306a36Sopenharmony_ci hw->mac_type == e1000_82547 || 10862306a36Sopenharmony_ci hw->mac_type == e1000_82547_rev_2) 10962306a36Sopenharmony_ci hw->phy_type = e1000_phy_igp; 11062306a36Sopenharmony_ci break; 11162306a36Sopenharmony_ci case RTL8211B_PHY_ID: 11262306a36Sopenharmony_ci hw->phy_type = e1000_phy_8211; 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci case RTL8201N_PHY_ID: 11562306a36Sopenharmony_ci hw->phy_type = e1000_phy_8201; 11662306a36Sopenharmony_ci break; 11762306a36Sopenharmony_ci default: 11862306a36Sopenharmony_ci /* Should never have loaded on this device */ 11962306a36Sopenharmony_ci hw->phy_type = e1000_phy_undefined; 12062306a36Sopenharmony_ci return -E1000_ERR_PHY_TYPE; 12162306a36Sopenharmony_ci } 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci return E1000_SUCCESS; 12462306a36Sopenharmony_ci} 12562306a36Sopenharmony_ci 12662306a36Sopenharmony_ci/** 12762306a36Sopenharmony_ci * e1000_phy_init_script - IGP phy init script - initializes the GbE PHY 12862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 12962306a36Sopenharmony_ci */ 13062306a36Sopenharmony_cistatic void e1000_phy_init_script(struct e1000_hw *hw) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci u16 phy_saved_data; 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (hw->phy_init_script) { 13562306a36Sopenharmony_ci msleep(20); 13662306a36Sopenharmony_ci 13762306a36Sopenharmony_ci /* Save off the current value of register 0x2F5B to be restored 13862306a36Sopenharmony_ci * at the end of this routine. 13962306a36Sopenharmony_ci */ 14062306a36Sopenharmony_ci e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci /* Disabled the PHY transmitter */ 14362306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x2F5B, 0x0003); 14462306a36Sopenharmony_ci msleep(20); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x0000, 0x0140); 14762306a36Sopenharmony_ci msleep(5); 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_ci switch (hw->mac_type) { 15062306a36Sopenharmony_ci case e1000_82541: 15162306a36Sopenharmony_ci case e1000_82547: 15262306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F95, 0x0001); 15362306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F71, 0xBD21); 15462306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F79, 0x0018); 15562306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F30, 0x1600); 15662306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F31, 0x0014); 15762306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F32, 0x161C); 15862306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F94, 0x0003); 15962306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F96, 0x003F); 16062306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x2010, 0x0008); 16162306a36Sopenharmony_ci break; 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci case e1000_82541_rev_2: 16462306a36Sopenharmony_ci case e1000_82547_rev_2: 16562306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x1F73, 0x0099); 16662306a36Sopenharmony_ci break; 16762306a36Sopenharmony_ci default: 16862306a36Sopenharmony_ci break; 16962306a36Sopenharmony_ci } 17062306a36Sopenharmony_ci 17162306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x0000, 0x3300); 17262306a36Sopenharmony_ci msleep(20); 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci /* Now enable the transmitter */ 17562306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci if (hw->mac_type == e1000_82547) { 17862306a36Sopenharmony_ci u16 fused, fine, coarse; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci /* Move to analog registers page */ 18162306a36Sopenharmony_ci e1000_read_phy_reg(hw, 18262306a36Sopenharmony_ci IGP01E1000_ANALOG_SPARE_FUSE_STATUS, 18362306a36Sopenharmony_ci &fused); 18462306a36Sopenharmony_ci 18562306a36Sopenharmony_ci if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) { 18662306a36Sopenharmony_ci e1000_read_phy_reg(hw, 18762306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_STATUS, 18862306a36Sopenharmony_ci &fused); 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK; 19162306a36Sopenharmony_ci coarse = 19262306a36Sopenharmony_ci fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK; 19362306a36Sopenharmony_ci 19462306a36Sopenharmony_ci if (coarse > 19562306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_COARSE_THRESH) { 19662306a36Sopenharmony_ci coarse -= 19762306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_COARSE_10; 19862306a36Sopenharmony_ci fine -= IGP01E1000_ANALOG_FUSE_FINE_1; 19962306a36Sopenharmony_ci } else if (coarse == 20062306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_COARSE_THRESH) 20162306a36Sopenharmony_ci fine -= IGP01E1000_ANALOG_FUSE_FINE_10; 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci fused = 20462306a36Sopenharmony_ci (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) | 20562306a36Sopenharmony_ci (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) | 20662306a36Sopenharmony_ci (coarse & 20762306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_COARSE_MASK); 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci e1000_write_phy_reg(hw, 21062306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_CONTROL, 21162306a36Sopenharmony_ci fused); 21262306a36Sopenharmony_ci e1000_write_phy_reg(hw, 21362306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_BYPASS, 21462306a36Sopenharmony_ci IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL); 21562306a36Sopenharmony_ci } 21662306a36Sopenharmony_ci } 21762306a36Sopenharmony_ci } 21862306a36Sopenharmony_ci} 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/** 22162306a36Sopenharmony_ci * e1000_set_mac_type - Set the mac type member in the hw struct. 22262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_cis32 e1000_set_mac_type(struct e1000_hw *hw) 22562306a36Sopenharmony_ci{ 22662306a36Sopenharmony_ci switch (hw->device_id) { 22762306a36Sopenharmony_ci case E1000_DEV_ID_82542: 22862306a36Sopenharmony_ci switch (hw->revision_id) { 22962306a36Sopenharmony_ci case E1000_82542_2_0_REV_ID: 23062306a36Sopenharmony_ci hw->mac_type = e1000_82542_rev2_0; 23162306a36Sopenharmony_ci break; 23262306a36Sopenharmony_ci case E1000_82542_2_1_REV_ID: 23362306a36Sopenharmony_ci hw->mac_type = e1000_82542_rev2_1; 23462306a36Sopenharmony_ci break; 23562306a36Sopenharmony_ci default: 23662306a36Sopenharmony_ci /* Invalid 82542 revision ID */ 23762306a36Sopenharmony_ci return -E1000_ERR_MAC_TYPE; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci break; 24062306a36Sopenharmony_ci case E1000_DEV_ID_82543GC_FIBER: 24162306a36Sopenharmony_ci case E1000_DEV_ID_82543GC_COPPER: 24262306a36Sopenharmony_ci hw->mac_type = e1000_82543; 24362306a36Sopenharmony_ci break; 24462306a36Sopenharmony_ci case E1000_DEV_ID_82544EI_COPPER: 24562306a36Sopenharmony_ci case E1000_DEV_ID_82544EI_FIBER: 24662306a36Sopenharmony_ci case E1000_DEV_ID_82544GC_COPPER: 24762306a36Sopenharmony_ci case E1000_DEV_ID_82544GC_LOM: 24862306a36Sopenharmony_ci hw->mac_type = e1000_82544; 24962306a36Sopenharmony_ci break; 25062306a36Sopenharmony_ci case E1000_DEV_ID_82540EM: 25162306a36Sopenharmony_ci case E1000_DEV_ID_82540EM_LOM: 25262306a36Sopenharmony_ci case E1000_DEV_ID_82540EP: 25362306a36Sopenharmony_ci case E1000_DEV_ID_82540EP_LOM: 25462306a36Sopenharmony_ci case E1000_DEV_ID_82540EP_LP: 25562306a36Sopenharmony_ci hw->mac_type = e1000_82540; 25662306a36Sopenharmony_ci break; 25762306a36Sopenharmony_ci case E1000_DEV_ID_82545EM_COPPER: 25862306a36Sopenharmony_ci case E1000_DEV_ID_82545EM_FIBER: 25962306a36Sopenharmony_ci hw->mac_type = e1000_82545; 26062306a36Sopenharmony_ci break; 26162306a36Sopenharmony_ci case E1000_DEV_ID_82545GM_COPPER: 26262306a36Sopenharmony_ci case E1000_DEV_ID_82545GM_FIBER: 26362306a36Sopenharmony_ci case E1000_DEV_ID_82545GM_SERDES: 26462306a36Sopenharmony_ci hw->mac_type = e1000_82545_rev_3; 26562306a36Sopenharmony_ci break; 26662306a36Sopenharmony_ci case E1000_DEV_ID_82546EB_COPPER: 26762306a36Sopenharmony_ci case E1000_DEV_ID_82546EB_FIBER: 26862306a36Sopenharmony_ci case E1000_DEV_ID_82546EB_QUAD_COPPER: 26962306a36Sopenharmony_ci hw->mac_type = e1000_82546; 27062306a36Sopenharmony_ci break; 27162306a36Sopenharmony_ci case E1000_DEV_ID_82546GB_COPPER: 27262306a36Sopenharmony_ci case E1000_DEV_ID_82546GB_FIBER: 27362306a36Sopenharmony_ci case E1000_DEV_ID_82546GB_SERDES: 27462306a36Sopenharmony_ci case E1000_DEV_ID_82546GB_PCIE: 27562306a36Sopenharmony_ci case E1000_DEV_ID_82546GB_QUAD_COPPER: 27662306a36Sopenharmony_ci case E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3: 27762306a36Sopenharmony_ci hw->mac_type = e1000_82546_rev_3; 27862306a36Sopenharmony_ci break; 27962306a36Sopenharmony_ci case E1000_DEV_ID_82541EI: 28062306a36Sopenharmony_ci case E1000_DEV_ID_82541EI_MOBILE: 28162306a36Sopenharmony_ci case E1000_DEV_ID_82541ER_LOM: 28262306a36Sopenharmony_ci hw->mac_type = e1000_82541; 28362306a36Sopenharmony_ci break; 28462306a36Sopenharmony_ci case E1000_DEV_ID_82541ER: 28562306a36Sopenharmony_ci case E1000_DEV_ID_82541GI: 28662306a36Sopenharmony_ci case E1000_DEV_ID_82541GI_LF: 28762306a36Sopenharmony_ci case E1000_DEV_ID_82541GI_MOBILE: 28862306a36Sopenharmony_ci hw->mac_type = e1000_82541_rev_2; 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci case E1000_DEV_ID_82547EI: 29162306a36Sopenharmony_ci case E1000_DEV_ID_82547EI_MOBILE: 29262306a36Sopenharmony_ci hw->mac_type = e1000_82547; 29362306a36Sopenharmony_ci break; 29462306a36Sopenharmony_ci case E1000_DEV_ID_82547GI: 29562306a36Sopenharmony_ci hw->mac_type = e1000_82547_rev_2; 29662306a36Sopenharmony_ci break; 29762306a36Sopenharmony_ci case E1000_DEV_ID_INTEL_CE4100_GBE: 29862306a36Sopenharmony_ci hw->mac_type = e1000_ce4100; 29962306a36Sopenharmony_ci break; 30062306a36Sopenharmony_ci default: 30162306a36Sopenharmony_ci /* Should never have loaded on this device */ 30262306a36Sopenharmony_ci return -E1000_ERR_MAC_TYPE; 30362306a36Sopenharmony_ci } 30462306a36Sopenharmony_ci 30562306a36Sopenharmony_ci switch (hw->mac_type) { 30662306a36Sopenharmony_ci case e1000_82541: 30762306a36Sopenharmony_ci case e1000_82547: 30862306a36Sopenharmony_ci case e1000_82541_rev_2: 30962306a36Sopenharmony_ci case e1000_82547_rev_2: 31062306a36Sopenharmony_ci hw->asf_firmware_present = true; 31162306a36Sopenharmony_ci break; 31262306a36Sopenharmony_ci default: 31362306a36Sopenharmony_ci break; 31462306a36Sopenharmony_ci } 31562306a36Sopenharmony_ci 31662306a36Sopenharmony_ci /* The 82543 chip does not count tx_carrier_errors properly in 31762306a36Sopenharmony_ci * FD mode 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ci if (hw->mac_type == e1000_82543) 32062306a36Sopenharmony_ci hw->bad_tx_carr_stats_fd = true; 32162306a36Sopenharmony_ci 32262306a36Sopenharmony_ci if (hw->mac_type > e1000_82544) 32362306a36Sopenharmony_ci hw->has_smbus = true; 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci return E1000_SUCCESS; 32662306a36Sopenharmony_ci} 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci/** 32962306a36Sopenharmony_ci * e1000_set_media_type - Set media type and TBI compatibility. 33062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 33162306a36Sopenharmony_ci */ 33262306a36Sopenharmony_civoid e1000_set_media_type(struct e1000_hw *hw) 33362306a36Sopenharmony_ci{ 33462306a36Sopenharmony_ci u32 status; 33562306a36Sopenharmony_ci 33662306a36Sopenharmony_ci if (hw->mac_type != e1000_82543) { 33762306a36Sopenharmony_ci /* tbi_compatibility is only valid on 82543 */ 33862306a36Sopenharmony_ci hw->tbi_compatibility_en = false; 33962306a36Sopenharmony_ci } 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci switch (hw->device_id) { 34262306a36Sopenharmony_ci case E1000_DEV_ID_82545GM_SERDES: 34362306a36Sopenharmony_ci case E1000_DEV_ID_82546GB_SERDES: 34462306a36Sopenharmony_ci hw->media_type = e1000_media_type_internal_serdes; 34562306a36Sopenharmony_ci break; 34662306a36Sopenharmony_ci default: 34762306a36Sopenharmony_ci switch (hw->mac_type) { 34862306a36Sopenharmony_ci case e1000_82542_rev2_0: 34962306a36Sopenharmony_ci case e1000_82542_rev2_1: 35062306a36Sopenharmony_ci hw->media_type = e1000_media_type_fiber; 35162306a36Sopenharmony_ci break; 35262306a36Sopenharmony_ci case e1000_ce4100: 35362306a36Sopenharmony_ci hw->media_type = e1000_media_type_copper; 35462306a36Sopenharmony_ci break; 35562306a36Sopenharmony_ci default: 35662306a36Sopenharmony_ci status = er32(STATUS); 35762306a36Sopenharmony_ci if (status & E1000_STATUS_TBIMODE) { 35862306a36Sopenharmony_ci hw->media_type = e1000_media_type_fiber; 35962306a36Sopenharmony_ci /* tbi_compatibility not valid on fiber */ 36062306a36Sopenharmony_ci hw->tbi_compatibility_en = false; 36162306a36Sopenharmony_ci } else { 36262306a36Sopenharmony_ci hw->media_type = e1000_media_type_copper; 36362306a36Sopenharmony_ci } 36462306a36Sopenharmony_ci break; 36562306a36Sopenharmony_ci } 36662306a36Sopenharmony_ci } 36762306a36Sopenharmony_ci} 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_ci/** 37062306a36Sopenharmony_ci * e1000_reset_hw - reset the hardware completely 37162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 37262306a36Sopenharmony_ci * 37362306a36Sopenharmony_ci * Reset the transmit and receive units; mask and clear all interrupts. 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_cis32 e1000_reset_hw(struct e1000_hw *hw) 37662306a36Sopenharmony_ci{ 37762306a36Sopenharmony_ci u32 ctrl; 37862306a36Sopenharmony_ci u32 ctrl_ext; 37962306a36Sopenharmony_ci u32 manc; 38062306a36Sopenharmony_ci u32 led_ctrl; 38162306a36Sopenharmony_ci s32 ret_val; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci /* For 82542 (rev 2.0), disable MWI before issuing a device reset */ 38462306a36Sopenharmony_ci if (hw->mac_type == e1000_82542_rev2_0) { 38562306a36Sopenharmony_ci e_dbg("Disabling MWI on 82542 rev 2.0\n"); 38662306a36Sopenharmony_ci e1000_pci_clear_mwi(hw); 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci 38962306a36Sopenharmony_ci /* Clear interrupt mask to stop board from generating interrupts */ 39062306a36Sopenharmony_ci e_dbg("Masking off all interrupts\n"); 39162306a36Sopenharmony_ci ew32(IMC, 0xffffffff); 39262306a36Sopenharmony_ci 39362306a36Sopenharmony_ci /* Disable the Transmit and Receive units. Then delay to allow 39462306a36Sopenharmony_ci * any pending transactions to complete before we hit the MAC with 39562306a36Sopenharmony_ci * the global reset. 39662306a36Sopenharmony_ci */ 39762306a36Sopenharmony_ci ew32(RCTL, 0); 39862306a36Sopenharmony_ci ew32(TCTL, E1000_TCTL_PSP); 39962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 40062306a36Sopenharmony_ci 40162306a36Sopenharmony_ci /* The tbi_compatibility_on Flag must be cleared when Rctl is cleared. */ 40262306a36Sopenharmony_ci hw->tbi_compatibility_on = false; 40362306a36Sopenharmony_ci 40462306a36Sopenharmony_ci /* Delay to allow any outstanding PCI transactions to complete before 40562306a36Sopenharmony_ci * resetting the device 40662306a36Sopenharmony_ci */ 40762306a36Sopenharmony_ci msleep(10); 40862306a36Sopenharmony_ci 40962306a36Sopenharmony_ci ctrl = er32(CTRL); 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_ci /* Must reset the PHY before resetting the MAC */ 41262306a36Sopenharmony_ci if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { 41362306a36Sopenharmony_ci ew32(CTRL, (ctrl | E1000_CTRL_PHY_RST)); 41462306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 41562306a36Sopenharmony_ci msleep(5); 41662306a36Sopenharmony_ci } 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci /* Issue a global reset to the MAC. This will reset the chip's 41962306a36Sopenharmony_ci * transmit, receive, DMA, and link units. It will not effect 42062306a36Sopenharmony_ci * the current PCI configuration. The global reset bit is self- 42162306a36Sopenharmony_ci * clearing, and should clear within a microsecond. 42262306a36Sopenharmony_ci */ 42362306a36Sopenharmony_ci e_dbg("Issuing a global reset to MAC\n"); 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci switch (hw->mac_type) { 42662306a36Sopenharmony_ci case e1000_82544: 42762306a36Sopenharmony_ci case e1000_82540: 42862306a36Sopenharmony_ci case e1000_82545: 42962306a36Sopenharmony_ci case e1000_82546: 43062306a36Sopenharmony_ci case e1000_82541: 43162306a36Sopenharmony_ci case e1000_82541_rev_2: 43262306a36Sopenharmony_ci /* These controllers can't ack the 64-bit write when issuing the 43362306a36Sopenharmony_ci * reset, so use IO-mapping as a workaround to issue the reset 43462306a36Sopenharmony_ci */ 43562306a36Sopenharmony_ci E1000_WRITE_REG_IO(hw, CTRL, (ctrl | E1000_CTRL_RST)); 43662306a36Sopenharmony_ci break; 43762306a36Sopenharmony_ci case e1000_82545_rev_3: 43862306a36Sopenharmony_ci case e1000_82546_rev_3: 43962306a36Sopenharmony_ci /* Reset is performed on a shadow of the control register */ 44062306a36Sopenharmony_ci ew32(CTRL_DUP, (ctrl | E1000_CTRL_RST)); 44162306a36Sopenharmony_ci break; 44262306a36Sopenharmony_ci case e1000_ce4100: 44362306a36Sopenharmony_ci default: 44462306a36Sopenharmony_ci ew32(CTRL, (ctrl | E1000_CTRL_RST)); 44562306a36Sopenharmony_ci break; 44662306a36Sopenharmony_ci } 44762306a36Sopenharmony_ci 44862306a36Sopenharmony_ci /* After MAC reset, force reload of EEPROM to restore power-on settings 44962306a36Sopenharmony_ci * to device. Later controllers reload the EEPROM automatically, so 45062306a36Sopenharmony_ci * just wait for reload to complete. 45162306a36Sopenharmony_ci */ 45262306a36Sopenharmony_ci switch (hw->mac_type) { 45362306a36Sopenharmony_ci case e1000_82542_rev2_0: 45462306a36Sopenharmony_ci case e1000_82542_rev2_1: 45562306a36Sopenharmony_ci case e1000_82543: 45662306a36Sopenharmony_ci case e1000_82544: 45762306a36Sopenharmony_ci /* Wait for reset to complete */ 45862306a36Sopenharmony_ci udelay(10); 45962306a36Sopenharmony_ci ctrl_ext = er32(CTRL_EXT); 46062306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_EXT_EE_RST; 46162306a36Sopenharmony_ci ew32(CTRL_EXT, ctrl_ext); 46262306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 46362306a36Sopenharmony_ci /* Wait for EEPROM reload */ 46462306a36Sopenharmony_ci msleep(2); 46562306a36Sopenharmony_ci break; 46662306a36Sopenharmony_ci case e1000_82541: 46762306a36Sopenharmony_ci case e1000_82541_rev_2: 46862306a36Sopenharmony_ci case e1000_82547: 46962306a36Sopenharmony_ci case e1000_82547_rev_2: 47062306a36Sopenharmony_ci /* Wait for EEPROM reload */ 47162306a36Sopenharmony_ci msleep(20); 47262306a36Sopenharmony_ci break; 47362306a36Sopenharmony_ci default: 47462306a36Sopenharmony_ci /* Auto read done will delay 5ms or poll based on mac type */ 47562306a36Sopenharmony_ci ret_val = e1000_get_auto_rd_done(hw); 47662306a36Sopenharmony_ci if (ret_val) 47762306a36Sopenharmony_ci return ret_val; 47862306a36Sopenharmony_ci break; 47962306a36Sopenharmony_ci } 48062306a36Sopenharmony_ci 48162306a36Sopenharmony_ci /* Disable HW ARPs on ASF enabled adapters */ 48262306a36Sopenharmony_ci if (hw->mac_type >= e1000_82540) { 48362306a36Sopenharmony_ci manc = er32(MANC); 48462306a36Sopenharmony_ci manc &= ~(E1000_MANC_ARP_EN); 48562306a36Sopenharmony_ci ew32(MANC, manc); 48662306a36Sopenharmony_ci } 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { 48962306a36Sopenharmony_ci e1000_phy_init_script(hw); 49062306a36Sopenharmony_ci 49162306a36Sopenharmony_ci /* Configure activity LED after PHY reset */ 49262306a36Sopenharmony_ci led_ctrl = er32(LEDCTL); 49362306a36Sopenharmony_ci led_ctrl &= IGP_ACTIVITY_LED_MASK; 49462306a36Sopenharmony_ci led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 49562306a36Sopenharmony_ci ew32(LEDCTL, led_ctrl); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci /* Clear interrupt mask to stop board from generating interrupts */ 49962306a36Sopenharmony_ci e_dbg("Masking off all interrupts\n"); 50062306a36Sopenharmony_ci ew32(IMC, 0xffffffff); 50162306a36Sopenharmony_ci 50262306a36Sopenharmony_ci /* Clear any pending interrupt events. */ 50362306a36Sopenharmony_ci er32(ICR); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci /* If MWI was previously enabled, reenable it. */ 50662306a36Sopenharmony_ci if (hw->mac_type == e1000_82542_rev2_0) { 50762306a36Sopenharmony_ci if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) 50862306a36Sopenharmony_ci e1000_pci_set_mwi(hw); 50962306a36Sopenharmony_ci } 51062306a36Sopenharmony_ci 51162306a36Sopenharmony_ci return E1000_SUCCESS; 51262306a36Sopenharmony_ci} 51362306a36Sopenharmony_ci 51462306a36Sopenharmony_ci/** 51562306a36Sopenharmony_ci * e1000_init_hw - Performs basic configuration of the adapter. 51662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 51762306a36Sopenharmony_ci * 51862306a36Sopenharmony_ci * Assumes that the controller has previously been reset and is in a 51962306a36Sopenharmony_ci * post-reset uninitialized state. Initializes the receive address registers, 52062306a36Sopenharmony_ci * multicast table, and VLAN filter table. Calls routines to setup link 52162306a36Sopenharmony_ci * configuration and flow control settings. Clears all on-chip counters. Leaves 52262306a36Sopenharmony_ci * the transmit and receive units disabled and uninitialized. 52362306a36Sopenharmony_ci */ 52462306a36Sopenharmony_cis32 e1000_init_hw(struct e1000_hw *hw) 52562306a36Sopenharmony_ci{ 52662306a36Sopenharmony_ci u32 ctrl; 52762306a36Sopenharmony_ci u32 i; 52862306a36Sopenharmony_ci s32 ret_val; 52962306a36Sopenharmony_ci u32 mta_size; 53062306a36Sopenharmony_ci u32 ctrl_ext; 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci /* Initialize Identification LED */ 53362306a36Sopenharmony_ci ret_val = e1000_id_led_init(hw); 53462306a36Sopenharmony_ci if (ret_val) { 53562306a36Sopenharmony_ci e_dbg("Error Initializing Identification LED\n"); 53662306a36Sopenharmony_ci return ret_val; 53762306a36Sopenharmony_ci } 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci /* Set the media type and TBI compatibility */ 54062306a36Sopenharmony_ci e1000_set_media_type(hw); 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_ci /* Disabling VLAN filtering. */ 54362306a36Sopenharmony_ci e_dbg("Initializing the IEEE VLAN\n"); 54462306a36Sopenharmony_ci if (hw->mac_type < e1000_82545_rev_3) 54562306a36Sopenharmony_ci ew32(VET, 0); 54662306a36Sopenharmony_ci e1000_clear_vfta(hw); 54762306a36Sopenharmony_ci 54862306a36Sopenharmony_ci /* For 82542 (rev 2.0), disable MWI and put the receiver into reset */ 54962306a36Sopenharmony_ci if (hw->mac_type == e1000_82542_rev2_0) { 55062306a36Sopenharmony_ci e_dbg("Disabling MWI on 82542 rev 2.0\n"); 55162306a36Sopenharmony_ci e1000_pci_clear_mwi(hw); 55262306a36Sopenharmony_ci ew32(RCTL, E1000_RCTL_RST); 55362306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 55462306a36Sopenharmony_ci msleep(5); 55562306a36Sopenharmony_ci } 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci /* Setup the receive address. This involves initializing all of the 55862306a36Sopenharmony_ci * Receive Address Registers (RARs 0 - 15). 55962306a36Sopenharmony_ci */ 56062306a36Sopenharmony_ci e1000_init_rx_addrs(hw); 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci /* For 82542 (rev 2.0), take the receiver out of reset and enable MWI */ 56362306a36Sopenharmony_ci if (hw->mac_type == e1000_82542_rev2_0) { 56462306a36Sopenharmony_ci ew32(RCTL, 0); 56562306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 56662306a36Sopenharmony_ci msleep(1); 56762306a36Sopenharmony_ci if (hw->pci_cmd_word & PCI_COMMAND_INVALIDATE) 56862306a36Sopenharmony_ci e1000_pci_set_mwi(hw); 56962306a36Sopenharmony_ci } 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci /* Zero out the Multicast HASH table */ 57262306a36Sopenharmony_ci e_dbg("Zeroing the MTA\n"); 57362306a36Sopenharmony_ci mta_size = E1000_MC_TBL_SIZE; 57462306a36Sopenharmony_ci for (i = 0; i < mta_size; i++) { 57562306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, MTA, i, 0); 57662306a36Sopenharmony_ci /* use write flush to prevent Memory Write Block (MWB) from 57762306a36Sopenharmony_ci * occurring when accessing our register space 57862306a36Sopenharmony_ci */ 57962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 58062306a36Sopenharmony_ci } 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci /* Set the PCI priority bit correctly in the CTRL register. This 58362306a36Sopenharmony_ci * determines if the adapter gives priority to receives, or if it 58462306a36Sopenharmony_ci * gives equal priority to transmits and receives. Valid only on 58562306a36Sopenharmony_ci * 82542 and 82543 silicon. 58662306a36Sopenharmony_ci */ 58762306a36Sopenharmony_ci if (hw->dma_fairness && hw->mac_type <= e1000_82543) { 58862306a36Sopenharmony_ci ctrl = er32(CTRL); 58962306a36Sopenharmony_ci ew32(CTRL, ctrl | E1000_CTRL_PRIOR); 59062306a36Sopenharmony_ci } 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci switch (hw->mac_type) { 59362306a36Sopenharmony_ci case e1000_82545_rev_3: 59462306a36Sopenharmony_ci case e1000_82546_rev_3: 59562306a36Sopenharmony_ci break; 59662306a36Sopenharmony_ci default: 59762306a36Sopenharmony_ci /* Workaround for PCI-X problem when BIOS sets MMRBC 59862306a36Sopenharmony_ci * incorrectly. 59962306a36Sopenharmony_ci */ 60062306a36Sopenharmony_ci if (hw->bus_type == e1000_bus_type_pcix && 60162306a36Sopenharmony_ci e1000_pcix_get_mmrbc(hw) > 2048) 60262306a36Sopenharmony_ci e1000_pcix_set_mmrbc(hw, 2048); 60362306a36Sopenharmony_ci break; 60462306a36Sopenharmony_ci } 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_ci /* Call a subroutine to configure the link and setup flow control. */ 60762306a36Sopenharmony_ci ret_val = e1000_setup_link(hw); 60862306a36Sopenharmony_ci 60962306a36Sopenharmony_ci /* Set the transmit descriptor write-back policy */ 61062306a36Sopenharmony_ci if (hw->mac_type > e1000_82544) { 61162306a36Sopenharmony_ci ctrl = er32(TXDCTL); 61262306a36Sopenharmony_ci ctrl = 61362306a36Sopenharmony_ci (ctrl & ~E1000_TXDCTL_WTHRESH) | 61462306a36Sopenharmony_ci E1000_TXDCTL_FULL_TX_DESC_WB; 61562306a36Sopenharmony_ci ew32(TXDCTL, ctrl); 61662306a36Sopenharmony_ci } 61762306a36Sopenharmony_ci 61862306a36Sopenharmony_ci /* Clear all of the statistics registers (clear on read). It is 61962306a36Sopenharmony_ci * important that we do this after we have tried to establish link 62062306a36Sopenharmony_ci * because the symbol error count will increment wildly if there 62162306a36Sopenharmony_ci * is no link. 62262306a36Sopenharmony_ci */ 62362306a36Sopenharmony_ci e1000_clear_hw_cntrs(hw); 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci if (hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER || 62662306a36Sopenharmony_ci hw->device_id == E1000_DEV_ID_82546GB_QUAD_COPPER_KSP3) { 62762306a36Sopenharmony_ci ctrl_ext = er32(CTRL_EXT); 62862306a36Sopenharmony_ci /* Relaxed ordering must be disabled to avoid a parity 62962306a36Sopenharmony_ci * error crash in a PCI slot. 63062306a36Sopenharmony_ci */ 63162306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_EXT_RO_DIS; 63262306a36Sopenharmony_ci ew32(CTRL_EXT, ctrl_ext); 63362306a36Sopenharmony_ci } 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci return ret_val; 63662306a36Sopenharmony_ci} 63762306a36Sopenharmony_ci 63862306a36Sopenharmony_ci/** 63962306a36Sopenharmony_ci * e1000_adjust_serdes_amplitude - Adjust SERDES output amplitude based on EEPROM setting. 64062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code. 64162306a36Sopenharmony_ci */ 64262306a36Sopenharmony_cistatic s32 e1000_adjust_serdes_amplitude(struct e1000_hw *hw) 64362306a36Sopenharmony_ci{ 64462306a36Sopenharmony_ci u16 eeprom_data; 64562306a36Sopenharmony_ci s32 ret_val; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci if (hw->media_type != e1000_media_type_internal_serdes) 64862306a36Sopenharmony_ci return E1000_SUCCESS; 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci switch (hw->mac_type) { 65162306a36Sopenharmony_ci case e1000_82545_rev_3: 65262306a36Sopenharmony_ci case e1000_82546_rev_3: 65362306a36Sopenharmony_ci break; 65462306a36Sopenharmony_ci default: 65562306a36Sopenharmony_ci return E1000_SUCCESS; 65662306a36Sopenharmony_ci } 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_ci ret_val = e1000_read_eeprom(hw, EEPROM_SERDES_AMPLITUDE, 1, 65962306a36Sopenharmony_ci &eeprom_data); 66062306a36Sopenharmony_ci if (ret_val) 66162306a36Sopenharmony_ci return ret_val; 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ci if (eeprom_data != EEPROM_RESERVED_WORD) { 66462306a36Sopenharmony_ci /* Adjust SERDES output amplitude only. */ 66562306a36Sopenharmony_ci eeprom_data &= EEPROM_SERDES_AMPLITUDE_MASK; 66662306a36Sopenharmony_ci ret_val = 66762306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_PHY_EXT_CTRL, eeprom_data); 66862306a36Sopenharmony_ci if (ret_val) 66962306a36Sopenharmony_ci return ret_val; 67062306a36Sopenharmony_ci } 67162306a36Sopenharmony_ci 67262306a36Sopenharmony_ci return E1000_SUCCESS; 67362306a36Sopenharmony_ci} 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci/** 67662306a36Sopenharmony_ci * e1000_setup_link - Configures flow control and link settings. 67762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 67862306a36Sopenharmony_ci * 67962306a36Sopenharmony_ci * Determines which flow control settings to use. Calls the appropriate media- 68062306a36Sopenharmony_ci * specific link configuration function. Configures the flow control settings. 68162306a36Sopenharmony_ci * Assuming the adapter has a valid link partner, a valid link should be 68262306a36Sopenharmony_ci * established. Assumes the hardware has previously been reset and the 68362306a36Sopenharmony_ci * transmitter and receiver are not enabled. 68462306a36Sopenharmony_ci */ 68562306a36Sopenharmony_cis32 e1000_setup_link(struct e1000_hw *hw) 68662306a36Sopenharmony_ci{ 68762306a36Sopenharmony_ci u32 ctrl_ext; 68862306a36Sopenharmony_ci s32 ret_val; 68962306a36Sopenharmony_ci u16 eeprom_data; 69062306a36Sopenharmony_ci 69162306a36Sopenharmony_ci /* Read and store word 0x0F of the EEPROM. This word contains bits 69262306a36Sopenharmony_ci * that determine the hardware's default PAUSE (flow control) mode, 69362306a36Sopenharmony_ci * a bit that determines whether the HW defaults to enabling or 69462306a36Sopenharmony_ci * disabling auto-negotiation, and the direction of the 69562306a36Sopenharmony_ci * SW defined pins. If there is no SW over-ride of the flow 69662306a36Sopenharmony_ci * control setting, then the variable hw->fc will 69762306a36Sopenharmony_ci * be initialized based on a value in the EEPROM. 69862306a36Sopenharmony_ci */ 69962306a36Sopenharmony_ci if (hw->fc == E1000_FC_DEFAULT) { 70062306a36Sopenharmony_ci ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 70162306a36Sopenharmony_ci 1, &eeprom_data); 70262306a36Sopenharmony_ci if (ret_val) { 70362306a36Sopenharmony_ci e_dbg("EEPROM Read Error\n"); 70462306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 70562306a36Sopenharmony_ci } 70662306a36Sopenharmony_ci if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 0) 70762306a36Sopenharmony_ci hw->fc = E1000_FC_NONE; 70862306a36Sopenharmony_ci else if ((eeprom_data & EEPROM_WORD0F_PAUSE_MASK) == 70962306a36Sopenharmony_ci EEPROM_WORD0F_ASM_DIR) 71062306a36Sopenharmony_ci hw->fc = E1000_FC_TX_PAUSE; 71162306a36Sopenharmony_ci else 71262306a36Sopenharmony_ci hw->fc = E1000_FC_FULL; 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci /* We want to save off the original Flow Control configuration just 71662306a36Sopenharmony_ci * in case we get disconnected and then reconnected into a different 71762306a36Sopenharmony_ci * hub or switch with different Flow Control capabilities. 71862306a36Sopenharmony_ci */ 71962306a36Sopenharmony_ci if (hw->mac_type == e1000_82542_rev2_0) 72062306a36Sopenharmony_ci hw->fc &= (~E1000_FC_TX_PAUSE); 72162306a36Sopenharmony_ci 72262306a36Sopenharmony_ci if ((hw->mac_type < e1000_82543) && (hw->report_tx_early == 1)) 72362306a36Sopenharmony_ci hw->fc &= (~E1000_FC_RX_PAUSE); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci hw->original_fc = hw->fc; 72662306a36Sopenharmony_ci 72762306a36Sopenharmony_ci e_dbg("After fix-ups FlowControl is now = %x\n", hw->fc); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* Take the 4 bits from EEPROM word 0x0F that determine the initial 73062306a36Sopenharmony_ci * polarity value for the SW controlled pins, and setup the 73162306a36Sopenharmony_ci * Extended Device Control reg with that info. 73262306a36Sopenharmony_ci * This is needed because one of the SW controlled pins is used for 73362306a36Sopenharmony_ci * signal detection. So this should be done before e1000_setup_pcs_link() 73462306a36Sopenharmony_ci * or e1000_phy_setup() is called. 73562306a36Sopenharmony_ci */ 73662306a36Sopenharmony_ci if (hw->mac_type == e1000_82543) { 73762306a36Sopenharmony_ci ret_val = e1000_read_eeprom(hw, EEPROM_INIT_CONTROL2_REG, 73862306a36Sopenharmony_ci 1, &eeprom_data); 73962306a36Sopenharmony_ci if (ret_val) { 74062306a36Sopenharmony_ci e_dbg("EEPROM Read Error\n"); 74162306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci ctrl_ext = ((eeprom_data & EEPROM_WORD0F_SWPDIO_EXT) << 74462306a36Sopenharmony_ci SWDPIO__EXT_SHIFT); 74562306a36Sopenharmony_ci ew32(CTRL_EXT, ctrl_ext); 74662306a36Sopenharmony_ci } 74762306a36Sopenharmony_ci 74862306a36Sopenharmony_ci /* Call the necessary subroutine to configure the link. */ 74962306a36Sopenharmony_ci ret_val = (hw->media_type == e1000_media_type_copper) ? 75062306a36Sopenharmony_ci e1000_setup_copper_link(hw) : e1000_setup_fiber_serdes_link(hw); 75162306a36Sopenharmony_ci 75262306a36Sopenharmony_ci /* Initialize the flow control address, type, and PAUSE timer 75362306a36Sopenharmony_ci * registers to their default values. This is done even if flow 75462306a36Sopenharmony_ci * control is disabled, because it does not hurt anything to 75562306a36Sopenharmony_ci * initialize these registers. 75662306a36Sopenharmony_ci */ 75762306a36Sopenharmony_ci e_dbg("Initializing the Flow Control address, type and timer regs\n"); 75862306a36Sopenharmony_ci 75962306a36Sopenharmony_ci ew32(FCT, FLOW_CONTROL_TYPE); 76062306a36Sopenharmony_ci ew32(FCAH, FLOW_CONTROL_ADDRESS_HIGH); 76162306a36Sopenharmony_ci ew32(FCAL, FLOW_CONTROL_ADDRESS_LOW); 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_ci ew32(FCTTV, hw->fc_pause_time); 76462306a36Sopenharmony_ci 76562306a36Sopenharmony_ci /* Set the flow control receive threshold registers. Normally, 76662306a36Sopenharmony_ci * these registers will be set to a default threshold that may be 76762306a36Sopenharmony_ci * adjusted later by the driver's runtime code. However, if the 76862306a36Sopenharmony_ci * ability to transmit pause frames in not enabled, then these 76962306a36Sopenharmony_ci * registers will be set to 0. 77062306a36Sopenharmony_ci */ 77162306a36Sopenharmony_ci if (!(hw->fc & E1000_FC_TX_PAUSE)) { 77262306a36Sopenharmony_ci ew32(FCRTL, 0); 77362306a36Sopenharmony_ci ew32(FCRTH, 0); 77462306a36Sopenharmony_ci } else { 77562306a36Sopenharmony_ci /* We need to set up the Receive Threshold high and low water 77662306a36Sopenharmony_ci * marks as well as (optionally) enabling the transmission of 77762306a36Sopenharmony_ci * XON frames. 77862306a36Sopenharmony_ci */ 77962306a36Sopenharmony_ci if (hw->fc_send_xon) { 78062306a36Sopenharmony_ci ew32(FCRTL, (hw->fc_low_water | E1000_FCRTL_XONE)); 78162306a36Sopenharmony_ci ew32(FCRTH, hw->fc_high_water); 78262306a36Sopenharmony_ci } else { 78362306a36Sopenharmony_ci ew32(FCRTL, hw->fc_low_water); 78462306a36Sopenharmony_ci ew32(FCRTH, hw->fc_high_water); 78562306a36Sopenharmony_ci } 78662306a36Sopenharmony_ci } 78762306a36Sopenharmony_ci return ret_val; 78862306a36Sopenharmony_ci} 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_ci/** 79162306a36Sopenharmony_ci * e1000_setup_fiber_serdes_link - prepare fiber or serdes link 79262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 79362306a36Sopenharmony_ci * 79462306a36Sopenharmony_ci * Manipulates Physical Coding Sublayer functions in order to configure 79562306a36Sopenharmony_ci * link. Assumes the hardware has been previously reset and the transmitter 79662306a36Sopenharmony_ci * and receiver are not enabled. 79762306a36Sopenharmony_ci */ 79862306a36Sopenharmony_cistatic s32 e1000_setup_fiber_serdes_link(struct e1000_hw *hw) 79962306a36Sopenharmony_ci{ 80062306a36Sopenharmony_ci u32 ctrl; 80162306a36Sopenharmony_ci u32 status; 80262306a36Sopenharmony_ci u32 txcw = 0; 80362306a36Sopenharmony_ci u32 i; 80462306a36Sopenharmony_ci u32 signal = 0; 80562306a36Sopenharmony_ci s32 ret_val; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci /* On adapters with a MAC newer than 82544, SWDP 1 will be 80862306a36Sopenharmony_ci * set when the optics detect a signal. On older adapters, it will be 80962306a36Sopenharmony_ci * cleared when there is a signal. This applies to fiber media only. 81062306a36Sopenharmony_ci * If we're on serdes media, adjust the output amplitude to value 81162306a36Sopenharmony_ci * set in the EEPROM. 81262306a36Sopenharmony_ci */ 81362306a36Sopenharmony_ci ctrl = er32(CTRL); 81462306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_fiber) 81562306a36Sopenharmony_ci signal = (hw->mac_type > e1000_82544) ? E1000_CTRL_SWDPIN1 : 0; 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci ret_val = e1000_adjust_serdes_amplitude(hw); 81862306a36Sopenharmony_ci if (ret_val) 81962306a36Sopenharmony_ci return ret_val; 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci /* Take the link out of reset */ 82262306a36Sopenharmony_ci ctrl &= ~(E1000_CTRL_LRST); 82362306a36Sopenharmony_ci 82462306a36Sopenharmony_ci /* Adjust VCO speed to improve BER performance */ 82562306a36Sopenharmony_ci ret_val = e1000_set_vco_speed(hw); 82662306a36Sopenharmony_ci if (ret_val) 82762306a36Sopenharmony_ci return ret_val; 82862306a36Sopenharmony_ci 82962306a36Sopenharmony_ci e1000_config_collision_dist(hw); 83062306a36Sopenharmony_ci 83162306a36Sopenharmony_ci /* Check for a software override of the flow control settings, and setup 83262306a36Sopenharmony_ci * the device accordingly. If auto-negotiation is enabled, then 83362306a36Sopenharmony_ci * software will have to set the "PAUSE" bits to the correct value in 83462306a36Sopenharmony_ci * the Tranmsit Config Word Register (TXCW) and re-start 83562306a36Sopenharmony_ci * auto-negotiation. However, if auto-negotiation is disabled, then 83662306a36Sopenharmony_ci * software will have to manually configure the two flow control enable 83762306a36Sopenharmony_ci * bits in the CTRL register. 83862306a36Sopenharmony_ci * 83962306a36Sopenharmony_ci * The possible values of the "fc" parameter are: 84062306a36Sopenharmony_ci * 0: Flow control is completely disabled 84162306a36Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause frames, but 84262306a36Sopenharmony_ci * not send pause frames). 84362306a36Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames but we do 84462306a36Sopenharmony_ci * not support receiving pause frames). 84562306a36Sopenharmony_ci * 3: Both Rx and TX flow control (symmetric) are enabled. 84662306a36Sopenharmony_ci */ 84762306a36Sopenharmony_ci switch (hw->fc) { 84862306a36Sopenharmony_ci case E1000_FC_NONE: 84962306a36Sopenharmony_ci /* Flow ctrl is completely disabled by a software over-ride */ 85062306a36Sopenharmony_ci txcw = (E1000_TXCW_ANE | E1000_TXCW_FD); 85162306a36Sopenharmony_ci break; 85262306a36Sopenharmony_ci case E1000_FC_RX_PAUSE: 85362306a36Sopenharmony_ci /* Rx Flow control is enabled and Tx Flow control is disabled by 85462306a36Sopenharmony_ci * a software over-ride. Since there really isn't a way to 85562306a36Sopenharmony_ci * advertise that we are capable of Rx Pause ONLY, we will 85662306a36Sopenharmony_ci * advertise that we support both symmetric and asymmetric Rx 85762306a36Sopenharmony_ci * PAUSE. Later, we will disable the adapter's ability to send 85862306a36Sopenharmony_ci * PAUSE frames. 85962306a36Sopenharmony_ci */ 86062306a36Sopenharmony_ci txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); 86162306a36Sopenharmony_ci break; 86262306a36Sopenharmony_ci case E1000_FC_TX_PAUSE: 86362306a36Sopenharmony_ci /* Tx Flow control is enabled, and Rx Flow control is disabled, 86462306a36Sopenharmony_ci * by a software over-ride. 86562306a36Sopenharmony_ci */ 86662306a36Sopenharmony_ci txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_ASM_DIR); 86762306a36Sopenharmony_ci break; 86862306a36Sopenharmony_ci case E1000_FC_FULL: 86962306a36Sopenharmony_ci /* Flow control (both Rx and Tx) is enabled by a software 87062306a36Sopenharmony_ci * over-ride. 87162306a36Sopenharmony_ci */ 87262306a36Sopenharmony_ci txcw = (E1000_TXCW_ANE | E1000_TXCW_FD | E1000_TXCW_PAUSE_MASK); 87362306a36Sopenharmony_ci break; 87462306a36Sopenharmony_ci default: 87562306a36Sopenharmony_ci e_dbg("Flow control param set incorrectly\n"); 87662306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 87762306a36Sopenharmony_ci } 87862306a36Sopenharmony_ci 87962306a36Sopenharmony_ci /* Since auto-negotiation is enabled, take the link out of reset (the 88062306a36Sopenharmony_ci * link will be in reset, because we previously reset the chip). This 88162306a36Sopenharmony_ci * will restart auto-negotiation. If auto-negotiation is successful 88262306a36Sopenharmony_ci * then the link-up status bit will be set and the flow control enable 88362306a36Sopenharmony_ci * bits (RFCE and TFCE) will be set according to their negotiated value. 88462306a36Sopenharmony_ci */ 88562306a36Sopenharmony_ci e_dbg("Auto-negotiation enabled\n"); 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci ew32(TXCW, txcw); 88862306a36Sopenharmony_ci ew32(CTRL, ctrl); 88962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 89062306a36Sopenharmony_ci 89162306a36Sopenharmony_ci hw->txcw = txcw; 89262306a36Sopenharmony_ci msleep(1); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci /* If we have a signal (the cable is plugged in) then poll for a 89562306a36Sopenharmony_ci * "Link-Up" indication in the Device Status Register. Time-out if a 89662306a36Sopenharmony_ci * link isn't seen in 500 milliseconds seconds (Auto-negotiation should 89762306a36Sopenharmony_ci * complete in less than 500 milliseconds even if the other end is doing 89862306a36Sopenharmony_ci * it in SW). For internal serdes, we just assume a signal is present, 89962306a36Sopenharmony_ci * then poll. 90062306a36Sopenharmony_ci */ 90162306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_internal_serdes || 90262306a36Sopenharmony_ci (er32(CTRL) & E1000_CTRL_SWDPIN1) == signal) { 90362306a36Sopenharmony_ci e_dbg("Looking for Link\n"); 90462306a36Sopenharmony_ci for (i = 0; i < (LINK_UP_TIMEOUT / 10); i++) { 90562306a36Sopenharmony_ci msleep(10); 90662306a36Sopenharmony_ci status = er32(STATUS); 90762306a36Sopenharmony_ci if (status & E1000_STATUS_LU) 90862306a36Sopenharmony_ci break; 90962306a36Sopenharmony_ci } 91062306a36Sopenharmony_ci if (i == (LINK_UP_TIMEOUT / 10)) { 91162306a36Sopenharmony_ci e_dbg("Never got a valid link from auto-neg!!!\n"); 91262306a36Sopenharmony_ci hw->autoneg_failed = 1; 91362306a36Sopenharmony_ci /* AutoNeg failed to achieve a link, so we'll call 91462306a36Sopenharmony_ci * e1000_check_for_link. This routine will force the 91562306a36Sopenharmony_ci * link up if we detect a signal. This will allow us to 91662306a36Sopenharmony_ci * communicate with non-autonegotiating link partners. 91762306a36Sopenharmony_ci */ 91862306a36Sopenharmony_ci ret_val = e1000_check_for_link(hw); 91962306a36Sopenharmony_ci if (ret_val) { 92062306a36Sopenharmony_ci e_dbg("Error while checking for link\n"); 92162306a36Sopenharmony_ci return ret_val; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci hw->autoneg_failed = 0; 92462306a36Sopenharmony_ci } else { 92562306a36Sopenharmony_ci hw->autoneg_failed = 0; 92662306a36Sopenharmony_ci e_dbg("Valid Link Found\n"); 92762306a36Sopenharmony_ci } 92862306a36Sopenharmony_ci } else { 92962306a36Sopenharmony_ci e_dbg("No Signal Detected\n"); 93062306a36Sopenharmony_ci } 93162306a36Sopenharmony_ci return E1000_SUCCESS; 93262306a36Sopenharmony_ci} 93362306a36Sopenharmony_ci 93462306a36Sopenharmony_ci/** 93562306a36Sopenharmony_ci * e1000_copper_link_rtl_setup - Copper link setup for e1000_phy_rtl series. 93662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 93762306a36Sopenharmony_ci * 93862306a36Sopenharmony_ci * Commits changes to PHY configuration by calling e1000_phy_reset(). 93962306a36Sopenharmony_ci */ 94062306a36Sopenharmony_cistatic s32 e1000_copper_link_rtl_setup(struct e1000_hw *hw) 94162306a36Sopenharmony_ci{ 94262306a36Sopenharmony_ci s32 ret_val; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* SW reset the PHY so all changes take effect */ 94562306a36Sopenharmony_ci ret_val = e1000_phy_reset(hw); 94662306a36Sopenharmony_ci if (ret_val) { 94762306a36Sopenharmony_ci e_dbg("Error Resetting the PHY\n"); 94862306a36Sopenharmony_ci return ret_val; 94962306a36Sopenharmony_ci } 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_ci return E1000_SUCCESS; 95262306a36Sopenharmony_ci} 95362306a36Sopenharmony_ci 95462306a36Sopenharmony_cistatic s32 gbe_dhg_phy_setup(struct e1000_hw *hw) 95562306a36Sopenharmony_ci{ 95662306a36Sopenharmony_ci s32 ret_val; 95762306a36Sopenharmony_ci u32 ctrl_aux; 95862306a36Sopenharmony_ci 95962306a36Sopenharmony_ci switch (hw->phy_type) { 96062306a36Sopenharmony_ci case e1000_phy_8211: 96162306a36Sopenharmony_ci ret_val = e1000_copper_link_rtl_setup(hw); 96262306a36Sopenharmony_ci if (ret_val) { 96362306a36Sopenharmony_ci e_dbg("e1000_copper_link_rtl_setup failed!\n"); 96462306a36Sopenharmony_ci return ret_val; 96562306a36Sopenharmony_ci } 96662306a36Sopenharmony_ci break; 96762306a36Sopenharmony_ci case e1000_phy_8201: 96862306a36Sopenharmony_ci /* Set RMII mode */ 96962306a36Sopenharmony_ci ctrl_aux = er32(CTL_AUX); 97062306a36Sopenharmony_ci ctrl_aux |= E1000_CTL_AUX_RMII; 97162306a36Sopenharmony_ci ew32(CTL_AUX, ctrl_aux); 97262306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci /* Disable the J/K bits required for receive */ 97562306a36Sopenharmony_ci ctrl_aux = er32(CTL_AUX); 97662306a36Sopenharmony_ci ctrl_aux |= 0x4; 97762306a36Sopenharmony_ci ctrl_aux &= ~0x2; 97862306a36Sopenharmony_ci ew32(CTL_AUX, ctrl_aux); 97962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 98062306a36Sopenharmony_ci ret_val = e1000_copper_link_rtl_setup(hw); 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_ci if (ret_val) { 98362306a36Sopenharmony_ci e_dbg("e1000_copper_link_rtl_setup failed!\n"); 98462306a36Sopenharmony_ci return ret_val; 98562306a36Sopenharmony_ci } 98662306a36Sopenharmony_ci break; 98762306a36Sopenharmony_ci default: 98862306a36Sopenharmony_ci e_dbg("Error Resetting the PHY\n"); 98962306a36Sopenharmony_ci return E1000_ERR_PHY_TYPE; 99062306a36Sopenharmony_ci } 99162306a36Sopenharmony_ci 99262306a36Sopenharmony_ci return E1000_SUCCESS; 99362306a36Sopenharmony_ci} 99462306a36Sopenharmony_ci 99562306a36Sopenharmony_ci/** 99662306a36Sopenharmony_ci * e1000_copper_link_preconfig - early configuration for copper 99762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 99862306a36Sopenharmony_ci * 99962306a36Sopenharmony_ci * Make sure we have a valid PHY and change PHY mode before link setup. 100062306a36Sopenharmony_ci */ 100162306a36Sopenharmony_cistatic s32 e1000_copper_link_preconfig(struct e1000_hw *hw) 100262306a36Sopenharmony_ci{ 100362306a36Sopenharmony_ci u32 ctrl; 100462306a36Sopenharmony_ci s32 ret_val; 100562306a36Sopenharmony_ci u16 phy_data; 100662306a36Sopenharmony_ci 100762306a36Sopenharmony_ci ctrl = er32(CTRL); 100862306a36Sopenharmony_ci /* With 82543, we need to force speed and duplex on the MAC equal to 100962306a36Sopenharmony_ci * what the PHY speed and duplex configuration is. In addition, we need 101062306a36Sopenharmony_ci * to perform a hardware reset on the PHY to take it out of reset. 101162306a36Sopenharmony_ci */ 101262306a36Sopenharmony_ci if (hw->mac_type > e1000_82543) { 101362306a36Sopenharmony_ci ctrl |= E1000_CTRL_SLU; 101462306a36Sopenharmony_ci ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 101562306a36Sopenharmony_ci ew32(CTRL, ctrl); 101662306a36Sopenharmony_ci } else { 101762306a36Sopenharmony_ci ctrl |= 101862306a36Sopenharmony_ci (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX | E1000_CTRL_SLU); 101962306a36Sopenharmony_ci ew32(CTRL, ctrl); 102062306a36Sopenharmony_ci ret_val = e1000_phy_hw_reset(hw); 102162306a36Sopenharmony_ci if (ret_val) 102262306a36Sopenharmony_ci return ret_val; 102362306a36Sopenharmony_ci } 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci /* Make sure we have a valid PHY */ 102662306a36Sopenharmony_ci ret_val = e1000_detect_gig_phy(hw); 102762306a36Sopenharmony_ci if (ret_val) { 102862306a36Sopenharmony_ci e_dbg("Error, did not detect valid phy.\n"); 102962306a36Sopenharmony_ci return ret_val; 103062306a36Sopenharmony_ci } 103162306a36Sopenharmony_ci e_dbg("Phy ID = %x\n", hw->phy_id); 103262306a36Sopenharmony_ci 103362306a36Sopenharmony_ci /* Set PHY to class A mode (if necessary) */ 103462306a36Sopenharmony_ci ret_val = e1000_set_phy_mode(hw); 103562306a36Sopenharmony_ci if (ret_val) 103662306a36Sopenharmony_ci return ret_val; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci if ((hw->mac_type == e1000_82545_rev_3) || 103962306a36Sopenharmony_ci (hw->mac_type == e1000_82546_rev_3)) { 104062306a36Sopenharmony_ci ret_val = 104162306a36Sopenharmony_ci e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 104262306a36Sopenharmony_ci phy_data |= 0x00000008; 104362306a36Sopenharmony_ci ret_val = 104462306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); 104562306a36Sopenharmony_ci } 104662306a36Sopenharmony_ci 104762306a36Sopenharmony_ci if (hw->mac_type <= e1000_82543 || 104862306a36Sopenharmony_ci hw->mac_type == e1000_82541 || hw->mac_type == e1000_82547 || 104962306a36Sopenharmony_ci hw->mac_type == e1000_82541_rev_2 || 105062306a36Sopenharmony_ci hw->mac_type == e1000_82547_rev_2) 105162306a36Sopenharmony_ci hw->phy_reset_disable = false; 105262306a36Sopenharmony_ci 105362306a36Sopenharmony_ci return E1000_SUCCESS; 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ci/** 105762306a36Sopenharmony_ci * e1000_copper_link_igp_setup - Copper link setup for e1000_phy_igp series. 105862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 105962306a36Sopenharmony_ci */ 106062306a36Sopenharmony_cistatic s32 e1000_copper_link_igp_setup(struct e1000_hw *hw) 106162306a36Sopenharmony_ci{ 106262306a36Sopenharmony_ci u32 led_ctrl; 106362306a36Sopenharmony_ci s32 ret_val; 106462306a36Sopenharmony_ci u16 phy_data; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci if (hw->phy_reset_disable) 106762306a36Sopenharmony_ci return E1000_SUCCESS; 106862306a36Sopenharmony_ci 106962306a36Sopenharmony_ci ret_val = e1000_phy_reset(hw); 107062306a36Sopenharmony_ci if (ret_val) { 107162306a36Sopenharmony_ci e_dbg("Error Resetting the PHY\n"); 107262306a36Sopenharmony_ci return ret_val; 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci 107562306a36Sopenharmony_ci /* Wait 15ms for MAC to configure PHY from eeprom settings */ 107662306a36Sopenharmony_ci msleep(15); 107762306a36Sopenharmony_ci /* Configure activity LED after PHY reset */ 107862306a36Sopenharmony_ci led_ctrl = er32(LEDCTL); 107962306a36Sopenharmony_ci led_ctrl &= IGP_ACTIVITY_LED_MASK; 108062306a36Sopenharmony_ci led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 108162306a36Sopenharmony_ci ew32(LEDCTL, led_ctrl); 108262306a36Sopenharmony_ci 108362306a36Sopenharmony_ci /* The NVM settings will configure LPLU in D3 for IGP2 and IGP3 PHYs */ 108462306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_igp) { 108562306a36Sopenharmony_ci /* disable lplu d3 during driver init */ 108662306a36Sopenharmony_ci ret_val = e1000_set_d3_lplu_state(hw, false); 108762306a36Sopenharmony_ci if (ret_val) { 108862306a36Sopenharmony_ci e_dbg("Error Disabling LPLU D3\n"); 108962306a36Sopenharmony_ci return ret_val; 109062306a36Sopenharmony_ci } 109162306a36Sopenharmony_ci } 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_ci /* Configure mdi-mdix settings */ 109462306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); 109562306a36Sopenharmony_ci if (ret_val) 109662306a36Sopenharmony_ci return ret_val; 109762306a36Sopenharmony_ci 109862306a36Sopenharmony_ci if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { 109962306a36Sopenharmony_ci hw->dsp_config_state = e1000_dsp_config_disabled; 110062306a36Sopenharmony_ci /* Force MDI for earlier revs of the IGP PHY */ 110162306a36Sopenharmony_ci phy_data &= 110262306a36Sopenharmony_ci ~(IGP01E1000_PSCR_AUTO_MDIX | 110362306a36Sopenharmony_ci IGP01E1000_PSCR_FORCE_MDI_MDIX); 110462306a36Sopenharmony_ci hw->mdix = 1; 110562306a36Sopenharmony_ci 110662306a36Sopenharmony_ci } else { 110762306a36Sopenharmony_ci hw->dsp_config_state = e1000_dsp_config_enabled; 110862306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci switch (hw->mdix) { 111162306a36Sopenharmony_ci case 1: 111262306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; 111362306a36Sopenharmony_ci break; 111462306a36Sopenharmony_ci case 2: 111562306a36Sopenharmony_ci phy_data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; 111662306a36Sopenharmony_ci break; 111762306a36Sopenharmony_ci case 0: 111862306a36Sopenharmony_ci default: 111962306a36Sopenharmony_ci phy_data |= IGP01E1000_PSCR_AUTO_MDIX; 112062306a36Sopenharmony_ci break; 112162306a36Sopenharmony_ci } 112262306a36Sopenharmony_ci } 112362306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); 112462306a36Sopenharmony_ci if (ret_val) 112562306a36Sopenharmony_ci return ret_val; 112662306a36Sopenharmony_ci 112762306a36Sopenharmony_ci /* set auto-master slave resolution settings */ 112862306a36Sopenharmony_ci if (hw->autoneg) { 112962306a36Sopenharmony_ci e1000_ms_type phy_ms_setting = hw->master_slave; 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_ci if (hw->ffe_config_state == e1000_ffe_config_active) 113262306a36Sopenharmony_ci hw->ffe_config_state = e1000_ffe_config_enabled; 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci if (hw->dsp_config_state == e1000_dsp_config_activated) 113562306a36Sopenharmony_ci hw->dsp_config_state = e1000_dsp_config_enabled; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci /* when autonegotiation advertisement is only 1000Mbps then we 113862306a36Sopenharmony_ci * should disable SmartSpeed and enable Auto MasterSlave 113962306a36Sopenharmony_ci * resolution as hardware default. 114062306a36Sopenharmony_ci */ 114162306a36Sopenharmony_ci if (hw->autoneg_advertised == ADVERTISE_1000_FULL) { 114262306a36Sopenharmony_ci /* Disable SmartSpeed */ 114362306a36Sopenharmony_ci ret_val = 114462306a36Sopenharmony_ci e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 114562306a36Sopenharmony_ci &phy_data); 114662306a36Sopenharmony_ci if (ret_val) 114762306a36Sopenharmony_ci return ret_val; 114862306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; 114962306a36Sopenharmony_ci ret_val = 115062306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 115162306a36Sopenharmony_ci phy_data); 115262306a36Sopenharmony_ci if (ret_val) 115362306a36Sopenharmony_ci return ret_val; 115462306a36Sopenharmony_ci /* Set auto Master/Slave resolution process */ 115562306a36Sopenharmony_ci ret_val = 115662306a36Sopenharmony_ci e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); 115762306a36Sopenharmony_ci if (ret_val) 115862306a36Sopenharmony_ci return ret_val; 115962306a36Sopenharmony_ci phy_data &= ~CR_1000T_MS_ENABLE; 116062306a36Sopenharmony_ci ret_val = 116162306a36Sopenharmony_ci e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); 116262306a36Sopenharmony_ci if (ret_val) 116362306a36Sopenharmony_ci return ret_val; 116462306a36Sopenharmony_ci } 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &phy_data); 116762306a36Sopenharmony_ci if (ret_val) 116862306a36Sopenharmony_ci return ret_val; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci /* load defaults for future use */ 117162306a36Sopenharmony_ci hw->original_master_slave = (phy_data & CR_1000T_MS_ENABLE) ? 117262306a36Sopenharmony_ci ((phy_data & CR_1000T_MS_VALUE) ? 117362306a36Sopenharmony_ci e1000_ms_force_master : 117462306a36Sopenharmony_ci e1000_ms_force_slave) : e1000_ms_auto; 117562306a36Sopenharmony_ci 117662306a36Sopenharmony_ci switch (phy_ms_setting) { 117762306a36Sopenharmony_ci case e1000_ms_force_master: 117862306a36Sopenharmony_ci phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); 117962306a36Sopenharmony_ci break; 118062306a36Sopenharmony_ci case e1000_ms_force_slave: 118162306a36Sopenharmony_ci phy_data |= CR_1000T_MS_ENABLE; 118262306a36Sopenharmony_ci phy_data &= ~(CR_1000T_MS_VALUE); 118362306a36Sopenharmony_ci break; 118462306a36Sopenharmony_ci case e1000_ms_auto: 118562306a36Sopenharmony_ci phy_data &= ~CR_1000T_MS_ENABLE; 118662306a36Sopenharmony_ci break; 118762306a36Sopenharmony_ci default: 118862306a36Sopenharmony_ci break; 118962306a36Sopenharmony_ci } 119062306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, phy_data); 119162306a36Sopenharmony_ci if (ret_val) 119262306a36Sopenharmony_ci return ret_val; 119362306a36Sopenharmony_ci } 119462306a36Sopenharmony_ci 119562306a36Sopenharmony_ci return E1000_SUCCESS; 119662306a36Sopenharmony_ci} 119762306a36Sopenharmony_ci 119862306a36Sopenharmony_ci/** 119962306a36Sopenharmony_ci * e1000_copper_link_mgp_setup - Copper link setup for e1000_phy_m88 series. 120062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 120162306a36Sopenharmony_ci */ 120262306a36Sopenharmony_cistatic s32 e1000_copper_link_mgp_setup(struct e1000_hw *hw) 120362306a36Sopenharmony_ci{ 120462306a36Sopenharmony_ci s32 ret_val; 120562306a36Sopenharmony_ci u16 phy_data; 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci if (hw->phy_reset_disable) 120862306a36Sopenharmony_ci return E1000_SUCCESS; 120962306a36Sopenharmony_ci 121062306a36Sopenharmony_ci /* Enable CRS on TX. This must be set for half-duplex operation. */ 121162306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 121262306a36Sopenharmony_ci if (ret_val) 121362306a36Sopenharmony_ci return ret_val; 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_ci phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_ci /* Options: 121862306a36Sopenharmony_ci * MDI/MDI-X = 0 (default) 121962306a36Sopenharmony_ci * 0 - Auto for all speeds 122062306a36Sopenharmony_ci * 1 - MDI mode 122162306a36Sopenharmony_ci * 2 - MDI-X mode 122262306a36Sopenharmony_ci * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) 122362306a36Sopenharmony_ci */ 122462306a36Sopenharmony_ci phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci switch (hw->mdix) { 122762306a36Sopenharmony_ci case 1: 122862306a36Sopenharmony_ci phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; 122962306a36Sopenharmony_ci break; 123062306a36Sopenharmony_ci case 2: 123162306a36Sopenharmony_ci phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; 123262306a36Sopenharmony_ci break; 123362306a36Sopenharmony_ci case 3: 123462306a36Sopenharmony_ci phy_data |= M88E1000_PSCR_AUTO_X_1000T; 123562306a36Sopenharmony_ci break; 123662306a36Sopenharmony_ci case 0: 123762306a36Sopenharmony_ci default: 123862306a36Sopenharmony_ci phy_data |= M88E1000_PSCR_AUTO_X_MODE; 123962306a36Sopenharmony_ci break; 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci /* Options: 124362306a36Sopenharmony_ci * disable_polarity_correction = 0 (default) 124462306a36Sopenharmony_ci * Automatic Correction for Reversed Cable Polarity 124562306a36Sopenharmony_ci * 0 - Disabled 124662306a36Sopenharmony_ci * 1 - Enabled 124762306a36Sopenharmony_ci */ 124862306a36Sopenharmony_ci phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; 124962306a36Sopenharmony_ci if (hw->disable_polarity_correction == 1) 125062306a36Sopenharmony_ci phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; 125162306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); 125262306a36Sopenharmony_ci if (ret_val) 125362306a36Sopenharmony_ci return ret_val; 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci if (hw->phy_revision < M88E1011_I_REV_4) { 125662306a36Sopenharmony_ci /* Force TX_CLK in the Extended PHY Specific Control Register 125762306a36Sopenharmony_ci * to 25MHz clock. 125862306a36Sopenharmony_ci */ 125962306a36Sopenharmony_ci ret_val = 126062306a36Sopenharmony_ci e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, 126162306a36Sopenharmony_ci &phy_data); 126262306a36Sopenharmony_ci if (ret_val) 126362306a36Sopenharmony_ci return ret_val; 126462306a36Sopenharmony_ci 126562306a36Sopenharmony_ci phy_data |= M88E1000_EPSCR_TX_CLK_25; 126662306a36Sopenharmony_ci 126762306a36Sopenharmony_ci if ((hw->phy_revision == E1000_REVISION_2) && 126862306a36Sopenharmony_ci (hw->phy_id == M88E1111_I_PHY_ID)) { 126962306a36Sopenharmony_ci /* Vidalia Phy, set the downshift counter to 5x */ 127062306a36Sopenharmony_ci phy_data &= ~(M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK); 127162306a36Sopenharmony_ci phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; 127262306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 127362306a36Sopenharmony_ci M88E1000_EXT_PHY_SPEC_CTRL, 127462306a36Sopenharmony_ci phy_data); 127562306a36Sopenharmony_ci if (ret_val) 127662306a36Sopenharmony_ci return ret_val; 127762306a36Sopenharmony_ci } else { 127862306a36Sopenharmony_ci /* Configure Master and Slave downshift values */ 127962306a36Sopenharmony_ci phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | 128062306a36Sopenharmony_ci M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); 128162306a36Sopenharmony_ci phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | 128262306a36Sopenharmony_ci M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); 128362306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 128462306a36Sopenharmony_ci M88E1000_EXT_PHY_SPEC_CTRL, 128562306a36Sopenharmony_ci phy_data); 128662306a36Sopenharmony_ci if (ret_val) 128762306a36Sopenharmony_ci return ret_val; 128862306a36Sopenharmony_ci } 128962306a36Sopenharmony_ci } 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci /* SW Reset the PHY so all changes take effect */ 129262306a36Sopenharmony_ci ret_val = e1000_phy_reset(hw); 129362306a36Sopenharmony_ci if (ret_val) { 129462306a36Sopenharmony_ci e_dbg("Error Resetting the PHY\n"); 129562306a36Sopenharmony_ci return ret_val; 129662306a36Sopenharmony_ci } 129762306a36Sopenharmony_ci 129862306a36Sopenharmony_ci return E1000_SUCCESS; 129962306a36Sopenharmony_ci} 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci/** 130262306a36Sopenharmony_ci * e1000_copper_link_autoneg - setup auto-neg 130362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 130462306a36Sopenharmony_ci * 130562306a36Sopenharmony_ci * Setup auto-negotiation and flow control advertisements, 130662306a36Sopenharmony_ci * and then perform auto-negotiation. 130762306a36Sopenharmony_ci */ 130862306a36Sopenharmony_cistatic s32 e1000_copper_link_autoneg(struct e1000_hw *hw) 130962306a36Sopenharmony_ci{ 131062306a36Sopenharmony_ci s32 ret_val; 131162306a36Sopenharmony_ci u16 phy_data; 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_ci /* Perform some bounds checking on the hw->autoneg_advertised 131462306a36Sopenharmony_ci * parameter. If this variable is zero, then set it to the default. 131562306a36Sopenharmony_ci */ 131662306a36Sopenharmony_ci hw->autoneg_advertised &= AUTONEG_ADVERTISE_SPEED_DEFAULT; 131762306a36Sopenharmony_ci 131862306a36Sopenharmony_ci /* If autoneg_advertised is zero, we assume it was not defaulted 131962306a36Sopenharmony_ci * by the calling code so we set to advertise full capability. 132062306a36Sopenharmony_ci */ 132162306a36Sopenharmony_ci if (hw->autoneg_advertised == 0) 132262306a36Sopenharmony_ci hw->autoneg_advertised = AUTONEG_ADVERTISE_SPEED_DEFAULT; 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_ci /* IFE/RTL8201N PHY only supports 10/100 */ 132562306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_8201) 132662306a36Sopenharmony_ci hw->autoneg_advertised &= AUTONEG_ADVERTISE_10_100_ALL; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci e_dbg("Reconfiguring auto-neg advertisement params\n"); 132962306a36Sopenharmony_ci ret_val = e1000_phy_setup_autoneg(hw); 133062306a36Sopenharmony_ci if (ret_val) { 133162306a36Sopenharmony_ci e_dbg("Error Setting up Auto-Negotiation\n"); 133262306a36Sopenharmony_ci return ret_val; 133362306a36Sopenharmony_ci } 133462306a36Sopenharmony_ci e_dbg("Restarting Auto-Neg\n"); 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci /* Restart auto-negotiation by setting the Auto Neg Enable bit and 133762306a36Sopenharmony_ci * the Auto Neg Restart bit in the PHY control register. 133862306a36Sopenharmony_ci */ 133962306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); 134062306a36Sopenharmony_ci if (ret_val) 134162306a36Sopenharmony_ci return ret_val; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci phy_data |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); 134462306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); 134562306a36Sopenharmony_ci if (ret_val) 134662306a36Sopenharmony_ci return ret_val; 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci /* Does the user want to wait for Auto-Neg to complete here, or 134962306a36Sopenharmony_ci * check at a later time (for example, callback routine). 135062306a36Sopenharmony_ci */ 135162306a36Sopenharmony_ci if (hw->wait_autoneg_complete) { 135262306a36Sopenharmony_ci ret_val = e1000_wait_autoneg(hw); 135362306a36Sopenharmony_ci if (ret_val) { 135462306a36Sopenharmony_ci e_dbg 135562306a36Sopenharmony_ci ("Error while waiting for autoneg to complete\n"); 135662306a36Sopenharmony_ci return ret_val; 135762306a36Sopenharmony_ci } 135862306a36Sopenharmony_ci } 135962306a36Sopenharmony_ci 136062306a36Sopenharmony_ci hw->get_link_status = true; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci return E1000_SUCCESS; 136362306a36Sopenharmony_ci} 136462306a36Sopenharmony_ci 136562306a36Sopenharmony_ci/** 136662306a36Sopenharmony_ci * e1000_copper_link_postconfig - post link setup 136762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 136862306a36Sopenharmony_ci * 136962306a36Sopenharmony_ci * Config the MAC and the PHY after link is up. 137062306a36Sopenharmony_ci * 1) Set up the MAC to the current PHY speed/duplex 137162306a36Sopenharmony_ci * if we are on 82543. If we 137262306a36Sopenharmony_ci * are on newer silicon, we only need to configure 137362306a36Sopenharmony_ci * collision distance in the Transmit Control Register. 137462306a36Sopenharmony_ci * 2) Set up flow control on the MAC to that established with 137562306a36Sopenharmony_ci * the link partner. 137662306a36Sopenharmony_ci * 3) Config DSP to improve Gigabit link quality for some PHY revisions. 137762306a36Sopenharmony_ci */ 137862306a36Sopenharmony_cistatic s32 e1000_copper_link_postconfig(struct e1000_hw *hw) 137962306a36Sopenharmony_ci{ 138062306a36Sopenharmony_ci s32 ret_val; 138162306a36Sopenharmony_ci 138262306a36Sopenharmony_ci if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) { 138362306a36Sopenharmony_ci e1000_config_collision_dist(hw); 138462306a36Sopenharmony_ci } else { 138562306a36Sopenharmony_ci ret_val = e1000_config_mac_to_phy(hw); 138662306a36Sopenharmony_ci if (ret_val) { 138762306a36Sopenharmony_ci e_dbg("Error configuring MAC to PHY settings\n"); 138862306a36Sopenharmony_ci return ret_val; 138962306a36Sopenharmony_ci } 139062306a36Sopenharmony_ci } 139162306a36Sopenharmony_ci ret_val = e1000_config_fc_after_link_up(hw); 139262306a36Sopenharmony_ci if (ret_val) { 139362306a36Sopenharmony_ci e_dbg("Error Configuring Flow Control\n"); 139462306a36Sopenharmony_ci return ret_val; 139562306a36Sopenharmony_ci } 139662306a36Sopenharmony_ci 139762306a36Sopenharmony_ci /* Config DSP to improve Giga link quality */ 139862306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_igp) { 139962306a36Sopenharmony_ci ret_val = e1000_config_dsp_after_link_change(hw, true); 140062306a36Sopenharmony_ci if (ret_val) { 140162306a36Sopenharmony_ci e_dbg("Error Configuring DSP after link up\n"); 140262306a36Sopenharmony_ci return ret_val; 140362306a36Sopenharmony_ci } 140462306a36Sopenharmony_ci } 140562306a36Sopenharmony_ci 140662306a36Sopenharmony_ci return E1000_SUCCESS; 140762306a36Sopenharmony_ci} 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci/** 141062306a36Sopenharmony_ci * e1000_setup_copper_link - phy/speed/duplex setting 141162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 141262306a36Sopenharmony_ci * 141362306a36Sopenharmony_ci * Detects which PHY is present and sets up the speed and duplex 141462306a36Sopenharmony_ci */ 141562306a36Sopenharmony_cistatic s32 e1000_setup_copper_link(struct e1000_hw *hw) 141662306a36Sopenharmony_ci{ 141762306a36Sopenharmony_ci s32 ret_val; 141862306a36Sopenharmony_ci u16 i; 141962306a36Sopenharmony_ci u16 phy_data; 142062306a36Sopenharmony_ci 142162306a36Sopenharmony_ci /* Check if it is a valid PHY and set PHY mode if necessary. */ 142262306a36Sopenharmony_ci ret_val = e1000_copper_link_preconfig(hw); 142362306a36Sopenharmony_ci if (ret_val) 142462306a36Sopenharmony_ci return ret_val; 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_igp) { 142762306a36Sopenharmony_ci ret_val = e1000_copper_link_igp_setup(hw); 142862306a36Sopenharmony_ci if (ret_val) 142962306a36Sopenharmony_ci return ret_val; 143062306a36Sopenharmony_ci } else if (hw->phy_type == e1000_phy_m88) { 143162306a36Sopenharmony_ci ret_val = e1000_copper_link_mgp_setup(hw); 143262306a36Sopenharmony_ci if (ret_val) 143362306a36Sopenharmony_ci return ret_val; 143462306a36Sopenharmony_ci } else { 143562306a36Sopenharmony_ci ret_val = gbe_dhg_phy_setup(hw); 143662306a36Sopenharmony_ci if (ret_val) { 143762306a36Sopenharmony_ci e_dbg("gbe_dhg_phy_setup failed!\n"); 143862306a36Sopenharmony_ci return ret_val; 143962306a36Sopenharmony_ci } 144062306a36Sopenharmony_ci } 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci if (hw->autoneg) { 144362306a36Sopenharmony_ci /* Setup autoneg and flow control advertisement 144462306a36Sopenharmony_ci * and perform autonegotiation 144562306a36Sopenharmony_ci */ 144662306a36Sopenharmony_ci ret_val = e1000_copper_link_autoneg(hw); 144762306a36Sopenharmony_ci if (ret_val) 144862306a36Sopenharmony_ci return ret_val; 144962306a36Sopenharmony_ci } else { 145062306a36Sopenharmony_ci /* PHY will be set to 10H, 10F, 100H,or 100F 145162306a36Sopenharmony_ci * depending on value from forced_speed_duplex. 145262306a36Sopenharmony_ci */ 145362306a36Sopenharmony_ci e_dbg("Forcing speed and duplex\n"); 145462306a36Sopenharmony_ci ret_val = e1000_phy_force_speed_duplex(hw); 145562306a36Sopenharmony_ci if (ret_val) { 145662306a36Sopenharmony_ci e_dbg("Error Forcing Speed and Duplex\n"); 145762306a36Sopenharmony_ci return ret_val; 145862306a36Sopenharmony_ci } 145962306a36Sopenharmony_ci } 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci /* Check link status. Wait up to 100 microseconds for link to become 146262306a36Sopenharmony_ci * valid. 146362306a36Sopenharmony_ci */ 146462306a36Sopenharmony_ci for (i = 0; i < 10; i++) { 146562306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 146662306a36Sopenharmony_ci if (ret_val) 146762306a36Sopenharmony_ci return ret_val; 146862306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 146962306a36Sopenharmony_ci if (ret_val) 147062306a36Sopenharmony_ci return ret_val; 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_ci if (phy_data & MII_SR_LINK_STATUS) { 147362306a36Sopenharmony_ci /* Config the MAC and PHY after link is up */ 147462306a36Sopenharmony_ci ret_val = e1000_copper_link_postconfig(hw); 147562306a36Sopenharmony_ci if (ret_val) 147662306a36Sopenharmony_ci return ret_val; 147762306a36Sopenharmony_ci 147862306a36Sopenharmony_ci e_dbg("Valid link established!!!\n"); 147962306a36Sopenharmony_ci return E1000_SUCCESS; 148062306a36Sopenharmony_ci } 148162306a36Sopenharmony_ci udelay(10); 148262306a36Sopenharmony_ci } 148362306a36Sopenharmony_ci 148462306a36Sopenharmony_ci e_dbg("Unable to establish link!!!\n"); 148562306a36Sopenharmony_ci return E1000_SUCCESS; 148662306a36Sopenharmony_ci} 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci/** 148962306a36Sopenharmony_ci * e1000_phy_setup_autoneg - phy settings 149062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 149162306a36Sopenharmony_ci * 149262306a36Sopenharmony_ci * Configures PHY autoneg and flow control advertisement settings 149362306a36Sopenharmony_ci */ 149462306a36Sopenharmony_cis32 e1000_phy_setup_autoneg(struct e1000_hw *hw) 149562306a36Sopenharmony_ci{ 149662306a36Sopenharmony_ci s32 ret_val; 149762306a36Sopenharmony_ci u16 mii_autoneg_adv_reg; 149862306a36Sopenharmony_ci u16 mii_1000t_ctrl_reg; 149962306a36Sopenharmony_ci 150062306a36Sopenharmony_ci /* Read the MII Auto-Neg Advertisement Register (Address 4). */ 150162306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); 150262306a36Sopenharmony_ci if (ret_val) 150362306a36Sopenharmony_ci return ret_val; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci /* Read the MII 1000Base-T Control Register (Address 9). */ 150662306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_1000T_CTRL, &mii_1000t_ctrl_reg); 150762306a36Sopenharmony_ci if (ret_val) 150862306a36Sopenharmony_ci return ret_val; 150962306a36Sopenharmony_ci else if (hw->phy_type == e1000_phy_8201) 151062306a36Sopenharmony_ci mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; 151162306a36Sopenharmony_ci 151262306a36Sopenharmony_ci /* Need to parse both autoneg_advertised and fc and set up 151362306a36Sopenharmony_ci * the appropriate PHY registers. First we will parse for 151462306a36Sopenharmony_ci * autoneg_advertised software override. Since we can advertise 151562306a36Sopenharmony_ci * a plethora of combinations, we need to check each bit 151662306a36Sopenharmony_ci * individually. 151762306a36Sopenharmony_ci */ 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_ci /* First we clear all the 10/100 mb speed bits in the Auto-Neg 152062306a36Sopenharmony_ci * Advertisement Register (Address 4) and the 1000 mb speed bits in 152162306a36Sopenharmony_ci * the 1000Base-T Control Register (Address 9). 152262306a36Sopenharmony_ci */ 152362306a36Sopenharmony_ci mii_autoneg_adv_reg &= ~REG4_SPEED_MASK; 152462306a36Sopenharmony_ci mii_1000t_ctrl_reg &= ~REG9_SPEED_MASK; 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci e_dbg("autoneg_advertised %x\n", hw->autoneg_advertised); 152762306a36Sopenharmony_ci 152862306a36Sopenharmony_ci /* Do we want to advertise 10 Mb Half Duplex? */ 152962306a36Sopenharmony_ci if (hw->autoneg_advertised & ADVERTISE_10_HALF) { 153062306a36Sopenharmony_ci e_dbg("Advertise 10mb Half duplex\n"); 153162306a36Sopenharmony_ci mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; 153262306a36Sopenharmony_ci } 153362306a36Sopenharmony_ci 153462306a36Sopenharmony_ci /* Do we want to advertise 10 Mb Full Duplex? */ 153562306a36Sopenharmony_ci if (hw->autoneg_advertised & ADVERTISE_10_FULL) { 153662306a36Sopenharmony_ci e_dbg("Advertise 10mb Full duplex\n"); 153762306a36Sopenharmony_ci mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; 153862306a36Sopenharmony_ci } 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci /* Do we want to advertise 100 Mb Half Duplex? */ 154162306a36Sopenharmony_ci if (hw->autoneg_advertised & ADVERTISE_100_HALF) { 154262306a36Sopenharmony_ci e_dbg("Advertise 100mb Half duplex\n"); 154362306a36Sopenharmony_ci mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; 154462306a36Sopenharmony_ci } 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_ci /* Do we want to advertise 100 Mb Full Duplex? */ 154762306a36Sopenharmony_ci if (hw->autoneg_advertised & ADVERTISE_100_FULL) { 154862306a36Sopenharmony_ci e_dbg("Advertise 100mb Full duplex\n"); 154962306a36Sopenharmony_ci mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; 155062306a36Sopenharmony_ci } 155162306a36Sopenharmony_ci 155262306a36Sopenharmony_ci /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ 155362306a36Sopenharmony_ci if (hw->autoneg_advertised & ADVERTISE_1000_HALF) { 155462306a36Sopenharmony_ci e_dbg 155562306a36Sopenharmony_ci ("Advertise 1000mb Half duplex requested, request denied!\n"); 155662306a36Sopenharmony_ci } 155762306a36Sopenharmony_ci 155862306a36Sopenharmony_ci /* Do we want to advertise 1000 Mb Full Duplex? */ 155962306a36Sopenharmony_ci if (hw->autoneg_advertised & ADVERTISE_1000_FULL) { 156062306a36Sopenharmony_ci e_dbg("Advertise 1000mb Full duplex\n"); 156162306a36Sopenharmony_ci mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; 156262306a36Sopenharmony_ci } 156362306a36Sopenharmony_ci 156462306a36Sopenharmony_ci /* Check for a software override of the flow control settings, and 156562306a36Sopenharmony_ci * setup the PHY advertisement registers accordingly. If 156662306a36Sopenharmony_ci * auto-negotiation is enabled, then software will have to set the 156762306a36Sopenharmony_ci * "PAUSE" bits to the correct value in the Auto-Negotiation 156862306a36Sopenharmony_ci * Advertisement Register (PHY_AUTONEG_ADV) and re-start 156962306a36Sopenharmony_ci * auto-negotiation. 157062306a36Sopenharmony_ci * 157162306a36Sopenharmony_ci * The possible values of the "fc" parameter are: 157262306a36Sopenharmony_ci * 0: Flow control is completely disabled 157362306a36Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause frames 157462306a36Sopenharmony_ci * but not send pause frames). 157562306a36Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames 157662306a36Sopenharmony_ci * but we do not support receiving pause frames). 157762306a36Sopenharmony_ci * 3: Both Rx and TX flow control (symmetric) are enabled. 157862306a36Sopenharmony_ci * other: No software override. The flow control configuration 157962306a36Sopenharmony_ci * in the EEPROM is used. 158062306a36Sopenharmony_ci */ 158162306a36Sopenharmony_ci switch (hw->fc) { 158262306a36Sopenharmony_ci case E1000_FC_NONE: /* 0 */ 158362306a36Sopenharmony_ci /* Flow control (RX & TX) is completely disabled by a 158462306a36Sopenharmony_ci * software over-ride. 158562306a36Sopenharmony_ci */ 158662306a36Sopenharmony_ci mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 158762306a36Sopenharmony_ci break; 158862306a36Sopenharmony_ci case E1000_FC_RX_PAUSE: /* 1 */ 158962306a36Sopenharmony_ci /* RX Flow control is enabled, and TX Flow control is 159062306a36Sopenharmony_ci * disabled, by a software over-ride. 159162306a36Sopenharmony_ci */ 159262306a36Sopenharmony_ci /* Since there really isn't a way to advertise that we are 159362306a36Sopenharmony_ci * capable of RX Pause ONLY, we will advertise that we 159462306a36Sopenharmony_ci * support both symmetric and asymmetric RX PAUSE. Later 159562306a36Sopenharmony_ci * (in e1000_config_fc_after_link_up) we will disable the 159662306a36Sopenharmony_ci * hw's ability to send PAUSE frames. 159762306a36Sopenharmony_ci */ 159862306a36Sopenharmony_ci mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 159962306a36Sopenharmony_ci break; 160062306a36Sopenharmony_ci case E1000_FC_TX_PAUSE: /* 2 */ 160162306a36Sopenharmony_ci /* TX Flow control is enabled, and RX Flow control is 160262306a36Sopenharmony_ci * disabled, by a software over-ride. 160362306a36Sopenharmony_ci */ 160462306a36Sopenharmony_ci mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; 160562306a36Sopenharmony_ci mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; 160662306a36Sopenharmony_ci break; 160762306a36Sopenharmony_ci case E1000_FC_FULL: /* 3 */ 160862306a36Sopenharmony_ci /* Flow control (both RX and TX) is enabled by a software 160962306a36Sopenharmony_ci * over-ride. 161062306a36Sopenharmony_ci */ 161162306a36Sopenharmony_ci mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 161262306a36Sopenharmony_ci break; 161362306a36Sopenharmony_ci default: 161462306a36Sopenharmony_ci e_dbg("Flow control param set incorrectly\n"); 161562306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 161662306a36Sopenharmony_ci } 161762306a36Sopenharmony_ci 161862306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); 161962306a36Sopenharmony_ci if (ret_val) 162062306a36Sopenharmony_ci return ret_val; 162162306a36Sopenharmony_ci 162262306a36Sopenharmony_ci e_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_8201) { 162562306a36Sopenharmony_ci mii_1000t_ctrl_reg = 0; 162662306a36Sopenharmony_ci } else { 162762306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, PHY_1000T_CTRL, 162862306a36Sopenharmony_ci mii_1000t_ctrl_reg); 162962306a36Sopenharmony_ci if (ret_val) 163062306a36Sopenharmony_ci return ret_val; 163162306a36Sopenharmony_ci } 163262306a36Sopenharmony_ci 163362306a36Sopenharmony_ci return E1000_SUCCESS; 163462306a36Sopenharmony_ci} 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci/** 163762306a36Sopenharmony_ci * e1000_phy_force_speed_duplex - force link settings 163862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 163962306a36Sopenharmony_ci * 164062306a36Sopenharmony_ci * Force PHY speed and duplex settings to hw->forced_speed_duplex 164162306a36Sopenharmony_ci */ 164262306a36Sopenharmony_cistatic s32 e1000_phy_force_speed_duplex(struct e1000_hw *hw) 164362306a36Sopenharmony_ci{ 164462306a36Sopenharmony_ci u32 ctrl; 164562306a36Sopenharmony_ci s32 ret_val; 164662306a36Sopenharmony_ci u16 mii_ctrl_reg; 164762306a36Sopenharmony_ci u16 mii_status_reg; 164862306a36Sopenharmony_ci u16 phy_data; 164962306a36Sopenharmony_ci u16 i; 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_ci /* Turn off Flow control if we are forcing speed and duplex. */ 165262306a36Sopenharmony_ci hw->fc = E1000_FC_NONE; 165362306a36Sopenharmony_ci 165462306a36Sopenharmony_ci e_dbg("hw->fc = %d\n", hw->fc); 165562306a36Sopenharmony_ci 165662306a36Sopenharmony_ci /* Read the Device Control Register. */ 165762306a36Sopenharmony_ci ctrl = er32(CTRL); 165862306a36Sopenharmony_ci 165962306a36Sopenharmony_ci /* Set the bits to Force Speed and Duplex in the Device Ctrl Reg. */ 166062306a36Sopenharmony_ci ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 166162306a36Sopenharmony_ci ctrl &= ~(DEVICE_SPEED_MASK); 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_ci /* Clear the Auto Speed Detect Enable bit. */ 166462306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_ASDE; 166562306a36Sopenharmony_ci 166662306a36Sopenharmony_ci /* Read the MII Control Register. */ 166762306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &mii_ctrl_reg); 166862306a36Sopenharmony_ci if (ret_val) 166962306a36Sopenharmony_ci return ret_val; 167062306a36Sopenharmony_ci 167162306a36Sopenharmony_ci /* We need to disable autoneg in order to force link and duplex. */ 167262306a36Sopenharmony_ci 167362306a36Sopenharmony_ci mii_ctrl_reg &= ~MII_CR_AUTO_NEG_EN; 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_ci /* Are we forcing Full or Half Duplex? */ 167662306a36Sopenharmony_ci if (hw->forced_speed_duplex == e1000_100_full || 167762306a36Sopenharmony_ci hw->forced_speed_duplex == e1000_10_full) { 167862306a36Sopenharmony_ci /* We want to force full duplex so we SET the full duplex bits 167962306a36Sopenharmony_ci * in the Device and MII Control Registers. 168062306a36Sopenharmony_ci */ 168162306a36Sopenharmony_ci ctrl |= E1000_CTRL_FD; 168262306a36Sopenharmony_ci mii_ctrl_reg |= MII_CR_FULL_DUPLEX; 168362306a36Sopenharmony_ci e_dbg("Full Duplex\n"); 168462306a36Sopenharmony_ci } else { 168562306a36Sopenharmony_ci /* We want to force half duplex so we CLEAR the full duplex bits 168662306a36Sopenharmony_ci * in the Device and MII Control Registers. 168762306a36Sopenharmony_ci */ 168862306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_FD; 168962306a36Sopenharmony_ci mii_ctrl_reg &= ~MII_CR_FULL_DUPLEX; 169062306a36Sopenharmony_ci e_dbg("Half Duplex\n"); 169162306a36Sopenharmony_ci } 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_ci /* Are we forcing 100Mbps??? */ 169462306a36Sopenharmony_ci if (hw->forced_speed_duplex == e1000_100_full || 169562306a36Sopenharmony_ci hw->forced_speed_duplex == e1000_100_half) { 169662306a36Sopenharmony_ci /* Set the 100Mb bit and turn off the 1000Mb and 10Mb bits. */ 169762306a36Sopenharmony_ci ctrl |= E1000_CTRL_SPD_100; 169862306a36Sopenharmony_ci mii_ctrl_reg |= MII_CR_SPEED_100; 169962306a36Sopenharmony_ci mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); 170062306a36Sopenharmony_ci e_dbg("Forcing 100mb "); 170162306a36Sopenharmony_ci } else { 170262306a36Sopenharmony_ci /* Set the 10Mb bit and turn off the 1000Mb and 100Mb bits. */ 170362306a36Sopenharmony_ci ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); 170462306a36Sopenharmony_ci mii_ctrl_reg |= MII_CR_SPEED_10; 170562306a36Sopenharmony_ci mii_ctrl_reg &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); 170662306a36Sopenharmony_ci e_dbg("Forcing 10mb "); 170762306a36Sopenharmony_ci } 170862306a36Sopenharmony_ci 170962306a36Sopenharmony_ci e1000_config_collision_dist(hw); 171062306a36Sopenharmony_ci 171162306a36Sopenharmony_ci /* Write the configured values back to the Device Control Reg. */ 171262306a36Sopenharmony_ci ew32(CTRL, ctrl); 171362306a36Sopenharmony_ci 171462306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_m88) { 171562306a36Sopenharmony_ci ret_val = 171662306a36Sopenharmony_ci e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 171762306a36Sopenharmony_ci if (ret_val) 171862306a36Sopenharmony_ci return ret_val; 171962306a36Sopenharmony_ci 172062306a36Sopenharmony_ci /* Clear Auto-Crossover to force MDI manually. M88E1000 requires 172162306a36Sopenharmony_ci * MDI forced whenever speed are duplex are forced. 172262306a36Sopenharmony_ci */ 172362306a36Sopenharmony_ci phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; 172462306a36Sopenharmony_ci ret_val = 172562306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); 172662306a36Sopenharmony_ci if (ret_val) 172762306a36Sopenharmony_ci return ret_val; 172862306a36Sopenharmony_ci 172962306a36Sopenharmony_ci e_dbg("M88E1000 PSCR: %x\n", phy_data); 173062306a36Sopenharmony_ci 173162306a36Sopenharmony_ci /* Need to reset the PHY or these changes will be ignored */ 173262306a36Sopenharmony_ci mii_ctrl_reg |= MII_CR_RESET; 173362306a36Sopenharmony_ci 173462306a36Sopenharmony_ci /* Disable MDI-X support for 10/100 */ 173562306a36Sopenharmony_ci } else { 173662306a36Sopenharmony_ci /* Clear Auto-Crossover to force MDI manually. IGP requires MDI 173762306a36Sopenharmony_ci * forced whenever speed or duplex are forced. 173862306a36Sopenharmony_ci */ 173962306a36Sopenharmony_ci ret_val = 174062306a36Sopenharmony_ci e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); 174162306a36Sopenharmony_ci if (ret_val) 174262306a36Sopenharmony_ci return ret_val; 174362306a36Sopenharmony_ci 174462306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; 174562306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; 174662306a36Sopenharmony_ci 174762306a36Sopenharmony_ci ret_val = 174862306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); 174962306a36Sopenharmony_ci if (ret_val) 175062306a36Sopenharmony_ci return ret_val; 175162306a36Sopenharmony_ci } 175262306a36Sopenharmony_ci 175362306a36Sopenharmony_ci /* Write back the modified PHY MII control register. */ 175462306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, PHY_CTRL, mii_ctrl_reg); 175562306a36Sopenharmony_ci if (ret_val) 175662306a36Sopenharmony_ci return ret_val; 175762306a36Sopenharmony_ci 175862306a36Sopenharmony_ci udelay(1); 175962306a36Sopenharmony_ci 176062306a36Sopenharmony_ci /* The wait_autoneg_complete flag may be a little misleading here. 176162306a36Sopenharmony_ci * Since we are forcing speed and duplex, Auto-Neg is not enabled. 176262306a36Sopenharmony_ci * But we do want to delay for a period while forcing only so we 176362306a36Sopenharmony_ci * don't generate false No Link messages. So we will wait here 176462306a36Sopenharmony_ci * only if the user has set wait_autoneg_complete to 1, which is 176562306a36Sopenharmony_ci * the default. 176662306a36Sopenharmony_ci */ 176762306a36Sopenharmony_ci if (hw->wait_autoneg_complete) { 176862306a36Sopenharmony_ci /* We will wait for autoneg to complete. */ 176962306a36Sopenharmony_ci e_dbg("Waiting for forced speed/duplex link.\n"); 177062306a36Sopenharmony_ci mii_status_reg = 0; 177162306a36Sopenharmony_ci 177262306a36Sopenharmony_ci /* Wait for autoneg to complete or 4.5 seconds to expire */ 177362306a36Sopenharmony_ci for (i = PHY_FORCE_TIME; i > 0; i--) { 177462306a36Sopenharmony_ci /* Read the MII Status Register and wait for Auto-Neg 177562306a36Sopenharmony_ci * Complete bit to be set. 177662306a36Sopenharmony_ci */ 177762306a36Sopenharmony_ci ret_val = 177862306a36Sopenharmony_ci e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 177962306a36Sopenharmony_ci if (ret_val) 178062306a36Sopenharmony_ci return ret_val; 178162306a36Sopenharmony_ci 178262306a36Sopenharmony_ci ret_val = 178362306a36Sopenharmony_ci e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 178462306a36Sopenharmony_ci if (ret_val) 178562306a36Sopenharmony_ci return ret_val; 178662306a36Sopenharmony_ci 178762306a36Sopenharmony_ci if (mii_status_reg & MII_SR_LINK_STATUS) 178862306a36Sopenharmony_ci break; 178962306a36Sopenharmony_ci msleep(100); 179062306a36Sopenharmony_ci } 179162306a36Sopenharmony_ci if ((i == 0) && (hw->phy_type == e1000_phy_m88)) { 179262306a36Sopenharmony_ci /* We didn't get link. Reset the DSP and wait again 179362306a36Sopenharmony_ci * for link. 179462306a36Sopenharmony_ci */ 179562306a36Sopenharmony_ci ret_val = e1000_phy_reset_dsp(hw); 179662306a36Sopenharmony_ci if (ret_val) { 179762306a36Sopenharmony_ci e_dbg("Error Resetting PHY DSP\n"); 179862306a36Sopenharmony_ci return ret_val; 179962306a36Sopenharmony_ci } 180062306a36Sopenharmony_ci } 180162306a36Sopenharmony_ci /* This loop will early-out if the link condition has been 180262306a36Sopenharmony_ci * met 180362306a36Sopenharmony_ci */ 180462306a36Sopenharmony_ci for (i = PHY_FORCE_TIME; i > 0; i--) { 180562306a36Sopenharmony_ci if (mii_status_reg & MII_SR_LINK_STATUS) 180662306a36Sopenharmony_ci break; 180762306a36Sopenharmony_ci msleep(100); 180862306a36Sopenharmony_ci /* Read the MII Status Register and wait for Auto-Neg 180962306a36Sopenharmony_ci * Complete bit to be set. 181062306a36Sopenharmony_ci */ 181162306a36Sopenharmony_ci ret_val = 181262306a36Sopenharmony_ci e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 181362306a36Sopenharmony_ci if (ret_val) 181462306a36Sopenharmony_ci return ret_val; 181562306a36Sopenharmony_ci 181662306a36Sopenharmony_ci ret_val = 181762306a36Sopenharmony_ci e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 181862306a36Sopenharmony_ci if (ret_val) 181962306a36Sopenharmony_ci return ret_val; 182062306a36Sopenharmony_ci } 182162306a36Sopenharmony_ci } 182262306a36Sopenharmony_ci 182362306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_m88) { 182462306a36Sopenharmony_ci /* Because we reset the PHY above, we need to re-force TX_CLK in 182562306a36Sopenharmony_ci * the Extended PHY Specific Control Register to 25MHz clock. 182662306a36Sopenharmony_ci * This value defaults back to a 2.5MHz clock when the PHY is 182762306a36Sopenharmony_ci * reset. 182862306a36Sopenharmony_ci */ 182962306a36Sopenharmony_ci ret_val = 183062306a36Sopenharmony_ci e1000_read_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, 183162306a36Sopenharmony_ci &phy_data); 183262306a36Sopenharmony_ci if (ret_val) 183362306a36Sopenharmony_ci return ret_val; 183462306a36Sopenharmony_ci 183562306a36Sopenharmony_ci phy_data |= M88E1000_EPSCR_TX_CLK_25; 183662306a36Sopenharmony_ci ret_val = 183762306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, 183862306a36Sopenharmony_ci phy_data); 183962306a36Sopenharmony_ci if (ret_val) 184062306a36Sopenharmony_ci return ret_val; 184162306a36Sopenharmony_ci 184262306a36Sopenharmony_ci /* In addition, because of the s/w reset above, we need to 184362306a36Sopenharmony_ci * enable CRS on Tx. This must be set for both full and half 184462306a36Sopenharmony_ci * duplex operation. 184562306a36Sopenharmony_ci */ 184662306a36Sopenharmony_ci ret_val = 184762306a36Sopenharmony_ci e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 184862306a36Sopenharmony_ci if (ret_val) 184962306a36Sopenharmony_ci return ret_val; 185062306a36Sopenharmony_ci 185162306a36Sopenharmony_ci phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; 185262306a36Sopenharmony_ci ret_val = 185362306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); 185462306a36Sopenharmony_ci if (ret_val) 185562306a36Sopenharmony_ci return ret_val; 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_ci if ((hw->mac_type == e1000_82544 || 185862306a36Sopenharmony_ci hw->mac_type == e1000_82543) && 185962306a36Sopenharmony_ci (!hw->autoneg) && 186062306a36Sopenharmony_ci (hw->forced_speed_duplex == e1000_10_full || 186162306a36Sopenharmony_ci hw->forced_speed_duplex == e1000_10_half)) { 186262306a36Sopenharmony_ci ret_val = e1000_polarity_reversal_workaround(hw); 186362306a36Sopenharmony_ci if (ret_val) 186462306a36Sopenharmony_ci return ret_val; 186562306a36Sopenharmony_ci } 186662306a36Sopenharmony_ci } 186762306a36Sopenharmony_ci return E1000_SUCCESS; 186862306a36Sopenharmony_ci} 186962306a36Sopenharmony_ci 187062306a36Sopenharmony_ci/** 187162306a36Sopenharmony_ci * e1000_config_collision_dist - set collision distance register 187262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 187362306a36Sopenharmony_ci * 187462306a36Sopenharmony_ci * Sets the collision distance in the Transmit Control register. 187562306a36Sopenharmony_ci * Link should have been established previously. Reads the speed and duplex 187662306a36Sopenharmony_ci * information from the Device Status register. 187762306a36Sopenharmony_ci */ 187862306a36Sopenharmony_civoid e1000_config_collision_dist(struct e1000_hw *hw) 187962306a36Sopenharmony_ci{ 188062306a36Sopenharmony_ci u32 tctl, coll_dist; 188162306a36Sopenharmony_ci 188262306a36Sopenharmony_ci if (hw->mac_type < e1000_82543) 188362306a36Sopenharmony_ci coll_dist = E1000_COLLISION_DISTANCE_82542; 188462306a36Sopenharmony_ci else 188562306a36Sopenharmony_ci coll_dist = E1000_COLLISION_DISTANCE; 188662306a36Sopenharmony_ci 188762306a36Sopenharmony_ci tctl = er32(TCTL); 188862306a36Sopenharmony_ci 188962306a36Sopenharmony_ci tctl &= ~E1000_TCTL_COLD; 189062306a36Sopenharmony_ci tctl |= coll_dist << E1000_COLD_SHIFT; 189162306a36Sopenharmony_ci 189262306a36Sopenharmony_ci ew32(TCTL, tctl); 189362306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 189462306a36Sopenharmony_ci} 189562306a36Sopenharmony_ci 189662306a36Sopenharmony_ci/** 189762306a36Sopenharmony_ci * e1000_config_mac_to_phy - sync phy and mac settings 189862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 189962306a36Sopenharmony_ci * 190062306a36Sopenharmony_ci * Sets MAC speed and duplex settings to reflect the those in the PHY 190162306a36Sopenharmony_ci * The contents of the PHY register containing the needed information need to 190262306a36Sopenharmony_ci * be passed in. 190362306a36Sopenharmony_ci */ 190462306a36Sopenharmony_cistatic s32 e1000_config_mac_to_phy(struct e1000_hw *hw) 190562306a36Sopenharmony_ci{ 190662306a36Sopenharmony_ci u32 ctrl; 190762306a36Sopenharmony_ci s32 ret_val; 190862306a36Sopenharmony_ci u16 phy_data; 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci /* 82544 or newer MAC, Auto Speed Detection takes care of 191162306a36Sopenharmony_ci * MAC speed/duplex configuration. 191262306a36Sopenharmony_ci */ 191362306a36Sopenharmony_ci if ((hw->mac_type >= e1000_82544) && (hw->mac_type != e1000_ce4100)) 191462306a36Sopenharmony_ci return E1000_SUCCESS; 191562306a36Sopenharmony_ci 191662306a36Sopenharmony_ci /* Read the Device Control Register and set the bits to Force Speed 191762306a36Sopenharmony_ci * and Duplex. 191862306a36Sopenharmony_ci */ 191962306a36Sopenharmony_ci ctrl = er32(CTRL); 192062306a36Sopenharmony_ci ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 192162306a36Sopenharmony_ci ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); 192262306a36Sopenharmony_ci 192362306a36Sopenharmony_ci switch (hw->phy_type) { 192462306a36Sopenharmony_ci case e1000_phy_8201: 192562306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); 192662306a36Sopenharmony_ci if (ret_val) 192762306a36Sopenharmony_ci return ret_val; 192862306a36Sopenharmony_ci 192962306a36Sopenharmony_ci if (phy_data & RTL_PHY_CTRL_FD) 193062306a36Sopenharmony_ci ctrl |= E1000_CTRL_FD; 193162306a36Sopenharmony_ci else 193262306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_FD; 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci if (phy_data & RTL_PHY_CTRL_SPD_100) 193562306a36Sopenharmony_ci ctrl |= E1000_CTRL_SPD_100; 193662306a36Sopenharmony_ci else 193762306a36Sopenharmony_ci ctrl |= E1000_CTRL_SPD_10; 193862306a36Sopenharmony_ci 193962306a36Sopenharmony_ci e1000_config_collision_dist(hw); 194062306a36Sopenharmony_ci break; 194162306a36Sopenharmony_ci default: 194262306a36Sopenharmony_ci /* Set up duplex in the Device Control and Transmit Control 194362306a36Sopenharmony_ci * registers depending on negotiated values. 194462306a36Sopenharmony_ci */ 194562306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, 194662306a36Sopenharmony_ci &phy_data); 194762306a36Sopenharmony_ci if (ret_val) 194862306a36Sopenharmony_ci return ret_val; 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci if (phy_data & M88E1000_PSSR_DPLX) 195162306a36Sopenharmony_ci ctrl |= E1000_CTRL_FD; 195262306a36Sopenharmony_ci else 195362306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_FD; 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci e1000_config_collision_dist(hw); 195662306a36Sopenharmony_ci 195762306a36Sopenharmony_ci /* Set up speed in the Device Control register depending on 195862306a36Sopenharmony_ci * negotiated values. 195962306a36Sopenharmony_ci */ 196062306a36Sopenharmony_ci if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) 196162306a36Sopenharmony_ci ctrl |= E1000_CTRL_SPD_1000; 196262306a36Sopenharmony_ci else if ((phy_data & M88E1000_PSSR_SPEED) == 196362306a36Sopenharmony_ci M88E1000_PSSR_100MBS) 196462306a36Sopenharmony_ci ctrl |= E1000_CTRL_SPD_100; 196562306a36Sopenharmony_ci } 196662306a36Sopenharmony_ci 196762306a36Sopenharmony_ci /* Write the configured values back to the Device Control Reg. */ 196862306a36Sopenharmony_ci ew32(CTRL, ctrl); 196962306a36Sopenharmony_ci return E1000_SUCCESS; 197062306a36Sopenharmony_ci} 197162306a36Sopenharmony_ci 197262306a36Sopenharmony_ci/** 197362306a36Sopenharmony_ci * e1000_force_mac_fc - force flow control settings 197462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 197562306a36Sopenharmony_ci * 197662306a36Sopenharmony_ci * Forces the MAC's flow control settings. 197762306a36Sopenharmony_ci * Sets the TFCE and RFCE bits in the device control register to reflect 197862306a36Sopenharmony_ci * the adapter settings. TFCE and RFCE need to be explicitly set by 197962306a36Sopenharmony_ci * software when a Copper PHY is used because autonegotiation is managed 198062306a36Sopenharmony_ci * by the PHY rather than the MAC. Software must also configure these 198162306a36Sopenharmony_ci * bits when link is forced on a fiber connection. 198262306a36Sopenharmony_ci */ 198362306a36Sopenharmony_cis32 e1000_force_mac_fc(struct e1000_hw *hw) 198462306a36Sopenharmony_ci{ 198562306a36Sopenharmony_ci u32 ctrl; 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_ci /* Get the current configuration of the Device Control Register */ 198862306a36Sopenharmony_ci ctrl = er32(CTRL); 198962306a36Sopenharmony_ci 199062306a36Sopenharmony_ci /* Because we didn't get link via the internal auto-negotiation 199162306a36Sopenharmony_ci * mechanism (we either forced link or we got link via PHY 199262306a36Sopenharmony_ci * auto-neg), we have to manually enable/disable transmit an 199362306a36Sopenharmony_ci * receive flow control. 199462306a36Sopenharmony_ci * 199562306a36Sopenharmony_ci * The "Case" statement below enables/disable flow control 199662306a36Sopenharmony_ci * according to the "hw->fc" parameter. 199762306a36Sopenharmony_ci * 199862306a36Sopenharmony_ci * The possible values of the "fc" parameter are: 199962306a36Sopenharmony_ci * 0: Flow control is completely disabled 200062306a36Sopenharmony_ci * 1: Rx flow control is enabled (we can receive pause 200162306a36Sopenharmony_ci * frames but not send pause frames). 200262306a36Sopenharmony_ci * 2: Tx flow control is enabled (we can send pause frames 200362306a36Sopenharmony_ci * but we do not receive pause frames). 200462306a36Sopenharmony_ci * 3: Both Rx and TX flow control (symmetric) is enabled. 200562306a36Sopenharmony_ci * other: No other values should be possible at this point. 200662306a36Sopenharmony_ci */ 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci switch (hw->fc) { 200962306a36Sopenharmony_ci case E1000_FC_NONE: 201062306a36Sopenharmony_ci ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE)); 201162306a36Sopenharmony_ci break; 201262306a36Sopenharmony_ci case E1000_FC_RX_PAUSE: 201362306a36Sopenharmony_ci ctrl &= (~E1000_CTRL_TFCE); 201462306a36Sopenharmony_ci ctrl |= E1000_CTRL_RFCE; 201562306a36Sopenharmony_ci break; 201662306a36Sopenharmony_ci case E1000_FC_TX_PAUSE: 201762306a36Sopenharmony_ci ctrl &= (~E1000_CTRL_RFCE); 201862306a36Sopenharmony_ci ctrl |= E1000_CTRL_TFCE; 201962306a36Sopenharmony_ci break; 202062306a36Sopenharmony_ci case E1000_FC_FULL: 202162306a36Sopenharmony_ci ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE); 202262306a36Sopenharmony_ci break; 202362306a36Sopenharmony_ci default: 202462306a36Sopenharmony_ci e_dbg("Flow control param set incorrectly\n"); 202562306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 202662306a36Sopenharmony_ci } 202762306a36Sopenharmony_ci 202862306a36Sopenharmony_ci /* Disable TX Flow Control for 82542 (rev 2.0) */ 202962306a36Sopenharmony_ci if (hw->mac_type == e1000_82542_rev2_0) 203062306a36Sopenharmony_ci ctrl &= (~E1000_CTRL_TFCE); 203162306a36Sopenharmony_ci 203262306a36Sopenharmony_ci ew32(CTRL, ctrl); 203362306a36Sopenharmony_ci return E1000_SUCCESS; 203462306a36Sopenharmony_ci} 203562306a36Sopenharmony_ci 203662306a36Sopenharmony_ci/** 203762306a36Sopenharmony_ci * e1000_config_fc_after_link_up - configure flow control after autoneg 203862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 203962306a36Sopenharmony_ci * 204062306a36Sopenharmony_ci * Configures flow control settings after link is established 204162306a36Sopenharmony_ci * Should be called immediately after a valid link has been established. 204262306a36Sopenharmony_ci * Forces MAC flow control settings if link was forced. When in MII/GMII mode 204362306a36Sopenharmony_ci * and autonegotiation is enabled, the MAC flow control settings will be set 204462306a36Sopenharmony_ci * based on the flow control negotiated by the PHY. In TBI mode, the TFCE 204562306a36Sopenharmony_ci * and RFCE bits will be automatically set to the negotiated flow control mode. 204662306a36Sopenharmony_ci */ 204762306a36Sopenharmony_cistatic s32 e1000_config_fc_after_link_up(struct e1000_hw *hw) 204862306a36Sopenharmony_ci{ 204962306a36Sopenharmony_ci s32 ret_val; 205062306a36Sopenharmony_ci u16 mii_status_reg; 205162306a36Sopenharmony_ci u16 mii_nway_adv_reg; 205262306a36Sopenharmony_ci u16 mii_nway_lp_ability_reg; 205362306a36Sopenharmony_ci u16 speed; 205462306a36Sopenharmony_ci u16 duplex; 205562306a36Sopenharmony_ci 205662306a36Sopenharmony_ci /* Check for the case where we have fiber media and auto-neg failed 205762306a36Sopenharmony_ci * so we had to force link. In this case, we need to force the 205862306a36Sopenharmony_ci * configuration of the MAC to match the "fc" parameter. 205962306a36Sopenharmony_ci */ 206062306a36Sopenharmony_ci if (((hw->media_type == e1000_media_type_fiber) && 206162306a36Sopenharmony_ci (hw->autoneg_failed)) || 206262306a36Sopenharmony_ci ((hw->media_type == e1000_media_type_internal_serdes) && 206362306a36Sopenharmony_ci (hw->autoneg_failed)) || 206462306a36Sopenharmony_ci ((hw->media_type == e1000_media_type_copper) && 206562306a36Sopenharmony_ci (!hw->autoneg))) { 206662306a36Sopenharmony_ci ret_val = e1000_force_mac_fc(hw); 206762306a36Sopenharmony_ci if (ret_val) { 206862306a36Sopenharmony_ci e_dbg("Error forcing flow control settings\n"); 206962306a36Sopenharmony_ci return ret_val; 207062306a36Sopenharmony_ci } 207162306a36Sopenharmony_ci } 207262306a36Sopenharmony_ci 207362306a36Sopenharmony_ci /* Check for the case where we have copper media and auto-neg is 207462306a36Sopenharmony_ci * enabled. In this case, we need to check and see if Auto-Neg 207562306a36Sopenharmony_ci * has completed, and if so, how the PHY and link partner has 207662306a36Sopenharmony_ci * flow control configured. 207762306a36Sopenharmony_ci */ 207862306a36Sopenharmony_ci if ((hw->media_type == e1000_media_type_copper) && hw->autoneg) { 207962306a36Sopenharmony_ci /* Read the MII Status Register and check to see if AutoNeg 208062306a36Sopenharmony_ci * has completed. We read this twice because this reg has 208162306a36Sopenharmony_ci * some "sticky" (latched) bits. 208262306a36Sopenharmony_ci */ 208362306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 208462306a36Sopenharmony_ci if (ret_val) 208562306a36Sopenharmony_ci return ret_val; 208662306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 208762306a36Sopenharmony_ci if (ret_val) 208862306a36Sopenharmony_ci return ret_val; 208962306a36Sopenharmony_ci 209062306a36Sopenharmony_ci if (mii_status_reg & MII_SR_AUTONEG_COMPLETE) { 209162306a36Sopenharmony_ci /* The AutoNeg process has completed, so we now need to 209262306a36Sopenharmony_ci * read both the Auto Negotiation Advertisement Register 209362306a36Sopenharmony_ci * (Address 4) and the Auto_Negotiation Base Page 209462306a36Sopenharmony_ci * Ability Register (Address 5) to determine how flow 209562306a36Sopenharmony_ci * control was negotiated. 209662306a36Sopenharmony_ci */ 209762306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_ADV, 209862306a36Sopenharmony_ci &mii_nway_adv_reg); 209962306a36Sopenharmony_ci if (ret_val) 210062306a36Sopenharmony_ci return ret_val; 210162306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_LP_ABILITY, 210262306a36Sopenharmony_ci &mii_nway_lp_ability_reg); 210362306a36Sopenharmony_ci if (ret_val) 210462306a36Sopenharmony_ci return ret_val; 210562306a36Sopenharmony_ci 210662306a36Sopenharmony_ci /* Two bits in the Auto Negotiation Advertisement 210762306a36Sopenharmony_ci * Register (Address 4) and two bits in the Auto 210862306a36Sopenharmony_ci * Negotiation Base Page Ability Register (Address 5) 210962306a36Sopenharmony_ci * determine flow control for both the PHY and the link 211062306a36Sopenharmony_ci * partner. The following table, taken out of the IEEE 211162306a36Sopenharmony_ci * 802.3ab/D6.0 dated March 25, 1999, describes these 211262306a36Sopenharmony_ci * PAUSE resolution bits and how flow control is 211362306a36Sopenharmony_ci * determined based upon these settings. 211462306a36Sopenharmony_ci * NOTE: DC = Don't Care 211562306a36Sopenharmony_ci * 211662306a36Sopenharmony_ci * LOCAL DEVICE | LINK PARTNER 211762306a36Sopenharmony_ci * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution 211862306a36Sopenharmony_ci *-------|---------|-------|---------|------------------ 211962306a36Sopenharmony_ci * 0 | 0 | DC | DC | E1000_FC_NONE 212062306a36Sopenharmony_ci * 0 | 1 | 0 | DC | E1000_FC_NONE 212162306a36Sopenharmony_ci * 0 | 1 | 1 | 0 | E1000_FC_NONE 212262306a36Sopenharmony_ci * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE 212362306a36Sopenharmony_ci * 1 | 0 | 0 | DC | E1000_FC_NONE 212462306a36Sopenharmony_ci * 1 | DC | 1 | DC | E1000_FC_FULL 212562306a36Sopenharmony_ci * 1 | 1 | 0 | 0 | E1000_FC_NONE 212662306a36Sopenharmony_ci * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE 212762306a36Sopenharmony_ci * 212862306a36Sopenharmony_ci */ 212962306a36Sopenharmony_ci /* Are both PAUSE bits set to 1? If so, this implies 213062306a36Sopenharmony_ci * Symmetric Flow Control is enabled at both ends. The 213162306a36Sopenharmony_ci * ASM_DIR bits are irrelevant per the spec. 213262306a36Sopenharmony_ci * 213362306a36Sopenharmony_ci * For Symmetric Flow Control: 213462306a36Sopenharmony_ci * 213562306a36Sopenharmony_ci * LOCAL DEVICE | LINK PARTNER 213662306a36Sopenharmony_ci * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result 213762306a36Sopenharmony_ci *-------|---------|-------|---------|------------------ 213862306a36Sopenharmony_ci * 1 | DC | 1 | DC | E1000_FC_FULL 213962306a36Sopenharmony_ci * 214062306a36Sopenharmony_ci */ 214162306a36Sopenharmony_ci if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && 214262306a36Sopenharmony_ci (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) { 214362306a36Sopenharmony_ci /* Now we need to check if the user selected Rx 214462306a36Sopenharmony_ci * ONLY of pause frames. In this case, we had 214562306a36Sopenharmony_ci * to advertise FULL flow control because we 214662306a36Sopenharmony_ci * could not advertise Rx ONLY. Hence, we must 214762306a36Sopenharmony_ci * now check to see if we need to turn OFF the 214862306a36Sopenharmony_ci * TRANSMISSION of PAUSE frames. 214962306a36Sopenharmony_ci */ 215062306a36Sopenharmony_ci if (hw->original_fc == E1000_FC_FULL) { 215162306a36Sopenharmony_ci hw->fc = E1000_FC_FULL; 215262306a36Sopenharmony_ci e_dbg("Flow Control = FULL.\n"); 215362306a36Sopenharmony_ci } else { 215462306a36Sopenharmony_ci hw->fc = E1000_FC_RX_PAUSE; 215562306a36Sopenharmony_ci e_dbg 215662306a36Sopenharmony_ci ("Flow Control = RX PAUSE frames only.\n"); 215762306a36Sopenharmony_ci } 215862306a36Sopenharmony_ci } 215962306a36Sopenharmony_ci /* For receiving PAUSE frames ONLY. 216062306a36Sopenharmony_ci * 216162306a36Sopenharmony_ci * LOCAL DEVICE | LINK PARTNER 216262306a36Sopenharmony_ci * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result 216362306a36Sopenharmony_ci *-------|---------|-------|---------|------------------ 216462306a36Sopenharmony_ci * 0 | 1 | 1 | 1 | E1000_FC_TX_PAUSE 216562306a36Sopenharmony_ci * 216662306a36Sopenharmony_ci */ 216762306a36Sopenharmony_ci else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) && 216862306a36Sopenharmony_ci (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && 216962306a36Sopenharmony_ci (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && 217062306a36Sopenharmony_ci (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { 217162306a36Sopenharmony_ci hw->fc = E1000_FC_TX_PAUSE; 217262306a36Sopenharmony_ci e_dbg 217362306a36Sopenharmony_ci ("Flow Control = TX PAUSE frames only.\n"); 217462306a36Sopenharmony_ci } 217562306a36Sopenharmony_ci /* For transmitting PAUSE frames ONLY. 217662306a36Sopenharmony_ci * 217762306a36Sopenharmony_ci * LOCAL DEVICE | LINK PARTNER 217862306a36Sopenharmony_ci * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result 217962306a36Sopenharmony_ci *-------|---------|-------|---------|------------------ 218062306a36Sopenharmony_ci * 1 | 1 | 0 | 1 | E1000_FC_RX_PAUSE 218162306a36Sopenharmony_ci * 218262306a36Sopenharmony_ci */ 218362306a36Sopenharmony_ci else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) && 218462306a36Sopenharmony_ci (mii_nway_adv_reg & NWAY_AR_ASM_DIR) && 218562306a36Sopenharmony_ci !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) && 218662306a36Sopenharmony_ci (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) { 218762306a36Sopenharmony_ci hw->fc = E1000_FC_RX_PAUSE; 218862306a36Sopenharmony_ci e_dbg 218962306a36Sopenharmony_ci ("Flow Control = RX PAUSE frames only.\n"); 219062306a36Sopenharmony_ci } 219162306a36Sopenharmony_ci /* Per the IEEE spec, at this point flow control should 219262306a36Sopenharmony_ci * be disabled. However, we want to consider that we 219362306a36Sopenharmony_ci * could be connected to a legacy switch that doesn't 219462306a36Sopenharmony_ci * advertise desired flow control, but can be forced on 219562306a36Sopenharmony_ci * the link partner. So if we advertised no flow 219662306a36Sopenharmony_ci * control, that is what we will resolve to. If we 219762306a36Sopenharmony_ci * advertised some kind of receive capability (Rx Pause 219862306a36Sopenharmony_ci * Only or Full Flow Control) and the link partner 219962306a36Sopenharmony_ci * advertised none, we will configure ourselves to 220062306a36Sopenharmony_ci * enable Rx Flow Control only. We can do this safely 220162306a36Sopenharmony_ci * for two reasons: If the link partner really 220262306a36Sopenharmony_ci * didn't want flow control enabled, and we enable Rx, 220362306a36Sopenharmony_ci * no harm done since we won't be receiving any PAUSE 220462306a36Sopenharmony_ci * frames anyway. If the intent on the link partner was 220562306a36Sopenharmony_ci * to have flow control enabled, then by us enabling Rx 220662306a36Sopenharmony_ci * only, we can at least receive pause frames and 220762306a36Sopenharmony_ci * process them. This is a good idea because in most 220862306a36Sopenharmony_ci * cases, since we are predominantly a server NIC, more 220962306a36Sopenharmony_ci * times than not we will be asked to delay transmission 221062306a36Sopenharmony_ci * of packets than asking our link partner to pause 221162306a36Sopenharmony_ci * transmission of frames. 221262306a36Sopenharmony_ci */ 221362306a36Sopenharmony_ci else if ((hw->original_fc == E1000_FC_NONE || 221462306a36Sopenharmony_ci hw->original_fc == E1000_FC_TX_PAUSE) || 221562306a36Sopenharmony_ci hw->fc_strict_ieee) { 221662306a36Sopenharmony_ci hw->fc = E1000_FC_NONE; 221762306a36Sopenharmony_ci e_dbg("Flow Control = NONE.\n"); 221862306a36Sopenharmony_ci } else { 221962306a36Sopenharmony_ci hw->fc = E1000_FC_RX_PAUSE; 222062306a36Sopenharmony_ci e_dbg 222162306a36Sopenharmony_ci ("Flow Control = RX PAUSE frames only.\n"); 222262306a36Sopenharmony_ci } 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci /* Now we need to do one last check... If we auto- 222562306a36Sopenharmony_ci * negotiated to HALF DUPLEX, flow control should not be 222662306a36Sopenharmony_ci * enabled per IEEE 802.3 spec. 222762306a36Sopenharmony_ci */ 222862306a36Sopenharmony_ci ret_val = 222962306a36Sopenharmony_ci e1000_get_speed_and_duplex(hw, &speed, &duplex); 223062306a36Sopenharmony_ci if (ret_val) { 223162306a36Sopenharmony_ci e_dbg 223262306a36Sopenharmony_ci ("Error getting link speed and duplex\n"); 223362306a36Sopenharmony_ci return ret_val; 223462306a36Sopenharmony_ci } 223562306a36Sopenharmony_ci 223662306a36Sopenharmony_ci if (duplex == HALF_DUPLEX) 223762306a36Sopenharmony_ci hw->fc = E1000_FC_NONE; 223862306a36Sopenharmony_ci 223962306a36Sopenharmony_ci /* Now we call a subroutine to actually force the MAC 224062306a36Sopenharmony_ci * controller to use the correct flow control settings. 224162306a36Sopenharmony_ci */ 224262306a36Sopenharmony_ci ret_val = e1000_force_mac_fc(hw); 224362306a36Sopenharmony_ci if (ret_val) { 224462306a36Sopenharmony_ci e_dbg 224562306a36Sopenharmony_ci ("Error forcing flow control settings\n"); 224662306a36Sopenharmony_ci return ret_val; 224762306a36Sopenharmony_ci } 224862306a36Sopenharmony_ci } else { 224962306a36Sopenharmony_ci e_dbg 225062306a36Sopenharmony_ci ("Copper PHY and Auto Neg has not completed.\n"); 225162306a36Sopenharmony_ci } 225262306a36Sopenharmony_ci } 225362306a36Sopenharmony_ci return E1000_SUCCESS; 225462306a36Sopenharmony_ci} 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_ci/** 225762306a36Sopenharmony_ci * e1000_check_for_serdes_link_generic - Check for link (Serdes) 225862306a36Sopenharmony_ci * @hw: pointer to the HW structure 225962306a36Sopenharmony_ci * 226062306a36Sopenharmony_ci * Checks for link up on the hardware. If link is not up and we have 226162306a36Sopenharmony_ci * a signal, then we need to force link up. 226262306a36Sopenharmony_ci */ 226362306a36Sopenharmony_cistatic s32 e1000_check_for_serdes_link_generic(struct e1000_hw *hw) 226462306a36Sopenharmony_ci{ 226562306a36Sopenharmony_ci u32 rxcw; 226662306a36Sopenharmony_ci u32 ctrl; 226762306a36Sopenharmony_ci u32 status; 226862306a36Sopenharmony_ci s32 ret_val = E1000_SUCCESS; 226962306a36Sopenharmony_ci 227062306a36Sopenharmony_ci ctrl = er32(CTRL); 227162306a36Sopenharmony_ci status = er32(STATUS); 227262306a36Sopenharmony_ci rxcw = er32(RXCW); 227362306a36Sopenharmony_ci 227462306a36Sopenharmony_ci /* If we don't have link (auto-negotiation failed or link partner 227562306a36Sopenharmony_ci * cannot auto-negotiate), and our link partner is not trying to 227662306a36Sopenharmony_ci * auto-negotiate with us (we are receiving idles or data), 227762306a36Sopenharmony_ci * we need to force link up. We also need to give auto-negotiation 227862306a36Sopenharmony_ci * time to complete. 227962306a36Sopenharmony_ci */ 228062306a36Sopenharmony_ci /* (ctrl & E1000_CTRL_SWDPIN1) == 1 == have signal */ 228162306a36Sopenharmony_ci if ((!(status & E1000_STATUS_LU)) && (!(rxcw & E1000_RXCW_C))) { 228262306a36Sopenharmony_ci if (hw->autoneg_failed == 0) { 228362306a36Sopenharmony_ci hw->autoneg_failed = 1; 228462306a36Sopenharmony_ci goto out; 228562306a36Sopenharmony_ci } 228662306a36Sopenharmony_ci e_dbg("NOT RXing /C/, disable AutoNeg and force link.\n"); 228762306a36Sopenharmony_ci 228862306a36Sopenharmony_ci /* Disable auto-negotiation in the TXCW register */ 228962306a36Sopenharmony_ci ew32(TXCW, (hw->txcw & ~E1000_TXCW_ANE)); 229062306a36Sopenharmony_ci 229162306a36Sopenharmony_ci /* Force link-up and also force full-duplex. */ 229262306a36Sopenharmony_ci ctrl = er32(CTRL); 229362306a36Sopenharmony_ci ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); 229462306a36Sopenharmony_ci ew32(CTRL, ctrl); 229562306a36Sopenharmony_ci 229662306a36Sopenharmony_ci /* Configure Flow Control after forcing link up. */ 229762306a36Sopenharmony_ci ret_val = e1000_config_fc_after_link_up(hw); 229862306a36Sopenharmony_ci if (ret_val) { 229962306a36Sopenharmony_ci e_dbg("Error configuring flow control\n"); 230062306a36Sopenharmony_ci goto out; 230162306a36Sopenharmony_ci } 230262306a36Sopenharmony_ci } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { 230362306a36Sopenharmony_ci /* If we are forcing link and we are receiving /C/ ordered 230462306a36Sopenharmony_ci * sets, re-enable auto-negotiation in the TXCW register 230562306a36Sopenharmony_ci * and disable forced link in the Device Control register 230662306a36Sopenharmony_ci * in an attempt to auto-negotiate with our link partner. 230762306a36Sopenharmony_ci */ 230862306a36Sopenharmony_ci e_dbg("RXing /C/, enable AutoNeg and stop forcing link.\n"); 230962306a36Sopenharmony_ci ew32(TXCW, hw->txcw); 231062306a36Sopenharmony_ci ew32(CTRL, (ctrl & ~E1000_CTRL_SLU)); 231162306a36Sopenharmony_ci 231262306a36Sopenharmony_ci hw->serdes_has_link = true; 231362306a36Sopenharmony_ci } else if (!(E1000_TXCW_ANE & er32(TXCW))) { 231462306a36Sopenharmony_ci /* If we force link for non-auto-negotiation switch, check 231562306a36Sopenharmony_ci * link status based on MAC synchronization for internal 231662306a36Sopenharmony_ci * serdes media type. 231762306a36Sopenharmony_ci */ 231862306a36Sopenharmony_ci /* SYNCH bit and IV bit are sticky. */ 231962306a36Sopenharmony_ci udelay(10); 232062306a36Sopenharmony_ci rxcw = er32(RXCW); 232162306a36Sopenharmony_ci if (rxcw & E1000_RXCW_SYNCH) { 232262306a36Sopenharmony_ci if (!(rxcw & E1000_RXCW_IV)) { 232362306a36Sopenharmony_ci hw->serdes_has_link = true; 232462306a36Sopenharmony_ci e_dbg("SERDES: Link up - forced.\n"); 232562306a36Sopenharmony_ci } 232662306a36Sopenharmony_ci } else { 232762306a36Sopenharmony_ci hw->serdes_has_link = false; 232862306a36Sopenharmony_ci e_dbg("SERDES: Link down - force failed.\n"); 232962306a36Sopenharmony_ci } 233062306a36Sopenharmony_ci } 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci if (E1000_TXCW_ANE & er32(TXCW)) { 233362306a36Sopenharmony_ci status = er32(STATUS); 233462306a36Sopenharmony_ci if (status & E1000_STATUS_LU) { 233562306a36Sopenharmony_ci /* SYNCH bit and IV bit are sticky, so reread rxcw. */ 233662306a36Sopenharmony_ci udelay(10); 233762306a36Sopenharmony_ci rxcw = er32(RXCW); 233862306a36Sopenharmony_ci if (rxcw & E1000_RXCW_SYNCH) { 233962306a36Sopenharmony_ci if (!(rxcw & E1000_RXCW_IV)) { 234062306a36Sopenharmony_ci hw->serdes_has_link = true; 234162306a36Sopenharmony_ci e_dbg("SERDES: Link up - autoneg " 234262306a36Sopenharmony_ci "completed successfully.\n"); 234362306a36Sopenharmony_ci } else { 234462306a36Sopenharmony_ci hw->serdes_has_link = false; 234562306a36Sopenharmony_ci e_dbg("SERDES: Link down - invalid" 234662306a36Sopenharmony_ci "codewords detected in autoneg.\n"); 234762306a36Sopenharmony_ci } 234862306a36Sopenharmony_ci } else { 234962306a36Sopenharmony_ci hw->serdes_has_link = false; 235062306a36Sopenharmony_ci e_dbg("SERDES: Link down - no sync.\n"); 235162306a36Sopenharmony_ci } 235262306a36Sopenharmony_ci } else { 235362306a36Sopenharmony_ci hw->serdes_has_link = false; 235462306a36Sopenharmony_ci e_dbg("SERDES: Link down - autoneg failed\n"); 235562306a36Sopenharmony_ci } 235662306a36Sopenharmony_ci } 235762306a36Sopenharmony_ci 235862306a36Sopenharmony_ci out: 235962306a36Sopenharmony_ci return ret_val; 236062306a36Sopenharmony_ci} 236162306a36Sopenharmony_ci 236262306a36Sopenharmony_ci/** 236362306a36Sopenharmony_ci * e1000_check_for_link 236462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 236562306a36Sopenharmony_ci * 236662306a36Sopenharmony_ci * Checks to see if the link status of the hardware has changed. 236762306a36Sopenharmony_ci * Called by any function that needs to check the link status of the adapter. 236862306a36Sopenharmony_ci */ 236962306a36Sopenharmony_cis32 e1000_check_for_link(struct e1000_hw *hw) 237062306a36Sopenharmony_ci{ 237162306a36Sopenharmony_ci u32 status; 237262306a36Sopenharmony_ci u32 rctl; 237362306a36Sopenharmony_ci u32 icr; 237462306a36Sopenharmony_ci s32 ret_val; 237562306a36Sopenharmony_ci u16 phy_data; 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_ci er32(CTRL); 237862306a36Sopenharmony_ci status = er32(STATUS); 237962306a36Sopenharmony_ci 238062306a36Sopenharmony_ci /* On adapters with a MAC newer than 82544, SW Definable pin 1 will be 238162306a36Sopenharmony_ci * set when the optics detect a signal. On older adapters, it will be 238262306a36Sopenharmony_ci * cleared when there is a signal. This applies to fiber media only. 238362306a36Sopenharmony_ci */ 238462306a36Sopenharmony_ci if ((hw->media_type == e1000_media_type_fiber) || 238562306a36Sopenharmony_ci (hw->media_type == e1000_media_type_internal_serdes)) { 238662306a36Sopenharmony_ci er32(RXCW); 238762306a36Sopenharmony_ci 238862306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_fiber) { 238962306a36Sopenharmony_ci if (status & E1000_STATUS_LU) 239062306a36Sopenharmony_ci hw->get_link_status = false; 239162306a36Sopenharmony_ci } 239262306a36Sopenharmony_ci } 239362306a36Sopenharmony_ci 239462306a36Sopenharmony_ci /* If we have a copper PHY then we only want to go out to the PHY 239562306a36Sopenharmony_ci * registers to see if Auto-Neg has completed and/or if our link 239662306a36Sopenharmony_ci * status has changed. The get_link_status flag will be set if we 239762306a36Sopenharmony_ci * receive a Link Status Change interrupt or we have Rx Sequence 239862306a36Sopenharmony_ci * Errors. 239962306a36Sopenharmony_ci */ 240062306a36Sopenharmony_ci if ((hw->media_type == e1000_media_type_copper) && hw->get_link_status) { 240162306a36Sopenharmony_ci /* First we want to see if the MII Status Register reports 240262306a36Sopenharmony_ci * link. If so, then we want to get the current speed/duplex 240362306a36Sopenharmony_ci * of the PHY. 240462306a36Sopenharmony_ci * Read the register twice since the link bit is sticky. 240562306a36Sopenharmony_ci */ 240662306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 240762306a36Sopenharmony_ci if (ret_val) 240862306a36Sopenharmony_ci return ret_val; 240962306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 241062306a36Sopenharmony_ci if (ret_val) 241162306a36Sopenharmony_ci return ret_val; 241262306a36Sopenharmony_ci 241362306a36Sopenharmony_ci if (phy_data & MII_SR_LINK_STATUS) { 241462306a36Sopenharmony_ci hw->get_link_status = false; 241562306a36Sopenharmony_ci /* Check if there was DownShift, must be checked 241662306a36Sopenharmony_ci * immediately after link-up 241762306a36Sopenharmony_ci */ 241862306a36Sopenharmony_ci e1000_check_downshift(hw); 241962306a36Sopenharmony_ci 242062306a36Sopenharmony_ci /* If we are on 82544 or 82543 silicon and speed/duplex 242162306a36Sopenharmony_ci * are forced to 10H or 10F, then we will implement the 242262306a36Sopenharmony_ci * polarity reversal workaround. We disable interrupts 242362306a36Sopenharmony_ci * first, and upon returning, place the devices 242462306a36Sopenharmony_ci * interrupt state to its previous value except for the 242562306a36Sopenharmony_ci * link status change interrupt which will 242662306a36Sopenharmony_ci * happen due to the execution of this workaround. 242762306a36Sopenharmony_ci */ 242862306a36Sopenharmony_ci 242962306a36Sopenharmony_ci if ((hw->mac_type == e1000_82544 || 243062306a36Sopenharmony_ci hw->mac_type == e1000_82543) && 243162306a36Sopenharmony_ci (!hw->autoneg) && 243262306a36Sopenharmony_ci (hw->forced_speed_duplex == e1000_10_full || 243362306a36Sopenharmony_ci hw->forced_speed_duplex == e1000_10_half)) { 243462306a36Sopenharmony_ci ew32(IMC, 0xffffffff); 243562306a36Sopenharmony_ci ret_val = 243662306a36Sopenharmony_ci e1000_polarity_reversal_workaround(hw); 243762306a36Sopenharmony_ci icr = er32(ICR); 243862306a36Sopenharmony_ci ew32(ICS, (icr & ~E1000_ICS_LSC)); 243962306a36Sopenharmony_ci ew32(IMS, IMS_ENABLE_MASK); 244062306a36Sopenharmony_ci } 244162306a36Sopenharmony_ci 244262306a36Sopenharmony_ci } else { 244362306a36Sopenharmony_ci /* No link detected */ 244462306a36Sopenharmony_ci e1000_config_dsp_after_link_change(hw, false); 244562306a36Sopenharmony_ci return 0; 244662306a36Sopenharmony_ci } 244762306a36Sopenharmony_ci 244862306a36Sopenharmony_ci /* If we are forcing speed/duplex, then we simply return since 244962306a36Sopenharmony_ci * we have already determined whether we have link or not. 245062306a36Sopenharmony_ci */ 245162306a36Sopenharmony_ci if (!hw->autoneg) 245262306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 245362306a36Sopenharmony_ci 245462306a36Sopenharmony_ci /* optimize the dsp settings for the igp phy */ 245562306a36Sopenharmony_ci e1000_config_dsp_after_link_change(hw, true); 245662306a36Sopenharmony_ci 245762306a36Sopenharmony_ci /* We have a M88E1000 PHY and Auto-Neg is enabled. If we 245862306a36Sopenharmony_ci * have Si on board that is 82544 or newer, Auto 245962306a36Sopenharmony_ci * Speed Detection takes care of MAC speed/duplex 246062306a36Sopenharmony_ci * configuration. So we only need to configure Collision 246162306a36Sopenharmony_ci * Distance in the MAC. Otherwise, we need to force 246262306a36Sopenharmony_ci * speed/duplex on the MAC to the current PHY speed/duplex 246362306a36Sopenharmony_ci * settings. 246462306a36Sopenharmony_ci */ 246562306a36Sopenharmony_ci if ((hw->mac_type >= e1000_82544) && 246662306a36Sopenharmony_ci (hw->mac_type != e1000_ce4100)) 246762306a36Sopenharmony_ci e1000_config_collision_dist(hw); 246862306a36Sopenharmony_ci else { 246962306a36Sopenharmony_ci ret_val = e1000_config_mac_to_phy(hw); 247062306a36Sopenharmony_ci if (ret_val) { 247162306a36Sopenharmony_ci e_dbg 247262306a36Sopenharmony_ci ("Error configuring MAC to PHY settings\n"); 247362306a36Sopenharmony_ci return ret_val; 247462306a36Sopenharmony_ci } 247562306a36Sopenharmony_ci } 247662306a36Sopenharmony_ci 247762306a36Sopenharmony_ci /* Configure Flow Control now that Auto-Neg has completed. 247862306a36Sopenharmony_ci * First, we need to restore the desired flow control settings 247962306a36Sopenharmony_ci * because we may have had to re-autoneg with a different link 248062306a36Sopenharmony_ci * partner. 248162306a36Sopenharmony_ci */ 248262306a36Sopenharmony_ci ret_val = e1000_config_fc_after_link_up(hw); 248362306a36Sopenharmony_ci if (ret_val) { 248462306a36Sopenharmony_ci e_dbg("Error configuring flow control\n"); 248562306a36Sopenharmony_ci return ret_val; 248662306a36Sopenharmony_ci } 248762306a36Sopenharmony_ci 248862306a36Sopenharmony_ci /* At this point we know that we are on copper and we have 248962306a36Sopenharmony_ci * auto-negotiated link. These are conditions for checking the 249062306a36Sopenharmony_ci * link partner capability register. We use the link speed to 249162306a36Sopenharmony_ci * determine if TBI compatibility needs to be turned on or off. 249262306a36Sopenharmony_ci * If the link is not at gigabit speed, then TBI compatibility 249362306a36Sopenharmony_ci * is not needed. If we are at gigabit speed, we turn on TBI 249462306a36Sopenharmony_ci * compatibility. 249562306a36Sopenharmony_ci */ 249662306a36Sopenharmony_ci if (hw->tbi_compatibility_en) { 249762306a36Sopenharmony_ci u16 speed, duplex; 249862306a36Sopenharmony_ci 249962306a36Sopenharmony_ci ret_val = 250062306a36Sopenharmony_ci e1000_get_speed_and_duplex(hw, &speed, &duplex); 250162306a36Sopenharmony_ci 250262306a36Sopenharmony_ci if (ret_val) { 250362306a36Sopenharmony_ci e_dbg 250462306a36Sopenharmony_ci ("Error getting link speed and duplex\n"); 250562306a36Sopenharmony_ci return ret_val; 250662306a36Sopenharmony_ci } 250762306a36Sopenharmony_ci if (speed != SPEED_1000) { 250862306a36Sopenharmony_ci /* If link speed is not set to gigabit speed, we 250962306a36Sopenharmony_ci * do not need to enable TBI compatibility. 251062306a36Sopenharmony_ci */ 251162306a36Sopenharmony_ci if (hw->tbi_compatibility_on) { 251262306a36Sopenharmony_ci /* If we previously were in the mode, 251362306a36Sopenharmony_ci * turn it off. 251462306a36Sopenharmony_ci */ 251562306a36Sopenharmony_ci rctl = er32(RCTL); 251662306a36Sopenharmony_ci rctl &= ~E1000_RCTL_SBP; 251762306a36Sopenharmony_ci ew32(RCTL, rctl); 251862306a36Sopenharmony_ci hw->tbi_compatibility_on = false; 251962306a36Sopenharmony_ci } 252062306a36Sopenharmony_ci } else { 252162306a36Sopenharmony_ci /* If TBI compatibility is was previously off, 252262306a36Sopenharmony_ci * turn it on. For compatibility with a TBI link 252362306a36Sopenharmony_ci * partner, we will store bad packets. Some 252462306a36Sopenharmony_ci * frames have an additional byte on the end and 252562306a36Sopenharmony_ci * will look like CRC errors to the hardware. 252662306a36Sopenharmony_ci */ 252762306a36Sopenharmony_ci if (!hw->tbi_compatibility_on) { 252862306a36Sopenharmony_ci hw->tbi_compatibility_on = true; 252962306a36Sopenharmony_ci rctl = er32(RCTL); 253062306a36Sopenharmony_ci rctl |= E1000_RCTL_SBP; 253162306a36Sopenharmony_ci ew32(RCTL, rctl); 253262306a36Sopenharmony_ci } 253362306a36Sopenharmony_ci } 253462306a36Sopenharmony_ci } 253562306a36Sopenharmony_ci } 253662306a36Sopenharmony_ci 253762306a36Sopenharmony_ci if ((hw->media_type == e1000_media_type_fiber) || 253862306a36Sopenharmony_ci (hw->media_type == e1000_media_type_internal_serdes)) 253962306a36Sopenharmony_ci e1000_check_for_serdes_link_generic(hw); 254062306a36Sopenharmony_ci 254162306a36Sopenharmony_ci return E1000_SUCCESS; 254262306a36Sopenharmony_ci} 254362306a36Sopenharmony_ci 254462306a36Sopenharmony_ci/** 254562306a36Sopenharmony_ci * e1000_get_speed_and_duplex 254662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 254762306a36Sopenharmony_ci * @speed: Speed of the connection 254862306a36Sopenharmony_ci * @duplex: Duplex setting of the connection 254962306a36Sopenharmony_ci * 255062306a36Sopenharmony_ci * Detects the current speed and duplex settings of the hardware. 255162306a36Sopenharmony_ci */ 255262306a36Sopenharmony_cis32 e1000_get_speed_and_duplex(struct e1000_hw *hw, u16 *speed, u16 *duplex) 255362306a36Sopenharmony_ci{ 255462306a36Sopenharmony_ci u32 status; 255562306a36Sopenharmony_ci s32 ret_val; 255662306a36Sopenharmony_ci u16 phy_data; 255762306a36Sopenharmony_ci 255862306a36Sopenharmony_ci if (hw->mac_type >= e1000_82543) { 255962306a36Sopenharmony_ci status = er32(STATUS); 256062306a36Sopenharmony_ci if (status & E1000_STATUS_SPEED_1000) { 256162306a36Sopenharmony_ci *speed = SPEED_1000; 256262306a36Sopenharmony_ci e_dbg("1000 Mbs, "); 256362306a36Sopenharmony_ci } else if (status & E1000_STATUS_SPEED_100) { 256462306a36Sopenharmony_ci *speed = SPEED_100; 256562306a36Sopenharmony_ci e_dbg("100 Mbs, "); 256662306a36Sopenharmony_ci } else { 256762306a36Sopenharmony_ci *speed = SPEED_10; 256862306a36Sopenharmony_ci e_dbg("10 Mbs, "); 256962306a36Sopenharmony_ci } 257062306a36Sopenharmony_ci 257162306a36Sopenharmony_ci if (status & E1000_STATUS_FD) { 257262306a36Sopenharmony_ci *duplex = FULL_DUPLEX; 257362306a36Sopenharmony_ci e_dbg("Full Duplex\n"); 257462306a36Sopenharmony_ci } else { 257562306a36Sopenharmony_ci *duplex = HALF_DUPLEX; 257662306a36Sopenharmony_ci e_dbg(" Half Duplex\n"); 257762306a36Sopenharmony_ci } 257862306a36Sopenharmony_ci } else { 257962306a36Sopenharmony_ci e_dbg("1000 Mbs, Full Duplex\n"); 258062306a36Sopenharmony_ci *speed = SPEED_1000; 258162306a36Sopenharmony_ci *duplex = FULL_DUPLEX; 258262306a36Sopenharmony_ci } 258362306a36Sopenharmony_ci 258462306a36Sopenharmony_ci /* IGP01 PHY may advertise full duplex operation after speed downgrade 258562306a36Sopenharmony_ci * even if it is operating at half duplex. Here we set the duplex 258662306a36Sopenharmony_ci * settings to match the duplex in the link partner's capabilities. 258762306a36Sopenharmony_ci */ 258862306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_igp && hw->speed_downgraded) { 258962306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_AUTONEG_EXP, &phy_data); 259062306a36Sopenharmony_ci if (ret_val) 259162306a36Sopenharmony_ci return ret_val; 259262306a36Sopenharmony_ci 259362306a36Sopenharmony_ci if (!(phy_data & NWAY_ER_LP_NWAY_CAPS)) 259462306a36Sopenharmony_ci *duplex = HALF_DUPLEX; 259562306a36Sopenharmony_ci else { 259662306a36Sopenharmony_ci ret_val = 259762306a36Sopenharmony_ci e1000_read_phy_reg(hw, PHY_LP_ABILITY, &phy_data); 259862306a36Sopenharmony_ci if (ret_val) 259962306a36Sopenharmony_ci return ret_val; 260062306a36Sopenharmony_ci if ((*speed == SPEED_100 && 260162306a36Sopenharmony_ci !(phy_data & NWAY_LPAR_100TX_FD_CAPS)) || 260262306a36Sopenharmony_ci (*speed == SPEED_10 && 260362306a36Sopenharmony_ci !(phy_data & NWAY_LPAR_10T_FD_CAPS))) 260462306a36Sopenharmony_ci *duplex = HALF_DUPLEX; 260562306a36Sopenharmony_ci } 260662306a36Sopenharmony_ci } 260762306a36Sopenharmony_ci 260862306a36Sopenharmony_ci return E1000_SUCCESS; 260962306a36Sopenharmony_ci} 261062306a36Sopenharmony_ci 261162306a36Sopenharmony_ci/** 261262306a36Sopenharmony_ci * e1000_wait_autoneg 261362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 261462306a36Sopenharmony_ci * 261562306a36Sopenharmony_ci * Blocks until autoneg completes or times out (~4.5 seconds) 261662306a36Sopenharmony_ci */ 261762306a36Sopenharmony_cistatic s32 e1000_wait_autoneg(struct e1000_hw *hw) 261862306a36Sopenharmony_ci{ 261962306a36Sopenharmony_ci s32 ret_val; 262062306a36Sopenharmony_ci u16 i; 262162306a36Sopenharmony_ci u16 phy_data; 262262306a36Sopenharmony_ci 262362306a36Sopenharmony_ci e_dbg("Waiting for Auto-Neg to complete.\n"); 262462306a36Sopenharmony_ci 262562306a36Sopenharmony_ci /* We will wait for autoneg to complete or 4.5 seconds to expire. */ 262662306a36Sopenharmony_ci for (i = PHY_AUTO_NEG_TIME; i > 0; i--) { 262762306a36Sopenharmony_ci /* Read the MII Status Register and wait for Auto-Neg 262862306a36Sopenharmony_ci * Complete bit to be set. 262962306a36Sopenharmony_ci */ 263062306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 263162306a36Sopenharmony_ci if (ret_val) 263262306a36Sopenharmony_ci return ret_val; 263362306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 263462306a36Sopenharmony_ci if (ret_val) 263562306a36Sopenharmony_ci return ret_val; 263662306a36Sopenharmony_ci if (phy_data & MII_SR_AUTONEG_COMPLETE) 263762306a36Sopenharmony_ci return E1000_SUCCESS; 263862306a36Sopenharmony_ci 263962306a36Sopenharmony_ci msleep(100); 264062306a36Sopenharmony_ci } 264162306a36Sopenharmony_ci return E1000_SUCCESS; 264262306a36Sopenharmony_ci} 264362306a36Sopenharmony_ci 264462306a36Sopenharmony_ci/** 264562306a36Sopenharmony_ci * e1000_raise_mdi_clk - Raises the Management Data Clock 264662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 264762306a36Sopenharmony_ci * @ctrl: Device control register's current value 264862306a36Sopenharmony_ci */ 264962306a36Sopenharmony_cistatic void e1000_raise_mdi_clk(struct e1000_hw *hw, u32 *ctrl) 265062306a36Sopenharmony_ci{ 265162306a36Sopenharmony_ci /* Raise the clock input to the Management Data Clock (by setting the 265262306a36Sopenharmony_ci * MDC bit), and then delay 10 microseconds. 265362306a36Sopenharmony_ci */ 265462306a36Sopenharmony_ci ew32(CTRL, (*ctrl | E1000_CTRL_MDC)); 265562306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 265662306a36Sopenharmony_ci udelay(10); 265762306a36Sopenharmony_ci} 265862306a36Sopenharmony_ci 265962306a36Sopenharmony_ci/** 266062306a36Sopenharmony_ci * e1000_lower_mdi_clk - Lowers the Management Data Clock 266162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 266262306a36Sopenharmony_ci * @ctrl: Device control register's current value 266362306a36Sopenharmony_ci */ 266462306a36Sopenharmony_cistatic void e1000_lower_mdi_clk(struct e1000_hw *hw, u32 *ctrl) 266562306a36Sopenharmony_ci{ 266662306a36Sopenharmony_ci /* Lower the clock input to the Management Data Clock (by clearing the 266762306a36Sopenharmony_ci * MDC bit), and then delay 10 microseconds. 266862306a36Sopenharmony_ci */ 266962306a36Sopenharmony_ci ew32(CTRL, (*ctrl & ~E1000_CTRL_MDC)); 267062306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 267162306a36Sopenharmony_ci udelay(10); 267262306a36Sopenharmony_ci} 267362306a36Sopenharmony_ci 267462306a36Sopenharmony_ci/** 267562306a36Sopenharmony_ci * e1000_shift_out_mdi_bits - Shifts data bits out to the PHY 267662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 267762306a36Sopenharmony_ci * @data: Data to send out to the PHY 267862306a36Sopenharmony_ci * @count: Number of bits to shift out 267962306a36Sopenharmony_ci * 268062306a36Sopenharmony_ci * Bits are shifted out in MSB to LSB order. 268162306a36Sopenharmony_ci */ 268262306a36Sopenharmony_cistatic void e1000_shift_out_mdi_bits(struct e1000_hw *hw, u32 data, u16 count) 268362306a36Sopenharmony_ci{ 268462306a36Sopenharmony_ci u32 ctrl; 268562306a36Sopenharmony_ci u32 mask; 268662306a36Sopenharmony_ci 268762306a36Sopenharmony_ci /* We need to shift "count" number of bits out to the PHY. So, the value 268862306a36Sopenharmony_ci * in the "data" parameter will be shifted out to the PHY one bit at a 268962306a36Sopenharmony_ci * time. In order to do this, "data" must be broken down into bits. 269062306a36Sopenharmony_ci */ 269162306a36Sopenharmony_ci mask = 0x01; 269262306a36Sopenharmony_ci mask <<= (count - 1); 269362306a36Sopenharmony_ci 269462306a36Sopenharmony_ci ctrl = er32(CTRL); 269562306a36Sopenharmony_ci 269662306a36Sopenharmony_ci /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ 269762306a36Sopenharmony_ci ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); 269862306a36Sopenharmony_ci 269962306a36Sopenharmony_ci while (mask) { 270062306a36Sopenharmony_ci /* A "1" is shifted out to the PHY by setting the MDIO bit to 270162306a36Sopenharmony_ci * "1" and then raising and lowering the Management Data Clock. 270262306a36Sopenharmony_ci * A "0" is shifted out to the PHY by setting the MDIO bit to 270362306a36Sopenharmony_ci * "0" and then raising and lowering the clock. 270462306a36Sopenharmony_ci */ 270562306a36Sopenharmony_ci if (data & mask) 270662306a36Sopenharmony_ci ctrl |= E1000_CTRL_MDIO; 270762306a36Sopenharmony_ci else 270862306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_MDIO; 270962306a36Sopenharmony_ci 271062306a36Sopenharmony_ci ew32(CTRL, ctrl); 271162306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 271262306a36Sopenharmony_ci 271362306a36Sopenharmony_ci udelay(10); 271462306a36Sopenharmony_ci 271562306a36Sopenharmony_ci e1000_raise_mdi_clk(hw, &ctrl); 271662306a36Sopenharmony_ci e1000_lower_mdi_clk(hw, &ctrl); 271762306a36Sopenharmony_ci 271862306a36Sopenharmony_ci mask = mask >> 1; 271962306a36Sopenharmony_ci } 272062306a36Sopenharmony_ci} 272162306a36Sopenharmony_ci 272262306a36Sopenharmony_ci/** 272362306a36Sopenharmony_ci * e1000_shift_in_mdi_bits - Shifts data bits in from the PHY 272462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 272562306a36Sopenharmony_ci * 272662306a36Sopenharmony_ci * Bits are shifted in MSB to LSB order. 272762306a36Sopenharmony_ci */ 272862306a36Sopenharmony_cistatic u16 e1000_shift_in_mdi_bits(struct e1000_hw *hw) 272962306a36Sopenharmony_ci{ 273062306a36Sopenharmony_ci u32 ctrl; 273162306a36Sopenharmony_ci u16 data = 0; 273262306a36Sopenharmony_ci u8 i; 273362306a36Sopenharmony_ci 273462306a36Sopenharmony_ci /* In order to read a register from the PHY, we need to shift in a total 273562306a36Sopenharmony_ci * of 18 bits from the PHY. The first two bit (turnaround) times are 273662306a36Sopenharmony_ci * used to avoid contention on the MDIO pin when a read operation is 273762306a36Sopenharmony_ci * performed. These two bits are ignored by us and thrown away. Bits are 273862306a36Sopenharmony_ci * "shifted in" by raising the input to the Management Data Clock 273962306a36Sopenharmony_ci * (setting the MDC bit), and then reading the value of the MDIO bit. 274062306a36Sopenharmony_ci */ 274162306a36Sopenharmony_ci ctrl = er32(CTRL); 274262306a36Sopenharmony_ci 274362306a36Sopenharmony_ci /* Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as 274462306a36Sopenharmony_ci * input. 274562306a36Sopenharmony_ci */ 274662306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_MDIO_DIR; 274762306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_MDIO; 274862306a36Sopenharmony_ci 274962306a36Sopenharmony_ci ew32(CTRL, ctrl); 275062306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 275162306a36Sopenharmony_ci 275262306a36Sopenharmony_ci /* Raise and Lower the clock before reading in the data. This accounts 275362306a36Sopenharmony_ci * for the turnaround bits. The first clock occurred when we clocked out 275462306a36Sopenharmony_ci * the last bit of the Register Address. 275562306a36Sopenharmony_ci */ 275662306a36Sopenharmony_ci e1000_raise_mdi_clk(hw, &ctrl); 275762306a36Sopenharmony_ci e1000_lower_mdi_clk(hw, &ctrl); 275862306a36Sopenharmony_ci 275962306a36Sopenharmony_ci for (data = 0, i = 0; i < 16; i++) { 276062306a36Sopenharmony_ci data = data << 1; 276162306a36Sopenharmony_ci e1000_raise_mdi_clk(hw, &ctrl); 276262306a36Sopenharmony_ci ctrl = er32(CTRL); 276362306a36Sopenharmony_ci /* Check to see if we shifted in a "1". */ 276462306a36Sopenharmony_ci if (ctrl & E1000_CTRL_MDIO) 276562306a36Sopenharmony_ci data |= 1; 276662306a36Sopenharmony_ci e1000_lower_mdi_clk(hw, &ctrl); 276762306a36Sopenharmony_ci } 276862306a36Sopenharmony_ci 276962306a36Sopenharmony_ci e1000_raise_mdi_clk(hw, &ctrl); 277062306a36Sopenharmony_ci e1000_lower_mdi_clk(hw, &ctrl); 277162306a36Sopenharmony_ci 277262306a36Sopenharmony_ci return data; 277362306a36Sopenharmony_ci} 277462306a36Sopenharmony_ci 277562306a36Sopenharmony_ci/** 277662306a36Sopenharmony_ci * e1000_read_phy_reg - read a phy register 277762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 277862306a36Sopenharmony_ci * @reg_addr: address of the PHY register to read 277962306a36Sopenharmony_ci * @phy_data: pointer to the value on the PHY register 278062306a36Sopenharmony_ci * 278162306a36Sopenharmony_ci * Reads the value from a PHY register, if the value is on a specific non zero 278262306a36Sopenharmony_ci * page, sets the page first. 278362306a36Sopenharmony_ci */ 278462306a36Sopenharmony_cis32 e1000_read_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 *phy_data) 278562306a36Sopenharmony_ci{ 278662306a36Sopenharmony_ci u32 ret_val; 278762306a36Sopenharmony_ci unsigned long flags; 278862306a36Sopenharmony_ci 278962306a36Sopenharmony_ci spin_lock_irqsave(&e1000_phy_lock, flags); 279062306a36Sopenharmony_ci 279162306a36Sopenharmony_ci if ((hw->phy_type == e1000_phy_igp) && 279262306a36Sopenharmony_ci (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { 279362306a36Sopenharmony_ci ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, 279462306a36Sopenharmony_ci (u16) reg_addr); 279562306a36Sopenharmony_ci if (ret_val) 279662306a36Sopenharmony_ci goto out; 279762306a36Sopenharmony_ci } 279862306a36Sopenharmony_ci 279962306a36Sopenharmony_ci ret_val = e1000_read_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, 280062306a36Sopenharmony_ci phy_data); 280162306a36Sopenharmony_ciout: 280262306a36Sopenharmony_ci spin_unlock_irqrestore(&e1000_phy_lock, flags); 280362306a36Sopenharmony_ci 280462306a36Sopenharmony_ci return ret_val; 280562306a36Sopenharmony_ci} 280662306a36Sopenharmony_ci 280762306a36Sopenharmony_cistatic s32 e1000_read_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, 280862306a36Sopenharmony_ci u16 *phy_data) 280962306a36Sopenharmony_ci{ 281062306a36Sopenharmony_ci u32 i; 281162306a36Sopenharmony_ci u32 mdic = 0; 281262306a36Sopenharmony_ci const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1; 281362306a36Sopenharmony_ci 281462306a36Sopenharmony_ci if (reg_addr > MAX_PHY_REG_ADDRESS) { 281562306a36Sopenharmony_ci e_dbg("PHY Address %d is out of range\n", reg_addr); 281662306a36Sopenharmony_ci return -E1000_ERR_PARAM; 281762306a36Sopenharmony_ci } 281862306a36Sopenharmony_ci 281962306a36Sopenharmony_ci if (hw->mac_type > e1000_82543) { 282062306a36Sopenharmony_ci /* Set up Op-code, Phy Address, and register address in the MDI 282162306a36Sopenharmony_ci * Control register. The MAC will take care of interfacing with 282262306a36Sopenharmony_ci * the PHY to retrieve the desired data. 282362306a36Sopenharmony_ci */ 282462306a36Sopenharmony_ci if (hw->mac_type == e1000_ce4100) { 282562306a36Sopenharmony_ci mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | 282662306a36Sopenharmony_ci (phy_addr << E1000_MDIC_PHY_SHIFT) | 282762306a36Sopenharmony_ci (INTEL_CE_GBE_MDIC_OP_READ) | 282862306a36Sopenharmony_ci (INTEL_CE_GBE_MDIC_GO)); 282962306a36Sopenharmony_ci 283062306a36Sopenharmony_ci writel(mdic, E1000_MDIO_CMD); 283162306a36Sopenharmony_ci 283262306a36Sopenharmony_ci /* Poll the ready bit to see if the MDI read 283362306a36Sopenharmony_ci * completed 283462306a36Sopenharmony_ci */ 283562306a36Sopenharmony_ci for (i = 0; i < 64; i++) { 283662306a36Sopenharmony_ci udelay(50); 283762306a36Sopenharmony_ci mdic = readl(E1000_MDIO_CMD); 283862306a36Sopenharmony_ci if (!(mdic & INTEL_CE_GBE_MDIC_GO)) 283962306a36Sopenharmony_ci break; 284062306a36Sopenharmony_ci } 284162306a36Sopenharmony_ci 284262306a36Sopenharmony_ci if (mdic & INTEL_CE_GBE_MDIC_GO) { 284362306a36Sopenharmony_ci e_dbg("MDI Read did not complete\n"); 284462306a36Sopenharmony_ci return -E1000_ERR_PHY; 284562306a36Sopenharmony_ci } 284662306a36Sopenharmony_ci 284762306a36Sopenharmony_ci mdic = readl(E1000_MDIO_STS); 284862306a36Sopenharmony_ci if (mdic & INTEL_CE_GBE_MDIC_READ_ERROR) { 284962306a36Sopenharmony_ci e_dbg("MDI Read Error\n"); 285062306a36Sopenharmony_ci return -E1000_ERR_PHY; 285162306a36Sopenharmony_ci } 285262306a36Sopenharmony_ci *phy_data = (u16)mdic; 285362306a36Sopenharmony_ci } else { 285462306a36Sopenharmony_ci mdic = ((reg_addr << E1000_MDIC_REG_SHIFT) | 285562306a36Sopenharmony_ci (phy_addr << E1000_MDIC_PHY_SHIFT) | 285662306a36Sopenharmony_ci (E1000_MDIC_OP_READ)); 285762306a36Sopenharmony_ci 285862306a36Sopenharmony_ci ew32(MDIC, mdic); 285962306a36Sopenharmony_ci 286062306a36Sopenharmony_ci /* Poll the ready bit to see if the MDI read 286162306a36Sopenharmony_ci * completed 286262306a36Sopenharmony_ci */ 286362306a36Sopenharmony_ci for (i = 0; i < 64; i++) { 286462306a36Sopenharmony_ci udelay(50); 286562306a36Sopenharmony_ci mdic = er32(MDIC); 286662306a36Sopenharmony_ci if (mdic & E1000_MDIC_READY) 286762306a36Sopenharmony_ci break; 286862306a36Sopenharmony_ci } 286962306a36Sopenharmony_ci if (!(mdic & E1000_MDIC_READY)) { 287062306a36Sopenharmony_ci e_dbg("MDI Read did not complete\n"); 287162306a36Sopenharmony_ci return -E1000_ERR_PHY; 287262306a36Sopenharmony_ci } 287362306a36Sopenharmony_ci if (mdic & E1000_MDIC_ERROR) { 287462306a36Sopenharmony_ci e_dbg("MDI Error\n"); 287562306a36Sopenharmony_ci return -E1000_ERR_PHY; 287662306a36Sopenharmony_ci } 287762306a36Sopenharmony_ci *phy_data = (u16)mdic; 287862306a36Sopenharmony_ci } 287962306a36Sopenharmony_ci } else { 288062306a36Sopenharmony_ci /* We must first send a preamble through the MDIO pin to signal 288162306a36Sopenharmony_ci * the beginning of an MII instruction. This is done by sending 288262306a36Sopenharmony_ci * 32 consecutive "1" bits. 288362306a36Sopenharmony_ci */ 288462306a36Sopenharmony_ci e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); 288562306a36Sopenharmony_ci 288662306a36Sopenharmony_ci /* Now combine the next few fields that are required for a read 288762306a36Sopenharmony_ci * operation. We use this method instead of calling the 288862306a36Sopenharmony_ci * e1000_shift_out_mdi_bits routine five different times. The 288962306a36Sopenharmony_ci * format of a MII read instruction consists of a shift out of 289062306a36Sopenharmony_ci * 14 bits and is defined as follows: 289162306a36Sopenharmony_ci * <Preamble><SOF><Op Code><Phy Addr><Reg Addr> 289262306a36Sopenharmony_ci * followed by a shift in of 18 bits. This first two bits 289362306a36Sopenharmony_ci * shifted in are TurnAround bits used to avoid contention on 289462306a36Sopenharmony_ci * the MDIO pin when a READ operation is performed. These two 289562306a36Sopenharmony_ci * bits are thrown away followed by a shift in of 16 bits which 289662306a36Sopenharmony_ci * contains the desired data. 289762306a36Sopenharmony_ci */ 289862306a36Sopenharmony_ci mdic = ((reg_addr) | (phy_addr << 5) | 289962306a36Sopenharmony_ci (PHY_OP_READ << 10) | (PHY_SOF << 12)); 290062306a36Sopenharmony_ci 290162306a36Sopenharmony_ci e1000_shift_out_mdi_bits(hw, mdic, 14); 290262306a36Sopenharmony_ci 290362306a36Sopenharmony_ci /* Now that we've shifted out the read command to the MII, we 290462306a36Sopenharmony_ci * need to "shift in" the 16-bit value (18 total bits) of the 290562306a36Sopenharmony_ci * requested PHY register address. 290662306a36Sopenharmony_ci */ 290762306a36Sopenharmony_ci *phy_data = e1000_shift_in_mdi_bits(hw); 290862306a36Sopenharmony_ci } 290962306a36Sopenharmony_ci return E1000_SUCCESS; 291062306a36Sopenharmony_ci} 291162306a36Sopenharmony_ci 291262306a36Sopenharmony_ci/** 291362306a36Sopenharmony_ci * e1000_write_phy_reg - write a phy register 291462306a36Sopenharmony_ci * 291562306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 291662306a36Sopenharmony_ci * @reg_addr: address of the PHY register to write 291762306a36Sopenharmony_ci * @phy_data: data to write to the PHY 291862306a36Sopenharmony_ci * 291962306a36Sopenharmony_ci * Writes a value to a PHY register 292062306a36Sopenharmony_ci */ 292162306a36Sopenharmony_cis32 e1000_write_phy_reg(struct e1000_hw *hw, u32 reg_addr, u16 phy_data) 292262306a36Sopenharmony_ci{ 292362306a36Sopenharmony_ci u32 ret_val; 292462306a36Sopenharmony_ci unsigned long flags; 292562306a36Sopenharmony_ci 292662306a36Sopenharmony_ci spin_lock_irqsave(&e1000_phy_lock, flags); 292762306a36Sopenharmony_ci 292862306a36Sopenharmony_ci if ((hw->phy_type == e1000_phy_igp) && 292962306a36Sopenharmony_ci (reg_addr > MAX_PHY_MULTI_PAGE_REG)) { 293062306a36Sopenharmony_ci ret_val = e1000_write_phy_reg_ex(hw, IGP01E1000_PHY_PAGE_SELECT, 293162306a36Sopenharmony_ci (u16)reg_addr); 293262306a36Sopenharmony_ci if (ret_val) { 293362306a36Sopenharmony_ci spin_unlock_irqrestore(&e1000_phy_lock, flags); 293462306a36Sopenharmony_ci return ret_val; 293562306a36Sopenharmony_ci } 293662306a36Sopenharmony_ci } 293762306a36Sopenharmony_ci 293862306a36Sopenharmony_ci ret_val = e1000_write_phy_reg_ex(hw, MAX_PHY_REG_ADDRESS & reg_addr, 293962306a36Sopenharmony_ci phy_data); 294062306a36Sopenharmony_ci spin_unlock_irqrestore(&e1000_phy_lock, flags); 294162306a36Sopenharmony_ci 294262306a36Sopenharmony_ci return ret_val; 294362306a36Sopenharmony_ci} 294462306a36Sopenharmony_ci 294562306a36Sopenharmony_cistatic s32 e1000_write_phy_reg_ex(struct e1000_hw *hw, u32 reg_addr, 294662306a36Sopenharmony_ci u16 phy_data) 294762306a36Sopenharmony_ci{ 294862306a36Sopenharmony_ci u32 i; 294962306a36Sopenharmony_ci u32 mdic = 0; 295062306a36Sopenharmony_ci const u32 phy_addr = (hw->mac_type == e1000_ce4100) ? hw->phy_addr : 1; 295162306a36Sopenharmony_ci 295262306a36Sopenharmony_ci if (reg_addr > MAX_PHY_REG_ADDRESS) { 295362306a36Sopenharmony_ci e_dbg("PHY Address %d is out of range\n", reg_addr); 295462306a36Sopenharmony_ci return -E1000_ERR_PARAM; 295562306a36Sopenharmony_ci } 295662306a36Sopenharmony_ci 295762306a36Sopenharmony_ci if (hw->mac_type > e1000_82543) { 295862306a36Sopenharmony_ci /* Set up Op-code, Phy Address, register address, and data 295962306a36Sopenharmony_ci * intended for the PHY register in the MDI Control register. 296062306a36Sopenharmony_ci * The MAC will take care of interfacing with the PHY to send 296162306a36Sopenharmony_ci * the desired data. 296262306a36Sopenharmony_ci */ 296362306a36Sopenharmony_ci if (hw->mac_type == e1000_ce4100) { 296462306a36Sopenharmony_ci mdic = (((u32)phy_data) | 296562306a36Sopenharmony_ci (reg_addr << E1000_MDIC_REG_SHIFT) | 296662306a36Sopenharmony_ci (phy_addr << E1000_MDIC_PHY_SHIFT) | 296762306a36Sopenharmony_ci (INTEL_CE_GBE_MDIC_OP_WRITE) | 296862306a36Sopenharmony_ci (INTEL_CE_GBE_MDIC_GO)); 296962306a36Sopenharmony_ci 297062306a36Sopenharmony_ci writel(mdic, E1000_MDIO_CMD); 297162306a36Sopenharmony_ci 297262306a36Sopenharmony_ci /* Poll the ready bit to see if the MDI read 297362306a36Sopenharmony_ci * completed 297462306a36Sopenharmony_ci */ 297562306a36Sopenharmony_ci for (i = 0; i < 640; i++) { 297662306a36Sopenharmony_ci udelay(5); 297762306a36Sopenharmony_ci mdic = readl(E1000_MDIO_CMD); 297862306a36Sopenharmony_ci if (!(mdic & INTEL_CE_GBE_MDIC_GO)) 297962306a36Sopenharmony_ci break; 298062306a36Sopenharmony_ci } 298162306a36Sopenharmony_ci if (mdic & INTEL_CE_GBE_MDIC_GO) { 298262306a36Sopenharmony_ci e_dbg("MDI Write did not complete\n"); 298362306a36Sopenharmony_ci return -E1000_ERR_PHY; 298462306a36Sopenharmony_ci } 298562306a36Sopenharmony_ci } else { 298662306a36Sopenharmony_ci mdic = (((u32)phy_data) | 298762306a36Sopenharmony_ci (reg_addr << E1000_MDIC_REG_SHIFT) | 298862306a36Sopenharmony_ci (phy_addr << E1000_MDIC_PHY_SHIFT) | 298962306a36Sopenharmony_ci (E1000_MDIC_OP_WRITE)); 299062306a36Sopenharmony_ci 299162306a36Sopenharmony_ci ew32(MDIC, mdic); 299262306a36Sopenharmony_ci 299362306a36Sopenharmony_ci /* Poll the ready bit to see if the MDI read 299462306a36Sopenharmony_ci * completed 299562306a36Sopenharmony_ci */ 299662306a36Sopenharmony_ci for (i = 0; i < 641; i++) { 299762306a36Sopenharmony_ci udelay(5); 299862306a36Sopenharmony_ci mdic = er32(MDIC); 299962306a36Sopenharmony_ci if (mdic & E1000_MDIC_READY) 300062306a36Sopenharmony_ci break; 300162306a36Sopenharmony_ci } 300262306a36Sopenharmony_ci if (!(mdic & E1000_MDIC_READY)) { 300362306a36Sopenharmony_ci e_dbg("MDI Write did not complete\n"); 300462306a36Sopenharmony_ci return -E1000_ERR_PHY; 300562306a36Sopenharmony_ci } 300662306a36Sopenharmony_ci } 300762306a36Sopenharmony_ci } else { 300862306a36Sopenharmony_ci /* We'll need to use the SW defined pins to shift the write 300962306a36Sopenharmony_ci * command out to the PHY. We first send a preamble to the PHY 301062306a36Sopenharmony_ci * to signal the beginning of the MII instruction. This is done 301162306a36Sopenharmony_ci * by sending 32 consecutive "1" bits. 301262306a36Sopenharmony_ci */ 301362306a36Sopenharmony_ci e1000_shift_out_mdi_bits(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); 301462306a36Sopenharmony_ci 301562306a36Sopenharmony_ci /* Now combine the remaining required fields that will indicate 301662306a36Sopenharmony_ci * a write operation. We use this method instead of calling the 301762306a36Sopenharmony_ci * e1000_shift_out_mdi_bits routine for each field in the 301862306a36Sopenharmony_ci * command. The format of a MII write instruction is as follows: 301962306a36Sopenharmony_ci * <Preamble><SOF><OpCode><PhyAddr><RegAddr><Turnaround><Data>. 302062306a36Sopenharmony_ci */ 302162306a36Sopenharmony_ci mdic = ((PHY_TURNAROUND) | (reg_addr << 2) | (phy_addr << 7) | 302262306a36Sopenharmony_ci (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); 302362306a36Sopenharmony_ci mdic <<= 16; 302462306a36Sopenharmony_ci mdic |= (u32)phy_data; 302562306a36Sopenharmony_ci 302662306a36Sopenharmony_ci e1000_shift_out_mdi_bits(hw, mdic, 32); 302762306a36Sopenharmony_ci } 302862306a36Sopenharmony_ci 302962306a36Sopenharmony_ci return E1000_SUCCESS; 303062306a36Sopenharmony_ci} 303162306a36Sopenharmony_ci 303262306a36Sopenharmony_ci/** 303362306a36Sopenharmony_ci * e1000_phy_hw_reset - reset the phy, hardware style 303462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 303562306a36Sopenharmony_ci * 303662306a36Sopenharmony_ci * Returns the PHY to the power-on reset state 303762306a36Sopenharmony_ci */ 303862306a36Sopenharmony_cis32 e1000_phy_hw_reset(struct e1000_hw *hw) 303962306a36Sopenharmony_ci{ 304062306a36Sopenharmony_ci u32 ctrl, ctrl_ext; 304162306a36Sopenharmony_ci u32 led_ctrl; 304262306a36Sopenharmony_ci 304362306a36Sopenharmony_ci e_dbg("Resetting Phy...\n"); 304462306a36Sopenharmony_ci 304562306a36Sopenharmony_ci if (hw->mac_type > e1000_82543) { 304662306a36Sopenharmony_ci /* Read the device control register and assert the 304762306a36Sopenharmony_ci * E1000_CTRL_PHY_RST bit. Then, take it out of reset. 304862306a36Sopenharmony_ci * For e1000 hardware, we delay for 10ms between the assert 304962306a36Sopenharmony_ci * and de-assert. 305062306a36Sopenharmony_ci */ 305162306a36Sopenharmony_ci ctrl = er32(CTRL); 305262306a36Sopenharmony_ci ew32(CTRL, ctrl | E1000_CTRL_PHY_RST); 305362306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 305462306a36Sopenharmony_ci 305562306a36Sopenharmony_ci msleep(10); 305662306a36Sopenharmony_ci 305762306a36Sopenharmony_ci ew32(CTRL, ctrl); 305862306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 305962306a36Sopenharmony_ci 306062306a36Sopenharmony_ci } else { 306162306a36Sopenharmony_ci /* Read the Extended Device Control Register, assert the 306262306a36Sopenharmony_ci * PHY_RESET_DIR bit to put the PHY into reset. Then, take it 306362306a36Sopenharmony_ci * out of reset. 306462306a36Sopenharmony_ci */ 306562306a36Sopenharmony_ci ctrl_ext = er32(CTRL_EXT); 306662306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; 306762306a36Sopenharmony_ci ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; 306862306a36Sopenharmony_ci ew32(CTRL_EXT, ctrl_ext); 306962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 307062306a36Sopenharmony_ci msleep(10); 307162306a36Sopenharmony_ci ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; 307262306a36Sopenharmony_ci ew32(CTRL_EXT, ctrl_ext); 307362306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 307462306a36Sopenharmony_ci } 307562306a36Sopenharmony_ci udelay(150); 307662306a36Sopenharmony_ci 307762306a36Sopenharmony_ci if ((hw->mac_type == e1000_82541) || (hw->mac_type == e1000_82547)) { 307862306a36Sopenharmony_ci /* Configure activity LED after PHY reset */ 307962306a36Sopenharmony_ci led_ctrl = er32(LEDCTL); 308062306a36Sopenharmony_ci led_ctrl &= IGP_ACTIVITY_LED_MASK; 308162306a36Sopenharmony_ci led_ctrl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE); 308262306a36Sopenharmony_ci ew32(LEDCTL, led_ctrl); 308362306a36Sopenharmony_ci } 308462306a36Sopenharmony_ci 308562306a36Sopenharmony_ci /* Wait for FW to finish PHY configuration. */ 308662306a36Sopenharmony_ci return e1000_get_phy_cfg_done(hw); 308762306a36Sopenharmony_ci} 308862306a36Sopenharmony_ci 308962306a36Sopenharmony_ci/** 309062306a36Sopenharmony_ci * e1000_phy_reset - reset the phy to commit settings 309162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 309262306a36Sopenharmony_ci * 309362306a36Sopenharmony_ci * Resets the PHY 309462306a36Sopenharmony_ci * Sets bit 15 of the MII Control register 309562306a36Sopenharmony_ci */ 309662306a36Sopenharmony_cis32 e1000_phy_reset(struct e1000_hw *hw) 309762306a36Sopenharmony_ci{ 309862306a36Sopenharmony_ci s32 ret_val; 309962306a36Sopenharmony_ci u16 phy_data; 310062306a36Sopenharmony_ci 310162306a36Sopenharmony_ci switch (hw->phy_type) { 310262306a36Sopenharmony_ci case e1000_phy_igp: 310362306a36Sopenharmony_ci ret_val = e1000_phy_hw_reset(hw); 310462306a36Sopenharmony_ci if (ret_val) 310562306a36Sopenharmony_ci return ret_val; 310662306a36Sopenharmony_ci break; 310762306a36Sopenharmony_ci default: 310862306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_CTRL, &phy_data); 310962306a36Sopenharmony_ci if (ret_val) 311062306a36Sopenharmony_ci return ret_val; 311162306a36Sopenharmony_ci 311262306a36Sopenharmony_ci phy_data |= MII_CR_RESET; 311362306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, PHY_CTRL, phy_data); 311462306a36Sopenharmony_ci if (ret_val) 311562306a36Sopenharmony_ci return ret_val; 311662306a36Sopenharmony_ci 311762306a36Sopenharmony_ci udelay(1); 311862306a36Sopenharmony_ci break; 311962306a36Sopenharmony_ci } 312062306a36Sopenharmony_ci 312162306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_igp) 312262306a36Sopenharmony_ci e1000_phy_init_script(hw); 312362306a36Sopenharmony_ci 312462306a36Sopenharmony_ci return E1000_SUCCESS; 312562306a36Sopenharmony_ci} 312662306a36Sopenharmony_ci 312762306a36Sopenharmony_ci/** 312862306a36Sopenharmony_ci * e1000_detect_gig_phy - check the phy type 312962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 313062306a36Sopenharmony_ci * 313162306a36Sopenharmony_ci * Probes the expected PHY address for known PHY IDs 313262306a36Sopenharmony_ci */ 313362306a36Sopenharmony_cistatic s32 e1000_detect_gig_phy(struct e1000_hw *hw) 313462306a36Sopenharmony_ci{ 313562306a36Sopenharmony_ci s32 phy_init_status, ret_val; 313662306a36Sopenharmony_ci u16 phy_id_high, phy_id_low; 313762306a36Sopenharmony_ci bool match = false; 313862306a36Sopenharmony_ci 313962306a36Sopenharmony_ci if (hw->phy_id != 0) 314062306a36Sopenharmony_ci return E1000_SUCCESS; 314162306a36Sopenharmony_ci 314262306a36Sopenharmony_ci /* Read the PHY ID Registers to identify which PHY is onboard. */ 314362306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_ID1, &phy_id_high); 314462306a36Sopenharmony_ci if (ret_val) 314562306a36Sopenharmony_ci return ret_val; 314662306a36Sopenharmony_ci 314762306a36Sopenharmony_ci hw->phy_id = (u32)(phy_id_high << 16); 314862306a36Sopenharmony_ci udelay(20); 314962306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_ID2, &phy_id_low); 315062306a36Sopenharmony_ci if (ret_val) 315162306a36Sopenharmony_ci return ret_val; 315262306a36Sopenharmony_ci 315362306a36Sopenharmony_ci hw->phy_id |= (u32)(phy_id_low & PHY_REVISION_MASK); 315462306a36Sopenharmony_ci hw->phy_revision = (u32)phy_id_low & ~PHY_REVISION_MASK; 315562306a36Sopenharmony_ci 315662306a36Sopenharmony_ci switch (hw->mac_type) { 315762306a36Sopenharmony_ci case e1000_82543: 315862306a36Sopenharmony_ci if (hw->phy_id == M88E1000_E_PHY_ID) 315962306a36Sopenharmony_ci match = true; 316062306a36Sopenharmony_ci break; 316162306a36Sopenharmony_ci case e1000_82544: 316262306a36Sopenharmony_ci if (hw->phy_id == M88E1000_I_PHY_ID) 316362306a36Sopenharmony_ci match = true; 316462306a36Sopenharmony_ci break; 316562306a36Sopenharmony_ci case e1000_82540: 316662306a36Sopenharmony_ci case e1000_82545: 316762306a36Sopenharmony_ci case e1000_82545_rev_3: 316862306a36Sopenharmony_ci case e1000_82546: 316962306a36Sopenharmony_ci case e1000_82546_rev_3: 317062306a36Sopenharmony_ci if (hw->phy_id == M88E1011_I_PHY_ID) 317162306a36Sopenharmony_ci match = true; 317262306a36Sopenharmony_ci break; 317362306a36Sopenharmony_ci case e1000_ce4100: 317462306a36Sopenharmony_ci if ((hw->phy_id == RTL8211B_PHY_ID) || 317562306a36Sopenharmony_ci (hw->phy_id == RTL8201N_PHY_ID) || 317662306a36Sopenharmony_ci (hw->phy_id == M88E1118_E_PHY_ID)) 317762306a36Sopenharmony_ci match = true; 317862306a36Sopenharmony_ci break; 317962306a36Sopenharmony_ci case e1000_82541: 318062306a36Sopenharmony_ci case e1000_82541_rev_2: 318162306a36Sopenharmony_ci case e1000_82547: 318262306a36Sopenharmony_ci case e1000_82547_rev_2: 318362306a36Sopenharmony_ci if (hw->phy_id == IGP01E1000_I_PHY_ID) 318462306a36Sopenharmony_ci match = true; 318562306a36Sopenharmony_ci break; 318662306a36Sopenharmony_ci default: 318762306a36Sopenharmony_ci e_dbg("Invalid MAC type %d\n", hw->mac_type); 318862306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 318962306a36Sopenharmony_ci } 319062306a36Sopenharmony_ci phy_init_status = e1000_set_phy_type(hw); 319162306a36Sopenharmony_ci 319262306a36Sopenharmony_ci if ((match) && (phy_init_status == E1000_SUCCESS)) { 319362306a36Sopenharmony_ci e_dbg("PHY ID 0x%X detected\n", hw->phy_id); 319462306a36Sopenharmony_ci return E1000_SUCCESS; 319562306a36Sopenharmony_ci } 319662306a36Sopenharmony_ci e_dbg("Invalid PHY ID 0x%X\n", hw->phy_id); 319762306a36Sopenharmony_ci return -E1000_ERR_PHY; 319862306a36Sopenharmony_ci} 319962306a36Sopenharmony_ci 320062306a36Sopenharmony_ci/** 320162306a36Sopenharmony_ci * e1000_phy_reset_dsp - reset DSP 320262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 320362306a36Sopenharmony_ci * 320462306a36Sopenharmony_ci * Resets the PHY's DSP 320562306a36Sopenharmony_ci */ 320662306a36Sopenharmony_cistatic s32 e1000_phy_reset_dsp(struct e1000_hw *hw) 320762306a36Sopenharmony_ci{ 320862306a36Sopenharmony_ci s32 ret_val; 320962306a36Sopenharmony_ci 321062306a36Sopenharmony_ci do { 321162306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 29, 0x001d); 321262306a36Sopenharmony_ci if (ret_val) 321362306a36Sopenharmony_ci break; 321462306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 30, 0x00c1); 321562306a36Sopenharmony_ci if (ret_val) 321662306a36Sopenharmony_ci break; 321762306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 30, 0x0000); 321862306a36Sopenharmony_ci if (ret_val) 321962306a36Sopenharmony_ci break; 322062306a36Sopenharmony_ci ret_val = E1000_SUCCESS; 322162306a36Sopenharmony_ci } while (0); 322262306a36Sopenharmony_ci 322362306a36Sopenharmony_ci return ret_val; 322462306a36Sopenharmony_ci} 322562306a36Sopenharmony_ci 322662306a36Sopenharmony_ci/** 322762306a36Sopenharmony_ci * e1000_phy_igp_get_info - get igp specific registers 322862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 322962306a36Sopenharmony_ci * @phy_info: PHY information structure 323062306a36Sopenharmony_ci * 323162306a36Sopenharmony_ci * Get PHY information from various PHY registers for igp PHY only. 323262306a36Sopenharmony_ci */ 323362306a36Sopenharmony_cistatic s32 e1000_phy_igp_get_info(struct e1000_hw *hw, 323462306a36Sopenharmony_ci struct e1000_phy_info *phy_info) 323562306a36Sopenharmony_ci{ 323662306a36Sopenharmony_ci s32 ret_val; 323762306a36Sopenharmony_ci u16 phy_data, min_length, max_length, average; 323862306a36Sopenharmony_ci e1000_rev_polarity polarity; 323962306a36Sopenharmony_ci 324062306a36Sopenharmony_ci /* The downshift status is checked only once, after link is established, 324162306a36Sopenharmony_ci * and it stored in the hw->speed_downgraded parameter. 324262306a36Sopenharmony_ci */ 324362306a36Sopenharmony_ci phy_info->downshift = (e1000_downshift) hw->speed_downgraded; 324462306a36Sopenharmony_ci 324562306a36Sopenharmony_ci /* IGP01E1000 does not need to support it. */ 324662306a36Sopenharmony_ci phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_normal; 324762306a36Sopenharmony_ci 324862306a36Sopenharmony_ci /* IGP01E1000 always correct polarity reversal */ 324962306a36Sopenharmony_ci phy_info->polarity_correction = e1000_polarity_reversal_enabled; 325062306a36Sopenharmony_ci 325162306a36Sopenharmony_ci /* Check polarity status */ 325262306a36Sopenharmony_ci ret_val = e1000_check_polarity(hw, &polarity); 325362306a36Sopenharmony_ci if (ret_val) 325462306a36Sopenharmony_ci return ret_val; 325562306a36Sopenharmony_ci 325662306a36Sopenharmony_ci phy_info->cable_polarity = polarity; 325762306a36Sopenharmony_ci 325862306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, &phy_data); 325962306a36Sopenharmony_ci if (ret_val) 326062306a36Sopenharmony_ci return ret_val; 326162306a36Sopenharmony_ci 326262306a36Sopenharmony_ci phy_info->mdix_mode = 326362306a36Sopenharmony_ci (e1000_auto_x_mode) ((phy_data & IGP01E1000_PSSR_MDIX) >> 326462306a36Sopenharmony_ci IGP01E1000_PSSR_MDIX_SHIFT); 326562306a36Sopenharmony_ci 326662306a36Sopenharmony_ci if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == 326762306a36Sopenharmony_ci IGP01E1000_PSSR_SPEED_1000MBPS) { 326862306a36Sopenharmony_ci /* Local/Remote Receiver Information are only valid @ 1000 326962306a36Sopenharmony_ci * Mbps 327062306a36Sopenharmony_ci */ 327162306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); 327262306a36Sopenharmony_ci if (ret_val) 327362306a36Sopenharmony_ci return ret_val; 327462306a36Sopenharmony_ci 327562306a36Sopenharmony_ci phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> 327662306a36Sopenharmony_ci SR_1000T_LOCAL_RX_STATUS_SHIFT) ? 327762306a36Sopenharmony_ci e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; 327862306a36Sopenharmony_ci phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> 327962306a36Sopenharmony_ci SR_1000T_REMOTE_RX_STATUS_SHIFT) ? 328062306a36Sopenharmony_ci e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; 328162306a36Sopenharmony_ci 328262306a36Sopenharmony_ci /* Get cable length */ 328362306a36Sopenharmony_ci ret_val = e1000_get_cable_length(hw, &min_length, &max_length); 328462306a36Sopenharmony_ci if (ret_val) 328562306a36Sopenharmony_ci return ret_val; 328662306a36Sopenharmony_ci 328762306a36Sopenharmony_ci /* Translate to old method */ 328862306a36Sopenharmony_ci average = (max_length + min_length) / 2; 328962306a36Sopenharmony_ci 329062306a36Sopenharmony_ci if (average <= e1000_igp_cable_length_50) 329162306a36Sopenharmony_ci phy_info->cable_length = e1000_cable_length_50; 329262306a36Sopenharmony_ci else if (average <= e1000_igp_cable_length_80) 329362306a36Sopenharmony_ci phy_info->cable_length = e1000_cable_length_50_80; 329462306a36Sopenharmony_ci else if (average <= e1000_igp_cable_length_110) 329562306a36Sopenharmony_ci phy_info->cable_length = e1000_cable_length_80_110; 329662306a36Sopenharmony_ci else if (average <= e1000_igp_cable_length_140) 329762306a36Sopenharmony_ci phy_info->cable_length = e1000_cable_length_110_140; 329862306a36Sopenharmony_ci else 329962306a36Sopenharmony_ci phy_info->cable_length = e1000_cable_length_140; 330062306a36Sopenharmony_ci } 330162306a36Sopenharmony_ci 330262306a36Sopenharmony_ci return E1000_SUCCESS; 330362306a36Sopenharmony_ci} 330462306a36Sopenharmony_ci 330562306a36Sopenharmony_ci/** 330662306a36Sopenharmony_ci * e1000_phy_m88_get_info - get m88 specific registers 330762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 330862306a36Sopenharmony_ci * @phy_info: PHY information structure 330962306a36Sopenharmony_ci * 331062306a36Sopenharmony_ci * Get PHY information from various PHY registers for m88 PHY only. 331162306a36Sopenharmony_ci */ 331262306a36Sopenharmony_cistatic s32 e1000_phy_m88_get_info(struct e1000_hw *hw, 331362306a36Sopenharmony_ci struct e1000_phy_info *phy_info) 331462306a36Sopenharmony_ci{ 331562306a36Sopenharmony_ci s32 ret_val; 331662306a36Sopenharmony_ci u16 phy_data; 331762306a36Sopenharmony_ci e1000_rev_polarity polarity; 331862306a36Sopenharmony_ci 331962306a36Sopenharmony_ci /* The downshift status is checked only once, after link is established, 332062306a36Sopenharmony_ci * and it stored in the hw->speed_downgraded parameter. 332162306a36Sopenharmony_ci */ 332262306a36Sopenharmony_ci phy_info->downshift = (e1000_downshift) hw->speed_downgraded; 332362306a36Sopenharmony_ci 332462306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 332562306a36Sopenharmony_ci if (ret_val) 332662306a36Sopenharmony_ci return ret_val; 332762306a36Sopenharmony_ci 332862306a36Sopenharmony_ci phy_info->extended_10bt_distance = 332962306a36Sopenharmony_ci ((phy_data & M88E1000_PSCR_10BT_EXT_DIST_ENABLE) >> 333062306a36Sopenharmony_ci M88E1000_PSCR_10BT_EXT_DIST_ENABLE_SHIFT) ? 333162306a36Sopenharmony_ci e1000_10bt_ext_dist_enable_lower : 333262306a36Sopenharmony_ci e1000_10bt_ext_dist_enable_normal; 333362306a36Sopenharmony_ci 333462306a36Sopenharmony_ci phy_info->polarity_correction = 333562306a36Sopenharmony_ci ((phy_data & M88E1000_PSCR_POLARITY_REVERSAL) >> 333662306a36Sopenharmony_ci M88E1000_PSCR_POLARITY_REVERSAL_SHIFT) ? 333762306a36Sopenharmony_ci e1000_polarity_reversal_disabled : e1000_polarity_reversal_enabled; 333862306a36Sopenharmony_ci 333962306a36Sopenharmony_ci /* Check polarity status */ 334062306a36Sopenharmony_ci ret_val = e1000_check_polarity(hw, &polarity); 334162306a36Sopenharmony_ci if (ret_val) 334262306a36Sopenharmony_ci return ret_val; 334362306a36Sopenharmony_ci phy_info->cable_polarity = polarity; 334462306a36Sopenharmony_ci 334562306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); 334662306a36Sopenharmony_ci if (ret_val) 334762306a36Sopenharmony_ci return ret_val; 334862306a36Sopenharmony_ci 334962306a36Sopenharmony_ci phy_info->mdix_mode = 335062306a36Sopenharmony_ci (e1000_auto_x_mode) ((phy_data & M88E1000_PSSR_MDIX) >> 335162306a36Sopenharmony_ci M88E1000_PSSR_MDIX_SHIFT); 335262306a36Sopenharmony_ci 335362306a36Sopenharmony_ci if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { 335462306a36Sopenharmony_ci /* Cable Length Estimation and Local/Remote Receiver Information 335562306a36Sopenharmony_ci * are only valid at 1000 Mbps. 335662306a36Sopenharmony_ci */ 335762306a36Sopenharmony_ci phy_info->cable_length = 335862306a36Sopenharmony_ci (e1000_cable_length) ((phy_data & 335962306a36Sopenharmony_ci M88E1000_PSSR_CABLE_LENGTH) >> 336062306a36Sopenharmony_ci M88E1000_PSSR_CABLE_LENGTH_SHIFT); 336162306a36Sopenharmony_ci 336262306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); 336362306a36Sopenharmony_ci if (ret_val) 336462306a36Sopenharmony_ci return ret_val; 336562306a36Sopenharmony_ci 336662306a36Sopenharmony_ci phy_info->local_rx = ((phy_data & SR_1000T_LOCAL_RX_STATUS) >> 336762306a36Sopenharmony_ci SR_1000T_LOCAL_RX_STATUS_SHIFT) ? 336862306a36Sopenharmony_ci e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; 336962306a36Sopenharmony_ci phy_info->remote_rx = ((phy_data & SR_1000T_REMOTE_RX_STATUS) >> 337062306a36Sopenharmony_ci SR_1000T_REMOTE_RX_STATUS_SHIFT) ? 337162306a36Sopenharmony_ci e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; 337262306a36Sopenharmony_ci } 337362306a36Sopenharmony_ci 337462306a36Sopenharmony_ci return E1000_SUCCESS; 337562306a36Sopenharmony_ci} 337662306a36Sopenharmony_ci 337762306a36Sopenharmony_ci/** 337862306a36Sopenharmony_ci * e1000_phy_get_info - request phy info 337962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 338062306a36Sopenharmony_ci * @phy_info: PHY information structure 338162306a36Sopenharmony_ci * 338262306a36Sopenharmony_ci * Get PHY information from various PHY registers 338362306a36Sopenharmony_ci */ 338462306a36Sopenharmony_cis32 e1000_phy_get_info(struct e1000_hw *hw, struct e1000_phy_info *phy_info) 338562306a36Sopenharmony_ci{ 338662306a36Sopenharmony_ci s32 ret_val; 338762306a36Sopenharmony_ci u16 phy_data; 338862306a36Sopenharmony_ci 338962306a36Sopenharmony_ci phy_info->cable_length = e1000_cable_length_undefined; 339062306a36Sopenharmony_ci phy_info->extended_10bt_distance = e1000_10bt_ext_dist_enable_undefined; 339162306a36Sopenharmony_ci phy_info->cable_polarity = e1000_rev_polarity_undefined; 339262306a36Sopenharmony_ci phy_info->downshift = e1000_downshift_undefined; 339362306a36Sopenharmony_ci phy_info->polarity_correction = e1000_polarity_reversal_undefined; 339462306a36Sopenharmony_ci phy_info->mdix_mode = e1000_auto_x_mode_undefined; 339562306a36Sopenharmony_ci phy_info->local_rx = e1000_1000t_rx_status_undefined; 339662306a36Sopenharmony_ci phy_info->remote_rx = e1000_1000t_rx_status_undefined; 339762306a36Sopenharmony_ci 339862306a36Sopenharmony_ci if (hw->media_type != e1000_media_type_copper) { 339962306a36Sopenharmony_ci e_dbg("PHY info is only valid for copper media\n"); 340062306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 340162306a36Sopenharmony_ci } 340262306a36Sopenharmony_ci 340362306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 340462306a36Sopenharmony_ci if (ret_val) 340562306a36Sopenharmony_ci return ret_val; 340662306a36Sopenharmony_ci 340762306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &phy_data); 340862306a36Sopenharmony_ci if (ret_val) 340962306a36Sopenharmony_ci return ret_val; 341062306a36Sopenharmony_ci 341162306a36Sopenharmony_ci if ((phy_data & MII_SR_LINK_STATUS) != MII_SR_LINK_STATUS) { 341262306a36Sopenharmony_ci e_dbg("PHY info is only valid if link is up\n"); 341362306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 341462306a36Sopenharmony_ci } 341562306a36Sopenharmony_ci 341662306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_igp) 341762306a36Sopenharmony_ci return e1000_phy_igp_get_info(hw, phy_info); 341862306a36Sopenharmony_ci else if ((hw->phy_type == e1000_phy_8211) || 341962306a36Sopenharmony_ci (hw->phy_type == e1000_phy_8201)) 342062306a36Sopenharmony_ci return E1000_SUCCESS; 342162306a36Sopenharmony_ci else 342262306a36Sopenharmony_ci return e1000_phy_m88_get_info(hw, phy_info); 342362306a36Sopenharmony_ci} 342462306a36Sopenharmony_ci 342562306a36Sopenharmony_cis32 e1000_validate_mdi_setting(struct e1000_hw *hw) 342662306a36Sopenharmony_ci{ 342762306a36Sopenharmony_ci if (!hw->autoneg && (hw->mdix == 0 || hw->mdix == 3)) { 342862306a36Sopenharmony_ci e_dbg("Invalid MDI setting detected\n"); 342962306a36Sopenharmony_ci hw->mdix = 1; 343062306a36Sopenharmony_ci return -E1000_ERR_CONFIG; 343162306a36Sopenharmony_ci } 343262306a36Sopenharmony_ci return E1000_SUCCESS; 343362306a36Sopenharmony_ci} 343462306a36Sopenharmony_ci 343562306a36Sopenharmony_ci/** 343662306a36Sopenharmony_ci * e1000_init_eeprom_params - initialize sw eeprom vars 343762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 343862306a36Sopenharmony_ci * 343962306a36Sopenharmony_ci * Sets up eeprom variables in the hw struct. Must be called after mac_type 344062306a36Sopenharmony_ci * is configured. 344162306a36Sopenharmony_ci */ 344262306a36Sopenharmony_cis32 e1000_init_eeprom_params(struct e1000_hw *hw) 344362306a36Sopenharmony_ci{ 344462306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 344562306a36Sopenharmony_ci u32 eecd = er32(EECD); 344662306a36Sopenharmony_ci s32 ret_val = E1000_SUCCESS; 344762306a36Sopenharmony_ci u16 eeprom_size; 344862306a36Sopenharmony_ci 344962306a36Sopenharmony_ci switch (hw->mac_type) { 345062306a36Sopenharmony_ci case e1000_82542_rev2_0: 345162306a36Sopenharmony_ci case e1000_82542_rev2_1: 345262306a36Sopenharmony_ci case e1000_82543: 345362306a36Sopenharmony_ci case e1000_82544: 345462306a36Sopenharmony_ci eeprom->type = e1000_eeprom_microwire; 345562306a36Sopenharmony_ci eeprom->word_size = 64; 345662306a36Sopenharmony_ci eeprom->opcode_bits = 3; 345762306a36Sopenharmony_ci eeprom->address_bits = 6; 345862306a36Sopenharmony_ci eeprom->delay_usec = 50; 345962306a36Sopenharmony_ci break; 346062306a36Sopenharmony_ci case e1000_82540: 346162306a36Sopenharmony_ci case e1000_82545: 346262306a36Sopenharmony_ci case e1000_82545_rev_3: 346362306a36Sopenharmony_ci case e1000_82546: 346462306a36Sopenharmony_ci case e1000_82546_rev_3: 346562306a36Sopenharmony_ci eeprom->type = e1000_eeprom_microwire; 346662306a36Sopenharmony_ci eeprom->opcode_bits = 3; 346762306a36Sopenharmony_ci eeprom->delay_usec = 50; 346862306a36Sopenharmony_ci if (eecd & E1000_EECD_SIZE) { 346962306a36Sopenharmony_ci eeprom->word_size = 256; 347062306a36Sopenharmony_ci eeprom->address_bits = 8; 347162306a36Sopenharmony_ci } else { 347262306a36Sopenharmony_ci eeprom->word_size = 64; 347362306a36Sopenharmony_ci eeprom->address_bits = 6; 347462306a36Sopenharmony_ci } 347562306a36Sopenharmony_ci break; 347662306a36Sopenharmony_ci case e1000_82541: 347762306a36Sopenharmony_ci case e1000_82541_rev_2: 347862306a36Sopenharmony_ci case e1000_82547: 347962306a36Sopenharmony_ci case e1000_82547_rev_2: 348062306a36Sopenharmony_ci if (eecd & E1000_EECD_TYPE) { 348162306a36Sopenharmony_ci eeprom->type = e1000_eeprom_spi; 348262306a36Sopenharmony_ci eeprom->opcode_bits = 8; 348362306a36Sopenharmony_ci eeprom->delay_usec = 1; 348462306a36Sopenharmony_ci if (eecd & E1000_EECD_ADDR_BITS) { 348562306a36Sopenharmony_ci eeprom->page_size = 32; 348662306a36Sopenharmony_ci eeprom->address_bits = 16; 348762306a36Sopenharmony_ci } else { 348862306a36Sopenharmony_ci eeprom->page_size = 8; 348962306a36Sopenharmony_ci eeprom->address_bits = 8; 349062306a36Sopenharmony_ci } 349162306a36Sopenharmony_ci } else { 349262306a36Sopenharmony_ci eeprom->type = e1000_eeprom_microwire; 349362306a36Sopenharmony_ci eeprom->opcode_bits = 3; 349462306a36Sopenharmony_ci eeprom->delay_usec = 50; 349562306a36Sopenharmony_ci if (eecd & E1000_EECD_ADDR_BITS) { 349662306a36Sopenharmony_ci eeprom->word_size = 256; 349762306a36Sopenharmony_ci eeprom->address_bits = 8; 349862306a36Sopenharmony_ci } else { 349962306a36Sopenharmony_ci eeprom->word_size = 64; 350062306a36Sopenharmony_ci eeprom->address_bits = 6; 350162306a36Sopenharmony_ci } 350262306a36Sopenharmony_ci } 350362306a36Sopenharmony_ci break; 350462306a36Sopenharmony_ci default: 350562306a36Sopenharmony_ci break; 350662306a36Sopenharmony_ci } 350762306a36Sopenharmony_ci 350862306a36Sopenharmony_ci if (eeprom->type == e1000_eeprom_spi) { 350962306a36Sopenharmony_ci /* eeprom_size will be an enum [0..8] that maps to eeprom sizes 351062306a36Sopenharmony_ci * 128B to 32KB (incremented by powers of 2). 351162306a36Sopenharmony_ci */ 351262306a36Sopenharmony_ci /* Set to default value for initial eeprom read. */ 351362306a36Sopenharmony_ci eeprom->word_size = 64; 351462306a36Sopenharmony_ci ret_val = e1000_read_eeprom(hw, EEPROM_CFG, 1, &eeprom_size); 351562306a36Sopenharmony_ci if (ret_val) 351662306a36Sopenharmony_ci return ret_val; 351762306a36Sopenharmony_ci eeprom_size = 351862306a36Sopenharmony_ci (eeprom_size & EEPROM_SIZE_MASK) >> EEPROM_SIZE_SHIFT; 351962306a36Sopenharmony_ci /* 256B eeprom size was not supported in earlier hardware, so we 352062306a36Sopenharmony_ci * bump eeprom_size up one to ensure that "1" (which maps to 352162306a36Sopenharmony_ci * 256B) is never the result used in the shifting logic below. 352262306a36Sopenharmony_ci */ 352362306a36Sopenharmony_ci if (eeprom_size) 352462306a36Sopenharmony_ci eeprom_size++; 352562306a36Sopenharmony_ci 352662306a36Sopenharmony_ci eeprom->word_size = 1 << (eeprom_size + EEPROM_WORD_SIZE_SHIFT); 352762306a36Sopenharmony_ci } 352862306a36Sopenharmony_ci return ret_val; 352962306a36Sopenharmony_ci} 353062306a36Sopenharmony_ci 353162306a36Sopenharmony_ci/** 353262306a36Sopenharmony_ci * e1000_raise_ee_clk - Raises the EEPROM's clock input. 353362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 353462306a36Sopenharmony_ci * @eecd: EECD's current value 353562306a36Sopenharmony_ci */ 353662306a36Sopenharmony_cistatic void e1000_raise_ee_clk(struct e1000_hw *hw, u32 *eecd) 353762306a36Sopenharmony_ci{ 353862306a36Sopenharmony_ci /* Raise the clock input to the EEPROM (by setting the SK bit), and then 353962306a36Sopenharmony_ci * wait <delay> microseconds. 354062306a36Sopenharmony_ci */ 354162306a36Sopenharmony_ci *eecd = *eecd | E1000_EECD_SK; 354262306a36Sopenharmony_ci ew32(EECD, *eecd); 354362306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 354462306a36Sopenharmony_ci udelay(hw->eeprom.delay_usec); 354562306a36Sopenharmony_ci} 354662306a36Sopenharmony_ci 354762306a36Sopenharmony_ci/** 354862306a36Sopenharmony_ci * e1000_lower_ee_clk - Lowers the EEPROM's clock input. 354962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 355062306a36Sopenharmony_ci * @eecd: EECD's current value 355162306a36Sopenharmony_ci */ 355262306a36Sopenharmony_cistatic void e1000_lower_ee_clk(struct e1000_hw *hw, u32 *eecd) 355362306a36Sopenharmony_ci{ 355462306a36Sopenharmony_ci /* Lower the clock input to the EEPROM (by clearing the SK bit), and 355562306a36Sopenharmony_ci * then wait 50 microseconds. 355662306a36Sopenharmony_ci */ 355762306a36Sopenharmony_ci *eecd = *eecd & ~E1000_EECD_SK; 355862306a36Sopenharmony_ci ew32(EECD, *eecd); 355962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 356062306a36Sopenharmony_ci udelay(hw->eeprom.delay_usec); 356162306a36Sopenharmony_ci} 356262306a36Sopenharmony_ci 356362306a36Sopenharmony_ci/** 356462306a36Sopenharmony_ci * e1000_shift_out_ee_bits - Shift data bits out to the EEPROM. 356562306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 356662306a36Sopenharmony_ci * @data: data to send to the EEPROM 356762306a36Sopenharmony_ci * @count: number of bits to shift out 356862306a36Sopenharmony_ci */ 356962306a36Sopenharmony_cistatic void e1000_shift_out_ee_bits(struct e1000_hw *hw, u16 data, u16 count) 357062306a36Sopenharmony_ci{ 357162306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 357262306a36Sopenharmony_ci u32 eecd; 357362306a36Sopenharmony_ci u32 mask; 357462306a36Sopenharmony_ci 357562306a36Sopenharmony_ci /* We need to shift "count" bits out to the EEPROM. So, value in the 357662306a36Sopenharmony_ci * "data" parameter will be shifted out to the EEPROM one bit at a time. 357762306a36Sopenharmony_ci * In order to do this, "data" must be broken down into bits. 357862306a36Sopenharmony_ci */ 357962306a36Sopenharmony_ci mask = 0x01 << (count - 1); 358062306a36Sopenharmony_ci eecd = er32(EECD); 358162306a36Sopenharmony_ci if (eeprom->type == e1000_eeprom_microwire) 358262306a36Sopenharmony_ci eecd &= ~E1000_EECD_DO; 358362306a36Sopenharmony_ci else if (eeprom->type == e1000_eeprom_spi) 358462306a36Sopenharmony_ci eecd |= E1000_EECD_DO; 358562306a36Sopenharmony_ci 358662306a36Sopenharmony_ci do { 358762306a36Sopenharmony_ci /* A "1" is shifted out to the EEPROM by setting bit "DI" to a 358862306a36Sopenharmony_ci * "1", and then raising and then lowering the clock (the SK bit 358962306a36Sopenharmony_ci * controls the clock input to the EEPROM). A "0" is shifted 359062306a36Sopenharmony_ci * out to the EEPROM by setting "DI" to "0" and then raising and 359162306a36Sopenharmony_ci * then lowering the clock. 359262306a36Sopenharmony_ci */ 359362306a36Sopenharmony_ci eecd &= ~E1000_EECD_DI; 359462306a36Sopenharmony_ci 359562306a36Sopenharmony_ci if (data & mask) 359662306a36Sopenharmony_ci eecd |= E1000_EECD_DI; 359762306a36Sopenharmony_ci 359862306a36Sopenharmony_ci ew32(EECD, eecd); 359962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 360062306a36Sopenharmony_ci 360162306a36Sopenharmony_ci udelay(eeprom->delay_usec); 360262306a36Sopenharmony_ci 360362306a36Sopenharmony_ci e1000_raise_ee_clk(hw, &eecd); 360462306a36Sopenharmony_ci e1000_lower_ee_clk(hw, &eecd); 360562306a36Sopenharmony_ci 360662306a36Sopenharmony_ci mask = mask >> 1; 360762306a36Sopenharmony_ci 360862306a36Sopenharmony_ci } while (mask); 360962306a36Sopenharmony_ci 361062306a36Sopenharmony_ci /* We leave the "DI" bit set to "0" when we leave this routine. */ 361162306a36Sopenharmony_ci eecd &= ~E1000_EECD_DI; 361262306a36Sopenharmony_ci ew32(EECD, eecd); 361362306a36Sopenharmony_ci} 361462306a36Sopenharmony_ci 361562306a36Sopenharmony_ci/** 361662306a36Sopenharmony_ci * e1000_shift_in_ee_bits - Shift data bits in from the EEPROM 361762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 361862306a36Sopenharmony_ci * @count: number of bits to shift in 361962306a36Sopenharmony_ci */ 362062306a36Sopenharmony_cistatic u16 e1000_shift_in_ee_bits(struct e1000_hw *hw, u16 count) 362162306a36Sopenharmony_ci{ 362262306a36Sopenharmony_ci u32 eecd; 362362306a36Sopenharmony_ci u32 i; 362462306a36Sopenharmony_ci u16 data; 362562306a36Sopenharmony_ci 362662306a36Sopenharmony_ci /* In order to read a register from the EEPROM, we need to shift 'count' 362762306a36Sopenharmony_ci * bits in from the EEPROM. Bits are "shifted in" by raising the clock 362862306a36Sopenharmony_ci * input to the EEPROM (setting the SK bit), and then reading the value 362962306a36Sopenharmony_ci * of the "DO" bit. During this "shifting in" process the "DI" bit 363062306a36Sopenharmony_ci * should always be clear. 363162306a36Sopenharmony_ci */ 363262306a36Sopenharmony_ci 363362306a36Sopenharmony_ci eecd = er32(EECD); 363462306a36Sopenharmony_ci 363562306a36Sopenharmony_ci eecd &= ~(E1000_EECD_DO | E1000_EECD_DI); 363662306a36Sopenharmony_ci data = 0; 363762306a36Sopenharmony_ci 363862306a36Sopenharmony_ci for (i = 0; i < count; i++) { 363962306a36Sopenharmony_ci data = data << 1; 364062306a36Sopenharmony_ci e1000_raise_ee_clk(hw, &eecd); 364162306a36Sopenharmony_ci 364262306a36Sopenharmony_ci eecd = er32(EECD); 364362306a36Sopenharmony_ci 364462306a36Sopenharmony_ci eecd &= ~(E1000_EECD_DI); 364562306a36Sopenharmony_ci if (eecd & E1000_EECD_DO) 364662306a36Sopenharmony_ci data |= 1; 364762306a36Sopenharmony_ci 364862306a36Sopenharmony_ci e1000_lower_ee_clk(hw, &eecd); 364962306a36Sopenharmony_ci } 365062306a36Sopenharmony_ci 365162306a36Sopenharmony_ci return data; 365262306a36Sopenharmony_ci} 365362306a36Sopenharmony_ci 365462306a36Sopenharmony_ci/** 365562306a36Sopenharmony_ci * e1000_acquire_eeprom - Prepares EEPROM for access 365662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 365762306a36Sopenharmony_ci * 365862306a36Sopenharmony_ci * Lowers EEPROM clock. Clears input pin. Sets the chip select pin. This 365962306a36Sopenharmony_ci * function should be called before issuing a command to the EEPROM. 366062306a36Sopenharmony_ci */ 366162306a36Sopenharmony_cistatic s32 e1000_acquire_eeprom(struct e1000_hw *hw) 366262306a36Sopenharmony_ci{ 366362306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 366462306a36Sopenharmony_ci u32 eecd, i = 0; 366562306a36Sopenharmony_ci 366662306a36Sopenharmony_ci eecd = er32(EECD); 366762306a36Sopenharmony_ci 366862306a36Sopenharmony_ci /* Request EEPROM Access */ 366962306a36Sopenharmony_ci if (hw->mac_type > e1000_82544) { 367062306a36Sopenharmony_ci eecd |= E1000_EECD_REQ; 367162306a36Sopenharmony_ci ew32(EECD, eecd); 367262306a36Sopenharmony_ci eecd = er32(EECD); 367362306a36Sopenharmony_ci while ((!(eecd & E1000_EECD_GNT)) && 367462306a36Sopenharmony_ci (i < E1000_EEPROM_GRANT_ATTEMPTS)) { 367562306a36Sopenharmony_ci i++; 367662306a36Sopenharmony_ci udelay(5); 367762306a36Sopenharmony_ci eecd = er32(EECD); 367862306a36Sopenharmony_ci } 367962306a36Sopenharmony_ci if (!(eecd & E1000_EECD_GNT)) { 368062306a36Sopenharmony_ci eecd &= ~E1000_EECD_REQ; 368162306a36Sopenharmony_ci ew32(EECD, eecd); 368262306a36Sopenharmony_ci e_dbg("Could not acquire EEPROM grant\n"); 368362306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 368462306a36Sopenharmony_ci } 368562306a36Sopenharmony_ci } 368662306a36Sopenharmony_ci 368762306a36Sopenharmony_ci /* Setup EEPROM for Read/Write */ 368862306a36Sopenharmony_ci 368962306a36Sopenharmony_ci if (eeprom->type == e1000_eeprom_microwire) { 369062306a36Sopenharmony_ci /* Clear SK and DI */ 369162306a36Sopenharmony_ci eecd &= ~(E1000_EECD_DI | E1000_EECD_SK); 369262306a36Sopenharmony_ci ew32(EECD, eecd); 369362306a36Sopenharmony_ci 369462306a36Sopenharmony_ci /* Set CS */ 369562306a36Sopenharmony_ci eecd |= E1000_EECD_CS; 369662306a36Sopenharmony_ci ew32(EECD, eecd); 369762306a36Sopenharmony_ci } else if (eeprom->type == e1000_eeprom_spi) { 369862306a36Sopenharmony_ci /* Clear SK and CS */ 369962306a36Sopenharmony_ci eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); 370062306a36Sopenharmony_ci ew32(EECD, eecd); 370162306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 370262306a36Sopenharmony_ci udelay(1); 370362306a36Sopenharmony_ci } 370462306a36Sopenharmony_ci 370562306a36Sopenharmony_ci return E1000_SUCCESS; 370662306a36Sopenharmony_ci} 370762306a36Sopenharmony_ci 370862306a36Sopenharmony_ci/** 370962306a36Sopenharmony_ci * e1000_standby_eeprom - Returns EEPROM to a "standby" state 371062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 371162306a36Sopenharmony_ci */ 371262306a36Sopenharmony_cistatic void e1000_standby_eeprom(struct e1000_hw *hw) 371362306a36Sopenharmony_ci{ 371462306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 371562306a36Sopenharmony_ci u32 eecd; 371662306a36Sopenharmony_ci 371762306a36Sopenharmony_ci eecd = er32(EECD); 371862306a36Sopenharmony_ci 371962306a36Sopenharmony_ci if (eeprom->type == e1000_eeprom_microwire) { 372062306a36Sopenharmony_ci eecd &= ~(E1000_EECD_CS | E1000_EECD_SK); 372162306a36Sopenharmony_ci ew32(EECD, eecd); 372262306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 372362306a36Sopenharmony_ci udelay(eeprom->delay_usec); 372462306a36Sopenharmony_ci 372562306a36Sopenharmony_ci /* Clock high */ 372662306a36Sopenharmony_ci eecd |= E1000_EECD_SK; 372762306a36Sopenharmony_ci ew32(EECD, eecd); 372862306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 372962306a36Sopenharmony_ci udelay(eeprom->delay_usec); 373062306a36Sopenharmony_ci 373162306a36Sopenharmony_ci /* Select EEPROM */ 373262306a36Sopenharmony_ci eecd |= E1000_EECD_CS; 373362306a36Sopenharmony_ci ew32(EECD, eecd); 373462306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 373562306a36Sopenharmony_ci udelay(eeprom->delay_usec); 373662306a36Sopenharmony_ci 373762306a36Sopenharmony_ci /* Clock low */ 373862306a36Sopenharmony_ci eecd &= ~E1000_EECD_SK; 373962306a36Sopenharmony_ci ew32(EECD, eecd); 374062306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 374162306a36Sopenharmony_ci udelay(eeprom->delay_usec); 374262306a36Sopenharmony_ci } else if (eeprom->type == e1000_eeprom_spi) { 374362306a36Sopenharmony_ci /* Toggle CS to flush commands */ 374462306a36Sopenharmony_ci eecd |= E1000_EECD_CS; 374562306a36Sopenharmony_ci ew32(EECD, eecd); 374662306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 374762306a36Sopenharmony_ci udelay(eeprom->delay_usec); 374862306a36Sopenharmony_ci eecd &= ~E1000_EECD_CS; 374962306a36Sopenharmony_ci ew32(EECD, eecd); 375062306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 375162306a36Sopenharmony_ci udelay(eeprom->delay_usec); 375262306a36Sopenharmony_ci } 375362306a36Sopenharmony_ci} 375462306a36Sopenharmony_ci 375562306a36Sopenharmony_ci/** 375662306a36Sopenharmony_ci * e1000_release_eeprom - drop chip select 375762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 375862306a36Sopenharmony_ci * 375962306a36Sopenharmony_ci * Terminates a command by inverting the EEPROM's chip select pin 376062306a36Sopenharmony_ci */ 376162306a36Sopenharmony_cistatic void e1000_release_eeprom(struct e1000_hw *hw) 376262306a36Sopenharmony_ci{ 376362306a36Sopenharmony_ci u32 eecd; 376462306a36Sopenharmony_ci 376562306a36Sopenharmony_ci eecd = er32(EECD); 376662306a36Sopenharmony_ci 376762306a36Sopenharmony_ci if (hw->eeprom.type == e1000_eeprom_spi) { 376862306a36Sopenharmony_ci eecd |= E1000_EECD_CS; /* Pull CS high */ 376962306a36Sopenharmony_ci eecd &= ~E1000_EECD_SK; /* Lower SCK */ 377062306a36Sopenharmony_ci 377162306a36Sopenharmony_ci ew32(EECD, eecd); 377262306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 377362306a36Sopenharmony_ci 377462306a36Sopenharmony_ci udelay(hw->eeprom.delay_usec); 377562306a36Sopenharmony_ci } else if (hw->eeprom.type == e1000_eeprom_microwire) { 377662306a36Sopenharmony_ci /* cleanup eeprom */ 377762306a36Sopenharmony_ci 377862306a36Sopenharmony_ci /* CS on Microwire is active-high */ 377962306a36Sopenharmony_ci eecd &= ~(E1000_EECD_CS | E1000_EECD_DI); 378062306a36Sopenharmony_ci 378162306a36Sopenharmony_ci ew32(EECD, eecd); 378262306a36Sopenharmony_ci 378362306a36Sopenharmony_ci /* Rising edge of clock */ 378462306a36Sopenharmony_ci eecd |= E1000_EECD_SK; 378562306a36Sopenharmony_ci ew32(EECD, eecd); 378662306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 378762306a36Sopenharmony_ci udelay(hw->eeprom.delay_usec); 378862306a36Sopenharmony_ci 378962306a36Sopenharmony_ci /* Falling edge of clock */ 379062306a36Sopenharmony_ci eecd &= ~E1000_EECD_SK; 379162306a36Sopenharmony_ci ew32(EECD, eecd); 379262306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 379362306a36Sopenharmony_ci udelay(hw->eeprom.delay_usec); 379462306a36Sopenharmony_ci } 379562306a36Sopenharmony_ci 379662306a36Sopenharmony_ci /* Stop requesting EEPROM access */ 379762306a36Sopenharmony_ci if (hw->mac_type > e1000_82544) { 379862306a36Sopenharmony_ci eecd &= ~E1000_EECD_REQ; 379962306a36Sopenharmony_ci ew32(EECD, eecd); 380062306a36Sopenharmony_ci } 380162306a36Sopenharmony_ci} 380262306a36Sopenharmony_ci 380362306a36Sopenharmony_ci/** 380462306a36Sopenharmony_ci * e1000_spi_eeprom_ready - Reads a 16 bit word from the EEPROM. 380562306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 380662306a36Sopenharmony_ci */ 380762306a36Sopenharmony_cistatic s32 e1000_spi_eeprom_ready(struct e1000_hw *hw) 380862306a36Sopenharmony_ci{ 380962306a36Sopenharmony_ci u16 retry_count = 0; 381062306a36Sopenharmony_ci u8 spi_stat_reg; 381162306a36Sopenharmony_ci 381262306a36Sopenharmony_ci /* Read "Status Register" repeatedly until the LSB is cleared. The 381362306a36Sopenharmony_ci * EEPROM will signal that the command has been completed by clearing 381462306a36Sopenharmony_ci * bit 0 of the internal status register. If it's not cleared within 381562306a36Sopenharmony_ci * 5 milliseconds, then error out. 381662306a36Sopenharmony_ci */ 381762306a36Sopenharmony_ci retry_count = 0; 381862306a36Sopenharmony_ci do { 381962306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, EEPROM_RDSR_OPCODE_SPI, 382062306a36Sopenharmony_ci hw->eeprom.opcode_bits); 382162306a36Sopenharmony_ci spi_stat_reg = (u8)e1000_shift_in_ee_bits(hw, 8); 382262306a36Sopenharmony_ci if (!(spi_stat_reg & EEPROM_STATUS_RDY_SPI)) 382362306a36Sopenharmony_ci break; 382462306a36Sopenharmony_ci 382562306a36Sopenharmony_ci udelay(5); 382662306a36Sopenharmony_ci retry_count += 5; 382762306a36Sopenharmony_ci 382862306a36Sopenharmony_ci e1000_standby_eeprom(hw); 382962306a36Sopenharmony_ci } while (retry_count < EEPROM_MAX_RETRY_SPI); 383062306a36Sopenharmony_ci 383162306a36Sopenharmony_ci /* ATMEL SPI write time could vary from 0-20mSec on 3.3V devices (and 383262306a36Sopenharmony_ci * only 0-5mSec on 5V devices) 383362306a36Sopenharmony_ci */ 383462306a36Sopenharmony_ci if (retry_count >= EEPROM_MAX_RETRY_SPI) { 383562306a36Sopenharmony_ci e_dbg("SPI EEPROM Status error\n"); 383662306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 383762306a36Sopenharmony_ci } 383862306a36Sopenharmony_ci 383962306a36Sopenharmony_ci return E1000_SUCCESS; 384062306a36Sopenharmony_ci} 384162306a36Sopenharmony_ci 384262306a36Sopenharmony_ci/** 384362306a36Sopenharmony_ci * e1000_read_eeprom - Reads a 16 bit word from the EEPROM. 384462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 384562306a36Sopenharmony_ci * @offset: offset of word in the EEPROM to read 384662306a36Sopenharmony_ci * @data: word read from the EEPROM 384762306a36Sopenharmony_ci * @words: number of words to read 384862306a36Sopenharmony_ci */ 384962306a36Sopenharmony_cis32 e1000_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) 385062306a36Sopenharmony_ci{ 385162306a36Sopenharmony_ci s32 ret; 385262306a36Sopenharmony_ci 385362306a36Sopenharmony_ci mutex_lock(&e1000_eeprom_lock); 385462306a36Sopenharmony_ci ret = e1000_do_read_eeprom(hw, offset, words, data); 385562306a36Sopenharmony_ci mutex_unlock(&e1000_eeprom_lock); 385662306a36Sopenharmony_ci return ret; 385762306a36Sopenharmony_ci} 385862306a36Sopenharmony_ci 385962306a36Sopenharmony_cistatic s32 e1000_do_read_eeprom(struct e1000_hw *hw, u16 offset, u16 words, 386062306a36Sopenharmony_ci u16 *data) 386162306a36Sopenharmony_ci{ 386262306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 386362306a36Sopenharmony_ci u32 i = 0; 386462306a36Sopenharmony_ci 386562306a36Sopenharmony_ci if (hw->mac_type == e1000_ce4100) { 386662306a36Sopenharmony_ci GBE_CONFIG_FLASH_READ(GBE_CONFIG_BASE_VIRT, offset, words, 386762306a36Sopenharmony_ci data); 386862306a36Sopenharmony_ci return E1000_SUCCESS; 386962306a36Sopenharmony_ci } 387062306a36Sopenharmony_ci 387162306a36Sopenharmony_ci /* A check for invalid values: offset too large, too many words, and 387262306a36Sopenharmony_ci * not enough words. 387362306a36Sopenharmony_ci */ 387462306a36Sopenharmony_ci if ((offset >= eeprom->word_size) || 387562306a36Sopenharmony_ci (words > eeprom->word_size - offset) || 387662306a36Sopenharmony_ci (words == 0)) { 387762306a36Sopenharmony_ci e_dbg("\"words\" parameter out of bounds. Words = %d," 387862306a36Sopenharmony_ci "size = %d\n", offset, eeprom->word_size); 387962306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 388062306a36Sopenharmony_ci } 388162306a36Sopenharmony_ci 388262306a36Sopenharmony_ci /* EEPROM's that don't use EERD to read require us to bit-bang the SPI 388362306a36Sopenharmony_ci * directly. In this case, we need to acquire the EEPROM so that 388462306a36Sopenharmony_ci * FW or other port software does not interrupt. 388562306a36Sopenharmony_ci */ 388662306a36Sopenharmony_ci /* Prepare the EEPROM for bit-bang reading */ 388762306a36Sopenharmony_ci if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) 388862306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 388962306a36Sopenharmony_ci 389062306a36Sopenharmony_ci /* Set up the SPI or Microwire EEPROM for bit-bang reading. We have 389162306a36Sopenharmony_ci * acquired the EEPROM at this point, so any returns should release it 389262306a36Sopenharmony_ci */ 389362306a36Sopenharmony_ci if (eeprom->type == e1000_eeprom_spi) { 389462306a36Sopenharmony_ci u16 word_in; 389562306a36Sopenharmony_ci u8 read_opcode = EEPROM_READ_OPCODE_SPI; 389662306a36Sopenharmony_ci 389762306a36Sopenharmony_ci if (e1000_spi_eeprom_ready(hw)) { 389862306a36Sopenharmony_ci e1000_release_eeprom(hw); 389962306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 390062306a36Sopenharmony_ci } 390162306a36Sopenharmony_ci 390262306a36Sopenharmony_ci e1000_standby_eeprom(hw); 390362306a36Sopenharmony_ci 390462306a36Sopenharmony_ci /* Some SPI eeproms use the 8th address bit embedded in the 390562306a36Sopenharmony_ci * opcode 390662306a36Sopenharmony_ci */ 390762306a36Sopenharmony_ci if ((eeprom->address_bits == 8) && (offset >= 128)) 390862306a36Sopenharmony_ci read_opcode |= EEPROM_A8_OPCODE_SPI; 390962306a36Sopenharmony_ci 391062306a36Sopenharmony_ci /* Send the READ command (opcode + addr) */ 391162306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, read_opcode, eeprom->opcode_bits); 391262306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, (u16)(offset * 2), 391362306a36Sopenharmony_ci eeprom->address_bits); 391462306a36Sopenharmony_ci 391562306a36Sopenharmony_ci /* Read the data. The address of the eeprom internally 391662306a36Sopenharmony_ci * increments with each byte (spi) being read, saving on the 391762306a36Sopenharmony_ci * overhead of eeprom setup and tear-down. The address counter 391862306a36Sopenharmony_ci * will roll over if reading beyond the size of the eeprom, thus 391962306a36Sopenharmony_ci * allowing the entire memory to be read starting from any 392062306a36Sopenharmony_ci * offset. 392162306a36Sopenharmony_ci */ 392262306a36Sopenharmony_ci for (i = 0; i < words; i++) { 392362306a36Sopenharmony_ci word_in = e1000_shift_in_ee_bits(hw, 16); 392462306a36Sopenharmony_ci data[i] = (word_in >> 8) | (word_in << 8); 392562306a36Sopenharmony_ci } 392662306a36Sopenharmony_ci } else if (eeprom->type == e1000_eeprom_microwire) { 392762306a36Sopenharmony_ci for (i = 0; i < words; i++) { 392862306a36Sopenharmony_ci /* Send the READ command (opcode + addr) */ 392962306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, 393062306a36Sopenharmony_ci EEPROM_READ_OPCODE_MICROWIRE, 393162306a36Sopenharmony_ci eeprom->opcode_bits); 393262306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, (u16)(offset + i), 393362306a36Sopenharmony_ci eeprom->address_bits); 393462306a36Sopenharmony_ci 393562306a36Sopenharmony_ci /* Read the data. For microwire, each word requires the 393662306a36Sopenharmony_ci * overhead of eeprom setup and tear-down. 393762306a36Sopenharmony_ci */ 393862306a36Sopenharmony_ci data[i] = e1000_shift_in_ee_bits(hw, 16); 393962306a36Sopenharmony_ci e1000_standby_eeprom(hw); 394062306a36Sopenharmony_ci cond_resched(); 394162306a36Sopenharmony_ci } 394262306a36Sopenharmony_ci } 394362306a36Sopenharmony_ci 394462306a36Sopenharmony_ci /* End this read operation */ 394562306a36Sopenharmony_ci e1000_release_eeprom(hw); 394662306a36Sopenharmony_ci 394762306a36Sopenharmony_ci return E1000_SUCCESS; 394862306a36Sopenharmony_ci} 394962306a36Sopenharmony_ci 395062306a36Sopenharmony_ci/** 395162306a36Sopenharmony_ci * e1000_validate_eeprom_checksum - Verifies that the EEPROM has a valid checksum 395262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 395362306a36Sopenharmony_ci * 395462306a36Sopenharmony_ci * Reads the first 64 16 bit words of the EEPROM and sums the values read. 395562306a36Sopenharmony_ci * If the sum of the 64 16 bit words is 0xBABA, the EEPROM's checksum is 395662306a36Sopenharmony_ci * valid. 395762306a36Sopenharmony_ci */ 395862306a36Sopenharmony_cis32 e1000_validate_eeprom_checksum(struct e1000_hw *hw) 395962306a36Sopenharmony_ci{ 396062306a36Sopenharmony_ci u16 checksum = 0; 396162306a36Sopenharmony_ci u16 i, eeprom_data; 396262306a36Sopenharmony_ci 396362306a36Sopenharmony_ci for (i = 0; i < (EEPROM_CHECKSUM_REG + 1); i++) { 396462306a36Sopenharmony_ci if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { 396562306a36Sopenharmony_ci e_dbg("EEPROM Read Error\n"); 396662306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 396762306a36Sopenharmony_ci } 396862306a36Sopenharmony_ci checksum += eeprom_data; 396962306a36Sopenharmony_ci } 397062306a36Sopenharmony_ci 397162306a36Sopenharmony_ci#ifdef CONFIG_PARISC 397262306a36Sopenharmony_ci /* This is a signature and not a checksum on HP c8000 */ 397362306a36Sopenharmony_ci if ((hw->subsystem_vendor_id == 0x103C) && (eeprom_data == 0x16d6)) 397462306a36Sopenharmony_ci return E1000_SUCCESS; 397562306a36Sopenharmony_ci 397662306a36Sopenharmony_ci#endif 397762306a36Sopenharmony_ci if (checksum == (u16)EEPROM_SUM) 397862306a36Sopenharmony_ci return E1000_SUCCESS; 397962306a36Sopenharmony_ci else { 398062306a36Sopenharmony_ci e_dbg("EEPROM Checksum Invalid\n"); 398162306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 398262306a36Sopenharmony_ci } 398362306a36Sopenharmony_ci} 398462306a36Sopenharmony_ci 398562306a36Sopenharmony_ci/** 398662306a36Sopenharmony_ci * e1000_update_eeprom_checksum - Calculates/writes the EEPROM checksum 398762306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 398862306a36Sopenharmony_ci * 398962306a36Sopenharmony_ci * Sums the first 63 16 bit words of the EEPROM. Subtracts the sum from 0xBABA. 399062306a36Sopenharmony_ci * Writes the difference to word offset 63 of the EEPROM. 399162306a36Sopenharmony_ci */ 399262306a36Sopenharmony_cis32 e1000_update_eeprom_checksum(struct e1000_hw *hw) 399362306a36Sopenharmony_ci{ 399462306a36Sopenharmony_ci u16 checksum = 0; 399562306a36Sopenharmony_ci u16 i, eeprom_data; 399662306a36Sopenharmony_ci 399762306a36Sopenharmony_ci for (i = 0; i < EEPROM_CHECKSUM_REG; i++) { 399862306a36Sopenharmony_ci if (e1000_read_eeprom(hw, i, 1, &eeprom_data) < 0) { 399962306a36Sopenharmony_ci e_dbg("EEPROM Read Error\n"); 400062306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 400162306a36Sopenharmony_ci } 400262306a36Sopenharmony_ci checksum += eeprom_data; 400362306a36Sopenharmony_ci } 400462306a36Sopenharmony_ci checksum = (u16)EEPROM_SUM - checksum; 400562306a36Sopenharmony_ci if (e1000_write_eeprom(hw, EEPROM_CHECKSUM_REG, 1, &checksum) < 0) { 400662306a36Sopenharmony_ci e_dbg("EEPROM Write Error\n"); 400762306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 400862306a36Sopenharmony_ci } 400962306a36Sopenharmony_ci return E1000_SUCCESS; 401062306a36Sopenharmony_ci} 401162306a36Sopenharmony_ci 401262306a36Sopenharmony_ci/** 401362306a36Sopenharmony_ci * e1000_write_eeprom - write words to the different EEPROM types. 401462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 401562306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to 401662306a36Sopenharmony_ci * @words: number of words to write 401762306a36Sopenharmony_ci * @data: 16 bit word to be written to the EEPROM 401862306a36Sopenharmony_ci * 401962306a36Sopenharmony_ci * If e1000_update_eeprom_checksum is not called after this function, the 402062306a36Sopenharmony_ci * EEPROM will most likely contain an invalid checksum. 402162306a36Sopenharmony_ci */ 402262306a36Sopenharmony_cis32 e1000_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, u16 *data) 402362306a36Sopenharmony_ci{ 402462306a36Sopenharmony_ci s32 ret; 402562306a36Sopenharmony_ci 402662306a36Sopenharmony_ci mutex_lock(&e1000_eeprom_lock); 402762306a36Sopenharmony_ci ret = e1000_do_write_eeprom(hw, offset, words, data); 402862306a36Sopenharmony_ci mutex_unlock(&e1000_eeprom_lock); 402962306a36Sopenharmony_ci return ret; 403062306a36Sopenharmony_ci} 403162306a36Sopenharmony_ci 403262306a36Sopenharmony_cistatic s32 e1000_do_write_eeprom(struct e1000_hw *hw, u16 offset, u16 words, 403362306a36Sopenharmony_ci u16 *data) 403462306a36Sopenharmony_ci{ 403562306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 403662306a36Sopenharmony_ci s32 status = 0; 403762306a36Sopenharmony_ci 403862306a36Sopenharmony_ci if (hw->mac_type == e1000_ce4100) { 403962306a36Sopenharmony_ci GBE_CONFIG_FLASH_WRITE(GBE_CONFIG_BASE_VIRT, offset, words, 404062306a36Sopenharmony_ci data); 404162306a36Sopenharmony_ci return E1000_SUCCESS; 404262306a36Sopenharmony_ci } 404362306a36Sopenharmony_ci 404462306a36Sopenharmony_ci /* A check for invalid values: offset too large, too many words, and 404562306a36Sopenharmony_ci * not enough words. 404662306a36Sopenharmony_ci */ 404762306a36Sopenharmony_ci if ((offset >= eeprom->word_size) || 404862306a36Sopenharmony_ci (words > eeprom->word_size - offset) || 404962306a36Sopenharmony_ci (words == 0)) { 405062306a36Sopenharmony_ci e_dbg("\"words\" parameter out of bounds\n"); 405162306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 405262306a36Sopenharmony_ci } 405362306a36Sopenharmony_ci 405462306a36Sopenharmony_ci /* Prepare the EEPROM for writing */ 405562306a36Sopenharmony_ci if (e1000_acquire_eeprom(hw) != E1000_SUCCESS) 405662306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 405762306a36Sopenharmony_ci 405862306a36Sopenharmony_ci if (eeprom->type == e1000_eeprom_microwire) { 405962306a36Sopenharmony_ci status = e1000_write_eeprom_microwire(hw, offset, words, data); 406062306a36Sopenharmony_ci } else { 406162306a36Sopenharmony_ci status = e1000_write_eeprom_spi(hw, offset, words, data); 406262306a36Sopenharmony_ci msleep(10); 406362306a36Sopenharmony_ci } 406462306a36Sopenharmony_ci 406562306a36Sopenharmony_ci /* Done with writing */ 406662306a36Sopenharmony_ci e1000_release_eeprom(hw); 406762306a36Sopenharmony_ci 406862306a36Sopenharmony_ci return status; 406962306a36Sopenharmony_ci} 407062306a36Sopenharmony_ci 407162306a36Sopenharmony_ci/** 407262306a36Sopenharmony_ci * e1000_write_eeprom_spi - Writes a 16 bit word to a given offset in an SPI EEPROM. 407362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 407462306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to 407562306a36Sopenharmony_ci * @words: number of words to write 407662306a36Sopenharmony_ci * @data: pointer to array of 8 bit words to be written to the EEPROM 407762306a36Sopenharmony_ci */ 407862306a36Sopenharmony_cistatic s32 e1000_write_eeprom_spi(struct e1000_hw *hw, u16 offset, u16 words, 407962306a36Sopenharmony_ci u16 *data) 408062306a36Sopenharmony_ci{ 408162306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 408262306a36Sopenharmony_ci u16 widx = 0; 408362306a36Sopenharmony_ci 408462306a36Sopenharmony_ci while (widx < words) { 408562306a36Sopenharmony_ci u8 write_opcode = EEPROM_WRITE_OPCODE_SPI; 408662306a36Sopenharmony_ci 408762306a36Sopenharmony_ci if (e1000_spi_eeprom_ready(hw)) 408862306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 408962306a36Sopenharmony_ci 409062306a36Sopenharmony_ci e1000_standby_eeprom(hw); 409162306a36Sopenharmony_ci cond_resched(); 409262306a36Sopenharmony_ci 409362306a36Sopenharmony_ci /* Send the WRITE ENABLE command (8 bit opcode ) */ 409462306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, EEPROM_WREN_OPCODE_SPI, 409562306a36Sopenharmony_ci eeprom->opcode_bits); 409662306a36Sopenharmony_ci 409762306a36Sopenharmony_ci e1000_standby_eeprom(hw); 409862306a36Sopenharmony_ci 409962306a36Sopenharmony_ci /* Some SPI eeproms use the 8th address bit embedded in the 410062306a36Sopenharmony_ci * opcode 410162306a36Sopenharmony_ci */ 410262306a36Sopenharmony_ci if ((eeprom->address_bits == 8) && (offset >= 128)) 410362306a36Sopenharmony_ci write_opcode |= EEPROM_A8_OPCODE_SPI; 410462306a36Sopenharmony_ci 410562306a36Sopenharmony_ci /* Send the Write command (8-bit opcode + addr) */ 410662306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, write_opcode, eeprom->opcode_bits); 410762306a36Sopenharmony_ci 410862306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, (u16)((offset + widx) * 2), 410962306a36Sopenharmony_ci eeprom->address_bits); 411062306a36Sopenharmony_ci 411162306a36Sopenharmony_ci /* Send the data */ 411262306a36Sopenharmony_ci 411362306a36Sopenharmony_ci /* Loop to allow for up to whole page write (32 bytes) of 411462306a36Sopenharmony_ci * eeprom 411562306a36Sopenharmony_ci */ 411662306a36Sopenharmony_ci while (widx < words) { 411762306a36Sopenharmony_ci u16 word_out = data[widx]; 411862306a36Sopenharmony_ci 411962306a36Sopenharmony_ci word_out = (word_out >> 8) | (word_out << 8); 412062306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, word_out, 16); 412162306a36Sopenharmony_ci widx++; 412262306a36Sopenharmony_ci 412362306a36Sopenharmony_ci /* Some larger eeprom sizes are capable of a 32-byte 412462306a36Sopenharmony_ci * PAGE WRITE operation, while the smaller eeproms are 412562306a36Sopenharmony_ci * capable of an 8-byte PAGE WRITE operation. Break the 412662306a36Sopenharmony_ci * inner loop to pass new address 412762306a36Sopenharmony_ci */ 412862306a36Sopenharmony_ci if ((((offset + widx) * 2) % eeprom->page_size) == 0) { 412962306a36Sopenharmony_ci e1000_standby_eeprom(hw); 413062306a36Sopenharmony_ci break; 413162306a36Sopenharmony_ci } 413262306a36Sopenharmony_ci } 413362306a36Sopenharmony_ci } 413462306a36Sopenharmony_ci 413562306a36Sopenharmony_ci return E1000_SUCCESS; 413662306a36Sopenharmony_ci} 413762306a36Sopenharmony_ci 413862306a36Sopenharmony_ci/** 413962306a36Sopenharmony_ci * e1000_write_eeprom_microwire - Writes a 16 bit word to a given offset in a Microwire EEPROM. 414062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 414162306a36Sopenharmony_ci * @offset: offset within the EEPROM to be written to 414262306a36Sopenharmony_ci * @words: number of words to write 414362306a36Sopenharmony_ci * @data: pointer to array of 8 bit words to be written to the EEPROM 414462306a36Sopenharmony_ci */ 414562306a36Sopenharmony_cistatic s32 e1000_write_eeprom_microwire(struct e1000_hw *hw, u16 offset, 414662306a36Sopenharmony_ci u16 words, u16 *data) 414762306a36Sopenharmony_ci{ 414862306a36Sopenharmony_ci struct e1000_eeprom_info *eeprom = &hw->eeprom; 414962306a36Sopenharmony_ci u32 eecd; 415062306a36Sopenharmony_ci u16 words_written = 0; 415162306a36Sopenharmony_ci u16 i = 0; 415262306a36Sopenharmony_ci 415362306a36Sopenharmony_ci /* Send the write enable command to the EEPROM (3-bit opcode plus 415462306a36Sopenharmony_ci * 6/8-bit dummy address beginning with 11). It's less work to include 415562306a36Sopenharmony_ci * the 11 of the dummy address as part of the opcode than it is to shift 415662306a36Sopenharmony_ci * it over the correct number of bits for the address. This puts the 415762306a36Sopenharmony_ci * EEPROM into write/erase mode. 415862306a36Sopenharmony_ci */ 415962306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, EEPROM_EWEN_OPCODE_MICROWIRE, 416062306a36Sopenharmony_ci (u16)(eeprom->opcode_bits + 2)); 416162306a36Sopenharmony_ci 416262306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2)); 416362306a36Sopenharmony_ci 416462306a36Sopenharmony_ci /* Prepare the EEPROM */ 416562306a36Sopenharmony_ci e1000_standby_eeprom(hw); 416662306a36Sopenharmony_ci 416762306a36Sopenharmony_ci while (words_written < words) { 416862306a36Sopenharmony_ci /* Send the Write command (3-bit opcode + addr) */ 416962306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, EEPROM_WRITE_OPCODE_MICROWIRE, 417062306a36Sopenharmony_ci eeprom->opcode_bits); 417162306a36Sopenharmony_ci 417262306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, (u16)(offset + words_written), 417362306a36Sopenharmony_ci eeprom->address_bits); 417462306a36Sopenharmony_ci 417562306a36Sopenharmony_ci /* Send the data */ 417662306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, data[words_written], 16); 417762306a36Sopenharmony_ci 417862306a36Sopenharmony_ci /* Toggle the CS line. This in effect tells the EEPROM to 417962306a36Sopenharmony_ci * execute the previous command. 418062306a36Sopenharmony_ci */ 418162306a36Sopenharmony_ci e1000_standby_eeprom(hw); 418262306a36Sopenharmony_ci 418362306a36Sopenharmony_ci /* Read DO repeatedly until it is high (equal to '1'). The 418462306a36Sopenharmony_ci * EEPROM will signal that the command has been completed by 418562306a36Sopenharmony_ci * raising the DO signal. If DO does not go high in 10 418662306a36Sopenharmony_ci * milliseconds, then error out. 418762306a36Sopenharmony_ci */ 418862306a36Sopenharmony_ci for (i = 0; i < 200; i++) { 418962306a36Sopenharmony_ci eecd = er32(EECD); 419062306a36Sopenharmony_ci if (eecd & E1000_EECD_DO) 419162306a36Sopenharmony_ci break; 419262306a36Sopenharmony_ci udelay(50); 419362306a36Sopenharmony_ci } 419462306a36Sopenharmony_ci if (i == 200) { 419562306a36Sopenharmony_ci e_dbg("EEPROM Write did not complete\n"); 419662306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 419762306a36Sopenharmony_ci } 419862306a36Sopenharmony_ci 419962306a36Sopenharmony_ci /* Recover from write */ 420062306a36Sopenharmony_ci e1000_standby_eeprom(hw); 420162306a36Sopenharmony_ci cond_resched(); 420262306a36Sopenharmony_ci 420362306a36Sopenharmony_ci words_written++; 420462306a36Sopenharmony_ci } 420562306a36Sopenharmony_ci 420662306a36Sopenharmony_ci /* Send the write disable command to the EEPROM (3-bit opcode plus 420762306a36Sopenharmony_ci * 6/8-bit dummy address beginning with 10). It's less work to include 420862306a36Sopenharmony_ci * the 10 of the dummy address as part of the opcode than it is to shift 420962306a36Sopenharmony_ci * it over the correct number of bits for the address. This takes the 421062306a36Sopenharmony_ci * EEPROM out of write/erase mode. 421162306a36Sopenharmony_ci */ 421262306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, EEPROM_EWDS_OPCODE_MICROWIRE, 421362306a36Sopenharmony_ci (u16)(eeprom->opcode_bits + 2)); 421462306a36Sopenharmony_ci 421562306a36Sopenharmony_ci e1000_shift_out_ee_bits(hw, 0, (u16)(eeprom->address_bits - 2)); 421662306a36Sopenharmony_ci 421762306a36Sopenharmony_ci return E1000_SUCCESS; 421862306a36Sopenharmony_ci} 421962306a36Sopenharmony_ci 422062306a36Sopenharmony_ci/** 422162306a36Sopenharmony_ci * e1000_read_mac_addr - read the adapters MAC from eeprom 422262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 422362306a36Sopenharmony_ci * 422462306a36Sopenharmony_ci * Reads the adapter's MAC address from the EEPROM and inverts the LSB for the 422562306a36Sopenharmony_ci * second function of dual function devices 422662306a36Sopenharmony_ci */ 422762306a36Sopenharmony_cis32 e1000_read_mac_addr(struct e1000_hw *hw) 422862306a36Sopenharmony_ci{ 422962306a36Sopenharmony_ci u16 offset; 423062306a36Sopenharmony_ci u16 eeprom_data, i; 423162306a36Sopenharmony_ci 423262306a36Sopenharmony_ci for (i = 0; i < NODE_ADDRESS_SIZE; i += 2) { 423362306a36Sopenharmony_ci offset = i >> 1; 423462306a36Sopenharmony_ci if (e1000_read_eeprom(hw, offset, 1, &eeprom_data) < 0) { 423562306a36Sopenharmony_ci e_dbg("EEPROM Read Error\n"); 423662306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 423762306a36Sopenharmony_ci } 423862306a36Sopenharmony_ci hw->perm_mac_addr[i] = (u8)(eeprom_data & 0x00FF); 423962306a36Sopenharmony_ci hw->perm_mac_addr[i + 1] = (u8)(eeprom_data >> 8); 424062306a36Sopenharmony_ci } 424162306a36Sopenharmony_ci 424262306a36Sopenharmony_ci switch (hw->mac_type) { 424362306a36Sopenharmony_ci default: 424462306a36Sopenharmony_ci break; 424562306a36Sopenharmony_ci case e1000_82546: 424662306a36Sopenharmony_ci case e1000_82546_rev_3: 424762306a36Sopenharmony_ci if (er32(STATUS) & E1000_STATUS_FUNC_1) 424862306a36Sopenharmony_ci hw->perm_mac_addr[5] ^= 0x01; 424962306a36Sopenharmony_ci break; 425062306a36Sopenharmony_ci } 425162306a36Sopenharmony_ci 425262306a36Sopenharmony_ci for (i = 0; i < NODE_ADDRESS_SIZE; i++) 425362306a36Sopenharmony_ci hw->mac_addr[i] = hw->perm_mac_addr[i]; 425462306a36Sopenharmony_ci return E1000_SUCCESS; 425562306a36Sopenharmony_ci} 425662306a36Sopenharmony_ci 425762306a36Sopenharmony_ci/** 425862306a36Sopenharmony_ci * e1000_init_rx_addrs - Initializes receive address filters. 425962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 426062306a36Sopenharmony_ci * 426162306a36Sopenharmony_ci * Places the MAC address in receive address register 0 and clears the rest 426262306a36Sopenharmony_ci * of the receive address registers. Clears the multicast table. Assumes 426362306a36Sopenharmony_ci * the receiver is in reset when the routine is called. 426462306a36Sopenharmony_ci */ 426562306a36Sopenharmony_cistatic void e1000_init_rx_addrs(struct e1000_hw *hw) 426662306a36Sopenharmony_ci{ 426762306a36Sopenharmony_ci u32 i; 426862306a36Sopenharmony_ci u32 rar_num; 426962306a36Sopenharmony_ci 427062306a36Sopenharmony_ci /* Setup the receive address. */ 427162306a36Sopenharmony_ci e_dbg("Programming MAC Address into RAR[0]\n"); 427262306a36Sopenharmony_ci 427362306a36Sopenharmony_ci e1000_rar_set(hw, hw->mac_addr, 0); 427462306a36Sopenharmony_ci 427562306a36Sopenharmony_ci rar_num = E1000_RAR_ENTRIES; 427662306a36Sopenharmony_ci 427762306a36Sopenharmony_ci /* Zero out the following 14 receive addresses. RAR[15] is for 427862306a36Sopenharmony_ci * manageability 427962306a36Sopenharmony_ci */ 428062306a36Sopenharmony_ci e_dbg("Clearing RAR[1-14]\n"); 428162306a36Sopenharmony_ci for (i = 1; i < rar_num; i++) { 428262306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, RA, (i << 1), 0); 428362306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 428462306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, RA, ((i << 1) + 1), 0); 428562306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 428662306a36Sopenharmony_ci } 428762306a36Sopenharmony_ci} 428862306a36Sopenharmony_ci 428962306a36Sopenharmony_ci/** 429062306a36Sopenharmony_ci * e1000_hash_mc_addr - Hashes an address to determine its location in the multicast table 429162306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 429262306a36Sopenharmony_ci * @mc_addr: the multicast address to hash 429362306a36Sopenharmony_ci */ 429462306a36Sopenharmony_ciu32 e1000_hash_mc_addr(struct e1000_hw *hw, u8 *mc_addr) 429562306a36Sopenharmony_ci{ 429662306a36Sopenharmony_ci u32 hash_value = 0; 429762306a36Sopenharmony_ci 429862306a36Sopenharmony_ci /* The portion of the address that is used for the hash table is 429962306a36Sopenharmony_ci * determined by the mc_filter_type setting. 430062306a36Sopenharmony_ci */ 430162306a36Sopenharmony_ci switch (hw->mc_filter_type) { 430262306a36Sopenharmony_ci /* [0] [1] [2] [3] [4] [5] 430362306a36Sopenharmony_ci * 01 AA 00 12 34 56 430462306a36Sopenharmony_ci * LSB MSB 430562306a36Sopenharmony_ci */ 430662306a36Sopenharmony_ci case 0: 430762306a36Sopenharmony_ci /* [47:36] i.e. 0x563 for above example address */ 430862306a36Sopenharmony_ci hash_value = ((mc_addr[4] >> 4) | (((u16)mc_addr[5]) << 4)); 430962306a36Sopenharmony_ci break; 431062306a36Sopenharmony_ci case 1: 431162306a36Sopenharmony_ci /* [46:35] i.e. 0xAC6 for above example address */ 431262306a36Sopenharmony_ci hash_value = ((mc_addr[4] >> 3) | (((u16)mc_addr[5]) << 5)); 431362306a36Sopenharmony_ci break; 431462306a36Sopenharmony_ci case 2: 431562306a36Sopenharmony_ci /* [45:34] i.e. 0x5D8 for above example address */ 431662306a36Sopenharmony_ci hash_value = ((mc_addr[4] >> 2) | (((u16)mc_addr[5]) << 6)); 431762306a36Sopenharmony_ci break; 431862306a36Sopenharmony_ci case 3: 431962306a36Sopenharmony_ci /* [43:32] i.e. 0x634 for above example address */ 432062306a36Sopenharmony_ci hash_value = ((mc_addr[4]) | (((u16)mc_addr[5]) << 8)); 432162306a36Sopenharmony_ci break; 432262306a36Sopenharmony_ci } 432362306a36Sopenharmony_ci 432462306a36Sopenharmony_ci hash_value &= 0xFFF; 432562306a36Sopenharmony_ci return hash_value; 432662306a36Sopenharmony_ci} 432762306a36Sopenharmony_ci 432862306a36Sopenharmony_ci/** 432962306a36Sopenharmony_ci * e1000_rar_set - Puts an ethernet address into a receive address register. 433062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 433162306a36Sopenharmony_ci * @addr: Address to put into receive address register 433262306a36Sopenharmony_ci * @index: Receive address register to write 433362306a36Sopenharmony_ci */ 433462306a36Sopenharmony_civoid e1000_rar_set(struct e1000_hw *hw, u8 *addr, u32 index) 433562306a36Sopenharmony_ci{ 433662306a36Sopenharmony_ci u32 rar_low, rar_high; 433762306a36Sopenharmony_ci 433862306a36Sopenharmony_ci /* HW expects these in little endian so we reverse the byte order 433962306a36Sopenharmony_ci * from network order (big endian) to little endian 434062306a36Sopenharmony_ci */ 434162306a36Sopenharmony_ci rar_low = ((u32)addr[0] | ((u32)addr[1] << 8) | 434262306a36Sopenharmony_ci ((u32)addr[2] << 16) | ((u32)addr[3] << 24)); 434362306a36Sopenharmony_ci rar_high = ((u32)addr[4] | ((u32)addr[5] << 8)); 434462306a36Sopenharmony_ci 434562306a36Sopenharmony_ci /* Disable Rx and flush all Rx frames before enabling RSS to avoid Rx 434662306a36Sopenharmony_ci * unit hang. 434762306a36Sopenharmony_ci * 434862306a36Sopenharmony_ci * Description: 434962306a36Sopenharmony_ci * If there are any Rx frames queued up or otherwise present in the HW 435062306a36Sopenharmony_ci * before RSS is enabled, and then we enable RSS, the HW Rx unit will 435162306a36Sopenharmony_ci * hang. To work around this issue, we have to disable receives and 435262306a36Sopenharmony_ci * flush out all Rx frames before we enable RSS. To do so, we modify we 435362306a36Sopenharmony_ci * redirect all Rx traffic to manageability and then reset the HW. 435462306a36Sopenharmony_ci * This flushes away Rx frames, and (since the redirections to 435562306a36Sopenharmony_ci * manageability persists across resets) keeps new ones from coming in 435662306a36Sopenharmony_ci * while we work. Then, we clear the Address Valid AV bit for all MAC 435762306a36Sopenharmony_ci * addresses and undo the re-direction to manageability. 435862306a36Sopenharmony_ci * Now, frames are coming in again, but the MAC won't accept them, so 435962306a36Sopenharmony_ci * far so good. We now proceed to initialize RSS (if necessary) and 436062306a36Sopenharmony_ci * configure the Rx unit. Last, we re-enable the AV bits and continue 436162306a36Sopenharmony_ci * on our merry way. 436262306a36Sopenharmony_ci */ 436362306a36Sopenharmony_ci switch (hw->mac_type) { 436462306a36Sopenharmony_ci default: 436562306a36Sopenharmony_ci /* Indicate to hardware the Address is Valid. */ 436662306a36Sopenharmony_ci rar_high |= E1000_RAH_AV; 436762306a36Sopenharmony_ci break; 436862306a36Sopenharmony_ci } 436962306a36Sopenharmony_ci 437062306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, RA, (index << 1), rar_low); 437162306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 437262306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, RA, ((index << 1) + 1), rar_high); 437362306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 437462306a36Sopenharmony_ci} 437562306a36Sopenharmony_ci 437662306a36Sopenharmony_ci/** 437762306a36Sopenharmony_ci * e1000_write_vfta - Writes a value to the specified offset in the VLAN filter table. 437862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 437962306a36Sopenharmony_ci * @offset: Offset in VLAN filter table to write 438062306a36Sopenharmony_ci * @value: Value to write into VLAN filter table 438162306a36Sopenharmony_ci */ 438262306a36Sopenharmony_civoid e1000_write_vfta(struct e1000_hw *hw, u32 offset, u32 value) 438362306a36Sopenharmony_ci{ 438462306a36Sopenharmony_ci u32 temp; 438562306a36Sopenharmony_ci 438662306a36Sopenharmony_ci if ((hw->mac_type == e1000_82544) && ((offset & 0x1) == 1)) { 438762306a36Sopenharmony_ci temp = E1000_READ_REG_ARRAY(hw, VFTA, (offset - 1)); 438862306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); 438962306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 439062306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, VFTA, (offset - 1), temp); 439162306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 439262306a36Sopenharmony_ci } else { 439362306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, VFTA, offset, value); 439462306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 439562306a36Sopenharmony_ci } 439662306a36Sopenharmony_ci} 439762306a36Sopenharmony_ci 439862306a36Sopenharmony_ci/** 439962306a36Sopenharmony_ci * e1000_clear_vfta - Clears the VLAN filter table 440062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 440162306a36Sopenharmony_ci */ 440262306a36Sopenharmony_cistatic void e1000_clear_vfta(struct e1000_hw *hw) 440362306a36Sopenharmony_ci{ 440462306a36Sopenharmony_ci u32 offset; 440562306a36Sopenharmony_ci 440662306a36Sopenharmony_ci for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { 440762306a36Sopenharmony_ci E1000_WRITE_REG_ARRAY(hw, VFTA, offset, 0); 440862306a36Sopenharmony_ci E1000_WRITE_FLUSH(); 440962306a36Sopenharmony_ci } 441062306a36Sopenharmony_ci} 441162306a36Sopenharmony_ci 441262306a36Sopenharmony_cistatic s32 e1000_id_led_init(struct e1000_hw *hw) 441362306a36Sopenharmony_ci{ 441462306a36Sopenharmony_ci u32 ledctl; 441562306a36Sopenharmony_ci const u32 ledctl_mask = 0x000000FF; 441662306a36Sopenharmony_ci const u32 ledctl_on = E1000_LEDCTL_MODE_LED_ON; 441762306a36Sopenharmony_ci const u32 ledctl_off = E1000_LEDCTL_MODE_LED_OFF; 441862306a36Sopenharmony_ci u16 eeprom_data, i, temp; 441962306a36Sopenharmony_ci const u16 led_mask = 0x0F; 442062306a36Sopenharmony_ci 442162306a36Sopenharmony_ci if (hw->mac_type < e1000_82540) { 442262306a36Sopenharmony_ci /* Nothing to do */ 442362306a36Sopenharmony_ci return E1000_SUCCESS; 442462306a36Sopenharmony_ci } 442562306a36Sopenharmony_ci 442662306a36Sopenharmony_ci ledctl = er32(LEDCTL); 442762306a36Sopenharmony_ci hw->ledctl_default = ledctl; 442862306a36Sopenharmony_ci hw->ledctl_mode1 = hw->ledctl_default; 442962306a36Sopenharmony_ci hw->ledctl_mode2 = hw->ledctl_default; 443062306a36Sopenharmony_ci 443162306a36Sopenharmony_ci if (e1000_read_eeprom(hw, EEPROM_ID_LED_SETTINGS, 1, &eeprom_data) < 0) { 443262306a36Sopenharmony_ci e_dbg("EEPROM Read Error\n"); 443362306a36Sopenharmony_ci return -E1000_ERR_EEPROM; 443462306a36Sopenharmony_ci } 443562306a36Sopenharmony_ci 443662306a36Sopenharmony_ci if ((eeprom_data == ID_LED_RESERVED_0000) || 443762306a36Sopenharmony_ci (eeprom_data == ID_LED_RESERVED_FFFF)) { 443862306a36Sopenharmony_ci eeprom_data = ID_LED_DEFAULT; 443962306a36Sopenharmony_ci } 444062306a36Sopenharmony_ci 444162306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 444262306a36Sopenharmony_ci temp = (eeprom_data >> (i << 2)) & led_mask; 444362306a36Sopenharmony_ci switch (temp) { 444462306a36Sopenharmony_ci case ID_LED_ON1_DEF2: 444562306a36Sopenharmony_ci case ID_LED_ON1_ON2: 444662306a36Sopenharmony_ci case ID_LED_ON1_OFF2: 444762306a36Sopenharmony_ci hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); 444862306a36Sopenharmony_ci hw->ledctl_mode1 |= ledctl_on << (i << 3); 444962306a36Sopenharmony_ci break; 445062306a36Sopenharmony_ci case ID_LED_OFF1_DEF2: 445162306a36Sopenharmony_ci case ID_LED_OFF1_ON2: 445262306a36Sopenharmony_ci case ID_LED_OFF1_OFF2: 445362306a36Sopenharmony_ci hw->ledctl_mode1 &= ~(ledctl_mask << (i << 3)); 445462306a36Sopenharmony_ci hw->ledctl_mode1 |= ledctl_off << (i << 3); 445562306a36Sopenharmony_ci break; 445662306a36Sopenharmony_ci default: 445762306a36Sopenharmony_ci /* Do nothing */ 445862306a36Sopenharmony_ci break; 445962306a36Sopenharmony_ci } 446062306a36Sopenharmony_ci switch (temp) { 446162306a36Sopenharmony_ci case ID_LED_DEF1_ON2: 446262306a36Sopenharmony_ci case ID_LED_ON1_ON2: 446362306a36Sopenharmony_ci case ID_LED_OFF1_ON2: 446462306a36Sopenharmony_ci hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); 446562306a36Sopenharmony_ci hw->ledctl_mode2 |= ledctl_on << (i << 3); 446662306a36Sopenharmony_ci break; 446762306a36Sopenharmony_ci case ID_LED_DEF1_OFF2: 446862306a36Sopenharmony_ci case ID_LED_ON1_OFF2: 446962306a36Sopenharmony_ci case ID_LED_OFF1_OFF2: 447062306a36Sopenharmony_ci hw->ledctl_mode2 &= ~(ledctl_mask << (i << 3)); 447162306a36Sopenharmony_ci hw->ledctl_mode2 |= ledctl_off << (i << 3); 447262306a36Sopenharmony_ci break; 447362306a36Sopenharmony_ci default: 447462306a36Sopenharmony_ci /* Do nothing */ 447562306a36Sopenharmony_ci break; 447662306a36Sopenharmony_ci } 447762306a36Sopenharmony_ci } 447862306a36Sopenharmony_ci return E1000_SUCCESS; 447962306a36Sopenharmony_ci} 448062306a36Sopenharmony_ci 448162306a36Sopenharmony_ci/** 448262306a36Sopenharmony_ci * e1000_setup_led 448362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 448462306a36Sopenharmony_ci * 448562306a36Sopenharmony_ci * Prepares SW controlable LED for use and saves the current state of the LED. 448662306a36Sopenharmony_ci */ 448762306a36Sopenharmony_cis32 e1000_setup_led(struct e1000_hw *hw) 448862306a36Sopenharmony_ci{ 448962306a36Sopenharmony_ci u32 ledctl; 449062306a36Sopenharmony_ci s32 ret_val = E1000_SUCCESS; 449162306a36Sopenharmony_ci 449262306a36Sopenharmony_ci switch (hw->mac_type) { 449362306a36Sopenharmony_ci case e1000_82542_rev2_0: 449462306a36Sopenharmony_ci case e1000_82542_rev2_1: 449562306a36Sopenharmony_ci case e1000_82543: 449662306a36Sopenharmony_ci case e1000_82544: 449762306a36Sopenharmony_ci /* No setup necessary */ 449862306a36Sopenharmony_ci break; 449962306a36Sopenharmony_ci case e1000_82541: 450062306a36Sopenharmony_ci case e1000_82547: 450162306a36Sopenharmony_ci case e1000_82541_rev_2: 450262306a36Sopenharmony_ci case e1000_82547_rev_2: 450362306a36Sopenharmony_ci /* Turn off PHY Smart Power Down (if enabled) */ 450462306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, 450562306a36Sopenharmony_ci &hw->phy_spd_default); 450662306a36Sopenharmony_ci if (ret_val) 450762306a36Sopenharmony_ci return ret_val; 450862306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, 450962306a36Sopenharmony_ci (u16)(hw->phy_spd_default & 451062306a36Sopenharmony_ci ~IGP01E1000_GMII_SPD)); 451162306a36Sopenharmony_ci if (ret_val) 451262306a36Sopenharmony_ci return ret_val; 451362306a36Sopenharmony_ci fallthrough; 451462306a36Sopenharmony_ci default: 451562306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_fiber) { 451662306a36Sopenharmony_ci ledctl = er32(LEDCTL); 451762306a36Sopenharmony_ci /* Save current LEDCTL settings */ 451862306a36Sopenharmony_ci hw->ledctl_default = ledctl; 451962306a36Sopenharmony_ci /* Turn off LED0 */ 452062306a36Sopenharmony_ci ledctl &= ~(E1000_LEDCTL_LED0_IVRT | 452162306a36Sopenharmony_ci E1000_LEDCTL_LED0_BLINK | 452262306a36Sopenharmony_ci E1000_LEDCTL_LED0_MODE_MASK); 452362306a36Sopenharmony_ci ledctl |= (E1000_LEDCTL_MODE_LED_OFF << 452462306a36Sopenharmony_ci E1000_LEDCTL_LED0_MODE_SHIFT); 452562306a36Sopenharmony_ci ew32(LEDCTL, ledctl); 452662306a36Sopenharmony_ci } else if (hw->media_type == e1000_media_type_copper) 452762306a36Sopenharmony_ci ew32(LEDCTL, hw->ledctl_mode1); 452862306a36Sopenharmony_ci break; 452962306a36Sopenharmony_ci } 453062306a36Sopenharmony_ci 453162306a36Sopenharmony_ci return E1000_SUCCESS; 453262306a36Sopenharmony_ci} 453362306a36Sopenharmony_ci 453462306a36Sopenharmony_ci/** 453562306a36Sopenharmony_ci * e1000_cleanup_led - Restores the saved state of the SW controlable LED. 453662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 453762306a36Sopenharmony_ci */ 453862306a36Sopenharmony_cis32 e1000_cleanup_led(struct e1000_hw *hw) 453962306a36Sopenharmony_ci{ 454062306a36Sopenharmony_ci s32 ret_val = E1000_SUCCESS; 454162306a36Sopenharmony_ci 454262306a36Sopenharmony_ci switch (hw->mac_type) { 454362306a36Sopenharmony_ci case e1000_82542_rev2_0: 454462306a36Sopenharmony_ci case e1000_82542_rev2_1: 454562306a36Sopenharmony_ci case e1000_82543: 454662306a36Sopenharmony_ci case e1000_82544: 454762306a36Sopenharmony_ci /* No cleanup necessary */ 454862306a36Sopenharmony_ci break; 454962306a36Sopenharmony_ci case e1000_82541: 455062306a36Sopenharmony_ci case e1000_82547: 455162306a36Sopenharmony_ci case e1000_82541_rev_2: 455262306a36Sopenharmony_ci case e1000_82547_rev_2: 455362306a36Sopenharmony_ci /* Turn on PHY Smart Power Down (if previously enabled) */ 455462306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, 455562306a36Sopenharmony_ci hw->phy_spd_default); 455662306a36Sopenharmony_ci if (ret_val) 455762306a36Sopenharmony_ci return ret_val; 455862306a36Sopenharmony_ci fallthrough; 455962306a36Sopenharmony_ci default: 456062306a36Sopenharmony_ci /* Restore LEDCTL settings */ 456162306a36Sopenharmony_ci ew32(LEDCTL, hw->ledctl_default); 456262306a36Sopenharmony_ci break; 456362306a36Sopenharmony_ci } 456462306a36Sopenharmony_ci 456562306a36Sopenharmony_ci return E1000_SUCCESS; 456662306a36Sopenharmony_ci} 456762306a36Sopenharmony_ci 456862306a36Sopenharmony_ci/** 456962306a36Sopenharmony_ci * e1000_led_on - Turns on the software controllable LED 457062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 457162306a36Sopenharmony_ci */ 457262306a36Sopenharmony_cis32 e1000_led_on(struct e1000_hw *hw) 457362306a36Sopenharmony_ci{ 457462306a36Sopenharmony_ci u32 ctrl = er32(CTRL); 457562306a36Sopenharmony_ci 457662306a36Sopenharmony_ci switch (hw->mac_type) { 457762306a36Sopenharmony_ci case e1000_82542_rev2_0: 457862306a36Sopenharmony_ci case e1000_82542_rev2_1: 457962306a36Sopenharmony_ci case e1000_82543: 458062306a36Sopenharmony_ci /* Set SW Defineable Pin 0 to turn on the LED */ 458162306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIN0; 458262306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 458362306a36Sopenharmony_ci break; 458462306a36Sopenharmony_ci case e1000_82544: 458562306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_fiber) { 458662306a36Sopenharmony_ci /* Set SW Defineable Pin 0 to turn on the LED */ 458762306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIN0; 458862306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 458962306a36Sopenharmony_ci } else { 459062306a36Sopenharmony_ci /* Clear SW Defineable Pin 0 to turn on the LED */ 459162306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_SWDPIN0; 459262306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 459362306a36Sopenharmony_ci } 459462306a36Sopenharmony_ci break; 459562306a36Sopenharmony_ci default: 459662306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_fiber) { 459762306a36Sopenharmony_ci /* Clear SW Defineable Pin 0 to turn on the LED */ 459862306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_SWDPIN0; 459962306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 460062306a36Sopenharmony_ci } else if (hw->media_type == e1000_media_type_copper) { 460162306a36Sopenharmony_ci ew32(LEDCTL, hw->ledctl_mode2); 460262306a36Sopenharmony_ci return E1000_SUCCESS; 460362306a36Sopenharmony_ci } 460462306a36Sopenharmony_ci break; 460562306a36Sopenharmony_ci } 460662306a36Sopenharmony_ci 460762306a36Sopenharmony_ci ew32(CTRL, ctrl); 460862306a36Sopenharmony_ci 460962306a36Sopenharmony_ci return E1000_SUCCESS; 461062306a36Sopenharmony_ci} 461162306a36Sopenharmony_ci 461262306a36Sopenharmony_ci/** 461362306a36Sopenharmony_ci * e1000_led_off - Turns off the software controllable LED 461462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 461562306a36Sopenharmony_ci */ 461662306a36Sopenharmony_cis32 e1000_led_off(struct e1000_hw *hw) 461762306a36Sopenharmony_ci{ 461862306a36Sopenharmony_ci u32 ctrl = er32(CTRL); 461962306a36Sopenharmony_ci 462062306a36Sopenharmony_ci switch (hw->mac_type) { 462162306a36Sopenharmony_ci case e1000_82542_rev2_0: 462262306a36Sopenharmony_ci case e1000_82542_rev2_1: 462362306a36Sopenharmony_ci case e1000_82543: 462462306a36Sopenharmony_ci /* Clear SW Defineable Pin 0 to turn off the LED */ 462562306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_SWDPIN0; 462662306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 462762306a36Sopenharmony_ci break; 462862306a36Sopenharmony_ci case e1000_82544: 462962306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_fiber) { 463062306a36Sopenharmony_ci /* Clear SW Defineable Pin 0 to turn off the LED */ 463162306a36Sopenharmony_ci ctrl &= ~E1000_CTRL_SWDPIN0; 463262306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 463362306a36Sopenharmony_ci } else { 463462306a36Sopenharmony_ci /* Set SW Defineable Pin 0 to turn off the LED */ 463562306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIN0; 463662306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 463762306a36Sopenharmony_ci } 463862306a36Sopenharmony_ci break; 463962306a36Sopenharmony_ci default: 464062306a36Sopenharmony_ci if (hw->media_type == e1000_media_type_fiber) { 464162306a36Sopenharmony_ci /* Set SW Defineable Pin 0 to turn off the LED */ 464262306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIN0; 464362306a36Sopenharmony_ci ctrl |= E1000_CTRL_SWDPIO0; 464462306a36Sopenharmony_ci } else if (hw->media_type == e1000_media_type_copper) { 464562306a36Sopenharmony_ci ew32(LEDCTL, hw->ledctl_mode1); 464662306a36Sopenharmony_ci return E1000_SUCCESS; 464762306a36Sopenharmony_ci } 464862306a36Sopenharmony_ci break; 464962306a36Sopenharmony_ci } 465062306a36Sopenharmony_ci 465162306a36Sopenharmony_ci ew32(CTRL, ctrl); 465262306a36Sopenharmony_ci 465362306a36Sopenharmony_ci return E1000_SUCCESS; 465462306a36Sopenharmony_ci} 465562306a36Sopenharmony_ci 465662306a36Sopenharmony_ci/** 465762306a36Sopenharmony_ci * e1000_clear_hw_cntrs - Clears all hardware statistics counters. 465862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 465962306a36Sopenharmony_ci */ 466062306a36Sopenharmony_cistatic void e1000_clear_hw_cntrs(struct e1000_hw *hw) 466162306a36Sopenharmony_ci{ 466262306a36Sopenharmony_ci er32(CRCERRS); 466362306a36Sopenharmony_ci er32(SYMERRS); 466462306a36Sopenharmony_ci er32(MPC); 466562306a36Sopenharmony_ci er32(SCC); 466662306a36Sopenharmony_ci er32(ECOL); 466762306a36Sopenharmony_ci er32(MCC); 466862306a36Sopenharmony_ci er32(LATECOL); 466962306a36Sopenharmony_ci er32(COLC); 467062306a36Sopenharmony_ci er32(DC); 467162306a36Sopenharmony_ci er32(SEC); 467262306a36Sopenharmony_ci er32(RLEC); 467362306a36Sopenharmony_ci er32(XONRXC); 467462306a36Sopenharmony_ci er32(XONTXC); 467562306a36Sopenharmony_ci er32(XOFFRXC); 467662306a36Sopenharmony_ci er32(XOFFTXC); 467762306a36Sopenharmony_ci er32(FCRUC); 467862306a36Sopenharmony_ci 467962306a36Sopenharmony_ci er32(PRC64); 468062306a36Sopenharmony_ci er32(PRC127); 468162306a36Sopenharmony_ci er32(PRC255); 468262306a36Sopenharmony_ci er32(PRC511); 468362306a36Sopenharmony_ci er32(PRC1023); 468462306a36Sopenharmony_ci er32(PRC1522); 468562306a36Sopenharmony_ci 468662306a36Sopenharmony_ci er32(GPRC); 468762306a36Sopenharmony_ci er32(BPRC); 468862306a36Sopenharmony_ci er32(MPRC); 468962306a36Sopenharmony_ci er32(GPTC); 469062306a36Sopenharmony_ci er32(GORCL); 469162306a36Sopenharmony_ci er32(GORCH); 469262306a36Sopenharmony_ci er32(GOTCL); 469362306a36Sopenharmony_ci er32(GOTCH); 469462306a36Sopenharmony_ci er32(RNBC); 469562306a36Sopenharmony_ci er32(RUC); 469662306a36Sopenharmony_ci er32(RFC); 469762306a36Sopenharmony_ci er32(ROC); 469862306a36Sopenharmony_ci er32(RJC); 469962306a36Sopenharmony_ci er32(TORL); 470062306a36Sopenharmony_ci er32(TORH); 470162306a36Sopenharmony_ci er32(TOTL); 470262306a36Sopenharmony_ci er32(TOTH); 470362306a36Sopenharmony_ci er32(TPR); 470462306a36Sopenharmony_ci er32(TPT); 470562306a36Sopenharmony_ci 470662306a36Sopenharmony_ci er32(PTC64); 470762306a36Sopenharmony_ci er32(PTC127); 470862306a36Sopenharmony_ci er32(PTC255); 470962306a36Sopenharmony_ci er32(PTC511); 471062306a36Sopenharmony_ci er32(PTC1023); 471162306a36Sopenharmony_ci er32(PTC1522); 471262306a36Sopenharmony_ci 471362306a36Sopenharmony_ci er32(MPTC); 471462306a36Sopenharmony_ci er32(BPTC); 471562306a36Sopenharmony_ci 471662306a36Sopenharmony_ci if (hw->mac_type < e1000_82543) 471762306a36Sopenharmony_ci return; 471862306a36Sopenharmony_ci 471962306a36Sopenharmony_ci er32(ALGNERRC); 472062306a36Sopenharmony_ci er32(RXERRC); 472162306a36Sopenharmony_ci er32(TNCRS); 472262306a36Sopenharmony_ci er32(CEXTERR); 472362306a36Sopenharmony_ci er32(TSCTC); 472462306a36Sopenharmony_ci er32(TSCTFC); 472562306a36Sopenharmony_ci 472662306a36Sopenharmony_ci if (hw->mac_type <= e1000_82544) 472762306a36Sopenharmony_ci return; 472862306a36Sopenharmony_ci 472962306a36Sopenharmony_ci er32(MGTPRC); 473062306a36Sopenharmony_ci er32(MGTPDC); 473162306a36Sopenharmony_ci er32(MGTPTC); 473262306a36Sopenharmony_ci} 473362306a36Sopenharmony_ci 473462306a36Sopenharmony_ci/** 473562306a36Sopenharmony_ci * e1000_reset_adaptive - Resets Adaptive IFS to its default state. 473662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 473762306a36Sopenharmony_ci * 473862306a36Sopenharmony_ci * Call this after e1000_init_hw. You may override the IFS defaults by setting 473962306a36Sopenharmony_ci * hw->ifs_params_forced to true. However, you must initialize hw-> 474062306a36Sopenharmony_ci * current_ifs_val, ifs_min_val, ifs_max_val, ifs_step_size, and ifs_ratio 474162306a36Sopenharmony_ci * before calling this function. 474262306a36Sopenharmony_ci */ 474362306a36Sopenharmony_civoid e1000_reset_adaptive(struct e1000_hw *hw) 474462306a36Sopenharmony_ci{ 474562306a36Sopenharmony_ci if (hw->adaptive_ifs) { 474662306a36Sopenharmony_ci if (!hw->ifs_params_forced) { 474762306a36Sopenharmony_ci hw->current_ifs_val = 0; 474862306a36Sopenharmony_ci hw->ifs_min_val = IFS_MIN; 474962306a36Sopenharmony_ci hw->ifs_max_val = IFS_MAX; 475062306a36Sopenharmony_ci hw->ifs_step_size = IFS_STEP; 475162306a36Sopenharmony_ci hw->ifs_ratio = IFS_RATIO; 475262306a36Sopenharmony_ci } 475362306a36Sopenharmony_ci hw->in_ifs_mode = false; 475462306a36Sopenharmony_ci ew32(AIT, 0); 475562306a36Sopenharmony_ci } else { 475662306a36Sopenharmony_ci e_dbg("Not in Adaptive IFS mode!\n"); 475762306a36Sopenharmony_ci } 475862306a36Sopenharmony_ci} 475962306a36Sopenharmony_ci 476062306a36Sopenharmony_ci/** 476162306a36Sopenharmony_ci * e1000_update_adaptive - update adaptive IFS 476262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 476362306a36Sopenharmony_ci * 476462306a36Sopenharmony_ci * Called during the callback/watchdog routine to update IFS value based on 476562306a36Sopenharmony_ci * the ratio of transmits to collisions. 476662306a36Sopenharmony_ci */ 476762306a36Sopenharmony_civoid e1000_update_adaptive(struct e1000_hw *hw) 476862306a36Sopenharmony_ci{ 476962306a36Sopenharmony_ci if (hw->adaptive_ifs) { 477062306a36Sopenharmony_ci if ((hw->collision_delta * hw->ifs_ratio) > hw->tx_packet_delta) { 477162306a36Sopenharmony_ci if (hw->tx_packet_delta > MIN_NUM_XMITS) { 477262306a36Sopenharmony_ci hw->in_ifs_mode = true; 477362306a36Sopenharmony_ci if (hw->current_ifs_val < hw->ifs_max_val) { 477462306a36Sopenharmony_ci if (hw->current_ifs_val == 0) 477562306a36Sopenharmony_ci hw->current_ifs_val = 477662306a36Sopenharmony_ci hw->ifs_min_val; 477762306a36Sopenharmony_ci else 477862306a36Sopenharmony_ci hw->current_ifs_val += 477962306a36Sopenharmony_ci hw->ifs_step_size; 478062306a36Sopenharmony_ci ew32(AIT, hw->current_ifs_val); 478162306a36Sopenharmony_ci } 478262306a36Sopenharmony_ci } 478362306a36Sopenharmony_ci } else { 478462306a36Sopenharmony_ci if (hw->in_ifs_mode && 478562306a36Sopenharmony_ci (hw->tx_packet_delta <= MIN_NUM_XMITS)) { 478662306a36Sopenharmony_ci hw->current_ifs_val = 0; 478762306a36Sopenharmony_ci hw->in_ifs_mode = false; 478862306a36Sopenharmony_ci ew32(AIT, 0); 478962306a36Sopenharmony_ci } 479062306a36Sopenharmony_ci } 479162306a36Sopenharmony_ci } else { 479262306a36Sopenharmony_ci e_dbg("Not in Adaptive IFS mode!\n"); 479362306a36Sopenharmony_ci } 479462306a36Sopenharmony_ci} 479562306a36Sopenharmony_ci 479662306a36Sopenharmony_ci/** 479762306a36Sopenharmony_ci * e1000_get_bus_info 479862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 479962306a36Sopenharmony_ci * 480062306a36Sopenharmony_ci * Gets the current PCI bus type, speed, and width of the hardware 480162306a36Sopenharmony_ci */ 480262306a36Sopenharmony_civoid e1000_get_bus_info(struct e1000_hw *hw) 480362306a36Sopenharmony_ci{ 480462306a36Sopenharmony_ci u32 status; 480562306a36Sopenharmony_ci 480662306a36Sopenharmony_ci switch (hw->mac_type) { 480762306a36Sopenharmony_ci case e1000_82542_rev2_0: 480862306a36Sopenharmony_ci case e1000_82542_rev2_1: 480962306a36Sopenharmony_ci hw->bus_type = e1000_bus_type_pci; 481062306a36Sopenharmony_ci hw->bus_speed = e1000_bus_speed_unknown; 481162306a36Sopenharmony_ci hw->bus_width = e1000_bus_width_unknown; 481262306a36Sopenharmony_ci break; 481362306a36Sopenharmony_ci default: 481462306a36Sopenharmony_ci status = er32(STATUS); 481562306a36Sopenharmony_ci hw->bus_type = (status & E1000_STATUS_PCIX_MODE) ? 481662306a36Sopenharmony_ci e1000_bus_type_pcix : e1000_bus_type_pci; 481762306a36Sopenharmony_ci 481862306a36Sopenharmony_ci if (hw->device_id == E1000_DEV_ID_82546EB_QUAD_COPPER) { 481962306a36Sopenharmony_ci hw->bus_speed = (hw->bus_type == e1000_bus_type_pci) ? 482062306a36Sopenharmony_ci e1000_bus_speed_66 : e1000_bus_speed_120; 482162306a36Sopenharmony_ci } else if (hw->bus_type == e1000_bus_type_pci) { 482262306a36Sopenharmony_ci hw->bus_speed = (status & E1000_STATUS_PCI66) ? 482362306a36Sopenharmony_ci e1000_bus_speed_66 : e1000_bus_speed_33; 482462306a36Sopenharmony_ci } else { 482562306a36Sopenharmony_ci switch (status & E1000_STATUS_PCIX_SPEED) { 482662306a36Sopenharmony_ci case E1000_STATUS_PCIX_SPEED_66: 482762306a36Sopenharmony_ci hw->bus_speed = e1000_bus_speed_66; 482862306a36Sopenharmony_ci break; 482962306a36Sopenharmony_ci case E1000_STATUS_PCIX_SPEED_100: 483062306a36Sopenharmony_ci hw->bus_speed = e1000_bus_speed_100; 483162306a36Sopenharmony_ci break; 483262306a36Sopenharmony_ci case E1000_STATUS_PCIX_SPEED_133: 483362306a36Sopenharmony_ci hw->bus_speed = e1000_bus_speed_133; 483462306a36Sopenharmony_ci break; 483562306a36Sopenharmony_ci default: 483662306a36Sopenharmony_ci hw->bus_speed = e1000_bus_speed_reserved; 483762306a36Sopenharmony_ci break; 483862306a36Sopenharmony_ci } 483962306a36Sopenharmony_ci } 484062306a36Sopenharmony_ci hw->bus_width = (status & E1000_STATUS_BUS64) ? 484162306a36Sopenharmony_ci e1000_bus_width_64 : e1000_bus_width_32; 484262306a36Sopenharmony_ci break; 484362306a36Sopenharmony_ci } 484462306a36Sopenharmony_ci} 484562306a36Sopenharmony_ci 484662306a36Sopenharmony_ci/** 484762306a36Sopenharmony_ci * e1000_write_reg_io 484862306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 484962306a36Sopenharmony_ci * @offset: offset to write to 485062306a36Sopenharmony_ci * @value: value to write 485162306a36Sopenharmony_ci * 485262306a36Sopenharmony_ci * Writes a value to one of the devices registers using port I/O (as opposed to 485362306a36Sopenharmony_ci * memory mapped I/O). Only 82544 and newer devices support port I/O. 485462306a36Sopenharmony_ci */ 485562306a36Sopenharmony_cistatic void e1000_write_reg_io(struct e1000_hw *hw, u32 offset, u32 value) 485662306a36Sopenharmony_ci{ 485762306a36Sopenharmony_ci unsigned long io_addr = hw->io_base; 485862306a36Sopenharmony_ci unsigned long io_data = hw->io_base + 4; 485962306a36Sopenharmony_ci 486062306a36Sopenharmony_ci e1000_io_write(hw, io_addr, offset); 486162306a36Sopenharmony_ci e1000_io_write(hw, io_data, value); 486262306a36Sopenharmony_ci} 486362306a36Sopenharmony_ci 486462306a36Sopenharmony_ci/** 486562306a36Sopenharmony_ci * e1000_get_cable_length - Estimates the cable length. 486662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 486762306a36Sopenharmony_ci * @min_length: The estimated minimum length 486862306a36Sopenharmony_ci * @max_length: The estimated maximum length 486962306a36Sopenharmony_ci * 487062306a36Sopenharmony_ci * returns: - E1000_ERR_XXX 487162306a36Sopenharmony_ci * E1000_SUCCESS 487262306a36Sopenharmony_ci * 487362306a36Sopenharmony_ci * This function always returns a ranged length (minimum & maximum). 487462306a36Sopenharmony_ci * So for M88 phy's, this function interprets the one value returned from the 487562306a36Sopenharmony_ci * register to the minimum and maximum range. 487662306a36Sopenharmony_ci * For IGP phy's, the function calculates the range by the AGC registers. 487762306a36Sopenharmony_ci */ 487862306a36Sopenharmony_cistatic s32 e1000_get_cable_length(struct e1000_hw *hw, u16 *min_length, 487962306a36Sopenharmony_ci u16 *max_length) 488062306a36Sopenharmony_ci{ 488162306a36Sopenharmony_ci s32 ret_val; 488262306a36Sopenharmony_ci u16 agc_value = 0; 488362306a36Sopenharmony_ci u16 i, phy_data; 488462306a36Sopenharmony_ci u16 cable_length; 488562306a36Sopenharmony_ci 488662306a36Sopenharmony_ci *min_length = *max_length = 0; 488762306a36Sopenharmony_ci 488862306a36Sopenharmony_ci /* Use old method for Phy older than IGP */ 488962306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_m88) { 489062306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, 489162306a36Sopenharmony_ci &phy_data); 489262306a36Sopenharmony_ci if (ret_val) 489362306a36Sopenharmony_ci return ret_val; 489462306a36Sopenharmony_ci cable_length = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> 489562306a36Sopenharmony_ci M88E1000_PSSR_CABLE_LENGTH_SHIFT; 489662306a36Sopenharmony_ci 489762306a36Sopenharmony_ci /* Convert the enum value to ranged values */ 489862306a36Sopenharmony_ci switch (cable_length) { 489962306a36Sopenharmony_ci case e1000_cable_length_50: 490062306a36Sopenharmony_ci *min_length = 0; 490162306a36Sopenharmony_ci *max_length = e1000_igp_cable_length_50; 490262306a36Sopenharmony_ci break; 490362306a36Sopenharmony_ci case e1000_cable_length_50_80: 490462306a36Sopenharmony_ci *min_length = e1000_igp_cable_length_50; 490562306a36Sopenharmony_ci *max_length = e1000_igp_cable_length_80; 490662306a36Sopenharmony_ci break; 490762306a36Sopenharmony_ci case e1000_cable_length_80_110: 490862306a36Sopenharmony_ci *min_length = e1000_igp_cable_length_80; 490962306a36Sopenharmony_ci *max_length = e1000_igp_cable_length_110; 491062306a36Sopenharmony_ci break; 491162306a36Sopenharmony_ci case e1000_cable_length_110_140: 491262306a36Sopenharmony_ci *min_length = e1000_igp_cable_length_110; 491362306a36Sopenharmony_ci *max_length = e1000_igp_cable_length_140; 491462306a36Sopenharmony_ci break; 491562306a36Sopenharmony_ci case e1000_cable_length_140: 491662306a36Sopenharmony_ci *min_length = e1000_igp_cable_length_140; 491762306a36Sopenharmony_ci *max_length = e1000_igp_cable_length_170; 491862306a36Sopenharmony_ci break; 491962306a36Sopenharmony_ci default: 492062306a36Sopenharmony_ci return -E1000_ERR_PHY; 492162306a36Sopenharmony_ci } 492262306a36Sopenharmony_ci } else if (hw->phy_type == e1000_phy_igp) { /* For IGP PHY */ 492362306a36Sopenharmony_ci u16 cur_agc_value; 492462306a36Sopenharmony_ci u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE; 492562306a36Sopenharmony_ci static const u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = { 492662306a36Sopenharmony_ci IGP01E1000_PHY_AGC_A, 492762306a36Sopenharmony_ci IGP01E1000_PHY_AGC_B, 492862306a36Sopenharmony_ci IGP01E1000_PHY_AGC_C, 492962306a36Sopenharmony_ci IGP01E1000_PHY_AGC_D 493062306a36Sopenharmony_ci }; 493162306a36Sopenharmony_ci /* Read the AGC registers for all channels */ 493262306a36Sopenharmony_ci for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 493362306a36Sopenharmony_ci ret_val = 493462306a36Sopenharmony_ci e1000_read_phy_reg(hw, agc_reg_array[i], &phy_data); 493562306a36Sopenharmony_ci if (ret_val) 493662306a36Sopenharmony_ci return ret_val; 493762306a36Sopenharmony_ci 493862306a36Sopenharmony_ci cur_agc_value = phy_data >> IGP01E1000_AGC_LENGTH_SHIFT; 493962306a36Sopenharmony_ci 494062306a36Sopenharmony_ci /* Value bound check. */ 494162306a36Sopenharmony_ci if ((cur_agc_value >= 494262306a36Sopenharmony_ci IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) || 494362306a36Sopenharmony_ci (cur_agc_value == 0)) 494462306a36Sopenharmony_ci return -E1000_ERR_PHY; 494562306a36Sopenharmony_ci 494662306a36Sopenharmony_ci agc_value += cur_agc_value; 494762306a36Sopenharmony_ci 494862306a36Sopenharmony_ci /* Update minimal AGC value. */ 494962306a36Sopenharmony_ci if (min_agc_value > cur_agc_value) 495062306a36Sopenharmony_ci min_agc_value = cur_agc_value; 495162306a36Sopenharmony_ci } 495262306a36Sopenharmony_ci 495362306a36Sopenharmony_ci /* Remove the minimal AGC result for length < 50m */ 495462306a36Sopenharmony_ci if (agc_value < 495562306a36Sopenharmony_ci IGP01E1000_PHY_CHANNEL_NUM * e1000_igp_cable_length_50) { 495662306a36Sopenharmony_ci agc_value -= min_agc_value; 495762306a36Sopenharmony_ci 495862306a36Sopenharmony_ci /* Get the average length of the remaining 3 channels */ 495962306a36Sopenharmony_ci agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1); 496062306a36Sopenharmony_ci } else { 496162306a36Sopenharmony_ci /* Get the average length of all the 4 channels. */ 496262306a36Sopenharmony_ci agc_value /= IGP01E1000_PHY_CHANNEL_NUM; 496362306a36Sopenharmony_ci } 496462306a36Sopenharmony_ci 496562306a36Sopenharmony_ci /* Set the range of the calculated length. */ 496662306a36Sopenharmony_ci *min_length = ((e1000_igp_cable_length_table[agc_value] - 496762306a36Sopenharmony_ci IGP01E1000_AGC_RANGE) > 0) ? 496862306a36Sopenharmony_ci (e1000_igp_cable_length_table[agc_value] - 496962306a36Sopenharmony_ci IGP01E1000_AGC_RANGE) : 0; 497062306a36Sopenharmony_ci *max_length = e1000_igp_cable_length_table[agc_value] + 497162306a36Sopenharmony_ci IGP01E1000_AGC_RANGE; 497262306a36Sopenharmony_ci } 497362306a36Sopenharmony_ci 497462306a36Sopenharmony_ci return E1000_SUCCESS; 497562306a36Sopenharmony_ci} 497662306a36Sopenharmony_ci 497762306a36Sopenharmony_ci/** 497862306a36Sopenharmony_ci * e1000_check_polarity - Check the cable polarity 497962306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 498062306a36Sopenharmony_ci * @polarity: output parameter : 0 - Polarity is not reversed 498162306a36Sopenharmony_ci * 1 - Polarity is reversed. 498262306a36Sopenharmony_ci * 498362306a36Sopenharmony_ci * returns: - E1000_ERR_XXX 498462306a36Sopenharmony_ci * E1000_SUCCESS 498562306a36Sopenharmony_ci * 498662306a36Sopenharmony_ci * For phy's older than IGP, this function simply reads the polarity bit in the 498762306a36Sopenharmony_ci * Phy Status register. For IGP phy's, this bit is valid only if link speed is 498862306a36Sopenharmony_ci * 10 Mbps. If the link speed is 100 Mbps there is no polarity so this bit will 498962306a36Sopenharmony_ci * return 0. If the link speed is 1000 Mbps the polarity status is in the 499062306a36Sopenharmony_ci * IGP01E1000_PHY_PCS_INIT_REG. 499162306a36Sopenharmony_ci */ 499262306a36Sopenharmony_cistatic s32 e1000_check_polarity(struct e1000_hw *hw, 499362306a36Sopenharmony_ci e1000_rev_polarity *polarity) 499462306a36Sopenharmony_ci{ 499562306a36Sopenharmony_ci s32 ret_val; 499662306a36Sopenharmony_ci u16 phy_data; 499762306a36Sopenharmony_ci 499862306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_m88) { 499962306a36Sopenharmony_ci /* return the Polarity bit in the Status register. */ 500062306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, 500162306a36Sopenharmony_ci &phy_data); 500262306a36Sopenharmony_ci if (ret_val) 500362306a36Sopenharmony_ci return ret_val; 500462306a36Sopenharmony_ci *polarity = ((phy_data & M88E1000_PSSR_REV_POLARITY) >> 500562306a36Sopenharmony_ci M88E1000_PSSR_REV_POLARITY_SHIFT) ? 500662306a36Sopenharmony_ci e1000_rev_polarity_reversed : e1000_rev_polarity_normal; 500762306a36Sopenharmony_ci 500862306a36Sopenharmony_ci } else if (hw->phy_type == e1000_phy_igp) { 500962306a36Sopenharmony_ci /* Read the Status register to check the speed */ 501062306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_STATUS, 501162306a36Sopenharmony_ci &phy_data); 501262306a36Sopenharmony_ci if (ret_val) 501362306a36Sopenharmony_ci return ret_val; 501462306a36Sopenharmony_ci 501562306a36Sopenharmony_ci /* If speed is 1000 Mbps, must read the 501662306a36Sopenharmony_ci * IGP01E1000_PHY_PCS_INIT_REG to find the polarity status 501762306a36Sopenharmony_ci */ 501862306a36Sopenharmony_ci if ((phy_data & IGP01E1000_PSSR_SPEED_MASK) == 501962306a36Sopenharmony_ci IGP01E1000_PSSR_SPEED_1000MBPS) { 502062306a36Sopenharmony_ci /* Read the GIG initialization PCS register (0x00B4) */ 502162306a36Sopenharmony_ci ret_val = 502262306a36Sopenharmony_ci e1000_read_phy_reg(hw, IGP01E1000_PHY_PCS_INIT_REG, 502362306a36Sopenharmony_ci &phy_data); 502462306a36Sopenharmony_ci if (ret_val) 502562306a36Sopenharmony_ci return ret_val; 502662306a36Sopenharmony_ci 502762306a36Sopenharmony_ci /* Check the polarity bits */ 502862306a36Sopenharmony_ci *polarity = (phy_data & IGP01E1000_PHY_POLARITY_MASK) ? 502962306a36Sopenharmony_ci e1000_rev_polarity_reversed : 503062306a36Sopenharmony_ci e1000_rev_polarity_normal; 503162306a36Sopenharmony_ci } else { 503262306a36Sopenharmony_ci /* For 10 Mbps, read the polarity bit in the status 503362306a36Sopenharmony_ci * register. (for 100 Mbps this bit is always 0) 503462306a36Sopenharmony_ci */ 503562306a36Sopenharmony_ci *polarity = 503662306a36Sopenharmony_ci (phy_data & IGP01E1000_PSSR_POLARITY_REVERSED) ? 503762306a36Sopenharmony_ci e1000_rev_polarity_reversed : 503862306a36Sopenharmony_ci e1000_rev_polarity_normal; 503962306a36Sopenharmony_ci } 504062306a36Sopenharmony_ci } 504162306a36Sopenharmony_ci return E1000_SUCCESS; 504262306a36Sopenharmony_ci} 504362306a36Sopenharmony_ci 504462306a36Sopenharmony_ci/** 504562306a36Sopenharmony_ci * e1000_check_downshift - Check if Downshift occurred 504662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 504762306a36Sopenharmony_ci * 504862306a36Sopenharmony_ci * returns: - E1000_ERR_XXX 504962306a36Sopenharmony_ci * E1000_SUCCESS 505062306a36Sopenharmony_ci * 505162306a36Sopenharmony_ci * For phy's older than IGP, this function reads the Downshift bit in the Phy 505262306a36Sopenharmony_ci * Specific Status register. For IGP phy's, it reads the Downgrade bit in the 505362306a36Sopenharmony_ci * Link Health register. In IGP this bit is latched high, so the driver must 505462306a36Sopenharmony_ci * read it immediately after link is established. 505562306a36Sopenharmony_ci */ 505662306a36Sopenharmony_cistatic s32 e1000_check_downshift(struct e1000_hw *hw) 505762306a36Sopenharmony_ci{ 505862306a36Sopenharmony_ci s32 ret_val; 505962306a36Sopenharmony_ci u16 phy_data; 506062306a36Sopenharmony_ci 506162306a36Sopenharmony_ci if (hw->phy_type == e1000_phy_igp) { 506262306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, IGP01E1000_PHY_LINK_HEALTH, 506362306a36Sopenharmony_ci &phy_data); 506462306a36Sopenharmony_ci if (ret_val) 506562306a36Sopenharmony_ci return ret_val; 506662306a36Sopenharmony_ci 506762306a36Sopenharmony_ci hw->speed_downgraded = 506862306a36Sopenharmony_ci (phy_data & IGP01E1000_PLHR_SS_DOWNGRADE) ? 1 : 0; 506962306a36Sopenharmony_ci } else if (hw->phy_type == e1000_phy_m88) { 507062306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_SPEC_STATUS, 507162306a36Sopenharmony_ci &phy_data); 507262306a36Sopenharmony_ci if (ret_val) 507362306a36Sopenharmony_ci return ret_val; 507462306a36Sopenharmony_ci 507562306a36Sopenharmony_ci hw->speed_downgraded = (phy_data & M88E1000_PSSR_DOWNSHIFT) >> 507662306a36Sopenharmony_ci M88E1000_PSSR_DOWNSHIFT_SHIFT; 507762306a36Sopenharmony_ci } 507862306a36Sopenharmony_ci 507962306a36Sopenharmony_ci return E1000_SUCCESS; 508062306a36Sopenharmony_ci} 508162306a36Sopenharmony_ci 508262306a36Sopenharmony_cistatic const u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = { 508362306a36Sopenharmony_ci IGP01E1000_PHY_AGC_PARAM_A, 508462306a36Sopenharmony_ci IGP01E1000_PHY_AGC_PARAM_B, 508562306a36Sopenharmony_ci IGP01E1000_PHY_AGC_PARAM_C, 508662306a36Sopenharmony_ci IGP01E1000_PHY_AGC_PARAM_D 508762306a36Sopenharmony_ci}; 508862306a36Sopenharmony_ci 508962306a36Sopenharmony_cistatic s32 e1000_1000Mb_check_cable_length(struct e1000_hw *hw) 509062306a36Sopenharmony_ci{ 509162306a36Sopenharmony_ci u16 min_length, max_length; 509262306a36Sopenharmony_ci u16 phy_data, i; 509362306a36Sopenharmony_ci s32 ret_val; 509462306a36Sopenharmony_ci 509562306a36Sopenharmony_ci ret_val = e1000_get_cable_length(hw, &min_length, &max_length); 509662306a36Sopenharmony_ci if (ret_val) 509762306a36Sopenharmony_ci return ret_val; 509862306a36Sopenharmony_ci 509962306a36Sopenharmony_ci if (hw->dsp_config_state != e1000_dsp_config_enabled) 510062306a36Sopenharmony_ci return 0; 510162306a36Sopenharmony_ci 510262306a36Sopenharmony_ci if (min_length >= e1000_igp_cable_length_50) { 510362306a36Sopenharmony_ci for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 510462306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, dsp_reg_array[i], 510562306a36Sopenharmony_ci &phy_data); 510662306a36Sopenharmony_ci if (ret_val) 510762306a36Sopenharmony_ci return ret_val; 510862306a36Sopenharmony_ci 510962306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; 511062306a36Sopenharmony_ci 511162306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, dsp_reg_array[i], 511262306a36Sopenharmony_ci phy_data); 511362306a36Sopenharmony_ci if (ret_val) 511462306a36Sopenharmony_ci return ret_val; 511562306a36Sopenharmony_ci } 511662306a36Sopenharmony_ci hw->dsp_config_state = e1000_dsp_config_activated; 511762306a36Sopenharmony_ci } else { 511862306a36Sopenharmony_ci u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20; 511962306a36Sopenharmony_ci u32 idle_errs = 0; 512062306a36Sopenharmony_ci 512162306a36Sopenharmony_ci /* clear previous idle error counts */ 512262306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, &phy_data); 512362306a36Sopenharmony_ci if (ret_val) 512462306a36Sopenharmony_ci return ret_val; 512562306a36Sopenharmony_ci 512662306a36Sopenharmony_ci for (i = 0; i < ffe_idle_err_timeout; i++) { 512762306a36Sopenharmony_ci udelay(1000); 512862306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_1000T_STATUS, 512962306a36Sopenharmony_ci &phy_data); 513062306a36Sopenharmony_ci if (ret_val) 513162306a36Sopenharmony_ci return ret_val; 513262306a36Sopenharmony_ci 513362306a36Sopenharmony_ci idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT); 513462306a36Sopenharmony_ci if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) { 513562306a36Sopenharmony_ci hw->ffe_config_state = e1000_ffe_config_active; 513662306a36Sopenharmony_ci 513762306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 513862306a36Sopenharmony_ci IGP01E1000_PHY_DSP_FFE, 513962306a36Sopenharmony_ci IGP01E1000_PHY_DSP_FFE_CM_CP); 514062306a36Sopenharmony_ci if (ret_val) 514162306a36Sopenharmony_ci return ret_val; 514262306a36Sopenharmony_ci break; 514362306a36Sopenharmony_ci } 514462306a36Sopenharmony_ci 514562306a36Sopenharmony_ci if (idle_errs) 514662306a36Sopenharmony_ci ffe_idle_err_timeout = 514762306a36Sopenharmony_ci FFE_IDLE_ERR_COUNT_TIMEOUT_100; 514862306a36Sopenharmony_ci } 514962306a36Sopenharmony_ci } 515062306a36Sopenharmony_ci 515162306a36Sopenharmony_ci return 0; 515262306a36Sopenharmony_ci} 515362306a36Sopenharmony_ci 515462306a36Sopenharmony_ci/** 515562306a36Sopenharmony_ci * e1000_config_dsp_after_link_change 515662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 515762306a36Sopenharmony_ci * @link_up: was link up at the time this was called 515862306a36Sopenharmony_ci * 515962306a36Sopenharmony_ci * returns: - E1000_ERR_PHY if fail to read/write the PHY 516062306a36Sopenharmony_ci * E1000_SUCCESS at any other case. 516162306a36Sopenharmony_ci * 516262306a36Sopenharmony_ci * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a 516362306a36Sopenharmony_ci * gigabit link is achieved to improve link quality. 516462306a36Sopenharmony_ci */ 516562306a36Sopenharmony_ci 516662306a36Sopenharmony_cistatic s32 e1000_config_dsp_after_link_change(struct e1000_hw *hw, bool link_up) 516762306a36Sopenharmony_ci{ 516862306a36Sopenharmony_ci s32 ret_val; 516962306a36Sopenharmony_ci u16 phy_data, phy_saved_data, speed, duplex, i; 517062306a36Sopenharmony_ci 517162306a36Sopenharmony_ci if (hw->phy_type != e1000_phy_igp) 517262306a36Sopenharmony_ci return E1000_SUCCESS; 517362306a36Sopenharmony_ci 517462306a36Sopenharmony_ci if (link_up) { 517562306a36Sopenharmony_ci ret_val = e1000_get_speed_and_duplex(hw, &speed, &duplex); 517662306a36Sopenharmony_ci if (ret_val) { 517762306a36Sopenharmony_ci e_dbg("Error getting link speed and duplex\n"); 517862306a36Sopenharmony_ci return ret_val; 517962306a36Sopenharmony_ci } 518062306a36Sopenharmony_ci 518162306a36Sopenharmony_ci if (speed == SPEED_1000) { 518262306a36Sopenharmony_ci ret_val = e1000_1000Mb_check_cable_length(hw); 518362306a36Sopenharmony_ci if (ret_val) 518462306a36Sopenharmony_ci return ret_val; 518562306a36Sopenharmony_ci } 518662306a36Sopenharmony_ci } else { 518762306a36Sopenharmony_ci if (hw->dsp_config_state == e1000_dsp_config_activated) { 518862306a36Sopenharmony_ci /* Save off the current value of register 0x2F5B to be 518962306a36Sopenharmony_ci * restored at the end of the routines. 519062306a36Sopenharmony_ci */ 519162306a36Sopenharmony_ci ret_val = 519262306a36Sopenharmony_ci e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); 519362306a36Sopenharmony_ci 519462306a36Sopenharmony_ci if (ret_val) 519562306a36Sopenharmony_ci return ret_val; 519662306a36Sopenharmony_ci 519762306a36Sopenharmony_ci /* Disable the PHY transmitter */ 519862306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003); 519962306a36Sopenharmony_ci 520062306a36Sopenharmony_ci if (ret_val) 520162306a36Sopenharmony_ci return ret_val; 520262306a36Sopenharmony_ci 520362306a36Sopenharmony_ci msleep(20); 520462306a36Sopenharmony_ci 520562306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 0x0000, 520662306a36Sopenharmony_ci IGP01E1000_IEEE_FORCE_GIGA); 520762306a36Sopenharmony_ci if (ret_val) 520862306a36Sopenharmony_ci return ret_val; 520962306a36Sopenharmony_ci for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) { 521062306a36Sopenharmony_ci ret_val = 521162306a36Sopenharmony_ci e1000_read_phy_reg(hw, dsp_reg_array[i], 521262306a36Sopenharmony_ci &phy_data); 521362306a36Sopenharmony_ci if (ret_val) 521462306a36Sopenharmony_ci return ret_val; 521562306a36Sopenharmony_ci 521662306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX; 521762306a36Sopenharmony_ci phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS; 521862306a36Sopenharmony_ci 521962306a36Sopenharmony_ci ret_val = 522062306a36Sopenharmony_ci e1000_write_phy_reg(hw, dsp_reg_array[i], 522162306a36Sopenharmony_ci phy_data); 522262306a36Sopenharmony_ci if (ret_val) 522362306a36Sopenharmony_ci return ret_val; 522462306a36Sopenharmony_ci } 522562306a36Sopenharmony_ci 522662306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 0x0000, 522762306a36Sopenharmony_ci IGP01E1000_IEEE_RESTART_AUTONEG); 522862306a36Sopenharmony_ci if (ret_val) 522962306a36Sopenharmony_ci return ret_val; 523062306a36Sopenharmony_ci 523162306a36Sopenharmony_ci msleep(20); 523262306a36Sopenharmony_ci 523362306a36Sopenharmony_ci /* Now enable the transmitter */ 523462306a36Sopenharmony_ci ret_val = 523562306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); 523662306a36Sopenharmony_ci 523762306a36Sopenharmony_ci if (ret_val) 523862306a36Sopenharmony_ci return ret_val; 523962306a36Sopenharmony_ci 524062306a36Sopenharmony_ci hw->dsp_config_state = e1000_dsp_config_enabled; 524162306a36Sopenharmony_ci } 524262306a36Sopenharmony_ci 524362306a36Sopenharmony_ci if (hw->ffe_config_state == e1000_ffe_config_active) { 524462306a36Sopenharmony_ci /* Save off the current value of register 0x2F5B to be 524562306a36Sopenharmony_ci * restored at the end of the routines. 524662306a36Sopenharmony_ci */ 524762306a36Sopenharmony_ci ret_val = 524862306a36Sopenharmony_ci e1000_read_phy_reg(hw, 0x2F5B, &phy_saved_data); 524962306a36Sopenharmony_ci 525062306a36Sopenharmony_ci if (ret_val) 525162306a36Sopenharmony_ci return ret_val; 525262306a36Sopenharmony_ci 525362306a36Sopenharmony_ci /* Disable the PHY transmitter */ 525462306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 0x2F5B, 0x0003); 525562306a36Sopenharmony_ci 525662306a36Sopenharmony_ci if (ret_val) 525762306a36Sopenharmony_ci return ret_val; 525862306a36Sopenharmony_ci 525962306a36Sopenharmony_ci msleep(20); 526062306a36Sopenharmony_ci 526162306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 0x0000, 526262306a36Sopenharmony_ci IGP01E1000_IEEE_FORCE_GIGA); 526362306a36Sopenharmony_ci if (ret_val) 526462306a36Sopenharmony_ci return ret_val; 526562306a36Sopenharmony_ci ret_val = 526662306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_PHY_DSP_FFE, 526762306a36Sopenharmony_ci IGP01E1000_PHY_DSP_FFE_DEFAULT); 526862306a36Sopenharmony_ci if (ret_val) 526962306a36Sopenharmony_ci return ret_val; 527062306a36Sopenharmony_ci 527162306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, 0x0000, 527262306a36Sopenharmony_ci IGP01E1000_IEEE_RESTART_AUTONEG); 527362306a36Sopenharmony_ci if (ret_val) 527462306a36Sopenharmony_ci return ret_val; 527562306a36Sopenharmony_ci 527662306a36Sopenharmony_ci msleep(20); 527762306a36Sopenharmony_ci 527862306a36Sopenharmony_ci /* Now enable the transmitter */ 527962306a36Sopenharmony_ci ret_val = 528062306a36Sopenharmony_ci e1000_write_phy_reg(hw, 0x2F5B, phy_saved_data); 528162306a36Sopenharmony_ci 528262306a36Sopenharmony_ci if (ret_val) 528362306a36Sopenharmony_ci return ret_val; 528462306a36Sopenharmony_ci 528562306a36Sopenharmony_ci hw->ffe_config_state = e1000_ffe_config_enabled; 528662306a36Sopenharmony_ci } 528762306a36Sopenharmony_ci } 528862306a36Sopenharmony_ci return E1000_SUCCESS; 528962306a36Sopenharmony_ci} 529062306a36Sopenharmony_ci 529162306a36Sopenharmony_ci/** 529262306a36Sopenharmony_ci * e1000_set_phy_mode - Set PHY to class A mode 529362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 529462306a36Sopenharmony_ci * 529562306a36Sopenharmony_ci * Assumes the following operations will follow to enable the new class mode. 529662306a36Sopenharmony_ci * 1. Do a PHY soft reset 529762306a36Sopenharmony_ci * 2. Restart auto-negotiation or force link. 529862306a36Sopenharmony_ci */ 529962306a36Sopenharmony_cistatic s32 e1000_set_phy_mode(struct e1000_hw *hw) 530062306a36Sopenharmony_ci{ 530162306a36Sopenharmony_ci s32 ret_val; 530262306a36Sopenharmony_ci u16 eeprom_data; 530362306a36Sopenharmony_ci 530462306a36Sopenharmony_ci if ((hw->mac_type == e1000_82545_rev_3) && 530562306a36Sopenharmony_ci (hw->media_type == e1000_media_type_copper)) { 530662306a36Sopenharmony_ci ret_val = 530762306a36Sopenharmony_ci e1000_read_eeprom(hw, EEPROM_PHY_CLASS_WORD, 1, 530862306a36Sopenharmony_ci &eeprom_data); 530962306a36Sopenharmony_ci if (ret_val) 531062306a36Sopenharmony_ci return ret_val; 531162306a36Sopenharmony_ci 531262306a36Sopenharmony_ci if ((eeprom_data != EEPROM_RESERVED_WORD) && 531362306a36Sopenharmony_ci (eeprom_data & EEPROM_PHY_CLASS_A)) { 531462306a36Sopenharmony_ci ret_val = 531562306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 531662306a36Sopenharmony_ci 0x000B); 531762306a36Sopenharmony_ci if (ret_val) 531862306a36Sopenharmony_ci return ret_val; 531962306a36Sopenharmony_ci ret_val = 532062306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 532162306a36Sopenharmony_ci 0x8104); 532262306a36Sopenharmony_ci if (ret_val) 532362306a36Sopenharmony_ci return ret_val; 532462306a36Sopenharmony_ci 532562306a36Sopenharmony_ci hw->phy_reset_disable = false; 532662306a36Sopenharmony_ci } 532762306a36Sopenharmony_ci } 532862306a36Sopenharmony_ci 532962306a36Sopenharmony_ci return E1000_SUCCESS; 533062306a36Sopenharmony_ci} 533162306a36Sopenharmony_ci 533262306a36Sopenharmony_ci/** 533362306a36Sopenharmony_ci * e1000_set_d3_lplu_state - set d3 link power state 533462306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 533562306a36Sopenharmony_ci * @active: true to enable lplu false to disable lplu. 533662306a36Sopenharmony_ci * 533762306a36Sopenharmony_ci * This function sets the lplu state according to the active flag. When 533862306a36Sopenharmony_ci * activating lplu this function also disables smart speed and vise versa. 533962306a36Sopenharmony_ci * lplu will not be activated unless the device autonegotiation advertisement 534062306a36Sopenharmony_ci * meets standards of either 10 or 10/100 or 10/100/1000 at all duplexes. 534162306a36Sopenharmony_ci * 534262306a36Sopenharmony_ci * returns: - E1000_ERR_PHY if fail to read/write the PHY 534362306a36Sopenharmony_ci * E1000_SUCCESS at any other case. 534462306a36Sopenharmony_ci */ 534562306a36Sopenharmony_cistatic s32 e1000_set_d3_lplu_state(struct e1000_hw *hw, bool active) 534662306a36Sopenharmony_ci{ 534762306a36Sopenharmony_ci s32 ret_val; 534862306a36Sopenharmony_ci u16 phy_data; 534962306a36Sopenharmony_ci 535062306a36Sopenharmony_ci if (hw->phy_type != e1000_phy_igp) 535162306a36Sopenharmony_ci return E1000_SUCCESS; 535262306a36Sopenharmony_ci 535362306a36Sopenharmony_ci /* During driver activity LPLU should not be used or it will attain link 535462306a36Sopenharmony_ci * from the lowest speeds starting from 10Mbps. The capability is used 535562306a36Sopenharmony_ci * for Dx transitions and states 535662306a36Sopenharmony_ci */ 535762306a36Sopenharmony_ci if (hw->mac_type == e1000_82541_rev_2 || 535862306a36Sopenharmony_ci hw->mac_type == e1000_82547_rev_2) { 535962306a36Sopenharmony_ci ret_val = 536062306a36Sopenharmony_ci e1000_read_phy_reg(hw, IGP01E1000_GMII_FIFO, &phy_data); 536162306a36Sopenharmony_ci if (ret_val) 536262306a36Sopenharmony_ci return ret_val; 536362306a36Sopenharmony_ci } 536462306a36Sopenharmony_ci 536562306a36Sopenharmony_ci if (!active) { 536662306a36Sopenharmony_ci if (hw->mac_type == e1000_82541_rev_2 || 536762306a36Sopenharmony_ci hw->mac_type == e1000_82547_rev_2) { 536862306a36Sopenharmony_ci phy_data &= ~IGP01E1000_GMII_FLEX_SPD; 536962306a36Sopenharmony_ci ret_val = 537062306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, 537162306a36Sopenharmony_ci phy_data); 537262306a36Sopenharmony_ci if (ret_val) 537362306a36Sopenharmony_ci return ret_val; 537462306a36Sopenharmony_ci } 537562306a36Sopenharmony_ci 537662306a36Sopenharmony_ci /* LPLU and SmartSpeed are mutually exclusive. LPLU is used 537762306a36Sopenharmony_ci * during Dx states where the power conservation is most 537862306a36Sopenharmony_ci * important. During driver activity we should enable 537962306a36Sopenharmony_ci * SmartSpeed, so performance is maintained. 538062306a36Sopenharmony_ci */ 538162306a36Sopenharmony_ci if (hw->smart_speed == e1000_smart_speed_on) { 538262306a36Sopenharmony_ci ret_val = 538362306a36Sopenharmony_ci e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 538462306a36Sopenharmony_ci &phy_data); 538562306a36Sopenharmony_ci if (ret_val) 538662306a36Sopenharmony_ci return ret_val; 538762306a36Sopenharmony_ci 538862306a36Sopenharmony_ci phy_data |= IGP01E1000_PSCFR_SMART_SPEED; 538962306a36Sopenharmony_ci ret_val = 539062306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 539162306a36Sopenharmony_ci phy_data); 539262306a36Sopenharmony_ci if (ret_val) 539362306a36Sopenharmony_ci return ret_val; 539462306a36Sopenharmony_ci } else if (hw->smart_speed == e1000_smart_speed_off) { 539562306a36Sopenharmony_ci ret_val = 539662306a36Sopenharmony_ci e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 539762306a36Sopenharmony_ci &phy_data); 539862306a36Sopenharmony_ci if (ret_val) 539962306a36Sopenharmony_ci return ret_val; 540062306a36Sopenharmony_ci 540162306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; 540262306a36Sopenharmony_ci ret_val = 540362306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 540462306a36Sopenharmony_ci phy_data); 540562306a36Sopenharmony_ci if (ret_val) 540662306a36Sopenharmony_ci return ret_val; 540762306a36Sopenharmony_ci } 540862306a36Sopenharmony_ci } else if ((hw->autoneg_advertised == AUTONEG_ADVERTISE_SPEED_DEFAULT) || 540962306a36Sopenharmony_ci (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_ALL) || 541062306a36Sopenharmony_ci (hw->autoneg_advertised == AUTONEG_ADVERTISE_10_100_ALL)) { 541162306a36Sopenharmony_ci if (hw->mac_type == e1000_82541_rev_2 || 541262306a36Sopenharmony_ci hw->mac_type == e1000_82547_rev_2) { 541362306a36Sopenharmony_ci phy_data |= IGP01E1000_GMII_FLEX_SPD; 541462306a36Sopenharmony_ci ret_val = 541562306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_GMII_FIFO, 541662306a36Sopenharmony_ci phy_data); 541762306a36Sopenharmony_ci if (ret_val) 541862306a36Sopenharmony_ci return ret_val; 541962306a36Sopenharmony_ci } 542062306a36Sopenharmony_ci 542162306a36Sopenharmony_ci /* When LPLU is enabled we should disable SmartSpeed */ 542262306a36Sopenharmony_ci ret_val = 542362306a36Sopenharmony_ci e1000_read_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 542462306a36Sopenharmony_ci &phy_data); 542562306a36Sopenharmony_ci if (ret_val) 542662306a36Sopenharmony_ci return ret_val; 542762306a36Sopenharmony_ci 542862306a36Sopenharmony_ci phy_data &= ~IGP01E1000_PSCFR_SMART_SPEED; 542962306a36Sopenharmony_ci ret_val = 543062306a36Sopenharmony_ci e1000_write_phy_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 543162306a36Sopenharmony_ci phy_data); 543262306a36Sopenharmony_ci if (ret_val) 543362306a36Sopenharmony_ci return ret_val; 543462306a36Sopenharmony_ci } 543562306a36Sopenharmony_ci return E1000_SUCCESS; 543662306a36Sopenharmony_ci} 543762306a36Sopenharmony_ci 543862306a36Sopenharmony_ci/** 543962306a36Sopenharmony_ci * e1000_set_vco_speed 544062306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 544162306a36Sopenharmony_ci * 544262306a36Sopenharmony_ci * Change VCO speed register to improve Bit Error Rate performance of SERDES. 544362306a36Sopenharmony_ci */ 544462306a36Sopenharmony_cistatic s32 e1000_set_vco_speed(struct e1000_hw *hw) 544562306a36Sopenharmony_ci{ 544662306a36Sopenharmony_ci s32 ret_val; 544762306a36Sopenharmony_ci u16 default_page = 0; 544862306a36Sopenharmony_ci u16 phy_data; 544962306a36Sopenharmony_ci 545062306a36Sopenharmony_ci switch (hw->mac_type) { 545162306a36Sopenharmony_ci case e1000_82545_rev_3: 545262306a36Sopenharmony_ci case e1000_82546_rev_3: 545362306a36Sopenharmony_ci break; 545462306a36Sopenharmony_ci default: 545562306a36Sopenharmony_ci return E1000_SUCCESS; 545662306a36Sopenharmony_ci } 545762306a36Sopenharmony_ci 545862306a36Sopenharmony_ci /* Set PHY register 30, page 5, bit 8 to 0 */ 545962306a36Sopenharmony_ci 546062306a36Sopenharmony_ci ret_val = 546162306a36Sopenharmony_ci e1000_read_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, &default_page); 546262306a36Sopenharmony_ci if (ret_val) 546362306a36Sopenharmony_ci return ret_val; 546462306a36Sopenharmony_ci 546562306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0005); 546662306a36Sopenharmony_ci if (ret_val) 546762306a36Sopenharmony_ci return ret_val; 546862306a36Sopenharmony_ci 546962306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); 547062306a36Sopenharmony_ci if (ret_val) 547162306a36Sopenharmony_ci return ret_val; 547262306a36Sopenharmony_ci 547362306a36Sopenharmony_ci phy_data &= ~M88E1000_PHY_VCO_REG_BIT8; 547462306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); 547562306a36Sopenharmony_ci if (ret_val) 547662306a36Sopenharmony_ci return ret_val; 547762306a36Sopenharmony_ci 547862306a36Sopenharmony_ci /* Set PHY register 30, page 4, bit 11 to 1 */ 547962306a36Sopenharmony_ci 548062306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0004); 548162306a36Sopenharmony_ci if (ret_val) 548262306a36Sopenharmony_ci return ret_val; 548362306a36Sopenharmony_ci 548462306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, &phy_data); 548562306a36Sopenharmony_ci if (ret_val) 548662306a36Sopenharmony_ci return ret_val; 548762306a36Sopenharmony_ci 548862306a36Sopenharmony_ci phy_data |= M88E1000_PHY_VCO_REG_BIT11; 548962306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, phy_data); 549062306a36Sopenharmony_ci if (ret_val) 549162306a36Sopenharmony_ci return ret_val; 549262306a36Sopenharmony_ci 549362306a36Sopenharmony_ci ret_val = 549462306a36Sopenharmony_ci e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, default_page); 549562306a36Sopenharmony_ci if (ret_val) 549662306a36Sopenharmony_ci return ret_val; 549762306a36Sopenharmony_ci 549862306a36Sopenharmony_ci return E1000_SUCCESS; 549962306a36Sopenharmony_ci} 550062306a36Sopenharmony_ci 550162306a36Sopenharmony_ci/** 550262306a36Sopenharmony_ci * e1000_enable_mng_pass_thru - check for bmc pass through 550362306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 550462306a36Sopenharmony_ci * 550562306a36Sopenharmony_ci * Verifies the hardware needs to allow ARPs to be processed by the host 550662306a36Sopenharmony_ci * returns: - true/false 550762306a36Sopenharmony_ci */ 550862306a36Sopenharmony_ciu32 e1000_enable_mng_pass_thru(struct e1000_hw *hw) 550962306a36Sopenharmony_ci{ 551062306a36Sopenharmony_ci u32 manc; 551162306a36Sopenharmony_ci 551262306a36Sopenharmony_ci if (hw->asf_firmware_present) { 551362306a36Sopenharmony_ci manc = er32(MANC); 551462306a36Sopenharmony_ci 551562306a36Sopenharmony_ci if (!(manc & E1000_MANC_RCV_TCO_EN) || 551662306a36Sopenharmony_ci !(manc & E1000_MANC_EN_MAC_ADDR_FILTER)) 551762306a36Sopenharmony_ci return false; 551862306a36Sopenharmony_ci if ((manc & E1000_MANC_SMBUS_EN) && !(manc & E1000_MANC_ASF_EN)) 551962306a36Sopenharmony_ci return true; 552062306a36Sopenharmony_ci } 552162306a36Sopenharmony_ci return false; 552262306a36Sopenharmony_ci} 552362306a36Sopenharmony_ci 552462306a36Sopenharmony_cistatic s32 e1000_polarity_reversal_workaround(struct e1000_hw *hw) 552562306a36Sopenharmony_ci{ 552662306a36Sopenharmony_ci s32 ret_val; 552762306a36Sopenharmony_ci u16 mii_status_reg; 552862306a36Sopenharmony_ci u16 i; 552962306a36Sopenharmony_ci 553062306a36Sopenharmony_ci /* Polarity reversal workaround for forced 10F/10H links. */ 553162306a36Sopenharmony_ci 553262306a36Sopenharmony_ci /* Disable the transmitter on the PHY */ 553362306a36Sopenharmony_ci 553462306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); 553562306a36Sopenharmony_ci if (ret_val) 553662306a36Sopenharmony_ci return ret_val; 553762306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); 553862306a36Sopenharmony_ci if (ret_val) 553962306a36Sopenharmony_ci return ret_val; 554062306a36Sopenharmony_ci 554162306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); 554262306a36Sopenharmony_ci if (ret_val) 554362306a36Sopenharmony_ci return ret_val; 554462306a36Sopenharmony_ci 554562306a36Sopenharmony_ci /* This loop will early-out if the NO link condition has been met. */ 554662306a36Sopenharmony_ci for (i = PHY_FORCE_TIME; i > 0; i--) { 554762306a36Sopenharmony_ci /* Read the MII Status Register and wait for Link Status bit 554862306a36Sopenharmony_ci * to be clear. 554962306a36Sopenharmony_ci */ 555062306a36Sopenharmony_ci 555162306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 555262306a36Sopenharmony_ci if (ret_val) 555362306a36Sopenharmony_ci return ret_val; 555462306a36Sopenharmony_ci 555562306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 555662306a36Sopenharmony_ci if (ret_val) 555762306a36Sopenharmony_ci return ret_val; 555862306a36Sopenharmony_ci 555962306a36Sopenharmony_ci if ((mii_status_reg & ~MII_SR_LINK_STATUS) == 0) 556062306a36Sopenharmony_ci break; 556162306a36Sopenharmony_ci msleep(100); 556262306a36Sopenharmony_ci } 556362306a36Sopenharmony_ci 556462306a36Sopenharmony_ci /* Recommended delay time after link has been lost */ 556562306a36Sopenharmony_ci msleep(1000); 556662306a36Sopenharmony_ci 556762306a36Sopenharmony_ci /* Now we will re-enable th transmitter on the PHY */ 556862306a36Sopenharmony_ci 556962306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); 557062306a36Sopenharmony_ci if (ret_val) 557162306a36Sopenharmony_ci return ret_val; 557262306a36Sopenharmony_ci msleep(50); 557362306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); 557462306a36Sopenharmony_ci if (ret_val) 557562306a36Sopenharmony_ci return ret_val; 557662306a36Sopenharmony_ci msleep(50); 557762306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); 557862306a36Sopenharmony_ci if (ret_val) 557962306a36Sopenharmony_ci return ret_val; 558062306a36Sopenharmony_ci msleep(50); 558162306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); 558262306a36Sopenharmony_ci if (ret_val) 558362306a36Sopenharmony_ci return ret_val; 558462306a36Sopenharmony_ci 558562306a36Sopenharmony_ci ret_val = e1000_write_phy_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); 558662306a36Sopenharmony_ci if (ret_val) 558762306a36Sopenharmony_ci return ret_val; 558862306a36Sopenharmony_ci 558962306a36Sopenharmony_ci /* This loop will early-out if the link condition has been met. */ 559062306a36Sopenharmony_ci for (i = PHY_FORCE_TIME; i > 0; i--) { 559162306a36Sopenharmony_ci /* Read the MII Status Register and wait for Link Status bit 559262306a36Sopenharmony_ci * to be set. 559362306a36Sopenharmony_ci */ 559462306a36Sopenharmony_ci 559562306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 559662306a36Sopenharmony_ci if (ret_val) 559762306a36Sopenharmony_ci return ret_val; 559862306a36Sopenharmony_ci 559962306a36Sopenharmony_ci ret_val = e1000_read_phy_reg(hw, PHY_STATUS, &mii_status_reg); 560062306a36Sopenharmony_ci if (ret_val) 560162306a36Sopenharmony_ci return ret_val; 560262306a36Sopenharmony_ci 560362306a36Sopenharmony_ci if (mii_status_reg & MII_SR_LINK_STATUS) 560462306a36Sopenharmony_ci break; 560562306a36Sopenharmony_ci msleep(100); 560662306a36Sopenharmony_ci } 560762306a36Sopenharmony_ci return E1000_SUCCESS; 560862306a36Sopenharmony_ci} 560962306a36Sopenharmony_ci 561062306a36Sopenharmony_ci/** 561162306a36Sopenharmony_ci * e1000_get_auto_rd_done 561262306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 561362306a36Sopenharmony_ci * 561462306a36Sopenharmony_ci * Check for EEPROM Auto Read bit done. 561562306a36Sopenharmony_ci * returns: - E1000_ERR_RESET if fail to reset MAC 561662306a36Sopenharmony_ci * E1000_SUCCESS at any other case. 561762306a36Sopenharmony_ci */ 561862306a36Sopenharmony_cistatic s32 e1000_get_auto_rd_done(struct e1000_hw *hw) 561962306a36Sopenharmony_ci{ 562062306a36Sopenharmony_ci msleep(5); 562162306a36Sopenharmony_ci return E1000_SUCCESS; 562262306a36Sopenharmony_ci} 562362306a36Sopenharmony_ci 562462306a36Sopenharmony_ci/** 562562306a36Sopenharmony_ci * e1000_get_phy_cfg_done 562662306a36Sopenharmony_ci * @hw: Struct containing variables accessed by shared code 562762306a36Sopenharmony_ci * 562862306a36Sopenharmony_ci * Checks if the PHY configuration is done 562962306a36Sopenharmony_ci * returns: - E1000_ERR_RESET if fail to reset MAC 563062306a36Sopenharmony_ci * E1000_SUCCESS at any other case. 563162306a36Sopenharmony_ci */ 563262306a36Sopenharmony_cistatic s32 e1000_get_phy_cfg_done(struct e1000_hw *hw) 563362306a36Sopenharmony_ci{ 563462306a36Sopenharmony_ci msleep(10); 563562306a36Sopenharmony_ci return E1000_SUCCESS; 563662306a36Sopenharmony_ci} 5637