xref: /dflybsd-src/sys/dev/netif/ig_hal/e1000_phy.c (revision 01a55482b42bba8de64caeb8c9ede647a9208734)
19c80d176SSepherosa Ziehau /******************************************************************************
29c80d176SSepherosa Ziehau 
3*01a55482SSepherosa Ziehau   Copyright (c) 2001-2019, Intel Corporation
49c80d176SSepherosa Ziehau   All rights reserved.
59c80d176SSepherosa Ziehau 
69c80d176SSepherosa Ziehau   Redistribution and use in source and binary forms, with or without
79c80d176SSepherosa Ziehau   modification, are permitted provided that the following conditions are met:
89c80d176SSepherosa Ziehau 
99c80d176SSepherosa Ziehau    1. Redistributions of source code must retain the above copyright notice,
109c80d176SSepherosa Ziehau       this list of conditions and the following disclaimer.
119c80d176SSepherosa Ziehau 
129c80d176SSepherosa Ziehau    2. Redistributions in binary form must reproduce the above copyright
139c80d176SSepherosa Ziehau       notice, this list of conditions and the following disclaimer in the
149c80d176SSepherosa Ziehau       documentation and/or other materials provided with the distribution.
159c80d176SSepherosa Ziehau 
169c80d176SSepherosa Ziehau    3. Neither the name of the Intel Corporation nor the names of its
179c80d176SSepherosa Ziehau       contributors may be used to endorse or promote products derived from
189c80d176SSepherosa Ziehau       this software without specific prior written permission.
199c80d176SSepherosa Ziehau 
209c80d176SSepherosa Ziehau   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
219c80d176SSepherosa Ziehau   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
229c80d176SSepherosa Ziehau   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
239c80d176SSepherosa Ziehau   ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
249c80d176SSepherosa Ziehau   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
259c80d176SSepherosa Ziehau   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
269c80d176SSepherosa Ziehau   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
279c80d176SSepherosa Ziehau   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
289c80d176SSepherosa Ziehau   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
299c80d176SSepherosa Ziehau   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
309c80d176SSepherosa Ziehau   POSSIBILITY OF SUCH DAMAGE.
319c80d176SSepherosa Ziehau 
329c80d176SSepherosa Ziehau ******************************************************************************/
3374dc3754SSepherosa Ziehau /*$FreeBSD$*/
349c80d176SSepherosa Ziehau 
359c80d176SSepherosa Ziehau #include "e1000_api.h"
369c80d176SSepherosa Ziehau 
37379ebbe7SSepherosa Ziehau static s32 e1000_wait_autoneg(struct e1000_hw *hw);
389c80d176SSepherosa Ziehau static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
396d5e2922SSepherosa Ziehau 					  u16 *data, bool read, bool page_set);
406a5a645eSSepherosa Ziehau static u32 e1000_get_phy_addr_for_hv_page(u32 page);
416a5a645eSSepherosa Ziehau static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
426a5a645eSSepherosa Ziehau 					  u16 *data, bool read);
436a5a645eSSepherosa Ziehau 
449c80d176SSepherosa Ziehau /* Cable length tables */
456d5e2922SSepherosa Ziehau static const u16 e1000_m88_cable_length_table[] = {
466d5e2922SSepherosa Ziehau 	0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED };
479c80d176SSepherosa Ziehau #define M88E1000_CABLE_LENGTH_TABLE_SIZE \
489c80d176SSepherosa Ziehau 		(sizeof(e1000_m88_cable_length_table) / \
499c80d176SSepherosa Ziehau 		 sizeof(e1000_m88_cable_length_table[0]))
509c80d176SSepherosa Ziehau 
516d5e2922SSepherosa Ziehau static const u16 e1000_igp_2_cable_length_table[] = {
526d5e2922SSepherosa Ziehau 	0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 0, 0, 0, 3,
536d5e2922SSepherosa Ziehau 	6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 6, 10, 14, 18, 22,
546d5e2922SSepherosa Ziehau 	26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 21, 26, 31, 35, 40,
556d5e2922SSepherosa Ziehau 	44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 40, 45, 51, 56, 61,
566d5e2922SSepherosa Ziehau 	66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 60, 66, 72, 77, 82,
576d5e2922SSepherosa Ziehau 	87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 83, 89, 95,
586d5e2922SSepherosa Ziehau 	100, 105, 109, 113, 116, 119, 122, 124, 104, 109, 114, 118, 121,
596d5e2922SSepherosa Ziehau 	124};
609c80d176SSepherosa Ziehau #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \
619c80d176SSepherosa Ziehau 		(sizeof(e1000_igp_2_cable_length_table) / \
629c80d176SSepherosa Ziehau 		 sizeof(e1000_igp_2_cable_length_table[0]))
639c80d176SSepherosa Ziehau 
649c80d176SSepherosa Ziehau /**
659c80d176SSepherosa Ziehau  *  e1000_init_phy_ops_generic - Initialize PHY function pointers
669c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
679c80d176SSepherosa Ziehau  *
689c80d176SSepherosa Ziehau  *  Setups up the function pointers to no-op functions
699c80d176SSepherosa Ziehau  **/
e1000_init_phy_ops_generic(struct e1000_hw * hw)709c80d176SSepherosa Ziehau void e1000_init_phy_ops_generic(struct e1000_hw *hw)
719c80d176SSepherosa Ziehau {
729c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
739c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_init_phy_ops_generic");
749c80d176SSepherosa Ziehau 
759c80d176SSepherosa Ziehau 	/* Initialize function pointers */
769c80d176SSepherosa Ziehau 	phy->ops.init_params = e1000_null_ops_generic;
779c80d176SSepherosa Ziehau 	phy->ops.acquire = e1000_null_ops_generic;
789c80d176SSepherosa Ziehau 	phy->ops.check_polarity = e1000_null_ops_generic;
799c80d176SSepherosa Ziehau 	phy->ops.check_reset_block = e1000_null_ops_generic;
809c80d176SSepherosa Ziehau 	phy->ops.commit = e1000_null_ops_generic;
819c80d176SSepherosa Ziehau 	phy->ops.force_speed_duplex = e1000_null_ops_generic;
829c80d176SSepherosa Ziehau 	phy->ops.get_cfg_done = e1000_null_ops_generic;
839c80d176SSepherosa Ziehau 	phy->ops.get_cable_length = e1000_null_ops_generic;
849c80d176SSepherosa Ziehau 	phy->ops.get_info = e1000_null_ops_generic;
856d5e2922SSepherosa Ziehau 	phy->ops.set_page = e1000_null_set_page;
869c80d176SSepherosa Ziehau 	phy->ops.read_reg = e1000_null_read_reg;
876a5a645eSSepherosa Ziehau 	phy->ops.read_reg_locked = e1000_null_read_reg;
886d5e2922SSepherosa Ziehau 	phy->ops.read_reg_page = e1000_null_read_reg;
899c80d176SSepherosa Ziehau 	phy->ops.release = e1000_null_phy_generic;
909c80d176SSepherosa Ziehau 	phy->ops.reset = e1000_null_ops_generic;
919c80d176SSepherosa Ziehau 	phy->ops.set_d0_lplu_state = e1000_null_lplu_state;
929c80d176SSepherosa Ziehau 	phy->ops.set_d3_lplu_state = e1000_null_lplu_state;
939c80d176SSepherosa Ziehau 	phy->ops.write_reg = e1000_null_write_reg;
946a5a645eSSepherosa Ziehau 	phy->ops.write_reg_locked = e1000_null_write_reg;
956d5e2922SSepherosa Ziehau 	phy->ops.write_reg_page = e1000_null_write_reg;
969c80d176SSepherosa Ziehau 	phy->ops.power_up = e1000_null_phy_generic;
979c80d176SSepherosa Ziehau 	phy->ops.power_down = e1000_null_phy_generic;
989c80d176SSepherosa Ziehau 	phy->ops.cfg_on_link_up = e1000_null_ops_generic;
994be59a01SSepherosa Ziehau 	phy->ops.read_i2c_byte = e1000_read_i2c_byte_null;
1004be59a01SSepherosa Ziehau 	phy->ops.write_i2c_byte = e1000_write_i2c_byte_null;
1019c80d176SSepherosa Ziehau }
1029c80d176SSepherosa Ziehau 
1039c80d176SSepherosa Ziehau /**
1046d5e2922SSepherosa Ziehau  *  e1000_null_set_page - No-op function, return 0
1056d5e2922SSepherosa Ziehau  *  @hw: pointer to the HW structure
106*01a55482SSepherosa Ziehau  *  @data: dummy variable
1076d5e2922SSepherosa Ziehau  **/
e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG * hw,u16 E1000_UNUSEDARG data)108379ebbe7SSepherosa Ziehau s32 e1000_null_set_page(struct e1000_hw E1000_UNUSEDARG *hw,
109379ebbe7SSepherosa Ziehau 			u16 E1000_UNUSEDARG data)
1106d5e2922SSepherosa Ziehau {
1116d5e2922SSepherosa Ziehau 	DEBUGFUNC("e1000_null_set_page");
1126d5e2922SSepherosa Ziehau 	return E1000_SUCCESS;
1136d5e2922SSepherosa Ziehau }
1146d5e2922SSepherosa Ziehau 
1156d5e2922SSepherosa Ziehau /**
1169c80d176SSepherosa Ziehau  *  e1000_null_read_reg - No-op function, return 0
1179c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
118*01a55482SSepherosa Ziehau  *  @offset: dummy variable
119*01a55482SSepherosa Ziehau  *  @data: dummy variable
1209c80d176SSepherosa Ziehau  **/
e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG * hw,u32 E1000_UNUSEDARG offset,u16 E1000_UNUSEDARG * data)121379ebbe7SSepherosa Ziehau s32 e1000_null_read_reg(struct e1000_hw E1000_UNUSEDARG *hw,
122379ebbe7SSepherosa Ziehau 			u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG *data)
1239c80d176SSepherosa Ziehau {
1249c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_read_reg");
1259c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
1269c80d176SSepherosa Ziehau }
1279c80d176SSepherosa Ziehau 
1289c80d176SSepherosa Ziehau /**
1299c80d176SSepherosa Ziehau  *  e1000_null_phy_generic - No-op function, return void
1309c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
1319c80d176SSepherosa Ziehau  **/
e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG * hw)132379ebbe7SSepherosa Ziehau void e1000_null_phy_generic(struct e1000_hw E1000_UNUSEDARG *hw)
1339c80d176SSepherosa Ziehau {
1349c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_phy_generic");
1359c80d176SSepherosa Ziehau 	return;
1369c80d176SSepherosa Ziehau }
1379c80d176SSepherosa Ziehau 
1389c80d176SSepherosa Ziehau /**
1399c80d176SSepherosa Ziehau  *  e1000_null_lplu_state - No-op function, return 0
1409c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
141*01a55482SSepherosa Ziehau  *  @active: dummy variable
1429c80d176SSepherosa Ziehau  **/
e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG * hw,bool E1000_UNUSEDARG active)143379ebbe7SSepherosa Ziehau s32 e1000_null_lplu_state(struct e1000_hw E1000_UNUSEDARG *hw,
144379ebbe7SSepherosa Ziehau 			  bool E1000_UNUSEDARG active)
1459c80d176SSepherosa Ziehau {
1469c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_lplu_state");
1479c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
1489c80d176SSepherosa Ziehau }
1499c80d176SSepherosa Ziehau 
1509c80d176SSepherosa Ziehau /**
1519c80d176SSepherosa Ziehau  *  e1000_null_write_reg - No-op function, return 0
1529c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
153*01a55482SSepherosa Ziehau  *  @offset: dummy variable
154*01a55482SSepherosa Ziehau  *  @data: dummy variable
1559c80d176SSepherosa Ziehau  **/
e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG * hw,u32 E1000_UNUSEDARG offset,u16 E1000_UNUSEDARG data)156379ebbe7SSepherosa Ziehau s32 e1000_null_write_reg(struct e1000_hw E1000_UNUSEDARG *hw,
157379ebbe7SSepherosa Ziehau 			 u32 E1000_UNUSEDARG offset, u16 E1000_UNUSEDARG data)
1589c80d176SSepherosa Ziehau {
1599c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_null_write_reg");
1609c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
1619c80d176SSepherosa Ziehau }
1629c80d176SSepherosa Ziehau 
1639c80d176SSepherosa Ziehau /**
1644be59a01SSepherosa Ziehau  *  e1000_read_i2c_byte_null - No-op function, return 0
1654be59a01SSepherosa Ziehau  *  @hw: pointer to hardware structure
1664be59a01SSepherosa Ziehau  *  @byte_offset: byte offset to write
1674be59a01SSepherosa Ziehau  *  @dev_addr: device address
1684be59a01SSepherosa Ziehau  *  @data: data value read
1694be59a01SSepherosa Ziehau  *
1704be59a01SSepherosa Ziehau  **/
e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG * hw,u8 E1000_UNUSEDARG byte_offset,u8 E1000_UNUSEDARG dev_addr,u8 E1000_UNUSEDARG * data)171379ebbe7SSepherosa Ziehau s32 e1000_read_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
172379ebbe7SSepherosa Ziehau 			     u8 E1000_UNUSEDARG byte_offset,
173379ebbe7SSepherosa Ziehau 			     u8 E1000_UNUSEDARG dev_addr,
174379ebbe7SSepherosa Ziehau 			     u8 E1000_UNUSEDARG *data)
1754be59a01SSepherosa Ziehau {
1764be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_read_i2c_byte_null");
1774be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
1784be59a01SSepherosa Ziehau }
1794be59a01SSepherosa Ziehau 
1804be59a01SSepherosa Ziehau /**
1814be59a01SSepherosa Ziehau  *  e1000_write_i2c_byte_null - No-op function, return 0
1824be59a01SSepherosa Ziehau  *  @hw: pointer to hardware structure
1834be59a01SSepherosa Ziehau  *  @byte_offset: byte offset to write
1844be59a01SSepherosa Ziehau  *  @dev_addr: device address
1854be59a01SSepherosa Ziehau  *  @data: data value to write
1864be59a01SSepherosa Ziehau  *
1874be59a01SSepherosa Ziehau  **/
e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG * hw,u8 E1000_UNUSEDARG byte_offset,u8 E1000_UNUSEDARG dev_addr,u8 E1000_UNUSEDARG data)188379ebbe7SSepherosa Ziehau s32 e1000_write_i2c_byte_null(struct e1000_hw E1000_UNUSEDARG *hw,
189379ebbe7SSepherosa Ziehau 			      u8 E1000_UNUSEDARG byte_offset,
190379ebbe7SSepherosa Ziehau 			      u8 E1000_UNUSEDARG dev_addr,
191379ebbe7SSepherosa Ziehau 			      u8 E1000_UNUSEDARG data)
1924be59a01SSepherosa Ziehau {
1934be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_write_i2c_byte_null");
1944be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
1954be59a01SSepherosa Ziehau }
1964be59a01SSepherosa Ziehau 
1974be59a01SSepherosa Ziehau /**
1989c80d176SSepherosa Ziehau  *  e1000_check_reset_block_generic - Check if PHY reset is blocked
1999c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
2009c80d176SSepherosa Ziehau  *
2019c80d176SSepherosa Ziehau  *  Read the PHY management control register and check whether a PHY reset
2029c80d176SSepherosa Ziehau  *  is blocked.  If a reset is not blocked return E1000_SUCCESS, otherwise
2039c80d176SSepherosa Ziehau  *  return E1000_BLK_PHY_RESET (12).
2049c80d176SSepherosa Ziehau  **/
e1000_check_reset_block_generic(struct e1000_hw * hw)2059c80d176SSepherosa Ziehau s32 e1000_check_reset_block_generic(struct e1000_hw *hw)
2069c80d176SSepherosa Ziehau {
2079c80d176SSepherosa Ziehau 	u32 manc;
2089c80d176SSepherosa Ziehau 
2099c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_check_reset_block");
2109c80d176SSepherosa Ziehau 
2119c80d176SSepherosa Ziehau 	manc = E1000_READ_REG(hw, E1000_MANC);
2129c80d176SSepherosa Ziehau 
2139c80d176SSepherosa Ziehau 	return (manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ?
2149c80d176SSepherosa Ziehau 	       E1000_BLK_PHY_RESET : E1000_SUCCESS;
2159c80d176SSepherosa Ziehau }
2169c80d176SSepherosa Ziehau 
2179c80d176SSepherosa Ziehau /**
2189c80d176SSepherosa Ziehau  *  e1000_get_phy_id - Retrieve the PHY ID and revision
2199c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
2209c80d176SSepherosa Ziehau  *
2219c80d176SSepherosa Ziehau  *  Reads the PHY registers and stores the PHY ID and possibly the PHY
2229c80d176SSepherosa Ziehau  *  revision in the hardware structure.
2239c80d176SSepherosa Ziehau  **/
e1000_get_phy_id(struct e1000_hw * hw)2249c80d176SSepherosa Ziehau s32 e1000_get_phy_id(struct e1000_hw *hw)
2259c80d176SSepherosa Ziehau {
2269c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
2279c80d176SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
2289c80d176SSepherosa Ziehau 	u16 phy_id;
2296a5a645eSSepherosa Ziehau 	u16 retry_count = 0;
2309c80d176SSepherosa Ziehau 
2319c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_get_phy_id");
2329c80d176SSepherosa Ziehau 
2334be59a01SSepherosa Ziehau 	if (!phy->ops.read_reg)
2344be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
2359c80d176SSepherosa Ziehau 
2366a5a645eSSepherosa Ziehau 	while (retry_count < 2) {
2379c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id);
2389c80d176SSepherosa Ziehau 		if (ret_val)
2394be59a01SSepherosa Ziehau 			return ret_val;
2409c80d176SSepherosa Ziehau 
2419c80d176SSepherosa Ziehau 		phy->id = (u32)(phy_id << 16);
2429c80d176SSepherosa Ziehau 		usec_delay(20);
2439c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id);
2449c80d176SSepherosa Ziehau 		if (ret_val)
2454be59a01SSepherosa Ziehau 			return ret_val;
2469c80d176SSepherosa Ziehau 
2479c80d176SSepherosa Ziehau 		phy->id |= (u32)(phy_id & PHY_REVISION_MASK);
2489c80d176SSepherosa Ziehau 		phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK);
2499c80d176SSepherosa Ziehau 
2506a5a645eSSepherosa Ziehau 		if (phy->id != 0 && phy->id != PHY_REVISION_MASK)
2514be59a01SSepherosa Ziehau 			return E1000_SUCCESS;
2526a5a645eSSepherosa Ziehau 
2536a5a645eSSepherosa Ziehau 		retry_count++;
2546a5a645eSSepherosa Ziehau 	}
2554be59a01SSepherosa Ziehau 
2564be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
2579c80d176SSepherosa Ziehau }
2589c80d176SSepherosa Ziehau 
2599c80d176SSepherosa Ziehau /**
2609c80d176SSepherosa Ziehau  *  e1000_phy_reset_dsp_generic - Reset PHY DSP
2619c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
2629c80d176SSepherosa Ziehau  *
2639c80d176SSepherosa Ziehau  *  Reset the digital signal processor.
2649c80d176SSepherosa Ziehau  **/
e1000_phy_reset_dsp_generic(struct e1000_hw * hw)2659c80d176SSepherosa Ziehau s32 e1000_phy_reset_dsp_generic(struct e1000_hw *hw)
2669c80d176SSepherosa Ziehau {
2674be59a01SSepherosa Ziehau 	s32 ret_val;
2689c80d176SSepherosa Ziehau 
2699c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_reset_dsp_generic");
2709c80d176SSepherosa Ziehau 
2714be59a01SSepherosa Ziehau 	if (!hw->phy.ops.write_reg)
2724be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
2739c80d176SSepherosa Ziehau 
2749c80d176SSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1);
2759c80d176SSepherosa Ziehau 	if (ret_val)
2769c80d176SSepherosa Ziehau 		return ret_val;
2774be59a01SSepherosa Ziehau 
2784be59a01SSepherosa Ziehau 	return hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0);
2799c80d176SSepherosa Ziehau }
2809c80d176SSepherosa Ziehau 
2819c80d176SSepherosa Ziehau /**
2829c80d176SSepherosa Ziehau  *  e1000_read_phy_reg_mdic - Read MDI control register
2839c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
2849c80d176SSepherosa Ziehau  *  @offset: register offset to be read
2859c80d176SSepherosa Ziehau  *  @data: pointer to the read data
2869c80d176SSepherosa Ziehau  *
2879c80d176SSepherosa Ziehau  *  Reads the MDI control register in the PHY at offset and stores the
2889c80d176SSepherosa Ziehau  *  information read to data.
2899c80d176SSepherosa Ziehau  **/
e1000_read_phy_reg_mdic(struct e1000_hw * hw,u32 offset,u16 * data)2909c80d176SSepherosa Ziehau s32 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data)
2919c80d176SSepherosa Ziehau {
2929c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
2939c80d176SSepherosa Ziehau 	u32 i, mdic = 0;
2949c80d176SSepherosa Ziehau 
2959c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_read_phy_reg_mdic");
2969c80d176SSepherosa Ziehau 
2976a5a645eSSepherosa Ziehau 	if (offset > MAX_PHY_REG_ADDRESS) {
2986a5a645eSSepherosa Ziehau 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
2996a5a645eSSepherosa Ziehau 		return -E1000_ERR_PARAM;
3006a5a645eSSepherosa Ziehau 	}
3016a5a645eSSepherosa Ziehau 
302379ebbe7SSepherosa Ziehau 	/* Set up Op-code, Phy Address, and register offset in the MDI
3039c80d176SSepherosa Ziehau 	 * Control register.  The MAC will take care of interfacing with the
3049c80d176SSepherosa Ziehau 	 * PHY to retrieve the desired data.
3059c80d176SSepherosa Ziehau 	 */
3069c80d176SSepherosa Ziehau 	mdic = ((offset << E1000_MDIC_REG_SHIFT) |
3079c80d176SSepherosa Ziehau 		(phy->addr << E1000_MDIC_PHY_SHIFT) |
3089c80d176SSepherosa Ziehau 		(E1000_MDIC_OP_READ));
3099c80d176SSepherosa Ziehau 
3109c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MDIC, mdic);
3119c80d176SSepherosa Ziehau 
312379ebbe7SSepherosa Ziehau 	/* Poll the ready bit to see if the MDI read completed
3139c80d176SSepherosa Ziehau 	 * Increasing the time out as testing showed failures with
3149c80d176SSepherosa Ziehau 	 * the lower time out
3159c80d176SSepherosa Ziehau 	 */
3169c80d176SSepherosa Ziehau 	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
3174765c386SMichael Neumann 		usec_delay_irq(50);
3189c80d176SSepherosa Ziehau 		mdic = E1000_READ_REG(hw, E1000_MDIC);
3199c80d176SSepherosa Ziehau 		if (mdic & E1000_MDIC_READY)
3209c80d176SSepherosa Ziehau 			break;
3219c80d176SSepherosa Ziehau 	}
3229c80d176SSepherosa Ziehau 	if (!(mdic & E1000_MDIC_READY)) {
3239c80d176SSepherosa Ziehau 		DEBUGOUT("MDI Read did not complete\n");
3244be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
3259c80d176SSepherosa Ziehau 	}
3269c80d176SSepherosa Ziehau 	if (mdic & E1000_MDIC_ERROR) {
3279c80d176SSepherosa Ziehau 		DEBUGOUT("MDI Error\n");
3284be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
3299c80d176SSepherosa Ziehau 	}
330379ebbe7SSepherosa Ziehau 	if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
331379ebbe7SSepherosa Ziehau 		DEBUGOUT2("MDI Read offset error - requested %d, returned %d\n",
332379ebbe7SSepherosa Ziehau 			  offset,
333379ebbe7SSepherosa Ziehau 			  (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
334379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
335379ebbe7SSepherosa Ziehau 	}
3369c80d176SSepherosa Ziehau 	*data = (u16) mdic;
3379c80d176SSepherosa Ziehau 
338379ebbe7SSepherosa Ziehau 	/* Allow some time after each MDIC transaction to avoid
3396a5a645eSSepherosa Ziehau 	 * reading duplicate data in the next MDIC transaction.
3406a5a645eSSepherosa Ziehau 	 */
3416a5a645eSSepherosa Ziehau 	if (hw->mac.type == e1000_pch2lan)
3424765c386SMichael Neumann 		usec_delay_irq(100);
3436a5a645eSSepherosa Ziehau 
3444be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
3459c80d176SSepherosa Ziehau }
3469c80d176SSepherosa Ziehau 
3479c80d176SSepherosa Ziehau /**
3489c80d176SSepherosa Ziehau  *  e1000_write_phy_reg_mdic - Write MDI control register
3499c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
3509c80d176SSepherosa Ziehau  *  @offset: register offset to write to
3519c80d176SSepherosa Ziehau  *  @data: data to write to register at offset
3529c80d176SSepherosa Ziehau  *
3539c80d176SSepherosa Ziehau  *  Writes data to MDI control register in the PHY at offset.
3549c80d176SSepherosa Ziehau  **/
e1000_write_phy_reg_mdic(struct e1000_hw * hw,u32 offset,u16 data)3559c80d176SSepherosa Ziehau s32 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data)
3569c80d176SSepherosa Ziehau {
3579c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
3589c80d176SSepherosa Ziehau 	u32 i, mdic = 0;
3599c80d176SSepherosa Ziehau 
3609c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_mdic");
3619c80d176SSepherosa Ziehau 
3626a5a645eSSepherosa Ziehau 	if (offset > MAX_PHY_REG_ADDRESS) {
3636a5a645eSSepherosa Ziehau 		DEBUGOUT1("PHY Address %d is out of range\n", offset);
3646a5a645eSSepherosa Ziehau 		return -E1000_ERR_PARAM;
3656a5a645eSSepherosa Ziehau 	}
3666a5a645eSSepherosa Ziehau 
367379ebbe7SSepherosa Ziehau 	/* Set up Op-code, Phy Address, and register offset in the MDI
3689c80d176SSepherosa Ziehau 	 * Control register.  The MAC will take care of interfacing with the
3699c80d176SSepherosa Ziehau 	 * PHY to retrieve the desired data.
3709c80d176SSepherosa Ziehau 	 */
3719c80d176SSepherosa Ziehau 	mdic = (((u32)data) |
3729c80d176SSepherosa Ziehau 		(offset << E1000_MDIC_REG_SHIFT) |
3739c80d176SSepherosa Ziehau 		(phy->addr << E1000_MDIC_PHY_SHIFT) |
3749c80d176SSepherosa Ziehau 		(E1000_MDIC_OP_WRITE));
3759c80d176SSepherosa Ziehau 
3769c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MDIC, mdic);
3779c80d176SSepherosa Ziehau 
378379ebbe7SSepherosa Ziehau 	/* Poll the ready bit to see if the MDI read completed
3799c80d176SSepherosa Ziehau 	 * Increasing the time out as testing showed failures with
3809c80d176SSepherosa Ziehau 	 * the lower time out
3819c80d176SSepherosa Ziehau 	 */
3829c80d176SSepherosa Ziehau 	for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) {
3834765c386SMichael Neumann 		usec_delay_irq(50);
3849c80d176SSepherosa Ziehau 		mdic = E1000_READ_REG(hw, E1000_MDIC);
3859c80d176SSepherosa Ziehau 		if (mdic & E1000_MDIC_READY)
3869c80d176SSepherosa Ziehau 			break;
3879c80d176SSepherosa Ziehau 	}
3889c80d176SSepherosa Ziehau 	if (!(mdic & E1000_MDIC_READY)) {
3899c80d176SSepherosa Ziehau 		DEBUGOUT("MDI Write did not complete\n");
3904be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
3919c80d176SSepherosa Ziehau 	}
3929c80d176SSepherosa Ziehau 	if (mdic & E1000_MDIC_ERROR) {
3939c80d176SSepherosa Ziehau 		DEBUGOUT("MDI Error\n");
3944be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
3959c80d176SSepherosa Ziehau 	}
396379ebbe7SSepherosa Ziehau 	if (((mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT) != offset) {
397379ebbe7SSepherosa Ziehau 		DEBUGOUT2("MDI Write offset error - requested %d, returned %d\n",
398379ebbe7SSepherosa Ziehau 			  offset,
399379ebbe7SSepherosa Ziehau 			  (mdic & E1000_MDIC_REG_MASK) >> E1000_MDIC_REG_SHIFT);
400379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
401379ebbe7SSepherosa Ziehau 	}
4029c80d176SSepherosa Ziehau 
403379ebbe7SSepherosa Ziehau 	/* Allow some time after each MDIC transaction to avoid
4046a5a645eSSepherosa Ziehau 	 * reading duplicate data in the next MDIC transaction.
4056a5a645eSSepherosa Ziehau 	 */
4066a5a645eSSepherosa Ziehau 	if (hw->mac.type == e1000_pch2lan)
4074765c386SMichael Neumann 		usec_delay_irq(100);
4086a5a645eSSepherosa Ziehau 
4094be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
4109c80d176SSepherosa Ziehau }
4119c80d176SSepherosa Ziehau 
4129c80d176SSepherosa Ziehau /**
41362583d18SSepherosa Ziehau  *  e1000_read_phy_reg_i2c - Read PHY register using i2c
41462583d18SSepherosa Ziehau  *  @hw: pointer to the HW structure
41562583d18SSepherosa Ziehau  *  @offset: register offset to be read
41662583d18SSepherosa Ziehau  *  @data: pointer to the read data
41762583d18SSepherosa Ziehau  *
41862583d18SSepherosa Ziehau  *  Reads the PHY register at offset using the i2c interface and stores the
41962583d18SSepherosa Ziehau  *  retrieved information in data.
42062583d18SSepherosa Ziehau  **/
e1000_read_phy_reg_i2c(struct e1000_hw * hw,u32 offset,u16 * data)42162583d18SSepherosa Ziehau s32 e1000_read_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 *data)
42262583d18SSepherosa Ziehau {
42362583d18SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
42462583d18SSepherosa Ziehau 	u32 i, i2ccmd = 0;
42562583d18SSepherosa Ziehau 
42662583d18SSepherosa Ziehau 	DEBUGFUNC("e1000_read_phy_reg_i2c");
42762583d18SSepherosa Ziehau 
428379ebbe7SSepherosa Ziehau 	/* Set up Op-code, Phy Address, and register address in the I2CCMD
42962583d18SSepherosa Ziehau 	 * register.  The MAC will take care of interfacing with the
43062583d18SSepherosa Ziehau 	 * PHY to retrieve the desired data.
43162583d18SSepherosa Ziehau 	 */
43262583d18SSepherosa Ziehau 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
43362583d18SSepherosa Ziehau 		  (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
43462583d18SSepherosa Ziehau 		  (E1000_I2CCMD_OPCODE_READ));
43562583d18SSepherosa Ziehau 
43662583d18SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
43762583d18SSepherosa Ziehau 
43862583d18SSepherosa Ziehau 	/* Poll the ready bit to see if the I2C read completed */
43962583d18SSepherosa Ziehau 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
44062583d18SSepherosa Ziehau 		usec_delay(50);
44162583d18SSepherosa Ziehau 		i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
44262583d18SSepherosa Ziehau 		if (i2ccmd & E1000_I2CCMD_READY)
44362583d18SSepherosa Ziehau 			break;
44462583d18SSepherosa Ziehau 	}
44562583d18SSepherosa Ziehau 	if (!(i2ccmd & E1000_I2CCMD_READY)) {
44662583d18SSepherosa Ziehau 		DEBUGOUT("I2CCMD Read did not complete\n");
44762583d18SSepherosa Ziehau 		return -E1000_ERR_PHY;
44862583d18SSepherosa Ziehau 	}
44962583d18SSepherosa Ziehau 	if (i2ccmd & E1000_I2CCMD_ERROR) {
45062583d18SSepherosa Ziehau 		DEBUGOUT("I2CCMD Error bit set\n");
45162583d18SSepherosa Ziehau 		return -E1000_ERR_PHY;
45262583d18SSepherosa Ziehau 	}
45362583d18SSepherosa Ziehau 
45462583d18SSepherosa Ziehau 	/* Need to byte-swap the 16-bit value. */
45562583d18SSepherosa Ziehau 	*data = ((i2ccmd >> 8) & 0x00FF) | ((i2ccmd << 8) & 0xFF00);
45662583d18SSepherosa Ziehau 
45762583d18SSepherosa Ziehau 	return E1000_SUCCESS;
45862583d18SSepherosa Ziehau }
45962583d18SSepherosa Ziehau 
46062583d18SSepherosa Ziehau /**
46162583d18SSepherosa Ziehau  *  e1000_write_phy_reg_i2c - Write PHY register using i2c
46262583d18SSepherosa Ziehau  *  @hw: pointer to the HW structure
46362583d18SSepherosa Ziehau  *  @offset: register offset to write to
46462583d18SSepherosa Ziehau  *  @data: data to write at register offset
46562583d18SSepherosa Ziehau  *
46662583d18SSepherosa Ziehau  *  Writes the data to PHY register at the offset using the i2c interface.
46762583d18SSepherosa Ziehau  **/
e1000_write_phy_reg_i2c(struct e1000_hw * hw,u32 offset,u16 data)46862583d18SSepherosa Ziehau s32 e1000_write_phy_reg_i2c(struct e1000_hw *hw, u32 offset, u16 data)
46962583d18SSepherosa Ziehau {
47062583d18SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
47162583d18SSepherosa Ziehau 	u32 i, i2ccmd = 0;
47262583d18SSepherosa Ziehau 	u16 phy_data_swapped;
47362583d18SSepherosa Ziehau 
47462583d18SSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_i2c");
47562583d18SSepherosa Ziehau 
4764be59a01SSepherosa Ziehau 	/* Prevent overwritting SFP I2C EEPROM which is at A0 address.*/
4774be59a01SSepherosa Ziehau 	if ((hw->phy.addr == 0) || (hw->phy.addr > 7)) {
4784be59a01SSepherosa Ziehau 		DEBUGOUT1("PHY I2C Address %d is out of range.\n",
4794be59a01SSepherosa Ziehau 			  hw->phy.addr);
4804be59a01SSepherosa Ziehau 		return -E1000_ERR_CONFIG;
4814be59a01SSepherosa Ziehau 	}
4824be59a01SSepherosa Ziehau 
48362583d18SSepherosa Ziehau 	/* Swap the data bytes for the I2C interface */
48462583d18SSepherosa Ziehau 	phy_data_swapped = ((data >> 8) & 0x00FF) | ((data << 8) & 0xFF00);
48562583d18SSepherosa Ziehau 
486379ebbe7SSepherosa Ziehau 	/* Set up Op-code, Phy Address, and register address in the I2CCMD
48762583d18SSepherosa Ziehau 	 * register.  The MAC will take care of interfacing with the
48862583d18SSepherosa Ziehau 	 * PHY to retrieve the desired data.
48962583d18SSepherosa Ziehau 	 */
49062583d18SSepherosa Ziehau 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
49162583d18SSepherosa Ziehau 		  (phy->addr << E1000_I2CCMD_PHY_ADDR_SHIFT) |
49262583d18SSepherosa Ziehau 		  E1000_I2CCMD_OPCODE_WRITE |
49362583d18SSepherosa Ziehau 		  phy_data_swapped);
49462583d18SSepherosa Ziehau 
49562583d18SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
49662583d18SSepherosa Ziehau 
49762583d18SSepherosa Ziehau 	/* Poll the ready bit to see if the I2C read completed */
49862583d18SSepherosa Ziehau 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
49962583d18SSepherosa Ziehau 		usec_delay(50);
50062583d18SSepherosa Ziehau 		i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
50162583d18SSepherosa Ziehau 		if (i2ccmd & E1000_I2CCMD_READY)
50262583d18SSepherosa Ziehau 			break;
50362583d18SSepherosa Ziehau 	}
50462583d18SSepherosa Ziehau 	if (!(i2ccmd & E1000_I2CCMD_READY)) {
50562583d18SSepherosa Ziehau 		DEBUGOUT("I2CCMD Write did not complete\n");
50662583d18SSepherosa Ziehau 		return -E1000_ERR_PHY;
50762583d18SSepherosa Ziehau 	}
50862583d18SSepherosa Ziehau 	if (i2ccmd & E1000_I2CCMD_ERROR) {
50962583d18SSepherosa Ziehau 		DEBUGOUT("I2CCMD Error bit set\n");
51062583d18SSepherosa Ziehau 		return -E1000_ERR_PHY;
51162583d18SSepherosa Ziehau 	}
51262583d18SSepherosa Ziehau 
51362583d18SSepherosa Ziehau 	return E1000_SUCCESS;
51462583d18SSepherosa Ziehau }
51562583d18SSepherosa Ziehau 
51662583d18SSepherosa Ziehau /**
5174be59a01SSepherosa Ziehau  *  e1000_read_sfp_data_byte - Reads SFP module data.
5184be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
5194be59a01SSepherosa Ziehau  *  @offset: byte location offset to be read
5204be59a01SSepherosa Ziehau  *  @data: read data buffer pointer
5214be59a01SSepherosa Ziehau  *
5224be59a01SSepherosa Ziehau  *  Reads one byte from SFP module data stored
5234be59a01SSepherosa Ziehau  *  in SFP resided EEPROM memory or SFP diagnostic area.
5244be59a01SSepherosa Ziehau  *  Function should be called with
5254be59a01SSepherosa Ziehau  *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
5264be59a01SSepherosa Ziehau  *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
5274be59a01SSepherosa Ziehau  *  access
5284be59a01SSepherosa Ziehau  **/
e1000_read_sfp_data_byte(struct e1000_hw * hw,u16 offset,u8 * data)5294be59a01SSepherosa Ziehau s32 e1000_read_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 *data)
5304be59a01SSepherosa Ziehau {
5314be59a01SSepherosa Ziehau 	u32 i = 0;
5324be59a01SSepherosa Ziehau 	u32 i2ccmd = 0;
5334be59a01SSepherosa Ziehau 	u32 data_local = 0;
5344be59a01SSepherosa Ziehau 
5354be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_read_sfp_data_byte");
5364be59a01SSepherosa Ziehau 
5374be59a01SSepherosa Ziehau 	if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
5384be59a01SSepherosa Ziehau 		DEBUGOUT("I2CCMD command address exceeds upper limit\n");
5394be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
5404be59a01SSepherosa Ziehau 	}
5414be59a01SSepherosa Ziehau 
542379ebbe7SSepherosa Ziehau 	/* Set up Op-code, EEPROM Address,in the I2CCMD
5434be59a01SSepherosa Ziehau 	 * register. The MAC will take care of interfacing with the
5444be59a01SSepherosa Ziehau 	 * EEPROM to retrieve the desired data.
5454be59a01SSepherosa Ziehau 	 */
5464be59a01SSepherosa Ziehau 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
5474be59a01SSepherosa Ziehau 		  E1000_I2CCMD_OPCODE_READ);
5484be59a01SSepherosa Ziehau 
5494be59a01SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
5504be59a01SSepherosa Ziehau 
5514be59a01SSepherosa Ziehau 	/* Poll the ready bit to see if the I2C read completed */
5524be59a01SSepherosa Ziehau 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
5534be59a01SSepherosa Ziehau 		usec_delay(50);
5544be59a01SSepherosa Ziehau 		data_local = E1000_READ_REG(hw, E1000_I2CCMD);
5554be59a01SSepherosa Ziehau 		if (data_local & E1000_I2CCMD_READY)
5564be59a01SSepherosa Ziehau 			break;
5574be59a01SSepherosa Ziehau 	}
5584be59a01SSepherosa Ziehau 	if (!(data_local & E1000_I2CCMD_READY)) {
5594be59a01SSepherosa Ziehau 		DEBUGOUT("I2CCMD Read did not complete\n");
5604be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
5614be59a01SSepherosa Ziehau 	}
5624be59a01SSepherosa Ziehau 	if (data_local & E1000_I2CCMD_ERROR) {
5634be59a01SSepherosa Ziehau 		DEBUGOUT("I2CCMD Error bit set\n");
5644be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
5654be59a01SSepherosa Ziehau 	}
5664be59a01SSepherosa Ziehau 	*data = (u8) data_local & 0xFF;
5674be59a01SSepherosa Ziehau 
5684be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
5694be59a01SSepherosa Ziehau }
5704be59a01SSepherosa Ziehau 
5714be59a01SSepherosa Ziehau /**
5724be59a01SSepherosa Ziehau  *  e1000_write_sfp_data_byte - Writes SFP module data.
5734be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
5744be59a01SSepherosa Ziehau  *  @offset: byte location offset to write to
5754be59a01SSepherosa Ziehau  *  @data: data to write
5764be59a01SSepherosa Ziehau  *
5774be59a01SSepherosa Ziehau  *  Writes one byte to SFP module data stored
5784be59a01SSepherosa Ziehau  *  in SFP resided EEPROM memory or SFP diagnostic area.
5794be59a01SSepherosa Ziehau  *  Function should be called with
5804be59a01SSepherosa Ziehau  *  E1000_I2CCMD_SFP_DATA_ADDR(<byte offset>) for SFP module database access
5814be59a01SSepherosa Ziehau  *  E1000_I2CCMD_SFP_DIAG_ADDR(<byte offset>) for SFP diagnostics parameters
5824be59a01SSepherosa Ziehau  *  access
5834be59a01SSepherosa Ziehau  **/
e1000_write_sfp_data_byte(struct e1000_hw * hw,u16 offset,u8 data)5844be59a01SSepherosa Ziehau s32 e1000_write_sfp_data_byte(struct e1000_hw *hw, u16 offset, u8 data)
5854be59a01SSepherosa Ziehau {
5864be59a01SSepherosa Ziehau 	u32 i = 0;
5874be59a01SSepherosa Ziehau 	u32 i2ccmd = 0;
5884be59a01SSepherosa Ziehau 	u32 data_local = 0;
5894be59a01SSepherosa Ziehau 
5904be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_write_sfp_data_byte");
5914be59a01SSepherosa Ziehau 
5924be59a01SSepherosa Ziehau 	if (offset > E1000_I2CCMD_SFP_DIAG_ADDR(255)) {
5934be59a01SSepherosa Ziehau 		DEBUGOUT("I2CCMD command address exceeds upper limit\n");
5944be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
5954be59a01SSepherosa Ziehau 	}
596379ebbe7SSepherosa Ziehau 	/* The programming interface is 16 bits wide
5974be59a01SSepherosa Ziehau 	 * so we need to read the whole word first
5984be59a01SSepherosa Ziehau 	 * then update appropriate byte lane and write
5994be59a01SSepherosa Ziehau 	 * the updated word back.
6004be59a01SSepherosa Ziehau 	 */
601379ebbe7SSepherosa Ziehau 	/* Set up Op-code, EEPROM Address,in the I2CCMD
6024be59a01SSepherosa Ziehau 	 * register. The MAC will take care of interfacing
6034be59a01SSepherosa Ziehau 	 * with an EEPROM to write the data given.
6044be59a01SSepherosa Ziehau 	 */
6054be59a01SSepherosa Ziehau 	i2ccmd = ((offset << E1000_I2CCMD_REG_ADDR_SHIFT) |
6064be59a01SSepherosa Ziehau 		  E1000_I2CCMD_OPCODE_READ);
6074be59a01SSepherosa Ziehau 	/* Set a command to read single word */
6084be59a01SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
6094be59a01SSepherosa Ziehau 	for (i = 0; i < E1000_I2CCMD_PHY_TIMEOUT; i++) {
6104be59a01SSepherosa Ziehau 		usec_delay(50);
611379ebbe7SSepherosa Ziehau 		/* Poll the ready bit to see if lastly
6124be59a01SSepherosa Ziehau 		 * launched I2C operation completed
6134be59a01SSepherosa Ziehau 		 */
6144be59a01SSepherosa Ziehau 		i2ccmd = E1000_READ_REG(hw, E1000_I2CCMD);
6154be59a01SSepherosa Ziehau 		if (i2ccmd & E1000_I2CCMD_READY) {
6164be59a01SSepherosa Ziehau 			/* Check if this is READ or WRITE phase */
6174be59a01SSepherosa Ziehau 			if ((i2ccmd & E1000_I2CCMD_OPCODE_READ) ==
6184be59a01SSepherosa Ziehau 			    E1000_I2CCMD_OPCODE_READ) {
619379ebbe7SSepherosa Ziehau 				/* Write the selected byte
6204be59a01SSepherosa Ziehau 				 * lane and update whole word
6214be59a01SSepherosa Ziehau 				 */
6224be59a01SSepherosa Ziehau 				data_local = i2ccmd & 0xFF00;
6234be59a01SSepherosa Ziehau 				data_local |= data;
6244be59a01SSepherosa Ziehau 				i2ccmd = ((offset <<
6254be59a01SSepherosa Ziehau 					E1000_I2CCMD_REG_ADDR_SHIFT) |
6264be59a01SSepherosa Ziehau 					E1000_I2CCMD_OPCODE_WRITE | data_local);
6274be59a01SSepherosa Ziehau 				E1000_WRITE_REG(hw, E1000_I2CCMD, i2ccmd);
6284be59a01SSepherosa Ziehau 			} else {
6294be59a01SSepherosa Ziehau 				break;
6304be59a01SSepherosa Ziehau 			}
6314be59a01SSepherosa Ziehau 		}
6324be59a01SSepherosa Ziehau 	}
6334be59a01SSepherosa Ziehau 	if (!(i2ccmd & E1000_I2CCMD_READY)) {
6344be59a01SSepherosa Ziehau 		DEBUGOUT("I2CCMD Write did not complete\n");
6354be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
6364be59a01SSepherosa Ziehau 	}
6374be59a01SSepherosa Ziehau 	if (i2ccmd & E1000_I2CCMD_ERROR) {
6384be59a01SSepherosa Ziehau 		DEBUGOUT("I2CCMD Error bit set\n");
6394be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
6404be59a01SSepherosa Ziehau 	}
6414be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
6424be59a01SSepherosa Ziehau }
6434be59a01SSepherosa Ziehau 
6444be59a01SSepherosa Ziehau /**
6459c80d176SSepherosa Ziehau  *  e1000_read_phy_reg_m88 - Read m88 PHY register
6469c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
6479c80d176SSepherosa Ziehau  *  @offset: register offset to be read
6489c80d176SSepherosa Ziehau  *  @data: pointer to the read data
6499c80d176SSepherosa Ziehau  *
6509c80d176SSepherosa Ziehau  *  Acquires semaphore, if necessary, then reads the PHY register at offset
6519c80d176SSepherosa Ziehau  *  and storing the retrieved information in data.  Release any acquired
6529c80d176SSepherosa Ziehau  *  semaphores before exiting.
6539c80d176SSepherosa Ziehau  **/
e1000_read_phy_reg_m88(struct e1000_hw * hw,u32 offset,u16 * data)6549c80d176SSepherosa Ziehau s32 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data)
6559c80d176SSepherosa Ziehau {
6564be59a01SSepherosa Ziehau 	s32 ret_val;
6579c80d176SSepherosa Ziehau 
6589c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_read_phy_reg_m88");
6599c80d176SSepherosa Ziehau 
6604be59a01SSepherosa Ziehau 	if (!hw->phy.ops.acquire)
6614be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
6629c80d176SSepherosa Ziehau 
6639c80d176SSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
6649c80d176SSepherosa Ziehau 	if (ret_val)
6654be59a01SSepherosa Ziehau 		return ret_val;
6669c80d176SSepherosa Ziehau 
6679c80d176SSepherosa Ziehau 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
6689c80d176SSepherosa Ziehau 					  data);
6699c80d176SSepherosa Ziehau 
6709c80d176SSepherosa Ziehau 	hw->phy.ops.release(hw);
6719c80d176SSepherosa Ziehau 
6729c80d176SSepherosa Ziehau 	return ret_val;
6739c80d176SSepherosa Ziehau }
6749c80d176SSepherosa Ziehau 
6759c80d176SSepherosa Ziehau /**
6769c80d176SSepherosa Ziehau  *  e1000_write_phy_reg_m88 - Write m88 PHY register
6779c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
6789c80d176SSepherosa Ziehau  *  @offset: register offset to write to
6799c80d176SSepherosa Ziehau  *  @data: data to write at register offset
6809c80d176SSepherosa Ziehau  *
6819c80d176SSepherosa Ziehau  *  Acquires semaphore, if necessary, then writes the data to PHY register
6829c80d176SSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
6839c80d176SSepherosa Ziehau  **/
e1000_write_phy_reg_m88(struct e1000_hw * hw,u32 offset,u16 data)6849c80d176SSepherosa Ziehau s32 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data)
6859c80d176SSepherosa Ziehau {
6864be59a01SSepherosa Ziehau 	s32 ret_val;
6879c80d176SSepherosa Ziehau 
6889c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_m88");
6899c80d176SSepherosa Ziehau 
6904be59a01SSepherosa Ziehau 	if (!hw->phy.ops.acquire)
6914be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
6929c80d176SSepherosa Ziehau 
6939c80d176SSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
6949c80d176SSepherosa Ziehau 	if (ret_val)
6954be59a01SSepherosa Ziehau 		return ret_val;
6969c80d176SSepherosa Ziehau 
6979c80d176SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
6989c80d176SSepherosa Ziehau 					   data);
6999c80d176SSepherosa Ziehau 
7009c80d176SSepherosa Ziehau 	hw->phy.ops.release(hw);
7019c80d176SSepherosa Ziehau 
7029c80d176SSepherosa Ziehau 	return ret_val;
7039c80d176SSepherosa Ziehau }
7049c80d176SSepherosa Ziehau 
7059c80d176SSepherosa Ziehau /**
7066d5e2922SSepherosa Ziehau  *  e1000_set_page_igp - Set page as on IGP-like PHY(s)
7076d5e2922SSepherosa Ziehau  *  @hw: pointer to the HW structure
7086d5e2922SSepherosa Ziehau  *  @page: page to set (shifted left when necessary)
7096d5e2922SSepherosa Ziehau  *
7106d5e2922SSepherosa Ziehau  *  Sets PHY page required for PHY register access.  Assumes semaphore is
7116d5e2922SSepherosa Ziehau  *  already acquired.  Note, this function sets phy.addr to 1 so the caller
7126d5e2922SSepherosa Ziehau  *  must set it appropriately (if necessary) after this function returns.
7136d5e2922SSepherosa Ziehau  **/
e1000_set_page_igp(struct e1000_hw * hw,u16 page)7146d5e2922SSepherosa Ziehau s32 e1000_set_page_igp(struct e1000_hw *hw, u16 page)
7156d5e2922SSepherosa Ziehau {
7166d5e2922SSepherosa Ziehau 	DEBUGFUNC("e1000_set_page_igp");
7176d5e2922SSepherosa Ziehau 
7186d5e2922SSepherosa Ziehau 	DEBUGOUT1("Setting page 0x%x\n", page);
7196d5e2922SSepherosa Ziehau 
7206d5e2922SSepherosa Ziehau 	hw->phy.addr = 1;
7216d5e2922SSepherosa Ziehau 
7226d5e2922SSepherosa Ziehau 	return e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, page);
7236d5e2922SSepherosa Ziehau }
7246d5e2922SSepherosa Ziehau 
7256d5e2922SSepherosa Ziehau /**
7266a5a645eSSepherosa Ziehau  *  __e1000_read_phy_reg_igp - Read igp PHY register
7279c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
7289c80d176SSepherosa Ziehau  *  @offset: register offset to be read
7299c80d176SSepherosa Ziehau  *  @data: pointer to the read data
7306a5a645eSSepherosa Ziehau  *  @locked: semaphore has already been acquired or not
7319c80d176SSepherosa Ziehau  *
7329c80d176SSepherosa Ziehau  *  Acquires semaphore, if necessary, then reads the PHY register at offset
7336a5a645eSSepherosa Ziehau  *  and stores the retrieved information in data.  Release any acquired
7349c80d176SSepherosa Ziehau  *  semaphores before exiting.
7359c80d176SSepherosa Ziehau  **/
__e1000_read_phy_reg_igp(struct e1000_hw * hw,u32 offset,u16 * data,bool locked)7366a5a645eSSepherosa Ziehau static s32 __e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data,
7376a5a645eSSepherosa Ziehau 				    bool locked)
7389c80d176SSepherosa Ziehau {
7399c80d176SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
7409c80d176SSepherosa Ziehau 
7416a5a645eSSepherosa Ziehau 	DEBUGFUNC("__e1000_read_phy_reg_igp");
7429c80d176SSepherosa Ziehau 
7436a5a645eSSepherosa Ziehau 	if (!locked) {
7444be59a01SSepherosa Ziehau 		if (!hw->phy.ops.acquire)
7454be59a01SSepherosa Ziehau 			return E1000_SUCCESS;
7469c80d176SSepherosa Ziehau 
7479c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.acquire(hw);
7489c80d176SSepherosa Ziehau 		if (ret_val)
7494be59a01SSepherosa Ziehau 			return ret_val;
7506a5a645eSSepherosa Ziehau 	}
7519c80d176SSepherosa Ziehau 
7524be59a01SSepherosa Ziehau 	if (offset > MAX_PHY_MULTI_PAGE_REG)
7539c80d176SSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw,
7549c80d176SSepherosa Ziehau 						   IGP01E1000_PHY_PAGE_SELECT,
7559c80d176SSepherosa Ziehau 						   (u16)offset);
7564be59a01SSepherosa Ziehau 	if (!ret_val)
7574be59a01SSepherosa Ziehau 		ret_val = e1000_read_phy_reg_mdic(hw,
7584be59a01SSepherosa Ziehau 						  MAX_PHY_REG_ADDRESS & offset,
7599c80d176SSepherosa Ziehau 						  data);
7606a5a645eSSepherosa Ziehau 	if (!locked)
7616a5a645eSSepherosa Ziehau 		hw->phy.ops.release(hw);
7624be59a01SSepherosa Ziehau 
7636a5a645eSSepherosa Ziehau 	return ret_val;
7646a5a645eSSepherosa Ziehau }
7656a5a645eSSepherosa Ziehau 
7666a5a645eSSepherosa Ziehau /**
7676a5a645eSSepherosa Ziehau  *  e1000_read_phy_reg_igp - Read igp PHY register
7686a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
7696a5a645eSSepherosa Ziehau  *  @offset: register offset to be read
7706a5a645eSSepherosa Ziehau  *  @data: pointer to the read data
7716a5a645eSSepherosa Ziehau  *
7726a5a645eSSepherosa Ziehau  *  Acquires semaphore then reads the PHY register at offset and stores the
7736a5a645eSSepherosa Ziehau  *  retrieved information in data.
7746a5a645eSSepherosa Ziehau  *  Release the acquired semaphore before exiting.
7756a5a645eSSepherosa Ziehau  **/
e1000_read_phy_reg_igp(struct e1000_hw * hw,u32 offset,u16 * data)7766a5a645eSSepherosa Ziehau s32 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data)
7776a5a645eSSepherosa Ziehau {
7786a5a645eSSepherosa Ziehau 	return __e1000_read_phy_reg_igp(hw, offset, data, FALSE);
7796a5a645eSSepherosa Ziehau }
7806a5a645eSSepherosa Ziehau 
7816a5a645eSSepherosa Ziehau /**
7826a5a645eSSepherosa Ziehau  *  e1000_read_phy_reg_igp_locked - Read igp PHY register
7836a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
7846a5a645eSSepherosa Ziehau  *  @offset: register offset to be read
7856a5a645eSSepherosa Ziehau  *  @data: pointer to the read data
7866a5a645eSSepherosa Ziehau  *
7876a5a645eSSepherosa Ziehau  *  Reads the PHY register at offset and stores the retrieved information
7886a5a645eSSepherosa Ziehau  *  in data.  Assumes semaphore already acquired.
7896a5a645eSSepherosa Ziehau  **/
e1000_read_phy_reg_igp_locked(struct e1000_hw * hw,u32 offset,u16 * data)7906a5a645eSSepherosa Ziehau s32 e1000_read_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 *data)
7916a5a645eSSepherosa Ziehau {
7926a5a645eSSepherosa Ziehau 	return __e1000_read_phy_reg_igp(hw, offset, data, TRUE);
7936a5a645eSSepherosa Ziehau }
7946a5a645eSSepherosa Ziehau 
7956a5a645eSSepherosa Ziehau /**
7966a5a645eSSepherosa Ziehau  *  e1000_write_phy_reg_igp - Write igp PHY register
7976a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
7986a5a645eSSepherosa Ziehau  *  @offset: register offset to write to
7996a5a645eSSepherosa Ziehau  *  @data: data to write at register offset
8006a5a645eSSepherosa Ziehau  *  @locked: semaphore has already been acquired or not
8016a5a645eSSepherosa Ziehau  *
8026a5a645eSSepherosa Ziehau  *  Acquires semaphore, if necessary, then writes the data to PHY register
8036a5a645eSSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
8046a5a645eSSepherosa Ziehau  **/
__e1000_write_phy_reg_igp(struct e1000_hw * hw,u32 offset,u16 data,bool locked)8056a5a645eSSepherosa Ziehau static s32 __e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data,
8066a5a645eSSepherosa Ziehau 				     bool locked)
8076a5a645eSSepherosa Ziehau {
8086a5a645eSSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
8096a5a645eSSepherosa Ziehau 
8106a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_igp");
8116a5a645eSSepherosa Ziehau 
8126a5a645eSSepherosa Ziehau 	if (!locked) {
8134be59a01SSepherosa Ziehau 		if (!hw->phy.ops.acquire)
8144be59a01SSepherosa Ziehau 			return E1000_SUCCESS;
8156a5a645eSSepherosa Ziehau 
8166a5a645eSSepherosa Ziehau 		ret_val = hw->phy.ops.acquire(hw);
8176a5a645eSSepherosa Ziehau 		if (ret_val)
8184be59a01SSepherosa Ziehau 			return ret_val;
8196a5a645eSSepherosa Ziehau 	}
8206a5a645eSSepherosa Ziehau 
8214be59a01SSepherosa Ziehau 	if (offset > MAX_PHY_MULTI_PAGE_REG)
8226a5a645eSSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw,
8236a5a645eSSepherosa Ziehau 						   IGP01E1000_PHY_PAGE_SELECT,
8246a5a645eSSepherosa Ziehau 						   (u16)offset);
8254be59a01SSepherosa Ziehau 	if (!ret_val)
8264be59a01SSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS &
8274be59a01SSepherosa Ziehau 						       offset,
8286a5a645eSSepherosa Ziehau 						   data);
8296a5a645eSSepherosa Ziehau 	if (!locked)
8309c80d176SSepherosa Ziehau 		hw->phy.ops.release(hw);
8319c80d176SSepherosa Ziehau 
8329c80d176SSepherosa Ziehau 	return ret_val;
8339c80d176SSepherosa Ziehau }
8349c80d176SSepherosa Ziehau 
8359c80d176SSepherosa Ziehau /**
8369c80d176SSepherosa Ziehau  *  e1000_write_phy_reg_igp - Write igp PHY register
8379c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
8389c80d176SSepherosa Ziehau  *  @offset: register offset to write to
8399c80d176SSepherosa Ziehau  *  @data: data to write at register offset
8409c80d176SSepherosa Ziehau  *
8416a5a645eSSepherosa Ziehau  *  Acquires semaphore then writes the data to PHY register
8429c80d176SSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
8439c80d176SSepherosa Ziehau  **/
e1000_write_phy_reg_igp(struct e1000_hw * hw,u32 offset,u16 data)8449c80d176SSepherosa Ziehau s32 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data)
8459c80d176SSepherosa Ziehau {
8466a5a645eSSepherosa Ziehau 	return __e1000_write_phy_reg_igp(hw, offset, data, FALSE);
8476a5a645eSSepherosa Ziehau }
8486a5a645eSSepherosa Ziehau 
8496a5a645eSSepherosa Ziehau /**
8506a5a645eSSepherosa Ziehau  *  e1000_write_phy_reg_igp_locked - Write igp PHY register
8516a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
8526a5a645eSSepherosa Ziehau  *  @offset: register offset to write to
8536a5a645eSSepherosa Ziehau  *  @data: data to write at register offset
8546a5a645eSSepherosa Ziehau  *
8556a5a645eSSepherosa Ziehau  *  Writes the data to PHY register at the offset.
8566a5a645eSSepherosa Ziehau  *  Assumes semaphore already acquired.
8576a5a645eSSepherosa Ziehau  **/
e1000_write_phy_reg_igp_locked(struct e1000_hw * hw,u32 offset,u16 data)8586a5a645eSSepherosa Ziehau s32 e1000_write_phy_reg_igp_locked(struct e1000_hw *hw, u32 offset, u16 data)
8596a5a645eSSepherosa Ziehau {
8606a5a645eSSepherosa Ziehau 	return __e1000_write_phy_reg_igp(hw, offset, data, TRUE);
8616a5a645eSSepherosa Ziehau }
8626a5a645eSSepherosa Ziehau 
8636a5a645eSSepherosa Ziehau /**
8646a5a645eSSepherosa Ziehau  *  __e1000_read_kmrn_reg - Read kumeran register
8656a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
8666a5a645eSSepherosa Ziehau  *  @offset: register offset to be read
8676a5a645eSSepherosa Ziehau  *  @data: pointer to the read data
8686a5a645eSSepherosa Ziehau  *  @locked: semaphore has already been acquired or not
8696a5a645eSSepherosa Ziehau  *
8706a5a645eSSepherosa Ziehau  *  Acquires semaphore, if necessary.  Then reads the PHY register at offset
8716a5a645eSSepherosa Ziehau  *  using the kumeran interface.  The information retrieved is stored in data.
8726a5a645eSSepherosa Ziehau  *  Release any acquired semaphores before exiting.
8736a5a645eSSepherosa Ziehau  **/
__e1000_read_kmrn_reg(struct e1000_hw * hw,u32 offset,u16 * data,bool locked)8746a5a645eSSepherosa Ziehau static s32 __e1000_read_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 *data,
8756a5a645eSSepherosa Ziehau 				 bool locked)
8766a5a645eSSepherosa Ziehau {
8776a5a645eSSepherosa Ziehau 	u32 kmrnctrlsta;
8789c80d176SSepherosa Ziehau 
8796a5a645eSSepherosa Ziehau 	DEBUGFUNC("__e1000_read_kmrn_reg");
8809c80d176SSepherosa Ziehau 
8816a5a645eSSepherosa Ziehau 	if (!locked) {
8824be59a01SSepherosa Ziehau 		s32 ret_val = E1000_SUCCESS;
8834be59a01SSepherosa Ziehau 
8844be59a01SSepherosa Ziehau 		if (!hw->phy.ops.acquire)
8854be59a01SSepherosa Ziehau 			return E1000_SUCCESS;
8869c80d176SSepherosa Ziehau 
8879c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.acquire(hw);
8889c80d176SSepherosa Ziehau 		if (ret_val)
8894be59a01SSepherosa Ziehau 			return ret_val;
8909c80d176SSepherosa Ziehau 	}
8919c80d176SSepherosa Ziehau 
8926a5a645eSSepherosa Ziehau 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
8936a5a645eSSepherosa Ziehau 		       E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN;
8946a5a645eSSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
8954be59a01SSepherosa Ziehau 	E1000_WRITE_FLUSH(hw);
8969c80d176SSepherosa Ziehau 
8976a5a645eSSepherosa Ziehau 	usec_delay(2);
8986a5a645eSSepherosa Ziehau 
8996a5a645eSSepherosa Ziehau 	kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA);
9006a5a645eSSepherosa Ziehau 	*data = (u16)kmrnctrlsta;
9016a5a645eSSepherosa Ziehau 
9026a5a645eSSepherosa Ziehau 	if (!locked)
9039c80d176SSepherosa Ziehau 		hw->phy.ops.release(hw);
9049c80d176SSepherosa Ziehau 
9054be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
9069c80d176SSepherosa Ziehau }
9079c80d176SSepherosa Ziehau 
9089c80d176SSepherosa Ziehau /**
9099c80d176SSepherosa Ziehau  *  e1000_read_kmrn_reg_generic -  Read kumeran register
9109c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
9119c80d176SSepherosa Ziehau  *  @offset: register offset to be read
9129c80d176SSepherosa Ziehau  *  @data: pointer to the read data
9139c80d176SSepherosa Ziehau  *
9146a5a645eSSepherosa Ziehau  *  Acquires semaphore then reads the PHY register at offset using the
9156a5a645eSSepherosa Ziehau  *  kumeran interface.  The information retrieved is stored in data.
9166a5a645eSSepherosa Ziehau  *  Release the acquired semaphore before exiting.
9179c80d176SSepherosa Ziehau  **/
e1000_read_kmrn_reg_generic(struct e1000_hw * hw,u32 offset,u16 * data)9189c80d176SSepherosa Ziehau s32 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data)
9199c80d176SSepherosa Ziehau {
9206a5a645eSSepherosa Ziehau 	return __e1000_read_kmrn_reg(hw, offset, data, FALSE);
9216a5a645eSSepherosa Ziehau }
9226a5a645eSSepherosa Ziehau 
9236a5a645eSSepherosa Ziehau /**
9246a5a645eSSepherosa Ziehau  *  e1000_read_kmrn_reg_locked -  Read kumeran register
9256a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
9266a5a645eSSepherosa Ziehau  *  @offset: register offset to be read
9276a5a645eSSepherosa Ziehau  *  @data: pointer to the read data
9286a5a645eSSepherosa Ziehau  *
9296a5a645eSSepherosa Ziehau  *  Reads the PHY register at offset using the kumeran interface.  The
9306a5a645eSSepherosa Ziehau  *  information retrieved is stored in data.
9316a5a645eSSepherosa Ziehau  *  Assumes semaphore already acquired.
9326a5a645eSSepherosa Ziehau  **/
e1000_read_kmrn_reg_locked(struct e1000_hw * hw,u32 offset,u16 * data)9336a5a645eSSepherosa Ziehau s32 e1000_read_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 *data)
9346a5a645eSSepherosa Ziehau {
9356a5a645eSSepherosa Ziehau 	return __e1000_read_kmrn_reg(hw, offset, data, TRUE);
9366a5a645eSSepherosa Ziehau }
9376a5a645eSSepherosa Ziehau 
9386a5a645eSSepherosa Ziehau /**
9396a5a645eSSepherosa Ziehau  *  __e1000_write_kmrn_reg - Write kumeran register
9406a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
9416a5a645eSSepherosa Ziehau  *  @offset: register offset to write to
9426a5a645eSSepherosa Ziehau  *  @data: data to write at register offset
9436a5a645eSSepherosa Ziehau  *  @locked: semaphore has already been acquired or not
9446a5a645eSSepherosa Ziehau  *
9456a5a645eSSepherosa Ziehau  *  Acquires semaphore, if necessary.  Then write the data to PHY register
9466a5a645eSSepherosa Ziehau  *  at the offset using the kumeran interface.  Release any acquired semaphores
9476a5a645eSSepherosa Ziehau  *  before exiting.
9486a5a645eSSepherosa Ziehau  **/
__e1000_write_kmrn_reg(struct e1000_hw * hw,u32 offset,u16 data,bool locked)9496a5a645eSSepherosa Ziehau static s32 __e1000_write_kmrn_reg(struct e1000_hw *hw, u32 offset, u16 data,
9506a5a645eSSepherosa Ziehau 				  bool locked)
9516a5a645eSSepherosa Ziehau {
9529c80d176SSepherosa Ziehau 	u32 kmrnctrlsta;
9539c80d176SSepherosa Ziehau 
9546a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_write_kmrn_reg_generic");
9559c80d176SSepherosa Ziehau 
9566a5a645eSSepherosa Ziehau 	if (!locked) {
9574be59a01SSepherosa Ziehau 		s32 ret_val = E1000_SUCCESS;
9584be59a01SSepherosa Ziehau 
9594be59a01SSepherosa Ziehau 		if (!hw->phy.ops.acquire)
9604be59a01SSepherosa Ziehau 			return E1000_SUCCESS;
9619c80d176SSepherosa Ziehau 
9629c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.acquire(hw);
9639c80d176SSepherosa Ziehau 		if (ret_val)
9644be59a01SSepherosa Ziehau 			return ret_val;
9656a5a645eSSepherosa Ziehau 	}
9669c80d176SSepherosa Ziehau 
9679c80d176SSepherosa Ziehau 	kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) &
9686a5a645eSSepherosa Ziehau 		       E1000_KMRNCTRLSTA_OFFSET) | data;
9699c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta);
9704be59a01SSepherosa Ziehau 	E1000_WRITE_FLUSH(hw);
9719c80d176SSepherosa Ziehau 
9729c80d176SSepherosa Ziehau 	usec_delay(2);
9739c80d176SSepherosa Ziehau 
9746a5a645eSSepherosa Ziehau 	if (!locked)
9759c80d176SSepherosa Ziehau 		hw->phy.ops.release(hw);
9769c80d176SSepherosa Ziehau 
9774be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
9789c80d176SSepherosa Ziehau }
9799c80d176SSepherosa Ziehau 
9809c80d176SSepherosa Ziehau /**
9819c80d176SSepherosa Ziehau  *  e1000_write_kmrn_reg_generic -  Write kumeran register
9829c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
9839c80d176SSepherosa Ziehau  *  @offset: register offset to write to
9849c80d176SSepherosa Ziehau  *  @data: data to write at register offset
9859c80d176SSepherosa Ziehau  *
9866a5a645eSSepherosa Ziehau  *  Acquires semaphore then writes the data to the PHY register at the offset
9876a5a645eSSepherosa Ziehau  *  using the kumeran interface.  Release the acquired semaphore before exiting.
9889c80d176SSepherosa Ziehau  **/
e1000_write_kmrn_reg_generic(struct e1000_hw * hw,u32 offset,u16 data)9899c80d176SSepherosa Ziehau s32 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data)
9909c80d176SSepherosa Ziehau {
9916a5a645eSSepherosa Ziehau 	return __e1000_write_kmrn_reg(hw, offset, data, FALSE);
9926a5a645eSSepherosa Ziehau }
9939c80d176SSepherosa Ziehau 
9946a5a645eSSepherosa Ziehau /**
9956a5a645eSSepherosa Ziehau  *  e1000_write_kmrn_reg_locked -  Write kumeran register
9966a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
9976a5a645eSSepherosa Ziehau  *  @offset: register offset to write to
9986a5a645eSSepherosa Ziehau  *  @data: data to write at register offset
9996a5a645eSSepherosa Ziehau  *
10006a5a645eSSepherosa Ziehau  *  Write the data to PHY register at the offset using the kumeran interface.
10016a5a645eSSepherosa Ziehau  *  Assumes semaphore already acquired.
10026a5a645eSSepherosa Ziehau  **/
e1000_write_kmrn_reg_locked(struct e1000_hw * hw,u32 offset,u16 data)10036a5a645eSSepherosa Ziehau s32 e1000_write_kmrn_reg_locked(struct e1000_hw *hw, u32 offset, u16 data)
10046a5a645eSSepherosa Ziehau {
10056a5a645eSSepherosa Ziehau 	return __e1000_write_kmrn_reg(hw, offset, data, TRUE);
10066a5a645eSSepherosa Ziehau }
10079c80d176SSepherosa Ziehau 
10086a5a645eSSepherosa Ziehau /**
10094be59a01SSepherosa Ziehau  *  e1000_set_master_slave_mode - Setup PHY for Master/slave mode
10104be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
10114be59a01SSepherosa Ziehau  *
10124be59a01SSepherosa Ziehau  *  Sets up Master/slave mode
10134be59a01SSepherosa Ziehau  **/
e1000_set_master_slave_mode(struct e1000_hw * hw)10144be59a01SSepherosa Ziehau static s32 e1000_set_master_slave_mode(struct e1000_hw *hw)
10154be59a01SSepherosa Ziehau {
10164be59a01SSepherosa Ziehau 	s32 ret_val;
10174be59a01SSepherosa Ziehau 	u16 phy_data;
10184be59a01SSepherosa Ziehau 
10194be59a01SSepherosa Ziehau 	/* Resolve Master/Slave mode */
10204be59a01SSepherosa Ziehau 	ret_val = hw->phy.ops.read_reg(hw, PHY_1000T_CTRL, &phy_data);
10214be59a01SSepherosa Ziehau 	if (ret_val)
10224be59a01SSepherosa Ziehau 		return ret_val;
10234be59a01SSepherosa Ziehau 
10244be59a01SSepherosa Ziehau 	/* load defaults for future use */
10254be59a01SSepherosa Ziehau 	hw->phy.original_ms_type = (phy_data & CR_1000T_MS_ENABLE) ?
10264be59a01SSepherosa Ziehau 				   ((phy_data & CR_1000T_MS_VALUE) ?
10274be59a01SSepherosa Ziehau 				    e1000_ms_force_master :
10284be59a01SSepherosa Ziehau 				    e1000_ms_force_slave) : e1000_ms_auto;
10294be59a01SSepherosa Ziehau 
10304be59a01SSepherosa Ziehau 	switch (hw->phy.ms_type) {
10314be59a01SSepherosa Ziehau 	case e1000_ms_force_master:
10324be59a01SSepherosa Ziehau 		phy_data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE);
10334be59a01SSepherosa Ziehau 		break;
10344be59a01SSepherosa Ziehau 	case e1000_ms_force_slave:
10354be59a01SSepherosa Ziehau 		phy_data |= CR_1000T_MS_ENABLE;
10364be59a01SSepherosa Ziehau 		phy_data &= ~(CR_1000T_MS_VALUE);
10374be59a01SSepherosa Ziehau 		break;
10384be59a01SSepherosa Ziehau 	case e1000_ms_auto:
10394be59a01SSepherosa Ziehau 		phy_data &= ~CR_1000T_MS_ENABLE;
10404be59a01SSepherosa Ziehau 		/* fall-through */
10414be59a01SSepherosa Ziehau 	default:
10424be59a01SSepherosa Ziehau 		break;
10434be59a01SSepherosa Ziehau 	}
10444be59a01SSepherosa Ziehau 
10454be59a01SSepherosa Ziehau 	return hw->phy.ops.write_reg(hw, PHY_1000T_CTRL, phy_data);
10464be59a01SSepherosa Ziehau }
10474be59a01SSepherosa Ziehau 
10484be59a01SSepherosa Ziehau /**
10496a5a645eSSepherosa Ziehau  *  e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link
10506a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
10516a5a645eSSepherosa Ziehau  *
10526a5a645eSSepherosa Ziehau  *  Sets up Carrier-sense on Transmit and downshift values.
10536a5a645eSSepherosa Ziehau  **/
e1000_copper_link_setup_82577(struct e1000_hw * hw)10546a5a645eSSepherosa Ziehau s32 e1000_copper_link_setup_82577(struct e1000_hw *hw)
10556a5a645eSSepherosa Ziehau {
10566a5a645eSSepherosa Ziehau 	s32 ret_val;
10576a5a645eSSepherosa Ziehau 	u16 phy_data;
10586a5a645eSSepherosa Ziehau 
10596a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_copper_link_setup_82577");
10606a5a645eSSepherosa Ziehau 
10616a5a645eSSepherosa Ziehau 	if (hw->phy.type == e1000_phy_82580) {
10626a5a645eSSepherosa Ziehau 		ret_val = hw->phy.ops.reset(hw);
10636a5a645eSSepherosa Ziehau 		if (ret_val) {
10646a5a645eSSepherosa Ziehau 			DEBUGOUT("Error resetting the PHY.\n");
10654be59a01SSepherosa Ziehau 			return ret_val;
10666a5a645eSSepherosa Ziehau 		}
10676a5a645eSSepherosa Ziehau 	}
10686a5a645eSSepherosa Ziehau 
10694765c386SMichael Neumann 	/* Enable CRS on Tx. This must be set for half-duplex operation. */
10706a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.read_reg(hw, I82577_CFG_REG, &phy_data);
10719c80d176SSepherosa Ziehau 	if (ret_val)
10724be59a01SSepherosa Ziehau 		return ret_val;
10739c80d176SSepherosa Ziehau 
10746a5a645eSSepherosa Ziehau 	phy_data |= I82577_CFG_ASSERT_CRS_ON_TX;
10759c80d176SSepherosa Ziehau 
10766a5a645eSSepherosa Ziehau 	/* Enable downshift */
10776a5a645eSSepherosa Ziehau 	phy_data |= I82577_CFG_ENABLE_DOWNSHIFT;
10786a5a645eSSepherosa Ziehau 
10796a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, I82577_CFG_REG, phy_data);
10804be59a01SSepherosa Ziehau 	if (ret_val)
10819c80d176SSepherosa Ziehau 		return ret_val;
10824be59a01SSepherosa Ziehau 
10834be59a01SSepherosa Ziehau 	/* Set MDI/MDIX mode */
10844be59a01SSepherosa Ziehau 	ret_val = hw->phy.ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data);
10854be59a01SSepherosa Ziehau 	if (ret_val)
10864be59a01SSepherosa Ziehau 		return ret_val;
10874be59a01SSepherosa Ziehau 	phy_data &= ~I82577_PHY_CTRL2_MDIX_CFG_MASK;
1088379ebbe7SSepherosa Ziehau 	/* Options:
10894be59a01SSepherosa Ziehau 	 *   0 - Auto (default)
10904be59a01SSepherosa Ziehau 	 *   1 - MDI mode
10914be59a01SSepherosa Ziehau 	 *   2 - MDI-X mode
10924be59a01SSepherosa Ziehau 	 */
10934be59a01SSepherosa Ziehau 	switch (hw->phy.mdix) {
10944be59a01SSepherosa Ziehau 	case 1:
10954be59a01SSepherosa Ziehau 		break;
10964be59a01SSepherosa Ziehau 	case 2:
10974be59a01SSepherosa Ziehau 		phy_data |= I82577_PHY_CTRL2_MANUAL_MDIX;
10984be59a01SSepherosa Ziehau 		break;
10994be59a01SSepherosa Ziehau 	case 0:
11004be59a01SSepherosa Ziehau 	default:
11014be59a01SSepherosa Ziehau 		phy_data |= I82577_PHY_CTRL2_AUTO_MDI_MDIX;
11024be59a01SSepherosa Ziehau 		break;
11034be59a01SSepherosa Ziehau 	}
11044be59a01SSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data);
11054be59a01SSepherosa Ziehau 	if (ret_val)
11064be59a01SSepherosa Ziehau 		return ret_val;
11074be59a01SSepherosa Ziehau 
11084be59a01SSepherosa Ziehau 	return e1000_set_master_slave_mode(hw);
11099c80d176SSepherosa Ziehau }
11109c80d176SSepherosa Ziehau 
11119c80d176SSepherosa Ziehau /**
11129c80d176SSepherosa Ziehau  *  e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link
11139c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
11149c80d176SSepherosa Ziehau  *
11159c80d176SSepherosa Ziehau  *  Sets up MDI/MDI-X and polarity for m88 PHY's.  If necessary, transmit clock
11169c80d176SSepherosa Ziehau  *  and downshift values are set also.
11179c80d176SSepherosa Ziehau  **/
e1000_copper_link_setup_m88(struct e1000_hw * hw)11189c80d176SSepherosa Ziehau s32 e1000_copper_link_setup_m88(struct e1000_hw *hw)
11199c80d176SSepherosa Ziehau {
11209c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
11219c80d176SSepherosa Ziehau 	s32 ret_val;
11229c80d176SSepherosa Ziehau 	u16 phy_data;
11239c80d176SSepherosa Ziehau 
11249c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_copper_link_setup_m88");
11259c80d176SSepherosa Ziehau 
11269c80d176SSepherosa Ziehau 
11276a5a645eSSepherosa Ziehau 	/* Enable CRS on Tx. This must be set for half-duplex operation. */
11289c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
11299c80d176SSepherosa Ziehau 	if (ret_val)
11304be59a01SSepherosa Ziehau 		return ret_val;
11319c80d176SSepherosa Ziehau 
11326a5a645eSSepherosa Ziehau 	/* For BM PHY this bit is downshift enable */
11336d5e2922SSepherosa Ziehau 	if (phy->type != e1000_phy_bm)
11346d5e2922SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
11359c80d176SSepherosa Ziehau 
1136379ebbe7SSepherosa Ziehau 	/* Options:
11379c80d176SSepherosa Ziehau 	 *   MDI/MDI-X = 0 (default)
11389c80d176SSepherosa Ziehau 	 *   0 - Auto for all speeds
11399c80d176SSepherosa Ziehau 	 *   1 - MDI mode
11409c80d176SSepherosa Ziehau 	 *   2 - MDI-X mode
11419c80d176SSepherosa Ziehau 	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
11429c80d176SSepherosa Ziehau 	 */
11439c80d176SSepherosa Ziehau 	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
11449c80d176SSepherosa Ziehau 
11459c80d176SSepherosa Ziehau 	switch (phy->mdix) {
11469c80d176SSepherosa Ziehau 	case 1:
11479c80d176SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
11489c80d176SSepherosa Ziehau 		break;
11499c80d176SSepherosa Ziehau 	case 2:
11509c80d176SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
11519c80d176SSepherosa Ziehau 		break;
11529c80d176SSepherosa Ziehau 	case 3:
11539c80d176SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_AUTO_X_1000T;
11549c80d176SSepherosa Ziehau 		break;
11559c80d176SSepherosa Ziehau 	case 0:
11569c80d176SSepherosa Ziehau 	default:
11579c80d176SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
11589c80d176SSepherosa Ziehau 		break;
11599c80d176SSepherosa Ziehau 	}
11609c80d176SSepherosa Ziehau 
1161379ebbe7SSepherosa Ziehau 	/* Options:
11629c80d176SSepherosa Ziehau 	 *   disable_polarity_correction = 0 (default)
11639c80d176SSepherosa Ziehau 	 *       Automatic Correction for Reversed Cable Polarity
11649c80d176SSepherosa Ziehau 	 *   0 - Disabled
11659c80d176SSepherosa Ziehau 	 *   1 - Enabled
11669c80d176SSepherosa Ziehau 	 */
11679c80d176SSepherosa Ziehau 	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
11684be59a01SSepherosa Ziehau 	if (phy->disable_polarity_correction)
11699c80d176SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
11709c80d176SSepherosa Ziehau 
11719c80d176SSepherosa Ziehau 	/* Enable downshift on BM (disabled by default) */
11724be59a01SSepherosa Ziehau 	if (phy->type == e1000_phy_bm) {
11734be59a01SSepherosa Ziehau 		/* For 82574/82583, first disable then enable downshift */
11744be59a01SSepherosa Ziehau 		if (phy->id == BME1000_E_PHY_ID_R2) {
11754be59a01SSepherosa Ziehau 			phy_data &= ~BME1000_PSCR_ENABLE_DOWNSHIFT;
11764be59a01SSepherosa Ziehau 			ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
11774be59a01SSepherosa Ziehau 						     phy_data);
11784be59a01SSepherosa Ziehau 			if (ret_val)
11794be59a01SSepherosa Ziehau 				return ret_val;
11804be59a01SSepherosa Ziehau 			/* Commit the changes. */
11814be59a01SSepherosa Ziehau 			ret_val = phy->ops.commit(hw);
11824be59a01SSepherosa Ziehau 			if (ret_val) {
11834be59a01SSepherosa Ziehau 				DEBUGOUT("Error committing the PHY changes\n");
11844be59a01SSepherosa Ziehau 				return ret_val;
11854be59a01SSepherosa Ziehau 			}
11864be59a01SSepherosa Ziehau 		}
11874be59a01SSepherosa Ziehau 
11889c80d176SSepherosa Ziehau 		phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT;
11894be59a01SSepherosa Ziehau 	}
11909c80d176SSepherosa Ziehau 
11919c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
11929c80d176SSepherosa Ziehau 	if (ret_val)
11934be59a01SSepherosa Ziehau 		return ret_val;
11949c80d176SSepherosa Ziehau 
119565aebe9fSSepherosa Ziehau 	if (phy->revision < E1000_REVISION_4 &&
119665aebe9fSSepherosa Ziehau 	    (hw->mac.type >= e1000_82575 ||
119765aebe9fSSepherosa Ziehau 	     (phy->type == e1000_phy_m88 && phy->id != BME1000_E_PHY_ID_R2))) {
1198379ebbe7SSepherosa Ziehau 		/* Force TX_CLK in the Extended PHY Specific Control Register
11999c80d176SSepherosa Ziehau 		 * to 25MHz clock.
12009c80d176SSepherosa Ziehau 		 */
12019c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
12029c80d176SSepherosa Ziehau 					    &phy_data);
12039c80d176SSepherosa Ziehau 		if (ret_val)
12044be59a01SSepherosa Ziehau 			return ret_val;
12059c80d176SSepherosa Ziehau 
12069c80d176SSepherosa Ziehau 		phy_data |= M88E1000_EPSCR_TX_CLK_25;
12079c80d176SSepherosa Ziehau 
12089c80d176SSepherosa Ziehau 		if ((phy->revision == E1000_REVISION_2) &&
12099c80d176SSepherosa Ziehau 		    (phy->id == M88E1111_I_PHY_ID)) {
12109c80d176SSepherosa Ziehau 			/* 82573L PHY - set the downshift counter to 5x. */
12119c80d176SSepherosa Ziehau 			phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK;
12129c80d176SSepherosa Ziehau 			phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X;
12139c80d176SSepherosa Ziehau 		} else {
12149c80d176SSepherosa Ziehau 			/* Configure Master and Slave downshift values */
12159c80d176SSepherosa Ziehau 			phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK |
12169c80d176SSepherosa Ziehau 				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK);
12179c80d176SSepherosa Ziehau 			phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X |
12189c80d176SSepherosa Ziehau 				     M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X);
12199c80d176SSepherosa Ziehau 		}
12209c80d176SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
12219c80d176SSepherosa Ziehau 					     phy_data);
12229c80d176SSepherosa Ziehau 		if (ret_val)
12234be59a01SSepherosa Ziehau 			return ret_val;
12249c80d176SSepherosa Ziehau 	}
12259c80d176SSepherosa Ziehau 
12269c80d176SSepherosa Ziehau 	if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) {
12279c80d176SSepherosa Ziehau 		/* Set PHY page 0, register 29 to 0x0003 */
12289c80d176SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, 29, 0x0003);
12299c80d176SSepherosa Ziehau 		if (ret_val)
12304be59a01SSepherosa Ziehau 			return ret_val;
12319c80d176SSepherosa Ziehau 
12329c80d176SSepherosa Ziehau 		/* Set PHY page 0, register 30 to 0x0000 */
12339c80d176SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, 30, 0x0000);
12349c80d176SSepherosa Ziehau 		if (ret_val)
12354be59a01SSepherosa Ziehau 			return ret_val;
12369c80d176SSepherosa Ziehau 	}
12379c80d176SSepherosa Ziehau 
12389c80d176SSepherosa Ziehau 	/* Commit the changes. */
12399c80d176SSepherosa Ziehau 	ret_val = phy->ops.commit(hw);
12409c80d176SSepherosa Ziehau 	if (ret_val) {
12419c80d176SSepherosa Ziehau 		DEBUGOUT("Error committing the PHY changes\n");
12424be59a01SSepherosa Ziehau 		return ret_val;
12439c80d176SSepherosa Ziehau 	}
12449c80d176SSepherosa Ziehau 
12456a5a645eSSepherosa Ziehau 	if (phy->type == e1000_phy_82578) {
12466a5a645eSSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
12476a5a645eSSepherosa Ziehau 					    &phy_data);
12486a5a645eSSepherosa Ziehau 		if (ret_val)
12494be59a01SSepherosa Ziehau 			return ret_val;
12506a5a645eSSepherosa Ziehau 
12516a5a645eSSepherosa Ziehau 		/* 82578 PHY - set the downshift count to 1x. */
12526a5a645eSSepherosa Ziehau 		phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE;
12536a5a645eSSepherosa Ziehau 		phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK;
12546a5a645eSSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL,
12556a5a645eSSepherosa Ziehau 					     phy_data);
12566a5a645eSSepherosa Ziehau 		if (ret_val)
12574be59a01SSepherosa Ziehau 			return ret_val;
12586a5a645eSSepherosa Ziehau 	}
12596a5a645eSSepherosa Ziehau 
12604be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
12614be59a01SSepherosa Ziehau }
12624be59a01SSepherosa Ziehau 
12639c80d176SSepherosa Ziehau /**
126462583d18SSepherosa Ziehau  *  e1000_copper_link_setup_m88_gen2 - Setup m88 PHY's for copper link
126562583d18SSepherosa Ziehau  *  @hw: pointer to the HW structure
126662583d18SSepherosa Ziehau  *
126762583d18SSepherosa Ziehau  *  Sets up MDI/MDI-X and polarity for i347-AT4, m88e1322 and m88e1112 PHY's.
126862583d18SSepherosa Ziehau  *  Also enables and sets the downshift parameters.
126962583d18SSepherosa Ziehau  **/
e1000_copper_link_setup_m88_gen2(struct e1000_hw * hw)127062583d18SSepherosa Ziehau s32 e1000_copper_link_setup_m88_gen2(struct e1000_hw *hw)
127162583d18SSepherosa Ziehau {
127262583d18SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
127362583d18SSepherosa Ziehau 	s32 ret_val;
127462583d18SSepherosa Ziehau 	u16 phy_data;
127562583d18SSepherosa Ziehau 
127662583d18SSepherosa Ziehau 	DEBUGFUNC("e1000_copper_link_setup_m88_gen2");
127762583d18SSepherosa Ziehau 
127862583d18SSepherosa Ziehau 
127962583d18SSepherosa Ziehau 	/* Enable CRS on Tx. This must be set for half-duplex operation. */
128062583d18SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
128162583d18SSepherosa Ziehau 	if (ret_val)
12824be59a01SSepherosa Ziehau 		return ret_val;
128362583d18SSepherosa Ziehau 
1284379ebbe7SSepherosa Ziehau 	/* Options:
128562583d18SSepherosa Ziehau 	 *   MDI/MDI-X = 0 (default)
128662583d18SSepherosa Ziehau 	 *   0 - Auto for all speeds
128762583d18SSepherosa Ziehau 	 *   1 - MDI mode
128862583d18SSepherosa Ziehau 	 *   2 - MDI-X mode
128962583d18SSepherosa Ziehau 	 *   3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes)
129062583d18SSepherosa Ziehau 	 */
129162583d18SSepherosa Ziehau 	phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
129262583d18SSepherosa Ziehau 
129362583d18SSepherosa Ziehau 	switch (phy->mdix) {
129462583d18SSepherosa Ziehau 	case 1:
129562583d18SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE;
129662583d18SSepherosa Ziehau 		break;
129762583d18SSepherosa Ziehau 	case 2:
129862583d18SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE;
129962583d18SSepherosa Ziehau 		break;
130062583d18SSepherosa Ziehau 	case 3:
130162583d18SSepherosa Ziehau 		/* M88E1112 does not support this mode) */
130262583d18SSepherosa Ziehau 		if (phy->id != M88E1112_E_PHY_ID) {
130362583d18SSepherosa Ziehau 			phy_data |= M88E1000_PSCR_AUTO_X_1000T;
130462583d18SSepherosa Ziehau 			break;
130562583d18SSepherosa Ziehau 		}
130662583d18SSepherosa Ziehau 	case 0:
130762583d18SSepherosa Ziehau 	default:
130862583d18SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_AUTO_X_MODE;
130962583d18SSepherosa Ziehau 		break;
131062583d18SSepherosa Ziehau 	}
131162583d18SSepherosa Ziehau 
1312379ebbe7SSepherosa Ziehau 	/* Options:
131362583d18SSepherosa Ziehau 	 *   disable_polarity_correction = 0 (default)
131462583d18SSepherosa Ziehau 	 *       Automatic Correction for Reversed Cable Polarity
131562583d18SSepherosa Ziehau 	 *   0 - Disabled
131662583d18SSepherosa Ziehau 	 *   1 - Enabled
131762583d18SSepherosa Ziehau 	 */
131862583d18SSepherosa Ziehau 	phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL;
13194be59a01SSepherosa Ziehau 	if (phy->disable_polarity_correction)
132062583d18SSepherosa Ziehau 		phy_data |= M88E1000_PSCR_POLARITY_REVERSAL;
132162583d18SSepherosa Ziehau 
132262583d18SSepherosa Ziehau 	/* Enable downshift and setting it to X6 */
1323ba0123e0SSepherosa Ziehau 	if (phy->id == M88E1543_E_PHY_ID) {
1324ba0123e0SSepherosa Ziehau 		phy_data &= ~I347AT4_PSCR_DOWNSHIFT_ENABLE;
1325ba0123e0SSepherosa Ziehau 		ret_val =
1326ba0123e0SSepherosa Ziehau 		    phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
1327ba0123e0SSepherosa Ziehau 		if (ret_val)
1328ba0123e0SSepherosa Ziehau 			return ret_val;
1329ba0123e0SSepherosa Ziehau 
1330ba0123e0SSepherosa Ziehau 		ret_val = phy->ops.commit(hw);
1331ba0123e0SSepherosa Ziehau 		if (ret_val) {
1332ba0123e0SSepherosa Ziehau 			DEBUGOUT("Error committing the PHY changes\n");
1333ba0123e0SSepherosa Ziehau 			return ret_val;
1334ba0123e0SSepherosa Ziehau 		}
1335ba0123e0SSepherosa Ziehau 	}
1336ba0123e0SSepherosa Ziehau 
133762583d18SSepherosa Ziehau 	phy_data &= ~I347AT4_PSCR_DOWNSHIFT_MASK;
133862583d18SSepherosa Ziehau 	phy_data |= I347AT4_PSCR_DOWNSHIFT_6X;
133962583d18SSepherosa Ziehau 	phy_data |= I347AT4_PSCR_DOWNSHIFT_ENABLE;
134062583d18SSepherosa Ziehau 
134162583d18SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
134262583d18SSepherosa Ziehau 	if (ret_val)
13434be59a01SSepherosa Ziehau 		return ret_val;
134462583d18SSepherosa Ziehau 
134562583d18SSepherosa Ziehau 	/* Commit the changes. */
134662583d18SSepherosa Ziehau 	ret_val = phy->ops.commit(hw);
134762583d18SSepherosa Ziehau 	if (ret_val) {
134862583d18SSepherosa Ziehau 		DEBUGOUT("Error committing the PHY changes\n");
13494be59a01SSepherosa Ziehau 		return ret_val;
135062583d18SSepherosa Ziehau 	}
135162583d18SSepherosa Ziehau 
13524765c386SMichael Neumann 	ret_val = e1000_set_master_slave_mode(hw);
13534765c386SMichael Neumann 	if (ret_val)
13544765c386SMichael Neumann 		return ret_val;
13554765c386SMichael Neumann 
13564be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
135762583d18SSepherosa Ziehau }
135862583d18SSepherosa Ziehau 
135962583d18SSepherosa Ziehau /**
13609c80d176SSepherosa Ziehau  *  e1000_copper_link_setup_igp - Setup igp PHY's for copper link
13619c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
13629c80d176SSepherosa Ziehau  *
13639c80d176SSepherosa Ziehau  *  Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for
13649c80d176SSepherosa Ziehau  *  igp PHY's.
13659c80d176SSepherosa Ziehau  **/
e1000_copper_link_setup_igp(struct e1000_hw * hw)13669c80d176SSepherosa Ziehau s32 e1000_copper_link_setup_igp(struct e1000_hw *hw)
13679c80d176SSepherosa Ziehau {
13689c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
13699c80d176SSepherosa Ziehau 	s32 ret_val;
13709c80d176SSepherosa Ziehau 	u16 data;
13719c80d176SSepherosa Ziehau 
13729c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_copper_link_setup_igp");
13739c80d176SSepherosa Ziehau 
13749c80d176SSepherosa Ziehau 
13759c80d176SSepherosa Ziehau 	ret_val = hw->phy.ops.reset(hw);
13769c80d176SSepherosa Ziehau 	if (ret_val) {
13779c80d176SSepherosa Ziehau 		DEBUGOUT("Error resetting the PHY.\n");
13784be59a01SSepherosa Ziehau 		return ret_val;
13799c80d176SSepherosa Ziehau 	}
13809c80d176SSepherosa Ziehau 
1381379ebbe7SSepherosa Ziehau 	/* Wait 100ms for MAC to configure PHY from NVM settings, to avoid
13829c80d176SSepherosa Ziehau 	 * timeout issues when LFS is enabled.
13839c80d176SSepherosa Ziehau 	 */
13849c80d176SSepherosa Ziehau 	msec_delay(100);
13859c80d176SSepherosa Ziehau 
1386379ebbe7SSepherosa Ziehau 	/* The NVM settings will configure LPLU in D3 for
13879c80d176SSepherosa Ziehau 	 * non-IGP1 PHYs.
13889c80d176SSepherosa Ziehau 	 */
13899c80d176SSepherosa Ziehau 	if (phy->type == e1000_phy_igp) {
13909c80d176SSepherosa Ziehau 		/* disable lplu d3 during driver init */
13919c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.set_d3_lplu_state(hw, FALSE);
13929c80d176SSepherosa Ziehau 		if (ret_val) {
13939c80d176SSepherosa Ziehau 			DEBUGOUT("Error Disabling LPLU D3\n");
13944be59a01SSepherosa Ziehau 			return ret_val;
13959c80d176SSepherosa Ziehau 		}
13969c80d176SSepherosa Ziehau 	}
13979c80d176SSepherosa Ziehau 
13989c80d176SSepherosa Ziehau 	/* disable lplu d0 during driver init */
13999c80d176SSepherosa Ziehau 	if (hw->phy.ops.set_d0_lplu_state) {
14009c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.set_d0_lplu_state(hw, FALSE);
14019c80d176SSepherosa Ziehau 		if (ret_val) {
14029c80d176SSepherosa Ziehau 			DEBUGOUT("Error Disabling LPLU D0\n");
14034be59a01SSepherosa Ziehau 			return ret_val;
14049c80d176SSepherosa Ziehau 		}
14059c80d176SSepherosa Ziehau 	}
14069c80d176SSepherosa Ziehau 	/* Configure mdi-mdix settings */
14079c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data);
14089c80d176SSepherosa Ziehau 	if (ret_val)
14094be59a01SSepherosa Ziehau 		return ret_val;
14109c80d176SSepherosa Ziehau 
14119c80d176SSepherosa Ziehau 	data &= ~IGP01E1000_PSCR_AUTO_MDIX;
14129c80d176SSepherosa Ziehau 
14139c80d176SSepherosa Ziehau 	switch (phy->mdix) {
14149c80d176SSepherosa Ziehau 	case 1:
14159c80d176SSepherosa Ziehau 		data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
14169c80d176SSepherosa Ziehau 		break;
14179c80d176SSepherosa Ziehau 	case 2:
14189c80d176SSepherosa Ziehau 		data |= IGP01E1000_PSCR_FORCE_MDI_MDIX;
14199c80d176SSepherosa Ziehau 		break;
14209c80d176SSepherosa Ziehau 	case 0:
14219c80d176SSepherosa Ziehau 	default:
14229c80d176SSepherosa Ziehau 		data |= IGP01E1000_PSCR_AUTO_MDIX;
14239c80d176SSepherosa Ziehau 		break;
14249c80d176SSepherosa Ziehau 	}
14259c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data);
14269c80d176SSepherosa Ziehau 	if (ret_val)
14274be59a01SSepherosa Ziehau 		return ret_val;
14289c80d176SSepherosa Ziehau 
14299c80d176SSepherosa Ziehau 	/* set auto-master slave resolution settings */
14309c80d176SSepherosa Ziehau 	if (hw->mac.autoneg) {
1431379ebbe7SSepherosa Ziehau 		/* when autonegotiation advertisement is only 1000Mbps then we
14329c80d176SSepherosa Ziehau 		 * should disable SmartSpeed and enable Auto MasterSlave
14339c80d176SSepherosa Ziehau 		 * resolution as hardware default.
14349c80d176SSepherosa Ziehau 		 */
14359c80d176SSepherosa Ziehau 		if (phy->autoneg_advertised == ADVERTISE_1000_FULL) {
14369c80d176SSepherosa Ziehau 			/* Disable SmartSpeed */
14379c80d176SSepherosa Ziehau 			ret_val = phy->ops.read_reg(hw,
14389c80d176SSepherosa Ziehau 						    IGP01E1000_PHY_PORT_CONFIG,
14399c80d176SSepherosa Ziehau 						    &data);
14409c80d176SSepherosa Ziehau 			if (ret_val)
14414be59a01SSepherosa Ziehau 				return ret_val;
14429c80d176SSepherosa Ziehau 
14439c80d176SSepherosa Ziehau 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
14449c80d176SSepherosa Ziehau 			ret_val = phy->ops.write_reg(hw,
14459c80d176SSepherosa Ziehau 						     IGP01E1000_PHY_PORT_CONFIG,
14469c80d176SSepherosa Ziehau 						     data);
14479c80d176SSepherosa Ziehau 			if (ret_val)
14484be59a01SSepherosa Ziehau 				return ret_val;
14499c80d176SSepherosa Ziehau 
14509c80d176SSepherosa Ziehau 			/* Set auto Master/Slave resolution process */
14519c80d176SSepherosa Ziehau 			ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data);
14529c80d176SSepherosa Ziehau 			if (ret_val)
14534be59a01SSepherosa Ziehau 				return ret_val;
14549c80d176SSepherosa Ziehau 
14559c80d176SSepherosa Ziehau 			data &= ~CR_1000T_MS_ENABLE;
14569c80d176SSepherosa Ziehau 			ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data);
14579c80d176SSepherosa Ziehau 			if (ret_val)
14589c80d176SSepherosa Ziehau 				return ret_val;
14599c80d176SSepherosa Ziehau 		}
14609c80d176SSepherosa Ziehau 
14614be59a01SSepherosa Ziehau 		ret_val = e1000_set_master_slave_mode(hw);
14629c80d176SSepherosa Ziehau 	}
14639c80d176SSepherosa Ziehau 
14649c80d176SSepherosa Ziehau 	return ret_val;
14659c80d176SSepherosa Ziehau }
14669c80d176SSepherosa Ziehau 
14679c80d176SSepherosa Ziehau /**
14689c80d176SSepherosa Ziehau  *  e1000_phy_setup_autoneg - Configure PHY for auto-negotiation
14699c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
14709c80d176SSepherosa Ziehau  *
14719c80d176SSepherosa Ziehau  *  Reads the MII auto-neg advertisement register and/or the 1000T control
14729c80d176SSepherosa Ziehau  *  register and if the PHY is already setup for auto-negotiation, then
14739c80d176SSepherosa Ziehau  *  return successful.  Otherwise, setup advertisement and flow control to
14749c80d176SSepherosa Ziehau  *  the appropriate values for the wanted auto-negotiation.
14759c80d176SSepherosa Ziehau  **/
e1000_phy_setup_autoneg(struct e1000_hw * hw)14769c80d176SSepherosa Ziehau s32 e1000_phy_setup_autoneg(struct e1000_hw *hw)
14779c80d176SSepherosa Ziehau {
14789c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
14799c80d176SSepherosa Ziehau 	s32 ret_val;
14809c80d176SSepherosa Ziehau 	u16 mii_autoneg_adv_reg;
14819c80d176SSepherosa Ziehau 	u16 mii_1000t_ctrl_reg = 0;
14829c80d176SSepherosa Ziehau 
14839c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_setup_autoneg");
14849c80d176SSepherosa Ziehau 
14859c80d176SSepherosa Ziehau 	phy->autoneg_advertised &= phy->autoneg_mask;
14869c80d176SSepherosa Ziehau 
14879c80d176SSepherosa Ziehau 	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
14889c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
14899c80d176SSepherosa Ziehau 	if (ret_val)
14904be59a01SSepherosa Ziehau 		return ret_val;
14919c80d176SSepherosa Ziehau 
14929c80d176SSepherosa Ziehau 	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
14939c80d176SSepherosa Ziehau 		/* Read the MII 1000Base-T Control Register (Address 9). */
14949c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
14959c80d176SSepherosa Ziehau 					    &mii_1000t_ctrl_reg);
14969c80d176SSepherosa Ziehau 		if (ret_val)
14974be59a01SSepherosa Ziehau 			return ret_val;
14989c80d176SSepherosa Ziehau 	}
14999c80d176SSepherosa Ziehau 
1500379ebbe7SSepherosa Ziehau 	/* Need to parse both autoneg_advertised and fc and set up
15019c80d176SSepherosa Ziehau 	 * the appropriate PHY registers.  First we will parse for
15029c80d176SSepherosa Ziehau 	 * autoneg_advertised software override.  Since we can advertise
15039c80d176SSepherosa Ziehau 	 * a plethora of combinations, we need to check each bit
15049c80d176SSepherosa Ziehau 	 * individually.
15059c80d176SSepherosa Ziehau 	 */
15069c80d176SSepherosa Ziehau 
1507379ebbe7SSepherosa Ziehau 	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
15089c80d176SSepherosa Ziehau 	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
15099c80d176SSepherosa Ziehau 	 * the  1000Base-T Control Register (Address 9).
15109c80d176SSepherosa Ziehau 	 */
15119c80d176SSepherosa Ziehau 	mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
15129c80d176SSepherosa Ziehau 				 NWAY_AR_100TX_HD_CAPS |
15139c80d176SSepherosa Ziehau 				 NWAY_AR_10T_FD_CAPS   |
15149c80d176SSepherosa Ziehau 				 NWAY_AR_10T_HD_CAPS);
15159c80d176SSepherosa Ziehau 	mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
15169c80d176SSepherosa Ziehau 
15179c80d176SSepherosa Ziehau 	DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised);
15189c80d176SSepherosa Ziehau 
15199c80d176SSepherosa Ziehau 	/* Do we want to advertise 10 Mb Half Duplex? */
15209c80d176SSepherosa Ziehau 	if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
15219c80d176SSepherosa Ziehau 		DEBUGOUT("Advertise 10mb Half duplex\n");
15229c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
15239c80d176SSepherosa Ziehau 	}
15249c80d176SSepherosa Ziehau 
15259c80d176SSepherosa Ziehau 	/* Do we want to advertise 10 Mb Full Duplex? */
15269c80d176SSepherosa Ziehau 	if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
15279c80d176SSepherosa Ziehau 		DEBUGOUT("Advertise 10mb Full duplex\n");
15289c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
15299c80d176SSepherosa Ziehau 	}
15309c80d176SSepherosa Ziehau 
15319c80d176SSepherosa Ziehau 	/* Do we want to advertise 100 Mb Half Duplex? */
15329c80d176SSepherosa Ziehau 	if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
15339c80d176SSepherosa Ziehau 		DEBUGOUT("Advertise 100mb Half duplex\n");
15349c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
15359c80d176SSepherosa Ziehau 	}
15369c80d176SSepherosa Ziehau 
15379c80d176SSepherosa Ziehau 	/* Do we want to advertise 100 Mb Full Duplex? */
15389c80d176SSepherosa Ziehau 	if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
15399c80d176SSepherosa Ziehau 		DEBUGOUT("Advertise 100mb Full duplex\n");
15409c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
15419c80d176SSepherosa Ziehau 	}
15429c80d176SSepherosa Ziehau 
15439c80d176SSepherosa Ziehau 	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
15449c80d176SSepherosa Ziehau 	if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
15459c80d176SSepherosa Ziehau 		DEBUGOUT("Advertise 1000mb Half duplex request denied!\n");
15469c80d176SSepherosa Ziehau 
15479c80d176SSepherosa Ziehau 	/* Do we want to advertise 1000 Mb Full Duplex? */
15489c80d176SSepherosa Ziehau 	if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
15499c80d176SSepherosa Ziehau 		DEBUGOUT("Advertise 1000mb Full duplex\n");
15509c80d176SSepherosa Ziehau 		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
15519c80d176SSepherosa Ziehau 	}
15529c80d176SSepherosa Ziehau 
1553379ebbe7SSepherosa Ziehau 	/* Check for a software override of the flow control settings, and
15549c80d176SSepherosa Ziehau 	 * setup the PHY advertisement registers accordingly.  If
15559c80d176SSepherosa Ziehau 	 * auto-negotiation is enabled, then software will have to set the
15569c80d176SSepherosa Ziehau 	 * "PAUSE" bits to the correct value in the Auto-Negotiation
15579c80d176SSepherosa Ziehau 	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
15589c80d176SSepherosa Ziehau 	 * negotiation.
15599c80d176SSepherosa Ziehau 	 *
15609c80d176SSepherosa Ziehau 	 * The possible values of the "fc" parameter are:
15619c80d176SSepherosa Ziehau 	 *      0:  Flow control is completely disabled
15629c80d176SSepherosa Ziehau 	 *      1:  Rx flow control is enabled (we can receive pause frames
15639c80d176SSepherosa Ziehau 	 *          but not send pause frames).
15649c80d176SSepherosa Ziehau 	 *      2:  Tx flow control is enabled (we can send pause frames
15659c80d176SSepherosa Ziehau 	 *          but we do not support receiving pause frames).
15669c80d176SSepherosa Ziehau 	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.
15679c80d176SSepherosa Ziehau 	 *  other:  No software override.  The flow control configuration
15689c80d176SSepherosa Ziehau 	 *          in the EEPROM is used.
15699c80d176SSepherosa Ziehau 	 */
15709c80d176SSepherosa Ziehau 	switch (hw->fc.current_mode) {
15719c80d176SSepherosa Ziehau 	case e1000_fc_none:
1572379ebbe7SSepherosa Ziehau 		/* Flow control (Rx & Tx) is completely disabled by a
15739c80d176SSepherosa Ziehau 		 * software over-ride.
15749c80d176SSepherosa Ziehau 		 */
15759c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
15769c80d176SSepherosa Ziehau 		break;
15779c80d176SSepherosa Ziehau 	case e1000_fc_rx_pause:
1578379ebbe7SSepherosa Ziehau 		/* Rx Flow control is enabled, and Tx Flow control is
15799c80d176SSepherosa Ziehau 		 * disabled, by a software over-ride.
15809c80d176SSepherosa Ziehau 		 *
15819c80d176SSepherosa Ziehau 		 * Since there really isn't a way to advertise that we are
15829c80d176SSepherosa Ziehau 		 * capable of Rx Pause ONLY, we will advertise that we
15839c80d176SSepherosa Ziehau 		 * support both symmetric and asymmetric Rx PAUSE.  Later
15849c80d176SSepherosa Ziehau 		 * (in e1000_config_fc_after_link_up) we will disable the
15859c80d176SSepherosa Ziehau 		 * hw's ability to send PAUSE frames.
15869c80d176SSepherosa Ziehau 		 */
15879c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
15889c80d176SSepherosa Ziehau 		break;
15899c80d176SSepherosa Ziehau 	case e1000_fc_tx_pause:
1590379ebbe7SSepherosa Ziehau 		/* Tx Flow control is enabled, and Rx Flow control is
15919c80d176SSepherosa Ziehau 		 * disabled, by a software over-ride.
15929c80d176SSepherosa Ziehau 		 */
15939c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
15949c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
15959c80d176SSepherosa Ziehau 		break;
15969c80d176SSepherosa Ziehau 	case e1000_fc_full:
1597379ebbe7SSepherosa Ziehau 		/* Flow control (both Rx and Tx) is enabled by a software
15989c80d176SSepherosa Ziehau 		 * over-ride.
15999c80d176SSepherosa Ziehau 		 */
16009c80d176SSepherosa Ziehau 		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
16019c80d176SSepherosa Ziehau 		break;
16029c80d176SSepherosa Ziehau 	default:
16039c80d176SSepherosa Ziehau 		DEBUGOUT("Flow control param set incorrectly\n");
16044be59a01SSepherosa Ziehau 		return -E1000_ERR_CONFIG;
16059c80d176SSepherosa Ziehau 	}
16069c80d176SSepherosa Ziehau 
16079c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
16089c80d176SSepherosa Ziehau 	if (ret_val)
16094be59a01SSepherosa Ziehau 		return ret_val;
16109c80d176SSepherosa Ziehau 
16119c80d176SSepherosa Ziehau 	DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
16129c80d176SSepherosa Ziehau 
16134be59a01SSepherosa Ziehau 	if (phy->autoneg_mask & ADVERTISE_1000_FULL)
16144be59a01SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
16159c80d176SSepherosa Ziehau 					     mii_1000t_ctrl_reg);
16164be59a01SSepherosa Ziehau 
16174be59a01SSepherosa Ziehau 	return ret_val;
16189c80d176SSepherosa Ziehau }
16199c80d176SSepherosa Ziehau 
16204be59a01SSepherosa Ziehau /**
16214be59a01SSepherosa Ziehau  *  e1000_copper_link_autoneg - Setup/Enable autoneg for copper link
16224be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
16234be59a01SSepherosa Ziehau  *
16244be59a01SSepherosa Ziehau  *  Performs initial bounds checking on autoneg advertisement parameter, then
16254be59a01SSepherosa Ziehau  *  configure to advertise the full capability.  Setup the PHY to autoneg
16264be59a01SSepherosa Ziehau  *  and restart the negotiation process between the link partner.  If
16274be59a01SSepherosa Ziehau  *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
16284be59a01SSepherosa Ziehau  **/
e1000_copper_link_autoneg(struct e1000_hw * hw)16294be59a01SSepherosa Ziehau s32 e1000_copper_link_autoneg(struct e1000_hw *hw)
16304be59a01SSepherosa Ziehau {
16314be59a01SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
16324be59a01SSepherosa Ziehau 	s32 ret_val;
16334be59a01SSepherosa Ziehau 	u16 phy_ctrl;
16344be59a01SSepherosa Ziehau 
16354be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_copper_link_autoneg");
16364be59a01SSepherosa Ziehau 
1637379ebbe7SSepherosa Ziehau 	/* Perform some bounds checking on the autoneg advertisement
16384be59a01SSepherosa Ziehau 	 * parameter.
16394be59a01SSepherosa Ziehau 	 */
16404be59a01SSepherosa Ziehau 	phy->autoneg_advertised &= phy->autoneg_mask;
16414be59a01SSepherosa Ziehau 
1642379ebbe7SSepherosa Ziehau 	/* If autoneg_advertised is zero, we assume it was not defaulted
16434be59a01SSepherosa Ziehau 	 * by the calling code so we set to advertise full capability.
16444be59a01SSepherosa Ziehau 	 */
16454be59a01SSepherosa Ziehau 	if (!phy->autoneg_advertised)
16464be59a01SSepherosa Ziehau 		phy->autoneg_advertised = phy->autoneg_mask;
16474be59a01SSepherosa Ziehau 
16484be59a01SSepherosa Ziehau 	DEBUGOUT("Reconfiguring auto-neg advertisement params\n");
16494be59a01SSepherosa Ziehau 	ret_val = e1000_phy_setup_autoneg(hw);
16504be59a01SSepherosa Ziehau 	if (ret_val) {
16514be59a01SSepherosa Ziehau 		DEBUGOUT("Error Setting up Auto-Negotiation\n");
16524be59a01SSepherosa Ziehau 		return ret_val;
16534be59a01SSepherosa Ziehau 	}
16544be59a01SSepherosa Ziehau 	DEBUGOUT("Restarting Auto-Neg\n");
16554be59a01SSepherosa Ziehau 
1656379ebbe7SSepherosa Ziehau 	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
16574be59a01SSepherosa Ziehau 	 * the Auto Neg Restart bit in the PHY control register.
16584be59a01SSepherosa Ziehau 	 */
16594be59a01SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
16604be59a01SSepherosa Ziehau 	if (ret_val)
16614be59a01SSepherosa Ziehau 		return ret_val;
16624be59a01SSepherosa Ziehau 
16634be59a01SSepherosa Ziehau 	phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
16644be59a01SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
16654be59a01SSepherosa Ziehau 	if (ret_val)
16664be59a01SSepherosa Ziehau 		return ret_val;
16674be59a01SSepherosa Ziehau 
1668379ebbe7SSepherosa Ziehau 	/* Does the user want to wait for Auto-Neg to complete here, or
16694be59a01SSepherosa Ziehau 	 * check at a later time (for example, callback routine).
16704be59a01SSepherosa Ziehau 	 */
16714be59a01SSepherosa Ziehau 	if (phy->autoneg_wait_to_complete) {
1672379ebbe7SSepherosa Ziehau 		ret_val = e1000_wait_autoneg(hw);
16734be59a01SSepherosa Ziehau 		if (ret_val) {
16744be59a01SSepherosa Ziehau 			DEBUGOUT("Error while waiting for autoneg to complete\n");
16754be59a01SSepherosa Ziehau 			return ret_val;
16764be59a01SSepherosa Ziehau 		}
16774be59a01SSepherosa Ziehau 	}
16784be59a01SSepherosa Ziehau 
16794be59a01SSepherosa Ziehau 	hw->mac.get_link_status = TRUE;
16804be59a01SSepherosa Ziehau 
16819c80d176SSepherosa Ziehau 	return ret_val;
16829c80d176SSepherosa Ziehau }
16839c80d176SSepherosa Ziehau 
16849c80d176SSepherosa Ziehau /**
16859c80d176SSepherosa Ziehau  *  e1000_setup_copper_link_generic - Configure copper link settings
16869c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
16879c80d176SSepherosa Ziehau  *
16889c80d176SSepherosa Ziehau  *  Calls the appropriate function to configure the link for auto-neg or forced
16899c80d176SSepherosa Ziehau  *  speed and duplex.  Then we check for link, once link is established calls
16909c80d176SSepherosa Ziehau  *  to configure collision distance and flow control are called.  If link is
16919c80d176SSepherosa Ziehau  *  not established, we return -E1000_ERR_PHY (-2).
16929c80d176SSepherosa Ziehau  **/
e1000_setup_copper_link_generic(struct e1000_hw * hw)16939c80d176SSepherosa Ziehau s32 e1000_setup_copper_link_generic(struct e1000_hw *hw)
16949c80d176SSepherosa Ziehau {
16959c80d176SSepherosa Ziehau 	s32 ret_val;
16969c80d176SSepherosa Ziehau 	bool link;
16979c80d176SSepherosa Ziehau 
16989c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_setup_copper_link_generic");
16999c80d176SSepherosa Ziehau 
17009c80d176SSepherosa Ziehau 	if (hw->mac.autoneg) {
1701379ebbe7SSepherosa Ziehau 		/* Setup autoneg and flow control advertisement and perform
17029c80d176SSepherosa Ziehau 		 * autonegotiation.
17039c80d176SSepherosa Ziehau 		 */
17049c80d176SSepherosa Ziehau 		ret_val = e1000_copper_link_autoneg(hw);
17059c80d176SSepherosa Ziehau 		if (ret_val)
17064be59a01SSepherosa Ziehau 			return ret_val;
17079c80d176SSepherosa Ziehau 	} else {
1708379ebbe7SSepherosa Ziehau 		/* PHY will be set to 10H, 10F, 100H or 100F
17099c80d176SSepherosa Ziehau 		 * depending on user settings.
17109c80d176SSepherosa Ziehau 		 */
17119c80d176SSepherosa Ziehau 		DEBUGOUT("Forcing Speed and Duplex\n");
17129c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.force_speed_duplex(hw);
17139c80d176SSepherosa Ziehau 		if (ret_val) {
17149c80d176SSepherosa Ziehau 			DEBUGOUT("Error Forcing Speed and Duplex\n");
17154be59a01SSepherosa Ziehau 			return ret_val;
17169c80d176SSepherosa Ziehau 		}
17179c80d176SSepherosa Ziehau 	}
17189c80d176SSepherosa Ziehau 
1719379ebbe7SSepherosa Ziehau 	/* Check link status. Wait up to 100 microseconds for link to become
17209c80d176SSepherosa Ziehau 	 * valid.
17219c80d176SSepherosa Ziehau 	 */
17224be59a01SSepherosa Ziehau 	ret_val = e1000_phy_has_link_generic(hw, COPPER_LINK_UP_LIMIT, 10,
17239c80d176SSepherosa Ziehau 					     &link);
17249c80d176SSepherosa Ziehau 	if (ret_val)
17254be59a01SSepherosa Ziehau 		return ret_val;
17269c80d176SSepherosa Ziehau 
17279c80d176SSepherosa Ziehau 	if (link) {
17289c80d176SSepherosa Ziehau 		DEBUGOUT("Valid link established!!!\n");
17294be59a01SSepherosa Ziehau 		hw->mac.ops.config_collision_dist(hw);
17309c80d176SSepherosa Ziehau 		ret_val = e1000_config_fc_after_link_up_generic(hw);
17319c80d176SSepherosa Ziehau 	} else {
17329c80d176SSepherosa Ziehau 		DEBUGOUT("Unable to establish link!!!\n");
17339c80d176SSepherosa Ziehau 	}
17349c80d176SSepherosa Ziehau 
17359c80d176SSepherosa Ziehau 	return ret_val;
17369c80d176SSepherosa Ziehau }
17379c80d176SSepherosa Ziehau 
17389c80d176SSepherosa Ziehau /**
17399c80d176SSepherosa Ziehau  *  e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY
17409c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
17419c80d176SSepherosa Ziehau  *
17429c80d176SSepherosa Ziehau  *  Calls the PHY setup function to force speed and duplex.  Clears the
17439c80d176SSepherosa Ziehau  *  auto-crossover to force MDI manually.  Waits for link and returns
17449c80d176SSepherosa Ziehau  *  successful if link up is successful, else -E1000_ERR_PHY (-2).
17459c80d176SSepherosa Ziehau  **/
e1000_phy_force_speed_duplex_igp(struct e1000_hw * hw)17469c80d176SSepherosa Ziehau s32 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw)
17479c80d176SSepherosa Ziehau {
17489c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
17499c80d176SSepherosa Ziehau 	s32 ret_val;
17509c80d176SSepherosa Ziehau 	u16 phy_data;
17519c80d176SSepherosa Ziehau 	bool link;
17529c80d176SSepherosa Ziehau 
17539c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_force_speed_duplex_igp");
17549c80d176SSepherosa Ziehau 
17559c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
17569c80d176SSepherosa Ziehau 	if (ret_val)
17574be59a01SSepherosa Ziehau 		return ret_val;
17589c80d176SSepherosa Ziehau 
17599c80d176SSepherosa Ziehau 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
17609c80d176SSepherosa Ziehau 
17619c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
17629c80d176SSepherosa Ziehau 	if (ret_val)
17634be59a01SSepherosa Ziehau 		return ret_val;
17649c80d176SSepherosa Ziehau 
1765379ebbe7SSepherosa Ziehau 	/* Clear Auto-Crossover to force MDI manually.  IGP requires MDI
17669c80d176SSepherosa Ziehau 	 * forced whenever speed and duplex are forced.
17679c80d176SSepherosa Ziehau 	 */
17689c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data);
17699c80d176SSepherosa Ziehau 	if (ret_val)
17704be59a01SSepherosa Ziehau 		return ret_val;
17719c80d176SSepherosa Ziehau 
17729c80d176SSepherosa Ziehau 	phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX;
17739c80d176SSepherosa Ziehau 	phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX;
17749c80d176SSepherosa Ziehau 
17759c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data);
17769c80d176SSepherosa Ziehau 	if (ret_val)
17774be59a01SSepherosa Ziehau 		return ret_val;
17789c80d176SSepherosa Ziehau 
17799c80d176SSepherosa Ziehau 	DEBUGOUT1("IGP PSCR: %X\n", phy_data);
17809c80d176SSepherosa Ziehau 
17819c80d176SSepherosa Ziehau 	usec_delay(1);
17829c80d176SSepherosa Ziehau 
17839c80d176SSepherosa Ziehau 	if (phy->autoneg_wait_to_complete) {
17849c80d176SSepherosa Ziehau 		DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n");
17859c80d176SSepherosa Ziehau 
17864be59a01SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
17874be59a01SSepherosa Ziehau 						     100000, &link);
17889c80d176SSepherosa Ziehau 		if (ret_val)
17894be59a01SSepherosa Ziehau 			return ret_val;
17909c80d176SSepherosa Ziehau 
17919c80d176SSepherosa Ziehau 		if (!link)
17929c80d176SSepherosa Ziehau 			DEBUGOUT("Link taking longer than expected.\n");
17939c80d176SSepherosa Ziehau 
17949c80d176SSepherosa Ziehau 		/* Try once more */
17954be59a01SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
17964be59a01SSepherosa Ziehau 						     100000, &link);
17979c80d176SSepherosa Ziehau 	}
17989c80d176SSepherosa Ziehau 
17999c80d176SSepherosa Ziehau 	return ret_val;
18009c80d176SSepherosa Ziehau }
18019c80d176SSepherosa Ziehau 
18029c80d176SSepherosa Ziehau /**
18039c80d176SSepherosa Ziehau  *  e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY
18049c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
18059c80d176SSepherosa Ziehau  *
18069c80d176SSepherosa Ziehau  *  Calls the PHY setup function to force speed and duplex.  Clears the
18079c80d176SSepherosa Ziehau  *  auto-crossover to force MDI manually.  Resets the PHY to commit the
18089c80d176SSepherosa Ziehau  *  changes.  If time expires while waiting for link up, we reset the DSP.
18099c80d176SSepherosa Ziehau  *  After reset, TX_CLK and CRS on Tx must be set.  Return successful upon
18109c80d176SSepherosa Ziehau  *  successful completion, else return corresponding error code.
18119c80d176SSepherosa Ziehau  **/
e1000_phy_force_speed_duplex_m88(struct e1000_hw * hw)18129c80d176SSepherosa Ziehau s32 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw)
18139c80d176SSepherosa Ziehau {
18149c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
18159c80d176SSepherosa Ziehau 	s32 ret_val;
18169c80d176SSepherosa Ziehau 	u16 phy_data;
18179c80d176SSepherosa Ziehau 	bool link;
18189c80d176SSepherosa Ziehau 
18199c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_force_speed_duplex_m88");
18209c80d176SSepherosa Ziehau 
18214be59a01SSepherosa Ziehau 	/* I210 and I211 devices support Auto-Crossover in forced operation. */
18224be59a01SSepherosa Ziehau 	if (phy->type != e1000_phy_i210) {
1823379ebbe7SSepherosa Ziehau 		/* Clear Auto-Crossover to force MDI manually.  M88E1000
18244be59a01SSepherosa Ziehau 		 * requires MDI forced whenever speed and duplex are forced.
18259c80d176SSepherosa Ziehau 		 */
18264be59a01SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL,
18274be59a01SSepherosa Ziehau 					    &phy_data);
18289c80d176SSepherosa Ziehau 		if (ret_val)
18294be59a01SSepherosa Ziehau 			return ret_val;
18309c80d176SSepherosa Ziehau 
18319c80d176SSepherosa Ziehau 		phy_data &= ~M88E1000_PSCR_AUTO_X_MODE;
18324be59a01SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL,
18334be59a01SSepherosa Ziehau 					     phy_data);
18349c80d176SSepherosa Ziehau 		if (ret_val)
18354be59a01SSepherosa Ziehau 			return ret_val;
18369c80d176SSepherosa Ziehau 
18379c80d176SSepherosa Ziehau 		DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data);
1838a40fda39SSepherosa Ziehau 	}
18399c80d176SSepherosa Ziehau 
18409c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
18419c80d176SSepherosa Ziehau 	if (ret_val)
18424be59a01SSepherosa Ziehau 		return ret_val;
18439c80d176SSepherosa Ziehau 
18449c80d176SSepherosa Ziehau 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
18459c80d176SSepherosa Ziehau 
18469c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
18479c80d176SSepherosa Ziehau 	if (ret_val)
18484be59a01SSepherosa Ziehau 		return ret_val;
18499c80d176SSepherosa Ziehau 
18509c80d176SSepherosa Ziehau 	/* Reset the phy to commit changes. */
18519c80d176SSepherosa Ziehau 	ret_val = hw->phy.ops.commit(hw);
18529c80d176SSepherosa Ziehau 	if (ret_val)
18534be59a01SSepherosa Ziehau 		return ret_val;
18549c80d176SSepherosa Ziehau 
18559c80d176SSepherosa Ziehau 	if (phy->autoneg_wait_to_complete) {
18569c80d176SSepherosa Ziehau 		DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n");
18579c80d176SSepherosa Ziehau 
18589c80d176SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
18599c80d176SSepherosa Ziehau 						     100000, &link);
18609c80d176SSepherosa Ziehau 		if (ret_val)
18614be59a01SSepherosa Ziehau 			return ret_val;
18629c80d176SSepherosa Ziehau 
18639c80d176SSepherosa Ziehau 		if (!link) {
18644be59a01SSepherosa Ziehau 			bool reset_dsp = TRUE;
18654be59a01SSepherosa Ziehau 
18664be59a01SSepherosa Ziehau 			switch (hw->phy.id) {
18674be59a01SSepherosa Ziehau 			case I347AT4_E_PHY_ID:
18684be59a01SSepherosa Ziehau 			case M88E1340M_E_PHY_ID:
18694be59a01SSepherosa Ziehau 			case M88E1112_E_PHY_ID:
1870ba0123e0SSepherosa Ziehau 			case M88E1543_E_PHY_ID:
1871ba0123e0SSepherosa Ziehau 			case M88E1512_E_PHY_ID:
18724be59a01SSepherosa Ziehau 			case I210_I_PHY_ID:
18734be59a01SSepherosa Ziehau 				reset_dsp = FALSE;
18744be59a01SSepherosa Ziehau 				break;
18754be59a01SSepherosa Ziehau 			default:
18764be59a01SSepherosa Ziehau 				if (hw->phy.type != e1000_phy_m88)
18774be59a01SSepherosa Ziehau 					reset_dsp = FALSE;
18784be59a01SSepherosa Ziehau 				break;
18794be59a01SSepherosa Ziehau 			}
18804be59a01SSepherosa Ziehau 
18814be59a01SSepherosa Ziehau 			if (!reset_dsp) {
18826a5a645eSSepherosa Ziehau 				DEBUGOUT("Link taking longer than expected.\n");
18836a5a645eSSepherosa Ziehau 			} else {
1884379ebbe7SSepherosa Ziehau 				/* We didn't get link.
18859c80d176SSepherosa Ziehau 				 * Reset the DSP and cross our fingers.
18869c80d176SSepherosa Ziehau 				 */
18879c80d176SSepherosa Ziehau 				ret_val = phy->ops.write_reg(hw,
18889c80d176SSepherosa Ziehau 						M88E1000_PHY_PAGE_SELECT,
18899c80d176SSepherosa Ziehau 						0x001d);
18909c80d176SSepherosa Ziehau 				if (ret_val)
18914be59a01SSepherosa Ziehau 					return ret_val;
18929c80d176SSepherosa Ziehau 				ret_val = e1000_phy_reset_dsp_generic(hw);
18939c80d176SSepherosa Ziehau 				if (ret_val)
18944be59a01SSepherosa Ziehau 					return ret_val;
18959c80d176SSepherosa Ziehau 			}
18966a5a645eSSepherosa Ziehau 		}
18979c80d176SSepherosa Ziehau 
18989c80d176SSepherosa Ziehau 		/* Try once more */
18999c80d176SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
19009c80d176SSepherosa Ziehau 						     100000, &link);
19019c80d176SSepherosa Ziehau 		if (ret_val)
19024be59a01SSepherosa Ziehau 			return ret_val;
19039c80d176SSepherosa Ziehau 	}
19049c80d176SSepherosa Ziehau 
19054be59a01SSepherosa Ziehau 	if (hw->phy.type != e1000_phy_m88)
19064be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
19074be59a01SSepherosa Ziehau 
19084be59a01SSepherosa Ziehau 	if (hw->phy.id == I347AT4_E_PHY_ID ||
190962583d18SSepherosa Ziehau 		hw->phy.id == M88E1340M_E_PHY_ID ||
191062583d18SSepherosa Ziehau 		hw->phy.id == M88E1112_E_PHY_ID)
19114be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
19124be59a01SSepherosa Ziehau 	if (hw->phy.id == I210_I_PHY_ID)
19134be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
1914ba0123e0SSepherosa Ziehau 	if ((hw->phy.id == M88E1543_E_PHY_ID) ||
1915ba0123e0SSepherosa Ziehau 	    (hw->phy.id == M88E1512_E_PHY_ID))
1916379ebbe7SSepherosa Ziehau 		return E1000_SUCCESS;
19179c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data);
19189c80d176SSepherosa Ziehau 	if (ret_val)
19194be59a01SSepherosa Ziehau 		return ret_val;
19209c80d176SSepherosa Ziehau 
1921379ebbe7SSepherosa Ziehau 	/* Resetting the phy means we need to re-force TX_CLK in the
19229c80d176SSepherosa Ziehau 	 * Extended PHY Specific Control Register to 25MHz clock from
19239c80d176SSepherosa Ziehau 	 * the reset value of 2.5MHz.
19249c80d176SSepherosa Ziehau 	 */
19259c80d176SSepherosa Ziehau 	phy_data |= M88E1000_EPSCR_TX_CLK_25;
19269c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data);
19279c80d176SSepherosa Ziehau 	if (ret_val)
19284be59a01SSepherosa Ziehau 		return ret_val;
19299c80d176SSepherosa Ziehau 
1930379ebbe7SSepherosa Ziehau 	/* In addition, we must re-enable CRS on Tx for both half and full
19319c80d176SSepherosa Ziehau 	 * duplex.
19329c80d176SSepherosa Ziehau 	 */
19339c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
19349c80d176SSepherosa Ziehau 	if (ret_val)
19354be59a01SSepherosa Ziehau 		return ret_val;
19369c80d176SSepherosa Ziehau 
19379c80d176SSepherosa Ziehau 	phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX;
19389c80d176SSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data);
19399c80d176SSepherosa Ziehau 
19409c80d176SSepherosa Ziehau 	return ret_val;
19419c80d176SSepherosa Ziehau }
19429c80d176SSepherosa Ziehau 
19439c80d176SSepherosa Ziehau /**
19446a5a645eSSepherosa Ziehau  *  e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex
19456a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
19466a5a645eSSepherosa Ziehau  *
19476a5a645eSSepherosa Ziehau  *  Forces the speed and duplex settings of the PHY.
19486a5a645eSSepherosa Ziehau  *  This is a function pointer entry point only called by
19496a5a645eSSepherosa Ziehau  *  PHY setup routines.
19506a5a645eSSepherosa Ziehau  **/
e1000_phy_force_speed_duplex_ife(struct e1000_hw * hw)19516a5a645eSSepherosa Ziehau s32 e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw)
19526a5a645eSSepherosa Ziehau {
19536a5a645eSSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
19546a5a645eSSepherosa Ziehau 	s32 ret_val;
19556a5a645eSSepherosa Ziehau 	u16 data;
19566a5a645eSSepherosa Ziehau 	bool link;
19576a5a645eSSepherosa Ziehau 
19586a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_phy_force_speed_duplex_ife");
19596a5a645eSSepherosa Ziehau 
19606a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data);
19616a5a645eSSepherosa Ziehau 	if (ret_val)
19624be59a01SSepherosa Ziehau 		return ret_val;
19636a5a645eSSepherosa Ziehau 
19646a5a645eSSepherosa Ziehau 	e1000_phy_force_speed_duplex_setup(hw, &data);
19656a5a645eSSepherosa Ziehau 
19666a5a645eSSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data);
19676a5a645eSSepherosa Ziehau 	if (ret_val)
19684be59a01SSepherosa Ziehau 		return ret_val;
19696a5a645eSSepherosa Ziehau 
19706a5a645eSSepherosa Ziehau 	/* Disable MDI-X support for 10/100 */
19716a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
19726a5a645eSSepherosa Ziehau 	if (ret_val)
19734be59a01SSepherosa Ziehau 		return ret_val;
19746a5a645eSSepherosa Ziehau 
19756a5a645eSSepherosa Ziehau 	data &= ~IFE_PMC_AUTO_MDIX;
19766a5a645eSSepherosa Ziehau 	data &= ~IFE_PMC_FORCE_MDIX;
19776a5a645eSSepherosa Ziehau 
19786a5a645eSSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data);
19796a5a645eSSepherosa Ziehau 	if (ret_val)
19804be59a01SSepherosa Ziehau 		return ret_val;
19816a5a645eSSepherosa Ziehau 
19826a5a645eSSepherosa Ziehau 	DEBUGOUT1("IFE PMC: %X\n", data);
19836a5a645eSSepherosa Ziehau 
19846a5a645eSSepherosa Ziehau 	usec_delay(1);
19856a5a645eSSepherosa Ziehau 
19866a5a645eSSepherosa Ziehau 	if (phy->autoneg_wait_to_complete) {
19876a5a645eSSepherosa Ziehau 		DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n");
19886a5a645eSSepherosa Ziehau 
19894be59a01SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
19904be59a01SSepherosa Ziehau 						     100000, &link);
19916a5a645eSSepherosa Ziehau 		if (ret_val)
19924be59a01SSepherosa Ziehau 			return ret_val;
19936a5a645eSSepherosa Ziehau 
19946a5a645eSSepherosa Ziehau 		if (!link)
19956a5a645eSSepherosa Ziehau 			DEBUGOUT("Link taking longer than expected.\n");
19966a5a645eSSepherosa Ziehau 
19976a5a645eSSepherosa Ziehau 		/* Try once more */
19984be59a01SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
19994be59a01SSepherosa Ziehau 						     100000, &link);
20006a5a645eSSepherosa Ziehau 		if (ret_val)
20014be59a01SSepherosa Ziehau 			return ret_val;
20026a5a645eSSepherosa Ziehau 	}
20036a5a645eSSepherosa Ziehau 
20044be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
20056a5a645eSSepherosa Ziehau }
20066a5a645eSSepherosa Ziehau 
20076a5a645eSSepherosa Ziehau /**
20089c80d176SSepherosa Ziehau  *  e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex
20099c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
20109c80d176SSepherosa Ziehau  *  @phy_ctrl: pointer to current value of PHY_CONTROL
20119c80d176SSepherosa Ziehau  *
20129c80d176SSepherosa Ziehau  *  Forces speed and duplex on the PHY by doing the following: disable flow
20139c80d176SSepherosa Ziehau  *  control, force speed/duplex on the MAC, disable auto speed detection,
20149c80d176SSepherosa Ziehau  *  disable auto-negotiation, configure duplex, configure speed, configure
20159c80d176SSepherosa Ziehau  *  the collision distance, write configuration to CTRL register.  The
20169c80d176SSepherosa Ziehau  *  caller must write to the PHY_CONTROL register for these settings to
20179c80d176SSepherosa Ziehau  *  take affect.
20189c80d176SSepherosa Ziehau  **/
e1000_phy_force_speed_duplex_setup(struct e1000_hw * hw,u16 * phy_ctrl)20199c80d176SSepherosa Ziehau void e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl)
20209c80d176SSepherosa Ziehau {
20219c80d176SSepherosa Ziehau 	struct e1000_mac_info *mac = &hw->mac;
20229c80d176SSepherosa Ziehau 	u32 ctrl;
20239c80d176SSepherosa Ziehau 
20249c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_force_speed_duplex_setup");
20259c80d176SSepherosa Ziehau 
20269c80d176SSepherosa Ziehau 	/* Turn off flow control when forcing speed/duplex */
20279c80d176SSepherosa Ziehau 	hw->fc.current_mode = e1000_fc_none;
20289c80d176SSepherosa Ziehau 
20299c80d176SSepherosa Ziehau 	/* Force speed/duplex on the mac */
20309c80d176SSepherosa Ziehau 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
20319c80d176SSepherosa Ziehau 	ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
20329c80d176SSepherosa Ziehau 	ctrl &= ~E1000_CTRL_SPD_SEL;
20339c80d176SSepherosa Ziehau 
20349c80d176SSepherosa Ziehau 	/* Disable Auto Speed Detection */
20359c80d176SSepherosa Ziehau 	ctrl &= ~E1000_CTRL_ASDE;
20369c80d176SSepherosa Ziehau 
20379c80d176SSepherosa Ziehau 	/* Disable autoneg on the phy */
20389c80d176SSepherosa Ziehau 	*phy_ctrl &= ~MII_CR_AUTO_NEG_EN;
20399c80d176SSepherosa Ziehau 
20409c80d176SSepherosa Ziehau 	/* Forcing Full or Half Duplex? */
20419c80d176SSepherosa Ziehau 	if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) {
20429c80d176SSepherosa Ziehau 		ctrl &= ~E1000_CTRL_FD;
20439c80d176SSepherosa Ziehau 		*phy_ctrl &= ~MII_CR_FULL_DUPLEX;
20449c80d176SSepherosa Ziehau 		DEBUGOUT("Half Duplex\n");
20459c80d176SSepherosa Ziehau 	} else {
20469c80d176SSepherosa Ziehau 		ctrl |= E1000_CTRL_FD;
20479c80d176SSepherosa Ziehau 		*phy_ctrl |= MII_CR_FULL_DUPLEX;
20489c80d176SSepherosa Ziehau 		DEBUGOUT("Full Duplex\n");
20499c80d176SSepherosa Ziehau 	}
20509c80d176SSepherosa Ziehau 
20519c80d176SSepherosa Ziehau 	/* Forcing 10mb or 100mb? */
20529c80d176SSepherosa Ziehau 	if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) {
20539c80d176SSepherosa Ziehau 		ctrl |= E1000_CTRL_SPD_100;
20549c80d176SSepherosa Ziehau 		*phy_ctrl |= MII_CR_SPEED_100;
2055379ebbe7SSepherosa Ziehau 		*phy_ctrl &= ~MII_CR_SPEED_1000;
20569c80d176SSepherosa Ziehau 		DEBUGOUT("Forcing 100mb\n");
20579c80d176SSepherosa Ziehau 	} else {
20589c80d176SSepherosa Ziehau 		ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
20599c80d176SSepherosa Ziehau 		*phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100);
20609c80d176SSepherosa Ziehau 		DEBUGOUT("Forcing 10mb\n");
20619c80d176SSepherosa Ziehau 	}
20629c80d176SSepherosa Ziehau 
20634be59a01SSepherosa Ziehau 	hw->mac.ops.config_collision_dist(hw);
20649c80d176SSepherosa Ziehau 
20659c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
20669c80d176SSepherosa Ziehau }
20679c80d176SSepherosa Ziehau 
20689c80d176SSepherosa Ziehau /**
20699c80d176SSepherosa Ziehau  *  e1000_set_d3_lplu_state_generic - Sets low power link up state for D3
20709c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
20719c80d176SSepherosa Ziehau  *  @active: boolean used to enable/disable lplu
20729c80d176SSepherosa Ziehau  *
20739c80d176SSepherosa Ziehau  *  Success returns 0, Failure returns 1
20749c80d176SSepherosa Ziehau  *
20759c80d176SSepherosa Ziehau  *  The low power link up (lplu) state is set to the power management level D3
20769c80d176SSepherosa Ziehau  *  and SmartSpeed is disabled when active is TRUE, else clear lplu for D3
20779c80d176SSepherosa Ziehau  *  and enable Smartspeed.  LPLU and Smartspeed are mutually exclusive.  LPLU
20789c80d176SSepherosa Ziehau  *  is used during Dx states where the power conservation is most important.
20799c80d176SSepherosa Ziehau  *  During driver activity, SmartSpeed should be enabled so performance is
20809c80d176SSepherosa Ziehau  *  maintained.
20819c80d176SSepherosa Ziehau  **/
e1000_set_d3_lplu_state_generic(struct e1000_hw * hw,bool active)20829c80d176SSepherosa Ziehau s32 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active)
20839c80d176SSepherosa Ziehau {
20849c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
20854be59a01SSepherosa Ziehau 	s32 ret_val;
20869c80d176SSepherosa Ziehau 	u16 data;
20879c80d176SSepherosa Ziehau 
20889c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_set_d3_lplu_state_generic");
20899c80d176SSepherosa Ziehau 
20904be59a01SSepherosa Ziehau 	if (!hw->phy.ops.read_reg)
20914be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
20929c80d176SSepherosa Ziehau 
20939c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data);
20949c80d176SSepherosa Ziehau 	if (ret_val)
20954be59a01SSepherosa Ziehau 		return ret_val;
20969c80d176SSepherosa Ziehau 
20979c80d176SSepherosa Ziehau 	if (!active) {
20989c80d176SSepherosa Ziehau 		data &= ~IGP02E1000_PM_D3_LPLU;
20999c80d176SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
21009c80d176SSepherosa Ziehau 					     data);
21019c80d176SSepherosa Ziehau 		if (ret_val)
21024be59a01SSepherosa Ziehau 			return ret_val;
2103379ebbe7SSepherosa Ziehau 		/* LPLU and SmartSpeed are mutually exclusive.  LPLU is used
21049c80d176SSepherosa Ziehau 		 * during Dx states where the power conservation is most
21059c80d176SSepherosa Ziehau 		 * important.  During driver activity we should enable
21069c80d176SSepherosa Ziehau 		 * SmartSpeed, so performance is maintained.
21079c80d176SSepherosa Ziehau 		 */
21089c80d176SSepherosa Ziehau 		if (phy->smart_speed == e1000_smart_speed_on) {
21099c80d176SSepherosa Ziehau 			ret_val = phy->ops.read_reg(hw,
21109c80d176SSepherosa Ziehau 						    IGP01E1000_PHY_PORT_CONFIG,
21119c80d176SSepherosa Ziehau 						    &data);
21129c80d176SSepherosa Ziehau 			if (ret_val)
21134be59a01SSepherosa Ziehau 				return ret_val;
21149c80d176SSepherosa Ziehau 
21159c80d176SSepherosa Ziehau 			data |= IGP01E1000_PSCFR_SMART_SPEED;
21169c80d176SSepherosa Ziehau 			ret_val = phy->ops.write_reg(hw,
21179c80d176SSepherosa Ziehau 						     IGP01E1000_PHY_PORT_CONFIG,
21189c80d176SSepherosa Ziehau 						     data);
21199c80d176SSepherosa Ziehau 			if (ret_val)
21204be59a01SSepherosa Ziehau 				return ret_val;
21219c80d176SSepherosa Ziehau 		} else if (phy->smart_speed == e1000_smart_speed_off) {
21229c80d176SSepherosa Ziehau 			ret_val = phy->ops.read_reg(hw,
21239c80d176SSepherosa Ziehau 						    IGP01E1000_PHY_PORT_CONFIG,
21249c80d176SSepherosa Ziehau 						    &data);
21259c80d176SSepherosa Ziehau 			if (ret_val)
21264be59a01SSepherosa Ziehau 				return ret_val;
21279c80d176SSepherosa Ziehau 
21289c80d176SSepherosa Ziehau 			data &= ~IGP01E1000_PSCFR_SMART_SPEED;
21299c80d176SSepherosa Ziehau 			ret_val = phy->ops.write_reg(hw,
21309c80d176SSepherosa Ziehau 						     IGP01E1000_PHY_PORT_CONFIG,
21319c80d176SSepherosa Ziehau 						     data);
21329c80d176SSepherosa Ziehau 			if (ret_val)
21334be59a01SSepherosa Ziehau 				return ret_val;
21349c80d176SSepherosa Ziehau 		}
21359c80d176SSepherosa Ziehau 	} else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) ||
21369c80d176SSepherosa Ziehau 		   (phy->autoneg_advertised == E1000_ALL_NOT_GIG) ||
21379c80d176SSepherosa Ziehau 		   (phy->autoneg_advertised == E1000_ALL_10_SPEED)) {
21389c80d176SSepherosa Ziehau 		data |= IGP02E1000_PM_D3_LPLU;
21399c80d176SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, IGP02E1000_PHY_POWER_MGMT,
21409c80d176SSepherosa Ziehau 					     data);
21419c80d176SSepherosa Ziehau 		if (ret_val)
21424be59a01SSepherosa Ziehau 			return ret_val;
21439c80d176SSepherosa Ziehau 
21449c80d176SSepherosa Ziehau 		/* When LPLU is enabled, we should disable SmartSpeed */
21459c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
21469c80d176SSepherosa Ziehau 					    &data);
21479c80d176SSepherosa Ziehau 		if (ret_val)
21484be59a01SSepherosa Ziehau 			return ret_val;
21499c80d176SSepherosa Ziehau 
21509c80d176SSepherosa Ziehau 		data &= ~IGP01E1000_PSCFR_SMART_SPEED;
21519c80d176SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CONFIG,
21529c80d176SSepherosa Ziehau 					     data);
21539c80d176SSepherosa Ziehau 	}
21549c80d176SSepherosa Ziehau 
21559c80d176SSepherosa Ziehau 	return ret_val;
21569c80d176SSepherosa Ziehau }
21579c80d176SSepherosa Ziehau 
21589c80d176SSepherosa Ziehau /**
21599c80d176SSepherosa Ziehau  *  e1000_check_downshift_generic - Checks whether a downshift in speed occurred
21609c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
21619c80d176SSepherosa Ziehau  *
21629c80d176SSepherosa Ziehau  *  Success returns 0, Failure returns 1
21639c80d176SSepherosa Ziehau  *
21649c80d176SSepherosa Ziehau  *  A downshift is detected by querying the PHY link health.
21659c80d176SSepherosa Ziehau  **/
e1000_check_downshift_generic(struct e1000_hw * hw)21669c80d176SSepherosa Ziehau s32 e1000_check_downshift_generic(struct e1000_hw *hw)
21679c80d176SSepherosa Ziehau {
21689c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
21699c80d176SSepherosa Ziehau 	s32 ret_val;
21709c80d176SSepherosa Ziehau 	u16 phy_data, offset, mask;
21719c80d176SSepherosa Ziehau 
21729c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_check_downshift_generic");
21739c80d176SSepherosa Ziehau 
21749c80d176SSepherosa Ziehau 	switch (phy->type) {
21754be59a01SSepherosa Ziehau 	case e1000_phy_i210:
21769c80d176SSepherosa Ziehau 	case e1000_phy_m88:
21779c80d176SSepherosa Ziehau 	case e1000_phy_gg82563:
21789c80d176SSepherosa Ziehau 	case e1000_phy_bm:
21796a5a645eSSepherosa Ziehau 	case e1000_phy_82578:
21809c80d176SSepherosa Ziehau 		offset = M88E1000_PHY_SPEC_STATUS;
21819c80d176SSepherosa Ziehau 		mask = M88E1000_PSSR_DOWNSHIFT;
21829c80d176SSepherosa Ziehau 		break;
21839c80d176SSepherosa Ziehau 	case e1000_phy_igp:
21846a5a645eSSepherosa Ziehau 	case e1000_phy_igp_2:
21859c80d176SSepherosa Ziehau 	case e1000_phy_igp_3:
21869c80d176SSepherosa Ziehau 		offset = IGP01E1000_PHY_LINK_HEALTH;
21879c80d176SSepherosa Ziehau 		mask = IGP01E1000_PLHR_SS_DOWNGRADE;
21889c80d176SSepherosa Ziehau 		break;
21899c80d176SSepherosa Ziehau 	default:
21909c80d176SSepherosa Ziehau 		/* speed downshift not supported */
21919c80d176SSepherosa Ziehau 		phy->speed_downgraded = FALSE;
21924be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
21939c80d176SSepherosa Ziehau 	}
21949c80d176SSepherosa Ziehau 
21959c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, offset, &phy_data);
21969c80d176SSepherosa Ziehau 
21979c80d176SSepherosa Ziehau 	if (!ret_val)
21984be59a01SSepherosa Ziehau 		phy->speed_downgraded = !!(phy_data & mask);
21999c80d176SSepherosa Ziehau 
22009c80d176SSepherosa Ziehau 	return ret_val;
22019c80d176SSepherosa Ziehau }
22029c80d176SSepherosa Ziehau 
22039c80d176SSepherosa Ziehau /**
22049c80d176SSepherosa Ziehau  *  e1000_check_polarity_m88 - Checks the polarity.
22059c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
22069c80d176SSepherosa Ziehau  *
22079c80d176SSepherosa Ziehau  *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
22089c80d176SSepherosa Ziehau  *
22099c80d176SSepherosa Ziehau  *  Polarity is determined based on the PHY specific status register.
22109c80d176SSepherosa Ziehau  **/
e1000_check_polarity_m88(struct e1000_hw * hw)22119c80d176SSepherosa Ziehau s32 e1000_check_polarity_m88(struct e1000_hw *hw)
22129c80d176SSepherosa Ziehau {
22139c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
22149c80d176SSepherosa Ziehau 	s32 ret_val;
22159c80d176SSepherosa Ziehau 	u16 data;
22169c80d176SSepherosa Ziehau 
22179c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_check_polarity_m88");
22189c80d176SSepherosa Ziehau 
22199c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data);
22209c80d176SSepherosa Ziehau 
22219c80d176SSepherosa Ziehau 	if (!ret_val)
2222379ebbe7SSepherosa Ziehau 		phy->cable_polarity = ((data & M88E1000_PSSR_REV_POLARITY)
22239c80d176SSepherosa Ziehau 				       ? e1000_rev_polarity_reversed
2224379ebbe7SSepherosa Ziehau 				       : e1000_rev_polarity_normal);
22259c80d176SSepherosa Ziehau 
22269c80d176SSepherosa Ziehau 	return ret_val;
22279c80d176SSepherosa Ziehau }
22289c80d176SSepherosa Ziehau 
22299c80d176SSepherosa Ziehau /**
22309c80d176SSepherosa Ziehau  *  e1000_check_polarity_igp - Checks the polarity.
22319c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
22329c80d176SSepherosa Ziehau  *
22339c80d176SSepherosa Ziehau  *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
22349c80d176SSepherosa Ziehau  *
22359c80d176SSepherosa Ziehau  *  Polarity is determined based on the PHY port status register, and the
22369c80d176SSepherosa Ziehau  *  current speed (since there is no polarity at 100Mbps).
22379c80d176SSepherosa Ziehau  **/
e1000_check_polarity_igp(struct e1000_hw * hw)22389c80d176SSepherosa Ziehau s32 e1000_check_polarity_igp(struct e1000_hw *hw)
22399c80d176SSepherosa Ziehau {
22409c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
22419c80d176SSepherosa Ziehau 	s32 ret_val;
22429c80d176SSepherosa Ziehau 	u16 data, offset, mask;
22439c80d176SSepherosa Ziehau 
22449c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_check_polarity_igp");
22459c80d176SSepherosa Ziehau 
2246379ebbe7SSepherosa Ziehau 	/* Polarity is determined based on the speed of
22479c80d176SSepherosa Ziehau 	 * our connection.
22489c80d176SSepherosa Ziehau 	 */
22499c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
22509c80d176SSepherosa Ziehau 	if (ret_val)
22514be59a01SSepherosa Ziehau 		return ret_val;
22529c80d176SSepherosa Ziehau 
22539c80d176SSepherosa Ziehau 	if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
22549c80d176SSepherosa Ziehau 	    IGP01E1000_PSSR_SPEED_1000MBPS) {
22559c80d176SSepherosa Ziehau 		offset = IGP01E1000_PHY_PCS_INIT_REG;
22569c80d176SSepherosa Ziehau 		mask = IGP01E1000_PHY_POLARITY_MASK;
22579c80d176SSepherosa Ziehau 	} else {
2258379ebbe7SSepherosa Ziehau 		/* This really only applies to 10Mbps since
22599c80d176SSepherosa Ziehau 		 * there is no polarity for 100Mbps (always 0).
22609c80d176SSepherosa Ziehau 		 */
22619c80d176SSepherosa Ziehau 		offset = IGP01E1000_PHY_PORT_STATUS;
22629c80d176SSepherosa Ziehau 		mask = IGP01E1000_PSSR_POLARITY_REVERSED;
22639c80d176SSepherosa Ziehau 	}
22649c80d176SSepherosa Ziehau 
22659c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, offset, &data);
22669c80d176SSepherosa Ziehau 
22679c80d176SSepherosa Ziehau 	if (!ret_val)
2268379ebbe7SSepherosa Ziehau 		phy->cable_polarity = ((data & mask)
22699c80d176SSepherosa Ziehau 				       ? e1000_rev_polarity_reversed
2270379ebbe7SSepherosa Ziehau 				       : e1000_rev_polarity_normal);
22719c80d176SSepherosa Ziehau 
22729c80d176SSepherosa Ziehau 	return ret_val;
22739c80d176SSepherosa Ziehau }
22749c80d176SSepherosa Ziehau 
22759c80d176SSepherosa Ziehau /**
22766a5a645eSSepherosa Ziehau  *  e1000_check_polarity_ife - Check cable polarity for IFE PHY
22776a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
22786a5a645eSSepherosa Ziehau  *
22796a5a645eSSepherosa Ziehau  *  Polarity is determined on the polarity reversal feature being enabled.
22806a5a645eSSepherosa Ziehau  **/
e1000_check_polarity_ife(struct e1000_hw * hw)22816a5a645eSSepherosa Ziehau s32 e1000_check_polarity_ife(struct e1000_hw *hw)
22826a5a645eSSepherosa Ziehau {
22836a5a645eSSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
22846a5a645eSSepherosa Ziehau 	s32 ret_val;
22856a5a645eSSepherosa Ziehau 	u16 phy_data, offset, mask;
22866a5a645eSSepherosa Ziehau 
22876a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_check_polarity_ife");
22886a5a645eSSepherosa Ziehau 
2289379ebbe7SSepherosa Ziehau 	/* Polarity is determined based on the reversal feature being enabled.
22906a5a645eSSepherosa Ziehau 	 */
22916a5a645eSSepherosa Ziehau 	if (phy->polarity_correction) {
22926a5a645eSSepherosa Ziehau 		offset = IFE_PHY_EXTENDED_STATUS_CONTROL;
22936a5a645eSSepherosa Ziehau 		mask = IFE_PESC_POLARITY_REVERSED;
22946a5a645eSSepherosa Ziehau 	} else {
22956a5a645eSSepherosa Ziehau 		offset = IFE_PHY_SPECIAL_CONTROL;
22966a5a645eSSepherosa Ziehau 		mask = IFE_PSC_FORCE_POLARITY;
22976a5a645eSSepherosa Ziehau 	}
22986a5a645eSSepherosa Ziehau 
22996a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, offset, &phy_data);
23006a5a645eSSepherosa Ziehau 
23016a5a645eSSepherosa Ziehau 	if (!ret_val)
2302379ebbe7SSepherosa Ziehau 		phy->cable_polarity = ((phy_data & mask)
23036a5a645eSSepherosa Ziehau 				       ? e1000_rev_polarity_reversed
2304379ebbe7SSepherosa Ziehau 				       : e1000_rev_polarity_normal);
23056a5a645eSSepherosa Ziehau 
23066a5a645eSSepherosa Ziehau 	return ret_val;
23076a5a645eSSepherosa Ziehau }
23086a5a645eSSepherosa Ziehau 
23096a5a645eSSepherosa Ziehau /**
2310379ebbe7SSepherosa Ziehau  *  e1000_wait_autoneg - Wait for auto-neg completion
23119c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
23129c80d176SSepherosa Ziehau  *
23139c80d176SSepherosa Ziehau  *  Waits for auto-negotiation to complete or for the auto-negotiation time
23149c80d176SSepherosa Ziehau  *  limit to expire, which ever happens first.
23159c80d176SSepherosa Ziehau  **/
e1000_wait_autoneg(struct e1000_hw * hw)2316379ebbe7SSepherosa Ziehau static s32 e1000_wait_autoneg(struct e1000_hw *hw)
23179c80d176SSepherosa Ziehau {
23189c80d176SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
23199c80d176SSepherosa Ziehau 	u16 i, phy_status;
23209c80d176SSepherosa Ziehau 
2321379ebbe7SSepherosa Ziehau 	DEBUGFUNC("e1000_wait_autoneg");
23229c80d176SSepherosa Ziehau 
23234be59a01SSepherosa Ziehau 	if (!hw->phy.ops.read_reg)
23249c80d176SSepherosa Ziehau 		return E1000_SUCCESS;
23259c80d176SSepherosa Ziehau 
23269c80d176SSepherosa Ziehau 	/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
23279c80d176SSepherosa Ziehau 	for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
23289c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
23299c80d176SSepherosa Ziehau 		if (ret_val)
23309c80d176SSepherosa Ziehau 			break;
23319c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
23329c80d176SSepherosa Ziehau 		if (ret_val)
23339c80d176SSepherosa Ziehau 			break;
23349c80d176SSepherosa Ziehau 		if (phy_status & MII_SR_AUTONEG_COMPLETE)
23359c80d176SSepherosa Ziehau 			break;
23369c80d176SSepherosa Ziehau 		msec_delay(100);
23379c80d176SSepherosa Ziehau 	}
23389c80d176SSepherosa Ziehau 
2339379ebbe7SSepherosa Ziehau 	/* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
23409c80d176SSepherosa Ziehau 	 * has completed.
23419c80d176SSepherosa Ziehau 	 */
23429c80d176SSepherosa Ziehau 	return ret_val;
23439c80d176SSepherosa Ziehau }
23449c80d176SSepherosa Ziehau 
23459c80d176SSepherosa Ziehau /**
23469c80d176SSepherosa Ziehau  *  e1000_phy_has_link_generic - Polls PHY for link
23479c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
23489c80d176SSepherosa Ziehau  *  @iterations: number of times to poll for link
23499c80d176SSepherosa Ziehau  *  @usec_interval: delay between polling attempts
23509c80d176SSepherosa Ziehau  *  @success: pointer to whether polling was successful or not
23519c80d176SSepherosa Ziehau  *
23529c80d176SSepherosa Ziehau  *  Polls the PHY status register for link, 'iterations' number of times.
23539c80d176SSepherosa Ziehau  **/
e1000_phy_has_link_generic(struct e1000_hw * hw,u32 iterations,u32 usec_interval,bool * success)23549c80d176SSepherosa Ziehau s32 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations,
23559c80d176SSepherosa Ziehau 			       u32 usec_interval, bool *success)
23569c80d176SSepherosa Ziehau {
23579c80d176SSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
23589c80d176SSepherosa Ziehau 	u16 i, phy_status;
23599c80d176SSepherosa Ziehau 
23609c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_has_link_generic");
23619c80d176SSepherosa Ziehau 
23624be59a01SSepherosa Ziehau 	if (!hw->phy.ops.read_reg)
23639c80d176SSepherosa Ziehau 		return E1000_SUCCESS;
23649c80d176SSepherosa Ziehau 
23659c80d176SSepherosa Ziehau 	for (i = 0; i < iterations; i++) {
2366379ebbe7SSepherosa Ziehau 		/* Some PHYs require the PHY_STATUS register to be read
23679c80d176SSepherosa Ziehau 		 * twice due to the link bit being sticky.  No harm doing
23689c80d176SSepherosa Ziehau 		 * it across the board.
23699c80d176SSepherosa Ziehau 		 */
23709c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
23714765c386SMichael Neumann 		if (ret_val) {
2372379ebbe7SSepherosa Ziehau 			/* If the first read fails, another entity may have
23736a5a645eSSepherosa Ziehau 			 * ownership of the resources, wait and try again to
23746a5a645eSSepherosa Ziehau 			 * see if they have relinquished the resources yet.
23756a5a645eSSepherosa Ziehau 			 */
23764765c386SMichael Neumann 			if (usec_interval >= 1000)
23774765c386SMichael Neumann 				msec_delay(usec_interval/1000);
23784765c386SMichael Neumann 			else
23796a5a645eSSepherosa Ziehau 				usec_delay(usec_interval);
23804765c386SMichael Neumann 		}
23819c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
23829c80d176SSepherosa Ziehau 		if (ret_val)
23839c80d176SSepherosa Ziehau 			break;
23849c80d176SSepherosa Ziehau 		if (phy_status & MII_SR_LINK_STATUS)
23859c80d176SSepherosa Ziehau 			break;
23869c80d176SSepherosa Ziehau 		if (usec_interval >= 1000)
23874765c386SMichael Neumann 			msec_delay(usec_interval/1000);
23889c80d176SSepherosa Ziehau 		else
23899c80d176SSepherosa Ziehau 			usec_delay(usec_interval);
23909c80d176SSepherosa Ziehau 	}
23919c80d176SSepherosa Ziehau 
23924be59a01SSepherosa Ziehau 	*success = (i < iterations);
23939c80d176SSepherosa Ziehau 
23949c80d176SSepherosa Ziehau 	return ret_val;
23959c80d176SSepherosa Ziehau }
23969c80d176SSepherosa Ziehau 
23979c80d176SSepherosa Ziehau /**
23989c80d176SSepherosa Ziehau  *  e1000_get_cable_length_m88 - Determine cable length for m88 PHY
23999c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
24009c80d176SSepherosa Ziehau  *
24019c80d176SSepherosa Ziehau  *  Reads the PHY specific status register to retrieve the cable length
24029c80d176SSepherosa Ziehau  *  information.  The cable length is determined by averaging the minimum and
24039c80d176SSepherosa Ziehau  *  maximum values to get the "average" cable length.  The m88 PHY has four
24049c80d176SSepherosa Ziehau  *  possible cable length values, which are:
24059c80d176SSepherosa Ziehau  *	Register Value		Cable Length
24069c80d176SSepherosa Ziehau  *	0			< 50 meters
24079c80d176SSepherosa Ziehau  *	1			50 - 80 meters
24089c80d176SSepherosa Ziehau  *	2			80 - 110 meters
24099c80d176SSepherosa Ziehau  *	3			110 - 140 meters
24109c80d176SSepherosa Ziehau  *	4			> 140 meters
24119c80d176SSepherosa Ziehau  **/
e1000_get_cable_length_m88(struct e1000_hw * hw)24129c80d176SSepherosa Ziehau s32 e1000_get_cable_length_m88(struct e1000_hw *hw)
24139c80d176SSepherosa Ziehau {
24149c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
24159c80d176SSepherosa Ziehau 	s32 ret_val;
24169c80d176SSepherosa Ziehau 	u16 phy_data, index;
24179c80d176SSepherosa Ziehau 
24189c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_get_cable_length_m88");
24199c80d176SSepherosa Ziehau 
24209c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
24219c80d176SSepherosa Ziehau 	if (ret_val)
24224be59a01SSepherosa Ziehau 		return ret_val;
24239c80d176SSepherosa Ziehau 
2424379ebbe7SSepherosa Ziehau 	index = ((phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
2425379ebbe7SSepherosa Ziehau 		 M88E1000_PSSR_CABLE_LENGTH_SHIFT);
24264be59a01SSepherosa Ziehau 
24274be59a01SSepherosa Ziehau 	if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
24284be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
24296a5a645eSSepherosa Ziehau 
24309c80d176SSepherosa Ziehau 	phy->min_cable_length = e1000_m88_cable_length_table[index];
24319c80d176SSepherosa Ziehau 	phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
24329c80d176SSepherosa Ziehau 
24336a5a645eSSepherosa Ziehau 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
24349c80d176SSepherosa Ziehau 
24354be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
24369c80d176SSepherosa Ziehau }
24379c80d176SSepherosa Ziehau 
e1000_get_cable_length_m88_gen2(struct e1000_hw * hw)243862583d18SSepherosa Ziehau s32 e1000_get_cable_length_m88_gen2(struct e1000_hw *hw)
243962583d18SSepherosa Ziehau {
244062583d18SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
244162583d18SSepherosa Ziehau 	s32 ret_val;
2442379ebbe7SSepherosa Ziehau 	u16 phy_data, phy_data2, is_cm;
2443379ebbe7SSepherosa Ziehau 	u16 index, default_page;
244462583d18SSepherosa Ziehau 
244562583d18SSepherosa Ziehau 	DEBUGFUNC("e1000_get_cable_length_m88_gen2");
244662583d18SSepherosa Ziehau 
244762583d18SSepherosa Ziehau 	switch (hw->phy.id) {
24484be59a01SSepherosa Ziehau 	case I210_I_PHY_ID:
24494be59a01SSepherosa Ziehau 		/* Get cable length from PHY Cable Diagnostics Control Reg */
24504be59a01SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
24514be59a01SSepherosa Ziehau 					    (I347AT4_PCDL + phy->addr),
24524be59a01SSepherosa Ziehau 					    &phy_data);
24534be59a01SSepherosa Ziehau 		if (ret_val)
24544be59a01SSepherosa Ziehau 			return ret_val;
24554be59a01SSepherosa Ziehau 
24564be59a01SSepherosa Ziehau 		/* Check if the unit of cable length is meters or cm */
24574be59a01SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, (0x7 << GS40G_PAGE_SHIFT) +
24584be59a01SSepherosa Ziehau 					    I347AT4_PCDC, &phy_data2);
24594be59a01SSepherosa Ziehau 		if (ret_val)
24604be59a01SSepherosa Ziehau 			return ret_val;
24614be59a01SSepherosa Ziehau 
24624be59a01SSepherosa Ziehau 		is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
24634be59a01SSepherosa Ziehau 
24644be59a01SSepherosa Ziehau 		/* Populate the phy structure with cable length in meters */
24654be59a01SSepherosa Ziehau 		phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
24664be59a01SSepherosa Ziehau 		phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
24674be59a01SSepherosa Ziehau 		phy->cable_length = phy_data / (is_cm ? 100 : 1);
24684be59a01SSepherosa Ziehau 		break;
2469ba0123e0SSepherosa Ziehau 	case M88E1543_E_PHY_ID:
2470ba0123e0SSepherosa Ziehau 	case M88E1512_E_PHY_ID:
247162583d18SSepherosa Ziehau 	case M88E1340M_E_PHY_ID:
247262583d18SSepherosa Ziehau 	case I347AT4_E_PHY_ID:
247362583d18SSepherosa Ziehau 		/* Remember the original page select and set it to 7 */
247462583d18SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
247562583d18SSepherosa Ziehau 					    &default_page);
247662583d18SSepherosa Ziehau 		if (ret_val)
24774be59a01SSepherosa Ziehau 			return ret_val;
247862583d18SSepherosa Ziehau 
247962583d18SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x07);
248062583d18SSepherosa Ziehau 		if (ret_val)
24814be59a01SSepherosa Ziehau 			return ret_val;
248262583d18SSepherosa Ziehau 
248362583d18SSepherosa Ziehau 		/* Get cable length from PHY Cable Diagnostics Control Reg */
248462583d18SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, (I347AT4_PCDL + phy->addr),
248562583d18SSepherosa Ziehau 					    &phy_data);
248662583d18SSepherosa Ziehau 		if (ret_val)
24874be59a01SSepherosa Ziehau 			return ret_val;
248862583d18SSepherosa Ziehau 
248962583d18SSepherosa Ziehau 		/* Check if the unit of cable length is meters or cm */
249062583d18SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, I347AT4_PCDC, &phy_data2);
249162583d18SSepherosa Ziehau 		if (ret_val)
24924be59a01SSepherosa Ziehau 			return ret_val;
249362583d18SSepherosa Ziehau 
24944be59a01SSepherosa Ziehau 		is_cm = !(phy_data2 & I347AT4_PCDC_CABLE_LENGTH_UNIT);
249562583d18SSepherosa Ziehau 
249662583d18SSepherosa Ziehau 		/* Populate the phy structure with cable length in meters */
249762583d18SSepherosa Ziehau 		phy->min_cable_length = phy_data / (is_cm ? 100 : 1);
249862583d18SSepherosa Ziehau 		phy->max_cable_length = phy_data / (is_cm ? 100 : 1);
249962583d18SSepherosa Ziehau 		phy->cable_length = phy_data / (is_cm ? 100 : 1);
250062583d18SSepherosa Ziehau 
25014be59a01SSepherosa Ziehau 		/* Reset the page select to its original value */
250262583d18SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
250362583d18SSepherosa Ziehau 					     default_page);
250462583d18SSepherosa Ziehau 		if (ret_val)
25054be59a01SSepherosa Ziehau 			return ret_val;
250662583d18SSepherosa Ziehau 		break;
25074be59a01SSepherosa Ziehau 
250862583d18SSepherosa Ziehau 	case M88E1112_E_PHY_ID:
250962583d18SSepherosa Ziehau 		/* Remember the original page select and set it to 5 */
251062583d18SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, I347AT4_PAGE_SELECT,
251162583d18SSepherosa Ziehau 					    &default_page);
251262583d18SSepherosa Ziehau 		if (ret_val)
25134be59a01SSepherosa Ziehau 			return ret_val;
251462583d18SSepherosa Ziehau 
251562583d18SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT, 0x05);
251662583d18SSepherosa Ziehau 		if (ret_val)
25174be59a01SSepherosa Ziehau 			return ret_val;
251862583d18SSepherosa Ziehau 
251962583d18SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, M88E1112_VCT_DSP_DISTANCE,
252062583d18SSepherosa Ziehau 					    &phy_data);
252162583d18SSepherosa Ziehau 		if (ret_val)
25224be59a01SSepherosa Ziehau 			return ret_val;
252362583d18SSepherosa Ziehau 
252462583d18SSepherosa Ziehau 		index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >>
252562583d18SSepherosa Ziehau 			M88E1000_PSSR_CABLE_LENGTH_SHIFT;
25264be59a01SSepherosa Ziehau 
25274be59a01SSepherosa Ziehau 		if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1)
25284be59a01SSepherosa Ziehau 			return -E1000_ERR_PHY;
252962583d18SSepherosa Ziehau 
253062583d18SSepherosa Ziehau 		phy->min_cable_length = e1000_m88_cable_length_table[index];
253162583d18SSepherosa Ziehau 		phy->max_cable_length = e1000_m88_cable_length_table[index + 1];
253262583d18SSepherosa Ziehau 
253362583d18SSepherosa Ziehau 		phy->cable_length = (phy->min_cable_length +
253462583d18SSepherosa Ziehau 				     phy->max_cable_length) / 2;
253562583d18SSepherosa Ziehau 
253662583d18SSepherosa Ziehau 		/* Reset the page select to its original value */
253762583d18SSepherosa Ziehau 		ret_val = phy->ops.write_reg(hw, I347AT4_PAGE_SELECT,
253862583d18SSepherosa Ziehau 					     default_page);
253962583d18SSepherosa Ziehau 		if (ret_val)
25404be59a01SSepherosa Ziehau 			return ret_val;
254162583d18SSepherosa Ziehau 
254262583d18SSepherosa Ziehau 		break;
254362583d18SSepherosa Ziehau 	default:
25444be59a01SSepherosa Ziehau 		return -E1000_ERR_PHY;
254562583d18SSepherosa Ziehau 	}
254662583d18SSepherosa Ziehau 
254762583d18SSepherosa Ziehau 	return ret_val;
254862583d18SSepherosa Ziehau }
254962583d18SSepherosa Ziehau 
25509c80d176SSepherosa Ziehau /**
25519c80d176SSepherosa Ziehau  *  e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY
25529c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
25539c80d176SSepherosa Ziehau  *
25549c80d176SSepherosa Ziehau  *  The automatic gain control (agc) normalizes the amplitude of the
25559c80d176SSepherosa Ziehau  *  received signal, adjusting for the attenuation produced by the
25569c80d176SSepherosa Ziehau  *  cable.  By reading the AGC registers, which represent the
25579c80d176SSepherosa Ziehau  *  combination of coarse and fine gain value, the value can be put
25589c80d176SSepherosa Ziehau  *  into a lookup table to obtain the approximate cable length
25599c80d176SSepherosa Ziehau  *  for each channel.
25609c80d176SSepherosa Ziehau  **/
e1000_get_cable_length_igp_2(struct e1000_hw * hw)25619c80d176SSepherosa Ziehau s32 e1000_get_cable_length_igp_2(struct e1000_hw *hw)
25629c80d176SSepherosa Ziehau {
25639c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
25644be59a01SSepherosa Ziehau 	s32 ret_val;
25659c80d176SSepherosa Ziehau 	u16 phy_data, i, agc_value = 0;
25669c80d176SSepherosa Ziehau 	u16 cur_agc_index, max_agc_index = 0;
25679c80d176SSepherosa Ziehau 	u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1;
25686d5e2922SSepherosa Ziehau 	static const u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = {
25696d5e2922SSepherosa Ziehau 		IGP02E1000_PHY_AGC_A,
25709c80d176SSepherosa Ziehau 		IGP02E1000_PHY_AGC_B,
25719c80d176SSepherosa Ziehau 		IGP02E1000_PHY_AGC_C,
25726d5e2922SSepherosa Ziehau 		IGP02E1000_PHY_AGC_D
25736d5e2922SSepherosa Ziehau 	};
25749c80d176SSepherosa Ziehau 
25759c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_get_cable_length_igp_2");
25769c80d176SSepherosa Ziehau 
25779c80d176SSepherosa Ziehau 	/* Read the AGC registers for all channels */
25789c80d176SSepherosa Ziehau 	for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) {
25799c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data);
25809c80d176SSepherosa Ziehau 		if (ret_val)
25814be59a01SSepherosa Ziehau 			return ret_val;
25829c80d176SSepherosa Ziehau 
2583379ebbe7SSepherosa Ziehau 		/* Getting bits 15:9, which represent the combination of
25849c80d176SSepherosa Ziehau 		 * coarse and fine gain values.  The result is a number
25859c80d176SSepherosa Ziehau 		 * that can be put into the lookup table to obtain the
25869c80d176SSepherosa Ziehau 		 * approximate cable length.
25879c80d176SSepherosa Ziehau 		 */
2588379ebbe7SSepherosa Ziehau 		cur_agc_index = ((phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) &
2589379ebbe7SSepherosa Ziehau 				 IGP02E1000_AGC_LENGTH_MASK);
25909c80d176SSepherosa Ziehau 
25919c80d176SSepherosa Ziehau 		/* Array index bound check. */
25929c80d176SSepherosa Ziehau 		if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) ||
25934be59a01SSepherosa Ziehau 		    (cur_agc_index == 0))
25944be59a01SSepherosa Ziehau 			return -E1000_ERR_PHY;
25959c80d176SSepherosa Ziehau 
25969c80d176SSepherosa Ziehau 		/* Remove min & max AGC values from calculation. */
25979c80d176SSepherosa Ziehau 		if (e1000_igp_2_cable_length_table[min_agc_index] >
25989c80d176SSepherosa Ziehau 		    e1000_igp_2_cable_length_table[cur_agc_index])
25999c80d176SSepherosa Ziehau 			min_agc_index = cur_agc_index;
26009c80d176SSepherosa Ziehau 		if (e1000_igp_2_cable_length_table[max_agc_index] <
26019c80d176SSepherosa Ziehau 		    e1000_igp_2_cable_length_table[cur_agc_index])
26029c80d176SSepherosa Ziehau 			max_agc_index = cur_agc_index;
26039c80d176SSepherosa Ziehau 
26049c80d176SSepherosa Ziehau 		agc_value += e1000_igp_2_cable_length_table[cur_agc_index];
26059c80d176SSepherosa Ziehau 	}
26069c80d176SSepherosa Ziehau 
26079c80d176SSepherosa Ziehau 	agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] +
26089c80d176SSepherosa Ziehau 		      e1000_igp_2_cable_length_table[max_agc_index]);
26099c80d176SSepherosa Ziehau 	agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2);
26109c80d176SSepherosa Ziehau 
26119c80d176SSepherosa Ziehau 	/* Calculate cable length with the error range of +/- 10 meters. */
2612379ebbe7SSepherosa Ziehau 	phy->min_cable_length = (((agc_value - IGP02E1000_AGC_RANGE) > 0) ?
2613379ebbe7SSepherosa Ziehau 				 (agc_value - IGP02E1000_AGC_RANGE) : 0);
26149c80d176SSepherosa Ziehau 	phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE;
26159c80d176SSepherosa Ziehau 
26169c80d176SSepherosa Ziehau 	phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2;
26179c80d176SSepherosa Ziehau 
26184be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
26199c80d176SSepherosa Ziehau }
26209c80d176SSepherosa Ziehau 
26219c80d176SSepherosa Ziehau /**
26229c80d176SSepherosa Ziehau  *  e1000_get_phy_info_m88 - Retrieve PHY information
26239c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
26249c80d176SSepherosa Ziehau  *
26259c80d176SSepherosa Ziehau  *  Valid for only copper links.  Read the PHY status register (sticky read)
26269c80d176SSepherosa Ziehau  *  to verify that link is up.  Read the PHY special control register to
26279c80d176SSepherosa Ziehau  *  determine the polarity and 10base-T extended distance.  Read the PHY
26289c80d176SSepherosa Ziehau  *  special status register to determine MDI/MDIx and current speed.  If
26299c80d176SSepherosa Ziehau  *  speed is 1000, then determine cable length, local and remote receiver.
26309c80d176SSepherosa Ziehau  **/
e1000_get_phy_info_m88(struct e1000_hw * hw)26319c80d176SSepherosa Ziehau s32 e1000_get_phy_info_m88(struct e1000_hw *hw)
26329c80d176SSepherosa Ziehau {
26339c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
26349c80d176SSepherosa Ziehau 	s32  ret_val;
26359c80d176SSepherosa Ziehau 	u16 phy_data;
26369c80d176SSepherosa Ziehau 	bool link;
26379c80d176SSepherosa Ziehau 
26389c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_get_phy_info_m88");
26399c80d176SSepherosa Ziehau 
26406a5a645eSSepherosa Ziehau 	if (phy->media_type != e1000_media_type_copper) {
26419c80d176SSepherosa Ziehau 		DEBUGOUT("Phy info is only valid for copper media\n");
26424be59a01SSepherosa Ziehau 		return -E1000_ERR_CONFIG;
26439c80d176SSepherosa Ziehau 	}
26449c80d176SSepherosa Ziehau 
26459c80d176SSepherosa Ziehau 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
26469c80d176SSepherosa Ziehau 	if (ret_val)
26474be59a01SSepherosa Ziehau 		return ret_val;
26489c80d176SSepherosa Ziehau 
26499c80d176SSepherosa Ziehau 	if (!link) {
26509c80d176SSepherosa Ziehau 		DEBUGOUT("Phy info is only valid if link is up\n");
26514be59a01SSepherosa Ziehau 		return -E1000_ERR_CONFIG;
26529c80d176SSepherosa Ziehau 	}
26539c80d176SSepherosa Ziehau 
26549c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data);
26559c80d176SSepherosa Ziehau 	if (ret_val)
26564be59a01SSepherosa Ziehau 		return ret_val;
26579c80d176SSepherosa Ziehau 
26584be59a01SSepherosa Ziehau 	phy->polarity_correction = !!(phy_data &
26594be59a01SSepherosa Ziehau 				      M88E1000_PSCR_POLARITY_REVERSAL);
26609c80d176SSepherosa Ziehau 
26619c80d176SSepherosa Ziehau 	ret_val = e1000_check_polarity_m88(hw);
26629c80d176SSepherosa Ziehau 	if (ret_val)
26634be59a01SSepherosa Ziehau 		return ret_val;
26649c80d176SSepherosa Ziehau 
26659c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data);
26669c80d176SSepherosa Ziehau 	if (ret_val)
26674be59a01SSepherosa Ziehau 		return ret_val;
26689c80d176SSepherosa Ziehau 
26694be59a01SSepherosa Ziehau 	phy->is_mdix = !!(phy_data & M88E1000_PSSR_MDIX);
26709c80d176SSepherosa Ziehau 
26719c80d176SSepherosa Ziehau 	if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) {
26729c80d176SSepherosa Ziehau 		ret_val = hw->phy.ops.get_cable_length(hw);
26739c80d176SSepherosa Ziehau 		if (ret_val)
26744be59a01SSepherosa Ziehau 			return ret_val;
26759c80d176SSepherosa Ziehau 
26769c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data);
26779c80d176SSepherosa Ziehau 		if (ret_val)
26784be59a01SSepherosa Ziehau 			return ret_val;
26799c80d176SSepherosa Ziehau 
26809c80d176SSepherosa Ziehau 		phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS)
26819c80d176SSepherosa Ziehau 				? e1000_1000t_rx_status_ok
26829c80d176SSepherosa Ziehau 				: e1000_1000t_rx_status_not_ok;
26839c80d176SSepherosa Ziehau 
26849c80d176SSepherosa Ziehau 		phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS)
26859c80d176SSepherosa Ziehau 				 ? e1000_1000t_rx_status_ok
26869c80d176SSepherosa Ziehau 				 : e1000_1000t_rx_status_not_ok;
26879c80d176SSepherosa Ziehau 	} else {
26889c80d176SSepherosa Ziehau 		/* Set values to "undefined" */
26899c80d176SSepherosa Ziehau 		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
26909c80d176SSepherosa Ziehau 		phy->local_rx = e1000_1000t_rx_status_undefined;
26919c80d176SSepherosa Ziehau 		phy->remote_rx = e1000_1000t_rx_status_undefined;
26929c80d176SSepherosa Ziehau 	}
26939c80d176SSepherosa Ziehau 
26949c80d176SSepherosa Ziehau 	return ret_val;
26959c80d176SSepherosa Ziehau }
26969c80d176SSepherosa Ziehau 
26979c80d176SSepherosa Ziehau /**
26989c80d176SSepherosa Ziehau  *  e1000_get_phy_info_igp - Retrieve igp PHY information
26999c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
27009c80d176SSepherosa Ziehau  *
27019c80d176SSepherosa Ziehau  *  Read PHY status to determine if link is up.  If link is up, then
27029c80d176SSepherosa Ziehau  *  set/determine 10base-T extended distance and polarity correction.  Read
27039c80d176SSepherosa Ziehau  *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
27049c80d176SSepherosa Ziehau  *  determine on the cable length, local and remote receiver.
27059c80d176SSepherosa Ziehau  **/
e1000_get_phy_info_igp(struct e1000_hw * hw)27069c80d176SSepherosa Ziehau s32 e1000_get_phy_info_igp(struct e1000_hw *hw)
27079c80d176SSepherosa Ziehau {
27089c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
27099c80d176SSepherosa Ziehau 	s32 ret_val;
27109c80d176SSepherosa Ziehau 	u16 data;
27119c80d176SSepherosa Ziehau 	bool link;
27129c80d176SSepherosa Ziehau 
27139c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_get_phy_info_igp");
27149c80d176SSepherosa Ziehau 
27159c80d176SSepherosa Ziehau 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
27169c80d176SSepherosa Ziehau 	if (ret_val)
27174be59a01SSepherosa Ziehau 		return ret_val;
27189c80d176SSepherosa Ziehau 
27199c80d176SSepherosa Ziehau 	if (!link) {
27209c80d176SSepherosa Ziehau 		DEBUGOUT("Phy info is only valid if link is up\n");
27214be59a01SSepherosa Ziehau 		return -E1000_ERR_CONFIG;
27229c80d176SSepherosa Ziehau 	}
27239c80d176SSepherosa Ziehau 
27249c80d176SSepherosa Ziehau 	phy->polarity_correction = TRUE;
27259c80d176SSepherosa Ziehau 
27269c80d176SSepherosa Ziehau 	ret_val = e1000_check_polarity_igp(hw);
27279c80d176SSepherosa Ziehau 	if (ret_val)
27284be59a01SSepherosa Ziehau 		return ret_val;
27299c80d176SSepherosa Ziehau 
27309c80d176SSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data);
27319c80d176SSepherosa Ziehau 	if (ret_val)
27324be59a01SSepherosa Ziehau 		return ret_val;
27339c80d176SSepherosa Ziehau 
27344be59a01SSepherosa Ziehau 	phy->is_mdix = !!(data & IGP01E1000_PSSR_MDIX);
27359c80d176SSepherosa Ziehau 
27369c80d176SSepherosa Ziehau 	if ((data & IGP01E1000_PSSR_SPEED_MASK) ==
27379c80d176SSepherosa Ziehau 	    IGP01E1000_PSSR_SPEED_1000MBPS) {
27386a5a645eSSepherosa Ziehau 		ret_val = phy->ops.get_cable_length(hw);
27399c80d176SSepherosa Ziehau 		if (ret_val)
27404be59a01SSepherosa Ziehau 			return ret_val;
27419c80d176SSepherosa Ziehau 
27429c80d176SSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
27439c80d176SSepherosa Ziehau 		if (ret_val)
27444be59a01SSepherosa Ziehau 			return ret_val;
27459c80d176SSepherosa Ziehau 
27469c80d176SSepherosa Ziehau 		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
27479c80d176SSepherosa Ziehau 				? e1000_1000t_rx_status_ok
27489c80d176SSepherosa Ziehau 				: e1000_1000t_rx_status_not_ok;
27499c80d176SSepherosa Ziehau 
27509c80d176SSepherosa Ziehau 		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
27519c80d176SSepherosa Ziehau 				 ? e1000_1000t_rx_status_ok
27529c80d176SSepherosa Ziehau 				 : e1000_1000t_rx_status_not_ok;
27539c80d176SSepherosa Ziehau 	} else {
27549c80d176SSepherosa Ziehau 		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
27559c80d176SSepherosa Ziehau 		phy->local_rx = e1000_1000t_rx_status_undefined;
27569c80d176SSepherosa Ziehau 		phy->remote_rx = e1000_1000t_rx_status_undefined;
27579c80d176SSepherosa Ziehau 	}
27589c80d176SSepherosa Ziehau 
27599c80d176SSepherosa Ziehau 	return ret_val;
27609c80d176SSepherosa Ziehau }
27619c80d176SSepherosa Ziehau 
27629c80d176SSepherosa Ziehau /**
27636a5a645eSSepherosa Ziehau  *  e1000_get_phy_info_ife - Retrieves various IFE PHY states
27646a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
27656a5a645eSSepherosa Ziehau  *
27666a5a645eSSepherosa Ziehau  *  Populates "phy" structure with various feature states.
27676a5a645eSSepherosa Ziehau  **/
e1000_get_phy_info_ife(struct e1000_hw * hw)27686a5a645eSSepherosa Ziehau s32 e1000_get_phy_info_ife(struct e1000_hw *hw)
27696a5a645eSSepherosa Ziehau {
27706a5a645eSSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
27716a5a645eSSepherosa Ziehau 	s32 ret_val;
27726a5a645eSSepherosa Ziehau 	u16 data;
27736a5a645eSSepherosa Ziehau 	bool link;
27746a5a645eSSepherosa Ziehau 
27756a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_get_phy_info_ife");
27766a5a645eSSepherosa Ziehau 
27776a5a645eSSepherosa Ziehau 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
27786a5a645eSSepherosa Ziehau 	if (ret_val)
27794be59a01SSepherosa Ziehau 		return ret_val;
27806a5a645eSSepherosa Ziehau 
27816a5a645eSSepherosa Ziehau 	if (!link) {
27826a5a645eSSepherosa Ziehau 		DEBUGOUT("Phy info is only valid if link is up\n");
27834be59a01SSepherosa Ziehau 		return -E1000_ERR_CONFIG;
27846a5a645eSSepherosa Ziehau 	}
27856a5a645eSSepherosa Ziehau 
27866a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IFE_PHY_SPECIAL_CONTROL, &data);
27876a5a645eSSepherosa Ziehau 	if (ret_val)
27884be59a01SSepherosa Ziehau 		return ret_val;
27894be59a01SSepherosa Ziehau 	phy->polarity_correction = !(data & IFE_PSC_AUTO_POLARITY_DISABLE);
27906a5a645eSSepherosa Ziehau 
27916a5a645eSSepherosa Ziehau 	if (phy->polarity_correction) {
27926a5a645eSSepherosa Ziehau 		ret_val = e1000_check_polarity_ife(hw);
27936a5a645eSSepherosa Ziehau 		if (ret_val)
27944be59a01SSepherosa Ziehau 			return ret_val;
27956a5a645eSSepherosa Ziehau 	} else {
27966a5a645eSSepherosa Ziehau 		/* Polarity is forced */
2797379ebbe7SSepherosa Ziehau 		phy->cable_polarity = ((data & IFE_PSC_FORCE_POLARITY)
27986a5a645eSSepherosa Ziehau 				       ? e1000_rev_polarity_reversed
2799379ebbe7SSepherosa Ziehau 				       : e1000_rev_polarity_normal);
28006a5a645eSSepherosa Ziehau 	}
28016a5a645eSSepherosa Ziehau 
28026a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data);
28036a5a645eSSepherosa Ziehau 	if (ret_val)
28044be59a01SSepherosa Ziehau 		return ret_val;
28056a5a645eSSepherosa Ziehau 
28064be59a01SSepherosa Ziehau 	phy->is_mdix = !!(data & IFE_PMC_MDIX_STATUS);
28076a5a645eSSepherosa Ziehau 
28086a5a645eSSepherosa Ziehau 	/* The following parameters are undefined for 10/100 operation. */
28096a5a645eSSepherosa Ziehau 	phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
28106a5a645eSSepherosa Ziehau 	phy->local_rx = e1000_1000t_rx_status_undefined;
28116a5a645eSSepherosa Ziehau 	phy->remote_rx = e1000_1000t_rx_status_undefined;
28126a5a645eSSepherosa Ziehau 
28134be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
28146a5a645eSSepherosa Ziehau }
28156a5a645eSSepherosa Ziehau 
28166a5a645eSSepherosa Ziehau /**
28179c80d176SSepherosa Ziehau  *  e1000_phy_sw_reset_generic - PHY software reset
28189c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
28199c80d176SSepherosa Ziehau  *
28209c80d176SSepherosa Ziehau  *  Does a software reset of the PHY by reading the PHY control register and
28219c80d176SSepherosa Ziehau  *  setting/write the control register reset bit to the PHY.
28229c80d176SSepherosa Ziehau  **/
e1000_phy_sw_reset_generic(struct e1000_hw * hw)28239c80d176SSepherosa Ziehau s32 e1000_phy_sw_reset_generic(struct e1000_hw *hw)
28249c80d176SSepherosa Ziehau {
28254be59a01SSepherosa Ziehau 	s32 ret_val;
28269c80d176SSepherosa Ziehau 	u16 phy_ctrl;
28279c80d176SSepherosa Ziehau 
28289c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_sw_reset_generic");
28299c80d176SSepherosa Ziehau 
28304be59a01SSepherosa Ziehau 	if (!hw->phy.ops.read_reg)
28314be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
28329c80d176SSepherosa Ziehau 
28339c80d176SSepherosa Ziehau 	ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
28349c80d176SSepherosa Ziehau 	if (ret_val)
28354be59a01SSepherosa Ziehau 		return ret_val;
28369c80d176SSepherosa Ziehau 
28379c80d176SSepherosa Ziehau 	phy_ctrl |= MII_CR_RESET;
28389c80d176SSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
28399c80d176SSepherosa Ziehau 	if (ret_val)
28404be59a01SSepherosa Ziehau 		return ret_val;
28419c80d176SSepherosa Ziehau 
28429c80d176SSepherosa Ziehau 	usec_delay(1);
28439c80d176SSepherosa Ziehau 
28449c80d176SSepherosa Ziehau 	return ret_val;
28459c80d176SSepherosa Ziehau }
28469c80d176SSepherosa Ziehau 
28479c80d176SSepherosa Ziehau /**
28489c80d176SSepherosa Ziehau  *  e1000_phy_hw_reset_generic - PHY hardware reset
28499c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
28509c80d176SSepherosa Ziehau  *
28519c80d176SSepherosa Ziehau  *  Verify the reset block is not blocking us from resetting.  Acquire
28529c80d176SSepherosa Ziehau  *  semaphore (if necessary) and read/set/write the device control reset
28539c80d176SSepherosa Ziehau  *  bit in the PHY.  Wait the appropriate delay time for the device to
28549c80d176SSepherosa Ziehau  *  reset and release the semaphore (if necessary).
28559c80d176SSepherosa Ziehau  **/
e1000_phy_hw_reset_generic(struct e1000_hw * hw)28569c80d176SSepherosa Ziehau s32 e1000_phy_hw_reset_generic(struct e1000_hw *hw)
28579c80d176SSepherosa Ziehau {
28589c80d176SSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
28594be59a01SSepherosa Ziehau 	s32 ret_val;
28609c80d176SSepherosa Ziehau 	u32 ctrl;
28619c80d176SSepherosa Ziehau 
28629c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_phy_hw_reset_generic");
28639c80d176SSepherosa Ziehau 
28644be59a01SSepherosa Ziehau 	if (phy->ops.check_reset_block) {
28659c80d176SSepherosa Ziehau 		ret_val = phy->ops.check_reset_block(hw);
28664be59a01SSepherosa Ziehau 		if (ret_val)
28674be59a01SSepherosa Ziehau 			return E1000_SUCCESS;
28689c80d176SSepherosa Ziehau 	}
28699c80d176SSepherosa Ziehau 
28709c80d176SSepherosa Ziehau 	ret_val = phy->ops.acquire(hw);
28719c80d176SSepherosa Ziehau 	if (ret_val)
28724be59a01SSepherosa Ziehau 		return ret_val;
28739c80d176SSepherosa Ziehau 
28749c80d176SSepherosa Ziehau 	ctrl = E1000_READ_REG(hw, E1000_CTRL);
28759c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST);
28769c80d176SSepherosa Ziehau 	E1000_WRITE_FLUSH(hw);
28779c80d176SSepherosa Ziehau 
28789c80d176SSepherosa Ziehau 	usec_delay(phy->reset_delay_us);
28799c80d176SSepherosa Ziehau 
28809c80d176SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_CTRL, ctrl);
28819c80d176SSepherosa Ziehau 	E1000_WRITE_FLUSH(hw);
28829c80d176SSepherosa Ziehau 
28839c80d176SSepherosa Ziehau 	usec_delay(150);
28849c80d176SSepherosa Ziehau 
28859c80d176SSepherosa Ziehau 	phy->ops.release(hw);
28869c80d176SSepherosa Ziehau 
28874be59a01SSepherosa Ziehau 	return phy->ops.get_cfg_done(hw);
28889c80d176SSepherosa Ziehau }
28899c80d176SSepherosa Ziehau 
28909c80d176SSepherosa Ziehau /**
28919c80d176SSepherosa Ziehau  *  e1000_get_cfg_done_generic - Generic configuration done
28929c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
28939c80d176SSepherosa Ziehau  *
28949c80d176SSepherosa Ziehau  *  Generic function to wait 10 milli-seconds for configuration to complete
28959c80d176SSepherosa Ziehau  *  and return success.
28969c80d176SSepherosa Ziehau  **/
e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG * hw)2897379ebbe7SSepherosa Ziehau s32 e1000_get_cfg_done_generic(struct e1000_hw E1000_UNUSEDARG *hw)
28989c80d176SSepherosa Ziehau {
28999c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_get_cfg_done_generic");
29009c80d176SSepherosa Ziehau 
29019c80d176SSepherosa Ziehau 	msec_delay_irq(10);
29029c80d176SSepherosa Ziehau 
29039c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
29049c80d176SSepherosa Ziehau }
29059c80d176SSepherosa Ziehau 
29069c80d176SSepherosa Ziehau /**
29079c80d176SSepherosa Ziehau  *  e1000_phy_init_script_igp3 - Inits the IGP3 PHY
29089c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
29099c80d176SSepherosa Ziehau  *
29109c80d176SSepherosa Ziehau  *  Initializes a Intel Gigabit PHY3 when an EEPROM is not present.
29119c80d176SSepherosa Ziehau  **/
e1000_phy_init_script_igp3(struct e1000_hw * hw)29129c80d176SSepherosa Ziehau s32 e1000_phy_init_script_igp3(struct e1000_hw *hw)
29139c80d176SSepherosa Ziehau {
29149c80d176SSepherosa Ziehau 	DEBUGOUT("Running IGP 3 PHY init script\n");
29159c80d176SSepherosa Ziehau 
29169c80d176SSepherosa Ziehau 	/* PHY init IGP 3 */
29179c80d176SSepherosa Ziehau 	/* Enable rise/fall, 10-mode work in class-A */
29189c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018);
29199c80d176SSepherosa Ziehau 	/* Remove all caps from Replica path filter */
29209c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x2F52, 0x0000);
29219c80d176SSepherosa Ziehau 	/* Bias trimming for ADC, AFE and Driver (Default) */
29229c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24);
29239c80d176SSepherosa Ziehau 	/* Increase Hybrid poly bias */
29249c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0);
29259c80d176SSepherosa Ziehau 	/* Add 4% to Tx amplitude in Gig mode */
29269c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x2010, 0x10B0);
29279c80d176SSepherosa Ziehau 	/* Disable trimming (TTT) */
29289c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x2011, 0x0000);
29299c80d176SSepherosa Ziehau 	/* Poly DC correction to 94.6% + 2% for all channels */
29309c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x20DD, 0x249A);
29319c80d176SSepherosa Ziehau 	/* ABS DC correction to 95.9% */
29329c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3);
29339c80d176SSepherosa Ziehau 	/* BG temp curve trim */
29349c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE);
29359c80d176SSepherosa Ziehau 	/* Increasing ADC OPAMP stage 1 currents to max */
29369c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4);
29379c80d176SSepherosa Ziehau 	/* Force 1000 ( required for enabling PHY regs configuration) */
29389c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x0000, 0x0140);
29399c80d176SSepherosa Ziehau 	/* Set upd_freq to 6 */
29409c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F30, 0x1606);
29419c80d176SSepherosa Ziehau 	/* Disable NPDFE */
29429c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F31, 0xB814);
29439c80d176SSepherosa Ziehau 	/* Disable adaptive fixed FFE (Default) */
29449c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F35, 0x002A);
29459c80d176SSepherosa Ziehau 	/* Enable FFE hysteresis */
29469c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067);
29479c80d176SSepherosa Ziehau 	/* Fixed FFE for short cable lengths */
29489c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F54, 0x0065);
29499c80d176SSepherosa Ziehau 	/* Fixed FFE for medium cable lengths */
29509c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F55, 0x002A);
29519c80d176SSepherosa Ziehau 	/* Fixed FFE for long cable lengths */
29529c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F56, 0x002A);
29539c80d176SSepherosa Ziehau 	/* Enable Adaptive Clip Threshold */
29549c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0);
29559c80d176SSepherosa Ziehau 	/* AHT reset limit to 1 */
29569c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF);
29579c80d176SSepherosa Ziehau 	/* Set AHT master delay to 127 msec */
29589c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC);
29599c80d176SSepherosa Ziehau 	/* Set scan bits for AHT */
29609c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF);
29619c80d176SSepherosa Ziehau 	/* Set AHT Preset bits */
29629c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1F79, 0x0210);
29639c80d176SSepherosa Ziehau 	/* Change integ_factor of channel A to 3 */
29649c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1895, 0x0003);
29659c80d176SSepherosa Ziehau 	/* Change prop_factor of channels BCD to 8 */
29669c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1796, 0x0008);
29679c80d176SSepherosa Ziehau 	/* Change cg_icount + enable integbp for channels BCD */
29689c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1798, 0xD008);
2969379ebbe7SSepherosa Ziehau 	/* Change cg_icount + enable integbp + change prop_factor_master
29709c80d176SSepherosa Ziehau 	 * to 8 for channel A
29719c80d176SSepherosa Ziehau 	 */
29729c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x1898, 0xD918);
29739c80d176SSepherosa Ziehau 	/* Disable AHT in Slave mode on channel A */
29749c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x187A, 0x0800);
2975379ebbe7SSepherosa Ziehau 	/* Enable LPLU and disable AN to 1000 in non-D0a states,
29769c80d176SSepherosa Ziehau 	 * Enable SPD+B2B
29779c80d176SSepherosa Ziehau 	 */
29789c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x0019, 0x008D);
29799c80d176SSepherosa Ziehau 	/* Enable restart AN on an1000_dis change */
29809c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x001B, 0x2080);
29819c80d176SSepherosa Ziehau 	/* Enable wh_fifo read clock in 10/100 modes */
29829c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x0014, 0x0045);
29839c80d176SSepherosa Ziehau 	/* Restart AN, Speed selection is 1000 */
29849c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, 0x0000, 0x1340);
29859c80d176SSepherosa Ziehau 
29869c80d176SSepherosa Ziehau 	return E1000_SUCCESS;
29879c80d176SSepherosa Ziehau }
29889c80d176SSepherosa Ziehau 
29899c80d176SSepherosa Ziehau /**
29909c80d176SSepherosa Ziehau  *  e1000_get_phy_type_from_id - Get PHY type from id
29919c80d176SSepherosa Ziehau  *  @phy_id: phy_id read from the phy
29929c80d176SSepherosa Ziehau  *
29939c80d176SSepherosa Ziehau  *  Returns the phy type from the id.
29949c80d176SSepherosa Ziehau  **/
e1000_get_phy_type_from_id(u32 phy_id)29959c80d176SSepherosa Ziehau enum e1000_phy_type e1000_get_phy_type_from_id(u32 phy_id)
29969c80d176SSepherosa Ziehau {
29979c80d176SSepherosa Ziehau 	enum e1000_phy_type phy_type = e1000_phy_unknown;
29989c80d176SSepherosa Ziehau 
29999c80d176SSepherosa Ziehau 	switch (phy_id) {
30009c80d176SSepherosa Ziehau 	case M88E1000_I_PHY_ID:
30019c80d176SSepherosa Ziehau 	case M88E1000_E_PHY_ID:
30029c80d176SSepherosa Ziehau 	case M88E1111_I_PHY_ID:
30039c80d176SSepherosa Ziehau 	case M88E1011_I_PHY_ID:
3004ba0123e0SSepherosa Ziehau 	case M88E1543_E_PHY_ID:
3005ba0123e0SSepherosa Ziehau 	case M88E1512_E_PHY_ID:
300662583d18SSepherosa Ziehau 	case I347AT4_E_PHY_ID:
300762583d18SSepherosa Ziehau 	case M88E1112_E_PHY_ID:
300862583d18SSepherosa Ziehau 	case M88E1340M_E_PHY_ID:
30099c80d176SSepherosa Ziehau 		phy_type = e1000_phy_m88;
30109c80d176SSepherosa Ziehau 		break;
30119c80d176SSepherosa Ziehau 	case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */
30129c80d176SSepherosa Ziehau 		phy_type = e1000_phy_igp_2;
30139c80d176SSepherosa Ziehau 		break;
30149c80d176SSepherosa Ziehau 	case GG82563_E_PHY_ID:
30159c80d176SSepherosa Ziehau 		phy_type = e1000_phy_gg82563;
30169c80d176SSepherosa Ziehau 		break;
30179c80d176SSepherosa Ziehau 	case IGP03E1000_E_PHY_ID:
30189c80d176SSepherosa Ziehau 		phy_type = e1000_phy_igp_3;
30199c80d176SSepherosa Ziehau 		break;
30209c80d176SSepherosa Ziehau 	case IFE_E_PHY_ID:
30219c80d176SSepherosa Ziehau 	case IFE_PLUS_E_PHY_ID:
30229c80d176SSepherosa Ziehau 	case IFE_C_E_PHY_ID:
30239c80d176SSepherosa Ziehau 		phy_type = e1000_phy_ife;
30249c80d176SSepherosa Ziehau 		break;
30259c80d176SSepherosa Ziehau 	case BME1000_E_PHY_ID:
30269c80d176SSepherosa Ziehau 	case BME1000_E_PHY_ID_R2:
30279c80d176SSepherosa Ziehau 		phy_type = e1000_phy_bm;
30289c80d176SSepherosa Ziehau 		break;
30296a5a645eSSepherosa Ziehau 	case I82578_E_PHY_ID:
30306a5a645eSSepherosa Ziehau 		phy_type = e1000_phy_82578;
30316a5a645eSSepherosa Ziehau 		break;
30326a5a645eSSepherosa Ziehau 	case I82577_E_PHY_ID:
30336a5a645eSSepherosa Ziehau 		phy_type = e1000_phy_82577;
30346a5a645eSSepherosa Ziehau 		break;
30356a5a645eSSepherosa Ziehau 	case I82579_E_PHY_ID:
30366a5a645eSSepherosa Ziehau 		phy_type = e1000_phy_82579;
30376a5a645eSSepherosa Ziehau 		break;
30386a5a645eSSepherosa Ziehau 	case I82580_I_PHY_ID:
30396a5a645eSSepherosa Ziehau 		phy_type = e1000_phy_82580;
30405f18a3ddSSascha Wildner 		break;
304165aebe9fSSepherosa Ziehau 	case I217_E_PHY_ID:
304265aebe9fSSepherosa Ziehau 		phy_type = e1000_phy_i217;
30436a5a645eSSepherosa Ziehau 		break;
30444be59a01SSepherosa Ziehau 	case I210_I_PHY_ID:
30454be59a01SSepherosa Ziehau 		phy_type = e1000_phy_i210;
30464be59a01SSepherosa Ziehau 		break;
30479c80d176SSepherosa Ziehau 	default:
30489c80d176SSepherosa Ziehau 		phy_type = e1000_phy_unknown;
30499c80d176SSepherosa Ziehau 		break;
30509c80d176SSepherosa Ziehau 	}
30519c80d176SSepherosa Ziehau 	return phy_type;
30529c80d176SSepherosa Ziehau }
30539c80d176SSepherosa Ziehau 
30549c80d176SSepherosa Ziehau /**
30559c80d176SSepherosa Ziehau  *  e1000_determine_phy_address - Determines PHY address.
30569c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
30579c80d176SSepherosa Ziehau  *
30589c80d176SSepherosa Ziehau  *  This uses a trial and error method to loop through possible PHY
30599c80d176SSepherosa Ziehau  *  addresses. It tests each by reading the PHY ID registers and
30609c80d176SSepherosa Ziehau  *  checking for a match.
30619c80d176SSepherosa Ziehau  **/
e1000_determine_phy_address(struct e1000_hw * hw)30629c80d176SSepherosa Ziehau s32 e1000_determine_phy_address(struct e1000_hw *hw)
30639c80d176SSepherosa Ziehau {
30649c80d176SSepherosa Ziehau 	u32 phy_addr = 0;
30659c80d176SSepherosa Ziehau 	u32 i;
30669c80d176SSepherosa Ziehau 	enum e1000_phy_type phy_type = e1000_phy_unknown;
30679c80d176SSepherosa Ziehau 
30686a5a645eSSepherosa Ziehau 	hw->phy.id = phy_type;
30696a5a645eSSepherosa Ziehau 
30709c80d176SSepherosa Ziehau 	for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) {
30719c80d176SSepherosa Ziehau 		hw->phy.addr = phy_addr;
30729c80d176SSepherosa Ziehau 		i = 0;
30739c80d176SSepherosa Ziehau 
30749c80d176SSepherosa Ziehau 		do {
30759c80d176SSepherosa Ziehau 			e1000_get_phy_id(hw);
30769c80d176SSepherosa Ziehau 			phy_type = e1000_get_phy_type_from_id(hw->phy.id);
30779c80d176SSepherosa Ziehau 
3078379ebbe7SSepherosa Ziehau 			/* If phy_type is valid, break - we found our
30799c80d176SSepherosa Ziehau 			 * PHY address
30809c80d176SSepherosa Ziehau 			 */
30814be59a01SSepherosa Ziehau 			if (phy_type != e1000_phy_unknown)
30824be59a01SSepherosa Ziehau 				return E1000_SUCCESS;
30834be59a01SSepherosa Ziehau 
30849c80d176SSepherosa Ziehau 			msec_delay(1);
30859c80d176SSepherosa Ziehau 			i++;
30869c80d176SSepherosa Ziehau 		} while (i < 10);
30879c80d176SSepherosa Ziehau 	}
30889c80d176SSepherosa Ziehau 
30894be59a01SSepherosa Ziehau 	return -E1000_ERR_PHY_TYPE;
30909c80d176SSepherosa Ziehau }
30919c80d176SSepherosa Ziehau 
30929c80d176SSepherosa Ziehau /**
30939c80d176SSepherosa Ziehau  *  e1000_get_phy_addr_for_bm_page - Retrieve PHY page address
30949c80d176SSepherosa Ziehau  *  @page: page to access
3095*01a55482SSepherosa Ziehau  *  @reg: register to access
30969c80d176SSepherosa Ziehau  *
30979c80d176SSepherosa Ziehau  *  Returns the phy address for the page requested.
30989c80d176SSepherosa Ziehau  **/
e1000_get_phy_addr_for_bm_page(u32 page,u32 reg)30999c80d176SSepherosa Ziehau static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg)
31009c80d176SSepherosa Ziehau {
31019c80d176SSepherosa Ziehau 	u32 phy_addr = 2;
31029c80d176SSepherosa Ziehau 
31039c80d176SSepherosa Ziehau 	if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31))
31049c80d176SSepherosa Ziehau 		phy_addr = 1;
31059c80d176SSepherosa Ziehau 
31069c80d176SSepherosa Ziehau 	return phy_addr;
31079c80d176SSepherosa Ziehau }
31089c80d176SSepherosa Ziehau 
31099c80d176SSepherosa Ziehau /**
31109c80d176SSepherosa Ziehau  *  e1000_write_phy_reg_bm - Write BM PHY register
31119c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
31129c80d176SSepherosa Ziehau  *  @offset: register offset to write to
31139c80d176SSepherosa Ziehau  *  @data: data to write at register offset
31149c80d176SSepherosa Ziehau  *
31159c80d176SSepherosa Ziehau  *  Acquires semaphore, if necessary, then writes the data to PHY register
31169c80d176SSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
31179c80d176SSepherosa Ziehau  **/
e1000_write_phy_reg_bm(struct e1000_hw * hw,u32 offset,u16 data)31189c80d176SSepherosa Ziehau s32 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data)
31199c80d176SSepherosa Ziehau {
31209c80d176SSepherosa Ziehau 	s32 ret_val;
31219c80d176SSepherosa Ziehau 	u32 page = offset >> IGP_PAGE_SHIFT;
31229c80d176SSepherosa Ziehau 
31239c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_bm");
31249c80d176SSepherosa Ziehau 
31256a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
31266a5a645eSSepherosa Ziehau 	if (ret_val)
31276a5a645eSSepherosa Ziehau 		return ret_val;
31286a5a645eSSepherosa Ziehau 
31299c80d176SSepherosa Ziehau 	/* Page 800 works differently than the rest so it has its own func */
31309c80d176SSepherosa Ziehau 	if (page == BM_WUC_PAGE) {
31319c80d176SSepherosa Ziehau 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
313265aebe9fSSepherosa Ziehau 							 FALSE, false);
31334be59a01SSepherosa Ziehau 		goto release;
31349c80d176SSepherosa Ziehau 	}
31359c80d176SSepherosa Ziehau 
31369c80d176SSepherosa Ziehau 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
31379c80d176SSepherosa Ziehau 
31389c80d176SSepherosa Ziehau 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
31396d5e2922SSepherosa Ziehau 		u32 page_shift, page_select;
31406d5e2922SSepherosa Ziehau 
3141379ebbe7SSepherosa Ziehau 		/* Page select is register 31 for phy address 1 and 22 for
31429c80d176SSepherosa Ziehau 		 * phy address 2 and 3. Page select is shifted only for
31439c80d176SSepherosa Ziehau 		 * phy address 1.
31449c80d176SSepherosa Ziehau 		 */
31459c80d176SSepherosa Ziehau 		if (hw->phy.addr == 1) {
31469c80d176SSepherosa Ziehau 			page_shift = IGP_PAGE_SHIFT;
31479c80d176SSepherosa Ziehau 			page_select = IGP01E1000_PHY_PAGE_SELECT;
31489c80d176SSepherosa Ziehau 		} else {
31499c80d176SSepherosa Ziehau 			page_shift = 0;
31509c80d176SSepherosa Ziehau 			page_select = BM_PHY_PAGE_SELECT;
31519c80d176SSepherosa Ziehau 		}
31529c80d176SSepherosa Ziehau 
31539c80d176SSepherosa Ziehau 		/* Page is shifted left, PHY expects (page x 32) */
31549c80d176SSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw, page_select,
31559c80d176SSepherosa Ziehau 						   (page << page_shift));
31566a5a645eSSepherosa Ziehau 		if (ret_val)
31574be59a01SSepherosa Ziehau 			goto release;
31589c80d176SSepherosa Ziehau 	}
31599c80d176SSepherosa Ziehau 
31609c80d176SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
31619c80d176SSepherosa Ziehau 					   data);
31629c80d176SSepherosa Ziehau 
31634be59a01SSepherosa Ziehau release:
31646a5a645eSSepherosa Ziehau 	hw->phy.ops.release(hw);
31659c80d176SSepherosa Ziehau 	return ret_val;
31669c80d176SSepherosa Ziehau }
31679c80d176SSepherosa Ziehau 
31689c80d176SSepherosa Ziehau /**
31699c80d176SSepherosa Ziehau  *  e1000_read_phy_reg_bm - Read BM PHY register
31709c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
31719c80d176SSepherosa Ziehau  *  @offset: register offset to be read
31729c80d176SSepherosa Ziehau  *  @data: pointer to the read data
31739c80d176SSepherosa Ziehau  *
31749c80d176SSepherosa Ziehau  *  Acquires semaphore, if necessary, then reads the PHY register at offset
31759c80d176SSepherosa Ziehau  *  and storing the retrieved information in data.  Release any acquired
31769c80d176SSepherosa Ziehau  *  semaphores before exiting.
31779c80d176SSepherosa Ziehau  **/
e1000_read_phy_reg_bm(struct e1000_hw * hw,u32 offset,u16 * data)31789c80d176SSepherosa Ziehau s32 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data)
31799c80d176SSepherosa Ziehau {
31809c80d176SSepherosa Ziehau 	s32 ret_val;
31819c80d176SSepherosa Ziehau 	u32 page = offset >> IGP_PAGE_SHIFT;
31829c80d176SSepherosa Ziehau 
31839c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_read_phy_reg_bm");
31849c80d176SSepherosa Ziehau 
31856a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
31866a5a645eSSepherosa Ziehau 	if (ret_val)
31876a5a645eSSepherosa Ziehau 		return ret_val;
31886a5a645eSSepherosa Ziehau 
31899c80d176SSepherosa Ziehau 	/* Page 800 works differently than the rest so it has its own func */
31909c80d176SSepherosa Ziehau 	if (page == BM_WUC_PAGE) {
31919c80d176SSepherosa Ziehau 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
31926d5e2922SSepherosa Ziehau 							 TRUE, FALSE);
31934be59a01SSepherosa Ziehau 		goto release;
31949c80d176SSepherosa Ziehau 	}
31959c80d176SSepherosa Ziehau 
31969c80d176SSepherosa Ziehau 	hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset);
31979c80d176SSepherosa Ziehau 
31989c80d176SSepherosa Ziehau 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
31996d5e2922SSepherosa Ziehau 		u32 page_shift, page_select;
32006d5e2922SSepherosa Ziehau 
3201379ebbe7SSepherosa Ziehau 		/* Page select is register 31 for phy address 1 and 22 for
32029c80d176SSepherosa Ziehau 		 * phy address 2 and 3. Page select is shifted only for
32039c80d176SSepherosa Ziehau 		 * phy address 1.
32049c80d176SSepherosa Ziehau 		 */
32059c80d176SSepherosa Ziehau 		if (hw->phy.addr == 1) {
32069c80d176SSepherosa Ziehau 			page_shift = IGP_PAGE_SHIFT;
32079c80d176SSepherosa Ziehau 			page_select = IGP01E1000_PHY_PAGE_SELECT;
32089c80d176SSepherosa Ziehau 		} else {
32099c80d176SSepherosa Ziehau 			page_shift = 0;
32109c80d176SSepherosa Ziehau 			page_select = BM_PHY_PAGE_SELECT;
32119c80d176SSepherosa Ziehau 		}
32129c80d176SSepherosa Ziehau 
32139c80d176SSepherosa Ziehau 		/* Page is shifted left, PHY expects (page x 32) */
32149c80d176SSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw, page_select,
32159c80d176SSepherosa Ziehau 						   (page << page_shift));
32166a5a645eSSepherosa Ziehau 		if (ret_val)
32174be59a01SSepherosa Ziehau 			goto release;
32189c80d176SSepherosa Ziehau 	}
32199c80d176SSepherosa Ziehau 
32209c80d176SSepherosa Ziehau 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
32219c80d176SSepherosa Ziehau 					  data);
32224be59a01SSepherosa Ziehau release:
32236a5a645eSSepherosa Ziehau 	hw->phy.ops.release(hw);
32249c80d176SSepherosa Ziehau 	return ret_val;
32259c80d176SSepherosa Ziehau }
32269c80d176SSepherosa Ziehau 
32279c80d176SSepherosa Ziehau /**
32289c80d176SSepherosa Ziehau  *  e1000_read_phy_reg_bm2 - Read BM PHY register
32299c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
32309c80d176SSepherosa Ziehau  *  @offset: register offset to be read
32319c80d176SSepherosa Ziehau  *  @data: pointer to the read data
32329c80d176SSepherosa Ziehau  *
32339c80d176SSepherosa Ziehau  *  Acquires semaphore, if necessary, then reads the PHY register at offset
32349c80d176SSepherosa Ziehau  *  and storing the retrieved information in data.  Release any acquired
32359c80d176SSepherosa Ziehau  *  semaphores before exiting.
32369c80d176SSepherosa Ziehau  **/
e1000_read_phy_reg_bm2(struct e1000_hw * hw,u32 offset,u16 * data)32379c80d176SSepherosa Ziehau s32 e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data)
32389c80d176SSepherosa Ziehau {
32399c80d176SSepherosa Ziehau 	s32 ret_val;
32409c80d176SSepherosa Ziehau 	u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
32419c80d176SSepherosa Ziehau 
32426d5e2922SSepherosa Ziehau 	DEBUGFUNC("e1000_read_phy_reg_bm2");
32439c80d176SSepherosa Ziehau 
32446a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
32456a5a645eSSepherosa Ziehau 	if (ret_val)
32466a5a645eSSepherosa Ziehau 		return ret_val;
32476a5a645eSSepherosa Ziehau 
32489c80d176SSepherosa Ziehau 	/* Page 800 works differently than the rest so it has its own func */
32499c80d176SSepherosa Ziehau 	if (page == BM_WUC_PAGE) {
32509c80d176SSepherosa Ziehau 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
32516d5e2922SSepherosa Ziehau 							 TRUE, FALSE);
32524be59a01SSepherosa Ziehau 		goto release;
32539c80d176SSepherosa Ziehau 	}
32549c80d176SSepherosa Ziehau 
32559c80d176SSepherosa Ziehau 	hw->phy.addr = 1;
32569c80d176SSepherosa Ziehau 
32579c80d176SSepherosa Ziehau 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
32589c80d176SSepherosa Ziehau 		/* Page is shifted left, PHY expects (page x 32) */
32599c80d176SSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
32609c80d176SSepherosa Ziehau 						   page);
32619c80d176SSepherosa Ziehau 
32626a5a645eSSepherosa Ziehau 		if (ret_val)
32634be59a01SSepherosa Ziehau 			goto release;
32649c80d176SSepherosa Ziehau 	}
32659c80d176SSepherosa Ziehau 
32669c80d176SSepherosa Ziehau 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
32679c80d176SSepherosa Ziehau 					  data);
32684be59a01SSepherosa Ziehau release:
32696a5a645eSSepherosa Ziehau 	hw->phy.ops.release(hw);
32709c80d176SSepherosa Ziehau 	return ret_val;
32719c80d176SSepherosa Ziehau }
32729c80d176SSepherosa Ziehau 
32739c80d176SSepherosa Ziehau /**
32749c80d176SSepherosa Ziehau  *  e1000_write_phy_reg_bm2 - Write BM PHY register
32759c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
32769c80d176SSepherosa Ziehau  *  @offset: register offset to write to
32779c80d176SSepherosa Ziehau  *  @data: data to write at register offset
32789c80d176SSepherosa Ziehau  *
32799c80d176SSepherosa Ziehau  *  Acquires semaphore, if necessary, then writes the data to PHY register
32809c80d176SSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
32819c80d176SSepherosa Ziehau  **/
e1000_write_phy_reg_bm2(struct e1000_hw * hw,u32 offset,u16 data)32829c80d176SSepherosa Ziehau s32 e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data)
32839c80d176SSepherosa Ziehau {
32849c80d176SSepherosa Ziehau 	s32 ret_val;
32859c80d176SSepherosa Ziehau 	u16 page = (u16)(offset >> IGP_PAGE_SHIFT);
32869c80d176SSepherosa Ziehau 
32879c80d176SSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_bm2");
32889c80d176SSepherosa Ziehau 
32896a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
32906a5a645eSSepherosa Ziehau 	if (ret_val)
32916a5a645eSSepherosa Ziehau 		return ret_val;
32926a5a645eSSepherosa Ziehau 
32939c80d176SSepherosa Ziehau 	/* Page 800 works differently than the rest so it has its own func */
32949c80d176SSepherosa Ziehau 	if (page == BM_WUC_PAGE) {
32959c80d176SSepherosa Ziehau 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
329665aebe9fSSepherosa Ziehau 							 FALSE, false);
32974be59a01SSepherosa Ziehau 		goto release;
32989c80d176SSepherosa Ziehau 	}
32999c80d176SSepherosa Ziehau 
33009c80d176SSepherosa Ziehau 	hw->phy.addr = 1;
33019c80d176SSepherosa Ziehau 
33029c80d176SSepherosa Ziehau 	if (offset > MAX_PHY_MULTI_PAGE_REG) {
33039c80d176SSepherosa Ziehau 		/* Page is shifted left, PHY expects (page x 32) */
33049c80d176SSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT,
33059c80d176SSepherosa Ziehau 						   page);
33069c80d176SSepherosa Ziehau 
33076a5a645eSSepherosa Ziehau 		if (ret_val)
33084be59a01SSepherosa Ziehau 			goto release;
33099c80d176SSepherosa Ziehau 	}
33109c80d176SSepherosa Ziehau 
33119c80d176SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset,
33129c80d176SSepherosa Ziehau 					   data);
33139c80d176SSepherosa Ziehau 
33144be59a01SSepherosa Ziehau release:
33156a5a645eSSepherosa Ziehau 	hw->phy.ops.release(hw);
33169c80d176SSepherosa Ziehau 	return ret_val;
33179c80d176SSepherosa Ziehau }
33189c80d176SSepherosa Ziehau 
33199c80d176SSepherosa Ziehau /**
33206d5e2922SSepherosa Ziehau  *  e1000_enable_phy_wakeup_reg_access_bm - enable access to BM wakeup registers
33216d5e2922SSepherosa Ziehau  *  @hw: pointer to the HW structure
33226d5e2922SSepherosa Ziehau  *  @phy_reg: pointer to store original contents of BM_WUC_ENABLE_REG
33236d5e2922SSepherosa Ziehau  *
33246d5e2922SSepherosa Ziehau  *  Assumes semaphore already acquired and phy_reg points to a valid memory
33256d5e2922SSepherosa Ziehau  *  address to store contents of the BM_WUC_ENABLE_REG register.
33266d5e2922SSepherosa Ziehau  **/
e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw * hw,u16 * phy_reg)33276d5e2922SSepherosa Ziehau s32 e1000_enable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
33286d5e2922SSepherosa Ziehau {
33296d5e2922SSepherosa Ziehau 	s32 ret_val;
33306d5e2922SSepherosa Ziehau 	u16 temp;
33316d5e2922SSepherosa Ziehau 
33326d5e2922SSepherosa Ziehau 	DEBUGFUNC("e1000_enable_phy_wakeup_reg_access_bm");
33336d5e2922SSepherosa Ziehau 
33344be59a01SSepherosa Ziehau 	if (!phy_reg)
33354be59a01SSepherosa Ziehau 		return -E1000_ERR_PARAM;
33366d5e2922SSepherosa Ziehau 
33376d5e2922SSepherosa Ziehau 	/* All page select, port ctrl and wakeup registers use phy address 1 */
33386d5e2922SSepherosa Ziehau 	hw->phy.addr = 1;
33396d5e2922SSepherosa Ziehau 
33406d5e2922SSepherosa Ziehau 	/* Select Port Control Registers page */
33416d5e2922SSepherosa Ziehau 	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
33426d5e2922SSepherosa Ziehau 	if (ret_val) {
33436d5e2922SSepherosa Ziehau 		DEBUGOUT("Could not set Port Control page\n");
33444be59a01SSepherosa Ziehau 		return ret_val;
33456d5e2922SSepherosa Ziehau 	}
33466d5e2922SSepherosa Ziehau 
33476d5e2922SSepherosa Ziehau 	ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg);
33486d5e2922SSepherosa Ziehau 	if (ret_val) {
33496d5e2922SSepherosa Ziehau 		DEBUGOUT2("Could not read PHY register %d.%d\n",
33506d5e2922SSepherosa Ziehau 			  BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
33514be59a01SSepherosa Ziehau 		return ret_val;
33526d5e2922SSepherosa Ziehau 	}
33536d5e2922SSepherosa Ziehau 
3354379ebbe7SSepherosa Ziehau 	/* Enable both PHY wakeup mode and Wakeup register page writes.
33556d5e2922SSepherosa Ziehau 	 * Prevent a power state change by disabling ME and Host PHY wakeup.
33566d5e2922SSepherosa Ziehau 	 */
33576d5e2922SSepherosa Ziehau 	temp = *phy_reg;
33586d5e2922SSepherosa Ziehau 	temp |= BM_WUC_ENABLE_BIT;
33596d5e2922SSepherosa Ziehau 	temp &= ~(BM_WUC_ME_WU_BIT | BM_WUC_HOST_WU_BIT);
33606d5e2922SSepherosa Ziehau 
33616d5e2922SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, temp);
33626d5e2922SSepherosa Ziehau 	if (ret_val) {
33636d5e2922SSepherosa Ziehau 		DEBUGOUT2("Could not write PHY register %d.%d\n",
33646d5e2922SSepherosa Ziehau 			  BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
33654be59a01SSepherosa Ziehau 		return ret_val;
33666d5e2922SSepherosa Ziehau 	}
33676d5e2922SSepherosa Ziehau 
3368379ebbe7SSepherosa Ziehau 	/* Select Host Wakeup Registers page - caller now able to write
33694be59a01SSepherosa Ziehau 	 * registers on the Wakeup registers page
33704be59a01SSepherosa Ziehau 	 */
33714be59a01SSepherosa Ziehau 	return e1000_set_page_igp(hw, (BM_WUC_PAGE << IGP_PAGE_SHIFT));
33726d5e2922SSepherosa Ziehau }
33736d5e2922SSepherosa Ziehau 
33746d5e2922SSepherosa Ziehau /**
33756d5e2922SSepherosa Ziehau  *  e1000_disable_phy_wakeup_reg_access_bm - disable access to BM wakeup regs
33766d5e2922SSepherosa Ziehau  *  @hw: pointer to the HW structure
33776d5e2922SSepherosa Ziehau  *  @phy_reg: pointer to original contents of BM_WUC_ENABLE_REG
33786d5e2922SSepherosa Ziehau  *
33796d5e2922SSepherosa Ziehau  *  Restore BM_WUC_ENABLE_REG to its original value.
33806d5e2922SSepherosa Ziehau  *
33816d5e2922SSepherosa Ziehau  *  Assumes semaphore already acquired and *phy_reg is the contents of the
33826d5e2922SSepherosa Ziehau  *  BM_WUC_ENABLE_REG before register(s) on BM_WUC_PAGE were accessed by
33836d5e2922SSepherosa Ziehau  *  caller.
33846d5e2922SSepherosa Ziehau  **/
e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw * hw,u16 * phy_reg)33856d5e2922SSepherosa Ziehau s32 e1000_disable_phy_wakeup_reg_access_bm(struct e1000_hw *hw, u16 *phy_reg)
33866d5e2922SSepherosa Ziehau {
3387379ebbe7SSepherosa Ziehau 	s32 ret_val;
33886d5e2922SSepherosa Ziehau 
33896d5e2922SSepherosa Ziehau 	DEBUGFUNC("e1000_disable_phy_wakeup_reg_access_bm");
33906d5e2922SSepherosa Ziehau 
33916d5e2922SSepherosa Ziehau 	if (!phy_reg)
33926d5e2922SSepherosa Ziehau 		return -E1000_ERR_PARAM;
33936d5e2922SSepherosa Ziehau 
33946d5e2922SSepherosa Ziehau 	/* Select Port Control Registers page */
33956d5e2922SSepherosa Ziehau 	ret_val = e1000_set_page_igp(hw, (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT));
33966d5e2922SSepherosa Ziehau 	if (ret_val) {
33976d5e2922SSepherosa Ziehau 		DEBUGOUT("Could not set Port Control page\n");
33984be59a01SSepherosa Ziehau 		return ret_val;
33996d5e2922SSepherosa Ziehau 	}
34006d5e2922SSepherosa Ziehau 
34016d5e2922SSepherosa Ziehau 	/* Restore 769.17 to its original value */
34026d5e2922SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, *phy_reg);
34036d5e2922SSepherosa Ziehau 	if (ret_val)
34046d5e2922SSepherosa Ziehau 		DEBUGOUT2("Could not restore PHY register %d.%d\n",
34056d5e2922SSepherosa Ziehau 			  BM_PORT_CTRL_PAGE, BM_WUC_ENABLE_REG);
34064be59a01SSepherosa Ziehau 
34076d5e2922SSepherosa Ziehau 	return ret_val;
34086d5e2922SSepherosa Ziehau }
34096d5e2922SSepherosa Ziehau 
34106d5e2922SSepherosa Ziehau /**
34116d5e2922SSepherosa Ziehau  *  e1000_access_phy_wakeup_reg_bm - Read/write BM PHY wakeup register
34129c80d176SSepherosa Ziehau  *  @hw: pointer to the HW structure
34139c80d176SSepherosa Ziehau  *  @offset: register offset to be read or written
34149c80d176SSepherosa Ziehau  *  @data: pointer to the data to read or write
34159c80d176SSepherosa Ziehau  *  @read: determines if operation is read or write
34166d5e2922SSepherosa Ziehau  *  @page_set: BM_WUC_PAGE already set and access enabled
34179c80d176SSepherosa Ziehau  *
34186d5e2922SSepherosa Ziehau  *  Read the PHY register at offset and store the retrieved information in
34196d5e2922SSepherosa Ziehau  *  data, or write data to PHY register at offset.  Note the procedure to
34206d5e2922SSepherosa Ziehau  *  access the PHY wakeup registers is different than reading the other PHY
34216d5e2922SSepherosa Ziehau  *  registers. It works as such:
34226d5e2922SSepherosa Ziehau  *  1) Set 769.17.2 (page 769, register 17, bit 2) = 1
34239c80d176SSepherosa Ziehau  *  2) Set page to 800 for host (801 if we were manageability)
34249c80d176SSepherosa Ziehau  *  3) Write the address using the address opcode (0x11)
34259c80d176SSepherosa Ziehau  *  4) Read or write the data using the data opcode (0x12)
34266d5e2922SSepherosa Ziehau  *  5) Restore 769.17.2 to its original value
34276a5a645eSSepherosa Ziehau  *
34286d5e2922SSepherosa Ziehau  *  Steps 1 and 2 are done by e1000_enable_phy_wakeup_reg_access_bm() and
34296d5e2922SSepherosa Ziehau  *  step 5 is done by e1000_disable_phy_wakeup_reg_access_bm().
34306d5e2922SSepherosa Ziehau  *
34316d5e2922SSepherosa Ziehau  *  Assumes semaphore is already acquired.  When page_set==TRUE, assumes
34326d5e2922SSepherosa Ziehau  *  the PHY page is set to BM_WUC_PAGE (i.e. a function in the call stack
34336d5e2922SSepherosa Ziehau  *  is responsible for calls to e1000_[enable|disable]_phy_wakeup_reg_bm()).
34349c80d176SSepherosa Ziehau  **/
e1000_access_phy_wakeup_reg_bm(struct e1000_hw * hw,u32 offset,u16 * data,bool read,bool page_set)34359c80d176SSepherosa Ziehau static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset,
34366d5e2922SSepherosa Ziehau 					  u16 *data, bool read, bool page_set)
34379c80d176SSepherosa Ziehau {
34389c80d176SSepherosa Ziehau 	s32 ret_val;
343974dc3754SSepherosa Ziehau 	u16 reg = BM_PHY_REG_NUM(offset);
344074dc3754SSepherosa Ziehau 	u16 page = BM_PHY_REG_PAGE(offset);
34419c80d176SSepherosa Ziehau 	u16 phy_reg = 0;
34429c80d176SSepherosa Ziehau 
34436a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_access_phy_wakeup_reg_bm");
34449c80d176SSepherosa Ziehau 
34456d5e2922SSepherosa Ziehau 	/* Gig must be disabled for MDIO accesses to Host Wakeup reg page */
34466a5a645eSSepherosa Ziehau 	if ((hw->mac.type == e1000_pchlan) &&
34476a5a645eSSepherosa Ziehau 	   (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & E1000_PHY_CTRL_GBE_DISABLE)))
34486d5e2922SSepherosa Ziehau 		DEBUGOUT1("Attempting to access page %d while gig enabled.\n",
34496d5e2922SSepherosa Ziehau 			  page);
34509c80d176SSepherosa Ziehau 
34516d5e2922SSepherosa Ziehau 	if (!page_set) {
34526d5e2922SSepherosa Ziehau 		/* Enable access to PHY wakeup registers */
34536d5e2922SSepherosa Ziehau 		ret_val = e1000_enable_phy_wakeup_reg_access_bm(hw, &phy_reg);
34549c80d176SSepherosa Ziehau 		if (ret_val) {
34556d5e2922SSepherosa Ziehau 			DEBUGOUT("Could not enable PHY wakeup reg access\n");
34564be59a01SSepherosa Ziehau 			return ret_val;
34579c80d176SSepherosa Ziehau 		}
34589c80d176SSepherosa Ziehau 	}
34599c80d176SSepherosa Ziehau 
34606d5e2922SSepherosa Ziehau 	DEBUGOUT2("Accessing PHY page %d reg 0x%x\n", page, reg);
34619c80d176SSepherosa Ziehau 
34626d5e2922SSepherosa Ziehau 	/* Write the Wakeup register page offset value using opcode 0x11 */
34639c80d176SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg);
34649c80d176SSepherosa Ziehau 	if (ret_val) {
34656d5e2922SSepherosa Ziehau 		DEBUGOUT1("Could not write address opcode to page %d\n", page);
34664be59a01SSepherosa Ziehau 		return ret_val;
34679c80d176SSepherosa Ziehau 	}
34689c80d176SSepherosa Ziehau 
34699c80d176SSepherosa Ziehau 	if (read) {
34706d5e2922SSepherosa Ziehau 		/* Read the Wakeup register page value using opcode 0x12 */
34719c80d176SSepherosa Ziehau 		ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
34729c80d176SSepherosa Ziehau 						  data);
34739c80d176SSepherosa Ziehau 	} else {
34746d5e2922SSepherosa Ziehau 		/* Write the Wakeup register page value using opcode 0x12 */
34759c80d176SSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE,
34769c80d176SSepherosa Ziehau 						   *data);
34779c80d176SSepherosa Ziehau 	}
34789c80d176SSepherosa Ziehau 
34799c80d176SSepherosa Ziehau 	if (ret_val) {
34806d5e2922SSepherosa Ziehau 		DEBUGOUT2("Could not access PHY reg %d.%d\n", page, reg);
34814be59a01SSepherosa Ziehau 		return ret_val;
34829c80d176SSepherosa Ziehau 	}
34839c80d176SSepherosa Ziehau 
34846d5e2922SSepherosa Ziehau 	if (!page_set)
34856d5e2922SSepherosa Ziehau 		ret_val = e1000_disable_phy_wakeup_reg_access_bm(hw, &phy_reg);
34869c80d176SSepherosa Ziehau 
34879c80d176SSepherosa Ziehau 	return ret_val;
34889c80d176SSepherosa Ziehau }
34899c80d176SSepherosa Ziehau 
34909c80d176SSepherosa Ziehau /**
34919c80d176SSepherosa Ziehau  * e1000_power_up_phy_copper - Restore copper link in case of PHY power down
34929c80d176SSepherosa Ziehau  * @hw: pointer to the HW structure
34939c80d176SSepherosa Ziehau  *
34949c80d176SSepherosa Ziehau  * In the case of a PHY power down to save power, or to turn off link during a
34959c80d176SSepherosa Ziehau  * driver unload, or wake on lan is not enabled, restore the link to previous
34969c80d176SSepherosa Ziehau  * settings.
34979c80d176SSepherosa Ziehau  **/
e1000_power_up_phy_copper(struct e1000_hw * hw)34989c80d176SSepherosa Ziehau void e1000_power_up_phy_copper(struct e1000_hw *hw)
34999c80d176SSepherosa Ziehau {
35009c80d176SSepherosa Ziehau 	u16 mii_reg = 0;
35019c80d176SSepherosa Ziehau 
35029c80d176SSepherosa Ziehau 	/* The PHY will retain its settings across a power down/up cycle */
35039c80d176SSepherosa Ziehau 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
35049c80d176SSepherosa Ziehau 	mii_reg &= ~MII_CR_POWER_DOWN;
35059c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
35069c80d176SSepherosa Ziehau }
35079c80d176SSepherosa Ziehau 
35089c80d176SSepherosa Ziehau /**
35099c80d176SSepherosa Ziehau  * e1000_power_down_phy_copper - Restore copper link in case of PHY power down
35109c80d176SSepherosa Ziehau  * @hw: pointer to the HW structure
35119c80d176SSepherosa Ziehau  *
35129c80d176SSepherosa Ziehau  * In the case of a PHY power down to save power, or to turn off link during a
35139c80d176SSepherosa Ziehau  * driver unload, or wake on lan is not enabled, restore the link to previous
35149c80d176SSepherosa Ziehau  * settings.
35159c80d176SSepherosa Ziehau  **/
e1000_power_down_phy_copper(struct e1000_hw * hw)35169c80d176SSepherosa Ziehau void e1000_power_down_phy_copper(struct e1000_hw *hw)
35179c80d176SSepherosa Ziehau {
35189c80d176SSepherosa Ziehau 	u16 mii_reg = 0;
35199c80d176SSepherosa Ziehau 
35209c80d176SSepherosa Ziehau 	/* The PHY will retain its settings across a power down/up cycle */
35219c80d176SSepherosa Ziehau 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
35229c80d176SSepherosa Ziehau 	mii_reg |= MII_CR_POWER_DOWN;
35239c80d176SSepherosa Ziehau 	hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
35249c80d176SSepherosa Ziehau 	msec_delay(1);
35259c80d176SSepherosa Ziehau }
35266a5a645eSSepherosa Ziehau 
35276a5a645eSSepherosa Ziehau /**
35286a5a645eSSepherosa Ziehau  *  __e1000_read_phy_reg_hv -  Read HV PHY register
35296a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
35306a5a645eSSepherosa Ziehau  *  @offset: register offset to be read
35316a5a645eSSepherosa Ziehau  *  @data: pointer to the read data
35326a5a645eSSepherosa Ziehau  *  @locked: semaphore has already been acquired or not
3533*01a55482SSepherosa Ziehau  *  @page_set: BM_WUC_PAGE already set and access enabled
35346a5a645eSSepherosa Ziehau  *
35356a5a645eSSepherosa Ziehau  *  Acquires semaphore, if necessary, then reads the PHY register at offset
35366a5a645eSSepherosa Ziehau  *  and stores the retrieved information in data.  Release any acquired
35376a5a645eSSepherosa Ziehau  *  semaphore before exiting.
35386a5a645eSSepherosa Ziehau  **/
__e1000_read_phy_reg_hv(struct e1000_hw * hw,u32 offset,u16 * data,bool locked,bool page_set)35396a5a645eSSepherosa Ziehau static s32 __e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data,
35406d5e2922SSepherosa Ziehau 				   bool locked, bool page_set)
35416a5a645eSSepherosa Ziehau {
35426a5a645eSSepherosa Ziehau 	s32 ret_val;
35436a5a645eSSepherosa Ziehau 	u16 page = BM_PHY_REG_PAGE(offset);
35446a5a645eSSepherosa Ziehau 	u16 reg = BM_PHY_REG_NUM(offset);
35456d5e2922SSepherosa Ziehau 	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
35466a5a645eSSepherosa Ziehau 
35476a5a645eSSepherosa Ziehau 	DEBUGFUNC("__e1000_read_phy_reg_hv");
35486a5a645eSSepherosa Ziehau 
35496a5a645eSSepherosa Ziehau 	if (!locked) {
35506a5a645eSSepherosa Ziehau 		ret_val = hw->phy.ops.acquire(hw);
35516a5a645eSSepherosa Ziehau 		if (ret_val)
35526a5a645eSSepherosa Ziehau 			return ret_val;
35536a5a645eSSepherosa Ziehau 	}
35546a5a645eSSepherosa Ziehau 	/* Page 800 works differently than the rest so it has its own func */
35556a5a645eSSepherosa Ziehau 	if (page == BM_WUC_PAGE) {
35566d5e2922SSepherosa Ziehau 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data,
35576d5e2922SSepherosa Ziehau 							 TRUE, page_set);
35586a5a645eSSepherosa Ziehau 		goto out;
35596a5a645eSSepherosa Ziehau 	}
35606a5a645eSSepherosa Ziehau 
35616a5a645eSSepherosa Ziehau 	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
35626a5a645eSSepherosa Ziehau 		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
35636a5a645eSSepherosa Ziehau 							 data, TRUE);
35646a5a645eSSepherosa Ziehau 		goto out;
35656a5a645eSSepherosa Ziehau 	}
35666a5a645eSSepherosa Ziehau 
35676d5e2922SSepherosa Ziehau 	if (!page_set) {
35686a5a645eSSepherosa Ziehau 		if (page == HV_INTC_FC_PAGE_START)
35696a5a645eSSepherosa Ziehau 			page = 0;
35706a5a645eSSepherosa Ziehau 
35716a5a645eSSepherosa Ziehau 		if (reg > MAX_PHY_MULTI_PAGE_REG) {
35726a5a645eSSepherosa Ziehau 			/* Page is shifted left, PHY expects (page x 32) */
35736d5e2922SSepherosa Ziehau 			ret_val = e1000_set_page_igp(hw,
35746a5a645eSSepherosa Ziehau 						     (page << IGP_PAGE_SHIFT));
35756d5e2922SSepherosa Ziehau 
35766a5a645eSSepherosa Ziehau 			hw->phy.addr = phy_addr;
35776a5a645eSSepherosa Ziehau 
35786a5a645eSSepherosa Ziehau 			if (ret_val)
35796a5a645eSSepherosa Ziehau 				goto out;
35806a5a645eSSepherosa Ziehau 		}
35816d5e2922SSepherosa Ziehau 	}
35826d5e2922SSepherosa Ziehau 
35836d5e2922SSepherosa Ziehau 	DEBUGOUT3("reading PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
35846d5e2922SSepherosa Ziehau 		  page << IGP_PAGE_SHIFT, reg);
35856a5a645eSSepherosa Ziehau 
35866a5a645eSSepherosa Ziehau 	ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
35876a5a645eSSepherosa Ziehau 					  data);
35886a5a645eSSepherosa Ziehau out:
35896a5a645eSSepherosa Ziehau 	if (!locked)
35906a5a645eSSepherosa Ziehau 		hw->phy.ops.release(hw);
35916a5a645eSSepherosa Ziehau 
35926a5a645eSSepherosa Ziehau 	return ret_val;
35936a5a645eSSepherosa Ziehau }
35946a5a645eSSepherosa Ziehau 
35956a5a645eSSepherosa Ziehau /**
35966a5a645eSSepherosa Ziehau  *  e1000_read_phy_reg_hv -  Read HV PHY register
35976a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
35986a5a645eSSepherosa Ziehau  *  @offset: register offset to be read
35996a5a645eSSepherosa Ziehau  *  @data: pointer to the read data
36006a5a645eSSepherosa Ziehau  *
36016a5a645eSSepherosa Ziehau  *  Acquires semaphore then reads the PHY register at offset and stores
36026a5a645eSSepherosa Ziehau  *  the retrieved information in data.  Release the acquired semaphore
36036a5a645eSSepherosa Ziehau  *  before exiting.
36046a5a645eSSepherosa Ziehau  **/
e1000_read_phy_reg_hv(struct e1000_hw * hw,u32 offset,u16 * data)36056a5a645eSSepherosa Ziehau s32 e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data)
36066a5a645eSSepherosa Ziehau {
360765aebe9fSSepherosa Ziehau 	return __e1000_read_phy_reg_hv(hw, offset, data, FALSE, false);
36086a5a645eSSepherosa Ziehau }
36096a5a645eSSepherosa Ziehau 
36106a5a645eSSepherosa Ziehau /**
36116a5a645eSSepherosa Ziehau  *  e1000_read_phy_reg_hv_locked -  Read HV PHY register
36126a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
36136a5a645eSSepherosa Ziehau  *  @offset: register offset to be read
36146a5a645eSSepherosa Ziehau  *  @data: pointer to the read data
36156a5a645eSSepherosa Ziehau  *
36166a5a645eSSepherosa Ziehau  *  Reads the PHY register at offset and stores the retrieved information
36176a5a645eSSepherosa Ziehau  *  in data.  Assumes semaphore already acquired.
36186a5a645eSSepherosa Ziehau  **/
e1000_read_phy_reg_hv_locked(struct e1000_hw * hw,u32 offset,u16 * data)36196a5a645eSSepherosa Ziehau s32 e1000_read_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 *data)
36206a5a645eSSepherosa Ziehau {
36216d5e2922SSepherosa Ziehau 	return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, FALSE);
36226d5e2922SSepherosa Ziehau }
36236d5e2922SSepherosa Ziehau 
36246d5e2922SSepherosa Ziehau /**
36256d5e2922SSepherosa Ziehau  *  e1000_read_phy_reg_page_hv - Read HV PHY register
36266d5e2922SSepherosa Ziehau  *  @hw: pointer to the HW structure
36276d5e2922SSepherosa Ziehau  *  @offset: register offset to write to
36286d5e2922SSepherosa Ziehau  *  @data: data to write at register offset
36296d5e2922SSepherosa Ziehau  *
36306d5e2922SSepherosa Ziehau  *  Reads the PHY register at offset and stores the retrieved information
36316d5e2922SSepherosa Ziehau  *  in data.  Assumes semaphore already acquired and page already set.
36326d5e2922SSepherosa Ziehau  **/
e1000_read_phy_reg_page_hv(struct e1000_hw * hw,u32 offset,u16 * data)36336d5e2922SSepherosa Ziehau s32 e1000_read_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 *data)
36346d5e2922SSepherosa Ziehau {
363565aebe9fSSepherosa Ziehau 	return __e1000_read_phy_reg_hv(hw, offset, data, TRUE, true);
36366a5a645eSSepherosa Ziehau }
36376a5a645eSSepherosa Ziehau 
36386a5a645eSSepherosa Ziehau /**
36396a5a645eSSepherosa Ziehau  *  __e1000_write_phy_reg_hv - Write HV PHY register
36406a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
36416a5a645eSSepherosa Ziehau  *  @offset: register offset to write to
36426a5a645eSSepherosa Ziehau  *  @data: data to write at register offset
36436a5a645eSSepherosa Ziehau  *  @locked: semaphore has already been acquired or not
3644*01a55482SSepherosa Ziehau  *  @page_set: BM_WUC_PAGE already set and access enabled
36456a5a645eSSepherosa Ziehau  *
36466a5a645eSSepherosa Ziehau  *  Acquires semaphore, if necessary, then writes the data to PHY register
36476a5a645eSSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
36486a5a645eSSepherosa Ziehau  **/
__e1000_write_phy_reg_hv(struct e1000_hw * hw,u32 offset,u16 data,bool locked,bool page_set)36496a5a645eSSepherosa Ziehau static s32 __e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data,
36506d5e2922SSepherosa Ziehau 				    bool locked, bool page_set)
36516a5a645eSSepherosa Ziehau {
36526a5a645eSSepherosa Ziehau 	s32 ret_val;
36536a5a645eSSepherosa Ziehau 	u16 page = BM_PHY_REG_PAGE(offset);
36546a5a645eSSepherosa Ziehau 	u16 reg = BM_PHY_REG_NUM(offset);
36556d5e2922SSepherosa Ziehau 	u32 phy_addr = hw->phy.addr = e1000_get_phy_addr_for_hv_page(page);
36566a5a645eSSepherosa Ziehau 
36576a5a645eSSepherosa Ziehau 	DEBUGFUNC("__e1000_write_phy_reg_hv");
36586a5a645eSSepherosa Ziehau 
36596a5a645eSSepherosa Ziehau 	if (!locked) {
36606a5a645eSSepherosa Ziehau 		ret_val = hw->phy.ops.acquire(hw);
36616a5a645eSSepherosa Ziehau 		if (ret_val)
36626a5a645eSSepherosa Ziehau 			return ret_val;
36636a5a645eSSepherosa Ziehau 	}
36646a5a645eSSepherosa Ziehau 	/* Page 800 works differently than the rest so it has its own func */
36656a5a645eSSepherosa Ziehau 	if (page == BM_WUC_PAGE) {
36666d5e2922SSepherosa Ziehau 		ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data,
36676d5e2922SSepherosa Ziehau 							 FALSE, page_set);
36686a5a645eSSepherosa Ziehau 		goto out;
36696a5a645eSSepherosa Ziehau 	}
36706a5a645eSSepherosa Ziehau 
36716a5a645eSSepherosa Ziehau 	if (page > 0 && page < HV_INTC_FC_PAGE_START) {
36726a5a645eSSepherosa Ziehau 		ret_val = e1000_access_phy_debug_regs_hv(hw, offset,
36736a5a645eSSepherosa Ziehau 							 &data, FALSE);
36746a5a645eSSepherosa Ziehau 		goto out;
36756a5a645eSSepherosa Ziehau 	}
36766a5a645eSSepherosa Ziehau 
36776d5e2922SSepherosa Ziehau 	if (!page_set) {
36786a5a645eSSepherosa Ziehau 		if (page == HV_INTC_FC_PAGE_START)
36796a5a645eSSepherosa Ziehau 			page = 0;
36806a5a645eSSepherosa Ziehau 
3681379ebbe7SSepherosa Ziehau 		/* Workaround MDIO accesses being disabled after entering IEEE
36826d5e2922SSepherosa Ziehau 		 * Power Down (when bit 11 of the PHY Control register is set)
36836a5a645eSSepherosa Ziehau 		 */
36846a5a645eSSepherosa Ziehau 		if ((hw->phy.type == e1000_phy_82578) &&
36856a5a645eSSepherosa Ziehau 		    (hw->phy.revision >= 1) &&
36866a5a645eSSepherosa Ziehau 		    (hw->phy.addr == 2) &&
3687379ebbe7SSepherosa Ziehau 		    !(MAX_PHY_REG_ADDRESS & reg) &&
36886a5a645eSSepherosa Ziehau 		    (data & (1 << 11))) {
36896a5a645eSSepherosa Ziehau 			u16 data2 = 0x7EFF;
36906d5e2922SSepherosa Ziehau 			ret_val = e1000_access_phy_debug_regs_hv(hw,
36916d5e2922SSepherosa Ziehau 								 (1 << 6) | 0x3,
36926a5a645eSSepherosa Ziehau 								 &data2, FALSE);
36936a5a645eSSepherosa Ziehau 			if (ret_val)
36946a5a645eSSepherosa Ziehau 				goto out;
36956a5a645eSSepherosa Ziehau 		}
36966a5a645eSSepherosa Ziehau 
36976a5a645eSSepherosa Ziehau 		if (reg > MAX_PHY_MULTI_PAGE_REG) {
36986a5a645eSSepherosa Ziehau 			/* Page is shifted left, PHY expects (page x 32) */
36996d5e2922SSepherosa Ziehau 			ret_val = e1000_set_page_igp(hw,
37006a5a645eSSepherosa Ziehau 						     (page << IGP_PAGE_SHIFT));
37016d5e2922SSepherosa Ziehau 
37026a5a645eSSepherosa Ziehau 			hw->phy.addr = phy_addr;
37036a5a645eSSepherosa Ziehau 
37046a5a645eSSepherosa Ziehau 			if (ret_val)
37056a5a645eSSepherosa Ziehau 				goto out;
37066a5a645eSSepherosa Ziehau 		}
37076d5e2922SSepherosa Ziehau 	}
37086d5e2922SSepherosa Ziehau 
37096d5e2922SSepherosa Ziehau 	DEBUGOUT3("writing PHY page %d (or 0x%x shifted) reg 0x%x\n", page,
37106d5e2922SSepherosa Ziehau 		  page << IGP_PAGE_SHIFT, reg);
37116a5a645eSSepherosa Ziehau 
37126a5a645eSSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg,
37136a5a645eSSepherosa Ziehau 					   data);
37146a5a645eSSepherosa Ziehau 
37156a5a645eSSepherosa Ziehau out:
37166a5a645eSSepherosa Ziehau 	if (!locked)
37176a5a645eSSepherosa Ziehau 		hw->phy.ops.release(hw);
37186a5a645eSSepherosa Ziehau 
37196a5a645eSSepherosa Ziehau 	return ret_val;
37206a5a645eSSepherosa Ziehau }
37216a5a645eSSepherosa Ziehau 
37226a5a645eSSepherosa Ziehau /**
37236a5a645eSSepherosa Ziehau  *  e1000_write_phy_reg_hv - Write HV PHY register
37246a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
37256a5a645eSSepherosa Ziehau  *  @offset: register offset to write to
37266a5a645eSSepherosa Ziehau  *  @data: data to write at register offset
37276a5a645eSSepherosa Ziehau  *
37286a5a645eSSepherosa Ziehau  *  Acquires semaphore then writes the data to PHY register at the offset.
37296a5a645eSSepherosa Ziehau  *  Release the acquired semaphores before exiting.
37306a5a645eSSepherosa Ziehau  **/
e1000_write_phy_reg_hv(struct e1000_hw * hw,u32 offset,u16 data)37316a5a645eSSepherosa Ziehau s32 e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data)
37326a5a645eSSepherosa Ziehau {
373365aebe9fSSepherosa Ziehau 	return __e1000_write_phy_reg_hv(hw, offset, data, FALSE, false);
37346a5a645eSSepherosa Ziehau }
37356a5a645eSSepherosa Ziehau 
37366a5a645eSSepherosa Ziehau /**
37376a5a645eSSepherosa Ziehau  *  e1000_write_phy_reg_hv_locked - Write HV PHY register
37386a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
37396a5a645eSSepherosa Ziehau  *  @offset: register offset to write to
37406a5a645eSSepherosa Ziehau  *  @data: data to write at register offset
37416a5a645eSSepherosa Ziehau  *
37426a5a645eSSepherosa Ziehau  *  Writes the data to PHY register at the offset.  Assumes semaphore
37436a5a645eSSepherosa Ziehau  *  already acquired.
37446a5a645eSSepherosa Ziehau  **/
e1000_write_phy_reg_hv_locked(struct e1000_hw * hw,u32 offset,u16 data)37456a5a645eSSepherosa Ziehau s32 e1000_write_phy_reg_hv_locked(struct e1000_hw *hw, u32 offset, u16 data)
37466a5a645eSSepherosa Ziehau {
37476d5e2922SSepherosa Ziehau 	return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, FALSE);
37486d5e2922SSepherosa Ziehau }
37496d5e2922SSepherosa Ziehau 
37506d5e2922SSepherosa Ziehau /**
37516d5e2922SSepherosa Ziehau  *  e1000_write_phy_reg_page_hv - Write HV PHY register
37526d5e2922SSepherosa Ziehau  *  @hw: pointer to the HW structure
37536d5e2922SSepherosa Ziehau  *  @offset: register offset to write to
37546d5e2922SSepherosa Ziehau  *  @data: data to write at register offset
37556d5e2922SSepherosa Ziehau  *
37566d5e2922SSepherosa Ziehau  *  Writes the data to PHY register at the offset.  Assumes semaphore
37576d5e2922SSepherosa Ziehau  *  already acquired and page already set.
37586d5e2922SSepherosa Ziehau  **/
e1000_write_phy_reg_page_hv(struct e1000_hw * hw,u32 offset,u16 data)37596d5e2922SSepherosa Ziehau s32 e1000_write_phy_reg_page_hv(struct e1000_hw *hw, u32 offset, u16 data)
37606d5e2922SSepherosa Ziehau {
376165aebe9fSSepherosa Ziehau 	return __e1000_write_phy_reg_hv(hw, offset, data, TRUE, true);
37626a5a645eSSepherosa Ziehau }
37636a5a645eSSepherosa Ziehau 
37646a5a645eSSepherosa Ziehau /**
37656a5a645eSSepherosa Ziehau  *  e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page
37666a5a645eSSepherosa Ziehau  *  @page: page to be accessed
37676a5a645eSSepherosa Ziehau  **/
e1000_get_phy_addr_for_hv_page(u32 page)37686a5a645eSSepherosa Ziehau static u32 e1000_get_phy_addr_for_hv_page(u32 page)
37696a5a645eSSepherosa Ziehau {
37706a5a645eSSepherosa Ziehau 	u32 phy_addr = 2;
37716a5a645eSSepherosa Ziehau 
37726a5a645eSSepherosa Ziehau 	if (page >= HV_INTC_FC_PAGE_START)
37736a5a645eSSepherosa Ziehau 		phy_addr = 1;
37746a5a645eSSepherosa Ziehau 
37756a5a645eSSepherosa Ziehau 	return phy_addr;
37766a5a645eSSepherosa Ziehau }
37776a5a645eSSepherosa Ziehau 
37786a5a645eSSepherosa Ziehau /**
37796a5a645eSSepherosa Ziehau  *  e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers
37806a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
37816a5a645eSSepherosa Ziehau  *  @offset: register offset to be read or written
37826a5a645eSSepherosa Ziehau  *  @data: pointer to the data to be read or written
37836d5e2922SSepherosa Ziehau  *  @read: determines if operation is read or write
37846a5a645eSSepherosa Ziehau  *
37856a5a645eSSepherosa Ziehau  *  Reads the PHY register at offset and stores the retreived information
37866a5a645eSSepherosa Ziehau  *  in data.  Assumes semaphore already acquired.  Note that the procedure
37876d5e2922SSepherosa Ziehau  *  to access these regs uses the address port and data port to read/write.
37886d5e2922SSepherosa Ziehau  *  These accesses done with PHY address 2 and without using pages.
37896a5a645eSSepherosa Ziehau  **/
e1000_access_phy_debug_regs_hv(struct e1000_hw * hw,u32 offset,u16 * data,bool read)37906a5a645eSSepherosa Ziehau static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset,
37916a5a645eSSepherosa Ziehau 					  u16 *data, bool read)
37926a5a645eSSepherosa Ziehau {
37936a5a645eSSepherosa Ziehau 	s32 ret_val;
3794379ebbe7SSepherosa Ziehau 	u32 addr_reg;
3795379ebbe7SSepherosa Ziehau 	u32 data_reg;
37966a5a645eSSepherosa Ziehau 
37976a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_access_phy_debug_regs_hv");
37986a5a645eSSepherosa Ziehau 
37996a5a645eSSepherosa Ziehau 	/* This takes care of the difference with desktop vs mobile phy */
38004765c386SMichael Neumann 	addr_reg = ((hw->phy.type == e1000_phy_82578) ?
38014765c386SMichael Neumann 		    I82578_ADDR_REG : I82577_ADDR_REG);
38026a5a645eSSepherosa Ziehau 	data_reg = addr_reg + 1;
38036a5a645eSSepherosa Ziehau 
38046a5a645eSSepherosa Ziehau 	/* All operations in this function are phy address 2 */
38056a5a645eSSepherosa Ziehau 	hw->phy.addr = 2;
38066a5a645eSSepherosa Ziehau 
38076a5a645eSSepherosa Ziehau 	/* masking with 0x3F to remove the page from offset */
38086a5a645eSSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F);
38096a5a645eSSepherosa Ziehau 	if (ret_val) {
38106d5e2922SSepherosa Ziehau 		DEBUGOUT("Could not write the Address Offset port register\n");
38114be59a01SSepherosa Ziehau 		return ret_val;
38126a5a645eSSepherosa Ziehau 	}
38136a5a645eSSepherosa Ziehau 
38146a5a645eSSepherosa Ziehau 	/* Read or write the data value next */
38156a5a645eSSepherosa Ziehau 	if (read)
38166a5a645eSSepherosa Ziehau 		ret_val = e1000_read_phy_reg_mdic(hw, data_reg, data);
38176a5a645eSSepherosa Ziehau 	else
38186a5a645eSSepherosa Ziehau 		ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data);
38196a5a645eSSepherosa Ziehau 
38204be59a01SSepherosa Ziehau 	if (ret_val)
38216d5e2922SSepherosa Ziehau 		DEBUGOUT("Could not access the Data port register\n");
38226a5a645eSSepherosa Ziehau 
38236a5a645eSSepherosa Ziehau 	return ret_val;
38246a5a645eSSepherosa Ziehau }
38256a5a645eSSepherosa Ziehau 
38266a5a645eSSepherosa Ziehau /**
38276a5a645eSSepherosa Ziehau  *  e1000_link_stall_workaround_hv - Si workaround
38286a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
38296a5a645eSSepherosa Ziehau  *
38306a5a645eSSepherosa Ziehau  *  This function works around a Si bug where the link partner can get
38316a5a645eSSepherosa Ziehau  *  a link up indication before the PHY does.  If small packets are sent
38326a5a645eSSepherosa Ziehau  *  by the link partner they can be placed in the packet buffer without
38336a5a645eSSepherosa Ziehau  *  being properly accounted for by the PHY and will stall preventing
38346a5a645eSSepherosa Ziehau  *  further packets from being received.  The workaround is to clear the
38356a5a645eSSepherosa Ziehau  *  packet buffer after the PHY detects link up.
38366a5a645eSSepherosa Ziehau  **/
e1000_link_stall_workaround_hv(struct e1000_hw * hw)38376a5a645eSSepherosa Ziehau s32 e1000_link_stall_workaround_hv(struct e1000_hw *hw)
38386a5a645eSSepherosa Ziehau {
38396a5a645eSSepherosa Ziehau 	s32 ret_val = E1000_SUCCESS;
38406a5a645eSSepherosa Ziehau 	u16 data;
38416a5a645eSSepherosa Ziehau 
38426a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_link_stall_workaround_hv");
38436a5a645eSSepherosa Ziehau 
38446a5a645eSSepherosa Ziehau 	if (hw->phy.type != e1000_phy_82578)
38454be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
38466a5a645eSSepherosa Ziehau 
38476a5a645eSSepherosa Ziehau 	/* Do not apply workaround if in PHY loopback bit 14 set */
38486a5a645eSSepherosa Ziehau 	hw->phy.ops.read_reg(hw, PHY_CONTROL, &data);
38496a5a645eSSepherosa Ziehau 	if (data & PHY_CONTROL_LB)
38504be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
38516a5a645eSSepherosa Ziehau 
38526a5a645eSSepherosa Ziehau 	/* check if link is up and at 1Gbps */
38536a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data);
38546a5a645eSSepherosa Ziehau 	if (ret_val)
38554be59a01SSepherosa Ziehau 		return ret_val;
38566a5a645eSSepherosa Ziehau 
38574765c386SMichael Neumann 	data &= (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
38584765c386SMichael Neumann 		 BM_CS_STATUS_SPEED_MASK);
38596a5a645eSSepherosa Ziehau 
38604be59a01SSepherosa Ziehau 	if (data != (BM_CS_STATUS_LINK_UP | BM_CS_STATUS_RESOLVED |
38616a5a645eSSepherosa Ziehau 		     BM_CS_STATUS_SPEED_1000))
38624be59a01SSepherosa Ziehau 		return E1000_SUCCESS;
38636a5a645eSSepherosa Ziehau 
38646a5a645eSSepherosa Ziehau 	msec_delay(200);
38656a5a645eSSepherosa Ziehau 
38666a5a645eSSepherosa Ziehau 	/* flush the packets in the fifo buffer */
38676a5a645eSSepherosa Ziehau 	ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
3868379ebbe7SSepherosa Ziehau 					(HV_MUX_DATA_CTRL_GEN_TO_MAC |
3869379ebbe7SSepherosa Ziehau 					 HV_MUX_DATA_CTRL_FORCE_SPEED));
38706a5a645eSSepherosa Ziehau 	if (ret_val)
38716a5a645eSSepherosa Ziehau 		return ret_val;
38724be59a01SSepherosa Ziehau 
38734be59a01SSepherosa Ziehau 	return hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL,
38744be59a01SSepherosa Ziehau 				     HV_MUX_DATA_CTRL_GEN_TO_MAC);
38756a5a645eSSepherosa Ziehau }
38766a5a645eSSepherosa Ziehau 
38776a5a645eSSepherosa Ziehau /**
38786a5a645eSSepherosa Ziehau  *  e1000_check_polarity_82577 - Checks the polarity.
38796a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
38806a5a645eSSepherosa Ziehau  *
38816a5a645eSSepherosa Ziehau  *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
38826a5a645eSSepherosa Ziehau  *
38836a5a645eSSepherosa Ziehau  *  Polarity is determined based on the PHY specific status register.
38846a5a645eSSepherosa Ziehau  **/
e1000_check_polarity_82577(struct e1000_hw * hw)38856a5a645eSSepherosa Ziehau s32 e1000_check_polarity_82577(struct e1000_hw *hw)
38866a5a645eSSepherosa Ziehau {
38876a5a645eSSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
38886a5a645eSSepherosa Ziehau 	s32 ret_val;
38896a5a645eSSepherosa Ziehau 	u16 data;
38906a5a645eSSepherosa Ziehau 
38916a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_check_polarity_82577");
38926a5a645eSSepherosa Ziehau 
38936a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
38946a5a645eSSepherosa Ziehau 
38956a5a645eSSepherosa Ziehau 	if (!ret_val)
3896379ebbe7SSepherosa Ziehau 		phy->cable_polarity = ((data & I82577_PHY_STATUS2_REV_POLARITY)
38976a5a645eSSepherosa Ziehau 				       ? e1000_rev_polarity_reversed
3898379ebbe7SSepherosa Ziehau 				       : e1000_rev_polarity_normal);
38996a5a645eSSepherosa Ziehau 
39006a5a645eSSepherosa Ziehau 	return ret_val;
39016a5a645eSSepherosa Ziehau }
39026a5a645eSSepherosa Ziehau 
39036a5a645eSSepherosa Ziehau /**
39046a5a645eSSepherosa Ziehau  *  e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY
39056a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
39066a5a645eSSepherosa Ziehau  *
39076a5a645eSSepherosa Ziehau  *  Calls the PHY setup function to force speed and duplex.
39086a5a645eSSepherosa Ziehau  **/
e1000_phy_force_speed_duplex_82577(struct e1000_hw * hw)39096a5a645eSSepherosa Ziehau s32 e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw)
39106a5a645eSSepherosa Ziehau {
39116a5a645eSSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
39126a5a645eSSepherosa Ziehau 	s32 ret_val;
39136a5a645eSSepherosa Ziehau 	u16 phy_data;
39146a5a645eSSepherosa Ziehau 	bool link;
39156a5a645eSSepherosa Ziehau 
39166a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_phy_force_speed_duplex_82577");
39176a5a645eSSepherosa Ziehau 
39186a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data);
39196a5a645eSSepherosa Ziehau 	if (ret_val)
39204be59a01SSepherosa Ziehau 		return ret_val;
39216a5a645eSSepherosa Ziehau 
39226a5a645eSSepherosa Ziehau 	e1000_phy_force_speed_duplex_setup(hw, &phy_data);
39236a5a645eSSepherosa Ziehau 
39246a5a645eSSepherosa Ziehau 	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data);
39256a5a645eSSepherosa Ziehau 	if (ret_val)
39264be59a01SSepherosa Ziehau 		return ret_val;
39276a5a645eSSepherosa Ziehau 
39286a5a645eSSepherosa Ziehau 	usec_delay(1);
39296a5a645eSSepherosa Ziehau 
39306a5a645eSSepherosa Ziehau 	if (phy->autoneg_wait_to_complete) {
39316a5a645eSSepherosa Ziehau 		DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n");
39326a5a645eSSepherosa Ziehau 
39334be59a01SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
39344be59a01SSepherosa Ziehau 						     100000, &link);
39356a5a645eSSepherosa Ziehau 		if (ret_val)
39364be59a01SSepherosa Ziehau 			return ret_val;
39376a5a645eSSepherosa Ziehau 
39386a5a645eSSepherosa Ziehau 		if (!link)
39396a5a645eSSepherosa Ziehau 			DEBUGOUT("Link taking longer than expected.\n");
39406a5a645eSSepherosa Ziehau 
39416a5a645eSSepherosa Ziehau 		/* Try once more */
39424be59a01SSepherosa Ziehau 		ret_val = e1000_phy_has_link_generic(hw, PHY_FORCE_LIMIT,
39434be59a01SSepherosa Ziehau 						     100000, &link);
39446a5a645eSSepherosa Ziehau 	}
39456a5a645eSSepherosa Ziehau 
39466a5a645eSSepherosa Ziehau 	return ret_val;
39476a5a645eSSepherosa Ziehau }
39486a5a645eSSepherosa Ziehau 
39496a5a645eSSepherosa Ziehau /**
39506a5a645eSSepherosa Ziehau  *  e1000_get_phy_info_82577 - Retrieve I82577 PHY information
39516a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
39526a5a645eSSepherosa Ziehau  *
39536a5a645eSSepherosa Ziehau  *  Read PHY status to determine if link is up.  If link is up, then
39546a5a645eSSepherosa Ziehau  *  set/determine 10base-T extended distance and polarity correction.  Read
39556a5a645eSSepherosa Ziehau  *  PHY port status to determine MDI/MDIx and speed.  Based on the speed,
39566a5a645eSSepherosa Ziehau  *  determine on the cable length, local and remote receiver.
39576a5a645eSSepherosa Ziehau  **/
e1000_get_phy_info_82577(struct e1000_hw * hw)39586a5a645eSSepherosa Ziehau s32 e1000_get_phy_info_82577(struct e1000_hw *hw)
39596a5a645eSSepherosa Ziehau {
39606a5a645eSSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
39616a5a645eSSepherosa Ziehau 	s32 ret_val;
39626a5a645eSSepherosa Ziehau 	u16 data;
39636a5a645eSSepherosa Ziehau 	bool link;
39646a5a645eSSepherosa Ziehau 
39656a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_get_phy_info_82577");
39666a5a645eSSepherosa Ziehau 
39676a5a645eSSepherosa Ziehau 	ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link);
39686a5a645eSSepherosa Ziehau 	if (ret_val)
39694be59a01SSepherosa Ziehau 		return ret_val;
39706a5a645eSSepherosa Ziehau 
39716a5a645eSSepherosa Ziehau 	if (!link) {
39726a5a645eSSepherosa Ziehau 		DEBUGOUT("Phy info is only valid if link is up\n");
39734be59a01SSepherosa Ziehau 		return -E1000_ERR_CONFIG;
39746a5a645eSSepherosa Ziehau 	}
39756a5a645eSSepherosa Ziehau 
39766a5a645eSSepherosa Ziehau 	phy->polarity_correction = TRUE;
39776a5a645eSSepherosa Ziehau 
39786a5a645eSSepherosa Ziehau 	ret_val = e1000_check_polarity_82577(hw);
39796a5a645eSSepherosa Ziehau 	if (ret_val)
39804be59a01SSepherosa Ziehau 		return ret_val;
39816a5a645eSSepherosa Ziehau 
39826a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data);
39836a5a645eSSepherosa Ziehau 	if (ret_val)
39844be59a01SSepherosa Ziehau 		return ret_val;
39856a5a645eSSepherosa Ziehau 
39864be59a01SSepherosa Ziehau 	phy->is_mdix = !!(data & I82577_PHY_STATUS2_MDIX);
39876a5a645eSSepherosa Ziehau 
39886a5a645eSSepherosa Ziehau 	if ((data & I82577_PHY_STATUS2_SPEED_MASK) ==
39896a5a645eSSepherosa Ziehau 	    I82577_PHY_STATUS2_SPEED_1000MBPS) {
39906a5a645eSSepherosa Ziehau 		ret_val = hw->phy.ops.get_cable_length(hw);
39916a5a645eSSepherosa Ziehau 		if (ret_val)
39924be59a01SSepherosa Ziehau 			return ret_val;
39936a5a645eSSepherosa Ziehau 
39946a5a645eSSepherosa Ziehau 		ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data);
39956a5a645eSSepherosa Ziehau 		if (ret_val)
39964be59a01SSepherosa Ziehau 			return ret_val;
39976a5a645eSSepherosa Ziehau 
39986a5a645eSSepherosa Ziehau 		phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS)
39996a5a645eSSepherosa Ziehau 				? e1000_1000t_rx_status_ok
40006a5a645eSSepherosa Ziehau 				: e1000_1000t_rx_status_not_ok;
40016a5a645eSSepherosa Ziehau 
40026a5a645eSSepherosa Ziehau 		phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS)
40036a5a645eSSepherosa Ziehau 				 ? e1000_1000t_rx_status_ok
40046a5a645eSSepherosa Ziehau 				 : e1000_1000t_rx_status_not_ok;
40056a5a645eSSepherosa Ziehau 	} else {
40066a5a645eSSepherosa Ziehau 		phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED;
40076a5a645eSSepherosa Ziehau 		phy->local_rx = e1000_1000t_rx_status_undefined;
40086a5a645eSSepherosa Ziehau 		phy->remote_rx = e1000_1000t_rx_status_undefined;
40096a5a645eSSepherosa Ziehau 	}
40106a5a645eSSepherosa Ziehau 
40114be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
40126a5a645eSSepherosa Ziehau }
40136a5a645eSSepherosa Ziehau 
40146a5a645eSSepherosa Ziehau /**
40156a5a645eSSepherosa Ziehau  *  e1000_get_cable_length_82577 - Determine cable length for 82577 PHY
40166a5a645eSSepherosa Ziehau  *  @hw: pointer to the HW structure
40176a5a645eSSepherosa Ziehau  *
40186a5a645eSSepherosa Ziehau  * Reads the diagnostic status register and verifies result is valid before
40196a5a645eSSepherosa Ziehau  * placing it in the phy_cable_length field.
40206a5a645eSSepherosa Ziehau  **/
e1000_get_cable_length_82577(struct e1000_hw * hw)40216a5a645eSSepherosa Ziehau s32 e1000_get_cable_length_82577(struct e1000_hw *hw)
40226a5a645eSSepherosa Ziehau {
40236a5a645eSSepherosa Ziehau 	struct e1000_phy_info *phy = &hw->phy;
40246a5a645eSSepherosa Ziehau 	s32 ret_val;
40256a5a645eSSepherosa Ziehau 	u16 phy_data, length;
40266a5a645eSSepherosa Ziehau 
40276a5a645eSSepherosa Ziehau 	DEBUGFUNC("e1000_get_cable_length_82577");
40286a5a645eSSepherosa Ziehau 
40296a5a645eSSepherosa Ziehau 	ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data);
40306a5a645eSSepherosa Ziehau 	if (ret_val)
40314be59a01SSepherosa Ziehau 		return ret_val;
40326a5a645eSSepherosa Ziehau 
4033379ebbe7SSepherosa Ziehau 	length = ((phy_data & I82577_DSTATUS_CABLE_LENGTH) >>
4034379ebbe7SSepherosa Ziehau 		  I82577_DSTATUS_CABLE_LENGTH_SHIFT);
40356a5a645eSSepherosa Ziehau 
40366a5a645eSSepherosa Ziehau 	if (length == E1000_CABLE_LENGTH_UNDEFINED)
4037379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
40386a5a645eSSepherosa Ziehau 
40396a5a645eSSepherosa Ziehau 	phy->cable_length = length;
40406a5a645eSSepherosa Ziehau 
40414be59a01SSepherosa Ziehau 	return E1000_SUCCESS;
40424be59a01SSepherosa Ziehau }
40434be59a01SSepherosa Ziehau 
40444be59a01SSepherosa Ziehau /**
40454be59a01SSepherosa Ziehau  *  e1000_write_phy_reg_gs40g - Write GS40G  PHY register
40464be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
40474be59a01SSepherosa Ziehau  *  @offset: register offset to write to
40484be59a01SSepherosa Ziehau  *  @data: data to write at register offset
40494be59a01SSepherosa Ziehau  *
40504be59a01SSepherosa Ziehau  *  Acquires semaphore, if necessary, then writes the data to PHY register
40514be59a01SSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
40524be59a01SSepherosa Ziehau  **/
e1000_write_phy_reg_gs40g(struct e1000_hw * hw,u32 offset,u16 data)40534be59a01SSepherosa Ziehau s32 e1000_write_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 data)
40544be59a01SSepherosa Ziehau {
40554be59a01SSepherosa Ziehau 	s32 ret_val;
40564be59a01SSepherosa Ziehau 	u16 page = offset >> GS40G_PAGE_SHIFT;
40574be59a01SSepherosa Ziehau 
40584be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_gs40g");
40594be59a01SSepherosa Ziehau 
40604be59a01SSepherosa Ziehau 	offset = offset & GS40G_OFFSET_MASK;
40614be59a01SSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
40624be59a01SSepherosa Ziehau 	if (ret_val)
40634be59a01SSepherosa Ziehau 		return ret_val;
40644be59a01SSepherosa Ziehau 
40654be59a01SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
40664be59a01SSepherosa Ziehau 	if (ret_val)
40674be59a01SSepherosa Ziehau 		goto release;
40684be59a01SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, offset, data);
40694be59a01SSepherosa Ziehau 
40704be59a01SSepherosa Ziehau release:
40714be59a01SSepherosa Ziehau 	hw->phy.ops.release(hw);
40724be59a01SSepherosa Ziehau 	return ret_val;
40734be59a01SSepherosa Ziehau }
40744be59a01SSepherosa Ziehau 
40754be59a01SSepherosa Ziehau /**
40764be59a01SSepherosa Ziehau  *  e1000_read_phy_reg_gs40g - Read GS40G  PHY register
40774be59a01SSepherosa Ziehau  *  @hw: pointer to the HW structure
40784be59a01SSepherosa Ziehau  *  @offset: lower half is register offset to read to
40794be59a01SSepherosa Ziehau  *     upper half is page to use.
40804be59a01SSepherosa Ziehau  *  @data: data to read at register offset
40814be59a01SSepherosa Ziehau  *
40824be59a01SSepherosa Ziehau  *  Acquires semaphore, if necessary, then reads the data in the PHY register
40834be59a01SSepherosa Ziehau  *  at the offset.  Release any acquired semaphores before exiting.
40844be59a01SSepherosa Ziehau  **/
e1000_read_phy_reg_gs40g(struct e1000_hw * hw,u32 offset,u16 * data)40854be59a01SSepherosa Ziehau s32 e1000_read_phy_reg_gs40g(struct e1000_hw *hw, u32 offset, u16 *data)
40864be59a01SSepherosa Ziehau {
40874be59a01SSepherosa Ziehau 	s32 ret_val;
40884be59a01SSepherosa Ziehau 	u16 page = offset >> GS40G_PAGE_SHIFT;
40894be59a01SSepherosa Ziehau 
40904be59a01SSepherosa Ziehau 	DEBUGFUNC("e1000_read_phy_reg_gs40g");
40914be59a01SSepherosa Ziehau 
40924be59a01SSepherosa Ziehau 	offset = offset & GS40G_OFFSET_MASK;
40934be59a01SSepherosa Ziehau 	ret_val = hw->phy.ops.acquire(hw);
40944be59a01SSepherosa Ziehau 	if (ret_val)
40954be59a01SSepherosa Ziehau 		return ret_val;
40964be59a01SSepherosa Ziehau 
40974be59a01SSepherosa Ziehau 	ret_val = e1000_write_phy_reg_mdic(hw, GS40G_PAGE_SELECT, page);
40984be59a01SSepherosa Ziehau 	if (ret_val)
40994be59a01SSepherosa Ziehau 		goto release;
41004be59a01SSepherosa Ziehau 	ret_val = e1000_read_phy_reg_mdic(hw, offset, data);
41014be59a01SSepherosa Ziehau 
41024be59a01SSepherosa Ziehau release:
41034be59a01SSepherosa Ziehau 	hw->phy.ops.release(hw);
41046a5a645eSSepherosa Ziehau 	return ret_val;
41056a5a645eSSepherosa Ziehau }
4106379ebbe7SSepherosa Ziehau 
4107379ebbe7SSepherosa Ziehau /**
4108379ebbe7SSepherosa Ziehau  *  e1000_read_phy_reg_mphy - Read mPHY control register
4109379ebbe7SSepherosa Ziehau  *  @hw: pointer to the HW structure
4110379ebbe7SSepherosa Ziehau  *  @address: address to be read
4111379ebbe7SSepherosa Ziehau  *  @data: pointer to the read data
4112379ebbe7SSepherosa Ziehau  *
4113379ebbe7SSepherosa Ziehau  *  Reads the mPHY control register in the PHY at offset and stores the
4114379ebbe7SSepherosa Ziehau  *  information read to data.
4115379ebbe7SSepherosa Ziehau  **/
e1000_read_phy_reg_mphy(struct e1000_hw * hw,u32 address,u32 * data)4116379ebbe7SSepherosa Ziehau s32 e1000_read_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 *data)
4117379ebbe7SSepherosa Ziehau {
4118379ebbe7SSepherosa Ziehau 	u32 mphy_ctrl = 0;
4119379ebbe7SSepherosa Ziehau 	bool locked = FALSE;
4120ba0123e0SSepherosa Ziehau 	bool ready;
4121379ebbe7SSepherosa Ziehau 
4122379ebbe7SSepherosa Ziehau 	DEBUGFUNC("e1000_read_phy_reg_mphy");
4123379ebbe7SSepherosa Ziehau 
4124379ebbe7SSepherosa Ziehau 	/* Check if mPHY is ready to read/write operations */
4125379ebbe7SSepherosa Ziehau 	ready = e1000_is_mphy_ready(hw);
4126379ebbe7SSepherosa Ziehau 	if (!ready)
4127379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4128379ebbe7SSepherosa Ziehau 
4129379ebbe7SSepherosa Ziehau 	/* Check if mPHY access is disabled and enable it if so */
4130379ebbe7SSepherosa Ziehau 	mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
4131379ebbe7SSepherosa Ziehau 	if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
4132379ebbe7SSepherosa Ziehau 		locked = TRUE;
4133379ebbe7SSepherosa Ziehau 		ready = e1000_is_mphy_ready(hw);
4134379ebbe7SSepherosa Ziehau 		if (!ready)
4135379ebbe7SSepherosa Ziehau 			return -E1000_ERR_PHY;
4136379ebbe7SSepherosa Ziehau 		mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
4137379ebbe7SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4138379ebbe7SSepherosa Ziehau 	}
4139379ebbe7SSepherosa Ziehau 
4140379ebbe7SSepherosa Ziehau 	/* Set the address that we want to read */
4141379ebbe7SSepherosa Ziehau 	ready = e1000_is_mphy_ready(hw);
4142379ebbe7SSepherosa Ziehau 	if (!ready)
4143379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4144ba0123e0SSepherosa Ziehau 
4145ba0123e0SSepherosa Ziehau 	/* We mask address, because we want to use only current lane */
4146ba0123e0SSepherosa Ziehau 	mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK &
4147ba0123e0SSepherosa Ziehau 		~E1000_MPHY_ADDRESS_FNC_OVERRIDE) |
4148ba0123e0SSepherosa Ziehau 		(address & E1000_MPHY_ADDRESS_MASK);
4149379ebbe7SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4150379ebbe7SSepherosa Ziehau 
4151379ebbe7SSepherosa Ziehau 	/* Read data from the address */
4152379ebbe7SSepherosa Ziehau 	ready = e1000_is_mphy_ready(hw);
4153379ebbe7SSepherosa Ziehau 	if (!ready)
4154379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4155379ebbe7SSepherosa Ziehau 	*data = E1000_READ_REG(hw, E1000_MPHY_DATA);
4156379ebbe7SSepherosa Ziehau 
4157379ebbe7SSepherosa Ziehau 	/* Disable access to mPHY if it was originally disabled */
415865aebe9fSSepherosa Ziehau 	if (locked)
4159379ebbe7SSepherosa Ziehau 		ready = e1000_is_mphy_ready(hw);
4160379ebbe7SSepherosa Ziehau 	if (!ready)
4161379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4162379ebbe7SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
4163379ebbe7SSepherosa Ziehau 			E1000_MPHY_DIS_ACCESS);
4164379ebbe7SSepherosa Ziehau 
4165379ebbe7SSepherosa Ziehau 	return E1000_SUCCESS;
4166379ebbe7SSepherosa Ziehau }
4167379ebbe7SSepherosa Ziehau 
4168379ebbe7SSepherosa Ziehau /**
4169379ebbe7SSepherosa Ziehau  *  e1000_write_phy_reg_mphy - Write mPHY control register
4170379ebbe7SSepherosa Ziehau  *  @hw: pointer to the HW structure
4171379ebbe7SSepherosa Ziehau  *  @address: address to write to
4172379ebbe7SSepherosa Ziehau  *  @data: data to write to register at offset
4173ba0123e0SSepherosa Ziehau  *  @line_override: used when we want to use different line than default one
4174379ebbe7SSepherosa Ziehau  *
4175379ebbe7SSepherosa Ziehau  *  Writes data to mPHY control register.
4176379ebbe7SSepherosa Ziehau  **/
e1000_write_phy_reg_mphy(struct e1000_hw * hw,u32 address,u32 data,bool line_override)4177ba0123e0SSepherosa Ziehau s32 e1000_write_phy_reg_mphy(struct e1000_hw *hw, u32 address, u32 data,
4178ba0123e0SSepherosa Ziehau 			     bool line_override)
4179379ebbe7SSepherosa Ziehau {
4180379ebbe7SSepherosa Ziehau 	u32 mphy_ctrl = 0;
4181379ebbe7SSepherosa Ziehau 	bool locked = FALSE;
4182ba0123e0SSepherosa Ziehau 	bool ready;
4183379ebbe7SSepherosa Ziehau 
4184379ebbe7SSepherosa Ziehau 	DEBUGFUNC("e1000_write_phy_reg_mphy");
4185379ebbe7SSepherosa Ziehau 
4186379ebbe7SSepherosa Ziehau 	/* Check if mPHY is ready to read/write operations */
4187379ebbe7SSepherosa Ziehau 	ready = e1000_is_mphy_ready(hw);
4188379ebbe7SSepherosa Ziehau 	if (!ready)
4189379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4190379ebbe7SSepherosa Ziehau 
4191379ebbe7SSepherosa Ziehau 	/* Check if mPHY access is disabled and enable it if so */
4192379ebbe7SSepherosa Ziehau 	mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
4193379ebbe7SSepherosa Ziehau 	if (mphy_ctrl & E1000_MPHY_DIS_ACCESS) {
4194379ebbe7SSepherosa Ziehau 		locked = TRUE;
4195379ebbe7SSepherosa Ziehau 		ready = e1000_is_mphy_ready(hw);
4196379ebbe7SSepherosa Ziehau 		if (!ready)
4197379ebbe7SSepherosa Ziehau 			return -E1000_ERR_PHY;
4198379ebbe7SSepherosa Ziehau 		mphy_ctrl |= E1000_MPHY_ENA_ACCESS;
4199379ebbe7SSepherosa Ziehau 		E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4200379ebbe7SSepherosa Ziehau 	}
4201379ebbe7SSepherosa Ziehau 
4202379ebbe7SSepherosa Ziehau 	/* Set the address that we want to read */
4203379ebbe7SSepherosa Ziehau 	ready = e1000_is_mphy_ready(hw);
4204379ebbe7SSepherosa Ziehau 	if (!ready)
4205379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4206ba0123e0SSepherosa Ziehau 
4207ba0123e0SSepherosa Ziehau 	/* We mask address, because we want to use only current lane */
4208ba0123e0SSepherosa Ziehau 	if (line_override)
4209ba0123e0SSepherosa Ziehau 		mphy_ctrl |= E1000_MPHY_ADDRESS_FNC_OVERRIDE;
4210ba0123e0SSepherosa Ziehau 	else
4211ba0123e0SSepherosa Ziehau 		mphy_ctrl &= ~E1000_MPHY_ADDRESS_FNC_OVERRIDE;
4212ba0123e0SSepherosa Ziehau 	mphy_ctrl = (mphy_ctrl & ~E1000_MPHY_ADDRESS_MASK) |
4213ba0123e0SSepherosa Ziehau 		(address & E1000_MPHY_ADDRESS_MASK);
4214379ebbe7SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL, mphy_ctrl);
4215379ebbe7SSepherosa Ziehau 
4216379ebbe7SSepherosa Ziehau 	/* Read data from the address */
4217379ebbe7SSepherosa Ziehau 	ready = e1000_is_mphy_ready(hw);
4218379ebbe7SSepherosa Ziehau 	if (!ready)
4219379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4220379ebbe7SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MPHY_DATA, data);
4221379ebbe7SSepherosa Ziehau 
4222379ebbe7SSepherosa Ziehau 	/* Disable access to mPHY if it was originally disabled */
422365aebe9fSSepherosa Ziehau 	if (locked)
4224379ebbe7SSepherosa Ziehau 		ready = e1000_is_mphy_ready(hw);
4225379ebbe7SSepherosa Ziehau 	if (!ready)
4226379ebbe7SSepherosa Ziehau 		return -E1000_ERR_PHY;
4227379ebbe7SSepherosa Ziehau 	E1000_WRITE_REG(hw, E1000_MPHY_ADDR_CTRL,
4228379ebbe7SSepherosa Ziehau 			E1000_MPHY_DIS_ACCESS);
4229379ebbe7SSepherosa Ziehau 
4230379ebbe7SSepherosa Ziehau 	return E1000_SUCCESS;
4231379ebbe7SSepherosa Ziehau }
4232379ebbe7SSepherosa Ziehau 
4233379ebbe7SSepherosa Ziehau /**
4234379ebbe7SSepherosa Ziehau  *  e1000_is_mphy_ready - Check if mPHY control register is not busy
4235379ebbe7SSepherosa Ziehau  *  @hw: pointer to the HW structure
4236379ebbe7SSepherosa Ziehau  *
4237379ebbe7SSepherosa Ziehau  *  Returns mPHY control register status.
4238379ebbe7SSepherosa Ziehau  **/
e1000_is_mphy_ready(struct e1000_hw * hw)4239379ebbe7SSepherosa Ziehau bool e1000_is_mphy_ready(struct e1000_hw *hw)
4240379ebbe7SSepherosa Ziehau {
4241379ebbe7SSepherosa Ziehau 	u16 retry_count = 0;
4242379ebbe7SSepherosa Ziehau 	u32 mphy_ctrl = 0;
4243379ebbe7SSepherosa Ziehau 	bool ready = FALSE;
4244379ebbe7SSepherosa Ziehau 
4245379ebbe7SSepherosa Ziehau 	while (retry_count < 2) {
4246379ebbe7SSepherosa Ziehau 		mphy_ctrl = E1000_READ_REG(hw, E1000_MPHY_ADDR_CTRL);
4247379ebbe7SSepherosa Ziehau 		if (mphy_ctrl & E1000_MPHY_BUSY) {
4248379ebbe7SSepherosa Ziehau 			usec_delay(20);
4249379ebbe7SSepherosa Ziehau 			retry_count++;
4250379ebbe7SSepherosa Ziehau 			continue;
4251379ebbe7SSepherosa Ziehau 		}
4252379ebbe7SSepherosa Ziehau 		ready = TRUE;
4253379ebbe7SSepherosa Ziehau 		break;
4254379ebbe7SSepherosa Ziehau 	}
4255379ebbe7SSepherosa Ziehau 
4256379ebbe7SSepherosa Ziehau 	if (!ready)
4257379ebbe7SSepherosa Ziehau 		DEBUGOUT("ERROR READING mPHY control register, phy is busy.\n");
4258379ebbe7SSepherosa Ziehau 
4259379ebbe7SSepherosa Ziehau 	return ready;
4260379ebbe7SSepherosa Ziehau }
4261