18cfa0ad2SJack F Vogel /****************************************************************************** 2*7282444bSPedro F. Giffuni SPDX-License-Identifier: BSD-3-Clause 38cfa0ad2SJack F Vogel 47c669ab6SSean Bruno Copyright (c) 2001-2015, Intel Corporation 58cfa0ad2SJack F Vogel All rights reserved. 68cfa0ad2SJack F Vogel 78cfa0ad2SJack F Vogel Redistribution and use in source and binary forms, with or without 88cfa0ad2SJack F Vogel modification, are permitted provided that the following conditions are met: 98cfa0ad2SJack F Vogel 108cfa0ad2SJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 118cfa0ad2SJack F Vogel this list of conditions and the following disclaimer. 128cfa0ad2SJack F Vogel 138cfa0ad2SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 148cfa0ad2SJack F Vogel notice, this list of conditions and the following disclaimer in the 158cfa0ad2SJack F Vogel documentation and/or other materials provided with the distribution. 168cfa0ad2SJack F Vogel 178cfa0ad2SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 188cfa0ad2SJack F Vogel contributors may be used to endorse or promote products derived from 198cfa0ad2SJack F Vogel this software without specific prior written permission. 208cfa0ad2SJack F Vogel 218cfa0ad2SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 228cfa0ad2SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 238cfa0ad2SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 248cfa0ad2SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 258cfa0ad2SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 268cfa0ad2SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 278cfa0ad2SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 288cfa0ad2SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 298cfa0ad2SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 308cfa0ad2SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 318cfa0ad2SJack F Vogel POSSIBILITY OF SUCH DAMAGE. 328cfa0ad2SJack F Vogel 338cfa0ad2SJack F Vogel ******************************************************************************/ 348cfa0ad2SJack F Vogel /*$FreeBSD$*/ 358cfa0ad2SJack F Vogel 36daf9197cSJack F Vogel /* 37daf9197cSJack F Vogel * 82543GC Gigabit Ethernet Controller (Fiber) 38daf9197cSJack F Vogel * 82543GC Gigabit Ethernet Controller (Copper) 39daf9197cSJack F Vogel * 82544EI Gigabit Ethernet Controller (Copper) 40daf9197cSJack F Vogel * 82544EI Gigabit Ethernet Controller (Fiber) 41daf9197cSJack F Vogel * 82544GC Gigabit Ethernet Controller (Copper) 42daf9197cSJack F Vogel * 82544GC Gigabit Ethernet Controller (LOM) 438cfa0ad2SJack F Vogel */ 448cfa0ad2SJack F Vogel 458cfa0ad2SJack F Vogel #include "e1000_api.h" 468cfa0ad2SJack F Vogel 478cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82543(struct e1000_hw *hw); 488cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw); 498cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82543(struct e1000_hw *hw); 508cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, 518cfa0ad2SJack F Vogel u16 *data); 528cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, 538cfa0ad2SJack F Vogel u16 data); 548cfa0ad2SJack F Vogel static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw); 558cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw); 568cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82543(struct e1000_hw *hw); 578cfa0ad2SJack F Vogel static s32 e1000_init_hw_82543(struct e1000_hw *hw); 588cfa0ad2SJack F Vogel static s32 e1000_setup_link_82543(struct e1000_hw *hw); 598cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw); 608cfa0ad2SJack F Vogel static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw); 618cfa0ad2SJack F Vogel static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw); 628cfa0ad2SJack F Vogel static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw); 638cfa0ad2SJack F Vogel static s32 e1000_led_on_82543(struct e1000_hw *hw); 648cfa0ad2SJack F Vogel static s32 e1000_led_off_82543(struct e1000_hw *hw); 658cfa0ad2SJack F Vogel static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, 668cfa0ad2SJack F Vogel u32 value); 678cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw); 688cfa0ad2SJack F Vogel static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw); 698cfa0ad2SJack F Vogel static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw); 708cfa0ad2SJack F Vogel static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl); 718cfa0ad2SJack F Vogel static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw); 728cfa0ad2SJack F Vogel static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl); 738cfa0ad2SJack F Vogel static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw); 748cfa0ad2SJack F Vogel static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, 758cfa0ad2SJack F Vogel u16 count); 768cfa0ad2SJack F Vogel static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw); 778cfa0ad2SJack F Vogel static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state); 7874dbc418SJack F Vogel static s32 e1000_read_mac_addr_82543(struct e1000_hw *hw); 7974dbc418SJack F Vogel 808cfa0ad2SJack F Vogel 818cfa0ad2SJack F Vogel /** 828cfa0ad2SJack F Vogel * e1000_init_phy_params_82543 - Init PHY func ptrs. 838cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 848cfa0ad2SJack F Vogel **/ 858cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82543(struct e1000_hw *hw) 868cfa0ad2SJack F Vogel { 878cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 888cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 898cfa0ad2SJack F Vogel 908cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_82543"); 918cfa0ad2SJack F Vogel 928cfa0ad2SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) { 938cfa0ad2SJack F Vogel phy->type = e1000_phy_none; 948cfa0ad2SJack F Vogel goto out; 958cfa0ad2SJack F Vogel } else { 968cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper; 978cfa0ad2SJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper; 988cfa0ad2SJack F Vogel } 998cfa0ad2SJack F Vogel 1008cfa0ad2SJack F Vogel phy->addr = 1; 1018cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 1028cfa0ad2SJack F Vogel phy->reset_delay_us = 10000; 1038cfa0ad2SJack F Vogel phy->type = e1000_phy_m88; 1048cfa0ad2SJack F Vogel 1058cfa0ad2SJack F Vogel /* Function Pointers */ 1068cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 1078cfa0ad2SJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic; 1088cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_82543; 1098cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88; 1108cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_generic; 1118cfa0ad2SJack F Vogel phy->ops.read_reg = (hw->mac.type == e1000_82543) 1128cfa0ad2SJack F Vogel ? e1000_read_phy_reg_82543 1138cfa0ad2SJack F Vogel : e1000_read_phy_reg_m88; 1148cfa0ad2SJack F Vogel phy->ops.reset = (hw->mac.type == e1000_82543) 1158cfa0ad2SJack F Vogel ? e1000_phy_hw_reset_82543 1168cfa0ad2SJack F Vogel : e1000_phy_hw_reset_generic; 1178cfa0ad2SJack F Vogel phy->ops.write_reg = (hw->mac.type == e1000_82543) 1188cfa0ad2SJack F Vogel ? e1000_write_phy_reg_82543 1198cfa0ad2SJack F Vogel : e1000_write_phy_reg_m88; 1208cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 1218cfa0ad2SJack F Vogel 1228cfa0ad2SJack F Vogel /* 1238cfa0ad2SJack F Vogel * The external PHY of the 82543 can be in a funky state. 1248cfa0ad2SJack F Vogel * Resetting helps us read the PHY registers for acquiring 1258cfa0ad2SJack F Vogel * the PHY ID. 1268cfa0ad2SJack F Vogel */ 1278cfa0ad2SJack F Vogel if (!e1000_init_phy_disabled_82543(hw)) { 1288cfa0ad2SJack F Vogel ret_val = phy->ops.reset(hw); 1298cfa0ad2SJack F Vogel if (ret_val) { 1308cfa0ad2SJack F Vogel DEBUGOUT("Resetting PHY during init failed.\n"); 1318cfa0ad2SJack F Vogel goto out; 1328cfa0ad2SJack F Vogel } 1338cfa0ad2SJack F Vogel msec_delay(20); 1348cfa0ad2SJack F Vogel } 1358cfa0ad2SJack F Vogel 1368cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw); 1378cfa0ad2SJack F Vogel if (ret_val) 1388cfa0ad2SJack F Vogel goto out; 1398cfa0ad2SJack F Vogel 1408cfa0ad2SJack F Vogel /* Verify phy id */ 1418cfa0ad2SJack F Vogel switch (hw->mac.type) { 1428cfa0ad2SJack F Vogel case e1000_82543: 1438cfa0ad2SJack F Vogel if (phy->id != M88E1000_E_PHY_ID) { 1448cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 1458cfa0ad2SJack F Vogel goto out; 1468cfa0ad2SJack F Vogel } 1478cfa0ad2SJack F Vogel break; 1488cfa0ad2SJack F Vogel case e1000_82544: 1498cfa0ad2SJack F Vogel if (phy->id != M88E1000_I_PHY_ID) { 1508cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 1518cfa0ad2SJack F Vogel goto out; 1528cfa0ad2SJack F Vogel } 1538cfa0ad2SJack F Vogel break; 1548cfa0ad2SJack F Vogel default: 1558cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 1568cfa0ad2SJack F Vogel goto out; 1578cfa0ad2SJack F Vogel break; 1588cfa0ad2SJack F Vogel } 1598cfa0ad2SJack F Vogel 1608cfa0ad2SJack F Vogel out: 1618cfa0ad2SJack F Vogel return ret_val; 1628cfa0ad2SJack F Vogel } 1638cfa0ad2SJack F Vogel 1648cfa0ad2SJack F Vogel /** 1658cfa0ad2SJack F Vogel * e1000_init_nvm_params_82543 - Init NVM func ptrs. 1668cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 1678cfa0ad2SJack F Vogel **/ 1688cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_82543(struct e1000_hw *hw) 1698cfa0ad2SJack F Vogel { 1708cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 1718cfa0ad2SJack F Vogel 1728cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_82543"); 1738cfa0ad2SJack F Vogel 1748cfa0ad2SJack F Vogel nvm->type = e1000_nvm_eeprom_microwire; 1758cfa0ad2SJack F Vogel nvm->word_size = 64; 1768cfa0ad2SJack F Vogel nvm->delay_usec = 50; 1778cfa0ad2SJack F Vogel nvm->address_bits = 6; 1788cfa0ad2SJack F Vogel nvm->opcode_bits = 3; 1798cfa0ad2SJack F Vogel 1808cfa0ad2SJack F Vogel /* Function Pointers */ 1818cfa0ad2SJack F Vogel nvm->ops.read = e1000_read_nvm_microwire; 1828cfa0ad2SJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_generic; 1838cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_generic; 1848cfa0ad2SJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_generic; 1858cfa0ad2SJack F Vogel nvm->ops.write = e1000_write_nvm_microwire; 1868cfa0ad2SJack F Vogel 1878cfa0ad2SJack F Vogel return E1000_SUCCESS; 1888cfa0ad2SJack F Vogel } 1898cfa0ad2SJack F Vogel 1908cfa0ad2SJack F Vogel /** 1918cfa0ad2SJack F Vogel * e1000_init_mac_params_82543 - Init MAC func ptrs. 1928cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 1938cfa0ad2SJack F Vogel **/ 1948cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82543(struct e1000_hw *hw) 1958cfa0ad2SJack F Vogel { 1968cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 1978cfa0ad2SJack F Vogel 1988cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_mac_params_82543"); 1998cfa0ad2SJack F Vogel 2008cfa0ad2SJack F Vogel /* Set media type */ 2018cfa0ad2SJack F Vogel switch (hw->device_id) { 2028cfa0ad2SJack F Vogel case E1000_DEV_ID_82543GC_FIBER: 2038cfa0ad2SJack F Vogel case E1000_DEV_ID_82544EI_FIBER: 2048cfa0ad2SJack F Vogel hw->phy.media_type = e1000_media_type_fiber; 2058cfa0ad2SJack F Vogel break; 2068cfa0ad2SJack F Vogel default: 2078cfa0ad2SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 2088cfa0ad2SJack F Vogel break; 2098cfa0ad2SJack F Vogel } 2108cfa0ad2SJack F Vogel 2118cfa0ad2SJack F Vogel /* Set mta register count */ 2128cfa0ad2SJack F Vogel mac->mta_reg_count = 128; 2138cfa0ad2SJack F Vogel /* Set rar entry count */ 2148cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES; 2158cfa0ad2SJack F Vogel 2168cfa0ad2SJack F Vogel /* Function pointers */ 2178cfa0ad2SJack F Vogel 2188cfa0ad2SJack F Vogel /* bus type/speed/width */ 2198cfa0ad2SJack F Vogel mac->ops.get_bus_info = e1000_get_bus_info_pci_generic; 220daf9197cSJack F Vogel /* function id */ 221daf9197cSJack F Vogel mac->ops.set_lan_id = e1000_set_lan_id_multi_port_pci; 2228cfa0ad2SJack F Vogel /* reset */ 2238cfa0ad2SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82543; 2248cfa0ad2SJack F Vogel /* hw initialization */ 2258cfa0ad2SJack F Vogel mac->ops.init_hw = e1000_init_hw_82543; 2268cfa0ad2SJack F Vogel /* link setup */ 2278cfa0ad2SJack F Vogel mac->ops.setup_link = e1000_setup_link_82543; 2288cfa0ad2SJack F Vogel /* physical interface setup */ 2298cfa0ad2SJack F Vogel mac->ops.setup_physical_interface = 2308cfa0ad2SJack F Vogel (hw->phy.media_type == e1000_media_type_copper) 23148600901SSean Bruno ? e1000_setup_copper_link_82543 : e1000_setup_fiber_link_82543; 2328cfa0ad2SJack F Vogel /* check for link */ 2338cfa0ad2SJack F Vogel mac->ops.check_for_link = 2348cfa0ad2SJack F Vogel (hw->phy.media_type == e1000_media_type_copper) 2358cfa0ad2SJack F Vogel ? e1000_check_for_copper_link_82543 2368cfa0ad2SJack F Vogel : e1000_check_for_fiber_link_82543; 2378cfa0ad2SJack F Vogel /* link info */ 2388cfa0ad2SJack F Vogel mac->ops.get_link_up_info = 2398cfa0ad2SJack F Vogel (hw->phy.media_type == e1000_media_type_copper) 2408cfa0ad2SJack F Vogel ? e1000_get_speed_and_duplex_copper_generic 2418cfa0ad2SJack F Vogel : e1000_get_speed_and_duplex_fiber_serdes_generic; 2428cfa0ad2SJack F Vogel /* multicast address update */ 2438cfa0ad2SJack F Vogel mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; 2448cfa0ad2SJack F Vogel /* writing VFTA */ 2458cfa0ad2SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_82543; 2468cfa0ad2SJack F Vogel /* clearing VFTA */ 2478cfa0ad2SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_generic; 24874dbc418SJack F Vogel /* read mac address */ 24974dbc418SJack F Vogel mac->ops.read_mac_addr = e1000_read_mac_addr_82543; 2508cfa0ad2SJack F Vogel /* turn on/off LED */ 2518cfa0ad2SJack F Vogel mac->ops.led_on = e1000_led_on_82543; 2528cfa0ad2SJack F Vogel mac->ops.led_off = e1000_led_off_82543; 2538cfa0ad2SJack F Vogel /* clear hardware counters */ 2548cfa0ad2SJack F Vogel mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82543; 2558cfa0ad2SJack F Vogel 2568cfa0ad2SJack F Vogel /* Set tbi compatibility */ 2578cfa0ad2SJack F Vogel if ((hw->mac.type != e1000_82543) || 2588cfa0ad2SJack F Vogel (hw->phy.media_type == e1000_media_type_fiber)) 2598cfa0ad2SJack F Vogel e1000_set_tbi_compatibility_82543(hw, FALSE); 2608cfa0ad2SJack F Vogel 261daf9197cSJack F Vogel return E1000_SUCCESS; 2628cfa0ad2SJack F Vogel } 2638cfa0ad2SJack F Vogel 2648cfa0ad2SJack F Vogel /** 2658cfa0ad2SJack F Vogel * e1000_init_function_pointers_82543 - Init func ptrs. 2668cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 2678cfa0ad2SJack F Vogel * 268daf9197cSJack F Vogel * Called to initialize all function pointers and parameters. 2698cfa0ad2SJack F Vogel **/ 2708cfa0ad2SJack F Vogel void e1000_init_function_pointers_82543(struct e1000_hw *hw) 2718cfa0ad2SJack F Vogel { 2728cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_82543"); 2738cfa0ad2SJack F Vogel 2748cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_82543; 2758cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_82543; 2768cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_82543; 2778cfa0ad2SJack F Vogel } 2788cfa0ad2SJack F Vogel 2798cfa0ad2SJack F Vogel /** 2808cfa0ad2SJack F Vogel * e1000_tbi_compatibility_enabled_82543 - Returns TBI compat status 2818cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 2828cfa0ad2SJack F Vogel * 2838cfa0ad2SJack F Vogel * Returns the current status of 10-bit Interface (TBI) compatibility 2848cfa0ad2SJack F Vogel * (enabled/disabled). 2858cfa0ad2SJack F Vogel **/ 2868cfa0ad2SJack F Vogel static bool e1000_tbi_compatibility_enabled_82543(struct e1000_hw *hw) 2878cfa0ad2SJack F Vogel { 288daf9197cSJack F Vogel struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; 2898cfa0ad2SJack F Vogel bool state = FALSE; 2908cfa0ad2SJack F Vogel 2918cfa0ad2SJack F Vogel DEBUGFUNC("e1000_tbi_compatibility_enabled_82543"); 2928cfa0ad2SJack F Vogel 2938cfa0ad2SJack F Vogel if (hw->mac.type != e1000_82543) { 2948cfa0ad2SJack F Vogel DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); 2958cfa0ad2SJack F Vogel goto out; 2968cfa0ad2SJack F Vogel } 2978cfa0ad2SJack F Vogel 29848600901SSean Bruno state = !!(dev_spec->tbi_compatibility & TBI_COMPAT_ENABLED); 2998cfa0ad2SJack F Vogel 3008cfa0ad2SJack F Vogel out: 3018cfa0ad2SJack F Vogel return state; 3028cfa0ad2SJack F Vogel } 3038cfa0ad2SJack F Vogel 3048cfa0ad2SJack F Vogel /** 3058cfa0ad2SJack F Vogel * e1000_set_tbi_compatibility_82543 - Set TBI compatibility 3068cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3078cfa0ad2SJack F Vogel * @state: enable/disable TBI compatibility 3088cfa0ad2SJack F Vogel * 3098cfa0ad2SJack F Vogel * Enables or disabled 10-bit Interface (TBI) compatibility. 3108cfa0ad2SJack F Vogel **/ 3118cfa0ad2SJack F Vogel void e1000_set_tbi_compatibility_82543(struct e1000_hw *hw, bool state) 3128cfa0ad2SJack F Vogel { 313daf9197cSJack F Vogel struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; 3148cfa0ad2SJack F Vogel 3158cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_tbi_compatibility_82543"); 3168cfa0ad2SJack F Vogel 3178cfa0ad2SJack F Vogel if (hw->mac.type != e1000_82543) { 3188cfa0ad2SJack F Vogel DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); 3198cfa0ad2SJack F Vogel goto out; 3208cfa0ad2SJack F Vogel } 3218cfa0ad2SJack F Vogel 3228cfa0ad2SJack F Vogel if (state) 3238cfa0ad2SJack F Vogel dev_spec->tbi_compatibility |= TBI_COMPAT_ENABLED; 3248cfa0ad2SJack F Vogel else 3258cfa0ad2SJack F Vogel dev_spec->tbi_compatibility &= ~TBI_COMPAT_ENABLED; 3268cfa0ad2SJack F Vogel 3278cfa0ad2SJack F Vogel out: 3288cfa0ad2SJack F Vogel return; 3298cfa0ad2SJack F Vogel } 3308cfa0ad2SJack F Vogel 3318cfa0ad2SJack F Vogel /** 3328cfa0ad2SJack F Vogel * e1000_tbi_sbp_enabled_82543 - Returns TBI SBP status 3338cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3348cfa0ad2SJack F Vogel * 3358cfa0ad2SJack F Vogel * Returns the current status of 10-bit Interface (TBI) store bad packet (SBP) 3368cfa0ad2SJack F Vogel * (enabled/disabled). 3378cfa0ad2SJack F Vogel **/ 3388cfa0ad2SJack F Vogel bool e1000_tbi_sbp_enabled_82543(struct e1000_hw *hw) 3398cfa0ad2SJack F Vogel { 340daf9197cSJack F Vogel struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; 3418cfa0ad2SJack F Vogel bool state = FALSE; 3428cfa0ad2SJack F Vogel 3438cfa0ad2SJack F Vogel DEBUGFUNC("e1000_tbi_sbp_enabled_82543"); 3448cfa0ad2SJack F Vogel 3458cfa0ad2SJack F Vogel if (hw->mac.type != e1000_82543) { 3468cfa0ad2SJack F Vogel DEBUGOUT("TBI compatibility workaround for 82543 only.\n"); 3478cfa0ad2SJack F Vogel goto out; 3488cfa0ad2SJack F Vogel } 3498cfa0ad2SJack F Vogel 35048600901SSean Bruno state = !!(dev_spec->tbi_compatibility & TBI_SBP_ENABLED); 3518cfa0ad2SJack F Vogel 3528cfa0ad2SJack F Vogel out: 3538cfa0ad2SJack F Vogel return state; 3548cfa0ad2SJack F Vogel } 3558cfa0ad2SJack F Vogel 3568cfa0ad2SJack F Vogel /** 3578cfa0ad2SJack F Vogel * e1000_set_tbi_sbp_82543 - Set TBI SBP 3588cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3598cfa0ad2SJack F Vogel * @state: enable/disable TBI store bad packet 3608cfa0ad2SJack F Vogel * 3618cfa0ad2SJack F Vogel * Enables or disabled 10-bit Interface (TBI) store bad packet (SBP). 3628cfa0ad2SJack F Vogel **/ 3638cfa0ad2SJack F Vogel static void e1000_set_tbi_sbp_82543(struct e1000_hw *hw, bool state) 3648cfa0ad2SJack F Vogel { 365daf9197cSJack F Vogel struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; 3668cfa0ad2SJack F Vogel 3678cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_tbi_sbp_82543"); 3688cfa0ad2SJack F Vogel 3698cfa0ad2SJack F Vogel if (state && e1000_tbi_compatibility_enabled_82543(hw)) 3708cfa0ad2SJack F Vogel dev_spec->tbi_compatibility |= TBI_SBP_ENABLED; 3718cfa0ad2SJack F Vogel else 3728cfa0ad2SJack F Vogel dev_spec->tbi_compatibility &= ~TBI_SBP_ENABLED; 3738cfa0ad2SJack F Vogel 3748cfa0ad2SJack F Vogel return; 3758cfa0ad2SJack F Vogel } 3768cfa0ad2SJack F Vogel 3778cfa0ad2SJack F Vogel /** 3788cfa0ad2SJack F Vogel * e1000_init_phy_disabled_82543 - Returns init PHY status 3798cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3808cfa0ad2SJack F Vogel * 3818cfa0ad2SJack F Vogel * Returns the current status of whether PHY initialization is disabled. 3828cfa0ad2SJack F Vogel * True if PHY initialization is disabled else FALSE. 3838cfa0ad2SJack F Vogel **/ 3848cfa0ad2SJack F Vogel static bool e1000_init_phy_disabled_82543(struct e1000_hw *hw) 3858cfa0ad2SJack F Vogel { 386daf9197cSJack F Vogel struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; 3878cfa0ad2SJack F Vogel bool ret_val; 3888cfa0ad2SJack F Vogel 3898cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_disabled_82543"); 3908cfa0ad2SJack F Vogel 3918cfa0ad2SJack F Vogel if (hw->mac.type != e1000_82543) { 3928cfa0ad2SJack F Vogel ret_val = FALSE; 3938cfa0ad2SJack F Vogel goto out; 3948cfa0ad2SJack F Vogel } 3958cfa0ad2SJack F Vogel 3968cfa0ad2SJack F Vogel ret_val = dev_spec->init_phy_disabled; 3978cfa0ad2SJack F Vogel 3988cfa0ad2SJack F Vogel out: 3998cfa0ad2SJack F Vogel return ret_val; 4008cfa0ad2SJack F Vogel } 4018cfa0ad2SJack F Vogel 4028cfa0ad2SJack F Vogel /** 4038cfa0ad2SJack F Vogel * e1000_tbi_adjust_stats_82543 - Adjust stats when TBI enabled 4048cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4058cfa0ad2SJack F Vogel * @stats: Struct containing statistic register values 4068cfa0ad2SJack F Vogel * @frame_len: The length of the frame in question 4078cfa0ad2SJack F Vogel * @mac_addr: The Ethernet destination address of the frame in question 4088cfa0ad2SJack F Vogel * @max_frame_size: The maximum frame size 4098cfa0ad2SJack F Vogel * 4108cfa0ad2SJack F Vogel * Adjusts the statistic counters when a frame is accepted by TBI_ACCEPT 4118cfa0ad2SJack F Vogel **/ 4128cfa0ad2SJack F Vogel void e1000_tbi_adjust_stats_82543(struct e1000_hw *hw, 4138cfa0ad2SJack F Vogel struct e1000_hw_stats *stats, u32 frame_len, 4148cfa0ad2SJack F Vogel u8 *mac_addr, u32 max_frame_size) 4158cfa0ad2SJack F Vogel { 4168cfa0ad2SJack F Vogel if (!(e1000_tbi_sbp_enabled_82543(hw))) 4178cfa0ad2SJack F Vogel goto out; 4188cfa0ad2SJack F Vogel 4198cfa0ad2SJack F Vogel /* First adjust the frame length. */ 4208cfa0ad2SJack F Vogel frame_len--; 4218cfa0ad2SJack F Vogel /* 4228cfa0ad2SJack F Vogel * We need to adjust the statistics counters, since the hardware 4238cfa0ad2SJack F Vogel * counters overcount this packet as a CRC error and undercount 4248cfa0ad2SJack F Vogel * the packet as a good packet 4258cfa0ad2SJack F Vogel */ 4268cfa0ad2SJack F Vogel /* This packet should not be counted as a CRC error. */ 4278cfa0ad2SJack F Vogel stats->crcerrs--; 4288cfa0ad2SJack F Vogel /* This packet does count as a Good Packet Received. */ 4298cfa0ad2SJack F Vogel stats->gprc++; 4308cfa0ad2SJack F Vogel 4318cfa0ad2SJack F Vogel /* Adjust the Good Octets received counters */ 4328cfa0ad2SJack F Vogel stats->gorc += frame_len; 4338cfa0ad2SJack F Vogel 4348cfa0ad2SJack F Vogel /* 4358cfa0ad2SJack F Vogel * Is this a broadcast or multicast? Check broadcast first, 4368cfa0ad2SJack F Vogel * since the test for a multicast frame will test positive on 4378cfa0ad2SJack F Vogel * a broadcast frame. 4388cfa0ad2SJack F Vogel */ 4398cfa0ad2SJack F Vogel if ((mac_addr[0] == 0xff) && (mac_addr[1] == 0xff)) 4408cfa0ad2SJack F Vogel /* Broadcast packet */ 4418cfa0ad2SJack F Vogel stats->bprc++; 4428cfa0ad2SJack F Vogel else if (*mac_addr & 0x01) 4438cfa0ad2SJack F Vogel /* Multicast packet */ 4448cfa0ad2SJack F Vogel stats->mprc++; 4458cfa0ad2SJack F Vogel 4468cfa0ad2SJack F Vogel /* 4478cfa0ad2SJack F Vogel * In this case, the hardware has over counted the number of 4488cfa0ad2SJack F Vogel * oversize frames. 4498cfa0ad2SJack F Vogel */ 4508cfa0ad2SJack F Vogel if ((frame_len == max_frame_size) && (stats->roc > 0)) 4518cfa0ad2SJack F Vogel stats->roc--; 4528cfa0ad2SJack F Vogel 4538cfa0ad2SJack F Vogel /* 4548cfa0ad2SJack F Vogel * Adjust the bin counters when the extra byte put the frame in the 4558cfa0ad2SJack F Vogel * wrong bin. Remember that the frame_len was adjusted above. 4568cfa0ad2SJack F Vogel */ 4578cfa0ad2SJack F Vogel if (frame_len == 64) { 4588cfa0ad2SJack F Vogel stats->prc64++; 4598cfa0ad2SJack F Vogel stats->prc127--; 4608cfa0ad2SJack F Vogel } else if (frame_len == 127) { 4618cfa0ad2SJack F Vogel stats->prc127++; 4628cfa0ad2SJack F Vogel stats->prc255--; 4638cfa0ad2SJack F Vogel } else if (frame_len == 255) { 4648cfa0ad2SJack F Vogel stats->prc255++; 4658cfa0ad2SJack F Vogel stats->prc511--; 4668cfa0ad2SJack F Vogel } else if (frame_len == 511) { 4678cfa0ad2SJack F Vogel stats->prc511++; 4688cfa0ad2SJack F Vogel stats->prc1023--; 4698cfa0ad2SJack F Vogel } else if (frame_len == 1023) { 4708cfa0ad2SJack F Vogel stats->prc1023++; 4718cfa0ad2SJack F Vogel stats->prc1522--; 4728cfa0ad2SJack F Vogel } else if (frame_len == 1522) { 4738cfa0ad2SJack F Vogel stats->prc1522++; 4748cfa0ad2SJack F Vogel } 4758cfa0ad2SJack F Vogel 4768cfa0ad2SJack F Vogel out: 4778cfa0ad2SJack F Vogel return; 4788cfa0ad2SJack F Vogel } 4798cfa0ad2SJack F Vogel 4808cfa0ad2SJack F Vogel /** 4818cfa0ad2SJack F Vogel * e1000_read_phy_reg_82543 - Read PHY register 4828cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4838cfa0ad2SJack F Vogel * @offset: register offset to be read 4848cfa0ad2SJack F Vogel * @data: pointer to the read data 4858cfa0ad2SJack F Vogel * 4868cfa0ad2SJack F Vogel * Reads the PHY at offset and stores the information read to data. 4878cfa0ad2SJack F Vogel **/ 4888cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 *data) 4898cfa0ad2SJack F Vogel { 4908cfa0ad2SJack F Vogel u32 mdic; 4918cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 4928cfa0ad2SJack F Vogel 4938cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_82543"); 4948cfa0ad2SJack F Vogel 4958cfa0ad2SJack F Vogel if (offset > MAX_PHY_REG_ADDRESS) { 4968cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %d is out of range\n", offset); 4978cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PARAM; 4988cfa0ad2SJack F Vogel goto out; 4998cfa0ad2SJack F Vogel } 5008cfa0ad2SJack F Vogel 5018cfa0ad2SJack F Vogel /* 5028cfa0ad2SJack F Vogel * We must first send a preamble through the MDIO pin to signal the 5038cfa0ad2SJack F Vogel * beginning of an MII instruction. This is done by sending 32 5048cfa0ad2SJack F Vogel * consecutive "1" bits. 5058cfa0ad2SJack F Vogel */ 5068cfa0ad2SJack F Vogel e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); 5078cfa0ad2SJack F Vogel 5088cfa0ad2SJack F Vogel /* 5098cfa0ad2SJack F Vogel * Now combine the next few fields that are required for a read 5108cfa0ad2SJack F Vogel * operation. We use this method instead of calling the 5118cfa0ad2SJack F Vogel * e1000_shift_out_mdi_bits routine five different times. The format 5128cfa0ad2SJack F Vogel * of an MII read instruction consists of a shift out of 14 bits and 5138cfa0ad2SJack F Vogel * is defined as follows: 5148cfa0ad2SJack F Vogel * <Preamble><SOF><Op Code><Phy Addr><Offset> 5158cfa0ad2SJack F Vogel * followed by a shift in of 18 bits. This first two bits shifted in 5168cfa0ad2SJack F Vogel * are TurnAround bits used to avoid contention on the MDIO pin when a 5178cfa0ad2SJack F Vogel * READ operation is performed. These two bits are thrown away 5188cfa0ad2SJack F Vogel * followed by a shift in of 16 bits which contains the desired data. 5198cfa0ad2SJack F Vogel */ 5208cfa0ad2SJack F Vogel mdic = (offset | (hw->phy.addr << 5) | 5218cfa0ad2SJack F Vogel (PHY_OP_READ << 10) | (PHY_SOF << 12)); 5228cfa0ad2SJack F Vogel 5238cfa0ad2SJack F Vogel e1000_shift_out_mdi_bits_82543(hw, mdic, 14); 5248cfa0ad2SJack F Vogel 5258cfa0ad2SJack F Vogel /* 5268cfa0ad2SJack F Vogel * Now that we've shifted out the read command to the MII, we need to 5278cfa0ad2SJack F Vogel * "shift in" the 16-bit value (18 total bits) of the requested PHY 5288cfa0ad2SJack F Vogel * register address. 5298cfa0ad2SJack F Vogel */ 5308cfa0ad2SJack F Vogel *data = e1000_shift_in_mdi_bits_82543(hw); 5318cfa0ad2SJack F Vogel 5328cfa0ad2SJack F Vogel out: 5338cfa0ad2SJack F Vogel return ret_val; 5348cfa0ad2SJack F Vogel } 5358cfa0ad2SJack F Vogel 5368cfa0ad2SJack F Vogel /** 5378cfa0ad2SJack F Vogel * e1000_write_phy_reg_82543 - Write PHY register 5388cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5398cfa0ad2SJack F Vogel * @offset: register offset to be written 5408cfa0ad2SJack F Vogel * @data: pointer to the data to be written at offset 5418cfa0ad2SJack F Vogel * 5428cfa0ad2SJack F Vogel * Writes data to the PHY at offset. 5438cfa0ad2SJack F Vogel **/ 5448cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_82543(struct e1000_hw *hw, u32 offset, u16 data) 5458cfa0ad2SJack F Vogel { 5468cfa0ad2SJack F Vogel u32 mdic; 5478cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 5488cfa0ad2SJack F Vogel 5498cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_82543"); 5508cfa0ad2SJack F Vogel 5518cfa0ad2SJack F Vogel if (offset > MAX_PHY_REG_ADDRESS) { 5528cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %d is out of range\n", offset); 5538cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PARAM; 5548cfa0ad2SJack F Vogel goto out; 5558cfa0ad2SJack F Vogel } 5568cfa0ad2SJack F Vogel 5578cfa0ad2SJack F Vogel /* 5588cfa0ad2SJack F Vogel * We'll need to use the SW defined pins to shift the write command 5598cfa0ad2SJack F Vogel * out to the PHY. We first send a preamble to the PHY to signal the 5608cfa0ad2SJack F Vogel * beginning of the MII instruction. This is done by sending 32 5618cfa0ad2SJack F Vogel * consecutive "1" bits. 5628cfa0ad2SJack F Vogel */ 5638cfa0ad2SJack F Vogel e1000_shift_out_mdi_bits_82543(hw, PHY_PREAMBLE, PHY_PREAMBLE_SIZE); 5648cfa0ad2SJack F Vogel 5658cfa0ad2SJack F Vogel /* 5668cfa0ad2SJack F Vogel * Now combine the remaining required fields that will indicate a 5678cfa0ad2SJack F Vogel * write operation. We use this method instead of calling the 5688cfa0ad2SJack F Vogel * e1000_shift_out_mdi_bits routine for each field in the command. The 5698cfa0ad2SJack F Vogel * format of a MII write instruction is as follows: 5708cfa0ad2SJack F Vogel * <Preamble><SOF><Op Code><Phy Addr><Reg Addr><Turnaround><Data>. 5718cfa0ad2SJack F Vogel */ 5728cfa0ad2SJack F Vogel mdic = ((PHY_TURNAROUND) | (offset << 2) | (hw->phy.addr << 7) | 5738cfa0ad2SJack F Vogel (PHY_OP_WRITE << 12) | (PHY_SOF << 14)); 5748cfa0ad2SJack F Vogel mdic <<= 16; 5758cfa0ad2SJack F Vogel mdic |= (u32)data; 5768cfa0ad2SJack F Vogel 5778cfa0ad2SJack F Vogel e1000_shift_out_mdi_bits_82543(hw, mdic, 32); 5788cfa0ad2SJack F Vogel 5798cfa0ad2SJack F Vogel out: 5808cfa0ad2SJack F Vogel return ret_val; 5818cfa0ad2SJack F Vogel } 5828cfa0ad2SJack F Vogel 5838cfa0ad2SJack F Vogel /** 5848cfa0ad2SJack F Vogel * e1000_raise_mdi_clk_82543 - Raise Management Data Input clock 5858cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5868cfa0ad2SJack F Vogel * @ctrl: pointer to the control register 5878cfa0ad2SJack F Vogel * 5888cfa0ad2SJack F Vogel * Raise the management data input clock by setting the MDC bit in the control 5898cfa0ad2SJack F Vogel * register. 5908cfa0ad2SJack F Vogel **/ 5918cfa0ad2SJack F Vogel static void e1000_raise_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl) 5928cfa0ad2SJack F Vogel { 5938cfa0ad2SJack F Vogel /* 5948cfa0ad2SJack F Vogel * Raise the clock input to the Management Data Clock (by setting the 5958cfa0ad2SJack F Vogel * MDC bit), and then delay a sufficient amount of time. 5968cfa0ad2SJack F Vogel */ 5978cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl | E1000_CTRL_MDC)); 5988cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 5998cfa0ad2SJack F Vogel usec_delay(10); 6008cfa0ad2SJack F Vogel } 6018cfa0ad2SJack F Vogel 6028cfa0ad2SJack F Vogel /** 6038cfa0ad2SJack F Vogel * e1000_lower_mdi_clk_82543 - Lower Management Data Input clock 6048cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6058cfa0ad2SJack F Vogel * @ctrl: pointer to the control register 6068cfa0ad2SJack F Vogel * 6078cfa0ad2SJack F Vogel * Lower the management data input clock by clearing the MDC bit in the 6088cfa0ad2SJack F Vogel * control register. 6098cfa0ad2SJack F Vogel **/ 6108cfa0ad2SJack F Vogel static void e1000_lower_mdi_clk_82543(struct e1000_hw *hw, u32 *ctrl) 6118cfa0ad2SJack F Vogel { 6128cfa0ad2SJack F Vogel /* 6138cfa0ad2SJack F Vogel * Lower the clock input to the Management Data Clock (by clearing the 6148cfa0ad2SJack F Vogel * MDC bit), and then delay a sufficient amount of time. 6158cfa0ad2SJack F Vogel */ 6168cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, (*ctrl & ~E1000_CTRL_MDC)); 6178cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 6188cfa0ad2SJack F Vogel usec_delay(10); 6198cfa0ad2SJack F Vogel } 6208cfa0ad2SJack F Vogel 6218cfa0ad2SJack F Vogel /** 6228cfa0ad2SJack F Vogel * e1000_shift_out_mdi_bits_82543 - Shift data bits our to the PHY 6238cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6248cfa0ad2SJack F Vogel * @data: data to send to the PHY 6258cfa0ad2SJack F Vogel * @count: number of bits to shift out 6268cfa0ad2SJack F Vogel * 6278cfa0ad2SJack F Vogel * We need to shift 'count' bits out to the PHY. So, the value in the 6288cfa0ad2SJack F Vogel * "data" parameter will be shifted out to the PHY one bit at a time. 6298cfa0ad2SJack F Vogel * In order to do this, "data" must be broken down into bits. 6308cfa0ad2SJack F Vogel **/ 6318cfa0ad2SJack F Vogel static void e1000_shift_out_mdi_bits_82543(struct e1000_hw *hw, u32 data, 6328cfa0ad2SJack F Vogel u16 count) 6338cfa0ad2SJack F Vogel { 6348cfa0ad2SJack F Vogel u32 ctrl, mask; 6358cfa0ad2SJack F Vogel 6368cfa0ad2SJack F Vogel /* 6378cfa0ad2SJack F Vogel * We need to shift "count" number of bits out to the PHY. So, the 6388cfa0ad2SJack F Vogel * value in the "data" parameter will be shifted out to the PHY one 6398cfa0ad2SJack F Vogel * bit at a time. In order to do this, "data" must be broken down 6408cfa0ad2SJack F Vogel * into bits. 6418cfa0ad2SJack F Vogel */ 6428cfa0ad2SJack F Vogel mask = 0x01; 6438cfa0ad2SJack F Vogel mask <<= (count - 1); 6448cfa0ad2SJack F Vogel 6458cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 6468cfa0ad2SJack F Vogel 6478cfa0ad2SJack F Vogel /* Set MDIO_DIR and MDC_DIR direction bits to be used as output pins. */ 6488cfa0ad2SJack F Vogel ctrl |= (E1000_CTRL_MDIO_DIR | E1000_CTRL_MDC_DIR); 6498cfa0ad2SJack F Vogel 6508cfa0ad2SJack F Vogel while (mask) { 6518cfa0ad2SJack F Vogel /* 6528cfa0ad2SJack F Vogel * A "1" is shifted out to the PHY by setting the MDIO bit to 6538cfa0ad2SJack F Vogel * "1" and then raising and lowering the Management Data Clock. 6548cfa0ad2SJack F Vogel * A "0" is shifted out to the PHY by setting the MDIO bit to 6558cfa0ad2SJack F Vogel * "0" and then raising and lowering the clock. 6568cfa0ad2SJack F Vogel */ 65748600901SSean Bruno if (data & mask) 65848600901SSean Bruno ctrl |= E1000_CTRL_MDIO; 65948600901SSean Bruno else 66048600901SSean Bruno ctrl &= ~E1000_CTRL_MDIO; 6618cfa0ad2SJack F Vogel 6628cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 6638cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 6648cfa0ad2SJack F Vogel 6658cfa0ad2SJack F Vogel usec_delay(10); 6668cfa0ad2SJack F Vogel 6678cfa0ad2SJack F Vogel e1000_raise_mdi_clk_82543(hw, &ctrl); 6688cfa0ad2SJack F Vogel e1000_lower_mdi_clk_82543(hw, &ctrl); 6698cfa0ad2SJack F Vogel 6708cfa0ad2SJack F Vogel mask >>= 1; 6718cfa0ad2SJack F Vogel } 6728cfa0ad2SJack F Vogel } 6738cfa0ad2SJack F Vogel 6748cfa0ad2SJack F Vogel /** 6758cfa0ad2SJack F Vogel * e1000_shift_in_mdi_bits_82543 - Shift data bits in from the PHY 6768cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6778cfa0ad2SJack F Vogel * 6788cfa0ad2SJack F Vogel * In order to read a register from the PHY, we need to shift 18 bits 6798cfa0ad2SJack F Vogel * in from the PHY. Bits are "shifted in" by raising the clock input to 6808cfa0ad2SJack F Vogel * the PHY (setting the MDC bit), and then reading the value of the data out 6818cfa0ad2SJack F Vogel * MDIO bit. 6828cfa0ad2SJack F Vogel **/ 6838cfa0ad2SJack F Vogel static u16 e1000_shift_in_mdi_bits_82543(struct e1000_hw *hw) 6848cfa0ad2SJack F Vogel { 6858cfa0ad2SJack F Vogel u32 ctrl; 6868cfa0ad2SJack F Vogel u16 data = 0; 6878cfa0ad2SJack F Vogel u8 i; 6888cfa0ad2SJack F Vogel 6898cfa0ad2SJack F Vogel /* 6908cfa0ad2SJack F Vogel * In order to read a register from the PHY, we need to shift in a 6918cfa0ad2SJack F Vogel * total of 18 bits from the PHY. The first two bit (turnaround) 6928cfa0ad2SJack F Vogel * times are used to avoid contention on the MDIO pin when a read 6938cfa0ad2SJack F Vogel * operation is performed. These two bits are ignored by us and 6948cfa0ad2SJack F Vogel * thrown away. Bits are "shifted in" by raising the input to the 6958cfa0ad2SJack F Vogel * Management Data Clock (setting the MDC bit) and then reading the 6968cfa0ad2SJack F Vogel * value of the MDIO bit. 6978cfa0ad2SJack F Vogel */ 6988cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 6998cfa0ad2SJack F Vogel 7008cfa0ad2SJack F Vogel /* 7018cfa0ad2SJack F Vogel * Clear MDIO_DIR (SWDPIO1) to indicate this bit is to be used as 7028cfa0ad2SJack F Vogel * input. 7038cfa0ad2SJack F Vogel */ 7048cfa0ad2SJack F Vogel ctrl &= ~E1000_CTRL_MDIO_DIR; 7058cfa0ad2SJack F Vogel ctrl &= ~E1000_CTRL_MDIO; 7068cfa0ad2SJack F Vogel 7078cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 7088cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 7098cfa0ad2SJack F Vogel 7108cfa0ad2SJack F Vogel /* 7118cfa0ad2SJack F Vogel * Raise and lower the clock before reading in the data. This accounts 7128cfa0ad2SJack F Vogel * for the turnaround bits. The first clock occurred when we clocked 7138cfa0ad2SJack F Vogel * out the last bit of the Register Address. 7148cfa0ad2SJack F Vogel */ 7158cfa0ad2SJack F Vogel e1000_raise_mdi_clk_82543(hw, &ctrl); 7168cfa0ad2SJack F Vogel e1000_lower_mdi_clk_82543(hw, &ctrl); 7178cfa0ad2SJack F Vogel 7188cfa0ad2SJack F Vogel for (data = 0, i = 0; i < 16; i++) { 7198cfa0ad2SJack F Vogel data <<= 1; 7208cfa0ad2SJack F Vogel e1000_raise_mdi_clk_82543(hw, &ctrl); 7218cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 7228cfa0ad2SJack F Vogel /* Check to see if we shifted in a "1". */ 7238cfa0ad2SJack F Vogel if (ctrl & E1000_CTRL_MDIO) 7248cfa0ad2SJack F Vogel data |= 1; 7258cfa0ad2SJack F Vogel e1000_lower_mdi_clk_82543(hw, &ctrl); 7268cfa0ad2SJack F Vogel } 7278cfa0ad2SJack F Vogel 7288cfa0ad2SJack F Vogel e1000_raise_mdi_clk_82543(hw, &ctrl); 7298cfa0ad2SJack F Vogel e1000_lower_mdi_clk_82543(hw, &ctrl); 7308cfa0ad2SJack F Vogel 7318cfa0ad2SJack F Vogel return data; 7328cfa0ad2SJack F Vogel } 7338cfa0ad2SJack F Vogel 7348cfa0ad2SJack F Vogel /** 7358cfa0ad2SJack F Vogel * e1000_phy_force_speed_duplex_82543 - Force speed/duplex for PHY 7368cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7378cfa0ad2SJack F Vogel * 7388cfa0ad2SJack F Vogel * Calls the function to force speed and duplex for the m88 PHY, and 7398cfa0ad2SJack F Vogel * if the PHY is not auto-negotiating and the speed is forced to 10Mbit, 7408cfa0ad2SJack F Vogel * then call the function for polarity reversal workaround. 7418cfa0ad2SJack F Vogel **/ 7428cfa0ad2SJack F Vogel static s32 e1000_phy_force_speed_duplex_82543(struct e1000_hw *hw) 7438cfa0ad2SJack F Vogel { 7448cfa0ad2SJack F Vogel s32 ret_val; 7458cfa0ad2SJack F Vogel 7468cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_force_speed_duplex_82543"); 7478cfa0ad2SJack F Vogel 7488cfa0ad2SJack F Vogel ret_val = e1000_phy_force_speed_duplex_m88(hw); 7498cfa0ad2SJack F Vogel if (ret_val) 7508cfa0ad2SJack F Vogel goto out; 7518cfa0ad2SJack F Vogel 75248600901SSean Bruno if (!hw->mac.autoneg && (hw->mac.forced_speed_duplex & 75348600901SSean Bruno E1000_ALL_10_SPEED)) 7548cfa0ad2SJack F Vogel ret_val = e1000_polarity_reversal_workaround_82543(hw); 7558cfa0ad2SJack F Vogel 7568cfa0ad2SJack F Vogel out: 7578cfa0ad2SJack F Vogel return ret_val; 7588cfa0ad2SJack F Vogel } 7598cfa0ad2SJack F Vogel 7608cfa0ad2SJack F Vogel /** 7618cfa0ad2SJack F Vogel * e1000_polarity_reversal_workaround_82543 - Workaround polarity reversal 7628cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7638cfa0ad2SJack F Vogel * 7648cfa0ad2SJack F Vogel * When forcing link to 10 Full or 10 Half, the PHY can reverse the polarity 7658cfa0ad2SJack F Vogel * inadvertently. To workaround the issue, we disable the transmitter on 7668cfa0ad2SJack F Vogel * the PHY until we have established the link partner's link parameters. 7678cfa0ad2SJack F Vogel **/ 7688cfa0ad2SJack F Vogel static s32 e1000_polarity_reversal_workaround_82543(struct e1000_hw *hw) 7698cfa0ad2SJack F Vogel { 7708cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 7718cfa0ad2SJack F Vogel u16 mii_status_reg; 7728cfa0ad2SJack F Vogel u16 i; 7738cfa0ad2SJack F Vogel bool link; 7748cfa0ad2SJack F Vogel 7758cfa0ad2SJack F Vogel if (!(hw->phy.ops.write_reg)) 7768cfa0ad2SJack F Vogel goto out; 7778cfa0ad2SJack F Vogel 7788cfa0ad2SJack F Vogel /* Polarity reversal workaround for forced 10F/10H links. */ 7798cfa0ad2SJack F Vogel 7808cfa0ad2SJack F Vogel /* Disable the transmitter on the PHY */ 7818cfa0ad2SJack F Vogel 7828cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); 7838cfa0ad2SJack F Vogel if (ret_val) 7848cfa0ad2SJack F Vogel goto out; 7858cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFFF); 7868cfa0ad2SJack F Vogel if (ret_val) 7878cfa0ad2SJack F Vogel goto out; 7888cfa0ad2SJack F Vogel 7898cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); 7908cfa0ad2SJack F Vogel if (ret_val) 7918cfa0ad2SJack F Vogel goto out; 7928cfa0ad2SJack F Vogel 7938cfa0ad2SJack F Vogel /* 7948cfa0ad2SJack F Vogel * This loop will early-out if the NO link condition has been met. 7958cfa0ad2SJack F Vogel * In other words, DO NOT use e1000_phy_has_link_generic() here. 7968cfa0ad2SJack F Vogel */ 7978cfa0ad2SJack F Vogel for (i = PHY_FORCE_TIME; i > 0; i--) { 7988cfa0ad2SJack F Vogel /* 7998cfa0ad2SJack F Vogel * Read the MII Status Register and wait for Link Status bit 8008cfa0ad2SJack F Vogel * to be clear. 8018cfa0ad2SJack F Vogel */ 8028cfa0ad2SJack F Vogel 8038cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); 8048cfa0ad2SJack F Vogel if (ret_val) 8058cfa0ad2SJack F Vogel goto out; 8068cfa0ad2SJack F Vogel 8078cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &mii_status_reg); 8088cfa0ad2SJack F Vogel if (ret_val) 8098cfa0ad2SJack F Vogel goto out; 8108cfa0ad2SJack F Vogel 81148600901SSean Bruno if (!(mii_status_reg & ~MII_SR_LINK_STATUS)) 8128cfa0ad2SJack F Vogel break; 8138cfa0ad2SJack F Vogel msec_delay_irq(100); 8148cfa0ad2SJack F Vogel } 8158cfa0ad2SJack F Vogel 8168cfa0ad2SJack F Vogel /* Recommended delay time after link has been lost */ 8178cfa0ad2SJack F Vogel msec_delay_irq(1000); 8188cfa0ad2SJack F Vogel 8198cfa0ad2SJack F Vogel /* Now we will re-enable the transmitter on the PHY */ 8208cfa0ad2SJack F Vogel 8218cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0019); 8228cfa0ad2SJack F Vogel if (ret_val) 8238cfa0ad2SJack F Vogel goto out; 8248cfa0ad2SJack F Vogel msec_delay_irq(50); 8258cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFFF0); 8268cfa0ad2SJack F Vogel if (ret_val) 8278cfa0ad2SJack F Vogel goto out; 8288cfa0ad2SJack F Vogel msec_delay_irq(50); 8298cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xFF00); 8308cfa0ad2SJack F Vogel if (ret_val) 8318cfa0ad2SJack F Vogel goto out; 8328cfa0ad2SJack F Vogel msec_delay_irq(50); 8338cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0x0000); 8348cfa0ad2SJack F Vogel if (ret_val) 8358cfa0ad2SJack F Vogel goto out; 8368cfa0ad2SJack F Vogel 8378cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_PAGE_SELECT, 0x0000); 8388cfa0ad2SJack F Vogel if (ret_val) 8398cfa0ad2SJack F Vogel goto out; 8408cfa0ad2SJack F Vogel 8418cfa0ad2SJack F Vogel /* 8428cfa0ad2SJack F Vogel * Read the MII Status Register and wait for Link Status bit 8438cfa0ad2SJack F Vogel * to be set. 8448cfa0ad2SJack F Vogel */ 8458cfa0ad2SJack F Vogel ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_TIME, 100000, &link); 8468cfa0ad2SJack F Vogel if (ret_val) 8478cfa0ad2SJack F Vogel goto out; 8488cfa0ad2SJack F Vogel 8498cfa0ad2SJack F Vogel out: 8508cfa0ad2SJack F Vogel return ret_val; 8518cfa0ad2SJack F Vogel } 8528cfa0ad2SJack F Vogel 8538cfa0ad2SJack F Vogel /** 8548cfa0ad2SJack F Vogel * e1000_phy_hw_reset_82543 - PHY hardware reset 8558cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 8568cfa0ad2SJack F Vogel * 8578cfa0ad2SJack F Vogel * Sets the PHY_RESET_DIR bit in the extended device control register 8588cfa0ad2SJack F Vogel * to put the PHY into a reset and waits for completion. Once the reset 8598cfa0ad2SJack F Vogel * has been accomplished, clear the PHY_RESET_DIR bit to take the PHY out 860daf9197cSJack F Vogel * of reset. 8618cfa0ad2SJack F Vogel **/ 8628cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_82543(struct e1000_hw *hw) 8638cfa0ad2SJack F Vogel { 8648cfa0ad2SJack F Vogel u32 ctrl_ext; 8658cfa0ad2SJack F Vogel s32 ret_val; 8668cfa0ad2SJack F Vogel 8678cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_hw_reset_82543"); 8688cfa0ad2SJack F Vogel 8698cfa0ad2SJack F Vogel /* 8708cfa0ad2SJack F Vogel * Read the Extended Device Control Register, assert the PHY_RESET_DIR 8718cfa0ad2SJack F Vogel * bit to put the PHY into reset... 8728cfa0ad2SJack F Vogel */ 8738cfa0ad2SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 8748cfa0ad2SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_SDP4_DIR; 8758cfa0ad2SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP4_DATA; 8768cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 8778cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 8788cfa0ad2SJack F Vogel 8798cfa0ad2SJack F Vogel msec_delay(10); 8808cfa0ad2SJack F Vogel 8818cfa0ad2SJack F Vogel /* ...then take it out of reset. */ 8828cfa0ad2SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_SDP4_DATA; 8838cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 8848cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 8858cfa0ad2SJack F Vogel 8868cfa0ad2SJack F Vogel usec_delay(150); 8878cfa0ad2SJack F Vogel 8888cfa0ad2SJack F Vogel if (!(hw->phy.ops.get_cfg_done)) 8898cfa0ad2SJack F Vogel return E1000_SUCCESS; 8908cfa0ad2SJack F Vogel 8918cfa0ad2SJack F Vogel ret_val = hw->phy.ops.get_cfg_done(hw); 8928cfa0ad2SJack F Vogel 8938cfa0ad2SJack F Vogel return ret_val; 8948cfa0ad2SJack F Vogel } 8958cfa0ad2SJack F Vogel 8968cfa0ad2SJack F Vogel /** 8978cfa0ad2SJack F Vogel * e1000_reset_hw_82543 - Reset hardware 8988cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 8998cfa0ad2SJack F Vogel * 900daf9197cSJack F Vogel * This resets the hardware into a known state. 9018cfa0ad2SJack F Vogel **/ 9028cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82543(struct e1000_hw *hw) 9038cfa0ad2SJack F Vogel { 904c80429ceSEric Joyner u32 ctrl; 9058cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 9068cfa0ad2SJack F Vogel 9078cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_82543"); 9088cfa0ad2SJack F Vogel 9098cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 9108cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 9118cfa0ad2SJack F Vogel 9128cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 9138cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 9148cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 9158cfa0ad2SJack F Vogel 9168cfa0ad2SJack F Vogel e1000_set_tbi_sbp_82543(hw, FALSE); 9178cfa0ad2SJack F Vogel 9188cfa0ad2SJack F Vogel /* 9198cfa0ad2SJack F Vogel * Delay to allow any outstanding PCI transactions to complete before 9208cfa0ad2SJack F Vogel * resetting the device 9218cfa0ad2SJack F Vogel */ 9228cfa0ad2SJack F Vogel msec_delay(10); 9238cfa0ad2SJack F Vogel 9248cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 9258cfa0ad2SJack F Vogel 9268cfa0ad2SJack F Vogel DEBUGOUT("Issuing a global reset to 82543/82544 MAC\n"); 9278cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82543) { 9288cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 9298cfa0ad2SJack F Vogel } else { 9308cfa0ad2SJack F Vogel /* 9318cfa0ad2SJack F Vogel * The 82544 can't ACK the 64-bit write when issuing the 9328cfa0ad2SJack F Vogel * reset, so use IO-mapping as a workaround. 9338cfa0ad2SJack F Vogel */ 9348cfa0ad2SJack F Vogel E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 9358cfa0ad2SJack F Vogel } 9368cfa0ad2SJack F Vogel 9378cfa0ad2SJack F Vogel /* 9388cfa0ad2SJack F Vogel * After MAC reset, force reload of NVM to restore power-on 9398cfa0ad2SJack F Vogel * settings to device. 9408cfa0ad2SJack F Vogel */ 9418cfa0ad2SJack F Vogel hw->nvm.ops.reload(hw); 9428cfa0ad2SJack F Vogel msec_delay(2); 9438cfa0ad2SJack F Vogel 9448cfa0ad2SJack F Vogel /* Masking off and clearing any pending interrupts */ 9458cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 946c80429ceSEric Joyner E1000_READ_REG(hw, E1000_ICR); 9478cfa0ad2SJack F Vogel 9488cfa0ad2SJack F Vogel return ret_val; 9498cfa0ad2SJack F Vogel } 9508cfa0ad2SJack F Vogel 9518cfa0ad2SJack F Vogel /** 9528cfa0ad2SJack F Vogel * e1000_init_hw_82543 - Initialize hardware 9538cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 9548cfa0ad2SJack F Vogel * 9558cfa0ad2SJack F Vogel * This inits the hardware readying it for operation. 9568cfa0ad2SJack F Vogel **/ 9578cfa0ad2SJack F Vogel static s32 e1000_init_hw_82543(struct e1000_hw *hw) 9588cfa0ad2SJack F Vogel { 9598cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 960daf9197cSJack F Vogel struct e1000_dev_spec_82543 *dev_spec = &hw->dev_spec._82543; 9618cfa0ad2SJack F Vogel u32 ctrl; 9628cfa0ad2SJack F Vogel s32 ret_val; 9638cfa0ad2SJack F Vogel u16 i; 9648cfa0ad2SJack F Vogel 9658cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_82543"); 9668cfa0ad2SJack F Vogel 9678cfa0ad2SJack F Vogel /* Disabling VLAN filtering */ 9688cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_VET, 0); 9698cfa0ad2SJack F Vogel mac->ops.clear_vfta(hw); 9708cfa0ad2SJack F Vogel 9718cfa0ad2SJack F Vogel /* Setup the receive address. */ 9728cfa0ad2SJack F Vogel e1000_init_rx_addrs_generic(hw, mac->rar_entry_count); 9738cfa0ad2SJack F Vogel 9748cfa0ad2SJack F Vogel /* Zero out the Multicast HASH table */ 9758cfa0ad2SJack F Vogel DEBUGOUT("Zeroing the MTA\n"); 9768cfa0ad2SJack F Vogel for (i = 0; i < mac->mta_reg_count; i++) { 9778cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); 9788cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 9798cfa0ad2SJack F Vogel } 9808cfa0ad2SJack F Vogel 9818cfa0ad2SJack F Vogel /* 9828cfa0ad2SJack F Vogel * Set the PCI priority bit correctly in the CTRL register. This 9838cfa0ad2SJack F Vogel * determines if the adapter gives priority to receives, or if it 9848cfa0ad2SJack F Vogel * gives equal priority to transmits and receives. 9858cfa0ad2SJack F Vogel */ 9868cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82543 && dev_spec->dma_fairness) { 9878cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 9888cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PRIOR); 9898cfa0ad2SJack F Vogel } 9908cfa0ad2SJack F Vogel 9918cfa0ad2SJack F Vogel e1000_pcix_mmrbc_workaround_generic(hw); 9928cfa0ad2SJack F Vogel 9938cfa0ad2SJack F Vogel /* Setup link and flow control */ 9948cfa0ad2SJack F Vogel ret_val = mac->ops.setup_link(hw); 9958cfa0ad2SJack F Vogel 9968cfa0ad2SJack F Vogel /* 9978cfa0ad2SJack F Vogel * Clear all of the statistics registers (clear on read). It is 9988cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link 9998cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there 10008cfa0ad2SJack F Vogel * is no link. 10018cfa0ad2SJack F Vogel */ 10028cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_82543(hw); 10038cfa0ad2SJack F Vogel 10048cfa0ad2SJack F Vogel return ret_val; 10058cfa0ad2SJack F Vogel } 10068cfa0ad2SJack F Vogel 10078cfa0ad2SJack F Vogel /** 10088cfa0ad2SJack F Vogel * e1000_setup_link_82543 - Setup flow control and link settings 10098cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10108cfa0ad2SJack F Vogel * 10118cfa0ad2SJack F Vogel * Read the EEPROM to determine the initial polarity value and write the 10128cfa0ad2SJack F Vogel * extended device control register with the information before calling 10138cfa0ad2SJack F Vogel * the generic setup link function, which does the following: 10148cfa0ad2SJack F Vogel * Determines which flow control settings to use, then configures flow 10158cfa0ad2SJack F Vogel * control. Calls the appropriate media-specific link configuration 10168cfa0ad2SJack F Vogel * function. Assuming the adapter has a valid link partner, a valid link 10178cfa0ad2SJack F Vogel * should be established. Assumes the hardware has previously been reset 10188cfa0ad2SJack F Vogel * and the transmitter and receiver are not enabled. 10198cfa0ad2SJack F Vogel **/ 10208cfa0ad2SJack F Vogel static s32 e1000_setup_link_82543(struct e1000_hw *hw) 10218cfa0ad2SJack F Vogel { 10228cfa0ad2SJack F Vogel u32 ctrl_ext; 10238cfa0ad2SJack F Vogel s32 ret_val; 10248cfa0ad2SJack F Vogel u16 data; 10258cfa0ad2SJack F Vogel 10268cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_link_82543"); 10278cfa0ad2SJack F Vogel 10288cfa0ad2SJack F Vogel /* 10298cfa0ad2SJack F Vogel * Take the 4 bits from NVM word 0xF that determine the initial 10308cfa0ad2SJack F Vogel * polarity value for the SW controlled pins, and setup the 10318cfa0ad2SJack F Vogel * Extended Device Control reg with that info. 10328cfa0ad2SJack F Vogel * This is needed because one of the SW controlled pins is used for 10338cfa0ad2SJack F Vogel * signal detection. So this should be done before phy setup. 10348cfa0ad2SJack F Vogel */ 10358cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82543) { 10368cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL2_REG, 1, &data); 10378cfa0ad2SJack F Vogel if (ret_val) { 10388cfa0ad2SJack F Vogel DEBUGOUT("NVM Read Error\n"); 10398cfa0ad2SJack F Vogel ret_val = -E1000_ERR_NVM; 10408cfa0ad2SJack F Vogel goto out; 10418cfa0ad2SJack F Vogel } 10428cfa0ad2SJack F Vogel ctrl_ext = ((data & NVM_WORD0F_SWPDIO_EXT_MASK) << 10438cfa0ad2SJack F Vogel NVM_SWDPIO_EXT_SHIFT); 10448cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 10458cfa0ad2SJack F Vogel } 10468cfa0ad2SJack F Vogel 10478cfa0ad2SJack F Vogel ret_val = e1000_setup_link_generic(hw); 10488cfa0ad2SJack F Vogel 10498cfa0ad2SJack F Vogel out: 10508cfa0ad2SJack F Vogel return ret_val; 10518cfa0ad2SJack F Vogel } 10528cfa0ad2SJack F Vogel 10538cfa0ad2SJack F Vogel /** 10548cfa0ad2SJack F Vogel * e1000_setup_copper_link_82543 - Configure copper link settings 10558cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10568cfa0ad2SJack F Vogel * 10578cfa0ad2SJack F Vogel * Configures the link for auto-neg or forced speed and duplex. Then we check 10588cfa0ad2SJack F Vogel * for link, once link is established calls to configure collision distance 10598cfa0ad2SJack F Vogel * and flow control are called. 10608cfa0ad2SJack F Vogel **/ 10618cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82543(struct e1000_hw *hw) 10628cfa0ad2SJack F Vogel { 10638cfa0ad2SJack F Vogel u32 ctrl; 10648cfa0ad2SJack F Vogel s32 ret_val; 10658cfa0ad2SJack F Vogel bool link; 10668cfa0ad2SJack F Vogel 10678cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_82543"); 10688cfa0ad2SJack F Vogel 10698cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL) | E1000_CTRL_SLU; 10708cfa0ad2SJack F Vogel /* 10718cfa0ad2SJack F Vogel * With 82543, we need to force speed and duplex on the MAC 10728cfa0ad2SJack F Vogel * equal to what the PHY speed and duplex configuration is. 10738cfa0ad2SJack F Vogel * In addition, we need to perform a hardware reset on the 10748cfa0ad2SJack F Vogel * PHY to take it out of reset. 10758cfa0ad2SJack F Vogel */ 10768cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82543) { 10778cfa0ad2SJack F Vogel ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 10788cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 10798cfa0ad2SJack F Vogel ret_val = hw->phy.ops.reset(hw); 10808cfa0ad2SJack F Vogel if (ret_val) 10818cfa0ad2SJack F Vogel goto out; 10828cfa0ad2SJack F Vogel } else { 10838cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 10848cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 10858cfa0ad2SJack F Vogel } 10868cfa0ad2SJack F Vogel 10878cfa0ad2SJack F Vogel /* Set MDI/MDI-X, Polarity Reversal, and downshift settings */ 10888cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_m88(hw); 10898cfa0ad2SJack F Vogel if (ret_val) 10908cfa0ad2SJack F Vogel goto out; 10918cfa0ad2SJack F Vogel 10928cfa0ad2SJack F Vogel if (hw->mac.autoneg) { 10938cfa0ad2SJack F Vogel /* 10948cfa0ad2SJack F Vogel * Setup autoneg and flow control advertisement and perform 10958cfa0ad2SJack F Vogel * autonegotiation. 10968cfa0ad2SJack F Vogel */ 10978cfa0ad2SJack F Vogel ret_val = e1000_copper_link_autoneg(hw); 10988cfa0ad2SJack F Vogel if (ret_val) 10998cfa0ad2SJack F Vogel goto out; 11008cfa0ad2SJack F Vogel } else { 11018cfa0ad2SJack F Vogel /* 11028cfa0ad2SJack F Vogel * PHY will be set to 10H, 10F, 100H or 100F 11038cfa0ad2SJack F Vogel * depending on user settings. 11048cfa0ad2SJack F Vogel */ 11058cfa0ad2SJack F Vogel DEBUGOUT("Forcing Speed and Duplex\n"); 11068cfa0ad2SJack F Vogel ret_val = e1000_phy_force_speed_duplex_82543(hw); 11078cfa0ad2SJack F Vogel if (ret_val) { 11088cfa0ad2SJack F Vogel DEBUGOUT("Error Forcing Speed and Duplex\n"); 11098cfa0ad2SJack F Vogel goto out; 11108cfa0ad2SJack F Vogel } 11118cfa0ad2SJack F Vogel } 11128cfa0ad2SJack F Vogel 11138cfa0ad2SJack F Vogel /* 11148cfa0ad2SJack F Vogel * Check link status. Wait up to 100 microseconds for link to become 11158cfa0ad2SJack F Vogel * valid. 11168cfa0ad2SJack F Vogel */ 111748600901SSean Bruno ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10, 11188cfa0ad2SJack F Vogel &link); 11198cfa0ad2SJack F Vogel if (ret_val) 11208cfa0ad2SJack F Vogel goto out; 11218cfa0ad2SJack F Vogel 11228cfa0ad2SJack F Vogel 11238cfa0ad2SJack F Vogel if (link) { 11248cfa0ad2SJack F Vogel DEBUGOUT("Valid link established!!!\n"); 11258cfa0ad2SJack F Vogel /* Config the MAC and PHY after link is up */ 11268cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82544) { 1127ab5d0362SJack F Vogel hw->mac.ops.config_collision_dist(hw); 11288cfa0ad2SJack F Vogel } else { 11298cfa0ad2SJack F Vogel ret_val = e1000_config_mac_to_phy_82543(hw); 11308cfa0ad2SJack F Vogel if (ret_val) 11318cfa0ad2SJack F Vogel goto out; 11328cfa0ad2SJack F Vogel } 11338cfa0ad2SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw); 11348cfa0ad2SJack F Vogel } else { 11358cfa0ad2SJack F Vogel DEBUGOUT("Unable to establish link!!!\n"); 11368cfa0ad2SJack F Vogel } 11378cfa0ad2SJack F Vogel 11388cfa0ad2SJack F Vogel out: 11398cfa0ad2SJack F Vogel return ret_val; 11408cfa0ad2SJack F Vogel } 11418cfa0ad2SJack F Vogel 11428cfa0ad2SJack F Vogel /** 11438cfa0ad2SJack F Vogel * e1000_setup_fiber_link_82543 - Setup link for fiber 11448cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11458cfa0ad2SJack F Vogel * 11468cfa0ad2SJack F Vogel * Configures collision distance and flow control for fiber links. Upon 11478cfa0ad2SJack F Vogel * successful setup, poll for link. 11488cfa0ad2SJack F Vogel **/ 11498cfa0ad2SJack F Vogel static s32 e1000_setup_fiber_link_82543(struct e1000_hw *hw) 11508cfa0ad2SJack F Vogel { 11518cfa0ad2SJack F Vogel u32 ctrl; 11528cfa0ad2SJack F Vogel s32 ret_val; 11538cfa0ad2SJack F Vogel 11548cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_fiber_link_82543"); 11558cfa0ad2SJack F Vogel 11568cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 11578cfa0ad2SJack F Vogel 11588cfa0ad2SJack F Vogel /* Take the link out of reset */ 11598cfa0ad2SJack F Vogel ctrl &= ~E1000_CTRL_LRST; 11608cfa0ad2SJack F Vogel 1161ab5d0362SJack F Vogel hw->mac.ops.config_collision_dist(hw); 11628cfa0ad2SJack F Vogel 11638cfa0ad2SJack F Vogel ret_val = e1000_commit_fc_settings_generic(hw); 11648cfa0ad2SJack F Vogel if (ret_val) 11658cfa0ad2SJack F Vogel goto out; 11668cfa0ad2SJack F Vogel 11678cfa0ad2SJack F Vogel DEBUGOUT("Auto-negotiation enabled\n"); 11688cfa0ad2SJack F Vogel 11698cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 11708cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 11718cfa0ad2SJack F Vogel msec_delay(1); 11728cfa0ad2SJack F Vogel 11738cfa0ad2SJack F Vogel /* 11748cfa0ad2SJack F Vogel * For these adapters, the SW definable pin 1 is cleared when the 11758cfa0ad2SJack F Vogel * optics detect a signal. If we have a signal, then poll for a 11768cfa0ad2SJack F Vogel * "Link-Up" indication. 11778cfa0ad2SJack F Vogel */ 117848600901SSean Bruno if (!(E1000_READ_REG(hw, E1000_CTRL) & E1000_CTRL_SWDPIN1)) 11798cfa0ad2SJack F Vogel ret_val = e1000_poll_fiber_serdes_link_generic(hw); 118048600901SSean Bruno else 11818cfa0ad2SJack F Vogel DEBUGOUT("No signal detected\n"); 11828cfa0ad2SJack F Vogel 11838cfa0ad2SJack F Vogel out: 11848cfa0ad2SJack F Vogel return ret_val; 11858cfa0ad2SJack F Vogel } 11868cfa0ad2SJack F Vogel 11878cfa0ad2SJack F Vogel /** 11888cfa0ad2SJack F Vogel * e1000_check_for_copper_link_82543 - Check for link (Copper) 11898cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11908cfa0ad2SJack F Vogel * 11918cfa0ad2SJack F Vogel * Checks the phy for link, if link exists, do the following: 11928cfa0ad2SJack F Vogel * - check for downshift 11938cfa0ad2SJack F Vogel * - do polarity workaround (if necessary) 11948cfa0ad2SJack F Vogel * - configure collision distance 11958cfa0ad2SJack F Vogel * - configure flow control after link up 11968cfa0ad2SJack F Vogel * - configure tbi compatibility 11978cfa0ad2SJack F Vogel **/ 11988cfa0ad2SJack F Vogel static s32 e1000_check_for_copper_link_82543(struct e1000_hw *hw) 11998cfa0ad2SJack F Vogel { 12008cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 12018cfa0ad2SJack F Vogel u32 icr, rctl; 12028cfa0ad2SJack F Vogel s32 ret_val; 12038cfa0ad2SJack F Vogel u16 speed, duplex; 12048cfa0ad2SJack F Vogel bool link; 12058cfa0ad2SJack F Vogel 12068cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_for_copper_link_82543"); 12078cfa0ad2SJack F Vogel 12088cfa0ad2SJack F Vogel if (!mac->get_link_status) { 12098cfa0ad2SJack F Vogel ret_val = E1000_SUCCESS; 12108cfa0ad2SJack F Vogel goto out; 12118cfa0ad2SJack F Vogel } 12128cfa0ad2SJack F Vogel 12138cfa0ad2SJack F Vogel ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 12148cfa0ad2SJack F Vogel if (ret_val) 12158cfa0ad2SJack F Vogel goto out; 12168cfa0ad2SJack F Vogel 12178cfa0ad2SJack F Vogel if (!link) 12188cfa0ad2SJack F Vogel goto out; /* No link detected */ 12198cfa0ad2SJack F Vogel 12208cfa0ad2SJack F Vogel mac->get_link_status = FALSE; 12218cfa0ad2SJack F Vogel 12228cfa0ad2SJack F Vogel e1000_check_downshift_generic(hw); 12238cfa0ad2SJack F Vogel 12248cfa0ad2SJack F Vogel /* 12258cfa0ad2SJack F Vogel * If we are forcing speed/duplex, then we can return since 12268cfa0ad2SJack F Vogel * we have already determined whether we have link or not. 12278cfa0ad2SJack F Vogel */ 12288cfa0ad2SJack F Vogel if (!mac->autoneg) { 12298cfa0ad2SJack F Vogel /* 12308cfa0ad2SJack F Vogel * If speed and duplex are forced to 10H or 10F, then we will 12318cfa0ad2SJack F Vogel * implement the polarity reversal workaround. We disable 12328cfa0ad2SJack F Vogel * interrupts first, and upon returning, place the devices 12338cfa0ad2SJack F Vogel * interrupt state to its previous value except for the link 12348cfa0ad2SJack F Vogel * status change interrupt which will happened due to the 12358cfa0ad2SJack F Vogel * execution of this workaround. 12368cfa0ad2SJack F Vogel */ 12378cfa0ad2SJack F Vogel if (mac->forced_speed_duplex & E1000_ALL_10_SPEED) { 12388cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF); 12398cfa0ad2SJack F Vogel ret_val = e1000_polarity_reversal_workaround_82543(hw); 12408cfa0ad2SJack F Vogel icr = E1000_READ_REG(hw, E1000_ICR); 12418cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_ICS, (icr & ~E1000_ICS_LSC)); 12428cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMS, IMS_ENABLE_MASK); 12438cfa0ad2SJack F Vogel } 12448cfa0ad2SJack F Vogel 12458cfa0ad2SJack F Vogel ret_val = -E1000_ERR_CONFIG; 12468cfa0ad2SJack F Vogel goto out; 12478cfa0ad2SJack F Vogel } 12488cfa0ad2SJack F Vogel 12498cfa0ad2SJack F Vogel /* 12508cfa0ad2SJack F Vogel * We have a M88E1000 PHY and Auto-Neg is enabled. If we 12518cfa0ad2SJack F Vogel * have Si on board that is 82544 or newer, Auto 12528cfa0ad2SJack F Vogel * Speed Detection takes care of MAC speed/duplex 12538cfa0ad2SJack F Vogel * configuration. So we only need to configure Collision 12548cfa0ad2SJack F Vogel * Distance in the MAC. Otherwise, we need to force 12558cfa0ad2SJack F Vogel * speed/duplex on the MAC to the current PHY speed/duplex 12568cfa0ad2SJack F Vogel * settings. 12578cfa0ad2SJack F Vogel */ 12588cfa0ad2SJack F Vogel if (mac->type == e1000_82544) 1259ab5d0362SJack F Vogel hw->mac.ops.config_collision_dist(hw); 12608cfa0ad2SJack F Vogel else { 12618cfa0ad2SJack F Vogel ret_val = e1000_config_mac_to_phy_82543(hw); 12628cfa0ad2SJack F Vogel if (ret_val) { 12638cfa0ad2SJack F Vogel DEBUGOUT("Error configuring MAC to PHY settings\n"); 12648cfa0ad2SJack F Vogel goto out; 12658cfa0ad2SJack F Vogel } 12668cfa0ad2SJack F Vogel } 12678cfa0ad2SJack F Vogel 12688cfa0ad2SJack F Vogel /* 12698cfa0ad2SJack F Vogel * Configure Flow Control now that Auto-Neg has completed. 12708cfa0ad2SJack F Vogel * First, we need to restore the desired flow control 12718cfa0ad2SJack F Vogel * settings because we may have had to re-autoneg with a 12728cfa0ad2SJack F Vogel * different link partner. 12738cfa0ad2SJack F Vogel */ 12748cfa0ad2SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw); 127548600901SSean Bruno if (ret_val) 12768cfa0ad2SJack F Vogel DEBUGOUT("Error configuring flow control\n"); 12778cfa0ad2SJack F Vogel 12788cfa0ad2SJack F Vogel /* 12798cfa0ad2SJack F Vogel * At this point we know that we are on copper and we have 12808cfa0ad2SJack F Vogel * auto-negotiated link. These are conditions for checking the link 12818cfa0ad2SJack F Vogel * partner capability register. We use the link speed to determine if 12828cfa0ad2SJack F Vogel * TBI compatibility needs to be turned on or off. If the link is not 12838cfa0ad2SJack F Vogel * at gigabit speed, then TBI compatibility is not needed. If we are 12848cfa0ad2SJack F Vogel * at gigabit speed, we turn on TBI compatibility. 12858cfa0ad2SJack F Vogel */ 12868cfa0ad2SJack F Vogel if (e1000_tbi_compatibility_enabled_82543(hw)) { 12878cfa0ad2SJack F Vogel ret_val = mac->ops.get_link_up_info(hw, &speed, &duplex); 12888cfa0ad2SJack F Vogel if (ret_val) { 12898cfa0ad2SJack F Vogel DEBUGOUT("Error getting link speed and duplex\n"); 12908cfa0ad2SJack F Vogel return ret_val; 12918cfa0ad2SJack F Vogel } 12928cfa0ad2SJack F Vogel if (speed != SPEED_1000) { 12938cfa0ad2SJack F Vogel /* 12948cfa0ad2SJack F Vogel * If link speed is not set to gigabit speed, 12958cfa0ad2SJack F Vogel * we do not need to enable TBI compatibility. 12968cfa0ad2SJack F Vogel */ 12978cfa0ad2SJack F Vogel if (e1000_tbi_sbp_enabled_82543(hw)) { 12988cfa0ad2SJack F Vogel /* 12998cfa0ad2SJack F Vogel * If we previously were in the mode, 13008cfa0ad2SJack F Vogel * turn it off. 13018cfa0ad2SJack F Vogel */ 13028cfa0ad2SJack F Vogel e1000_set_tbi_sbp_82543(hw, FALSE); 13038cfa0ad2SJack F Vogel rctl = E1000_READ_REG(hw, E1000_RCTL); 13048cfa0ad2SJack F Vogel rctl &= ~E1000_RCTL_SBP; 13058cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, rctl); 13068cfa0ad2SJack F Vogel } 13078cfa0ad2SJack F Vogel } else { 13088cfa0ad2SJack F Vogel /* 13098cfa0ad2SJack F Vogel * If TBI compatibility is was previously off, 13108cfa0ad2SJack F Vogel * turn it on. For compatibility with a TBI link 13118cfa0ad2SJack F Vogel * partner, we will store bad packets. Some 13128cfa0ad2SJack F Vogel * frames have an additional byte on the end and 13138cfa0ad2SJack F Vogel * will look like CRC errors to to the hardware. 13148cfa0ad2SJack F Vogel */ 13158cfa0ad2SJack F Vogel if (!e1000_tbi_sbp_enabled_82543(hw)) { 13168cfa0ad2SJack F Vogel e1000_set_tbi_sbp_82543(hw, TRUE); 13178cfa0ad2SJack F Vogel rctl = E1000_READ_REG(hw, E1000_RCTL); 13188cfa0ad2SJack F Vogel rctl |= E1000_RCTL_SBP; 13198cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, rctl); 13208cfa0ad2SJack F Vogel } 13218cfa0ad2SJack F Vogel } 13228cfa0ad2SJack F Vogel } 13238cfa0ad2SJack F Vogel out: 13248cfa0ad2SJack F Vogel return ret_val; 13258cfa0ad2SJack F Vogel } 13268cfa0ad2SJack F Vogel 13278cfa0ad2SJack F Vogel /** 13288cfa0ad2SJack F Vogel * e1000_check_for_fiber_link_82543 - Check for link (Fiber) 13298cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13308cfa0ad2SJack F Vogel * 13318cfa0ad2SJack F Vogel * Checks for link up on the hardware. If link is not up and we have 13328cfa0ad2SJack F Vogel * a signal, then we need to force link up. 13338cfa0ad2SJack F Vogel **/ 13348cfa0ad2SJack F Vogel static s32 e1000_check_for_fiber_link_82543(struct e1000_hw *hw) 13358cfa0ad2SJack F Vogel { 13368cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 13378cfa0ad2SJack F Vogel u32 rxcw, ctrl, status; 13388cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 13398cfa0ad2SJack F Vogel 13408cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_for_fiber_link_82543"); 13418cfa0ad2SJack F Vogel 13428cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 13438cfa0ad2SJack F Vogel status = E1000_READ_REG(hw, E1000_STATUS); 13448cfa0ad2SJack F Vogel rxcw = E1000_READ_REG(hw, E1000_RXCW); 13458cfa0ad2SJack F Vogel 13468cfa0ad2SJack F Vogel /* 13478cfa0ad2SJack F Vogel * If we don't have link (auto-negotiation failed or link partner 13488cfa0ad2SJack F Vogel * cannot auto-negotiate), the cable is plugged in (we have signal), 13498cfa0ad2SJack F Vogel * and our link partner is not trying to auto-negotiate with us (we 13508cfa0ad2SJack F Vogel * are receiving idles or data), we need to force link up. We also 13518cfa0ad2SJack F Vogel * need to give auto-negotiation time to complete, in case the cable 13528cfa0ad2SJack F Vogel * was just plugged in. The autoneg_failed flag does this. 13538cfa0ad2SJack F Vogel */ 13548cfa0ad2SJack F Vogel /* (ctrl & E1000_CTRL_SWDPIN1) == 0 == have signal */ 13558cfa0ad2SJack F Vogel if ((!(ctrl & E1000_CTRL_SWDPIN1)) && 13568cfa0ad2SJack F Vogel (!(status & E1000_STATUS_LU)) && 13578cfa0ad2SJack F Vogel (!(rxcw & E1000_RXCW_C))) { 135848600901SSean Bruno if (!mac->autoneg_failed) { 135948600901SSean Bruno mac->autoneg_failed = TRUE; 13608cfa0ad2SJack F Vogel ret_val = 0; 13618cfa0ad2SJack F Vogel goto out; 13628cfa0ad2SJack F Vogel } 13638cfa0ad2SJack F Vogel DEBUGOUT("NOT RXing /C/, disable AutoNeg and force link.\n"); 13648cfa0ad2SJack F Vogel 13658cfa0ad2SJack F Vogel /* Disable auto-negotiation in the TXCW register */ 13668cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXCW, (mac->txcw & ~E1000_TXCW_ANE)); 13678cfa0ad2SJack F Vogel 13688cfa0ad2SJack F Vogel /* Force link-up and also force full-duplex. */ 13698cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 13708cfa0ad2SJack F Vogel ctrl |= (E1000_CTRL_SLU | E1000_CTRL_FD); 13718cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 13728cfa0ad2SJack F Vogel 13738cfa0ad2SJack F Vogel /* Configure Flow Control after forcing link up. */ 13748cfa0ad2SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw); 13758cfa0ad2SJack F Vogel if (ret_val) { 13768cfa0ad2SJack F Vogel DEBUGOUT("Error configuring flow control\n"); 13778cfa0ad2SJack F Vogel goto out; 13788cfa0ad2SJack F Vogel } 13798cfa0ad2SJack F Vogel } else if ((ctrl & E1000_CTRL_SLU) && (rxcw & E1000_RXCW_C)) { 13808cfa0ad2SJack F Vogel /* 13818cfa0ad2SJack F Vogel * If we are forcing link and we are receiving /C/ ordered 13828cfa0ad2SJack F Vogel * sets, re-enable auto-negotiation in the TXCW register 13838cfa0ad2SJack F Vogel * and disable forced link in the Device Control register 13848cfa0ad2SJack F Vogel * in an attempt to auto-negotiate with our link partner. 13858cfa0ad2SJack F Vogel */ 13868cfa0ad2SJack F Vogel DEBUGOUT("RXing /C/, enable AutoNeg and stop forcing link.\n"); 13878cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXCW, mac->txcw); 13888cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, (ctrl & ~E1000_CTRL_SLU)); 13898cfa0ad2SJack F Vogel 13908cfa0ad2SJack F Vogel mac->serdes_has_link = TRUE; 13918cfa0ad2SJack F Vogel } 13928cfa0ad2SJack F Vogel 13938cfa0ad2SJack F Vogel out: 13948cfa0ad2SJack F Vogel return ret_val; 13958cfa0ad2SJack F Vogel } 13968cfa0ad2SJack F Vogel 13978cfa0ad2SJack F Vogel /** 13988cfa0ad2SJack F Vogel * e1000_config_mac_to_phy_82543 - Configure MAC to PHY settings 13998cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14008cfa0ad2SJack F Vogel * 14018cfa0ad2SJack F Vogel * For the 82543 silicon, we need to set the MAC to match the settings 14028cfa0ad2SJack F Vogel * of the PHY, even if the PHY is auto-negotiating. 14038cfa0ad2SJack F Vogel **/ 14048cfa0ad2SJack F Vogel static s32 e1000_config_mac_to_phy_82543(struct e1000_hw *hw) 14058cfa0ad2SJack F Vogel { 14068cfa0ad2SJack F Vogel u32 ctrl; 14078cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 14088cfa0ad2SJack F Vogel u16 phy_data; 14098cfa0ad2SJack F Vogel 14108cfa0ad2SJack F Vogel DEBUGFUNC("e1000_config_mac_to_phy_82543"); 14118cfa0ad2SJack F Vogel 14128cfa0ad2SJack F Vogel if (!(hw->phy.ops.read_reg)) 14138cfa0ad2SJack F Vogel goto out; 14148cfa0ad2SJack F Vogel 14158cfa0ad2SJack F Vogel /* Set the bits to force speed and duplex */ 14168cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 14178cfa0ad2SJack F Vogel ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 14188cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_SPD_SEL | E1000_CTRL_ILOS); 14198cfa0ad2SJack F Vogel 14208cfa0ad2SJack F Vogel /* 14218cfa0ad2SJack F Vogel * Set up duplex in the Device Control and Transmit Control 14228cfa0ad2SJack F Vogel * registers depending on negotiated values. 14238cfa0ad2SJack F Vogel */ 14248cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); 14258cfa0ad2SJack F Vogel if (ret_val) 14268cfa0ad2SJack F Vogel goto out; 14278cfa0ad2SJack F Vogel 14288cfa0ad2SJack F Vogel ctrl &= ~E1000_CTRL_FD; 14298cfa0ad2SJack F Vogel if (phy_data & M88E1000_PSSR_DPLX) 14308cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_FD; 14318cfa0ad2SJack F Vogel 1432ab5d0362SJack F Vogel hw->mac.ops.config_collision_dist(hw); 14338cfa0ad2SJack F Vogel 14348cfa0ad2SJack F Vogel /* 14358cfa0ad2SJack F Vogel * Set up speed in the Device Control register depending on 14368cfa0ad2SJack F Vogel * negotiated values. 14378cfa0ad2SJack F Vogel */ 14388cfa0ad2SJack F Vogel if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) 14398cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SPD_1000; 14408cfa0ad2SJack F Vogel else if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_100MBS) 14418cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SPD_100; 14428cfa0ad2SJack F Vogel 14438cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 14448cfa0ad2SJack F Vogel 14458cfa0ad2SJack F Vogel out: 14468cfa0ad2SJack F Vogel return ret_val; 14478cfa0ad2SJack F Vogel } 14488cfa0ad2SJack F Vogel 14498cfa0ad2SJack F Vogel /** 14508cfa0ad2SJack F Vogel * e1000_write_vfta_82543 - Write value to VLAN filter table 14518cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14528cfa0ad2SJack F Vogel * @offset: the 32-bit offset in which to write the value to. 14538cfa0ad2SJack F Vogel * @value: the 32-bit value to write at location offset. 14548cfa0ad2SJack F Vogel * 14558cfa0ad2SJack F Vogel * This writes a 32-bit value to a 32-bit offset in the VLAN filter 14568cfa0ad2SJack F Vogel * table. 14578cfa0ad2SJack F Vogel **/ 14588cfa0ad2SJack F Vogel static void e1000_write_vfta_82543(struct e1000_hw *hw, u32 offset, u32 value) 14598cfa0ad2SJack F Vogel { 14608cfa0ad2SJack F Vogel u32 temp; 14618cfa0ad2SJack F Vogel 14628cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_vfta_82543"); 14638cfa0ad2SJack F Vogel 14648cfa0ad2SJack F Vogel if ((hw->mac.type == e1000_82544) && (offset & 1)) { 14658cfa0ad2SJack F Vogel temp = E1000_READ_REG_ARRAY(hw, E1000_VFTA, offset - 1); 14668cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); 14678cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 14688cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset - 1, temp); 14698cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 14708cfa0ad2SJack F Vogel } else { 14718cfa0ad2SJack F Vogel e1000_write_vfta_generic(hw, offset, value); 14728cfa0ad2SJack F Vogel } 14738cfa0ad2SJack F Vogel } 14748cfa0ad2SJack F Vogel 14758cfa0ad2SJack F Vogel /** 14768cfa0ad2SJack F Vogel * e1000_led_on_82543 - Turn on SW controllable LED 14778cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14788cfa0ad2SJack F Vogel * 1479daf9197cSJack F Vogel * Turns the SW defined LED on. 14808cfa0ad2SJack F Vogel **/ 14818cfa0ad2SJack F Vogel static s32 e1000_led_on_82543(struct e1000_hw *hw) 14828cfa0ad2SJack F Vogel { 14838cfa0ad2SJack F Vogel u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); 14848cfa0ad2SJack F Vogel 14858cfa0ad2SJack F Vogel DEBUGFUNC("e1000_led_on_82543"); 14868cfa0ad2SJack F Vogel 14878cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82544 && 14888cfa0ad2SJack F Vogel hw->phy.media_type == e1000_media_type_copper) { 14898cfa0ad2SJack F Vogel /* Clear SW-definable Pin 0 to turn on the LED */ 14908cfa0ad2SJack F Vogel ctrl &= ~E1000_CTRL_SWDPIN0; 14918cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SWDPIO0; 14928cfa0ad2SJack F Vogel } else { 14938cfa0ad2SJack F Vogel /* Fiber 82544 and all 82543 use this method */ 14948cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SWDPIN0; 14958cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SWDPIO0; 14968cfa0ad2SJack F Vogel } 14978cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 14988cfa0ad2SJack F Vogel 14998cfa0ad2SJack F Vogel return E1000_SUCCESS; 15008cfa0ad2SJack F Vogel } 15018cfa0ad2SJack F Vogel 15028cfa0ad2SJack F Vogel /** 15038cfa0ad2SJack F Vogel * e1000_led_off_82543 - Turn off SW controllable LED 15048cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 15058cfa0ad2SJack F Vogel * 1506daf9197cSJack F Vogel * Turns the SW defined LED off. 15078cfa0ad2SJack F Vogel **/ 15088cfa0ad2SJack F Vogel static s32 e1000_led_off_82543(struct e1000_hw *hw) 15098cfa0ad2SJack F Vogel { 15108cfa0ad2SJack F Vogel u32 ctrl = E1000_READ_REG(hw, E1000_CTRL); 15118cfa0ad2SJack F Vogel 15128cfa0ad2SJack F Vogel DEBUGFUNC("e1000_led_off_82543"); 15138cfa0ad2SJack F Vogel 15148cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82544 && 15158cfa0ad2SJack F Vogel hw->phy.media_type == e1000_media_type_copper) { 15168cfa0ad2SJack F Vogel /* Set SW-definable Pin 0 to turn off the LED */ 15178cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SWDPIN0; 15188cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SWDPIO0; 15198cfa0ad2SJack F Vogel } else { 15208cfa0ad2SJack F Vogel ctrl &= ~E1000_CTRL_SWDPIN0; 15218cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SWDPIO0; 15228cfa0ad2SJack F Vogel } 15238cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 15248cfa0ad2SJack F Vogel 15258cfa0ad2SJack F Vogel return E1000_SUCCESS; 15268cfa0ad2SJack F Vogel } 15278cfa0ad2SJack F Vogel 15288cfa0ad2SJack F Vogel /** 15298cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_82543 - Clear device specific hardware counters 15308cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 15318cfa0ad2SJack F Vogel * 15328cfa0ad2SJack F Vogel * Clears the hardware counters by reading the counter registers. 15338cfa0ad2SJack F Vogel **/ 15348cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82543(struct e1000_hw *hw) 15358cfa0ad2SJack F Vogel { 15368cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_82543"); 15378cfa0ad2SJack F Vogel 15388cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw); 15398cfa0ad2SJack F Vogel 1540daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC64); 1541daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC127); 1542daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC255); 1543daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC511); 1544daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1023); 1545daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1522); 1546daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC64); 1547daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC127); 1548daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC255); 1549daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC511); 1550daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1023); 1551daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1522); 15528cfa0ad2SJack F Vogel 1553daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ALGNERRC); 1554daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RXERRC); 1555daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TNCRS); 1556daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CEXTERR); 1557daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTC); 1558daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTFC); 15598cfa0ad2SJack F Vogel } 156074dbc418SJack F Vogel 156174dbc418SJack F Vogel /** 156274dbc418SJack F Vogel * e1000_read_mac_addr_82543 - Read device MAC address 156374dbc418SJack F Vogel * @hw: pointer to the HW structure 156474dbc418SJack F Vogel * 156574dbc418SJack F Vogel * Reads the device MAC address from the EEPROM and stores the value. 156674dbc418SJack F Vogel * Since devices with two ports use the same EEPROM, we increment the 156774dbc418SJack F Vogel * last bit in the MAC address for the second port. 156874dbc418SJack F Vogel * 156974dbc418SJack F Vogel **/ 157074dbc418SJack F Vogel s32 e1000_read_mac_addr_82543(struct e1000_hw *hw) 157174dbc418SJack F Vogel { 157274dbc418SJack F Vogel s32 ret_val = E1000_SUCCESS; 157374dbc418SJack F Vogel u16 offset, nvm_data, i; 157474dbc418SJack F Vogel 157574dbc418SJack F Vogel DEBUGFUNC("e1000_read_mac_addr"); 157674dbc418SJack F Vogel 157774dbc418SJack F Vogel for (i = 0; i < ETH_ADDR_LEN; i += 2) { 157874dbc418SJack F Vogel offset = i >> 1; 157974dbc418SJack F Vogel ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data); 158074dbc418SJack F Vogel if (ret_val) { 158174dbc418SJack F Vogel DEBUGOUT("NVM Read Error\n"); 158274dbc418SJack F Vogel goto out; 158374dbc418SJack F Vogel } 158474dbc418SJack F Vogel hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF); 158574dbc418SJack F Vogel hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8); 158674dbc418SJack F Vogel } 158774dbc418SJack F Vogel 158874dbc418SJack F Vogel /* Flip last bit of mac address if we're on second port */ 158974dbc418SJack F Vogel if (hw->bus.func == E1000_FUNC_1) 159074dbc418SJack F Vogel hw->mac.perm_addr[5] ^= 1; 159174dbc418SJack F Vogel 159274dbc418SJack F Vogel for (i = 0; i < ETH_ADDR_LEN; i++) 159374dbc418SJack F Vogel hw->mac.addr[i] = hw->mac.perm_addr[i]; 159474dbc418SJack F Vogel 159574dbc418SJack F Vogel out: 159674dbc418SJack F Vogel return ret_val; 159774dbc418SJack F Vogel } 1598