1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 3 */ 4 5 #include "ngbe_phy_rtl.h" 6 7 s32 ngbe_read_phy_reg_rtl(struct ngbe_hw *hw, 8 u32 reg_addr, u32 device_type, u16 *phy_data) 9 { 10 mdi_reg_t reg; 11 mdi_reg_22_t reg22; 12 13 reg.device_type = device_type; 14 reg.addr = reg_addr; 15 ngbe_mdi_map_register(®, ®22); 16 17 if (!(reg22.page == 0xa43 && 18 (reg22.addr == 0x1a || reg22.addr == 0x1d))) 19 wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page); 20 *phy_data = 0xFFFF & rd32(hw, NGBE_PHY_CONFIG(reg22.addr)); 21 22 return 0; 23 } 24 25 s32 ngbe_write_phy_reg_rtl(struct ngbe_hw *hw, 26 u32 reg_addr, u32 device_type, u16 phy_data) 27 { 28 mdi_reg_t reg; 29 mdi_reg_22_t reg22; 30 31 reg.device_type = device_type; 32 reg.addr = reg_addr; 33 ngbe_mdi_map_register(®, ®22); 34 35 if (!(reg22.page == 0xa43 && 36 (reg22.addr == 0x1a || reg22.addr == 0x1d))) 37 wr32(hw, NGBE_PHY_CONFIG(RTL_PAGE_SELECT), reg22.page); 38 wr32(hw, NGBE_PHY_CONFIG(reg22.addr), phy_data); 39 40 return 0; 41 } 42 43 static void ngbe_phy_led_ctrl_rtl(struct ngbe_hw *hw) 44 { 45 u16 value = 0; 46 47 if (hw->led_conf != 0xFFFF) 48 value = hw->led_conf & 0xFFFF; 49 else 50 value = 0x205B; 51 52 hw->phy.write_reg(hw, RTL_LCR, 0xd04, value); 53 hw->phy.write_reg(hw, RTL_EEELCR, 0xd04, 0); 54 55 hw->phy.read_reg(hw, RTL_LPCR, 0xd04, &value); 56 if (hw->led_conf != 0xFFFF) { 57 value &= ~0x73; 58 value |= hw->led_conf >> 16; 59 } else { 60 value &= 0xFFFC; 61 /*act led blinking mode set to 60ms*/ 62 value |= 0x2; 63 } 64 hw->phy.write_reg(hw, RTL_LPCR, 0xd04, value); 65 } 66 67 static s32 ngbe_wait_mdio_access_on(struct ngbe_hw *hw) 68 { 69 int i; 70 u16 val = 0; 71 72 for (i = 0; i < 100; i++) { 73 /* irq status */ 74 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &val); 75 if (val & RTL_INSR_ACCESS) 76 break; 77 msec_delay(1); 78 } 79 80 if (i == 100) { 81 DEBUGOUT("wait_mdio_access_on timeout"); 82 return NGBE_ERR_PHY_TIMEOUT; 83 } 84 85 return 0; 86 } 87 88 static void ngbe_efuse_calibration(struct ngbe_hw *hw) 89 { 90 u32 efuse[2]; 91 92 ngbe_wait_mdio_access_on(hw); 93 94 efuse[0] = hw->gphy_efuse[0]; 95 efuse[1] = hw->gphy_efuse[1]; 96 97 if (!efuse[0] && !efuse[1]) { 98 efuse[0] = 0xFFFFFFFF; 99 efuse[1] = 0xFFFFFFFF; 100 } 101 102 /* calibration */ 103 efuse[0] |= 0xF0000100; 104 efuse[1] |= 0xFF807FFF; 105 DEBUGOUT("port %d efuse[0] = %08x, efuse[1] = %08x", 106 hw->bus.lan_id, efuse[0], efuse[1]); 107 108 /* EODR, Efuse Output Data Register */ 109 hw->phy.write_reg(hw, 16, 0xa46, (efuse[0] >> 0) & 0xFFFF); 110 hw->phy.write_reg(hw, 17, 0xa46, (efuse[0] >> 16) & 0xFFFF); 111 hw->phy.write_reg(hw, 18, 0xa46, (efuse[1] >> 0) & 0xFFFF); 112 hw->phy.write_reg(hw, 19, 0xa46, (efuse[1] >> 16) & 0xFFFF); 113 } 114 115 s32 ngbe_init_phy_rtl(struct ngbe_hw *hw) 116 { 117 int i; 118 u16 value = 0; 119 120 hw->init_phy = true; 121 msec_delay(1); 122 123 hw->phy.set_phy_power(hw, true); 124 125 for (i = 0; i < 15; i++) { 126 if (!rd32m(hw, NGBE_STAT, 127 NGBE_STAT_GPHY_IN_RST(hw->bus.lan_id))) 128 break; 129 130 msec_delay(10); 131 } 132 if (i == 15) { 133 DEBUGOUT("GPhy reset exceeds maximum times."); 134 return NGBE_ERR_PHY_TIMEOUT; 135 } 136 137 ngbe_efuse_calibration(hw); 138 139 hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EFUSE); 140 hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value); 141 if (!(value & RTL_SCR_EFUSE)) { 142 DEBUGOUT("Write EFUSE failed."); 143 return NGBE_ERR_PHY_TIMEOUT; 144 } 145 146 ngbe_wait_mdio_access_on(hw); 147 148 hw->phy.write_reg(hw, 27, 0xa42, 0x8011); 149 hw->phy.write_reg(hw, 28, 0xa42, 0x5737); 150 151 /* Disable fall to 100m if signal is not good */ 152 hw->phy.read_reg(hw, 17, 0xa44, &value); 153 value &= ~0x8; 154 hw->phy.write_reg(hw, 17, 0xa44, value); 155 156 hw->phy.write_reg(hw, RTL_SCR, 0xa46, RTL_SCR_EXTINI); 157 hw->phy.read_reg(hw, RTL_SCR, 0xa46, &value); 158 if (!(value & RTL_SCR_EXTINI)) { 159 DEBUGOUT("Write EXIINI failed."); 160 return NGBE_ERR_PHY_TIMEOUT; 161 } 162 163 ngbe_wait_mdio_access_on(hw); 164 165 for (i = 0; i < 100; i++) { 166 hw->phy.read_reg(hw, RTL_GSR, 0xa42, &value); 167 if ((value & RTL_GSR_ST) == RTL_GSR_ST_LANON) 168 break; 169 msec_delay(1); 170 } 171 if (i == 100) 172 return NGBE_ERR_PHY_TIMEOUT; 173 174 /* Disable EEE */ 175 hw->phy.write_reg(hw, 0x11, 0xa4b, 0x1110); 176 hw->phy.write_reg(hw, 0xd, 0x0, 0x0007); 177 hw->phy.write_reg(hw, 0xe, 0x0, 0x003c); 178 hw->phy.write_reg(hw, 0xd, 0x0, 0x4007); 179 hw->phy.write_reg(hw, 0xe, 0x0, 0x0000); 180 181 hw->init_phy = false; 182 183 return 0; 184 } 185 186 /** 187 * ngbe_setup_phy_link_rtl - Set and restart auto-neg 188 * @hw: pointer to hardware structure 189 * 190 * Restart auto-negotiation and PHY and waits for completion. 191 **/ 192 s32 ngbe_setup_phy_link_rtl(struct ngbe_hw *hw, 193 u32 speed, bool autoneg_wait_to_complete) 194 { 195 u16 autoneg_reg = NGBE_MII_AUTONEG_REG; 196 u16 value = 0; 197 198 UNREFERENCED_PARAMETER(autoneg_wait_to_complete); 199 200 hw->init_phy = true; 201 msec_delay(1); 202 203 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &autoneg_reg); 204 205 if (!hw->mac.autoneg) { 206 hw->phy.reset_hw(hw); 207 208 switch (speed) { 209 case NGBE_LINK_SPEED_1GB_FULL: 210 value = RTL_BMCR_SPEED_SELECT1; 211 break; 212 case NGBE_LINK_SPEED_100M_FULL: 213 value = RTL_BMCR_SPEED_SELECT0; 214 break; 215 case NGBE_LINK_SPEED_10M_FULL: 216 value = 0; 217 break; 218 default: 219 value = RTL_BMCR_SPEED_SELECT1 | RTL_BMCR_SPEED_SELECT0; 220 DEBUGOUT("unknown speed = 0x%x.", speed); 221 break; 222 } 223 /* duplex full */ 224 value |= RTL_BMCR_DUPLEX; 225 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value); 226 227 goto skip_an; 228 } 229 230 /* 231 * Clear autoneg_advertised and set new values based on input link 232 * speed. 233 */ 234 if (speed) { 235 hw->phy.autoneg_advertised = 0; 236 237 if (speed & NGBE_LINK_SPEED_1GB_FULL) 238 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_1GB_FULL; 239 240 if (speed & NGBE_LINK_SPEED_100M_FULL) 241 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_100M_FULL; 242 243 if (speed & NGBE_LINK_SPEED_10M_FULL) 244 hw->phy.autoneg_advertised |= NGBE_LINK_SPEED_10M_FULL; 245 } 246 247 /* disable 10/100M Half Duplex */ 248 hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &autoneg_reg); 249 autoneg_reg &= 0xFF5F; 250 hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, autoneg_reg); 251 252 /* set advertise enable according to input speed */ 253 if (!(speed & NGBE_LINK_SPEED_1GB_FULL)) { 254 hw->phy.read_reg(hw, RTL_GBCR, 255 RTL_DEV_ZERO, &autoneg_reg); 256 autoneg_reg &= ~RTL_GBCR_1000F; 257 hw->phy.write_reg(hw, RTL_GBCR, 258 RTL_DEV_ZERO, autoneg_reg); 259 } else { 260 hw->phy.read_reg(hw, RTL_GBCR, 261 RTL_DEV_ZERO, &autoneg_reg); 262 autoneg_reg |= RTL_GBCR_1000F; 263 hw->phy.write_reg(hw, RTL_GBCR, 264 RTL_DEV_ZERO, autoneg_reg); 265 } 266 267 if (!(speed & NGBE_LINK_SPEED_100M_FULL)) { 268 hw->phy.read_reg(hw, RTL_ANAR, 269 RTL_DEV_ZERO, &autoneg_reg); 270 autoneg_reg &= ~RTL_ANAR_100F; 271 autoneg_reg &= ~RTL_ANAR_100H; 272 hw->phy.write_reg(hw, RTL_ANAR, 273 RTL_DEV_ZERO, autoneg_reg); 274 } else { 275 hw->phy.read_reg(hw, RTL_ANAR, 276 RTL_DEV_ZERO, &autoneg_reg); 277 autoneg_reg |= RTL_ANAR_100F; 278 hw->phy.write_reg(hw, RTL_ANAR, 279 RTL_DEV_ZERO, autoneg_reg); 280 } 281 282 if (!(speed & NGBE_LINK_SPEED_10M_FULL)) { 283 hw->phy.read_reg(hw, RTL_ANAR, 284 RTL_DEV_ZERO, &autoneg_reg); 285 autoneg_reg &= ~RTL_ANAR_10F; 286 autoneg_reg &= ~RTL_ANAR_10H; 287 hw->phy.write_reg(hw, RTL_ANAR, 288 RTL_DEV_ZERO, autoneg_reg); 289 } else { 290 hw->phy.read_reg(hw, RTL_ANAR, 291 RTL_DEV_ZERO, &autoneg_reg); 292 autoneg_reg |= RTL_ANAR_10F; 293 hw->phy.write_reg(hw, RTL_ANAR, 294 RTL_DEV_ZERO, autoneg_reg); 295 } 296 297 /* restart AN and wait AN done interrupt */ 298 if (!hw->ncsi_enabled) 299 autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE; 300 else 301 autoneg_reg = RTL_BMCR_ANE; 302 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg); 303 304 skip_an: 305 ngbe_phy_led_ctrl_rtl(hw); 306 307 hw->init_phy = false; 308 309 return 0; 310 } 311 312 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw) 313 { 314 u16 value = 0; 315 s32 status = 0; 316 317 value |= RTL_BMCR_RESET; 318 status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value); 319 320 msec_delay(5); 321 322 return status; 323 } 324 325 s32 ngbe_get_phy_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit) 326 { 327 u16 value; 328 s32 status = 0; 329 330 status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value); 331 value &= RTL_ANAR_APAUSE | RTL_ANAR_PAUSE; 332 *pause_bit = (u8)(value >> 10); 333 return status; 334 } 335 336 s32 ngbe_get_phy_lp_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit) 337 { 338 u16 value; 339 s32 status = 0; 340 341 status = hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value); 342 343 status = hw->phy.read_reg(hw, RTL_BMSR, RTL_DEV_ZERO, &value); 344 value = value & RTL_BMSR_ANC; 345 346 /* if AN complete then check lp adv pause */ 347 status = hw->phy.read_reg(hw, RTL_ANLPAR, RTL_DEV_ZERO, &value); 348 value &= RTL_ANLPAR_LP; 349 *pause_bit = (u8)(value >> 10); 350 return status; 351 } 352 353 s32 ngbe_set_phy_pause_adv_rtl(struct ngbe_hw *hw, u16 pause_bit) 354 { 355 u16 value; 356 s32 status = 0; 357 358 status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value); 359 value &= ~(RTL_ANAR_APAUSE | RTL_ANAR_PAUSE); 360 value |= pause_bit; 361 362 status = hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, value); 363 364 return status; 365 } 366 367 s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up) 368 { 369 s32 status = 0; 370 u16 phy_link = 0; 371 u16 phy_speed = 0; 372 u16 phy_data = 0; 373 u16 insr = 0; 374 375 if (hw->init_phy) 376 return -1; 377 378 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr); 379 380 /* Initialize speed and link to default case */ 381 *link_up = false; 382 *speed = NGBE_LINK_SPEED_UNKNOWN; 383 384 /* 385 * Check current speed and link status of the PHY register. 386 * This is a vendor specific register and may have to 387 * be changed for other copper PHYs. 388 */ 389 status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data); 390 phy_link = phy_data & RTL_PHYSR_RTLS; 391 phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP); 392 if (phy_link == RTL_PHYSR_RTLS) { 393 *link_up = true; 394 395 if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP)) 396 *speed = NGBE_LINK_SPEED_1GB_FULL; 397 else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP)) 398 *speed = NGBE_LINK_SPEED_100M_FULL; 399 else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP)) 400 *speed = NGBE_LINK_SPEED_10M_FULL; 401 } 402 403 if (hw->lsc) 404 return status; 405 406 /* 407 * Because of the slow speed of getting link state, RTL_PHYSR 408 * may still be up while the actual link state is down. 409 * So we read RTL_GBSR to get accurate state when speed is 1G 410 * in polling mode. 411 */ 412 if (*speed == NGBE_LINK_SPEED_1GB_FULL) { 413 status = hw->phy.read_reg(hw, RTL_GBSR, 414 RTL_DEV_ZERO, &phy_data); 415 phy_link = phy_data & RTL_GBSR_LRS; 416 417 /* Only need to detect link down */ 418 if (!phy_link) { 419 *link_up = false; 420 *speed = NGBE_LINK_SPEED_UNKNOWN; 421 } 422 } 423 return status; 424 } 425 426 s32 ngbe_set_phy_power_rtl(struct ngbe_hw *hw, bool on) 427 { 428 u16 value = 0; 429 430 hw->phy.read_reg(hw, RTL_BMCR, 0, &value); 431 if (on) 432 value &= ~RTL_BMCR_PWDN; 433 else 434 value |= RTL_BMCR_PWDN; 435 hw->phy.write_reg(hw, RTL_BMCR, 0, value); 436 437 return 0; 438 } 439