1 /* 2 * Copyright 2014-2017 Cavium, Inc. 3 * The contents of this file are subject to the terms of the Common Development 4 * and Distribution License, v.1, (the "License"). 5 * 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the License at available 9 * at http://opensource.org/licenses/CDDL-1.0 10 * 11 * See the License for the specific language governing permissions and 12 * limitations under the License. 13 */ 14 15 #include "54xx_reg.h" 16 #include "serdes.h" 17 #include "lm5706.h" 18 #include "netlink.h" 19 20 21 22 /******************************************************************************* 23 * Macros. 24 ******************************************************************************/ 25 26 #define MII_REG(_type, _field) (OFFSETOF(_type, _field)/2) 27 28 29 30 /******************************************************************************* 31 * Description: 32 * 33 * Return: 34 ******************************************************************************/ 35 lm_status_t 36 lm_mwrite( 37 lm_device_t *pdev, 38 u32_t phy_addr, 39 u32_t reg, 40 u32_t val) 41 { 42 lm_status_t lm_status; 43 u32_t tmp; 44 u32_t cnt; 45 46 DbgBreakIf(pdev->params.enable_remote_phy); 47 48 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 49 { 50 REG_RD(pdev, emac.emac_mdio_mode, &tmp); 51 tmp &= ~EMAC_MDIO_MODE_AUTO_POLL; 52 53 REG_WR(pdev, emac.emac_mdio_mode, tmp); 54 55 mm_wait(pdev, 40); 56 } 57 58 tmp = (phy_addr << 21) | 59 (reg << 16) | 60 val | 61 EMAC_MDIO_COMM_COMMAND_WRITE_TE | 62 EMAC_MDIO_COMM_START_BUSY | 63 EMAC_MDIO_COMM_DISEXT; 64 65 REG_WR(pdev, emac.emac_mdio_comm, tmp); 66 67 for(cnt = 0; cnt < 1000; cnt++) 68 { 69 mm_wait(pdev, 10); 70 71 REG_RD(pdev, emac.emac_mdio_comm, &tmp); 72 if(!(tmp & EMAC_MDIO_COMM_START_BUSY)) 73 { 74 mm_wait(pdev, 5); 75 break; 76 } 77 } 78 79 if(tmp & EMAC_MDIO_COMM_START_BUSY) 80 { 81 DbgBreakMsg("Write phy register failed\n"); 82 83 lm_status = LM_STATUS_FAILURE; 84 } 85 else 86 { 87 lm_status = LM_STATUS_SUCCESS; 88 } 89 90 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 91 { 92 REG_RD(pdev, emac.emac_mdio_mode, &tmp); 93 tmp |= EMAC_MDIO_MODE_AUTO_POLL; 94 95 REG_WR(pdev, emac.emac_mdio_mode, tmp); 96 } 97 98 return lm_status; 99 } /* lm_mwrite */ 100 101 102 103 /******************************************************************************* 104 * Description: 105 * 106 * Return: 107 ******************************************************************************/ 108 lm_status_t 109 lm_mread( 110 lm_device_t *pdev, 111 u32_t phy_addr, 112 u32_t reg, 113 u32_t *ret_val) 114 { 115 lm_status_t lm_status; 116 u32_t val; 117 u32_t cnt; 118 119 DbgBreakIf(pdev->params.enable_remote_phy); 120 121 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 122 { 123 REG_RD(pdev, emac.emac_mdio_mode, &val); 124 val &= ~EMAC_MDIO_MODE_AUTO_POLL; 125 126 REG_WR(pdev, emac.emac_mdio_mode, val); 127 128 mm_wait(pdev, 40); 129 } 130 131 val = (phy_addr << 21) | 132 (reg << 16) | 133 EMAC_MDIO_COMM_COMMAND_READ_TE | 134 EMAC_MDIO_COMM_DISEXT | 135 EMAC_MDIO_COMM_START_BUSY; 136 137 REG_WR(pdev, emac.emac_mdio_comm, val); 138 139 for(cnt = 0; cnt < 1000; cnt++) 140 { 141 mm_wait(pdev, 10); 142 143 REG_RD(pdev, emac.emac_mdio_comm, &val); 144 if(!(val & EMAC_MDIO_COMM_START_BUSY)) 145 { 146 /* There is a bug here. The MI_COM_BUSY bit may be cleared 147 * before the data is loaded into the register. */ 148 REG_RD(pdev, emac.emac_mdio_comm, &val); 149 150 REG_RD(pdev, emac.emac_mdio_comm, &val); 151 val &= EMAC_MDIO_COMM_DATA; 152 153 break; 154 } 155 } 156 157 if(val & EMAC_MDIO_COMM_START_BUSY) 158 { 159 DbgBreakMsg("Read phy register failed\n"); 160 161 val = 0; 162 163 lm_status = LM_STATUS_FAILURE; 164 } 165 else 166 { 167 lm_status = LM_STATUS_SUCCESS; 168 } 169 170 *ret_val = val; 171 172 if(pdev->params.phy_int_mode == PHY_INT_MODE_AUTO_POLLING) 173 { 174 REG_RD(pdev, emac.emac_mdio_mode, &val); 175 val |= EMAC_MDIO_MODE_AUTO_POLL; 176 177 REG_WR(pdev, emac.emac_mdio_mode, val); 178 } 179 180 return lm_status; 181 } /* lm_mread */ 182 183 184 185 /******************************************************************************* 186 * Description: 187 * 188 * Return: 189 ******************************************************************************/ 190 STATIC u32_t 191 phy_ad_settings( 192 lm_device_t *pdev, 193 lm_medium_t req_medium, 194 lm_flow_control_t flow_ctrl) 195 { 196 u32_t val; 197 198 val = 0; 199 200 /* Please refer to Table 28B-3 of the 802.3ab-1999 spec. */ 201 if((flow_ctrl == LM_FLOW_CONTROL_AUTO_PAUSE) || 202 ((flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) && 203 (flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE))) 204 { 205 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER) 206 { 207 if(CHIP_NUM(pdev) == CHIP_NUM_5706) 208 { 209 val |= PHY_AN_AD_1000X_PAUSE_CAPABLE | 210 PHY_AN_AD_1000X_ASYM_PAUSE; 211 } 212 else 213 { 214 val |= MII_ADVERT_PAUSE; 215 } 216 } 217 else 218 { 219 val |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE; 220 } 221 } 222 else if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 223 { 224 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER) 225 { 226 if(CHIP_NUM(pdev) == CHIP_NUM_5706) 227 { 228 val |= PHY_AN_AD_1000X_ASYM_PAUSE; 229 } 230 else 231 { 232 val |= MII_ADVERT_ASYM_PAUSE; 233 } 234 } 235 else 236 { 237 val |= PHY_AN_AD_ASYM_PAUSE; 238 } 239 } 240 else if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) 241 { 242 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_FIBER) 243 { 244 if(CHIP_NUM(pdev) == CHIP_NUM_5706) 245 { 246 val |= PHY_AN_AD_1000X_PAUSE_CAPABLE | 247 PHY_AN_AD_1000X_ASYM_PAUSE; 248 } 249 else 250 { 251 val |= MII_ADVERT_PAUSE; 252 } 253 } 254 else 255 { 256 val |= PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE; 257 } 258 } 259 260 return val; 261 } /* phy_ad_settings */ 262 263 264 265 /******************************************************************************* 266 * Description: 267 * 268 * Return: 269 ******************************************************************************/ 270 STATIC lm_status_t 271 init_utp( 272 lm_device_t *pdev, 273 lm_medium_t req_medium, 274 lm_flow_control_t flow_ctrl, 275 u32_t selective_autoneg, 276 u32_t wire_speed, 277 u32_t wait_link_timeout_us) 278 { 279 u32_t restart_autoneg; 280 lm_status_t lm_status; 281 lm_medium_t duplex; 282 lm_medium_t speed; 283 u32_t val; 284 u32_t cnt; 285 286 if(GET_MEDIUM_TYPE(req_medium) != LM_MEDIUM_TYPE_UTP) 287 { 288 return LM_STATUS_INVALID_PARAMETER; 289 } 290 291 speed = GET_MEDIUM_SPEED(req_medium); 292 duplex = GET_MEDIUM_DUPLEX(req_medium); 293 294 lm_status = LM_STATUS_SUCCESS; 295 296 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, PHY_CTRL_PHY_RESET); 297 for(cnt = 0; cnt < 1000; cnt++) 298 { 299 mm_wait(pdev, 5); 300 301 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val); 302 303 if(!(val & PHY_CTRL_PHY_RESET)) 304 { 305 mm_wait(pdev, 5); 306 307 break; 308 } 309 } 310 311 DbgBreakIf(val & PHY_CTRL_PHY_RESET); 312 313 /* Get the PHY id. */ 314 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val); 315 pdev->hw_info.phy_id = val << 16; 316 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val); 317 318 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val); 319 pdev->hw_info.phy_id |= val & 0xffff; 320 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val); 321 322 DbgBreakIf( 323 (pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff || 324 pdev->hw_info.phy_id == 0); 325 326 if(CHIP_REV(pdev) == CHIP_REV_FPGA) 327 { 328 /* Configure how the MAC obtain link from the external PHY. 329 * On the FPGA board, LED2 is used as a link signal into the 330 * MAC. Configure LED2 to a link event on the AC101L PHY. */ 331 (void) lm_mwrite(pdev, pdev->params.phy_addr, 28, 0x3044); 332 (void) lm_mwrite(pdev, pdev->params.phy_addr, 29, 0x0100); 333 } 334 else 335 { 336 if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708) 337 { 338 /* Gen6 PHY core has a slight increase in CRC error. 339 * This will workaround the problem which will be 340 * fixed in Gen7 PHY core. */ 341 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0c00); 342 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x000a); 343 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x310b); 344 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x201f); 345 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x9506); 346 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x401f); 347 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, 0x14e2); 348 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400); 349 } 350 351 /* Enable/Disable Ethernet@WireSpeed. */ 352 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x7007); 353 (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val); 354 355 val &= 0x0ff8; 356 357 if(wire_speed) 358 { 359 val |= 0x10; 360 } 361 else 362 { 363 val &= ~0x10; 364 } 365 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, val | 0x8000 | 0x7); 366 367 /* 368 * Cont00039501 Issue Description: Auto MDIX mode doesn't work in forced speed 369 * while two 5716 connected back-to-back 370 */ 371 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x7007); 372 (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val); 373 val |= BIT_9; /*auto mdix*/ 374 (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, val | 0x8000 | 0x7); 375 376 } 377 378 /* Expansion register 0x8 is the 10BT control register. BIT 8 of this 379 * register controls the Early DAC Wakeup Enable. this bit allows the 380 * transmitter to be shutdown in 10BT mode except for sending out link 381 * pulses. This allows for a low power operation in 10BT mode which is 382 * useful in WOL application. The default value of this register bit 383 * gets loaded from a strap value on the GPHY provided by the chip that 384 * instantiates the PHY. in Xinan this strap value is 1, meaning that 385 * the early DAC Wakeup Enable bit is set by default. FW/Driver needs to 386 * clear this bit when bringing the PHY out of reset. */ 387 if(CHIP_ID(pdev) == CHIP_ID_5709_A0 || 388 CHIP_ID(pdev) == CHIP_ID_5709_A1 || 389 CHIP_ID(pdev) == CHIP_ID_5709_B0 || 390 CHIP_ID(pdev) == CHIP_ID_5709_B1) 391 { 392 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0xf08); 393 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &val); 394 val &= ~0x100; 395 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x15, val); 396 } 397 398 /* Configure the PHY for jumbo frame. */ 399 if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE) 400 { 401 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x0001); 402 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x4400); 403 } 404 else 405 { 406 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x0000); 407 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400); 408 } 409 410 /* Configure line speed. */ 411 restart_autoneg = FALSE; 412 413 switch(speed) 414 { 415 case LM_MEDIUM_SPEED_10MBPS: 416 /* Don't advertise 1000mb. This register is undefined on a 417 * 10/100 Mb PHY. */ 418 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, 0); 419 420 /* Setup AN_AD to advertise 10mb. */ 421 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; 422 val |= phy_ad_settings(pdev, req_medium, flow_ctrl); 423 424 if(duplex == LM_MEDIUM_FULL_DUPLEX) 425 { 426 val |= PHY_AN_AD_10BASET_FULL; 427 428 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 429 { 430 val |= PHY_AN_AD_10BASET_HALF; 431 } 432 } 433 else 434 { 435 val |= PHY_AN_AD_10BASET_HALF; 436 } 437 438 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val); 439 440 /* Forcing or advertising 10mb. */ 441 if(selective_autoneg) 442 { 443 restart_autoneg = TRUE; 444 445 DbgMessage(pdev, INFORM, "autoneg 10mb hd\n"); 446 if(duplex == LM_MEDIUM_FULL_DUPLEX) 447 { 448 DbgMessage(pdev, INFORM, "and 10mb fd\n"); 449 } 450 } 451 else 452 { 453 if(duplex == LM_MEDIUM_HALF_DUPLEX) 454 { 455 DbgMessage(pdev, INFORM, "force 10mb hd\n"); 456 (void) lm_mwrite( 457 pdev, 458 pdev->params.phy_addr, 459 PHY_CTRL_REG, 460 PHY_CTRL_SPEED_SELECT_10MBPS); 461 } 462 else 463 { 464 DbgMessage(pdev, INFORM, "force 10mb fd\n"); 465 (void) lm_mwrite( 466 pdev, 467 pdev->params.phy_addr, 468 PHY_CTRL_REG, 469 PHY_CTRL_SPEED_SELECT_10MBPS | 470 PHY_CTRL_FULL_DUPLEX_MODE); 471 } 472 } 473 474 break; 475 476 case LM_MEDIUM_SPEED_100MBPS: 477 /* Don't advertise 1000mb. This register is undefined on a 478 * 10/100 PHY. */ 479 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, 0); 480 481 /* Setup AN_AD to advertise 10/100mb. */ 482 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; 483 val |= phy_ad_settings(pdev, req_medium, flow_ctrl); 484 485 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 486 { 487 val |= PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL; 488 } 489 490 if(duplex == LM_MEDIUM_FULL_DUPLEX) 491 { 492 val |= PHY_AN_AD_100BASETX_FULL; 493 494 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 495 { 496 val |= PHY_AN_AD_100BASETX_HALF; 497 } 498 } 499 else 500 { 501 val |= PHY_AN_AD_100BASETX_HALF; 502 } 503 504 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val); 505 506 /* Forcing or advertising 100mb. */ 507 if(selective_autoneg) 508 { 509 restart_autoneg = TRUE; 510 511 DbgMessage(pdev, INFORM, "autoneg 10mb and 100mb hd\n"); 512 if(duplex == LM_MEDIUM_FULL_DUPLEX) 513 { 514 DbgMessage(pdev, INFORM, "and 100mb fd\n"); 515 } 516 } 517 else 518 { 519 if(duplex == LM_MEDIUM_HALF_DUPLEX) 520 { 521 DbgMessage(pdev, INFORM, "force 100mb hd\n"); 522 (void) lm_mwrite( 523 pdev, 524 pdev->params.phy_addr, 525 PHY_CTRL_REG, 526 PHY_CTRL_SPEED_SELECT_100MBPS); 527 } 528 else 529 { 530 DbgMessage(pdev, INFORM, "force 100mb fd\n"); 531 (void) lm_mwrite( 532 pdev, 533 pdev->params.phy_addr, 534 PHY_CTRL_REG, 535 PHY_CTRL_SPEED_SELECT_100MBPS | 536 PHY_CTRL_FULL_DUPLEX_MODE); 537 } 538 } 539 540 break; 541 542 case LM_MEDIUM_SPEED_1000MBPS: 543 /* Don't advertise 10/100mb. */ 544 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD; 545 val |= phy_ad_settings(pdev, req_medium, flow_ctrl); 546 547 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 548 { 549 val |= PHY_AN_AD_10BASET_HALF | PHY_AN_AD_10BASET_FULL; 550 val |= PHY_AN_AD_100BASETX_HALF | PHY_AN_AD_100BASETX_FULL; 551 } 552 553 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val); 554 555 /* Setup AN_AD to advertise 1000mb. This register is defined on 556 * a 10/100 Mb PHY. */ 557 if(duplex == LM_MEDIUM_FULL_DUPLEX) 558 { 559 val |= PHY_AN_AD_1000BASET_FULL; 560 561 if(selective_autoneg == SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 562 { 563 val |= PHY_AN_AD_1000BASET_HALF; 564 } 565 } 566 else 567 { 568 val |= PHY_AN_AD_1000BASET_HALF; 569 } 570 571 /* Forcing or advertising 1000mb. */ 572 if(selective_autoneg) 573 { 574 DbgMessage(pdev, INFORM, "autoneg 10/100mb and 1000mb hd\n"); 575 if(duplex == LM_MEDIUM_FULL_DUPLEX) 576 { 577 DbgMessage(pdev, INFORM, "and 1000mb fd\n"); 578 } 579 580 restart_autoneg = TRUE; 581 } 582 else 583 { 584 /* external loopback at 1gb link. */ 585 (void) lm_mwrite( 586 pdev, 587 pdev->params.phy_addr, 588 PHY_CTRL_REG, 589 PHY_CTRL_SPEED_SELECT_1000MBPS); 590 591 (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, 0x7); 592 (void) lm_mread(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, &val); 593 val |= BCM5401_SHDW_NORMAL_EXTERNAL_LOOPBACK; 594 (void) lm_mwrite(pdev, pdev->params.phy_addr, BCM5401_AUX_CTRL, val); 595 596 val = PHY_CONFIG_AS_MASTER | PHY_ENABLE_CONFIG_AS_MASTER; 597 } 598 599 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_1000BASET_CTRL_REG, val); 600 break; 601 602 default: 603 val = PHY_AN_AD_PROTOCOL_802_3_CSMA_CD | 604 PHY_AN_AD_10BASET_HALF | 605 PHY_AN_AD_10BASET_FULL | 606 PHY_AN_AD_100BASETX_FULL | 607 PHY_AN_AD_100BASETX_HALF; 608 val |= phy_ad_settings(pdev, req_medium, flow_ctrl); 609 610 /* Set up the 10/100 advertisement register. */ 611 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val); 612 613 /* Advertise 1000Mbps. This register is undefined on a 614 * 10/100 Mb PHY. */ 615 (void) lm_mwrite( 616 pdev, 617 pdev->params.phy_addr, 618 PHY_1000BASET_CTRL_REG, 619 PHY_AN_AD_1000BASET_HALF | 620 PHY_AN_AD_1000BASET_FULL); 621 622 restart_autoneg = TRUE; 623 speed = LM_MEDIUM_SPEED_AUTONEG; 624 break; 625 } 626 627 /* exit mac loopback. we could be in mac loopback mode if previously 628 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK 629 * medium type for diagnostic. */ 630 REG_RD(pdev, emac.emac_mode, &val); 631 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK); 632 REG_WR(pdev, emac.emac_mode, val); 633 634 /* Restart auto-negotation. */ 635 if(restart_autoneg) 636 { 637 DbgMessage(pdev, INFORM, "phy init - restart autoneg\n"); 638 639 (void) lm_mwrite( 640 pdev, 641 pdev->params.phy_addr, 642 PHY_CTRL_REG, 643 PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG); 644 } 645 646 /* Save current medium settings. */ 647 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_UTP); 648 SET_MEDIUM_SPEED(pdev->vars.medium, speed); 649 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex); 650 651 pdev->vars.cable_is_attached = FALSE; 652 653 /* Wait for link. */ 654 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val); 655 656 if(CHIP_REV(pdev) != CHIP_REV_FPGA) 657 { 658 /* Wait for link only if the cable is connected. */ 659 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00); 660 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val); 661 if(val & 0x20) 662 { 663 for(; ;) 664 { 665 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val); 666 if(val & PHY_STATUS_LINK_PASS) 667 { 668 break; 669 } 670 671 mm_wait(pdev, 10); 672 673 if(wait_link_timeout_us <= 10) 674 { 675 break; 676 } 677 678 wait_link_timeout_us -= 10; 679 } 680 681 pdev->vars.cable_is_attached = TRUE; 682 } 683 } 684 685 /* Need to read a second time to get the current link status. */ 686 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val); 687 if(val & PHY_STATUS_LINK_PASS) 688 { 689 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 690 DbgMessage(pdev, INFORM, "phy init link up\n"); 691 692 pdev->vars.cable_is_attached = TRUE; 693 } 694 else 695 { 696 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 697 DbgMessage(pdev, INFORM, "phy init link down\n"); 698 } 699 700 return lm_status; 701 } /* init_utp */ 702 703 704 705 /******************************************************************************* 706 * Description: 707 * 708 * Return: 709 ******************************************************************************/ 710 STATIC u32_t 711 mii_get_serdes_link_status( 712 lm_device_t *pdev) 713 { 714 u32_t val; 715 716 /* The link status in the MII status register is not reliable for 717 * the SERDES part. We need to get the link info from the MAC. */ 718 if(CHIP_NUM(pdev) == CHIP_NUM_5706 && 719 lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER) 720 { 721 REG_RD(pdev, emac.emac_status, &val); 722 if(val & EMAC_STATUS_LINK) 723 { 724 val = PHY_STATUS_LINK_PASS; 725 } 726 else 727 { 728 val = 0; 729 } 730 } 731 else 732 { 733 /* The second read returns the current status. */ 734 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val); 735 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &val); 736 } 737 738 return val; 739 } /* mii_get_serdes_link_status */ 740 741 742 743 /******************************************************************************* 744 * Description: 745 * 746 * Return: 747 ******************************************************************************/ 748 STATIC u8_t 749 set_5708_serdes_pre_emphasis( 750 lm_device_t *pdev, 751 u32_t pre_emphasis) 752 { 753 u8_t restart_autoneg; 754 u32_t val; 755 756 restart_autoneg = FALSE; 757 758 if(pre_emphasis == 0) 759 { 760 (void) lm_mread( 761 pdev, 762 pdev->params.phy_addr, 763 MII_REG(serdes_reg_t, mii_aneg_nxt_pg_rcv2), 764 &pre_emphasis); 765 pre_emphasis &= 0xf; 766 767 if(pre_emphasis != pdev->vars.serdes_pre_emphasis) 768 { 769 pdev->vars.serdes_pre_emphasis = pre_emphasis; 770 771 restart_autoneg = TRUE; 772 773 /* Switch to Bank 5. */ 774 (void) lm_mwrite( 775 pdev, 776 pdev->params.phy_addr, 777 MII_REG(serdes_reg_t, mii_block_addr), 778 MII_BLK_ADDR_TXMISC); 779 780 /* Write the new pre-emphasis. */ 781 (void) lm_mread( 782 pdev, 783 pdev->params.phy_addr, 784 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3), 785 &val); 786 787 pre_emphasis = 788 ((pre_emphasis & 0x1) << 15) | 789 ((pre_emphasis & 0x2) << 13) | 790 ((pre_emphasis & 0x4) << 11) | 791 ((pre_emphasis & 0x8) << 9); 792 val = (val & 0x0fff) | pre_emphasis; 793 794 (void) lm_mwrite( 795 pdev, 796 pdev->params.phy_addr, 797 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3), 798 val); 799 800 /* Select Bank 0. */ 801 (void) lm_mwrite( 802 pdev, 803 pdev->params.phy_addr, 804 MII_REG(serdes_reg_t, mii_block_addr), 805 MII_BLK_ADDR_DIGITAL); 806 807 /* Restart autoneg. */ 808 (void) lm_mwrite( 809 pdev, 810 pdev->params.phy_addr, 811 MII_REG(serdes_reg_t, mii_ctrl), 812 MII_CTRL_RESTART_ANEG | MII_CTRL_ANEG_ENA); 813 } 814 } 815 else 816 { 817 (void) lm_mwrite( 818 pdev, 819 pdev->params.phy_addr, 820 MII_REG(serdes_reg_t, mii_block_addr), 821 MII_BLK_ADDR_TXMISC); 822 823 (void) lm_mwrite( 824 pdev, 825 pdev->params.phy_addr, 826 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl3), 827 pre_emphasis); 828 829 (void) lm_mwrite( 830 pdev, 831 pdev->params.phy_addr, 832 MII_REG(serdes_reg_t, mii_block_addr), 833 MII_BLK_ADDR_DIGITAL); 834 } 835 836 return restart_autoneg; 837 } /* set_5708_serdes_pre_emphasis */ 838 839 840 841 /******************************************************************************* 842 * Description: 843 * 844 * Return: 845 ******************************************************************************/ 846 STATIC lm_status_t 847 init_5708_serdes( 848 lm_device_t *pdev, 849 lm_medium_t req_medium, 850 lm_flow_control_t flow_ctrl, 851 u32_t selective_autoneg, 852 u32_t wait_link_timeout_us) 853 { 854 lm_medium_t duplex; 855 lm_medium_t speed; 856 u32_t cnt; 857 u32_t val; 858 859 if(GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_UNKNOWN) 860 { 861 selective_autoneg = FALSE; 862 } 863 864 speed = GET_MEDIUM_SPEED(req_medium); 865 duplex = GET_MEDIUM_DUPLEX(req_medium); 866 867 if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT) 868 { 869 REG_RD_IND( 870 pdev, 871 pdev->hw_info.shmem_base + 872 OFFSETOF(shmem_region_t, dev_info.port_hw_config.config), 873 &val); 874 875 switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK) 876 { 877 case PORT_HW_CFG_DEFAULT_LINK_1G: 878 speed = LM_MEDIUM_SPEED_1000MBPS; 879 break; 880 881 case PORT_HW_CFG_DEFAULT_LINK_2_5G: 882 speed = LM_MEDIUM_SPEED_2500MBPS; 883 break; 884 885 default: 886 speed = LM_MEDIUM_SPEED_UNKNOWN; 887 break; 888 } 889 } 890 891 /* Reset the SERDES. */ 892 (void) lm_mwrite( 893 pdev, 894 pdev->params.phy_addr, 895 MII_REG(serdes_reg_t, mii_ctrl), 896 MII_CTRL_RESET); 897 898 for(cnt = 0; cnt < 1000; cnt++) 899 { 900 mm_wait(pdev, 5); 901 902 (void) lm_mread( 903 pdev, 904 pdev->params.phy_addr, 905 MII_REG(serdes_reg_t, mii_ctrl), 906 &val); 907 908 if(!(val & MII_CTRL_RESET)) 909 { 910 mm_wait(pdev, 5); 911 912 break; 913 } 914 } 915 916 DbgBreakIf(val & MII_CTRL_RESET); 917 918 /* Workaround for 5708A0 and B0. 919 * 920 * Errata 1.75: Tx peak-to-peak amplitude was measured as low 921 * as 765mV under full PVT testing, whereas 800mV is considered 922 * a passing result. */ 923 if(CHIP_NUM(pdev) == CHIP_NUM_5708) 924 { 925 /* Switch to Bank 5. */ 926 (void) lm_mwrite( 927 pdev, 928 pdev->params.phy_addr, 929 MII_REG(serdes_reg_t, mii_block_addr), 930 MII_BLK_ADDR_TXMISC); 931 932 (void) lm_mread( 933 pdev, 934 pdev->params.phy_addr, 935 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl1), 936 &val); 937 938 val &= ~ MII_TXACTL1_DRIVER_VCM; 939 940 (void) lm_mwrite( 941 pdev, 942 pdev->params.phy_addr, 943 0x10+MII_REG(serdes_tx_misc_reg_t, mii_txactl1), 944 val); 945 } 946 947 /* Set up pre-emphasis for a backplane application. */ 948 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP) 949 { 950 (void) set_5708_serdes_pre_emphasis(pdev, pdev->params.serdes_pre_emphasis); 951 } 952 953 /* Reset the pre_emphasis. */ 954 pdev->vars.serdes_pre_emphasis = 0; 955 956 /* Get the PHY id. */ 957 (void) lm_mread( 958 pdev, 959 pdev->params.phy_addr, 960 MII_REG(serdes_reg_t, mii_phy_id_msb), 961 &val); 962 pdev->hw_info.phy_id = val << 16; 963 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val); 964 965 (void) lm_mread( 966 pdev, 967 pdev->params.phy_addr, 968 MII_REG(serdes_reg_t, mii_phy_id_lsb), 969 &val); 970 pdev->hw_info.phy_id |= val & 0xffff; 971 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val); 972 973 DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff || 974 pdev->hw_info.phy_id == 0); 975 976 /* Enable 2.5G register set to be accessible in the IEEE registers. */ 977 (void) lm_mwrite( 978 pdev, 979 pdev->params.phy_addr, 980 MII_REG(serdes_reg_t, mii_block_addr), 981 MII_BLK_ADDR_DIGITAL3); 982 (void) lm_mwrite( 983 pdev, 984 pdev->params.phy_addr, 985 0x10+MII_REG(serdes_digital3_reg_t, mii_digctl_3_0), 986 MII_DIG3_USE_IEEE); 987 988 /* Switch back to the IEEE Bank. */ 989 (void) lm_mwrite( 990 pdev, 991 pdev->params.phy_addr, 992 MII_REG(serdes_reg_t, mii_block_addr), 993 MII_BLK_ADDR_DIGITAL); 994 995 /* Enable SGMII/Fiber mode autodetection. */ 996 (void) lm_mread( 997 pdev, 998 pdev->params.phy_addr, 999 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1), 1000 &val); 1001 1002 val |= MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN; 1003 1004 /* Sigdet is enabled by default. For backplane application, we need 1005 * to disable Sigdet by clearing 0*0x10.2 of the Digital Bank. */ 1006 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP) 1007 { 1008 val &= ~MII_1000X_CTL1_SIG_DET_EN; 1009 } 1010 else 1011 { 1012 val |= MII_1000X_CTL1_SIG_DET_EN; 1013 } 1014 1015 (void) lm_mwrite( 1016 pdev, 1017 pdev->params.phy_addr, 1018 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1), 1019 val); 1020 1021 /* We should always enable parallel detection. */ 1022 (void) lm_mread( 1023 pdev, 1024 pdev->params.phy_addr, 1025 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl2), 1026 &val); 1027 1028 val |= MII_1000X_CTL2_PAR_DET_EN; 1029 1030 (void) lm_mwrite( 1031 pdev, 1032 pdev->params.phy_addr, 1033 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl2), 1034 val); 1035 1036 /* Enable/disable 2.5G capability. */ 1037 (void) lm_mread( 1038 pdev, 1039 pdev->params.phy_addr, 1040 MII_REG(serdes_reg_t, mii_aneg_nxt_pg_xmit1), 1041 &val); 1042 1043 val &= ~MII_ANEG_NXT_PG_XMIT1_2G5; 1044 1045 if(selective_autoneg) 1046 { 1047 if(speed == LM_MEDIUM_SPEED_2500MBPS) 1048 { 1049 val |= MII_ANEG_NXT_PG_XMIT1_2G5; 1050 } 1051 } 1052 else if(speed == LM_MEDIUM_SPEED_AUTONEG) 1053 { 1054 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_PHY_FIBER_2_5G) 1055 { 1056 val |= MII_ANEG_NXT_PG_XMIT1_2G5; 1057 } 1058 } 1059 else if(speed == LM_MEDIUM_SPEED_2500MBPS) 1060 { 1061 val |= MII_ANEG_NXT_PG_XMIT1_2G5; 1062 } 1063 1064 (void) lm_mwrite( 1065 pdev, 1066 pdev->params.phy_addr, 1067 MII_REG(serdes_reg_t, mii_aneg_nxt_pg_xmit1), 1068 val); 1069 1070 val = 0; 1071 1072 if(selective_autoneg || speed == LM_MEDIUM_SPEED_UNKNOWN) 1073 { 1074 val |= phy_ad_settings(pdev, req_medium, flow_ctrl); 1075 1076 if((selective_autoneg && speed == LM_MEDIUM_SPEED_1000MBPS) || 1077 speed == LM_MEDIUM_SPEED_UNKNOWN) 1078 { 1079 val |= MII_ABILITY_HALF | MII_ABILITY_FULL; 1080 } 1081 1082 (void) lm_mwrite( 1083 pdev, 1084 pdev->params.phy_addr, 1085 MII_REG(serdes_reg_t, mii_aneg_advert), 1086 val); 1087 1088 (void) lm_mwrite( 1089 pdev, 1090 pdev->params.phy_addr, 1091 MII_REG(serdes_reg_t, mii_ctrl), 1092 MII_CTRL_RESTART_ANEG | MII_CTRL_ANEG_ENA); 1093 1094 speed = LM_MEDIUM_SPEED_AUTONEG; 1095 } 1096 else 1097 { 1098 switch(speed) 1099 { 1100 case LM_MEDIUM_SPEED_10MBPS: 1101 if(duplex == LM_MEDIUM_FULL_DUPLEX) 1102 { 1103 val |= MII_CTRL_DUPLEX_MODE; 1104 } 1105 1106 (void) lm_mwrite( 1107 pdev, 1108 pdev->params.phy_addr, 1109 MII_REG(serdes_reg_t, mii_ctrl), 1110 val); 1111 /* Switch to SGMII mode and disable auto-detect */ 1112 (void) lm_mread( 1113 pdev, 1114 pdev->params.phy_addr, 1115 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1), 1116 &val); 1117 (void) lm_mwrite( 1118 pdev, 1119 pdev->params.phy_addr, 1120 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1), 1121 val & ~(MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN)); 1122 break; 1123 1124 case LM_MEDIUM_SPEED_100MBPS: 1125 if(duplex == LM_MEDIUM_FULL_DUPLEX) 1126 { 1127 val |= MII_CTRL_DUPLEX_MODE; 1128 } 1129 1130 val |= MII_CTRL_MANUAL_SPD0; 1131 1132 (void) lm_mwrite( 1133 pdev, 1134 pdev->params.phy_addr, 1135 MII_REG(serdes_reg_t, mii_ctrl), 1136 val); 1137 /* Switch to SGMII mode and disable auto-detect */ 1138 (void) lm_mread( 1139 pdev, 1140 pdev->params.phy_addr, 1141 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1), 1142 &val); 1143 (void) lm_mwrite( 1144 pdev, 1145 pdev->params.phy_addr, 1146 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl1), 1147 val & ~(MII_1000X_CTL1_FIBER_MODE | MII_1000X_CTL1_AUTODET_EN)); 1148 break; 1149 1150 case LM_MEDIUM_SPEED_1000MBPS: 1151 if(duplex == LM_MEDIUM_FULL_DUPLEX) 1152 { 1153 val |= MII_CTRL_DUPLEX_MODE; 1154 } 1155 1156 val |= MII_CTRL_MANUAL_SPD1; 1157 1158 (void) lm_mwrite( 1159 pdev, 1160 pdev->params.phy_addr, 1161 MII_REG(serdes_reg_t, mii_ctrl), 1162 val); 1163 break; 1164 1165 case LM_MEDIUM_SPEED_2500MBPS: 1166 if(duplex == LM_MEDIUM_FULL_DUPLEX) 1167 { 1168 val |= MII_CTRL_DUPLEX_MODE; 1169 } 1170 1171 val |= MII_CTRL_MANUAL_FORCE_2500; 1172 1173 (void) lm_mwrite( 1174 pdev, 1175 pdev->params.phy_addr, 1176 MII_REG(serdes_reg_t, mii_ctrl), 1177 val); 1178 break; 1179 } 1180 } 1181 1182 /* exit mac loopback. we could be in mac loopback mode if previously 1183 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK 1184 * medium type for diagnostic. */ 1185 REG_RD(pdev, emac.emac_mode, &val); 1186 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK); 1187 REG_WR(pdev, emac.emac_mode, val); 1188 1189 /* Configure the PHY for jumbo frame. */ 1190 if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE) 1191 { 1192 (void) lm_mwrite( 1193 pdev, 1194 pdev->params.phy_addr, 1195 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl3), 1196 MII_1000X_CTL3_FIFO_ELAST_10K); 1197 } 1198 else 1199 { 1200 (void) lm_mwrite( 1201 pdev, 1202 pdev->params.phy_addr, 1203 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_ctl3), 1204 0); 1205 } 1206 1207 /* Save current medium settings. */ 1208 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER); 1209 SET_MEDIUM_SPEED(pdev->vars.medium, speed); 1210 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex); 1211 1212 pdev->vars.cable_is_attached = FALSE; 1213 1214 /* Wait for link. */ 1215 (void) lm_mread( 1216 pdev, 1217 pdev->params.phy_addr, 1218 MII_REG(serdes_reg_t, mii_status), 1219 &val); 1220 1221 for(; ;) 1222 { 1223 (void) lm_mread( 1224 pdev, 1225 pdev->params.phy_addr, 1226 MII_REG(serdes_reg_t, mii_status), 1227 &val); 1228 if(val & MII_STAT_LINK_STATUS) 1229 { 1230 break; 1231 } 1232 1233 mm_wait(pdev, 10); 1234 1235 if(wait_link_timeout_us <= 10) 1236 { 1237 break; 1238 } 1239 1240 wait_link_timeout_us -= 10; 1241 } 1242 1243 /* Need to read a second time to get the current link status. */ 1244 (void) lm_mread( 1245 pdev, 1246 pdev->params.phy_addr, 1247 MII_REG(serdes_reg_t, mii_status), 1248 &val); 1249 if(val & MII_STAT_LINK_STATUS) 1250 { 1251 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 1252 DbgMessage(pdev, INFORM, "phy init link up\n"); 1253 1254 pdev->vars.cable_is_attached = TRUE; 1255 } 1256 else 1257 { 1258 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 1259 DbgMessage(pdev, INFORM, "phy init link down\n"); 1260 } 1261 1262 return LM_STATUS_SUCCESS; 1263 } /* init_5708_serdes */ 1264 1265 1266 1267 /******************************************************************************* 1268 * Description: 1269 * 1270 * Return: 1271 ******************************************************************************/ 1272 STATIC void 1273 force_5709_serdes_link( 1274 lm_device_t *pdev, 1275 lm_medium_t speed, 1276 lm_medium_t duplex) 1277 { 1278 u32_t val; 1279 1280 /* select serdes digital block. */ 1281 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300); 1282 1283 /* disable sgmii/fiber mode autodetection. */ 1284 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 1285 val &= ~0x10; 1286 1287 /* sgmii or 1000x_fiber mode. */ 1288 val &= ~1; 1289 if(speed == LM_MEDIUM_SPEED_2500MBPS) 1290 { 1291 val |= 1; 1292 } 1293 1294 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val); 1295 1296 /* select combo ieee0 block. */ 1297 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 1298 1299 /* phy control register. */ 1300 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 1301 1302 val &= ~0x1000; /* autoneg. */ 1303 val &= ~0x100; /* duplex. */ 1304 val &= ~0x2060; /* speed. */ 1305 1306 if(duplex == LM_MEDIUM_FULL_DUPLEX) 1307 { 1308 val |= 0x100; 1309 } 1310 1311 if(speed == LM_MEDIUM_SPEED_10MBPS) 1312 { 1313 /* bit 13 and 6 are already cleared. */ 1314 ; 1315 } 1316 else if(speed == LM_MEDIUM_SPEED_100MBPS) 1317 { 1318 val |= 0x2000; 1319 } 1320 else if(speed == LM_MEDIUM_SPEED_1000MBPS) 1321 { 1322 val |= 0x2040; 1323 } 1324 else if(speed == LM_MEDIUM_SPEED_2500MBPS) 1325 { 1326 val |= 0x20; 1327 } 1328 else 1329 { 1330 DbgBreakMsg("unknown forced speed.\n"); 1331 } 1332 1333 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val); 1334 1335 /* set speed. */ 1336 if(speed == LM_MEDIUM_SPEED_2500MBPS) 1337 { 1338 /* select serdes digital block. */ 1339 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300); 1340 1341 /* set 2.5g speed. */ 1342 (void) lm_mread(pdev, pdev->params.phy_addr, 0x18, &val); 1343 val &= 0xfff0; 1344 val |= 0x10; 1345 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, val); 1346 } 1347 } /* force_5709_serdes_link */ 1348 1349 1350 1351 /******************************************************************************* 1352 * Description: 1353 * 1354 * Return: 1355 ******************************************************************************/ 1356 STATIC void 1357 init_5709_serdes_for_autoneg( 1358 lm_device_t *pdev, 1359 lm_medium_t req_medium, 1360 lm_flow_control_t flow_ctrl, 1361 u32_t selective_autoneg) 1362 { 1363 u32_t val; 1364 1365 if(GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_UNKNOWN) 1366 { 1367 selective_autoneg = FALSE; 1368 } 1369 1370 if(!(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_PHY_FIBER_2_5G) || 1371 (selective_autoneg && 1372 GET_MEDIUM_SPEED(req_medium) != LM_MEDIUM_SPEED_2500MBPS)) 1373 { 1374 /* disable 2.5g adv */ 1375 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8320); 1376 (void) lm_mread(pdev, pdev->params.phy_addr, 0x19, &val); 1377 val &= ~1; 1378 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x19, val); 1379 } 1380 1381 /* select serdes digital block. */ 1382 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8300); 1383 1384 /* enable sgmii/fiber mode autodetection. */ 1385 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 1386 val |= 0x10; 1387 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val); 1388 1389 /* disable parallel detection. */ 1390 if(selective_autoneg) 1391 { 1392 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val); 1393 val &= ~0x1; 1394 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x11, val); 1395 } 1396 1397 /* select bam next page block. */ 1398 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8350); 1399 1400 /* mp5_next_page_control. */ 1401 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 1402 val &= ~3; 1403 val |= 1; /* set bam mode. */ 1404 val |= 2; /* enable t2 mode. */ 1405 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val); 1406 1407 /* select cl73_userb0 block. */ 1408 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8370); 1409 1410 /* enable bam_en, bam_station_mngr_en, bam_np_after_bp_en. */ 1411 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x12, 0xe000); 1412 1413 /* select ieee1 block. */ 1414 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x10); 1415 1416 /* advertise 1000kx. */ 1417 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1, &val); 1418 val |= 0x20; 1419 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1, val); 1420 1421 /* select ieee0 block. */ 1422 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0); 1423 1424 /* enable cl73 aneg. */ 1425 (void) lm_mread(pdev, pdev->params.phy_addr, 0x0, &val); 1426 val |= 0x1200; 1427 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x0, val); 1428 1429 /* select combo ieee0 block. */ 1430 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 1431 1432 /* advertise pause capability and duplex mode. */ 1433 val = phy_ad_settings(pdev, req_medium, flow_ctrl); 1434 if(selective_autoneg && 1435 GET_MEDIUM_SPEED(req_medium) == LM_MEDIUM_SPEED_2500MBPS) 1436 { 1437 val &= ~0x60; 1438 } 1439 else 1440 { 1441 val |= 0x60; /* half/full duplex. */ 1442 } 1443 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x14, val); 1444 1445 /* autoneg_enable and restart. */ 1446 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 1447 val |= 0x1200; 1448 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, val); 1449 } /* init_5709_serdes_for_autoneg */ 1450 1451 1452 1453 /******************************************************************************* 1454 * Description: 1455 * 1456 * Return: 1457 ******************************************************************************/ 1458 STATIC lm_status_t 1459 init_5709_serdes( 1460 lm_device_t *pdev, 1461 lm_medium_t req_medium, 1462 lm_flow_control_t flow_ctrl, 1463 u32_t selective_autoneg, 1464 u32_t wait_link_timeout_us) 1465 { 1466 lm_medium_t duplex; 1467 lm_medium_t speed; 1468 u32_t idx; 1469 u32_t val; 1470 1471 speed = GET_MEDIUM_SPEED(req_medium); 1472 duplex = GET_MEDIUM_DUPLEX(req_medium); 1473 1474 /* use nvram link speed configuration. */ 1475 if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT) 1476 { 1477 REG_RD_IND( 1478 pdev, 1479 pdev->hw_info.shmem_base + 1480 OFFSETOF(shmem_region_t, dev_info.port_hw_config.config), 1481 &val); 1482 1483 switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK) 1484 { 1485 case PORT_HW_CFG_DEFAULT_LINK_1G: 1486 speed = LM_MEDIUM_SPEED_1000MBPS; 1487 break; 1488 1489 case PORT_HW_CFG_DEFAULT_LINK_2_5G: 1490 speed = LM_MEDIUM_SPEED_2500MBPS; 1491 break; 1492 1493 default: 1494 speed = LM_MEDIUM_SPEED_UNKNOWN; 1495 break; 1496 } 1497 1498 selective_autoneg = FALSE; 1499 } 1500 1501 /* set an_mmd. an_mmd is the only register set we need for 1502 * programming xinan serdes. all other registers are can 1503 * be access through an_mmd. */ 1504 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffd0); 1505 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1e, 0x3800); 1506 1507 /* select combo_ieee0 block. */ 1508 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 1509 1510 /* reset. */ 1511 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, MII_CTRL_RESET); 1512 for(idx = 0; idx < 1000; idx++) 1513 { 1514 mm_wait(pdev, 5); 1515 1516 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 1517 if(!(val & MII_CTRL_RESET)) 1518 { 1519 mm_wait(pdev, 5); 1520 break; 1521 } 1522 } 1523 DbgBreakIf(val & MII_CTRL_RESET); 1524 1525 /* get phy id. */ 1526 (void) lm_mread(pdev, pdev->params.phy_addr, 0x12, &val); 1527 pdev->hw_info.phy_id = val << 16; 1528 (void) lm_mread(pdev, pdev->params.phy_addr, 0x13, &val); 1529 pdev->hw_info.phy_id |= val & 0xffff; 1530 1531 if(speed == LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK) 1532 { 1533 speed = LM_MEDIUM_SPEED_AUTONEG; 1534 } 1535 1536 /* config link speed or autoneg setting. */ 1537 if(speed == LM_MEDIUM_SPEED_AUTONEG || selective_autoneg) 1538 { 1539 init_5709_serdes_for_autoneg( 1540 pdev, 1541 req_medium, 1542 flow_ctrl, 1543 selective_autoneg); 1544 } 1545 else 1546 { 1547 force_5709_serdes_link(pdev, speed, duplex); 1548 } 1549 1550 /* exit mac loopback. we could be in mac loopback mode if previously 1551 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK 1552 * medium type for diagnostic. */ 1553 REG_RD(pdev, emac.emac_mode, &val); 1554 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK); 1555 REG_WR(pdev, emac.emac_mode, val); 1556 1557 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER); 1558 SET_MEDIUM_SPEED(pdev->vars.medium, speed); 1559 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex); 1560 1561 pdev->vars.cable_is_attached = FALSE; 1562 1563 /* select combo_ieee0 block. */ 1564 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 1565 1566 /* wait for link. */ 1567 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val); 1568 1569 for(; ;) 1570 { 1571 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val); 1572 if(val & 0x4) 1573 { 1574 break; 1575 } 1576 1577 mm_wait(pdev, 10); 1578 1579 if(wait_link_timeout_us <= 10) 1580 { 1581 break; 1582 } 1583 1584 wait_link_timeout_us -= 10; 1585 } 1586 1587 /* need to read a second time to get the current link status. */ 1588 (void) lm_mread(pdev, pdev->params.phy_addr, 0x11, &val); 1589 1590 if(val & MII_STAT_LINK_STATUS) 1591 { 1592 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 1593 pdev->vars.cable_is_attached = TRUE; 1594 } 1595 else 1596 { 1597 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 1598 } 1599 1600 return LM_STATUS_SUCCESS; 1601 } /* init_5709_serdes */ 1602 1603 1604 1605 /******************************************************************************* 1606 * Description: 1607 * 1608 * Return: 1609 ******************************************************************************/ 1610 STATIC lm_status_t 1611 init_5706_serdes( 1612 lm_device_t *pdev, 1613 lm_medium_t req_medium, 1614 lm_flow_control_t flow_ctrl, 1615 u32_t wait_link_timeout_us) 1616 { 1617 lm_medium_t duplex; 1618 lm_medium_t speed; 1619 u32_t val; 1620 u32_t cnt; 1621 1622 speed = GET_MEDIUM_SPEED(req_medium); 1623 duplex = GET_MEDIUM_DUPLEX(req_medium); 1624 1625 if(speed == LM_MEDIUM_SPEED_HARDWARE_DEFAULT) 1626 { 1627 REG_RD_IND( 1628 pdev, 1629 pdev->hw_info.shmem_base + 1630 OFFSETOF(shmem_region_t, dev_info.port_hw_config.config), 1631 &val); 1632 switch(val & PORT_HW_CFG_DEFAULT_LINK_MASK) 1633 { 1634 case PORT_HW_CFG_DEFAULT_LINK_1G: 1635 speed = LM_MEDIUM_SPEED_1000MBPS; 1636 break; 1637 1638 case PORT_HW_CFG_DEFAULT_LINK_2_5G: 1639 speed = LM_MEDIUM_SPEED_2500MBPS; 1640 break; 1641 1642 case PORT_HW_CFG_DEFAULT_LINK_AN_1G_FALLBACK: 1643 speed = LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK; 1644 break; 1645 1646 case PORT_HW_CFG_DEFAULT_LINK_AN_2_5G_FALLBACK: 1647 speed = LM_MEDIUM_SPEED_AUTONEG_2_5G_FALLBACK; 1648 break; 1649 1650 default: 1651 speed = LM_MEDIUM_SPEED_UNKNOWN; 1652 } 1653 } 1654 1655 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, PHY_CTRL_PHY_RESET); 1656 for(cnt = 0; cnt < 1000; cnt++) 1657 { 1658 mm_wait(pdev, 5); 1659 1660 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val); 1661 1662 if(!(val & PHY_CTRL_PHY_RESET)) 1663 { 1664 mm_wait(pdev, 5); 1665 1666 break; 1667 } 1668 } 1669 1670 DbgBreakIf(val & PHY_CTRL_PHY_RESET); 1671 1672 /* Get the PHY id. */ 1673 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val); 1674 pdev->hw_info.phy_id = val << 16; 1675 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val); 1676 1677 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val); 1678 pdev->hw_info.phy_id |= val & 0xffff; 1679 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val); 1680 1681 DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff || 1682 pdev->hw_info.phy_id == 0); 1683 1684 /* The 5706S has problem determining link so getting link from 1685 * the MII status register is not reliable. This will force 1686 * the MAC to qualify the link ready signal with signal detect. 1687 * We will need to get the link status from the MAC instead of 1688 * the SERDES (MII status register). */ 1689 if(CHIP_NUM(pdev) == CHIP_NUM_5706 && 1690 lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER) 1691 { 1692 REG_WR(pdev, misc.misc_gp_hw_ctl0, 1693 MISC_GP_HW_CTL0_ENA_SEL_VAUX_B_IN_L2_TE | 1694 MISC_GP_HW_CTL0_GRC_BNK_FREE_FIX_TE); 1695 } 1696 1697 /* Setup flow control capabilities advertisement. */ 1698 val = PHY_AN_AD_1000X_HALF_DUPLEX; 1699 if(duplex == LM_MEDIUM_FULL_DUPLEX) 1700 { 1701 val |= PHY_AN_AD_1000X_FULL_DUPLEX; 1702 } 1703 val |= phy_ad_settings(pdev, req_medium, flow_ctrl); 1704 1705 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, val); 1706 1707 /* Determine the fallback selection. */ 1708 switch(speed) 1709 { 1710 case LM_MEDIUM_SPEED_AUTONEG_1G_FALLBACK: 1711 DbgMessage(pdev, INFORM, "enable serdes_fallback_1g\n"); 1712 pdev->vars.serdes_fallback_select = SERDES_FALLBACK_1G; 1713 break; 1714 1715 case LM_MEDIUM_SPEED_AUTONEG_2_5G_FALLBACK: 1716 DbgMessage(pdev, INFORM, "enable serdes_fallback_2.5g\n"); 1717 pdev->vars.serdes_fallback_select = SERDES_FALLBACK_2_5G; 1718 break; 1719 1720 default: 1721 DbgMessage(pdev, INFORM, "disable serdes_fallback.\n"); 1722 pdev->vars.serdes_fallback_select = SERDES_FALLBACK_NONE; 1723 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE; 1724 break; 1725 } 1726 1727 /* This routine could be called anytime. So if has not gone down 1728 * yet, we want to perserve the fallback setting. */ 1729 if(pdev->vars.serdes_fallback_select != SERDES_FALLBACK_NONE) 1730 { 1731 speed = LM_MEDIUM_SPEED_AUTONEG; 1732 1733 if(pdev->vars.link_status == LM_STATUS_LINK_ACTIVE) 1734 { 1735 if(pdev->vars.serdes_fallback_status == SERDES_FALLBACK_1G) 1736 { 1737 speed = LM_MEDIUM_SPEED_1000MBPS; 1738 } 1739 else if(pdev->vars.serdes_fallback_status == SERDES_FALLBACK_2_5G) 1740 { 1741 speed = LM_MEDIUM_SPEED_2500MBPS; 1742 } 1743 } 1744 } 1745 1746 if(speed == LM_MEDIUM_SPEED_1000MBPS) 1747 { 1748 val = PHY_CTRL_SPEED_SELECT_1000MBPS; 1749 if(duplex == LM_MEDIUM_FULL_DUPLEX) 1750 { 1751 val |= PHY_CTRL_FULL_DUPLEX_MODE; 1752 } 1753 1754 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, val); 1755 } 1756 else 1757 { 1758 val = PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG; 1759 1760 (void) lm_mwrite(pdev, pdev->params.phy_addr, PHY_CTRL_REG, val); 1761 1762 speed = LM_MEDIUM_SPEED_AUTONEG; 1763 } 1764 1765 /* exit mac loopback. we could be in mac loopback mode if previously 1766 * the upper module calls lm_init_phy with LM_MEDIUM_TYPE_MAC_LOOPBACK 1767 * medium type for diagnostic. */ 1768 REG_RD(pdev, emac.emac_mode, &val); 1769 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK); 1770 REG_WR(pdev, emac.emac_mode, val); 1771 1772 /* Configure the PHY for jumbo frame. */ 1773 if(pdev->params.mtu > MAX_ETHERNET_PACKET_SIZE) 1774 { 1775 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x4400); 1776 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0xec87); 1777 } 1778 else 1779 { 1780 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x18, 0x0400); 1781 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0xec85); 1782 } 1783 1784 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_FIBER); 1785 SET_MEDIUM_SPEED(pdev->vars.medium, speed); 1786 SET_MEDIUM_DUPLEX(pdev->vars.medium, duplex); 1787 1788 pdev->vars.cable_is_attached = FALSE; 1789 1790 /* Clear the latch bits. The second read below will get the 1791 * current status. */ 1792 val = mii_get_serdes_link_status(pdev); 1793 1794 /* Wait for link only if the cable is connected. */ 1795 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00); 1796 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val); 1797 if(val & 0x10) 1798 { 1799 for(; ;) 1800 { 1801 val = mii_get_serdes_link_status(pdev); 1802 1803 if(val & PHY_STATUS_LINK_PASS) 1804 { 1805 break; 1806 } 1807 1808 mm_wait(pdev, 10); 1809 1810 if(wait_link_timeout_us <= 10) 1811 { 1812 break; 1813 } 1814 1815 wait_link_timeout_us -= 10; 1816 } 1817 1818 pdev->vars.cable_is_attached = TRUE; 1819 } 1820 1821 /* Need to read a second time to get the current link status. */ 1822 val = mii_get_serdes_link_status(pdev); 1823 1824 if(val & PHY_STATUS_LINK_PASS) 1825 { 1826 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 1827 DbgMessage(pdev, INFORM, "phy init link up\n"); 1828 } 1829 else 1830 { 1831 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 1832 DbgMessage(pdev, INFORM, "phy init link down\n"); 1833 } 1834 1835 return LM_STATUS_SUCCESS; 1836 } /* init_5706_serdes */ 1837 1838 1839 1840 /******************************************************************************* 1841 * Description: 1842 * 1843 * Return: 1844 ******************************************************************************/ 1845 STATIC void 1846 init_serdes_or_phy_loopback( 1847 lm_device_t *pdev) 1848 { 1849 u32_t cnt; 1850 u32_t val; 1851 1852 (void) lm_mwrite( 1853 pdev, 1854 pdev->params.phy_addr, 1855 PHY_CTRL_REG, 1856 PHY_CTRL_PHY_RESET); 1857 for(cnt = 0; cnt < 1000; cnt++) 1858 { 1859 mm_wait(pdev, 5); 1860 1861 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &val); 1862 1863 if(!(val & PHY_CTRL_PHY_RESET)) 1864 { 1865 mm_wait(pdev, 5); 1866 break; 1867 } 1868 } 1869 1870 DbgBreakIf(val & PHY_CTRL_PHY_RESET); 1871 1872 /* Get the PHY id. */ 1873 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID1_REG, &val); 1874 pdev->hw_info.phy_id = val << 16; 1875 DbgMessage1(pdev, INFORM, "Phy Id1 0x%x\n", val); 1876 1877 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_ID2_REG, &val); 1878 pdev->hw_info.phy_id |= val & 0xffff; 1879 DbgMessage1(pdev, INFORM, "Phy Id2 0x%x\n", val); 1880 1881 DbgBreakIf((pdev->hw_info.phy_id & 0x0fffffff) == 0x0fffffff || 1882 pdev->hw_info.phy_id == 0); 1883 1884 REG_WR(pdev, emac.emac_tx_lengths, 0x26ff); 1885 1886 /* Set the phy into loopback mode. */ 1887 (void) lm_mwrite( 1888 pdev, 1889 pdev->params.phy_addr, 1890 PHY_CTRL_REG, 1891 PHY_CTRL_LOOPBACK_MODE | 1892 PHY_CTRL_FULL_DUPLEX_MODE | 1893 PHY_CTRL_SPEED_SELECT_1000MBPS); 1894 } /* init_serdes_or_phy_loopback */ 1895 1896 1897 1898 /******************************************************************************* 1899 * Description: 1900 * 1901 * Return: 1902 ******************************************************************************/ 1903 STATIC void 1904 init_5709_serdes_loopback( 1905 lm_device_t *pdev) 1906 { 1907 u32_t val; 1908 1909 /* 1910 * reset causes the speed not be back to 2.5g intermittently 1911 * after phy lookback test when connecting to a switch. 1912 */ 1913 #if 0 1914 /* select combo_ieee0 block. */ 1915 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 1916 1917 /* reset. */ 1918 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, MII_CTRL_RESET); 1919 for(idx = 0; idx < 1000; idx++) 1920 { 1921 mm_wait(pdev, 5); 1922 1923 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 1924 if(!(val & MII_CTRL_RESET)) 1925 { 1926 mm_wait(pdev, 5); 1927 break; 1928 } 1929 } 1930 DbgBreakIf(val & MII_CTRL_RESET); 1931 #endif 1932 1933 /* set an_mmd. an_mmd is the only register set we need for 1934 * programming xinan serdes. all other registers are can 1935 * be access through an_mmd. */ 1936 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffd0); 1937 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1e, 0x3800); 1938 1939 /* get phy id. */ 1940 (void) lm_mread(pdev, pdev->params.phy_addr, 0x12, &val); 1941 pdev->hw_info.phy_id = val << 16; 1942 (void) lm_mread(pdev, pdev->params.phy_addr, 0x13, &val); 1943 pdev->hw_info.phy_id |= val & 0xffff; 1944 1945 /* select combo_ieee0 block. */ 1946 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 1947 1948 /*CQ31687:set autoneg_enable bit too.*/ 1949 /* Set the phy into loopback mode. */ 1950 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x10, 0x5140); 1951 1952 } /* init_5709_serdes_loopback */ 1953 1954 1955 1956 /******************************************************************************* 1957 * Description: 1958 * 1959 * Return: 1960 ******************************************************************************/ 1961 STATIC lm_status_t 1962 init_loopback_mac_link( 1963 lm_device_t *pdev, 1964 lm_medium_t req_medium, 1965 lm_flow_control_t flow_ctrl) 1966 { 1967 lm_status_t lm_status; 1968 u32_t val; 1969 1970 lm_status = LM_STATUS_SUCCESS; 1971 1972 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_PHY_LOOPBACK) 1973 { 1974 if(CHIP_NUM(pdev) == CHIP_NUM_5709 && 1975 lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER) 1976 { 1977 init_5709_serdes_loopback(pdev); 1978 } 1979 else 1980 { 1981 init_serdes_or_phy_loopback(pdev); 1982 } 1983 1984 REG_WR(pdev, emac.emac_tx_lengths, 0x26ff); 1985 1986 REG_RD(pdev, emac.emac_mode, &val); 1987 val &= ~(EMAC_MODE_MAC_LOOP | EMAC_MODE_PORT); 1988 val |= EMAC_MODE_FORCE_LINK | EMAC_MODE_PORT_GMII; 1989 REG_WR(pdev, emac.emac_mode, val); 1990 1991 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_PHY_LOOPBACK); 1992 SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_UNKNOWN); 1993 SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX); 1994 1995 /* Save current link status. */ 1996 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 1997 1998 pdev->vars.cable_is_attached = TRUE; 1999 } 2000 else if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_TYPE_MAC_LOOPBACK) 2001 { 2002 DbgMessage(pdev, INFORM, "Set up MAC loopback mode.\n"); 2003 2004 /* Set the MAC into loopback mode. Mac loopback will intermittenly 2005 * fail if half_duplex bit is set. CQ#24594. */ 2006 REG_RD(pdev, emac.emac_mode, &val); 2007 val &= ~(EMAC_MODE_PORT | EMAC_MODE_HALF_DUPLEX); 2008 val |= EMAC_MODE_MAC_LOOP | EMAC_MODE_FORCE_LINK; 2009 2010 /* The port mode must be set to none on the real chip. */ 2011 if(CHIP_REV(pdev) == CHIP_REV_FPGA) 2012 { 2013 val |= EMAC_MODE_PORT_GMII; 2014 } 2015 2016 REG_WR(pdev, emac.emac_mode, val); 2017 2018 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_MAC_LOOPBACK); 2019 SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_UNKNOWN); 2020 SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX); 2021 2022 /* Save current link status. */ 2023 pdev->vars.link_status = LM_STATUS_LINK_ACTIVE; 2024 2025 pdev->vars.cable_is_attached = TRUE; 2026 } 2027 else 2028 { 2029 DbgBreakMsg("Not loopback medium type.\n"); 2030 2031 lm_status = LM_STATUS_FAILURE; 2032 2033 /* Save current link status. */ 2034 pdev->vars.link_status = LM_STATUS_LINK_DOWN; 2035 2036 pdev->vars.cable_is_attached = FALSE; 2037 } 2038 2039 /* Enable status block link attention. */ 2040 REG_RD(pdev, hc.hc_attn_bits_enable, &val); 2041 val |= STATUS_ATTN_BITS_LINK_STATE; 2042 REG_WR(pdev, hc.hc_attn_bits_enable, val); 2043 2044 return lm_status; 2045 } /* init_loopback_mac_link */ 2046 2047 2048 2049 /******************************************************************************* 2050 * Description: 2051 * 2052 * Return: 2053 ******************************************************************************/ 2054 STATIC lm_status_t 2055 init_null_phy( 2056 lm_device_t *pdev, 2057 lm_medium_t req_medium, 2058 lm_flow_control_t flow_ctrl, 2059 u32_t wait_link_timeout_us) 2060 { 2061 DbgMessage(pdev, INFORM, "### init_null_phy\n"); 2062 2063 if(GET_MEDIUM_TYPE(req_medium) != LM_MEDIUM_TYPE_NULL) 2064 { 2065 return LM_STATUS_INVALID_PARAMETER; 2066 } 2067 2068 /* Save current medium settings. */ 2069 SET_MEDIUM_TYPE(pdev->vars.medium, LM_MEDIUM_TYPE_NULL); 2070 SET_MEDIUM_SPEED(pdev->vars.medium, LM_MEDIUM_SPEED_1000MBPS); 2071 SET_MEDIUM_DUPLEX(pdev->vars.medium, LM_MEDIUM_FULL_DUPLEX); 2072 2073 pdev->vars.cable_is_attached = TRUE; 2074 2075 return LM_STATUS_SUCCESS; 2076 } /* init_null_phy */ 2077 2078 2079 2080 /******************************************************************************* 2081 * Description: 2082 * 2083 * Return: 2084 ******************************************************************************/ 2085 STATIC u32_t 2086 netlink_pause_ad( 2087 lm_flow_control_t flow_ctrl) 2088 { 2089 u32_t pause_ad; 2090 2091 pause_ad = 0; 2092 2093 if((flow_ctrl == LM_FLOW_CONTROL_AUTO_PAUSE) || 2094 ((flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) && 2095 (flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE))) 2096 { 2097 pause_ad |= NETLINK_DRV_SET_LINK_FC_SYM_PAUSE | 2098 NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE; 2099 } 2100 else if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 2101 { 2102 pause_ad |= NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE; 2103 } 2104 else if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) 2105 { 2106 pause_ad |= NETLINK_DRV_SET_LINK_FC_SYM_PAUSE | 2107 NETLINK_DRV_SET_LINK_FC_ASYM_PAUSE; 2108 } 2109 2110 return pause_ad; 2111 } /* netlink_pause_ad */ 2112 2113 2114 2115 /******************************************************************************* 2116 * Description: 2117 * 2118 * Return: 2119 ******************************************************************************/ 2120 STATIC u32_t 2121 link_setting_to_netlink( 2122 lm_link_settings_t *link_settings, 2123 u32_t serdes) 2124 { 2125 lm_medium_t duplex; 2126 lm_medium_t speed; 2127 u32_t netlink; 2128 2129 speed = GET_MEDIUM_SPEED(link_settings->req_medium); 2130 duplex = GET_MEDIUM_DUPLEX(link_settings->req_medium); 2131 netlink = 0; 2132 2133 switch(speed) 2134 { 2135 case LM_MEDIUM_SPEED_10MBPS: 2136 if(duplex == LM_MEDIUM_FULL_DUPLEX) 2137 { 2138 netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL; 2139 2140 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) == 2141 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 2142 { 2143 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF; 2144 } 2145 } 2146 else 2147 { 2148 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF; 2149 } 2150 break; 2151 2152 case LM_MEDIUM_SPEED_100MBPS: 2153 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) == 2154 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 2155 { 2156 netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL; 2157 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF; 2158 } 2159 2160 if(duplex == LM_MEDIUM_FULL_DUPLEX) 2161 { 2162 netlink |= NETLINK_DRV_SET_LINK_SPEED_100FULL; 2163 2164 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) == 2165 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 2166 { 2167 netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF; 2168 } 2169 } 2170 else 2171 { 2172 netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF; 2173 } 2174 break; 2175 2176 case LM_MEDIUM_SPEED_1000MBPS: 2177 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) == 2178 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 2179 { 2180 netlink |= NETLINK_DRV_SET_LINK_SPEED_10FULL; 2181 netlink |= NETLINK_DRV_SET_LINK_SPEED_10HALF; 2182 netlink |= NETLINK_DRV_SET_LINK_SPEED_100FULL; 2183 netlink |= NETLINK_DRV_SET_LINK_SPEED_100HALF; 2184 } 2185 2186 if(duplex == LM_MEDIUM_FULL_DUPLEX) 2187 { 2188 netlink |= NETLINK_DRV_SET_LINK_SPEED_1GFULL; 2189 2190 if((link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) == 2191 LINK_FLAG_SELECTIVE_AUTONEG_ENABLE_SLOWER_SPEEDS) 2192 { 2193 netlink |= NETLINK_DRV_SET_LINK_SPEED_1GHALF; 2194 } 2195 } 2196 else 2197 { 2198 netlink |= NETLINK_DRV_SET_LINK_SPEED_1GHALF; 2199 } 2200 break; 2201 2202 default: 2203 if (serdes) 2204 { 2205 netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG | 2206 NETLINK_DRV_SET_LINK_SPEED_1GHALF | 2207 NETLINK_DRV_SET_LINK_SPEED_1GFULL; 2208 } 2209 else 2210 { 2211 netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG | 2212 NETLINK_DRV_SET_LINK_SPEED_10HALF | 2213 NETLINK_DRV_SET_LINK_SPEED_10FULL | 2214 NETLINK_DRV_SET_LINK_SPEED_100HALF | 2215 NETLINK_DRV_SET_LINK_SPEED_100FULL | 2216 NETLINK_DRV_SET_LINK_SPEED_1GHALF | 2217 NETLINK_DRV_SET_LINK_SPEED_1GFULL; 2218 } 2219 break; 2220 } 2221 2222 netlink |= NETLINK_DRV_SET_LINK_PHY_RESET; 2223 2224 if(link_settings->flag & LINK_FLAG_SELECTIVE_AUTONEG_MASK) 2225 { 2226 netlink |= NETLINK_DRV_SET_LINK_ENABLE_AUTONEG; 2227 } 2228 2229 if(link_settings->flag & LINK_FLAG_WIRE_SPEED) 2230 { 2231 netlink |= NETLINK_DRV_SET_LINK_ETH_AT_WIRESPEED_ENABLE; 2232 } 2233 2234 netlink |= netlink_pause_ad(link_settings->flow_ctrl); 2235 2236 return netlink; 2237 } /* link_settings_to_netlink */ 2238 2239 2240 2241 /******************************************************************************* 2242 * Description: 2243 * 2244 * Return: 2245 ******************************************************************************/ 2246 lm_status_t 2247 lm_init_remote_phy( 2248 lm_device_t *pdev, 2249 lm_link_settings_t *serdes_link, 2250 lm_link_settings_t *rphy_link) 2251 { 2252 u32_t serdes_netlink; 2253 u32_t rphy_netlink; 2254 u32_t set_link_arg; 2255 u32_t val; 2256 2257 DbgBreakIf(pdev->params.enable_remote_phy == FALSE); 2258 2259 serdes_netlink = link_setting_to_netlink(serdes_link, TRUE); 2260 rphy_netlink = link_setting_to_netlink(rphy_link, FALSE); 2261 2262 REG_WR_IND( 2263 pdev, 2264 pdev->hw_info.shmem_base + 2265 OFFSETOF(shmem_region_t, remotephy.serdes_link_pref), 2266 serdes_netlink); 2267 2268 REG_WR_IND( 2269 pdev, 2270 pdev->hw_info.shmem_base + 2271 OFFSETOF(shmem_region_t, remotephy.copper_phy_link_pref), 2272 rphy_netlink | NETLINK_DRV_SET_LINK_PHY_APP_REMOTE); 2273 2274 REG_RD_IND( 2275 pdev, 2276 pdev->hw_info.shmem_base + 2277 OFFSETOF(shmem_region_t, drv_fw_mb.link_status), 2278 &val); 2279 if(val & NETLINK_GET_LINK_STATUS_SERDES_LINK) 2280 { 2281 set_link_arg = serdes_netlink; 2282 } 2283 else 2284 { 2285 set_link_arg = rphy_netlink | NETLINK_DRV_SET_LINK_PHY_APP_REMOTE; 2286 } 2287 2288 REG_WR_IND( 2289 pdev, 2290 pdev->hw_info.shmem_base + 2291 OFFSETOF(shmem_region_t, drv_fw_mb.mb_args[0]), 2292 set_link_arg); 2293 2294 (void) lm_submit_fw_cmd(pdev, DRV_MSG_CODE_CMD_SET_LINK); 2295 2296 return LM_STATUS_SUCCESS; 2297 } /* lm_init_remote_phy */ 2298 2299 2300 2301 /******************************************************************************* 2302 * Description: 2303 * 2304 * Return: 2305 ******************************************************************************/ 2306 lm_status_t 2307 lm_init_phy( 2308 lm_device_t *pdev, 2309 lm_medium_t req_medium, 2310 lm_flow_control_t flow_ctrl, 2311 u32_t selective_autoneg, 2312 u32_t wire_speed, 2313 u32_t wait_link_timeout_us) 2314 { 2315 lm_status_t lm_status; 2316 2317 DbgBreakIf(pdev->params.enable_remote_phy); 2318 2319 if(GET_MEDIUM_AUTONEG_MODE(req_medium) == LM_MEDIUM_SELECTIVE_AUTONEG) 2320 { 2321 selective_autoneg = TRUE; 2322 } 2323 2324 if(GET_MEDIUM_TYPE(req_medium) == LM_MEDIUM_AUTO_DETECT) 2325 { 2326 if(CHIP_REV(pdev) == CHIP_REV_IKOS) 2327 { 2328 req_medium = LM_MEDIUM_TYPE_NULL; 2329 } 2330 else if(CHIP_REV(pdev) == CHIP_REV_FPGA) 2331 { 2332 selective_autoneg = TRUE; 2333 req_medium = LM_MEDIUM_TYPE_UTP | 2334 LM_MEDIUM_SPEED_10MBPS | 2335 LM_MEDIUM_FULL_DUPLEX; 2336 } 2337 else if(lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER) 2338 { 2339 if(req_medium == LM_MEDIUM_AUTO_DETECT) 2340 { 2341 req_medium = LM_MEDIUM_TYPE_FIBER; 2342 } 2343 else 2344 { 2345 SET_MEDIUM_TYPE(req_medium, LM_MEDIUM_TYPE_FIBER); 2346 } 2347 } 2348 else 2349 { 2350 if(req_medium == LM_MEDIUM_AUTO_DETECT) 2351 { 2352 req_medium = LM_MEDIUM_TYPE_UTP; 2353 } 2354 else 2355 { 2356 SET_MEDIUM_TYPE(req_medium, LM_MEDIUM_TYPE_UTP); 2357 } 2358 } 2359 } 2360 2361 switch(GET_MEDIUM_TYPE(req_medium)) 2362 { 2363 case LM_MEDIUM_TYPE_UTP: 2364 lm_status = init_utp( 2365 pdev, 2366 req_medium, 2367 flow_ctrl, 2368 selective_autoneg, 2369 wire_speed, 2370 wait_link_timeout_us); 2371 break; 2372 2373 case LM_MEDIUM_TYPE_FIBER: 2374 DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5706 && 2375 CHIP_NUM(pdev) != CHIP_NUM_5708 && 2376 CHIP_NUM(pdev) != CHIP_NUM_5709); 2377 2378 if(CHIP_NUM(pdev) == CHIP_NUM_5706) 2379 { 2380 lm_status = init_5706_serdes( 2381 pdev, 2382 req_medium, 2383 flow_ctrl, 2384 wait_link_timeout_us); 2385 } 2386 else if(CHIP_NUM(pdev) == CHIP_NUM_5708) 2387 { 2388 lm_status = init_5708_serdes( 2389 pdev, 2390 req_medium, 2391 flow_ctrl, 2392 selective_autoneg, 2393 wait_link_timeout_us); 2394 } 2395 else 2396 { 2397 lm_status = init_5709_serdes( 2398 pdev, 2399 req_medium, 2400 flow_ctrl, 2401 selective_autoneg, 2402 wait_link_timeout_us); 2403 } 2404 2405 break; 2406 2407 case LM_MEDIUM_TYPE_NULL: 2408 lm_status = init_null_phy( 2409 pdev, 2410 req_medium, 2411 flow_ctrl, 2412 wait_link_timeout_us); 2413 break; 2414 2415 case LM_MEDIUM_TYPE_PHY_LOOPBACK: 2416 case LM_MEDIUM_TYPE_MAC_LOOPBACK: 2417 lm_status = init_loopback_mac_link( 2418 pdev, 2419 req_medium, 2420 flow_ctrl); 2421 break; 2422 2423 default: 2424 lm_status = LM_STATUS_UNKNOWN_MEDIUM; 2425 break; 2426 } 2427 2428 return lm_status; 2429 } /* lm_init_phy */ 2430 2431 2432 2433 /******************************************************************************* 2434 * Description: 2435 * 2436 * Return: 2437 ******************************************************************************/ 2438 STATIC void 2439 get_serdes_phy_ad( 2440 lm_device_t *pdev, 2441 u32_t *local_phy_ad, 2442 u32_t *remote_phy_ad) 2443 { 2444 u32_t val; 2445 2446 *local_phy_ad = 0; 2447 *remote_phy_ad = 0; 2448 2449 if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708) 2450 { 2451 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_AN_AD_REG, &val); 2452 2453 if(val & PHY_AN_AD_1000X_PAUSE_CAPABLE) 2454 { 2455 *local_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE; 2456 } 2457 2458 if(val & PHY_AN_AD_1000X_ASYM_PAUSE) 2459 { 2460 *local_phy_ad |= PHY_AN_AD_ASYM_PAUSE; 2461 } 2462 2463 (void) lm_mread(pdev,pdev->params.phy_addr,PHY_LINK_PARTNER_ABILITY_REG,&val); 2464 2465 if(val & PHY_AN_AD_1000X_PAUSE_CAPABLE) 2466 { 2467 *remote_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE; 2468 } 2469 2470 if(val & PHY_AN_AD_1000X_ASYM_PAUSE) 2471 { 2472 *remote_phy_ad |= PHY_AN_AD_ASYM_PAUSE; 2473 } 2474 } 2475 else 2476 { 2477 /* select combo ieee0 block. */ 2478 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 2479 2480 /* local advertisement. */ 2481 (void) lm_mread(pdev, pdev->params.phy_addr, 0x14, &val); 2482 2483 if(val & 0x80) 2484 { 2485 *local_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE; 2486 } 2487 2488 if(val & 0x100) 2489 { 2490 *local_phy_ad |= PHY_AN_AD_ASYM_PAUSE; 2491 } 2492 2493 /* remote advertisement. */ 2494 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &val); 2495 2496 if(val & 0x80) 2497 { 2498 *remote_phy_ad |= PHY_AN_AD_PAUSE_CAPABLE; 2499 } 2500 2501 if(val & 0x100) 2502 { 2503 *remote_phy_ad |= PHY_AN_AD_ASYM_PAUSE; 2504 } 2505 } 2506 } /* get_serdes_phy_ad */ 2507 2508 2509 2510 /******************************************************************************* 2511 * Description: 2512 * 2513 * Return: 2514 ******************************************************************************/ 2515 STATIC lm_flow_control_t 2516 set_mac_flow_control( 2517 lm_device_t *pdev, 2518 lm_medium_t medium, 2519 lm_flow_control_t flow_control_cap) 2520 { 2521 lm_flow_control_t flow_ctrl; 2522 u32_t remote_phy_link; 2523 u32_t remote_phy_ad; 2524 u32_t local_phy_ad; 2525 u32_t val; 2526 lm_rx_chain_t *rxq; 2527 u32_t idx; 2528 2529 if(pdev->params.enable_remote_phy) 2530 { 2531 local_phy_ad = 0; 2532 2533 if((flow_control_cap == LM_FLOW_CONTROL_AUTO_PAUSE) || 2534 ((flow_control_cap & LM_FLOW_CONTROL_RECEIVE_PAUSE) && 2535 (flow_control_cap & LM_FLOW_CONTROL_TRANSMIT_PAUSE)) || 2536 (flow_control_cap & LM_FLOW_CONTROL_RECEIVE_PAUSE)) 2537 { 2538 local_phy_ad |= (PHY_AN_AD_PAUSE_CAPABLE | PHY_AN_AD_ASYM_PAUSE); 2539 } 2540 else if(flow_control_cap & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 2541 { 2542 local_phy_ad |= PHY_AN_AD_ASYM_PAUSE; 2543 } 2544 2545 remote_phy_ad = 0; 2546 2547 REG_RD_IND( 2548 pdev, 2549 pdev->hw_info.shmem_base + 2550 OFFSETOF(shmem_region_t, drv_fw_mb.link_status), 2551 &remote_phy_link); 2552 2553 if(remote_phy_link & NETLINK_GET_LINK_STATUS_PARTNER_SYM_PAUSE_CAP) 2554 { 2555 remote_phy_ad |= PHY_LINK_PARTNER_PAUSE_CAPABLE; 2556 } 2557 2558 if(remote_phy_link & NETLINK_GET_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP) 2559 { 2560 remote_phy_ad |= PHY_LINK_PARTNER_ASYM_PAUSE; 2561 } 2562 } 2563 else 2564 { 2565 if(GET_MEDIUM_TYPE(medium) == LM_MEDIUM_TYPE_FIBER) 2566 { 2567 get_serdes_phy_ad(pdev, &local_phy_ad, &remote_phy_ad); 2568 } 2569 else 2570 { 2571 (void) lm_mread( 2572 pdev, 2573 pdev->params.phy_addr, 2574 PHY_AN_AD_REG, 2575 &local_phy_ad); 2576 2577 (void) lm_mread( 2578 pdev, 2579 pdev->params.phy_addr, 2580 PHY_LINK_PARTNER_ABILITY_REG, 2581 &remote_phy_ad); 2582 } 2583 } 2584 2585 DbgMessage(pdev, INFORM, "Local flow control settings.\n"); 2586 2587 if(local_phy_ad & PHY_AN_AD_PAUSE_CAPABLE) 2588 { 2589 DbgMessage(pdev, INFORM, " PAUSE capable.\n"); 2590 } 2591 2592 if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE) 2593 { 2594 DbgMessage(pdev, INFORM, " ASYM_PAUSE capable.\n"); 2595 } 2596 2597 DbgMessage(pdev, INFORM, "Remote flow control settings.\n"); 2598 2599 if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE) 2600 { 2601 DbgMessage(pdev, INFORM, " PAUSE capable.\n"); 2602 } 2603 2604 if(remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE) 2605 { 2606 DbgMessage(pdev, INFORM, " ASYM_PAUSE capable.\n"); 2607 } 2608 2609 /* Resultant flow control setting. */ 2610 flow_ctrl = LM_FLOW_CONTROL_NONE; 2611 2612 if((flow_control_cap & LM_FLOW_CONTROL_AUTO_PAUSE) || 2613 pdev->params.flow_control_reporting_mode) 2614 { 2615 /* See Table 28B-3 of 802.3ab-1999 spec. */ 2616 if(local_phy_ad & PHY_AN_AD_PAUSE_CAPABLE) 2617 { 2618 if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE) 2619 { 2620 if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE) 2621 { 2622 DbgMessage(pdev, INFORM, "FlowCap: tx/rx\n"); 2623 2624 flow_ctrl = 2625 LM_FLOW_CONTROL_TRANSMIT_PAUSE | 2626 LM_FLOW_CONTROL_RECEIVE_PAUSE; 2627 } 2628 else if(remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE) 2629 { 2630 DbgMessage(pdev, INFORM, "FlowCap: rx PAUSE\n"); 2631 2632 flow_ctrl = LM_FLOW_CONTROL_RECEIVE_PAUSE; 2633 } 2634 } 2635 else 2636 { 2637 if(remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE) 2638 { 2639 DbgMessage(pdev, INFORM, "FlowCap: tx/rx\n"); 2640 2641 flow_ctrl = 2642 LM_FLOW_CONTROL_TRANSMIT_PAUSE | 2643 LM_FLOW_CONTROL_RECEIVE_PAUSE; 2644 } 2645 } 2646 } 2647 else if(local_phy_ad & PHY_AN_AD_ASYM_PAUSE) 2648 { 2649 if((remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE) && 2650 (remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE)) 2651 { 2652 DbgMessage(pdev, INFORM, "FlowCap: tx PAUSE\n"); 2653 2654 flow_ctrl = LM_FLOW_CONTROL_TRANSMIT_PAUSE; 2655 } 2656 } 2657 } 2658 else 2659 { 2660 flow_ctrl = flow_control_cap; 2661 } 2662 2663 DbgMessage(pdev, INFORM, "Flow control capabilities.\n"); 2664 2665 if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 2666 { 2667 DbgMessage(pdev, INFORM, " tx PAUSE\n"); 2668 } 2669 2670 if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) 2671 { 2672 DbgMessage(pdev, INFORM, " rx PAUSE\n"); 2673 } 2674 2675 if(flow_ctrl == LM_FLOW_CONTROL_NONE) 2676 { 2677 DbgMessage(pdev, INFORM, " none.\n"); 2678 } 2679 2680 /* Enable/disable rx PAUSE. */ 2681 REG_RD(pdev, emac.emac_rx_mode, &val); 2682 val &= ~EMAC_RX_MODE_FLOW_EN; 2683 2684 if(flow_ctrl & LM_FLOW_CONTROL_RECEIVE_PAUSE) 2685 { 2686 val |= EMAC_RX_MODE_FLOW_EN; 2687 DbgMessage(pdev, INFORM, "Enable rx PAUSE.\n"); 2688 } 2689 REG_WR(pdev, emac.emac_rx_mode, val); 2690 2691 /* Enable/disable tx PAUSE. */ 2692 REG_RD(pdev, emac.emac_tx_mode, &val); 2693 val &= ~EMAC_TX_MODE_FLOW_EN; 2694 2695 if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 2696 { 2697 val |= EMAC_TX_MODE_FLOW_EN; 2698 DbgMessage(pdev, INFORM, "Enable tx PAUSE.\n"); 2699 } 2700 REG_WR(pdev, emac.emac_tx_mode, val); 2701 2702 for(idx = 0; idx < pdev->rx_info.num_rxq; idx++) 2703 { 2704 rxq = &pdev->rx_info.chain[idx]; 2705 val = CTX_RD( 2706 pdev, 2707 rxq->cid_addr, 2708 WORD_ALIGNED_OFFSETOF(l2_bd_chain_context_t, l2ctx_ctx_type)); 2709 2710 /* Enable/disable RV2P wait (i.e. watermark field) for buffer post based on flow control setting. */ 2711 if(flow_ctrl & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 2712 { 2713 val |= 0xFF; 2714 } 2715 else 2716 { 2717 // RV2P is checking for non-zero in this byte field 2718 val &= ~0xFF; 2719 } 2720 CTX_WR( 2721 pdev, 2722 rxq->cid_addr, 2723 WORD_ALIGNED_OFFSETOF(l2_bd_chain_context_t, l2ctx_ctx_type), 2724 val); 2725 } 2726 2727 return flow_ctrl; 2728 } /* set_mac_flow_control */ 2729 2730 2731 2732 /******************************************************************************* 2733 * Description: 2734 * 2735 * Return: 2736 ******************************************************************************/ 2737 STATIC lm_status_t 2738 get_copper_phy_link( 2739 lm_device_t *pdev, 2740 lm_medium_t *medium) 2741 { 2742 lm_medium_t duplex; 2743 lm_medium_t speed; 2744 lm_status_t link; 2745 u32_t phy_status; 2746 u32_t remote_adv; 2747 u32_t local_adv; 2748 u32_t phy_ctrl; 2749 u32_t val; 2750 2751 DbgMessage(pdev, INFORM, "### get_copper_phy_link\n"); 2752 2753 *medium = LM_MEDIUM_TYPE_UTP | 2754 LM_MEDIUM_SPEED_UNKNOWN | 2755 LM_MEDIUM_FULL_DUPLEX; 2756 2757 pdev->vars.cable_is_attached = FALSE; 2758 2759 /* Check for link. The first read returns the latched value, the 2760 * second read returns the current value. */ 2761 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status); 2762 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status); 2763 if((phy_status & PHY_STATUS_LINK_PASS) == 0) 2764 { 2765 DbgMessage(pdev, INFORM, "link down.\n"); 2766 2767 if(CHIP_REV(pdev) != CHIP_REV_FPGA) 2768 { 2769 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00); 2770 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val); 2771 if(val & 0x20) 2772 { 2773 pdev->vars.cable_is_attached = TRUE; 2774 } 2775 } 2776 2777 return LM_STATUS_LINK_DOWN; 2778 } 2779 2780 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl); 2781 2782 /* Make sure the PHY control register is valid. */ 2783 DbgBreakIf(phy_ctrl & ( 2784 PHY_CTRL_COLLISION_TEST_ENABLE | 2785 PHY_CTRL_RESTART_AUTO_NEG | 2786 PHY_CTRL_ISOLATE_PHY | 2787 PHY_CTRL_LOOPBACK_MODE | 2788 PHY_CTRL_PHY_RESET)); 2789 2790 link = LM_STATUS_LINK_ACTIVE; 2791 pdev->vars.cable_is_attached = TRUE; 2792 2793 /* Determine duplex mode. Link is present also means autoneg is done. */ 2794 if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE) 2795 { 2796 /* Autonegotiation is enabled. And since we have link, we know 2797 * autonegotiation has completed. 2798 * 2799 * Infer the link speed by figuring out the highest common speed 2800 * between us and our link partner. */ 2801 2802 /* Get local and remote 1000BASET advertisement. */ 2803 (void) lm_mread( 2804 pdev, 2805 pdev->params.phy_addr, 2806 PHY_1000BASET_CTRL_REG, 2807 &local_adv); 2808 (void) lm_mread( 2809 pdev, 2810 pdev->params.phy_addr, 2811 PHY_1000BASET_STATUS_REG, 2812 &remote_adv); 2813 2814 val = local_adv & (remote_adv >> 2); 2815 if(val & PHY_AN_AD_1000BASET_FULL) 2816 { 2817 DbgMessage(pdev, INFORM, "detected 1gb full autoneg.\n"); 2818 2819 speed = LM_MEDIUM_SPEED_1000MBPS; 2820 duplex = LM_MEDIUM_FULL_DUPLEX; 2821 } 2822 else if(val & PHY_AN_AD_1000BASET_HALF) 2823 { 2824 DbgMessage(pdev, INFORM, "detected 1gb half autoneg.\n"); 2825 2826 speed = LM_MEDIUM_SPEED_1000MBPS; 2827 duplex = LM_MEDIUM_HALF_DUPLEX; 2828 } 2829 else 2830 { 2831 /* Get local and remote 10/100 mb advertisement. */ 2832 (void) lm_mread( 2833 pdev, 2834 pdev->params.phy_addr, 2835 PHY_AN_AD_REG, 2836 &local_adv); 2837 2838 (void) lm_mread( 2839 pdev, 2840 pdev->params.phy_addr, 2841 PHY_LINK_PARTNER_ABILITY_REG, 2842 &remote_adv); 2843 2844 val = local_adv & remote_adv; 2845 if(val & PHY_AN_AD_100BASETX_FULL) 2846 { 2847 DbgMessage(pdev, INFORM, "detected 100mb full autoneg.\n"); 2848 2849 speed = LM_MEDIUM_SPEED_100MBPS; 2850 duplex = LM_MEDIUM_FULL_DUPLEX; 2851 } 2852 else if(val & PHY_AN_AD_100BASETX_HALF) 2853 { 2854 DbgMessage(pdev, INFORM, "detected 100mb half autoneg.\n"); 2855 2856 speed = LM_MEDIUM_SPEED_100MBPS; 2857 duplex = LM_MEDIUM_HALF_DUPLEX; 2858 } 2859 else if(val & PHY_AN_AD_10BASET_FULL) 2860 { 2861 DbgMessage(pdev, INFORM, "detected 10mb full autoneg.\n"); 2862 2863 speed = LM_MEDIUM_SPEED_10MBPS; 2864 duplex = LM_MEDIUM_FULL_DUPLEX; 2865 } 2866 else if(val & PHY_AN_AD_10BASET_HALF) 2867 { 2868 DbgMessage(pdev, INFORM, "detected 10mb half autoneg.\n"); 2869 2870 speed = LM_MEDIUM_SPEED_10MBPS; 2871 duplex = LM_MEDIUM_HALF_DUPLEX; 2872 } 2873 else 2874 { 2875 DbgBreakMsg("unable to determine autoneg speed.\n"); 2876 2877 speed = LM_MEDIUM_SPEED_UNKNOWN; 2878 duplex = LM_MEDIUM_FULL_DUPLEX; 2879 link = LM_STATUS_LINK_DOWN; 2880 } 2881 } 2882 } 2883 else 2884 { 2885 /* The link speed speed and duplex mode are forced. Get the forced 2886 * line settings from the PHY control register. */ 2887 if(phy_ctrl & PHY_CTRL_SPEED_SELECT_100MBPS) 2888 { 2889 DbgMessage(pdev, INFORM, "PHY forced to 100mb.\n"); 2890 speed = LM_MEDIUM_SPEED_100MBPS; 2891 } 2892 else if(phy_ctrl & PHY_CTRL_SPEED_SELECT_1000MBPS) 2893 { 2894 DbgMessage(pdev, INFORM, "PHY forced to 1gb.\n"); 2895 2896 speed = LM_MEDIUM_SPEED_1000MBPS; 2897 } 2898 else 2899 { 2900 DbgMessage(pdev, INFORM, "PHY forced to 10mb.\n"); 2901 2902 speed = LM_MEDIUM_SPEED_10MBPS; 2903 } 2904 2905 if(phy_ctrl & PHY_CTRL_FULL_DUPLEX_MODE) 2906 { 2907 DbgMessage(pdev, INFORM, "PHY forced to full duplex.\n"); 2908 2909 duplex = LM_MEDIUM_FULL_DUPLEX; 2910 } 2911 else 2912 { 2913 DbgMessage(pdev, INFORM, "PHY forced to half duplex.\n"); 2914 2915 duplex = LM_MEDIUM_HALF_DUPLEX; 2916 } 2917 } 2918 2919 *medium = LM_MEDIUM_TYPE_UTP | speed | duplex; 2920 2921 return link; 2922 } /* get_copper_phy_link */ 2923 2924 2925 2926 /******************************************************************************* 2927 * Description: 2928 * 2929 * Return: 2930 ******************************************************************************/ 2931 STATIC void 2932 init_mac_link( 2933 lm_device_t *pdev, 2934 lm_status_t link, 2935 lm_medium_t medium, 2936 lm_flow_control_t flow_ctrl) 2937 { 2938 u32_t val; 2939 2940 /* Configure slot time, IPG, and 802.3 flow control. */ 2941 REG_WR(pdev, emac.emac_tx_lengths, 0x2620); 2942 if(link == LM_STATUS_LINK_ACTIVE) 2943 { 2944 if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_1000MBPS && 2945 GET_MEDIUM_DUPLEX(medium) == LM_MEDIUM_HALF_DUPLEX) 2946 { 2947 REG_WR(pdev, emac.emac_tx_lengths, 0x26ff); 2948 } 2949 2950 pdev->vars.flow_control = set_mac_flow_control(pdev, medium, flow_ctrl); 2951 } 2952 2953 /* Configure the EMAC mode register. */ 2954 REG_RD(pdev, emac.emac_mode, &val); 2955 2956 val &= ~(EMAC_MODE_PORT | EMAC_MODE_FORCE_LINK); 2957 2958 if(link == LM_STATUS_LINK_ACTIVE) 2959 { 2960 if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_10MBPS) 2961 { 2962 if(CHIP_NUM(pdev) == CHIP_NUM_5706) 2963 { 2964 val |= EMAC_MODE_PORT_MII; 2965 } 2966 else 2967 { 2968 /* 5708 setting. */ 2969 val |= EMAC_MODE_PORT_MII_10M; 2970 } 2971 } 2972 else if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_100MBPS) 2973 { 2974 val |= EMAC_MODE_PORT_MII; 2975 } 2976 else 2977 { 2978 val |= EMAC_MODE_PORT_GMII; 2979 } 2980 2981 if(GET_MEDIUM_SPEED(medium) == LM_MEDIUM_SPEED_2500MBPS) 2982 { 2983 val |= EMAC_MODE_25G_MODE; 2984 } 2985 2986 /* We need to set the port mode to GMII when we are running in 2987 * the FPGA mode, regardless of the actual line speed. */ 2988 if(CHIP_REV(pdev) == CHIP_REV_FPGA) 2989 { 2990 val &= ~EMAC_MODE_PORT; 2991 val |= EMAC_MODE_PORT_GMII; 2992 } 2993 } 2994 else 2995 { 2996 val |= EMAC_MODE_PORT_GMII; 2997 } 2998 2999 if(GET_MEDIUM_TYPE(medium) == LM_MEDIUM_TYPE_NULL) 3000 { 3001 val |= EMAC_MODE_FORCE_LINK; 3002 } 3003 3004 /* Set the MAC to operate in the appropriate duplex mode. */ 3005 val &= ~EMAC_MODE_HALF_DUPLEX; 3006 if(GET_MEDIUM_DUPLEX(medium) == LM_MEDIUM_HALF_DUPLEX) 3007 { 3008 val |= EMAC_MODE_HALF_DUPLEX; 3009 } 3010 REG_WR(pdev, emac.emac_mode, val); 3011 3012 /* Acknowledge the interrupt. */ 3013 REG_WR(pdev, emac.emac_status, EMAC_STATUS_LINK_CHANGE); 3014 3015 /* Enable phy link change attention. */ 3016 if(pdev->params.phy_int_mode == PHY_INT_MODE_MI_INTERRUPT) 3017 { 3018 REG_WR(pdev, emac.emac_attention_ena, EMAC_ATTENTION_ENA_MI_INT); 3019 } 3020 else 3021 { 3022 REG_WR(pdev, emac.emac_attention_ena, EMAC_ATTENTION_ENA_LINK); 3023 } 3024 3025 /* Enable status block link attention. */ 3026 REG_RD(pdev, hc.hc_attn_bits_enable, &val); 3027 val &= ~STATUS_ATTN_BITS_LINK_STATE; 3028 if(pdev->params.link_chng_mode == LINK_CHNG_MODE_USE_STATUS_BLOCK) 3029 { 3030 val |= STATUS_ATTN_BITS_LINK_STATE; 3031 } 3032 REG_WR(pdev, hc.hc_attn_bits_enable, val); 3033 3034 pdev->vars.medium = medium; 3035 pdev->vars.link_status = link; 3036 } /* init_mac_link */ 3037 3038 3039 3040 /******************************************************************************* 3041 * Description: 3042 * 3043 * Return: 3044 ******************************************************************************/ 3045 STATIC lm_status_t 3046 serdes_fallback( 3047 lm_device_t *pdev, 3048 u8_t fallback_select) 3049 { 3050 u32_t intr_exp_status; 3051 u8_t fallback_to; 3052 u32_t phy_status; 3053 u32_t phy_ctrl; 3054 u32_t val; 3055 u32_t cnt; 3056 3057 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE; 3058 3059 if(fallback_select == SERDES_FALLBACK_NONE) 3060 { 3061 return LM_STATUS_LINK_DOWN; 3062 } 3063 3064 /* See if the cable is connected. */ 3065 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00); 3066 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val); 3067 3068 /* We think the cable is not attached, set up the serdes to 3069 * autoneg as the default. */ 3070 if(!(val & 0x10)) /* SIG_DETECT */ 3071 { 3072 DbgMessage(pdev, INFORM, "no cable, default to autoneg.\n"); 3073 3074 (void) lm_mwrite( 3075 pdev, 3076 pdev->params.phy_addr, 3077 PHY_CTRL_REG, 3078 PHY_CTRL_AUTO_NEG_ENABLE); 3079 3080 return LM_STATUS_LINK_DOWN; 3081 } 3082 3083 /* Read the interrupt expansion register to see if rudi_c is set. 3084 * rudi_c is set when we are receiving config words which means 3085 * the link partner is attempting to autonegotiate. 3086 * 3087 * When the link partner is attempting to autonegotiate and we 3088 * are not able to get linke, it could mean our transmit cable 3089 * is not plugged in. In this case we don't want to fallback 3090 * to the force mode. We want to remain in autonegotiation mode. */ 3091 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x0f01); 3092 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &intr_exp_status); 3093 (void) lm_mread(pdev, pdev->params.phy_addr, 0x15, &intr_exp_status); 3094 3095 /* See if autoneg is enabled and the remote is not sending us 3096 * configs. If this is the case and link is currently down, we 3097 * will switch to the force mode and disable autonegotiation. 3098 * 3099 * If we are current in the forced mode or the link partner is 3100 * sending use configs, we'll enable autoneg and restart it. */ 3101 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl); 3102 if((phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE) && !(intr_exp_status & 0x20)) 3103 { 3104 DbgMessage(pdev, INFORM, "switch to force mode - 1G full\n"); 3105 3106 (void) lm_mwrite( 3107 pdev, 3108 pdev->params.phy_addr, 3109 PHY_CTRL_REG, 3110 PHY_CTRL_SPEED_SELECT_1000MBPS | PHY_CTRL_FULL_DUPLEX_MODE); 3111 3112 fallback_to = SERDES_FALLBACK_1G; 3113 } 3114 else 3115 { 3116 DbgMessage(pdev, INFORM, "switch to autoneg mode - 1G full\n"); 3117 3118 /* Switch to autoneg mode. */ 3119 (void) lm_mwrite( 3120 pdev, 3121 pdev->params.phy_addr, 3122 PHY_CTRL_REG, 3123 PHY_CTRL_AUTO_NEG_ENABLE | PHY_CTRL_RESTART_AUTO_NEG); 3124 3125 fallback_to = SERDES_FALLBACK_NONE; 3126 } 3127 3128 for(cnt = 0; cnt < 100; cnt++) 3129 { 3130 mm_wait(pdev, 10); 3131 } 3132 3133 phy_status = mii_get_serdes_link_status(pdev); 3134 3135 if(phy_status & PHY_STATUS_LINK_PASS) 3136 { 3137 pdev->vars.serdes_fallback_status = fallback_to; 3138 3139 return LM_STATUS_LINK_ACTIVE; 3140 } 3141 3142 return LM_STATUS_LINK_DOWN; 3143 } /* serdes_fallback */ 3144 3145 3146 3147 /******************************************************************************* 3148 * Description: 3149 * 3150 * Return: 3151 ******************************************************************************/ 3152 STATIC lm_status_t 3153 get_5708_serdes_link( 3154 lm_device_t *pdev, 3155 lm_medium_t *medium) 3156 { 3157 u8_t restarted_autoneg; 3158 lm_medium_t duplex; 3159 lm_medium_t speed; 3160 lm_status_t link; 3161 u32_t val; 3162 u32_t idx; 3163 3164 *medium = LM_MEDIUM_TYPE_FIBER | 3165 LM_MEDIUM_SPEED_UNKNOWN | 3166 LM_MEDIUM_FULL_DUPLEX; 3167 3168 pdev->vars.cable_is_attached = FALSE; 3169 3170 /* Check for link. The first read returns the latched value, the 3171 * second read returns the current value. */ 3172 (void) lm_mread( 3173 pdev, 3174 pdev->params.phy_addr, 3175 MII_REG(serdes_reg_t, mii_status), 3176 &val); 3177 (void) lm_mread( 3178 pdev, 3179 pdev->params.phy_addr, 3180 MII_REG(serdes_reg_t, mii_status), 3181 &val); 3182 3183 /* CQ#23742 - Link status in the status block and the link status 3184 * in the mii_status are not consistent. mii_status appears to 3185 * return invalid value. Added a workaround here. */ 3186 for(idx = 0; idx < 10 && val == 0; idx++) 3187 { 3188 mm_wait(pdev, 10); 3189 3190 (void) lm_mread( 3191 pdev, 3192 pdev->params.phy_addr, 3193 MII_REG(serdes_reg_t, mii_status), 3194 &val); 3195 } 3196 3197 if((val & MII_STAT_LINK_STATUS) == 0) 3198 { 3199 DbgMessage(pdev, INFORM, "serdes link down.\n"); 3200 3201 pdev->vars.cable_is_attached = FALSE; 3202 3203 return LM_STATUS_LINK_DOWN; 3204 } 3205 3206 link = LM_STATUS_LINK_ACTIVE; 3207 pdev->vars.cable_is_attached = TRUE; 3208 3209 /* Determine duplex mode. Link is present also means autoneg is done. */ 3210 (void) lm_mread( 3211 pdev, 3212 pdev->params.phy_addr, 3213 MII_REG(serdes_reg_t, mii_ctrl), 3214 &val); 3215 if(val & MII_CTRL_ANEG_ENA) 3216 { 3217 /* Select Bank 0. */ 3218 (void) lm_mwrite( 3219 pdev, 3220 pdev->params.phy_addr, 3221 MII_REG(serdes_reg_t, mii_block_addr), 3222 MII_BLK_ADDR_DIGITAL); 3223 3224 /* Get the negotiated speed and duplex mode. */ 3225 (void) lm_mread( 3226 pdev, 3227 pdev->params.phy_addr, 3228 0x10+MII_REG(serdes_digital_reg_t, mii_1000x_stat1), 3229 &val); 3230 switch(val & MII_1000X_STAT1_SPEED) 3231 { 3232 case MII_1000X_STAT1_SPEED_2G5: 3233 DbgMessage(pdev, INFORM, "serdes autoneg to 2.5gb.\n"); 3234 speed = LM_MEDIUM_SPEED_2500MBPS; 3235 break; 3236 3237 case MII_1000X_STAT1_SPEED_1G: 3238 DbgMessage(pdev, INFORM, "serdes autoneg to 1gb.\n"); 3239 speed = LM_MEDIUM_SPEED_1000MBPS; 3240 break; 3241 3242 case MII_1000X_STAT1_SPEED_100: 3243 DbgMessage(pdev, INFORM, "serdes autoneg to 100mb.\n"); 3244 speed = LM_MEDIUM_SPEED_100MBPS; 3245 break; 3246 3247 case MII_1000X_STAT1_SPEED_10: 3248 default: 3249 DbgMessage(pdev, INFORM, "serdes autoneg to 10mb.\n"); 3250 speed = LM_MEDIUM_SPEED_10MBPS; 3251 break; 3252 } 3253 3254 /* Get the duplex mode. */ 3255 duplex = LM_MEDIUM_FULL_DUPLEX; 3256 if(val & MII_1000X_STAT1_DUPLEX) 3257 { 3258 DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n"); 3259 } 3260 else 3261 { 3262 (void) lm_mread( 3263 pdev, 3264 pdev->params.phy_addr, 3265 MII_REG(serdes_reg_t, mii_status), 3266 &val); 3267 if(val & MII_STAT_ANEG_CMPL) 3268 { 3269 duplex = LM_MEDIUM_HALF_DUPLEX; 3270 DbgMessage(pdev, INFORM, "serdes autoneg to half duplex.\n"); 3271 } 3272 else 3273 { 3274 DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n"); 3275 } 3276 } 3277 3278 /* Set up pre-emphasis for a backplane application. */ 3279 if(pdev->hw_info.nvm_hw_config & SHARED_HW_CFG_BACKPLANE_APP) 3280 { 3281 restarted_autoneg = set_5708_serdes_pre_emphasis( 3282 pdev, 3283 pdev->params.serdes_pre_emphasis); 3284 3285 if(restarted_autoneg) 3286 { 3287 speed = LM_MEDIUM_SPEED_UNKNOWN; 3288 duplex = LM_MEDIUM_FULL_DUPLEX; 3289 link = LM_STATUS_LINK_DOWN; 3290 } 3291 } 3292 } 3293 else 3294 { 3295 /* Determine the forced link settings. */ 3296 if(val & MII_CTRL_MANUAL_FORCE_2500) 3297 { 3298 DbgMessage(pdev, INFORM, "serdes forced to 2.5gb.\n"); 3299 speed = LM_MEDIUM_SPEED_2500MBPS; 3300 } 3301 else if(val & MII_CTRL_MANUAL_SPD1) 3302 { 3303 DbgMessage(pdev, INFORM, "serdes forced to 1gb.\n"); 3304 speed = LM_MEDIUM_SPEED_1000MBPS; 3305 } 3306 else if(val & MII_CTRL_MANUAL_SPD0) 3307 { 3308 DbgMessage(pdev, INFORM, "serdes forced to 100mb.\n"); 3309 speed = LM_MEDIUM_SPEED_100MBPS; 3310 } 3311 else 3312 { 3313 DbgMessage(pdev, INFORM, "serdes forced to 10mb.\n"); 3314 speed = LM_MEDIUM_SPEED_10MBPS; 3315 } 3316 3317 if(val & MII_CTRL_DUPLEX_MODE) 3318 { 3319 DbgMessage(pdev, INFORM, "serdes forced to full duplex.\n"); 3320 duplex = LM_MEDIUM_FULL_DUPLEX; 3321 } 3322 else 3323 { 3324 DbgMessage(pdev, INFORM, "serdes forced to half duplex.\n"); 3325 duplex = LM_MEDIUM_HALF_DUPLEX; 3326 } 3327 } 3328 3329 *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex; 3330 3331 return link; 3332 } /* get_5708_serdes_link */ 3333 3334 3335 3336 /******************************************************************************* 3337 * Description: 3338 * 3339 * Return: 3340 ******************************************************************************/ 3341 STATIC lm_status_t 3342 get_5709_serdes_link( 3343 lm_device_t *pdev, 3344 lm_medium_t *medium) 3345 { 3346 lm_medium_t duplex = LM_MEDIUM_FULL_DUPLEX; 3347 lm_medium_t speed = LM_MEDIUM_SPEED_UNKNOWN; 3348 lm_status_t link = LM_STATUS_LINK_UNKNOWN; 3349 u32_t mac_status; 3350 u32_t val; 3351 3352 *medium = LM_MEDIUM_TYPE_FIBER | 3353 LM_MEDIUM_SPEED_UNKNOWN | 3354 LM_MEDIUM_FULL_DUPLEX; 3355 3356 pdev->vars.cable_is_attached = FALSE; 3357 3358 /* select gp_status block. */ 3359 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8120); 3360 3361 /* get status. */ 3362 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val); 3363 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val); /* is this needed? */ 3364 3365 /* sometimes when we get a link event, mii register 0x1b does not 3366 * reflect the current link status but mac_status does reflect the 3367 * correct link status. */ 3368 REG_RD(pdev, emac.emac_status, &mac_status); 3369 3370 /* link down. */ 3371 if((val & 0x4) == 0 && (mac_status & EMAC_STATUS_LINK) == 0) 3372 { 3373 return LM_STATUS_LINK_DOWN; 3374 } 3375 3376 link = LM_STATUS_LINK_ACTIVE; 3377 pdev->vars.cable_is_attached = TRUE; 3378 3379 /* select combo ieee0 block. */ 3380 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0xffe0); 3381 3382 /* phy_ctrl register. */ 3383 (void) lm_mread(pdev, pdev->params.phy_addr, 0x10, &val); 3384 3385 if(val & 0x1000) 3386 { 3387 /* select gp_status block. */ 3388 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1f, 0x8120); 3389 3390 /* get status. */ 3391 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1b, &val); 3392 3393 /* duplex mode. */ 3394 if(val & 0x8) 3395 { 3396 duplex = LM_MEDIUM_FULL_DUPLEX; 3397 } 3398 else 3399 { 3400 duplex = LM_MEDIUM_HALF_DUPLEX; 3401 } 3402 3403 /* Determine autoneg speed. */ 3404 val = (val >> 8) & 0x3f; 3405 if(val == 0) 3406 { 3407 speed = LM_MEDIUM_SPEED_10MBPS; 3408 } 3409 else if(val == 1) 3410 { 3411 speed = LM_MEDIUM_SPEED_100MBPS; 3412 } 3413 else if(val == 2 || val == 13) 3414 { 3415 speed = LM_MEDIUM_SPEED_1000MBPS; 3416 } 3417 else if(val == 3) 3418 { 3419 speed = LM_MEDIUM_SPEED_2500MBPS; 3420 } 3421 else 3422 { 3423 DbgBreakMsg("unknown link speed status.\n"); 3424 } 3425 } 3426 else 3427 { 3428 /* get forced duplex mode. */ 3429 if(val & 0x100) 3430 { 3431 duplex = LM_MEDIUM_FULL_DUPLEX; 3432 } 3433 else 3434 { 3435 duplex = LM_MEDIUM_HALF_DUPLEX; 3436 } 3437 3438 /* get forced speed. */ 3439 if(val & 0x20) 3440 { 3441 speed = LM_MEDIUM_SPEED_2500MBPS; 3442 } 3443 else if((val & 0x2040) == 0) 3444 { 3445 speed = LM_MEDIUM_SPEED_10MBPS; 3446 } 3447 else if((val & 0x2040) == 0x2000) 3448 { 3449 speed = LM_MEDIUM_SPEED_100MBPS; 3450 } 3451 else if((val & 0x2040) == 0x40) 3452 { 3453 speed = LM_MEDIUM_SPEED_1000MBPS; 3454 } 3455 else 3456 { 3457 DbgBreakMsg("unknown speed.\n"); 3458 } 3459 } 3460 3461 *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex; 3462 3463 return link; 3464 } /* get_5709_serdes_link */ 3465 3466 3467 3468 /******************************************************************************* 3469 * Description: 3470 * 3471 * Return: 3472 ******************************************************************************/ 3473 STATIC lm_status_t 3474 get_5706_serdes_link( 3475 lm_device_t *pdev, 3476 lm_medium_t *medium) 3477 { 3478 lm_status_t link; 3479 u32_t phy_status; 3480 u32_t remote_adv; 3481 u32_t local_adv; 3482 u32_t phy_ctrl; 3483 u32_t val; 3484 3485 *medium = LM_MEDIUM_TYPE_FIBER; 3486 3487 phy_status = mii_get_serdes_link_status(pdev); 3488 3489 if(phy_status & PHY_STATUS_LINK_PASS) 3490 { 3491 DbgMessage(pdev, INFORM, "serdes link up.\n"); 3492 3493 link = LM_STATUS_LINK_ACTIVE; 3494 *medium |= LM_MEDIUM_SPEED_1000MBPS; 3495 3496 /* Determine duplex mode. Link is present also means 3497 * autoneg is done. */ 3498 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl); 3499 if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE) 3500 { 3501 (void) lm_mread( 3502 pdev, 3503 pdev->params.phy_addr, 3504 PHY_AN_AD_REG, 3505 &local_adv); 3506 (void) lm_mread( 3507 pdev, 3508 pdev->params.phy_addr, 3509 PHY_LINK_PARTNER_ABILITY_REG, 3510 &remote_adv); 3511 3512 val = local_adv & remote_adv; 3513 if(val & PHY_AN_AD_1000X_FULL_DUPLEX) 3514 { 3515 DbgMessage(pdev, INFORM, "serdes autoneg to full duplex.\n"); 3516 3517 *medium |= LM_MEDIUM_FULL_DUPLEX; 3518 } 3519 else 3520 { 3521 DbgMessage(pdev, INFORM, "serdes autoneg to half duplex.\n"); 3522 3523 *medium |= LM_MEDIUM_HALF_DUPLEX; 3524 } 3525 3526 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_NONE; 3527 } 3528 else 3529 { 3530 if(phy_ctrl & PHY_CTRL_FULL_DUPLEX_MODE) 3531 { 3532 DbgMessage(pdev, INFORM, "serdes forced to full duplex.\n"); 3533 3534 *medium |= LM_MEDIUM_FULL_DUPLEX; 3535 } 3536 else 3537 { 3538 DbgMessage(pdev, INFORM, "serdes forced to half duplex.\n"); 3539 3540 *medium |= LM_MEDIUM_HALF_DUPLEX; 3541 } 3542 3543 if(pdev->vars.serdes_fallback_select) 3544 { 3545 pdev->vars.serdes_fallback_status = SERDES_FALLBACK_1G; 3546 } 3547 } 3548 } 3549 else 3550 { 3551 DbgMessage(pdev, INFORM, "serdes link down.\n"); 3552 3553 /* This routine is called only when the link is down. */ 3554 link = serdes_fallback(pdev, pdev->vars.serdes_fallback_select); 3555 } 3556 3557 /* cq#30504 - restore the tx driver current so we can get link. */ 3558 if(pdev->vars.bcm5706s_tx_drv_cur) 3559 { 3560 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x17, 0x0f03); 3561 3562 (void) lm_mwrite( 3563 pdev, 3564 pdev->params.phy_addr, 3565 0x15, 3566 pdev->vars.bcm5706s_tx_drv_cur); 3567 3568 pdev->vars.bcm5706s_tx_drv_cur = 0; 3569 } 3570 3571 pdev->vars.cable_is_attached = TRUE; 3572 3573 if(link == LM_STATUS_LINK_DOWN) 3574 { 3575 (void) lm_mwrite(pdev, pdev->params.phy_addr, 0x1c, 0x7c00); 3576 (void) lm_mread(pdev, pdev->params.phy_addr, 0x1c, &val); 3577 if(!(val & 0x10)) 3578 { 3579 pdev->vars.cable_is_attached = FALSE; 3580 } 3581 } 3582 3583 return link; 3584 } /* get_5706_serdes_link */ 3585 3586 3587 3588 /******************************************************************************* 3589 * Description: 3590 * 3591 * Return: 3592 ******************************************************************************/ 3593 STATIC lm_status_t 3594 get_remote_phy_link( 3595 lm_device_t *pdev, 3596 lm_medium_t *medium) 3597 { 3598 u32_t remote_phy_link; 3599 lm_medium_t duplex; 3600 lm_medium_t speed; 3601 lm_status_t link; 3602 3603 DbgBreakIf(pdev->params.enable_remote_phy == FALSE); 3604 3605 *medium = LM_MEDIUM_TYPE_FIBER | 3606 LM_MEDIUM_SPEED_UNKNOWN | 3607 LM_MEDIUM_FULL_DUPLEX; 3608 3609 pdev->vars.cable_is_attached = FALSE; 3610 3611 REG_RD_IND( 3612 pdev, 3613 pdev->hw_info.shmem_base + 3614 OFFSETOF(shmem_region_t, drv_fw_mb.link_status), 3615 &remote_phy_link); 3616 3617 pdev->vars.rphy_status = 0; 3618 3619 if((remote_phy_link & NETLINK_GET_LINK_STATUS_SERDES_LINK) == 0) 3620 { 3621 pdev->vars.rphy_status |= RPHY_STATUS_ACTIVE; 3622 } 3623 3624 if((remote_phy_link & NETLINK_GET_LINK_STATUS_NO_MEDIA_DETECTED) == 0) 3625 { 3626 pdev->vars.rphy_status |= RPHY_STATUS_MODULE_PRESENT; 3627 } 3628 3629 if((remote_phy_link & NETLINK_GET_LINK_STATUS_LINK_UP) == 0) 3630 { 3631 return LM_STATUS_LINK_DOWN; 3632 } 3633 3634 link = LM_STATUS_LINK_ACTIVE; 3635 pdev->vars.cable_is_attached = TRUE; 3636 3637 switch(remote_phy_link & NETLINK_GET_LINK_STATUS_SPEED_MASK) 3638 { 3639 case NETLINK_GET_LINK_STATUS_10HALF: 3640 speed = LM_MEDIUM_SPEED_10MBPS; 3641 duplex = LM_MEDIUM_HALF_DUPLEX; 3642 break; 3643 3644 case NETLINK_GET_LINK_STATUS_10FULL: 3645 speed = LM_MEDIUM_SPEED_10MBPS; 3646 duplex = LM_MEDIUM_FULL_DUPLEX; 3647 break; 3648 3649 case NETLINK_GET_LINK_STATUS_100HALF: 3650 speed = LM_MEDIUM_SPEED_100MBPS; 3651 duplex = LM_MEDIUM_HALF_DUPLEX; 3652 break; 3653 3654 case NETLINK_GET_LINK_STATUS_100FULL: 3655 speed = LM_MEDIUM_SPEED_100MBPS; 3656 duplex = LM_MEDIUM_FULL_DUPLEX; 3657 break; 3658 3659 case NETLINK_GET_LINK_STATUS_1000HALF: 3660 speed = LM_MEDIUM_SPEED_1000MBPS; 3661 duplex = LM_MEDIUM_HALF_DUPLEX; 3662 break; 3663 3664 case NETLINK_GET_LINK_STATUS_1000FULL: 3665 speed = LM_MEDIUM_SPEED_1000MBPS; 3666 duplex = LM_MEDIUM_FULL_DUPLEX; 3667 break; 3668 3669 case NETLINK_GET_LINK_STATUS_2500HALF: 3670 speed = LM_MEDIUM_SPEED_2500MBPS; 3671 duplex = LM_MEDIUM_HALF_DUPLEX; 3672 break; 3673 3674 case NETLINK_GET_LINK_STATUS_2500FULL: 3675 speed = LM_MEDIUM_SPEED_2500MBPS; 3676 duplex = LM_MEDIUM_FULL_DUPLEX; 3677 break; 3678 3679 default: 3680 speed = LM_MEDIUM_SPEED_UNKNOWN; 3681 duplex = LM_MEDIUM_FULL_DUPLEX; 3682 break; 3683 } 3684 3685 *medium = LM_MEDIUM_TYPE_FIBER | speed | duplex; 3686 3687 return link; 3688 } /* get_remote_phy_link */ 3689 3690 3691 3692 /******************************************************************************* 3693 * Description: 3694 * 3695 * Return: 3696 ******************************************************************************/ 3697 lm_status_t 3698 lm_init_mac_link( 3699 lm_device_t *pdev) 3700 { 3701 lm_status_t lm_status; 3702 lm_medium_t medium; 3703 lm_status_t link; 3704 u32_t val, phy_ctrl, phy_status; 3705 3706 if(pdev->params.enable_remote_phy) 3707 { 3708 link = get_remote_phy_link(pdev, &medium); 3709 init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap); 3710 3711 return LM_STATUS_SUCCESS; 3712 } 3713 3714 switch(GET_MEDIUM_TYPE(pdev->vars.medium)) 3715 { 3716 case LM_MEDIUM_TYPE_UTP: 3717 link = get_copper_phy_link(pdev, &medium); 3718 init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap); 3719 3720 lm_status = LM_STATUS_SUCCESS; 3721 break; 3722 3723 case LM_MEDIUM_TYPE_FIBER: 3724 DbgBreakIf(CHIP_NUM(pdev) != CHIP_NUM_5706 && 3725 CHIP_NUM(pdev) != CHIP_NUM_5708 && 3726 CHIP_NUM(pdev) != CHIP_NUM_5709); 3727 3728 if(CHIP_NUM(pdev) == CHIP_NUM_5706) 3729 { 3730 link = get_5706_serdes_link(pdev, &medium); 3731 } 3732 else if(CHIP_NUM(pdev) == CHIP_NUM_5708) 3733 { 3734 link = get_5708_serdes_link(pdev, &medium); 3735 } 3736 else 3737 { 3738 link = get_5709_serdes_link(pdev, &medium); 3739 } 3740 3741 init_mac_link(pdev, link, medium, pdev->params.flow_ctrl_cap); 3742 3743 lm_status = LM_STATUS_SUCCESS; 3744 break; 3745 3746 case LM_MEDIUM_TYPE_PHY_LOOPBACK: 3747 case LM_MEDIUM_TYPE_MAC_LOOPBACK: 3748 lm_status = init_loopback_mac_link( 3749 pdev, 3750 pdev->params.req_medium, 3751 pdev->params.flow_ctrl_cap); 3752 break; 3753 3754 case LM_MEDIUM_TYPE_NULL: 3755 init_mac_link( 3756 pdev, 3757 LM_STATUS_LINK_ACTIVE, 3758 LM_MEDIUM_TYPE_NULL | 3759 LM_MEDIUM_SPEED_1000MBPS | 3760 LM_MEDIUM_FULL_DUPLEX, 3761 pdev->params.flow_ctrl_cap); 3762 3763 lm_status = LM_STATUS_SUCCESS; 3764 break; 3765 3766 default: 3767 lm_status = LM_STATUS_UNKNOWN_MEDIUM; 3768 break; 3769 } 3770 3771 /* Report the currnet link status to the management firmware. */ 3772 val = 0; 3773 3774 if(pdev->vars.link_status == LM_STATUS_LINK_ACTIVE) 3775 { 3776 val |= NETLINK_GET_LINK_STATUS_LINK_UP; 3777 3778 if(lm_get_medium(pdev) == LM_MEDIUM_TYPE_FIBER) 3779 { 3780 val |= NETLINK_GET_LINK_STATUS_SERDES_LINK; 3781 } 3782 } 3783 3784 switch(GET_MEDIUM_SPEED(pdev->vars.medium)) 3785 { 3786 case LM_MEDIUM_SPEED_10MBPS: 3787 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX) 3788 { 3789 val |= NETLINK_GET_LINK_STATUS_10FULL; 3790 } 3791 else 3792 { 3793 val |= NETLINK_GET_LINK_STATUS_10HALF; 3794 } 3795 break; 3796 3797 case LM_MEDIUM_SPEED_100MBPS: 3798 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX) 3799 { 3800 val |= NETLINK_GET_LINK_STATUS_100FULL; 3801 } 3802 else 3803 { 3804 val |= NETLINK_GET_LINK_STATUS_100HALF; 3805 } 3806 break; 3807 3808 case LM_MEDIUM_SPEED_1000MBPS: 3809 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX) 3810 { 3811 val |= NETLINK_GET_LINK_STATUS_1000FULL; 3812 } 3813 else 3814 { 3815 val |= NETLINK_GET_LINK_STATUS_1000HALF; 3816 } 3817 break; 3818 3819 case LM_MEDIUM_SPEED_2500MBPS: 3820 if(GET_MEDIUM_DUPLEX(pdev->vars.medium) == LM_MEDIUM_FULL_DUPLEX) 3821 { 3822 val |= NETLINK_GET_LINK_STATUS_2500FULL; 3823 } 3824 else 3825 { 3826 val |= NETLINK_GET_LINK_STATUS_2500HALF; 3827 } 3828 break; 3829 } 3830 3831 // read PHY_CTRL_REG to see if auto-negotiation is enabled/completed 3832 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_CTRL_REG, &phy_ctrl); 3833 3834 if(phy_ctrl & PHY_CTRL_AUTO_NEG_ENABLE) 3835 { 3836 val |= NETLINK_GET_LINK_STATUS_AN_ENABLED; 3837 (void) lm_mread(pdev, pdev->params.phy_addr, PHY_STATUS_REG, &phy_status); 3838 if(phy_status & PHY_STATUS_AUTO_NEG_COMPLETE) 3839 { 3840 val |= NETLINK_GET_LINK_STATUS_AN_COMPLETE; 3841 // Following bits are valid for copper (i.e. SerDes flag == 0) 3842 if ((val & NETLINK_GET_LINK_STATUS_SERDES_LINK) == 0) 3843 { 3844 u32_t remote_phy_ad; 3845 (void) lm_mread( 3846 pdev, 3847 pdev->params.phy_addr, 3848 PHY_1000BASET_STATUS_REG, 3849 &remote_phy_ad); 3850 3851 if(remote_phy_ad & PHY_LINK_PARTNER_1000BASET_FULL) 3852 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_1000FULL; 3853 if(remote_phy_ad & PHY_LINK_PARTNER_1000BASET_HALF) 3854 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_1000HALF; 3855 3856 (void) lm_mread( 3857 pdev, 3858 pdev->params.phy_addr, 3859 PHY_LINK_PARTNER_ABILITY_REG, 3860 &remote_phy_ad); 3861 if (remote_phy_ad & PHY_LINK_PARTNER_10BASET_HALF) 3862 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_10HALF; 3863 if (remote_phy_ad & PHY_LINK_PARTNER_10BASET_FULL) 3864 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_10FULL; 3865 if (remote_phy_ad & PHY_LINK_PARTNER_100BASETX_HALF) 3866 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_100HALF; 3867 if (remote_phy_ad & PHY_LINK_PARTNER_100BASETX_FULL) 3868 val |= NETLINK_GET_LINK_STATUS_PARTNER_AD_100FULL; 3869 if (remote_phy_ad & PHY_LINK_PARTNER_PAUSE_CAPABLE) 3870 val |= NETLINK_GET_LINK_STATUS_PARTNER_SYM_PAUSE_CAP; 3871 if (remote_phy_ad & PHY_LINK_PARTNER_ASYM_PAUSE) 3872 val |= NETLINK_GET_LINK_STATUS_PARTNER_ASYM_PAUSE_CAP; 3873 // Read PHY_AN_EXPANSION_REG to see if Link partner support auto 3874 // negotiation 3875 (void) lm_mread( 3876 pdev, 3877 pdev->params.phy_addr, 3878 PHY_AN_EXPANSION_REG, 3879 &remote_phy_ad); 3880 // If Link partner does not support auto negotiation, we assume 3881 // parallel detection was used to get link. 3882 if ((remote_phy_ad & PHY_LINK_PARTNER_AUTONEG_ABILITY) == 0) 3883 val |= NETLINK_GET_LINK_STATUS_PARALLEL_DET; 3884 } 3885 } 3886 } 3887 if(pdev->vars.flow_control & LM_FLOW_CONTROL_TRANSMIT_PAUSE) 3888 { 3889 val |= NETLINK_GET_LINK_STATUS_TX_FC_ENABLED; 3890 } 3891 if(pdev->vars.flow_control & LM_FLOW_CONTROL_RECEIVE_PAUSE) 3892 { 3893 val |= NETLINK_GET_LINK_STATUS_RX_FC_ENABLED; 3894 } 3895 // Following bits are not supported yet 3896 // NETLINK_GET_LINK_STATUS_NO_MEDIA_DETECTED; 3897 // NETLINK_GET_LINK_STATUS_CABLESENSE; 3898 // NETLINK_GET_LINK_STATUS_SW_TIMER_EVENT; 3899 REG_WR_IND( 3900 pdev, 3901 pdev->hw_info.shmem_base + 3902 OFFSETOF(shmem_region_t, drv_fw_mb.link_status), 3903 val); 3904 3905 return lm_status; 3906 } /* lm_init_mac_link */ 3907 3908 3909 3910 /******************************************************************************* 3911 * Description: 3912 * 3913 * Return: 3914 ******************************************************************************/ 3915 void 3916 lm_service_phy_int( 3917 lm_device_t *pdev, 3918 u32_t force_service_int) 3919 { 3920 u32_t deasserted_attns; 3921 u32_t asserted_attns; 3922 u32_t link_chng; 3923 u32_t val; 3924 3925 link_chng = FALSE; 3926 3927 if(pdev->params.link_chng_mode == LINK_CHNG_MODE_USE_STATUS_REG) 3928 { 3929 REG_RD(pdev, emac.emac_status, &val); 3930 if(pdev->params.phy_int_mode == PHY_INT_MODE_MI_INTERRUPT) 3931 { 3932 if(val & EMAC_STATUS_MI_INT) 3933 { 3934 link_chng = TRUE; 3935 } 3936 } 3937 else if(val & EMAC_STATUS_LINK_CHANGE) 3938 { 3939 link_chng = TRUE; 3940 } 3941 } 3942 else 3943 { 3944 link_chng = FALSE; 3945 3946 GET_ATTN_CHNG_BITS(pdev, &asserted_attns, &deasserted_attns); 3947 3948 asserted_attns &= STATUS_ATTN_BITS_LINK_STATE; 3949 deasserted_attns &= STATUS_ATTN_BITS_LINK_STATE; 3950 3951 if(asserted_attns) 3952 { 3953 link_chng = TRUE; 3954 3955 REG_WR( 3956 pdev, 3957 pci_config.pcicfg_status_bit_set_cmd, 3958 asserted_attns); 3959 } 3960 else if(deasserted_attns) 3961 { 3962 link_chng = TRUE; 3963 3964 REG_WR( 3965 pdev, 3966 pci_config.pcicfg_status_bit_clear_cmd, 3967 deasserted_attns); 3968 } 3969 } 3970 3971 if(link_chng || force_service_int || pdev->params.enable_remote_phy) 3972 { 3973 (void) lm_init_mac_link(pdev); 3974 3975 mm_indicate_link(pdev, pdev->vars.link_status, pdev->vars.medium); 3976 } 3977 } /* lm_service_phy_int */ 3978 3979 3980 3981 /******************************************************************************* 3982 * Description: 3983 * 3984 * Return: 3985 ******************************************************************************/ 3986 lm_medium_t 3987 lm_get_medium( 3988 lm_device_t *pdev) 3989 { 3990 u32_t decode; 3991 u32_t val; 3992 3993 if(CHIP_REV(pdev) == CHIP_REV_IKOS) 3994 { 3995 return LM_MEDIUM_TYPE_NULL; 3996 } 3997 3998 if(CHIP_REV(pdev) == CHIP_REV_FPGA) 3999 { 4000 return LM_MEDIUM_TYPE_UTP; 4001 } 4002 4003 if(CHIP_NUM(pdev) == CHIP_NUM_5706 || CHIP_NUM(pdev) == CHIP_NUM_5708) 4004 { 4005 if(CHIP_BOND_ID(pdev) & CHIP_BOND_ID_SERDES_BIT) 4006 { 4007 return LM_MEDIUM_TYPE_FIBER; 4008 } 4009 4010 return LM_MEDIUM_TYPE_UTP; 4011 } 4012 4013 if(CHIP_NUM(pdev) == CHIP_NUM_5709) 4014 { 4015 REG_RD(pdev, misc.misc_dual_media_ctrl, &val); 4016 4017 if((val & MISC_DUAL_MEDIA_CTRL_BOND_ID) == 4018 MISC_DUAL_MEDIA_CTRL_BOND_ID_C) 4019 { 4020 return LM_MEDIUM_TYPE_UTP; 4021 } 4022 4023 if((val & MISC_DUAL_MEDIA_CTRL_BOND_ID) == 4024 MISC_DUAL_MEDIA_CTRL_BOND_ID_S) 4025 { 4026 return LM_MEDIUM_TYPE_FIBER; 4027 } 4028 4029 /* mac to phy/serdes decode. 4030 * swap strap mac0 mac1 4031 * ==== ===== ==== ==== 4032 * 0 000 phy0 phy1 4033 * 0 001 phy0 ser0 4034 * 0 010 phy0 ser1 4035 * 0 110 ser0 phy0 4036 * 0 101 ser0 phy1 4037 * 0 100 ser0 ser1 4038 * 4039 * 1 000 phy1 phy0 4040 * 1 001 phy1 ser1 4041 * 1 010 phy1 ser0 4042 * 1 110 ser1 phy1 4043 * 1 101 ser1 phy0 4044 * 1 100 ser1 ser0 */ 4045 if(val & MISC_DUAL_MEDIA_CTRL_STRAP_OVERRIDE) 4046 { 4047 decode = (val & MISC_DUAL_MEDIA_CTRL_PHY_CTRL) >> 21; 4048 4049 if(val & MISC_DUAL_MEDIA_CTRL_PORT_SWAP) 4050 { 4051 decode |= 0x8; 4052 } 4053 } 4054 else 4055 { 4056 decode = (val & MISC_DUAL_MEDIA_CTRL_PHY_CTRL_STRAP) >> 8; 4057 4058 if(val & MISC_DUAL_MEDIA_CTRL_PORT_SWAP_PIN) 4059 { 4060 decode |= 0x8; 4061 } 4062 } 4063 4064 decode |= pdev->hw_info.mac_id << 4; 4065 4066 /* mac:4, swap:3, strap:2-0. */ 4067 switch(decode) 4068 { 4069 case 0x00: /* 00000 - mac0, phy0 */ 4070 case 0x01: /* 00001 - mac0, phy0 */ 4071 case 0x02: /* 00010 - mac0, phy0 */ 4072 case 0x08: /* 01000 - mac0, phy1 */ 4073 case 0x09: /* 01001 - mac0, phy1 */ 4074 case 0x0a: /* 01010 - mac0, phy1 */ 4075 case 0x10: /* 10000 - mac1, phy1 */ 4076 case 0x15: /* 10101 - mac1, phy1 */ 4077 case 0x16: /* 10110 - mac1, phy0 */ 4078 case 0x18: /* 11000 - mac1, phy0 */ 4079 case 0x1d: /* 11101 - mac1, phy0 */ 4080 case 0x1e: /* 11110 - mac1, phy1 */ 4081 return LM_MEDIUM_TYPE_UTP; 4082 4083 case 0x04: /* 00100 - mac0, ser0 */ 4084 case 0x05: /* 00101 - mac0, ser0 */ 4085 case 0x06: /* 00110 - mac0, ser0 */ 4086 case 0x0c: /* 01100 - mac0, ser1 */ 4087 case 0x0d: /* 01101 - mac0, ser1 */ 4088 case 0x0e: /* 01110 - mac0, ser1 */ 4089 case 0x11: /* 10001 - mac1, ser0 */ 4090 case 0x12: /* 10010 - mac1, ser1 */ 4091 case 0x14: /* 10100 - mac1, ser1 */ 4092 case 0x19: /* 11001 - mac1, ser1 */ 4093 case 0x1a: /* 11010 - mac1, ser0 */ 4094 case 0x1c: /* 11100 - mac1, ser0 */ 4095 return LM_MEDIUM_TYPE_FIBER; 4096 } 4097 } 4098 4099 return LM_MEDIUM_TYPE_NULL; 4100 } /* lm_get_medium */ 4101