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 /*$FreeBSD$*/ 358cfa0ad2SJack F Vogel 36daf9197cSJack F Vogel /* 37daf9197cSJack F Vogel * 82575EB Gigabit Network Connection 38daf9197cSJack F Vogel * 82575EB Gigabit Backplane Connection 39daf9197cSJack F Vogel * 82575GB Gigabit Network Connection 40daf9197cSJack F Vogel * 82576 Gigabit Network Connection 419d81738fSJack F Vogel * 82576 Quad Port Gigabit Mezzanine Adapter 42ab5d0362SJack F Vogel * 82580 Gigabit Network Connection 43ab5d0362SJack F Vogel * I350 Gigabit Network Connection 448cfa0ad2SJack F Vogel */ 458cfa0ad2SJack F Vogel 468cfa0ad2SJack F Vogel #include "e1000_api.h" 47ab5d0362SJack F Vogel #include "e1000_i210.h" 488cfa0ad2SJack F Vogel 498cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw); 508cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82575(struct e1000_hw *hw); 518cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_82575(struct e1000_hw *hw); 528cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw); 538cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw); 548cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw); 558cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw); 567609433eSJack F Vogel static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw); 578cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw); 588cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, 598cfa0ad2SJack F Vogel u16 *duplex); 608cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); 618cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 628cfa0ad2SJack F Vogel u16 *data); 638cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw); 644edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw); 654edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, 664edd8523SJack F Vogel u32 offset, u16 *data); 674edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, 684edd8523SJack F Vogel u32 offset, u16 data); 69f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, 70f0ecc46dSJack F Vogel bool active); 71f0ecc46dSJack F Vogel static s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, 72f0ecc46dSJack F Vogel bool active); 738cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, 748cfa0ad2SJack F Vogel bool active); 758cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw); 764edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw); 774dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw); 784dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw); 798cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data); 808cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, 818cfa0ad2SJack F Vogel u32 offset, u16 data); 828cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw); 838cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, 848cfa0ad2SJack F Vogel u16 *speed, u16 *duplex); 858cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw); 868cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw); 878cfa0ad2SJack F Vogel static s32 e1000_reset_init_script_82575(struct e1000_hw *hw); 888cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw); 89a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw); 908cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw); 914edd8523SJack F Vogel static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw); 92a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw); 939d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw); 947d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw); 95f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw); 96f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw); 97f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, 98f0ecc46dSJack F Vogel u16 offset); 99f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, 100f0ecc46dSJack F Vogel u16 offset); 101f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw); 102f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw); 1034dab5c37SJack F Vogel static void e1000_clear_vfta_i350(struct e1000_hw *hw); 1048cfa0ad2SJack F Vogel 1054dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw); 1064dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw); 1074dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data); 1084dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data); 1094dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw); 1104dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data); 1114dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data); 1124dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); 1134dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); 1144dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data); 1154dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl); 1164dab5c37SJack F Vogel 1174dab5c37SJack F Vogel static const u16 e1000_82580_rxpbs_table[] = { 1184dab5c37SJack F Vogel 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; 1194edd8523SJack F Vogel #define E1000_82580_RXPBS_TABLE_SIZE \ 1208cc64f1eSJack F Vogel (sizeof(e1000_82580_rxpbs_table) / \ 1218cc64f1eSJack F Vogel sizeof(e1000_82580_rxpbs_table[0])) 1224edd8523SJack F Vogel 1237d9119bdSJack F Vogel 1247d9119bdSJack F Vogel /** 1257d9119bdSJack F Vogel * e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO 1267d9119bdSJack F Vogel * @hw: pointer to the HW structure 1277d9119bdSJack F Vogel * 1287d9119bdSJack F Vogel * Called to determine if the I2C pins are being used for I2C or as an 1297d9119bdSJack F Vogel * external MDIO interface since the two options are mutually exclusive. 1307d9119bdSJack F Vogel **/ 1317d9119bdSJack F Vogel static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw) 1327d9119bdSJack F Vogel { 1337d9119bdSJack F Vogel u32 reg = 0; 1347d9119bdSJack F Vogel bool ext_mdio = FALSE; 1357d9119bdSJack F Vogel 1367d9119bdSJack F Vogel DEBUGFUNC("e1000_sgmii_uses_mdio_82575"); 1377d9119bdSJack F Vogel 1387d9119bdSJack F Vogel switch (hw->mac.type) { 1397d9119bdSJack F Vogel case e1000_82575: 1407d9119bdSJack F Vogel case e1000_82576: 1417d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDIC); 1427d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDIC_DEST); 1437d9119bdSJack F Vogel break; 1447d9119bdSJack F Vogel case e1000_82580: 145f0ecc46dSJack F Vogel case e1000_i350: 1467609433eSJack F Vogel case e1000_i354: 1476ab6bfe3SJack F Vogel case e1000_i210: 1486ab6bfe3SJack F Vogel case e1000_i211: 1497d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDICNFG); 1507d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); 1517d9119bdSJack F Vogel break; 1527d9119bdSJack F Vogel default: 1537d9119bdSJack F Vogel break; 1547d9119bdSJack F Vogel } 1557d9119bdSJack F Vogel return ext_mdio; 1567d9119bdSJack F Vogel } 1577d9119bdSJack F Vogel 1588cfa0ad2SJack F Vogel /** 1598cfa0ad2SJack F Vogel * e1000_init_phy_params_82575 - Init PHY func ptrs. 1608cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 1618cfa0ad2SJack F Vogel **/ 1628cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) 1638cfa0ad2SJack F Vogel { 1648cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 1658cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 1667d9119bdSJack F Vogel u32 ctrl_ext; 1678cfa0ad2SJack F Vogel 1688cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_82575"); 1698cfa0ad2SJack F Vogel 170ab5d0362SJack F Vogel phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic; 171ab5d0362SJack F Vogel phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic; 172ab5d0362SJack F Vogel 1738cfa0ad2SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) { 1748cfa0ad2SJack F Vogel phy->type = e1000_phy_none; 1758cfa0ad2SJack F Vogel goto out; 1764edd8523SJack F Vogel } 1774edd8523SJack F Vogel 1788cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper; 1798cfa0ad2SJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper_82575; 1808cfa0ad2SJack F Vogel 1818cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 1828cfa0ad2SJack F Vogel phy->reset_delay_us = 100; 1838cfa0ad2SJack F Vogel 1848cfa0ad2SJack F Vogel phy->ops.acquire = e1000_acquire_phy_82575; 1858cfa0ad2SJack F Vogel phy->ops.check_reset_block = e1000_check_reset_block_generic; 1868cfa0ad2SJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic; 1878cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_82575; 1888cfa0ad2SJack F Vogel phy->ops.release = e1000_release_phy_82575; 1898cfa0ad2SJack F Vogel 1907d9119bdSJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 1917d9119bdSJack F Vogel 1928cfa0ad2SJack F Vogel if (e1000_sgmii_active_82575(hw)) { 1938cfa0ad2SJack F Vogel phy->ops.reset = e1000_phy_hw_reset_sgmii_82575; 1947d9119bdSJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA; 1957d9119bdSJack F Vogel } else { 1967d9119bdSJack F Vogel phy->ops.reset = e1000_phy_hw_reset_generic; 1977d9119bdSJack F Vogel ctrl_ext &= ~E1000_CTRL_I2C_ENA; 1987d9119bdSJack F Vogel } 1997d9119bdSJack F Vogel 2007d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 2017d9119bdSJack F Vogel e1000_reset_mdicnfg_82580(hw); 2027d9119bdSJack F Vogel 2037d9119bdSJack F Vogel if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) { 2048cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; 2058cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; 206ab5d0362SJack F Vogel } else { 207ab5d0362SJack F Vogel switch (hw->mac.type) { 208ab5d0362SJack F Vogel case e1000_82580: 209ab5d0362SJack F Vogel case e1000_i350: 2107609433eSJack F Vogel case e1000_i354: 2114edd8523SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_82580; 2124edd8523SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_82580; 213ab5d0362SJack F Vogel break; 214ab5d0362SJack F Vogel case e1000_i210: 215ab5d0362SJack F Vogel case e1000_i211: 216ab5d0362SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_gs40g; 217ab5d0362SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_gs40g; 218ab5d0362SJack F Vogel break; 219ab5d0362SJack F Vogel default: 2208cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_igp; 2218cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_igp; 2228cfa0ad2SJack F Vogel } 223ab5d0362SJack F Vogel } 2248cfa0ad2SJack F Vogel 2258cfa0ad2SJack F Vogel /* Set phy->phy_addr and phy->id. */ 2268cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id_82575(hw); 2278cfa0ad2SJack F Vogel 2288cfa0ad2SJack F Vogel /* Verify phy id and set remaining function pointers */ 2298cfa0ad2SJack F Vogel switch (phy->id) { 2307609433eSJack F Vogel case M88E1543_E_PHY_ID: 2317609433eSJack F Vogel case M88E1512_E_PHY_ID: 232f0ecc46dSJack F Vogel case I347AT4_E_PHY_ID: 233f0ecc46dSJack F Vogel case M88E1112_E_PHY_ID: 2341fd3c44fSJack F Vogel case M88E1340M_E_PHY_ID: 2358cfa0ad2SJack F Vogel case M88E1111_I_PHY_ID: 2368cfa0ad2SJack F Vogel phy->type = e1000_phy_m88; 2378cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 2388cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 239f0ecc46dSJack F Vogel if (phy->id == I347AT4_E_PHY_ID || 2401fd3c44fSJack F Vogel phy->id == M88E1112_E_PHY_ID || 2411fd3c44fSJack F Vogel phy->id == M88E1340M_E_PHY_ID) 2424dab5c37SJack F Vogel phy->ops.get_cable_length = 2434dab5c37SJack F Vogel e1000_get_cable_length_m88_gen2; 2447609433eSJack F Vogel else if (phy->id == M88E1543_E_PHY_ID || 2457609433eSJack F Vogel phy->id == M88E1512_E_PHY_ID) 2467609433eSJack F Vogel phy->ops.get_cable_length = 2477609433eSJack F Vogel e1000_get_cable_length_m88_gen2; 248f0ecc46dSJack F Vogel else 2498cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88; 2508cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 2517609433eSJack F Vogel /* Check if this PHY is confgured for media swap. */ 2527609433eSJack F Vogel if (phy->id == M88E1112_E_PHY_ID) { 2537609433eSJack F Vogel u16 data; 2547609433eSJack F Vogel 2557609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, 2567609433eSJack F Vogel E1000_M88E1112_PAGE_ADDR, 2577609433eSJack F Vogel 2); 2587609433eSJack F Vogel if (ret_val) 2597609433eSJack F Vogel goto out; 2607609433eSJack F Vogel 2617609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, 2627609433eSJack F Vogel E1000_M88E1112_MAC_CTRL_1, 2637609433eSJack F Vogel &data); 2647609433eSJack F Vogel if (ret_val) 2657609433eSJack F Vogel goto out; 2667609433eSJack F Vogel 2677609433eSJack F Vogel data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >> 2687609433eSJack F Vogel E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT; 2697609433eSJack F Vogel if (data == E1000_M88E1112_AUTO_COPPER_SGMII || 2707609433eSJack F Vogel data == E1000_M88E1112_AUTO_COPPER_BASEX) 2717609433eSJack F Vogel hw->mac.ops.check_for_link = 2727609433eSJack F Vogel e1000_check_for_link_media_swap; 2737609433eSJack F Vogel } 2748cc64f1eSJack F Vogel if (phy->id == M88E1512_E_PHY_ID) { 2758cc64f1eSJack F Vogel ret_val = e1000_initialize_M88E1512_phy(hw); 2768cc64f1eSJack F Vogel if (ret_val) 2778cc64f1eSJack F Vogel goto out; 2788cc64f1eSJack F Vogel } 279c80429ceSEric Joyner if (phy->id == M88E1543_E_PHY_ID) { 280c80429ceSEric Joyner ret_val = e1000_initialize_M88E1543_phy(hw); 281c80429ceSEric Joyner if (ret_val) 282c80429ceSEric Joyner goto out; 283c80429ceSEric Joyner } 2848cfa0ad2SJack F Vogel break; 2858cfa0ad2SJack F Vogel case IGP03E1000_E_PHY_ID: 2868cfa0ad2SJack F Vogel case IGP04E1000_E_PHY_ID: 2878cfa0ad2SJack F Vogel phy->type = e1000_phy_igp_3; 2888cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_igp; 2898cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_igp; 2908cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_igp_2; 2918cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; 2928cfa0ad2SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575; 2938cfa0ad2SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; 2948cfa0ad2SJack F Vogel break; 2954edd8523SJack F Vogel case I82580_I_PHY_ID: 296f0ecc46dSJack F Vogel case I350_I_PHY_ID: 2974edd8523SJack F Vogel phy->type = e1000_phy_82580; 2984edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_82577; 2994dab5c37SJack F Vogel phy->ops.force_speed_duplex = 3004dab5c37SJack F Vogel e1000_phy_force_speed_duplex_82577; 3014edd8523SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_82577; 3024edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_82577; 303f0ecc46dSJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; 304f0ecc46dSJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; 3054edd8523SJack F Vogel break; 306ab5d0362SJack F Vogel case I210_I_PHY_ID: 307ab5d0362SJack F Vogel phy->type = e1000_phy_i210; 308ab5d0362SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 309ab5d0362SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 310ab5d0362SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; 311ab5d0362SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; 312ab5d0362SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; 313ab5d0362SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 314ab5d0362SJack F Vogel break; 3158cfa0ad2SJack F Vogel default: 3168cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 3178cfa0ad2SJack F Vogel goto out; 3188cfa0ad2SJack F Vogel } 3198cfa0ad2SJack F Vogel 3208cfa0ad2SJack F Vogel out: 3218cfa0ad2SJack F Vogel return ret_val; 3228cfa0ad2SJack F Vogel } 3238cfa0ad2SJack F Vogel 3248cfa0ad2SJack F Vogel /** 3258cfa0ad2SJack F Vogel * e1000_init_nvm_params_82575 - Init NVM func ptrs. 3268cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3278cfa0ad2SJack F Vogel **/ 3281fd3c44fSJack F Vogel s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) 3298cfa0ad2SJack F Vogel { 3308cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 3318cfa0ad2SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 3328cfa0ad2SJack F Vogel u16 size; 3338cfa0ad2SJack F Vogel 3348cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_82575"); 3358cfa0ad2SJack F Vogel 336f0ecc46dSJack F Vogel size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> 337f0ecc46dSJack F Vogel E1000_EECD_SIZE_EX_SHIFT); 338f0ecc46dSJack F Vogel /* 339f0ecc46dSJack F Vogel * Added to a constant, "size" becomes the left-shift value 340f0ecc46dSJack F Vogel * for setting word_size. 341f0ecc46dSJack F Vogel */ 342f0ecc46dSJack F Vogel size += NVM_WORD_SIZE_BASE_SHIFT; 343f0ecc46dSJack F Vogel 3444dab5c37SJack F Vogel /* Just in case size is out of range, cap it to the largest 3454dab5c37SJack F Vogel * EEPROM size supported 3464dab5c37SJack F Vogel */ 3474dab5c37SJack F Vogel if (size > 15) 3484dab5c37SJack F Vogel size = 15; 3494dab5c37SJack F Vogel 350f0ecc46dSJack F Vogel nvm->word_size = 1 << size; 351ab5d0362SJack F Vogel if (hw->mac.type < e1000_i210) { 3528cfa0ad2SJack F Vogel nvm->opcode_bits = 8; 3538cfa0ad2SJack F Vogel nvm->delay_usec = 1; 354ab5d0362SJack F Vogel 3558cfa0ad2SJack F Vogel switch (nvm->override) { 3568cfa0ad2SJack F Vogel case e1000_nvm_override_spi_large: 3578cfa0ad2SJack F Vogel nvm->page_size = 32; 3588cfa0ad2SJack F Vogel nvm->address_bits = 16; 3598cfa0ad2SJack F Vogel break; 3608cfa0ad2SJack F Vogel case e1000_nvm_override_spi_small: 3618cfa0ad2SJack F Vogel nvm->page_size = 8; 3628cfa0ad2SJack F Vogel nvm->address_bits = 8; 3638cfa0ad2SJack F Vogel break; 3648cfa0ad2SJack F Vogel default: 3658cfa0ad2SJack F Vogel nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; 366ab5d0362SJack F Vogel nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 367ab5d0362SJack F Vogel 16 : 8; 3688cfa0ad2SJack F Vogel break; 3698cfa0ad2SJack F Vogel } 3701fd3c44fSJack F Vogel if (nvm->word_size == (1 << 15)) 371f0ecc46dSJack F Vogel nvm->page_size = 128; 3728cfa0ad2SJack F Vogel 373ab5d0362SJack F Vogel nvm->type = e1000_nvm_eeprom_spi; 374ab5d0362SJack F Vogel } else { 375ab5d0362SJack F Vogel nvm->type = e1000_nvm_flash_hw; 376ab5d0362SJack F Vogel } 3776ab6bfe3SJack F Vogel 3788cfa0ad2SJack F Vogel /* Function Pointers */ 3798cfa0ad2SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_82575; 3808cfa0ad2SJack F Vogel nvm->ops.release = e1000_release_nvm_82575; 3811fd3c44fSJack F Vogel if (nvm->word_size < (1 << 15)) 3821fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_eerd; 3831fd3c44fSJack F Vogel else 3841fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_spi; 3851fd3c44fSJack F Vogel 3861fd3c44fSJack F Vogel nvm->ops.write = e1000_write_nvm_spi; 3871fd3c44fSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_generic; 3881fd3c44fSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_generic; 3898cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_82575; 3901fd3c44fSJack F Vogel 391ab5d0362SJack F Vogel /* override generic family function pointers for specific descendants */ 392f0ecc46dSJack F Vogel switch (hw->mac.type) { 393f0ecc46dSJack F Vogel case e1000_82580: 394f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_82580; 395f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_82580; 396f0ecc46dSJack F Vogel break; 397f0ecc46dSJack F Vogel case e1000_i350: 3987609433eSJack F Vogel case e1000_i354: 399f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_i350; 400f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_i350; 401f0ecc46dSJack F Vogel break; 402f0ecc46dSJack F Vogel default: 4031fd3c44fSJack F Vogel break; 404f0ecc46dSJack F Vogel } 4058cfa0ad2SJack F Vogel 4068cfa0ad2SJack F Vogel return E1000_SUCCESS; 4078cfa0ad2SJack F Vogel } 4088cfa0ad2SJack F Vogel 4098cfa0ad2SJack F Vogel /** 4108cfa0ad2SJack F Vogel * e1000_init_mac_params_82575 - Init MAC func ptrs. 4118cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4128cfa0ad2SJack F Vogel **/ 4138cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) 4148cfa0ad2SJack F Vogel { 4158cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 416daf9197cSJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 4178cfa0ad2SJack F Vogel 4188cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_mac_params_82575"); 4198cfa0ad2SJack F Vogel 4204dab5c37SJack F Vogel /* Derives media type */ 4214dab5c37SJack F Vogel e1000_get_media_type_82575(hw); 4228cfa0ad2SJack F Vogel /* Set mta register count */ 4238cfa0ad2SJack F Vogel mac->mta_reg_count = 128; 4244edd8523SJack F Vogel /* Set uta register count */ 4254edd8523SJack F Vogel mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; 4268cfa0ad2SJack F Vogel /* Set rar entry count */ 4278cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82575; 4288cfa0ad2SJack F Vogel if (mac->type == e1000_82576) 4298cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82576; 430a69ed8dfSJack F Vogel if (mac->type == e1000_82580) 4314edd8523SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82580; 4327609433eSJack F Vogel if (mac->type == e1000_i350 || mac->type == e1000_i354) 433f0ecc46dSJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_I350; 4346ab6bfe3SJack F Vogel 4356ab6bfe3SJack F Vogel /* Enable EEE default settings for EEE supported devices */ 4366ab6bfe3SJack F Vogel if (mac->type >= e1000_i350) 437f0ecc46dSJack F Vogel dev_spec->eee_disable = FALSE; 4386ab6bfe3SJack F Vogel 4396ab6bfe3SJack F Vogel /* Allow a single clear of the SW semaphore on I210 and newer */ 4406ab6bfe3SJack F Vogel if (mac->type >= e1000_i210) 4416ab6bfe3SJack F Vogel dev_spec->clear_semaphore_once = TRUE; 442f0ecc46dSJack F Vogel 4438cfa0ad2SJack F Vogel /* Set if part includes ASF firmware */ 4448cfa0ad2SJack F Vogel mac->asf_firmware_present = TRUE; 4458ec87fc5SJack F Vogel /* FWSM register */ 4468ec87fc5SJack F Vogel mac->has_fwsm = TRUE; 4478ec87fc5SJack F Vogel /* ARC supported; valid only if manageability features are enabled. */ 4488cfa0ad2SJack F Vogel mac->arc_subsystem_valid = 449ab5d0362SJack F Vogel !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); 4508cfa0ad2SJack F Vogel 4518cfa0ad2SJack F Vogel /* Function pointers */ 4528cfa0ad2SJack F Vogel 4538cfa0ad2SJack F Vogel /* bus type/speed/width */ 4548cfa0ad2SJack F Vogel mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; 4558cfa0ad2SJack F Vogel /* reset */ 456a69ed8dfSJack F Vogel if (mac->type >= e1000_82580) 4574edd8523SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82580; 4584edd8523SJack F Vogel else 4598cfa0ad2SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82575; 4608cfa0ad2SJack F Vogel /* hw initialization */ 4618cc64f1eSJack F Vogel if ((mac->type == e1000_i210) || (mac->type == e1000_i211)) 4628cc64f1eSJack F Vogel mac->ops.init_hw = e1000_init_hw_i210; 4638cc64f1eSJack F Vogel else 4648cfa0ad2SJack F Vogel mac->ops.init_hw = e1000_init_hw_82575; 4658cfa0ad2SJack F Vogel /* link setup */ 4668cfa0ad2SJack F Vogel mac->ops.setup_link = e1000_setup_link_generic; 4678cfa0ad2SJack F Vogel /* physical interface link setup */ 4688cfa0ad2SJack F Vogel mac->ops.setup_physical_interface = 4698cfa0ad2SJack F Vogel (hw->phy.media_type == e1000_media_type_copper) 4704dab5c37SJack F Vogel ? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575; 4718cfa0ad2SJack F Vogel /* physical interface shutdown */ 4724edd8523SJack F Vogel mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575; 473a69ed8dfSJack F Vogel /* physical interface power up */ 474a69ed8dfSJack F Vogel mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; 4758cfa0ad2SJack F Vogel /* check for link */ 4768cfa0ad2SJack F Vogel mac->ops.check_for_link = e1000_check_for_link_82575; 4778cfa0ad2SJack F Vogel /* read mac address */ 4788cfa0ad2SJack F Vogel mac->ops.read_mac_addr = e1000_read_mac_addr_82575; 479a69ed8dfSJack F Vogel /* configure collision distance */ 480a69ed8dfSJack F Vogel mac->ops.config_collision_dist = e1000_config_collision_dist_82575; 4818cfa0ad2SJack F Vogel /* multicast address update */ 482d035aa2dSJack F Vogel mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; 4837609433eSJack F Vogel if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) { 4844dab5c37SJack F Vogel /* writing VFTA */ 4854dab5c37SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_i350; 4864dab5c37SJack F Vogel /* clearing VFTA */ 4874dab5c37SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_i350; 4884dab5c37SJack F Vogel } else { 4898cfa0ad2SJack F Vogel /* writing VFTA */ 4908cfa0ad2SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_generic; 4918cfa0ad2SJack F Vogel /* clearing VFTA */ 4928cfa0ad2SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_generic; 4934dab5c37SJack F Vogel } 4946ab6bfe3SJack F Vogel if (hw->mac.type >= e1000_82580) 4956ab6bfe3SJack F Vogel mac->ops.validate_mdi_setting = 4966ab6bfe3SJack F Vogel e1000_validate_mdi_setting_crossover_generic; 497d035aa2dSJack F Vogel /* ID LED init */ 498d035aa2dSJack F Vogel mac->ops.id_led_init = e1000_id_led_init_generic; 4998cfa0ad2SJack F Vogel /* blink LED */ 5008cfa0ad2SJack F Vogel mac->ops.blink_led = e1000_blink_led_generic; 5018cfa0ad2SJack F Vogel /* setup LED */ 5028cfa0ad2SJack F Vogel mac->ops.setup_led = e1000_setup_led_generic; 5038cfa0ad2SJack F Vogel /* cleanup LED */ 5048cfa0ad2SJack F Vogel mac->ops.cleanup_led = e1000_cleanup_led_generic; 5058cfa0ad2SJack F Vogel /* turn on/off LED */ 5068cfa0ad2SJack F Vogel mac->ops.led_on = e1000_led_on_generic; 5078cfa0ad2SJack F Vogel mac->ops.led_off = e1000_led_off_generic; 5088cfa0ad2SJack F Vogel /* clear hardware counters */ 5098cfa0ad2SJack F Vogel mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; 5108cfa0ad2SJack F Vogel /* link info */ 5118cfa0ad2SJack F Vogel mac->ops.get_link_up_info = e1000_get_link_up_info_82575; 512ab5d0362SJack F Vogel /* acquire SW_FW sync */ 513d5210708SMatt Macy mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync; 514d5210708SMatt Macy mac->ops.release_swfw_sync = e1000_release_swfw_sync; 5158cfa0ad2SJack F Vogel 5164edd8523SJack F Vogel /* set lan id for port to determine which phy lock to use */ 5174edd8523SJack F Vogel hw->mac.ops.set_lan_id(hw); 5184edd8523SJack F Vogel 519daf9197cSJack F Vogel return E1000_SUCCESS; 5208cfa0ad2SJack F Vogel } 5218cfa0ad2SJack F Vogel 5228cfa0ad2SJack F Vogel /** 5238cfa0ad2SJack F Vogel * e1000_init_function_pointers_82575 - Init func ptrs. 5248cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5258cfa0ad2SJack F Vogel * 526daf9197cSJack F Vogel * Called to initialize all function pointers and parameters. 5278cfa0ad2SJack F Vogel **/ 5288cfa0ad2SJack F Vogel void e1000_init_function_pointers_82575(struct e1000_hw *hw) 5298cfa0ad2SJack F Vogel { 5308cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_82575"); 5318cfa0ad2SJack F Vogel 5328cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_82575; 5338cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_82575; 5348cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_82575; 5357d9119bdSJack F Vogel hw->mbx.ops.init_params = e1000_init_mbx_params_pf; 5368cfa0ad2SJack F Vogel } 5378cfa0ad2SJack F Vogel 5388cfa0ad2SJack F Vogel /** 5398cfa0ad2SJack F Vogel * e1000_acquire_phy_82575 - Acquire rights to access PHY 5408cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5418cfa0ad2SJack F Vogel * 542daf9197cSJack F Vogel * Acquire access rights to the correct PHY. 5438cfa0ad2SJack F Vogel **/ 5448cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) 5458cfa0ad2SJack F Vogel { 5469d81738fSJack F Vogel u16 mask = E1000_SWFW_PHY0_SM; 5478cfa0ad2SJack F Vogel 5488cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_phy_82575"); 5498cfa0ad2SJack F Vogel 5509d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 5519d81738fSJack F Vogel mask = E1000_SWFW_PHY1_SM; 5524edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 5534edd8523SJack F Vogel mask = E1000_SWFW_PHY2_SM; 5544edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 5554edd8523SJack F Vogel mask = E1000_SWFW_PHY3_SM; 5568cfa0ad2SJack F Vogel 557ab5d0362SJack F Vogel return hw->mac.ops.acquire_swfw_sync(hw, mask); 5588cfa0ad2SJack F Vogel } 5598cfa0ad2SJack F Vogel 5608cfa0ad2SJack F Vogel /** 5618cfa0ad2SJack F Vogel * e1000_release_phy_82575 - Release rights to access PHY 5628cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5638cfa0ad2SJack F Vogel * 564daf9197cSJack F Vogel * A wrapper to release access rights to the correct PHY. 5658cfa0ad2SJack F Vogel **/ 5668cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw) 5678cfa0ad2SJack F Vogel { 5689d81738fSJack F Vogel u16 mask = E1000_SWFW_PHY0_SM; 5698cfa0ad2SJack F Vogel 5708cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_phy_82575"); 5718cfa0ad2SJack F Vogel 5729d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 5739d81738fSJack F Vogel mask = E1000_SWFW_PHY1_SM; 5744edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 5754edd8523SJack F Vogel mask = E1000_SWFW_PHY2_SM; 5764edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 5774edd8523SJack F Vogel mask = E1000_SWFW_PHY3_SM; 5789d81738fSJack F Vogel 579ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, mask); 5808cfa0ad2SJack F Vogel } 5818cfa0ad2SJack F Vogel 5828cfa0ad2SJack F Vogel /** 5838cfa0ad2SJack F Vogel * e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii 5848cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5858cfa0ad2SJack F Vogel * @offset: register offset to be read 5868cfa0ad2SJack F Vogel * @data: pointer to the read data 5878cfa0ad2SJack F Vogel * 5888cfa0ad2SJack F Vogel * Reads the PHY register at offset using the serial gigabit media independent 5898cfa0ad2SJack F Vogel * interface and stores the retrieved information in data. 5908cfa0ad2SJack F Vogel **/ 5918cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 5928cfa0ad2SJack F Vogel u16 *data) 5938cfa0ad2SJack F Vogel { 5944edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM; 5958cfa0ad2SJack F Vogel 5968cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_sgmii_82575"); 5978cfa0ad2SJack F Vogel 5988cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 5998cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %u is out of range\n", offset); 6004edd8523SJack F Vogel goto out; 6018cfa0ad2SJack F Vogel } 6028cfa0ad2SJack F Vogel 6034edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 6044edd8523SJack F Vogel if (ret_val) 6054edd8523SJack F Vogel goto out; 6068cfa0ad2SJack F Vogel 6074edd8523SJack F Vogel ret_val = e1000_read_phy_reg_i2c(hw, offset, data); 6088cfa0ad2SJack F Vogel 6094edd8523SJack F Vogel hw->phy.ops.release(hw); 6108cfa0ad2SJack F Vogel 6114edd8523SJack F Vogel out: 6124edd8523SJack F Vogel return ret_val; 6138cfa0ad2SJack F Vogel } 6148cfa0ad2SJack F Vogel 6158cfa0ad2SJack F Vogel /** 6168cfa0ad2SJack F Vogel * e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii 6178cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6188cfa0ad2SJack F Vogel * @offset: register offset to write to 6198cfa0ad2SJack F Vogel * @data: data to write at register offset 6208cfa0ad2SJack F Vogel * 6218cfa0ad2SJack F Vogel * Writes the data to PHY register at the offset using the serial gigabit 6228cfa0ad2SJack F Vogel * media independent interface. 6238cfa0ad2SJack F Vogel **/ 6248cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 6258cfa0ad2SJack F Vogel u16 data) 6268cfa0ad2SJack F Vogel { 6274edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM; 6288cfa0ad2SJack F Vogel 6298cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_sgmii_82575"); 6308cfa0ad2SJack F Vogel 6318cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 6328cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %d is out of range\n", offset); 6334edd8523SJack F Vogel goto out; 6348cfa0ad2SJack F Vogel } 6358cfa0ad2SJack F Vogel 6364edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 6374edd8523SJack F Vogel if (ret_val) 6384edd8523SJack F Vogel goto out; 6398cfa0ad2SJack F Vogel 6404edd8523SJack F Vogel ret_val = e1000_write_phy_reg_i2c(hw, offset, data); 6418cfa0ad2SJack F Vogel 6424edd8523SJack F Vogel hw->phy.ops.release(hw); 6438cfa0ad2SJack F Vogel 6444edd8523SJack F Vogel out: 6454edd8523SJack F Vogel return ret_val; 6468cfa0ad2SJack F Vogel } 6478cfa0ad2SJack F Vogel 6488cfa0ad2SJack F Vogel /** 6498cfa0ad2SJack F Vogel * e1000_get_phy_id_82575 - Retrieve PHY addr and id 6508cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6518cfa0ad2SJack F Vogel * 6528cfa0ad2SJack F Vogel * Retrieves the PHY address and ID for both PHY's which do and do not use 6538cfa0ad2SJack F Vogel * sgmi interface. 6548cfa0ad2SJack F Vogel **/ 6558cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) 6568cfa0ad2SJack F Vogel { 6578cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 6588cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 6598cfa0ad2SJack F Vogel u16 phy_id; 6604edd8523SJack F Vogel u32 ctrl_ext; 6617d9119bdSJack F Vogel u32 mdic; 6628cfa0ad2SJack F Vogel 6638cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_phy_id_82575"); 6648cfa0ad2SJack F Vogel 6657609433eSJack F Vogel /* some i354 devices need an extra read for phy id */ 6667609433eSJack F Vogel if (hw->mac.type == e1000_i354) 6677609433eSJack F Vogel e1000_get_phy_id(hw); 6687609433eSJack F Vogel 6698cfa0ad2SJack F Vogel /* 6708cfa0ad2SJack F Vogel * For SGMII PHYs, we try the list of possible addresses until 6718cfa0ad2SJack F Vogel * we find one that works. For non-SGMII PHYs 6728cfa0ad2SJack F Vogel * (e.g. integrated copper PHYs), an address of 1 should 6738cfa0ad2SJack F Vogel * work. The result of this function should mean phy->phy_addr 6748cfa0ad2SJack F Vogel * and phy->id are set correctly. 6758cfa0ad2SJack F Vogel */ 6764edd8523SJack F Vogel if (!e1000_sgmii_active_82575(hw)) { 6778cfa0ad2SJack F Vogel phy->addr = 1; 6788cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw); 6798cfa0ad2SJack F Vogel goto out; 6808cfa0ad2SJack F Vogel } 6818cfa0ad2SJack F Vogel 6827d9119bdSJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) { 6837d9119bdSJack F Vogel switch (hw->mac.type) { 6847d9119bdSJack F Vogel case e1000_82575: 6857d9119bdSJack F Vogel case e1000_82576: 6867d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDIC); 6877d9119bdSJack F Vogel mdic &= E1000_MDIC_PHY_MASK; 6887d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDIC_PHY_SHIFT; 6897d9119bdSJack F Vogel break; 6907d9119bdSJack F Vogel case e1000_82580: 691f0ecc46dSJack F Vogel case e1000_i350: 6927609433eSJack F Vogel case e1000_i354: 6936ab6bfe3SJack F Vogel case e1000_i210: 6946ab6bfe3SJack F Vogel case e1000_i211: 6957d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDICNFG); 6967d9119bdSJack F Vogel mdic &= E1000_MDICNFG_PHY_MASK; 6977d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; 6987d9119bdSJack F Vogel break; 6997d9119bdSJack F Vogel default: 7007d9119bdSJack F Vogel ret_val = -E1000_ERR_PHY; 7017d9119bdSJack F Vogel goto out; 7027d9119bdSJack F Vogel break; 7037d9119bdSJack F Vogel } 7047d9119bdSJack F Vogel ret_val = e1000_get_phy_id(hw); 7057d9119bdSJack F Vogel goto out; 7067d9119bdSJack F Vogel } 7077d9119bdSJack F Vogel 7084edd8523SJack F Vogel /* Power on sgmii phy if it is disabled */ 7094edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 7104edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, 7114edd8523SJack F Vogel ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); 7124edd8523SJack F Vogel E1000_WRITE_FLUSH(hw); 7134edd8523SJack F Vogel msec_delay(300); 7144edd8523SJack F Vogel 7158cfa0ad2SJack F Vogel /* 7168cfa0ad2SJack F Vogel * The address field in the I2CCMD register is 3 bits and 0 is invalid. 7178cfa0ad2SJack F Vogel * Therefore, we need to test 1-7 7188cfa0ad2SJack F Vogel */ 7198cfa0ad2SJack F Vogel for (phy->addr = 1; phy->addr < 8; phy->addr++) { 7208cfa0ad2SJack F Vogel ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id); 7218cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) { 7228cfa0ad2SJack F Vogel DEBUGOUT2("Vendor ID 0x%08X read at address %u\n", 7234dab5c37SJack F Vogel phy_id, phy->addr); 7248cfa0ad2SJack F Vogel /* 7258cfa0ad2SJack F Vogel * At the time of this writing, The M88 part is 7268cfa0ad2SJack F Vogel * the only supported SGMII PHY product. 7278cfa0ad2SJack F Vogel */ 7288cfa0ad2SJack F Vogel if (phy_id == M88_VENDOR) 7298cfa0ad2SJack F Vogel break; 7308cfa0ad2SJack F Vogel } else { 7318cfa0ad2SJack F Vogel DEBUGOUT1("PHY address %u was unreadable\n", 7328cfa0ad2SJack F Vogel phy->addr); 7338cfa0ad2SJack F Vogel } 7348cfa0ad2SJack F Vogel } 7358cfa0ad2SJack F Vogel 7368cfa0ad2SJack F Vogel /* A valid PHY type couldn't be found. */ 7378cfa0ad2SJack F Vogel if (phy->addr == 8) { 7388cfa0ad2SJack F Vogel phy->addr = 0; 7398cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 7404edd8523SJack F Vogel } else { 7414edd8523SJack F Vogel ret_val = e1000_get_phy_id(hw); 7428cfa0ad2SJack F Vogel } 7438cfa0ad2SJack F Vogel 7444edd8523SJack F Vogel /* restore previous sfp cage power state */ 7454edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 7468cfa0ad2SJack F Vogel 7478cfa0ad2SJack F Vogel out: 7488cfa0ad2SJack F Vogel return ret_val; 7498cfa0ad2SJack F Vogel } 7508cfa0ad2SJack F Vogel 7518cfa0ad2SJack F Vogel /** 7528cfa0ad2SJack F Vogel * e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset 7538cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7548cfa0ad2SJack F Vogel * 7558cfa0ad2SJack F Vogel * Resets the PHY using the serial gigabit media independent interface. 7568cfa0ad2SJack F Vogel **/ 7578cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) 7588cfa0ad2SJack F Vogel { 7598cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 7608cc64f1eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 7618cfa0ad2SJack F Vogel 7628cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); 7638cfa0ad2SJack F Vogel 7648cfa0ad2SJack F Vogel /* 7658cfa0ad2SJack F Vogel * This isn't a TRUE "hard" reset, but is the only reset 7668cfa0ad2SJack F Vogel * available to us at this time. 7678cfa0ad2SJack F Vogel */ 7688cfa0ad2SJack F Vogel 7698cfa0ad2SJack F Vogel DEBUGOUT("Soft resetting SGMII attached PHY...\n"); 7708cfa0ad2SJack F Vogel 7718cfa0ad2SJack F Vogel if (!(hw->phy.ops.write_reg)) 7728cfa0ad2SJack F Vogel goto out; 7738cfa0ad2SJack F Vogel 7748cfa0ad2SJack F Vogel /* 7758cfa0ad2SJack F Vogel * SFP documentation requires the following to configure the SPF module 7768cfa0ad2SJack F Vogel * to work on SGMII. No further documentation is given. 7778cfa0ad2SJack F Vogel */ 7788cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); 7798cfa0ad2SJack F Vogel if (ret_val) 7808cfa0ad2SJack F Vogel goto out; 7818cfa0ad2SJack F Vogel 7828cfa0ad2SJack F Vogel ret_val = hw->phy.ops.commit(hw); 7838cc64f1eSJack F Vogel if (ret_val) 7848cc64f1eSJack F Vogel goto out; 7858cfa0ad2SJack F Vogel 7868cc64f1eSJack F Vogel if (phy->id == M88E1512_E_PHY_ID) 7878cc64f1eSJack F Vogel ret_val = e1000_initialize_M88E1512_phy(hw); 7888cfa0ad2SJack F Vogel out: 7898cfa0ad2SJack F Vogel return ret_val; 7908cfa0ad2SJack F Vogel } 7918cfa0ad2SJack F Vogel 7928cfa0ad2SJack F Vogel /** 7938cfa0ad2SJack F Vogel * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state 7948cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7958cfa0ad2SJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 7968cfa0ad2SJack F Vogel * 7978cfa0ad2SJack F Vogel * Sets the LPLU D0 state according to the active flag. When 7988cfa0ad2SJack F Vogel * activating LPLU this function also disables smart speed 7998cfa0ad2SJack F Vogel * and vice versa. LPLU will not be activated unless the 8008cfa0ad2SJack F Vogel * device autonegotiation advertisement meets standards of 8018cfa0ad2SJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 8028cfa0ad2SJack F Vogel * This is a function pointer entry point only called by 8038cfa0ad2SJack F Vogel * PHY setup routines. 8048cfa0ad2SJack F Vogel **/ 8058cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) 8068cfa0ad2SJack F Vogel { 8078cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 8088cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 8098cfa0ad2SJack F Vogel u16 data; 8108cfa0ad2SJack F Vogel 8118cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82575"); 8128cfa0ad2SJack F Vogel 8138cfa0ad2SJack F Vogel if (!(hw->phy.ops.read_reg)) 8148cfa0ad2SJack F Vogel goto out; 8158cfa0ad2SJack F Vogel 8168cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); 8178cfa0ad2SJack F Vogel if (ret_val) 8188cfa0ad2SJack F Vogel goto out; 8198cfa0ad2SJack F Vogel 8208cfa0ad2SJack F Vogel if (active) { 8218cfa0ad2SJack F Vogel data |= IGP02E1000_PM_D0_LPLU; 8228cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 8238cfa0ad2SJack F Vogel data); 8248cfa0ad2SJack F Vogel if (ret_val) 8258cfa0ad2SJack F Vogel goto out; 8268cfa0ad2SJack F Vogel 8278cfa0ad2SJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 8288cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 8298cfa0ad2SJack F Vogel &data); 8308cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 8318cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 8328cfa0ad2SJack F Vogel data); 8338cfa0ad2SJack F Vogel if (ret_val) 8348cfa0ad2SJack F Vogel goto out; 8358cfa0ad2SJack F Vogel } else { 8368cfa0ad2SJack F Vogel data &= ~IGP02E1000_PM_D0_LPLU; 8378cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 8388cfa0ad2SJack F Vogel data); 8398cfa0ad2SJack F Vogel /* 8408cfa0ad2SJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 8418cfa0ad2SJack F Vogel * during Dx states where the power conservation is most 8428cfa0ad2SJack F Vogel * important. During driver activity we should enable 8438cfa0ad2SJack F Vogel * SmartSpeed, so performance is maintained. 8448cfa0ad2SJack F Vogel */ 8458cfa0ad2SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) { 8468cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 8478cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8488cfa0ad2SJack F Vogel &data); 8498cfa0ad2SJack F Vogel if (ret_val) 8508cfa0ad2SJack F Vogel goto out; 8518cfa0ad2SJack F Vogel 8528cfa0ad2SJack F Vogel data |= IGP01E1000_PSCFR_SMART_SPEED; 8538cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8548cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8558cfa0ad2SJack F Vogel data); 8568cfa0ad2SJack F Vogel if (ret_val) 8578cfa0ad2SJack F Vogel goto out; 8588cfa0ad2SJack F Vogel } else if (phy->smart_speed == e1000_smart_speed_off) { 8598cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 8608cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8618cfa0ad2SJack F Vogel &data); 8628cfa0ad2SJack F Vogel if (ret_val) 8638cfa0ad2SJack F Vogel goto out; 8648cfa0ad2SJack F Vogel 8658cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 8668cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8678cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8688cfa0ad2SJack F Vogel data); 8698cfa0ad2SJack F Vogel if (ret_val) 8708cfa0ad2SJack F Vogel goto out; 8718cfa0ad2SJack F Vogel } 8728cfa0ad2SJack F Vogel } 8738cfa0ad2SJack F Vogel 8748cfa0ad2SJack F Vogel out: 8758cfa0ad2SJack F Vogel return ret_val; 8768cfa0ad2SJack F Vogel } 8778cfa0ad2SJack F Vogel 8788cfa0ad2SJack F Vogel /** 879f0ecc46dSJack F Vogel * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state 880f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 881f0ecc46dSJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 882f0ecc46dSJack F Vogel * 883f0ecc46dSJack F Vogel * Sets the LPLU D0 state according to the active flag. When 884f0ecc46dSJack F Vogel * activating LPLU this function also disables smart speed 885f0ecc46dSJack F Vogel * and vice versa. LPLU will not be activated unless the 886f0ecc46dSJack F Vogel * device autonegotiation advertisement meets standards of 887f0ecc46dSJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 888f0ecc46dSJack F Vogel * This is a function pointer entry point only called by 889f0ecc46dSJack F Vogel * PHY setup routines. 890f0ecc46dSJack F Vogel **/ 891f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) 892f0ecc46dSJack F Vogel { 893f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 894ab5d0362SJack F Vogel u32 data; 895f0ecc46dSJack F Vogel 896f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82580"); 897f0ecc46dSJack F Vogel 898f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 899f0ecc46dSJack F Vogel 900f0ecc46dSJack F Vogel if (active) { 901f0ecc46dSJack F Vogel data |= E1000_82580_PM_D0_LPLU; 902f0ecc46dSJack F Vogel 903f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 904f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 905f0ecc46dSJack F Vogel } else { 906f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D0_LPLU; 907f0ecc46dSJack F Vogel 908f0ecc46dSJack F Vogel /* 909f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 910f0ecc46dSJack F Vogel * during Dx states where the power conservation is most 911f0ecc46dSJack F Vogel * important. During driver activity we should enable 912f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained. 913f0ecc46dSJack F Vogel */ 9144dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) 915f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD; 9164dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off) 917f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 918f0ecc46dSJack F Vogel } 919f0ecc46dSJack F Vogel 920f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); 9218cc64f1eSJack F Vogel return E1000_SUCCESS; 922f0ecc46dSJack F Vogel } 923f0ecc46dSJack F Vogel 924f0ecc46dSJack F Vogel /** 925f0ecc46dSJack F Vogel * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3 926f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 927f0ecc46dSJack F Vogel * @active: boolean used to enable/disable lplu 928f0ecc46dSJack F Vogel * 929f0ecc46dSJack F Vogel * Success returns 0, Failure returns 1 930f0ecc46dSJack F Vogel * 931f0ecc46dSJack F Vogel * The low power link up (lplu) state is set to the power management level D3 932f0ecc46dSJack F Vogel * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3 933f0ecc46dSJack F Vogel * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU 934f0ecc46dSJack F Vogel * is used during Dx states where the power conservation is most important. 935f0ecc46dSJack F Vogel * During driver activity, SmartSpeed should be enabled so performance is 936f0ecc46dSJack F Vogel * maintained. 937f0ecc46dSJack F Vogel **/ 938f0ecc46dSJack F Vogel s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) 939f0ecc46dSJack F Vogel { 940f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 941ab5d0362SJack F Vogel u32 data; 942f0ecc46dSJack F Vogel 943f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d3_lplu_state_82580"); 944f0ecc46dSJack F Vogel 945f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 946f0ecc46dSJack F Vogel 947f0ecc46dSJack F Vogel if (!active) { 948f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D3_LPLU; 949f0ecc46dSJack F Vogel /* 950f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 951f0ecc46dSJack F Vogel * during Dx states where the power conservation is most 952f0ecc46dSJack F Vogel * important. During driver activity we should enable 953f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained. 954f0ecc46dSJack F Vogel */ 9554dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) 956f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD; 9574dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off) 958f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 959f0ecc46dSJack F Vogel } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 960f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 961f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 962f0ecc46dSJack F Vogel data |= E1000_82580_PM_D3_LPLU; 963f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 964f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 965f0ecc46dSJack F Vogel } 966f0ecc46dSJack F Vogel 967f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); 9688cc64f1eSJack F Vogel return E1000_SUCCESS; 969f0ecc46dSJack F Vogel } 970f0ecc46dSJack F Vogel 971f0ecc46dSJack F Vogel /** 9728cfa0ad2SJack F Vogel * e1000_acquire_nvm_82575 - Request for access to EEPROM 9738cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 9748cfa0ad2SJack F Vogel * 9758cfa0ad2SJack F Vogel * Acquire the necessary semaphores for exclusive access to the EEPROM. 9768cfa0ad2SJack F Vogel * Set the EEPROM access request bit and wait for EEPROM access grant bit. 9778cfa0ad2SJack F Vogel * Return successful if access grant bit set, else clear the request for 9788cfa0ad2SJack F Vogel * EEPROM access and return -E1000_ERR_NVM (-1). 9798cfa0ad2SJack F Vogel **/ 9808cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) 9818cfa0ad2SJack F Vogel { 9828cc64f1eSJack F Vogel s32 ret_val = E1000_SUCCESS; 9838cfa0ad2SJack F Vogel 9848cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_nvm_82575"); 9858cfa0ad2SJack F Vogel 986d5210708SMatt Macy ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM); 9878cfa0ad2SJack F Vogel if (ret_val) 9888cfa0ad2SJack F Vogel goto out; 9894dab5c37SJack F Vogel 9904dab5c37SJack F Vogel /* 9914dab5c37SJack F Vogel * Check if there is some access 9924dab5c37SJack F Vogel * error this access may hook on 9934dab5c37SJack F Vogel */ 9944dab5c37SJack F Vogel if (hw->mac.type == e1000_i350) { 9954dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 9964dab5c37SJack F Vogel if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT | 9974dab5c37SJack F Vogel E1000_EECD_TIMEOUT)) { 9984dab5c37SJack F Vogel /* Clear all access error flags */ 9994dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd | 10004dab5c37SJack F Vogel E1000_EECD_ERROR_CLR); 10014dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); 10024dab5c37SJack F Vogel } 10034dab5c37SJack F Vogel } 10048cc64f1eSJack F Vogel 10054dab5c37SJack F Vogel if (hw->mac.type == e1000_82580) { 10064dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 10074dab5c37SJack F Vogel if (eecd & E1000_EECD_BLOCKED) { 10084dab5c37SJack F Vogel /* Clear access error flag */ 10094dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd | 10104dab5c37SJack F Vogel E1000_EECD_BLOCKED); 10114dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); 10124dab5c37SJack F Vogel } 10134dab5c37SJack F Vogel } 10144dab5c37SJack F Vogel 10158cfa0ad2SJack F Vogel ret_val = e1000_acquire_nvm_generic(hw); 10168cfa0ad2SJack F Vogel if (ret_val) 1017d5210708SMatt Macy e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM); 10188cfa0ad2SJack F Vogel 10198cfa0ad2SJack F Vogel out: 10208cfa0ad2SJack F Vogel return ret_val; 10218cfa0ad2SJack F Vogel } 10228cfa0ad2SJack F Vogel 10238cfa0ad2SJack F Vogel /** 10248cfa0ad2SJack F Vogel * e1000_release_nvm_82575 - Release exclusive access to EEPROM 10258cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10268cfa0ad2SJack F Vogel * 10278cfa0ad2SJack F Vogel * Stop any current commands to the EEPROM and clear the EEPROM request bit, 10288cfa0ad2SJack F Vogel * then release the semaphores acquired. 10298cfa0ad2SJack F Vogel **/ 10308cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw) 10318cfa0ad2SJack F Vogel { 10328cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_nvm_82575"); 10338cfa0ad2SJack F Vogel 10344dab5c37SJack F Vogel e1000_release_nvm_generic(hw); 1035ab5d0362SJack F Vogel 1036d5210708SMatt Macy e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM); 10378cfa0ad2SJack F Vogel } 10388cfa0ad2SJack F Vogel 10398cfa0ad2SJack F Vogel /** 10408cfa0ad2SJack F Vogel * e1000_get_cfg_done_82575 - Read config done bit 10418cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10428cfa0ad2SJack F Vogel * 10438cfa0ad2SJack F Vogel * Read the management control register for the config done bit for 10448cfa0ad2SJack F Vogel * completion status. NOTE: silicon which is EEPROM-less will fail trying 10458cfa0ad2SJack F Vogel * to read the config done bit, so an error is *ONLY* logged and returns 10468cfa0ad2SJack F Vogel * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon 10478cfa0ad2SJack F Vogel * would not be able to be reset or change link. 10488cfa0ad2SJack F Vogel **/ 10498cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) 10508cfa0ad2SJack F Vogel { 10518cfa0ad2SJack F Vogel s32 timeout = PHY_CFG_TIMEOUT; 10528cfa0ad2SJack F Vogel u32 mask = E1000_NVM_CFG_DONE_PORT_0; 10538cfa0ad2SJack F Vogel 10548cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_cfg_done_82575"); 10558cfa0ad2SJack F Vogel 10569d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 10578cfa0ad2SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_1; 10584edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 10594edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_2; 10604edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 10614edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_3; 10628cfa0ad2SJack F Vogel while (timeout) { 10638cfa0ad2SJack F Vogel if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) 10648cfa0ad2SJack F Vogel break; 10658cfa0ad2SJack F Vogel msec_delay(1); 10668cfa0ad2SJack F Vogel timeout--; 10678cfa0ad2SJack F Vogel } 10684edd8523SJack F Vogel if (!timeout) 10698cfa0ad2SJack F Vogel DEBUGOUT("MNG configuration cycle has not completed.\n"); 10708cfa0ad2SJack F Vogel 10718cfa0ad2SJack F Vogel /* If EEPROM is not marked present, init the PHY manually */ 1072ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && 10734edd8523SJack F Vogel (hw->phy.type == e1000_phy_igp_3)) 10748cfa0ad2SJack F Vogel e1000_phy_init_script_igp3(hw); 10758cfa0ad2SJack F Vogel 10768cc64f1eSJack F Vogel return E1000_SUCCESS; 10778cfa0ad2SJack F Vogel } 10788cfa0ad2SJack F Vogel 10798cfa0ad2SJack F Vogel /** 10808cfa0ad2SJack F Vogel * e1000_get_link_up_info_82575 - Get link speed/duplex info 10818cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10828cfa0ad2SJack F Vogel * @speed: stores the current speed 10838cfa0ad2SJack F Vogel * @duplex: stores the current duplex 10848cfa0ad2SJack F Vogel * 10858cfa0ad2SJack F Vogel * This is a wrapper function, if using the serial gigabit media independent 10868cfa0ad2SJack F Vogel * interface, use PCS to retrieve the link speed and duplex information. 10878cfa0ad2SJack F Vogel * Otherwise, use the generic function to get the link speed and duplex info. 10888cfa0ad2SJack F Vogel **/ 10898cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, 10908cfa0ad2SJack F Vogel u16 *duplex) 10918cfa0ad2SJack F Vogel { 10928cfa0ad2SJack F Vogel s32 ret_val; 10938cfa0ad2SJack F Vogel 10948cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_link_up_info_82575"); 10958cfa0ad2SJack F Vogel 10964edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) 10978cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed, 10988cfa0ad2SJack F Vogel duplex); 10994edd8523SJack F Vogel else 11008cfa0ad2SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, 11018cfa0ad2SJack F Vogel duplex); 11028cfa0ad2SJack F Vogel 11038cfa0ad2SJack F Vogel return ret_val; 11048cfa0ad2SJack F Vogel } 11058cfa0ad2SJack F Vogel 11068cfa0ad2SJack F Vogel /** 11078cfa0ad2SJack F Vogel * e1000_check_for_link_82575 - Check for link 11088cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11098cfa0ad2SJack F Vogel * 11108cfa0ad2SJack F Vogel * If sgmii is enabled, then use the pcs register to determine link, otherwise 11118cfa0ad2SJack F Vogel * use the generic interface for determining link. 11128cfa0ad2SJack F Vogel **/ 11138cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw) 11148cfa0ad2SJack F Vogel { 11158cfa0ad2SJack F Vogel s32 ret_val; 11168cfa0ad2SJack F Vogel u16 speed, duplex; 11178cfa0ad2SJack F Vogel 11188cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_for_link_82575"); 11198cfa0ad2SJack F Vogel 11204edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) { 11218cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed, 11228cfa0ad2SJack F Vogel &duplex); 1123d035aa2dSJack F Vogel /* 1124d035aa2dSJack F Vogel * Use this flag to determine if link needs to be checked or 1125d035aa2dSJack F Vogel * not. If we have link clear the flag so that we do not 1126d035aa2dSJack F Vogel * continue to check for link. 1127d035aa2dSJack F Vogel */ 1128d035aa2dSJack F Vogel hw->mac.get_link_status = !hw->mac.serdes_has_link; 1129ab5d0362SJack F Vogel 11306ab6bfe3SJack F Vogel /* 11316ab6bfe3SJack F Vogel * Configure Flow Control now that Auto-Neg has completed. 11326ab6bfe3SJack F Vogel * First, we need to restore the desired flow control 11336ab6bfe3SJack F Vogel * settings because we may have had to re-autoneg with a 11346ab6bfe3SJack F Vogel * different link partner. 11356ab6bfe3SJack F Vogel */ 11366ab6bfe3SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw); 11376ab6bfe3SJack F Vogel if (ret_val) 11386ab6bfe3SJack F Vogel DEBUGOUT("Error configuring flow control\n"); 1139d035aa2dSJack F Vogel } else { 11408cfa0ad2SJack F Vogel ret_val = e1000_check_for_copper_link_generic(hw); 1141d035aa2dSJack F Vogel } 11428cfa0ad2SJack F Vogel 11438cfa0ad2SJack F Vogel return ret_val; 11448cfa0ad2SJack F Vogel } 11458cfa0ad2SJack F Vogel 11468cfa0ad2SJack F Vogel /** 11477609433eSJack F Vogel * e1000_check_for_link_media_swap - Check which M88E1112 interface linked 11487609433eSJack F Vogel * @hw: pointer to the HW structure 11497609433eSJack F Vogel * 11507609433eSJack F Vogel * Poll the M88E1112 interfaces to see which interface achieved link. 11517609433eSJack F Vogel */ 11527609433eSJack F Vogel static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) 11537609433eSJack F Vogel { 11547609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 11557609433eSJack F Vogel s32 ret_val; 11567609433eSJack F Vogel u16 data; 11577609433eSJack F Vogel u8 port = 0; 11587609433eSJack F Vogel 11597609433eSJack F Vogel DEBUGFUNC("e1000_check_for_link_media_swap"); 11607609433eSJack F Vogel 1161c80429ceSEric Joyner /* Check for copper. */ 11627609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 11637609433eSJack F Vogel if (ret_val) 11647609433eSJack F Vogel return ret_val; 11657609433eSJack F Vogel 11667609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); 11677609433eSJack F Vogel if (ret_val) 11687609433eSJack F Vogel return ret_val; 11697609433eSJack F Vogel 11707609433eSJack F Vogel if (data & E1000_M88E1112_STATUS_LINK) 11717609433eSJack F Vogel port = E1000_MEDIA_PORT_COPPER; 11727609433eSJack F Vogel 1173c80429ceSEric Joyner /* Check for other. */ 11747609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); 11757609433eSJack F Vogel if (ret_val) 11767609433eSJack F Vogel return ret_val; 11777609433eSJack F Vogel 11787609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); 11797609433eSJack F Vogel if (ret_val) 11807609433eSJack F Vogel return ret_val; 11817609433eSJack F Vogel 11827609433eSJack F Vogel if (data & E1000_M88E1112_STATUS_LINK) 11837609433eSJack F Vogel port = E1000_MEDIA_PORT_OTHER; 11847609433eSJack F Vogel 11857609433eSJack F Vogel /* Determine if a swap needs to happen. */ 11867609433eSJack F Vogel if (port && (hw->dev_spec._82575.media_port != port)) { 11877609433eSJack F Vogel hw->dev_spec._82575.media_port = port; 11887609433eSJack F Vogel hw->dev_spec._82575.media_changed = TRUE; 1189c80429ceSEric Joyner } 1190c80429ceSEric Joyner 1191c80429ceSEric Joyner if (port == E1000_MEDIA_PORT_COPPER) { 1192c80429ceSEric Joyner /* reset page to 0 */ 1193c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 1194c80429ceSEric Joyner if (ret_val) 1195c80429ceSEric Joyner return ret_val; 1196c80429ceSEric Joyner e1000_check_for_link_82575(hw); 11977609433eSJack F Vogel } else { 1198c80429ceSEric Joyner e1000_check_for_link_82575(hw); 1199c80429ceSEric Joyner /* reset page to 0 */ 1200c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 1201c80429ceSEric Joyner if (ret_val) 1202c80429ceSEric Joyner return ret_val; 12037609433eSJack F Vogel } 12047609433eSJack F Vogel 12057609433eSJack F Vogel return E1000_SUCCESS; 12067609433eSJack F Vogel } 12077609433eSJack F Vogel 12087609433eSJack F Vogel /** 1209a69ed8dfSJack F Vogel * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown 1210a69ed8dfSJack F Vogel * @hw: pointer to the HW structure 1211a69ed8dfSJack F Vogel **/ 1212a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw) 1213a69ed8dfSJack F Vogel { 1214a69ed8dfSJack F Vogel u32 reg; 1215a69ed8dfSJack F Vogel 1216a69ed8dfSJack F Vogel DEBUGFUNC("e1000_power_up_serdes_link_82575"); 1217a69ed8dfSJack F Vogel 1218a69ed8dfSJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 1219a69ed8dfSJack F Vogel !e1000_sgmii_active_82575(hw)) 1220a69ed8dfSJack F Vogel return; 1221a69ed8dfSJack F Vogel 1222a69ed8dfSJack F Vogel /* Enable PCS to turn on link */ 1223a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0); 1224a69ed8dfSJack F Vogel reg |= E1000_PCS_CFG_PCS_EN; 1225a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); 1226a69ed8dfSJack F Vogel 1227a69ed8dfSJack F Vogel /* Power up the laser */ 1228a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT); 1229a69ed8dfSJack F Vogel reg &= ~E1000_CTRL_EXT_SDP3_DATA; 1230a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); 1231a69ed8dfSJack F Vogel 1232a69ed8dfSJack F Vogel /* flush the write to verify completion */ 1233a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw); 1234a69ed8dfSJack F Vogel msec_delay(1); 1235a69ed8dfSJack F Vogel } 1236a69ed8dfSJack F Vogel 1237a69ed8dfSJack F Vogel /** 12388cfa0ad2SJack F Vogel * e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex 12398cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 12408cfa0ad2SJack F Vogel * @speed: stores the current speed 12418cfa0ad2SJack F Vogel * @duplex: stores the current duplex 12428cfa0ad2SJack F Vogel * 12438cfa0ad2SJack F Vogel * Using the physical coding sub-layer (PCS), retrieve the current speed and 12448cfa0ad2SJack F Vogel * duplex, then store the values in the pointers provided. 12458cfa0ad2SJack F Vogel **/ 12468cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, 12478cfa0ad2SJack F Vogel u16 *speed, u16 *duplex) 12488cfa0ad2SJack F Vogel { 12498cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 12508cfa0ad2SJack F Vogel u32 pcs; 12517609433eSJack F Vogel u32 status; 12528cfa0ad2SJack F Vogel 12538cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); 12548cfa0ad2SJack F Vogel 12558cfa0ad2SJack F Vogel /* 12568cfa0ad2SJack F Vogel * Read the PCS Status register for link state. For non-copper mode, 12578cfa0ad2SJack F Vogel * the status register is not accurate. The PCS status register is 12588cfa0ad2SJack F Vogel * used instead. 12598cfa0ad2SJack F Vogel */ 12608cfa0ad2SJack F Vogel pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT); 12618cfa0ad2SJack F Vogel 12628cfa0ad2SJack F Vogel /* 1263ab5d0362SJack F Vogel * The link up bit determines when link is up on autoneg. 12648cfa0ad2SJack F Vogel */ 1265ab5d0362SJack F Vogel if (pcs & E1000_PCS_LSTS_LINK_OK) { 12668cfa0ad2SJack F Vogel mac->serdes_has_link = TRUE; 12678cfa0ad2SJack F Vogel 12688cfa0ad2SJack F Vogel /* Detect and store PCS speed */ 12694dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_SPEED_1000) 12708cfa0ad2SJack F Vogel *speed = SPEED_1000; 12714dab5c37SJack F Vogel else if (pcs & E1000_PCS_LSTS_SPEED_100) 12728cfa0ad2SJack F Vogel *speed = SPEED_100; 12734dab5c37SJack F Vogel else 12748cfa0ad2SJack F Vogel *speed = SPEED_10; 12758cfa0ad2SJack F Vogel 12768cfa0ad2SJack F Vogel /* Detect and store PCS duplex */ 12774dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) 12788cfa0ad2SJack F Vogel *duplex = FULL_DUPLEX; 12794dab5c37SJack F Vogel else 12808cfa0ad2SJack F Vogel *duplex = HALF_DUPLEX; 12816ab6bfe3SJack F Vogel 12827609433eSJack F Vogel /* Check if it is an I354 2.5Gb backplane connection. */ 12837609433eSJack F Vogel if (mac->type == e1000_i354) { 12847609433eSJack F Vogel status = E1000_READ_REG(hw, E1000_STATUS); 12857609433eSJack F Vogel if ((status & E1000_STATUS_2P5_SKU) && 12867609433eSJack F Vogel !(status & E1000_STATUS_2P5_SKU_OVER)) { 12877609433eSJack F Vogel *speed = SPEED_2500; 12887609433eSJack F Vogel *duplex = FULL_DUPLEX; 12897609433eSJack F Vogel DEBUGOUT("2500 Mbs, "); 12907609433eSJack F Vogel DEBUGOUT("Full Duplex\n"); 12917609433eSJack F Vogel } 12927609433eSJack F Vogel } 12937609433eSJack F Vogel 1294ab5d0362SJack F Vogel } else { 1295ab5d0362SJack F Vogel mac->serdes_has_link = FALSE; 1296ab5d0362SJack F Vogel *speed = 0; 1297ab5d0362SJack F Vogel *duplex = 0; 12988cfa0ad2SJack F Vogel } 12998cfa0ad2SJack F Vogel 13008cfa0ad2SJack F Vogel return E1000_SUCCESS; 13018cfa0ad2SJack F Vogel } 13028cfa0ad2SJack F Vogel 13038cfa0ad2SJack F Vogel /** 13044edd8523SJack F Vogel * e1000_shutdown_serdes_link_82575 - Remove link during power down 13058cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13068cfa0ad2SJack F Vogel * 13074edd8523SJack F Vogel * In the case of serdes shut down sfp and PCS on driver unload 13088cfa0ad2SJack F Vogel * when management pass thru is not enabled. 13098cfa0ad2SJack F Vogel **/ 13104edd8523SJack F Vogel void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw) 13118cfa0ad2SJack F Vogel { 13128cfa0ad2SJack F Vogel u32 reg; 1313a69ed8dfSJack F Vogel 1314a69ed8dfSJack F Vogel DEBUGFUNC("e1000_shutdown_serdes_link_82575"); 13158cfa0ad2SJack F Vogel 13164edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 13174edd8523SJack F Vogel !e1000_sgmii_active_82575(hw)) 13188cfa0ad2SJack F Vogel return; 13198cfa0ad2SJack F Vogel 1320a69ed8dfSJack F Vogel if (!e1000_enable_mng_pass_thru(hw)) { 13218cfa0ad2SJack F Vogel /* Disable PCS to turn off link */ 13228cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0); 13238cfa0ad2SJack F Vogel reg &= ~E1000_PCS_CFG_PCS_EN; 13248cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); 13258cfa0ad2SJack F Vogel 13268cfa0ad2SJack F Vogel /* shutdown the laser */ 13278cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT); 13284edd8523SJack F Vogel reg |= E1000_CTRL_EXT_SDP3_DATA; 13298cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); 13308cfa0ad2SJack F Vogel 13314edd8523SJack F Vogel /* flush the write to verify completion */ 13328cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 13338cfa0ad2SJack F Vogel msec_delay(1); 13348cfa0ad2SJack F Vogel } 13358cfa0ad2SJack F Vogel 13368cfa0ad2SJack F Vogel return; 13378cfa0ad2SJack F Vogel } 13388cfa0ad2SJack F Vogel 13398cfa0ad2SJack F Vogel /** 13408cfa0ad2SJack F Vogel * e1000_reset_hw_82575 - Reset hardware 13418cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13428cfa0ad2SJack F Vogel * 1343daf9197cSJack F Vogel * This resets the hardware into a known state. 13448cfa0ad2SJack F Vogel **/ 13458cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw) 13468cfa0ad2SJack F Vogel { 1347f0ecc46dSJack F Vogel u32 ctrl; 13488cfa0ad2SJack F Vogel s32 ret_val; 13498cfa0ad2SJack F Vogel 13508cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_82575"); 13518cfa0ad2SJack F Vogel 13528cfa0ad2SJack F Vogel /* 13538cfa0ad2SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection 13548cfa0ad2SJack F Vogel * on the last TLP read/write transaction when MAC is reset. 13558cfa0ad2SJack F Vogel */ 13568cfa0ad2SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw); 13574dab5c37SJack F Vogel if (ret_val) 13588cfa0ad2SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 13598cfa0ad2SJack F Vogel 13609d81738fSJack F Vogel /* set the completion timeout for interface */ 13619d81738fSJack F Vogel ret_val = e1000_set_pcie_completion_timeout(hw); 13624dab5c37SJack F Vogel if (ret_val) 13639d81738fSJack F Vogel DEBUGOUT("PCI-E Set completion timeout has failed.\n"); 13649d81738fSJack F Vogel 13658cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 13668cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 13678cfa0ad2SJack F Vogel 13688cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 13698cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 13708cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 13718cfa0ad2SJack F Vogel 13728cfa0ad2SJack F Vogel msec_delay(10); 13738cfa0ad2SJack F Vogel 13748cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 13758cfa0ad2SJack F Vogel 13768cfa0ad2SJack F Vogel DEBUGOUT("Issuing a global reset to MAC\n"); 13778cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 13788cfa0ad2SJack F Vogel 13798cfa0ad2SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw); 13808cfa0ad2SJack F Vogel if (ret_val) { 13818cfa0ad2SJack F Vogel /* 13828cfa0ad2SJack F Vogel * When auto config read does not complete, do not 13838cfa0ad2SJack F Vogel * return with an error. This can happen in situations 13848cfa0ad2SJack F Vogel * where there is no eeprom and prevents getting link. 13858cfa0ad2SJack F Vogel */ 13868cfa0ad2SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n"); 13878cfa0ad2SJack F Vogel } 13888cfa0ad2SJack F Vogel 13898cfa0ad2SJack F Vogel /* If EEPROM is not present, run manual init scripts */ 1390ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) 13918cfa0ad2SJack F Vogel e1000_reset_init_script_82575(hw); 13928cfa0ad2SJack F Vogel 13938cfa0ad2SJack F Vogel /* Clear any pending interrupt events. */ 13948cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 1395f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR); 13968cfa0ad2SJack F Vogel 1397d035aa2dSJack F Vogel /* Install any alternate MAC address into RAR0 */ 1398d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 13998cfa0ad2SJack F Vogel 14008cfa0ad2SJack F Vogel return ret_val; 14018cfa0ad2SJack F Vogel } 14028cfa0ad2SJack F Vogel 14038cfa0ad2SJack F Vogel /** 14048cfa0ad2SJack F Vogel * e1000_init_hw_82575 - Initialize hardware 14058cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14068cfa0ad2SJack F Vogel * 14078cfa0ad2SJack F Vogel * This inits the hardware readying it for operation. 14088cfa0ad2SJack F Vogel **/ 14098cc64f1eSJack F Vogel s32 e1000_init_hw_82575(struct e1000_hw *hw) 14108cfa0ad2SJack F Vogel { 14118cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 14128cfa0ad2SJack F Vogel s32 ret_val; 14138cfa0ad2SJack F Vogel u16 i, rar_count = mac->rar_entry_count; 14148cfa0ad2SJack F Vogel 14158cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_82575"); 14168cfa0ad2SJack F Vogel 14178cfa0ad2SJack F Vogel /* Initialize identification LED */ 1418d035aa2dSJack F Vogel ret_val = mac->ops.id_led_init(hw); 14198cfa0ad2SJack F Vogel if (ret_val) { 14208cfa0ad2SJack F Vogel DEBUGOUT("Error initializing identification LED\n"); 14218cfa0ad2SJack F Vogel /* This is not fatal and we should not stop init due to this */ 14228cfa0ad2SJack F Vogel } 14238cfa0ad2SJack F Vogel 14248cfa0ad2SJack F Vogel /* Disabling VLAN filtering */ 14258cfa0ad2SJack F Vogel DEBUGOUT("Initializing the IEEE VLAN\n"); 14268cfa0ad2SJack F Vogel mac->ops.clear_vfta(hw); 14278cfa0ad2SJack F Vogel 14288cfa0ad2SJack F Vogel /* Setup the receive address */ 1429d035aa2dSJack F Vogel e1000_init_rx_addrs_generic(hw, rar_count); 1430d035aa2dSJack F Vogel 14318cfa0ad2SJack F Vogel /* Zero out the Multicast HASH table */ 14328cfa0ad2SJack F Vogel DEBUGOUT("Zeroing the MTA\n"); 14338cfa0ad2SJack F Vogel for (i = 0; i < mac->mta_reg_count; i++) 14348cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); 14358cfa0ad2SJack F Vogel 14364edd8523SJack F Vogel /* Zero out the Unicast HASH table */ 14374edd8523SJack F Vogel DEBUGOUT("Zeroing the UTA\n"); 14384edd8523SJack F Vogel for (i = 0; i < mac->uta_reg_count; i++) 14394edd8523SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); 14404edd8523SJack F Vogel 14418cfa0ad2SJack F Vogel /* Setup link and flow control */ 14428cfa0ad2SJack F Vogel ret_val = mac->ops.setup_link(hw); 14438cfa0ad2SJack F Vogel 14444dab5c37SJack F Vogel /* Set the default MTU size */ 14454dab5c37SJack F Vogel hw->dev_spec._82575.mtu = 1500; 14464dab5c37SJack F Vogel 14478cfa0ad2SJack F Vogel /* 14488cfa0ad2SJack F Vogel * Clear all of the statistics registers (clear on read). It is 14498cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link 14508cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there 14518cfa0ad2SJack F Vogel * is no link. 14528cfa0ad2SJack F Vogel */ 14538cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_82575(hw); 14548cfa0ad2SJack F Vogel 14558cfa0ad2SJack F Vogel return ret_val; 14568cfa0ad2SJack F Vogel } 14578cfa0ad2SJack F Vogel 14588cfa0ad2SJack F Vogel /** 14598cfa0ad2SJack F Vogel * e1000_setup_copper_link_82575 - Configure copper link settings 14608cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14618cfa0ad2SJack F Vogel * 14628cfa0ad2SJack F Vogel * Configures the link for auto-neg or forced speed and duplex. Then we check 14638cfa0ad2SJack F Vogel * for link, once link is established calls to configure collision distance 14648cfa0ad2SJack F Vogel * and flow control are called. 14658cfa0ad2SJack F Vogel **/ 14668cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) 14678cfa0ad2SJack F Vogel { 14689d81738fSJack F Vogel u32 ctrl; 14698cfa0ad2SJack F Vogel s32 ret_val; 14706ab6bfe3SJack F Vogel u32 phpm_reg; 14718cfa0ad2SJack F Vogel 14728cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_82575"); 14738cfa0ad2SJack F Vogel 14748cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 14758cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SLU; 14768cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 14778cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 14788cfa0ad2SJack F Vogel 14797609433eSJack F Vogel /* Clear Go Link Disconnect bit on supported devices */ 14807609433eSJack F Vogel switch (hw->mac.type) { 14817609433eSJack F Vogel case e1000_82580: 14827609433eSJack F Vogel case e1000_i350: 14837609433eSJack F Vogel case e1000_i210: 14847609433eSJack F Vogel case e1000_i211: 14856ab6bfe3SJack F Vogel phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 14866ab6bfe3SJack F Vogel phpm_reg &= ~E1000_82580_PM_GO_LINKD; 14876ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); 14887609433eSJack F Vogel break; 14897609433eSJack F Vogel default: 14907609433eSJack F Vogel break; 14916ab6bfe3SJack F Vogel } 14926ab6bfe3SJack F Vogel 14934edd8523SJack F Vogel ret_val = e1000_setup_serdes_link_82575(hw); 14944edd8523SJack F Vogel if (ret_val) 14954edd8523SJack F Vogel goto out; 14964edd8523SJack F Vogel 14974dab5c37SJack F Vogel if (e1000_sgmii_active_82575(hw)) { 14984edd8523SJack F Vogel /* allow time for SFP cage time to power up phy */ 14994edd8523SJack F Vogel msec_delay(300); 15004edd8523SJack F Vogel 15014edd8523SJack F Vogel ret_val = hw->phy.ops.reset(hw); 15024edd8523SJack F Vogel if (ret_val) { 15034edd8523SJack F Vogel DEBUGOUT("Error resetting the PHY.\n"); 15044edd8523SJack F Vogel goto out; 15054edd8523SJack F Vogel } 15064edd8523SJack F Vogel } 15078cfa0ad2SJack F Vogel switch (hw->phy.type) { 1508ab5d0362SJack F Vogel case e1000_phy_i210: 15098cfa0ad2SJack F Vogel case e1000_phy_m88: 15106ab6bfe3SJack F Vogel switch (hw->phy.id) { 15116ab6bfe3SJack F Vogel case I347AT4_E_PHY_ID: 15126ab6bfe3SJack F Vogel case M88E1112_E_PHY_ID: 15136ab6bfe3SJack F Vogel case M88E1340M_E_PHY_ID: 15147609433eSJack F Vogel case M88E1543_E_PHY_ID: 15157609433eSJack F Vogel case M88E1512_E_PHY_ID: 15166ab6bfe3SJack F Vogel case I210_I_PHY_ID: 1517f0ecc46dSJack F Vogel ret_val = e1000_copper_link_setup_m88_gen2(hw); 15186ab6bfe3SJack F Vogel break; 15196ab6bfe3SJack F Vogel default: 15208cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_m88(hw); 15218cfa0ad2SJack F Vogel break; 15226ab6bfe3SJack F Vogel } 15236ab6bfe3SJack F Vogel break; 15248cfa0ad2SJack F Vogel case e1000_phy_igp_3: 15258cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_igp(hw); 15268cfa0ad2SJack F Vogel break; 15274edd8523SJack F Vogel case e1000_phy_82580: 15284edd8523SJack F Vogel ret_val = e1000_copper_link_setup_82577(hw); 15294edd8523SJack F Vogel break; 15308cfa0ad2SJack F Vogel default: 15318cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 15328cfa0ad2SJack F Vogel break; 15338cfa0ad2SJack F Vogel } 15348cfa0ad2SJack F Vogel 15358cfa0ad2SJack F Vogel if (ret_val) 15368cfa0ad2SJack F Vogel goto out; 15378cfa0ad2SJack F Vogel 15384edd8523SJack F Vogel ret_val = e1000_setup_copper_link_generic(hw); 15398cfa0ad2SJack F Vogel out: 15408cfa0ad2SJack F Vogel return ret_val; 15418cfa0ad2SJack F Vogel } 15428cfa0ad2SJack F Vogel 15438cfa0ad2SJack F Vogel /** 15444edd8523SJack F Vogel * e1000_setup_serdes_link_82575 - Setup link for serdes 15458cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 15468cfa0ad2SJack F Vogel * 15474edd8523SJack F Vogel * Configure the physical coding sub-layer (PCS) link. The PCS link is 15484edd8523SJack F Vogel * used on copper connections where the serialized gigabit media independent 15494edd8523SJack F Vogel * interface (sgmii), or serdes fiber is being used. Configures the link 15504edd8523SJack F Vogel * for auto-negotiation or forces speed/duplex. 15518cfa0ad2SJack F Vogel **/ 15524edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) 15538cfa0ad2SJack F Vogel { 15546ab6bfe3SJack F Vogel u32 ctrl_ext, ctrl_reg, reg, anadv_reg; 15554edd8523SJack F Vogel bool pcs_autoneg; 15564dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS; 15574dab5c37SJack F Vogel u16 data; 15588cfa0ad2SJack F Vogel 15594edd8523SJack F Vogel DEBUGFUNC("e1000_setup_serdes_link_82575"); 15604edd8523SJack F Vogel 15614edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 15624edd8523SJack F Vogel !e1000_sgmii_active_82575(hw)) 15634dab5c37SJack F Vogel return ret_val; 15648cfa0ad2SJack F Vogel 15658cfa0ad2SJack F Vogel /* 15668cfa0ad2SJack F Vogel * On the 82575, SerDes loopback mode persists until it is 15678cfa0ad2SJack F Vogel * explicitly turned off or a power cycle is performed. A read to 15688cfa0ad2SJack F Vogel * the register does not indicate its status. Therefore, we ensure 15698cfa0ad2SJack F Vogel * loopback mode is disabled during initialization. 15708cfa0ad2SJack F Vogel */ 15718cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); 15728cfa0ad2SJack F Vogel 15734edd8523SJack F Vogel /* power on the sfp cage if present */ 15744edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 15754edd8523SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; 15764edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 15774edd8523SJack F Vogel 15784edd8523SJack F Vogel ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); 15794edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SLU; 15804edd8523SJack F Vogel 1581a69ed8dfSJack F Vogel /* set both sw defined pins on 82575/82576*/ 1582a69ed8dfSJack F Vogel if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) 15834edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; 15848cfa0ad2SJack F Vogel 15854edd8523SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_LCTL); 15864edd8523SJack F Vogel 15874edd8523SJack F Vogel /* default pcs_autoneg to the same setting as mac autoneg */ 15884edd8523SJack F Vogel pcs_autoneg = hw->mac.autoneg; 15894edd8523SJack F Vogel 15904edd8523SJack F Vogel switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { 15914edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII: 15924edd8523SJack F Vogel /* sgmii mode lets the phy handle forcing speed/duplex */ 15934edd8523SJack F Vogel pcs_autoneg = TRUE; 15944edd8523SJack F Vogel /* autoneg time out should be disabled for SGMII mode */ 15954edd8523SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); 15964edd8523SJack F Vogel break; 15974edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 15984edd8523SJack F Vogel /* disable PCS autoneg and support parallel detect only */ 15994edd8523SJack F Vogel pcs_autoneg = FALSE; 1600a5b0fd9cSToomas Soome /* FALLTHROUGH */ 16014edd8523SJack F Vogel default: 16024dab5c37SJack F Vogel if (hw->mac.type == e1000_82575 || 16034dab5c37SJack F Vogel hw->mac.type == e1000_82576) { 16044dab5c37SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data); 16054dab5c37SJack F Vogel if (ret_val) { 16064dab5c37SJack F Vogel DEBUGOUT("NVM Read Error\n"); 16074dab5c37SJack F Vogel return ret_val; 16084dab5c37SJack F Vogel } 16094dab5c37SJack F Vogel 16104dab5c37SJack F Vogel if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT) 16114dab5c37SJack F Vogel pcs_autoneg = FALSE; 16124dab5c37SJack F Vogel } 16134dab5c37SJack F Vogel 16144edd8523SJack F Vogel /* 16154edd8523SJack F Vogel * non-SGMII modes only supports a speed of 1000/Full for the 16164edd8523SJack F Vogel * link so it is best to just force the MAC and let the pcs 16174edd8523SJack F Vogel * link either autoneg or be forced to 1000/Full 16184edd8523SJack F Vogel */ 16194edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | 16204edd8523SJack F Vogel E1000_CTRL_FD | E1000_CTRL_FRCDPX; 16214edd8523SJack F Vogel 16224edd8523SJack F Vogel /* set speed of 1000/Full if speed/duplex is forced */ 16234edd8523SJack F Vogel reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL; 16244edd8523SJack F Vogel break; 16254edd8523SJack F Vogel } 16264edd8523SJack F Vogel 16274edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); 16288cfa0ad2SJack F Vogel 16298cfa0ad2SJack F Vogel /* 16308cfa0ad2SJack F Vogel * New SerDes mode allows for forcing speed or autonegotiating speed 16318cfa0ad2SJack F Vogel * at 1gb. Autoneg should be default set by most drivers. This is the 16328cfa0ad2SJack F Vogel * mode that will be compatible with older link partners and switches. 16338cfa0ad2SJack F Vogel * However, both are supported by the hardware and some drivers/tools. 16348cfa0ad2SJack F Vogel */ 16358cfa0ad2SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | 16368cfa0ad2SJack F Vogel E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); 16378cfa0ad2SJack F Vogel 16384edd8523SJack F Vogel if (pcs_autoneg) { 16394edd8523SJack F Vogel /* Set PCS register for autoneg */ 16404edd8523SJack F Vogel reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ 16414edd8523SJack F Vogel E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ 16426ab6bfe3SJack F Vogel 16436ab6bfe3SJack F Vogel /* Disable force flow control for autoneg */ 16446ab6bfe3SJack F Vogel reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; 16456ab6bfe3SJack F Vogel 16466ab6bfe3SJack F Vogel /* Configure flow control advertisement for autoneg */ 16476ab6bfe3SJack F Vogel anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); 16486ab6bfe3SJack F Vogel anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); 16496ab6bfe3SJack F Vogel 16506ab6bfe3SJack F Vogel switch (hw->fc.requested_mode) { 16516ab6bfe3SJack F Vogel case e1000_fc_full: 16526ab6bfe3SJack F Vogel case e1000_fc_rx_pause: 16536ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_ASM_DIR; 16546ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_PAUSE; 16556ab6bfe3SJack F Vogel break; 16566ab6bfe3SJack F Vogel case e1000_fc_tx_pause: 16576ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_ASM_DIR; 16586ab6bfe3SJack F Vogel break; 16596ab6bfe3SJack F Vogel default: 16606ab6bfe3SJack F Vogel break; 16616ab6bfe3SJack F Vogel } 16626ab6bfe3SJack F Vogel 16636ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg); 16646ab6bfe3SJack F Vogel 16654edd8523SJack F Vogel DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); 16664edd8523SJack F Vogel } else { 16674edd8523SJack F Vogel /* Set PCS register for forced link */ 1668a69ed8dfSJack F Vogel reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ 16696ab6bfe3SJack F Vogel 16706ab6bfe3SJack F Vogel /* Force flow control for forced link */ 16716ab6bfe3SJack F Vogel reg |= E1000_PCS_LCTL_FORCE_FCTRL; 16726ab6bfe3SJack F Vogel 16734edd8523SJack F Vogel DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); 16748cfa0ad2SJack F Vogel } 16758cfa0ad2SJack F Vogel 16768cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); 16778cfa0ad2SJack F Vogel 16786ab6bfe3SJack F Vogel if (!pcs_autoneg && !e1000_sgmii_active_82575(hw)) 16794edd8523SJack F Vogel e1000_force_mac_fc_generic(hw); 16804edd8523SJack F Vogel 16814dab5c37SJack F Vogel return ret_val; 16824dab5c37SJack F Vogel } 16834dab5c37SJack F Vogel 16844dab5c37SJack F Vogel /** 16854dab5c37SJack F Vogel * e1000_get_media_type_82575 - derives current media type. 16864dab5c37SJack F Vogel * @hw: pointer to the HW structure 16874dab5c37SJack F Vogel * 16884dab5c37SJack F Vogel * The media type is chosen reflecting few settings. 16894dab5c37SJack F Vogel * The following are taken into account: 16904dab5c37SJack F Vogel * - link mode set in the current port Init Control Word #3 16914dab5c37SJack F Vogel * - current link mode settings in CSR register 16924dab5c37SJack F Vogel * - MDIO vs. I2C PHY control interface chosen 16934dab5c37SJack F Vogel * - SFP module media type 16944dab5c37SJack F Vogel **/ 16954dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw) 16964dab5c37SJack F Vogel { 16974dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 16986ab6bfe3SJack F Vogel s32 ret_val = E1000_SUCCESS; 16994dab5c37SJack F Vogel u32 ctrl_ext = 0; 17006ab6bfe3SJack F Vogel u32 link_mode = 0; 17014dab5c37SJack F Vogel 17024dab5c37SJack F Vogel /* Set internal phy as default */ 17034dab5c37SJack F Vogel dev_spec->sgmii_active = FALSE; 17044dab5c37SJack F Vogel dev_spec->module_plugged = FALSE; 17054dab5c37SJack F Vogel 17064dab5c37SJack F Vogel /* Get CSR setting */ 17074dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 17084dab5c37SJack F Vogel 17096ab6bfe3SJack F Vogel /* extract link mode setting */ 17106ab6bfe3SJack F Vogel link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; 17114dab5c37SJack F Vogel 17126ab6bfe3SJack F Vogel switch (link_mode) { 17134dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 17144dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 17154dab5c37SJack F Vogel break; 17164dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_GMII: 17174dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 17184dab5c37SJack F Vogel break; 17194dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII: 17204dab5c37SJack F Vogel /* Get phy control interface type set (MDIO vs. I2C)*/ 17214dab5c37SJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) { 17224dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 17234dab5c37SJack F Vogel dev_spec->sgmii_active = TRUE; 17244dab5c37SJack F Vogel break; 17254dab5c37SJack F Vogel } 17266ab6bfe3SJack F Vogel /* fall through for I2C based SGMII */ 1727a5b0fd9cSToomas Soome /* FALLTHROUGH */ 17286ab6bfe3SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: 17296ab6bfe3SJack F Vogel /* read media type from SFP EEPROM */ 17306ab6bfe3SJack F Vogel ret_val = e1000_set_sfp_media_type_82575(hw); 17316ab6bfe3SJack F Vogel if ((ret_val != E1000_SUCCESS) || 17326ab6bfe3SJack F Vogel (hw->phy.media_type == e1000_media_type_unknown)) { 17334dab5c37SJack F Vogel /* 17346ab6bfe3SJack F Vogel * If media type was not identified then return media 17356ab6bfe3SJack F Vogel * type defined by the CTRL_EXT settings. 17364dab5c37SJack F Vogel */ 17376ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 17386ab6bfe3SJack F Vogel 17396ab6bfe3SJack F Vogel if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { 17406ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 17416ab6bfe3SJack F Vogel dev_spec->sgmii_active = TRUE; 17424dab5c37SJack F Vogel } 17434dab5c37SJack F Vogel 17446ab6bfe3SJack F Vogel break; 17456ab6bfe3SJack F Vogel } 17466ab6bfe3SJack F Vogel 17476ab6bfe3SJack F Vogel /* do not change link mode for 100BaseFX */ 17486ab6bfe3SJack F Vogel if (dev_spec->eth_flags.e100_base_fx) 17496ab6bfe3SJack F Vogel break; 17506ab6bfe3SJack F Vogel 17516ab6bfe3SJack F Vogel /* change current link mode setting */ 17526ab6bfe3SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; 17536ab6bfe3SJack F Vogel 17546ab6bfe3SJack F Vogel if (hw->phy.media_type == e1000_media_type_copper) 17556ab6bfe3SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; 17564dab5c37SJack F Vogel else 17576ab6bfe3SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 17586ab6bfe3SJack F Vogel 17596ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 17606ab6bfe3SJack F Vogel 17616ab6bfe3SJack F Vogel break; 17624dab5c37SJack F Vogel } 17634dab5c37SJack F Vogel 17644dab5c37SJack F Vogel return ret_val; 17654dab5c37SJack F Vogel } 17664dab5c37SJack F Vogel 17674dab5c37SJack F Vogel /** 17684dab5c37SJack F Vogel * e1000_set_sfp_media_type_82575 - derives SFP module media type. 17694dab5c37SJack F Vogel * @hw: pointer to the HW structure 17704dab5c37SJack F Vogel * 17714dab5c37SJack F Vogel * The media type is chosen based on SFP module. 17724dab5c37SJack F Vogel * compatibility flags retrieved from SFP ID EEPROM. 17734dab5c37SJack F Vogel **/ 17744dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) 17754dab5c37SJack F Vogel { 17764dab5c37SJack F Vogel s32 ret_val = E1000_ERR_CONFIG; 17774dab5c37SJack F Vogel u32 ctrl_ext = 0; 17784dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 17796ab6bfe3SJack F Vogel struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags; 17804dab5c37SJack F Vogel u8 tranceiver_type = 0; 17816ab6bfe3SJack F Vogel s32 timeout = 3; 17824dab5c37SJack F Vogel 17836ab6bfe3SJack F Vogel /* Turn I2C interface ON and power on sfp cage */ 17844dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 17856ab6bfe3SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; 17864dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); 17874dab5c37SJack F Vogel 17886ab6bfe3SJack F Vogel E1000_WRITE_FLUSH(hw); 17896ab6bfe3SJack F Vogel 17904dab5c37SJack F Vogel /* Read SFP module data */ 17916ab6bfe3SJack F Vogel while (timeout) { 17924dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw, 17934dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), 17944dab5c37SJack F Vogel &tranceiver_type); 17956ab6bfe3SJack F Vogel if (ret_val == E1000_SUCCESS) 17966ab6bfe3SJack F Vogel break; 17976ab6bfe3SJack F Vogel msec_delay(100); 17986ab6bfe3SJack F Vogel timeout--; 17996ab6bfe3SJack F Vogel } 18004dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS) 18014dab5c37SJack F Vogel goto out; 18026ab6bfe3SJack F Vogel 18034dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw, 18044dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), 18056ab6bfe3SJack F Vogel (u8 *)eth_flags); 18064dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS) 18074dab5c37SJack F Vogel goto out; 18086ab6bfe3SJack F Vogel 18096ab6bfe3SJack F Vogel /* Check if there is some SFP module plugged and powered */ 18104dab5c37SJack F Vogel if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || 18114dab5c37SJack F Vogel (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { 18124dab5c37SJack F Vogel dev_spec->module_plugged = TRUE; 18136ab6bfe3SJack F Vogel if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { 18144dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 18156ab6bfe3SJack F Vogel } else if (eth_flags->e100_base_fx) { 18166ab6bfe3SJack F Vogel dev_spec->sgmii_active = TRUE; 18176ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 18186ab6bfe3SJack F Vogel } else if (eth_flags->e1000_base_t) { 18194dab5c37SJack F Vogel dev_spec->sgmii_active = TRUE; 18204dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 18214dab5c37SJack F Vogel } else { 18224dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_unknown; 18234dab5c37SJack F Vogel DEBUGOUT("PHY module has not been recognized\n"); 18244dab5c37SJack F Vogel goto out; 18254dab5c37SJack F Vogel } 18264dab5c37SJack F Vogel } else { 18274dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_unknown; 18284dab5c37SJack F Vogel } 18294dab5c37SJack F Vogel ret_val = E1000_SUCCESS; 18304dab5c37SJack F Vogel out: 18314dab5c37SJack F Vogel /* Restore I2C interface setting */ 18324dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 18334dab5c37SJack F Vogel return ret_val; 18348cfa0ad2SJack F Vogel } 18358cfa0ad2SJack F Vogel 18368cfa0ad2SJack F Vogel /** 18378cfa0ad2SJack F Vogel * e1000_valid_led_default_82575 - Verify a valid default LED config 18388cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18398cfa0ad2SJack F Vogel * @data: pointer to the NVM (EEPROM) 18408cfa0ad2SJack F Vogel * 18418cfa0ad2SJack F Vogel * Read the EEPROM for the current default LED configuration. If the 18428cfa0ad2SJack F Vogel * LED configuration is not valid, set to a valid LED configuration. 18438cfa0ad2SJack F Vogel **/ 18448cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data) 18458cfa0ad2SJack F Vogel { 18468cfa0ad2SJack F Vogel s32 ret_val; 18478cfa0ad2SJack F Vogel 18488cfa0ad2SJack F Vogel DEBUGFUNC("e1000_valid_led_default_82575"); 18498cfa0ad2SJack F Vogel 18508cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 18518cfa0ad2SJack F Vogel if (ret_val) { 18528cfa0ad2SJack F Vogel DEBUGOUT("NVM Read Error\n"); 18538cfa0ad2SJack F Vogel goto out; 18548cfa0ad2SJack F Vogel } 18558cfa0ad2SJack F Vogel 18568cfa0ad2SJack F Vogel if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 18578cfa0ad2SJack F Vogel switch (hw->phy.media_type) { 18588cfa0ad2SJack F Vogel case e1000_media_type_internal_serdes: 18598cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT_82575_SERDES; 18608cfa0ad2SJack F Vogel break; 18618cfa0ad2SJack F Vogel case e1000_media_type_copper: 18628cfa0ad2SJack F Vogel default: 18638cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT; 18648cfa0ad2SJack F Vogel break; 18658cfa0ad2SJack F Vogel } 18668cfa0ad2SJack F Vogel } 18678cfa0ad2SJack F Vogel out: 18688cfa0ad2SJack F Vogel return ret_val; 18698cfa0ad2SJack F Vogel } 18708cfa0ad2SJack F Vogel 18718cfa0ad2SJack F Vogel /** 18728cfa0ad2SJack F Vogel * e1000_sgmii_active_82575 - Return sgmii state 18738cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18748cfa0ad2SJack F Vogel * 18758cfa0ad2SJack F Vogel * 82575 silicon has a serialized gigabit media independent interface (sgmii) 18768cfa0ad2SJack F Vogel * which can be enabled for use in the embedded applications. Simply 18778cfa0ad2SJack F Vogel * return the current state of the sgmii interface. 18788cfa0ad2SJack F Vogel **/ 18798cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw) 18808cfa0ad2SJack F Vogel { 1881daf9197cSJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 1882daf9197cSJack F Vogel return dev_spec->sgmii_active; 18838cfa0ad2SJack F Vogel } 18848cfa0ad2SJack F Vogel 18858cfa0ad2SJack F Vogel /** 18868cfa0ad2SJack F Vogel * e1000_reset_init_script_82575 - Inits HW defaults after reset 18878cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18888cfa0ad2SJack F Vogel * 18898cfa0ad2SJack F Vogel * Inits recommended HW defaults after a reset when there is no EEPROM 18908cfa0ad2SJack F Vogel * detected. This is only for the 82575. 18918cfa0ad2SJack F Vogel **/ 18928cfa0ad2SJack F Vogel static s32 e1000_reset_init_script_82575(struct e1000_hw *hw) 18938cfa0ad2SJack F Vogel { 18948cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_init_script_82575"); 18958cfa0ad2SJack F Vogel 18968cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82575) { 18978cfa0ad2SJack F Vogel DEBUGOUT("Running reset init script for 82575\n"); 18988cfa0ad2SJack F Vogel /* SerDes configuration via SERDESCTRL */ 18998cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C); 19008cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78); 19018cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23); 19028cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15); 19038cfa0ad2SJack F Vogel 19048cfa0ad2SJack F Vogel /* CCM configuration via CCMCTL register */ 19058cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00); 19068cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00); 19078cfa0ad2SJack F Vogel 19088cfa0ad2SJack F Vogel /* PCIe lanes configuration */ 19098cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC); 19108cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF); 19118cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05); 19128cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81); 19138cfa0ad2SJack F Vogel 19148cfa0ad2SJack F Vogel /* PCIe PLL Configuration */ 19158cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47); 19168cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00); 19178cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00); 19188cfa0ad2SJack F Vogel } 19198cfa0ad2SJack F Vogel 19208cfa0ad2SJack F Vogel return E1000_SUCCESS; 19218cfa0ad2SJack F Vogel } 19228cfa0ad2SJack F Vogel 19238cfa0ad2SJack F Vogel /** 19248cfa0ad2SJack F Vogel * e1000_read_mac_addr_82575 - Read device MAC address 19258cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19268cfa0ad2SJack F Vogel **/ 19278cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw) 19288cfa0ad2SJack F Vogel { 19298cc64f1eSJack F Vogel s32 ret_val; 19308cfa0ad2SJack F Vogel 19318cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_mac_addr_82575"); 1932d035aa2dSJack F Vogel 1933d035aa2dSJack F Vogel /* 1934d035aa2dSJack F Vogel * If there's an alternate MAC address place it in RAR0 1935d035aa2dSJack F Vogel * so that it will override the Si installed default perm 1936d035aa2dSJack F Vogel * address. 1937d035aa2dSJack F Vogel */ 1938d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 1939d035aa2dSJack F Vogel if (ret_val) 1940d035aa2dSJack F Vogel goto out; 1941d035aa2dSJack F Vogel 19428cfa0ad2SJack F Vogel ret_val = e1000_read_mac_addr_generic(hw); 19438cfa0ad2SJack F Vogel 1944d035aa2dSJack F Vogel out: 19458cfa0ad2SJack F Vogel return ret_val; 19468cfa0ad2SJack F Vogel } 19478cfa0ad2SJack F Vogel 19488cfa0ad2SJack F Vogel /** 1949a69ed8dfSJack F Vogel * e1000_config_collision_dist_82575 - Configure collision distance 1950a69ed8dfSJack F Vogel * @hw: pointer to the HW structure 1951a69ed8dfSJack F Vogel * 1952a69ed8dfSJack F Vogel * Configures the collision distance to the default value and is used 1953a69ed8dfSJack F Vogel * during link setup. 1954a69ed8dfSJack F Vogel **/ 1955a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw) 1956a69ed8dfSJack F Vogel { 1957a69ed8dfSJack F Vogel u32 tctl_ext; 1958a69ed8dfSJack F Vogel 1959a69ed8dfSJack F Vogel DEBUGFUNC("e1000_config_collision_dist_82575"); 1960a69ed8dfSJack F Vogel 1961a69ed8dfSJack F Vogel tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT); 1962a69ed8dfSJack F Vogel 1963a69ed8dfSJack F Vogel tctl_ext &= ~E1000_TCTL_EXT_COLD; 1964a69ed8dfSJack F Vogel tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT; 1965a69ed8dfSJack F Vogel 1966a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext); 1967a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw); 1968a69ed8dfSJack F Vogel } 1969a69ed8dfSJack F Vogel 1970a69ed8dfSJack F Vogel /** 19718cfa0ad2SJack F Vogel * e1000_power_down_phy_copper_82575 - Remove link during PHY power down 19728cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19738cfa0ad2SJack F Vogel * 19748cfa0ad2SJack F Vogel * In the case of a PHY power down to save power, or to turn off link during a 19758cfa0ad2SJack F Vogel * driver unload, or wake on lan is not enabled, remove the link. 19768cfa0ad2SJack F Vogel **/ 19778cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) 19788cfa0ad2SJack F Vogel { 19798cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 19808cfa0ad2SJack F Vogel 19818cfa0ad2SJack F Vogel if (!(phy->ops.check_reset_block)) 19828cfa0ad2SJack F Vogel return; 19838cfa0ad2SJack F Vogel 19848cfa0ad2SJack F Vogel /* If the management interface is not enabled, then power down */ 19858ec87fc5SJack F Vogel if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw))) 19868cfa0ad2SJack F Vogel e1000_power_down_phy_copper(hw); 19878cfa0ad2SJack F Vogel 19888cfa0ad2SJack F Vogel return; 19898cfa0ad2SJack F Vogel } 19908cfa0ad2SJack F Vogel 19918cfa0ad2SJack F Vogel /** 19928cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters 19938cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19948cfa0ad2SJack F Vogel * 19958cfa0ad2SJack F Vogel * Clears the hardware counters by reading the counter registers. 19968cfa0ad2SJack F Vogel **/ 19978cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) 19988cfa0ad2SJack F Vogel { 19998cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_82575"); 20008cfa0ad2SJack F Vogel 20018cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw); 20028cfa0ad2SJack F Vogel 2003daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC64); 2004daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC127); 2005daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC255); 2006daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC511); 2007daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1023); 2008daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1522); 2009daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC64); 2010daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC127); 2011daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC255); 2012daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC511); 2013daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1023); 2014daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1522); 20158cfa0ad2SJack F Vogel 2016daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ALGNERRC); 2017daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RXERRC); 2018daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TNCRS); 2019daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CEXTERR); 2020daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTC); 2021daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTFC); 20228cfa0ad2SJack F Vogel 2023daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPRC); 2024daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPDC); 2025daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPTC); 20268cfa0ad2SJack F Vogel 2027daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_IAC); 2028daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXOC); 20298cfa0ad2SJack F Vogel 2030daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXPTC); 2031daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXATC); 2032daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXPTC); 2033daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXATC); 2034daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQEC); 2035daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQMTC); 2036daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXDMTC); 20378cfa0ad2SJack F Vogel 2038daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBTMPC); 2039daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTDPMC); 2040daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBRMPC); 2041daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RPTHC); 2042daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGPTC); 2043daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTCBDPC); 2044daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCL); 2045daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCH); 2046daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCL); 2047daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCH); 2048daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_LENERRS); 20498cfa0ad2SJack F Vogel 20508cfa0ad2SJack F Vogel /* This register should not be read in copper configurations */ 20514edd8523SJack F Vogel if ((hw->phy.media_type == e1000_media_type_internal_serdes) || 20524edd8523SJack F Vogel e1000_sgmii_active_82575(hw)) 2053daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_SCVPC); 20548cfa0ad2SJack F Vogel } 20559d81738fSJack F Vogel 20568cfa0ad2SJack F Vogel /** 2057f0ecc46dSJack F Vogel * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable 20588cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 20598cfa0ad2SJack F Vogel * 206048600901SSean Bruno * After Rx enable, if manageability is enabled then there is likely some 20618cfa0ad2SJack F Vogel * bad data at the start of the fifo and possibly in the DMA fifo. This 20628cfa0ad2SJack F Vogel * function clears the fifos and flushes any packets that came in as rx was 20638cfa0ad2SJack F Vogel * being enabled. 20648cfa0ad2SJack F Vogel **/ 20658cfa0ad2SJack F Vogel void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) 20668cfa0ad2SJack F Vogel { 20678cfa0ad2SJack F Vogel u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; 20688cfa0ad2SJack F Vogel int i, ms_wait; 20698cfa0ad2SJack F Vogel 2070c80429ceSEric Joyner DEBUGFUNC("e1000_rx_fifo_flush_82575"); 2071c80429ceSEric Joyner 2072c80429ceSEric Joyner /* disable IPv6 options as per hardware errata */ 2073c80429ceSEric Joyner rfctl = E1000_READ_REG(hw, E1000_RFCTL); 2074c80429ceSEric Joyner rfctl |= E1000_RFCTL_IPV6_EX_DIS; 2075c80429ceSEric Joyner E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); 2076c80429ceSEric Joyner 20778cfa0ad2SJack F Vogel if (hw->mac.type != e1000_82575 || 20788cfa0ad2SJack F Vogel !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) 20798cfa0ad2SJack F Vogel return; 20808cfa0ad2SJack F Vogel 2081f0ecc46dSJack F Vogel /* Disable all Rx queues */ 20828cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) { 20838cfa0ad2SJack F Vogel rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); 20848cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RXDCTL(i), 20858cfa0ad2SJack F Vogel rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); 20868cfa0ad2SJack F Vogel } 20878cfa0ad2SJack F Vogel /* Poll all queues to verify they have shut down */ 20888cfa0ad2SJack F Vogel for (ms_wait = 0; ms_wait < 10; ms_wait++) { 20898cfa0ad2SJack F Vogel msec_delay(1); 20908cfa0ad2SJack F Vogel rx_enabled = 0; 20918cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) 20928cfa0ad2SJack F Vogel rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i)); 20938cfa0ad2SJack F Vogel if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) 20948cfa0ad2SJack F Vogel break; 20958cfa0ad2SJack F Vogel } 20968cfa0ad2SJack F Vogel 20978cfa0ad2SJack F Vogel if (ms_wait == 10) 20988cfa0ad2SJack F Vogel DEBUGOUT("Queue disable timed out after 10ms\n"); 20998cfa0ad2SJack F Vogel 21008cfa0ad2SJack F Vogel /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all 21018cfa0ad2SJack F Vogel * incoming packets are rejected. Set enable and wait 2ms so that 21028cfa0ad2SJack F Vogel * any packet that was coming in as RCTL.EN was set is flushed 21038cfa0ad2SJack F Vogel */ 21048cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); 21058cfa0ad2SJack F Vogel 21068cfa0ad2SJack F Vogel rlpml = E1000_READ_REG(hw, E1000_RLPML); 21078cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RLPML, 0); 21088cfa0ad2SJack F Vogel 21098cfa0ad2SJack F Vogel rctl = E1000_READ_REG(hw, E1000_RCTL); 21108cfa0ad2SJack F Vogel temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); 21118cfa0ad2SJack F Vogel temp_rctl |= E1000_RCTL_LPE; 21128cfa0ad2SJack F Vogel 21138cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl); 21148cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN); 21158cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 21168cfa0ad2SJack F Vogel msec_delay(2); 21178cfa0ad2SJack F Vogel 2118f0ecc46dSJack F Vogel /* Enable Rx queues that were previously enabled and restore our 21198cfa0ad2SJack F Vogel * previous state 21208cfa0ad2SJack F Vogel */ 21218cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) 21228cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]); 21238cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, rctl); 21248cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 21258cfa0ad2SJack F Vogel 21268cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RLPML, rlpml); 21278cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); 21288cfa0ad2SJack F Vogel 21298cfa0ad2SJack F Vogel /* Flush receive errors generated by workaround */ 21308cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_ROC); 21318cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_RNBC); 21328cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_MPC); 21338cfa0ad2SJack F Vogel } 2134daf9197cSJack F Vogel 21359d81738fSJack F Vogel /** 21369d81738fSJack F Vogel * e1000_set_pcie_completion_timeout - set pci-e completion timeout 21379d81738fSJack F Vogel * @hw: pointer to the HW structure 21389d81738fSJack F Vogel * 21399d81738fSJack F Vogel * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, 21409d81738fSJack F Vogel * however the hardware default for these parts is 500us to 1ms which is less 21419d81738fSJack F Vogel * than the 10ms recommended by the pci-e spec. To address this we need to 21429d81738fSJack F Vogel * increase the value to either 10ms to 200ms for capability version 1 config, 21439d81738fSJack F Vogel * or 16ms to 55ms for version 2. 21449d81738fSJack F Vogel **/ 21459d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw) 21469d81738fSJack F Vogel { 21479d81738fSJack F Vogel u32 gcr = E1000_READ_REG(hw, E1000_GCR); 21489d81738fSJack F Vogel s32 ret_val = E1000_SUCCESS; 21499d81738fSJack F Vogel u16 pcie_devctl2; 21509d81738fSJack F Vogel 21519d81738fSJack F Vogel /* only take action if timeout value is defaulted to 0 */ 21529d81738fSJack F Vogel if (gcr & E1000_GCR_CMPL_TMOUT_MASK) 21539d81738fSJack F Vogel goto out; 21549d81738fSJack F Vogel 21559d81738fSJack F Vogel /* 21569d81738fSJack F Vogel * if capababilities version is type 1 we can write the 21579d81738fSJack F Vogel * timeout of 10ms to 200ms through the GCR register 21589d81738fSJack F Vogel */ 21599d81738fSJack F Vogel if (!(gcr & E1000_GCR_CAP_VER2)) { 21609d81738fSJack F Vogel gcr |= E1000_GCR_CMPL_TMOUT_10ms; 21619d81738fSJack F Vogel goto out; 21629d81738fSJack F Vogel } 21639d81738fSJack F Vogel 21649d81738fSJack F Vogel /* 21659d81738fSJack F Vogel * for version 2 capabilities we need to write the config space 21669d81738fSJack F Vogel * directly in order to set the completion timeout value for 21679d81738fSJack F Vogel * 16ms to 55ms 21689d81738fSJack F Vogel */ 21699d81738fSJack F Vogel ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 21709d81738fSJack F Vogel &pcie_devctl2); 21719d81738fSJack F Vogel if (ret_val) 21729d81738fSJack F Vogel goto out; 21739d81738fSJack F Vogel 21749d81738fSJack F Vogel pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; 21759d81738fSJack F Vogel 21769d81738fSJack F Vogel ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 21779d81738fSJack F Vogel &pcie_devctl2); 21789d81738fSJack F Vogel out: 21799d81738fSJack F Vogel /* disable completion timeout resend */ 21809d81738fSJack F Vogel gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; 21819d81738fSJack F Vogel 21829d81738fSJack F Vogel E1000_WRITE_REG(hw, E1000_GCR, gcr); 21839d81738fSJack F Vogel return ret_val; 21849d81738fSJack F Vogel } 21859d81738fSJack F Vogel 21867d9119bdSJack F Vogel /** 21877d9119bdSJack F Vogel * e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing 21887d9119bdSJack F Vogel * @hw: pointer to the hardware struct 21897d9119bdSJack F Vogel * @enable: state to enter, either enabled or disabled 21907d9119bdSJack F Vogel * @pf: Physical Function pool - do not set anti-spoofing for the PF 21917d9119bdSJack F Vogel * 21927d9119bdSJack F Vogel * enables/disables L2 switch anti-spoofing functionality. 21937d9119bdSJack F Vogel **/ 21947d9119bdSJack F Vogel void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) 21957d9119bdSJack F Vogel { 21967609433eSJack F Vogel u32 reg_val, reg_offset; 21977d9119bdSJack F Vogel 21987d9119bdSJack F Vogel switch (hw->mac.type) { 21997d9119bdSJack F Vogel case e1000_82576: 22007609433eSJack F Vogel reg_offset = E1000_DTXSWC; 22017d9119bdSJack F Vogel break; 22024dab5c37SJack F Vogel case e1000_i350: 22037609433eSJack F Vogel case e1000_i354: 22047609433eSJack F Vogel reg_offset = E1000_TXSWC; 22057609433eSJack F Vogel break; 22067609433eSJack F Vogel default: 22077609433eSJack F Vogel return; 22087609433eSJack F Vogel } 22097609433eSJack F Vogel 22107609433eSJack F Vogel reg_val = E1000_READ_REG(hw, reg_offset); 22114dab5c37SJack F Vogel if (enable) { 22127609433eSJack F Vogel reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | 22134dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 22144dab5c37SJack F Vogel /* The PF can spoof - it has to in order to 22154dab5c37SJack F Vogel * support emulation mode NICs 22164dab5c37SJack F Vogel */ 22177609433eSJack F Vogel reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); 22184dab5c37SJack F Vogel } else { 22197609433eSJack F Vogel reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | 22204dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 22214dab5c37SJack F Vogel } 22227609433eSJack F Vogel E1000_WRITE_REG(hw, reg_offset, reg_val); 22237d9119bdSJack F Vogel } 22247d9119bdSJack F Vogel 22254edd8523SJack F Vogel /** 22264edd8523SJack F Vogel * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback 22274edd8523SJack F Vogel * @hw: pointer to the hardware struct 22284edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled 22294edd8523SJack F Vogel * 22304edd8523SJack F Vogel * enables/disables L2 switch loopback functionality. 22314edd8523SJack F Vogel **/ 22324edd8523SJack F Vogel void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) 22334edd8523SJack F Vogel { 22348ec87fc5SJack F Vogel u32 dtxswc; 22354edd8523SJack F Vogel 22368ec87fc5SJack F Vogel switch (hw->mac.type) { 22378ec87fc5SJack F Vogel case e1000_82576: 22388ec87fc5SJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); 22394edd8523SJack F Vogel if (enable) 22404edd8523SJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 22414edd8523SJack F Vogel else 22424edd8523SJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 22434edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); 22448ec87fc5SJack F Vogel break; 2245f0ecc46dSJack F Vogel case e1000_i350: 22467609433eSJack F Vogel case e1000_i354: 2247f0ecc46dSJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_TXSWC); 2248f0ecc46dSJack F Vogel if (enable) 2249f0ecc46dSJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 2250f0ecc46dSJack F Vogel else 2251f0ecc46dSJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 2252f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc); 2253f0ecc46dSJack F Vogel break; 22548ec87fc5SJack F Vogel default: 22558ec87fc5SJack F Vogel /* Currently no other hardware supports loopback */ 22568ec87fc5SJack F Vogel break; 22578ec87fc5SJack F Vogel } 22588ec87fc5SJack F Vogel 22598ec87fc5SJack F Vogel 22604edd8523SJack F Vogel } 22614edd8523SJack F Vogel 22624edd8523SJack F Vogel /** 22634edd8523SJack F Vogel * e1000_vmdq_set_replication_pf - enable or disable vmdq replication 22644edd8523SJack F Vogel * @hw: pointer to the hardware struct 22654edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled 22664edd8523SJack F Vogel * 22674edd8523SJack F Vogel * enables/disables replication of packets across multiple pools. 22684edd8523SJack F Vogel **/ 22694edd8523SJack F Vogel void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) 22704edd8523SJack F Vogel { 22714edd8523SJack F Vogel u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); 22724edd8523SJack F Vogel 22734edd8523SJack F Vogel if (enable) 22744edd8523SJack F Vogel vt_ctl |= E1000_VT_CTL_VM_REPL_EN; 22754edd8523SJack F Vogel else 22764edd8523SJack F Vogel vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; 22774edd8523SJack F Vogel 22784edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); 22794edd8523SJack F Vogel } 22804edd8523SJack F Vogel 22814edd8523SJack F Vogel /** 22824edd8523SJack F Vogel * e1000_read_phy_reg_82580 - Read 82580 MDI control register 22834edd8523SJack F Vogel * @hw: pointer to the HW structure 22844edd8523SJack F Vogel * @offset: register offset to be read 22854edd8523SJack F Vogel * @data: pointer to the read data 22864edd8523SJack F Vogel * 22874edd8523SJack F Vogel * Reads the MDI control register in the PHY at offset and stores the 22884edd8523SJack F Vogel * information read to data. 22894edd8523SJack F Vogel **/ 22904edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) 22914edd8523SJack F Vogel { 22924edd8523SJack F Vogel s32 ret_val; 22934edd8523SJack F Vogel 22944edd8523SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_82580"); 22954edd8523SJack F Vogel 22964edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 22974edd8523SJack F Vogel if (ret_val) 22984edd8523SJack F Vogel goto out; 22994edd8523SJack F Vogel 23004edd8523SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw, offset, data); 23014edd8523SJack F Vogel 23024edd8523SJack F Vogel hw->phy.ops.release(hw); 23034edd8523SJack F Vogel 23044edd8523SJack F Vogel out: 23054edd8523SJack F Vogel return ret_val; 23064edd8523SJack F Vogel } 23074edd8523SJack F Vogel 23084edd8523SJack F Vogel /** 23094edd8523SJack F Vogel * e1000_write_phy_reg_82580 - Write 82580 MDI control register 23104edd8523SJack F Vogel * @hw: pointer to the HW structure 23114edd8523SJack F Vogel * @offset: register offset to write to 23124edd8523SJack F Vogel * @data: data to write to register at offset 23134edd8523SJack F Vogel * 23144edd8523SJack F Vogel * Writes data to MDI control register in the PHY at offset. 23154edd8523SJack F Vogel **/ 23164edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data) 23174edd8523SJack F Vogel { 23184edd8523SJack F Vogel s32 ret_val; 23194edd8523SJack F Vogel 23204edd8523SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_82580"); 23214edd8523SJack F Vogel 23224edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 23234edd8523SJack F Vogel if (ret_val) 23244edd8523SJack F Vogel goto out; 23254edd8523SJack F Vogel 23264edd8523SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw, offset, data); 23274edd8523SJack F Vogel 23284edd8523SJack F Vogel hw->phy.ops.release(hw); 23294edd8523SJack F Vogel 23304edd8523SJack F Vogel out: 23314edd8523SJack F Vogel return ret_val; 23324edd8523SJack F Vogel } 2333a69ed8dfSJack F Vogel 23344edd8523SJack F Vogel /** 23357d9119bdSJack F Vogel * e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits 23367d9119bdSJack F Vogel * @hw: pointer to the HW structure 23377d9119bdSJack F Vogel * 2338cef367e6SEitan Adler * This resets the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on 23397d9119bdSJack F Vogel * the values found in the EEPROM. This addresses an issue in which these 23407d9119bdSJack F Vogel * bits are not restored from EEPROM after reset. 23417d9119bdSJack F Vogel **/ 23427d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw) 23437d9119bdSJack F Vogel { 23447d9119bdSJack F Vogel s32 ret_val = E1000_SUCCESS; 23457d9119bdSJack F Vogel u32 mdicnfg; 2346f0ecc46dSJack F Vogel u16 nvm_data = 0; 23477d9119bdSJack F Vogel 23487d9119bdSJack F Vogel DEBUGFUNC("e1000_reset_mdicnfg_82580"); 23497d9119bdSJack F Vogel 23507d9119bdSJack F Vogel if (hw->mac.type != e1000_82580) 23517d9119bdSJack F Vogel goto out; 23527d9119bdSJack F Vogel if (!e1000_sgmii_active_82575(hw)) 23537d9119bdSJack F Vogel goto out; 23547d9119bdSJack F Vogel 23557d9119bdSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + 23567d9119bdSJack F Vogel NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, 23577d9119bdSJack F Vogel &nvm_data); 23587d9119bdSJack F Vogel if (ret_val) { 23597d9119bdSJack F Vogel DEBUGOUT("NVM Read Error\n"); 23607d9119bdSJack F Vogel goto out; 23617d9119bdSJack F Vogel } 23627d9119bdSJack F Vogel 23637d9119bdSJack F Vogel mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); 23647d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_EXT_MDIO) 23657d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_EXT_MDIO; 23667d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_COM_MDIO) 23677d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_COM_MDIO; 23687d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); 23697d9119bdSJack F Vogel out: 23707d9119bdSJack F Vogel return ret_val; 23717d9119bdSJack F Vogel } 23727d9119bdSJack F Vogel 23737d9119bdSJack F Vogel /** 23744edd8523SJack F Vogel * e1000_reset_hw_82580 - Reset hardware 23754edd8523SJack F Vogel * @hw: pointer to the HW structure 23764edd8523SJack F Vogel * 23774edd8523SJack F Vogel * This resets function or entire device (all ports, etc.) 23784edd8523SJack F Vogel * to a known state. 23794edd8523SJack F Vogel **/ 23804edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw) 23814edd8523SJack F Vogel { 23824edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS; 23834edd8523SJack F Vogel /* BH SW mailbox bit in SW_FW_SYNC */ 23844edd8523SJack F Vogel u16 swmbsw_mask = E1000_SW_SYNCH_MB; 2385f0ecc46dSJack F Vogel u32 ctrl; 23864edd8523SJack F Vogel bool global_device_reset = hw->dev_spec._82575.global_device_reset; 23874edd8523SJack F Vogel 23884edd8523SJack F Vogel DEBUGFUNC("e1000_reset_hw_82580"); 23894edd8523SJack F Vogel 23904edd8523SJack F Vogel hw->dev_spec._82575.global_device_reset = FALSE; 23914edd8523SJack F Vogel 23926ab6bfe3SJack F Vogel /* 82580 does not reliably do global_device_reset due to hw errata */ 23936ab6bfe3SJack F Vogel if (hw->mac.type == e1000_82580) 23946ab6bfe3SJack F Vogel global_device_reset = FALSE; 23956ab6bfe3SJack F Vogel 23964edd8523SJack F Vogel /* Get current control state. */ 23974edd8523SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 23984edd8523SJack F Vogel 23994edd8523SJack F Vogel /* 24004edd8523SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection 24014edd8523SJack F Vogel * on the last TLP read/write transaction when MAC is reset. 24024edd8523SJack F Vogel */ 24034edd8523SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw); 24044edd8523SJack F Vogel if (ret_val) 24054edd8523SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 24064edd8523SJack F Vogel 24074edd8523SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 24084edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 24094edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 24104edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 24114edd8523SJack F Vogel E1000_WRITE_FLUSH(hw); 24124edd8523SJack F Vogel 24134edd8523SJack F Vogel msec_delay(10); 24144edd8523SJack F Vogel 24154edd8523SJack F Vogel /* Determine whether or not a global dev reset is requested */ 2416ab5d0362SJack F Vogel if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw, 24174dab5c37SJack F Vogel swmbsw_mask)) 24184edd8523SJack F Vogel global_device_reset = FALSE; 24194edd8523SJack F Vogel 24204dab5c37SJack F Vogel if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) & 24214dab5c37SJack F Vogel E1000_STAT_DEV_RST_SET)) 24224edd8523SJack F Vogel ctrl |= E1000_CTRL_DEV_RST; 24234edd8523SJack F Vogel else 24244edd8523SJack F Vogel ctrl |= E1000_CTRL_RST; 24254edd8523SJack F Vogel 24264edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 24274edd8523SJack F Vogel 24288cc64f1eSJack F Vogel switch (hw->device_id) { 24298cc64f1eSJack F Vogel case E1000_DEV_ID_DH89XXCC_SGMII: 24308cc64f1eSJack F Vogel break; 24318cc64f1eSJack F Vogel default: 24328cc64f1eSJack F Vogel E1000_WRITE_FLUSH(hw); 24338cc64f1eSJack F Vogel break; 24348cc64f1eSJack F Vogel } 24358cc64f1eSJack F Vogel 24368cc64f1eSJack F Vogel /* Add delay to insure DEV_RST or RST has time to complete */ 24374edd8523SJack F Vogel msec_delay(5); 24384edd8523SJack F Vogel 24394edd8523SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw); 24404edd8523SJack F Vogel if (ret_val) { 24414edd8523SJack F Vogel /* 24424edd8523SJack F Vogel * When auto config read does not complete, do not 24434edd8523SJack F Vogel * return with an error. This can happen in situations 24444edd8523SJack F Vogel * where there is no eeprom and prevents getting link. 24454edd8523SJack F Vogel */ 24464edd8523SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n"); 24474edd8523SJack F Vogel } 24484edd8523SJack F Vogel 24494edd8523SJack F Vogel /* clear global device reset status bit */ 24504edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); 24514edd8523SJack F Vogel 24524edd8523SJack F Vogel /* Clear any pending interrupt events. */ 24534edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 2454f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR); 24554edd8523SJack F Vogel 24567d9119bdSJack F Vogel ret_val = e1000_reset_mdicnfg_82580(hw); 24577d9119bdSJack F Vogel if (ret_val) 24587d9119bdSJack F Vogel DEBUGOUT("Could not reset MDICNFG based on EEPROM\n"); 24597d9119bdSJack F Vogel 24604edd8523SJack F Vogel /* Install any alternate MAC address into RAR0 */ 24614edd8523SJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 24624edd8523SJack F Vogel 24634edd8523SJack F Vogel /* Release semaphore */ 24644edd8523SJack F Vogel if (global_device_reset) 2465ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); 24664edd8523SJack F Vogel 24674edd8523SJack F Vogel return ret_val; 24684edd8523SJack F Vogel } 24694edd8523SJack F Vogel 24704edd8523SJack F Vogel /** 2471f0ecc46dSJack F Vogel * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size 24724edd8523SJack F Vogel * @data: data received by reading RXPBS register 24734edd8523SJack F Vogel * 24744edd8523SJack F Vogel * The 82580 uses a table based approach for packet buffer allocation sizes. 24754edd8523SJack F Vogel * This function converts the retrieved value into the correct table value 24764edd8523SJack F Vogel * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 24774edd8523SJack F Vogel * 0x0 36 72 144 1 2 4 8 16 24784edd8523SJack F Vogel * 0x8 35 70 140 rsv rsv rsv rsv rsv 24794edd8523SJack F Vogel */ 24804edd8523SJack F Vogel u16 e1000_rxpbs_adjust_82580(u32 data) 24814edd8523SJack F Vogel { 24824edd8523SJack F Vogel u16 ret_val = 0; 24834edd8523SJack F Vogel 24844edd8523SJack F Vogel if (data < E1000_82580_RXPBS_TABLE_SIZE) 24854edd8523SJack F Vogel ret_val = e1000_82580_rxpbs_table[data]; 24864edd8523SJack F Vogel 24874edd8523SJack F Vogel return ret_val; 24884edd8523SJack F Vogel } 2489f0ecc46dSJack F Vogel 2490f0ecc46dSJack F Vogel /** 2491f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_with_offset - Validate EEPROM 2492f0ecc46dSJack F Vogel * checksum 2493f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2494f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region 2495f0ecc46dSJack F Vogel * 2496f0ecc46dSJack F Vogel * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 2497f0ecc46dSJack F Vogel * and then verifies that the sum of the EEPROM is equal to 0xBABA. 2498f0ecc46dSJack F Vogel **/ 2499f0ecc46dSJack F Vogel s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) 2500f0ecc46dSJack F Vogel { 2501f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2502f0ecc46dSJack F Vogel u16 checksum = 0; 2503f0ecc46dSJack F Vogel u16 i, nvm_data; 2504f0ecc46dSJack F Vogel 2505f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_with_offset"); 2506f0ecc46dSJack F Vogel 2507f0ecc46dSJack F Vogel for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) { 2508f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 2509f0ecc46dSJack F Vogel if (ret_val) { 2510f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2511f0ecc46dSJack F Vogel goto out; 2512f0ecc46dSJack F Vogel } 2513f0ecc46dSJack F Vogel checksum += nvm_data; 2514f0ecc46dSJack F Vogel } 2515f0ecc46dSJack F Vogel 2516f0ecc46dSJack F Vogel if (checksum != (u16) NVM_SUM) { 2517f0ecc46dSJack F Vogel DEBUGOUT("NVM Checksum Invalid\n"); 2518f0ecc46dSJack F Vogel ret_val = -E1000_ERR_NVM; 2519f0ecc46dSJack F Vogel goto out; 2520f0ecc46dSJack F Vogel } 2521f0ecc46dSJack F Vogel 2522f0ecc46dSJack F Vogel out: 2523f0ecc46dSJack F Vogel return ret_val; 2524f0ecc46dSJack F Vogel } 2525f0ecc46dSJack F Vogel 2526f0ecc46dSJack F Vogel /** 2527f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_with_offset - Update EEPROM 2528f0ecc46dSJack F Vogel * checksum 2529f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2530f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region 2531f0ecc46dSJack F Vogel * 2532f0ecc46dSJack F Vogel * Updates the EEPROM checksum by reading/adding each word of the EEPROM 2533f0ecc46dSJack F Vogel * up to the checksum. Then calculates the EEPROM checksum and writes the 2534f0ecc46dSJack F Vogel * value to the EEPROM. 2535f0ecc46dSJack F Vogel **/ 2536f0ecc46dSJack F Vogel s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) 2537f0ecc46dSJack F Vogel { 2538f0ecc46dSJack F Vogel s32 ret_val; 2539f0ecc46dSJack F Vogel u16 checksum = 0; 2540f0ecc46dSJack F Vogel u16 i, nvm_data; 2541f0ecc46dSJack F Vogel 2542f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_with_offset"); 2543f0ecc46dSJack F Vogel 2544f0ecc46dSJack F Vogel for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) { 2545f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 2546f0ecc46dSJack F Vogel if (ret_val) { 2547f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error while updating checksum.\n"); 2548f0ecc46dSJack F Vogel goto out; 2549f0ecc46dSJack F Vogel } 2550f0ecc46dSJack F Vogel checksum += nvm_data; 2551f0ecc46dSJack F Vogel } 2552f0ecc46dSJack F Vogel checksum = (u16) NVM_SUM - checksum; 2553f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1, 2554f0ecc46dSJack F Vogel &checksum); 2555f0ecc46dSJack F Vogel if (ret_val) 2556f0ecc46dSJack F Vogel DEBUGOUT("NVM Write Error while updating checksum.\n"); 2557f0ecc46dSJack F Vogel 2558f0ecc46dSJack F Vogel out: 2559f0ecc46dSJack F Vogel return ret_val; 2560f0ecc46dSJack F Vogel } 2561f0ecc46dSJack F Vogel 2562f0ecc46dSJack F Vogel /** 2563f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum 2564f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2565f0ecc46dSJack F Vogel * 2566f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of 2567f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is 2568f0ecc46dSJack F Vogel * equal to 0xBABA. 2569f0ecc46dSJack F Vogel **/ 2570f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw) 2571f0ecc46dSJack F Vogel { 25728cc64f1eSJack F Vogel s32 ret_val; 2573f0ecc46dSJack F Vogel u16 eeprom_regions_count = 1; 2574f0ecc46dSJack F Vogel u16 j, nvm_data; 2575f0ecc46dSJack F Vogel u16 nvm_offset; 2576f0ecc46dSJack F Vogel 2577f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_82580"); 2578f0ecc46dSJack F Vogel 2579f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 2580f0ecc46dSJack F Vogel if (ret_val) { 2581f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2582f0ecc46dSJack F Vogel goto out; 2583f0ecc46dSJack F Vogel } 2584f0ecc46dSJack F Vogel 2585f0ecc46dSJack F Vogel if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { 2586f0ecc46dSJack F Vogel /* if chekcsums compatibility bit is set validate checksums 2587f0ecc46dSJack F Vogel * for all 4 ports. */ 2588f0ecc46dSJack F Vogel eeprom_regions_count = 4; 2589f0ecc46dSJack F Vogel } 2590f0ecc46dSJack F Vogel 2591f0ecc46dSJack F Vogel for (j = 0; j < eeprom_regions_count; j++) { 2592f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2593f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw, 2594f0ecc46dSJack F Vogel nvm_offset); 2595f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2596f0ecc46dSJack F Vogel goto out; 2597f0ecc46dSJack F Vogel } 2598f0ecc46dSJack F Vogel 2599f0ecc46dSJack F Vogel out: 2600f0ecc46dSJack F Vogel return ret_val; 2601f0ecc46dSJack F Vogel } 2602f0ecc46dSJack F Vogel 2603f0ecc46dSJack F Vogel /** 2604f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_82580 - Update EEPROM checksum 2605f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2606f0ecc46dSJack F Vogel * 2607f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding 2608f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM 2609f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM. 2610f0ecc46dSJack F Vogel **/ 2611f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) 2612f0ecc46dSJack F Vogel { 2613f0ecc46dSJack F Vogel s32 ret_val; 2614f0ecc46dSJack F Vogel u16 j, nvm_data; 2615f0ecc46dSJack F Vogel u16 nvm_offset; 2616f0ecc46dSJack F Vogel 2617f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_82580"); 2618f0ecc46dSJack F Vogel 2619f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 2620f0ecc46dSJack F Vogel if (ret_val) { 26214dab5c37SJack F Vogel DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n"); 2622f0ecc46dSJack F Vogel goto out; 2623f0ecc46dSJack F Vogel } 2624f0ecc46dSJack F Vogel 2625ab5d0362SJack F Vogel if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { 2626f0ecc46dSJack F Vogel /* set compatibility bit to validate checksums appropriately */ 2627f0ecc46dSJack F Vogel nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; 2628f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, 2629f0ecc46dSJack F Vogel &nvm_data); 2630f0ecc46dSJack F Vogel if (ret_val) { 26314dab5c37SJack F Vogel DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n"); 2632f0ecc46dSJack F Vogel goto out; 2633f0ecc46dSJack F Vogel } 2634f0ecc46dSJack F Vogel } 2635f0ecc46dSJack F Vogel 2636f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2637f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2638f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); 26394dab5c37SJack F Vogel if (ret_val) 2640f0ecc46dSJack F Vogel goto out; 2641f0ecc46dSJack F Vogel } 2642f0ecc46dSJack F Vogel 2643f0ecc46dSJack F Vogel out: 2644f0ecc46dSJack F Vogel return ret_val; 2645f0ecc46dSJack F Vogel } 2646f0ecc46dSJack F Vogel 2647f0ecc46dSJack F Vogel /** 2648f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum 2649f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2650f0ecc46dSJack F Vogel * 2651f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of 2652f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is 2653f0ecc46dSJack F Vogel * equal to 0xBABA. 2654f0ecc46dSJack F Vogel **/ 2655f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw) 2656f0ecc46dSJack F Vogel { 2657f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2658f0ecc46dSJack F Vogel u16 j; 2659f0ecc46dSJack F Vogel u16 nvm_offset; 2660f0ecc46dSJack F Vogel 2661f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_i350"); 2662f0ecc46dSJack F Vogel 2663f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2664f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2665f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw, 2666f0ecc46dSJack F Vogel nvm_offset); 2667f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2668f0ecc46dSJack F Vogel goto out; 2669f0ecc46dSJack F Vogel } 2670f0ecc46dSJack F Vogel 2671f0ecc46dSJack F Vogel out: 2672f0ecc46dSJack F Vogel return ret_val; 2673f0ecc46dSJack F Vogel } 2674f0ecc46dSJack F Vogel 2675f0ecc46dSJack F Vogel /** 2676f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_i350 - Update EEPROM checksum 2677f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2678f0ecc46dSJack F Vogel * 2679f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding 2680f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM 2681f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM. 2682f0ecc46dSJack F Vogel **/ 2683f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw) 2684f0ecc46dSJack F Vogel { 2685f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2686f0ecc46dSJack F Vogel u16 j; 2687f0ecc46dSJack F Vogel u16 nvm_offset; 2688f0ecc46dSJack F Vogel 2689f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_i350"); 2690f0ecc46dSJack F Vogel 2691f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2692f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2693f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); 2694f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2695f0ecc46dSJack F Vogel goto out; 2696f0ecc46dSJack F Vogel } 2697f0ecc46dSJack F Vogel 2698f0ecc46dSJack F Vogel out: 2699f0ecc46dSJack F Vogel return ret_val; 2700f0ecc46dSJack F Vogel } 2701f0ecc46dSJack F Vogel 2702f0ecc46dSJack F Vogel /** 27037609433eSJack F Vogel * __e1000_access_emi_reg - Read/write EMI register 27047609433eSJack F Vogel * @hw: pointer to the HW structure 2705*5b426b3eSGuinan Sun * @address: EMI address to program 27067609433eSJack F Vogel * @data: pointer to value to read/write from/to the EMI address 27077609433eSJack F Vogel * @read: boolean flag to indicate read or write 27087609433eSJack F Vogel **/ 27097609433eSJack F Vogel static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address, 27107609433eSJack F Vogel u16 *data, bool read) 27117609433eSJack F Vogel { 27128cc64f1eSJack F Vogel s32 ret_val; 27137609433eSJack F Vogel 27147609433eSJack F Vogel DEBUGFUNC("__e1000_access_emi_reg"); 27157609433eSJack F Vogel 27167609433eSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address); 27177609433eSJack F Vogel if (ret_val) 27187609433eSJack F Vogel return ret_val; 27197609433eSJack F Vogel 27207609433eSJack F Vogel if (read) 27217609433eSJack F Vogel ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data); 27227609433eSJack F Vogel else 27237609433eSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data); 27247609433eSJack F Vogel 27257609433eSJack F Vogel return ret_val; 27267609433eSJack F Vogel } 27277609433eSJack F Vogel 27287609433eSJack F Vogel /** 27297609433eSJack F Vogel * e1000_read_emi_reg - Read Extended Management Interface register 27307609433eSJack F Vogel * @hw: pointer to the HW structure 27317609433eSJack F Vogel * @addr: EMI address to program 27327609433eSJack F Vogel * @data: value to be read from the EMI address 27337609433eSJack F Vogel **/ 27347609433eSJack F Vogel s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) 27357609433eSJack F Vogel { 27367609433eSJack F Vogel DEBUGFUNC("e1000_read_emi_reg"); 27377609433eSJack F Vogel 27387609433eSJack F Vogel return __e1000_access_emi_reg(hw, addr, data, TRUE); 27397609433eSJack F Vogel } 27407609433eSJack F Vogel 27417609433eSJack F Vogel /** 27428cc64f1eSJack F Vogel * e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY 27438cc64f1eSJack F Vogel * @hw: pointer to the HW structure 27448cc64f1eSJack F Vogel * 2745c80429ceSEric Joyner * Initialize Marvell 1512 to work correctly with Avoton. 27468cc64f1eSJack F Vogel **/ 27478cc64f1eSJack F Vogel s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) 27488cc64f1eSJack F Vogel { 27498cc64f1eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 27508cc64f1eSJack F Vogel s32 ret_val = E1000_SUCCESS; 27518cc64f1eSJack F Vogel 27528cc64f1eSJack F Vogel DEBUGFUNC("e1000_initialize_M88E1512_phy"); 27538cc64f1eSJack F Vogel 27548cc64f1eSJack F Vogel /* Check if this is correct PHY. */ 27558cc64f1eSJack F Vogel if (phy->id != M88E1512_E_PHY_ID) 27568cc64f1eSJack F Vogel goto out; 27578cc64f1eSJack F Vogel 27588cc64f1eSJack F Vogel /* Switch to PHY page 0xFF. */ 27598cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); 27608cc64f1eSJack F Vogel if (ret_val) 27618cc64f1eSJack F Vogel goto out; 27628cc64f1eSJack F Vogel 27638cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); 27648cc64f1eSJack F Vogel if (ret_val) 27658cc64f1eSJack F Vogel goto out; 27668cc64f1eSJack F Vogel 27678cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); 27688cc64f1eSJack F Vogel if (ret_val) 27698cc64f1eSJack F Vogel goto out; 27708cc64f1eSJack F Vogel 27718cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); 27728cc64f1eSJack F Vogel if (ret_val) 27738cc64f1eSJack F Vogel goto out; 27748cc64f1eSJack F Vogel 27758cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); 27768cc64f1eSJack F Vogel if (ret_val) 27778cc64f1eSJack F Vogel goto out; 27788cc64f1eSJack F Vogel 27798cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); 27808cc64f1eSJack F Vogel if (ret_val) 27818cc64f1eSJack F Vogel goto out; 27828cc64f1eSJack F Vogel 27838cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); 27848cc64f1eSJack F Vogel if (ret_val) 27858cc64f1eSJack F Vogel goto out; 27868cc64f1eSJack F Vogel 27878cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xCC0C); 27888cc64f1eSJack F Vogel if (ret_val) 27898cc64f1eSJack F Vogel goto out; 27908cc64f1eSJack F Vogel 27918cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); 27928cc64f1eSJack F Vogel if (ret_val) 27938cc64f1eSJack F Vogel goto out; 27948cc64f1eSJack F Vogel 27958cc64f1eSJack F Vogel /* Switch to PHY page 0xFB. */ 27968cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); 27978cc64f1eSJack F Vogel if (ret_val) 27988cc64f1eSJack F Vogel goto out; 27998cc64f1eSJack F Vogel 28008cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0x000D); 28018cc64f1eSJack F Vogel if (ret_val) 28028cc64f1eSJack F Vogel goto out; 28038cc64f1eSJack F Vogel 28048cc64f1eSJack F Vogel /* Switch to PHY page 0x12. */ 28058cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); 28068cc64f1eSJack F Vogel if (ret_val) 28078cc64f1eSJack F Vogel goto out; 28088cc64f1eSJack F Vogel 28098cc64f1eSJack F Vogel /* Change mode to SGMII-to-Copper */ 28108cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); 28118cc64f1eSJack F Vogel if (ret_val) 28128cc64f1eSJack F Vogel goto out; 28138cc64f1eSJack F Vogel 28148cc64f1eSJack F Vogel /* Return the PHY to page 0. */ 28158cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); 28168cc64f1eSJack F Vogel if (ret_val) 28178cc64f1eSJack F Vogel goto out; 28188cc64f1eSJack F Vogel 28198cc64f1eSJack F Vogel ret_val = phy->ops.commit(hw); 28208cc64f1eSJack F Vogel if (ret_val) { 28218cc64f1eSJack F Vogel DEBUGOUT("Error committing the PHY changes\n"); 28228cc64f1eSJack F Vogel return ret_val; 28238cc64f1eSJack F Vogel } 28248cc64f1eSJack F Vogel 28258cc64f1eSJack F Vogel msec_delay(1000); 28268cc64f1eSJack F Vogel out: 28278cc64f1eSJack F Vogel return ret_val; 28288cc64f1eSJack F Vogel } 28298cc64f1eSJack F Vogel 28308cc64f1eSJack F Vogel /** 2831c80429ceSEric Joyner * e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY 2832c80429ceSEric Joyner * @hw: pointer to the HW structure 2833c80429ceSEric Joyner * 2834c80429ceSEric Joyner * Initialize Marvell 1543 to work correctly with Avoton. 2835c80429ceSEric Joyner **/ 2836c80429ceSEric Joyner s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw) 2837c80429ceSEric Joyner { 2838c80429ceSEric Joyner struct e1000_phy_info *phy = &hw->phy; 2839c80429ceSEric Joyner s32 ret_val = E1000_SUCCESS; 2840c80429ceSEric Joyner 2841c80429ceSEric Joyner DEBUGFUNC("e1000_initialize_M88E1543_phy"); 2842c80429ceSEric Joyner 2843c80429ceSEric Joyner /* Check if this is correct PHY. */ 2844c80429ceSEric Joyner if (phy->id != M88E1543_E_PHY_ID) 2845c80429ceSEric Joyner goto out; 2846c80429ceSEric Joyner 2847c80429ceSEric Joyner /* Switch to PHY page 0xFF. */ 2848c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); 2849c80429ceSEric Joyner if (ret_val) 2850c80429ceSEric Joyner goto out; 2851c80429ceSEric Joyner 2852c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); 2853c80429ceSEric Joyner if (ret_val) 2854c80429ceSEric Joyner goto out; 2855c80429ceSEric Joyner 2856c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); 2857c80429ceSEric Joyner if (ret_val) 2858c80429ceSEric Joyner goto out; 2859c80429ceSEric Joyner 2860c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); 2861c80429ceSEric Joyner if (ret_val) 2862c80429ceSEric Joyner goto out; 2863c80429ceSEric Joyner 2864c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); 2865c80429ceSEric Joyner if (ret_val) 2866c80429ceSEric Joyner goto out; 2867c80429ceSEric Joyner 2868c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); 2869c80429ceSEric Joyner if (ret_val) 2870c80429ceSEric Joyner goto out; 2871c80429ceSEric Joyner 2872c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); 2873c80429ceSEric Joyner if (ret_val) 2874c80429ceSEric Joyner goto out; 2875c80429ceSEric Joyner 2876c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C); 2877c80429ceSEric Joyner if (ret_val) 2878c80429ceSEric Joyner goto out; 2879c80429ceSEric Joyner 2880c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); 2881c80429ceSEric Joyner if (ret_val) 2882c80429ceSEric Joyner goto out; 2883c80429ceSEric Joyner 2884c80429ceSEric Joyner /* Switch to PHY page 0xFB. */ 2885c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); 2886c80429ceSEric Joyner if (ret_val) 2887c80429ceSEric Joyner goto out; 2888c80429ceSEric Joyner 2889c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D); 2890c80429ceSEric Joyner if (ret_val) 2891c80429ceSEric Joyner goto out; 2892c80429ceSEric Joyner 2893c80429ceSEric Joyner /* Switch to PHY page 0x12. */ 2894c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); 2895c80429ceSEric Joyner if (ret_val) 2896c80429ceSEric Joyner goto out; 2897c80429ceSEric Joyner 2898c80429ceSEric Joyner /* Change mode to SGMII-to-Copper */ 2899c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); 2900c80429ceSEric Joyner if (ret_val) 2901c80429ceSEric Joyner goto out; 2902c80429ceSEric Joyner 2903c80429ceSEric Joyner /* Switch to PHY page 1. */ 2904c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1); 2905c80429ceSEric Joyner if (ret_val) 2906c80429ceSEric Joyner goto out; 2907c80429ceSEric Joyner 2908c80429ceSEric Joyner /* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */ 2909c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140); 2910c80429ceSEric Joyner if (ret_val) 2911c80429ceSEric Joyner goto out; 2912c80429ceSEric Joyner 2913c80429ceSEric Joyner /* Return the PHY to page 0. */ 2914c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); 2915c80429ceSEric Joyner if (ret_val) 2916c80429ceSEric Joyner goto out; 2917c80429ceSEric Joyner 2918c80429ceSEric Joyner ret_val = phy->ops.commit(hw); 2919c80429ceSEric Joyner if (ret_val) { 2920c80429ceSEric Joyner DEBUGOUT("Error committing the PHY changes\n"); 2921c80429ceSEric Joyner return ret_val; 2922c80429ceSEric Joyner } 2923c80429ceSEric Joyner 2924c80429ceSEric Joyner msec_delay(1000); 2925c80429ceSEric Joyner out: 2926c80429ceSEric Joyner return ret_val; 2927c80429ceSEric Joyner } 2928c80429ceSEric Joyner 2929c80429ceSEric Joyner /** 2930f0ecc46dSJack F Vogel * e1000_set_eee_i350 - Enable/disable EEE support 2931f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2932*5b426b3eSGuinan Sun * @adv1G: boolean flag enabling 1G EEE advertisement 2933*5b426b3eSGuinan Sun * @adv100M: boolean flag enabling 100M EEE advertisement 2934f0ecc46dSJack F Vogel * 2935f0ecc46dSJack F Vogel * Enable/disable EEE based on setting in dev_spec structure. 2936f0ecc46dSJack F Vogel * 2937f0ecc46dSJack F Vogel **/ 2938c80429ceSEric Joyner s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M) 2939f0ecc46dSJack F Vogel { 29404dab5c37SJack F Vogel u32 ipcnfg, eeer; 2941f0ecc46dSJack F Vogel 2942f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_eee_i350"); 2943f0ecc46dSJack F Vogel 29444dab5c37SJack F Vogel if ((hw->mac.type < e1000_i350) || 29454dab5c37SJack F Vogel (hw->phy.media_type != e1000_media_type_copper)) 2946f0ecc46dSJack F Vogel goto out; 2947f0ecc46dSJack F Vogel ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); 2948f0ecc46dSJack F Vogel eeer = E1000_READ_REG(hw, E1000_EEER); 2949f0ecc46dSJack F Vogel 2950f0ecc46dSJack F Vogel /* enable or disable per user setting */ 2951f0ecc46dSJack F Vogel if (!(hw->dev_spec._82575.eee_disable)) { 29526ab6bfe3SJack F Vogel u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); 29536ab6bfe3SJack F Vogel 2954c80429ceSEric Joyner if (adv100M) 2955c80429ceSEric Joyner ipcnfg |= E1000_IPCNFG_EEE_100M_AN; 2956c80429ceSEric Joyner else 2957c80429ceSEric Joyner ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN; 2958c80429ceSEric Joyner 2959c80429ceSEric Joyner if (adv1G) 2960c80429ceSEric Joyner ipcnfg |= E1000_IPCNFG_EEE_1G_AN; 2961c80429ceSEric Joyner else 2962c80429ceSEric Joyner ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN; 2963c80429ceSEric Joyner 29644dab5c37SJack F Vogel eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | 2965f0ecc46dSJack F Vogel E1000_EEER_LPI_FC); 2966f0ecc46dSJack F Vogel 29676ab6bfe3SJack F Vogel /* This bit should not be set in normal operation. */ 29686ab6bfe3SJack F Vogel if (eee_su & E1000_EEE_SU_LPI_CLK_STP) 29696ab6bfe3SJack F Vogel DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); 2970f0ecc46dSJack F Vogel } else { 29714dab5c37SJack F Vogel ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); 29724dab5c37SJack F Vogel eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | 2973f0ecc46dSJack F Vogel E1000_EEER_LPI_FC); 2974f0ecc46dSJack F Vogel } 2975f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg); 2976f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_EEER, eeer); 2977f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_IPCNFG); 2978f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_EEER); 2979f0ecc46dSJack F Vogel out: 2980f0ecc46dSJack F Vogel 29818cc64f1eSJack F Vogel return E1000_SUCCESS; 2982f0ecc46dSJack F Vogel } 29834dab5c37SJack F Vogel 29847609433eSJack F Vogel /** 29857609433eSJack F Vogel * e1000_set_eee_i354 - Enable/disable EEE support 29867609433eSJack F Vogel * @hw: pointer to the HW structure 2987*5b426b3eSGuinan Sun * @adv1G: boolean flag enabling 1G EEE advertisement 2988*5b426b3eSGuinan Sun * @adv100M: boolean flag enabling 100M EEE advertisement 29897609433eSJack F Vogel * 29907609433eSJack F Vogel * Enable/disable EEE legacy mode based on setting in dev_spec structure. 29917609433eSJack F Vogel * 29927609433eSJack F Vogel **/ 2993c80429ceSEric Joyner s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M) 29947609433eSJack F Vogel { 29957609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 29967609433eSJack F Vogel s32 ret_val = E1000_SUCCESS; 29977609433eSJack F Vogel u16 phy_data; 29987609433eSJack F Vogel 29997609433eSJack F Vogel DEBUGFUNC("e1000_set_eee_i354"); 30007609433eSJack F Vogel 30017609433eSJack F Vogel if ((hw->phy.media_type != e1000_media_type_copper) || 30027609433eSJack F Vogel ((phy->id != M88E1543_E_PHY_ID) && 30037609433eSJack F Vogel (phy->id != M88E1512_E_PHY_ID))) 30047609433eSJack F Vogel goto out; 30057609433eSJack F Vogel 30067609433eSJack F Vogel if (!hw->dev_spec._82575.eee_disable) { 30077609433eSJack F Vogel /* Switch to PHY page 18. */ 30087609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18); 30097609433eSJack F Vogel if (ret_val) 30107609433eSJack F Vogel goto out; 30117609433eSJack F Vogel 30127609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, 30137609433eSJack F Vogel &phy_data); 30147609433eSJack F Vogel if (ret_val) 30157609433eSJack F Vogel goto out; 30167609433eSJack F Vogel 30177609433eSJack F Vogel phy_data |= E1000_M88E1543_EEE_CTRL_1_MS; 30187609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1, 30197609433eSJack F Vogel phy_data); 30207609433eSJack F Vogel if (ret_val) 30217609433eSJack F Vogel goto out; 30227609433eSJack F Vogel 30237609433eSJack F Vogel /* Return the PHY to page 0. */ 30247609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); 30257609433eSJack F Vogel if (ret_val) 30267609433eSJack F Vogel goto out; 30277609433eSJack F Vogel 30287609433eSJack F Vogel /* Turn on EEE advertisement. */ 30297609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 30307609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 30317609433eSJack F Vogel &phy_data); 30327609433eSJack F Vogel if (ret_val) 30337609433eSJack F Vogel goto out; 30347609433eSJack F Vogel 3035c80429ceSEric Joyner if (adv100M) 3036c80429ceSEric Joyner phy_data |= E1000_EEE_ADV_100_SUPPORTED; 3037c80429ceSEric Joyner else 3038c80429ceSEric Joyner phy_data &= ~E1000_EEE_ADV_100_SUPPORTED; 3039c80429ceSEric Joyner 3040c80429ceSEric Joyner if (adv1G) 3041c80429ceSEric Joyner phy_data |= E1000_EEE_ADV_1000_SUPPORTED; 3042c80429ceSEric Joyner else 3043c80429ceSEric Joyner phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED; 3044c80429ceSEric Joyner 30457609433eSJack F Vogel ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 30467609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 30477609433eSJack F Vogel phy_data); 30487609433eSJack F Vogel } else { 30497609433eSJack F Vogel /* Turn off EEE advertisement. */ 30507609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 30517609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 30527609433eSJack F Vogel &phy_data); 30537609433eSJack F Vogel if (ret_val) 30547609433eSJack F Vogel goto out; 30557609433eSJack F Vogel 30567609433eSJack F Vogel phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED | 30577609433eSJack F Vogel E1000_EEE_ADV_1000_SUPPORTED); 30587609433eSJack F Vogel ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 30597609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 30607609433eSJack F Vogel phy_data); 30617609433eSJack F Vogel } 30627609433eSJack F Vogel 30637609433eSJack F Vogel out: 30647609433eSJack F Vogel return ret_val; 30657609433eSJack F Vogel } 30667609433eSJack F Vogel 30677609433eSJack F Vogel /** 30687609433eSJack F Vogel * e1000_get_eee_status_i354 - Get EEE status 30697609433eSJack F Vogel * @hw: pointer to the HW structure 30707609433eSJack F Vogel * @status: EEE status 30717609433eSJack F Vogel * 30727609433eSJack F Vogel * Get EEE status by guessing based on whether Tx or Rx LPI indications have 30737609433eSJack F Vogel * been received. 30747609433eSJack F Vogel **/ 30757609433eSJack F Vogel s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status) 30767609433eSJack F Vogel { 30777609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 30787609433eSJack F Vogel s32 ret_val = E1000_SUCCESS; 30797609433eSJack F Vogel u16 phy_data; 30807609433eSJack F Vogel 30817609433eSJack F Vogel DEBUGFUNC("e1000_get_eee_status_i354"); 30827609433eSJack F Vogel 30837609433eSJack F Vogel /* Check if EEE is supported on this device. */ 30847609433eSJack F Vogel if ((hw->phy.media_type != e1000_media_type_copper) || 30857609433eSJack F Vogel ((phy->id != M88E1543_E_PHY_ID) && 30867609433eSJack F Vogel (phy->id != M88E1512_E_PHY_ID))) 30877609433eSJack F Vogel goto out; 30887609433eSJack F Vogel 30897609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, 30907609433eSJack F Vogel E1000_PCS_STATUS_DEV_I354, 30917609433eSJack F Vogel &phy_data); 30927609433eSJack F Vogel if (ret_val) 30937609433eSJack F Vogel goto out; 30947609433eSJack F Vogel 30957609433eSJack F Vogel *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD | 30967609433eSJack F Vogel E1000_PCS_STATUS_RX_LPI_RCVD) ? TRUE : FALSE; 30977609433eSJack F Vogel 30987609433eSJack F Vogel out: 30997609433eSJack F Vogel return ret_val; 31007609433eSJack F Vogel } 31017609433eSJack F Vogel 31024dab5c37SJack F Vogel /* Due to a hw errata, if the host tries to configure the VFTA register 31034dab5c37SJack F Vogel * while performing queries from the BMC or DMA, then the VFTA in some 31044dab5c37SJack F Vogel * cases won't be written. 31054dab5c37SJack F Vogel */ 31064dab5c37SJack F Vogel 31074dab5c37SJack F Vogel /** 31084dab5c37SJack F Vogel * e1000_clear_vfta_i350 - Clear VLAN filter table 31094dab5c37SJack F Vogel * @hw: pointer to the HW structure 31104dab5c37SJack F Vogel * 31114dab5c37SJack F Vogel * Clears the register array which contains the VLAN filter table by 31124dab5c37SJack F Vogel * setting all the values to 0. 31134dab5c37SJack F Vogel **/ 31144dab5c37SJack F Vogel void e1000_clear_vfta_i350(struct e1000_hw *hw) 31154dab5c37SJack F Vogel { 31164dab5c37SJack F Vogel u32 offset; 31174dab5c37SJack F Vogel int i; 31184dab5c37SJack F Vogel 31194dab5c37SJack F Vogel DEBUGFUNC("e1000_clear_vfta_350"); 31204dab5c37SJack F Vogel 31214dab5c37SJack F Vogel for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { 31224dab5c37SJack F Vogel for (i = 0; i < 10; i++) 31234dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); 31244dab5c37SJack F Vogel 31254dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 31264dab5c37SJack F Vogel } 31274dab5c37SJack F Vogel } 31284dab5c37SJack F Vogel 31294dab5c37SJack F Vogel /** 31304dab5c37SJack F Vogel * e1000_write_vfta_i350 - Write value to VLAN filter table 31314dab5c37SJack F Vogel * @hw: pointer to the HW structure 31324dab5c37SJack F Vogel * @offset: register offset in VLAN filter table 31334dab5c37SJack F Vogel * @value: register value written to VLAN filter table 31344dab5c37SJack F Vogel * 31354dab5c37SJack F Vogel * Writes value at the given offset in the register array which stores 31364dab5c37SJack F Vogel * the VLAN filter table. 31374dab5c37SJack F Vogel **/ 31384dab5c37SJack F Vogel void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) 31394dab5c37SJack F Vogel { 31404dab5c37SJack F Vogel int i; 31414dab5c37SJack F Vogel 31424dab5c37SJack F Vogel DEBUGFUNC("e1000_write_vfta_350"); 31434dab5c37SJack F Vogel 31444dab5c37SJack F Vogel for (i = 0; i < 10; i++) 31454dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); 31464dab5c37SJack F Vogel 31474dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 31484dab5c37SJack F Vogel } 31494dab5c37SJack F Vogel 31504dab5c37SJack F Vogel 31514dab5c37SJack F Vogel /** 31524dab5c37SJack F Vogel * e1000_set_i2c_bb - Enable I2C bit-bang 31534dab5c37SJack F Vogel * @hw: pointer to the HW structure 31544dab5c37SJack F Vogel * 31554dab5c37SJack F Vogel * Enable I2C bit-bang interface 31564dab5c37SJack F Vogel * 31574dab5c37SJack F Vogel **/ 31584dab5c37SJack F Vogel s32 e1000_set_i2c_bb(struct e1000_hw *hw) 31594dab5c37SJack F Vogel { 31604dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS; 31614dab5c37SJack F Vogel u32 ctrl_ext, i2cparams; 31624dab5c37SJack F Vogel 31634dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_bb"); 31644dab5c37SJack F Vogel 31654dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 31664dab5c37SJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA; 31674dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 31684dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 31694dab5c37SJack F Vogel 31704dab5c37SJack F Vogel i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS); 31714dab5c37SJack F Vogel i2cparams |= E1000_I2CBB_EN; 31724dab5c37SJack F Vogel i2cparams |= E1000_I2C_DATA_OE_N; 31734dab5c37SJack F Vogel i2cparams |= E1000_I2C_CLK_OE_N; 31744dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams); 31754dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 31764dab5c37SJack F Vogel 31774dab5c37SJack F Vogel return ret_val; 31784dab5c37SJack F Vogel } 31794dab5c37SJack F Vogel 31804dab5c37SJack F Vogel /** 31814dab5c37SJack F Vogel * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C 31824dab5c37SJack F Vogel * @hw: pointer to hardware structure 31834dab5c37SJack F Vogel * @byte_offset: byte offset to read 3184ab5d0362SJack F Vogel * @dev_addr: device address 31854dab5c37SJack F Vogel * @data: value read 31864dab5c37SJack F Vogel * 31874dab5c37SJack F Vogel * Performs byte read operation over I2C interface at 31884dab5c37SJack F Vogel * a specified device address. 31894dab5c37SJack F Vogel **/ 31904dab5c37SJack F Vogel s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, 31914dab5c37SJack F Vogel u8 dev_addr, u8 *data) 31924dab5c37SJack F Vogel { 31934dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 31944dab5c37SJack F Vogel u32 max_retry = 10; 31954dab5c37SJack F Vogel u32 retry = 1; 31964dab5c37SJack F Vogel u16 swfw_mask = 0; 31974dab5c37SJack F Vogel 3198ab5d0362SJack F Vogel bool nack = TRUE; 31994dab5c37SJack F Vogel 32004dab5c37SJack F Vogel DEBUGFUNC("e1000_read_i2c_byte_generic"); 32014dab5c37SJack F Vogel 32024dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM; 32034dab5c37SJack F Vogel 32044dab5c37SJack F Vogel do { 3205ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) 32064dab5c37SJack F Vogel != E1000_SUCCESS) { 32074dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC; 32084dab5c37SJack F Vogel goto read_byte_out; 32094dab5c37SJack F Vogel } 32104dab5c37SJack F Vogel 32114dab5c37SJack F Vogel e1000_i2c_start(hw); 32124dab5c37SJack F Vogel 32134dab5c37SJack F Vogel /* Device Address and write indication */ 32144dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr); 32154dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32164dab5c37SJack F Vogel goto fail; 32174dab5c37SJack F Vogel 32184dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 32194dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32204dab5c37SJack F Vogel goto fail; 32214dab5c37SJack F Vogel 32224dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset); 32234dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32244dab5c37SJack F Vogel goto fail; 32254dab5c37SJack F Vogel 32264dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 32274dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32284dab5c37SJack F Vogel goto fail; 32294dab5c37SJack F Vogel 32304dab5c37SJack F Vogel e1000_i2c_start(hw); 32314dab5c37SJack F Vogel 32324dab5c37SJack F Vogel /* Device Address and read indication */ 32334dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1)); 32344dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32354dab5c37SJack F Vogel goto fail; 32364dab5c37SJack F Vogel 32374dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 32384dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32394dab5c37SJack F Vogel goto fail; 32404dab5c37SJack F Vogel 32414dab5c37SJack F Vogel status = e1000_clock_in_i2c_byte(hw, data); 32424dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32434dab5c37SJack F Vogel goto fail; 32444dab5c37SJack F Vogel 32454dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, nack); 32464dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32474dab5c37SJack F Vogel goto fail; 32484dab5c37SJack F Vogel 32494dab5c37SJack F Vogel e1000_i2c_stop(hw); 32504dab5c37SJack F Vogel break; 32514dab5c37SJack F Vogel 32524dab5c37SJack F Vogel fail: 3253ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 32544dab5c37SJack F Vogel msec_delay(100); 32554dab5c37SJack F Vogel e1000_i2c_bus_clear(hw); 32564dab5c37SJack F Vogel retry++; 32574dab5c37SJack F Vogel if (retry < max_retry) 32584dab5c37SJack F Vogel DEBUGOUT("I2C byte read error - Retrying.\n"); 32594dab5c37SJack F Vogel else 32604dab5c37SJack F Vogel DEBUGOUT("I2C byte read error.\n"); 32614dab5c37SJack F Vogel 32624dab5c37SJack F Vogel } while (retry < max_retry); 32634dab5c37SJack F Vogel 3264ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 32654dab5c37SJack F Vogel 32664dab5c37SJack F Vogel read_byte_out: 32674dab5c37SJack F Vogel 32684dab5c37SJack F Vogel return status; 32694dab5c37SJack F Vogel } 32704dab5c37SJack F Vogel 32714dab5c37SJack F Vogel /** 32724dab5c37SJack F Vogel * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C 32734dab5c37SJack F Vogel * @hw: pointer to hardware structure 32744dab5c37SJack F Vogel * @byte_offset: byte offset to write 3275ab5d0362SJack F Vogel * @dev_addr: device address 32764dab5c37SJack F Vogel * @data: value to write 32774dab5c37SJack F Vogel * 32784dab5c37SJack F Vogel * Performs byte write operation over I2C interface at 32794dab5c37SJack F Vogel * a specified device address. 32804dab5c37SJack F Vogel **/ 32814dab5c37SJack F Vogel s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, 32824dab5c37SJack F Vogel u8 dev_addr, u8 data) 32834dab5c37SJack F Vogel { 32844dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 32854dab5c37SJack F Vogel u32 max_retry = 1; 32864dab5c37SJack F Vogel u32 retry = 0; 32874dab5c37SJack F Vogel u16 swfw_mask = 0; 32884dab5c37SJack F Vogel 32894dab5c37SJack F Vogel DEBUGFUNC("e1000_write_i2c_byte_generic"); 32904dab5c37SJack F Vogel 32914dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM; 32924dab5c37SJack F Vogel 3293ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { 32944dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC; 32954dab5c37SJack F Vogel goto write_byte_out; 32964dab5c37SJack F Vogel } 32974dab5c37SJack F Vogel 32984dab5c37SJack F Vogel do { 32994dab5c37SJack F Vogel e1000_i2c_start(hw); 33004dab5c37SJack F Vogel 33014dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr); 33024dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33034dab5c37SJack F Vogel goto fail; 33044dab5c37SJack F Vogel 33054dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33064dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33074dab5c37SJack F Vogel goto fail; 33084dab5c37SJack F Vogel 33094dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset); 33104dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33114dab5c37SJack F Vogel goto fail; 33124dab5c37SJack F Vogel 33134dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33144dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33154dab5c37SJack F Vogel goto fail; 33164dab5c37SJack F Vogel 33174dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, data); 33184dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33194dab5c37SJack F Vogel goto fail; 33204dab5c37SJack F Vogel 33214dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33224dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33234dab5c37SJack F Vogel goto fail; 33244dab5c37SJack F Vogel 33254dab5c37SJack F Vogel e1000_i2c_stop(hw); 33264dab5c37SJack F Vogel break; 33274dab5c37SJack F Vogel 33284dab5c37SJack F Vogel fail: 33294dab5c37SJack F Vogel e1000_i2c_bus_clear(hw); 33304dab5c37SJack F Vogel retry++; 33314dab5c37SJack F Vogel if (retry < max_retry) 33324dab5c37SJack F Vogel DEBUGOUT("I2C byte write error - Retrying.\n"); 33334dab5c37SJack F Vogel else 33344dab5c37SJack F Vogel DEBUGOUT("I2C byte write error.\n"); 33354dab5c37SJack F Vogel } while (retry < max_retry); 33364dab5c37SJack F Vogel 3337ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 33384dab5c37SJack F Vogel 33394dab5c37SJack F Vogel write_byte_out: 33404dab5c37SJack F Vogel 33414dab5c37SJack F Vogel return status; 33424dab5c37SJack F Vogel } 33434dab5c37SJack F Vogel 33444dab5c37SJack F Vogel /** 33454dab5c37SJack F Vogel * e1000_i2c_start - Sets I2C start condition 33464dab5c37SJack F Vogel * @hw: pointer to hardware structure 33474dab5c37SJack F Vogel * 33484dab5c37SJack F Vogel * Sets I2C start condition (High -> Low on SDA while SCL is High) 33494dab5c37SJack F Vogel **/ 33504dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw) 33514dab5c37SJack F Vogel { 33524dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 33534dab5c37SJack F Vogel 33544dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_start"); 33554dab5c37SJack F Vogel 33564dab5c37SJack F Vogel /* Start condition must begin with data and clock high */ 33574dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 33584dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 33594dab5c37SJack F Vogel 33604dab5c37SJack F Vogel /* Setup time for start condition (4.7us) */ 33614dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STA); 33624dab5c37SJack F Vogel 33634dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0); 33644dab5c37SJack F Vogel 33654dab5c37SJack F Vogel /* Hold time for start condition (4us) */ 33664dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HD_STA); 33674dab5c37SJack F Vogel 33684dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 33694dab5c37SJack F Vogel 33704dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 33714dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 33724dab5c37SJack F Vogel 33734dab5c37SJack F Vogel } 33744dab5c37SJack F Vogel 33754dab5c37SJack F Vogel /** 33764dab5c37SJack F Vogel * e1000_i2c_stop - Sets I2C stop condition 33774dab5c37SJack F Vogel * @hw: pointer to hardware structure 33784dab5c37SJack F Vogel * 33794dab5c37SJack F Vogel * Sets I2C stop condition (Low -> High on SDA while SCL is High) 33804dab5c37SJack F Vogel **/ 33814dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw) 33824dab5c37SJack F Vogel { 33834dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 33844dab5c37SJack F Vogel 33854dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_stop"); 33864dab5c37SJack F Vogel 33874dab5c37SJack F Vogel /* Stop condition must begin with data low and clock high */ 33884dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0); 33894dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 33904dab5c37SJack F Vogel 33914dab5c37SJack F Vogel /* Setup time for stop condition (4us) */ 33924dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STO); 33934dab5c37SJack F Vogel 33944dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 33954dab5c37SJack F Vogel 33964dab5c37SJack F Vogel /* bus free time between stop and start (4.7us)*/ 33974dab5c37SJack F Vogel usec_delay(E1000_I2C_T_BUF); 33984dab5c37SJack F Vogel } 33994dab5c37SJack F Vogel 34004dab5c37SJack F Vogel /** 34014dab5c37SJack F Vogel * e1000_clock_in_i2c_byte - Clocks in one byte via I2C 34024dab5c37SJack F Vogel * @hw: pointer to hardware structure 34034dab5c37SJack F Vogel * @data: data byte to clock in 34044dab5c37SJack F Vogel * 34054dab5c37SJack F Vogel * Clocks in one byte data via I2C data/clock 34064dab5c37SJack F Vogel **/ 34074dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data) 34084dab5c37SJack F Vogel { 34094dab5c37SJack F Vogel s32 i; 34104dab5c37SJack F Vogel bool bit = 0; 34114dab5c37SJack F Vogel 34124dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_byte"); 34134dab5c37SJack F Vogel 34144dab5c37SJack F Vogel *data = 0; 34154dab5c37SJack F Vogel for (i = 7; i >= 0; i--) { 34164dab5c37SJack F Vogel e1000_clock_in_i2c_bit(hw, &bit); 34174dab5c37SJack F Vogel *data |= bit << i; 34184dab5c37SJack F Vogel } 34194dab5c37SJack F Vogel 34204dab5c37SJack F Vogel return E1000_SUCCESS; 34214dab5c37SJack F Vogel } 34224dab5c37SJack F Vogel 34234dab5c37SJack F Vogel /** 34244dab5c37SJack F Vogel * e1000_clock_out_i2c_byte - Clocks out one byte via I2C 34254dab5c37SJack F Vogel * @hw: pointer to hardware structure 34264dab5c37SJack F Vogel * @data: data byte clocked out 34274dab5c37SJack F Vogel * 34284dab5c37SJack F Vogel * Clocks out one byte data via I2C data/clock 34294dab5c37SJack F Vogel **/ 34304dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data) 34314dab5c37SJack F Vogel { 34324dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 34334dab5c37SJack F Vogel s32 i; 34344dab5c37SJack F Vogel u32 i2cctl; 34354dab5c37SJack F Vogel bool bit = 0; 34364dab5c37SJack F Vogel 34374dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_byte"); 34384dab5c37SJack F Vogel 34394dab5c37SJack F Vogel for (i = 7; i >= 0; i--) { 34404dab5c37SJack F Vogel bit = (data >> i) & 0x1; 34414dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, bit); 34424dab5c37SJack F Vogel 34434dab5c37SJack F Vogel if (status != E1000_SUCCESS) 34444dab5c37SJack F Vogel break; 34454dab5c37SJack F Vogel } 34464dab5c37SJack F Vogel 34474dab5c37SJack F Vogel /* Release SDA line (set high) */ 34484dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 34494dab5c37SJack F Vogel 34504dab5c37SJack F Vogel i2cctl |= E1000_I2C_DATA_OE_N; 34514dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl); 34524dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 34534dab5c37SJack F Vogel 34544dab5c37SJack F Vogel return status; 34554dab5c37SJack F Vogel } 34564dab5c37SJack F Vogel 34574dab5c37SJack F Vogel /** 34584dab5c37SJack F Vogel * e1000_get_i2c_ack - Polls for I2C ACK 34594dab5c37SJack F Vogel * @hw: pointer to hardware structure 34604dab5c37SJack F Vogel * 34614dab5c37SJack F Vogel * Clocks in/out one bit via I2C data/clock 34624dab5c37SJack F Vogel **/ 34634dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw) 34644dab5c37SJack F Vogel { 34654dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 34664dab5c37SJack F Vogel u32 i = 0; 34674dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 34684dab5c37SJack F Vogel u32 timeout = 10; 3469ab5d0362SJack F Vogel bool ack = TRUE; 34704dab5c37SJack F Vogel 34714dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_ack"); 34724dab5c37SJack F Vogel 34734dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 34744dab5c37SJack F Vogel 34754dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 34764dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 34774dab5c37SJack F Vogel 34784dab5c37SJack F Vogel /* Wait until SCL returns high */ 34794dab5c37SJack F Vogel for (i = 0; i < timeout; i++) { 34804dab5c37SJack F Vogel usec_delay(1); 34814dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 34824dab5c37SJack F Vogel if (i2cctl & E1000_I2C_CLK_IN) 34834dab5c37SJack F Vogel break; 34844dab5c37SJack F Vogel } 34854dab5c37SJack F Vogel if (!(i2cctl & E1000_I2C_CLK_IN)) 34864dab5c37SJack F Vogel return E1000_ERR_I2C; 34874dab5c37SJack F Vogel 34884dab5c37SJack F Vogel ack = e1000_get_i2c_data(&i2cctl); 3489ab5d0362SJack F Vogel if (ack) { 34904dab5c37SJack F Vogel DEBUGOUT("I2C ack was not received.\n"); 34914dab5c37SJack F Vogel status = E1000_ERR_I2C; 34924dab5c37SJack F Vogel } 34934dab5c37SJack F Vogel 34944dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 34954dab5c37SJack F Vogel 34964dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 34974dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 34984dab5c37SJack F Vogel 34994dab5c37SJack F Vogel return status; 35004dab5c37SJack F Vogel } 35014dab5c37SJack F Vogel 35024dab5c37SJack F Vogel /** 35034dab5c37SJack F Vogel * e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock 35044dab5c37SJack F Vogel * @hw: pointer to hardware structure 35054dab5c37SJack F Vogel * @data: read data value 35064dab5c37SJack F Vogel * 35074dab5c37SJack F Vogel * Clocks in one bit via I2C data/clock 35084dab5c37SJack F Vogel **/ 35094dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data) 35104dab5c37SJack F Vogel { 35114dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 35124dab5c37SJack F Vogel 35134dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_bit"); 35144dab5c37SJack F Vogel 35154dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 35164dab5c37SJack F Vogel 35174dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 35184dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 35194dab5c37SJack F Vogel 35204dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 35214dab5c37SJack F Vogel *data = e1000_get_i2c_data(&i2cctl); 35224dab5c37SJack F Vogel 35234dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 35244dab5c37SJack F Vogel 35254dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 35264dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 35274dab5c37SJack F Vogel 35284dab5c37SJack F Vogel return E1000_SUCCESS; 35294dab5c37SJack F Vogel } 35304dab5c37SJack F Vogel 35314dab5c37SJack F Vogel /** 35324dab5c37SJack F Vogel * e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock 35334dab5c37SJack F Vogel * @hw: pointer to hardware structure 35344dab5c37SJack F Vogel * @data: data value to write 35354dab5c37SJack F Vogel * 35364dab5c37SJack F Vogel * Clocks out one bit via I2C data/clock 35374dab5c37SJack F Vogel **/ 35384dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data) 35394dab5c37SJack F Vogel { 35404dab5c37SJack F Vogel s32 status; 35414dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 35424dab5c37SJack F Vogel 35434dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_bit"); 35444dab5c37SJack F Vogel 35454dab5c37SJack F Vogel status = e1000_set_i2c_data(hw, &i2cctl, data); 35464dab5c37SJack F Vogel if (status == E1000_SUCCESS) { 35474dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 35484dab5c37SJack F Vogel 35494dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 35504dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 35514dab5c37SJack F Vogel 35524dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 35534dab5c37SJack F Vogel 35544dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us. 35554dab5c37SJack F Vogel * This also takes care of the data hold time. 35564dab5c37SJack F Vogel */ 35574dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 35584dab5c37SJack F Vogel } else { 35594dab5c37SJack F Vogel status = E1000_ERR_I2C; 35604dab5c37SJack F Vogel DEBUGOUT1("I2C data was not set to %X\n", data); 35614dab5c37SJack F Vogel } 35624dab5c37SJack F Vogel 35634dab5c37SJack F Vogel return status; 35644dab5c37SJack F Vogel } 35654dab5c37SJack F Vogel /** 35664dab5c37SJack F Vogel * e1000_raise_i2c_clk - Raises the I2C SCL clock 35674dab5c37SJack F Vogel * @hw: pointer to hardware structure 35684dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 35694dab5c37SJack F Vogel * 35704dab5c37SJack F Vogel * Raises the I2C clock line '0'->'1' 35714dab5c37SJack F Vogel **/ 35724dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) 35734dab5c37SJack F Vogel { 35744dab5c37SJack F Vogel DEBUGFUNC("e1000_raise_i2c_clk"); 35754dab5c37SJack F Vogel 35764dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OUT; 35774dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N; 35784dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 35794dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 35804dab5c37SJack F Vogel 35814dab5c37SJack F Vogel /* SCL rise time (1000ns) */ 35824dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE); 35834dab5c37SJack F Vogel } 35844dab5c37SJack F Vogel 35854dab5c37SJack F Vogel /** 35864dab5c37SJack F Vogel * e1000_lower_i2c_clk - Lowers the I2C SCL clock 35874dab5c37SJack F Vogel * @hw: pointer to hardware structure 35884dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 35894dab5c37SJack F Vogel * 35904dab5c37SJack F Vogel * Lowers the I2C clock line '1'->'0' 35914dab5c37SJack F Vogel **/ 35924dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) 35934dab5c37SJack F Vogel { 35944dab5c37SJack F Vogel 35954dab5c37SJack F Vogel DEBUGFUNC("e1000_lower_i2c_clk"); 35964dab5c37SJack F Vogel 35974dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OUT; 35984dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N; 35994dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 36004dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 36014dab5c37SJack F Vogel 36024dab5c37SJack F Vogel /* SCL fall time (300ns) */ 36034dab5c37SJack F Vogel usec_delay(E1000_I2C_T_FALL); 36044dab5c37SJack F Vogel } 36054dab5c37SJack F Vogel 36064dab5c37SJack F Vogel /** 36074dab5c37SJack F Vogel * e1000_set_i2c_data - Sets the I2C data bit 36084dab5c37SJack F Vogel * @hw: pointer to hardware structure 36094dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 36104dab5c37SJack F Vogel * @data: I2C data value (0 or 1) to set 36114dab5c37SJack F Vogel * 36124dab5c37SJack F Vogel * Sets the I2C data bit 36134dab5c37SJack F Vogel **/ 36144dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data) 36154dab5c37SJack F Vogel { 36164dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 36174dab5c37SJack F Vogel 36184dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_data"); 36194dab5c37SJack F Vogel 36204dab5c37SJack F Vogel if (data) 36214dab5c37SJack F Vogel *i2cctl |= E1000_I2C_DATA_OUT; 36224dab5c37SJack F Vogel else 36234dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OUT; 36244dab5c37SJack F Vogel 36254dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OE_N; 36264dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OE_N; 36274dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 36284dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 36294dab5c37SJack F Vogel 36304dab5c37SJack F Vogel /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ 36314dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA); 36324dab5c37SJack F Vogel 36334dab5c37SJack F Vogel *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 36344dab5c37SJack F Vogel if (data != e1000_get_i2c_data(i2cctl)) { 36354dab5c37SJack F Vogel status = E1000_ERR_I2C; 36364dab5c37SJack F Vogel DEBUGOUT1("Error - I2C data was not set to %X.\n", data); 36374dab5c37SJack F Vogel } 36384dab5c37SJack F Vogel 36394dab5c37SJack F Vogel return status; 36404dab5c37SJack F Vogel } 36414dab5c37SJack F Vogel 36424dab5c37SJack F Vogel /** 36434dab5c37SJack F Vogel * e1000_get_i2c_data - Reads the I2C SDA data bit 36444dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 36454dab5c37SJack F Vogel * 36464dab5c37SJack F Vogel * Returns the I2C data bit value 36474dab5c37SJack F Vogel **/ 36484dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl) 36494dab5c37SJack F Vogel { 36504dab5c37SJack F Vogel bool data; 36514dab5c37SJack F Vogel 36524dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_data"); 36534dab5c37SJack F Vogel 36544dab5c37SJack F Vogel if (*i2cctl & E1000_I2C_DATA_IN) 36554dab5c37SJack F Vogel data = 1; 36564dab5c37SJack F Vogel else 36574dab5c37SJack F Vogel data = 0; 36584dab5c37SJack F Vogel 36594dab5c37SJack F Vogel return data; 36604dab5c37SJack F Vogel } 36614dab5c37SJack F Vogel 36624dab5c37SJack F Vogel /** 36634dab5c37SJack F Vogel * e1000_i2c_bus_clear - Clears the I2C bus 36644dab5c37SJack F Vogel * @hw: pointer to hardware structure 36654dab5c37SJack F Vogel * 36664dab5c37SJack F Vogel * Clears the I2C bus by sending nine clock pulses. 36674dab5c37SJack F Vogel * Used when data line is stuck low. 36684dab5c37SJack F Vogel **/ 36694dab5c37SJack F Vogel void e1000_i2c_bus_clear(struct e1000_hw *hw) 36704dab5c37SJack F Vogel { 36714dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 36724dab5c37SJack F Vogel u32 i; 36734dab5c37SJack F Vogel 36744dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_bus_clear"); 36754dab5c37SJack F Vogel 36764dab5c37SJack F Vogel e1000_i2c_start(hw); 36774dab5c37SJack F Vogel 36784dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 36794dab5c37SJack F Vogel 36804dab5c37SJack F Vogel for (i = 0; i < 9; i++) { 36814dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 36824dab5c37SJack F Vogel 36834dab5c37SJack F Vogel /* Min high period of clock is 4us */ 36844dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 36854dab5c37SJack F Vogel 36864dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 36874dab5c37SJack F Vogel 36884dab5c37SJack F Vogel /* Min low period of clock is 4.7us*/ 36894dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 36904dab5c37SJack F Vogel } 36914dab5c37SJack F Vogel 36924dab5c37SJack F Vogel e1000_i2c_start(hw); 36934dab5c37SJack F Vogel 36944dab5c37SJack F Vogel /* Put the i2c bus back to default state */ 36954dab5c37SJack F Vogel e1000_i2c_stop(hw); 36964dab5c37SJack F Vogel } 36974dab5c37SJack F Vogel 3698