Commit 9dda173667207fe59d380e522d318c144dc032f7
Committed by
Jeff Kirsher
1 parent
7e7eb43463
Exists in
master
and in
7 other branches
ixgbe: update PHY code to support 100Mbps as well as 1G/10G
This change updates the PHY setup code to support 100Mbps capable PHYs as well as 10G and 1Gbps. Signed-off-by: Emil Tantilov <emil.s.tantilov@intel.com> Tested-by: Stephen Ko <stephen.s.ko@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Showing 4 changed files with 245 additions and 99 deletions Side-by-side Diff
drivers/net/ixgbe/ixgbe_82598.c
drivers/net/ixgbe/ixgbe_phy.c
... | ... | @@ -402,49 +402,89 @@ |
402 | 402 | **/ |
403 | 403 | s32 ixgbe_setup_phy_link_generic(struct ixgbe_hw *hw) |
404 | 404 | { |
405 | - s32 status = IXGBE_NOT_IMPLEMENTED; | |
405 | + s32 status = 0; | |
406 | 406 | u32 time_out; |
407 | 407 | u32 max_time_out = 10; |
408 | - u16 autoneg_reg; | |
408 | + u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; | |
409 | + bool autoneg = false; | |
410 | + ixgbe_link_speed speed; | |
409 | 411 | |
410 | - /* | |
411 | - * Set advertisement settings in PHY based on autoneg_advertised | |
412 | - * settings. If autoneg_advertised = 0, then advertise default values | |
413 | - * tnx devices cannot be "forced" to a autoneg 10G and fail. But can | |
414 | - * for a 1G. | |
415 | - */ | |
416 | - hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, &autoneg_reg); | |
412 | + ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); | |
417 | 413 | |
418 | - if (hw->phy.autoneg_advertised == IXGBE_LINK_SPEED_1GB_FULL) | |
414 | + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { | |
415 | + /* Set or unset auto-negotiation 10G advertisement */ | |
416 | + hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, | |
417 | + MDIO_MMD_AN, | |
418 | + &autoneg_reg); | |
419 | + | |
419 | 420 | autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; |
420 | - else | |
421 | - autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; | |
421 | + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) | |
422 | + autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; | |
422 | 423 | |
423 | - hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, MDIO_MMD_AN, autoneg_reg); | |
424 | + hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, | |
425 | + MDIO_MMD_AN, | |
426 | + autoneg_reg); | |
427 | + } | |
424 | 428 | |
429 | + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { | |
430 | + /* Set or unset auto-negotiation 1G advertisement */ | |
431 | + hw->phy.ops.read_reg(hw, | |
432 | + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, | |
433 | + MDIO_MMD_AN, | |
434 | + &autoneg_reg); | |
435 | + | |
436 | + autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE; | |
437 | + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) | |
438 | + autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE; | |
439 | + | |
440 | + hw->phy.ops.write_reg(hw, | |
441 | + IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG, | |
442 | + MDIO_MMD_AN, | |
443 | + autoneg_reg); | |
444 | + } | |
445 | + | |
446 | + if (speed & IXGBE_LINK_SPEED_100_FULL) { | |
447 | + /* Set or unset auto-negotiation 100M advertisement */ | |
448 | + hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, | |
449 | + MDIO_MMD_AN, | |
450 | + &autoneg_reg); | |
451 | + | |
452 | + autoneg_reg &= ~ADVERTISE_100FULL; | |
453 | + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) | |
454 | + autoneg_reg |= ADVERTISE_100FULL; | |
455 | + | |
456 | + hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, | |
457 | + MDIO_MMD_AN, | |
458 | + autoneg_reg); | |
459 | + } | |
460 | + | |
425 | 461 | /* Restart PHY autonegotiation and wait for completion */ |
426 | - hw->phy.ops.read_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, &autoneg_reg); | |
462 | + hw->phy.ops.read_reg(hw, MDIO_CTRL1, | |
463 | + MDIO_MMD_AN, &autoneg_reg); | |
427 | 464 | |
428 | 465 | autoneg_reg |= MDIO_AN_CTRL1_RESTART; |
429 | 466 | |
430 | - hw->phy.ops.write_reg(hw, MDIO_CTRL1, MDIO_MMD_AN, autoneg_reg); | |
467 | + hw->phy.ops.write_reg(hw, MDIO_CTRL1, | |
468 | + MDIO_MMD_AN, autoneg_reg); | |
431 | 469 | |
432 | 470 | /* Wait for autonegotiation to finish */ |
433 | 471 | for (time_out = 0; time_out < max_time_out; time_out++) { |
434 | 472 | udelay(10); |
435 | 473 | /* Restart PHY autonegotiation and wait for completion */ |
436 | - status = hw->phy.ops.read_reg(hw, MDIO_STAT1, MDIO_MMD_AN, | |
437 | - &autoneg_reg); | |
474 | + status = hw->phy.ops.read_reg(hw, MDIO_STAT1, | |
475 | + MDIO_MMD_AN, | |
476 | + &autoneg_reg); | |
438 | 477 | |
439 | 478 | autoneg_reg &= MDIO_AN_STAT1_COMPLETE; |
440 | 479 | if (autoneg_reg == MDIO_AN_STAT1_COMPLETE) { |
441 | - status = 0; | |
442 | 480 | break; |
443 | 481 | } |
444 | 482 | } |
445 | 483 | |
446 | - if (time_out == max_time_out) | |
484 | + if (time_out == max_time_out) { | |
447 | 485 | status = IXGBE_ERR_LINK_SETUP; |
486 | + hw_dbg(hw, "ixgbe_setup_phy_link_generic: time out"); | |
487 | + } | |
448 | 488 | |
449 | 489 | return status; |
450 | 490 | } |
... | ... | @@ -473,6 +513,9 @@ |
473 | 513 | if (speed & IXGBE_LINK_SPEED_1GB_FULL) |
474 | 514 | hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_1GB_FULL; |
475 | 515 | |
516 | + if (speed & IXGBE_LINK_SPEED_100_FULL) | |
517 | + hw->phy.autoneg_advertised |= IXGBE_LINK_SPEED_100_FULL; | |
518 | + | |
476 | 519 | /* Setup link based on the new speed settings */ |
477 | 520 | hw->phy.ops.setup_link(hw); |
478 | 521 | |
... | ... | @@ -513,6 +556,180 @@ |
513 | 556 | } |
514 | 557 | |
515 | 558 | /** |
559 | + * ixgbe_check_phy_link_tnx - Determine link and speed status | |
560 | + * @hw: pointer to hardware structure | |
561 | + * | |
562 | + * Reads the VS1 register to determine if link is up and the current speed for | |
563 | + * the PHY. | |
564 | + **/ | |
565 | +s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, | |
566 | + bool *link_up) | |
567 | +{ | |
568 | + s32 status = 0; | |
569 | + u32 time_out; | |
570 | + u32 max_time_out = 10; | |
571 | + u16 phy_link = 0; | |
572 | + u16 phy_speed = 0; | |
573 | + u16 phy_data = 0; | |
574 | + | |
575 | + /* Initialize speed and link to default case */ | |
576 | + *link_up = false; | |
577 | + *speed = IXGBE_LINK_SPEED_10GB_FULL; | |
578 | + | |
579 | + /* | |
580 | + * Check current speed and link status of the PHY register. | |
581 | + * This is a vendor specific register and may have to | |
582 | + * be changed for other copper PHYs. | |
583 | + */ | |
584 | + for (time_out = 0; time_out < max_time_out; time_out++) { | |
585 | + udelay(10); | |
586 | + status = hw->phy.ops.read_reg(hw, | |
587 | + MDIO_STAT1, | |
588 | + MDIO_MMD_VEND1, | |
589 | + &phy_data); | |
590 | + phy_link = phy_data & | |
591 | + IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; | |
592 | + phy_speed = phy_data & | |
593 | + IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS; | |
594 | + if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) { | |
595 | + *link_up = true; | |
596 | + if (phy_speed == | |
597 | + IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS) | |
598 | + *speed = IXGBE_LINK_SPEED_1GB_FULL; | |
599 | + break; | |
600 | + } | |
601 | + } | |
602 | + | |
603 | + return status; | |
604 | +} | |
605 | + | |
606 | +/** | |
607 | + * ixgbe_setup_phy_link_tnx - Set and restart autoneg | |
608 | + * @hw: pointer to hardware structure | |
609 | + * | |
610 | + * Restart autonegotiation and PHY and waits for completion. | |
611 | + **/ | |
612 | +s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw) | |
613 | +{ | |
614 | + s32 status = 0; | |
615 | + u32 time_out; | |
616 | + u32 max_time_out = 10; | |
617 | + u16 autoneg_reg = IXGBE_MII_AUTONEG_REG; | |
618 | + bool autoneg = false; | |
619 | + ixgbe_link_speed speed; | |
620 | + | |
621 | + ixgbe_get_copper_link_capabilities_generic(hw, &speed, &autoneg); | |
622 | + | |
623 | + if (speed & IXGBE_LINK_SPEED_10GB_FULL) { | |
624 | + /* Set or unset auto-negotiation 10G advertisement */ | |
625 | + hw->phy.ops.read_reg(hw, MDIO_AN_10GBT_CTRL, | |
626 | + MDIO_MMD_AN, | |
627 | + &autoneg_reg); | |
628 | + | |
629 | + autoneg_reg &= ~MDIO_AN_10GBT_CTRL_ADV10G; | |
630 | + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL) | |
631 | + autoneg_reg |= MDIO_AN_10GBT_CTRL_ADV10G; | |
632 | + | |
633 | + hw->phy.ops.write_reg(hw, MDIO_AN_10GBT_CTRL, | |
634 | + MDIO_MMD_AN, | |
635 | + autoneg_reg); | |
636 | + } | |
637 | + | |
638 | + if (speed & IXGBE_LINK_SPEED_1GB_FULL) { | |
639 | + /* Set or unset auto-negotiation 1G advertisement */ | |
640 | + hw->phy.ops.read_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, | |
641 | + MDIO_MMD_AN, | |
642 | + &autoneg_reg); | |
643 | + | |
644 | + autoneg_reg &= ~IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; | |
645 | + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) | |
646 | + autoneg_reg |= IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX; | |
647 | + | |
648 | + hw->phy.ops.write_reg(hw, IXGBE_MII_AUTONEG_XNP_TX_REG, | |
649 | + MDIO_MMD_AN, | |
650 | + autoneg_reg); | |
651 | + } | |
652 | + | |
653 | + if (speed & IXGBE_LINK_SPEED_100_FULL) { | |
654 | + /* Set or unset auto-negotiation 100M advertisement */ | |
655 | + hw->phy.ops.read_reg(hw, MDIO_AN_ADVERTISE, | |
656 | + MDIO_MMD_AN, | |
657 | + &autoneg_reg); | |
658 | + | |
659 | + autoneg_reg &= ~ADVERTISE_100FULL; | |
660 | + if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL) | |
661 | + autoneg_reg |= ADVERTISE_100FULL; | |
662 | + | |
663 | + hw->phy.ops.write_reg(hw, MDIO_AN_ADVERTISE, | |
664 | + MDIO_MMD_AN, | |
665 | + autoneg_reg); | |
666 | + } | |
667 | + | |
668 | + /* Restart PHY autonegotiation and wait for completion */ | |
669 | + hw->phy.ops.read_reg(hw, MDIO_CTRL1, | |
670 | + MDIO_MMD_AN, &autoneg_reg); | |
671 | + | |
672 | + autoneg_reg |= MDIO_AN_CTRL1_RESTART; | |
673 | + | |
674 | + hw->phy.ops.write_reg(hw, MDIO_CTRL1, | |
675 | + MDIO_MMD_AN, autoneg_reg); | |
676 | + | |
677 | + /* Wait for autonegotiation to finish */ | |
678 | + for (time_out = 0; time_out < max_time_out; time_out++) { | |
679 | + udelay(10); | |
680 | + /* Restart PHY autonegotiation and wait for completion */ | |
681 | + status = hw->phy.ops.read_reg(hw, MDIO_STAT1, | |
682 | + MDIO_MMD_AN, | |
683 | + &autoneg_reg); | |
684 | + | |
685 | + autoneg_reg &= MDIO_AN_STAT1_COMPLETE; | |
686 | + if (autoneg_reg == MDIO_AN_STAT1_COMPLETE) | |
687 | + break; | |
688 | + } | |
689 | + | |
690 | + if (time_out == max_time_out) { | |
691 | + status = IXGBE_ERR_LINK_SETUP; | |
692 | + hw_dbg(hw, "ixgbe_setup_phy_link_tnx: time out"); | |
693 | + } | |
694 | + | |
695 | + return status; | |
696 | +} | |
697 | + | |
698 | +/** | |
699 | + * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version | |
700 | + * @hw: pointer to hardware structure | |
701 | + * @firmware_version: pointer to the PHY Firmware Version | |
702 | + **/ | |
703 | +s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, | |
704 | + u16 *firmware_version) | |
705 | +{ | |
706 | + s32 status = 0; | |
707 | + | |
708 | + status = hw->phy.ops.read_reg(hw, TNX_FW_REV, | |
709 | + MDIO_MMD_VEND1, | |
710 | + firmware_version); | |
711 | + | |
712 | + return status; | |
713 | +} | |
714 | + | |
715 | +/** | |
716 | + * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version | |
717 | + * @hw: pointer to hardware structure | |
718 | + * @firmware_version: pointer to the PHY Firmware Version | |
719 | + **/ | |
720 | +s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, | |
721 | + u16 *firmware_version) | |
722 | +{ | |
723 | + s32 status = 0; | |
724 | + | |
725 | + status = hw->phy.ops.read_reg(hw, AQ_FW_REV, | |
726 | + MDIO_MMD_VEND1, | |
727 | + firmware_version); | |
728 | + | |
729 | + return status; | |
730 | +} | |
731 | + | |
732 | +/** | |
516 | 733 | * ixgbe_reset_phy_nl - Performs a PHY reset |
517 | 734 | * @hw: pointer to hardware structure |
518 | 735 | **/ |
... | ... | @@ -1474,86 +1691,6 @@ |
1474 | 1691 | |
1475 | 1692 | /* Put the i2c bus back to default state */ |
1476 | 1693 | ixgbe_i2c_stop(hw); |
1477 | -} | |
1478 | - | |
1479 | -/** | |
1480 | - * ixgbe_check_phy_link_tnx - Determine link and speed status | |
1481 | - * @hw: pointer to hardware structure | |
1482 | - * | |
1483 | - * Reads the VS1 register to determine if link is up and the current speed for | |
1484 | - * the PHY. | |
1485 | - **/ | |
1486 | -s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, ixgbe_link_speed *speed, | |
1487 | - bool *link_up) | |
1488 | -{ | |
1489 | - s32 status = 0; | |
1490 | - u32 time_out; | |
1491 | - u32 max_time_out = 10; | |
1492 | - u16 phy_link = 0; | |
1493 | - u16 phy_speed = 0; | |
1494 | - u16 phy_data = 0; | |
1495 | - | |
1496 | - /* Initialize speed and link to default case */ | |
1497 | - *link_up = false; | |
1498 | - *speed = IXGBE_LINK_SPEED_10GB_FULL; | |
1499 | - | |
1500 | - /* | |
1501 | - * Check current speed and link status of the PHY register. | |
1502 | - * This is a vendor specific register and may have to | |
1503 | - * be changed for other copper PHYs. | |
1504 | - */ | |
1505 | - for (time_out = 0; time_out < max_time_out; time_out++) { | |
1506 | - udelay(10); | |
1507 | - status = hw->phy.ops.read_reg(hw, | |
1508 | - IXGBE_MDIO_VENDOR_SPECIFIC_1_STATUS, | |
1509 | - MDIO_MMD_VEND1, | |
1510 | - &phy_data); | |
1511 | - phy_link = phy_data & | |
1512 | - IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS; | |
1513 | - phy_speed = phy_data & | |
1514 | - IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS; | |
1515 | - if (phy_link == IXGBE_MDIO_VENDOR_SPECIFIC_1_LINK_STATUS) { | |
1516 | - *link_up = true; | |
1517 | - if (phy_speed == | |
1518 | - IXGBE_MDIO_VENDOR_SPECIFIC_1_SPEED_STATUS) | |
1519 | - *speed = IXGBE_LINK_SPEED_1GB_FULL; | |
1520 | - break; | |
1521 | - } | |
1522 | - } | |
1523 | - | |
1524 | - return status; | |
1525 | -} | |
1526 | - | |
1527 | -/** | |
1528 | - * ixgbe_get_phy_firmware_version_tnx - Gets the PHY Firmware Version | |
1529 | - * @hw: pointer to hardware structure | |
1530 | - * @firmware_version: pointer to the PHY Firmware Version | |
1531 | - **/ | |
1532 | -s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, | |
1533 | - u16 *firmware_version) | |
1534 | -{ | |
1535 | - s32 status = 0; | |
1536 | - | |
1537 | - status = hw->phy.ops.read_reg(hw, TNX_FW_REV, MDIO_MMD_VEND1, | |
1538 | - firmware_version); | |
1539 | - | |
1540 | - return status; | |
1541 | -} | |
1542 | - | |
1543 | -/** | |
1544 | - * ixgbe_get_phy_firmware_version_generic - Gets the PHY Firmware Version | |
1545 | - * @hw: pointer to hardware structure | |
1546 | - * @firmware_version: pointer to the PHY Firmware Version | |
1547 | -**/ | |
1548 | -s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, | |
1549 | - u16 *firmware_version) | |
1550 | -{ | |
1551 | - s32 status = 0; | |
1552 | - | |
1553 | - status = hw->phy.ops.read_reg(hw, AQ_FW_REV, MDIO_MMD_VEND1, | |
1554 | - firmware_version); | |
1555 | - | |
1556 | - return status; | |
1557 | 1694 | } |
1558 | 1695 | |
1559 | 1696 | /** |
drivers/net/ixgbe/ixgbe_phy.h
... | ... | @@ -108,6 +108,7 @@ |
108 | 108 | s32 ixgbe_check_phy_link_tnx(struct ixgbe_hw *hw, |
109 | 109 | ixgbe_link_speed *speed, |
110 | 110 | bool *link_up); |
111 | +s32 ixgbe_setup_phy_link_tnx(struct ixgbe_hw *hw); | |
111 | 112 | s32 ixgbe_get_phy_firmware_version_tnx(struct ixgbe_hw *hw, |
112 | 113 | u16 *firmware_version); |
113 | 114 | s32 ixgbe_get_phy_firmware_version_generic(struct ixgbe_hw *hw, |
drivers/net/ixgbe/ixgbe_type.h
... | ... | @@ -1009,6 +1009,13 @@ |
1009 | 1009 | #define IXGBE_MDIO_PMA_PMD_SDA_SCL_DATA 0xC30B /* PHY_XS SDA/SCL Data Reg */ |
1010 | 1010 | #define IXGBE_MDIO_PMA_PMD_SDA_SCL_STAT 0xC30C /* PHY_XS SDA/SCL Status Reg */ |
1011 | 1011 | |
1012 | +/* MII clause 22/28 definitions */ | |
1013 | +#define IXGBE_MII_AUTONEG_VENDOR_PROVISION_1_REG 0xC400 /* 1G Provisioning 1 */ | |
1014 | +#define IXGBE_MII_AUTONEG_XNP_TX_REG 0x17 /* 1G XNP Transmit */ | |
1015 | +#define IXGBE_MII_1GBASE_T_ADVERTISE_XNP_TX 0x4000 /* full duplex, bit:14*/ | |
1016 | +#define IXGBE_MII_1GBASE_T_ADVERTISE 0x8000 /* full duplex, bit:15*/ | |
1017 | +#define IXGBE_MII_AUTONEG_REG 0x0 | |
1018 | + | |
1012 | 1019 | #define IXGBE_PHY_REVISION_MASK 0xFFFFFFF0 |
1013 | 1020 | #define IXGBE_MAX_PHY_ADDR 32 |
1014 | 1021 |