xref: /titanic_51/usr/src/uts/common/io/e1000api/e1000_ich8lan.c (revision 42cc51e07cdbcad3b9aca8d9d991fc09b251feb7)
175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi 
3*42cc51e0SRobert 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$*/
3475eba5b6SRobert Mustacchi 
3575eba5b6SRobert Mustacchi /* 82562G 10/100 Network Connection
3675eba5b6SRobert Mustacchi  * 82562G-2 10/100 Network Connection
3775eba5b6SRobert Mustacchi  * 82562GT 10/100 Network Connection
3875eba5b6SRobert Mustacchi  * 82562GT-2 10/100 Network Connection
3975eba5b6SRobert Mustacchi  * 82562V 10/100 Network Connection
4075eba5b6SRobert Mustacchi  * 82562V-2 10/100 Network Connection
4175eba5b6SRobert Mustacchi  * 82566DC-2 Gigabit Network Connection
4275eba5b6SRobert Mustacchi  * 82566DC Gigabit Network Connection
4375eba5b6SRobert Mustacchi  * 82566DM-2 Gigabit Network Connection
4475eba5b6SRobert Mustacchi  * 82566DM Gigabit Network Connection
4575eba5b6SRobert Mustacchi  * 82566MC Gigabit Network Connection
4675eba5b6SRobert Mustacchi  * 82566MM Gigabit Network Connection
4775eba5b6SRobert Mustacchi  * 82567LM Gigabit Network Connection
4875eba5b6SRobert Mustacchi  * 82567LF Gigabit Network Connection
4975eba5b6SRobert Mustacchi  * 82567V Gigabit Network Connection
5075eba5b6SRobert Mustacchi  * 82567LM-2 Gigabit Network Connection
5175eba5b6SRobert Mustacchi  * 82567LF-2 Gigabit Network Connection
5275eba5b6SRobert Mustacchi  * 82567V-2 Gigabit Network Connection
5375eba5b6SRobert Mustacchi  * 82567LF-3 Gigabit Network Connection
5475eba5b6SRobert Mustacchi  * 82567LM-3 Gigabit Network Connection
5575eba5b6SRobert Mustacchi  * 82567LM-4 Gigabit Network Connection
5675eba5b6SRobert Mustacchi  * 82577LM Gigabit Network Connection
5775eba5b6SRobert Mustacchi  * 82577LC Gigabit Network Connection
5875eba5b6SRobert Mustacchi  * 82578DM Gigabit Network Connection
5975eba5b6SRobert Mustacchi  * 82578DC Gigabit Network Connection
6075eba5b6SRobert Mustacchi  * 82579LM Gigabit Network Connection
6175eba5b6SRobert Mustacchi  * 82579V Gigabit Network Connection
62c124a83eSRobert Mustacchi  * Ethernet Connection I217-LM
63c124a83eSRobert Mustacchi  * Ethernet Connection I217-V
64c124a83eSRobert Mustacchi  * Ethernet Connection I218-V
65c124a83eSRobert Mustacchi  * Ethernet Connection I218-LM
66c124a83eSRobert Mustacchi  * Ethernet Connection (2) I218-LM
67c124a83eSRobert Mustacchi  * Ethernet Connection (2) I218-V
68c124a83eSRobert Mustacchi  * Ethernet Connection (3) I218-LM
69c124a83eSRobert Mustacchi  * Ethernet Connection (3) I218-V
7075eba5b6SRobert Mustacchi  */
7175eba5b6SRobert Mustacchi 
7275eba5b6SRobert Mustacchi #include "e1000_api.h"
7375eba5b6SRobert Mustacchi 
7475eba5b6SRobert Mustacchi static s32  e1000_acquire_swflag_ich8lan(struct e1000_hw *hw);
7575eba5b6SRobert Mustacchi static void e1000_release_swflag_ich8lan(struct e1000_hw *hw);
7675eba5b6SRobert Mustacchi static s32  e1000_acquire_nvm_ich8lan(struct e1000_hw *hw);
7775eba5b6SRobert Mustacchi static void e1000_release_nvm_ich8lan(struct e1000_hw *hw);
7875eba5b6SRobert Mustacchi static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);
7975eba5b6SRobert Mustacchi static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw);
80c124a83eSRobert Mustacchi static int  e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index);
81c124a83eSRobert Mustacchi static int  e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index);
82c124a83eSRobert Mustacchi static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw);
8375eba5b6SRobert Mustacchi static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw,
8475eba5b6SRobert Mustacchi 					      u8 *mc_addr_list,
8575eba5b6SRobert Mustacchi 					      u32 mc_addr_count);
8675eba5b6SRobert Mustacchi static s32  e1000_check_reset_block_ich8lan(struct e1000_hw *hw);
8775eba5b6SRobert Mustacchi static s32  e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw);
8875eba5b6SRobert Mustacchi static s32  e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
8975eba5b6SRobert Mustacchi static s32  e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw,
9075eba5b6SRobert Mustacchi 					    bool active);
9175eba5b6SRobert Mustacchi static s32  e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw,
9275eba5b6SRobert Mustacchi 					    bool active);
9375eba5b6SRobert Mustacchi static s32  e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
9475eba5b6SRobert Mustacchi 				   u16 words, u16 *data);
95*42cc51e0SRobert Mustacchi static s32  e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
96*42cc51e0SRobert Mustacchi 			       u16 *data);
9775eba5b6SRobert Mustacchi static s32  e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset,
9875eba5b6SRobert Mustacchi 				    u16 words, u16 *data);
9975eba5b6SRobert Mustacchi static s32  e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw);
10075eba5b6SRobert Mustacchi static s32  e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw);
101*42cc51e0SRobert Mustacchi static s32  e1000_update_nvm_checksum_spt(struct e1000_hw *hw);
10275eba5b6SRobert Mustacchi static s32  e1000_valid_led_default_ich8lan(struct e1000_hw *hw,
10375eba5b6SRobert Mustacchi 					    u16 *data);
10475eba5b6SRobert Mustacchi static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw);
10575eba5b6SRobert Mustacchi static s32  e1000_get_bus_info_ich8lan(struct e1000_hw *hw);
10675eba5b6SRobert Mustacchi static s32  e1000_reset_hw_ich8lan(struct e1000_hw *hw);
10775eba5b6SRobert Mustacchi static s32  e1000_init_hw_ich8lan(struct e1000_hw *hw);
10875eba5b6SRobert Mustacchi static s32  e1000_setup_link_ich8lan(struct e1000_hw *hw);
10975eba5b6SRobert Mustacchi static s32  e1000_setup_copper_link_ich8lan(struct e1000_hw *hw);
11075eba5b6SRobert Mustacchi static s32  e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw);
11175eba5b6SRobert Mustacchi static s32  e1000_get_link_up_info_ich8lan(struct e1000_hw *hw,
11275eba5b6SRobert Mustacchi 					   u16 *speed, u16 *duplex);
11375eba5b6SRobert Mustacchi static s32  e1000_cleanup_led_ich8lan(struct e1000_hw *hw);
11475eba5b6SRobert Mustacchi static s32  e1000_led_on_ich8lan(struct e1000_hw *hw);
11575eba5b6SRobert Mustacchi static s32  e1000_led_off_ich8lan(struct e1000_hw *hw);
11675eba5b6SRobert Mustacchi static s32  e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
11775eba5b6SRobert Mustacchi static s32  e1000_setup_led_pchlan(struct e1000_hw *hw);
11875eba5b6SRobert Mustacchi static s32  e1000_cleanup_led_pchlan(struct e1000_hw *hw);
11975eba5b6SRobert Mustacchi static s32  e1000_led_on_pchlan(struct e1000_hw *hw);
12075eba5b6SRobert Mustacchi static s32  e1000_led_off_pchlan(struct e1000_hw *hw);
12175eba5b6SRobert Mustacchi static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw);
12275eba5b6SRobert Mustacchi static s32  e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank);
12375eba5b6SRobert Mustacchi static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw);
12475eba5b6SRobert Mustacchi static s32  e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw);
12575eba5b6SRobert Mustacchi static s32  e1000_read_flash_byte_ich8lan(struct e1000_hw *hw,
12675eba5b6SRobert Mustacchi 					  u32 offset, u8 *data);
12775eba5b6SRobert Mustacchi static s32  e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
12875eba5b6SRobert Mustacchi 					  u8 size, u16 *data);
129*42cc51e0SRobert Mustacchi static s32  e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
130*42cc51e0SRobert Mustacchi 					    u32 *data);
131*42cc51e0SRobert Mustacchi static s32  e1000_read_flash_dword_ich8lan(struct e1000_hw *hw,
132*42cc51e0SRobert Mustacchi 					   u32 offset, u32 *data);
133*42cc51e0SRobert Mustacchi static s32  e1000_write_flash_data32_ich8lan(struct e1000_hw *hw,
134*42cc51e0SRobert Mustacchi 					     u32 offset, u32 data);
135*42cc51e0SRobert Mustacchi static s32  e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
136*42cc51e0SRobert Mustacchi 						  u32 offset, u32 dword);
13775eba5b6SRobert Mustacchi static s32  e1000_read_flash_word_ich8lan(struct e1000_hw *hw,
13875eba5b6SRobert Mustacchi 					  u32 offset, u16 *data);
13975eba5b6SRobert Mustacchi static s32  e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
14075eba5b6SRobert Mustacchi 						 u32 offset, u8 byte);
14175eba5b6SRobert Mustacchi static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw);
14275eba5b6SRobert Mustacchi static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw);
14375eba5b6SRobert Mustacchi static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw);
14475eba5b6SRobert Mustacchi static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);
14575eba5b6SRobert Mustacchi static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);
14675eba5b6SRobert Mustacchi static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate);
14775eba5b6SRobert Mustacchi static s32 e1000_set_obff_timer_pch_lpt(struct e1000_hw *hw, u32 itr);
14875eba5b6SRobert Mustacchi 
14975eba5b6SRobert Mustacchi /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
15075eba5b6SRobert Mustacchi /* Offset 04h HSFSTS */
15175eba5b6SRobert Mustacchi union ich8_hws_flash_status {
15275eba5b6SRobert Mustacchi 	struct ich8_hsfsts {
15375eba5b6SRobert Mustacchi 		u16 flcdone:1; /* bit 0 Flash Cycle Done */
15475eba5b6SRobert Mustacchi 		u16 flcerr:1; /* bit 1 Flash Cycle Error */
15575eba5b6SRobert Mustacchi 		u16 dael:1; /* bit 2 Direct Access error Log */
15675eba5b6SRobert Mustacchi 		u16 berasesz:2; /* bit 4:3 Sector Erase Size */
15775eba5b6SRobert Mustacchi 		u16 flcinprog:1; /* bit 5 flash cycle in Progress */
15875eba5b6SRobert Mustacchi 		u16 reserved1:2; /* bit 13:6 Reserved */
15975eba5b6SRobert Mustacchi 		u16 reserved2:6; /* bit 13:6 Reserved */
16075eba5b6SRobert Mustacchi 		u16 fldesvalid:1; /* bit 14 Flash Descriptor Valid */
16175eba5b6SRobert Mustacchi 		u16 flockdn:1; /* bit 15 Flash Config Lock-Down */
16275eba5b6SRobert Mustacchi 	} hsf_status;
16375eba5b6SRobert Mustacchi 	u16 regval;
16475eba5b6SRobert Mustacchi };
16575eba5b6SRobert Mustacchi 
16675eba5b6SRobert Mustacchi /* ICH GbE Flash Hardware Sequencing Flash control Register bit breakdown */
16775eba5b6SRobert Mustacchi /* Offset 06h FLCTL */
16875eba5b6SRobert Mustacchi union ich8_hws_flash_ctrl {
16975eba5b6SRobert Mustacchi 	struct ich8_hsflctl {
17075eba5b6SRobert Mustacchi 		u16 flcgo:1;   /* 0 Flash Cycle Go */
17175eba5b6SRobert Mustacchi 		u16 flcycle:2;   /* 2:1 Flash Cycle */
17275eba5b6SRobert Mustacchi 		u16 reserved:5;   /* 7:3 Reserved  */
17375eba5b6SRobert Mustacchi 		u16 fldbcount:2;   /* 9:8 Flash Data Byte Count */
17475eba5b6SRobert Mustacchi 		u16 flockdn:6;   /* 15:10 Reserved */
17575eba5b6SRobert Mustacchi 	} hsf_ctrl;
17675eba5b6SRobert Mustacchi 	u16 regval;
17775eba5b6SRobert Mustacchi };
17875eba5b6SRobert Mustacchi 
17975eba5b6SRobert Mustacchi /* ICH Flash Region Access Permissions */
18075eba5b6SRobert Mustacchi union ich8_hws_flash_regacc {
18175eba5b6SRobert Mustacchi 	struct ich8_flracc {
18275eba5b6SRobert Mustacchi 		u32 grra:8; /* 0:7 GbE region Read Access */
18375eba5b6SRobert Mustacchi 		u32 grwa:8; /* 8:15 GbE region Write Access */
18475eba5b6SRobert Mustacchi 		u32 gmrag:8; /* 23:16 GbE Master Read Access Grant */
18575eba5b6SRobert Mustacchi 		u32 gmwag:8; /* 31:24 GbE Master Write Access Grant */
18675eba5b6SRobert Mustacchi 	} hsf_flregacc;
18775eba5b6SRobert Mustacchi 	u16 regval;
18875eba5b6SRobert Mustacchi };
18975eba5b6SRobert Mustacchi 
19075eba5b6SRobert Mustacchi /**
19175eba5b6SRobert Mustacchi  *  e1000_phy_is_accessible_pchlan - Check if able to access PHY registers
19275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
19375eba5b6SRobert Mustacchi  *
19475eba5b6SRobert Mustacchi  *  Test access to the PHY registers by reading the PHY ID registers.  If
19575eba5b6SRobert Mustacchi  *  the PHY ID is already known (e.g. resume path) compare it with known ID,
19675eba5b6SRobert Mustacchi  *  otherwise assume the read PHY ID is correct if it is valid.
19775eba5b6SRobert Mustacchi  *
19875eba5b6SRobert Mustacchi  *  Assumes the sw/fw/hw semaphore is already acquired.
19975eba5b6SRobert Mustacchi  **/
20075eba5b6SRobert Mustacchi static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)
20175eba5b6SRobert Mustacchi {
20275eba5b6SRobert Mustacchi 	u16 phy_reg = 0;
20375eba5b6SRobert Mustacchi 	u32 phy_id = 0;
204c124a83eSRobert Mustacchi 	s32 ret_val = 0;
20575eba5b6SRobert Mustacchi 	u16 retry_count;
206c124a83eSRobert Mustacchi 	u32 mac_reg = 0;
20775eba5b6SRobert Mustacchi 
20875eba5b6SRobert Mustacchi 	for (retry_count = 0; retry_count < 2; retry_count++) {
20975eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID1, &phy_reg);
21075eba5b6SRobert Mustacchi 		if (ret_val || (phy_reg == 0xFFFF))
21175eba5b6SRobert Mustacchi 			continue;
21275eba5b6SRobert Mustacchi 		phy_id = (u32)(phy_reg << 16);
21375eba5b6SRobert Mustacchi 
21475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg_locked(hw, PHY_ID2, &phy_reg);
21575eba5b6SRobert Mustacchi 		if (ret_val || (phy_reg == 0xFFFF)) {
21675eba5b6SRobert Mustacchi 			phy_id = 0;
21775eba5b6SRobert Mustacchi 			continue;
21875eba5b6SRobert Mustacchi 		}
21975eba5b6SRobert Mustacchi 		phy_id |= (u32)(phy_reg & PHY_REVISION_MASK);
22075eba5b6SRobert Mustacchi 		break;
22175eba5b6SRobert Mustacchi 	}
22275eba5b6SRobert Mustacchi 
22375eba5b6SRobert Mustacchi 	if (hw->phy.id) {
22475eba5b6SRobert Mustacchi 		if  (hw->phy.id == phy_id)
225c124a83eSRobert Mustacchi 			goto out;
22675eba5b6SRobert Mustacchi 	} else if (phy_id) {
22775eba5b6SRobert Mustacchi 		hw->phy.id = phy_id;
22875eba5b6SRobert Mustacchi 		hw->phy.revision = (u32)(phy_reg & ~PHY_REVISION_MASK);
229c124a83eSRobert Mustacchi 		goto out;
23075eba5b6SRobert Mustacchi 	}
23175eba5b6SRobert Mustacchi 
23275eba5b6SRobert Mustacchi 	/* In case the PHY needs to be in mdio slow mode,
23375eba5b6SRobert Mustacchi 	 * set slow mode and try to get the PHY id again.
23475eba5b6SRobert Mustacchi 	 */
235c124a83eSRobert Mustacchi 	if (hw->mac.type < e1000_pch_lpt) {
23675eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
23775eba5b6SRobert Mustacchi 		ret_val = e1000_set_mdio_slow_mode_hv(hw);
23875eba5b6SRobert Mustacchi 		if (!ret_val)
23975eba5b6SRobert Mustacchi 			ret_val = e1000_get_phy_id(hw);
24075eba5b6SRobert Mustacchi 		hw->phy.ops.acquire(hw);
241c124a83eSRobert Mustacchi 	}
24275eba5b6SRobert Mustacchi 
243c124a83eSRobert Mustacchi 	if (ret_val)
244c124a83eSRobert Mustacchi 		return FALSE;
245c124a83eSRobert Mustacchi out:
246*42cc51e0SRobert Mustacchi 	if ((hw->mac.type == e1000_pch_lpt) ||
247*42cc51e0SRobert Mustacchi 	    (hw->mac.type == e1000_pch_spt)) {
248*42cc51e0SRobert Mustacchi 		/* Only unforce SMBus if ME is not active */
249*42cc51e0SRobert Mustacchi 		if (!(E1000_READ_REG(hw, E1000_FWSM) &
250*42cc51e0SRobert Mustacchi 		    E1000_ICH_FWSM_FW_VALID)) {
251c124a83eSRobert Mustacchi 			/* Unforce SMBus mode in PHY */
252c124a83eSRobert Mustacchi 			hw->phy.ops.read_reg_locked(hw, CV_SMB_CTRL, &phy_reg);
253c124a83eSRobert Mustacchi 			phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
254c124a83eSRobert Mustacchi 			hw->phy.ops.write_reg_locked(hw, CV_SMB_CTRL, phy_reg);
255c124a83eSRobert Mustacchi 
256c124a83eSRobert Mustacchi 			/* Unforce SMBus mode in MAC */
257c124a83eSRobert Mustacchi 			mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
258c124a83eSRobert Mustacchi 			mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
259c124a83eSRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
260c124a83eSRobert Mustacchi 		}
261*42cc51e0SRobert Mustacchi 	}
262c124a83eSRobert Mustacchi 
263c124a83eSRobert Mustacchi 	return TRUE;
264c124a83eSRobert Mustacchi }
265c124a83eSRobert Mustacchi 
266c124a83eSRobert Mustacchi /**
267c124a83eSRobert Mustacchi  *  e1000_toggle_lanphypc_pch_lpt - toggle the LANPHYPC pin value
268c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
269c124a83eSRobert Mustacchi  *
270c124a83eSRobert Mustacchi  *  Toggling the LANPHYPC pin value fully power-cycles the PHY and is
271c124a83eSRobert Mustacchi  *  used to reset the PHY to a quiescent state when necessary.
272c124a83eSRobert Mustacchi  **/
273c124a83eSRobert Mustacchi static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw)
274c124a83eSRobert Mustacchi {
275c124a83eSRobert Mustacchi 	u32 mac_reg;
276c124a83eSRobert Mustacchi 
277c124a83eSRobert Mustacchi 	DEBUGFUNC("e1000_toggle_lanphypc_pch_lpt");
278c124a83eSRobert Mustacchi 
279c124a83eSRobert Mustacchi 	/* Set Phy Config Counter to 50msec */
280c124a83eSRobert Mustacchi 	mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM3);
281c124a83eSRobert Mustacchi 	mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
282c124a83eSRobert Mustacchi 	mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
283c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_FEXTNVM3, mac_reg);
284c124a83eSRobert Mustacchi 
285c124a83eSRobert Mustacchi 	/* Toggle LANPHYPC Value bit */
286c124a83eSRobert Mustacchi 	mac_reg = E1000_READ_REG(hw, E1000_CTRL);
287c124a83eSRobert Mustacchi 	mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE;
288c124a83eSRobert Mustacchi 	mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE;
289c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
290c124a83eSRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
291c124a83eSRobert Mustacchi 	usec_delay(10);
292c124a83eSRobert Mustacchi 	mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE;
293c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, mac_reg);
294c124a83eSRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
295c124a83eSRobert Mustacchi 
296c124a83eSRobert Mustacchi 	if (hw->mac.type < e1000_pch_lpt) {
297c124a83eSRobert Mustacchi 		msec_delay(50);
298c124a83eSRobert Mustacchi 	} else {
299c124a83eSRobert Mustacchi 		u16 count = 20;
300c124a83eSRobert Mustacchi 
301c124a83eSRobert Mustacchi 		do {
302c124a83eSRobert Mustacchi 			msec_delay(5);
303c124a83eSRobert Mustacchi 		} while (!(E1000_READ_REG(hw, E1000_CTRL_EXT) &
304c124a83eSRobert Mustacchi 			   E1000_CTRL_EXT_LPCD) && count--);
305c124a83eSRobert Mustacchi 
306c124a83eSRobert Mustacchi 		msec_delay(30);
307c124a83eSRobert Mustacchi 	}
30875eba5b6SRobert Mustacchi }
30975eba5b6SRobert Mustacchi 
31075eba5b6SRobert Mustacchi /**
31175eba5b6SRobert Mustacchi  *  e1000_init_phy_workarounds_pchlan - PHY initialization workarounds
31275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
31375eba5b6SRobert Mustacchi  *
31475eba5b6SRobert Mustacchi  *  Workarounds/flow necessary for PHY initialization during driver load
31575eba5b6SRobert Mustacchi  *  and resume paths.
31675eba5b6SRobert Mustacchi  **/
31775eba5b6SRobert Mustacchi static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)
31875eba5b6SRobert Mustacchi {
31975eba5b6SRobert Mustacchi 	u32 mac_reg, fwsm = E1000_READ_REG(hw, E1000_FWSM);
32075eba5b6SRobert Mustacchi 	s32 ret_val;
32175eba5b6SRobert Mustacchi 
32275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_phy_workarounds_pchlan");
32375eba5b6SRobert Mustacchi 
32475eba5b6SRobert Mustacchi 	/* Gate automatic PHY configuration by hardware on managed and
32575eba5b6SRobert Mustacchi 	 * non-managed 82579 and newer adapters.
32675eba5b6SRobert Mustacchi 	 */
32775eba5b6SRobert Mustacchi 	e1000_gate_hw_phy_config_ich8lan(hw, TRUE);
32875eba5b6SRobert Mustacchi 
329c124a83eSRobert Mustacchi 	/* It is not possible to be certain of the current state of ULP
330c124a83eSRobert Mustacchi 	 * so forcibly disable it.
331c124a83eSRobert Mustacchi 	 */
332c124a83eSRobert Mustacchi 	hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_unknown;
333c124a83eSRobert Mustacchi 	e1000_disable_ulp_lpt_lp(hw, TRUE);
334c124a83eSRobert Mustacchi 
33575eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
33675eba5b6SRobert Mustacchi 	if (ret_val) {
33775eba5b6SRobert Mustacchi 		DEBUGOUT("Failed to initialize PHY flow\n");
33875eba5b6SRobert Mustacchi 		goto out;
33975eba5b6SRobert Mustacchi 	}
34075eba5b6SRobert Mustacchi 
34175eba5b6SRobert Mustacchi 	/* The MAC-PHY interconnect may be in SMBus mode.  If the PHY is
34275eba5b6SRobert Mustacchi 	 * inaccessible and resetting the PHY is not blocked, toggle the
34375eba5b6SRobert Mustacchi 	 * LANPHYPC Value bit to force the interconnect to PCIe mode.
34475eba5b6SRobert Mustacchi 	 */
34575eba5b6SRobert Mustacchi 	switch (hw->mac.type) {
34675eba5b6SRobert Mustacchi 	case e1000_pch_lpt:
347*42cc51e0SRobert Mustacchi 	case e1000_pch_spt:
34875eba5b6SRobert Mustacchi 		if (e1000_phy_is_accessible_pchlan(hw))
34975eba5b6SRobert Mustacchi 			break;
35075eba5b6SRobert Mustacchi 
35175eba5b6SRobert Mustacchi 		/* Before toggling LANPHYPC, see if PHY is accessible by
35275eba5b6SRobert Mustacchi 		 * forcing MAC to SMBus mode first.
35375eba5b6SRobert Mustacchi 		 */
35475eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
35575eba5b6SRobert Mustacchi 		mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
35675eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
35775eba5b6SRobert Mustacchi 
358c124a83eSRobert Mustacchi 		/* Wait 50 milliseconds for MAC to finish any retries
359c124a83eSRobert Mustacchi 		 * that it might be trying to perform from previous
360c124a83eSRobert Mustacchi 		 * attempts to acknowledge any phy read requests.
361c124a83eSRobert Mustacchi 		 */
362c124a83eSRobert Mustacchi 		 msec_delay(50);
363c124a83eSRobert Mustacchi 
36475eba5b6SRobert Mustacchi 		/* fall-through */
36575eba5b6SRobert Mustacchi 	case e1000_pch2lan:
366c124a83eSRobert Mustacchi 		if (e1000_phy_is_accessible_pchlan(hw))
36775eba5b6SRobert Mustacchi 			break;
36875eba5b6SRobert Mustacchi 
36975eba5b6SRobert Mustacchi 		/* fall-through */
37075eba5b6SRobert Mustacchi 	case e1000_pchlan:
37175eba5b6SRobert Mustacchi 		if ((hw->mac.type == e1000_pchlan) &&
37275eba5b6SRobert Mustacchi 		    (fwsm & E1000_ICH_FWSM_FW_VALID))
37375eba5b6SRobert Mustacchi 			break;
37475eba5b6SRobert Mustacchi 
37575eba5b6SRobert Mustacchi 		if (hw->phy.ops.check_reset_block(hw)) {
37675eba5b6SRobert Mustacchi 			DEBUGOUT("Required LANPHYPC toggle blocked by ME\n");
377c124a83eSRobert Mustacchi 			ret_val = -E1000_ERR_PHY;
37875eba5b6SRobert Mustacchi 			break;
37975eba5b6SRobert Mustacchi 		}
38075eba5b6SRobert Mustacchi 
381c124a83eSRobert Mustacchi 		/* Toggle LANPHYPC Value bit */
382c124a83eSRobert Mustacchi 		e1000_toggle_lanphypc_pch_lpt(hw);
383c124a83eSRobert Mustacchi 		if (hw->mac.type >= e1000_pch_lpt) {
384c124a83eSRobert Mustacchi 			if (e1000_phy_is_accessible_pchlan(hw))
385c124a83eSRobert Mustacchi 				break;
38675eba5b6SRobert Mustacchi 
38775eba5b6SRobert Mustacchi 			/* Toggling LANPHYPC brings the PHY out of SMBus mode
388c124a83eSRobert Mustacchi 			 * so ensure that the MAC is also out of SMBus mode
38975eba5b6SRobert Mustacchi 			 */
39075eba5b6SRobert Mustacchi 			mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
39175eba5b6SRobert Mustacchi 			mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
39275eba5b6SRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
39375eba5b6SRobert Mustacchi 
394c124a83eSRobert Mustacchi 			if (e1000_phy_is_accessible_pchlan(hw))
395c124a83eSRobert Mustacchi 				break;
396c124a83eSRobert Mustacchi 
397c124a83eSRobert Mustacchi 			ret_val = -E1000_ERR_PHY;
39875eba5b6SRobert Mustacchi 		}
39975eba5b6SRobert Mustacchi 		break;
40075eba5b6SRobert Mustacchi 	default:
40175eba5b6SRobert Mustacchi 		break;
40275eba5b6SRobert Mustacchi 	}
40375eba5b6SRobert Mustacchi 
40475eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
405c124a83eSRobert Mustacchi 	if (!ret_val) {
406c124a83eSRobert Mustacchi 
407c124a83eSRobert Mustacchi 		/* Check to see if able to reset PHY.  Print error if not */
408c124a83eSRobert Mustacchi 		if (hw->phy.ops.check_reset_block(hw)) {
409c124a83eSRobert Mustacchi 			ERROR_REPORT("Reset blocked by ME\n");
410c124a83eSRobert Mustacchi 			goto out;
411c124a83eSRobert Mustacchi 		}
41275eba5b6SRobert Mustacchi 
41375eba5b6SRobert Mustacchi 		/* Reset the PHY before any access to it.  Doing so, ensures
41475eba5b6SRobert Mustacchi 		 * that the PHY is in a known good state before we read/write
41575eba5b6SRobert Mustacchi 		 * PHY registers.  The generic reset is sufficient here,
41675eba5b6SRobert Mustacchi 		 * because we haven't determined the PHY type yet.
41775eba5b6SRobert Mustacchi 		 */
41875eba5b6SRobert Mustacchi 		ret_val = e1000_phy_hw_reset_generic(hw);
419c124a83eSRobert Mustacchi 		if (ret_val)
420c124a83eSRobert Mustacchi 			goto out;
421c124a83eSRobert Mustacchi 
422c124a83eSRobert Mustacchi 		/* On a successful reset, possibly need to wait for the PHY
423c124a83eSRobert Mustacchi 		 * to quiesce to an accessible state before returning control
424c124a83eSRobert Mustacchi 		 * to the calling function.  If the PHY does not quiesce, then
425c124a83eSRobert Mustacchi 		 * return E1000E_BLK_PHY_RESET, as this is the condition that
426c124a83eSRobert Mustacchi 		 *  the PHY is in.
427c124a83eSRobert Mustacchi 		 */
428c124a83eSRobert Mustacchi 		ret_val = hw->phy.ops.check_reset_block(hw);
429c124a83eSRobert Mustacchi 		if (ret_val)
430c124a83eSRobert Mustacchi 			ERROR_REPORT("ME blocked access to PHY after reset\n");
431c124a83eSRobert Mustacchi 	}
43275eba5b6SRobert Mustacchi 
43375eba5b6SRobert Mustacchi out:
43475eba5b6SRobert Mustacchi 	/* Ungate automatic PHY configuration on non-managed 82579 */
43575eba5b6SRobert Mustacchi 	if ((hw->mac.type == e1000_pch2lan) &&
43675eba5b6SRobert Mustacchi 	    !(fwsm & E1000_ICH_FWSM_FW_VALID)) {
43775eba5b6SRobert Mustacchi 		msec_delay(10);
43875eba5b6SRobert Mustacchi 		e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
43975eba5b6SRobert Mustacchi 	}
44075eba5b6SRobert Mustacchi 
44175eba5b6SRobert Mustacchi 	return ret_val;
44275eba5b6SRobert Mustacchi }
44375eba5b6SRobert Mustacchi 
44475eba5b6SRobert Mustacchi /**
44575eba5b6SRobert Mustacchi  *  e1000_init_phy_params_pchlan - Initialize PHY function pointers
44675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
44775eba5b6SRobert Mustacchi  *
44875eba5b6SRobert Mustacchi  *  Initialize family-specific PHY parameters and function pointers.
44975eba5b6SRobert Mustacchi  **/
45075eba5b6SRobert Mustacchi static s32 e1000_init_phy_params_pchlan(struct e1000_hw *hw)
45175eba5b6SRobert Mustacchi {
45275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
45375eba5b6SRobert Mustacchi 	s32 ret_val;
45475eba5b6SRobert Mustacchi 
45575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_phy_params_pchlan");
45675eba5b6SRobert Mustacchi 
45775eba5b6SRobert Mustacchi 	phy->addr		= 1;
45875eba5b6SRobert Mustacchi 	phy->reset_delay_us	= 100;
45975eba5b6SRobert Mustacchi 
46075eba5b6SRobert Mustacchi 	phy->ops.acquire	= e1000_acquire_swflag_ich8lan;
46175eba5b6SRobert Mustacchi 	phy->ops.check_reset_block = e1000_check_reset_block_ich8lan;
46275eba5b6SRobert Mustacchi 	phy->ops.get_cfg_done	= e1000_get_cfg_done_ich8lan;
46375eba5b6SRobert Mustacchi 	phy->ops.set_page	= e1000_set_page_igp;
46475eba5b6SRobert Mustacchi 	phy->ops.read_reg	= e1000_read_phy_reg_hv;
46575eba5b6SRobert Mustacchi 	phy->ops.read_reg_locked = e1000_read_phy_reg_hv_locked;
46675eba5b6SRobert Mustacchi 	phy->ops.read_reg_page	= e1000_read_phy_reg_page_hv;
46775eba5b6SRobert Mustacchi 	phy->ops.release	= e1000_release_swflag_ich8lan;
46875eba5b6SRobert Mustacchi 	phy->ops.reset		= e1000_phy_hw_reset_ich8lan;
46975eba5b6SRobert Mustacchi 	phy->ops.set_d0_lplu_state = e1000_set_lplu_state_pchlan;
47075eba5b6SRobert Mustacchi 	phy->ops.set_d3_lplu_state = e1000_set_lplu_state_pchlan;
47175eba5b6SRobert Mustacchi 	phy->ops.write_reg	= e1000_write_phy_reg_hv;
47275eba5b6SRobert Mustacchi 	phy->ops.write_reg_locked = e1000_write_phy_reg_hv_locked;
47375eba5b6SRobert Mustacchi 	phy->ops.write_reg_page	= e1000_write_phy_reg_page_hv;
47475eba5b6SRobert Mustacchi 	phy->ops.power_up	= e1000_power_up_phy_copper;
47575eba5b6SRobert Mustacchi 	phy->ops.power_down	= e1000_power_down_phy_copper_ich8lan;
47675eba5b6SRobert Mustacchi 	phy->autoneg_mask	= AUTONEG_ADVERTISE_SPEED_DEFAULT;
47775eba5b6SRobert Mustacchi 
47875eba5b6SRobert Mustacchi 	phy->id = e1000_phy_unknown;
47975eba5b6SRobert Mustacchi 
48075eba5b6SRobert Mustacchi 	ret_val = e1000_init_phy_workarounds_pchlan(hw);
48175eba5b6SRobert Mustacchi 	if (ret_val)
48275eba5b6SRobert Mustacchi 		return ret_val;
48375eba5b6SRobert Mustacchi 
48475eba5b6SRobert Mustacchi 	if (phy->id == e1000_phy_unknown)
48575eba5b6SRobert Mustacchi 		switch (hw->mac.type) {
48675eba5b6SRobert Mustacchi 		default:
48775eba5b6SRobert Mustacchi 			ret_val = e1000_get_phy_id(hw);
48875eba5b6SRobert Mustacchi 			if (ret_val)
48975eba5b6SRobert Mustacchi 				return ret_val;
49075eba5b6SRobert Mustacchi 			if ((phy->id != 0) && (phy->id != PHY_REVISION_MASK))
49175eba5b6SRobert Mustacchi 				break;
49275eba5b6SRobert Mustacchi 			/* fall-through */
49375eba5b6SRobert Mustacchi 		case e1000_pch2lan:
49475eba5b6SRobert Mustacchi 		case e1000_pch_lpt:
495*42cc51e0SRobert Mustacchi 		case e1000_pch_spt:
49675eba5b6SRobert Mustacchi 			/* In case the PHY needs to be in mdio slow mode,
49775eba5b6SRobert Mustacchi 			 * set slow mode and try to get the PHY id again.
49875eba5b6SRobert Mustacchi 			 */
49975eba5b6SRobert Mustacchi 			ret_val = e1000_set_mdio_slow_mode_hv(hw);
50075eba5b6SRobert Mustacchi 			if (ret_val)
50175eba5b6SRobert Mustacchi 				return ret_val;
50275eba5b6SRobert Mustacchi 			ret_val = e1000_get_phy_id(hw);
50375eba5b6SRobert Mustacchi 			if (ret_val)
50475eba5b6SRobert Mustacchi 				return ret_val;
50575eba5b6SRobert Mustacchi 			break;
50675eba5b6SRobert Mustacchi 		}
50775eba5b6SRobert Mustacchi 	phy->type = e1000_get_phy_type_from_id(phy->id);
50875eba5b6SRobert Mustacchi 
50975eba5b6SRobert Mustacchi 	switch (phy->type) {
51075eba5b6SRobert Mustacchi 	case e1000_phy_82577:
51175eba5b6SRobert Mustacchi 	case e1000_phy_82579:
51275eba5b6SRobert Mustacchi 	case e1000_phy_i217:
51375eba5b6SRobert Mustacchi 		phy->ops.check_polarity = e1000_check_polarity_82577;
51475eba5b6SRobert Mustacchi 		phy->ops.force_speed_duplex =
51575eba5b6SRobert Mustacchi 			e1000_phy_force_speed_duplex_82577;
51675eba5b6SRobert Mustacchi 		phy->ops.get_cable_length = e1000_get_cable_length_82577;
51775eba5b6SRobert Mustacchi 		phy->ops.get_info = e1000_get_phy_info_82577;
51875eba5b6SRobert Mustacchi 		phy->ops.commit = e1000_phy_sw_reset_generic;
51975eba5b6SRobert Mustacchi 		break;
52075eba5b6SRobert Mustacchi 	case e1000_phy_82578:
52175eba5b6SRobert Mustacchi 		phy->ops.check_polarity = e1000_check_polarity_m88;
52275eba5b6SRobert Mustacchi 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
52375eba5b6SRobert Mustacchi 		phy->ops.get_cable_length = e1000_get_cable_length_m88;
52475eba5b6SRobert Mustacchi 		phy->ops.get_info = e1000_get_phy_info_m88;
52575eba5b6SRobert Mustacchi 		break;
52675eba5b6SRobert Mustacchi 	default:
52775eba5b6SRobert Mustacchi 		ret_val = -E1000_ERR_PHY;
52875eba5b6SRobert Mustacchi 		break;
52975eba5b6SRobert Mustacchi 	}
53075eba5b6SRobert Mustacchi 
53175eba5b6SRobert Mustacchi 	return ret_val;
53275eba5b6SRobert Mustacchi }
53375eba5b6SRobert Mustacchi 
53475eba5b6SRobert Mustacchi /**
53575eba5b6SRobert Mustacchi  *  e1000_init_phy_params_ich8lan - Initialize PHY function pointers
53675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
53775eba5b6SRobert Mustacchi  *
53875eba5b6SRobert Mustacchi  *  Initialize family-specific PHY parameters and function pointers.
53975eba5b6SRobert Mustacchi  **/
54075eba5b6SRobert Mustacchi static s32 e1000_init_phy_params_ich8lan(struct e1000_hw *hw)
54175eba5b6SRobert Mustacchi {
54275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
54375eba5b6SRobert Mustacchi 	s32 ret_val;
54475eba5b6SRobert Mustacchi 	u16 i = 0;
54575eba5b6SRobert Mustacchi 
54675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_phy_params_ich8lan");
54775eba5b6SRobert Mustacchi 
54875eba5b6SRobert Mustacchi 	phy->addr		= 1;
54975eba5b6SRobert Mustacchi 	phy->reset_delay_us	= 100;
55075eba5b6SRobert Mustacchi 
55175eba5b6SRobert Mustacchi 	phy->ops.acquire	= e1000_acquire_swflag_ich8lan;
55275eba5b6SRobert Mustacchi 	phy->ops.check_reset_block = e1000_check_reset_block_ich8lan;
55375eba5b6SRobert Mustacchi 	phy->ops.get_cable_length = e1000_get_cable_length_igp_2;
55475eba5b6SRobert Mustacchi 	phy->ops.get_cfg_done	= e1000_get_cfg_done_ich8lan;
55575eba5b6SRobert Mustacchi 	phy->ops.read_reg	= e1000_read_phy_reg_igp;
55675eba5b6SRobert Mustacchi 	phy->ops.release	= e1000_release_swflag_ich8lan;
55775eba5b6SRobert Mustacchi 	phy->ops.reset		= e1000_phy_hw_reset_ich8lan;
55875eba5b6SRobert Mustacchi 	phy->ops.set_d0_lplu_state = e1000_set_d0_lplu_state_ich8lan;
55975eba5b6SRobert Mustacchi 	phy->ops.set_d3_lplu_state = e1000_set_d3_lplu_state_ich8lan;
56075eba5b6SRobert Mustacchi 	phy->ops.write_reg	= e1000_write_phy_reg_igp;
56175eba5b6SRobert Mustacchi 	phy->ops.power_up	= e1000_power_up_phy_copper;
56275eba5b6SRobert Mustacchi 	phy->ops.power_down	= e1000_power_down_phy_copper_ich8lan;
56375eba5b6SRobert Mustacchi 
56475eba5b6SRobert Mustacchi 	/* We may need to do this twice - once for IGP and if that fails,
56575eba5b6SRobert Mustacchi 	 * we'll set BM func pointers and try again
56675eba5b6SRobert Mustacchi 	 */
56775eba5b6SRobert Mustacchi 	ret_val = e1000_determine_phy_address(hw);
56875eba5b6SRobert Mustacchi 	if (ret_val) {
56975eba5b6SRobert Mustacchi 		phy->ops.write_reg = e1000_write_phy_reg_bm;
57075eba5b6SRobert Mustacchi 		phy->ops.read_reg  = e1000_read_phy_reg_bm;
57175eba5b6SRobert Mustacchi 		ret_val = e1000_determine_phy_address(hw);
57275eba5b6SRobert Mustacchi 		if (ret_val) {
57375eba5b6SRobert Mustacchi 			DEBUGOUT("Cannot determine PHY addr. Erroring out\n");
57475eba5b6SRobert Mustacchi 			return ret_val;
57575eba5b6SRobert Mustacchi 		}
57675eba5b6SRobert Mustacchi 	}
57775eba5b6SRobert Mustacchi 
57875eba5b6SRobert Mustacchi 	phy->id = 0;
57975eba5b6SRobert Mustacchi 	while ((e1000_phy_unknown == e1000_get_phy_type_from_id(phy->id)) &&
58075eba5b6SRobert Mustacchi 	       (i++ < 100)) {
58175eba5b6SRobert Mustacchi 		msec_delay(1);
58275eba5b6SRobert Mustacchi 		ret_val = e1000_get_phy_id(hw);
58375eba5b6SRobert Mustacchi 		if (ret_val)
58475eba5b6SRobert Mustacchi 			return ret_val;
58575eba5b6SRobert Mustacchi 	}
58675eba5b6SRobert Mustacchi 
58775eba5b6SRobert Mustacchi 	/* Verify phy id */
58875eba5b6SRobert Mustacchi 	switch (phy->id) {
58975eba5b6SRobert Mustacchi 	case IGP03E1000_E_PHY_ID:
59075eba5b6SRobert Mustacchi 		phy->type = e1000_phy_igp_3;
59175eba5b6SRobert Mustacchi 		phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
59275eba5b6SRobert Mustacchi 		phy->ops.read_reg_locked = e1000_read_phy_reg_igp_locked;
59375eba5b6SRobert Mustacchi 		phy->ops.write_reg_locked = e1000_write_phy_reg_igp_locked;
59475eba5b6SRobert Mustacchi 		phy->ops.get_info = e1000_get_phy_info_igp;
59575eba5b6SRobert Mustacchi 		phy->ops.check_polarity = e1000_check_polarity_igp;
59675eba5b6SRobert Mustacchi 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_igp;
59775eba5b6SRobert Mustacchi 		break;
59875eba5b6SRobert Mustacchi 	case IFE_E_PHY_ID:
59975eba5b6SRobert Mustacchi 	case IFE_PLUS_E_PHY_ID:
60075eba5b6SRobert Mustacchi 	case IFE_C_E_PHY_ID:
60175eba5b6SRobert Mustacchi 		phy->type = e1000_phy_ife;
60275eba5b6SRobert Mustacchi 		phy->autoneg_mask = E1000_ALL_NOT_GIG;
60375eba5b6SRobert Mustacchi 		phy->ops.get_info = e1000_get_phy_info_ife;
60475eba5b6SRobert Mustacchi 		phy->ops.check_polarity = e1000_check_polarity_ife;
60575eba5b6SRobert Mustacchi 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_ife;
60675eba5b6SRobert Mustacchi 		break;
60775eba5b6SRobert Mustacchi 	case BME1000_E_PHY_ID:
60875eba5b6SRobert Mustacchi 		phy->type = e1000_phy_bm;
60975eba5b6SRobert Mustacchi 		phy->autoneg_mask = AUTONEG_ADVERTISE_SPEED_DEFAULT;
61075eba5b6SRobert Mustacchi 		phy->ops.read_reg = e1000_read_phy_reg_bm;
61175eba5b6SRobert Mustacchi 		phy->ops.write_reg = e1000_write_phy_reg_bm;
61275eba5b6SRobert Mustacchi 		phy->ops.commit = e1000_phy_sw_reset_generic;
61375eba5b6SRobert Mustacchi 		phy->ops.get_info = e1000_get_phy_info_m88;
61475eba5b6SRobert Mustacchi 		phy->ops.check_polarity = e1000_check_polarity_m88;
61575eba5b6SRobert Mustacchi 		phy->ops.force_speed_duplex = e1000_phy_force_speed_duplex_m88;
61675eba5b6SRobert Mustacchi 		break;
61775eba5b6SRobert Mustacchi 	default:
61875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
61975eba5b6SRobert Mustacchi 		break;
62075eba5b6SRobert Mustacchi 	}
62175eba5b6SRobert Mustacchi 
62275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
62375eba5b6SRobert Mustacchi }
62475eba5b6SRobert Mustacchi 
62575eba5b6SRobert Mustacchi /**
62675eba5b6SRobert Mustacchi  *  e1000_init_nvm_params_ich8lan - Initialize NVM function pointers
62775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
62875eba5b6SRobert Mustacchi  *
62975eba5b6SRobert Mustacchi  *  Initialize family-specific NVM parameters and function
63075eba5b6SRobert Mustacchi  *  pointers.
63175eba5b6SRobert Mustacchi  **/
63275eba5b6SRobert Mustacchi static s32 e1000_init_nvm_params_ich8lan(struct e1000_hw *hw)
63375eba5b6SRobert Mustacchi {
63475eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
63575eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
63675eba5b6SRobert Mustacchi 	u32 gfpreg, sector_base_addr, sector_end_addr;
63775eba5b6SRobert Mustacchi 	u16 i;
638*42cc51e0SRobert Mustacchi 	u32 nvm_size;
63975eba5b6SRobert Mustacchi 
64075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_nvm_params_ich8lan");
64175eba5b6SRobert Mustacchi 
642c124a83eSRobert Mustacchi 	nvm->type = e1000_nvm_flash_sw;
643*42cc51e0SRobert Mustacchi 
644*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt) {
645*42cc51e0SRobert Mustacchi 		/* in SPT, gfpreg doesn't exist. NVM size is taken from the
646*42cc51e0SRobert Mustacchi 		 * STRAP register. This is because in SPT the GbE Flash region
647*42cc51e0SRobert Mustacchi 		 * is no longer accessed through the flash registers. Instead,
648*42cc51e0SRobert Mustacchi 		 * the mechanism has changed, and the Flash region access
649*42cc51e0SRobert Mustacchi 		 * registers are now implemented in GbE memory space.
650*42cc51e0SRobert Mustacchi 		 */
651*42cc51e0SRobert Mustacchi 		nvm->flash_base_addr = 0;
652*42cc51e0SRobert Mustacchi 		nvm_size =
653*42cc51e0SRobert Mustacchi 		    (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1)
654*42cc51e0SRobert Mustacchi 		    * NVM_SIZE_MULTIPLIER;
655*42cc51e0SRobert Mustacchi 		nvm->flash_bank_size = nvm_size / 2;
656*42cc51e0SRobert Mustacchi 		/* Adjust to word count */
657*42cc51e0SRobert Mustacchi 		nvm->flash_bank_size /= sizeof(u16);
658*42cc51e0SRobert Mustacchi 		/* Set the base address for flash register access */
659*42cc51e0SRobert Mustacchi 		hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR;
660*42cc51e0SRobert Mustacchi 	} else {
661*42cc51e0SRobert Mustacchi 		/* Can't read flash registers if register set isn't mapped. */
66275eba5b6SRobert Mustacchi 		if (!hw->flash_address) {
66375eba5b6SRobert Mustacchi 			DEBUGOUT("ERROR: Flash registers not mapped\n");
66475eba5b6SRobert Mustacchi 			return -E1000_ERR_CONFIG;
66575eba5b6SRobert Mustacchi 		}
66675eba5b6SRobert Mustacchi 
66775eba5b6SRobert Mustacchi 		gfpreg = E1000_READ_FLASH_REG(hw, ICH_FLASH_GFPREG);
66875eba5b6SRobert Mustacchi 
66975eba5b6SRobert Mustacchi 		/* sector_X_addr is a "sector"-aligned address (4096 bytes)
67075eba5b6SRobert Mustacchi 		 * Add 1 to sector_end_addr since this sector is included in
67175eba5b6SRobert Mustacchi 		 * the overall size.
67275eba5b6SRobert Mustacchi 		 */
67375eba5b6SRobert Mustacchi 		sector_base_addr = gfpreg & FLASH_GFPREG_BASE_MASK;
67475eba5b6SRobert Mustacchi 		sector_end_addr = ((gfpreg >> 16) & FLASH_GFPREG_BASE_MASK) + 1;
67575eba5b6SRobert Mustacchi 
67675eba5b6SRobert Mustacchi 		/* flash_base_addr is byte-aligned */
677*42cc51e0SRobert Mustacchi 		nvm->flash_base_addr = sector_base_addr
678*42cc51e0SRobert Mustacchi 				       << FLASH_SECTOR_ADDR_SHIFT;
67975eba5b6SRobert Mustacchi 
68075eba5b6SRobert Mustacchi 		/* find total size of the NVM, then cut in half since the total
68175eba5b6SRobert Mustacchi 		 * size represents two separate NVM banks.
68275eba5b6SRobert Mustacchi 		 */
683c124a83eSRobert Mustacchi 		nvm->flash_bank_size = ((sector_end_addr - sector_base_addr)
684c124a83eSRobert Mustacchi 					<< FLASH_SECTOR_ADDR_SHIFT);
68575eba5b6SRobert Mustacchi 		nvm->flash_bank_size /= 2;
68675eba5b6SRobert Mustacchi 		/* Adjust to word count */
68775eba5b6SRobert Mustacchi 		nvm->flash_bank_size /= sizeof(u16);
688*42cc51e0SRobert Mustacchi 	}
68975eba5b6SRobert Mustacchi 
69075eba5b6SRobert Mustacchi 	nvm->word_size = E1000_SHADOW_RAM_WORDS;
69175eba5b6SRobert Mustacchi 
69275eba5b6SRobert Mustacchi 	/* Clear shadow ram */
69375eba5b6SRobert Mustacchi 	for (i = 0; i < nvm->word_size; i++) {
69475eba5b6SRobert Mustacchi 		dev_spec->shadow_ram[i].modified = FALSE;
69575eba5b6SRobert Mustacchi 		dev_spec->shadow_ram[i].value    = 0xFFFF;
69675eba5b6SRobert Mustacchi 	}
69775eba5b6SRobert Mustacchi 
69875eba5b6SRobert Mustacchi 	E1000_MUTEX_INIT(&dev_spec->nvm_mutex);
69975eba5b6SRobert Mustacchi 	E1000_MUTEX_INIT(&dev_spec->swflag_mutex);
70075eba5b6SRobert Mustacchi 
70175eba5b6SRobert Mustacchi 	/* Function Pointers */
70275eba5b6SRobert Mustacchi 	nvm->ops.acquire	= e1000_acquire_nvm_ich8lan;
70375eba5b6SRobert Mustacchi 	nvm->ops.release	= e1000_release_nvm_ich8lan;
704*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt) {
705*42cc51e0SRobert Mustacchi 		nvm->ops.read	= e1000_read_nvm_spt;
706*42cc51e0SRobert Mustacchi 		nvm->ops.update	= e1000_update_nvm_checksum_spt;
707*42cc51e0SRobert Mustacchi 	} else {
70875eba5b6SRobert Mustacchi 		nvm->ops.read	= e1000_read_nvm_ich8lan;
70975eba5b6SRobert Mustacchi 		nvm->ops.update	= e1000_update_nvm_checksum_ich8lan;
710*42cc51e0SRobert Mustacchi 	}
71175eba5b6SRobert Mustacchi 	nvm->ops.valid_led_default = e1000_valid_led_default_ich8lan;
71275eba5b6SRobert Mustacchi 	nvm->ops.validate	= e1000_validate_nvm_checksum_ich8lan;
71375eba5b6SRobert Mustacchi 	nvm->ops.write		= e1000_write_nvm_ich8lan;
71475eba5b6SRobert Mustacchi 
71575eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
71675eba5b6SRobert Mustacchi }
71775eba5b6SRobert Mustacchi 
71875eba5b6SRobert Mustacchi /**
71975eba5b6SRobert Mustacchi  *  e1000_init_mac_params_ich8lan - Initialize MAC function pointers
72075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
72175eba5b6SRobert Mustacchi  *
72275eba5b6SRobert Mustacchi  *  Initialize family-specific MAC parameters and function
72375eba5b6SRobert Mustacchi  *  pointers.
72475eba5b6SRobert Mustacchi  **/
72575eba5b6SRobert Mustacchi static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)
72675eba5b6SRobert Mustacchi {
72775eba5b6SRobert Mustacchi 	struct e1000_mac_info *mac = &hw->mac;
72875eba5b6SRobert Mustacchi 
72975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_mac_params_ich8lan");
73075eba5b6SRobert Mustacchi 
73175eba5b6SRobert Mustacchi 	/* Set media type function pointer */
73275eba5b6SRobert Mustacchi 	hw->phy.media_type = e1000_media_type_copper;
73375eba5b6SRobert Mustacchi 
73475eba5b6SRobert Mustacchi 	/* Set mta register count */
73575eba5b6SRobert Mustacchi 	mac->mta_reg_count = 32;
73675eba5b6SRobert Mustacchi 	/* Set rar entry count */
73775eba5b6SRobert Mustacchi 	mac->rar_entry_count = E1000_ICH_RAR_ENTRIES;
73875eba5b6SRobert Mustacchi 	if (mac->type == e1000_ich8lan)
73975eba5b6SRobert Mustacchi 		mac->rar_entry_count--;
74075eba5b6SRobert Mustacchi 	/* Set if part includes ASF firmware */
74175eba5b6SRobert Mustacchi 	mac->asf_firmware_present = TRUE;
74275eba5b6SRobert Mustacchi 	/* FWSM register */
74375eba5b6SRobert Mustacchi 	mac->has_fwsm = TRUE;
74475eba5b6SRobert Mustacchi 	/* ARC subsystem not supported */
74575eba5b6SRobert Mustacchi 	mac->arc_subsystem_valid = FALSE;
74675eba5b6SRobert Mustacchi 	/* Adaptive IFS supported */
74775eba5b6SRobert Mustacchi 	mac->adaptive_ifs = TRUE;
74875eba5b6SRobert Mustacchi 
74975eba5b6SRobert Mustacchi 	/* Function pointers */
75075eba5b6SRobert Mustacchi 
75175eba5b6SRobert Mustacchi 	/* bus type/speed/width */
75275eba5b6SRobert Mustacchi 	mac->ops.get_bus_info = e1000_get_bus_info_ich8lan;
75375eba5b6SRobert Mustacchi 	/* function id */
75475eba5b6SRobert Mustacchi 	mac->ops.set_lan_id = e1000_set_lan_id_single_port;
75575eba5b6SRobert Mustacchi 	/* reset */
75675eba5b6SRobert Mustacchi 	mac->ops.reset_hw = e1000_reset_hw_ich8lan;
75775eba5b6SRobert Mustacchi 	/* hw initialization */
75875eba5b6SRobert Mustacchi 	mac->ops.init_hw = e1000_init_hw_ich8lan;
75975eba5b6SRobert Mustacchi 	/* link setup */
76075eba5b6SRobert Mustacchi 	mac->ops.setup_link = e1000_setup_link_ich8lan;
76175eba5b6SRobert Mustacchi 	/* physical interface setup */
76275eba5b6SRobert Mustacchi 	mac->ops.setup_physical_interface = e1000_setup_copper_link_ich8lan;
76375eba5b6SRobert Mustacchi 	/* check for link */
76475eba5b6SRobert Mustacchi 	mac->ops.check_for_link = e1000_check_for_copper_link_ich8lan;
76575eba5b6SRobert Mustacchi 	/* link info */
76675eba5b6SRobert Mustacchi 	mac->ops.get_link_up_info = e1000_get_link_up_info_ich8lan;
76775eba5b6SRobert Mustacchi 	/* multicast address update */
76875eba5b6SRobert Mustacchi 	mac->ops.update_mc_addr_list = e1000_update_mc_addr_list_generic;
76975eba5b6SRobert Mustacchi 	/* clear hardware counters */
77075eba5b6SRobert Mustacchi 	mac->ops.clear_hw_cntrs = e1000_clear_hw_cntrs_ich8lan;
77175eba5b6SRobert Mustacchi 
77275eba5b6SRobert Mustacchi 	/* LED and other operations */
77375eba5b6SRobert Mustacchi 	switch (mac->type) {
77475eba5b6SRobert Mustacchi 	case e1000_ich8lan:
77575eba5b6SRobert Mustacchi 	case e1000_ich9lan:
77675eba5b6SRobert Mustacchi 	case e1000_ich10lan:
77775eba5b6SRobert Mustacchi 		/* check management mode */
77875eba5b6SRobert Mustacchi 		mac->ops.check_mng_mode = e1000_check_mng_mode_ich8lan;
77975eba5b6SRobert Mustacchi 		/* ID LED init */
78075eba5b6SRobert Mustacchi 		mac->ops.id_led_init = e1000_id_led_init_generic;
78175eba5b6SRobert Mustacchi 		/* blink LED */
78275eba5b6SRobert Mustacchi 		mac->ops.blink_led = e1000_blink_led_generic;
78375eba5b6SRobert Mustacchi 		/* setup LED */
78475eba5b6SRobert Mustacchi 		mac->ops.setup_led = e1000_setup_led_generic;
78575eba5b6SRobert Mustacchi 		/* cleanup LED */
78675eba5b6SRobert Mustacchi 		mac->ops.cleanup_led = e1000_cleanup_led_ich8lan;
78775eba5b6SRobert Mustacchi 		/* turn on/off LED */
78875eba5b6SRobert Mustacchi 		mac->ops.led_on = e1000_led_on_ich8lan;
78975eba5b6SRobert Mustacchi 		mac->ops.led_off = e1000_led_off_ich8lan;
79075eba5b6SRobert Mustacchi 		break;
79175eba5b6SRobert Mustacchi 	case e1000_pch2lan:
79275eba5b6SRobert Mustacchi 		mac->rar_entry_count = E1000_PCH2_RAR_ENTRIES;
79375eba5b6SRobert Mustacchi 		mac->ops.rar_set = e1000_rar_set_pch2lan;
79475eba5b6SRobert Mustacchi 		/* fall-through */
79575eba5b6SRobert Mustacchi 	case e1000_pch_lpt:
796*42cc51e0SRobert Mustacchi 	case e1000_pch_spt:
79775eba5b6SRobert Mustacchi 		/* multicast address update for pch2 */
79875eba5b6SRobert Mustacchi 		mac->ops.update_mc_addr_list =
79975eba5b6SRobert Mustacchi 			e1000_update_mc_addr_list_pch2lan;
800*42cc51e0SRobert Mustacchi 		/* fall-through */
80175eba5b6SRobert Mustacchi 	case e1000_pchlan:
80275eba5b6SRobert Mustacchi 		/* check management mode */
80375eba5b6SRobert Mustacchi 		mac->ops.check_mng_mode = e1000_check_mng_mode_pchlan;
80475eba5b6SRobert Mustacchi 		/* ID LED init */
80575eba5b6SRobert Mustacchi 		mac->ops.id_led_init = e1000_id_led_init_pchlan;
80675eba5b6SRobert Mustacchi 		/* setup LED */
80775eba5b6SRobert Mustacchi 		mac->ops.setup_led = e1000_setup_led_pchlan;
80875eba5b6SRobert Mustacchi 		/* cleanup LED */
80975eba5b6SRobert Mustacchi 		mac->ops.cleanup_led = e1000_cleanup_led_pchlan;
81075eba5b6SRobert Mustacchi 		/* turn on/off LED */
81175eba5b6SRobert Mustacchi 		mac->ops.led_on = e1000_led_on_pchlan;
81275eba5b6SRobert Mustacchi 		mac->ops.led_off = e1000_led_off_pchlan;
81375eba5b6SRobert Mustacchi 		break;
81475eba5b6SRobert Mustacchi 	default:
81575eba5b6SRobert Mustacchi 		break;
81675eba5b6SRobert Mustacchi 	}
81775eba5b6SRobert Mustacchi 
818*42cc51e0SRobert Mustacchi 	if ((mac->type == e1000_pch_lpt) ||
819*42cc51e0SRobert Mustacchi 	    (mac->type == e1000_pch_spt)) {
82075eba5b6SRobert Mustacchi 		mac->rar_entry_count = E1000_PCH_LPT_RAR_ENTRIES;
82175eba5b6SRobert Mustacchi 		mac->ops.rar_set = e1000_rar_set_pch_lpt;
82275eba5b6SRobert Mustacchi 		mac->ops.setup_physical_interface = e1000_setup_copper_link_pch_lpt;
82375eba5b6SRobert Mustacchi 		mac->ops.set_obff_timer = e1000_set_obff_timer_pch_lpt;
82475eba5b6SRobert Mustacchi 	}
82575eba5b6SRobert Mustacchi 
82675eba5b6SRobert Mustacchi 	/* Enable PCS Lock-loss workaround for ICH8 */
82775eba5b6SRobert Mustacchi 	if (mac->type == e1000_ich8lan)
82875eba5b6SRobert Mustacchi 		e1000_set_kmrn_lock_loss_workaround_ich8lan(hw, TRUE);
82975eba5b6SRobert Mustacchi 
83075eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
83175eba5b6SRobert Mustacchi }
83275eba5b6SRobert Mustacchi 
83375eba5b6SRobert Mustacchi /**
83475eba5b6SRobert Mustacchi  *  __e1000_access_emi_reg_locked - Read/write EMI register
83575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
83675eba5b6SRobert Mustacchi  *  @addr: EMI address to program
83775eba5b6SRobert Mustacchi  *  @data: pointer to value to read/write from/to the EMI address
83875eba5b6SRobert Mustacchi  *  @read: boolean flag to indicate read or write
83975eba5b6SRobert Mustacchi  *
84075eba5b6SRobert Mustacchi  *  This helper function assumes the SW/FW/HW Semaphore is already acquired.
84175eba5b6SRobert Mustacchi  **/
84275eba5b6SRobert Mustacchi static s32 __e1000_access_emi_reg_locked(struct e1000_hw *hw, u16 address,
84375eba5b6SRobert Mustacchi 					 u16 *data, bool read)
84475eba5b6SRobert Mustacchi {
84575eba5b6SRobert Mustacchi 	s32 ret_val;
84675eba5b6SRobert Mustacchi 
84775eba5b6SRobert Mustacchi 	DEBUGFUNC("__e1000_access_emi_reg_locked");
84875eba5b6SRobert Mustacchi 
84975eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_ADDR, address);
85075eba5b6SRobert Mustacchi 	if (ret_val)
85175eba5b6SRobert Mustacchi 		return ret_val;
85275eba5b6SRobert Mustacchi 
85375eba5b6SRobert Mustacchi 	if (read)
85475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg_locked(hw, I82579_EMI_DATA,
85575eba5b6SRobert Mustacchi 						      data);
85675eba5b6SRobert Mustacchi 	else
85775eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg_locked(hw, I82579_EMI_DATA,
85875eba5b6SRobert Mustacchi 						       *data);
85975eba5b6SRobert Mustacchi 
86075eba5b6SRobert Mustacchi 	return ret_val;
86175eba5b6SRobert Mustacchi }
86275eba5b6SRobert Mustacchi 
86375eba5b6SRobert Mustacchi /**
86475eba5b6SRobert Mustacchi  *  e1000_read_emi_reg_locked - Read Extended Management Interface register
86575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
86675eba5b6SRobert Mustacchi  *  @addr: EMI address to program
86775eba5b6SRobert Mustacchi  *  @data: value to be read from the EMI address
86875eba5b6SRobert Mustacchi  *
86975eba5b6SRobert Mustacchi  *  Assumes the SW/FW/HW Semaphore is already acquired.
87075eba5b6SRobert Mustacchi  **/
87175eba5b6SRobert Mustacchi s32 e1000_read_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 *data)
87275eba5b6SRobert Mustacchi {
87375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_emi_reg_locked");
87475eba5b6SRobert Mustacchi 
87575eba5b6SRobert Mustacchi 	return __e1000_access_emi_reg_locked(hw, addr, data, TRUE);
87675eba5b6SRobert Mustacchi }
87775eba5b6SRobert Mustacchi 
87875eba5b6SRobert Mustacchi /**
87975eba5b6SRobert Mustacchi  *  e1000_write_emi_reg_locked - Write Extended Management Interface register
88075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
88175eba5b6SRobert Mustacchi  *  @addr: EMI address to program
88275eba5b6SRobert Mustacchi  *  @data: value to be written to the EMI address
88375eba5b6SRobert Mustacchi  *
88475eba5b6SRobert Mustacchi  *  Assumes the SW/FW/HW Semaphore is already acquired.
88575eba5b6SRobert Mustacchi  **/
886c124a83eSRobert Mustacchi s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)
88775eba5b6SRobert Mustacchi {
88875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_emi_reg_locked");
88975eba5b6SRobert Mustacchi 
89075eba5b6SRobert Mustacchi 	return __e1000_access_emi_reg_locked(hw, addr, &data, FALSE);
89175eba5b6SRobert Mustacchi }
89275eba5b6SRobert Mustacchi 
89375eba5b6SRobert Mustacchi /**
89475eba5b6SRobert Mustacchi  *  e1000_set_eee_pchlan - Enable/disable EEE support
89575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
89675eba5b6SRobert Mustacchi  *
89775eba5b6SRobert Mustacchi  *  Enable/disable EEE based on setting in dev_spec structure, the duplex of
89875eba5b6SRobert Mustacchi  *  the link and the EEE capabilities of the link partner.  The LPI Control
89975eba5b6SRobert Mustacchi  *  register bits will remain set only if/when link is up.
900c124a83eSRobert Mustacchi  *
901c124a83eSRobert Mustacchi  *  EEE LPI must not be asserted earlier than one second after link is up.
902c124a83eSRobert Mustacchi  *  On 82579, EEE LPI should not be enabled until such time otherwise there
903c124a83eSRobert Mustacchi  *  can be link issues with some switches.  Other devices can have EEE LPI
904c124a83eSRobert Mustacchi  *  enabled immediately upon link up since they have a timer in hardware which
905c124a83eSRobert Mustacchi  *  prevents LPI from being asserted too early.
90675eba5b6SRobert Mustacchi  **/
907c124a83eSRobert Mustacchi s32 e1000_set_eee_pchlan(struct e1000_hw *hw)
90875eba5b6SRobert Mustacchi {
90975eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
91075eba5b6SRobert Mustacchi 	s32 ret_val;
911c124a83eSRobert Mustacchi 	u16 lpa, pcs_status, adv, adv_addr, lpi_ctrl, data;
91275eba5b6SRobert Mustacchi 
91375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_eee_pchlan");
91475eba5b6SRobert Mustacchi 
915c124a83eSRobert Mustacchi 	switch (hw->phy.type) {
916c124a83eSRobert Mustacchi 	case e1000_phy_82579:
917c124a83eSRobert Mustacchi 		lpa = I82579_EEE_LP_ABILITY;
918c124a83eSRobert Mustacchi 		pcs_status = I82579_EEE_PCS_STATUS;
919c124a83eSRobert Mustacchi 		adv_addr = I82579_EEE_ADVERTISEMENT;
920c124a83eSRobert Mustacchi 		break;
921c124a83eSRobert Mustacchi 	case e1000_phy_i217:
922c124a83eSRobert Mustacchi 		lpa = I217_EEE_LP_ABILITY;
923c124a83eSRobert Mustacchi 		pcs_status = I217_EEE_PCS_STATUS;
924c124a83eSRobert Mustacchi 		adv_addr = I217_EEE_ADVERTISEMENT;
925c124a83eSRobert Mustacchi 		break;
926c124a83eSRobert Mustacchi 	default:
92775eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
928c124a83eSRobert Mustacchi 	}
92975eba5b6SRobert Mustacchi 
93075eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
93175eba5b6SRobert Mustacchi 	if (ret_val)
93275eba5b6SRobert Mustacchi 		return ret_val;
93375eba5b6SRobert Mustacchi 
93475eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg_locked(hw, I82579_LPI_CTRL, &lpi_ctrl);
93575eba5b6SRobert Mustacchi 	if (ret_val)
93675eba5b6SRobert Mustacchi 		goto release;
93775eba5b6SRobert Mustacchi 
93875eba5b6SRobert Mustacchi 	/* Clear bits that enable EEE in various speeds */
93975eba5b6SRobert Mustacchi 	lpi_ctrl &= ~I82579_LPI_CTRL_ENABLE_MASK;
94075eba5b6SRobert Mustacchi 
94175eba5b6SRobert Mustacchi 	/* Enable EEE if not disabled by user */
94275eba5b6SRobert Mustacchi 	if (!dev_spec->eee_disable) {
94375eba5b6SRobert Mustacchi 		/* Save off link partner's EEE ability */
94475eba5b6SRobert Mustacchi 		ret_val = e1000_read_emi_reg_locked(hw, lpa,
94575eba5b6SRobert Mustacchi 						    &dev_spec->eee_lp_ability);
94675eba5b6SRobert Mustacchi 		if (ret_val)
94775eba5b6SRobert Mustacchi 			goto release;
94875eba5b6SRobert Mustacchi 
949c124a83eSRobert Mustacchi 		/* Read EEE advertisement */
950c124a83eSRobert Mustacchi 		ret_val = e1000_read_emi_reg_locked(hw, adv_addr, &adv);
951c124a83eSRobert Mustacchi 		if (ret_val)
952c124a83eSRobert Mustacchi 			goto release;
953c124a83eSRobert Mustacchi 
95475eba5b6SRobert Mustacchi 		/* Enable EEE only for speeds in which the link partner is
955c124a83eSRobert Mustacchi 		 * EEE capable and for which we advertise EEE.
95675eba5b6SRobert Mustacchi 		 */
957c124a83eSRobert Mustacchi 		if (adv & dev_spec->eee_lp_ability & I82579_EEE_1000_SUPPORTED)
95875eba5b6SRobert Mustacchi 			lpi_ctrl |= I82579_LPI_CTRL_1000_ENABLE;
95975eba5b6SRobert Mustacchi 
960c124a83eSRobert Mustacchi 		if (adv & dev_spec->eee_lp_ability & I82579_EEE_100_SUPPORTED) {
96175eba5b6SRobert Mustacchi 			hw->phy.ops.read_reg_locked(hw, PHY_LP_ABILITY, &data);
96275eba5b6SRobert Mustacchi 			if (data & NWAY_LPAR_100TX_FD_CAPS)
96375eba5b6SRobert Mustacchi 				lpi_ctrl |= I82579_LPI_CTRL_100_ENABLE;
96475eba5b6SRobert Mustacchi 			else
96575eba5b6SRobert Mustacchi 				/* EEE is not supported in 100Half, so ignore
96675eba5b6SRobert Mustacchi 				 * partner's EEE in 100 ability if full-duplex
96775eba5b6SRobert Mustacchi 				 * is not advertised.
96875eba5b6SRobert Mustacchi 				 */
96975eba5b6SRobert Mustacchi 				dev_spec->eee_lp_ability &=
97075eba5b6SRobert Mustacchi 				    ~I82579_EEE_100_SUPPORTED;
97175eba5b6SRobert Mustacchi 		}
972c124a83eSRobert Mustacchi 	}
973c124a83eSRobert Mustacchi 
974c124a83eSRobert Mustacchi 	if (hw->phy.type == e1000_phy_82579) {
975c124a83eSRobert Mustacchi 		ret_val = e1000_read_emi_reg_locked(hw, I82579_LPI_PLL_SHUT,
976c124a83eSRobert Mustacchi 						    &data);
977c124a83eSRobert Mustacchi 		if (ret_val)
978c124a83eSRobert Mustacchi 			goto release;
979c124a83eSRobert Mustacchi 
980c124a83eSRobert Mustacchi 		data &= ~I82579_LPI_100_PLL_SHUT;
981c124a83eSRobert Mustacchi 		ret_val = e1000_write_emi_reg_locked(hw, I82579_LPI_PLL_SHUT,
982c124a83eSRobert Mustacchi 						     data);
983c124a83eSRobert Mustacchi 	}
98475eba5b6SRobert Mustacchi 
98575eba5b6SRobert Mustacchi 	/* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */
98675eba5b6SRobert Mustacchi 	ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);
98775eba5b6SRobert Mustacchi 	if (ret_val)
98875eba5b6SRobert Mustacchi 		goto release;
98975eba5b6SRobert Mustacchi 
99075eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg_locked(hw, I82579_LPI_CTRL, lpi_ctrl);
99175eba5b6SRobert Mustacchi release:
99275eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
99375eba5b6SRobert Mustacchi 
99475eba5b6SRobert Mustacchi 	return ret_val;
99575eba5b6SRobert Mustacchi }
99675eba5b6SRobert Mustacchi 
99775eba5b6SRobert Mustacchi /**
99875eba5b6SRobert Mustacchi  *  e1000_k1_workaround_lpt_lp - K1 workaround on Lynxpoint-LP
99975eba5b6SRobert Mustacchi  *  @hw:   pointer to the HW structure
100075eba5b6SRobert Mustacchi  *  @link: link up bool flag
100175eba5b6SRobert Mustacchi  *
100275eba5b6SRobert Mustacchi  *  When K1 is enabled for 1Gbps, the MAC can miss 2 DMA completion indications
100375eba5b6SRobert Mustacchi  *  preventing further DMA write requests.  Workaround the issue by disabling
100475eba5b6SRobert Mustacchi  *  the de-assertion of the clock request when in 1Gpbs mode.
1005c124a83eSRobert Mustacchi  *  Also, set appropriate Tx re-transmission timeouts for 10 and 100Half link
1006c124a83eSRobert Mustacchi  *  speeds in order to avoid Tx hangs.
100775eba5b6SRobert Mustacchi  **/
100875eba5b6SRobert Mustacchi static s32 e1000_k1_workaround_lpt_lp(struct e1000_hw *hw, bool link)
100975eba5b6SRobert Mustacchi {
101075eba5b6SRobert Mustacchi 	u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
1011c124a83eSRobert Mustacchi 	u32 status = E1000_READ_REG(hw, E1000_STATUS);
101275eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
1013c124a83eSRobert Mustacchi 	u16 reg;
101475eba5b6SRobert Mustacchi 
1015c124a83eSRobert Mustacchi 	if (link && (status & E1000_STATUS_SPEED_1000)) {
101675eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
101775eba5b6SRobert Mustacchi 		if (ret_val)
101875eba5b6SRobert Mustacchi 			return ret_val;
101975eba5b6SRobert Mustacchi 
102075eba5b6SRobert Mustacchi 		ret_val =
102175eba5b6SRobert Mustacchi 		    e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
1022c124a83eSRobert Mustacchi 					       &reg);
102375eba5b6SRobert Mustacchi 		if (ret_val)
102475eba5b6SRobert Mustacchi 			goto release;
102575eba5b6SRobert Mustacchi 
102675eba5b6SRobert Mustacchi 		ret_val =
102775eba5b6SRobert Mustacchi 		    e1000_write_kmrn_reg_locked(hw,
102875eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_K1_CONFIG,
1029c124a83eSRobert Mustacchi 						reg &
103075eba5b6SRobert Mustacchi 						~E1000_KMRNCTRLSTA_K1_ENABLE);
103175eba5b6SRobert Mustacchi 		if (ret_val)
103275eba5b6SRobert Mustacchi 			goto release;
103375eba5b6SRobert Mustacchi 
103475eba5b6SRobert Mustacchi 		usec_delay(10);
103575eba5b6SRobert Mustacchi 
103675eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FEXTNVM6,
103775eba5b6SRobert Mustacchi 				fextnvm6 | E1000_FEXTNVM6_REQ_PLL_CLK);
103875eba5b6SRobert Mustacchi 
103975eba5b6SRobert Mustacchi 		ret_val =
104075eba5b6SRobert Mustacchi 		    e1000_write_kmrn_reg_locked(hw,
104175eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_K1_CONFIG,
1042c124a83eSRobert Mustacchi 						reg);
104375eba5b6SRobert Mustacchi release:
104475eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
104575eba5b6SRobert Mustacchi 	} else {
104675eba5b6SRobert Mustacchi 		/* clear FEXTNVM6 bit 8 on link down or 10/100 */
1047c124a83eSRobert Mustacchi 		fextnvm6 &= ~E1000_FEXTNVM6_REQ_PLL_CLK;
1048c124a83eSRobert Mustacchi 
1049*42cc51e0SRobert Mustacchi 		if ((hw->phy.revision > 5) || !link ||
1050*42cc51e0SRobert Mustacchi 		    ((status & E1000_STATUS_SPEED_100) &&
1051c124a83eSRobert Mustacchi 		     (status & E1000_STATUS_FD)))
1052c124a83eSRobert Mustacchi 			goto update_fextnvm6;
1053c124a83eSRobert Mustacchi 
1054c124a83eSRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, I217_INBAND_CTRL, &reg);
1055c124a83eSRobert Mustacchi 		if (ret_val)
1056c124a83eSRobert Mustacchi 			return ret_val;
1057c124a83eSRobert Mustacchi 
1058c124a83eSRobert Mustacchi 		/* Clear link status transmit timeout */
1059c124a83eSRobert Mustacchi 		reg &= ~I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_MASK;
1060c124a83eSRobert Mustacchi 
1061c124a83eSRobert Mustacchi 		if (status & E1000_STATUS_SPEED_100) {
1062c124a83eSRobert Mustacchi 			/* Set inband Tx timeout to 5x10us for 100Half */
1063c124a83eSRobert Mustacchi 			reg |= 5 << I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
1064c124a83eSRobert Mustacchi 
1065c124a83eSRobert Mustacchi 			/* Do not extend the K1 entry latency for 100Half */
1066c124a83eSRobert Mustacchi 			fextnvm6 &= ~E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
1067c124a83eSRobert Mustacchi 		} else {
1068c124a83eSRobert Mustacchi 			/* Set inband Tx timeout to 50x10us for 10Full/Half */
1069c124a83eSRobert Mustacchi 			reg |= 50 <<
1070c124a83eSRobert Mustacchi 			       I217_INBAND_CTRL_LINK_STAT_TX_TIMEOUT_SHIFT;
1071c124a83eSRobert Mustacchi 
1072c124a83eSRobert Mustacchi 			/* Extend the K1 entry latency for 10 Mbps */
1073c124a83eSRobert Mustacchi 			fextnvm6 |= E1000_FEXTNVM6_ENABLE_K1_ENTRY_CONDITION;
1074c124a83eSRobert Mustacchi 		}
1075c124a83eSRobert Mustacchi 
1076c124a83eSRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, I217_INBAND_CTRL, reg);
1077c124a83eSRobert Mustacchi 		if (ret_val)
1078c124a83eSRobert Mustacchi 			return ret_val;
1079c124a83eSRobert Mustacchi 
1080c124a83eSRobert Mustacchi update_fextnvm6:
1081c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
108275eba5b6SRobert Mustacchi 	}
108375eba5b6SRobert Mustacchi 
108475eba5b6SRobert Mustacchi 	return ret_val;
108575eba5b6SRobert Mustacchi }
108675eba5b6SRobert Mustacchi 
108775eba5b6SRobert Mustacchi static u64 e1000_ltr2ns(u16 ltr)
108875eba5b6SRobert Mustacchi {
108975eba5b6SRobert Mustacchi 	u32 value, scale;
109075eba5b6SRobert Mustacchi 
109175eba5b6SRobert Mustacchi 	/* Determine the latency in nsec based on the LTR value & scale */
109275eba5b6SRobert Mustacchi 	value = ltr & E1000_LTRV_VALUE_MASK;
109375eba5b6SRobert Mustacchi 	scale = (ltr & E1000_LTRV_SCALE_MASK) >> E1000_LTRV_SCALE_SHIFT;
109475eba5b6SRobert Mustacchi 
109575eba5b6SRobert Mustacchi 	return value * (1 << (scale * E1000_LTRV_SCALE_FACTOR));
109675eba5b6SRobert Mustacchi }
109775eba5b6SRobert Mustacchi 
109875eba5b6SRobert Mustacchi /**
109975eba5b6SRobert Mustacchi  *  e1000_platform_pm_pch_lpt - Set platform power management values
110075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
110175eba5b6SRobert Mustacchi  *  @link: bool indicating link status
110275eba5b6SRobert Mustacchi  *
110375eba5b6SRobert Mustacchi  *  Set the Latency Tolerance Reporting (LTR) values for the "PCIe-like"
110475eba5b6SRobert Mustacchi  *  GbE MAC in the Lynx Point PCH based on Rx buffer size and link speed
110575eba5b6SRobert Mustacchi  *  when link is up (which must not exceed the maximum latency supported
110675eba5b6SRobert Mustacchi  *  by the platform), otherwise specify there is no LTR requirement.
110775eba5b6SRobert Mustacchi  *  Unlike TRUE-PCIe devices which set the LTR maximum snoop/no-snoop
110875eba5b6SRobert Mustacchi  *  latencies in the LTR Extended Capability Structure in the PCIe Extended
110975eba5b6SRobert Mustacchi  *  Capability register set, on this device LTR is set by writing the
111075eba5b6SRobert Mustacchi  *  equivalent snoop/no-snoop latencies in the LTRV register in the MAC and
111175eba5b6SRobert Mustacchi  *  set the SEND bit to send an Intel On-chip System Fabric sideband (IOSF-SB)
111275eba5b6SRobert Mustacchi  *  message to the PMC.
111375eba5b6SRobert Mustacchi  *
111475eba5b6SRobert Mustacchi  *  Use the LTR value to calculate the Optimized Buffer Flush/Fill (OBFF)
111575eba5b6SRobert Mustacchi  *  high-water mark.
111675eba5b6SRobert Mustacchi  **/
111775eba5b6SRobert Mustacchi static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)
111875eba5b6SRobert Mustacchi {
111975eba5b6SRobert Mustacchi 	u32 reg = link << (E1000_LTRV_REQ_SHIFT + E1000_LTRV_NOSNOOP_SHIFT) |
112075eba5b6SRobert Mustacchi 		  link << E1000_LTRV_REQ_SHIFT | E1000_LTRV_SEND;
112175eba5b6SRobert Mustacchi 	u16 lat_enc = 0;	/* latency encoded */
112275eba5b6SRobert Mustacchi 	s32 obff_hwm = 0;
112375eba5b6SRobert Mustacchi 
112475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_platform_pm_pch_lpt");
112575eba5b6SRobert Mustacchi 
112675eba5b6SRobert Mustacchi 	if (link) {
112775eba5b6SRobert Mustacchi 		u16 speed, duplex, scale = 0;
112875eba5b6SRobert Mustacchi 		u16 max_snoop, max_nosnoop;
112975eba5b6SRobert Mustacchi 		u16 max_ltr_enc;	/* max LTR latency encoded */
1130*42cc51e0SRobert Mustacchi 		s64 lat_ns;
113175eba5b6SRobert Mustacchi 		s64 value;
113275eba5b6SRobert Mustacchi 		u32 rxa;
113375eba5b6SRobert Mustacchi 
113475eba5b6SRobert Mustacchi 		if (!hw->mac.max_frame_size) {
113575eba5b6SRobert Mustacchi 			DEBUGOUT("max_frame_size not set.\n");
113675eba5b6SRobert Mustacchi 			return -E1000_ERR_CONFIG;
113775eba5b6SRobert Mustacchi 		}
113875eba5b6SRobert Mustacchi 
113975eba5b6SRobert Mustacchi 		hw->mac.ops.get_link_up_info(hw, &speed, &duplex);
114075eba5b6SRobert Mustacchi 		if (!speed) {
114175eba5b6SRobert Mustacchi 			DEBUGOUT("Speed not set.\n");
114275eba5b6SRobert Mustacchi 			return -E1000_ERR_CONFIG;
114375eba5b6SRobert Mustacchi 		}
114475eba5b6SRobert Mustacchi 
114575eba5b6SRobert Mustacchi 		/* Rx Packet Buffer Allocation size (KB) */
114675eba5b6SRobert Mustacchi 		rxa = E1000_READ_REG(hw, E1000_PBA) & E1000_PBA_RXA_MASK;
114775eba5b6SRobert Mustacchi 
114875eba5b6SRobert Mustacchi 		/* Determine the maximum latency tolerated by the device.
114975eba5b6SRobert Mustacchi 		 *
115075eba5b6SRobert Mustacchi 		 * Per the PCIe spec, the tolerated latencies are encoded as
115175eba5b6SRobert Mustacchi 		 * a 3-bit encoded scale (only 0-5 are valid) multiplied by
115275eba5b6SRobert Mustacchi 		 * a 10-bit value (0-1023) to provide a range from 1 ns to
115375eba5b6SRobert Mustacchi 		 * 2^25*(2^10-1) ns.  The scale is encoded as 0=2^0ns,
115475eba5b6SRobert Mustacchi 		 * 1=2^5ns, 2=2^10ns,...5=2^25ns.
115575eba5b6SRobert Mustacchi 		 */
115675eba5b6SRobert Mustacchi 		lat_ns = ((s64)rxa * 1024 -
115775eba5b6SRobert Mustacchi 			  (2 * (s64)hw->mac.max_frame_size)) * 8 * 1000;
115875eba5b6SRobert Mustacchi 		if (lat_ns < 0)
115975eba5b6SRobert Mustacchi 			lat_ns = 0;
116075eba5b6SRobert Mustacchi 		else
116175eba5b6SRobert Mustacchi 			lat_ns /= speed;
116275eba5b6SRobert Mustacchi 		value = lat_ns;
1163*42cc51e0SRobert Mustacchi 
116475eba5b6SRobert Mustacchi 		while (value > E1000_LTRV_VALUE_MASK) {
116575eba5b6SRobert Mustacchi 			scale++;
116675eba5b6SRobert Mustacchi 			value = E1000_DIVIDE_ROUND_UP(value, (1 << 5));
116775eba5b6SRobert Mustacchi 		}
116875eba5b6SRobert Mustacchi 		if (scale > E1000_LTRV_SCALE_MAX) {
116975eba5b6SRobert Mustacchi 			DEBUGOUT1("Invalid LTR latency scale %d\n", scale);
117075eba5b6SRobert Mustacchi 			return -E1000_ERR_CONFIG;
117175eba5b6SRobert Mustacchi 		}
117275eba5b6SRobert Mustacchi 		lat_enc = (u16)((scale << E1000_LTRV_SCALE_SHIFT) | value);
117375eba5b6SRobert Mustacchi 
117475eba5b6SRobert Mustacchi 		/* Determine the maximum latency tolerated by the platform */
117575eba5b6SRobert Mustacchi 		e1000_read_pci_cfg(hw, E1000_PCI_LTR_CAP_LPT, &max_snoop);
117675eba5b6SRobert Mustacchi 		e1000_read_pci_cfg(hw, E1000_PCI_LTR_CAP_LPT + 2, &max_nosnoop);
117775eba5b6SRobert Mustacchi 		max_ltr_enc = E1000_MAX(max_snoop, max_nosnoop);
117875eba5b6SRobert Mustacchi 
117975eba5b6SRobert Mustacchi 		if (lat_enc > max_ltr_enc) {
118075eba5b6SRobert Mustacchi 			lat_enc = max_ltr_enc;
118175eba5b6SRobert Mustacchi 			lat_ns = e1000_ltr2ns(max_ltr_enc);
118275eba5b6SRobert Mustacchi 		}
118375eba5b6SRobert Mustacchi 
118475eba5b6SRobert Mustacchi 		if (lat_ns) {
118575eba5b6SRobert Mustacchi 			lat_ns *= speed * 1000;
118675eba5b6SRobert Mustacchi 			lat_ns /= 8;
118775eba5b6SRobert Mustacchi 			lat_ns /= 1000000000;
118875eba5b6SRobert Mustacchi 			obff_hwm = (s32)(rxa - lat_ns);
118975eba5b6SRobert Mustacchi 		}
119075eba5b6SRobert Mustacchi 		if ((obff_hwm < 0) || (obff_hwm > E1000_SVT_OFF_HWM_MASK)) {
119175eba5b6SRobert Mustacchi 			DEBUGOUT1("Invalid high water mark %d\n", obff_hwm);
119275eba5b6SRobert Mustacchi 			return -E1000_ERR_CONFIG;
119375eba5b6SRobert Mustacchi 		}
119475eba5b6SRobert Mustacchi 	}
119575eba5b6SRobert Mustacchi 
119675eba5b6SRobert Mustacchi 	/* Set Snoop and No-Snoop latencies the same */
119775eba5b6SRobert Mustacchi 	reg |= lat_enc | (lat_enc << E1000_LTRV_NOSNOOP_SHIFT);
119875eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_LTRV, reg);
119975eba5b6SRobert Mustacchi 
120075eba5b6SRobert Mustacchi 	/* Set OBFF high water mark */
120175eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_SVT) & ~E1000_SVT_OFF_HWM_MASK;
120275eba5b6SRobert Mustacchi 	reg |= obff_hwm;
120375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_SVT, reg);
120475eba5b6SRobert Mustacchi 
120575eba5b6SRobert Mustacchi 	/* Enable OBFF */
120675eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_SVCR);
120775eba5b6SRobert Mustacchi 	reg |= E1000_SVCR_OFF_EN;
120875eba5b6SRobert Mustacchi 	/* Always unblock interrupts to the CPU even when the system is
120975eba5b6SRobert Mustacchi 	 * in OBFF mode. This ensures that small round-robin traffic
121075eba5b6SRobert Mustacchi 	 * (like ping) does not get dropped or experience long latency.
121175eba5b6SRobert Mustacchi 	 */
121275eba5b6SRobert Mustacchi 	reg |= E1000_SVCR_OFF_MASKINT;
121375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_SVCR, reg);
121475eba5b6SRobert Mustacchi 
121575eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
121675eba5b6SRobert Mustacchi }
121775eba5b6SRobert Mustacchi 
121875eba5b6SRobert Mustacchi /**
121975eba5b6SRobert Mustacchi  *  e1000_set_obff_timer_pch_lpt - Update Optimized Buffer Flush/Fill timer
122075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
122175eba5b6SRobert Mustacchi  *  @itr: interrupt throttling rate
122275eba5b6SRobert Mustacchi  *
122375eba5b6SRobert Mustacchi  *  Configure OBFF with the updated interrupt rate.
122475eba5b6SRobert Mustacchi  **/
122575eba5b6SRobert Mustacchi static s32 e1000_set_obff_timer_pch_lpt(struct e1000_hw *hw, u32 itr)
122675eba5b6SRobert Mustacchi {
122775eba5b6SRobert Mustacchi 	u32 svcr;
122875eba5b6SRobert Mustacchi 	s32 timer;
122975eba5b6SRobert Mustacchi 
123075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_obff_timer_pch_lpt");
123175eba5b6SRobert Mustacchi 
123275eba5b6SRobert Mustacchi 	/* Convert ITR value into microseconds for OBFF timer */
123375eba5b6SRobert Mustacchi 	timer = itr & E1000_ITR_MASK;
123475eba5b6SRobert Mustacchi 	timer = (timer * E1000_ITR_MULT) / 1000;
123575eba5b6SRobert Mustacchi 
123675eba5b6SRobert Mustacchi 	if ((timer < 0) || (timer > E1000_ITR_MASK)) {
123775eba5b6SRobert Mustacchi 		DEBUGOUT1("Invalid OBFF timer %d\n", timer);
123875eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
123975eba5b6SRobert Mustacchi 	}
124075eba5b6SRobert Mustacchi 
124175eba5b6SRobert Mustacchi 	svcr = E1000_READ_REG(hw, E1000_SVCR);
124275eba5b6SRobert Mustacchi 	svcr &= ~E1000_SVCR_OFF_TIMER_MASK;
124375eba5b6SRobert Mustacchi 	svcr |= timer << E1000_SVCR_OFF_TIMER_SHIFT;
124475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_SVCR, svcr);
124575eba5b6SRobert Mustacchi 
124675eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
124775eba5b6SRobert Mustacchi }
124875eba5b6SRobert Mustacchi 
124975eba5b6SRobert Mustacchi /**
1250c124a83eSRobert Mustacchi  *  e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP
1251c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
1252c124a83eSRobert Mustacchi  *  @to_sx: boolean indicating a system power state transition to Sx
1253c124a83eSRobert Mustacchi  *
1254c124a83eSRobert Mustacchi  *  When link is down, configure ULP mode to significantly reduce the power
1255c124a83eSRobert Mustacchi  *  to the PHY.  If on a Manageability Engine (ME) enabled system, tell the
1256c124a83eSRobert Mustacchi  *  ME firmware to start the ULP configuration.  If not on an ME enabled
1257c124a83eSRobert Mustacchi  *  system, configure the ULP mode by software.
1258c124a83eSRobert Mustacchi  */
1259c124a83eSRobert Mustacchi s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx)
1260c124a83eSRobert Mustacchi {
1261c124a83eSRobert Mustacchi 	u32 mac_reg;
1262c124a83eSRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
1263c124a83eSRobert Mustacchi 	u16 phy_reg;
1264*42cc51e0SRobert Mustacchi 	u16 oem_reg = 0;
1265c124a83eSRobert Mustacchi 
1266c124a83eSRobert Mustacchi 	if ((hw->mac.type < e1000_pch_lpt) ||
1267c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) ||
1268c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_V) ||
1269c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_I218_LM2) ||
1270c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_I218_V2) ||
1271c124a83eSRobert Mustacchi 	    (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_on))
1272c124a83eSRobert Mustacchi 		return 0;
1273c124a83eSRobert Mustacchi 
1274c124a83eSRobert Mustacchi 	if (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID) {
1275c124a83eSRobert Mustacchi 		/* Request ME configure ULP mode in the PHY */
1276c124a83eSRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_H2ME);
1277c124a83eSRobert Mustacchi 		mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS;
1278c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);
1279c124a83eSRobert Mustacchi 
1280c124a83eSRobert Mustacchi 		goto out;
1281c124a83eSRobert Mustacchi 	}
1282c124a83eSRobert Mustacchi 
1283c124a83eSRobert Mustacchi 	if (!to_sx) {
1284c124a83eSRobert Mustacchi 		int i = 0;
1285c124a83eSRobert Mustacchi 
1286c124a83eSRobert Mustacchi 		/* Poll up to 5 seconds for Cable Disconnected indication */
1287c124a83eSRobert Mustacchi 		while (!(E1000_READ_REG(hw, E1000_FEXT) &
1288c124a83eSRobert Mustacchi 			 E1000_FEXT_PHY_CABLE_DISCONNECTED)) {
1289c124a83eSRobert Mustacchi 			/* Bail if link is re-acquired */
1290c124a83eSRobert Mustacchi 			if (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)
1291c124a83eSRobert Mustacchi 				return -E1000_ERR_PHY;
1292c124a83eSRobert Mustacchi 
1293c124a83eSRobert Mustacchi 			if (i++ == 100)
1294c124a83eSRobert Mustacchi 				break;
1295c124a83eSRobert Mustacchi 
1296c124a83eSRobert Mustacchi 			msec_delay(50);
1297c124a83eSRobert Mustacchi 		}
1298c124a83eSRobert Mustacchi 		DEBUGOUT2("CABLE_DISCONNECTED %s set after %dmsec\n",
1299c124a83eSRobert Mustacchi 			 (E1000_READ_REG(hw, E1000_FEXT) &
1300c124a83eSRobert Mustacchi 			  E1000_FEXT_PHY_CABLE_DISCONNECTED) ? "" : "not",
1301c124a83eSRobert Mustacchi 			 i * 50);
1302c124a83eSRobert Mustacchi 	}
1303c124a83eSRobert Mustacchi 
1304c124a83eSRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
1305c124a83eSRobert Mustacchi 	if (ret_val)
1306c124a83eSRobert Mustacchi 		goto out;
1307c124a83eSRobert Mustacchi 
1308c124a83eSRobert Mustacchi 	/* Force SMBus mode in PHY */
1309c124a83eSRobert Mustacchi 	ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
1310c124a83eSRobert Mustacchi 	if (ret_val)
1311c124a83eSRobert Mustacchi 		goto release;
1312c124a83eSRobert Mustacchi 	phy_reg |= CV_SMB_CTRL_FORCE_SMBUS;
1313c124a83eSRobert Mustacchi 	e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
1314c124a83eSRobert Mustacchi 
1315c124a83eSRobert Mustacchi 	/* Force SMBus mode in MAC */
1316c124a83eSRobert Mustacchi 	mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
1317c124a83eSRobert Mustacchi 	mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
1318c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
1319c124a83eSRobert Mustacchi 
1320*42cc51e0SRobert Mustacchi 	/* Si workaround for ULP entry flow on i127/rev6 h/w.  Enable
1321*42cc51e0SRobert Mustacchi 	 * LPLU and disable Gig speed when entering ULP
1322*42cc51e0SRobert Mustacchi 	 */
1323*42cc51e0SRobert Mustacchi 	if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
1324*42cc51e0SRobert Mustacchi 		ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
1325*42cc51e0SRobert Mustacchi 						       &oem_reg);
1326*42cc51e0SRobert Mustacchi 		if (ret_val)
1327*42cc51e0SRobert Mustacchi 			goto release;
1328*42cc51e0SRobert Mustacchi 
1329*42cc51e0SRobert Mustacchi 		phy_reg = oem_reg;
1330*42cc51e0SRobert Mustacchi 		phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
1331*42cc51e0SRobert Mustacchi 
1332*42cc51e0SRobert Mustacchi 		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
1333*42cc51e0SRobert Mustacchi 							phy_reg);
1334*42cc51e0SRobert Mustacchi 
1335*42cc51e0SRobert Mustacchi 		if (ret_val)
1336*42cc51e0SRobert Mustacchi 			goto release;
1337*42cc51e0SRobert Mustacchi 	}
1338*42cc51e0SRobert Mustacchi 
1339c124a83eSRobert Mustacchi 	/* Set Inband ULP Exit, Reset to SMBus mode and
1340c124a83eSRobert Mustacchi 	 * Disable SMBus Release on PERST# in PHY
1341c124a83eSRobert Mustacchi 	 */
1342c124a83eSRobert Mustacchi 	ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg);
1343c124a83eSRobert Mustacchi 	if (ret_val)
1344c124a83eSRobert Mustacchi 		goto release;
1345c124a83eSRobert Mustacchi 	phy_reg |= (I218_ULP_CONFIG1_RESET_TO_SMBUS |
1346c124a83eSRobert Mustacchi 		    I218_ULP_CONFIG1_DISABLE_SMB_PERST);
1347c124a83eSRobert Mustacchi 	if (to_sx) {
1348c124a83eSRobert Mustacchi 		if (E1000_READ_REG(hw, E1000_WUFC) & E1000_WUFC_LNKC)
1349c124a83eSRobert Mustacchi 			phy_reg |= I218_ULP_CONFIG1_WOL_HOST;
1350*42cc51e0SRobert Mustacchi 		else
1351*42cc51e0SRobert Mustacchi 			phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
1352c124a83eSRobert Mustacchi 
1353c124a83eSRobert Mustacchi 		phy_reg |= I218_ULP_CONFIG1_STICKY_ULP;
1354*42cc51e0SRobert Mustacchi 		phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT;
1355c124a83eSRobert Mustacchi 	} else {
1356c124a83eSRobert Mustacchi 		phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT;
1357*42cc51e0SRobert Mustacchi 		phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP;
1358*42cc51e0SRobert Mustacchi 		phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
1359c124a83eSRobert Mustacchi 	}
1360c124a83eSRobert Mustacchi 	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
1361c124a83eSRobert Mustacchi 
1362c124a83eSRobert Mustacchi 	/* Set Disable SMBus Release on PERST# in MAC */
1363c124a83eSRobert Mustacchi 	mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7);
1364c124a83eSRobert Mustacchi 	mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST;
1365c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg);
1366c124a83eSRobert Mustacchi 
1367c124a83eSRobert Mustacchi 	/* Commit ULP changes in PHY by starting auto ULP configuration */
1368c124a83eSRobert Mustacchi 	phy_reg |= I218_ULP_CONFIG1_START;
1369c124a83eSRobert Mustacchi 	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
1370*42cc51e0SRobert Mustacchi 
1371*42cc51e0SRobert Mustacchi 	if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) &&
1372*42cc51e0SRobert Mustacchi 	    to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
1373*42cc51e0SRobert Mustacchi 		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
1374*42cc51e0SRobert Mustacchi 							oem_reg);
1375*42cc51e0SRobert Mustacchi 		if (ret_val)
1376*42cc51e0SRobert Mustacchi 			goto release;
1377*42cc51e0SRobert Mustacchi 	}
1378*42cc51e0SRobert Mustacchi 
1379c124a83eSRobert Mustacchi release:
1380c124a83eSRobert Mustacchi 	hw->phy.ops.release(hw);
1381c124a83eSRobert Mustacchi out:
1382*42cc51e0SRobert Mustacchi 	if (ret_val)
1383c124a83eSRobert Mustacchi 		DEBUGOUT1("Error in ULP enable flow: %d\n", ret_val);
1384*42cc51e0SRobert Mustacchi 	else
1385c124a83eSRobert Mustacchi 		hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on;
1386c124a83eSRobert Mustacchi 
1387c124a83eSRobert Mustacchi 	return ret_val;
1388c124a83eSRobert Mustacchi }
1389c124a83eSRobert Mustacchi 
1390c124a83eSRobert Mustacchi /**
1391c124a83eSRobert Mustacchi  *  e1000_disable_ulp_lpt_lp - unconfigure Ultra Low Power mode for LynxPoint-LP
1392c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
1393c124a83eSRobert Mustacchi  *  @force: boolean indicating whether or not to force disabling ULP
1394c124a83eSRobert Mustacchi  *
1395c124a83eSRobert Mustacchi  *  Un-configure ULP mode when link is up, the system is transitioned from
1396c124a83eSRobert Mustacchi  *  Sx or the driver is unloaded.  If on a Manageability Engine (ME) enabled
1397c124a83eSRobert Mustacchi  *  system, poll for an indication from ME that ULP has been un-configured.
1398c124a83eSRobert Mustacchi  *  If not on an ME enabled system, un-configure the ULP mode by software.
1399c124a83eSRobert Mustacchi  *
1400c124a83eSRobert Mustacchi  *  During nominal operation, this function is called when link is acquired
1401c124a83eSRobert Mustacchi  *  to disable ULP mode (force=FALSE); otherwise, for example when unloading
1402c124a83eSRobert Mustacchi  *  the driver or during Sx->S0 transitions, this is called with force=TRUE
1403c124a83eSRobert Mustacchi  *  to forcibly disable ULP.
1404c124a83eSRobert Mustacchi  */
1405c124a83eSRobert Mustacchi s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force)
1406c124a83eSRobert Mustacchi {
1407c124a83eSRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
1408c124a83eSRobert Mustacchi 	u32 mac_reg;
1409c124a83eSRobert Mustacchi 	u16 phy_reg;
1410c124a83eSRobert Mustacchi 	int i = 0;
1411c124a83eSRobert Mustacchi 
1412c124a83eSRobert Mustacchi 	if ((hw->mac.type < e1000_pch_lpt) ||
1413c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_LM) ||
1414c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_LPT_I217_V) ||
1415c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_I218_LM2) ||
1416c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_I218_V2) ||
1417c124a83eSRobert Mustacchi 	    (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_off))
1418c124a83eSRobert Mustacchi 		return 0;
1419c124a83eSRobert Mustacchi 
1420c124a83eSRobert Mustacchi 	if (E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID) {
1421c124a83eSRobert Mustacchi 		if (force) {
1422c124a83eSRobert Mustacchi 			/* Request ME un-configure ULP mode in the PHY */
1423c124a83eSRobert Mustacchi 			mac_reg = E1000_READ_REG(hw, E1000_H2ME);
1424c124a83eSRobert Mustacchi 			mac_reg &= ~E1000_H2ME_ULP;
1425c124a83eSRobert Mustacchi 			mac_reg |= E1000_H2ME_ENFORCE_SETTINGS;
1426c124a83eSRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);
1427c124a83eSRobert Mustacchi 		}
1428c124a83eSRobert Mustacchi 
1429*42cc51e0SRobert Mustacchi 		/* Poll up to 300msec for ME to clear ULP_CFG_DONE. */
1430c124a83eSRobert Mustacchi 		while (E1000_READ_REG(hw, E1000_FWSM) &
1431c124a83eSRobert Mustacchi 		       E1000_FWSM_ULP_CFG_DONE) {
1432*42cc51e0SRobert Mustacchi 			if (i++ == 30) {
1433c124a83eSRobert Mustacchi 				ret_val = -E1000_ERR_PHY;
1434c124a83eSRobert Mustacchi 				goto out;
1435c124a83eSRobert Mustacchi 			}
1436c124a83eSRobert Mustacchi 
1437c124a83eSRobert Mustacchi 			msec_delay(10);
1438c124a83eSRobert Mustacchi 		}
1439c124a83eSRobert Mustacchi 		DEBUGOUT1("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10);
1440c124a83eSRobert Mustacchi 
1441c124a83eSRobert Mustacchi 		if (force) {
1442c124a83eSRobert Mustacchi 			mac_reg = E1000_READ_REG(hw, E1000_H2ME);
1443c124a83eSRobert Mustacchi 			mac_reg &= ~E1000_H2ME_ENFORCE_SETTINGS;
1444c124a83eSRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);
1445c124a83eSRobert Mustacchi 		} else {
1446c124a83eSRobert Mustacchi 			/* Clear H2ME.ULP after ME ULP configuration */
1447c124a83eSRobert Mustacchi 			mac_reg = E1000_READ_REG(hw, E1000_H2ME);
1448c124a83eSRobert Mustacchi 			mac_reg &= ~E1000_H2ME_ULP;
1449c124a83eSRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_H2ME, mac_reg);
1450c124a83eSRobert Mustacchi 		}
1451c124a83eSRobert Mustacchi 
1452c124a83eSRobert Mustacchi 		goto out;
1453c124a83eSRobert Mustacchi 	}
1454c124a83eSRobert Mustacchi 
1455c124a83eSRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
1456c124a83eSRobert Mustacchi 	if (ret_val)
1457c124a83eSRobert Mustacchi 		goto out;
1458c124a83eSRobert Mustacchi 
1459c124a83eSRobert Mustacchi 	if (force)
1460c124a83eSRobert Mustacchi 		/* Toggle LANPHYPC Value bit */
1461c124a83eSRobert Mustacchi 		e1000_toggle_lanphypc_pch_lpt(hw);
1462c124a83eSRobert Mustacchi 
1463c124a83eSRobert Mustacchi 	/* Unforce SMBus mode in PHY */
1464c124a83eSRobert Mustacchi 	ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg);
1465c124a83eSRobert Mustacchi 	if (ret_val) {
1466c124a83eSRobert Mustacchi 		/* The MAC might be in PCIe mode, so temporarily force to
1467c124a83eSRobert Mustacchi 		 * SMBus mode in order to access the PHY.
1468c124a83eSRobert Mustacchi 		 */
1469c124a83eSRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
1470c124a83eSRobert Mustacchi 		mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS;
1471c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
1472c124a83eSRobert Mustacchi 
1473c124a83eSRobert Mustacchi 		msec_delay(50);
1474c124a83eSRobert Mustacchi 
1475c124a83eSRobert Mustacchi 		ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL,
1476c124a83eSRobert Mustacchi 						       &phy_reg);
1477c124a83eSRobert Mustacchi 		if (ret_val)
1478c124a83eSRobert Mustacchi 			goto release;
1479c124a83eSRobert Mustacchi 	}
1480c124a83eSRobert Mustacchi 	phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS;
1481c124a83eSRobert Mustacchi 	e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg);
1482c124a83eSRobert Mustacchi 
1483c124a83eSRobert Mustacchi 	/* Unforce SMBus mode in MAC */
1484c124a83eSRobert Mustacchi 	mac_reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
1485c124a83eSRobert Mustacchi 	mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS;
1486c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, mac_reg);
1487c124a83eSRobert Mustacchi 
1488c124a83eSRobert Mustacchi 	/* When ULP mode was previously entered, K1 was disabled by the
1489c124a83eSRobert Mustacchi 	 * hardware.  Re-Enable K1 in the PHY when exiting ULP.
1490c124a83eSRobert Mustacchi 	 */
1491c124a83eSRobert Mustacchi 	ret_val = e1000_read_phy_reg_hv_locked(hw, HV_PM_CTRL, &phy_reg);
1492c124a83eSRobert Mustacchi 	if (ret_val)
1493c124a83eSRobert Mustacchi 		goto release;
1494c124a83eSRobert Mustacchi 	phy_reg |= HV_PM_CTRL_K1_ENABLE;
1495c124a83eSRobert Mustacchi 	e1000_write_phy_reg_hv_locked(hw, HV_PM_CTRL, phy_reg);
1496c124a83eSRobert Mustacchi 
1497c124a83eSRobert Mustacchi 	/* Clear ULP enabled configuration */
1498c124a83eSRobert Mustacchi 	ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg);
1499c124a83eSRobert Mustacchi 	if (ret_val)
1500c124a83eSRobert Mustacchi 		goto release;
1501c124a83eSRobert Mustacchi 		phy_reg &= ~(I218_ULP_CONFIG1_IND |
1502c124a83eSRobert Mustacchi 			     I218_ULP_CONFIG1_STICKY_ULP |
1503c124a83eSRobert Mustacchi 			     I218_ULP_CONFIG1_RESET_TO_SMBUS |
1504c124a83eSRobert Mustacchi 			     I218_ULP_CONFIG1_WOL_HOST |
1505c124a83eSRobert Mustacchi 			     I218_ULP_CONFIG1_INBAND_EXIT |
1506*42cc51e0SRobert Mustacchi 			     I218_ULP_CONFIG1_EN_ULP_LANPHYPC |
1507*42cc51e0SRobert Mustacchi 			     I218_ULP_CONFIG1_DIS_CLR_STICKY_ON_PERST |
1508c124a83eSRobert Mustacchi 			     I218_ULP_CONFIG1_DISABLE_SMB_PERST);
1509c124a83eSRobert Mustacchi 		e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
1510c124a83eSRobert Mustacchi 
1511c124a83eSRobert Mustacchi 		/* Commit ULP changes by starting auto ULP configuration */
1512c124a83eSRobert Mustacchi 		phy_reg |= I218_ULP_CONFIG1_START;
1513c124a83eSRobert Mustacchi 		e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg);
1514c124a83eSRobert Mustacchi 
1515c124a83eSRobert Mustacchi 		/* Clear Disable SMBus Release on PERST# in MAC */
1516c124a83eSRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM7);
1517c124a83eSRobert Mustacchi 		mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST;
1518c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FEXTNVM7, mac_reg);
1519c124a83eSRobert Mustacchi 
1520c124a83eSRobert Mustacchi release:
1521c124a83eSRobert Mustacchi 	hw->phy.ops.release(hw);
1522c124a83eSRobert Mustacchi 	if (force) {
1523c124a83eSRobert Mustacchi 		hw->phy.ops.reset(hw);
1524c124a83eSRobert Mustacchi 		msec_delay(50);
1525c124a83eSRobert Mustacchi 	}
1526c124a83eSRobert Mustacchi out:
1527*42cc51e0SRobert Mustacchi 	if (ret_val)
1528c124a83eSRobert Mustacchi 		DEBUGOUT1("Error in ULP disable flow: %d\n", ret_val);
1529*42cc51e0SRobert Mustacchi 	else
1530c124a83eSRobert Mustacchi 		hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_off;
1531c124a83eSRobert Mustacchi 
1532c124a83eSRobert Mustacchi 	return ret_val;
1533c124a83eSRobert Mustacchi }
1534c124a83eSRobert Mustacchi 
1535c124a83eSRobert Mustacchi /**
153675eba5b6SRobert Mustacchi  *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)
153775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
153875eba5b6SRobert Mustacchi  *
153975eba5b6SRobert Mustacchi  *  Checks to see of the link status of the hardware has changed.  If a
154075eba5b6SRobert Mustacchi  *  change in link status has been detected, then we read the PHY registers
154175eba5b6SRobert Mustacchi  *  to get the current speed/duplex if link exists.
154275eba5b6SRobert Mustacchi  **/
154375eba5b6SRobert Mustacchi static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
154475eba5b6SRobert Mustacchi {
154575eba5b6SRobert Mustacchi 	struct e1000_mac_info *mac = &hw->mac;
1546*42cc51e0SRobert Mustacchi 	s32 ret_val, tipg_reg = 0;
1547*42cc51e0SRobert Mustacchi 	u16 emi_addr, emi_val = 0;
154875eba5b6SRobert Mustacchi 	bool link;
154975eba5b6SRobert Mustacchi 	u16 phy_reg;
155075eba5b6SRobert Mustacchi 
155175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_for_copper_link_ich8lan");
155275eba5b6SRobert Mustacchi 
155375eba5b6SRobert Mustacchi 	/* We only want to go out to the PHY registers to see if Auto-Neg
155475eba5b6SRobert Mustacchi 	 * has completed and/or if our link status has changed.  The
155575eba5b6SRobert Mustacchi 	 * get_link_status flag is set upon receiving a Link Status
155675eba5b6SRobert Mustacchi 	 * Change or Rx Sequence Error interrupt.
155775eba5b6SRobert Mustacchi 	 */
155875eba5b6SRobert Mustacchi 	if (!mac->get_link_status)
155975eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
156075eba5b6SRobert Mustacchi 
156175eba5b6SRobert Mustacchi 		/* First we want to see if the MII Status Register reports
156275eba5b6SRobert Mustacchi 		 * link.  If so, then we want to get the current speed/duplex
156375eba5b6SRobert Mustacchi 		 * of the PHY.
156475eba5b6SRobert Mustacchi 		 */
156575eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
156675eba5b6SRobert Mustacchi 		if (ret_val)
156775eba5b6SRobert Mustacchi 			return ret_val;
156875eba5b6SRobert Mustacchi 
156975eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pchlan) {
157075eba5b6SRobert Mustacchi 		ret_val = e1000_k1_gig_workaround_hv(hw, link);
157175eba5b6SRobert Mustacchi 		if (ret_val)
157275eba5b6SRobert Mustacchi 			return ret_val;
157375eba5b6SRobert Mustacchi 	}
157475eba5b6SRobert Mustacchi 
1575c124a83eSRobert Mustacchi 	/* When connected at 10Mbps half-duplex, some parts are excessively
157675eba5b6SRobert Mustacchi 	 * aggressive resulting in many collisions. To avoid this, increase
157775eba5b6SRobert Mustacchi 	 * the IPG and reduce Rx latency in the PHY.
157875eba5b6SRobert Mustacchi 	 */
1579c124a83eSRobert Mustacchi 	if (((hw->mac.type == e1000_pch2lan) ||
1580*42cc51e0SRobert Mustacchi 	     (hw->mac.type == e1000_pch_lpt) ||
1581*42cc51e0SRobert Mustacchi 	     (hw->mac.type == e1000_pch_spt)) && link) {
1582*42cc51e0SRobert Mustacchi 		u16 speed, duplex;
1583c124a83eSRobert Mustacchi 
1584*42cc51e0SRobert Mustacchi 		e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex);
1585*42cc51e0SRobert Mustacchi 		tipg_reg = E1000_READ_REG(hw, E1000_TIPG);
1586*42cc51e0SRobert Mustacchi 		tipg_reg &= ~E1000_TIPG_IPGT_MASK;
158775eba5b6SRobert Mustacchi 
1588*42cc51e0SRobert Mustacchi 		if (duplex == HALF_DUPLEX && speed == SPEED_10) {
1589*42cc51e0SRobert Mustacchi 			tipg_reg |= 0xFF;
159075eba5b6SRobert Mustacchi 			/* Reduce Rx latency in analog PHY */
1591*42cc51e0SRobert Mustacchi 			emi_val = 0;
1592*42cc51e0SRobert Mustacchi 		} else if (hw->mac.type == e1000_pch_spt &&
1593*42cc51e0SRobert Mustacchi 			   duplex == FULL_DUPLEX && speed != SPEED_1000) {
1594*42cc51e0SRobert Mustacchi 			tipg_reg |= 0xC;
1595*42cc51e0SRobert Mustacchi 			emi_val = 1;
1596*42cc51e0SRobert Mustacchi 		} else {
1597*42cc51e0SRobert Mustacchi 			/* Roll back the default values */
1598*42cc51e0SRobert Mustacchi 			tipg_reg |= 0x08;
1599*42cc51e0SRobert Mustacchi 			emi_val = 1;
1600*42cc51e0SRobert Mustacchi 		}
1601*42cc51e0SRobert Mustacchi 
1602*42cc51e0SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_TIPG, tipg_reg);
1603*42cc51e0SRobert Mustacchi 
160475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
160575eba5b6SRobert Mustacchi 		if (ret_val)
160675eba5b6SRobert Mustacchi 			return ret_val;
160775eba5b6SRobert Mustacchi 
1608c124a83eSRobert Mustacchi 		if (hw->mac.type == e1000_pch2lan)
1609c124a83eSRobert Mustacchi 			emi_addr = I82579_RX_CONFIG;
1610c124a83eSRobert Mustacchi 		else
1611c124a83eSRobert Mustacchi 			emi_addr = I217_RX_CONFIG;
1612*42cc51e0SRobert Mustacchi 		ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
161375eba5b6SRobert Mustacchi 
1614*42cc51e0SRobert Mustacchi 		if (hw->mac.type == e1000_pch_lpt ||
1615*42cc51e0SRobert Mustacchi 		    hw->mac.type == e1000_pch_spt) {
1616*42cc51e0SRobert Mustacchi 			u16 phy_reg;
1617*42cc51e0SRobert Mustacchi 
1618*42cc51e0SRobert Mustacchi 			hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG,
1619*42cc51e0SRobert Mustacchi 						    &phy_reg);
1620*42cc51e0SRobert Mustacchi 			phy_reg &= ~I217_PLL_CLOCK_GATE_MASK;
1621*42cc51e0SRobert Mustacchi 			if (speed == SPEED_100 || speed == SPEED_10)
1622*42cc51e0SRobert Mustacchi 				phy_reg |= 0x3E8;
1623*42cc51e0SRobert Mustacchi 			else
1624*42cc51e0SRobert Mustacchi 				phy_reg |= 0xFA;
1625*42cc51e0SRobert Mustacchi 			hw->phy.ops.write_reg_locked(hw,
1626*42cc51e0SRobert Mustacchi 						     I217_PLL_CLOCK_GATE_REG,
1627*42cc51e0SRobert Mustacchi 						     phy_reg);
1628*42cc51e0SRobert Mustacchi 		}
162975eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
163075eba5b6SRobert Mustacchi 
163175eba5b6SRobert Mustacchi 		if (ret_val)
163275eba5b6SRobert Mustacchi 			return ret_val;
1633*42cc51e0SRobert Mustacchi 
1634*42cc51e0SRobert Mustacchi 		if (hw->mac.type == e1000_pch_spt) {
1635*42cc51e0SRobert Mustacchi 			u16 data;
1636*42cc51e0SRobert Mustacchi 			u16 ptr_gap;
1637*42cc51e0SRobert Mustacchi 
1638*42cc51e0SRobert Mustacchi 			if (speed == SPEED_1000) {
1639*42cc51e0SRobert Mustacchi 				ret_val = hw->phy.ops.acquire(hw);
1640*42cc51e0SRobert Mustacchi 				if (ret_val)
1641*42cc51e0SRobert Mustacchi 					return ret_val;
1642*42cc51e0SRobert Mustacchi 
1643*42cc51e0SRobert Mustacchi 				ret_val = hw->phy.ops.read_reg_locked(hw,
1644*42cc51e0SRobert Mustacchi 							      PHY_REG(776, 20),
1645*42cc51e0SRobert Mustacchi 							      &data);
1646*42cc51e0SRobert Mustacchi 				if (ret_val) {
1647*42cc51e0SRobert Mustacchi 					hw->phy.ops.release(hw);
1648*42cc51e0SRobert Mustacchi 					return ret_val;
164975eba5b6SRobert Mustacchi 				}
1650*42cc51e0SRobert Mustacchi 
1651*42cc51e0SRobert Mustacchi 				ptr_gap = (data & (0x3FF << 2)) >> 2;
1652*42cc51e0SRobert Mustacchi 				if (ptr_gap < 0x18) {
1653*42cc51e0SRobert Mustacchi 					data &= ~(0x3FF << 2);
1654*42cc51e0SRobert Mustacchi 					data |= (0x18 << 2);
1655*42cc51e0SRobert Mustacchi 					ret_val =
1656*42cc51e0SRobert Mustacchi 						hw->phy.ops.write_reg_locked(hw,
1657*42cc51e0SRobert Mustacchi 							PHY_REG(776, 20), data);
1658*42cc51e0SRobert Mustacchi 				}
1659*42cc51e0SRobert Mustacchi 				hw->phy.ops.release(hw);
1660*42cc51e0SRobert Mustacchi 				if (ret_val)
1661*42cc51e0SRobert Mustacchi 					return ret_val;
1662*42cc51e0SRobert Mustacchi 			} else {
1663*42cc51e0SRobert Mustacchi 				ret_val = hw->phy.ops.acquire(hw);
1664*42cc51e0SRobert Mustacchi 				if (ret_val)
1665*42cc51e0SRobert Mustacchi 					return ret_val;
1666*42cc51e0SRobert Mustacchi 
1667*42cc51e0SRobert Mustacchi 				ret_val = hw->phy.ops.write_reg_locked(hw,
1668*42cc51e0SRobert Mustacchi 							     PHY_REG(776, 20),
1669*42cc51e0SRobert Mustacchi 							     0xC023);
1670*42cc51e0SRobert Mustacchi 				hw->phy.ops.release(hw);
1671*42cc51e0SRobert Mustacchi 				if (ret_val)
1672*42cc51e0SRobert Mustacchi 					return ret_val;
1673*42cc51e0SRobert Mustacchi 
1674*42cc51e0SRobert Mustacchi 			}
1675*42cc51e0SRobert Mustacchi 		}
1676*42cc51e0SRobert Mustacchi 	}
1677*42cc51e0SRobert Mustacchi 
1678*42cc51e0SRobert Mustacchi 	/* I217 Packet Loss issue:
1679*42cc51e0SRobert Mustacchi 	 * ensure that FEXTNVM4 Beacon Duration is set correctly
1680*42cc51e0SRobert Mustacchi 	 * on power up.
1681*42cc51e0SRobert Mustacchi 	 * Set the Beacon Duration for I217 to 8 usec
1682*42cc51e0SRobert Mustacchi 	 */
1683*42cc51e0SRobert Mustacchi 	if ((hw->mac.type == e1000_pch_lpt) ||
1684*42cc51e0SRobert Mustacchi 	    (hw->mac.type == e1000_pch_spt)) {
1685*42cc51e0SRobert Mustacchi 		u32 mac_reg;
1686*42cc51e0SRobert Mustacchi 
1687*42cc51e0SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
1688*42cc51e0SRobert Mustacchi 		mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
1689*42cc51e0SRobert Mustacchi 		mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
1690*42cc51e0SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg);
169175eba5b6SRobert Mustacchi 	}
169275eba5b6SRobert Mustacchi 
169375eba5b6SRobert Mustacchi 	/* Work-around I218 hang issue */
169475eba5b6SRobert Mustacchi 	if ((hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
1695c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
1696c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_I218_LM3) ||
1697c124a83eSRobert Mustacchi 	    (hw->device_id == E1000_DEV_ID_PCH_I218_V3)) {
169875eba5b6SRobert Mustacchi 		ret_val = e1000_k1_workaround_lpt_lp(hw, link);
169975eba5b6SRobert Mustacchi 		if (ret_val)
170075eba5b6SRobert Mustacchi 			return ret_val;
170175eba5b6SRobert Mustacchi 	}
1702*42cc51e0SRobert Mustacchi 	if ((hw->mac.type == e1000_pch_lpt) ||
1703*42cc51e0SRobert Mustacchi 	    (hw->mac.type == e1000_pch_spt)) {
1704c124a83eSRobert Mustacchi 		/* Set platform power management values for
1705c124a83eSRobert Mustacchi 		 * Latency Tolerance Reporting (LTR)
1706c124a83eSRobert Mustacchi 		 * Optimized Buffer Flush/Fill (OBFF)
170775eba5b6SRobert Mustacchi 		 */
170875eba5b6SRobert Mustacchi 		ret_val = e1000_platform_pm_pch_lpt(hw, link);
170975eba5b6SRobert Mustacchi 		if (ret_val)
171075eba5b6SRobert Mustacchi 			return ret_val;
171175eba5b6SRobert Mustacchi 	}
171275eba5b6SRobert Mustacchi 
171375eba5b6SRobert Mustacchi 	/* Clear link partner's EEE ability */
171475eba5b6SRobert Mustacchi 	hw->dev_spec.ich8lan.eee_lp_ability = 0;
171575eba5b6SRobert Mustacchi 
1716*42cc51e0SRobert Mustacchi 	/* FEXTNVM6 K1-off workaround */
1717*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt) {
1718*42cc51e0SRobert Mustacchi 		u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
1719*42cc51e0SRobert Mustacchi 		u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
1720*42cc51e0SRobert Mustacchi 
1721*42cc51e0SRobert Mustacchi 		if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
1722*42cc51e0SRobert Mustacchi 			fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
1723*42cc51e0SRobert Mustacchi 		else
1724*42cc51e0SRobert Mustacchi 			fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
1725*42cc51e0SRobert Mustacchi 
1726*42cc51e0SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
1727*42cc51e0SRobert Mustacchi 	}
1728*42cc51e0SRobert Mustacchi 
172975eba5b6SRobert Mustacchi 	if (!link)
173075eba5b6SRobert Mustacchi 		return E1000_SUCCESS; /* No link detected */
173175eba5b6SRobert Mustacchi 
173275eba5b6SRobert Mustacchi 	mac->get_link_status = FALSE;
173375eba5b6SRobert Mustacchi 
173475eba5b6SRobert Mustacchi 	switch (hw->mac.type) {
173575eba5b6SRobert Mustacchi 	case e1000_pch2lan:
173675eba5b6SRobert Mustacchi 		ret_val = e1000_k1_workaround_lv(hw);
173775eba5b6SRobert Mustacchi 		if (ret_val)
173875eba5b6SRobert Mustacchi 			return ret_val;
173975eba5b6SRobert Mustacchi 		/* fall-thru */
174075eba5b6SRobert Mustacchi 	case e1000_pchlan:
174175eba5b6SRobert Mustacchi 		if (hw->phy.type == e1000_phy_82578) {
174275eba5b6SRobert Mustacchi 			ret_val = e1000_link_stall_workaround_hv(hw);
174375eba5b6SRobert Mustacchi 			if (ret_val)
174475eba5b6SRobert Mustacchi 				return ret_val;
174575eba5b6SRobert Mustacchi 		}
174675eba5b6SRobert Mustacchi 
174775eba5b6SRobert Mustacchi 		/* Workaround for PCHx parts in half-duplex:
174875eba5b6SRobert Mustacchi 		 * Set the number of preambles removed from the packet
174975eba5b6SRobert Mustacchi 		 * when it is passed from the PHY to the MAC to prevent
175075eba5b6SRobert Mustacchi 		 * the MAC from misinterpreting the packet type.
175175eba5b6SRobert Mustacchi 		 */
175275eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg);
175375eba5b6SRobert Mustacchi 		phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK;
175475eba5b6SRobert Mustacchi 
175575eba5b6SRobert Mustacchi 		if ((E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_FD) !=
175675eba5b6SRobert Mustacchi 		    E1000_STATUS_FD)
175775eba5b6SRobert Mustacchi 			phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT);
175875eba5b6SRobert Mustacchi 
175975eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg);
176075eba5b6SRobert Mustacchi 		break;
176175eba5b6SRobert Mustacchi 	default:
176275eba5b6SRobert Mustacchi 		break;
176375eba5b6SRobert Mustacchi 	}
176475eba5b6SRobert Mustacchi 
176575eba5b6SRobert Mustacchi 	/* Check if there was DownShift, must be checked
176675eba5b6SRobert Mustacchi 	 * immediately after link-up
176775eba5b6SRobert Mustacchi 	 */
176875eba5b6SRobert Mustacchi 	e1000_check_downshift_generic(hw);
176975eba5b6SRobert Mustacchi 
177075eba5b6SRobert Mustacchi 	/* Enable/Disable EEE after link up */
1771c124a83eSRobert Mustacchi 	if (hw->phy.type > e1000_phy_82579) {
177275eba5b6SRobert Mustacchi 		ret_val = e1000_set_eee_pchlan(hw);
177375eba5b6SRobert Mustacchi 		if (ret_val)
177475eba5b6SRobert Mustacchi 			return ret_val;
1775c124a83eSRobert Mustacchi 	}
177675eba5b6SRobert Mustacchi 
177775eba5b6SRobert Mustacchi 	/* If we are forcing speed/duplex, then we simply return since
177875eba5b6SRobert Mustacchi 	 * we have already determined whether we have link or not.
177975eba5b6SRobert Mustacchi 	 */
178075eba5b6SRobert Mustacchi 	if (!mac->autoneg)
178175eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
178275eba5b6SRobert Mustacchi 
178375eba5b6SRobert Mustacchi 	/* Auto-Neg is enabled.  Auto Speed Detection takes care
178475eba5b6SRobert Mustacchi 	 * of MAC speed/duplex configuration.  So we only need to
178575eba5b6SRobert Mustacchi 	 * configure Collision Distance in the MAC.
178675eba5b6SRobert Mustacchi 	 */
178775eba5b6SRobert Mustacchi 	mac->ops.config_collision_dist(hw);
178875eba5b6SRobert Mustacchi 
178975eba5b6SRobert Mustacchi 	/* Configure Flow Control now that Auto-Neg has completed.
179075eba5b6SRobert Mustacchi 	 * First, we need to restore the desired flow control
179175eba5b6SRobert Mustacchi 	 * settings because we may have had to re-autoneg with a
179275eba5b6SRobert Mustacchi 	 * different link partner.
179375eba5b6SRobert Mustacchi 	 */
179475eba5b6SRobert Mustacchi 	ret_val = e1000_config_fc_after_link_up_generic(hw);
179575eba5b6SRobert Mustacchi 	if (ret_val)
179675eba5b6SRobert Mustacchi 		DEBUGOUT("Error configuring flow control\n");
179775eba5b6SRobert Mustacchi 
179875eba5b6SRobert Mustacchi 	return ret_val;
179975eba5b6SRobert Mustacchi }
180075eba5b6SRobert Mustacchi 
180175eba5b6SRobert Mustacchi /**
180275eba5b6SRobert Mustacchi  *  e1000_init_function_pointers_ich8lan - Initialize ICH8 function pointers
180375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
180475eba5b6SRobert Mustacchi  *
180575eba5b6SRobert Mustacchi  *  Initialize family-specific function pointers for PHY, MAC, and NVM.
180675eba5b6SRobert Mustacchi  **/
180775eba5b6SRobert Mustacchi void e1000_init_function_pointers_ich8lan(struct e1000_hw *hw)
180875eba5b6SRobert Mustacchi {
180975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_function_pointers_ich8lan");
181075eba5b6SRobert Mustacchi 
181175eba5b6SRobert Mustacchi 	hw->mac.ops.init_params = e1000_init_mac_params_ich8lan;
181275eba5b6SRobert Mustacchi 	hw->nvm.ops.init_params = e1000_init_nvm_params_ich8lan;
181375eba5b6SRobert Mustacchi 	switch (hw->mac.type) {
181475eba5b6SRobert Mustacchi 	case e1000_ich8lan:
181575eba5b6SRobert Mustacchi 	case e1000_ich9lan:
181675eba5b6SRobert Mustacchi 	case e1000_ich10lan:
181775eba5b6SRobert Mustacchi 		hw->phy.ops.init_params = e1000_init_phy_params_ich8lan;
181875eba5b6SRobert Mustacchi 		break;
181975eba5b6SRobert Mustacchi 	case e1000_pchlan:
182075eba5b6SRobert Mustacchi 	case e1000_pch2lan:
182175eba5b6SRobert Mustacchi 	case e1000_pch_lpt:
1822*42cc51e0SRobert Mustacchi 	case e1000_pch_spt:
182375eba5b6SRobert Mustacchi 		hw->phy.ops.init_params = e1000_init_phy_params_pchlan;
182475eba5b6SRobert Mustacchi 		break;
182575eba5b6SRobert Mustacchi 	default:
182675eba5b6SRobert Mustacchi 		break;
182775eba5b6SRobert Mustacchi 	}
182875eba5b6SRobert Mustacchi }
182975eba5b6SRobert Mustacchi 
183075eba5b6SRobert Mustacchi /**
183175eba5b6SRobert Mustacchi  *  e1000_acquire_nvm_ich8lan - Acquire NVM mutex
183275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
183375eba5b6SRobert Mustacchi  *
183475eba5b6SRobert Mustacchi  *  Acquires the mutex for performing NVM operations.
183575eba5b6SRobert Mustacchi  **/
183675eba5b6SRobert Mustacchi static s32 e1000_acquire_nvm_ich8lan(struct e1000_hw *hw)
183775eba5b6SRobert Mustacchi {
183875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_nvm_ich8lan");
183975eba5b6SRobert Mustacchi 
184075eba5b6SRobert Mustacchi 	E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.nvm_mutex);
184175eba5b6SRobert Mustacchi 
184275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
184375eba5b6SRobert Mustacchi }
184475eba5b6SRobert Mustacchi 
184575eba5b6SRobert Mustacchi /**
184675eba5b6SRobert Mustacchi  *  e1000_release_nvm_ich8lan - Release NVM mutex
184775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
184875eba5b6SRobert Mustacchi  *
184975eba5b6SRobert Mustacchi  *  Releases the mutex used while performing NVM operations.
185075eba5b6SRobert Mustacchi  **/
185175eba5b6SRobert Mustacchi static void e1000_release_nvm_ich8lan(struct e1000_hw *hw)
185275eba5b6SRobert Mustacchi {
185375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_nvm_ich8lan");
185475eba5b6SRobert Mustacchi 
185575eba5b6SRobert Mustacchi 	E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.nvm_mutex);
185675eba5b6SRobert Mustacchi 
185775eba5b6SRobert Mustacchi 	return;
185875eba5b6SRobert Mustacchi }
185975eba5b6SRobert Mustacchi 
186075eba5b6SRobert Mustacchi /**
186175eba5b6SRobert Mustacchi  *  e1000_acquire_swflag_ich8lan - Acquire software control flag
186275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
186375eba5b6SRobert Mustacchi  *
186475eba5b6SRobert Mustacchi  *  Acquires the software control flag for performing PHY and select
186575eba5b6SRobert Mustacchi  *  MAC CSR accesses.
186675eba5b6SRobert Mustacchi  **/
186775eba5b6SRobert Mustacchi static s32 e1000_acquire_swflag_ich8lan(struct e1000_hw *hw)
186875eba5b6SRobert Mustacchi {
186975eba5b6SRobert Mustacchi 	u32 extcnf_ctrl, timeout = PHY_CFG_TIMEOUT;
187075eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
187175eba5b6SRobert Mustacchi 
187275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_acquire_swflag_ich8lan");
187375eba5b6SRobert Mustacchi 
187475eba5b6SRobert Mustacchi 	E1000_MUTEX_LOCK(&hw->dev_spec.ich8lan.swflag_mutex);
187575eba5b6SRobert Mustacchi 
187675eba5b6SRobert Mustacchi 	while (timeout) {
187775eba5b6SRobert Mustacchi 		extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
187875eba5b6SRobert Mustacchi 		if (!(extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG))
187975eba5b6SRobert Mustacchi 			break;
188075eba5b6SRobert Mustacchi 
188175eba5b6SRobert Mustacchi 		msec_delay_irq(1);
188275eba5b6SRobert Mustacchi 		timeout--;
188375eba5b6SRobert Mustacchi 	}
188475eba5b6SRobert Mustacchi 
188575eba5b6SRobert Mustacchi 	if (!timeout) {
188675eba5b6SRobert Mustacchi 		DEBUGOUT("SW has already locked the resource.\n");
188775eba5b6SRobert Mustacchi 		ret_val = -E1000_ERR_CONFIG;
188875eba5b6SRobert Mustacchi 		goto out;
188975eba5b6SRobert Mustacchi 	}
189075eba5b6SRobert Mustacchi 
189175eba5b6SRobert Mustacchi 	timeout = SW_FLAG_TIMEOUT;
189275eba5b6SRobert Mustacchi 
189375eba5b6SRobert Mustacchi 	extcnf_ctrl |= E1000_EXTCNF_CTRL_SWFLAG;
189475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
189575eba5b6SRobert Mustacchi 
189675eba5b6SRobert Mustacchi 	while (timeout) {
189775eba5b6SRobert Mustacchi 		extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
189875eba5b6SRobert Mustacchi 		if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG)
189975eba5b6SRobert Mustacchi 			break;
190075eba5b6SRobert Mustacchi 
190175eba5b6SRobert Mustacchi 		msec_delay_irq(1);
190275eba5b6SRobert Mustacchi 		timeout--;
190375eba5b6SRobert Mustacchi 	}
190475eba5b6SRobert Mustacchi 
190575eba5b6SRobert Mustacchi 	if (!timeout) {
190675eba5b6SRobert Mustacchi 		DEBUGOUT2("Failed to acquire the semaphore, FW or HW has it: FWSM=0x%8.8x EXTCNF_CTRL=0x%8.8x)\n",
190775eba5b6SRobert Mustacchi 			  E1000_READ_REG(hw, E1000_FWSM), extcnf_ctrl);
190875eba5b6SRobert Mustacchi 		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
190975eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
191075eba5b6SRobert Mustacchi 		ret_val = -E1000_ERR_CONFIG;
191175eba5b6SRobert Mustacchi 		goto out;
191275eba5b6SRobert Mustacchi 	}
191375eba5b6SRobert Mustacchi 
191475eba5b6SRobert Mustacchi out:
191575eba5b6SRobert Mustacchi 	if (ret_val)
191675eba5b6SRobert Mustacchi 		E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
191775eba5b6SRobert Mustacchi 
191875eba5b6SRobert Mustacchi 	return ret_val;
191975eba5b6SRobert Mustacchi }
192075eba5b6SRobert Mustacchi 
192175eba5b6SRobert Mustacchi /**
192275eba5b6SRobert Mustacchi  *  e1000_release_swflag_ich8lan - Release software control flag
192375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
192475eba5b6SRobert Mustacchi  *
192575eba5b6SRobert Mustacchi  *  Releases the software control flag for performing PHY and select
192675eba5b6SRobert Mustacchi  *  MAC CSR accesses.
192775eba5b6SRobert Mustacchi  **/
192875eba5b6SRobert Mustacchi static void e1000_release_swflag_ich8lan(struct e1000_hw *hw)
192975eba5b6SRobert Mustacchi {
193075eba5b6SRobert Mustacchi 	u32 extcnf_ctrl;
193175eba5b6SRobert Mustacchi 
193275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_release_swflag_ich8lan");
193375eba5b6SRobert Mustacchi 
193475eba5b6SRobert Mustacchi 	extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
193575eba5b6SRobert Mustacchi 
193675eba5b6SRobert Mustacchi 	if (extcnf_ctrl & E1000_EXTCNF_CTRL_SWFLAG) {
193775eba5b6SRobert Mustacchi 		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_SWFLAG;
193875eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
193975eba5b6SRobert Mustacchi 	} else {
194075eba5b6SRobert Mustacchi 		DEBUGOUT("Semaphore unexpectedly released by sw/fw/hw\n");
194175eba5b6SRobert Mustacchi 	}
194275eba5b6SRobert Mustacchi 
194375eba5b6SRobert Mustacchi 	E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
194475eba5b6SRobert Mustacchi 
194575eba5b6SRobert Mustacchi 	return;
194675eba5b6SRobert Mustacchi }
194775eba5b6SRobert Mustacchi 
194875eba5b6SRobert Mustacchi /**
194975eba5b6SRobert Mustacchi  *  e1000_check_mng_mode_ich8lan - Checks management mode
195075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
195175eba5b6SRobert Mustacchi  *
195275eba5b6SRobert Mustacchi  *  This checks if the adapter has any manageability enabled.
195375eba5b6SRobert Mustacchi  *  This is a function pointer entry point only called by read/write
195475eba5b6SRobert Mustacchi  *  routines for the PHY and NVM parts.
195575eba5b6SRobert Mustacchi  **/
195675eba5b6SRobert Mustacchi static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)
195775eba5b6SRobert Mustacchi {
195875eba5b6SRobert Mustacchi 	u32 fwsm;
195975eba5b6SRobert Mustacchi 
196075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_mng_mode_ich8lan");
196175eba5b6SRobert Mustacchi 
196275eba5b6SRobert Mustacchi 	fwsm = E1000_READ_REG(hw, E1000_FWSM);
196375eba5b6SRobert Mustacchi 
196475eba5b6SRobert Mustacchi 	return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
196575eba5b6SRobert Mustacchi 	       ((fwsm & E1000_FWSM_MODE_MASK) ==
196675eba5b6SRobert Mustacchi 		(E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
196775eba5b6SRobert Mustacchi }
196875eba5b6SRobert Mustacchi 
196975eba5b6SRobert Mustacchi /**
197075eba5b6SRobert Mustacchi  *  e1000_check_mng_mode_pchlan - Checks management mode
197175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
197275eba5b6SRobert Mustacchi  *
197375eba5b6SRobert Mustacchi  *  This checks if the adapter has iAMT enabled.
197475eba5b6SRobert Mustacchi  *  This is a function pointer entry point only called by read/write
197575eba5b6SRobert Mustacchi  *  routines for the PHY and NVM parts.
197675eba5b6SRobert Mustacchi  **/
197775eba5b6SRobert Mustacchi static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)
197875eba5b6SRobert Mustacchi {
197975eba5b6SRobert Mustacchi 	u32 fwsm;
198075eba5b6SRobert Mustacchi 
198175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_mng_mode_pchlan");
198275eba5b6SRobert Mustacchi 
198375eba5b6SRobert Mustacchi 	fwsm = E1000_READ_REG(hw, E1000_FWSM);
198475eba5b6SRobert Mustacchi 
198575eba5b6SRobert Mustacchi 	return (fwsm & E1000_ICH_FWSM_FW_VALID) &&
198675eba5b6SRobert Mustacchi 	       (fwsm & (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));
198775eba5b6SRobert Mustacchi }
198875eba5b6SRobert Mustacchi 
198975eba5b6SRobert Mustacchi /**
199075eba5b6SRobert Mustacchi  *  e1000_rar_set_pch2lan - Set receive address register
199175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
199275eba5b6SRobert Mustacchi  *  @addr: pointer to the receive address
199375eba5b6SRobert Mustacchi  *  @index: receive address array register
199475eba5b6SRobert Mustacchi  *
199575eba5b6SRobert Mustacchi  *  Sets the receive address array register at index to the address passed
199675eba5b6SRobert Mustacchi  *  in by addr.  For 82579, RAR[0] is the base address register that is to
199775eba5b6SRobert Mustacchi  *  contain the MAC address but RAR[1-6] are reserved for manageability (ME).
199875eba5b6SRobert Mustacchi  *  Use SHRA[0-3] in place of those reserved for ME.
199975eba5b6SRobert Mustacchi  **/
2000c124a83eSRobert Mustacchi static int e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)
200175eba5b6SRobert Mustacchi {
200275eba5b6SRobert Mustacchi 	u32 rar_low, rar_high;
200375eba5b6SRobert Mustacchi 
200475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_rar_set_pch2lan");
200575eba5b6SRobert Mustacchi 
200675eba5b6SRobert Mustacchi 	/* HW expects these in little endian so we reverse the byte order
200775eba5b6SRobert Mustacchi 	 * from network order (big endian) to little endian
200875eba5b6SRobert Mustacchi 	 */
200975eba5b6SRobert Mustacchi 	rar_low = ((u32) addr[0] |
201075eba5b6SRobert Mustacchi 		   ((u32) addr[1] << 8) |
201175eba5b6SRobert Mustacchi 		   ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
201275eba5b6SRobert Mustacchi 
201375eba5b6SRobert Mustacchi 	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
201475eba5b6SRobert Mustacchi 
201575eba5b6SRobert Mustacchi 	/* If MAC address zero, no need to set the AV bit */
201675eba5b6SRobert Mustacchi 	if (rar_low || rar_high)
201775eba5b6SRobert Mustacchi 		rar_high |= E1000_RAH_AV;
201875eba5b6SRobert Mustacchi 
201975eba5b6SRobert Mustacchi 	if (index == 0) {
202075eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_RAL(index), rar_low);
202175eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
202275eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);
202375eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
2024c124a83eSRobert Mustacchi 		return E1000_SUCCESS;
202575eba5b6SRobert Mustacchi 	}
202675eba5b6SRobert Mustacchi 
2027c124a83eSRobert Mustacchi 	/* RAR[1-6] are owned by manageability.  Skip those and program the
2028c124a83eSRobert Mustacchi 	 * next address into the SHRA register array.
2029c124a83eSRobert Mustacchi 	 */
2030c124a83eSRobert Mustacchi 	if (index < (u32) (hw->mac.rar_entry_count)) {
203175eba5b6SRobert Mustacchi 		s32 ret_val;
203275eba5b6SRobert Mustacchi 
203375eba5b6SRobert Mustacchi 		ret_val = e1000_acquire_swflag_ich8lan(hw);
203475eba5b6SRobert Mustacchi 		if (ret_val)
203575eba5b6SRobert Mustacchi 			goto out;
203675eba5b6SRobert Mustacchi 
203775eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_SHRAL(index - 1), rar_low);
203875eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
203975eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_SHRAH(index - 1), rar_high);
204075eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
204175eba5b6SRobert Mustacchi 
204275eba5b6SRobert Mustacchi 		e1000_release_swflag_ich8lan(hw);
204375eba5b6SRobert Mustacchi 
204475eba5b6SRobert Mustacchi 		/* verify the register updates */
204575eba5b6SRobert Mustacchi 		if ((E1000_READ_REG(hw, E1000_SHRAL(index - 1)) == rar_low) &&
204675eba5b6SRobert Mustacchi 		    (E1000_READ_REG(hw, E1000_SHRAH(index - 1)) == rar_high))
2047c124a83eSRobert Mustacchi 			return E1000_SUCCESS;
204875eba5b6SRobert Mustacchi 
204975eba5b6SRobert Mustacchi 		DEBUGOUT2("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n",
205075eba5b6SRobert Mustacchi 			 (index - 1), E1000_READ_REG(hw, E1000_FWSM));
205175eba5b6SRobert Mustacchi 	}
205275eba5b6SRobert Mustacchi 
205375eba5b6SRobert Mustacchi out:
205475eba5b6SRobert Mustacchi 	DEBUGOUT1("Failed to write receive address at index %d\n", index);
2055c124a83eSRobert Mustacchi 	return -E1000_ERR_CONFIG;
205675eba5b6SRobert Mustacchi }
205775eba5b6SRobert Mustacchi 
205875eba5b6SRobert Mustacchi /**
205975eba5b6SRobert Mustacchi  *  e1000_rar_set_pch_lpt - Set receive address registers
206075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
206175eba5b6SRobert Mustacchi  *  @addr: pointer to the receive address
206275eba5b6SRobert Mustacchi  *  @index: receive address array register
206375eba5b6SRobert Mustacchi  *
206475eba5b6SRobert Mustacchi  *  Sets the receive address register array at index to the address passed
206575eba5b6SRobert Mustacchi  *  in by addr. For LPT, RAR[0] is the base address register that is to
206675eba5b6SRobert Mustacchi  *  contain the MAC address. SHRA[0-10] are the shared receive address
206775eba5b6SRobert Mustacchi  *  registers that are shared between the Host and manageability engine (ME).
206875eba5b6SRobert Mustacchi  **/
2069c124a83eSRobert Mustacchi static int e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)
207075eba5b6SRobert Mustacchi {
207175eba5b6SRobert Mustacchi 	u32 rar_low, rar_high;
207275eba5b6SRobert Mustacchi 	u32 wlock_mac;
207375eba5b6SRobert Mustacchi 
207475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_rar_set_pch_lpt");
207575eba5b6SRobert Mustacchi 
207675eba5b6SRobert Mustacchi 	/* HW expects these in little endian so we reverse the byte order
207775eba5b6SRobert Mustacchi 	 * from network order (big endian) to little endian
207875eba5b6SRobert Mustacchi 	 */
207975eba5b6SRobert Mustacchi 	rar_low = ((u32) addr[0] | ((u32) addr[1] << 8) |
208075eba5b6SRobert Mustacchi 		   ((u32) addr[2] << 16) | ((u32) addr[3] << 24));
208175eba5b6SRobert Mustacchi 
208275eba5b6SRobert Mustacchi 	rar_high = ((u32) addr[4] | ((u32) addr[5] << 8));
208375eba5b6SRobert Mustacchi 
208475eba5b6SRobert Mustacchi 	/* If MAC address zero, no need to set the AV bit */
208575eba5b6SRobert Mustacchi 	if (rar_low || rar_high)
208675eba5b6SRobert Mustacchi 		rar_high |= E1000_RAH_AV;
208775eba5b6SRobert Mustacchi 
208875eba5b6SRobert Mustacchi 	if (index == 0) {
208975eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_RAL(index), rar_low);
209075eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
209175eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_RAH(index), rar_high);
209275eba5b6SRobert Mustacchi 		E1000_WRITE_FLUSH(hw);
2093c124a83eSRobert Mustacchi 		return E1000_SUCCESS;
209475eba5b6SRobert Mustacchi 	}
209575eba5b6SRobert Mustacchi 
209675eba5b6SRobert Mustacchi 	/* The manageability engine (ME) can lock certain SHRAR registers that
209775eba5b6SRobert Mustacchi 	 * it is using - those registers are unavailable for use.
209875eba5b6SRobert Mustacchi 	 */
209975eba5b6SRobert Mustacchi 	if (index < hw->mac.rar_entry_count) {
210075eba5b6SRobert Mustacchi 		wlock_mac = E1000_READ_REG(hw, E1000_FWSM) &
210175eba5b6SRobert Mustacchi 			    E1000_FWSM_WLOCK_MAC_MASK;
210275eba5b6SRobert Mustacchi 		wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT;
210375eba5b6SRobert Mustacchi 
210475eba5b6SRobert Mustacchi 		/* Check if all SHRAR registers are locked */
210575eba5b6SRobert Mustacchi 		if (wlock_mac == 1)
210675eba5b6SRobert Mustacchi 			goto out;
210775eba5b6SRobert Mustacchi 
210875eba5b6SRobert Mustacchi 		if ((wlock_mac == 0) || (index <= wlock_mac)) {
210975eba5b6SRobert Mustacchi 			s32 ret_val;
211075eba5b6SRobert Mustacchi 
211175eba5b6SRobert Mustacchi 			ret_val = e1000_acquire_swflag_ich8lan(hw);
211275eba5b6SRobert Mustacchi 
211375eba5b6SRobert Mustacchi 			if (ret_val)
211475eba5b6SRobert Mustacchi 				goto out;
211575eba5b6SRobert Mustacchi 
211675eba5b6SRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_SHRAL_PCH_LPT(index - 1),
211775eba5b6SRobert Mustacchi 					rar_low);
211875eba5b6SRobert Mustacchi 			E1000_WRITE_FLUSH(hw);
211975eba5b6SRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_SHRAH_PCH_LPT(index - 1),
212075eba5b6SRobert Mustacchi 					rar_high);
212175eba5b6SRobert Mustacchi 			E1000_WRITE_FLUSH(hw);
212275eba5b6SRobert Mustacchi 
212375eba5b6SRobert Mustacchi 			e1000_release_swflag_ich8lan(hw);
212475eba5b6SRobert Mustacchi 
212575eba5b6SRobert Mustacchi 			/* verify the register updates */
212675eba5b6SRobert Mustacchi 			if ((E1000_READ_REG(hw, E1000_SHRAL_PCH_LPT(index - 1)) == rar_low) &&
212775eba5b6SRobert Mustacchi 			    (E1000_READ_REG(hw, E1000_SHRAH_PCH_LPT(index - 1)) == rar_high))
2128c124a83eSRobert Mustacchi 				return E1000_SUCCESS;
212975eba5b6SRobert Mustacchi 		}
213075eba5b6SRobert Mustacchi 	}
213175eba5b6SRobert Mustacchi 
213275eba5b6SRobert Mustacchi out:
213375eba5b6SRobert Mustacchi 	DEBUGOUT1("Failed to write receive address at index %d\n", index);
2134c124a83eSRobert Mustacchi 	return -E1000_ERR_CONFIG;
213575eba5b6SRobert Mustacchi }
213675eba5b6SRobert Mustacchi 
213775eba5b6SRobert Mustacchi /**
213875eba5b6SRobert Mustacchi  *  e1000_update_mc_addr_list_pch2lan - Update Multicast addresses
213975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
214075eba5b6SRobert Mustacchi  *  @mc_addr_list: array of multicast addresses to program
214175eba5b6SRobert Mustacchi  *  @mc_addr_count: number of multicast addresses to program
214275eba5b6SRobert Mustacchi  *
214375eba5b6SRobert Mustacchi  *  Updates entire Multicast Table Array of the PCH2 MAC and PHY.
214475eba5b6SRobert Mustacchi  *  The caller must have a packed mc_addr_list of multicast addresses.
214575eba5b6SRobert Mustacchi  **/
214675eba5b6SRobert Mustacchi static void e1000_update_mc_addr_list_pch2lan(struct e1000_hw *hw,
214775eba5b6SRobert Mustacchi 					      u8 *mc_addr_list,
214875eba5b6SRobert Mustacchi 					      u32 mc_addr_count)
214975eba5b6SRobert Mustacchi {
215075eba5b6SRobert Mustacchi 	u16 phy_reg = 0;
215175eba5b6SRobert Mustacchi 	int i;
215275eba5b6SRobert Mustacchi 	s32 ret_val;
215375eba5b6SRobert Mustacchi 
215475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_update_mc_addr_list_pch2lan");
215575eba5b6SRobert Mustacchi 
215675eba5b6SRobert Mustacchi 	e1000_update_mc_addr_list_generic(hw, mc_addr_list, mc_addr_count);
215775eba5b6SRobert Mustacchi 
215875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
215975eba5b6SRobert Mustacchi 	if (ret_val)
216075eba5b6SRobert Mustacchi 		return;
216175eba5b6SRobert Mustacchi 
216275eba5b6SRobert Mustacchi 	ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
216375eba5b6SRobert Mustacchi 	if (ret_val)
216475eba5b6SRobert Mustacchi 		goto release;
216575eba5b6SRobert Mustacchi 
216675eba5b6SRobert Mustacchi 	for (i = 0; i < hw->mac.mta_reg_count; i++) {
216775eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_page(hw, BM_MTA(i),
216875eba5b6SRobert Mustacchi 					   (u16)(hw->mac.mta_shadow[i] &
216975eba5b6SRobert Mustacchi 						 0xFFFF));
217075eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_page(hw, (BM_MTA(i) + 1),
217175eba5b6SRobert Mustacchi 					   (u16)((hw->mac.mta_shadow[i] >> 16) &
217275eba5b6SRobert Mustacchi 						 0xFFFF));
217375eba5b6SRobert Mustacchi 	}
217475eba5b6SRobert Mustacchi 
217575eba5b6SRobert Mustacchi 	e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
217675eba5b6SRobert Mustacchi 
217775eba5b6SRobert Mustacchi release:
217875eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
217975eba5b6SRobert Mustacchi }
218075eba5b6SRobert Mustacchi 
218175eba5b6SRobert Mustacchi /**
218275eba5b6SRobert Mustacchi  *  e1000_check_reset_block_ich8lan - Check if PHY reset is blocked
218375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
218475eba5b6SRobert Mustacchi  *
218575eba5b6SRobert Mustacchi  *  Checks if firmware is blocking the reset of the PHY.
218675eba5b6SRobert Mustacchi  *  This is a function pointer entry point only called by
218775eba5b6SRobert Mustacchi  *  reset routines.
218875eba5b6SRobert Mustacchi  **/
218975eba5b6SRobert Mustacchi static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)
219075eba5b6SRobert Mustacchi {
219175eba5b6SRobert Mustacchi 	u32 fwsm;
2192c124a83eSRobert Mustacchi 	bool blocked = FALSE;
2193c124a83eSRobert Mustacchi 	int i = 0;
219475eba5b6SRobert Mustacchi 
219575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_reset_block_ich8lan");
219675eba5b6SRobert Mustacchi 
2197c124a83eSRobert Mustacchi 	do {
219875eba5b6SRobert Mustacchi 		fwsm = E1000_READ_REG(hw, E1000_FWSM);
2199c124a83eSRobert Mustacchi 		if (!(fwsm & E1000_ICH_FWSM_RSPCIPHY)) {
2200c124a83eSRobert Mustacchi 			blocked = TRUE;
2201c124a83eSRobert Mustacchi 			msec_delay(10);
2202c124a83eSRobert Mustacchi 			continue;
2203c124a83eSRobert Mustacchi 		}
2204c124a83eSRobert Mustacchi 		blocked = FALSE;
2205*42cc51e0SRobert Mustacchi 	} while (blocked && (i++ < 30));
2206c124a83eSRobert Mustacchi 	return blocked ? E1000_BLK_PHY_RESET : E1000_SUCCESS;
220775eba5b6SRobert Mustacchi }
220875eba5b6SRobert Mustacchi 
220975eba5b6SRobert Mustacchi /**
221075eba5b6SRobert Mustacchi  *  e1000_write_smbus_addr - Write SMBus address to PHY needed during Sx states
221175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
221275eba5b6SRobert Mustacchi  *
221375eba5b6SRobert Mustacchi  *  Assumes semaphore already acquired.
221475eba5b6SRobert Mustacchi  *
221575eba5b6SRobert Mustacchi  **/
221675eba5b6SRobert Mustacchi static s32 e1000_write_smbus_addr(struct e1000_hw *hw)
221775eba5b6SRobert Mustacchi {
221875eba5b6SRobert Mustacchi 	u16 phy_data;
221975eba5b6SRobert Mustacchi 	u32 strap = E1000_READ_REG(hw, E1000_STRAP);
222075eba5b6SRobert Mustacchi 	u32 freq = (strap & E1000_STRAP_SMT_FREQ_MASK) >>
222175eba5b6SRobert Mustacchi 		E1000_STRAP_SMT_FREQ_SHIFT;
222275eba5b6SRobert Mustacchi 	s32 ret_val;
222375eba5b6SRobert Mustacchi 
222475eba5b6SRobert Mustacchi 	strap &= E1000_STRAP_SMBUS_ADDRESS_MASK;
222575eba5b6SRobert Mustacchi 
222675eba5b6SRobert Mustacchi 	ret_val = e1000_read_phy_reg_hv_locked(hw, HV_SMB_ADDR, &phy_data);
222775eba5b6SRobert Mustacchi 	if (ret_val)
222875eba5b6SRobert Mustacchi 		return ret_val;
222975eba5b6SRobert Mustacchi 
223075eba5b6SRobert Mustacchi 	phy_data &= ~HV_SMB_ADDR_MASK;
223175eba5b6SRobert Mustacchi 	phy_data |= (strap >> E1000_STRAP_SMBUS_ADDRESS_SHIFT);
223275eba5b6SRobert Mustacchi 	phy_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
223375eba5b6SRobert Mustacchi 
223475eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_i217) {
223575eba5b6SRobert Mustacchi 		/* Restore SMBus frequency */
223675eba5b6SRobert Mustacchi 		if (freq--) {
223775eba5b6SRobert Mustacchi 			phy_data &= ~HV_SMB_ADDR_FREQ_MASK;
223875eba5b6SRobert Mustacchi 			phy_data |= (freq & (1 << 0)) <<
223975eba5b6SRobert Mustacchi 				HV_SMB_ADDR_FREQ_LOW_SHIFT;
224075eba5b6SRobert Mustacchi 			phy_data |= (freq & (1 << 1)) <<
224175eba5b6SRobert Mustacchi 				(HV_SMB_ADDR_FREQ_HIGH_SHIFT - 1);
224275eba5b6SRobert Mustacchi 		} else {
224375eba5b6SRobert Mustacchi 			DEBUGOUT("Unsupported SMB frequency in PHY\n");
224475eba5b6SRobert Mustacchi 		}
224575eba5b6SRobert Mustacchi 	}
224675eba5b6SRobert Mustacchi 
224775eba5b6SRobert Mustacchi 	return e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR, phy_data);
224875eba5b6SRobert Mustacchi }
224975eba5b6SRobert Mustacchi 
225075eba5b6SRobert Mustacchi /**
225175eba5b6SRobert Mustacchi  *  e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
225275eba5b6SRobert Mustacchi  *  @hw:   pointer to the HW structure
225375eba5b6SRobert Mustacchi  *
225475eba5b6SRobert Mustacchi  *  SW should configure the LCD from the NVM extended configuration region
225575eba5b6SRobert Mustacchi  *  as a workaround for certain parts.
225675eba5b6SRobert Mustacchi  **/
225775eba5b6SRobert Mustacchi static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
225875eba5b6SRobert Mustacchi {
225975eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
226075eba5b6SRobert Mustacchi 	u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
226175eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
226275eba5b6SRobert Mustacchi 	u16 word_addr, reg_data, reg_addr, phy_page = 0;
226375eba5b6SRobert Mustacchi 
226475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_sw_lcd_config_ich8lan");
226575eba5b6SRobert Mustacchi 
226675eba5b6SRobert Mustacchi 	/* Initialize the PHY from the NVM on ICH platforms.  This
226775eba5b6SRobert Mustacchi 	 * is needed due to an issue where the NVM configuration is
226875eba5b6SRobert Mustacchi 	 * not properly autoloaded after power transitions.
226975eba5b6SRobert Mustacchi 	 * Therefore, after each PHY reset, we will load the
227075eba5b6SRobert Mustacchi 	 * configuration data out of the NVM manually.
227175eba5b6SRobert Mustacchi 	 */
227275eba5b6SRobert Mustacchi 	switch (hw->mac.type) {
227375eba5b6SRobert Mustacchi 	case e1000_ich8lan:
227475eba5b6SRobert Mustacchi 		if (phy->type != e1000_phy_igp_3)
227575eba5b6SRobert Mustacchi 			return ret_val;
227675eba5b6SRobert Mustacchi 
227775eba5b6SRobert Mustacchi 		if ((hw->device_id == E1000_DEV_ID_ICH8_IGP_AMT) ||
227875eba5b6SRobert Mustacchi 		    (hw->device_id == E1000_DEV_ID_ICH8_IGP_C)) {
227975eba5b6SRobert Mustacchi 			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;
228075eba5b6SRobert Mustacchi 			break;
228175eba5b6SRobert Mustacchi 		}
228275eba5b6SRobert Mustacchi 		/* Fall-thru */
228375eba5b6SRobert Mustacchi 	case e1000_pchlan:
228475eba5b6SRobert Mustacchi 	case e1000_pch2lan:
228575eba5b6SRobert Mustacchi 	case e1000_pch_lpt:
2286*42cc51e0SRobert Mustacchi 	case e1000_pch_spt:
228775eba5b6SRobert Mustacchi 		sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
228875eba5b6SRobert Mustacchi 		break;
228975eba5b6SRobert Mustacchi 	default:
229075eba5b6SRobert Mustacchi 		return ret_val;
229175eba5b6SRobert Mustacchi 	}
229275eba5b6SRobert Mustacchi 
229375eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
229475eba5b6SRobert Mustacchi 	if (ret_val)
229575eba5b6SRobert Mustacchi 		return ret_val;
229675eba5b6SRobert Mustacchi 
229775eba5b6SRobert Mustacchi 	data = E1000_READ_REG(hw, E1000_FEXTNVM);
229875eba5b6SRobert Mustacchi 	if (!(data & sw_cfg_mask))
229975eba5b6SRobert Mustacchi 		goto release;
230075eba5b6SRobert Mustacchi 
230175eba5b6SRobert Mustacchi 	/* Make sure HW does not configure LCD from PHY
230275eba5b6SRobert Mustacchi 	 * extended configuration before SW configuration
230375eba5b6SRobert Mustacchi 	 */
230475eba5b6SRobert Mustacchi 	data = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
230575eba5b6SRobert Mustacchi 	if ((hw->mac.type < e1000_pch2lan) &&
230675eba5b6SRobert Mustacchi 	    (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE))
230775eba5b6SRobert Mustacchi 			goto release;
230875eba5b6SRobert Mustacchi 
230975eba5b6SRobert Mustacchi 	cnf_size = E1000_READ_REG(hw, E1000_EXTCNF_SIZE);
231075eba5b6SRobert Mustacchi 	cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
231175eba5b6SRobert Mustacchi 	cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
231275eba5b6SRobert Mustacchi 	if (!cnf_size)
231375eba5b6SRobert Mustacchi 		goto release;
231475eba5b6SRobert Mustacchi 
231575eba5b6SRobert Mustacchi 	cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
231675eba5b6SRobert Mustacchi 	cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;
231775eba5b6SRobert Mustacchi 
231875eba5b6SRobert Mustacchi 	if (((hw->mac.type == e1000_pchlan) &&
231975eba5b6SRobert Mustacchi 	     !(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)) ||
232075eba5b6SRobert Mustacchi 	    (hw->mac.type > e1000_pchlan)) {
232175eba5b6SRobert Mustacchi 		/* HW configures the SMBus address and LEDs when the
232275eba5b6SRobert Mustacchi 		 * OEM and LCD Write Enable bits are set in the NVM.
232375eba5b6SRobert Mustacchi 		 * When both NVM bits are cleared, SW will configure
232475eba5b6SRobert Mustacchi 		 * them instead.
232575eba5b6SRobert Mustacchi 		 */
232675eba5b6SRobert Mustacchi 		ret_val = e1000_write_smbus_addr(hw);
232775eba5b6SRobert Mustacchi 		if (ret_val)
232875eba5b6SRobert Mustacchi 			goto release;
232975eba5b6SRobert Mustacchi 
233075eba5b6SRobert Mustacchi 		data = E1000_READ_REG(hw, E1000_LEDCTL);
233175eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_hv_locked(hw, HV_LED_CONFIG,
233275eba5b6SRobert Mustacchi 							(u16)data);
233375eba5b6SRobert Mustacchi 		if (ret_val)
233475eba5b6SRobert Mustacchi 			goto release;
233575eba5b6SRobert Mustacchi 	}
233675eba5b6SRobert Mustacchi 
233775eba5b6SRobert Mustacchi 	/* Configure LCD from extended configuration region. */
233875eba5b6SRobert Mustacchi 
233975eba5b6SRobert Mustacchi 	/* cnf_base_addr is in DWORD */
234075eba5b6SRobert Mustacchi 	word_addr = (u16)(cnf_base_addr << 1);
234175eba5b6SRobert Mustacchi 
234275eba5b6SRobert Mustacchi 	for (i = 0; i < cnf_size; i++) {
234375eba5b6SRobert Mustacchi 		ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2), 1,
234475eba5b6SRobert Mustacchi 					   &reg_data);
234575eba5b6SRobert Mustacchi 		if (ret_val)
234675eba5b6SRobert Mustacchi 			goto release;
234775eba5b6SRobert Mustacchi 
234875eba5b6SRobert Mustacchi 		ret_val = hw->nvm.ops.read(hw, (word_addr + i * 2 + 1),
234975eba5b6SRobert Mustacchi 					   1, &reg_addr);
235075eba5b6SRobert Mustacchi 		if (ret_val)
235175eba5b6SRobert Mustacchi 			goto release;
235275eba5b6SRobert Mustacchi 
235375eba5b6SRobert Mustacchi 		/* Save off the PHY page for future writes. */
235475eba5b6SRobert Mustacchi 		if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
235575eba5b6SRobert Mustacchi 			phy_page = reg_data;
235675eba5b6SRobert Mustacchi 			continue;
235775eba5b6SRobert Mustacchi 		}
235875eba5b6SRobert Mustacchi 
235975eba5b6SRobert Mustacchi 		reg_addr &= PHY_REG_MASK;
236075eba5b6SRobert Mustacchi 		reg_addr |= phy_page;
236175eba5b6SRobert Mustacchi 
236275eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg_locked(hw, (u32)reg_addr,
236375eba5b6SRobert Mustacchi 						    reg_data);
236475eba5b6SRobert Mustacchi 		if (ret_val)
236575eba5b6SRobert Mustacchi 			goto release;
236675eba5b6SRobert Mustacchi 	}
236775eba5b6SRobert Mustacchi 
236875eba5b6SRobert Mustacchi release:
236975eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
237075eba5b6SRobert Mustacchi 	return ret_val;
237175eba5b6SRobert Mustacchi }
237275eba5b6SRobert Mustacchi 
237375eba5b6SRobert Mustacchi /**
237475eba5b6SRobert Mustacchi  *  e1000_k1_gig_workaround_hv - K1 Si workaround
237575eba5b6SRobert Mustacchi  *  @hw:   pointer to the HW structure
237675eba5b6SRobert Mustacchi  *  @link: link up bool flag
237775eba5b6SRobert Mustacchi  *
237875eba5b6SRobert Mustacchi  *  If K1 is enabled for 1Gbps, the MAC might stall when transitioning
237975eba5b6SRobert Mustacchi  *  from a lower speed.  This workaround disables K1 whenever link is at 1Gig
238075eba5b6SRobert Mustacchi  *  If link is down, the function will restore the default K1 setting located
238175eba5b6SRobert Mustacchi  *  in the NVM.
238275eba5b6SRobert Mustacchi  **/
238375eba5b6SRobert Mustacchi static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
238475eba5b6SRobert Mustacchi {
238575eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
238675eba5b6SRobert Mustacchi 	u16 status_reg = 0;
238775eba5b6SRobert Mustacchi 	bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;
238875eba5b6SRobert Mustacchi 
238975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_k1_gig_workaround_hv");
239075eba5b6SRobert Mustacchi 
239175eba5b6SRobert Mustacchi 	if (hw->mac.type != e1000_pchlan)
239275eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
239375eba5b6SRobert Mustacchi 
239475eba5b6SRobert Mustacchi 	/* Wrap the whole flow with the sw flag */
239575eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
239675eba5b6SRobert Mustacchi 	if (ret_val)
239775eba5b6SRobert Mustacchi 		return ret_val;
239875eba5b6SRobert Mustacchi 
239975eba5b6SRobert Mustacchi 	/* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
240075eba5b6SRobert Mustacchi 	if (link) {
240175eba5b6SRobert Mustacchi 		if (hw->phy.type == e1000_phy_82578) {
240275eba5b6SRobert Mustacchi 			ret_val = hw->phy.ops.read_reg_locked(hw, BM_CS_STATUS,
240375eba5b6SRobert Mustacchi 							      &status_reg);
240475eba5b6SRobert Mustacchi 			if (ret_val)
240575eba5b6SRobert Mustacchi 				goto release;
240675eba5b6SRobert Mustacchi 
2407c124a83eSRobert Mustacchi 			status_reg &= (BM_CS_STATUS_LINK_UP |
240875eba5b6SRobert Mustacchi 				       BM_CS_STATUS_RESOLVED |
2409c124a83eSRobert Mustacchi 				       BM_CS_STATUS_SPEED_MASK);
241075eba5b6SRobert Mustacchi 
241175eba5b6SRobert Mustacchi 			if (status_reg == (BM_CS_STATUS_LINK_UP |
241275eba5b6SRobert Mustacchi 					   BM_CS_STATUS_RESOLVED |
241375eba5b6SRobert Mustacchi 					   BM_CS_STATUS_SPEED_1000))
241475eba5b6SRobert Mustacchi 				k1_enable = FALSE;
241575eba5b6SRobert Mustacchi 		}
241675eba5b6SRobert Mustacchi 
241775eba5b6SRobert Mustacchi 		if (hw->phy.type == e1000_phy_82577) {
241875eba5b6SRobert Mustacchi 			ret_val = hw->phy.ops.read_reg_locked(hw, HV_M_STATUS,
241975eba5b6SRobert Mustacchi 							      &status_reg);
242075eba5b6SRobert Mustacchi 			if (ret_val)
242175eba5b6SRobert Mustacchi 				goto release;
242275eba5b6SRobert Mustacchi 
2423c124a83eSRobert Mustacchi 			status_reg &= (HV_M_STATUS_LINK_UP |
242475eba5b6SRobert Mustacchi 				       HV_M_STATUS_AUTONEG_COMPLETE |
2425c124a83eSRobert Mustacchi 				       HV_M_STATUS_SPEED_MASK);
242675eba5b6SRobert Mustacchi 
242775eba5b6SRobert Mustacchi 			if (status_reg == (HV_M_STATUS_LINK_UP |
242875eba5b6SRobert Mustacchi 					   HV_M_STATUS_AUTONEG_COMPLETE |
242975eba5b6SRobert Mustacchi 					   HV_M_STATUS_SPEED_1000))
243075eba5b6SRobert Mustacchi 				k1_enable = FALSE;
243175eba5b6SRobert Mustacchi 		}
243275eba5b6SRobert Mustacchi 
243375eba5b6SRobert Mustacchi 		/* Link stall fix for link up */
243475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
243575eba5b6SRobert Mustacchi 						       0x0100);
243675eba5b6SRobert Mustacchi 		if (ret_val)
243775eba5b6SRobert Mustacchi 			goto release;
243875eba5b6SRobert Mustacchi 
243975eba5b6SRobert Mustacchi 	} else {
244075eba5b6SRobert Mustacchi 		/* Link stall fix for link down */
244175eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg_locked(hw, PHY_REG(770, 19),
244275eba5b6SRobert Mustacchi 						       0x4100);
244375eba5b6SRobert Mustacchi 		if (ret_val)
244475eba5b6SRobert Mustacchi 			goto release;
244575eba5b6SRobert Mustacchi 	}
244675eba5b6SRobert Mustacchi 
244775eba5b6SRobert Mustacchi 	ret_val = e1000_configure_k1_ich8lan(hw, k1_enable);
244875eba5b6SRobert Mustacchi 
244975eba5b6SRobert Mustacchi release:
245075eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
245175eba5b6SRobert Mustacchi 
245275eba5b6SRobert Mustacchi 	return ret_val;
245375eba5b6SRobert Mustacchi }
245475eba5b6SRobert Mustacchi 
245575eba5b6SRobert Mustacchi /**
245675eba5b6SRobert Mustacchi  *  e1000_configure_k1_ich8lan - Configure K1 power state
245775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
245875eba5b6SRobert Mustacchi  *  @enable: K1 state to configure
245975eba5b6SRobert Mustacchi  *
246075eba5b6SRobert Mustacchi  *  Configure the K1 power state based on the provided parameter.
246175eba5b6SRobert Mustacchi  *  Assumes semaphore already acquired.
246275eba5b6SRobert Mustacchi  *
246375eba5b6SRobert Mustacchi  *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
246475eba5b6SRobert Mustacchi  **/
246575eba5b6SRobert Mustacchi s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
246675eba5b6SRobert Mustacchi {
246775eba5b6SRobert Mustacchi 	s32 ret_val;
246875eba5b6SRobert Mustacchi 	u32 ctrl_reg = 0;
246975eba5b6SRobert Mustacchi 	u32 ctrl_ext = 0;
247075eba5b6SRobert Mustacchi 	u32 reg = 0;
247175eba5b6SRobert Mustacchi 	u16 kmrn_reg = 0;
247275eba5b6SRobert Mustacchi 
247375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_configure_k1_ich8lan");
247475eba5b6SRobert Mustacchi 
247575eba5b6SRobert Mustacchi 	ret_val = e1000_read_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
247675eba5b6SRobert Mustacchi 					     &kmrn_reg);
247775eba5b6SRobert Mustacchi 	if (ret_val)
247875eba5b6SRobert Mustacchi 		return ret_val;
247975eba5b6SRobert Mustacchi 
248075eba5b6SRobert Mustacchi 	if (k1_enable)
248175eba5b6SRobert Mustacchi 		kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
248275eba5b6SRobert Mustacchi 	else
248375eba5b6SRobert Mustacchi 		kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;
248475eba5b6SRobert Mustacchi 
248575eba5b6SRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_locked(hw, E1000_KMRNCTRLSTA_K1_CONFIG,
248675eba5b6SRobert Mustacchi 					      kmrn_reg);
248775eba5b6SRobert Mustacchi 	if (ret_val)
248875eba5b6SRobert Mustacchi 		return ret_val;
248975eba5b6SRobert Mustacchi 
249075eba5b6SRobert Mustacchi 	usec_delay(20);
249175eba5b6SRobert Mustacchi 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
249275eba5b6SRobert Mustacchi 	ctrl_reg = E1000_READ_REG(hw, E1000_CTRL);
249375eba5b6SRobert Mustacchi 
249475eba5b6SRobert Mustacchi 	reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
249575eba5b6SRobert Mustacchi 	reg |= E1000_CTRL_FRCSPD;
249675eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, reg);
249775eba5b6SRobert Mustacchi 
249875eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
249975eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
250075eba5b6SRobert Mustacchi 	usec_delay(20);
250175eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl_reg);
250275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
250375eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
250475eba5b6SRobert Mustacchi 	usec_delay(20);
250575eba5b6SRobert Mustacchi 
250675eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
250775eba5b6SRobert Mustacchi }
250875eba5b6SRobert Mustacchi 
250975eba5b6SRobert Mustacchi /**
251075eba5b6SRobert Mustacchi  *  e1000_oem_bits_config_ich8lan - SW-based LCD Configuration
251175eba5b6SRobert Mustacchi  *  @hw:       pointer to the HW structure
251275eba5b6SRobert Mustacchi  *  @d0_state: boolean if entering d0 or d3 device state
251375eba5b6SRobert Mustacchi  *
251475eba5b6SRobert Mustacchi  *  SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
251575eba5b6SRobert Mustacchi  *  collectively called OEM bits.  The OEM Write Enable bit and SW Config bit
251675eba5b6SRobert Mustacchi  *  in NVM determines whether HW should configure LPLU and Gbe Disable.
251775eba5b6SRobert Mustacchi  **/
251875eba5b6SRobert Mustacchi static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
251975eba5b6SRobert Mustacchi {
252075eba5b6SRobert Mustacchi 	s32 ret_val = 0;
252175eba5b6SRobert Mustacchi 	u32 mac_reg;
252275eba5b6SRobert Mustacchi 	u16 oem_reg;
252375eba5b6SRobert Mustacchi 
252475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_oem_bits_config_ich8lan");
252575eba5b6SRobert Mustacchi 
252675eba5b6SRobert Mustacchi 	if (hw->mac.type < e1000_pchlan)
252775eba5b6SRobert Mustacchi 		return ret_val;
252875eba5b6SRobert Mustacchi 
252975eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
253075eba5b6SRobert Mustacchi 	if (ret_val)
253175eba5b6SRobert Mustacchi 		return ret_val;
253275eba5b6SRobert Mustacchi 
253375eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pchlan) {
253475eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
253575eba5b6SRobert Mustacchi 		if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
253675eba5b6SRobert Mustacchi 			goto release;
253775eba5b6SRobert Mustacchi 	}
253875eba5b6SRobert Mustacchi 
253975eba5b6SRobert Mustacchi 	mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM);
254075eba5b6SRobert Mustacchi 	if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
254175eba5b6SRobert Mustacchi 		goto release;
254275eba5b6SRobert Mustacchi 
254375eba5b6SRobert Mustacchi 	mac_reg = E1000_READ_REG(hw, E1000_PHY_CTRL);
254475eba5b6SRobert Mustacchi 
254575eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg_locked(hw, HV_OEM_BITS, &oem_reg);
254675eba5b6SRobert Mustacchi 	if (ret_val)
254775eba5b6SRobert Mustacchi 		goto release;
254875eba5b6SRobert Mustacchi 
254975eba5b6SRobert Mustacchi 	oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);
255075eba5b6SRobert Mustacchi 
255175eba5b6SRobert Mustacchi 	if (d0_state) {
255275eba5b6SRobert Mustacchi 		if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE)
255375eba5b6SRobert Mustacchi 			oem_reg |= HV_OEM_BITS_GBE_DIS;
255475eba5b6SRobert Mustacchi 
255575eba5b6SRobert Mustacchi 		if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
255675eba5b6SRobert Mustacchi 			oem_reg |= HV_OEM_BITS_LPLU;
255775eba5b6SRobert Mustacchi 	} else {
255875eba5b6SRobert Mustacchi 		if (mac_reg & (E1000_PHY_CTRL_GBE_DISABLE |
255975eba5b6SRobert Mustacchi 		    E1000_PHY_CTRL_NOND0A_GBE_DISABLE))
256075eba5b6SRobert Mustacchi 			oem_reg |= HV_OEM_BITS_GBE_DIS;
256175eba5b6SRobert Mustacchi 
256275eba5b6SRobert Mustacchi 		if (mac_reg & (E1000_PHY_CTRL_D0A_LPLU |
256375eba5b6SRobert Mustacchi 		    E1000_PHY_CTRL_NOND0A_LPLU))
256475eba5b6SRobert Mustacchi 			oem_reg |= HV_OEM_BITS_LPLU;
256575eba5b6SRobert Mustacchi 	}
256675eba5b6SRobert Mustacchi 
256775eba5b6SRobert Mustacchi 	/* Set Restart auto-neg to activate the bits */
256875eba5b6SRobert Mustacchi 	if ((d0_state || (hw->mac.type != e1000_pchlan)) &&
256975eba5b6SRobert Mustacchi 	    !hw->phy.ops.check_reset_block(hw))
257075eba5b6SRobert Mustacchi 		oem_reg |= HV_OEM_BITS_RESTART_AN;
257175eba5b6SRobert Mustacchi 
257275eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg_locked(hw, HV_OEM_BITS, oem_reg);
257375eba5b6SRobert Mustacchi 
257475eba5b6SRobert Mustacchi release:
257575eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
257675eba5b6SRobert Mustacchi 
257775eba5b6SRobert Mustacchi 	return ret_val;
257875eba5b6SRobert Mustacchi }
257975eba5b6SRobert Mustacchi 
258075eba5b6SRobert Mustacchi 
258175eba5b6SRobert Mustacchi /**
258275eba5b6SRobert Mustacchi  *  e1000_set_mdio_slow_mode_hv - Set slow MDIO access mode
258375eba5b6SRobert Mustacchi  *  @hw:   pointer to the HW structure
258475eba5b6SRobert Mustacchi  **/
258575eba5b6SRobert Mustacchi static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw)
258675eba5b6SRobert Mustacchi {
258775eba5b6SRobert Mustacchi 	s32 ret_val;
258875eba5b6SRobert Mustacchi 	u16 data;
258975eba5b6SRobert Mustacchi 
259075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_mdio_slow_mode_hv");
259175eba5b6SRobert Mustacchi 
259275eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, HV_KMRN_MODE_CTRL, &data);
259375eba5b6SRobert Mustacchi 	if (ret_val)
259475eba5b6SRobert Mustacchi 		return ret_val;
259575eba5b6SRobert Mustacchi 
259675eba5b6SRobert Mustacchi 	data |= HV_KMRN_MDIO_SLOW;
259775eba5b6SRobert Mustacchi 
259875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_MODE_CTRL, data);
259975eba5b6SRobert Mustacchi 
260075eba5b6SRobert Mustacchi 	return ret_val;
260175eba5b6SRobert Mustacchi }
260275eba5b6SRobert Mustacchi 
260375eba5b6SRobert Mustacchi /**
260475eba5b6SRobert Mustacchi  *  e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
260575eba5b6SRobert Mustacchi  *  done after every PHY reset.
260675eba5b6SRobert Mustacchi  **/
260775eba5b6SRobert Mustacchi static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
260875eba5b6SRobert Mustacchi {
260975eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
261075eba5b6SRobert Mustacchi 	u16 phy_data;
261175eba5b6SRobert Mustacchi 
261275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_hv_phy_workarounds_ich8lan");
261375eba5b6SRobert Mustacchi 
261475eba5b6SRobert Mustacchi 	if (hw->mac.type != e1000_pchlan)
261575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
261675eba5b6SRobert Mustacchi 
261775eba5b6SRobert Mustacchi 	/* Set MDIO slow mode before any other MDIO access */
261875eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_82577) {
261975eba5b6SRobert Mustacchi 		ret_val = e1000_set_mdio_slow_mode_hv(hw);
262075eba5b6SRobert Mustacchi 		if (ret_val)
262175eba5b6SRobert Mustacchi 			return ret_val;
262275eba5b6SRobert Mustacchi 	}
262375eba5b6SRobert Mustacchi 
262475eba5b6SRobert Mustacchi 	if (((hw->phy.type == e1000_phy_82577) &&
262575eba5b6SRobert Mustacchi 	     ((hw->phy.revision == 1) || (hw->phy.revision == 2))) ||
262675eba5b6SRobert Mustacchi 	    ((hw->phy.type == e1000_phy_82578) && (hw->phy.revision == 1))) {
262775eba5b6SRobert Mustacchi 		/* Disable generation of early preamble */
262875eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 25), 0x4431);
262975eba5b6SRobert Mustacchi 		if (ret_val)
263075eba5b6SRobert Mustacchi 			return ret_val;
263175eba5b6SRobert Mustacchi 
263275eba5b6SRobert Mustacchi 		/* Preamble tuning for SSC */
263375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, HV_KMRN_FIFO_CTRLSTA,
263475eba5b6SRobert Mustacchi 						0xA204);
263575eba5b6SRobert Mustacchi 		if (ret_val)
263675eba5b6SRobert Mustacchi 			return ret_val;
263775eba5b6SRobert Mustacchi 	}
263875eba5b6SRobert Mustacchi 
263975eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_82578) {
264075eba5b6SRobert Mustacchi 		/* Return registers to default by doing a soft reset then
264175eba5b6SRobert Mustacchi 		 * writing 0x3140 to the control register.
264275eba5b6SRobert Mustacchi 		 */
264375eba5b6SRobert Mustacchi 		if (hw->phy.revision < 2) {
264475eba5b6SRobert Mustacchi 			e1000_phy_sw_reset_generic(hw);
264575eba5b6SRobert Mustacchi 			ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL,
264675eba5b6SRobert Mustacchi 							0x3140);
264775eba5b6SRobert Mustacchi 		}
264875eba5b6SRobert Mustacchi 	}
264975eba5b6SRobert Mustacchi 
265075eba5b6SRobert Mustacchi 	/* Select page 0 */
265175eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
265275eba5b6SRobert Mustacchi 	if (ret_val)
265375eba5b6SRobert Mustacchi 		return ret_val;
265475eba5b6SRobert Mustacchi 
265575eba5b6SRobert Mustacchi 	hw->phy.addr = 1;
265675eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
265775eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
265875eba5b6SRobert Mustacchi 	if (ret_val)
265975eba5b6SRobert Mustacchi 		return ret_val;
266075eba5b6SRobert Mustacchi 
266175eba5b6SRobert Mustacchi 	/* Configure the K1 Si workaround during phy reset assuming there is
266275eba5b6SRobert Mustacchi 	 * link so that it disables K1 if link is in 1Gbps.
266375eba5b6SRobert Mustacchi 	 */
266475eba5b6SRobert Mustacchi 	ret_val = e1000_k1_gig_workaround_hv(hw, TRUE);
266575eba5b6SRobert Mustacchi 	if (ret_val)
266675eba5b6SRobert Mustacchi 		return ret_val;
266775eba5b6SRobert Mustacchi 
266875eba5b6SRobert Mustacchi 	/* Workaround for link disconnects on a busy hub in half duplex */
266975eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
267075eba5b6SRobert Mustacchi 	if (ret_val)
267175eba5b6SRobert Mustacchi 		return ret_val;
267275eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg_locked(hw, BM_PORT_GEN_CFG, &phy_data);
267375eba5b6SRobert Mustacchi 	if (ret_val)
267475eba5b6SRobert Mustacchi 		goto release;
267575eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg_locked(hw, BM_PORT_GEN_CFG,
267675eba5b6SRobert Mustacchi 					       phy_data & 0x00FF);
267775eba5b6SRobert Mustacchi 	if (ret_val)
267875eba5b6SRobert Mustacchi 		goto release;
267975eba5b6SRobert Mustacchi 
268075eba5b6SRobert Mustacchi 	/* set MSE higher to enable link to stay up when noise is high */
268175eba5b6SRobert Mustacchi 	ret_val = e1000_write_emi_reg_locked(hw, I82577_MSE_THRESHOLD, 0x0034);
268275eba5b6SRobert Mustacchi release:
268375eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
268475eba5b6SRobert Mustacchi 
268575eba5b6SRobert Mustacchi 	return ret_val;
268675eba5b6SRobert Mustacchi }
268775eba5b6SRobert Mustacchi 
268875eba5b6SRobert Mustacchi /**
268975eba5b6SRobert Mustacchi  *  e1000_copy_rx_addrs_to_phy_ich8lan - Copy Rx addresses from MAC to PHY
269075eba5b6SRobert Mustacchi  *  @hw:   pointer to the HW structure
269175eba5b6SRobert Mustacchi  **/
269275eba5b6SRobert Mustacchi void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)
269375eba5b6SRobert Mustacchi {
269475eba5b6SRobert Mustacchi 	u32 mac_reg;
269575eba5b6SRobert Mustacchi 	u16 i, phy_reg = 0;
269675eba5b6SRobert Mustacchi 	s32 ret_val;
269775eba5b6SRobert Mustacchi 
269875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_copy_rx_addrs_to_phy_ich8lan");
269975eba5b6SRobert Mustacchi 
270075eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
270175eba5b6SRobert Mustacchi 	if (ret_val)
270275eba5b6SRobert Mustacchi 		return;
270375eba5b6SRobert Mustacchi 	ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
270475eba5b6SRobert Mustacchi 	if (ret_val)
270575eba5b6SRobert Mustacchi 		goto release;
270675eba5b6SRobert Mustacchi 
2707c124a83eSRobert Mustacchi 	/* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */
2708c124a83eSRobert Mustacchi 	for (i = 0; i < (hw->mac.rar_entry_count); i++) {
270975eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_RAL(i));
271075eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),
271175eba5b6SRobert Mustacchi 					   (u16)(mac_reg & 0xFFFF));
271275eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_page(hw, BM_RAR_M(i),
271375eba5b6SRobert Mustacchi 					   (u16)((mac_reg >> 16) & 0xFFFF));
271475eba5b6SRobert Mustacchi 
271575eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_RAH(i));
271675eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_page(hw, BM_RAR_H(i),
271775eba5b6SRobert Mustacchi 					   (u16)(mac_reg & 0xFFFF));
271875eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_page(hw, BM_RAR_CTRL(i),
271975eba5b6SRobert Mustacchi 					   (u16)((mac_reg & E1000_RAH_AV)
272075eba5b6SRobert Mustacchi 						 >> 16));
272175eba5b6SRobert Mustacchi 	}
272275eba5b6SRobert Mustacchi 
272375eba5b6SRobert Mustacchi 	e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
272475eba5b6SRobert Mustacchi 
272575eba5b6SRobert Mustacchi release:
272675eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
272775eba5b6SRobert Mustacchi }
272875eba5b6SRobert Mustacchi 
272975eba5b6SRobert Mustacchi static u32 e1000_calc_rx_da_crc(u8 mac[])
273075eba5b6SRobert Mustacchi {
273175eba5b6SRobert Mustacchi 	u32 poly = 0xEDB88320;	/* Polynomial for 802.3 CRC calculation */
273275eba5b6SRobert Mustacchi 	u32 i, j, mask, crc;
273375eba5b6SRobert Mustacchi 
273475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_calc_rx_da_crc");
273575eba5b6SRobert Mustacchi 
273675eba5b6SRobert Mustacchi 	crc = 0xffffffff;
273775eba5b6SRobert Mustacchi 	for (i = 0; i < 6; i++) {
273875eba5b6SRobert Mustacchi 		crc = crc ^ mac[i];
273975eba5b6SRobert Mustacchi 		for (j = 8; j > 0; j--) {
274075eba5b6SRobert Mustacchi 			mask = (crc & 1) * (-1);
274175eba5b6SRobert Mustacchi 			crc = (crc >> 1) ^ (poly & mask);
274275eba5b6SRobert Mustacchi 		}
274375eba5b6SRobert Mustacchi 	}
274475eba5b6SRobert Mustacchi 	return ~crc;
274575eba5b6SRobert Mustacchi }
274675eba5b6SRobert Mustacchi 
274775eba5b6SRobert Mustacchi /**
274875eba5b6SRobert Mustacchi  *  e1000_lv_jumbo_workaround_ich8lan - required for jumbo frame operation
274975eba5b6SRobert Mustacchi  *  with 82579 PHY
275075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
275175eba5b6SRobert Mustacchi  *  @enable: flag to enable/disable workaround when enabling/disabling jumbos
275275eba5b6SRobert Mustacchi  **/
275375eba5b6SRobert Mustacchi s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)
275475eba5b6SRobert Mustacchi {
275575eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
275675eba5b6SRobert Mustacchi 	u16 phy_reg, data;
275775eba5b6SRobert Mustacchi 	u32 mac_reg;
275875eba5b6SRobert Mustacchi 	u16 i;
275975eba5b6SRobert Mustacchi 
276075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_lv_jumbo_workaround_ich8lan");
276175eba5b6SRobert Mustacchi 
276275eba5b6SRobert Mustacchi 	if (hw->mac.type < e1000_pch2lan)
276375eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
276475eba5b6SRobert Mustacchi 
276575eba5b6SRobert Mustacchi 	/* disable Rx path while enabling/disabling workaround */
276675eba5b6SRobert Mustacchi 	hw->phy.ops.read_reg(hw, PHY_REG(769, 20), &phy_reg);
276775eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 20),
276875eba5b6SRobert Mustacchi 					phy_reg | (1 << 14));
276975eba5b6SRobert Mustacchi 	if (ret_val)
277075eba5b6SRobert Mustacchi 		return ret_val;
277175eba5b6SRobert Mustacchi 
277275eba5b6SRobert Mustacchi 	if (enable) {
2773c124a83eSRobert Mustacchi 		/* Write Rx addresses (rar_entry_count for RAL/H, and
277475eba5b6SRobert Mustacchi 		 * SHRAL/H) and initial CRC values to the MAC
277575eba5b6SRobert Mustacchi 		 */
2776c124a83eSRobert Mustacchi 		for (i = 0; i < hw->mac.rar_entry_count; i++) {
277775eba5b6SRobert Mustacchi 			u8 mac_addr[ETH_ADDR_LEN] = {0};
277875eba5b6SRobert Mustacchi 			u32 addr_high, addr_low;
277975eba5b6SRobert Mustacchi 
278075eba5b6SRobert Mustacchi 			addr_high = E1000_READ_REG(hw, E1000_RAH(i));
278175eba5b6SRobert Mustacchi 			if (!(addr_high & E1000_RAH_AV))
278275eba5b6SRobert Mustacchi 				continue;
278375eba5b6SRobert Mustacchi 			addr_low = E1000_READ_REG(hw, E1000_RAL(i));
278475eba5b6SRobert Mustacchi 			mac_addr[0] = (addr_low & 0xFF);
278575eba5b6SRobert Mustacchi 			mac_addr[1] = ((addr_low >> 8) & 0xFF);
278675eba5b6SRobert Mustacchi 			mac_addr[2] = ((addr_low >> 16) & 0xFF);
278775eba5b6SRobert Mustacchi 			mac_addr[3] = ((addr_low >> 24) & 0xFF);
278875eba5b6SRobert Mustacchi 			mac_addr[4] = (addr_high & 0xFF);
278975eba5b6SRobert Mustacchi 			mac_addr[5] = ((addr_high >> 8) & 0xFF);
279075eba5b6SRobert Mustacchi 
279175eba5b6SRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_PCH_RAICC(i),
279275eba5b6SRobert Mustacchi 					e1000_calc_rx_da_crc(mac_addr));
279375eba5b6SRobert Mustacchi 		}
279475eba5b6SRobert Mustacchi 
279575eba5b6SRobert Mustacchi 		/* Write Rx addresses to the PHY */
279675eba5b6SRobert Mustacchi 		e1000_copy_rx_addrs_to_phy_ich8lan(hw);
279775eba5b6SRobert Mustacchi 
279875eba5b6SRobert Mustacchi 		/* Enable jumbo frame workaround in the MAC */
279975eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_FFLT_DBG);
280075eba5b6SRobert Mustacchi 		mac_reg &= ~(1 << 14);
280175eba5b6SRobert Mustacchi 		mac_reg |= (7 << 15);
280275eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FFLT_DBG, mac_reg);
280375eba5b6SRobert Mustacchi 
280475eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_RCTL);
280575eba5b6SRobert Mustacchi 		mac_reg |= E1000_RCTL_SECRC;
280675eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_RCTL, mac_reg);
280775eba5b6SRobert Mustacchi 
280875eba5b6SRobert Mustacchi 		ret_val = e1000_read_kmrn_reg_generic(hw,
280975eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_CTRL_OFFSET,
281075eba5b6SRobert Mustacchi 						&data);
281175eba5b6SRobert Mustacchi 		if (ret_val)
281275eba5b6SRobert Mustacchi 			return ret_val;
281375eba5b6SRobert Mustacchi 		ret_val = e1000_write_kmrn_reg_generic(hw,
281475eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_CTRL_OFFSET,
281575eba5b6SRobert Mustacchi 						data | (1 << 0));
281675eba5b6SRobert Mustacchi 		if (ret_val)
281775eba5b6SRobert Mustacchi 			return ret_val;
281875eba5b6SRobert Mustacchi 		ret_val = e1000_read_kmrn_reg_generic(hw,
281975eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_HD_CTRL,
282075eba5b6SRobert Mustacchi 						&data);
282175eba5b6SRobert Mustacchi 		if (ret_val)
282275eba5b6SRobert Mustacchi 			return ret_val;
282375eba5b6SRobert Mustacchi 		data &= ~(0xF << 8);
282475eba5b6SRobert Mustacchi 		data |= (0xB << 8);
282575eba5b6SRobert Mustacchi 		ret_val = e1000_write_kmrn_reg_generic(hw,
282675eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_HD_CTRL,
282775eba5b6SRobert Mustacchi 						data);
282875eba5b6SRobert Mustacchi 		if (ret_val)
282975eba5b6SRobert Mustacchi 			return ret_val;
283075eba5b6SRobert Mustacchi 
283175eba5b6SRobert Mustacchi 		/* Enable jumbo frame workaround in the PHY */
283275eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data);
283375eba5b6SRobert Mustacchi 		data &= ~(0x7F << 5);
283475eba5b6SRobert Mustacchi 		data |= (0x37 << 5);
283575eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data);
283675eba5b6SRobert Mustacchi 		if (ret_val)
283775eba5b6SRobert Mustacchi 			return ret_val;
283875eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data);
283975eba5b6SRobert Mustacchi 		data &= ~(1 << 13);
284075eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data);
284175eba5b6SRobert Mustacchi 		if (ret_val)
284275eba5b6SRobert Mustacchi 			return ret_val;
284375eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data);
284475eba5b6SRobert Mustacchi 		data &= ~(0x3FF << 2);
2845c124a83eSRobert Mustacchi 		data |= (E1000_TX_PTR_GAP << 2);
284675eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data);
284775eba5b6SRobert Mustacchi 		if (ret_val)
284875eba5b6SRobert Mustacchi 			return ret_val;
284975eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0xF100);
285075eba5b6SRobert Mustacchi 		if (ret_val)
285175eba5b6SRobert Mustacchi 			return ret_val;
285275eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data);
285375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data |
285475eba5b6SRobert Mustacchi 						(1 << 10));
285575eba5b6SRobert Mustacchi 		if (ret_val)
285675eba5b6SRobert Mustacchi 			return ret_val;
285775eba5b6SRobert Mustacchi 	} else {
285875eba5b6SRobert Mustacchi 		/* Write MAC register values back to h/w defaults */
285975eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_FFLT_DBG);
286075eba5b6SRobert Mustacchi 		mac_reg &= ~(0xF << 14);
286175eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FFLT_DBG, mac_reg);
286275eba5b6SRobert Mustacchi 
286375eba5b6SRobert Mustacchi 		mac_reg = E1000_READ_REG(hw, E1000_RCTL);
286475eba5b6SRobert Mustacchi 		mac_reg &= ~E1000_RCTL_SECRC;
286575eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_RCTL, mac_reg);
286675eba5b6SRobert Mustacchi 
286775eba5b6SRobert Mustacchi 		ret_val = e1000_read_kmrn_reg_generic(hw,
286875eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_CTRL_OFFSET,
286975eba5b6SRobert Mustacchi 						&data);
287075eba5b6SRobert Mustacchi 		if (ret_val)
287175eba5b6SRobert Mustacchi 			return ret_val;
287275eba5b6SRobert Mustacchi 		ret_val = e1000_write_kmrn_reg_generic(hw,
287375eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_CTRL_OFFSET,
287475eba5b6SRobert Mustacchi 						data & ~(1 << 0));
287575eba5b6SRobert Mustacchi 		if (ret_val)
287675eba5b6SRobert Mustacchi 			return ret_val;
287775eba5b6SRobert Mustacchi 		ret_val = e1000_read_kmrn_reg_generic(hw,
287875eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_HD_CTRL,
287975eba5b6SRobert Mustacchi 						&data);
288075eba5b6SRobert Mustacchi 		if (ret_val)
288175eba5b6SRobert Mustacchi 			return ret_val;
288275eba5b6SRobert Mustacchi 		data &= ~(0xF << 8);
288375eba5b6SRobert Mustacchi 		data |= (0xB << 8);
288475eba5b6SRobert Mustacchi 		ret_val = e1000_write_kmrn_reg_generic(hw,
288575eba5b6SRobert Mustacchi 						E1000_KMRNCTRLSTA_HD_CTRL,
288675eba5b6SRobert Mustacchi 						data);
288775eba5b6SRobert Mustacchi 		if (ret_val)
288875eba5b6SRobert Mustacchi 			return ret_val;
288975eba5b6SRobert Mustacchi 
289075eba5b6SRobert Mustacchi 		/* Write PHY register values back to h/w defaults */
289175eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, PHY_REG(769, 23), &data);
289275eba5b6SRobert Mustacchi 		data &= ~(0x7F << 5);
289375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 23), data);
289475eba5b6SRobert Mustacchi 		if (ret_val)
289575eba5b6SRobert Mustacchi 			return ret_val;
289675eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, PHY_REG(769, 16), &data);
289775eba5b6SRobert Mustacchi 		data |= (1 << 13);
289875eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(769, 16), data);
289975eba5b6SRobert Mustacchi 		if (ret_val)
290075eba5b6SRobert Mustacchi 			return ret_val;
290175eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, PHY_REG(776, 20), &data);
290275eba5b6SRobert Mustacchi 		data &= ~(0x3FF << 2);
290375eba5b6SRobert Mustacchi 		data |= (0x8 << 2);
290475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 20), data);
290575eba5b6SRobert Mustacchi 		if (ret_val)
290675eba5b6SRobert Mustacchi 			return ret_val;
290775eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, PHY_REG(776, 23), 0x7E00);
290875eba5b6SRobert Mustacchi 		if (ret_val)
290975eba5b6SRobert Mustacchi 			return ret_val;
291075eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, HV_PM_CTRL, &data);
291175eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL, data &
291275eba5b6SRobert Mustacchi 						~(1 << 10));
291375eba5b6SRobert Mustacchi 		if (ret_val)
291475eba5b6SRobert Mustacchi 			return ret_val;
291575eba5b6SRobert Mustacchi 	}
291675eba5b6SRobert Mustacchi 
291775eba5b6SRobert Mustacchi 	/* re-enable Rx path after enabling/disabling workaround */
291875eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, PHY_REG(769, 20), phy_reg &
291975eba5b6SRobert Mustacchi 				     ~(1 << 14));
292075eba5b6SRobert Mustacchi }
292175eba5b6SRobert Mustacchi 
292275eba5b6SRobert Mustacchi /**
292375eba5b6SRobert Mustacchi  *  e1000_lv_phy_workarounds_ich8lan - A series of Phy workarounds to be
292475eba5b6SRobert Mustacchi  *  done after every PHY reset.
292575eba5b6SRobert Mustacchi  **/
292675eba5b6SRobert Mustacchi static s32 e1000_lv_phy_workarounds_ich8lan(struct e1000_hw *hw)
292775eba5b6SRobert Mustacchi {
292875eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
292975eba5b6SRobert Mustacchi 
293075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_lv_phy_workarounds_ich8lan");
293175eba5b6SRobert Mustacchi 
293275eba5b6SRobert Mustacchi 	if (hw->mac.type != e1000_pch2lan)
293375eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
293475eba5b6SRobert Mustacchi 
293575eba5b6SRobert Mustacchi 	/* Set MDIO slow mode before any other MDIO access */
293675eba5b6SRobert Mustacchi 	ret_val = e1000_set_mdio_slow_mode_hv(hw);
293775eba5b6SRobert Mustacchi 	if (ret_val)
293875eba5b6SRobert Mustacchi 		return ret_val;
293975eba5b6SRobert Mustacchi 
294075eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
294175eba5b6SRobert Mustacchi 	if (ret_val)
294275eba5b6SRobert Mustacchi 		return ret_val;
294375eba5b6SRobert Mustacchi 	/* set MSE higher to enable link to stay up when noise is high */
294475eba5b6SRobert Mustacchi 	ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_THRESHOLD, 0x0034);
294575eba5b6SRobert Mustacchi 	if (ret_val)
294675eba5b6SRobert Mustacchi 		goto release;
294775eba5b6SRobert Mustacchi 	/* drop link after 5 times MSE threshold was reached */
294875eba5b6SRobert Mustacchi 	ret_val = e1000_write_emi_reg_locked(hw, I82579_MSE_LINK_DOWN, 0x0005);
294975eba5b6SRobert Mustacchi release:
295075eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
295175eba5b6SRobert Mustacchi 
295275eba5b6SRobert Mustacchi 	return ret_val;
295375eba5b6SRobert Mustacchi }
295475eba5b6SRobert Mustacchi 
295575eba5b6SRobert Mustacchi /**
295675eba5b6SRobert Mustacchi  *  e1000_k1_gig_workaround_lv - K1 Si workaround
295775eba5b6SRobert Mustacchi  *  @hw:   pointer to the HW structure
295875eba5b6SRobert Mustacchi  *
2959c124a83eSRobert Mustacchi  *  Workaround to set the K1 beacon duration for 82579 parts in 10Mbps
2960c124a83eSRobert Mustacchi  *  Disable K1 for 1000 and 100 speeds
296175eba5b6SRobert Mustacchi  **/
296275eba5b6SRobert Mustacchi static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)
296375eba5b6SRobert Mustacchi {
296475eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
296575eba5b6SRobert Mustacchi 	u16 status_reg = 0;
296675eba5b6SRobert Mustacchi 
296775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_k1_workaround_lv");
296875eba5b6SRobert Mustacchi 
296975eba5b6SRobert Mustacchi 	if (hw->mac.type != e1000_pch2lan)
297075eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
297175eba5b6SRobert Mustacchi 
2972c124a83eSRobert Mustacchi 	/* Set K1 beacon duration based on 10Mbs speed */
297375eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, HV_M_STATUS, &status_reg);
297475eba5b6SRobert Mustacchi 	if (ret_val)
297575eba5b6SRobert Mustacchi 		return ret_val;
297675eba5b6SRobert Mustacchi 
297775eba5b6SRobert Mustacchi 	if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))
297875eba5b6SRobert Mustacchi 	    == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) {
2979c124a83eSRobert Mustacchi 		if (status_reg &
2980c124a83eSRobert Mustacchi 		    (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) {
298175eba5b6SRobert Mustacchi 			u16 pm_phy_reg;
298275eba5b6SRobert Mustacchi 
2983c124a83eSRobert Mustacchi 			/* LV 1G/100 Packet drop issue wa  */
298475eba5b6SRobert Mustacchi 			ret_val = hw->phy.ops.read_reg(hw, HV_PM_CTRL,
298575eba5b6SRobert Mustacchi 						       &pm_phy_reg);
298675eba5b6SRobert Mustacchi 			if (ret_val)
298775eba5b6SRobert Mustacchi 				return ret_val;
2988c124a83eSRobert Mustacchi 			pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE;
298975eba5b6SRobert Mustacchi 			ret_val = hw->phy.ops.write_reg(hw, HV_PM_CTRL,
299075eba5b6SRobert Mustacchi 							pm_phy_reg);
299175eba5b6SRobert Mustacchi 			if (ret_val)
299275eba5b6SRobert Mustacchi 				return ret_val;
299375eba5b6SRobert Mustacchi 		} else {
2994c124a83eSRobert Mustacchi 			u32 mac_reg;
2995c124a83eSRobert Mustacchi 			mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
2996c124a83eSRobert Mustacchi 			mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
299775eba5b6SRobert Mustacchi 			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC;
299875eba5b6SRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_FEXTNVM4, mac_reg);
2999c124a83eSRobert Mustacchi 		}
300075eba5b6SRobert Mustacchi 	}
300175eba5b6SRobert Mustacchi 
300275eba5b6SRobert Mustacchi 	return ret_val;
300375eba5b6SRobert Mustacchi }
300475eba5b6SRobert Mustacchi 
300575eba5b6SRobert Mustacchi /**
300675eba5b6SRobert Mustacchi  *  e1000_gate_hw_phy_config_ich8lan - disable PHY config via hardware
300775eba5b6SRobert Mustacchi  *  @hw:   pointer to the HW structure
300875eba5b6SRobert Mustacchi  *  @gate: boolean set to TRUE to gate, FALSE to ungate
300975eba5b6SRobert Mustacchi  *
301075eba5b6SRobert Mustacchi  *  Gate/ungate the automatic PHY configuration via hardware; perform
301175eba5b6SRobert Mustacchi  *  the configuration via software instead.
301275eba5b6SRobert Mustacchi  **/
301375eba5b6SRobert Mustacchi static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate)
301475eba5b6SRobert Mustacchi {
301575eba5b6SRobert Mustacchi 	u32 extcnf_ctrl;
301675eba5b6SRobert Mustacchi 
301775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_gate_hw_phy_config_ich8lan");
301875eba5b6SRobert Mustacchi 
301975eba5b6SRobert Mustacchi 	if (hw->mac.type < e1000_pch2lan)
302075eba5b6SRobert Mustacchi 		return;
302175eba5b6SRobert Mustacchi 
302275eba5b6SRobert Mustacchi 	extcnf_ctrl = E1000_READ_REG(hw, E1000_EXTCNF_CTRL);
302375eba5b6SRobert Mustacchi 
302475eba5b6SRobert Mustacchi 	if (gate)
302575eba5b6SRobert Mustacchi 		extcnf_ctrl |= E1000_EXTCNF_CTRL_GATE_PHY_CFG;
302675eba5b6SRobert Mustacchi 	else
302775eba5b6SRobert Mustacchi 		extcnf_ctrl &= ~E1000_EXTCNF_CTRL_GATE_PHY_CFG;
302875eba5b6SRobert Mustacchi 
302975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_EXTCNF_CTRL, extcnf_ctrl);
303075eba5b6SRobert Mustacchi }
303175eba5b6SRobert Mustacchi 
303275eba5b6SRobert Mustacchi /**
303375eba5b6SRobert Mustacchi  *  e1000_lan_init_done_ich8lan - Check for PHY config completion
303475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
303575eba5b6SRobert Mustacchi  *
303675eba5b6SRobert Mustacchi  *  Check the appropriate indication the MAC has finished configuring the
303775eba5b6SRobert Mustacchi  *  PHY after a software reset.
303875eba5b6SRobert Mustacchi  **/
303975eba5b6SRobert Mustacchi static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
304075eba5b6SRobert Mustacchi {
304175eba5b6SRobert Mustacchi 	u32 data, loop = E1000_ICH8_LAN_INIT_TIMEOUT;
304275eba5b6SRobert Mustacchi 
304375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_lan_init_done_ich8lan");
304475eba5b6SRobert Mustacchi 
304575eba5b6SRobert Mustacchi 	/* Wait for basic configuration completes before proceeding */
304675eba5b6SRobert Mustacchi 	do {
304775eba5b6SRobert Mustacchi 		data = E1000_READ_REG(hw, E1000_STATUS);
304875eba5b6SRobert Mustacchi 		data &= E1000_STATUS_LAN_INIT_DONE;
304975eba5b6SRobert Mustacchi 		usec_delay(100);
305075eba5b6SRobert Mustacchi 	} while ((!data) && --loop);
305175eba5b6SRobert Mustacchi 
305275eba5b6SRobert Mustacchi 	/* If basic configuration is incomplete before the above loop
305375eba5b6SRobert Mustacchi 	 * count reaches 0, loading the configuration from NVM will
305475eba5b6SRobert Mustacchi 	 * leave the PHY in a bad state possibly resulting in no link.
305575eba5b6SRobert Mustacchi 	 */
305675eba5b6SRobert Mustacchi 	if (loop == 0)
305775eba5b6SRobert Mustacchi 		DEBUGOUT("LAN_INIT_DONE not set, increase timeout\n");
305875eba5b6SRobert Mustacchi 
305975eba5b6SRobert Mustacchi 	/* Clear the Init Done bit for the next init event */
306075eba5b6SRobert Mustacchi 	data = E1000_READ_REG(hw, E1000_STATUS);
306175eba5b6SRobert Mustacchi 	data &= ~E1000_STATUS_LAN_INIT_DONE;
306275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_STATUS, data);
306375eba5b6SRobert Mustacchi }
306475eba5b6SRobert Mustacchi 
306575eba5b6SRobert Mustacchi /**
306675eba5b6SRobert Mustacchi  *  e1000_post_phy_reset_ich8lan - Perform steps required after a PHY reset
306775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
306875eba5b6SRobert Mustacchi  **/
306975eba5b6SRobert Mustacchi static s32 e1000_post_phy_reset_ich8lan(struct e1000_hw *hw)
307075eba5b6SRobert Mustacchi {
307175eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
307275eba5b6SRobert Mustacchi 	u16 reg;
307375eba5b6SRobert Mustacchi 
307475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_post_phy_reset_ich8lan");
307575eba5b6SRobert Mustacchi 
307675eba5b6SRobert Mustacchi 	if (hw->phy.ops.check_reset_block(hw))
307775eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
307875eba5b6SRobert Mustacchi 
307975eba5b6SRobert Mustacchi 	/* Allow time for h/w to get to quiescent state after reset */
308075eba5b6SRobert Mustacchi 	msec_delay(10);
308175eba5b6SRobert Mustacchi 
308275eba5b6SRobert Mustacchi 	/* Perform any necessary post-reset workarounds */
308375eba5b6SRobert Mustacchi 	switch (hw->mac.type) {
308475eba5b6SRobert Mustacchi 	case e1000_pchlan:
308575eba5b6SRobert Mustacchi 		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
308675eba5b6SRobert Mustacchi 		if (ret_val)
308775eba5b6SRobert Mustacchi 			return ret_val;
308875eba5b6SRobert Mustacchi 		break;
308975eba5b6SRobert Mustacchi 	case e1000_pch2lan:
309075eba5b6SRobert Mustacchi 		ret_val = e1000_lv_phy_workarounds_ich8lan(hw);
309175eba5b6SRobert Mustacchi 		if (ret_val)
309275eba5b6SRobert Mustacchi 			return ret_val;
309375eba5b6SRobert Mustacchi 		break;
309475eba5b6SRobert Mustacchi 	default:
309575eba5b6SRobert Mustacchi 		break;
309675eba5b6SRobert Mustacchi 	}
309775eba5b6SRobert Mustacchi 
309875eba5b6SRobert Mustacchi 	/* Clear the host wakeup bit after lcd reset */
309975eba5b6SRobert Mustacchi 	if (hw->mac.type >= e1000_pchlan) {
310075eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, &reg);
310175eba5b6SRobert Mustacchi 		reg &= ~BM_WUC_HOST_WU_BIT;
310275eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, reg);
310375eba5b6SRobert Mustacchi 	}
310475eba5b6SRobert Mustacchi 
310575eba5b6SRobert Mustacchi 	/* Configure the LCD with the extended configuration region in NVM */
310675eba5b6SRobert Mustacchi 	ret_val = e1000_sw_lcd_config_ich8lan(hw);
310775eba5b6SRobert Mustacchi 	if (ret_val)
310875eba5b6SRobert Mustacchi 		return ret_val;
310975eba5b6SRobert Mustacchi 
311075eba5b6SRobert Mustacchi 	/* Configure the LCD with the OEM bits in NVM */
311175eba5b6SRobert Mustacchi 	ret_val = e1000_oem_bits_config_ich8lan(hw, TRUE);
311275eba5b6SRobert Mustacchi 
311375eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pch2lan) {
311475eba5b6SRobert Mustacchi 		/* Ungate automatic PHY configuration on non-managed 82579 */
311575eba5b6SRobert Mustacchi 		if (!(E1000_READ_REG(hw, E1000_FWSM) &
311675eba5b6SRobert Mustacchi 		    E1000_ICH_FWSM_FW_VALID)) {
311775eba5b6SRobert Mustacchi 			msec_delay(10);
311875eba5b6SRobert Mustacchi 			e1000_gate_hw_phy_config_ich8lan(hw, FALSE);
311975eba5b6SRobert Mustacchi 		}
312075eba5b6SRobert Mustacchi 
312175eba5b6SRobert Mustacchi 		/* Set EEE LPI Update Timer to 200usec */
312275eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
312375eba5b6SRobert Mustacchi 		if (ret_val)
312475eba5b6SRobert Mustacchi 			return ret_val;
312575eba5b6SRobert Mustacchi 		ret_val = e1000_write_emi_reg_locked(hw,
312675eba5b6SRobert Mustacchi 						     I82579_LPI_UPDATE_TIMER,
312775eba5b6SRobert Mustacchi 						     0x1387);
312875eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
312975eba5b6SRobert Mustacchi 	}
313075eba5b6SRobert Mustacchi 
313175eba5b6SRobert Mustacchi 	return ret_val;
313275eba5b6SRobert Mustacchi }
313375eba5b6SRobert Mustacchi 
313475eba5b6SRobert Mustacchi /**
313575eba5b6SRobert Mustacchi  *  e1000_phy_hw_reset_ich8lan - Performs a PHY reset
313675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
313775eba5b6SRobert Mustacchi  *
313875eba5b6SRobert Mustacchi  *  Resets the PHY
313975eba5b6SRobert Mustacchi  *  This is a function pointer entry point called by drivers
314075eba5b6SRobert Mustacchi  *  or other shared routines.
314175eba5b6SRobert Mustacchi  **/
314275eba5b6SRobert Mustacchi static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
314375eba5b6SRobert Mustacchi {
314475eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
314575eba5b6SRobert Mustacchi 
314675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_hw_reset_ich8lan");
314775eba5b6SRobert Mustacchi 
314875eba5b6SRobert Mustacchi 	/* Gate automatic PHY configuration by hardware on non-managed 82579 */
314975eba5b6SRobert Mustacchi 	if ((hw->mac.type == e1000_pch2lan) &&
315075eba5b6SRobert Mustacchi 	    !(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID))
315175eba5b6SRobert Mustacchi 		e1000_gate_hw_phy_config_ich8lan(hw, TRUE);
315275eba5b6SRobert Mustacchi 
315375eba5b6SRobert Mustacchi 	ret_val = e1000_phy_hw_reset_generic(hw);
315475eba5b6SRobert Mustacchi 	if (ret_val)
315575eba5b6SRobert Mustacchi 		return ret_val;
315675eba5b6SRobert Mustacchi 
315775eba5b6SRobert Mustacchi 	return e1000_post_phy_reset_ich8lan(hw);
315875eba5b6SRobert Mustacchi }
315975eba5b6SRobert Mustacchi 
316075eba5b6SRobert Mustacchi /**
316175eba5b6SRobert Mustacchi  *  e1000_set_lplu_state_pchlan - Set Low Power Link Up state
316275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
316375eba5b6SRobert Mustacchi  *  @active: TRUE to enable LPLU, FALSE to disable
316475eba5b6SRobert Mustacchi  *
316575eba5b6SRobert Mustacchi  *  Sets the LPLU state according to the active flag.  For PCH, if OEM write
316675eba5b6SRobert Mustacchi  *  bit are disabled in the NVM, writing the LPLU bits in the MAC will not set
316775eba5b6SRobert Mustacchi  *  the phy speed. This function will manually set the LPLU bit and restart
316875eba5b6SRobert Mustacchi  *  auto-neg as hw would do. D3 and D0 LPLU will call the same function
316975eba5b6SRobert Mustacchi  *  since it configures the same bit.
317075eba5b6SRobert Mustacchi  **/
317175eba5b6SRobert Mustacchi static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active)
317275eba5b6SRobert Mustacchi {
317375eba5b6SRobert Mustacchi 	s32 ret_val;
317475eba5b6SRobert Mustacchi 	u16 oem_reg;
317575eba5b6SRobert Mustacchi 
317675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_lplu_state_pchlan");
317775eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, HV_OEM_BITS, &oem_reg);
317875eba5b6SRobert Mustacchi 	if (ret_val)
317975eba5b6SRobert Mustacchi 		return ret_val;
318075eba5b6SRobert Mustacchi 
318175eba5b6SRobert Mustacchi 	if (active)
318275eba5b6SRobert Mustacchi 		oem_reg |= HV_OEM_BITS_LPLU;
318375eba5b6SRobert Mustacchi 	else
318475eba5b6SRobert Mustacchi 		oem_reg &= ~HV_OEM_BITS_LPLU;
318575eba5b6SRobert Mustacchi 
318675eba5b6SRobert Mustacchi 	if (!hw->phy.ops.check_reset_block(hw))
318775eba5b6SRobert Mustacchi 		oem_reg |= HV_OEM_BITS_RESTART_AN;
318875eba5b6SRobert Mustacchi 
318975eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, HV_OEM_BITS, oem_reg);
319075eba5b6SRobert Mustacchi }
319175eba5b6SRobert Mustacchi 
319275eba5b6SRobert Mustacchi /**
319375eba5b6SRobert Mustacchi  *  e1000_set_d0_lplu_state_ich8lan - Set Low Power Linkup D0 state
319475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
319575eba5b6SRobert Mustacchi  *  @active: TRUE to enable LPLU, FALSE to disable
319675eba5b6SRobert Mustacchi  *
319775eba5b6SRobert Mustacchi  *  Sets the LPLU D0 state according to the active flag.  When
319875eba5b6SRobert Mustacchi  *  activating LPLU this function also disables smart speed
319975eba5b6SRobert Mustacchi  *  and vice versa.  LPLU will not be activated unless the
320075eba5b6SRobert Mustacchi  *  device autonegotiation advertisement meets standards of
320175eba5b6SRobert Mustacchi  *  either 10 or 10/100 or 10/100/1000 at all duplexes.
320275eba5b6SRobert Mustacchi  *  This is a function pointer entry point only called by
320375eba5b6SRobert Mustacchi  *  PHY setup routines.
320475eba5b6SRobert Mustacchi  **/
320575eba5b6SRobert Mustacchi static s32 e1000_set_d0_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
320675eba5b6SRobert Mustacchi {
320775eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
320875eba5b6SRobert Mustacchi 	u32 phy_ctrl;
320975eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
321075eba5b6SRobert Mustacchi 	u16 data;
321175eba5b6SRobert Mustacchi 
321275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_d0_lplu_state_ich8lan");
321375eba5b6SRobert Mustacchi 
321475eba5b6SRobert Mustacchi 	if (phy->type == e1000_phy_ife)
321575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
321675eba5b6SRobert Mustacchi 
321775eba5b6SRobert Mustacchi 	phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
321875eba5b6SRobert Mustacchi 
321975eba5b6SRobert Mustacchi 	if (active) {
322075eba5b6SRobert Mustacchi 		phy_ctrl |= E1000_PHY_CTRL_D0A_LPLU;
322175eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
322275eba5b6SRobert Mustacchi 
322375eba5b6SRobert Mustacchi 		if (phy->type != e1000_phy_igp_3)
322475eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
322575eba5b6SRobert Mustacchi 
322675eba5b6SRobert Mustacchi 		/* Call gig speed drop workaround on LPLU before accessing
322775eba5b6SRobert Mustacchi 		 * any PHY registers
322875eba5b6SRobert Mustacchi 		 */
322975eba5b6SRobert Mustacchi 		if (hw->mac.type == e1000_ich8lan)
323075eba5b6SRobert Mustacchi 			e1000_gig_downshift_workaround_ich8lan(hw);
323175eba5b6SRobert Mustacchi 
323275eba5b6SRobert Mustacchi 		/* When LPLU is enabled, we should disable SmartSpeed */
323375eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw,
323475eba5b6SRobert Mustacchi 					    IGP01E1000_PHY_PORT_CONFIG,
323575eba5b6SRobert Mustacchi 					    &data);
323675eba5b6SRobert Mustacchi 		if (ret_val)
323775eba5b6SRobert Mustacchi 			return ret_val;
323875eba5b6SRobert Mustacchi 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
323975eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw,
324075eba5b6SRobert Mustacchi 					     IGP01E1000_PHY_PORT_CONFIG,
324175eba5b6SRobert Mustacchi 					     data);
324275eba5b6SRobert Mustacchi 		if (ret_val)
324375eba5b6SRobert Mustacchi 			return ret_val;
324475eba5b6SRobert Mustacchi 	} else {
324575eba5b6SRobert Mustacchi 		phy_ctrl &= ~E1000_PHY_CTRL_D0A_LPLU;
324675eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
324775eba5b6SRobert Mustacchi 
324875eba5b6SRobert Mustacchi 		if (phy->type != e1000_phy_igp_3)
324975eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
325075eba5b6SRobert Mustacchi 
325175eba5b6SRobert Mustacchi 		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
325275eba5b6SRobert Mustacchi 		 * during Dx states where the power conservation is most
325375eba5b6SRobert Mustacchi 		 * important.  During driver activity we should enable
325475eba5b6SRobert Mustacchi 		 * SmartSpeed, so performance is maintained.
325575eba5b6SRobert Mustacchi 		 */
325675eba5b6SRobert Mustacchi 		if (phy->smart_speed == e1000_smart_speed_on) {
325775eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw,
325875eba5b6SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
325975eba5b6SRobert Mustacchi 						    &data);
326075eba5b6SRobert Mustacchi 			if (ret_val)
326175eba5b6SRobert Mustacchi 				return ret_val;
326275eba5b6SRobert Mustacchi 
326375eba5b6SRobert Mustacchi 			data |= IGP01E1000_PSCFR_SMART_SPEED;
326475eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw,
326575eba5b6SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
326675eba5b6SRobert Mustacchi 						     data);
326775eba5b6SRobert Mustacchi 			if (ret_val)
326875eba5b6SRobert Mustacchi 				return ret_val;
326975eba5b6SRobert Mustacchi 		} else if (phy->smart_speed == e1000_smart_speed_off) {
327075eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw,
327175eba5b6SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
327275eba5b6SRobert Mustacchi 						    &data);
327375eba5b6SRobert Mustacchi 			if (ret_val)
327475eba5b6SRobert Mustacchi 				return ret_val;
327575eba5b6SRobert Mustacchi 
327675eba5b6SRobert Mustacchi 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
327775eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw,
327875eba5b6SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
327975eba5b6SRobert Mustacchi 						     data);
328075eba5b6SRobert Mustacchi 			if (ret_val)
328175eba5b6SRobert Mustacchi 				return ret_val;
328275eba5b6SRobert Mustacchi 		}
328375eba5b6SRobert Mustacchi 	}
328475eba5b6SRobert Mustacchi 
328575eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
328675eba5b6SRobert Mustacchi }
328775eba5b6SRobert Mustacchi 
328875eba5b6SRobert Mustacchi /**
328975eba5b6SRobert Mustacchi  *  e1000_set_d3_lplu_state_ich8lan - Set Low Power Linkup D3 state
329075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
329175eba5b6SRobert Mustacchi  *  @active: TRUE to enable LPLU, FALSE to disable
329275eba5b6SRobert Mustacchi  *
329375eba5b6SRobert Mustacchi  *  Sets the LPLU D3 state according to the active flag.  When
329475eba5b6SRobert Mustacchi  *  activating LPLU this function also disables smart speed
329575eba5b6SRobert Mustacchi  *  and vice versa.  LPLU will not be activated unless the
329675eba5b6SRobert Mustacchi  *  device autonegotiation advertisement meets standards of
329775eba5b6SRobert Mustacchi  *  either 10 or 10/100 or 10/100/1000 at all duplexes.
329875eba5b6SRobert Mustacchi  *  This is a function pointer entry point only called by
329975eba5b6SRobert Mustacchi  *  PHY setup routines.
330075eba5b6SRobert Mustacchi  **/
330175eba5b6SRobert Mustacchi static s32 e1000_set_d3_lplu_state_ich8lan(struct e1000_hw *hw, bool active)
330275eba5b6SRobert Mustacchi {
330375eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
330475eba5b6SRobert Mustacchi 	u32 phy_ctrl;
330575eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
330675eba5b6SRobert Mustacchi 	u16 data;
330775eba5b6SRobert Mustacchi 
330875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_d3_lplu_state_ich8lan");
330975eba5b6SRobert Mustacchi 
331075eba5b6SRobert Mustacchi 	phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
331175eba5b6SRobert Mustacchi 
331275eba5b6SRobert Mustacchi 	if (!active) {
331375eba5b6SRobert Mustacchi 		phy_ctrl &= ~E1000_PHY_CTRL_NOND0A_LPLU;
331475eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
331575eba5b6SRobert Mustacchi 
331675eba5b6SRobert Mustacchi 		if (phy->type != e1000_phy_igp_3)
331775eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
331875eba5b6SRobert Mustacchi 
331975eba5b6SRobert Mustacchi 		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
332075eba5b6SRobert Mustacchi 		 * during Dx states where the power conservation is most
332175eba5b6SRobert Mustacchi 		 * important.  During driver activity we should enable
332275eba5b6SRobert Mustacchi 		 * SmartSpeed, so performance is maintained.
332375eba5b6SRobert Mustacchi 		 */
332475eba5b6SRobert Mustacchi 		if (phy->smart_speed == e1000_smart_speed_on) {
332575eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw,
332675eba5b6SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
332775eba5b6SRobert Mustacchi 						    &data);
332875eba5b6SRobert Mustacchi 			if (ret_val)
332975eba5b6SRobert Mustacchi 				return ret_val;
333075eba5b6SRobert Mustacchi 
333175eba5b6SRobert Mustacchi 			data |= IGP01E1000_PSCFR_SMART_SPEED;
333275eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw,
333375eba5b6SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
333475eba5b6SRobert Mustacchi 						     data);
333575eba5b6SRobert Mustacchi 			if (ret_val)
333675eba5b6SRobert Mustacchi 				return ret_val;
333775eba5b6SRobert Mustacchi 		} else if (phy->smart_speed == e1000_smart_speed_off) {
333875eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw,
333975eba5b6SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
334075eba5b6SRobert Mustacchi 						    &data);
334175eba5b6SRobert Mustacchi 			if (ret_val)
334275eba5b6SRobert Mustacchi 				return ret_val;
334375eba5b6SRobert Mustacchi 
334475eba5b6SRobert Mustacchi 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
334575eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw,
334675eba5b6SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
334775eba5b6SRobert Mustacchi 						     data);
334875eba5b6SRobert Mustacchi 			if (ret_val)
334975eba5b6SRobert Mustacchi 				return ret_val;
335075eba5b6SRobert Mustacchi 		}
335175eba5b6SRobert Mustacchi 	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
335275eba5b6SRobert Mustacchi 		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
335375eba5b6SRobert Mustacchi 		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
335475eba5b6SRobert Mustacchi 		phy_ctrl |= E1000_PHY_CTRL_NOND0A_LPLU;
335575eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
335675eba5b6SRobert Mustacchi 
335775eba5b6SRobert Mustacchi 		if (phy->type != e1000_phy_igp_3)
335875eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
335975eba5b6SRobert Mustacchi 
336075eba5b6SRobert Mustacchi 		/* Call gig speed drop workaround on LPLU before accessing
336175eba5b6SRobert Mustacchi 		 * any PHY registers
336275eba5b6SRobert Mustacchi 		 */
336375eba5b6SRobert Mustacchi 		if (hw->mac.type == e1000_ich8lan)
336475eba5b6SRobert Mustacchi 			e1000_gig_downshift_workaround_ich8lan(hw);
336575eba5b6SRobert Mustacchi 
336675eba5b6SRobert Mustacchi 		/* When LPLU is enabled, we should disable SmartSpeed */
336775eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw,
336875eba5b6SRobert Mustacchi 					    IGP01E1000_PHY_PORT_CONFIG,
336975eba5b6SRobert Mustacchi 					    &data);
337075eba5b6SRobert Mustacchi 		if (ret_val)
337175eba5b6SRobert Mustacchi 			return ret_val;
337275eba5b6SRobert Mustacchi 
337375eba5b6SRobert Mustacchi 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
337475eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw,
337575eba5b6SRobert Mustacchi 					     IGP01E1000_PHY_PORT_CONFIG,
337675eba5b6SRobert Mustacchi 					     data);
337775eba5b6SRobert Mustacchi 	}
337875eba5b6SRobert Mustacchi 
337975eba5b6SRobert Mustacchi 	return ret_val;
338075eba5b6SRobert Mustacchi }
338175eba5b6SRobert Mustacchi 
338275eba5b6SRobert Mustacchi /**
338375eba5b6SRobert Mustacchi  *  e1000_valid_nvm_bank_detect_ich8lan - finds out the valid bank 0 or 1
338475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
338575eba5b6SRobert Mustacchi  *  @bank:  pointer to the variable that returns the active bank
338675eba5b6SRobert Mustacchi  *
338775eba5b6SRobert Mustacchi  *  Reads signature byte from the NVM using the flash access registers.
338875eba5b6SRobert Mustacchi  *  Word 0x13 bits 15:14 = 10b indicate a valid signature for that bank.
338975eba5b6SRobert Mustacchi  **/
339075eba5b6SRobert Mustacchi static s32 e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw *hw, u32 *bank)
339175eba5b6SRobert Mustacchi {
339275eba5b6SRobert Mustacchi 	u32 eecd;
339375eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
339475eba5b6SRobert Mustacchi 	u32 bank1_offset = nvm->flash_bank_size * sizeof(u16);
339575eba5b6SRobert Mustacchi 	u32 act_offset = E1000_ICH_NVM_SIG_WORD * 2 + 1;
3396*42cc51e0SRobert Mustacchi 	u32 nvm_dword = 0;
339775eba5b6SRobert Mustacchi 	u8 sig_byte = 0;
339875eba5b6SRobert Mustacchi 	s32 ret_val;
339975eba5b6SRobert Mustacchi 
340075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_valid_nvm_bank_detect_ich8lan");
340175eba5b6SRobert Mustacchi 
340275eba5b6SRobert Mustacchi 	switch (hw->mac.type) {
3403*42cc51e0SRobert Mustacchi 	case e1000_pch_spt:
3404*42cc51e0SRobert Mustacchi 		bank1_offset = nvm->flash_bank_size;
3405*42cc51e0SRobert Mustacchi 		act_offset = E1000_ICH_NVM_SIG_WORD;
3406*42cc51e0SRobert Mustacchi 
3407*42cc51e0SRobert Mustacchi 		/* set bank to 0 in case flash read fails */
3408*42cc51e0SRobert Mustacchi 		*bank = 0;
3409*42cc51e0SRobert Mustacchi 
3410*42cc51e0SRobert Mustacchi 		/* Check bank 0 */
3411*42cc51e0SRobert Mustacchi 		ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset,
3412*42cc51e0SRobert Mustacchi 							 &nvm_dword);
3413*42cc51e0SRobert Mustacchi 		if (ret_val)
3414*42cc51e0SRobert Mustacchi 			return ret_val;
3415*42cc51e0SRobert Mustacchi 		sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
3416*42cc51e0SRobert Mustacchi 		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
3417*42cc51e0SRobert Mustacchi 		    E1000_ICH_NVM_SIG_VALUE) {
3418*42cc51e0SRobert Mustacchi 			*bank = 0;
3419*42cc51e0SRobert Mustacchi 			return E1000_SUCCESS;
3420*42cc51e0SRobert Mustacchi 		}
3421*42cc51e0SRobert Mustacchi 
3422*42cc51e0SRobert Mustacchi 		/* Check bank 1 */
3423*42cc51e0SRobert Mustacchi 		ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset +
3424*42cc51e0SRobert Mustacchi 							 bank1_offset,
3425*42cc51e0SRobert Mustacchi 							 &nvm_dword);
3426*42cc51e0SRobert Mustacchi 		if (ret_val)
3427*42cc51e0SRobert Mustacchi 			return ret_val;
3428*42cc51e0SRobert Mustacchi 		sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
3429*42cc51e0SRobert Mustacchi 		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
3430*42cc51e0SRobert Mustacchi 		    E1000_ICH_NVM_SIG_VALUE) {
3431*42cc51e0SRobert Mustacchi 			*bank = 1;
3432*42cc51e0SRobert Mustacchi 			return E1000_SUCCESS;
3433*42cc51e0SRobert Mustacchi 		}
3434*42cc51e0SRobert Mustacchi 
3435*42cc51e0SRobert Mustacchi 		DEBUGOUT("ERROR: No valid NVM bank present\n");
3436*42cc51e0SRobert Mustacchi 		return -E1000_ERR_NVM;
343775eba5b6SRobert Mustacchi 	case e1000_ich8lan:
343875eba5b6SRobert Mustacchi 	case e1000_ich9lan:
343975eba5b6SRobert Mustacchi 		eecd = E1000_READ_REG(hw, E1000_EECD);
344075eba5b6SRobert Mustacchi 		if ((eecd & E1000_EECD_SEC1VAL_VALID_MASK) ==
344175eba5b6SRobert Mustacchi 		    E1000_EECD_SEC1VAL_VALID_MASK) {
344275eba5b6SRobert Mustacchi 			if (eecd & E1000_EECD_SEC1VAL)
344375eba5b6SRobert Mustacchi 				*bank = 1;
344475eba5b6SRobert Mustacchi 			else
344575eba5b6SRobert Mustacchi 				*bank = 0;
344675eba5b6SRobert Mustacchi 
344775eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
344875eba5b6SRobert Mustacchi 		}
344975eba5b6SRobert Mustacchi 		DEBUGOUT("Unable to determine valid NVM bank via EEC - reading flash signature\n");
345075eba5b6SRobert Mustacchi 		/* fall-thru */
345175eba5b6SRobert Mustacchi 	default:
345275eba5b6SRobert Mustacchi 		/* set bank to 0 in case flash read fails */
345375eba5b6SRobert Mustacchi 		*bank = 0;
345475eba5b6SRobert Mustacchi 
345575eba5b6SRobert Mustacchi 		/* Check bank 0 */
345675eba5b6SRobert Mustacchi 		ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset,
345775eba5b6SRobert Mustacchi 							&sig_byte);
345875eba5b6SRobert Mustacchi 		if (ret_val)
345975eba5b6SRobert Mustacchi 			return ret_val;
346075eba5b6SRobert Mustacchi 		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
346175eba5b6SRobert Mustacchi 		    E1000_ICH_NVM_SIG_VALUE) {
346275eba5b6SRobert Mustacchi 			*bank = 0;
346375eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
346475eba5b6SRobert Mustacchi 		}
346575eba5b6SRobert Mustacchi 
346675eba5b6SRobert Mustacchi 		/* Check bank 1 */
346775eba5b6SRobert Mustacchi 		ret_val = e1000_read_flash_byte_ich8lan(hw, act_offset +
346875eba5b6SRobert Mustacchi 							bank1_offset,
346975eba5b6SRobert Mustacchi 							&sig_byte);
347075eba5b6SRobert Mustacchi 		if (ret_val)
347175eba5b6SRobert Mustacchi 			return ret_val;
347275eba5b6SRobert Mustacchi 		if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
347375eba5b6SRobert Mustacchi 		    E1000_ICH_NVM_SIG_VALUE) {
347475eba5b6SRobert Mustacchi 			*bank = 1;
347575eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
347675eba5b6SRobert Mustacchi 		}
347775eba5b6SRobert Mustacchi 
347875eba5b6SRobert Mustacchi 		DEBUGOUT("ERROR: No valid NVM bank present\n");
347975eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
348075eba5b6SRobert Mustacchi 	}
348175eba5b6SRobert Mustacchi }
348275eba5b6SRobert Mustacchi 
348375eba5b6SRobert Mustacchi /**
3484*42cc51e0SRobert Mustacchi  *  e1000_read_nvm_spt - NVM access for SPT
3485*42cc51e0SRobert Mustacchi  *  @hw: pointer to the HW structure
3486*42cc51e0SRobert Mustacchi  *  @offset: The offset (in bytes) of the word(s) to read.
3487*42cc51e0SRobert Mustacchi  *  @words: Size of data to read in words.
3488*42cc51e0SRobert Mustacchi  *  @data: pointer to the word(s) to read at offset.
3489*42cc51e0SRobert Mustacchi  *
3490*42cc51e0SRobert Mustacchi  *  Reads a word(s) from the NVM
3491*42cc51e0SRobert Mustacchi  **/
3492*42cc51e0SRobert Mustacchi static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
3493*42cc51e0SRobert Mustacchi 			      u16 *data)
3494*42cc51e0SRobert Mustacchi {
3495*42cc51e0SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
3496*42cc51e0SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
3497*42cc51e0SRobert Mustacchi 	u32 act_offset;
3498*42cc51e0SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
3499*42cc51e0SRobert Mustacchi 	u32 bank = 0;
3500*42cc51e0SRobert Mustacchi 	u32 dword = 0;
3501*42cc51e0SRobert Mustacchi 	u16 offset_to_read;
3502*42cc51e0SRobert Mustacchi 	u16 i;
3503*42cc51e0SRobert Mustacchi 
3504*42cc51e0SRobert Mustacchi 	DEBUGFUNC("e1000_read_nvm_spt");
3505*42cc51e0SRobert Mustacchi 
3506*42cc51e0SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
3507*42cc51e0SRobert Mustacchi 	    (words == 0)) {
3508*42cc51e0SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
3509*42cc51e0SRobert Mustacchi 		ret_val = -E1000_ERR_NVM;
3510*42cc51e0SRobert Mustacchi 		goto out;
3511*42cc51e0SRobert Mustacchi 	}
3512*42cc51e0SRobert Mustacchi 
3513*42cc51e0SRobert Mustacchi 	nvm->ops.acquire(hw);
3514*42cc51e0SRobert Mustacchi 
3515*42cc51e0SRobert Mustacchi 	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
3516*42cc51e0SRobert Mustacchi 	if (ret_val != E1000_SUCCESS) {
3517*42cc51e0SRobert Mustacchi 		DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
3518*42cc51e0SRobert Mustacchi 		bank = 0;
3519*42cc51e0SRobert Mustacchi 	}
3520*42cc51e0SRobert Mustacchi 
3521*42cc51e0SRobert Mustacchi 	act_offset = (bank) ? nvm->flash_bank_size : 0;
3522*42cc51e0SRobert Mustacchi 	act_offset += offset;
3523*42cc51e0SRobert Mustacchi 
3524*42cc51e0SRobert Mustacchi 	ret_val = E1000_SUCCESS;
3525*42cc51e0SRobert Mustacchi 
3526*42cc51e0SRobert Mustacchi 	for (i = 0; i < words; i += 2) {
3527*42cc51e0SRobert Mustacchi 		if (words - i == 1) {
3528*42cc51e0SRobert Mustacchi 			if (dev_spec->shadow_ram[offset+i].modified) {
3529*42cc51e0SRobert Mustacchi 				data[i] = dev_spec->shadow_ram[offset+i].value;
3530*42cc51e0SRobert Mustacchi 			} else {
3531*42cc51e0SRobert Mustacchi 				offset_to_read = act_offset + i -
3532*42cc51e0SRobert Mustacchi 						 ((act_offset + i) % 2);
3533*42cc51e0SRobert Mustacchi 				ret_val =
3534*42cc51e0SRobert Mustacchi 				   e1000_read_flash_dword_ich8lan(hw,
3535*42cc51e0SRobert Mustacchi 								 offset_to_read,
3536*42cc51e0SRobert Mustacchi 								 &dword);
3537*42cc51e0SRobert Mustacchi 				if (ret_val)
3538*42cc51e0SRobert Mustacchi 					break;
3539*42cc51e0SRobert Mustacchi 				if ((act_offset + i) % 2 == 0)
3540*42cc51e0SRobert Mustacchi 					data[i] = (u16)(dword & 0xFFFF);
3541*42cc51e0SRobert Mustacchi 				else
3542*42cc51e0SRobert Mustacchi 					data[i] = (u16)((dword >> 16) & 0xFFFF);
3543*42cc51e0SRobert Mustacchi 			}
3544*42cc51e0SRobert Mustacchi 		} else {
3545*42cc51e0SRobert Mustacchi 			offset_to_read = act_offset + i;
3546*42cc51e0SRobert Mustacchi 			if (!(dev_spec->shadow_ram[offset+i].modified) ||
3547*42cc51e0SRobert Mustacchi 			    !(dev_spec->shadow_ram[offset+i+1].modified)) {
3548*42cc51e0SRobert Mustacchi 				ret_val =
3549*42cc51e0SRobert Mustacchi 				   e1000_read_flash_dword_ich8lan(hw,
3550*42cc51e0SRobert Mustacchi 								 offset_to_read,
3551*42cc51e0SRobert Mustacchi 								 &dword);
3552*42cc51e0SRobert Mustacchi 				if (ret_val)
3553*42cc51e0SRobert Mustacchi 					break;
3554*42cc51e0SRobert Mustacchi 			}
3555*42cc51e0SRobert Mustacchi 			if (dev_spec->shadow_ram[offset+i].modified)
3556*42cc51e0SRobert Mustacchi 				data[i] = dev_spec->shadow_ram[offset+i].value;
3557*42cc51e0SRobert Mustacchi 			else
3558*42cc51e0SRobert Mustacchi 				data[i] = (u16) (dword & 0xFFFF);
3559*42cc51e0SRobert Mustacchi 			if (dev_spec->shadow_ram[offset+i].modified)
3560*42cc51e0SRobert Mustacchi 				data[i+1] =
3561*42cc51e0SRobert Mustacchi 				   dev_spec->shadow_ram[offset+i+1].value;
3562*42cc51e0SRobert Mustacchi 			else
3563*42cc51e0SRobert Mustacchi 				data[i+1] = (u16) (dword >> 16 & 0xFFFF);
3564*42cc51e0SRobert Mustacchi 		}
3565*42cc51e0SRobert Mustacchi 	}
3566*42cc51e0SRobert Mustacchi 
3567*42cc51e0SRobert Mustacchi 	nvm->ops.release(hw);
3568*42cc51e0SRobert Mustacchi 
3569*42cc51e0SRobert Mustacchi out:
3570*42cc51e0SRobert Mustacchi 	if (ret_val)
3571*42cc51e0SRobert Mustacchi 		DEBUGOUT1("NVM read error: %d\n", ret_val);
3572*42cc51e0SRobert Mustacchi 
3573*42cc51e0SRobert Mustacchi 	return ret_val;
3574*42cc51e0SRobert Mustacchi }
3575*42cc51e0SRobert Mustacchi 
3576*42cc51e0SRobert Mustacchi /**
357775eba5b6SRobert Mustacchi  *  e1000_read_nvm_ich8lan - Read word(s) from the NVM
357875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
357975eba5b6SRobert Mustacchi  *  @offset: The offset (in bytes) of the word(s) to read.
358075eba5b6SRobert Mustacchi  *  @words: Size of data to read in words
358175eba5b6SRobert Mustacchi  *  @data: Pointer to the word(s) to read at offset.
358275eba5b6SRobert Mustacchi  *
358375eba5b6SRobert Mustacchi  *  Reads a word(s) from the NVM using the flash access registers.
358475eba5b6SRobert Mustacchi  **/
358575eba5b6SRobert Mustacchi static s32 e1000_read_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
358675eba5b6SRobert Mustacchi 				  u16 *data)
358775eba5b6SRobert Mustacchi {
358875eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
358975eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
359075eba5b6SRobert Mustacchi 	u32 act_offset;
359175eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
359275eba5b6SRobert Mustacchi 	u32 bank = 0;
359375eba5b6SRobert Mustacchi 	u16 i, word;
359475eba5b6SRobert Mustacchi 
359575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_nvm_ich8lan");
359675eba5b6SRobert Mustacchi 
359775eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
359875eba5b6SRobert Mustacchi 	    (words == 0)) {
359975eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
360075eba5b6SRobert Mustacchi 		ret_val = -E1000_ERR_NVM;
360175eba5b6SRobert Mustacchi 		goto out;
360275eba5b6SRobert Mustacchi 	}
360375eba5b6SRobert Mustacchi 
360475eba5b6SRobert Mustacchi 	nvm->ops.acquire(hw);
360575eba5b6SRobert Mustacchi 
360675eba5b6SRobert Mustacchi 	ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
360775eba5b6SRobert Mustacchi 	if (ret_val != E1000_SUCCESS) {
360875eba5b6SRobert Mustacchi 		DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
360975eba5b6SRobert Mustacchi 		bank = 0;
361075eba5b6SRobert Mustacchi 	}
361175eba5b6SRobert Mustacchi 
361275eba5b6SRobert Mustacchi 	act_offset = (bank) ? nvm->flash_bank_size : 0;
361375eba5b6SRobert Mustacchi 	act_offset += offset;
361475eba5b6SRobert Mustacchi 
361575eba5b6SRobert Mustacchi 	ret_val = E1000_SUCCESS;
361675eba5b6SRobert Mustacchi 	for (i = 0; i < words; i++) {
361775eba5b6SRobert Mustacchi 		if (dev_spec->shadow_ram[offset+i].modified) {
361875eba5b6SRobert Mustacchi 			data[i] = dev_spec->shadow_ram[offset+i].value;
361975eba5b6SRobert Mustacchi 		} else {
362075eba5b6SRobert Mustacchi 			ret_val = e1000_read_flash_word_ich8lan(hw,
362175eba5b6SRobert Mustacchi 								act_offset + i,
362275eba5b6SRobert Mustacchi 								&word);
362375eba5b6SRobert Mustacchi 			if (ret_val)
362475eba5b6SRobert Mustacchi 				break;
362575eba5b6SRobert Mustacchi 			data[i] = word;
362675eba5b6SRobert Mustacchi 		}
362775eba5b6SRobert Mustacchi 	}
362875eba5b6SRobert Mustacchi 
362975eba5b6SRobert Mustacchi 	nvm->ops.release(hw);
363075eba5b6SRobert Mustacchi 
363175eba5b6SRobert Mustacchi out:
363275eba5b6SRobert Mustacchi 	if (ret_val)
363375eba5b6SRobert Mustacchi 		DEBUGOUT1("NVM read error: %d\n", ret_val);
363475eba5b6SRobert Mustacchi 
363575eba5b6SRobert Mustacchi 	return ret_val;
363675eba5b6SRobert Mustacchi }
363775eba5b6SRobert Mustacchi 
363875eba5b6SRobert Mustacchi /**
363975eba5b6SRobert Mustacchi  *  e1000_flash_cycle_init_ich8lan - Initialize flash
364075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
364175eba5b6SRobert Mustacchi  *
364275eba5b6SRobert Mustacchi  *  This function does initial flash setup so that a new read/write/erase cycle
364375eba5b6SRobert Mustacchi  *  can be started.
364475eba5b6SRobert Mustacchi  **/
364575eba5b6SRobert Mustacchi static s32 e1000_flash_cycle_init_ich8lan(struct e1000_hw *hw)
364675eba5b6SRobert Mustacchi {
364775eba5b6SRobert Mustacchi 	union ich8_hws_flash_status hsfsts;
364875eba5b6SRobert Mustacchi 	s32 ret_val = -E1000_ERR_NVM;
364975eba5b6SRobert Mustacchi 
365075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_flash_cycle_init_ich8lan");
365175eba5b6SRobert Mustacchi 
365275eba5b6SRobert Mustacchi 	hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
365375eba5b6SRobert Mustacchi 
365475eba5b6SRobert Mustacchi 	/* Check if the flash descriptor is valid */
365575eba5b6SRobert Mustacchi 	if (!hsfsts.hsf_status.fldesvalid) {
365675eba5b6SRobert Mustacchi 		DEBUGOUT("Flash descriptor invalid.  SW Sequencing must be used.\n");
365775eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
365875eba5b6SRobert Mustacchi 	}
365975eba5b6SRobert Mustacchi 
366075eba5b6SRobert Mustacchi 	/* Clear FCERR and DAEL in hw status by writing 1 */
366175eba5b6SRobert Mustacchi 	hsfsts.hsf_status.flcerr = 1;
366275eba5b6SRobert Mustacchi 	hsfsts.hsf_status.dael = 1;
3663*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt)
3664*42cc51e0SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3665*42cc51e0SRobert Mustacchi 				      hsfsts.regval & 0xFFFF);
3666*42cc51e0SRobert Mustacchi 	else
366775eba5b6SRobert Mustacchi 		E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS, hsfsts.regval);
366875eba5b6SRobert Mustacchi 
366975eba5b6SRobert Mustacchi 	/* Either we should have a hardware SPI cycle in progress
367075eba5b6SRobert Mustacchi 	 * bit to check against, in order to start a new cycle or
367175eba5b6SRobert Mustacchi 	 * FDONE bit should be changed in the hardware so that it
367275eba5b6SRobert Mustacchi 	 * is 1 after hardware reset, which can then be used as an
367375eba5b6SRobert Mustacchi 	 * indication whether a cycle is in progress or has been
367475eba5b6SRobert Mustacchi 	 * completed.
367575eba5b6SRobert Mustacchi 	 */
367675eba5b6SRobert Mustacchi 
367775eba5b6SRobert Mustacchi 	if (!hsfsts.hsf_status.flcinprog) {
367875eba5b6SRobert Mustacchi 		/* There is no cycle running at present,
367975eba5b6SRobert Mustacchi 		 * so we can start a cycle.
368075eba5b6SRobert Mustacchi 		 * Begin by setting Flash Cycle Done.
368175eba5b6SRobert Mustacchi 		 */
368275eba5b6SRobert Mustacchi 		hsfsts.hsf_status.flcdone = 1;
3683*42cc51e0SRobert Mustacchi 		if (hw->mac.type == e1000_pch_spt)
3684*42cc51e0SRobert Mustacchi 			E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3685*42cc51e0SRobert Mustacchi 					      hsfsts.regval & 0xFFFF);
3686*42cc51e0SRobert Mustacchi 		else
3687*42cc51e0SRobert Mustacchi 			E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
3688*42cc51e0SRobert Mustacchi 						hsfsts.regval);
368975eba5b6SRobert Mustacchi 		ret_val = E1000_SUCCESS;
369075eba5b6SRobert Mustacchi 	} else {
369175eba5b6SRobert Mustacchi 		s32 i;
369275eba5b6SRobert Mustacchi 
369375eba5b6SRobert Mustacchi 		/* Otherwise poll for sometime so the current
369475eba5b6SRobert Mustacchi 		 * cycle has a chance to end before giving up.
369575eba5b6SRobert Mustacchi 		 */
369675eba5b6SRobert Mustacchi 		for (i = 0; i < ICH_FLASH_READ_COMMAND_TIMEOUT; i++) {
369775eba5b6SRobert Mustacchi 			hsfsts.regval = E1000_READ_FLASH_REG16(hw,
369875eba5b6SRobert Mustacchi 							      ICH_FLASH_HSFSTS);
369975eba5b6SRobert Mustacchi 			if (!hsfsts.hsf_status.flcinprog) {
370075eba5b6SRobert Mustacchi 				ret_val = E1000_SUCCESS;
370175eba5b6SRobert Mustacchi 				break;
370275eba5b6SRobert Mustacchi 			}
370375eba5b6SRobert Mustacchi 			usec_delay(1);
370475eba5b6SRobert Mustacchi 		}
370575eba5b6SRobert Mustacchi 		if (ret_val == E1000_SUCCESS) {
370675eba5b6SRobert Mustacchi 			/* Successful in waiting for previous cycle to timeout,
370775eba5b6SRobert Mustacchi 			 * now set the Flash Cycle Done.
370875eba5b6SRobert Mustacchi 			 */
370975eba5b6SRobert Mustacchi 			hsfsts.hsf_status.flcdone = 1;
3710*42cc51e0SRobert Mustacchi 			if (hw->mac.type == e1000_pch_spt)
3711*42cc51e0SRobert Mustacchi 				E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3712*42cc51e0SRobert Mustacchi 						      hsfsts.regval & 0xFFFF);
3713*42cc51e0SRobert Mustacchi 			else
371475eba5b6SRobert Mustacchi 				E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
371575eba5b6SRobert Mustacchi 							hsfsts.regval);
371675eba5b6SRobert Mustacchi 		} else {
371775eba5b6SRobert Mustacchi 			DEBUGOUT("Flash controller busy, cannot get access\n");
371875eba5b6SRobert Mustacchi 		}
371975eba5b6SRobert Mustacchi 	}
372075eba5b6SRobert Mustacchi 
372175eba5b6SRobert Mustacchi 	return ret_val;
372275eba5b6SRobert Mustacchi }
372375eba5b6SRobert Mustacchi 
372475eba5b6SRobert Mustacchi /**
372575eba5b6SRobert Mustacchi  *  e1000_flash_cycle_ich8lan - Starts flash cycle (read/write/erase)
372675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
372775eba5b6SRobert Mustacchi  *  @timeout: maximum time to wait for completion
372875eba5b6SRobert Mustacchi  *
372975eba5b6SRobert Mustacchi  *  This function starts a flash cycle and waits for its completion.
373075eba5b6SRobert Mustacchi  **/
373175eba5b6SRobert Mustacchi static s32 e1000_flash_cycle_ich8lan(struct e1000_hw *hw, u32 timeout)
373275eba5b6SRobert Mustacchi {
373375eba5b6SRobert Mustacchi 	union ich8_hws_flash_ctrl hsflctl;
373475eba5b6SRobert Mustacchi 	union ich8_hws_flash_status hsfsts;
373575eba5b6SRobert Mustacchi 	u32 i = 0;
373675eba5b6SRobert Mustacchi 
373775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_flash_cycle_ich8lan");
373875eba5b6SRobert Mustacchi 
373975eba5b6SRobert Mustacchi 	/* Start a cycle by writing 1 in Flash Cycle Go in Hw Flash Control */
3740*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt)
3741*42cc51e0SRobert Mustacchi 		hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
3742*42cc51e0SRobert Mustacchi 	else
374375eba5b6SRobert Mustacchi 		hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
374475eba5b6SRobert Mustacchi 	hsflctl.hsf_ctrl.flcgo = 1;
3745c124a83eSRobert Mustacchi 
3746*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt)
3747*42cc51e0SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3748*42cc51e0SRobert Mustacchi 				      hsflctl.regval << 16);
3749*42cc51e0SRobert Mustacchi 	else
375075eba5b6SRobert Mustacchi 		E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
375175eba5b6SRobert Mustacchi 
375275eba5b6SRobert Mustacchi 	/* wait till FDONE bit is set to 1 */
375375eba5b6SRobert Mustacchi 	do {
375475eba5b6SRobert Mustacchi 		hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
375575eba5b6SRobert Mustacchi 		if (hsfsts.hsf_status.flcdone)
375675eba5b6SRobert Mustacchi 			break;
375775eba5b6SRobert Mustacchi 		usec_delay(1);
375875eba5b6SRobert Mustacchi 	} while (i++ < timeout);
375975eba5b6SRobert Mustacchi 
376075eba5b6SRobert Mustacchi 	if (hsfsts.hsf_status.flcdone && !hsfsts.hsf_status.flcerr)
376175eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
376275eba5b6SRobert Mustacchi 
376375eba5b6SRobert Mustacchi 	return -E1000_ERR_NVM;
376475eba5b6SRobert Mustacchi }
376575eba5b6SRobert Mustacchi 
376675eba5b6SRobert Mustacchi /**
3767*42cc51e0SRobert Mustacchi  *  e1000_read_flash_dword_ich8lan - Read dword from flash
3768*42cc51e0SRobert Mustacchi  *  @hw: pointer to the HW structure
3769*42cc51e0SRobert Mustacchi  *  @offset: offset to data location
3770*42cc51e0SRobert Mustacchi  *  @data: pointer to the location for storing the data
3771*42cc51e0SRobert Mustacchi  *
3772*42cc51e0SRobert Mustacchi  *  Reads the flash dword at offset into data.  Offset is converted
3773*42cc51e0SRobert Mustacchi  *  to bytes before read.
3774*42cc51e0SRobert Mustacchi  **/
3775*42cc51e0SRobert Mustacchi static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset,
3776*42cc51e0SRobert Mustacchi 					  u32 *data)
3777*42cc51e0SRobert Mustacchi {
3778*42cc51e0SRobert Mustacchi 	DEBUGFUNC("e1000_read_flash_dword_ich8lan");
3779*42cc51e0SRobert Mustacchi 
3780*42cc51e0SRobert Mustacchi 	if (!data)
3781*42cc51e0SRobert Mustacchi 		return -E1000_ERR_NVM;
3782*42cc51e0SRobert Mustacchi 
3783*42cc51e0SRobert Mustacchi 	/* Must convert word offset into bytes. */
3784*42cc51e0SRobert Mustacchi 	offset <<= 1;
3785*42cc51e0SRobert Mustacchi 
3786*42cc51e0SRobert Mustacchi 	return e1000_read_flash_data32_ich8lan(hw, offset, data);
3787*42cc51e0SRobert Mustacchi }
3788*42cc51e0SRobert Mustacchi 
3789*42cc51e0SRobert Mustacchi /**
379075eba5b6SRobert Mustacchi  *  e1000_read_flash_word_ich8lan - Read word from flash
379175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
379275eba5b6SRobert Mustacchi  *  @offset: offset to data location
379375eba5b6SRobert Mustacchi  *  @data: pointer to the location for storing the data
379475eba5b6SRobert Mustacchi  *
379575eba5b6SRobert Mustacchi  *  Reads the flash word at offset into data.  Offset is converted
379675eba5b6SRobert Mustacchi  *  to bytes before read.
379775eba5b6SRobert Mustacchi  **/
379875eba5b6SRobert Mustacchi static s32 e1000_read_flash_word_ich8lan(struct e1000_hw *hw, u32 offset,
379975eba5b6SRobert Mustacchi 					 u16 *data)
380075eba5b6SRobert Mustacchi {
380175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_flash_word_ich8lan");
380275eba5b6SRobert Mustacchi 
380375eba5b6SRobert Mustacchi 	if (!data)
380475eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
380575eba5b6SRobert Mustacchi 
380675eba5b6SRobert Mustacchi 	/* Must convert offset into bytes. */
380775eba5b6SRobert Mustacchi 	offset <<= 1;
380875eba5b6SRobert Mustacchi 
380975eba5b6SRobert Mustacchi 	return e1000_read_flash_data_ich8lan(hw, offset, 2, data);
381075eba5b6SRobert Mustacchi }
381175eba5b6SRobert Mustacchi 
381275eba5b6SRobert Mustacchi /**
381375eba5b6SRobert Mustacchi  *  e1000_read_flash_byte_ich8lan - Read byte from flash
381475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
381575eba5b6SRobert Mustacchi  *  @offset: The offset of the byte to read.
381675eba5b6SRobert Mustacchi  *  @data: Pointer to a byte to store the value read.
381775eba5b6SRobert Mustacchi  *
381875eba5b6SRobert Mustacchi  *  Reads a single byte from the NVM using the flash access registers.
381975eba5b6SRobert Mustacchi  **/
382075eba5b6SRobert Mustacchi static s32 e1000_read_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
382175eba5b6SRobert Mustacchi 					 u8 *data)
382275eba5b6SRobert Mustacchi {
382375eba5b6SRobert Mustacchi 	s32 ret_val;
382475eba5b6SRobert Mustacchi 	u16 word = 0;
382575eba5b6SRobert Mustacchi 
3826*42cc51e0SRobert Mustacchi 	/* In SPT, only 32 bits access is supported,
3827*42cc51e0SRobert Mustacchi 	 * so this function should not be called.
3828*42cc51e0SRobert Mustacchi 	 */
3829*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt)
3830*42cc51e0SRobert Mustacchi 		return -E1000_ERR_NVM;
3831*42cc51e0SRobert Mustacchi 	else
383275eba5b6SRobert Mustacchi 		ret_val = e1000_read_flash_data_ich8lan(hw, offset, 1, &word);
3833c124a83eSRobert Mustacchi 
383475eba5b6SRobert Mustacchi 	if (ret_val)
383575eba5b6SRobert Mustacchi 		return ret_val;
383675eba5b6SRobert Mustacchi 
383775eba5b6SRobert Mustacchi 	*data = (u8)word;
383875eba5b6SRobert Mustacchi 
383975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
384075eba5b6SRobert Mustacchi }
384175eba5b6SRobert Mustacchi 
384275eba5b6SRobert Mustacchi /**
384375eba5b6SRobert Mustacchi  *  e1000_read_flash_data_ich8lan - Read byte or word from NVM
384475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
384575eba5b6SRobert Mustacchi  *  @offset: The offset (in bytes) of the byte or word to read.
384675eba5b6SRobert Mustacchi  *  @size: Size of data to read, 1=byte 2=word
384775eba5b6SRobert Mustacchi  *  @data: Pointer to the word to store the value read.
384875eba5b6SRobert Mustacchi  *
384975eba5b6SRobert Mustacchi  *  Reads a byte or word from the NVM using the flash access registers.
385075eba5b6SRobert Mustacchi  **/
385175eba5b6SRobert Mustacchi static s32 e1000_read_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
385275eba5b6SRobert Mustacchi 					 u8 size, u16 *data)
385375eba5b6SRobert Mustacchi {
385475eba5b6SRobert Mustacchi 	union ich8_hws_flash_status hsfsts;
385575eba5b6SRobert Mustacchi 	union ich8_hws_flash_ctrl hsflctl;
385675eba5b6SRobert Mustacchi 	u32 flash_linear_addr;
385775eba5b6SRobert Mustacchi 	u32 flash_data = 0;
385875eba5b6SRobert Mustacchi 	s32 ret_val = -E1000_ERR_NVM;
385975eba5b6SRobert Mustacchi 	u8 count = 0;
386075eba5b6SRobert Mustacchi 
386175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_flash_data_ich8lan");
386275eba5b6SRobert Mustacchi 
386375eba5b6SRobert Mustacchi 	if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
386475eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
3865c124a83eSRobert Mustacchi 	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
3866c124a83eSRobert Mustacchi 			     hw->nvm.flash_base_addr);
386775eba5b6SRobert Mustacchi 
386875eba5b6SRobert Mustacchi 	do {
386975eba5b6SRobert Mustacchi 		usec_delay(1);
387075eba5b6SRobert Mustacchi 		/* Steps */
387175eba5b6SRobert Mustacchi 		ret_val = e1000_flash_cycle_init_ich8lan(hw);
387275eba5b6SRobert Mustacchi 		if (ret_val != E1000_SUCCESS)
387375eba5b6SRobert Mustacchi 			break;
387475eba5b6SRobert Mustacchi 		hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
3875c124a83eSRobert Mustacchi 
387675eba5b6SRobert Mustacchi 		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
387775eba5b6SRobert Mustacchi 		hsflctl.hsf_ctrl.fldbcount = size - 1;
387875eba5b6SRobert Mustacchi 		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
387975eba5b6SRobert Mustacchi 		E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL, hsflctl.regval);
388075eba5b6SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
388175eba5b6SRobert Mustacchi 
388275eba5b6SRobert Mustacchi 		ret_val = e1000_flash_cycle_ich8lan(hw,
388375eba5b6SRobert Mustacchi 						ICH_FLASH_READ_COMMAND_TIMEOUT);
388475eba5b6SRobert Mustacchi 
388575eba5b6SRobert Mustacchi 		/* Check if FCERR is set to 1, if set to 1, clear it
388675eba5b6SRobert Mustacchi 		 * and try the whole sequence a few more times, else
388775eba5b6SRobert Mustacchi 		 * read in (shift in) the Flash Data0, the order is
388875eba5b6SRobert Mustacchi 		 * least significant byte first msb to lsb
388975eba5b6SRobert Mustacchi 		 */
389075eba5b6SRobert Mustacchi 		if (ret_val == E1000_SUCCESS) {
389175eba5b6SRobert Mustacchi 			flash_data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0);
389275eba5b6SRobert Mustacchi 			if (size == 1)
389375eba5b6SRobert Mustacchi 				*data = (u8)(flash_data & 0x000000FF);
389475eba5b6SRobert Mustacchi 			else if (size == 2)
389575eba5b6SRobert Mustacchi 				*data = (u16)(flash_data & 0x0000FFFF);
389675eba5b6SRobert Mustacchi 			break;
389775eba5b6SRobert Mustacchi 		} else {
389875eba5b6SRobert Mustacchi 			/* If we've gotten here, then things are probably
389975eba5b6SRobert Mustacchi 			 * completely hosed, but if the error condition is
390075eba5b6SRobert Mustacchi 			 * detected, it won't hurt to give it another try...
390175eba5b6SRobert Mustacchi 			 * ICH_FLASH_CYCLE_REPEAT_COUNT times.
390275eba5b6SRobert Mustacchi 			 */
390375eba5b6SRobert Mustacchi 			hsfsts.regval = E1000_READ_FLASH_REG16(hw,
390475eba5b6SRobert Mustacchi 							      ICH_FLASH_HSFSTS);
390575eba5b6SRobert Mustacchi 			if (hsfsts.hsf_status.flcerr) {
390675eba5b6SRobert Mustacchi 				/* Repeat for some time before giving up. */
390775eba5b6SRobert Mustacchi 				continue;
390875eba5b6SRobert Mustacchi 			} else if (!hsfsts.hsf_status.flcdone) {
390975eba5b6SRobert Mustacchi 				DEBUGOUT("Timeout error - flash cycle did not complete.\n");
391075eba5b6SRobert Mustacchi 				break;
391175eba5b6SRobert Mustacchi 			}
391275eba5b6SRobert Mustacchi 		}
391375eba5b6SRobert Mustacchi 	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
391475eba5b6SRobert Mustacchi 
391575eba5b6SRobert Mustacchi 	return ret_val;
391675eba5b6SRobert Mustacchi }
391775eba5b6SRobert Mustacchi 
3918*42cc51e0SRobert Mustacchi /**
3919*42cc51e0SRobert Mustacchi  *  e1000_read_flash_data32_ich8lan - Read dword from NVM
3920*42cc51e0SRobert Mustacchi  *  @hw: pointer to the HW structure
3921*42cc51e0SRobert Mustacchi  *  @offset: The offset (in bytes) of the dword to read.
3922*42cc51e0SRobert Mustacchi  *  @data: Pointer to the dword to store the value read.
3923*42cc51e0SRobert Mustacchi  *
3924*42cc51e0SRobert Mustacchi  *  Reads a byte or word from the NVM using the flash access registers.
3925*42cc51e0SRobert Mustacchi  **/
3926*42cc51e0SRobert Mustacchi static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
3927*42cc51e0SRobert Mustacchi 					   u32 *data)
3928*42cc51e0SRobert Mustacchi {
3929*42cc51e0SRobert Mustacchi 	union ich8_hws_flash_status hsfsts;
3930*42cc51e0SRobert Mustacchi 	union ich8_hws_flash_ctrl hsflctl;
3931*42cc51e0SRobert Mustacchi 	u32 flash_linear_addr;
3932*42cc51e0SRobert Mustacchi 	s32 ret_val = -E1000_ERR_NVM;
3933*42cc51e0SRobert Mustacchi 	u8 count = 0;
3934*42cc51e0SRobert Mustacchi 
3935*42cc51e0SRobert Mustacchi 	DEBUGFUNC("e1000_read_flash_data_ich8lan");
3936*42cc51e0SRobert Mustacchi 
3937*42cc51e0SRobert Mustacchi 		if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
3938*42cc51e0SRobert Mustacchi 		    hw->mac.type != e1000_pch_spt)
3939*42cc51e0SRobert Mustacchi 			return -E1000_ERR_NVM;
3940*42cc51e0SRobert Mustacchi 	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
3941*42cc51e0SRobert Mustacchi 			     hw->nvm.flash_base_addr);
3942*42cc51e0SRobert Mustacchi 
3943*42cc51e0SRobert Mustacchi 	do {
3944*42cc51e0SRobert Mustacchi 		usec_delay(1);
3945*42cc51e0SRobert Mustacchi 		/* Steps */
3946*42cc51e0SRobert Mustacchi 		ret_val = e1000_flash_cycle_init_ich8lan(hw);
3947*42cc51e0SRobert Mustacchi 		if (ret_val != E1000_SUCCESS)
3948*42cc51e0SRobert Mustacchi 			break;
3949*42cc51e0SRobert Mustacchi 		/* In SPT, This register is in Lan memory space, not flash.
3950*42cc51e0SRobert Mustacchi 		 * Therefore, only 32 bit access is supported
3951*42cc51e0SRobert Mustacchi 		 */
3952*42cc51e0SRobert Mustacchi 		hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
3953*42cc51e0SRobert Mustacchi 
3954*42cc51e0SRobert Mustacchi 		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
3955*42cc51e0SRobert Mustacchi 		hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
3956*42cc51e0SRobert Mustacchi 		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
3957*42cc51e0SRobert Mustacchi 		/* In SPT, This register is in Lan memory space, not flash.
3958*42cc51e0SRobert Mustacchi 		 * Therefore, only 32 bit access is supported
3959*42cc51e0SRobert Mustacchi 		 */
3960*42cc51e0SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3961*42cc51e0SRobert Mustacchi 				      (u32)hsflctl.regval << 16);
3962*42cc51e0SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
3963*42cc51e0SRobert Mustacchi 
3964*42cc51e0SRobert Mustacchi 		ret_val = e1000_flash_cycle_ich8lan(hw,
3965*42cc51e0SRobert Mustacchi 						ICH_FLASH_READ_COMMAND_TIMEOUT);
3966*42cc51e0SRobert Mustacchi 
3967*42cc51e0SRobert Mustacchi 		/* Check if FCERR is set to 1, if set to 1, clear it
3968*42cc51e0SRobert Mustacchi 		 * and try the whole sequence a few more times, else
3969*42cc51e0SRobert Mustacchi 		 * read in (shift in) the Flash Data0, the order is
3970*42cc51e0SRobert Mustacchi 		 * least significant byte first msb to lsb
3971*42cc51e0SRobert Mustacchi 		 */
3972*42cc51e0SRobert Mustacchi 		if (ret_val == E1000_SUCCESS) {
3973*42cc51e0SRobert Mustacchi 			*data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0);
3974*42cc51e0SRobert Mustacchi 			break;
3975*42cc51e0SRobert Mustacchi 		} else {
3976*42cc51e0SRobert Mustacchi 			/* If we've gotten here, then things are probably
3977*42cc51e0SRobert Mustacchi 			 * completely hosed, but if the error condition is
3978*42cc51e0SRobert Mustacchi 			 * detected, it won't hurt to give it another try...
3979*42cc51e0SRobert Mustacchi 			 * ICH_FLASH_CYCLE_REPEAT_COUNT times.
3980*42cc51e0SRobert Mustacchi 			 */
3981*42cc51e0SRobert Mustacchi 			hsfsts.regval = E1000_READ_FLASH_REG16(hw,
3982*42cc51e0SRobert Mustacchi 							      ICH_FLASH_HSFSTS);
3983*42cc51e0SRobert Mustacchi 			if (hsfsts.hsf_status.flcerr) {
3984*42cc51e0SRobert Mustacchi 				/* Repeat for some time before giving up. */
3985*42cc51e0SRobert Mustacchi 				continue;
3986*42cc51e0SRobert Mustacchi 			} else if (!hsfsts.hsf_status.flcdone) {
3987*42cc51e0SRobert Mustacchi 				DEBUGOUT("Timeout error - flash cycle did not complete.\n");
3988*42cc51e0SRobert Mustacchi 				break;
3989*42cc51e0SRobert Mustacchi 			}
3990*42cc51e0SRobert Mustacchi 		}
3991*42cc51e0SRobert Mustacchi 	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
3992*42cc51e0SRobert Mustacchi 
3993*42cc51e0SRobert Mustacchi 	return ret_val;
3994*42cc51e0SRobert Mustacchi }
3995c124a83eSRobert Mustacchi 
399675eba5b6SRobert Mustacchi /**
399775eba5b6SRobert Mustacchi  *  e1000_write_nvm_ich8lan - Write word(s) to the NVM
399875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
399975eba5b6SRobert Mustacchi  *  @offset: The offset (in bytes) of the word(s) to write.
400075eba5b6SRobert Mustacchi  *  @words: Size of data to write in words
400175eba5b6SRobert Mustacchi  *  @data: Pointer to the word(s) to write at offset.
400275eba5b6SRobert Mustacchi  *
400375eba5b6SRobert Mustacchi  *  Writes a byte or word to the NVM using the flash access registers.
400475eba5b6SRobert Mustacchi  **/
400575eba5b6SRobert Mustacchi static s32 e1000_write_nvm_ich8lan(struct e1000_hw *hw, u16 offset, u16 words,
400675eba5b6SRobert Mustacchi 				   u16 *data)
400775eba5b6SRobert Mustacchi {
400875eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
400975eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
401075eba5b6SRobert Mustacchi 	u16 i;
401175eba5b6SRobert Mustacchi 
401275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_nvm_ich8lan");
401375eba5b6SRobert Mustacchi 
401475eba5b6SRobert Mustacchi 	if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
401575eba5b6SRobert Mustacchi 	    (words == 0)) {
401675eba5b6SRobert Mustacchi 		DEBUGOUT("nvm parameter(s) out of bounds\n");
401775eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
401875eba5b6SRobert Mustacchi 	}
401975eba5b6SRobert Mustacchi 
402075eba5b6SRobert Mustacchi 	nvm->ops.acquire(hw);
402175eba5b6SRobert Mustacchi 
402275eba5b6SRobert Mustacchi 	for (i = 0; i < words; i++) {
402375eba5b6SRobert Mustacchi 		dev_spec->shadow_ram[offset+i].modified = TRUE;
402475eba5b6SRobert Mustacchi 		dev_spec->shadow_ram[offset+i].value = data[i];
402575eba5b6SRobert Mustacchi 	}
402675eba5b6SRobert Mustacchi 
402775eba5b6SRobert Mustacchi 	nvm->ops.release(hw);
402875eba5b6SRobert Mustacchi 
402975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
403075eba5b6SRobert Mustacchi }
403175eba5b6SRobert Mustacchi 
403275eba5b6SRobert Mustacchi /**
4033*42cc51e0SRobert Mustacchi  *  e1000_update_nvm_checksum_spt - Update the checksum for NVM
4034*42cc51e0SRobert Mustacchi  *  @hw: pointer to the HW structure
4035*42cc51e0SRobert Mustacchi  *
4036*42cc51e0SRobert Mustacchi  *  The NVM checksum is updated by calling the generic update_nvm_checksum,
4037*42cc51e0SRobert Mustacchi  *  which writes the checksum to the shadow ram.  The changes in the shadow
4038*42cc51e0SRobert Mustacchi  *  ram are then committed to the EEPROM by processing each bank at a time
4039*42cc51e0SRobert Mustacchi  *  checking for the modified bit and writing only the pending changes.
4040*42cc51e0SRobert Mustacchi  *  After a successful commit, the shadow ram is cleared and is ready for
4041*42cc51e0SRobert Mustacchi  *  future writes.
4042*42cc51e0SRobert Mustacchi  **/
4043*42cc51e0SRobert Mustacchi static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw)
4044*42cc51e0SRobert Mustacchi {
4045*42cc51e0SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
4046*42cc51e0SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
4047*42cc51e0SRobert Mustacchi 	u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
4048*42cc51e0SRobert Mustacchi 	s32 ret_val;
4049*42cc51e0SRobert Mustacchi 	u32 dword = 0;
4050*42cc51e0SRobert Mustacchi 
4051*42cc51e0SRobert Mustacchi 	DEBUGFUNC("e1000_update_nvm_checksum_spt");
4052*42cc51e0SRobert Mustacchi 
4053*42cc51e0SRobert Mustacchi 	ret_val = e1000_update_nvm_checksum_generic(hw);
4054*42cc51e0SRobert Mustacchi 	if (ret_val)
4055*42cc51e0SRobert Mustacchi 		goto out;
4056*42cc51e0SRobert Mustacchi 
4057*42cc51e0SRobert Mustacchi 	if (nvm->type != e1000_nvm_flash_sw)
4058*42cc51e0SRobert Mustacchi 		goto out;
4059*42cc51e0SRobert Mustacchi 
4060*42cc51e0SRobert Mustacchi 	nvm->ops.acquire(hw);
4061*42cc51e0SRobert Mustacchi 
4062*42cc51e0SRobert Mustacchi 	/* We're writing to the opposite bank so if we're on bank 1,
4063*42cc51e0SRobert Mustacchi 	 * write to bank 0 etc.  We also need to erase the segment that
4064*42cc51e0SRobert Mustacchi 	 * is going to be written
4065*42cc51e0SRobert Mustacchi 	 */
4066*42cc51e0SRobert Mustacchi 	ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
4067*42cc51e0SRobert Mustacchi 	if (ret_val != E1000_SUCCESS) {
4068*42cc51e0SRobert Mustacchi 		DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
4069*42cc51e0SRobert Mustacchi 		bank = 0;
4070*42cc51e0SRobert Mustacchi 	}
4071*42cc51e0SRobert Mustacchi 
4072*42cc51e0SRobert Mustacchi 	if (bank == 0) {
4073*42cc51e0SRobert Mustacchi 		new_bank_offset = nvm->flash_bank_size;
4074*42cc51e0SRobert Mustacchi 		old_bank_offset = 0;
4075*42cc51e0SRobert Mustacchi 		ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
4076*42cc51e0SRobert Mustacchi 		if (ret_val)
4077*42cc51e0SRobert Mustacchi 			goto release;
4078*42cc51e0SRobert Mustacchi 	} else {
4079*42cc51e0SRobert Mustacchi 		old_bank_offset = nvm->flash_bank_size;
4080*42cc51e0SRobert Mustacchi 		new_bank_offset = 0;
4081*42cc51e0SRobert Mustacchi 		ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
4082*42cc51e0SRobert Mustacchi 		if (ret_val)
4083*42cc51e0SRobert Mustacchi 			goto release;
4084*42cc51e0SRobert Mustacchi 	}
4085*42cc51e0SRobert Mustacchi 	for (i = 0; i < E1000_SHADOW_RAM_WORDS; i += 2) {
4086*42cc51e0SRobert Mustacchi 		/* Determine whether to write the value stored
4087*42cc51e0SRobert Mustacchi 		 * in the other NVM bank or a modified value stored
4088*42cc51e0SRobert Mustacchi 		 * in the shadow RAM
4089*42cc51e0SRobert Mustacchi 		 */
4090*42cc51e0SRobert Mustacchi 		ret_val = e1000_read_flash_dword_ich8lan(hw,
4091*42cc51e0SRobert Mustacchi 							 i + old_bank_offset,
4092*42cc51e0SRobert Mustacchi 							 &dword);
4093*42cc51e0SRobert Mustacchi 
4094*42cc51e0SRobert Mustacchi 		if (dev_spec->shadow_ram[i].modified) {
4095*42cc51e0SRobert Mustacchi 			dword &= 0xffff0000;
4096*42cc51e0SRobert Mustacchi 			dword |= (dev_spec->shadow_ram[i].value & 0xffff);
4097*42cc51e0SRobert Mustacchi 		}
4098*42cc51e0SRobert Mustacchi 		if (dev_spec->shadow_ram[i + 1].modified) {
4099*42cc51e0SRobert Mustacchi 			dword &= 0x0000ffff;
4100*42cc51e0SRobert Mustacchi 			dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff)
4101*42cc51e0SRobert Mustacchi 				  << 16);
4102*42cc51e0SRobert Mustacchi 		}
4103*42cc51e0SRobert Mustacchi 		if (ret_val)
4104*42cc51e0SRobert Mustacchi 			break;
4105*42cc51e0SRobert Mustacchi 
4106*42cc51e0SRobert Mustacchi 		/* If the word is 0x13, then make sure the signature bits
4107*42cc51e0SRobert Mustacchi 		 * (15:14) are 11b until the commit has completed.
4108*42cc51e0SRobert Mustacchi 		 * This will allow us to write 10b which indicates the
4109*42cc51e0SRobert Mustacchi 		 * signature is valid.  We want to do this after the write
4110*42cc51e0SRobert Mustacchi 		 * has completed so that we don't mark the segment valid
4111*42cc51e0SRobert Mustacchi 		 * while the write is still in progress
4112*42cc51e0SRobert Mustacchi 		 */
4113*42cc51e0SRobert Mustacchi 		if (i == E1000_ICH_NVM_SIG_WORD - 1)
4114*42cc51e0SRobert Mustacchi 			dword |= E1000_ICH_NVM_SIG_MASK << 16;
4115*42cc51e0SRobert Mustacchi 
4116*42cc51e0SRobert Mustacchi 		/* Convert offset to bytes. */
4117*42cc51e0SRobert Mustacchi 		act_offset = (i + new_bank_offset) << 1;
4118*42cc51e0SRobert Mustacchi 
4119*42cc51e0SRobert Mustacchi 		usec_delay(100);
4120*42cc51e0SRobert Mustacchi 
4121*42cc51e0SRobert Mustacchi 		/* Write the data to the new bank. Offset in words*/
4122*42cc51e0SRobert Mustacchi 		act_offset = i + new_bank_offset;
4123*42cc51e0SRobert Mustacchi 		ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset,
4124*42cc51e0SRobert Mustacchi 								dword);
4125*42cc51e0SRobert Mustacchi 		if (ret_val)
4126*42cc51e0SRobert Mustacchi 			break;
4127*42cc51e0SRobert Mustacchi 	 }
4128*42cc51e0SRobert Mustacchi 
4129*42cc51e0SRobert Mustacchi 	/* Don't bother writing the segment valid bits if sector
4130*42cc51e0SRobert Mustacchi 	 * programming failed.
4131*42cc51e0SRobert Mustacchi 	 */
4132*42cc51e0SRobert Mustacchi 	if (ret_val) {
4133*42cc51e0SRobert Mustacchi 		DEBUGOUT("Flash commit failed.\n");
4134*42cc51e0SRobert Mustacchi 		goto release;
4135*42cc51e0SRobert Mustacchi 	}
4136*42cc51e0SRobert Mustacchi 
4137*42cc51e0SRobert Mustacchi 	/* Finally validate the new segment by setting bit 15:14
4138*42cc51e0SRobert Mustacchi 	 * to 10b in word 0x13 , this can be done without an
4139*42cc51e0SRobert Mustacchi 	 * erase as well since these bits are 11 to start with
4140*42cc51e0SRobert Mustacchi 	 * and we need to change bit 14 to 0b
4141*42cc51e0SRobert Mustacchi 	 */
4142*42cc51e0SRobert Mustacchi 	act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
4143*42cc51e0SRobert Mustacchi 
4144*42cc51e0SRobert Mustacchi 	/*offset in words but we read dword*/
4145*42cc51e0SRobert Mustacchi 	--act_offset;
4146*42cc51e0SRobert Mustacchi 	ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
4147*42cc51e0SRobert Mustacchi 
4148*42cc51e0SRobert Mustacchi 	if (ret_val)
4149*42cc51e0SRobert Mustacchi 		goto release;
4150*42cc51e0SRobert Mustacchi 
4151*42cc51e0SRobert Mustacchi 	dword &= 0xBFFFFFFF;
4152*42cc51e0SRobert Mustacchi 	ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
4153*42cc51e0SRobert Mustacchi 
4154*42cc51e0SRobert Mustacchi 	if (ret_val)
4155*42cc51e0SRobert Mustacchi 		goto release;
4156*42cc51e0SRobert Mustacchi 
4157*42cc51e0SRobert Mustacchi 	/* And invalidate the previously valid segment by setting
4158*42cc51e0SRobert Mustacchi 	 * its signature word (0x13) high_byte to 0b. This can be
4159*42cc51e0SRobert Mustacchi 	 * done without an erase because flash erase sets all bits
4160*42cc51e0SRobert Mustacchi 	 * to 1's. We can write 1's to 0's without an erase
4161*42cc51e0SRobert Mustacchi 	 */
4162*42cc51e0SRobert Mustacchi 	act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
4163*42cc51e0SRobert Mustacchi 
4164*42cc51e0SRobert Mustacchi 	/* offset in words but we read dword*/
4165*42cc51e0SRobert Mustacchi 	act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1;
4166*42cc51e0SRobert Mustacchi 	ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
4167*42cc51e0SRobert Mustacchi 
4168*42cc51e0SRobert Mustacchi 	if (ret_val)
4169*42cc51e0SRobert Mustacchi 		goto release;
4170*42cc51e0SRobert Mustacchi 
4171*42cc51e0SRobert Mustacchi 	dword &= 0x00FFFFFF;
4172*42cc51e0SRobert Mustacchi 	ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
4173*42cc51e0SRobert Mustacchi 
4174*42cc51e0SRobert Mustacchi 	if (ret_val)
4175*42cc51e0SRobert Mustacchi 		goto release;
4176*42cc51e0SRobert Mustacchi 
4177*42cc51e0SRobert Mustacchi 	/* Great!  Everything worked, we can now clear the cached entries. */
4178*42cc51e0SRobert Mustacchi 	for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
4179*42cc51e0SRobert Mustacchi 		dev_spec->shadow_ram[i].modified = FALSE;
4180*42cc51e0SRobert Mustacchi 		dev_spec->shadow_ram[i].value = 0xFFFF;
4181*42cc51e0SRobert Mustacchi 	}
4182*42cc51e0SRobert Mustacchi 
4183*42cc51e0SRobert Mustacchi release:
4184*42cc51e0SRobert Mustacchi 	nvm->ops.release(hw);
4185*42cc51e0SRobert Mustacchi 
4186*42cc51e0SRobert Mustacchi 	/* Reload the EEPROM, or else modifications will not appear
4187*42cc51e0SRobert Mustacchi 	 * until after the next adapter reset.
4188*42cc51e0SRobert Mustacchi 	 */
4189*42cc51e0SRobert Mustacchi 	if (!ret_val) {
4190*42cc51e0SRobert Mustacchi 		nvm->ops.reload(hw);
4191*42cc51e0SRobert Mustacchi 		msec_delay(10);
4192*42cc51e0SRobert Mustacchi 	}
4193*42cc51e0SRobert Mustacchi 
4194*42cc51e0SRobert Mustacchi out:
4195*42cc51e0SRobert Mustacchi 	if (ret_val)
4196*42cc51e0SRobert Mustacchi 		DEBUGOUT1("NVM update error: %d\n", ret_val);
4197*42cc51e0SRobert Mustacchi 
4198*42cc51e0SRobert Mustacchi 	return ret_val;
4199*42cc51e0SRobert Mustacchi }
4200*42cc51e0SRobert Mustacchi 
4201*42cc51e0SRobert Mustacchi /**
420275eba5b6SRobert Mustacchi  *  e1000_update_nvm_checksum_ich8lan - Update the checksum for NVM
420375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
420475eba5b6SRobert Mustacchi  *
420575eba5b6SRobert Mustacchi  *  The NVM checksum is updated by calling the generic update_nvm_checksum,
420675eba5b6SRobert Mustacchi  *  which writes the checksum to the shadow ram.  The changes in the shadow
420775eba5b6SRobert Mustacchi  *  ram are then committed to the EEPROM by processing each bank at a time
420875eba5b6SRobert Mustacchi  *  checking for the modified bit and writing only the pending changes.
420975eba5b6SRobert Mustacchi  *  After a successful commit, the shadow ram is cleared and is ready for
421075eba5b6SRobert Mustacchi  *  future writes.
421175eba5b6SRobert Mustacchi  **/
421275eba5b6SRobert Mustacchi static s32 e1000_update_nvm_checksum_ich8lan(struct e1000_hw *hw)
421375eba5b6SRobert Mustacchi {
421475eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
421575eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
421675eba5b6SRobert Mustacchi 	u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
421775eba5b6SRobert Mustacchi 	s32 ret_val;
4218c124a83eSRobert Mustacchi 	u16 data = 0;
421975eba5b6SRobert Mustacchi 
422075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_update_nvm_checksum_ich8lan");
422175eba5b6SRobert Mustacchi 
422275eba5b6SRobert Mustacchi 	ret_val = e1000_update_nvm_checksum_generic(hw);
422375eba5b6SRobert Mustacchi 	if (ret_val)
422475eba5b6SRobert Mustacchi 		goto out;
422575eba5b6SRobert Mustacchi 
422675eba5b6SRobert Mustacchi 	if (nvm->type != e1000_nvm_flash_sw)
422775eba5b6SRobert Mustacchi 		goto out;
422875eba5b6SRobert Mustacchi 
422975eba5b6SRobert Mustacchi 	nvm->ops.acquire(hw);
423075eba5b6SRobert Mustacchi 
423175eba5b6SRobert Mustacchi 	/* We're writing to the opposite bank so if we're on bank 1,
423275eba5b6SRobert Mustacchi 	 * write to bank 0 etc.  We also need to erase the segment that
423375eba5b6SRobert Mustacchi 	 * is going to be written
423475eba5b6SRobert Mustacchi 	 */
423575eba5b6SRobert Mustacchi 	ret_val =  e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
423675eba5b6SRobert Mustacchi 	if (ret_val != E1000_SUCCESS) {
423775eba5b6SRobert Mustacchi 		DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
423875eba5b6SRobert Mustacchi 		bank = 0;
423975eba5b6SRobert Mustacchi 	}
424075eba5b6SRobert Mustacchi 
424175eba5b6SRobert Mustacchi 	if (bank == 0) {
424275eba5b6SRobert Mustacchi 		new_bank_offset = nvm->flash_bank_size;
424375eba5b6SRobert Mustacchi 		old_bank_offset = 0;
424475eba5b6SRobert Mustacchi 		ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
424575eba5b6SRobert Mustacchi 		if (ret_val)
424675eba5b6SRobert Mustacchi 			goto release;
424775eba5b6SRobert Mustacchi 	} else {
424875eba5b6SRobert Mustacchi 		old_bank_offset = nvm->flash_bank_size;
424975eba5b6SRobert Mustacchi 		new_bank_offset = 0;
425075eba5b6SRobert Mustacchi 		ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
425175eba5b6SRobert Mustacchi 		if (ret_val)
425275eba5b6SRobert Mustacchi 			goto release;
425375eba5b6SRobert Mustacchi 	}
425475eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
425575eba5b6SRobert Mustacchi 		if (dev_spec->shadow_ram[i].modified) {
425675eba5b6SRobert Mustacchi 			data = dev_spec->shadow_ram[i].value;
425775eba5b6SRobert Mustacchi 		} else {
425875eba5b6SRobert Mustacchi 			ret_val = e1000_read_flash_word_ich8lan(hw, i +
425975eba5b6SRobert Mustacchi 								old_bank_offset,
426075eba5b6SRobert Mustacchi 								&data);
426175eba5b6SRobert Mustacchi 			if (ret_val)
426275eba5b6SRobert Mustacchi 				break;
426375eba5b6SRobert Mustacchi 		}
426475eba5b6SRobert Mustacchi 		/* If the word is 0x13, then make sure the signature bits
426575eba5b6SRobert Mustacchi 		 * (15:14) are 11b until the commit has completed.
426675eba5b6SRobert Mustacchi 		 * This will allow us to write 10b which indicates the
426775eba5b6SRobert Mustacchi 		 * signature is valid.  We want to do this after the write
426875eba5b6SRobert Mustacchi 		 * has completed so that we don't mark the segment valid
426975eba5b6SRobert Mustacchi 		 * while the write is still in progress
427075eba5b6SRobert Mustacchi 		 */
427175eba5b6SRobert Mustacchi 		if (i == E1000_ICH_NVM_SIG_WORD)
427275eba5b6SRobert Mustacchi 			data |= E1000_ICH_NVM_SIG_MASK;
427375eba5b6SRobert Mustacchi 
427475eba5b6SRobert Mustacchi 		/* Convert offset to bytes. */
427575eba5b6SRobert Mustacchi 		act_offset = (i + new_bank_offset) << 1;
427675eba5b6SRobert Mustacchi 
427775eba5b6SRobert Mustacchi 		usec_delay(100);
4278c124a83eSRobert Mustacchi 
427975eba5b6SRobert Mustacchi 		/* Write the bytes to the new bank. */
428075eba5b6SRobert Mustacchi 		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
428175eba5b6SRobert Mustacchi 							       act_offset,
428275eba5b6SRobert Mustacchi 							       (u8)data);
428375eba5b6SRobert Mustacchi 		if (ret_val)
428475eba5b6SRobert Mustacchi 			break;
428575eba5b6SRobert Mustacchi 
428675eba5b6SRobert Mustacchi 		usec_delay(100);
428775eba5b6SRobert Mustacchi 		ret_val = e1000_retry_write_flash_byte_ich8lan(hw,
428875eba5b6SRobert Mustacchi 							  act_offset + 1,
428975eba5b6SRobert Mustacchi 							  (u8)(data >> 8));
429075eba5b6SRobert Mustacchi 		if (ret_val)
429175eba5b6SRobert Mustacchi 			break;
429275eba5b6SRobert Mustacchi 	 }
429375eba5b6SRobert Mustacchi 
429475eba5b6SRobert Mustacchi 	/* Don't bother writing the segment valid bits if sector
429575eba5b6SRobert Mustacchi 	 * programming failed.
429675eba5b6SRobert Mustacchi 	 */
429775eba5b6SRobert Mustacchi 	if (ret_val) {
429875eba5b6SRobert Mustacchi 		DEBUGOUT("Flash commit failed.\n");
429975eba5b6SRobert Mustacchi 		goto release;
430075eba5b6SRobert Mustacchi 	}
430175eba5b6SRobert Mustacchi 
430275eba5b6SRobert Mustacchi 	/* Finally validate the new segment by setting bit 15:14
430375eba5b6SRobert Mustacchi 	 * to 10b in word 0x13 , this can be done without an
430475eba5b6SRobert Mustacchi 	 * erase as well since these bits are 11 to start with
430575eba5b6SRobert Mustacchi 	 * and we need to change bit 14 to 0b
430675eba5b6SRobert Mustacchi 	 */
430775eba5b6SRobert Mustacchi 	act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
430875eba5b6SRobert Mustacchi 	ret_val = e1000_read_flash_word_ich8lan(hw, act_offset, &data);
430975eba5b6SRobert Mustacchi 	if (ret_val)
431075eba5b6SRobert Mustacchi 		goto release;
431175eba5b6SRobert Mustacchi 
431275eba5b6SRobert Mustacchi 	data &= 0xBFFF;
4313c124a83eSRobert Mustacchi 	ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset * 2 + 1,
431475eba5b6SRobert Mustacchi 						       (u8)(data >> 8));
431575eba5b6SRobert Mustacchi 	if (ret_val)
431675eba5b6SRobert Mustacchi 		goto release;
431775eba5b6SRobert Mustacchi 
431875eba5b6SRobert Mustacchi 	/* And invalidate the previously valid segment by setting
431975eba5b6SRobert Mustacchi 	 * its signature word (0x13) high_byte to 0b. This can be
432075eba5b6SRobert Mustacchi 	 * done without an erase because flash erase sets all bits
432175eba5b6SRobert Mustacchi 	 * to 1's. We can write 1's to 0's without an erase
432275eba5b6SRobert Mustacchi 	 */
432375eba5b6SRobert Mustacchi 	act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
4324c124a83eSRobert Mustacchi 
432575eba5b6SRobert Mustacchi 	ret_val = e1000_retry_write_flash_byte_ich8lan(hw, act_offset, 0);
4326c124a83eSRobert Mustacchi 
432775eba5b6SRobert Mustacchi 	if (ret_val)
432875eba5b6SRobert Mustacchi 		goto release;
432975eba5b6SRobert Mustacchi 
433075eba5b6SRobert Mustacchi 	/* Great!  Everything worked, we can now clear the cached entries. */
433175eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
433275eba5b6SRobert Mustacchi 		dev_spec->shadow_ram[i].modified = FALSE;
433375eba5b6SRobert Mustacchi 		dev_spec->shadow_ram[i].value = 0xFFFF;
433475eba5b6SRobert Mustacchi 	}
433575eba5b6SRobert Mustacchi 
433675eba5b6SRobert Mustacchi release:
433775eba5b6SRobert Mustacchi 	nvm->ops.release(hw);
433875eba5b6SRobert Mustacchi 
433975eba5b6SRobert Mustacchi 	/* Reload the EEPROM, or else modifications will not appear
434075eba5b6SRobert Mustacchi 	 * until after the next adapter reset.
434175eba5b6SRobert Mustacchi 	 */
434275eba5b6SRobert Mustacchi 	if (!ret_val) {
434375eba5b6SRobert Mustacchi 		nvm->ops.reload(hw);
434475eba5b6SRobert Mustacchi 		msec_delay(10);
434575eba5b6SRobert Mustacchi 	}
434675eba5b6SRobert Mustacchi 
434775eba5b6SRobert Mustacchi out:
434875eba5b6SRobert Mustacchi 	if (ret_val)
434975eba5b6SRobert Mustacchi 		DEBUGOUT1("NVM update error: %d\n", ret_val);
435075eba5b6SRobert Mustacchi 
435175eba5b6SRobert Mustacchi 	return ret_val;
435275eba5b6SRobert Mustacchi }
435375eba5b6SRobert Mustacchi 
435475eba5b6SRobert Mustacchi /**
435575eba5b6SRobert Mustacchi  *  e1000_validate_nvm_checksum_ich8lan - Validate EEPROM checksum
435675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
435775eba5b6SRobert Mustacchi  *
435875eba5b6SRobert Mustacchi  *  Check to see if checksum needs to be fixed by reading bit 6 in word 0x19.
435975eba5b6SRobert Mustacchi  *  If the bit is 0, that the EEPROM had been modified, but the checksum was not
436075eba5b6SRobert Mustacchi  *  calculated, in which case we need to calculate the checksum and set bit 6.
436175eba5b6SRobert Mustacchi  **/
436275eba5b6SRobert Mustacchi static s32 e1000_validate_nvm_checksum_ich8lan(struct e1000_hw *hw)
436375eba5b6SRobert Mustacchi {
436475eba5b6SRobert Mustacchi 	s32 ret_val;
436575eba5b6SRobert Mustacchi 	u16 data;
436675eba5b6SRobert Mustacchi 	u16 word;
436775eba5b6SRobert Mustacchi 	u16 valid_csum_mask;
436875eba5b6SRobert Mustacchi 
436975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_validate_nvm_checksum_ich8lan");
437075eba5b6SRobert Mustacchi 
437175eba5b6SRobert Mustacchi 	/* Read NVM and check Invalid Image CSUM bit.  If this bit is 0,
437275eba5b6SRobert Mustacchi 	 * the checksum needs to be fixed.  This bit is an indication that
437375eba5b6SRobert Mustacchi 	 * the NVM was prepared by OEM software and did not calculate
437475eba5b6SRobert Mustacchi 	 * the checksum...a likely scenario.
437575eba5b6SRobert Mustacchi 	 */
437675eba5b6SRobert Mustacchi 	switch (hw->mac.type) {
437775eba5b6SRobert Mustacchi 	case e1000_pch_lpt:
4378*42cc51e0SRobert Mustacchi 	case e1000_pch_spt:
437975eba5b6SRobert Mustacchi 		word = NVM_COMPAT;
438075eba5b6SRobert Mustacchi 		valid_csum_mask = NVM_COMPAT_VALID_CSUM;
438175eba5b6SRobert Mustacchi 		break;
438275eba5b6SRobert Mustacchi 	default:
438375eba5b6SRobert Mustacchi 		word = NVM_FUTURE_INIT_WORD1;
438475eba5b6SRobert Mustacchi 		valid_csum_mask = NVM_FUTURE_INIT_WORD1_VALID_CSUM;
438575eba5b6SRobert Mustacchi 		break;
438675eba5b6SRobert Mustacchi 	}
438775eba5b6SRobert Mustacchi 
438875eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, word, 1, &data);
438975eba5b6SRobert Mustacchi 	if (ret_val)
439075eba5b6SRobert Mustacchi 		return ret_val;
439175eba5b6SRobert Mustacchi 
439275eba5b6SRobert Mustacchi 	if (!(data & valid_csum_mask)) {
439375eba5b6SRobert Mustacchi 		data |= valid_csum_mask;
439475eba5b6SRobert Mustacchi 		ret_val = hw->nvm.ops.write(hw, word, 1, &data);
439575eba5b6SRobert Mustacchi 		if (ret_val)
439675eba5b6SRobert Mustacchi 			return ret_val;
439775eba5b6SRobert Mustacchi 		ret_val = hw->nvm.ops.update(hw);
439875eba5b6SRobert Mustacchi 		if (ret_val)
439975eba5b6SRobert Mustacchi 			return ret_val;
440075eba5b6SRobert Mustacchi 	}
440175eba5b6SRobert Mustacchi 
440275eba5b6SRobert Mustacchi 	return e1000_validate_nvm_checksum_generic(hw);
440375eba5b6SRobert Mustacchi }
440475eba5b6SRobert Mustacchi 
440575eba5b6SRobert Mustacchi /**
440675eba5b6SRobert Mustacchi  *  e1000_write_flash_data_ich8lan - Writes bytes to the NVM
440775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
440875eba5b6SRobert Mustacchi  *  @offset: The offset (in bytes) of the byte/word to read.
440975eba5b6SRobert Mustacchi  *  @size: Size of data to read, 1=byte 2=word
441075eba5b6SRobert Mustacchi  *  @data: The byte(s) to write to the NVM.
441175eba5b6SRobert Mustacchi  *
441275eba5b6SRobert Mustacchi  *  Writes one/two bytes to the NVM using the flash access registers.
441375eba5b6SRobert Mustacchi  **/
441475eba5b6SRobert Mustacchi static s32 e1000_write_flash_data_ich8lan(struct e1000_hw *hw, u32 offset,
441575eba5b6SRobert Mustacchi 					  u8 size, u16 data)
441675eba5b6SRobert Mustacchi {
441775eba5b6SRobert Mustacchi 	union ich8_hws_flash_status hsfsts;
441875eba5b6SRobert Mustacchi 	union ich8_hws_flash_ctrl hsflctl;
441975eba5b6SRobert Mustacchi 	u32 flash_linear_addr;
442075eba5b6SRobert Mustacchi 	u32 flash_data = 0;
442175eba5b6SRobert Mustacchi 	s32 ret_val;
442275eba5b6SRobert Mustacchi 	u8 count = 0;
442375eba5b6SRobert Mustacchi 
442475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_ich8_data");
442575eba5b6SRobert Mustacchi 
4426*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt) {
4427*42cc51e0SRobert Mustacchi 		if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
4428*42cc51e0SRobert Mustacchi 			return -E1000_ERR_NVM;
4429*42cc51e0SRobert Mustacchi 	} else {
4430c124a83eSRobert Mustacchi 		if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
443175eba5b6SRobert Mustacchi 			return -E1000_ERR_NVM;
4432*42cc51e0SRobert Mustacchi 	}
443375eba5b6SRobert Mustacchi 
4434c124a83eSRobert Mustacchi 	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
4435c124a83eSRobert Mustacchi 			     hw->nvm.flash_base_addr);
443675eba5b6SRobert Mustacchi 
443775eba5b6SRobert Mustacchi 	do {
443875eba5b6SRobert Mustacchi 		usec_delay(1);
443975eba5b6SRobert Mustacchi 		/* Steps */
444075eba5b6SRobert Mustacchi 		ret_val = e1000_flash_cycle_init_ich8lan(hw);
444175eba5b6SRobert Mustacchi 		if (ret_val != E1000_SUCCESS)
444275eba5b6SRobert Mustacchi 			break;
4443*42cc51e0SRobert Mustacchi 		/* In SPT, This register is in Lan memory space, not
4444*42cc51e0SRobert Mustacchi 		 * flash.  Therefore, only 32 bit access is supported
4445*42cc51e0SRobert Mustacchi 		 */
4446*42cc51e0SRobert Mustacchi 		if (hw->mac.type == e1000_pch_spt)
4447*42cc51e0SRobert Mustacchi 			hsflctl.regval =
4448*42cc51e0SRobert Mustacchi 			    E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
4449*42cc51e0SRobert Mustacchi 		else
4450*42cc51e0SRobert Mustacchi 			hsflctl.regval =
4451*42cc51e0SRobert Mustacchi 			    E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
4452c124a83eSRobert Mustacchi 
445375eba5b6SRobert Mustacchi 		/* 0b/1b corresponds to 1 or 2 byte size, respectively. */
445475eba5b6SRobert Mustacchi 		hsflctl.hsf_ctrl.fldbcount = size - 1;
445575eba5b6SRobert Mustacchi 		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
4456*42cc51e0SRobert Mustacchi 		/* In SPT, This register is in Lan memory space,
4457*42cc51e0SRobert Mustacchi 		 * not flash.  Therefore, only 32 bit access is
4458*42cc51e0SRobert Mustacchi 		 * supported
4459*42cc51e0SRobert Mustacchi 		 */
4460*42cc51e0SRobert Mustacchi 		if (hw->mac.type == e1000_pch_spt)
4461*42cc51e0SRobert Mustacchi 			E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
4462*42cc51e0SRobert Mustacchi 					      hsflctl.regval << 16);
4463*42cc51e0SRobert Mustacchi 		else
4464*42cc51e0SRobert Mustacchi 			E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
4465*42cc51e0SRobert Mustacchi 						hsflctl.regval);
446675eba5b6SRobert Mustacchi 
446775eba5b6SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
446875eba5b6SRobert Mustacchi 
446975eba5b6SRobert Mustacchi 		if (size == 1)
447075eba5b6SRobert Mustacchi 			flash_data = (u32)data & 0x00FF;
447175eba5b6SRobert Mustacchi 		else
447275eba5b6SRobert Mustacchi 			flash_data = (u32)data;
447375eba5b6SRobert Mustacchi 
447475eba5b6SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, flash_data);
447575eba5b6SRobert Mustacchi 
447675eba5b6SRobert Mustacchi 		/* check if FCERR is set to 1 , if set to 1, clear it
447775eba5b6SRobert Mustacchi 		 * and try the whole sequence a few more times else done
447875eba5b6SRobert Mustacchi 		 */
4479c124a83eSRobert Mustacchi 		ret_val =
4480c124a83eSRobert Mustacchi 		    e1000_flash_cycle_ich8lan(hw,
448175eba5b6SRobert Mustacchi 					      ICH_FLASH_WRITE_COMMAND_TIMEOUT);
448275eba5b6SRobert Mustacchi 		if (ret_val == E1000_SUCCESS)
448375eba5b6SRobert Mustacchi 			break;
448475eba5b6SRobert Mustacchi 
448575eba5b6SRobert Mustacchi 		/* If we're here, then things are most likely
448675eba5b6SRobert Mustacchi 		 * completely hosed, but if the error condition
448775eba5b6SRobert Mustacchi 		 * is detected, it won't hurt to give it another
448875eba5b6SRobert Mustacchi 		 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
448975eba5b6SRobert Mustacchi 		 */
449075eba5b6SRobert Mustacchi 		hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
449175eba5b6SRobert Mustacchi 		if (hsfsts.hsf_status.flcerr)
449275eba5b6SRobert Mustacchi 			/* Repeat for some time before giving up. */
449375eba5b6SRobert Mustacchi 			continue;
449475eba5b6SRobert Mustacchi 		if (!hsfsts.hsf_status.flcdone) {
449575eba5b6SRobert Mustacchi 			DEBUGOUT("Timeout error - flash cycle did not complete.\n");
449675eba5b6SRobert Mustacchi 			break;
449775eba5b6SRobert Mustacchi 		}
449875eba5b6SRobert Mustacchi 	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
449975eba5b6SRobert Mustacchi 
450075eba5b6SRobert Mustacchi 	return ret_val;
450175eba5b6SRobert Mustacchi }
450275eba5b6SRobert Mustacchi 
4503*42cc51e0SRobert Mustacchi /**
4504*42cc51e0SRobert Mustacchi *  e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM
4505*42cc51e0SRobert Mustacchi *  @hw: pointer to the HW structure
4506*42cc51e0SRobert Mustacchi *  @offset: The offset (in bytes) of the dwords to read.
4507*42cc51e0SRobert Mustacchi *  @data: The 4 bytes to write to the NVM.
4508*42cc51e0SRobert Mustacchi *
4509*42cc51e0SRobert Mustacchi *  Writes one/two/four bytes to the NVM using the flash access registers.
4510*42cc51e0SRobert Mustacchi **/
4511*42cc51e0SRobert Mustacchi static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
4512*42cc51e0SRobert Mustacchi 					    u32 data)
4513*42cc51e0SRobert Mustacchi {
4514*42cc51e0SRobert Mustacchi 	union ich8_hws_flash_status hsfsts;
4515*42cc51e0SRobert Mustacchi 	union ich8_hws_flash_ctrl hsflctl;
4516*42cc51e0SRobert Mustacchi 	u32 flash_linear_addr;
4517*42cc51e0SRobert Mustacchi 	s32 ret_val;
4518*42cc51e0SRobert Mustacchi 	u8 count = 0;
4519*42cc51e0SRobert Mustacchi 
4520*42cc51e0SRobert Mustacchi 	DEBUGFUNC("e1000_write_flash_data32_ich8lan");
4521*42cc51e0SRobert Mustacchi 
4522*42cc51e0SRobert Mustacchi 	if (hw->mac.type == e1000_pch_spt) {
4523*42cc51e0SRobert Mustacchi 		if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
4524*42cc51e0SRobert Mustacchi 			return -E1000_ERR_NVM;
4525*42cc51e0SRobert Mustacchi 	}
4526*42cc51e0SRobert Mustacchi 	flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
4527*42cc51e0SRobert Mustacchi 			     hw->nvm.flash_base_addr);
4528*42cc51e0SRobert Mustacchi 	do {
4529*42cc51e0SRobert Mustacchi 		usec_delay(1);
4530*42cc51e0SRobert Mustacchi 		/* Steps */
4531*42cc51e0SRobert Mustacchi 		ret_val = e1000_flash_cycle_init_ich8lan(hw);
4532*42cc51e0SRobert Mustacchi 		if (ret_val != E1000_SUCCESS)
4533*42cc51e0SRobert Mustacchi 			break;
4534*42cc51e0SRobert Mustacchi 
4535*42cc51e0SRobert Mustacchi 		/* In SPT, This register is in Lan memory space, not
4536*42cc51e0SRobert Mustacchi 		 * flash.  Therefore, only 32 bit access is supported
4537*42cc51e0SRobert Mustacchi 		 */
4538*42cc51e0SRobert Mustacchi 		if (hw->mac.type == e1000_pch_spt)
4539*42cc51e0SRobert Mustacchi 			hsflctl.regval = E1000_READ_FLASH_REG(hw,
4540*42cc51e0SRobert Mustacchi 							      ICH_FLASH_HSFSTS)
4541*42cc51e0SRobert Mustacchi 					 >> 16;
4542*42cc51e0SRobert Mustacchi 		else
4543*42cc51e0SRobert Mustacchi 			hsflctl.regval = E1000_READ_FLASH_REG16(hw,
4544*42cc51e0SRobert Mustacchi 							      ICH_FLASH_HSFCTL);
4545*42cc51e0SRobert Mustacchi 
4546*42cc51e0SRobert Mustacchi 		hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
4547*42cc51e0SRobert Mustacchi 		hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
4548*42cc51e0SRobert Mustacchi 
4549*42cc51e0SRobert Mustacchi 		/* In SPT, This register is in Lan memory space,
4550*42cc51e0SRobert Mustacchi 		 * not flash.  Therefore, only 32 bit access is
4551*42cc51e0SRobert Mustacchi 		 * supported
4552*42cc51e0SRobert Mustacchi 		 */
4553*42cc51e0SRobert Mustacchi 		if (hw->mac.type == e1000_pch_spt)
4554*42cc51e0SRobert Mustacchi 			E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
4555*42cc51e0SRobert Mustacchi 					      hsflctl.regval << 16);
4556*42cc51e0SRobert Mustacchi 		else
4557*42cc51e0SRobert Mustacchi 			E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
4558*42cc51e0SRobert Mustacchi 						hsflctl.regval);
4559*42cc51e0SRobert Mustacchi 
4560*42cc51e0SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
4561*42cc51e0SRobert Mustacchi 
4562*42cc51e0SRobert Mustacchi 		E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, data);
4563*42cc51e0SRobert Mustacchi 
4564*42cc51e0SRobert Mustacchi 		/* check if FCERR is set to 1 , if set to 1, clear it
4565*42cc51e0SRobert Mustacchi 		 * and try the whole sequence a few more times else done
4566*42cc51e0SRobert Mustacchi 		 */
4567*42cc51e0SRobert Mustacchi 		ret_val = e1000_flash_cycle_ich8lan(hw,
4568*42cc51e0SRobert Mustacchi 					       ICH_FLASH_WRITE_COMMAND_TIMEOUT);
4569*42cc51e0SRobert Mustacchi 
4570*42cc51e0SRobert Mustacchi 		if (ret_val == E1000_SUCCESS)
4571*42cc51e0SRobert Mustacchi 			break;
4572*42cc51e0SRobert Mustacchi 
4573*42cc51e0SRobert Mustacchi 		/* If we're here, then things are most likely
4574*42cc51e0SRobert Mustacchi 		 * completely hosed, but if the error condition
4575*42cc51e0SRobert Mustacchi 		 * is detected, it won't hurt to give it another
4576*42cc51e0SRobert Mustacchi 		 * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
4577*42cc51e0SRobert Mustacchi 		 */
4578*42cc51e0SRobert Mustacchi 		hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
4579*42cc51e0SRobert Mustacchi 
4580*42cc51e0SRobert Mustacchi 		if (hsfsts.hsf_status.flcerr)
4581*42cc51e0SRobert Mustacchi 			/* Repeat for some time before giving up. */
4582*42cc51e0SRobert Mustacchi 			continue;
4583*42cc51e0SRobert Mustacchi 		if (!hsfsts.hsf_status.flcdone) {
4584*42cc51e0SRobert Mustacchi 			DEBUGOUT("Timeout error - flash cycle did not complete.\n");
4585*42cc51e0SRobert Mustacchi 			break;
4586*42cc51e0SRobert Mustacchi 		}
4587*42cc51e0SRobert Mustacchi 	} while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
4588*42cc51e0SRobert Mustacchi 
4589*42cc51e0SRobert Mustacchi 	return ret_val;
4590*42cc51e0SRobert Mustacchi }
4591c124a83eSRobert Mustacchi 
459275eba5b6SRobert Mustacchi /**
459375eba5b6SRobert Mustacchi  *  e1000_write_flash_byte_ich8lan - Write a single byte to NVM
459475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
459575eba5b6SRobert Mustacchi  *  @offset: The index of the byte to read.
459675eba5b6SRobert Mustacchi  *  @data: The byte to write to the NVM.
459775eba5b6SRobert Mustacchi  *
459875eba5b6SRobert Mustacchi  *  Writes a single byte to the NVM using the flash access registers.
459975eba5b6SRobert Mustacchi  **/
460075eba5b6SRobert Mustacchi static s32 e1000_write_flash_byte_ich8lan(struct e1000_hw *hw, u32 offset,
460175eba5b6SRobert Mustacchi 					  u8 data)
460275eba5b6SRobert Mustacchi {
460375eba5b6SRobert Mustacchi 	u16 word = (u16)data;
460475eba5b6SRobert Mustacchi 
460575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_flash_byte_ich8lan");
460675eba5b6SRobert Mustacchi 
460775eba5b6SRobert Mustacchi 	return e1000_write_flash_data_ich8lan(hw, offset, 1, word);
460875eba5b6SRobert Mustacchi }
460975eba5b6SRobert Mustacchi 
4610*42cc51e0SRobert Mustacchi /**
4611*42cc51e0SRobert Mustacchi *  e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM
4612*42cc51e0SRobert Mustacchi *  @hw: pointer to the HW structure
4613*42cc51e0SRobert Mustacchi *  @offset: The offset of the word to write.
4614*42cc51e0SRobert Mustacchi *  @dword: The dword to write to the NVM.
4615*42cc51e0SRobert Mustacchi *
4616*42cc51e0SRobert Mustacchi *  Writes a single dword to the NVM using the flash access registers.
4617*42cc51e0SRobert Mustacchi *  Goes through a retry algorithm before giving up.
4618*42cc51e0SRobert Mustacchi **/
4619*42cc51e0SRobert Mustacchi static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
4620*42cc51e0SRobert Mustacchi 						 u32 offset, u32 dword)
4621*42cc51e0SRobert Mustacchi {
4622*42cc51e0SRobert Mustacchi 	s32 ret_val;
4623*42cc51e0SRobert Mustacchi 	u16 program_retries;
4624c124a83eSRobert Mustacchi 
4625*42cc51e0SRobert Mustacchi 	DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan");
4626*42cc51e0SRobert Mustacchi 
4627*42cc51e0SRobert Mustacchi 	/* Must convert word offset into bytes. */
4628*42cc51e0SRobert Mustacchi 	offset <<= 1;
4629*42cc51e0SRobert Mustacchi 
4630*42cc51e0SRobert Mustacchi 	ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
4631*42cc51e0SRobert Mustacchi 
4632*42cc51e0SRobert Mustacchi 	if (!ret_val)
4633*42cc51e0SRobert Mustacchi 		return ret_val;
4634*42cc51e0SRobert Mustacchi 	for (program_retries = 0; program_retries < 100; program_retries++) {
4635*42cc51e0SRobert Mustacchi 		DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset);
4636*42cc51e0SRobert Mustacchi 		usec_delay(100);
4637*42cc51e0SRobert Mustacchi 		ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
4638*42cc51e0SRobert Mustacchi 		if (ret_val == E1000_SUCCESS)
4639*42cc51e0SRobert Mustacchi 			break;
4640*42cc51e0SRobert Mustacchi 	}
4641*42cc51e0SRobert Mustacchi 	if (program_retries == 100)
4642*42cc51e0SRobert Mustacchi 		return -E1000_ERR_NVM;
4643*42cc51e0SRobert Mustacchi 
4644*42cc51e0SRobert Mustacchi 	return E1000_SUCCESS;
4645*42cc51e0SRobert Mustacchi }
4646c124a83eSRobert Mustacchi 
464775eba5b6SRobert Mustacchi /**
464875eba5b6SRobert Mustacchi  *  e1000_retry_write_flash_byte_ich8lan - Writes a single byte to NVM
464975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
465075eba5b6SRobert Mustacchi  *  @offset: The offset of the byte to write.
465175eba5b6SRobert Mustacchi  *  @byte: The byte to write to the NVM.
465275eba5b6SRobert Mustacchi  *
465375eba5b6SRobert Mustacchi  *  Writes a single byte to the NVM using the flash access registers.
465475eba5b6SRobert Mustacchi  *  Goes through a retry algorithm before giving up.
465575eba5b6SRobert Mustacchi  **/
465675eba5b6SRobert Mustacchi static s32 e1000_retry_write_flash_byte_ich8lan(struct e1000_hw *hw,
465775eba5b6SRobert Mustacchi 						u32 offset, u8 byte)
465875eba5b6SRobert Mustacchi {
465975eba5b6SRobert Mustacchi 	s32 ret_val;
466075eba5b6SRobert Mustacchi 	u16 program_retries;
466175eba5b6SRobert Mustacchi 
466275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_retry_write_flash_byte_ich8lan");
466375eba5b6SRobert Mustacchi 
466475eba5b6SRobert Mustacchi 	ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
466575eba5b6SRobert Mustacchi 	if (!ret_val)
466675eba5b6SRobert Mustacchi 		return ret_val;
466775eba5b6SRobert Mustacchi 
466875eba5b6SRobert Mustacchi 	for (program_retries = 0; program_retries < 100; program_retries++) {
466975eba5b6SRobert Mustacchi 		DEBUGOUT2("Retrying Byte %2.2X at offset %u\n", byte, offset);
467075eba5b6SRobert Mustacchi 		usec_delay(100);
467175eba5b6SRobert Mustacchi 		ret_val = e1000_write_flash_byte_ich8lan(hw, offset, byte);
467275eba5b6SRobert Mustacchi 		if (ret_val == E1000_SUCCESS)
467375eba5b6SRobert Mustacchi 			break;
467475eba5b6SRobert Mustacchi 	}
467575eba5b6SRobert Mustacchi 	if (program_retries == 100)
467675eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
467775eba5b6SRobert Mustacchi 
467875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
467975eba5b6SRobert Mustacchi }
468075eba5b6SRobert Mustacchi 
468175eba5b6SRobert Mustacchi /**
468275eba5b6SRobert Mustacchi  *  e1000_erase_flash_bank_ich8lan - Erase a bank (4k) from NVM
468375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
468475eba5b6SRobert Mustacchi  *  @bank: 0 for first bank, 1 for second bank, etc.
468575eba5b6SRobert Mustacchi  *
468675eba5b6SRobert Mustacchi  *  Erases the bank specified. Each bank is a 4k block. Banks are 0 based.
468775eba5b6SRobert Mustacchi  *  bank N is 4096 * N + flash_reg_addr.
468875eba5b6SRobert Mustacchi  **/
468975eba5b6SRobert Mustacchi static s32 e1000_erase_flash_bank_ich8lan(struct e1000_hw *hw, u32 bank)
469075eba5b6SRobert Mustacchi {
469175eba5b6SRobert Mustacchi 	struct e1000_nvm_info *nvm = &hw->nvm;
469275eba5b6SRobert Mustacchi 	union ich8_hws_flash_status hsfsts;
469375eba5b6SRobert Mustacchi 	union ich8_hws_flash_ctrl hsflctl;
469475eba5b6SRobert Mustacchi 	u32 flash_linear_addr;
469575eba5b6SRobert Mustacchi 	/* bank size is in 16bit words - adjust to bytes */
469675eba5b6SRobert Mustacchi 	u32 flash_bank_size = nvm->flash_bank_size * 2;
469775eba5b6SRobert Mustacchi 	s32 ret_val;
469875eba5b6SRobert Mustacchi 	s32 count = 0;
469975eba5b6SRobert Mustacchi 	s32 j, iteration, sector_size;
470075eba5b6SRobert Mustacchi 
470175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_erase_flash_bank_ich8lan");
470275eba5b6SRobert Mustacchi 
470375eba5b6SRobert Mustacchi 	hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
470475eba5b6SRobert Mustacchi 
470575eba5b6SRobert Mustacchi 	/* Determine HW Sector size: Read BERASE bits of hw flash status
470675eba5b6SRobert Mustacchi 	 * register
470775eba5b6SRobert Mustacchi 	 * 00: The Hw sector is 256 bytes, hence we need to erase 16
470875eba5b6SRobert Mustacchi 	 *     consecutive sectors.  The start index for the nth Hw sector
470975eba5b6SRobert Mustacchi 	 *     can be calculated as = bank * 4096 + n * 256
471075eba5b6SRobert Mustacchi 	 * 01: The Hw sector is 4K bytes, hence we need to erase 1 sector.
471175eba5b6SRobert Mustacchi 	 *     The start index for the nth Hw sector can be calculated
471275eba5b6SRobert Mustacchi 	 *     as = bank * 4096
471375eba5b6SRobert Mustacchi 	 * 10: The Hw sector is 8K bytes, nth sector = bank * 8192
471475eba5b6SRobert Mustacchi 	 *     (ich9 only, otherwise error condition)
471575eba5b6SRobert Mustacchi 	 * 11: The Hw sector is 64K bytes, nth sector = bank * 65536
471675eba5b6SRobert Mustacchi 	 */
471775eba5b6SRobert Mustacchi 	switch (hsfsts.hsf_status.berasesz) {
471875eba5b6SRobert Mustacchi 	case 0:
471975eba5b6SRobert Mustacchi 		/* Hw sector size 256 */
472075eba5b6SRobert Mustacchi 		sector_size = ICH_FLASH_SEG_SIZE_256;
472175eba5b6SRobert Mustacchi 		iteration = flash_bank_size / ICH_FLASH_SEG_SIZE_256;
472275eba5b6SRobert Mustacchi 		break;
472375eba5b6SRobert Mustacchi 	case 1:
472475eba5b6SRobert Mustacchi 		sector_size = ICH_FLASH_SEG_SIZE_4K;
472575eba5b6SRobert Mustacchi 		iteration = 1;
472675eba5b6SRobert Mustacchi 		break;
472775eba5b6SRobert Mustacchi 	case 2:
472875eba5b6SRobert Mustacchi 		sector_size = ICH_FLASH_SEG_SIZE_8K;
472975eba5b6SRobert Mustacchi 		iteration = 1;
473075eba5b6SRobert Mustacchi 		break;
473175eba5b6SRobert Mustacchi 	case 3:
473275eba5b6SRobert Mustacchi 		sector_size = ICH_FLASH_SEG_SIZE_64K;
473375eba5b6SRobert Mustacchi 		iteration = 1;
473475eba5b6SRobert Mustacchi 		break;
473575eba5b6SRobert Mustacchi 	default:
473675eba5b6SRobert Mustacchi 		return -E1000_ERR_NVM;
473775eba5b6SRobert Mustacchi 	}
473875eba5b6SRobert Mustacchi 
473975eba5b6SRobert Mustacchi 	/* Start with the base address, then add the sector offset. */
474075eba5b6SRobert Mustacchi 	flash_linear_addr = hw->nvm.flash_base_addr;
474175eba5b6SRobert Mustacchi 	flash_linear_addr += (bank) ? flash_bank_size : 0;
474275eba5b6SRobert Mustacchi 
474375eba5b6SRobert Mustacchi 	for (j = 0; j < iteration; j++) {
474475eba5b6SRobert Mustacchi 		do {
4745c124a83eSRobert Mustacchi 			u32 timeout = ICH_FLASH_ERASE_COMMAND_TIMEOUT;
4746c124a83eSRobert Mustacchi 
474775eba5b6SRobert Mustacchi 			/* Steps */
474875eba5b6SRobert Mustacchi 			ret_val = e1000_flash_cycle_init_ich8lan(hw);
474975eba5b6SRobert Mustacchi 			if (ret_val)
475075eba5b6SRobert Mustacchi 				return ret_val;
475175eba5b6SRobert Mustacchi 
475275eba5b6SRobert Mustacchi 			/* Write a value 11 (block Erase) in Flash
475375eba5b6SRobert Mustacchi 			 * Cycle field in hw flash control
475475eba5b6SRobert Mustacchi 			 */
4755*42cc51e0SRobert Mustacchi 			if (hw->mac.type == e1000_pch_spt)
4756c124a83eSRobert Mustacchi 				hsflctl.regval =
4757*42cc51e0SRobert Mustacchi 				    E1000_READ_FLASH_REG(hw,
4758*42cc51e0SRobert Mustacchi 							 ICH_FLASH_HSFSTS)>>16;
4759*42cc51e0SRobert Mustacchi 			else
4760*42cc51e0SRobert Mustacchi 				hsflctl.regval =
4761*42cc51e0SRobert Mustacchi 				    E1000_READ_FLASH_REG16(hw,
4762*42cc51e0SRobert Mustacchi 							   ICH_FLASH_HSFCTL);
4763c124a83eSRobert Mustacchi 
476475eba5b6SRobert Mustacchi 			hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
4765*42cc51e0SRobert Mustacchi 			if (hw->mac.type == e1000_pch_spt)
4766*42cc51e0SRobert Mustacchi 				E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
4767*42cc51e0SRobert Mustacchi 						      hsflctl.regval << 16);
4768*42cc51e0SRobert Mustacchi 			else
476975eba5b6SRobert Mustacchi 				E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
477075eba5b6SRobert Mustacchi 							hsflctl.regval);
477175eba5b6SRobert Mustacchi 
477275eba5b6SRobert Mustacchi 			/* Write the last 24 bits of an index within the
477375eba5b6SRobert Mustacchi 			 * block into Flash Linear address field in Flash
477475eba5b6SRobert Mustacchi 			 * Address.
477575eba5b6SRobert Mustacchi 			 */
477675eba5b6SRobert Mustacchi 			flash_linear_addr += (j * sector_size);
477775eba5b6SRobert Mustacchi 			E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR,
477875eba5b6SRobert Mustacchi 					      flash_linear_addr);
477975eba5b6SRobert Mustacchi 
4780c124a83eSRobert Mustacchi 			ret_val = e1000_flash_cycle_ich8lan(hw, timeout);
478175eba5b6SRobert Mustacchi 			if (ret_val == E1000_SUCCESS)
478275eba5b6SRobert Mustacchi 				break;
478375eba5b6SRobert Mustacchi 
478475eba5b6SRobert Mustacchi 			/* Check if FCERR is set to 1.  If 1,
478575eba5b6SRobert Mustacchi 			 * clear it and try the whole sequence
478675eba5b6SRobert Mustacchi 			 * a few more times else Done
478775eba5b6SRobert Mustacchi 			 */
478875eba5b6SRobert Mustacchi 			hsfsts.regval = E1000_READ_FLASH_REG16(hw,
478975eba5b6SRobert Mustacchi 						      ICH_FLASH_HSFSTS);
479075eba5b6SRobert Mustacchi 			if (hsfsts.hsf_status.flcerr)
479175eba5b6SRobert Mustacchi 				/* repeat for some time before giving up */
479275eba5b6SRobert Mustacchi 				continue;
479375eba5b6SRobert Mustacchi 			else if (!hsfsts.hsf_status.flcdone)
479475eba5b6SRobert Mustacchi 				return ret_val;
479575eba5b6SRobert Mustacchi 		} while (++count < ICH_FLASH_CYCLE_REPEAT_COUNT);
479675eba5b6SRobert Mustacchi 	}
479775eba5b6SRobert Mustacchi 
479875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
479975eba5b6SRobert Mustacchi }
480075eba5b6SRobert Mustacchi 
480175eba5b6SRobert Mustacchi /**
480275eba5b6SRobert Mustacchi  *  e1000_valid_led_default_ich8lan - Set the default LED settings
480375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
480475eba5b6SRobert Mustacchi  *  @data: Pointer to the LED settings
480575eba5b6SRobert Mustacchi  *
480675eba5b6SRobert Mustacchi  *  Reads the LED default settings from the NVM to data.  If the NVM LED
480775eba5b6SRobert Mustacchi  *  settings is all 0's or F's, set the LED default to a valid LED default
480875eba5b6SRobert Mustacchi  *  setting.
480975eba5b6SRobert Mustacchi  **/
481075eba5b6SRobert Mustacchi static s32 e1000_valid_led_default_ich8lan(struct e1000_hw *hw, u16 *data)
481175eba5b6SRobert Mustacchi {
481275eba5b6SRobert Mustacchi 	s32 ret_val;
481375eba5b6SRobert Mustacchi 
481475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_valid_led_default_ich8lan");
481575eba5b6SRobert Mustacchi 
481675eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.read(hw, NVM_ID_LED_SETTINGS, 1, data);
481775eba5b6SRobert Mustacchi 	if (ret_val) {
481875eba5b6SRobert Mustacchi 		DEBUGOUT("NVM Read Error\n");
481975eba5b6SRobert Mustacchi 		return ret_val;
482075eba5b6SRobert Mustacchi 	}
482175eba5b6SRobert Mustacchi 
482275eba5b6SRobert Mustacchi 	if (*data == ID_LED_RESERVED_0000 || *data == ID_LED_RESERVED_FFFF)
482375eba5b6SRobert Mustacchi 		*data = ID_LED_DEFAULT_ICH8LAN;
482475eba5b6SRobert Mustacchi 
482575eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
482675eba5b6SRobert Mustacchi }
482775eba5b6SRobert Mustacchi 
482875eba5b6SRobert Mustacchi /**
482975eba5b6SRobert Mustacchi  *  e1000_id_led_init_pchlan - store LED configurations
483075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
483175eba5b6SRobert Mustacchi  *
483275eba5b6SRobert Mustacchi  *  PCH does not control LEDs via the LEDCTL register, rather it uses
483375eba5b6SRobert Mustacchi  *  the PHY LED configuration register.
483475eba5b6SRobert Mustacchi  *
483575eba5b6SRobert Mustacchi  *  PCH also does not have an "always on" or "always off" mode which
483675eba5b6SRobert Mustacchi  *  complicates the ID feature.  Instead of using the "on" mode to indicate
483775eba5b6SRobert Mustacchi  *  in ledctl_mode2 the LEDs to use for ID (see e1000_id_led_init_generic()),
483875eba5b6SRobert Mustacchi  *  use "link_up" mode.  The LEDs will still ID on request if there is no
483975eba5b6SRobert Mustacchi  *  link based on logic in e1000_led_[on|off]_pchlan().
484075eba5b6SRobert Mustacchi  **/
484175eba5b6SRobert Mustacchi static s32 e1000_id_led_init_pchlan(struct e1000_hw *hw)
484275eba5b6SRobert Mustacchi {
484375eba5b6SRobert Mustacchi 	struct e1000_mac_info *mac = &hw->mac;
484475eba5b6SRobert Mustacchi 	s32 ret_val;
484575eba5b6SRobert Mustacchi 	const u32 ledctl_on = E1000_LEDCTL_MODE_LINK_UP;
484675eba5b6SRobert Mustacchi 	const u32 ledctl_off = E1000_LEDCTL_MODE_LINK_UP | E1000_PHY_LED0_IVRT;
484775eba5b6SRobert Mustacchi 	u16 data, i, temp, shift;
484875eba5b6SRobert Mustacchi 
484975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_id_led_init_pchlan");
485075eba5b6SRobert Mustacchi 
485175eba5b6SRobert Mustacchi 	/* Get default ID LED modes */
485275eba5b6SRobert Mustacchi 	ret_val = hw->nvm.ops.valid_led_default(hw, &data);
485375eba5b6SRobert Mustacchi 	if (ret_val)
485475eba5b6SRobert Mustacchi 		return ret_val;
485575eba5b6SRobert Mustacchi 
485675eba5b6SRobert Mustacchi 	mac->ledctl_default = E1000_READ_REG(hw, E1000_LEDCTL);
485775eba5b6SRobert Mustacchi 	mac->ledctl_mode1 = mac->ledctl_default;
485875eba5b6SRobert Mustacchi 	mac->ledctl_mode2 = mac->ledctl_default;
485975eba5b6SRobert Mustacchi 
486075eba5b6SRobert Mustacchi 	for (i = 0; i < 4; i++) {
486175eba5b6SRobert Mustacchi 		temp = (data >> (i << 2)) & E1000_LEDCTL_LED0_MODE_MASK;
486275eba5b6SRobert Mustacchi 		shift = (i * 5);
486375eba5b6SRobert Mustacchi 		switch (temp) {
486475eba5b6SRobert Mustacchi 		case ID_LED_ON1_DEF2:
486575eba5b6SRobert Mustacchi 		case ID_LED_ON1_ON2:
486675eba5b6SRobert Mustacchi 		case ID_LED_ON1_OFF2:
486775eba5b6SRobert Mustacchi 			mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
486875eba5b6SRobert Mustacchi 			mac->ledctl_mode1 |= (ledctl_on << shift);
486975eba5b6SRobert Mustacchi 			break;
487075eba5b6SRobert Mustacchi 		case ID_LED_OFF1_DEF2:
487175eba5b6SRobert Mustacchi 		case ID_LED_OFF1_ON2:
487275eba5b6SRobert Mustacchi 		case ID_LED_OFF1_OFF2:
487375eba5b6SRobert Mustacchi 			mac->ledctl_mode1 &= ~(E1000_PHY_LED0_MASK << shift);
487475eba5b6SRobert Mustacchi 			mac->ledctl_mode1 |= (ledctl_off << shift);
487575eba5b6SRobert Mustacchi 			break;
487675eba5b6SRobert Mustacchi 		default:
487775eba5b6SRobert Mustacchi 			/* Do nothing */
487875eba5b6SRobert Mustacchi 			break;
487975eba5b6SRobert Mustacchi 		}
488075eba5b6SRobert Mustacchi 		switch (temp) {
488175eba5b6SRobert Mustacchi 		case ID_LED_DEF1_ON2:
488275eba5b6SRobert Mustacchi 		case ID_LED_ON1_ON2:
488375eba5b6SRobert Mustacchi 		case ID_LED_OFF1_ON2:
488475eba5b6SRobert Mustacchi 			mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
488575eba5b6SRobert Mustacchi 			mac->ledctl_mode2 |= (ledctl_on << shift);
488675eba5b6SRobert Mustacchi 			break;
488775eba5b6SRobert Mustacchi 		case ID_LED_DEF1_OFF2:
488875eba5b6SRobert Mustacchi 		case ID_LED_ON1_OFF2:
488975eba5b6SRobert Mustacchi 		case ID_LED_OFF1_OFF2:
489075eba5b6SRobert Mustacchi 			mac->ledctl_mode2 &= ~(E1000_PHY_LED0_MASK << shift);
489175eba5b6SRobert Mustacchi 			mac->ledctl_mode2 |= (ledctl_off << shift);
489275eba5b6SRobert Mustacchi 			break;
489375eba5b6SRobert Mustacchi 		default:
489475eba5b6SRobert Mustacchi 			/* Do nothing */
489575eba5b6SRobert Mustacchi 			break;
489675eba5b6SRobert Mustacchi 		}
489775eba5b6SRobert Mustacchi 	}
489875eba5b6SRobert Mustacchi 
489975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
490075eba5b6SRobert Mustacchi }
490175eba5b6SRobert Mustacchi 
490275eba5b6SRobert Mustacchi /**
490375eba5b6SRobert Mustacchi  *  e1000_get_bus_info_ich8lan - Get/Set the bus type and width
490475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
490575eba5b6SRobert Mustacchi  *
490675eba5b6SRobert Mustacchi  *  ICH8 use the PCI Express bus, but does not contain a PCI Express Capability
490775eba5b6SRobert Mustacchi  *  register, so the the bus width is hard coded.
490875eba5b6SRobert Mustacchi  **/
490975eba5b6SRobert Mustacchi static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
491075eba5b6SRobert Mustacchi {
491175eba5b6SRobert Mustacchi 	struct e1000_bus_info *bus = &hw->bus;
491275eba5b6SRobert Mustacchi 	s32 ret_val;
491375eba5b6SRobert Mustacchi 
491475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_bus_info_ich8lan");
491575eba5b6SRobert Mustacchi 
491675eba5b6SRobert Mustacchi 	ret_val = e1000_get_bus_info_pcie_generic(hw);
491775eba5b6SRobert Mustacchi 
491875eba5b6SRobert Mustacchi 	/* ICH devices are "PCI Express"-ish.  They have
491975eba5b6SRobert Mustacchi 	 * a configuration space, but do not contain
492075eba5b6SRobert Mustacchi 	 * PCI Express Capability registers, so bus width
492175eba5b6SRobert Mustacchi 	 * must be hardcoded.
492275eba5b6SRobert Mustacchi 	 */
492375eba5b6SRobert Mustacchi 	if (bus->width == e1000_bus_width_unknown)
492475eba5b6SRobert Mustacchi 		bus->width = e1000_bus_width_pcie_x1;
492575eba5b6SRobert Mustacchi 
492675eba5b6SRobert Mustacchi 	return ret_val;
492775eba5b6SRobert Mustacchi }
492875eba5b6SRobert Mustacchi 
492975eba5b6SRobert Mustacchi /**
493075eba5b6SRobert Mustacchi  *  e1000_reset_hw_ich8lan - Reset the hardware
493175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
493275eba5b6SRobert Mustacchi  *
493375eba5b6SRobert Mustacchi  *  Does a full reset of the hardware which includes a reset of the PHY and
493475eba5b6SRobert Mustacchi  *  MAC.
493575eba5b6SRobert Mustacchi  **/
493675eba5b6SRobert Mustacchi static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
493775eba5b6SRobert Mustacchi {
493875eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
493975eba5b6SRobert Mustacchi 	u16 kum_cfg;
494075eba5b6SRobert Mustacchi 	u32 ctrl, reg;
494175eba5b6SRobert Mustacchi 	s32 ret_val;
494275eba5b6SRobert Mustacchi 
494375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_reset_hw_ich8lan");
494475eba5b6SRobert Mustacchi 
494575eba5b6SRobert Mustacchi 	/* Prevent the PCI-E bus from sticking if there is no TLP connection
494675eba5b6SRobert Mustacchi 	 * on the last TLP read/write transaction when MAC is reset.
494775eba5b6SRobert Mustacchi 	 */
494875eba5b6SRobert Mustacchi 	ret_val = e1000_disable_pcie_master_generic(hw);
494975eba5b6SRobert Mustacchi 	if (ret_val)
495075eba5b6SRobert Mustacchi 		DEBUGOUT("PCI-E Master disable polling has failed.\n");
495175eba5b6SRobert Mustacchi 
495275eba5b6SRobert Mustacchi 	DEBUGOUT("Masking off all interrupts\n");
495375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
495475eba5b6SRobert Mustacchi 
495575eba5b6SRobert Mustacchi 	/* Disable the Transmit and Receive units.  Then delay to allow
495675eba5b6SRobert Mustacchi 	 * any pending transactions to complete before we hit the MAC
495775eba5b6SRobert Mustacchi 	 * with the global reset.
495875eba5b6SRobert Mustacchi 	 */
495975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_RCTL, 0);
496075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TCTL, E1000_TCTL_PSP);
496175eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
496275eba5b6SRobert Mustacchi 
496375eba5b6SRobert Mustacchi 	msec_delay(10);
496475eba5b6SRobert Mustacchi 
496575eba5b6SRobert Mustacchi 	/* Workaround for ICH8 bit corruption issue in FIFO memory */
496675eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_ich8lan) {
496775eba5b6SRobert Mustacchi 		/* Set Tx and Rx buffer allocation to 8k apiece. */
496875eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PBA, E1000_PBA_8K);
496975eba5b6SRobert Mustacchi 		/* Set Packet Buffer Size to 16k. */
497075eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PBS, E1000_PBS_16K);
497175eba5b6SRobert Mustacchi 	}
497275eba5b6SRobert Mustacchi 
497375eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pchlan) {
497475eba5b6SRobert Mustacchi 		/* Save the NVM K1 bit setting*/
497575eba5b6SRobert Mustacchi 		ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &kum_cfg);
497675eba5b6SRobert Mustacchi 		if (ret_val)
497775eba5b6SRobert Mustacchi 			return ret_val;
497875eba5b6SRobert Mustacchi 
497975eba5b6SRobert Mustacchi 		if (kum_cfg & E1000_NVM_K1_ENABLE)
498075eba5b6SRobert Mustacchi 			dev_spec->nvm_k1_enabled = TRUE;
498175eba5b6SRobert Mustacchi 		else
498275eba5b6SRobert Mustacchi 			dev_spec->nvm_k1_enabled = FALSE;
498375eba5b6SRobert Mustacchi 	}
498475eba5b6SRobert Mustacchi 
498575eba5b6SRobert Mustacchi 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
498675eba5b6SRobert Mustacchi 
498775eba5b6SRobert Mustacchi 	if (!hw->phy.ops.check_reset_block(hw)) {
498875eba5b6SRobert Mustacchi 		/* Full-chip reset requires MAC and PHY reset at the same
498975eba5b6SRobert Mustacchi 		 * time to make sure the interface between MAC and the
499075eba5b6SRobert Mustacchi 		 * external PHY is reset.
499175eba5b6SRobert Mustacchi 		 */
499275eba5b6SRobert Mustacchi 		ctrl |= E1000_CTRL_PHY_RST;
499375eba5b6SRobert Mustacchi 
499475eba5b6SRobert Mustacchi 		/* Gate automatic PHY configuration by hardware on
499575eba5b6SRobert Mustacchi 		 * non-managed 82579
499675eba5b6SRobert Mustacchi 		 */
499775eba5b6SRobert Mustacchi 		if ((hw->mac.type == e1000_pch2lan) &&
499875eba5b6SRobert Mustacchi 		    !(E1000_READ_REG(hw, E1000_FWSM) & E1000_ICH_FWSM_FW_VALID))
499975eba5b6SRobert Mustacchi 			e1000_gate_hw_phy_config_ich8lan(hw, TRUE);
500075eba5b6SRobert Mustacchi 	}
500175eba5b6SRobert Mustacchi 	ret_val = e1000_acquire_swflag_ich8lan(hw);
500275eba5b6SRobert Mustacchi 	DEBUGOUT("Issuing a global reset to ich8lan\n");
500375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, (ctrl | E1000_CTRL_RST));
500475eba5b6SRobert Mustacchi 	/* cannot issue a flush here because it hangs the hardware */
500575eba5b6SRobert Mustacchi 	msec_delay(20);
500675eba5b6SRobert Mustacchi 
500775eba5b6SRobert Mustacchi 	/* Set Phy Config Counter to 50msec */
500875eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pch2lan) {
500975eba5b6SRobert Mustacchi 		reg = E1000_READ_REG(hw, E1000_FEXTNVM3);
501075eba5b6SRobert Mustacchi 		reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK;
501175eba5b6SRobert Mustacchi 		reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC;
501275eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FEXTNVM3, reg);
501375eba5b6SRobert Mustacchi 	}
501475eba5b6SRobert Mustacchi 
501575eba5b6SRobert Mustacchi 	if (!ret_val)
501675eba5b6SRobert Mustacchi 		E1000_MUTEX_UNLOCK(&hw->dev_spec.ich8lan.swflag_mutex);
501775eba5b6SRobert Mustacchi 
501875eba5b6SRobert Mustacchi 	if (ctrl & E1000_CTRL_PHY_RST) {
501975eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.get_cfg_done(hw);
502075eba5b6SRobert Mustacchi 		if (ret_val)
502175eba5b6SRobert Mustacchi 			return ret_val;
502275eba5b6SRobert Mustacchi 
502375eba5b6SRobert Mustacchi 		ret_val = e1000_post_phy_reset_ich8lan(hw);
502475eba5b6SRobert Mustacchi 		if (ret_val)
502575eba5b6SRobert Mustacchi 			return ret_val;
502675eba5b6SRobert Mustacchi 	}
502775eba5b6SRobert Mustacchi 
502875eba5b6SRobert Mustacchi 	/* For PCH, this write will make sure that any noise
502975eba5b6SRobert Mustacchi 	 * will be detected as a CRC error and be dropped rather than show up
503075eba5b6SRobert Mustacchi 	 * as a bad packet to the DMA engine.
503175eba5b6SRobert Mustacchi 	 */
503275eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pchlan)
503375eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_CRC_OFFSET, 0x65656565);
503475eba5b6SRobert Mustacchi 
503575eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_IMC, 0xffffffff);
503675eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICR);
503775eba5b6SRobert Mustacchi 
503875eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_KABGTXD);
503975eba5b6SRobert Mustacchi 	reg |= E1000_KABGTXD_BGSQLBIAS;
504075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_KABGTXD, reg);
504175eba5b6SRobert Mustacchi 
504275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
504375eba5b6SRobert Mustacchi }
504475eba5b6SRobert Mustacchi 
504575eba5b6SRobert Mustacchi /**
504675eba5b6SRobert Mustacchi  *  e1000_init_hw_ich8lan - Initialize the hardware
504775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
504875eba5b6SRobert Mustacchi  *
504975eba5b6SRobert Mustacchi  *  Prepares the hardware for transmit and receive by doing the following:
505075eba5b6SRobert Mustacchi  *   - initialize hardware bits
505175eba5b6SRobert Mustacchi  *   - initialize LED identification
505275eba5b6SRobert Mustacchi  *   - setup receive address registers
505375eba5b6SRobert Mustacchi  *   - setup flow control
505475eba5b6SRobert Mustacchi  *   - setup transmit descriptors
505575eba5b6SRobert Mustacchi  *   - clear statistics
505675eba5b6SRobert Mustacchi  **/
505775eba5b6SRobert Mustacchi static s32 e1000_init_hw_ich8lan(struct e1000_hw *hw)
505875eba5b6SRobert Mustacchi {
505975eba5b6SRobert Mustacchi 	struct e1000_mac_info *mac = &hw->mac;
506075eba5b6SRobert Mustacchi 	u32 ctrl_ext, txdctl, snoop;
506175eba5b6SRobert Mustacchi 	s32 ret_val;
506275eba5b6SRobert Mustacchi 	u16 i;
506375eba5b6SRobert Mustacchi 
506475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_hw_ich8lan");
506575eba5b6SRobert Mustacchi 
506675eba5b6SRobert Mustacchi 	e1000_initialize_hw_bits_ich8lan(hw);
506775eba5b6SRobert Mustacchi 
506875eba5b6SRobert Mustacchi 	/* Initialize identification LED */
506975eba5b6SRobert Mustacchi 	ret_val = mac->ops.id_led_init(hw);
507075eba5b6SRobert Mustacchi 	/* An error is not fatal and we should not stop init due to this */
507175eba5b6SRobert Mustacchi 	if (ret_val)
507275eba5b6SRobert Mustacchi 		DEBUGOUT("Error initializing identification LED\n");
507375eba5b6SRobert Mustacchi 
507475eba5b6SRobert Mustacchi 	/* Setup the receive address. */
507575eba5b6SRobert Mustacchi 	e1000_init_rx_addrs_generic(hw, mac->rar_entry_count);
507675eba5b6SRobert Mustacchi 
507775eba5b6SRobert Mustacchi 	/* Zero out the Multicast HASH table */
507875eba5b6SRobert Mustacchi 	DEBUGOUT("Zeroing the MTA\n");
507975eba5b6SRobert Mustacchi 	for (i = 0; i < mac->mta_reg_count; i++)
508075eba5b6SRobert Mustacchi 		E1000_WRITE_REG_ARRAY(hw, E1000_MTA, i, 0);
508175eba5b6SRobert Mustacchi 
508275eba5b6SRobert Mustacchi 	/* The 82578 Rx buffer will stall if wakeup is enabled in host and
508375eba5b6SRobert Mustacchi 	 * the ME.  Disable wakeup by clearing the host wakeup bit.
508475eba5b6SRobert Mustacchi 	 * Reset the phy after disabling host wakeup to reset the Rx buffer.
508575eba5b6SRobert Mustacchi 	 */
508675eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_82578) {
508775eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, BM_PORT_GEN_CFG, &i);
508875eba5b6SRobert Mustacchi 		i &= ~BM_WUC_HOST_WU_BIT;
508975eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg(hw, BM_PORT_GEN_CFG, i);
509075eba5b6SRobert Mustacchi 		ret_val = e1000_phy_hw_reset_ich8lan(hw);
509175eba5b6SRobert Mustacchi 		if (ret_val)
509275eba5b6SRobert Mustacchi 			return ret_val;
509375eba5b6SRobert Mustacchi 	}
509475eba5b6SRobert Mustacchi 
509575eba5b6SRobert Mustacchi 	/* Setup link and flow control */
509675eba5b6SRobert Mustacchi 	ret_val = mac->ops.setup_link(hw);
509775eba5b6SRobert Mustacchi 
509875eba5b6SRobert Mustacchi 	/* Set the transmit descriptor write-back policy for both queues */
509975eba5b6SRobert Mustacchi 	txdctl = E1000_READ_REG(hw, E1000_TXDCTL(0));
5100c124a83eSRobert Mustacchi 	txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) |
5101c124a83eSRobert Mustacchi 		  E1000_TXDCTL_FULL_TX_DESC_WB);
5102c124a83eSRobert Mustacchi 	txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) |
5103c124a83eSRobert Mustacchi 		  E1000_TXDCTL_MAX_TX_DESC_PREFETCH);
510475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), txdctl);
510575eba5b6SRobert Mustacchi 	txdctl = E1000_READ_REG(hw, E1000_TXDCTL(1));
5106c124a83eSRobert Mustacchi 	txdctl = ((txdctl & ~E1000_TXDCTL_WTHRESH) |
5107c124a83eSRobert Mustacchi 		  E1000_TXDCTL_FULL_TX_DESC_WB);
5108c124a83eSRobert Mustacchi 	txdctl = ((txdctl & ~E1000_TXDCTL_PTHRESH) |
5109c124a83eSRobert Mustacchi 		  E1000_TXDCTL_MAX_TX_DESC_PREFETCH);
511075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(1), txdctl);
511175eba5b6SRobert Mustacchi 
511275eba5b6SRobert Mustacchi 	/* ICH8 has opposite polarity of no_snoop bits.
511375eba5b6SRobert Mustacchi 	 * By default, we should use snoop behavior.
511475eba5b6SRobert Mustacchi 	 */
511575eba5b6SRobert Mustacchi 	if (mac->type == e1000_ich8lan)
511675eba5b6SRobert Mustacchi 		snoop = PCIE_ICH8_SNOOP_ALL;
511775eba5b6SRobert Mustacchi 	else
511875eba5b6SRobert Mustacchi 		snoop = (u32) ~(PCIE_NO_SNOOP_ALL);
511975eba5b6SRobert Mustacchi 	e1000_set_pcie_no_snoop_generic(hw, snoop);
512075eba5b6SRobert Mustacchi 
512175eba5b6SRobert Mustacchi 	ctrl_ext = E1000_READ_REG(hw, E1000_CTRL_EXT);
512275eba5b6SRobert Mustacchi 	ctrl_ext |= E1000_CTRL_EXT_RO_DIS;
512375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, ctrl_ext);
512475eba5b6SRobert Mustacchi 
512575eba5b6SRobert Mustacchi 	/* Clear all of the statistics registers (clear on read).  It is
512675eba5b6SRobert Mustacchi 	 * important that we do this after we have tried to establish link
512775eba5b6SRobert Mustacchi 	 * because the symbol error count will increment wildly if there
512875eba5b6SRobert Mustacchi 	 * is no link.
512975eba5b6SRobert Mustacchi 	 */
513075eba5b6SRobert Mustacchi 	e1000_clear_hw_cntrs_ich8lan(hw);
513175eba5b6SRobert Mustacchi 
513275eba5b6SRobert Mustacchi 	return ret_val;
513375eba5b6SRobert Mustacchi }
513475eba5b6SRobert Mustacchi 
513575eba5b6SRobert Mustacchi /**
513675eba5b6SRobert Mustacchi  *  e1000_initialize_hw_bits_ich8lan - Initialize required hardware bits
513775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
513875eba5b6SRobert Mustacchi  *
513975eba5b6SRobert Mustacchi  *  Sets/Clears required hardware bits necessary for correctly setting up the
514075eba5b6SRobert Mustacchi  *  hardware for transmit and receive.
514175eba5b6SRobert Mustacchi  **/
514275eba5b6SRobert Mustacchi static void e1000_initialize_hw_bits_ich8lan(struct e1000_hw *hw)
514375eba5b6SRobert Mustacchi {
514475eba5b6SRobert Mustacchi 	u32 reg;
514575eba5b6SRobert Mustacchi 
514675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_initialize_hw_bits_ich8lan");
514775eba5b6SRobert Mustacchi 
514875eba5b6SRobert Mustacchi 	/* Extended Device Control */
514975eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_CTRL_EXT);
515075eba5b6SRobert Mustacchi 	reg |= (1 << 22);
515175eba5b6SRobert Mustacchi 	/* Enable PHY low-power state when MAC is at D3 w/o WoL */
515275eba5b6SRobert Mustacchi 	if (hw->mac.type >= e1000_pchlan)
515375eba5b6SRobert Mustacchi 		reg |= E1000_CTRL_EXT_PHYPDEN;
515475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL_EXT, reg);
515575eba5b6SRobert Mustacchi 
515675eba5b6SRobert Mustacchi 	/* Transmit Descriptor Control 0 */
515775eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TXDCTL(0));
515875eba5b6SRobert Mustacchi 	reg |= (1 << 22);
515975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(0), reg);
516075eba5b6SRobert Mustacchi 
516175eba5b6SRobert Mustacchi 	/* Transmit Descriptor Control 1 */
516275eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TXDCTL(1));
516375eba5b6SRobert Mustacchi 	reg |= (1 << 22);
516475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TXDCTL(1), reg);
516575eba5b6SRobert Mustacchi 
516675eba5b6SRobert Mustacchi 	/* Transmit Arbitration Control 0 */
516775eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TARC(0));
516875eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_ich8lan)
516975eba5b6SRobert Mustacchi 		reg |= (1 << 28) | (1 << 29);
517075eba5b6SRobert Mustacchi 	reg |= (1 << 23) | (1 << 24) | (1 << 26) | (1 << 27);
517175eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TARC(0), reg);
517275eba5b6SRobert Mustacchi 
517375eba5b6SRobert Mustacchi 	/* Transmit Arbitration Control 1 */
517475eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_TARC(1));
517575eba5b6SRobert Mustacchi 	if (E1000_READ_REG(hw, E1000_TCTL) & E1000_TCTL_MULR)
517675eba5b6SRobert Mustacchi 		reg &= ~(1 << 28);
517775eba5b6SRobert Mustacchi 	else
517875eba5b6SRobert Mustacchi 		reg |= (1 << 28);
517975eba5b6SRobert Mustacchi 	reg |= (1 << 24) | (1 << 26) | (1 << 30);
518075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_TARC(1), reg);
518175eba5b6SRobert Mustacchi 
518275eba5b6SRobert Mustacchi 	/* Device Status */
518375eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_ich8lan) {
518475eba5b6SRobert Mustacchi 		reg = E1000_READ_REG(hw, E1000_STATUS);
518575eba5b6SRobert Mustacchi 		reg &= ~(1UL << 31);
518675eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_STATUS, reg);
518775eba5b6SRobert Mustacchi 	}
518875eba5b6SRobert Mustacchi 
518975eba5b6SRobert Mustacchi 	/* work-around descriptor data corruption issue during nfs v2 udp
519075eba5b6SRobert Mustacchi 	 * traffic, just disable the nfs filtering capability
519175eba5b6SRobert Mustacchi 	 */
519275eba5b6SRobert Mustacchi 	reg = E1000_READ_REG(hw, E1000_RFCTL);
519375eba5b6SRobert Mustacchi 	reg |= (E1000_RFCTL_NFSW_DIS | E1000_RFCTL_NFSR_DIS);
5194c124a83eSRobert Mustacchi 
519575eba5b6SRobert Mustacchi 	/* Disable IPv6 extension header parsing because some malformed
519675eba5b6SRobert Mustacchi 	 * IPv6 headers can hang the Rx.
519775eba5b6SRobert Mustacchi 	 */
519875eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_ich8lan)
519975eba5b6SRobert Mustacchi 		reg |= (E1000_RFCTL_IPV6_EX_DIS | E1000_RFCTL_NEW_IPV6_EXT_DIS);
520075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_RFCTL, reg);
520175eba5b6SRobert Mustacchi 
520275eba5b6SRobert Mustacchi 	/* Enable ECC on Lynxpoint */
5203*42cc51e0SRobert Mustacchi 	if ((hw->mac.type == e1000_pch_lpt) ||
5204*42cc51e0SRobert Mustacchi 	    (hw->mac.type == e1000_pch_spt)) {
520575eba5b6SRobert Mustacchi 		reg = E1000_READ_REG(hw, E1000_PBECCSTS);
520675eba5b6SRobert Mustacchi 		reg |= E1000_PBECCSTS_ECC_ENABLE;
520775eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PBECCSTS, reg);
520875eba5b6SRobert Mustacchi 
520975eba5b6SRobert Mustacchi 		reg = E1000_READ_REG(hw, E1000_CTRL);
521075eba5b6SRobert Mustacchi 		reg |= E1000_CTRL_MEHE;
521175eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_CTRL, reg);
521275eba5b6SRobert Mustacchi 	}
521375eba5b6SRobert Mustacchi 
521475eba5b6SRobert Mustacchi 	return;
521575eba5b6SRobert Mustacchi }
521675eba5b6SRobert Mustacchi 
521775eba5b6SRobert Mustacchi /**
521875eba5b6SRobert Mustacchi  *  e1000_setup_link_ich8lan - Setup flow control and link settings
521975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
522075eba5b6SRobert Mustacchi  *
522175eba5b6SRobert Mustacchi  *  Determines which flow control settings to use, then configures flow
522275eba5b6SRobert Mustacchi  *  control.  Calls the appropriate media-specific link configuration
522375eba5b6SRobert Mustacchi  *  function.  Assuming the adapter has a valid link partner, a valid link
522475eba5b6SRobert Mustacchi  *  should be established.  Assumes the hardware has previously been reset
522575eba5b6SRobert Mustacchi  *  and the transmitter and receiver are not enabled.
522675eba5b6SRobert Mustacchi  **/
522775eba5b6SRobert Mustacchi static s32 e1000_setup_link_ich8lan(struct e1000_hw *hw)
522875eba5b6SRobert Mustacchi {
522975eba5b6SRobert Mustacchi 	s32 ret_val;
523075eba5b6SRobert Mustacchi 
523175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_setup_link_ich8lan");
523275eba5b6SRobert Mustacchi 
523375eba5b6SRobert Mustacchi 	if (hw->phy.ops.check_reset_block(hw))
523475eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
523575eba5b6SRobert Mustacchi 
523675eba5b6SRobert Mustacchi 	/* ICH parts do not have a word in the NVM to determine
523775eba5b6SRobert Mustacchi 	 * the default flow control setting, so we explicitly
523875eba5b6SRobert Mustacchi 	 * set it to full.
523975eba5b6SRobert Mustacchi 	 */
524075eba5b6SRobert Mustacchi 	if (hw->fc.requested_mode == e1000_fc_default)
524175eba5b6SRobert Mustacchi 		hw->fc.requested_mode = e1000_fc_full;
524275eba5b6SRobert Mustacchi 
524375eba5b6SRobert Mustacchi 	/* Save off the requested flow control mode for use later.  Depending
524475eba5b6SRobert Mustacchi 	 * on the link partner's capabilities, we may or may not use this mode.
524575eba5b6SRobert Mustacchi 	 */
524675eba5b6SRobert Mustacchi 	hw->fc.current_mode = hw->fc.requested_mode;
524775eba5b6SRobert Mustacchi 
524875eba5b6SRobert Mustacchi 	DEBUGOUT1("After fix-ups FlowControl is now = %x\n",
524975eba5b6SRobert Mustacchi 		hw->fc.current_mode);
525075eba5b6SRobert Mustacchi 
525175eba5b6SRobert Mustacchi 	/* Continue to configure the copper link. */
525275eba5b6SRobert Mustacchi 	ret_val = hw->mac.ops.setup_physical_interface(hw);
525375eba5b6SRobert Mustacchi 	if (ret_val)
525475eba5b6SRobert Mustacchi 		return ret_val;
525575eba5b6SRobert Mustacchi 
525675eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_FCTTV, hw->fc.pause_time);
525775eba5b6SRobert Mustacchi 	if ((hw->phy.type == e1000_phy_82578) ||
525875eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_82579) ||
525975eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_i217) ||
526075eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_82577)) {
526175eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_FCRTV_PCH, hw->fc.refresh_time);
526275eba5b6SRobert Mustacchi 
526375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw,
526475eba5b6SRobert Mustacchi 					     PHY_REG(BM_PORT_CTRL_PAGE, 27),
526575eba5b6SRobert Mustacchi 					     hw->fc.pause_time);
526675eba5b6SRobert Mustacchi 		if (ret_val)
526775eba5b6SRobert Mustacchi 			return ret_val;
526875eba5b6SRobert Mustacchi 	}
526975eba5b6SRobert Mustacchi 
527075eba5b6SRobert Mustacchi 	return e1000_set_fc_watermarks_generic(hw);
527175eba5b6SRobert Mustacchi }
527275eba5b6SRobert Mustacchi 
527375eba5b6SRobert Mustacchi /**
527475eba5b6SRobert Mustacchi  *  e1000_setup_copper_link_ich8lan - Configure MAC/PHY interface
527575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
527675eba5b6SRobert Mustacchi  *
527775eba5b6SRobert Mustacchi  *  Configures the kumeran interface to the PHY to wait the appropriate time
527875eba5b6SRobert Mustacchi  *  when polling the PHY, then call the generic setup_copper_link to finish
527975eba5b6SRobert Mustacchi  *  configuring the copper link.
528075eba5b6SRobert Mustacchi  **/
528175eba5b6SRobert Mustacchi static s32 e1000_setup_copper_link_ich8lan(struct e1000_hw *hw)
528275eba5b6SRobert Mustacchi {
528375eba5b6SRobert Mustacchi 	u32 ctrl;
528475eba5b6SRobert Mustacchi 	s32 ret_val;
528575eba5b6SRobert Mustacchi 	u16 reg_data;
528675eba5b6SRobert Mustacchi 
528775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_setup_copper_link_ich8lan");
528875eba5b6SRobert Mustacchi 
528975eba5b6SRobert Mustacchi 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
529075eba5b6SRobert Mustacchi 	ctrl |= E1000_CTRL_SLU;
529175eba5b6SRobert Mustacchi 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
529275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
529375eba5b6SRobert Mustacchi 
529475eba5b6SRobert Mustacchi 	/* Set the mac to wait the maximum time between each iteration
529575eba5b6SRobert Mustacchi 	 * and increase the max iterations when polling the phy;
529675eba5b6SRobert Mustacchi 	 * this fixes erroneous timeouts at 10Mbps.
529775eba5b6SRobert Mustacchi 	 */
529875eba5b6SRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_TIMEOUTS,
529975eba5b6SRobert Mustacchi 					       0xFFFF);
530075eba5b6SRobert Mustacchi 	if (ret_val)
530175eba5b6SRobert Mustacchi 		return ret_val;
530275eba5b6SRobert Mustacchi 	ret_val = e1000_read_kmrn_reg_generic(hw,
530375eba5b6SRobert Mustacchi 					      E1000_KMRNCTRLSTA_INBAND_PARAM,
530475eba5b6SRobert Mustacchi 					      &reg_data);
530575eba5b6SRobert Mustacchi 	if (ret_val)
530675eba5b6SRobert Mustacchi 		return ret_val;
530775eba5b6SRobert Mustacchi 	reg_data |= 0x3F;
530875eba5b6SRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_generic(hw,
530975eba5b6SRobert Mustacchi 					       E1000_KMRNCTRLSTA_INBAND_PARAM,
531075eba5b6SRobert Mustacchi 					       reg_data);
531175eba5b6SRobert Mustacchi 	if (ret_val)
531275eba5b6SRobert Mustacchi 		return ret_val;
531375eba5b6SRobert Mustacchi 
531475eba5b6SRobert Mustacchi 	switch (hw->phy.type) {
531575eba5b6SRobert Mustacchi 	case e1000_phy_igp_3:
531675eba5b6SRobert Mustacchi 		ret_val = e1000_copper_link_setup_igp(hw);
531775eba5b6SRobert Mustacchi 		if (ret_val)
531875eba5b6SRobert Mustacchi 			return ret_val;
531975eba5b6SRobert Mustacchi 		break;
532075eba5b6SRobert Mustacchi 	case e1000_phy_bm:
532175eba5b6SRobert Mustacchi 	case e1000_phy_82578:
532275eba5b6SRobert Mustacchi 		ret_val = e1000_copper_link_setup_m88(hw);
532375eba5b6SRobert Mustacchi 		if (ret_val)
532475eba5b6SRobert Mustacchi 			return ret_val;
532575eba5b6SRobert Mustacchi 		break;
532675eba5b6SRobert Mustacchi 	case e1000_phy_82577:
532775eba5b6SRobert Mustacchi 	case e1000_phy_82579:
532875eba5b6SRobert Mustacchi 		ret_val = e1000_copper_link_setup_82577(hw);
532975eba5b6SRobert Mustacchi 		if (ret_val)
533075eba5b6SRobert Mustacchi 			return ret_val;
533175eba5b6SRobert Mustacchi 		break;
533275eba5b6SRobert Mustacchi 	case e1000_phy_ife:
533375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, IFE_PHY_MDIX_CONTROL,
533475eba5b6SRobert Mustacchi 					       &reg_data);
533575eba5b6SRobert Mustacchi 		if (ret_val)
533675eba5b6SRobert Mustacchi 			return ret_val;
533775eba5b6SRobert Mustacchi 
533875eba5b6SRobert Mustacchi 		reg_data &= ~IFE_PMC_AUTO_MDIX;
533975eba5b6SRobert Mustacchi 
534075eba5b6SRobert Mustacchi 		switch (hw->phy.mdix) {
534175eba5b6SRobert Mustacchi 		case 1:
534275eba5b6SRobert Mustacchi 			reg_data &= ~IFE_PMC_FORCE_MDIX;
534375eba5b6SRobert Mustacchi 			break;
534475eba5b6SRobert Mustacchi 		case 2:
534575eba5b6SRobert Mustacchi 			reg_data |= IFE_PMC_FORCE_MDIX;
534675eba5b6SRobert Mustacchi 			break;
534775eba5b6SRobert Mustacchi 		case 0:
534875eba5b6SRobert Mustacchi 		default:
534975eba5b6SRobert Mustacchi 			reg_data |= IFE_PMC_AUTO_MDIX;
535075eba5b6SRobert Mustacchi 			break;
535175eba5b6SRobert Mustacchi 		}
535275eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.write_reg(hw, IFE_PHY_MDIX_CONTROL,
535375eba5b6SRobert Mustacchi 						reg_data);
535475eba5b6SRobert Mustacchi 		if (ret_val)
535575eba5b6SRobert Mustacchi 			return ret_val;
535675eba5b6SRobert Mustacchi 		break;
535775eba5b6SRobert Mustacchi 	default:
535875eba5b6SRobert Mustacchi 		break;
535975eba5b6SRobert Mustacchi 	}
536075eba5b6SRobert Mustacchi 
536175eba5b6SRobert Mustacchi 	return e1000_setup_copper_link_generic(hw);
536275eba5b6SRobert Mustacchi }
536375eba5b6SRobert Mustacchi 
536475eba5b6SRobert Mustacchi /**
536575eba5b6SRobert Mustacchi  *  e1000_setup_copper_link_pch_lpt - Configure MAC/PHY interface
536675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
536775eba5b6SRobert Mustacchi  *
536875eba5b6SRobert Mustacchi  *  Calls the PHY specific link setup function and then calls the
536975eba5b6SRobert Mustacchi  *  generic setup_copper_link to finish configuring the link for
537075eba5b6SRobert Mustacchi  *  Lynxpoint PCH devices
537175eba5b6SRobert Mustacchi  **/
537275eba5b6SRobert Mustacchi static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw)
537375eba5b6SRobert Mustacchi {
537475eba5b6SRobert Mustacchi 	u32 ctrl;
537575eba5b6SRobert Mustacchi 	s32 ret_val;
537675eba5b6SRobert Mustacchi 
537775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_setup_copper_link_pch_lpt");
537875eba5b6SRobert Mustacchi 
537975eba5b6SRobert Mustacchi 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
538075eba5b6SRobert Mustacchi 	ctrl |= E1000_CTRL_SLU;
538175eba5b6SRobert Mustacchi 	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
538275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
538375eba5b6SRobert Mustacchi 
538475eba5b6SRobert Mustacchi 	ret_val = e1000_copper_link_setup_82577(hw);
538575eba5b6SRobert Mustacchi 	if (ret_val)
538675eba5b6SRobert Mustacchi 		return ret_val;
538775eba5b6SRobert Mustacchi 
538875eba5b6SRobert Mustacchi 	return e1000_setup_copper_link_generic(hw);
538975eba5b6SRobert Mustacchi }
539075eba5b6SRobert Mustacchi 
539175eba5b6SRobert Mustacchi /**
539275eba5b6SRobert Mustacchi  *  e1000_get_link_up_info_ich8lan - Get current link speed and duplex
539375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
539475eba5b6SRobert Mustacchi  *  @speed: pointer to store current link speed
539575eba5b6SRobert Mustacchi  *  @duplex: pointer to store the current link duplex
539675eba5b6SRobert Mustacchi  *
539775eba5b6SRobert Mustacchi  *  Calls the generic get_speed_and_duplex to retrieve the current link
539875eba5b6SRobert Mustacchi  *  information and then calls the Kumeran lock loss workaround for links at
539975eba5b6SRobert Mustacchi  *  gigabit speeds.
540075eba5b6SRobert Mustacchi  **/
540175eba5b6SRobert Mustacchi static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
540275eba5b6SRobert Mustacchi 					  u16 *duplex)
540375eba5b6SRobert Mustacchi {
540475eba5b6SRobert Mustacchi 	s32 ret_val;
540575eba5b6SRobert Mustacchi 
540675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_link_up_info_ich8lan");
540775eba5b6SRobert Mustacchi 
540875eba5b6SRobert Mustacchi 	ret_val = e1000_get_speed_and_duplex_copper_generic(hw, speed, duplex);
540975eba5b6SRobert Mustacchi 	if (ret_val)
541075eba5b6SRobert Mustacchi 		return ret_val;
541175eba5b6SRobert Mustacchi 
541275eba5b6SRobert Mustacchi 	if ((hw->mac.type == e1000_ich8lan) &&
541375eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_igp_3) &&
541475eba5b6SRobert Mustacchi 	    (*speed == SPEED_1000)) {
541575eba5b6SRobert Mustacchi 		ret_val = e1000_kmrn_lock_loss_workaround_ich8lan(hw);
541675eba5b6SRobert Mustacchi 	}
541775eba5b6SRobert Mustacchi 
541875eba5b6SRobert Mustacchi 	return ret_val;
541975eba5b6SRobert Mustacchi }
542075eba5b6SRobert Mustacchi 
542175eba5b6SRobert Mustacchi /**
542275eba5b6SRobert Mustacchi  *  e1000_kmrn_lock_loss_workaround_ich8lan - Kumeran workaround
542375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
542475eba5b6SRobert Mustacchi  *
542575eba5b6SRobert Mustacchi  *  Work-around for 82566 Kumeran PCS lock loss:
542675eba5b6SRobert Mustacchi  *  On link status change (i.e. PCI reset, speed change) and link is up and
542775eba5b6SRobert Mustacchi  *  speed is gigabit-
542875eba5b6SRobert Mustacchi  *    0) if workaround is optionally disabled do nothing
542975eba5b6SRobert Mustacchi  *    1) wait 1ms for Kumeran link to come up
543075eba5b6SRobert Mustacchi  *    2) check Kumeran Diagnostic register PCS lock loss bit
543175eba5b6SRobert Mustacchi  *    3) if not set the link is locked (all is good), otherwise...
543275eba5b6SRobert Mustacchi  *    4) reset the PHY
543375eba5b6SRobert Mustacchi  *    5) repeat up to 10 times
543475eba5b6SRobert Mustacchi  *  Note: this is only called for IGP3 copper when speed is 1gb.
543575eba5b6SRobert Mustacchi  **/
543675eba5b6SRobert Mustacchi static s32 e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw)
543775eba5b6SRobert Mustacchi {
543875eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
543975eba5b6SRobert Mustacchi 	u32 phy_ctrl;
544075eba5b6SRobert Mustacchi 	s32 ret_val;
544175eba5b6SRobert Mustacchi 	u16 i, data;
544275eba5b6SRobert Mustacchi 	bool link;
544375eba5b6SRobert Mustacchi 
544475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_kmrn_lock_loss_workaround_ich8lan");
544575eba5b6SRobert Mustacchi 
544675eba5b6SRobert Mustacchi 	if (!dev_spec->kmrn_lock_loss_workaround_enabled)
544775eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
544875eba5b6SRobert Mustacchi 
544975eba5b6SRobert Mustacchi 	/* Make sure link is up before proceeding.  If not just return.
545075eba5b6SRobert Mustacchi 	 * Attempting this while link is negotiating fouled up link
545175eba5b6SRobert Mustacchi 	 * stability
545275eba5b6SRobert Mustacchi 	 */
545375eba5b6SRobert Mustacchi 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
545475eba5b6SRobert Mustacchi 	if (!link)
545575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
545675eba5b6SRobert Mustacchi 
545775eba5b6SRobert Mustacchi 	for (i = 0; i < 10; i++) {
545875eba5b6SRobert Mustacchi 		/* read once to clear */
545975eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data);
546075eba5b6SRobert Mustacchi 		if (ret_val)
546175eba5b6SRobert Mustacchi 			return ret_val;
546275eba5b6SRobert Mustacchi 		/* and again to get new status */
546375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, IGP3_KMRN_DIAG, &data);
546475eba5b6SRobert Mustacchi 		if (ret_val)
546575eba5b6SRobert Mustacchi 			return ret_val;
546675eba5b6SRobert Mustacchi 
546775eba5b6SRobert Mustacchi 		/* check for PCS lock */
546875eba5b6SRobert Mustacchi 		if (!(data & IGP3_KMRN_DIAG_PCS_LOCK_LOSS))
546975eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
547075eba5b6SRobert Mustacchi 
547175eba5b6SRobert Mustacchi 		/* Issue PHY reset */
547275eba5b6SRobert Mustacchi 		hw->phy.ops.reset(hw);
547375eba5b6SRobert Mustacchi 		msec_delay_irq(5);
547475eba5b6SRobert Mustacchi 	}
547575eba5b6SRobert Mustacchi 	/* Disable GigE link negotiation */
547675eba5b6SRobert Mustacchi 	phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
547775eba5b6SRobert Mustacchi 	phy_ctrl |= (E1000_PHY_CTRL_GBE_DISABLE |
547875eba5b6SRobert Mustacchi 		     E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
547975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
548075eba5b6SRobert Mustacchi 
548175eba5b6SRobert Mustacchi 	/* Call gig speed drop workaround on Gig disable before accessing
548275eba5b6SRobert Mustacchi 	 * any PHY registers
548375eba5b6SRobert Mustacchi 	 */
548475eba5b6SRobert Mustacchi 	e1000_gig_downshift_workaround_ich8lan(hw);
548575eba5b6SRobert Mustacchi 
548675eba5b6SRobert Mustacchi 	/* unable to acquire PCS lock */
548775eba5b6SRobert Mustacchi 	return -E1000_ERR_PHY;
548875eba5b6SRobert Mustacchi }
548975eba5b6SRobert Mustacchi 
549075eba5b6SRobert Mustacchi /**
549175eba5b6SRobert Mustacchi  *  e1000_set_kmrn_lock_loss_workaround_ich8lan - Set Kumeran workaround state
549275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
549375eba5b6SRobert Mustacchi  *  @state: boolean value used to set the current Kumeran workaround state
549475eba5b6SRobert Mustacchi  *
549575eba5b6SRobert Mustacchi  *  If ICH8, set the current Kumeran workaround state (enabled - TRUE
549675eba5b6SRobert Mustacchi  *  /disabled - FALSE).
549775eba5b6SRobert Mustacchi  **/
549875eba5b6SRobert Mustacchi void e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw *hw,
549975eba5b6SRobert Mustacchi 						 bool state)
550075eba5b6SRobert Mustacchi {
550175eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
550275eba5b6SRobert Mustacchi 
550375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_kmrn_lock_loss_workaround_ich8lan");
550475eba5b6SRobert Mustacchi 
550575eba5b6SRobert Mustacchi 	if (hw->mac.type != e1000_ich8lan) {
550675eba5b6SRobert Mustacchi 		DEBUGOUT("Workaround applies to ICH8 only.\n");
550775eba5b6SRobert Mustacchi 		return;
550875eba5b6SRobert Mustacchi 	}
550975eba5b6SRobert Mustacchi 
551075eba5b6SRobert Mustacchi 	dev_spec->kmrn_lock_loss_workaround_enabled = state;
551175eba5b6SRobert Mustacchi 
551275eba5b6SRobert Mustacchi 	return;
551375eba5b6SRobert Mustacchi }
551475eba5b6SRobert Mustacchi 
551575eba5b6SRobert Mustacchi /**
551675eba5b6SRobert Mustacchi  *  e1000_ipg3_phy_powerdown_workaround_ich8lan - Power down workaround on D3
551775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
551875eba5b6SRobert Mustacchi  *
551975eba5b6SRobert Mustacchi  *  Workaround for 82566 power-down on D3 entry:
552075eba5b6SRobert Mustacchi  *    1) disable gigabit link
552175eba5b6SRobert Mustacchi  *    2) write VR power-down enable
552275eba5b6SRobert Mustacchi  *    3) read it back
552375eba5b6SRobert Mustacchi  *  Continue if successful, else issue LCD reset and repeat
552475eba5b6SRobert Mustacchi  **/
552575eba5b6SRobert Mustacchi void e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw *hw)
552675eba5b6SRobert Mustacchi {
552775eba5b6SRobert Mustacchi 	u32 reg;
552875eba5b6SRobert Mustacchi 	u16 data;
552975eba5b6SRobert Mustacchi 	u8  retry = 0;
553075eba5b6SRobert Mustacchi 
553175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_igp3_phy_powerdown_workaround_ich8lan");
553275eba5b6SRobert Mustacchi 
553375eba5b6SRobert Mustacchi 	if (hw->phy.type != e1000_phy_igp_3)
553475eba5b6SRobert Mustacchi 		return;
553575eba5b6SRobert Mustacchi 
553675eba5b6SRobert Mustacchi 	/* Try the workaround twice (if needed) */
553775eba5b6SRobert Mustacchi 	do {
553875eba5b6SRobert Mustacchi 		/* Disable link */
553975eba5b6SRobert Mustacchi 		reg = E1000_READ_REG(hw, E1000_PHY_CTRL);
554075eba5b6SRobert Mustacchi 		reg |= (E1000_PHY_CTRL_GBE_DISABLE |
554175eba5b6SRobert Mustacchi 			E1000_PHY_CTRL_NOND0A_GBE_DISABLE);
554275eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_PHY_CTRL, reg);
554375eba5b6SRobert Mustacchi 
554475eba5b6SRobert Mustacchi 		/* Call gig speed drop workaround on Gig disable before
554575eba5b6SRobert Mustacchi 		 * accessing any PHY registers
554675eba5b6SRobert Mustacchi 		 */
554775eba5b6SRobert Mustacchi 		if (hw->mac.type == e1000_ich8lan)
554875eba5b6SRobert Mustacchi 			e1000_gig_downshift_workaround_ich8lan(hw);
554975eba5b6SRobert Mustacchi 
555075eba5b6SRobert Mustacchi 		/* Write VR power-down enable */
555175eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data);
555275eba5b6SRobert Mustacchi 		data &= ~IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
555375eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg(hw, IGP3_VR_CTRL,
555475eba5b6SRobert Mustacchi 				      data | IGP3_VR_CTRL_MODE_SHUTDOWN);
555575eba5b6SRobert Mustacchi 
555675eba5b6SRobert Mustacchi 		/* Read it back and test */
555775eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg(hw, IGP3_VR_CTRL, &data);
555875eba5b6SRobert Mustacchi 		data &= IGP3_VR_CTRL_DEV_POWERDOWN_MODE_MASK;
555975eba5b6SRobert Mustacchi 		if ((data == IGP3_VR_CTRL_MODE_SHUTDOWN) || retry)
556075eba5b6SRobert Mustacchi 			break;
556175eba5b6SRobert Mustacchi 
556275eba5b6SRobert Mustacchi 		/* Issue PHY reset and repeat at most one more time */
556375eba5b6SRobert Mustacchi 		reg = E1000_READ_REG(hw, E1000_CTRL);
556475eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_CTRL, reg | E1000_CTRL_PHY_RST);
556575eba5b6SRobert Mustacchi 		retry++;
556675eba5b6SRobert Mustacchi 	} while (retry);
556775eba5b6SRobert Mustacchi }
556875eba5b6SRobert Mustacchi 
556975eba5b6SRobert Mustacchi /**
557075eba5b6SRobert Mustacchi  *  e1000_gig_downshift_workaround_ich8lan - WoL from S5 stops working
557175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
557275eba5b6SRobert Mustacchi  *
557375eba5b6SRobert Mustacchi  *  Steps to take when dropping from 1Gb/s (eg. link cable removal (LSC),
557475eba5b6SRobert Mustacchi  *  LPLU, Gig disable, MDIC PHY reset):
557575eba5b6SRobert Mustacchi  *    1) Set Kumeran Near-end loopback
557675eba5b6SRobert Mustacchi  *    2) Clear Kumeran Near-end loopback
557775eba5b6SRobert Mustacchi  *  Should only be called for ICH8[m] devices with any 1G Phy.
557875eba5b6SRobert Mustacchi  **/
557975eba5b6SRobert Mustacchi void e1000_gig_downshift_workaround_ich8lan(struct e1000_hw *hw)
558075eba5b6SRobert Mustacchi {
558175eba5b6SRobert Mustacchi 	s32 ret_val;
558275eba5b6SRobert Mustacchi 	u16 reg_data;
558375eba5b6SRobert Mustacchi 
558475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_gig_downshift_workaround_ich8lan");
558575eba5b6SRobert Mustacchi 
558675eba5b6SRobert Mustacchi 	if ((hw->mac.type != e1000_ich8lan) ||
558775eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_ife))
558875eba5b6SRobert Mustacchi 		return;
558975eba5b6SRobert Mustacchi 
559075eba5b6SRobert Mustacchi 	ret_val = e1000_read_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
559175eba5b6SRobert Mustacchi 					      &reg_data);
559275eba5b6SRobert Mustacchi 	if (ret_val)
559375eba5b6SRobert Mustacchi 		return;
559475eba5b6SRobert Mustacchi 	reg_data |= E1000_KMRNCTRLSTA_DIAG_NELPBK;
559575eba5b6SRobert Mustacchi 	ret_val = e1000_write_kmrn_reg_generic(hw,
559675eba5b6SRobert Mustacchi 					       E1000_KMRNCTRLSTA_DIAG_OFFSET,
559775eba5b6SRobert Mustacchi 					       reg_data);
559875eba5b6SRobert Mustacchi 	if (ret_val)
559975eba5b6SRobert Mustacchi 		return;
560075eba5b6SRobert Mustacchi 	reg_data &= ~E1000_KMRNCTRLSTA_DIAG_NELPBK;
560175eba5b6SRobert Mustacchi 	e1000_write_kmrn_reg_generic(hw, E1000_KMRNCTRLSTA_DIAG_OFFSET,
560275eba5b6SRobert Mustacchi 				     reg_data);
560375eba5b6SRobert Mustacchi }
560475eba5b6SRobert Mustacchi 
560575eba5b6SRobert Mustacchi /**
560675eba5b6SRobert Mustacchi  *  e1000_suspend_workarounds_ich8lan - workarounds needed during S0->Sx
560775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
560875eba5b6SRobert Mustacchi  *
560975eba5b6SRobert Mustacchi  *  During S0 to Sx transition, it is possible the link remains at gig
561075eba5b6SRobert Mustacchi  *  instead of negotiating to a lower speed.  Before going to Sx, set
561175eba5b6SRobert Mustacchi  *  'Gig Disable' to force link speed negotiation to a lower speed based on
561275eba5b6SRobert Mustacchi  *  the LPLU setting in the NVM or custom setting.  For PCH and newer parts,
561375eba5b6SRobert Mustacchi  *  the OEM bits PHY register (LED, GbE disable and LPLU configurations) also
561475eba5b6SRobert Mustacchi  *  needs to be written.
561575eba5b6SRobert Mustacchi  *  Parts that support (and are linked to a partner which support) EEE in
561675eba5b6SRobert Mustacchi  *  100Mbps should disable LPLU since 100Mbps w/ EEE requires less power
561775eba5b6SRobert Mustacchi  *  than 10Mbps w/o EEE.
561875eba5b6SRobert Mustacchi  **/
561975eba5b6SRobert Mustacchi void e1000_suspend_workarounds_ich8lan(struct e1000_hw *hw)
562075eba5b6SRobert Mustacchi {
562175eba5b6SRobert Mustacchi 	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
562275eba5b6SRobert Mustacchi 	u32 phy_ctrl;
562375eba5b6SRobert Mustacchi 	s32 ret_val;
562475eba5b6SRobert Mustacchi 
562575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_suspend_workarounds_ich8lan");
562675eba5b6SRobert Mustacchi 
562775eba5b6SRobert Mustacchi 	phy_ctrl = E1000_READ_REG(hw, E1000_PHY_CTRL);
562875eba5b6SRobert Mustacchi 	phy_ctrl |= E1000_PHY_CTRL_GBE_DISABLE;
562975eba5b6SRobert Mustacchi 
563075eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_i217) {
563175eba5b6SRobert Mustacchi 		u16 phy_reg, device_id = hw->device_id;
563275eba5b6SRobert Mustacchi 
563375eba5b6SRobert Mustacchi 		if ((device_id == E1000_DEV_ID_PCH_LPTLP_I218_LM) ||
5634c124a83eSRobert Mustacchi 		    (device_id == E1000_DEV_ID_PCH_LPTLP_I218_V) ||
5635c124a83eSRobert Mustacchi 		    (device_id == E1000_DEV_ID_PCH_I218_LM3) ||
5636*42cc51e0SRobert Mustacchi 		    (device_id == E1000_DEV_ID_PCH_I218_V3) ||
5637*42cc51e0SRobert Mustacchi 		    (hw->mac.type == e1000_pch_spt)) {
563875eba5b6SRobert Mustacchi 			u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
563975eba5b6SRobert Mustacchi 
564075eba5b6SRobert Mustacchi 			E1000_WRITE_REG(hw, E1000_FEXTNVM6,
564175eba5b6SRobert Mustacchi 					fextnvm6 & ~E1000_FEXTNVM6_REQ_PLL_CLK);
564275eba5b6SRobert Mustacchi 		}
564375eba5b6SRobert Mustacchi 
564475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
564575eba5b6SRobert Mustacchi 		if (ret_val)
564675eba5b6SRobert Mustacchi 			goto out;
564775eba5b6SRobert Mustacchi 
564875eba5b6SRobert Mustacchi 		if (!dev_spec->eee_disable) {
564975eba5b6SRobert Mustacchi 			u16 eee_advert;
565075eba5b6SRobert Mustacchi 
565175eba5b6SRobert Mustacchi 			ret_val =
565275eba5b6SRobert Mustacchi 			    e1000_read_emi_reg_locked(hw,
565375eba5b6SRobert Mustacchi 						      I217_EEE_ADVERTISEMENT,
565475eba5b6SRobert Mustacchi 						      &eee_advert);
565575eba5b6SRobert Mustacchi 			if (ret_val)
565675eba5b6SRobert Mustacchi 				goto release;
565775eba5b6SRobert Mustacchi 
565875eba5b6SRobert Mustacchi 			/* Disable LPLU if both link partners support 100BaseT
565975eba5b6SRobert Mustacchi 			 * EEE and 100Full is advertised on both ends of the
5660c124a83eSRobert Mustacchi 			 * link, and enable Auto Enable LPI since there will
5661c124a83eSRobert Mustacchi 			 * be no driver to enable LPI while in Sx.
566275eba5b6SRobert Mustacchi 			 */
566375eba5b6SRobert Mustacchi 			if ((eee_advert & I82579_EEE_100_SUPPORTED) &&
566475eba5b6SRobert Mustacchi 			    (dev_spec->eee_lp_ability &
566575eba5b6SRobert Mustacchi 			     I82579_EEE_100_SUPPORTED) &&
5666c124a83eSRobert Mustacchi 			    (hw->phy.autoneg_advertised & ADVERTISE_100_FULL)) {
566775eba5b6SRobert Mustacchi 				phy_ctrl &= ~(E1000_PHY_CTRL_D0A_LPLU |
566875eba5b6SRobert Mustacchi 					      E1000_PHY_CTRL_NOND0A_LPLU);
5669c124a83eSRobert Mustacchi 
5670c124a83eSRobert Mustacchi 				/* Set Auto Enable LPI after link up */
5671c124a83eSRobert Mustacchi 				hw->phy.ops.read_reg_locked(hw,
5672c124a83eSRobert Mustacchi 							    I217_LPI_GPIO_CTRL,
5673c124a83eSRobert Mustacchi 							    &phy_reg);
5674c124a83eSRobert Mustacchi 				phy_reg |= I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
5675c124a83eSRobert Mustacchi 				hw->phy.ops.write_reg_locked(hw,
5676c124a83eSRobert Mustacchi 							     I217_LPI_GPIO_CTRL,
5677c124a83eSRobert Mustacchi 							     phy_reg);
5678c124a83eSRobert Mustacchi 			}
567975eba5b6SRobert Mustacchi 		}
568075eba5b6SRobert Mustacchi 
568175eba5b6SRobert Mustacchi 		/* For i217 Intel Rapid Start Technology support,
568275eba5b6SRobert Mustacchi 		 * when the system is going into Sx and no manageability engine
568375eba5b6SRobert Mustacchi 		 * is present, the driver must configure proxy to reset only on
568475eba5b6SRobert Mustacchi 		 * power good.  LPI (Low Power Idle) state must also reset only
568575eba5b6SRobert Mustacchi 		 * on power good, as well as the MTA (Multicast table array).
568675eba5b6SRobert Mustacchi 		 * The SMBus release must also be disabled on LCD reset.
568775eba5b6SRobert Mustacchi 		 */
568875eba5b6SRobert Mustacchi 		if (!(E1000_READ_REG(hw, E1000_FWSM) &
568975eba5b6SRobert Mustacchi 		      E1000_ICH_FWSM_FW_VALID)) {
569075eba5b6SRobert Mustacchi 			/* Enable proxy to reset only on power good. */
569175eba5b6SRobert Mustacchi 			hw->phy.ops.read_reg_locked(hw, I217_PROXY_CTRL,
569275eba5b6SRobert Mustacchi 						    &phy_reg);
569375eba5b6SRobert Mustacchi 			phy_reg |= I217_PROXY_CTRL_AUTO_DISABLE;
569475eba5b6SRobert Mustacchi 			hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL,
569575eba5b6SRobert Mustacchi 						     phy_reg);
569675eba5b6SRobert Mustacchi 
569775eba5b6SRobert Mustacchi 			/* Set bit enable LPI (EEE) to reset only on
569875eba5b6SRobert Mustacchi 			 * power good.
569975eba5b6SRobert Mustacchi 			*/
570075eba5b6SRobert Mustacchi 			hw->phy.ops.read_reg_locked(hw, I217_SxCTRL, &phy_reg);
570175eba5b6SRobert Mustacchi 			phy_reg |= I217_SxCTRL_ENABLE_LPI_RESET;
570275eba5b6SRobert Mustacchi 			hw->phy.ops.write_reg_locked(hw, I217_SxCTRL, phy_reg);
570375eba5b6SRobert Mustacchi 
570475eba5b6SRobert Mustacchi 			/* Disable the SMB release on LCD reset. */
570575eba5b6SRobert Mustacchi 			hw->phy.ops.read_reg_locked(hw, I217_MEMPWR, &phy_reg);
570675eba5b6SRobert Mustacchi 			phy_reg &= ~I217_MEMPWR_DISABLE_SMB_RELEASE;
570775eba5b6SRobert Mustacchi 			hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg);
570875eba5b6SRobert Mustacchi 		}
570975eba5b6SRobert Mustacchi 
571075eba5b6SRobert Mustacchi 		/* Enable MTA to reset for Intel Rapid Start Technology
571175eba5b6SRobert Mustacchi 		 * Support
571275eba5b6SRobert Mustacchi 		 */
571375eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_locked(hw, I217_CGFREG, &phy_reg);
571475eba5b6SRobert Mustacchi 		phy_reg |= I217_CGFREG_ENABLE_MTA_RESET;
571575eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg);
571675eba5b6SRobert Mustacchi 
571775eba5b6SRobert Mustacchi release:
571875eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
571975eba5b6SRobert Mustacchi 	}
572075eba5b6SRobert Mustacchi out:
572175eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_PHY_CTRL, phy_ctrl);
572275eba5b6SRobert Mustacchi 
572375eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_ich8lan)
572475eba5b6SRobert Mustacchi 		e1000_gig_downshift_workaround_ich8lan(hw);
572575eba5b6SRobert Mustacchi 
572675eba5b6SRobert Mustacchi 	if (hw->mac.type >= e1000_pchlan) {
572775eba5b6SRobert Mustacchi 		e1000_oem_bits_config_ich8lan(hw, FALSE);
572875eba5b6SRobert Mustacchi 
572975eba5b6SRobert Mustacchi 		/* Reset PHY to activate OEM bits on 82577/8 */
573075eba5b6SRobert Mustacchi 		if (hw->mac.type == e1000_pchlan)
573175eba5b6SRobert Mustacchi 			e1000_phy_hw_reset_generic(hw);
573275eba5b6SRobert Mustacchi 
573375eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
573475eba5b6SRobert Mustacchi 		if (ret_val)
573575eba5b6SRobert Mustacchi 			return;
573675eba5b6SRobert Mustacchi 		e1000_write_smbus_addr(hw);
573775eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
573875eba5b6SRobert Mustacchi 	}
573975eba5b6SRobert Mustacchi 
574075eba5b6SRobert Mustacchi 	return;
574175eba5b6SRobert Mustacchi }
574275eba5b6SRobert Mustacchi 
574375eba5b6SRobert Mustacchi /**
574475eba5b6SRobert Mustacchi  *  e1000_resume_workarounds_pchlan - workarounds needed during Sx->S0
574575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
574675eba5b6SRobert Mustacchi  *
574775eba5b6SRobert Mustacchi  *  During Sx to S0 transitions on non-managed devices or managed devices
574875eba5b6SRobert Mustacchi  *  on which PHY resets are not blocked, if the PHY registers cannot be
574975eba5b6SRobert Mustacchi  *  accessed properly by the s/w toggle the LANPHYPC value to power cycle
575075eba5b6SRobert Mustacchi  *  the PHY.
575175eba5b6SRobert Mustacchi  *  On i217, setup Intel Rapid Start Technology.
575275eba5b6SRobert Mustacchi  **/
5753*42cc51e0SRobert Mustacchi u32 e1000_resume_workarounds_pchlan(struct e1000_hw *hw)
575475eba5b6SRobert Mustacchi {
575575eba5b6SRobert Mustacchi 	s32 ret_val;
575675eba5b6SRobert Mustacchi 
575775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_resume_workarounds_pchlan");
575875eba5b6SRobert Mustacchi 	if (hw->mac.type < e1000_pch2lan)
5759*42cc51e0SRobert Mustacchi 		return E1000_SUCCESS;
576075eba5b6SRobert Mustacchi 
576175eba5b6SRobert Mustacchi 	ret_val = e1000_init_phy_workarounds_pchlan(hw);
576275eba5b6SRobert Mustacchi 	if (ret_val) {
576375eba5b6SRobert Mustacchi 		DEBUGOUT1("Failed to init PHY flow ret_val=%d\n", ret_val);
5764*42cc51e0SRobert Mustacchi 		return ret_val;
576575eba5b6SRobert Mustacchi 	}
576675eba5b6SRobert Mustacchi 
576775eba5b6SRobert Mustacchi 	/* For i217 Intel Rapid Start Technology support when the system
576875eba5b6SRobert Mustacchi 	 * is transitioning from Sx and no manageability engine is present
576975eba5b6SRobert Mustacchi 	 * configure SMBus to restore on reset, disable proxy, and enable
577075eba5b6SRobert Mustacchi 	 * the reset on MTA (Multicast table array).
577175eba5b6SRobert Mustacchi 	 */
577275eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_i217) {
577375eba5b6SRobert Mustacchi 		u16 phy_reg;
577475eba5b6SRobert Mustacchi 
577575eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
577675eba5b6SRobert Mustacchi 		if (ret_val) {
577775eba5b6SRobert Mustacchi 			DEBUGOUT("Failed to setup iRST\n");
5778*42cc51e0SRobert Mustacchi 			return ret_val;
577975eba5b6SRobert Mustacchi 		}
578075eba5b6SRobert Mustacchi 
5781c124a83eSRobert Mustacchi 		/* Clear Auto Enable LPI after link up */
5782c124a83eSRobert Mustacchi 		hw->phy.ops.read_reg_locked(hw, I217_LPI_GPIO_CTRL, &phy_reg);
5783c124a83eSRobert Mustacchi 		phy_reg &= ~I217_LPI_GPIO_CTRL_AUTO_EN_LPI;
5784c124a83eSRobert Mustacchi 		hw->phy.ops.write_reg_locked(hw, I217_LPI_GPIO_CTRL, phy_reg);
5785c124a83eSRobert Mustacchi 
578675eba5b6SRobert Mustacchi 		if (!(E1000_READ_REG(hw, E1000_FWSM) &
578775eba5b6SRobert Mustacchi 		    E1000_ICH_FWSM_FW_VALID)) {
578875eba5b6SRobert Mustacchi 			/* Restore clear on SMB if no manageability engine
578975eba5b6SRobert Mustacchi 			 * is present
579075eba5b6SRobert Mustacchi 			 */
579175eba5b6SRobert Mustacchi 			ret_val = hw->phy.ops.read_reg_locked(hw, I217_MEMPWR,
579275eba5b6SRobert Mustacchi 							      &phy_reg);
579375eba5b6SRobert Mustacchi 			if (ret_val)
579475eba5b6SRobert Mustacchi 				goto release;
579575eba5b6SRobert Mustacchi 			phy_reg |= I217_MEMPWR_DISABLE_SMB_RELEASE;
579675eba5b6SRobert Mustacchi 			hw->phy.ops.write_reg_locked(hw, I217_MEMPWR, phy_reg);
579775eba5b6SRobert Mustacchi 
579875eba5b6SRobert Mustacchi 			/* Disable Proxy */
579975eba5b6SRobert Mustacchi 			hw->phy.ops.write_reg_locked(hw, I217_PROXY_CTRL, 0);
580075eba5b6SRobert Mustacchi 		}
580175eba5b6SRobert Mustacchi 		/* Enable reset on MTA */
580275eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg_locked(hw, I217_CGFREG,
580375eba5b6SRobert Mustacchi 						      &phy_reg);
580475eba5b6SRobert Mustacchi 		if (ret_val)
580575eba5b6SRobert Mustacchi 			goto release;
580675eba5b6SRobert Mustacchi 		phy_reg &= ~I217_CGFREG_ENABLE_MTA_RESET;
580775eba5b6SRobert Mustacchi 		hw->phy.ops.write_reg_locked(hw, I217_CGFREG, phy_reg);
580875eba5b6SRobert Mustacchi release:
580975eba5b6SRobert Mustacchi 		if (ret_val)
581075eba5b6SRobert Mustacchi 			DEBUGOUT1("Error %d in resume workarounds\n", ret_val);
581175eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
5812*42cc51e0SRobert Mustacchi 		return ret_val;
581375eba5b6SRobert Mustacchi 	}
5814*42cc51e0SRobert Mustacchi 	return E1000_SUCCESS;
581575eba5b6SRobert Mustacchi }
581675eba5b6SRobert Mustacchi 
581775eba5b6SRobert Mustacchi /**
581875eba5b6SRobert Mustacchi  *  e1000_cleanup_led_ich8lan - Restore the default LED operation
581975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
582075eba5b6SRobert Mustacchi  *
582175eba5b6SRobert Mustacchi  *  Return the LED back to the default configuration.
582275eba5b6SRobert Mustacchi  **/
582375eba5b6SRobert Mustacchi static s32 e1000_cleanup_led_ich8lan(struct e1000_hw *hw)
582475eba5b6SRobert Mustacchi {
582575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_cleanup_led_ich8lan");
582675eba5b6SRobert Mustacchi 
582775eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_ife)
582875eba5b6SRobert Mustacchi 		return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
582975eba5b6SRobert Mustacchi 					     0);
583075eba5b6SRobert Mustacchi 
583175eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_default);
583275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
583375eba5b6SRobert Mustacchi }
583475eba5b6SRobert Mustacchi 
583575eba5b6SRobert Mustacchi /**
583675eba5b6SRobert Mustacchi  *  e1000_led_on_ich8lan - Turn LEDs on
583775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
583875eba5b6SRobert Mustacchi  *
583975eba5b6SRobert Mustacchi  *  Turn on the LEDs.
584075eba5b6SRobert Mustacchi  **/
584175eba5b6SRobert Mustacchi static s32 e1000_led_on_ich8lan(struct e1000_hw *hw)
584275eba5b6SRobert Mustacchi {
584375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_led_on_ich8lan");
584475eba5b6SRobert Mustacchi 
584575eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_ife)
584675eba5b6SRobert Mustacchi 		return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
584775eba5b6SRobert Mustacchi 				(IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_ON));
584875eba5b6SRobert Mustacchi 
584975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode2);
585075eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
585175eba5b6SRobert Mustacchi }
585275eba5b6SRobert Mustacchi 
585375eba5b6SRobert Mustacchi /**
585475eba5b6SRobert Mustacchi  *  e1000_led_off_ich8lan - Turn LEDs off
585575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
585675eba5b6SRobert Mustacchi  *
585775eba5b6SRobert Mustacchi  *  Turn off the LEDs.
585875eba5b6SRobert Mustacchi  **/
585975eba5b6SRobert Mustacchi static s32 e1000_led_off_ich8lan(struct e1000_hw *hw)
586075eba5b6SRobert Mustacchi {
586175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_led_off_ich8lan");
586275eba5b6SRobert Mustacchi 
586375eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_ife)
586475eba5b6SRobert Mustacchi 		return hw->phy.ops.write_reg(hw, IFE_PHY_SPECIAL_CONTROL_LED,
586575eba5b6SRobert Mustacchi 			       (IFE_PSCL_PROBE_MODE | IFE_PSCL_PROBE_LEDS_OFF));
586675eba5b6SRobert Mustacchi 
586775eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_LEDCTL, hw->mac.ledctl_mode1);
586875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
586975eba5b6SRobert Mustacchi }
587075eba5b6SRobert Mustacchi 
587175eba5b6SRobert Mustacchi /**
587275eba5b6SRobert Mustacchi  *  e1000_setup_led_pchlan - Configures SW controllable LED
587375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
587475eba5b6SRobert Mustacchi  *
587575eba5b6SRobert Mustacchi  *  This prepares the SW controllable LED for use.
587675eba5b6SRobert Mustacchi  **/
587775eba5b6SRobert Mustacchi static s32 e1000_setup_led_pchlan(struct e1000_hw *hw)
587875eba5b6SRobert Mustacchi {
587975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_setup_led_pchlan");
588075eba5b6SRobert Mustacchi 
588175eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG,
588275eba5b6SRobert Mustacchi 				     (u16)hw->mac.ledctl_mode1);
588375eba5b6SRobert Mustacchi }
588475eba5b6SRobert Mustacchi 
588575eba5b6SRobert Mustacchi /**
588675eba5b6SRobert Mustacchi  *  e1000_cleanup_led_pchlan - Restore the default LED operation
588775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
588875eba5b6SRobert Mustacchi  *
588975eba5b6SRobert Mustacchi  *  Return the LED back to the default configuration.
589075eba5b6SRobert Mustacchi  **/
589175eba5b6SRobert Mustacchi static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw)
589275eba5b6SRobert Mustacchi {
589375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_cleanup_led_pchlan");
589475eba5b6SRobert Mustacchi 
589575eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG,
589675eba5b6SRobert Mustacchi 				     (u16)hw->mac.ledctl_default);
589775eba5b6SRobert Mustacchi }
589875eba5b6SRobert Mustacchi 
589975eba5b6SRobert Mustacchi /**
590075eba5b6SRobert Mustacchi  *  e1000_led_on_pchlan - Turn LEDs on
590175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
590275eba5b6SRobert Mustacchi  *
590375eba5b6SRobert Mustacchi  *  Turn on the LEDs.
590475eba5b6SRobert Mustacchi  **/
590575eba5b6SRobert Mustacchi static s32 e1000_led_on_pchlan(struct e1000_hw *hw)
590675eba5b6SRobert Mustacchi {
590775eba5b6SRobert Mustacchi 	u16 data = (u16)hw->mac.ledctl_mode2;
590875eba5b6SRobert Mustacchi 	u32 i, led;
590975eba5b6SRobert Mustacchi 
591075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_led_on_pchlan");
591175eba5b6SRobert Mustacchi 
591275eba5b6SRobert Mustacchi 	/* If no link, then turn LED on by setting the invert bit
591375eba5b6SRobert Mustacchi 	 * for each LED that's mode is "link_up" in ledctl_mode2.
591475eba5b6SRobert Mustacchi 	 */
591575eba5b6SRobert Mustacchi 	if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
591675eba5b6SRobert Mustacchi 		for (i = 0; i < 3; i++) {
591775eba5b6SRobert Mustacchi 			led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
591875eba5b6SRobert Mustacchi 			if ((led & E1000_PHY_LED0_MODE_MASK) !=
591975eba5b6SRobert Mustacchi 			    E1000_LEDCTL_MODE_LINK_UP)
592075eba5b6SRobert Mustacchi 				continue;
592175eba5b6SRobert Mustacchi 			if (led & E1000_PHY_LED0_IVRT)
592275eba5b6SRobert Mustacchi 				data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
592375eba5b6SRobert Mustacchi 			else
592475eba5b6SRobert Mustacchi 				data |= (E1000_PHY_LED0_IVRT << (i * 5));
592575eba5b6SRobert Mustacchi 		}
592675eba5b6SRobert Mustacchi 	}
592775eba5b6SRobert Mustacchi 
592875eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data);
592975eba5b6SRobert Mustacchi }
593075eba5b6SRobert Mustacchi 
593175eba5b6SRobert Mustacchi /**
593275eba5b6SRobert Mustacchi  *  e1000_led_off_pchlan - Turn LEDs off
593375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
593475eba5b6SRobert Mustacchi  *
593575eba5b6SRobert Mustacchi  *  Turn off the LEDs.
593675eba5b6SRobert Mustacchi  **/
593775eba5b6SRobert Mustacchi static s32 e1000_led_off_pchlan(struct e1000_hw *hw)
593875eba5b6SRobert Mustacchi {
593975eba5b6SRobert Mustacchi 	u16 data = (u16)hw->mac.ledctl_mode1;
594075eba5b6SRobert Mustacchi 	u32 i, led;
594175eba5b6SRobert Mustacchi 
594275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_led_off_pchlan");
594375eba5b6SRobert Mustacchi 
594475eba5b6SRobert Mustacchi 	/* If no link, then turn LED off by clearing the invert bit
594575eba5b6SRobert Mustacchi 	 * for each LED that's mode is "link_up" in ledctl_mode1.
594675eba5b6SRobert Mustacchi 	 */
594775eba5b6SRobert Mustacchi 	if (!(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
594875eba5b6SRobert Mustacchi 		for (i = 0; i < 3; i++) {
594975eba5b6SRobert Mustacchi 			led = (data >> (i * 5)) & E1000_PHY_LED0_MASK;
595075eba5b6SRobert Mustacchi 			if ((led & E1000_PHY_LED0_MODE_MASK) !=
595175eba5b6SRobert Mustacchi 			    E1000_LEDCTL_MODE_LINK_UP)
595275eba5b6SRobert Mustacchi 				continue;
595375eba5b6SRobert Mustacchi 			if (led & E1000_PHY_LED0_IVRT)
595475eba5b6SRobert Mustacchi 				data &= ~(E1000_PHY_LED0_IVRT << (i * 5));
595575eba5b6SRobert Mustacchi 			else
595675eba5b6SRobert Mustacchi 				data |= (E1000_PHY_LED0_IVRT << (i * 5));
595775eba5b6SRobert Mustacchi 		}
595875eba5b6SRobert Mustacchi 	}
595975eba5b6SRobert Mustacchi 
596075eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, HV_LED_CONFIG, data);
596175eba5b6SRobert Mustacchi }
596275eba5b6SRobert Mustacchi 
596375eba5b6SRobert Mustacchi /**
596475eba5b6SRobert Mustacchi  *  e1000_get_cfg_done_ich8lan - Read config done bit after Full or PHY reset
596575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
596675eba5b6SRobert Mustacchi  *
596775eba5b6SRobert Mustacchi  *  Read appropriate register for the config done bit for completion status
596875eba5b6SRobert Mustacchi  *  and configure the PHY through s/w for EEPROM-less parts.
596975eba5b6SRobert Mustacchi  *
597075eba5b6SRobert Mustacchi  *  NOTE: some silicon which is EEPROM-less will fail trying to read the
597175eba5b6SRobert Mustacchi  *  config done bit, so only an error is logged and continues.  If we were
597275eba5b6SRobert Mustacchi  *  to return with error, EEPROM-less silicon would not be able to be reset
597375eba5b6SRobert Mustacchi  *  or change link.
597475eba5b6SRobert Mustacchi  **/
597575eba5b6SRobert Mustacchi static s32 e1000_get_cfg_done_ich8lan(struct e1000_hw *hw)
597675eba5b6SRobert Mustacchi {
597775eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
597875eba5b6SRobert Mustacchi 	u32 bank = 0;
597975eba5b6SRobert Mustacchi 	u32 status;
598075eba5b6SRobert Mustacchi 
598175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cfg_done_ich8lan");
598275eba5b6SRobert Mustacchi 
598375eba5b6SRobert Mustacchi 	e1000_get_cfg_done_generic(hw);
598475eba5b6SRobert Mustacchi 
598575eba5b6SRobert Mustacchi 	/* Wait for indication from h/w that it has completed basic config */
598675eba5b6SRobert Mustacchi 	if (hw->mac.type >= e1000_ich10lan) {
598775eba5b6SRobert Mustacchi 		e1000_lan_init_done_ich8lan(hw);
598875eba5b6SRobert Mustacchi 	} else {
598975eba5b6SRobert Mustacchi 		ret_val = e1000_get_auto_rd_done_generic(hw);
599075eba5b6SRobert Mustacchi 		if (ret_val) {
599175eba5b6SRobert Mustacchi 			/* When auto config read does not complete, do not
599275eba5b6SRobert Mustacchi 			 * return with an error. This can happen in situations
599375eba5b6SRobert Mustacchi 			 * where there is no eeprom and prevents getting link.
599475eba5b6SRobert Mustacchi 			 */
599575eba5b6SRobert Mustacchi 			DEBUGOUT("Auto Read Done did not complete\n");
599675eba5b6SRobert Mustacchi 			ret_val = E1000_SUCCESS;
599775eba5b6SRobert Mustacchi 		}
599875eba5b6SRobert Mustacchi 	}
599975eba5b6SRobert Mustacchi 
600075eba5b6SRobert Mustacchi 	/* Clear PHY Reset Asserted bit */
600175eba5b6SRobert Mustacchi 	status = E1000_READ_REG(hw, E1000_STATUS);
6002*42cc51e0SRobert Mustacchi 	if (status & E1000_STATUS_PHYRA)
600375eba5b6SRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_STATUS, status & ~E1000_STATUS_PHYRA);
6004*42cc51e0SRobert Mustacchi 	else
600575eba5b6SRobert Mustacchi 		DEBUGOUT("PHY Reset Asserted not set - needs delay\n");
600675eba5b6SRobert Mustacchi 
600775eba5b6SRobert Mustacchi 	/* If EEPROM is not marked present, init the IGP 3 PHY manually */
600875eba5b6SRobert Mustacchi 	if (hw->mac.type <= e1000_ich9lan) {
600975eba5b6SRobert Mustacchi 		if (!(E1000_READ_REG(hw, E1000_EECD) & E1000_EECD_PRES) &&
601075eba5b6SRobert Mustacchi 		    (hw->phy.type == e1000_phy_igp_3)) {
601175eba5b6SRobert Mustacchi 			e1000_phy_init_script_igp3(hw);
601275eba5b6SRobert Mustacchi 		}
601375eba5b6SRobert Mustacchi 	} else {
601475eba5b6SRobert Mustacchi 		if (e1000_valid_nvm_bank_detect_ich8lan(hw, &bank)) {
601575eba5b6SRobert Mustacchi 			/* Maybe we should do a basic PHY config */
601675eba5b6SRobert Mustacchi 			DEBUGOUT("EEPROM not present\n");
601775eba5b6SRobert Mustacchi 			ret_val = -E1000_ERR_CONFIG;
601875eba5b6SRobert Mustacchi 		}
601975eba5b6SRobert Mustacchi 	}
602075eba5b6SRobert Mustacchi 
602175eba5b6SRobert Mustacchi 	return ret_val;
602275eba5b6SRobert Mustacchi }
602375eba5b6SRobert Mustacchi 
602475eba5b6SRobert Mustacchi /**
602575eba5b6SRobert Mustacchi  * e1000_power_down_phy_copper_ich8lan - Remove link during PHY power down
602675eba5b6SRobert Mustacchi  * @hw: pointer to the HW structure
602775eba5b6SRobert Mustacchi  *
602875eba5b6SRobert Mustacchi  * In the case of a PHY power down to save power, or to turn off link during a
602975eba5b6SRobert Mustacchi  * driver unload, or wake on lan is not enabled, remove the link.
603075eba5b6SRobert Mustacchi  **/
603175eba5b6SRobert Mustacchi static void e1000_power_down_phy_copper_ich8lan(struct e1000_hw *hw)
603275eba5b6SRobert Mustacchi {
603375eba5b6SRobert Mustacchi 	/* If the management interface is not enabled, then power down */
603475eba5b6SRobert Mustacchi 	if (!(hw->mac.ops.check_mng_mode(hw) ||
603575eba5b6SRobert Mustacchi 	      hw->phy.ops.check_reset_block(hw)))
603675eba5b6SRobert Mustacchi 		e1000_power_down_phy_copper(hw);
603775eba5b6SRobert Mustacchi 
603875eba5b6SRobert Mustacchi 	return;
603975eba5b6SRobert Mustacchi }
604075eba5b6SRobert Mustacchi 
604175eba5b6SRobert Mustacchi /**
604275eba5b6SRobert Mustacchi  *  e1000_clear_hw_cntrs_ich8lan - Clear statistical counters
604375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
604475eba5b6SRobert Mustacchi  *
604575eba5b6SRobert Mustacchi  *  Clears hardware counters specific to the silicon family and calls
604675eba5b6SRobert Mustacchi  *  clear_hw_cntrs_generic to clear all general purpose counters.
604775eba5b6SRobert Mustacchi  **/
604875eba5b6SRobert Mustacchi static void e1000_clear_hw_cntrs_ich8lan(struct e1000_hw *hw)
604975eba5b6SRobert Mustacchi {
605075eba5b6SRobert Mustacchi 	u16 phy_data;
605175eba5b6SRobert Mustacchi 	s32 ret_val;
605275eba5b6SRobert Mustacchi 
605375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_clear_hw_cntrs_ich8lan");
605475eba5b6SRobert Mustacchi 
605575eba5b6SRobert Mustacchi 	e1000_clear_hw_cntrs_base_generic(hw);
605675eba5b6SRobert Mustacchi 
605775eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ALGNERRC);
605875eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_RXERRC);
605975eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_TNCRS);
606075eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_CEXTERR);
606175eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_TSCTC);
606275eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_TSCTFC);
606375eba5b6SRobert Mustacchi 
606475eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_MGTPRC);
606575eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_MGTPDC);
606675eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_MGTPTC);
606775eba5b6SRobert Mustacchi 
606875eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_IAC);
606975eba5b6SRobert Mustacchi 	E1000_READ_REG(hw, E1000_ICRXOC);
607075eba5b6SRobert Mustacchi 
607175eba5b6SRobert Mustacchi 	/* Clear PHY statistics registers */
607275eba5b6SRobert Mustacchi 	if ((hw->phy.type == e1000_phy_82578) ||
607375eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_82579) ||
607475eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_i217) ||
607575eba5b6SRobert Mustacchi 	    (hw->phy.type == e1000_phy_82577)) {
607675eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
607775eba5b6SRobert Mustacchi 		if (ret_val)
607875eba5b6SRobert Mustacchi 			return;
607975eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.set_page(hw,
608075eba5b6SRobert Mustacchi 					       HV_STATS_PAGE << IGP_PAGE_SHIFT);
608175eba5b6SRobert Mustacchi 		if (ret_val)
608275eba5b6SRobert Mustacchi 			goto release;
608375eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_SCC_UPPER, &phy_data);
608475eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_SCC_LOWER, &phy_data);
608575eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_ECOL_UPPER, &phy_data);
608675eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_ECOL_LOWER, &phy_data);
608775eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_MCC_UPPER, &phy_data);
608875eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_MCC_LOWER, &phy_data);
608975eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_LATECOL_UPPER, &phy_data);
609075eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_LATECOL_LOWER, &phy_data);
609175eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_COLC_UPPER, &phy_data);
609275eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_COLC_LOWER, &phy_data);
609375eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_DC_UPPER, &phy_data);
609475eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_DC_LOWER, &phy_data);
609575eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_TNCRS_UPPER, &phy_data);
609675eba5b6SRobert Mustacchi 		hw->phy.ops.read_reg_page(hw, HV_TNCRS_LOWER, &phy_data);
609775eba5b6SRobert Mustacchi release:
609875eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
609975eba5b6SRobert Mustacchi 	}
610075eba5b6SRobert Mustacchi }
610175eba5b6SRobert Mustacchi 
6102