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