e1000_82541.c revision 190872
161822Sgreen/******************************************************************************
255992Swpaul
355992Swpaul  Copyright (c) 2001-2009, Intel Corporation
455992Swpaul  All rights reserved.
555992Swpaul
655992Swpaul  Redistribution and use in source and binary forms, with or without
755992Swpaul  modification, are permitted provided that the following conditions are met:
855992Swpaul
955992Swpaul   1. Redistributions of source code must retain the above copyright notice,
1055992Swpaul      this list of conditions and the following disclaimer.
1155992Swpaul
1255992Swpaul   2. Redistributions in binary form must reproduce the above copyright
1355992Swpaul      notice, this list of conditions and the following disclaimer in the
1455992Swpaul      documentation and/or other materials provided with the distribution.
1555992Swpaul
1655992Swpaul   3. Neither the name of the Intel Corporation nor the names of its
1755992Swpaul      contributors may be used to endorse or promote products derived from
1855992Swpaul      this software without specific prior written permission.
1955992Swpaul
2055992Swpaul  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2155992Swpaul  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2255992Swpaul  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2355992Swpaul  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2455992Swpaul  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2555992Swpaul  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2655992Swpaul  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2755992Swpaul  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2855992Swpaul  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2955992Swpaul  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3055992Swpaul  POSSIBILITY OF SUCH DAMAGE.
3155992Swpaul
3255992Swpaul******************************************************************************/
33114601Sobrien/*$FreeBSD: head/sys/dev/e1000/e1000_82541.c 190872 2009-04-10 00:05:46Z jfv $*/
3481586Sru
3581586Sru/*
3681586Sru * 82541EI Gigabit Ethernet Controller
3781586Sru * 82541ER Gigabit Ethernet Controller
38114601Sobrien * 82541GI Gigabit Ethernet Controller
39114601Sobrien * 82541PI Gigabit Ethernet Controller
40114601Sobrien * 82547EI Gigabit Ethernet Controller
4181586Sru * 82547GI Gigabit Ethernet Controller
4255992Swpaul */
4355992Swpaul
4455992Swpaul#include "e1000_api.h"
4555992Swpaul
4690868Smikestatic s32  e1000_init_phy_params_82541(struct e1000_hw *hw);
4790868Smikestatic s32  e1000_init_nvm_params_82541(struct e1000_hw *hw);
4855992Swpaulstatic s32  e1000_init_mac_params_82541(struct e1000_hw *hw);
4955992Swpaulstatic s32  e1000_reset_hw_82541(struct e1000_hw *hw);
5055992Swpaulstatic s32  e1000_init_hw_82541(struct e1000_hw *hw);
5155992Swpaulstatic s32  e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
5255992Swpaul                                         u16 *duplex);
5355992Swpaulstatic s32  e1000_phy_hw_reset_82541(struct e1000_hw *hw);
5455992Swpaulstatic s32  e1000_setup_copper_link_82541(struct e1000_hw *hw);
5555992Swpaulstatic s32  e1000_check_for_link_82541(struct e1000_hw *hw);
5655992Swpaulstatic s32  e1000_get_cable_length_igp_82541(struct e1000_hw *hw);
5755992Swpaulstatic s32  e1000_set_d3_lplu_state_82541(struct e1000_hw *hw,
5855992Swpaul                                          bool active);
5955992Swpaulstatic s32  e1000_setup_led_82541(struct e1000_hw *hw);
6088748Sambriskostatic s32  e1000_cleanup_led_82541(struct e1000_hw *hw);
61108401Sambriskostatic void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw);
6255992Swpaulstatic s32  e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
63108401Sambrisko                                                     bool link_up);
6499800Salfredstatic s32  e1000_phy_init_script_82541(struct e1000_hw *hw);
65132860Snjlstatic void e1000_power_down_phy_copper_82541(struct e1000_hw *hw);
66132860Snjl
6799800Salfredstatic const u16 e1000_igp_cable_length_table[] =
68132860Snjl    { 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5,
6999800Salfred      5, 10, 10, 10, 10, 10, 10, 10, 20, 20, 20, 20, 20, 25, 25, 25,
7099800Salfred      25, 25, 25, 25, 30, 30, 30, 30, 40, 40, 40, 40, 40, 40, 40, 40,
7199800Salfred      40, 50, 50, 50, 50, 50, 50, 50, 60, 60, 60, 60, 60, 60, 60, 60,
7299800Salfred      60, 70, 70, 70, 70, 70, 70, 80, 80, 80, 80, 80, 80, 90, 90, 90,
7399800Salfred      90, 90, 90, 90, 90, 90, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100,
7499800Salfred      100, 100, 100, 100, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
7599800Salfred      110, 110, 110, 110, 110, 110, 120, 120, 120, 120, 120, 120, 120, 120, 120, 120};
7699800Salfred#define IGP01E1000_AGC_LENGTH_TABLE_SIZE \
7799800Salfred                (sizeof(e1000_igp_cable_length_table) / \
7899800Salfred                 sizeof(e1000_igp_cable_length_table[0]))
7999800Salfred
8099800Salfred/**
8155992Swpaul *  e1000_init_phy_params_82541 - Init PHY func ptrs.
8299800Salfred *  @hw: pointer to the HW structure
8399800Salfred **/
8455992Swpaulstatic s32 e1000_init_phy_params_82541(struct e1000_hw *hw)
8599800Salfred{
86132860Snjl	struct e1000_phy_info *phy = &hw->phy;
87132860Snjl	s32 ret_val = E1000_SUCCESS;
88132860Snjl
89132860Snjl	DEBUGFUNC("e1000_init_phy_params_82541");
90108401Sambrisko
91132860Snjl	phy->addr                      = 1;
9255992Swpaul	phy->autoneg_mask              = AUTONEG_ADVERTISE_SPEED_DEFAULT;
9355992Swpaul	phy->reset_delay_us            = 10000;
9455992Swpaul	phy->type                      = e1000_phy_igp;
9555992Swpaul
9655992Swpaul	/* Function Pointers */
9755992Swpaul	phy->ops.check_polarity        = e1000_check_polarity_igp;
9855992Swpaul	phy->ops.force_speed_duplex    = e1000_phy_force_speed_duplex_igp;
9955992Swpaul	phy->ops.get_cable_length      = e1000_get_cable_length_igp_82541;
10055992Swpaul	phy->ops.get_cfg_done          = e1000_get_cfg_done_generic;
101119156Sambrisko	phy->ops.get_info              = e1000_get_phy_info_igp;
10255992Swpaul	phy->ops.read_reg              = e1000_read_phy_reg_igp;
10355992Swpaul	phy->ops.reset                 = e1000_phy_hw_reset_82541;
10455992Swpaul	phy->ops.set_d3_lplu_state     = e1000_set_d3_lplu_state_82541;
10555992Swpaul	phy->ops.write_reg             = e1000_write_phy_reg_igp;
10655992Swpaul	phy->ops.power_up              = e1000_power_up_phy_copper;
10755992Swpaul	phy->ops.power_down            = e1000_power_down_phy_copper_82541;
10855992Swpaul
10955992Swpaul	ret_val = e1000_get_phy_id(hw);
11055992Swpaul	if (ret_val)
11155992Swpaul		goto out;
11255992Swpaul
11355992Swpaul	/* Verify phy id */
11455992Swpaul	if (phy->id != IGP01E1000_I_PHY_ID) {
11555992Swpaul		ret_val = -E1000_ERR_PHY;
11655992Swpaul		goto out;
11755992Swpaul	}
11855992Swpaul
11955992Swpaulout:
12055992Swpaul	return ret_val;
12155992Swpaul}
12255992Swpaul
12355992Swpaul/**
12455992Swpaul *  e1000_init_nvm_params_82541 - Init NVM func ptrs.
12555992Swpaul *  @hw: pointer to the HW structure
12668692Swpaul **/
12768692Swpaulstatic s32 e1000_init_nvm_params_82541(struct e1000_hw *hw)
12868692Swpaul{
12969772Sarchie	struct   e1000_nvm_info *nvm = &hw->nvm;
13083269Sbrooks	s32  ret_val = E1000_SUCCESS;
13188748Sambrisko	u32 eecd = E1000_READ_REG(hw, E1000_EECD);
13268692Swpaul	u16 size;
133108401Sambrisko
134108401Sambrisko	DEBUGFUNC("e1000_init_nvm_params_82541");
135132860Snjl
136132860Snjl	switch (nvm->override) {
13755992Swpaul	case e1000_nvm_override_spi_large:
13855992Swpaul		nvm->type = e1000_nvm_eeprom_spi;
139108401Sambrisko		eecd |= E1000_EECD_ADDR_BITS;
14055992Swpaul		break;
141132900Snjl	case e1000_nvm_override_spi_small:
14255992Swpaul		nvm->type = e1000_nvm_eeprom_spi;
14361815Sroberto		eecd &= ~E1000_EECD_ADDR_BITS;
14455992Swpaul		break;
14555992Swpaul	case e1000_nvm_override_microwire_large:
14655992Swpaul		nvm->type = e1000_nvm_eeprom_microwire;
14755992Swpaul		eecd |= E1000_EECD_SIZE;
14855992Swpaul		break;
14955992Swpaul	case e1000_nvm_override_microwire_small:
15055992Swpaul		nvm->type = e1000_nvm_eeprom_microwire;
151108401Sambrisko		eecd &= ~E1000_EECD_SIZE;
152108401Sambrisko		break;
15355992Swpaul	default:
154108401Sambrisko		nvm->type = eecd & E1000_EECD_TYPE
15555992Swpaul		            ? e1000_nvm_eeprom_spi
15655992Swpaul		            : e1000_nvm_eeprom_microwire;
15755992Swpaul		break;
158132860Snjl	}
15955992Swpaul
16055992Swpaul	if (nvm->type == e1000_nvm_eeprom_spi) {
161132860Snjl		nvm->address_bits       = (eecd & E1000_EECD_ADDR_BITS)
162132860Snjl		                          ? 16 : 8;
16355992Swpaul		nvm->delay_usec         = 1;
16455992Swpaul		nvm->opcode_bits        = 8;
16555992Swpaul		nvm->page_size          = (eecd & E1000_EECD_ADDR_BITS)
16655992Swpaul		                          ? 32 : 8;
167132900Snjl
16855992Swpaul		/* Function Pointers */
16961815Sroberto		nvm->ops.acquire        = e1000_acquire_nvm_generic;
17055992Swpaul		nvm->ops.read           = e1000_read_nvm_spi;
17155992Swpaul		nvm->ops.release        = e1000_release_nvm_generic;
17255992Swpaul		nvm->ops.update         = e1000_update_nvm_checksum_generic;
17355992Swpaul		nvm->ops.valid_led_default = e1000_valid_led_default_generic;
17455992Swpaul		nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
17555992Swpaul		nvm->ops.write          = e1000_write_nvm_spi;
17655992Swpaul
17755992Swpaul		/*
17855992Swpaul		 * nvm->word_size must be discovered after the pointers
17955992Swpaul		 * are set so we can verify the size from the nvm image
18055992Swpaul		 * itself.  Temporarily set it to a dummy value so the
18155992Swpaul		 * read will work.
18255992Swpaul		 */
18355992Swpaul		nvm->word_size = 64;
18455992Swpaul		ret_val = nvm->ops.read(hw, NVM_CFG, 1, &size);
185132860Snjl		if (ret_val)
186132860Snjl			goto out;
18755992Swpaul		size = (size & NVM_SIZE_MASK) >> NVM_SIZE_SHIFT;
18855992Swpaul		/*
18955992Swpaul		 * if size != 0, it can be added to a constant and become
19055992Swpaul		 * the left-shift value to set the word_size.  Otherwise,
19155992Swpaul		 * word_size stays at 64.
19255992Swpaul		 */
19355992Swpaul		if (size) {
19455992Swpaul			size += NVM_WORD_SIZE_BASE_SHIFT_82541;
19555992Swpaul			nvm->word_size = 1 << size;
19655992Swpaul		}
19755992Swpaul	} else {
198132860Snjl		nvm->address_bits       = (eecd & E1000_EECD_ADDR_BITS)
199132860Snjl		                          ? 8 : 6;
20055992Swpaul		nvm->delay_usec         = 50;
20155992Swpaul		nvm->opcode_bits        = 3;
20255992Swpaul		nvm->word_size          = (eecd & E1000_EECD_ADDR_BITS)
20355992Swpaul		                          ? 256 : 64;
20455992Swpaul
205132860Snjl		/* Function Pointers */
20655992Swpaul		nvm->ops.acquire        = e1000_acquire_nvm_generic;
20755992Swpaul		nvm->ops.read           = e1000_read_nvm_microwire;
20855992Swpaul		nvm->ops.release        = e1000_release_nvm_generic;
209132860Snjl		nvm->ops.update         = e1000_update_nvm_checksum_generic;
210132860Snjl		nvm->ops.valid_led_default = e1000_valid_led_default_generic;
21155992Swpaul		nvm->ops.validate       = e1000_validate_nvm_checksum_generic;
21255992Swpaul		nvm->ops.write          = e1000_write_nvm_microwire;
21355992Swpaul	}
21455992Swpaul
21555992Swpaulout:
21655992Swpaul	return ret_val;
21755992Swpaul}
21855992Swpaul
21955992Swpaul/**
220132860Snjl *  e1000_init_mac_params_82541 - Init MAC func ptrs.
221132860Snjl *  @hw: pointer to the HW structure
22255992Swpaul **/
22355992Swpaulstatic s32 e1000_init_mac_params_82541(struct e1000_hw *hw)
22455992Swpaul{
22555992Swpaul	struct e1000_mac_info *mac = &hw->mac;
22655992Swpaul
22755992Swpaul	DEBUGFUNC("e1000_init_mac_params_82541");
22855992Swpaul
229132860Snjl	/* Set media type */
230132860Snjl	hw->phy.media_type = e1000_media_type_copper;
23155992Swpaul	/* Set mta register count */
23255992Swpaul	mac->mta_reg_count = 128;
23355992Swpaul	/* Set rar entry count */
23455992Swpaul	mac->rar_entry_count = E1000_RAR_ENTRIES;
23555992Swpaul	/* Set if part includes ASF firmware */
23655992Swpaul	mac->asf_firmware_present = TRUE;
23755992Swpaul
23855992Swpaul	/* Function Pointers */
23955992Swpaul
24055992Swpaul	/* bus type/speed/width */
24155992Swpaul	mac->ops.get_bus_info = e1000_get_bus_info_pci_generic;
24255992Swpaul	/* function id */
24355992Swpaul	mac->ops.set_lan_id = e1000_set_lan_id_single_port;
24468692Swpaul	/* reset */
24568692Swpaul	mac->ops.reset_hw = e1000_reset_hw_82541;
246132860Snjl	/* hw initialization */
247132860Snjl	mac->ops.init_hw = e1000_init_hw_82541;
24855992Swpaul	/* link setup */
24955992Swpaul	mac->ops.setup_link = e1000_setup_link_generic;
25055992Swpaul	/* physical interface link setup */
251108401Sambrisko	mac->ops.setup_physical_interface = e1000_setup_copper_link_82541;
252108401Sambrisko	/* check for link */
25355992Swpaul	mac->ops.check_for_link = e1000_check_for_link_82541;
254108401Sambrisko	/* link info */
255108401Sambrisko	mac->ops.get_link_up_info = e1000_get_link_up_info_82541;
256108401Sambrisko	/* multicast address update */
257108401Sambrisko	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
258108401Sambrisko	/* writing VFTA */
259108401Sambrisko	mac->ops.write_vfta = e1000_write_vfta_generic;
260108401Sambrisko	/* clearing VFTA */
261108401Sambrisko	mac->ops.clear_vfta = e1000_clear_vfta_generic;
262108401Sambrisko	/* setting MTA */
263108401Sambrisko	mac->ops.mta_set = e1000_mta_set_generic;
264108401Sambrisko	/* ID LED init */
265108401Sambrisko	mac->ops.id_led_init = e1000_id_led_init_generic;
266108401Sambrisko	/* setup LED */
26755992Swpaul	mac->ops.setup_led = e1000_setup_led_82541;
26855992Swpaul	/* cleanup LED */
26955992Swpaul	mac->ops.cleanup_led = e1000_cleanup_led_82541;
27055992Swpaul	/* turn on/off LED */
27155992Swpaul	mac->ops.led_on = e1000_led_on_generic;
27255992Swpaul	mac->ops.led_off = e1000_led_off_generic;
27355992Swpaul	/* clear hardware counters */
27455992Swpaul	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_82541;
27555992Swpaul
27655992Swpaul	return E1000_SUCCESS;
27755992Swpaul}
27855992Swpaul
27955992Swpaul/**
28055992Swpaul *  e1000_init_function_pointers_82541 - Init func ptrs.
28155992Swpaul *  @hw: pointer to the HW structure
28255992Swpaul *
28355992Swpaul *  Called to initialize all function pointers and parameters.
28455992Swpaul **/
28555992Swpaulvoid e1000_init_function_pointers_82541(struct e1000_hw *hw)
28655992Swpaul{
28788748Sambrisko	DEBUGFUNC("e1000_init_function_pointers_82541");
28888748Sambrisko
28955992Swpaul	hw->mac.ops.init_params = e1000_init_mac_params_82541;
29055992Swpaul	hw->nvm.ops.init_params = e1000_init_nvm_params_82541;
29155992Swpaul	hw->phy.ops.init_params = e1000_init_phy_params_82541;
29255992Swpaul}
29355992Swpaul
294108401Sambrisko/**
295132860Snjl *  e1000_reset_hw_82541 - Reset hardware
296108401Sambrisko *  @hw: pointer to the HW structure
297108401Sambrisko *
298108401Sambrisko *  This resets the hardware into a known state.
299132860Snjl **/
300108401Sambriskostatic s32 e1000_reset_hw_82541(struct e1000_hw *hw)
301132860Snjl{
302108401Sambrisko	u32 ledctl, ctrl, icr, manc;
303132860Snjl
304108401Sambrisko	DEBUGFUNC("e1000_reset_hw_82541");
305108401Sambrisko
306108401Sambrisko	DEBUGOUT("Masking off all interrupts\n");
307132860Snjl	E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
308108401Sambrisko
309132860Snjl	E1000_WRITE_REG(hw, E1000_RCTL, 0);
31078788Sbrooks	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
31178788Sbrooks	E1000_WRITE_FLUSH(hw);
31278788Sbrooks
31378788Sbrooks	/*
31478788Sbrooks	 * Delay to allow any outstanding PCI transactions to complete
31578788Sbrooks	 * before resetting the device.
31678788Sbrooks	 */
31778788Sbrooks	msec_delay(10);
31878788Sbrooks
319132860Snjl	ctrl = E1000_READ_REG(hw, E1000_CTRL);
32078788Sbrooks
32155992Swpaul	/* Must reset the Phy before resetting the MAC */
32255992Swpaul	if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
32355992Swpaul		E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_PHY_RST));
32455992Swpaul		msec_delay(5);
32555992Swpaul	}
32655992Swpaul
32755992Swpaul	DEBUGOUT("Issuing a global reset to 82541/82547 MAC\n");
32855992Swpaul	switch (hw->mac.type) {
32955992Swpaul	case e1000_82541:
33055992Swpaul	case e1000_82541_rev_2:
33155992Swpaul		/*
33255992Swpaul		 * These controllers can't ack the 64-bit write when
33355992Swpaul		 * issuing the reset, so we use IO-mapping as a
33455992Swpaul		 * workaround to issue the reset.
33555992Swpaul		 */
33655992Swpaul		E1000_WRITE_REG_IO(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
33755992Swpaul		break;
33855992Swpaul	default:
33955992Swpaul		E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_RST);
34055992Swpaul		break;
34155992Swpaul	}
34255992Swpaul
34355992Swpaul	/* Wait for NVM reload */
34455992Swpaul	msec_delay(20);
34555992Swpaul
34655992Swpaul	/* Disable HW ARPs on ASF enabled adapters */
34755992Swpaul	manc = E1000_READ_REG(hw, E1000_MANC);
34855992Swpaul	manc &= ~E1000_MANC_ARP_EN;
34955992Swpaul	E1000_WRITE_REG(hw, E1000_MANC, manc);
35055992Swpaul
351132860Snjl	if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
352132860Snjl		e1000_phy_init_script_82541(hw);
35355992Swpaul
35455992Swpaul		/* Configure activity LED after Phy reset */
35555992Swpaul		ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
35655992Swpaul		ledctl &= IGP_ACTIVITY_LED_MASK;
35755992Swpaul		ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
35855992Swpaul		E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
35955992Swpaul	}
36055992Swpaul
36155992Swpaul	/* Once again, mask the interrupts */
36255992Swpaul	DEBUGOUT("Masking off all interrupts\n");
36355992Swpaul	E1000_WRITE_REG(hw, E1000_IMC, 0xFFFFFFFF);
36455992Swpaul
36555992Swpaul	/* Clear any pending interrupt events. */
36655992Swpaul	icr = E1000_READ_REG(hw, E1000_ICR);
36755992Swpaul
36855992Swpaul	return E1000_SUCCESS;
36955992Swpaul}
37055992Swpaul
37155992Swpaul/**
37255992Swpaul *  e1000_init_hw_82541 - Initialize hardware
37355992Swpaul *  @hw: pointer to the HW structure
37455992Swpaul *
37555992Swpaul *  This inits the hardware readying it for operation.
37655992Swpaul **/
37755992Swpaulstatic s32 e1000_init_hw_82541(struct e1000_hw *hw)
37855992Swpaul{
37955992Swpaul	struct e1000_mac_info *mac = &hw->mac;
38055992Swpaul	u32 i, txdctl;
38155992Swpaul	s32 ret_val;
38255992Swpaul
38355992Swpaul	DEBUGFUNC("e1000_init_hw_82541");
38455992Swpaul
38555992Swpaul	/* Initialize identification LED */
38655992Swpaul	ret_val = mac->ops.id_led_init(hw);
38755992Swpaul	if (ret_val) {
38855992Swpaul		DEBUGOUT("Error initializing identification LED\n");
38955992Swpaul		/* This is not fatal and we should not stop init due to this */
39055992Swpaul	}
39155992Swpaul
39255992Swpaul	/* Disabling VLAN filtering */
39355992Swpaul	DEBUGOUT("Initializing the IEEE VLAN\n");
39455992Swpaul	mac->ops.clear_vfta(hw);
39555992Swpaul
396108401Sambrisko	/* Setup the receive address. */
397108401Sambrisko	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
398108401Sambrisko
39955992Swpaul	/* Zero out the Multicast HASH table */
40055992Swpaul	DEBUGOUT("Zeroing the MTA\n");
40155992Swpaul	for (i = 0; i < mac->mta_reg_count; i++) {
40255992Swpaul		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
40355992Swpaul		/*
40455992Swpaul		 * Avoid back to back register writes by adding the register
40555992Swpaul		 * read (flush).  This is to protect against some strange
406108401Sambrisko		 * bridge configurations that may issue Memory Write Block
407108401Sambrisko		 * (MWB) to our register space.
408108401Sambrisko		 */
40955992Swpaul		E1000_WRITE_FLUSH(hw);
410108401Sambrisko	}
41155992Swpaul
412108401Sambrisko	/* Setup link and flow control */
41355992Swpaul	ret_val = mac->ops.setup_link(hw);
41455992Swpaul
41555992Swpaul	txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
41655992Swpaul	txdctl = (txdctl & ~E1000_TXDCTL_WTHRESH) |
41755992Swpaul	         E1000_TXDCTL_FULL_TX_DESC_WB;
41855992Swpaul	E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
41955992Swpaul
42055992Swpaul	/*
42155992Swpaul	 * Clear all of the statistics registers (clear on read).  It is
42255992Swpaul	 * important that we do this after we have tried to establish link
42355992Swpaul	 * because the symbol error count will increment wildly if there
42455992Swpaul	 * is no link.
42555992Swpaul	 */
42655992Swpaul	e1000_clear_hw_cntrs_82541(hw);
42755992Swpaul
42855992Swpaul	return ret_val;
42955992Swpaul}
43055992Swpaul
43155992Swpaul/**
43255992Swpaul * e1000_get_link_up_info_82541 - Report speed and duplex
43355992Swpaul * @hw: pointer to the HW structure
43455992Swpaul * @speed: pointer to speed buffer
43555992Swpaul * @duplex: pointer to duplex buffer
436132860Snjl *
437132860Snjl * Retrieve the current speed and duplex configuration.
43855992Swpaul **/
43955992Swpaulstatic s32 e1000_get_link_up_info_82541(struct e1000_hw *hw, u16 *speed,
44055992Swpaul                                        u16 *duplex)
44155992Swpaul{
44255992Swpaul	struct e1000_phy_info *phy = &hw->phy;
44355992Swpaul	s32 ret_val;
44455992Swpaul	u16 data;
44555992Swpaul
44655992Swpaul	DEBUGFUNC("e1000_get_link_up_info_82541");
447132900Snjl
44855992Swpaul	ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex);
449132860Snjl	if (ret_val)
450132860Snjl		goto out;
45155992Swpaul
452132860Snjl	if (!phy->speed_downgraded)
45355992Swpaul		goto out;
454132860Snjl
45555992Swpaul	/*
456132860Snjl	 * IGP01 PHY may advertise full duplex operation after speed
45755992Swpaul	 * downgrade even if it is operating at half duplex.
458132860Snjl	 * Here we set the duplex settings to match the duplex in the
45955992Swpaul	 * link partner's capabilities.
460132860Snjl	 */
46155992Swpaul	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_EXP, &data);
462132860Snjl	if (ret_val)
46355992Swpaul		goto out;
464132860Snjl
46555992Swpaul	if (!(data & NWAY_ER_LP_NWAY_CAPS)) {
466132860Snjl		*duplex = HALF_DUPLEX;
46755992Swpaul	} else {
468132860Snjl		ret_val = phy->ops.read_reg(hw, PHY_LP_ABILITY, &data);
46955992Swpaul		if (ret_val)
470132860Snjl			goto out;
47155992Swpaul
472132860Snjl		if (*speed == SPEED_100) {
47355992Swpaul			if (!(data & NWAY_LPAR_100TX_FD_CAPS))
474132860Snjl				*duplex = HALF_DUPLEX;
47555992Swpaul		} else if (*speed == SPEED_10) {
476132860Snjl			if (!(data & NWAY_LPAR_10T_FD_CAPS))
47755992Swpaul				*duplex = HALF_DUPLEX;
478132860Snjl		}
47955992Swpaul	}
480132860Snjl
48155992Swpaulout:
482132860Snjl	return ret_val;
48355992Swpaul}
484132860Snjl
48555992Swpaul/**
486132860Snjl *  e1000_phy_hw_reset_82541 - PHY hardware reset
48755992Swpaul *  @hw: pointer to the HW structure
488132860Snjl *
48955992Swpaul *  Verify the reset block is not blocking us from resetting.  Acquire
490132860Snjl *  semaphore (if necessary) and read/set/write the device control reset
49155992Swpaul *  bit in the PHY.  Wait the appropriate delay time for the device to
492132860Snjl *  reset and release the semaphore (if necessary).
49355992Swpaul **/
494132860Snjlstatic s32 e1000_phy_hw_reset_82541(struct e1000_hw *hw)
49555992Swpaul{
496132860Snjl	s32 ret_val;
49755992Swpaul	u32 ledctl;
498132860Snjl
49955992Swpaul	DEBUGFUNC("e1000_phy_hw_reset_82541");
500132860Snjl
50155992Swpaul	ret_val = e1000_phy_hw_reset_generic(hw);
502132860Snjl	if (ret_val)
50355992Swpaul		goto out;
504132860Snjl
50555992Swpaul	e1000_phy_init_script_82541(hw);
506132860Snjl
50755992Swpaul	if ((hw->mac.type == e1000_82541) || (hw->mac.type == e1000_82547)) {
508132860Snjl		/* Configure activity LED after PHY reset */
50955992Swpaul		ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
510132860Snjl		ledctl &= IGP_ACTIVITY_LED_MASK;
51155992Swpaul		ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
512132860Snjl		E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
51355992Swpaul	}
514132860Snjl
51555992Swpaulout:
516132860Snjl	return ret_val;
51755992Swpaul}
518132860Snjl
51955992Swpaul/**
520132860Snjl *  e1000_setup_copper_link_82541 - Configure copper link settings
52155992Swpaul *  @hw: pointer to the HW structure
522132860Snjl *
52355992Swpaul *  Calls the appropriate function to configure the link for auto-neg or forced
524132860Snjl *  speed and duplex.  Then we check for link, once link is established calls
52555992Swpaul *  to configure collision distance and flow control are called.  If link is
526132860Snjl *  not established, we return -E1000_ERR_PHY (-2).
52755992Swpaul **/
528132860Snjlstatic s32 e1000_setup_copper_link_82541(struct e1000_hw *hw)
52955992Swpaul{
530132860Snjl	struct e1000_phy_info *phy = &hw->phy;
53155992Swpaul	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
532132860Snjl	s32  ret_val;
53355992Swpaul	u32 ctrl, ledctl;
534132860Snjl
53555992Swpaul	DEBUGFUNC("e1000_setup_copper_link_82541");
536132860Snjl
53755992Swpaul	ctrl = E1000_READ_REG(hw, E1000_CTRL);
538132860Snjl	ctrl |= E1000_CTRL_SLU;
53955992Swpaul	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
540132860Snjl	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
54155992Swpaul
542132860Snjl	hw->phy.reset_disable = FALSE;
54355992Swpaul
544132860Snjl	/* Earlier revs of the IGP phy require us to force MDI. */
54555992Swpaul	if (hw->mac.type == e1000_82541 || hw->mac.type == e1000_82547) {
546132860Snjl		dev_spec->dsp_config = e1000_dsp_config_disabled;
54755992Swpaul		phy->mdix = 1;
548132860Snjl	} else {
54955992Swpaul		dev_spec->dsp_config = e1000_dsp_config_enabled;
550132860Snjl	}
55155992Swpaul
552132860Snjl	ret_val = e1000_copper_link_setup_igp(hw);
55355992Swpaul	if (ret_val)
554132860Snjl		goto out;
55555992Swpaul
556132860Snjl	if (hw->mac.autoneg) {
55755992Swpaul		if (dev_spec->ffe_config == e1000_ffe_config_active)
558132860Snjl			dev_spec->ffe_config = e1000_ffe_config_enabled;
55955992Swpaul	}
560132860Snjl
56155992Swpaul	/* Configure activity LED after Phy reset */
562132860Snjl	ledctl = E1000_READ_REG(hw, E1000_LEDCTL);
56355992Swpaul	ledctl &= IGP_ACTIVITY_LED_MASK;
564132860Snjl	ledctl |= (IGP_ACTIVITY_LED_ENABLE | IGP_LED3_MODE);
56555992Swpaul	E1000_WRITE_REG(hw, E1000_LEDCTL, ledctl);
566132860Snjl
56755992Swpaul	ret_val = e1000_setup_copper_link_generic(hw);
568132860Snjl
56955992Swpaulout:
570132860Snjl	return ret_val;
57155992Swpaul}
572132860Snjl
57355992Swpaul/**
574132860Snjl *  e1000_check_for_link_82541 - Check/Store link connection
57555992Swpaul *  @hw: pointer to the HW structure
576132860Snjl *
577305619Spfg *  This checks the link condition of the adapter and stores the
578132860Snjl *  results in the hw->mac structure.
579305619Spfg **/
580132860Snjlstatic s32 e1000_check_for_link_82541(struct e1000_hw *hw)
58155992Swpaul{
582132860Snjl	struct e1000_mac_info *mac = &hw->mac;
58355992Swpaul	s32 ret_val;
584132860Snjl	bool link;
58555992Swpaul
586132860Snjl	DEBUGFUNC("e1000_check_for_link_82541");
58755992Swpaul
588132860Snjl	/*
58955992Swpaul	 * We only want to go out to the PHY registers to see if Auto-Neg
590132860Snjl	 * has completed and/or if our link status has changed.  The
59155992Swpaul	 * get_link_status flag is set upon receiving a Link Status
592132860Snjl	 * Change or Rx Sequence Error interrupt.
59355992Swpaul	 */
594132860Snjl	if (!mac->get_link_status) {
59555992Swpaul		ret_val = E1000_SUCCESS;
59655992Swpaul		goto out;
59755992Swpaul	}
598132860Snjl
599132860Snjl	/*
60055992Swpaul	 * First we want to see if the MII Status Register reports
60155992Swpaul	 * link.  If so, then we want to get the current speed/duplex
60255992Swpaul	 * of the PHY.
60355992Swpaul	 */
60455992Swpaul	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
60555992Swpaul	if (ret_val)
60655992Swpaul		goto out;
60755992Swpaul
60855992Swpaul	if (!link) {
60955992Swpaul		ret_val = e1000_config_dsp_after_link_change_82541(hw, FALSE);
61055992Swpaul		goto out; /* No link detected */
61155992Swpaul	}
61255992Swpaul
61355992Swpaul	mac->get_link_status = FALSE;
61455992Swpaul
61555992Swpaul	/*
61655992Swpaul	 * Check if there was DownShift, must be checked
61755992Swpaul	 * immediately after link-up
61855992Swpaul	 */
61955992Swpaul	e1000_check_downshift_generic(hw);
62055992Swpaul
62155992Swpaul	/*
62255992Swpaul	 * If we are forcing speed/duplex, then we simply return since
623132860Snjl	 * we have already determined whether we have link or not.
624132860Snjl	 */
62555992Swpaul	if (!mac->autoneg) {
626119156Sambrisko		ret_val = -E1000_ERR_CONFIG;
62755992Swpaul		goto out;
628119156Sambrisko	}
62955992Swpaul
63055992Swpaul	ret_val = e1000_config_dsp_after_link_change_82541(hw, TRUE);
63155992Swpaul
63255992Swpaul	/*
63355992Swpaul	 * Auto-Neg is enabled.  Auto Speed Detection takes care
63455992Swpaul	 * of MAC speed/duplex configuration.  So we only need to
635119156Sambrisko	 * configure Collision Distance in the MAC.
636119156Sambrisko	 */
637132860Snjl	e1000_config_collision_dist_generic(hw);
638119156Sambrisko
639119156Sambrisko	/*
640119156Sambrisko	 * Configure Flow Control now that Auto-Neg has completed.
641119156Sambrisko	 * First, we need to restore the desired flow control
642119156Sambrisko	 * settings because we may have had to re-autoneg with a
643119156Sambrisko	 * different link partner.
644119156Sambrisko	 */
645119156Sambrisko	ret_val = e1000_config_fc_after_link_up_generic(hw);
64655992Swpaul	if (ret_val) {
64755992Swpaul		DEBUGOUT("Error configuring flow control\n");
64855992Swpaul	}
64955992Swpaul
650132860Snjlout:
651132860Snjl	return ret_val;
65255992Swpaul}
65355992Swpaul
65455992Swpaul/**
65580454Sbrooks *  e1000_config_dsp_after_link_change_82541 - Config DSP after link
65655992Swpaul *  @hw: pointer to the HW structure
65755992Swpaul *  @link_up: boolean flag for link up status
65855992Swpaul *
65955992Swpaul *  Return E1000_ERR_PHY when failing to read/write the PHY, else E1000_SUCCESS
66055992Swpaul *  at any other case.
66155992Swpaul *
66255992Swpaul *  82541_rev_2 & 82547_rev_2 have the capability to configure the DSP when a
66355992Swpaul *  gigabit link is achieved to improve link quality.
66455992Swpaul **/
66555992Swpaulstatic s32 e1000_config_dsp_after_link_change_82541(struct e1000_hw *hw,
66655992Swpaul                                                    bool link_up)
66755992Swpaul{
66855992Swpaul	struct e1000_phy_info *phy = &hw->phy;
66955992Swpaul	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
67055992Swpaul	s32 ret_val;
67155992Swpaul	u32 idle_errs = 0;
67255992Swpaul	u16 phy_data, phy_saved_data, speed, duplex, i;
67355992Swpaul	u16 ffe_idle_err_timeout = FFE_IDLE_ERR_COUNT_TIMEOUT_20;
67455992Swpaul	u16 dsp_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
67555992Swpaul	                                           {IGP01E1000_PHY_AGC_PARAM_A,
67655992Swpaul	                                            IGP01E1000_PHY_AGC_PARAM_B,
67755992Swpaul	                                            IGP01E1000_PHY_AGC_PARAM_C,
67855992Swpaul	                                            IGP01E1000_PHY_AGC_PARAM_D};
67955992Swpaul
68055992Swpaul	DEBUGFUNC("e1000_config_dsp_after_link_change_82541");
68155992Swpaul
68255992Swpaul	if (link_up) {
68355992Swpaul		ret_val = hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
68455992Swpaul		if (ret_val) {
68555992Swpaul			DEBUGOUT("Error getting link speed and duplex\n");
68655992Swpaul			goto out;
68755992Swpaul		}
68855992Swpaul
68955992Swpaul		if (speed != SPEED_1000) {
69055992Swpaul			ret_val = E1000_SUCCESS;
69155992Swpaul			goto out;
69255992Swpaul		}
69355992Swpaul
69455992Swpaul		ret_val = phy->ops.get_cable_length(hw);
69555992Swpaul		if (ret_val)
69655992Swpaul			goto out;
69755992Swpaul
69855992Swpaul		if ((dev_spec->dsp_config == e1000_dsp_config_enabled) &&
69955992Swpaul		    phy->min_cable_length >= 50) {
70055992Swpaul
70155992Swpaul			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
70255992Swpaul				ret_val = phy->ops.read_reg(hw,
70355992Swpaul				                            dsp_reg_array[i],
70455992Swpaul				                            &phy_data);
70555992Swpaul				if (ret_val)
70655992Swpaul					goto out;
70755992Swpaul
70855992Swpaul				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
70955992Swpaul
71055992Swpaul				ret_val = phy->ops.write_reg(hw,
71155992Swpaul				                             dsp_reg_array[i],
71255992Swpaul				                             phy_data);
71355992Swpaul				if (ret_val)
71455992Swpaul					goto out;
71555992Swpaul			}
71655992Swpaul			dev_spec->dsp_config = e1000_dsp_config_activated;
71755992Swpaul		}
71855992Swpaul
71955992Swpaul		if ((dev_spec->ffe_config != e1000_ffe_config_enabled) ||
72055992Swpaul		    (phy->min_cable_length >= 50)) {
72155992Swpaul			ret_val = E1000_SUCCESS;
72255992Swpaul			goto out;
72355992Swpaul		}
72455992Swpaul
72555992Swpaul		/* clear previous idle error counts */
72655992Swpaul		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
72755992Swpaul		if (ret_val)
72855992Swpaul			goto out;
72955992Swpaul
73055992Swpaul		for (i = 0; i < ffe_idle_err_timeout; i++) {
73155992Swpaul			usec_delay(1000);
73255992Swpaul			ret_val = phy->ops.read_reg(hw,
73355992Swpaul			                            PHY_1000T_STATUS,
73455992Swpaul			                            &phy_data);
73555992Swpaul			if (ret_val)
73668692Swpaul				goto out;
73769772Sarchie
73869772Sarchie			idle_errs += (phy_data & SR_1000T_IDLE_ERROR_CNT);
73988748Sambrisko			if (idle_errs > SR_1000T_PHY_EXCESSIVE_IDLE_ERR_COUNT) {
74088748Sambrisko				dev_spec->ffe_config = e1000_ffe_config_active;
74188748Sambrisko
74269772Sarchie				ret_val = phy->ops.write_reg(hw,
74369772Sarchie				                  IGP01E1000_PHY_DSP_FFE,
74469772Sarchie				                  IGP01E1000_PHY_DSP_FFE_CM_CP);
74569772Sarchie				if (ret_val)
74668692Swpaul					goto out;
74768692Swpaul				break;
74868692Swpaul			}
74955992Swpaul
75068692Swpaul			if (idle_errs)
75168692Swpaul				ffe_idle_err_timeout =
75268692Swpaul				                 FFE_IDLE_ERR_COUNT_TIMEOUT_100;
75355992Swpaul		}
75468692Swpaul	} else {
75555992Swpaul		if (dev_spec->dsp_config == e1000_dsp_config_activated) {
75655992Swpaul			/*
75755992Swpaul			 * Save off the current value of register 0x2F5B
75855992Swpaul			 * to be restored at the end of the routines.
75955992Swpaul			 */
76055992Swpaul			ret_val = phy->ops.read_reg(hw,
76155992Swpaul			                            0x2F5B,
76255992Swpaul			                            &phy_saved_data);
76355992Swpaul			if (ret_val)
76455992Swpaul				goto out;
76555992Swpaul
76655992Swpaul			/* Disable the PHY transmitter */
76755992Swpaul			ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
76855992Swpaul			if (ret_val)
76955992Swpaul				goto out;
77055992Swpaul
77155992Swpaul			msec_delay_irq(20);
77255992Swpaul
77355992Swpaul			ret_val = phy->ops.write_reg(hw,
77455992Swpaul			                             0x0000,
77555992Swpaul			                             IGP01E1000_IEEE_FORCE_GIG);
77655992Swpaul			if (ret_val)
77755992Swpaul				goto out;
77855992Swpaul			for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
77955992Swpaul				ret_val = phy->ops.read_reg(hw,
78055992Swpaul				                            dsp_reg_array[i],
78155992Swpaul				                            &phy_data);
78255992Swpaul				if (ret_val)
78355992Swpaul					goto out;
78455992Swpaul
78555992Swpaul				phy_data &= ~IGP01E1000_PHY_EDAC_MU_INDEX;
78655992Swpaul				phy_data |= IGP01E1000_PHY_EDAC_SIGN_EXT_9_BITS;
78755992Swpaul
78855992Swpaul				ret_val = phy->ops.write_reg(hw,
78955992Swpaul				                             dsp_reg_array[i],
79055992Swpaul				                             phy_data);
79155992Swpaul				if (ret_val)
79255992Swpaul					goto out;
79355992Swpaul			}
79455992Swpaul
79555992Swpaul			ret_val = phy->ops.write_reg(hw,
79655992Swpaul			                       0x0000,
79755992Swpaul			                       IGP01E1000_IEEE_RESTART_AUTONEG);
79855992Swpaul			if (ret_val)
79955992Swpaul				goto out;
80055992Swpaul
80155992Swpaul			msec_delay_irq(20);
80255992Swpaul
80355992Swpaul			/* Now enable the transmitter */
80455992Swpaul			ret_val = phy->ops.write_reg(hw,
80555992Swpaul			                             0x2F5B,
80655992Swpaul			                             phy_saved_data);
80755992Swpaul			if (ret_val)
80855992Swpaul				goto out;
80955992Swpaul
81080454Sbrooks			dev_spec->dsp_config = e1000_dsp_config_enabled;
811108401Sambrisko		}
812108401Sambrisko
813108401Sambrisko		if (dev_spec->ffe_config != e1000_ffe_config_active) {
81455992Swpaul			ret_val = E1000_SUCCESS;
81580454Sbrooks			goto out;
81655992Swpaul		}
81780454Sbrooks
81855992Swpaul		/*
81955992Swpaul		 * Save off the current value of register 0x2F5B
82055992Swpaul		 * to be restored at the end of the routines.
82180454Sbrooks		 */
822108401Sambrisko		ret_val = phy->ops.read_reg(hw, 0x2F5B, &phy_saved_data);
823108401Sambrisko		if (ret_val)
824108401Sambrisko			goto out;
82555992Swpaul
82680454Sbrooks		/* Disable the PHY transmitter */
82755992Swpaul		ret_val = phy->ops.write_reg(hw, 0x2F5B, 0x0003);
82880454Sbrooks		if (ret_val)
82955992Swpaul			goto out;
83055992Swpaul
83155992Swpaul		msec_delay_irq(20);
83255992Swpaul
83355992Swpaul		ret_val = phy->ops.write_reg(hw,
83455992Swpaul		                             0x0000,
83555992Swpaul		                             IGP01E1000_IEEE_FORCE_GIG);
83655992Swpaul		if (ret_val)
83755992Swpaul			goto out;
83855992Swpaul
83955992Swpaul		ret_val = phy->ops.write_reg(hw,
84055992Swpaul		                             IGP01E1000_PHY_DSP_FFE,
84155992Swpaul		                             IGP01E1000_PHY_DSP_FFE_DEFAULT);
84255992Swpaul		if (ret_val)
84388748Sambrisko			goto out;
84488748Sambrisko
84588748Sambrisko		ret_val = phy->ops.write_reg(hw,
84688748Sambrisko		                             0x0000,
84788748Sambrisko		                             IGP01E1000_IEEE_RESTART_AUTONEG);
84888748Sambrisko		if (ret_val)
84955992Swpaul			goto out;
85055992Swpaul
85169772Sarchie		msec_delay_irq(20);
85269772Sarchie
85355992Swpaul		/* Now enable the transmitter */
85455992Swpaul		ret_val = phy->ops.write_reg(hw, 0x2F5B, phy_saved_data);
855132860Snjl
856132860Snjl		if (ret_val)
857108401Sambrisko			goto out;
858108401Sambrisko
859108401Sambrisko		dev_spec->ffe_config = e1000_ffe_config_enabled;
860108401Sambrisko	}
86155992Swpaul
862108401Sambriskoout:
863108401Sambrisko	return ret_val;
864108401Sambrisko}
865108401Sambrisko
866108401Sambrisko/**
867108401Sambrisko *  e1000_get_cable_length_igp_82541 - Determine cable length for igp PHY
868108401Sambrisko *  @hw: pointer to the HW structure
869108401Sambrisko *
870108401Sambrisko *  The automatic gain control (agc) normalizes the amplitude of the
871108401Sambrisko *  received signal, adjusting for the attenuation produced by the
872108401Sambrisko *  cable.  By reading the AGC registers, which represent the
873108401Sambrisko *  combination of coarse and fine gain value, the value can be put
874108401Sambrisko *  into a lookup table to obtain the approximate cable length
875108401Sambrisko *  for each channel.
876108401Sambrisko **/
877108401Sambriskostatic s32 e1000_get_cable_length_igp_82541(struct e1000_hw *hw)
878108401Sambrisko{
879108401Sambrisko	struct e1000_phy_info *phy = &hw->phy;
880108401Sambrisko	s32 ret_val = E1000_SUCCESS;
881108401Sambrisko	u16 i, data;
882132860Snjl	u16 cur_agc_value, agc_value = 0;
883132860Snjl	u16 min_agc_value = IGP01E1000_AGC_LENGTH_TABLE_SIZE;
88455992Swpaul	u16 agc_reg_array[IGP01E1000_PHY_CHANNEL_NUM] =
88555992Swpaul	                                                 {IGP01E1000_PHY_AGC_A,
88655992Swpaul	                                                  IGP01E1000_PHY_AGC_B,
88755992Swpaul	                                                  IGP01E1000_PHY_AGC_C,
88855992Swpaul	                                                  IGP01E1000_PHY_AGC_D};
88955992Swpaul
89055992Swpaul	DEBUGFUNC("e1000_get_cable_length_igp_82541");
891108401Sambrisko
89289380Sambrisko	/* Read the AGC registers for all channels */
89389380Sambrisko	for (i = 0; i < IGP01E1000_PHY_CHANNEL_NUM; i++) {
89489380Sambrisko		ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &data);
89555992Swpaul		if (ret_val)
89655992Swpaul			goto out;
89755992Swpaul
89889380Sambrisko		cur_agc_value = data >> IGP01E1000_AGC_LENGTH_SHIFT;
89989380Sambrisko
90089380Sambrisko		/* Bounds checking */
90189380Sambrisko		if ((cur_agc_value >= IGP01E1000_AGC_LENGTH_TABLE_SIZE - 1) ||
90255992Swpaul		    (cur_agc_value == 0)) {
90355992Swpaul			ret_val = -E1000_ERR_PHY;
90489380Sambrisko			goto out;
90555992Swpaul		}
90655992Swpaul
90755992Swpaul		agc_value += cur_agc_value;
90855992Swpaul
90955992Swpaul		if (min_agc_value > cur_agc_value)
91083269Sbrooks			min_agc_value = cur_agc_value;
91188748Sambrisko	}
91255992Swpaul
91355992Swpaul	/* Remove the minimal AGC result for length < 50m */
91455992Swpaul	if (agc_value < IGP01E1000_PHY_CHANNEL_NUM * 50) {
91555992Swpaul		agc_value -= min_agc_value;
91655992Swpaul		/* Average the three remaining channels for the length. */
91755992Swpaul		agc_value /= (IGP01E1000_PHY_CHANNEL_NUM - 1);
91855992Swpaul	} else {
91955992Swpaul		/* Average the channels for the length. */
92055992Swpaul		agc_value /= IGP01E1000_PHY_CHANNEL_NUM;
92155992Swpaul	}
922132860Snjl
923132860Snjl	phy->min_cable_length = (e1000_igp_cable_length_table[agc_value] >
92455992Swpaul	                         IGP01E1000_AGC_RANGE)
92555992Swpaul	                        ? (e1000_igp_cable_length_table[agc_value] -
92655992Swpaul	                           IGP01E1000_AGC_RANGE)
92755992Swpaul	                        : 0;
92855992Swpaul	phy->max_cable_length = e1000_igp_cable_length_table[agc_value] +
92955992Swpaul	                        IGP01E1000_AGC_RANGE;
93055992Swpaul
93155992Swpaul	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
93255992Swpaul
93355992Swpaulout:
93455992Swpaul	return ret_val;
93555992Swpaul}
93655992Swpaul
93755992Swpaul/**
93855992Swpaul *  e1000_set_d3_lplu_state_82541 - Sets low power link up state for D3
93955992Swpaul *  @hw: pointer to the HW structure
94055992Swpaul *  @active: boolean used to enable/disable lplu
94155992Swpaul *
94255992Swpaul *  Success returns 0, Failure returns 1
94355992Swpaul *
94455992Swpaul *  The low power link up (lplu) state is set to the power management level D3
94555992Swpaul *  and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
94655992Swpaul *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
94755992Swpaul *  is used during Dx states where the power conservation is most important.
94855992Swpaul *  During driver activity, SmartSpeed should be enabled so performance is
94955992Swpaul *  maintained.
95055992Swpaul **/
95155992Swpaulstatic s32 e1000_set_d3_lplu_state_82541(struct e1000_hw *hw, bool active)
95255992Swpaul{
95355992Swpaul	struct e1000_phy_info *phy = &hw->phy;
95455992Swpaul	s32 ret_val;
95555992Swpaul	u16 data;
95655992Swpaul
95755992Swpaul	DEBUGFUNC("e1000_set_d3_lplu_state_82541");
95855992Swpaul
95955992Swpaul	switch (hw->mac.type) {
96055992Swpaul	case e1000_82541_rev_2:
96155992Swpaul	case e1000_82547_rev_2:
96255992Swpaul		break;
96355992Swpaul	default:
96455992Swpaul		ret_val = e1000_set_d3_lplu_state_generic(hw, active);
96555992Swpaul		goto out;
96655992Swpaul		break;
96755992Swpaul	}
96855992Swpaul
96955992Swpaul	ret_val = phy->ops.read_reg(hw, IGP01E1000_GMII_FIFO, &data);
97055992Swpaul	if (ret_val)
97155992Swpaul		goto out;
972132860Snjl
97355992Swpaul	if (!active) {
97455992Swpaul		data &= ~IGP01E1000_GMII_FLEX_SPD;
975108401Sambrisko		ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
976108401Sambrisko		if (ret_val)
977108401Sambrisko			goto out;
978108401Sambrisko
97955992Swpaul		/*
98055992Swpaul		 * LPLU and SmartSpeed are mutually exclusive.  LPLU is used
98155992Swpaul		 * during Dx states where the power conservation is most
98255992Swpaul		 * important.  During driver activity we should enable
98355992Swpaul		 * SmartSpeed, so performance is maintained.
98455992Swpaul		 */
98555992Swpaul		if (phy->smart_speed == e1000_smart_speed_on) {
98655992Swpaul			ret_val = phy->ops.read_reg(hw,
98755992Swpaul			                            IGP01E1000_PHY_PORT_CONFIG,
98855992Swpaul			                            &data);
98955992Swpaul			if (ret_val)
99055992Swpaul				goto out;
99155992Swpaul
99255992Swpaul			data |= IGP01E1000_PSCFR_SMART_SPEED;
99355992Swpaul			ret_val = phy->ops.write_reg(hw,
99455992Swpaul			                             IGP01E1000_PHY_PORT_CONFIG,
99555992Swpaul			                             data);
99655992Swpaul			if (ret_val)
99755992Swpaul				goto out;
99855992Swpaul		} else if (phy->smart_speed == e1000_smart_speed_off) {
99955992Swpaul			ret_val = phy->ops.read_reg(hw,
100055992Swpaul			                            IGP01E1000_PHY_PORT_CONFIG,
100155992Swpaul			                            &data);
100255992Swpaul			if (ret_val)
100355992Swpaul				goto out;
100455992Swpaul
100555992Swpaul			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
100655992Swpaul			ret_val = phy->ops.write_reg(hw,
100755992Swpaul			                             IGP01E1000_PHY_PORT_CONFIG,
100855992Swpaul			                             data);
100955992Swpaul			if (ret_val)
101055992Swpaul				goto out;
101155992Swpaul		}
101255992Swpaul	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
101355992Swpaul	           (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
101455992Swpaul	           (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
101555992Swpaul		data |= IGP01E1000_GMII_FLEX_SPD;
101655992Swpaul		ret_val = phy->ops.write_reg(hw, IGP01E1000_GMII_FIFO, data);
101755992Swpaul		if (ret_val)
101855992Swpaul			goto out;
101955992Swpaul
102055992Swpaul		/* When LPLU is enabled, we should disable SmartSpeed */
102155992Swpaul		ret_val = phy->ops.read_reg(hw,
1022132900Snjl		                            IGP01E1000_PHY_PORT_CONFIG,
102355992Swpaul		                            &data);
102468692Swpaul		if (ret_val)
102569772Sarchie			goto out;
102669772Sarchie
102769772Sarchie		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
102869772Sarchie		ret_val = phy->ops.write_reg(hw,
102988748Sambrisko		                             IGP01E1000_PHY_PORT_CONFIG,
103088748Sambrisko		                             data);
103169772Sarchie	}
103269772Sarchie
103369772Sarchieout:
103469772Sarchie	return ret_val;
103569772Sarchie}
103688748Sambrisko
103769772Sarchie/**
103869772Sarchie *  e1000_setup_led_82541 - Configures SW controllable LED
103969772Sarchie *  @hw: pointer to the HW structure
104069772Sarchie *
104169772Sarchie *  This prepares the SW controllable LED for use and saves the current state
104269772Sarchie *  of the LED so it can be later restored.
104369772Sarchie **/
104468692Swpaulstatic s32 e1000_setup_led_82541(struct e1000_hw *hw)
104568692Swpaul{
104668692Swpaul	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
104768692Swpaul	s32 ret_val;
104868692Swpaul
104983269Sbrooks	DEBUGFUNC("e1000_setup_led_82541");
105083269Sbrooks
105183269Sbrooks	ret_val = hw->phy.ops.read_reg(hw,
105283269Sbrooks	                               IGP01E1000_GMII_FIFO,
105355992Swpaul	                               &dev_spec->spd_default);
105455992Swpaul	if (ret_val)
105555992Swpaul		goto out;
105655992Swpaul
105755992Swpaul	ret_val = hw->phy.ops.write_reg(hw,
105855992Swpaul	                                IGP01E1000_GMII_FIFO,
105955992Swpaul	                                (u16)(dev_spec->spd_default &
106055992Swpaul	                                        ~IGP01E1000_GMII_SPD));
106155992Swpaul	if (ret_val)
1062132860Snjl		goto out;
1063132860Snjl
106455992Swpaul	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
106555992Swpaul
106655992Swpaulout:
106755992Swpaul	return ret_val;
106855992Swpaul}
106955992Swpaul
107055992Swpaul/**
107155992Swpaul *  e1000_cleanup_led_82541 - Set LED config to default operation
107255992Swpaul *  @hw: pointer to the HW structure
107355992Swpaul *
107455992Swpaul *  Remove the current LED configuration and set the LED configuration
107555992Swpaul *  to the default value, saved from the EEPROM.
107655992Swpaul **/
107755992Swpaulstatic s32 e1000_cleanup_led_82541(struct e1000_hw *hw)
107855992Swpaul{
107955992Swpaul	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
108055992Swpaul	s32 ret_val;
108155992Swpaul
108255992Swpaul	DEBUGFUNC("e1000_cleanup_led_82541");
108355992Swpaul
108455992Swpaul	ret_val = hw->phy.ops.write_reg(hw,
108555992Swpaul	                                IGP01E1000_GMII_FIFO,
108655992Swpaul	                                dev_spec->spd_default);
108755992Swpaul	if (ret_val)
108855992Swpaul		goto out;
108955992Swpaul
109055992Swpaul	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
109155992Swpaul
109255992Swpaulout:
109355992Swpaul	return ret_val;
109455992Swpaul}
109555992Swpaul
109655992Swpaul/**
109755992Swpaul *  e1000_phy_init_script_82541 - Initialize GbE PHY
109855992Swpaul *  @hw: pointer to the HW structure
109955992Swpaul *
110055992Swpaul *  Initializes the IGP PHY.
110155992Swpaul **/
110255992Swpaulstatic s32 e1000_phy_init_script_82541(struct e1000_hw *hw)
110355992Swpaul{
110455992Swpaul	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
110555992Swpaul	u32 ret_val;
110655992Swpaul	u16 phy_saved_data;
110755992Swpaul
1108132860Snjl	DEBUGFUNC("e1000_phy_init_script_82541");
1109132860Snjl
111055992Swpaul	if (!dev_spec->phy_init_script) {
111155992Swpaul		ret_val = E1000_SUCCESS;
111255992Swpaul		goto out;
111355992Swpaul	}
111455992Swpaul
111555992Swpaul	/* Delay after phy reset to enable NVM configuration to load */
111655992Swpaul	msec_delay(20);
111755992Swpaul
111855992Swpaul	/*
111955992Swpaul	 * Save off the current value of register 0x2F5B to be restored at
112055992Swpaul	 * the end of this routine.
112155992Swpaul	 */
112255992Swpaul	ret_val = hw->phy.ops.read_reg(hw, 0x2F5B, &phy_saved_data);
112355992Swpaul
112455992Swpaul	/* Disabled the PHY transmitter */
112555992Swpaul	hw->phy.ops.write_reg(hw, 0x2F5B, 0x0003);
112655992Swpaul
112755992Swpaul	msec_delay(20);
112855992Swpaul
1129132900Snjl	hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
113055992Swpaul
113155992Swpaul	msec_delay(5);
113255992Swpaul
1133132900Snjl	switch (hw->mac.type) {
113455992Swpaul	case e1000_82541:
113555992Swpaul	case e1000_82547:
113655992Swpaul		hw->phy.ops.write_reg(hw, 0x1F95, 0x0001);
1137132900Snjl
113855992Swpaul		hw->phy.ops.write_reg(hw, 0x1F71, 0xBD21);
113955992Swpaul
114055992Swpaul		hw->phy.ops.write_reg(hw, 0x1F79, 0x0018);
1141132900Snjl
114255992Swpaul		hw->phy.ops.write_reg(hw, 0x1F30, 0x1600);
114355992Swpaul
114455992Swpaul		hw->phy.ops.write_reg(hw, 0x1F31, 0x0014);
114555992Swpaul
114655992Swpaul		hw->phy.ops.write_reg(hw, 0x1F32, 0x161C);
114755992Swpaul
114855992Swpaul		hw->phy.ops.write_reg(hw, 0x1F94, 0x0003);
114955992Swpaul
115055992Swpaul		hw->phy.ops.write_reg(hw, 0x1F96, 0x003F);
115155992Swpaul
1152132860Snjl		hw->phy.ops.write_reg(hw, 0x2010, 0x0008);
1153132860Snjl		break;
115455992Swpaul	case e1000_82541_rev_2:
1155119156Sambrisko	case e1000_82547_rev_2:
115655992Swpaul		hw->phy.ops.write_reg(hw, 0x1F73, 0x0099);
1157119156Sambrisko		break;
115855992Swpaul	default:
115955992Swpaul		break;
116055992Swpaul	}
116155992Swpaul
116255992Swpaul	hw->phy.ops.write_reg(hw, 0x0000, 0x3300);
1163119156Sambrisko
116455992Swpaul	msec_delay(20);
1165119156Sambrisko
1166119156Sambrisko	/* Now enable the transmitter */
1167132860Snjl	hw->phy.ops.write_reg(hw, 0x2F5B, phy_saved_data);
1168119156Sambrisko
1169119156Sambrisko	if (hw->mac.type == e1000_82547) {
117055992Swpaul		u16 fused, fine, coarse;
117155992Swpaul
1172119156Sambrisko		/* Move to analog registers page */
1173119156Sambrisko		hw->phy.ops.read_reg(hw,
1174119156Sambrisko		                  IGP01E1000_ANALOG_SPARE_FUSE_STATUS,
1175119156Sambrisko		                  &fused);
1176119156Sambrisko
1177119156Sambrisko		if (!(fused & IGP01E1000_ANALOG_SPARE_FUSE_ENABLED)) {
1178119156Sambrisko			hw->phy.ops.read_reg(hw,
1179119156Sambrisko			                  IGP01E1000_ANALOG_FUSE_STATUS,
1180119156Sambrisko			                  &fused);
1181119156Sambrisko
1182119156Sambrisko			fine = fused & IGP01E1000_ANALOG_FUSE_FINE_MASK;
1183119156Sambrisko			coarse = fused & IGP01E1000_ANALOG_FUSE_COARSE_MASK;
1184119156Sambrisko
118555992Swpaul			if (coarse > IGP01E1000_ANALOG_FUSE_COARSE_THRESH) {
1186119156Sambrisko				coarse -= IGP01E1000_ANALOG_FUSE_COARSE_10;
118755992Swpaul				fine -= IGP01E1000_ANALOG_FUSE_FINE_1;
118855992Swpaul			} else if (coarse ==
118955992Swpaul			           IGP01E1000_ANALOG_FUSE_COARSE_THRESH)
119055992Swpaul				fine -= IGP01E1000_ANALOG_FUSE_FINE_10;
1191132860Snjl
1192132860Snjl			fused = (fused & IGP01E1000_ANALOG_FUSE_POLY_MASK) |
119355992Swpaul			        (fine & IGP01E1000_ANALOG_FUSE_FINE_MASK) |
119455992Swpaul			        (coarse & IGP01E1000_ANALOG_FUSE_COARSE_MASK);
119555992Swpaul
1196132900Snjl			hw->phy.ops.write_reg(hw,
119755992Swpaul			                   IGP01E1000_ANALOG_FUSE_CONTROL,
119855992Swpaul			                   fused);
119955992Swpaul			hw->phy.ops.write_reg(hw,
120055992Swpaul			              IGP01E1000_ANALOG_FUSE_BYPASS,
120155992Swpaul			              IGP01E1000_ANALOG_FUSE_ENABLE_SW_CONTROL);
120255992Swpaul		}
1203132860Snjl	}
1204132860Snjl
120555992Swpaulout:
120655992Swpaul	return ret_val;
1207132900Snjl}
120855992Swpaul
120955992Swpaul/**
121055992Swpaul *  e1000_init_script_state_82541 - Enable/Disable PHY init script
121155992Swpaul *  @hw: pointer to the HW structure
121255992Swpaul *  @state: boolean value used to enable/disable PHY init script
121355992Swpaul *
1214132900Snjl *  Allows the driver to enable/disable the PHY init script, if the PHY is an
121555992Swpaul *  IGP PHY.
121655992Swpaul **/
121755992Swpaulvoid e1000_init_script_state_82541(struct e1000_hw *hw, bool state)
121855992Swpaul{
121955992Swpaul	struct e1000_dev_spec_82541 *dev_spec = &hw->dev_spec._82541;
1220132900Snjl
1221132900Snjl	DEBUGFUNC("e1000_init_script_state_82541");
122255992Swpaul
122355992Swpaul	if (hw->phy.type != e1000_phy_igp) {
122455992Swpaul		DEBUGOUT("Initialization script not necessary.\n");
122555992Swpaul		goto out;
122655992Swpaul	}
122755992Swpaul
122855992Swpaul	dev_spec->phy_init_script = state;
122955992Swpaul
123055992Swpaulout:
123155992Swpaul	return;
123255992Swpaul}
123355992Swpaul
123455992Swpaul/**
123555992Swpaul * e1000_power_down_phy_copper_82541 - Remove link in case of PHY power down
123655992Swpaul * @hw: pointer to the HW structure
123755992Swpaul *
123855992Swpaul * In the case of a PHY power down to save power, or to turn off link during a
123955992Swpaul * driver unload, or wake on lan is not enabled, remove the link.
124055992Swpaul **/
124155992Swpaulstatic void e1000_power_down_phy_copper_82541(struct e1000_hw *hw)
124255992Swpaul{
124355992Swpaul	/* If the management interface is not enabled, then power down */
124455992Swpaul	if (!(E1000_READ_REG(hw, E1000_MANC) & E1000_MANC_SMBUS_EN))
1245132860Snjl		e1000_power_down_phy_copper(hw);
1246132860Snjl
124768692Swpaul	return;
124868692Swpaul}
124968692Swpaul
125068692Swpaul/**
125168692Swpaul *  e1000_clear_hw_cntrs_82541 - Clear device specific hardware counters
125268692Swpaul *  @hw: pointer to the HW structure
125368692Swpaul *
125455992Swpaul *  Clears the hardware counters by reading the counter registers.
125568692Swpaul **/
125668692Swpaulstatic void e1000_clear_hw_cntrs_82541(struct e1000_hw *hw)
125768692Swpaul{
1258132860Snjl	DEBUGFUNC("e1000_clear_hw_cntrs_82541");
1259132860Snjl
126068692Swpaul	e1000_clear_hw_cntrs_base_generic(hw);
126168692Swpaul
126268692Swpaul	E1000_READ_REG(hw, E1000_PRC64);
126368692Swpaul	E1000_READ_REG(hw, E1000_PRC127);
126468692Swpaul	E1000_READ_REG(hw, E1000_PRC255);
126568692Swpaul	E1000_READ_REG(hw, E1000_PRC511);
126668692Swpaul	E1000_READ_REG(hw, E1000_PRC1023);
126768692Swpaul	E1000_READ_REG(hw, E1000_PRC1522);
126868692Swpaul	E1000_READ_REG(hw, E1000_PTC64);
126980454Sbrooks	E1000_READ_REG(hw, E1000_PTC127);
127068692Swpaul	E1000_READ_REG(hw, E1000_PTC255);
127168692Swpaul	E1000_READ_REG(hw, E1000_PTC511);
127268692Swpaul	E1000_READ_REG(hw, E1000_PTC1023);
127380454Sbrooks	E1000_READ_REG(hw, E1000_PTC1522);
127480454Sbrooks
127568692Swpaul	E1000_READ_REG(hw, E1000_ALGNERRC);
127668692Swpaul	E1000_READ_REG(hw, E1000_RXERRC);
127768692Swpaul	E1000_READ_REG(hw, E1000_TNCRS);
127868692Swpaul	E1000_READ_REG(hw, E1000_CEXTERR);
127968692Swpaul	E1000_READ_REG(hw, E1000_TSCTC);
128068692Swpaul	E1000_READ_REG(hw, E1000_TSCTFC);
128168692Swpaul
128268692Swpaul	E1000_READ_REG(hw, E1000_MGTPRC);
128368692Swpaul	E1000_READ_REG(hw, E1000_MGTPDC);
128468692Swpaul	E1000_READ_REG(hw, E1000_MGTPTC);
1285132860Snjl}
1286132860Snjl