18cfa0ad2SJack F Vogel /******************************************************************************
27282444bSPedro F. Giffuni SPDX-License-Identifier: BSD-3-Clause
38cfa0ad2SJack F Vogel
4702cac6cSKevin Bowling Copyright (c) 2001-2020, Intel Corporation
58cfa0ad2SJack F Vogel All rights reserved.
68cfa0ad2SJack F Vogel
78cfa0ad2SJack F Vogel Redistribution and use in source and binary forms, with or without
88cfa0ad2SJack F Vogel modification, are permitted provided that the following conditions are met:
98cfa0ad2SJack F Vogel
108cfa0ad2SJack F Vogel 1. Redistributions of source code must retain the above copyright notice,
118cfa0ad2SJack F Vogel this list of conditions and the following disclaimer.
128cfa0ad2SJack F Vogel
138cfa0ad2SJack F Vogel 2. Redistributions in binary form must reproduce the above copyright
148cfa0ad2SJack F Vogel notice, this list of conditions and the following disclaimer in the
158cfa0ad2SJack F Vogel documentation and/or other materials provided with the distribution.
168cfa0ad2SJack F Vogel
178cfa0ad2SJack F Vogel 3. Neither the name of the Intel Corporation nor the names of its
188cfa0ad2SJack F Vogel contributors may be used to endorse or promote products derived from
198cfa0ad2SJack F Vogel this software without specific prior written permission.
208cfa0ad2SJack F Vogel
218cfa0ad2SJack F Vogel THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
228cfa0ad2SJack F Vogel AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
238cfa0ad2SJack F Vogel IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
248cfa0ad2SJack F Vogel ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
258cfa0ad2SJack F Vogel LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
268cfa0ad2SJack F Vogel CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
278cfa0ad2SJack F Vogel SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
288cfa0ad2SJack F Vogel INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
298cfa0ad2SJack F Vogel CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
308cfa0ad2SJack F Vogel ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
318cfa0ad2SJack F Vogel POSSIBILITY OF SUCH DAMAGE.
328cfa0ad2SJack F Vogel
338cfa0ad2SJack F Vogel ******************************************************************************/
348cfa0ad2SJack F Vogel
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_nvm_82575(struct e1000_hw *hw);
518cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw);
528cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw);
537609433eSJack F Vogel static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw);
548cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw);
558cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
568cfa0ad2SJack F Vogel u16 *duplex);
578cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw);
588cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
598cfa0ad2SJack F Vogel u16 *data);
608cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw);
616b9d35faSGuinan Sun static s32 e1000_init_hw_82575(struct e1000_hw *hw);
624edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw);
634edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw,
644edd8523SJack F Vogel u32 offset, u16 *data);
654edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw,
664edd8523SJack F Vogel u32 offset, u16 data);
67f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw,
68f0ecc46dSJack F Vogel bool active);
69f0ecc46dSJack F Vogel static s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw,
70f0ecc46dSJack F Vogel bool active);
718cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw,
728cfa0ad2SJack F Vogel bool active);
738cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw);
744edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw);
754dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw);
764dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw);
778cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data);
788cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw,
798cfa0ad2SJack F Vogel u32 offset, u16 data);
808cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw);
818cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
828cfa0ad2SJack F Vogel u16 *speed, u16 *duplex);
838cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw);
848cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw);
858cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw);
86a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw);
874edd8523SJack F Vogel static void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw);
88a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw);
899d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw);
907d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw);
91f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw);
92f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw);
93f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw,
94f0ecc46dSJack F Vogel u16 offset);
95f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw,
96f0ecc46dSJack F Vogel u16 offset);
97f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw);
98f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw);
994dab5c37SJack F Vogel static void e1000_clear_vfta_i350(struct e1000_hw *hw);
1008cfa0ad2SJack F Vogel
1014dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw);
1024dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw);
1036c59e186SGuinan Sun static void e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data);
1044dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data);
1054dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw);
1066c59e186SGuinan Sun static void e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data);
1074dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data);
1084dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
1094dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl);
1104dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data);
1114dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl);
1124dab5c37SJack F Vogel
1134dab5c37SJack F Vogel static const u16 e1000_82580_rxpbs_table[] = {
1144dab5c37SJack F Vogel 36, 72, 144, 1, 2, 4, 8, 16, 35, 70, 140 };
1154edd8523SJack F Vogel #define E1000_82580_RXPBS_TABLE_SIZE \
1168cc64f1eSJack F Vogel (sizeof(e1000_82580_rxpbs_table) / \
1178cc64f1eSJack F Vogel sizeof(e1000_82580_rxpbs_table[0]))
1184edd8523SJack F Vogel
1197d9119bdSJack F Vogel
1207d9119bdSJack F Vogel /**
1217d9119bdSJack F Vogel * e1000_sgmii_uses_mdio_82575 - Determine if I2C pins are for external MDIO
1227d9119bdSJack F Vogel * @hw: pointer to the HW structure
1237d9119bdSJack F Vogel *
1247d9119bdSJack F Vogel * Called to determine if the I2C pins are being used for I2C or as an
1257d9119bdSJack F Vogel * external MDIO interface since the two options are mutually exclusive.
1267d9119bdSJack F Vogel **/
e1000_sgmii_uses_mdio_82575(struct e1000_hw * hw)1277d9119bdSJack F Vogel static bool e1000_sgmii_uses_mdio_82575(struct e1000_hw *hw)
1287d9119bdSJack F Vogel {
1297d9119bdSJack F Vogel u32 reg = 0;
1301bbdc25fSKevin Bowling bool ext_mdio = false;
1317d9119bdSJack F Vogel
1327d9119bdSJack F Vogel DEBUGFUNC("e1000_sgmii_uses_mdio_82575");
1337d9119bdSJack F Vogel
1347d9119bdSJack F Vogel switch (hw->mac.type) {
1357d9119bdSJack F Vogel case e1000_82575:
1367d9119bdSJack F Vogel case e1000_82576:
1377d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDIC);
1387d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDIC_DEST);
1397d9119bdSJack F Vogel break;
1407d9119bdSJack F Vogel case e1000_82580:
141f0ecc46dSJack F Vogel case e1000_i350:
1427609433eSJack F Vogel case e1000_i354:
1436ab6bfe3SJack F Vogel case e1000_i210:
1446ab6bfe3SJack F Vogel case e1000_i211:
1457d9119bdSJack F Vogel reg = E1000_READ_REG(hw, E1000_MDICNFG);
1467d9119bdSJack F Vogel ext_mdio = !!(reg & E1000_MDICNFG_EXT_MDIO);
1477d9119bdSJack F Vogel break;
1487d9119bdSJack F Vogel default:
1497d9119bdSJack F Vogel break;
1507d9119bdSJack F Vogel }
1517d9119bdSJack F Vogel return ext_mdio;
1527d9119bdSJack F Vogel }
1537d9119bdSJack F Vogel
1548cfa0ad2SJack F Vogel /**
1556b9d35faSGuinan Sun * e1000_init_phy_params_82575 - Initialize PHY function ptrs
1568cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
1578cfa0ad2SJack F Vogel **/
e1000_init_phy_params_82575(struct e1000_hw * hw)1588cfa0ad2SJack F Vogel static s32 e1000_init_phy_params_82575(struct e1000_hw *hw)
1598cfa0ad2SJack F Vogel {
1608cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy;
1618cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS;
1627d9119bdSJack F Vogel u32 ctrl_ext;
1638cfa0ad2SJack F Vogel
1648cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_phy_params_82575");
1658cfa0ad2SJack F Vogel
166ab5d0362SJack F Vogel phy->ops.read_i2c_byte = e1000_read_i2c_byte_generic;
167ab5d0362SJack F Vogel phy->ops.write_i2c_byte = e1000_write_i2c_byte_generic;
168ab5d0362SJack F Vogel
1698cfa0ad2SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) {
1708cfa0ad2SJack F Vogel phy->type = e1000_phy_none;
1718cfa0ad2SJack F Vogel goto out;
1724edd8523SJack F Vogel }
1734edd8523SJack F Vogel
1748cfa0ad2SJack F Vogel phy->ops.power_up = e1000_power_up_phy_copper;
1756b9d35faSGuinan Sun phy->ops.power_down = e1000_power_down_phy_copper_base;
1768cfa0ad2SJack F Vogel
1778cfa0ad2SJack F Vogel phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
1788cfa0ad2SJack F Vogel phy->reset_delay_us = 100;
1798cfa0ad2SJack F Vogel
1806b9d35faSGuinan Sun phy->ops.acquire = e1000_acquire_phy_base;
1818cfa0ad2SJack F Vogel phy->ops.check_reset_block = e1000_check_reset_block_generic;
1828cfa0ad2SJack F Vogel phy->ops.commit = e1000_phy_sw_reset_generic;
1838cfa0ad2SJack F Vogel phy->ops.get_cfg_done = e1000_get_cfg_done_82575;
1846b9d35faSGuinan Sun phy->ops.release = e1000_release_phy_base;
1858cfa0ad2SJack F Vogel
1867d9119bdSJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
1877d9119bdSJack F Vogel
1888cfa0ad2SJack F Vogel if (e1000_sgmii_active_82575(hw)) {
1898cfa0ad2SJack F Vogel phy->ops.reset = e1000_phy_hw_reset_sgmii_82575;
1907d9119bdSJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA;
1917d9119bdSJack F Vogel } else {
1927d9119bdSJack F Vogel phy->ops.reset = e1000_phy_hw_reset_generic;
1937d9119bdSJack F Vogel ctrl_ext &= ~E1000_CTRL_I2C_ENA;
1947d9119bdSJack F Vogel }
1957d9119bdSJack F Vogel
1967d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
1977d9119bdSJack F Vogel e1000_reset_mdicnfg_82580(hw);
1987d9119bdSJack F Vogel
1997d9119bdSJack F Vogel if (e1000_sgmii_active_82575(hw) && !e1000_sgmii_uses_mdio_82575(hw)) {
2008cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_sgmii_82575;
2018cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_sgmii_82575;
202ab5d0362SJack F Vogel } else {
203ab5d0362SJack F Vogel switch (hw->mac.type) {
204ab5d0362SJack F Vogel case e1000_82580:
205ab5d0362SJack F Vogel case e1000_i350:
2067609433eSJack F Vogel case e1000_i354:
2074edd8523SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_82580;
2084edd8523SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_82580;
209ab5d0362SJack F Vogel break;
210ab5d0362SJack F Vogel case e1000_i210:
211ab5d0362SJack F Vogel case e1000_i211:
212ab5d0362SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_gs40g;
213ab5d0362SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_gs40g;
214ab5d0362SJack F Vogel break;
215ab5d0362SJack F Vogel default:
2168cfa0ad2SJack F Vogel phy->ops.read_reg = e1000_read_phy_reg_igp;
2178cfa0ad2SJack F Vogel phy->ops.write_reg = e1000_write_phy_reg_igp;
2188cfa0ad2SJack F Vogel }
219ab5d0362SJack F Vogel }
2208cfa0ad2SJack F Vogel
2218cfa0ad2SJack F Vogel /* Set phy->phy_addr and phy->id. */
2228cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id_82575(hw);
2238cfa0ad2SJack F Vogel
2248cfa0ad2SJack F Vogel /* Verify phy id and set remaining function pointers */
2258cfa0ad2SJack F Vogel switch (phy->id) {
2267609433eSJack F Vogel case M88E1543_E_PHY_ID:
2277609433eSJack F Vogel case M88E1512_E_PHY_ID:
228f0ecc46dSJack F Vogel case I347AT4_E_PHY_ID:
229f0ecc46dSJack F Vogel case M88E1112_E_PHY_ID:
2301fd3c44fSJack F Vogel case M88E1340M_E_PHY_ID:
2316b9d35faSGuinan Sun phy->type = e1000_phy_m88;
2326b9d35faSGuinan Sun phy->ops.check_polarity = e1000_check_polarity_m88;
2336b9d35faSGuinan Sun phy->ops.get_info = e1000_get_phy_info_m88;
2346b9d35faSGuinan Sun phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
2356b9d35faSGuinan Sun phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
2366b9d35faSGuinan Sun break;
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;
2418cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88;
2428cfa0ad2SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
2438cfa0ad2SJack F Vogel break;
2448cfa0ad2SJack F Vogel case IGP03E1000_E_PHY_ID:
2458cfa0ad2SJack F Vogel case IGP04E1000_E_PHY_ID:
2468cfa0ad2SJack F Vogel phy->type = e1000_phy_igp_3;
2478cfa0ad2SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_igp;
2488cfa0ad2SJack F Vogel phy->ops.get_info = e1000_get_phy_info_igp;
2498cfa0ad2SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
2508cfa0ad2SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82575;
2518cfa0ad2SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_generic;
2526b9d35faSGuinan Sun phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
2538cfa0ad2SJack F Vogel break;
2544edd8523SJack F Vogel case I82580_I_PHY_ID:
255f0ecc46dSJack F Vogel case I350_I_PHY_ID:
2564edd8523SJack F Vogel phy->type = e1000_phy_82580;
2574edd8523SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_82577;
2584edd8523SJack F Vogel phy->ops.get_info = e1000_get_phy_info_82577;
2596b9d35faSGuinan Sun phy->ops.get_cable_length = e1000_get_cable_length_82577;
260f0ecc46dSJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
261f0ecc46dSJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
2626b9d35faSGuinan Sun phy->ops.force_speed_duplex =
2636b9d35faSGuinan Sun e1000_phy_force_speed_duplex_82577;
2644edd8523SJack F Vogel break;
265ab5d0362SJack F Vogel case I210_I_PHY_ID:
266ab5d0362SJack F Vogel phy->type = e1000_phy_i210;
267ab5d0362SJack F Vogel phy->ops.check_polarity = e1000_check_polarity_m88;
268ab5d0362SJack F Vogel phy->ops.get_info = e1000_get_phy_info_m88;
269ab5d0362SJack F Vogel phy->ops.get_cable_length = e1000_get_cable_length_m88_gen2;
270ab5d0362SJack F Vogel phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_82580;
271ab5d0362SJack F Vogel phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82580;
272ab5d0362SJack F Vogel phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
273ab5d0362SJack F Vogel break;
2748cfa0ad2SJack F Vogel default:
2758cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY;
2768cfa0ad2SJack F Vogel goto out;
2778cfa0ad2SJack F Vogel }
2788cfa0ad2SJack F Vogel
2796b9d35faSGuinan Sun /* Check if this PHY is configured for media swap. */
2806b9d35faSGuinan Sun switch (phy->id) {
2816b9d35faSGuinan Sun case M88E1112_E_PHY_ID:
2826b9d35faSGuinan Sun {
2836b9d35faSGuinan Sun u16 data;
2846b9d35faSGuinan Sun
2856b9d35faSGuinan Sun ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 2);
2866b9d35faSGuinan Sun if (ret_val)
2876b9d35faSGuinan Sun goto out;
2886b9d35faSGuinan Sun ret_val = phy->ops.read_reg(hw, E1000_M88E1112_MAC_CTRL_1,
2896b9d35faSGuinan Sun &data);
2906b9d35faSGuinan Sun if (ret_val)
2916b9d35faSGuinan Sun goto out;
2926b9d35faSGuinan Sun
2936b9d35faSGuinan Sun data = (data & E1000_M88E1112_MAC_CTRL_1_MODE_MASK) >>
2946b9d35faSGuinan Sun E1000_M88E1112_MAC_CTRL_1_MODE_SHIFT;
2956b9d35faSGuinan Sun if (data == E1000_M88E1112_AUTO_COPPER_SGMII ||
2966b9d35faSGuinan Sun data == E1000_M88E1112_AUTO_COPPER_BASEX)
2976b9d35faSGuinan Sun hw->mac.ops.check_for_link =
2986b9d35faSGuinan Sun e1000_check_for_link_media_swap;
2996b9d35faSGuinan Sun break;
3006b9d35faSGuinan Sun }
3016b9d35faSGuinan Sun case M88E1512_E_PHY_ID:
3026b9d35faSGuinan Sun {
3036b9d35faSGuinan Sun ret_val = e1000_initialize_M88E1512_phy(hw);
3046b9d35faSGuinan Sun break;
3056b9d35faSGuinan Sun }
3066b9d35faSGuinan Sun case M88E1543_E_PHY_ID:
3076b9d35faSGuinan Sun {
3086b9d35faSGuinan Sun ret_val = e1000_initialize_M88E1543_phy(hw);
3096b9d35faSGuinan Sun break;
3106b9d35faSGuinan Sun }
3116b9d35faSGuinan Sun default:
3126b9d35faSGuinan Sun goto out;
3136b9d35faSGuinan Sun }
3146b9d35faSGuinan Sun
3158cfa0ad2SJack F Vogel out:
3168cfa0ad2SJack F Vogel return ret_val;
3178cfa0ad2SJack F Vogel }
3188cfa0ad2SJack F Vogel
3198cfa0ad2SJack F Vogel /**
3206b9d35faSGuinan Sun * e1000_init_mac_params_82575 - Init MAC func ptrs.
3216b9d35faSGuinan Sun * @hw: pointer to the HW structure
3226b9d35faSGuinan Sun **/
e1000_init_mac_params_82575(struct e1000_hw * hw)3236b9d35faSGuinan Sun static s32 e1000_init_mac_params_82575(struct e1000_hw *hw)
3246b9d35faSGuinan Sun {
3256b9d35faSGuinan Sun struct e1000_mac_info *mac = &hw->mac;
3266b9d35faSGuinan Sun struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
3276b9d35faSGuinan Sun
3286b9d35faSGuinan Sun DEBUGFUNC("e1000_init_mac_params_82575");
3296b9d35faSGuinan Sun
3306b9d35faSGuinan Sun /* Initialize function pointer */
3316b9d35faSGuinan Sun e1000_init_mac_ops_generic(hw);
3326b9d35faSGuinan Sun
3336b9d35faSGuinan Sun /* Derives media type */
3346b9d35faSGuinan Sun e1000_get_media_type_82575(hw);
3356b9d35faSGuinan Sun /* Set MTA register count */
3366b9d35faSGuinan Sun mac->mta_reg_count = 128;
3376b9d35faSGuinan Sun /* Set UTA register count */
3386b9d35faSGuinan Sun mac->uta_reg_count = (hw->mac.type == e1000_82575) ? 0 : 128;
3396b9d35faSGuinan Sun /* Set RAR entry count */
3406b9d35faSGuinan Sun mac->rar_entry_count = E1000_RAR_ENTRIES_82575;
3416b9d35faSGuinan Sun if (mac->type == e1000_82576)
3426b9d35faSGuinan Sun mac->rar_entry_count = E1000_RAR_ENTRIES_82576;
3436b9d35faSGuinan Sun if (mac->type == e1000_82580)
3446b9d35faSGuinan Sun mac->rar_entry_count = E1000_RAR_ENTRIES_82580;
3456b9d35faSGuinan Sun if (mac->type == e1000_i350 || mac->type == e1000_i354)
3466b9d35faSGuinan Sun mac->rar_entry_count = E1000_RAR_ENTRIES_I350;
3476b9d35faSGuinan Sun
3486b9d35faSGuinan Sun /* Enable EEE default settings for EEE supported devices */
3496b9d35faSGuinan Sun if (mac->type >= e1000_i350)
3501bbdc25fSKevin Bowling dev_spec->eee_disable = false;
3516b9d35faSGuinan Sun
3526b9d35faSGuinan Sun /* Allow a single clear of the SW semaphore on I210 and newer */
3536b9d35faSGuinan Sun if (mac->type >= e1000_i210)
3541bbdc25fSKevin Bowling dev_spec->clear_semaphore_once = true;
3556b9d35faSGuinan Sun
3566b9d35faSGuinan Sun /* Set if part includes ASF firmware */
3571bbdc25fSKevin Bowling mac->asf_firmware_present = true;
3586b9d35faSGuinan Sun /* FWSM register */
3591bbdc25fSKevin Bowling mac->has_fwsm = true;
3606b9d35faSGuinan Sun /* ARC supported; valid only if manageability features are enabled. */
3616b9d35faSGuinan Sun mac->arc_subsystem_valid =
3626b9d35faSGuinan Sun !!(E1000_READ_REG(hw, E1000_FWSM) & E1000_FWSM_MODE_MASK);
3636b9d35faSGuinan Sun
3646b9d35faSGuinan Sun /* Function pointers */
3656b9d35faSGuinan Sun
3666b9d35faSGuinan Sun /* bus type/speed/width */
3676b9d35faSGuinan Sun mac->ops.get_bus_info = e1000_get_bus_info_pcie_generic;
3686b9d35faSGuinan Sun /* reset */
3696b9d35faSGuinan Sun if (mac->type >= e1000_82580)
3706b9d35faSGuinan Sun mac->ops.reset_hw = e1000_reset_hw_82580;
3716b9d35faSGuinan Sun else
3726b9d35faSGuinan Sun mac->ops.reset_hw = e1000_reset_hw_82575;
3736b9d35faSGuinan Sun /* HW initialization */
3746b9d35faSGuinan Sun if ((mac->type == e1000_i210) || (mac->type == e1000_i211))
3756b9d35faSGuinan Sun mac->ops.init_hw = e1000_init_hw_i210;
3766b9d35faSGuinan Sun else
3776b9d35faSGuinan Sun mac->ops.init_hw = e1000_init_hw_82575;
3786b9d35faSGuinan Sun /* link setup */
3796b9d35faSGuinan Sun mac->ops.setup_link = e1000_setup_link_generic;
3806b9d35faSGuinan Sun /* physical interface link setup */
3816b9d35faSGuinan Sun mac->ops.setup_physical_interface =
3826b9d35faSGuinan Sun (hw->phy.media_type == e1000_media_type_copper)
3836b9d35faSGuinan Sun ? e1000_setup_copper_link_82575 : e1000_setup_serdes_link_82575;
3846b9d35faSGuinan Sun /* physical interface shutdown */
3856b9d35faSGuinan Sun mac->ops.shutdown_serdes = e1000_shutdown_serdes_link_82575;
3866b9d35faSGuinan Sun /* physical interface power up */
3876b9d35faSGuinan Sun mac->ops.power_up_serdes = e1000_power_up_serdes_link_82575;
3886b9d35faSGuinan Sun /* check for link */
3896b9d35faSGuinan Sun mac->ops.check_for_link = e1000_check_for_link_82575;
3906b9d35faSGuinan Sun /* read mac address */
3916b9d35faSGuinan Sun mac->ops.read_mac_addr = e1000_read_mac_addr_82575;
3926b9d35faSGuinan Sun /* configure collision distance */
3936b9d35faSGuinan Sun mac->ops.config_collision_dist = e1000_config_collision_dist_82575;
3946b9d35faSGuinan Sun /* multicast address update */
3956b9d35faSGuinan Sun mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
3966b9d35faSGuinan Sun if (hw->mac.type == e1000_i350 || mac->type == e1000_i354) {
3976b9d35faSGuinan Sun /* writing VFTA */
3986b9d35faSGuinan Sun mac->ops.write_vfta = e1000_write_vfta_i350;
3996b9d35faSGuinan Sun /* clearing VFTA */
4006b9d35faSGuinan Sun mac->ops.clear_vfta = e1000_clear_vfta_i350;
4016b9d35faSGuinan Sun } else {
4026b9d35faSGuinan Sun /* writing VFTA */
4036b9d35faSGuinan Sun mac->ops.write_vfta = e1000_write_vfta_generic;
4046b9d35faSGuinan Sun /* clearing VFTA */
4056b9d35faSGuinan Sun mac->ops.clear_vfta = e1000_clear_vfta_generic;
4066b9d35faSGuinan Sun }
4076b9d35faSGuinan Sun if (hw->mac.type >= e1000_82580)
4086b9d35faSGuinan Sun mac->ops.validate_mdi_setting =
4096b9d35faSGuinan Sun e1000_validate_mdi_setting_crossover_generic;
4106b9d35faSGuinan Sun /* ID LED init */
4116b9d35faSGuinan Sun mac->ops.id_led_init = e1000_id_led_init_generic;
4126b9d35faSGuinan Sun /* blink LED */
4136b9d35faSGuinan Sun mac->ops.blink_led = e1000_blink_led_generic;
4146b9d35faSGuinan Sun /* setup LED */
4156b9d35faSGuinan Sun mac->ops.setup_led = e1000_setup_led_generic;
4166b9d35faSGuinan Sun /* cleanup LED */
4176b9d35faSGuinan Sun mac->ops.cleanup_led = e1000_cleanup_led_generic;
4186b9d35faSGuinan Sun /* turn on/off LED */
4196b9d35faSGuinan Sun mac->ops.led_on = e1000_led_on_generic;
4206b9d35faSGuinan Sun mac->ops.led_off = e1000_led_off_generic;
4216b9d35faSGuinan Sun /* clear hardware counters */
4226b9d35faSGuinan Sun mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82575;
4236b9d35faSGuinan Sun /* link info */
4246b9d35faSGuinan Sun mac->ops.get_link_up_info = e1000_get_link_up_info_82575;
4256b9d35faSGuinan Sun /* acquire SW_FW sync */
4266b9d35faSGuinan Sun mac->ops.acquire_swfw_sync = e1000_acquire_swfw_sync;
4276b9d35faSGuinan Sun /* release SW_FW sync */
4286b9d35faSGuinan Sun mac->ops.release_swfw_sync = e1000_release_swfw_sync;
4296b9d35faSGuinan Sun
4306b9d35faSGuinan Sun /* set lan id for port to determine which phy lock to use */
4316b9d35faSGuinan Sun hw->mac.ops.set_lan_id(hw);
4326b9d35faSGuinan Sun
4336b9d35faSGuinan Sun return E1000_SUCCESS;
4346b9d35faSGuinan Sun }
4356b9d35faSGuinan Sun
4366b9d35faSGuinan Sun /**
4376b9d35faSGuinan Sun * e1000_init_nvm_params_82575 - Initialize NVM function ptrs
4388cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
4398cfa0ad2SJack F Vogel **/
e1000_init_nvm_params_82575(struct e1000_hw * hw)4401fd3c44fSJack F Vogel s32 e1000_init_nvm_params_82575(struct e1000_hw *hw)
4418cfa0ad2SJack F Vogel {
4428cfa0ad2SJack F Vogel struct e1000_nvm_info *nvm = &hw->nvm;
4438cfa0ad2SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD);
4448cfa0ad2SJack F Vogel u16 size;
4458cfa0ad2SJack F Vogel
4468cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_nvm_params_82575");
4478cfa0ad2SJack F Vogel
448f0ecc46dSJack F Vogel size = (u16)((eecd & E1000_EECD_SIZE_EX_MASK) >>
449f0ecc46dSJack F Vogel E1000_EECD_SIZE_EX_SHIFT);
4506b9d35faSGuinan Sun /* Added to a constant, "size" becomes the left-shift value
451f0ecc46dSJack F Vogel * for setting word_size.
452f0ecc46dSJack F Vogel */
453f0ecc46dSJack F Vogel size += NVM_WORD_SIZE_BASE_SHIFT;
454f0ecc46dSJack F Vogel
4554dab5c37SJack F Vogel /* Just in case size is out of range, cap it to the largest
4564dab5c37SJack F Vogel * EEPROM size supported
4574dab5c37SJack F Vogel */
4584dab5c37SJack F Vogel if (size > 15)
4594dab5c37SJack F Vogel size = 15;
4604dab5c37SJack F Vogel
461f0ecc46dSJack F Vogel nvm->word_size = 1 << size;
462ab5d0362SJack F Vogel if (hw->mac.type < e1000_i210) {
4638cfa0ad2SJack F Vogel nvm->opcode_bits = 8;
4648cfa0ad2SJack F Vogel nvm->delay_usec = 1;
465ab5d0362SJack F Vogel
4668cfa0ad2SJack F Vogel switch (nvm->override) {
4678cfa0ad2SJack F Vogel case e1000_nvm_override_spi_large:
4688cfa0ad2SJack F Vogel nvm->page_size = 32;
4698cfa0ad2SJack F Vogel nvm->address_bits = 16;
4708cfa0ad2SJack F Vogel break;
4718cfa0ad2SJack F Vogel case e1000_nvm_override_spi_small:
4728cfa0ad2SJack F Vogel nvm->page_size = 8;
4738cfa0ad2SJack F Vogel nvm->address_bits = 8;
4748cfa0ad2SJack F Vogel break;
4758cfa0ad2SJack F Vogel default:
4768cfa0ad2SJack F Vogel nvm->page_size = eecd & E1000_EECD_ADDR_BITS ? 32 : 8;
477ab5d0362SJack F Vogel nvm->address_bits = eecd & E1000_EECD_ADDR_BITS ?
478ab5d0362SJack F Vogel 16 : 8;
4798cfa0ad2SJack F Vogel break;
4808cfa0ad2SJack F Vogel }
4811fd3c44fSJack F Vogel if (nvm->word_size == (1 << 15))
482f0ecc46dSJack F Vogel nvm->page_size = 128;
4838cfa0ad2SJack F Vogel
484ab5d0362SJack F Vogel nvm->type = e1000_nvm_eeprom_spi;
485ab5d0362SJack F Vogel } else {
486ab5d0362SJack F Vogel nvm->type = e1000_nvm_flash_hw;
487ab5d0362SJack F Vogel }
4886ab6bfe3SJack F Vogel
4898cfa0ad2SJack F Vogel /* Function Pointers */
4908cfa0ad2SJack F Vogel nvm->ops.acquire = e1000_acquire_nvm_82575;
4918cfa0ad2SJack F Vogel nvm->ops.release = e1000_release_nvm_82575;
4921fd3c44fSJack F Vogel if (nvm->word_size < (1 << 15))
4931fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_eerd;
4941fd3c44fSJack F Vogel else
4951fd3c44fSJack F Vogel nvm->ops.read = e1000_read_nvm_spi;
4961fd3c44fSJack F Vogel
4971fd3c44fSJack F Vogel nvm->ops.write = e1000_write_nvm_spi;
4981fd3c44fSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_generic;
4991fd3c44fSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_generic;
5008cfa0ad2SJack F Vogel nvm->ops.valid_led_default = e1000_valid_led_default_82575;
5011fd3c44fSJack F Vogel
502ab5d0362SJack F Vogel /* override generic family function pointers for specific descendants */
503f0ecc46dSJack F Vogel switch (hw->mac.type) {
504f0ecc46dSJack F Vogel case e1000_82580:
505f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_82580;
506f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_82580;
507f0ecc46dSJack F Vogel break;
508f0ecc46dSJack F Vogel case e1000_i350:
509f0ecc46dSJack F Vogel nvm->ops.validate = e1000_validate_nvm_checksum_i350;
510f0ecc46dSJack F Vogel nvm->ops.update = e1000_update_nvm_checksum_i350;
511f0ecc46dSJack F Vogel break;
512f0ecc46dSJack F Vogel default:
5131fd3c44fSJack F Vogel break;
514f0ecc46dSJack F Vogel }
5158cfa0ad2SJack F Vogel
5168cfa0ad2SJack F Vogel return E1000_SUCCESS;
5178cfa0ad2SJack F Vogel }
5188cfa0ad2SJack F Vogel
5198cfa0ad2SJack F Vogel /**
5208cfa0ad2SJack F Vogel * e1000_init_function_pointers_82575 - Init func ptrs.
5218cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
5228cfa0ad2SJack F Vogel *
523daf9197cSJack F Vogel * Called to initialize all function pointers and parameters.
5248cfa0ad2SJack F Vogel **/
e1000_init_function_pointers_82575(struct e1000_hw * hw)5258cfa0ad2SJack F Vogel void e1000_init_function_pointers_82575(struct e1000_hw *hw)
5268cfa0ad2SJack F Vogel {
5278cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_function_pointers_82575");
5288cfa0ad2SJack F Vogel
5298cfa0ad2SJack F Vogel hw->mac.ops.init_params = e1000_init_mac_params_82575;
5308cfa0ad2SJack F Vogel hw->nvm.ops.init_params = e1000_init_nvm_params_82575;
5318cfa0ad2SJack F Vogel hw->phy.ops.init_params = e1000_init_phy_params_82575;
5327d9119bdSJack F Vogel hw->mbx.ops.init_params = e1000_init_mbx_params_pf;
5338cfa0ad2SJack F Vogel }
5348cfa0ad2SJack F Vogel
5358cfa0ad2SJack F Vogel /**
5368cfa0ad2SJack F Vogel * e1000_read_phy_reg_sgmii_82575 - Read PHY register using sgmii
5378cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
5388cfa0ad2SJack F Vogel * @offset: register offset to be read
5398cfa0ad2SJack F Vogel * @data: pointer to the read data
5408cfa0ad2SJack F Vogel *
5418cfa0ad2SJack F Vogel * Reads the PHY register at offset using the serial gigabit media independent
5428cfa0ad2SJack F Vogel * interface and stores the retrieved information in data.
5438cfa0ad2SJack F Vogel **/
e1000_read_phy_reg_sgmii_82575(struct e1000_hw * hw,u32 offset,u16 * data)5448cfa0ad2SJack F Vogel static s32 e1000_read_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
5458cfa0ad2SJack F Vogel u16 *data)
5468cfa0ad2SJack F Vogel {
5474edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM;
5488cfa0ad2SJack F Vogel
5498cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_sgmii_82575");
5508cfa0ad2SJack F Vogel
5518cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
5528cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %u is out of range\n", offset);
5534edd8523SJack F Vogel goto out;
5548cfa0ad2SJack F Vogel }
5558cfa0ad2SJack F Vogel
5564edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw);
5574edd8523SJack F Vogel if (ret_val)
5584edd8523SJack F Vogel goto out;
5598cfa0ad2SJack F Vogel
5604edd8523SJack F Vogel ret_val = e1000_read_phy_reg_i2c(hw, offset, data);
5618cfa0ad2SJack F Vogel
5624edd8523SJack F Vogel hw->phy.ops.release(hw);
5638cfa0ad2SJack F Vogel
5644edd8523SJack F Vogel out:
5654edd8523SJack F Vogel return ret_val;
5668cfa0ad2SJack F Vogel }
5678cfa0ad2SJack F Vogel
5688cfa0ad2SJack F Vogel /**
5698cfa0ad2SJack F Vogel * e1000_write_phy_reg_sgmii_82575 - Write PHY register using sgmii
5708cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
5718cfa0ad2SJack F Vogel * @offset: register offset to write to
5728cfa0ad2SJack F Vogel * @data: data to write at register offset
5738cfa0ad2SJack F Vogel *
5748cfa0ad2SJack F Vogel * Writes the data to PHY register at the offset using the serial gigabit
5758cfa0ad2SJack F Vogel * media independent interface.
5768cfa0ad2SJack F Vogel **/
e1000_write_phy_reg_sgmii_82575(struct e1000_hw * hw,u32 offset,u16 data)5778cfa0ad2SJack F Vogel static s32 e1000_write_phy_reg_sgmii_82575(struct e1000_hw *hw, u32 offset,
5788cfa0ad2SJack F Vogel u16 data)
5798cfa0ad2SJack F Vogel {
5804edd8523SJack F Vogel s32 ret_val = -E1000_ERR_PARAM;
5818cfa0ad2SJack F Vogel
5828cfa0ad2SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_sgmii_82575");
5838cfa0ad2SJack F Vogel
5848cfa0ad2SJack F Vogel if (offset > E1000_MAX_SGMII_PHY_REG_ADDR) {
5858cfa0ad2SJack F Vogel DEBUGOUT1("PHY Address %d is out of range\n", offset);
5864edd8523SJack F Vogel goto out;
5878cfa0ad2SJack F Vogel }
5888cfa0ad2SJack F Vogel
5894edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw);
5904edd8523SJack F Vogel if (ret_val)
5914edd8523SJack F Vogel goto out;
5928cfa0ad2SJack F Vogel
5934edd8523SJack F Vogel ret_val = e1000_write_phy_reg_i2c(hw, offset, data);
5948cfa0ad2SJack F Vogel
5954edd8523SJack F Vogel hw->phy.ops.release(hw);
5968cfa0ad2SJack F Vogel
5974edd8523SJack F Vogel out:
5984edd8523SJack F Vogel return ret_val;
5998cfa0ad2SJack F Vogel }
6008cfa0ad2SJack F Vogel
6018cfa0ad2SJack F Vogel /**
6028cfa0ad2SJack F Vogel * e1000_get_phy_id_82575 - Retrieve PHY addr and id
6038cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
6048cfa0ad2SJack F Vogel *
6058cfa0ad2SJack F Vogel * Retrieves the PHY address and ID for both PHY's which do and do not use
6068cfa0ad2SJack F Vogel * sgmi interface.
6078cfa0ad2SJack F Vogel **/
e1000_get_phy_id_82575(struct e1000_hw * hw)6088cfa0ad2SJack F Vogel static s32 e1000_get_phy_id_82575(struct e1000_hw *hw)
6098cfa0ad2SJack F Vogel {
6108cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy;
6118cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS;
6128cfa0ad2SJack F Vogel u16 phy_id;
6134edd8523SJack F Vogel u32 ctrl_ext;
6147d9119bdSJack F Vogel u32 mdic;
6158cfa0ad2SJack F Vogel
6168cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_phy_id_82575");
6178cfa0ad2SJack F Vogel
6187609433eSJack F Vogel /* some i354 devices need an extra read for phy id */
6197609433eSJack F Vogel if (hw->mac.type == e1000_i354)
6207609433eSJack F Vogel e1000_get_phy_id(hw);
6217609433eSJack F Vogel
6228cfa0ad2SJack F Vogel /*
6238cfa0ad2SJack F Vogel * For SGMII PHYs, we try the list of possible addresses until
6248cfa0ad2SJack F Vogel * we find one that works. For non-SGMII PHYs
6258cfa0ad2SJack F Vogel * (e.g. integrated copper PHYs), an address of 1 should
6268cfa0ad2SJack F Vogel * work. The result of this function should mean phy->phy_addr
6278cfa0ad2SJack F Vogel * and phy->id are set correctly.
6288cfa0ad2SJack F Vogel */
6294edd8523SJack F Vogel if (!e1000_sgmii_active_82575(hw)) {
6308cfa0ad2SJack F Vogel phy->addr = 1;
6318cfa0ad2SJack F Vogel ret_val = e1000_get_phy_id(hw);
6328cfa0ad2SJack F Vogel goto out;
6338cfa0ad2SJack F Vogel }
6348cfa0ad2SJack F Vogel
6357d9119bdSJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) {
6367d9119bdSJack F Vogel switch (hw->mac.type) {
6377d9119bdSJack F Vogel case e1000_82575:
6387d9119bdSJack F Vogel case e1000_82576:
6397d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDIC);
6407d9119bdSJack F Vogel mdic &= E1000_MDIC_PHY_MASK;
6417d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDIC_PHY_SHIFT;
6427d9119bdSJack F Vogel break;
6437d9119bdSJack F Vogel case e1000_82580:
644f0ecc46dSJack F Vogel case e1000_i350:
6457609433eSJack F Vogel case e1000_i354:
6466ab6bfe3SJack F Vogel case e1000_i210:
6476ab6bfe3SJack F Vogel case e1000_i211:
6487d9119bdSJack F Vogel mdic = E1000_READ_REG(hw, E1000_MDICNFG);
6497d9119bdSJack F Vogel mdic &= E1000_MDICNFG_PHY_MASK;
6507d9119bdSJack F Vogel phy->addr = mdic >> E1000_MDICNFG_PHY_SHIFT;
6517d9119bdSJack F Vogel break;
6527d9119bdSJack F Vogel default:
6537d9119bdSJack F Vogel ret_val = -E1000_ERR_PHY;
6547d9119bdSJack F Vogel goto out;
6557d9119bdSJack F Vogel break;
6567d9119bdSJack F Vogel }
6577d9119bdSJack F Vogel ret_val = e1000_get_phy_id(hw);
6587d9119bdSJack F Vogel goto out;
6597d9119bdSJack F Vogel }
6607d9119bdSJack F Vogel
6614edd8523SJack F Vogel /* Power on sgmii phy if it is disabled */
6624edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
6634edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT,
6644edd8523SJack F Vogel ctrl_ext & ~E1000_CTRL_EXT_SDP3_DATA);
6654edd8523SJack F Vogel E1000_WRITE_FLUSH(hw);
6664edd8523SJack F Vogel msec_delay(300);
6674edd8523SJack F Vogel
6688cfa0ad2SJack F Vogel /*
6698cfa0ad2SJack F Vogel * The address field in the I2CCMD register is 3 bits and 0 is invalid.
6708cfa0ad2SJack F Vogel * Therefore, we need to test 1-7
6718cfa0ad2SJack F Vogel */
6728cfa0ad2SJack F Vogel for (phy->addr = 1; phy->addr < 8; phy->addr++) {
6738cfa0ad2SJack F Vogel ret_val = e1000_read_phy_reg_sgmii_82575(hw, PHY_ID1, &phy_id);
6748cfa0ad2SJack F Vogel if (ret_val == E1000_SUCCESS) {
6758cfa0ad2SJack F Vogel DEBUGOUT2("Vendor ID 0x%08X read at address %u\n",
6764dab5c37SJack F Vogel phy_id, phy->addr);
6778cfa0ad2SJack F Vogel /*
6788cfa0ad2SJack F Vogel * At the time of this writing, The M88 part is
6798cfa0ad2SJack F Vogel * the only supported SGMII PHY product.
6808cfa0ad2SJack F Vogel */
6818cfa0ad2SJack F Vogel if (phy_id == M88_VENDOR)
6828cfa0ad2SJack F Vogel break;
6838cfa0ad2SJack F Vogel } else {
6848cfa0ad2SJack F Vogel DEBUGOUT1("PHY address %u was unreadable\n",
6858cfa0ad2SJack F Vogel phy->addr);
6868cfa0ad2SJack F Vogel }
6878cfa0ad2SJack F Vogel }
6888cfa0ad2SJack F Vogel
6898cfa0ad2SJack F Vogel /* A valid PHY type couldn't be found. */
6908cfa0ad2SJack F Vogel if (phy->addr == 8) {
6918cfa0ad2SJack F Vogel phy->addr = 0;
6928cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY;
6934edd8523SJack F Vogel } else {
6944edd8523SJack F Vogel ret_val = e1000_get_phy_id(hw);
6958cfa0ad2SJack F Vogel }
6968cfa0ad2SJack F Vogel
6974edd8523SJack F Vogel /* restore previous sfp cage power state */
6984edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
6998cfa0ad2SJack F Vogel
7008cfa0ad2SJack F Vogel out:
7018cfa0ad2SJack F Vogel return ret_val;
7028cfa0ad2SJack F Vogel }
7038cfa0ad2SJack F Vogel
7048cfa0ad2SJack F Vogel /**
7058cfa0ad2SJack F Vogel * e1000_phy_hw_reset_sgmii_82575 - Performs a PHY reset
7068cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
7078cfa0ad2SJack F Vogel *
7088cfa0ad2SJack F Vogel * Resets the PHY using the serial gigabit media independent interface.
7098cfa0ad2SJack F Vogel **/
e1000_phy_hw_reset_sgmii_82575(struct e1000_hw * hw)7108cfa0ad2SJack F Vogel static s32 e1000_phy_hw_reset_sgmii_82575(struct e1000_hw *hw)
7118cfa0ad2SJack F Vogel {
7128cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS;
7138cc64f1eSJack F Vogel struct e1000_phy_info *phy = &hw->phy;
7148cfa0ad2SJack F Vogel
7158cfa0ad2SJack F Vogel DEBUGFUNC("e1000_phy_hw_reset_sgmii_82575");
7168cfa0ad2SJack F Vogel
7178cfa0ad2SJack F Vogel /*
7181bbdc25fSKevin Bowling * This isn't a true "hard" reset, but is the only reset
7198cfa0ad2SJack F Vogel * available to us at this time.
7208cfa0ad2SJack F Vogel */
7218cfa0ad2SJack F Vogel
7228cfa0ad2SJack F Vogel DEBUGOUT("Soft resetting SGMII attached PHY...\n");
7238cfa0ad2SJack F Vogel
7248cfa0ad2SJack F Vogel if (!(hw->phy.ops.write_reg))
7258cfa0ad2SJack F Vogel goto out;
7268cfa0ad2SJack F Vogel
7278cfa0ad2SJack F Vogel /*
7288cfa0ad2SJack F Vogel * SFP documentation requires the following to configure the SPF module
7298cfa0ad2SJack F Vogel * to work on SGMII. No further documentation is given.
7308cfa0ad2SJack F Vogel */
7318cfa0ad2SJack F Vogel ret_val = hw->phy.ops.write_reg(hw, 0x1B, 0x8084);
7328cfa0ad2SJack F Vogel if (ret_val)
7338cfa0ad2SJack F Vogel goto out;
7348cfa0ad2SJack F Vogel
7358cfa0ad2SJack F Vogel ret_val = hw->phy.ops.commit(hw);
7368cc64f1eSJack F Vogel if (ret_val)
7378cc64f1eSJack F Vogel goto out;
7388cfa0ad2SJack F Vogel
7398cc64f1eSJack F Vogel if (phy->id == M88E1512_E_PHY_ID)
7408cc64f1eSJack F Vogel ret_val = e1000_initialize_M88E1512_phy(hw);
7418cfa0ad2SJack F Vogel out:
7428cfa0ad2SJack F Vogel return ret_val;
7438cfa0ad2SJack F Vogel }
7448cfa0ad2SJack F Vogel
7458cfa0ad2SJack F Vogel /**
7468cfa0ad2SJack F Vogel * e1000_set_d0_lplu_state_82575 - Set Low Power Linkup D0 state
7478cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
7481bbdc25fSKevin Bowling * @active: true to enable LPLU, false to disable
7498cfa0ad2SJack F Vogel *
7508cfa0ad2SJack F Vogel * Sets the LPLU D0 state according to the active flag. When
7518cfa0ad2SJack F Vogel * activating LPLU this function also disables smart speed
7528cfa0ad2SJack F Vogel * and vice versa. LPLU will not be activated unless the
7538cfa0ad2SJack F Vogel * device autonegotiation advertisement meets standards of
7548cfa0ad2SJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes.
7558cfa0ad2SJack F Vogel * This is a function pointer entry point only called by
7568cfa0ad2SJack F Vogel * PHY setup routines.
7578cfa0ad2SJack F Vogel **/
e1000_set_d0_lplu_state_82575(struct e1000_hw * hw,bool active)7588cfa0ad2SJack F Vogel static s32 e1000_set_d0_lplu_state_82575(struct e1000_hw *hw, bool active)
7598cfa0ad2SJack F Vogel {
7608cfa0ad2SJack F Vogel struct e1000_phy_info *phy = &hw->phy;
7618cfa0ad2SJack F Vogel s32 ret_val = E1000_SUCCESS;
7628cfa0ad2SJack F Vogel u16 data;
7638cfa0ad2SJack F Vogel
7648cfa0ad2SJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82575");
7658cfa0ad2SJack F Vogel
7668cfa0ad2SJack F Vogel if (!(hw->phy.ops.read_reg))
7678cfa0ad2SJack F Vogel goto out;
7688cfa0ad2SJack F Vogel
7698cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
7708cfa0ad2SJack F Vogel if (ret_val)
7718cfa0ad2SJack F Vogel goto out;
7728cfa0ad2SJack F Vogel
7738cfa0ad2SJack F Vogel if (active) {
7748cfa0ad2SJack F Vogel data |= IGP02E1000_PM_D0_LPLU;
7758cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
7768cfa0ad2SJack F Vogel data);
7778cfa0ad2SJack F Vogel if (ret_val)
7788cfa0ad2SJack F Vogel goto out;
7798cfa0ad2SJack F Vogel
7808cfa0ad2SJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */
7818cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
7828cfa0ad2SJack F Vogel &data);
7838cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED;
7848cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
7858cfa0ad2SJack F Vogel data);
7868cfa0ad2SJack F Vogel if (ret_val)
7878cfa0ad2SJack F Vogel goto out;
7888cfa0ad2SJack F Vogel } else {
7898cfa0ad2SJack F Vogel data &= ~IGP02E1000_PM_D0_LPLU;
7908cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
7918cfa0ad2SJack F Vogel data);
7928cfa0ad2SJack F Vogel /*
7938cfa0ad2SJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used
7948cfa0ad2SJack F Vogel * during Dx states where the power conservation is most
7958cfa0ad2SJack F Vogel * important. During driver activity we should enable
7968cfa0ad2SJack F Vogel * SmartSpeed, so performance is maintained.
7978cfa0ad2SJack F Vogel */
7988cfa0ad2SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on) {
7998cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw,
8008cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG,
8018cfa0ad2SJack F Vogel &data);
8028cfa0ad2SJack F Vogel if (ret_val)
8038cfa0ad2SJack F Vogel goto out;
8048cfa0ad2SJack F Vogel
8058cfa0ad2SJack F Vogel data |= IGP01E1000_PSCFR_SMART_SPEED;
8068cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw,
8078cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG,
8088cfa0ad2SJack F Vogel data);
8098cfa0ad2SJack F Vogel if (ret_val)
8108cfa0ad2SJack F Vogel goto out;
8118cfa0ad2SJack F Vogel } else if (phy->smart_speed == e1000_smart_speed_off) {
8128cfa0ad2SJack F Vogel ret_val = phy->ops.read_reg(hw,
8138cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG,
8148cfa0ad2SJack F Vogel &data);
8158cfa0ad2SJack F Vogel if (ret_val)
8168cfa0ad2SJack F Vogel goto out;
8178cfa0ad2SJack F Vogel
8188cfa0ad2SJack F Vogel data &= ~IGP01E1000_PSCFR_SMART_SPEED;
8198cfa0ad2SJack F Vogel ret_val = phy->ops.write_reg(hw,
8208cfa0ad2SJack F Vogel IGP01E1000_PHY_PORT_CONFIG,
8218cfa0ad2SJack F Vogel data);
8228cfa0ad2SJack F Vogel if (ret_val)
8238cfa0ad2SJack F Vogel goto out;
8248cfa0ad2SJack F Vogel }
8258cfa0ad2SJack F Vogel }
8268cfa0ad2SJack F Vogel
8278cfa0ad2SJack F Vogel out:
8288cfa0ad2SJack F Vogel return ret_val;
8298cfa0ad2SJack F Vogel }
8308cfa0ad2SJack F Vogel
8318cfa0ad2SJack F Vogel /**
832f0ecc46dSJack F Vogel * e1000_set_d0_lplu_state_82580 - Set Low Power Linkup D0 state
833f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
8341bbdc25fSKevin Bowling * @active: true to enable LPLU, false to disable
835f0ecc46dSJack F Vogel *
836f0ecc46dSJack F Vogel * Sets the LPLU D0 state according to the active flag. When
837f0ecc46dSJack F Vogel * activating LPLU this function also disables smart speed
838f0ecc46dSJack F Vogel * and vice versa. LPLU will not be activated unless the
839f0ecc46dSJack F Vogel * device autonegotiation advertisement meets standards of
840f0ecc46dSJack F Vogel * either 10 or 10/100 or 10/100/1000 at all duplexes.
841f0ecc46dSJack F Vogel * This is a function pointer entry point only called by
842f0ecc46dSJack F Vogel * PHY setup routines.
843f0ecc46dSJack F Vogel **/
e1000_set_d0_lplu_state_82580(struct e1000_hw * hw,bool active)844f0ecc46dSJack F Vogel static s32 e1000_set_d0_lplu_state_82580(struct e1000_hw *hw, bool active)
845f0ecc46dSJack F Vogel {
846f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy;
847ab5d0362SJack F Vogel u32 data;
848f0ecc46dSJack F Vogel
849f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d0_lplu_state_82580");
850f0ecc46dSJack F Vogel
851f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
852f0ecc46dSJack F Vogel
853f0ecc46dSJack F Vogel if (active) {
854f0ecc46dSJack F Vogel data |= E1000_82580_PM_D0_LPLU;
855f0ecc46dSJack F Vogel
856f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */
857f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD;
858f0ecc46dSJack F Vogel } else {
859f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D0_LPLU;
860f0ecc46dSJack F Vogel
861f0ecc46dSJack F Vogel /*
862f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used
863f0ecc46dSJack F Vogel * during Dx states where the power conservation is most
864f0ecc46dSJack F Vogel * important. During driver activity we should enable
865f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained.
866f0ecc46dSJack F Vogel */
8674dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on)
868f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD;
8694dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off)
870f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD;
871f0ecc46dSJack F Vogel }
872f0ecc46dSJack F Vogel
873f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
8748cc64f1eSJack F Vogel return E1000_SUCCESS;
875f0ecc46dSJack F Vogel }
876f0ecc46dSJack F Vogel
877f0ecc46dSJack F Vogel /**
878f0ecc46dSJack F Vogel * e1000_set_d3_lplu_state_82580 - Sets low power link up state for D3
879f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
880f0ecc46dSJack F Vogel * @active: boolean used to enable/disable lplu
881f0ecc46dSJack F Vogel *
882f0ecc46dSJack F Vogel * Success returns 0, Failure returns 1
883f0ecc46dSJack F Vogel *
884f0ecc46dSJack F Vogel * The low power link up (lplu) state is set to the power management level D3
8851bbdc25fSKevin Bowling * and SmartSpeed is disabled when active is true, else clear lplu for D3
886f0ecc46dSJack F Vogel * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
887f0ecc46dSJack F Vogel * is used during Dx states where the power conservation is most important.
888f0ecc46dSJack F Vogel * During driver activity, SmartSpeed should be enabled so performance is
889f0ecc46dSJack F Vogel * maintained.
890f0ecc46dSJack F Vogel **/
e1000_set_d3_lplu_state_82580(struct e1000_hw * hw,bool active)891f0ecc46dSJack F Vogel s32 e1000_set_d3_lplu_state_82580(struct e1000_hw *hw, bool active)
892f0ecc46dSJack F Vogel {
893f0ecc46dSJack F Vogel struct e1000_phy_info *phy = &hw->phy;
894ab5d0362SJack F Vogel u32 data;
895f0ecc46dSJack F Vogel
896f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_d3_lplu_state_82580");
897f0ecc46dSJack F Vogel
898f0ecc46dSJack F Vogel data = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
899f0ecc46dSJack F Vogel
900f0ecc46dSJack F Vogel if (!active) {
901f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_D3_LPLU;
902f0ecc46dSJack F Vogel /*
903f0ecc46dSJack F Vogel * LPLU and SmartSpeed are mutually exclusive. LPLU is used
904f0ecc46dSJack F Vogel * during Dx states where the power conservation is most
905f0ecc46dSJack F Vogel * important. During driver activity we should enable
906f0ecc46dSJack F Vogel * SmartSpeed, so performance is maintained.
907f0ecc46dSJack F Vogel */
9084dab5c37SJack F Vogel if (phy->smart_speed == e1000_smart_speed_on)
909f0ecc46dSJack F Vogel data |= E1000_82580_PM_SPD;
9104dab5c37SJack F Vogel else if (phy->smart_speed == e1000_smart_speed_off)
911f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD;
912f0ecc46dSJack F Vogel } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
913f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
914f0ecc46dSJack F Vogel (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
915f0ecc46dSJack F Vogel data |= E1000_82580_PM_D3_LPLU;
916f0ecc46dSJack F Vogel /* When LPLU is enabled, we should disable SmartSpeed */
917f0ecc46dSJack F Vogel data &= ~E1000_82580_PM_SPD;
918f0ecc46dSJack F Vogel }
919f0ecc46dSJack F Vogel
920f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, data);
9218cc64f1eSJack F Vogel return E1000_SUCCESS;
922f0ecc46dSJack F Vogel }
923f0ecc46dSJack F Vogel
924f0ecc46dSJack F Vogel /**
9258cfa0ad2SJack F Vogel * e1000_acquire_nvm_82575 - Request for access to EEPROM
9268cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
9278cfa0ad2SJack F Vogel *
9288cfa0ad2SJack F Vogel * Acquire the necessary semaphores for exclusive access to the EEPROM.
9298cfa0ad2SJack F Vogel * Set the EEPROM access request bit and wait for EEPROM access grant bit.
9308cfa0ad2SJack F Vogel * Return successful if access grant bit set, else clear the request for
9318cfa0ad2SJack F Vogel * EEPROM access and return -E1000_ERR_NVM (-1).
9328cfa0ad2SJack F Vogel **/
e1000_acquire_nvm_82575(struct e1000_hw * hw)9338cfa0ad2SJack F Vogel static s32 e1000_acquire_nvm_82575(struct e1000_hw *hw)
9348cfa0ad2SJack F Vogel {
9358cc64f1eSJack F Vogel s32 ret_val = E1000_SUCCESS;
9368cfa0ad2SJack F Vogel
9378cfa0ad2SJack F Vogel DEBUGFUNC("e1000_acquire_nvm_82575");
9388cfa0ad2SJack F Vogel
939d5210708SMatt Macy ret_val = e1000_acquire_swfw_sync(hw, E1000_SWFW_EEP_SM);
9408cfa0ad2SJack F Vogel if (ret_val)
9418cfa0ad2SJack F Vogel goto out;
9424dab5c37SJack F Vogel
9434dab5c37SJack F Vogel /*
9444dab5c37SJack F Vogel * Check if there is some access
9454dab5c37SJack F Vogel * error this access may hook on
9464dab5c37SJack F Vogel */
9474dab5c37SJack F Vogel if (hw->mac.type == e1000_i350) {
9484dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD);
9494dab5c37SJack F Vogel if (eecd & (E1000_EECD_BLOCKED | E1000_EECD_ABORT |
9504dab5c37SJack F Vogel E1000_EECD_TIMEOUT)) {
9514dab5c37SJack F Vogel /* Clear all access error flags */
9524dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd |
9534dab5c37SJack F Vogel E1000_EECD_ERROR_CLR);
9544dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
9554dab5c37SJack F Vogel }
9564dab5c37SJack F Vogel }
9578cc64f1eSJack F Vogel
9584dab5c37SJack F Vogel if (hw->mac.type == e1000_82580) {
9594dab5c37SJack F Vogel u32 eecd = E1000_READ_REG(hw, E1000_EECD);
9604dab5c37SJack F Vogel if (eecd & E1000_EECD_BLOCKED) {
9614dab5c37SJack F Vogel /* Clear access error flag */
9624dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_EECD, eecd |
9634dab5c37SJack F Vogel E1000_EECD_BLOCKED);
9644dab5c37SJack F Vogel DEBUGOUT("Nvm bit banging access error detected and cleared.\n");
9654dab5c37SJack F Vogel }
9664dab5c37SJack F Vogel }
9674dab5c37SJack F Vogel
9688cfa0ad2SJack F Vogel ret_val = e1000_acquire_nvm_generic(hw);
9698cfa0ad2SJack F Vogel if (ret_val)
970d5210708SMatt Macy e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
9718cfa0ad2SJack F Vogel
9728cfa0ad2SJack F Vogel out:
9738cfa0ad2SJack F Vogel return ret_val;
9748cfa0ad2SJack F Vogel }
9758cfa0ad2SJack F Vogel
9768cfa0ad2SJack F Vogel /**
9778cfa0ad2SJack F Vogel * e1000_release_nvm_82575 - Release exclusive access to EEPROM
9788cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
9798cfa0ad2SJack F Vogel *
9808cfa0ad2SJack F Vogel * Stop any current commands to the EEPROM and clear the EEPROM request bit,
9818cfa0ad2SJack F Vogel * then release the semaphores acquired.
9828cfa0ad2SJack F Vogel **/
e1000_release_nvm_82575(struct e1000_hw * hw)9838cfa0ad2SJack F Vogel static void e1000_release_nvm_82575(struct e1000_hw *hw)
9848cfa0ad2SJack F Vogel {
9858cfa0ad2SJack F Vogel DEBUGFUNC("e1000_release_nvm_82575");
9868cfa0ad2SJack F Vogel
9874dab5c37SJack F Vogel e1000_release_nvm_generic(hw);
988ab5d0362SJack F Vogel
989d5210708SMatt Macy e1000_release_swfw_sync(hw, E1000_SWFW_EEP_SM);
9908cfa0ad2SJack F Vogel }
9918cfa0ad2SJack F Vogel
9928cfa0ad2SJack F Vogel /**
9938cfa0ad2SJack F Vogel * e1000_get_cfg_done_82575 - Read config done bit
9948cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
9958cfa0ad2SJack F Vogel *
9968cfa0ad2SJack F Vogel * Read the management control register for the config done bit for
9978cfa0ad2SJack F Vogel * completion status. NOTE: silicon which is EEPROM-less will fail trying
9988cfa0ad2SJack F Vogel * to read the config done bit, so an error is *ONLY* logged and returns
9998cfa0ad2SJack F Vogel * E1000_SUCCESS. If we were to return with error, EEPROM-less silicon
10008cfa0ad2SJack F Vogel * would not be able to be reset or change link.
10018cfa0ad2SJack F Vogel **/
e1000_get_cfg_done_82575(struct e1000_hw * hw)10028cfa0ad2SJack F Vogel static s32 e1000_get_cfg_done_82575(struct e1000_hw *hw)
10038cfa0ad2SJack F Vogel {
10048cfa0ad2SJack F Vogel s32 timeout = PHY_CFG_TIMEOUT;
10058cfa0ad2SJack F Vogel u32 mask = E1000_NVM_CFG_DONE_PORT_0;
10068cfa0ad2SJack F Vogel
10078cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_cfg_done_82575");
10088cfa0ad2SJack F Vogel
10099d81738fSJack F Vogel if (hw->bus.func == E1000_FUNC_1)
10108cfa0ad2SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_1;
10114edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_2)
10124edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_2;
10134edd8523SJack F Vogel else if (hw->bus.func == E1000_FUNC_3)
10144edd8523SJack F Vogel mask = E1000_NVM_CFG_DONE_PORT_3;
10158cfa0ad2SJack F Vogel while (timeout) {
10168cfa0ad2SJack F Vogel if (E1000_READ_REG(hw, E1000_EEMNGCTL) & mask)
10178cfa0ad2SJack F Vogel break;
10188cfa0ad2SJack F Vogel msec_delay(1);
10198cfa0ad2SJack F Vogel timeout--;
10208cfa0ad2SJack F Vogel }
10214edd8523SJack F Vogel if (!timeout)
10228cfa0ad2SJack F Vogel DEBUGOUT("MNG configuration cycle has not completed.\n");
10238cfa0ad2SJack F Vogel
10248cfa0ad2SJack F Vogel /* If EEPROM is not marked present, init the PHY manually */
1025ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) &&
10264edd8523SJack F Vogel (hw->phy.type == e1000_phy_igp_3))
10278cfa0ad2SJack F Vogel e1000_phy_init_script_igp3(hw);
10288cfa0ad2SJack F Vogel
10298cc64f1eSJack F Vogel return E1000_SUCCESS;
10308cfa0ad2SJack F Vogel }
10318cfa0ad2SJack F Vogel
10328cfa0ad2SJack F Vogel /**
10338cfa0ad2SJack F Vogel * e1000_get_link_up_info_82575 - Get link speed/duplex info
10348cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
10358cfa0ad2SJack F Vogel * @speed: stores the current speed
10368cfa0ad2SJack F Vogel * @duplex: stores the current duplex
10378cfa0ad2SJack F Vogel *
10388cfa0ad2SJack F Vogel * This is a wrapper function, if using the serial gigabit media independent
10398cfa0ad2SJack F Vogel * interface, use PCS to retrieve the link speed and duplex information.
10408cfa0ad2SJack F Vogel * Otherwise, use the generic function to get the link speed and duplex info.
10418cfa0ad2SJack F Vogel **/
e1000_get_link_up_info_82575(struct e1000_hw * hw,u16 * speed,u16 * duplex)10428cfa0ad2SJack F Vogel static s32 e1000_get_link_up_info_82575(struct e1000_hw *hw, u16 *speed,
10438cfa0ad2SJack F Vogel u16 *duplex)
10448cfa0ad2SJack F Vogel {
10458cfa0ad2SJack F Vogel s32 ret_val;
10468cfa0ad2SJack F Vogel
10478cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_link_up_info_82575");
10488cfa0ad2SJack F Vogel
10494edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper)
10508cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, speed,
10518cfa0ad2SJack F Vogel duplex);
10524edd8523SJack F Vogel else
10538cfa0ad2SJack F Vogel ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed,
10548cfa0ad2SJack F Vogel duplex);
10558cfa0ad2SJack F Vogel
10568cfa0ad2SJack F Vogel return ret_val;
10578cfa0ad2SJack F Vogel }
10588cfa0ad2SJack F Vogel
10598cfa0ad2SJack F Vogel /**
10608cfa0ad2SJack F Vogel * e1000_check_for_link_82575 - Check for link
10618cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
10628cfa0ad2SJack F Vogel *
10638cfa0ad2SJack F Vogel * If sgmii is enabled, then use the pcs register to determine link, otherwise
10648cfa0ad2SJack F Vogel * use the generic interface for determining link.
10658cfa0ad2SJack F Vogel **/
e1000_check_for_link_82575(struct e1000_hw * hw)10668cfa0ad2SJack F Vogel static s32 e1000_check_for_link_82575(struct e1000_hw *hw)
10678cfa0ad2SJack F Vogel {
10688cfa0ad2SJack F Vogel s32 ret_val;
10698cfa0ad2SJack F Vogel u16 speed, duplex;
10708cfa0ad2SJack F Vogel
10718cfa0ad2SJack F Vogel DEBUGFUNC("e1000_check_for_link_82575");
10728cfa0ad2SJack F Vogel
10734edd8523SJack F Vogel if (hw->phy.media_type != e1000_media_type_copper) {
10748cfa0ad2SJack F Vogel ret_val = e1000_get_pcs_speed_and_duplex_82575(hw, &speed,
10758cfa0ad2SJack F Vogel &duplex);
1076d035aa2dSJack F Vogel /*
1077d035aa2dSJack F Vogel * Use this flag to determine if link needs to be checked or
1078d035aa2dSJack F Vogel * not. If we have link clear the flag so that we do not
1079d035aa2dSJack F Vogel * continue to check for link.
1080d035aa2dSJack F Vogel */
1081d035aa2dSJack F Vogel hw->mac.get_link_status = !hw->mac.serdes_has_link;
1082ab5d0362SJack F Vogel
10836ab6bfe3SJack F Vogel /*
10846ab6bfe3SJack F Vogel * Configure Flow Control now that Auto-Neg has completed.
10856ab6bfe3SJack F Vogel * First, we need to restore the desired flow control
10866ab6bfe3SJack F Vogel * settings because we may have had to re-autoneg with a
10876ab6bfe3SJack F Vogel * different link partner.
10886ab6bfe3SJack F Vogel */
10896ab6bfe3SJack F Vogel ret_val = e1000_config_fc_after_link_up_generic(hw);
10906ab6bfe3SJack F Vogel if (ret_val)
10916ab6bfe3SJack F Vogel DEBUGOUT("Error configuring flow control\n");
1092d035aa2dSJack F Vogel } else {
10938cfa0ad2SJack F Vogel ret_val = e1000_check_for_copper_link_generic(hw);
1094d035aa2dSJack F Vogel }
10958cfa0ad2SJack F Vogel
10968cfa0ad2SJack F Vogel return ret_val;
10978cfa0ad2SJack F Vogel }
10988cfa0ad2SJack F Vogel
10998cfa0ad2SJack F Vogel /**
11007609433eSJack F Vogel * e1000_check_for_link_media_swap - Check which M88E1112 interface linked
11017609433eSJack F Vogel * @hw: pointer to the HW structure
11027609433eSJack F Vogel *
11037609433eSJack F Vogel * Poll the M88E1112 interfaces to see which interface achieved link.
11047609433eSJack F Vogel */
e1000_check_for_link_media_swap(struct e1000_hw * hw)11057609433eSJack F Vogel static s32 e1000_check_for_link_media_swap(struct e1000_hw *hw)
11067609433eSJack F Vogel {
11077609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy;
11087609433eSJack F Vogel s32 ret_val;
11097609433eSJack F Vogel u16 data;
11107609433eSJack F Vogel u8 port = 0;
11117609433eSJack F Vogel
11127609433eSJack F Vogel DEBUGFUNC("e1000_check_for_link_media_swap");
11137609433eSJack F Vogel
1114c80429ceSEric Joyner /* Check for copper. */
11157609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
11167609433eSJack F Vogel if (ret_val)
11177609433eSJack F Vogel return ret_val;
11187609433eSJack F Vogel
11197609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
11207609433eSJack F Vogel if (ret_val)
11217609433eSJack F Vogel return ret_val;
11227609433eSJack F Vogel
11237609433eSJack F Vogel if (data & E1000_M88E1112_STATUS_LINK)
11247609433eSJack F Vogel port = E1000_MEDIA_PORT_COPPER;
11257609433eSJack F Vogel
1126c80429ceSEric Joyner /* Check for other. */
11277609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 1);
11287609433eSJack F Vogel if (ret_val)
11297609433eSJack F Vogel return ret_val;
11307609433eSJack F Vogel
11317609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1112_STATUS, &data);
11327609433eSJack F Vogel if (ret_val)
11337609433eSJack F Vogel return ret_val;
11347609433eSJack F Vogel
11357609433eSJack F Vogel if (data & E1000_M88E1112_STATUS_LINK)
11367609433eSJack F Vogel port = E1000_MEDIA_PORT_OTHER;
11377609433eSJack F Vogel
11387609433eSJack F Vogel /* Determine if a swap needs to happen. */
11397609433eSJack F Vogel if (port && (hw->dev_spec._82575.media_port != port)) {
11407609433eSJack F Vogel hw->dev_spec._82575.media_port = port;
11411bbdc25fSKevin Bowling hw->dev_spec._82575.media_changed = true;
1142c80429ceSEric Joyner }
1143c80429ceSEric Joyner
1144c80429ceSEric Joyner if (port == E1000_MEDIA_PORT_COPPER) {
1145c80429ceSEric Joyner /* reset page to 0 */
1146c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
1147c80429ceSEric Joyner if (ret_val)
1148c80429ceSEric Joyner return ret_val;
1149c80429ceSEric Joyner e1000_check_for_link_82575(hw);
11507609433eSJack F Vogel } else {
1151c80429ceSEric Joyner e1000_check_for_link_82575(hw);
1152c80429ceSEric Joyner /* reset page to 0 */
1153c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1112_PAGE_ADDR, 0);
1154c80429ceSEric Joyner if (ret_val)
1155c80429ceSEric Joyner return ret_val;
11567609433eSJack F Vogel }
11577609433eSJack F Vogel
11587609433eSJack F Vogel return E1000_SUCCESS;
11597609433eSJack F Vogel }
11607609433eSJack F Vogel
11617609433eSJack F Vogel /**
1162a69ed8dfSJack F Vogel * e1000_power_up_serdes_link_82575 - Power up the serdes link after shutdown
1163a69ed8dfSJack F Vogel * @hw: pointer to the HW structure
1164a69ed8dfSJack F Vogel **/
e1000_power_up_serdes_link_82575(struct e1000_hw * hw)1165a69ed8dfSJack F Vogel static void e1000_power_up_serdes_link_82575(struct e1000_hw *hw)
1166a69ed8dfSJack F Vogel {
1167a69ed8dfSJack F Vogel u32 reg;
1168a69ed8dfSJack F Vogel
1169a69ed8dfSJack F Vogel DEBUGFUNC("e1000_power_up_serdes_link_82575");
1170a69ed8dfSJack F Vogel
1171a69ed8dfSJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
1172a69ed8dfSJack F Vogel !e1000_sgmii_active_82575(hw))
1173a69ed8dfSJack F Vogel return;
1174a69ed8dfSJack F Vogel
1175a69ed8dfSJack F Vogel /* Enable PCS to turn on link */
1176a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
1177a69ed8dfSJack F Vogel reg |= E1000_PCS_CFG_PCS_EN;
1178a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
1179a69ed8dfSJack F Vogel
1180a69ed8dfSJack F Vogel /* Power up the laser */
1181a69ed8dfSJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
1182a69ed8dfSJack F Vogel reg &= ~E1000_CTRL_EXT_SDP3_DATA;
1183a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
1184a69ed8dfSJack F Vogel
1185a69ed8dfSJack F Vogel /* flush the write to verify completion */
1186a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw);
1187a69ed8dfSJack F Vogel msec_delay(1);
1188a69ed8dfSJack F Vogel }
1189a69ed8dfSJack F Vogel
1190a69ed8dfSJack F Vogel /**
11918cfa0ad2SJack F Vogel * e1000_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
11928cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
11938cfa0ad2SJack F Vogel * @speed: stores the current speed
11948cfa0ad2SJack F Vogel * @duplex: stores the current duplex
11958cfa0ad2SJack F Vogel *
11968cfa0ad2SJack F Vogel * Using the physical coding sub-layer (PCS), retrieve the current speed and
11978cfa0ad2SJack F Vogel * duplex, then store the values in the pointers provided.
11988cfa0ad2SJack F Vogel **/
e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw * hw,u16 * speed,u16 * duplex)11998cfa0ad2SJack F Vogel static s32 e1000_get_pcs_speed_and_duplex_82575(struct e1000_hw *hw,
12008cfa0ad2SJack F Vogel u16 *speed, u16 *duplex)
12018cfa0ad2SJack F Vogel {
12028cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac;
12038cfa0ad2SJack F Vogel u32 pcs;
12047609433eSJack F Vogel u32 status;
12058cfa0ad2SJack F Vogel
12068cfa0ad2SJack F Vogel DEBUGFUNC("e1000_get_pcs_speed_and_duplex_82575");
12078cfa0ad2SJack F Vogel
12088cfa0ad2SJack F Vogel /*
12098cfa0ad2SJack F Vogel * Read the PCS Status register for link state. For non-copper mode,
12108cfa0ad2SJack F Vogel * the status register is not accurate. The PCS status register is
12118cfa0ad2SJack F Vogel * used instead.
12128cfa0ad2SJack F Vogel */
12138cfa0ad2SJack F Vogel pcs = E1000_READ_REG(hw, E1000_PCS_LSTAT);
12148cfa0ad2SJack F Vogel
12158cfa0ad2SJack F Vogel /*
1216ab5d0362SJack F Vogel * The link up bit determines when link is up on autoneg.
12178cfa0ad2SJack F Vogel */
1218ab5d0362SJack F Vogel if (pcs & E1000_PCS_LSTS_LINK_OK) {
12191bbdc25fSKevin Bowling mac->serdes_has_link = true;
12208cfa0ad2SJack F Vogel
12218cfa0ad2SJack F Vogel /* Detect and store PCS speed */
12224dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_SPEED_1000)
12238cfa0ad2SJack F Vogel *speed = SPEED_1000;
12244dab5c37SJack F Vogel else if (pcs & E1000_PCS_LSTS_SPEED_100)
12258cfa0ad2SJack F Vogel *speed = SPEED_100;
12264dab5c37SJack F Vogel else
12278cfa0ad2SJack F Vogel *speed = SPEED_10;
12288cfa0ad2SJack F Vogel
12298cfa0ad2SJack F Vogel /* Detect and store PCS duplex */
12304dab5c37SJack F Vogel if (pcs & E1000_PCS_LSTS_DUPLEX_FULL)
12318cfa0ad2SJack F Vogel *duplex = FULL_DUPLEX;
12324dab5c37SJack F Vogel else
12338cfa0ad2SJack F Vogel *duplex = HALF_DUPLEX;
12346ab6bfe3SJack F Vogel
12357609433eSJack F Vogel /* Check if it is an I354 2.5Gb backplane connection. */
12367609433eSJack F Vogel if (mac->type == e1000_i354) {
12377609433eSJack F Vogel status = E1000_READ_REG(hw, E1000_STATUS);
12387609433eSJack F Vogel if ((status & E1000_STATUS_2P5_SKU) &&
12397609433eSJack F Vogel !(status & E1000_STATUS_2P5_SKU_OVER)) {
12407609433eSJack F Vogel *speed = SPEED_2500;
12417609433eSJack F Vogel *duplex = FULL_DUPLEX;
12427609433eSJack F Vogel DEBUGOUT("2500 Mbs, ");
12437609433eSJack F Vogel DEBUGOUT("Full Duplex\n");
12447609433eSJack F Vogel }
12457609433eSJack F Vogel }
12467609433eSJack F Vogel
1247ab5d0362SJack F Vogel } else {
12481bbdc25fSKevin Bowling mac->serdes_has_link = false;
1249ab5d0362SJack F Vogel *speed = 0;
1250ab5d0362SJack F Vogel *duplex = 0;
12518cfa0ad2SJack F Vogel }
12528cfa0ad2SJack F Vogel
12538cfa0ad2SJack F Vogel return E1000_SUCCESS;
12548cfa0ad2SJack F Vogel }
12558cfa0ad2SJack F Vogel
12568cfa0ad2SJack F Vogel /**
12574edd8523SJack F Vogel * e1000_shutdown_serdes_link_82575 - Remove link during power down
12588cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
12598cfa0ad2SJack F Vogel *
12604edd8523SJack F Vogel * In the case of serdes shut down sfp and PCS on driver unload
12618cfa0ad2SJack F Vogel * when management pass thru is not enabled.
12628cfa0ad2SJack F Vogel **/
e1000_shutdown_serdes_link_82575(struct e1000_hw * hw)12634edd8523SJack F Vogel void e1000_shutdown_serdes_link_82575(struct e1000_hw *hw)
12648cfa0ad2SJack F Vogel {
12658cfa0ad2SJack F Vogel u32 reg;
1266a69ed8dfSJack F Vogel
1267a69ed8dfSJack F Vogel DEBUGFUNC("e1000_shutdown_serdes_link_82575");
12688cfa0ad2SJack F Vogel
12694edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
12704edd8523SJack F Vogel !e1000_sgmii_active_82575(hw))
12718cfa0ad2SJack F Vogel return;
12728cfa0ad2SJack F Vogel
1273a69ed8dfSJack F Vogel if (!e1000_enable_mng_pass_thru(hw)) {
12748cfa0ad2SJack F Vogel /* Disable PCS to turn off link */
12758cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_CFG0);
12768cfa0ad2SJack F Vogel reg &= ~E1000_PCS_CFG_PCS_EN;
12778cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_CFG0, reg);
12788cfa0ad2SJack F Vogel
12798cfa0ad2SJack F Vogel /* shutdown the laser */
12808cfa0ad2SJack F Vogel reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
12814edd8523SJack F Vogel reg |= E1000_CTRL_EXT_SDP3_DATA;
12828cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
12838cfa0ad2SJack F Vogel
12844edd8523SJack F Vogel /* flush the write to verify completion */
12858cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw);
12868cfa0ad2SJack F Vogel msec_delay(1);
12878cfa0ad2SJack F Vogel }
12888cfa0ad2SJack F Vogel
12898cfa0ad2SJack F Vogel return;
12908cfa0ad2SJack F Vogel }
12918cfa0ad2SJack F Vogel
12928cfa0ad2SJack F Vogel /**
12938cfa0ad2SJack F Vogel * e1000_reset_hw_82575 - Reset hardware
12948cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
12958cfa0ad2SJack F Vogel *
1296daf9197cSJack F Vogel * This resets the hardware into a known state.
12978cfa0ad2SJack F Vogel **/
e1000_reset_hw_82575(struct e1000_hw * hw)12988cfa0ad2SJack F Vogel static s32 e1000_reset_hw_82575(struct e1000_hw *hw)
12998cfa0ad2SJack F Vogel {
1300f0ecc46dSJack F Vogel u32 ctrl;
13018cfa0ad2SJack F Vogel s32 ret_val;
13028cfa0ad2SJack F Vogel
13038cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_hw_82575");
13048cfa0ad2SJack F Vogel
13058cfa0ad2SJack F Vogel /*
13068cfa0ad2SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection
13078cfa0ad2SJack F Vogel * on the last TLP read/write transaction when MAC is reset.
13088cfa0ad2SJack F Vogel */
13098cfa0ad2SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw);
13104dab5c37SJack F Vogel if (ret_val)
13118cfa0ad2SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n");
13128cfa0ad2SJack F Vogel
13139d81738fSJack F Vogel /* set the completion timeout for interface */
13149d81738fSJack F Vogel ret_val = e1000_set_pcie_completion_timeout(hw);
13154dab5c37SJack F Vogel if (ret_val)
13169d81738fSJack F Vogel DEBUGOUT("PCI-E Set completion timeout has failed.\n");
13179d81738fSJack F Vogel
13188cfa0ad2SJack F Vogel DEBUGOUT("Masking off all interrupts\n");
13198cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
13208cfa0ad2SJack F Vogel
13218cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0);
13228cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
13238cfa0ad2SJack F Vogel E1000_WRITE_FLUSH(hw);
13248cfa0ad2SJack F Vogel
13258cfa0ad2SJack F Vogel msec_delay(10);
13268cfa0ad2SJack F Vogel
13278cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL);
13288cfa0ad2SJack F Vogel
13298cfa0ad2SJack F Vogel DEBUGOUT("Issuing a global reset to MAC\n");
13308cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
13318cfa0ad2SJack F Vogel
13328cfa0ad2SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw);
13338cfa0ad2SJack F Vogel if (ret_val) {
13348cfa0ad2SJack F Vogel /*
13358cfa0ad2SJack F Vogel * When auto config read does not complete, do not
13368cfa0ad2SJack F Vogel * return with an error. This can happen in situations
13378cfa0ad2SJack F Vogel * where there is no eeprom and prevents getting link.
13388cfa0ad2SJack F Vogel */
13398cfa0ad2SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n");
13408cfa0ad2SJack F Vogel }
13418cfa0ad2SJack F Vogel
13428cfa0ad2SJack F Vogel /* If EEPROM is not present, run manual init scripts */
1343ab5d0362SJack F Vogel if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES))
13448cfa0ad2SJack F Vogel e1000_reset_init_script_82575(hw);
13458cfa0ad2SJack F Vogel
13468cfa0ad2SJack F Vogel /* Clear any pending interrupt events. */
13478cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
1348f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR);
13498cfa0ad2SJack F Vogel
1350d035aa2dSJack F Vogel /* Install any alternate MAC address into RAR0 */
1351d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw);
13528cfa0ad2SJack F Vogel
13538cfa0ad2SJack F Vogel return ret_val;
13548cfa0ad2SJack F Vogel }
13558cfa0ad2SJack F Vogel
13568cfa0ad2SJack F Vogel /**
13578cfa0ad2SJack F Vogel * e1000_init_hw_82575 - Initialize hardware
13588cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
13598cfa0ad2SJack F Vogel *
13608cfa0ad2SJack F Vogel * This inits the hardware readying it for operation.
13618cfa0ad2SJack F Vogel **/
e1000_init_hw_82575(struct e1000_hw * hw)1362984d1616SKevin Bowling static s32 e1000_init_hw_82575(struct e1000_hw *hw)
13638cfa0ad2SJack F Vogel {
13648cfa0ad2SJack F Vogel struct e1000_mac_info *mac = &hw->mac;
13658cfa0ad2SJack F Vogel s32 ret_val;
13668cfa0ad2SJack F Vogel
13678cfa0ad2SJack F Vogel DEBUGFUNC("e1000_init_hw_82575");
13688cfa0ad2SJack F Vogel
13698cfa0ad2SJack F Vogel /* Initialize identification LED */
1370d035aa2dSJack F Vogel ret_val = mac->ops.id_led_init(hw);
13718cfa0ad2SJack F Vogel if (ret_val) {
13728cfa0ad2SJack F Vogel DEBUGOUT("Error initializing identification LED\n");
13738cfa0ad2SJack F Vogel /* This is not fatal and we should not stop init due to this */
13748cfa0ad2SJack F Vogel }
13758cfa0ad2SJack F Vogel
13768cfa0ad2SJack F Vogel /* Disabling VLAN filtering */
13778cfa0ad2SJack F Vogel DEBUGOUT("Initializing the IEEE VLAN\n");
13788cfa0ad2SJack F Vogel mac->ops.clear_vfta(hw);
13798cfa0ad2SJack F Vogel
13806b9d35faSGuinan Sun ret_val = e1000_init_hw_base(hw);
13818cfa0ad2SJack F Vogel
13824dab5c37SJack F Vogel /* Set the default MTU size */
13834dab5c37SJack F Vogel hw->dev_spec._82575.mtu = 1500;
13844dab5c37SJack F Vogel
13856b9d35faSGuinan Sun /* Clear all of the statistics registers (clear on read). It is
13868cfa0ad2SJack F Vogel * important that we do this after we have tried to establish link
13878cfa0ad2SJack F Vogel * because the symbol error count will increment wildly if there
13888cfa0ad2SJack F Vogel * is no link.
13898cfa0ad2SJack F Vogel */
13908cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_82575(hw);
13918cfa0ad2SJack F Vogel
13928cfa0ad2SJack F Vogel return ret_val;
13938cfa0ad2SJack F Vogel }
13948cfa0ad2SJack F Vogel /**
13958cfa0ad2SJack F Vogel * e1000_setup_copper_link_82575 - Configure copper link settings
13968cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
13978cfa0ad2SJack F Vogel *
13988cfa0ad2SJack F Vogel * Configures the link for auto-neg or forced speed and duplex. Then we check
13998cfa0ad2SJack F Vogel * for link, once link is established calls to configure collision distance
14008cfa0ad2SJack F Vogel * and flow control are called.
14018cfa0ad2SJack F Vogel **/
e1000_setup_copper_link_82575(struct e1000_hw * hw)14028cfa0ad2SJack F Vogel static s32 e1000_setup_copper_link_82575(struct e1000_hw *hw)
14038cfa0ad2SJack F Vogel {
14046b9d35faSGuinan Sun u32 phpm_reg;
14059d81738fSJack F Vogel u32 ctrl;
14068cfa0ad2SJack F Vogel s32 ret_val;
14078cfa0ad2SJack F Vogel
14088cfa0ad2SJack F Vogel DEBUGFUNC("e1000_setup_copper_link_82575");
14098cfa0ad2SJack F Vogel
14108cfa0ad2SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL);
14118cfa0ad2SJack F Vogel ctrl |= E1000_CTRL_SLU;
14128cfa0ad2SJack F Vogel ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
14138cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
14148cfa0ad2SJack F Vogel
14157609433eSJack F Vogel /* Clear Go Link Disconnect bit on supported devices */
14167609433eSJack F Vogel switch (hw->mac.type) {
14177609433eSJack F Vogel case e1000_82580:
14187609433eSJack F Vogel case e1000_i350:
14197609433eSJack F Vogel case e1000_i210:
14207609433eSJack F Vogel case e1000_i211:
14216ab6bfe3SJack F Vogel phpm_reg = E1000_READ_REG(hw, E1000_82580_PHY_POWER_MGMT);
14226ab6bfe3SJack F Vogel phpm_reg &= ~E1000_82580_PM_GO_LINKD;
14236ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_82580_PHY_POWER_MGMT, phpm_reg);
14247609433eSJack F Vogel break;
14257609433eSJack F Vogel default:
14267609433eSJack F Vogel break;
14276ab6bfe3SJack F Vogel }
14286ab6bfe3SJack F Vogel
14294edd8523SJack F Vogel ret_val = e1000_setup_serdes_link_82575(hw);
14304edd8523SJack F Vogel if (ret_val)
14314edd8523SJack F Vogel goto out;
14324edd8523SJack F Vogel
14334dab5c37SJack F Vogel if (e1000_sgmii_active_82575(hw)) {
14344edd8523SJack F Vogel /* allow time for SFP cage time to power up phy */
14354edd8523SJack F Vogel msec_delay(300);
14364edd8523SJack F Vogel
14374edd8523SJack F Vogel ret_val = hw->phy.ops.reset(hw);
14384edd8523SJack F Vogel if (ret_val) {
14394edd8523SJack F Vogel DEBUGOUT("Error resetting the PHY.\n");
14404edd8523SJack F Vogel goto out;
14414edd8523SJack F Vogel }
14424edd8523SJack F Vogel }
14438cfa0ad2SJack F Vogel switch (hw->phy.type) {
1444ab5d0362SJack F Vogel case e1000_phy_i210:
1445e05d9788SKevin Bowling /* FALLTHROUGH */
14468cfa0ad2SJack F Vogel case e1000_phy_m88:
14476ab6bfe3SJack F Vogel switch (hw->phy.id) {
14486ab6bfe3SJack F Vogel case I347AT4_E_PHY_ID:
1449e05d9788SKevin Bowling /* FALLTHROUGH */
14506ab6bfe3SJack F Vogel case M88E1112_E_PHY_ID:
1451e05d9788SKevin Bowling /* FALLTHROUGH */
14526ab6bfe3SJack F Vogel case M88E1340M_E_PHY_ID:
1453e05d9788SKevin Bowling /* FALLTHROUGH */
14547609433eSJack F Vogel case M88E1543_E_PHY_ID:
1455e05d9788SKevin Bowling /* FALLTHROUGH */
14567609433eSJack F Vogel case M88E1512_E_PHY_ID:
1457e05d9788SKevin Bowling /* FALLTHROUGH */
14586ab6bfe3SJack F Vogel case I210_I_PHY_ID:
1459f0ecc46dSJack F Vogel ret_val = e1000_copper_link_setup_m88_gen2(hw);
14606ab6bfe3SJack F Vogel break;
14616ab6bfe3SJack F Vogel default:
14628cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_m88(hw);
14638cfa0ad2SJack F Vogel break;
14646ab6bfe3SJack F Vogel }
14656ab6bfe3SJack F Vogel break;
14668cfa0ad2SJack F Vogel case e1000_phy_igp_3:
14678cfa0ad2SJack F Vogel ret_val = e1000_copper_link_setup_igp(hw);
14688cfa0ad2SJack F Vogel break;
14694edd8523SJack F Vogel case e1000_phy_82580:
14704edd8523SJack F Vogel ret_val = e1000_copper_link_setup_82577(hw);
14714edd8523SJack F Vogel break;
14728cfa0ad2SJack F Vogel default:
14738cfa0ad2SJack F Vogel ret_val = -E1000_ERR_PHY;
14748cfa0ad2SJack F Vogel break;
14758cfa0ad2SJack F Vogel }
14768cfa0ad2SJack F Vogel
14778cfa0ad2SJack F Vogel if (ret_val)
14788cfa0ad2SJack F Vogel goto out;
14798cfa0ad2SJack F Vogel
14804edd8523SJack F Vogel ret_val = e1000_setup_copper_link_generic(hw);
14818cfa0ad2SJack F Vogel out:
14828cfa0ad2SJack F Vogel return ret_val;
14838cfa0ad2SJack F Vogel }
14848cfa0ad2SJack F Vogel
14858cfa0ad2SJack F Vogel /**
14864edd8523SJack F Vogel * e1000_setup_serdes_link_82575 - Setup link for serdes
14878cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
14888cfa0ad2SJack F Vogel *
14894edd8523SJack F Vogel * Configure the physical coding sub-layer (PCS) link. The PCS link is
14904edd8523SJack F Vogel * used on copper connections where the serialized gigabit media independent
14914edd8523SJack F Vogel * interface (sgmii), or serdes fiber is being used. Configures the link
14924edd8523SJack F Vogel * for auto-negotiation or forces speed/duplex.
14938cfa0ad2SJack F Vogel **/
e1000_setup_serdes_link_82575(struct e1000_hw * hw)14944edd8523SJack F Vogel static s32 e1000_setup_serdes_link_82575(struct e1000_hw *hw)
14958cfa0ad2SJack F Vogel {
14966ab6bfe3SJack F Vogel u32 ctrl_ext, ctrl_reg, reg, anadv_reg;
14974edd8523SJack F Vogel bool pcs_autoneg;
14984dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS;
14994dab5c37SJack F Vogel u16 data;
15008cfa0ad2SJack F Vogel
15014edd8523SJack F Vogel DEBUGFUNC("e1000_setup_serdes_link_82575");
15024edd8523SJack F Vogel
15034edd8523SJack F Vogel if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
15044edd8523SJack F Vogel !e1000_sgmii_active_82575(hw))
15054dab5c37SJack F Vogel return ret_val;
15068cfa0ad2SJack F Vogel
15078cfa0ad2SJack F Vogel /*
15088cfa0ad2SJack F Vogel * On the 82575, SerDes loopback mode persists until it is
15098cfa0ad2SJack F Vogel * explicitly turned off or a power cycle is performed. A read to
15108cfa0ad2SJack F Vogel * the register does not indicate its status. Therefore, we ensure
15118cfa0ad2SJack F Vogel * loopback mode is disabled during initialization.
15128cfa0ad2SJack F Vogel */
15138cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_SCTL, E1000_SCTL_DISABLE_SERDES_LOOPBACK);
15148cfa0ad2SJack F Vogel
15154edd8523SJack F Vogel /* power on the sfp cage if present */
15164edd8523SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
15174edd8523SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
15184edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
15194edd8523SJack F Vogel
15204edd8523SJack F Vogel ctrl_reg = E1000_READ_REG(hw, E1000_CTRL);
15214edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SLU;
15224edd8523SJack F Vogel
1523a69ed8dfSJack F Vogel /* set both sw defined pins on 82575/82576*/
1524a69ed8dfSJack F Vogel if (hw->mac.type == e1000_82575 || hw->mac.type == e1000_82576)
15254edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SWDPIN0 | E1000_CTRL_SWDPIN1;
15268cfa0ad2SJack F Vogel
15274edd8523SJack F Vogel reg = E1000_READ_REG(hw, E1000_PCS_LCTL);
15284edd8523SJack F Vogel
15294edd8523SJack F Vogel /* default pcs_autoneg to the same setting as mac autoneg */
15304edd8523SJack F Vogel pcs_autoneg = hw->mac.autoneg;
15314edd8523SJack F Vogel
15324edd8523SJack F Vogel switch (ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK) {
15334edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII:
15344edd8523SJack F Vogel /* sgmii mode lets the phy handle forcing speed/duplex */
15351bbdc25fSKevin Bowling pcs_autoneg = true;
15364edd8523SJack F Vogel /* autoneg time out should be disabled for SGMII mode */
15374edd8523SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_TIMEOUT);
15384edd8523SJack F Vogel break;
15394edd8523SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
15404edd8523SJack F Vogel /* disable PCS autoneg and support parallel detect only */
15411bbdc25fSKevin Bowling pcs_autoneg = false;
1542a5b0fd9cSToomas Soome /* FALLTHROUGH */
15434edd8523SJack F Vogel default:
15444dab5c37SJack F Vogel if (hw->mac.type == e1000_82575 ||
15454dab5c37SJack F Vogel hw->mac.type == e1000_82576) {
15464dab5c37SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPAT, 1, &data);
15474dab5c37SJack F Vogel if (ret_val) {
15484dab5c37SJack F Vogel DEBUGOUT("NVM Read Error\n");
15494dab5c37SJack F Vogel return ret_val;
15504dab5c37SJack F Vogel }
15514dab5c37SJack F Vogel
15524dab5c37SJack F Vogel if (data & E1000_EEPROM_PCS_AUTONEG_DISABLE_BIT)
15531bbdc25fSKevin Bowling pcs_autoneg = false;
15544dab5c37SJack F Vogel }
15554dab5c37SJack F Vogel
15564edd8523SJack F Vogel /*
15574edd8523SJack F Vogel * non-SGMII modes only supports a speed of 1000/Full for the
15584edd8523SJack F Vogel * link so it is best to just force the MAC and let the pcs
15594edd8523SJack F Vogel * link either autoneg or be forced to 1000/Full
15604edd8523SJack F Vogel */
15614edd8523SJack F Vogel ctrl_reg |= E1000_CTRL_SPD_1000 | E1000_CTRL_FRCSPD |
15624edd8523SJack F Vogel E1000_CTRL_FD | E1000_CTRL_FRCDPX;
15634edd8523SJack F Vogel
15644edd8523SJack F Vogel /* set speed of 1000/Full if speed/duplex is forced */
15654edd8523SJack F Vogel reg |= E1000_PCS_LCTL_FSV_1000 | E1000_PCS_LCTL_FDV_FULL;
15664edd8523SJack F Vogel break;
15674edd8523SJack F Vogel }
15684edd8523SJack F Vogel
15694edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
15708cfa0ad2SJack F Vogel
15718cfa0ad2SJack F Vogel /*
15728cfa0ad2SJack F Vogel * New SerDes mode allows for forcing speed or autonegotiating speed
15738cfa0ad2SJack F Vogel * at 1gb. Autoneg should be default set by most drivers. This is the
15748cfa0ad2SJack F Vogel * mode that will be compatible with older link partners and switches.
15758cfa0ad2SJack F Vogel * However, both are supported by the hardware and some drivers/tools.
15768cfa0ad2SJack F Vogel */
15778cfa0ad2SJack F Vogel reg &= ~(E1000_PCS_LCTL_AN_ENABLE | E1000_PCS_LCTL_FLV_LINK_UP |
15788cfa0ad2SJack F Vogel E1000_PCS_LCTL_FSD | E1000_PCS_LCTL_FORCE_LINK);
15798cfa0ad2SJack F Vogel
15804edd8523SJack F Vogel if (pcs_autoneg) {
15814edd8523SJack F Vogel /* Set PCS register for autoneg */
15824edd8523SJack F Vogel reg |= E1000_PCS_LCTL_AN_ENABLE | /* Enable Autoneg */
15834edd8523SJack F Vogel E1000_PCS_LCTL_AN_RESTART; /* Restart autoneg */
15846ab6bfe3SJack F Vogel
15856ab6bfe3SJack F Vogel /* Disable force flow control for autoneg */
15866ab6bfe3SJack F Vogel reg &= ~E1000_PCS_LCTL_FORCE_FCTRL;
15876ab6bfe3SJack F Vogel
15886ab6bfe3SJack F Vogel /* Configure flow control advertisement for autoneg */
15896ab6bfe3SJack F Vogel anadv_reg = E1000_READ_REG(hw, E1000_PCS_ANADV);
15906ab6bfe3SJack F Vogel anadv_reg &= ~(E1000_TXCW_ASM_DIR | E1000_TXCW_PAUSE);
15916ab6bfe3SJack F Vogel
15926ab6bfe3SJack F Vogel switch (hw->fc.requested_mode) {
15936ab6bfe3SJack F Vogel case e1000_fc_full:
15946ab6bfe3SJack F Vogel case e1000_fc_rx_pause:
15956ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_ASM_DIR;
15966ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_PAUSE;
15976ab6bfe3SJack F Vogel break;
15986ab6bfe3SJack F Vogel case e1000_fc_tx_pause:
15996ab6bfe3SJack F Vogel anadv_reg |= E1000_TXCW_ASM_DIR;
16006ab6bfe3SJack F Vogel break;
16016ab6bfe3SJack F Vogel default:
16026ab6bfe3SJack F Vogel break;
16036ab6bfe3SJack F Vogel }
16046ab6bfe3SJack F Vogel
16056ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_ANADV, anadv_reg);
16066ab6bfe3SJack F Vogel
16074edd8523SJack F Vogel DEBUGOUT1("Configuring Autoneg:PCS_LCTL=0x%08X\n", reg);
16084edd8523SJack F Vogel } else {
16094edd8523SJack F Vogel /* Set PCS register for forced link */
1610a69ed8dfSJack F Vogel reg |= E1000_PCS_LCTL_FSD; /* Force Speed */
16116ab6bfe3SJack F Vogel
16126ab6bfe3SJack F Vogel /* Force flow control for forced link */
16136ab6bfe3SJack F Vogel reg |= E1000_PCS_LCTL_FORCE_FCTRL;
16146ab6bfe3SJack F Vogel
16154edd8523SJack F Vogel DEBUGOUT1("Configuring Forced Link:PCS_LCTL=0x%08X\n", reg);
16168cfa0ad2SJack F Vogel }
16178cfa0ad2SJack F Vogel
16188cfa0ad2SJack F Vogel E1000_WRITE_REG(hw, E1000_PCS_LCTL, reg);
16198cfa0ad2SJack F Vogel
16206ab6bfe3SJack F Vogel if (!pcs_autoneg && !e1000_sgmii_active_82575(hw))
16214edd8523SJack F Vogel e1000_force_mac_fc_generic(hw);
16224edd8523SJack F Vogel
16234dab5c37SJack F Vogel return ret_val;
16244dab5c37SJack F Vogel }
16254dab5c37SJack F Vogel
16264dab5c37SJack F Vogel /**
16274dab5c37SJack F Vogel * e1000_get_media_type_82575 - derives current media type.
16284dab5c37SJack F Vogel * @hw: pointer to the HW structure
16294dab5c37SJack F Vogel *
16304dab5c37SJack F Vogel * The media type is chosen reflecting few settings.
16314dab5c37SJack F Vogel * The following are taken into account:
16324dab5c37SJack F Vogel * - link mode set in the current port Init Control Word #3
16334dab5c37SJack F Vogel * - current link mode settings in CSR register
16344dab5c37SJack F Vogel * - MDIO vs. I2C PHY control interface chosen
16354dab5c37SJack F Vogel * - SFP module media type
16364dab5c37SJack F Vogel **/
e1000_get_media_type_82575(struct e1000_hw * hw)16374dab5c37SJack F Vogel static s32 e1000_get_media_type_82575(struct e1000_hw *hw)
16384dab5c37SJack F Vogel {
16394dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
16406ab6bfe3SJack F Vogel s32 ret_val = E1000_SUCCESS;
16414dab5c37SJack F Vogel u32 ctrl_ext = 0;
16426ab6bfe3SJack F Vogel u32 link_mode = 0;
16434dab5c37SJack F Vogel
16444dab5c37SJack F Vogel /* Set internal phy as default */
16451bbdc25fSKevin Bowling dev_spec->sgmii_active = false;
16461bbdc25fSKevin Bowling dev_spec->module_plugged = false;
16474dab5c37SJack F Vogel
16484dab5c37SJack F Vogel /* Get CSR setting */
16494dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
16504dab5c37SJack F Vogel
16516ab6bfe3SJack F Vogel /* extract link mode setting */
16526ab6bfe3SJack F Vogel link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
16534dab5c37SJack F Vogel
16546ab6bfe3SJack F Vogel switch (link_mode) {
16554dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_1000BASE_KX:
16564dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes;
16574dab5c37SJack F Vogel break;
16584dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_GMII:
16594dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper;
16604dab5c37SJack F Vogel break;
16614dab5c37SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_SGMII:
16624dab5c37SJack F Vogel /* Get phy control interface type set (MDIO vs. I2C)*/
16634dab5c37SJack F Vogel if (e1000_sgmii_uses_mdio_82575(hw)) {
16644dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper;
16651bbdc25fSKevin Bowling dev_spec->sgmii_active = true;
16664dab5c37SJack F Vogel break;
16674dab5c37SJack F Vogel }
16686ab6bfe3SJack F Vogel /* fall through for I2C based SGMII */
1669a5b0fd9cSToomas Soome /* FALLTHROUGH */
16706ab6bfe3SJack F Vogel case E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES:
16716ab6bfe3SJack F Vogel /* read media type from SFP EEPROM */
16726ab6bfe3SJack F Vogel ret_val = e1000_set_sfp_media_type_82575(hw);
16736ab6bfe3SJack F Vogel if ((ret_val != E1000_SUCCESS) ||
16746ab6bfe3SJack F Vogel (hw->phy.media_type == e1000_media_type_unknown)) {
16754dab5c37SJack F Vogel /*
16766ab6bfe3SJack F Vogel * If media type was not identified then return media
16776ab6bfe3SJack F Vogel * type defined by the CTRL_EXT settings.
16784dab5c37SJack F Vogel */
16796ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes;
16806ab6bfe3SJack F Vogel
16816ab6bfe3SJack F Vogel if (link_mode == E1000_CTRL_EXT_LINK_MODE_SGMII) {
16826ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_copper;
16831bbdc25fSKevin Bowling dev_spec->sgmii_active = true;
16844dab5c37SJack F Vogel }
16854dab5c37SJack F Vogel
16866ab6bfe3SJack F Vogel break;
16876ab6bfe3SJack F Vogel }
16886ab6bfe3SJack F Vogel
16896ab6bfe3SJack F Vogel /* change current link mode setting */
16906ab6bfe3SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_LINK_MODE_MASK;
16916ab6bfe3SJack F Vogel
1692*15853a5fSKevin Bowling if (dev_spec->sgmii_active)
16936ab6bfe3SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_SGMII;
16944dab5c37SJack F Vogel else
16956ab6bfe3SJack F Vogel ctrl_ext |= E1000_CTRL_EXT_LINK_MODE_PCIE_SERDES;
16966ab6bfe3SJack F Vogel
16976ab6bfe3SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
16986ab6bfe3SJack F Vogel
16996ab6bfe3SJack F Vogel break;
1700*15853a5fSKevin Bowling default:
1701*15853a5fSKevin Bowling DEBUGOUT("e1000_get_media_type_82575 unknown link type\n");
1702*15853a5fSKevin Bowling break;
17034dab5c37SJack F Vogel }
17044dab5c37SJack F Vogel
17054dab5c37SJack F Vogel return ret_val;
17064dab5c37SJack F Vogel }
17074dab5c37SJack F Vogel
17084dab5c37SJack F Vogel /**
17094dab5c37SJack F Vogel * e1000_set_sfp_media_type_82575 - derives SFP module media type.
17104dab5c37SJack F Vogel * @hw: pointer to the HW structure
17114dab5c37SJack F Vogel *
17124dab5c37SJack F Vogel * The media type is chosen based on SFP module.
17134dab5c37SJack F Vogel * compatibility flags retrieved from SFP ID EEPROM.
17144dab5c37SJack F Vogel **/
e1000_set_sfp_media_type_82575(struct e1000_hw * hw)17154dab5c37SJack F Vogel static s32 e1000_set_sfp_media_type_82575(struct e1000_hw *hw)
17164dab5c37SJack F Vogel {
17174dab5c37SJack F Vogel s32 ret_val = E1000_ERR_CONFIG;
17184dab5c37SJack F Vogel u32 ctrl_ext = 0;
17194dab5c37SJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
17206ab6bfe3SJack F Vogel struct sfp_e1000_flags *eth_flags = &dev_spec->eth_flags;
17214dab5c37SJack F Vogel u8 tranceiver_type = 0;
17226ab6bfe3SJack F Vogel s32 timeout = 3;
17234dab5c37SJack F Vogel
17246ab6bfe3SJack F Vogel /* Turn I2C interface ON and power on sfp cage */
17254dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
17266ab6bfe3SJack F Vogel ctrl_ext &= ~E1000_CTRL_EXT_SDP3_DATA;
17274dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_I2C_ENA);
17284dab5c37SJack F Vogel
17296ab6bfe3SJack F Vogel E1000_WRITE_FLUSH(hw);
17306ab6bfe3SJack F Vogel
17314dab5c37SJack F Vogel /* Read SFP module data */
17326ab6bfe3SJack F Vogel while (timeout) {
17334dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw,
17344dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_IDENTIFIER_OFFSET),
17354dab5c37SJack F Vogel &tranceiver_type);
17366ab6bfe3SJack F Vogel if (ret_val == E1000_SUCCESS)
17376ab6bfe3SJack F Vogel break;
17386ab6bfe3SJack F Vogel msec_delay(100);
17396ab6bfe3SJack F Vogel timeout--;
17406ab6bfe3SJack F Vogel }
17414dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS)
17424dab5c37SJack F Vogel goto out;
17436ab6bfe3SJack F Vogel
17444dab5c37SJack F Vogel ret_val = e1000_read_sfp_data_byte(hw,
17454dab5c37SJack F Vogel E1000_I2CCMD_SFP_DATA_ADDR(E1000_SFF_ETH_FLAGS_OFFSET),
17466ab6bfe3SJack F Vogel (u8 *)eth_flags);
17474dab5c37SJack F Vogel if (ret_val != E1000_SUCCESS)
17484dab5c37SJack F Vogel goto out;
17496ab6bfe3SJack F Vogel
17506ab6bfe3SJack F Vogel /* Check if there is some SFP module plugged and powered */
17514dab5c37SJack F Vogel if ((tranceiver_type == E1000_SFF_IDENTIFIER_SFP) ||
1752*15853a5fSKevin Bowling (tranceiver_type == E1000_SFF_IDENTIFIER_SFF))
17531bbdc25fSKevin Bowling dev_spec->module_plugged = true;
1754*15853a5fSKevin Bowling else
1755*15853a5fSKevin Bowling DEBUGOUT("PHY module is not SFP/SFF %x\n", tranceiver_type);
1756*15853a5fSKevin Bowling
17576ab6bfe3SJack F Vogel if (eth_flags->e1000_base_lx || eth_flags->e1000_base_sx) {
17584dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes;
1759*15853a5fSKevin Bowling DEBUGOUT("PHY module is 1000_base_lxsx\n");
1760*15853a5fSKevin Bowling } else if (eth_flags->e100_base_fx || eth_flags->e100_base_lx) {
17611bbdc25fSKevin Bowling dev_spec->sgmii_active = true;
17626ab6bfe3SJack F Vogel hw->phy.media_type = e1000_media_type_internal_serdes;
1763*15853a5fSKevin Bowling DEBUGOUT("PHY module is 100_base_fxlx\n");
17646ab6bfe3SJack F Vogel } else if (eth_flags->e1000_base_t) {
17651bbdc25fSKevin Bowling dev_spec->sgmii_active = true;
17664dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_copper;
1767*15853a5fSKevin Bowling DEBUGOUT("PHY module is 1000_base_t\n");
17684dab5c37SJack F Vogel } else {
17694dab5c37SJack F Vogel hw->phy.media_type = e1000_media_type_unknown;
17704dab5c37SJack F Vogel DEBUGOUT("PHY module has not been recognized\n");
17714dab5c37SJack F Vogel }
1772*15853a5fSKevin Bowling
17734dab5c37SJack F Vogel ret_val = E1000_SUCCESS;
17744dab5c37SJack F Vogel out:
17754dab5c37SJack F Vogel /* Restore I2C interface setting */
17764dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
17774dab5c37SJack F Vogel return ret_val;
17788cfa0ad2SJack F Vogel }
17798cfa0ad2SJack F Vogel
17808cfa0ad2SJack F Vogel /**
17818cfa0ad2SJack F Vogel * e1000_valid_led_default_82575 - Verify a valid default LED config
17828cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
17838cfa0ad2SJack F Vogel * @data: pointer to the NVM (EEPROM)
17848cfa0ad2SJack F Vogel *
17858cfa0ad2SJack F Vogel * Read the EEPROM for the current default LED configuration. If the
17868cfa0ad2SJack F Vogel * LED configuration is not valid, set to a valid LED configuration.
17878cfa0ad2SJack F Vogel **/
e1000_valid_led_default_82575(struct e1000_hw * hw,u16 * data)17888cfa0ad2SJack F Vogel static s32 e1000_valid_led_default_82575(struct e1000_hw *hw, u16 *data)
17898cfa0ad2SJack F Vogel {
17908cfa0ad2SJack F Vogel s32 ret_val;
17918cfa0ad2SJack F Vogel
17928cfa0ad2SJack F Vogel DEBUGFUNC("e1000_valid_led_default_82575");
17938cfa0ad2SJack F Vogel
17948cfa0ad2SJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
17958cfa0ad2SJack F Vogel if (ret_val) {
17968cfa0ad2SJack F Vogel DEBUGOUT("NVM Read Error\n");
17978cfa0ad2SJack F Vogel goto out;
17988cfa0ad2SJack F Vogel }
17998cfa0ad2SJack F Vogel
18008cfa0ad2SJack F Vogel if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF) {
18018cfa0ad2SJack F Vogel switch (hw->phy.media_type) {
18028cfa0ad2SJack F Vogel case e1000_media_type_internal_serdes:
18038cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT_82575_SERDES;
18048cfa0ad2SJack F Vogel break;
18058cfa0ad2SJack F Vogel case e1000_media_type_copper:
18068cfa0ad2SJack F Vogel default:
18078cfa0ad2SJack F Vogel *data = ID_LED_DEFAULT;
18088cfa0ad2SJack F Vogel break;
18098cfa0ad2SJack F Vogel }
18108cfa0ad2SJack F Vogel }
18118cfa0ad2SJack F Vogel out:
18128cfa0ad2SJack F Vogel return ret_val;
18138cfa0ad2SJack F Vogel }
18148cfa0ad2SJack F Vogel
18158cfa0ad2SJack F Vogel /**
18168cfa0ad2SJack F Vogel * e1000_sgmii_active_82575 - Return sgmii state
18178cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
18188cfa0ad2SJack F Vogel *
18198cfa0ad2SJack F Vogel * 82575 silicon has a serialized gigabit media independent interface (sgmii)
18208cfa0ad2SJack F Vogel * which can be enabled for use in the embedded applications. Simply
18218cfa0ad2SJack F Vogel * return the current state of the sgmii interface.
18228cfa0ad2SJack F Vogel **/
e1000_sgmii_active_82575(struct e1000_hw * hw)18238cfa0ad2SJack F Vogel static bool e1000_sgmii_active_82575(struct e1000_hw *hw)
18248cfa0ad2SJack F Vogel {
1825daf9197cSJack F Vogel struct e1000_dev_spec_82575 *dev_spec = &hw->dev_spec._82575;
1826daf9197cSJack F Vogel return dev_spec->sgmii_active;
18278cfa0ad2SJack F Vogel }
18288cfa0ad2SJack F Vogel
18298cfa0ad2SJack F Vogel /**
18308cfa0ad2SJack F Vogel * e1000_reset_init_script_82575 - Inits HW defaults after reset
18318cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
18328cfa0ad2SJack F Vogel *
18338cfa0ad2SJack F Vogel * Inits recommended HW defaults after a reset when there is no EEPROM
18348cfa0ad2SJack F Vogel * detected. This is only for the 82575.
18358cfa0ad2SJack F Vogel **/
e1000_reset_init_script_82575(struct e1000_hw * hw)18366b9d35faSGuinan Sun s32 e1000_reset_init_script_82575(struct e1000_hw *hw)
18378cfa0ad2SJack F Vogel {
18388cfa0ad2SJack F Vogel DEBUGFUNC("e1000_reset_init_script_82575");
18398cfa0ad2SJack F Vogel
18408cfa0ad2SJack F Vogel if (hw->mac.type == e1000_82575) {
18418cfa0ad2SJack F Vogel DEBUGOUT("Running reset init script for 82575\n");
18428cfa0ad2SJack F Vogel /* SerDes configuration via SERDESCTRL */
18438cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x00, 0x0C);
18448cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x01, 0x78);
18458cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x1B, 0x23);
18468cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCTL, 0x23, 0x15);
18478cfa0ad2SJack F Vogel
18488cfa0ad2SJack F Vogel /* CCM configuration via CCMCTL register */
18498cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x14, 0x00);
18508cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_CCMCTL, 0x10, 0x00);
18518cfa0ad2SJack F Vogel
18528cfa0ad2SJack F Vogel /* PCIe lanes configuration */
18538cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x00, 0xEC);
18548cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x61, 0xDF);
18558cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x34, 0x05);
18568cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_GIOCTL, 0x2F, 0x81);
18578cfa0ad2SJack F Vogel
18588cfa0ad2SJack F Vogel /* PCIe PLL Configuration */
18598cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x02, 0x47);
18608cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x14, 0x00);
18618cfa0ad2SJack F Vogel e1000_write_8bit_ctrl_reg_generic(hw, E1000_SCCTL, 0x10, 0x00);
18628cfa0ad2SJack F Vogel }
18638cfa0ad2SJack F Vogel
18648cfa0ad2SJack F Vogel return E1000_SUCCESS;
18658cfa0ad2SJack F Vogel }
18668cfa0ad2SJack F Vogel
18678cfa0ad2SJack F Vogel /**
18688cfa0ad2SJack F Vogel * e1000_read_mac_addr_82575 - Read device MAC address
18698cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
18708cfa0ad2SJack F Vogel **/
e1000_read_mac_addr_82575(struct e1000_hw * hw)18718cfa0ad2SJack F Vogel static s32 e1000_read_mac_addr_82575(struct e1000_hw *hw)
18728cfa0ad2SJack F Vogel {
18738cc64f1eSJack F Vogel s32 ret_val;
18748cfa0ad2SJack F Vogel
18758cfa0ad2SJack F Vogel DEBUGFUNC("e1000_read_mac_addr_82575");
1876d035aa2dSJack F Vogel
1877d035aa2dSJack F Vogel /*
1878d035aa2dSJack F Vogel * If there's an alternate MAC address place it in RAR0
1879d035aa2dSJack F Vogel * so that it will override the Si installed default perm
1880d035aa2dSJack F Vogel * address.
1881d035aa2dSJack F Vogel */
1882d035aa2dSJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw);
1883d035aa2dSJack F Vogel if (ret_val)
1884d035aa2dSJack F Vogel goto out;
1885d035aa2dSJack F Vogel
18868cfa0ad2SJack F Vogel ret_val = e1000_read_mac_addr_generic(hw);
18878cfa0ad2SJack F Vogel
1888d035aa2dSJack F Vogel out:
18898cfa0ad2SJack F Vogel return ret_val;
18908cfa0ad2SJack F Vogel }
18918cfa0ad2SJack F Vogel
18928cfa0ad2SJack F Vogel /**
1893a69ed8dfSJack F Vogel * e1000_config_collision_dist_82575 - Configure collision distance
1894a69ed8dfSJack F Vogel * @hw: pointer to the HW structure
1895a69ed8dfSJack F Vogel *
1896a69ed8dfSJack F Vogel * Configures the collision distance to the default value and is used
1897a69ed8dfSJack F Vogel * during link setup.
1898a69ed8dfSJack F Vogel **/
e1000_config_collision_dist_82575(struct e1000_hw * hw)1899a69ed8dfSJack F Vogel static void e1000_config_collision_dist_82575(struct e1000_hw *hw)
1900a69ed8dfSJack F Vogel {
1901a69ed8dfSJack F Vogel u32 tctl_ext;
1902a69ed8dfSJack F Vogel
1903a69ed8dfSJack F Vogel DEBUGFUNC("e1000_config_collision_dist_82575");
1904a69ed8dfSJack F Vogel
1905a69ed8dfSJack F Vogel tctl_ext = E1000_READ_REG(hw, E1000_TCTL_EXT);
1906a69ed8dfSJack F Vogel
1907a69ed8dfSJack F Vogel tctl_ext &= ~E1000_TCTL_EXT_COLD;
1908a69ed8dfSJack F Vogel tctl_ext |= E1000_COLLISION_DISTANCE << E1000_TCTL_EXT_COLD_SHIFT;
1909a69ed8dfSJack F Vogel
1910a69ed8dfSJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL_EXT, tctl_ext);
1911a69ed8dfSJack F Vogel E1000_WRITE_FLUSH(hw);
1912a69ed8dfSJack F Vogel }
1913a69ed8dfSJack F Vogel
1914a69ed8dfSJack F Vogel /**
19158cfa0ad2SJack F Vogel * e1000_clear_hw_cntrs_82575 - Clear device specific hardware counters
19168cfa0ad2SJack F Vogel * @hw: pointer to the HW structure
19178cfa0ad2SJack F Vogel *
19188cfa0ad2SJack F Vogel * Clears the hardware counters by reading the counter registers.
19198cfa0ad2SJack F Vogel **/
e1000_clear_hw_cntrs_82575(struct e1000_hw * hw)19208cfa0ad2SJack F Vogel static void e1000_clear_hw_cntrs_82575(struct e1000_hw *hw)
19218cfa0ad2SJack F Vogel {
19228cfa0ad2SJack F Vogel DEBUGFUNC("e1000_clear_hw_cntrs_82575");
19238cfa0ad2SJack F Vogel
19248cfa0ad2SJack F Vogel e1000_clear_hw_cntrs_base_generic(hw);
19258cfa0ad2SJack F Vogel
1926daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC64);
1927daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC127);
1928daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC255);
1929daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC511);
1930daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1023);
1931daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PRC1522);
1932daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC64);
1933daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC127);
1934daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC255);
1935daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC511);
1936daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1023);
1937daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_PTC1522);
19388cfa0ad2SJack F Vogel
1939daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ALGNERRC);
1940daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RXERRC);
1941daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TNCRS);
1942daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CEXTERR);
1943daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTC);
1944daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_TSCTFC);
19458cfa0ad2SJack F Vogel
1946daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPRC);
1947daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPDC);
1948daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_MGTPTC);
19498cfa0ad2SJack F Vogel
1950daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_IAC);
1951daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXOC);
19528cfa0ad2SJack F Vogel
1953daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXPTC);
1954daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXATC);
1955daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXPTC);
1956daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXATC);
1957daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQEC);
1958daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICTXQMTC);
1959daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_ICRXDMTC);
19608cfa0ad2SJack F Vogel
1961daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBTMPC);
1962daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTDPMC);
1963daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_CBRMPC);
1964daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_RPTHC);
1965daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGPTC);
1966daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HTCBDPC);
1967daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCL);
1968daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGORCH);
1969daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCL);
1970daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_HGOTCH);
1971daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_LENERRS);
19728cfa0ad2SJack F Vogel
19738cfa0ad2SJack F Vogel /* This register should not be read in copper configurations */
19744edd8523SJack F Vogel if ((hw->phy.media_type == e1000_media_type_internal_serdes) ||
19754edd8523SJack F Vogel e1000_sgmii_active_82575(hw))
1976daf9197cSJack F Vogel E1000_READ_REG(hw, E1000_SCVPC);
19778cfa0ad2SJack F Vogel }
19789d81738fSJack F Vogel
19798cfa0ad2SJack F Vogel /**
19809d81738fSJack F Vogel * e1000_set_pcie_completion_timeout - set pci-e completion timeout
19819d81738fSJack F Vogel * @hw: pointer to the HW structure
19829d81738fSJack F Vogel *
19839d81738fSJack F Vogel * The defaults for 82575 and 82576 should be in the range of 50us to 50ms,
19849d81738fSJack F Vogel * however the hardware default for these parts is 500us to 1ms which is less
19859d81738fSJack F Vogel * than the 10ms recommended by the pci-e spec. To address this we need to
19869d81738fSJack F Vogel * increase the value to either 10ms to 200ms for capability version 1 config,
19879d81738fSJack F Vogel * or 16ms to 55ms for version 2.
19889d81738fSJack F Vogel **/
e1000_set_pcie_completion_timeout(struct e1000_hw * hw)19899d81738fSJack F Vogel static s32 e1000_set_pcie_completion_timeout(struct e1000_hw *hw)
19909d81738fSJack F Vogel {
19919d81738fSJack F Vogel u32 gcr = E1000_READ_REG(hw, E1000_GCR);
19929d81738fSJack F Vogel s32 ret_val = E1000_SUCCESS;
19939d81738fSJack F Vogel u16 pcie_devctl2;
19949d81738fSJack F Vogel
19959d81738fSJack F Vogel /* only take action if timeout value is defaulted to 0 */
19969d81738fSJack F Vogel if (gcr & E1000_GCR_CMPL_TMOUT_MASK)
19979d81738fSJack F Vogel goto out;
19989d81738fSJack F Vogel
19999d81738fSJack F Vogel /*
20009d81738fSJack F Vogel * if capababilities version is type 1 we can write the
20019d81738fSJack F Vogel * timeout of 10ms to 200ms through the GCR register
20029d81738fSJack F Vogel */
20039d81738fSJack F Vogel if (!(gcr & E1000_GCR_CAP_VER2)) {
20049d81738fSJack F Vogel gcr |= E1000_GCR_CMPL_TMOUT_10ms;
20059d81738fSJack F Vogel goto out;
20069d81738fSJack F Vogel }
20079d81738fSJack F Vogel
20089d81738fSJack F Vogel /*
20099d81738fSJack F Vogel * for version 2 capabilities we need to write the config space
20109d81738fSJack F Vogel * directly in order to set the completion timeout value for
20119d81738fSJack F Vogel * 16ms to 55ms
20129d81738fSJack F Vogel */
20139d81738fSJack F Vogel ret_val = e1000_read_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
20149d81738fSJack F Vogel &pcie_devctl2);
20159d81738fSJack F Vogel if (ret_val)
20169d81738fSJack F Vogel goto out;
20179d81738fSJack F Vogel
20189d81738fSJack F Vogel pcie_devctl2 |= PCIE_DEVICE_CONTROL2_16ms;
20199d81738fSJack F Vogel
20209d81738fSJack F Vogel ret_val = e1000_write_pcie_cap_reg(hw, PCIE_DEVICE_CONTROL2,
20219d81738fSJack F Vogel &pcie_devctl2);
20229d81738fSJack F Vogel out:
20239d81738fSJack F Vogel /* disable completion timeout resend */
20249d81738fSJack F Vogel gcr &= ~E1000_GCR_CMPL_TMOUT_RESEND;
20259d81738fSJack F Vogel
20269d81738fSJack F Vogel E1000_WRITE_REG(hw, E1000_GCR, gcr);
20279d81738fSJack F Vogel return ret_val;
20289d81738fSJack F Vogel }
20299d81738fSJack F Vogel
20307d9119bdSJack F Vogel /**
20317d9119bdSJack F Vogel * e1000_vmdq_set_anti_spoofing_pf - enable or disable anti-spoofing
20327d9119bdSJack F Vogel * @hw: pointer to the hardware struct
20337d9119bdSJack F Vogel * @enable: state to enter, either enabled or disabled
20347d9119bdSJack F Vogel * @pf: Physical Function pool - do not set anti-spoofing for the PF
20357d9119bdSJack F Vogel *
20367d9119bdSJack F Vogel * enables/disables L2 switch anti-spoofing functionality.
20377d9119bdSJack F Vogel **/
e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw * hw,bool enable,int pf)20387d9119bdSJack F Vogel void e1000_vmdq_set_anti_spoofing_pf(struct e1000_hw *hw, bool enable, int pf)
20397d9119bdSJack F Vogel {
20407609433eSJack F Vogel u32 reg_val, reg_offset;
20417d9119bdSJack F Vogel
20427d9119bdSJack F Vogel switch (hw->mac.type) {
20437d9119bdSJack F Vogel case e1000_82576:
20447609433eSJack F Vogel reg_offset = E1000_DTXSWC;
20457d9119bdSJack F Vogel break;
20464dab5c37SJack F Vogel case e1000_i350:
20477609433eSJack F Vogel case e1000_i354:
20487609433eSJack F Vogel reg_offset = E1000_TXSWC;
20497609433eSJack F Vogel break;
20507609433eSJack F Vogel default:
20517609433eSJack F Vogel return;
20527609433eSJack F Vogel }
20537609433eSJack F Vogel
20547609433eSJack F Vogel reg_val = E1000_READ_REG(hw, reg_offset);
20554dab5c37SJack F Vogel if (enable) {
20567609433eSJack F Vogel reg_val |= (E1000_DTXSWC_MAC_SPOOF_MASK |
20574dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK);
20584dab5c37SJack F Vogel /* The PF can spoof - it has to in order to
20594dab5c37SJack F Vogel * support emulation mode NICs
20604dab5c37SJack F Vogel */
20617609433eSJack F Vogel reg_val ^= (1 << pf | 1 << (pf + MAX_NUM_VFS));
20624dab5c37SJack F Vogel } else {
20637609433eSJack F Vogel reg_val &= ~(E1000_DTXSWC_MAC_SPOOF_MASK |
20644dab5c37SJack F Vogel E1000_DTXSWC_VLAN_SPOOF_MASK);
20654dab5c37SJack F Vogel }
20667609433eSJack F Vogel E1000_WRITE_REG(hw, reg_offset, reg_val);
20677d9119bdSJack F Vogel }
20687d9119bdSJack F Vogel
20694edd8523SJack F Vogel /**
20704edd8523SJack F Vogel * e1000_vmdq_set_loopback_pf - enable or disable vmdq loopback
20714edd8523SJack F Vogel * @hw: pointer to the hardware struct
20724edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled
20734edd8523SJack F Vogel *
20744edd8523SJack F Vogel * enables/disables L2 switch loopback functionality.
20754edd8523SJack F Vogel **/
e1000_vmdq_set_loopback_pf(struct e1000_hw * hw,bool enable)20764edd8523SJack F Vogel void e1000_vmdq_set_loopback_pf(struct e1000_hw *hw, bool enable)
20774edd8523SJack F Vogel {
20788ec87fc5SJack F Vogel u32 dtxswc;
20794edd8523SJack F Vogel
20808ec87fc5SJack F Vogel switch (hw->mac.type) {
20818ec87fc5SJack F Vogel case e1000_82576:
20828ec87fc5SJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_DTXSWC);
20834edd8523SJack F Vogel if (enable)
20844edd8523SJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
20854edd8523SJack F Vogel else
20864edd8523SJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
20874edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_DTXSWC, dtxswc);
20888ec87fc5SJack F Vogel break;
2089f0ecc46dSJack F Vogel case e1000_i350:
20907609433eSJack F Vogel case e1000_i354:
2091f0ecc46dSJack F Vogel dtxswc = E1000_READ_REG(hw, E1000_TXSWC);
2092f0ecc46dSJack F Vogel if (enable)
2093f0ecc46dSJack F Vogel dtxswc |= E1000_DTXSWC_VMDQ_LOOPBACK_EN;
2094f0ecc46dSJack F Vogel else
2095f0ecc46dSJack F Vogel dtxswc &= ~E1000_DTXSWC_VMDQ_LOOPBACK_EN;
2096f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_TXSWC, dtxswc);
2097f0ecc46dSJack F Vogel break;
20988ec87fc5SJack F Vogel default:
20998ec87fc5SJack F Vogel /* Currently no other hardware supports loopback */
21008ec87fc5SJack F Vogel break;
21018ec87fc5SJack F Vogel }
21028ec87fc5SJack F Vogel
21038ec87fc5SJack F Vogel
21044edd8523SJack F Vogel }
21054edd8523SJack F Vogel
21064edd8523SJack F Vogel /**
21074edd8523SJack F Vogel * e1000_vmdq_set_replication_pf - enable or disable vmdq replication
21084edd8523SJack F Vogel * @hw: pointer to the hardware struct
21094edd8523SJack F Vogel * @enable: state to enter, either enabled or disabled
21104edd8523SJack F Vogel *
21114edd8523SJack F Vogel * enables/disables replication of packets across multiple pools.
21124edd8523SJack F Vogel **/
e1000_vmdq_set_replication_pf(struct e1000_hw * hw,bool enable)21134edd8523SJack F Vogel void e1000_vmdq_set_replication_pf(struct e1000_hw *hw, bool enable)
21144edd8523SJack F Vogel {
21154edd8523SJack F Vogel u32 vt_ctl = E1000_READ_REG(hw, E1000_VT_CTL);
21164edd8523SJack F Vogel
21174edd8523SJack F Vogel if (enable)
21184edd8523SJack F Vogel vt_ctl |= E1000_VT_CTL_VM_REPL_EN;
21194edd8523SJack F Vogel else
21204edd8523SJack F Vogel vt_ctl &= ~E1000_VT_CTL_VM_REPL_EN;
21214edd8523SJack F Vogel
21224edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_VT_CTL, vt_ctl);
21234edd8523SJack F Vogel }
21244edd8523SJack F Vogel
21254edd8523SJack F Vogel /**
21264edd8523SJack F Vogel * e1000_read_phy_reg_82580 - Read 82580 MDI control register
21274edd8523SJack F Vogel * @hw: pointer to the HW structure
21284edd8523SJack F Vogel * @offset: register offset to be read
21294edd8523SJack F Vogel * @data: pointer to the read data
21304edd8523SJack F Vogel *
21314edd8523SJack F Vogel * Reads the MDI control register in the PHY at offset and stores the
21324edd8523SJack F Vogel * information read to data.
21334edd8523SJack F Vogel **/
e1000_read_phy_reg_82580(struct e1000_hw * hw,u32 offset,u16 * data)21344edd8523SJack F Vogel static s32 e1000_read_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 *data)
21354edd8523SJack F Vogel {
21364edd8523SJack F Vogel s32 ret_val;
21374edd8523SJack F Vogel
21384edd8523SJack F Vogel DEBUGFUNC("e1000_read_phy_reg_82580");
21394edd8523SJack F Vogel
21404edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw);
21414edd8523SJack F Vogel if (ret_val)
21424edd8523SJack F Vogel goto out;
21434edd8523SJack F Vogel
21444edd8523SJack F Vogel ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
21454edd8523SJack F Vogel
21464edd8523SJack F Vogel hw->phy.ops.release(hw);
21474edd8523SJack F Vogel
21484edd8523SJack F Vogel out:
21494edd8523SJack F Vogel return ret_val;
21504edd8523SJack F Vogel }
21514edd8523SJack F Vogel
21524edd8523SJack F Vogel /**
21534edd8523SJack F Vogel * e1000_write_phy_reg_82580 - Write 82580 MDI control register
21544edd8523SJack F Vogel * @hw: pointer to the HW structure
21554edd8523SJack F Vogel * @offset: register offset to write to
21564edd8523SJack F Vogel * @data: data to write to register at offset
21574edd8523SJack F Vogel *
21584edd8523SJack F Vogel * Writes data to MDI control register in the PHY at offset.
21594edd8523SJack F Vogel **/
e1000_write_phy_reg_82580(struct e1000_hw * hw,u32 offset,u16 data)21604edd8523SJack F Vogel static s32 e1000_write_phy_reg_82580(struct e1000_hw *hw, u32 offset, u16 data)
21614edd8523SJack F Vogel {
21624edd8523SJack F Vogel s32 ret_val;
21634edd8523SJack F Vogel
21644edd8523SJack F Vogel DEBUGFUNC("e1000_write_phy_reg_82580");
21654edd8523SJack F Vogel
21664edd8523SJack F Vogel ret_val = hw->phy.ops.acquire(hw);
21674edd8523SJack F Vogel if (ret_val)
21684edd8523SJack F Vogel goto out;
21694edd8523SJack F Vogel
21704edd8523SJack F Vogel ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
21714edd8523SJack F Vogel
21724edd8523SJack F Vogel hw->phy.ops.release(hw);
21734edd8523SJack F Vogel
21744edd8523SJack F Vogel out:
21754edd8523SJack F Vogel return ret_val;
21764edd8523SJack F Vogel }
2177a69ed8dfSJack F Vogel
21784edd8523SJack F Vogel /**
21797d9119bdSJack F Vogel * e1000_reset_mdicnfg_82580 - Reset MDICNFG destination and com_mdio bits
21807d9119bdSJack F Vogel * @hw: pointer to the HW structure
21817d9119bdSJack F Vogel *
2182cef367e6SEitan Adler * This resets the MDICNFG.Destination and MDICNFG.Com_MDIO bits based on
21837d9119bdSJack F Vogel * the values found in the EEPROM. This addresses an issue in which these
21847d9119bdSJack F Vogel * bits are not restored from EEPROM after reset.
21857d9119bdSJack F Vogel **/
e1000_reset_mdicnfg_82580(struct e1000_hw * hw)21867d9119bdSJack F Vogel static s32 e1000_reset_mdicnfg_82580(struct e1000_hw *hw)
21877d9119bdSJack F Vogel {
21887d9119bdSJack F Vogel s32 ret_val = E1000_SUCCESS;
21897d9119bdSJack F Vogel u32 mdicnfg;
2190f0ecc46dSJack F Vogel u16 nvm_data = 0;
21917d9119bdSJack F Vogel
21927d9119bdSJack F Vogel DEBUGFUNC("e1000_reset_mdicnfg_82580");
21937d9119bdSJack F Vogel
21947d9119bdSJack F Vogel if (hw->mac.type != e1000_82580)
21957d9119bdSJack F Vogel goto out;
21967d9119bdSJack F Vogel if (!e1000_sgmii_active_82575(hw))
21977d9119bdSJack F Vogel goto out;
21987d9119bdSJack F Vogel
21997d9119bdSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_INIT_CONTROL3_PORT_A +
22007d9119bdSJack F Vogel NVM_82580_LAN_FUNC_OFFSET(hw->bus.func), 1,
22017d9119bdSJack F Vogel &nvm_data);
22027d9119bdSJack F Vogel if (ret_val) {
22037d9119bdSJack F Vogel DEBUGOUT("NVM Read Error\n");
22047d9119bdSJack F Vogel goto out;
22057d9119bdSJack F Vogel }
22067d9119bdSJack F Vogel
22077d9119bdSJack F Vogel mdicnfg = E1000_READ_REG(hw, E1000_MDICNFG);
22087d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_EXT_MDIO)
22097d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_EXT_MDIO;
22107d9119bdSJack F Vogel if (nvm_data & NVM_WORD24_COM_MDIO)
22117d9119bdSJack F Vogel mdicnfg |= E1000_MDICNFG_COM_MDIO;
22127d9119bdSJack F Vogel E1000_WRITE_REG(hw, E1000_MDICNFG, mdicnfg);
22137d9119bdSJack F Vogel out:
22147d9119bdSJack F Vogel return ret_val;
22157d9119bdSJack F Vogel }
22167d9119bdSJack F Vogel
22177d9119bdSJack F Vogel /**
22184edd8523SJack F Vogel * e1000_reset_hw_82580 - Reset hardware
22194edd8523SJack F Vogel * @hw: pointer to the HW structure
22204edd8523SJack F Vogel *
22214edd8523SJack F Vogel * This resets function or entire device (all ports, etc.)
22224edd8523SJack F Vogel * to a known state.
22234edd8523SJack F Vogel **/
e1000_reset_hw_82580(struct e1000_hw * hw)22244edd8523SJack F Vogel static s32 e1000_reset_hw_82580(struct e1000_hw *hw)
22254edd8523SJack F Vogel {
22264edd8523SJack F Vogel s32 ret_val = E1000_SUCCESS;
22274edd8523SJack F Vogel /* BH SW mailbox bit in SW_FW_SYNC */
22284edd8523SJack F Vogel u16 swmbsw_mask = E1000_SW_SYNCH_MB;
2229f0ecc46dSJack F Vogel u32 ctrl;
22304edd8523SJack F Vogel bool global_device_reset = hw->dev_spec._82575.global_device_reset;
22314edd8523SJack F Vogel
22324edd8523SJack F Vogel DEBUGFUNC("e1000_reset_hw_82580");
22334edd8523SJack F Vogel
22341bbdc25fSKevin Bowling hw->dev_spec._82575.global_device_reset = false;
22354edd8523SJack F Vogel
22366ab6bfe3SJack F Vogel /* 82580 does not reliably do global_device_reset due to hw errata */
22376ab6bfe3SJack F Vogel if (hw->mac.type == e1000_82580)
22381bbdc25fSKevin Bowling global_device_reset = false;
22396ab6bfe3SJack F Vogel
22404edd8523SJack F Vogel /* Get current control state. */
22414edd8523SJack F Vogel ctrl = E1000_READ_REG(hw, E1000_CTRL);
22424edd8523SJack F Vogel
22434edd8523SJack F Vogel /*
22444edd8523SJack F Vogel * Prevent the PCI-E bus from sticking if there is no TLP connection
22454edd8523SJack F Vogel * on the last TLP read/write transaction when MAC is reset.
22464edd8523SJack F Vogel */
22474edd8523SJack F Vogel ret_val = e1000_disable_pcie_master_generic(hw);
22484edd8523SJack F Vogel if (ret_val)
22494edd8523SJack F Vogel DEBUGOUT("PCI-E Master disable polling has failed.\n");
22504edd8523SJack F Vogel
22514edd8523SJack F Vogel DEBUGOUT("Masking off all interrupts\n");
22524edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
22534edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_RCTL, 0);
22544edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
22554edd8523SJack F Vogel E1000_WRITE_FLUSH(hw);
22564edd8523SJack F Vogel
22574edd8523SJack F Vogel msec_delay(10);
22584edd8523SJack F Vogel
22594edd8523SJack F Vogel /* Determine whether or not a global dev reset is requested */
2260ab5d0362SJack F Vogel if (global_device_reset && hw->mac.ops.acquire_swfw_sync(hw,
22614dab5c37SJack F Vogel swmbsw_mask))
22621bbdc25fSKevin Bowling global_device_reset = false;
22634edd8523SJack F Vogel
22644dab5c37SJack F Vogel if (global_device_reset && !(E1000_READ_REG(hw, E1000_STATUS) &
22654dab5c37SJack F Vogel E1000_STAT_DEV_RST_SET))
22664edd8523SJack F Vogel ctrl |= E1000_CTRL_DEV_RST;
22674edd8523SJack F Vogel else
22684edd8523SJack F Vogel ctrl |= E1000_CTRL_RST;
22694edd8523SJack F Vogel
22704edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
22714edd8523SJack F Vogel
22728cc64f1eSJack F Vogel switch (hw->device_id) {
22738cc64f1eSJack F Vogel case E1000_DEV_ID_DH89XXCC_SGMII:
22748cc64f1eSJack F Vogel break;
22758cc64f1eSJack F Vogel default:
22768cc64f1eSJack F Vogel E1000_WRITE_FLUSH(hw);
22778cc64f1eSJack F Vogel break;
22788cc64f1eSJack F Vogel }
22798cc64f1eSJack F Vogel
22808cc64f1eSJack F Vogel /* Add delay to insure DEV_RST or RST has time to complete */
22814edd8523SJack F Vogel msec_delay(5);
22824edd8523SJack F Vogel
22834edd8523SJack F Vogel ret_val = e1000_get_auto_rd_done_generic(hw);
22844edd8523SJack F Vogel if (ret_val) {
22854edd8523SJack F Vogel /*
22864edd8523SJack F Vogel * When auto config read does not complete, do not
22874edd8523SJack F Vogel * return with an error. This can happen in situations
22884edd8523SJack F Vogel * where there is no eeprom and prevents getting link.
22894edd8523SJack F Vogel */
22904edd8523SJack F Vogel DEBUGOUT("Auto Read Done did not complete\n");
22914edd8523SJack F Vogel }
22924edd8523SJack F Vogel
22934edd8523SJack F Vogel /* clear global device reset status bit */
22944edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_STATUS, E1000_STAT_DEV_RST_SET);
22954edd8523SJack F Vogel
22964edd8523SJack F Vogel /* Clear any pending interrupt events. */
22974edd8523SJack F Vogel E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
2298f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_ICR);
22994edd8523SJack F Vogel
23007d9119bdSJack F Vogel ret_val = e1000_reset_mdicnfg_82580(hw);
23017d9119bdSJack F Vogel if (ret_val)
23027d9119bdSJack F Vogel DEBUGOUT("Could not reset MDICNFG based on EEPROM\n");
23037d9119bdSJack F Vogel
23044edd8523SJack F Vogel /* Install any alternate MAC address into RAR0 */
23054edd8523SJack F Vogel ret_val = e1000_check_alt_mac_addr_generic(hw);
23064edd8523SJack F Vogel
23074edd8523SJack F Vogel /* Release semaphore */
23084edd8523SJack F Vogel if (global_device_reset)
2309ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swmbsw_mask);
23104edd8523SJack F Vogel
23114edd8523SJack F Vogel return ret_val;
23124edd8523SJack F Vogel }
23134edd8523SJack F Vogel
23144edd8523SJack F Vogel /**
2315f0ecc46dSJack F Vogel * e1000_rxpbs_adjust_82580 - adjust RXPBS value to reflect actual Rx PBA size
23164edd8523SJack F Vogel * @data: data received by reading RXPBS register
23174edd8523SJack F Vogel *
23184edd8523SJack F Vogel * The 82580 uses a table based approach for packet buffer allocation sizes.
23194edd8523SJack F Vogel * This function converts the retrieved value into the correct table value
23204edd8523SJack F Vogel * 0x0 0x1 0x2 0x3 0x4 0x5 0x6 0x7
23214edd8523SJack F Vogel * 0x0 36 72 144 1 2 4 8 16
23224edd8523SJack F Vogel * 0x8 35 70 140 rsv rsv rsv rsv rsv
23234edd8523SJack F Vogel */
e1000_rxpbs_adjust_82580(u32 data)23244edd8523SJack F Vogel u16 e1000_rxpbs_adjust_82580(u32 data)
23254edd8523SJack F Vogel {
23264edd8523SJack F Vogel u16 ret_val = 0;
23274edd8523SJack F Vogel
23284edd8523SJack F Vogel if (data < E1000_82580_RXPBS_TABLE_SIZE)
23294edd8523SJack F Vogel ret_val = e1000_82580_rxpbs_table[data];
23304edd8523SJack F Vogel
23314edd8523SJack F Vogel return ret_val;
23324edd8523SJack F Vogel }
2333f0ecc46dSJack F Vogel
2334f0ecc46dSJack F Vogel /**
2335f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_with_offset - Validate EEPROM
2336f0ecc46dSJack F Vogel * checksum
2337f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
2338f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region
2339f0ecc46dSJack F Vogel *
2340f0ecc46dSJack F Vogel * Calculates the EEPROM checksum by reading/adding each word of the EEPROM
2341f0ecc46dSJack F Vogel * and then verifies that the sum of the EEPROM is equal to 0xBABA.
2342f0ecc46dSJack F Vogel **/
e1000_validate_nvm_checksum_with_offset(struct e1000_hw * hw,u16 offset)2343f0ecc46dSJack F Vogel s32 e1000_validate_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
2344f0ecc46dSJack F Vogel {
2345f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS;
2346f0ecc46dSJack F Vogel u16 checksum = 0;
2347f0ecc46dSJack F Vogel u16 i, nvm_data;
2348f0ecc46dSJack F Vogel
2349f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_with_offset");
2350f0ecc46dSJack F Vogel
2351f0ecc46dSJack F Vogel for (i = offset; i < ((NVM_CHECKSUM_REG + offset) + 1); i++) {
2352f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
2353f0ecc46dSJack F Vogel if (ret_val) {
2354f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n");
2355f0ecc46dSJack F Vogel goto out;
2356f0ecc46dSJack F Vogel }
2357f0ecc46dSJack F Vogel checksum += nvm_data;
2358f0ecc46dSJack F Vogel }
2359f0ecc46dSJack F Vogel
2360f0ecc46dSJack F Vogel if (checksum != (u16) NVM_SUM) {
2361f0ecc46dSJack F Vogel DEBUGOUT("NVM Checksum Invalid\n");
2362f0ecc46dSJack F Vogel ret_val = -E1000_ERR_NVM;
2363f0ecc46dSJack F Vogel goto out;
2364f0ecc46dSJack F Vogel }
2365f0ecc46dSJack F Vogel
2366f0ecc46dSJack F Vogel out:
2367f0ecc46dSJack F Vogel return ret_val;
2368f0ecc46dSJack F Vogel }
2369f0ecc46dSJack F Vogel
2370f0ecc46dSJack F Vogel /**
2371f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_with_offset - Update EEPROM
2372f0ecc46dSJack F Vogel * checksum
2373f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
2374f0ecc46dSJack F Vogel * @offset: offset in words of the checksum protected region
2375f0ecc46dSJack F Vogel *
2376f0ecc46dSJack F Vogel * Updates the EEPROM checksum by reading/adding each word of the EEPROM
2377f0ecc46dSJack F Vogel * up to the checksum. Then calculates the EEPROM checksum and writes the
2378f0ecc46dSJack F Vogel * value to the EEPROM.
2379f0ecc46dSJack F Vogel **/
e1000_update_nvm_checksum_with_offset(struct e1000_hw * hw,u16 offset)2380f0ecc46dSJack F Vogel s32 e1000_update_nvm_checksum_with_offset(struct e1000_hw *hw, u16 offset)
2381f0ecc46dSJack F Vogel {
2382f0ecc46dSJack F Vogel s32 ret_val;
2383f0ecc46dSJack F Vogel u16 checksum = 0;
2384f0ecc46dSJack F Vogel u16 i, nvm_data;
2385f0ecc46dSJack F Vogel
2386f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_with_offset");
2387f0ecc46dSJack F Vogel
2388f0ecc46dSJack F Vogel for (i = offset; i < (NVM_CHECKSUM_REG + offset); i++) {
2389f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, i, 1, &nvm_data);
2390f0ecc46dSJack F Vogel if (ret_val) {
2391f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error while updating checksum.\n");
2392f0ecc46dSJack F Vogel goto out;
2393f0ecc46dSJack F Vogel }
2394f0ecc46dSJack F Vogel checksum += nvm_data;
2395f0ecc46dSJack F Vogel }
2396f0ecc46dSJack F Vogel checksum = (u16) NVM_SUM - checksum;
2397f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, (NVM_CHECKSUM_REG + offset), 1,
2398f0ecc46dSJack F Vogel &checksum);
2399f0ecc46dSJack F Vogel if (ret_val)
2400f0ecc46dSJack F Vogel DEBUGOUT("NVM Write Error while updating checksum.\n");
2401f0ecc46dSJack F Vogel
2402f0ecc46dSJack F Vogel out:
2403f0ecc46dSJack F Vogel return ret_val;
2404f0ecc46dSJack F Vogel }
2405f0ecc46dSJack F Vogel
2406f0ecc46dSJack F Vogel /**
2407f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_82580 - Validate EEPROM checksum
2408f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
2409f0ecc46dSJack F Vogel *
2410f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of
2411f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is
2412f0ecc46dSJack F Vogel * equal to 0xBABA.
2413f0ecc46dSJack F Vogel **/
e1000_validate_nvm_checksum_82580(struct e1000_hw * hw)2414f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_82580(struct e1000_hw *hw)
2415f0ecc46dSJack F Vogel {
24168cc64f1eSJack F Vogel s32 ret_val;
2417f0ecc46dSJack F Vogel u16 eeprom_regions_count = 1;
2418f0ecc46dSJack F Vogel u16 j, nvm_data;
2419f0ecc46dSJack F Vogel u16 nvm_offset;
2420f0ecc46dSJack F Vogel
2421f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_82580");
2422f0ecc46dSJack F Vogel
2423f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
2424f0ecc46dSJack F Vogel if (ret_val) {
2425f0ecc46dSJack F Vogel DEBUGOUT("NVM Read Error\n");
2426f0ecc46dSJack F Vogel goto out;
2427f0ecc46dSJack F Vogel }
2428f0ecc46dSJack F Vogel
2429f0ecc46dSJack F Vogel if (nvm_data & NVM_COMPATIBILITY_BIT_MASK) {
24303e614fb6SGordon Bergling /* if checksums compatibility bit is set validate checksums
2431f0ecc46dSJack F Vogel * for all 4 ports. */
2432f0ecc46dSJack F Vogel eeprom_regions_count = 4;
2433f0ecc46dSJack F Vogel }
2434f0ecc46dSJack F Vogel
2435f0ecc46dSJack F Vogel for (j = 0; j < eeprom_regions_count; j++) {
2436f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2437f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw,
2438f0ecc46dSJack F Vogel nvm_offset);
2439f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS)
2440f0ecc46dSJack F Vogel goto out;
2441f0ecc46dSJack F Vogel }
2442f0ecc46dSJack F Vogel
2443f0ecc46dSJack F Vogel out:
2444f0ecc46dSJack F Vogel return ret_val;
2445f0ecc46dSJack F Vogel }
2446f0ecc46dSJack F Vogel
2447f0ecc46dSJack F Vogel /**
2448f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_82580 - Update EEPROM checksum
2449f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
2450f0ecc46dSJack F Vogel *
2451f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding
2452f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM
2453f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM.
2454f0ecc46dSJack F Vogel **/
e1000_update_nvm_checksum_82580(struct e1000_hw * hw)2455f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_82580(struct e1000_hw *hw)
2456f0ecc46dSJack F Vogel {
2457f0ecc46dSJack F Vogel s32 ret_val;
2458f0ecc46dSJack F Vogel u16 j, nvm_data;
2459f0ecc46dSJack F Vogel u16 nvm_offset;
2460f0ecc46dSJack F Vogel
2461f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_82580");
2462f0ecc46dSJack F Vogel
2463f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.read(hw, NVM_COMPATIBILITY_REG_3, 1, &nvm_data);
2464f0ecc46dSJack F Vogel if (ret_val) {
24654dab5c37SJack F Vogel DEBUGOUT("NVM Read Error while updating checksum compatibility bit.\n");
2466f0ecc46dSJack F Vogel goto out;
2467f0ecc46dSJack F Vogel }
2468f0ecc46dSJack F Vogel
2469ab5d0362SJack F Vogel if (!(nvm_data & NVM_COMPATIBILITY_BIT_MASK)) {
2470f0ecc46dSJack F Vogel /* set compatibility bit to validate checksums appropriately */
2471f0ecc46dSJack F Vogel nvm_data = nvm_data | NVM_COMPATIBILITY_BIT_MASK;
2472f0ecc46dSJack F Vogel ret_val = hw->nvm.ops.write(hw, NVM_COMPATIBILITY_REG_3, 1,
2473f0ecc46dSJack F Vogel &nvm_data);
2474f0ecc46dSJack F Vogel if (ret_val) {
24754dab5c37SJack F Vogel DEBUGOUT("NVM Write Error while updating checksum compatibility bit.\n");
2476f0ecc46dSJack F Vogel goto out;
2477f0ecc46dSJack F Vogel }
2478f0ecc46dSJack F Vogel }
2479f0ecc46dSJack F Vogel
2480f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) {
2481f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2482f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
24834dab5c37SJack F Vogel if (ret_val)
2484f0ecc46dSJack F Vogel goto out;
2485f0ecc46dSJack F Vogel }
2486f0ecc46dSJack F Vogel
2487f0ecc46dSJack F Vogel out:
2488f0ecc46dSJack F Vogel return ret_val;
2489f0ecc46dSJack F Vogel }
2490f0ecc46dSJack F Vogel
2491f0ecc46dSJack F Vogel /**
2492f0ecc46dSJack F Vogel * e1000_validate_nvm_checksum_i350 - Validate EEPROM checksum
2493f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
2494f0ecc46dSJack F Vogel *
2495f0ecc46dSJack F Vogel * Calculates the EEPROM section checksum by reading/adding each word of
2496f0ecc46dSJack F Vogel * the EEPROM and then verifies that the sum of the EEPROM is
2497f0ecc46dSJack F Vogel * equal to 0xBABA.
2498f0ecc46dSJack F Vogel **/
e1000_validate_nvm_checksum_i350(struct e1000_hw * hw)2499f0ecc46dSJack F Vogel static s32 e1000_validate_nvm_checksum_i350(struct e1000_hw *hw)
2500f0ecc46dSJack F Vogel {
2501f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS;
2502f0ecc46dSJack F Vogel u16 j;
2503f0ecc46dSJack F Vogel u16 nvm_offset;
2504f0ecc46dSJack F Vogel
2505f0ecc46dSJack F Vogel DEBUGFUNC("e1000_validate_nvm_checksum_i350");
2506f0ecc46dSJack F Vogel
2507f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) {
2508f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2509f0ecc46dSJack F Vogel ret_val = e1000_validate_nvm_checksum_with_offset(hw,
2510f0ecc46dSJack F Vogel nvm_offset);
2511f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS)
2512f0ecc46dSJack F Vogel goto out;
2513f0ecc46dSJack F Vogel }
2514f0ecc46dSJack F Vogel
2515f0ecc46dSJack F Vogel out:
2516f0ecc46dSJack F Vogel return ret_val;
2517f0ecc46dSJack F Vogel }
2518f0ecc46dSJack F Vogel
2519f0ecc46dSJack F Vogel /**
2520f0ecc46dSJack F Vogel * e1000_update_nvm_checksum_i350 - Update EEPROM checksum
2521f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
2522f0ecc46dSJack F Vogel *
2523f0ecc46dSJack F Vogel * Updates the EEPROM section checksums for all 4 ports by reading/adding
2524f0ecc46dSJack F Vogel * each word of the EEPROM up to the checksum. Then calculates the EEPROM
2525f0ecc46dSJack F Vogel * checksum and writes the value to the EEPROM.
2526f0ecc46dSJack F Vogel **/
e1000_update_nvm_checksum_i350(struct e1000_hw * hw)2527f0ecc46dSJack F Vogel static s32 e1000_update_nvm_checksum_i350(struct e1000_hw *hw)
2528f0ecc46dSJack F Vogel {
2529f0ecc46dSJack F Vogel s32 ret_val = E1000_SUCCESS;
2530f0ecc46dSJack F Vogel u16 j;
2531f0ecc46dSJack F Vogel u16 nvm_offset;
2532f0ecc46dSJack F Vogel
2533f0ecc46dSJack F Vogel DEBUGFUNC("e1000_update_nvm_checksum_i350");
2534f0ecc46dSJack F Vogel
2535f0ecc46dSJack F Vogel for (j = 0; j < 4; j++) {
2536f0ecc46dSJack F Vogel nvm_offset = NVM_82580_LAN_FUNC_OFFSET(j);
2537f0ecc46dSJack F Vogel ret_val = e1000_update_nvm_checksum_with_offset(hw, nvm_offset);
2538f0ecc46dSJack F Vogel if (ret_val != E1000_SUCCESS)
2539f0ecc46dSJack F Vogel goto out;
2540f0ecc46dSJack F Vogel }
2541f0ecc46dSJack F Vogel
2542f0ecc46dSJack F Vogel out:
2543f0ecc46dSJack F Vogel return ret_val;
2544f0ecc46dSJack F Vogel }
2545f0ecc46dSJack F Vogel
2546f0ecc46dSJack F Vogel /**
25477609433eSJack F Vogel * __e1000_access_emi_reg - Read/write EMI register
25487609433eSJack F Vogel * @hw: pointer to the HW structure
25495b426b3eSGuinan Sun * @address: EMI address to program
25507609433eSJack F Vogel * @data: pointer to value to read/write from/to the EMI address
25517609433eSJack F Vogel * @read: boolean flag to indicate read or write
25527609433eSJack F Vogel **/
__e1000_access_emi_reg(struct e1000_hw * hw,u16 address,u16 * data,bool read)25537609433eSJack F Vogel static s32 __e1000_access_emi_reg(struct e1000_hw *hw, u16 address,
25547609433eSJack F Vogel u16 *data, bool read)
25557609433eSJack F Vogel {
25568cc64f1eSJack F Vogel s32 ret_val;
25577609433eSJack F Vogel
25587609433eSJack F Vogel DEBUGFUNC("__e1000_access_emi_reg");
25597609433eSJack F Vogel
25607609433eSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, E1000_EMIADD, address);
25617609433eSJack F Vogel if (ret_val)
25627609433eSJack F Vogel return ret_val;
25637609433eSJack F Vogel
25647609433eSJack F Vogel if (read)
25657609433eSJack F Vogel ret_val = hw->phy.ops.read_reg(hw, E1000_EMIDATA, data);
25667609433eSJack F Vogel else
25677609433eSJack F Vogel ret_val = hw->phy.ops.write_reg(hw, E1000_EMIDATA, *data);
25687609433eSJack F Vogel
25697609433eSJack F Vogel return ret_val;
25707609433eSJack F Vogel }
25717609433eSJack F Vogel
25727609433eSJack F Vogel /**
25737609433eSJack F Vogel * e1000_read_emi_reg - Read Extended Management Interface register
25747609433eSJack F Vogel * @hw: pointer to the HW structure
25757609433eSJack F Vogel * @addr: EMI address to program
25767609433eSJack F Vogel * @data: value to be read from the EMI address
25777609433eSJack F Vogel **/
e1000_read_emi_reg(struct e1000_hw * hw,u16 addr,u16 * data)25787609433eSJack F Vogel s32 e1000_read_emi_reg(struct e1000_hw *hw, u16 addr, u16 *data)
25797609433eSJack F Vogel {
25807609433eSJack F Vogel DEBUGFUNC("e1000_read_emi_reg");
25817609433eSJack F Vogel
25821bbdc25fSKevin Bowling return __e1000_access_emi_reg(hw, addr, data, true);
25837609433eSJack F Vogel }
25847609433eSJack F Vogel
25857609433eSJack F Vogel /**
25868cc64f1eSJack F Vogel * e1000_initialize_M88E1512_phy - Initialize M88E1512 PHY
25878cc64f1eSJack F Vogel * @hw: pointer to the HW structure
25888cc64f1eSJack F Vogel *
2589c80429ceSEric Joyner * Initialize Marvell 1512 to work correctly with Avoton.
25908cc64f1eSJack F Vogel **/
e1000_initialize_M88E1512_phy(struct e1000_hw * hw)25918cc64f1eSJack F Vogel s32 e1000_initialize_M88E1512_phy(struct e1000_hw *hw)
25928cc64f1eSJack F Vogel {
25938cc64f1eSJack F Vogel struct e1000_phy_info *phy = &hw->phy;
25948cc64f1eSJack F Vogel s32 ret_val = E1000_SUCCESS;
25958cc64f1eSJack F Vogel
25968cc64f1eSJack F Vogel DEBUGFUNC("e1000_initialize_M88E1512_phy");
25978cc64f1eSJack F Vogel
25988cc64f1eSJack F Vogel /* Check if this is correct PHY. */
25998cc64f1eSJack F Vogel if (phy->id != M88E1512_E_PHY_ID)
26008cc64f1eSJack F Vogel goto out;
26018cc64f1eSJack F Vogel
26028cc64f1eSJack F Vogel /* Switch to PHY page 0xFF. */
26038cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF);
26048cc64f1eSJack F Vogel if (ret_val)
26058cc64f1eSJack F Vogel goto out;
26068cc64f1eSJack F Vogel
26078cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B);
26088cc64f1eSJack F Vogel if (ret_val)
26098cc64f1eSJack F Vogel goto out;
26108cc64f1eSJack F Vogel
26118cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144);
26128cc64f1eSJack F Vogel if (ret_val)
26138cc64f1eSJack F Vogel goto out;
26148cc64f1eSJack F Vogel
26158cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28);
26168cc64f1eSJack F Vogel if (ret_val)
26178cc64f1eSJack F Vogel goto out;
26188cc64f1eSJack F Vogel
26198cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146);
26208cc64f1eSJack F Vogel if (ret_val)
26218cc64f1eSJack F Vogel goto out;
26228cc64f1eSJack F Vogel
26238cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233);
26248cc64f1eSJack F Vogel if (ret_val)
26258cc64f1eSJack F Vogel goto out;
26268cc64f1eSJack F Vogel
26278cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D);
26288cc64f1eSJack F Vogel if (ret_val)
26298cc64f1eSJack F Vogel goto out;
26308cc64f1eSJack F Vogel
26318cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xCC0C);
26328cc64f1eSJack F Vogel if (ret_val)
26338cc64f1eSJack F Vogel goto out;
26348cc64f1eSJack F Vogel
26358cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159);
26368cc64f1eSJack F Vogel if (ret_val)
26378cc64f1eSJack F Vogel goto out;
26388cc64f1eSJack F Vogel
26398cc64f1eSJack F Vogel /* Switch to PHY page 0xFB. */
26408cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB);
26418cc64f1eSJack F Vogel if (ret_val)
26428cc64f1eSJack F Vogel goto out;
26438cc64f1eSJack F Vogel
26448cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0x000D);
26458cc64f1eSJack F Vogel if (ret_val)
26468cc64f1eSJack F Vogel goto out;
26478cc64f1eSJack F Vogel
26488cc64f1eSJack F Vogel /* Switch to PHY page 0x12. */
26498cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12);
26508cc64f1eSJack F Vogel if (ret_val)
26518cc64f1eSJack F Vogel goto out;
26528cc64f1eSJack F Vogel
26538cc64f1eSJack F Vogel /* Change mode to SGMII-to-Copper */
26548cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001);
26558cc64f1eSJack F Vogel if (ret_val)
26568cc64f1eSJack F Vogel goto out;
26578cc64f1eSJack F Vogel
26588cc64f1eSJack F Vogel /* Return the PHY to page 0. */
26598cc64f1eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
26608cc64f1eSJack F Vogel if (ret_val)
26618cc64f1eSJack F Vogel goto out;
26628cc64f1eSJack F Vogel
26638cc64f1eSJack F Vogel ret_val = phy->ops.commit(hw);
26648cc64f1eSJack F Vogel if (ret_val) {
26658cc64f1eSJack F Vogel DEBUGOUT("Error committing the PHY changes\n");
26668cc64f1eSJack F Vogel return ret_val;
26678cc64f1eSJack F Vogel }
26688cc64f1eSJack F Vogel
26698cc64f1eSJack F Vogel msec_delay(1000);
26708cc64f1eSJack F Vogel out:
26718cc64f1eSJack F Vogel return ret_val;
26728cc64f1eSJack F Vogel }
26738cc64f1eSJack F Vogel
26748cc64f1eSJack F Vogel /**
2675c80429ceSEric Joyner * e1000_initialize_M88E1543_phy - Initialize M88E1543 PHY
2676c80429ceSEric Joyner * @hw: pointer to the HW structure
2677c80429ceSEric Joyner *
2678c80429ceSEric Joyner * Initialize Marvell 1543 to work correctly with Avoton.
2679c80429ceSEric Joyner **/
e1000_initialize_M88E1543_phy(struct e1000_hw * hw)2680c80429ceSEric Joyner s32 e1000_initialize_M88E1543_phy(struct e1000_hw *hw)
2681c80429ceSEric Joyner {
2682c80429ceSEric Joyner struct e1000_phy_info *phy = &hw->phy;
2683c80429ceSEric Joyner s32 ret_val = E1000_SUCCESS;
2684c80429ceSEric Joyner
2685c80429ceSEric Joyner DEBUGFUNC("e1000_initialize_M88E1543_phy");
2686c80429ceSEric Joyner
2687c80429ceSEric Joyner /* Check if this is correct PHY. */
2688c80429ceSEric Joyner if (phy->id != M88E1543_E_PHY_ID)
2689c80429ceSEric Joyner goto out;
2690c80429ceSEric Joyner
2691c80429ceSEric Joyner /* Switch to PHY page 0xFF. */
2692c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FF);
2693c80429ceSEric Joyner if (ret_val)
2694c80429ceSEric Joyner goto out;
2695c80429ceSEric Joyner
2696c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x214B);
2697c80429ceSEric Joyner if (ret_val)
2698c80429ceSEric Joyner goto out;
2699c80429ceSEric Joyner
2700c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2144);
2701c80429ceSEric Joyner if (ret_val)
2702c80429ceSEric Joyner goto out;
2703c80429ceSEric Joyner
2704c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0x0C28);
2705c80429ceSEric Joyner if (ret_val)
2706c80429ceSEric Joyner goto out;
2707c80429ceSEric Joyner
2708c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2146);
2709c80429ceSEric Joyner if (ret_val)
2710c80429ceSEric Joyner goto out;
2711c80429ceSEric Joyner
2712c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xB233);
2713c80429ceSEric Joyner if (ret_val)
2714c80429ceSEric Joyner goto out;
2715c80429ceSEric Joyner
2716c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x214D);
2717c80429ceSEric Joyner if (ret_val)
2718c80429ceSEric Joyner goto out;
2719c80429ceSEric Joyner
2720c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_2, 0xDC0C);
2721c80429ceSEric Joyner if (ret_val)
2722c80429ceSEric Joyner goto out;
2723c80429ceSEric Joyner
2724c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_1, 0x2159);
2725c80429ceSEric Joyner if (ret_val)
2726c80429ceSEric Joyner goto out;
2727c80429ceSEric Joyner
2728c80429ceSEric Joyner /* Switch to PHY page 0xFB. */
2729c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x00FB);
2730c80429ceSEric Joyner if (ret_val)
2731c80429ceSEric Joyner goto out;
2732c80429ceSEric Joyner
2733c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_CFG_REG_3, 0xC00D);
2734c80429ceSEric Joyner if (ret_val)
2735c80429ceSEric Joyner goto out;
2736c80429ceSEric Joyner
2737c80429ceSEric Joyner /* Switch to PHY page 0x12. */
2738c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x12);
2739c80429ceSEric Joyner if (ret_val)
2740c80429ceSEric Joyner goto out;
2741c80429ceSEric Joyner
2742c80429ceSEric Joyner /* Change mode to SGMII-to-Copper */
2743c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1512_MODE, 0x8001);
2744c80429ceSEric Joyner if (ret_val)
2745c80429ceSEric Joyner goto out;
2746c80429ceSEric Joyner
2747c80429ceSEric Joyner /* Switch to PHY page 1. */
2748c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0x1);
2749c80429ceSEric Joyner if (ret_val)
2750c80429ceSEric Joyner goto out;
2751c80429ceSEric Joyner
2752c80429ceSEric Joyner /* Change mode to 1000BASE-X/SGMII and autoneg enable; reset */
2753c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_FIBER_CTRL, 0x9140);
2754c80429ceSEric Joyner if (ret_val)
2755c80429ceSEric Joyner goto out;
2756c80429ceSEric Joyner
2757c80429ceSEric Joyner /* Return the PHY to page 0. */
2758c80429ceSEric Joyner ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
2759c80429ceSEric Joyner if (ret_val)
2760c80429ceSEric Joyner goto out;
2761c80429ceSEric Joyner
2762c80429ceSEric Joyner ret_val = phy->ops.commit(hw);
2763c80429ceSEric Joyner if (ret_val) {
2764c80429ceSEric Joyner DEBUGOUT("Error committing the PHY changes\n");
2765c80429ceSEric Joyner return ret_val;
2766c80429ceSEric Joyner }
2767c80429ceSEric Joyner
2768c80429ceSEric Joyner msec_delay(1000);
2769c80429ceSEric Joyner out:
2770c80429ceSEric Joyner return ret_val;
2771c80429ceSEric Joyner }
2772c80429ceSEric Joyner
2773c80429ceSEric Joyner /**
2774f0ecc46dSJack F Vogel * e1000_set_eee_i350 - Enable/disable EEE support
2775f0ecc46dSJack F Vogel * @hw: pointer to the HW structure
27765b426b3eSGuinan Sun * @adv1G: boolean flag enabling 1G EEE advertisement
27775b426b3eSGuinan Sun * @adv100M: boolean flag enabling 100M EEE advertisement
2778f0ecc46dSJack F Vogel *
2779f0ecc46dSJack F Vogel * Enable/disable EEE based on setting in dev_spec structure.
2780f0ecc46dSJack F Vogel *
2781f0ecc46dSJack F Vogel **/
e1000_set_eee_i350(struct e1000_hw * hw,bool adv1G,bool adv100M)2782c80429ceSEric Joyner s32 e1000_set_eee_i350(struct e1000_hw *hw, bool adv1G, bool adv100M)
2783f0ecc46dSJack F Vogel {
27844dab5c37SJack F Vogel u32 ipcnfg, eeer;
2785f0ecc46dSJack F Vogel
2786f0ecc46dSJack F Vogel DEBUGFUNC("e1000_set_eee_i350");
2787f0ecc46dSJack F Vogel
27884dab5c37SJack F Vogel if ((hw->mac.type < e1000_i350) ||
27894dab5c37SJack F Vogel (hw->phy.media_type != e1000_media_type_copper))
2790f0ecc46dSJack F Vogel goto out;
2791f0ecc46dSJack F Vogel ipcnfg = E1000_READ_REG(hw, E1000_IPCNFG);
2792f0ecc46dSJack F Vogel eeer = E1000_READ_REG(hw, E1000_EEER);
2793f0ecc46dSJack F Vogel
2794f0ecc46dSJack F Vogel /* enable or disable per user setting */
2795f0ecc46dSJack F Vogel if (!(hw->dev_spec._82575.eee_disable)) {
27966ab6bfe3SJack F Vogel u32 eee_su = E1000_READ_REG(hw, E1000_EEE_SU);
27976ab6bfe3SJack F Vogel
2798c80429ceSEric Joyner if (adv100M)
2799c80429ceSEric Joyner ipcnfg |= E1000_IPCNFG_EEE_100M_AN;
2800c80429ceSEric Joyner else
2801c80429ceSEric Joyner ipcnfg &= ~E1000_IPCNFG_EEE_100M_AN;
2802c80429ceSEric Joyner
2803c80429ceSEric Joyner if (adv1G)
2804c80429ceSEric Joyner ipcnfg |= E1000_IPCNFG_EEE_1G_AN;
2805c80429ceSEric Joyner else
2806c80429ceSEric Joyner ipcnfg &= ~E1000_IPCNFG_EEE_1G_AN;
2807c80429ceSEric Joyner
28084dab5c37SJack F Vogel eeer |= (E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
2809f0ecc46dSJack F Vogel E1000_EEER_LPI_FC);
2810f0ecc46dSJack F Vogel
28116ab6bfe3SJack F Vogel /* This bit should not be set in normal operation. */
28126ab6bfe3SJack F Vogel if (eee_su & E1000_EEE_SU_LPI_CLK_STP)
28136ab6bfe3SJack F Vogel DEBUGOUT("LPI Clock Stop Bit should not be set!\n");
2814f0ecc46dSJack F Vogel } else {
28154dab5c37SJack F Vogel ipcnfg &= ~(E1000_IPCNFG_EEE_1G_AN | E1000_IPCNFG_EEE_100M_AN);
28164dab5c37SJack F Vogel eeer &= ~(E1000_EEER_TX_LPI_EN | E1000_EEER_RX_LPI_EN |
2817f0ecc46dSJack F Vogel E1000_EEER_LPI_FC);
2818f0ecc46dSJack F Vogel }
2819f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_IPCNFG, ipcnfg);
2820f0ecc46dSJack F Vogel E1000_WRITE_REG(hw, E1000_EEER, eeer);
2821f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_IPCNFG);
2822f0ecc46dSJack F Vogel E1000_READ_REG(hw, E1000_EEER);
2823f0ecc46dSJack F Vogel out:
2824f0ecc46dSJack F Vogel
28258cc64f1eSJack F Vogel return E1000_SUCCESS;
2826f0ecc46dSJack F Vogel }
28274dab5c37SJack F Vogel
28287609433eSJack F Vogel /**
28297609433eSJack F Vogel * e1000_set_eee_i354 - Enable/disable EEE support
28307609433eSJack F Vogel * @hw: pointer to the HW structure
28315b426b3eSGuinan Sun * @adv1G: boolean flag enabling 1G EEE advertisement
28325b426b3eSGuinan Sun * @adv100M: boolean flag enabling 100M EEE advertisement
28337609433eSJack F Vogel *
28347609433eSJack F Vogel * Enable/disable EEE legacy mode based on setting in dev_spec structure.
28357609433eSJack F Vogel *
28367609433eSJack F Vogel **/
e1000_set_eee_i354(struct e1000_hw * hw,bool adv1G,bool adv100M)2837c80429ceSEric Joyner s32 e1000_set_eee_i354(struct e1000_hw *hw, bool adv1G, bool adv100M)
28387609433eSJack F Vogel {
28397609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy;
28407609433eSJack F Vogel s32 ret_val = E1000_SUCCESS;
28417609433eSJack F Vogel u16 phy_data;
28427609433eSJack F Vogel
28437609433eSJack F Vogel DEBUGFUNC("e1000_set_eee_i354");
28447609433eSJack F Vogel
28457609433eSJack F Vogel if ((hw->phy.media_type != e1000_media_type_copper) ||
28467609433eSJack F Vogel ((phy->id != M88E1543_E_PHY_ID) &&
28477609433eSJack F Vogel (phy->id != M88E1512_E_PHY_ID)))
28487609433eSJack F Vogel goto out;
28497609433eSJack F Vogel
28507609433eSJack F Vogel if (!hw->dev_spec._82575.eee_disable) {
28517609433eSJack F Vogel /* Switch to PHY page 18. */
28527609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 18);
28537609433eSJack F Vogel if (ret_val)
28547609433eSJack F Vogel goto out;
28557609433eSJack F Vogel
28567609433eSJack F Vogel ret_val = phy->ops.read_reg(hw, E1000_M88E1543_EEE_CTRL_1,
28577609433eSJack F Vogel &phy_data);
28587609433eSJack F Vogel if (ret_val)
28597609433eSJack F Vogel goto out;
28607609433eSJack F Vogel
28617609433eSJack F Vogel phy_data |= E1000_M88E1543_EEE_CTRL_1_MS;
28627609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_EEE_CTRL_1,
28637609433eSJack F Vogel phy_data);
28647609433eSJack F Vogel if (ret_val)
28657609433eSJack F Vogel goto out;
28667609433eSJack F Vogel
28677609433eSJack F Vogel /* Return the PHY to page 0. */
28687609433eSJack F Vogel ret_val = phy->ops.write_reg(hw, E1000_M88E1543_PAGE_ADDR, 0);
28697609433eSJack F Vogel if (ret_val)
28707609433eSJack F Vogel goto out;
28717609433eSJack F Vogel
28727609433eSJack F Vogel /* Turn on EEE advertisement. */
28737609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
28747609433eSJack F Vogel E1000_EEE_ADV_DEV_I354,
28757609433eSJack F Vogel &phy_data);
28767609433eSJack F Vogel if (ret_val)
28777609433eSJack F Vogel goto out;
28787609433eSJack F Vogel
2879c80429ceSEric Joyner if (adv100M)
2880c80429ceSEric Joyner phy_data |= E1000_EEE_ADV_100_SUPPORTED;
2881c80429ceSEric Joyner else
2882c80429ceSEric Joyner phy_data &= ~E1000_EEE_ADV_100_SUPPORTED;
2883c80429ceSEric Joyner
2884c80429ceSEric Joyner if (adv1G)
2885c80429ceSEric Joyner phy_data |= E1000_EEE_ADV_1000_SUPPORTED;
2886c80429ceSEric Joyner else
2887c80429ceSEric Joyner phy_data &= ~E1000_EEE_ADV_1000_SUPPORTED;
2888c80429ceSEric Joyner
28897609433eSJack F Vogel ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
28907609433eSJack F Vogel E1000_EEE_ADV_DEV_I354,
28917609433eSJack F Vogel phy_data);
28927609433eSJack F Vogel } else {
28937609433eSJack F Vogel /* Turn off EEE advertisement. */
28947609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
28957609433eSJack F Vogel E1000_EEE_ADV_DEV_I354,
28967609433eSJack F Vogel &phy_data);
28977609433eSJack F Vogel if (ret_val)
28987609433eSJack F Vogel goto out;
28997609433eSJack F Vogel
29007609433eSJack F Vogel phy_data &= ~(E1000_EEE_ADV_100_SUPPORTED |
29017609433eSJack F Vogel E1000_EEE_ADV_1000_SUPPORTED);
29027609433eSJack F Vogel ret_val = e1000_write_xmdio_reg(hw, E1000_EEE_ADV_ADDR_I354,
29037609433eSJack F Vogel E1000_EEE_ADV_DEV_I354,
29047609433eSJack F Vogel phy_data);
29057609433eSJack F Vogel }
29067609433eSJack F Vogel
29077609433eSJack F Vogel out:
29087609433eSJack F Vogel return ret_val;
29097609433eSJack F Vogel }
29107609433eSJack F Vogel
29117609433eSJack F Vogel /**
29127609433eSJack F Vogel * e1000_get_eee_status_i354 - Get EEE status
29137609433eSJack F Vogel * @hw: pointer to the HW structure
29147609433eSJack F Vogel * @status: EEE status
29157609433eSJack F Vogel *
29167609433eSJack F Vogel * Get EEE status by guessing based on whether Tx or Rx LPI indications have
29177609433eSJack F Vogel * been received.
29187609433eSJack F Vogel **/
e1000_get_eee_status_i354(struct e1000_hw * hw,bool * status)29197609433eSJack F Vogel s32 e1000_get_eee_status_i354(struct e1000_hw *hw, bool *status)
29207609433eSJack F Vogel {
29217609433eSJack F Vogel struct e1000_phy_info *phy = &hw->phy;
29227609433eSJack F Vogel s32 ret_val = E1000_SUCCESS;
29237609433eSJack F Vogel u16 phy_data;
29247609433eSJack F Vogel
29257609433eSJack F Vogel DEBUGFUNC("e1000_get_eee_status_i354");
29267609433eSJack F Vogel
29277609433eSJack F Vogel /* Check if EEE is supported on this device. */
29287609433eSJack F Vogel if ((hw->phy.media_type != e1000_media_type_copper) ||
29297609433eSJack F Vogel ((phy->id != M88E1543_E_PHY_ID) &&
29307609433eSJack F Vogel (phy->id != M88E1512_E_PHY_ID)))
29317609433eSJack F Vogel goto out;
29327609433eSJack F Vogel
29337609433eSJack F Vogel ret_val = e1000_read_xmdio_reg(hw, E1000_PCS_STATUS_ADDR_I354,
29347609433eSJack F Vogel E1000_PCS_STATUS_DEV_I354,
29357609433eSJack F Vogel &phy_data);
29367609433eSJack F Vogel if (ret_val)
29377609433eSJack F Vogel goto out;
29387609433eSJack F Vogel
29397609433eSJack F Vogel *status = phy_data & (E1000_PCS_STATUS_TX_LPI_RCVD |
29401bbdc25fSKevin Bowling E1000_PCS_STATUS_RX_LPI_RCVD) ? true : false;
29417609433eSJack F Vogel
29427609433eSJack F Vogel out:
29437609433eSJack F Vogel return ret_val;
29447609433eSJack F Vogel }
29457609433eSJack F Vogel
29464dab5c37SJack F Vogel /* Due to a hw errata, if the host tries to configure the VFTA register
29474dab5c37SJack F Vogel * while performing queries from the BMC or DMA, then the VFTA in some
29484dab5c37SJack F Vogel * cases won't be written.
29494dab5c37SJack F Vogel */
29504dab5c37SJack F Vogel
29514dab5c37SJack F Vogel /**
29524dab5c37SJack F Vogel * e1000_clear_vfta_i350 - Clear VLAN filter table
29534dab5c37SJack F Vogel * @hw: pointer to the HW structure
29544dab5c37SJack F Vogel *
29554dab5c37SJack F Vogel * Clears the register array which contains the VLAN filter table by
29564dab5c37SJack F Vogel * setting all the values to 0.
29574dab5c37SJack F Vogel **/
e1000_clear_vfta_i350(struct e1000_hw * hw)29584dab5c37SJack F Vogel void e1000_clear_vfta_i350(struct e1000_hw *hw)
29594dab5c37SJack F Vogel {
29604dab5c37SJack F Vogel u32 offset;
29614dab5c37SJack F Vogel int i;
29624dab5c37SJack F Vogel
29634dab5c37SJack F Vogel DEBUGFUNC("e1000_clear_vfta_350");
29644dab5c37SJack F Vogel
29654dab5c37SJack F Vogel for (offset = 0; offset < E1000_VLAN_FILTER_TBL_SIZE; offset++) {
29664dab5c37SJack F Vogel for (i = 0; i < 10; i++)
29674dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, 0);
29684dab5c37SJack F Vogel
29694dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
29704dab5c37SJack F Vogel }
29714dab5c37SJack F Vogel }
29724dab5c37SJack F Vogel
29734dab5c37SJack F Vogel /**
29744dab5c37SJack F Vogel * e1000_write_vfta_i350 - Write value to VLAN filter table
29754dab5c37SJack F Vogel * @hw: pointer to the HW structure
29764dab5c37SJack F Vogel * @offset: register offset in VLAN filter table
29774dab5c37SJack F Vogel * @value: register value written to VLAN filter table
29784dab5c37SJack F Vogel *
29794dab5c37SJack F Vogel * Writes value at the given offset in the register array which stores
29804dab5c37SJack F Vogel * the VLAN filter table.
29814dab5c37SJack F Vogel **/
e1000_write_vfta_i350(struct e1000_hw * hw,u32 offset,u32 value)29824dab5c37SJack F Vogel void e1000_write_vfta_i350(struct e1000_hw *hw, u32 offset, u32 value)
29834dab5c37SJack F Vogel {
29844dab5c37SJack F Vogel int i;
29854dab5c37SJack F Vogel
29864dab5c37SJack F Vogel DEBUGFUNC("e1000_write_vfta_350");
29874dab5c37SJack F Vogel
29884dab5c37SJack F Vogel for (i = 0; i < 10; i++)
29894dab5c37SJack F Vogel E1000_WRITE_REG_ARRAY(hw, E1000_VFTA, offset, value);
29904dab5c37SJack F Vogel
29914dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
29924dab5c37SJack F Vogel }
29934dab5c37SJack F Vogel
29944dab5c37SJack F Vogel
29954dab5c37SJack F Vogel /**
29964dab5c37SJack F Vogel * e1000_set_i2c_bb - Enable I2C bit-bang
29974dab5c37SJack F Vogel * @hw: pointer to the HW structure
29984dab5c37SJack F Vogel *
29994dab5c37SJack F Vogel * Enable I2C bit-bang interface
30004dab5c37SJack F Vogel *
30014dab5c37SJack F Vogel **/
e1000_set_i2c_bb(struct e1000_hw * hw)30024dab5c37SJack F Vogel s32 e1000_set_i2c_bb(struct e1000_hw *hw)
30034dab5c37SJack F Vogel {
30044dab5c37SJack F Vogel s32 ret_val = E1000_SUCCESS;
30054dab5c37SJack F Vogel u32 ctrl_ext, i2cparams;
30064dab5c37SJack F Vogel
30074dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_bb");
30084dab5c37SJack F Vogel
30094dab5c37SJack F Vogel ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
30104dab5c37SJack F Vogel ctrl_ext |= E1000_CTRL_I2C_ENA;
30114dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
30124dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
30134dab5c37SJack F Vogel
30144dab5c37SJack F Vogel i2cparams = E1000_READ_REG(hw, E1000_I2CPARAMS);
30154dab5c37SJack F Vogel i2cparams |= E1000_I2CBB_EN;
30164dab5c37SJack F Vogel i2cparams |= E1000_I2C_DATA_OE_N;
30174dab5c37SJack F Vogel i2cparams |= E1000_I2C_CLK_OE_N;
30184dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cparams);
30194dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
30204dab5c37SJack F Vogel
30214dab5c37SJack F Vogel return ret_val;
30224dab5c37SJack F Vogel }
30234dab5c37SJack F Vogel
30244dab5c37SJack F Vogel /**
30254dab5c37SJack F Vogel * e1000_read_i2c_byte_generic - Reads 8 bit word over I2C
30264dab5c37SJack F Vogel * @hw: pointer to hardware structure
30274dab5c37SJack F Vogel * @byte_offset: byte offset to read
3028ab5d0362SJack F Vogel * @dev_addr: device address
30294dab5c37SJack F Vogel * @data: value read
30304dab5c37SJack F Vogel *
30314dab5c37SJack F Vogel * Performs byte read operation over I2C interface at
30324dab5c37SJack F Vogel * a specified device address.
30334dab5c37SJack F Vogel **/
e1000_read_i2c_byte_generic(struct e1000_hw * hw,u8 byte_offset,u8 dev_addr,u8 * data)30344dab5c37SJack F Vogel s32 e1000_read_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
30354dab5c37SJack F Vogel u8 dev_addr, u8 *data)
30364dab5c37SJack F Vogel {
30374dab5c37SJack F Vogel s32 status = E1000_SUCCESS;
30384dab5c37SJack F Vogel u32 max_retry = 10;
30394dab5c37SJack F Vogel u32 retry = 1;
30404dab5c37SJack F Vogel u16 swfw_mask = 0;
30414dab5c37SJack F Vogel
30421bbdc25fSKevin Bowling bool nack = true;
30434dab5c37SJack F Vogel
30444dab5c37SJack F Vogel DEBUGFUNC("e1000_read_i2c_byte_generic");
30454dab5c37SJack F Vogel
30464dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM;
30474dab5c37SJack F Vogel
30484dab5c37SJack F Vogel do {
3049ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask)
30504dab5c37SJack F Vogel != E1000_SUCCESS) {
30514dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC;
30524dab5c37SJack F Vogel goto read_byte_out;
30534dab5c37SJack F Vogel }
30544dab5c37SJack F Vogel
30554dab5c37SJack F Vogel e1000_i2c_start(hw);
30564dab5c37SJack F Vogel
30574dab5c37SJack F Vogel /* Device Address and write indication */
30584dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr);
30594dab5c37SJack F Vogel if (status != E1000_SUCCESS)
30604dab5c37SJack F Vogel goto fail;
30614dab5c37SJack F Vogel
30624dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw);
30634dab5c37SJack F Vogel if (status != E1000_SUCCESS)
30644dab5c37SJack F Vogel goto fail;
30654dab5c37SJack F Vogel
30664dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset);
30674dab5c37SJack F Vogel if (status != E1000_SUCCESS)
30684dab5c37SJack F Vogel goto fail;
30694dab5c37SJack F Vogel
30704dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw);
30714dab5c37SJack F Vogel if (status != E1000_SUCCESS)
30724dab5c37SJack F Vogel goto fail;
30734dab5c37SJack F Vogel
30744dab5c37SJack F Vogel e1000_i2c_start(hw);
30754dab5c37SJack F Vogel
30764dab5c37SJack F Vogel /* Device Address and read indication */
30774dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, (dev_addr | 0x1));
30784dab5c37SJack F Vogel if (status != E1000_SUCCESS)
30794dab5c37SJack F Vogel goto fail;
30804dab5c37SJack F Vogel
30814dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw);
30824dab5c37SJack F Vogel if (status != E1000_SUCCESS)
30834dab5c37SJack F Vogel goto fail;
30844dab5c37SJack F Vogel
30856c59e186SGuinan Sun e1000_clock_in_i2c_byte(hw, data);
30864dab5c37SJack F Vogel
30874dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, nack);
30884dab5c37SJack F Vogel if (status != E1000_SUCCESS)
30894dab5c37SJack F Vogel goto fail;
30904dab5c37SJack F Vogel
30914dab5c37SJack F Vogel e1000_i2c_stop(hw);
30924dab5c37SJack F Vogel break;
30934dab5c37SJack F Vogel
30944dab5c37SJack F Vogel fail:
3095ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask);
30964dab5c37SJack F Vogel msec_delay(100);
30974dab5c37SJack F Vogel e1000_i2c_bus_clear(hw);
30984dab5c37SJack F Vogel retry++;
30994dab5c37SJack F Vogel if (retry < max_retry)
31004dab5c37SJack F Vogel DEBUGOUT("I2C byte read error - Retrying.\n");
31014dab5c37SJack F Vogel else
31024dab5c37SJack F Vogel DEBUGOUT("I2C byte read error.\n");
31034dab5c37SJack F Vogel
31044dab5c37SJack F Vogel } while (retry < max_retry);
31054dab5c37SJack F Vogel
3106ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask);
31074dab5c37SJack F Vogel
31084dab5c37SJack F Vogel read_byte_out:
31094dab5c37SJack F Vogel
31104dab5c37SJack F Vogel return status;
31114dab5c37SJack F Vogel }
31124dab5c37SJack F Vogel
31134dab5c37SJack F Vogel /**
31144dab5c37SJack F Vogel * e1000_write_i2c_byte_generic - Writes 8 bit word over I2C
31154dab5c37SJack F Vogel * @hw: pointer to hardware structure
31164dab5c37SJack F Vogel * @byte_offset: byte offset to write
3117ab5d0362SJack F Vogel * @dev_addr: device address
31184dab5c37SJack F Vogel * @data: value to write
31194dab5c37SJack F Vogel *
31204dab5c37SJack F Vogel * Performs byte write operation over I2C interface at
31214dab5c37SJack F Vogel * a specified device address.
31224dab5c37SJack F Vogel **/
e1000_write_i2c_byte_generic(struct e1000_hw * hw,u8 byte_offset,u8 dev_addr,u8 data)31234dab5c37SJack F Vogel s32 e1000_write_i2c_byte_generic(struct e1000_hw *hw, u8 byte_offset,
31244dab5c37SJack F Vogel u8 dev_addr, u8 data)
31254dab5c37SJack F Vogel {
31264dab5c37SJack F Vogel s32 status = E1000_SUCCESS;
31274dab5c37SJack F Vogel u32 max_retry = 1;
31284dab5c37SJack F Vogel u32 retry = 0;
31294dab5c37SJack F Vogel u16 swfw_mask = 0;
31304dab5c37SJack F Vogel
31314dab5c37SJack F Vogel DEBUGFUNC("e1000_write_i2c_byte_generic");
31324dab5c37SJack F Vogel
31334dab5c37SJack F Vogel swfw_mask = E1000_SWFW_PHY0_SM;
31344dab5c37SJack F Vogel
3135ab5d0362SJack F Vogel if (hw->mac.ops.acquire_swfw_sync(hw, swfw_mask) != E1000_SUCCESS) {
31364dab5c37SJack F Vogel status = E1000_ERR_SWFW_SYNC;
31374dab5c37SJack F Vogel goto write_byte_out;
31384dab5c37SJack F Vogel }
31394dab5c37SJack F Vogel
31404dab5c37SJack F Vogel do {
31414dab5c37SJack F Vogel e1000_i2c_start(hw);
31424dab5c37SJack F Vogel
31434dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, dev_addr);
31444dab5c37SJack F Vogel if (status != E1000_SUCCESS)
31454dab5c37SJack F Vogel goto fail;
31464dab5c37SJack F Vogel
31474dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw);
31484dab5c37SJack F Vogel if (status != E1000_SUCCESS)
31494dab5c37SJack F Vogel goto fail;
31504dab5c37SJack F Vogel
31514dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, byte_offset);
31524dab5c37SJack F Vogel if (status != E1000_SUCCESS)
31534dab5c37SJack F Vogel goto fail;
31544dab5c37SJack F Vogel
31554dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw);
31564dab5c37SJack F Vogel if (status != E1000_SUCCESS)
31574dab5c37SJack F Vogel goto fail;
31584dab5c37SJack F Vogel
31594dab5c37SJack F Vogel status = e1000_clock_out_i2c_byte(hw, data);
31604dab5c37SJack F Vogel if (status != E1000_SUCCESS)
31614dab5c37SJack F Vogel goto fail;
31624dab5c37SJack F Vogel
31634dab5c37SJack F Vogel status = e1000_get_i2c_ack(hw);
31644dab5c37SJack F Vogel if (status != E1000_SUCCESS)
31654dab5c37SJack F Vogel goto fail;
31664dab5c37SJack F Vogel
31674dab5c37SJack F Vogel e1000_i2c_stop(hw);
31684dab5c37SJack F Vogel break;
31694dab5c37SJack F Vogel
31704dab5c37SJack F Vogel fail:
31714dab5c37SJack F Vogel e1000_i2c_bus_clear(hw);
31724dab5c37SJack F Vogel retry++;
31734dab5c37SJack F Vogel if (retry < max_retry)
31744dab5c37SJack F Vogel DEBUGOUT("I2C byte write error - Retrying.\n");
31754dab5c37SJack F Vogel else
31764dab5c37SJack F Vogel DEBUGOUT("I2C byte write error.\n");
31774dab5c37SJack F Vogel } while (retry < max_retry);
31784dab5c37SJack F Vogel
3179ab5d0362SJack F Vogel hw->mac.ops.release_swfw_sync(hw, swfw_mask);
31804dab5c37SJack F Vogel
31814dab5c37SJack F Vogel write_byte_out:
31824dab5c37SJack F Vogel
31834dab5c37SJack F Vogel return status;
31844dab5c37SJack F Vogel }
31854dab5c37SJack F Vogel
31864dab5c37SJack F Vogel /**
31874dab5c37SJack F Vogel * e1000_i2c_start - Sets I2C start condition
31884dab5c37SJack F Vogel * @hw: pointer to hardware structure
31894dab5c37SJack F Vogel *
31904dab5c37SJack F Vogel * Sets I2C start condition (High -> Low on SDA while SCL is High)
31914dab5c37SJack F Vogel **/
e1000_i2c_start(struct e1000_hw * hw)31924dab5c37SJack F Vogel static void e1000_i2c_start(struct e1000_hw *hw)
31934dab5c37SJack F Vogel {
31944dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
31954dab5c37SJack F Vogel
31964dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_start");
31974dab5c37SJack F Vogel
31984dab5c37SJack F Vogel /* Start condition must begin with data and clock high */
31994dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1);
32004dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl);
32014dab5c37SJack F Vogel
32024dab5c37SJack F Vogel /* Setup time for start condition (4.7us) */
32034dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STA);
32044dab5c37SJack F Vogel
32054dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0);
32064dab5c37SJack F Vogel
32074dab5c37SJack F Vogel /* Hold time for start condition (4us) */
32084dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HD_STA);
32094dab5c37SJack F Vogel
32104dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl);
32114dab5c37SJack F Vogel
32124dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */
32134dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW);
32144dab5c37SJack F Vogel
32154dab5c37SJack F Vogel }
32164dab5c37SJack F Vogel
32174dab5c37SJack F Vogel /**
32184dab5c37SJack F Vogel * e1000_i2c_stop - Sets I2C stop condition
32194dab5c37SJack F Vogel * @hw: pointer to hardware structure
32204dab5c37SJack F Vogel *
32214dab5c37SJack F Vogel * Sets I2C stop condition (Low -> High on SDA while SCL is High)
32224dab5c37SJack F Vogel **/
e1000_i2c_stop(struct e1000_hw * hw)32234dab5c37SJack F Vogel static void e1000_i2c_stop(struct e1000_hw *hw)
32244dab5c37SJack F Vogel {
32254dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
32264dab5c37SJack F Vogel
32274dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_stop");
32284dab5c37SJack F Vogel
32294dab5c37SJack F Vogel /* Stop condition must begin with data low and clock high */
32304dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 0);
32314dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl);
32324dab5c37SJack F Vogel
32334dab5c37SJack F Vogel /* Setup time for stop condition (4us) */
32344dab5c37SJack F Vogel usec_delay(E1000_I2C_T_SU_STO);
32354dab5c37SJack F Vogel
32364dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1);
32374dab5c37SJack F Vogel
32384dab5c37SJack F Vogel /* bus free time between stop and start (4.7us)*/
32394dab5c37SJack F Vogel usec_delay(E1000_I2C_T_BUF);
32404dab5c37SJack F Vogel }
32414dab5c37SJack F Vogel
32424dab5c37SJack F Vogel /**
32434dab5c37SJack F Vogel * e1000_clock_in_i2c_byte - Clocks in one byte via I2C
32444dab5c37SJack F Vogel * @hw: pointer to hardware structure
32454dab5c37SJack F Vogel * @data: data byte to clock in
32464dab5c37SJack F Vogel *
32474dab5c37SJack F Vogel * Clocks in one byte data via I2C data/clock
32484dab5c37SJack F Vogel **/
e1000_clock_in_i2c_byte(struct e1000_hw * hw,u8 * data)32496c59e186SGuinan Sun static void e1000_clock_in_i2c_byte(struct e1000_hw *hw, u8 *data)
32504dab5c37SJack F Vogel {
32514dab5c37SJack F Vogel s32 i;
32524dab5c37SJack F Vogel bool bit = 0;
32534dab5c37SJack F Vogel
32544dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_byte");
32554dab5c37SJack F Vogel
32564dab5c37SJack F Vogel *data = 0;
32574dab5c37SJack F Vogel for (i = 7; i >= 0; i--) {
32584dab5c37SJack F Vogel e1000_clock_in_i2c_bit(hw, &bit);
32594dab5c37SJack F Vogel *data |= bit << i;
32604dab5c37SJack F Vogel }
32614dab5c37SJack F Vogel }
32624dab5c37SJack F Vogel
32634dab5c37SJack F Vogel /**
32644dab5c37SJack F Vogel * e1000_clock_out_i2c_byte - Clocks out one byte via I2C
32654dab5c37SJack F Vogel * @hw: pointer to hardware structure
32664dab5c37SJack F Vogel * @data: data byte clocked out
32674dab5c37SJack F Vogel *
32684dab5c37SJack F Vogel * Clocks out one byte data via I2C data/clock
32694dab5c37SJack F Vogel **/
e1000_clock_out_i2c_byte(struct e1000_hw * hw,u8 data)32704dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_byte(struct e1000_hw *hw, u8 data)
32714dab5c37SJack F Vogel {
32724dab5c37SJack F Vogel s32 status = E1000_SUCCESS;
32734dab5c37SJack F Vogel s32 i;
32744dab5c37SJack F Vogel u32 i2cctl;
32754dab5c37SJack F Vogel bool bit = 0;
32764dab5c37SJack F Vogel
32774dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_byte");
32784dab5c37SJack F Vogel
32794dab5c37SJack F Vogel for (i = 7; i >= 0; i--) {
32804dab5c37SJack F Vogel bit = (data >> i) & 0x1;
32814dab5c37SJack F Vogel status = e1000_clock_out_i2c_bit(hw, bit);
32824dab5c37SJack F Vogel
32834dab5c37SJack F Vogel if (status != E1000_SUCCESS)
32844dab5c37SJack F Vogel break;
32854dab5c37SJack F Vogel }
32864dab5c37SJack F Vogel
32874dab5c37SJack F Vogel /* Release SDA line (set high) */
32884dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
32894dab5c37SJack F Vogel
32904dab5c37SJack F Vogel i2cctl |= E1000_I2C_DATA_OE_N;
32914dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, i2cctl);
32924dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
32934dab5c37SJack F Vogel
32944dab5c37SJack F Vogel return status;
32954dab5c37SJack F Vogel }
32964dab5c37SJack F Vogel
32974dab5c37SJack F Vogel /**
32984dab5c37SJack F Vogel * e1000_get_i2c_ack - Polls for I2C ACK
32994dab5c37SJack F Vogel * @hw: pointer to hardware structure
33004dab5c37SJack F Vogel *
33014dab5c37SJack F Vogel * Clocks in/out one bit via I2C data/clock
33024dab5c37SJack F Vogel **/
e1000_get_i2c_ack(struct e1000_hw * hw)33034dab5c37SJack F Vogel static s32 e1000_get_i2c_ack(struct e1000_hw *hw)
33044dab5c37SJack F Vogel {
33054dab5c37SJack F Vogel s32 status = E1000_SUCCESS;
33064dab5c37SJack F Vogel u32 i = 0;
33074dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
33084dab5c37SJack F Vogel u32 timeout = 10;
33091bbdc25fSKevin Bowling bool ack = true;
33104dab5c37SJack F Vogel
33114dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_ack");
33124dab5c37SJack F Vogel
33134dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl);
33144dab5c37SJack F Vogel
33154dab5c37SJack F Vogel /* Minimum high period of clock is 4us */
33164dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH);
33174dab5c37SJack F Vogel
33184dab5c37SJack F Vogel /* Wait until SCL returns high */
33194dab5c37SJack F Vogel for (i = 0; i < timeout; i++) {
33204dab5c37SJack F Vogel usec_delay(1);
33214dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
33224dab5c37SJack F Vogel if (i2cctl & E1000_I2C_CLK_IN)
33234dab5c37SJack F Vogel break;
33244dab5c37SJack F Vogel }
33254dab5c37SJack F Vogel if (!(i2cctl & E1000_I2C_CLK_IN))
33264dab5c37SJack F Vogel return E1000_ERR_I2C;
33274dab5c37SJack F Vogel
33284dab5c37SJack F Vogel ack = e1000_get_i2c_data(&i2cctl);
3329ab5d0362SJack F Vogel if (ack) {
33304dab5c37SJack F Vogel DEBUGOUT("I2C ack was not received.\n");
33314dab5c37SJack F Vogel status = E1000_ERR_I2C;
33324dab5c37SJack F Vogel }
33334dab5c37SJack F Vogel
33344dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl);
33354dab5c37SJack F Vogel
33364dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */
33374dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW);
33384dab5c37SJack F Vogel
33394dab5c37SJack F Vogel return status;
33404dab5c37SJack F Vogel }
33414dab5c37SJack F Vogel
33424dab5c37SJack F Vogel /**
33434dab5c37SJack F Vogel * e1000_clock_in_i2c_bit - Clocks in one bit via I2C data/clock
33444dab5c37SJack F Vogel * @hw: pointer to hardware structure
33454dab5c37SJack F Vogel * @data: read data value
33464dab5c37SJack F Vogel *
33474dab5c37SJack F Vogel * Clocks in one bit via I2C data/clock
33484dab5c37SJack F Vogel **/
e1000_clock_in_i2c_bit(struct e1000_hw * hw,bool * data)33496c59e186SGuinan Sun static void e1000_clock_in_i2c_bit(struct e1000_hw *hw, bool *data)
33504dab5c37SJack F Vogel {
33514dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
33524dab5c37SJack F Vogel
33534dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_in_i2c_bit");
33544dab5c37SJack F Vogel
33554dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl);
33564dab5c37SJack F Vogel
33574dab5c37SJack F Vogel /* Minimum high period of clock is 4us */
33584dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH);
33594dab5c37SJack F Vogel
33604dab5c37SJack F Vogel i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
33614dab5c37SJack F Vogel *data = e1000_get_i2c_data(&i2cctl);
33624dab5c37SJack F Vogel
33634dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl);
33644dab5c37SJack F Vogel
33654dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us */
33664dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW);
33674dab5c37SJack F Vogel }
33684dab5c37SJack F Vogel
33694dab5c37SJack F Vogel /**
33704dab5c37SJack F Vogel * e1000_clock_out_i2c_bit - Clocks in/out one bit via I2C data/clock
33714dab5c37SJack F Vogel * @hw: pointer to hardware structure
33724dab5c37SJack F Vogel * @data: data value to write
33734dab5c37SJack F Vogel *
33744dab5c37SJack F Vogel * Clocks out one bit via I2C data/clock
33754dab5c37SJack F Vogel **/
e1000_clock_out_i2c_bit(struct e1000_hw * hw,bool data)33764dab5c37SJack F Vogel static s32 e1000_clock_out_i2c_bit(struct e1000_hw *hw, bool data)
33774dab5c37SJack F Vogel {
33784dab5c37SJack F Vogel s32 status;
33794dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
33804dab5c37SJack F Vogel
33814dab5c37SJack F Vogel DEBUGFUNC("e1000_clock_out_i2c_bit");
33824dab5c37SJack F Vogel
33834dab5c37SJack F Vogel status = e1000_set_i2c_data(hw, &i2cctl, data);
33844dab5c37SJack F Vogel if (status == E1000_SUCCESS) {
33854dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl);
33864dab5c37SJack F Vogel
33874dab5c37SJack F Vogel /* Minimum high period of clock is 4us */
33884dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH);
33894dab5c37SJack F Vogel
33904dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl);
33914dab5c37SJack F Vogel
33924dab5c37SJack F Vogel /* Minimum low period of clock is 4.7 us.
33934dab5c37SJack F Vogel * This also takes care of the data hold time.
33944dab5c37SJack F Vogel */
33954dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW);
33964dab5c37SJack F Vogel } else {
33974dab5c37SJack F Vogel status = E1000_ERR_I2C;
33984dab5c37SJack F Vogel DEBUGOUT1("I2C data was not set to %X\n", data);
33994dab5c37SJack F Vogel }
34004dab5c37SJack F Vogel
34014dab5c37SJack F Vogel return status;
34024dab5c37SJack F Vogel }
34034dab5c37SJack F Vogel /**
34044dab5c37SJack F Vogel * e1000_raise_i2c_clk - Raises the I2C SCL clock
34054dab5c37SJack F Vogel * @hw: pointer to hardware structure
34064dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register
34074dab5c37SJack F Vogel *
34084dab5c37SJack F Vogel * Raises the I2C clock line '0'->'1'
34094dab5c37SJack F Vogel **/
e1000_raise_i2c_clk(struct e1000_hw * hw,u32 * i2cctl)34104dab5c37SJack F Vogel static void e1000_raise_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
34114dab5c37SJack F Vogel {
34124dab5c37SJack F Vogel DEBUGFUNC("e1000_raise_i2c_clk");
34134dab5c37SJack F Vogel
34144dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OUT;
34154dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N;
34164dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
34174dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
34184dab5c37SJack F Vogel
34194dab5c37SJack F Vogel /* SCL rise time (1000ns) */
34204dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE);
34214dab5c37SJack F Vogel }
34224dab5c37SJack F Vogel
34234dab5c37SJack F Vogel /**
34244dab5c37SJack F Vogel * e1000_lower_i2c_clk - Lowers the I2C SCL clock
34254dab5c37SJack F Vogel * @hw: pointer to hardware structure
34264dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register
34274dab5c37SJack F Vogel *
34284dab5c37SJack F Vogel * Lowers the I2C clock line '1'->'0'
34294dab5c37SJack F Vogel **/
e1000_lower_i2c_clk(struct e1000_hw * hw,u32 * i2cctl)34304dab5c37SJack F Vogel static void e1000_lower_i2c_clk(struct e1000_hw *hw, u32 *i2cctl)
34314dab5c37SJack F Vogel {
34324dab5c37SJack F Vogel
34334dab5c37SJack F Vogel DEBUGFUNC("e1000_lower_i2c_clk");
34344dab5c37SJack F Vogel
34354dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OUT;
34364dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_CLK_OE_N;
34374dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
34384dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
34394dab5c37SJack F Vogel
34404dab5c37SJack F Vogel /* SCL fall time (300ns) */
34414dab5c37SJack F Vogel usec_delay(E1000_I2C_T_FALL);
34424dab5c37SJack F Vogel }
34434dab5c37SJack F Vogel
34444dab5c37SJack F Vogel /**
34454dab5c37SJack F Vogel * e1000_set_i2c_data - Sets the I2C data bit
34464dab5c37SJack F Vogel * @hw: pointer to hardware structure
34474dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register
34484dab5c37SJack F Vogel * @data: I2C data value (0 or 1) to set
34494dab5c37SJack F Vogel *
34504dab5c37SJack F Vogel * Sets the I2C data bit
34514dab5c37SJack F Vogel **/
e1000_set_i2c_data(struct e1000_hw * hw,u32 * i2cctl,bool data)34524dab5c37SJack F Vogel static s32 e1000_set_i2c_data(struct e1000_hw *hw, u32 *i2cctl, bool data)
34534dab5c37SJack F Vogel {
34544dab5c37SJack F Vogel s32 status = E1000_SUCCESS;
34554dab5c37SJack F Vogel
34564dab5c37SJack F Vogel DEBUGFUNC("e1000_set_i2c_data");
34574dab5c37SJack F Vogel
34584dab5c37SJack F Vogel if (data)
34594dab5c37SJack F Vogel *i2cctl |= E1000_I2C_DATA_OUT;
34604dab5c37SJack F Vogel else
34614dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OUT;
34624dab5c37SJack F Vogel
34634dab5c37SJack F Vogel *i2cctl &= ~E1000_I2C_DATA_OE_N;
34644dab5c37SJack F Vogel *i2cctl |= E1000_I2C_CLK_OE_N;
34654dab5c37SJack F Vogel E1000_WRITE_REG(hw, E1000_I2CPARAMS, *i2cctl);
34664dab5c37SJack F Vogel E1000_WRITE_FLUSH(hw);
34674dab5c37SJack F Vogel
34684dab5c37SJack F Vogel /* Data rise/fall (1000ns/300ns) and set-up time (250ns) */
34694dab5c37SJack F Vogel usec_delay(E1000_I2C_T_RISE + E1000_I2C_T_FALL + E1000_I2C_T_SU_DATA);
34704dab5c37SJack F Vogel
34714dab5c37SJack F Vogel *i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
34724dab5c37SJack F Vogel if (data != e1000_get_i2c_data(i2cctl)) {
34734dab5c37SJack F Vogel status = E1000_ERR_I2C;
34744dab5c37SJack F Vogel DEBUGOUT1("Error - I2C data was not set to %X.\n", data);
34754dab5c37SJack F Vogel }
34764dab5c37SJack F Vogel
34774dab5c37SJack F Vogel return status;
34784dab5c37SJack F Vogel }
34794dab5c37SJack F Vogel
34804dab5c37SJack F Vogel /**
34814dab5c37SJack F Vogel * e1000_get_i2c_data - Reads the I2C SDA data bit
34824dab5c37SJack F Vogel * @i2cctl: Current value of I2CCTL register
34834dab5c37SJack F Vogel *
34844dab5c37SJack F Vogel * Returns the I2C data bit value
34854dab5c37SJack F Vogel **/
e1000_get_i2c_data(u32 * i2cctl)34864dab5c37SJack F Vogel static bool e1000_get_i2c_data(u32 *i2cctl)
34874dab5c37SJack F Vogel {
34884dab5c37SJack F Vogel bool data;
34894dab5c37SJack F Vogel
34904dab5c37SJack F Vogel DEBUGFUNC("e1000_get_i2c_data");
34914dab5c37SJack F Vogel
34924dab5c37SJack F Vogel if (*i2cctl & E1000_I2C_DATA_IN)
34934dab5c37SJack F Vogel data = 1;
34944dab5c37SJack F Vogel else
34954dab5c37SJack F Vogel data = 0;
34964dab5c37SJack F Vogel
34974dab5c37SJack F Vogel return data;
34984dab5c37SJack F Vogel }
34994dab5c37SJack F Vogel
35004dab5c37SJack F Vogel /**
35014dab5c37SJack F Vogel * e1000_i2c_bus_clear - Clears the I2C bus
35024dab5c37SJack F Vogel * @hw: pointer to hardware structure
35034dab5c37SJack F Vogel *
35044dab5c37SJack F Vogel * Clears the I2C bus by sending nine clock pulses.
35054dab5c37SJack F Vogel * Used when data line is stuck low.
35064dab5c37SJack F Vogel **/
e1000_i2c_bus_clear(struct e1000_hw * hw)35074dab5c37SJack F Vogel void e1000_i2c_bus_clear(struct e1000_hw *hw)
35084dab5c37SJack F Vogel {
35094dab5c37SJack F Vogel u32 i2cctl = E1000_READ_REG(hw, E1000_I2CPARAMS);
35104dab5c37SJack F Vogel u32 i;
35114dab5c37SJack F Vogel
35124dab5c37SJack F Vogel DEBUGFUNC("e1000_i2c_bus_clear");
35134dab5c37SJack F Vogel
35144dab5c37SJack F Vogel e1000_i2c_start(hw);
35154dab5c37SJack F Vogel
35164dab5c37SJack F Vogel e1000_set_i2c_data(hw, &i2cctl, 1);
35174dab5c37SJack F Vogel
35184dab5c37SJack F Vogel for (i = 0; i < 9; i++) {
35194dab5c37SJack F Vogel e1000_raise_i2c_clk(hw, &i2cctl);
35204dab5c37SJack F Vogel
35214dab5c37SJack F Vogel /* Min high period of clock is 4us */
35224dab5c37SJack F Vogel usec_delay(E1000_I2C_T_HIGH);
35234dab5c37SJack F Vogel
35244dab5c37SJack F Vogel e1000_lower_i2c_clk(hw, &i2cctl);
35254dab5c37SJack F Vogel
35264dab5c37SJack F Vogel /* Min low period of clock is 4.7us*/
35274dab5c37SJack F Vogel usec_delay(E1000_I2C_T_LOW);
35284dab5c37SJack F Vogel }
35294dab5c37SJack F Vogel
35304dab5c37SJack F Vogel e1000_i2c_start(hw);
35314dab5c37SJack F Vogel
35324dab5c37SJack F Vogel /* Put the i2c bus back to default state */
35334dab5c37SJack F Vogel e1000_i2c_stop(hw);
35344dab5c37SJack F Vogel }
35354dab5c37SJack F Vogel
3536