18cfa0ad2SJack F Vogel /****************************************************************************** 28cfa0ad2SJack F Vogel 37c669ab6SSean Bruno Copyright (c) 2001-2015, 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 41ab5d0362SJack F Vogel * 82580 Gigabit Network Connection 42ab5d0362SJack F Vogel * I350 Gigabit Network Connection 438cfa0ad2SJack F Vogel */ 448cfa0ad2SJack F Vogel 458cfa0ad2SJack F Vogel #include "e1000_api.h" 46ab5d0362SJack 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); 557609433eSJack F Vogel static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw); 568cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw); 578cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, 588cfa0ad2SJack F Vogel u16 *duplex); 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 \ 1228cc64f1eSJack F Vogel (sizeof(e1000_82580_rxpbs_table) / \ 1238cc64f1eSJack F Vogel sizeof(e1000_82580_rxpbs_table[0])) 1244edd8523SJack F Vogel 1257d9119bdSJack F Vogel 1267d9119bdSJack F Vogel /** 1277d9119bdSJack F Vogel * e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO 1287d9119bdSJack F Vogel * @hw: pointer to the HW structure 1297d9119bdSJack F Vogel * 1307d9119bdSJack F Vogel * Called to determine if the I2C pins are being used for I2C or as an 1317d9119bdSJack F Vogel * external MDIO interface since the two options are mutually exclusive. 1327d9119bdSJack F Vogel **/ 1337d9119bdSJack F Vogel static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw) 1347d9119bdSJack F Vogel { 1357d9119bdSJack F Vogel u32 reg = 0; 1367d9119bdSJack F Vogel bool ext_mdio = FALSE; 1377d9119bdSJack F Vogel 1387d9119bdSJack F Vogel DEBUGFUNC("e1000_sgmii_uses_mdio_82575"); 1397d9119bdSJack F Vogel 1407d9119bdSJack F Vogel switch (hw->mac.type) { 1417d9119bdSJack F Vogel case e1000_82575: 1427d9119bdSJack F Vogel case e1000_82576: 1437d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDIC); 1447d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDIC_DEST); 1457d9119bdSJack F Vogel break; 1467d9119bdSJack F Vogel case e1000_82580: 147f0ecc46dSJack F Vogel case e1000_i350: 1487609433eSJack F Vogel case e1000_i354: 1496ab6bfe3SJack F Vogel case e1000_i210: 1506ab6bfe3SJack F Vogel case e1000_i211: 1517d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDICNFG); 1527d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO); 1537d9119bdSJack F Vogel break; 1547d9119bdSJack F Vogel default: 1557d9119bdSJack F Vogel break; 1567d9119bdSJack F Vogel } 1577d9119bdSJack F Vogel return ext_mdio; 1587d9119bdSJack F Vogel } 1597d9119bdSJack F Vogel 1608cfa0ad2SJack F Vogel /** 1618cfa0ad2SJack F Vogel * e1000_init_phy_params_82575 - Init PHY func ptrs. 1628cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 1638cfa0ad2SJack F Vogel **/ 1648cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw) 1658cfa0ad2SJack F Vogel { 1668cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 1678cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 1687d9119bdSJack F Vogel u32 ctrl_ext; 1698cfa0ad2SJack F Vogel 1708cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_82575"); 1718cfa0ad2SJack F Vogel 172ab5d0362SJack F Vogel phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic; 173ab5d0362SJack F Vogel phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic; 174ab5d0362SJack F Vogel 1758cfa0ad2SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) { 1768cfa0ad2SJack F Vogel phy->type = e1000_phy_none; 1778cfa0ad2SJack F Vogel goto out; 1784edd8523SJack F Vogel } 1794edd8523SJack F Vogel 1808cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper; 1818cfa0ad2SJack F Vogel phy->ops.power_down = e1000_power_down_phy_copper_82575; 1828cfa0ad2SJack F Vogel 1838cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT; 1848cfa0ad2SJack F Vogel phy->reset_delay_us = 100; 1858cfa0ad2SJack F Vogel 1868cfa0ad2SJack F Vogel phy->ops.acquire = e1000_acquire_phy_82575; 1878cfa0ad2SJack F Vogel phy->ops.check_reset_block = e1000_check_reset_block_generic; 1888cfa0ad2SJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic; 1898cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_82575; 1908cfa0ad2SJack F Vogel phy->ops.release = e1000_release_phy_82575; 1918cfa0ad2SJack F Vogel 1927d9119bdSJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 1937d9119bdSJack F Vogel 1948cfa0ad2SJack F Vogel if (e1000_sgmii_active_82575(hw)) { 1958cfa0ad2SJack F Vogel phy->ops.reset = e1000_phy_hw_reset_sgmii_82575; 1967d9119bdSJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA; 1977d9119bdSJack F Vogel } else { 1987d9119bdSJack F Vogel phy->ops.reset = e1000_phy_hw_reset_generic; 1997d9119bdSJack F Vogel ctrl_ext &= ~E1000_CTRL_I2C_ENA; 2007d9119bdSJack F Vogel } 2017d9119bdSJack F Vogel 2027d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 2037d9119bdSJack F Vogel e1000_reset_mdicnfg_82580(hw); 2047d9119bdSJack F Vogel 2057d9119bdSJack F Vogel if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) { 2068cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575; 2078cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575; 208ab5d0362SJack F Vogel } else { 209ab5d0362SJack F Vogel switch (hw->mac.type) { 210ab5d0362SJack F Vogel case e1000_82580: 211ab5d0362SJack F Vogel case e1000_i350: 2127609433eSJack F Vogel case e1000_i354: 2134edd8523SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_82580; 2144edd8523SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_82580; 215ab5d0362SJack F Vogel break; 216ab5d0362SJack F Vogel case e1000_i210: 217ab5d0362SJack F Vogel case e1000_i211: 218ab5d0362SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_gs40g; 219ab5d0362SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_gs40g; 220ab5d0362SJack F Vogel break; 221ab5d0362SJack F Vogel default: 2228cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_igp; 2238cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_igp; 2248cfa0ad2SJack F Vogel } 225ab5d0362SJack F Vogel } 2268cfa0ad2SJack F Vogel 2278cfa0ad2SJack F Vogel /* Set phy->phy_addr and phy->id. */ 2288cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id_82575(hw); 2298cfa0ad2SJack F Vogel 2308cfa0ad2SJack F Vogel /* Verify phy id and set remaining function pointers */ 2318cfa0ad2SJack F Vogel switch (phy->id) { 2327609433eSJack F Vogel case M88E1543_E_PHY_ID: 2337609433eSJack F Vogel case M88E1512_E_PHY_ID: 234f0ecc46dSJack F Vogel case I347AT4_E_PHY_ID: 235f0ecc46dSJack F Vogel case M88E1112_E_PHY_ID: 2361fd3c44fSJack F Vogel case M88E1340M_E_PHY_ID: 2378cfa0ad2SJack F Vogel case M88E1111_I_PHY_ID: 2388cfa0ad2SJack F Vogel phy->type = e1000_phy_m88; 2398cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 2408cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 241f0ecc46dSJack F Vogel if (phy->id == I347AT4_E_PHY_ID || 2421fd3c44fSJack F Vogel phy->id == M88E1112_E_PHY_ID || 2431fd3c44fSJack F Vogel phy->id == M88E1340M_E_PHY_ID) 2444dab5c37SJack F Vogel phy->ops.get_cable_length = 2454dab5c37SJack F Vogel e1000_get_cable_length_m88_gen2; 2467609433eSJack F Vogel else if (phy->id == M88E1543_E_PHY_ID || 2477609433eSJack F Vogel phy->id == M88E1512_E_PHY_ID) 2487609433eSJack F Vogel phy->ops.get_cable_length = 2497609433eSJack F Vogel e1000_get_cable_length_m88_gen2; 250f0ecc46dSJack F Vogel else 2518cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88; 2528cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 2537609433eSJack F Vogel /* Check if this PHY is confgured for media swap. */ 2547609433eSJack F Vogel if (phy->id == M88E1112_E_PHY_ID) { 2557609433eSJack F Vogel u16 data; 2567609433eSJack F Vogel 2577609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, 2587609433eSJack F Vogel E1000_M88E1112_PAGE_ADDR, 2597609433eSJack F Vogel 2); 2607609433eSJack F Vogel if (ret_val) 2617609433eSJack F Vogel goto out; 2627609433eSJack F Vogel 2637609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, 2647609433eSJack F Vogel E1000_M88E1112_MAC_CTRL_1, 2657609433eSJack F Vogel &data); 2667609433eSJack F Vogel if (ret_val) 2677609433eSJack F Vogel goto out; 2687609433eSJack F Vogel 2697609433eSJack F Vogel data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >> 2707609433eSJack F Vogel E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT; 2717609433eSJack F Vogel if (data == E1000_M88E1112_AUTO_COPPER_SGMII || 2727609433eSJack F Vogel data == E1000_M88E1112_AUTO_COPPER_BASEX) 2737609433eSJack F Vogel hw->mac.ops.check_for_link = 2747609433eSJack F Vogel e1000_check_for_link_media_swap; 2757609433eSJack F Vogel } 2768cc64f1eSJack F Vogel if (phy->id == M88E1512_E_PHY_ID) { 2778cc64f1eSJack F Vogel ret_val = e1000_initialize_M88E1512_phy(hw); 2788cc64f1eSJack F Vogel if (ret_val) 2798cc64f1eSJack F Vogel goto out; 2808cc64f1eSJack F Vogel } 281c80429ceSEric Joyner if (phy->id == M88E1543_E_PHY_ID) { 282c80429ceSEric Joyner ret_val = e1000_initialize_M88E1543_phy(hw); 283c80429ceSEric Joyner if (ret_val) 284c80429ceSEric Joyner goto out; 285c80429ceSEric Joyner } 2868cfa0ad2SJack F Vogel break; 2878cfa0ad2SJack F Vogel case IGP03E1000_E_PHY_ID: 2888cfa0ad2SJack F Vogel case IGP04E1000_E_PHY_ID: 2898cfa0ad2SJack F Vogel phy->type = e1000_phy_igp_3; 2908cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_igp; 2918cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_igp; 2928cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_igp_2; 2938cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp; 2948cfa0ad2SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575; 2958cfa0ad2SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic; 2968cfa0ad2SJack F Vogel break; 2974edd8523SJack F Vogel case I82580_I_PHY_ID: 298f0ecc46dSJack F Vogel case I350_I_PHY_ID: 2994edd8523SJack F Vogel phy->type = e1000_phy_82580; 3004edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_82577; 3014dab5c37SJack F Vogel phy->ops.force_speed_duplex = 3024dab5c37SJack F Vogel e1000_phy_force_speed_duplex_82577; 3034edd8523SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_82577; 3044edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_82577; 305f0ecc46dSJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; 306f0ecc46dSJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; 3074edd8523SJack F Vogel break; 308ab5d0362SJack F Vogel case I210_I_PHY_ID: 309ab5d0362SJack F Vogel phy->type = e1000_phy_i210; 310ab5d0362SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88; 311ab5d0362SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88; 312ab5d0362SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2; 313ab5d0362SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580; 314ab5d0362SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580; 315ab5d0362SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88; 316ab5d0362SJack F Vogel break; 3178cfa0ad2SJack F Vogel default: 3188cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 3198cfa0ad2SJack F Vogel goto out; 3208cfa0ad2SJack F Vogel } 3218cfa0ad2SJack F Vogel 3228cfa0ad2SJack F Vogel out: 3238cfa0ad2SJack F Vogel return ret_val; 3248cfa0ad2SJack F Vogel } 3258cfa0ad2SJack F Vogel 3268cfa0ad2SJack F Vogel /** 3278cfa0ad2SJack F Vogel * e1000_init_nvm_params_82575 - Init NVM func ptrs. 3288cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 3298cfa0ad2SJack F Vogel **/ 3301fd3c44fSJack F Vogel s32 e1000_init_nvm_params_82575(struct e1000_hw *hw) 3318cfa0ad2SJack F Vogel { 3328cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm; 3338cfa0ad2SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 3348cfa0ad2SJack F Vogel u16 size; 3358cfa0ad2SJack F Vogel 3368cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_82575"); 3378cfa0ad2SJack F Vogel 338f0ecc46dSJack F Vogel size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >> 339f0ecc46dSJack F Vogel E1000_EECD_SIZE_EX_SHIFT); 340f0ecc46dSJack F Vogel /* 341f0ecc46dSJack F Vogel * Added to a constant, "size" becomes the left-shift value 342f0ecc46dSJack F Vogel * for setting word_size. 343f0ecc46dSJack F Vogel */ 344f0ecc46dSJack F Vogel size += NVM_WORD_SIZE_BASE_SHIFT; 345f0ecc46dSJack F Vogel 3464dab5c37SJack F Vogel /* Just in case size is out of range, cap it to the largest 3474dab5c37SJack F Vogel * EEPROM size supported 3484dab5c37SJack F Vogel */ 3494dab5c37SJack F Vogel if (size > 15) 3504dab5c37SJack F Vogel size = 15; 3514dab5c37SJack F Vogel 352f0ecc46dSJack F Vogel nvm->word_size = 1 << size; 353ab5d0362SJack F Vogel if (hw->mac.type < e1000_i210) { 3548cfa0ad2SJack F Vogel nvm->opcode_bits = 8; 3558cfa0ad2SJack F Vogel nvm->delay_usec = 1; 356ab5d0362SJack F Vogel 3578cfa0ad2SJack F Vogel switch (nvm->override) { 3588cfa0ad2SJack F Vogel case e1000_nvm_override_spi_large: 3598cfa0ad2SJack F Vogel nvm->page_size = 32; 3608cfa0ad2SJack F Vogel nvm->address_bits = 16; 3618cfa0ad2SJack F Vogel break; 3628cfa0ad2SJack F Vogel case e1000_nvm_override_spi_small: 3638cfa0ad2SJack F Vogel nvm->page_size = 8; 3648cfa0ad2SJack F Vogel nvm->address_bits = 8; 3658cfa0ad2SJack F Vogel break; 3668cfa0ad2SJack F Vogel default: 3678cfa0ad2SJack F Vogel nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8; 368ab5d0362SJack F Vogel nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ? 369ab5d0362SJack F Vogel 16 : 8; 3708cfa0ad2SJack F Vogel break; 3718cfa0ad2SJack F Vogel } 3721fd3c44fSJack F Vogel if (nvm->word_size == (1 << 15)) 373f0ecc46dSJack F Vogel nvm->page_size = 128; 3748cfa0ad2SJack F Vogel 375ab5d0362SJack F Vogel nvm->type = e1000_nvm_eeprom_spi; 376ab5d0362SJack F Vogel } else { 377ab5d0362SJack F Vogel nvm->type = e1000_nvm_flash_hw; 378ab5d0362SJack F Vogel } 3796ab6bfe3SJack F Vogel 3808cfa0ad2SJack F Vogel /* Function Pointers */ 3818cfa0ad2SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_82575; 3828cfa0ad2SJack F Vogel nvm->ops.release = e1000_release_nvm_82575; 3831fd3c44fSJack F Vogel if (nvm->word_size < (1 << 15)) 3841fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_eerd; 3851fd3c44fSJack F Vogel else 3861fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_spi; 3871fd3c44fSJack F Vogel 3881fd3c44fSJack F Vogel nvm->ops.write = e1000_write_nvm_spi; 3891fd3c44fSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_generic; 3901fd3c44fSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_generic; 3918cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_82575; 3921fd3c44fSJack F Vogel 393ab5d0362SJack F Vogel /* override generic family function pointers for specific descendants */ 394f0ecc46dSJack F Vogel switch (hw->mac.type) { 395f0ecc46dSJack F Vogel case e1000_82580: 396f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_82580; 397f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_82580; 398f0ecc46dSJack F Vogel break; 399f0ecc46dSJack F Vogel case e1000_i350: 4007609433eSJack F Vogel case e1000_i354: 401f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_i350; 402f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_i350; 403f0ecc46dSJack F Vogel break; 404f0ecc46dSJack F Vogel default: 4051fd3c44fSJack F Vogel break; 406f0ecc46dSJack F Vogel } 4078cfa0ad2SJack F Vogel 4088cfa0ad2SJack F Vogel return E1000_SUCCESS; 4098cfa0ad2SJack F Vogel } 4108cfa0ad2SJack F Vogel 4118cfa0ad2SJack F Vogel /** 4128cfa0ad2SJack F Vogel * e1000_init_mac_params_82575 - Init MAC func ptrs. 4138cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 4148cfa0ad2SJack F Vogel **/ 4158cfa0ad2SJack F Vogel static s32 e1000_init_mac_params_82575(struct e1000_hw *hw) 4168cfa0ad2SJack F Vogel { 4178cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 418daf9197cSJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 4198cfa0ad2SJack F Vogel 4208cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_mac_params_82575"); 4218cfa0ad2SJack F Vogel 4224dab5c37SJack F Vogel /* Derives media type */ 4234dab5c37SJack F Vogel e1000_get_media_type_82575(hw); 4248cfa0ad2SJack F Vogel /* Set mta register count */ 4258cfa0ad2SJack F Vogel mac->mta_reg_count = 128; 4264edd8523SJack F Vogel /* Set uta register count */ 4274edd8523SJack F Vogel mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128; 4288cfa0ad2SJack F Vogel /* Set rar entry count */ 4298cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82575; 4308cfa0ad2SJack F Vogel if (mac->type == e1000_82576) 4318cfa0ad2SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82576; 432a69ed8dfSJack F Vogel if (mac->type == e1000_82580) 4334edd8523SJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_82580; 4347609433eSJack F Vogel if (mac->type == e1000_i350 || mac->type == e1000_i354) 435f0ecc46dSJack F Vogel mac->rar_entry_count = E1000_RAR_ENTRIES_I350; 4366ab6bfe3SJack F Vogel 4376ab6bfe3SJack F Vogel /* Enable EEE default settings for EEE supported devices */ 4386ab6bfe3SJack F Vogel if (mac->type >= e1000_i350) 439f0ecc46dSJack F Vogel dev_spec->eee_disable = FALSE; 4406ab6bfe3SJack F Vogel 4416ab6bfe3SJack F Vogel /* Allow a single clear of the SW semaphore on I210 and newer */ 4426ab6bfe3SJack F Vogel if (mac->type >= e1000_i210) 4436ab6bfe3SJack F Vogel dev_spec->clear_semaphore_once = TRUE; 444f0ecc46dSJack F Vogel 4458cfa0ad2SJack F Vogel /* Set if part includes ASF firmware */ 4468cfa0ad2SJack F Vogel mac->asf_firmware_present = TRUE; 4478ec87fc5SJack F Vogel /* FWSM register */ 4488ec87fc5SJack F Vogel mac->has_fwsm = TRUE; 4498ec87fc5SJack F Vogel /* ARC supported; valid only if manageability features are enabled. */ 4508cfa0ad2SJack F Vogel mac->arc_subsystem_valid = 451ab5d0362SJack F Vogel !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK); 4528cfa0ad2SJack F Vogel 4538cfa0ad2SJack F Vogel /* Function pointers */ 4548cfa0ad2SJack F Vogel 4558cfa0ad2SJack F Vogel /* bus type/speed/width */ 4568cfa0ad2SJack F Vogel mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic; 4578cfa0ad2SJack F Vogel /* reset */ 458a69ed8dfSJack F Vogel if (mac->type >= e1000_82580) 4594edd8523SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82580; 4604edd8523SJack F Vogel else 4618cfa0ad2SJack F Vogel mac->ops.reset_hw = e1000_reset_hw_82575; 4628cfa0ad2SJack F Vogel /* hw initialization */ 4638cc64f1eSJack F Vogel if ((mac->type == e1000_i210) || (mac->type == e1000_i211)) 4648cc64f1eSJack F Vogel mac->ops.init_hw = e1000_init_hw_i210; 4658cc64f1eSJack F Vogel else 4668cfa0ad2SJack F Vogel mac->ops.init_hw = e1000_init_hw_82575; 4678cfa0ad2SJack F Vogel /* link setup */ 4688cfa0ad2SJack F Vogel mac->ops.setup_link = e1000_setup_link_generic; 4698cfa0ad2SJack F Vogel /* physical interface link setup */ 4708cfa0ad2SJack F Vogel mac->ops.setup_physical_interface = 4718cfa0ad2SJack F Vogel (hw->phy.media_type == e1000_media_type_copper) 4724dab5c37SJack F Vogel ? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575; 4738cfa0ad2SJack F Vogel /* physical interface shutdown */ 4744edd8523SJack F Vogel mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575; 475a69ed8dfSJack F Vogel /* physical interface power up */ 476a69ed8dfSJack F Vogel mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575; 4778cfa0ad2SJack F Vogel /* check for link */ 4788cfa0ad2SJack F Vogel mac->ops.check_for_link = e1000_check_for_link_82575; 4798cfa0ad2SJack F Vogel /* read mac address */ 4808cfa0ad2SJack F Vogel mac->ops.read_mac_addr = e1000_read_mac_addr_82575; 481a69ed8dfSJack F Vogel /* configure collision distance */ 482a69ed8dfSJack F Vogel mac->ops.config_collision_dist = e1000_config_collision_dist_82575; 4838cfa0ad2SJack F Vogel /* multicast address update */ 484d035aa2dSJack F Vogel mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic; 4857609433eSJack F Vogel if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) { 4864dab5c37SJack F Vogel /* writing VFTA */ 4874dab5c37SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_i350; 4884dab5c37SJack F Vogel /* clearing VFTA */ 4894dab5c37SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_i350; 4904dab5c37SJack F Vogel } else { 4918cfa0ad2SJack F Vogel /* writing VFTA */ 4928cfa0ad2SJack F Vogel mac->ops.write_vfta = e1000_write_vfta_generic; 4938cfa0ad2SJack F Vogel /* clearing VFTA */ 4948cfa0ad2SJack F Vogel mac->ops.clear_vfta = e1000_clear_vfta_generic; 4954dab5c37SJack F Vogel } 4966ab6bfe3SJack F Vogel if (hw->mac.type >= e1000_82580) 4976ab6bfe3SJack F Vogel mac->ops.validate_mdi_setting = 4986ab6bfe3SJack F Vogel e1000_validate_mdi_setting_crossover_generic; 499d035aa2dSJack F Vogel /* ID LED init */ 500d035aa2dSJack F Vogel mac->ops.id_led_init = e1000_id_led_init_generic; 5018cfa0ad2SJack F Vogel /* blink LED */ 5028cfa0ad2SJack F Vogel mac->ops.blink_led = e1000_blink_led_generic; 5038cfa0ad2SJack F Vogel /* setup LED */ 5048cfa0ad2SJack F Vogel mac->ops.setup_led = e1000_setup_led_generic; 5058cfa0ad2SJack F Vogel /* cleanup LED */ 5068cfa0ad2SJack F Vogel mac->ops.cleanup_led = e1000_cleanup_led_generic; 5078cfa0ad2SJack F Vogel /* turn on/off LED */ 5088cfa0ad2SJack F Vogel mac->ops.led_on = e1000_led_on_generic; 5098cfa0ad2SJack F Vogel mac->ops.led_off = e1000_led_off_generic; 5108cfa0ad2SJack F Vogel /* clear hardware counters */ 5118cfa0ad2SJack F Vogel mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575; 5128cfa0ad2SJack F Vogel /* link info */ 5138cfa0ad2SJack F Vogel mac->ops.get_link_up_info = e1000_get_link_up_info_82575; 514ab5d0362SJack F Vogel /* acquire SW_FW sync */ 515ab5d0362SJack F Vogel mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_82575; 516ab5d0362SJack F Vogel mac->ops.release_swfw_sync = e1000_release_swfw_sync_82575; 517ab5d0362SJack F Vogel if (mac->type >= e1000_i210) { 518ab5d0362SJack F Vogel mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync_i210; 519ab5d0362SJack F Vogel mac->ops.release_swfw_sync = e1000_release_swfw_sync_i210; 520ab5d0362SJack F Vogel } 5218cfa0ad2SJack F Vogel 5224edd8523SJack F Vogel /* set lan id for port to determine which phy lock to use */ 5234edd8523SJack F Vogel hw->mac.ops.set_lan_id(hw); 5244edd8523SJack F Vogel 525daf9197cSJack F Vogel return E1000_SUCCESS; 5268cfa0ad2SJack F Vogel } 5278cfa0ad2SJack F Vogel 5288cfa0ad2SJack F Vogel /** 5298cfa0ad2SJack F Vogel * e1000_init_function_pointers_82575 - Init func ptrs. 5308cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5318cfa0ad2SJack F Vogel * 532daf9197cSJack F Vogel * Called to initialize all function pointers and parameters. 5338cfa0ad2SJack F Vogel **/ 5348cfa0ad2SJack F Vogel void e1000_init_function_pointers_82575(struct e1000_hw *hw) 5358cfa0ad2SJack F Vogel { 5368cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_82575"); 5378cfa0ad2SJack F Vogel 5388cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_82575; 5398cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_82575; 5408cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_82575; 5417d9119bdSJack F Vogel hw->mbx.ops.init_params = e1000_init_mbx_params_pf; 5428cfa0ad2SJack F Vogel } 5438cfa0ad2SJack F Vogel 5448cfa0ad2SJack F Vogel /** 5458cfa0ad2SJack F Vogel * e1000_acquire_phy_82575 - Acquire rights to access PHY 5468cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5478cfa0ad2SJack F Vogel * 548daf9197cSJack F Vogel * Acquire access rights to the correct PHY. 5498cfa0ad2SJack F Vogel **/ 5508cfa0ad2SJack F Vogel static s32 e1000_acquire_phy_82575(struct e1000_hw *hw) 5518cfa0ad2SJack F Vogel { 5529d81738fSJack F Vogel u16 mask = E1000_SWFW_PHY0_SM; 5538cfa0ad2SJack F Vogel 5548cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_phy_82575"); 5558cfa0ad2SJack F Vogel 5569d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 5579d81738fSJack F Vogel mask = E1000_SWFW_PHY1_SM; 5584edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 5594edd8523SJack F Vogel mask = E1000_SWFW_PHY2_SM; 5604edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 5614edd8523SJack F Vogel mask = E1000_SWFW_PHY3_SM; 5628cfa0ad2SJack F Vogel 563ab5d0362SJack F Vogel return hw->mac.ops.acquire_swfw_sync(hw, mask); 5648cfa0ad2SJack F Vogel } 5658cfa0ad2SJack F Vogel 5668cfa0ad2SJack F Vogel /** 5678cfa0ad2SJack F Vogel * e1000_release_phy_82575 - Release rights to access PHY 5688cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5698cfa0ad2SJack F Vogel * 570daf9197cSJack F Vogel * A wrapper to release access rights to the correct PHY. 5718cfa0ad2SJack F Vogel **/ 5728cfa0ad2SJack F Vogel static void e1000_release_phy_82575(struct e1000_hw *hw) 5738cfa0ad2SJack F Vogel { 5749d81738fSJack F Vogel u16 mask = E1000_SWFW_PHY0_SM; 5758cfa0ad2SJack F Vogel 5768cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_phy_82575"); 5778cfa0ad2SJack F Vogel 5789d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 5799d81738fSJack F Vogel mask = E1000_SWFW_PHY1_SM; 5804edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 5814edd8523SJack F Vogel mask = E1000_SWFW_PHY2_SM; 5824edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 5834edd8523SJack F Vogel mask = E1000_SWFW_PHY3_SM; 5849d81738fSJack F Vogel 585ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, mask); 5868cfa0ad2SJack F Vogel } 5878cfa0ad2SJack F Vogel 5888cfa0ad2SJack F Vogel /** 5898cfa0ad2SJack F Vogel * e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii 5908cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 5918cfa0ad2SJack F Vogel * @offset: register offset to be read 5928cfa0ad2SJack F Vogel * @data: pointer to the read data 5938cfa0ad2SJack F Vogel * 5948cfa0ad2SJack F Vogel * Reads the PHY register at offset using the serial gigabit media independent 5958cfa0ad2SJack F Vogel * interface and stores the retrieved information in data. 5968cfa0ad2SJack F Vogel **/ 5978cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 5988cfa0ad2SJack F Vogel u16 *data) 5998cfa0ad2SJack F Vogel { 6004edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM; 6018cfa0ad2SJack F Vogel 6028cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_sgmii_82575"); 6038cfa0ad2SJack F Vogel 6048cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 6058cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %u is out of range\n", offset); 6064edd8523SJack F Vogel goto out; 6078cfa0ad2SJack F Vogel } 6088cfa0ad2SJack F Vogel 6094edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 6104edd8523SJack F Vogel if (ret_val) 6114edd8523SJack F Vogel goto out; 6128cfa0ad2SJack F Vogel 6134edd8523SJack F Vogel ret_val = e1000_read_phy_reg_i2c(hw, offset, data); 6148cfa0ad2SJack F Vogel 6154edd8523SJack F Vogel hw->phy.ops.release(hw); 6168cfa0ad2SJack F Vogel 6174edd8523SJack F Vogel out: 6184edd8523SJack F Vogel return ret_val; 6198cfa0ad2SJack F Vogel } 6208cfa0ad2SJack F Vogel 6218cfa0ad2SJack F Vogel /** 6228cfa0ad2SJack F Vogel * e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii 6238cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6248cfa0ad2SJack F Vogel * @offset: register offset to write to 6258cfa0ad2SJack F Vogel * @data: data to write at register offset 6268cfa0ad2SJack F Vogel * 6278cfa0ad2SJack F Vogel * Writes the data to PHY register at the offset using the serial gigabit 6288cfa0ad2SJack F Vogel * media independent interface. 6298cfa0ad2SJack F Vogel **/ 6308cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset, 6318cfa0ad2SJack F Vogel u16 data) 6328cfa0ad2SJack F Vogel { 6334edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM; 6348cfa0ad2SJack F Vogel 6358cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_sgmii_82575"); 6368cfa0ad2SJack F Vogel 6378cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) { 6388cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %d is out of range\n", offset); 6394edd8523SJack F Vogel goto out; 6408cfa0ad2SJack F Vogel } 6418cfa0ad2SJack F Vogel 6424edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 6434edd8523SJack F Vogel if (ret_val) 6444edd8523SJack F Vogel goto out; 6458cfa0ad2SJack F Vogel 6464edd8523SJack F Vogel ret_val = e1000_write_phy_reg_i2c(hw, offset, data); 6478cfa0ad2SJack F Vogel 6484edd8523SJack F Vogel hw->phy.ops.release(hw); 6498cfa0ad2SJack F Vogel 6504edd8523SJack F Vogel out: 6514edd8523SJack F Vogel return ret_val; 6528cfa0ad2SJack F Vogel } 6538cfa0ad2SJack F Vogel 6548cfa0ad2SJack F Vogel /** 6558cfa0ad2SJack F Vogel * e1000_get_phy_id_82575 - Retrieve PHY addr and id 6568cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 6578cfa0ad2SJack F Vogel * 6588cfa0ad2SJack F Vogel * Retrieves the PHY address and ID for both PHY's which do and do not use 6598cfa0ad2SJack F Vogel * sgmi interface. 6608cfa0ad2SJack F Vogel **/ 6618cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw) 6628cfa0ad2SJack F Vogel { 6638cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 6648cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 6658cfa0ad2SJack F Vogel u16 phy_id; 6664edd8523SJack F Vogel u32 ctrl_ext; 6677d9119bdSJack F Vogel u32 mdic; 6688cfa0ad2SJack F Vogel 6698cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_phy_id_82575"); 6708cfa0ad2SJack F Vogel 6717609433eSJack F Vogel /* some i354 devices need an extra read for phy id */ 6727609433eSJack F Vogel if (hw->mac.type == e1000_i354) 6737609433eSJack F Vogel e1000_get_phy_id(hw); 6747609433eSJack F Vogel 6758cfa0ad2SJack F Vogel /* 6768cfa0ad2SJack F Vogel * For SGMII PHYs, we try the list of possible addresses until 6778cfa0ad2SJack F Vogel * we find one that works. For non-SGMII PHYs 6788cfa0ad2SJack F Vogel * (e.g. integrated copper PHYs), an address of 1 should 6798cfa0ad2SJack F Vogel * work. The result of this function should mean phy->phy_addr 6808cfa0ad2SJack F Vogel * and phy->id are set correctly. 6818cfa0ad2SJack F Vogel */ 6824edd8523SJack F Vogel if (!e1000_sgmii_active_82575(hw)) { 6838cfa0ad2SJack F Vogel phy->addr = 1; 6848cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw); 6858cfa0ad2SJack F Vogel goto out; 6868cfa0ad2SJack F Vogel } 6878cfa0ad2SJack F Vogel 6887d9119bdSJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) { 6897d9119bdSJack F Vogel switch (hw->mac.type) { 6907d9119bdSJack F Vogel case e1000_82575: 6917d9119bdSJack F Vogel case e1000_82576: 6927d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDIC); 6937d9119bdSJack F Vogel mdic &= E1000_MDIC_PHY_MASK; 6947d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDIC_PHY_SHIFT; 6957d9119bdSJack F Vogel break; 6967d9119bdSJack F Vogel case e1000_82580: 697f0ecc46dSJack F Vogel case e1000_i350: 6987609433eSJack F Vogel case e1000_i354: 6996ab6bfe3SJack F Vogel case e1000_i210: 7006ab6bfe3SJack F Vogel case e1000_i211: 7017d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDICNFG); 7027d9119bdSJack F Vogel mdic &= E1000_MDICNFG_PHY_MASK; 7037d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT; 7047d9119bdSJack F Vogel break; 7057d9119bdSJack F Vogel default: 7067d9119bdSJack F Vogel ret_val = -E1000_ERR_PHY; 7077d9119bdSJack F Vogel goto out; 7087d9119bdSJack F Vogel break; 7097d9119bdSJack F Vogel } 7107d9119bdSJack F Vogel ret_val = e1000_get_phy_id(hw); 7117d9119bdSJack F Vogel goto out; 7127d9119bdSJack F Vogel } 7137d9119bdSJack F Vogel 7144edd8523SJack F Vogel /* Power on sgmii phy if it is disabled */ 7154edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 7164edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, 7174edd8523SJack F Vogel ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA); 7184edd8523SJack F Vogel E1000_WRITE_FLUSH(hw); 7194edd8523SJack F Vogel msec_delay(300); 7204edd8523SJack F Vogel 7218cfa0ad2SJack F Vogel /* 7228cfa0ad2SJack F Vogel * The address field in the I2CCMD register is 3 bits and 0 is invalid. 7238cfa0ad2SJack F Vogel * Therefore, we need to test 1-7 7248cfa0ad2SJack F Vogel */ 7258cfa0ad2SJack F Vogel for (phy->addr = 1; phy->addr < 8; phy->addr++) { 7268cfa0ad2SJack F Vogel ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id); 7278cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) { 7288cfa0ad2SJack F Vogel DEBUGOUT2("Vendor ID 0x%08X read at address %u\n", 7294dab5c37SJack F Vogel phy_id, phy->addr); 7308cfa0ad2SJack F Vogel /* 7318cfa0ad2SJack F Vogel * At the time of this writing, The M88 part is 7328cfa0ad2SJack F Vogel * the only supported SGMII PHY product. 7338cfa0ad2SJack F Vogel */ 7348cfa0ad2SJack F Vogel if (phy_id == M88_VENDOR) 7358cfa0ad2SJack F Vogel break; 7368cfa0ad2SJack F Vogel } else { 7378cfa0ad2SJack F Vogel DEBUGOUT1("PHY address %u was unreadable\n", 7388cfa0ad2SJack F Vogel phy->addr); 7398cfa0ad2SJack F Vogel } 7408cfa0ad2SJack F Vogel } 7418cfa0ad2SJack F Vogel 7428cfa0ad2SJack F Vogel /* A valid PHY type couldn't be found. */ 7438cfa0ad2SJack F Vogel if (phy->addr == 8) { 7448cfa0ad2SJack F Vogel phy->addr = 0; 7458cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 7464edd8523SJack F Vogel } else { 7474edd8523SJack F Vogel ret_val = e1000_get_phy_id(hw); 7488cfa0ad2SJack F Vogel } 7498cfa0ad2SJack F Vogel 7504edd8523SJack F Vogel /* restore previous sfp cage power state */ 7514edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 7528cfa0ad2SJack F Vogel 7538cfa0ad2SJack F Vogel out: 7548cfa0ad2SJack F Vogel return ret_val; 7558cfa0ad2SJack F Vogel } 7568cfa0ad2SJack F Vogel 7578cfa0ad2SJack F Vogel /** 7588cfa0ad2SJack F Vogel * e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset 7598cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 7608cfa0ad2SJack F Vogel * 7618cfa0ad2SJack F Vogel * Resets the PHY using the serial gigabit media independent interface. 7628cfa0ad2SJack F Vogel **/ 7638cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw) 7648cfa0ad2SJack F Vogel { 7658cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 7668cc64f1eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 7678cfa0ad2SJack F Vogel 7688cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575"); 7698cfa0ad2SJack F Vogel 7708cfa0ad2SJack F Vogel /* 7718cfa0ad2SJack F Vogel * This isn't a TRUE "hard" reset, but is the only reset 7728cfa0ad2SJack F Vogel * available to us at this time. 7738cfa0ad2SJack F Vogel */ 7748cfa0ad2SJack F Vogel 7758cfa0ad2SJack F Vogel DEBUGOUT("Soft resetting SGMII attached PHY...\n"); 7768cfa0ad2SJack F Vogel 7778cfa0ad2SJack F Vogel if (!(hw->phy.ops.write_reg)) 7788cfa0ad2SJack F Vogel goto out; 7798cfa0ad2SJack F Vogel 7808cfa0ad2SJack F Vogel /* 7818cfa0ad2SJack F Vogel * SFP documentation requires the following to configure the SPF module 7828cfa0ad2SJack F Vogel * to work on SGMII. No further documentation is given. 7838cfa0ad2SJack F Vogel */ 7848cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084); 7858cfa0ad2SJack F Vogel if (ret_val) 7868cfa0ad2SJack F Vogel goto out; 7878cfa0ad2SJack F Vogel 7888cfa0ad2SJack F Vogel ret_val = hw->phy.ops.commit(hw); 7898cc64f1eSJack F Vogel if (ret_val) 7908cc64f1eSJack F Vogel goto out; 7918cfa0ad2SJack F Vogel 7928cc64f1eSJack F Vogel if (phy->id == M88E1512_E_PHY_ID) 7938cc64f1eSJack F Vogel ret_val = e1000_initialize_M88E1512_phy(hw); 7948cfa0ad2SJack F Vogel out: 7958cfa0ad2SJack F Vogel return ret_val; 7968cfa0ad2SJack F Vogel } 7978cfa0ad2SJack F Vogel 7988cfa0ad2SJack F Vogel /** 7998cfa0ad2SJack F Vogel * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state 8008cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 8018cfa0ad2SJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 8028cfa0ad2SJack F Vogel * 8038cfa0ad2SJack F Vogel * Sets the LPLU D0 state according to the active flag. When 8048cfa0ad2SJack F Vogel * activating LPLU this function also disables smart speed 8058cfa0ad2SJack F Vogel * and vice versa. LPLU will not be activated unless the 8068cfa0ad2SJack F Vogel * device autonegotiation advertisement meets standards of 8078cfa0ad2SJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 8088cfa0ad2SJack F Vogel * This is a function pointer entry point only called by 8098cfa0ad2SJack F Vogel * PHY setup routines. 8108cfa0ad2SJack F Vogel **/ 8118cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active) 8128cfa0ad2SJack F Vogel { 8138cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 8148cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 8158cfa0ad2SJack F Vogel u16 data; 8168cfa0ad2SJack F Vogel 8178cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82575"); 8188cfa0ad2SJack F Vogel 8198cfa0ad2SJack F Vogel if (!(hw->phy.ops.read_reg)) 8208cfa0ad2SJack F Vogel goto out; 8218cfa0ad2SJack F Vogel 8228cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); 8238cfa0ad2SJack F Vogel if (ret_val) 8248cfa0ad2SJack F Vogel goto out; 8258cfa0ad2SJack F Vogel 8268cfa0ad2SJack F Vogel if (active) { 8278cfa0ad2SJack F Vogel data |= IGP02E1000_PM_D0_LPLU; 8288cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 8298cfa0ad2SJack F Vogel data); 8308cfa0ad2SJack F Vogel if (ret_val) 8318cfa0ad2SJack F Vogel goto out; 8328cfa0ad2SJack F Vogel 8338cfa0ad2SJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 8348cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 8358cfa0ad2SJack F Vogel &data); 8368cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 8378cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG, 8388cfa0ad2SJack F Vogel data); 8398cfa0ad2SJack F Vogel if (ret_val) 8408cfa0ad2SJack F Vogel goto out; 8418cfa0ad2SJack F Vogel } else { 8428cfa0ad2SJack F Vogel data &= ~IGP02E1000_PM_D0_LPLU; 8438cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT, 8448cfa0ad2SJack F Vogel data); 8458cfa0ad2SJack F Vogel /* 8468cfa0ad2SJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 8478cfa0ad2SJack F Vogel * during Dx states where the power conservation is most 8488cfa0ad2SJack F Vogel * important. During driver activity we should enable 8498cfa0ad2SJack F Vogel * SmartSpeed, so performance is maintained. 8508cfa0ad2SJack F Vogel */ 8518cfa0ad2SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) { 8528cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 8538cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8548cfa0ad2SJack F Vogel &data); 8558cfa0ad2SJack F Vogel if (ret_val) 8568cfa0ad2SJack F Vogel goto out; 8578cfa0ad2SJack F Vogel 8588cfa0ad2SJack F Vogel data |= IGP01E1000_PSCFR_SMART_SPEED; 8598cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8608cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8618cfa0ad2SJack F Vogel data); 8628cfa0ad2SJack F Vogel if (ret_val) 8638cfa0ad2SJack F Vogel goto out; 8648cfa0ad2SJack F Vogel } else if (phy->smart_speed == e1000_smart_speed_off) { 8658cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, 8668cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8678cfa0ad2SJack F Vogel &data); 8688cfa0ad2SJack F Vogel if (ret_val) 8698cfa0ad2SJack F Vogel goto out; 8708cfa0ad2SJack F Vogel 8718cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED; 8728cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, 8738cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG, 8748cfa0ad2SJack F Vogel data); 8758cfa0ad2SJack F Vogel if (ret_val) 8768cfa0ad2SJack F Vogel goto out; 8778cfa0ad2SJack F Vogel } 8788cfa0ad2SJack F Vogel } 8798cfa0ad2SJack F Vogel 8808cfa0ad2SJack F Vogel out: 8818cfa0ad2SJack F Vogel return ret_val; 8828cfa0ad2SJack F Vogel } 8838cfa0ad2SJack F Vogel 8848cfa0ad2SJack F Vogel /** 885f0ecc46dSJack F Vogel * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state 886f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 887f0ecc46dSJack F Vogel * @active: TRUE to enable LPLU, FALSE to disable 888f0ecc46dSJack F Vogel * 889f0ecc46dSJack F Vogel * Sets the LPLU D0 state according to the active flag. When 890f0ecc46dSJack F Vogel * activating LPLU this function also disables smart speed 891f0ecc46dSJack F Vogel * and vice versa. LPLU will not be activated unless the 892f0ecc46dSJack F Vogel * device autonegotiation advertisement meets standards of 893f0ecc46dSJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes. 894f0ecc46dSJack F Vogel * This is a function pointer entry point only called by 895f0ecc46dSJack F Vogel * PHY setup routines. 896f0ecc46dSJack F Vogel **/ 897f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active) 898f0ecc46dSJack F Vogel { 899f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 900ab5d0362SJack F Vogel u32 data; 901f0ecc46dSJack F Vogel 902f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82580"); 903f0ecc46dSJack F Vogel 904f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 905f0ecc46dSJack F Vogel 906f0ecc46dSJack F Vogel if (active) { 907f0ecc46dSJack F Vogel data |= E1000_82580_PM_D0_LPLU; 908f0ecc46dSJack F Vogel 909f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 910f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 911f0ecc46dSJack F Vogel } else { 912f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D0_LPLU; 913f0ecc46dSJack F Vogel 914f0ecc46dSJack F Vogel /* 915f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 916f0ecc46dSJack F Vogel * during Dx states where the power conservation is most 917f0ecc46dSJack F Vogel * important. During driver activity we should enable 918f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained. 919f0ecc46dSJack F Vogel */ 9204dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) 921f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD; 9224dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off) 923f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 924f0ecc46dSJack F Vogel } 925f0ecc46dSJack F Vogel 926f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); 9278cc64f1eSJack F Vogel return E1000_SUCCESS; 928f0ecc46dSJack F Vogel } 929f0ecc46dSJack F Vogel 930f0ecc46dSJack F Vogel /** 931f0ecc46dSJack F Vogel * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3 932f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 933f0ecc46dSJack F Vogel * @active: boolean used to enable/disable lplu 934f0ecc46dSJack F Vogel * 935f0ecc46dSJack F Vogel * Success returns 0, Failure returns 1 936f0ecc46dSJack F Vogel * 937f0ecc46dSJack F Vogel * The low power link up (lplu) state is set to the power management level D3 938f0ecc46dSJack F Vogel * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3 939f0ecc46dSJack F Vogel * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU 940f0ecc46dSJack F Vogel * is used during Dx states where the power conservation is most important. 941f0ecc46dSJack F Vogel * During driver activity, SmartSpeed should be enabled so performance is 942f0ecc46dSJack F Vogel * maintained. 943f0ecc46dSJack F Vogel **/ 944f0ecc46dSJack F Vogel s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active) 945f0ecc46dSJack F Vogel { 946f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 947ab5d0362SJack F Vogel u32 data; 948f0ecc46dSJack F Vogel 949f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d3_lplu_state_82580"); 950f0ecc46dSJack F Vogel 951f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 952f0ecc46dSJack F Vogel 953f0ecc46dSJack F Vogel if (!active) { 954f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D3_LPLU; 955f0ecc46dSJack F Vogel /* 956f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used 957f0ecc46dSJack F Vogel * during Dx states where the power conservation is most 958f0ecc46dSJack F Vogel * important. During driver activity we should enable 959f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained. 960f0ecc46dSJack F Vogel */ 9614dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) 962f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD; 9634dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off) 964f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 965f0ecc46dSJack F Vogel } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 966f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 967f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 968f0ecc46dSJack F Vogel data |= E1000_82580_PM_D3_LPLU; 969f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */ 970f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD; 971f0ecc46dSJack F Vogel } 972f0ecc46dSJack F Vogel 973f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data); 9748cc64f1eSJack F Vogel return E1000_SUCCESS; 975f0ecc46dSJack F Vogel } 976f0ecc46dSJack F Vogel 977f0ecc46dSJack F Vogel /** 9788cfa0ad2SJack F Vogel * e1000_acquire_nvm_82575 - Request for access to EEPROM 9798cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 9808cfa0ad2SJack F Vogel * 9818cfa0ad2SJack F Vogel * Acquire the necessary semaphores for exclusive access to the EEPROM. 9828cfa0ad2SJack F Vogel * Set the EEPROM access request bit and wait for EEPROM access grant bit. 9838cfa0ad2SJack F Vogel * Return successful if access grant bit set, else clear the request for 9848cfa0ad2SJack F Vogel * EEPROM access and return -E1000_ERR_NVM (-1). 9858cfa0ad2SJack F Vogel **/ 9868cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw) 9878cfa0ad2SJack F Vogel { 9888cc64f1eSJack F Vogel s32 ret_val = E1000_SUCCESS; 9898cfa0ad2SJack F Vogel 9908cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_nvm_82575"); 9918cfa0ad2SJack F Vogel 9928cfa0ad2SJack F Vogel ret_val = e1000_acquire_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); 9938cfa0ad2SJack F Vogel if (ret_val) 9948cfa0ad2SJack F Vogel goto out; 9954dab5c37SJack F Vogel 9964dab5c37SJack F Vogel /* 9974dab5c37SJack F Vogel * Check if there is some access 9984dab5c37SJack F Vogel * error this access may hook on 9994dab5c37SJack F Vogel */ 10004dab5c37SJack F Vogel if (hw->mac.type == e1000_i350) { 10014dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 10024dab5c37SJack F Vogel if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT | 10034dab5c37SJack F Vogel E1000_EECD_TIMEOUT)) { 10044dab5c37SJack F Vogel /* Clear all access error flags */ 10054dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd | 10064dab5c37SJack F Vogel E1000_EECD_ERROR_CLR); 10074dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); 10084dab5c37SJack F Vogel } 10094dab5c37SJack F Vogel } 10108cc64f1eSJack F Vogel 10114dab5c37SJack F Vogel if (hw->mac.type == e1000_82580) { 10124dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD); 10134dab5c37SJack F Vogel if (eecd & E1000_EECD_BLOCKED) { 10144dab5c37SJack F Vogel /* Clear access error flag */ 10154dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd | 10164dab5c37SJack F Vogel E1000_EECD_BLOCKED); 10174dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n"); 10184dab5c37SJack F Vogel } 10194dab5c37SJack F Vogel } 10204dab5c37SJack F Vogel 10218cfa0ad2SJack F Vogel ret_val = e1000_acquire_nvm_generic(hw); 10228cfa0ad2SJack F Vogel if (ret_val) 10238cfa0ad2SJack F Vogel e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); 10248cfa0ad2SJack F Vogel 10258cfa0ad2SJack F Vogel out: 10268cfa0ad2SJack F Vogel return ret_val; 10278cfa0ad2SJack F Vogel } 10288cfa0ad2SJack F Vogel 10298cfa0ad2SJack F Vogel /** 10308cfa0ad2SJack F Vogel * e1000_release_nvm_82575 - Release exclusive access to EEPROM 10318cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10328cfa0ad2SJack F Vogel * 10338cfa0ad2SJack F Vogel * Stop any current commands to the EEPROM and clear the EEPROM request bit, 10348cfa0ad2SJack F Vogel * then release the semaphores acquired. 10358cfa0ad2SJack F Vogel **/ 10368cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw) 10378cfa0ad2SJack F Vogel { 10388cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_nvm_82575"); 10398cfa0ad2SJack F Vogel 10404dab5c37SJack F Vogel e1000_release_nvm_generic(hw); 1041ab5d0362SJack F Vogel 10428cfa0ad2SJack F Vogel e1000_release_swfw_sync_82575(hw, E1000_SWFW_EEP_SM); 10438cfa0ad2SJack F Vogel } 10448cfa0ad2SJack F Vogel 10458cfa0ad2SJack F Vogel /** 10468cfa0ad2SJack F Vogel * e1000_acquire_swfw_sync_82575 - Acquire SW/FW semaphore 10478cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 10488cfa0ad2SJack F Vogel * @mask: specifies which semaphore to acquire 10498cfa0ad2SJack F Vogel * 10508cfa0ad2SJack F Vogel * Acquire the SW/FW semaphore to access the PHY or NVM. The mask 10518cfa0ad2SJack F Vogel * will also specify which port we're acquiring the lock for. 10528cfa0ad2SJack F Vogel **/ 10538cfa0ad2SJack F Vogel static s32 e1000_acquire_swfw_sync_82575(struct e1000_hw *hw, u16 mask) 10548cfa0ad2SJack F Vogel { 10558cfa0ad2SJack F Vogel u32 swfw_sync; 10568cfa0ad2SJack F Vogel u32 swmask = mask; 10578cfa0ad2SJack F Vogel u32 fwmask = mask << 16; 10588cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS; 105948600901SSean Bruno s32 i = 0, timeout = 200; 10608cfa0ad2SJack F Vogel 10618cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_swfw_sync_82575"); 10628cfa0ad2SJack F Vogel 10638cfa0ad2SJack F Vogel while (i < timeout) { 10648cfa0ad2SJack F Vogel if (e1000_get_hw_semaphore_generic(hw)) { 10658cfa0ad2SJack F Vogel ret_val = -E1000_ERR_SWFW_SYNC; 10668cfa0ad2SJack F Vogel goto out; 10678cfa0ad2SJack F Vogel } 10688cfa0ad2SJack F Vogel 10698cfa0ad2SJack F Vogel swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 10708cfa0ad2SJack F Vogel if (!(swfw_sync & (fwmask | swmask))) 10718cfa0ad2SJack F Vogel break; 10728cfa0ad2SJack F Vogel 10738cfa0ad2SJack F Vogel /* 10748cfa0ad2SJack F Vogel * Firmware currently using resource (fwmask) 10758cfa0ad2SJack F Vogel * or other software thread using resource (swmask) 10768cfa0ad2SJack F Vogel */ 10778cfa0ad2SJack F Vogel e1000_put_hw_semaphore_generic(hw); 10788cfa0ad2SJack F Vogel msec_delay_irq(5); 10798cfa0ad2SJack F Vogel i++; 10808cfa0ad2SJack F Vogel } 10818cfa0ad2SJack F Vogel 10828cfa0ad2SJack F Vogel if (i == timeout) { 10838cfa0ad2SJack F Vogel DEBUGOUT("Driver can't access resource, SW_FW_SYNC timeout.\n"); 10848cfa0ad2SJack F Vogel ret_val = -E1000_ERR_SWFW_SYNC; 10858cfa0ad2SJack F Vogel goto out; 10868cfa0ad2SJack F Vogel } 10878cfa0ad2SJack F Vogel 10888cfa0ad2SJack F Vogel swfw_sync |= swmask; 10898cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 10908cfa0ad2SJack F Vogel 10918cfa0ad2SJack F Vogel e1000_put_hw_semaphore_generic(hw); 10928cfa0ad2SJack F Vogel 10938cfa0ad2SJack F Vogel out: 10948cfa0ad2SJack F Vogel return ret_val; 10958cfa0ad2SJack F Vogel } 10968cfa0ad2SJack F Vogel 10978cfa0ad2SJack F Vogel /** 10988cfa0ad2SJack F Vogel * e1000_release_swfw_sync_82575 - Release SW/FW semaphore 10998cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11008cfa0ad2SJack F Vogel * @mask: specifies which semaphore to acquire 11018cfa0ad2SJack F Vogel * 11028cfa0ad2SJack F Vogel * Release the SW/FW semaphore used to access the PHY or NVM. The mask 11038cfa0ad2SJack F Vogel * will also specify which port we're releasing the lock for. 11048cfa0ad2SJack F Vogel **/ 11058cfa0ad2SJack F Vogel static void e1000_release_swfw_sync_82575(struct e1000_hw *hw, u16 mask) 11068cfa0ad2SJack F Vogel { 11078cfa0ad2SJack F Vogel u32 swfw_sync; 11088cfa0ad2SJack F Vogel 11098cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_swfw_sync_82575"); 11108cfa0ad2SJack F Vogel 11114dab5c37SJack F Vogel while (e1000_get_hw_semaphore_generic(hw) != E1000_SUCCESS) 11124dab5c37SJack F Vogel ; /* Empty */ 11138cfa0ad2SJack F Vogel 11148cfa0ad2SJack F Vogel swfw_sync = E1000_READ_REG(hw, E1000_SW_FW_SYNC); 11158cfa0ad2SJack F Vogel swfw_sync &= ~mask; 11168cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SW_FW_SYNC, swfw_sync); 11178cfa0ad2SJack F Vogel 11188cfa0ad2SJack F Vogel e1000_put_hw_semaphore_generic(hw); 11198cfa0ad2SJack F Vogel } 11208cfa0ad2SJack F Vogel 11218cfa0ad2SJack F Vogel /** 11228cfa0ad2SJack F Vogel * e1000_get_cfg_done_82575 - Read config done bit 11238cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11248cfa0ad2SJack F Vogel * 11258cfa0ad2SJack F Vogel * Read the management control register for the config done bit for 11268cfa0ad2SJack F Vogel * completion status. NOTE: silicon which is EEPROM-less will fail trying 11278cfa0ad2SJack F Vogel * to read the config done bit, so an error is *ONLY* logged and returns 11288cfa0ad2SJack F Vogel * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon 11298cfa0ad2SJack F Vogel * would not be able to be reset or change link. 11308cfa0ad2SJack F Vogel **/ 11318cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw) 11328cfa0ad2SJack F Vogel { 11338cfa0ad2SJack F Vogel s32 timeout = PHY_CFG_TIMEOUT; 11348cfa0ad2SJack F Vogel u32 mask = E1000_NVM_CFG_DONE_PORT_0; 11358cfa0ad2SJack F Vogel 11368cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_cfg_done_82575"); 11378cfa0ad2SJack F Vogel 11389d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1) 11398cfa0ad2SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_1; 11404edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2) 11414edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_2; 11424edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3) 11434edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_3; 11448cfa0ad2SJack F Vogel while (timeout) { 11458cfa0ad2SJack F Vogel if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask) 11468cfa0ad2SJack F Vogel break; 11478cfa0ad2SJack F Vogel msec_delay(1); 11488cfa0ad2SJack F Vogel timeout--; 11498cfa0ad2SJack F Vogel } 11504edd8523SJack F Vogel if (!timeout) 11518cfa0ad2SJack F Vogel DEBUGOUT("MNG configuration cycle has not completed.\n"); 11528cfa0ad2SJack F Vogel 11538cfa0ad2SJack F Vogel /* If EEPROM is not marked present, init the PHY manually */ 1154ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) && 11554edd8523SJack F Vogel (hw->phy.type == e1000_phy_igp_3)) 11568cfa0ad2SJack F Vogel e1000_phy_init_script_igp3(hw); 11578cfa0ad2SJack F Vogel 11588cc64f1eSJack F Vogel return E1000_SUCCESS; 11598cfa0ad2SJack F Vogel } 11608cfa0ad2SJack F Vogel 11618cfa0ad2SJack F Vogel /** 11628cfa0ad2SJack F Vogel * e1000_get_link_up_info_82575 - Get link speed/duplex info 11638cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11648cfa0ad2SJack F Vogel * @speed: stores the current speed 11658cfa0ad2SJack F Vogel * @duplex: stores the current duplex 11668cfa0ad2SJack F Vogel * 11678cfa0ad2SJack F Vogel * This is a wrapper function, if using the serial gigabit media independent 11688cfa0ad2SJack F Vogel * interface, use PCS to retrieve the link speed and duplex information. 11698cfa0ad2SJack F Vogel * Otherwise, use the generic function to get the link speed and duplex info. 11708cfa0ad2SJack F Vogel **/ 11718cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed, 11728cfa0ad2SJack F Vogel u16 *duplex) 11738cfa0ad2SJack F Vogel { 11748cfa0ad2SJack F Vogel s32 ret_val; 11758cfa0ad2SJack F Vogel 11768cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_link_up_info_82575"); 11778cfa0ad2SJack F Vogel 11784edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) 11798cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed, 11808cfa0ad2SJack F Vogel duplex); 11814edd8523SJack F Vogel else 11828cfa0ad2SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, 11838cfa0ad2SJack F Vogel duplex); 11848cfa0ad2SJack F Vogel 11858cfa0ad2SJack F Vogel return ret_val; 11868cfa0ad2SJack F Vogel } 11878cfa0ad2SJack F Vogel 11888cfa0ad2SJack F Vogel /** 11898cfa0ad2SJack F Vogel * e1000_check_for_link_82575 - Check for link 11908cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 11918cfa0ad2SJack F Vogel * 11928cfa0ad2SJack F Vogel * If sgmii is enabled, then use the pcs register to determine link, otherwise 11938cfa0ad2SJack F Vogel * use the generic interface for determining link. 11948cfa0ad2SJack F Vogel **/ 11958cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw) 11968cfa0ad2SJack F Vogel { 11978cfa0ad2SJack F Vogel s32 ret_val; 11988cfa0ad2SJack F Vogel u16 speed, duplex; 11998cfa0ad2SJack F Vogel 12008cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_for_link_82575"); 12018cfa0ad2SJack F Vogel 12024edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) { 12038cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed, 12048cfa0ad2SJack F Vogel &duplex); 1205d035aa2dSJack F Vogel /* 1206d035aa2dSJack F Vogel * Use this flag to determine if link needs to be checked or 1207d035aa2dSJack F Vogel * not. If we have link clear the flag so that we do not 1208d035aa2dSJack F Vogel * continue to check for link. 1209d035aa2dSJack F Vogel */ 1210d035aa2dSJack F Vogel hw->mac.get_link_status = !hw->mac.serdes_has_link; 1211ab5d0362SJack F Vogel 12126ab6bfe3SJack F Vogel /* 12136ab6bfe3SJack F Vogel * Configure Flow Control now that Auto-Neg has completed. 12146ab6bfe3SJack F Vogel * First, we need to restore the desired flow control 12156ab6bfe3SJack F Vogel * settings because we may have had to re-autoneg with a 12166ab6bfe3SJack F Vogel * different link partner. 12176ab6bfe3SJack F Vogel */ 12186ab6bfe3SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw); 12196ab6bfe3SJack F Vogel if (ret_val) 12206ab6bfe3SJack F Vogel DEBUGOUT("Error configuring flow control\n"); 1221d035aa2dSJack F Vogel } else { 12228cfa0ad2SJack F Vogel ret_val = e1000_check_for_copper_link_generic(hw); 1223d035aa2dSJack F Vogel } 12248cfa0ad2SJack F Vogel 12258cfa0ad2SJack F Vogel return ret_val; 12268cfa0ad2SJack F Vogel } 12278cfa0ad2SJack F Vogel 12288cfa0ad2SJack F Vogel /** 12297609433eSJack F Vogel * e1000_check_for_link_media_swap - Check which M88E1112 interface linked 12307609433eSJack F Vogel * @hw: pointer to the HW structure 12317609433eSJack F Vogel * 12327609433eSJack F Vogel * Poll the M88E1112 interfaces to see which interface achieved link. 12337609433eSJack F Vogel */ 12347609433eSJack F Vogel static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw) 12357609433eSJack F Vogel { 12367609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 12377609433eSJack F Vogel s32 ret_val; 12387609433eSJack F Vogel u16 data; 12397609433eSJack F Vogel u8 port = 0; 12407609433eSJack F Vogel 12417609433eSJack F Vogel DEBUGFUNC("e1000_check_for_link_media_swap"); 12427609433eSJack F Vogel 1243c80429ceSEric Joyner /* Check for copper. */ 12447609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 12457609433eSJack F Vogel if (ret_val) 12467609433eSJack F Vogel return ret_val; 12477609433eSJack F Vogel 12487609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); 12497609433eSJack F Vogel if (ret_val) 12507609433eSJack F Vogel return ret_val; 12517609433eSJack F Vogel 12527609433eSJack F Vogel if (data & E1000_M88E1112_STATUS_LINK) 12537609433eSJack F Vogel port = E1000_MEDIA_PORT_COPPER; 12547609433eSJack F Vogel 1255c80429ceSEric Joyner /* Check for other. */ 12567609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1); 12577609433eSJack F Vogel if (ret_val) 12587609433eSJack F Vogel return ret_val; 12597609433eSJack F Vogel 12607609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data); 12617609433eSJack F Vogel if (ret_val) 12627609433eSJack F Vogel return ret_val; 12637609433eSJack F Vogel 12647609433eSJack F Vogel if (data & E1000_M88E1112_STATUS_LINK) 12657609433eSJack F Vogel port = E1000_MEDIA_PORT_OTHER; 12667609433eSJack F Vogel 12677609433eSJack F Vogel /* Determine if a swap needs to happen. */ 12687609433eSJack F Vogel if (port && (hw->dev_spec._82575.media_port != port)) { 12697609433eSJack F Vogel hw->dev_spec._82575.media_port = port; 12707609433eSJack F Vogel hw->dev_spec._82575.media_changed = TRUE; 1271c80429ceSEric Joyner } 1272c80429ceSEric Joyner 1273c80429ceSEric Joyner if (port == E1000_MEDIA_PORT_COPPER) { 1274c80429ceSEric Joyner /* reset page to 0 */ 1275c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 1276c80429ceSEric Joyner if (ret_val) 1277c80429ceSEric Joyner return ret_val; 1278c80429ceSEric Joyner e1000_check_for_link_82575(hw); 12797609433eSJack F Vogel } else { 1280c80429ceSEric Joyner e1000_check_for_link_82575(hw); 1281c80429ceSEric Joyner /* reset page to 0 */ 1282c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0); 1283c80429ceSEric Joyner if (ret_val) 1284c80429ceSEric Joyner return ret_val; 12857609433eSJack F Vogel } 12867609433eSJack F Vogel 12877609433eSJack F Vogel return E1000_SUCCESS; 12887609433eSJack F Vogel } 12897609433eSJack F Vogel 12907609433eSJack F Vogel /** 1291a69ed8dfSJack F Vogel * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown 1292a69ed8dfSJack F Vogel * @hw: pointer to the HW structure 1293a69ed8dfSJack F Vogel **/ 1294a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw) 1295a69ed8dfSJack F Vogel { 1296a69ed8dfSJack F Vogel u32 reg; 1297a69ed8dfSJack F Vogel 1298a69ed8dfSJack F Vogel DEBUGFUNC("e1000_power_up_serdes_link_82575"); 1299a69ed8dfSJack F Vogel 1300a69ed8dfSJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 1301a69ed8dfSJack F Vogel !e1000_sgmii_active_82575(hw)) 1302a69ed8dfSJack F Vogel return; 1303a69ed8dfSJack F Vogel 1304a69ed8dfSJack F Vogel /* Enable PCS to turn on link */ 1305a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0); 1306a69ed8dfSJack F Vogel reg |= E1000_PCS_CFG_PCS_EN; 1307a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); 1308a69ed8dfSJack F Vogel 1309a69ed8dfSJack F Vogel /* Power up the laser */ 1310a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT); 1311a69ed8dfSJack F Vogel reg &= ~E1000_CTRL_EXT_SDP3_DATA; 1312a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); 1313a69ed8dfSJack F Vogel 1314a69ed8dfSJack F Vogel /* flush the write to verify completion */ 1315a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw); 1316a69ed8dfSJack F Vogel msec_delay(1); 1317a69ed8dfSJack F Vogel } 1318a69ed8dfSJack F Vogel 1319a69ed8dfSJack F Vogel /** 13208cfa0ad2SJack F Vogel * e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex 13218cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13228cfa0ad2SJack F Vogel * @speed: stores the current speed 13238cfa0ad2SJack F Vogel * @duplex: stores the current duplex 13248cfa0ad2SJack F Vogel * 13258cfa0ad2SJack F Vogel * Using the physical coding sub-layer (PCS), retrieve the current speed and 13268cfa0ad2SJack F Vogel * duplex, then store the values in the pointers provided. 13278cfa0ad2SJack F Vogel **/ 13288cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw, 13298cfa0ad2SJack F Vogel u16 *speed, u16 *duplex) 13308cfa0ad2SJack F Vogel { 13318cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 13328cfa0ad2SJack F Vogel u32 pcs; 13337609433eSJack F Vogel u32 status; 13348cfa0ad2SJack F Vogel 13358cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575"); 13368cfa0ad2SJack F Vogel 13378cfa0ad2SJack F Vogel /* 13388cfa0ad2SJack F Vogel * Read the PCS Status register for link state. For non-copper mode, 13398cfa0ad2SJack F Vogel * the status register is not accurate. The PCS status register is 13408cfa0ad2SJack F Vogel * used instead. 13418cfa0ad2SJack F Vogel */ 13428cfa0ad2SJack F Vogel pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT); 13438cfa0ad2SJack F Vogel 13448cfa0ad2SJack F Vogel /* 1345ab5d0362SJack F Vogel * The link up bit determines when link is up on autoneg. 13468cfa0ad2SJack F Vogel */ 1347ab5d0362SJack F Vogel if (pcs & E1000_PCS_LSTS_LINK_OK) { 13488cfa0ad2SJack F Vogel mac->serdes_has_link = TRUE; 13498cfa0ad2SJack F Vogel 13508cfa0ad2SJack F Vogel /* Detect and store PCS speed */ 13514dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_SPEED_1000) 13528cfa0ad2SJack F Vogel *speed = SPEED_1000; 13534dab5c37SJack F Vogel else if (pcs & E1000_PCS_LSTS_SPEED_100) 13548cfa0ad2SJack F Vogel *speed = SPEED_100; 13554dab5c37SJack F Vogel else 13568cfa0ad2SJack F Vogel *speed = SPEED_10; 13578cfa0ad2SJack F Vogel 13588cfa0ad2SJack F Vogel /* Detect and store PCS duplex */ 13594dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_DUPLEX_FULL) 13608cfa0ad2SJack F Vogel *duplex = FULL_DUPLEX; 13614dab5c37SJack F Vogel else 13628cfa0ad2SJack F Vogel *duplex = HALF_DUPLEX; 13636ab6bfe3SJack F Vogel 13647609433eSJack F Vogel /* Check if it is an I354 2.5Gb backplane connection. */ 13657609433eSJack F Vogel if (mac->type == e1000_i354) { 13667609433eSJack F Vogel status = E1000_READ_REG(hw, E1000_STATUS); 13677609433eSJack F Vogel if ((status & E1000_STATUS_2P5_SKU) && 13687609433eSJack F Vogel !(status & E1000_STATUS_2P5_SKU_OVER)) { 13697609433eSJack F Vogel *speed = SPEED_2500; 13707609433eSJack F Vogel *duplex = FULL_DUPLEX; 13717609433eSJack F Vogel DEBUGOUT("2500 Mbs, "); 13727609433eSJack F Vogel DEBUGOUT("Full Duplex\n"); 13737609433eSJack F Vogel } 13747609433eSJack F Vogel } 13757609433eSJack F Vogel 1376ab5d0362SJack F Vogel } else { 1377ab5d0362SJack F Vogel mac->serdes_has_link = FALSE; 1378ab5d0362SJack F Vogel *speed = 0; 1379ab5d0362SJack F Vogel *duplex = 0; 13808cfa0ad2SJack F Vogel } 13818cfa0ad2SJack F Vogel 13828cfa0ad2SJack F Vogel return E1000_SUCCESS; 13838cfa0ad2SJack F Vogel } 13848cfa0ad2SJack F Vogel 13858cfa0ad2SJack F Vogel /** 13864edd8523SJack F Vogel * e1000_shutdown_serdes_link_82575 - Remove link during power down 13878cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 13888cfa0ad2SJack F Vogel * 13894edd8523SJack F Vogel * In the case of serdes shut down sfp and PCS on driver unload 13908cfa0ad2SJack F Vogel * when management pass thru is not enabled. 13918cfa0ad2SJack F Vogel **/ 13924edd8523SJack F Vogel void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw) 13938cfa0ad2SJack F Vogel { 13948cfa0ad2SJack F Vogel u32 reg; 1395a69ed8dfSJack F Vogel 1396a69ed8dfSJack F Vogel DEBUGFUNC("e1000_shutdown_serdes_link_82575"); 13978cfa0ad2SJack F Vogel 13984edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 13994edd8523SJack F Vogel !e1000_sgmii_active_82575(hw)) 14008cfa0ad2SJack F Vogel return; 14018cfa0ad2SJack F Vogel 1402a69ed8dfSJack F Vogel if (!e1000_enable_mng_pass_thru(hw)) { 14038cfa0ad2SJack F Vogel /* Disable PCS to turn off link */ 14048cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0); 14058cfa0ad2SJack F Vogel reg &= ~E1000_PCS_CFG_PCS_EN; 14068cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg); 14078cfa0ad2SJack F Vogel 14088cfa0ad2SJack F Vogel /* shutdown the laser */ 14098cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT); 14104edd8523SJack F Vogel reg |= E1000_CTRL_EXT_SDP3_DATA; 14118cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg); 14128cfa0ad2SJack F Vogel 14134edd8523SJack F Vogel /* flush the write to verify completion */ 14148cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 14158cfa0ad2SJack F Vogel msec_delay(1); 14168cfa0ad2SJack F Vogel } 14178cfa0ad2SJack F Vogel 14188cfa0ad2SJack F Vogel return; 14198cfa0ad2SJack F Vogel } 14208cfa0ad2SJack F Vogel 14218cfa0ad2SJack F Vogel /** 14228cfa0ad2SJack F Vogel * e1000_reset_hw_82575 - Reset hardware 14238cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14248cfa0ad2SJack F Vogel * 1425daf9197cSJack F Vogel * This resets the hardware into a known state. 14268cfa0ad2SJack F Vogel **/ 14278cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw) 14288cfa0ad2SJack F Vogel { 1429f0ecc46dSJack F Vogel u32 ctrl; 14308cfa0ad2SJack F Vogel s32 ret_val; 14318cfa0ad2SJack F Vogel 14328cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_82575"); 14338cfa0ad2SJack F Vogel 14348cfa0ad2SJack F Vogel /* 14358cfa0ad2SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection 14368cfa0ad2SJack F Vogel * on the last TLP read/write transaction when MAC is reset. 14378cfa0ad2SJack F Vogel */ 14388cfa0ad2SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw); 14394dab5c37SJack F Vogel if (ret_val) 14408cfa0ad2SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 14418cfa0ad2SJack F Vogel 14429d81738fSJack F Vogel /* set the completion timeout for interface */ 14439d81738fSJack F Vogel ret_val = e1000_set_pcie_completion_timeout(hw); 14444dab5c37SJack F Vogel if (ret_val) 14459d81738fSJack F Vogel DEBUGOUT("PCI-E Set completion timeout has failed.\n"); 14469d81738fSJack F Vogel 14478cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 14488cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 14498cfa0ad2SJack F Vogel 14508cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 14518cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 14528cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 14538cfa0ad2SJack F Vogel 14548cfa0ad2SJack F Vogel msec_delay(10); 14558cfa0ad2SJack F Vogel 14568cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 14578cfa0ad2SJack F Vogel 14588cfa0ad2SJack F Vogel DEBUGOUT("Issuing a global reset to MAC\n"); 14598cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST); 14608cfa0ad2SJack F Vogel 14618cfa0ad2SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw); 14628cfa0ad2SJack F Vogel if (ret_val) { 14638cfa0ad2SJack F Vogel /* 14648cfa0ad2SJack F Vogel * When auto config read does not complete, do not 14658cfa0ad2SJack F Vogel * return with an error. This can happen in situations 14668cfa0ad2SJack F Vogel * where there is no eeprom and prevents getting link. 14678cfa0ad2SJack F Vogel */ 14688cfa0ad2SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n"); 14698cfa0ad2SJack F Vogel } 14708cfa0ad2SJack F Vogel 14718cfa0ad2SJack F Vogel /* If EEPROM is not present, run manual init scripts */ 1472ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES)) 14738cfa0ad2SJack F Vogel e1000_reset_init_script_82575(hw); 14748cfa0ad2SJack F Vogel 14758cfa0ad2SJack F Vogel /* Clear any pending interrupt events. */ 14768cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 1477f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR); 14788cfa0ad2SJack F Vogel 1479d035aa2dSJack F Vogel /* Install any alternate MAC address into RAR0 */ 1480d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 14818cfa0ad2SJack F Vogel 14828cfa0ad2SJack F Vogel return ret_val; 14838cfa0ad2SJack F Vogel } 14848cfa0ad2SJack F Vogel 14858cfa0ad2SJack F Vogel /** 14868cfa0ad2SJack F Vogel * e1000_init_hw_82575 - Initialize hardware 14878cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 14888cfa0ad2SJack F Vogel * 14898cfa0ad2SJack F Vogel * This inits the hardware readying it for operation. 14908cfa0ad2SJack F Vogel **/ 14918cc64f1eSJack F Vogel s32 e1000_init_hw_82575(struct e1000_hw *hw) 14928cfa0ad2SJack F Vogel { 14938cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac; 14948cfa0ad2SJack F Vogel s32 ret_val; 14958cfa0ad2SJack F Vogel u16 i, rar_count = mac->rar_entry_count; 14968cfa0ad2SJack F Vogel 14978cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_82575"); 14988cfa0ad2SJack F Vogel 14998cfa0ad2SJack F Vogel /* Initialize identification LED */ 1500d035aa2dSJack F Vogel ret_val = mac->ops.id_led_init(hw); 15018cfa0ad2SJack F Vogel if (ret_val) { 15028cfa0ad2SJack F Vogel DEBUGOUT("Error initializing identification LED\n"); 15038cfa0ad2SJack F Vogel /* This is not fatal and we should not stop init due to this */ 15048cfa0ad2SJack F Vogel } 15058cfa0ad2SJack F Vogel 15068cfa0ad2SJack F Vogel /* Disabling VLAN filtering */ 15078cfa0ad2SJack F Vogel DEBUGOUT("Initializing the IEEE VLAN\n"); 15088cfa0ad2SJack F Vogel mac->ops.clear_vfta(hw); 15098cfa0ad2SJack F Vogel 15108cfa0ad2SJack F Vogel /* Setup the receive address */ 1511d035aa2dSJack F Vogel e1000_init_rx_addrs_generic(hw, rar_count); 1512d035aa2dSJack F Vogel 15138cfa0ad2SJack F Vogel /* Zero out the Multicast HASH table */ 15148cfa0ad2SJack F Vogel DEBUGOUT("Zeroing the MTA\n"); 15158cfa0ad2SJack F Vogel for (i = 0; i < mac->mta_reg_count; i++) 15168cfa0ad2SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0); 15178cfa0ad2SJack F Vogel 15184edd8523SJack F Vogel /* Zero out the Unicast HASH table */ 15194edd8523SJack F Vogel DEBUGOUT("Zeroing the UTA\n"); 15204edd8523SJack F Vogel for (i = 0; i < mac->uta_reg_count; i++) 15214edd8523SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_UTA, i, 0); 15224edd8523SJack F Vogel 15238cfa0ad2SJack F Vogel /* Setup link and flow control */ 15248cfa0ad2SJack F Vogel ret_val = mac->ops.setup_link(hw); 15258cfa0ad2SJack F Vogel 15264dab5c37SJack F Vogel /* Set the default MTU size */ 15274dab5c37SJack F Vogel hw->dev_spec._82575.mtu = 1500; 15284dab5c37SJack F Vogel 15298cfa0ad2SJack F Vogel /* 15308cfa0ad2SJack F Vogel * Clear all of the statistics registers (clear on read). It is 15318cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link 15328cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there 15338cfa0ad2SJack F Vogel * is no link. 15348cfa0ad2SJack F Vogel */ 15358cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_82575(hw); 15368cfa0ad2SJack F Vogel 15378cfa0ad2SJack F Vogel return ret_val; 15388cfa0ad2SJack F Vogel } 15398cfa0ad2SJack F Vogel 15408cfa0ad2SJack F Vogel /** 15418cfa0ad2SJack F Vogel * e1000_setup_copper_link_82575 - Configure copper link settings 15428cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 15438cfa0ad2SJack F Vogel * 15448cfa0ad2SJack F Vogel * Configures the link for auto-neg or forced speed and duplex. Then we check 15458cfa0ad2SJack F Vogel * for link, once link is established calls to configure collision distance 15468cfa0ad2SJack F Vogel * and flow control are called. 15478cfa0ad2SJack F Vogel **/ 15488cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw) 15498cfa0ad2SJack F Vogel { 15509d81738fSJack F Vogel u32 ctrl; 15518cfa0ad2SJack F Vogel s32 ret_val; 15526ab6bfe3SJack F Vogel u32 phpm_reg; 15538cfa0ad2SJack F Vogel 15548cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_82575"); 15558cfa0ad2SJack F Vogel 15568cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 15578cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SLU; 15588cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 15598cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 15608cfa0ad2SJack F Vogel 15617609433eSJack F Vogel /* Clear Go Link Disconnect bit on supported devices */ 15627609433eSJack F Vogel switch (hw->mac.type) { 15637609433eSJack F Vogel case e1000_82580: 15647609433eSJack F Vogel case e1000_i350: 15657609433eSJack F Vogel case e1000_i210: 15667609433eSJack F Vogel case e1000_i211: 15676ab6bfe3SJack F Vogel phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT); 15686ab6bfe3SJack F Vogel phpm_reg &= ~E1000_82580_PM_GO_LINKD; 15696ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg); 15707609433eSJack F Vogel break; 15717609433eSJack F Vogel default: 15727609433eSJack F Vogel break; 15736ab6bfe3SJack F Vogel } 15746ab6bfe3SJack F Vogel 15754edd8523SJack F Vogel ret_val = e1000_setup_serdes_link_82575(hw); 15764edd8523SJack F Vogel if (ret_val) 15774edd8523SJack F Vogel goto out; 15784edd8523SJack F Vogel 15794dab5c37SJack F Vogel if (e1000_sgmii_active_82575(hw)) { 15804edd8523SJack F Vogel /* allow time for SFP cage time to power up phy */ 15814edd8523SJack F Vogel msec_delay(300); 15824edd8523SJack F Vogel 15834edd8523SJack F Vogel ret_val = hw->phy.ops.reset(hw); 15844edd8523SJack F Vogel if (ret_val) { 15854edd8523SJack F Vogel DEBUGOUT("Error resetting the PHY.\n"); 15864edd8523SJack F Vogel goto out; 15874edd8523SJack F Vogel } 15884edd8523SJack F Vogel } 15898cfa0ad2SJack F Vogel switch (hw->phy.type) { 1590ab5d0362SJack F Vogel case e1000_phy_i210: 15918cfa0ad2SJack F Vogel case e1000_phy_m88: 15926ab6bfe3SJack F Vogel switch (hw->phy.id) { 15936ab6bfe3SJack F Vogel case I347AT4_E_PHY_ID: 15946ab6bfe3SJack F Vogel case M88E1112_E_PHY_ID: 15956ab6bfe3SJack F Vogel case M88E1340M_E_PHY_ID: 15967609433eSJack F Vogel case M88E1543_E_PHY_ID: 15977609433eSJack F Vogel case M88E1512_E_PHY_ID: 15986ab6bfe3SJack F Vogel case I210_I_PHY_ID: 1599f0ecc46dSJack F Vogel ret_val = e1000_copper_link_setup_m88_gen2(hw); 16006ab6bfe3SJack F Vogel break; 16016ab6bfe3SJack F Vogel default: 16028cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_m88(hw); 16038cfa0ad2SJack F Vogel break; 16046ab6bfe3SJack F Vogel } 16056ab6bfe3SJack F Vogel break; 16068cfa0ad2SJack F Vogel case e1000_phy_igp_3: 16078cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_igp(hw); 16088cfa0ad2SJack F Vogel break; 16094edd8523SJack F Vogel case e1000_phy_82580: 16104edd8523SJack F Vogel ret_val = e1000_copper_link_setup_82577(hw); 16114edd8523SJack F Vogel break; 16128cfa0ad2SJack F Vogel default: 16138cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY; 16148cfa0ad2SJack F Vogel break; 16158cfa0ad2SJack F Vogel } 16168cfa0ad2SJack F Vogel 16178cfa0ad2SJack F Vogel if (ret_val) 16188cfa0ad2SJack F Vogel goto out; 16198cfa0ad2SJack F Vogel 16204edd8523SJack F Vogel ret_val = e1000_setup_copper_link_generic(hw); 16218cfa0ad2SJack F Vogel out: 16228cfa0ad2SJack F Vogel return ret_val; 16238cfa0ad2SJack F Vogel } 16248cfa0ad2SJack F Vogel 16258cfa0ad2SJack F Vogel /** 16264edd8523SJack F Vogel * e1000_setup_serdes_link_82575 - Setup link for serdes 16278cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 16288cfa0ad2SJack F Vogel * 16294edd8523SJack F Vogel * Configure the physical coding sub-layer (PCS) link. The PCS link is 16304edd8523SJack F Vogel * used on copper connections where the serialized gigabit media independent 16314edd8523SJack F Vogel * interface (sgmii), or serdes fiber is being used. Configures the link 16324edd8523SJack F Vogel * for auto-negotiation or forces speed/duplex. 16338cfa0ad2SJack F Vogel **/ 16344edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw) 16358cfa0ad2SJack F Vogel { 16366ab6bfe3SJack F Vogel u32 ctrl_ext, ctrl_reg, reg, anadv_reg; 16374edd8523SJack F Vogel bool pcs_autoneg; 16384dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS; 16394dab5c37SJack F Vogel u16 data; 16408cfa0ad2SJack F Vogel 16414edd8523SJack F Vogel DEBUGFUNC("e1000_setup_serdes_link_82575"); 16424edd8523SJack F Vogel 16434edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) && 16444edd8523SJack F Vogel !e1000_sgmii_active_82575(hw)) 16454dab5c37SJack F Vogel return ret_val; 16468cfa0ad2SJack F Vogel 16478cfa0ad2SJack F Vogel /* 16488cfa0ad2SJack F Vogel * On the 82575, SerDes loopback mode persists until it is 16498cfa0ad2SJack F Vogel * explicitly turned off or a power cycle is performed. A read to 16508cfa0ad2SJack F Vogel * the register does not indicate its status. Therefore, we ensure 16518cfa0ad2SJack F Vogel * loopback mode is disabled during initialization. 16528cfa0ad2SJack F Vogel */ 16538cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK); 16548cfa0ad2SJack F Vogel 16554edd8523SJack F Vogel /* power on the sfp cage if present */ 16564edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 16574edd8523SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; 16584edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 16594edd8523SJack F Vogel 16604edd8523SJack F Vogel ctrl_reg = E1000_READ_REG(hw, E1000_CTRL); 16614edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SLU; 16624edd8523SJack F Vogel 1663a69ed8dfSJack F Vogel /* set both sw defined pins on 82575/82576*/ 1664a69ed8dfSJack F Vogel if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576) 16654edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1; 16668cfa0ad2SJack F Vogel 16674edd8523SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_LCTL); 16684edd8523SJack F Vogel 16694edd8523SJack F Vogel /* default pcs_autoneg to the same setting as mac autoneg */ 16704edd8523SJack F Vogel pcs_autoneg = hw->mac.autoneg; 16714edd8523SJack F Vogel 16724edd8523SJack F Vogel switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) { 16734edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII: 16744edd8523SJack F Vogel /* sgmii mode lets the phy handle forcing speed/duplex */ 16754edd8523SJack F Vogel pcs_autoneg = TRUE; 16764edd8523SJack F Vogel /* autoneg time out should be disabled for SGMII mode */ 16774edd8523SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT); 16784edd8523SJack F Vogel break; 16794edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 16804edd8523SJack F Vogel /* disable PCS autoneg and support parallel detect only */ 16814edd8523SJack F Vogel pcs_autoneg = FALSE; 16827d9119bdSJack F Vogel /* fall through to default case */ 16834edd8523SJack F Vogel default: 16844dab5c37SJack F Vogel if (hw->mac.type == e1000_82575 || 16854dab5c37SJack F Vogel hw->mac.type == e1000_82576) { 16864dab5c37SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data); 16874dab5c37SJack F Vogel if (ret_val) { 16884dab5c37SJack F Vogel DEBUGOUT("NVM Read Error\n"); 16894dab5c37SJack F Vogel return ret_val; 16904dab5c37SJack F Vogel } 16914dab5c37SJack F Vogel 16924dab5c37SJack F Vogel if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT) 16934dab5c37SJack F Vogel pcs_autoneg = FALSE; 16944dab5c37SJack F Vogel } 16954dab5c37SJack F Vogel 16964edd8523SJack F Vogel /* 16974edd8523SJack F Vogel * non-SGMII modes only supports a speed of 1000/Full for the 16984edd8523SJack F Vogel * link so it is best to just force the MAC and let the pcs 16994edd8523SJack F Vogel * link either autoneg or be forced to 1000/Full 17004edd8523SJack F Vogel */ 17014edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD | 17024edd8523SJack F Vogel E1000_CTRL_FD | E1000_CTRL_FRCDPX; 17034edd8523SJack F Vogel 17044edd8523SJack F Vogel /* set speed of 1000/Full if speed/duplex is forced */ 17054edd8523SJack F Vogel reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL; 17064edd8523SJack F Vogel break; 17074edd8523SJack F Vogel } 17084edd8523SJack F Vogel 17094edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg); 17108cfa0ad2SJack F Vogel 17118cfa0ad2SJack F Vogel /* 17128cfa0ad2SJack F Vogel * New SerDes mode allows for forcing speed or autonegotiating speed 17138cfa0ad2SJack F Vogel * at 1gb. Autoneg should be default set by most drivers. This is the 17148cfa0ad2SJack F Vogel * mode that will be compatible with older link partners and switches. 17158cfa0ad2SJack F Vogel * However, both are supported by the hardware and some drivers/tools. 17168cfa0ad2SJack F Vogel */ 17178cfa0ad2SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP | 17188cfa0ad2SJack F Vogel E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK); 17198cfa0ad2SJack F Vogel 17204edd8523SJack F Vogel if (pcs_autoneg) { 17214edd8523SJack F Vogel /* Set PCS register for autoneg */ 17224edd8523SJack F Vogel reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */ 17234edd8523SJack F Vogel E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */ 17246ab6bfe3SJack F Vogel 17256ab6bfe3SJack F Vogel /* Disable force flow control for autoneg */ 17266ab6bfe3SJack F Vogel reg &= ~E1000_PCS_LCTL_FORCE_FCTRL; 17276ab6bfe3SJack F Vogel 17286ab6bfe3SJack F Vogel /* Configure flow control advertisement for autoneg */ 17296ab6bfe3SJack F Vogel anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV); 17306ab6bfe3SJack F Vogel anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE); 17316ab6bfe3SJack F Vogel 17326ab6bfe3SJack F Vogel switch (hw->fc.requested_mode) { 17336ab6bfe3SJack F Vogel case e1000_fc_full: 17346ab6bfe3SJack F Vogel case e1000_fc_rx_pause: 17356ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_ASM_DIR; 17366ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_PAUSE; 17376ab6bfe3SJack F Vogel break; 17386ab6bfe3SJack F Vogel case e1000_fc_tx_pause: 17396ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_ASM_DIR; 17406ab6bfe3SJack F Vogel break; 17416ab6bfe3SJack F Vogel default: 17426ab6bfe3SJack F Vogel break; 17436ab6bfe3SJack F Vogel } 17446ab6bfe3SJack F Vogel 17456ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg); 17466ab6bfe3SJack F Vogel 17474edd8523SJack F Vogel DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg); 17484edd8523SJack F Vogel } else { 17494edd8523SJack F Vogel /* Set PCS register for forced link */ 1750a69ed8dfSJack F Vogel reg |= E1000_PCS_LCTL_FSD; /* Force Speed */ 17516ab6bfe3SJack F Vogel 17526ab6bfe3SJack F Vogel /* Force flow control for forced link */ 17536ab6bfe3SJack F Vogel reg |= E1000_PCS_LCTL_FORCE_FCTRL; 17546ab6bfe3SJack F Vogel 17554edd8523SJack F Vogel DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg); 17568cfa0ad2SJack F Vogel } 17578cfa0ad2SJack F Vogel 17588cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg); 17598cfa0ad2SJack F Vogel 17606ab6bfe3SJack F Vogel if (!pcs_autoneg && !e1000_sgmii_active_82575(hw)) 17614edd8523SJack F Vogel e1000_force_mac_fc_generic(hw); 17624edd8523SJack F Vogel 17634dab5c37SJack F Vogel return ret_val; 17644dab5c37SJack F Vogel } 17654dab5c37SJack F Vogel 17664dab5c37SJack F Vogel /** 17674dab5c37SJack F Vogel * e1000_get_media_type_82575 - derives current media type. 17684dab5c37SJack F Vogel * @hw: pointer to the HW structure 17694dab5c37SJack F Vogel * 17704dab5c37SJack F Vogel * The media type is chosen reflecting few settings. 17714dab5c37SJack F Vogel * The following are taken into account: 17724dab5c37SJack F Vogel * - link mode set in the current port Init Control Word #3 17734dab5c37SJack F Vogel * - current link mode settings in CSR register 17744dab5c37SJack F Vogel * - MDIO vs. I2C PHY control interface chosen 17754dab5c37SJack F Vogel * - SFP module media type 17764dab5c37SJack F Vogel **/ 17774dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw) 17784dab5c37SJack F Vogel { 17794dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 17806ab6bfe3SJack F Vogel s32 ret_val = E1000_SUCCESS; 17814dab5c37SJack F Vogel u32 ctrl_ext = 0; 17826ab6bfe3SJack F Vogel u32 link_mode = 0; 17834dab5c37SJack F Vogel 17844dab5c37SJack F Vogel /* Set internal phy as default */ 17854dab5c37SJack F Vogel dev_spec->sgmii_active = FALSE; 17864dab5c37SJack F Vogel dev_spec->module_plugged = FALSE; 17874dab5c37SJack F Vogel 17884dab5c37SJack F Vogel /* Get CSR setting */ 17894dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 17904dab5c37SJack F Vogel 17916ab6bfe3SJack F Vogel /* extract link mode setting */ 17926ab6bfe3SJack F Vogel link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK; 17934dab5c37SJack F Vogel 17946ab6bfe3SJack F Vogel switch (link_mode) { 17954dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX: 17964dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 17974dab5c37SJack F Vogel break; 17984dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_GMII: 17994dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 18004dab5c37SJack F Vogel break; 18014dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII: 18024dab5c37SJack F Vogel /* Get phy control interface type set (MDIO vs. I2C)*/ 18034dab5c37SJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) { 18044dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 18054dab5c37SJack F Vogel dev_spec->sgmii_active = TRUE; 18064dab5c37SJack F Vogel break; 18074dab5c37SJack F Vogel } 18086ab6bfe3SJack F Vogel /* fall through for I2C based SGMII */ 18096ab6bfe3SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES: 18106ab6bfe3SJack F Vogel /* read media type from SFP EEPROM */ 18116ab6bfe3SJack F Vogel ret_val = e1000_set_sfp_media_type_82575(hw); 18126ab6bfe3SJack F Vogel if ((ret_val != E1000_SUCCESS) || 18136ab6bfe3SJack F Vogel (hw->phy.media_type == e1000_media_type_unknown)) { 18144dab5c37SJack F Vogel /* 18156ab6bfe3SJack F Vogel * If media type was not identified then return media 18166ab6bfe3SJack F Vogel * type defined by the CTRL_EXT settings. 18174dab5c37SJack F Vogel */ 18186ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 18196ab6bfe3SJack F Vogel 18206ab6bfe3SJack F Vogel if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) { 18216ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 18226ab6bfe3SJack F Vogel dev_spec->sgmii_active = TRUE; 18234dab5c37SJack F Vogel } 18244dab5c37SJack F Vogel 18256ab6bfe3SJack F Vogel break; 18266ab6bfe3SJack F Vogel } 18276ab6bfe3SJack F Vogel 18286ab6bfe3SJack F Vogel /* do not change link mode for 100BaseFX */ 18296ab6bfe3SJack F Vogel if (dev_spec->eth_flags.e100_base_fx) 18306ab6bfe3SJack F Vogel break; 18316ab6bfe3SJack F Vogel 18326ab6bfe3SJack F Vogel /* change current link mode setting */ 18336ab6bfe3SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK; 18346ab6bfe3SJack F Vogel 18356ab6bfe3SJack F Vogel if (hw->phy.media_type == e1000_media_type_copper) 18366ab6bfe3SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII; 18374dab5c37SJack F Vogel else 18386ab6bfe3SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES; 18396ab6bfe3SJack F Vogel 18406ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 18416ab6bfe3SJack F Vogel 18426ab6bfe3SJack F Vogel break; 18434dab5c37SJack F Vogel } 18444dab5c37SJack F Vogel 18454dab5c37SJack F Vogel return ret_val; 18464dab5c37SJack F Vogel } 18474dab5c37SJack F Vogel 18484dab5c37SJack F Vogel /** 18494dab5c37SJack F Vogel * e1000_set_sfp_media_type_82575 - derives SFP module media type. 18504dab5c37SJack F Vogel * @hw: pointer to the HW structure 18514dab5c37SJack F Vogel * 18524dab5c37SJack F Vogel * The media type is chosen based on SFP module. 18534dab5c37SJack F Vogel * compatibility flags retrieved from SFP ID EEPROM. 18544dab5c37SJack F Vogel **/ 18554dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw) 18564dab5c37SJack F Vogel { 18574dab5c37SJack F Vogel s32 ret_val = E1000_ERR_CONFIG; 18584dab5c37SJack F Vogel u32 ctrl_ext = 0; 18594dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 18606ab6bfe3SJack F Vogel struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags; 18614dab5c37SJack F Vogel u8 tranceiver_type = 0; 18626ab6bfe3SJack F Vogel s32 timeout = 3; 18634dab5c37SJack F Vogel 18646ab6bfe3SJack F Vogel /* Turn I2C interface ON and power on sfp cage */ 18654dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 18666ab6bfe3SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA; 18674dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA); 18684dab5c37SJack F Vogel 18696ab6bfe3SJack F Vogel E1000_WRITE_FLUSH(hw); 18706ab6bfe3SJack F Vogel 18714dab5c37SJack F Vogel /* Read SFP module data */ 18726ab6bfe3SJack F Vogel while (timeout) { 18734dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw, 18744dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET), 18754dab5c37SJack F Vogel &tranceiver_type); 18766ab6bfe3SJack F Vogel if (ret_val == E1000_SUCCESS) 18776ab6bfe3SJack F Vogel break; 18786ab6bfe3SJack F Vogel msec_delay(100); 18796ab6bfe3SJack F Vogel timeout--; 18806ab6bfe3SJack F Vogel } 18814dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS) 18824dab5c37SJack F Vogel goto out; 18836ab6bfe3SJack F Vogel 18844dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw, 18854dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET), 18866ab6bfe3SJack F Vogel (u8 *)eth_flags); 18874dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS) 18884dab5c37SJack F Vogel goto out; 18896ab6bfe3SJack F Vogel 18906ab6bfe3SJack F Vogel /* Check if there is some SFP module plugged and powered */ 18914dab5c37SJack F Vogel if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) || 18924dab5c37SJack F Vogel (tranceiver_type == E1000_SFF_IDENTIFIER_SFF)) { 18934dab5c37SJack F Vogel dev_spec->module_plugged = TRUE; 18946ab6bfe3SJack F Vogel if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) { 18954dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 18966ab6bfe3SJack F Vogel } else if (eth_flags->e100_base_fx) { 18976ab6bfe3SJack F Vogel dev_spec->sgmii_active = TRUE; 18986ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes; 18996ab6bfe3SJack F Vogel } else if (eth_flags->e1000_base_t) { 19004dab5c37SJack F Vogel dev_spec->sgmii_active = TRUE; 19014dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper; 19024dab5c37SJack F Vogel } else { 19034dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_unknown; 19044dab5c37SJack F Vogel DEBUGOUT("PHY module has not been recognized\n"); 19054dab5c37SJack F Vogel goto out; 19064dab5c37SJack F Vogel } 19074dab5c37SJack F Vogel } else { 19084dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_unknown; 19094dab5c37SJack F Vogel } 19104dab5c37SJack F Vogel ret_val = E1000_SUCCESS; 19114dab5c37SJack F Vogel out: 19124dab5c37SJack F Vogel /* Restore I2C interface setting */ 19134dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 19144dab5c37SJack F Vogel return ret_val; 19158cfa0ad2SJack F Vogel } 19168cfa0ad2SJack F Vogel 19178cfa0ad2SJack F Vogel /** 19188cfa0ad2SJack F Vogel * e1000_valid_led_default_82575 - Verify a valid default LED config 19198cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19208cfa0ad2SJack F Vogel * @data: pointer to the NVM (EEPROM) 19218cfa0ad2SJack F Vogel * 19228cfa0ad2SJack F Vogel * Read the EEPROM for the current default LED configuration. If the 19238cfa0ad2SJack F Vogel * LED configuration is not valid, set to a valid LED configuration. 19248cfa0ad2SJack F Vogel **/ 19258cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data) 19268cfa0ad2SJack F Vogel { 19278cfa0ad2SJack F Vogel s32 ret_val; 19288cfa0ad2SJack F Vogel 19298cfa0ad2SJack F Vogel DEBUGFUNC("e1000_valid_led_default_82575"); 19308cfa0ad2SJack F Vogel 19318cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data); 19328cfa0ad2SJack F Vogel if (ret_val) { 19338cfa0ad2SJack F Vogel DEBUGOUT("NVM Read Error\n"); 19348cfa0ad2SJack F Vogel goto out; 19358cfa0ad2SJack F Vogel } 19368cfa0ad2SJack F Vogel 19378cfa0ad2SJack F Vogel if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) { 19388cfa0ad2SJack F Vogel switch (hw->phy.media_type) { 19398cfa0ad2SJack F Vogel case e1000_media_type_internal_serdes: 19408cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT_82575_SERDES; 19418cfa0ad2SJack F Vogel break; 19428cfa0ad2SJack F Vogel case e1000_media_type_copper: 19438cfa0ad2SJack F Vogel default: 19448cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT; 19458cfa0ad2SJack F Vogel break; 19468cfa0ad2SJack F Vogel } 19478cfa0ad2SJack F Vogel } 19488cfa0ad2SJack F Vogel out: 19498cfa0ad2SJack F Vogel return ret_val; 19508cfa0ad2SJack F Vogel } 19518cfa0ad2SJack F Vogel 19528cfa0ad2SJack F Vogel /** 19538cfa0ad2SJack F Vogel * e1000_sgmii_active_82575 - Return sgmii state 19548cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19558cfa0ad2SJack F Vogel * 19568cfa0ad2SJack F Vogel * 82575 silicon has a serialized gigabit media independent interface (sgmii) 19578cfa0ad2SJack F Vogel * which can be enabled for use in the embedded applications. Simply 19588cfa0ad2SJack F Vogel * return the current state of the sgmii interface. 19598cfa0ad2SJack F Vogel **/ 19608cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw) 19618cfa0ad2SJack F Vogel { 1962daf9197cSJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575; 1963daf9197cSJack F Vogel return dev_spec->sgmii_active; 19648cfa0ad2SJack F Vogel } 19658cfa0ad2SJack F Vogel 19668cfa0ad2SJack F Vogel /** 19678cfa0ad2SJack F Vogel * e1000_reset_init_script_82575 - Inits HW defaults after reset 19688cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 19698cfa0ad2SJack F Vogel * 19708cfa0ad2SJack F Vogel * Inits recommended HW defaults after a reset when there is no EEPROM 19718cfa0ad2SJack F Vogel * detected. This is only for the 82575. 19728cfa0ad2SJack F Vogel **/ 19738cfa0ad2SJack F Vogel static s32 e1000_reset_init_script_82575(struct e1000_hw *hw) 19748cfa0ad2SJack F Vogel { 19758cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_init_script_82575"); 19768cfa0ad2SJack F Vogel 19778cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82575) { 19788cfa0ad2SJack F Vogel DEBUGOUT("Running reset init script for 82575\n"); 19798cfa0ad2SJack F Vogel /* SerDes configuration via SERDESCTRL */ 19808cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C); 19818cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78); 19828cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23); 19838cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15); 19848cfa0ad2SJack F Vogel 19858cfa0ad2SJack F Vogel /* CCM configuration via CCMCTL register */ 19868cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00); 19878cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00); 19888cfa0ad2SJack F Vogel 19898cfa0ad2SJack F Vogel /* PCIe lanes configuration */ 19908cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC); 19918cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF); 19928cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05); 19938cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81); 19948cfa0ad2SJack F Vogel 19958cfa0ad2SJack F Vogel /* PCIe PLL Configuration */ 19968cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47); 19978cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00); 19988cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00); 19998cfa0ad2SJack F Vogel } 20008cfa0ad2SJack F Vogel 20018cfa0ad2SJack F Vogel return E1000_SUCCESS; 20028cfa0ad2SJack F Vogel } 20038cfa0ad2SJack F Vogel 20048cfa0ad2SJack F Vogel /** 20058cfa0ad2SJack F Vogel * e1000_read_mac_addr_82575 - Read device MAC address 20068cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 20078cfa0ad2SJack F Vogel **/ 20088cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw) 20098cfa0ad2SJack F Vogel { 20108cc64f1eSJack F Vogel s32 ret_val; 20118cfa0ad2SJack F Vogel 20128cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_mac_addr_82575"); 2013d035aa2dSJack F Vogel 2014d035aa2dSJack F Vogel /* 2015d035aa2dSJack F Vogel * If there's an alternate MAC address place it in RAR0 2016d035aa2dSJack F Vogel * so that it will override the Si installed default perm 2017d035aa2dSJack F Vogel * address. 2018d035aa2dSJack F Vogel */ 2019d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 2020d035aa2dSJack F Vogel if (ret_val) 2021d035aa2dSJack F Vogel goto out; 2022d035aa2dSJack F Vogel 20238cfa0ad2SJack F Vogel ret_val = e1000_read_mac_addr_generic(hw); 20248cfa0ad2SJack F Vogel 2025d035aa2dSJack F Vogel out: 20268cfa0ad2SJack F Vogel return ret_val; 20278cfa0ad2SJack F Vogel } 20288cfa0ad2SJack F Vogel 20298cfa0ad2SJack F Vogel /** 2030a69ed8dfSJack F Vogel * e1000_config_collision_dist_82575 - Configure collision distance 2031a69ed8dfSJack F Vogel * @hw: pointer to the HW structure 2032a69ed8dfSJack F Vogel * 2033a69ed8dfSJack F Vogel * Configures the collision distance to the default value and is used 2034a69ed8dfSJack F Vogel * during link setup. 2035a69ed8dfSJack F Vogel **/ 2036a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw) 2037a69ed8dfSJack F Vogel { 2038a69ed8dfSJack F Vogel u32 tctl_ext; 2039a69ed8dfSJack F Vogel 2040a69ed8dfSJack F Vogel DEBUGFUNC("e1000_config_collision_dist_82575"); 2041a69ed8dfSJack F Vogel 2042a69ed8dfSJack F Vogel tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT); 2043a69ed8dfSJack F Vogel 2044a69ed8dfSJack F Vogel tctl_ext &= ~E1000_TCTL_EXT_COLD; 2045a69ed8dfSJack F Vogel tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT; 2046a69ed8dfSJack F Vogel 2047a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext); 2048a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw); 2049a69ed8dfSJack F Vogel } 2050a69ed8dfSJack F Vogel 2051a69ed8dfSJack F Vogel /** 20528cfa0ad2SJack F Vogel * e1000_power_down_phy_copper_82575 - Remove link during PHY power down 20538cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 20548cfa0ad2SJack F Vogel * 20558cfa0ad2SJack F Vogel * In the case of a PHY power down to save power, or to turn off link during a 20568cfa0ad2SJack F Vogel * driver unload, or wake on lan is not enabled, remove the link. 20578cfa0ad2SJack F Vogel **/ 20588cfa0ad2SJack F Vogel static void e1000_power_down_phy_copper_82575(struct e1000_hw *hw) 20598cfa0ad2SJack F Vogel { 20608cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy; 20618cfa0ad2SJack F Vogel 20628cfa0ad2SJack F Vogel if (!(phy->ops.check_reset_block)) 20638cfa0ad2SJack F Vogel return; 20648cfa0ad2SJack F Vogel 20658cfa0ad2SJack F Vogel /* If the management interface is not enabled, then power down */ 20668ec87fc5SJack F Vogel if (!(e1000_enable_mng_pass_thru(hw) || phy->ops.check_reset_block(hw))) 20678cfa0ad2SJack F Vogel e1000_power_down_phy_copper(hw); 20688cfa0ad2SJack F Vogel 20698cfa0ad2SJack F Vogel return; 20708cfa0ad2SJack F Vogel } 20718cfa0ad2SJack F Vogel 20728cfa0ad2SJack F Vogel /** 20738cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters 20748cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 20758cfa0ad2SJack F Vogel * 20768cfa0ad2SJack F Vogel * Clears the hardware counters by reading the counter registers. 20778cfa0ad2SJack F Vogel **/ 20788cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw) 20798cfa0ad2SJack F Vogel { 20808cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_82575"); 20818cfa0ad2SJack F Vogel 20828cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw); 20838cfa0ad2SJack F Vogel 2084daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC64); 2085daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC127); 2086daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC255); 2087daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC511); 2088daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1023); 2089daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1522); 2090daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC64); 2091daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC127); 2092daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC255); 2093daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC511); 2094daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1023); 2095daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1522); 20968cfa0ad2SJack F Vogel 2097daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ALGNERRC); 2098daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RXERRC); 2099daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TNCRS); 2100daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CEXTERR); 2101daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTC); 2102daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTFC); 21038cfa0ad2SJack F Vogel 2104daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPRC); 2105daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPDC); 2106daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPTC); 21078cfa0ad2SJack F Vogel 2108daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_IAC); 2109daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXOC); 21108cfa0ad2SJack F Vogel 2111daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXPTC); 2112daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXATC); 2113daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXPTC); 2114daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXATC); 2115daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQEC); 2116daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQMTC); 2117daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXDMTC); 21188cfa0ad2SJack F Vogel 2119daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBTMPC); 2120daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTDPMC); 2121daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBRMPC); 2122daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RPTHC); 2123daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGPTC); 2124daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTCBDPC); 2125daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCL); 2126daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCH); 2127daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCL); 2128daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCH); 2129daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_LENERRS); 21308cfa0ad2SJack F Vogel 21318cfa0ad2SJack F Vogel /* This register should not be read in copper configurations */ 21324edd8523SJack F Vogel if ((hw->phy.media_type == e1000_media_type_internal_serdes) || 21334edd8523SJack F Vogel e1000_sgmii_active_82575(hw)) 2134daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_SCVPC); 21358cfa0ad2SJack F Vogel } 21369d81738fSJack F Vogel 21378cfa0ad2SJack F Vogel /** 2138f0ecc46dSJack F Vogel * e1000_rx_fifo_flush_82575 - Clean rx fifo after Rx enable 21398cfa0ad2SJack F Vogel * @hw: pointer to the HW structure 21408cfa0ad2SJack F Vogel * 214148600901SSean Bruno * After Rx enable, if manageability is enabled then there is likely some 21428cfa0ad2SJack F Vogel * bad data at the start of the fifo and possibly in the DMA fifo. This 21438cfa0ad2SJack F Vogel * function clears the fifos and flushes any packets that came in as rx was 21448cfa0ad2SJack F Vogel * being enabled. 21458cfa0ad2SJack F Vogel **/ 21468cfa0ad2SJack F Vogel void e1000_rx_fifo_flush_82575(struct e1000_hw *hw) 21478cfa0ad2SJack F Vogel { 21488cfa0ad2SJack F Vogel u32 rctl, rlpml, rxdctl[4], rfctl, temp_rctl, rx_enabled; 21498cfa0ad2SJack F Vogel int i, ms_wait; 21508cfa0ad2SJack F Vogel 2151c80429ceSEric Joyner DEBUGFUNC("e1000_rx_fifo_flush_82575"); 2152c80429ceSEric Joyner 2153c80429ceSEric Joyner /* disable IPv6 options as per hardware errata */ 2154c80429ceSEric Joyner rfctl = E1000_READ_REG(hw, E1000_RFCTL); 2155c80429ceSEric Joyner rfctl |= E1000_RFCTL_IPV6_EX_DIS; 2156c80429ceSEric Joyner E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); 2157c80429ceSEric Joyner 21588cfa0ad2SJack F Vogel if (hw->mac.type != e1000_82575 || 21598cfa0ad2SJack F Vogel !(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_RCV_TCO_EN)) 21608cfa0ad2SJack F Vogel return; 21618cfa0ad2SJack F Vogel 2162f0ecc46dSJack F Vogel /* Disable all Rx queues */ 21638cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) { 21648cfa0ad2SJack F Vogel rxdctl[i] = E1000_READ_REG(hw, E1000_RXDCTL(i)); 21658cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RXDCTL(i), 21668cfa0ad2SJack F Vogel rxdctl[i] & ~E1000_RXDCTL_QUEUE_ENABLE); 21678cfa0ad2SJack F Vogel } 21688cfa0ad2SJack F Vogel /* Poll all queues to verify they have shut down */ 21698cfa0ad2SJack F Vogel for (ms_wait = 0; ms_wait < 10; ms_wait++) { 21708cfa0ad2SJack F Vogel msec_delay(1); 21718cfa0ad2SJack F Vogel rx_enabled = 0; 21728cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) 21738cfa0ad2SJack F Vogel rx_enabled |= E1000_READ_REG(hw, E1000_RXDCTL(i)); 21748cfa0ad2SJack F Vogel if (!(rx_enabled & E1000_RXDCTL_QUEUE_ENABLE)) 21758cfa0ad2SJack F Vogel break; 21768cfa0ad2SJack F Vogel } 21778cfa0ad2SJack F Vogel 21788cfa0ad2SJack F Vogel if (ms_wait == 10) 21798cfa0ad2SJack F Vogel DEBUGOUT("Queue disable timed out after 10ms\n"); 21808cfa0ad2SJack F Vogel 21818cfa0ad2SJack F Vogel /* Clear RLPML, RCTL.SBP, RFCTL.LEF, and set RCTL.LPE so that all 21828cfa0ad2SJack F Vogel * incoming packets are rejected. Set enable and wait 2ms so that 21838cfa0ad2SJack F Vogel * any packet that was coming in as RCTL.EN was set is flushed 21848cfa0ad2SJack F Vogel */ 21858cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, rfctl & ~E1000_RFCTL_LEF); 21868cfa0ad2SJack F Vogel 21878cfa0ad2SJack F Vogel rlpml = E1000_READ_REG(hw, E1000_RLPML); 21888cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RLPML, 0); 21898cfa0ad2SJack F Vogel 21908cfa0ad2SJack F Vogel rctl = E1000_READ_REG(hw, E1000_RCTL); 21918cfa0ad2SJack F Vogel temp_rctl = rctl & ~(E1000_RCTL_EN | E1000_RCTL_SBP); 21928cfa0ad2SJack F Vogel temp_rctl |= E1000_RCTL_LPE; 21938cfa0ad2SJack F Vogel 21948cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl); 21958cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, temp_rctl | E1000_RCTL_EN); 21968cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 21978cfa0ad2SJack F Vogel msec_delay(2); 21988cfa0ad2SJack F Vogel 2199f0ecc46dSJack F Vogel /* Enable Rx queues that were previously enabled and restore our 22008cfa0ad2SJack F Vogel * previous state 22018cfa0ad2SJack F Vogel */ 22028cfa0ad2SJack F Vogel for (i = 0; i < 4; i++) 22038cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RXDCTL(i), rxdctl[i]); 22048cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, rctl); 22058cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw); 22068cfa0ad2SJack F Vogel 22078cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RLPML, rlpml); 22088cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RFCTL, rfctl); 22098cfa0ad2SJack F Vogel 22108cfa0ad2SJack F Vogel /* Flush receive errors generated by workaround */ 22118cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_ROC); 22128cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_RNBC); 22138cfa0ad2SJack F Vogel E1000_READ_REG(hw, E1000_MPC); 22148cfa0ad2SJack F Vogel } 2215daf9197cSJack F Vogel 22169d81738fSJack F Vogel /** 22179d81738fSJack F Vogel * e1000_set_pcie_completion_timeout - set pci-e completion timeout 22189d81738fSJack F Vogel * @hw: pointer to the HW structure 22199d81738fSJack F Vogel * 22209d81738fSJack F Vogel * The defaults for 82575 and 82576 should be in the range of 50us to 50ms, 22219d81738fSJack F Vogel * however the hardware default for these parts is 500us to 1ms which is less 22229d81738fSJack F Vogel * than the 10ms recommended by the pci-e spec. To address this we need to 22239d81738fSJack F Vogel * increase the value to either 10ms to 200ms for capability version 1 config, 22249d81738fSJack F Vogel * or 16ms to 55ms for version 2. 22259d81738fSJack F Vogel **/ 22269d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw) 22279d81738fSJack F Vogel { 22289d81738fSJack F Vogel u32 gcr = E1000_READ_REG(hw, E1000_GCR); 22299d81738fSJack F Vogel s32 ret_val = E1000_SUCCESS; 22309d81738fSJack F Vogel u16 pcie_devctl2; 22319d81738fSJack F Vogel 22329d81738fSJack F Vogel /* only take action if timeout value is defaulted to 0 */ 22339d81738fSJack F Vogel if (gcr & E1000_GCR_CMPL_TMOUT_MASK) 22349d81738fSJack F Vogel goto out; 22359d81738fSJack F Vogel 22369d81738fSJack F Vogel /* 22379d81738fSJack F Vogel * if capababilities version is type 1 we can write the 22389d81738fSJack F Vogel * timeout of 10ms to 200ms through the GCR register 22399d81738fSJack F Vogel */ 22409d81738fSJack F Vogel if (!(gcr & E1000_GCR_CAP_VER2)) { 22419d81738fSJack F Vogel gcr |= E1000_GCR_CMPL_TMOUT_10ms; 22429d81738fSJack F Vogel goto out; 22439d81738fSJack F Vogel } 22449d81738fSJack F Vogel 22459d81738fSJack F Vogel /* 22469d81738fSJack F Vogel * for version 2 capabilities we need to write the config space 22479d81738fSJack F Vogel * directly in order to set the completion timeout value for 22489d81738fSJack F Vogel * 16ms to 55ms 22499d81738fSJack F Vogel */ 22509d81738fSJack F Vogel ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 22519d81738fSJack F Vogel &pcie_devctl2); 22529d81738fSJack F Vogel if (ret_val) 22539d81738fSJack F Vogel goto out; 22549d81738fSJack F Vogel 22559d81738fSJack F Vogel pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms; 22569d81738fSJack F Vogel 22579d81738fSJack F Vogel ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2, 22589d81738fSJack F Vogel &pcie_devctl2); 22599d81738fSJack F Vogel out: 22609d81738fSJack F Vogel /* disable completion timeout resend */ 22619d81738fSJack F Vogel gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND; 22629d81738fSJack F Vogel 22639d81738fSJack F Vogel E1000_WRITE_REG(hw, E1000_GCR, gcr); 22649d81738fSJack F Vogel return ret_val; 22659d81738fSJack F Vogel } 22669d81738fSJack F Vogel 22677d9119bdSJack F Vogel /** 22687d9119bdSJack F Vogel * e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing 22697d9119bdSJack F Vogel * @hw: pointer to the hardware struct 22707d9119bdSJack F Vogel * @enable: state to enter, either enabled or disabled 22717d9119bdSJack F Vogel * @pf: Physical Function pool - do not set anti-spoofing for the PF 22727d9119bdSJack F Vogel * 22737d9119bdSJack F Vogel * enables/disables L2 switch anti-spoofing functionality. 22747d9119bdSJack F Vogel **/ 22757d9119bdSJack F Vogel void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf) 22767d9119bdSJack F Vogel { 22777609433eSJack F Vogel u32 reg_val, reg_offset; 22787d9119bdSJack F Vogel 22797d9119bdSJack F Vogel switch (hw->mac.type) { 22807d9119bdSJack F Vogel case e1000_82576: 22817609433eSJack F Vogel reg_offset = E1000_DTXSWC; 22827d9119bdSJack F Vogel break; 22834dab5c37SJack F Vogel case e1000_i350: 22847609433eSJack F Vogel case e1000_i354: 22857609433eSJack F Vogel reg_offset = E1000_TXSWC; 22867609433eSJack F Vogel break; 22877609433eSJack F Vogel default: 22887609433eSJack F Vogel return; 22897609433eSJack F Vogel } 22907609433eSJack F Vogel 22917609433eSJack F Vogel reg_val = E1000_READ_REG(hw, reg_offset); 22924dab5c37SJack F Vogel if (enable) { 22937609433eSJack F Vogel reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK | 22944dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 22954dab5c37SJack F Vogel /* The PF can spoof - it has to in order to 22964dab5c37SJack F Vogel * support emulation mode NICs 22974dab5c37SJack F Vogel */ 22987609433eSJack F Vogel reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS)); 22994dab5c37SJack F Vogel } else { 23007609433eSJack F Vogel reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK | 23014dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK); 23024dab5c37SJack F Vogel } 23037609433eSJack F Vogel E1000_WRITE_REG(hw, reg_offset, reg_val); 23047d9119bdSJack F Vogel } 23057d9119bdSJack F Vogel 23064edd8523SJack F Vogel /** 23074edd8523SJack F Vogel * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback 23084edd8523SJack F Vogel * @hw: pointer to the hardware struct 23094edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled 23104edd8523SJack F Vogel * 23114edd8523SJack F Vogel * enables/disables L2 switch loopback functionality. 23124edd8523SJack F Vogel **/ 23134edd8523SJack F Vogel void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable) 23144edd8523SJack F Vogel { 23158ec87fc5SJack F Vogel u32 dtxswc; 23164edd8523SJack F Vogel 23178ec87fc5SJack F Vogel switch (hw->mac.type) { 23188ec87fc5SJack F Vogel case e1000_82576: 23198ec87fc5SJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_DTXSWC); 23204edd8523SJack F Vogel if (enable) 23214edd8523SJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 23224edd8523SJack F Vogel else 23234edd8523SJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 23244edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc); 23258ec87fc5SJack F Vogel break; 2326f0ecc46dSJack F Vogel case e1000_i350: 23277609433eSJack F Vogel case e1000_i354: 2328f0ecc46dSJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_TXSWC); 2329f0ecc46dSJack F Vogel if (enable) 2330f0ecc46dSJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN; 2331f0ecc46dSJack F Vogel else 2332f0ecc46dSJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN; 2333f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc); 2334f0ecc46dSJack F Vogel break; 23358ec87fc5SJack F Vogel default: 23368ec87fc5SJack F Vogel /* Currently no other hardware supports loopback */ 23378ec87fc5SJack F Vogel break; 23388ec87fc5SJack F Vogel } 23398ec87fc5SJack F Vogel 23408ec87fc5SJack F Vogel 23414edd8523SJack F Vogel } 23424edd8523SJack F Vogel 23434edd8523SJack F Vogel /** 23444edd8523SJack F Vogel * e1000_vmdq_set_replication_pf - enable or disable vmdq replication 23454edd8523SJack F Vogel * @hw: pointer to the hardware struct 23464edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled 23474edd8523SJack F Vogel * 23484edd8523SJack F Vogel * enables/disables replication of packets across multiple pools. 23494edd8523SJack F Vogel **/ 23504edd8523SJack F Vogel void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable) 23514edd8523SJack F Vogel { 23524edd8523SJack F Vogel u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL); 23534edd8523SJack F Vogel 23544edd8523SJack F Vogel if (enable) 23554edd8523SJack F Vogel vt_ctl |= E1000_VT_CTL_VM_REPL_EN; 23564edd8523SJack F Vogel else 23574edd8523SJack F Vogel vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN; 23584edd8523SJack F Vogel 23594edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl); 23604edd8523SJack F Vogel } 23614edd8523SJack F Vogel 23624edd8523SJack F Vogel /** 23634edd8523SJack F Vogel * e1000_read_phy_reg_82580 - Read 82580 MDI control register 23644edd8523SJack F Vogel * @hw: pointer to the HW structure 23654edd8523SJack F Vogel * @offset: register offset to be read 23664edd8523SJack F Vogel * @data: pointer to the read data 23674edd8523SJack F Vogel * 23684edd8523SJack F Vogel * Reads the MDI control register in the PHY at offset and stores the 23694edd8523SJack F Vogel * information read to data. 23704edd8523SJack F Vogel **/ 23714edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data) 23724edd8523SJack F Vogel { 23734edd8523SJack F Vogel s32 ret_val; 23744edd8523SJack F Vogel 23754edd8523SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_82580"); 23764edd8523SJack F Vogel 23774edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 23784edd8523SJack F Vogel if (ret_val) 23794edd8523SJack F Vogel goto out; 23804edd8523SJack F Vogel 23814edd8523SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw, offset, data); 23824edd8523SJack F Vogel 23834edd8523SJack F Vogel hw->phy.ops.release(hw); 23844edd8523SJack F Vogel 23854edd8523SJack F Vogel out: 23864edd8523SJack F Vogel return ret_val; 23874edd8523SJack F Vogel } 23884edd8523SJack F Vogel 23894edd8523SJack F Vogel /** 23904edd8523SJack F Vogel * e1000_write_phy_reg_82580 - Write 82580 MDI control register 23914edd8523SJack F Vogel * @hw: pointer to the HW structure 23924edd8523SJack F Vogel * @offset: register offset to write to 23934edd8523SJack F Vogel * @data: data to write to register at offset 23944edd8523SJack F Vogel * 23954edd8523SJack F Vogel * Writes data to MDI control register in the PHY at offset. 23964edd8523SJack F Vogel **/ 23974edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data) 23984edd8523SJack F Vogel { 23994edd8523SJack F Vogel s32 ret_val; 24004edd8523SJack F Vogel 24014edd8523SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_82580"); 24024edd8523SJack F Vogel 24034edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw); 24044edd8523SJack F Vogel if (ret_val) 24054edd8523SJack F Vogel goto out; 24064edd8523SJack F Vogel 24074edd8523SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw, offset, data); 24084edd8523SJack F Vogel 24094edd8523SJack F Vogel hw->phy.ops.release(hw); 24104edd8523SJack F Vogel 24114edd8523SJack F Vogel out: 24124edd8523SJack F Vogel return ret_val; 24134edd8523SJack F Vogel } 2414a69ed8dfSJack F Vogel 24154edd8523SJack F Vogel /** 24167d9119bdSJack F Vogel * e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits 24177d9119bdSJack F Vogel * @hw: pointer to the HW structure 24187d9119bdSJack F Vogel * 2419*cef367e6SEitan Adler * This resets the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on 24207d9119bdSJack F Vogel * the values found in the EEPROM. This addresses an issue in which these 24217d9119bdSJack F Vogel * bits are not restored from EEPROM after reset. 24227d9119bdSJack F Vogel **/ 24237d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw) 24247d9119bdSJack F Vogel { 24257d9119bdSJack F Vogel s32 ret_val = E1000_SUCCESS; 24267d9119bdSJack F Vogel u32 mdicnfg; 2427f0ecc46dSJack F Vogel u16 nvm_data = 0; 24287d9119bdSJack F Vogel 24297d9119bdSJack F Vogel DEBUGFUNC("e1000_reset_mdicnfg_82580"); 24307d9119bdSJack F Vogel 24317d9119bdSJack F Vogel if (hw->mac.type != e1000_82580) 24327d9119bdSJack F Vogel goto out; 24337d9119bdSJack F Vogel if (!e1000_sgmii_active_82575(hw)) 24347d9119bdSJack F Vogel goto out; 24357d9119bdSJack F Vogel 24367d9119bdSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A + 24377d9119bdSJack F Vogel NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1, 24387d9119bdSJack F Vogel &nvm_data); 24397d9119bdSJack F Vogel if (ret_val) { 24407d9119bdSJack F Vogel DEBUGOUT("NVM Read Error\n"); 24417d9119bdSJack F Vogel goto out; 24427d9119bdSJack F Vogel } 24437d9119bdSJack F Vogel 24447d9119bdSJack F Vogel mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG); 24457d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_EXT_MDIO) 24467d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_EXT_MDIO; 24477d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_COM_MDIO) 24487d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_COM_MDIO; 24497d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg); 24507d9119bdSJack F Vogel out: 24517d9119bdSJack F Vogel return ret_val; 24527d9119bdSJack F Vogel } 24537d9119bdSJack F Vogel 24547d9119bdSJack F Vogel /** 24554edd8523SJack F Vogel * e1000_reset_hw_82580 - Reset hardware 24564edd8523SJack F Vogel * @hw: pointer to the HW structure 24574edd8523SJack F Vogel * 24584edd8523SJack F Vogel * This resets function or entire device (all ports, etc.) 24594edd8523SJack F Vogel * to a known state. 24604edd8523SJack F Vogel **/ 24614edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw) 24624edd8523SJack F Vogel { 24634edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS; 24644edd8523SJack F Vogel /* BH SW mailbox bit in SW_FW_SYNC */ 24654edd8523SJack F Vogel u16 swmbsw_mask = E1000_SW_SYNCH_MB; 2466f0ecc46dSJack F Vogel u32 ctrl; 24674edd8523SJack F Vogel bool global_device_reset = hw->dev_spec._82575.global_device_reset; 24684edd8523SJack F Vogel 24694edd8523SJack F Vogel DEBUGFUNC("e1000_reset_hw_82580"); 24704edd8523SJack F Vogel 24714edd8523SJack F Vogel hw->dev_spec._82575.global_device_reset = FALSE; 24724edd8523SJack F Vogel 24736ab6bfe3SJack F Vogel /* 82580 does not reliably do global_device_reset due to hw errata */ 24746ab6bfe3SJack F Vogel if (hw->mac.type == e1000_82580) 24756ab6bfe3SJack F Vogel global_device_reset = FALSE; 24766ab6bfe3SJack F Vogel 24774edd8523SJack F Vogel /* Get current control state. */ 24784edd8523SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL); 24794edd8523SJack F Vogel 24804edd8523SJack F Vogel /* 24814edd8523SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection 24824edd8523SJack F Vogel * on the last TLP read/write transaction when MAC is reset. 24834edd8523SJack F Vogel */ 24844edd8523SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw); 24854edd8523SJack F Vogel if (ret_val) 24864edd8523SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n"); 24874edd8523SJack F Vogel 24884edd8523SJack F Vogel DEBUGOUT("Masking off all interrupts\n"); 24894edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 24904edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0); 24914edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP); 24924edd8523SJack F Vogel E1000_WRITE_FLUSH(hw); 24934edd8523SJack F Vogel 24944edd8523SJack F Vogel msec_delay(10); 24954edd8523SJack F Vogel 24964edd8523SJack F Vogel /* Determine whether or not a global dev reset is requested */ 2497ab5d0362SJack F Vogel if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw, 24984dab5c37SJack F Vogel swmbsw_mask)) 24994edd8523SJack F Vogel global_device_reset = FALSE; 25004edd8523SJack F Vogel 25014dab5c37SJack F Vogel if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) & 25024dab5c37SJack F Vogel E1000_STAT_DEV_RST_SET)) 25034edd8523SJack F Vogel ctrl |= E1000_CTRL_DEV_RST; 25044edd8523SJack F Vogel else 25054edd8523SJack F Vogel ctrl |= E1000_CTRL_RST; 25064edd8523SJack F Vogel 25074edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 25084edd8523SJack F Vogel 25098cc64f1eSJack F Vogel switch (hw->device_id) { 25108cc64f1eSJack F Vogel case E1000_DEV_ID_DH89XXCC_SGMII: 25118cc64f1eSJack F Vogel break; 25128cc64f1eSJack F Vogel default: 25138cc64f1eSJack F Vogel E1000_WRITE_FLUSH(hw); 25148cc64f1eSJack F Vogel break; 25158cc64f1eSJack F Vogel } 25168cc64f1eSJack F Vogel 25178cc64f1eSJack F Vogel /* Add delay to insure DEV_RST or RST has time to complete */ 25184edd8523SJack F Vogel msec_delay(5); 25194edd8523SJack F Vogel 25204edd8523SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw); 25214edd8523SJack F Vogel if (ret_val) { 25224edd8523SJack F Vogel /* 25234edd8523SJack F Vogel * When auto config read does not complete, do not 25244edd8523SJack F Vogel * return with an error. This can happen in situations 25254edd8523SJack F Vogel * where there is no eeprom and prevents getting link. 25264edd8523SJack F Vogel */ 25274edd8523SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n"); 25284edd8523SJack F Vogel } 25294edd8523SJack F Vogel 25304edd8523SJack F Vogel /* clear global device reset status bit */ 25314edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET); 25324edd8523SJack F Vogel 25334edd8523SJack F Vogel /* Clear any pending interrupt events. */ 25344edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff); 2535f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR); 25364edd8523SJack F Vogel 25377d9119bdSJack F Vogel ret_val = e1000_reset_mdicnfg_82580(hw); 25387d9119bdSJack F Vogel if (ret_val) 25397d9119bdSJack F Vogel DEBUGOUT("Could not reset MDICNFG based on EEPROM\n"); 25407d9119bdSJack F Vogel 25414edd8523SJack F Vogel /* Install any alternate MAC address into RAR0 */ 25424edd8523SJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw); 25434edd8523SJack F Vogel 25444edd8523SJack F Vogel /* Release semaphore */ 25454edd8523SJack F Vogel if (global_device_reset) 2546ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swmbsw_mask); 25474edd8523SJack F Vogel 25484edd8523SJack F Vogel return ret_val; 25494edd8523SJack F Vogel } 25504edd8523SJack F Vogel 25514edd8523SJack F Vogel /** 2552f0ecc46dSJack F Vogel * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size 25534edd8523SJack F Vogel * @data: data received by reading RXPBS register 25544edd8523SJack F Vogel * 25554edd8523SJack F Vogel * The 82580 uses a table based approach for packet buffer allocation sizes. 25564edd8523SJack F Vogel * This function converts the retrieved value into the correct table value 25574edd8523SJack F Vogel * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7 25584edd8523SJack F Vogel * 0x0 36 72 144 1 2 4 8 16 25594edd8523SJack F Vogel * 0x8 35 70 140 rsv rsv rsv rsv rsv 25604edd8523SJack F Vogel */ 25614edd8523SJack F Vogel u16 e1000_rxpbs_adjust_82580(u32 data) 25624edd8523SJack F Vogel { 25634edd8523SJack F Vogel u16 ret_val = 0; 25644edd8523SJack F Vogel 25654edd8523SJack F Vogel if (data < E1000_82580_RXPBS_TABLE_SIZE) 25664edd8523SJack F Vogel ret_val = e1000_82580_rxpbs_table[data]; 25674edd8523SJack F Vogel 25684edd8523SJack F Vogel return ret_val; 25694edd8523SJack F Vogel } 2570f0ecc46dSJack F Vogel 2571f0ecc46dSJack F Vogel /** 2572f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_with_offset - Validate EEPROM 2573f0ecc46dSJack F Vogel * checksum 2574f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2575f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region 2576f0ecc46dSJack F Vogel * 2577f0ecc46dSJack F Vogel * Calculates the EEPROM checksum by reading/adding each word of the EEPROM 2578f0ecc46dSJack F Vogel * and then verifies that the sum of the EEPROM is equal to 0xBABA. 2579f0ecc46dSJack F Vogel **/ 2580f0ecc46dSJack F Vogel s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) 2581f0ecc46dSJack F Vogel { 2582f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2583f0ecc46dSJack F Vogel u16 checksum = 0; 2584f0ecc46dSJack F Vogel u16 i, nvm_data; 2585f0ecc46dSJack F Vogel 2586f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_with_offset"); 2587f0ecc46dSJack F Vogel 2588f0ecc46dSJack F Vogel for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) { 2589f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 2590f0ecc46dSJack F Vogel if (ret_val) { 2591f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2592f0ecc46dSJack F Vogel goto out; 2593f0ecc46dSJack F Vogel } 2594f0ecc46dSJack F Vogel checksum += nvm_data; 2595f0ecc46dSJack F Vogel } 2596f0ecc46dSJack F Vogel 2597f0ecc46dSJack F Vogel if (checksum != (u16) NVM_SUM) { 2598f0ecc46dSJack F Vogel DEBUGOUT("NVM Checksum Invalid\n"); 2599f0ecc46dSJack F Vogel ret_val = -E1000_ERR_NVM; 2600f0ecc46dSJack F Vogel goto out; 2601f0ecc46dSJack F Vogel } 2602f0ecc46dSJack F Vogel 2603f0ecc46dSJack F Vogel out: 2604f0ecc46dSJack F Vogel return ret_val; 2605f0ecc46dSJack F Vogel } 2606f0ecc46dSJack F Vogel 2607f0ecc46dSJack F Vogel /** 2608f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_with_offset - Update EEPROM 2609f0ecc46dSJack F Vogel * checksum 2610f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2611f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region 2612f0ecc46dSJack F Vogel * 2613f0ecc46dSJack F Vogel * Updates the EEPROM checksum by reading/adding each word of the EEPROM 2614f0ecc46dSJack F Vogel * up to the checksum. Then calculates the EEPROM checksum and writes the 2615f0ecc46dSJack F Vogel * value to the EEPROM. 2616f0ecc46dSJack F Vogel **/ 2617f0ecc46dSJack F Vogel s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset) 2618f0ecc46dSJack F Vogel { 2619f0ecc46dSJack F Vogel s32 ret_val; 2620f0ecc46dSJack F Vogel u16 checksum = 0; 2621f0ecc46dSJack F Vogel u16 i, nvm_data; 2622f0ecc46dSJack F Vogel 2623f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_with_offset"); 2624f0ecc46dSJack F Vogel 2625f0ecc46dSJack F Vogel for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) { 2626f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data); 2627f0ecc46dSJack F Vogel if (ret_val) { 2628f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error while updating checksum.\n"); 2629f0ecc46dSJack F Vogel goto out; 2630f0ecc46dSJack F Vogel } 2631f0ecc46dSJack F Vogel checksum += nvm_data; 2632f0ecc46dSJack F Vogel } 2633f0ecc46dSJack F Vogel checksum = (u16) NVM_SUM - checksum; 2634f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1, 2635f0ecc46dSJack F Vogel &checksum); 2636f0ecc46dSJack F Vogel if (ret_val) 2637f0ecc46dSJack F Vogel DEBUGOUT("NVM Write Error while updating checksum.\n"); 2638f0ecc46dSJack F Vogel 2639f0ecc46dSJack F Vogel out: 2640f0ecc46dSJack F Vogel return ret_val; 2641f0ecc46dSJack F Vogel } 2642f0ecc46dSJack F Vogel 2643f0ecc46dSJack F Vogel /** 2644f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum 2645f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2646f0ecc46dSJack F Vogel * 2647f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of 2648f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is 2649f0ecc46dSJack F Vogel * equal to 0xBABA. 2650f0ecc46dSJack F Vogel **/ 2651f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw) 2652f0ecc46dSJack F Vogel { 26538cc64f1eSJack F Vogel s32 ret_val; 2654f0ecc46dSJack F Vogel u16 eeprom_regions_count = 1; 2655f0ecc46dSJack F Vogel u16 j, nvm_data; 2656f0ecc46dSJack F Vogel u16 nvm_offset; 2657f0ecc46dSJack F Vogel 2658f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_82580"); 2659f0ecc46dSJack F Vogel 2660f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 2661f0ecc46dSJack F Vogel if (ret_val) { 2662f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n"); 2663f0ecc46dSJack F Vogel goto out; 2664f0ecc46dSJack F Vogel } 2665f0ecc46dSJack F Vogel 2666f0ecc46dSJack F Vogel if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) { 2667f0ecc46dSJack F Vogel /* if chekcsums compatibility bit is set validate checksums 2668f0ecc46dSJack F Vogel * for all 4 ports. */ 2669f0ecc46dSJack F Vogel eeprom_regions_count = 4; 2670f0ecc46dSJack F Vogel } 2671f0ecc46dSJack F Vogel 2672f0ecc46dSJack F Vogel for (j = 0; j < eeprom_regions_count; j++) { 2673f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2674f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw, 2675f0ecc46dSJack F Vogel nvm_offset); 2676f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2677f0ecc46dSJack F Vogel goto out; 2678f0ecc46dSJack F Vogel } 2679f0ecc46dSJack F Vogel 2680f0ecc46dSJack F Vogel out: 2681f0ecc46dSJack F Vogel return ret_val; 2682f0ecc46dSJack F Vogel } 2683f0ecc46dSJack F Vogel 2684f0ecc46dSJack F Vogel /** 2685f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_82580 - Update EEPROM checksum 2686f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2687f0ecc46dSJack F Vogel * 2688f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding 2689f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM 2690f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM. 2691f0ecc46dSJack F Vogel **/ 2692f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw) 2693f0ecc46dSJack F Vogel { 2694f0ecc46dSJack F Vogel s32 ret_val; 2695f0ecc46dSJack F Vogel u16 j, nvm_data; 2696f0ecc46dSJack F Vogel u16 nvm_offset; 2697f0ecc46dSJack F Vogel 2698f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_82580"); 2699f0ecc46dSJack F Vogel 2700f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data); 2701f0ecc46dSJack F Vogel if (ret_val) { 27024dab5c37SJack F Vogel DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n"); 2703f0ecc46dSJack F Vogel goto out; 2704f0ecc46dSJack F Vogel } 2705f0ecc46dSJack F Vogel 2706ab5d0362SJack F Vogel if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) { 2707f0ecc46dSJack F Vogel /* set compatibility bit to validate checksums appropriately */ 2708f0ecc46dSJack F Vogel nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK; 2709f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1, 2710f0ecc46dSJack F Vogel &nvm_data); 2711f0ecc46dSJack F Vogel if (ret_val) { 27124dab5c37SJack F Vogel DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n"); 2713f0ecc46dSJack F Vogel goto out; 2714f0ecc46dSJack F Vogel } 2715f0ecc46dSJack F Vogel } 2716f0ecc46dSJack F Vogel 2717f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2718f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2719f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); 27204dab5c37SJack F Vogel if (ret_val) 2721f0ecc46dSJack F Vogel goto out; 2722f0ecc46dSJack F Vogel } 2723f0ecc46dSJack F Vogel 2724f0ecc46dSJack F Vogel out: 2725f0ecc46dSJack F Vogel return ret_val; 2726f0ecc46dSJack F Vogel } 2727f0ecc46dSJack F Vogel 2728f0ecc46dSJack F Vogel /** 2729f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum 2730f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2731f0ecc46dSJack F Vogel * 2732f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of 2733f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is 2734f0ecc46dSJack F Vogel * equal to 0xBABA. 2735f0ecc46dSJack F Vogel **/ 2736f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw) 2737f0ecc46dSJack F Vogel { 2738f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2739f0ecc46dSJack F Vogel u16 j; 2740f0ecc46dSJack F Vogel u16 nvm_offset; 2741f0ecc46dSJack F Vogel 2742f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_i350"); 2743f0ecc46dSJack F Vogel 2744f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2745f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2746f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw, 2747f0ecc46dSJack F Vogel nvm_offset); 2748f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2749f0ecc46dSJack F Vogel goto out; 2750f0ecc46dSJack F Vogel } 2751f0ecc46dSJack F Vogel 2752f0ecc46dSJack F Vogel out: 2753f0ecc46dSJack F Vogel return ret_val; 2754f0ecc46dSJack F Vogel } 2755f0ecc46dSJack F Vogel 2756f0ecc46dSJack F Vogel /** 2757f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_i350 - Update EEPROM checksum 2758f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 2759f0ecc46dSJack F Vogel * 2760f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding 2761f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM 2762f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM. 2763f0ecc46dSJack F Vogel **/ 2764f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw) 2765f0ecc46dSJack F Vogel { 2766f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS; 2767f0ecc46dSJack F Vogel u16 j; 2768f0ecc46dSJack F Vogel u16 nvm_offset; 2769f0ecc46dSJack F Vogel 2770f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_i350"); 2771f0ecc46dSJack F Vogel 2772f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) { 2773f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j); 2774f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset); 2775f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS) 2776f0ecc46dSJack F Vogel goto out; 2777f0ecc46dSJack F Vogel } 2778f0ecc46dSJack F Vogel 2779f0ecc46dSJack F Vogel out: 2780f0ecc46dSJack F Vogel return ret_val; 2781f0ecc46dSJack F Vogel } 2782f0ecc46dSJack F Vogel 2783f0ecc46dSJack F Vogel /** 27847609433eSJack F Vogel * __e1000_access_emi_reg - Read/write EMI register 27857609433eSJack F Vogel * @hw: pointer to the HW structure 27867609433eSJack F Vogel * @addr: EMI address to program 27877609433eSJack F Vogel * @data: pointer to value to read/write from/to the EMI address 27887609433eSJack F Vogel * @read: boolean flag to indicate read or write 27897609433eSJack F Vogel **/ 27907609433eSJack F Vogel static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address, 27917609433eSJack F Vogel u16 *data, bool read) 27927609433eSJack F Vogel { 27938cc64f1eSJack F Vogel s32 ret_val; 27947609433eSJack F Vogel 27957609433eSJack F Vogel DEBUGFUNC("__e1000_access_emi_reg"); 27967609433eSJack F Vogel 27977609433eSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address); 27987609433eSJack F Vogel if (ret_val) 27997609433eSJack F Vogel return ret_val; 28007609433eSJack F Vogel 28017609433eSJack F Vogel if (read) 28027609433eSJack F Vogel ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data); 28037609433eSJack F Vogel else 28047609433eSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data); 28057609433eSJack F Vogel 28067609433eSJack F Vogel return ret_val; 28077609433eSJack F Vogel } 28087609433eSJack F Vogel 28097609433eSJack F Vogel /** 28107609433eSJack F Vogel * e1000_read_emi_reg - Read Extended Management Interface register 28117609433eSJack F Vogel * @hw: pointer to the HW structure 28127609433eSJack F Vogel * @addr: EMI address to program 28137609433eSJack F Vogel * @data: value to be read from the EMI address 28147609433eSJack F Vogel **/ 28157609433eSJack F Vogel s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data) 28167609433eSJack F Vogel { 28177609433eSJack F Vogel DEBUGFUNC("e1000_read_emi_reg"); 28187609433eSJack F Vogel 28197609433eSJack F Vogel return __e1000_access_emi_reg(hw, addr, data, TRUE); 28207609433eSJack F Vogel } 28217609433eSJack F Vogel 28227609433eSJack F Vogel /** 28238cc64f1eSJack F Vogel * e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY 28248cc64f1eSJack F Vogel * @hw: pointer to the HW structure 28258cc64f1eSJack F Vogel * 2826c80429ceSEric Joyner * Initialize Marvell 1512 to work correctly with Avoton. 28278cc64f1eSJack F Vogel **/ 28288cc64f1eSJack F Vogel s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw) 28298cc64f1eSJack F Vogel { 28308cc64f1eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 28318cc64f1eSJack F Vogel s32 ret_val = E1000_SUCCESS; 28328cc64f1eSJack F Vogel 28338cc64f1eSJack F Vogel DEBUGFUNC("e1000_initialize_M88E1512_phy"); 28348cc64f1eSJack F Vogel 28358cc64f1eSJack F Vogel /* Check if this is correct PHY. */ 28368cc64f1eSJack F Vogel if (phy->id != M88E1512_E_PHY_ID) 28378cc64f1eSJack F Vogel goto out; 28388cc64f1eSJack F Vogel 28398cc64f1eSJack F Vogel /* Switch to PHY page 0xFF. */ 28408cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); 28418cc64f1eSJack F Vogel if (ret_val) 28428cc64f1eSJack F Vogel goto out; 28438cc64f1eSJack F Vogel 28448cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); 28458cc64f1eSJack F Vogel if (ret_val) 28468cc64f1eSJack F Vogel goto out; 28478cc64f1eSJack F Vogel 28488cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); 28498cc64f1eSJack F Vogel if (ret_val) 28508cc64f1eSJack F Vogel goto out; 28518cc64f1eSJack F Vogel 28528cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); 28538cc64f1eSJack F Vogel if (ret_val) 28548cc64f1eSJack F Vogel goto out; 28558cc64f1eSJack F Vogel 28568cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); 28578cc64f1eSJack F Vogel if (ret_val) 28588cc64f1eSJack F Vogel goto out; 28598cc64f1eSJack F Vogel 28608cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); 28618cc64f1eSJack F Vogel if (ret_val) 28628cc64f1eSJack F Vogel goto out; 28638cc64f1eSJack F Vogel 28648cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); 28658cc64f1eSJack F Vogel if (ret_val) 28668cc64f1eSJack F Vogel goto out; 28678cc64f1eSJack F Vogel 28688cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xCC0C); 28698cc64f1eSJack F Vogel if (ret_val) 28708cc64f1eSJack F Vogel goto out; 28718cc64f1eSJack F Vogel 28728cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); 28738cc64f1eSJack F Vogel if (ret_val) 28748cc64f1eSJack F Vogel goto out; 28758cc64f1eSJack F Vogel 28768cc64f1eSJack F Vogel /* Switch to PHY page 0xFB. */ 28778cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); 28788cc64f1eSJack F Vogel if (ret_val) 28798cc64f1eSJack F Vogel goto out; 28808cc64f1eSJack F Vogel 28818cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0x000D); 28828cc64f1eSJack F Vogel if (ret_val) 28838cc64f1eSJack F Vogel goto out; 28848cc64f1eSJack F Vogel 28858cc64f1eSJack F Vogel /* Switch to PHY page 0x12. */ 28868cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); 28878cc64f1eSJack F Vogel if (ret_val) 28888cc64f1eSJack F Vogel goto out; 28898cc64f1eSJack F Vogel 28908cc64f1eSJack F Vogel /* Change mode to SGMII-to-Copper */ 28918cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); 28928cc64f1eSJack F Vogel if (ret_val) 28938cc64f1eSJack F Vogel goto out; 28948cc64f1eSJack F Vogel 28958cc64f1eSJack F Vogel /* Return the PHY to page 0. */ 28968cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); 28978cc64f1eSJack F Vogel if (ret_val) 28988cc64f1eSJack F Vogel goto out; 28998cc64f1eSJack F Vogel 29008cc64f1eSJack F Vogel ret_val = phy->ops.commit(hw); 29018cc64f1eSJack F Vogel if (ret_val) { 29028cc64f1eSJack F Vogel DEBUGOUT("Error committing the PHY changes\n"); 29038cc64f1eSJack F Vogel return ret_val; 29048cc64f1eSJack F Vogel } 29058cc64f1eSJack F Vogel 29068cc64f1eSJack F Vogel msec_delay(1000); 29078cc64f1eSJack F Vogel out: 29088cc64f1eSJack F Vogel return ret_val; 29098cc64f1eSJack F Vogel } 29108cc64f1eSJack F Vogel 29118cc64f1eSJack F Vogel /** 2912c80429ceSEric Joyner * e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY 2913c80429ceSEric Joyner * @hw: pointer to the HW structure 2914c80429ceSEric Joyner * 2915c80429ceSEric Joyner * Initialize Marvell 1543 to work correctly with Avoton. 2916c80429ceSEric Joyner **/ 2917c80429ceSEric Joyner s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw) 2918c80429ceSEric Joyner { 2919c80429ceSEric Joyner struct e1000_phy_info *phy = &hw->phy; 2920c80429ceSEric Joyner s32 ret_val = E1000_SUCCESS; 2921c80429ceSEric Joyner 2922c80429ceSEric Joyner DEBUGFUNC("e1000_initialize_M88E1543_phy"); 2923c80429ceSEric Joyner 2924c80429ceSEric Joyner /* Check if this is correct PHY. */ 2925c80429ceSEric Joyner if (phy->id != M88E1543_E_PHY_ID) 2926c80429ceSEric Joyner goto out; 2927c80429ceSEric Joyner 2928c80429ceSEric Joyner /* Switch to PHY page 0xFF. */ 2929c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF); 2930c80429ceSEric Joyner if (ret_val) 2931c80429ceSEric Joyner goto out; 2932c80429ceSEric Joyner 2933c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B); 2934c80429ceSEric Joyner if (ret_val) 2935c80429ceSEric Joyner goto out; 2936c80429ceSEric Joyner 2937c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144); 2938c80429ceSEric Joyner if (ret_val) 2939c80429ceSEric Joyner goto out; 2940c80429ceSEric Joyner 2941c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28); 2942c80429ceSEric Joyner if (ret_val) 2943c80429ceSEric Joyner goto out; 2944c80429ceSEric Joyner 2945c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146); 2946c80429ceSEric Joyner if (ret_val) 2947c80429ceSEric Joyner goto out; 2948c80429ceSEric Joyner 2949c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233); 2950c80429ceSEric Joyner if (ret_val) 2951c80429ceSEric Joyner goto out; 2952c80429ceSEric Joyner 2953c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D); 2954c80429ceSEric Joyner if (ret_val) 2955c80429ceSEric Joyner goto out; 2956c80429ceSEric Joyner 2957c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C); 2958c80429ceSEric Joyner if (ret_val) 2959c80429ceSEric Joyner goto out; 2960c80429ceSEric Joyner 2961c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159); 2962c80429ceSEric Joyner if (ret_val) 2963c80429ceSEric Joyner goto out; 2964c80429ceSEric Joyner 2965c80429ceSEric Joyner /* Switch to PHY page 0xFB. */ 2966c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB); 2967c80429ceSEric Joyner if (ret_val) 2968c80429ceSEric Joyner goto out; 2969c80429ceSEric Joyner 2970c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D); 2971c80429ceSEric Joyner if (ret_val) 2972c80429ceSEric Joyner goto out; 2973c80429ceSEric Joyner 2974c80429ceSEric Joyner /* Switch to PHY page 0x12. */ 2975c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12); 2976c80429ceSEric Joyner if (ret_val) 2977c80429ceSEric Joyner goto out; 2978c80429ceSEric Joyner 2979c80429ceSEric Joyner /* Change mode to SGMII-to-Copper */ 2980c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001); 2981c80429ceSEric Joyner if (ret_val) 2982c80429ceSEric Joyner goto out; 2983c80429ceSEric Joyner 2984c80429ceSEric Joyner /* Switch to PHY page 1. */ 2985c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1); 2986c80429ceSEric Joyner if (ret_val) 2987c80429ceSEric Joyner goto out; 2988c80429ceSEric Joyner 2989c80429ceSEric Joyner /* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */ 2990c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140); 2991c80429ceSEric Joyner if (ret_val) 2992c80429ceSEric Joyner goto out; 2993c80429ceSEric Joyner 2994c80429ceSEric Joyner /* Return the PHY to page 0. */ 2995c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); 2996c80429ceSEric Joyner if (ret_val) 2997c80429ceSEric Joyner goto out; 2998c80429ceSEric Joyner 2999c80429ceSEric Joyner ret_val = phy->ops.commit(hw); 3000c80429ceSEric Joyner if (ret_val) { 3001c80429ceSEric Joyner DEBUGOUT("Error committing the PHY changes\n"); 3002c80429ceSEric Joyner return ret_val; 3003c80429ceSEric Joyner } 3004c80429ceSEric Joyner 3005c80429ceSEric Joyner msec_delay(1000); 3006c80429ceSEric Joyner out: 3007c80429ceSEric Joyner return ret_val; 3008c80429ceSEric Joyner } 3009c80429ceSEric Joyner 3010c80429ceSEric Joyner /** 3011f0ecc46dSJack F Vogel * e1000_set_eee_i350 - Enable/disable EEE support 3012f0ecc46dSJack F Vogel * @hw: pointer to the HW structure 3013c80429ceSEric Joyner * @adv1g: boolean flag enabling 1G EEE advertisement 3014c80429ceSEric Joyner * @adv100m: boolean flag enabling 100M EEE advertisement 3015f0ecc46dSJack F Vogel * 3016f0ecc46dSJack F Vogel * Enable/disable EEE based on setting in dev_spec structure. 3017f0ecc46dSJack F Vogel * 3018f0ecc46dSJack F Vogel **/ 3019c80429ceSEric Joyner s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M) 3020f0ecc46dSJack F Vogel { 30214dab5c37SJack F Vogel u32 ipcnfg, eeer; 3022f0ecc46dSJack F Vogel 3023f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_eee_i350"); 3024f0ecc46dSJack F Vogel 30254dab5c37SJack F Vogel if ((hw->mac.type < e1000_i350) || 30264dab5c37SJack F Vogel (hw->phy.media_type != e1000_media_type_copper)) 3027f0ecc46dSJack F Vogel goto out; 3028f0ecc46dSJack F Vogel ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG); 3029f0ecc46dSJack F Vogel eeer = E1000_READ_REG(hw, E1000_EEER); 3030f0ecc46dSJack F Vogel 3031f0ecc46dSJack F Vogel /* enable or disable per user setting */ 3032f0ecc46dSJack F Vogel if (!(hw->dev_spec._82575.eee_disable)) { 30336ab6bfe3SJack F Vogel u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU); 30346ab6bfe3SJack F Vogel 3035c80429ceSEric Joyner if (adv100M) 3036c80429ceSEric Joyner ipcnfg |= E1000_IPCNFG_EEE_100M_AN; 3037c80429ceSEric Joyner else 3038c80429ceSEric Joyner ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN; 3039c80429ceSEric Joyner 3040c80429ceSEric Joyner if (adv1G) 3041c80429ceSEric Joyner ipcnfg |= E1000_IPCNFG_EEE_1G_AN; 3042c80429ceSEric Joyner else 3043c80429ceSEric Joyner ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN; 3044c80429ceSEric Joyner 30454dab5c37SJack F Vogel eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | 3046f0ecc46dSJack F Vogel E1000_EEER_LPI_FC); 3047f0ecc46dSJack F Vogel 30486ab6bfe3SJack F Vogel /* This bit should not be set in normal operation. */ 30496ab6bfe3SJack F Vogel if (eee_su & E1000_EEE_SU_LPI_CLK_STP) 30506ab6bfe3SJack F Vogel DEBUGOUT("LPI Clock Stop Bit should not be set!\n"); 3051f0ecc46dSJack F Vogel } else { 30524dab5c37SJack F Vogel ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN); 30534dab5c37SJack F Vogel eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN | 3054f0ecc46dSJack F Vogel E1000_EEER_LPI_FC); 3055f0ecc46dSJack F Vogel } 3056f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg); 3057f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_EEER, eeer); 3058f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_IPCNFG); 3059f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_EEER); 3060f0ecc46dSJack F Vogel out: 3061f0ecc46dSJack F Vogel 30628cc64f1eSJack F Vogel return E1000_SUCCESS; 3063f0ecc46dSJack F Vogel } 30644dab5c37SJack F Vogel 30657609433eSJack F Vogel /** 30667609433eSJack F Vogel * e1000_set_eee_i354 - Enable/disable EEE support 30677609433eSJack F Vogel * @hw: pointer to the HW structure 3068c80429ceSEric Joyner * @adv1g: boolean flag enabling 1G EEE advertisement 3069c80429ceSEric Joyner * @adv100m: boolean flag enabling 100M EEE advertisement 30707609433eSJack F Vogel * 30717609433eSJack F Vogel * Enable/disable EEE legacy mode based on setting in dev_spec structure. 30727609433eSJack F Vogel * 30737609433eSJack F Vogel **/ 3074c80429ceSEric Joyner s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M) 30757609433eSJack F Vogel { 30767609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 30777609433eSJack F Vogel s32 ret_val = E1000_SUCCESS; 30787609433eSJack F Vogel u16 phy_data; 30797609433eSJack F Vogel 30807609433eSJack F Vogel DEBUGFUNC("e1000_set_eee_i354"); 30817609433eSJack F Vogel 30827609433eSJack F Vogel if ((hw->phy.media_type != e1000_media_type_copper) || 30837609433eSJack F Vogel ((phy->id != M88E1543_E_PHY_ID) && 30847609433eSJack F Vogel (phy->id != M88E1512_E_PHY_ID))) 30857609433eSJack F Vogel goto out; 30867609433eSJack F Vogel 30877609433eSJack F Vogel if (!hw->dev_spec._82575.eee_disable) { 30887609433eSJack F Vogel /* Switch to PHY page 18. */ 30897609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18); 30907609433eSJack F Vogel if (ret_val) 30917609433eSJack F Vogel goto out; 30927609433eSJack F Vogel 30937609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1, 30947609433eSJack F Vogel &phy_data); 30957609433eSJack F Vogel if (ret_val) 30967609433eSJack F Vogel goto out; 30977609433eSJack F Vogel 30987609433eSJack F Vogel phy_data |= E1000_M88E1543_EEE_CTRL_1_MS; 30997609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1, 31007609433eSJack F Vogel phy_data); 31017609433eSJack F Vogel if (ret_val) 31027609433eSJack F Vogel goto out; 31037609433eSJack F Vogel 31047609433eSJack F Vogel /* Return the PHY to page 0. */ 31057609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0); 31067609433eSJack F Vogel if (ret_val) 31077609433eSJack F Vogel goto out; 31087609433eSJack F Vogel 31097609433eSJack F Vogel /* Turn on EEE advertisement. */ 31107609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 31117609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 31127609433eSJack F Vogel &phy_data); 31137609433eSJack F Vogel if (ret_val) 31147609433eSJack F Vogel goto out; 31157609433eSJack F Vogel 3116c80429ceSEric Joyner if (adv100M) 3117c80429ceSEric Joyner phy_data |= E1000_EEE_ADV_100_SUPPORTED; 3118c80429ceSEric Joyner else 3119c80429ceSEric Joyner phy_data &= ~E1000_EEE_ADV_100_SUPPORTED; 3120c80429ceSEric Joyner 3121c80429ceSEric Joyner if (adv1G) 3122c80429ceSEric Joyner phy_data |= E1000_EEE_ADV_1000_SUPPORTED; 3123c80429ceSEric Joyner else 3124c80429ceSEric Joyner phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED; 3125c80429ceSEric Joyner 31267609433eSJack F Vogel ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 31277609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 31287609433eSJack F Vogel phy_data); 31297609433eSJack F Vogel } else { 31307609433eSJack F Vogel /* Turn off EEE advertisement. */ 31317609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 31327609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 31337609433eSJack F Vogel &phy_data); 31347609433eSJack F Vogel if (ret_val) 31357609433eSJack F Vogel goto out; 31367609433eSJack F Vogel 31377609433eSJack F Vogel phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED | 31387609433eSJack F Vogel E1000_EEE_ADV_1000_SUPPORTED); 31397609433eSJack F Vogel ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354, 31407609433eSJack F Vogel E1000_EEE_ADV_DEV_I354, 31417609433eSJack F Vogel phy_data); 31427609433eSJack F Vogel } 31437609433eSJack F Vogel 31447609433eSJack F Vogel out: 31457609433eSJack F Vogel return ret_val; 31467609433eSJack F Vogel } 31477609433eSJack F Vogel 31487609433eSJack F Vogel /** 31497609433eSJack F Vogel * e1000_get_eee_status_i354 - Get EEE status 31507609433eSJack F Vogel * @hw: pointer to the HW structure 31517609433eSJack F Vogel * @status: EEE status 31527609433eSJack F Vogel * 31537609433eSJack F Vogel * Get EEE status by guessing based on whether Tx or Rx LPI indications have 31547609433eSJack F Vogel * been received. 31557609433eSJack F Vogel **/ 31567609433eSJack F Vogel s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status) 31577609433eSJack F Vogel { 31587609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy; 31597609433eSJack F Vogel s32 ret_val = E1000_SUCCESS; 31607609433eSJack F Vogel u16 phy_data; 31617609433eSJack F Vogel 31627609433eSJack F Vogel DEBUGFUNC("e1000_get_eee_status_i354"); 31637609433eSJack F Vogel 31647609433eSJack F Vogel /* Check if EEE is supported on this device. */ 31657609433eSJack F Vogel if ((hw->phy.media_type != e1000_media_type_copper) || 31667609433eSJack F Vogel ((phy->id != M88E1543_E_PHY_ID) && 31677609433eSJack F Vogel (phy->id != M88E1512_E_PHY_ID))) 31687609433eSJack F Vogel goto out; 31697609433eSJack F Vogel 31707609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354, 31717609433eSJack F Vogel E1000_PCS_STATUS_DEV_I354, 31727609433eSJack F Vogel &phy_data); 31737609433eSJack F Vogel if (ret_val) 31747609433eSJack F Vogel goto out; 31757609433eSJack F Vogel 31767609433eSJack F Vogel *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD | 31777609433eSJack F Vogel E1000_PCS_STATUS_RX_LPI_RCVD) ? TRUE : FALSE; 31787609433eSJack F Vogel 31797609433eSJack F Vogel out: 31807609433eSJack F Vogel return ret_val; 31817609433eSJack F Vogel } 31827609433eSJack F Vogel 31834dab5c37SJack F Vogel /* Due to a hw errata, if the host tries to configure the VFTA register 31844dab5c37SJack F Vogel * while performing queries from the BMC or DMA, then the VFTA in some 31854dab5c37SJack F Vogel * cases won't be written. 31864dab5c37SJack F Vogel */ 31874dab5c37SJack F Vogel 31884dab5c37SJack F Vogel /** 31894dab5c37SJack F Vogel * e1000_clear_vfta_i350 - Clear VLAN filter table 31904dab5c37SJack F Vogel * @hw: pointer to the HW structure 31914dab5c37SJack F Vogel * 31924dab5c37SJack F Vogel * Clears the register array which contains the VLAN filter table by 31934dab5c37SJack F Vogel * setting all the values to 0. 31944dab5c37SJack F Vogel **/ 31954dab5c37SJack F Vogel void e1000_clear_vfta_i350(struct e1000_hw *hw) 31964dab5c37SJack F Vogel { 31974dab5c37SJack F Vogel u32 offset; 31984dab5c37SJack F Vogel int i; 31994dab5c37SJack F Vogel 32004dab5c37SJack F Vogel DEBUGFUNC("e1000_clear_vfta_350"); 32014dab5c37SJack F Vogel 32024dab5c37SJack F Vogel for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) { 32034dab5c37SJack F Vogel for (i = 0; i < 10; i++) 32044dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0); 32054dab5c37SJack F Vogel 32064dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 32074dab5c37SJack F Vogel } 32084dab5c37SJack F Vogel } 32094dab5c37SJack F Vogel 32104dab5c37SJack F Vogel /** 32114dab5c37SJack F Vogel * e1000_write_vfta_i350 - Write value to VLAN filter table 32124dab5c37SJack F Vogel * @hw: pointer to the HW structure 32134dab5c37SJack F Vogel * @offset: register offset in VLAN filter table 32144dab5c37SJack F Vogel * @value: register value written to VLAN filter table 32154dab5c37SJack F Vogel * 32164dab5c37SJack F Vogel * Writes value at the given offset in the register array which stores 32174dab5c37SJack F Vogel * the VLAN filter table. 32184dab5c37SJack F Vogel **/ 32194dab5c37SJack F Vogel void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value) 32204dab5c37SJack F Vogel { 32214dab5c37SJack F Vogel int i; 32224dab5c37SJack F Vogel 32234dab5c37SJack F Vogel DEBUGFUNC("e1000_write_vfta_350"); 32244dab5c37SJack F Vogel 32254dab5c37SJack F Vogel for (i = 0; i < 10; i++) 32264dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value); 32274dab5c37SJack F Vogel 32284dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 32294dab5c37SJack F Vogel } 32304dab5c37SJack F Vogel 32314dab5c37SJack F Vogel 32324dab5c37SJack F Vogel /** 32334dab5c37SJack F Vogel * e1000_set_i2c_bb - Enable I2C bit-bang 32344dab5c37SJack F Vogel * @hw: pointer to the HW structure 32354dab5c37SJack F Vogel * 32364dab5c37SJack F Vogel * Enable I2C bit-bang interface 32374dab5c37SJack F Vogel * 32384dab5c37SJack F Vogel **/ 32394dab5c37SJack F Vogel s32 e1000_set_i2c_bb(struct e1000_hw *hw) 32404dab5c37SJack F Vogel { 32414dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS; 32424dab5c37SJack F Vogel u32 ctrl_ext, i2cparams; 32434dab5c37SJack F Vogel 32444dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_bb"); 32454dab5c37SJack F Vogel 32464dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT); 32474dab5c37SJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA; 32484dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext); 32494dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 32504dab5c37SJack F Vogel 32514dab5c37SJack F Vogel i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS); 32524dab5c37SJack F Vogel i2cparams |= E1000_I2CBB_EN; 32534dab5c37SJack F Vogel i2cparams |= E1000_I2C_DATA_OE_N; 32544dab5c37SJack F Vogel i2cparams |= E1000_I2C_CLK_OE_N; 32554dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams); 32564dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 32574dab5c37SJack F Vogel 32584dab5c37SJack F Vogel return ret_val; 32594dab5c37SJack F Vogel } 32604dab5c37SJack F Vogel 32614dab5c37SJack F Vogel /** 32624dab5c37SJack F Vogel * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C 32634dab5c37SJack F Vogel * @hw: pointer to hardware structure 32644dab5c37SJack F Vogel * @byte_offset: byte offset to read 3265ab5d0362SJack F Vogel * @dev_addr: device address 32664dab5c37SJack F Vogel * @data: value read 32674dab5c37SJack F Vogel * 32684dab5c37SJack F Vogel * Performs byte read operation over I2C interface at 32694dab5c37SJack F Vogel * a specified device address. 32704dab5c37SJack F Vogel **/ 32714dab5c37SJack F Vogel s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, 32724dab5c37SJack F Vogel u8 dev_addr, u8 *data) 32734dab5c37SJack F Vogel { 32744dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 32754dab5c37SJack F Vogel u32 max_retry = 10; 32764dab5c37SJack F Vogel u32 retry = 1; 32774dab5c37SJack F Vogel u16 swfw_mask = 0; 32784dab5c37SJack F Vogel 3279ab5d0362SJack F Vogel bool nack = TRUE; 32804dab5c37SJack F Vogel 32814dab5c37SJack F Vogel DEBUGFUNC("e1000_read_i2c_byte_generic"); 32824dab5c37SJack F Vogel 32834dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM; 32844dab5c37SJack F Vogel 32854dab5c37SJack F Vogel do { 3286ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) 32874dab5c37SJack F Vogel != E1000_SUCCESS) { 32884dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC; 32894dab5c37SJack F Vogel goto read_byte_out; 32904dab5c37SJack F Vogel } 32914dab5c37SJack F Vogel 32924dab5c37SJack F Vogel e1000_i2c_start(hw); 32934dab5c37SJack F Vogel 32944dab5c37SJack F Vogel /* Device Address and write indication */ 32954dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr); 32964dab5c37SJack F Vogel if (status != E1000_SUCCESS) 32974dab5c37SJack F Vogel goto fail; 32984dab5c37SJack F Vogel 32994dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33004dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33014dab5c37SJack F Vogel goto fail; 33024dab5c37SJack F Vogel 33034dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset); 33044dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33054dab5c37SJack F Vogel goto fail; 33064dab5c37SJack F Vogel 33074dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33084dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33094dab5c37SJack F Vogel goto fail; 33104dab5c37SJack F Vogel 33114dab5c37SJack F Vogel e1000_i2c_start(hw); 33124dab5c37SJack F Vogel 33134dab5c37SJack F Vogel /* Device Address and read indication */ 33144dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1)); 33154dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33164dab5c37SJack F Vogel goto fail; 33174dab5c37SJack F Vogel 33184dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33194dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33204dab5c37SJack F Vogel goto fail; 33214dab5c37SJack F Vogel 33224dab5c37SJack F Vogel status = e1000_clock_in_i2c_byte(hw, data); 33234dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33244dab5c37SJack F Vogel goto fail; 33254dab5c37SJack F Vogel 33264dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, nack); 33274dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33284dab5c37SJack F Vogel goto fail; 33294dab5c37SJack F Vogel 33304dab5c37SJack F Vogel e1000_i2c_stop(hw); 33314dab5c37SJack F Vogel break; 33324dab5c37SJack F Vogel 33334dab5c37SJack F Vogel fail: 3334ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 33354dab5c37SJack F Vogel msec_delay(100); 33364dab5c37SJack F Vogel e1000_i2c_bus_clear(hw); 33374dab5c37SJack F Vogel retry++; 33384dab5c37SJack F Vogel if (retry < max_retry) 33394dab5c37SJack F Vogel DEBUGOUT("I2C byte read error - Retrying.\n"); 33404dab5c37SJack F Vogel else 33414dab5c37SJack F Vogel DEBUGOUT("I2C byte read error.\n"); 33424dab5c37SJack F Vogel 33434dab5c37SJack F Vogel } while (retry < max_retry); 33444dab5c37SJack F Vogel 3345ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 33464dab5c37SJack F Vogel 33474dab5c37SJack F Vogel read_byte_out: 33484dab5c37SJack F Vogel 33494dab5c37SJack F Vogel return status; 33504dab5c37SJack F Vogel } 33514dab5c37SJack F Vogel 33524dab5c37SJack F Vogel /** 33534dab5c37SJack F Vogel * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C 33544dab5c37SJack F Vogel * @hw: pointer to hardware structure 33554dab5c37SJack F Vogel * @byte_offset: byte offset to write 3356ab5d0362SJack F Vogel * @dev_addr: device address 33574dab5c37SJack F Vogel * @data: value to write 33584dab5c37SJack F Vogel * 33594dab5c37SJack F Vogel * Performs byte write operation over I2C interface at 33604dab5c37SJack F Vogel * a specified device address. 33614dab5c37SJack F Vogel **/ 33624dab5c37SJack F Vogel s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset, 33634dab5c37SJack F Vogel u8 dev_addr, u8 data) 33644dab5c37SJack F Vogel { 33654dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 33664dab5c37SJack F Vogel u32 max_retry = 1; 33674dab5c37SJack F Vogel u32 retry = 0; 33684dab5c37SJack F Vogel u16 swfw_mask = 0; 33694dab5c37SJack F Vogel 33704dab5c37SJack F Vogel DEBUGFUNC("e1000_write_i2c_byte_generic"); 33714dab5c37SJack F Vogel 33724dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM; 33734dab5c37SJack F Vogel 3374ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) { 33754dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC; 33764dab5c37SJack F Vogel goto write_byte_out; 33774dab5c37SJack F Vogel } 33784dab5c37SJack F Vogel 33794dab5c37SJack F Vogel do { 33804dab5c37SJack F Vogel e1000_i2c_start(hw); 33814dab5c37SJack F Vogel 33824dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr); 33834dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33844dab5c37SJack F Vogel goto fail; 33854dab5c37SJack F Vogel 33864dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33874dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33884dab5c37SJack F Vogel goto fail; 33894dab5c37SJack F Vogel 33904dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset); 33914dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33924dab5c37SJack F Vogel goto fail; 33934dab5c37SJack F Vogel 33944dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 33954dab5c37SJack F Vogel if (status != E1000_SUCCESS) 33964dab5c37SJack F Vogel goto fail; 33974dab5c37SJack F Vogel 33984dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, data); 33994dab5c37SJack F Vogel if (status != E1000_SUCCESS) 34004dab5c37SJack F Vogel goto fail; 34014dab5c37SJack F Vogel 34024dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw); 34034dab5c37SJack F Vogel if (status != E1000_SUCCESS) 34044dab5c37SJack F Vogel goto fail; 34054dab5c37SJack F Vogel 34064dab5c37SJack F Vogel e1000_i2c_stop(hw); 34074dab5c37SJack F Vogel break; 34084dab5c37SJack F Vogel 34094dab5c37SJack F Vogel fail: 34104dab5c37SJack F Vogel e1000_i2c_bus_clear(hw); 34114dab5c37SJack F Vogel retry++; 34124dab5c37SJack F Vogel if (retry < max_retry) 34134dab5c37SJack F Vogel DEBUGOUT("I2C byte write error - Retrying.\n"); 34144dab5c37SJack F Vogel else 34154dab5c37SJack F Vogel DEBUGOUT("I2C byte write error.\n"); 34164dab5c37SJack F Vogel } while (retry < max_retry); 34174dab5c37SJack F Vogel 3418ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask); 34194dab5c37SJack F Vogel 34204dab5c37SJack F Vogel write_byte_out: 34214dab5c37SJack F Vogel 34224dab5c37SJack F Vogel return status; 34234dab5c37SJack F Vogel } 34244dab5c37SJack F Vogel 34254dab5c37SJack F Vogel /** 34264dab5c37SJack F Vogel * e1000_i2c_start - Sets I2C start condition 34274dab5c37SJack F Vogel * @hw: pointer to hardware structure 34284dab5c37SJack F Vogel * 34294dab5c37SJack F Vogel * Sets I2C start condition (High -> Low on SDA while SCL is High) 34304dab5c37SJack F Vogel **/ 34314dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw) 34324dab5c37SJack F Vogel { 34334dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 34344dab5c37SJack F Vogel 34354dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_start"); 34364dab5c37SJack F Vogel 34374dab5c37SJack F Vogel /* Start condition must begin with data and clock high */ 34384dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 34394dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 34404dab5c37SJack F Vogel 34414dab5c37SJack F Vogel /* Setup time for start condition (4.7us) */ 34424dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STA); 34434dab5c37SJack F Vogel 34444dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0); 34454dab5c37SJack F Vogel 34464dab5c37SJack F Vogel /* Hold time for start condition (4us) */ 34474dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HD_STA); 34484dab5c37SJack F Vogel 34494dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 34504dab5c37SJack F Vogel 34514dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 34524dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 34534dab5c37SJack F Vogel 34544dab5c37SJack F Vogel } 34554dab5c37SJack F Vogel 34564dab5c37SJack F Vogel /** 34574dab5c37SJack F Vogel * e1000_i2c_stop - Sets I2C stop condition 34584dab5c37SJack F Vogel * @hw: pointer to hardware structure 34594dab5c37SJack F Vogel * 34604dab5c37SJack F Vogel * Sets I2C stop condition (Low -> High on SDA while SCL is High) 34614dab5c37SJack F Vogel **/ 34624dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw) 34634dab5c37SJack F Vogel { 34644dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 34654dab5c37SJack F Vogel 34664dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_stop"); 34674dab5c37SJack F Vogel 34684dab5c37SJack F Vogel /* Stop condition must begin with data low and clock high */ 34694dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0); 34704dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 34714dab5c37SJack F Vogel 34724dab5c37SJack F Vogel /* Setup time for stop condition (4us) */ 34734dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STO); 34744dab5c37SJack F Vogel 34754dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 34764dab5c37SJack F Vogel 34774dab5c37SJack F Vogel /* bus free time between stop and start (4.7us)*/ 34784dab5c37SJack F Vogel usec_delay(E1000_I2C_T_BUF); 34794dab5c37SJack F Vogel } 34804dab5c37SJack F Vogel 34814dab5c37SJack F Vogel /** 34824dab5c37SJack F Vogel * e1000_clock_in_i2c_byte - Clocks in one byte via I2C 34834dab5c37SJack F Vogel * @hw: pointer to hardware structure 34844dab5c37SJack F Vogel * @data: data byte to clock in 34854dab5c37SJack F Vogel * 34864dab5c37SJack F Vogel * Clocks in one byte data via I2C data/clock 34874dab5c37SJack F Vogel **/ 34884dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data) 34894dab5c37SJack F Vogel { 34904dab5c37SJack F Vogel s32 i; 34914dab5c37SJack F Vogel bool bit = 0; 34924dab5c37SJack F Vogel 34934dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_byte"); 34944dab5c37SJack F Vogel 34954dab5c37SJack F Vogel *data = 0; 34964dab5c37SJack F Vogel for (i = 7; i >= 0; i--) { 34974dab5c37SJack F Vogel e1000_clock_in_i2c_bit(hw, &bit); 34984dab5c37SJack F Vogel *data |= bit << i; 34994dab5c37SJack F Vogel } 35004dab5c37SJack F Vogel 35014dab5c37SJack F Vogel return E1000_SUCCESS; 35024dab5c37SJack F Vogel } 35034dab5c37SJack F Vogel 35044dab5c37SJack F Vogel /** 35054dab5c37SJack F Vogel * e1000_clock_out_i2c_byte - Clocks out one byte via I2C 35064dab5c37SJack F Vogel * @hw: pointer to hardware structure 35074dab5c37SJack F Vogel * @data: data byte clocked out 35084dab5c37SJack F Vogel * 35094dab5c37SJack F Vogel * Clocks out one byte data via I2C data/clock 35104dab5c37SJack F Vogel **/ 35114dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data) 35124dab5c37SJack F Vogel { 35134dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 35144dab5c37SJack F Vogel s32 i; 35154dab5c37SJack F Vogel u32 i2cctl; 35164dab5c37SJack F Vogel bool bit = 0; 35174dab5c37SJack F Vogel 35184dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_byte"); 35194dab5c37SJack F Vogel 35204dab5c37SJack F Vogel for (i = 7; i >= 0; i--) { 35214dab5c37SJack F Vogel bit = (data >> i) & 0x1; 35224dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, bit); 35234dab5c37SJack F Vogel 35244dab5c37SJack F Vogel if (status != E1000_SUCCESS) 35254dab5c37SJack F Vogel break; 35264dab5c37SJack F Vogel } 35274dab5c37SJack F Vogel 35284dab5c37SJack F Vogel /* Release SDA line (set high) */ 35294dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 35304dab5c37SJack F Vogel 35314dab5c37SJack F Vogel i2cctl |= E1000_I2C_DATA_OE_N; 35324dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl); 35334dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 35344dab5c37SJack F Vogel 35354dab5c37SJack F Vogel return status; 35364dab5c37SJack F Vogel } 35374dab5c37SJack F Vogel 35384dab5c37SJack F Vogel /** 35394dab5c37SJack F Vogel * e1000_get_i2c_ack - Polls for I2C ACK 35404dab5c37SJack F Vogel * @hw: pointer to hardware structure 35414dab5c37SJack F Vogel * 35424dab5c37SJack F Vogel * Clocks in/out one bit via I2C data/clock 35434dab5c37SJack F Vogel **/ 35444dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw) 35454dab5c37SJack F Vogel { 35464dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 35474dab5c37SJack F Vogel u32 i = 0; 35484dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 35494dab5c37SJack F Vogel u32 timeout = 10; 3550ab5d0362SJack F Vogel bool ack = TRUE; 35514dab5c37SJack F Vogel 35524dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_ack"); 35534dab5c37SJack F Vogel 35544dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 35554dab5c37SJack F Vogel 35564dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 35574dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 35584dab5c37SJack F Vogel 35594dab5c37SJack F Vogel /* Wait until SCL returns high */ 35604dab5c37SJack F Vogel for (i = 0; i < timeout; i++) { 35614dab5c37SJack F Vogel usec_delay(1); 35624dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 35634dab5c37SJack F Vogel if (i2cctl & E1000_I2C_CLK_IN) 35644dab5c37SJack F Vogel break; 35654dab5c37SJack F Vogel } 35664dab5c37SJack F Vogel if (!(i2cctl & E1000_I2C_CLK_IN)) 35674dab5c37SJack F Vogel return E1000_ERR_I2C; 35684dab5c37SJack F Vogel 35694dab5c37SJack F Vogel ack = e1000_get_i2c_data(&i2cctl); 3570ab5d0362SJack F Vogel if (ack) { 35714dab5c37SJack F Vogel DEBUGOUT("I2C ack was not received.\n"); 35724dab5c37SJack F Vogel status = E1000_ERR_I2C; 35734dab5c37SJack F Vogel } 35744dab5c37SJack F Vogel 35754dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 35764dab5c37SJack F Vogel 35774dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 35784dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 35794dab5c37SJack F Vogel 35804dab5c37SJack F Vogel return status; 35814dab5c37SJack F Vogel } 35824dab5c37SJack F Vogel 35834dab5c37SJack F Vogel /** 35844dab5c37SJack F Vogel * e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock 35854dab5c37SJack F Vogel * @hw: pointer to hardware structure 35864dab5c37SJack F Vogel * @data: read data value 35874dab5c37SJack F Vogel * 35884dab5c37SJack F Vogel * Clocks in one bit via I2C data/clock 35894dab5c37SJack F Vogel **/ 35904dab5c37SJack F Vogel static s32 e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data) 35914dab5c37SJack F Vogel { 35924dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 35934dab5c37SJack F Vogel 35944dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_bit"); 35954dab5c37SJack F Vogel 35964dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 35974dab5c37SJack F Vogel 35984dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 35994dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 36004dab5c37SJack F Vogel 36014dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 36024dab5c37SJack F Vogel *data = e1000_get_i2c_data(&i2cctl); 36034dab5c37SJack F Vogel 36044dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 36054dab5c37SJack F Vogel 36064dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */ 36074dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 36084dab5c37SJack F Vogel 36094dab5c37SJack F Vogel return E1000_SUCCESS; 36104dab5c37SJack F Vogel } 36114dab5c37SJack F Vogel 36124dab5c37SJack F Vogel /** 36134dab5c37SJack F Vogel * e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock 36144dab5c37SJack F Vogel * @hw: pointer to hardware structure 36154dab5c37SJack F Vogel * @data: data value to write 36164dab5c37SJack F Vogel * 36174dab5c37SJack F Vogel * Clocks out one bit via I2C data/clock 36184dab5c37SJack F Vogel **/ 36194dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data) 36204dab5c37SJack F Vogel { 36214dab5c37SJack F Vogel s32 status; 36224dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 36234dab5c37SJack F Vogel 36244dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_bit"); 36254dab5c37SJack F Vogel 36264dab5c37SJack F Vogel status = e1000_set_i2c_data(hw, &i2cctl, data); 36274dab5c37SJack F Vogel if (status == E1000_SUCCESS) { 36284dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 36294dab5c37SJack F Vogel 36304dab5c37SJack F Vogel /* Minimum high period of clock is 4us */ 36314dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 36324dab5c37SJack F Vogel 36334dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 36344dab5c37SJack F Vogel 36354dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us. 36364dab5c37SJack F Vogel * This also takes care of the data hold time. 36374dab5c37SJack F Vogel */ 36384dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 36394dab5c37SJack F Vogel } else { 36404dab5c37SJack F Vogel status = E1000_ERR_I2C; 36414dab5c37SJack F Vogel DEBUGOUT1("I2C data was not set to %X\n", data); 36424dab5c37SJack F Vogel } 36434dab5c37SJack F Vogel 36444dab5c37SJack F Vogel return status; 36454dab5c37SJack F Vogel } 36464dab5c37SJack F Vogel /** 36474dab5c37SJack F Vogel * e1000_raise_i2c_clk - Raises the I2C SCL clock 36484dab5c37SJack F Vogel * @hw: pointer to hardware structure 36494dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 36504dab5c37SJack F Vogel * 36514dab5c37SJack F Vogel * Raises the I2C clock line '0'->'1' 36524dab5c37SJack F Vogel **/ 36534dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) 36544dab5c37SJack F Vogel { 36554dab5c37SJack F Vogel DEBUGFUNC("e1000_raise_i2c_clk"); 36564dab5c37SJack F Vogel 36574dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OUT; 36584dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N; 36594dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 36604dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 36614dab5c37SJack F Vogel 36624dab5c37SJack F Vogel /* SCL rise time (1000ns) */ 36634dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE); 36644dab5c37SJack F Vogel } 36654dab5c37SJack F Vogel 36664dab5c37SJack F Vogel /** 36674dab5c37SJack F Vogel * e1000_lower_i2c_clk - Lowers the I2C SCL clock 36684dab5c37SJack F Vogel * @hw: pointer to hardware structure 36694dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 36704dab5c37SJack F Vogel * 36714dab5c37SJack F Vogel * Lowers the I2C clock line '1'->'0' 36724dab5c37SJack F Vogel **/ 36734dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl) 36744dab5c37SJack F Vogel { 36754dab5c37SJack F Vogel 36764dab5c37SJack F Vogel DEBUGFUNC("e1000_lower_i2c_clk"); 36774dab5c37SJack F Vogel 36784dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OUT; 36794dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N; 36804dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 36814dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 36824dab5c37SJack F Vogel 36834dab5c37SJack F Vogel /* SCL fall time (300ns) */ 36844dab5c37SJack F Vogel usec_delay(E1000_I2C_T_FALL); 36854dab5c37SJack F Vogel } 36864dab5c37SJack F Vogel 36874dab5c37SJack F Vogel /** 36884dab5c37SJack F Vogel * e1000_set_i2c_data - Sets the I2C data bit 36894dab5c37SJack F Vogel * @hw: pointer to hardware structure 36904dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 36914dab5c37SJack F Vogel * @data: I2C data value (0 or 1) to set 36924dab5c37SJack F Vogel * 36934dab5c37SJack F Vogel * Sets the I2C data bit 36944dab5c37SJack F Vogel **/ 36954dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data) 36964dab5c37SJack F Vogel { 36974dab5c37SJack F Vogel s32 status = E1000_SUCCESS; 36984dab5c37SJack F Vogel 36994dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_data"); 37004dab5c37SJack F Vogel 37014dab5c37SJack F Vogel if (data) 37024dab5c37SJack F Vogel *i2cctl |= E1000_I2C_DATA_OUT; 37034dab5c37SJack F Vogel else 37044dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OUT; 37054dab5c37SJack F Vogel 37064dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OE_N; 37074dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OE_N; 37084dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl); 37094dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw); 37104dab5c37SJack F Vogel 37114dab5c37SJack F Vogel /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */ 37124dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA); 37134dab5c37SJack F Vogel 37144dab5c37SJack F Vogel *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 37154dab5c37SJack F Vogel if (data != e1000_get_i2c_data(i2cctl)) { 37164dab5c37SJack F Vogel status = E1000_ERR_I2C; 37174dab5c37SJack F Vogel DEBUGOUT1("Error - I2C data was not set to %X.\n", data); 37184dab5c37SJack F Vogel } 37194dab5c37SJack F Vogel 37204dab5c37SJack F Vogel return status; 37214dab5c37SJack F Vogel } 37224dab5c37SJack F Vogel 37234dab5c37SJack F Vogel /** 37244dab5c37SJack F Vogel * e1000_get_i2c_data - Reads the I2C SDA data bit 37254dab5c37SJack F Vogel * @hw: pointer to hardware structure 37264dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register 37274dab5c37SJack F Vogel * 37284dab5c37SJack F Vogel * Returns the I2C data bit value 37294dab5c37SJack F Vogel **/ 37304dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl) 37314dab5c37SJack F Vogel { 37324dab5c37SJack F Vogel bool data; 37334dab5c37SJack F Vogel 37344dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_data"); 37354dab5c37SJack F Vogel 37364dab5c37SJack F Vogel if (*i2cctl & E1000_I2C_DATA_IN) 37374dab5c37SJack F Vogel data = 1; 37384dab5c37SJack F Vogel else 37394dab5c37SJack F Vogel data = 0; 37404dab5c37SJack F Vogel 37414dab5c37SJack F Vogel return data; 37424dab5c37SJack F Vogel } 37434dab5c37SJack F Vogel 37444dab5c37SJack F Vogel /** 37454dab5c37SJack F Vogel * e1000_i2c_bus_clear - Clears the I2C bus 37464dab5c37SJack F Vogel * @hw: pointer to hardware structure 37474dab5c37SJack F Vogel * 37484dab5c37SJack F Vogel * Clears the I2C bus by sending nine clock pulses. 37494dab5c37SJack F Vogel * Used when data line is stuck low. 37504dab5c37SJack F Vogel **/ 37514dab5c37SJack F Vogel void e1000_i2c_bus_clear(struct e1000_hw *hw) 37524dab5c37SJack F Vogel { 37534dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS); 37544dab5c37SJack F Vogel u32 i; 37554dab5c37SJack F Vogel 37564dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_bus_clear"); 37574dab5c37SJack F Vogel 37584dab5c37SJack F Vogel e1000_i2c_start(hw); 37594dab5c37SJack F Vogel 37604dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1); 37614dab5c37SJack F Vogel 37624dab5c37SJack F Vogel for (i = 0; i < 9; i++) { 37634dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl); 37644dab5c37SJack F Vogel 37654dab5c37SJack F Vogel /* Min high period of clock is 4us */ 37664dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH); 37674dab5c37SJack F Vogel 37684dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl); 37694dab5c37SJack F Vogel 37704dab5c37SJack F Vogel /* Min low period of clock is 4.7us*/ 37714dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW); 37724dab5c37SJack F Vogel } 37734dab5c37SJack F Vogel 37744dab5c37SJack F Vogel e1000_i2c_start(hw); 37754dab5c37SJack F Vogel 37764dab5c37SJack F Vogel /* Put the i2c bus back to default state */ 37774dab5c37SJack F Vogel e1000_i2c_stop(hw); 37784dab5c37SJack F Vogel } 37794dab5c37SJack F Vogel 3780