18cfa0ad2SJack F Vogel /******************************************************************************
27282444bSPedro F. Giffuni SPDX-License-Identifier: BSD-3-Clause
38cfa0ad2SJack F Vogel
4702cac6cSKevin Bowling Copyright (c) 2001-2020, 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
357609433eSJack F Vogel /* 80003ES2LAN Gigabit Ethernet Controller (Copper)
36daf9197cSJack F Vogel * 80003ES2LAN Gigabit Ethernet Controller (Serdes)
378cfa0ad2SJack F Vogel */
388cfa0ad2SJack F Vogel
398cfa0ad2SJack F Vogel #include "e1000_api.h"
408cfa0ad2SJack F Vogel
418cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw);
428cfa0ad2SJack F Vogel static void e1000_release_phy_80003es2lan(struct e1000_hw *hw);
438cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw);
448cfa0ad2SJack F Vogel static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw);
458cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
468cfa0ad2SJack F Vogel u32 offset,
478cfa0ad2SJack F Vogel u16 *data);
488cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
498cfa0ad2SJack F Vogel u32 offset,
508cfa0ad2SJack F Vogel u16 data);
518cfa0ad2SJack F Vogel static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
528cfa0ad2SJack F Vogel u16 words, u16 *data);
538cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw);
548cfa0ad2SJack F Vogel static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw);
558cfa0ad2SJack F Vogel static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw);
568cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
578cfa0ad2SJack F Vogel u16 *duplex);
588cfa0ad2SJack F Vogel static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw);
598cfa0ad2SJack F Vogel static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw);
608cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw);
618cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw);
628cfa0ad2SJack F Vogel static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex);
638cfa0ad2SJack F Vogel static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw);
64daf9197cSJack F Vogel static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw);
65daf9197cSJack F Vogel static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
66daf9197cSJack F Vogel u16 *data);
67daf9197cSJack F Vogel static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
68daf9197cSJack F Vogel u16 data);
698cfa0ad2SJack F Vogel static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw);
708cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw);
718cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw);
728cfa0ad2SJack F Vogel
737609433eSJack F Vogel /* A table for the GG82563 cable length where the range is defined
748cfa0ad2SJack F Vogel * with a lower bound at "index" and the upper bound at
758cfa0ad2SJack F Vogel * "index + 5".
768cfa0ad2SJack F Vogel */
77730d3130SJack F Vogel static const u16 e1000_gg82563_cable_length_table[] = {
78730d3130SJack F Vogel 0, 60, 115, 150, 150, 60, 115, 150, 180, 180, 0xFF };
798cfa0ad2SJack F Vogel #define GG82563_CABLE_LENGTH_TABLE_SIZE \
808cfa0ad2SJack F Vogel (sizeof(e1000_gg82563_cable_length_table) / \
818cfa0ad2SJack F Vogel sizeof(e1000_gg82563_cable_length_table[0]))
828cfa0ad2SJack F Vogel
838cfa0ad2SJack F Vogel /**
848cfa0ad2SJack F Vogel * e1000_init_phy_params_80003es2lan - Init ESB2 PHY func ptrs.
858cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
868cfa0ad2SJack F Vogel **/
e1000_init_phy_params_80003es2lan(struct e1000_hw * hw)878cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_80003es2lan(struct e1000_hw *hw)
888cfa0ad2SJack F Vogel {
898cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy;
907609433eSJack F Vogel s32 ret_val;
918cfa0ad2SJack F Vogel
928cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_80003es2lan");
938cfa0ad2SJack F Vogel
948cfa0ad2SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) {
958cfa0ad2SJack F Vogel phy->type = e1000_phy_none;
967609433eSJack F Vogel return E1000_SUCCESS;
978cfa0ad2SJack F Vogel } else {
988cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper;
998cfa0ad2SJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper_80003es2lan;
1008cfa0ad2SJack F Vogel }
1018cfa0ad2SJack F Vogel
1028cfa0ad2SJack F Vogel phy->addr = 1;
1038cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
1048cfa0ad2SJack F Vogel phy->reset_delay_us = 100;
1058cfa0ad2SJack F Vogel phy->type = e1000_phy_gg82563;
1068cfa0ad2SJack F Vogel
1078cfa0ad2SJack F Vogel phy->ops.acquire = e1000_acquire_phy_80003es2lan;
1088cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88;
1098cfa0ad2SJack F Vogel phy->ops.check_reset_block = e1000_check_reset_block_generic;
1108cfa0ad2SJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic;
1118cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_80003es2lan;
1128cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88;
1138cfa0ad2SJack F Vogel phy->ops.release = e1000_release_phy_80003es2lan;
1148cfa0ad2SJack F Vogel phy->ops.reset = e1000_phy_hw_reset_generic;
1158cfa0ad2SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
1168cfa0ad2SJack F Vogel
1178cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_80003es2lan;
1188cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_80003es2lan;
1198cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_gg82563_80003es2lan;
1208cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_gg82563_80003es2lan;
1218cfa0ad2SJack F Vogel
122daf9197cSJack F Vogel phy->ops.cfg_on_link_up = e1000_cfg_on_link_up_80003es2lan;
123daf9197cSJack F Vogel
1248cfa0ad2SJack F Vogel /* This can only be done after all function pointers are setup. */
1258cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw);
1268cfa0ad2SJack F Vogel
1278cfa0ad2SJack F Vogel /* Verify phy id */
1287609433eSJack F Vogel if (phy->id != GG82563_E_PHY_ID)
1297609433eSJack F Vogel return -E1000_ERR_PHY;
1308cfa0ad2SJack F Vogel
1318cfa0ad2SJack F Vogel return ret_val;
1328cfa0ad2SJack F Vogel }
1338cfa0ad2SJack F Vogel
1348cfa0ad2SJack F Vogel /**
1358cfa0ad2SJack F Vogel * e1000_init_nvm_params_80003es2lan - Init ESB2 NVM func ptrs.
1368cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
1378cfa0ad2SJack F Vogel **/
e1000_init_nvm_params_80003es2lan(struct e1000_hw * hw)1388cfa0ad2SJack F Vogel static s32 e1000_init_nvm_params_80003es2lan(struct e1000_hw *hw)
1398cfa0ad2SJack F Vogel {
1408cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm;
1418cfa0ad2SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD);
1428cfa0ad2SJack F Vogel u16 size;
1438cfa0ad2SJack F Vogel
1448cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_80003es2lan");
1458cfa0ad2SJack F Vogel
1468cfa0ad2SJack F Vogel nvm->opcode_bits = 8;
1478cfa0ad2SJack F Vogel nvm->delay_usec = 1;
1488cfa0ad2SJack F Vogel switch (nvm->override) {
1498cfa0ad2SJack F Vogel case e1000_nvm_override_spi_large:
1508cfa0ad2SJack F Vogel nvm->page_size = 32;
1518cfa0ad2SJack F Vogel nvm->address_bits = 16;
1528cfa0ad2SJack F Vogel break;
1538cfa0ad2SJack F Vogel case e1000_nvm_override_spi_small:
1548cfa0ad2SJack F Vogel nvm->page_size = 8;
1558cfa0ad2SJack F Vogel nvm->address_bits = 8;
1568cfa0ad2SJack F Vogel break;
1578cfa0ad2SJack F Vogel default:
1588cfa0ad2SJack F Vogel nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
1598cfa0ad2SJack F Vogel nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 16 : 8;
1608cfa0ad2SJack F Vogel break;
1618cfa0ad2SJack F Vogel }
1628cfa0ad2SJack F Vogel
1638cfa0ad2SJack F Vogel nvm->type = e1000_nvm_eeprom_spi;
1648cfa0ad2SJack F Vogel
1658cfa0ad2SJack F Vogel size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
1668cfa0ad2SJack F Vogel E1000_EECD_SIZE_EX_SHIFT);
1678cfa0ad2SJack F Vogel
1687609433eSJack F Vogel /* Added to a constant, "size" becomes the left-shift value
1698cfa0ad2SJack F Vogel * for setting word_size.
1708cfa0ad2SJack F Vogel */
1718cfa0ad2SJack F Vogel size += NVM_WORD_SIZE_BASE_SHIFT;
1728cfa0ad2SJack F Vogel
1738cfa0ad2SJack F Vogel /* EEPROM access above 16k is unsupported */
1748cfa0ad2SJack F Vogel if (size > 14)
1758cfa0ad2SJack F Vogel size = 14;
1768cfa0ad2SJack F Vogel nvm->word_size = 1 << size;
1778cfa0ad2SJack F Vogel
1788cfa0ad2SJack F Vogel /* Function Pointers */
1798cfa0ad2SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_80003es2lan;
1808cfa0ad2SJack F Vogel nvm->ops.read = e1000_read_nvm_eerd;
1818cfa0ad2SJack F Vogel nvm->ops.release = e1000_release_nvm_80003es2lan;
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_80003es2lan;
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_80003es2lan - Init ESB2 MAC func ptrs.
1928cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
1938cfa0ad2SJack F Vogel **/
e1000_init_mac_params_80003es2lan(struct e1000_hw * hw)1948cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_80003es2lan(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_80003es2lan");
1998cfa0ad2SJack F Vogel
2004edd8523SJack F Vogel /* Set media type and media-dependent function pointers */
2018cfa0ad2SJack F Vogel switch (hw->device_id) {
2028cfa0ad2SJack F Vogel case E1000_DEV_ID_80003ES2LAN_SERDES_DPT:
2038cfa0ad2SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes;
2044edd8523SJack F Vogel mac->ops.check_for_link = e1000_check_for_serdes_link_generic;
2054edd8523SJack F Vogel mac->ops.setup_physical_interface =
2064edd8523SJack F Vogel e1000_setup_fiber_serdes_link_generic;
2078cfa0ad2SJack F Vogel break;
2088cfa0ad2SJack F Vogel default:
2098cfa0ad2SJack F Vogel hw->phy.media_type = e1000_media_type_copper;
2104edd8523SJack F Vogel mac->ops.check_for_link = e1000_check_for_copper_link_generic;
2114edd8523SJack F Vogel mac->ops.setup_physical_interface =
2124edd8523SJack F Vogel e1000_setup_copper_link_80003es2lan;
2138cfa0ad2SJack F Vogel break;
2148cfa0ad2SJack F Vogel }
2158cfa0ad2SJack F Vogel
2168cfa0ad2SJack F Vogel /* Set mta register count */
2178cfa0ad2SJack F Vogel mac->mta_reg_count = 128;
2188cfa0ad2SJack F Vogel /* Set rar entry count */
2198cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES;
2208cfa0ad2SJack F Vogel /* Set if part includes ASF firmware */
221*1bbdc25fSKevin Bowling mac->asf_firmware_present = true;
2228ec87fc5SJack F Vogel /* FWSM register */
223*1bbdc25fSKevin Bowling mac->has_fwsm = true;
2248ec87fc5SJack F Vogel /* ARC supported; valid only if manageability features are enabled. */
2257609433eSJack F Vogel mac->arc_subsystem_valid = !!(E1000_READ_REG(hw, E1000_FWSM) &
2267609433eSJack F Vogel E1000_FWSM_MODE_MASK);
2274edd8523SJack F Vogel /* Adaptive IFS not supported */
228*1bbdc25fSKevin Bowling mac->adaptive_ifs = false;
2298cfa0ad2SJack F Vogel
2308cfa0ad2SJack F Vogel /* Function pointers */
2318cfa0ad2SJack F Vogel
2328cfa0ad2SJack F Vogel /* bus type/speed/width */
2338cfa0ad2SJack F Vogel mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
2348cfa0ad2SJack F Vogel /* reset */
2358cfa0ad2SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_80003es2lan;
2368cfa0ad2SJack F Vogel /* hw initialization */
2378cfa0ad2SJack F Vogel mac->ops.init_hw = e1000_init_hw_80003es2lan;
2388cfa0ad2SJack F Vogel /* link setup */
2398cfa0ad2SJack F Vogel mac->ops.setup_link = e1000_setup_link_generic;
2408cfa0ad2SJack F Vogel /* check management mode */
2418cfa0ad2SJack F Vogel mac->ops.check_mng_mode = e1000_check_mng_mode_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_generic;
2468cfa0ad2SJack F Vogel /* clearing VFTA */
2478cfa0ad2SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_generic;
2488cfa0ad2SJack F Vogel /* read mac address */
2498cfa0ad2SJack F Vogel mac->ops.read_mac_addr = e1000_read_mac_addr_80003es2lan;
250d035aa2dSJack F Vogel /* ID LED init */
251d035aa2dSJack F Vogel mac->ops.id_led_init = e1000_id_led_init_generic;
2528cfa0ad2SJack F Vogel /* blink LED */
2538cfa0ad2SJack F Vogel mac->ops.blink_led = e1000_blink_led_generic;
2548cfa0ad2SJack F Vogel /* setup LED */
2558cfa0ad2SJack F Vogel mac->ops.setup_led = e1000_setup_led_generic;
2568cfa0ad2SJack F Vogel /* cleanup LED */
2578cfa0ad2SJack F Vogel mac->ops.cleanup_led = e1000_cleanup_led_generic;
2588cfa0ad2SJack F Vogel /* turn on/off LED */
2598cfa0ad2SJack F Vogel mac->ops.led_on = e1000_led_on_generic;
2608cfa0ad2SJack F Vogel mac->ops.led_off = e1000_led_off_generic;
2618cfa0ad2SJack F Vogel /* clear hardware counters */
2628cfa0ad2SJack F Vogel mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_80003es2lan;
2638cfa0ad2SJack F Vogel /* link info */
2648cfa0ad2SJack F Vogel mac->ops.get_link_up_info = e1000_get_link_up_info_80003es2lan;
2658cfa0ad2SJack F Vogel
2664edd8523SJack F Vogel /* set lan id for port to determine which phy lock to use */
2674edd8523SJack F Vogel hw->mac.ops.set_lan_id(hw);
2684edd8523SJack F Vogel
2694edd8523SJack F Vogel return E1000_SUCCESS;
2708cfa0ad2SJack F Vogel }
2718cfa0ad2SJack F Vogel
2728cfa0ad2SJack F Vogel /**
2738cfa0ad2SJack F Vogel * e1000_init_function_pointers_80003es2lan - Init ESB2 func ptrs.
2748cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
2758cfa0ad2SJack F Vogel *
276daf9197cSJack F Vogel * Called to initialize all function pointers and parameters.
2778cfa0ad2SJack F Vogel **/
e1000_init_function_pointers_80003es2lan(struct e1000_hw * hw)2788cfa0ad2SJack F Vogel void e1000_init_function_pointers_80003es2lan(struct e1000_hw *hw)
2798cfa0ad2SJack F Vogel {
2808cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_80003es2lan");
2818cfa0ad2SJack F Vogel
2828cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_80003es2lan;
2838cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_80003es2lan;
2848cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_80003es2lan;
2858cfa0ad2SJack F Vogel }
2868cfa0ad2SJack F Vogel
2878cfa0ad2SJack F Vogel /**
2888cfa0ad2SJack F Vogel * e1000_acquire_phy_80003es2lan - Acquire rights to access PHY
2898cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
2908cfa0ad2SJack F Vogel *
291daf9197cSJack F Vogel * A wrapper to acquire access rights to the correct PHY.
2928cfa0ad2SJack F Vogel **/
e1000_acquire_phy_80003es2lan(struct e1000_hw * hw)2938cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_80003es2lan(struct e1000_hw *hw)
2948cfa0ad2SJack F Vogel {
2958cfa0ad2SJack F Vogel u16 mask;
2968cfa0ad2SJack F Vogel
2978cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_phy_80003es2lan");
2988cfa0ad2SJack F Vogel
2998cfa0ad2SJack F Vogel mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
300d5210708SMatt Macy return e1000_acquire_swfw_sync(hw, mask);
3018cfa0ad2SJack F Vogel }
3028cfa0ad2SJack F Vogel
3038cfa0ad2SJack F Vogel /**
3048cfa0ad2SJack F Vogel * e1000_release_phy_80003es2lan - Release rights to access PHY
3058cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
3068cfa0ad2SJack F Vogel *
307daf9197cSJack F Vogel * A wrapper to release access rights to the correct PHY.
3088cfa0ad2SJack F Vogel **/
e1000_release_phy_80003es2lan(struct e1000_hw * hw)3098cfa0ad2SJack F Vogel static void e1000_release_phy_80003es2lan(struct e1000_hw *hw)
3108cfa0ad2SJack F Vogel {
3118cfa0ad2SJack F Vogel u16 mask;
3128cfa0ad2SJack F Vogel
3138cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_phy_80003es2lan");
3148cfa0ad2SJack F Vogel
3158cfa0ad2SJack F Vogel mask = hw->bus.func ? E1000_SWFW_PHY1_SM : E1000_SWFW_PHY0_SM;
316d5210708SMatt Macy e1000_release_swfw_sync(hw, mask);
317daf9197cSJack F Vogel }
318daf9197cSJack F Vogel
319daf9197cSJack F Vogel /**
3204dab5c37SJack F Vogel * e1000_acquire_mac_csr_80003es2lan - Acquire right to access Kumeran register
321daf9197cSJack F Vogel * @hw: pointer to the HW structure
322daf9197cSJack F Vogel *
323daf9197cSJack F Vogel * Acquire the semaphore to access the Kumeran interface.
324daf9197cSJack F Vogel *
325daf9197cSJack F Vogel **/
e1000_acquire_mac_csr_80003es2lan(struct e1000_hw * hw)326daf9197cSJack F Vogel static s32 e1000_acquire_mac_csr_80003es2lan(struct e1000_hw *hw)
327daf9197cSJack F Vogel {
328daf9197cSJack F Vogel u16 mask;
329daf9197cSJack F Vogel
330daf9197cSJack F Vogel DEBUGFUNC("e1000_acquire_mac_csr_80003es2lan");
331daf9197cSJack F Vogel
332daf9197cSJack F Vogel mask = E1000_SWFW_CSR_SM;
333daf9197cSJack F Vogel
334d5210708SMatt Macy return e1000_acquire_swfw_sync(hw, mask);
335daf9197cSJack F Vogel }
336daf9197cSJack F Vogel
337daf9197cSJack F Vogel /**
3384dab5c37SJack F Vogel * e1000_release_mac_csr_80003es2lan - Release right to access Kumeran Register
339daf9197cSJack F Vogel * @hw: pointer to the HW structure
340daf9197cSJack F Vogel *
341daf9197cSJack F Vogel * Release the semaphore used to access the Kumeran interface
342daf9197cSJack F Vogel **/
e1000_release_mac_csr_80003es2lan(struct e1000_hw * hw)343daf9197cSJack F Vogel static void e1000_release_mac_csr_80003es2lan(struct e1000_hw *hw)
344daf9197cSJack F Vogel {
345daf9197cSJack F Vogel u16 mask;
346daf9197cSJack F Vogel
347daf9197cSJack F Vogel DEBUGFUNC("e1000_release_mac_csr_80003es2lan");
348daf9197cSJack F Vogel
349daf9197cSJack F Vogel mask = E1000_SWFW_CSR_SM;
3508cfa0ad2SJack F Vogel
351d5210708SMatt Macy e1000_release_swfw_sync(hw, mask);
3528cfa0ad2SJack F Vogel }
3538cfa0ad2SJack F Vogel
3548cfa0ad2SJack F Vogel /**
3558cfa0ad2SJack F Vogel * e1000_acquire_nvm_80003es2lan - Acquire rights to access NVM
3568cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
3578cfa0ad2SJack F Vogel *
358daf9197cSJack F Vogel * Acquire the semaphore to access the EEPROM.
3598cfa0ad2SJack F Vogel **/
e1000_acquire_nvm_80003es2lan(struct e1000_hw * hw)3608cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_80003es2lan(struct e1000_hw *hw)
3618cfa0ad2SJack F Vogel {
3628cfa0ad2SJack F Vogel s32 ret_val;
3638cfa0ad2SJack F Vogel
3648cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_nvm_80003es2lan");
3658cfa0ad2SJack F Vogel
366d5210708SMatt Macy ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
3678cfa0ad2SJack F Vogel if (ret_val)
3687609433eSJack F Vogel return ret_val;
3698cfa0ad2SJack F Vogel
3708cfa0ad2SJack F Vogel ret_val = e1000_acquire_nvm_generic(hw);
3718cfa0ad2SJack F Vogel
3728cfa0ad2SJack F Vogel if (ret_val)
373d5210708SMatt Macy e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
3748cfa0ad2SJack F Vogel
3758cfa0ad2SJack F Vogel return ret_val;
3768cfa0ad2SJack F Vogel }
3778cfa0ad2SJack F Vogel
3788cfa0ad2SJack F Vogel /**
3798cfa0ad2SJack F Vogel * e1000_release_nvm_80003es2lan - Relinquish rights to access NVM
3808cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
3818cfa0ad2SJack F Vogel *
382daf9197cSJack F Vogel * Release the semaphore used to access the EEPROM.
3838cfa0ad2SJack F Vogel **/
e1000_release_nvm_80003es2lan(struct e1000_hw * hw)3848cfa0ad2SJack F Vogel static void e1000_release_nvm_80003es2lan(struct e1000_hw *hw)
3858cfa0ad2SJack F Vogel {
3868cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_nvm_80003es2lan");
3878cfa0ad2SJack F Vogel
3888cfa0ad2SJack F Vogel e1000_release_nvm_generic(hw);
389d5210708SMatt Macy e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
3908cfa0ad2SJack F Vogel }
3918cfa0ad2SJack F Vogel
3928cfa0ad2SJack F Vogel /**
3938cfa0ad2SJack F Vogel * e1000_read_phy_reg_gg82563_80003es2lan - Read GG82563 PHY register
3948cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
3958cfa0ad2SJack F Vogel * @offset: offset of the register to read
3968cfa0ad2SJack F Vogel * @data: pointer to the data returned from the operation
3978cfa0ad2SJack F Vogel *
398daf9197cSJack F Vogel * Read the GG82563 PHY register.
3998cfa0ad2SJack F Vogel **/
e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)4008cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
4018cfa0ad2SJack F Vogel u32 offset, u16 *data)
4028cfa0ad2SJack F Vogel {
4038cfa0ad2SJack F Vogel s32 ret_val;
4048cfa0ad2SJack F Vogel u32 page_select;
4058cfa0ad2SJack F Vogel u16 temp;
4068cfa0ad2SJack F Vogel
4078cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_gg82563_80003es2lan");
4088cfa0ad2SJack F Vogel
4098cfa0ad2SJack F Vogel ret_val = e1000_acquire_phy_80003es2lan(hw);
4108cfa0ad2SJack F Vogel if (ret_val)
4117609433eSJack F Vogel return ret_val;
4128cfa0ad2SJack F Vogel
4138cfa0ad2SJack F Vogel /* Select Configuration Page */
4148cfa0ad2SJack F Vogel if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
4158cfa0ad2SJack F Vogel page_select = GG82563_PHY_PAGE_SELECT;
4168cfa0ad2SJack F Vogel } else {
4177609433eSJack F Vogel /* Use Alternative Page Select register to access
4188cfa0ad2SJack F Vogel * registers 30 and 31
4198cfa0ad2SJack F Vogel */
4208cfa0ad2SJack F Vogel page_select = GG82563_PHY_PAGE_SELECT_ALT;
4218cfa0ad2SJack F Vogel }
4228cfa0ad2SJack F Vogel
4238cfa0ad2SJack F Vogel temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
4248cfa0ad2SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
4258cfa0ad2SJack F Vogel if (ret_val) {
4268cfa0ad2SJack F Vogel e1000_release_phy_80003es2lan(hw);
4277609433eSJack F Vogel return ret_val;
4288cfa0ad2SJack F Vogel }
4298cfa0ad2SJack F Vogel
4307609433eSJack F Vogel if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
4317609433eSJack F Vogel /* The "ready" bit in the MDIC register may be incorrectly set
4328cfa0ad2SJack F Vogel * before the device has completed the "Page Select" MDI
4338cfa0ad2SJack F Vogel * transaction. So we wait 200us after each MDI command...
4348cfa0ad2SJack F Vogel */
4358cfa0ad2SJack F Vogel usec_delay(200);
4368cfa0ad2SJack F Vogel
4378cfa0ad2SJack F Vogel /* ...and verify the command was successful. */
4388cfa0ad2SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
4398cfa0ad2SJack F Vogel
4408cfa0ad2SJack F Vogel if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
4418cfa0ad2SJack F Vogel e1000_release_phy_80003es2lan(hw);
4427609433eSJack F Vogel return -E1000_ERR_PHY;
4438cfa0ad2SJack F Vogel }
4448cfa0ad2SJack F Vogel
4458cfa0ad2SJack F Vogel usec_delay(200);
4468cfa0ad2SJack F Vogel
4474edd8523SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw,
4484edd8523SJack F Vogel MAX_PHY_REG_ADDRESS & offset,
4498cfa0ad2SJack F Vogel data);
4508cfa0ad2SJack F Vogel
4518cfa0ad2SJack F Vogel usec_delay(200);
4524edd8523SJack F Vogel } else {
4534edd8523SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw,
4544edd8523SJack F Vogel MAX_PHY_REG_ADDRESS & offset,
4554edd8523SJack F Vogel data);
4564edd8523SJack F Vogel }
4574edd8523SJack F Vogel
4588cfa0ad2SJack F Vogel e1000_release_phy_80003es2lan(hw);
4598cfa0ad2SJack F Vogel
4608cfa0ad2SJack F Vogel return ret_val;
4618cfa0ad2SJack F Vogel }
4628cfa0ad2SJack F Vogel
4638cfa0ad2SJack F Vogel /**
4648cfa0ad2SJack F Vogel * e1000_write_phy_reg_gg82563_80003es2lan - Write GG82563 PHY register
4658cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
4668cfa0ad2SJack F Vogel * @offset: offset of the register to read
4678cfa0ad2SJack F Vogel * @data: value to write to the register
4688cfa0ad2SJack F Vogel *
469daf9197cSJack F Vogel * Write to the GG82563 PHY register.
4708cfa0ad2SJack F Vogel **/
e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)4718cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_gg82563_80003es2lan(struct e1000_hw *hw,
4728cfa0ad2SJack F Vogel u32 offset, u16 data)
4738cfa0ad2SJack F Vogel {
4748cfa0ad2SJack F Vogel s32 ret_val;
4758cfa0ad2SJack F Vogel u32 page_select;
4768cfa0ad2SJack F Vogel u16 temp;
4778cfa0ad2SJack F Vogel
4788cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_gg82563_80003es2lan");
4798cfa0ad2SJack F Vogel
4808cfa0ad2SJack F Vogel ret_val = e1000_acquire_phy_80003es2lan(hw);
4818cfa0ad2SJack F Vogel if (ret_val)
4827609433eSJack F Vogel return ret_val;
4838cfa0ad2SJack F Vogel
4848cfa0ad2SJack F Vogel /* Select Configuration Page */
4858cfa0ad2SJack F Vogel if ((offset & MAX_PHY_REG_ADDRESS) < GG82563_MIN_ALT_REG) {
4868cfa0ad2SJack F Vogel page_select = GG82563_PHY_PAGE_SELECT;
4878cfa0ad2SJack F Vogel } else {
4887609433eSJack F Vogel /* Use Alternative Page Select register to access
4898cfa0ad2SJack F Vogel * registers 30 and 31
4908cfa0ad2SJack F Vogel */
4918cfa0ad2SJack F Vogel page_select = GG82563_PHY_PAGE_SELECT_ALT;
4928cfa0ad2SJack F Vogel }
4938cfa0ad2SJack F Vogel
4948cfa0ad2SJack F Vogel temp = (u16)((u16)offset >> GG82563_PAGE_SHIFT);
4958cfa0ad2SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw, page_select, temp);
4968cfa0ad2SJack F Vogel if (ret_val) {
4978cfa0ad2SJack F Vogel e1000_release_phy_80003es2lan(hw);
4987609433eSJack F Vogel return ret_val;
4998cfa0ad2SJack F Vogel }
5008cfa0ad2SJack F Vogel
5017609433eSJack F Vogel if (hw->dev_spec._80003es2lan.mdic_wa_enable) {
5027609433eSJack F Vogel /* The "ready" bit in the MDIC register may be incorrectly set
5038cfa0ad2SJack F Vogel * before the device has completed the "Page Select" MDI
5048cfa0ad2SJack F Vogel * transaction. So we wait 200us after each MDI command...
5058cfa0ad2SJack F Vogel */
5068cfa0ad2SJack F Vogel usec_delay(200);
5078cfa0ad2SJack F Vogel
5088cfa0ad2SJack F Vogel /* ...and verify the command was successful. */
5098cfa0ad2SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw, page_select, &temp);
5108cfa0ad2SJack F Vogel
5118cfa0ad2SJack F Vogel if (((u16)offset >> GG82563_PAGE_SHIFT) != temp) {
5128cfa0ad2SJack F Vogel e1000_release_phy_80003es2lan(hw);
5137609433eSJack F Vogel return -E1000_ERR_PHY;
5148cfa0ad2SJack F Vogel }
5158cfa0ad2SJack F Vogel
5168cfa0ad2SJack F Vogel usec_delay(200);
5178cfa0ad2SJack F Vogel
5184edd8523SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw,
5194edd8523SJack F Vogel MAX_PHY_REG_ADDRESS & offset,
5208cfa0ad2SJack F Vogel data);
5218cfa0ad2SJack F Vogel
5228cfa0ad2SJack F Vogel usec_delay(200);
5234edd8523SJack F Vogel } else {
5244edd8523SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw,
5254edd8523SJack F Vogel MAX_PHY_REG_ADDRESS & offset,
5264edd8523SJack F Vogel data);
5274edd8523SJack F Vogel }
5284edd8523SJack F Vogel
5298cfa0ad2SJack F Vogel e1000_release_phy_80003es2lan(hw);
5308cfa0ad2SJack F Vogel
5318cfa0ad2SJack F Vogel return ret_val;
5328cfa0ad2SJack F Vogel }
5338cfa0ad2SJack F Vogel
5348cfa0ad2SJack F Vogel /**
5358cfa0ad2SJack F Vogel * e1000_write_nvm_80003es2lan - Write to ESB2 NVM
5368cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
5378cfa0ad2SJack F Vogel * @offset: offset of the register to read
5388cfa0ad2SJack F Vogel * @words: number of words to write
5398cfa0ad2SJack F Vogel * @data: buffer of data to write to the NVM
5408cfa0ad2SJack F Vogel *
541daf9197cSJack F Vogel * Write "words" of data to the ESB2 NVM.
5428cfa0ad2SJack F Vogel **/
e1000_write_nvm_80003es2lan(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)5438cfa0ad2SJack F Vogel static s32 e1000_write_nvm_80003es2lan(struct e1000_hw *hw, u16 offset,
5448cfa0ad2SJack F Vogel u16 words, u16 *data)
5458cfa0ad2SJack F Vogel {
5468cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_nvm_80003es2lan");
5478cfa0ad2SJack F Vogel
5488cfa0ad2SJack F Vogel return e1000_write_nvm_spi(hw, offset, words, data);
5498cfa0ad2SJack F Vogel }
5508cfa0ad2SJack F Vogel
5518cfa0ad2SJack F Vogel /**
5528cfa0ad2SJack F Vogel * e1000_get_cfg_done_80003es2lan - Wait for configuration to complete
5538cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
5548cfa0ad2SJack F Vogel *
5558cfa0ad2SJack F Vogel * Wait a specific amount of time for manageability processes to complete.
5568cfa0ad2SJack F Vogel * This is a function pointer entry point called by the phy module.
5578cfa0ad2SJack F Vogel **/
e1000_get_cfg_done_80003es2lan(struct e1000_hw * hw)5588cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_80003es2lan(struct e1000_hw *hw)
5598cfa0ad2SJack F Vogel {
5608cfa0ad2SJack F Vogel s32 timeout = PHY_CFG_TIMEOUT;
5618cfa0ad2SJack F Vogel u32 mask = E1000_NVM_CFG_DONE_PORT_0;
5628cfa0ad2SJack F Vogel
5638cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_cfg_done_80003es2lan");
5648cfa0ad2SJack F Vogel
5658cfa0ad2SJack F Vogel if (hw->bus.func == 1)
5668cfa0ad2SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_1;
5678cfa0ad2SJack F Vogel
5688cfa0ad2SJack F Vogel while (timeout) {
5698cfa0ad2SJack F Vogel if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
5708cfa0ad2SJack F Vogel break;
5718cfa0ad2SJack F Vogel msec_delay(1);
5728cfa0ad2SJack F Vogel timeout--;
5738cfa0ad2SJack F Vogel }
5748cfa0ad2SJack F Vogel if (!timeout) {
5758cfa0ad2SJack F Vogel DEBUGOUT("MNG configuration cycle has not completed.\n");
5767609433eSJack F Vogel return -E1000_ERR_RESET;
5778cfa0ad2SJack F Vogel }
5788cfa0ad2SJack F Vogel
5797609433eSJack F Vogel return E1000_SUCCESS;
5808cfa0ad2SJack F Vogel }
5818cfa0ad2SJack F Vogel
5828cfa0ad2SJack F Vogel /**
5838cfa0ad2SJack F Vogel * e1000_phy_force_speed_duplex_80003es2lan - Force PHY speed and duplex
5848cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
5858cfa0ad2SJack F Vogel *
5868cfa0ad2SJack F Vogel * Force the speed and duplex settings onto the PHY. This is a
5878cfa0ad2SJack F Vogel * function pointer entry point called by the phy module.
5888cfa0ad2SJack F Vogel **/
e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw * hw)5898cfa0ad2SJack F Vogel static s32 e1000_phy_force_speed_duplex_80003es2lan(struct e1000_hw *hw)
5908cfa0ad2SJack F Vogel {
5917609433eSJack F Vogel s32 ret_val;
5928cfa0ad2SJack F Vogel u16 phy_data;
5938cfa0ad2SJack F Vogel bool link;
5948cfa0ad2SJack F Vogel
5958cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_force_speed_duplex_80003es2lan");
5968cfa0ad2SJack F Vogel
5978cfa0ad2SJack F Vogel if (!(hw->phy.ops.read_reg))
5987609433eSJack F Vogel return E1000_SUCCESS;
5998cfa0ad2SJack F Vogel
6007609433eSJack F Vogel /* Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI
6018cfa0ad2SJack F Vogel * forced whenever speed and duplex are forced.
6028cfa0ad2SJack F Vogel */
6038cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
6048cfa0ad2SJack F Vogel if (ret_val)
6057609433eSJack F Vogel return ret_val;
6068cfa0ad2SJack F Vogel
6078cfa0ad2SJack F Vogel phy_data &= ~GG82563_PSCR_CROSSOVER_MODE_AUTO;
6088cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, phy_data);
6098cfa0ad2SJack F Vogel if (ret_val)
6107609433eSJack F Vogel return ret_val;
6118cfa0ad2SJack F Vogel
6128cfa0ad2SJack F Vogel DEBUGOUT1("GG82563 PSCR: %X\n", phy_data);
6138cfa0ad2SJack F Vogel
6148cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_data);
6158cfa0ad2SJack F Vogel if (ret_val)
6167609433eSJack F Vogel return ret_val;
6178cfa0ad2SJack F Vogel
6188cfa0ad2SJack F Vogel e1000_phy_force_speed_duplex_setup(hw, &phy_data);
6198cfa0ad2SJack F Vogel
6208cfa0ad2SJack F Vogel /* Reset the phy to commit changes. */
6218cfa0ad2SJack F Vogel phy_data |= MII_CR_RESET;
6228cfa0ad2SJack F Vogel
6238cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_data);
6248cfa0ad2SJack F Vogel if (ret_val)
6257609433eSJack F Vogel return ret_val;
6268cfa0ad2SJack F Vogel
6278cfa0ad2SJack F Vogel usec_delay(1);
6288cfa0ad2SJack F Vogel
6298cfa0ad2SJack F Vogel if (hw->phy.autoneg_wait_to_complete) {
6304dab5c37SJack F Vogel DEBUGOUT("Waiting for forced speed/duplex link on GG82563 phy.\n");
6318cfa0ad2SJack F Vogel
6328cfa0ad2SJack F Vogel ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
6338cfa0ad2SJack F Vogel 100000, &link);
6348cfa0ad2SJack F Vogel if (ret_val)
6357609433eSJack F Vogel return ret_val;
6368cfa0ad2SJack F Vogel
6378cfa0ad2SJack F Vogel if (!link) {
6387609433eSJack F Vogel /* We didn't get link.
6398cfa0ad2SJack F Vogel * Reset the DSP and cross our fingers.
6408cfa0ad2SJack F Vogel */
6418cfa0ad2SJack F Vogel ret_val = e1000_phy_reset_dsp_generic(hw);
6428cfa0ad2SJack F Vogel if (ret_val)
6437609433eSJack F Vogel return ret_val;
6448cfa0ad2SJack F Vogel }
6458cfa0ad2SJack F Vogel
6468cfa0ad2SJack F Vogel /* Try once more */
6478cfa0ad2SJack F Vogel ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
6488cfa0ad2SJack F Vogel 100000, &link);
6498cfa0ad2SJack F Vogel if (ret_val)
6507609433eSJack F Vogel return ret_val;
6518cfa0ad2SJack F Vogel }
6528cfa0ad2SJack F Vogel
6534dab5c37SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
6544dab5c37SJack F Vogel &phy_data);
6558cfa0ad2SJack F Vogel if (ret_val)
6567609433eSJack F Vogel return ret_val;
6578cfa0ad2SJack F Vogel
6587609433eSJack F Vogel /* Resetting the phy means we need to verify the TX_CLK corresponds
6598cfa0ad2SJack F Vogel * to the link speed. 10Mbps -> 2.5MHz, else 25MHz.
6608cfa0ad2SJack F Vogel */
6618cfa0ad2SJack F Vogel phy_data &= ~GG82563_MSCR_TX_CLK_MASK;
6628cfa0ad2SJack F Vogel if (hw->mac.forced_speed_duplex & E1000_ALL_10_SPEED)
6638cfa0ad2SJack F Vogel phy_data |= GG82563_MSCR_TX_CLK_10MBPS_2_5;
6648cfa0ad2SJack F Vogel else
6658cfa0ad2SJack F Vogel phy_data |= GG82563_MSCR_TX_CLK_100MBPS_25;
6668cfa0ad2SJack F Vogel
6677609433eSJack F Vogel /* In addition, we must re-enable CRS on Tx for both half and full
6688cfa0ad2SJack F Vogel * duplex.
6698cfa0ad2SJack F Vogel */
6708cfa0ad2SJack F Vogel phy_data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
6714dab5c37SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL,
6724dab5c37SJack F Vogel phy_data);
6738cfa0ad2SJack F Vogel
6748cfa0ad2SJack F Vogel return ret_val;
6758cfa0ad2SJack F Vogel }
6768cfa0ad2SJack F Vogel
6778cfa0ad2SJack F Vogel /**
6788cfa0ad2SJack F Vogel * e1000_get_cable_length_80003es2lan - Set approximate cable length
6798cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
6808cfa0ad2SJack F Vogel *
6818cfa0ad2SJack F Vogel * Find the approximate cable length as measured by the GG82563 PHY.
6828cfa0ad2SJack F Vogel * This is a function pointer entry point called by the phy module.
6838cfa0ad2SJack F Vogel **/
e1000_get_cable_length_80003es2lan(struct e1000_hw * hw)6848cfa0ad2SJack F Vogel static s32 e1000_get_cable_length_80003es2lan(struct e1000_hw *hw)
6858cfa0ad2SJack F Vogel {
6868cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy;
6877609433eSJack F Vogel s32 ret_val;
6888cfa0ad2SJack F Vogel u16 phy_data, index;
6898cfa0ad2SJack F Vogel
6908cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_cable_length_80003es2lan");
6918cfa0ad2SJack F Vogel
6928cfa0ad2SJack F Vogel if (!(hw->phy.ops.read_reg))
6937609433eSJack F Vogel return E1000_SUCCESS;
6948cfa0ad2SJack F Vogel
6958cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_DSP_DISTANCE, &phy_data);
6968cfa0ad2SJack F Vogel if (ret_val)
6977609433eSJack F Vogel return ret_val;
6988cfa0ad2SJack F Vogel
6998cfa0ad2SJack F Vogel index = phy_data & GG82563_DSPD_CABLE_LENGTH;
7008cfa0ad2SJack F Vogel
7017609433eSJack F Vogel if (index >= GG82563_CABLE_LENGTH_TABLE_SIZE - 5)
7027609433eSJack F Vogel return -E1000_ERR_PHY;
7038cfa0ad2SJack F Vogel
704d035aa2dSJack F Vogel phy->min_cable_length = e1000_gg82563_cable_length_table[index];
705d035aa2dSJack F Vogel phy->max_cable_length = e1000_gg82563_cable_length_table[index + 5];
706d035aa2dSJack F Vogel
707d035aa2dSJack F Vogel phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
708d035aa2dSJack F Vogel
7097609433eSJack F Vogel return E1000_SUCCESS;
7108cfa0ad2SJack F Vogel }
7118cfa0ad2SJack F Vogel
7128cfa0ad2SJack F Vogel /**
7138cfa0ad2SJack F Vogel * e1000_get_link_up_info_80003es2lan - Report speed and duplex
7148cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
7158cfa0ad2SJack F Vogel * @speed: pointer to speed buffer
7168cfa0ad2SJack F Vogel * @duplex: pointer to duplex buffer
7178cfa0ad2SJack F Vogel *
7188cfa0ad2SJack F Vogel * Retrieve the current speed and duplex configuration.
7198cfa0ad2SJack F Vogel **/
e1000_get_link_up_info_80003es2lan(struct e1000_hw * hw,u16 * speed,u16 * duplex)7208cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_80003es2lan(struct e1000_hw *hw, u16 *speed,
7218cfa0ad2SJack F Vogel u16 *duplex)
7228cfa0ad2SJack F Vogel {
7238cfa0ad2SJack F Vogel s32 ret_val;
7248cfa0ad2SJack F Vogel
7258cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_link_up_info_80003es2lan");
7268cfa0ad2SJack F Vogel
7278cfa0ad2SJack F Vogel if (hw->phy.media_type == e1000_media_type_copper) {
7284dab5c37SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
7298cfa0ad2SJack F Vogel duplex);
730daf9197cSJack F Vogel hw->phy.ops.cfg_on_link_up(hw);
7318cfa0ad2SJack F Vogel } else {
7328cfa0ad2SJack F Vogel ret_val = e1000_get_speed_and_duplex_fiber_serdes_generic(hw,
7338cfa0ad2SJack F Vogel speed,
7348cfa0ad2SJack F Vogel duplex);
7358cfa0ad2SJack F Vogel }
7368cfa0ad2SJack F Vogel
7378cfa0ad2SJack F Vogel return ret_val;
7388cfa0ad2SJack F Vogel }
7398cfa0ad2SJack F Vogel
7408cfa0ad2SJack F Vogel /**
7418cfa0ad2SJack F Vogel * e1000_reset_hw_80003es2lan - Reset the ESB2 controller
7428cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
7438cfa0ad2SJack F Vogel *
7448cfa0ad2SJack F Vogel * Perform a global reset to the ESB2 controller.
7458cfa0ad2SJack F Vogel **/
e1000_reset_hw_80003es2lan(struct e1000_hw * hw)7468cfa0ad2SJack F Vogel static s32 e1000_reset_hw_80003es2lan(struct e1000_hw *hw)
7478cfa0ad2SJack F Vogel {
748730d3130SJack F Vogel u32 ctrl;
7498cfa0ad2SJack F Vogel s32 ret_val;
7507609433eSJack F Vogel u16 kum_reg_data;
7518cfa0ad2SJack F Vogel
7528cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_80003es2lan");
7538cfa0ad2SJack F Vogel
7547609433eSJack F Vogel /* Prevent the PCI-E bus from sticking if there is no TLP connection
7558cfa0ad2SJack F Vogel * on the last TLP read/write transaction when MAC is reset.
7568cfa0ad2SJack F Vogel */
7578cfa0ad2SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw);
758daf9197cSJack F Vogel if (ret_val)
7598cfa0ad2SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n");
7608cfa0ad2SJack F Vogel
7618cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n");
7628cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
7638cfa0ad2SJack F Vogel
7648cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0);
7658cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
7668cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw);
7678cfa0ad2SJack F Vogel
7688cfa0ad2SJack F Vogel msec_delay(10);
7698cfa0ad2SJack F Vogel
7708cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL);
7718cfa0ad2SJack F Vogel
772daf9197cSJack F Vogel ret_val = e1000_acquire_phy_80003es2lan(hw);
7737609433eSJack F Vogel if (ret_val)
7747609433eSJack F Vogel return ret_val;
7757609433eSJack F Vogel
7768cfa0ad2SJack F Vogel DEBUGOUT("Issuing a global reset to MAC\n");
7778cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
778daf9197cSJack F Vogel e1000_release_phy_80003es2lan(hw);
7798cfa0ad2SJack F Vogel
7807609433eSJack F Vogel /* Disable IBIST slave mode (far-end loopback) */
781c80429ceSEric Joyner ret_val = e1000_read_kmrn_reg_80003es2lan(hw,
782c80429ceSEric Joyner E1000_KMRNCTRLSTA_INBAND_PARAM, &kum_reg_data);
783c80429ceSEric Joyner if (!ret_val) {
7847609433eSJack F Vogel kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
785c80429ceSEric Joyner ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
786c80429ceSEric Joyner E1000_KMRNCTRLSTA_INBAND_PARAM,
7877609433eSJack F Vogel kum_reg_data);
788c80429ceSEric Joyner if (ret_val)
789c80429ceSEric Joyner DEBUGOUT("Error disabling far-end loopback\n");
790c80429ceSEric Joyner } else
791c80429ceSEric Joyner DEBUGOUT("Error disabling far-end loopback\n");
7927609433eSJack F Vogel
7938cfa0ad2SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw);
7948cfa0ad2SJack F Vogel if (ret_val)
7958cfa0ad2SJack F Vogel /* We don't want to continue accessing MAC registers. */
7967609433eSJack F Vogel return ret_val;
7978cfa0ad2SJack F Vogel
7988cfa0ad2SJack F Vogel /* Clear any pending interrupt events. */
7998cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
800730d3130SJack F Vogel E1000_READ_REG(hw, E1000_ICR);
8018cfa0ad2SJack F Vogel
8027609433eSJack F Vogel return e1000_check_alt_mac_addr_generic(hw);
8038cfa0ad2SJack F Vogel }
8048cfa0ad2SJack F Vogel
8058cfa0ad2SJack F Vogel /**
8068cfa0ad2SJack F Vogel * e1000_init_hw_80003es2lan - Initialize the ESB2 controller
8078cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
8088cfa0ad2SJack F Vogel *
8098cfa0ad2SJack F Vogel * Initialize the hw bits, LED, VFTA, MTA, link and hw counters.
8108cfa0ad2SJack F Vogel **/
e1000_init_hw_80003es2lan(struct e1000_hw * hw)8118cfa0ad2SJack F Vogel static s32 e1000_init_hw_80003es2lan(struct e1000_hw *hw)
8128cfa0ad2SJack F Vogel {
8138cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac;
8148cfa0ad2SJack F Vogel u32 reg_data;
8158cfa0ad2SJack F Vogel s32 ret_val;
816730d3130SJack F Vogel u16 kum_reg_data;
8178cfa0ad2SJack F Vogel u16 i;
8188cfa0ad2SJack F Vogel
8198cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_80003es2lan");
8208cfa0ad2SJack F Vogel
8218cfa0ad2SJack F Vogel e1000_initialize_hw_bits_80003es2lan(hw);
8228cfa0ad2SJack F Vogel
8238cfa0ad2SJack F Vogel /* Initialize identification LED */
824d035aa2dSJack F Vogel ret_val = mac->ops.id_led_init(hw);
8257609433eSJack F Vogel /* An error is not fatal and we should not stop init due to this */
8264edd8523SJack F Vogel if (ret_val)
8278cfa0ad2SJack F Vogel DEBUGOUT("Error initializing identification LED\n");
8288cfa0ad2SJack F Vogel
8298cfa0ad2SJack F Vogel /* Disabling VLAN filtering */
8308cfa0ad2SJack F Vogel DEBUGOUT("Initializing the IEEE VLAN\n");
8318cfa0ad2SJack F Vogel mac->ops.clear_vfta(hw);
8328cfa0ad2SJack F Vogel
8338cfa0ad2SJack F Vogel /* Setup the receive address. */
8348cfa0ad2SJack F Vogel e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
8358cfa0ad2SJack F Vogel
8368cfa0ad2SJack F Vogel /* Zero out the Multicast HASH table */
8378cfa0ad2SJack F Vogel DEBUGOUT("Zeroing the MTA\n");
8388cfa0ad2SJack F Vogel for (i = 0; i < mac->mta_reg_count; i++)
8398cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
8408cfa0ad2SJack F Vogel
8418cfa0ad2SJack F Vogel /* Setup link and flow control */
8428cfa0ad2SJack F Vogel ret_val = mac->ops.setup_link(hw);
8437609433eSJack F Vogel if (ret_val)
8447609433eSJack F Vogel return ret_val;
8458cfa0ad2SJack F Vogel
846730d3130SJack F Vogel /* Disable IBIST slave mode (far-end loopback) */
847c80429ceSEric Joyner ret_val =
848730d3130SJack F Vogel e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_INBAND_PARAM,
849730d3130SJack F Vogel &kum_reg_data);
850c80429ceSEric Joyner if (!ret_val) {
851730d3130SJack F Vogel kum_reg_data |= E1000_KMRNCTRLSTA_IBIST_DISABLE;
852c80429ceSEric Joyner ret_val = e1000_write_kmrn_reg_80003es2lan(hw,
853c80429ceSEric Joyner E1000_KMRNCTRLSTA_INBAND_PARAM,
854730d3130SJack F Vogel kum_reg_data);
855c80429ceSEric Joyner if (ret_val)
856c80429ceSEric Joyner DEBUGOUT("Error disabling far-end loopback\n");
857c80429ceSEric Joyner } else
858c80429ceSEric Joyner DEBUGOUT("Error disabling far-end loopback\n");
859730d3130SJack F Vogel
8608cfa0ad2SJack F Vogel /* Set the transmit descriptor write-back policy */
8618cfa0ad2SJack F Vogel reg_data = E1000_READ_REG(hw, E1000_TXDCTL(0));
8627609433eSJack F Vogel reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
8637609433eSJack F Vogel E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
8648cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg_data);
8658cfa0ad2SJack F Vogel
8668cfa0ad2SJack F Vogel /* ...for both queues. */
8678cfa0ad2SJack F Vogel reg_data = E1000_READ_REG(hw, E1000_TXDCTL(1));
8687609433eSJack F Vogel reg_data = ((reg_data & ~E1000_TXDCTL_WTHRESH) |
8697609433eSJack F Vogel E1000_TXDCTL_FULL_TX_DESC_WB | E1000_TXDCTL_COUNT_DESC);
8708cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg_data);
8718cfa0ad2SJack F Vogel
8728cfa0ad2SJack F Vogel /* Enable retransmit on late collisions */
8738cfa0ad2SJack F Vogel reg_data = E1000_READ_REG(hw, E1000_TCTL);
8748cfa0ad2SJack F Vogel reg_data |= E1000_TCTL_RTLC;
8758cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, reg_data);
8768cfa0ad2SJack F Vogel
8778cfa0ad2SJack F Vogel /* Configure Gigabit Carry Extend Padding */
8788cfa0ad2SJack F Vogel reg_data = E1000_READ_REG(hw, E1000_TCTL_EXT);
8798cfa0ad2SJack F Vogel reg_data &= ~E1000_TCTL_EXT_GCEX_MASK;
8808cfa0ad2SJack F Vogel reg_data |= DEFAULT_TCTL_EXT_GCEX_80003ES2LAN;
8818cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL_EXT, reg_data);
8828cfa0ad2SJack F Vogel
8838cfa0ad2SJack F Vogel /* Configure Transmit Inter-Packet Gap */
8848cfa0ad2SJack F Vogel reg_data = E1000_READ_REG(hw, E1000_TIPG);
8858cfa0ad2SJack F Vogel reg_data &= ~E1000_TIPG_IPGT_MASK;
8868cfa0ad2SJack F Vogel reg_data |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
8878cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TIPG, reg_data);
8888cfa0ad2SJack F Vogel
8898cfa0ad2SJack F Vogel reg_data = E1000_READ_REG_ARRAY(hw, E1000_FFLT, 0x0001);
8908cfa0ad2SJack F Vogel reg_data &= ~0x00100000;
8918cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_FFLT, 0x0001, reg_data);
8928cfa0ad2SJack F Vogel
893*1bbdc25fSKevin Bowling /* default to true to enable the MDIC W/A */
894*1bbdc25fSKevin Bowling hw->dev_spec._80003es2lan.mdic_wa_enable = true;
8954edd8523SJack F Vogel
8967609433eSJack F Vogel ret_val =
8977609433eSJack F Vogel e1000_read_kmrn_reg_80003es2lan(hw, E1000_KMRNCTRLSTA_OFFSET >>
8987609433eSJack F Vogel E1000_KMRNCTRLSTA_OFFSET_SHIFT, &i);
8994edd8523SJack F Vogel if (!ret_val) {
9004edd8523SJack F Vogel if ((i & E1000_KMRNCTRLSTA_OPMODE_MASK) ==
9014edd8523SJack F Vogel E1000_KMRNCTRLSTA_OPMODE_INBAND_MDIO)
902*1bbdc25fSKevin Bowling hw->dev_spec._80003es2lan.mdic_wa_enable = false;
9034edd8523SJack F Vogel }
9044edd8523SJack F Vogel
9057609433eSJack F Vogel /* Clear all of the statistics registers (clear on read). It is
9068cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link
9078cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there
9088cfa0ad2SJack F Vogel * is no link.
9098cfa0ad2SJack F Vogel */
9108cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_80003es2lan(hw);
9118cfa0ad2SJack F Vogel
9128cfa0ad2SJack F Vogel return ret_val;
9138cfa0ad2SJack F Vogel }
9148cfa0ad2SJack F Vogel
9158cfa0ad2SJack F Vogel /**
9168cfa0ad2SJack F Vogel * e1000_initialize_hw_bits_80003es2lan - Init hw bits of ESB2
9178cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
9188cfa0ad2SJack F Vogel *
9198cfa0ad2SJack F Vogel * Initializes required hardware-dependent bits needed for normal operation.
9208cfa0ad2SJack F Vogel **/
e1000_initialize_hw_bits_80003es2lan(struct e1000_hw * hw)9218cfa0ad2SJack F Vogel static void e1000_initialize_hw_bits_80003es2lan(struct e1000_hw *hw)
9228cfa0ad2SJack F Vogel {
9238cfa0ad2SJack F Vogel u32 reg;
9248cfa0ad2SJack F Vogel
9258cfa0ad2SJack F Vogel DEBUGFUNC("e1000_initialize_hw_bits_80003es2lan");
9268cfa0ad2SJack F Vogel
9278cfa0ad2SJack F Vogel /* Transmit Descriptor Control 0 */
9288cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
9298cfa0ad2SJack F Vogel reg |= (1 << 22);
9308cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
9318cfa0ad2SJack F Vogel
9328cfa0ad2SJack F Vogel /* Transmit Descriptor Control 1 */
9338cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
9348cfa0ad2SJack F Vogel reg |= (1 << 22);
9358cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
9368cfa0ad2SJack F Vogel
9378cfa0ad2SJack F Vogel /* Transmit Arbitration Control 0 */
9388cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TARC(0));
9398cfa0ad2SJack F Vogel reg &= ~(0xF << 27); /* 30:27 */
9408cfa0ad2SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper)
9418cfa0ad2SJack F Vogel reg &= ~(1 << 20);
9428cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TARC(0), reg);
9438cfa0ad2SJack F Vogel
9448cfa0ad2SJack F Vogel /* Transmit Arbitration Control 1 */
9458cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_TARC(1));
9468cfa0ad2SJack F Vogel if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR)
9478cfa0ad2SJack F Vogel reg &= ~(1 << 28);
9488cfa0ad2SJack F Vogel else
9498cfa0ad2SJack F Vogel reg |= (1 << 28);
9508cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TARC(1), reg);
9518cfa0ad2SJack F Vogel
9527609433eSJack F Vogel /* Disable IPv6 extension header parsing because some malformed
9537609433eSJack F Vogel * IPv6 headers can hang the Rx.
9547609433eSJack F Vogel */
9557609433eSJack F Vogel reg = E1000_READ_REG(hw, E1000_RFCTL);
9567609433eSJack F Vogel reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
9577609433eSJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, reg);
9587609433eSJack F Vogel
9598cfa0ad2SJack F Vogel return;
9608cfa0ad2SJack F Vogel }
9618cfa0ad2SJack F Vogel
9628cfa0ad2SJack F Vogel /**
9638cfa0ad2SJack F Vogel * e1000_copper_link_setup_gg82563_80003es2lan - Configure GG82563 Link
9648cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
9658cfa0ad2SJack F Vogel *
9668cfa0ad2SJack F Vogel * Setup some GG82563 PHY registers for obtaining link
9678cfa0ad2SJack F Vogel **/
e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw * hw)9688cfa0ad2SJack F Vogel static s32 e1000_copper_link_setup_gg82563_80003es2lan(struct e1000_hw *hw)
9698cfa0ad2SJack F Vogel {
9708cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy;
9718cfa0ad2SJack F Vogel s32 ret_val;
9727609433eSJack F Vogel u32 reg;
973daf9197cSJack F Vogel u16 data;
9748cfa0ad2SJack F Vogel
9758cfa0ad2SJack F Vogel DEBUGFUNC("e1000_copper_link_setup_gg82563_80003es2lan");
9768cfa0ad2SJack F Vogel
9774dab5c37SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, &data);
9788cfa0ad2SJack F Vogel if (ret_val)
9797609433eSJack F Vogel return ret_val;
9808cfa0ad2SJack F Vogel
9818cfa0ad2SJack F Vogel data |= GG82563_MSCR_ASSERT_CRS_ON_TX;
9828cfa0ad2SJack F Vogel /* Use 25MHz for both link down and 1000Base-T for Tx clock. */
9838cfa0ad2SJack F Vogel data |= GG82563_MSCR_TX_CLK_1000MBPS_25;
9848cfa0ad2SJack F Vogel
9854dab5c37SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_MAC_SPEC_CTRL, data);
9868cfa0ad2SJack F Vogel if (ret_val)
9877609433eSJack F Vogel return ret_val;
9888cfa0ad2SJack F Vogel
9897609433eSJack F Vogel /* Options:
9908cfa0ad2SJack F Vogel * MDI/MDI-X = 0 (default)
9918cfa0ad2SJack F Vogel * 0 - Auto for all speeds
9928cfa0ad2SJack F Vogel * 1 - MDI mode
9938cfa0ad2SJack F Vogel * 2 - MDI-X mode
9948cfa0ad2SJack F Vogel * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
9958cfa0ad2SJack F Vogel */
9968cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL, &data);
9978cfa0ad2SJack F Vogel if (ret_val)
9987609433eSJack F Vogel return ret_val;
9998cfa0ad2SJack F Vogel
10008cfa0ad2SJack F Vogel data &= ~GG82563_PSCR_CROSSOVER_MODE_MASK;
10018cfa0ad2SJack F Vogel
10028cfa0ad2SJack F Vogel switch (phy->mdix) {
10038cfa0ad2SJack F Vogel case 1:
10048cfa0ad2SJack F Vogel data |= GG82563_PSCR_CROSSOVER_MODE_MDI;
10058cfa0ad2SJack F Vogel break;
10068cfa0ad2SJack F Vogel case 2:
10078cfa0ad2SJack F Vogel data |= GG82563_PSCR_CROSSOVER_MODE_MDIX;
10088cfa0ad2SJack F Vogel break;
10098cfa0ad2SJack F Vogel case 0:
10108cfa0ad2SJack F Vogel default:
10118cfa0ad2SJack F Vogel data |= GG82563_PSCR_CROSSOVER_MODE_AUTO;
10128cfa0ad2SJack F Vogel break;
10138cfa0ad2SJack F Vogel }
10148cfa0ad2SJack F Vogel
10157609433eSJack F Vogel /* Options:
10168cfa0ad2SJack F Vogel * disable_polarity_correction = 0 (default)
10178cfa0ad2SJack F Vogel * Automatic Correction for Reversed Cable Polarity
10188cfa0ad2SJack F Vogel * 0 - Disabled
10198cfa0ad2SJack F Vogel * 1 - Enabled
10208cfa0ad2SJack F Vogel */
10218cfa0ad2SJack F Vogel data &= ~GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
10228cfa0ad2SJack F Vogel if (phy->disable_polarity_correction)
10238cfa0ad2SJack F Vogel data |= GG82563_PSCR_POLARITY_REVERSAL_DISABLE;
10248cfa0ad2SJack F Vogel
10258cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL, data);
10268cfa0ad2SJack F Vogel if (ret_val)
10277609433eSJack F Vogel return ret_val;
10288cfa0ad2SJack F Vogel
10298cfa0ad2SJack F Vogel /* SW Reset the PHY so all changes take effect */
10308cfa0ad2SJack F Vogel ret_val = hw->phy.ops.commit(hw);
10318cfa0ad2SJack F Vogel if (ret_val) {
10328cfa0ad2SJack F Vogel DEBUGOUT("Error Resetting the PHY\n");
10337609433eSJack F Vogel return ret_val;
10348cfa0ad2SJack F Vogel }
10358cfa0ad2SJack F Vogel
10368cfa0ad2SJack F Vogel /* Bypass Rx and Tx FIFO's */
10377609433eSJack F Vogel reg = E1000_KMRNCTRLSTA_OFFSET_FIFO_CTRL;
10387609433eSJack F Vogel data = (E1000_KMRNCTRLSTA_FIFO_CTRL_RX_BYPASS |
10398cfa0ad2SJack F Vogel E1000_KMRNCTRLSTA_FIFO_CTRL_TX_BYPASS);
10407609433eSJack F Vogel ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
10418cfa0ad2SJack F Vogel if (ret_val)
10427609433eSJack F Vogel return ret_val;
10438cfa0ad2SJack F Vogel
10447609433eSJack F Vogel reg = E1000_KMRNCTRLSTA_OFFSET_MAC2PHY_OPMODE;
10457609433eSJack F Vogel ret_val = e1000_read_kmrn_reg_80003es2lan(hw, reg, &data);
10468cfa0ad2SJack F Vogel if (ret_val)
10477609433eSJack F Vogel return ret_val;
10488cfa0ad2SJack F Vogel data |= E1000_KMRNCTRLSTA_OPMODE_E_IDLE;
10497609433eSJack F Vogel ret_val = e1000_write_kmrn_reg_80003es2lan(hw, reg, data);
10508cfa0ad2SJack F Vogel if (ret_val)
10517609433eSJack F Vogel return ret_val;
10528cfa0ad2SJack F Vogel
10538cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_SPEC_CTRL_2, &data);
10548cfa0ad2SJack F Vogel if (ret_val)
10557609433eSJack F Vogel return ret_val;
10568cfa0ad2SJack F Vogel
10578cfa0ad2SJack F Vogel data &= ~GG82563_PSCR2_REVERSE_AUTO_NEG;
10588cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_SPEC_CTRL_2, data);
10598cfa0ad2SJack F Vogel if (ret_val)
10607609433eSJack F Vogel return ret_val;
10618cfa0ad2SJack F Vogel
10627609433eSJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
10637609433eSJack F Vogel reg &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
10647609433eSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
10658cfa0ad2SJack F Vogel
10668cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_PWR_MGMT_CTRL, &data);
10678cfa0ad2SJack F Vogel if (ret_val)
10687609433eSJack F Vogel return ret_val;
10698cfa0ad2SJack F Vogel
10707609433eSJack F Vogel /* Do not init these registers when the HW is in IAMT mode, since the
10718cfa0ad2SJack F Vogel * firmware will have already initialized them. We only initialize
10728cfa0ad2SJack F Vogel * them if the HW is not in IAMT mode.
10738cfa0ad2SJack F Vogel */
10747609433eSJack F Vogel if (!hw->mac.ops.check_mng_mode(hw)) {
10758cfa0ad2SJack F Vogel /* Enable Electrical Idle on the PHY */
10768cfa0ad2SJack F Vogel data |= GG82563_PMCR_ENABLE_ELECTRICAL_IDLE;
1077d035aa2dSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_PWR_MGMT_CTRL,
10788cfa0ad2SJack F Vogel data);
10798cfa0ad2SJack F Vogel if (ret_val)
10807609433eSJack F Vogel return ret_val;
1081d035aa2dSJack F Vogel
1082d035aa2dSJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
10838cfa0ad2SJack F Vogel &data);
10848cfa0ad2SJack F Vogel if (ret_val)
10857609433eSJack F Vogel return ret_val;
10868cfa0ad2SJack F Vogel
10878cfa0ad2SJack F Vogel data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
1088d035aa2dSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
10898cfa0ad2SJack F Vogel data);
10908cfa0ad2SJack F Vogel if (ret_val)
10917609433eSJack F Vogel return ret_val;
10928cfa0ad2SJack F Vogel }
10938cfa0ad2SJack F Vogel
10947609433eSJack F Vogel /* Workaround: Disable padding in Kumeran interface in the MAC
10958cfa0ad2SJack F Vogel * and in the PHY to avoid CRC errors.
10968cfa0ad2SJack F Vogel */
10978cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_INBAND_CTRL, &data);
10988cfa0ad2SJack F Vogel if (ret_val)
10997609433eSJack F Vogel return ret_val;
11008cfa0ad2SJack F Vogel
11018cfa0ad2SJack F Vogel data |= GG82563_ICR_DIS_PADDING;
11028cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, GG82563_PHY_INBAND_CTRL, data);
11038cfa0ad2SJack F Vogel if (ret_val)
11048cfa0ad2SJack F Vogel return ret_val;
11057609433eSJack F Vogel
11067609433eSJack F Vogel return E1000_SUCCESS;
11078cfa0ad2SJack F Vogel }
11088cfa0ad2SJack F Vogel
11098cfa0ad2SJack F Vogel /**
11108cfa0ad2SJack F Vogel * e1000_setup_copper_link_80003es2lan - Setup Copper Link for ESB2
11118cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
11128cfa0ad2SJack F Vogel *
11138cfa0ad2SJack F Vogel * Essentially a wrapper for setting up all things "copper" related.
11148cfa0ad2SJack F Vogel * This is a function pointer entry point called by the mac module.
11158cfa0ad2SJack F Vogel **/
e1000_setup_copper_link_80003es2lan(struct e1000_hw * hw)11168cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_80003es2lan(struct e1000_hw *hw)
11178cfa0ad2SJack F Vogel {
11188cfa0ad2SJack F Vogel u32 ctrl;
11198cfa0ad2SJack F Vogel s32 ret_val;
11208cfa0ad2SJack F Vogel u16 reg_data;
11218cfa0ad2SJack F Vogel
11228cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_80003es2lan");
11238cfa0ad2SJack F Vogel
11248cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL);
11258cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SLU;
11268cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
11278cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
11288cfa0ad2SJack F Vogel
11297609433eSJack F Vogel /* Set the mac to wait the maximum time between each
11308cfa0ad2SJack F Vogel * iteration and increase the max iterations when
11318cfa0ad2SJack F Vogel * polling the phy; this fixes erroneous timeouts at 10Mbps.
11328cfa0ad2SJack F Vogel */
1133daf9197cSJack F Vogel ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 4),
11348cfa0ad2SJack F Vogel 0xFFFF);
11358cfa0ad2SJack F Vogel if (ret_val)
11367609433eSJack F Vogel return ret_val;
1137daf9197cSJack F Vogel ret_val = e1000_read_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
11388cfa0ad2SJack F Vogel ®_data);
11398cfa0ad2SJack F Vogel if (ret_val)
11407609433eSJack F Vogel return ret_val;
11418cfa0ad2SJack F Vogel reg_data |= 0x3F;
1142daf9197cSJack F Vogel ret_val = e1000_write_kmrn_reg_80003es2lan(hw, GG82563_REG(0x34, 9),
11438cfa0ad2SJack F Vogel reg_data);
11448cfa0ad2SJack F Vogel if (ret_val)
11457609433eSJack F Vogel return ret_val;
11467609433eSJack F Vogel ret_val =
11477609433eSJack F Vogel e1000_read_kmrn_reg_80003es2lan(hw,
11487609433eSJack F Vogel E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
11497609433eSJack F Vogel ®_data);
11508cfa0ad2SJack F Vogel if (ret_val)
11517609433eSJack F Vogel return ret_val;
11528cfa0ad2SJack F Vogel reg_data |= E1000_KMRNCTRLSTA_INB_CTRL_DIS_PADDING;
11537609433eSJack F Vogel ret_val =
11547609433eSJack F Vogel e1000_write_kmrn_reg_80003es2lan(hw,
11557609433eSJack F Vogel E1000_KMRNCTRLSTA_OFFSET_INB_CTRL,
11567609433eSJack F Vogel reg_data);
11578cfa0ad2SJack F Vogel if (ret_val)
11587609433eSJack F Vogel return ret_val;
11598cfa0ad2SJack F Vogel
11608cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_gg82563_80003es2lan(hw);
11618cfa0ad2SJack F Vogel if (ret_val)
11628cfa0ad2SJack F Vogel return ret_val;
11637609433eSJack F Vogel
11647609433eSJack F Vogel return e1000_setup_copper_link_generic(hw);
11658cfa0ad2SJack F Vogel }
11668cfa0ad2SJack F Vogel
11678cfa0ad2SJack F Vogel /**
1168daf9197cSJack F Vogel * e1000_cfg_on_link_up_80003es2lan - es2 link configuration after link-up
1169daf9197cSJack F Vogel * @hw: pointer to the HW structure
1170daf9197cSJack F Vogel *
1171daf9197cSJack F Vogel * Configure the KMRN interface by applying last minute quirks for
1172daf9197cSJack F Vogel * 10/100 operation.
1173daf9197cSJack F Vogel **/
e1000_cfg_on_link_up_80003es2lan(struct e1000_hw * hw)1174daf9197cSJack F Vogel static s32 e1000_cfg_on_link_up_80003es2lan(struct e1000_hw *hw)
1175daf9197cSJack F Vogel {
1176daf9197cSJack F Vogel s32 ret_val = E1000_SUCCESS;
1177daf9197cSJack F Vogel u16 speed;
1178daf9197cSJack F Vogel u16 duplex;
1179daf9197cSJack F Vogel
1180daf9197cSJack F Vogel DEBUGFUNC("e1000_configure_on_link_up");
1181daf9197cSJack F Vogel
1182daf9197cSJack F Vogel if (hw->phy.media_type == e1000_media_type_copper) {
11834dab5c37SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, &speed,
1184daf9197cSJack F Vogel &duplex);
1185daf9197cSJack F Vogel if (ret_val)
11867609433eSJack F Vogel return ret_val;
1187daf9197cSJack F Vogel
1188daf9197cSJack F Vogel if (speed == SPEED_1000)
1189daf9197cSJack F Vogel ret_val = e1000_cfg_kmrn_1000_80003es2lan(hw);
1190daf9197cSJack F Vogel else
1191daf9197cSJack F Vogel ret_val = e1000_cfg_kmrn_10_100_80003es2lan(hw, duplex);
1192daf9197cSJack F Vogel }
1193daf9197cSJack F Vogel
1194daf9197cSJack F Vogel return ret_val;
1195daf9197cSJack F Vogel }
1196daf9197cSJack F Vogel
1197daf9197cSJack F Vogel /**
11988cfa0ad2SJack F Vogel * e1000_cfg_kmrn_10_100_80003es2lan - Apply "quirks" for 10/100 operation
11998cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
12008cfa0ad2SJack F Vogel * @duplex: current duplex setting
12018cfa0ad2SJack F Vogel *
12028cfa0ad2SJack F Vogel * Configure the KMRN interface by applying last minute quirks for
12038cfa0ad2SJack F Vogel * 10/100 operation.
12048cfa0ad2SJack F Vogel **/
e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw * hw,u16 duplex)12058cfa0ad2SJack F Vogel static s32 e1000_cfg_kmrn_10_100_80003es2lan(struct e1000_hw *hw, u16 duplex)
12068cfa0ad2SJack F Vogel {
12077609433eSJack F Vogel s32 ret_val;
12088cfa0ad2SJack F Vogel u32 tipg;
12098cfa0ad2SJack F Vogel u32 i = 0;
12108cfa0ad2SJack F Vogel u16 reg_data, reg_data2;
12118cfa0ad2SJack F Vogel
12128cfa0ad2SJack F Vogel DEBUGFUNC("e1000_configure_kmrn_for_10_100");
12138cfa0ad2SJack F Vogel
12148cfa0ad2SJack F Vogel reg_data = E1000_KMRNCTRLSTA_HD_CTRL_10_100_DEFAULT;
12157609433eSJack F Vogel ret_val =
12167609433eSJack F Vogel e1000_write_kmrn_reg_80003es2lan(hw,
12178cfa0ad2SJack F Vogel E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
12188cfa0ad2SJack F Vogel reg_data);
12198cfa0ad2SJack F Vogel if (ret_val)
12207609433eSJack F Vogel return ret_val;
12218cfa0ad2SJack F Vogel
12228cfa0ad2SJack F Vogel /* Configure Transmit Inter-Packet Gap */
12238cfa0ad2SJack F Vogel tipg = E1000_READ_REG(hw, E1000_TIPG);
12248cfa0ad2SJack F Vogel tipg &= ~E1000_TIPG_IPGT_MASK;
12258cfa0ad2SJack F Vogel tipg |= DEFAULT_TIPG_IPGT_10_100_80003ES2LAN;
12268cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TIPG, tipg);
12278cfa0ad2SJack F Vogel
12288cfa0ad2SJack F Vogel do {
12298cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12308cfa0ad2SJack F Vogel ®_data);
12318cfa0ad2SJack F Vogel if (ret_val)
12327609433eSJack F Vogel return ret_val;
12338cfa0ad2SJack F Vogel
12348cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12358cfa0ad2SJack F Vogel ®_data2);
12368cfa0ad2SJack F Vogel if (ret_val)
12377609433eSJack F Vogel return ret_val;
12388cfa0ad2SJack F Vogel i++;
12398cfa0ad2SJack F Vogel } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
12408cfa0ad2SJack F Vogel
12418cfa0ad2SJack F Vogel if (duplex == HALF_DUPLEX)
12428cfa0ad2SJack F Vogel reg_data |= GG82563_KMCR_PASS_FALSE_CARRIER;
12438cfa0ad2SJack F Vogel else
12448cfa0ad2SJack F Vogel reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
12458cfa0ad2SJack F Vogel
12467609433eSJack F Vogel return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
12478cfa0ad2SJack F Vogel }
12488cfa0ad2SJack F Vogel
12498cfa0ad2SJack F Vogel /**
12508cfa0ad2SJack F Vogel * e1000_cfg_kmrn_1000_80003es2lan - Apply "quirks" for gigabit operation
12518cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
12528cfa0ad2SJack F Vogel *
12538cfa0ad2SJack F Vogel * Configure the KMRN interface by applying last minute quirks for
12548cfa0ad2SJack F Vogel * gigabit operation.
12558cfa0ad2SJack F Vogel **/
e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw * hw)12568cfa0ad2SJack F Vogel static s32 e1000_cfg_kmrn_1000_80003es2lan(struct e1000_hw *hw)
12578cfa0ad2SJack F Vogel {
12587609433eSJack F Vogel s32 ret_val;
12598cfa0ad2SJack F Vogel u16 reg_data, reg_data2;
12608cfa0ad2SJack F Vogel u32 tipg;
12618cfa0ad2SJack F Vogel u32 i = 0;
12628cfa0ad2SJack F Vogel
12638cfa0ad2SJack F Vogel DEBUGFUNC("e1000_configure_kmrn_for_1000");
12648cfa0ad2SJack F Vogel
12658cfa0ad2SJack F Vogel reg_data = E1000_KMRNCTRLSTA_HD_CTRL_1000_DEFAULT;
12667609433eSJack F Vogel ret_val =
12677609433eSJack F Vogel e1000_write_kmrn_reg_80003es2lan(hw,
12687609433eSJack F Vogel E1000_KMRNCTRLSTA_OFFSET_HD_CTRL,
12697609433eSJack F Vogel reg_data);
12708cfa0ad2SJack F Vogel if (ret_val)
12717609433eSJack F Vogel return ret_val;
12728cfa0ad2SJack F Vogel
12738cfa0ad2SJack F Vogel /* Configure Transmit Inter-Packet Gap */
12748cfa0ad2SJack F Vogel tipg = E1000_READ_REG(hw, E1000_TIPG);
12758cfa0ad2SJack F Vogel tipg &= ~E1000_TIPG_IPGT_MASK;
12768cfa0ad2SJack F Vogel tipg |= DEFAULT_TIPG_IPGT_1000_80003ES2LAN;
12778cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TIPG, tipg);
12788cfa0ad2SJack F Vogel
12798cfa0ad2SJack F Vogel do {
12808cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12818cfa0ad2SJack F Vogel ®_data);
12828cfa0ad2SJack F Vogel if (ret_val)
12837609433eSJack F Vogel return ret_val;
12848cfa0ad2SJack F Vogel
12858cfa0ad2SJack F Vogel ret_val = hw->phy.ops.read_reg(hw, GG82563_PHY_KMRN_MODE_CTRL,
12868cfa0ad2SJack F Vogel ®_data2);
12878cfa0ad2SJack F Vogel if (ret_val)
12887609433eSJack F Vogel return ret_val;
12898cfa0ad2SJack F Vogel i++;
12908cfa0ad2SJack F Vogel } while ((reg_data != reg_data2) && (i < GG82563_MAX_KMRN_RETRY));
12918cfa0ad2SJack F Vogel
12928cfa0ad2SJack F Vogel reg_data &= ~GG82563_KMCR_PASS_FALSE_CARRIER;
12938cfa0ad2SJack F Vogel
12947609433eSJack F Vogel return hw->phy.ops.write_reg(hw, GG82563_PHY_KMRN_MODE_CTRL, reg_data);
12958cfa0ad2SJack F Vogel }
12968cfa0ad2SJack F Vogel
12978cfa0ad2SJack F Vogel /**
1298daf9197cSJack F Vogel * e1000_read_kmrn_reg_80003es2lan - Read kumeran register
1299daf9197cSJack F Vogel * @hw: pointer to the HW structure
1300daf9197cSJack F Vogel * @offset: register offset to be read
1301daf9197cSJack F Vogel * @data: pointer to the read data
1302daf9197cSJack F Vogel *
1303daf9197cSJack F Vogel * Acquire semaphore, then read the PHY register at offset
1304daf9197cSJack F Vogel * using the kumeran interface. The information retrieved is stored in data.
1305daf9197cSJack F Vogel * Release the semaphore before exiting.
1306daf9197cSJack F Vogel **/
e1000_read_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 * data)1307d035aa2dSJack F Vogel static s32 e1000_read_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
1308d035aa2dSJack F Vogel u16 *data)
1309daf9197cSJack F Vogel {
1310daf9197cSJack F Vogel u32 kmrnctrlsta;
13117609433eSJack F Vogel s32 ret_val;
1312daf9197cSJack F Vogel
1313daf9197cSJack F Vogel DEBUGFUNC("e1000_read_kmrn_reg_80003es2lan");
1314daf9197cSJack F Vogel
1315daf9197cSJack F Vogel ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
1316daf9197cSJack F Vogel if (ret_val)
13177609433eSJack F Vogel return ret_val;
1318daf9197cSJack F Vogel
1319daf9197cSJack F Vogel kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
1320daf9197cSJack F Vogel E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
1321daf9197cSJack F Vogel E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
13224dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
1323daf9197cSJack F Vogel
1324daf9197cSJack F Vogel usec_delay(2);
1325daf9197cSJack F Vogel
1326daf9197cSJack F Vogel kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
1327daf9197cSJack F Vogel *data = (u16)kmrnctrlsta;
1328daf9197cSJack F Vogel
1329daf9197cSJack F Vogel e1000_release_mac_csr_80003es2lan(hw);
1330daf9197cSJack F Vogel
1331daf9197cSJack F Vogel return ret_val;
1332daf9197cSJack F Vogel }
1333daf9197cSJack F Vogel
1334daf9197cSJack F Vogel /**
1335daf9197cSJack F Vogel * e1000_write_kmrn_reg_80003es2lan - Write kumeran register
1336daf9197cSJack F Vogel * @hw: pointer to the HW structure
1337daf9197cSJack F Vogel * @offset: register offset to write to
1338daf9197cSJack F Vogel * @data: data to write at register offset
1339daf9197cSJack F Vogel *
1340daf9197cSJack F Vogel * Acquire semaphore, then write the data to PHY register
1341daf9197cSJack F Vogel * at the offset using the kumeran interface. Release semaphore
1342daf9197cSJack F Vogel * before exiting.
1343daf9197cSJack F Vogel **/
e1000_write_kmrn_reg_80003es2lan(struct e1000_hw * hw,u32 offset,u16 data)1344d035aa2dSJack F Vogel static s32 e1000_write_kmrn_reg_80003es2lan(struct e1000_hw *hw, u32 offset,
1345d035aa2dSJack F Vogel u16 data)
1346daf9197cSJack F Vogel {
1347daf9197cSJack F Vogel u32 kmrnctrlsta;
13487609433eSJack F Vogel s32 ret_val;
1349daf9197cSJack F Vogel
1350daf9197cSJack F Vogel DEBUGFUNC("e1000_write_kmrn_reg_80003es2lan");
1351daf9197cSJack F Vogel
1352daf9197cSJack F Vogel ret_val = e1000_acquire_mac_csr_80003es2lan(hw);
1353daf9197cSJack F Vogel if (ret_val)
13547609433eSJack F Vogel return ret_val;
1355daf9197cSJack F Vogel
1356daf9197cSJack F Vogel kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
1357daf9197cSJack F Vogel E1000_KMRNCTRLSTA_OFFSET) | data;
1358daf9197cSJack F Vogel E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
13594dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
1360daf9197cSJack F Vogel
1361daf9197cSJack F Vogel usec_delay(2);
1362daf9197cSJack F Vogel
1363daf9197cSJack F Vogel e1000_release_mac_csr_80003es2lan(hw);
1364daf9197cSJack F Vogel
1365daf9197cSJack F Vogel return ret_val;
1366daf9197cSJack F Vogel }
1367daf9197cSJack F Vogel
1368daf9197cSJack F Vogel /**
13698cfa0ad2SJack F Vogel * e1000_read_mac_addr_80003es2lan - Read device MAC address
13708cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
13718cfa0ad2SJack F Vogel **/
e1000_read_mac_addr_80003es2lan(struct e1000_hw * hw)13728cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_80003es2lan(struct e1000_hw *hw)
13738cfa0ad2SJack F Vogel {
13747609433eSJack F Vogel s32 ret_val;
13758cfa0ad2SJack F Vogel
13768cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_mac_addr_80003es2lan");
1377d035aa2dSJack F Vogel
13787609433eSJack F Vogel /* If there's an alternate MAC address place it in RAR0
1379d035aa2dSJack F Vogel * so that it will override the Si installed default perm
1380d035aa2dSJack F Vogel * address.
1381d035aa2dSJack F Vogel */
1382d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw);
1383d035aa2dSJack F Vogel if (ret_val)
13848cfa0ad2SJack F Vogel return ret_val;
13857609433eSJack F Vogel
13867609433eSJack F Vogel return e1000_read_mac_addr_generic(hw);
13878cfa0ad2SJack F Vogel }
13888cfa0ad2SJack F Vogel
13898cfa0ad2SJack F Vogel /**
13908cfa0ad2SJack F Vogel * e1000_power_down_phy_copper_80003es2lan - Remove link during PHY power down
13918cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
13928cfa0ad2SJack F Vogel *
13938cfa0ad2SJack F Vogel * In the case of a PHY power down to save power, or to turn off link during a
13948cfa0ad2SJack F Vogel * driver unload, or wake on lan is not enabled, remove the link.
13958cfa0ad2SJack F Vogel **/
e1000_power_down_phy_copper_80003es2lan(struct e1000_hw * hw)13968cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_80003es2lan(struct e1000_hw *hw)
13978cfa0ad2SJack F Vogel {
13988cfa0ad2SJack F Vogel /* If the management interface is not enabled, then power down */
13998cfa0ad2SJack F Vogel if (!(hw->mac.ops.check_mng_mode(hw) ||
14008cfa0ad2SJack F Vogel hw->phy.ops.check_reset_block(hw)))
14018cfa0ad2SJack F Vogel e1000_power_down_phy_copper(hw);
14028cfa0ad2SJack F Vogel
14038cfa0ad2SJack F Vogel return;
14048cfa0ad2SJack F Vogel }
14058cfa0ad2SJack F Vogel
14068cfa0ad2SJack F Vogel /**
14078cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_80003es2lan - Clear device specific hardware counters
14088cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
14098cfa0ad2SJack F Vogel *
14108cfa0ad2SJack F Vogel * Clears the hardware counters by reading the counter registers.
14118cfa0ad2SJack F Vogel **/
e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw * hw)14128cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_80003es2lan(struct e1000_hw *hw)
14138cfa0ad2SJack F Vogel {
14148cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_80003es2lan");
14158cfa0ad2SJack F Vogel
14168cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw);
14178cfa0ad2SJack F Vogel
1418daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC64);
1419daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC127);
1420daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC255);
1421daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC511);
1422daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1023);
1423daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1522);
1424daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC64);
1425daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC127);
1426daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC255);
1427daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC511);
1428daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1023);
1429daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1522);
14308cfa0ad2SJack F Vogel
1431daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ALGNERRC);
1432daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RXERRC);
1433daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TNCRS);
1434daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CEXTERR);
1435daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTC);
1436daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTFC);
14378cfa0ad2SJack F Vogel
1438daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPRC);
1439daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPDC);
1440daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPTC);
14418cfa0ad2SJack F Vogel
1442daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_IAC);
1443daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXOC);
14448cfa0ad2SJack F Vogel
1445daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXPTC);
1446daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXATC);
1447daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXPTC);
1448daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXATC);
1449daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQEC);
1450daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQMTC);
1451daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXDMTC);
14528cfa0ad2SJack F Vogel }
1453