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 autoneg_reg = RTL_BMCR_RESTART_AN | RTL_BMCR_ANE; 299 hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, autoneg_reg); 300 301 skip_an: 302 ngbe_phy_led_ctrl_rtl(hw); 303 304 hw->init_phy = false; 305 306 return 0; 307 } 308 309 s32 ngbe_reset_phy_rtl(struct ngbe_hw *hw) 310 { 311 u16 value = 0; 312 s32 status = 0; 313 314 value |= RTL_BMCR_RESET; 315 status = hw->phy.write_reg(hw, RTL_BMCR, RTL_DEV_ZERO, value); 316 317 msec_delay(5); 318 319 return status; 320 } 321 322 s32 ngbe_get_phy_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit) 323 { 324 u16 value; 325 s32 status = 0; 326 327 status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value); 328 value &= RTL_ANAR_APAUSE | RTL_ANAR_PAUSE; 329 *pause_bit = (u8)(value >> 10); 330 return status; 331 } 332 333 s32 ngbe_get_phy_lp_advertised_pause_rtl(struct ngbe_hw *hw, u8 *pause_bit) 334 { 335 u16 value; 336 s32 status = 0; 337 338 status = hw->phy.read_reg(hw, RTL_INSR, 0xa43, &value); 339 340 status = hw->phy.read_reg(hw, RTL_BMSR, RTL_DEV_ZERO, &value); 341 value = value & RTL_BMSR_ANC; 342 343 /* if AN complete then check lp adv pause */ 344 status = hw->phy.read_reg(hw, RTL_ANLPAR, RTL_DEV_ZERO, &value); 345 value &= RTL_ANLPAR_LP; 346 *pause_bit = (u8)(value >> 10); 347 return status; 348 } 349 350 s32 ngbe_set_phy_pause_adv_rtl(struct ngbe_hw *hw, u16 pause_bit) 351 { 352 u16 value; 353 s32 status = 0; 354 355 status = hw->phy.read_reg(hw, RTL_ANAR, RTL_DEV_ZERO, &value); 356 value &= ~(RTL_ANAR_APAUSE | RTL_ANAR_PAUSE); 357 value |= pause_bit; 358 359 status = hw->phy.write_reg(hw, RTL_ANAR, RTL_DEV_ZERO, value); 360 361 return status; 362 } 363 364 s32 ngbe_check_phy_link_rtl(struct ngbe_hw *hw, u32 *speed, bool *link_up) 365 { 366 s32 status = 0; 367 u16 phy_link = 0; 368 u16 phy_speed = 0; 369 u16 phy_data = 0; 370 u16 insr = 0; 371 372 if (hw->init_phy) 373 return -1; 374 375 hw->phy.read_reg(hw, RTL_INSR, 0xa43, &insr); 376 377 /* Initialize speed and link to default case */ 378 *link_up = false; 379 *speed = NGBE_LINK_SPEED_UNKNOWN; 380 381 /* 382 * Check current speed and link status of the PHY register. 383 * This is a vendor specific register and may have to 384 * be changed for other copper PHYs. 385 */ 386 status = hw->phy.read_reg(hw, RTL_PHYSR, 0xa43, &phy_data); 387 phy_link = phy_data & RTL_PHYSR_RTLS; 388 phy_speed = phy_data & (RTL_PHYSR_SPEED_MASK | RTL_PHYSR_DP); 389 if (phy_link == RTL_PHYSR_RTLS) { 390 *link_up = true; 391 392 if (phy_speed == (RTL_PHYSR_SPEED_1000M | RTL_PHYSR_DP)) 393 *speed = NGBE_LINK_SPEED_1GB_FULL; 394 else if (phy_speed == (RTL_PHYSR_SPEED_100M | RTL_PHYSR_DP)) 395 *speed = NGBE_LINK_SPEED_100M_FULL; 396 else if (phy_speed == (RTL_PHYSR_SPEED_10M | RTL_PHYSR_DP)) 397 *speed = NGBE_LINK_SPEED_10M_FULL; 398 } 399 400 if (hw->lsc) 401 return status; 402 403 /* 404 * Because of the slow speed of getting link state, RTL_PHYSR 405 * may still be up while the actual link state is down. 406 * So we read RTL_GBSR to get accurate state when speed is 1G 407 * in polling mode. 408 */ 409 if (*speed == NGBE_LINK_SPEED_1GB_FULL) { 410 status = hw->phy.read_reg(hw, RTL_GBSR, 411 RTL_DEV_ZERO, &phy_data); 412 phy_link = phy_data & RTL_GBSR_LRS; 413 414 /* Only need to detect link down */ 415 if (!phy_link) { 416 *link_up = false; 417 *speed = NGBE_LINK_SPEED_UNKNOWN; 418 } 419 } 420 return status; 421 } 422 423 s32 ngbe_set_phy_power_rtl(struct ngbe_hw *hw, bool on) 424 { 425 u16 value = 0; 426 427 hw->phy.read_reg(hw, RTL_BMCR, 0, &value); 428 if (on) 429 value &= ~RTL_BMCR_PWDN; 430 else 431 value |= RTL_BMCR_PWDN; 432 hw->phy.write_reg(hw, RTL_BMCR, 0, value); 433 434 return 0; 435 } 436