18cfa0ad2SJack F Vogel /****************************************************************************** 28cfa0ad2SJack F Vogel 3*ab5d0362SJack F Vogel Copyright (c) 2001-2012, Intel Corporation 48cfa0ad2SJack F Vogel All rights reserved. 58cfa0ad2SJack F Vogel 68cfa0ad2SJack F Vogel Redistribution and use in source and binary forms, with or without 78cfa0ad2SJack F Vogel modification, are permitted provided that the following conditions are met: 88cfa0ad2SJack F Vogel 98cfa0ad2SJack F Vogel 1. Redistributions of source code must retain the above copyright notice, 108cfa0ad2SJack F Vogel this list of conditions and the following disclaimer. 118cfa0ad2SJack F Vogel 128cfa0ad2SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright 138cfa0ad2SJack F Vogel notice, this list of conditions and the following disclaimer in the 148cfa0ad2SJack F Vogel documentation and/or other materials provided with the distribution. 158cfa0ad2SJack F Vogel 168cfa0ad2SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its 178cfa0ad2SJack F Vogel contributors may be used to endorse or promote products derived from 188cfa0ad2SJack F Vogel this software without specific prior written permission. 198cfa0ad2SJack F Vogel 208cfa0ad2SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 218cfa0ad2SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 228cfa0ad2SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 238cfa0ad2SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 248cfa0ad2SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 258cfa0ad2SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 268cfa0ad2SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 278cfa0ad2SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 288cfa0ad2SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 298cfa0ad2SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 308cfa0ad2SJack F Vogel POSSIBILITY OF SUCH DAMAGE. 318cfa0ad2SJack F Vogel 328cfa0ad2SJack F Vogel ******************************************************************************/ 338cfa0ad2SJack F Vogel /*$FreeBSD$*/ 348cfa0ad2SJack F Vogel 35daf9197cSJack F Vogel /* 36daf9197cSJack F Vogel * 82575EB Gigabit Network Connection 37daf9197cSJack F Vogel * 82575EB Gigabit Backplane Connection 38daf9197cSJack F Vogel * 82575GB Gigabit Network Connection 39daf9197cSJack F Vogel * 82576 Gigabit Network Connection 409d81738fSJack F Vogel * 82576 Quad Port Gigabit Mezzanine Adapter 41*ab5d0362SJack F Vogel * 82580 Gigabit Network Connection 42*ab5d0362SJack F Vogel * I350 Gigabit Network Connection 438cfa0ad2SJack F Vogel */ 448cfa0ad2SJack F Vogel 458cfa0ad2SJack F Vogel #include "e1000_api.h" 46*ab5d0362SJack F Vogel #include "e1000_i210.h" 478cfa0ad2SJack F Vogel 488cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw); 498cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82575(struct e1000_hw *hw); 508cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_82575(struct e1000_hw *hw); 518cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw); 528cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw); 538cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw); 548cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw); 558cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw); 568cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, 578cfa0ad2SJack F Vogel u16 *duplex); 588cfa0ad2SJack F Vogel static s32 e1000_init_hw_82575(struct e1000_hw *hw); 598cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw); 608cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 618cfa0ad2SJack F Vogel u16 *data); 628cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw); 634edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw); 644edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, 654edd8523SJack F Vogel u32 offset, u16 *data); 664edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, 674edd8523SJack F Vogel u32 offset, u16 data); 68f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, 69f0ecc46dSJack F Vogel bool active); 70f0ecc46dSJack F Vogel static s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, 71f0ecc46dSJack F Vogel bool active); 728cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, 738cfa0ad2SJack F Vogel bool active); 748cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw); 754edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw); 764dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw); 774dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw); 788cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data); 798cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, 808cfa0ad2SJack F Vogel u32 offset, u16 data); 818cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw); 828cfa0ad2SJack F Vogel static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask); 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 void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask); 878cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw); 888cfa0ad2SJack F Vogel static s32 e1000_reset_init_script_82575(struct e1000_hw *hw); 898cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw); 90a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw); 918cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw); 924edd8523SJack F Vogel static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw); 93a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw); 949d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw); 957d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw); 96f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw); 97f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw); 98f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, 99f0ecc46dSJack F Vogel u16 offset); 100f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, 101f0ecc46dSJack F Vogel u16 offset); 102f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw); 103f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw); 1044dab5c37SJack F Vogel static void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value); 1054dab5c37SJack F Vogel static void e1000_clear_vfta_i350(struct e1000_hw *hw); 1068cfa0ad2SJack F Vogel 1074dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw); 1084dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw); 1094dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data); 1104dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data); 1114dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw); 1124dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data); 1134dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data); 1144dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); 1154dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl); 1164dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data); 1174dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl); 1184dab5c37SJack F Vogel 1194dab5c37SJack F Vogel static const u16 e1000_82580_rxpbs_table[] = { 1204dab5c37SJack F Vogel 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 }; 1214edd8523SJack F Vogel #define E1000_82580_RXPBS_TABLE_SIZE \ 1224edd8523SJack F Vogel (sizeof(e1000_82580_rxpbs_table)/sizeof(u16)) 1234edd8523SJack F Vogel 1247d9119bdSJack F Vogel 1257d9119bdSJack F Vogel /** 1267d9119bdSJack F Vogel * e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO 1277d9119bdSJack F Vogel * @hw: pointer to the HW structure 1287d9119bdSJack F Vogel * 1297d9119bdSJack F Vogel * Called to determine if the I2C pins are being used for I2C or as an 1307d9119bdSJack F Vogel * external MDIO interface since the two options are mutually exclusive. 1317d9119bdSJack F Vogel **/ 1327d9119bdSJack F Vogel static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw) 1337d9119bdSJack F Vogel { 1347d9119bdSJack F Vogel u32 reg = 0; 1357d9119bdSJack F Vogel bool ext_mdio = FALSE; 1367d9119bdSJack F Vogel 1377d9119bdSJack F Vogel DEBUGFUNC("e1000_sgmii_uses_mdio_82575"); 1387d9119bdSJack F Vogel 1397d9119bdSJack F Vogel switch (hw->mac.type) { 1407d9119bdSJack F Vogel case e1000_82575: 1417d9119bdSJack F Vogel case e1000_82576: 1427d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDIC); 1437d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDIC_DEST); 1447d9119bdSJack F Vogel break; 1457d9119bdSJack F Vogel case e1000_82580: 146f0ecc46dSJack F Vogel case e1000_i350: 1477d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDICNFG); 1487d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); 1497d9119bdSJack F Vogel break; 1507d9119bdSJack F Vogel default: 1517d9119bdSJack F Vogel break; 1527d9119bdSJack F Vogel } 1537d9119bdSJack F Vogel return ext_mdio; 1547d9119bdSJack F Vogel } 1557d9119bdSJack F Vogel 1568cfa0ad2SJack F Vogel /** 1578cfa0ad2SJack F Vogel * e1000_init_phy_params_82575 - Init PHY func ptrs. 1588cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 1598cfa0ad2SJack F Vogel **/ 1608cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) 1618cfa0ad2SJack F Vogel { 1628cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 1638cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 1647d9119bdSJack F Vogel u32 ctrl_ext; 1658cfa0ad2SJack F Vogel 1668cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_82575"); 1678cfa0ad2SJack F Vogel 168*ab5d0362SJack F Vogel phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic; 169*ab5d0362SJack F Vogel phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic; 170*ab5d0362SJack F Vogel 1718cfa0ad2SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) { 1728cfa0ad2SJack F Vogel phy->type = e1000_phy_none; 1738cfa0ad2SJack F Vogel goto out; 1744edd8523SJack F Vogel } 1754edd8523SJack F Vogel 1768cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper; 1778cfa0ad2SJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper_82575; 1788cfa0ad2SJack F Vogel 1798cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 1808cfa0ad2SJack F Vogel phy->reset_delay_us = 100; 1818cfa0ad2SJack F Vogel 1828cfa0ad2SJack F Vogel phy->ops.acquire = e1000_acquire_phy_82575; 1838cfa0ad2SJack F Vogel phy->ops.check_reset_block = e1000_check_reset_block_generic; 1848cfa0ad2SJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic; 1858cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_82575; 1868cfa0ad2SJack F Vogel phy->ops.release = e1000_release_phy_82575; 1878cfa0ad2SJack F Vogel 1887d9119bdSJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 1897d9119bdSJack F Vogel 1908cfa0ad2SJack F Vogel if (e1000_sgmii_active_82575(hw)) { 1918cfa0ad2SJack F Vogel phy->ops.reset = e1000_phy_hw_reset_sgmii_82575; 1927d9119bdSJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA; 1937d9119bdSJack F Vogel } else { 1947d9119bdSJack F Vogel phy->ops.reset = e1000_phy_hw_reset_generic; 1957d9119bdSJack F Vogel ctrl_ext &= ~E1000_CTRL_I2C_ENA; 1967d9119bdSJack F Vogel } 1977d9119bdSJack F Vogel 1987d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 1997d9119bdSJack F Vogel e1000_reset_mdicnfg_82580(hw); 2007d9119bdSJack F Vogel 2017d9119bdSJack F Vogel if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) { 2028cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; 2038cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; 204*ab5d0362SJack F Vogel } else { 205*ab5d0362SJack F Vogel switch (hw->mac.type) { 206*ab5d0362SJack F Vogel case e1000_82580: 207*ab5d0362SJack F Vogel case e1000_i350: 2084edd8523SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_82580; 2094edd8523SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_82580; 210*ab5d0362SJack F Vogel break; 211*ab5d0362SJack F Vogel case e1000_i210: 212*ab5d0362SJack F Vogel case e1000_i211: 213*ab5d0362SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_gs40g; 214*ab5d0362SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_gs40g; 215*ab5d0362SJack F Vogel break; 216*ab5d0362SJack F Vogel default: 2178cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_igp; 2188cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_igp; 2198cfa0ad2SJack F Vogel } 220*ab5d0362SJack F Vogel } 2218cfa0ad2SJack F Vogel 2228cfa0ad2SJack F Vogel /* Set phy->phy_addr and phy->id. */ 2238cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id_82575(hw); 2248cfa0ad2SJack F Vogel 2258cfa0ad2SJack F Vogel /* Verify phy id and set remaining function pointers */ 2268cfa0ad2SJack F Vogel switch (phy->id) { 227f0ecc46dSJack F Vogel case I347AT4_E_PHY_ID: 228f0ecc46dSJack F Vogel case M88E1112_E_PHY_ID: 2291fd3c44fSJack F Vogel case M88E1340M_E_PHY_ID: 2308cfa0ad2SJack F Vogel case M88E1111_I_PHY_ID: 2318cfa0ad2SJack F Vogel phy->type = e1000_phy_m88; 2328cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 2338cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 234f0ecc46dSJack F Vogel if (phy->id == I347AT4_E_PHY_ID || 2351fd3c44fSJack F Vogel phy->id == M88E1112_E_PHY_ID || 2361fd3c44fSJack F Vogel phy->id == M88E1340M_E_PHY_ID) 2374dab5c37SJack F Vogel phy->ops.get_cable_length = 2384dab5c37SJack F Vogel e1000_get_cable_length_m88_gen2; 239f0ecc46dSJack F Vogel else 2408cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88; 2418cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 2428cfa0ad2SJack F Vogel break; 2438cfa0ad2SJack F Vogel case IGP03E1000_E_PHY_ID: 2448cfa0ad2SJack F Vogel case IGP04E1000_E_PHY_ID: 2458cfa0ad2SJack F Vogel phy->type = e1000_phy_igp_3; 2468cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_igp; 2478cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_igp; 2488cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_igp_2; 2498cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; 2508cfa0ad2SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575; 2518cfa0ad2SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; 2528cfa0ad2SJack F Vogel break; 2534edd8523SJack F Vogel case I82580_I_PHY_ID: 254f0ecc46dSJack F Vogel case I350_I_PHY_ID: 2554edd8523SJack F Vogel phy->type = e1000_phy_82580; 2564edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_82577; 2574dab5c37SJack F Vogel phy->ops.force_speed_duplex = 2584dab5c37SJack F Vogel e1000_phy_force_speed_duplex_82577; 2594edd8523SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_82577; 2604edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_82577; 261f0ecc46dSJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; 262f0ecc46dSJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; 2634edd8523SJack F Vogel break; 264*ab5d0362SJack F Vogel case I210_I_PHY_ID: 265*ab5d0362SJack F Vogel phy->type = e1000_phy_i210; 266*ab5d0362SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 267*ab5d0362SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 268*ab5d0362SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; 269*ab5d0362SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; 270*ab5d0362SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; 271*ab5d0362SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 272*ab5d0362SJack F Vogel break; 2738cfa0ad2SJack F Vogel default: 2748cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 2758cfa0ad2SJack F Vogel goto out; 2768cfa0ad2SJack F Vogel } 2778cfa0ad2SJack F Vogel 2788cfa0ad2SJack F Vogel out: 2798cfa0ad2SJack F Vogel return ret_val; 2808cfa0ad2SJack F Vogel } 2818cfa0ad2SJack F Vogel 2828cfa0ad2SJack F Vogel /** 2838cfa0ad2SJack F Vogel * e1000_init_nvm_params_82575 - Init NVM func ptrs. 2848cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 2858cfa0ad2SJack F Vogel **/ 2861fd3c44fSJack F Vogel s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) 2878cfa0ad2SJack F Vogel { 2888cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 2898cfa0ad2SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 2908cfa0ad2SJack F Vogel u16 size; 2918cfa0ad2SJack F Vogel 2928cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_82575"); 2938cfa0ad2SJack F Vogel 294f0ecc46dSJack F Vogel size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> 295f0ecc46dSJack F Vogel E1000_EECD_SIZE_EX_SHIFT); 296f0ecc46dSJack F Vogel /* 297f0ecc46dSJack F Vogel * Added to a constant, "size" becomes the left-shift value 298f0ecc46dSJack F Vogel * for setting word_size. 299f0ecc46dSJack F Vogel */ 300f0ecc46dSJack F Vogel size += NVM_WORD_SIZE_BASE_SHIFT; 301f0ecc46dSJack F Vogel 3024dab5c37SJack F Vogel /* Just in case size is out of range, cap it to the largest 3034dab5c37SJack F Vogel * EEPROM size supported 3044dab5c37SJack F Vogel */ 3054dab5c37SJack F Vogel if (size > 15) 3064dab5c37SJack F Vogel size = 15; 3074dab5c37SJack F Vogel 308f0ecc46dSJack F Vogel nvm->word_size = 1 << size; 309*ab5d0362SJack F Vogel if (hw->mac.type < e1000_i210) { 3108cfa0ad2SJack F Vogel nvm->opcode_bits = 8; 3118cfa0ad2SJack F Vogel nvm->delay_usec = 1; 312*ab5d0362SJack F Vogel 3138cfa0ad2SJack F Vogel switch (nvm->override) { 3148cfa0ad2SJack F Vogel case e1000_nvm_override_spi_large: 3158cfa0ad2SJack F Vogel nvm->page_size = 32; 3168cfa0ad2SJack F Vogel nvm->address_bits = 16; 3178cfa0ad2SJack F Vogel break; 3188cfa0ad2SJack F Vogel case e1000_nvm_override_spi_small: 3198cfa0ad2SJack F Vogel nvm->page_size = 8; 3208cfa0ad2SJack F Vogel nvm->address_bits = 8; 3218cfa0ad2SJack F Vogel break; 3228cfa0ad2SJack F Vogel default: 3238cfa0ad2SJack F Vogel nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; 324*ab5d0362SJack F Vogel nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 325*ab5d0362SJack F Vogel 16 : 8; 3268cfa0ad2SJack F Vogel break; 3278cfa0ad2SJack F Vogel } 3281fd3c44fSJack F Vogel if (nvm->word_size == (1 << 15)) 329f0ecc46dSJack F Vogel nvm->page_size = 128; 3308cfa0ad2SJack F Vogel 331*ab5d0362SJack F Vogel nvm->type = e1000_nvm_eeprom_spi; 332*ab5d0362SJack F Vogel } else { 333*ab5d0362SJack F Vogel nvm->type = e1000_nvm_flash_hw; 334*ab5d0362SJack F Vogel } 3358cfa0ad2SJack F Vogel /* Function Pointers */ 3368cfa0ad2SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_82575; 3378cfa0ad2SJack F Vogel nvm->ops.release = e1000_release_nvm_82575; 3381fd3c44fSJack F Vogel if (nvm->word_size < (1 << 15)) 3391fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_eerd; 3401fd3c44fSJack F Vogel else 3411fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_spi; 3421fd3c44fSJack F Vogel 3431fd3c44fSJack F Vogel nvm->ops.write = e1000_write_nvm_spi; 3441fd3c44fSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_generic; 3451fd3c44fSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_generic; 3468cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_82575; 3471fd3c44fSJack F Vogel 348*ab5d0362SJack F Vogel /* override generic family function pointers for specific descendants */ 349f0ecc46dSJack F Vogel switch (hw->mac.type) { 350f0ecc46dSJack F Vogel case e1000_82580: 351f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_82580; 352f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_82580; 353f0ecc46dSJack F Vogel break; 354f0ecc46dSJack F Vogel case e1000_i350: 355f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_i350; 356f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_i350; 357f0ecc46dSJack F Vogel break; 358f0ecc46dSJack F Vogel default: 3591fd3c44fSJack F Vogel break; 360f0ecc46dSJack F Vogel } 3618cfa0ad2SJack F Vogel 3628cfa0ad2SJack F Vogel return E1000_SUCCESS; 3638cfa0ad2SJack F Vogel } 3648cfa0ad2SJack F Vogel 3658cfa0ad2SJack F Vogel /** 3668cfa0ad2SJack F Vogel * e1000_init_mac_params_82575 - Init MAC func ptrs. 3678cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3688cfa0ad2SJack F Vogel **/ 3698cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) 3708cfa0ad2SJack F Vogel { 3718cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 372daf9197cSJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 3738cfa0ad2SJack F Vogel 3748cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_mac_params_82575"); 3758cfa0ad2SJack F Vogel 3764dab5c37SJack F Vogel /* Derives media type */ 3774dab5c37SJack F Vogel e1000_get_media_type_82575(hw); 3788cfa0ad2SJack F Vogel /* Set mta register count */ 3798cfa0ad2SJack F Vogel mac->mta_reg_count = 128; 3804edd8523SJack F Vogel /* Set uta register count */ 3814edd8523SJack F Vogel mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; 3828cfa0ad2SJack F Vogel /* Set rar entry count */ 3838cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82575; 3848cfa0ad2SJack F Vogel if (mac->type == e1000_82576) 3858cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82576; 386a69ed8dfSJack F Vogel if (mac->type == e1000_82580) 3874edd8523SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82580; 388f0ecc46dSJack F Vogel if (mac->type == e1000_i350) { 389f0ecc46dSJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_I350; 390f0ecc46dSJack F Vogel /* Enable EEE default settings for i350 */ 391f0ecc46dSJack F Vogel dev_spec->eee_disable = FALSE; 392f0ecc46dSJack F Vogel } 393f0ecc46dSJack F Vogel 3948cfa0ad2SJack F Vogel /* Set if part includes ASF firmware */ 3958cfa0ad2SJack F Vogel mac->asf_firmware_present = TRUE; 3968ec87fc5SJack F Vogel /* FWSM register */ 3978ec87fc5SJack F Vogel mac->has_fwsm = TRUE; 3988ec87fc5SJack F Vogel /* ARC supported; valid only if manageability features are enabled. */ 3998cfa0ad2SJack F Vogel mac->arc_subsystem_valid = 400*ab5d0362SJack F Vogel !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); 4018cfa0ad2SJack F Vogel 4028cfa0ad2SJack F Vogel /* Function pointers */ 4038cfa0ad2SJack F Vogel 4048cfa0ad2SJack F Vogel /* bus type/speed/width */ 4058cfa0ad2SJack F Vogel mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; 4068cfa0ad2SJack F Vogel /* reset */ 407a69ed8dfSJack F Vogel if (mac->type >= e1000_82580) 4084edd8523SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82580; 4094edd8523SJack F Vogel else 4108cfa0ad2SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82575; 4118cfa0ad2SJack F Vogel /* hw initialization */ 4128cfa0ad2SJack F Vogel mac->ops.init_hw = e1000_init_hw_82575; 4138cfa0ad2SJack F Vogel /* link setup */ 4148cfa0ad2SJack F Vogel mac->ops.setup_link = e1000_setup_link_generic; 4158cfa0ad2SJack F Vogel /* physical interface link setup */ 4168cfa0ad2SJack F Vogel mac->ops.setup_physical_interface = 4178cfa0ad2SJack F Vogel (hw->phy.media_type == e1000_media_type_copper) 4184dab5c37SJack F Vogel ? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575; 4198cfa0ad2SJack F Vogel /* physical interface shutdown */ 4204edd8523SJack F Vogel mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575; 421a69ed8dfSJack F Vogel /* physical interface power up */ 422a69ed8dfSJack F Vogel mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; 4238cfa0ad2SJack F Vogel /* check for link */ 4248cfa0ad2SJack F Vogel mac->ops.check_for_link = e1000_check_for_link_82575; 4258cfa0ad2SJack F Vogel /* read mac address */ 4268cfa0ad2SJack F Vogel mac->ops.read_mac_addr = e1000_read_mac_addr_82575; 427a69ed8dfSJack F Vogel /* configure collision distance */ 428a69ed8dfSJack F Vogel mac->ops.config_collision_dist = e1000_config_collision_dist_82575; 4298cfa0ad2SJack F Vogel /* multicast address update */ 430d035aa2dSJack F Vogel mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; 4314dab5c37SJack F Vogel if (hw->mac.type == e1000_i350) { 4324dab5c37SJack F Vogel /* writing VFTA */ 4334dab5c37SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_i350; 4344dab5c37SJack F Vogel /* clearing VFTA */ 4354dab5c37SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_i350; 4364dab5c37SJack F Vogel } else { 4378cfa0ad2SJack F Vogel /* writing VFTA */ 4388cfa0ad2SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_generic; 4398cfa0ad2SJack F Vogel /* clearing VFTA */ 4408cfa0ad2SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_generic; 4414dab5c37SJack F Vogel } 442d035aa2dSJack F Vogel /* ID LED init */ 443d035aa2dSJack F Vogel mac->ops.id_led_init = e1000_id_led_init_generic; 4448cfa0ad2SJack F Vogel /* blink LED */ 4458cfa0ad2SJack F Vogel mac->ops.blink_led = e1000_blink_led_generic; 4468cfa0ad2SJack F Vogel /* setup LED */ 4478cfa0ad2SJack F Vogel mac->ops.setup_led = e1000_setup_led_generic; 4488cfa0ad2SJack F Vogel /* cleanup LED */ 4498cfa0ad2SJack F Vogel mac->ops.cleanup_led = e1000_cleanup_led_generic; 4508cfa0ad2SJack F Vogel /* turn on/off LED */ 4518cfa0ad2SJack F Vogel mac->ops.led_on = e1000_led_on_generic; 4528cfa0ad2SJack F Vogel mac->ops.led_off = e1000_led_off_generic; 4538cfa0ad2SJack F Vogel /* clear hardware counters */ 4548cfa0ad2SJack F Vogel mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; 4558cfa0ad2SJack F Vogel /* link info */ 4568cfa0ad2SJack F Vogel mac->ops.get_link_up_info = e1000_get_link_up_info_82575; 457*ab5d0362SJack F Vogel /* acquire SW_FW sync */ 458*ab5d0362SJack F Vogel mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575; 459*ab5d0362SJack F Vogel mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575; 460*ab5d0362SJack F Vogel if (mac->type >= e1000_i210) { 461*ab5d0362SJack F Vogel mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210; 462*ab5d0362SJack F Vogel mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210; 463*ab5d0362SJack F Vogel } 4648cfa0ad2SJack F Vogel 4654edd8523SJack F Vogel /* set lan id for port to determine which phy lock to use */ 4664edd8523SJack F Vogel hw->mac.ops.set_lan_id(hw); 4674edd8523SJack F Vogel 468daf9197cSJack F Vogel return E1000_SUCCESS; 4698cfa0ad2SJack F Vogel } 4708cfa0ad2SJack F Vogel 4718cfa0ad2SJack F Vogel /** 4728cfa0ad2SJack F Vogel * e1000_init_function_pointers_82575 - Init func ptrs. 4738cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4748cfa0ad2SJack F Vogel * 475daf9197cSJack F Vogel * Called to initialize all function pointers and parameters. 4768cfa0ad2SJack F Vogel **/ 4778cfa0ad2SJack F Vogel void e1000_init_function_pointers_82575(struct e1000_hw *hw) 4788cfa0ad2SJack F Vogel { 4798cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_82575"); 4808cfa0ad2SJack F Vogel 4818cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_82575; 4828cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_82575; 4838cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_82575; 4847d9119bdSJack F Vogel hw->mbx.ops.init_params = e1000_init_mbx_params_pf; 4858cfa0ad2SJack F Vogel } 4868cfa0ad2SJack F Vogel 4878cfa0ad2SJack F Vogel /** 4888cfa0ad2SJack F Vogel * e1000_acquire_phy_82575 - Acquire rights to access PHY 4898cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4908cfa0ad2SJack F Vogel * 491daf9197cSJack F Vogel * Acquire access rights to the correct PHY. 4928cfa0ad2SJack F Vogel **/ 4938cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) 4948cfa0ad2SJack F Vogel { 4959d81738fSJack F Vogel u16 mask = E1000_SWFW_PHY0_SM; 4968cfa0ad2SJack F Vogel 4978cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_phy_82575"); 4988cfa0ad2SJack F Vogel 4999d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 5009d81738fSJack F Vogel mask = E1000_SWFW_PHY1_SM; 5014edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 5024edd8523SJack F Vogel mask = E1000_SWFW_PHY2_SM; 5034edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 5044edd8523SJack F Vogel mask = E1000_SWFW_PHY3_SM; 5058cfa0ad2SJack F Vogel 506*ab5d0362SJack F Vogel return hw->mac.ops.acquire_swfw_sync(hw, mask); 5078cfa0ad2SJack F Vogel } 5088cfa0ad2SJack F Vogel 5098cfa0ad2SJack F Vogel /** 5108cfa0ad2SJack F Vogel * e1000_release_phy_82575 - Release rights to access PHY 5118cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5128cfa0ad2SJack F Vogel * 513daf9197cSJack F Vogel * A wrapper to release access rights to the correct PHY. 5148cfa0ad2SJack F Vogel **/ 5158cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw) 5168cfa0ad2SJack F Vogel { 5179d81738fSJack F Vogel u16 mask = E1000_SWFW_PHY0_SM; 5188cfa0ad2SJack F Vogel 5198cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_phy_82575"); 5208cfa0ad2SJack F Vogel 5219d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 5229d81738fSJack F Vogel mask = E1000_SWFW_PHY1_SM; 5234edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 5244edd8523SJack F Vogel mask = E1000_SWFW_PHY2_SM; 5254edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 5264edd8523SJack F Vogel mask = E1000_SWFW_PHY3_SM; 5279d81738fSJack F Vogel 528*ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, mask); 5298cfa0ad2SJack F Vogel } 5308cfa0ad2SJack F Vogel 5318cfa0ad2SJack F Vogel /** 5328cfa0ad2SJack F Vogel * e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii 5338cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5348cfa0ad2SJack F Vogel * @offset: register offset to be read 5358cfa0ad2SJack F Vogel * @data: pointer to the read data 5368cfa0ad2SJack F Vogel * 5378cfa0ad2SJack F Vogel * Reads the PHY register at offset using the serial gigabit media independent 5388cfa0ad2SJack F Vogel * interface and stores the retrieved information in data. 5398cfa0ad2SJack F Vogel **/ 5408cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 5418cfa0ad2SJack F Vogel u16 *data) 5428cfa0ad2SJack F Vogel { 5434edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM; 5448cfa0ad2SJack F Vogel 5458cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_sgmii_82575"); 5468cfa0ad2SJack F Vogel 5478cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 5488cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %u is out of range\n", offset); 5494edd8523SJack F Vogel goto out; 5508cfa0ad2SJack F Vogel } 5518cfa0ad2SJack F Vogel 5524edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 5534edd8523SJack F Vogel if (ret_val) 5544edd8523SJack F Vogel goto out; 5558cfa0ad2SJack F Vogel 5564edd8523SJack F Vogel ret_val = e1000_read_phy_reg_i2c(hw, offset, data); 5578cfa0ad2SJack F Vogel 5584edd8523SJack F Vogel hw->phy.ops.release(hw); 5598cfa0ad2SJack F Vogel 5604edd8523SJack F Vogel out: 5614edd8523SJack F Vogel return ret_val; 5628cfa0ad2SJack F Vogel } 5638cfa0ad2SJack F Vogel 5648cfa0ad2SJack F Vogel /** 5658cfa0ad2SJack F Vogel * e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii 5668cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5678cfa0ad2SJack F Vogel * @offset: register offset to write to 5688cfa0ad2SJack F Vogel * @data: data to write at register offset 5698cfa0ad2SJack F Vogel * 5708cfa0ad2SJack F Vogel * Writes the data to PHY register at the offset using the serial gigabit 5718cfa0ad2SJack F Vogel * media independent interface. 5728cfa0ad2SJack F Vogel **/ 5738cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 5748cfa0ad2SJack F Vogel u16 data) 5758cfa0ad2SJack F Vogel { 5764edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM; 5778cfa0ad2SJack F Vogel 5788cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_sgmii_82575"); 5798cfa0ad2SJack F Vogel 5808cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 5818cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %d is out of range\n", offset); 5824edd8523SJack F Vogel goto out; 5838cfa0ad2SJack F Vogel } 5848cfa0ad2SJack F Vogel 5854edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 5864edd8523SJack F Vogel if (ret_val) 5874edd8523SJack F Vogel goto out; 5888cfa0ad2SJack F Vogel 5894edd8523SJack F Vogel ret_val = e1000_write_phy_reg_i2c(hw, offset, data); 5908cfa0ad2SJack F Vogel 5914edd8523SJack F Vogel hw->phy.ops.release(hw); 5928cfa0ad2SJack F Vogel 5934edd8523SJack F Vogel out: 5944edd8523SJack F Vogel return ret_val; 5958cfa0ad2SJack F Vogel } 5968cfa0ad2SJack F Vogel 5978cfa0ad2SJack F Vogel /** 5988cfa0ad2SJack F Vogel * e1000_get_phy_id_82575 - Retrieve PHY addr and id 5998cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6008cfa0ad2SJack F Vogel * 6018cfa0ad2SJack F Vogel * Retrieves the PHY address and ID for both PHY's which do and do not use 6028cfa0ad2SJack F Vogel * sgmi interface. 6038cfa0ad2SJack F Vogel **/ 6048cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) 6058cfa0ad2SJack F Vogel { 6068cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 6078cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 6088cfa0ad2SJack F Vogel u16 phy_id; 6094edd8523SJack F Vogel u32 ctrl_ext; 6107d9119bdSJack F Vogel u32 mdic; 6118cfa0ad2SJack F Vogel 6128cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_phy_id_82575"); 6138cfa0ad2SJack F Vogel 6148cfa0ad2SJack F Vogel /* 6158cfa0ad2SJack F Vogel * For SGMII PHYs, we try the list of possible addresses until 6168cfa0ad2SJack F Vogel * we find one that works. For non-SGMII PHYs 6178cfa0ad2SJack F Vogel * (e.g. integrated copper PHYs), an address of 1 should 6188cfa0ad2SJack F Vogel * work. The result of this function should mean phy->phy_addr 6198cfa0ad2SJack F Vogel * and phy->id are set correctly. 6208cfa0ad2SJack F Vogel */ 6214edd8523SJack F Vogel if (!e1000_sgmii_active_82575(hw)) { 6228cfa0ad2SJack F Vogel phy->addr = 1; 6238cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw); 6248cfa0ad2SJack F Vogel goto out; 6258cfa0ad2SJack F Vogel } 6268cfa0ad2SJack F Vogel 6277d9119bdSJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) { 6287d9119bdSJack F Vogel switch (hw->mac.type) { 6297d9119bdSJack F Vogel case e1000_82575: 6307d9119bdSJack F Vogel case e1000_82576: 6317d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDIC); 6327d9119bdSJack F Vogel mdic &= E1000_MDIC_PHY_MASK; 6337d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDIC_PHY_SHIFT; 6347d9119bdSJack F Vogel break; 6357d9119bdSJack F Vogel case e1000_82580: 636f0ecc46dSJack F Vogel case e1000_i350: 6377d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDICNFG); 6387d9119bdSJack F Vogel mdic &= E1000_MDICNFG_PHY_MASK; 6397d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; 6407d9119bdSJack F Vogel break; 6417d9119bdSJack F Vogel default: 6427d9119bdSJack F Vogel ret_val = -E1000_ERR_PHY; 6437d9119bdSJack F Vogel goto out; 6447d9119bdSJack F Vogel break; 6457d9119bdSJack F Vogel } 6467d9119bdSJack F Vogel ret_val = e1000_get_phy_id(hw); 6477d9119bdSJack F Vogel goto out; 6487d9119bdSJack F Vogel } 6497d9119bdSJack F Vogel 6504edd8523SJack F Vogel /* Power on sgmii phy if it is disabled */ 6514edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 6524edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, 6534edd8523SJack F Vogel ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); 6544edd8523SJack F Vogel E1000_WRITE_FLUSH(hw); 6554edd8523SJack F Vogel msec_delay(300); 6564edd8523SJack F Vogel 6578cfa0ad2SJack F Vogel /* 6588cfa0ad2SJack F Vogel * The address field in the I2CCMD register is 3 bits and 0 is invalid. 6598cfa0ad2SJack F Vogel * Therefore, we need to test 1-7 6608cfa0ad2SJack F Vogel */ 6618cfa0ad2SJack F Vogel for (phy->addr = 1; phy->addr < 8; phy->addr++) { 6628cfa0ad2SJack F Vogel ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id); 6638cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) { 6648cfa0ad2SJack F Vogel DEBUGOUT2("Vendor ID 0x%08X read at address %u\n", 6654dab5c37SJack F Vogel phy_id, phy->addr); 6668cfa0ad2SJack F Vogel /* 6678cfa0ad2SJack F Vogel * At the time of this writing, The M88 part is 6688cfa0ad2SJack F Vogel * the only supported SGMII PHY product. 6698cfa0ad2SJack F Vogel */ 6708cfa0ad2SJack F Vogel if (phy_id == M88_VENDOR) 6718cfa0ad2SJack F Vogel break; 6728cfa0ad2SJack F Vogel } else { 6738cfa0ad2SJack F Vogel DEBUGOUT1("PHY address %u was unreadable\n", 6748cfa0ad2SJack F Vogel phy->addr); 6758cfa0ad2SJack F Vogel } 6768cfa0ad2SJack F Vogel } 6778cfa0ad2SJack F Vogel 6788cfa0ad2SJack F Vogel /* A valid PHY type couldn't be found. */ 6798cfa0ad2SJack F Vogel if (phy->addr == 8) { 6808cfa0ad2SJack F Vogel phy->addr = 0; 6818cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 6824edd8523SJack F Vogel } else { 6834edd8523SJack F Vogel ret_val = e1000_get_phy_id(hw); 6848cfa0ad2SJack F Vogel } 6858cfa0ad2SJack F Vogel 6864edd8523SJack F Vogel /* restore previous sfp cage power state */ 6874edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 6888cfa0ad2SJack F Vogel 6898cfa0ad2SJack F Vogel out: 6908cfa0ad2SJack F Vogel return ret_val; 6918cfa0ad2SJack F Vogel } 6928cfa0ad2SJack F Vogel 6938cfa0ad2SJack F Vogel /** 6948cfa0ad2SJack F Vogel * e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset 6958cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6968cfa0ad2SJack F Vogel * 6978cfa0ad2SJack F Vogel * Resets the PHY using the serial gigabit media independent interface. 6988cfa0ad2SJack F Vogel **/ 6998cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) 7008cfa0ad2SJack F Vogel { 7018cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 7028cfa0ad2SJack F Vogel 7038cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); 7048cfa0ad2SJack F Vogel 7058cfa0ad2SJack F Vogel /* 7068cfa0ad2SJack F Vogel * This isn't a TRUE "hard" reset, but is the only reset 7078cfa0ad2SJack F Vogel * available to us at this time. 7088cfa0ad2SJack F Vogel */ 7098cfa0ad2SJack F Vogel 7108cfa0ad2SJack F Vogel DEBUGOUT("Soft resetting SGMII attached PHY...\n"); 7118cfa0ad2SJack F Vogel 7128cfa0ad2SJack F Vogel if (!(hw->phy.ops.write_reg)) 7138cfa0ad2SJack F Vogel goto out; 7148cfa0ad2SJack F Vogel 7158cfa0ad2SJack F Vogel /* 7168cfa0ad2SJack F Vogel * SFP documentation requires the following to configure the SPF module 7178cfa0ad2SJack F Vogel * to work on SGMII. No further documentation is given. 7188cfa0ad2SJack F Vogel */ 7198cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); 7208cfa0ad2SJack F Vogel if (ret_val) 7218cfa0ad2SJack F Vogel goto out; 7228cfa0ad2SJack F Vogel 7238cfa0ad2SJack F Vogel ret_val = hw->phy.ops.commit(hw); 7248cfa0ad2SJack F Vogel 7258cfa0ad2SJack F Vogel out: 7268cfa0ad2SJack F Vogel return ret_val; 7278cfa0ad2SJack F Vogel } 7288cfa0ad2SJack F Vogel 7298cfa0ad2SJack F Vogel /** 7308cfa0ad2SJack F Vogel * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state 7318cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7328cfa0ad2SJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 7338cfa0ad2SJack F Vogel * 7348cfa0ad2SJack F Vogel * Sets the LPLU D0 state according to the active flag. When 7358cfa0ad2SJack F Vogel * activating LPLU this function also disables smart speed 7368cfa0ad2SJack F Vogel * and vice versa. LPLU will not be activated unless the 7378cfa0ad2SJack F Vogel * device autonegotiation advertisement meets standards of 7388cfa0ad2SJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 7398cfa0ad2SJack F Vogel * This is a function pointer entry point only called by 7408cfa0ad2SJack F Vogel * PHY setup routines. 7418cfa0ad2SJack F Vogel **/ 7428cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) 7438cfa0ad2SJack F Vogel { 7448cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 7458cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 7468cfa0ad2SJack F Vogel u16 data; 7478cfa0ad2SJack F Vogel 7488cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82575"); 7498cfa0ad2SJack F Vogel 7508cfa0ad2SJack F Vogel if (!(hw->phy.ops.read_reg)) 7518cfa0ad2SJack F Vogel goto out; 7528cfa0ad2SJack F Vogel 7538cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); 7548cfa0ad2SJack F Vogel if (ret_val) 7558cfa0ad2SJack F Vogel goto out; 7568cfa0ad2SJack F Vogel 7578cfa0ad2SJack F Vogel if (active) { 7588cfa0ad2SJack F Vogel data |= IGP02E1000_PM_D0_LPLU; 7598cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 7608cfa0ad2SJack F Vogel data); 7618cfa0ad2SJack F Vogel if (ret_val) 7628cfa0ad2SJack F Vogel goto out; 7638cfa0ad2SJack F Vogel 7648cfa0ad2SJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 7658cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 7668cfa0ad2SJack F Vogel &data); 7678cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 7688cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 7698cfa0ad2SJack F Vogel data); 7708cfa0ad2SJack F Vogel if (ret_val) 7718cfa0ad2SJack F Vogel goto out; 7728cfa0ad2SJack F Vogel } else { 7738cfa0ad2SJack F Vogel data &= ~IGP02E1000_PM_D0_LPLU; 7748cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 7758cfa0ad2SJack F Vogel data); 7768cfa0ad2SJack F Vogel /* 7778cfa0ad2SJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 7788cfa0ad2SJack F Vogel * during Dx states where the power conservation is most 7798cfa0ad2SJack F Vogel * important. During driver activity we should enable 7808cfa0ad2SJack F Vogel * SmartSpeed, so performance is maintained. 7818cfa0ad2SJack F Vogel */ 7828cfa0ad2SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) { 7838cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 7848cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 7858cfa0ad2SJack F Vogel &data); 7868cfa0ad2SJack F Vogel if (ret_val) 7878cfa0ad2SJack F Vogel goto out; 7888cfa0ad2SJack F Vogel 7898cfa0ad2SJack F Vogel data |= IGP01E1000_PSCFR_SMART_SPEED; 7908cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 7918cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 7928cfa0ad2SJack F Vogel data); 7938cfa0ad2SJack F Vogel if (ret_val) 7948cfa0ad2SJack F Vogel goto out; 7958cfa0ad2SJack F Vogel } else if (phy->smart_speed == e1000_smart_speed_off) { 7968cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 7978cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 7988cfa0ad2SJack F Vogel &data); 7998cfa0ad2SJack F Vogel if (ret_val) 8008cfa0ad2SJack F Vogel goto out; 8018cfa0ad2SJack F Vogel 8028cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 8038cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8048cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8058cfa0ad2SJack F Vogel data); 8068cfa0ad2SJack F Vogel if (ret_val) 8078cfa0ad2SJack F Vogel goto out; 8088cfa0ad2SJack F Vogel } 8098cfa0ad2SJack F Vogel } 8108cfa0ad2SJack F Vogel 8118cfa0ad2SJack F Vogel out: 8128cfa0ad2SJack F Vogel return ret_val; 8138cfa0ad2SJack F Vogel } 8148cfa0ad2SJack F Vogel 8158cfa0ad2SJack F Vogel /** 816f0ecc46dSJack F Vogel * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state 817f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 818f0ecc46dSJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 819f0ecc46dSJack F Vogel * 820f0ecc46dSJack F Vogel * Sets the LPLU D0 state according to the active flag. When 821f0ecc46dSJack F Vogel * activating LPLU this function also disables smart speed 822f0ecc46dSJack F Vogel * and vice versa. LPLU will not be activated unless the 823f0ecc46dSJack F Vogel * device autonegotiation advertisement meets standards of 824f0ecc46dSJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 825f0ecc46dSJack F Vogel * This is a function pointer entry point only called by 826f0ecc46dSJack F Vogel * PHY setup routines. 827f0ecc46dSJack F Vogel **/ 828f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) 829f0ecc46dSJack F Vogel { 830f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 831f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 832*ab5d0362SJack F Vogel u32 data; 833f0ecc46dSJack F Vogel 834f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82580"); 835f0ecc46dSJack F Vogel 836f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 837f0ecc46dSJack F Vogel 838f0ecc46dSJack F Vogel if (active) { 839f0ecc46dSJack F Vogel data |= E1000_82580_PM_D0_LPLU; 840f0ecc46dSJack F Vogel 841f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 842f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 843f0ecc46dSJack F Vogel } else { 844f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D0_LPLU; 845f0ecc46dSJack F Vogel 846f0ecc46dSJack F Vogel /* 847f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 848f0ecc46dSJack F Vogel * during Dx states where the power conservation is most 849f0ecc46dSJack F Vogel * important. During driver activity we should enable 850f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained. 851f0ecc46dSJack F Vogel */ 8524dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) 853f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD; 8544dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off) 855f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 856f0ecc46dSJack F Vogel } 857f0ecc46dSJack F Vogel 858f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); 859f0ecc46dSJack F Vogel return ret_val; 860f0ecc46dSJack F Vogel } 861f0ecc46dSJack F Vogel 862f0ecc46dSJack F Vogel /** 863f0ecc46dSJack F Vogel * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3 864f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 865f0ecc46dSJack F Vogel * @active: boolean used to enable/disable lplu 866f0ecc46dSJack F Vogel * 867f0ecc46dSJack F Vogel * Success returns 0, Failure returns 1 868f0ecc46dSJack F Vogel * 869f0ecc46dSJack F Vogel * The low power link up (lplu) state is set to the power management level D3 870f0ecc46dSJack F Vogel * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3 871f0ecc46dSJack F Vogel * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU 872f0ecc46dSJack F Vogel * is used during Dx states where the power conservation is most important. 873f0ecc46dSJack F Vogel * During driver activity, SmartSpeed should be enabled so performance is 874f0ecc46dSJack F Vogel * maintained. 875f0ecc46dSJack F Vogel **/ 876f0ecc46dSJack F Vogel s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) 877f0ecc46dSJack F Vogel { 878f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 879f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 880*ab5d0362SJack F Vogel u32 data; 881f0ecc46dSJack F Vogel 882f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d3_lplu_state_82580"); 883f0ecc46dSJack F Vogel 884f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 885f0ecc46dSJack F Vogel 886f0ecc46dSJack F Vogel if (!active) { 887f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D3_LPLU; 888f0ecc46dSJack F Vogel /* 889f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 890f0ecc46dSJack F Vogel * during Dx states where the power conservation is most 891f0ecc46dSJack F Vogel * important. During driver activity we should enable 892f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained. 893f0ecc46dSJack F Vogel */ 8944dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) 895f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD; 8964dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off) 897f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 898f0ecc46dSJack F Vogel } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 899f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 900f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 901f0ecc46dSJack F Vogel data |= E1000_82580_PM_D3_LPLU; 902f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 903f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 904f0ecc46dSJack F Vogel } 905f0ecc46dSJack F Vogel 906f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); 907f0ecc46dSJack F Vogel return ret_val; 908f0ecc46dSJack F Vogel } 909f0ecc46dSJack F Vogel 910f0ecc46dSJack F Vogel /** 9118cfa0ad2SJack F Vogel * e1000_acquire_nvm_82575 - Request for access to EEPROM 9128cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 9138cfa0ad2SJack F Vogel * 9148cfa0ad2SJack F Vogel * Acquire the necessary semaphores for exclusive access to the EEPROM. 9158cfa0ad2SJack F Vogel * Set the EEPROM access request bit and wait for EEPROM access grant bit. 9168cfa0ad2SJack F Vogel * Return successful if access grant bit set, else clear the request for 9178cfa0ad2SJack F Vogel * EEPROM access and return -E1000_ERR_NVM (-1). 9188cfa0ad2SJack F Vogel **/ 9198cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) 9208cfa0ad2SJack F Vogel { 9218cfa0ad2SJack F Vogel s32 ret_val; 9228cfa0ad2SJack F Vogel 9238cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_nvm_82575"); 9248cfa0ad2SJack F Vogel 9258cfa0ad2SJack F Vogel ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); 9268cfa0ad2SJack F Vogel if (ret_val) 9278cfa0ad2SJack F Vogel goto out; 9284dab5c37SJack F Vogel 9294dab5c37SJack F Vogel /* 9304dab5c37SJack F Vogel * Check if there is some access 9314dab5c37SJack F Vogel * error this access may hook on 9324dab5c37SJack F Vogel */ 9334dab5c37SJack F Vogel if (hw->mac.type == e1000_i350) { 9344dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 9354dab5c37SJack F Vogel if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT | 9364dab5c37SJack F Vogel E1000_EECD_TIMEOUT)) { 9374dab5c37SJack F Vogel /* Clear all access error flags */ 9384dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd | 9394dab5c37SJack F Vogel E1000_EECD_ERROR_CLR); 9404dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); 9414dab5c37SJack F Vogel } 9424dab5c37SJack F Vogel } 9434dab5c37SJack F Vogel if (hw->mac.type == e1000_82580) { 9444dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 9454dab5c37SJack F Vogel if (eecd & E1000_EECD_BLOCKED) { 9464dab5c37SJack F Vogel /* Clear access error flag */ 9474dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd | 9484dab5c37SJack F Vogel E1000_EECD_BLOCKED); 9494dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); 9504dab5c37SJack F Vogel } 9514dab5c37SJack F Vogel } 9524dab5c37SJack F Vogel 9534dab5c37SJack F Vogel 9548cfa0ad2SJack F Vogel ret_val = e1000_acquire_nvm_generic(hw); 9558cfa0ad2SJack F Vogel if (ret_val) 9568cfa0ad2SJack F Vogel e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); 9578cfa0ad2SJack F Vogel 9588cfa0ad2SJack F Vogel out: 9598cfa0ad2SJack F Vogel return ret_val; 9608cfa0ad2SJack F Vogel } 9618cfa0ad2SJack F Vogel 9628cfa0ad2SJack F Vogel /** 9638cfa0ad2SJack F Vogel * e1000_release_nvm_82575 - Release exclusive access to EEPROM 9648cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 9658cfa0ad2SJack F Vogel * 9668cfa0ad2SJack F Vogel * Stop any current commands to the EEPROM and clear the EEPROM request bit, 9678cfa0ad2SJack F Vogel * then release the semaphores acquired. 9688cfa0ad2SJack F Vogel **/ 9698cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw) 9708cfa0ad2SJack F Vogel { 9718cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_nvm_82575"); 9728cfa0ad2SJack F Vogel 9734dab5c37SJack F Vogel e1000_release_nvm_generic(hw); 974*ab5d0362SJack F Vogel 9758cfa0ad2SJack F Vogel e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); 9768cfa0ad2SJack F Vogel } 9778cfa0ad2SJack F Vogel 9788cfa0ad2SJack F Vogel /** 9798cfa0ad2SJack F Vogel * e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore 9808cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 9818cfa0ad2SJack F Vogel * @mask: specifies which semaphore to acquire 9828cfa0ad2SJack F Vogel * 9838cfa0ad2SJack F Vogel * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 9848cfa0ad2SJack F Vogel * will also specify which port we're acquiring the lock for. 9858cfa0ad2SJack F Vogel **/ 9868cfa0ad2SJack F Vogel static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) 9878cfa0ad2SJack F Vogel { 9888cfa0ad2SJack F Vogel u32 swfw_sync; 9898cfa0ad2SJack F Vogel u32 swmask = mask; 9908cfa0ad2SJack F Vogel u32 fwmask = mask << 16; 9918cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 9928cfa0ad2SJack F Vogel s32 i = 0, timeout = 200; /* FIXME: find real value to use here */ 9938cfa0ad2SJack F Vogel 9948cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_swfw_sync_82575"); 9958cfa0ad2SJack F Vogel 9968cfa0ad2SJack F Vogel while (i < timeout) { 9978cfa0ad2SJack F Vogel if (e1000_get_hw_semaphore_generic(hw)) { 9988cfa0ad2SJack F Vogel ret_val = -E1000_ERR_SWFW_SYNC; 9998cfa0ad2SJack F Vogel goto out; 10008cfa0ad2SJack F Vogel } 10018cfa0ad2SJack F Vogel 10028cfa0ad2SJack F Vogel swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 10038cfa0ad2SJack F Vogel if (!(swfw_sync & (fwmask | swmask))) 10048cfa0ad2SJack F Vogel break; 10058cfa0ad2SJack F Vogel 10068cfa0ad2SJack F Vogel /* 10078cfa0ad2SJack F Vogel * Firmware currently using resource (fwmask) 10088cfa0ad2SJack F Vogel * or other software thread using resource (swmask) 10098cfa0ad2SJack F Vogel */ 10108cfa0ad2SJack F Vogel e1000_put_hw_semaphore_generic(hw); 10118cfa0ad2SJack F Vogel msec_delay_irq(5); 10128cfa0ad2SJack F Vogel i++; 10138cfa0ad2SJack F Vogel } 10148cfa0ad2SJack F Vogel 10158cfa0ad2SJack F Vogel if (i == timeout) { 10168cfa0ad2SJack F Vogel DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); 10178cfa0ad2SJack F Vogel ret_val = -E1000_ERR_SWFW_SYNC; 10188cfa0ad2SJack F Vogel goto out; 10198cfa0ad2SJack F Vogel } 10208cfa0ad2SJack F Vogel 10218cfa0ad2SJack F Vogel swfw_sync |= swmask; 10228cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 10238cfa0ad2SJack F Vogel 10248cfa0ad2SJack F Vogel e1000_put_hw_semaphore_generic(hw); 10258cfa0ad2SJack F Vogel 10268cfa0ad2SJack F Vogel out: 10278cfa0ad2SJack F Vogel return ret_val; 10288cfa0ad2SJack F Vogel } 10298cfa0ad2SJack F Vogel 10308cfa0ad2SJack F Vogel /** 10318cfa0ad2SJack F Vogel * e1000_release_swfw_sync_82575 - Release SW/FW semaphore 10328cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10338cfa0ad2SJack F Vogel * @mask: specifies which semaphore to acquire 10348cfa0ad2SJack F Vogel * 10358cfa0ad2SJack F Vogel * Release the SW/FW semaphore used to access the PHY or NVM. The mask 10368cfa0ad2SJack F Vogel * will also specify which port we're releasing the lock for. 10378cfa0ad2SJack F Vogel **/ 10388cfa0ad2SJack F Vogel static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) 10398cfa0ad2SJack F Vogel { 10408cfa0ad2SJack F Vogel u32 swfw_sync; 10418cfa0ad2SJack F Vogel 10428cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_swfw_sync_82575"); 10438cfa0ad2SJack F Vogel 10444dab5c37SJack F Vogel while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) 10454dab5c37SJack F Vogel ; /* Empty */ 10468cfa0ad2SJack F Vogel 10478cfa0ad2SJack F Vogel swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 10488cfa0ad2SJack F Vogel swfw_sync &= ~mask; 10498cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 10508cfa0ad2SJack F Vogel 10518cfa0ad2SJack F Vogel e1000_put_hw_semaphore_generic(hw); 10528cfa0ad2SJack F Vogel } 10538cfa0ad2SJack F Vogel 10548cfa0ad2SJack F Vogel /** 10558cfa0ad2SJack F Vogel * e1000_get_cfg_done_82575 - Read config done bit 10568cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10578cfa0ad2SJack F Vogel * 10588cfa0ad2SJack F Vogel * Read the management control register for the config done bit for 10598cfa0ad2SJack F Vogel * completion status. NOTE: silicon which is EEPROM-less will fail trying 10608cfa0ad2SJack F Vogel * to read the config done bit, so an error is *ONLY* logged and returns 10618cfa0ad2SJack F Vogel * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon 10628cfa0ad2SJack F Vogel * would not be able to be reset or change link. 10638cfa0ad2SJack F Vogel **/ 10648cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) 10658cfa0ad2SJack F Vogel { 10668cfa0ad2SJack F Vogel s32 timeout = PHY_CFG_TIMEOUT; 10678cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 10688cfa0ad2SJack F Vogel u32 mask = E1000_NVM_CFG_DONE_PORT_0; 10698cfa0ad2SJack F Vogel 10708cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_cfg_done_82575"); 10718cfa0ad2SJack F Vogel 10729d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 10738cfa0ad2SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_1; 10744edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 10754edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_2; 10764edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 10774edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_3; 10788cfa0ad2SJack F Vogel while (timeout) { 10798cfa0ad2SJack F Vogel if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) 10808cfa0ad2SJack F Vogel break; 10818cfa0ad2SJack F Vogel msec_delay(1); 10828cfa0ad2SJack F Vogel timeout--; 10838cfa0ad2SJack F Vogel } 10844edd8523SJack F Vogel if (!timeout) 10858cfa0ad2SJack F Vogel DEBUGOUT("MNG configuration cycle has not completed.\n"); 10868cfa0ad2SJack F Vogel 10878cfa0ad2SJack F Vogel /* If EEPROM is not marked present, init the PHY manually */ 1088*ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && 10894edd8523SJack F Vogel (hw->phy.type == e1000_phy_igp_3)) 10908cfa0ad2SJack F Vogel e1000_phy_init_script_igp3(hw); 10918cfa0ad2SJack F Vogel 10928cfa0ad2SJack F Vogel return ret_val; 10938cfa0ad2SJack F Vogel } 10948cfa0ad2SJack F Vogel 10958cfa0ad2SJack F Vogel /** 10968cfa0ad2SJack F Vogel * e1000_get_link_up_info_82575 - Get link speed/duplex info 10978cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10988cfa0ad2SJack F Vogel * @speed: stores the current speed 10998cfa0ad2SJack F Vogel * @duplex: stores the current duplex 11008cfa0ad2SJack F Vogel * 11018cfa0ad2SJack F Vogel * This is a wrapper function, if using the serial gigabit media independent 11028cfa0ad2SJack F Vogel * interface, use PCS to retrieve the link speed and duplex information. 11038cfa0ad2SJack F Vogel * Otherwise, use the generic function to get the link speed and duplex info. 11048cfa0ad2SJack F Vogel **/ 11058cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, 11068cfa0ad2SJack F Vogel u16 *duplex) 11078cfa0ad2SJack F Vogel { 11088cfa0ad2SJack F Vogel s32 ret_val; 11098cfa0ad2SJack F Vogel 11108cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_link_up_info_82575"); 11118cfa0ad2SJack F Vogel 11124edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) 11138cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed, 11148cfa0ad2SJack F Vogel duplex); 11154edd8523SJack F Vogel else 11168cfa0ad2SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, 11178cfa0ad2SJack F Vogel duplex); 11188cfa0ad2SJack F Vogel 11198cfa0ad2SJack F Vogel return ret_val; 11208cfa0ad2SJack F Vogel } 11218cfa0ad2SJack F Vogel 11228cfa0ad2SJack F Vogel /** 11238cfa0ad2SJack F Vogel * e1000_check_for_link_82575 - Check for link 11248cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11258cfa0ad2SJack F Vogel * 11268cfa0ad2SJack F Vogel * If sgmii is enabled, then use the pcs register to determine link, otherwise 11278cfa0ad2SJack F Vogel * use the generic interface for determining link. 11288cfa0ad2SJack F Vogel **/ 11298cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw) 11308cfa0ad2SJack F Vogel { 11318cfa0ad2SJack F Vogel s32 ret_val; 11328cfa0ad2SJack F Vogel u16 speed, duplex; 11338cfa0ad2SJack F Vogel 11348cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_for_link_82575"); 11358cfa0ad2SJack F Vogel 11364edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) { 11378cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed, 11388cfa0ad2SJack F Vogel &duplex); 1139d035aa2dSJack F Vogel /* 1140d035aa2dSJack F Vogel * Use this flag to determine if link needs to be checked or 1141d035aa2dSJack F Vogel * not. If we have link clear the flag so that we do not 1142d035aa2dSJack F Vogel * continue to check for link. 1143d035aa2dSJack F Vogel */ 1144d035aa2dSJack F Vogel hw->mac.get_link_status = !hw->mac.serdes_has_link; 1145*ab5d0362SJack F Vogel 1146d035aa2dSJack F Vogel } else { 11478cfa0ad2SJack F Vogel ret_val = e1000_check_for_copper_link_generic(hw); 1148d035aa2dSJack F Vogel } 11498cfa0ad2SJack F Vogel 11508cfa0ad2SJack F Vogel return ret_val; 11518cfa0ad2SJack F Vogel } 11528cfa0ad2SJack F Vogel 11538cfa0ad2SJack F Vogel /** 1154a69ed8dfSJack F Vogel * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown 1155a69ed8dfSJack F Vogel * @hw: pointer to the HW structure 1156a69ed8dfSJack F Vogel **/ 1157a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw) 1158a69ed8dfSJack F Vogel { 1159a69ed8dfSJack F Vogel u32 reg; 1160a69ed8dfSJack F Vogel 1161a69ed8dfSJack F Vogel DEBUGFUNC("e1000_power_up_serdes_link_82575"); 1162a69ed8dfSJack F Vogel 1163a69ed8dfSJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 1164a69ed8dfSJack F Vogel !e1000_sgmii_active_82575(hw)) 1165a69ed8dfSJack F Vogel return; 1166a69ed8dfSJack F Vogel 1167a69ed8dfSJack F Vogel /* Enable PCS to turn on link */ 1168a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0); 1169a69ed8dfSJack F Vogel reg |= E1000_PCS_CFG_PCS_EN; 1170a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); 1171a69ed8dfSJack F Vogel 1172a69ed8dfSJack F Vogel /* Power up the laser */ 1173a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT); 1174a69ed8dfSJack F Vogel reg &= ~E1000_CTRL_EXT_SDP3_DATA; 1175a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); 1176a69ed8dfSJack F Vogel 1177a69ed8dfSJack F Vogel /* flush the write to verify completion */ 1178a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw); 1179a69ed8dfSJack F Vogel msec_delay(1); 1180a69ed8dfSJack F Vogel } 1181a69ed8dfSJack F Vogel 1182a69ed8dfSJack F Vogel /** 11838cfa0ad2SJack F Vogel * e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex 11848cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11858cfa0ad2SJack F Vogel * @speed: stores the current speed 11868cfa0ad2SJack F Vogel * @duplex: stores the current duplex 11878cfa0ad2SJack F Vogel * 11888cfa0ad2SJack F Vogel * Using the physical coding sub-layer (PCS), retrieve the current speed and 11898cfa0ad2SJack F Vogel * duplex, then store the values in the pointers provided. 11908cfa0ad2SJack F Vogel **/ 11918cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, 11928cfa0ad2SJack F Vogel u16 *speed, u16 *duplex) 11938cfa0ad2SJack F Vogel { 11948cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 11958cfa0ad2SJack F Vogel u32 pcs; 11968cfa0ad2SJack F Vogel 11978cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); 11988cfa0ad2SJack F Vogel 11998cfa0ad2SJack F Vogel /* 12008cfa0ad2SJack F Vogel * Read the PCS Status register for link state. For non-copper mode, 12018cfa0ad2SJack F Vogel * the status register is not accurate. The PCS status register is 12028cfa0ad2SJack F Vogel * used instead. 12038cfa0ad2SJack F Vogel */ 12048cfa0ad2SJack F Vogel pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT); 12058cfa0ad2SJack F Vogel 12068cfa0ad2SJack F Vogel /* 1207*ab5d0362SJack F Vogel * The link up bit determines when link is up on autoneg. 12088cfa0ad2SJack F Vogel */ 1209*ab5d0362SJack F Vogel if (pcs & E1000_PCS_LSTS_LINK_OK) { 12108cfa0ad2SJack F Vogel mac->serdes_has_link = TRUE; 12118cfa0ad2SJack F Vogel 12128cfa0ad2SJack F Vogel /* Detect and store PCS speed */ 12134dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_SPEED_1000) 12148cfa0ad2SJack F Vogel *speed = SPEED_1000; 12154dab5c37SJack F Vogel else if (pcs & E1000_PCS_LSTS_SPEED_100) 12168cfa0ad2SJack F Vogel *speed = SPEED_100; 12174dab5c37SJack F Vogel else 12188cfa0ad2SJack F Vogel *speed = SPEED_10; 12198cfa0ad2SJack F Vogel 12208cfa0ad2SJack F Vogel /* Detect and store PCS duplex */ 12214dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) 12228cfa0ad2SJack F Vogel *duplex = FULL_DUPLEX; 12234dab5c37SJack F Vogel else 12248cfa0ad2SJack F Vogel *duplex = HALF_DUPLEX; 1225*ab5d0362SJack F Vogel } else { 1226*ab5d0362SJack F Vogel mac->serdes_has_link = FALSE; 1227*ab5d0362SJack F Vogel *speed = 0; 1228*ab5d0362SJack F Vogel *duplex = 0; 12298cfa0ad2SJack F Vogel } 12308cfa0ad2SJack F Vogel 12318cfa0ad2SJack F Vogel return E1000_SUCCESS; 12328cfa0ad2SJack F Vogel } 12338cfa0ad2SJack F Vogel 12348cfa0ad2SJack F Vogel /** 12354edd8523SJack F Vogel * e1000_shutdown_serdes_link_82575 - Remove link during power down 12368cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 12378cfa0ad2SJack F Vogel * 12384edd8523SJack F Vogel * In the case of serdes shut down sfp and PCS on driver unload 12398cfa0ad2SJack F Vogel * when management pass thru is not enabled. 12408cfa0ad2SJack F Vogel **/ 12414edd8523SJack F Vogel void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw) 12428cfa0ad2SJack F Vogel { 12438cfa0ad2SJack F Vogel u32 reg; 1244a69ed8dfSJack F Vogel 1245a69ed8dfSJack F Vogel DEBUGFUNC("e1000_shutdown_serdes_link_82575"); 12468cfa0ad2SJack F Vogel 12474edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 12484edd8523SJack F Vogel !e1000_sgmii_active_82575(hw)) 12498cfa0ad2SJack F Vogel return; 12508cfa0ad2SJack F Vogel 1251a69ed8dfSJack F Vogel if (!e1000_enable_mng_pass_thru(hw)) { 12528cfa0ad2SJack F Vogel /* Disable PCS to turn off link */ 12538cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0); 12548cfa0ad2SJack F Vogel reg &= ~E1000_PCS_CFG_PCS_EN; 12558cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); 12568cfa0ad2SJack F Vogel 12578cfa0ad2SJack F Vogel /* shutdown the laser */ 12588cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT); 12594edd8523SJack F Vogel reg |= E1000_CTRL_EXT_SDP3_DATA; 12608cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); 12618cfa0ad2SJack F Vogel 12624edd8523SJack F Vogel /* flush the write to verify completion */ 12638cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 12648cfa0ad2SJack F Vogel msec_delay(1); 12658cfa0ad2SJack F Vogel } 12668cfa0ad2SJack F Vogel 12678cfa0ad2SJack F Vogel return; 12688cfa0ad2SJack F Vogel } 12698cfa0ad2SJack F Vogel 12708cfa0ad2SJack F Vogel /** 12718cfa0ad2SJack F Vogel * e1000_reset_hw_82575 - Reset hardware 12728cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 12738cfa0ad2SJack F Vogel * 1274daf9197cSJack F Vogel * This resets the hardware into a known state. 12758cfa0ad2SJack F Vogel **/ 12768cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw) 12778cfa0ad2SJack F Vogel { 1278f0ecc46dSJack F Vogel u32 ctrl; 12798cfa0ad2SJack F Vogel s32 ret_val; 12808cfa0ad2SJack F Vogel 12818cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_82575"); 12828cfa0ad2SJack F Vogel 12838cfa0ad2SJack F Vogel /* 12848cfa0ad2SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection 12858cfa0ad2SJack F Vogel * on the last TLP read/write transaction when MAC is reset. 12868cfa0ad2SJack F Vogel */ 12878cfa0ad2SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw); 12884dab5c37SJack F Vogel if (ret_val) 12898cfa0ad2SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 12908cfa0ad2SJack F Vogel 12919d81738fSJack F Vogel /* set the completion timeout for interface */ 12929d81738fSJack F Vogel ret_val = e1000_set_pcie_completion_timeout(hw); 12934dab5c37SJack F Vogel if (ret_val) 12949d81738fSJack F Vogel DEBUGOUT("PCI-E Set completion timeout has failed.\n"); 12959d81738fSJack F Vogel 12968cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 12978cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 12988cfa0ad2SJack F Vogel 12998cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 13008cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 13018cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 13028cfa0ad2SJack F Vogel 13038cfa0ad2SJack F Vogel msec_delay(10); 13048cfa0ad2SJack F Vogel 13058cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 13068cfa0ad2SJack F Vogel 13078cfa0ad2SJack F Vogel DEBUGOUT("Issuing a global reset to MAC\n"); 13088cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 13098cfa0ad2SJack F Vogel 13108cfa0ad2SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw); 13118cfa0ad2SJack F Vogel if (ret_val) { 13128cfa0ad2SJack F Vogel /* 13138cfa0ad2SJack F Vogel * When auto config read does not complete, do not 13148cfa0ad2SJack F Vogel * return with an error. This can happen in situations 13158cfa0ad2SJack F Vogel * where there is no eeprom and prevents getting link. 13168cfa0ad2SJack F Vogel */ 13178cfa0ad2SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n"); 13188cfa0ad2SJack F Vogel } 13198cfa0ad2SJack F Vogel 13208cfa0ad2SJack F Vogel /* If EEPROM is not present, run manual init scripts */ 1321*ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) 13228cfa0ad2SJack F Vogel e1000_reset_init_script_82575(hw); 13238cfa0ad2SJack F Vogel 13248cfa0ad2SJack F Vogel /* Clear any pending interrupt events. */ 13258cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 1326f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR); 13278cfa0ad2SJack F Vogel 1328d035aa2dSJack F Vogel /* Install any alternate MAC address into RAR0 */ 1329d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 13308cfa0ad2SJack F Vogel 13318cfa0ad2SJack F Vogel return ret_val; 13328cfa0ad2SJack F Vogel } 13338cfa0ad2SJack F Vogel 13348cfa0ad2SJack F Vogel /** 13358cfa0ad2SJack F Vogel * e1000_init_hw_82575 - Initialize hardware 13368cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13378cfa0ad2SJack F Vogel * 13388cfa0ad2SJack F Vogel * This inits the hardware readying it for operation. 13398cfa0ad2SJack F Vogel **/ 13408cfa0ad2SJack F Vogel static s32 e1000_init_hw_82575(struct e1000_hw *hw) 13418cfa0ad2SJack F Vogel { 13428cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 13438cfa0ad2SJack F Vogel s32 ret_val; 13448cfa0ad2SJack F Vogel u16 i, rar_count = mac->rar_entry_count; 13458cfa0ad2SJack F Vogel 13468cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_82575"); 13478cfa0ad2SJack F Vogel 13488cfa0ad2SJack F Vogel /* Initialize identification LED */ 1349d035aa2dSJack F Vogel ret_val = mac->ops.id_led_init(hw); 13508cfa0ad2SJack F Vogel if (ret_val) { 13518cfa0ad2SJack F Vogel DEBUGOUT("Error initializing identification LED\n"); 13528cfa0ad2SJack F Vogel /* This is not fatal and we should not stop init due to this */ 13538cfa0ad2SJack F Vogel } 13548cfa0ad2SJack F Vogel 13558cfa0ad2SJack F Vogel /* Disabling VLAN filtering */ 13568cfa0ad2SJack F Vogel DEBUGOUT("Initializing the IEEE VLAN\n"); 13578cfa0ad2SJack F Vogel mac->ops.clear_vfta(hw); 13588cfa0ad2SJack F Vogel 13598cfa0ad2SJack F Vogel /* Setup the receive address */ 1360d035aa2dSJack F Vogel e1000_init_rx_addrs_generic(hw, rar_count); 1361d035aa2dSJack F Vogel 13628cfa0ad2SJack F Vogel /* Zero out the Multicast HASH table */ 13638cfa0ad2SJack F Vogel DEBUGOUT("Zeroing the MTA\n"); 13648cfa0ad2SJack F Vogel for (i = 0; i < mac->mta_reg_count; i++) 13658cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); 13668cfa0ad2SJack F Vogel 13674edd8523SJack F Vogel /* Zero out the Unicast HASH table */ 13684edd8523SJack F Vogel DEBUGOUT("Zeroing the UTA\n"); 13694edd8523SJack F Vogel for (i = 0; i < mac->uta_reg_count; i++) 13704edd8523SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); 13714edd8523SJack F Vogel 13728cfa0ad2SJack F Vogel /* Setup link and flow control */ 13738cfa0ad2SJack F Vogel ret_val = mac->ops.setup_link(hw); 13748cfa0ad2SJack F Vogel 13754dab5c37SJack F Vogel /* Set the default MTU size */ 13764dab5c37SJack F Vogel hw->dev_spec._82575.mtu = 1500; 13774dab5c37SJack F Vogel 13788cfa0ad2SJack F Vogel /* 13798cfa0ad2SJack F Vogel * Clear all of the statistics registers (clear on read). It is 13808cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link 13818cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there 13828cfa0ad2SJack F Vogel * is no link. 13838cfa0ad2SJack F Vogel */ 13848cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_82575(hw); 13858cfa0ad2SJack F Vogel 13868cfa0ad2SJack F Vogel return ret_val; 13878cfa0ad2SJack F Vogel } 13888cfa0ad2SJack F Vogel 13898cfa0ad2SJack F Vogel /** 13908cfa0ad2SJack F Vogel * e1000_setup_copper_link_82575 - Configure copper link settings 13918cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13928cfa0ad2SJack F Vogel * 13938cfa0ad2SJack F Vogel * Configures the link for auto-neg or forced speed and duplex. Then we check 13948cfa0ad2SJack F Vogel * for link, once link is established calls to configure collision distance 13958cfa0ad2SJack F Vogel * and flow control are called. 13968cfa0ad2SJack F Vogel **/ 13978cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) 13988cfa0ad2SJack F Vogel { 13999d81738fSJack F Vogel u32 ctrl; 14008cfa0ad2SJack F Vogel s32 ret_val; 14018cfa0ad2SJack F Vogel 14028cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_82575"); 14038cfa0ad2SJack F Vogel 14048cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 14058cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SLU; 14068cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 14078cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 14088cfa0ad2SJack F Vogel 14094edd8523SJack F Vogel ret_val = e1000_setup_serdes_link_82575(hw); 14104edd8523SJack F Vogel if (ret_val) 14114edd8523SJack F Vogel goto out; 14124edd8523SJack F Vogel 14134dab5c37SJack F Vogel if (e1000_sgmii_active_82575(hw)) { 14144edd8523SJack F Vogel /* allow time for SFP cage time to power up phy */ 14154edd8523SJack F Vogel msec_delay(300); 14164edd8523SJack F Vogel 14174edd8523SJack F Vogel ret_val = hw->phy.ops.reset(hw); 14184edd8523SJack F Vogel if (ret_val) { 14194edd8523SJack F Vogel DEBUGOUT("Error resetting the PHY.\n"); 14204edd8523SJack F Vogel goto out; 14214edd8523SJack F Vogel } 14224edd8523SJack F Vogel } 14238cfa0ad2SJack F Vogel switch (hw->phy.type) { 1424*ab5d0362SJack F Vogel case e1000_phy_i210: 14258cfa0ad2SJack F Vogel case e1000_phy_m88: 1426f0ecc46dSJack F Vogel if (hw->phy.id == I347AT4_E_PHY_ID || 14271fd3c44fSJack F Vogel hw->phy.id == M88E1112_E_PHY_ID || 14281fd3c44fSJack F Vogel hw->phy.id == M88E1340M_E_PHY_ID) 1429f0ecc46dSJack F Vogel ret_val = e1000_copper_link_setup_m88_gen2(hw); 1430f0ecc46dSJack F Vogel else 14318cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_m88(hw); 14328cfa0ad2SJack F Vogel break; 14338cfa0ad2SJack F Vogel case e1000_phy_igp_3: 14348cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_igp(hw); 14358cfa0ad2SJack F Vogel break; 14364edd8523SJack F Vogel case e1000_phy_82580: 14374edd8523SJack F Vogel ret_val = e1000_copper_link_setup_82577(hw); 14384edd8523SJack F Vogel break; 14398cfa0ad2SJack F Vogel default: 14408cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 14418cfa0ad2SJack F Vogel break; 14428cfa0ad2SJack F Vogel } 14438cfa0ad2SJack F Vogel 14448cfa0ad2SJack F Vogel if (ret_val) 14458cfa0ad2SJack F Vogel goto out; 14468cfa0ad2SJack F Vogel 14474edd8523SJack F Vogel ret_val = e1000_setup_copper_link_generic(hw); 14488cfa0ad2SJack F Vogel out: 14498cfa0ad2SJack F Vogel return ret_val; 14508cfa0ad2SJack F Vogel } 14518cfa0ad2SJack F Vogel 14528cfa0ad2SJack F Vogel /** 14534edd8523SJack F Vogel * e1000_setup_serdes_link_82575 - Setup link for serdes 14548cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14558cfa0ad2SJack F Vogel * 14564edd8523SJack F Vogel * Configure the physical coding sub-layer (PCS) link. The PCS link is 14574edd8523SJack F Vogel * used on copper connections where the serialized gigabit media independent 14584edd8523SJack F Vogel * interface (sgmii), or serdes fiber is being used. Configures the link 14594edd8523SJack F Vogel * for auto-negotiation or forces speed/duplex. 14608cfa0ad2SJack F Vogel **/ 14614edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) 14628cfa0ad2SJack F Vogel { 14634edd8523SJack F Vogel u32 ctrl_ext, ctrl_reg, reg; 14644edd8523SJack F Vogel bool pcs_autoneg; 14654dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS; 14664dab5c37SJack F Vogel u16 data; 14678cfa0ad2SJack F Vogel 14684edd8523SJack F Vogel DEBUGFUNC("e1000_setup_serdes_link_82575"); 14694edd8523SJack F Vogel 14704edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 14714edd8523SJack F Vogel !e1000_sgmii_active_82575(hw)) 14724dab5c37SJack F Vogel return ret_val; 14738cfa0ad2SJack F Vogel 14748cfa0ad2SJack F Vogel /* 14758cfa0ad2SJack F Vogel * On the 82575, SerDes loopback mode persists until it is 14768cfa0ad2SJack F Vogel * explicitly turned off or a power cycle is performed. A read to 14778cfa0ad2SJack F Vogel * the register does not indicate its status. Therefore, we ensure 14788cfa0ad2SJack F Vogel * loopback mode is disabled during initialization. 14798cfa0ad2SJack F Vogel */ 14808cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); 14818cfa0ad2SJack F Vogel 14824edd8523SJack F Vogel /* power on the sfp cage if present */ 14834edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 14844edd8523SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; 14854edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 14864edd8523SJack F Vogel 14874edd8523SJack F Vogel ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); 14884edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SLU; 14894edd8523SJack F Vogel 1490a69ed8dfSJack F Vogel /* set both sw defined pins on 82575/82576*/ 1491a69ed8dfSJack F Vogel if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) 14924edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; 14938cfa0ad2SJack F Vogel 14944edd8523SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_LCTL); 14954edd8523SJack F Vogel 14964edd8523SJack F Vogel /* default pcs_autoneg to the same setting as mac autoneg */ 14974edd8523SJack F Vogel pcs_autoneg = hw->mac.autoneg; 14984edd8523SJack F Vogel 14994edd8523SJack F Vogel switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { 15004edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII: 15014edd8523SJack F Vogel /* sgmii mode lets the phy handle forcing speed/duplex */ 15024edd8523SJack F Vogel pcs_autoneg = TRUE; 15034edd8523SJack F Vogel /* autoneg time out should be disabled for SGMII mode */ 15044edd8523SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); 15054edd8523SJack F Vogel break; 15064edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 15074edd8523SJack F Vogel /* disable PCS autoneg and support parallel detect only */ 15084edd8523SJack F Vogel pcs_autoneg = FALSE; 15097d9119bdSJack F Vogel /* fall through to default case */ 15104edd8523SJack F Vogel default: 15114dab5c37SJack F Vogel if (hw->mac.type == e1000_82575 || 15124dab5c37SJack F Vogel hw->mac.type == e1000_82576) { 15134dab5c37SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data); 15144dab5c37SJack F Vogel if (ret_val) { 15154dab5c37SJack F Vogel DEBUGOUT("NVM Read Error\n"); 15164dab5c37SJack F Vogel return ret_val; 15174dab5c37SJack F Vogel } 15184dab5c37SJack F Vogel 15194dab5c37SJack F Vogel if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT) 15204dab5c37SJack F Vogel pcs_autoneg = FALSE; 15214dab5c37SJack F Vogel } 15224dab5c37SJack F Vogel 15234edd8523SJack F Vogel /* 15244edd8523SJack F Vogel * non-SGMII modes only supports a speed of 1000/Full for the 15254edd8523SJack F Vogel * link so it is best to just force the MAC and let the pcs 15264edd8523SJack F Vogel * link either autoneg or be forced to 1000/Full 15274edd8523SJack F Vogel */ 15284edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | 15294edd8523SJack F Vogel E1000_CTRL_FD | E1000_CTRL_FRCDPX; 15304edd8523SJack F Vogel 15314edd8523SJack F Vogel /* set speed of 1000/Full if speed/duplex is forced */ 15324edd8523SJack F Vogel reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL; 15334edd8523SJack F Vogel break; 15344edd8523SJack F Vogel } 15354edd8523SJack F Vogel 15364edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); 15378cfa0ad2SJack F Vogel 15388cfa0ad2SJack F Vogel /* 15398cfa0ad2SJack F Vogel * New SerDes mode allows for forcing speed or autonegotiating speed 15408cfa0ad2SJack F Vogel * at 1gb. Autoneg should be default set by most drivers. This is the 15418cfa0ad2SJack F Vogel * mode that will be compatible with older link partners and switches. 15428cfa0ad2SJack F Vogel * However, both are supported by the hardware and some drivers/tools. 15438cfa0ad2SJack F Vogel */ 15448cfa0ad2SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | 15458cfa0ad2SJack F Vogel E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); 15468cfa0ad2SJack F Vogel 15474edd8523SJack F Vogel /* 15484edd8523SJack F Vogel * We force flow control to prevent the CTRL register values from being 15494edd8523SJack F Vogel * overwritten by the autonegotiated flow control values 15504edd8523SJack F Vogel */ 15518cfa0ad2SJack F Vogel reg |= E1000_PCS_LCTL_FORCE_FCTRL; 15524edd8523SJack F Vogel 15534edd8523SJack F Vogel if (pcs_autoneg) { 15544edd8523SJack F Vogel /* Set PCS register for autoneg */ 15554edd8523SJack F Vogel reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ 15564edd8523SJack F Vogel E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ 15574edd8523SJack F Vogel DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); 15584edd8523SJack F Vogel } else { 15594edd8523SJack F Vogel /* Set PCS register for forced link */ 1560a69ed8dfSJack F Vogel reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ 15614edd8523SJack F Vogel DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); 15628cfa0ad2SJack F Vogel } 15638cfa0ad2SJack F Vogel 15648cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); 15658cfa0ad2SJack F Vogel 15664edd8523SJack F Vogel if (!e1000_sgmii_active_82575(hw)) 15674edd8523SJack F Vogel e1000_force_mac_fc_generic(hw); 15684edd8523SJack F Vogel 15694dab5c37SJack F Vogel return ret_val; 15704dab5c37SJack F Vogel } 15714dab5c37SJack F Vogel 15724dab5c37SJack F Vogel /** 15734dab5c37SJack F Vogel * e1000_get_media_type_82575 - derives current media type. 15744dab5c37SJack F Vogel * @hw: pointer to the HW structure 15754dab5c37SJack F Vogel * 15764dab5c37SJack F Vogel * The media type is chosen reflecting few settings. 15774dab5c37SJack F Vogel * The following are taken into account: 15784dab5c37SJack F Vogel * - link mode set in the current port Init Control Word #3 15794dab5c37SJack F Vogel * - current link mode settings in CSR register 15804dab5c37SJack F Vogel * - MDIO vs. I2C PHY control interface chosen 15814dab5c37SJack F Vogel * - SFP module media type 15824dab5c37SJack F Vogel **/ 15834dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw) 15844dab5c37SJack F Vogel { 15854dab5c37SJack F Vogel u32 lan_id = 0; 15864dab5c37SJack F Vogel s32 ret_val = E1000_ERR_CONFIG; 15874dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 15884dab5c37SJack F Vogel u32 ctrl_ext = 0; 15894dab5c37SJack F Vogel u32 current_link_mode = 0; 15904dab5c37SJack F Vogel u16 init_ctrl_wd_3 = 0; 15914dab5c37SJack F Vogel u8 init_ctrl_wd_3_offset = 0; 15924dab5c37SJack F Vogel u8 init_ctrl_wd_3_bit_offset = 0; 15934dab5c37SJack F Vogel 15944dab5c37SJack F Vogel /* Set internal phy as default */ 15954dab5c37SJack F Vogel dev_spec->sgmii_active = FALSE; 15964dab5c37SJack F Vogel dev_spec->module_plugged = FALSE; 15974dab5c37SJack F Vogel 15984dab5c37SJack F Vogel /* 15994dab5c37SJack F Vogel * Check if NVM access method is attached already. 16004dab5c37SJack F Vogel * If it is then Init Control Word #3 is considered 16014dab5c37SJack F Vogel * otherwise runtime CSR register content is taken. 16024dab5c37SJack F Vogel */ 16034dab5c37SJack F Vogel 16044dab5c37SJack F Vogel /* Get CSR setting */ 16054dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 16064dab5c37SJack F Vogel 16074dab5c37SJack F Vogel /* Get link mode setting */ 16084dab5c37SJack F Vogel if ((hw->nvm.ops.read) && (hw->nvm.ops.read != e1000_null_read_nvm)) { 16094dab5c37SJack F Vogel /* Take link mode from EEPROM */ 16104dab5c37SJack F Vogel 16114dab5c37SJack F Vogel /* 16124dab5c37SJack F Vogel * Get LAN port ID to derive its 16134dab5c37SJack F Vogel * adequate Init Control Word #3 16144dab5c37SJack F Vogel */ 16154dab5c37SJack F Vogel lan_id = ((E1000_READ_REG(hw, E1000_STATUS) & 16164dab5c37SJack F Vogel E1000_STATUS_LAN_ID_MASK) >> E1000_STATUS_LAN_ID_OFFSET); 16174dab5c37SJack F Vogel /* 16184dab5c37SJack F Vogel * Derive Init Control Word #3 offset 16194dab5c37SJack F Vogel * and mask to pick up link mode setting. 16204dab5c37SJack F Vogel */ 16214dab5c37SJack F Vogel if (hw->mac.type < e1000_82580) { 16224dab5c37SJack F Vogel init_ctrl_wd_3_offset = lan_id ? 16234dab5c37SJack F Vogel NVM_INIT_CONTROL3_PORT_A : NVM_INIT_CONTROL3_PORT_B; 16244dab5c37SJack F Vogel init_ctrl_wd_3_bit_offset = NVM_WORD24_LNK_MODE_OFFSET; 16254dab5c37SJack F Vogel } else { 16264dab5c37SJack F Vogel init_ctrl_wd_3_offset = 16274dab5c37SJack F Vogel NVM_82580_LAN_FUNC_OFFSET(lan_id) + 16284dab5c37SJack F Vogel NVM_INIT_CONTROL3_PORT_A; 16294dab5c37SJack F Vogel init_ctrl_wd_3_bit_offset = 16304dab5c37SJack F Vogel NVM_WORD24_82580_LNK_MODE_OFFSET; 16314dab5c37SJack F Vogel } 16324dab5c37SJack F Vogel /* Read Init Control Word #3*/ 16334dab5c37SJack F Vogel hw->nvm.ops.read(hw, init_ctrl_wd_3_offset, 1, &init_ctrl_wd_3); 16344dab5c37SJack F Vogel 16354dab5c37SJack F Vogel /* 16364dab5c37SJack F Vogel * Align link mode bits to 16374dab5c37SJack F Vogel * their CTRL_EXT location. 16384dab5c37SJack F Vogel */ 1639*ab5d0362SJack F Vogel current_link_mode = init_ctrl_wd_3; 16404dab5c37SJack F Vogel current_link_mode <<= (E1000_CTRL_EXT_LINK_MODE_OFFSET - 16414dab5c37SJack F Vogel init_ctrl_wd_3_bit_offset); 16424dab5c37SJack F Vogel current_link_mode &= E1000_CTRL_EXT_LINK_MODE_MASK; 16434dab5c37SJack F Vogel 1644*ab5d0362SJack F Vogel /* 1645*ab5d0362SJack F Vogel * Switch to CSR for all but internal PHY. 1646*ab5d0362SJack F Vogel */ 1647*ab5d0362SJack F Vogel if (current_link_mode != E1000_CTRL_EXT_LINK_MODE_GMII) 1648*ab5d0362SJack F Vogel /* Take link mode from CSR */ 1649*ab5d0362SJack F Vogel current_link_mode = ctrl_ext & 1650*ab5d0362SJack F Vogel E1000_CTRL_EXT_LINK_MODE_MASK; 1651*ab5d0362SJack F Vogel } else { 1652*ab5d0362SJack F Vogel /* Take link mode from CSR */ 1653*ab5d0362SJack F Vogel current_link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; 1654*ab5d0362SJack F Vogel } 1655*ab5d0362SJack F Vogel 16564dab5c37SJack F Vogel switch (current_link_mode) { 16574dab5c37SJack F Vogel 16584dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 16594dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 16604dab5c37SJack F Vogel current_link_mode = E1000_CTRL_EXT_LINK_MODE_1000BASE_KX; 16614dab5c37SJack F Vogel break; 16624dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_GMII: 16634dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 16644dab5c37SJack F Vogel current_link_mode = E1000_CTRL_EXT_LINK_MODE_GMII; 16654dab5c37SJack F Vogel break; 16664dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII: 16674dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: 16684dab5c37SJack F Vogel /* Get phy control interface type set (MDIO vs. I2C)*/ 16694dab5c37SJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) { 16704dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 16714dab5c37SJack F Vogel dev_spec->sgmii_active = TRUE; 16724dab5c37SJack F Vogel current_link_mode = E1000_CTRL_EXT_LINK_MODE_SGMII; 16734dab5c37SJack F Vogel } else { 16744dab5c37SJack F Vogel ret_val = e1000_set_sfp_media_type_82575(hw); 16754dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS) 16764dab5c37SJack F Vogel goto out; 16774dab5c37SJack F Vogel if (hw->phy.media_type == 16784dab5c37SJack F Vogel e1000_media_type_internal_serdes) { 16794dab5c37SJack F Vogel current_link_mode = 16804dab5c37SJack F Vogel E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 16814dab5c37SJack F Vogel } else if (hw->phy.media_type == 16824dab5c37SJack F Vogel e1000_media_type_copper) { 16834dab5c37SJack F Vogel current_link_mode = 16844dab5c37SJack F Vogel E1000_CTRL_EXT_LINK_MODE_SGMII; 16854dab5c37SJack F Vogel } 16864dab5c37SJack F Vogel } 16874dab5c37SJack F Vogel break; 16884dab5c37SJack F Vogel default: 16894dab5c37SJack F Vogel DEBUGOUT("Link mode mask doesn't fit bit field size\n"); 16904dab5c37SJack F Vogel goto out; 16914dab5c37SJack F Vogel } 16924dab5c37SJack F Vogel /* 16934dab5c37SJack F Vogel * Do not change current link mode setting 16944dab5c37SJack F Vogel * if media type is fibre or has not been 16954dab5c37SJack F Vogel * recognized. 16964dab5c37SJack F Vogel */ 16974dab5c37SJack F Vogel if ((hw->phy.media_type != e1000_media_type_unknown) && 16984dab5c37SJack F Vogel (hw->phy.media_type != e1000_media_type_fiber)) { 16994dab5c37SJack F Vogel /* Update link mode */ 17004dab5c37SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; 17014dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | 17024dab5c37SJack F Vogel current_link_mode); 17034dab5c37SJack F Vogel } 17044dab5c37SJack F Vogel 17054dab5c37SJack F Vogel ret_val = E1000_SUCCESS; 17064dab5c37SJack F Vogel out: 17074dab5c37SJack F Vogel /* 17084dab5c37SJack F Vogel * If media type was not identified then return media type 17094dab5c37SJack F Vogel * defined by the CTRL_EXT settings. 17104dab5c37SJack F Vogel */ 17114dab5c37SJack F Vogel if (hw->phy.media_type == e1000_media_type_unknown) { 17124dab5c37SJack F Vogel if (current_link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) 17134dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 17144dab5c37SJack F Vogel else 17154dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 17164dab5c37SJack F Vogel } 17174dab5c37SJack F Vogel 17184dab5c37SJack F Vogel return ret_val; 17194dab5c37SJack F Vogel } 17204dab5c37SJack F Vogel 17214dab5c37SJack F Vogel /** 17224dab5c37SJack F Vogel * e1000_set_sfp_media_type_82575 - derives SFP module media type. 17234dab5c37SJack F Vogel * @hw: pointer to the HW structure 17244dab5c37SJack F Vogel * 17254dab5c37SJack F Vogel * The media type is chosen based on SFP module. 17264dab5c37SJack F Vogel * compatibility flags retrieved from SFP ID EEPROM. 17274dab5c37SJack F Vogel **/ 17284dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) 17294dab5c37SJack F Vogel { 17304dab5c37SJack F Vogel s32 ret_val = E1000_ERR_CONFIG; 17314dab5c37SJack F Vogel u32 ctrl_ext = 0; 17324dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 17334dab5c37SJack F Vogel struct sfp_e1000_flags eth_flags = {0}; 17344dab5c37SJack F Vogel u8 tranceiver_type = 0; 17354dab5c37SJack F Vogel 17364dab5c37SJack F Vogel /* Turn I2C interface ON */ 17374dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 17384dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); 17394dab5c37SJack F Vogel 17404dab5c37SJack F Vogel /* Read SFP module data */ 17414dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw, 17424dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), 17434dab5c37SJack F Vogel &tranceiver_type); 17444dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS) 17454dab5c37SJack F Vogel goto out; 17464dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw, 17474dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), 17484dab5c37SJack F Vogel (u8 *)ð_flags); 17494dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS) 17504dab5c37SJack F Vogel goto out; 17514dab5c37SJack F Vogel /* 17524dab5c37SJack F Vogel * Check if there is some SFP 17534dab5c37SJack F Vogel * module plugged and powered 17544dab5c37SJack F Vogel */ 17554dab5c37SJack F Vogel if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || 17564dab5c37SJack F Vogel (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { 17574dab5c37SJack F Vogel dev_spec->module_plugged = TRUE; 17584dab5c37SJack F Vogel if (eth_flags.e1000_base_lx || eth_flags.e1000_base_sx) { 17594dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 17604dab5c37SJack F Vogel } else if (eth_flags.e1000_base_t) { 17614dab5c37SJack F Vogel dev_spec->sgmii_active = TRUE; 17624dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 17634dab5c37SJack F Vogel } else { 17644dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_unknown; 17654dab5c37SJack F Vogel DEBUGOUT("PHY module has not been recognized\n"); 17664dab5c37SJack F Vogel goto out; 17674dab5c37SJack F Vogel } 17684dab5c37SJack F Vogel } else { 17694dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_unknown; 17704dab5c37SJack F Vogel } 17714dab5c37SJack F Vogel ret_val = E1000_SUCCESS; 17724dab5c37SJack F Vogel out: 17734dab5c37SJack F Vogel /* Restore I2C interface setting */ 17744dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 17754dab5c37SJack F Vogel return ret_val; 17768cfa0ad2SJack F Vogel } 17778cfa0ad2SJack F Vogel 17788cfa0ad2SJack F Vogel /** 17798cfa0ad2SJack F Vogel * e1000_valid_led_default_82575 - Verify a valid default LED config 17808cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 17818cfa0ad2SJack F Vogel * @data: pointer to the NVM (EEPROM) 17828cfa0ad2SJack F Vogel * 17838cfa0ad2SJack F Vogel * Read the EEPROM for the current default LED configuration. If the 17848cfa0ad2SJack F Vogel * LED configuration is not valid, set to a valid LED configuration. 17858cfa0ad2SJack F Vogel **/ 17868cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data) 17878cfa0ad2SJack F Vogel { 17888cfa0ad2SJack F Vogel s32 ret_val; 17898cfa0ad2SJack F Vogel 17908cfa0ad2SJack F Vogel DEBUGFUNC("e1000_valid_led_default_82575"); 17918cfa0ad2SJack F Vogel 17928cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 17938cfa0ad2SJack F Vogel if (ret_val) { 17948cfa0ad2SJack F Vogel DEBUGOUT("NVM Read Error\n"); 17958cfa0ad2SJack F Vogel goto out; 17968cfa0ad2SJack F Vogel } 17978cfa0ad2SJack F Vogel 17988cfa0ad2SJack F Vogel if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 17998cfa0ad2SJack F Vogel switch (hw->phy.media_type) { 18008cfa0ad2SJack F Vogel case e1000_media_type_internal_serdes: 18018cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT_82575_SERDES; 18028cfa0ad2SJack F Vogel break; 18038cfa0ad2SJack F Vogel case e1000_media_type_copper: 18048cfa0ad2SJack F Vogel default: 18058cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT; 18068cfa0ad2SJack F Vogel break; 18078cfa0ad2SJack F Vogel } 18088cfa0ad2SJack F Vogel } 18098cfa0ad2SJack F Vogel out: 18108cfa0ad2SJack F Vogel return ret_val; 18118cfa0ad2SJack F Vogel } 18128cfa0ad2SJack F Vogel 18138cfa0ad2SJack F Vogel /** 18148cfa0ad2SJack F Vogel * e1000_sgmii_active_82575 - Return sgmii state 18158cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18168cfa0ad2SJack F Vogel * 18178cfa0ad2SJack F Vogel * 82575 silicon has a serialized gigabit media independent interface (sgmii) 18188cfa0ad2SJack F Vogel * which can be enabled for use in the embedded applications. Simply 18198cfa0ad2SJack F Vogel * return the current state of the sgmii interface. 18208cfa0ad2SJack F Vogel **/ 18218cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw) 18228cfa0ad2SJack F Vogel { 1823daf9197cSJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 1824daf9197cSJack F Vogel return dev_spec->sgmii_active; 18258cfa0ad2SJack F Vogel } 18268cfa0ad2SJack F Vogel 18278cfa0ad2SJack F Vogel /** 18288cfa0ad2SJack F Vogel * e1000_reset_init_script_82575 - Inits HW defaults after reset 18298cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18308cfa0ad2SJack F Vogel * 18318cfa0ad2SJack F Vogel * Inits recommended HW defaults after a reset when there is no EEPROM 18328cfa0ad2SJack F Vogel * detected. This is only for the 82575. 18338cfa0ad2SJack F Vogel **/ 18348cfa0ad2SJack F Vogel static s32 e1000_reset_init_script_82575(struct e1000_hw *hw) 18358cfa0ad2SJack F Vogel { 18368cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_init_script_82575"); 18378cfa0ad2SJack F Vogel 18388cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82575) { 18398cfa0ad2SJack F Vogel DEBUGOUT("Running reset init script for 82575\n"); 18408cfa0ad2SJack F Vogel /* SerDes configuration via SERDESCTRL */ 18418cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C); 18428cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78); 18438cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23); 18448cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15); 18458cfa0ad2SJack F Vogel 18468cfa0ad2SJack F Vogel /* CCM configuration via CCMCTL register */ 18478cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00); 18488cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00); 18498cfa0ad2SJack F Vogel 18508cfa0ad2SJack F Vogel /* PCIe lanes configuration */ 18518cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC); 18528cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF); 18538cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05); 18548cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81); 18558cfa0ad2SJack F Vogel 18568cfa0ad2SJack F Vogel /* PCIe PLL Configuration */ 18578cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47); 18588cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00); 18598cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00); 18608cfa0ad2SJack F Vogel } 18618cfa0ad2SJack F Vogel 18628cfa0ad2SJack F Vogel return E1000_SUCCESS; 18638cfa0ad2SJack F Vogel } 18648cfa0ad2SJack F Vogel 18658cfa0ad2SJack F Vogel /** 18668cfa0ad2SJack F Vogel * e1000_read_mac_addr_82575 - Read device MAC address 18678cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 18688cfa0ad2SJack F Vogel **/ 18698cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw) 18708cfa0ad2SJack F Vogel { 18718cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 18728cfa0ad2SJack F Vogel 18738cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_mac_addr_82575"); 1874d035aa2dSJack F Vogel 1875d035aa2dSJack F Vogel /* 1876d035aa2dSJack F Vogel * If there's an alternate MAC address place it in RAR0 1877d035aa2dSJack F Vogel * so that it will override the Si installed default perm 1878d035aa2dSJack F Vogel * address. 1879d035aa2dSJack F Vogel */ 1880d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 1881d035aa2dSJack F Vogel if (ret_val) 1882d035aa2dSJack F Vogel goto out; 1883d035aa2dSJack F Vogel 18848cfa0ad2SJack F Vogel ret_val = e1000_read_mac_addr_generic(hw); 18858cfa0ad2SJack F Vogel 1886d035aa2dSJack F Vogel out: 18878cfa0ad2SJack F Vogel return ret_val; 18888cfa0ad2SJack F Vogel } 18898cfa0ad2SJack F Vogel 18908cfa0ad2SJack F Vogel /** 1891a69ed8dfSJack F Vogel * e1000_config_collision_dist_82575 - Configure collision distance 1892a69ed8dfSJack F Vogel * @hw: pointer to the HW structure 1893a69ed8dfSJack F Vogel * 1894a69ed8dfSJack F Vogel * Configures the collision distance to the default value and is used 1895a69ed8dfSJack F Vogel * during link setup. 1896a69ed8dfSJack F Vogel **/ 1897a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw) 1898a69ed8dfSJack F Vogel { 1899a69ed8dfSJack F Vogel u32 tctl_ext; 1900a69ed8dfSJack F Vogel 1901a69ed8dfSJack F Vogel DEBUGFUNC("e1000_config_collision_dist_82575"); 1902a69ed8dfSJack F Vogel 1903a69ed8dfSJack F Vogel tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT); 1904a69ed8dfSJack F Vogel 1905a69ed8dfSJack F Vogel tctl_ext &= ~E1000_TCTL_EXT_COLD; 1906a69ed8dfSJack F Vogel tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT; 1907a69ed8dfSJack F Vogel 1908a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext); 1909a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw); 1910a69ed8dfSJack F Vogel } 1911a69ed8dfSJack F Vogel 1912a69ed8dfSJack F Vogel /** 19138cfa0ad2SJack F Vogel * e1000_power_down_phy_copper_82575 - Remove link during PHY power down 19148cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19158cfa0ad2SJack F Vogel * 19168cfa0ad2SJack F Vogel * In the case of a PHY power down to save power, or to turn off link during a 19178cfa0ad2SJack F Vogel * driver unload, or wake on lan is not enabled, remove the link. 19188cfa0ad2SJack F Vogel **/ 19198cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) 19208cfa0ad2SJack F Vogel { 19218cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 19228cfa0ad2SJack F Vogel 19238cfa0ad2SJack F Vogel if (!(phy->ops.check_reset_block)) 19248cfa0ad2SJack F Vogel return; 19258cfa0ad2SJack F Vogel 19268cfa0ad2SJack F Vogel /* If the management interface is not enabled, then power down */ 19278ec87fc5SJack F Vogel if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw))) 19288cfa0ad2SJack F Vogel e1000_power_down_phy_copper(hw); 19298cfa0ad2SJack F Vogel 19308cfa0ad2SJack F Vogel return; 19318cfa0ad2SJack F Vogel } 19328cfa0ad2SJack F Vogel 19338cfa0ad2SJack F Vogel /** 19348cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters 19358cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19368cfa0ad2SJack F Vogel * 19378cfa0ad2SJack F Vogel * Clears the hardware counters by reading the counter registers. 19388cfa0ad2SJack F Vogel **/ 19398cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) 19408cfa0ad2SJack F Vogel { 19418cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_82575"); 19428cfa0ad2SJack F Vogel 19438cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw); 19448cfa0ad2SJack F Vogel 1945daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC64); 1946daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC127); 1947daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC255); 1948daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC511); 1949daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1023); 1950daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1522); 1951daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC64); 1952daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC127); 1953daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC255); 1954daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC511); 1955daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1023); 1956daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1522); 19578cfa0ad2SJack F Vogel 1958daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ALGNERRC); 1959daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RXERRC); 1960daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TNCRS); 1961daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CEXTERR); 1962daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTC); 1963daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTFC); 19648cfa0ad2SJack F Vogel 1965daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPRC); 1966daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPDC); 1967daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPTC); 19688cfa0ad2SJack F Vogel 1969daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_IAC); 1970daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXOC); 19718cfa0ad2SJack F Vogel 1972daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXPTC); 1973daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXATC); 1974daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXPTC); 1975daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXATC); 1976daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQEC); 1977daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQMTC); 1978daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXDMTC); 19798cfa0ad2SJack F Vogel 1980daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBTMPC); 1981daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTDPMC); 1982daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBRMPC); 1983daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RPTHC); 1984daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGPTC); 1985daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTCBDPC); 1986daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCL); 1987daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCH); 1988daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCL); 1989daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCH); 1990daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_LENERRS); 19918cfa0ad2SJack F Vogel 19928cfa0ad2SJack F Vogel /* This register should not be read in copper configurations */ 19934edd8523SJack F Vogel if ((hw->phy.media_type == e1000_media_type_internal_serdes) || 19944edd8523SJack F Vogel e1000_sgmii_active_82575(hw)) 1995daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_SCVPC); 19968cfa0ad2SJack F Vogel } 19979d81738fSJack F Vogel 19988cfa0ad2SJack F Vogel /** 1999f0ecc46dSJack F Vogel * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable 20008cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 20018cfa0ad2SJack F Vogel * 20028cfa0ad2SJack F Vogel * After rx enable if managability is enabled then there is likely some 20038cfa0ad2SJack F Vogel * bad data at the start of the fifo and possibly in the DMA fifo. This 20048cfa0ad2SJack F Vogel * function clears the fifos and flushes any packets that came in as rx was 20058cfa0ad2SJack F Vogel * being enabled. 20068cfa0ad2SJack F Vogel **/ 20078cfa0ad2SJack F Vogel void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) 20088cfa0ad2SJack F Vogel { 20098cfa0ad2SJack F Vogel u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; 20108cfa0ad2SJack F Vogel int i, ms_wait; 20118cfa0ad2SJack F Vogel 20128cfa0ad2SJack F Vogel DEBUGFUNC("e1000_rx_fifo_workaround_82575"); 20138cfa0ad2SJack F Vogel if (hw->mac.type != e1000_82575 || 20148cfa0ad2SJack F Vogel !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) 20158cfa0ad2SJack F Vogel return; 20168cfa0ad2SJack F Vogel 2017f0ecc46dSJack F Vogel /* Disable all Rx queues */ 20188cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) { 20198cfa0ad2SJack F Vogel rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); 20208cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RXDCTL(i), 20218cfa0ad2SJack F Vogel rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); 20228cfa0ad2SJack F Vogel } 20238cfa0ad2SJack F Vogel /* Poll all queues to verify they have shut down */ 20248cfa0ad2SJack F Vogel for (ms_wait = 0; ms_wait < 10; ms_wait++) { 20258cfa0ad2SJack F Vogel msec_delay(1); 20268cfa0ad2SJack F Vogel rx_enabled = 0; 20278cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) 20288cfa0ad2SJack F Vogel rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i)); 20298cfa0ad2SJack F Vogel if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) 20308cfa0ad2SJack F Vogel break; 20318cfa0ad2SJack F Vogel } 20328cfa0ad2SJack F Vogel 20338cfa0ad2SJack F Vogel if (ms_wait == 10) 20348cfa0ad2SJack F Vogel DEBUGOUT("Queue disable timed out after 10ms\n"); 20358cfa0ad2SJack F Vogel 20368cfa0ad2SJack F Vogel /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all 20378cfa0ad2SJack F Vogel * incoming packets are rejected. Set enable and wait 2ms so that 20388cfa0ad2SJack F Vogel * any packet that was coming in as RCTL.EN was set is flushed 20398cfa0ad2SJack F Vogel */ 20408cfa0ad2SJack F Vogel rfctl = E1000_READ_REG(hw, E1000_RFCTL); 20418cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); 20428cfa0ad2SJack F Vogel 20438cfa0ad2SJack F Vogel rlpml = E1000_READ_REG(hw, E1000_RLPML); 20448cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RLPML, 0); 20458cfa0ad2SJack F Vogel 20468cfa0ad2SJack F Vogel rctl = E1000_READ_REG(hw, E1000_RCTL); 20478cfa0ad2SJack F Vogel temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); 20488cfa0ad2SJack F Vogel temp_rctl |= E1000_RCTL_LPE; 20498cfa0ad2SJack F Vogel 20508cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl); 20518cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN); 20528cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 20538cfa0ad2SJack F Vogel msec_delay(2); 20548cfa0ad2SJack F Vogel 2055f0ecc46dSJack F Vogel /* Enable Rx queues that were previously enabled and restore our 20568cfa0ad2SJack F Vogel * previous state 20578cfa0ad2SJack F Vogel */ 20588cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) 20598cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]); 20608cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, rctl); 20618cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 20628cfa0ad2SJack F Vogel 20638cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RLPML, rlpml); 20648cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); 20658cfa0ad2SJack F Vogel 20668cfa0ad2SJack F Vogel /* Flush receive errors generated by workaround */ 20678cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_ROC); 20688cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_RNBC); 20698cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_MPC); 20708cfa0ad2SJack F Vogel } 2071daf9197cSJack F Vogel 20729d81738fSJack F Vogel /** 20739d81738fSJack F Vogel * e1000_set_pcie_completion_timeout - set pci-e completion timeout 20749d81738fSJack F Vogel * @hw: pointer to the HW structure 20759d81738fSJack F Vogel * 20769d81738fSJack F Vogel * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, 20779d81738fSJack F Vogel * however the hardware default for these parts is 500us to 1ms which is less 20789d81738fSJack F Vogel * than the 10ms recommended by the pci-e spec. To address this we need to 20799d81738fSJack F Vogel * increase the value to either 10ms to 200ms for capability version 1 config, 20809d81738fSJack F Vogel * or 16ms to 55ms for version 2. 20819d81738fSJack F Vogel **/ 20829d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw) 20839d81738fSJack F Vogel { 20849d81738fSJack F Vogel u32 gcr = E1000_READ_REG(hw, E1000_GCR); 20859d81738fSJack F Vogel s32 ret_val = E1000_SUCCESS; 20869d81738fSJack F Vogel u16 pcie_devctl2; 20879d81738fSJack F Vogel 20889d81738fSJack F Vogel /* only take action if timeout value is defaulted to 0 */ 20899d81738fSJack F Vogel if (gcr & E1000_GCR_CMPL_TMOUT_MASK) 20909d81738fSJack F Vogel goto out; 20919d81738fSJack F Vogel 20929d81738fSJack F Vogel /* 20939d81738fSJack F Vogel * if capababilities version is type 1 we can write the 20949d81738fSJack F Vogel * timeout of 10ms to 200ms through the GCR register 20959d81738fSJack F Vogel */ 20969d81738fSJack F Vogel if (!(gcr & E1000_GCR_CAP_VER2)) { 20979d81738fSJack F Vogel gcr |= E1000_GCR_CMPL_TMOUT_10ms; 20989d81738fSJack F Vogel goto out; 20999d81738fSJack F Vogel } 21009d81738fSJack F Vogel 21019d81738fSJack F Vogel /* 21029d81738fSJack F Vogel * for version 2 capabilities we need to write the config space 21039d81738fSJack F Vogel * directly in order to set the completion timeout value for 21049d81738fSJack F Vogel * 16ms to 55ms 21059d81738fSJack F Vogel */ 21069d81738fSJack F Vogel ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 21079d81738fSJack F Vogel &pcie_devctl2); 21089d81738fSJack F Vogel if (ret_val) 21099d81738fSJack F Vogel goto out; 21109d81738fSJack F Vogel 21119d81738fSJack F Vogel pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; 21129d81738fSJack F Vogel 21139d81738fSJack F Vogel ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 21149d81738fSJack F Vogel &pcie_devctl2); 21159d81738fSJack F Vogel out: 21169d81738fSJack F Vogel /* disable completion timeout resend */ 21179d81738fSJack F Vogel gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; 21189d81738fSJack F Vogel 21199d81738fSJack F Vogel E1000_WRITE_REG(hw, E1000_GCR, gcr); 21209d81738fSJack F Vogel return ret_val; 21219d81738fSJack F Vogel } 21229d81738fSJack F Vogel 21237d9119bdSJack F Vogel /** 21247d9119bdSJack F Vogel * e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing 21257d9119bdSJack F Vogel * @hw: pointer to the hardware struct 21267d9119bdSJack F Vogel * @enable: state to enter, either enabled or disabled 21277d9119bdSJack F Vogel * @pf: Physical Function pool - do not set anti-spoofing for the PF 21287d9119bdSJack F Vogel * 21297d9119bdSJack F Vogel * enables/disables L2 switch anti-spoofing functionality. 21307d9119bdSJack F Vogel **/ 21317d9119bdSJack F Vogel void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) 21327d9119bdSJack F Vogel { 21337d9119bdSJack F Vogel u32 dtxswc; 21347d9119bdSJack F Vogel 21357d9119bdSJack F Vogel switch (hw->mac.type) { 21367d9119bdSJack F Vogel case e1000_82576: 21377d9119bdSJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); 21387d9119bdSJack F Vogel if (enable) { 21397d9119bdSJack F Vogel dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK | 21407d9119bdSJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 21417d9119bdSJack F Vogel /* The PF can spoof - it has to in order to 21427d9119bdSJack F Vogel * support emulation mode NICs */ 21434dab5c37SJack F Vogel dtxswc ^= (1 << pf | 1 << (pf + 21444dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_SHIFT)); 21457d9119bdSJack F Vogel } else { 21467d9119bdSJack F Vogel dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | 21477d9119bdSJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 21487d9119bdSJack F Vogel } 21497d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); 21507d9119bdSJack F Vogel break; 21514dab5c37SJack F Vogel case e1000_i350: 21524dab5c37SJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_TXSWC); 21534dab5c37SJack F Vogel if (enable) { 21544dab5c37SJack F Vogel dtxswc |= (E1000_DTXSWC_MAC_SPOOF_MASK | 21554dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 21564dab5c37SJack F Vogel /* The PF can spoof - it has to in order to 21574dab5c37SJack F Vogel * support emulation mode NICs 21584dab5c37SJack F Vogel */ 21594dab5c37SJack F Vogel dtxswc ^= (1 << pf | 1 << (pf + 21604dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_SHIFT)); 21614dab5c37SJack F Vogel } else { 21624dab5c37SJack F Vogel dtxswc &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | 21634dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 21644dab5c37SJack F Vogel } 21654dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc); 21667d9119bdSJack F Vogel default: 21677d9119bdSJack F Vogel break; 21687d9119bdSJack F Vogel } 21697d9119bdSJack F Vogel } 21707d9119bdSJack F Vogel 21714edd8523SJack F Vogel /** 21724edd8523SJack F Vogel * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback 21734edd8523SJack F Vogel * @hw: pointer to the hardware struct 21744edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled 21754edd8523SJack F Vogel * 21764edd8523SJack F Vogel * enables/disables L2 switch loopback functionality. 21774edd8523SJack F Vogel **/ 21784edd8523SJack F Vogel void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) 21794edd8523SJack F Vogel { 21808ec87fc5SJack F Vogel u32 dtxswc; 21814edd8523SJack F Vogel 21828ec87fc5SJack F Vogel switch (hw->mac.type) { 21838ec87fc5SJack F Vogel case e1000_82576: 21848ec87fc5SJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); 21854edd8523SJack F Vogel if (enable) 21864edd8523SJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 21874edd8523SJack F Vogel else 21884edd8523SJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 21894edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); 21908ec87fc5SJack F Vogel break; 2191f0ecc46dSJack F Vogel case e1000_i350: 2192f0ecc46dSJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_TXSWC); 2193f0ecc46dSJack F Vogel if (enable) 2194f0ecc46dSJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 2195f0ecc46dSJack F Vogel else 2196f0ecc46dSJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 2197f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc); 2198f0ecc46dSJack F Vogel break; 21998ec87fc5SJack F Vogel default: 22008ec87fc5SJack F Vogel /* Currently no other hardware supports loopback */ 22018ec87fc5SJack F Vogel break; 22028ec87fc5SJack F Vogel } 22038ec87fc5SJack F Vogel 22048ec87fc5SJack F Vogel 22054edd8523SJack F Vogel } 22064edd8523SJack F Vogel 22074edd8523SJack F Vogel /** 22084edd8523SJack F Vogel * e1000_vmdq_set_replication_pf - enable or disable vmdq replication 22094edd8523SJack F Vogel * @hw: pointer to the hardware struct 22104edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled 22114edd8523SJack F Vogel * 22124edd8523SJack F Vogel * enables/disables replication of packets across multiple pools. 22134edd8523SJack F Vogel **/ 22144edd8523SJack F Vogel void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) 22154edd8523SJack F Vogel { 22164edd8523SJack F Vogel u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); 22174edd8523SJack F Vogel 22184edd8523SJack F Vogel if (enable) 22194edd8523SJack F Vogel vt_ctl |= E1000_VT_CTL_VM_REPL_EN; 22204edd8523SJack F Vogel else 22214edd8523SJack F Vogel vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; 22224edd8523SJack F Vogel 22234edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); 22244edd8523SJack F Vogel } 22254edd8523SJack F Vogel 22264edd8523SJack F Vogel /** 22274edd8523SJack F Vogel * e1000_read_phy_reg_82580 - Read 82580 MDI control register 22284edd8523SJack F Vogel * @hw: pointer to the HW structure 22294edd8523SJack F Vogel * @offset: register offset to be read 22304edd8523SJack F Vogel * @data: pointer to the read data 22314edd8523SJack F Vogel * 22324edd8523SJack F Vogel * Reads the MDI control register in the PHY at offset and stores the 22334edd8523SJack F Vogel * information read to data. 22344edd8523SJack F Vogel **/ 22354edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) 22364edd8523SJack F Vogel { 22374edd8523SJack F Vogel s32 ret_val; 22384edd8523SJack F Vogel 22394edd8523SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_82580"); 22404edd8523SJack F Vogel 22414edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 22424edd8523SJack F Vogel if (ret_val) 22434edd8523SJack F Vogel goto out; 22444edd8523SJack F Vogel 22454edd8523SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw, offset, data); 22464edd8523SJack F Vogel 22474edd8523SJack F Vogel hw->phy.ops.release(hw); 22484edd8523SJack F Vogel 22494edd8523SJack F Vogel out: 22504edd8523SJack F Vogel return ret_val; 22514edd8523SJack F Vogel } 22524edd8523SJack F Vogel 22534edd8523SJack F Vogel /** 22544edd8523SJack F Vogel * e1000_write_phy_reg_82580 - Write 82580 MDI control register 22554edd8523SJack F Vogel * @hw: pointer to the HW structure 22564edd8523SJack F Vogel * @offset: register offset to write to 22574edd8523SJack F Vogel * @data: data to write to register at offset 22584edd8523SJack F Vogel * 22594edd8523SJack F Vogel * Writes data to MDI control register in the PHY at offset. 22604edd8523SJack F Vogel **/ 22614edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data) 22624edd8523SJack F Vogel { 22634edd8523SJack F Vogel s32 ret_val; 22644edd8523SJack F Vogel 22654edd8523SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_82580"); 22664edd8523SJack F Vogel 22674edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 22684edd8523SJack F Vogel if (ret_val) 22694edd8523SJack F Vogel goto out; 22704edd8523SJack F Vogel 22714edd8523SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw, offset, data); 22724edd8523SJack F Vogel 22734edd8523SJack F Vogel hw->phy.ops.release(hw); 22744edd8523SJack F Vogel 22754edd8523SJack F Vogel out: 22764edd8523SJack F Vogel return ret_val; 22774edd8523SJack F Vogel } 2278a69ed8dfSJack F Vogel 22794edd8523SJack F Vogel /** 22807d9119bdSJack F Vogel * e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits 22817d9119bdSJack F Vogel * @hw: pointer to the HW structure 22827d9119bdSJack F Vogel * 22834dab5c37SJack F Vogel * This resets the the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on 22847d9119bdSJack F Vogel * the values found in the EEPROM. This addresses an issue in which these 22857d9119bdSJack F Vogel * bits are not restored from EEPROM after reset. 22867d9119bdSJack F Vogel **/ 22877d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw) 22887d9119bdSJack F Vogel { 22897d9119bdSJack F Vogel s32 ret_val = E1000_SUCCESS; 22907d9119bdSJack F Vogel u32 mdicnfg; 2291f0ecc46dSJack F Vogel u16 nvm_data = 0; 22927d9119bdSJack F Vogel 22937d9119bdSJack F Vogel DEBUGFUNC("e1000_reset_mdicnfg_82580"); 22947d9119bdSJack F Vogel 22957d9119bdSJack F Vogel if (hw->mac.type != e1000_82580) 22967d9119bdSJack F Vogel goto out; 22977d9119bdSJack F Vogel if (!e1000_sgmii_active_82575(hw)) 22987d9119bdSJack F Vogel goto out; 22997d9119bdSJack F Vogel 23007d9119bdSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + 23017d9119bdSJack F Vogel NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, 23027d9119bdSJack F Vogel &nvm_data); 23037d9119bdSJack F Vogel if (ret_val) { 23047d9119bdSJack F Vogel DEBUGOUT("NVM Read Error\n"); 23057d9119bdSJack F Vogel goto out; 23067d9119bdSJack F Vogel } 23077d9119bdSJack F Vogel 23087d9119bdSJack F Vogel mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); 23097d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_EXT_MDIO) 23107d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_EXT_MDIO; 23117d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_COM_MDIO) 23127d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_COM_MDIO; 23137d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); 23147d9119bdSJack F Vogel out: 23157d9119bdSJack F Vogel return ret_val; 23167d9119bdSJack F Vogel } 23177d9119bdSJack F Vogel 23187d9119bdSJack F Vogel /** 23194edd8523SJack F Vogel * e1000_reset_hw_82580 - Reset hardware 23204edd8523SJack F Vogel * @hw: pointer to the HW structure 23214edd8523SJack F Vogel * 23224edd8523SJack F Vogel * This resets function or entire device (all ports, etc.) 23234edd8523SJack F Vogel * to a known state. 23244edd8523SJack F Vogel **/ 23254edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw) 23264edd8523SJack F Vogel { 23274edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS; 23284edd8523SJack F Vogel /* BH SW mailbox bit in SW_FW_SYNC */ 23294edd8523SJack F Vogel u16 swmbsw_mask = E1000_SW_SYNCH_MB; 2330f0ecc46dSJack F Vogel u32 ctrl; 23314edd8523SJack F Vogel bool global_device_reset = hw->dev_spec._82575.global_device_reset; 23324edd8523SJack F Vogel 23334edd8523SJack F Vogel DEBUGFUNC("e1000_reset_hw_82580"); 23344edd8523SJack F Vogel 23354edd8523SJack F Vogel hw->dev_spec._82575.global_device_reset = FALSE; 23364edd8523SJack F Vogel 23374edd8523SJack F Vogel /* Get current control state. */ 23384edd8523SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 23394edd8523SJack F Vogel 23404edd8523SJack F Vogel /* 23414edd8523SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection 23424edd8523SJack F Vogel * on the last TLP read/write transaction when MAC is reset. 23434edd8523SJack F Vogel */ 23444edd8523SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw); 23454edd8523SJack F Vogel if (ret_val) 23464edd8523SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 23474edd8523SJack F Vogel 23484edd8523SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 23494edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 23504edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 23514edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 23524edd8523SJack F Vogel E1000_WRITE_FLUSH(hw); 23534edd8523SJack F Vogel 23544edd8523SJack F Vogel msec_delay(10); 23554edd8523SJack F Vogel 23564edd8523SJack F Vogel /* Determine whether or not a global dev reset is requested */ 2357*ab5d0362SJack F Vogel if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw, 23584dab5c37SJack F Vogel swmbsw_mask)) 23594edd8523SJack F Vogel global_device_reset = FALSE; 23604edd8523SJack F Vogel 23614dab5c37SJack F Vogel if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) & 23624dab5c37SJack F Vogel E1000_STAT_DEV_RST_SET)) 23634edd8523SJack F Vogel ctrl |= E1000_CTRL_DEV_RST; 23644edd8523SJack F Vogel else 23654edd8523SJack F Vogel ctrl |= E1000_CTRL_RST; 23664edd8523SJack F Vogel 23674edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 23684dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 23694edd8523SJack F Vogel 23704edd8523SJack F Vogel /* Add delay to insure DEV_RST has time to complete */ 23714edd8523SJack F Vogel if (global_device_reset) 23724edd8523SJack F Vogel msec_delay(5); 23734edd8523SJack F Vogel 23744edd8523SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw); 23754edd8523SJack F Vogel if (ret_val) { 23764edd8523SJack F Vogel /* 23774edd8523SJack F Vogel * When auto config read does not complete, do not 23784edd8523SJack F Vogel * return with an error. This can happen in situations 23794edd8523SJack F Vogel * where there is no eeprom and prevents getting link. 23804edd8523SJack F Vogel */ 23814edd8523SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n"); 23824edd8523SJack F Vogel } 23834edd8523SJack F Vogel 23844edd8523SJack F Vogel /* If EEPROM is not present, run manual init scripts */ 2385*ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) 23864edd8523SJack F Vogel e1000_reset_init_script_82575(hw); 23874edd8523SJack F Vogel 23884edd8523SJack F Vogel /* clear global device reset status bit */ 23894edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); 23904edd8523SJack F Vogel 23914edd8523SJack F Vogel /* Clear any pending interrupt events. */ 23924edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 2393f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR); 23944edd8523SJack F Vogel 23957d9119bdSJack F Vogel ret_val = e1000_reset_mdicnfg_82580(hw); 23967d9119bdSJack F Vogel if (ret_val) 23977d9119bdSJack F Vogel DEBUGOUT("Could not reset MDICNFG based on EEPROM\n"); 23987d9119bdSJack F Vogel 23994edd8523SJack F Vogel /* Install any alternate MAC address into RAR0 */ 24004edd8523SJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 24014edd8523SJack F Vogel 24024edd8523SJack F Vogel /* Release semaphore */ 24034edd8523SJack F Vogel if (global_device_reset) 2404*ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); 24054edd8523SJack F Vogel 24064edd8523SJack F Vogel return ret_val; 24074edd8523SJack F Vogel } 24084edd8523SJack F Vogel 24094edd8523SJack F Vogel /** 2410f0ecc46dSJack F Vogel * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size 24114edd8523SJack F Vogel * @data: data received by reading RXPBS register 24124edd8523SJack F Vogel * 24134edd8523SJack F Vogel * The 82580 uses a table based approach for packet buffer allocation sizes. 24144edd8523SJack F Vogel * This function converts the retrieved value into the correct table value 24154edd8523SJack F Vogel * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 24164edd8523SJack F Vogel * 0x0 36 72 144 1 2 4 8 16 24174edd8523SJack F Vogel * 0x8 35 70 140 rsv rsv rsv rsv rsv 24184edd8523SJack F Vogel */ 24194edd8523SJack F Vogel u16 e1000_rxpbs_adjust_82580(u32 data) 24204edd8523SJack F Vogel { 24214edd8523SJack F Vogel u16 ret_val = 0; 24224edd8523SJack F Vogel 24234edd8523SJack F Vogel if (data < E1000_82580_RXPBS_TABLE_SIZE) 24244edd8523SJack F Vogel ret_val = e1000_82580_rxpbs_table[data]; 24254edd8523SJack F Vogel 24264edd8523SJack F Vogel return ret_val; 24274edd8523SJack F Vogel } 2428f0ecc46dSJack F Vogel 2429f0ecc46dSJack F Vogel /** 2430f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_with_offset - Validate EEPROM 2431f0ecc46dSJack F Vogel * checksum 2432f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2433f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region 2434f0ecc46dSJack F Vogel * 2435f0ecc46dSJack F Vogel * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 2436f0ecc46dSJack F Vogel * and then verifies that the sum of the EEPROM is equal to 0xBABA. 2437f0ecc46dSJack F Vogel **/ 2438f0ecc46dSJack F Vogel s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) 2439f0ecc46dSJack F Vogel { 2440f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2441f0ecc46dSJack F Vogel u16 checksum = 0; 2442f0ecc46dSJack F Vogel u16 i, nvm_data; 2443f0ecc46dSJack F Vogel 2444f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_with_offset"); 2445f0ecc46dSJack F Vogel 2446f0ecc46dSJack F Vogel for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) { 2447f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 2448f0ecc46dSJack F Vogel if (ret_val) { 2449f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2450f0ecc46dSJack F Vogel goto out; 2451f0ecc46dSJack F Vogel } 2452f0ecc46dSJack F Vogel checksum += nvm_data; 2453f0ecc46dSJack F Vogel } 2454f0ecc46dSJack F Vogel 2455f0ecc46dSJack F Vogel if (checksum != (u16) NVM_SUM) { 2456f0ecc46dSJack F Vogel DEBUGOUT("NVM Checksum Invalid\n"); 2457f0ecc46dSJack F Vogel ret_val = -E1000_ERR_NVM; 2458f0ecc46dSJack F Vogel goto out; 2459f0ecc46dSJack F Vogel } 2460f0ecc46dSJack F Vogel 2461f0ecc46dSJack F Vogel out: 2462f0ecc46dSJack F Vogel return ret_val; 2463f0ecc46dSJack F Vogel } 2464f0ecc46dSJack F Vogel 2465f0ecc46dSJack F Vogel /** 2466f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_with_offset - Update EEPROM 2467f0ecc46dSJack F Vogel * checksum 2468f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2469f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region 2470f0ecc46dSJack F Vogel * 2471f0ecc46dSJack F Vogel * Updates the EEPROM checksum by reading/adding each word of the EEPROM 2472f0ecc46dSJack F Vogel * up to the checksum. Then calculates the EEPROM checksum and writes the 2473f0ecc46dSJack F Vogel * value to the EEPROM. 2474f0ecc46dSJack F Vogel **/ 2475f0ecc46dSJack F Vogel s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) 2476f0ecc46dSJack F Vogel { 2477f0ecc46dSJack F Vogel s32 ret_val; 2478f0ecc46dSJack F Vogel u16 checksum = 0; 2479f0ecc46dSJack F Vogel u16 i, nvm_data; 2480f0ecc46dSJack F Vogel 2481f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_with_offset"); 2482f0ecc46dSJack F Vogel 2483f0ecc46dSJack F Vogel for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) { 2484f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 2485f0ecc46dSJack F Vogel if (ret_val) { 2486f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error while updating checksum.\n"); 2487f0ecc46dSJack F Vogel goto out; 2488f0ecc46dSJack F Vogel } 2489f0ecc46dSJack F Vogel checksum += nvm_data; 2490f0ecc46dSJack F Vogel } 2491f0ecc46dSJack F Vogel checksum = (u16) NVM_SUM - checksum; 2492f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1, 2493f0ecc46dSJack F Vogel &checksum); 2494f0ecc46dSJack F Vogel if (ret_val) 2495f0ecc46dSJack F Vogel DEBUGOUT("NVM Write Error while updating checksum.\n"); 2496f0ecc46dSJack F Vogel 2497f0ecc46dSJack F Vogel out: 2498f0ecc46dSJack F Vogel return ret_val; 2499f0ecc46dSJack F Vogel } 2500f0ecc46dSJack F Vogel 2501f0ecc46dSJack F Vogel /** 2502f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum 2503f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2504f0ecc46dSJack F Vogel * 2505f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of 2506f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is 2507f0ecc46dSJack F Vogel * equal to 0xBABA. 2508f0ecc46dSJack F Vogel **/ 2509f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw) 2510f0ecc46dSJack F Vogel { 2511f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2512f0ecc46dSJack F Vogel u16 eeprom_regions_count = 1; 2513f0ecc46dSJack F Vogel u16 j, nvm_data; 2514f0ecc46dSJack F Vogel u16 nvm_offset; 2515f0ecc46dSJack F Vogel 2516f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_82580"); 2517f0ecc46dSJack F Vogel 2518f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 2519f0ecc46dSJack F Vogel if (ret_val) { 2520f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2521f0ecc46dSJack F Vogel goto out; 2522f0ecc46dSJack F Vogel } 2523f0ecc46dSJack F Vogel 2524f0ecc46dSJack F Vogel if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { 2525f0ecc46dSJack F Vogel /* if chekcsums compatibility bit is set validate checksums 2526f0ecc46dSJack F Vogel * for all 4 ports. */ 2527f0ecc46dSJack F Vogel eeprom_regions_count = 4; 2528f0ecc46dSJack F Vogel } 2529f0ecc46dSJack F Vogel 2530f0ecc46dSJack F Vogel for (j = 0; j < eeprom_regions_count; j++) { 2531f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2532f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw, 2533f0ecc46dSJack F Vogel nvm_offset); 2534f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2535f0ecc46dSJack F Vogel goto out; 2536f0ecc46dSJack F Vogel } 2537f0ecc46dSJack F Vogel 2538f0ecc46dSJack F Vogel out: 2539f0ecc46dSJack F Vogel return ret_val; 2540f0ecc46dSJack F Vogel } 2541f0ecc46dSJack F Vogel 2542f0ecc46dSJack F Vogel /** 2543f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_82580 - Update EEPROM checksum 2544f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2545f0ecc46dSJack F Vogel * 2546f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding 2547f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM 2548f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM. 2549f0ecc46dSJack F Vogel **/ 2550f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) 2551f0ecc46dSJack F Vogel { 2552f0ecc46dSJack F Vogel s32 ret_val; 2553f0ecc46dSJack F Vogel u16 j, nvm_data; 2554f0ecc46dSJack F Vogel u16 nvm_offset; 2555f0ecc46dSJack F Vogel 2556f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_82580"); 2557f0ecc46dSJack F Vogel 2558f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 2559f0ecc46dSJack F Vogel if (ret_val) { 25604dab5c37SJack F Vogel DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n"); 2561f0ecc46dSJack F Vogel goto out; 2562f0ecc46dSJack F Vogel } 2563f0ecc46dSJack F Vogel 2564*ab5d0362SJack F Vogel if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { 2565f0ecc46dSJack F Vogel /* set compatibility bit to validate checksums appropriately */ 2566f0ecc46dSJack F Vogel nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; 2567f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, 2568f0ecc46dSJack F Vogel &nvm_data); 2569f0ecc46dSJack F Vogel if (ret_val) { 25704dab5c37SJack F Vogel DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n"); 2571f0ecc46dSJack F Vogel goto out; 2572f0ecc46dSJack F Vogel } 2573f0ecc46dSJack F Vogel } 2574f0ecc46dSJack F Vogel 2575f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2576f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2577f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); 25784dab5c37SJack F Vogel if (ret_val) 2579f0ecc46dSJack F Vogel goto out; 2580f0ecc46dSJack F Vogel } 2581f0ecc46dSJack F Vogel 2582f0ecc46dSJack F Vogel out: 2583f0ecc46dSJack F Vogel return ret_val; 2584f0ecc46dSJack F Vogel } 2585f0ecc46dSJack F Vogel 2586f0ecc46dSJack F Vogel /** 2587f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum 2588f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2589f0ecc46dSJack F Vogel * 2590f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of 2591f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is 2592f0ecc46dSJack F Vogel * equal to 0xBABA. 2593f0ecc46dSJack F Vogel **/ 2594f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw) 2595f0ecc46dSJack F Vogel { 2596f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2597f0ecc46dSJack F Vogel u16 j; 2598f0ecc46dSJack F Vogel u16 nvm_offset; 2599f0ecc46dSJack F Vogel 2600f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_i350"); 2601f0ecc46dSJack F Vogel 2602f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2603f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2604f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw, 2605f0ecc46dSJack F Vogel nvm_offset); 2606f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2607f0ecc46dSJack F Vogel goto out; 2608f0ecc46dSJack F Vogel } 2609f0ecc46dSJack F Vogel 2610f0ecc46dSJack F Vogel out: 2611f0ecc46dSJack F Vogel return ret_val; 2612f0ecc46dSJack F Vogel } 2613f0ecc46dSJack F Vogel 2614f0ecc46dSJack F Vogel /** 2615f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_i350 - Update EEPROM checksum 2616f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2617f0ecc46dSJack F Vogel * 2618f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding 2619f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM 2620f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM. 2621f0ecc46dSJack F Vogel **/ 2622f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw) 2623f0ecc46dSJack F Vogel { 2624f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2625f0ecc46dSJack F Vogel u16 j; 2626f0ecc46dSJack F Vogel u16 nvm_offset; 2627f0ecc46dSJack F Vogel 2628f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_i350"); 2629f0ecc46dSJack F Vogel 2630f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2631f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2632f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); 2633f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2634f0ecc46dSJack F Vogel goto out; 2635f0ecc46dSJack F Vogel } 2636f0ecc46dSJack F Vogel 2637f0ecc46dSJack F Vogel out: 2638f0ecc46dSJack F Vogel return ret_val; 2639f0ecc46dSJack F Vogel } 2640f0ecc46dSJack F Vogel 2641f0ecc46dSJack F Vogel /** 2642f0ecc46dSJack F Vogel * e1000_set_eee_i350 - Enable/disable EEE support 2643f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2644f0ecc46dSJack F Vogel * 2645f0ecc46dSJack F Vogel * Enable/disable EEE based on setting in dev_spec structure. 2646f0ecc46dSJack F Vogel * 2647f0ecc46dSJack F Vogel **/ 2648f0ecc46dSJack F Vogel s32 e1000_set_eee_i350(struct e1000_hw *hw) 2649f0ecc46dSJack F Vogel { 2650f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 26514dab5c37SJack F Vogel u32 ipcnfg, eeer; 2652f0ecc46dSJack F Vogel 2653f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_eee_i350"); 2654f0ecc46dSJack F Vogel 26554dab5c37SJack F Vogel if ((hw->mac.type < e1000_i350) || 26564dab5c37SJack F Vogel (hw->phy.media_type != e1000_media_type_copper)) 2657f0ecc46dSJack F Vogel goto out; 2658f0ecc46dSJack F Vogel ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); 2659f0ecc46dSJack F Vogel eeer = E1000_READ_REG(hw, E1000_EEER); 2660f0ecc46dSJack F Vogel 2661f0ecc46dSJack F Vogel /* enable or disable per user setting */ 2662f0ecc46dSJack F Vogel if (!(hw->dev_spec._82575.eee_disable)) { 26634dab5c37SJack F Vogel ipcnfg |= (E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); 26644dab5c37SJack F Vogel eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | 2665f0ecc46dSJack F Vogel E1000_EEER_LPI_FC); 2666f0ecc46dSJack F Vogel 2667f0ecc46dSJack F Vogel } else { 26684dab5c37SJack F Vogel ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); 26694dab5c37SJack F Vogel eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | 2670f0ecc46dSJack F Vogel E1000_EEER_LPI_FC); 2671f0ecc46dSJack F Vogel } 2672f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg); 2673f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_EEER, eeer); 2674f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_IPCNFG); 2675f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_EEER); 2676f0ecc46dSJack F Vogel out: 2677f0ecc46dSJack F Vogel 2678f0ecc46dSJack F Vogel return ret_val; 2679f0ecc46dSJack F Vogel } 26804dab5c37SJack F Vogel 26814dab5c37SJack F Vogel /* Due to a hw errata, if the host tries to configure the VFTA register 26824dab5c37SJack F Vogel * while performing queries from the BMC or DMA, then the VFTA in some 26834dab5c37SJack F Vogel * cases won't be written. 26844dab5c37SJack F Vogel */ 26854dab5c37SJack F Vogel 26864dab5c37SJack F Vogel /** 26874dab5c37SJack F Vogel * e1000_clear_vfta_i350 - Clear VLAN filter table 26884dab5c37SJack F Vogel * @hw: pointer to the HW structure 26894dab5c37SJack F Vogel * 26904dab5c37SJack F Vogel * Clears the register array which contains the VLAN filter table by 26914dab5c37SJack F Vogel * setting all the values to 0. 26924dab5c37SJack F Vogel **/ 26934dab5c37SJack F Vogel void e1000_clear_vfta_i350(struct e1000_hw *hw) 26944dab5c37SJack F Vogel { 26954dab5c37SJack F Vogel u32 offset; 26964dab5c37SJack F Vogel int i; 26974dab5c37SJack F Vogel 26984dab5c37SJack F Vogel DEBUGFUNC("e1000_clear_vfta_350"); 26994dab5c37SJack F Vogel 27004dab5c37SJack F Vogel for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { 27014dab5c37SJack F Vogel for (i = 0; i < 10; i++) 27024dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); 27034dab5c37SJack F Vogel 27044dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 27054dab5c37SJack F Vogel } 27064dab5c37SJack F Vogel } 27074dab5c37SJack F Vogel 27084dab5c37SJack F Vogel /** 27094dab5c37SJack F Vogel * e1000_write_vfta_i350 - Write value to VLAN filter table 27104dab5c37SJack F Vogel * @hw: pointer to the HW structure 27114dab5c37SJack F Vogel * @offset: register offset in VLAN filter table 27124dab5c37SJack F Vogel * @value: register value written to VLAN filter table 27134dab5c37SJack F Vogel * 27144dab5c37SJack F Vogel * Writes value at the given offset in the register array which stores 27154dab5c37SJack F Vogel * the VLAN filter table. 27164dab5c37SJack F Vogel **/ 27174dab5c37SJack F Vogel void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) 27184dab5c37SJack F Vogel { 27194dab5c37SJack F Vogel int i; 27204dab5c37SJack F Vogel 27214dab5c37SJack F Vogel DEBUGFUNC("e1000_write_vfta_350"); 27224dab5c37SJack F Vogel 27234dab5c37SJack F Vogel for (i = 0; i < 10; i++) 27244dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); 27254dab5c37SJack F Vogel 27264dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 27274dab5c37SJack F Vogel } 27284dab5c37SJack F Vogel 27294dab5c37SJack F Vogel 27304dab5c37SJack F Vogel /** 27314dab5c37SJack F Vogel * e1000_set_i2c_bb - Enable I2C bit-bang 27324dab5c37SJack F Vogel * @hw: pointer to the HW structure 27334dab5c37SJack F Vogel * 27344dab5c37SJack F Vogel * Enable I2C bit-bang interface 27354dab5c37SJack F Vogel * 27364dab5c37SJack F Vogel **/ 27374dab5c37SJack F Vogel s32 e1000_set_i2c_bb(struct e1000_hw *hw) 27384dab5c37SJack F Vogel { 27394dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS; 27404dab5c37SJack F Vogel u32 ctrl_ext, i2cparams; 27414dab5c37SJack F Vogel 27424dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_bb"); 27434dab5c37SJack F Vogel 27444dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 27454dab5c37SJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA; 27464dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 27474dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 27484dab5c37SJack F Vogel 27494dab5c37SJack F Vogel i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS); 27504dab5c37SJack F Vogel i2cparams |= E1000_I2CBB_EN; 27514dab5c37SJack F Vogel i2cparams |= E1000_I2C_DATA_OE_N; 27524dab5c37SJack F Vogel i2cparams |= E1000_I2C_CLK_OE_N; 27534dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams); 27544dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 27554dab5c37SJack F Vogel 27564dab5c37SJack F Vogel return ret_val; 27574dab5c37SJack F Vogel } 27584dab5c37SJack F Vogel 27594dab5c37SJack F Vogel /** 27604dab5c37SJack F Vogel * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C 27614dab5c37SJack F Vogel * @hw: pointer to hardware structure 27624dab5c37SJack F Vogel * @byte_offset: byte offset to read 2763*ab5d0362SJack F Vogel * @dev_addr: device address 27644dab5c37SJack F Vogel * @data: value read 27654dab5c37SJack F Vogel * 27664dab5c37SJack F Vogel * Performs byte read operation over I2C interface at 27674dab5c37SJack F Vogel * a specified device address. 27684dab5c37SJack F Vogel **/ 27694dab5c37SJack F Vogel s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, 27704dab5c37SJack F Vogel u8 dev_addr, u8 *data) 27714dab5c37SJack F Vogel { 27724dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 27734dab5c37SJack F Vogel u32 max_retry = 10; 27744dab5c37SJack F Vogel u32 retry = 1; 27754dab5c37SJack F Vogel u16 swfw_mask = 0; 27764dab5c37SJack F Vogel 2777*ab5d0362SJack F Vogel bool nack = TRUE; 27784dab5c37SJack F Vogel 27794dab5c37SJack F Vogel DEBUGFUNC("e1000_read_i2c_byte_generic"); 27804dab5c37SJack F Vogel 27814dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM; 27824dab5c37SJack F Vogel 27834dab5c37SJack F Vogel do { 2784*ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) 27854dab5c37SJack F Vogel != E1000_SUCCESS) { 27864dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC; 27874dab5c37SJack F Vogel goto read_byte_out; 27884dab5c37SJack F Vogel } 27894dab5c37SJack F Vogel 27904dab5c37SJack F Vogel e1000_i2c_start(hw); 27914dab5c37SJack F Vogel 27924dab5c37SJack F Vogel /* Device Address and write indication */ 27934dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr); 27944dab5c37SJack F Vogel if (status != E1000_SUCCESS) 27954dab5c37SJack F Vogel goto fail; 27964dab5c37SJack F Vogel 27974dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 27984dab5c37SJack F Vogel if (status != E1000_SUCCESS) 27994dab5c37SJack F Vogel goto fail; 28004dab5c37SJack F Vogel 28014dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset); 28024dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28034dab5c37SJack F Vogel goto fail; 28044dab5c37SJack F Vogel 28054dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 28064dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28074dab5c37SJack F Vogel goto fail; 28084dab5c37SJack F Vogel 28094dab5c37SJack F Vogel e1000_i2c_start(hw); 28104dab5c37SJack F Vogel 28114dab5c37SJack F Vogel /* Device Address and read indication */ 28124dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1)); 28134dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28144dab5c37SJack F Vogel goto fail; 28154dab5c37SJack F Vogel 28164dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 28174dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28184dab5c37SJack F Vogel goto fail; 28194dab5c37SJack F Vogel 28204dab5c37SJack F Vogel status = e1000_clock_in_i2c_byte(hw, data); 28214dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28224dab5c37SJack F Vogel goto fail; 28234dab5c37SJack F Vogel 28244dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, nack); 28254dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28264dab5c37SJack F Vogel goto fail; 28274dab5c37SJack F Vogel 28284dab5c37SJack F Vogel e1000_i2c_stop(hw); 28294dab5c37SJack F Vogel break; 28304dab5c37SJack F Vogel 28314dab5c37SJack F Vogel fail: 2832*ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 28334dab5c37SJack F Vogel msec_delay(100); 28344dab5c37SJack F Vogel e1000_i2c_bus_clear(hw); 28354dab5c37SJack F Vogel retry++; 28364dab5c37SJack F Vogel if (retry < max_retry) 28374dab5c37SJack F Vogel DEBUGOUT("I2C byte read error - Retrying.\n"); 28384dab5c37SJack F Vogel else 28394dab5c37SJack F Vogel DEBUGOUT("I2C byte read error.\n"); 28404dab5c37SJack F Vogel 28414dab5c37SJack F Vogel } while (retry < max_retry); 28424dab5c37SJack F Vogel 2843*ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 28444dab5c37SJack F Vogel 28454dab5c37SJack F Vogel read_byte_out: 28464dab5c37SJack F Vogel 28474dab5c37SJack F Vogel return status; 28484dab5c37SJack F Vogel } 28494dab5c37SJack F Vogel 28504dab5c37SJack F Vogel /** 28514dab5c37SJack F Vogel * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C 28524dab5c37SJack F Vogel * @hw: pointer to hardware structure 28534dab5c37SJack F Vogel * @byte_offset: byte offset to write 2854*ab5d0362SJack F Vogel * @dev_addr: device address 28554dab5c37SJack F Vogel * @data: value to write 28564dab5c37SJack F Vogel * 28574dab5c37SJack F Vogel * Performs byte write operation over I2C interface at 28584dab5c37SJack F Vogel * a specified device address. 28594dab5c37SJack F Vogel **/ 28604dab5c37SJack F Vogel s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, 28614dab5c37SJack F Vogel u8 dev_addr, u8 data) 28624dab5c37SJack F Vogel { 28634dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 28644dab5c37SJack F Vogel u32 max_retry = 1; 28654dab5c37SJack F Vogel u32 retry = 0; 28664dab5c37SJack F Vogel u16 swfw_mask = 0; 28674dab5c37SJack F Vogel 28684dab5c37SJack F Vogel DEBUGFUNC("e1000_write_i2c_byte_generic"); 28694dab5c37SJack F Vogel 28704dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM; 28714dab5c37SJack F Vogel 2872*ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { 28734dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC; 28744dab5c37SJack F Vogel goto write_byte_out; 28754dab5c37SJack F Vogel } 28764dab5c37SJack F Vogel 28774dab5c37SJack F Vogel do { 28784dab5c37SJack F Vogel e1000_i2c_start(hw); 28794dab5c37SJack F Vogel 28804dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr); 28814dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28824dab5c37SJack F Vogel goto fail; 28834dab5c37SJack F Vogel 28844dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 28854dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28864dab5c37SJack F Vogel goto fail; 28874dab5c37SJack F Vogel 28884dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset); 28894dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28904dab5c37SJack F Vogel goto fail; 28914dab5c37SJack F Vogel 28924dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 28934dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28944dab5c37SJack F Vogel goto fail; 28954dab5c37SJack F Vogel 28964dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, data); 28974dab5c37SJack F Vogel if (status != E1000_SUCCESS) 28984dab5c37SJack F Vogel goto fail; 28994dab5c37SJack F Vogel 29004dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 29014dab5c37SJack F Vogel if (status != E1000_SUCCESS) 29024dab5c37SJack F Vogel goto fail; 29034dab5c37SJack F Vogel 29044dab5c37SJack F Vogel e1000_i2c_stop(hw); 29054dab5c37SJack F Vogel break; 29064dab5c37SJack F Vogel 29074dab5c37SJack F Vogel fail: 29084dab5c37SJack F Vogel e1000_i2c_bus_clear(hw); 29094dab5c37SJack F Vogel retry++; 29104dab5c37SJack F Vogel if (retry < max_retry) 29114dab5c37SJack F Vogel DEBUGOUT("I2C byte write error - Retrying.\n"); 29124dab5c37SJack F Vogel else 29134dab5c37SJack F Vogel DEBUGOUT("I2C byte write error.\n"); 29144dab5c37SJack F Vogel } while (retry < max_retry); 29154dab5c37SJack F Vogel 2916*ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 29174dab5c37SJack F Vogel 29184dab5c37SJack F Vogel write_byte_out: 29194dab5c37SJack F Vogel 29204dab5c37SJack F Vogel return status; 29214dab5c37SJack F Vogel } 29224dab5c37SJack F Vogel 29234dab5c37SJack F Vogel /** 29244dab5c37SJack F Vogel * e1000_i2c_start - Sets I2C start condition 29254dab5c37SJack F Vogel * @hw: pointer to hardware structure 29264dab5c37SJack F Vogel * 29274dab5c37SJack F Vogel * Sets I2C start condition (High -> Low on SDA while SCL is High) 29284dab5c37SJack F Vogel **/ 29294dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw) 29304dab5c37SJack F Vogel { 29314dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 29324dab5c37SJack F Vogel 29334dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_start"); 29344dab5c37SJack F Vogel 29354dab5c37SJack F Vogel /* Start condition must begin with data and clock high */ 29364dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 29374dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 29384dab5c37SJack F Vogel 29394dab5c37SJack F Vogel /* Setup time for start condition (4.7us) */ 29404dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STA); 29414dab5c37SJack F Vogel 29424dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0); 29434dab5c37SJack F Vogel 29444dab5c37SJack F Vogel /* Hold time for start condition (4us) */ 29454dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HD_STA); 29464dab5c37SJack F Vogel 29474dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 29484dab5c37SJack F Vogel 29494dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 29504dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 29514dab5c37SJack F Vogel 29524dab5c37SJack F Vogel } 29534dab5c37SJack F Vogel 29544dab5c37SJack F Vogel /** 29554dab5c37SJack F Vogel * e1000_i2c_stop - Sets I2C stop condition 29564dab5c37SJack F Vogel * @hw: pointer to hardware structure 29574dab5c37SJack F Vogel * 29584dab5c37SJack F Vogel * Sets I2C stop condition (Low -> High on SDA while SCL is High) 29594dab5c37SJack F Vogel **/ 29604dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw) 29614dab5c37SJack F Vogel { 29624dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 29634dab5c37SJack F Vogel 29644dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_stop"); 29654dab5c37SJack F Vogel 29664dab5c37SJack F Vogel /* Stop condition must begin with data low and clock high */ 29674dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0); 29684dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 29694dab5c37SJack F Vogel 29704dab5c37SJack F Vogel /* Setup time for stop condition (4us) */ 29714dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STO); 29724dab5c37SJack F Vogel 29734dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 29744dab5c37SJack F Vogel 29754dab5c37SJack F Vogel /* bus free time between stop and start (4.7us)*/ 29764dab5c37SJack F Vogel usec_delay(E1000_I2C_T_BUF); 29774dab5c37SJack F Vogel } 29784dab5c37SJack F Vogel 29794dab5c37SJack F Vogel /** 29804dab5c37SJack F Vogel * e1000_clock_in_i2c_byte - Clocks in one byte via I2C 29814dab5c37SJack F Vogel * @hw: pointer to hardware structure 29824dab5c37SJack F Vogel * @data: data byte to clock in 29834dab5c37SJack F Vogel * 29844dab5c37SJack F Vogel * Clocks in one byte data via I2C data/clock 29854dab5c37SJack F Vogel **/ 29864dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data) 29874dab5c37SJack F Vogel { 29884dab5c37SJack F Vogel s32 i; 29894dab5c37SJack F Vogel bool bit = 0; 29904dab5c37SJack F Vogel 29914dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_byte"); 29924dab5c37SJack F Vogel 29934dab5c37SJack F Vogel *data = 0; 29944dab5c37SJack F Vogel for (i = 7; i >= 0; i--) { 29954dab5c37SJack F Vogel e1000_clock_in_i2c_bit(hw, &bit); 29964dab5c37SJack F Vogel *data |= bit << i; 29974dab5c37SJack F Vogel } 29984dab5c37SJack F Vogel 29994dab5c37SJack F Vogel return E1000_SUCCESS; 30004dab5c37SJack F Vogel } 30014dab5c37SJack F Vogel 30024dab5c37SJack F Vogel /** 30034dab5c37SJack F Vogel * e1000_clock_out_i2c_byte - Clocks out one byte via I2C 30044dab5c37SJack F Vogel * @hw: pointer to hardware structure 30054dab5c37SJack F Vogel * @data: data byte clocked out 30064dab5c37SJack F Vogel * 30074dab5c37SJack F Vogel * Clocks out one byte data via I2C data/clock 30084dab5c37SJack F Vogel **/ 30094dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data) 30104dab5c37SJack F Vogel { 30114dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 30124dab5c37SJack F Vogel s32 i; 30134dab5c37SJack F Vogel u32 i2cctl; 30144dab5c37SJack F Vogel bool bit = 0; 30154dab5c37SJack F Vogel 30164dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_byte"); 30174dab5c37SJack F Vogel 30184dab5c37SJack F Vogel for (i = 7; i >= 0; i--) { 30194dab5c37SJack F Vogel bit = (data >> i) & 0x1; 30204dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, bit); 30214dab5c37SJack F Vogel 30224dab5c37SJack F Vogel if (status != E1000_SUCCESS) 30234dab5c37SJack F Vogel break; 30244dab5c37SJack F Vogel } 30254dab5c37SJack F Vogel 30264dab5c37SJack F Vogel /* Release SDA line (set high) */ 30274dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 30284dab5c37SJack F Vogel 30294dab5c37SJack F Vogel i2cctl |= E1000_I2C_DATA_OE_N; 30304dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl); 30314dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 30324dab5c37SJack F Vogel 30334dab5c37SJack F Vogel return status; 30344dab5c37SJack F Vogel } 30354dab5c37SJack F Vogel 30364dab5c37SJack F Vogel /** 30374dab5c37SJack F Vogel * e1000_get_i2c_ack - Polls for I2C ACK 30384dab5c37SJack F Vogel * @hw: pointer to hardware structure 30394dab5c37SJack F Vogel * 30404dab5c37SJack F Vogel * Clocks in/out one bit via I2C data/clock 30414dab5c37SJack F Vogel **/ 30424dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw) 30434dab5c37SJack F Vogel { 30444dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 30454dab5c37SJack F Vogel u32 i = 0; 30464dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 30474dab5c37SJack F Vogel u32 timeout = 10; 3048*ab5d0362SJack F Vogel bool ack = TRUE; 30494dab5c37SJack F Vogel 30504dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_ack"); 30514dab5c37SJack F Vogel 30524dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 30534dab5c37SJack F Vogel 30544dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 30554dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 30564dab5c37SJack F Vogel 30574dab5c37SJack F Vogel /* Wait until SCL returns high */ 30584dab5c37SJack F Vogel for (i = 0; i < timeout; i++) { 30594dab5c37SJack F Vogel usec_delay(1); 30604dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 30614dab5c37SJack F Vogel if (i2cctl & E1000_I2C_CLK_IN) 30624dab5c37SJack F Vogel break; 30634dab5c37SJack F Vogel } 30644dab5c37SJack F Vogel if (!(i2cctl & E1000_I2C_CLK_IN)) 30654dab5c37SJack F Vogel return E1000_ERR_I2C; 30664dab5c37SJack F Vogel 30674dab5c37SJack F Vogel ack = e1000_get_i2c_data(&i2cctl); 3068*ab5d0362SJack F Vogel if (ack) { 30694dab5c37SJack F Vogel DEBUGOUT("I2C ack was not received.\n"); 30704dab5c37SJack F Vogel status = E1000_ERR_I2C; 30714dab5c37SJack F Vogel } 30724dab5c37SJack F Vogel 30734dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 30744dab5c37SJack F Vogel 30754dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 30764dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 30774dab5c37SJack F Vogel 30784dab5c37SJack F Vogel return status; 30794dab5c37SJack F Vogel } 30804dab5c37SJack F Vogel 30814dab5c37SJack F Vogel /** 30824dab5c37SJack F Vogel * e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock 30834dab5c37SJack F Vogel * @hw: pointer to hardware structure 30844dab5c37SJack F Vogel * @data: read data value 30854dab5c37SJack F Vogel * 30864dab5c37SJack F Vogel * Clocks in one bit via I2C data/clock 30874dab5c37SJack F Vogel **/ 30884dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data) 30894dab5c37SJack F Vogel { 30904dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 30914dab5c37SJack F Vogel 30924dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_bit"); 30934dab5c37SJack F Vogel 30944dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 30954dab5c37SJack F Vogel 30964dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 30974dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 30984dab5c37SJack F Vogel 30994dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 31004dab5c37SJack F Vogel *data = e1000_get_i2c_data(&i2cctl); 31014dab5c37SJack F Vogel 31024dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 31034dab5c37SJack F Vogel 31044dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 31054dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 31064dab5c37SJack F Vogel 31074dab5c37SJack F Vogel return E1000_SUCCESS; 31084dab5c37SJack F Vogel } 31094dab5c37SJack F Vogel 31104dab5c37SJack F Vogel /** 31114dab5c37SJack F Vogel * e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock 31124dab5c37SJack F Vogel * @hw: pointer to hardware structure 31134dab5c37SJack F Vogel * @data: data value to write 31144dab5c37SJack F Vogel * 31154dab5c37SJack F Vogel * Clocks out one bit via I2C data/clock 31164dab5c37SJack F Vogel **/ 31174dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data) 31184dab5c37SJack F Vogel { 31194dab5c37SJack F Vogel s32 status; 31204dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 31214dab5c37SJack F Vogel 31224dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_bit"); 31234dab5c37SJack F Vogel 31244dab5c37SJack F Vogel status = e1000_set_i2c_data(hw, &i2cctl, data); 31254dab5c37SJack F Vogel if (status == E1000_SUCCESS) { 31264dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 31274dab5c37SJack F Vogel 31284dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 31294dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 31304dab5c37SJack F Vogel 31314dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 31324dab5c37SJack F Vogel 31334dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us. 31344dab5c37SJack F Vogel * This also takes care of the data hold time. 31354dab5c37SJack F Vogel */ 31364dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 31374dab5c37SJack F Vogel } else { 31384dab5c37SJack F Vogel status = E1000_ERR_I2C; 31394dab5c37SJack F Vogel DEBUGOUT1("I2C data was not set to %X\n", data); 31404dab5c37SJack F Vogel } 31414dab5c37SJack F Vogel 31424dab5c37SJack F Vogel return status; 31434dab5c37SJack F Vogel } 31444dab5c37SJack F Vogel /** 31454dab5c37SJack F Vogel * e1000_raise_i2c_clk - Raises the I2C SCL clock 31464dab5c37SJack F Vogel * @hw: pointer to hardware structure 31474dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 31484dab5c37SJack F Vogel * 31494dab5c37SJack F Vogel * Raises the I2C clock line '0'->'1' 31504dab5c37SJack F Vogel **/ 31514dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) 31524dab5c37SJack F Vogel { 31534dab5c37SJack F Vogel DEBUGFUNC("e1000_raise_i2c_clk"); 31544dab5c37SJack F Vogel 31554dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OUT; 31564dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N; 31574dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 31584dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 31594dab5c37SJack F Vogel 31604dab5c37SJack F Vogel /* SCL rise time (1000ns) */ 31614dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE); 31624dab5c37SJack F Vogel } 31634dab5c37SJack F Vogel 31644dab5c37SJack F Vogel /** 31654dab5c37SJack F Vogel * e1000_lower_i2c_clk - Lowers the I2C SCL clock 31664dab5c37SJack F Vogel * @hw: pointer to hardware structure 31674dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 31684dab5c37SJack F Vogel * 31694dab5c37SJack F Vogel * Lowers the I2C clock line '1'->'0' 31704dab5c37SJack F Vogel **/ 31714dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) 31724dab5c37SJack F Vogel { 31734dab5c37SJack F Vogel 31744dab5c37SJack F Vogel DEBUGFUNC("e1000_lower_i2c_clk"); 31754dab5c37SJack F Vogel 31764dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OUT; 31774dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N; 31784dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 31794dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 31804dab5c37SJack F Vogel 31814dab5c37SJack F Vogel /* SCL fall time (300ns) */ 31824dab5c37SJack F Vogel usec_delay(E1000_I2C_T_FALL); 31834dab5c37SJack F Vogel } 31844dab5c37SJack F Vogel 31854dab5c37SJack F Vogel /** 31864dab5c37SJack F Vogel * e1000_set_i2c_data - Sets the I2C data bit 31874dab5c37SJack F Vogel * @hw: pointer to hardware structure 31884dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 31894dab5c37SJack F Vogel * @data: I2C data value (0 or 1) to set 31904dab5c37SJack F Vogel * 31914dab5c37SJack F Vogel * Sets the I2C data bit 31924dab5c37SJack F Vogel **/ 31934dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data) 31944dab5c37SJack F Vogel { 31954dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 31964dab5c37SJack F Vogel 31974dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_data"); 31984dab5c37SJack F Vogel 31994dab5c37SJack F Vogel if (data) 32004dab5c37SJack F Vogel *i2cctl |= E1000_I2C_DATA_OUT; 32014dab5c37SJack F Vogel else 32024dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OUT; 32034dab5c37SJack F Vogel 32044dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OE_N; 32054dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OE_N; 32064dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 32074dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 32084dab5c37SJack F Vogel 32094dab5c37SJack F Vogel /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ 32104dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA); 32114dab5c37SJack F Vogel 32124dab5c37SJack F Vogel *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 32134dab5c37SJack F Vogel if (data != e1000_get_i2c_data(i2cctl)) { 32144dab5c37SJack F Vogel status = E1000_ERR_I2C; 32154dab5c37SJack F Vogel DEBUGOUT1("Error - I2C data was not set to %X.\n", data); 32164dab5c37SJack F Vogel } 32174dab5c37SJack F Vogel 32184dab5c37SJack F Vogel return status; 32194dab5c37SJack F Vogel } 32204dab5c37SJack F Vogel 32214dab5c37SJack F Vogel /** 32224dab5c37SJack F Vogel * e1000_get_i2c_data - Reads the I2C SDA data bit 32234dab5c37SJack F Vogel * @hw: pointer to hardware structure 32244dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 32254dab5c37SJack F Vogel * 32264dab5c37SJack F Vogel * Returns the I2C data bit value 32274dab5c37SJack F Vogel **/ 32284dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl) 32294dab5c37SJack F Vogel { 32304dab5c37SJack F Vogel bool data; 32314dab5c37SJack F Vogel 32324dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_data"); 32334dab5c37SJack F Vogel 32344dab5c37SJack F Vogel if (*i2cctl & E1000_I2C_DATA_IN) 32354dab5c37SJack F Vogel data = 1; 32364dab5c37SJack F Vogel else 32374dab5c37SJack F Vogel data = 0; 32384dab5c37SJack F Vogel 32394dab5c37SJack F Vogel return data; 32404dab5c37SJack F Vogel } 32414dab5c37SJack F Vogel 32424dab5c37SJack F Vogel /** 32434dab5c37SJack F Vogel * e1000_i2c_bus_clear - Clears the I2C bus 32444dab5c37SJack F Vogel * @hw: pointer to hardware structure 32454dab5c37SJack F Vogel * 32464dab5c37SJack F Vogel * Clears the I2C bus by sending nine clock pulses. 32474dab5c37SJack F Vogel * Used when data line is stuck low. 32484dab5c37SJack F Vogel **/ 32494dab5c37SJack F Vogel void e1000_i2c_bus_clear(struct e1000_hw *hw) 32504dab5c37SJack F Vogel { 32514dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 32524dab5c37SJack F Vogel u32 i; 32534dab5c37SJack F Vogel 32544dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_bus_clear"); 32554dab5c37SJack F Vogel 32564dab5c37SJack F Vogel e1000_i2c_start(hw); 32574dab5c37SJack F Vogel 32584dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 32594dab5c37SJack F Vogel 32604dab5c37SJack F Vogel for (i = 0; i < 9; i++) { 32614dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 32624dab5c37SJack F Vogel 32634dab5c37SJack F Vogel /* Min high period of clock is 4us */ 32644dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 32654dab5c37SJack F Vogel 32664dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 32674dab5c37SJack F Vogel 32684dab5c37SJack F Vogel /* Min low period of clock is 4.7us*/ 32694dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 32704dab5c37SJack F Vogel } 32714dab5c37SJack F Vogel 32724dab5c37SJack F Vogel e1000_i2c_start(hw); 32734dab5c37SJack F Vogel 32744dab5c37SJack F Vogel /* Put the i2c bus back to default state */ 32754dab5c37SJack F Vogel e1000_i2c_stop(hw); 32764dab5c37SJack F Vogel } 32774dab5c37SJack F Vogel 3278