144e97550SJiawen Wu /* SPDX-License-Identifier: BSD-3-Clause 244e97550SJiawen Wu * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 344e97550SJiawen Wu */ 444e97550SJiawen Wu 544e97550SJiawen Wu #include "ngbe_phy_mvl.h" 644e97550SJiawen Wu 744e97550SJiawen Wu #define MVL_PHY_RST_WAIT_PERIOD 5 844e97550SJiawen Wu 944e97550SJiawen Wu s32 ngbe_read_phy_reg_mvl(struct ngbe_hw *hw, 1044e97550SJiawen Wu u32 reg_addr, u32 device_type, u16 *phy_data) 1144e97550SJiawen Wu { 1244e97550SJiawen Wu mdi_reg_t reg; 1344e97550SJiawen Wu mdi_reg_22_t reg22; 1444e97550SJiawen Wu 1544e97550SJiawen Wu reg.device_type = device_type; 1644e97550SJiawen Wu reg.addr = reg_addr; 1744e97550SJiawen Wu 1844e97550SJiawen Wu if (hw->phy.media_type == ngbe_media_type_fiber) 1944e97550SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1); 2044e97550SJiawen Wu else 2144e97550SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0); 2244e97550SJiawen Wu 2344e97550SJiawen Wu ngbe_mdi_map_register(®, ®22); 2444e97550SJiawen Wu 2544e97550SJiawen Wu ngbe_read_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data); 2644e97550SJiawen Wu 2744e97550SJiawen Wu return 0; 2844e97550SJiawen Wu } 2944e97550SJiawen Wu 3044e97550SJiawen Wu s32 ngbe_write_phy_reg_mvl(struct ngbe_hw *hw, 3144e97550SJiawen Wu u32 reg_addr, u32 device_type, u16 phy_data) 3244e97550SJiawen Wu { 3344e97550SJiawen Wu mdi_reg_t reg; 3444e97550SJiawen Wu mdi_reg_22_t reg22; 3544e97550SJiawen Wu 3644e97550SJiawen Wu reg.device_type = device_type; 3744e97550SJiawen Wu reg.addr = reg_addr; 3844e97550SJiawen Wu 3944e97550SJiawen Wu if (hw->phy.media_type == ngbe_media_type_fiber) 4044e97550SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 1); 4144e97550SJiawen Wu else 4244e97550SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 0); 4344e97550SJiawen Wu 4444e97550SJiawen Wu ngbe_mdi_map_register(®, ®22); 4544e97550SJiawen Wu 4644e97550SJiawen Wu ngbe_write_phy_reg_mdi(hw, reg22.addr, reg22.device_type, phy_data); 4744e97550SJiawen Wu 4844e97550SJiawen Wu return 0; 4944e97550SJiawen Wu } 5044e97550SJiawen Wu 511c44384fSJiawen Wu s32 ngbe_check_phy_mode_mvl(struct ngbe_hw *hw) 521c44384fSJiawen Wu { 536dcfb19fSJiawen Wu u8 value = 0; 546dcfb19fSJiawen Wu u32 phy_mode = 0; 551c44384fSJiawen Wu 56*91e64c0eSJiawen Wu ngbe_flash_read_dword(hw, 0xFF010, &phy_mode); 576dcfb19fSJiawen Wu value = (u8)(phy_mode >> (hw->bus.lan_id * 8)); 586dcfb19fSJiawen Wu 591c44384fSJiawen Wu if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_COPPER) { 601c44384fSJiawen Wu /* mode select to RGMII-to-copper */ 611c44384fSJiawen Wu hw->phy.type = ngbe_phy_mvl; 621c44384fSJiawen Wu hw->phy.media_type = ngbe_media_type_copper; 631c44384fSJiawen Wu hw->mac.link_type = ngbe_link_copper; 641c44384fSJiawen Wu } else if (MVL_GEN_CTL_MODE(value) == MVL_GEN_CTL_MODE_FIBER) { 651c44384fSJiawen Wu /* mode select to RGMII-to-sfi */ 661c44384fSJiawen Wu hw->phy.type = ngbe_phy_mvl_sfi; 671c44384fSJiawen Wu hw->phy.media_type = ngbe_media_type_fiber; 681c44384fSJiawen Wu hw->mac.link_type = ngbe_link_fiber; 691c44384fSJiawen Wu } else { 70c811e6a4SJiawen Wu DEBUGOUT("marvell 88E1512 mode %x is not supported.", value); 711c44384fSJiawen Wu return NGBE_ERR_DEVICE_NOT_SUPPORTED; 721c44384fSJiawen Wu } 731c44384fSJiawen Wu 741c44384fSJiawen Wu return 0; 751c44384fSJiawen Wu } 761c44384fSJiawen Wu 773518df57SJiawen Wu s32 ngbe_init_phy_mvl(struct ngbe_hw *hw) 783518df57SJiawen Wu { 793518df57SJiawen Wu s32 ret_val = 0; 803518df57SJiawen Wu u16 value = 0; 813518df57SJiawen Wu int i; 823518df57SJiawen Wu 833518df57SJiawen Wu /* enable interrupts, only link status change and an done is allowed */ 843518df57SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 2); 853518df57SJiawen Wu ngbe_read_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, &value); 863518df57SJiawen Wu value &= ~MVL_RGM_CTL2_TTC; 873518df57SJiawen Wu value |= MVL_RGM_CTL2_RTC; 883518df57SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_RGM_CTL2, 0, value); 893518df57SJiawen Wu 903518df57SJiawen Wu hw->phy.write_reg(hw, MVL_CTRL, 0, MVL_CTRL_RESET); 913518df57SJiawen Wu for (i = 0; i < 15; i++) { 923518df57SJiawen Wu ngbe_read_phy_reg_mdi(hw, MVL_CTRL, 0, &value); 933518df57SJiawen Wu if (value & MVL_CTRL_RESET) 943518df57SJiawen Wu msleep(1); 953518df57SJiawen Wu else 963518df57SJiawen Wu break; 973518df57SJiawen Wu } 983518df57SJiawen Wu 993518df57SJiawen Wu if (i == 15) { 100c811e6a4SJiawen Wu DEBUGOUT("phy reset exceeds maximum waiting period."); 1013518df57SJiawen Wu return NGBE_ERR_TIMEOUT; 1023518df57SJiawen Wu } 1033518df57SJiawen Wu 1043518df57SJiawen Wu ret_val = hw->phy.reset_hw(hw); 1053518df57SJiawen Wu if (ret_val) 1063518df57SJiawen Wu return ret_val; 1073518df57SJiawen Wu 1083518df57SJiawen Wu /* set LED2 to interrupt output and INTn active low */ 1093518df57SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3); 1103518df57SJiawen Wu ngbe_read_phy_reg_mdi(hw, MVL_LEDTCR, 0, &value); 1113518df57SJiawen Wu value |= MVL_LEDTCR_INTR_EN; 1123518df57SJiawen Wu value &= ~(MVL_LEDTCR_INTR_POL); 1133518df57SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_LEDTCR, 0, value); 1143518df57SJiawen Wu 1153518df57SJiawen Wu if (hw->phy.type == ngbe_phy_mvl_sfi) { 1163518df57SJiawen Wu hw->phy.read_reg(hw, MVL_CTRL1, 0, &value); 1173518df57SJiawen Wu value &= ~MVL_CTRL1_INTR_POL; 1183518df57SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_CTRL1, 0, value); 1193518df57SJiawen Wu } 1203518df57SJiawen Wu 1213518df57SJiawen Wu /* enable link status change and AN complete interrupts */ 1223518df57SJiawen Wu value = MVL_INTR_EN_ANC | MVL_INTR_EN_LSC; 1233518df57SJiawen Wu hw->phy.write_reg(hw, MVL_INTR_EN, 0, value); 1243518df57SJiawen Wu 125708ebe7dSJiawen Wu hw->phy.set_phy_power(hw, false); 1263518df57SJiawen Wu 1273518df57SJiawen Wu return ret_val; 1283518df57SJiawen Wu } 1293518df57SJiawen Wu 1303d0af706SJiawen Wu s32 ngbe_setup_phy_link_mvl(struct ngbe_hw *hw, u32 speed, 1313d0af706SJiawen Wu bool autoneg_wait_to_complete) 1323d0af706SJiawen Wu { 1333d0af706SJiawen Wu u16 value_r4 = 0; 1343d0af706SJiawen Wu u16 value_r9 = 0; 1353d0af706SJiawen Wu u16 value; 1363d0af706SJiawen Wu 1373d0af706SJiawen Wu UNREFERENCED_PARAMETER(autoneg_wait_to_complete); 1383d0af706SJiawen Wu 139fbd5ceb0SJiawen Wu if (hw->led_conf == 0xFFFF) { 140fbd5ceb0SJiawen Wu /* LED control */ 141fbd5ceb0SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 3); 142fbd5ceb0SJiawen Wu ngbe_read_phy_reg_mdi(hw, MVL_LEDFCR, 0, &value); 143fbd5ceb0SJiawen Wu value &= ~(MVL_LEDFCR_CTL0 | MVL_LEDFCR_CTL1); 144fbd5ceb0SJiawen Wu value |= MVL_LEDFCR_CTL0_CONF | MVL_LEDFCR_CTL1_CONF; 145fbd5ceb0SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_LEDFCR, 0, value); 146fbd5ceb0SJiawen Wu ngbe_read_phy_reg_mdi(hw, MVL_LEDPCR, 0, &value); 147fbd5ceb0SJiawen Wu value &= ~(MVL_LEDPCR_CTL0 | MVL_LEDPCR_CTL1); 148fbd5ceb0SJiawen Wu value |= MVL_LEDPCR_CTL0_CONF | MVL_LEDPCR_CTL1_CONF; 149fbd5ceb0SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_LEDPCR, 0, value); 150fbd5ceb0SJiawen Wu } 151fbd5ceb0SJiawen Wu 1523d0af706SJiawen Wu hw->phy.autoneg_advertised = 0; 1533d0af706SJiawen Wu 1543d0af706SJiawen Wu if (hw->phy.type == ngbe_phy_mvl) { 1551c44384fSJiawen Wu if (!hw->mac.autoneg) { 1561c44384fSJiawen Wu switch (speed) { 1571c44384fSJiawen Wu case NGBE_LINK_SPEED_1GB_FULL: 1581c44384fSJiawen Wu value = MVL_CTRL_SPEED_SELECT1; 1591c44384fSJiawen Wu break; 1601c44384fSJiawen Wu case NGBE_LINK_SPEED_100M_FULL: 1611c44384fSJiawen Wu value = MVL_CTRL_SPEED_SELECT0; 1621c44384fSJiawen Wu break; 1631c44384fSJiawen Wu case NGBE_LINK_SPEED_10M_FULL: 1641c44384fSJiawen Wu value = 0; 1651c44384fSJiawen Wu break; 1661c44384fSJiawen Wu default: 1671c44384fSJiawen Wu value = MVL_CTRL_SPEED_SELECT0 | 1681c44384fSJiawen Wu MVL_CTRL_SPEED_SELECT1; 169c811e6a4SJiawen Wu DEBUGOUT("unknown speed = 0x%x.", speed); 1701c44384fSJiawen Wu break; 1711c44384fSJiawen Wu } 1721c44384fSJiawen Wu /* duplex full */ 1731c44384fSJiawen Wu value |= MVL_CTRL_DUPLEX | MVL_CTRL_RESET; 1741c44384fSJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value); 1751c44384fSJiawen Wu 1761c44384fSJiawen Wu goto skip_an; 1771c44384fSJiawen Wu } 1783d0af706SJiawen Wu if (speed & NGBE_LINK_SPEED_1GB_FULL) { 1793d0af706SJiawen Wu value_r9 |= MVL_PHY_1000BASET_FULL; 1803d0af706SJiawen Wu hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; 1813d0af706SJiawen Wu } 1823d0af706SJiawen Wu 1833d0af706SJiawen Wu if (speed & NGBE_LINK_SPEED_100M_FULL) { 1843d0af706SJiawen Wu value_r4 |= MVL_PHY_100BASET_FULL; 1853d0af706SJiawen Wu hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL; 1863d0af706SJiawen Wu } 1873d0af706SJiawen Wu 1883d0af706SJiawen Wu if (speed & NGBE_LINK_SPEED_10M_FULL) { 1893d0af706SJiawen Wu value_r4 |= MVL_PHY_10BASET_FULL; 1903d0af706SJiawen Wu hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL; 1913d0af706SJiawen Wu } 1923d0af706SJiawen Wu 1933d0af706SJiawen Wu hw->phy.read_reg(hw, MVL_ANA, 0, &value); 1943d0af706SJiawen Wu value &= ~(MVL_PHY_100BASET_FULL | 1953d0af706SJiawen Wu MVL_PHY_100BASET_HALF | 1963d0af706SJiawen Wu MVL_PHY_10BASET_FULL | 1973d0af706SJiawen Wu MVL_PHY_10BASET_HALF); 1983d0af706SJiawen Wu value_r4 |= value; 1993d0af706SJiawen Wu hw->phy.write_reg(hw, MVL_ANA, 0, value_r4); 2003d0af706SJiawen Wu 2013d0af706SJiawen Wu hw->phy.read_reg(hw, MVL_PHY_1000BASET, 0, &value); 2023d0af706SJiawen Wu value &= ~(MVL_PHY_1000BASET_FULL | 2033d0af706SJiawen Wu MVL_PHY_1000BASET_HALF); 2043d0af706SJiawen Wu value_r9 |= value; 2053d0af706SJiawen Wu hw->phy.write_reg(hw, MVL_PHY_1000BASET, 0, value_r9); 206f1268369SJiawen Wu 207f1268369SJiawen Wu value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE | 208f1268369SJiawen Wu MVL_CTRL_RESET | MVL_CTRL_DUPLEX; 209f1268369SJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value); 2103d0af706SJiawen Wu } else { 211708ebe7dSJiawen Wu hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; 2123d0af706SJiawen Wu 2133d0af706SJiawen Wu hw->phy.read_reg(hw, MVL_ANA, 0, &value); 2143d0af706SJiawen Wu value &= ~(MVL_PHY_1000BASEX_HALF | MVL_PHY_1000BASEX_FULL); 2153d0af706SJiawen Wu value |= MVL_PHY_1000BASEX_FULL; 2163d0af706SJiawen Wu hw->phy.write_reg(hw, MVL_ANA, 0, value); 2173d0af706SJiawen Wu 218f1268369SJiawen Wu if (hw->mac.autoneg) 219f1268369SJiawen Wu value = MVL_CTRL_RESTART_AN | MVL_CTRL_ANE | 220f1268369SJiawen Wu MVL_CTRL_RESET | MVL_CTRL_DUPLEX | 221f1268369SJiawen Wu MVL_CTRL_SPEED_SELECT1; 222f1268369SJiawen Wu else 223f1268369SJiawen Wu value = MVL_CTRL_RESET | MVL_CTRL_DUPLEX | 224f1268369SJiawen Wu MVL_CTRL_SPEED_SELECT1; 2251c44384fSJiawen Wu ngbe_write_phy_reg_mdi(hw, MVL_CTRL, 0, value); 226f1268369SJiawen Wu } 2271c44384fSJiawen Wu 2281c44384fSJiawen Wu skip_an: 229708ebe7dSJiawen Wu hw->phy.set_phy_power(hw, true); 2303d0af706SJiawen Wu 2313d0af706SJiawen Wu hw->phy.read_reg(hw, MVL_INTR, 0, &value); 2323d0af706SJiawen Wu 2333d0af706SJiawen Wu return 0; 2343d0af706SJiawen Wu } 2353d0af706SJiawen Wu 23644e97550SJiawen Wu s32 ngbe_reset_phy_mvl(struct ngbe_hw *hw) 23744e97550SJiawen Wu { 23844e97550SJiawen Wu u32 i; 23944e97550SJiawen Wu u16 ctrl = 0; 24044e97550SJiawen Wu s32 status = 0; 24144e97550SJiawen Wu 24244e97550SJiawen Wu if (hw->phy.type != ngbe_phy_mvl && hw->phy.type != ngbe_phy_mvl_sfi) 24344e97550SJiawen Wu return NGBE_ERR_PHY_TYPE; 24444e97550SJiawen Wu 24544e97550SJiawen Wu /* select page 18 reg 20 */ 24644e97550SJiawen Wu status = ngbe_write_phy_reg_mdi(hw, MVL_PAGE_SEL, 0, 18); 24744e97550SJiawen Wu 24844e97550SJiawen Wu /* mode select to RGMII-to-copper or RGMII-to-sfi*/ 24944e97550SJiawen Wu if (hw->phy.type == ngbe_phy_mvl) 25044e97550SJiawen Wu ctrl = MVL_GEN_CTL_MODE_COPPER; 25144e97550SJiawen Wu else 25244e97550SJiawen Wu ctrl = MVL_GEN_CTL_MODE_FIBER; 25344e97550SJiawen Wu status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl); 25444e97550SJiawen Wu /* mode reset */ 25544e97550SJiawen Wu ctrl |= MVL_GEN_CTL_RESET; 25644e97550SJiawen Wu status = ngbe_write_phy_reg_mdi(hw, MVL_GEN_CTL, 0, ctrl); 25744e97550SJiawen Wu 25844e97550SJiawen Wu for (i = 0; i < MVL_PHY_RST_WAIT_PERIOD; i++) { 25944e97550SJiawen Wu status = ngbe_read_phy_reg_mdi(hw, MVL_GEN_CTL, 0, &ctrl); 26044e97550SJiawen Wu if (!(ctrl & MVL_GEN_CTL_RESET)) 26144e97550SJiawen Wu break; 26244e97550SJiawen Wu msleep(1); 26344e97550SJiawen Wu } 26444e97550SJiawen Wu 26544e97550SJiawen Wu if (i == MVL_PHY_RST_WAIT_PERIOD) { 266c811e6a4SJiawen Wu DEBUGOUT("PHY reset polling failed to complete."); 26744e97550SJiawen Wu return NGBE_ERR_RESET_FAILED; 26844e97550SJiawen Wu } 26944e97550SJiawen Wu 27044e97550SJiawen Wu return status; 27144e97550SJiawen Wu } 27244e97550SJiawen Wu 273f40e9f0eSJiawen Wu s32 ngbe_get_phy_advertised_pause_mvl(struct ngbe_hw *hw, u8 *pause_bit) 274f40e9f0eSJiawen Wu { 275f40e9f0eSJiawen Wu u16 value; 276f40e9f0eSJiawen Wu s32 status = 0; 277f40e9f0eSJiawen Wu 278f40e9f0eSJiawen Wu if (hw->phy.type == ngbe_phy_mvl) { 279f40e9f0eSJiawen Wu status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); 280f40e9f0eSJiawen Wu value &= MVL_CANA_ASM_PAUSE | MVL_CANA_PAUSE; 281f40e9f0eSJiawen Wu *pause_bit = (u8)(value >> 10); 282f40e9f0eSJiawen Wu } else { 283f40e9f0eSJiawen Wu status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); 284f40e9f0eSJiawen Wu value &= MVL_FANA_PAUSE_MASK; 285f40e9f0eSJiawen Wu *pause_bit = (u8)(value >> 7); 286f40e9f0eSJiawen Wu } 287f40e9f0eSJiawen Wu 288f40e9f0eSJiawen Wu return status; 289f40e9f0eSJiawen Wu } 290f40e9f0eSJiawen Wu 291f40e9f0eSJiawen Wu s32 ngbe_get_phy_lp_advertised_pause_mvl(struct ngbe_hw *hw, u8 *pause_bit) 292f40e9f0eSJiawen Wu { 293f40e9f0eSJiawen Wu u16 value; 294f40e9f0eSJiawen Wu s32 status = 0; 295f40e9f0eSJiawen Wu 296f40e9f0eSJiawen Wu if (hw->phy.type == ngbe_phy_mvl) { 297f40e9f0eSJiawen Wu status = hw->phy.read_reg(hw, MVL_LPAR, 0, &value); 298f40e9f0eSJiawen Wu value &= MVL_CLPAR_ASM_PAUSE | MVL_CLPAR_PAUSE; 299f40e9f0eSJiawen Wu *pause_bit = (u8)(value >> 10); 300f40e9f0eSJiawen Wu } else { 301f40e9f0eSJiawen Wu status = hw->phy.read_reg(hw, MVL_LPAR, 0, &value); 302f40e9f0eSJiawen Wu value &= MVL_FLPAR_PAUSE_MASK; 303f40e9f0eSJiawen Wu *pause_bit = (u8)(value >> 7); 304f40e9f0eSJiawen Wu } 305f40e9f0eSJiawen Wu 306f40e9f0eSJiawen Wu return status; 307f40e9f0eSJiawen Wu } 308f40e9f0eSJiawen Wu 309f40e9f0eSJiawen Wu s32 ngbe_set_phy_pause_adv_mvl(struct ngbe_hw *hw, u16 pause_bit) 310f40e9f0eSJiawen Wu { 311f40e9f0eSJiawen Wu u16 value; 312f40e9f0eSJiawen Wu s32 status = 0; 313f40e9f0eSJiawen Wu 314f40e9f0eSJiawen Wu if (hw->phy.type == ngbe_phy_mvl) { 315f40e9f0eSJiawen Wu status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); 316f40e9f0eSJiawen Wu value &= ~(MVL_CANA_ASM_PAUSE | MVL_CANA_PAUSE); 317f40e9f0eSJiawen Wu } else { 318f40e9f0eSJiawen Wu status = hw->phy.read_reg(hw, MVL_ANA, 0, &value); 319f40e9f0eSJiawen Wu value &= ~MVL_FANA_PAUSE_MASK; 320f40e9f0eSJiawen Wu } 321f40e9f0eSJiawen Wu 322f40e9f0eSJiawen Wu value |= pause_bit; 323f40e9f0eSJiawen Wu status = hw->phy.write_reg(hw, MVL_ANA, 0, value); 324f40e9f0eSJiawen Wu 325f40e9f0eSJiawen Wu return status; 326f40e9f0eSJiawen Wu } 327f40e9f0eSJiawen Wu 3283d0af706SJiawen Wu s32 ngbe_check_phy_link_mvl(struct ngbe_hw *hw, 3293d0af706SJiawen Wu u32 *speed, bool *link_up) 3303d0af706SJiawen Wu { 3313d0af706SJiawen Wu s32 status = 0; 3323d0af706SJiawen Wu u16 phy_link = 0; 3333d0af706SJiawen Wu u16 phy_speed = 0; 3343d0af706SJiawen Wu u16 phy_data = 0; 3353d0af706SJiawen Wu u16 insr = 0; 3363d0af706SJiawen Wu 3373d0af706SJiawen Wu /* Initialize speed and link to default case */ 3383d0af706SJiawen Wu *link_up = false; 3393d0af706SJiawen Wu *speed = NGBE_LINK_SPEED_UNKNOWN; 3403d0af706SJiawen Wu 3413d0af706SJiawen Wu hw->phy.read_reg(hw, MVL_INTR, 0, &insr); 3423d0af706SJiawen Wu 3433d0af706SJiawen Wu /* 3443d0af706SJiawen Wu * Check current speed and link status of the PHY register. 3453d0af706SJiawen Wu * This is a vendor specific register and may have to 3463d0af706SJiawen Wu * be changed for other copper PHYs. 3473d0af706SJiawen Wu */ 3483d0af706SJiawen Wu status = hw->phy.read_reg(hw, MVL_PHYSR, 0, &phy_data); 3493d0af706SJiawen Wu phy_link = phy_data & MVL_PHYSR_LINK; 3503d0af706SJiawen Wu phy_speed = phy_data & MVL_PHYSR_SPEED_MASK; 3513d0af706SJiawen Wu 3523d0af706SJiawen Wu if (phy_link == MVL_PHYSR_LINK) { 3533d0af706SJiawen Wu *link_up = true; 3543d0af706SJiawen Wu 3553d0af706SJiawen Wu if (phy_speed == MVL_PHYSR_SPEED_1000M) 3563d0af706SJiawen Wu *speed = NGBE_LINK_SPEED_1GB_FULL; 3573d0af706SJiawen Wu else if (phy_speed == MVL_PHYSR_SPEED_100M) 3583d0af706SJiawen Wu *speed = NGBE_LINK_SPEED_100M_FULL; 3593d0af706SJiawen Wu else if (phy_speed == MVL_PHYSR_SPEED_10M) 3603d0af706SJiawen Wu *speed = NGBE_LINK_SPEED_10M_FULL; 3613d0af706SJiawen Wu } 3623d0af706SJiawen Wu 3633d0af706SJiawen Wu return status; 3643d0af706SJiawen Wu } 3653d0af706SJiawen Wu 366708ebe7dSJiawen Wu s32 ngbe_set_phy_power_mvl(struct ngbe_hw *hw, bool on) 367708ebe7dSJiawen Wu { 368708ebe7dSJiawen Wu u16 value = 0; 369708ebe7dSJiawen Wu 370708ebe7dSJiawen Wu hw->phy.read_reg(hw, MVL_CTRL, 0, &value); 371708ebe7dSJiawen Wu if (on) 372708ebe7dSJiawen Wu value &= ~MVL_CTRL_PWDN; 373708ebe7dSJiawen Wu else 374708ebe7dSJiawen Wu value |= MVL_CTRL_PWDN; 375708ebe7dSJiawen Wu hw->phy.write_reg(hw, MVL_CTRL, 0, value); 376708ebe7dSJiawen Wu 377708ebe7dSJiawen Wu return 0; 378708ebe7dSJiawen Wu } 379