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 if (hw->sub_device_id == NGBE_SUB_DEV_ID_EM_YT8521S_SFP) 124 return true; 125 126 hw->phy.addr = phy_addr; 127 hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH, 128 NGBE_MD_DEV_PMA_PMD, &phy_id); 129 130 if (phy_id != 0xFFFF && phy_id != 0x0) 131 valid = true; 132 133 DEBUGOUT("PHY ID HIGH is 0x%04X", phy_id); 134 135 return valid; 136 } 137 138 /** 139 * ngbe_get_phy_id - Get the phy ID 140 * @hw: pointer to hardware structure 141 * 142 **/ 143 s32 ngbe_get_phy_id(struct ngbe_hw *hw) 144 { 145 u32 err; 146 u16 phy_id_high = 0; 147 u16 phy_id_low = 0; 148 149 err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_HIGH, 150 NGBE_MD_DEV_PMA_PMD, 151 &phy_id_high); 152 hw->phy.id = (u32)(phy_id_high << 16); 153 154 err = hw->phy.read_reg(hw, NGBE_MD_PHY_ID_LOW, 155 NGBE_MD_DEV_PMA_PMD, 156 &phy_id_low); 157 hw->phy.id |= (u32)(phy_id_low & NGBE_PHY_REVISION_MASK); 158 hw->phy.revision = (u32)(phy_id_low & ~NGBE_PHY_REVISION_MASK); 159 160 DEBUGOUT("PHY_ID_HIGH 0x%04X, PHY_ID_LOW 0x%04X", 161 phy_id_high, phy_id_low); 162 163 return err; 164 } 165 166 /** 167 * ngbe_get_phy_type_from_id - Get the phy type 168 * 169 **/ 170 s32 ngbe_get_phy_type_from_id(struct ngbe_hw *hw) 171 { 172 s32 status = 0; 173 174 switch (hw->phy.id) { 175 case NGBE_PHYID_RTL: 176 hw->phy.type = ngbe_phy_rtl; 177 break; 178 case NGBE_PHYID_MVL: 179 if (hw->phy.media_type == ngbe_media_type_fiber) 180 hw->phy.type = ngbe_phy_mvl_sfi; 181 else if (hw->phy.media_type == ngbe_media_type_copper) 182 hw->phy.type = ngbe_phy_mvl; 183 else 184 status = ngbe_check_phy_mode_mvl(hw); 185 break; 186 case NGBE_PHYID_YT: 187 if (hw->phy.media_type == ngbe_media_type_fiber) 188 hw->phy.type = ngbe_phy_yt8521s_sfi; 189 else 190 hw->phy.type = ngbe_phy_yt8521s; 191 break; 192 default: 193 hw->phy.type = ngbe_phy_unknown; 194 status = NGBE_ERR_DEVICE_NOT_SUPPORTED; 195 break; 196 } 197 198 return status; 199 } 200 201 /** 202 * ngbe_reset_phy - Performs a PHY reset 203 * @hw: pointer to hardware structure 204 **/ 205 s32 ngbe_reset_phy(struct ngbe_hw *hw) 206 { 207 s32 err = 0; 208 209 if (hw->phy.type == ngbe_phy_unknown) 210 err = ngbe_identify_phy(hw); 211 212 if (err != 0 || hw->phy.type == ngbe_phy_none) 213 return err; 214 215 /* Don't reset PHY if it's shut down due to overtemp. */ 216 if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP) 217 return err; 218 219 /* Blocked by MNG FW so bail */ 220 if (ngbe_check_reset_blocked(hw)) 221 return err; 222 223 switch (hw->phy.type) { 224 case ngbe_phy_rtl: 225 err = ngbe_reset_phy_rtl(hw); 226 break; 227 case ngbe_phy_mvl: 228 case ngbe_phy_mvl_sfi: 229 err = ngbe_reset_phy_mvl(hw); 230 break; 231 case ngbe_phy_yt8521s: 232 case ngbe_phy_yt8521s_sfi: 233 err = ngbe_reset_phy_yt(hw); 234 break; 235 default: 236 break; 237 } 238 239 return err; 240 } 241 242 /** 243 * ngbe_read_phy_mdi - Reads a value from a specified PHY register without 244 * the SWFW lock 245 * @hw: pointer to hardware structure 246 * @reg_addr: 32 bit address of PHY register to read 247 * @device_type: 5 bit device type 248 * @phy_data: Pointer to read data from PHY register 249 **/ 250 s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, 251 u16 *phy_data) 252 { 253 u32 command, data; 254 255 /* Setup and write the address cycle command */ 256 command = NGBE_MDIOSCA_REG(reg_addr) | 257 NGBE_MDIOSCA_DEV(device_type) | 258 NGBE_MDIOSCA_PORT(hw->phy.addr); 259 wr32(hw, NGBE_MDIOSCA, command); 260 261 command = NGBE_MDIOSCD_CMD_READ | 262 NGBE_MDIOSCD_BUSY | 263 NGBE_MDIOSCD_CLOCK(6); 264 wr32(hw, NGBE_MDIOSCD, command); 265 266 /* 267 * Check every 10 usec to see if the address cycle completed. 268 * The MDI Command bit will clear when the operation is 269 * complete 270 */ 271 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, 272 0, NULL, 100, 100)) { 273 DEBUGOUT("PHY address command did not complete"); 274 return NGBE_ERR_PHY; 275 } 276 277 data = rd32(hw, NGBE_MDIOSCD); 278 *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data); 279 280 return 0; 281 } 282 283 /** 284 * ngbe_read_phy_reg - Reads a value from a specified PHY register 285 * using the SWFW lock - this function is needed in most cases 286 * @hw: pointer to hardware structure 287 * @reg_addr: 32 bit address of PHY register to read 288 * @device_type: 5 bit device type 289 * @phy_data: Pointer to read data from PHY register 290 **/ 291 s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr, 292 u32 device_type, u16 *phy_data) 293 { 294 s32 err; 295 u32 gssr = hw->phy.phy_semaphore_mask; 296 297 if (hw->mac.acquire_swfw_sync(hw, gssr)) 298 return NGBE_ERR_SWFW_SYNC; 299 300 err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type, 301 phy_data); 302 303 hw->mac.release_swfw_sync(hw, gssr); 304 305 return err; 306 } 307 308 /** 309 * ngbe_write_phy_reg_mdi - Writes a value to specified PHY register 310 * without SWFW lock 311 * @hw: pointer to hardware structure 312 * @reg_addr: 32 bit PHY register to write 313 * @device_type: 5 bit device type 314 * @phy_data: Data to write to the PHY register 315 **/ 316 s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, 317 u32 device_type, u16 phy_data) 318 { 319 u32 command; 320 321 /* write command */ 322 command = NGBE_MDIOSCA_REG(reg_addr) | 323 NGBE_MDIOSCA_DEV(device_type) | 324 NGBE_MDIOSCA_PORT(hw->phy.addr); 325 wr32(hw, NGBE_MDIOSCA, command); 326 327 command = NGBE_MDIOSCD_CMD_WRITE | 328 NGBE_MDIOSCD_DAT(phy_data) | 329 NGBE_MDIOSCD_BUSY | 330 NGBE_MDIOSCD_CLOCK(6); 331 wr32(hw, NGBE_MDIOSCD, command); 332 333 /* wait for completion */ 334 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, 335 0, NULL, 100, 100)) { 336 DEBUGOUT("PHY write cmd didn't complete"); 337 return NGBE_ERR_PHY; 338 } 339 340 return 0; 341 } 342 343 /** 344 * ngbe_write_phy_reg - Writes a value to specified PHY register 345 * using SWFW lock- this function is needed in most cases 346 * @hw: pointer to hardware structure 347 * @reg_addr: 32 bit PHY register to write 348 * @device_type: 5 bit device type 349 * @phy_data: Data to write to the PHY register 350 **/ 351 s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr, 352 u32 device_type, u16 phy_data) 353 { 354 s32 err; 355 u32 gssr = hw->phy.phy_semaphore_mask; 356 357 if (hw->mac.acquire_swfw_sync(hw, gssr)) 358 err = NGBE_ERR_SWFW_SYNC; 359 360 err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type, 361 phy_data); 362 363 hw->mac.release_swfw_sync(hw, gssr); 364 365 return err; 366 } 367 368 /** 369 * ngbe_init_phy - PHY specific init 370 * @hw: pointer to hardware structure 371 * 372 * Initialize any function pointers that were not able to be 373 * set during init_shared_code because the PHY type was 374 * not known. 375 * 376 **/ 377 s32 ngbe_init_phy(struct ngbe_hw *hw) 378 { 379 struct ngbe_phy_info *phy = &hw->phy; 380 s32 err = 0; 381 382 hw->phy.addr = 0; 383 384 switch (hw->sub_device_id) { 385 case NGBE_SUB_DEV_ID_EM_RTL_SGMII: 386 case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP: 387 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl; 388 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl; 389 break; 390 case NGBE_SUB_DEV_ID_EM_MVL_RGMII: 391 case NGBE_SUB_DEV_ID_EM_MVL_SFP: 392 case NGBE_SUB_DEV_ID_EM_MVL_MIX: 393 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl; 394 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl; 395 break; 396 case NGBE_SUB_DEV_ID_EM_YT8521S_SFP: 397 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt; 398 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt; 399 break; 400 default: 401 break; 402 } 403 404 hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY; 405 406 /* Identify the PHY */ 407 err = phy->identify(hw); 408 if (err == NGBE_ERR_PHY_ADDR_INVALID) 409 goto init_phy_ops_out; 410 411 /* Set necessary function pointers based on PHY type */ 412 switch (hw->phy.type) { 413 case ngbe_phy_rtl: 414 hw->phy.init_hw = ngbe_init_phy_rtl; 415 hw->phy.check_link = ngbe_check_phy_link_rtl; 416 hw->phy.setup_link = ngbe_setup_phy_link_rtl; 417 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_rtl; 418 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_rtl; 419 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_rtl; 420 break; 421 case ngbe_phy_mvl: 422 case ngbe_phy_mvl_sfi: 423 hw->phy.init_hw = ngbe_init_phy_mvl; 424 hw->phy.check_link = ngbe_check_phy_link_mvl; 425 hw->phy.setup_link = ngbe_setup_phy_link_mvl; 426 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_mvl; 427 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_mvl; 428 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_mvl; 429 break; 430 case ngbe_phy_yt8521s: 431 case ngbe_phy_yt8521s_sfi: 432 hw->phy.init_hw = ngbe_init_phy_yt; 433 hw->phy.check_link = ngbe_check_phy_link_yt; 434 hw->phy.setup_link = ngbe_setup_phy_link_yt; 435 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_yt; 436 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_yt; 437 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_yt; 438 default: 439 break; 440 } 441 442 init_phy_ops_out: 443 return err; 444 } 445 446