175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi
3*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
96*7c5988f9SRobert 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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
130*7c5988f9SRobert Mustacchi u32 *data);
131*7c5988f9SRobert Mustacchi static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw,
132*7c5988f9SRobert Mustacchi u32 offset, u32 *data);
133*7c5988f9SRobert Mustacchi static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw,
134*7c5988f9SRobert Mustacchi u32 offset, u32 data);
135*7c5988f9SRobert Mustacchi static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
136*7c5988f9SRobert 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 **/
e1000_phy_is_accessible_pchlan(struct e1000_hw * hw)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*7c5988f9SRobert Mustacchi if ((hw->mac.type == e1000_pch_lpt) ||
247*7c5988f9SRobert Mustacchi (hw->mac.type == e1000_pch_spt)) {
248*7c5988f9SRobert Mustacchi /* Only unforce SMBus if ME is not active */
249*7c5988f9SRobert Mustacchi if (!(E1000_READ_REG(hw, E1000_FWSM) &
250*7c5988f9SRobert 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*7c5988f9SRobert 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 **/
e1000_toggle_lanphypc_pch_lpt(struct e1000_hw * hw)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 **/
e1000_init_phy_workarounds_pchlan(struct e1000_hw * hw)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*7c5988f9SRobert 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 **/
e1000_init_phy_params_pchlan(struct e1000_hw * hw)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*7c5988f9SRobert 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 **/
e1000_init_phy_params_ich8lan(struct e1000_hw * hw)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 **/
e1000_init_nvm_params_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi
644*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt) {
645*7c5988f9SRobert Mustacchi /* in SPT, gfpreg doesn't exist. NVM size is taken from the
646*7c5988f9SRobert Mustacchi * STRAP register. This is because in SPT the GbE Flash region
647*7c5988f9SRobert Mustacchi * is no longer accessed through the flash registers. Instead,
648*7c5988f9SRobert Mustacchi * the mechanism has changed, and the Flash region access
649*7c5988f9SRobert Mustacchi * registers are now implemented in GbE memory space.
650*7c5988f9SRobert Mustacchi */
651*7c5988f9SRobert Mustacchi nvm->flash_base_addr = 0;
652*7c5988f9SRobert Mustacchi nvm_size =
653*7c5988f9SRobert Mustacchi (((E1000_READ_REG(hw, E1000_STRAP) >> 1) & 0x1F) + 1)
654*7c5988f9SRobert Mustacchi * NVM_SIZE_MULTIPLIER;
655*7c5988f9SRobert Mustacchi nvm->flash_bank_size = nvm_size / 2;
656*7c5988f9SRobert Mustacchi /* Adjust to word count */
657*7c5988f9SRobert Mustacchi nvm->flash_bank_size /= sizeof(u16);
658*7c5988f9SRobert Mustacchi /* Set the base address for flash register access */
659*7c5988f9SRobert Mustacchi hw->flash_address = hw->hw_addr + E1000_FLASH_BASE_ADDR;
660*7c5988f9SRobert Mustacchi } else {
661*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi nvm->flash_base_addr = sector_base_addr
678*7c5988f9SRobert 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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt) {
705*7c5988f9SRobert Mustacchi nvm->ops.read = e1000_read_nvm_spt;
706*7c5988f9SRobert Mustacchi nvm->ops.update = e1000_update_nvm_checksum_spt;
707*7c5988f9SRobert Mustacchi } else {
70875eba5b6SRobert Mustacchi nvm->ops.read = e1000_read_nvm_ich8lan;
70975eba5b6SRobert Mustacchi nvm->ops.update = e1000_update_nvm_checksum_ich8lan;
710*7c5988f9SRobert 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 **/
e1000_init_mac_params_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert 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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi if ((mac->type == e1000_pch_lpt) ||
819*7c5988f9SRobert 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 **/
__e1000_access_emi_reg_locked(struct e1000_hw * hw,u16 address,u16 * data,bool read)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 **/
e1000_read_emi_reg_locked(struct e1000_hw * hw,u16 addr,u16 * data)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 **/
e1000_write_emi_reg_locked(struct e1000_hw * hw,u16 addr,u16 data)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 **/
e1000_set_eee_pchlan(struct e1000_hw * hw)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 **/
e1000_k1_workaround_lpt_lp(struct e1000_hw * hw,bool link)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 ®);
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*7c5988f9SRobert Mustacchi if ((hw->phy.revision > 5) || !link ||
1050*7c5988f9SRobert 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, ®);
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
e1000_ltr2ns(u16 ltr)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 **/
e1000_platform_pm_pch_lpt(struct e1000_hw * hw,bool link)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*7c5988f9SRobert 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*7c5988f9SRobert 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 **/
e1000_set_obff_timer_pch_lpt(struct e1000_hw * hw,u32 itr)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 */
e1000_enable_ulp_lpt_lp(struct e1000_hw * hw,bool to_sx)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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi /* Si workaround for ULP entry flow on i127/rev6 h/w. Enable
1321*7c5988f9SRobert Mustacchi * LPLU and disable Gig speed when entering ULP
1322*7c5988f9SRobert Mustacchi */
1323*7c5988f9SRobert Mustacchi if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6)) {
1324*7c5988f9SRobert Mustacchi ret_val = e1000_read_phy_reg_hv_locked(hw, HV_OEM_BITS,
1325*7c5988f9SRobert Mustacchi &oem_reg);
1326*7c5988f9SRobert Mustacchi if (ret_val)
1327*7c5988f9SRobert Mustacchi goto release;
1328*7c5988f9SRobert Mustacchi
1329*7c5988f9SRobert Mustacchi phy_reg = oem_reg;
1330*7c5988f9SRobert Mustacchi phy_reg |= HV_OEM_BITS_LPLU | HV_OEM_BITS_GBE_DIS;
1331*7c5988f9SRobert Mustacchi
1332*7c5988f9SRobert Mustacchi ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
1333*7c5988f9SRobert Mustacchi phy_reg);
1334*7c5988f9SRobert Mustacchi
1335*7c5988f9SRobert Mustacchi if (ret_val)
1336*7c5988f9SRobert Mustacchi goto release;
1337*7c5988f9SRobert Mustacchi }
1338*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi else
1351*7c5988f9SRobert Mustacchi phy_reg &= ~I218_ULP_CONFIG1_WOL_HOST;
1352c124a83eSRobert Mustacchi
1353c124a83eSRobert Mustacchi phy_reg |= I218_ULP_CONFIG1_STICKY_ULP;
1354*7c5988f9SRobert Mustacchi phy_reg &= ~I218_ULP_CONFIG1_INBAND_EXIT;
1355c124a83eSRobert Mustacchi } else {
1356c124a83eSRobert Mustacchi phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT;
1357*7c5988f9SRobert Mustacchi phy_reg &= ~I218_ULP_CONFIG1_STICKY_ULP;
1358*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi
1371*7c5988f9SRobert Mustacchi if ((hw->phy.type == e1000_phy_i217) && (hw->phy.revision == 6) &&
1372*7c5988f9SRobert Mustacchi to_sx && (E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) {
1373*7c5988f9SRobert Mustacchi ret_val = e1000_write_phy_reg_hv_locked(hw, HV_OEM_BITS,
1374*7c5988f9SRobert Mustacchi oem_reg);
1375*7c5988f9SRobert Mustacchi if (ret_val)
1376*7c5988f9SRobert Mustacchi goto release;
1377*7c5988f9SRobert Mustacchi }
1378*7c5988f9SRobert Mustacchi
1379c124a83eSRobert Mustacchi release:
1380c124a83eSRobert Mustacchi hw->phy.ops.release(hw);
1381c124a83eSRobert Mustacchi out:
1382*7c5988f9SRobert Mustacchi if (ret_val)
1383c124a83eSRobert Mustacchi DEBUGOUT1("Error in ULP enable flow: %d\n", ret_val);
1384*7c5988f9SRobert 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 */
e1000_disable_ulp_lpt_lp(struct e1000_hw * hw,bool force)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*7c5988f9SRobert 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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi I218_ULP_CONFIG1_EN_ULP_LANPHYPC |
1507*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi if (ret_val)
1528c124a83eSRobert Mustacchi DEBUGOUT1("Error in ULP disable flow: %d\n", ret_val);
1529*7c5988f9SRobert 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 **/
e1000_check_for_copper_link_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert Mustacchi s32 ret_val, tipg_reg = 0;
1547*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi (hw->mac.type == e1000_pch_lpt) ||
1581*7c5988f9SRobert Mustacchi (hw->mac.type == e1000_pch_spt)) && link) {
1582*7c5988f9SRobert Mustacchi u16 speed, duplex;
1583c124a83eSRobert Mustacchi
1584*7c5988f9SRobert Mustacchi e1000_get_speed_and_duplex_copper_generic(hw, &speed, &duplex);
1585*7c5988f9SRobert Mustacchi tipg_reg = E1000_READ_REG(hw, E1000_TIPG);
1586*7c5988f9SRobert Mustacchi tipg_reg &= ~E1000_TIPG_IPGT_MASK;
158775eba5b6SRobert Mustacchi
1588*7c5988f9SRobert Mustacchi if (duplex == HALF_DUPLEX && speed == SPEED_10) {
1589*7c5988f9SRobert Mustacchi tipg_reg |= 0xFF;
159075eba5b6SRobert Mustacchi /* Reduce Rx latency in analog PHY */
1591*7c5988f9SRobert Mustacchi emi_val = 0;
1592*7c5988f9SRobert Mustacchi } else if (hw->mac.type == e1000_pch_spt &&
1593*7c5988f9SRobert Mustacchi duplex == FULL_DUPLEX && speed != SPEED_1000) {
1594*7c5988f9SRobert Mustacchi tipg_reg |= 0xC;
1595*7c5988f9SRobert Mustacchi emi_val = 1;
1596*7c5988f9SRobert Mustacchi } else {
1597*7c5988f9SRobert Mustacchi /* Roll back the default values */
1598*7c5988f9SRobert Mustacchi tipg_reg |= 0x08;
1599*7c5988f9SRobert Mustacchi emi_val = 1;
1600*7c5988f9SRobert Mustacchi }
1601*7c5988f9SRobert Mustacchi
1602*7c5988f9SRobert Mustacchi E1000_WRITE_REG(hw, E1000_TIPG, tipg_reg);
1603*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi ret_val = e1000_write_emi_reg_locked(hw, emi_addr, emi_val);
161375eba5b6SRobert Mustacchi
1614*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_lpt ||
1615*7c5988f9SRobert Mustacchi hw->mac.type == e1000_pch_spt) {
1616*7c5988f9SRobert Mustacchi u16 phy_reg;
1617*7c5988f9SRobert Mustacchi
1618*7c5988f9SRobert Mustacchi hw->phy.ops.read_reg_locked(hw, I217_PLL_CLOCK_GATE_REG,
1619*7c5988f9SRobert Mustacchi &phy_reg);
1620*7c5988f9SRobert Mustacchi phy_reg &= ~I217_PLL_CLOCK_GATE_MASK;
1621*7c5988f9SRobert Mustacchi if (speed == SPEED_100 || speed == SPEED_10)
1622*7c5988f9SRobert Mustacchi phy_reg |= 0x3E8;
1623*7c5988f9SRobert Mustacchi else
1624*7c5988f9SRobert Mustacchi phy_reg |= 0xFA;
1625*7c5988f9SRobert Mustacchi hw->phy.ops.write_reg_locked(hw,
1626*7c5988f9SRobert Mustacchi I217_PLL_CLOCK_GATE_REG,
1627*7c5988f9SRobert Mustacchi phy_reg);
1628*7c5988f9SRobert Mustacchi }
162975eba5b6SRobert Mustacchi hw->phy.ops.release(hw);
163075eba5b6SRobert Mustacchi
163175eba5b6SRobert Mustacchi if (ret_val)
163275eba5b6SRobert Mustacchi return ret_val;
1633*7c5988f9SRobert Mustacchi
1634*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt) {
1635*7c5988f9SRobert Mustacchi u16 data;
1636*7c5988f9SRobert Mustacchi u16 ptr_gap;
1637*7c5988f9SRobert Mustacchi
1638*7c5988f9SRobert Mustacchi if (speed == SPEED_1000) {
1639*7c5988f9SRobert Mustacchi ret_val = hw->phy.ops.acquire(hw);
1640*7c5988f9SRobert Mustacchi if (ret_val)
1641*7c5988f9SRobert Mustacchi return ret_val;
1642*7c5988f9SRobert Mustacchi
1643*7c5988f9SRobert Mustacchi ret_val = hw->phy.ops.read_reg_locked(hw,
1644*7c5988f9SRobert Mustacchi PHY_REG(776, 20),
1645*7c5988f9SRobert Mustacchi &data);
1646*7c5988f9SRobert Mustacchi if (ret_val) {
1647*7c5988f9SRobert Mustacchi hw->phy.ops.release(hw);
1648*7c5988f9SRobert Mustacchi return ret_val;
164975eba5b6SRobert Mustacchi }
1650*7c5988f9SRobert Mustacchi
1651*7c5988f9SRobert Mustacchi ptr_gap = (data & (0x3FF << 2)) >> 2;
1652*7c5988f9SRobert Mustacchi if (ptr_gap < 0x18) {
1653*7c5988f9SRobert Mustacchi data &= ~(0x3FF << 2);
1654*7c5988f9SRobert Mustacchi data |= (0x18 << 2);
1655*7c5988f9SRobert Mustacchi ret_val =
1656*7c5988f9SRobert Mustacchi hw->phy.ops.write_reg_locked(hw,
1657*7c5988f9SRobert Mustacchi PHY_REG(776, 20), data);
1658*7c5988f9SRobert Mustacchi }
1659*7c5988f9SRobert Mustacchi hw->phy.ops.release(hw);
1660*7c5988f9SRobert Mustacchi if (ret_val)
1661*7c5988f9SRobert Mustacchi return ret_val;
1662*7c5988f9SRobert Mustacchi } else {
1663*7c5988f9SRobert Mustacchi ret_val = hw->phy.ops.acquire(hw);
1664*7c5988f9SRobert Mustacchi if (ret_val)
1665*7c5988f9SRobert Mustacchi return ret_val;
1666*7c5988f9SRobert Mustacchi
1667*7c5988f9SRobert Mustacchi ret_val = hw->phy.ops.write_reg_locked(hw,
1668*7c5988f9SRobert Mustacchi PHY_REG(776, 20),
1669*7c5988f9SRobert Mustacchi 0xC023);
1670*7c5988f9SRobert Mustacchi hw->phy.ops.release(hw);
1671*7c5988f9SRobert Mustacchi if (ret_val)
1672*7c5988f9SRobert Mustacchi return ret_val;
1673*7c5988f9SRobert Mustacchi
1674*7c5988f9SRobert Mustacchi }
1675*7c5988f9SRobert Mustacchi }
1676*7c5988f9SRobert Mustacchi }
1677*7c5988f9SRobert Mustacchi
1678*7c5988f9SRobert Mustacchi /* I217 Packet Loss issue:
1679*7c5988f9SRobert Mustacchi * ensure that FEXTNVM4 Beacon Duration is set correctly
1680*7c5988f9SRobert Mustacchi * on power up.
1681*7c5988f9SRobert Mustacchi * Set the Beacon Duration for I217 to 8 usec
1682*7c5988f9SRobert Mustacchi */
1683*7c5988f9SRobert Mustacchi if ((hw->mac.type == e1000_pch_lpt) ||
1684*7c5988f9SRobert Mustacchi (hw->mac.type == e1000_pch_spt)) {
1685*7c5988f9SRobert Mustacchi u32 mac_reg;
1686*7c5988f9SRobert Mustacchi
1687*7c5988f9SRobert Mustacchi mac_reg = E1000_READ_REG(hw, E1000_FEXTNVM4);
1688*7c5988f9SRobert Mustacchi mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;
1689*7c5988f9SRobert Mustacchi mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC;
1690*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi if ((hw->mac.type == e1000_pch_lpt) ||
1703*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi /* FEXTNVM6 K1-off workaround */
1717*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt) {
1718*7c5988f9SRobert Mustacchi u32 pcieanacfg = E1000_READ_REG(hw, E1000_PCIEANACFG);
1719*7c5988f9SRobert Mustacchi u32 fextnvm6 = E1000_READ_REG(hw, E1000_FEXTNVM6);
1720*7c5988f9SRobert Mustacchi
1721*7c5988f9SRobert Mustacchi if (pcieanacfg & E1000_FEXTNVM6_K1_OFF_ENABLE)
1722*7c5988f9SRobert Mustacchi fextnvm6 |= E1000_FEXTNVM6_K1_OFF_ENABLE;
1723*7c5988f9SRobert Mustacchi else
1724*7c5988f9SRobert Mustacchi fextnvm6 &= ~E1000_FEXTNVM6_K1_OFF_ENABLE;
1725*7c5988f9SRobert Mustacchi
1726*7c5988f9SRobert Mustacchi E1000_WRITE_REG(hw, E1000_FEXTNVM6, fextnvm6);
1727*7c5988f9SRobert Mustacchi }
1728*7c5988f9SRobert 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 **/
e1000_init_function_pointers_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert 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 **/
e1000_acquire_nvm_ich8lan(struct e1000_hw * hw)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 **/
e1000_release_nvm_ich8lan(struct e1000_hw * hw)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 **/
e1000_acquire_swflag_ich8lan(struct e1000_hw * hw)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 **/
e1000_release_swflag_ich8lan(struct e1000_hw * hw)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 **/
e1000_check_mng_mode_ich8lan(struct e1000_hw * hw)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 **/
e1000_check_mng_mode_pchlan(struct e1000_hw * hw)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 **/
e1000_rar_set_pch2lan(struct e1000_hw * hw,u8 * addr,u32 index)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 **/
e1000_rar_set_pch_lpt(struct e1000_hw * hw,u8 * addr,u32 index)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 **/
e1000_update_mc_addr_list_pch2lan(struct e1000_hw * hw,u8 * mc_addr_list,u32 mc_addr_count)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 **/
e1000_check_reset_block_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert 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 **/
e1000_write_smbus_addr(struct e1000_hw * hw)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 **/
e1000_sw_lcd_config_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert 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 ®_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, ®_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 **/
e1000_k1_gig_workaround_hv(struct e1000_hw * hw,bool link)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 **/
e1000_configure_k1_ich8lan(struct e1000_hw * hw,bool k1_enable)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 **/
e1000_oem_bits_config_ich8lan(struct e1000_hw * hw,bool d0_state)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 **/
e1000_set_mdio_slow_mode_hv(struct e1000_hw * hw)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 **/
e1000_hv_phy_workarounds_ich8lan(struct e1000_hw * hw)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 **/
e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw * hw)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
e1000_calc_rx_da_crc(u8 mac[])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 **/
e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw * hw,bool enable)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 **/
e1000_lv_phy_workarounds_ich8lan(struct e1000_hw * hw)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 **/
e1000_k1_workaround_lv(struct e1000_hw * hw)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 **/
e1000_gate_hw_phy_config_ich8lan(struct e1000_hw * hw,bool gate)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 **/
e1000_lan_init_done_ich8lan(struct e1000_hw * hw)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 **/
e1000_post_phy_reset_ich8lan(struct e1000_hw * hw)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, ®);
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 **/
e1000_phy_hw_reset_ich8lan(struct e1000_hw * hw)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 **/
e1000_set_lplu_state_pchlan(struct e1000_hw * hw,bool active)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 **/
e1000_set_d0_lplu_state_ich8lan(struct e1000_hw * hw,bool active)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 **/
e1000_set_d3_lplu_state_ich8lan(struct e1000_hw * hw,bool active)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 **/
e1000_valid_nvm_bank_detect_ich8lan(struct e1000_hw * hw,u32 * bank)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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi case e1000_pch_spt:
3404*7c5988f9SRobert Mustacchi bank1_offset = nvm->flash_bank_size;
3405*7c5988f9SRobert Mustacchi act_offset = E1000_ICH_NVM_SIG_WORD;
3406*7c5988f9SRobert Mustacchi
3407*7c5988f9SRobert Mustacchi /* set bank to 0 in case flash read fails */
3408*7c5988f9SRobert Mustacchi *bank = 0;
3409*7c5988f9SRobert Mustacchi
3410*7c5988f9SRobert Mustacchi /* Check bank 0 */
3411*7c5988f9SRobert Mustacchi ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset,
3412*7c5988f9SRobert Mustacchi &nvm_dword);
3413*7c5988f9SRobert Mustacchi if (ret_val)
3414*7c5988f9SRobert Mustacchi return ret_val;
3415*7c5988f9SRobert Mustacchi sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
3416*7c5988f9SRobert Mustacchi if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
3417*7c5988f9SRobert Mustacchi E1000_ICH_NVM_SIG_VALUE) {
3418*7c5988f9SRobert Mustacchi *bank = 0;
3419*7c5988f9SRobert Mustacchi return E1000_SUCCESS;
3420*7c5988f9SRobert Mustacchi }
3421*7c5988f9SRobert Mustacchi
3422*7c5988f9SRobert Mustacchi /* Check bank 1 */
3423*7c5988f9SRobert Mustacchi ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset +
3424*7c5988f9SRobert Mustacchi bank1_offset,
3425*7c5988f9SRobert Mustacchi &nvm_dword);
3426*7c5988f9SRobert Mustacchi if (ret_val)
3427*7c5988f9SRobert Mustacchi return ret_val;
3428*7c5988f9SRobert Mustacchi sig_byte = (u8)((nvm_dword & 0xFF00) >> 8);
3429*7c5988f9SRobert Mustacchi if ((sig_byte & E1000_ICH_NVM_VALID_SIG_MASK) ==
3430*7c5988f9SRobert Mustacchi E1000_ICH_NVM_SIG_VALUE) {
3431*7c5988f9SRobert Mustacchi *bank = 1;
3432*7c5988f9SRobert Mustacchi return E1000_SUCCESS;
3433*7c5988f9SRobert Mustacchi }
3434*7c5988f9SRobert Mustacchi
3435*7c5988f9SRobert Mustacchi DEBUGOUT("ERROR: No valid NVM bank present\n");
3436*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi * e1000_read_nvm_spt - NVM access for SPT
3485*7c5988f9SRobert Mustacchi * @hw: pointer to the HW structure
3486*7c5988f9SRobert Mustacchi * @offset: The offset (in bytes) of the word(s) to read.
3487*7c5988f9SRobert Mustacchi * @words: Size of data to read in words.
3488*7c5988f9SRobert Mustacchi * @data: pointer to the word(s) to read at offset.
3489*7c5988f9SRobert Mustacchi *
3490*7c5988f9SRobert Mustacchi * Reads a word(s) from the NVM
3491*7c5988f9SRobert Mustacchi **/
e1000_read_nvm_spt(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)3492*7c5988f9SRobert Mustacchi static s32 e1000_read_nvm_spt(struct e1000_hw *hw, u16 offset, u16 words,
3493*7c5988f9SRobert Mustacchi u16 *data)
3494*7c5988f9SRobert Mustacchi {
3495*7c5988f9SRobert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
3496*7c5988f9SRobert Mustacchi struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
3497*7c5988f9SRobert Mustacchi u32 act_offset;
3498*7c5988f9SRobert Mustacchi s32 ret_val = E1000_SUCCESS;
3499*7c5988f9SRobert Mustacchi u32 bank = 0;
3500*7c5988f9SRobert Mustacchi u32 dword = 0;
3501*7c5988f9SRobert Mustacchi u16 offset_to_read;
3502*7c5988f9SRobert Mustacchi u16 i;
3503*7c5988f9SRobert Mustacchi
3504*7c5988f9SRobert Mustacchi DEBUGFUNC("e1000_read_nvm_spt");
3505*7c5988f9SRobert Mustacchi
3506*7c5988f9SRobert Mustacchi if ((offset >= nvm->word_size) || (words > nvm->word_size - offset) ||
3507*7c5988f9SRobert Mustacchi (words == 0)) {
3508*7c5988f9SRobert Mustacchi DEBUGOUT("nvm parameter(s) out of bounds\n");
3509*7c5988f9SRobert Mustacchi ret_val = -E1000_ERR_NVM;
3510*7c5988f9SRobert Mustacchi goto out;
3511*7c5988f9SRobert Mustacchi }
3512*7c5988f9SRobert Mustacchi
3513*7c5988f9SRobert Mustacchi nvm->ops.acquire(hw);
3514*7c5988f9SRobert Mustacchi
3515*7c5988f9SRobert Mustacchi ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
3516*7c5988f9SRobert Mustacchi if (ret_val != E1000_SUCCESS) {
3517*7c5988f9SRobert Mustacchi DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
3518*7c5988f9SRobert Mustacchi bank = 0;
3519*7c5988f9SRobert Mustacchi }
3520*7c5988f9SRobert Mustacchi
3521*7c5988f9SRobert Mustacchi act_offset = (bank) ? nvm->flash_bank_size : 0;
3522*7c5988f9SRobert Mustacchi act_offset += offset;
3523*7c5988f9SRobert Mustacchi
3524*7c5988f9SRobert Mustacchi ret_val = E1000_SUCCESS;
3525*7c5988f9SRobert Mustacchi
3526*7c5988f9SRobert Mustacchi for (i = 0; i < words; i += 2) {
3527*7c5988f9SRobert Mustacchi if (words - i == 1) {
3528*7c5988f9SRobert Mustacchi if (dev_spec->shadow_ram[offset+i].modified) {
3529*7c5988f9SRobert Mustacchi data[i] = dev_spec->shadow_ram[offset+i].value;
3530*7c5988f9SRobert Mustacchi } else {
3531*7c5988f9SRobert Mustacchi offset_to_read = act_offset + i -
3532*7c5988f9SRobert Mustacchi ((act_offset + i) % 2);
3533*7c5988f9SRobert Mustacchi ret_val =
3534*7c5988f9SRobert Mustacchi e1000_read_flash_dword_ich8lan(hw,
3535*7c5988f9SRobert Mustacchi offset_to_read,
3536*7c5988f9SRobert Mustacchi &dword);
3537*7c5988f9SRobert Mustacchi if (ret_val)
3538*7c5988f9SRobert Mustacchi break;
3539*7c5988f9SRobert Mustacchi if ((act_offset + i) % 2 == 0)
3540*7c5988f9SRobert Mustacchi data[i] = (u16)(dword & 0xFFFF);
3541*7c5988f9SRobert Mustacchi else
3542*7c5988f9SRobert Mustacchi data[i] = (u16)((dword >> 16) & 0xFFFF);
3543*7c5988f9SRobert Mustacchi }
3544*7c5988f9SRobert Mustacchi } else {
3545*7c5988f9SRobert Mustacchi offset_to_read = act_offset + i;
3546*7c5988f9SRobert Mustacchi if (!(dev_spec->shadow_ram[offset+i].modified) ||
3547*7c5988f9SRobert Mustacchi !(dev_spec->shadow_ram[offset+i+1].modified)) {
3548*7c5988f9SRobert Mustacchi ret_val =
3549*7c5988f9SRobert Mustacchi e1000_read_flash_dword_ich8lan(hw,
3550*7c5988f9SRobert Mustacchi offset_to_read,
3551*7c5988f9SRobert Mustacchi &dword);
3552*7c5988f9SRobert Mustacchi if (ret_val)
3553*7c5988f9SRobert Mustacchi break;
3554*7c5988f9SRobert Mustacchi }
3555*7c5988f9SRobert Mustacchi if (dev_spec->shadow_ram[offset+i].modified)
3556*7c5988f9SRobert Mustacchi data[i] = dev_spec->shadow_ram[offset+i].value;
3557*7c5988f9SRobert Mustacchi else
3558*7c5988f9SRobert Mustacchi data[i] = (u16) (dword & 0xFFFF);
3559*7c5988f9SRobert Mustacchi if (dev_spec->shadow_ram[offset+i].modified)
3560*7c5988f9SRobert Mustacchi data[i+1] =
3561*7c5988f9SRobert Mustacchi dev_spec->shadow_ram[offset+i+1].value;
3562*7c5988f9SRobert Mustacchi else
3563*7c5988f9SRobert Mustacchi data[i+1] = (u16) (dword >> 16 & 0xFFFF);
3564*7c5988f9SRobert Mustacchi }
3565*7c5988f9SRobert Mustacchi }
3566*7c5988f9SRobert Mustacchi
3567*7c5988f9SRobert Mustacchi nvm->ops.release(hw);
3568*7c5988f9SRobert Mustacchi
3569*7c5988f9SRobert Mustacchi out:
3570*7c5988f9SRobert Mustacchi if (ret_val)
3571*7c5988f9SRobert Mustacchi DEBUGOUT1("NVM read error: %d\n", ret_val);
3572*7c5988f9SRobert Mustacchi
3573*7c5988f9SRobert Mustacchi return ret_val;
3574*7c5988f9SRobert Mustacchi }
3575*7c5988f9SRobert Mustacchi
3576*7c5988f9SRobert 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 **/
e1000_read_nvm_ich8lan(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)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 **/
e1000_flash_cycle_init_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
3664*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3665*7c5988f9SRobert Mustacchi hsfsts.regval & 0xFFFF);
3666*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
3684*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3685*7c5988f9SRobert Mustacchi hsfsts.regval & 0xFFFF);
3686*7c5988f9SRobert Mustacchi else
3687*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFSTS,
3688*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
3711*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3712*7c5988f9SRobert Mustacchi hsfsts.regval & 0xFFFF);
3713*7c5988f9SRobert 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 **/
e1000_flash_cycle_ich8lan(struct e1000_hw * hw,u32 timeout)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*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
3741*7c5988f9SRobert Mustacchi hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
3742*7c5988f9SRobert Mustacchi else
374375eba5b6SRobert Mustacchi hsflctl.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFCTL);
374475eba5b6SRobert Mustacchi hsflctl.hsf_ctrl.flcgo = 1;
3745c124a83eSRobert Mustacchi
3746*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
3747*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3748*7c5988f9SRobert Mustacchi hsflctl.regval << 16);
3749*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi * e1000_read_flash_dword_ich8lan - Read dword from flash
3768*7c5988f9SRobert Mustacchi * @hw: pointer to the HW structure
3769*7c5988f9SRobert Mustacchi * @offset: offset to data location
3770*7c5988f9SRobert Mustacchi * @data: pointer to the location for storing the data
3771*7c5988f9SRobert Mustacchi *
3772*7c5988f9SRobert Mustacchi * Reads the flash dword at offset into data. Offset is converted
3773*7c5988f9SRobert Mustacchi * to bytes before read.
3774*7c5988f9SRobert Mustacchi **/
e1000_read_flash_dword_ich8lan(struct e1000_hw * hw,u32 offset,u32 * data)3775*7c5988f9SRobert Mustacchi static s32 e1000_read_flash_dword_ich8lan(struct e1000_hw *hw, u32 offset,
3776*7c5988f9SRobert Mustacchi u32 *data)
3777*7c5988f9SRobert Mustacchi {
3778*7c5988f9SRobert Mustacchi DEBUGFUNC("e1000_read_flash_dword_ich8lan");
3779*7c5988f9SRobert Mustacchi
3780*7c5988f9SRobert Mustacchi if (!data)
3781*7c5988f9SRobert Mustacchi return -E1000_ERR_NVM;
3782*7c5988f9SRobert Mustacchi
3783*7c5988f9SRobert Mustacchi /* Must convert word offset into bytes. */
3784*7c5988f9SRobert Mustacchi offset <<= 1;
3785*7c5988f9SRobert Mustacchi
3786*7c5988f9SRobert Mustacchi return e1000_read_flash_data32_ich8lan(hw, offset, data);
3787*7c5988f9SRobert Mustacchi }
3788*7c5988f9SRobert Mustacchi
3789*7c5988f9SRobert 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 **/
e1000_read_flash_word_ich8lan(struct e1000_hw * hw,u32 offset,u16 * data)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 **/
e1000_read_flash_byte_ich8lan(struct e1000_hw * hw,u32 offset,u8 * data)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*7c5988f9SRobert Mustacchi /* In SPT, only 32 bits access is supported,
3827*7c5988f9SRobert Mustacchi * so this function should not be called.
3828*7c5988f9SRobert Mustacchi */
3829*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
3830*7c5988f9SRobert Mustacchi return -E1000_ERR_NVM;
3831*7c5988f9SRobert 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 **/
e1000_read_flash_data_ich8lan(struct e1000_hw * hw,u32 offset,u8 size,u16 * data)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*7c5988f9SRobert Mustacchi /**
3919*7c5988f9SRobert Mustacchi * e1000_read_flash_data32_ich8lan - Read dword from NVM
3920*7c5988f9SRobert Mustacchi * @hw: pointer to the HW structure
3921*7c5988f9SRobert Mustacchi * @offset: The offset (in bytes) of the dword to read.
3922*7c5988f9SRobert Mustacchi * @data: Pointer to the dword to store the value read.
3923*7c5988f9SRobert Mustacchi *
3924*7c5988f9SRobert Mustacchi * Reads a byte or word from the NVM using the flash access registers.
3925*7c5988f9SRobert Mustacchi **/
e1000_read_flash_data32_ich8lan(struct e1000_hw * hw,u32 offset,u32 * data)3926*7c5988f9SRobert Mustacchi static s32 e1000_read_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
3927*7c5988f9SRobert Mustacchi u32 *data)
3928*7c5988f9SRobert Mustacchi {
3929*7c5988f9SRobert Mustacchi union ich8_hws_flash_status hsfsts;
3930*7c5988f9SRobert Mustacchi union ich8_hws_flash_ctrl hsflctl;
3931*7c5988f9SRobert Mustacchi u32 flash_linear_addr;
3932*7c5988f9SRobert Mustacchi s32 ret_val = -E1000_ERR_NVM;
3933*7c5988f9SRobert Mustacchi u8 count = 0;
3934*7c5988f9SRobert Mustacchi
3935*7c5988f9SRobert Mustacchi DEBUGFUNC("e1000_read_flash_data_ich8lan");
3936*7c5988f9SRobert Mustacchi
3937*7c5988f9SRobert Mustacchi if (offset > ICH_FLASH_LINEAR_ADDR_MASK ||
3938*7c5988f9SRobert Mustacchi hw->mac.type != e1000_pch_spt)
3939*7c5988f9SRobert Mustacchi return -E1000_ERR_NVM;
3940*7c5988f9SRobert Mustacchi flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
3941*7c5988f9SRobert Mustacchi hw->nvm.flash_base_addr);
3942*7c5988f9SRobert Mustacchi
3943*7c5988f9SRobert Mustacchi do {
3944*7c5988f9SRobert Mustacchi usec_delay(1);
3945*7c5988f9SRobert Mustacchi /* Steps */
3946*7c5988f9SRobert Mustacchi ret_val = e1000_flash_cycle_init_ich8lan(hw);
3947*7c5988f9SRobert Mustacchi if (ret_val != E1000_SUCCESS)
3948*7c5988f9SRobert Mustacchi break;
3949*7c5988f9SRobert Mustacchi /* In SPT, This register is in Lan memory space, not flash.
3950*7c5988f9SRobert Mustacchi * Therefore, only 32 bit access is supported
3951*7c5988f9SRobert Mustacchi */
3952*7c5988f9SRobert Mustacchi hsflctl.regval = E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
3953*7c5988f9SRobert Mustacchi
3954*7c5988f9SRobert Mustacchi /* 0b/1b corresponds to 1 or 2 byte size, respectively. */
3955*7c5988f9SRobert Mustacchi hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
3956*7c5988f9SRobert Mustacchi hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_READ;
3957*7c5988f9SRobert Mustacchi /* In SPT, This register is in Lan memory space, not flash.
3958*7c5988f9SRobert Mustacchi * Therefore, only 32 bit access is supported
3959*7c5988f9SRobert Mustacchi */
3960*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
3961*7c5988f9SRobert Mustacchi (u32)hsflctl.regval << 16);
3962*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
3963*7c5988f9SRobert Mustacchi
3964*7c5988f9SRobert Mustacchi ret_val = e1000_flash_cycle_ich8lan(hw,
3965*7c5988f9SRobert Mustacchi ICH_FLASH_READ_COMMAND_TIMEOUT);
3966*7c5988f9SRobert Mustacchi
3967*7c5988f9SRobert Mustacchi /* Check if FCERR is set to 1, if set to 1, clear it
3968*7c5988f9SRobert Mustacchi * and try the whole sequence a few more times, else
3969*7c5988f9SRobert Mustacchi * read in (shift in) the Flash Data0, the order is
3970*7c5988f9SRobert Mustacchi * least significant byte first msb to lsb
3971*7c5988f9SRobert Mustacchi */
3972*7c5988f9SRobert Mustacchi if (ret_val == E1000_SUCCESS) {
3973*7c5988f9SRobert Mustacchi *data = E1000_READ_FLASH_REG(hw, ICH_FLASH_FDATA0);
3974*7c5988f9SRobert Mustacchi break;
3975*7c5988f9SRobert Mustacchi } else {
3976*7c5988f9SRobert Mustacchi /* If we've gotten here, then things are probably
3977*7c5988f9SRobert Mustacchi * completely hosed, but if the error condition is
3978*7c5988f9SRobert Mustacchi * detected, it won't hurt to give it another try...
3979*7c5988f9SRobert Mustacchi * ICH_FLASH_CYCLE_REPEAT_COUNT times.
3980*7c5988f9SRobert Mustacchi */
3981*7c5988f9SRobert Mustacchi hsfsts.regval = E1000_READ_FLASH_REG16(hw,
3982*7c5988f9SRobert Mustacchi ICH_FLASH_HSFSTS);
3983*7c5988f9SRobert Mustacchi if (hsfsts.hsf_status.flcerr) {
3984*7c5988f9SRobert Mustacchi /* Repeat for some time before giving up. */
3985*7c5988f9SRobert Mustacchi continue;
3986*7c5988f9SRobert Mustacchi } else if (!hsfsts.hsf_status.flcdone) {
3987*7c5988f9SRobert Mustacchi DEBUGOUT("Timeout error - flash cycle did not complete.\n");
3988*7c5988f9SRobert Mustacchi break;
3989*7c5988f9SRobert Mustacchi }
3990*7c5988f9SRobert Mustacchi }
3991*7c5988f9SRobert Mustacchi } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
3992*7c5988f9SRobert Mustacchi
3993*7c5988f9SRobert Mustacchi return ret_val;
3994*7c5988f9SRobert 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 **/
e1000_write_nvm_ich8lan(struct e1000_hw * hw,u16 offset,u16 words,u16 * data)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*7c5988f9SRobert Mustacchi * e1000_update_nvm_checksum_spt - Update the checksum for NVM
4034*7c5988f9SRobert Mustacchi * @hw: pointer to the HW structure
4035*7c5988f9SRobert Mustacchi *
4036*7c5988f9SRobert Mustacchi * The NVM checksum is updated by calling the generic update_nvm_checksum,
4037*7c5988f9SRobert Mustacchi * which writes the checksum to the shadow ram. The changes in the shadow
4038*7c5988f9SRobert Mustacchi * ram are then committed to the EEPROM by processing each bank at a time
4039*7c5988f9SRobert Mustacchi * checking for the modified bit and writing only the pending changes.
4040*7c5988f9SRobert Mustacchi * After a successful commit, the shadow ram is cleared and is ready for
4041*7c5988f9SRobert Mustacchi * future writes.
4042*7c5988f9SRobert Mustacchi **/
e1000_update_nvm_checksum_spt(struct e1000_hw * hw)4043*7c5988f9SRobert Mustacchi static s32 e1000_update_nvm_checksum_spt(struct e1000_hw *hw)
4044*7c5988f9SRobert Mustacchi {
4045*7c5988f9SRobert Mustacchi struct e1000_nvm_info *nvm = &hw->nvm;
4046*7c5988f9SRobert Mustacchi struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
4047*7c5988f9SRobert Mustacchi u32 i, act_offset, new_bank_offset, old_bank_offset, bank;
4048*7c5988f9SRobert Mustacchi s32 ret_val;
4049*7c5988f9SRobert Mustacchi u32 dword = 0;
4050*7c5988f9SRobert Mustacchi
4051*7c5988f9SRobert Mustacchi DEBUGFUNC("e1000_update_nvm_checksum_spt");
4052*7c5988f9SRobert Mustacchi
4053*7c5988f9SRobert Mustacchi ret_val = e1000_update_nvm_checksum_generic(hw);
4054*7c5988f9SRobert Mustacchi if (ret_val)
4055*7c5988f9SRobert Mustacchi goto out;
4056*7c5988f9SRobert Mustacchi
4057*7c5988f9SRobert Mustacchi if (nvm->type != e1000_nvm_flash_sw)
4058*7c5988f9SRobert Mustacchi goto out;
4059*7c5988f9SRobert Mustacchi
4060*7c5988f9SRobert Mustacchi nvm->ops.acquire(hw);
4061*7c5988f9SRobert Mustacchi
4062*7c5988f9SRobert Mustacchi /* We're writing to the opposite bank so if we're on bank 1,
4063*7c5988f9SRobert Mustacchi * write to bank 0 etc. We also need to erase the segment that
4064*7c5988f9SRobert Mustacchi * is going to be written
4065*7c5988f9SRobert Mustacchi */
4066*7c5988f9SRobert Mustacchi ret_val = e1000_valid_nvm_bank_detect_ich8lan(hw, &bank);
4067*7c5988f9SRobert Mustacchi if (ret_val != E1000_SUCCESS) {
4068*7c5988f9SRobert Mustacchi DEBUGOUT("Could not detect valid bank, assuming bank 0\n");
4069*7c5988f9SRobert Mustacchi bank = 0;
4070*7c5988f9SRobert Mustacchi }
4071*7c5988f9SRobert Mustacchi
4072*7c5988f9SRobert Mustacchi if (bank == 0) {
4073*7c5988f9SRobert Mustacchi new_bank_offset = nvm->flash_bank_size;
4074*7c5988f9SRobert Mustacchi old_bank_offset = 0;
4075*7c5988f9SRobert Mustacchi ret_val = e1000_erase_flash_bank_ich8lan(hw, 1);
4076*7c5988f9SRobert Mustacchi if (ret_val)
4077*7c5988f9SRobert Mustacchi goto release;
4078*7c5988f9SRobert Mustacchi } else {
4079*7c5988f9SRobert Mustacchi old_bank_offset = nvm->flash_bank_size;
4080*7c5988f9SRobert Mustacchi new_bank_offset = 0;
4081*7c5988f9SRobert Mustacchi ret_val = e1000_erase_flash_bank_ich8lan(hw, 0);
4082*7c5988f9SRobert Mustacchi if (ret_val)
4083*7c5988f9SRobert Mustacchi goto release;
4084*7c5988f9SRobert Mustacchi }
4085*7c5988f9SRobert Mustacchi for (i = 0; i < E1000_SHADOW_RAM_WORDS; i += 2) {
4086*7c5988f9SRobert Mustacchi /* Determine whether to write the value stored
4087*7c5988f9SRobert Mustacchi * in the other NVM bank or a modified value stored
4088*7c5988f9SRobert Mustacchi * in the shadow RAM
4089*7c5988f9SRobert Mustacchi */
4090*7c5988f9SRobert Mustacchi ret_val = e1000_read_flash_dword_ich8lan(hw,
4091*7c5988f9SRobert Mustacchi i + old_bank_offset,
4092*7c5988f9SRobert Mustacchi &dword);
4093*7c5988f9SRobert Mustacchi
4094*7c5988f9SRobert Mustacchi if (dev_spec->shadow_ram[i].modified) {
4095*7c5988f9SRobert Mustacchi dword &= 0xffff0000;
4096*7c5988f9SRobert Mustacchi dword |= (dev_spec->shadow_ram[i].value & 0xffff);
4097*7c5988f9SRobert Mustacchi }
4098*7c5988f9SRobert Mustacchi if (dev_spec->shadow_ram[i + 1].modified) {
4099*7c5988f9SRobert Mustacchi dword &= 0x0000ffff;
4100*7c5988f9SRobert Mustacchi dword |= ((dev_spec->shadow_ram[i + 1].value & 0xffff)
4101*7c5988f9SRobert Mustacchi << 16);
4102*7c5988f9SRobert Mustacchi }
4103*7c5988f9SRobert Mustacchi if (ret_val)
4104*7c5988f9SRobert Mustacchi break;
4105*7c5988f9SRobert Mustacchi
4106*7c5988f9SRobert Mustacchi /* If the word is 0x13, then make sure the signature bits
4107*7c5988f9SRobert Mustacchi * (15:14) are 11b until the commit has completed.
4108*7c5988f9SRobert Mustacchi * This will allow us to write 10b which indicates the
4109*7c5988f9SRobert Mustacchi * signature is valid. We want to do this after the write
4110*7c5988f9SRobert Mustacchi * has completed so that we don't mark the segment valid
4111*7c5988f9SRobert Mustacchi * while the write is still in progress
4112*7c5988f9SRobert Mustacchi */
4113*7c5988f9SRobert Mustacchi if (i == E1000_ICH_NVM_SIG_WORD - 1)
4114*7c5988f9SRobert Mustacchi dword |= E1000_ICH_NVM_SIG_MASK << 16;
4115*7c5988f9SRobert Mustacchi
4116*7c5988f9SRobert Mustacchi /* Convert offset to bytes. */
4117*7c5988f9SRobert Mustacchi act_offset = (i + new_bank_offset) << 1;
4118*7c5988f9SRobert Mustacchi
4119*7c5988f9SRobert Mustacchi usec_delay(100);
4120*7c5988f9SRobert Mustacchi
4121*7c5988f9SRobert Mustacchi /* Write the data to the new bank. Offset in words*/
4122*7c5988f9SRobert Mustacchi act_offset = i + new_bank_offset;
4123*7c5988f9SRobert Mustacchi ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset,
4124*7c5988f9SRobert Mustacchi dword);
4125*7c5988f9SRobert Mustacchi if (ret_val)
4126*7c5988f9SRobert Mustacchi break;
4127*7c5988f9SRobert Mustacchi }
4128*7c5988f9SRobert Mustacchi
4129*7c5988f9SRobert Mustacchi /* Don't bother writing the segment valid bits if sector
4130*7c5988f9SRobert Mustacchi * programming failed.
4131*7c5988f9SRobert Mustacchi */
4132*7c5988f9SRobert Mustacchi if (ret_val) {
4133*7c5988f9SRobert Mustacchi DEBUGOUT("Flash commit failed.\n");
4134*7c5988f9SRobert Mustacchi goto release;
4135*7c5988f9SRobert Mustacchi }
4136*7c5988f9SRobert Mustacchi
4137*7c5988f9SRobert Mustacchi /* Finally validate the new segment by setting bit 15:14
4138*7c5988f9SRobert Mustacchi * to 10b in word 0x13 , this can be done without an
4139*7c5988f9SRobert Mustacchi * erase as well since these bits are 11 to start with
4140*7c5988f9SRobert Mustacchi * and we need to change bit 14 to 0b
4141*7c5988f9SRobert Mustacchi */
4142*7c5988f9SRobert Mustacchi act_offset = new_bank_offset + E1000_ICH_NVM_SIG_WORD;
4143*7c5988f9SRobert Mustacchi
4144*7c5988f9SRobert Mustacchi /*offset in words but we read dword*/
4145*7c5988f9SRobert Mustacchi --act_offset;
4146*7c5988f9SRobert Mustacchi ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
4147*7c5988f9SRobert Mustacchi
4148*7c5988f9SRobert Mustacchi if (ret_val)
4149*7c5988f9SRobert Mustacchi goto release;
4150*7c5988f9SRobert Mustacchi
4151*7c5988f9SRobert Mustacchi dword &= 0xBFFFFFFF;
4152*7c5988f9SRobert Mustacchi ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
4153*7c5988f9SRobert Mustacchi
4154*7c5988f9SRobert Mustacchi if (ret_val)
4155*7c5988f9SRobert Mustacchi goto release;
4156*7c5988f9SRobert Mustacchi
4157*7c5988f9SRobert Mustacchi /* And invalidate the previously valid segment by setting
4158*7c5988f9SRobert Mustacchi * its signature word (0x13) high_byte to 0b. This can be
4159*7c5988f9SRobert Mustacchi * done without an erase because flash erase sets all bits
4160*7c5988f9SRobert Mustacchi * to 1's. We can write 1's to 0's without an erase
4161*7c5988f9SRobert Mustacchi */
4162*7c5988f9SRobert Mustacchi act_offset = (old_bank_offset + E1000_ICH_NVM_SIG_WORD) * 2 + 1;
4163*7c5988f9SRobert Mustacchi
4164*7c5988f9SRobert Mustacchi /* offset in words but we read dword*/
4165*7c5988f9SRobert Mustacchi act_offset = old_bank_offset + E1000_ICH_NVM_SIG_WORD - 1;
4166*7c5988f9SRobert Mustacchi ret_val = e1000_read_flash_dword_ich8lan(hw, act_offset, &dword);
4167*7c5988f9SRobert Mustacchi
4168*7c5988f9SRobert Mustacchi if (ret_val)
4169*7c5988f9SRobert Mustacchi goto release;
4170*7c5988f9SRobert Mustacchi
4171*7c5988f9SRobert Mustacchi dword &= 0x00FFFFFF;
4172*7c5988f9SRobert Mustacchi ret_val = e1000_retry_write_flash_dword_ich8lan(hw, act_offset, dword);
4173*7c5988f9SRobert Mustacchi
4174*7c5988f9SRobert Mustacchi if (ret_val)
4175*7c5988f9SRobert Mustacchi goto release;
4176*7c5988f9SRobert Mustacchi
4177*7c5988f9SRobert Mustacchi /* Great! Everything worked, we can now clear the cached entries. */
4178*7c5988f9SRobert Mustacchi for (i = 0; i < E1000_SHADOW_RAM_WORDS; i++) {
4179*7c5988f9SRobert Mustacchi dev_spec->shadow_ram[i].modified = FALSE;
4180*7c5988f9SRobert Mustacchi dev_spec->shadow_ram[i].value = 0xFFFF;
4181*7c5988f9SRobert Mustacchi }
4182*7c5988f9SRobert Mustacchi
4183*7c5988f9SRobert Mustacchi release:
4184*7c5988f9SRobert Mustacchi nvm->ops.release(hw);
4185*7c5988f9SRobert Mustacchi
4186*7c5988f9SRobert Mustacchi /* Reload the EEPROM, or else modifications will not appear
4187*7c5988f9SRobert Mustacchi * until after the next adapter reset.
4188*7c5988f9SRobert Mustacchi */
4189*7c5988f9SRobert Mustacchi if (!ret_val) {
4190*7c5988f9SRobert Mustacchi nvm->ops.reload(hw);
4191*7c5988f9SRobert Mustacchi msec_delay(10);
4192*7c5988f9SRobert Mustacchi }
4193*7c5988f9SRobert Mustacchi
4194*7c5988f9SRobert Mustacchi out:
4195*7c5988f9SRobert Mustacchi if (ret_val)
4196*7c5988f9SRobert Mustacchi DEBUGOUT1("NVM update error: %d\n", ret_val);
4197*7c5988f9SRobert Mustacchi
4198*7c5988f9SRobert Mustacchi return ret_val;
4199*7c5988f9SRobert Mustacchi }
4200*7c5988f9SRobert Mustacchi
4201*7c5988f9SRobert 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 **/
e1000_update_nvm_checksum_ich8lan(struct e1000_hw * hw)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 **/
e1000_validate_nvm_checksum_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert 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 **/
e1000_write_flash_data_ich8lan(struct e1000_hw * hw,u32 offset,u8 size,u16 data)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*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt) {
4427*7c5988f9SRobert Mustacchi if (size != 4 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
4428*7c5988f9SRobert Mustacchi return -E1000_ERR_NVM;
4429*7c5988f9SRobert Mustacchi } else {
4430c124a83eSRobert Mustacchi if (size < 1 || size > 2 || offset > ICH_FLASH_LINEAR_ADDR_MASK)
443175eba5b6SRobert Mustacchi return -E1000_ERR_NVM;
4432*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi /* In SPT, This register is in Lan memory space, not
4444*7c5988f9SRobert Mustacchi * flash. Therefore, only 32 bit access is supported
4445*7c5988f9SRobert Mustacchi */
4446*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
4447*7c5988f9SRobert Mustacchi hsflctl.regval =
4448*7c5988f9SRobert Mustacchi E1000_READ_FLASH_REG(hw, ICH_FLASH_HSFSTS)>>16;
4449*7c5988f9SRobert Mustacchi else
4450*7c5988f9SRobert Mustacchi hsflctl.regval =
4451*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi /* In SPT, This register is in Lan memory space,
4457*7c5988f9SRobert Mustacchi * not flash. Therefore, only 32 bit access is
4458*7c5988f9SRobert Mustacchi * supported
4459*7c5988f9SRobert Mustacchi */
4460*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
4461*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
4462*7c5988f9SRobert Mustacchi hsflctl.regval << 16);
4463*7c5988f9SRobert Mustacchi else
4464*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
4465*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi /**
4504*7c5988f9SRobert Mustacchi * e1000_write_flash_data32_ich8lan - Writes 4 bytes to the NVM
4505*7c5988f9SRobert Mustacchi * @hw: pointer to the HW structure
4506*7c5988f9SRobert Mustacchi * @offset: The offset (in bytes) of the dwords to read.
4507*7c5988f9SRobert Mustacchi * @data: The 4 bytes to write to the NVM.
4508*7c5988f9SRobert Mustacchi *
4509*7c5988f9SRobert Mustacchi * Writes one/two/four bytes to the NVM using the flash access registers.
4510*7c5988f9SRobert Mustacchi **/
e1000_write_flash_data32_ich8lan(struct e1000_hw * hw,u32 offset,u32 data)4511*7c5988f9SRobert Mustacchi static s32 e1000_write_flash_data32_ich8lan(struct e1000_hw *hw, u32 offset,
4512*7c5988f9SRobert Mustacchi u32 data)
4513*7c5988f9SRobert Mustacchi {
4514*7c5988f9SRobert Mustacchi union ich8_hws_flash_status hsfsts;
4515*7c5988f9SRobert Mustacchi union ich8_hws_flash_ctrl hsflctl;
4516*7c5988f9SRobert Mustacchi u32 flash_linear_addr;
4517*7c5988f9SRobert Mustacchi s32 ret_val;
4518*7c5988f9SRobert Mustacchi u8 count = 0;
4519*7c5988f9SRobert Mustacchi
4520*7c5988f9SRobert Mustacchi DEBUGFUNC("e1000_write_flash_data32_ich8lan");
4521*7c5988f9SRobert Mustacchi
4522*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt) {
4523*7c5988f9SRobert Mustacchi if (offset > ICH_FLASH_LINEAR_ADDR_MASK)
4524*7c5988f9SRobert Mustacchi return -E1000_ERR_NVM;
4525*7c5988f9SRobert Mustacchi }
4526*7c5988f9SRobert Mustacchi flash_linear_addr = ((ICH_FLASH_LINEAR_ADDR_MASK & offset) +
4527*7c5988f9SRobert Mustacchi hw->nvm.flash_base_addr);
4528*7c5988f9SRobert Mustacchi do {
4529*7c5988f9SRobert Mustacchi usec_delay(1);
4530*7c5988f9SRobert Mustacchi /* Steps */
4531*7c5988f9SRobert Mustacchi ret_val = e1000_flash_cycle_init_ich8lan(hw);
4532*7c5988f9SRobert Mustacchi if (ret_val != E1000_SUCCESS)
4533*7c5988f9SRobert Mustacchi break;
4534*7c5988f9SRobert Mustacchi
4535*7c5988f9SRobert Mustacchi /* In SPT, This register is in Lan memory space, not
4536*7c5988f9SRobert Mustacchi * flash. Therefore, only 32 bit access is supported
4537*7c5988f9SRobert Mustacchi */
4538*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
4539*7c5988f9SRobert Mustacchi hsflctl.regval = E1000_READ_FLASH_REG(hw,
4540*7c5988f9SRobert Mustacchi ICH_FLASH_HSFSTS)
4541*7c5988f9SRobert Mustacchi >> 16;
4542*7c5988f9SRobert Mustacchi else
4543*7c5988f9SRobert Mustacchi hsflctl.regval = E1000_READ_FLASH_REG16(hw,
4544*7c5988f9SRobert Mustacchi ICH_FLASH_HSFCTL);
4545*7c5988f9SRobert Mustacchi
4546*7c5988f9SRobert Mustacchi hsflctl.hsf_ctrl.fldbcount = sizeof(u32) - 1;
4547*7c5988f9SRobert Mustacchi hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_WRITE;
4548*7c5988f9SRobert Mustacchi
4549*7c5988f9SRobert Mustacchi /* In SPT, This register is in Lan memory space,
4550*7c5988f9SRobert Mustacchi * not flash. Therefore, only 32 bit access is
4551*7c5988f9SRobert Mustacchi * supported
4552*7c5988f9SRobert Mustacchi */
4553*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
4554*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
4555*7c5988f9SRobert Mustacchi hsflctl.regval << 16);
4556*7c5988f9SRobert Mustacchi else
4557*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG16(hw, ICH_FLASH_HSFCTL,
4558*7c5988f9SRobert Mustacchi hsflctl.regval);
4559*7c5988f9SRobert Mustacchi
4560*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FADDR, flash_linear_addr);
4561*7c5988f9SRobert Mustacchi
4562*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_FDATA0, data);
4563*7c5988f9SRobert Mustacchi
4564*7c5988f9SRobert Mustacchi /* check if FCERR is set to 1 , if set to 1, clear it
4565*7c5988f9SRobert Mustacchi * and try the whole sequence a few more times else done
4566*7c5988f9SRobert Mustacchi */
4567*7c5988f9SRobert Mustacchi ret_val = e1000_flash_cycle_ich8lan(hw,
4568*7c5988f9SRobert Mustacchi ICH_FLASH_WRITE_COMMAND_TIMEOUT);
4569*7c5988f9SRobert Mustacchi
4570*7c5988f9SRobert Mustacchi if (ret_val == E1000_SUCCESS)
4571*7c5988f9SRobert Mustacchi break;
4572*7c5988f9SRobert Mustacchi
4573*7c5988f9SRobert Mustacchi /* If we're here, then things are most likely
4574*7c5988f9SRobert Mustacchi * completely hosed, but if the error condition
4575*7c5988f9SRobert Mustacchi * is detected, it won't hurt to give it another
4576*7c5988f9SRobert Mustacchi * try...ICH_FLASH_CYCLE_REPEAT_COUNT times.
4577*7c5988f9SRobert Mustacchi */
4578*7c5988f9SRobert Mustacchi hsfsts.regval = E1000_READ_FLASH_REG16(hw, ICH_FLASH_HSFSTS);
4579*7c5988f9SRobert Mustacchi
4580*7c5988f9SRobert Mustacchi if (hsfsts.hsf_status.flcerr)
4581*7c5988f9SRobert Mustacchi /* Repeat for some time before giving up. */
4582*7c5988f9SRobert Mustacchi continue;
4583*7c5988f9SRobert Mustacchi if (!hsfsts.hsf_status.flcdone) {
4584*7c5988f9SRobert Mustacchi DEBUGOUT("Timeout error - flash cycle did not complete.\n");
4585*7c5988f9SRobert Mustacchi break;
4586*7c5988f9SRobert Mustacchi }
4587*7c5988f9SRobert Mustacchi } while (count++ < ICH_FLASH_CYCLE_REPEAT_COUNT);
4588*7c5988f9SRobert Mustacchi
4589*7c5988f9SRobert Mustacchi return ret_val;
4590*7c5988f9SRobert 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 **/
e1000_write_flash_byte_ich8lan(struct e1000_hw * hw,u32 offset,u8 data)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*7c5988f9SRobert Mustacchi /**
4611*7c5988f9SRobert Mustacchi * e1000_retry_write_flash_dword_ich8lan - Writes a dword to NVM
4612*7c5988f9SRobert Mustacchi * @hw: pointer to the HW structure
4613*7c5988f9SRobert Mustacchi * @offset: The offset of the word to write.
4614*7c5988f9SRobert Mustacchi * @dword: The dword to write to the NVM.
4615*7c5988f9SRobert Mustacchi *
4616*7c5988f9SRobert Mustacchi * Writes a single dword to the NVM using the flash access registers.
4617*7c5988f9SRobert Mustacchi * Goes through a retry algorithm before giving up.
4618*7c5988f9SRobert Mustacchi **/
e1000_retry_write_flash_dword_ich8lan(struct e1000_hw * hw,u32 offset,u32 dword)4619*7c5988f9SRobert Mustacchi static s32 e1000_retry_write_flash_dword_ich8lan(struct e1000_hw *hw,
4620*7c5988f9SRobert Mustacchi u32 offset, u32 dword)
4621*7c5988f9SRobert Mustacchi {
4622*7c5988f9SRobert Mustacchi s32 ret_val;
4623*7c5988f9SRobert Mustacchi u16 program_retries;
4624c124a83eSRobert Mustacchi
4625*7c5988f9SRobert Mustacchi DEBUGFUNC("e1000_retry_write_flash_dword_ich8lan");
4626*7c5988f9SRobert Mustacchi
4627*7c5988f9SRobert Mustacchi /* Must convert word offset into bytes. */
4628*7c5988f9SRobert Mustacchi offset <<= 1;
4629*7c5988f9SRobert Mustacchi
4630*7c5988f9SRobert Mustacchi ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
4631*7c5988f9SRobert Mustacchi
4632*7c5988f9SRobert Mustacchi if (!ret_val)
4633*7c5988f9SRobert Mustacchi return ret_val;
4634*7c5988f9SRobert Mustacchi for (program_retries = 0; program_retries < 100; program_retries++) {
4635*7c5988f9SRobert Mustacchi DEBUGOUT2("Retrying Byte %8.8X at offset %u\n", dword, offset);
4636*7c5988f9SRobert Mustacchi usec_delay(100);
4637*7c5988f9SRobert Mustacchi ret_val = e1000_write_flash_data32_ich8lan(hw, offset, dword);
4638*7c5988f9SRobert Mustacchi if (ret_val == E1000_SUCCESS)
4639*7c5988f9SRobert Mustacchi break;
4640*7c5988f9SRobert Mustacchi }
4641*7c5988f9SRobert Mustacchi if (program_retries == 100)
4642*7c5988f9SRobert Mustacchi return -E1000_ERR_NVM;
4643*7c5988f9SRobert Mustacchi
4644*7c5988f9SRobert Mustacchi return E1000_SUCCESS;
4645*7c5988f9SRobert 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 **/
e1000_retry_write_flash_byte_ich8lan(struct e1000_hw * hw,u32 offset,u8 byte)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 **/
e1000_erase_flash_bank_ich8lan(struct e1000_hw * hw,u32 bank)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*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
4756c124a83eSRobert Mustacchi hsflctl.regval =
4757*7c5988f9SRobert Mustacchi E1000_READ_FLASH_REG(hw,
4758*7c5988f9SRobert Mustacchi ICH_FLASH_HSFSTS)>>16;
4759*7c5988f9SRobert Mustacchi else
4760*7c5988f9SRobert Mustacchi hsflctl.regval =
4761*7c5988f9SRobert Mustacchi E1000_READ_FLASH_REG16(hw,
4762*7c5988f9SRobert Mustacchi ICH_FLASH_HSFCTL);
4763c124a83eSRobert Mustacchi
476475eba5b6SRobert Mustacchi hsflctl.hsf_ctrl.flcycle = ICH_CYCLE_ERASE;
4765*7c5988f9SRobert Mustacchi if (hw->mac.type == e1000_pch_spt)
4766*7c5988f9SRobert Mustacchi E1000_WRITE_FLASH_REG(hw, ICH_FLASH_HSFSTS,
4767*7c5988f9SRobert Mustacchi hsflctl.regval << 16);
4768*7c5988f9SRobert 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 **/
e1000_valid_led_default_ich8lan(struct e1000_hw * hw,u16 * data)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 **/
e1000_id_led_init_pchlan(struct e1000_hw * hw)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 **/
e1000_get_bus_info_ich8lan(struct e1000_hw * hw)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 **/
e1000_reset_hw_ich8lan(struct e1000_hw * hw)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 **/
e1000_init_hw_ich8lan(struct e1000_hw * hw)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 **/
e1000_initialize_hw_bits_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert Mustacchi if ((hw->mac.type == e1000_pch_lpt) ||
5204*7c5988f9SRobert 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 **/
e1000_setup_link_ich8lan(struct e1000_hw * hw)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 **/
e1000_setup_copper_link_ich8lan(struct e1000_hw * hw)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 ®_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 ®_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 **/
e1000_setup_copper_link_pch_lpt(struct e1000_hw * hw)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 **/
e1000_get_link_up_info_ich8lan(struct e1000_hw * hw,u16 * speed,u16 * duplex)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 **/
e1000_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw * hw)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 **/
e1000_set_kmrn_lock_loss_workaround_ich8lan(struct e1000_hw * hw,bool state)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 **/
e1000_igp3_phy_powerdown_workaround_ich8lan(struct e1000_hw * hw)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 **/
e1000_gig_downshift_workaround_ich8lan(struct e1000_hw * hw)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 ®_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 **/
e1000_suspend_workarounds_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert Mustacchi (device_id == E1000_DEV_ID_PCH_I218_V3) ||
5637*7c5988f9SRobert 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 **/
e1000_resume_workarounds_pchlan(struct e1000_hw * hw)5753*7c5988f9SRobert 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*7c5988f9SRobert 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*7c5988f9SRobert 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*7c5988f9SRobert 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*7c5988f9SRobert Mustacchi return ret_val;
581375eba5b6SRobert Mustacchi }
5814*7c5988f9SRobert 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 **/
e1000_cleanup_led_ich8lan(struct e1000_hw * hw)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 **/
e1000_led_on_ich8lan(struct e1000_hw * hw)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 **/
e1000_led_off_ich8lan(struct e1000_hw * hw)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 **/
e1000_setup_led_pchlan(struct e1000_hw * hw)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 **/
e1000_cleanup_led_pchlan(struct e1000_hw * hw)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 **/
e1000_led_on_pchlan(struct e1000_hw * hw)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 **/
e1000_led_off_pchlan(struct e1000_hw * hw)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 **/
e1000_get_cfg_done_ich8lan(struct e1000_hw * hw)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*7c5988f9SRobert Mustacchi if (status & E1000_STATUS_PHYRA)
600375eba5b6SRobert Mustacchi E1000_WRITE_REG(hw, E1000_STATUS, status & ~E1000_STATUS_PHYRA);
6004*7c5988f9SRobert 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 **/
e1000_power_down_phy_copper_ich8lan(struct e1000_hw * hw)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 **/
e1000_clear_hw_cntrs_ich8lan(struct e1000_hw * hw)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