14919Sxy150489 /* 24919Sxy150489 * This file is provided under a CDDLv1 license. When using or 34919Sxy150489 * redistributing this file, you may do so under this license. 44919Sxy150489 * In redistributing this file this license must be included 54919Sxy150489 * and no other modification of this header file is permitted. 64919Sxy150489 * 74919Sxy150489 * CDDL LICENSE SUMMARY 84919Sxy150489 * 98479SChenlu.Chen@Sun.COM * Copyright(c) 1999 - 2009 Intel Corporation. All rights reserved. 104919Sxy150489 * 114919Sxy150489 * The contents of this file are subject to the terms of Version 124919Sxy150489 * 1.0 of the Common Development and Distribution License (the "License"). 134919Sxy150489 * 144919Sxy150489 * You should have received a copy of the License with this software. 154919Sxy150489 * You can obtain a copy of the License at 164919Sxy150489 * http://www.opensolaris.org/os/licensing. 174919Sxy150489 * See the License for the specific language governing permissions 184919Sxy150489 * and limitations under the License. 194919Sxy150489 */ 204919Sxy150489 214919Sxy150489 /* 228479SChenlu.Chen@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 234919Sxy150489 * Use is subject to license terms of the CDDLv1. 244919Sxy150489 */ 254919Sxy150489 264919Sxy150489 /* 27*10680SMin.Xu@Sun.COM * IntelVersion: 1.143 v3-1-3_2009-8-20 284919Sxy150489 */ 294919Sxy150489 #include "e1000_api.h" 304919Sxy150489 314919Sxy150489 static u32 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg); 328479SChenlu.Chen@Sun.COM static s32 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, u32 offset, 338479SChenlu.Chen@Sun.COM u16 *data, bool read); 344919Sxy150489 35*10680SMin.Xu@Sun.COM static u32 e1000_get_phy_addr_for_hv_page(u32 page); 36*10680SMin.Xu@Sun.COM static s32 e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, 37*10680SMin.Xu@Sun.COM u16 *data, bool read); 38*10680SMin.Xu@Sun.COM 394919Sxy150489 /* Cable length tables */ 404919Sxy150489 static const u16 e1000_m88_cable_length_table[] = 414919Sxy150489 {0, 50, 80, 110, 140, 140, E1000_CABLE_LENGTH_UNDEFINED}; 424919Sxy150489 434919Sxy150489 #define M88E1000_CABLE_LENGTH_TABLE_SIZE \ 444919Sxy150489 (sizeof (e1000_m88_cable_length_table) / \ 454919Sxy150489 sizeof (e1000_m88_cable_length_table[0])) 464919Sxy150489 474919Sxy150489 static const u16 e1000_igp_2_cable_length_table[] = 484919Sxy150489 {0, 0, 0, 0, 0, 0, 0, 0, 3, 5, 8, 11, 13, 16, 18, 21, 494919Sxy150489 0, 0, 0, 3, 6, 10, 13, 16, 19, 23, 26, 29, 32, 35, 38, 41, 504919Sxy150489 6, 10, 14, 18, 22, 26, 30, 33, 37, 41, 44, 48, 51, 54, 58, 61, 514919Sxy150489 21, 26, 31, 35, 40, 44, 49, 53, 57, 61, 65, 68, 72, 75, 79, 82, 524919Sxy150489 40, 45, 51, 56, 61, 66, 70, 75, 79, 83, 87, 91, 94, 98, 101, 104, 534919Sxy150489 60, 66, 72, 77, 82, 87, 92, 96, 100, 104, 108, 111, 114, 117, 119, 121, 544919Sxy150489 83, 89, 95, 100, 105, 109, 113, 116, 119, 122, 124, 554919Sxy150489 104, 109, 114, 118, 121, 124}; 564919Sxy150489 574919Sxy150489 #define IGP02E1000_CABLE_LENGTH_TABLE_SIZE \ 584919Sxy150489 (sizeof (e1000_igp_2_cable_length_table) / \ 594919Sxy150489 sizeof (e1000_igp_2_cable_length_table[0])) 604919Sxy150489 614919Sxy150489 /* 626735Scc210113 * e1000_init_phy_ops_generic - Initialize PHY function pointers 636735Scc210113 * @hw: pointer to the HW structure 646735Scc210113 * 656735Scc210113 * Setups up the function pointers to no-op functions 666735Scc210113 */ 676735Scc210113 void 686735Scc210113 e1000_init_phy_ops_generic(struct e1000_hw *hw) 696735Scc210113 { 706735Scc210113 struct e1000_phy_info *phy = &hw->phy; 716735Scc210113 DEBUGFUNC("e1000_init_phy_ops_generic"); 726735Scc210113 736735Scc210113 /* Initialize function pointers */ 746735Scc210113 phy->ops.init_params = e1000_null_ops_generic; 756735Scc210113 phy->ops.acquire = e1000_null_ops_generic; 766735Scc210113 phy->ops.check_polarity = e1000_null_ops_generic; 776735Scc210113 phy->ops.check_reset_block = e1000_null_ops_generic; 786735Scc210113 phy->ops.commit = e1000_null_ops_generic; 796735Scc210113 phy->ops.force_speed_duplex = e1000_null_ops_generic; 806735Scc210113 phy->ops.get_cfg_done = e1000_null_ops_generic; 816735Scc210113 phy->ops.get_cable_length = e1000_null_ops_generic; 826735Scc210113 phy->ops.get_info = e1000_null_ops_generic; 836735Scc210113 phy->ops.read_reg = e1000_null_read_reg; 846735Scc210113 phy->ops.release = e1000_null_phy_generic; 856735Scc210113 phy->ops.reset = e1000_null_ops_generic; 866735Scc210113 phy->ops.set_d0_lplu_state = e1000_null_lplu_state; 876735Scc210113 phy->ops.set_d3_lplu_state = e1000_null_lplu_state; 886735Scc210113 phy->ops.write_reg = e1000_null_write_reg; 896735Scc210113 phy->ops.power_up = e1000_null_phy_generic; 906735Scc210113 phy->ops.power_down = e1000_null_phy_generic; 918479SChenlu.Chen@Sun.COM phy->ops.cfg_on_link_up = e1000_null_ops_generic; 926735Scc210113 } 936735Scc210113 946735Scc210113 /* 956735Scc210113 * e1000_null_read_reg - No-op function, return 0 966735Scc210113 * @hw: pointer to the HW structure 976735Scc210113 */ 986735Scc210113 s32 996735Scc210113 e1000_null_read_reg(struct e1000_hw *hw, u32 offset, u16 *data) 1006735Scc210113 { 1016735Scc210113 DEBUGFUNC("e1000_null_read_reg"); 1026735Scc210113 UNREFERENCED_3PARAMETER(hw, offset, data); 1036735Scc210113 return (E1000_SUCCESS); 1046735Scc210113 } 1056735Scc210113 1066735Scc210113 /* 1076735Scc210113 * e1000_null_phy_generic - No-op function, return void 1086735Scc210113 * @hw: pointer to the HW structure 1096735Scc210113 */ 1106735Scc210113 void 1116735Scc210113 e1000_null_phy_generic(struct e1000_hw *hw) 1126735Scc210113 { 1136735Scc210113 DEBUGFUNC("e1000_null_phy_generic"); 1146735Scc210113 UNREFERENCED_1PARAMETER(hw); 1156735Scc210113 } 1166735Scc210113 1176735Scc210113 /* 1186735Scc210113 * e1000_null_lplu_state - No-op function, return 0 1196735Scc210113 * @hw: pointer to the HW structure 1206735Scc210113 */ 1216735Scc210113 s32 1226735Scc210113 e1000_null_lplu_state(struct e1000_hw *hw, bool active) 1236735Scc210113 { 1246735Scc210113 DEBUGFUNC("e1000_null_lplu_state"); 1256735Scc210113 UNREFERENCED_2PARAMETER(hw, active); 1266735Scc210113 return (E1000_SUCCESS); 1276735Scc210113 } 1286735Scc210113 1296735Scc210113 /* 1306735Scc210113 * e1000_null_write_reg - No-op function, return 0 1316735Scc210113 * @hw: pointer to the HW structure 1326735Scc210113 */ 1336735Scc210113 s32 1346735Scc210113 e1000_null_write_reg(struct e1000_hw *hw, u32 offset, u16 data) 1356735Scc210113 { 1366735Scc210113 DEBUGFUNC("e1000_null_write_reg"); 1376735Scc210113 UNREFERENCED_3PARAMETER(hw, offset, data); 1386735Scc210113 return (E1000_SUCCESS); 1396735Scc210113 } 1406735Scc210113 1416735Scc210113 /* 1424919Sxy150489 * e1000_check_reset_block_generic - Check if PHY reset is blocked 1434919Sxy150489 * @hw: pointer to the HW structure 1444919Sxy150489 * 1454919Sxy150489 * Read the PHY management control register and check whether a PHY reset 1464919Sxy150489 * is blocked. If a reset is not blocked return E1000_SUCCESS, otherwise 1474919Sxy150489 * return E1000_BLK_PHY_RESET (12). 1484919Sxy150489 */ 1494919Sxy150489 s32 1504919Sxy150489 e1000_check_reset_block_generic(struct e1000_hw *hw) 1514919Sxy150489 { 1524919Sxy150489 u32 manc; 1534919Sxy150489 1544919Sxy150489 DEBUGFUNC("e1000_check_reset_block"); 1554919Sxy150489 1564919Sxy150489 manc = E1000_READ_REG(hw, E1000_MANC); 1574919Sxy150489 1584919Sxy150489 return ((manc & E1000_MANC_BLK_PHY_RST_ON_IDE) ? 1594919Sxy150489 E1000_BLK_PHY_RESET : E1000_SUCCESS); 1604919Sxy150489 } 1614919Sxy150489 1624919Sxy150489 /* 1634919Sxy150489 * e1000_get_phy_id - Retrieve the PHY ID and revision 1644919Sxy150489 * @hw: pointer to the HW structure 1654919Sxy150489 * 1664919Sxy150489 * Reads the PHY registers and stores the PHY ID and possibly the PHY 1674919Sxy150489 * revision in the hardware structure. 1684919Sxy150489 */ 1694919Sxy150489 s32 1704919Sxy150489 e1000_get_phy_id(struct e1000_hw *hw) 1714919Sxy150489 { 1724919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 1734919Sxy150489 s32 ret_val = E1000_SUCCESS; 1744919Sxy150489 u16 phy_id; 175*10680SMin.Xu@Sun.COM u16 retry_count = 0; 1764919Sxy150489 1774919Sxy150489 DEBUGFUNC("e1000_get_phy_id"); 1784919Sxy150489 1796735Scc210113 if (!(phy->ops.read_reg)) 1806735Scc210113 goto out; 1816735Scc210113 182*10680SMin.Xu@Sun.COM while (retry_count < 2) { 183*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, PHY_ID1, &phy_id); 184*10680SMin.Xu@Sun.COM if (ret_val) 185*10680SMin.Xu@Sun.COM goto out; 186*10680SMin.Xu@Sun.COM 187*10680SMin.Xu@Sun.COM phy->id = (u32)(phy_id << 16); 188*10680SMin.Xu@Sun.COM usec_delay(20); 189*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, PHY_ID2, &phy_id); 190*10680SMin.Xu@Sun.COM if (ret_val) 191*10680SMin.Xu@Sun.COM goto out; 192*10680SMin.Xu@Sun.COM 193*10680SMin.Xu@Sun.COM phy->id |= (u32)(phy_id & PHY_REVISION_MASK); 194*10680SMin.Xu@Sun.COM phy->revision = (u32)(phy_id & ~PHY_REVISION_MASK); 195*10680SMin.Xu@Sun.COM 196*10680SMin.Xu@Sun.COM if (phy->id != 0 && phy->id != PHY_REVISION_MASK) 197*10680SMin.Xu@Sun.COM goto out; 198*10680SMin.Xu@Sun.COM 199*10680SMin.Xu@Sun.COM /* 200*10680SMin.Xu@Sun.COM * If the PHY ID is still unknown, we may have an 82577 without 201*10680SMin.Xu@Sun.COM * link. We will try again after setting Slow MDIC mode. No 202*10680SMin.Xu@Sun.COM * harm in trying again in this case since the PHY ID is 203*10680SMin.Xu@Sun.COM * unknown at this point anyway 204*10680SMin.Xu@Sun.COM */ 205*10680SMin.Xu@Sun.COM ret_val = e1000_set_mdio_slow_mode_hv(hw, true); 206*10680SMin.Xu@Sun.COM if (ret_val) 207*10680SMin.Xu@Sun.COM goto out; 208*10680SMin.Xu@Sun.COM 209*10680SMin.Xu@Sun.COM retry_count++; 210*10680SMin.Xu@Sun.COM } 2114919Sxy150489 out: 212*10680SMin.Xu@Sun.COM /* Revert to MDIO fast mode, if applicable */ 213*10680SMin.Xu@Sun.COM if (retry_count) 214*10680SMin.Xu@Sun.COM ret_val = e1000_set_mdio_slow_mode_hv(hw, false); 215*10680SMin.Xu@Sun.COM 2164919Sxy150489 return (ret_val); 2174919Sxy150489 } 2184919Sxy150489 2194919Sxy150489 /* 2204919Sxy150489 * e1000_phy_reset_dsp_generic - Reset PHY DSP 2214919Sxy150489 * @hw: pointer to the HW structure 2224919Sxy150489 * 2234919Sxy150489 * Reset the digital signal processor. 2244919Sxy150489 */ 2254919Sxy150489 s32 2264919Sxy150489 e1000_phy_reset_dsp_generic(struct e1000_hw *hw) 2274919Sxy150489 { 2286735Scc210113 s32 ret_val = E1000_SUCCESS; 2294919Sxy150489 2304919Sxy150489 DEBUGFUNC("e1000_phy_reset_dsp_generic"); 2314919Sxy150489 2326735Scc210113 if (!(hw->phy.ops.write_reg)) 2336735Scc210113 goto out; 2346735Scc210113 2356735Scc210113 ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0xC1); 2364919Sxy150489 if (ret_val) 2374919Sxy150489 goto out; 2384919Sxy150489 2396735Scc210113 ret_val = hw->phy.ops.write_reg(hw, M88E1000_PHY_GEN_CONTROL, 0); 2404919Sxy150489 2414919Sxy150489 out: 2424919Sxy150489 return (ret_val); 2434919Sxy150489 } 2444919Sxy150489 2454919Sxy150489 /* 2464919Sxy150489 * e1000_read_phy_reg_mdic - Read MDI control register 2474919Sxy150489 * @hw: pointer to the HW structure 2484919Sxy150489 * @offset: register offset to be read 2494919Sxy150489 * @data: pointer to the read data 2504919Sxy150489 * 2516735Scc210113 * Reads the MDI control register in the PHY at offset and stores the 2524919Sxy150489 * information read to data. 2534919Sxy150489 */ 2546735Scc210113 s32 2554919Sxy150489 e1000_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data) 2564919Sxy150489 { 2574919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 2584919Sxy150489 u32 i, mdic = 0; 2594919Sxy150489 s32 ret_val = E1000_SUCCESS; 2604919Sxy150489 2614919Sxy150489 DEBUGFUNC("e1000_read_phy_reg_mdic"); 2624919Sxy150489 2634919Sxy150489 /* 2644919Sxy150489 * Set up Op-code, Phy Address, and register offset in the MDI Control 2654919Sxy150489 * register. The MAC will take care of interfacing with the PHY to 2664919Sxy150489 * retrieve the desired data. 2674919Sxy150489 */ 2684919Sxy150489 mdic = ((offset << E1000_MDIC_REG_SHIFT) | 2694919Sxy150489 (phy->addr << E1000_MDIC_PHY_SHIFT) | 2704919Sxy150489 (E1000_MDIC_OP_READ)); 2714919Sxy150489 2724919Sxy150489 E1000_WRITE_REG(hw, E1000_MDIC, mdic); 2734919Sxy150489 2746735Scc210113 /* 2756735Scc210113 * Poll the ready bit to see if the MDI read completed 2766735Scc210113 * Increasing the time out as testing showed failures with 2776735Scc210113 * the lower time out 2786735Scc210113 */ 2796735Scc210113 for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { 2804919Sxy150489 usec_delay(50); 2814919Sxy150489 mdic = E1000_READ_REG(hw, E1000_MDIC); 2824919Sxy150489 if (mdic & E1000_MDIC_READY) 2834919Sxy150489 break; 2844919Sxy150489 } 2854919Sxy150489 if (!(mdic & E1000_MDIC_READY)) { 2864919Sxy150489 DEBUGOUT("MDI Read did not complete\n"); 2874919Sxy150489 ret_val = -E1000_ERR_PHY; 2884919Sxy150489 goto out; 2894919Sxy150489 } 2904919Sxy150489 if (mdic & E1000_MDIC_ERROR) { 2914919Sxy150489 DEBUGOUT("MDI Error\n"); 2924919Sxy150489 ret_val = -E1000_ERR_PHY; 2934919Sxy150489 goto out; 2944919Sxy150489 } 2954919Sxy150489 *data = (u16)mdic; 2964919Sxy150489 2974919Sxy150489 out: 2984919Sxy150489 return (ret_val); 2994919Sxy150489 } 3004919Sxy150489 3014919Sxy150489 /* 3024919Sxy150489 * e1000_write_phy_reg_mdic - Write MDI control register 3034919Sxy150489 * @hw: pointer to the HW structure 3044919Sxy150489 * @offset: register offset to write to 3054919Sxy150489 * @data: data to write to register at offset 3064919Sxy150489 * 3074919Sxy150489 * Writes data to MDI control register in the PHY at offset. 3084919Sxy150489 */ 3096735Scc210113 s32 3104919Sxy150489 e1000_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data) 3114919Sxy150489 { 3124919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 3134919Sxy150489 u32 i, mdic = 0; 3144919Sxy150489 s32 ret_val = E1000_SUCCESS; 3154919Sxy150489 3164919Sxy150489 DEBUGFUNC("e1000_write_phy_reg_mdic"); 3174919Sxy150489 3184919Sxy150489 /* 3194919Sxy150489 * Set up Op-code, Phy Address, and register offset in the MDI Control 3204919Sxy150489 * register. The MAC will take care of interfacing with the PHY to 3214919Sxy150489 * retrieve the desired data. 3224919Sxy150489 */ 3234919Sxy150489 mdic = (((u32)data) | 3244919Sxy150489 (offset << E1000_MDIC_REG_SHIFT) | 3254919Sxy150489 (phy->addr << E1000_MDIC_PHY_SHIFT) | 3264919Sxy150489 (E1000_MDIC_OP_WRITE)); 3274919Sxy150489 3284919Sxy150489 E1000_WRITE_REG(hw, E1000_MDIC, mdic); 3294919Sxy150489 3306735Scc210113 /* 3316735Scc210113 * Poll the ready bit to see if the MDI read completed 3326735Scc210113 * Increasing the time out as testing showed failures with 3336735Scc210113 * the lower time out 3346735Scc210113 */ 3356735Scc210113 for (i = 0; i < (E1000_GEN_POLL_TIMEOUT * 3); i++) { 3366735Scc210113 usec_delay(50); 3374919Sxy150489 mdic = E1000_READ_REG(hw, E1000_MDIC); 3384919Sxy150489 if (mdic & E1000_MDIC_READY) 3394919Sxy150489 break; 3404919Sxy150489 } 3414919Sxy150489 if (!(mdic & E1000_MDIC_READY)) { 3424919Sxy150489 DEBUGOUT("MDI Write did not complete\n"); 3434919Sxy150489 ret_val = -E1000_ERR_PHY; 3444919Sxy150489 goto out; 3454919Sxy150489 } 3466735Scc210113 if (mdic & E1000_MDIC_ERROR) { 3476735Scc210113 DEBUGOUT("MDI Error\n"); 3486735Scc210113 ret_val = -E1000_ERR_PHY; 3496735Scc210113 goto out; 3506735Scc210113 } 3514919Sxy150489 3524919Sxy150489 out: 3534919Sxy150489 return (ret_val); 3544919Sxy150489 } 3554919Sxy150489 3564919Sxy150489 /* 3574919Sxy150489 * e1000_read_phy_reg_m88 - Read m88 PHY register 3584919Sxy150489 * @hw: pointer to the HW structure 3594919Sxy150489 * @offset: register offset to be read 3604919Sxy150489 * @data: pointer to the read data 3614919Sxy150489 * 3624919Sxy150489 * Acquires semaphore, if necessary, then reads the PHY register at offset 3634919Sxy150489 * and storing the retrieved information in data. Release any acquired 3644919Sxy150489 * semaphores before exiting. 3654919Sxy150489 */ 3664919Sxy150489 s32 3674919Sxy150489 e1000_read_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 *data) 3684919Sxy150489 { 3696735Scc210113 s32 ret_val = E1000_SUCCESS; 3704919Sxy150489 3714919Sxy150489 DEBUGFUNC("e1000_read_phy_reg_m88"); 3724919Sxy150489 3736735Scc210113 if (!(hw->phy.ops.acquire)) 3746735Scc210113 goto out; 3756735Scc210113 3766735Scc210113 ret_val = hw->phy.ops.acquire(hw); 3774919Sxy150489 if (ret_val) 3784919Sxy150489 goto out; 3794919Sxy150489 3804919Sxy150489 ret_val = e1000_read_phy_reg_mdic(hw, 3814919Sxy150489 MAX_PHY_REG_ADDRESS & offset, 3824919Sxy150489 data); 3834919Sxy150489 3846735Scc210113 hw->phy.ops.release(hw); 3854919Sxy150489 3864919Sxy150489 out: 3874919Sxy150489 return (ret_val); 3884919Sxy150489 } 3894919Sxy150489 3904919Sxy150489 /* 3914919Sxy150489 * e1000_write_phy_reg_m88 - Write m88 PHY register 3924919Sxy150489 * @hw: pointer to the HW structure 3934919Sxy150489 * @offset: register offset to write to 3944919Sxy150489 * @data: data to write at register offset 3954919Sxy150489 * 3964919Sxy150489 * Acquires semaphore, if necessary, then writes the data to PHY register 3974919Sxy150489 * at the offset. Release any acquired semaphores before exiting. 3984919Sxy150489 */ 3994919Sxy150489 s32 4004919Sxy150489 e1000_write_phy_reg_m88(struct e1000_hw *hw, u32 offset, u16 data) 4014919Sxy150489 { 4026735Scc210113 s32 ret_val = E1000_SUCCESS; 4034919Sxy150489 4044919Sxy150489 DEBUGFUNC("e1000_write_phy_reg_m88"); 4054919Sxy150489 4066735Scc210113 if (!(hw->phy.ops.acquire)) 4076735Scc210113 goto out; 4086735Scc210113 4096735Scc210113 ret_val = hw->phy.ops.acquire(hw); 4104919Sxy150489 if (ret_val) 4114919Sxy150489 goto out; 4124919Sxy150489 4134919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, 4144919Sxy150489 MAX_PHY_REG_ADDRESS & offset, 4154919Sxy150489 data); 4164919Sxy150489 4176735Scc210113 hw->phy.ops.release(hw); 4184919Sxy150489 4194919Sxy150489 out: 4204919Sxy150489 return (ret_val); 4214919Sxy150489 } 4224919Sxy150489 4234919Sxy150489 /* 4244919Sxy150489 * e1000_read_phy_reg_igp - Read igp PHY register 4254919Sxy150489 * @hw: pointer to the HW structure 4264919Sxy150489 * @offset: register offset to be read 4274919Sxy150489 * @data: pointer to the read data 4284919Sxy150489 * 4294919Sxy150489 * Acquires semaphore, if necessary, then reads the PHY register at offset 4304919Sxy150489 * and storing the retrieved information in data. Release any acquired 4314919Sxy150489 * semaphores before exiting. 4324919Sxy150489 */ 4334919Sxy150489 s32 4344919Sxy150489 e1000_read_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 *data) 4354919Sxy150489 { 4366735Scc210113 s32 ret_val = E1000_SUCCESS; 4374919Sxy150489 4384919Sxy150489 DEBUGFUNC("e1000_read_phy_reg_igp"); 4394919Sxy150489 4406735Scc210113 if (!(hw->phy.ops.acquire)) 4416735Scc210113 goto out; 4426735Scc210113 4436735Scc210113 ret_val = hw->phy.ops.acquire(hw); 4444919Sxy150489 if (ret_val) 4454919Sxy150489 goto out; 4464919Sxy150489 4474919Sxy150489 if (offset > MAX_PHY_MULTI_PAGE_REG) { 4484919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, 4494919Sxy150489 IGP01E1000_PHY_PAGE_SELECT, 4504919Sxy150489 (u16)offset); 4514919Sxy150489 if (ret_val) { 4526735Scc210113 hw->phy.ops.release(hw); 4534919Sxy150489 goto out; 4544919Sxy150489 } 4554919Sxy150489 } 4564919Sxy150489 ret_val = e1000_read_phy_reg_mdic(hw, 4574919Sxy150489 MAX_PHY_REG_ADDRESS & offset, 4584919Sxy150489 data); 4594919Sxy150489 4606735Scc210113 hw->phy.ops.release(hw); 4614919Sxy150489 4624919Sxy150489 out: 4634919Sxy150489 return (ret_val); 4644919Sxy150489 } 4654919Sxy150489 4664919Sxy150489 /* 4674919Sxy150489 * e1000_write_phy_reg_igp - Write igp PHY register 4684919Sxy150489 * @hw: pointer to the HW structure 4694919Sxy150489 * @offset: register offset to write to 4704919Sxy150489 * @data: data to write at register offset 4714919Sxy150489 * 4724919Sxy150489 * Acquires semaphore, if necessary, then writes the data to PHY register 4734919Sxy150489 * at the offset. Release any acquired semaphores before exiting. 4744919Sxy150489 */ 4754919Sxy150489 s32 4764919Sxy150489 e1000_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data) 4774919Sxy150489 { 4786735Scc210113 s32 ret_val = E1000_SUCCESS; 4794919Sxy150489 4804919Sxy150489 DEBUGFUNC("e1000_write_phy_reg_igp"); 4814919Sxy150489 4826735Scc210113 if (!(hw->phy.ops.acquire)) 4836735Scc210113 goto out; 4846735Scc210113 4856735Scc210113 ret_val = hw->phy.ops.acquire(hw); 4864919Sxy150489 if (ret_val) 4874919Sxy150489 goto out; 4884919Sxy150489 4894919Sxy150489 if (offset > MAX_PHY_MULTI_PAGE_REG) { 4904919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, 4914919Sxy150489 IGP01E1000_PHY_PAGE_SELECT, 4924919Sxy150489 (u16)offset); 4934919Sxy150489 if (ret_val) { 4946735Scc210113 hw->phy.ops.release(hw); 4954919Sxy150489 goto out; 4964919Sxy150489 } 4974919Sxy150489 } 4984919Sxy150489 4994919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, 5004919Sxy150489 MAX_PHY_REG_ADDRESS & offset, 5014919Sxy150489 data); 5024919Sxy150489 5036735Scc210113 hw->phy.ops.release(hw); 5044919Sxy150489 5054919Sxy150489 out: 5064919Sxy150489 return (ret_val); 5074919Sxy150489 } 5084919Sxy150489 5094919Sxy150489 /* 5104919Sxy150489 * e1000_read_kmrn_reg_generic - Read kumeran register 5114919Sxy150489 * @hw: pointer to the HW structure 5124919Sxy150489 * @offset: register offset to be read 5134919Sxy150489 * @data: pointer to the read data 5144919Sxy150489 * 5154919Sxy150489 * Acquires semaphore, if necessary. Then reads the PHY register at offset 5164919Sxy150489 * using the kumeran interface. The information retrieved is stored in data. 5174919Sxy150489 * Release any acquired semaphores before exiting. 5184919Sxy150489 */ 5194919Sxy150489 s32 5204919Sxy150489 e1000_read_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 *data) 5214919Sxy150489 { 5224919Sxy150489 u32 kmrnctrlsta; 5236735Scc210113 s32 ret_val = E1000_SUCCESS; 5244919Sxy150489 5254919Sxy150489 DEBUGFUNC("e1000_read_kmrn_reg_generic"); 5264919Sxy150489 5276735Scc210113 if (!(hw->phy.ops.acquire)) 5286735Scc210113 goto out; 5296735Scc210113 5306735Scc210113 ret_val = hw->phy.ops.acquire(hw); 5314919Sxy150489 if (ret_val) 5324919Sxy150489 goto out; 5334919Sxy150489 5344919Sxy150489 kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & 5354919Sxy150489 E1000_KMRNCTRLSTA_OFFSET) | E1000_KMRNCTRLSTA_REN; 5364919Sxy150489 E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); 5374919Sxy150489 5384919Sxy150489 usec_delay(2); 5394919Sxy150489 5404919Sxy150489 kmrnctrlsta = E1000_READ_REG(hw, E1000_KMRNCTRLSTA); 5414919Sxy150489 *data = (u16)kmrnctrlsta; 5424919Sxy150489 5436735Scc210113 hw->phy.ops.release(hw); 5444919Sxy150489 5454919Sxy150489 out: 5464919Sxy150489 return (ret_val); 5474919Sxy150489 } 5484919Sxy150489 5494919Sxy150489 /* 5504919Sxy150489 * e1000_write_kmrn_reg_generic - Write kumeran register 5514919Sxy150489 * @hw: pointer to the HW structure 5524919Sxy150489 * @offset: register offset to write to 5534919Sxy150489 * @data: data to write at register offset 5544919Sxy150489 * 5554919Sxy150489 * Acquires semaphore, if necessary. Then write the data to PHY register 5564919Sxy150489 * at the offset using the kumeran interface. Release any acquired semaphores 5574919Sxy150489 * before exiting. 5584919Sxy150489 */ 5594919Sxy150489 s32 5604919Sxy150489 e1000_write_kmrn_reg_generic(struct e1000_hw *hw, u32 offset, u16 data) 5614919Sxy150489 { 5624919Sxy150489 u32 kmrnctrlsta; 5636735Scc210113 s32 ret_val = E1000_SUCCESS; 5644919Sxy150489 5654919Sxy150489 DEBUGFUNC("e1000_write_kmrn_reg_generic"); 5664919Sxy150489 5676735Scc210113 if (!(hw->phy.ops.acquire)) 5686735Scc210113 goto out; 5696735Scc210113 5706735Scc210113 ret_val = hw->phy.ops.acquire(hw); 5714919Sxy150489 if (ret_val) 5724919Sxy150489 goto out; 5734919Sxy150489 5744919Sxy150489 kmrnctrlsta = ((offset << E1000_KMRNCTRLSTA_OFFSET_SHIFT) & 5754919Sxy150489 E1000_KMRNCTRLSTA_OFFSET) | data; 5764919Sxy150489 E1000_WRITE_REG(hw, E1000_KMRNCTRLSTA, kmrnctrlsta); 5774919Sxy150489 5784919Sxy150489 usec_delay(2); 5796735Scc210113 hw->phy.ops.release(hw); 5804919Sxy150489 5814919Sxy150489 out: 5824919Sxy150489 return (ret_val); 5834919Sxy150489 } 5844919Sxy150489 5854919Sxy150489 /* 586*10680SMin.Xu@Sun.COM * e1000_copper_link_setup_82577 - Setup 82577 PHY for copper link 587*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 588*10680SMin.Xu@Sun.COM * 589*10680SMin.Xu@Sun.COM * Sets up Carrier-sense on Transmit and downshift values. 590*10680SMin.Xu@Sun.COM */ 591*10680SMin.Xu@Sun.COM s32 592*10680SMin.Xu@Sun.COM e1000_copper_link_setup_82577(struct e1000_hw *hw) 593*10680SMin.Xu@Sun.COM { 594*10680SMin.Xu@Sun.COM struct e1000_phy_info *phy = &hw->phy; 595*10680SMin.Xu@Sun.COM s32 ret_val; 596*10680SMin.Xu@Sun.COM u16 phy_data; 597*10680SMin.Xu@Sun.COM 598*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_copper_link_setup_82577"); 599*10680SMin.Xu@Sun.COM 600*10680SMin.Xu@Sun.COM if (phy->reset_disable) { 601*10680SMin.Xu@Sun.COM ret_val = E1000_SUCCESS; 602*10680SMin.Xu@Sun.COM goto out; 603*10680SMin.Xu@Sun.COM } 604*10680SMin.Xu@Sun.COM 605*10680SMin.Xu@Sun.COM /* Enable CRS on TX. This must be set for half-duplex operation. */ 606*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, I82577_CFG_REG, &phy_data); 607*10680SMin.Xu@Sun.COM if (ret_val) 608*10680SMin.Xu@Sun.COM goto out; 609*10680SMin.Xu@Sun.COM 610*10680SMin.Xu@Sun.COM phy_data |= I82577_CFG_ASSERT_CRS_ON_TX; 611*10680SMin.Xu@Sun.COM 612*10680SMin.Xu@Sun.COM /* Enable downshift */ 613*10680SMin.Xu@Sun.COM phy_data |= I82577_CFG_ENABLE_DOWNSHIFT; 614*10680SMin.Xu@Sun.COM 615*10680SMin.Xu@Sun.COM ret_val = phy->ops.write_reg(hw, I82577_CFG_REG, phy_data); 616*10680SMin.Xu@Sun.COM if (ret_val) 617*10680SMin.Xu@Sun.COM goto out; 618*10680SMin.Xu@Sun.COM 619*10680SMin.Xu@Sun.COM /* Set number of link attempts before downshift */ 620*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, I82577_CTRL_REG, &phy_data); 621*10680SMin.Xu@Sun.COM if (ret_val) 622*10680SMin.Xu@Sun.COM goto out; 623*10680SMin.Xu@Sun.COM phy_data &= ~I82577_CTRL_DOWNSHIFT_MASK; 624*10680SMin.Xu@Sun.COM ret_val = phy->ops.write_reg(hw, I82577_CTRL_REG, phy_data); 625*10680SMin.Xu@Sun.COM 626*10680SMin.Xu@Sun.COM out: 627*10680SMin.Xu@Sun.COM return (ret_val); 628*10680SMin.Xu@Sun.COM } 629*10680SMin.Xu@Sun.COM 630*10680SMin.Xu@Sun.COM /* 6314919Sxy150489 * e1000_copper_link_setup_m88 - Setup m88 PHY's for copper link 6324919Sxy150489 * @hw: pointer to the HW structure 6334919Sxy150489 * 6344919Sxy150489 * Sets up MDI/MDI-X and polarity for m88 PHY's. If necessary, transmit clock 6354919Sxy150489 * and downshift values are set also. 6364919Sxy150489 */ 6374919Sxy150489 s32 6384919Sxy150489 e1000_copper_link_setup_m88(struct e1000_hw *hw) 6394919Sxy150489 { 6404919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 6414919Sxy150489 s32 ret_val; 6424919Sxy150489 u16 phy_data; 6434919Sxy150489 6444919Sxy150489 DEBUGFUNC("e1000_copper_link_setup_m88"); 6454919Sxy150489 6464919Sxy150489 if (phy->reset_disable) { 6474919Sxy150489 ret_val = E1000_SUCCESS; 6484919Sxy150489 goto out; 6494919Sxy150489 } 6504919Sxy150489 6514919Sxy150489 /* Enable CRS on TX. This must be set for half-duplex operation. */ 6526735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 6534919Sxy150489 if (ret_val) 6544919Sxy150489 goto out; 6554919Sxy150489 656*10680SMin.Xu@Sun.COM /* For BM PHY this bit is downshift enable */ 657*10680SMin.Xu@Sun.COM if (phy->type != e1000_phy_bm) 6584919Sxy150489 phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; 6594919Sxy150489 6604919Sxy150489 /* 6614919Sxy150489 * Options: 6624919Sxy150489 * MDI/MDI-X = 0 (default) 6634919Sxy150489 * 0 - Auto for all speeds 6644919Sxy150489 * 1 - MDI mode 6654919Sxy150489 * 2 - MDI-X mode 6664919Sxy150489 * 3 - Auto for 1000Base-T only (MDI-X for 10/100Base-T modes) 6674919Sxy150489 */ 6684919Sxy150489 phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; 6694919Sxy150489 6704919Sxy150489 switch (phy->mdix) { 6714919Sxy150489 case 1: 6724919Sxy150489 phy_data |= M88E1000_PSCR_MDI_MANUAL_MODE; 6734919Sxy150489 break; 6744919Sxy150489 case 2: 6754919Sxy150489 phy_data |= M88E1000_PSCR_MDIX_MANUAL_MODE; 6764919Sxy150489 break; 6774919Sxy150489 case 3: 6784919Sxy150489 phy_data |= M88E1000_PSCR_AUTO_X_1000T; 6794919Sxy150489 break; 6804919Sxy150489 case 0: 6814919Sxy150489 default: 6824919Sxy150489 phy_data |= M88E1000_PSCR_AUTO_X_MODE; 6834919Sxy150489 break; 6844919Sxy150489 } 6854919Sxy150489 6864919Sxy150489 /* 6874919Sxy150489 * Options: 6884919Sxy150489 * disable_polarity_correction = 0 (default) 6894919Sxy150489 * Automatic Correction for Reversed Cable Polarity 6904919Sxy150489 * 0 - Disabled 6914919Sxy150489 * 1 - Enabled 6924919Sxy150489 */ 6934919Sxy150489 phy_data &= ~M88E1000_PSCR_POLARITY_REVERSAL; 6944919Sxy150489 if (phy->disable_polarity_correction == 1) 6954919Sxy150489 phy_data |= M88E1000_PSCR_POLARITY_REVERSAL; 6964919Sxy150489 6976735Scc210113 /* Enable downshift on BM (disabled by default) */ 6986735Scc210113 if (phy->type == e1000_phy_bm) 6996735Scc210113 phy_data |= BME1000_PSCR_ENABLE_DOWNSHIFT; 7006735Scc210113 7016735Scc210113 ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); 7024919Sxy150489 if (ret_val) 7034919Sxy150489 goto out; 7044919Sxy150489 7056735Scc210113 if ((phy->type == e1000_phy_m88) && 7067607STed.You@Sun.COM (phy->revision < E1000_REVISION_4) && 7077607STed.You@Sun.COM (phy->id != BME1000_E_PHY_ID_R2)) { 7084919Sxy150489 /* 7094919Sxy150489 * Force TX_CLK in the Extended PHY Specific Control Register 7104919Sxy150489 * to 25MHz clock. 7114919Sxy150489 */ 7126735Scc210113 ret_val = phy->ops.read_reg(hw, 7134919Sxy150489 M88E1000_EXT_PHY_SPEC_CTRL, 7144919Sxy150489 &phy_data); 7154919Sxy150489 if (ret_val) 7164919Sxy150489 goto out; 7174919Sxy150489 7184919Sxy150489 phy_data |= M88E1000_EPSCR_TX_CLK_25; 7194919Sxy150489 7204919Sxy150489 if ((phy->revision == E1000_REVISION_2) && 7214919Sxy150489 (phy->id == M88E1111_I_PHY_ID)) { 7224919Sxy150489 /* 82573L PHY - set the downshift counter to 5x. */ 7234919Sxy150489 phy_data &= ~M88EC018_EPSCR_DOWNSHIFT_COUNTER_MASK; 7244919Sxy150489 phy_data |= M88EC018_EPSCR_DOWNSHIFT_COUNTER_5X; 7254919Sxy150489 } else { 7264919Sxy150489 /* Configure Master and Slave downshift values */ 7274919Sxy150489 phy_data &= ~(M88E1000_EPSCR_MASTER_DOWNSHIFT_MASK | 7284919Sxy150489 M88E1000_EPSCR_SLAVE_DOWNSHIFT_MASK); 7294919Sxy150489 phy_data |= (M88E1000_EPSCR_MASTER_DOWNSHIFT_1X | 7304919Sxy150489 M88E1000_EPSCR_SLAVE_DOWNSHIFT_1X); 7314919Sxy150489 } 7326735Scc210113 ret_val = phy->ops.write_reg(hw, 7334919Sxy150489 M88E1000_EXT_PHY_SPEC_CTRL, 7344919Sxy150489 phy_data); 7354919Sxy150489 if (ret_val) 7364919Sxy150489 goto out; 7374919Sxy150489 } 7384919Sxy150489 7397607STed.You@Sun.COM if ((phy->type == e1000_phy_bm) && (phy->id == BME1000_E_PHY_ID_R2)) { 7407607STed.You@Sun.COM /* Set PHY page 0, register 29 to 0x0003 */ 7417607STed.You@Sun.COM ret_val = phy->ops.write_reg(hw, 29, 0x0003); 7427607STed.You@Sun.COM if (ret_val) 7437607STed.You@Sun.COM goto out; 7447607STed.You@Sun.COM 7457607STed.You@Sun.COM /* Set PHY page 0, register 30 to 0x0000 */ 7467607STed.You@Sun.COM ret_val = phy->ops.write_reg(hw, 30, 0x0000); 7477607STed.You@Sun.COM if (ret_val) 7487607STed.You@Sun.COM goto out; 7497607STed.You@Sun.COM } 7507607STed.You@Sun.COM 7514919Sxy150489 /* Commit the changes. */ 7526735Scc210113 ret_val = phy->ops.commit(hw); 7534919Sxy150489 if (ret_val) { 7544919Sxy150489 DEBUGOUT("Error committing the PHY changes\n"); 7554919Sxy150489 goto out; 7564919Sxy150489 } 7574919Sxy150489 758*10680SMin.Xu@Sun.COM if (phy->type == e1000_phy_82578) { 759*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, 760*10680SMin.Xu@Sun.COM &phy_data); 761*10680SMin.Xu@Sun.COM if (ret_val) 762*10680SMin.Xu@Sun.COM goto out; 763*10680SMin.Xu@Sun.COM 764*10680SMin.Xu@Sun.COM /* 82578 PHY - set the downshift count to 1x. */ 765*10680SMin.Xu@Sun.COM phy_data |= I82578_EPSCR_DOWNSHIFT_ENABLE; 766*10680SMin.Xu@Sun.COM phy_data &= ~I82578_EPSCR_DOWNSHIFT_COUNTER_MASK; 767*10680SMin.Xu@Sun.COM ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, 768*10680SMin.Xu@Sun.COM phy_data); 769*10680SMin.Xu@Sun.COM if (ret_val) 770*10680SMin.Xu@Sun.COM goto out; 771*10680SMin.Xu@Sun.COM } 772*10680SMin.Xu@Sun.COM 7734919Sxy150489 out: 7744919Sxy150489 return (ret_val); 7754919Sxy150489 } 7764919Sxy150489 7774919Sxy150489 /* 7784919Sxy150489 * e1000_copper_link_setup_igp - Setup igp PHY's for copper link 7794919Sxy150489 * @hw: pointer to the HW structure 7804919Sxy150489 * 7814919Sxy150489 * Sets up LPLU, MDI/MDI-X, polarity, Smartspeed and Master/Slave config for 7824919Sxy150489 * igp PHY's. 7834919Sxy150489 */ 7844919Sxy150489 s32 7854919Sxy150489 e1000_copper_link_setup_igp(struct e1000_hw *hw) 7864919Sxy150489 { 7874919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 7884919Sxy150489 s32 ret_val; 7894919Sxy150489 u16 data; 7904919Sxy150489 7914919Sxy150489 DEBUGFUNC("e1000_copper_link_setup_igp"); 7924919Sxy150489 7934919Sxy150489 if (phy->reset_disable) { 7944919Sxy150489 ret_val = E1000_SUCCESS; 7954919Sxy150489 goto out; 7964919Sxy150489 } 7974919Sxy150489 7987607STed.You@Sun.COM ret_val = hw->phy.ops.reset(hw); 7994919Sxy150489 if (ret_val) { 8004919Sxy150489 DEBUGOUT("Error resetting the PHY.\n"); 8014919Sxy150489 goto out; 8024919Sxy150489 } 8034919Sxy150489 8046735Scc210113 /* 8056735Scc210113 * Wait 100ms for MAC to configure PHY from NVM settings, to avoid 8066735Scc210113 * timeout issues when LFS is enabled. 8076735Scc210113 */ 8086735Scc210113 msec_delay(100); 8094919Sxy150489 8104919Sxy150489 /* 8114919Sxy150489 * The NVM settings will configure LPLU in D3 for non-IGP1 PHYs. 8124919Sxy150489 */ 8134919Sxy150489 if (phy->type == e1000_phy_igp) { 8144919Sxy150489 /* disable lplu d3 during driver init */ 8157607STed.You@Sun.COM ret_val = hw->phy.ops.set_d3_lplu_state(hw, false); 8164919Sxy150489 if (ret_val) { 8174919Sxy150489 DEBUGOUT("Error Disabling LPLU D3\n"); 8184919Sxy150489 goto out; 8194919Sxy150489 } 8204919Sxy150489 } 8214919Sxy150489 8224919Sxy150489 /* disable lplu d0 during driver init */ 8237607STed.You@Sun.COM if (hw->phy.ops.set_d0_lplu_state) { 8247607STed.You@Sun.COM ret_val = hw->phy.ops.set_d0_lplu_state(hw, false); 8257607STed.You@Sun.COM if (ret_val) { 8267607STed.You@Sun.COM DEBUGOUT("Error Disabling LPLU D0\n"); 8277607STed.You@Sun.COM goto out; 8287607STed.You@Sun.COM } 8294919Sxy150489 } 8304919Sxy150489 /* Configure mdi-mdix settings */ 8316735Scc210113 ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &data); 8324919Sxy150489 if (ret_val) 8334919Sxy150489 goto out; 8344919Sxy150489 8354919Sxy150489 data &= ~IGP01E1000_PSCR_AUTO_MDIX; 8364919Sxy150489 8374919Sxy150489 switch (phy->mdix) { 8384919Sxy150489 case 1: 8394919Sxy150489 data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; 8404919Sxy150489 break; 8414919Sxy150489 case 2: 8424919Sxy150489 data |= IGP01E1000_PSCR_FORCE_MDI_MDIX; 8434919Sxy150489 break; 8444919Sxy150489 case 0: 8454919Sxy150489 default: 8464919Sxy150489 data |= IGP01E1000_PSCR_AUTO_MDIX; 8474919Sxy150489 break; 8484919Sxy150489 } 8496735Scc210113 ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, data); 8504919Sxy150489 if (ret_val) 8514919Sxy150489 goto out; 8524919Sxy150489 8534919Sxy150489 /* set auto-master slave resolution settings */ 8544919Sxy150489 if (hw->mac.autoneg) { 8554919Sxy150489 /* 8564919Sxy150489 * when autonegotiation advertisement is only 1000Mbps then we 8574919Sxy150489 * should disable SmartSpeed and enable Auto MasterSlave 8584919Sxy150489 * resolution as hardware default. 8594919Sxy150489 */ 8604919Sxy150489 if (phy->autoneg_advertised == ADVERTISE_1000_FULL) { 8614919Sxy150489 /* Disable SmartSpeed */ 8626735Scc210113 ret_val = phy->ops.read_reg(hw, 8634919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 8644919Sxy150489 &data); 8654919Sxy150489 if (ret_val) 8664919Sxy150489 goto out; 8674919Sxy150489 8684919Sxy150489 data &= ~IGP01E1000_PSCFR_SMART_SPEED; 8696735Scc210113 ret_val = phy->ops.write_reg(hw, 8704919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 8714919Sxy150489 data); 8724919Sxy150489 if (ret_val) 8734919Sxy150489 goto out; 8744919Sxy150489 8754919Sxy150489 /* Set auto Master/Slave resolution process */ 8766735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); 8774919Sxy150489 if (ret_val) 8784919Sxy150489 goto out; 8794919Sxy150489 8804919Sxy150489 data &= ~CR_1000T_MS_ENABLE; 8816735Scc210113 ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); 8824919Sxy150489 if (ret_val) 8834919Sxy150489 goto out; 8844919Sxy150489 } 8854919Sxy150489 8866735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL, &data); 8874919Sxy150489 if (ret_val) 8884919Sxy150489 goto out; 8894919Sxy150489 8904919Sxy150489 /* load defaults for future use */ 8914919Sxy150489 phy->original_ms_type = (data & CR_1000T_MS_ENABLE) ? 8924919Sxy150489 ((data & CR_1000T_MS_VALUE) ? 8934919Sxy150489 e1000_ms_force_master : 8944919Sxy150489 e1000_ms_force_slave) : 8954919Sxy150489 e1000_ms_auto; 8964919Sxy150489 8974919Sxy150489 switch (phy->ms_type) { 8984919Sxy150489 case e1000_ms_force_master: 8994919Sxy150489 data |= (CR_1000T_MS_ENABLE | CR_1000T_MS_VALUE); 9004919Sxy150489 break; 9014919Sxy150489 case e1000_ms_force_slave: 9024919Sxy150489 data |= CR_1000T_MS_ENABLE; 9034919Sxy150489 data &= ~(CR_1000T_MS_VALUE); 9044919Sxy150489 break; 9054919Sxy150489 case e1000_ms_auto: 9064919Sxy150489 data &= ~CR_1000T_MS_ENABLE; 9074919Sxy150489 default: 9084919Sxy150489 break; 9094919Sxy150489 } 9106735Scc210113 ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL, data); 9114919Sxy150489 if (ret_val) 9124919Sxy150489 goto out; 9134919Sxy150489 } 9144919Sxy150489 9154919Sxy150489 out: 9164919Sxy150489 return (ret_val); 9174919Sxy150489 } 9184919Sxy150489 9194919Sxy150489 /* 9204919Sxy150489 * e1000_copper_link_autoneg - Setup/Enable autoneg for copper link 9214919Sxy150489 * @hw: pointer to the HW structure 9224919Sxy150489 * 9234919Sxy150489 * Performs initial bounds checking on autoneg advertisement parameter, then 9244919Sxy150489 * configure to advertise the full capability. Setup the PHY to autoneg 9254919Sxy150489 * and restart the negotiation process between the link partner. If 9266735Scc210113 * autoneg_wait_to_complete, then wait for autoneg to complete before exiting. 9274919Sxy150489 */ 9284919Sxy150489 s32 9294919Sxy150489 e1000_copper_link_autoneg(struct e1000_hw *hw) 9304919Sxy150489 { 9314919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 9324919Sxy150489 s32 ret_val; 9334919Sxy150489 u16 phy_ctrl; 9344919Sxy150489 9354919Sxy150489 DEBUGFUNC("e1000_copper_link_autoneg"); 9364919Sxy150489 9374919Sxy150489 /* 9384919Sxy150489 * Perform some bounds checking on the autoneg advertisement 9394919Sxy150489 * parameter. 9404919Sxy150489 */ 9414919Sxy150489 phy->autoneg_advertised &= phy->autoneg_mask; 9424919Sxy150489 9434919Sxy150489 /* 9444919Sxy150489 * If autoneg_advertised is zero, we assume it was not defaulted by 9454919Sxy150489 * the calling code so we set to advertise full capability. 9464919Sxy150489 */ 9474919Sxy150489 if (phy->autoneg_advertised == 0) 9484919Sxy150489 phy->autoneg_advertised = phy->autoneg_mask; 9494919Sxy150489 9504919Sxy150489 DEBUGOUT("Reconfiguring auto-neg advertisement params\n"); 9514919Sxy150489 ret_val = e1000_phy_setup_autoneg(hw); 9524919Sxy150489 if (ret_val) { 9534919Sxy150489 DEBUGOUT("Error Setting up Auto-Negotiation\n"); 9544919Sxy150489 goto out; 9554919Sxy150489 } 9564919Sxy150489 DEBUGOUT("Restarting Auto-Neg\n"); 9574919Sxy150489 9584919Sxy150489 /* 9594919Sxy150489 * Restart auto-negotiation by setting the Auto Neg Enable bit and the 9604919Sxy150489 * Auto Neg Restart bit in the PHY control register. 9614919Sxy150489 */ 9626735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); 9634919Sxy150489 if (ret_val) 9644919Sxy150489 goto out; 9654919Sxy150489 9664919Sxy150489 phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG); 9676735Scc210113 ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl); 9684919Sxy150489 if (ret_val) 9694919Sxy150489 goto out; 9704919Sxy150489 9714919Sxy150489 /* 9724919Sxy150489 * Does the user want to wait for Auto-Neg to complete here, or check 9734919Sxy150489 * at a later time (for example, callback routine). 9744919Sxy150489 */ 9756735Scc210113 if (phy->autoneg_wait_to_complete) { 9767607STed.You@Sun.COM ret_val = hw->mac.ops.wait_autoneg(hw); 9774919Sxy150489 if (ret_val) { 9784919Sxy150489 DEBUGOUT("Error while waiting for " 9794919Sxy150489 "autoneg to complete\n"); 9804919Sxy150489 goto out; 9814919Sxy150489 } 9824919Sxy150489 } 9834919Sxy150489 9847607STed.You@Sun.COM hw->mac.get_link_status = true; 9854919Sxy150489 9864919Sxy150489 out: 9874919Sxy150489 return (ret_val); 9884919Sxy150489 } 9894919Sxy150489 9904919Sxy150489 /* 9914919Sxy150489 * e1000_phy_setup_autoneg - Configure PHY for auto-negotiation 9924919Sxy150489 * @hw: pointer to the HW structure 9934919Sxy150489 * 9944919Sxy150489 * Reads the MII auto-neg advertisement register and/or the 1000T control 9954919Sxy150489 * register and if the PHY is already setup for auto-negotiation, then 9964919Sxy150489 * return successful. Otherwise, setup advertisement and flow control to 9974919Sxy150489 * the appropriate values for the wanted auto-negotiation. 9984919Sxy150489 */ 9994919Sxy150489 s32 10004919Sxy150489 e1000_phy_setup_autoneg(struct e1000_hw *hw) 10014919Sxy150489 { 10024919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 10034919Sxy150489 s32 ret_val; 10044919Sxy150489 u16 mii_autoneg_adv_reg; 10054919Sxy150489 u16 mii_1000t_ctrl_reg = 0; 10064919Sxy150489 10074919Sxy150489 DEBUGFUNC("e1000_phy_setup_autoneg"); 10084919Sxy150489 10094919Sxy150489 phy->autoneg_advertised &= phy->autoneg_mask; 10104919Sxy150489 10114919Sxy150489 /* Read the MII Auto-Neg Advertisement Register (Address 4). */ 10126735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg); 10134919Sxy150489 if (ret_val) 10144919Sxy150489 goto out; 10154919Sxy150489 10164919Sxy150489 if (phy->autoneg_mask & ADVERTISE_1000_FULL) { 10174919Sxy150489 /* Read the MII 1000Base-T Control Register (Address 9). */ 10186735Scc210113 ret_val = phy->ops.read_reg(hw, 10194919Sxy150489 PHY_1000T_CTRL, 10204919Sxy150489 &mii_1000t_ctrl_reg); 10214919Sxy150489 if (ret_val) 10224919Sxy150489 goto out; 10234919Sxy150489 } 10244919Sxy150489 10254919Sxy150489 /* 10264919Sxy150489 * Need to parse both autoneg_advertised and fc and set up the 10274919Sxy150489 * appropriate PHY registers. First we will parse for 10284919Sxy150489 * autoneg_advertised software override. Since we can advertise a 10294919Sxy150489 * plethora of combinations, we need to check each bit individually. 10304919Sxy150489 */ 10314919Sxy150489 10324919Sxy150489 /* 10334919Sxy150489 * First we clear all the 10/100 mb speed bits in the Auto-Neg 10344919Sxy150489 * Advertisement Register (Address 4) and the 1000 mb speed bits in 10354919Sxy150489 * the 1000Base-T Control Register (Address 9). 10364919Sxy150489 */ 10374919Sxy150489 mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS | 10384919Sxy150489 NWAY_AR_100TX_HD_CAPS | 10394919Sxy150489 NWAY_AR_10T_FD_CAPS | 10404919Sxy150489 NWAY_AR_10T_HD_CAPS); 10414919Sxy150489 mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS); 10424919Sxy150489 10434919Sxy150489 DEBUGOUT1("autoneg_advertised %x\n", phy->autoneg_advertised); 10444919Sxy150489 10454919Sxy150489 /* Do we want to advertise 10 Mb Half Duplex? */ 10464919Sxy150489 if (phy->autoneg_advertised & ADVERTISE_10_HALF) { 10474919Sxy150489 DEBUGOUT("Advertise 10mb Half duplex\n"); 10484919Sxy150489 mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS; 10494919Sxy150489 } 10504919Sxy150489 10514919Sxy150489 /* Do we want to advertise 10 Mb Full Duplex? */ 10524919Sxy150489 if (phy->autoneg_advertised & ADVERTISE_10_FULL) { 10534919Sxy150489 DEBUGOUT("Advertise 10mb Full duplex\n"); 10544919Sxy150489 mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS; 10554919Sxy150489 } 10564919Sxy150489 10574919Sxy150489 /* Do we want to advertise 100 Mb Half Duplex? */ 10584919Sxy150489 if (phy->autoneg_advertised & ADVERTISE_100_HALF) { 10594919Sxy150489 DEBUGOUT("Advertise 100mb Half duplex\n"); 10604919Sxy150489 mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS; 10614919Sxy150489 } 10624919Sxy150489 10634919Sxy150489 /* Do we want to advertise 100 Mb Full Duplex? */ 10644919Sxy150489 if (phy->autoneg_advertised & ADVERTISE_100_FULL) { 10654919Sxy150489 DEBUGOUT("Advertise 100mb Full duplex\n"); 10664919Sxy150489 mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS; 10674919Sxy150489 } 10684919Sxy150489 10694919Sxy150489 /* We do not allow the Phy to advertise 1000 Mb Half Duplex */ 10708479SChenlu.Chen@Sun.COM if (phy->autoneg_advertised & ADVERTISE_1000_HALF) 10714919Sxy150489 DEBUGOUT("Advertise 1000mb Half duplex request denied!\n"); 10724919Sxy150489 10734919Sxy150489 /* Do we want to advertise 1000 Mb Full Duplex? */ 10744919Sxy150489 if (phy->autoneg_advertised & ADVERTISE_1000_FULL) { 10754919Sxy150489 DEBUGOUT("Advertise 1000mb Full duplex\n"); 10764919Sxy150489 mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS; 10774919Sxy150489 } 10784919Sxy150489 10794919Sxy150489 /* 10804919Sxy150489 * Check for a software override of the flow control settings, and 10814919Sxy150489 * setup the PHY advertisement registers accordingly. If 10824919Sxy150489 * auto-negotiation is enabled, then software will have to set the 10834919Sxy150489 * "PAUSE" bits to the correct value in the Auto-Negotiation 10844919Sxy150489 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto- 10854919Sxy150489 * negotiation. 10864919Sxy150489 * 10874919Sxy150489 * The possible values of the "fc" parameter are: 10884919Sxy150489 * 0: Flow control is completely disabled 10894919Sxy150489 * 1: Rx flow control is enabled (we can receive pause frames 10904919Sxy150489 * but not send pause frames). 10914919Sxy150489 * 2: Tx flow control is enabled (we can send pause frames 10924919Sxy150489 * but we do not support receiving pause frames). 10936735Scc210113 * 3: Both Rx and Tx flow control (symmetric) are enabled. 10944919Sxy150489 * other: No software override. The flow control configuration 10954919Sxy150489 * in the EEPROM is used. 10964919Sxy150489 */ 10978479SChenlu.Chen@Sun.COM switch (hw->fc.current_mode) { 10984919Sxy150489 case e1000_fc_none: 10994919Sxy150489 /* 11006735Scc210113 * Flow control (Rx & Tx) is completely disabled by a software 11014919Sxy150489 * over-ride. 11024919Sxy150489 */ 11034919Sxy150489 mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 11044919Sxy150489 break; 11054919Sxy150489 case e1000_fc_rx_pause: 11064919Sxy150489 /* 11076735Scc210113 * Rx Flow control is enabled, and Tx Flow control is 11084919Sxy150489 * disabled, by a software over-ride. 11094919Sxy150489 * 11104919Sxy150489 * Since there really isn't a way to advertise that we are 11116735Scc210113 * capable of Rx Pause ONLY, we will advertise that we support 11126735Scc210113 * both symmetric and asymmetric Rx PAUSE. Later (in 11134919Sxy150489 * e1000_config_fc_after_link_up) we will disable the hw's 11144919Sxy150489 * ability to send PAUSE frames. 11154919Sxy150489 */ 11164919Sxy150489 mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 11174919Sxy150489 break; 11184919Sxy150489 case e1000_fc_tx_pause: 11194919Sxy150489 /* 11206735Scc210113 * Tx Flow control is enabled, and Rx Flow control is 11214919Sxy150489 * disabled, by a software over-ride. 11224919Sxy150489 */ 11234919Sxy150489 mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR; 11244919Sxy150489 mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE; 11254919Sxy150489 break; 11264919Sxy150489 case e1000_fc_full: 11274919Sxy150489 /* 11286735Scc210113 * Flow control (both Rx and Tx) is enabled by a software 11294919Sxy150489 * over-ride. 11304919Sxy150489 */ 11314919Sxy150489 mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE); 11324919Sxy150489 break; 11334919Sxy150489 default: 11344919Sxy150489 DEBUGOUT("Flow control param set incorrectly\n"); 11354919Sxy150489 ret_val = -E1000_ERR_CONFIG; 11364919Sxy150489 goto out; 11374919Sxy150489 } 11384919Sxy150489 11396735Scc210113 ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg); 11404919Sxy150489 if (ret_val) 11414919Sxy150489 goto out; 11424919Sxy150489 11434919Sxy150489 DEBUGOUT1("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg); 11444919Sxy150489 11454919Sxy150489 if (phy->autoneg_mask & ADVERTISE_1000_FULL) { 11466735Scc210113 ret_val = phy->ops.write_reg(hw, 11474919Sxy150489 PHY_1000T_CTRL, 11484919Sxy150489 mii_1000t_ctrl_reg); 11494919Sxy150489 if (ret_val) 11504919Sxy150489 goto out; 11514919Sxy150489 } 11524919Sxy150489 11534919Sxy150489 out: 11544919Sxy150489 return (ret_val); 11554919Sxy150489 } 11564919Sxy150489 11574919Sxy150489 /* 11584919Sxy150489 * e1000_setup_copper_link_generic - Configure copper link settings 11594919Sxy150489 * @hw: pointer to the HW structure 11604919Sxy150489 * 11614919Sxy150489 * Calls the appropriate function to configure the link for auto-neg or forced 11624919Sxy150489 * speed and duplex. Then we check for link, once link is established calls 11634919Sxy150489 * to configure collision distance and flow control are called. If link is 11644919Sxy150489 * not established, we return -E1000_ERR_PHY (-2). 11654919Sxy150489 */ 11664919Sxy150489 s32 11674919Sxy150489 e1000_setup_copper_link_generic(struct e1000_hw *hw) 11684919Sxy150489 { 11694919Sxy150489 s32 ret_val; 11706735Scc210113 bool link; 11714919Sxy150489 11724919Sxy150489 DEBUGFUNC("e1000_setup_copper_link_generic"); 11734919Sxy150489 11744919Sxy150489 if (hw->mac.autoneg) { 11754919Sxy150489 /* 11764919Sxy150489 * Setup autoneg and flow control advertisement and perform 11774919Sxy150489 * autonegotiation. 11784919Sxy150489 */ 11794919Sxy150489 ret_val = e1000_copper_link_autoneg(hw); 11804919Sxy150489 if (ret_val) 11814919Sxy150489 goto out; 11824919Sxy150489 } else { 11834919Sxy150489 /* 11844919Sxy150489 * PHY will be set to 10H, 10F, 100H or 100F depending on user 11854919Sxy150489 * settings. 11864919Sxy150489 */ 11874919Sxy150489 DEBUGOUT("Forcing Speed and Duplex\n"); 11886735Scc210113 ret_val = hw->phy.ops.force_speed_duplex(hw); 11894919Sxy150489 if (ret_val) { 11904919Sxy150489 DEBUGOUT("Error Forcing Speed and Duplex\n"); 11914919Sxy150489 goto out; 11924919Sxy150489 } 11934919Sxy150489 } 11944919Sxy150489 11954919Sxy150489 /* 11964919Sxy150489 * Check link status. Wait up to 100 microseconds for link to become 11974919Sxy150489 * valid. 11984919Sxy150489 */ 11994919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, 12004919Sxy150489 COPPER_LINK_UP_LIMIT, 12014919Sxy150489 10, 12024919Sxy150489 &link); 12034919Sxy150489 if (ret_val) 12044919Sxy150489 goto out; 12054919Sxy150489 12064919Sxy150489 if (link) { 12074919Sxy150489 DEBUGOUT("Valid link established!!!\n"); 12084919Sxy150489 e1000_config_collision_dist_generic(hw); 12094919Sxy150489 ret_val = e1000_config_fc_after_link_up_generic(hw); 12104919Sxy150489 } else { 12114919Sxy150489 DEBUGOUT("Unable to establish link!!!\n"); 12124919Sxy150489 } 12134919Sxy150489 12144919Sxy150489 out: 12154919Sxy150489 return (ret_val); 12164919Sxy150489 } 12174919Sxy150489 12184919Sxy150489 /* 12194919Sxy150489 * e1000_phy_force_speed_duplex_igp - Force speed/duplex for igp PHY 12204919Sxy150489 * @hw: pointer to the HW structure 12214919Sxy150489 * 12224919Sxy150489 * Calls the PHY setup function to force speed and duplex. Clears the 12234919Sxy150489 * auto-crossover to force MDI manually. Waits for link and returns 12244919Sxy150489 * successful if link up is successful, else -E1000_ERR_PHY (-2). 12254919Sxy150489 */ 12264919Sxy150489 s32 12274919Sxy150489 e1000_phy_force_speed_duplex_igp(struct e1000_hw *hw) 12284919Sxy150489 { 12294919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 12304919Sxy150489 s32 ret_val; 12314919Sxy150489 u16 phy_data; 12326735Scc210113 bool link; 12334919Sxy150489 12344919Sxy150489 DEBUGFUNC("e1000_phy_force_speed_duplex_igp"); 12354919Sxy150489 12366735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); 12374919Sxy150489 if (ret_val) 12384919Sxy150489 goto out; 12394919Sxy150489 12404919Sxy150489 e1000_phy_force_speed_duplex_setup(hw, &phy_data); 12414919Sxy150489 12426735Scc210113 ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); 12434919Sxy150489 if (ret_val) 12444919Sxy150489 goto out; 12454919Sxy150489 12464919Sxy150489 /* 12474919Sxy150489 * Clear Auto-Crossover to force MDI manually. IGP requires MDI 12484919Sxy150489 * forced whenever speed and duplex are forced. 12494919Sxy150489 */ 12506735Scc210113 ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_CTRL, &phy_data); 12514919Sxy150489 if (ret_val) 12524919Sxy150489 goto out; 12534919Sxy150489 12544919Sxy150489 phy_data &= ~IGP01E1000_PSCR_AUTO_MDIX; 12554919Sxy150489 phy_data &= ~IGP01E1000_PSCR_FORCE_MDI_MDIX; 12564919Sxy150489 12576735Scc210113 ret_val = phy->ops.write_reg(hw, IGP01E1000_PHY_PORT_CTRL, phy_data); 12584919Sxy150489 if (ret_val) 12594919Sxy150489 goto out; 12604919Sxy150489 12614919Sxy150489 DEBUGOUT1("IGP PSCR: %X\n", phy_data); 12624919Sxy150489 12634919Sxy150489 usec_delay(1); 12644919Sxy150489 12656735Scc210113 if (phy->autoneg_wait_to_complete) { 12664919Sxy150489 DEBUGOUT("Waiting for forced speed/duplex link on IGP phy.\n"); 12674919Sxy150489 12684919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, 12694919Sxy150489 PHY_FORCE_LIMIT, 12704919Sxy150489 100000, 12714919Sxy150489 &link); 12724919Sxy150489 if (ret_val) 12734919Sxy150489 goto out; 12744919Sxy150489 12758479SChenlu.Chen@Sun.COM if (!link) 12764919Sxy150489 DEBUGOUT("Link taking longer than expected.\n"); 12774919Sxy150489 12784919Sxy150489 /* Try once more */ 12794919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, 12804919Sxy150489 PHY_FORCE_LIMIT, 12814919Sxy150489 100000, 12824919Sxy150489 &link); 12834919Sxy150489 if (ret_val) 12844919Sxy150489 goto out; 12854919Sxy150489 } 12864919Sxy150489 12874919Sxy150489 out: 12884919Sxy150489 return (ret_val); 12894919Sxy150489 } 12904919Sxy150489 12914919Sxy150489 /* 12924919Sxy150489 * e1000_phy_force_speed_duplex_m88 - Force speed/duplex for m88 PHY 12934919Sxy150489 * @hw: pointer to the HW structure 12944919Sxy150489 * 12954919Sxy150489 * Calls the PHY setup function to force speed and duplex. Clears the 12964919Sxy150489 * auto-crossover to force MDI manually. Resets the PHY to commit the 12974919Sxy150489 * changes. If time expires while waiting for link up, we reset the DSP. 12986735Scc210113 * After reset, TX_CLK and CRS on Tx must be set. Return successful upon 12994919Sxy150489 * successful completion, else return corresponding error code. 13004919Sxy150489 */ 13014919Sxy150489 s32 13024919Sxy150489 e1000_phy_force_speed_duplex_m88(struct e1000_hw *hw) 13034919Sxy150489 { 13044919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 13054919Sxy150489 s32 ret_val; 13064919Sxy150489 u16 phy_data; 13076735Scc210113 bool link; 13084919Sxy150489 13094919Sxy150489 DEBUGFUNC("e1000_phy_force_speed_duplex_m88"); 13104919Sxy150489 13114919Sxy150489 /* 13124919Sxy150489 * Clear Auto-Crossover to force MDI manually. M88E1000 requires MDI 13134919Sxy150489 * forced whenever speed and duplex are forced. 13144919Sxy150489 */ 13156735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 13164919Sxy150489 if (ret_val) 13174919Sxy150489 goto out; 13184919Sxy150489 13194919Sxy150489 phy_data &= ~M88E1000_PSCR_AUTO_X_MODE; 13206735Scc210113 ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); 13214919Sxy150489 if (ret_val) 13224919Sxy150489 goto out; 13234919Sxy150489 13244919Sxy150489 DEBUGOUT1("M88E1000 PSCR: %X\n", phy_data); 13254919Sxy150489 13266735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); 13274919Sxy150489 if (ret_val) 13284919Sxy150489 goto out; 13294919Sxy150489 13304919Sxy150489 e1000_phy_force_speed_duplex_setup(hw, &phy_data); 13314919Sxy150489 13326735Scc210113 ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); 13334919Sxy150489 if (ret_val) 13344919Sxy150489 goto out; 13354919Sxy150489 13368479SChenlu.Chen@Sun.COM /* Reset the phy to commit changes. */ 13378479SChenlu.Chen@Sun.COM ret_val = hw->phy.ops.commit(hw); 13388479SChenlu.Chen@Sun.COM if (ret_val) 13398479SChenlu.Chen@Sun.COM goto out; 13404919Sxy150489 13416735Scc210113 if (phy->autoneg_wait_to_complete) { 13424919Sxy150489 DEBUGOUT("Waiting for forced speed/duplex link on M88 phy.\n"); 13434919Sxy150489 13444919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, 13454919Sxy150489 PHY_FORCE_LIMIT, 13464919Sxy150489 100000, 13474919Sxy150489 &link); 13484919Sxy150489 if (ret_val) 13494919Sxy150489 goto out; 13504919Sxy150489 13514919Sxy150489 if (!link) { 13524919Sxy150489 /* 13534919Sxy150489 * We didn't get link. Reset the DSP and cross our 13544919Sxy150489 * fingers. 13554919Sxy150489 */ 13566735Scc210113 ret_val = phy->ops.write_reg(hw, 13574919Sxy150489 M88E1000_PHY_PAGE_SELECT, 13584919Sxy150489 0x001d); 13594919Sxy150489 if (ret_val) 13604919Sxy150489 goto out; 13614919Sxy150489 ret_val = e1000_phy_reset_dsp_generic(hw); 13624919Sxy150489 if (ret_val) 13634919Sxy150489 goto out; 13644919Sxy150489 } 13654919Sxy150489 /* Try once more */ 13664919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, 13674919Sxy150489 PHY_FORCE_LIMIT, 13684919Sxy150489 100000, 13694919Sxy150489 &link); 13704919Sxy150489 if (ret_val) 13714919Sxy150489 goto out; 13724919Sxy150489 } 13736735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, &phy_data); 13744919Sxy150489 if (ret_val) 13754919Sxy150489 goto out; 13764919Sxy150489 13774919Sxy150489 /* 13784919Sxy150489 * Resetting the phy means we need to re-force TX_CLK in the Extended 13794919Sxy150489 * PHY Specific Control Register to 25MHz clock from the reset value 13804919Sxy150489 * of 2.5MHz. 13814919Sxy150489 */ 13824919Sxy150489 phy_data |= M88E1000_EPSCR_TX_CLK_25; 13836735Scc210113 ret_val = phy->ops.write_reg(hw, M88E1000_EXT_PHY_SPEC_CTRL, phy_data); 13844919Sxy150489 if (ret_val) 13854919Sxy150489 goto out; 13864919Sxy150489 13874919Sxy150489 /* 13884919Sxy150489 * In addition, we must re-enable CRS on Tx for both half and full 13894919Sxy150489 * duplex. 13904919Sxy150489 */ 13916735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 13924919Sxy150489 if (ret_val) 13934919Sxy150489 goto out; 13944919Sxy150489 13954919Sxy150489 phy_data |= M88E1000_PSCR_ASSERT_CRS_ON_TX; 13966735Scc210113 ret_val = phy->ops.write_reg(hw, M88E1000_PHY_SPEC_CTRL, phy_data); 13974919Sxy150489 13984919Sxy150489 out: 13994919Sxy150489 return (ret_val); 14004919Sxy150489 } 14014919Sxy150489 14024919Sxy150489 /* 1403*10680SMin.Xu@Sun.COM * e1000_phy_force_speed_duplex_ife - Force PHY speed & duplex 1404*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 1405*10680SMin.Xu@Sun.COM * 1406*10680SMin.Xu@Sun.COM * Forces the speed and duplex settings of the PHY. 1407*10680SMin.Xu@Sun.COM * This is a function pointer entry point only called by 1408*10680SMin.Xu@Sun.COM * PHY setup routines. 1409*10680SMin.Xu@Sun.COM */ 1410*10680SMin.Xu@Sun.COM s32 1411*10680SMin.Xu@Sun.COM e1000_phy_force_speed_duplex_ife(struct e1000_hw *hw) 1412*10680SMin.Xu@Sun.COM { 1413*10680SMin.Xu@Sun.COM struct e1000_phy_info *phy = &hw->phy; 1414*10680SMin.Xu@Sun.COM s32 ret_val; 1415*10680SMin.Xu@Sun.COM u16 data; 1416*10680SMin.Xu@Sun.COM bool link; 1417*10680SMin.Xu@Sun.COM 1418*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_phy_force_speed_duplex_ife"); 1419*10680SMin.Xu@Sun.COM 1420*10680SMin.Xu@Sun.COM if (phy->type != e1000_phy_ife) { 1421*10680SMin.Xu@Sun.COM ret_val = e1000_phy_force_speed_duplex_igp(hw); 1422*10680SMin.Xu@Sun.COM goto out; 1423*10680SMin.Xu@Sun.COM } 1424*10680SMin.Xu@Sun.COM 1425*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &data); 1426*10680SMin.Xu@Sun.COM if (ret_val) 1427*10680SMin.Xu@Sun.COM goto out; 1428*10680SMin.Xu@Sun.COM 1429*10680SMin.Xu@Sun.COM e1000_phy_force_speed_duplex_setup(hw, &data); 1430*10680SMin.Xu@Sun.COM 1431*10680SMin.Xu@Sun.COM ret_val = phy->ops.write_reg(hw, PHY_CONTROL, data); 1432*10680SMin.Xu@Sun.COM if (ret_val) 1433*10680SMin.Xu@Sun.COM goto out; 1434*10680SMin.Xu@Sun.COM 1435*10680SMin.Xu@Sun.COM /* Disable MDI-X support for 10/100 */ 1436*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, IFE_PHY_MDIX_CONTROL, &data); 1437*10680SMin.Xu@Sun.COM if (ret_val) 1438*10680SMin.Xu@Sun.COM goto out; 1439*10680SMin.Xu@Sun.COM 1440*10680SMin.Xu@Sun.COM data &= ~IFE_PMC_AUTO_MDIX; 1441*10680SMin.Xu@Sun.COM data &= ~IFE_PMC_FORCE_MDIX; 1442*10680SMin.Xu@Sun.COM 1443*10680SMin.Xu@Sun.COM ret_val = phy->ops.write_reg(hw, IFE_PHY_MDIX_CONTROL, data); 1444*10680SMin.Xu@Sun.COM if (ret_val) 1445*10680SMin.Xu@Sun.COM goto out; 1446*10680SMin.Xu@Sun.COM 1447*10680SMin.Xu@Sun.COM DEBUGOUT1("IFE PMC: %X\n", data); 1448*10680SMin.Xu@Sun.COM 1449*10680SMin.Xu@Sun.COM usec_delay(1); 1450*10680SMin.Xu@Sun.COM 1451*10680SMin.Xu@Sun.COM if (phy->autoneg_wait_to_complete) { 1452*10680SMin.Xu@Sun.COM DEBUGOUT("Waiting for forced speed/duplex link on IFE phy.\n"); 1453*10680SMin.Xu@Sun.COM 1454*10680SMin.Xu@Sun.COM ret_val = e1000_phy_has_link_generic(hw, 1455*10680SMin.Xu@Sun.COM PHY_FORCE_LIMIT, 100000, &link); 1456*10680SMin.Xu@Sun.COM if (ret_val) 1457*10680SMin.Xu@Sun.COM goto out; 1458*10680SMin.Xu@Sun.COM 1459*10680SMin.Xu@Sun.COM if (!link) 1460*10680SMin.Xu@Sun.COM DEBUGOUT("Link taking longer than expected.\n"); 1461*10680SMin.Xu@Sun.COM 1462*10680SMin.Xu@Sun.COM /* Try once more */ 1463*10680SMin.Xu@Sun.COM ret_val = e1000_phy_has_link_generic(hw, 1464*10680SMin.Xu@Sun.COM PHY_FORCE_LIMIT, 100000, &link); 1465*10680SMin.Xu@Sun.COM if (ret_val) 1466*10680SMin.Xu@Sun.COM goto out; 1467*10680SMin.Xu@Sun.COM } 1468*10680SMin.Xu@Sun.COM 1469*10680SMin.Xu@Sun.COM out: 1470*10680SMin.Xu@Sun.COM return (ret_val); 1471*10680SMin.Xu@Sun.COM } 1472*10680SMin.Xu@Sun.COM 1473*10680SMin.Xu@Sun.COM /* 14744919Sxy150489 * e1000_phy_force_speed_duplex_setup - Configure forced PHY speed/duplex 14754919Sxy150489 * @hw: pointer to the HW structure 14764919Sxy150489 * @phy_ctrl: pointer to current value of PHY_CONTROL 14774919Sxy150489 * 14784919Sxy150489 * Forces speed and duplex on the PHY by doing the following: disable flow 14794919Sxy150489 * control, force speed/duplex on the MAC, disable auto speed detection, 14804919Sxy150489 * disable auto-negotiation, configure duplex, configure speed, configure 14814919Sxy150489 * the collision distance, write configuration to CTRL register. The 14824919Sxy150489 * caller must write to the PHY_CONTROL register for these settings to 14834919Sxy150489 * take affect. 14844919Sxy150489 */ 14854919Sxy150489 void 14864919Sxy150489 e1000_phy_force_speed_duplex_setup(struct e1000_hw *hw, u16 *phy_ctrl) 14874919Sxy150489 { 14884919Sxy150489 struct e1000_mac_info *mac = &hw->mac; 14894919Sxy150489 u32 ctrl; 14904919Sxy150489 14914919Sxy150489 DEBUGFUNC("e1000_phy_force_speed_duplex_setup"); 14924919Sxy150489 14934919Sxy150489 /* Turn off flow control when forcing speed/duplex */ 14948479SChenlu.Chen@Sun.COM hw->fc.current_mode = e1000_fc_none; 14954919Sxy150489 14964919Sxy150489 /* Force speed/duplex on the mac */ 14974919Sxy150489 ctrl = E1000_READ_REG(hw, E1000_CTRL); 14984919Sxy150489 ctrl |= (E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX); 14994919Sxy150489 ctrl &= ~E1000_CTRL_SPD_SEL; 15004919Sxy150489 15014919Sxy150489 /* Disable Auto Speed Detection */ 15024919Sxy150489 ctrl &= ~E1000_CTRL_ASDE; 15034919Sxy150489 15044919Sxy150489 /* Disable autoneg on the phy */ 15054919Sxy150489 *phy_ctrl &= ~MII_CR_AUTO_NEG_EN; 15064919Sxy150489 15074919Sxy150489 /* Forcing Full or Half Duplex? */ 15084919Sxy150489 if (mac->forced_speed_duplex & E1000_ALL_HALF_DUPLEX) { 15094919Sxy150489 ctrl &= ~E1000_CTRL_FD; 15104919Sxy150489 *phy_ctrl &= ~MII_CR_FULL_DUPLEX; 15114919Sxy150489 DEBUGOUT("Half Duplex\n"); 15124919Sxy150489 } else { 15134919Sxy150489 ctrl |= E1000_CTRL_FD; 15144919Sxy150489 *phy_ctrl |= MII_CR_FULL_DUPLEX; 15154919Sxy150489 DEBUGOUT("Full Duplex\n"); 15164919Sxy150489 } 15174919Sxy150489 15184919Sxy150489 /* Forcing 10mb or 100mb? */ 15194919Sxy150489 if (mac->forced_speed_duplex & E1000_ALL_100_SPEED) { 15204919Sxy150489 ctrl |= E1000_CTRL_SPD_100; 15214919Sxy150489 *phy_ctrl |= MII_CR_SPEED_100; 15224919Sxy150489 *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_10); 15234919Sxy150489 DEBUGOUT("Forcing 100mb\n"); 15244919Sxy150489 } else { 15254919Sxy150489 ctrl &= ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100); 1526*10680SMin.Xu@Sun.COM /* LINTED */ 15274919Sxy150489 *phy_ctrl |= MII_CR_SPEED_10; 15284919Sxy150489 *phy_ctrl &= ~(MII_CR_SPEED_1000 | MII_CR_SPEED_100); 15294919Sxy150489 DEBUGOUT("Forcing 10mb\n"); 15304919Sxy150489 } 15314919Sxy150489 15324919Sxy150489 e1000_config_collision_dist_generic(hw); 15334919Sxy150489 15344919Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 15354919Sxy150489 } 15364919Sxy150489 15374919Sxy150489 /* 15384919Sxy150489 * e1000_set_d3_lplu_state_generic - Sets low power link up state for D3 15394919Sxy150489 * @hw: pointer to the HW structure 15404919Sxy150489 * @active: boolean used to enable/disable lplu 15414919Sxy150489 * 15424919Sxy150489 * Success returns 0, Failure returns 1 15434919Sxy150489 * 15444919Sxy150489 * The low power link up (lplu) state is set to the power management level D3 15454919Sxy150489 * and SmartSpeed is disabled when active is true, else clear lplu for D3 15464919Sxy150489 * and enable Smartspeed. LPLU and Smartspeed are mutually exclusive. LPLU 15474919Sxy150489 * is used during Dx states where the power conservation is most important. 15484919Sxy150489 * During driver activity, SmartSpeed should be enabled so performance is 15494919Sxy150489 * maintained. 15504919Sxy150489 */ 15514919Sxy150489 s32 15526735Scc210113 e1000_set_d3_lplu_state_generic(struct e1000_hw *hw, bool active) 15534919Sxy150489 { 15544919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 15556735Scc210113 s32 ret_val = E1000_SUCCESS; 15564919Sxy150489 u16 data; 15574919Sxy150489 15584919Sxy150489 DEBUGFUNC("e1000_set_d3_lplu_state_generic"); 15594919Sxy150489 15606735Scc210113 if (!(hw->phy.ops.read_reg)) 15616735Scc210113 goto out; 15626735Scc210113 15636735Scc210113 ret_val = phy->ops.read_reg(hw, IGP02E1000_PHY_POWER_MGMT, &data); 15644919Sxy150489 if (ret_val) 15654919Sxy150489 goto out; 15664919Sxy150489 15674919Sxy150489 if (!active) { 15684919Sxy150489 data &= ~IGP02E1000_PM_D3_LPLU; 15696735Scc210113 ret_val = phy->ops.write_reg(hw, 15704919Sxy150489 IGP02E1000_PHY_POWER_MGMT, 15714919Sxy150489 data); 15724919Sxy150489 if (ret_val) 15734919Sxy150489 goto out; 15744919Sxy150489 /* 15754919Sxy150489 * LPLU and SmartSpeed are mutually exclusive. LPLU is used 15764919Sxy150489 * during Dx states where the power conservation is most 15774919Sxy150489 * important. During driver activity we should enable 15784919Sxy150489 * SmartSpeed, so performance is maintained. 15794919Sxy150489 */ 15804919Sxy150489 if (phy->smart_speed == e1000_smart_speed_on) { 15816735Scc210113 ret_val = phy->ops.read_reg(hw, 15824919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 15834919Sxy150489 &data); 15844919Sxy150489 if (ret_val) 15854919Sxy150489 goto out; 15864919Sxy150489 15874919Sxy150489 data |= IGP01E1000_PSCFR_SMART_SPEED; 15886735Scc210113 ret_val = phy->ops.write_reg(hw, 15894919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 15904919Sxy150489 data); 15914919Sxy150489 if (ret_val) 15924919Sxy150489 goto out; 15934919Sxy150489 } else if (phy->smart_speed == e1000_smart_speed_off) { 15946735Scc210113 ret_val = phy->ops.read_reg(hw, 15954919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 15964919Sxy150489 &data); 15974919Sxy150489 if (ret_val) 15984919Sxy150489 goto out; 15994919Sxy150489 16004919Sxy150489 data &= ~IGP01E1000_PSCFR_SMART_SPEED; 16016735Scc210113 ret_val = phy->ops.write_reg(hw, 16024919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 16034919Sxy150489 data); 16044919Sxy150489 if (ret_val) 16054919Sxy150489 goto out; 16064919Sxy150489 } 16074919Sxy150489 } else if ((phy->autoneg_advertised == E1000_ALL_SPEED_DUPLEX) || 16084919Sxy150489 (phy->autoneg_advertised == E1000_ALL_NOT_GIG) || 16094919Sxy150489 (phy->autoneg_advertised == E1000_ALL_10_SPEED)) { 16104919Sxy150489 data |= IGP02E1000_PM_D3_LPLU; 16116735Scc210113 ret_val = phy->ops.write_reg(hw, 16124919Sxy150489 IGP02E1000_PHY_POWER_MGMT, 16134919Sxy150489 data); 16144919Sxy150489 if (ret_val) 16154919Sxy150489 goto out; 16164919Sxy150489 16174919Sxy150489 /* When LPLU is enabled, we should disable SmartSpeed */ 16186735Scc210113 ret_val = phy->ops.read_reg(hw, 16194919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 16204919Sxy150489 &data); 16214919Sxy150489 if (ret_val) 16224919Sxy150489 goto out; 16234919Sxy150489 16244919Sxy150489 data &= ~IGP01E1000_PSCFR_SMART_SPEED; 16256735Scc210113 ret_val = phy->ops.write_reg(hw, 16264919Sxy150489 IGP01E1000_PHY_PORT_CONFIG, 16274919Sxy150489 data); 16284919Sxy150489 } 16294919Sxy150489 16304919Sxy150489 out: 16314919Sxy150489 return (ret_val); 16324919Sxy150489 } 16334919Sxy150489 16344919Sxy150489 /* 16356735Scc210113 * e1000_check_downshift_generic - Checks whether a downshift in speed occurred 16364919Sxy150489 * @hw: pointer to the HW structure 16374919Sxy150489 * 16384919Sxy150489 * Success returns 0, Failure returns 1 16394919Sxy150489 * 16404919Sxy150489 * A downshift is detected by querying the PHY link health. 16414919Sxy150489 */ 16424919Sxy150489 s32 16434919Sxy150489 e1000_check_downshift_generic(struct e1000_hw *hw) 16444919Sxy150489 { 16454919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 16464919Sxy150489 s32 ret_val; 16474919Sxy150489 u16 phy_data, offset, mask; 16484919Sxy150489 16494919Sxy150489 DEBUGFUNC("e1000_check_downshift_generic"); 16504919Sxy150489 16514919Sxy150489 switch (phy->type) { 16524919Sxy150489 case e1000_phy_m88: 16534919Sxy150489 case e1000_phy_gg82563: 16544919Sxy150489 case e1000_phy_bm: 1655*10680SMin.Xu@Sun.COM case e1000_phy_82578: 16564919Sxy150489 offset = M88E1000_PHY_SPEC_STATUS; 16574919Sxy150489 mask = M88E1000_PSSR_DOWNSHIFT; 16584919Sxy150489 break; 16594919Sxy150489 case e1000_phy_igp_2: 16604919Sxy150489 case e1000_phy_igp: 16614919Sxy150489 case e1000_phy_igp_3: 16624919Sxy150489 offset = IGP01E1000_PHY_LINK_HEALTH; 16634919Sxy150489 mask = IGP01E1000_PLHR_SS_DOWNGRADE; 16644919Sxy150489 break; 16654919Sxy150489 default: 16664919Sxy150489 /* speed downshift not supported */ 16677607STed.You@Sun.COM phy->speed_downgraded = false; 16684919Sxy150489 ret_val = E1000_SUCCESS; 16694919Sxy150489 goto out; 16704919Sxy150489 } 16714919Sxy150489 16726735Scc210113 ret_val = phy->ops.read_reg(hw, offset, &phy_data); 16734919Sxy150489 16744919Sxy150489 if (!ret_val) 16757607STed.You@Sun.COM phy->speed_downgraded = (phy_data & mask) ? true : false; 16764919Sxy150489 16774919Sxy150489 out: 16784919Sxy150489 return (ret_val); 16794919Sxy150489 } 16804919Sxy150489 16814919Sxy150489 /* 16824919Sxy150489 * e1000_check_polarity_m88 - Checks the polarity. 16834919Sxy150489 * @hw: pointer to the HW structure 16844919Sxy150489 * 16854919Sxy150489 * Success returns 0, Failure returns -E1000_ERR_PHY (-2) 16864919Sxy150489 * 16874919Sxy150489 * Polarity is determined based on the PHY specific status register. 16884919Sxy150489 */ 16894919Sxy150489 s32 16904919Sxy150489 e1000_check_polarity_m88(struct e1000_hw *hw) 16914919Sxy150489 { 16924919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 16934919Sxy150489 s32 ret_val; 16944919Sxy150489 u16 data; 16954919Sxy150489 16964919Sxy150489 DEBUGFUNC("e1000_check_polarity_m88"); 16974919Sxy150489 16986735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &data); 16994919Sxy150489 17004919Sxy150489 if (!ret_val) 17014919Sxy150489 phy->cable_polarity = (data & M88E1000_PSSR_REV_POLARITY) 17024919Sxy150489 ? e1000_rev_polarity_reversed 17034919Sxy150489 : e1000_rev_polarity_normal; 17044919Sxy150489 17054919Sxy150489 return (ret_val); 17064919Sxy150489 } 17074919Sxy150489 17084919Sxy150489 /* 17094919Sxy150489 * e1000_check_polarity_igp - Checks the polarity. 17104919Sxy150489 * @hw: pointer to the HW structure 17114919Sxy150489 * 17124919Sxy150489 * Success returns 0, Failure returns -E1000_ERR_PHY (-2) 17134919Sxy150489 * 17144919Sxy150489 * Polarity is determined based on the PHY port status register, and the 17154919Sxy150489 * current speed (since there is no polarity at 100Mbps). 17164919Sxy150489 */ 17174919Sxy150489 s32 17184919Sxy150489 e1000_check_polarity_igp(struct e1000_hw *hw) 17194919Sxy150489 { 17204919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 17214919Sxy150489 s32 ret_val; 17224919Sxy150489 u16 data, offset, mask; 17234919Sxy150489 17244919Sxy150489 DEBUGFUNC("e1000_check_polarity_igp"); 17254919Sxy150489 17264919Sxy150489 /* 17274919Sxy150489 * Polarity is determined based on the speed of our connection. 17284919Sxy150489 */ 17296735Scc210113 ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); 17304919Sxy150489 if (ret_val) 17314919Sxy150489 goto out; 17324919Sxy150489 17334919Sxy150489 if ((data & IGP01E1000_PSSR_SPEED_MASK) == 17344919Sxy150489 IGP01E1000_PSSR_SPEED_1000MBPS) { 17354919Sxy150489 offset = IGP01E1000_PHY_PCS_INIT_REG; 17364919Sxy150489 mask = IGP01E1000_PHY_POLARITY_MASK; 17374919Sxy150489 } else { 17384919Sxy150489 /* 17394919Sxy150489 * This really only applies to 10Mbps since there is no 17404919Sxy150489 * polarity for 100Mbps (always 0). 17414919Sxy150489 */ 17424919Sxy150489 offset = IGP01E1000_PHY_PORT_STATUS; 17434919Sxy150489 mask = IGP01E1000_PSSR_POLARITY_REVERSED; 17444919Sxy150489 } 17454919Sxy150489 17466735Scc210113 ret_val = phy->ops.read_reg(hw, offset, &data); 17474919Sxy150489 17484919Sxy150489 if (!ret_val) 17494919Sxy150489 phy->cable_polarity = (data & mask) 17504919Sxy150489 ? e1000_rev_polarity_reversed 17514919Sxy150489 : e1000_rev_polarity_normal; 17524919Sxy150489 17534919Sxy150489 out: 17544919Sxy150489 return (ret_val); 17554919Sxy150489 } 17564919Sxy150489 17574919Sxy150489 /* 1758*10680SMin.Xu@Sun.COM * e1000_check_polarity_ife - Check cable polarity for IFE PHY 1759*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 1760*10680SMin.Xu@Sun.COM * 1761*10680SMin.Xu@Sun.COM * Polarity is determined on the polarity reversal feature being enabled. 1762*10680SMin.Xu@Sun.COM */ 1763*10680SMin.Xu@Sun.COM s32 1764*10680SMin.Xu@Sun.COM e1000_check_polarity_ife(struct e1000_hw *hw) 1765*10680SMin.Xu@Sun.COM { 1766*10680SMin.Xu@Sun.COM struct e1000_phy_info *phy = &hw->phy; 1767*10680SMin.Xu@Sun.COM s32 ret_val; 1768*10680SMin.Xu@Sun.COM u16 phy_data, offset, mask; 1769*10680SMin.Xu@Sun.COM 1770*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_check_polarity_ife"); 1771*10680SMin.Xu@Sun.COM 1772*10680SMin.Xu@Sun.COM /* 1773*10680SMin.Xu@Sun.COM * Polarity is determined based on the reversal feature being enabled. 1774*10680SMin.Xu@Sun.COM */ 1775*10680SMin.Xu@Sun.COM if (phy->polarity_correction) { 1776*10680SMin.Xu@Sun.COM offset = IFE_PHY_EXTENDED_STATUS_CONTROL; 1777*10680SMin.Xu@Sun.COM mask = IFE_PESC_POLARITY_REVERSED; 1778*10680SMin.Xu@Sun.COM } else { 1779*10680SMin.Xu@Sun.COM offset = IFE_PHY_SPECIAL_CONTROL; 1780*10680SMin.Xu@Sun.COM mask = IFE_PSC_FORCE_POLARITY; 1781*10680SMin.Xu@Sun.COM } 1782*10680SMin.Xu@Sun.COM 1783*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, offset, &phy_data); 1784*10680SMin.Xu@Sun.COM 1785*10680SMin.Xu@Sun.COM if (!ret_val) 1786*10680SMin.Xu@Sun.COM phy->cable_polarity = (phy_data & mask) 1787*10680SMin.Xu@Sun.COM ? e1000_rev_polarity_reversed : e1000_rev_polarity_normal; 1788*10680SMin.Xu@Sun.COM 1789*10680SMin.Xu@Sun.COM return (ret_val); 1790*10680SMin.Xu@Sun.COM } 1791*10680SMin.Xu@Sun.COM 1792*10680SMin.Xu@Sun.COM /* 17936735Scc210113 * e1000_wait_autoneg_generic - Wait for auto-neg completion 17944919Sxy150489 * @hw: pointer to the HW structure 17954919Sxy150489 * 17964919Sxy150489 * Waits for auto-negotiation to complete or for the auto-negotiation time 17974919Sxy150489 * limit to expire, which ever happens first. 17984919Sxy150489 */ 17994919Sxy150489 s32 18004919Sxy150489 e1000_wait_autoneg_generic(struct e1000_hw *hw) 18014919Sxy150489 { 18024919Sxy150489 s32 ret_val = E1000_SUCCESS; 18034919Sxy150489 u16 i, phy_status; 18044919Sxy150489 18054919Sxy150489 DEBUGFUNC("e1000_wait_autoneg_generic"); 18064919Sxy150489 18076735Scc210113 if (!(hw->phy.ops.read_reg)) 18086735Scc210113 return (E1000_SUCCESS); 18096735Scc210113 18104919Sxy150489 /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */ 18114919Sxy150489 for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) { 18126735Scc210113 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); 18134919Sxy150489 if (ret_val) 18144919Sxy150489 break; 18156735Scc210113 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); 18164919Sxy150489 if (ret_val) 18174919Sxy150489 break; 18184919Sxy150489 if (phy_status & MII_SR_AUTONEG_COMPLETE) 18194919Sxy150489 break; 18204919Sxy150489 msec_delay(100); 18214919Sxy150489 } 18224919Sxy150489 18234919Sxy150489 /* 18244919Sxy150489 * PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation has 18254919Sxy150489 * completed. 18264919Sxy150489 */ 18274919Sxy150489 return (ret_val); 18284919Sxy150489 } 18294919Sxy150489 18304919Sxy150489 /* 18314919Sxy150489 * e1000_phy_has_link_generic - Polls PHY for link 18324919Sxy150489 * @hw: pointer to the HW structure 18334919Sxy150489 * @iterations: number of times to poll for link 18344919Sxy150489 * @usec_interval: delay between polling attempts 18354919Sxy150489 * @success: pointer to whether polling was successful or not 18364919Sxy150489 * 18374919Sxy150489 * Polls the PHY status register for link, 'iterations' number of times. 18384919Sxy150489 */ 18394919Sxy150489 s32 18404919Sxy150489 e1000_phy_has_link_generic(struct e1000_hw *hw, u32 iterations, 18416735Scc210113 u32 usec_interval, bool *success) 18424919Sxy150489 { 18434919Sxy150489 s32 ret_val = E1000_SUCCESS; 18444919Sxy150489 u16 i, phy_status; 18454919Sxy150489 18464919Sxy150489 DEBUGFUNC("e1000_phy_has_link_generic"); 18474919Sxy150489 18486735Scc210113 if (!(hw->phy.ops.read_reg)) 18496735Scc210113 return (E1000_SUCCESS); 18506735Scc210113 18514919Sxy150489 for (i = 0; i < iterations; i++) { 18524919Sxy150489 /* 18534919Sxy150489 * Some PHYs require the PHY_STATUS register to be read twice 18544919Sxy150489 * due to the link bit being sticky. No harm doing it across 18554919Sxy150489 * the board. 18564919Sxy150489 */ 18576735Scc210113 ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status); 1858*10680SMin.Xu@Sun.COM if (ret_val) { 1859*10680SMin.Xu@Sun.COM /* 1860*10680SMin.Xu@Sun.COM * If the first read fails, another entity may have 1861*10680SMin.Xu@Sun.COM * ownership of the resources, wait and try again to 1862*10680SMin.Xu@Sun.COM * see if they have relinquished the resources yet. 1863*10680SMin.Xu@Sun.COM */ 1864*10680SMin.Xu@Sun.COM usec_delay(usec_interval); 1865*10680SMin.Xu@Sun.COM } 1866*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, 1867*10680SMin.Xu@Sun.COM &phy_status); 18684919Sxy150489 if (ret_val) 18694919Sxy150489 break; 18704919Sxy150489 if (phy_status & MII_SR_LINK_STATUS) 18714919Sxy150489 break; 18724919Sxy150489 if (usec_interval >= 1000) 18734919Sxy150489 msec_delay_irq(usec_interval / 1000); 18744919Sxy150489 else 18754919Sxy150489 usec_delay(usec_interval); 18764919Sxy150489 } 18774919Sxy150489 18787607STed.You@Sun.COM *success = (i < iterations) ? true : false; 18794919Sxy150489 18804919Sxy150489 return (ret_val); 18814919Sxy150489 } 18824919Sxy150489 18834919Sxy150489 /* 18844919Sxy150489 * e1000_get_cable_length_m88 - Determine cable length for m88 PHY 18854919Sxy150489 * @hw: pointer to the HW structure 18864919Sxy150489 * 18874919Sxy150489 * Reads the PHY specific status register to retrieve the cable length 18884919Sxy150489 * information. The cable length is determined by averaging the minimum and 18894919Sxy150489 * maximum values to get the "average" cable length. The m88 PHY has four 18904919Sxy150489 * possible cable length values, which are: 18914919Sxy150489 * Register Value Cable Length 18924919Sxy150489 * 0 < 50 meters 18934919Sxy150489 * 1 50 - 80 meters 18944919Sxy150489 * 2 80 - 110 meters 18954919Sxy150489 * 3 110 - 140 meters 18964919Sxy150489 * 4 > 140 meters 18974919Sxy150489 */ 18984919Sxy150489 s32 18994919Sxy150489 e1000_get_cable_length_m88(struct e1000_hw *hw) 19004919Sxy150489 { 19014919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 19024919Sxy150489 s32 ret_val; 19034919Sxy150489 u16 phy_data, index; 19044919Sxy150489 19054919Sxy150489 DEBUGFUNC("e1000_get_cable_length_m88"); 19064919Sxy150489 19076735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); 19084919Sxy150489 if (ret_val) 19094919Sxy150489 goto out; 19104919Sxy150489 19114919Sxy150489 index = (phy_data & M88E1000_PSSR_CABLE_LENGTH) >> 19124919Sxy150489 M88E1000_PSSR_CABLE_LENGTH_SHIFT; 19138479SChenlu.Chen@Sun.COM 1914*10680SMin.Xu@Sun.COM if (index >= M88E1000_CABLE_LENGTH_TABLE_SIZE - 1) { 19158479SChenlu.Chen@Sun.COM ret_val = E1000_ERR_PHY; 1916*10680SMin.Xu@Sun.COM goto out; 19178479SChenlu.Chen@Sun.COM } 1918*10680SMin.Xu@Sun.COM phy->min_cable_length = e1000_m88_cable_length_table[index]; 1919*10680SMin.Xu@Sun.COM phy->max_cable_length = e1000_m88_cable_length_table[index + 1]; 1920*10680SMin.Xu@Sun.COM 1921*10680SMin.Xu@Sun.COM phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; 19224919Sxy150489 19234919Sxy150489 out: 19244919Sxy150489 return (ret_val); 19254919Sxy150489 } 19264919Sxy150489 19274919Sxy150489 /* 19284919Sxy150489 * e1000_get_cable_length_igp_2 - Determine cable length for igp2 PHY 19294919Sxy150489 * @hw: pointer to the HW structure 19304919Sxy150489 * 19314919Sxy150489 * The automatic gain control (agc) normalizes the amplitude of the 19324919Sxy150489 * received signal, adjusting for the attenuation produced by the 19336735Scc210113 * cable. By reading the AGC registers, which represent the 19346735Scc210113 * combination of coarse and fine gain value, the value can be put 19354919Sxy150489 * into a lookup table to obtain the approximate cable length 19364919Sxy150489 * for each channel. 19374919Sxy150489 */ 19384919Sxy150489 s32 19394919Sxy150489 e1000_get_cable_length_igp_2(struct e1000_hw *hw) 19404919Sxy150489 { 19414919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 19426735Scc210113 s32 ret_val = E1000_SUCCESS; 19434919Sxy150489 u16 phy_data, i, agc_value = 0; 19444919Sxy150489 u16 cur_agc_index, max_agc_index = 0; 19454919Sxy150489 u16 min_agc_index = IGP02E1000_CABLE_LENGTH_TABLE_SIZE - 1; 19464919Sxy150489 u16 agc_reg_array[IGP02E1000_PHY_CHANNEL_NUM] = 19474919Sxy150489 {IGP02E1000_PHY_AGC_A, 19484919Sxy150489 IGP02E1000_PHY_AGC_B, 19494919Sxy150489 IGP02E1000_PHY_AGC_C, 19504919Sxy150489 IGP02E1000_PHY_AGC_D}; 19514919Sxy150489 19524919Sxy150489 DEBUGFUNC("e1000_get_cable_length_igp_2"); 19534919Sxy150489 19544919Sxy150489 /* Read the AGC registers for all channels */ 19554919Sxy150489 for (i = 0; i < IGP02E1000_PHY_CHANNEL_NUM; i++) { 19566735Scc210113 ret_val = phy->ops.read_reg(hw, agc_reg_array[i], &phy_data); 19574919Sxy150489 if (ret_val) 19584919Sxy150489 goto out; 19594919Sxy150489 19604919Sxy150489 /* 19614919Sxy150489 * Getting bits 15:9, which represent the combination of 19626735Scc210113 * coarse and fine gain values. The result is a number that 19634919Sxy150489 * can be put into the lookup table to obtain the approximate 19644919Sxy150489 * cable length. 19654919Sxy150489 */ 19664919Sxy150489 cur_agc_index = (phy_data >> IGP02E1000_AGC_LENGTH_SHIFT) & 19674919Sxy150489 IGP02E1000_AGC_LENGTH_MASK; 19684919Sxy150489 19694919Sxy150489 /* Array index bound check. */ 19704919Sxy150489 if ((cur_agc_index >= IGP02E1000_CABLE_LENGTH_TABLE_SIZE) || 19714919Sxy150489 (cur_agc_index == 0)) { 19724919Sxy150489 ret_val = -E1000_ERR_PHY; 19734919Sxy150489 goto out; 19744919Sxy150489 } 19754919Sxy150489 19764919Sxy150489 /* Remove min & max AGC values from calculation. */ 19774919Sxy150489 if (e1000_igp_2_cable_length_table[min_agc_index] > 19784919Sxy150489 e1000_igp_2_cable_length_table[cur_agc_index]) 19794919Sxy150489 min_agc_index = cur_agc_index; 19804919Sxy150489 if (e1000_igp_2_cable_length_table[max_agc_index] < 19814919Sxy150489 e1000_igp_2_cable_length_table[cur_agc_index]) 19824919Sxy150489 max_agc_index = cur_agc_index; 19834919Sxy150489 19844919Sxy150489 agc_value += e1000_igp_2_cable_length_table[cur_agc_index]; 19854919Sxy150489 } 19864919Sxy150489 19874919Sxy150489 agc_value -= (e1000_igp_2_cable_length_table[min_agc_index] + 19884919Sxy150489 e1000_igp_2_cable_length_table[max_agc_index]); 19894919Sxy150489 agc_value /= (IGP02E1000_PHY_CHANNEL_NUM - 2); 19904919Sxy150489 19914919Sxy150489 /* Calculate cable length with the error range of +/- 10 meters. */ 19924919Sxy150489 phy->min_cable_length = ((agc_value - IGP02E1000_AGC_RANGE) > 0) ? 19934919Sxy150489 (agc_value - IGP02E1000_AGC_RANGE) : 0; 19944919Sxy150489 phy->max_cable_length = agc_value + IGP02E1000_AGC_RANGE; 19954919Sxy150489 19964919Sxy150489 phy->cable_length = (phy->min_cable_length + phy->max_cable_length) / 2; 19974919Sxy150489 19984919Sxy150489 out: 19994919Sxy150489 return (ret_val); 20004919Sxy150489 } 20014919Sxy150489 20024919Sxy150489 /* 20034919Sxy150489 * e1000_get_phy_info_m88 - Retrieve PHY information 20044919Sxy150489 * @hw: pointer to the HW structure 20054919Sxy150489 * 20064919Sxy150489 * Valid for only copper links. Read the PHY status register (sticky read) 20074919Sxy150489 * to verify that link is up. Read the PHY special control register to 20084919Sxy150489 * determine the polarity and 10base-T extended distance. Read the PHY 20094919Sxy150489 * special status register to determine MDI/MDIx and current speed. If 20104919Sxy150489 * speed is 1000, then determine cable length, local and remote receiver. 20114919Sxy150489 */ 20124919Sxy150489 s32 20134919Sxy150489 e1000_get_phy_info_m88(struct e1000_hw *hw) 20144919Sxy150489 { 20154919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 20164919Sxy150489 s32 ret_val; 20174919Sxy150489 u16 phy_data; 20186735Scc210113 bool link; 20194919Sxy150489 20204919Sxy150489 DEBUGFUNC("e1000_get_phy_info_m88"); 20214919Sxy150489 20226735Scc210113 if (hw->phy.media_type != e1000_media_type_copper) { 20234919Sxy150489 DEBUGOUT("Phy info is only valid for copper media\n"); 20244919Sxy150489 ret_val = -E1000_ERR_CONFIG; 20254919Sxy150489 goto out; 20264919Sxy150489 } 20274919Sxy150489 20284919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 20294919Sxy150489 if (ret_val) 20304919Sxy150489 goto out; 20314919Sxy150489 20324919Sxy150489 if (!link) { 20334919Sxy150489 DEBUGOUT("Phy info is only valid if link is up\n"); 20344919Sxy150489 ret_val = -E1000_ERR_CONFIG; 20354919Sxy150489 goto out; 20364919Sxy150489 } 20374919Sxy150489 20386735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_CTRL, &phy_data); 20394919Sxy150489 if (ret_val) 20404919Sxy150489 goto out; 20414919Sxy150489 20424919Sxy150489 phy->polarity_correction = (phy_data & M88E1000_PSCR_POLARITY_REVERSAL) 20437607STed.You@Sun.COM ? true 20447607STed.You@Sun.COM : false; 20454919Sxy150489 20464919Sxy150489 ret_val = e1000_check_polarity_m88(hw); 20474919Sxy150489 if (ret_val) 20484919Sxy150489 goto out; 20494919Sxy150489 20506735Scc210113 ret_val = phy->ops.read_reg(hw, M88E1000_PHY_SPEC_STATUS, &phy_data); 20514919Sxy150489 if (ret_val) 20524919Sxy150489 goto out; 20534919Sxy150489 20547607STed.You@Sun.COM phy->is_mdix = (phy_data & M88E1000_PSSR_MDIX) ? true : false; 20554919Sxy150489 20564919Sxy150489 if ((phy_data & M88E1000_PSSR_SPEED) == M88E1000_PSSR_1000MBS) { 20577607STed.You@Sun.COM ret_val = hw->phy.ops.get_cable_length(hw); 20584919Sxy150489 if (ret_val) 20594919Sxy150489 goto out; 20604919Sxy150489 20616735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &phy_data); 20624919Sxy150489 if (ret_val) 20634919Sxy150489 goto out; 20644919Sxy150489 20654919Sxy150489 phy->local_rx = (phy_data & SR_1000T_LOCAL_RX_STATUS) 20664919Sxy150489 ? e1000_1000t_rx_status_ok 20674919Sxy150489 : e1000_1000t_rx_status_not_ok; 20684919Sxy150489 20694919Sxy150489 phy->remote_rx = (phy_data & SR_1000T_REMOTE_RX_STATUS) 20704919Sxy150489 ? e1000_1000t_rx_status_ok 20714919Sxy150489 : e1000_1000t_rx_status_not_ok; 20724919Sxy150489 } else { 20734919Sxy150489 /* Set values to "undefined" */ 20744919Sxy150489 phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; 20754919Sxy150489 phy->local_rx = e1000_1000t_rx_status_undefined; 20764919Sxy150489 phy->remote_rx = e1000_1000t_rx_status_undefined; 20774919Sxy150489 } 20784919Sxy150489 20794919Sxy150489 out: 20804919Sxy150489 return (ret_val); 20814919Sxy150489 } 20824919Sxy150489 20834919Sxy150489 /* 20844919Sxy150489 * e1000_get_phy_info_igp - Retrieve igp PHY information 20854919Sxy150489 * @hw: pointer to the HW structure 20864919Sxy150489 * 20874919Sxy150489 * Read PHY status to determine if link is up. If link is up, then 20884919Sxy150489 * set/determine 10base-T extended distance and polarity correction. Read 20894919Sxy150489 * PHY port status to determine MDI/MDIx and speed. Based on the speed, 20904919Sxy150489 * determine on the cable length, local and remote receiver. 20914919Sxy150489 */ 20924919Sxy150489 s32 20934919Sxy150489 e1000_get_phy_info_igp(struct e1000_hw *hw) 20944919Sxy150489 { 20954919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 20964919Sxy150489 s32 ret_val; 20974919Sxy150489 u16 data; 20986735Scc210113 bool link; 20994919Sxy150489 21004919Sxy150489 DEBUGFUNC("e1000_get_phy_info_igp"); 21014919Sxy150489 21024919Sxy150489 ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 21034919Sxy150489 if (ret_val) 21044919Sxy150489 goto out; 21054919Sxy150489 21064919Sxy150489 if (!link) { 21074919Sxy150489 DEBUGOUT("Phy info is only valid if link is up\n"); 21084919Sxy150489 ret_val = -E1000_ERR_CONFIG; 21094919Sxy150489 goto out; 21104919Sxy150489 } 21114919Sxy150489 21127607STed.You@Sun.COM phy->polarity_correction = true; 21134919Sxy150489 21144919Sxy150489 ret_val = e1000_check_polarity_igp(hw); 21154919Sxy150489 if (ret_val) 21164919Sxy150489 goto out; 21174919Sxy150489 21186735Scc210113 ret_val = phy->ops.read_reg(hw, IGP01E1000_PHY_PORT_STATUS, &data); 21194919Sxy150489 if (ret_val) 21204919Sxy150489 goto out; 21214919Sxy150489 21227607STed.You@Sun.COM phy->is_mdix = (data & IGP01E1000_PSSR_MDIX) ? true : false; 21234919Sxy150489 21244919Sxy150489 if ((data & IGP01E1000_PSSR_SPEED_MASK) == 21254919Sxy150489 IGP01E1000_PSSR_SPEED_1000MBPS) { 21267607STed.You@Sun.COM ret_val = hw->phy.ops.get_cable_length(hw); 21274919Sxy150489 if (ret_val) 21284919Sxy150489 goto out; 21294919Sxy150489 21306735Scc210113 ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); 21314919Sxy150489 if (ret_val) 21324919Sxy150489 goto out; 21334919Sxy150489 21344919Sxy150489 phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) 21354919Sxy150489 ? e1000_1000t_rx_status_ok 21364919Sxy150489 : e1000_1000t_rx_status_not_ok; 21374919Sxy150489 21384919Sxy150489 phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) 21394919Sxy150489 ? e1000_1000t_rx_status_ok 21404919Sxy150489 : e1000_1000t_rx_status_not_ok; 21414919Sxy150489 } else { 21424919Sxy150489 phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; 21434919Sxy150489 phy->local_rx = e1000_1000t_rx_status_undefined; 21444919Sxy150489 phy->remote_rx = e1000_1000t_rx_status_undefined; 21454919Sxy150489 } 21464919Sxy150489 21474919Sxy150489 out: 21484919Sxy150489 return (ret_val); 21494919Sxy150489 } 21504919Sxy150489 21514919Sxy150489 /* 21524919Sxy150489 * e1000_phy_sw_reset_generic - PHY software reset 21534919Sxy150489 * @hw: pointer to the HW structure 21544919Sxy150489 * 21554919Sxy150489 * Does a software reset of the PHY by reading the PHY control register and 21564919Sxy150489 * setting/write the control register reset bit to the PHY. 21574919Sxy150489 */ 21584919Sxy150489 s32 21594919Sxy150489 e1000_phy_sw_reset_generic(struct e1000_hw *hw) 21604919Sxy150489 { 21616735Scc210113 s32 ret_val = E1000_SUCCESS; 21624919Sxy150489 u16 phy_ctrl; 21634919Sxy150489 21644919Sxy150489 DEBUGFUNC("e1000_phy_sw_reset_generic"); 21654919Sxy150489 21666735Scc210113 if (!(hw->phy.ops.read_reg)) 21676735Scc210113 goto out; 21686735Scc210113 21696735Scc210113 ret_val = hw->phy.ops.read_reg(hw, PHY_CONTROL, &phy_ctrl); 21704919Sxy150489 if (ret_val) 21714919Sxy150489 goto out; 21724919Sxy150489 21734919Sxy150489 phy_ctrl |= MII_CR_RESET; 21746735Scc210113 ret_val = hw->phy.ops.write_reg(hw, PHY_CONTROL, phy_ctrl); 21754919Sxy150489 if (ret_val) 21764919Sxy150489 goto out; 21774919Sxy150489 21784919Sxy150489 usec_delay(1); 21794919Sxy150489 21804919Sxy150489 out: 21814919Sxy150489 return (ret_val); 21824919Sxy150489 } 21834919Sxy150489 21844919Sxy150489 /* 21854919Sxy150489 * e1000_phy_hw_reset_generic - PHY hardware reset 21864919Sxy150489 * @hw: pointer to the HW structure 21874919Sxy150489 * 21884919Sxy150489 * Verify the reset block is not blocking us from resetting. Acquire 21894919Sxy150489 * semaphore (if necessary) and read/set/write the device control reset 21904919Sxy150489 * bit in the PHY. Wait the appropriate delay time for the device to 21916735Scc210113 * reset and release the semaphore (if necessary). 21924919Sxy150489 */ 21934919Sxy150489 s32 21944919Sxy150489 e1000_phy_hw_reset_generic(struct e1000_hw *hw) 21954919Sxy150489 { 21964919Sxy150489 struct e1000_phy_info *phy = &hw->phy; 21976735Scc210113 s32 ret_val = E1000_SUCCESS; 21984919Sxy150489 u32 ctrl; 21994919Sxy150489 22004919Sxy150489 DEBUGFUNC("e1000_phy_hw_reset_generic"); 22014919Sxy150489 22026735Scc210113 ret_val = phy->ops.check_reset_block(hw); 22034919Sxy150489 if (ret_val) { 22044919Sxy150489 ret_val = E1000_SUCCESS; 22054919Sxy150489 goto out; 22064919Sxy150489 } 22074919Sxy150489 22086735Scc210113 ret_val = phy->ops.acquire(hw); 22094919Sxy150489 if (ret_val) 22104919Sxy150489 goto out; 22114919Sxy150489 22124919Sxy150489 ctrl = E1000_READ_REG(hw, E1000_CTRL); 22134919Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL, ctrl | E1000_CTRL_PHY_RST); 22144919Sxy150489 E1000_WRITE_FLUSH(hw); 22154919Sxy150489 22164919Sxy150489 usec_delay(phy->reset_delay_us); 22174919Sxy150489 22184919Sxy150489 E1000_WRITE_REG(hw, E1000_CTRL, ctrl); 22194919Sxy150489 E1000_WRITE_FLUSH(hw); 22204919Sxy150489 22214919Sxy150489 usec_delay(150); 22224919Sxy150489 22236735Scc210113 phy->ops.release(hw); 22244919Sxy150489 22256735Scc210113 ret_val = phy->ops.get_cfg_done(hw); 22264919Sxy150489 22274919Sxy150489 out: 22284919Sxy150489 return (ret_val); 22294919Sxy150489 } 22304919Sxy150489 22314919Sxy150489 /* 22324919Sxy150489 * e1000_get_cfg_done_generic - Generic configuration done 22334919Sxy150489 * @hw: pointer to the HW structure 22344919Sxy150489 * 22354919Sxy150489 * Generic function to wait 10 milli-seconds for configuration to complete 22364919Sxy150489 * and return success. 22374919Sxy150489 */ 22384919Sxy150489 s32 22394919Sxy150489 e1000_get_cfg_done_generic(struct e1000_hw *hw) 22404919Sxy150489 { 22414919Sxy150489 DEBUGFUNC("e1000_get_cfg_done_generic"); 22426735Scc210113 UNREFERENCED_1PARAMETER(hw); 22434919Sxy150489 22444919Sxy150489 msec_delay_irq(10); 22454919Sxy150489 22464919Sxy150489 return (E1000_SUCCESS); 22474919Sxy150489 } 22484919Sxy150489 22494919Sxy150489 /* 22504919Sxy150489 * e1000_phy_init_script_igp3 - Inits the IGP3 PHY 22514919Sxy150489 * @hw: pointer to the HW structure 22524919Sxy150489 * 22534919Sxy150489 * Initializes a Intel Gigabit PHY3 when an EEPROM is not present. 22544919Sxy150489 */ 22554919Sxy150489 s32 22564919Sxy150489 e1000_phy_init_script_igp3(struct e1000_hw *hw) 22574919Sxy150489 { 22584919Sxy150489 DEBUGOUT("Running IGP 3 PHY init script\n"); 22594919Sxy150489 22604919Sxy150489 /* PHY init IGP 3 */ 22614919Sxy150489 /* Enable rise/fall, 10-mode work in class-A */ 22626735Scc210113 hw->phy.ops.write_reg(hw, 0x2F5B, 0x9018); 22634919Sxy150489 /* Remove all caps from Replica path filter */ 22646735Scc210113 hw->phy.ops.write_reg(hw, 0x2F52, 0x0000); 22654919Sxy150489 /* Bias trimming for ADC, AFE and Driver (Default) */ 22666735Scc210113 hw->phy.ops.write_reg(hw, 0x2FB1, 0x8B24); 22674919Sxy150489 /* Increase Hybrid poly bias */ 22686735Scc210113 hw->phy.ops.write_reg(hw, 0x2FB2, 0xF8F0); 22694919Sxy150489 /* Add 4% to TX amplitude in Giga mode */ 22706735Scc210113 hw->phy.ops.write_reg(hw, 0x2010, 0x10B0); 22714919Sxy150489 /* Disable trimming (TTT) */ 22726735Scc210113 hw->phy.ops.write_reg(hw, 0x2011, 0x0000); 22734919Sxy150489 /* Poly DC correction to 94.6% + 2% for all channels */ 22746735Scc210113 hw->phy.ops.write_reg(hw, 0x20DD, 0x249A); 22754919Sxy150489 /* ABS DC correction to 95.9% */ 22766735Scc210113 hw->phy.ops.write_reg(hw, 0x20DE, 0x00D3); 22774919Sxy150489 /* BG temp curve trim */ 22786735Scc210113 hw->phy.ops.write_reg(hw, 0x28B4, 0x04CE); 22794919Sxy150489 /* Increasing ADC OPAMP stage 1 currents to max */ 22806735Scc210113 hw->phy.ops.write_reg(hw, 0x2F70, 0x29E4); 22814919Sxy150489 /* Force 1000 ( required for enabling PHY regs configuration) */ 22826735Scc210113 hw->phy.ops.write_reg(hw, 0x0000, 0x0140); 22834919Sxy150489 /* Set upd_freq to 6 */ 22846735Scc210113 hw->phy.ops.write_reg(hw, 0x1F30, 0x1606); 22854919Sxy150489 /* Disable NPDFE */ 22866735Scc210113 hw->phy.ops.write_reg(hw, 0x1F31, 0xB814); 22874919Sxy150489 /* Disable adaptive fixed FFE (Default) */ 22886735Scc210113 hw->phy.ops.write_reg(hw, 0x1F35, 0x002A); 22894919Sxy150489 /* Enable FFE hysteresis */ 22906735Scc210113 hw->phy.ops.write_reg(hw, 0x1F3E, 0x0067); 22914919Sxy150489 /* Fixed FFE for short cable lengths */ 22926735Scc210113 hw->phy.ops.write_reg(hw, 0x1F54, 0x0065); 22934919Sxy150489 /* Fixed FFE for medium cable lengths */ 22946735Scc210113 hw->phy.ops.write_reg(hw, 0x1F55, 0x002A); 22954919Sxy150489 /* Fixed FFE for long cable lengths */ 22966735Scc210113 hw->phy.ops.write_reg(hw, 0x1F56, 0x002A); 22974919Sxy150489 /* Enable Adaptive Clip Threshold */ 22986735Scc210113 hw->phy.ops.write_reg(hw, 0x1F72, 0x3FB0); 22994919Sxy150489 /* AHT reset limit to 1 */ 23006735Scc210113 hw->phy.ops.write_reg(hw, 0x1F76, 0xC0FF); 23014919Sxy150489 /* Set AHT master delay to 127 msec */ 23026735Scc210113 hw->phy.ops.write_reg(hw, 0x1F77, 0x1DEC); 23034919Sxy150489 /* Set scan bits for AHT */ 23046735Scc210113 hw->phy.ops.write_reg(hw, 0x1F78, 0xF9EF); 23054919Sxy150489 /* Set AHT Preset bits */ 23066735Scc210113 hw->phy.ops.write_reg(hw, 0x1F79, 0x0210); 23074919Sxy150489 /* Change integ_factor of channel A to 3 */ 23086735Scc210113 hw->phy.ops.write_reg(hw, 0x1895, 0x0003); 23094919Sxy150489 /* Change prop_factor of channels BCD to 8 */ 23106735Scc210113 hw->phy.ops.write_reg(hw, 0x1796, 0x0008); 23114919Sxy150489 /* Change cg_icount + enable integbp for channels BCD */ 23126735Scc210113 hw->phy.ops.write_reg(hw, 0x1798, 0xD008); 23134919Sxy150489 /* 23144919Sxy150489 * Change cg_icount + enable integbp + change prop_factor_master to 8 23154919Sxy150489 * for channel A 23164919Sxy150489 */ 23176735Scc210113 hw->phy.ops.write_reg(hw, 0x1898, 0xD918); 23184919Sxy150489 /* Disable AHT in Slave mode on channel A */ 23196735Scc210113 hw->phy.ops.write_reg(hw, 0x187A, 0x0800); 23204919Sxy150489 /* 23214919Sxy150489 * Enable LPLU and disable AN to 1000 in non-D0a states, Enable 23224919Sxy150489 * SPD+B2B 23234919Sxy150489 */ 23246735Scc210113 hw->phy.ops.write_reg(hw, 0x0019, 0x008D); 23254919Sxy150489 /* Enable restart AN on an1000_dis change */ 23266735Scc210113 hw->phy.ops.write_reg(hw, 0x001B, 0x2080); 23274919Sxy150489 /* Enable wh_fifo read clock in 10/100 modes */ 23286735Scc210113 hw->phy.ops.write_reg(hw, 0x0014, 0x0045); 23294919Sxy150489 /* Restart AN, Speed selection is 1000 */ 23306735Scc210113 hw->phy.ops.write_reg(hw, 0x0000, 0x1340); 23314919Sxy150489 23324919Sxy150489 return (E1000_SUCCESS); 23334919Sxy150489 } 23344919Sxy150489 23354919Sxy150489 /* 23364919Sxy150489 * e1000_get_phy_type_from_id - Get PHY type from id 23374919Sxy150489 * @phy_id: phy_id read from the phy 23384919Sxy150489 * 23394919Sxy150489 * Returns the phy type from the id. 23404919Sxy150489 */ 23418479SChenlu.Chen@Sun.COM enum e1000_phy_type 23424919Sxy150489 e1000_get_phy_type_from_id(u32 phy_id) 23434919Sxy150489 { 23448479SChenlu.Chen@Sun.COM enum e1000_phy_type phy_type = e1000_phy_unknown; 23454919Sxy150489 23464919Sxy150489 switch (phy_id) { 23474919Sxy150489 case M88E1000_I_PHY_ID: 23484919Sxy150489 case M88E1000_E_PHY_ID: 23494919Sxy150489 case M88E1111_I_PHY_ID: 23504919Sxy150489 case M88E1011_I_PHY_ID: 23514919Sxy150489 phy_type = e1000_phy_m88; 23524919Sxy150489 break; 23534919Sxy150489 case IGP01E1000_I_PHY_ID: /* IGP 1 & 2 share this */ 23544919Sxy150489 phy_type = e1000_phy_igp_2; 23554919Sxy150489 break; 23564919Sxy150489 case GG82563_E_PHY_ID: 23574919Sxy150489 phy_type = e1000_phy_gg82563; 23584919Sxy150489 break; 23594919Sxy150489 case IGP03E1000_E_PHY_ID: 23604919Sxy150489 phy_type = e1000_phy_igp_3; 23614919Sxy150489 break; 23624919Sxy150489 case IFE_E_PHY_ID: 23634919Sxy150489 case IFE_PLUS_E_PHY_ID: 23644919Sxy150489 case IFE_C_E_PHY_ID: 23654919Sxy150489 phy_type = e1000_phy_ife; 23664919Sxy150489 break; 23674919Sxy150489 case BME1000_E_PHY_ID: 23686735Scc210113 case BME1000_E_PHY_ID_R2: 23694919Sxy150489 phy_type = e1000_phy_bm; 23704919Sxy150489 break; 2371*10680SMin.Xu@Sun.COM case I82578_E_PHY_ID: 2372*10680SMin.Xu@Sun.COM phy_type = e1000_phy_82578; 2373*10680SMin.Xu@Sun.COM break; 2374*10680SMin.Xu@Sun.COM case I82577_E_PHY_ID: 2375*10680SMin.Xu@Sun.COM phy_type = e1000_phy_82577; 2376*10680SMin.Xu@Sun.COM break; 23774919Sxy150489 default: 23784919Sxy150489 phy_type = e1000_phy_unknown; 23794919Sxy150489 break; 23804919Sxy150489 } 23814919Sxy150489 return (phy_type); 23824919Sxy150489 } 23834919Sxy150489 23844919Sxy150489 /* 23854919Sxy150489 * e1000_determine_phy_address - Determines PHY address. 23864919Sxy150489 * @hw: pointer to the HW structure 23874919Sxy150489 * 23884919Sxy150489 * This uses a trial and error method to loop through possible PHY 23894919Sxy150489 * addresses. It tests each by reading the PHY ID registers and 23904919Sxy150489 * checking for a match. 23914919Sxy150489 */ 23924919Sxy150489 s32 23934919Sxy150489 e1000_determine_phy_address(struct e1000_hw *hw) 23944919Sxy150489 { 23954919Sxy150489 s32 ret_val = -E1000_ERR_PHY_TYPE; 23964919Sxy150489 u32 phy_addr = 0; 23976735Scc210113 u32 i; 23988479SChenlu.Chen@Sun.COM enum e1000_phy_type phy_type = e1000_phy_unknown; 23994919Sxy150489 2400*10680SMin.Xu@Sun.COM hw->phy.id = phy_type; 2401*10680SMin.Xu@Sun.COM 24026735Scc210113 for (phy_addr = 0; phy_addr < E1000_MAX_PHY_ADDR; phy_addr++) { 24034919Sxy150489 hw->phy.addr = phy_addr; 24046735Scc210113 i = 0; 24056735Scc210113 24066735Scc210113 do { 24077426SChenliang.Xu@Sun.COM (void) e1000_get_phy_id(hw); 24086735Scc210113 phy_type = e1000_get_phy_type_from_id(hw->phy.id); 24094919Sxy150489 24106735Scc210113 /* 24116735Scc210113 * If phy_type is valid, break - we found our 24126735Scc210113 * PHY address 24136735Scc210113 */ 24146735Scc210113 if (phy_type != e1000_phy_unknown) { 24156735Scc210113 ret_val = E1000_SUCCESS; 24166735Scc210113 goto out; 24176735Scc210113 } 24186735Scc210113 msec_delay(1); 24196735Scc210113 i++; 24206735Scc210113 } while (i < 10); 24214919Sxy150489 } 24224919Sxy150489 24236735Scc210113 out: 24244919Sxy150489 return (ret_val); 24254919Sxy150489 } 24264919Sxy150489 24274919Sxy150489 /* 24284919Sxy150489 * e1000_get_phy_addr_for_bm_page - Retrieve PHY page address 24294919Sxy150489 * @page: page to access 24304919Sxy150489 * 24314919Sxy150489 * Returns the phy address for the page requested. 24324919Sxy150489 */ 24334919Sxy150489 static u32 24344919Sxy150489 e1000_get_phy_addr_for_bm_page(u32 page, u32 reg) 24354919Sxy150489 { 24364919Sxy150489 u32 phy_addr = 2; 24374919Sxy150489 24384919Sxy150489 if ((page >= 768) || (page == 0 && reg == 25) || (reg == 31)) 24394919Sxy150489 phy_addr = 1; 24404919Sxy150489 24414919Sxy150489 return (phy_addr); 24424919Sxy150489 } 24434919Sxy150489 24444919Sxy150489 /* 24454919Sxy150489 * e1000_write_phy_reg_bm - Write BM PHY register 24464919Sxy150489 * @hw: pointer to the HW structure 24474919Sxy150489 * @offset: register offset to write to 24484919Sxy150489 * @data: data to write at register offset 24494919Sxy150489 * 24504919Sxy150489 * Acquires semaphore, if necessary, then writes the data to PHY register 24514919Sxy150489 * at the offset. Release any acquired semaphores before exiting. 24524919Sxy150489 */ 24534919Sxy150489 s32 24544919Sxy150489 e1000_write_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 data) 24554919Sxy150489 { 24564919Sxy150489 s32 ret_val; 24574919Sxy150489 u32 page_select = 0; 24584919Sxy150489 u32 page = offset >> IGP_PAGE_SHIFT; 24594919Sxy150489 u32 page_shift = 0; 24604919Sxy150489 24614919Sxy150489 DEBUGFUNC("e1000_write_phy_reg_bm"); 24624919Sxy150489 24634919Sxy150489 /* Page 800 works differently than the rest so it has its own func */ 24644919Sxy150489 if (page == BM_WUC_PAGE) { 24654919Sxy150489 ret_val = e1000_access_phy_wakeup_reg_bm(hw, 24667607STed.You@Sun.COM offset, &data, false); 24674919Sxy150489 goto out; 24684919Sxy150489 } 24696735Scc210113 ret_val = hw->phy.ops.acquire(hw); 24704919Sxy150489 if (ret_val) 24714919Sxy150489 goto out; 24724919Sxy150489 24734919Sxy150489 hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); 24744919Sxy150489 24754919Sxy150489 if (offset > MAX_PHY_MULTI_PAGE_REG) { 24764919Sxy150489 /* 24774919Sxy150489 * Page select is register 31 for phy address 1 and 22 for phy 24784919Sxy150489 * address 2 and 3. Page select is shifted only for phy 24794919Sxy150489 * address 1. 24804919Sxy150489 */ 24814919Sxy150489 if (hw->phy.addr == 1) { 24824919Sxy150489 page_shift = IGP_PAGE_SHIFT; 24834919Sxy150489 page_select = IGP01E1000_PHY_PAGE_SELECT; 24844919Sxy150489 } else { 24854919Sxy150489 page_shift = 0; 24864919Sxy150489 page_select = BM_PHY_PAGE_SELECT; 24874919Sxy150489 } 24884919Sxy150489 24894919Sxy150489 /* Page is shifted left, PHY expects (page x 32) */ 24904919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, page_select, 24914919Sxy150489 (page << page_shift)); 24924919Sxy150489 if (ret_val) { 24936735Scc210113 hw->phy.ops.release(hw); 24944919Sxy150489 goto out; 24954919Sxy150489 } 24964919Sxy150489 } 24974919Sxy150489 24984919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, 24994919Sxy150489 MAX_PHY_REG_ADDRESS & offset, 25004919Sxy150489 data); 25014919Sxy150489 25026735Scc210113 hw->phy.ops.release(hw); 25034919Sxy150489 25044919Sxy150489 out: 25054919Sxy150489 return (ret_val); 25064919Sxy150489 } 25074919Sxy150489 25084919Sxy150489 /* 25094919Sxy150489 * e1000_read_phy_reg_bm - Read BM PHY register 25104919Sxy150489 * @hw: pointer to the HW structure 25114919Sxy150489 * @offset: register offset to be read 25124919Sxy150489 * @data: pointer to the read data 25134919Sxy150489 * 25144919Sxy150489 * Acquires semaphore, if necessary, then reads the PHY register at offset 25154919Sxy150489 * and storing the retrieved information in data. Release any acquired 25164919Sxy150489 * semaphores before exiting. 25174919Sxy150489 */ 25184919Sxy150489 s32 25194919Sxy150489 e1000_read_phy_reg_bm(struct e1000_hw *hw, u32 offset, u16 *data) 25204919Sxy150489 { 25214919Sxy150489 s32 ret_val; 25224919Sxy150489 u32 page_select = 0; 25234919Sxy150489 u32 page = offset >> IGP_PAGE_SHIFT; 25244919Sxy150489 u32 page_shift = 0; 25254919Sxy150489 25266735Scc210113 DEBUGFUNC("e1000_read_phy_reg_bm"); 25274919Sxy150489 25284919Sxy150489 /* Page 800 works differently than the rest so it has its own func */ 25294919Sxy150489 if (page == BM_WUC_PAGE) { 25304919Sxy150489 ret_val = e1000_access_phy_wakeup_reg_bm(hw, 25317607STed.You@Sun.COM offset, data, true); 25324919Sxy150489 goto out; 25334919Sxy150489 } 25346735Scc210113 ret_val = hw->phy.ops.acquire(hw); 25354919Sxy150489 if (ret_val) 25364919Sxy150489 goto out; 25374919Sxy150489 25384919Sxy150489 hw->phy.addr = e1000_get_phy_addr_for_bm_page(page, offset); 25394919Sxy150489 25404919Sxy150489 if (offset > MAX_PHY_MULTI_PAGE_REG) { 25414919Sxy150489 /* 25424919Sxy150489 * Page select is register 31 for phy address 1 and 22 for phy 25434919Sxy150489 * address 2 and 3. Page select is shifted only for phy 25444919Sxy150489 * address 1. 25454919Sxy150489 */ 25464919Sxy150489 if (hw->phy.addr == 1) { 25474919Sxy150489 page_shift = IGP_PAGE_SHIFT; 25484919Sxy150489 page_select = IGP01E1000_PHY_PAGE_SELECT; 25494919Sxy150489 } else { 25504919Sxy150489 page_shift = 0; 25514919Sxy150489 page_select = BM_PHY_PAGE_SELECT; 25524919Sxy150489 } 25534919Sxy150489 25544919Sxy150489 /* Page is shifted left, PHY expects (page x 32) */ 25554919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, page_select, 25564919Sxy150489 (page << page_shift)); 25574919Sxy150489 if (ret_val) { 25586735Scc210113 hw->phy.ops.release(hw); 25594919Sxy150489 goto out; 25604919Sxy150489 } 25614919Sxy150489 } 25624919Sxy150489 25634919Sxy150489 ret_val = e1000_read_phy_reg_mdic(hw, 25644919Sxy150489 MAX_PHY_REG_ADDRESS & offset, 25654919Sxy150489 data); 25666735Scc210113 hw->phy.ops.release(hw); 25674919Sxy150489 25684919Sxy150489 out: 25694919Sxy150489 return (ret_val); 25704919Sxy150489 } 25714919Sxy150489 25724919Sxy150489 /* 25737607STed.You@Sun.COM * e1000_read_phy_reg_bm2 - Read BM PHY register 25747607STed.You@Sun.COM * @hw: pointer to the HW structure 25757607STed.You@Sun.COM * @offset: register offset to be read 25767607STed.You@Sun.COM * @data: pointer to the read data 25777607STed.You@Sun.COM * 25787607STed.You@Sun.COM * Acquires semaphore, if necessary, then reads the PHY register at offset 25797607STed.You@Sun.COM * and storing the retrieved information in data. Release any acquired 25807607STed.You@Sun.COM * semaphores before exiting. 25817607STed.You@Sun.COM */ 25827607STed.You@Sun.COM s32 25837607STed.You@Sun.COM e1000_read_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 *data) 25847607STed.You@Sun.COM { 25857607STed.You@Sun.COM s32 ret_val; 25867607STed.You@Sun.COM u16 page = (u16)(offset >> IGP_PAGE_SHIFT); 25877607STed.You@Sun.COM 25887607STed.You@Sun.COM DEBUGFUNC("e1000_write_phy_reg_bm2"); 25897607STed.You@Sun.COM 25907607STed.You@Sun.COM /* Page 800 works differently than the rest so it has its own func */ 25917607STed.You@Sun.COM if (page == BM_WUC_PAGE) { 25927607STed.You@Sun.COM ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, data, 25937607STed.You@Sun.COM true); 25947607STed.You@Sun.COM goto out; 25957607STed.You@Sun.COM } 25967607STed.You@Sun.COM 25977607STed.You@Sun.COM ret_val = hw->phy.ops.acquire(hw); 25987607STed.You@Sun.COM if (ret_val) 25997607STed.You@Sun.COM goto out; 26007607STed.You@Sun.COM 26017607STed.You@Sun.COM hw->phy.addr = 1; 26027607STed.You@Sun.COM 26037607STed.You@Sun.COM if (offset > MAX_PHY_MULTI_PAGE_REG) { 26047607STed.You@Sun.COM 26057607STed.You@Sun.COM /* Page is shifted left, PHY expects (page x 32) */ 26067607STed.You@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, 26077607STed.You@Sun.COM page); 26087607STed.You@Sun.COM 26097607STed.You@Sun.COM if (ret_val) { 26107607STed.You@Sun.COM hw->phy.ops.release(hw); 26117607STed.You@Sun.COM goto out; 26127607STed.You@Sun.COM } 26137607STed.You@Sun.COM } 26147607STed.You@Sun.COM 26157607STed.You@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, 26167607STed.You@Sun.COM data); 26177607STed.You@Sun.COM hw->phy.ops.release(hw); 26187607STed.You@Sun.COM 26197607STed.You@Sun.COM out: 26207607STed.You@Sun.COM return (ret_val); 26217607STed.You@Sun.COM } 26227607STed.You@Sun.COM 26237607STed.You@Sun.COM /* 26247607STed.You@Sun.COM * e1000_write_phy_reg_bm2 - Write BM PHY register 26257607STed.You@Sun.COM * @hw: pointer to the HW structure 26267607STed.You@Sun.COM * @offset: register offset to write to 26277607STed.You@Sun.COM * @data: data to write at register offset 26287607STed.You@Sun.COM * 26297607STed.You@Sun.COM * Acquires semaphore, if necessary, then writes the data to PHY register 26307607STed.You@Sun.COM * at the offset. Release any acquired semaphores before exiting. 26317607STed.You@Sun.COM */ 26327607STed.You@Sun.COM s32 26337607STed.You@Sun.COM e1000_write_phy_reg_bm2(struct e1000_hw *hw, u32 offset, u16 data) 26347607STed.You@Sun.COM { 26357607STed.You@Sun.COM s32 ret_val; 26367607STed.You@Sun.COM u16 page = (u16)(offset >> IGP_PAGE_SHIFT); 26377607STed.You@Sun.COM 26387607STed.You@Sun.COM DEBUGFUNC("e1000_write_phy_reg_bm2"); 26397607STed.You@Sun.COM 26407607STed.You@Sun.COM /* Page 800 works differently than the rest so it has its own func */ 26417607STed.You@Sun.COM if (page == BM_WUC_PAGE) { 26427607STed.You@Sun.COM ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, &data, 26437607STed.You@Sun.COM false); 26447607STed.You@Sun.COM goto out; 26457607STed.You@Sun.COM } 26467607STed.You@Sun.COM 26477607STed.You@Sun.COM ret_val = hw->phy.ops.acquire(hw); 26487607STed.You@Sun.COM if (ret_val) 26497607STed.You@Sun.COM goto out; 26507607STed.You@Sun.COM 26517607STed.You@Sun.COM hw->phy.addr = 1; 26527607STed.You@Sun.COM 26537607STed.You@Sun.COM if (offset > MAX_PHY_MULTI_PAGE_REG) { 26547607STed.You@Sun.COM /* Page is shifted left, PHY expects (page x 32) */ 26557607STed.You@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, BM_PHY_PAGE_SELECT, 26567607STed.You@Sun.COM page); 26577607STed.You@Sun.COM 26587607STed.You@Sun.COM if (ret_val) { 26597607STed.You@Sun.COM hw->phy.ops.release(hw); 26607607STed.You@Sun.COM goto out; 26617607STed.You@Sun.COM } 26627607STed.You@Sun.COM } 26637607STed.You@Sun.COM 26647607STed.You@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & offset, 26657607STed.You@Sun.COM data); 26667607STed.You@Sun.COM 26677607STed.You@Sun.COM hw->phy.ops.release(hw); 26687607STed.You@Sun.COM 26697607STed.You@Sun.COM out: 26707607STed.You@Sun.COM return (ret_val); 26717607STed.You@Sun.COM } 26727607STed.You@Sun.COM 26737607STed.You@Sun.COM /* 26744919Sxy150489 * e1000_access_phy_wakeup_reg_bm - Read BM PHY wakeup register 26754919Sxy150489 * @hw: pointer to the HW structure 26764919Sxy150489 * @offset: register offset to be read or written 26774919Sxy150489 * @data: pointer to the data to read or write 26784919Sxy150489 * @read: determines if operation is read or write 26794919Sxy150489 * 26804919Sxy150489 * Acquires semaphore, if necessary, then reads the PHY register at offset 26814919Sxy150489 * and storing the retrieved information in data. Release any acquired 26824919Sxy150489 * semaphores before exiting. Note that procedure to read the wakeup 26834919Sxy150489 * registers are different. It works as such: 26844919Sxy150489 * 1) Set page 769, register 17, bit 2 = 1 26854919Sxy150489 * 2) Set page to 800 for host (801 if we were manageability) 26864919Sxy150489 * 3) Write the address using the address opcode (0x11) 26874919Sxy150489 * 4) Read or write the data using the data opcode (0x12) 26884919Sxy150489 * 5) Restore 769_17.2 to its original value 26894919Sxy150489 */ 26908479SChenlu.Chen@Sun.COM static s32 26914919Sxy150489 e1000_access_phy_wakeup_reg_bm(struct e1000_hw *hw, 26926735Scc210113 u32 offset, u16 *data, bool read) 26934919Sxy150489 { 26944919Sxy150489 s32 ret_val; 2695*10680SMin.Xu@Sun.COM u16 reg = BM_PHY_REG_NUM(offset); 26964919Sxy150489 u16 phy_reg = 0; 26974919Sxy150489 u8 phy_acquired = 1; 26984919Sxy150489 2699*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_access_phy_wakeup_reg_bm"); 2700*10680SMin.Xu@Sun.COM 2701*10680SMin.Xu@Sun.COM /* Gig must be disabled for MDIO accesses to page 800 */ 2702*10680SMin.Xu@Sun.COM if ((hw->mac.type == e1000_pchlan) && 2703*10680SMin.Xu@Sun.COM (!(E1000_READ_REG(hw, E1000_PHY_CTRL) & 2704*10680SMin.Xu@Sun.COM E1000_PHY_CTRL_GBE_DISABLE))) 2705*10680SMin.Xu@Sun.COM DEBUGOUT("Attempting to access page 800 while gig enabled.\n"); 27064919Sxy150489 27076735Scc210113 ret_val = hw->phy.ops.acquire(hw); 27084919Sxy150489 if (ret_val) { 27096735Scc210113 DEBUGOUT("Could not acquire PHY\n"); 27104919Sxy150489 phy_acquired = 0; 27114919Sxy150489 goto out; 27124919Sxy150489 } 27134919Sxy150489 27144919Sxy150489 /* All operations in this function are phy address 1 */ 27154919Sxy150489 hw->phy.addr = 1; 27164919Sxy150489 27174919Sxy150489 /* Set page 769 */ 27187426SChenliang.Xu@Sun.COM (void) e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 27194919Sxy150489 (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); 27204919Sxy150489 27214919Sxy150489 ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, &phy_reg); 27224919Sxy150489 if (ret_val) { 27236735Scc210113 DEBUGOUT("Could not read PHY page 769\n"); 27244919Sxy150489 goto out; 27254919Sxy150489 } 27264919Sxy150489 27274919Sxy150489 /* First clear bit 4 to avoid a power state change */ 27284919Sxy150489 phy_reg &= ~(BM_WUC_HOST_WU_BIT); 27294919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); 27304919Sxy150489 if (ret_val) { 27316735Scc210113 DEBUGOUT("Could not clear PHY page 769 bit 4\n"); 27324919Sxy150489 goto out; 27334919Sxy150489 } 27344919Sxy150489 27354919Sxy150489 /* Write bit 2 = 1, and clear bit 4 to 769_17 */ 27364919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, 27374919Sxy150489 phy_reg | BM_WUC_ENABLE_BIT); 27384919Sxy150489 if (ret_val) { 27396735Scc210113 DEBUGOUT("Could not write PHY page 769 bit 2\n"); 27404919Sxy150489 goto out; 27414919Sxy150489 } 27424919Sxy150489 27434919Sxy150489 /* Select page 800 */ 27444919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, 27454919Sxy150489 IGP01E1000_PHY_PAGE_SELECT, 27464919Sxy150489 (BM_WUC_PAGE << IGP_PAGE_SHIFT)); 27474919Sxy150489 27484919Sxy150489 /* Write the page 800 offset value using opcode 0x11 */ 27494919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ADDRESS_OPCODE, reg); 27504919Sxy150489 if (ret_val) { 27516735Scc210113 DEBUGOUT("Could not write address opcode to page 800\n"); 27524919Sxy150489 goto out; 27534919Sxy150489 } 27544919Sxy150489 27554919Sxy150489 if (read) { 27564919Sxy150489 /* Read the page 800 value using opcode 0x12 */ 27574919Sxy150489 ret_val = e1000_read_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, 27584919Sxy150489 data); 27594919Sxy150489 } else { 2760*10680SMin.Xu@Sun.COM /* Write the page 800 value using opcode 0x12 */ 27614919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_DATA_OPCODE, 27624919Sxy150489 *data); 27634919Sxy150489 } 27644919Sxy150489 27654919Sxy150489 if (ret_val) { 2766*10680SMin.Xu@Sun.COM DEBUGOUT("Could not access data value from page 800\n"); 27674919Sxy150489 goto out; 27684919Sxy150489 } 27694919Sxy150489 27704919Sxy150489 /* 27714919Sxy150489 * Restore 769_17.2 to its original value Set page 769 27724919Sxy150489 */ 27737426SChenliang.Xu@Sun.COM (void) e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 27744919Sxy150489 (BM_WUC_ENABLE_PAGE << IGP_PAGE_SHIFT)); 27754919Sxy150489 27764919Sxy150489 /* Clear 769_17.2 */ 27774919Sxy150489 ret_val = e1000_write_phy_reg_mdic(hw, BM_WUC_ENABLE_REG, phy_reg); 27784919Sxy150489 if (ret_val) { 27796735Scc210113 DEBUGOUT("Could not clear PHY page 769 bit 2\n"); 27804919Sxy150489 goto out; 27814919Sxy150489 } 27824919Sxy150489 27834919Sxy150489 out: 27844919Sxy150489 if (phy_acquired == 1) 27856735Scc210113 hw->phy.ops.release(hw); 27864919Sxy150489 return (ret_val); 27874919Sxy150489 } 27886735Scc210113 27896735Scc210113 /* 27906735Scc210113 * e1000_power_up_phy_copper - Restore copper link in case of PHY power down 27916735Scc210113 * @hw: pointer to the HW structure 27926735Scc210113 * 27936735Scc210113 * In the case of a PHY power down to save power, or to turn off link during a 27946735Scc210113 * driver unload, or wake on lan is not enabled, restore the link to previous 27956735Scc210113 * settings. 27966735Scc210113 */ 27976735Scc210113 void 27986735Scc210113 e1000_power_up_phy_copper(struct e1000_hw *hw) 27996735Scc210113 { 28006735Scc210113 u16 mii_reg = 0; 28016735Scc210113 28026735Scc210113 /* The PHY will retain its settings across a power down/up cycle */ 28036735Scc210113 hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); 28046735Scc210113 mii_reg &= ~MII_CR_POWER_DOWN; 28056735Scc210113 hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); 28066735Scc210113 } 28076735Scc210113 28086735Scc210113 /* 28096735Scc210113 * e1000_power_down_phy_copper - Restore copper link in case of PHY power down 28106735Scc210113 * @hw: pointer to the HW structure 28116735Scc210113 * 28126735Scc210113 * In the case of a PHY power down to save power, or to turn off link during a 28136735Scc210113 * driver unload, or wake on lan is not enabled, restore the link to previous 28146735Scc210113 * settings. 28156735Scc210113 */ 28166735Scc210113 void 28176735Scc210113 e1000_power_down_phy_copper(struct e1000_hw *hw) 28186735Scc210113 { 28196735Scc210113 u16 mii_reg = 0; 28206735Scc210113 28216735Scc210113 /* The PHY will retain its settings across a power down/up cycle */ 28226735Scc210113 hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg); 28236735Scc210113 mii_reg |= MII_CR_POWER_DOWN; 28246735Scc210113 hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg); 28256735Scc210113 msec_delay(1); 28266735Scc210113 } 2827*10680SMin.Xu@Sun.COM 2828*10680SMin.Xu@Sun.COM s32 2829*10680SMin.Xu@Sun.COM e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw, bool slow) 2830*10680SMin.Xu@Sun.COM { 2831*10680SMin.Xu@Sun.COM s32 ret_val = E1000_SUCCESS; 2832*10680SMin.Xu@Sun.COM u16 data = 0; 2833*10680SMin.Xu@Sun.COM 2834*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.acquire(hw); 2835*10680SMin.Xu@Sun.COM if (ret_val) 2836*10680SMin.Xu@Sun.COM return (ret_val); 2837*10680SMin.Xu@Sun.COM 2838*10680SMin.Xu@Sun.COM /* Set MDIO mode - page 769, register 16: 0x2580==slow, 0x2180==fast */ 2839*10680SMin.Xu@Sun.COM hw->phy.addr = 1; 2840*10680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 2841*10680SMin.Xu@Sun.COM (BM_PORT_CTRL_PAGE << IGP_PAGE_SHIFT)); 2842*10680SMin.Xu@Sun.COM if (ret_val) 2843*10680SMin.Xu@Sun.COM goto out; 2844*10680SMin.Xu@Sun.COM 2845*10680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, BM_CS_CTRL1, 2846*10680SMin.Xu@Sun.COM (0x2180 | (slow << 10))); 2847*10680SMin.Xu@Sun.COM 2848*10680SMin.Xu@Sun.COM if (ret_val) 2849*10680SMin.Xu@Sun.COM goto out; 2850*10680SMin.Xu@Sun.COM 2851*10680SMin.Xu@Sun.COM /* dummy read when reverting to fast mode - throw away result */ 2852*10680SMin.Xu@Sun.COM if (!slow) 2853*10680SMin.Xu@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw, BM_CS_CTRL1, &data); 2854*10680SMin.Xu@Sun.COM 2855*10680SMin.Xu@Sun.COM out: 2856*10680SMin.Xu@Sun.COM hw->phy.ops.release(hw); 2857*10680SMin.Xu@Sun.COM return (ret_val); 2858*10680SMin.Xu@Sun.COM } 2859*10680SMin.Xu@Sun.COM 2860*10680SMin.Xu@Sun.COM /* 2861*10680SMin.Xu@Sun.COM * e1000_read_phy_reg_hv - Read HV PHY register 2862*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 2863*10680SMin.Xu@Sun.COM * @offset: register offset to be read 2864*10680SMin.Xu@Sun.COM * @data: pointer to the read data 2865*10680SMin.Xu@Sun.COM * 2866*10680SMin.Xu@Sun.COM * Acquires semaphore, if necessary, then reads the PHY register at offset 2867*10680SMin.Xu@Sun.COM * and storing the retrieved information in data. Release any acquired 2868*10680SMin.Xu@Sun.COM * semaphore before exiting. 2869*10680SMin.Xu@Sun.COM */ 2870*10680SMin.Xu@Sun.COM s32 2871*10680SMin.Xu@Sun.COM e1000_read_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 *data) 2872*10680SMin.Xu@Sun.COM { 2873*10680SMin.Xu@Sun.COM s32 ret_val; 2874*10680SMin.Xu@Sun.COM u16 page = BM_PHY_REG_PAGE(offset); 2875*10680SMin.Xu@Sun.COM u16 reg = BM_PHY_REG_NUM(offset); 2876*10680SMin.Xu@Sun.COM bool in_slow_mode = false; 2877*10680SMin.Xu@Sun.COM 2878*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_read_phy_reg_hv"); 2879*10680SMin.Xu@Sun.COM 2880*10680SMin.Xu@Sun.COM /* Workaround failure in MDIO access while cable is disconnected */ 2881*10680SMin.Xu@Sun.COM if ((hw->phy.type == e1000_phy_82577) && 2882*10680SMin.Xu@Sun.COM !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { 2883*10680SMin.Xu@Sun.COM ret_val = e1000_set_mdio_slow_mode_hv(hw, true); 2884*10680SMin.Xu@Sun.COM if (ret_val) 2885*10680SMin.Xu@Sun.COM goto out; 2886*10680SMin.Xu@Sun.COM 2887*10680SMin.Xu@Sun.COM in_slow_mode = true; 2888*10680SMin.Xu@Sun.COM } 2889*10680SMin.Xu@Sun.COM 2890*10680SMin.Xu@Sun.COM /* Page 800 works differently than the rest so it has its own func */ 2891*10680SMin.Xu@Sun.COM if (page == BM_WUC_PAGE) { 2892*10680SMin.Xu@Sun.COM ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, 2893*10680SMin.Xu@Sun.COM data, true); 2894*10680SMin.Xu@Sun.COM goto out; 2895*10680SMin.Xu@Sun.COM } 2896*10680SMin.Xu@Sun.COM 2897*10680SMin.Xu@Sun.COM if (page > 0 && page < HV_INTC_FC_PAGE_START) { 2898*10680SMin.Xu@Sun.COM ret_val = e1000_access_phy_debug_regs_hv(hw, offset, 2899*10680SMin.Xu@Sun.COM data, true); 2900*10680SMin.Xu@Sun.COM goto out; 2901*10680SMin.Xu@Sun.COM } 2902*10680SMin.Xu@Sun.COM 2903*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.acquire(hw); 2904*10680SMin.Xu@Sun.COM if (ret_val) 2905*10680SMin.Xu@Sun.COM goto out; 2906*10680SMin.Xu@Sun.COM 2907*10680SMin.Xu@Sun.COM hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); 2908*10680SMin.Xu@Sun.COM 2909*10680SMin.Xu@Sun.COM if (page == HV_INTC_FC_PAGE_START) 2910*10680SMin.Xu@Sun.COM page = 0; 2911*10680SMin.Xu@Sun.COM 2912*10680SMin.Xu@Sun.COM if (reg > MAX_PHY_MULTI_PAGE_REG) { 2913*10680SMin.Xu@Sun.COM u32 phy_addr = hw->phy.addr; 2914*10680SMin.Xu@Sun.COM hw->phy.addr = 1; 2915*10680SMin.Xu@Sun.COM 2916*10680SMin.Xu@Sun.COM /* Page is shifted left, PHY expects (page x 32) */ 2917*10680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, 2918*10680SMin.Xu@Sun.COM IGP01E1000_PHY_PAGE_SELECT, 2919*10680SMin.Xu@Sun.COM (page << IGP_PAGE_SHIFT)); 2920*10680SMin.Xu@Sun.COM hw->phy.addr = phy_addr; 2921*10680SMin.Xu@Sun.COM 2922*10680SMin.Xu@Sun.COM if (ret_val) { 2923*10680SMin.Xu@Sun.COM hw->phy.ops.release(hw); 2924*10680SMin.Xu@Sun.COM goto out; 2925*10680SMin.Xu@Sun.COM } 2926*10680SMin.Xu@Sun.COM } 2927*10680SMin.Xu@Sun.COM 2928*10680SMin.Xu@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, 2929*10680SMin.Xu@Sun.COM data); 2930*10680SMin.Xu@Sun.COM hw->phy.ops.release(hw); 2931*10680SMin.Xu@Sun.COM 2932*10680SMin.Xu@Sun.COM out: 2933*10680SMin.Xu@Sun.COM /* Revert to MDIO fast mode, if applicable */ 2934*10680SMin.Xu@Sun.COM if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) 2935*10680SMin.Xu@Sun.COM ret_val = e1000_set_mdio_slow_mode_hv(hw, false); 2936*10680SMin.Xu@Sun.COM 2937*10680SMin.Xu@Sun.COM return (ret_val); 2938*10680SMin.Xu@Sun.COM } 2939*10680SMin.Xu@Sun.COM 2940*10680SMin.Xu@Sun.COM /* 2941*10680SMin.Xu@Sun.COM * e1000_write_phy_reg_hv - Write HV PHY register 2942*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 2943*10680SMin.Xu@Sun.COM * @offset: register offset to write to 2944*10680SMin.Xu@Sun.COM * @data: data to write at register offset 2945*10680SMin.Xu@Sun.COM * 2946*10680SMin.Xu@Sun.COM * Acquires semaphore, if necessary, then writes the data to PHY register 2947*10680SMin.Xu@Sun.COM * at the offset. Release any acquired semaphores before exiting. 2948*10680SMin.Xu@Sun.COM */ 2949*10680SMin.Xu@Sun.COM s32 2950*10680SMin.Xu@Sun.COM e1000_write_phy_reg_hv(struct e1000_hw *hw, u32 offset, u16 data) 2951*10680SMin.Xu@Sun.COM { 2952*10680SMin.Xu@Sun.COM s32 ret_val; 2953*10680SMin.Xu@Sun.COM u16 page = BM_PHY_REG_PAGE(offset); 2954*10680SMin.Xu@Sun.COM u16 reg = BM_PHY_REG_NUM(offset); 2955*10680SMin.Xu@Sun.COM bool in_slow_mode = false; 2956*10680SMin.Xu@Sun.COM 2957*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_write_phy_reg_hv"); 2958*10680SMin.Xu@Sun.COM 2959*10680SMin.Xu@Sun.COM /* Workaround failure in MDIO access while cable is disconnected */ 2960*10680SMin.Xu@Sun.COM if ((hw->phy.type == e1000_phy_82577) && 2961*10680SMin.Xu@Sun.COM !(E1000_READ_REG(hw, E1000_STATUS) & E1000_STATUS_LU)) { 2962*10680SMin.Xu@Sun.COM ret_val = e1000_set_mdio_slow_mode_hv(hw, true); 2963*10680SMin.Xu@Sun.COM if (ret_val) 2964*10680SMin.Xu@Sun.COM goto out; 2965*10680SMin.Xu@Sun.COM 2966*10680SMin.Xu@Sun.COM in_slow_mode = true; 2967*10680SMin.Xu@Sun.COM } 2968*10680SMin.Xu@Sun.COM 2969*10680SMin.Xu@Sun.COM /* Page 800 works differently than the rest so it has its own func */ 2970*10680SMin.Xu@Sun.COM if (page == BM_WUC_PAGE) { 2971*10680SMin.Xu@Sun.COM ret_val = e1000_access_phy_wakeup_reg_bm(hw, offset, 2972*10680SMin.Xu@Sun.COM &data, false); 2973*10680SMin.Xu@Sun.COM goto out; 2974*10680SMin.Xu@Sun.COM } 2975*10680SMin.Xu@Sun.COM 2976*10680SMin.Xu@Sun.COM if (page > 0 && page < HV_INTC_FC_PAGE_START) { 2977*10680SMin.Xu@Sun.COM ret_val = e1000_access_phy_debug_regs_hv(hw, offset, 2978*10680SMin.Xu@Sun.COM &data, false); 2979*10680SMin.Xu@Sun.COM goto out; 2980*10680SMin.Xu@Sun.COM } 2981*10680SMin.Xu@Sun.COM 2982*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.acquire(hw); 2983*10680SMin.Xu@Sun.COM if (ret_val) 2984*10680SMin.Xu@Sun.COM goto out; 2985*10680SMin.Xu@Sun.COM 2986*10680SMin.Xu@Sun.COM hw->phy.addr = e1000_get_phy_addr_for_hv_page(page); 2987*10680SMin.Xu@Sun.COM 2988*10680SMin.Xu@Sun.COM if (page == HV_INTC_FC_PAGE_START) 2989*10680SMin.Xu@Sun.COM page = 0; 2990*10680SMin.Xu@Sun.COM 2991*10680SMin.Xu@Sun.COM /* 2992*10680SMin.Xu@Sun.COM * Workaround MDIO accesses being disabled after entering IEEE Power 2993*10680SMin.Xu@Sun.COM * Down (whenever bit 11 of the PHY Control register is set) 2994*10680SMin.Xu@Sun.COM */ 2995*10680SMin.Xu@Sun.COM if ((hw->phy.type == e1000_phy_82578) && 2996*10680SMin.Xu@Sun.COM (hw->phy.revision >= 1) && 2997*10680SMin.Xu@Sun.COM (hw->phy.addr == 2) && 2998*10680SMin.Xu@Sun.COM ((MAX_PHY_REG_ADDRESS & reg) == 0) && 2999*10680SMin.Xu@Sun.COM (data & (1 << 11))) { 3000*10680SMin.Xu@Sun.COM u16 data2 = 0x7EFF; 3001*10680SMin.Xu@Sun.COM hw->phy.ops.release(hw); 3002*10680SMin.Xu@Sun.COM ret_val = e1000_access_phy_debug_regs_hv(hw, (1 << 6) | 0x3, 3003*10680SMin.Xu@Sun.COM &data2, false); 3004*10680SMin.Xu@Sun.COM if (ret_val) 3005*10680SMin.Xu@Sun.COM goto out; 3006*10680SMin.Xu@Sun.COM 3007*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.acquire(hw); 3008*10680SMin.Xu@Sun.COM if (ret_val) 3009*10680SMin.Xu@Sun.COM goto out; 3010*10680SMin.Xu@Sun.COM } 3011*10680SMin.Xu@Sun.COM 3012*10680SMin.Xu@Sun.COM if (reg > MAX_PHY_MULTI_PAGE_REG) { 3013*10680SMin.Xu@Sun.COM u32 phy_addr = hw->phy.addr; 3014*10680SMin.Xu@Sun.COM hw->phy.addr = 1; 3015*10680SMin.Xu@Sun.COM 3016*10680SMin.Xu@Sun.COM /* Page is shifted left, PHY expects (page x 32) */ 3017*10680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, 3018*10680SMin.Xu@Sun.COM IGP01E1000_PHY_PAGE_SELECT, 3019*10680SMin.Xu@Sun.COM (page << IGP_PAGE_SHIFT)); 3020*10680SMin.Xu@Sun.COM hw->phy.addr = phy_addr; 3021*10680SMin.Xu@Sun.COM 3022*10680SMin.Xu@Sun.COM if (ret_val) { 3023*10680SMin.Xu@Sun.COM hw->phy.ops.release(hw); 3024*10680SMin.Xu@Sun.COM goto out; 3025*10680SMin.Xu@Sun.COM } 3026*10680SMin.Xu@Sun.COM } 3027*10680SMin.Xu@Sun.COM 3028*10680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, MAX_PHY_REG_ADDRESS & reg, 3029*10680SMin.Xu@Sun.COM data); 3030*10680SMin.Xu@Sun.COM hw->phy.ops.release(hw); 3031*10680SMin.Xu@Sun.COM 3032*10680SMin.Xu@Sun.COM out: 3033*10680SMin.Xu@Sun.COM /* Revert to MDIO fast mode, if applicable */ 3034*10680SMin.Xu@Sun.COM if ((hw->phy.type == e1000_phy_82577) && in_slow_mode) 3035*10680SMin.Xu@Sun.COM ret_val = e1000_set_mdio_slow_mode_hv(hw, false); 3036*10680SMin.Xu@Sun.COM 3037*10680SMin.Xu@Sun.COM return (ret_val); 3038*10680SMin.Xu@Sun.COM } 3039*10680SMin.Xu@Sun.COM 3040*10680SMin.Xu@Sun.COM /* 3041*10680SMin.Xu@Sun.COM * e1000_get_phy_addr_for_hv_page - Get PHY adrress based on page 3042*10680SMin.Xu@Sun.COM * @page: page to be accessed 3043*10680SMin.Xu@Sun.COM */ 3044*10680SMin.Xu@Sun.COM static u32 3045*10680SMin.Xu@Sun.COM e1000_get_phy_addr_for_hv_page(u32 page) 3046*10680SMin.Xu@Sun.COM { 3047*10680SMin.Xu@Sun.COM u32 phy_addr = 2; 3048*10680SMin.Xu@Sun.COM 3049*10680SMin.Xu@Sun.COM if (page >= HV_INTC_FC_PAGE_START) 3050*10680SMin.Xu@Sun.COM phy_addr = 1; 3051*10680SMin.Xu@Sun.COM 3052*10680SMin.Xu@Sun.COM return (phy_addr); 3053*10680SMin.Xu@Sun.COM } 3054*10680SMin.Xu@Sun.COM 3055*10680SMin.Xu@Sun.COM /* 3056*10680SMin.Xu@Sun.COM * e1000_access_phy_debug_regs_hv - Read HV PHY vendor specific high registers 3057*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 3058*10680SMin.Xu@Sun.COM * @offset: register offset to be read or written 3059*10680SMin.Xu@Sun.COM * @data: pointer to the data to be read or written 3060*10680SMin.Xu@Sun.COM * @read: determines if operation is read or written 3061*10680SMin.Xu@Sun.COM * 3062*10680SMin.Xu@Sun.COM * Acquires semaphore, if necessary, then reads the PHY register at offset 3063*10680SMin.Xu@Sun.COM * and storing the retreived information in data. Release any acquired 3064*10680SMin.Xu@Sun.COM * semaphores before exiting. Note that the procedure to read these regs 3065*10680SMin.Xu@Sun.COM * uses the address port and data port to read/write. 3066*10680SMin.Xu@Sun.COM */ 3067*10680SMin.Xu@Sun.COM static s32 3068*10680SMin.Xu@Sun.COM e1000_access_phy_debug_regs_hv(struct e1000_hw *hw, u32 offset, 3069*10680SMin.Xu@Sun.COM u16 *data, bool read) 3070*10680SMin.Xu@Sun.COM { 3071*10680SMin.Xu@Sun.COM s32 ret_val; 3072*10680SMin.Xu@Sun.COM u32 addr_reg = 0; 3073*10680SMin.Xu@Sun.COM u32 data_reg = 0; 3074*10680SMin.Xu@Sun.COM u8 phy_acquired = 1; 3075*10680SMin.Xu@Sun.COM 3076*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_access_phy_debug_regs_hv"); 3077*10680SMin.Xu@Sun.COM 3078*10680SMin.Xu@Sun.COM /* This takes care of the difference with desktop vs mobile phy */ 3079*10680SMin.Xu@Sun.COM addr_reg = (hw->phy.type == e1000_phy_82578) ? 3080*10680SMin.Xu@Sun.COM I82578_ADDR_REG : I82577_ADDR_REG; 3081*10680SMin.Xu@Sun.COM data_reg = addr_reg + 1; 3082*10680SMin.Xu@Sun.COM 3083*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.acquire(hw); 3084*10680SMin.Xu@Sun.COM if (ret_val) { 3085*10680SMin.Xu@Sun.COM DEBUGOUT("Could not acquire PHY\n"); 3086*10680SMin.Xu@Sun.COM phy_acquired = 0; 3087*10680SMin.Xu@Sun.COM goto out; 3088*10680SMin.Xu@Sun.COM } 3089*10680SMin.Xu@Sun.COM 3090*10680SMin.Xu@Sun.COM /* All operations in this function are phy address 2 */ 3091*10680SMin.Xu@Sun.COM hw->phy.addr = 2; 3092*10680SMin.Xu@Sun.COM 3093*10680SMin.Xu@Sun.COM /* masking with 0x3F to remove the page from offset */ 3094*10680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, addr_reg, (u16)offset & 0x3F); 3095*10680SMin.Xu@Sun.COM if (ret_val) { 3096*10680SMin.Xu@Sun.COM DEBUGOUT("Could not write PHY the HV address register\n"); 3097*10680SMin.Xu@Sun.COM goto out; 3098*10680SMin.Xu@Sun.COM } 3099*10680SMin.Xu@Sun.COM 3100*10680SMin.Xu@Sun.COM /* Read or write the data value next */ 3101*10680SMin.Xu@Sun.COM if (read) 3102*10680SMin.Xu@Sun.COM ret_val = e1000_read_phy_reg_mdic(hw, data_reg, data); 3103*10680SMin.Xu@Sun.COM else 3104*10680SMin.Xu@Sun.COM ret_val = e1000_write_phy_reg_mdic(hw, data_reg, *data); 3105*10680SMin.Xu@Sun.COM 3106*10680SMin.Xu@Sun.COM if (ret_val) { 3107*10680SMin.Xu@Sun.COM DEBUGOUT("Could not read data value from HV data register\n"); 3108*10680SMin.Xu@Sun.COM goto out; 3109*10680SMin.Xu@Sun.COM } 3110*10680SMin.Xu@Sun.COM 3111*10680SMin.Xu@Sun.COM out: 3112*10680SMin.Xu@Sun.COM if (phy_acquired == 1) 3113*10680SMin.Xu@Sun.COM hw->phy.ops.release(hw); 3114*10680SMin.Xu@Sun.COM return (ret_val); 3115*10680SMin.Xu@Sun.COM } 3116*10680SMin.Xu@Sun.COM 3117*10680SMin.Xu@Sun.COM /* 3118*10680SMin.Xu@Sun.COM * e1000_link_stall_workaround_hv - Si workaround 3119*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 3120*10680SMin.Xu@Sun.COM * 3121*10680SMin.Xu@Sun.COM * This function works around a Si bug where the link partner can get 3122*10680SMin.Xu@Sun.COM * a link up indication before the PHY does. If small packets are sent 3123*10680SMin.Xu@Sun.COM * by the link partner they can be placed in the packet buffer without 3124*10680SMin.Xu@Sun.COM * being properly accounted for by the PHY and will stall preventing 3125*10680SMin.Xu@Sun.COM * further packets from being received. The workaround is to clear the 3126*10680SMin.Xu@Sun.COM * packet buffer after the PHY detects link up. 3127*10680SMin.Xu@Sun.COM */ 3128*10680SMin.Xu@Sun.COM s32 3129*10680SMin.Xu@Sun.COM e1000_link_stall_workaround_hv(struct e1000_hw *hw) 3130*10680SMin.Xu@Sun.COM { 3131*10680SMin.Xu@Sun.COM s32 ret_val = E1000_SUCCESS; 3132*10680SMin.Xu@Sun.COM u16 data; 3133*10680SMin.Xu@Sun.COM 3134*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_link_stall_workaround_hv"); 3135*10680SMin.Xu@Sun.COM 3136*10680SMin.Xu@Sun.COM if (hw->phy.type != e1000_phy_82578) 3137*10680SMin.Xu@Sun.COM goto out; 3138*10680SMin.Xu@Sun.COM 3139*10680SMin.Xu@Sun.COM /* Do not apply workaround if in PHY loopback bit 14 set */ 3140*10680SMin.Xu@Sun.COM hw->phy.ops.read_reg(hw, PHY_CONTROL, &data); 3141*10680SMin.Xu@Sun.COM if (data & PHY_CONTROL_LB) 3142*10680SMin.Xu@Sun.COM goto out; 3143*10680SMin.Xu@Sun.COM 3144*10680SMin.Xu@Sun.COM /* check if link is up and at 1Gbps */ 3145*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.read_reg(hw, BM_CS_STATUS, &data); 3146*10680SMin.Xu@Sun.COM if (ret_val) 3147*10680SMin.Xu@Sun.COM goto out; 3148*10680SMin.Xu@Sun.COM 3149*10680SMin.Xu@Sun.COM data &= BM_CS_STATUS_LINK_UP | 3150*10680SMin.Xu@Sun.COM BM_CS_STATUS_RESOLVED | 3151*10680SMin.Xu@Sun.COM BM_CS_STATUS_SPEED_MASK; 3152*10680SMin.Xu@Sun.COM 3153*10680SMin.Xu@Sun.COM if (data != (BM_CS_STATUS_LINK_UP | 3154*10680SMin.Xu@Sun.COM BM_CS_STATUS_RESOLVED | 3155*10680SMin.Xu@Sun.COM BM_CS_STATUS_SPEED_1000)) 3156*10680SMin.Xu@Sun.COM goto out; 3157*10680SMin.Xu@Sun.COM 3158*10680SMin.Xu@Sun.COM msec_delay(200); 3159*10680SMin.Xu@Sun.COM 3160*10680SMin.Xu@Sun.COM /* flush the packets in the fifo buffer */ 3161*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL, 3162*10680SMin.Xu@Sun.COM HV_MUX_DATA_CTRL_GEN_TO_MAC | HV_MUX_DATA_CTRL_FORCE_SPEED); 3163*10680SMin.Xu@Sun.COM if (ret_val) 3164*10680SMin.Xu@Sun.COM goto out; 3165*10680SMin.Xu@Sun.COM 3166*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.write_reg(hw, HV_MUX_DATA_CTRL, 3167*10680SMin.Xu@Sun.COM HV_MUX_DATA_CTRL_GEN_TO_MAC); 3168*10680SMin.Xu@Sun.COM 3169*10680SMin.Xu@Sun.COM out: 3170*10680SMin.Xu@Sun.COM return (ret_val); 3171*10680SMin.Xu@Sun.COM } 3172*10680SMin.Xu@Sun.COM 3173*10680SMin.Xu@Sun.COM /* 3174*10680SMin.Xu@Sun.COM * e1000_check_polarity_82577 - Checks the polarity. 3175*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 3176*10680SMin.Xu@Sun.COM * 3177*10680SMin.Xu@Sun.COM * Success returns 0, Failure returns -E1000_ERR_PHY (-2) 3178*10680SMin.Xu@Sun.COM * 3179*10680SMin.Xu@Sun.COM * Polarity is determined based on the PHY specific status register. 3180*10680SMin.Xu@Sun.COM */ 3181*10680SMin.Xu@Sun.COM s32 3182*10680SMin.Xu@Sun.COM e1000_check_polarity_82577(struct e1000_hw *hw) 3183*10680SMin.Xu@Sun.COM { 3184*10680SMin.Xu@Sun.COM struct e1000_phy_info *phy = &hw->phy; 3185*10680SMin.Xu@Sun.COM s32 ret_val; 3186*10680SMin.Xu@Sun.COM u16 data; 3187*10680SMin.Xu@Sun.COM 3188*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_check_polarity_82577"); 3189*10680SMin.Xu@Sun.COM 3190*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); 3191*10680SMin.Xu@Sun.COM 3192*10680SMin.Xu@Sun.COM if (!ret_val) 3193*10680SMin.Xu@Sun.COM phy->cable_polarity = (data & I82577_PHY_STATUS2_REV_POLARITY) 3194*10680SMin.Xu@Sun.COM ? e1000_rev_polarity_reversed 3195*10680SMin.Xu@Sun.COM : e1000_rev_polarity_normal; 3196*10680SMin.Xu@Sun.COM 3197*10680SMin.Xu@Sun.COM return (ret_val); 3198*10680SMin.Xu@Sun.COM } 3199*10680SMin.Xu@Sun.COM 3200*10680SMin.Xu@Sun.COM /* 3201*10680SMin.Xu@Sun.COM * e1000_phy_force_speed_duplex_82577 - Force speed/duplex for I82577 PHY 3202*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 3203*10680SMin.Xu@Sun.COM * 3204*10680SMin.Xu@Sun.COM * Calls the PHY setup function to force speed and duplex. Clears the 3205*10680SMin.Xu@Sun.COM * auto-crossover to force MDI manually. Waits for link and returns 3206*10680SMin.Xu@Sun.COM * successful if link up is successful, else -E1000_ERR_PHY (-2). 3207*10680SMin.Xu@Sun.COM */ 3208*10680SMin.Xu@Sun.COM s32 3209*10680SMin.Xu@Sun.COM e1000_phy_force_speed_duplex_82577(struct e1000_hw *hw) 3210*10680SMin.Xu@Sun.COM { 3211*10680SMin.Xu@Sun.COM struct e1000_phy_info *phy = &hw->phy; 3212*10680SMin.Xu@Sun.COM s32 ret_val; 3213*10680SMin.Xu@Sun.COM u16 phy_data; 3214*10680SMin.Xu@Sun.COM bool link; 3215*10680SMin.Xu@Sun.COM 3216*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_phy_force_speed_duplex_82577"); 3217*10680SMin.Xu@Sun.COM 3218*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_data); 3219*10680SMin.Xu@Sun.COM if (ret_val) 3220*10680SMin.Xu@Sun.COM goto out; 3221*10680SMin.Xu@Sun.COM 3222*10680SMin.Xu@Sun.COM e1000_phy_force_speed_duplex_setup(hw, &phy_data); 3223*10680SMin.Xu@Sun.COM 3224*10680SMin.Xu@Sun.COM ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_data); 3225*10680SMin.Xu@Sun.COM if (ret_val) 3226*10680SMin.Xu@Sun.COM goto out; 3227*10680SMin.Xu@Sun.COM 3228*10680SMin.Xu@Sun.COM /* 3229*10680SMin.Xu@Sun.COM * Clear Auto-Crossover to force MDI manually. 82577 requires MDI 3230*10680SMin.Xu@Sun.COM * forced whenever speed and duplex are forced. 3231*10680SMin.Xu@Sun.COM */ 3232*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, I82577_PHY_CTRL_2, &phy_data); 3233*10680SMin.Xu@Sun.COM if (ret_val) 3234*10680SMin.Xu@Sun.COM goto out; 3235*10680SMin.Xu@Sun.COM 3236*10680SMin.Xu@Sun.COM phy_data &= ~I82577_PHY_CTRL2_AUTO_MDIX; 3237*10680SMin.Xu@Sun.COM phy_data &= ~I82577_PHY_CTRL2_FORCE_MDI_MDIX; 3238*10680SMin.Xu@Sun.COM 3239*10680SMin.Xu@Sun.COM ret_val = phy->ops.write_reg(hw, I82577_PHY_CTRL_2, phy_data); 3240*10680SMin.Xu@Sun.COM if (ret_val) 3241*10680SMin.Xu@Sun.COM goto out; 3242*10680SMin.Xu@Sun.COM 3243*10680SMin.Xu@Sun.COM DEBUGOUT1("I82577_PHY_CTRL_2: %X\n", phy_data); 3244*10680SMin.Xu@Sun.COM 3245*10680SMin.Xu@Sun.COM usec_delay(1); 3246*10680SMin.Xu@Sun.COM 3247*10680SMin.Xu@Sun.COM if (phy->autoneg_wait_to_complete) { 3248*10680SMin.Xu@Sun.COM DEBUGOUT("Waiting for forced speed/duplex link on 82577 phy\n"); 3249*10680SMin.Xu@Sun.COM 3250*10680SMin.Xu@Sun.COM ret_val = e1000_phy_has_link_generic(hw, 3251*10680SMin.Xu@Sun.COM PHY_FORCE_LIMIT, 100000, &link); 3252*10680SMin.Xu@Sun.COM if (ret_val) 3253*10680SMin.Xu@Sun.COM goto out; 3254*10680SMin.Xu@Sun.COM 3255*10680SMin.Xu@Sun.COM if (!link) 3256*10680SMin.Xu@Sun.COM DEBUGOUT("Link taking longer than expected.\n"); 3257*10680SMin.Xu@Sun.COM 3258*10680SMin.Xu@Sun.COM /* Try once more */ 3259*10680SMin.Xu@Sun.COM ret_val = e1000_phy_has_link_generic(hw, 3260*10680SMin.Xu@Sun.COM PHY_FORCE_LIMIT, 100000, &link); 3261*10680SMin.Xu@Sun.COM if (ret_val) 3262*10680SMin.Xu@Sun.COM goto out; 3263*10680SMin.Xu@Sun.COM } 3264*10680SMin.Xu@Sun.COM 3265*10680SMin.Xu@Sun.COM out: 3266*10680SMin.Xu@Sun.COM return (ret_val); 3267*10680SMin.Xu@Sun.COM } 3268*10680SMin.Xu@Sun.COM 3269*10680SMin.Xu@Sun.COM /* 3270*10680SMin.Xu@Sun.COM * e1000_get_phy_info_82577 - Retrieve I82577 PHY information 3271*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 3272*10680SMin.Xu@Sun.COM * 3273*10680SMin.Xu@Sun.COM * Read PHY status to determine if link is up. If link is up, then 3274*10680SMin.Xu@Sun.COM * set/determine 10base-T extended distance and polarity correction. Read 3275*10680SMin.Xu@Sun.COM * PHY port status to determine MDI/MDIx and speed. Based on the speed, 3276*10680SMin.Xu@Sun.COM * determine on the cable length, local and remote receiver. 3277*10680SMin.Xu@Sun.COM */ 3278*10680SMin.Xu@Sun.COM s32 3279*10680SMin.Xu@Sun.COM e1000_get_phy_info_82577(struct e1000_hw *hw) 3280*10680SMin.Xu@Sun.COM { 3281*10680SMin.Xu@Sun.COM struct e1000_phy_info *phy = &hw->phy; 3282*10680SMin.Xu@Sun.COM s32 ret_val; 3283*10680SMin.Xu@Sun.COM u16 data; 3284*10680SMin.Xu@Sun.COM bool link; 3285*10680SMin.Xu@Sun.COM 3286*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_get_phy_info_82577"); 3287*10680SMin.Xu@Sun.COM 3288*10680SMin.Xu@Sun.COM ret_val = e1000_phy_has_link_generic(hw, 1, 0, &link); 3289*10680SMin.Xu@Sun.COM if (ret_val) 3290*10680SMin.Xu@Sun.COM goto out; 3291*10680SMin.Xu@Sun.COM 3292*10680SMin.Xu@Sun.COM if (!link) { 3293*10680SMin.Xu@Sun.COM DEBUGOUT("Phy info is only valid if link is up\n"); 3294*10680SMin.Xu@Sun.COM ret_val = -E1000_ERR_CONFIG; 3295*10680SMin.Xu@Sun.COM goto out; 3296*10680SMin.Xu@Sun.COM } 3297*10680SMin.Xu@Sun.COM 3298*10680SMin.Xu@Sun.COM phy->polarity_correction = true; 3299*10680SMin.Xu@Sun.COM 3300*10680SMin.Xu@Sun.COM ret_val = e1000_check_polarity_82577(hw); 3301*10680SMin.Xu@Sun.COM if (ret_val) 3302*10680SMin.Xu@Sun.COM goto out; 3303*10680SMin.Xu@Sun.COM 3304*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, I82577_PHY_STATUS_2, &data); 3305*10680SMin.Xu@Sun.COM if (ret_val) 3306*10680SMin.Xu@Sun.COM goto out; 3307*10680SMin.Xu@Sun.COM 3308*10680SMin.Xu@Sun.COM phy->is_mdix = (data & I82577_PHY_STATUS2_MDIX) ? true : false; 3309*10680SMin.Xu@Sun.COM 3310*10680SMin.Xu@Sun.COM if ((data & I82577_PHY_STATUS2_SPEED_MASK) == 3311*10680SMin.Xu@Sun.COM I82577_PHY_STATUS2_SPEED_1000MBPS) { 3312*10680SMin.Xu@Sun.COM ret_val = hw->phy.ops.get_cable_length(hw); 3313*10680SMin.Xu@Sun.COM if (ret_val) 3314*10680SMin.Xu@Sun.COM goto out; 3315*10680SMin.Xu@Sun.COM 3316*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, PHY_1000T_STATUS, &data); 3317*10680SMin.Xu@Sun.COM if (ret_val) 3318*10680SMin.Xu@Sun.COM goto out; 3319*10680SMin.Xu@Sun.COM 3320*10680SMin.Xu@Sun.COM phy->local_rx = (data & SR_1000T_LOCAL_RX_STATUS) 3321*10680SMin.Xu@Sun.COM ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; 3322*10680SMin.Xu@Sun.COM 3323*10680SMin.Xu@Sun.COM phy->remote_rx = (data & SR_1000T_REMOTE_RX_STATUS) 3324*10680SMin.Xu@Sun.COM ? e1000_1000t_rx_status_ok : e1000_1000t_rx_status_not_ok; 3325*10680SMin.Xu@Sun.COM } else { 3326*10680SMin.Xu@Sun.COM phy->cable_length = E1000_CABLE_LENGTH_UNDEFINED; 3327*10680SMin.Xu@Sun.COM phy->local_rx = e1000_1000t_rx_status_undefined; 3328*10680SMin.Xu@Sun.COM phy->remote_rx = e1000_1000t_rx_status_undefined; 3329*10680SMin.Xu@Sun.COM } 3330*10680SMin.Xu@Sun.COM 3331*10680SMin.Xu@Sun.COM out: 3332*10680SMin.Xu@Sun.COM return (ret_val); 3333*10680SMin.Xu@Sun.COM } 3334*10680SMin.Xu@Sun.COM 3335*10680SMin.Xu@Sun.COM /* 3336*10680SMin.Xu@Sun.COM * e1000_get_cable_length_82577 - Determine cable length for 82577 PHY 3337*10680SMin.Xu@Sun.COM * @hw: pointer to the HW structure 3338*10680SMin.Xu@Sun.COM * 3339*10680SMin.Xu@Sun.COM * Reads the diagnostic status register and verifies result is valid before 3340*10680SMin.Xu@Sun.COM * placing it in the phy_cable_length field. 3341*10680SMin.Xu@Sun.COM */ 3342*10680SMin.Xu@Sun.COM s32 3343*10680SMin.Xu@Sun.COM e1000_get_cable_length_82577(struct e1000_hw *hw) 3344*10680SMin.Xu@Sun.COM { 3345*10680SMin.Xu@Sun.COM struct e1000_phy_info *phy = &hw->phy; 3346*10680SMin.Xu@Sun.COM s32 ret_val; 3347*10680SMin.Xu@Sun.COM u16 phy_data, length; 3348*10680SMin.Xu@Sun.COM 3349*10680SMin.Xu@Sun.COM DEBUGFUNC("e1000_get_cable_length_82577"); 3350*10680SMin.Xu@Sun.COM 3351*10680SMin.Xu@Sun.COM ret_val = phy->ops.read_reg(hw, I82577_PHY_DIAG_STATUS, &phy_data); 3352*10680SMin.Xu@Sun.COM if (ret_val) 3353*10680SMin.Xu@Sun.COM goto out; 3354*10680SMin.Xu@Sun.COM 3355*10680SMin.Xu@Sun.COM length = (phy_data & I82577_DSTATUS_CABLE_LENGTH) >> 3356*10680SMin.Xu@Sun.COM I82577_DSTATUS_CABLE_LENGTH_SHIFT; 3357*10680SMin.Xu@Sun.COM 3358*10680SMin.Xu@Sun.COM if (length == E1000_CABLE_LENGTH_UNDEFINED) 3359*10680SMin.Xu@Sun.COM ret_val = E1000_ERR_PHY; 3360*10680SMin.Xu@Sun.COM 3361*10680SMin.Xu@Sun.COM phy->cable_length = length; 3362*10680SMin.Xu@Sun.COM 3363*10680SMin.Xu@Sun.COM out: 3364*10680SMin.Xu@Sun.COM return (ret_val); 3365*10680SMin.Xu@Sun.COM } 3366