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 /* Don't reset PHY if it's shut down due to overtemp. */ 214 if (hw->mac.check_overtemp(hw) == NGBE_ERR_OVERTEMP) 215 return err; 216 217 /* Blocked by MNG FW so bail */ 218 if (ngbe_check_reset_blocked(hw)) 219 return err; 220 221 switch (hw->phy.type) { 222 case ngbe_phy_rtl: 223 err = ngbe_reset_phy_rtl(hw); 224 break; 225 case ngbe_phy_mvl: 226 case ngbe_phy_mvl_sfi: 227 err = ngbe_reset_phy_mvl(hw); 228 break; 229 case ngbe_phy_yt8521s: 230 case ngbe_phy_yt8521s_sfi: 231 err = ngbe_reset_phy_yt(hw); 232 break; 233 default: 234 break; 235 } 236 237 return err; 238 } 239 240 /** 241 * ngbe_read_phy_mdi - Reads a value from a specified PHY register without 242 * the SWFW lock 243 * @hw: pointer to hardware structure 244 * @reg_addr: 32 bit address of PHY register to read 245 * @device_type: 5 bit device type 246 * @phy_data: Pointer to read data from PHY register 247 **/ 248 s32 ngbe_read_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, u32 device_type, 249 u16 *phy_data) 250 { 251 u32 command, data; 252 253 /* Setup and write the address cycle command */ 254 command = NGBE_MDIOSCA_REG(reg_addr) | 255 NGBE_MDIOSCA_DEV(device_type) | 256 NGBE_MDIOSCA_PORT(hw->phy.addr); 257 wr32(hw, NGBE_MDIOSCA, command); 258 259 command = NGBE_MDIOSCD_CMD_READ | 260 NGBE_MDIOSCD_BUSY | 261 NGBE_MDIOSCD_CLOCK(6); 262 wr32(hw, NGBE_MDIOSCD, command); 263 264 /* 265 * Check every 10 usec to see if the address cycle completed. 266 * The MDI Command bit will clear when the operation is 267 * complete 268 */ 269 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, 270 0, NULL, 100, 100)) { 271 DEBUGOUT("PHY address command did not complete"); 272 return NGBE_ERR_PHY; 273 } 274 275 data = rd32(hw, NGBE_MDIOSCD); 276 *phy_data = (u16)NGBE_MDIOSCD_DAT_R(data); 277 278 return 0; 279 } 280 281 /** 282 * ngbe_read_phy_reg - Reads a value from a specified PHY register 283 * using the SWFW lock - this function is needed in most cases 284 * @hw: pointer to hardware structure 285 * @reg_addr: 32 bit address of PHY register to read 286 * @device_type: 5 bit device type 287 * @phy_data: Pointer to read data from PHY register 288 **/ 289 s32 ngbe_read_phy_reg(struct ngbe_hw *hw, u32 reg_addr, 290 u32 device_type, u16 *phy_data) 291 { 292 s32 err; 293 294 err = hw->phy.read_reg_unlocked(hw, reg_addr, device_type, 295 phy_data); 296 297 return err; 298 } 299 300 /** 301 * ngbe_write_phy_reg_mdi - Writes a value to specified PHY register 302 * without SWFW lock 303 * @hw: pointer to hardware structure 304 * @reg_addr: 32 bit PHY register to write 305 * @device_type: 5 bit device type 306 * @phy_data: Data to write to the PHY register 307 **/ 308 s32 ngbe_write_phy_reg_mdi(struct ngbe_hw *hw, u32 reg_addr, 309 u32 device_type, u16 phy_data) 310 { 311 u32 command; 312 313 /* write command */ 314 command = NGBE_MDIOSCA_REG(reg_addr) | 315 NGBE_MDIOSCA_DEV(device_type) | 316 NGBE_MDIOSCA_PORT(hw->phy.addr); 317 wr32(hw, NGBE_MDIOSCA, command); 318 319 command = NGBE_MDIOSCD_CMD_WRITE | 320 NGBE_MDIOSCD_DAT(phy_data) | 321 NGBE_MDIOSCD_BUSY | 322 NGBE_MDIOSCD_CLOCK(6); 323 wr32(hw, NGBE_MDIOSCD, command); 324 325 /* wait for completion */ 326 if (!po32m(hw, NGBE_MDIOSCD, NGBE_MDIOSCD_BUSY, 327 0, NULL, 100, 100)) { 328 DEBUGOUT("PHY write cmd didn't complete"); 329 return NGBE_ERR_PHY; 330 } 331 332 return 0; 333 } 334 335 /** 336 * ngbe_write_phy_reg - Writes a value to specified PHY register 337 * using SWFW lock- this function is needed in most cases 338 * @hw: pointer to hardware structure 339 * @reg_addr: 32 bit PHY register to write 340 * @device_type: 5 bit device type 341 * @phy_data: Data to write to the PHY register 342 **/ 343 s32 ngbe_write_phy_reg(struct ngbe_hw *hw, u32 reg_addr, 344 u32 device_type, u16 phy_data) 345 { 346 s32 err; 347 348 err = hw->phy.write_reg_unlocked(hw, reg_addr, device_type, 349 phy_data); 350 351 return err; 352 } 353 354 /** 355 * ngbe_init_phy - PHY specific init 356 * @hw: pointer to hardware structure 357 * 358 * Initialize any function pointers that were not able to be 359 * set during init_shared_code because the PHY type was 360 * not known. 361 * 362 **/ 363 s32 ngbe_init_phy(struct ngbe_hw *hw) 364 { 365 struct ngbe_phy_info *phy = &hw->phy; 366 s32 err = 0; 367 368 hw->phy.addr = 0; 369 370 switch (hw->sub_device_id) { 371 case NGBE_SUB_DEV_ID_EM_RTL_SGMII: 372 case NGBE_SUB_DEV_ID_EM_RTL_YT8521S_SFP: 373 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_rtl; 374 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_rtl; 375 break; 376 case NGBE_SUB_DEV_ID_EM_MVL_RGMII: 377 case NGBE_SUB_DEV_ID_EM_MVL_SFP: 378 case NGBE_SUB_DEV_ID_EM_MVL_MIX: 379 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_mvl; 380 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_mvl; 381 break; 382 case NGBE_SUB_DEV_ID_EM_YT8521S_SFP: 383 hw->phy.read_reg_unlocked = ngbe_read_phy_reg_yt; 384 hw->phy.write_reg_unlocked = ngbe_write_phy_reg_yt; 385 break; 386 default: 387 break; 388 } 389 390 hw->phy.phy_semaphore_mask = NGBE_MNGSEM_SWPHY; 391 392 /* Identify the PHY */ 393 err = phy->identify(hw); 394 if (err == NGBE_ERR_PHY_ADDR_INVALID) 395 goto init_phy_ops_out; 396 397 /* Set necessary function pointers based on PHY type */ 398 switch (hw->phy.type) { 399 case ngbe_phy_rtl: 400 hw->phy.init_hw = ngbe_init_phy_rtl; 401 hw->phy.check_link = ngbe_check_phy_link_rtl; 402 hw->phy.setup_link = ngbe_setup_phy_link_rtl; 403 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_rtl; 404 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_rtl; 405 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_rtl; 406 break; 407 case ngbe_phy_mvl: 408 case ngbe_phy_mvl_sfi: 409 hw->phy.init_hw = ngbe_init_phy_mvl; 410 hw->phy.check_link = ngbe_check_phy_link_mvl; 411 hw->phy.setup_link = ngbe_setup_phy_link_mvl; 412 hw->phy.set_phy_power = ngbe_set_phy_power_mvl; 413 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_mvl; 414 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_mvl; 415 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_mvl; 416 break; 417 case ngbe_phy_yt8521s: 418 case ngbe_phy_yt8521s_sfi: 419 hw->phy.init_hw = ngbe_init_phy_yt; 420 hw->phy.check_link = ngbe_check_phy_link_yt; 421 hw->phy.setup_link = ngbe_setup_phy_link_yt; 422 hw->phy.set_phy_power = ngbe_set_phy_power_yt; 423 hw->phy.get_adv_pause = ngbe_get_phy_advertised_pause_yt; 424 hw->phy.get_lp_adv_pause = ngbe_get_phy_lp_advertised_pause_yt; 425 hw->phy.set_pause_adv = ngbe_set_phy_pause_adv_yt; 426 default: 427 break; 428 } 429 430 init_phy_ops_out: 431 return err; 432 } 433 434