175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi
3*49b78600SRobert Mustacchi Copyright (c) 2001-2015, Intel Corporation
475eba5b6SRobert Mustacchi All rights reserved.
575eba5b6SRobert Mustacchi
675eba5b6SRobert Mustacchi Redistribution and use in source and binary forms, with or without
775eba5b6SRobert Mustacchi modification, are permitted provided that the following conditions are met:
875eba5b6SRobert Mustacchi
975eba5b6SRobert Mustacchi 1. Redistributions of source code must retain the above copyright notice,
1075eba5b6SRobert Mustacchi this list of conditions and the following disclaimer.
1175eba5b6SRobert Mustacchi
1275eba5b6SRobert Mustacchi 2. Redistributions in binary form must reproduce the above copyright
1375eba5b6SRobert Mustacchi notice, this list of conditions and the following disclaimer in the
1475eba5b6SRobert Mustacchi documentation and/or other materials provided with the distribution.
1575eba5b6SRobert Mustacchi
1675eba5b6SRobert Mustacchi 3. Neither the name of the Intel Corporation nor the names of its
1775eba5b6SRobert Mustacchi contributors may be used to endorse or promote products derived from
1875eba5b6SRobert Mustacchi this software without specific prior written permission.
1975eba5b6SRobert Mustacchi
2075eba5b6SRobert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2175eba5b6SRobert Mustacchi AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2275eba5b6SRobert Mustacchi IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2375eba5b6SRobert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2475eba5b6SRobert Mustacchi LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2575eba5b6SRobert Mustacchi CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2675eba5b6SRobert Mustacchi SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2775eba5b6SRobert Mustacchi INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2875eba5b6SRobert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2975eba5b6SRobert Mustacchi ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3075eba5b6SRobert Mustacchi POSSIBILITY OF SUCH DAMAGE.
3175eba5b6SRobert Mustacchi
3275eba5b6SRobert Mustacchi ******************************************************************************/
3375eba5b6SRobert Mustacchi /*$FreeBSD$*/
34592a4d85Scc
3525f2d433Sxy /*
36d5c3073dSchenlu chen - Sun Microsystems - Beijing China * 82541EI Gigabit Ethernet Controller
37d5c3073dSchenlu chen - Sun Microsystems - Beijing China * 82541ER Gigabit Ethernet Controller
38d5c3073dSchenlu chen - Sun Microsystems - Beijing China * 82541GI Gigabit Ethernet Controller
39d5c3073dSchenlu chen - Sun Microsystems - Beijing China * 82541PI Gigabit Ethernet Controller
40d5c3073dSchenlu chen - Sun Microsystems - Beijing China * 82547EI Gigabit Ethernet Controller
41d5c3073dSchenlu chen - Sun Microsystems - Beijing China * 82547GI Gigabit Ethernet Controller
4225f2d433Sxy */
4325f2d433Sxy
4425f2d433Sxy #include "e1000_api.h"
4525f2d433Sxy
4675eba5b6SRobert Mustacchi static s32 e1000_init_phy_params_82541(struct e1000_hw *hw);
4775eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw);
4875eba5b6SRobert Mustacchi static s32 e1000_init_mac_params_82541(struct e1000_hw *hw);
4975eba5b6SRobert Mustacchi static s32 e1000_reset_hw_82541(struct e1000_hw *hw);
5075eba5b6SRobert Mustacchi static s32 e1000_init_hw_82541(struct e1000_hw *hw);
5175eba5b6SRobert Mustacchi static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
52*49b78600SRobert Mustacchi u16 *duplex);
5375eba5b6SRobert Mustacchi static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw);
5475eba5b6SRobert Mustacchi static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw);
5575eba5b6SRobert Mustacchi static s32 e1000_check_for_link_82541(struct e1000_hw *hw);
5675eba5b6SRobert Mustacchi static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw);
5775eba5b6SRobert Mustacchi static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw,
58*49b78600SRobert Mustacchi bool active);
5975eba5b6SRobert Mustacchi static s32 e1000_setup_led_82541(struct e1000_hw *hw);
6075eba5b6SRobert Mustacchi static s32 e1000_cleanup_led_82541(struct e1000_hw *hw);
6125f2d433Sxy static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw);
6275eba5b6SRobert Mustacchi static s32 e1000_read_mac_addr_82541(struct e1000_hw *hw);
6375eba5b6SRobert Mustacchi static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
64*49b78600SRobert Mustacchi bool link_up);
6575eba5b6SRobert Mustacchi static s32 e1000_phy_init_script_82541(struct e1000_hw *hw);
66592a4d85Scc static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw);
6725f2d433Sxy
68*49b78600SRobert Mustacchi static const u16 e1000_igp_cable_length_table[] = {
69*49b78600SRobert Mustacchi 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 10, 10, 10, 10, 10,
70*49b78600SRobert Mustacchi 10, 10, 20, 20, 20, 20, 20, 25, 25, 25, 25, 25, 25, 25, 30, 30, 30, 30,
71*49b78600SRobert Mustacchi 40, 40, 40, 40, 40, 40, 40, 40, 40, 50, 50, 50, 50, 50, 50, 50, 60, 60,
72*49b78600SRobert Mustacchi 60, 60, 60, 60, 60, 60, 60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80,
73*49b78600SRobert Mustacchi 80, 90, 90, 90, 90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100,
74*49b78600SRobert Mustacchi 100, 100, 100, 100, 100, 100, 100, 100, 110, 110, 110, 110, 110, 110,
75*49b78600SRobert Mustacchi 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 120, 120,
76*49b78600SRobert Mustacchi 120, 120, 120, 120, 120, 120, 120, 120};
7775eba5b6SRobert Mustacchi #define IGP01E1000_AGC_LENGTH_TABLE_SIZE \
78*49b78600SRobert Mustacchi (sizeof(e1000_igp_cable_length_table) / \
79*49b78600SRobert Mustacchi sizeof(e1000_igp_cable_length_table[0]))
8075eba5b6SRobert Mustacchi
8175eba5b6SRobert Mustacchi /**
8275eba5b6SRobert Mustacchi * e1000_init_phy_params_82541 - Init PHY func ptrs.
8375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
8475eba5b6SRobert Mustacchi **/
e1000_init_phy_params_82541(struct e1000_hw * hw)8575eba5b6SRobert Mustacchi static s32 e1000_init_phy_params_82541(struct e1000_hw *hw)
8625f2d433Sxy {
8725f2d433Sxy struct e1000_phy_info *phy = &hw->phy;
88*49b78600SRobert Mustacchi s32 ret_val;
8925f2d433Sxy
9025f2d433Sxy DEBUGFUNC("e1000_init_phy_params_82541");
9125f2d433Sxy
92*49b78600SRobert Mustacchi phy->addr = 1;
93*49b78600SRobert Mustacchi phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
94*49b78600SRobert Mustacchi phy->reset_delay_us = 10000;
95*49b78600SRobert Mustacchi phy->type = e1000_phy_igp;
9625f2d433Sxy
9725f2d433Sxy /* Function Pointers */
98*49b78600SRobert Mustacchi phy->ops.check_polarity = e1000_check_polarity_igp;
99*49b78600SRobert Mustacchi phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
100*49b78600SRobert Mustacchi phy->ops.get_cable_length = e1000_get_cable_length_igp_82541;
101*49b78600SRobert Mustacchi phy->ops.get_cfg_done = e1000_get_cfg_done_generic;
102*49b78600SRobert Mustacchi phy->ops.get_info = e1000_get_phy_info_igp;
103*49b78600SRobert Mustacchi phy->ops.read_reg = e1000_read_phy_reg_igp;
104*49b78600SRobert Mustacchi phy->ops.reset = e1000_phy_hw_reset_82541;
105*49b78600SRobert Mustacchi phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_82541;
106*49b78600SRobert Mustacchi phy->ops.write_reg = e1000_write_phy_reg_igp;
107*49b78600SRobert Mustacchi phy->ops.power_up = e1000_power_up_phy_copper;
108*49b78600SRobert Mustacchi phy->ops.power_down = e1000_power_down_phy_copper_82541;
10925f2d433Sxy
11025f2d433Sxy ret_val = e1000_get_phy_id(hw);
11125f2d433Sxy if (ret_val)
11225f2d433Sxy goto out;
11325f2d433Sxy
11425f2d433Sxy /* Verify phy id */
11525f2d433Sxy if (phy->id != IGP01E1000_I_PHY_ID) {
11625f2d433Sxy ret_val = -E1000_ERR_PHY;
11725f2d433Sxy goto out;
11825f2d433Sxy }
119caf05df5SMiles Xu, Sun Microsystems
12025f2d433Sxy out:
12175eba5b6SRobert Mustacchi return ret_val;
12225f2d433Sxy }
12325f2d433Sxy
12475eba5b6SRobert Mustacchi /**
12575eba5b6SRobert Mustacchi * e1000_init_nvm_params_82541 - Init NVM func ptrs.
12675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
12775eba5b6SRobert Mustacchi **/
e1000_init_nvm_params_82541(struct e1000_hw * hw)12875eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
12925f2d433Sxy {
130*49b78600SRobert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
131*49b78600SRobert Mustacchi s32 ret_val = E1000_SUCCESS;
13225f2d433Sxy u32 eecd = E1000_READ_REG(hw, E1000_EECD);
13325f2d433Sxy u16 size;
13425f2d433Sxy
13525f2d433Sxy DEBUGFUNC("e1000_init_nvm_params_82541");
13625f2d433Sxy
13725f2d433Sxy switch (nvm->override) {
13825f2d433Sxy case e1000_nvm_override_spi_large:
13925f2d433Sxy nvm->type = e1000_nvm_eeprom_spi;
14025f2d433Sxy eecd |= E1000_EECD_ADDR_BITS;
14125f2d433Sxy break;
14225f2d433Sxy case e1000_nvm_override_spi_small:
14325f2d433Sxy nvm->type = e1000_nvm_eeprom_spi;
14425f2d433Sxy eecd &= ~E1000_EECD_ADDR_BITS;
14525f2d433Sxy break;
14625f2d433Sxy case e1000_nvm_override_microwire_large:
14725f2d433Sxy nvm->type = e1000_nvm_eeprom_microwire;
14825f2d433Sxy eecd |= E1000_EECD_SIZE;
14925f2d433Sxy break;
15025f2d433Sxy case e1000_nvm_override_microwire_small:
15125f2d433Sxy nvm->type = e1000_nvm_eeprom_microwire;
15225f2d433Sxy eecd &= ~E1000_EECD_SIZE;
15325f2d433Sxy break;
15425f2d433Sxy default:
155*49b78600SRobert Mustacchi nvm->type = eecd & E1000_EECD_TYPE ? e1000_nvm_eeprom_spi
156*49b78600SRobert Mustacchi : e1000_nvm_eeprom_microwire;
15725f2d433Sxy break;
15825f2d433Sxy }
15925f2d433Sxy
16025f2d433Sxy if (nvm->type == e1000_nvm_eeprom_spi) {
161*49b78600SRobert Mustacchi nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 16 : 8;
162*49b78600SRobert Mustacchi nvm->delay_usec = 1;
163*49b78600SRobert Mustacchi nvm->opcode_bits = 8;
164*49b78600SRobert Mustacchi nvm->page_size = (eecd & E1000_EECD_ADDR_BITS) ? 32 : 8;
16525f2d433Sxy
16625f2d433Sxy /* Function Pointers */
167*49b78600SRobert Mustacchi nvm->ops.acquire = e1000_acquire_nvm_generic;
168*49b78600SRobert Mustacchi nvm->ops.read = e1000_read_nvm_spi;
169*49b78600SRobert Mustacchi nvm->ops.release = e1000_release_nvm_generic;
170*49b78600SRobert Mustacchi nvm->ops.update = e1000_update_nvm_checksum_generic;
171592a4d85Scc nvm->ops.valid_led_default = e1000_valid_led_default_generic;
172*49b78600SRobert Mustacchi nvm->ops.validate = e1000_validate_nvm_checksum_generic;
173*49b78600SRobert Mustacchi nvm->ops.write = e1000_write_nvm_spi;
17425f2d433Sxy
17525f2d433Sxy /*
17625f2d433Sxy * nvm->word_size must be discovered after the pointers
17725f2d433Sxy * are set so we can verify the size from the nvm image
17875eba5b6SRobert Mustacchi * itself. Temporarily set it to a dummy value so the
17925f2d433Sxy * read will work.
18025f2d433Sxy */
18125f2d433Sxy nvm->word_size = 64;
182592a4d85Scc ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size);
18325f2d433Sxy if (ret_val)
18425f2d433Sxy goto out;
18525f2d433Sxy size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT;
18625f2d433Sxy /*
18725f2d433Sxy * if size != 0, it can be added to a constant and become
18825f2d433Sxy * the left-shift value to set the word_size. Otherwise,
18925f2d433Sxy * word_size stays at 64.
19025f2d433Sxy */
19125f2d433Sxy if (size) {
19225f2d433Sxy size += NVM_WORD_SIZE_BASE_SHIFT_82541;
19325f2d433Sxy nvm->word_size = 1 << size;
19425f2d433Sxy }
19525f2d433Sxy } else {
196*49b78600SRobert Mustacchi nvm->address_bits = (eecd & E1000_EECD_ADDR_BITS) ? 8 : 6;
197*49b78600SRobert Mustacchi nvm->delay_usec = 50;
198*49b78600SRobert Mustacchi nvm->opcode_bits = 3;
199*49b78600SRobert Mustacchi nvm->word_size = (eecd & E1000_EECD_ADDR_BITS) ? 256 : 64;
20025f2d433Sxy
20125f2d433Sxy /* Function Pointers */
202*49b78600SRobert Mustacchi nvm->ops.acquire = e1000_acquire_nvm_generic;
203*49b78600SRobert Mustacchi nvm->ops.read = e1000_read_nvm_microwire;
204*49b78600SRobert Mustacchi nvm->ops.release = e1000_release_nvm_generic;
205*49b78600SRobert Mustacchi nvm->ops.update = e1000_update_nvm_checksum_generic;
206592a4d85Scc nvm->ops.valid_led_default = e1000_valid_led_default_generic;
207*49b78600SRobert Mustacchi nvm->ops.validate = e1000_validate_nvm_checksum_generic;
208*49b78600SRobert Mustacchi nvm->ops.write = e1000_write_nvm_microwire;
20925f2d433Sxy }
21025f2d433Sxy
21125f2d433Sxy out:
21275eba5b6SRobert Mustacchi return ret_val;
21325f2d433Sxy }
21425f2d433Sxy
21575eba5b6SRobert Mustacchi /**
21675eba5b6SRobert Mustacchi * e1000_init_mac_params_82541 - Init MAC func ptrs.
21775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
21875eba5b6SRobert Mustacchi **/
e1000_init_mac_params_82541(struct e1000_hw * hw)21975eba5b6SRobert Mustacchi static s32 e1000_init_mac_params_82541(struct e1000_hw *hw)
22025f2d433Sxy {
22125f2d433Sxy struct e1000_mac_info *mac = &hw->mac;
22225f2d433Sxy
22325f2d433Sxy DEBUGFUNC("e1000_init_mac_params_82541");
22425f2d433Sxy
22525f2d433Sxy /* Set media type */
226592a4d85Scc hw->phy.media_type = e1000_media_type_copper;
22725f2d433Sxy /* Set mta register count */
22825f2d433Sxy mac->mta_reg_count = 128;
22925f2d433Sxy /* Set rar entry count */
23025f2d433Sxy mac->rar_entry_count = E1000_RAR_ENTRIES;
23125f2d433Sxy /* Set if part includes ASF firmware */
23275eba5b6SRobert Mustacchi mac->asf_firmware_present = TRUE;
23325f2d433Sxy
23425f2d433Sxy /* Function Pointers */
23525f2d433Sxy
23625f2d433Sxy /* bus type/speed/width */
237592a4d85Scc mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
238caf05df5SMiles Xu, Sun Microsystems /* function id */
239caf05df5SMiles Xu, Sun Microsystems mac->ops.set_lan_id = e1000_set_lan_id_single_port;
24025f2d433Sxy /* reset */
241592a4d85Scc mac->ops.reset_hw = e1000_reset_hw_82541;
24225f2d433Sxy /* hw initialization */
243592a4d85Scc mac->ops.init_hw = e1000_init_hw_82541;
24425f2d433Sxy /* link setup */
245592a4d85Scc mac->ops.setup_link = e1000_setup_link_generic;
24625f2d433Sxy /* physical interface link setup */
247592a4d85Scc mac->ops.setup_physical_interface = e1000_setup_copper_link_82541;
24825f2d433Sxy /* check for link */
249592a4d85Scc mac->ops.check_for_link = e1000_check_for_link_82541;
25025f2d433Sxy /* link info */
251592a4d85Scc mac->ops.get_link_up_info = e1000_get_link_up_info_82541;
25225f2d433Sxy /* multicast address update */
253592a4d85Scc mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
25425f2d433Sxy /* writing VFTA */
255592a4d85Scc mac->ops.write_vfta = e1000_write_vfta_generic;
25625f2d433Sxy /* clearing VFTA */
257592a4d85Scc mac->ops.clear_vfta = e1000_clear_vfta_generic;
25875eba5b6SRobert Mustacchi /* read mac address */
25975eba5b6SRobert Mustacchi mac->ops.read_mac_addr = e1000_read_mac_addr_82541;
260caf05df5SMiles Xu, Sun Microsystems /* ID LED init */
261caf05df5SMiles Xu, Sun Microsystems mac->ops.id_led_init = e1000_id_led_init_generic;
26225f2d433Sxy /* setup LED */
263592a4d85Scc mac->ops.setup_led = e1000_setup_led_82541;
26425f2d433Sxy /* cleanup LED */
265592a4d85Scc mac->ops.cleanup_led = e1000_cleanup_led_82541;
26625f2d433Sxy /* turn on/off LED */
267592a4d85Scc mac->ops.led_on = e1000_led_on_generic;
268592a4d85Scc mac->ops.led_off = e1000_led_off_generic;
26925f2d433Sxy /* clear hardware counters */
270592a4d85Scc mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541;
27125f2d433Sxy
27275eba5b6SRobert Mustacchi return E1000_SUCCESS;
27325f2d433Sxy }
27425f2d433Sxy
27575eba5b6SRobert Mustacchi /**
27675eba5b6SRobert Mustacchi * e1000_init_function_pointers_82541 - Init func ptrs.
27775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
27825f2d433Sxy *
27975eba5b6SRobert Mustacchi * Called to initialize all function pointers and parameters.
28075eba5b6SRobert Mustacchi **/
e1000_init_function_pointers_82541(struct e1000_hw * hw)28175eba5b6SRobert Mustacchi void e1000_init_function_pointers_82541(struct e1000_hw *hw)
28225f2d433Sxy {
28325f2d433Sxy DEBUGFUNC("e1000_init_function_pointers_82541");
28425f2d433Sxy
285592a4d85Scc hw->mac.ops.init_params = e1000_init_mac_params_82541;
286592a4d85Scc hw->nvm.ops.init_params = e1000_init_nvm_params_82541;
287592a4d85Scc hw->phy.ops.init_params = e1000_init_phy_params_82541;
28825f2d433Sxy }
28925f2d433Sxy
29075eba5b6SRobert Mustacchi /**
29175eba5b6SRobert Mustacchi * e1000_reset_hw_82541 - Reset hardware
29275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
29325f2d433Sxy *
29475eba5b6SRobert Mustacchi * This resets the hardware into a known state.
29575eba5b6SRobert Mustacchi **/
e1000_reset_hw_82541(struct e1000_hw * hw)29675eba5b6SRobert Mustacchi static s32 e1000_reset_hw_82541(struct e1000_hw *hw)
29725f2d433Sxy {
298*49b78600SRobert Mustacchi u32 ledctl, ctrl, manc;
29925f2d433Sxy
30025f2d433Sxy DEBUGFUNC("e1000_reset_hw_82541");
30125f2d433Sxy
30225f2d433Sxy DEBUGOUT("Masking off all interrupts\n");
30325f2d433Sxy E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
30425f2d433Sxy
30525f2d433Sxy E1000_WRITE_REG(hw, E1000_RCTL, 0);
30625f2d433Sxy E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
30725f2d433Sxy E1000_WRITE_FLUSH(hw);
30825f2d433Sxy
30925f2d433Sxy /*
31025f2d433Sxy * Delay to allow any outstanding PCI transactions to complete
31125f2d433Sxy * before resetting the device.
31225f2d433Sxy */
31325f2d433Sxy msec_delay(10);
31425f2d433Sxy
31525f2d433Sxy ctrl = E1000_READ_REG(hw, E1000_CTRL);
31625f2d433Sxy
31725f2d433Sxy /* Must reset the Phy before resetting the MAC */
31825f2d433Sxy if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
31925f2d433Sxy E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST));
320*49b78600SRobert Mustacchi E1000_WRITE_FLUSH(hw);
32125f2d433Sxy msec_delay(5);
32225f2d433Sxy }
32325f2d433Sxy
32425f2d433Sxy DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n");
32525f2d433Sxy switch (hw->mac.type) {
32625f2d433Sxy case e1000_82541:
32725f2d433Sxy case e1000_82541_rev_2:
32825f2d433Sxy /*
32925f2d433Sxy * These controllers can't ack the 64-bit write when
33025f2d433Sxy * issuing the reset, so we use IO-mapping as a
33125f2d433Sxy * workaround to issue the reset.
33225f2d433Sxy */
33325f2d433Sxy E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
33425f2d433Sxy break;
33525f2d433Sxy default:
33625f2d433Sxy E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
33725f2d433Sxy break;
33825f2d433Sxy }
33925f2d433Sxy
34025f2d433Sxy /* Wait for NVM reload */
34125f2d433Sxy msec_delay(20);
34225f2d433Sxy
34325f2d433Sxy /* Disable HW ARPs on ASF enabled adapters */
34425f2d433Sxy manc = E1000_READ_REG(hw, E1000_MANC);
34525f2d433Sxy manc &= ~E1000_MANC_ARP_EN;
34625f2d433Sxy E1000_WRITE_REG(hw, E1000_MANC, manc);
34725f2d433Sxy
34825f2d433Sxy if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
34975eba5b6SRobert Mustacchi e1000_phy_init_script_82541(hw);
35025f2d433Sxy
35125f2d433Sxy /* Configure activity LED after Phy reset */
35225f2d433Sxy ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
35325f2d433Sxy ledctl &= IGP_ACTIVITY_LED_MASK;
35425f2d433Sxy ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
35525f2d433Sxy E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
35625f2d433Sxy }
35725f2d433Sxy
35825f2d433Sxy /* Once again, mask the interrupts */
35925f2d433Sxy DEBUGOUT("Masking off all interrupts\n");
36025f2d433Sxy E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
36125f2d433Sxy
36225f2d433Sxy /* Clear any pending interrupt events. */
363*49b78600SRobert Mustacchi E1000_READ_REG(hw, E1000_ICR);
36425f2d433Sxy
36575eba5b6SRobert Mustacchi return E1000_SUCCESS;
36625f2d433Sxy }
36725f2d433Sxy
36875eba5b6SRobert Mustacchi /**
36975eba5b6SRobert Mustacchi * e1000_init_hw_82541 - Initialize hardware
37075eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
37125f2d433Sxy *
37275eba5b6SRobert Mustacchi * This inits the hardware readying it for operation.
37375eba5b6SRobert Mustacchi **/
e1000_init_hw_82541(struct e1000_hw * hw)37475eba5b6SRobert Mustacchi static s32 e1000_init_hw_82541(struct e1000_hw *hw)
37525f2d433Sxy {
37625f2d433Sxy struct e1000_mac_info *mac = &hw->mac;
377d5c3073dSchenlu chen - Sun Microsystems - Beijing China struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
37825f2d433Sxy u32 i, txdctl;
37925f2d433Sxy s32 ret_val;
38025f2d433Sxy
38125f2d433Sxy DEBUGFUNC("e1000_init_hw_82541");
38225f2d433Sxy
38325f2d433Sxy /* Initialize identification LED */
384caf05df5SMiles Xu, Sun Microsystems ret_val = mac->ops.id_led_init(hw);
38525f2d433Sxy if (ret_val) {
38625f2d433Sxy DEBUGOUT("Error initializing identification LED\n");
387592a4d85Scc /* This is not fatal and we should not stop init due to this */
38825f2d433Sxy }
389*49b78600SRobert Mustacchi
390caf05df5SMiles Xu, Sun Microsystems /* Storing the Speed Power Down value for later use */
391*49b78600SRobert Mustacchi ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
392*49b78600SRobert Mustacchi &dev_spec->spd_default);
393caf05df5SMiles Xu, Sun Microsystems if (ret_val)
394111c450cSMiles Xu, Sun Microsystems goto out;
395111c450cSMiles Xu, Sun Microsystems
39625f2d433Sxy /* Disabling VLAN filtering */
39725f2d433Sxy DEBUGOUT("Initializing the IEEE VLAN\n");
398592a4d85Scc mac->ops.clear_vfta(hw);
39925f2d433Sxy
40025f2d433Sxy /* Setup the receive address. */
40125f2d433Sxy e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
40225f2d433Sxy
40325f2d433Sxy /* Zero out the Multicast HASH table */
40425f2d433Sxy DEBUGOUT("Zeroing the MTA\n");
40525f2d433Sxy for (i = 0; i < mac->mta_reg_count; i++) {
40625f2d433Sxy E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
40725f2d433Sxy /*
40825f2d433Sxy * Avoid back to back register writes by adding the register
40925f2d433Sxy * read (flush). This is to protect against some strange
41025f2d433Sxy * bridge configurations that may issue Memory Write Block
41125f2d433Sxy * (MWB) to our register space.
41225f2d433Sxy */
41325f2d433Sxy E1000_WRITE_FLUSH(hw);
41425f2d433Sxy }
41525f2d433Sxy
41625f2d433Sxy /* Setup link and flow control */
417592a4d85Scc ret_val = mac->ops.setup_link(hw);
41825f2d433Sxy
419592a4d85Scc txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
42025f2d433Sxy txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
421*49b78600SRobert Mustacchi E1000_TXDCTL_FULL_TX_DESC_WB;
422592a4d85Scc E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
42325f2d433Sxy
42425f2d433Sxy /*
42525f2d433Sxy * Clear all of the statistics registers (clear on read). It is
42625f2d433Sxy * important that we do this after we have tried to establish link
42725f2d433Sxy * because the symbol error count will increment wildly if there
42825f2d433Sxy * is no link.
42925f2d433Sxy */
43025f2d433Sxy e1000_clear_hw_cntrs_82541(hw);
43125f2d433Sxy
432111c450cSMiles Xu, Sun Microsystems out:
43375eba5b6SRobert Mustacchi return ret_val;
43425f2d433Sxy }
43525f2d433Sxy
43675eba5b6SRobert Mustacchi /**
43725f2d433Sxy * e1000_get_link_up_info_82541 - Report speed and duplex
43825f2d433Sxy * @hw: pointer to the HW structure
43925f2d433Sxy * @speed: pointer to speed buffer
44025f2d433Sxy * @duplex: pointer to duplex buffer
44125f2d433Sxy *
44225f2d433Sxy * Retrieve the current speed and duplex configuration.
44375eba5b6SRobert Mustacchi **/
e1000_get_link_up_info_82541(struct e1000_hw * hw,u16 * speed,u16 * duplex)44475eba5b6SRobert Mustacchi static s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
445*49b78600SRobert Mustacchi u16 *duplex)
44625f2d433Sxy {
44725f2d433Sxy struct e1000_phy_info *phy = &hw->phy;
44825f2d433Sxy s32 ret_val;
44925f2d433Sxy u16 data;
45025f2d433Sxy
45125f2d433Sxy DEBUGFUNC("e1000_get_link_up_info_82541");
45225f2d433Sxy
45325f2d433Sxy ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex);
45425f2d433Sxy if (ret_val)
45525f2d433Sxy goto out;
45625f2d433Sxy
45725f2d433Sxy if (!phy->speed_downgraded)
45825f2d433Sxy goto out;
45925f2d433Sxy
46025f2d433Sxy /*
46125f2d433Sxy * IGP01 PHY may advertise full duplex operation after speed
46225f2d433Sxy * downgrade even if it is operating at half duplex.
46325f2d433Sxy * Here we set the duplex settings to match the duplex in the
46425f2d433Sxy * link partner's capabilities.
46525f2d433Sxy */
466592a4d85Scc ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data);
46725f2d433Sxy if (ret_val)
46825f2d433Sxy goto out;
46925f2d433Sxy
47025f2d433Sxy if (!(data & NWAY_ER_LP_NWAY_CAPS)) {
47125f2d433Sxy *duplex = HALF_DUPLEX;
47225f2d433Sxy } else {
473592a4d85Scc ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data);
47425f2d433Sxy if (ret_val)
47525f2d433Sxy goto out;
47625f2d433Sxy
47725f2d433Sxy if (*speed == SPEED_100) {
47825f2d433Sxy if (!(data & NWAY_LPAR_100TX_FD_CAPS))
47925f2d433Sxy *duplex = HALF_DUPLEX;
48025f2d433Sxy } else if (*speed == SPEED_10) {
48125f2d433Sxy if (!(data & NWAY_LPAR_10T_FD_CAPS))
48225f2d433Sxy *duplex = HALF_DUPLEX;
48325f2d433Sxy }
48425f2d433Sxy }
48525f2d433Sxy
48625f2d433Sxy out:
48775eba5b6SRobert Mustacchi return ret_val;
48825f2d433Sxy }
48925f2d433Sxy
49075eba5b6SRobert Mustacchi /**
49175eba5b6SRobert Mustacchi * e1000_phy_hw_reset_82541 - PHY hardware reset
49275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
49325f2d433Sxy *
49475eba5b6SRobert Mustacchi * Verify the reset block is not blocking us from resetting. Acquire
49575eba5b6SRobert Mustacchi * semaphore (if necessary) and read/set/write the device control reset
49675eba5b6SRobert Mustacchi * bit in the PHY. Wait the appropriate delay time for the device to
49775eba5b6SRobert Mustacchi * reset and release the semaphore (if necessary).
49875eba5b6SRobert Mustacchi **/
e1000_phy_hw_reset_82541(struct e1000_hw * hw)49975eba5b6SRobert Mustacchi static s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw)
50025f2d433Sxy {
50125f2d433Sxy s32 ret_val;
50225f2d433Sxy u32 ledctl;
50325f2d433Sxy
50425f2d433Sxy DEBUGFUNC("e1000_phy_hw_reset_82541");
50525f2d433Sxy
50625f2d433Sxy ret_val = e1000_phy_hw_reset_generic(hw);
50725f2d433Sxy if (ret_val)
50825f2d433Sxy goto out;
50925f2d433Sxy
51075eba5b6SRobert Mustacchi e1000_phy_init_script_82541(hw);
51125f2d433Sxy
51225f2d433Sxy if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
51325f2d433Sxy /* Configure activity LED after PHY reset */
51425f2d433Sxy ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
51525f2d433Sxy ledctl &= IGP_ACTIVITY_LED_MASK;
51625f2d433Sxy ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
51725f2d433Sxy E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
51825f2d433Sxy }
51925f2d433Sxy
52025f2d433Sxy out:
52175eba5b6SRobert Mustacchi return ret_val;
52225f2d433Sxy }
52325f2d433Sxy
52475eba5b6SRobert Mustacchi /**
52575eba5b6SRobert Mustacchi * e1000_setup_copper_link_82541 - Configure copper link settings
52675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
52725f2d433Sxy *
52875eba5b6SRobert Mustacchi * Calls the appropriate function to configure the link for auto-neg or forced
52975eba5b6SRobert Mustacchi * speed and duplex. Then we check for link, once link is established calls
53075eba5b6SRobert Mustacchi * to configure collision distance and flow control are called. If link is
53175eba5b6SRobert Mustacchi * not established, we return -E1000_ERR_PHY (-2).
53275eba5b6SRobert Mustacchi **/
e1000_setup_copper_link_82541(struct e1000_hw * hw)53375eba5b6SRobert Mustacchi static s32 e1000_setup_copper_link_82541(struct e1000_hw *hw)
53425f2d433Sxy {
53525f2d433Sxy struct e1000_phy_info *phy = &hw->phy;
536d5c3073dSchenlu chen - Sun Microsystems - Beijing China struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
53775eba5b6SRobert Mustacchi s32 ret_val;
53825f2d433Sxy u32 ctrl, ledctl;
53925f2d433Sxy
54025f2d433Sxy DEBUGFUNC("e1000_setup_copper_link_82541");
54125f2d433Sxy
54225f2d433Sxy ctrl = E1000_READ_REG(hw, E1000_CTRL);
54325f2d433Sxy ctrl |= E1000_CTRL_SLU;
54425f2d433Sxy ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
54525f2d433Sxy E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
54625f2d433Sxy
547*49b78600SRobert Mustacchi
54825f2d433Sxy /* Earlier revs of the IGP phy require us to force MDI. */
54925f2d433Sxy if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
55025f2d433Sxy dev_spec->dsp_config = e1000_dsp_config_disabled;
55125f2d433Sxy phy->mdix = 1;
55225f2d433Sxy } else {
55325f2d433Sxy dev_spec->dsp_config = e1000_dsp_config_enabled;
55425f2d433Sxy }
55525f2d433Sxy
55625f2d433Sxy ret_val = e1000_copper_link_setup_igp(hw);
55725f2d433Sxy if (ret_val)
55825f2d433Sxy goto out;
55925f2d433Sxy
56025f2d433Sxy if (hw->mac.autoneg) {
56125f2d433Sxy if (dev_spec->ffe_config == e1000_ffe_config_active)
56225f2d433Sxy dev_spec->ffe_config = e1000_ffe_config_enabled;
56325f2d433Sxy }
56425f2d433Sxy
56525f2d433Sxy /* Configure activity LED after Phy reset */
56625f2d433Sxy ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
56725f2d433Sxy ledctl &= IGP_ACTIVITY_LED_MASK;
56825f2d433Sxy ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
56925f2d433Sxy E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
57025f2d433Sxy
57125f2d433Sxy ret_val = e1000_setup_copper_link_generic(hw);
57225f2d433Sxy
57325f2d433Sxy out:
57475eba5b6SRobert Mustacchi return ret_val;
57525f2d433Sxy }
57625f2d433Sxy
57775eba5b6SRobert Mustacchi /**
57875eba5b6SRobert Mustacchi * e1000_check_for_link_82541 - Check/Store link connection
57975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
58025f2d433Sxy *
58175eba5b6SRobert Mustacchi * This checks the link condition of the adapter and stores the
58275eba5b6SRobert Mustacchi * results in the hw->mac structure.
58375eba5b6SRobert Mustacchi **/
e1000_check_for_link_82541(struct e1000_hw * hw)58475eba5b6SRobert Mustacchi static s32 e1000_check_for_link_82541(struct e1000_hw *hw)
58525f2d433Sxy {
58625f2d433Sxy struct e1000_mac_info *mac = &hw->mac;
58725f2d433Sxy s32 ret_val;
588592a4d85Scc bool link;
58925f2d433Sxy
59025f2d433Sxy DEBUGFUNC("e1000_check_for_link_82541");
59125f2d433Sxy
59225f2d433Sxy /*
59325f2d433Sxy * We only want to go out to the PHY registers to see if Auto-Neg
59425f2d433Sxy * has completed and/or if our link status has changed. The
59525f2d433Sxy * get_link_status flag is set upon receiving a Link Status
59625f2d433Sxy * Change or Rx Sequence Error interrupt.
59725f2d433Sxy */
59825f2d433Sxy if (!mac->get_link_status) {
59925f2d433Sxy ret_val = E1000_SUCCESS;
60025f2d433Sxy goto out;
60125f2d433Sxy }
60225f2d433Sxy
60325f2d433Sxy /*
60425f2d433Sxy * First we want to see if the MII Status Register reports
60525f2d433Sxy * link. If so, then we want to get the current speed/duplex
60625f2d433Sxy * of the PHY.
60725f2d433Sxy */
60825f2d433Sxy ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
60925f2d433Sxy if (ret_val)
61025f2d433Sxy goto out;
61125f2d433Sxy
61225f2d433Sxy if (!link) {
61375eba5b6SRobert Mustacchi ret_val = e1000_config_dsp_after_link_change_82541(hw, FALSE);
61475eba5b6SRobert Mustacchi goto out; /* No link detected */
61525f2d433Sxy }
61625f2d433Sxy
61775eba5b6SRobert Mustacchi mac->get_link_status = FALSE;
61825f2d433Sxy
61925f2d433Sxy /*
62025f2d433Sxy * Check if there was DownShift, must be checked
62125f2d433Sxy * immediately after link-up
62225f2d433Sxy */
62375eba5b6SRobert Mustacchi e1000_check_downshift_generic(hw);
62425f2d433Sxy
62525f2d433Sxy /*
62625f2d433Sxy * If we are forcing speed/duplex, then we simply return since
62725f2d433Sxy * we have already determined whether we have link or not.
62825f2d433Sxy */
62925f2d433Sxy if (!mac->autoneg) {
63025f2d433Sxy ret_val = -E1000_ERR_CONFIG;
63125f2d433Sxy goto out;
63225f2d433Sxy }
63325f2d433Sxy
63475eba5b6SRobert Mustacchi ret_val = e1000_config_dsp_after_link_change_82541(hw, TRUE);
63525f2d433Sxy
63625f2d433Sxy /*
63725f2d433Sxy * Auto-Neg is enabled. Auto Speed Detection takes care
63825f2d433Sxy * of MAC speed/duplex configuration. So we only need to
63925f2d433Sxy * configure Collision Distance in the MAC.
64025f2d433Sxy */
64175eba5b6SRobert Mustacchi mac->ops.config_collision_dist(hw);
64225f2d433Sxy
64325f2d433Sxy /*
64425f2d433Sxy * Configure Flow Control now that Auto-Neg has completed.
64525f2d433Sxy * First, we need to restore the desired flow control
64625f2d433Sxy * settings because we may have had to re-autoneg with a
64725f2d433Sxy * different link partner.
64825f2d433Sxy */
64925f2d433Sxy ret_val = e1000_config_fc_after_link_up_generic(hw);
650*49b78600SRobert Mustacchi if (ret_val)
65125f2d433Sxy DEBUGOUT("Error configuring flow control\n");
65225f2d433Sxy
65325f2d433Sxy out:
65475eba5b6SRobert Mustacchi return ret_val;
65525f2d433Sxy }
65625f2d433Sxy
65775eba5b6SRobert Mustacchi /**
65875eba5b6SRobert Mustacchi * e1000_config_dsp_after_link_change_82541 - Config DSP after link
65975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
66075eba5b6SRobert Mustacchi * @link_up: boolean flag for link up status
66125f2d433Sxy *
66275eba5b6SRobert Mustacchi * Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS
66375eba5b6SRobert Mustacchi * at any other case.
66425f2d433Sxy *
66575eba5b6SRobert Mustacchi * 82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
66675eba5b6SRobert Mustacchi * gigabit link is achieved to improve link quality.
66775eba5b6SRobert Mustacchi **/
e1000_config_dsp_after_link_change_82541(struct e1000_hw * hw,bool link_up)66875eba5b6SRobert Mustacchi static s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
669*49b78600SRobert Mustacchi bool link_up)
67025f2d433Sxy {
67125f2d433Sxy struct e1000_phy_info *phy = &hw->phy;
672d5c3073dSchenlu chen - Sun Microsystems - Beijing China struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
67325f2d433Sxy s32 ret_val;
67425f2d433Sxy u32 idle_errs = 0;
67525f2d433Sxy u16 phy_data, phy_saved_data, speed, duplex, i;
67625f2d433Sxy u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
677*49b78600SRobert Mustacchi u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {
678*49b78600SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_A,
679*49b78600SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_B,
680*49b78600SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_C,
681*49b78600SRobert Mustacchi IGP01E1000_PHY_AGC_PARAM_D};
68225f2d433Sxy
68325f2d433Sxy DEBUGFUNC("e1000_config_dsp_after_link_change_82541");
68425f2d433Sxy
68525f2d433Sxy if (link_up) {
686592a4d85Scc ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
68725f2d433Sxy if (ret_val) {
68825f2d433Sxy DEBUGOUT("Error getting link speed and duplex\n");
68925f2d433Sxy goto out;
69025f2d433Sxy }
69125f2d433Sxy
69225f2d433Sxy if (speed != SPEED_1000) {
69325f2d433Sxy ret_val = E1000_SUCCESS;
69425f2d433Sxy goto out;
69525f2d433Sxy }
69625f2d433Sxy
697592a4d85Scc ret_val = phy->ops.get_cable_length(hw);
69825f2d433Sxy if (ret_val)
69925f2d433Sxy goto out;
70025f2d433Sxy
70125f2d433Sxy if ((dev_spec->dsp_config == e1000_dsp_config_enabled) &&
70225f2d433Sxy phy->min_cable_length >= 50) {
70325f2d433Sxy
70425f2d433Sxy for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
705592a4d85Scc ret_val = phy->ops.read_reg(hw,
706*49b78600SRobert Mustacchi dsp_reg_array[i],
707*49b78600SRobert Mustacchi &phy_data);
70825f2d433Sxy if (ret_val)
70925f2d433Sxy goto out;
71025f2d433Sxy
71125f2d433Sxy phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
71225f2d433Sxy
713592a4d85Scc ret_val = phy->ops.write_reg(hw,
714*49b78600SRobert Mustacchi dsp_reg_array[i],
715*49b78600SRobert Mustacchi phy_data);
71625f2d433Sxy if (ret_val)
71725f2d433Sxy goto out;
71825f2d433Sxy }
71925f2d433Sxy dev_spec->dsp_config = e1000_dsp_config_activated;
72025f2d433Sxy }
72125f2d433Sxy
72225f2d433Sxy if ((dev_spec->ffe_config != e1000_ffe_config_enabled) ||
72325f2d433Sxy (phy->min_cable_length >= 50)) {
72425f2d433Sxy ret_val = E1000_SUCCESS;
72525f2d433Sxy goto out;
72625f2d433Sxy }
72725f2d433Sxy
72825f2d433Sxy /* clear previous idle error counts */
729592a4d85Scc ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
73025f2d433Sxy if (ret_val)
73125f2d433Sxy goto out;
73225f2d433Sxy
73325f2d433Sxy for (i = 0; i < ffe_idle_err_timeout; i++) {
73425f2d433Sxy usec_delay(1000);
735*49b78600SRobert Mustacchi ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS,
736*49b78600SRobert Mustacchi &phy_data);
73725f2d433Sxy if (ret_val)
73825f2d433Sxy goto out;
73925f2d433Sxy
74025f2d433Sxy idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
74125f2d433Sxy if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
74225f2d433Sxy dev_spec->ffe_config = e1000_ffe_config_active;
74325f2d433Sxy
744592a4d85Scc ret_val = phy->ops.write_reg(hw,
745*49b78600SRobert Mustacchi IGP01E1000_PHY_DSP_FFE,
746*49b78600SRobert Mustacchi IGP01E1000_PHY_DSP_FFE_CM_CP);
74725f2d433Sxy if (ret_val)
74825f2d433Sxy goto out;
74925f2d433Sxy break;
75025f2d433Sxy }
75125f2d433Sxy
75225f2d433Sxy if (idle_errs)
75325f2d433Sxy ffe_idle_err_timeout =
754*49b78600SRobert Mustacchi FFE_IDLE_ERR_COUNT_TIMEOUT_100;
75525f2d433Sxy }
75625f2d433Sxy } else {
75725f2d433Sxy if (dev_spec->dsp_config == e1000_dsp_config_activated) {
75825f2d433Sxy /*
75925f2d433Sxy * Save off the current value of register 0x2F5B
76025f2d433Sxy * to be restored at the end of the routines.
76125f2d433Sxy */
762*49b78600SRobert Mustacchi ret_val = phy->ops.read_reg(hw, 0x2F5B,
763*49b78600SRobert Mustacchi &phy_saved_data);
76425f2d433Sxy if (ret_val)
76525f2d433Sxy goto out;
76625f2d433Sxy
76725f2d433Sxy /* Disable the PHY transmitter */
768592a4d85Scc ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
76925f2d433Sxy if (ret_val)
77025f2d433Sxy goto out;
77125f2d433Sxy
77225f2d433Sxy msec_delay_irq(20);
77325f2d433Sxy
774*49b78600SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
775*49b78600SRobert Mustacchi IGP01E1000_IEEE_FORCE_GIG);
77625f2d433Sxy if (ret_val)
77725f2d433Sxy goto out;
77825f2d433Sxy for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
779592a4d85Scc ret_val = phy->ops.read_reg(hw,
780*49b78600SRobert Mustacchi dsp_reg_array[i],
781*49b78600SRobert Mustacchi &phy_data);
78225f2d433Sxy if (ret_val)
78325f2d433Sxy goto out;
78425f2d433Sxy
78525f2d433Sxy phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
78625f2d433Sxy phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
78725f2d433Sxy
788592a4d85Scc ret_val = phy->ops.write_reg(hw,
789*49b78600SRobert Mustacchi dsp_reg_array[i],
790*49b78600SRobert Mustacchi phy_data);
79125f2d433Sxy if (ret_val)
79225f2d433Sxy goto out;
79325f2d433Sxy }
79425f2d433Sxy
795*49b78600SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
796*49b78600SRobert Mustacchi IGP01E1000_IEEE_RESTART_AUTONEG);
79725f2d433Sxy if (ret_val)
79825f2d433Sxy goto out;
79925f2d433Sxy
80025f2d433Sxy msec_delay_irq(20);
80125f2d433Sxy
80225f2d433Sxy /* Now enable the transmitter */
803*49b78600SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x2F5B,
804*49b78600SRobert Mustacchi phy_saved_data);
80525f2d433Sxy if (ret_val)
80625f2d433Sxy goto out;
80725f2d433Sxy
80825f2d433Sxy dev_spec->dsp_config = e1000_dsp_config_enabled;
80925f2d433Sxy }
81025f2d433Sxy
81125f2d433Sxy if (dev_spec->ffe_config != e1000_ffe_config_active) {
81225f2d433Sxy ret_val = E1000_SUCCESS;
81325f2d433Sxy goto out;
81425f2d433Sxy }
81525f2d433Sxy
81625f2d433Sxy /*
81725f2d433Sxy * Save off the current value of register 0x2F5B
81825f2d433Sxy * to be restored at the end of the routines.
81925f2d433Sxy */
820592a4d85Scc ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data);
82125f2d433Sxy if (ret_val)
82225f2d433Sxy goto out;
82325f2d433Sxy
82425f2d433Sxy /* Disable the PHY transmitter */
825592a4d85Scc ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
82625f2d433Sxy if (ret_val)
82725f2d433Sxy goto out;
82825f2d433Sxy
82925f2d433Sxy msec_delay_irq(20);
83025f2d433Sxy
831*49b78600SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
832*49b78600SRobert Mustacchi IGP01E1000_IEEE_FORCE_GIG);
83325f2d433Sxy if (ret_val)
83425f2d433Sxy goto out;
83525f2d433Sxy
836*49b78600SRobert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_DSP_FFE,
837*49b78600SRobert Mustacchi IGP01E1000_PHY_DSP_FFE_DEFAULT);
83825f2d433Sxy if (ret_val)
83925f2d433Sxy goto out;
84025f2d433Sxy
841*49b78600SRobert Mustacchi ret_val = phy->ops.write_reg(hw, 0x0000,
842*49b78600SRobert Mustacchi IGP01E1000_IEEE_RESTART_AUTONEG);
84325f2d433Sxy if (ret_val)
84425f2d433Sxy goto out;
84525f2d433Sxy
84625f2d433Sxy msec_delay_irq(20);
84725f2d433Sxy
84825f2d433Sxy /* Now enable the transmitter */
849592a4d85Scc ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data);
85025f2d433Sxy
85125f2d433Sxy if (ret_val)
85225f2d433Sxy goto out;
85325f2d433Sxy
85425f2d433Sxy dev_spec->ffe_config = e1000_ffe_config_enabled;
85525f2d433Sxy }
85625f2d433Sxy
85725f2d433Sxy out:
85875eba5b6SRobert Mustacchi return ret_val;
85925f2d433Sxy }
86025f2d433Sxy
86175eba5b6SRobert Mustacchi /**
86275eba5b6SRobert Mustacchi * e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY
86375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
86425f2d433Sxy *
86575eba5b6SRobert Mustacchi * The automatic gain control (agc) normalizes the amplitude of the
86675eba5b6SRobert Mustacchi * received signal, adjusting for the attenuation produced by the
86775eba5b6SRobert Mustacchi * cable. By reading the AGC registers, which represent the
86875eba5b6SRobert Mustacchi * combination of coarse and fine gain value, the value can be put
86975eba5b6SRobert Mustacchi * into a lookup table to obtain the approximate cable length
87075eba5b6SRobert Mustacchi * for each channel.
87175eba5b6SRobert Mustacchi **/
e1000_get_cable_length_igp_82541(struct e1000_hw * hw)87275eba5b6SRobert Mustacchi static s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
87325f2d433Sxy {
87425f2d433Sxy struct e1000_phy_info *phy = &hw->phy;
87525f2d433Sxy s32 ret_val = E1000_SUCCESS;
87625f2d433Sxy u16 i, data;
87725f2d433Sxy u16 cur_agc_value, agc_value = 0;
87825f2d433Sxy u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
879*49b78600SRobert Mustacchi u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] = {IGP01E1000_PHY_AGC_A,
880*49b78600SRobert Mustacchi IGP01E1000_PHY_AGC_B,
881*49b78600SRobert Mustacchi IGP01E1000_PHY_AGC_C,
882*49b78600SRobert Mustacchi IGP01E1000_PHY_AGC_D};
88325f2d433Sxy
88425f2d433Sxy DEBUGFUNC("e1000_get_cable_length_igp_82541");
88525f2d433Sxy
88625f2d433Sxy /* Read the AGC registers for all channels */
88725f2d433Sxy for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
888592a4d85Scc ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data);
88925f2d433Sxy if (ret_val)
89025f2d433Sxy goto out;
89125f2d433Sxy
89225f2d433Sxy cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT;
89325f2d433Sxy
89425f2d433Sxy /* Bounds checking */
89525f2d433Sxy if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
89625f2d433Sxy (cur_agc_value == 0)) {
89725f2d433Sxy ret_val = -E1000_ERR_PHY;
89825f2d433Sxy goto out;
89925f2d433Sxy }
90025f2d433Sxy
90125f2d433Sxy agc_value += cur_agc_value;
90225f2d433Sxy
90325f2d433Sxy if (min_agc_value > cur_agc_value)
90425f2d433Sxy min_agc_value = cur_agc_value;
90525f2d433Sxy }
90625f2d433Sxy
90725f2d433Sxy /* Remove the minimal AGC result for length < 50m */
90825f2d433Sxy if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) {
90925f2d433Sxy agc_value -= min_agc_value;
91025f2d433Sxy /* Average the three remaining channels for the length. */
91125f2d433Sxy agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
91225f2d433Sxy } else {
91325f2d433Sxy /* Average the channels for the length. */
91425f2d433Sxy agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
91525f2d433Sxy }
91625f2d433Sxy
91725f2d433Sxy phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] >
918*49b78600SRobert Mustacchi IGP01E1000_AGC_RANGE)
919*49b78600SRobert Mustacchi ? (e1000_igp_cable_length_table[agc_value] -
920*49b78600SRobert Mustacchi IGP01E1000_AGC_RANGE)
921*49b78600SRobert Mustacchi : 0;
92225f2d433Sxy phy->max_cable_length = e1000_igp_cable_length_table[agc_value] +
923*49b78600SRobert Mustacchi IGP01E1000_AGC_RANGE;
92425f2d433Sxy
92525f2d433Sxy phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
92625f2d433Sxy
92725f2d433Sxy out:
92875eba5b6SRobert Mustacchi return ret_val;
92925f2d433Sxy }
93025f2d433Sxy
93175eba5b6SRobert Mustacchi /**
93275eba5b6SRobert Mustacchi * e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3
93375eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
93475eba5b6SRobert Mustacchi * @active: boolean used to enable/disable lplu
93525f2d433Sxy *
93675eba5b6SRobert Mustacchi * Success returns 0, Failure returns 1
93725f2d433Sxy *
93875eba5b6SRobert Mustacchi * The low power link up (lplu) state is set to the power management level D3
93975eba5b6SRobert Mustacchi * and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
94075eba5b6SRobert Mustacchi * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU
94175eba5b6SRobert Mustacchi * is used during Dx states where the power conservation is most important.
94275eba5b6SRobert Mustacchi * During driver activity, SmartSpeed should be enabled so performance is
94375eba5b6SRobert Mustacchi * maintained.
94475eba5b6SRobert Mustacchi **/
e1000_set_d3_lplu_state_82541(struct e1000_hw * hw,bool active)94575eba5b6SRobert Mustacchi static s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active)
94625f2d433Sxy {
94725f2d433Sxy struct e1000_phy_info *phy = &hw->phy;
94825f2d433Sxy s32 ret_val;
94925f2d433Sxy u16 data;
95025f2d433Sxy
95125f2d433Sxy DEBUGFUNC("e1000_set_d3_lplu_state_82541");
95225f2d433Sxy
95325f2d433Sxy switch (hw->mac.type) {
95425f2d433Sxy case e1000_82541_rev_2:
95525f2d433Sxy case e1000_82547_rev_2:
95625f2d433Sxy break;
95725f2d433Sxy default:
95825f2d433Sxy ret_val = e1000_set_d3_lplu_state_generic(hw, active);
95925f2d433Sxy goto out;
96075eba5b6SRobert Mustacchi break;
96125f2d433Sxy }
96225f2d433Sxy
963592a4d85Scc ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data);
96425f2d433Sxy if (ret_val)
96525f2d433Sxy goto out;
96625f2d433Sxy
96725f2d433Sxy if (!active) {
96825f2d433Sxy data &= ~IGP01E1000_GMII_FLEX_SPD;
969592a4d85Scc ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
97025f2d433Sxy if (ret_val)
97125f2d433Sxy goto out;
97225f2d433Sxy
97325f2d433Sxy /*
97425f2d433Sxy * LPLU and SmartSpeed are mutually exclusive. LPLU is used
97525f2d433Sxy * during Dx states where the power conservation is most
97625f2d433Sxy * important. During driver activity we should enable
97725f2d433Sxy * SmartSpeed, so performance is maintained.
97825f2d433Sxy */
97925f2d433Sxy if (phy->smart_speed == e1000_smart_speed_on) {
980592a4d85Scc ret_val = phy->ops.read_reg(hw,
981*49b78600SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
982*49b78600SRobert Mustacchi &data);
98325f2d433Sxy if (ret_val)
98425f2d433Sxy goto out;
98525f2d433Sxy
98625f2d433Sxy data |= IGP01E1000_PSCFR_SMART_SPEED;
987592a4d85Scc ret_val = phy->ops.write_reg(hw,
988*49b78600SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
989*49b78600SRobert Mustacchi data);
99025f2d433Sxy if (ret_val)
99125f2d433Sxy goto out;
99225f2d433Sxy } else if (phy->smart_speed == e1000_smart_speed_off) {
993592a4d85Scc ret_val = phy->ops.read_reg(hw,
994*49b78600SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
995*49b78600SRobert Mustacchi &data);
99625f2d433Sxy if (ret_val)
99725f2d433Sxy goto out;
99825f2d433Sxy
99925f2d433Sxy data &= ~IGP01E1000_PSCFR_SMART_SPEED;
1000592a4d85Scc ret_val = phy->ops.write_reg(hw,
1001*49b78600SRobert Mustacchi IGP01E1000_PHY_PORT_CONFIG,
1002*49b78600SRobert Mustacchi data);
100325f2d433Sxy if (ret_val)
100425f2d433Sxy goto out;
100525f2d433Sxy }
100625f2d433Sxy } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
1007*49b78600SRobert Mustacchi (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
1008*49b78600SRobert Mustacchi (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
100925f2d433Sxy data |= IGP01E1000_GMII_FLEX_SPD;
1010592a4d85Scc ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
101125f2d433Sxy if (ret_val)
101225f2d433Sxy goto out;
101325f2d433Sxy
101425f2d433Sxy /* When LPLU is enabled, we should disable SmartSpeed */
1015*49b78600SRobert Mustacchi ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
1016*49b78600SRobert Mustacchi &data);
101725f2d433Sxy if (ret_val)
101825f2d433Sxy goto out;
101925f2d433Sxy
102025f2d433Sxy data &= ~IGP01E1000_PSCFR_SMART_SPEED;
1021*49b78600SRobert Mustacchi ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
1022*49b78600SRobert Mustacchi data);
102325f2d433Sxy }
102425f2d433Sxy
102525f2d433Sxy out:
102675eba5b6SRobert Mustacchi return ret_val;
102725f2d433Sxy }
102825f2d433Sxy
102975eba5b6SRobert Mustacchi /**
103075eba5b6SRobert Mustacchi * e1000_setup_led_82541 - Configures SW controllable LED
103175eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
103225f2d433Sxy *
103375eba5b6SRobert Mustacchi * This prepares the SW controllable LED for use and saves the current state
103475eba5b6SRobert Mustacchi * of the LED so it can be later restored.
103575eba5b6SRobert Mustacchi **/
e1000_setup_led_82541(struct e1000_hw * hw)103675eba5b6SRobert Mustacchi static s32 e1000_setup_led_82541(struct e1000_hw *hw)
103725f2d433Sxy {
1038d5c3073dSchenlu chen - Sun Microsystems - Beijing China struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
103925f2d433Sxy s32 ret_val;
104025f2d433Sxy
104125f2d433Sxy DEBUGFUNC("e1000_setup_led_82541");
104225f2d433Sxy
1043*49b78600SRobert Mustacchi ret_val = hw->phy.ops.read_reg(hw, IGP01E1000_GMII_FIFO,
1044*49b78600SRobert Mustacchi &dev_spec->spd_default);
104525f2d433Sxy if (ret_val)
104625f2d433Sxy goto out;
104725f2d433Sxy
1048*49b78600SRobert Mustacchi ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
1049*49b78600SRobert Mustacchi (u16)(dev_spec->spd_default &
1050*49b78600SRobert Mustacchi ~IGP01E1000_GMII_SPD));
105125f2d433Sxy if (ret_val)
105225f2d433Sxy goto out;
105325f2d433Sxy
105425f2d433Sxy E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
105525f2d433Sxy
105625f2d433Sxy out:
105775eba5b6SRobert Mustacchi return ret_val;
105825f2d433Sxy }
105925f2d433Sxy
106075eba5b6SRobert Mustacchi /**
106175eba5b6SRobert Mustacchi * e1000_cleanup_led_82541 - Set LED config to default operation
106275eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
106325f2d433Sxy *
106475eba5b6SRobert Mustacchi * Remove the current LED configuration and set the LED configuration
106575eba5b6SRobert Mustacchi * to the default value, saved from the EEPROM.
106675eba5b6SRobert Mustacchi **/
e1000_cleanup_led_82541(struct e1000_hw * hw)106775eba5b6SRobert Mustacchi static s32 e1000_cleanup_led_82541(struct e1000_hw *hw)
106825f2d433Sxy {
1069d5c3073dSchenlu chen - Sun Microsystems - Beijing China struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
107025f2d433Sxy s32 ret_val;
107125f2d433Sxy
107225f2d433Sxy DEBUGFUNC("e1000_cleanup_led_82541");
107325f2d433Sxy
1074*49b78600SRobert Mustacchi ret_val = hw->phy.ops.write_reg(hw, IGP01E1000_GMII_FIFO,
1075*49b78600SRobert Mustacchi dev_spec->spd_default);
107625f2d433Sxy if (ret_val)
107725f2d433Sxy goto out;
107825f2d433Sxy
107925f2d433Sxy E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
108025f2d433Sxy
108125f2d433Sxy out:
108275eba5b6SRobert Mustacchi return ret_val;
108325f2d433Sxy }
108425f2d433Sxy
108575eba5b6SRobert Mustacchi /**
108675eba5b6SRobert Mustacchi * e1000_phy_init_script_82541 - Initialize GbE PHY
108775eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
108825f2d433Sxy *
108975eba5b6SRobert Mustacchi * Initializes the IGP PHY.
109075eba5b6SRobert Mustacchi **/
e1000_phy_init_script_82541(struct e1000_hw * hw)109175eba5b6SRobert Mustacchi static s32 e1000_phy_init_script_82541(struct e1000_hw *hw)
109225f2d433Sxy {
1093d5c3073dSchenlu chen - Sun Microsystems - Beijing China struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
109425f2d433Sxy u32 ret_val;
109525f2d433Sxy u16 phy_saved_data;
109625f2d433Sxy
109725f2d433Sxy DEBUGFUNC("e1000_phy_init_script_82541");
109825f2d433Sxy
109925f2d433Sxy if (!dev_spec->phy_init_script) {
110025f2d433Sxy ret_val = E1000_SUCCESS;
110125f2d433Sxy goto out;
110225f2d433Sxy }
110325f2d433Sxy
110425f2d433Sxy /* Delay after phy reset to enable NVM configuration to load */
110525f2d433Sxy msec_delay(20);
110625f2d433Sxy
110725f2d433Sxy /*
110825f2d433Sxy * Save off the current value of register 0x2F5B to be restored at
110925f2d433Sxy * the end of this routine.
111025f2d433Sxy */
1111592a4d85Scc ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data);
111225f2d433Sxy
111325f2d433Sxy /* Disabled the PHY transmitter */
1114592a4d85Scc hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003);
111525f2d433Sxy
111625f2d433Sxy msec_delay(20);
111725f2d433Sxy
1118592a4d85Scc hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
111925f2d433Sxy
112025f2d433Sxy msec_delay(5);
112125f2d433Sxy
112225f2d433Sxy switch (hw->mac.type) {
112325f2d433Sxy case e1000_82541:
112425f2d433Sxy case e1000_82547:
1125592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F95, 0x0001);
112625f2d433Sxy
1127592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21);
112825f2d433Sxy
1129592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F79, 0x0018);
113025f2d433Sxy
1131592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F30, 0x1600);
113225f2d433Sxy
1133592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F31, 0x0014);
113425f2d433Sxy
1135592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F32, 0x161C);
113625f2d433Sxy
1137592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F94, 0x0003);
113825f2d433Sxy
1139592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F96, 0x003F);
114025f2d433Sxy
1141592a4d85Scc hw->phy.ops.write_reg(hw, 0x2010, 0x0008);
114225f2d433Sxy break;
114325f2d433Sxy case e1000_82541_rev_2:
114425f2d433Sxy case e1000_82547_rev_2:
1145592a4d85Scc hw->phy.ops.write_reg(hw, 0x1F73, 0x0099);
114625f2d433Sxy break;
114725f2d433Sxy default:
114825f2d433Sxy break;
114925f2d433Sxy }
115025f2d433Sxy
1151592a4d85Scc hw->phy.ops.write_reg(hw, 0x0000, 0x3300);
115225f2d433Sxy
115325f2d433Sxy msec_delay(20);
115425f2d433Sxy
115525f2d433Sxy /* Now enable the transmitter */
1156592a4d85Scc hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data);
115725f2d433Sxy
115825f2d433Sxy if (hw->mac.type == e1000_82547) {
115925f2d433Sxy u16 fused, fine, coarse;
116025f2d433Sxy
116125f2d433Sxy /* Move to analog registers page */
1162*49b78600SRobert Mustacchi hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
1163*49b78600SRobert Mustacchi &fused);
116425f2d433Sxy
116525f2d433Sxy if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
1166*49b78600SRobert Mustacchi hw->phy.ops.read_reg(hw, IGP01E1000_ANALOG_FUSE_STATUS,
1167*49b78600SRobert Mustacchi &fused);
116825f2d433Sxy
116925f2d433Sxy fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
117025f2d433Sxy coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
117125f2d433Sxy
117225f2d433Sxy if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
117325f2d433Sxy coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
117425f2d433Sxy fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
117525f2d433Sxy } else if (coarse ==
1176*49b78600SRobert Mustacchi IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
117725f2d433Sxy fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
117825f2d433Sxy
117925f2d433Sxy fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
1180*49b78600SRobert Mustacchi (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
1181*49b78600SRobert Mustacchi (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
118225f2d433Sxy
1183592a4d85Scc hw->phy.ops.write_reg(hw,
1184*49b78600SRobert Mustacchi IGP01E1000_ANALOG_FUSE_CONTROL,
1185*49b78600SRobert Mustacchi fused);
1186592a4d85Scc hw->phy.ops.write_reg(hw,
1187*49b78600SRobert Mustacchi IGP01E1000_ANALOG_FUSE_BYPASS,
1188*49b78600SRobert Mustacchi IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
118925f2d433Sxy }
119025f2d433Sxy }
119125f2d433Sxy
119225f2d433Sxy out:
119375eba5b6SRobert Mustacchi return ret_val;
119425f2d433Sxy }
119525f2d433Sxy
119675eba5b6SRobert Mustacchi /**
119775eba5b6SRobert Mustacchi * e1000_init_script_state_82541 - Enable/Disable PHY init script
119875eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
119975eba5b6SRobert Mustacchi * @state: boolean value used to enable/disable PHY init script
120025f2d433Sxy *
120175eba5b6SRobert Mustacchi * Allows the driver to enable/disable the PHY init script, if the PHY is an
120275eba5b6SRobert Mustacchi * IGP PHY.
120375eba5b6SRobert Mustacchi **/
e1000_init_script_state_82541(struct e1000_hw * hw,bool state)120475eba5b6SRobert Mustacchi void e1000_init_script_state_82541(struct e1000_hw *hw, bool state)
120525f2d433Sxy {
1206d5c3073dSchenlu chen - Sun Microsystems - Beijing China struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
120725f2d433Sxy
120825f2d433Sxy DEBUGFUNC("e1000_init_script_state_82541");
120925f2d433Sxy
121025f2d433Sxy if (hw->phy.type != e1000_phy_igp) {
121125f2d433Sxy DEBUGOUT("Initialization script not necessary.\n");
121225f2d433Sxy goto out;
121325f2d433Sxy }
121425f2d433Sxy
121575eba5b6SRobert Mustacchi dev_spec->phy_init_script = state;
121625f2d433Sxy
121725f2d433Sxy out:
121875eba5b6SRobert Mustacchi return;
121925f2d433Sxy }
122025f2d433Sxy
122175eba5b6SRobert Mustacchi /**
122275eba5b6SRobert Mustacchi * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down
122325f2d433Sxy * @hw: pointer to the HW structure
122425f2d433Sxy *
122575eba5b6SRobert Mustacchi * In the case of a PHY power down to save power, or to turn off link during a
122675eba5b6SRobert Mustacchi * driver unload, or wake on lan is not enabled, remove the link.
122775eba5b6SRobert Mustacchi **/
e1000_power_down_phy_copper_82541(struct e1000_hw * hw)122875eba5b6SRobert Mustacchi static void e1000_power_down_phy_copper_82541(struct e1000_hw *hw)
122925f2d433Sxy {
123075eba5b6SRobert Mustacchi /* If the management interface is not enabled, then power down */
123175eba5b6SRobert Mustacchi if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
123275eba5b6SRobert Mustacchi e1000_power_down_phy_copper(hw);
123325f2d433Sxy
123475eba5b6SRobert Mustacchi return;
123525f2d433Sxy }
123625f2d433Sxy
123775eba5b6SRobert Mustacchi /**
123875eba5b6SRobert Mustacchi * e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters
123975eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
124025f2d433Sxy *
124175eba5b6SRobert Mustacchi * Clears the hardware counters by reading the counter registers.
124275eba5b6SRobert Mustacchi **/
e1000_clear_hw_cntrs_82541(struct e1000_hw * hw)124375eba5b6SRobert Mustacchi static void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw)
124425f2d433Sxy {
124575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_clear_hw_cntrs_82541");
124625f2d433Sxy
124775eba5b6SRobert Mustacchi e1000_clear_hw_cntrs_base_generic(hw);
124825f2d433Sxy
124975eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC64);
125075eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC127);
125175eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC255);
125275eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC511);
125375eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC1023);
125475eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PRC1522);
125575eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC64);
125675eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC127);
125775eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC255);
125875eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC511);
125975eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC1023);
126075eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_PTC1522);
126175eba5b6SRobert Mustacchi
126275eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_ALGNERRC);
126375eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_RXERRC);
126475eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_TNCRS);
126575eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_CEXTERR);
126675eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_TSCTC);
126775eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_TSCTFC);
126875eba5b6SRobert Mustacchi
126975eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_MGTPRC);
127075eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_MGTPDC);
127175eba5b6SRobert Mustacchi E1000_READ_REG(hw, E1000_MGTPTC);
127225f2d433Sxy }
127325f2d433Sxy
127475eba5b6SRobert Mustacchi /**
127575eba5b6SRobert Mustacchi * e1000_read_mac_addr_82541 - Read device MAC address
127675eba5b6SRobert Mustacchi * @hw: pointer to the HW structure
127725f2d433Sxy *
127875eba5b6SRobert Mustacchi * Reads the device MAC address from the EEPROM and stores the value.
127975eba5b6SRobert Mustacchi **/
e1000_read_mac_addr_82541(struct e1000_hw * hw)128075eba5b6SRobert Mustacchi static s32 e1000_read_mac_addr_82541(struct e1000_hw *hw)
128125f2d433Sxy {
128275eba5b6SRobert Mustacchi s32 ret_val = E1000_SUCCESS;
128375eba5b6SRobert Mustacchi u16 offset, nvm_data, i;
128425f2d433Sxy
128575eba5b6SRobert Mustacchi DEBUGFUNC("e1000_read_mac_addr");
128625f2d433Sxy
128775eba5b6SRobert Mustacchi for (i = 0; i < ETH_ADDR_LEN; i += 2) {
128875eba5b6SRobert Mustacchi offset = i >> 1;
128975eba5b6SRobert Mustacchi ret_val = hw->nvm.ops.read(hw, offset, 1, &nvm_data);
129075eba5b6SRobert Mustacchi if (ret_val) {
129175eba5b6SRobert Mustacchi DEBUGOUT("NVM Read Error\n");
129225f2d433Sxy goto out;
129325f2d433Sxy }
129475eba5b6SRobert Mustacchi hw->mac.perm_addr[i] = (u8)(nvm_data & 0xFF);
129575eba5b6SRobert Mustacchi hw->mac.perm_addr[i+1] = (u8)(nvm_data >> 8);
129625f2d433Sxy }
129725f2d433Sxy
129875eba5b6SRobert Mustacchi for (i = 0; i < ETH_ADDR_LEN; i++)
129975eba5b6SRobert Mustacchi hw->mac.addr[i] = hw->mac.perm_addr[i];
130025f2d433Sxy
130125f2d433Sxy out:
130275eba5b6SRobert Mustacchi return ret_val;
1303592a4d85Scc }
1304592a4d85Scc
1305