1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2018-2021 Beijing WangXun Technology Co., Ltd. 3 * Copyright(c) 2010-2017 Intel Corporation 4 */ 5 6 #include "ngbe_hw.h" 7 #include "ngbe_phy.h" 8 9 s32 ngbe_mdi_map_register(mdi_reg_t *reg, mdi_reg_22_t *reg22) 10 { 11 bool match = 1; 12 switch (reg->device_type) { 13 case NGBE_MD_DEV_PMA_PMD: 14 switch (reg->addr) { 15 case NGBE_MD_PHY_ID_HIGH: 16 case NGBE_MD_PHY_ID_LOW: 17 reg22->page = 0; 18 reg22->addr = reg->addr; 19 reg22->device_type = 0; 20 break; 21 default: 22 match = 0; 23 } 24 break; 25 default: 26 match = 0; 27 break; 28 } 29 30 if (!match) { 31 reg22->page = reg->device_type; 32 reg22->device_type = reg->device_type; 33 reg22->addr = reg->addr; 34 } 35 36 return 0; 37 } 38 39 /** 40 * ngbe_probe_phy - Identify a single address for a PHY 41 * @hw: pointer to hardware structure 42 * @phy_addr: PHY address to probe 43 * 44 * Returns true if PHY found 45 */ 46 static bool ngbe_probe_phy(struct ngbe_hw *hw, u16 phy_addr) 47 { 48 if (!ngbe_validate_phy_addr(hw, phy_addr)) { 49 DEBUGOUT("Unable to validate PHY address 0x%04X", 50 phy_addr); 51 return false; 52 } 53 54 if (ngbe_get_phy_id(hw)) 55 return false; 56 57 if (ngbe_get_phy_type_from_id(hw)) 58 return false; 59 60 return true; 61 } 62 63 /** 64 * ngbe_identify_phy - Get physical layer module 65 * @hw: pointer to hardware structure 66 * 67 * Determines the physical layer module found on the current adapter. 68 **/ 69 s32 ngbe_identify_phy(struct ngbe_hw *hw) 70 { 71 s32 err = NGBE_ERR_PHY_ADDR_INVALID; 72 u16 phy_addr; 73 74 if (hw->phy.type != ngbe_phy_unknown) 75 return 0; 76 77 /* select clause22 */ 78 wr32(hw, NGBE_MDIOMODE, NGBE_MDIOMODE_MASK); 79 80 for (phy_addr = 0; phy_addr < NGBE_MAX_PHY_ADDR; phy_addr++) { 81 if (ngbe_probe_phy(hw, phy_addr)) { 82 err = 0; 83 break; 84 } 85 } 86 87 return err; 88 } 89 90 /** 91 * ngbe_check_reset_blocked - check status of MNG FW veto bit 92 * @hw: pointer to the hardware structure 93 * 94 * This function checks the STAT.MNGVETO bit to see if there are 95 * any constraints on link from manageability. For MAC's that don't 96 * have this bit just return faluse since the link can not be blocked 97 * via this method. 98 **/ 99 s32 ngbe_check_reset_blocked(struct ngbe_hw *hw) 100 { 101 u32 mmngc; 102 103 mmngc = rd32(hw, NGBE_STAT); 104 if (mmngc & NGBE_STAT_MNGVETO) { 105 DEBUGOUT("MNG_VETO bit detected."); 106 return true; 107 } 108 109 return false; 110 } 111 112 /** 113 * ngbe_validate_phy_addr - Determines phy address is valid 114 * @hw: pointer to hardware structure 115 * @phy_addr: PHY address 116 * 117 **/ 118 bool ngbe_validate_phy_addr(struct ngbe_hw *hw, u32 phy_addr) 119 { 120 u16 phy_id = 0; 121 bool valid = false; 122 123 hw->phy.addr = phy_addr; 124 hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW, 125 NGBE_MD_DEV_PMA_PMD, &phy_id); 126 127 if (phy_id != 0xFFFF && phy_id != 0x0) 128 valid = true; 129 130 DEBUGOUT("PHY ID LOW is 0x%04X", phy_id); 131 132 return valid; 133 } 134 135 /** 136 * ngbe_get_phy_id - Get the phy ID 137 * @hw: pointer to hardware structure 138 * 139 **/ 140 s32 ngbe_get_phy_id(struct ngbe_hw *hw) 141 { 142 u32 err; 143 u16 phy_id_high = 0; 144 u16 phy_id_low = 0; 145 146 err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH, 147 NGBE_MD_DEV_PMA_PMD, 148 &phy_id_high); 149 hw->phy.id = (u32)(phy_id_high << 16); 150 151 err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW, 152 NGBE_MD_DEV_PMA_PMD, 153 &phy_id_low); 154 hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK); 155 hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK); 156 157 DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X", 158 phy_id_high, phy_id_low); 159 160 return err; 161 } 162 163 /** 164 * ngbe_get_phy_type_from_id - Get the phy type 165 * 166 **/ 167 s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw) 168 { 169 s32 status = 0; 170 171 switch (hw->phy.id) { 172 case NGBE_PHYID_RTL: 173 hw->phy.type = ngbe_phy_rtl; 174 break; 175 case NGBE_PHYID_MVL: 176 if (hw->phy.media_type == ngbe_media_type_fiber) 177 hw->phy.type = ngbe_phy_mvl_sfi; 178 else if (hw->phy.media_type == ngbe_media_type_copper) 179 hw->phy.type = ngbe_phy_mvl; 180 else 181 status = ngbe_check_phy_mode_mvl(hw); 182 break; 183 case NGBE_PHYID_YT8521: 184 case NGBE_PHYID_YT8531: 185 if (hw->phy.media_type == ngbe_media_type_fiber) 186 hw->phy.type = ngbe_phy_yt8521s_sfi; 187 else 188 hw->phy.type = ngbe_phy_yt8521s; 189 break; 190 default: 191 hw->phy.type = ngbe_phy_unknown; 192 status = NGBE_ERR_DEVICE_NOT_SUPPORTED; 193 break; 194 } 195 196 return status; 197 } 198 199 /** 200 * ngbe_reset_phy - Performs a PHY reset 201 * @hw: pointer to hardware structure 202 **/ 203 s32 ngbe_reset_phy(struct ngbe_hw *hw) 204 { 205 s32 err = 0; 206 207 if (hw->phy.type == ngbe_phy_unknown) 208 err = ngbe_identify_phy(hw); 209 210 if (err != 0 || hw->phy.type == ngbe_phy_none) 211 return err; 212 213 if (hw->ncsi_enabled) 214 return err; 215 216 /* Don't reset PHY if it's shut down due to overtemp. */ 217 if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP) 218 return err; 219 220 /* Blocked by MNG FW so bail */ 221 if (ngbe_check_reset_blocked(hw)) 222 return err; 223 224 switch (hw->phy.type) { 225 case ngbe_phy_rtl: 226 err = ngbe_reset_phy_rtl(hw); 227 break; 228 case ngbe_phy_mvl: 229 case ngbe_phy_mvl_sfi: 230 err = ngbe_reset_phy_mvl(hw); 231 break; 232 case ngbe_phy_yt8521s: 233 case ngbe_phy_yt8521s_sfi: 234 err = ngbe_reset_phy_yt(hw); 235 break; 236 default: 237 break; 238 } 239 240 return err; 241 } 242 243 /** 244 * ngbe_read_phy_mdi - Reads a value from a specified PHY register without 245 * the SWFW lock 246 * @hw: pointer to hardware structure 247 * @reg_addr: 32 bit address of PHY register to read 248 * @device_type: 5 bit device type 249 * @phy_data: Pointer to read data from PHY register 250 **/ 251 s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, 252 u16 *phy_data) 253 { 254 u32 command, data; 255 256 /* Setup and write the address cycle command */ 257 command = NGBE_MDIOSCA_REG(reg_addr) | 258 NGBE_MDIOSCA_DEV(device_type) | 259 NGBE_MDIOSCA_PORT(hw->phy.addr); 260 wr32(hw, NGBE_MDIOSCA, command); 261 262 command = NGBE_MDIOSCD_CMD_READ | 263 NGBE_MDIOSCD_BUSY | 264 NGBE_MDIOSCD_CLOCK(6); 265 wr32(hw, NGBE_MDIOSCD, command); 266 267 /* 268 * Check every 10 usec to see if the address cycle completed. 269 * The MDI Command bit will clear when the operation is 270 * complete 271 */ 272 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, 273 0, NULL, 100, 100)) { 274 DEBUGOUT("PHY address command did not complete"); 275 return NGBE_ERR_PHY; 276 } 277 278 data = rd32(hw, NGBE_MDIOSCD); 279 *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data); 280 281 return 0; 282 } 283 284 /** 285 * ngbe_read_phy_reg - Reads a value from a specified PHY register 286 * using the SWFW lock - this function is needed in most cases 287 * @hw: pointer to hardware structure 288 * @reg_addr: 32 bit address of PHY register to read 289 * @device_type: 5 bit device type 290 * @phy_data: Pointer to read data from PHY register 291 **/ 292 s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr, 293 u32 device_type, u16 *phy_data) 294 { 295 s32 err; 296 297 err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type, 298 phy_data); 299 300 return err; 301 } 302 303 /** 304 * ngbe_write_phy_reg_mdi - Writes a value to specified PHY register 305 * without SWFW lock 306 * @hw: pointer to hardware structure 307 * @reg_addr: 32 bit PHY register to write 308 * @device_type: 5 bit device type 309 * @phy_data: Data to write to the PHY register 310 **/ 311 s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, 312 u32 device_type, u16 phy_data) 313 { 314 u32 command; 315 316 /* write command */ 317 command = NGBE_MDIOSCA_REG(reg_addr) | 318 NGBE_MDIOSCA_DEV(device_type) | 319 NGBE_MDIOSCA_PORT(hw->phy.addr); 320 wr32(hw, NGBE_MDIOSCA, command); 321 322 command = NGBE_MDIOSCD_CMD_WRITE | 323 NGBE_MDIOSCD_DAT(phy_data) | 324 NGBE_MDIOSCD_BUSY | 325 NGBE_MDIOSCD_CLOCK(6); 326 wr32(hw, NGBE_MDIOSCD, command); 327 328 /* wait for completion */ 329 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, 330 0, NULL, 100, 100)) { 331 DEBUGOUT("PHY write cmd didn't complete"); 332 return NGBE_ERR_PHY; 333 } 334 335 return 0; 336 } 337 338 /** 339 * ngbe_write_phy_reg - Writes a value to specified PHY register 340 * using SWFW lock- this function is needed in most cases 341 * @hw: pointer to hardware structure 342 * @reg_addr: 32 bit PHY register to write 343 * @device_type: 5 bit device type 344 * @phy_data: Data to write to the PHY register 345 **/ 346 s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr, 347 u32 device_type, u16 phy_data) 348 { 349 s32 err; 350 351 err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type, 352 phy_data); 353 354 return err; 355 } 356 357 /** 358 * ngbe_init_phy - PHY specific init 359 * @hw: pointer to hardware structure 360 * 361 * Initialize any function pointers that were not able to be 362 * set during init_shared_code because the PHY type was 363 * not known. 364 * 365 **/ 366 s32 ngbe_init_phy(struct ngbe_hw *hw) 367 { 368 struct ngbe_phy_info *phy = &hw->phy; 369 s32 err = 0; 370 371 hw->phy.addr = 0; 372 373 switch (hw->sub_device_id) { 374 case NGBE_SUB_DEV_ID_EM_RTL_SGMII: 375 case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP: 376 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl; 377 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl; 378 break; 379 case NGBE_SUB_DEV_ID_EM_MVL_RGMII: 380 case NGBE_SUB_DEV_ID_EM_MVL_SFP: 381 case NGBE_SUB_DEV_ID_EM_MVL_MIX: 382 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl; 383 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl; 384 break; 385 case NGBE_SUB_DEV_ID_EM_YT8521S_SFP: 386 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt; 387 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt; 388 break; 389 default: 390 break; 391 } 392 393 hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY; 394 395 /* Identify the PHY */ 396 err = phy->identify(hw); 397 if (err == NGBE_ERR_PHY_ADDR_INVALID) 398 goto init_phy_ops_out; 399 400 /* Set necessary function pointers based on PHY type */ 401 switch (hw->phy.type) { 402 case ngbe_phy_rtl: 403 hw->phy.init_hw = ngbe_init_phy_rtl; 404 hw->phy.check_link = ngbe_check_phy_link_rtl; 405 hw->phy.setup_link = ngbe_setup_phy_link_rtl; 406 hw->phy.set_phy_power = ngbe_set_phy_power_rtl; 407 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_rtl; 408 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_rtl; 409 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_rtl; 410 break; 411 case ngbe_phy_mvl: 412 case ngbe_phy_mvl_sfi: 413 hw->phy.init_hw = ngbe_init_phy_mvl; 414 hw->phy.check_link = ngbe_check_phy_link_mvl; 415 hw->phy.setup_link = ngbe_setup_phy_link_mvl; 416 hw->phy.set_phy_power = ngbe_set_phy_power_mvl; 417 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_mvl; 418 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_mvl; 419 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_mvl; 420 break; 421 case ngbe_phy_yt8521s: 422 case ngbe_phy_yt8521s_sfi: 423 hw->phy.init_hw = ngbe_init_phy_yt; 424 hw->phy.check_link = ngbe_check_phy_link_yt; 425 hw->phy.setup_link = ngbe_setup_phy_link_yt; 426 hw->phy.set_phy_power = ngbe_set_phy_power_yt; 427 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_yt; 428 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_yt; 429 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_yt; 430 default: 431 break; 432 } 433 434 if (hw->wol_enabled || hw->ncsi_enabled) 435 hw->phy.reset_disable = true; 436 437 init_phy_ops_out: 438 return err; 439 } 440 441