xref: /titanic_51/usr/src/uts/common/io/e1000api/e1000_phy.c (revision 42cc51e07cdbcad3b9aca8d9d991fc09b251feb7)
175eba5b6SRobert Mustacchi /******************************************************************************
275eba5b6SRobert Mustacchi 
3*42cc51e0SRobert Mustacchi   Copyright (c) 2001-2015, Intel Corporation
475eba5b6SRobert Mustacchi   All rights reserved.
575eba5b6SRobert Mustacchi 
675eba5b6SRobert Mustacchi   Redistribution and use in source and binary forms, with or without
775eba5b6SRobert Mustacchi   modification, are permitted provided that the following conditions are met:
875eba5b6SRobert Mustacchi 
975eba5b6SRobert Mustacchi    1. Redistributions of source code must retain the above copyright notice,
1075eba5b6SRobert Mustacchi       this list of conditions and the following disclaimer.
1175eba5b6SRobert Mustacchi 
1275eba5b6SRobert Mustacchi    2. Redistributions in binary form must reproduce the above copyright
1375eba5b6SRobert Mustacchi       notice, this list of conditions and the following disclaimer in the
1475eba5b6SRobert Mustacchi       documentation and/or other materials provided with the distribution.
1575eba5b6SRobert Mustacchi 
1675eba5b6SRobert Mustacchi    3. Neither the name of the Intel Corporation nor the names of its
1775eba5b6SRobert Mustacchi       contributors may be used to endorse or promote products derived from
1875eba5b6SRobert Mustacchi       this software without specific prior written permission.
1975eba5b6SRobert Mustacchi 
2075eba5b6SRobert Mustacchi   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
2175eba5b6SRobert Mustacchi   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2275eba5b6SRobert Mustacchi   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2375eba5b6SRobert Mustacchi   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
2475eba5b6SRobert Mustacchi   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
2575eba5b6SRobert Mustacchi   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
2675eba5b6SRobert Mustacchi   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
2775eba5b6SRobert Mustacchi   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
2875eba5b6SRobert Mustacchi   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
2975eba5b6SRobert Mustacchi   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
3075eba5b6SRobert Mustacchi   POSSIBILITY OF SUCH DAMAGE.
3175eba5b6SRobert Mustacchi 
3275eba5b6SRobert Mustacchi ******************************************************************************/
3375eba5b6SRobert Mustacchi /*$FreeBSD$*/
3475eba5b6SRobert Mustacchi 
3575eba5b6SRobert Mustacchi #include "e1000_api.h"
3675eba5b6SRobert Mustacchi 
3775eba5b6SRobert Mustacchi static s32 e1000_wait_autoneg(struct e1000_hw *hw);
3875eba5b6SRobert Mustacchi static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
3975eba5b6SRobert Mustacchi 					  u16 *data, bool read, bool page_set);
4075eba5b6SRobert Mustacchi static u32 e1000_get_phy_addr_for_hv_page(u32 page);
4175eba5b6SRobert Mustacchi static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
4275eba5b6SRobert Mustacchi 					  u16 *data, bool read);
4375eba5b6SRobert Mustacchi 
4475eba5b6SRobert Mustacchi /* Cable length tables */
4575eba5b6SRobert Mustacchi static const u16 e1000_m88_cable_length_table[] = {
4675eba5b6SRobert Mustacchi 	0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
4775eba5b6SRobert Mustacchi #define M88E1000_CABLE_LENGTH_TABLE_SIZE \
4875eba5b6SRobert Mustacchi 		(sizeof(e1000_m88_cable_length_table) / \
4975eba5b6SRobert Mustacchi 		 sizeof(e1000_m88_cable_length_table[0]))
5075eba5b6SRobert Mustacchi 
5175eba5b6SRobert Mustacchi static const u16 e1000_igp_2_cable_length_table[] = {
5275eba5b6SRobert Mustacchi 	0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
5375eba5b6SRobert Mustacchi 	6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
5475eba5b6SRobert Mustacchi 	26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
5575eba5b6SRobert Mustacchi 	44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
5675eba5b6SRobert Mustacchi 	66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
5775eba5b6SRobert Mustacchi 	87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
5875eba5b6SRobert Mustacchi 	100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
5975eba5b6SRobert Mustacchi 	124};
6075eba5b6SRobert Mustacchi #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
6175eba5b6SRobert Mustacchi 		(sizeof(e1000_igp_2_cable_length_table) / \
6275eba5b6SRobert Mustacchi 		 sizeof(e1000_igp_2_cable_length_table[0]))
6375eba5b6SRobert Mustacchi 
6475eba5b6SRobert Mustacchi /**
6575eba5b6SRobert Mustacchi  *  e1000_init_phy_ops_generic - Initialize PHY function pointers
6675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
6775eba5b6SRobert Mustacchi  *
6875eba5b6SRobert Mustacchi  *  Setups up the function pointers to no-op functions
6975eba5b6SRobert Mustacchi  **/
7075eba5b6SRobert Mustacchi void e1000_init_phy_ops_generic(struct e1000_hw *hw)
7175eba5b6SRobert Mustacchi {
7275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
7375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_init_phy_ops_generic");
7475eba5b6SRobert Mustacchi 
7575eba5b6SRobert Mustacchi 	/* Initialize function pointers */
7675eba5b6SRobert Mustacchi 	phy->ops.init_params = e1000_null_ops_generic;
7775eba5b6SRobert Mustacchi 	phy->ops.acquire = e1000_null_ops_generic;
7875eba5b6SRobert Mustacchi 	phy->ops.check_polarity = e1000_null_ops_generic;
7975eba5b6SRobert Mustacchi 	phy->ops.check_reset_block = e1000_null_ops_generic;
8075eba5b6SRobert Mustacchi 	phy->ops.commit = e1000_null_ops_generic;
8175eba5b6SRobert Mustacchi 	phy->ops.force_speed_duplex = e1000_null_ops_generic;
8275eba5b6SRobert Mustacchi 	phy->ops.get_cfg_done = e1000_null_ops_generic;
8375eba5b6SRobert Mustacchi 	phy->ops.get_cable_length = e1000_null_ops_generic;
8475eba5b6SRobert Mustacchi 	phy->ops.get_info = e1000_null_ops_generic;
8575eba5b6SRobert Mustacchi 	phy->ops.set_page = e1000_null_set_page;
8675eba5b6SRobert Mustacchi 	phy->ops.read_reg = e1000_null_read_reg;
8775eba5b6SRobert Mustacchi 	phy->ops.read_reg_locked = e1000_null_read_reg;
8875eba5b6SRobert Mustacchi 	phy->ops.read_reg_page = e1000_null_read_reg;
8975eba5b6SRobert Mustacchi 	phy->ops.release = e1000_null_phy_generic;
9075eba5b6SRobert Mustacchi 	phy->ops.reset = e1000_null_ops_generic;
9175eba5b6SRobert Mustacchi 	phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
9275eba5b6SRobert Mustacchi 	phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
9375eba5b6SRobert Mustacchi 	phy->ops.write_reg = e1000_null_write_reg;
9475eba5b6SRobert Mustacchi 	phy->ops.write_reg_locked = e1000_null_write_reg;
9575eba5b6SRobert Mustacchi 	phy->ops.write_reg_page = e1000_null_write_reg;
9675eba5b6SRobert Mustacchi 	phy->ops.power_up = e1000_null_phy_generic;
9775eba5b6SRobert Mustacchi 	phy->ops.power_down = e1000_null_phy_generic;
9875eba5b6SRobert Mustacchi 	phy->ops.read_i2c_byte = e1000_read_i2c_byte_null;
9975eba5b6SRobert Mustacchi 	phy->ops.write_i2c_byte = e1000_write_i2c_byte_null;
10075eba5b6SRobert Mustacchi 	phy->ops.cfg_on_link_up = e1000_null_ops_generic;
10175eba5b6SRobert Mustacchi }
10275eba5b6SRobert Mustacchi 
10375eba5b6SRobert Mustacchi /**
10475eba5b6SRobert Mustacchi  *  e1000_null_set_page - No-op function, return 0
10575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
10675eba5b6SRobert Mustacchi  **/
107c124a83eSRobert Mustacchi s32 e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG *hw,
108c124a83eSRobert Mustacchi 			u16 E1000_UNUSEDARG data)
10975eba5b6SRobert Mustacchi {
11075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_set_page");
11175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
11275eba5b6SRobert Mustacchi }
11375eba5b6SRobert Mustacchi 
11475eba5b6SRobert Mustacchi /**
11575eba5b6SRobert Mustacchi  *  e1000_null_read_reg - No-op function, return 0
11675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
11775eba5b6SRobert Mustacchi  **/
118c124a83eSRobert Mustacchi s32 e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG *hw,
119c124a83eSRobert Mustacchi 			u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG *data)
12075eba5b6SRobert Mustacchi {
12175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_read_reg");
12275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
12375eba5b6SRobert Mustacchi }
12475eba5b6SRobert Mustacchi 
12575eba5b6SRobert Mustacchi /**
12675eba5b6SRobert Mustacchi  *  e1000_null_phy_generic - No-op function, return void
12775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
12875eba5b6SRobert Mustacchi  **/
129c124a83eSRobert Mustacchi void e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG *hw)
13075eba5b6SRobert Mustacchi {
13175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_phy_generic");
13275eba5b6SRobert Mustacchi 	return;
13375eba5b6SRobert Mustacchi }
13475eba5b6SRobert Mustacchi 
13575eba5b6SRobert Mustacchi /**
13675eba5b6SRobert Mustacchi  *  e1000_null_lplu_state - No-op function, return 0
13775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
13875eba5b6SRobert Mustacchi  **/
139c124a83eSRobert Mustacchi s32 e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG *hw,
140c124a83eSRobert Mustacchi 			  bool E1000_UNUSEDARG active)
14175eba5b6SRobert Mustacchi {
14275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_lplu_state");
14375eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
14475eba5b6SRobert Mustacchi }
14575eba5b6SRobert Mustacchi 
14675eba5b6SRobert Mustacchi /**
14775eba5b6SRobert Mustacchi  *  e1000_null_write_reg - No-op function, return 0
14875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
14975eba5b6SRobert Mustacchi  **/
150c124a83eSRobert Mustacchi s32 e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG *hw,
151c124a83eSRobert Mustacchi 			 u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG data)
15275eba5b6SRobert Mustacchi {
15375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_null_write_reg");
15475eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
15575eba5b6SRobert Mustacchi }
15675eba5b6SRobert Mustacchi 
15775eba5b6SRobert Mustacchi /**
15875eba5b6SRobert Mustacchi  *  e1000_read_i2c_byte_null - No-op function, return 0
15975eba5b6SRobert Mustacchi  *  @hw: pointer to hardware structure
16075eba5b6SRobert Mustacchi  *  @byte_offset: byte offset to write
16175eba5b6SRobert Mustacchi  *  @dev_addr: device address
16275eba5b6SRobert Mustacchi  *  @data: data value read
16375eba5b6SRobert Mustacchi  *
16475eba5b6SRobert Mustacchi  **/
165c124a83eSRobert Mustacchi s32 e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
166c124a83eSRobert Mustacchi 			     u8 E1000_UNUSEDARG byte_offset,
167c124a83eSRobert Mustacchi 			     u8 E1000_UNUSEDARG dev_addr,
168c124a83eSRobert Mustacchi 			     u8 E1000_UNUSEDARG *data)
16975eba5b6SRobert Mustacchi {
17075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_i2c_byte_null");
17175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
17275eba5b6SRobert Mustacchi }
17375eba5b6SRobert Mustacchi 
17475eba5b6SRobert Mustacchi /**
17575eba5b6SRobert Mustacchi  *  e1000_write_i2c_byte_null - No-op function, return 0
17675eba5b6SRobert Mustacchi  *  @hw: pointer to hardware structure
17775eba5b6SRobert Mustacchi  *  @byte_offset: byte offset to write
17875eba5b6SRobert Mustacchi  *  @dev_addr: device address
17975eba5b6SRobert Mustacchi  *  @data: data value to write
18075eba5b6SRobert Mustacchi  *
18175eba5b6SRobert Mustacchi  **/
182c124a83eSRobert Mustacchi s32 e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
183c124a83eSRobert Mustacchi 			      u8 E1000_UNUSEDARG byte_offset,
184c124a83eSRobert Mustacchi 			      u8 E1000_UNUSEDARG dev_addr,
185c124a83eSRobert Mustacchi 			      u8 E1000_UNUSEDARG data)
18675eba5b6SRobert Mustacchi {
18775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_i2c_byte_null");
18875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
18975eba5b6SRobert Mustacchi }
19075eba5b6SRobert Mustacchi 
19175eba5b6SRobert Mustacchi /**
19275eba5b6SRobert Mustacchi  *  e1000_check_reset_block_generic - Check if PHY reset is blocked
19375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
19475eba5b6SRobert Mustacchi  *
19575eba5b6SRobert Mustacchi  *  Read the PHY management control register and check whether a PHY reset
19675eba5b6SRobert Mustacchi  *  is blocked.  If a reset is not blocked return E1000_SUCCESS, otherwise
19775eba5b6SRobert Mustacchi  *  return E1000_BLK_PHY_RESET (12).
19875eba5b6SRobert Mustacchi  **/
19975eba5b6SRobert Mustacchi s32 e1000_check_reset_block_generic(struct e1000_hw *hw)
20075eba5b6SRobert Mustacchi {
20175eba5b6SRobert Mustacchi 	u32 manc;
20275eba5b6SRobert Mustacchi 
20375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_reset_block");
20475eba5b6SRobert Mustacchi 
20575eba5b6SRobert Mustacchi 	manc = E1000_READ_REG(hw, E1000_MANC);
20675eba5b6SRobert Mustacchi 
20775eba5b6SRobert Mustacchi 	return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
20875eba5b6SRobert Mustacchi 	       E1000_BLK_PHY_RESET : E1000_SUCCESS;
20975eba5b6SRobert Mustacchi }
21075eba5b6SRobert Mustacchi 
21175eba5b6SRobert Mustacchi /**
21275eba5b6SRobert Mustacchi  *  e1000_get_phy_id - Retrieve the PHY ID and revision
21375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
21475eba5b6SRobert Mustacchi  *
21575eba5b6SRobert Mustacchi  *  Reads the PHY registers and stores the PHY ID and possibly the PHY
21675eba5b6SRobert Mustacchi  *  revision in the hardware structure.
21775eba5b6SRobert Mustacchi  **/
21875eba5b6SRobert Mustacchi s32 e1000_get_phy_id(struct e1000_hw *hw)
21975eba5b6SRobert Mustacchi {
22075eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
22175eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
22275eba5b6SRobert Mustacchi 	u16 phy_id;
22375eba5b6SRobert Mustacchi 	u16 retry_count = 0;
22475eba5b6SRobert Mustacchi 
22575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_phy_id");
22675eba5b6SRobert Mustacchi 
22775eba5b6SRobert Mustacchi 	if (!phy->ops.read_reg)
22875eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
22975eba5b6SRobert Mustacchi 
23075eba5b6SRobert Mustacchi 	while (retry_count < 2) {
23175eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
23275eba5b6SRobert Mustacchi 		if (ret_val)
23375eba5b6SRobert Mustacchi 			return ret_val;
23475eba5b6SRobert Mustacchi 
23575eba5b6SRobert Mustacchi 		phy->id = (u32)(phy_id << 16);
23675eba5b6SRobert Mustacchi 		usec_delay(20);
23775eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
23875eba5b6SRobert Mustacchi 		if (ret_val)
23975eba5b6SRobert Mustacchi 			return ret_val;
24075eba5b6SRobert Mustacchi 
24175eba5b6SRobert Mustacchi 		phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
24275eba5b6SRobert Mustacchi 		phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
24375eba5b6SRobert Mustacchi 
24475eba5b6SRobert Mustacchi 		if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
24575eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
24675eba5b6SRobert Mustacchi 
24775eba5b6SRobert Mustacchi 		retry_count++;
24875eba5b6SRobert Mustacchi 	}
24975eba5b6SRobert Mustacchi 
25075eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
25175eba5b6SRobert Mustacchi }
25275eba5b6SRobert Mustacchi 
25375eba5b6SRobert Mustacchi /**
25475eba5b6SRobert Mustacchi  *  e1000_phy_reset_dsp_generic - Reset PHY DSP
25575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
25675eba5b6SRobert Mustacchi  *
25775eba5b6SRobert Mustacchi  *  Reset the digital signal processor.
25875eba5b6SRobert Mustacchi  **/
25975eba5b6SRobert Mustacchi s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
26075eba5b6SRobert Mustacchi {
26175eba5b6SRobert Mustacchi 	s32 ret_val;
26275eba5b6SRobert Mustacchi 
26375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_reset_dsp_generic");
26475eba5b6SRobert Mustacchi 
26575eba5b6SRobert Mustacchi 	if (!hw->phy.ops.write_reg)
26675eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
26775eba5b6SRobert Mustacchi 
26875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
26975eba5b6SRobert Mustacchi 	if (ret_val)
27075eba5b6SRobert Mustacchi 		return ret_val;
27175eba5b6SRobert Mustacchi 
27275eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
27375eba5b6SRobert Mustacchi }
27475eba5b6SRobert Mustacchi 
27575eba5b6SRobert Mustacchi /**
27675eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_mdic - Read MDI control register
27775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
27875eba5b6SRobert Mustacchi  *  @offset: register offset to be read
27975eba5b6SRobert Mustacchi  *  @data: pointer to the read data
28075eba5b6SRobert Mustacchi  *
28175eba5b6SRobert Mustacchi  *  Reads the MDI control register in the PHY at offset and stores the
28275eba5b6SRobert Mustacchi  *  information read to data.
28375eba5b6SRobert Mustacchi  **/
28475eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
28575eba5b6SRobert Mustacchi {
28675eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
28775eba5b6SRobert Mustacchi 	u32 i, mdic = 0;
28875eba5b6SRobert Mustacchi 
28975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_mdic");
29075eba5b6SRobert Mustacchi 
29175eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_REG_ADDRESS) {
29275eba5b6SRobert Mustacchi 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
29375eba5b6SRobert Mustacchi 		return -E1000_ERR_PARAM;
29475eba5b6SRobert Mustacchi 	}
29575eba5b6SRobert Mustacchi 
29675eba5b6SRobert Mustacchi 	/* Set up Op-code, Phy Address, and register offset in the MDI
29775eba5b6SRobert Mustacchi 	 * Control register.  The MAC will take care of interfacing with the
29875eba5b6SRobert Mustacchi 	 * PHY to retrieve the desired data.
29975eba5b6SRobert Mustacchi 	 */
30075eba5b6SRobert Mustacchi 	mdic = ((offset << E1000_MDIC_REG_SHIFT) |
30175eba5b6SRobert Mustacchi 		(phy->addr << E1000_MDIC_PHY_SHIFT) |
30275eba5b6SRobert Mustacchi 		(E1000_MDIC_OP_READ));
30375eba5b6SRobert Mustacchi 
30475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_MDIC, mdic);
30575eba5b6SRobert Mustacchi 
30675eba5b6SRobert Mustacchi 	/* Poll the ready bit to see if the MDI read completed
30775eba5b6SRobert Mustacchi 	 * Increasing the time out as testing showed failures with
30875eba5b6SRobert Mustacchi 	 * the lower time out
30975eba5b6SRobert Mustacchi 	 */
31075eba5b6SRobert Mustacchi 	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
311c124a83eSRobert Mustacchi 		usec_delay_irq(50);
31275eba5b6SRobert Mustacchi 		mdic = E1000_READ_REG(hw, E1000_MDIC);
31375eba5b6SRobert Mustacchi 		if (mdic & E1000_MDIC_READY)
31475eba5b6SRobert Mustacchi 			break;
31575eba5b6SRobert Mustacchi 	}
31675eba5b6SRobert Mustacchi 	if (!(mdic & E1000_MDIC_READY)) {
31775eba5b6SRobert Mustacchi 		DEBUGOUT("MDI Read did not complete\n");
31875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
31975eba5b6SRobert Mustacchi 	}
32075eba5b6SRobert Mustacchi 	if (mdic & E1000_MDIC_ERROR) {
32175eba5b6SRobert Mustacchi 		DEBUGOUT("MDI Error\n");
32275eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
32375eba5b6SRobert Mustacchi 	}
32475eba5b6SRobert Mustacchi 	if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
32575eba5b6SRobert Mustacchi 		DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n",
32675eba5b6SRobert Mustacchi 			  offset,
32775eba5b6SRobert Mustacchi 			  (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
32875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
32975eba5b6SRobert Mustacchi 	}
33075eba5b6SRobert Mustacchi 	*data = (u16) mdic;
33175eba5b6SRobert Mustacchi 
33275eba5b6SRobert Mustacchi 	/* Allow some time after each MDIC transaction to avoid
33375eba5b6SRobert Mustacchi 	 * reading duplicate data in the next MDIC transaction.
33475eba5b6SRobert Mustacchi 	 */
33575eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pch2lan)
336c124a83eSRobert Mustacchi 		usec_delay_irq(100);
33775eba5b6SRobert Mustacchi 
33875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
33975eba5b6SRobert Mustacchi }
34075eba5b6SRobert Mustacchi 
34175eba5b6SRobert Mustacchi /**
34275eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_mdic - Write MDI control register
34375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
34475eba5b6SRobert Mustacchi  *  @offset: register offset to write to
34575eba5b6SRobert Mustacchi  *  @data: data to write to register at offset
34675eba5b6SRobert Mustacchi  *
34775eba5b6SRobert Mustacchi  *  Writes data to MDI control register in the PHY at offset.
34875eba5b6SRobert Mustacchi  **/
34975eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
35075eba5b6SRobert Mustacchi {
35175eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
35275eba5b6SRobert Mustacchi 	u32 i, mdic = 0;
35375eba5b6SRobert Mustacchi 
35475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_mdic");
35575eba5b6SRobert Mustacchi 
35675eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_REG_ADDRESS) {
35775eba5b6SRobert Mustacchi 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
35875eba5b6SRobert Mustacchi 		return -E1000_ERR_PARAM;
35975eba5b6SRobert Mustacchi 	}
36075eba5b6SRobert Mustacchi 
36175eba5b6SRobert Mustacchi 	/* Set up Op-code, Phy Address, and register offset in the MDI
36275eba5b6SRobert Mustacchi 	 * Control register.  The MAC will take care of interfacing with the
36375eba5b6SRobert Mustacchi 	 * PHY to retrieve the desired data.
36475eba5b6SRobert Mustacchi 	 */
36575eba5b6SRobert Mustacchi 	mdic = (((u32)data) |
36675eba5b6SRobert Mustacchi 		(offset << E1000_MDIC_REG_SHIFT) |
36775eba5b6SRobert Mustacchi 		(phy->addr << E1000_MDIC_PHY_SHIFT) |
36875eba5b6SRobert Mustacchi 		(E1000_MDIC_OP_WRITE));
36975eba5b6SRobert Mustacchi 
37075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_MDIC, mdic);
37175eba5b6SRobert Mustacchi 
37275eba5b6SRobert Mustacchi 	/* Poll the ready bit to see if the MDI read completed
37375eba5b6SRobert Mustacchi 	 * Increasing the time out as testing showed failures with
37475eba5b6SRobert Mustacchi 	 * the lower time out
37575eba5b6SRobert Mustacchi 	 */
37675eba5b6SRobert Mustacchi 	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
377c124a83eSRobert Mustacchi 		usec_delay_irq(50);
37875eba5b6SRobert Mustacchi 		mdic = E1000_READ_REG(hw, E1000_MDIC);
37975eba5b6SRobert Mustacchi 		if (mdic & E1000_MDIC_READY)
38075eba5b6SRobert Mustacchi 			break;
38175eba5b6SRobert Mustacchi 	}
38275eba5b6SRobert Mustacchi 	if (!(mdic & E1000_MDIC_READY)) {
38375eba5b6SRobert Mustacchi 		DEBUGOUT("MDI Write did not complete\n");
38475eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
38575eba5b6SRobert Mustacchi 	}
38675eba5b6SRobert Mustacchi 	if (mdic & E1000_MDIC_ERROR) {
38775eba5b6SRobert Mustacchi 		DEBUGOUT("MDI Error\n");
38875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
38975eba5b6SRobert Mustacchi 	}
39075eba5b6SRobert Mustacchi 	if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
39175eba5b6SRobert Mustacchi 		DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n",
39275eba5b6SRobert Mustacchi 			  offset,
39375eba5b6SRobert Mustacchi 			  (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
39475eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
39575eba5b6SRobert Mustacchi 	}
39675eba5b6SRobert Mustacchi 
39775eba5b6SRobert Mustacchi 	/* Allow some time after each MDIC transaction to avoid
39875eba5b6SRobert Mustacchi 	 * reading duplicate data in the next MDIC transaction.
39975eba5b6SRobert Mustacchi 	 */
40075eba5b6SRobert Mustacchi 	if (hw->mac.type == e1000_pch2lan)
401c124a83eSRobert Mustacchi 		usec_delay_irq(100);
40275eba5b6SRobert Mustacchi 
40375eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
40475eba5b6SRobert Mustacchi }
40575eba5b6SRobert Mustacchi 
40675eba5b6SRobert Mustacchi /**
40775eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_i2c - Read PHY register using i2c
40875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
40975eba5b6SRobert Mustacchi  *  @offset: register offset to be read
41075eba5b6SRobert Mustacchi  *  @data: pointer to the read data
41175eba5b6SRobert Mustacchi  *
41275eba5b6SRobert Mustacchi  *  Reads the PHY register at offset using the i2c interface and stores the
41375eba5b6SRobert Mustacchi  *  retrieved information in data.
41475eba5b6SRobert Mustacchi  **/
41575eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
41675eba5b6SRobert Mustacchi {
41775eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
41875eba5b6SRobert Mustacchi 	u32 i, i2ccmd = 0;
41975eba5b6SRobert Mustacchi 
42075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_i2c");
42175eba5b6SRobert Mustacchi 
42275eba5b6SRobert Mustacchi 	/* Set up Op-code, Phy Address, and register address in the I2CCMD
42375eba5b6SRobert Mustacchi 	 * register.  The MAC will take care of interfacing with the
42475eba5b6SRobert Mustacchi 	 * PHY to retrieve the desired data.
42575eba5b6SRobert Mustacchi 	 */
42675eba5b6SRobert Mustacchi 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
42775eba5b6SRobert Mustacchi 		  (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
42875eba5b6SRobert Mustacchi 		  (E1000_I2CCMD_OPCODE_READ));
42975eba5b6SRobert Mustacchi 
43075eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
43175eba5b6SRobert Mustacchi 
43275eba5b6SRobert Mustacchi 	/* Poll the ready bit to see if the I2C read completed */
43375eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
43475eba5b6SRobert Mustacchi 		usec_delay(50);
43575eba5b6SRobert Mustacchi 		i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
43675eba5b6SRobert Mustacchi 		if (i2ccmd & E1000_I2CCMD_READY)
43775eba5b6SRobert Mustacchi 			break;
43875eba5b6SRobert Mustacchi 	}
43975eba5b6SRobert Mustacchi 	if (!(i2ccmd & E1000_I2CCMD_READY)) {
44075eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Read did not complete\n");
44175eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
44275eba5b6SRobert Mustacchi 	}
44375eba5b6SRobert Mustacchi 	if (i2ccmd & E1000_I2CCMD_ERROR) {
44475eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Error bit set\n");
44575eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
44675eba5b6SRobert Mustacchi 	}
44775eba5b6SRobert Mustacchi 
44875eba5b6SRobert Mustacchi 	/* Need to byte-swap the 16-bit value. */
44975eba5b6SRobert Mustacchi 	*data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
45075eba5b6SRobert Mustacchi 
45175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
45275eba5b6SRobert Mustacchi }
45375eba5b6SRobert Mustacchi 
45475eba5b6SRobert Mustacchi /**
45575eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_i2c - Write PHY register using i2c
45675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
45775eba5b6SRobert Mustacchi  *  @offset: register offset to write to
45875eba5b6SRobert Mustacchi  *  @data: data to write at register offset
45975eba5b6SRobert Mustacchi  *
46075eba5b6SRobert Mustacchi  *  Writes the data to PHY register at the offset using the i2c interface.
46175eba5b6SRobert Mustacchi  **/
46275eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
46375eba5b6SRobert Mustacchi {
46475eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
46575eba5b6SRobert Mustacchi 	u32 i, i2ccmd = 0;
46675eba5b6SRobert Mustacchi 	u16 phy_data_swapped;
46775eba5b6SRobert Mustacchi 
46875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_i2c");
46975eba5b6SRobert Mustacchi 
47075eba5b6SRobert Mustacchi 	/* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/
47175eba5b6SRobert Mustacchi 	if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) {
47275eba5b6SRobert Mustacchi 		DEBUGOUT1("PHY I2C Address %d is out of range.\n",
47375eba5b6SRobert Mustacchi 			  hw->phy.addr);
47475eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
47575eba5b6SRobert Mustacchi 	}
47675eba5b6SRobert Mustacchi 
47775eba5b6SRobert Mustacchi 	/* Swap the data bytes for the I2C interface */
47875eba5b6SRobert Mustacchi 	phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
47975eba5b6SRobert Mustacchi 
48075eba5b6SRobert Mustacchi 	/* Set up Op-code, Phy Address, and register address in the I2CCMD
48175eba5b6SRobert Mustacchi 	 * register.  The MAC will take care of interfacing with the
48275eba5b6SRobert Mustacchi 	 * PHY to retrieve the desired data.
48375eba5b6SRobert Mustacchi 	 */
48475eba5b6SRobert Mustacchi 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
48575eba5b6SRobert Mustacchi 		  (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
48675eba5b6SRobert Mustacchi 		  E1000_I2CCMD_OPCODE_WRITE |
48775eba5b6SRobert Mustacchi 		  phy_data_swapped);
48875eba5b6SRobert Mustacchi 
48975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
49075eba5b6SRobert Mustacchi 
49175eba5b6SRobert Mustacchi 	/* Poll the ready bit to see if the I2C read completed */
49275eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
49375eba5b6SRobert Mustacchi 		usec_delay(50);
49475eba5b6SRobert Mustacchi 		i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
49575eba5b6SRobert Mustacchi 		if (i2ccmd & E1000_I2CCMD_READY)
49675eba5b6SRobert Mustacchi 			break;
49775eba5b6SRobert Mustacchi 	}
49875eba5b6SRobert Mustacchi 	if (!(i2ccmd & E1000_I2CCMD_READY)) {
49975eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Write did not complete\n");
50075eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
50175eba5b6SRobert Mustacchi 	}
50275eba5b6SRobert Mustacchi 	if (i2ccmd & E1000_I2CCMD_ERROR) {
50375eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Error bit set\n");
50475eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
50575eba5b6SRobert Mustacchi 	}
50675eba5b6SRobert Mustacchi 
50775eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
50875eba5b6SRobert Mustacchi }
50975eba5b6SRobert Mustacchi 
51075eba5b6SRobert Mustacchi /**
51175eba5b6SRobert Mustacchi  *  e1000_read_sfp_data_byte - Reads SFP module data.
51275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
51375eba5b6SRobert Mustacchi  *  @offset: byte location offset to be read
51475eba5b6SRobert Mustacchi  *  @data: read data buffer pointer
51575eba5b6SRobert Mustacchi  *
51675eba5b6SRobert Mustacchi  *  Reads one byte from SFP module data stored
51775eba5b6SRobert Mustacchi  *  in SFP resided EEPROM memory or SFP diagnostic area.
51875eba5b6SRobert Mustacchi  *  Function should be called with
51975eba5b6SRobert Mustacchi  *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
52075eba5b6SRobert Mustacchi  *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
52175eba5b6SRobert Mustacchi  *  access
52275eba5b6SRobert Mustacchi  **/
52375eba5b6SRobert Mustacchi s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
52475eba5b6SRobert Mustacchi {
52575eba5b6SRobert Mustacchi 	u32 i = 0;
52675eba5b6SRobert Mustacchi 	u32 i2ccmd = 0;
52775eba5b6SRobert Mustacchi 	u32 data_local = 0;
52875eba5b6SRobert Mustacchi 
52975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_sfp_data_byte");
53075eba5b6SRobert Mustacchi 
53175eba5b6SRobert Mustacchi 	if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
53275eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD command address exceeds upper limit\n");
53375eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
53475eba5b6SRobert Mustacchi 	}
53575eba5b6SRobert Mustacchi 
53675eba5b6SRobert Mustacchi 	/* Set up Op-code, EEPROM Address,in the I2CCMD
53775eba5b6SRobert Mustacchi 	 * register. The MAC will take care of interfacing with the
53875eba5b6SRobert Mustacchi 	 * EEPROM to retrieve the desired data.
53975eba5b6SRobert Mustacchi 	 */
54075eba5b6SRobert Mustacchi 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
54175eba5b6SRobert Mustacchi 		  E1000_I2CCMD_OPCODE_READ);
54275eba5b6SRobert Mustacchi 
54375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
54475eba5b6SRobert Mustacchi 
54575eba5b6SRobert Mustacchi 	/* Poll the ready bit to see if the I2C read completed */
54675eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
54775eba5b6SRobert Mustacchi 		usec_delay(50);
54875eba5b6SRobert Mustacchi 		data_local = E1000_READ_REG(hw, E1000_I2CCMD);
54975eba5b6SRobert Mustacchi 		if (data_local & E1000_I2CCMD_READY)
55075eba5b6SRobert Mustacchi 			break;
55175eba5b6SRobert Mustacchi 	}
55275eba5b6SRobert Mustacchi 	if (!(data_local & E1000_I2CCMD_READY)) {
55375eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Read did not complete\n");
55475eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
55575eba5b6SRobert Mustacchi 	}
55675eba5b6SRobert Mustacchi 	if (data_local & E1000_I2CCMD_ERROR) {
55775eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Error bit set\n");
55875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
55975eba5b6SRobert Mustacchi 	}
56075eba5b6SRobert Mustacchi 	*data = (u8) data_local & 0xFF;
56175eba5b6SRobert Mustacchi 
56275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
56375eba5b6SRobert Mustacchi }
56475eba5b6SRobert Mustacchi 
56575eba5b6SRobert Mustacchi /**
56675eba5b6SRobert Mustacchi  *  e1000_write_sfp_data_byte - Writes SFP module data.
56775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
56875eba5b6SRobert Mustacchi  *  @offset: byte location offset to write to
56975eba5b6SRobert Mustacchi  *  @data: data to write
57075eba5b6SRobert Mustacchi  *
57175eba5b6SRobert Mustacchi  *  Writes one byte to SFP module data stored
57275eba5b6SRobert Mustacchi  *  in SFP resided EEPROM memory or SFP diagnostic area.
57375eba5b6SRobert Mustacchi  *  Function should be called with
57475eba5b6SRobert Mustacchi  *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
57575eba5b6SRobert Mustacchi  *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
57675eba5b6SRobert Mustacchi  *  access
57775eba5b6SRobert Mustacchi  **/
57875eba5b6SRobert Mustacchi s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
57975eba5b6SRobert Mustacchi {
58075eba5b6SRobert Mustacchi 	u32 i = 0;
58175eba5b6SRobert Mustacchi 	u32 i2ccmd = 0;
58275eba5b6SRobert Mustacchi 	u32 data_local = 0;
58375eba5b6SRobert Mustacchi 
58475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_sfp_data_byte");
58575eba5b6SRobert Mustacchi 
58675eba5b6SRobert Mustacchi 	if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
58775eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD command address exceeds upper limit\n");
58875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
58975eba5b6SRobert Mustacchi 	}
59075eba5b6SRobert Mustacchi 	/* The programming interface is 16 bits wide
59175eba5b6SRobert Mustacchi 	 * so we need to read the whole word first
59275eba5b6SRobert Mustacchi 	 * then update appropriate byte lane and write
59375eba5b6SRobert Mustacchi 	 * the updated word back.
59475eba5b6SRobert Mustacchi 	 */
59575eba5b6SRobert Mustacchi 	/* Set up Op-code, EEPROM Address,in the I2CCMD
59675eba5b6SRobert Mustacchi 	 * register. The MAC will take care of interfacing
59775eba5b6SRobert Mustacchi 	 * with an EEPROM to write the data given.
59875eba5b6SRobert Mustacchi 	 */
59975eba5b6SRobert Mustacchi 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
60075eba5b6SRobert Mustacchi 		  E1000_I2CCMD_OPCODE_READ);
60175eba5b6SRobert Mustacchi 	/* Set a command to read single word */
60275eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
60375eba5b6SRobert Mustacchi 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
60475eba5b6SRobert Mustacchi 		usec_delay(50);
60575eba5b6SRobert Mustacchi 		/* Poll the ready bit to see if lastly
60675eba5b6SRobert Mustacchi 		 * launched I2C operation completed
60775eba5b6SRobert Mustacchi 		 */
60875eba5b6SRobert Mustacchi 		i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
60975eba5b6SRobert Mustacchi 		if (i2ccmd & E1000_I2CCMD_READY) {
61075eba5b6SRobert Mustacchi 			/* Check if this is READ or WRITE phase */
61175eba5b6SRobert Mustacchi 			if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
61275eba5b6SRobert Mustacchi 			    E1000_I2CCMD_OPCODE_READ) {
61375eba5b6SRobert Mustacchi 				/* Write the selected byte
61475eba5b6SRobert Mustacchi 				 * lane and update whole word
61575eba5b6SRobert Mustacchi 				 */
61675eba5b6SRobert Mustacchi 				data_local = i2ccmd & 0xFF00;
61775eba5b6SRobert Mustacchi 				data_local |= data;
61875eba5b6SRobert Mustacchi 				i2ccmd = ((offset <<
61975eba5b6SRobert Mustacchi 					E1000_I2CCMD_REG_ADDR_SHIFT) |
62075eba5b6SRobert Mustacchi 					E1000_I2CCMD_OPCODE_WRITE | data_local);
62175eba5b6SRobert Mustacchi 				E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
62275eba5b6SRobert Mustacchi 			} else {
62375eba5b6SRobert Mustacchi 				break;
62475eba5b6SRobert Mustacchi 			}
62575eba5b6SRobert Mustacchi 		}
62675eba5b6SRobert Mustacchi 	}
62775eba5b6SRobert Mustacchi 	if (!(i2ccmd & E1000_I2CCMD_READY)) {
62875eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Write did not complete\n");
62975eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
63075eba5b6SRobert Mustacchi 	}
63175eba5b6SRobert Mustacchi 	if (i2ccmd & E1000_I2CCMD_ERROR) {
63275eba5b6SRobert Mustacchi 		DEBUGOUT("I2CCMD Error bit set\n");
63375eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
63475eba5b6SRobert Mustacchi 	}
63575eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
63675eba5b6SRobert Mustacchi }
63775eba5b6SRobert Mustacchi 
63875eba5b6SRobert Mustacchi /**
63975eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_m88 - Read m88 PHY register
64075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
64175eba5b6SRobert Mustacchi  *  @offset: register offset to be read
64275eba5b6SRobert Mustacchi  *  @data: pointer to the read data
64375eba5b6SRobert Mustacchi  *
64475eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then reads the PHY register at offset
64575eba5b6SRobert Mustacchi  *  and storing the retrieved information in data.  Release any acquired
64675eba5b6SRobert Mustacchi  *  semaphores before exiting.
64775eba5b6SRobert Mustacchi  **/
64875eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
64975eba5b6SRobert Mustacchi {
65075eba5b6SRobert Mustacchi 	s32 ret_val;
65175eba5b6SRobert Mustacchi 
65275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_m88");
65375eba5b6SRobert Mustacchi 
65475eba5b6SRobert Mustacchi 	if (!hw->phy.ops.acquire)
65575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
65675eba5b6SRobert Mustacchi 
65775eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
65875eba5b6SRobert Mustacchi 	if (ret_val)
65975eba5b6SRobert Mustacchi 		return ret_val;
66075eba5b6SRobert Mustacchi 
66175eba5b6SRobert Mustacchi 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
66275eba5b6SRobert Mustacchi 					  data);
66375eba5b6SRobert Mustacchi 
66475eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
66575eba5b6SRobert Mustacchi 
66675eba5b6SRobert Mustacchi 	return ret_val;
66775eba5b6SRobert Mustacchi }
66875eba5b6SRobert Mustacchi 
66975eba5b6SRobert Mustacchi /**
67075eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_m88 - Write m88 PHY register
67175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
67275eba5b6SRobert Mustacchi  *  @offset: register offset to write to
67375eba5b6SRobert Mustacchi  *  @data: data to write at register offset
67475eba5b6SRobert Mustacchi  *
67575eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then writes the data to PHY register
67675eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
67775eba5b6SRobert Mustacchi  **/
67875eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
67975eba5b6SRobert Mustacchi {
68075eba5b6SRobert Mustacchi 	s32 ret_val;
68175eba5b6SRobert Mustacchi 
68275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_m88");
68375eba5b6SRobert Mustacchi 
68475eba5b6SRobert Mustacchi 	if (!hw->phy.ops.acquire)
68575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
68675eba5b6SRobert Mustacchi 
68775eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
68875eba5b6SRobert Mustacchi 	if (ret_val)
68975eba5b6SRobert Mustacchi 		return ret_val;
69075eba5b6SRobert Mustacchi 
69175eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
69275eba5b6SRobert Mustacchi 					   data);
69375eba5b6SRobert Mustacchi 
69475eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
69575eba5b6SRobert Mustacchi 
69675eba5b6SRobert Mustacchi 	return ret_val;
69775eba5b6SRobert Mustacchi }
69875eba5b6SRobert Mustacchi 
69975eba5b6SRobert Mustacchi /**
70075eba5b6SRobert Mustacchi  *  e1000_set_page_igp - Set page as on IGP-like PHY(s)
70175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
70275eba5b6SRobert Mustacchi  *  @page: page to set (shifted left when necessary)
70375eba5b6SRobert Mustacchi  *
70475eba5b6SRobert Mustacchi  *  Sets PHY page required for PHY register access.  Assumes semaphore is
70575eba5b6SRobert Mustacchi  *  already acquired.  Note, this function sets phy.addr to 1 so the caller
70675eba5b6SRobert Mustacchi  *  must set it appropriately (if necessary) after this function returns.
70775eba5b6SRobert Mustacchi  **/
70875eba5b6SRobert Mustacchi s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
70975eba5b6SRobert Mustacchi {
71075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_page_igp");
71175eba5b6SRobert Mustacchi 
71275eba5b6SRobert Mustacchi 	DEBUGOUT1("Setting page 0x%x\n", page);
71375eba5b6SRobert Mustacchi 
71475eba5b6SRobert Mustacchi 	hw->phy.addr = 1;
71575eba5b6SRobert Mustacchi 
71675eba5b6SRobert Mustacchi 	return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
71775eba5b6SRobert Mustacchi }
71875eba5b6SRobert Mustacchi 
71975eba5b6SRobert Mustacchi /**
72075eba5b6SRobert Mustacchi  *  __e1000_read_phy_reg_igp - Read igp PHY register
72175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
72275eba5b6SRobert Mustacchi  *  @offset: register offset to be read
72375eba5b6SRobert Mustacchi  *  @data: pointer to the read data
72475eba5b6SRobert Mustacchi  *  @locked: semaphore has already been acquired or not
72575eba5b6SRobert Mustacchi  *
72675eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then reads the PHY register at offset
72775eba5b6SRobert Mustacchi  *  and stores the retrieved information in data.  Release any acquired
72875eba5b6SRobert Mustacchi  *  semaphores before exiting.
72975eba5b6SRobert Mustacchi  **/
73075eba5b6SRobert Mustacchi static s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
73175eba5b6SRobert Mustacchi 				    bool locked)
73275eba5b6SRobert Mustacchi {
73375eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
73475eba5b6SRobert Mustacchi 
73575eba5b6SRobert Mustacchi 	DEBUGFUNC("__e1000_read_phy_reg_igp");
73675eba5b6SRobert Mustacchi 
73775eba5b6SRobert Mustacchi 	if (!locked) {
73875eba5b6SRobert Mustacchi 		if (!hw->phy.ops.acquire)
73975eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
74075eba5b6SRobert Mustacchi 
74175eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
74275eba5b6SRobert Mustacchi 		if (ret_val)
74375eba5b6SRobert Mustacchi 			return ret_val;
74475eba5b6SRobert Mustacchi 	}
74575eba5b6SRobert Mustacchi 
74675eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_MULTI_PAGE_REG)
74775eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw,
74875eba5b6SRobert Mustacchi 						   IGP01E1000_PHY_PAGE_SELECT,
74975eba5b6SRobert Mustacchi 						   (u16)offset);
75075eba5b6SRobert Mustacchi 	if (!ret_val)
75175eba5b6SRobert Mustacchi 		ret_val = e1000_read_phy_reg_mdic(hw,
75275eba5b6SRobert Mustacchi 						  MAX_PHY_REG_ADDRESS & offset,
75375eba5b6SRobert Mustacchi 						  data);
75475eba5b6SRobert Mustacchi 	if (!locked)
75575eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
75675eba5b6SRobert Mustacchi 
75775eba5b6SRobert Mustacchi 	return ret_val;
75875eba5b6SRobert Mustacchi }
75975eba5b6SRobert Mustacchi 
76075eba5b6SRobert Mustacchi /**
76175eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_igp - Read igp PHY register
76275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
76375eba5b6SRobert Mustacchi  *  @offset: register offset to be read
76475eba5b6SRobert Mustacchi  *  @data: pointer to the read data
76575eba5b6SRobert Mustacchi  *
76675eba5b6SRobert Mustacchi  *  Acquires semaphore then reads the PHY register at offset and stores the
76775eba5b6SRobert Mustacchi  *  retrieved information in data.
76875eba5b6SRobert Mustacchi  *  Release the acquired semaphore before exiting.
76975eba5b6SRobert Mustacchi  **/
77075eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
77175eba5b6SRobert Mustacchi {
77275eba5b6SRobert Mustacchi 	return __e1000_read_phy_reg_igp(hw, offset, data, FALSE);
77375eba5b6SRobert Mustacchi }
77475eba5b6SRobert Mustacchi 
77575eba5b6SRobert Mustacchi /**
77675eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_igp_locked - Read igp PHY register
77775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
77875eba5b6SRobert Mustacchi  *  @offset: register offset to be read
77975eba5b6SRobert Mustacchi  *  @data: pointer to the read data
78075eba5b6SRobert Mustacchi  *
78175eba5b6SRobert Mustacchi  *  Reads the PHY register at offset and stores the retrieved information
78275eba5b6SRobert Mustacchi  *  in data.  Assumes semaphore already acquired.
78375eba5b6SRobert Mustacchi  **/
78475eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
78575eba5b6SRobert Mustacchi {
78675eba5b6SRobert Mustacchi 	return __e1000_read_phy_reg_igp(hw, offset, data, TRUE);
78775eba5b6SRobert Mustacchi }
78875eba5b6SRobert Mustacchi 
78975eba5b6SRobert Mustacchi /**
79075eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_igp - Write igp PHY register
79175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
79275eba5b6SRobert Mustacchi  *  @offset: register offset to write to
79375eba5b6SRobert Mustacchi  *  @data: data to write at register offset
79475eba5b6SRobert Mustacchi  *  @locked: semaphore has already been acquired or not
79575eba5b6SRobert Mustacchi  *
79675eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then writes the data to PHY register
79775eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
79875eba5b6SRobert Mustacchi  **/
79975eba5b6SRobert Mustacchi static s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
80075eba5b6SRobert Mustacchi 				     bool locked)
80175eba5b6SRobert Mustacchi {
80275eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
80375eba5b6SRobert Mustacchi 
80475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_igp");
80575eba5b6SRobert Mustacchi 
80675eba5b6SRobert Mustacchi 	if (!locked) {
80775eba5b6SRobert Mustacchi 		if (!hw->phy.ops.acquire)
80875eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
80975eba5b6SRobert Mustacchi 
81075eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
81175eba5b6SRobert Mustacchi 		if (ret_val)
81275eba5b6SRobert Mustacchi 			return ret_val;
81375eba5b6SRobert Mustacchi 	}
81475eba5b6SRobert Mustacchi 
81575eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_MULTI_PAGE_REG)
81675eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw,
81775eba5b6SRobert Mustacchi 						   IGP01E1000_PHY_PAGE_SELECT,
81875eba5b6SRobert Mustacchi 						   (u16)offset);
81975eba5b6SRobert Mustacchi 	if (!ret_val)
82075eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
82175eba5b6SRobert Mustacchi 						       offset,
82275eba5b6SRobert Mustacchi 						   data);
82375eba5b6SRobert Mustacchi 	if (!locked)
82475eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
82575eba5b6SRobert Mustacchi 
82675eba5b6SRobert Mustacchi 	return ret_val;
82775eba5b6SRobert Mustacchi }
82875eba5b6SRobert Mustacchi 
82975eba5b6SRobert Mustacchi /**
83075eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_igp - Write igp PHY register
83175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
83275eba5b6SRobert Mustacchi  *  @offset: register offset to write to
83375eba5b6SRobert Mustacchi  *  @data: data to write at register offset
83475eba5b6SRobert Mustacchi  *
83575eba5b6SRobert Mustacchi  *  Acquires semaphore then writes the data to PHY register
83675eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
83775eba5b6SRobert Mustacchi  **/
83875eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
83975eba5b6SRobert Mustacchi {
84075eba5b6SRobert Mustacchi 	return __e1000_write_phy_reg_igp(hw, offset, data, FALSE);
84175eba5b6SRobert Mustacchi }
84275eba5b6SRobert Mustacchi 
84375eba5b6SRobert Mustacchi /**
84475eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_igp_locked - Write igp PHY register
84575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
84675eba5b6SRobert Mustacchi  *  @offset: register offset to write to
84775eba5b6SRobert Mustacchi  *  @data: data to write at register offset
84875eba5b6SRobert Mustacchi  *
84975eba5b6SRobert Mustacchi  *  Writes the data to PHY register at the offset.
85075eba5b6SRobert Mustacchi  *  Assumes semaphore already acquired.
85175eba5b6SRobert Mustacchi  **/
85275eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
85375eba5b6SRobert Mustacchi {
85475eba5b6SRobert Mustacchi 	return __e1000_write_phy_reg_igp(hw, offset, data, TRUE);
85575eba5b6SRobert Mustacchi }
85675eba5b6SRobert Mustacchi 
85775eba5b6SRobert Mustacchi /**
85875eba5b6SRobert Mustacchi  *  __e1000_read_kmrn_reg - Read kumeran register
85975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
86075eba5b6SRobert Mustacchi  *  @offset: register offset to be read
86175eba5b6SRobert Mustacchi  *  @data: pointer to the read data
86275eba5b6SRobert Mustacchi  *  @locked: semaphore has already been acquired or not
86375eba5b6SRobert Mustacchi  *
86475eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary.  Then reads the PHY register at offset
86575eba5b6SRobert Mustacchi  *  using the kumeran interface.  The information retrieved is stored in data.
86675eba5b6SRobert Mustacchi  *  Release any acquired semaphores before exiting.
86775eba5b6SRobert Mustacchi  **/
86875eba5b6SRobert Mustacchi static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
86975eba5b6SRobert Mustacchi 				 bool locked)
87075eba5b6SRobert Mustacchi {
87175eba5b6SRobert Mustacchi 	u32 kmrnctrlsta;
87275eba5b6SRobert Mustacchi 
87375eba5b6SRobert Mustacchi 	DEBUGFUNC("__e1000_read_kmrn_reg");
87475eba5b6SRobert Mustacchi 
87575eba5b6SRobert Mustacchi 	if (!locked) {
87675eba5b6SRobert Mustacchi 		s32 ret_val = E1000_SUCCESS;
87775eba5b6SRobert Mustacchi 
87875eba5b6SRobert Mustacchi 		if (!hw->phy.ops.acquire)
87975eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
88075eba5b6SRobert Mustacchi 
88175eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
88275eba5b6SRobert Mustacchi 		if (ret_val)
88375eba5b6SRobert Mustacchi 			return ret_val;
88475eba5b6SRobert Mustacchi 	}
88575eba5b6SRobert Mustacchi 
88675eba5b6SRobert Mustacchi 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
88775eba5b6SRobert Mustacchi 		       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
88875eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
88975eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
89075eba5b6SRobert Mustacchi 
89175eba5b6SRobert Mustacchi 	usec_delay(2);
89275eba5b6SRobert Mustacchi 
89375eba5b6SRobert Mustacchi 	kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
89475eba5b6SRobert Mustacchi 	*data = (u16)kmrnctrlsta;
89575eba5b6SRobert Mustacchi 
89675eba5b6SRobert Mustacchi 	if (!locked)
89775eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
89875eba5b6SRobert Mustacchi 
89975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
90075eba5b6SRobert Mustacchi }
90175eba5b6SRobert Mustacchi 
90275eba5b6SRobert Mustacchi /**
90375eba5b6SRobert Mustacchi  *  e1000_read_kmrn_reg_generic -  Read kumeran register
90475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
90575eba5b6SRobert Mustacchi  *  @offset: register offset to be read
90675eba5b6SRobert Mustacchi  *  @data: pointer to the read data
90775eba5b6SRobert Mustacchi  *
90875eba5b6SRobert Mustacchi  *  Acquires semaphore then reads the PHY register at offset using the
90975eba5b6SRobert Mustacchi  *  kumeran interface.  The information retrieved is stored in data.
91075eba5b6SRobert Mustacchi  *  Release the acquired semaphore before exiting.
91175eba5b6SRobert Mustacchi  **/
91275eba5b6SRobert Mustacchi s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
91375eba5b6SRobert Mustacchi {
91475eba5b6SRobert Mustacchi 	return __e1000_read_kmrn_reg(hw, offset, data, FALSE);
91575eba5b6SRobert Mustacchi }
91675eba5b6SRobert Mustacchi 
91775eba5b6SRobert Mustacchi /**
91875eba5b6SRobert Mustacchi  *  e1000_read_kmrn_reg_locked -  Read kumeran register
91975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
92075eba5b6SRobert Mustacchi  *  @offset: register offset to be read
92175eba5b6SRobert Mustacchi  *  @data: pointer to the read data
92275eba5b6SRobert Mustacchi  *
92375eba5b6SRobert Mustacchi  *  Reads the PHY register at offset using the kumeran interface.  The
92475eba5b6SRobert Mustacchi  *  information retrieved is stored in data.
92575eba5b6SRobert Mustacchi  *  Assumes semaphore already acquired.
92675eba5b6SRobert Mustacchi  **/
92775eba5b6SRobert Mustacchi s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
92875eba5b6SRobert Mustacchi {
92975eba5b6SRobert Mustacchi 	return __e1000_read_kmrn_reg(hw, offset, data, TRUE);
93075eba5b6SRobert Mustacchi }
93175eba5b6SRobert Mustacchi 
93275eba5b6SRobert Mustacchi /**
93375eba5b6SRobert Mustacchi  *  __e1000_write_kmrn_reg - Write kumeran register
93475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
93575eba5b6SRobert Mustacchi  *  @offset: register offset to write to
93675eba5b6SRobert Mustacchi  *  @data: data to write at register offset
93775eba5b6SRobert Mustacchi  *  @locked: semaphore has already been acquired or not
93875eba5b6SRobert Mustacchi  *
93975eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary.  Then write the data to PHY register
94075eba5b6SRobert Mustacchi  *  at the offset using the kumeran interface.  Release any acquired semaphores
94175eba5b6SRobert Mustacchi  *  before exiting.
94275eba5b6SRobert Mustacchi  **/
94375eba5b6SRobert Mustacchi static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
94475eba5b6SRobert Mustacchi 				  bool locked)
94575eba5b6SRobert Mustacchi {
94675eba5b6SRobert Mustacchi 	u32 kmrnctrlsta;
94775eba5b6SRobert Mustacchi 
94875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_kmrn_reg_generic");
94975eba5b6SRobert Mustacchi 
95075eba5b6SRobert Mustacchi 	if (!locked) {
95175eba5b6SRobert Mustacchi 		s32 ret_val = E1000_SUCCESS;
95275eba5b6SRobert Mustacchi 
95375eba5b6SRobert Mustacchi 		if (!hw->phy.ops.acquire)
95475eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
95575eba5b6SRobert Mustacchi 
95675eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
95775eba5b6SRobert Mustacchi 		if (ret_val)
95875eba5b6SRobert Mustacchi 			return ret_val;
95975eba5b6SRobert Mustacchi 	}
96075eba5b6SRobert Mustacchi 
96175eba5b6SRobert Mustacchi 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
96275eba5b6SRobert Mustacchi 		       E1000_KMRNCTRLSTA_OFFSET) | data;
96375eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
96475eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
96575eba5b6SRobert Mustacchi 
96675eba5b6SRobert Mustacchi 	usec_delay(2);
96775eba5b6SRobert Mustacchi 
96875eba5b6SRobert Mustacchi 	if (!locked)
96975eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
97075eba5b6SRobert Mustacchi 
97175eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
97275eba5b6SRobert Mustacchi }
97375eba5b6SRobert Mustacchi 
97475eba5b6SRobert Mustacchi /**
97575eba5b6SRobert Mustacchi  *  e1000_write_kmrn_reg_generic -  Write kumeran register
97675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
97775eba5b6SRobert Mustacchi  *  @offset: register offset to write to
97875eba5b6SRobert Mustacchi  *  @data: data to write at register offset
97975eba5b6SRobert Mustacchi  *
98075eba5b6SRobert Mustacchi  *  Acquires semaphore then writes the data to the PHY register at the offset
98175eba5b6SRobert Mustacchi  *  using the kumeran interface.  Release the acquired semaphore before exiting.
98275eba5b6SRobert Mustacchi  **/
98375eba5b6SRobert Mustacchi s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data)
98475eba5b6SRobert Mustacchi {
98575eba5b6SRobert Mustacchi 	return __e1000_write_kmrn_reg(hw, offset, data, FALSE);
98675eba5b6SRobert Mustacchi }
98775eba5b6SRobert Mustacchi 
98875eba5b6SRobert Mustacchi /**
98975eba5b6SRobert Mustacchi  *  e1000_write_kmrn_reg_locked -  Write kumeran register
99075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
99175eba5b6SRobert Mustacchi  *  @offset: register offset to write to
99275eba5b6SRobert Mustacchi  *  @data: data to write at register offset
99375eba5b6SRobert Mustacchi  *
99475eba5b6SRobert Mustacchi  *  Write the data to PHY register at the offset using the kumeran interface.
99575eba5b6SRobert Mustacchi  *  Assumes semaphore already acquired.
99675eba5b6SRobert Mustacchi  **/
99775eba5b6SRobert Mustacchi s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
99875eba5b6SRobert Mustacchi {
99975eba5b6SRobert Mustacchi 	return __e1000_write_kmrn_reg(hw, offset, data, TRUE);
100075eba5b6SRobert Mustacchi }
100175eba5b6SRobert Mustacchi 
100275eba5b6SRobert Mustacchi /**
100375eba5b6SRobert Mustacchi  *  e1000_set_master_slave_mode - Setup PHY for Master/slave mode
100475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
100575eba5b6SRobert Mustacchi  *
100675eba5b6SRobert Mustacchi  *  Sets up Master/slave mode
100775eba5b6SRobert Mustacchi  **/
100875eba5b6SRobert Mustacchi static s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
100975eba5b6SRobert Mustacchi {
101075eba5b6SRobert Mustacchi 	s32 ret_val;
101175eba5b6SRobert Mustacchi 	u16 phy_data;
101275eba5b6SRobert Mustacchi 
101375eba5b6SRobert Mustacchi 	/* Resolve Master/Slave mode */
101475eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
101575eba5b6SRobert Mustacchi 	if (ret_val)
101675eba5b6SRobert Mustacchi 		return ret_val;
101775eba5b6SRobert Mustacchi 
101875eba5b6SRobert Mustacchi 	/* load defaults for future use */
101975eba5b6SRobert Mustacchi 	hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
102075eba5b6SRobert Mustacchi 				   ((phy_data & CR_1000T_MS_VALUE) ?
102175eba5b6SRobert Mustacchi 				    e1000_ms_force_master :
102275eba5b6SRobert Mustacchi 				    e1000_ms_force_slave) : e1000_ms_auto;
102375eba5b6SRobert Mustacchi 
102475eba5b6SRobert Mustacchi 	switch (hw->phy.ms_type) {
102575eba5b6SRobert Mustacchi 	case e1000_ms_force_master:
102675eba5b6SRobert Mustacchi 		phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
102775eba5b6SRobert Mustacchi 		break;
102875eba5b6SRobert Mustacchi 	case e1000_ms_force_slave:
102975eba5b6SRobert Mustacchi 		phy_data |= CR_1000T_MS_ENABLE;
103075eba5b6SRobert Mustacchi 		phy_data &= ~(CR_1000T_MS_VALUE);
103175eba5b6SRobert Mustacchi 		break;
103275eba5b6SRobert Mustacchi 	case e1000_ms_auto:
103375eba5b6SRobert Mustacchi 		phy_data &= ~CR_1000T_MS_ENABLE;
103475eba5b6SRobert Mustacchi 		/* fall-through */
103575eba5b6SRobert Mustacchi 	default:
103675eba5b6SRobert Mustacchi 		break;
103775eba5b6SRobert Mustacchi 	}
103875eba5b6SRobert Mustacchi 
103975eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
104075eba5b6SRobert Mustacchi }
104175eba5b6SRobert Mustacchi 
104275eba5b6SRobert Mustacchi /**
104375eba5b6SRobert Mustacchi  *  e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
104475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
104575eba5b6SRobert Mustacchi  *
104675eba5b6SRobert Mustacchi  *  Sets up Carrier-sense on Transmit and downshift values.
104775eba5b6SRobert Mustacchi  **/
104875eba5b6SRobert Mustacchi s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
104975eba5b6SRobert Mustacchi {
105075eba5b6SRobert Mustacchi 	s32 ret_val;
105175eba5b6SRobert Mustacchi 	u16 phy_data;
105275eba5b6SRobert Mustacchi 
105375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_copper_link_setup_82577");
105475eba5b6SRobert Mustacchi 
105575eba5b6SRobert Mustacchi 	if (hw->phy.type == e1000_phy_82580) {
105675eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.reset(hw);
105775eba5b6SRobert Mustacchi 		if (ret_val) {
105875eba5b6SRobert Mustacchi 			DEBUGOUT("Error resetting the PHY.\n");
105975eba5b6SRobert Mustacchi 			return ret_val;
106075eba5b6SRobert Mustacchi 		}
106175eba5b6SRobert Mustacchi 	}
106275eba5b6SRobert Mustacchi 
1063c124a83eSRobert Mustacchi 	/* Enable CRS on Tx. This must be set for half-duplex operation. */
106475eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
106575eba5b6SRobert Mustacchi 	if (ret_val)
106675eba5b6SRobert Mustacchi 		return ret_val;
106775eba5b6SRobert Mustacchi 
106875eba5b6SRobert Mustacchi 	phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
106975eba5b6SRobert Mustacchi 
107075eba5b6SRobert Mustacchi 	/* Enable downshift */
107175eba5b6SRobert Mustacchi 	phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
107275eba5b6SRobert Mustacchi 
107375eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data);
107475eba5b6SRobert Mustacchi 	if (ret_val)
107575eba5b6SRobert Mustacchi 		return ret_val;
107675eba5b6SRobert Mustacchi 
107775eba5b6SRobert Mustacchi 	/* Set MDI/MDIX mode */
107875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
107975eba5b6SRobert Mustacchi 	if (ret_val)
108075eba5b6SRobert Mustacchi 		return ret_val;
108175eba5b6SRobert Mustacchi 	phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
108275eba5b6SRobert Mustacchi 	/* Options:
108375eba5b6SRobert Mustacchi 	 *   0 - Auto (default)
108475eba5b6SRobert Mustacchi 	 *   1 - MDI mode
108575eba5b6SRobert Mustacchi 	 *   2 - MDI-X mode
108675eba5b6SRobert Mustacchi 	 */
108775eba5b6SRobert Mustacchi 	switch (hw->phy.mdix) {
108875eba5b6SRobert Mustacchi 	case 1:
108975eba5b6SRobert Mustacchi 		break;
109075eba5b6SRobert Mustacchi 	case 2:
109175eba5b6SRobert Mustacchi 		phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX;
109275eba5b6SRobert Mustacchi 		break;
109375eba5b6SRobert Mustacchi 	case 0:
109475eba5b6SRobert Mustacchi 	default:
109575eba5b6SRobert Mustacchi 		phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX;
109675eba5b6SRobert Mustacchi 		break;
109775eba5b6SRobert Mustacchi 	}
109875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
109975eba5b6SRobert Mustacchi 	if (ret_val)
110075eba5b6SRobert Mustacchi 		return ret_val;
110175eba5b6SRobert Mustacchi 
110275eba5b6SRobert Mustacchi 	return e1000_set_master_slave_mode(hw);
110375eba5b6SRobert Mustacchi }
110475eba5b6SRobert Mustacchi 
110575eba5b6SRobert Mustacchi /**
110675eba5b6SRobert Mustacchi  *  e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link
110775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
110875eba5b6SRobert Mustacchi  *
110975eba5b6SRobert Mustacchi  *  Sets up MDI/MDI-X and polarity for m88 PHY's.  If necessary, transmit clock
111075eba5b6SRobert Mustacchi  *  and downshift values are set also.
111175eba5b6SRobert Mustacchi  **/
111275eba5b6SRobert Mustacchi s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
111375eba5b6SRobert Mustacchi {
111475eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
111575eba5b6SRobert Mustacchi 	s32 ret_val;
111675eba5b6SRobert Mustacchi 	u16 phy_data;
111775eba5b6SRobert Mustacchi 
111875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_copper_link_setup_m88");
111975eba5b6SRobert Mustacchi 
112075eba5b6SRobert Mustacchi 
112175eba5b6SRobert Mustacchi 	/* Enable CRS on Tx. This must be set for half-duplex operation. */
112275eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
112375eba5b6SRobert Mustacchi 	if (ret_val)
112475eba5b6SRobert Mustacchi 		return ret_val;
112575eba5b6SRobert Mustacchi 
112675eba5b6SRobert Mustacchi 	/* For BM PHY this bit is downshift enable */
112775eba5b6SRobert Mustacchi 	if (phy->type != e1000_phy_bm)
112875eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
112975eba5b6SRobert Mustacchi 
113075eba5b6SRobert Mustacchi 	/* Options:
113175eba5b6SRobert Mustacchi 	 *   MDI/MDI-X = 0 (default)
113275eba5b6SRobert Mustacchi 	 *   0 - Auto for all speeds
113375eba5b6SRobert Mustacchi 	 *   1 - MDI mode
113475eba5b6SRobert Mustacchi 	 *   2 - MDI-X mode
113575eba5b6SRobert Mustacchi 	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
113675eba5b6SRobert Mustacchi 	 */
113775eba5b6SRobert Mustacchi 	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
113875eba5b6SRobert Mustacchi 
113975eba5b6SRobert Mustacchi 	switch (phy->mdix) {
114075eba5b6SRobert Mustacchi 	case 1:
114175eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
114275eba5b6SRobert Mustacchi 		break;
114375eba5b6SRobert Mustacchi 	case 2:
114475eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
114575eba5b6SRobert Mustacchi 		break;
114675eba5b6SRobert Mustacchi 	case 3:
114775eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_AUTO_X_1000T;
114875eba5b6SRobert Mustacchi 		break;
114975eba5b6SRobert Mustacchi 	case 0:
115075eba5b6SRobert Mustacchi 	default:
115175eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
115275eba5b6SRobert Mustacchi 		break;
115375eba5b6SRobert Mustacchi 	}
115475eba5b6SRobert Mustacchi 
115575eba5b6SRobert Mustacchi 	/* Options:
115675eba5b6SRobert Mustacchi 	 *   disable_polarity_correction = 0 (default)
115775eba5b6SRobert Mustacchi 	 *       Automatic Correction for Reversed Cable Polarity
115875eba5b6SRobert Mustacchi 	 *   0 - Disabled
115975eba5b6SRobert Mustacchi 	 *   1 - Enabled
116075eba5b6SRobert Mustacchi 	 */
116175eba5b6SRobert Mustacchi 	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
116275eba5b6SRobert Mustacchi 	if (phy->disable_polarity_correction)
116375eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
116475eba5b6SRobert Mustacchi 
116575eba5b6SRobert Mustacchi 	/* Enable downshift on BM (disabled by default) */
116675eba5b6SRobert Mustacchi 	if (phy->type == e1000_phy_bm) {
116775eba5b6SRobert Mustacchi 		/* For 82574/82583, first disable then enable downshift */
116875eba5b6SRobert Mustacchi 		if (phy->id == BME1000_E_PHY_ID_R2) {
116975eba5b6SRobert Mustacchi 			phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT;
117075eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
117175eba5b6SRobert Mustacchi 						     phy_data);
117275eba5b6SRobert Mustacchi 			if (ret_val)
117375eba5b6SRobert Mustacchi 				return ret_val;
117475eba5b6SRobert Mustacchi 			/* Commit the changes. */
117575eba5b6SRobert Mustacchi 			ret_val = phy->ops.commit(hw);
117675eba5b6SRobert Mustacchi 			if (ret_val) {
117775eba5b6SRobert Mustacchi 				DEBUGOUT("Error committing the PHY changes\n");
117875eba5b6SRobert Mustacchi 				return ret_val;
117975eba5b6SRobert Mustacchi 			}
118075eba5b6SRobert Mustacchi 		}
118175eba5b6SRobert Mustacchi 
118275eba5b6SRobert Mustacchi 		phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
118375eba5b6SRobert Mustacchi 	}
118475eba5b6SRobert Mustacchi 
118575eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
118675eba5b6SRobert Mustacchi 	if (ret_val)
118775eba5b6SRobert Mustacchi 		return ret_val;
118875eba5b6SRobert Mustacchi 
118975eba5b6SRobert Mustacchi 	if ((phy->type == e1000_phy_m88) &&
119075eba5b6SRobert Mustacchi 	    (phy->revision < E1000_REVISION_4) &&
119175eba5b6SRobert Mustacchi 	    (phy->id != BME1000_E_PHY_ID_R2)) {
119275eba5b6SRobert Mustacchi 		/* Force TX_CLK in the Extended PHY Specific Control Register
119375eba5b6SRobert Mustacchi 		 * to 25MHz clock.
119475eba5b6SRobert Mustacchi 		 */
119575eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
119675eba5b6SRobert Mustacchi 					    &phy_data);
119775eba5b6SRobert Mustacchi 		if (ret_val)
119875eba5b6SRobert Mustacchi 			return ret_val;
119975eba5b6SRobert Mustacchi 
120075eba5b6SRobert Mustacchi 		phy_data |= M88E1000_EPSCR_TX_CLK_25;
120175eba5b6SRobert Mustacchi 
120275eba5b6SRobert Mustacchi 		if ((phy->revision == E1000_REVISION_2) &&
120375eba5b6SRobert Mustacchi 		    (phy->id == M88E1111_I_PHY_ID)) {
120475eba5b6SRobert Mustacchi 			/* 82573L PHY - set the downshift counter to 5x. */
120575eba5b6SRobert Mustacchi 			phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK;
120675eba5b6SRobert Mustacchi 			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
120775eba5b6SRobert Mustacchi 		} else {
120875eba5b6SRobert Mustacchi 			/* Configure Master and Slave downshift values */
120975eba5b6SRobert Mustacchi 			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
121075eba5b6SRobert Mustacchi 				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
121175eba5b6SRobert Mustacchi 			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
121275eba5b6SRobert Mustacchi 				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
121375eba5b6SRobert Mustacchi 		}
121475eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
121575eba5b6SRobert Mustacchi 					     phy_data);
121675eba5b6SRobert Mustacchi 		if (ret_val)
121775eba5b6SRobert Mustacchi 			return ret_val;
121875eba5b6SRobert Mustacchi 	}
121975eba5b6SRobert Mustacchi 
122075eba5b6SRobert Mustacchi 	if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
122175eba5b6SRobert Mustacchi 		/* Set PHY page 0, register 29 to 0x0003 */
122275eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, 29, 0x0003);
122375eba5b6SRobert Mustacchi 		if (ret_val)
122475eba5b6SRobert Mustacchi 			return ret_val;
122575eba5b6SRobert Mustacchi 
122675eba5b6SRobert Mustacchi 		/* Set PHY page 0, register 30 to 0x0000 */
122775eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, 30, 0x0000);
122875eba5b6SRobert Mustacchi 		if (ret_val)
122975eba5b6SRobert Mustacchi 			return ret_val;
123075eba5b6SRobert Mustacchi 	}
123175eba5b6SRobert Mustacchi 
123275eba5b6SRobert Mustacchi 	/* Commit the changes. */
123375eba5b6SRobert Mustacchi 	ret_val = phy->ops.commit(hw);
123475eba5b6SRobert Mustacchi 	if (ret_val) {
123575eba5b6SRobert Mustacchi 		DEBUGOUT("Error committing the PHY changes\n");
123675eba5b6SRobert Mustacchi 		return ret_val;
123775eba5b6SRobert Mustacchi 	}
123875eba5b6SRobert Mustacchi 
123975eba5b6SRobert Mustacchi 	if (phy->type == e1000_phy_82578) {
124075eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
124175eba5b6SRobert Mustacchi 					    &phy_data);
124275eba5b6SRobert Mustacchi 		if (ret_val)
124375eba5b6SRobert Mustacchi 			return ret_val;
124475eba5b6SRobert Mustacchi 
124575eba5b6SRobert Mustacchi 		/* 82578 PHY - set the downshift count to 1x. */
124675eba5b6SRobert Mustacchi 		phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
124775eba5b6SRobert Mustacchi 		phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
124875eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
124975eba5b6SRobert Mustacchi 					     phy_data);
125075eba5b6SRobert Mustacchi 		if (ret_val)
125175eba5b6SRobert Mustacchi 			return ret_val;
125275eba5b6SRobert Mustacchi 	}
125375eba5b6SRobert Mustacchi 
125475eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
125575eba5b6SRobert Mustacchi }
125675eba5b6SRobert Mustacchi 
125775eba5b6SRobert Mustacchi /**
125875eba5b6SRobert Mustacchi  *  e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
125975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
126075eba5b6SRobert Mustacchi  *
126175eba5b6SRobert Mustacchi  *  Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
126275eba5b6SRobert Mustacchi  *  Also enables and sets the downshift parameters.
126375eba5b6SRobert Mustacchi  **/
126475eba5b6SRobert Mustacchi s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
126575eba5b6SRobert Mustacchi {
126675eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
126775eba5b6SRobert Mustacchi 	s32 ret_val;
126875eba5b6SRobert Mustacchi 	u16 phy_data;
126975eba5b6SRobert Mustacchi 
127075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_copper_link_setup_m88_gen2");
127175eba5b6SRobert Mustacchi 
127275eba5b6SRobert Mustacchi 
127375eba5b6SRobert Mustacchi 	/* Enable CRS on Tx. This must be set for half-duplex operation. */
127475eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
127575eba5b6SRobert Mustacchi 	if (ret_val)
127675eba5b6SRobert Mustacchi 		return ret_val;
127775eba5b6SRobert Mustacchi 
127875eba5b6SRobert Mustacchi 	/* Options:
127975eba5b6SRobert Mustacchi 	 *   MDI/MDI-X = 0 (default)
128075eba5b6SRobert Mustacchi 	 *   0 - Auto for all speeds
128175eba5b6SRobert Mustacchi 	 *   1 - MDI mode
128275eba5b6SRobert Mustacchi 	 *   2 - MDI-X mode
128375eba5b6SRobert Mustacchi 	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
128475eba5b6SRobert Mustacchi 	 */
128575eba5b6SRobert Mustacchi 	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
128675eba5b6SRobert Mustacchi 
128775eba5b6SRobert Mustacchi 	switch (phy->mdix) {
128875eba5b6SRobert Mustacchi 	case 1:
128975eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
129075eba5b6SRobert Mustacchi 		break;
129175eba5b6SRobert Mustacchi 	case 2:
129275eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
129375eba5b6SRobert Mustacchi 		break;
129475eba5b6SRobert Mustacchi 	case 3:
129575eba5b6SRobert Mustacchi 		/* M88E1112 does not support this mode) */
129675eba5b6SRobert Mustacchi 		if (phy->id != M88E1112_E_PHY_ID) {
129775eba5b6SRobert Mustacchi 			phy_data |= M88E1000_PSCR_AUTO_X_1000T;
129875eba5b6SRobert Mustacchi 			break;
129975eba5b6SRobert Mustacchi 		}
130075eba5b6SRobert Mustacchi 	case 0:
130175eba5b6SRobert Mustacchi 	default:
130275eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
130375eba5b6SRobert Mustacchi 		break;
130475eba5b6SRobert Mustacchi 	}
130575eba5b6SRobert Mustacchi 
130675eba5b6SRobert Mustacchi 	/* Options:
130775eba5b6SRobert Mustacchi 	 *   disable_polarity_correction = 0 (default)
130875eba5b6SRobert Mustacchi 	 *       Automatic Correction for Reversed Cable Polarity
130975eba5b6SRobert Mustacchi 	 *   0 - Disabled
131075eba5b6SRobert Mustacchi 	 *   1 - Enabled
131175eba5b6SRobert Mustacchi 	 */
131275eba5b6SRobert Mustacchi 	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
131375eba5b6SRobert Mustacchi 	if (phy->disable_polarity_correction)
131475eba5b6SRobert Mustacchi 		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
131575eba5b6SRobert Mustacchi 
131675eba5b6SRobert Mustacchi 	/* Enable downshift and setting it to X6 */
1317c124a83eSRobert Mustacchi 	if (phy->id == M88E1543_E_PHY_ID) {
1318c124a83eSRobert Mustacchi 		phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE;
1319c124a83eSRobert Mustacchi 		ret_val =
1320c124a83eSRobert Mustacchi 		    phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
1321c124a83eSRobert Mustacchi 		if (ret_val)
1322c124a83eSRobert Mustacchi 			return ret_val;
1323c124a83eSRobert Mustacchi 
1324c124a83eSRobert Mustacchi 		ret_val = phy->ops.commit(hw);
1325c124a83eSRobert Mustacchi 		if (ret_val) {
1326c124a83eSRobert Mustacchi 			DEBUGOUT("Error committing the PHY changes\n");
1327c124a83eSRobert Mustacchi 			return ret_val;
1328c124a83eSRobert Mustacchi 		}
1329c124a83eSRobert Mustacchi 	}
1330c124a83eSRobert Mustacchi 
133175eba5b6SRobert Mustacchi 	phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
133275eba5b6SRobert Mustacchi 	phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
133375eba5b6SRobert Mustacchi 	phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
133475eba5b6SRobert Mustacchi 
133575eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
133675eba5b6SRobert Mustacchi 	if (ret_val)
133775eba5b6SRobert Mustacchi 		return ret_val;
133875eba5b6SRobert Mustacchi 
133975eba5b6SRobert Mustacchi 	/* Commit the changes. */
134075eba5b6SRobert Mustacchi 	ret_val = phy->ops.commit(hw);
134175eba5b6SRobert Mustacchi 	if (ret_val) {
134275eba5b6SRobert Mustacchi 		DEBUGOUT("Error committing the PHY changes\n");
134375eba5b6SRobert Mustacchi 		return ret_val;
134475eba5b6SRobert Mustacchi 	}
134575eba5b6SRobert Mustacchi 
1346c124a83eSRobert Mustacchi 	ret_val = e1000_set_master_slave_mode(hw);
1347c124a83eSRobert Mustacchi 	if (ret_val)
1348c124a83eSRobert Mustacchi 		return ret_val;
1349c124a83eSRobert Mustacchi 
135075eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
135175eba5b6SRobert Mustacchi }
135275eba5b6SRobert Mustacchi 
135375eba5b6SRobert Mustacchi /**
135475eba5b6SRobert Mustacchi  *  e1000_copper_link_setup_igp - Setup igp PHY's for copper link
135575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
135675eba5b6SRobert Mustacchi  *
135775eba5b6SRobert Mustacchi  *  Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for
135875eba5b6SRobert Mustacchi  *  igp PHY's.
135975eba5b6SRobert Mustacchi  **/
136075eba5b6SRobert Mustacchi s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
136175eba5b6SRobert Mustacchi {
136275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
136375eba5b6SRobert Mustacchi 	s32 ret_val;
136475eba5b6SRobert Mustacchi 	u16 data;
136575eba5b6SRobert Mustacchi 
136675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_copper_link_setup_igp");
136775eba5b6SRobert Mustacchi 
136875eba5b6SRobert Mustacchi 
136975eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.reset(hw);
137075eba5b6SRobert Mustacchi 	if (ret_val) {
137175eba5b6SRobert Mustacchi 		DEBUGOUT("Error resetting the PHY.\n");
137275eba5b6SRobert Mustacchi 		return ret_val;
137375eba5b6SRobert Mustacchi 	}
137475eba5b6SRobert Mustacchi 
137575eba5b6SRobert Mustacchi 	/* Wait 100ms for MAC to configure PHY from NVM settings, to avoid
137675eba5b6SRobert Mustacchi 	 * timeout issues when LFS is enabled.
137775eba5b6SRobert Mustacchi 	 */
137875eba5b6SRobert Mustacchi 	msec_delay(100);
137975eba5b6SRobert Mustacchi 
138075eba5b6SRobert Mustacchi 	/* The NVM settings will configure LPLU in D3 for
138175eba5b6SRobert Mustacchi 	 * non-IGP1 PHYs.
138275eba5b6SRobert Mustacchi 	 */
138375eba5b6SRobert Mustacchi 	if (phy->type == e1000_phy_igp) {
138475eba5b6SRobert Mustacchi 		/* disable lplu d3 during driver init */
138575eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.set_d3_lplu_state(hw, FALSE);
138675eba5b6SRobert Mustacchi 		if (ret_val) {
138775eba5b6SRobert Mustacchi 			DEBUGOUT("Error Disabling LPLU D3\n");
138875eba5b6SRobert Mustacchi 			return ret_val;
138975eba5b6SRobert Mustacchi 		}
139075eba5b6SRobert Mustacchi 	}
139175eba5b6SRobert Mustacchi 
139275eba5b6SRobert Mustacchi 	/* disable lplu d0 during driver init */
139375eba5b6SRobert Mustacchi 	if (hw->phy.ops.set_d0_lplu_state) {
139475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
139575eba5b6SRobert Mustacchi 		if (ret_val) {
139675eba5b6SRobert Mustacchi 			DEBUGOUT("Error Disabling LPLU D0\n");
139775eba5b6SRobert Mustacchi 			return ret_val;
139875eba5b6SRobert Mustacchi 		}
139975eba5b6SRobert Mustacchi 	}
140075eba5b6SRobert Mustacchi 	/* Configure mdi-mdix settings */
140175eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
140275eba5b6SRobert Mustacchi 	if (ret_val)
140375eba5b6SRobert Mustacchi 		return ret_val;
140475eba5b6SRobert Mustacchi 
140575eba5b6SRobert Mustacchi 	data &= ~IGP01E1000_PSCR_AUTO_MDIX;
140675eba5b6SRobert Mustacchi 
140775eba5b6SRobert Mustacchi 	switch (phy->mdix) {
140875eba5b6SRobert Mustacchi 	case 1:
140975eba5b6SRobert Mustacchi 		data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
141075eba5b6SRobert Mustacchi 		break;
141175eba5b6SRobert Mustacchi 	case 2:
141275eba5b6SRobert Mustacchi 		data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
141375eba5b6SRobert Mustacchi 		break;
141475eba5b6SRobert Mustacchi 	case 0:
141575eba5b6SRobert Mustacchi 	default:
141675eba5b6SRobert Mustacchi 		data |= IGP01E1000_PSCR_AUTO_MDIX;
141775eba5b6SRobert Mustacchi 		break;
141875eba5b6SRobert Mustacchi 	}
141975eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
142075eba5b6SRobert Mustacchi 	if (ret_val)
142175eba5b6SRobert Mustacchi 		return ret_val;
142275eba5b6SRobert Mustacchi 
142375eba5b6SRobert Mustacchi 	/* set auto-master slave resolution settings */
142475eba5b6SRobert Mustacchi 	if (hw->mac.autoneg) {
142575eba5b6SRobert Mustacchi 		/* when autonegotiation advertisement is only 1000Mbps then we
142675eba5b6SRobert Mustacchi 		 * should disable SmartSpeed and enable Auto MasterSlave
142775eba5b6SRobert Mustacchi 		 * resolution as hardware default.
142875eba5b6SRobert Mustacchi 		 */
142975eba5b6SRobert Mustacchi 		if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
143075eba5b6SRobert Mustacchi 			/* Disable SmartSpeed */
143175eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw,
143275eba5b6SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
143375eba5b6SRobert Mustacchi 						    &data);
143475eba5b6SRobert Mustacchi 			if (ret_val)
143575eba5b6SRobert Mustacchi 				return ret_val;
143675eba5b6SRobert Mustacchi 
143775eba5b6SRobert Mustacchi 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
143875eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw,
143975eba5b6SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
144075eba5b6SRobert Mustacchi 						     data);
144175eba5b6SRobert Mustacchi 			if (ret_val)
144275eba5b6SRobert Mustacchi 				return ret_val;
144375eba5b6SRobert Mustacchi 
144475eba5b6SRobert Mustacchi 			/* Set auto Master/Slave resolution process */
144575eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
144675eba5b6SRobert Mustacchi 			if (ret_val)
144775eba5b6SRobert Mustacchi 				return ret_val;
144875eba5b6SRobert Mustacchi 
144975eba5b6SRobert Mustacchi 			data &= ~CR_1000T_MS_ENABLE;
145075eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
145175eba5b6SRobert Mustacchi 			if (ret_val)
145275eba5b6SRobert Mustacchi 				return ret_val;
145375eba5b6SRobert Mustacchi 		}
145475eba5b6SRobert Mustacchi 
145575eba5b6SRobert Mustacchi 		ret_val = e1000_set_master_slave_mode(hw);
145675eba5b6SRobert Mustacchi 	}
145775eba5b6SRobert Mustacchi 
145875eba5b6SRobert Mustacchi 	return ret_val;
145975eba5b6SRobert Mustacchi }
146075eba5b6SRobert Mustacchi 
146175eba5b6SRobert Mustacchi /**
146275eba5b6SRobert Mustacchi  *  e1000_phy_setup_autoneg - Configure PHY for auto-negotiation
146375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
146475eba5b6SRobert Mustacchi  *
146575eba5b6SRobert Mustacchi  *  Reads the MII auto-neg advertisement register and/or the 1000T control
146675eba5b6SRobert Mustacchi  *  register and if the PHY is already setup for auto-negotiation, then
146775eba5b6SRobert Mustacchi  *  return successful.  Otherwise, setup advertisement and flow control to
146875eba5b6SRobert Mustacchi  *  the appropriate values for the wanted auto-negotiation.
146975eba5b6SRobert Mustacchi  **/
147075eba5b6SRobert Mustacchi s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
147175eba5b6SRobert Mustacchi {
147275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
147375eba5b6SRobert Mustacchi 	s32 ret_val;
147475eba5b6SRobert Mustacchi 	u16 mii_autoneg_adv_reg;
147575eba5b6SRobert Mustacchi 	u16 mii_1000t_ctrl_reg = 0;
147675eba5b6SRobert Mustacchi 
147775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_setup_autoneg");
147875eba5b6SRobert Mustacchi 
147975eba5b6SRobert Mustacchi 	phy->autoneg_advertised &= phy->autoneg_mask;
148075eba5b6SRobert Mustacchi 
148175eba5b6SRobert Mustacchi 	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
148275eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
148375eba5b6SRobert Mustacchi 	if (ret_val)
148475eba5b6SRobert Mustacchi 		return ret_val;
148575eba5b6SRobert Mustacchi 
148675eba5b6SRobert Mustacchi 	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
148775eba5b6SRobert Mustacchi 		/* Read the MII 1000Base-T Control Register (Address 9). */
148875eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
148975eba5b6SRobert Mustacchi 					    &mii_1000t_ctrl_reg);
149075eba5b6SRobert Mustacchi 		if (ret_val)
149175eba5b6SRobert Mustacchi 			return ret_val;
149275eba5b6SRobert Mustacchi 	}
149375eba5b6SRobert Mustacchi 
149475eba5b6SRobert Mustacchi 	/* Need to parse both autoneg_advertised and fc and set up
149575eba5b6SRobert Mustacchi 	 * the appropriate PHY registers.  First we will parse for
149675eba5b6SRobert Mustacchi 	 * autoneg_advertised software override.  Since we can advertise
149775eba5b6SRobert Mustacchi 	 * a plethora of combinations, we need to check each bit
149875eba5b6SRobert Mustacchi 	 * individually.
149975eba5b6SRobert Mustacchi 	 */
150075eba5b6SRobert Mustacchi 
150175eba5b6SRobert Mustacchi 	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
150275eba5b6SRobert Mustacchi 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
150375eba5b6SRobert Mustacchi 	 * the  1000Base-T Control Register (Address 9).
150475eba5b6SRobert Mustacchi 	 */
150575eba5b6SRobert Mustacchi 	mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
150675eba5b6SRobert Mustacchi 				 NWAY_AR_100TX_HD_CAPS |
150775eba5b6SRobert Mustacchi 				 NWAY_AR_10T_FD_CAPS   |
150875eba5b6SRobert Mustacchi 				 NWAY_AR_10T_HD_CAPS);
150975eba5b6SRobert Mustacchi 	mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
151075eba5b6SRobert Mustacchi 
151175eba5b6SRobert Mustacchi 	DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised);
151275eba5b6SRobert Mustacchi 
151375eba5b6SRobert Mustacchi 	/* Do we want to advertise 10 Mb Half Duplex? */
151475eba5b6SRobert Mustacchi 	if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
151575eba5b6SRobert Mustacchi 		DEBUGOUT("Advertise 10mb Half duplex\n");
151675eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
151775eba5b6SRobert Mustacchi 	}
151875eba5b6SRobert Mustacchi 
151975eba5b6SRobert Mustacchi 	/* Do we want to advertise 10 Mb Full Duplex? */
152075eba5b6SRobert Mustacchi 	if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
152175eba5b6SRobert Mustacchi 		DEBUGOUT("Advertise 10mb Full duplex\n");
152275eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
152375eba5b6SRobert Mustacchi 	}
152475eba5b6SRobert Mustacchi 
152575eba5b6SRobert Mustacchi 	/* Do we want to advertise 100 Mb Half Duplex? */
152675eba5b6SRobert Mustacchi 	if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
152775eba5b6SRobert Mustacchi 		DEBUGOUT("Advertise 100mb Half duplex\n");
152875eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
152975eba5b6SRobert Mustacchi 	}
153075eba5b6SRobert Mustacchi 
153175eba5b6SRobert Mustacchi 	/* Do we want to advertise 100 Mb Full Duplex? */
153275eba5b6SRobert Mustacchi 	if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
153375eba5b6SRobert Mustacchi 		DEBUGOUT("Advertise 100mb Full duplex\n");
153475eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
153575eba5b6SRobert Mustacchi 	}
153675eba5b6SRobert Mustacchi 
153775eba5b6SRobert Mustacchi 	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
153875eba5b6SRobert Mustacchi 	if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
153975eba5b6SRobert Mustacchi 		DEBUGOUT("Advertise 1000mb Half duplex request denied!\n");
154075eba5b6SRobert Mustacchi 
154175eba5b6SRobert Mustacchi 	/* Do we want to advertise 1000 Mb Full Duplex? */
154275eba5b6SRobert Mustacchi 	if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
154375eba5b6SRobert Mustacchi 		DEBUGOUT("Advertise 1000mb Full duplex\n");
154475eba5b6SRobert Mustacchi 		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
154575eba5b6SRobert Mustacchi 	}
154675eba5b6SRobert Mustacchi 
154775eba5b6SRobert Mustacchi 	/* Check for a software override of the flow control settings, and
154875eba5b6SRobert Mustacchi 	 * setup the PHY advertisement registers accordingly.  If
154975eba5b6SRobert Mustacchi 	 * auto-negotiation is enabled, then software will have to set the
155075eba5b6SRobert Mustacchi 	 * "PAUSE" bits to the correct value in the Auto-Negotiation
155175eba5b6SRobert Mustacchi 	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
155275eba5b6SRobert Mustacchi 	 * negotiation.
155375eba5b6SRobert Mustacchi 	 *
155475eba5b6SRobert Mustacchi 	 * The possible values of the "fc" parameter are:
155575eba5b6SRobert Mustacchi 	 *      0:  Flow control is completely disabled
155675eba5b6SRobert Mustacchi 	 *      1:  Rx flow control is enabled (we can receive pause frames
155775eba5b6SRobert Mustacchi 	 *          but not send pause frames).
155875eba5b6SRobert Mustacchi 	 *      2:  Tx flow control is enabled (we can send pause frames
155975eba5b6SRobert Mustacchi 	 *          but we do not support receiving pause frames).
156075eba5b6SRobert Mustacchi 	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.
156175eba5b6SRobert Mustacchi 	 *  other:  No software override.  The flow control configuration
156275eba5b6SRobert Mustacchi 	 *          in the EEPROM is used.
156375eba5b6SRobert Mustacchi 	 */
156475eba5b6SRobert Mustacchi 	switch (hw->fc.current_mode) {
156575eba5b6SRobert Mustacchi 	case e1000_fc_none:
156675eba5b6SRobert Mustacchi 		/* Flow control (Rx & Tx) is completely disabled by a
156775eba5b6SRobert Mustacchi 		 * software over-ride.
156875eba5b6SRobert Mustacchi 		 */
156975eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
157075eba5b6SRobert Mustacchi 		break;
157175eba5b6SRobert Mustacchi 	case e1000_fc_rx_pause:
157275eba5b6SRobert Mustacchi 		/* Rx Flow control is enabled, and Tx Flow control is
157375eba5b6SRobert Mustacchi 		 * disabled, by a software over-ride.
157475eba5b6SRobert Mustacchi 		 *
157575eba5b6SRobert Mustacchi 		 * Since there really isn't a way to advertise that we are
157675eba5b6SRobert Mustacchi 		 * capable of Rx Pause ONLY, we will advertise that we
157775eba5b6SRobert Mustacchi 		 * support both symmetric and asymmetric Rx PAUSE.  Later
157875eba5b6SRobert Mustacchi 		 * (in e1000_config_fc_after_link_up) we will disable the
157975eba5b6SRobert Mustacchi 		 * hw's ability to send PAUSE frames.
158075eba5b6SRobert Mustacchi 		 */
158175eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
158275eba5b6SRobert Mustacchi 		break;
158375eba5b6SRobert Mustacchi 	case e1000_fc_tx_pause:
158475eba5b6SRobert Mustacchi 		/* Tx Flow control is enabled, and Rx Flow control is
158575eba5b6SRobert Mustacchi 		 * disabled, by a software over-ride.
158675eba5b6SRobert Mustacchi 		 */
158775eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
158875eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
158975eba5b6SRobert Mustacchi 		break;
159075eba5b6SRobert Mustacchi 	case e1000_fc_full:
159175eba5b6SRobert Mustacchi 		/* Flow control (both Rx and Tx) is enabled by a software
159275eba5b6SRobert Mustacchi 		 * over-ride.
159375eba5b6SRobert Mustacchi 		 */
159475eba5b6SRobert Mustacchi 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
159575eba5b6SRobert Mustacchi 		break;
159675eba5b6SRobert Mustacchi 	default:
159775eba5b6SRobert Mustacchi 		DEBUGOUT("Flow control param set incorrectly\n");
159875eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
159975eba5b6SRobert Mustacchi 	}
160075eba5b6SRobert Mustacchi 
160175eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
160275eba5b6SRobert Mustacchi 	if (ret_val)
160375eba5b6SRobert Mustacchi 		return ret_val;
160475eba5b6SRobert Mustacchi 
160575eba5b6SRobert Mustacchi 	DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
160675eba5b6SRobert Mustacchi 
160775eba5b6SRobert Mustacchi 	if (phy->autoneg_mask & ADVERTISE_1000_FULL)
160875eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
160975eba5b6SRobert Mustacchi 					     mii_1000t_ctrl_reg);
161075eba5b6SRobert Mustacchi 
161175eba5b6SRobert Mustacchi 	return ret_val;
161275eba5b6SRobert Mustacchi }
161375eba5b6SRobert Mustacchi 
161475eba5b6SRobert Mustacchi /**
161575eba5b6SRobert Mustacchi  *  e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
161675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
161775eba5b6SRobert Mustacchi  *
161875eba5b6SRobert Mustacchi  *  Performs initial bounds checking on autoneg advertisement parameter, then
161975eba5b6SRobert Mustacchi  *  configure to advertise the full capability.  Setup the PHY to autoneg
162075eba5b6SRobert Mustacchi  *  and restart the negotiation process between the link partner.  If
162175eba5b6SRobert Mustacchi  *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
162275eba5b6SRobert Mustacchi  **/
162375eba5b6SRobert Mustacchi s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
162475eba5b6SRobert Mustacchi {
162575eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
162675eba5b6SRobert Mustacchi 	s32 ret_val;
162775eba5b6SRobert Mustacchi 	u16 phy_ctrl;
162875eba5b6SRobert Mustacchi 
162975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_copper_link_autoneg");
163075eba5b6SRobert Mustacchi 
163175eba5b6SRobert Mustacchi 	/* Perform some bounds checking on the autoneg advertisement
163275eba5b6SRobert Mustacchi 	 * parameter.
163375eba5b6SRobert Mustacchi 	 */
163475eba5b6SRobert Mustacchi 	phy->autoneg_advertised &= phy->autoneg_mask;
163575eba5b6SRobert Mustacchi 
163675eba5b6SRobert Mustacchi 	/* If autoneg_advertised is zero, we assume it was not defaulted
163775eba5b6SRobert Mustacchi 	 * by the calling code so we set to advertise full capability.
163875eba5b6SRobert Mustacchi 	 */
163975eba5b6SRobert Mustacchi 	if (!phy->autoneg_advertised)
164075eba5b6SRobert Mustacchi 		phy->autoneg_advertised = phy->autoneg_mask;
164175eba5b6SRobert Mustacchi 
164275eba5b6SRobert Mustacchi 	DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
164375eba5b6SRobert Mustacchi 	ret_val = e1000_phy_setup_autoneg(hw);
164475eba5b6SRobert Mustacchi 	if (ret_val) {
164575eba5b6SRobert Mustacchi 		DEBUGOUT("Error Setting up Auto-Negotiation\n");
164675eba5b6SRobert Mustacchi 		return ret_val;
164775eba5b6SRobert Mustacchi 	}
164875eba5b6SRobert Mustacchi 	DEBUGOUT("Restarting Auto-Neg\n");
164975eba5b6SRobert Mustacchi 
165075eba5b6SRobert Mustacchi 	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
165175eba5b6SRobert Mustacchi 	 * the Auto Neg Restart bit in the PHY control register.
165275eba5b6SRobert Mustacchi 	 */
165375eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
165475eba5b6SRobert Mustacchi 	if (ret_val)
165575eba5b6SRobert Mustacchi 		return ret_val;
165675eba5b6SRobert Mustacchi 
165775eba5b6SRobert Mustacchi 	phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
165875eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
165975eba5b6SRobert Mustacchi 	if (ret_val)
166075eba5b6SRobert Mustacchi 		return ret_val;
166175eba5b6SRobert Mustacchi 
166275eba5b6SRobert Mustacchi 	/* Does the user want to wait for Auto-Neg to complete here, or
166375eba5b6SRobert Mustacchi 	 * check at a later time (for example, callback routine).
166475eba5b6SRobert Mustacchi 	 */
166575eba5b6SRobert Mustacchi 	if (phy->autoneg_wait_to_complete) {
166675eba5b6SRobert Mustacchi 		ret_val = e1000_wait_autoneg(hw);
166775eba5b6SRobert Mustacchi 		if (ret_val) {
166875eba5b6SRobert Mustacchi 			DEBUGOUT("Error while waiting for autoneg to complete\n");
166975eba5b6SRobert Mustacchi 			return ret_val;
167075eba5b6SRobert Mustacchi 		}
167175eba5b6SRobert Mustacchi 	}
167275eba5b6SRobert Mustacchi 
167375eba5b6SRobert Mustacchi 	hw->mac.get_link_status = TRUE;
167475eba5b6SRobert Mustacchi 
167575eba5b6SRobert Mustacchi 	return ret_val;
167675eba5b6SRobert Mustacchi }
167775eba5b6SRobert Mustacchi 
167875eba5b6SRobert Mustacchi /**
167975eba5b6SRobert Mustacchi  *  e1000_setup_copper_link_generic - Configure copper link settings
168075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
168175eba5b6SRobert Mustacchi  *
168275eba5b6SRobert Mustacchi  *  Calls the appropriate function to configure the link for auto-neg or forced
168375eba5b6SRobert Mustacchi  *  speed and duplex.  Then we check for link, once link is established calls
168475eba5b6SRobert Mustacchi  *  to configure collision distance and flow control are called.  If link is
168575eba5b6SRobert Mustacchi  *  not established, we return -E1000_ERR_PHY (-2).
168675eba5b6SRobert Mustacchi  **/
168775eba5b6SRobert Mustacchi s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
168875eba5b6SRobert Mustacchi {
168975eba5b6SRobert Mustacchi 	s32 ret_val;
169075eba5b6SRobert Mustacchi 	bool link;
169175eba5b6SRobert Mustacchi 
169275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_setup_copper_link_generic");
169375eba5b6SRobert Mustacchi 
169475eba5b6SRobert Mustacchi 	if (hw->mac.autoneg) {
169575eba5b6SRobert Mustacchi 		/* Setup autoneg and flow control advertisement and perform
169675eba5b6SRobert Mustacchi 		 * autonegotiation.
169775eba5b6SRobert Mustacchi 		 */
169875eba5b6SRobert Mustacchi 		ret_val = e1000_copper_link_autoneg(hw);
169975eba5b6SRobert Mustacchi 		if (ret_val)
170075eba5b6SRobert Mustacchi 			return ret_val;
170175eba5b6SRobert Mustacchi 	} else {
170275eba5b6SRobert Mustacchi 		/* PHY will be set to 10H, 10F, 100H or 100F
170375eba5b6SRobert Mustacchi 		 * depending on user settings.
170475eba5b6SRobert Mustacchi 		 */
170575eba5b6SRobert Mustacchi 		DEBUGOUT("Forcing Speed and Duplex\n");
170675eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.force_speed_duplex(hw);
170775eba5b6SRobert Mustacchi 		if (ret_val) {
170875eba5b6SRobert Mustacchi 			DEBUGOUT("Error Forcing Speed and Duplex\n");
170975eba5b6SRobert Mustacchi 			return ret_val;
171075eba5b6SRobert Mustacchi 		}
171175eba5b6SRobert Mustacchi 	}
171275eba5b6SRobert Mustacchi 
171375eba5b6SRobert Mustacchi 	/* Check link status. Wait up to 100 microseconds for link to become
171475eba5b6SRobert Mustacchi 	 * valid.
171575eba5b6SRobert Mustacchi 	 */
171675eba5b6SRobert Mustacchi 	ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
171775eba5b6SRobert Mustacchi 					     &link);
171875eba5b6SRobert Mustacchi 	if (ret_val)
171975eba5b6SRobert Mustacchi 		return ret_val;
172075eba5b6SRobert Mustacchi 
172175eba5b6SRobert Mustacchi 	if (link) {
172275eba5b6SRobert Mustacchi 		DEBUGOUT("Valid link established!!!\n");
172375eba5b6SRobert Mustacchi 		hw->mac.ops.config_collision_dist(hw);
172475eba5b6SRobert Mustacchi 		ret_val = e1000_config_fc_after_link_up_generic(hw);
172575eba5b6SRobert Mustacchi 	} else {
172675eba5b6SRobert Mustacchi 		DEBUGOUT("Unable to establish link!!!\n");
172775eba5b6SRobert Mustacchi 	}
172875eba5b6SRobert Mustacchi 
172975eba5b6SRobert Mustacchi 	return ret_val;
173075eba5b6SRobert Mustacchi }
173175eba5b6SRobert Mustacchi 
173275eba5b6SRobert Mustacchi /**
173375eba5b6SRobert Mustacchi  *  e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY
173475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
173575eba5b6SRobert Mustacchi  *
173675eba5b6SRobert Mustacchi  *  Calls the PHY setup function to force speed and duplex.  Clears the
173775eba5b6SRobert Mustacchi  *  auto-crossover to force MDI manually.  Waits for link and returns
173875eba5b6SRobert Mustacchi  *  successful if link up is successful, else -E1000_ERR_PHY (-2).
173975eba5b6SRobert Mustacchi  **/
174075eba5b6SRobert Mustacchi s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
174175eba5b6SRobert Mustacchi {
174275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
174375eba5b6SRobert Mustacchi 	s32 ret_val;
174475eba5b6SRobert Mustacchi 	u16 phy_data;
174575eba5b6SRobert Mustacchi 	bool link;
174675eba5b6SRobert Mustacchi 
174775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_force_speed_duplex_igp");
174875eba5b6SRobert Mustacchi 
174975eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
175075eba5b6SRobert Mustacchi 	if (ret_val)
175175eba5b6SRobert Mustacchi 		return ret_val;
175275eba5b6SRobert Mustacchi 
175375eba5b6SRobert Mustacchi 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
175475eba5b6SRobert Mustacchi 
175575eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
175675eba5b6SRobert Mustacchi 	if (ret_val)
175775eba5b6SRobert Mustacchi 		return ret_val;
175875eba5b6SRobert Mustacchi 
175975eba5b6SRobert Mustacchi 	/* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
176075eba5b6SRobert Mustacchi 	 * forced whenever speed and duplex are forced.
176175eba5b6SRobert Mustacchi 	 */
176275eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
176375eba5b6SRobert Mustacchi 	if (ret_val)
176475eba5b6SRobert Mustacchi 		return ret_val;
176575eba5b6SRobert Mustacchi 
176675eba5b6SRobert Mustacchi 	phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
176775eba5b6SRobert Mustacchi 	phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
176875eba5b6SRobert Mustacchi 
176975eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
177075eba5b6SRobert Mustacchi 	if (ret_val)
177175eba5b6SRobert Mustacchi 		return ret_val;
177275eba5b6SRobert Mustacchi 
177375eba5b6SRobert Mustacchi 	DEBUGOUT1("IGP PSCR: %X\n", phy_data);
177475eba5b6SRobert Mustacchi 
177575eba5b6SRobert Mustacchi 	usec_delay(1);
177675eba5b6SRobert Mustacchi 
177775eba5b6SRobert Mustacchi 	if (phy->autoneg_wait_to_complete) {
177875eba5b6SRobert Mustacchi 		DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n");
177975eba5b6SRobert Mustacchi 
178075eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
178175eba5b6SRobert Mustacchi 						     100000, &link);
178275eba5b6SRobert Mustacchi 		if (ret_val)
178375eba5b6SRobert Mustacchi 			return ret_val;
178475eba5b6SRobert Mustacchi 
178575eba5b6SRobert Mustacchi 		if (!link)
178675eba5b6SRobert Mustacchi 			DEBUGOUT("Link taking longer than expected.\n");
178775eba5b6SRobert Mustacchi 
178875eba5b6SRobert Mustacchi 		/* Try once more */
178975eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
179075eba5b6SRobert Mustacchi 						     100000, &link);
179175eba5b6SRobert Mustacchi 	}
179275eba5b6SRobert Mustacchi 
179375eba5b6SRobert Mustacchi 	return ret_val;
179475eba5b6SRobert Mustacchi }
179575eba5b6SRobert Mustacchi 
179675eba5b6SRobert Mustacchi /**
179775eba5b6SRobert Mustacchi  *  e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY
179875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
179975eba5b6SRobert Mustacchi  *
180075eba5b6SRobert Mustacchi  *  Calls the PHY setup function to force speed and duplex.  Clears the
180175eba5b6SRobert Mustacchi  *  auto-crossover to force MDI manually.  Resets the PHY to commit the
180275eba5b6SRobert Mustacchi  *  changes.  If time expires while waiting for link up, we reset the DSP.
180375eba5b6SRobert Mustacchi  *  After reset, TX_CLK and CRS on Tx must be set.  Return successful upon
180475eba5b6SRobert Mustacchi  *  successful completion, else return corresponding error code.
180575eba5b6SRobert Mustacchi  **/
180675eba5b6SRobert Mustacchi s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
180775eba5b6SRobert Mustacchi {
180875eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
180975eba5b6SRobert Mustacchi 	s32 ret_val;
181075eba5b6SRobert Mustacchi 	u16 phy_data;
181175eba5b6SRobert Mustacchi 	bool link;
181275eba5b6SRobert Mustacchi 
181375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_force_speed_duplex_m88");
181475eba5b6SRobert Mustacchi 
181575eba5b6SRobert Mustacchi 	/* I210 and I211 devices support Auto-Crossover in forced operation. */
181675eba5b6SRobert Mustacchi 	if (phy->type != e1000_phy_i210) {
181775eba5b6SRobert Mustacchi 		/* Clear Auto-Crossover to force MDI manually.  M88E1000
181875eba5b6SRobert Mustacchi 		 * requires MDI forced whenever speed and duplex are forced.
181975eba5b6SRobert Mustacchi 		 */
182075eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
182175eba5b6SRobert Mustacchi 					    &phy_data);
182275eba5b6SRobert Mustacchi 		if (ret_val)
182375eba5b6SRobert Mustacchi 			return ret_val;
182475eba5b6SRobert Mustacchi 
182575eba5b6SRobert Mustacchi 		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
182675eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
182775eba5b6SRobert Mustacchi 					     phy_data);
182875eba5b6SRobert Mustacchi 		if (ret_val)
182975eba5b6SRobert Mustacchi 			return ret_val;
183075eba5b6SRobert Mustacchi 
183175eba5b6SRobert Mustacchi 		DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
1832*42cc51e0SRobert Mustacchi 	}
183375eba5b6SRobert Mustacchi 
183475eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
183575eba5b6SRobert Mustacchi 	if (ret_val)
183675eba5b6SRobert Mustacchi 		return ret_val;
183775eba5b6SRobert Mustacchi 
183875eba5b6SRobert Mustacchi 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
183975eba5b6SRobert Mustacchi 
184075eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
184175eba5b6SRobert Mustacchi 	if (ret_val)
184275eba5b6SRobert Mustacchi 		return ret_val;
184375eba5b6SRobert Mustacchi 
184475eba5b6SRobert Mustacchi 	/* Reset the phy to commit changes. */
184575eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.commit(hw);
184675eba5b6SRobert Mustacchi 	if (ret_val)
184775eba5b6SRobert Mustacchi 		return ret_val;
184875eba5b6SRobert Mustacchi 
184975eba5b6SRobert Mustacchi 	if (phy->autoneg_wait_to_complete) {
185075eba5b6SRobert Mustacchi 		DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n");
185175eba5b6SRobert Mustacchi 
185275eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
185375eba5b6SRobert Mustacchi 						     100000, &link);
185475eba5b6SRobert Mustacchi 		if (ret_val)
185575eba5b6SRobert Mustacchi 			return ret_val;
185675eba5b6SRobert Mustacchi 
185775eba5b6SRobert Mustacchi 		if (!link) {
185875eba5b6SRobert Mustacchi 			bool reset_dsp = TRUE;
185975eba5b6SRobert Mustacchi 
186075eba5b6SRobert Mustacchi 			switch (hw->phy.id) {
186175eba5b6SRobert Mustacchi 			case I347AT4_E_PHY_ID:
186275eba5b6SRobert Mustacchi 			case M88E1340M_E_PHY_ID:
186375eba5b6SRobert Mustacchi 			case M88E1112_E_PHY_ID:
1864c124a83eSRobert Mustacchi 			case M88E1543_E_PHY_ID:
1865c124a83eSRobert Mustacchi 			case M88E1512_E_PHY_ID:
186675eba5b6SRobert Mustacchi 			case I210_I_PHY_ID:
186775eba5b6SRobert Mustacchi 				reset_dsp = FALSE;
186875eba5b6SRobert Mustacchi 				break;
186975eba5b6SRobert Mustacchi 			default:
187075eba5b6SRobert Mustacchi 				if (hw->phy.type != e1000_phy_m88)
187175eba5b6SRobert Mustacchi 					reset_dsp = FALSE;
187275eba5b6SRobert Mustacchi 				break;
187375eba5b6SRobert Mustacchi 			}
187475eba5b6SRobert Mustacchi 
187575eba5b6SRobert Mustacchi 			if (!reset_dsp) {
187675eba5b6SRobert Mustacchi 				DEBUGOUT("Link taking longer than expected.\n");
187775eba5b6SRobert Mustacchi 			} else {
187875eba5b6SRobert Mustacchi 				/* We didn't get link.
187975eba5b6SRobert Mustacchi 				 * Reset the DSP and cross our fingers.
188075eba5b6SRobert Mustacchi 				 */
188175eba5b6SRobert Mustacchi 				ret_val = phy->ops.write_reg(hw,
188275eba5b6SRobert Mustacchi 						M88E1000_PHY_PAGE_SELECT,
188375eba5b6SRobert Mustacchi 						0x001d);
188475eba5b6SRobert Mustacchi 				if (ret_val)
188575eba5b6SRobert Mustacchi 					return ret_val;
188675eba5b6SRobert Mustacchi 				ret_val = e1000_phy_reset_dsp_generic(hw);
188775eba5b6SRobert Mustacchi 				if (ret_val)
188875eba5b6SRobert Mustacchi 					return ret_val;
188975eba5b6SRobert Mustacchi 			}
189075eba5b6SRobert Mustacchi 		}
189175eba5b6SRobert Mustacchi 
189275eba5b6SRobert Mustacchi 		/* Try once more */
189375eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
189475eba5b6SRobert Mustacchi 						     100000, &link);
189575eba5b6SRobert Mustacchi 		if (ret_val)
189675eba5b6SRobert Mustacchi 			return ret_val;
189775eba5b6SRobert Mustacchi 	}
189875eba5b6SRobert Mustacchi 
189975eba5b6SRobert Mustacchi 	if (hw->phy.type != e1000_phy_m88)
190075eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
190175eba5b6SRobert Mustacchi 
190275eba5b6SRobert Mustacchi 	if (hw->phy.id == I347AT4_E_PHY_ID ||
190375eba5b6SRobert Mustacchi 		hw->phy.id == M88E1340M_E_PHY_ID ||
190475eba5b6SRobert Mustacchi 		hw->phy.id == M88E1112_E_PHY_ID)
190575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
190675eba5b6SRobert Mustacchi 	if (hw->phy.id == I210_I_PHY_ID)
190775eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
1908c124a83eSRobert Mustacchi 	if ((hw->phy.id == M88E1543_E_PHY_ID) ||
1909c124a83eSRobert Mustacchi 	    (hw->phy.id == M88E1512_E_PHY_ID))
1910c124a83eSRobert Mustacchi 		return E1000_SUCCESS;
191175eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
191275eba5b6SRobert Mustacchi 	if (ret_val)
191375eba5b6SRobert Mustacchi 		return ret_val;
191475eba5b6SRobert Mustacchi 
191575eba5b6SRobert Mustacchi 	/* Resetting the phy means we need to re-force TX_CLK in the
191675eba5b6SRobert Mustacchi 	 * Extended PHY Specific Control Register to 25MHz clock from
191775eba5b6SRobert Mustacchi 	 * the reset value of 2.5MHz.
191875eba5b6SRobert Mustacchi 	 */
191975eba5b6SRobert Mustacchi 	phy_data |= M88E1000_EPSCR_TX_CLK_25;
192075eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
192175eba5b6SRobert Mustacchi 	if (ret_val)
192275eba5b6SRobert Mustacchi 		return ret_val;
192375eba5b6SRobert Mustacchi 
192475eba5b6SRobert Mustacchi 	/* In addition, we must re-enable CRS on Tx for both half and full
192575eba5b6SRobert Mustacchi 	 * duplex.
192675eba5b6SRobert Mustacchi 	 */
192775eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
192875eba5b6SRobert Mustacchi 	if (ret_val)
192975eba5b6SRobert Mustacchi 		return ret_val;
193075eba5b6SRobert Mustacchi 
193175eba5b6SRobert Mustacchi 	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
193275eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
193375eba5b6SRobert Mustacchi 
193475eba5b6SRobert Mustacchi 	return ret_val;
193575eba5b6SRobert Mustacchi }
193675eba5b6SRobert Mustacchi 
193775eba5b6SRobert Mustacchi /**
193875eba5b6SRobert Mustacchi  *  e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex
193975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
194075eba5b6SRobert Mustacchi  *
194175eba5b6SRobert Mustacchi  *  Forces the speed and duplex settings of the PHY.
194275eba5b6SRobert Mustacchi  *  This is a function pointer entry point only called by
194375eba5b6SRobert Mustacchi  *  PHY setup routines.
194475eba5b6SRobert Mustacchi  **/
194575eba5b6SRobert Mustacchi s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
194675eba5b6SRobert Mustacchi {
194775eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
194875eba5b6SRobert Mustacchi 	s32 ret_val;
194975eba5b6SRobert Mustacchi 	u16 data;
195075eba5b6SRobert Mustacchi 	bool link;
195175eba5b6SRobert Mustacchi 
195275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_force_speed_duplex_ife");
195375eba5b6SRobert Mustacchi 
195475eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);
195575eba5b6SRobert Mustacchi 	if (ret_val)
195675eba5b6SRobert Mustacchi 		return ret_val;
195775eba5b6SRobert Mustacchi 
195875eba5b6SRobert Mustacchi 	e1000_phy_force_speed_duplex_setup(hw, &data);
195975eba5b6SRobert Mustacchi 
196075eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);
196175eba5b6SRobert Mustacchi 	if (ret_val)
196275eba5b6SRobert Mustacchi 		return ret_val;
196375eba5b6SRobert Mustacchi 
196475eba5b6SRobert Mustacchi 	/* Disable MDI-X support for 10/100 */
196575eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
196675eba5b6SRobert Mustacchi 	if (ret_val)
196775eba5b6SRobert Mustacchi 		return ret_val;
196875eba5b6SRobert Mustacchi 
196975eba5b6SRobert Mustacchi 	data &= ~IFE_PMC_AUTO_MDIX;
197075eba5b6SRobert Mustacchi 	data &= ~IFE_PMC_FORCE_MDIX;
197175eba5b6SRobert Mustacchi 
197275eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);
197375eba5b6SRobert Mustacchi 	if (ret_val)
197475eba5b6SRobert Mustacchi 		return ret_val;
197575eba5b6SRobert Mustacchi 
197675eba5b6SRobert Mustacchi 	DEBUGOUT1("IFE PMC: %X\n", data);
197775eba5b6SRobert Mustacchi 
197875eba5b6SRobert Mustacchi 	usec_delay(1);
197975eba5b6SRobert Mustacchi 
198075eba5b6SRobert Mustacchi 	if (phy->autoneg_wait_to_complete) {
198175eba5b6SRobert Mustacchi 		DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n");
198275eba5b6SRobert Mustacchi 
198375eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
198475eba5b6SRobert Mustacchi 						     100000, &link);
198575eba5b6SRobert Mustacchi 		if (ret_val)
198675eba5b6SRobert Mustacchi 			return ret_val;
198775eba5b6SRobert Mustacchi 
198875eba5b6SRobert Mustacchi 		if (!link)
198975eba5b6SRobert Mustacchi 			DEBUGOUT("Link taking longer than expected.\n");
199075eba5b6SRobert Mustacchi 
199175eba5b6SRobert Mustacchi 		/* Try once more */
199275eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
199375eba5b6SRobert Mustacchi 						     100000, &link);
199475eba5b6SRobert Mustacchi 		if (ret_val)
199575eba5b6SRobert Mustacchi 			return ret_val;
199675eba5b6SRobert Mustacchi 	}
199775eba5b6SRobert Mustacchi 
199875eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
199975eba5b6SRobert Mustacchi }
200075eba5b6SRobert Mustacchi 
200175eba5b6SRobert Mustacchi /**
200275eba5b6SRobert Mustacchi  *  e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex
200375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
200475eba5b6SRobert Mustacchi  *  @phy_ctrl: pointer to current value of PHY_CONTROL
200575eba5b6SRobert Mustacchi  *
200675eba5b6SRobert Mustacchi  *  Forces speed and duplex on the PHY by doing the following: disable flow
200775eba5b6SRobert Mustacchi  *  control, force speed/duplex on the MAC, disable auto speed detection,
200875eba5b6SRobert Mustacchi  *  disable auto-negotiation, configure duplex, configure speed, configure
200975eba5b6SRobert Mustacchi  *  the collision distance, write configuration to CTRL register.  The
201075eba5b6SRobert Mustacchi  *  caller must write to the PHY_CONTROL register for these settings to
201175eba5b6SRobert Mustacchi  *  take affect.
201275eba5b6SRobert Mustacchi  **/
201375eba5b6SRobert Mustacchi void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
201475eba5b6SRobert Mustacchi {
201575eba5b6SRobert Mustacchi 	struct e1000_mac_info *mac = &hw->mac;
201675eba5b6SRobert Mustacchi 	u32 ctrl;
201775eba5b6SRobert Mustacchi 
201875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_force_speed_duplex_setup");
201975eba5b6SRobert Mustacchi 
202075eba5b6SRobert Mustacchi 	/* Turn off flow control when forcing speed/duplex */
202175eba5b6SRobert Mustacchi 	hw->fc.current_mode = e1000_fc_none;
202275eba5b6SRobert Mustacchi 
202375eba5b6SRobert Mustacchi 	/* Force speed/duplex on the mac */
202475eba5b6SRobert Mustacchi 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
202575eba5b6SRobert Mustacchi 	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
202675eba5b6SRobert Mustacchi 	ctrl &= ~E1000_CTRL_SPD_SEL;
202775eba5b6SRobert Mustacchi 
202875eba5b6SRobert Mustacchi 	/* Disable Auto Speed Detection */
202975eba5b6SRobert Mustacchi 	ctrl &= ~E1000_CTRL_ASDE;
203075eba5b6SRobert Mustacchi 
203175eba5b6SRobert Mustacchi 	/* Disable autoneg on the phy */
203275eba5b6SRobert Mustacchi 	*phy_ctrl &= ~MII_CR_AUTO_NEG_EN;
203375eba5b6SRobert Mustacchi 
203475eba5b6SRobert Mustacchi 	/* Forcing Full or Half Duplex? */
203575eba5b6SRobert Mustacchi 	if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) {
203675eba5b6SRobert Mustacchi 		ctrl &= ~E1000_CTRL_FD;
203775eba5b6SRobert Mustacchi 		*phy_ctrl &= ~MII_CR_FULL_DUPLEX;
203875eba5b6SRobert Mustacchi 		DEBUGOUT("Half Duplex\n");
203975eba5b6SRobert Mustacchi 	} else {
204075eba5b6SRobert Mustacchi 		ctrl |= E1000_CTRL_FD;
204175eba5b6SRobert Mustacchi 		*phy_ctrl |= MII_CR_FULL_DUPLEX;
204275eba5b6SRobert Mustacchi 		DEBUGOUT("Full Duplex\n");
204375eba5b6SRobert Mustacchi 	}
204475eba5b6SRobert Mustacchi 
204575eba5b6SRobert Mustacchi 	/* Forcing 10mb or 100mb? */
204675eba5b6SRobert Mustacchi 	if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) {
204775eba5b6SRobert Mustacchi 		ctrl |= E1000_CTRL_SPD_100;
204875eba5b6SRobert Mustacchi 		*phy_ctrl |= MII_CR_SPEED_100;
204975eba5b6SRobert Mustacchi 		*phy_ctrl &= ~MII_CR_SPEED_1000;
205075eba5b6SRobert Mustacchi 		DEBUGOUT("Forcing 100mb\n");
205175eba5b6SRobert Mustacchi 	} else {
205275eba5b6SRobert Mustacchi 		ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
205375eba5b6SRobert Mustacchi 		*phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
205475eba5b6SRobert Mustacchi 		DEBUGOUT("Forcing 10mb\n");
205575eba5b6SRobert Mustacchi 	}
205675eba5b6SRobert Mustacchi 
205775eba5b6SRobert Mustacchi 	hw->mac.ops.config_collision_dist(hw);
205875eba5b6SRobert Mustacchi 
205975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
206075eba5b6SRobert Mustacchi }
206175eba5b6SRobert Mustacchi 
206275eba5b6SRobert Mustacchi /**
206375eba5b6SRobert Mustacchi  *  e1000_set_d3_lplu_state_generic - Sets low power link up state for D3
206475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
206575eba5b6SRobert Mustacchi  *  @active: boolean used to enable/disable lplu
206675eba5b6SRobert Mustacchi  *
206775eba5b6SRobert Mustacchi  *  Success returns 0, Failure returns 1
206875eba5b6SRobert Mustacchi  *
206975eba5b6SRobert Mustacchi  *  The low power link up (lplu) state is set to the power management level D3
207075eba5b6SRobert Mustacchi  *  and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
207175eba5b6SRobert Mustacchi  *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
207275eba5b6SRobert Mustacchi  *  is used during Dx states where the power conservation is most important.
207375eba5b6SRobert Mustacchi  *  During driver activity, SmartSpeed should be enabled so performance is
207475eba5b6SRobert Mustacchi  *  maintained.
207575eba5b6SRobert Mustacchi  **/
207675eba5b6SRobert Mustacchi s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
207775eba5b6SRobert Mustacchi {
207875eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
207975eba5b6SRobert Mustacchi 	s32 ret_val;
208075eba5b6SRobert Mustacchi 	u16 data;
208175eba5b6SRobert Mustacchi 
208275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_set_d3_lplu_state_generic");
208375eba5b6SRobert Mustacchi 
208475eba5b6SRobert Mustacchi 	if (!hw->phy.ops.read_reg)
208575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
208675eba5b6SRobert Mustacchi 
208775eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
208875eba5b6SRobert Mustacchi 	if (ret_val)
208975eba5b6SRobert Mustacchi 		return ret_val;
209075eba5b6SRobert Mustacchi 
209175eba5b6SRobert Mustacchi 	if (!active) {
209275eba5b6SRobert Mustacchi 		data &= ~IGP02E1000_PM_D3_LPLU;
209375eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
209475eba5b6SRobert Mustacchi 					     data);
209575eba5b6SRobert Mustacchi 		if (ret_val)
209675eba5b6SRobert Mustacchi 			return ret_val;
209775eba5b6SRobert Mustacchi 		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
209875eba5b6SRobert Mustacchi 		 * during Dx states where the power conservation is most
209975eba5b6SRobert Mustacchi 		 * important.  During driver activity we should enable
210075eba5b6SRobert Mustacchi 		 * SmartSpeed, so performance is maintained.
210175eba5b6SRobert Mustacchi 		 */
210275eba5b6SRobert Mustacchi 		if (phy->smart_speed == e1000_smart_speed_on) {
210375eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw,
210475eba5b6SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
210575eba5b6SRobert Mustacchi 						    &data);
210675eba5b6SRobert Mustacchi 			if (ret_val)
210775eba5b6SRobert Mustacchi 				return ret_val;
210875eba5b6SRobert Mustacchi 
210975eba5b6SRobert Mustacchi 			data |= IGP01E1000_PSCFR_SMART_SPEED;
211075eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw,
211175eba5b6SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
211275eba5b6SRobert Mustacchi 						     data);
211375eba5b6SRobert Mustacchi 			if (ret_val)
211475eba5b6SRobert Mustacchi 				return ret_val;
211575eba5b6SRobert Mustacchi 		} else if (phy->smart_speed == e1000_smart_speed_off) {
211675eba5b6SRobert Mustacchi 			ret_val = phy->ops.read_reg(hw,
211775eba5b6SRobert Mustacchi 						    IGP01E1000_PHY_PORT_CONFIG,
211875eba5b6SRobert Mustacchi 						    &data);
211975eba5b6SRobert Mustacchi 			if (ret_val)
212075eba5b6SRobert Mustacchi 				return ret_val;
212175eba5b6SRobert Mustacchi 
212275eba5b6SRobert Mustacchi 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
212375eba5b6SRobert Mustacchi 			ret_val = phy->ops.write_reg(hw,
212475eba5b6SRobert Mustacchi 						     IGP01E1000_PHY_PORT_CONFIG,
212575eba5b6SRobert Mustacchi 						     data);
212675eba5b6SRobert Mustacchi 			if (ret_val)
212775eba5b6SRobert Mustacchi 				return ret_val;
212875eba5b6SRobert Mustacchi 		}
212975eba5b6SRobert Mustacchi 	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
213075eba5b6SRobert Mustacchi 		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
213175eba5b6SRobert Mustacchi 		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
213275eba5b6SRobert Mustacchi 		data |= IGP02E1000_PM_D3_LPLU;
213375eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
213475eba5b6SRobert Mustacchi 					     data);
213575eba5b6SRobert Mustacchi 		if (ret_val)
213675eba5b6SRobert Mustacchi 			return ret_val;
213775eba5b6SRobert Mustacchi 
213875eba5b6SRobert Mustacchi 		/* When LPLU is enabled, we should disable SmartSpeed */
213975eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
214075eba5b6SRobert Mustacchi 					    &data);
214175eba5b6SRobert Mustacchi 		if (ret_val)
214275eba5b6SRobert Mustacchi 			return ret_val;
214375eba5b6SRobert Mustacchi 
214475eba5b6SRobert Mustacchi 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
214575eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
214675eba5b6SRobert Mustacchi 					     data);
214775eba5b6SRobert Mustacchi 	}
214875eba5b6SRobert Mustacchi 
214975eba5b6SRobert Mustacchi 	return ret_val;
215075eba5b6SRobert Mustacchi }
215175eba5b6SRobert Mustacchi 
215275eba5b6SRobert Mustacchi /**
215375eba5b6SRobert Mustacchi  *  e1000_check_downshift_generic - Checks whether a downshift in speed occurred
215475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
215575eba5b6SRobert Mustacchi  *
215675eba5b6SRobert Mustacchi  *  Success returns 0, Failure returns 1
215775eba5b6SRobert Mustacchi  *
215875eba5b6SRobert Mustacchi  *  A downshift is detected by querying the PHY link health.
215975eba5b6SRobert Mustacchi  **/
216075eba5b6SRobert Mustacchi s32 e1000_check_downshift_generic(struct e1000_hw *hw)
216175eba5b6SRobert Mustacchi {
216275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
216375eba5b6SRobert Mustacchi 	s32 ret_val;
216475eba5b6SRobert Mustacchi 	u16 phy_data, offset, mask;
216575eba5b6SRobert Mustacchi 
216675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_downshift_generic");
216775eba5b6SRobert Mustacchi 
216875eba5b6SRobert Mustacchi 	switch (phy->type) {
216975eba5b6SRobert Mustacchi 	case e1000_phy_i210:
217075eba5b6SRobert Mustacchi 	case e1000_phy_m88:
217175eba5b6SRobert Mustacchi 	case e1000_phy_gg82563:
217275eba5b6SRobert Mustacchi 	case e1000_phy_bm:
217375eba5b6SRobert Mustacchi 	case e1000_phy_82578:
217475eba5b6SRobert Mustacchi 		offset = M88E1000_PHY_SPEC_STATUS;
217575eba5b6SRobert Mustacchi 		mask = M88E1000_PSSR_DOWNSHIFT;
217675eba5b6SRobert Mustacchi 		break;
217775eba5b6SRobert Mustacchi 	case e1000_phy_igp:
217875eba5b6SRobert Mustacchi 	case e1000_phy_igp_2:
217975eba5b6SRobert Mustacchi 	case e1000_phy_igp_3:
218075eba5b6SRobert Mustacchi 		offset = IGP01E1000_PHY_LINK_HEALTH;
218175eba5b6SRobert Mustacchi 		mask = IGP01E1000_PLHR_SS_DOWNGRADE;
218275eba5b6SRobert Mustacchi 		break;
218375eba5b6SRobert Mustacchi 	default:
218475eba5b6SRobert Mustacchi 		/* speed downshift not supported */
218575eba5b6SRobert Mustacchi 		phy->speed_downgraded = FALSE;
218675eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
218775eba5b6SRobert Mustacchi 	}
218875eba5b6SRobert Mustacchi 
218975eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, offset, &phy_data);
219075eba5b6SRobert Mustacchi 
219175eba5b6SRobert Mustacchi 	if (!ret_val)
219275eba5b6SRobert Mustacchi 		phy->speed_downgraded = !!(phy_data & mask);
219375eba5b6SRobert Mustacchi 
219475eba5b6SRobert Mustacchi 	return ret_val;
219575eba5b6SRobert Mustacchi }
219675eba5b6SRobert Mustacchi 
219775eba5b6SRobert Mustacchi /**
219875eba5b6SRobert Mustacchi  *  e1000_check_polarity_m88 - Checks the polarity.
219975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
220075eba5b6SRobert Mustacchi  *
220175eba5b6SRobert Mustacchi  *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
220275eba5b6SRobert Mustacchi  *
220375eba5b6SRobert Mustacchi  *  Polarity is determined based on the PHY specific status register.
220475eba5b6SRobert Mustacchi  **/
220575eba5b6SRobert Mustacchi s32 e1000_check_polarity_m88(struct e1000_hw *hw)
220675eba5b6SRobert Mustacchi {
220775eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
220875eba5b6SRobert Mustacchi 	s32 ret_val;
220975eba5b6SRobert Mustacchi 	u16 data;
221075eba5b6SRobert Mustacchi 
221175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_polarity_m88");
221275eba5b6SRobert Mustacchi 
221375eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data);
221475eba5b6SRobert Mustacchi 
221575eba5b6SRobert Mustacchi 	if (!ret_val)
2216c124a83eSRobert Mustacchi 		phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY)
221775eba5b6SRobert Mustacchi 				       ? e1000_rev_polarity_reversed
2218c124a83eSRobert Mustacchi 				       : e1000_rev_polarity_normal);
221975eba5b6SRobert Mustacchi 
222075eba5b6SRobert Mustacchi 	return ret_val;
222175eba5b6SRobert Mustacchi }
222275eba5b6SRobert Mustacchi 
222375eba5b6SRobert Mustacchi /**
222475eba5b6SRobert Mustacchi  *  e1000_check_polarity_igp - Checks the polarity.
222575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
222675eba5b6SRobert Mustacchi  *
222775eba5b6SRobert Mustacchi  *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
222875eba5b6SRobert Mustacchi  *
222975eba5b6SRobert Mustacchi  *  Polarity is determined based on the PHY port status register, and the
223075eba5b6SRobert Mustacchi  *  current speed (since there is no polarity at 100Mbps).
223175eba5b6SRobert Mustacchi  **/
223275eba5b6SRobert Mustacchi s32 e1000_check_polarity_igp(struct e1000_hw *hw)
223375eba5b6SRobert Mustacchi {
223475eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
223575eba5b6SRobert Mustacchi 	s32 ret_val;
223675eba5b6SRobert Mustacchi 	u16 data, offset, mask;
223775eba5b6SRobert Mustacchi 
223875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_polarity_igp");
223975eba5b6SRobert Mustacchi 
224075eba5b6SRobert Mustacchi 	/* Polarity is determined based on the speed of
224175eba5b6SRobert Mustacchi 	 * our connection.
224275eba5b6SRobert Mustacchi 	 */
224375eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
224475eba5b6SRobert Mustacchi 	if (ret_val)
224575eba5b6SRobert Mustacchi 		return ret_val;
224675eba5b6SRobert Mustacchi 
224775eba5b6SRobert Mustacchi 	if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
224875eba5b6SRobert Mustacchi 	    IGP01E1000_PSSR_SPEED_1000MBPS) {
224975eba5b6SRobert Mustacchi 		offset = IGP01E1000_PHY_PCS_INIT_REG;
225075eba5b6SRobert Mustacchi 		mask = IGP01E1000_PHY_POLARITY_MASK;
225175eba5b6SRobert Mustacchi 	} else {
225275eba5b6SRobert Mustacchi 		/* This really only applies to 10Mbps since
225375eba5b6SRobert Mustacchi 		 * there is no polarity for 100Mbps (always 0).
225475eba5b6SRobert Mustacchi 		 */
225575eba5b6SRobert Mustacchi 		offset = IGP01E1000_PHY_PORT_STATUS;
225675eba5b6SRobert Mustacchi 		mask = IGP01E1000_PSSR_POLARITY_REVERSED;
225775eba5b6SRobert Mustacchi 	}
225875eba5b6SRobert Mustacchi 
225975eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, offset, &data);
226075eba5b6SRobert Mustacchi 
226175eba5b6SRobert Mustacchi 	if (!ret_val)
2262c124a83eSRobert Mustacchi 		phy->cable_polarity = ((data & mask)
226375eba5b6SRobert Mustacchi 				       ? e1000_rev_polarity_reversed
2264c124a83eSRobert Mustacchi 				       : e1000_rev_polarity_normal);
226575eba5b6SRobert Mustacchi 
226675eba5b6SRobert Mustacchi 	return ret_val;
226775eba5b6SRobert Mustacchi }
226875eba5b6SRobert Mustacchi 
226975eba5b6SRobert Mustacchi /**
227075eba5b6SRobert Mustacchi  *  e1000_check_polarity_ife - Check cable polarity for IFE PHY
227175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
227275eba5b6SRobert Mustacchi  *
227375eba5b6SRobert Mustacchi  *  Polarity is determined on the polarity reversal feature being enabled.
227475eba5b6SRobert Mustacchi  **/
227575eba5b6SRobert Mustacchi s32 e1000_check_polarity_ife(struct e1000_hw *hw)
227675eba5b6SRobert Mustacchi {
227775eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
227875eba5b6SRobert Mustacchi 	s32 ret_val;
227975eba5b6SRobert Mustacchi 	u16 phy_data, offset, mask;
228075eba5b6SRobert Mustacchi 
228175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_polarity_ife");
228275eba5b6SRobert Mustacchi 
228375eba5b6SRobert Mustacchi 	/* Polarity is determined based on the reversal feature being enabled.
228475eba5b6SRobert Mustacchi 	 */
228575eba5b6SRobert Mustacchi 	if (phy->polarity_correction) {
228675eba5b6SRobert Mustacchi 		offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
228775eba5b6SRobert Mustacchi 		mask = IFE_PESC_POLARITY_REVERSED;
228875eba5b6SRobert Mustacchi 	} else {
228975eba5b6SRobert Mustacchi 		offset = IFE_PHY_SPECIAL_CONTROL;
229075eba5b6SRobert Mustacchi 		mask = IFE_PSC_FORCE_POLARITY;
229175eba5b6SRobert Mustacchi 	}
229275eba5b6SRobert Mustacchi 
229375eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, offset, &phy_data);
229475eba5b6SRobert Mustacchi 
229575eba5b6SRobert Mustacchi 	if (!ret_val)
2296c124a83eSRobert Mustacchi 		phy->cable_polarity = ((phy_data & mask)
229775eba5b6SRobert Mustacchi 				       ? e1000_rev_polarity_reversed
2298c124a83eSRobert Mustacchi 				       : e1000_rev_polarity_normal);
229975eba5b6SRobert Mustacchi 
230075eba5b6SRobert Mustacchi 	return ret_val;
230175eba5b6SRobert Mustacchi }
230275eba5b6SRobert Mustacchi 
230375eba5b6SRobert Mustacchi /**
230475eba5b6SRobert Mustacchi  *  e1000_wait_autoneg - Wait for auto-neg completion
230575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
230675eba5b6SRobert Mustacchi  *
230775eba5b6SRobert Mustacchi  *  Waits for auto-negotiation to complete or for the auto-negotiation time
230875eba5b6SRobert Mustacchi  *  limit to expire, which ever happens first.
230975eba5b6SRobert Mustacchi  **/
231075eba5b6SRobert Mustacchi static s32 e1000_wait_autoneg(struct e1000_hw *hw)
231175eba5b6SRobert Mustacchi {
231275eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
231375eba5b6SRobert Mustacchi 	u16 i, phy_status;
231475eba5b6SRobert Mustacchi 
231575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_wait_autoneg");
231675eba5b6SRobert Mustacchi 
231775eba5b6SRobert Mustacchi 	if (!hw->phy.ops.read_reg)
231875eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
231975eba5b6SRobert Mustacchi 
232075eba5b6SRobert Mustacchi 	/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
232175eba5b6SRobert Mustacchi 	for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
232275eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
232375eba5b6SRobert Mustacchi 		if (ret_val)
232475eba5b6SRobert Mustacchi 			break;
232575eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
232675eba5b6SRobert Mustacchi 		if (ret_val)
232775eba5b6SRobert Mustacchi 			break;
232875eba5b6SRobert Mustacchi 		if (phy_status & MII_SR_AUTONEG_COMPLETE)
232975eba5b6SRobert Mustacchi 			break;
233075eba5b6SRobert Mustacchi 		msec_delay(100);
233175eba5b6SRobert Mustacchi 	}
233275eba5b6SRobert Mustacchi 
233375eba5b6SRobert Mustacchi 	/* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
233475eba5b6SRobert Mustacchi 	 * has completed.
233575eba5b6SRobert Mustacchi 	 */
233675eba5b6SRobert Mustacchi 	return ret_val;
233775eba5b6SRobert Mustacchi }
233875eba5b6SRobert Mustacchi 
233975eba5b6SRobert Mustacchi /**
234075eba5b6SRobert Mustacchi  *  e1000_phy_has_link_generic - Polls PHY for link
234175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
234275eba5b6SRobert Mustacchi  *  @iterations: number of times to poll for link
234375eba5b6SRobert Mustacchi  *  @usec_interval: delay between polling attempts
234475eba5b6SRobert Mustacchi  *  @success: pointer to whether polling was successful or not
234575eba5b6SRobert Mustacchi  *
234675eba5b6SRobert Mustacchi  *  Polls the PHY status register for link, 'iterations' number of times.
234775eba5b6SRobert Mustacchi  **/
234875eba5b6SRobert Mustacchi s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
234975eba5b6SRobert Mustacchi 			       u32 usec_interval, bool *success)
235075eba5b6SRobert Mustacchi {
235175eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
235275eba5b6SRobert Mustacchi 	u16 i, phy_status;
235375eba5b6SRobert Mustacchi 
235475eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_has_link_generic");
235575eba5b6SRobert Mustacchi 
235675eba5b6SRobert Mustacchi 	if (!hw->phy.ops.read_reg)
235775eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
235875eba5b6SRobert Mustacchi 
235975eba5b6SRobert Mustacchi 	for (i = 0; i < iterations; i++) {
236075eba5b6SRobert Mustacchi 		/* Some PHYs require the PHY_STATUS register to be read
236175eba5b6SRobert Mustacchi 		 * twice due to the link bit being sticky.  No harm doing
236275eba5b6SRobert Mustacchi 		 * it across the board.
236375eba5b6SRobert Mustacchi 		 */
236475eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
2365c124a83eSRobert Mustacchi 		if (ret_val) {
236675eba5b6SRobert Mustacchi 			/* If the first read fails, another entity may have
236775eba5b6SRobert Mustacchi 			 * ownership of the resources, wait and try again to
236875eba5b6SRobert Mustacchi 			 * see if they have relinquished the resources yet.
236975eba5b6SRobert Mustacchi 			 */
2370c124a83eSRobert Mustacchi 			if (usec_interval >= 1000)
2371c124a83eSRobert Mustacchi 				msec_delay(usec_interval/1000);
2372c124a83eSRobert Mustacchi 			else
237375eba5b6SRobert Mustacchi 				usec_delay(usec_interval);
2374c124a83eSRobert Mustacchi 		}
237575eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
237675eba5b6SRobert Mustacchi 		if (ret_val)
237775eba5b6SRobert Mustacchi 			break;
237875eba5b6SRobert Mustacchi 		if (phy_status & MII_SR_LINK_STATUS)
237975eba5b6SRobert Mustacchi 			break;
238075eba5b6SRobert Mustacchi 		if (usec_interval >= 1000)
2381c124a83eSRobert Mustacchi 			msec_delay(usec_interval/1000);
238275eba5b6SRobert Mustacchi 		else
238375eba5b6SRobert Mustacchi 			usec_delay(usec_interval);
238475eba5b6SRobert Mustacchi 	}
238575eba5b6SRobert Mustacchi 
238675eba5b6SRobert Mustacchi 	*success = (i < iterations);
238775eba5b6SRobert Mustacchi 
238875eba5b6SRobert Mustacchi 	return ret_val;
238975eba5b6SRobert Mustacchi }
239075eba5b6SRobert Mustacchi 
239175eba5b6SRobert Mustacchi /**
239275eba5b6SRobert Mustacchi  *  e1000_get_cable_length_m88 - Determine cable length for m88 PHY
239375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
239475eba5b6SRobert Mustacchi  *
239575eba5b6SRobert Mustacchi  *  Reads the PHY specific status register to retrieve the cable length
239675eba5b6SRobert Mustacchi  *  information.  The cable length is determined by averaging the minimum and
239775eba5b6SRobert Mustacchi  *  maximum values to get the "average" cable length.  The m88 PHY has four
239875eba5b6SRobert Mustacchi  *  possible cable length values, which are:
239975eba5b6SRobert Mustacchi  *	Register Value		Cable Length
240075eba5b6SRobert Mustacchi  *	0			< 50 meters
240175eba5b6SRobert Mustacchi  *	1			50 - 80 meters
240275eba5b6SRobert Mustacchi  *	2			80 - 110 meters
240375eba5b6SRobert Mustacchi  *	3			110 - 140 meters
240475eba5b6SRobert Mustacchi  *	4			> 140 meters
240575eba5b6SRobert Mustacchi  **/
240675eba5b6SRobert Mustacchi s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
240775eba5b6SRobert Mustacchi {
240875eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
240975eba5b6SRobert Mustacchi 	s32 ret_val;
241075eba5b6SRobert Mustacchi 	u16 phy_data, index;
241175eba5b6SRobert Mustacchi 
241275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cable_length_m88");
241375eba5b6SRobert Mustacchi 
241475eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
241575eba5b6SRobert Mustacchi 	if (ret_val)
241675eba5b6SRobert Mustacchi 		return ret_val;
241775eba5b6SRobert Mustacchi 
2418c124a83eSRobert Mustacchi 	index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
2419c124a83eSRobert Mustacchi 		 M88E1000_PSSR_CABLE_LENGTH_SHIFT);
242075eba5b6SRobert Mustacchi 
242175eba5b6SRobert Mustacchi 	if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
242275eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
242375eba5b6SRobert Mustacchi 
242475eba5b6SRobert Mustacchi 	phy->min_cable_length = e1000_m88_cable_length_table[index];
242575eba5b6SRobert Mustacchi 	phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
242675eba5b6SRobert Mustacchi 
242775eba5b6SRobert Mustacchi 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
242875eba5b6SRobert Mustacchi 
242975eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
243075eba5b6SRobert Mustacchi }
243175eba5b6SRobert Mustacchi 
243275eba5b6SRobert Mustacchi s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
243375eba5b6SRobert Mustacchi {
243475eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
243575eba5b6SRobert Mustacchi 	s32 ret_val;
243675eba5b6SRobert Mustacchi 	u16 phy_data, phy_data2, is_cm;
243775eba5b6SRobert Mustacchi 	u16 index, default_page;
243875eba5b6SRobert Mustacchi 
243975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cable_length_m88_gen2");
244075eba5b6SRobert Mustacchi 
244175eba5b6SRobert Mustacchi 	switch (hw->phy.id) {
244275eba5b6SRobert Mustacchi 	case I210_I_PHY_ID:
244375eba5b6SRobert Mustacchi 		/* Get cable length from PHY Cable Diagnostics Control Reg */
244475eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
244575eba5b6SRobert Mustacchi 					    (I347AT4_PCDL + phy->addr),
244675eba5b6SRobert Mustacchi 					    &phy_data);
244775eba5b6SRobert Mustacchi 		if (ret_val)
244875eba5b6SRobert Mustacchi 			return ret_val;
244975eba5b6SRobert Mustacchi 
245075eba5b6SRobert Mustacchi 		/* Check if the unit of cable length is meters or cm */
245175eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
245275eba5b6SRobert Mustacchi 					    I347AT4_PCDC, &phy_data2);
245375eba5b6SRobert Mustacchi 		if (ret_val)
245475eba5b6SRobert Mustacchi 			return ret_val;
245575eba5b6SRobert Mustacchi 
245675eba5b6SRobert Mustacchi 		is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
245775eba5b6SRobert Mustacchi 
245875eba5b6SRobert Mustacchi 		/* Populate the phy structure with cable length in meters */
245975eba5b6SRobert Mustacchi 		phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
246075eba5b6SRobert Mustacchi 		phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
246175eba5b6SRobert Mustacchi 		phy->cable_length = phy_data / (is_cm ? 100 : 1);
246275eba5b6SRobert Mustacchi 		break;
2463c124a83eSRobert Mustacchi 	case M88E1543_E_PHY_ID:
2464c124a83eSRobert Mustacchi 	case M88E1512_E_PHY_ID:
246575eba5b6SRobert Mustacchi 	case M88E1340M_E_PHY_ID:
246675eba5b6SRobert Mustacchi 	case I347AT4_E_PHY_ID:
246775eba5b6SRobert Mustacchi 		/* Remember the original page select and set it to 7 */
246875eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
246975eba5b6SRobert Mustacchi 					    &default_page);
247075eba5b6SRobert Mustacchi 		if (ret_val)
247175eba5b6SRobert Mustacchi 			return ret_val;
247275eba5b6SRobert Mustacchi 
247375eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
247475eba5b6SRobert Mustacchi 		if (ret_val)
247575eba5b6SRobert Mustacchi 			return ret_val;
247675eba5b6SRobert Mustacchi 
247775eba5b6SRobert Mustacchi 		/* Get cable length from PHY Cable Diagnostics Control Reg */
247875eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
247975eba5b6SRobert Mustacchi 					    &phy_data);
248075eba5b6SRobert Mustacchi 		if (ret_val)
248175eba5b6SRobert Mustacchi 			return ret_val;
248275eba5b6SRobert Mustacchi 
248375eba5b6SRobert Mustacchi 		/* Check if the unit of cable length is meters or cm */
248475eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
248575eba5b6SRobert Mustacchi 		if (ret_val)
248675eba5b6SRobert Mustacchi 			return ret_val;
248775eba5b6SRobert Mustacchi 
248875eba5b6SRobert Mustacchi 		is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
248975eba5b6SRobert Mustacchi 
249075eba5b6SRobert Mustacchi 		/* Populate the phy structure with cable length in meters */
249175eba5b6SRobert Mustacchi 		phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
249275eba5b6SRobert Mustacchi 		phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
249375eba5b6SRobert Mustacchi 		phy->cable_length = phy_data / (is_cm ? 100 : 1);
249475eba5b6SRobert Mustacchi 
249575eba5b6SRobert Mustacchi 		/* Reset the page select to its original value */
249675eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
249775eba5b6SRobert Mustacchi 					     default_page);
249875eba5b6SRobert Mustacchi 		if (ret_val)
249975eba5b6SRobert Mustacchi 			return ret_val;
250075eba5b6SRobert Mustacchi 		break;
250175eba5b6SRobert Mustacchi 
250275eba5b6SRobert Mustacchi 	case M88E1112_E_PHY_ID:
250375eba5b6SRobert Mustacchi 		/* Remember the original page select and set it to 5 */
250475eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
250575eba5b6SRobert Mustacchi 					    &default_page);
250675eba5b6SRobert Mustacchi 		if (ret_val)
250775eba5b6SRobert Mustacchi 			return ret_val;
250875eba5b6SRobert Mustacchi 
250975eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
251075eba5b6SRobert Mustacchi 		if (ret_val)
251175eba5b6SRobert Mustacchi 			return ret_val;
251275eba5b6SRobert Mustacchi 
251375eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
251475eba5b6SRobert Mustacchi 					    &phy_data);
251575eba5b6SRobert Mustacchi 		if (ret_val)
251675eba5b6SRobert Mustacchi 			return ret_val;
251775eba5b6SRobert Mustacchi 
251875eba5b6SRobert Mustacchi 		index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
251975eba5b6SRobert Mustacchi 			M88E1000_PSSR_CABLE_LENGTH_SHIFT;
252075eba5b6SRobert Mustacchi 
252175eba5b6SRobert Mustacchi 		if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
252275eba5b6SRobert Mustacchi 			return -E1000_ERR_PHY;
252375eba5b6SRobert Mustacchi 
252475eba5b6SRobert Mustacchi 		phy->min_cable_length = e1000_m88_cable_length_table[index];
252575eba5b6SRobert Mustacchi 		phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
252675eba5b6SRobert Mustacchi 
252775eba5b6SRobert Mustacchi 		phy->cable_length = (phy->min_cable_length +
252875eba5b6SRobert Mustacchi 				     phy->max_cable_length) / 2;
252975eba5b6SRobert Mustacchi 
253075eba5b6SRobert Mustacchi 		/* Reset the page select to its original value */
253175eba5b6SRobert Mustacchi 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
253275eba5b6SRobert Mustacchi 					     default_page);
253375eba5b6SRobert Mustacchi 		if (ret_val)
253475eba5b6SRobert Mustacchi 			return ret_val;
253575eba5b6SRobert Mustacchi 
253675eba5b6SRobert Mustacchi 		break;
253775eba5b6SRobert Mustacchi 	default:
253875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
253975eba5b6SRobert Mustacchi 	}
254075eba5b6SRobert Mustacchi 
254175eba5b6SRobert Mustacchi 	return ret_val;
254275eba5b6SRobert Mustacchi }
254375eba5b6SRobert Mustacchi 
254475eba5b6SRobert Mustacchi /**
254575eba5b6SRobert Mustacchi  *  e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY
254675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
254775eba5b6SRobert Mustacchi  *
254875eba5b6SRobert Mustacchi  *  The automatic gain control (agc) normalizes the amplitude of the
254975eba5b6SRobert Mustacchi  *  received signal, adjusting for the attenuation produced by the
255075eba5b6SRobert Mustacchi  *  cable.  By reading the AGC registers, which represent the
255175eba5b6SRobert Mustacchi  *  combination of coarse and fine gain value, the value can be put
255275eba5b6SRobert Mustacchi  *  into a lookup table to obtain the approximate cable length
255375eba5b6SRobert Mustacchi  *  for each channel.
255475eba5b6SRobert Mustacchi  **/
255575eba5b6SRobert Mustacchi s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
255675eba5b6SRobert Mustacchi {
255775eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
255875eba5b6SRobert Mustacchi 	s32 ret_val;
255975eba5b6SRobert Mustacchi 	u16 phy_data, i, agc_value = 0;
256075eba5b6SRobert Mustacchi 	u16 cur_agc_index, max_agc_index = 0;
256175eba5b6SRobert Mustacchi 	u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
256275eba5b6SRobert Mustacchi 	static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
256375eba5b6SRobert Mustacchi 		IGP02E1000_PHY_AGC_A,
256475eba5b6SRobert Mustacchi 		IGP02E1000_PHY_AGC_B,
256575eba5b6SRobert Mustacchi 		IGP02E1000_PHY_AGC_C,
256675eba5b6SRobert Mustacchi 		IGP02E1000_PHY_AGC_D
256775eba5b6SRobert Mustacchi 	};
256875eba5b6SRobert Mustacchi 
256975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cable_length_igp_2");
257075eba5b6SRobert Mustacchi 
257175eba5b6SRobert Mustacchi 	/* Read the AGC registers for all channels */
257275eba5b6SRobert Mustacchi 	for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
257375eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data);
257475eba5b6SRobert Mustacchi 		if (ret_val)
257575eba5b6SRobert Mustacchi 			return ret_val;
257675eba5b6SRobert Mustacchi 
257775eba5b6SRobert Mustacchi 		/* Getting bits 15:9, which represent the combination of
257875eba5b6SRobert Mustacchi 		 * coarse and fine gain values.  The result is a number
257975eba5b6SRobert Mustacchi 		 * that can be put into the lookup table to obtain the
258075eba5b6SRobert Mustacchi 		 * approximate cable length.
258175eba5b6SRobert Mustacchi 		 */
2582c124a83eSRobert Mustacchi 		cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
2583c124a83eSRobert Mustacchi 				 IGP02E1000_AGC_LENGTH_MASK);
258475eba5b6SRobert Mustacchi 
258575eba5b6SRobert Mustacchi 		/* Array index bound check. */
258675eba5b6SRobert Mustacchi 		if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
258775eba5b6SRobert Mustacchi 		    (cur_agc_index == 0))
258875eba5b6SRobert Mustacchi 			return -E1000_ERR_PHY;
258975eba5b6SRobert Mustacchi 
259075eba5b6SRobert Mustacchi 		/* Remove min & max AGC values from calculation. */
259175eba5b6SRobert Mustacchi 		if (e1000_igp_2_cable_length_table[min_agc_index] >
259275eba5b6SRobert Mustacchi 		    e1000_igp_2_cable_length_table[cur_agc_index])
259375eba5b6SRobert Mustacchi 			min_agc_index = cur_agc_index;
259475eba5b6SRobert Mustacchi 		if (e1000_igp_2_cable_length_table[max_agc_index] <
259575eba5b6SRobert Mustacchi 		    e1000_igp_2_cable_length_table[cur_agc_index])
259675eba5b6SRobert Mustacchi 			max_agc_index = cur_agc_index;
259775eba5b6SRobert Mustacchi 
259875eba5b6SRobert Mustacchi 		agc_value += e1000_igp_2_cable_length_table[cur_agc_index];
259975eba5b6SRobert Mustacchi 	}
260075eba5b6SRobert Mustacchi 
260175eba5b6SRobert Mustacchi 	agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] +
260275eba5b6SRobert Mustacchi 		      e1000_igp_2_cable_length_table[max_agc_index]);
260375eba5b6SRobert Mustacchi 	agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
260475eba5b6SRobert Mustacchi 
260575eba5b6SRobert Mustacchi 	/* Calculate cable length with the error range of +/- 10 meters. */
2606c124a83eSRobert Mustacchi 	phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
2607c124a83eSRobert Mustacchi 				 (agc_value - IGP02E1000_AGC_RANGE) : 0);
260875eba5b6SRobert Mustacchi 	phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
260975eba5b6SRobert Mustacchi 
261075eba5b6SRobert Mustacchi 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
261175eba5b6SRobert Mustacchi 
261275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
261375eba5b6SRobert Mustacchi }
261475eba5b6SRobert Mustacchi 
261575eba5b6SRobert Mustacchi /**
261675eba5b6SRobert Mustacchi  *  e1000_get_phy_info_m88 - Retrieve PHY information
261775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
261875eba5b6SRobert Mustacchi  *
261975eba5b6SRobert Mustacchi  *  Valid for only copper links.  Read the PHY status register (sticky read)
262075eba5b6SRobert Mustacchi  *  to verify that link is up.  Read the PHY special control register to
262175eba5b6SRobert Mustacchi  *  determine the polarity and 10base-T extended distance.  Read the PHY
262275eba5b6SRobert Mustacchi  *  special status register to determine MDI/MDIx and current speed.  If
262375eba5b6SRobert Mustacchi  *  speed is 1000, then determine cable length, local and remote receiver.
262475eba5b6SRobert Mustacchi  **/
262575eba5b6SRobert Mustacchi s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
262675eba5b6SRobert Mustacchi {
262775eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
262875eba5b6SRobert Mustacchi 	s32  ret_val;
262975eba5b6SRobert Mustacchi 	u16 phy_data;
263075eba5b6SRobert Mustacchi 	bool link;
263175eba5b6SRobert Mustacchi 
263275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_phy_info_m88");
263375eba5b6SRobert Mustacchi 
263475eba5b6SRobert Mustacchi 	if (phy->media_type != e1000_media_type_copper) {
263575eba5b6SRobert Mustacchi 		DEBUGOUT("Phy info is only valid for copper media\n");
263675eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
263775eba5b6SRobert Mustacchi 	}
263875eba5b6SRobert Mustacchi 
263975eba5b6SRobert Mustacchi 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
264075eba5b6SRobert Mustacchi 	if (ret_val)
264175eba5b6SRobert Mustacchi 		return ret_val;
264275eba5b6SRobert Mustacchi 
264375eba5b6SRobert Mustacchi 	if (!link) {
264475eba5b6SRobert Mustacchi 		DEBUGOUT("Phy info is only valid if link is up\n");
264575eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
264675eba5b6SRobert Mustacchi 	}
264775eba5b6SRobert Mustacchi 
264875eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
264975eba5b6SRobert Mustacchi 	if (ret_val)
265075eba5b6SRobert Mustacchi 		return ret_val;
265175eba5b6SRobert Mustacchi 
265275eba5b6SRobert Mustacchi 	phy->polarity_correction = !!(phy_data &
265375eba5b6SRobert Mustacchi 				      M88E1000_PSCR_POLARITY_REVERSAL);
265475eba5b6SRobert Mustacchi 
265575eba5b6SRobert Mustacchi 	ret_val = e1000_check_polarity_m88(hw);
265675eba5b6SRobert Mustacchi 	if (ret_val)
265775eba5b6SRobert Mustacchi 		return ret_val;
265875eba5b6SRobert Mustacchi 
265975eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
266075eba5b6SRobert Mustacchi 	if (ret_val)
266175eba5b6SRobert Mustacchi 		return ret_val;
266275eba5b6SRobert Mustacchi 
266375eba5b6SRobert Mustacchi 	phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX);
266475eba5b6SRobert Mustacchi 
266575eba5b6SRobert Mustacchi 	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
266675eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.get_cable_length(hw);
266775eba5b6SRobert Mustacchi 		if (ret_val)
266875eba5b6SRobert Mustacchi 			return ret_val;
266975eba5b6SRobert Mustacchi 
267075eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
267175eba5b6SRobert Mustacchi 		if (ret_val)
267275eba5b6SRobert Mustacchi 			return ret_val;
267375eba5b6SRobert Mustacchi 
267475eba5b6SRobert Mustacchi 		phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
267575eba5b6SRobert Mustacchi 				? e1000_1000t_rx_status_ok
267675eba5b6SRobert Mustacchi 				: e1000_1000t_rx_status_not_ok;
267775eba5b6SRobert Mustacchi 
267875eba5b6SRobert Mustacchi 		phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS)
267975eba5b6SRobert Mustacchi 				 ? e1000_1000t_rx_status_ok
268075eba5b6SRobert Mustacchi 				 : e1000_1000t_rx_status_not_ok;
268175eba5b6SRobert Mustacchi 	} else {
268275eba5b6SRobert Mustacchi 		/* Set values to "undefined" */
268375eba5b6SRobert Mustacchi 		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
268475eba5b6SRobert Mustacchi 		phy->local_rx = e1000_1000t_rx_status_undefined;
268575eba5b6SRobert Mustacchi 		phy->remote_rx = e1000_1000t_rx_status_undefined;
268675eba5b6SRobert Mustacchi 	}
268775eba5b6SRobert Mustacchi 
268875eba5b6SRobert Mustacchi 	return ret_val;
268975eba5b6SRobert Mustacchi }
269075eba5b6SRobert Mustacchi 
269175eba5b6SRobert Mustacchi /**
269275eba5b6SRobert Mustacchi  *  e1000_get_phy_info_igp - Retrieve igp PHY information
269375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
269475eba5b6SRobert Mustacchi  *
269575eba5b6SRobert Mustacchi  *  Read PHY status to determine if link is up.  If link is up, then
269675eba5b6SRobert Mustacchi  *  set/determine 10base-T extended distance and polarity correction.  Read
269775eba5b6SRobert Mustacchi  *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
269875eba5b6SRobert Mustacchi  *  determine on the cable length, local and remote receiver.
269975eba5b6SRobert Mustacchi  **/
270075eba5b6SRobert Mustacchi s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
270175eba5b6SRobert Mustacchi {
270275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
270375eba5b6SRobert Mustacchi 	s32 ret_val;
270475eba5b6SRobert Mustacchi 	u16 data;
270575eba5b6SRobert Mustacchi 	bool link;
270675eba5b6SRobert Mustacchi 
270775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_phy_info_igp");
270875eba5b6SRobert Mustacchi 
270975eba5b6SRobert Mustacchi 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
271075eba5b6SRobert Mustacchi 	if (ret_val)
271175eba5b6SRobert Mustacchi 		return ret_val;
271275eba5b6SRobert Mustacchi 
271375eba5b6SRobert Mustacchi 	if (!link) {
271475eba5b6SRobert Mustacchi 		DEBUGOUT("Phy info is only valid if link is up\n");
271575eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
271675eba5b6SRobert Mustacchi 	}
271775eba5b6SRobert Mustacchi 
271875eba5b6SRobert Mustacchi 	phy->polarity_correction = TRUE;
271975eba5b6SRobert Mustacchi 
272075eba5b6SRobert Mustacchi 	ret_val = e1000_check_polarity_igp(hw);
272175eba5b6SRobert Mustacchi 	if (ret_val)
272275eba5b6SRobert Mustacchi 		return ret_val;
272375eba5b6SRobert Mustacchi 
272475eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
272575eba5b6SRobert Mustacchi 	if (ret_val)
272675eba5b6SRobert Mustacchi 		return ret_val;
272775eba5b6SRobert Mustacchi 
272875eba5b6SRobert Mustacchi 	phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX);
272975eba5b6SRobert Mustacchi 
273075eba5b6SRobert Mustacchi 	if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
273175eba5b6SRobert Mustacchi 	    IGP01E1000_PSSR_SPEED_1000MBPS) {
273275eba5b6SRobert Mustacchi 		ret_val = phy->ops.get_cable_length(hw);
273375eba5b6SRobert Mustacchi 		if (ret_val)
273475eba5b6SRobert Mustacchi 			return ret_val;
273575eba5b6SRobert Mustacchi 
273675eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
273775eba5b6SRobert Mustacchi 		if (ret_val)
273875eba5b6SRobert Mustacchi 			return ret_val;
273975eba5b6SRobert Mustacchi 
274075eba5b6SRobert Mustacchi 		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
274175eba5b6SRobert Mustacchi 				? e1000_1000t_rx_status_ok
274275eba5b6SRobert Mustacchi 				: e1000_1000t_rx_status_not_ok;
274375eba5b6SRobert Mustacchi 
274475eba5b6SRobert Mustacchi 		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
274575eba5b6SRobert Mustacchi 				 ? e1000_1000t_rx_status_ok
274675eba5b6SRobert Mustacchi 				 : e1000_1000t_rx_status_not_ok;
274775eba5b6SRobert Mustacchi 	} else {
274875eba5b6SRobert Mustacchi 		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
274975eba5b6SRobert Mustacchi 		phy->local_rx = e1000_1000t_rx_status_undefined;
275075eba5b6SRobert Mustacchi 		phy->remote_rx = e1000_1000t_rx_status_undefined;
275175eba5b6SRobert Mustacchi 	}
275275eba5b6SRobert Mustacchi 
275375eba5b6SRobert Mustacchi 	return ret_val;
275475eba5b6SRobert Mustacchi }
275575eba5b6SRobert Mustacchi 
275675eba5b6SRobert Mustacchi /**
275775eba5b6SRobert Mustacchi  *  e1000_get_phy_info_ife - Retrieves various IFE PHY states
275875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
275975eba5b6SRobert Mustacchi  *
276075eba5b6SRobert Mustacchi  *  Populates "phy" structure with various feature states.
276175eba5b6SRobert Mustacchi  **/
276275eba5b6SRobert Mustacchi s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
276375eba5b6SRobert Mustacchi {
276475eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
276575eba5b6SRobert Mustacchi 	s32 ret_val;
276675eba5b6SRobert Mustacchi 	u16 data;
276775eba5b6SRobert Mustacchi 	bool link;
276875eba5b6SRobert Mustacchi 
276975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_phy_info_ife");
277075eba5b6SRobert Mustacchi 
277175eba5b6SRobert Mustacchi 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
277275eba5b6SRobert Mustacchi 	if (ret_val)
277375eba5b6SRobert Mustacchi 		return ret_val;
277475eba5b6SRobert Mustacchi 
277575eba5b6SRobert Mustacchi 	if (!link) {
277675eba5b6SRobert Mustacchi 		DEBUGOUT("Phy info is only valid if link is up\n");
277775eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
277875eba5b6SRobert Mustacchi 	}
277975eba5b6SRobert Mustacchi 
278075eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
278175eba5b6SRobert Mustacchi 	if (ret_val)
278275eba5b6SRobert Mustacchi 		return ret_val;
278375eba5b6SRobert Mustacchi 	phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE);
278475eba5b6SRobert Mustacchi 
278575eba5b6SRobert Mustacchi 	if (phy->polarity_correction) {
278675eba5b6SRobert Mustacchi 		ret_val = e1000_check_polarity_ife(hw);
278775eba5b6SRobert Mustacchi 		if (ret_val)
278875eba5b6SRobert Mustacchi 			return ret_val;
278975eba5b6SRobert Mustacchi 	} else {
279075eba5b6SRobert Mustacchi 		/* Polarity is forced */
2791c124a83eSRobert Mustacchi 		phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY)
279275eba5b6SRobert Mustacchi 				       ? e1000_rev_polarity_reversed
2793c124a83eSRobert Mustacchi 				       : e1000_rev_polarity_normal);
279475eba5b6SRobert Mustacchi 	}
279575eba5b6SRobert Mustacchi 
279675eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
279775eba5b6SRobert Mustacchi 	if (ret_val)
279875eba5b6SRobert Mustacchi 		return ret_val;
279975eba5b6SRobert Mustacchi 
280075eba5b6SRobert Mustacchi 	phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS);
280175eba5b6SRobert Mustacchi 
280275eba5b6SRobert Mustacchi 	/* The following parameters are undefined for 10/100 operation. */
280375eba5b6SRobert Mustacchi 	phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
280475eba5b6SRobert Mustacchi 	phy->local_rx = e1000_1000t_rx_status_undefined;
280575eba5b6SRobert Mustacchi 	phy->remote_rx = e1000_1000t_rx_status_undefined;
280675eba5b6SRobert Mustacchi 
280775eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
280875eba5b6SRobert Mustacchi }
280975eba5b6SRobert Mustacchi 
281075eba5b6SRobert Mustacchi /**
281175eba5b6SRobert Mustacchi  *  e1000_phy_sw_reset_generic - PHY software reset
281275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
281375eba5b6SRobert Mustacchi  *
281475eba5b6SRobert Mustacchi  *  Does a software reset of the PHY by reading the PHY control register and
281575eba5b6SRobert Mustacchi  *  setting/write the control register reset bit to the PHY.
281675eba5b6SRobert Mustacchi  **/
281775eba5b6SRobert Mustacchi s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw)
281875eba5b6SRobert Mustacchi {
281975eba5b6SRobert Mustacchi 	s32 ret_val;
282075eba5b6SRobert Mustacchi 	u16 phy_ctrl;
282175eba5b6SRobert Mustacchi 
282275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_sw_reset_generic");
282375eba5b6SRobert Mustacchi 
282475eba5b6SRobert Mustacchi 	if (!hw->phy.ops.read_reg)
282575eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
282675eba5b6SRobert Mustacchi 
282775eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
282875eba5b6SRobert Mustacchi 	if (ret_val)
282975eba5b6SRobert Mustacchi 		return ret_val;
283075eba5b6SRobert Mustacchi 
283175eba5b6SRobert Mustacchi 	phy_ctrl |= MII_CR_RESET;
283275eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
283375eba5b6SRobert Mustacchi 	if (ret_val)
283475eba5b6SRobert Mustacchi 		return ret_val;
283575eba5b6SRobert Mustacchi 
283675eba5b6SRobert Mustacchi 	usec_delay(1);
283775eba5b6SRobert Mustacchi 
283875eba5b6SRobert Mustacchi 	return ret_val;
283975eba5b6SRobert Mustacchi }
284075eba5b6SRobert Mustacchi 
284175eba5b6SRobert Mustacchi /**
284275eba5b6SRobert Mustacchi  *  e1000_phy_hw_reset_generic - PHY hardware reset
284375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
284475eba5b6SRobert Mustacchi  *
284575eba5b6SRobert Mustacchi  *  Verify the reset block is not blocking us from resetting.  Acquire
284675eba5b6SRobert Mustacchi  *  semaphore (if necessary) and read/set/write the device control reset
284775eba5b6SRobert Mustacchi  *  bit in the PHY.  Wait the appropriate delay time for the device to
284875eba5b6SRobert Mustacchi  *  reset and release the semaphore (if necessary).
284975eba5b6SRobert Mustacchi  **/
285075eba5b6SRobert Mustacchi s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
285175eba5b6SRobert Mustacchi {
285275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
285375eba5b6SRobert Mustacchi 	s32 ret_val;
285475eba5b6SRobert Mustacchi 	u32 ctrl;
285575eba5b6SRobert Mustacchi 
285675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_hw_reset_generic");
285775eba5b6SRobert Mustacchi 
285875eba5b6SRobert Mustacchi 	if (phy->ops.check_reset_block) {
285975eba5b6SRobert Mustacchi 		ret_val = phy->ops.check_reset_block(hw);
286075eba5b6SRobert Mustacchi 		if (ret_val)
286175eba5b6SRobert Mustacchi 			return E1000_SUCCESS;
286275eba5b6SRobert Mustacchi 	}
286375eba5b6SRobert Mustacchi 
286475eba5b6SRobert Mustacchi 	ret_val = phy->ops.acquire(hw);
286575eba5b6SRobert Mustacchi 	if (ret_val)
286675eba5b6SRobert Mustacchi 		return ret_val;
286775eba5b6SRobert Mustacchi 
286875eba5b6SRobert Mustacchi 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
286975eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST);
287075eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
287175eba5b6SRobert Mustacchi 
287275eba5b6SRobert Mustacchi 	usec_delay(phy->reset_delay_us);
287375eba5b6SRobert Mustacchi 
287475eba5b6SRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
287575eba5b6SRobert Mustacchi 	E1000_WRITE_FLUSH(hw);
287675eba5b6SRobert Mustacchi 
287775eba5b6SRobert Mustacchi 	usec_delay(150);
287875eba5b6SRobert Mustacchi 
287975eba5b6SRobert Mustacchi 	phy->ops.release(hw);
288075eba5b6SRobert Mustacchi 
288175eba5b6SRobert Mustacchi 	return phy->ops.get_cfg_done(hw);
288275eba5b6SRobert Mustacchi }
288375eba5b6SRobert Mustacchi 
288475eba5b6SRobert Mustacchi /**
288575eba5b6SRobert Mustacchi  *  e1000_get_cfg_done_generic - Generic configuration done
288675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
288775eba5b6SRobert Mustacchi  *
288875eba5b6SRobert Mustacchi  *  Generic function to wait 10 milli-seconds for configuration to complete
288975eba5b6SRobert Mustacchi  *  and return success.
289075eba5b6SRobert Mustacchi  **/
2891c124a83eSRobert Mustacchi s32 e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG *hw)
289275eba5b6SRobert Mustacchi {
289375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cfg_done_generic");
289475eba5b6SRobert Mustacchi 
289575eba5b6SRobert Mustacchi 	msec_delay_irq(10);
289675eba5b6SRobert Mustacchi 
289775eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
289875eba5b6SRobert Mustacchi }
289975eba5b6SRobert Mustacchi 
290075eba5b6SRobert Mustacchi /**
290175eba5b6SRobert Mustacchi  *  e1000_phy_init_script_igp3 - Inits the IGP3 PHY
290275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
290375eba5b6SRobert Mustacchi  *
290475eba5b6SRobert Mustacchi  *  Initializes a Intel Gigabit PHY3 when an EEPROM is not present.
290575eba5b6SRobert Mustacchi  **/
290675eba5b6SRobert Mustacchi s32 e1000_phy_init_script_igp3(struct e1000_hw *hw)
290775eba5b6SRobert Mustacchi {
290875eba5b6SRobert Mustacchi 	DEBUGOUT("Running IGP 3 PHY init script\n");
290975eba5b6SRobert Mustacchi 
291075eba5b6SRobert Mustacchi 	/* PHY init IGP 3 */
291175eba5b6SRobert Mustacchi 	/* Enable rise/fall, 10-mode work in class-A */
291275eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018);
291375eba5b6SRobert Mustacchi 	/* Remove all caps from Replica path filter */
291475eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x2F52, 0x0000);
291575eba5b6SRobert Mustacchi 	/* Bias trimming for ADC, AFE and Driver (Default) */
291675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24);
291775eba5b6SRobert Mustacchi 	/* Increase Hybrid poly bias */
291875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0);
291975eba5b6SRobert Mustacchi 	/* Add 4% to Tx amplitude in Gig mode */
292075eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x2010, 0x10B0);
292175eba5b6SRobert Mustacchi 	/* Disable trimming (TTT) */
292275eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x2011, 0x0000);
292375eba5b6SRobert Mustacchi 	/* Poly DC correction to 94.6% + 2% for all channels */
292475eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x20DD, 0x249A);
292575eba5b6SRobert Mustacchi 	/* ABS DC correction to 95.9% */
292675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3);
292775eba5b6SRobert Mustacchi 	/* BG temp curve trim */
292875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE);
292975eba5b6SRobert Mustacchi 	/* Increasing ADC OPAMP stage 1 currents to max */
293075eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4);
293175eba5b6SRobert Mustacchi 	/* Force 1000 ( required for enabling PHY regs configuration) */
293275eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
293375eba5b6SRobert Mustacchi 	/* Set upd_freq to 6 */
293475eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F30, 0x1606);
293575eba5b6SRobert Mustacchi 	/* Disable NPDFE */
293675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F31, 0xB814);
293775eba5b6SRobert Mustacchi 	/* Disable adaptive fixed FFE (Default) */
293875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F35, 0x002A);
293975eba5b6SRobert Mustacchi 	/* Enable FFE hysteresis */
294075eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067);
294175eba5b6SRobert Mustacchi 	/* Fixed FFE for short cable lengths */
294275eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F54, 0x0065);
294375eba5b6SRobert Mustacchi 	/* Fixed FFE for medium cable lengths */
294475eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F55, 0x002A);
294575eba5b6SRobert Mustacchi 	/* Fixed FFE for long cable lengths */
294675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F56, 0x002A);
294775eba5b6SRobert Mustacchi 	/* Enable Adaptive Clip Threshold */
294875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0);
294975eba5b6SRobert Mustacchi 	/* AHT reset limit to 1 */
295075eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF);
295175eba5b6SRobert Mustacchi 	/* Set AHT master delay to 127 msec */
295275eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC);
295375eba5b6SRobert Mustacchi 	/* Set scan bits for AHT */
295475eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF);
295575eba5b6SRobert Mustacchi 	/* Set AHT Preset bits */
295675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1F79, 0x0210);
295775eba5b6SRobert Mustacchi 	/* Change integ_factor of channel A to 3 */
295875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1895, 0x0003);
295975eba5b6SRobert Mustacchi 	/* Change prop_factor of channels BCD to 8 */
296075eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1796, 0x0008);
296175eba5b6SRobert Mustacchi 	/* Change cg_icount + enable integbp for channels BCD */
296275eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1798, 0xD008);
296375eba5b6SRobert Mustacchi 	/* Change cg_icount + enable integbp + change prop_factor_master
296475eba5b6SRobert Mustacchi 	 * to 8 for channel A
296575eba5b6SRobert Mustacchi 	 */
296675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x1898, 0xD918);
296775eba5b6SRobert Mustacchi 	/* Disable AHT in Slave mode on channel A */
296875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x187A, 0x0800);
296975eba5b6SRobert Mustacchi 	/* Enable LPLU and disable AN to 1000 in non-D0a states,
297075eba5b6SRobert Mustacchi 	 * Enable SPD+B2B
297175eba5b6SRobert Mustacchi 	 */
297275eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x0019, 0x008D);
297375eba5b6SRobert Mustacchi 	/* Enable restart AN on an1000_dis change */
297475eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x001B, 0x2080);
297575eba5b6SRobert Mustacchi 	/* Enable wh_fifo read clock in 10/100 modes */
297675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x0014, 0x0045);
297775eba5b6SRobert Mustacchi 	/* Restart AN, Speed selection is 1000 */
297875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, 0x0000, 0x1340);
297975eba5b6SRobert Mustacchi 
298075eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
298175eba5b6SRobert Mustacchi }
298275eba5b6SRobert Mustacchi 
298375eba5b6SRobert Mustacchi /**
298475eba5b6SRobert Mustacchi  *  e1000_get_phy_type_from_id - Get PHY type from id
298575eba5b6SRobert Mustacchi  *  @phy_id: phy_id read from the phy
298675eba5b6SRobert Mustacchi  *
298775eba5b6SRobert Mustacchi  *  Returns the phy type from the id.
298875eba5b6SRobert Mustacchi  **/
298975eba5b6SRobert Mustacchi enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
299075eba5b6SRobert Mustacchi {
299175eba5b6SRobert Mustacchi 	enum e1000_phy_type phy_type = e1000_phy_unknown;
299275eba5b6SRobert Mustacchi 
299375eba5b6SRobert Mustacchi 	switch (phy_id) {
299475eba5b6SRobert Mustacchi 	case M88E1000_I_PHY_ID:
299575eba5b6SRobert Mustacchi 	case M88E1000_E_PHY_ID:
299675eba5b6SRobert Mustacchi 	case M88E1111_I_PHY_ID:
299775eba5b6SRobert Mustacchi 	case M88E1011_I_PHY_ID:
2998c124a83eSRobert Mustacchi 	case M88E1543_E_PHY_ID:
2999c124a83eSRobert Mustacchi 	case M88E1512_E_PHY_ID:
300075eba5b6SRobert Mustacchi 	case I347AT4_E_PHY_ID:
300175eba5b6SRobert Mustacchi 	case M88E1112_E_PHY_ID:
300275eba5b6SRobert Mustacchi 	case M88E1340M_E_PHY_ID:
300375eba5b6SRobert Mustacchi 		phy_type = e1000_phy_m88;
300475eba5b6SRobert Mustacchi 		break;
300575eba5b6SRobert Mustacchi 	case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
300675eba5b6SRobert Mustacchi 		phy_type = e1000_phy_igp_2;
300775eba5b6SRobert Mustacchi 		break;
300875eba5b6SRobert Mustacchi 	case GG82563_E_PHY_ID:
300975eba5b6SRobert Mustacchi 		phy_type = e1000_phy_gg82563;
301075eba5b6SRobert Mustacchi 		break;
301175eba5b6SRobert Mustacchi 	case IGP03E1000_E_PHY_ID:
301275eba5b6SRobert Mustacchi 		phy_type = e1000_phy_igp_3;
301375eba5b6SRobert Mustacchi 		break;
301475eba5b6SRobert Mustacchi 	case IFE_E_PHY_ID:
301575eba5b6SRobert Mustacchi 	case IFE_PLUS_E_PHY_ID:
301675eba5b6SRobert Mustacchi 	case IFE_C_E_PHY_ID:
301775eba5b6SRobert Mustacchi 		phy_type = e1000_phy_ife;
301875eba5b6SRobert Mustacchi 		break;
301975eba5b6SRobert Mustacchi 	case BME1000_E_PHY_ID:
302075eba5b6SRobert Mustacchi 	case BME1000_E_PHY_ID_R2:
302175eba5b6SRobert Mustacchi 		phy_type = e1000_phy_bm;
302275eba5b6SRobert Mustacchi 		break;
302375eba5b6SRobert Mustacchi 	case I82578_E_PHY_ID:
302475eba5b6SRobert Mustacchi 		phy_type = e1000_phy_82578;
302575eba5b6SRobert Mustacchi 		break;
302675eba5b6SRobert Mustacchi 	case I82577_E_PHY_ID:
302775eba5b6SRobert Mustacchi 		phy_type = e1000_phy_82577;
302875eba5b6SRobert Mustacchi 		break;
302975eba5b6SRobert Mustacchi 	case I82579_E_PHY_ID:
303075eba5b6SRobert Mustacchi 		phy_type = e1000_phy_82579;
303175eba5b6SRobert Mustacchi 		break;
303275eba5b6SRobert Mustacchi 	case I217_E_PHY_ID:
303375eba5b6SRobert Mustacchi 		phy_type = e1000_phy_i217;
303475eba5b6SRobert Mustacchi 		break;
303575eba5b6SRobert Mustacchi 	case I82580_I_PHY_ID:
303675eba5b6SRobert Mustacchi 		phy_type = e1000_phy_82580;
303775eba5b6SRobert Mustacchi 		break;
303875eba5b6SRobert Mustacchi 	case I210_I_PHY_ID:
303975eba5b6SRobert Mustacchi 		phy_type = e1000_phy_i210;
304075eba5b6SRobert Mustacchi 		break;
304175eba5b6SRobert Mustacchi 	default:
304275eba5b6SRobert Mustacchi 		phy_type = e1000_phy_unknown;
304375eba5b6SRobert Mustacchi 		break;
304475eba5b6SRobert Mustacchi 	}
304575eba5b6SRobert Mustacchi 	return phy_type;
304675eba5b6SRobert Mustacchi }
304775eba5b6SRobert Mustacchi 
304875eba5b6SRobert Mustacchi /**
304975eba5b6SRobert Mustacchi  *  e1000_determine_phy_address - Determines PHY address.
305075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
305175eba5b6SRobert Mustacchi  *
305275eba5b6SRobert Mustacchi  *  This uses a trial and error method to loop through possible PHY
305375eba5b6SRobert Mustacchi  *  addresses. It tests each by reading the PHY ID registers and
305475eba5b6SRobert Mustacchi  *  checking for a match.
305575eba5b6SRobert Mustacchi  **/
305675eba5b6SRobert Mustacchi s32 e1000_determine_phy_address(struct e1000_hw *hw)
305775eba5b6SRobert Mustacchi {
305875eba5b6SRobert Mustacchi 	u32 phy_addr = 0;
305975eba5b6SRobert Mustacchi 	u32 i;
306075eba5b6SRobert Mustacchi 	enum e1000_phy_type phy_type = e1000_phy_unknown;
306175eba5b6SRobert Mustacchi 
306275eba5b6SRobert Mustacchi 	hw->phy.id = phy_type;
306375eba5b6SRobert Mustacchi 
306475eba5b6SRobert Mustacchi 	for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) {
306575eba5b6SRobert Mustacchi 		hw->phy.addr = phy_addr;
306675eba5b6SRobert Mustacchi 		i = 0;
306775eba5b6SRobert Mustacchi 
306875eba5b6SRobert Mustacchi 		do {
306975eba5b6SRobert Mustacchi 			e1000_get_phy_id(hw);
307075eba5b6SRobert Mustacchi 			phy_type = e1000_get_phy_type_from_id(hw->phy.id);
307175eba5b6SRobert Mustacchi 
307275eba5b6SRobert Mustacchi 			/* If phy_type is valid, break - we found our
307375eba5b6SRobert Mustacchi 			 * PHY address
307475eba5b6SRobert Mustacchi 			 */
307575eba5b6SRobert Mustacchi 			if (phy_type != e1000_phy_unknown)
307675eba5b6SRobert Mustacchi 				return E1000_SUCCESS;
307775eba5b6SRobert Mustacchi 
307875eba5b6SRobert Mustacchi 			msec_delay(1);
307975eba5b6SRobert Mustacchi 			i++;
308075eba5b6SRobert Mustacchi 		} while (i < 10);
308175eba5b6SRobert Mustacchi 	}
308275eba5b6SRobert Mustacchi 
308375eba5b6SRobert Mustacchi 	return -E1000_ERR_PHY_TYPE;
308475eba5b6SRobert Mustacchi }
308575eba5b6SRobert Mustacchi 
308675eba5b6SRobert Mustacchi /**
308775eba5b6SRobert Mustacchi  *  e1000_get_phy_addr_for_bm_page - Retrieve PHY page address
308875eba5b6SRobert Mustacchi  *  @page: page to access
308975eba5b6SRobert Mustacchi  *
309075eba5b6SRobert Mustacchi  *  Returns the phy address for the page requested.
309175eba5b6SRobert Mustacchi  **/
309275eba5b6SRobert Mustacchi static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
309375eba5b6SRobert Mustacchi {
309475eba5b6SRobert Mustacchi 	u32 phy_addr = 2;
309575eba5b6SRobert Mustacchi 
309675eba5b6SRobert Mustacchi 	if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31))
309775eba5b6SRobert Mustacchi 		phy_addr = 1;
309875eba5b6SRobert Mustacchi 
309975eba5b6SRobert Mustacchi 	return phy_addr;
310075eba5b6SRobert Mustacchi }
310175eba5b6SRobert Mustacchi 
310275eba5b6SRobert Mustacchi /**
310375eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_bm - Write BM PHY register
310475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
310575eba5b6SRobert Mustacchi  *  @offset: register offset to write to
310675eba5b6SRobert Mustacchi  *  @data: data to write at register offset
310775eba5b6SRobert Mustacchi  *
310875eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then writes the data to PHY register
310975eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
311075eba5b6SRobert Mustacchi  **/
311175eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
311275eba5b6SRobert Mustacchi {
311375eba5b6SRobert Mustacchi 	s32 ret_val;
311475eba5b6SRobert Mustacchi 	u32 page = offset >> IGP_PAGE_SHIFT;
311575eba5b6SRobert Mustacchi 
311675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_bm");
311775eba5b6SRobert Mustacchi 
311875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
311975eba5b6SRobert Mustacchi 	if (ret_val)
312075eba5b6SRobert Mustacchi 		return ret_val;
312175eba5b6SRobert Mustacchi 
312275eba5b6SRobert Mustacchi 	/* Page 800 works differently than the rest so it has its own func */
312375eba5b6SRobert Mustacchi 	if (page == BM_WUC_PAGE) {
312475eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
3125*42cc51e0SRobert Mustacchi 							 FALSE, false);
312675eba5b6SRobert Mustacchi 		goto release;
312775eba5b6SRobert Mustacchi 	}
312875eba5b6SRobert Mustacchi 
312975eba5b6SRobert Mustacchi 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
313075eba5b6SRobert Mustacchi 
313175eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
313275eba5b6SRobert Mustacchi 		u32 page_shift, page_select;
313375eba5b6SRobert Mustacchi 
313475eba5b6SRobert Mustacchi 		/* Page select is register 31 for phy address 1 and 22 for
313575eba5b6SRobert Mustacchi 		 * phy address 2 and 3. Page select is shifted only for
313675eba5b6SRobert Mustacchi 		 * phy address 1.
313775eba5b6SRobert Mustacchi 		 */
313875eba5b6SRobert Mustacchi 		if (hw->phy.addr == 1) {
313975eba5b6SRobert Mustacchi 			page_shift = IGP_PAGE_SHIFT;
314075eba5b6SRobert Mustacchi 			page_select = IGP01E1000_PHY_PAGE_SELECT;
314175eba5b6SRobert Mustacchi 		} else {
314275eba5b6SRobert Mustacchi 			page_shift = 0;
314375eba5b6SRobert Mustacchi 			page_select = BM_PHY_PAGE_SELECT;
314475eba5b6SRobert Mustacchi 		}
314575eba5b6SRobert Mustacchi 
314675eba5b6SRobert Mustacchi 		/* Page is shifted left, PHY expects (page x 32) */
314775eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw, page_select,
314875eba5b6SRobert Mustacchi 						   (page << page_shift));
314975eba5b6SRobert Mustacchi 		if (ret_val)
315075eba5b6SRobert Mustacchi 			goto release;
315175eba5b6SRobert Mustacchi 	}
315275eba5b6SRobert Mustacchi 
315375eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
315475eba5b6SRobert Mustacchi 					   data);
315575eba5b6SRobert Mustacchi 
315675eba5b6SRobert Mustacchi release:
315775eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
315875eba5b6SRobert Mustacchi 	return ret_val;
315975eba5b6SRobert Mustacchi }
316075eba5b6SRobert Mustacchi 
316175eba5b6SRobert Mustacchi /**
316275eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_bm - Read BM PHY register
316375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
316475eba5b6SRobert Mustacchi  *  @offset: register offset to be read
316575eba5b6SRobert Mustacchi  *  @data: pointer to the read data
316675eba5b6SRobert Mustacchi  *
316775eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then reads the PHY register at offset
316875eba5b6SRobert Mustacchi  *  and storing the retrieved information in data.  Release any acquired
316975eba5b6SRobert Mustacchi  *  semaphores before exiting.
317075eba5b6SRobert Mustacchi  **/
317175eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
317275eba5b6SRobert Mustacchi {
317375eba5b6SRobert Mustacchi 	s32 ret_val;
317475eba5b6SRobert Mustacchi 	u32 page = offset >> IGP_PAGE_SHIFT;
317575eba5b6SRobert Mustacchi 
317675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_bm");
317775eba5b6SRobert Mustacchi 
317875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
317975eba5b6SRobert Mustacchi 	if (ret_val)
318075eba5b6SRobert Mustacchi 		return ret_val;
318175eba5b6SRobert Mustacchi 
318275eba5b6SRobert Mustacchi 	/* Page 800 works differently than the rest so it has its own func */
318375eba5b6SRobert Mustacchi 	if (page == BM_WUC_PAGE) {
318475eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
318575eba5b6SRobert Mustacchi 							 TRUE, FALSE);
318675eba5b6SRobert Mustacchi 		goto release;
318775eba5b6SRobert Mustacchi 	}
318875eba5b6SRobert Mustacchi 
318975eba5b6SRobert Mustacchi 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
319075eba5b6SRobert Mustacchi 
319175eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
319275eba5b6SRobert Mustacchi 		u32 page_shift, page_select;
319375eba5b6SRobert Mustacchi 
319475eba5b6SRobert Mustacchi 		/* Page select is register 31 for phy address 1 and 22 for
319575eba5b6SRobert Mustacchi 		 * phy address 2 and 3. Page select is shifted only for
319675eba5b6SRobert Mustacchi 		 * phy address 1.
319775eba5b6SRobert Mustacchi 		 */
319875eba5b6SRobert Mustacchi 		if (hw->phy.addr == 1) {
319975eba5b6SRobert Mustacchi 			page_shift = IGP_PAGE_SHIFT;
320075eba5b6SRobert Mustacchi 			page_select = IGP01E1000_PHY_PAGE_SELECT;
320175eba5b6SRobert Mustacchi 		} else {
320275eba5b6SRobert Mustacchi 			page_shift = 0;
320375eba5b6SRobert Mustacchi 			page_select = BM_PHY_PAGE_SELECT;
320475eba5b6SRobert Mustacchi 		}
320575eba5b6SRobert Mustacchi 
320675eba5b6SRobert Mustacchi 		/* Page is shifted left, PHY expects (page x 32) */
320775eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw, page_select,
320875eba5b6SRobert Mustacchi 						   (page << page_shift));
320975eba5b6SRobert Mustacchi 		if (ret_val)
321075eba5b6SRobert Mustacchi 			goto release;
321175eba5b6SRobert Mustacchi 	}
321275eba5b6SRobert Mustacchi 
321375eba5b6SRobert Mustacchi 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
321475eba5b6SRobert Mustacchi 					  data);
321575eba5b6SRobert Mustacchi release:
321675eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
321775eba5b6SRobert Mustacchi 	return ret_val;
321875eba5b6SRobert Mustacchi }
321975eba5b6SRobert Mustacchi 
322075eba5b6SRobert Mustacchi /**
322175eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_bm2 - Read BM PHY register
322275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
322375eba5b6SRobert Mustacchi  *  @offset: register offset to be read
322475eba5b6SRobert Mustacchi  *  @data: pointer to the read data
322575eba5b6SRobert Mustacchi  *
322675eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then reads the PHY register at offset
322775eba5b6SRobert Mustacchi  *  and storing the retrieved information in data.  Release any acquired
322875eba5b6SRobert Mustacchi  *  semaphores before exiting.
322975eba5b6SRobert Mustacchi  **/
323075eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
323175eba5b6SRobert Mustacchi {
323275eba5b6SRobert Mustacchi 	s32 ret_val;
323375eba5b6SRobert Mustacchi 	u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
323475eba5b6SRobert Mustacchi 
323575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_bm2");
323675eba5b6SRobert Mustacchi 
323775eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
323875eba5b6SRobert Mustacchi 	if (ret_val)
323975eba5b6SRobert Mustacchi 		return ret_val;
324075eba5b6SRobert Mustacchi 
324175eba5b6SRobert Mustacchi 	/* Page 800 works differently than the rest so it has its own func */
324275eba5b6SRobert Mustacchi 	if (page == BM_WUC_PAGE) {
324375eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
324475eba5b6SRobert Mustacchi 							 TRUE, FALSE);
324575eba5b6SRobert Mustacchi 		goto release;
324675eba5b6SRobert Mustacchi 	}
324775eba5b6SRobert Mustacchi 
324875eba5b6SRobert Mustacchi 	hw->phy.addr = 1;
324975eba5b6SRobert Mustacchi 
325075eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
325175eba5b6SRobert Mustacchi 		/* Page is shifted left, PHY expects (page x 32) */
325275eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
325375eba5b6SRobert Mustacchi 						   page);
325475eba5b6SRobert Mustacchi 
325575eba5b6SRobert Mustacchi 		if (ret_val)
325675eba5b6SRobert Mustacchi 			goto release;
325775eba5b6SRobert Mustacchi 	}
325875eba5b6SRobert Mustacchi 
325975eba5b6SRobert Mustacchi 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
326075eba5b6SRobert Mustacchi 					  data);
326175eba5b6SRobert Mustacchi release:
326275eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
326375eba5b6SRobert Mustacchi 	return ret_val;
326475eba5b6SRobert Mustacchi }
326575eba5b6SRobert Mustacchi 
326675eba5b6SRobert Mustacchi /**
326775eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_bm2 - Write BM PHY register
326875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
326975eba5b6SRobert Mustacchi  *  @offset: register offset to write to
327075eba5b6SRobert Mustacchi  *  @data: data to write at register offset
327175eba5b6SRobert Mustacchi  *
327275eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then writes the data to PHY register
327375eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
327475eba5b6SRobert Mustacchi  **/
327575eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
327675eba5b6SRobert Mustacchi {
327775eba5b6SRobert Mustacchi 	s32 ret_val;
327875eba5b6SRobert Mustacchi 	u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
327975eba5b6SRobert Mustacchi 
328075eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_bm2");
328175eba5b6SRobert Mustacchi 
328275eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
328375eba5b6SRobert Mustacchi 	if (ret_val)
328475eba5b6SRobert Mustacchi 		return ret_val;
328575eba5b6SRobert Mustacchi 
328675eba5b6SRobert Mustacchi 	/* Page 800 works differently than the rest so it has its own func */
328775eba5b6SRobert Mustacchi 	if (page == BM_WUC_PAGE) {
328875eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
3289*42cc51e0SRobert Mustacchi 							 FALSE, false);
329075eba5b6SRobert Mustacchi 		goto release;
329175eba5b6SRobert Mustacchi 	}
329275eba5b6SRobert Mustacchi 
329375eba5b6SRobert Mustacchi 	hw->phy.addr = 1;
329475eba5b6SRobert Mustacchi 
329575eba5b6SRobert Mustacchi 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
329675eba5b6SRobert Mustacchi 		/* Page is shifted left, PHY expects (page x 32) */
329775eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
329875eba5b6SRobert Mustacchi 						   page);
329975eba5b6SRobert Mustacchi 
330075eba5b6SRobert Mustacchi 		if (ret_val)
330175eba5b6SRobert Mustacchi 			goto release;
330275eba5b6SRobert Mustacchi 	}
330375eba5b6SRobert Mustacchi 
330475eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
330575eba5b6SRobert Mustacchi 					   data);
330675eba5b6SRobert Mustacchi 
330775eba5b6SRobert Mustacchi release:
330875eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
330975eba5b6SRobert Mustacchi 	return ret_val;
331075eba5b6SRobert Mustacchi }
331175eba5b6SRobert Mustacchi 
331275eba5b6SRobert Mustacchi /**
331375eba5b6SRobert Mustacchi  *  e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
331475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
331575eba5b6SRobert Mustacchi  *  @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
331675eba5b6SRobert Mustacchi  *
331775eba5b6SRobert Mustacchi  *  Assumes semaphore already acquired and phy_reg points to a valid memory
331875eba5b6SRobert Mustacchi  *  address to store contents of the BM_WUC_ENABLE_REG register.
331975eba5b6SRobert Mustacchi  **/
332075eba5b6SRobert Mustacchi s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
332175eba5b6SRobert Mustacchi {
332275eba5b6SRobert Mustacchi 	s32 ret_val;
332375eba5b6SRobert Mustacchi 	u16 temp;
332475eba5b6SRobert Mustacchi 
332575eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm");
332675eba5b6SRobert Mustacchi 
332775eba5b6SRobert Mustacchi 	if (!phy_reg)
332875eba5b6SRobert Mustacchi 		return -E1000_ERR_PARAM;
332975eba5b6SRobert Mustacchi 
333075eba5b6SRobert Mustacchi 	/* All page select, port ctrl and wakeup registers use phy address 1 */
333175eba5b6SRobert Mustacchi 	hw->phy.addr = 1;
333275eba5b6SRobert Mustacchi 
333375eba5b6SRobert Mustacchi 	/* Select Port Control Registers page */
333475eba5b6SRobert Mustacchi 	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
333575eba5b6SRobert Mustacchi 	if (ret_val) {
333675eba5b6SRobert Mustacchi 		DEBUGOUT("Could not set Port Control page\n");
333775eba5b6SRobert Mustacchi 		return ret_val;
333875eba5b6SRobert Mustacchi 	}
333975eba5b6SRobert Mustacchi 
334075eba5b6SRobert Mustacchi 	ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
334175eba5b6SRobert Mustacchi 	if (ret_val) {
334275eba5b6SRobert Mustacchi 		DEBUGOUT2("Could not read PHY register %d.%d\n",
334375eba5b6SRobert Mustacchi 			  BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
334475eba5b6SRobert Mustacchi 		return ret_val;
334575eba5b6SRobert Mustacchi 	}
334675eba5b6SRobert Mustacchi 
334775eba5b6SRobert Mustacchi 	/* Enable both PHY wakeup mode and Wakeup register page writes.
334875eba5b6SRobert Mustacchi 	 * Prevent a power state change by disabling ME and Host PHY wakeup.
334975eba5b6SRobert Mustacchi 	 */
335075eba5b6SRobert Mustacchi 	temp = *phy_reg;
335175eba5b6SRobert Mustacchi 	temp |= BM_WUC_ENABLE_BIT;
335275eba5b6SRobert Mustacchi 	temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
335375eba5b6SRobert Mustacchi 
335475eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
335575eba5b6SRobert Mustacchi 	if (ret_val) {
335675eba5b6SRobert Mustacchi 		DEBUGOUT2("Could not write PHY register %d.%d\n",
335775eba5b6SRobert Mustacchi 			  BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
335875eba5b6SRobert Mustacchi 		return ret_val;
335975eba5b6SRobert Mustacchi 	}
336075eba5b6SRobert Mustacchi 
336175eba5b6SRobert Mustacchi 	/* Select Host Wakeup Registers page - caller now able to write
336275eba5b6SRobert Mustacchi 	 * registers on the Wakeup registers page
336375eba5b6SRobert Mustacchi 	 */
336475eba5b6SRobert Mustacchi 	return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
336575eba5b6SRobert Mustacchi }
336675eba5b6SRobert Mustacchi 
336775eba5b6SRobert Mustacchi /**
336875eba5b6SRobert Mustacchi  *  e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
336975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
337075eba5b6SRobert Mustacchi  *  @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
337175eba5b6SRobert Mustacchi  *
337275eba5b6SRobert Mustacchi  *  Restore BM_WUC_ENABLE_REG to its original value.
337375eba5b6SRobert Mustacchi  *
337475eba5b6SRobert Mustacchi  *  Assumes semaphore already acquired and *phy_reg is the contents of the
337575eba5b6SRobert Mustacchi  *  BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
337675eba5b6SRobert Mustacchi  *  caller.
337775eba5b6SRobert Mustacchi  **/
337875eba5b6SRobert Mustacchi s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
337975eba5b6SRobert Mustacchi {
338075eba5b6SRobert Mustacchi 	s32 ret_val;
338175eba5b6SRobert Mustacchi 
338275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm");
338375eba5b6SRobert Mustacchi 
338475eba5b6SRobert Mustacchi 	if (!phy_reg)
338575eba5b6SRobert Mustacchi 		return -E1000_ERR_PARAM;
338675eba5b6SRobert Mustacchi 
338775eba5b6SRobert Mustacchi 	/* Select Port Control Registers page */
338875eba5b6SRobert Mustacchi 	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
338975eba5b6SRobert Mustacchi 	if (ret_val) {
339075eba5b6SRobert Mustacchi 		DEBUGOUT("Could not set Port Control page\n");
339175eba5b6SRobert Mustacchi 		return ret_val;
339275eba5b6SRobert Mustacchi 	}
339375eba5b6SRobert Mustacchi 
339475eba5b6SRobert Mustacchi 	/* Restore 769.17 to its original value */
339575eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
339675eba5b6SRobert Mustacchi 	if (ret_val)
339775eba5b6SRobert Mustacchi 		DEBUGOUT2("Could not restore PHY register %d.%d\n",
339875eba5b6SRobert Mustacchi 			  BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
339975eba5b6SRobert Mustacchi 
340075eba5b6SRobert Mustacchi 	return ret_val;
340175eba5b6SRobert Mustacchi }
340275eba5b6SRobert Mustacchi 
340375eba5b6SRobert Mustacchi /**
340475eba5b6SRobert Mustacchi  *  e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
340575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
340675eba5b6SRobert Mustacchi  *  @offset: register offset to be read or written
340775eba5b6SRobert Mustacchi  *  @data: pointer to the data to read or write
340875eba5b6SRobert Mustacchi  *  @read: determines if operation is read or write
340975eba5b6SRobert Mustacchi  *  @page_set: BM_WUC_PAGE already set and access enabled
341075eba5b6SRobert Mustacchi  *
341175eba5b6SRobert Mustacchi  *  Read the PHY register at offset and store the retrieved information in
341275eba5b6SRobert Mustacchi  *  data, or write data to PHY register at offset.  Note the procedure to
341375eba5b6SRobert Mustacchi  *  access the PHY wakeup registers is different than reading the other PHY
341475eba5b6SRobert Mustacchi  *  registers. It works as such:
341575eba5b6SRobert Mustacchi  *  1) Set 769.17.2 (page 769, register 17, bit 2) = 1
341675eba5b6SRobert Mustacchi  *  2) Set page to 800 for host (801 if we were manageability)
341775eba5b6SRobert Mustacchi  *  3) Write the address using the address opcode (0x11)
341875eba5b6SRobert Mustacchi  *  4) Read or write the data using the data opcode (0x12)
341975eba5b6SRobert Mustacchi  *  5) Restore 769.17.2 to its original value
342075eba5b6SRobert Mustacchi  *
342175eba5b6SRobert Mustacchi  *  Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
342275eba5b6SRobert Mustacchi  *  step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
342375eba5b6SRobert Mustacchi  *
342475eba5b6SRobert Mustacchi  *  Assumes semaphore is already acquired.  When page_set==TRUE, assumes
342575eba5b6SRobert Mustacchi  *  the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
342675eba5b6SRobert Mustacchi  *  is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
342775eba5b6SRobert Mustacchi  **/
342875eba5b6SRobert Mustacchi static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
342975eba5b6SRobert Mustacchi 					  u16 *data, bool read, bool page_set)
343075eba5b6SRobert Mustacchi {
343175eba5b6SRobert Mustacchi 	s32 ret_val;
3432*42cc51e0SRobert Mustacchi 	u16 reg = BM_PHY_REG_NUM(offset);
3433*42cc51e0SRobert Mustacchi 	u16 page = BM_PHY_REG_PAGE(offset);
343475eba5b6SRobert Mustacchi 	u16 phy_reg = 0;
343575eba5b6SRobert Mustacchi 
343675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
343775eba5b6SRobert Mustacchi 
343875eba5b6SRobert Mustacchi 	/* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
343975eba5b6SRobert Mustacchi 	if ((hw->mac.type == e1000_pchlan) &&
344075eba5b6SRobert Mustacchi 	   (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
344175eba5b6SRobert Mustacchi 		DEBUGOUT1("Attempting to access page %d while gig enabled.\n",
344275eba5b6SRobert Mustacchi 			  page);
344375eba5b6SRobert Mustacchi 
344475eba5b6SRobert Mustacchi 	if (!page_set) {
344575eba5b6SRobert Mustacchi 		/* Enable access to PHY wakeup registers */
344675eba5b6SRobert Mustacchi 		ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
344775eba5b6SRobert Mustacchi 		if (ret_val) {
344875eba5b6SRobert Mustacchi 			DEBUGOUT("Could not enable PHY wakeup reg access\n");
344975eba5b6SRobert Mustacchi 			return ret_val;
345075eba5b6SRobert Mustacchi 		}
345175eba5b6SRobert Mustacchi 	}
345275eba5b6SRobert Mustacchi 
345375eba5b6SRobert Mustacchi 	DEBUGOUT2("Accessing PHY page %d reg 0x%x\n", page, reg);
345475eba5b6SRobert Mustacchi 
345575eba5b6SRobert Mustacchi 	/* Write the Wakeup register page offset value using opcode 0x11 */
345675eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
345775eba5b6SRobert Mustacchi 	if (ret_val) {
345875eba5b6SRobert Mustacchi 		DEBUGOUT1("Could not write address opcode to page %d\n", page);
345975eba5b6SRobert Mustacchi 		return ret_val;
346075eba5b6SRobert Mustacchi 	}
346175eba5b6SRobert Mustacchi 
346275eba5b6SRobert Mustacchi 	if (read) {
346375eba5b6SRobert Mustacchi 		/* Read the Wakeup register page value using opcode 0x12 */
346475eba5b6SRobert Mustacchi 		ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
346575eba5b6SRobert Mustacchi 						  data);
346675eba5b6SRobert Mustacchi 	} else {
346775eba5b6SRobert Mustacchi 		/* Write the Wakeup register page value using opcode 0x12 */
346875eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
346975eba5b6SRobert Mustacchi 						   *data);
347075eba5b6SRobert Mustacchi 	}
347175eba5b6SRobert Mustacchi 
347275eba5b6SRobert Mustacchi 	if (ret_val) {
347375eba5b6SRobert Mustacchi 		DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg);
347475eba5b6SRobert Mustacchi 		return ret_val;
347575eba5b6SRobert Mustacchi 	}
347675eba5b6SRobert Mustacchi 
347775eba5b6SRobert Mustacchi 	if (!page_set)
347875eba5b6SRobert Mustacchi 		ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
347975eba5b6SRobert Mustacchi 
348075eba5b6SRobert Mustacchi 	return ret_val;
348175eba5b6SRobert Mustacchi }
348275eba5b6SRobert Mustacchi 
348375eba5b6SRobert Mustacchi /**
348475eba5b6SRobert Mustacchi  * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
348575eba5b6SRobert Mustacchi  * @hw: pointer to the HW structure
348675eba5b6SRobert Mustacchi  *
348775eba5b6SRobert Mustacchi  * In the case of a PHY power down to save power, or to turn off link during a
348875eba5b6SRobert Mustacchi  * driver unload, or wake on lan is not enabled, restore the link to previous
348975eba5b6SRobert Mustacchi  * settings.
349075eba5b6SRobert Mustacchi  **/
349175eba5b6SRobert Mustacchi void e1000_power_up_phy_copper(struct e1000_hw *hw)
349275eba5b6SRobert Mustacchi {
349375eba5b6SRobert Mustacchi 	u16 mii_reg = 0;
349475eba5b6SRobert Mustacchi 
349575eba5b6SRobert Mustacchi 	/* The PHY will retain its settings across a power down/up cycle */
349675eba5b6SRobert Mustacchi 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
349775eba5b6SRobert Mustacchi 	mii_reg &= ~MII_CR_POWER_DOWN;
349875eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
349975eba5b6SRobert Mustacchi }
350075eba5b6SRobert Mustacchi 
350175eba5b6SRobert Mustacchi /**
350275eba5b6SRobert Mustacchi  * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
350375eba5b6SRobert Mustacchi  * @hw: pointer to the HW structure
350475eba5b6SRobert Mustacchi  *
350575eba5b6SRobert Mustacchi  * In the case of a PHY power down to save power, or to turn off link during a
350675eba5b6SRobert Mustacchi  * driver unload, or wake on lan is not enabled, restore the link to previous
350775eba5b6SRobert Mustacchi  * settings.
350875eba5b6SRobert Mustacchi  **/
350975eba5b6SRobert Mustacchi void e1000_power_down_phy_copper(struct e1000_hw *hw)
351075eba5b6SRobert Mustacchi {
351175eba5b6SRobert Mustacchi 	u16 mii_reg = 0;
351275eba5b6SRobert Mustacchi 
351375eba5b6SRobert Mustacchi 	/* The PHY will retain its settings across a power down/up cycle */
351475eba5b6SRobert Mustacchi 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
351575eba5b6SRobert Mustacchi 	mii_reg |= MII_CR_POWER_DOWN;
351675eba5b6SRobert Mustacchi 	hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
351775eba5b6SRobert Mustacchi 	msec_delay(1);
351875eba5b6SRobert Mustacchi }
351975eba5b6SRobert Mustacchi 
352075eba5b6SRobert Mustacchi /**
352175eba5b6SRobert Mustacchi  *  __e1000_read_phy_reg_hv -  Read HV PHY register
352275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
352375eba5b6SRobert Mustacchi  *  @offset: register offset to be read
352475eba5b6SRobert Mustacchi  *  @data: pointer to the read data
352575eba5b6SRobert Mustacchi  *  @locked: semaphore has already been acquired or not
352675eba5b6SRobert Mustacchi  *
352775eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then reads the PHY register at offset
352875eba5b6SRobert Mustacchi  *  and stores the retrieved information in data.  Release any acquired
352975eba5b6SRobert Mustacchi  *  semaphore before exiting.
353075eba5b6SRobert Mustacchi  **/
353175eba5b6SRobert Mustacchi static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
353275eba5b6SRobert Mustacchi 				   bool locked, bool page_set)
353375eba5b6SRobert Mustacchi {
353475eba5b6SRobert Mustacchi 	s32 ret_val;
353575eba5b6SRobert Mustacchi 	u16 page = BM_PHY_REG_PAGE(offset);
353675eba5b6SRobert Mustacchi 	u16 reg = BM_PHY_REG_NUM(offset);
353775eba5b6SRobert Mustacchi 	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
353875eba5b6SRobert Mustacchi 
353975eba5b6SRobert Mustacchi 	DEBUGFUNC("__e1000_read_phy_reg_hv");
354075eba5b6SRobert Mustacchi 
354175eba5b6SRobert Mustacchi 	if (!locked) {
354275eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
354375eba5b6SRobert Mustacchi 		if (ret_val)
354475eba5b6SRobert Mustacchi 			return ret_val;
354575eba5b6SRobert Mustacchi 	}
354675eba5b6SRobert Mustacchi 	/* Page 800 works differently than the rest so it has its own func */
354775eba5b6SRobert Mustacchi 	if (page == BM_WUC_PAGE) {
354875eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
354975eba5b6SRobert Mustacchi 							 TRUE, page_set);
355075eba5b6SRobert Mustacchi 		goto out;
355175eba5b6SRobert Mustacchi 	}
355275eba5b6SRobert Mustacchi 
355375eba5b6SRobert Mustacchi 	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
355475eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
355575eba5b6SRobert Mustacchi 							 data, TRUE);
355675eba5b6SRobert Mustacchi 		goto out;
355775eba5b6SRobert Mustacchi 	}
355875eba5b6SRobert Mustacchi 
355975eba5b6SRobert Mustacchi 	if (!page_set) {
356075eba5b6SRobert Mustacchi 		if (page == HV_INTC_FC_PAGE_START)
356175eba5b6SRobert Mustacchi 			page = 0;
356275eba5b6SRobert Mustacchi 
356375eba5b6SRobert Mustacchi 		if (reg > MAX_PHY_MULTI_PAGE_REG) {
356475eba5b6SRobert Mustacchi 			/* Page is shifted left, PHY expects (page x 32) */
356575eba5b6SRobert Mustacchi 			ret_val = e1000_set_page_igp(hw,
356675eba5b6SRobert Mustacchi 						     (page << IGP_PAGE_SHIFT));
356775eba5b6SRobert Mustacchi 
356875eba5b6SRobert Mustacchi 			hw->phy.addr = phy_addr;
356975eba5b6SRobert Mustacchi 
357075eba5b6SRobert Mustacchi 			if (ret_val)
357175eba5b6SRobert Mustacchi 				goto out;
357275eba5b6SRobert Mustacchi 		}
357375eba5b6SRobert Mustacchi 	}
357475eba5b6SRobert Mustacchi 
357575eba5b6SRobert Mustacchi 	DEBUGOUT3("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
357675eba5b6SRobert Mustacchi 		  page << IGP_PAGE_SHIFT, reg);
357775eba5b6SRobert Mustacchi 
357875eba5b6SRobert Mustacchi 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
357975eba5b6SRobert Mustacchi 					  data);
358075eba5b6SRobert Mustacchi out:
358175eba5b6SRobert Mustacchi 	if (!locked)
358275eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
358375eba5b6SRobert Mustacchi 
358475eba5b6SRobert Mustacchi 	return ret_val;
358575eba5b6SRobert Mustacchi }
358675eba5b6SRobert Mustacchi 
358775eba5b6SRobert Mustacchi /**
358875eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_hv -  Read HV PHY register
358975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
359075eba5b6SRobert Mustacchi  *  @offset: register offset to be read
359175eba5b6SRobert Mustacchi  *  @data: pointer to the read data
359275eba5b6SRobert Mustacchi  *
359375eba5b6SRobert Mustacchi  *  Acquires semaphore then reads the PHY register at offset and stores
359475eba5b6SRobert Mustacchi  *  the retrieved information in data.  Release the acquired semaphore
359575eba5b6SRobert Mustacchi  *  before exiting.
359675eba5b6SRobert Mustacchi  **/
359775eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
359875eba5b6SRobert Mustacchi {
3599*42cc51e0SRobert Mustacchi 	return __e1000_read_phy_reg_hv(hw, offset, data, FALSE, false);
360075eba5b6SRobert Mustacchi }
360175eba5b6SRobert Mustacchi 
360275eba5b6SRobert Mustacchi /**
360375eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_hv_locked -  Read HV PHY register
360475eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
360575eba5b6SRobert Mustacchi  *  @offset: register offset to be read
360675eba5b6SRobert Mustacchi  *  @data: pointer to the read data
360775eba5b6SRobert Mustacchi  *
360875eba5b6SRobert Mustacchi  *  Reads the PHY register at offset and stores the retrieved information
360975eba5b6SRobert Mustacchi  *  in data.  Assumes semaphore already acquired.
361075eba5b6SRobert Mustacchi  **/
361175eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
361275eba5b6SRobert Mustacchi {
361375eba5b6SRobert Mustacchi 	return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, FALSE);
361475eba5b6SRobert Mustacchi }
361575eba5b6SRobert Mustacchi 
361675eba5b6SRobert Mustacchi /**
361775eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_page_hv - Read HV PHY register
361875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
361975eba5b6SRobert Mustacchi  *  @offset: register offset to write to
362075eba5b6SRobert Mustacchi  *  @data: data to write at register offset
362175eba5b6SRobert Mustacchi  *
362275eba5b6SRobert Mustacchi  *  Reads the PHY register at offset and stores the retrieved information
362375eba5b6SRobert Mustacchi  *  in data.  Assumes semaphore already acquired and page already set.
362475eba5b6SRobert Mustacchi  **/
362575eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
362675eba5b6SRobert Mustacchi {
362775eba5b6SRobert Mustacchi 	return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, true);
362875eba5b6SRobert Mustacchi }
362975eba5b6SRobert Mustacchi 
363075eba5b6SRobert Mustacchi /**
363175eba5b6SRobert Mustacchi  *  __e1000_write_phy_reg_hv - Write HV PHY register
363275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
363375eba5b6SRobert Mustacchi  *  @offset: register offset to write to
363475eba5b6SRobert Mustacchi  *  @data: data to write at register offset
363575eba5b6SRobert Mustacchi  *  @locked: semaphore has already been acquired or not
363675eba5b6SRobert Mustacchi  *
363775eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then writes the data to PHY register
363875eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
363975eba5b6SRobert Mustacchi  **/
364075eba5b6SRobert Mustacchi static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
364175eba5b6SRobert Mustacchi 				    bool locked, bool page_set)
364275eba5b6SRobert Mustacchi {
364375eba5b6SRobert Mustacchi 	s32 ret_val;
364475eba5b6SRobert Mustacchi 	u16 page = BM_PHY_REG_PAGE(offset);
364575eba5b6SRobert Mustacchi 	u16 reg = BM_PHY_REG_NUM(offset);
364675eba5b6SRobert Mustacchi 	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
364775eba5b6SRobert Mustacchi 
364875eba5b6SRobert Mustacchi 	DEBUGFUNC("__e1000_write_phy_reg_hv");
364975eba5b6SRobert Mustacchi 
365075eba5b6SRobert Mustacchi 	if (!locked) {
365175eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.acquire(hw);
365275eba5b6SRobert Mustacchi 		if (ret_val)
365375eba5b6SRobert Mustacchi 			return ret_val;
365475eba5b6SRobert Mustacchi 	}
365575eba5b6SRobert Mustacchi 	/* Page 800 works differently than the rest so it has its own func */
365675eba5b6SRobert Mustacchi 	if (page == BM_WUC_PAGE) {
365775eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
365875eba5b6SRobert Mustacchi 							 FALSE, page_set);
365975eba5b6SRobert Mustacchi 		goto out;
366075eba5b6SRobert Mustacchi 	}
366175eba5b6SRobert Mustacchi 
366275eba5b6SRobert Mustacchi 	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
366375eba5b6SRobert Mustacchi 		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
366475eba5b6SRobert Mustacchi 							 &data, FALSE);
366575eba5b6SRobert Mustacchi 		goto out;
366675eba5b6SRobert Mustacchi 	}
366775eba5b6SRobert Mustacchi 
366875eba5b6SRobert Mustacchi 	if (!page_set) {
366975eba5b6SRobert Mustacchi 		if (page == HV_INTC_FC_PAGE_START)
367075eba5b6SRobert Mustacchi 			page = 0;
367175eba5b6SRobert Mustacchi 
367275eba5b6SRobert Mustacchi 		/* Workaround MDIO accesses being disabled after entering IEEE
367375eba5b6SRobert Mustacchi 		 * Power Down (when bit 11 of the PHY Control register is set)
367475eba5b6SRobert Mustacchi 		 */
367575eba5b6SRobert Mustacchi 		if ((hw->phy.type == e1000_phy_82578) &&
367675eba5b6SRobert Mustacchi 		    (hw->phy.revision >= 1) &&
367775eba5b6SRobert Mustacchi 		    (hw->phy.addr == 2) &&
367875eba5b6SRobert Mustacchi 		    !(MAX_PHY_REG_ADDRESS & reg) &&
367975eba5b6SRobert Mustacchi 		    (data & (1 << 11))) {
368075eba5b6SRobert Mustacchi 			u16 data2 = 0x7EFF;
368175eba5b6SRobert Mustacchi 			ret_val = e1000_access_phy_debug_regs_hv(hw,
368275eba5b6SRobert Mustacchi 								 (1 << 6) | 0x3,
368375eba5b6SRobert Mustacchi 								 &data2, FALSE);
368475eba5b6SRobert Mustacchi 			if (ret_val)
368575eba5b6SRobert Mustacchi 				goto out;
368675eba5b6SRobert Mustacchi 		}
368775eba5b6SRobert Mustacchi 
368875eba5b6SRobert Mustacchi 		if (reg > MAX_PHY_MULTI_PAGE_REG) {
368975eba5b6SRobert Mustacchi 			/* Page is shifted left, PHY expects (page x 32) */
369075eba5b6SRobert Mustacchi 			ret_val = e1000_set_page_igp(hw,
369175eba5b6SRobert Mustacchi 						     (page << IGP_PAGE_SHIFT));
369275eba5b6SRobert Mustacchi 
369375eba5b6SRobert Mustacchi 			hw->phy.addr = phy_addr;
369475eba5b6SRobert Mustacchi 
369575eba5b6SRobert Mustacchi 			if (ret_val)
369675eba5b6SRobert Mustacchi 				goto out;
369775eba5b6SRobert Mustacchi 		}
369875eba5b6SRobert Mustacchi 	}
369975eba5b6SRobert Mustacchi 
370075eba5b6SRobert Mustacchi 	DEBUGOUT3("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
370175eba5b6SRobert Mustacchi 		  page << IGP_PAGE_SHIFT, reg);
370275eba5b6SRobert Mustacchi 
370375eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
370475eba5b6SRobert Mustacchi 					   data);
370575eba5b6SRobert Mustacchi 
370675eba5b6SRobert Mustacchi out:
370775eba5b6SRobert Mustacchi 	if (!locked)
370875eba5b6SRobert Mustacchi 		hw->phy.ops.release(hw);
370975eba5b6SRobert Mustacchi 
371075eba5b6SRobert Mustacchi 	return ret_val;
371175eba5b6SRobert Mustacchi }
371275eba5b6SRobert Mustacchi 
371375eba5b6SRobert Mustacchi /**
371475eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_hv - Write HV PHY register
371575eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
371675eba5b6SRobert Mustacchi  *  @offset: register offset to write to
371775eba5b6SRobert Mustacchi  *  @data: data to write at register offset
371875eba5b6SRobert Mustacchi  *
371975eba5b6SRobert Mustacchi  *  Acquires semaphore then writes the data to PHY register at the offset.
372075eba5b6SRobert Mustacchi  *  Release the acquired semaphores before exiting.
372175eba5b6SRobert Mustacchi  **/
372275eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
372375eba5b6SRobert Mustacchi {
3724*42cc51e0SRobert Mustacchi 	return __e1000_write_phy_reg_hv(hw, offset, data, FALSE, false);
372575eba5b6SRobert Mustacchi }
372675eba5b6SRobert Mustacchi 
372775eba5b6SRobert Mustacchi /**
372875eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_hv_locked - Write HV PHY register
372975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
373075eba5b6SRobert Mustacchi  *  @offset: register offset to write to
373175eba5b6SRobert Mustacchi  *  @data: data to write at register offset
373275eba5b6SRobert Mustacchi  *
373375eba5b6SRobert Mustacchi  *  Writes the data to PHY register at the offset.  Assumes semaphore
373475eba5b6SRobert Mustacchi  *  already acquired.
373575eba5b6SRobert Mustacchi  **/
373675eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
373775eba5b6SRobert Mustacchi {
373875eba5b6SRobert Mustacchi 	return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, FALSE);
373975eba5b6SRobert Mustacchi }
374075eba5b6SRobert Mustacchi 
374175eba5b6SRobert Mustacchi /**
374275eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_page_hv - Write HV PHY register
374375eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
374475eba5b6SRobert Mustacchi  *  @offset: register offset to write to
374575eba5b6SRobert Mustacchi  *  @data: data to write at register offset
374675eba5b6SRobert Mustacchi  *
374775eba5b6SRobert Mustacchi  *  Writes the data to PHY register at the offset.  Assumes semaphore
374875eba5b6SRobert Mustacchi  *  already acquired and page already set.
374975eba5b6SRobert Mustacchi  **/
375075eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
375175eba5b6SRobert Mustacchi {
375275eba5b6SRobert Mustacchi 	return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, true);
375375eba5b6SRobert Mustacchi }
375475eba5b6SRobert Mustacchi 
375575eba5b6SRobert Mustacchi /**
375675eba5b6SRobert Mustacchi  *  e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
375775eba5b6SRobert Mustacchi  *  @page: page to be accessed
375875eba5b6SRobert Mustacchi  **/
375975eba5b6SRobert Mustacchi static u32 e1000_get_phy_addr_for_hv_page(u32 page)
376075eba5b6SRobert Mustacchi {
376175eba5b6SRobert Mustacchi 	u32 phy_addr = 2;
376275eba5b6SRobert Mustacchi 
376375eba5b6SRobert Mustacchi 	if (page >= HV_INTC_FC_PAGE_START)
376475eba5b6SRobert Mustacchi 		phy_addr = 1;
376575eba5b6SRobert Mustacchi 
376675eba5b6SRobert Mustacchi 	return phy_addr;
376775eba5b6SRobert Mustacchi }
376875eba5b6SRobert Mustacchi 
376975eba5b6SRobert Mustacchi /**
377075eba5b6SRobert Mustacchi  *  e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers
377175eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
377275eba5b6SRobert Mustacchi  *  @offset: register offset to be read or written
377375eba5b6SRobert Mustacchi  *  @data: pointer to the data to be read or written
377475eba5b6SRobert Mustacchi  *  @read: determines if operation is read or write
377575eba5b6SRobert Mustacchi  *
377675eba5b6SRobert Mustacchi  *  Reads the PHY register at offset and stores the retreived information
377775eba5b6SRobert Mustacchi  *  in data.  Assumes semaphore already acquired.  Note that the procedure
377875eba5b6SRobert Mustacchi  *  to access these regs uses the address port and data port to read/write.
377975eba5b6SRobert Mustacchi  *  These accesses done with PHY address 2 and without using pages.
378075eba5b6SRobert Mustacchi  **/
378175eba5b6SRobert Mustacchi static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
378275eba5b6SRobert Mustacchi 					  u16 *data, bool read)
378375eba5b6SRobert Mustacchi {
378475eba5b6SRobert Mustacchi 	s32 ret_val;
378575eba5b6SRobert Mustacchi 	u32 addr_reg;
378675eba5b6SRobert Mustacchi 	u32 data_reg;
378775eba5b6SRobert Mustacchi 
378875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_access_phy_debug_regs_hv");
378975eba5b6SRobert Mustacchi 
379075eba5b6SRobert Mustacchi 	/* This takes care of the difference with desktop vs mobile phy */
3791c124a83eSRobert Mustacchi 	addr_reg = ((hw->phy.type == e1000_phy_82578) ?
3792c124a83eSRobert Mustacchi 		    I82578_ADDR_REG : I82577_ADDR_REG);
379375eba5b6SRobert Mustacchi 	data_reg = addr_reg + 1;
379475eba5b6SRobert Mustacchi 
379575eba5b6SRobert Mustacchi 	/* All operations in this function are phy address 2 */
379675eba5b6SRobert Mustacchi 	hw->phy.addr = 2;
379775eba5b6SRobert Mustacchi 
379875eba5b6SRobert Mustacchi 	/* masking with 0x3F to remove the page from offset */
379975eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
380075eba5b6SRobert Mustacchi 	if (ret_val) {
380175eba5b6SRobert Mustacchi 		DEBUGOUT("Could not write the Address Offset port register\n");
380275eba5b6SRobert Mustacchi 		return ret_val;
380375eba5b6SRobert Mustacchi 	}
380475eba5b6SRobert Mustacchi 
380575eba5b6SRobert Mustacchi 	/* Read or write the data value next */
380675eba5b6SRobert Mustacchi 	if (read)
380775eba5b6SRobert Mustacchi 		ret_val = e1000_read_phy_reg_mdic(hw, data_reg, data);
380875eba5b6SRobert Mustacchi 	else
380975eba5b6SRobert Mustacchi 		ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data);
381075eba5b6SRobert Mustacchi 
381175eba5b6SRobert Mustacchi 	if (ret_val)
381275eba5b6SRobert Mustacchi 		DEBUGOUT("Could not access the Data port register\n");
381375eba5b6SRobert Mustacchi 
381475eba5b6SRobert Mustacchi 	return ret_val;
381575eba5b6SRobert Mustacchi }
381675eba5b6SRobert Mustacchi 
381775eba5b6SRobert Mustacchi /**
381875eba5b6SRobert Mustacchi  *  e1000_link_stall_workaround_hv - Si workaround
381975eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
382075eba5b6SRobert Mustacchi  *
382175eba5b6SRobert Mustacchi  *  This function works around a Si bug where the link partner can get
382275eba5b6SRobert Mustacchi  *  a link up indication before the PHY does.  If small packets are sent
382375eba5b6SRobert Mustacchi  *  by the link partner they can be placed in the packet buffer without
382475eba5b6SRobert Mustacchi  *  being properly accounted for by the PHY and will stall preventing
382575eba5b6SRobert Mustacchi  *  further packets from being received.  The workaround is to clear the
382675eba5b6SRobert Mustacchi  *  packet buffer after the PHY detects link up.
382775eba5b6SRobert Mustacchi  **/
382875eba5b6SRobert Mustacchi s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
382975eba5b6SRobert Mustacchi {
383075eba5b6SRobert Mustacchi 	s32 ret_val = E1000_SUCCESS;
383175eba5b6SRobert Mustacchi 	u16 data;
383275eba5b6SRobert Mustacchi 
383375eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_link_stall_workaround_hv");
383475eba5b6SRobert Mustacchi 
383575eba5b6SRobert Mustacchi 	if (hw->phy.type != e1000_phy_82578)
383675eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
383775eba5b6SRobert Mustacchi 
383875eba5b6SRobert Mustacchi 	/* Do not apply workaround if in PHY loopback bit 14 set */
383975eba5b6SRobert Mustacchi 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
384075eba5b6SRobert Mustacchi 	if (data & PHY_CONTROL_LB)
384175eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
384275eba5b6SRobert Mustacchi 
384375eba5b6SRobert Mustacchi 	/* check if link is up and at 1Gbps */
384475eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
384575eba5b6SRobert Mustacchi 	if (ret_val)
384675eba5b6SRobert Mustacchi 		return ret_val;
384775eba5b6SRobert Mustacchi 
3848c124a83eSRobert Mustacchi 	data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
3849c124a83eSRobert Mustacchi 		 BM_CS_STATUS_SPEED_MASK);
385075eba5b6SRobert Mustacchi 
385175eba5b6SRobert Mustacchi 	if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
385275eba5b6SRobert Mustacchi 		     BM_CS_STATUS_SPEED_1000))
385375eba5b6SRobert Mustacchi 		return E1000_SUCCESS;
385475eba5b6SRobert Mustacchi 
385575eba5b6SRobert Mustacchi 	msec_delay(200);
385675eba5b6SRobert Mustacchi 
385775eba5b6SRobert Mustacchi 	/* flush the packets in the fifo buffer */
385875eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
385975eba5b6SRobert Mustacchi 					(HV_MUX_DATA_CTRL_GEN_TO_MAC |
386075eba5b6SRobert Mustacchi 					 HV_MUX_DATA_CTRL_FORCE_SPEED));
386175eba5b6SRobert Mustacchi 	if (ret_val)
386275eba5b6SRobert Mustacchi 		return ret_val;
386375eba5b6SRobert Mustacchi 
386475eba5b6SRobert Mustacchi 	return hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
386575eba5b6SRobert Mustacchi 				     HV_MUX_DATA_CTRL_GEN_TO_MAC);
386675eba5b6SRobert Mustacchi }
386775eba5b6SRobert Mustacchi 
386875eba5b6SRobert Mustacchi /**
386975eba5b6SRobert Mustacchi  *  e1000_check_polarity_82577 - Checks the polarity.
387075eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
387175eba5b6SRobert Mustacchi  *
387275eba5b6SRobert Mustacchi  *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
387375eba5b6SRobert Mustacchi  *
387475eba5b6SRobert Mustacchi  *  Polarity is determined based on the PHY specific status register.
387575eba5b6SRobert Mustacchi  **/
387675eba5b6SRobert Mustacchi s32 e1000_check_polarity_82577(struct e1000_hw *hw)
387775eba5b6SRobert Mustacchi {
387875eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
387975eba5b6SRobert Mustacchi 	s32 ret_val;
388075eba5b6SRobert Mustacchi 	u16 data;
388175eba5b6SRobert Mustacchi 
388275eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_check_polarity_82577");
388375eba5b6SRobert Mustacchi 
388475eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
388575eba5b6SRobert Mustacchi 
388675eba5b6SRobert Mustacchi 	if (!ret_val)
3887c124a83eSRobert Mustacchi 		phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY)
388875eba5b6SRobert Mustacchi 				       ? e1000_rev_polarity_reversed
3889c124a83eSRobert Mustacchi 				       : e1000_rev_polarity_normal);
389075eba5b6SRobert Mustacchi 
389175eba5b6SRobert Mustacchi 	return ret_val;
389275eba5b6SRobert Mustacchi }
389375eba5b6SRobert Mustacchi 
389475eba5b6SRobert Mustacchi /**
389575eba5b6SRobert Mustacchi  *  e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
389675eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
389775eba5b6SRobert Mustacchi  *
389875eba5b6SRobert Mustacchi  *  Calls the PHY setup function to force speed and duplex.
389975eba5b6SRobert Mustacchi  **/
390075eba5b6SRobert Mustacchi s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
390175eba5b6SRobert Mustacchi {
390275eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
390375eba5b6SRobert Mustacchi 	s32 ret_val;
390475eba5b6SRobert Mustacchi 	u16 phy_data;
390575eba5b6SRobert Mustacchi 	bool link;
390675eba5b6SRobert Mustacchi 
390775eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_phy_force_speed_duplex_82577");
390875eba5b6SRobert Mustacchi 
390975eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
391075eba5b6SRobert Mustacchi 	if (ret_val)
391175eba5b6SRobert Mustacchi 		return ret_val;
391275eba5b6SRobert Mustacchi 
391375eba5b6SRobert Mustacchi 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
391475eba5b6SRobert Mustacchi 
391575eba5b6SRobert Mustacchi 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
391675eba5b6SRobert Mustacchi 	if (ret_val)
391775eba5b6SRobert Mustacchi 		return ret_val;
391875eba5b6SRobert Mustacchi 
391975eba5b6SRobert Mustacchi 	usec_delay(1);
392075eba5b6SRobert Mustacchi 
392175eba5b6SRobert Mustacchi 	if (phy->autoneg_wait_to_complete) {
392275eba5b6SRobert Mustacchi 		DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n");
392375eba5b6SRobert Mustacchi 
392475eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
392575eba5b6SRobert Mustacchi 						     100000, &link);
392675eba5b6SRobert Mustacchi 		if (ret_val)
392775eba5b6SRobert Mustacchi 			return ret_val;
392875eba5b6SRobert Mustacchi 
392975eba5b6SRobert Mustacchi 		if (!link)
393075eba5b6SRobert Mustacchi 			DEBUGOUT("Link taking longer than expected.\n");
393175eba5b6SRobert Mustacchi 
393275eba5b6SRobert Mustacchi 		/* Try once more */
393375eba5b6SRobert Mustacchi 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
393475eba5b6SRobert Mustacchi 						     100000, &link);
393575eba5b6SRobert Mustacchi 	}
393675eba5b6SRobert Mustacchi 
393775eba5b6SRobert Mustacchi 	return ret_val;
393875eba5b6SRobert Mustacchi }
393975eba5b6SRobert Mustacchi 
394075eba5b6SRobert Mustacchi /**
394175eba5b6SRobert Mustacchi  *  e1000_get_phy_info_82577 - Retrieve I82577 PHY information
394275eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
394375eba5b6SRobert Mustacchi  *
394475eba5b6SRobert Mustacchi  *  Read PHY status to determine if link is up.  If link is up, then
394575eba5b6SRobert Mustacchi  *  set/determine 10base-T extended distance and polarity correction.  Read
394675eba5b6SRobert Mustacchi  *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
394775eba5b6SRobert Mustacchi  *  determine on the cable length, local and remote receiver.
394875eba5b6SRobert Mustacchi  **/
394975eba5b6SRobert Mustacchi s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
395075eba5b6SRobert Mustacchi {
395175eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
395275eba5b6SRobert Mustacchi 	s32 ret_val;
395375eba5b6SRobert Mustacchi 	u16 data;
395475eba5b6SRobert Mustacchi 	bool link;
395575eba5b6SRobert Mustacchi 
395675eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_phy_info_82577");
395775eba5b6SRobert Mustacchi 
395875eba5b6SRobert Mustacchi 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
395975eba5b6SRobert Mustacchi 	if (ret_val)
396075eba5b6SRobert Mustacchi 		return ret_val;
396175eba5b6SRobert Mustacchi 
396275eba5b6SRobert Mustacchi 	if (!link) {
396375eba5b6SRobert Mustacchi 		DEBUGOUT("Phy info is only valid if link is up\n");
396475eba5b6SRobert Mustacchi 		return -E1000_ERR_CONFIG;
396575eba5b6SRobert Mustacchi 	}
396675eba5b6SRobert Mustacchi 
396775eba5b6SRobert Mustacchi 	phy->polarity_correction = TRUE;
396875eba5b6SRobert Mustacchi 
396975eba5b6SRobert Mustacchi 	ret_val = e1000_check_polarity_82577(hw);
397075eba5b6SRobert Mustacchi 	if (ret_val)
397175eba5b6SRobert Mustacchi 		return ret_val;
397275eba5b6SRobert Mustacchi 
397375eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
397475eba5b6SRobert Mustacchi 	if (ret_val)
397575eba5b6SRobert Mustacchi 		return ret_val;
397675eba5b6SRobert Mustacchi 
397775eba5b6SRobert Mustacchi 	phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX);
397875eba5b6SRobert Mustacchi 
397975eba5b6SRobert Mustacchi 	if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
398075eba5b6SRobert Mustacchi 	    I82577_PHY_STATUS2_SPEED_1000MBPS) {
398175eba5b6SRobert Mustacchi 		ret_val = hw->phy.ops.get_cable_length(hw);
398275eba5b6SRobert Mustacchi 		if (ret_val)
398375eba5b6SRobert Mustacchi 			return ret_val;
398475eba5b6SRobert Mustacchi 
398575eba5b6SRobert Mustacchi 		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
398675eba5b6SRobert Mustacchi 		if (ret_val)
398775eba5b6SRobert Mustacchi 			return ret_val;
398875eba5b6SRobert Mustacchi 
398975eba5b6SRobert Mustacchi 		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
399075eba5b6SRobert Mustacchi 				? e1000_1000t_rx_status_ok
399175eba5b6SRobert Mustacchi 				: e1000_1000t_rx_status_not_ok;
399275eba5b6SRobert Mustacchi 
399375eba5b6SRobert Mustacchi 		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
399475eba5b6SRobert Mustacchi 				 ? e1000_1000t_rx_status_ok
399575eba5b6SRobert Mustacchi 				 : e1000_1000t_rx_status_not_ok;
399675eba5b6SRobert Mustacchi 	} else {
399775eba5b6SRobert Mustacchi 		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
399875eba5b6SRobert Mustacchi 		phy->local_rx = e1000_1000t_rx_status_undefined;
399975eba5b6SRobert Mustacchi 		phy->remote_rx = e1000_1000t_rx_status_undefined;
400075eba5b6SRobert Mustacchi 	}
400175eba5b6SRobert Mustacchi 
400275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
400375eba5b6SRobert Mustacchi }
400475eba5b6SRobert Mustacchi 
400575eba5b6SRobert Mustacchi /**
400675eba5b6SRobert Mustacchi  *  e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
400775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
400875eba5b6SRobert Mustacchi  *
400975eba5b6SRobert Mustacchi  * Reads the diagnostic status register and verifies result is valid before
401075eba5b6SRobert Mustacchi  * placing it in the phy_cable_length field.
401175eba5b6SRobert Mustacchi  **/
401275eba5b6SRobert Mustacchi s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
401375eba5b6SRobert Mustacchi {
401475eba5b6SRobert Mustacchi 	struct e1000_phy_info *phy = &hw->phy;
401575eba5b6SRobert Mustacchi 	s32 ret_val;
401675eba5b6SRobert Mustacchi 	u16 phy_data, length;
401775eba5b6SRobert Mustacchi 
401875eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_get_cable_length_82577");
401975eba5b6SRobert Mustacchi 
402075eba5b6SRobert Mustacchi 	ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
402175eba5b6SRobert Mustacchi 	if (ret_val)
402275eba5b6SRobert Mustacchi 		return ret_val;
402375eba5b6SRobert Mustacchi 
4024c124a83eSRobert Mustacchi 	length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
4025c124a83eSRobert Mustacchi 		  I82577_DSTATUS_CABLE_LENGTH_SHIFT);
402675eba5b6SRobert Mustacchi 
402775eba5b6SRobert Mustacchi 	if (length == E1000_CABLE_LENGTH_UNDEFINED)
402875eba5b6SRobert Mustacchi 		return -E1000_ERR_PHY;
402975eba5b6SRobert Mustacchi 
403075eba5b6SRobert Mustacchi 	phy->cable_length = length;
403175eba5b6SRobert Mustacchi 
403275eba5b6SRobert Mustacchi 	return E1000_SUCCESS;
403375eba5b6SRobert Mustacchi }
403475eba5b6SRobert Mustacchi 
403575eba5b6SRobert Mustacchi /**
403675eba5b6SRobert Mustacchi  *  e1000_write_phy_reg_gs40g - Write GS40G  PHY register
403775eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
403875eba5b6SRobert Mustacchi  *  @offset: register offset to write to
403975eba5b6SRobert Mustacchi  *  @data: data to write at register offset
404075eba5b6SRobert Mustacchi  *
404175eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then writes the data to PHY register
404275eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
404375eba5b6SRobert Mustacchi  **/
404475eba5b6SRobert Mustacchi s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
404575eba5b6SRobert Mustacchi {
404675eba5b6SRobert Mustacchi 	s32 ret_val;
404775eba5b6SRobert Mustacchi 	u16 page = offset >> GS40G_PAGE_SHIFT;
404875eba5b6SRobert Mustacchi 
404975eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_gs40g");
405075eba5b6SRobert Mustacchi 
405175eba5b6SRobert Mustacchi 	offset = offset & GS40G_OFFSET_MASK;
405275eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
405375eba5b6SRobert Mustacchi 	if (ret_val)
405475eba5b6SRobert Mustacchi 		return ret_val;
405575eba5b6SRobert Mustacchi 
405675eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
405775eba5b6SRobert Mustacchi 	if (ret_val)
405875eba5b6SRobert Mustacchi 		goto release;
405975eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
406075eba5b6SRobert Mustacchi 
406175eba5b6SRobert Mustacchi release:
406275eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
406375eba5b6SRobert Mustacchi 	return ret_val;
406475eba5b6SRobert Mustacchi }
406575eba5b6SRobert Mustacchi 
406675eba5b6SRobert Mustacchi /**
406775eba5b6SRobert Mustacchi  *  e1000_read_phy_reg_gs40g - Read GS40G  PHY register
406875eba5b6SRobert Mustacchi  *  @hw: pointer to the HW structure
406975eba5b6SRobert Mustacchi  *  @offset: lower half is register offset to read to
407075eba5b6SRobert Mustacchi  *     upper half is page to use.
407175eba5b6SRobert Mustacchi  *  @data: data to read at register offset
407275eba5b6SRobert Mustacchi  *
407375eba5b6SRobert Mustacchi  *  Acquires semaphore, if necessary, then reads the data in the PHY register
407475eba5b6SRobert Mustacchi  *  at the offset.  Release any acquired semaphores before exiting.
407575eba5b6SRobert Mustacchi  **/
407675eba5b6SRobert Mustacchi s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
407775eba5b6SRobert Mustacchi {
407875eba5b6SRobert Mustacchi 	s32 ret_val;
407975eba5b6SRobert Mustacchi 	u16 page = offset >> GS40G_PAGE_SHIFT;
408075eba5b6SRobert Mustacchi 
408175eba5b6SRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_gs40g");
408275eba5b6SRobert Mustacchi 
408375eba5b6SRobert Mustacchi 	offset = offset & GS40G_OFFSET_MASK;
408475eba5b6SRobert Mustacchi 	ret_val = hw->phy.ops.acquire(hw);
408575eba5b6SRobert Mustacchi 	if (ret_val)
408675eba5b6SRobert Mustacchi 		return ret_val;
408775eba5b6SRobert Mustacchi 
408875eba5b6SRobert Mustacchi 	ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
408975eba5b6SRobert Mustacchi 	if (ret_val)
409075eba5b6SRobert Mustacchi 		goto release;
409175eba5b6SRobert Mustacchi 	ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
409275eba5b6SRobert Mustacchi 
409375eba5b6SRobert Mustacchi release:
409475eba5b6SRobert Mustacchi 	hw->phy.ops.release(hw);
409575eba5b6SRobert Mustacchi 	return ret_val;
409675eba5b6SRobert Mustacchi }
409775eba5b6SRobert Mustacchi 
4098c124a83eSRobert Mustacchi /**
4099c124a83eSRobert Mustacchi  *  e1000_read_phy_reg_mphy - Read mPHY control register
4100c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
4101c124a83eSRobert Mustacchi  *  @address: address to be read
4102c124a83eSRobert Mustacchi  *  @data: pointer to the read data
4103c124a83eSRobert Mustacchi  *
4104c124a83eSRobert Mustacchi  *  Reads the mPHY control register in the PHY at offset and stores the
4105c124a83eSRobert Mustacchi  *  information read to data.
4106c124a83eSRobert Mustacchi  **/
4107c124a83eSRobert Mustacchi s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data)
4108c124a83eSRobert Mustacchi {
4109c124a83eSRobert Mustacchi 	u32 mphy_ctrl = 0;
4110c124a83eSRobert Mustacchi 	bool locked = FALSE;
4111c124a83eSRobert Mustacchi 	bool ready;
4112c124a83eSRobert Mustacchi 
4113c124a83eSRobert Mustacchi 	DEBUGFUNC("e1000_read_phy_reg_mphy");
4114c124a83eSRobert Mustacchi 
4115c124a83eSRobert Mustacchi 	/* Check if mPHY is ready to read/write operations */
4116c124a83eSRobert Mustacchi 	ready = e1000_is_mphy_ready(hw);
4117c124a83eSRobert Mustacchi 	if (!ready)
4118c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
4119c124a83eSRobert Mustacchi 
4120c124a83eSRobert Mustacchi 	/* Check if mPHY access is disabled and enable it if so */
4121c124a83eSRobert Mustacchi 	mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
4122c124a83eSRobert Mustacchi 	if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
4123c124a83eSRobert Mustacchi 		locked = TRUE;
4124c124a83eSRobert Mustacchi 		ready = e1000_is_mphy_ready(hw);
4125c124a83eSRobert Mustacchi 		if (!ready)
4126c124a83eSRobert Mustacchi 			return -E1000_ERR_PHY;
4127c124a83eSRobert Mustacchi 		mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
4128c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4129c124a83eSRobert Mustacchi 	}
4130c124a83eSRobert Mustacchi 
4131c124a83eSRobert Mustacchi 	/* Set the address that we want to read */
4132c124a83eSRobert Mustacchi 	ready = e1000_is_mphy_ready(hw);
4133c124a83eSRobert Mustacchi 	if (!ready)
4134c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
4135c124a83eSRobert Mustacchi 
4136c124a83eSRobert Mustacchi 	/* We mask address, because we want to use only current lane */
4137c124a83eSRobert Mustacchi 	mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK &
4138c124a83eSRobert Mustacchi 		~E1000_MPHY_ADDRESS_FNC_OVERRIDE) |
4139c124a83eSRobert Mustacchi 		(address & E1000_MPHY_ADDRESS_MASK);
4140c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4141c124a83eSRobert Mustacchi 
4142c124a83eSRobert Mustacchi 	/* Read data from the address */
4143c124a83eSRobert Mustacchi 	ready = e1000_is_mphy_ready(hw);
4144c124a83eSRobert Mustacchi 	if (!ready)
4145c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
4146c124a83eSRobert Mustacchi 	*data = E1000_READ_REG(hw, E1000_MPHY_DATA);
4147c124a83eSRobert Mustacchi 
4148c124a83eSRobert Mustacchi 	/* Disable access to mPHY if it was originally disabled */
4149c124a83eSRobert Mustacchi 	if (locked)
4150c124a83eSRobert Mustacchi 		ready = e1000_is_mphy_ready(hw);
4151c124a83eSRobert Mustacchi 		if (!ready)
4152c124a83eSRobert Mustacchi 			return -E1000_ERR_PHY;
4153c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
4154c124a83eSRobert Mustacchi 				E1000_MPHY_DIS_ACCESS);
4155c124a83eSRobert Mustacchi 
4156c124a83eSRobert Mustacchi 	return E1000_SUCCESS;
4157c124a83eSRobert Mustacchi }
4158c124a83eSRobert Mustacchi 
4159c124a83eSRobert Mustacchi /**
4160c124a83eSRobert Mustacchi  *  e1000_write_phy_reg_mphy - Write mPHY control register
4161c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
4162c124a83eSRobert Mustacchi  *  @address: address to write to
4163c124a83eSRobert Mustacchi  *  @data: data to write to register at offset
4164c124a83eSRobert Mustacchi  *  @line_override: used when we want to use different line than default one
4165c124a83eSRobert Mustacchi  *
4166c124a83eSRobert Mustacchi  *  Writes data to mPHY control register.
4167c124a83eSRobert Mustacchi  **/
4168c124a83eSRobert Mustacchi s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
4169c124a83eSRobert Mustacchi 			     bool line_override)
4170c124a83eSRobert Mustacchi {
4171c124a83eSRobert Mustacchi 	u32 mphy_ctrl = 0;
4172c124a83eSRobert Mustacchi 	bool locked = FALSE;
4173c124a83eSRobert Mustacchi 	bool ready;
4174c124a83eSRobert Mustacchi 
4175c124a83eSRobert Mustacchi 	DEBUGFUNC("e1000_write_phy_reg_mphy");
4176c124a83eSRobert Mustacchi 
4177c124a83eSRobert Mustacchi 	/* Check if mPHY is ready to read/write operations */
4178c124a83eSRobert Mustacchi 	ready = e1000_is_mphy_ready(hw);
4179c124a83eSRobert Mustacchi 	if (!ready)
4180c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
4181c124a83eSRobert Mustacchi 
4182c124a83eSRobert Mustacchi 	/* Check if mPHY access is disabled and enable it if so */
4183c124a83eSRobert Mustacchi 	mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
4184c124a83eSRobert Mustacchi 	if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
4185c124a83eSRobert Mustacchi 		locked = TRUE;
4186c124a83eSRobert Mustacchi 		ready = e1000_is_mphy_ready(hw);
4187c124a83eSRobert Mustacchi 		if (!ready)
4188c124a83eSRobert Mustacchi 			return -E1000_ERR_PHY;
4189c124a83eSRobert Mustacchi 		mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
4190c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4191c124a83eSRobert Mustacchi 	}
4192c124a83eSRobert Mustacchi 
4193c124a83eSRobert Mustacchi 	/* Set the address that we want to read */
4194c124a83eSRobert Mustacchi 	ready = e1000_is_mphy_ready(hw);
4195c124a83eSRobert Mustacchi 	if (!ready)
4196c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
4197c124a83eSRobert Mustacchi 
4198c124a83eSRobert Mustacchi 	/* We mask address, because we want to use only current lane */
4199c124a83eSRobert Mustacchi 	if (line_override)
4200c124a83eSRobert Mustacchi 		mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE;
4201c124a83eSRobert Mustacchi 	else
4202c124a83eSRobert Mustacchi 		mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE;
4203c124a83eSRobert Mustacchi 	mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) |
4204c124a83eSRobert Mustacchi 		(address & E1000_MPHY_ADDRESS_MASK);
4205c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4206c124a83eSRobert Mustacchi 
4207c124a83eSRobert Mustacchi 	/* Read data from the address */
4208c124a83eSRobert Mustacchi 	ready = e1000_is_mphy_ready(hw);
4209c124a83eSRobert Mustacchi 	if (!ready)
4210c124a83eSRobert Mustacchi 		return -E1000_ERR_PHY;
4211c124a83eSRobert Mustacchi 	E1000_WRITE_REG(hw, E1000_MPHY_DATA, data);
4212c124a83eSRobert Mustacchi 
4213c124a83eSRobert Mustacchi 	/* Disable access to mPHY if it was originally disabled */
4214c124a83eSRobert Mustacchi 	if (locked)
4215c124a83eSRobert Mustacchi 		ready = e1000_is_mphy_ready(hw);
4216c124a83eSRobert Mustacchi 		if (!ready)
4217c124a83eSRobert Mustacchi 			return -E1000_ERR_PHY;
4218c124a83eSRobert Mustacchi 		E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
4219c124a83eSRobert Mustacchi 				E1000_MPHY_DIS_ACCESS);
4220c124a83eSRobert Mustacchi 
4221c124a83eSRobert Mustacchi 	return E1000_SUCCESS;
4222c124a83eSRobert Mustacchi }
4223c124a83eSRobert Mustacchi 
4224c124a83eSRobert Mustacchi /**
4225c124a83eSRobert Mustacchi  *  e1000_is_mphy_ready - Check if mPHY control register is not busy
4226c124a83eSRobert Mustacchi  *  @hw: pointer to the HW structure
4227c124a83eSRobert Mustacchi  *
4228c124a83eSRobert Mustacchi  *  Returns mPHY control register status.
4229c124a83eSRobert Mustacchi  **/
4230c124a83eSRobert Mustacchi bool e1000_is_mphy_ready(struct e1000_hw *hw)
4231c124a83eSRobert Mustacchi {
4232c124a83eSRobert Mustacchi 	u16 retry_count = 0;
4233c124a83eSRobert Mustacchi 	u32 mphy_ctrl = 0;
4234c124a83eSRobert Mustacchi 	bool ready = FALSE;
4235c124a83eSRobert Mustacchi 
4236c124a83eSRobert Mustacchi 	while (retry_count < 2) {
4237c124a83eSRobert Mustacchi 		mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
4238c124a83eSRobert Mustacchi 		if (mphy_ctrl & E1000_MPHY_BUSY) {
4239c124a83eSRobert Mustacchi 			usec_delay(20);
4240c124a83eSRobert Mustacchi 			retry_count++;
4241c124a83eSRobert Mustacchi 			continue;
4242c124a83eSRobert Mustacchi 		}
4243c124a83eSRobert Mustacchi 		ready = TRUE;
4244c124a83eSRobert Mustacchi 		break;
4245c124a83eSRobert Mustacchi 	}
4246c124a83eSRobert Mustacchi 
4247c124a83eSRobert Mustacchi 	if (!ready)
4248c124a83eSRobert Mustacchi 		DEBUGOUT("ERROR READING mPHY control register, phy is busy.\n");
4249c124a83eSRobert Mustacchi 
4250c124a83eSRobert Mustacchi 	return ready;
4251c124a83eSRobert Mustacchi }
4252