aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/cavium/thunder/thunder_bgx.c')
-rw-r--r--drivers/net/ethernet/cavium/thunder/thunder_bgx.c108
1 files changed, 96 insertions, 12 deletions
diff --git a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
index 2f85b64f01fa..1e4695270da6 100644
--- a/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
+++ b/drivers/net/ethernet/cavium/thunder/thunder_bgx.c
@@ -31,6 +31,7 @@ struct lmac {
31 u8 lmac_type; 31 u8 lmac_type;
32 u8 lane_to_sds; 32 u8 lane_to_sds;
33 bool use_training; 33 bool use_training;
34 bool autoneg;
34 bool link_up; 35 bool link_up;
35 int lmacid; /* ID within BGX */ 36 int lmacid; /* ID within BGX */
36 int lmacid_bd; /* ID on board */ 37 int lmacid_bd; /* ID on board */
@@ -461,7 +462,17 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
461 /* power down, reset autoneg, autoneg enable */ 462 /* power down, reset autoneg, autoneg enable */
462 cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MRX_CTL); 463 cfg = bgx_reg_read(bgx, lmacid, BGX_GMP_PCS_MRX_CTL);
463 cfg &= ~PCS_MRX_CTL_PWR_DN; 464 cfg &= ~PCS_MRX_CTL_PWR_DN;
464 cfg |= (PCS_MRX_CTL_RST_AN | PCS_MRX_CTL_AN_EN); 465 cfg |= PCS_MRX_CTL_RST_AN;
466 if (lmac->phydev) {
467 cfg |= PCS_MRX_CTL_AN_EN;
468 } else {
469 /* In scenarios where PHY driver is not present or it's a
470 * non-standard PHY, FW sets AN_EN to inform Linux driver
471 * to do auto-neg and link polling or not.
472 */
473 if (cfg & PCS_MRX_CTL_AN_EN)
474 lmac->autoneg = true;
475 }
465 bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg); 476 bgx_reg_write(bgx, lmacid, BGX_GMP_PCS_MRX_CTL, cfg);
466 477
467 if (lmac->lmac_type == BGX_MODE_QSGMII) { 478 if (lmac->lmac_type == BGX_MODE_QSGMII) {
@@ -472,7 +483,7 @@ static int bgx_lmac_sgmii_init(struct bgx *bgx, struct lmac *lmac)
472 return 0; 483 return 0;
473 } 484 }
474 485
475 if (lmac->lmac_type == BGX_MODE_SGMII) { 486 if ((lmac->lmac_type == BGX_MODE_SGMII) && lmac->phydev) {
476 if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS, 487 if (bgx_poll_reg(bgx, lmacid, BGX_GMP_PCS_MRX_STATUS,
477 PCS_MRX_STATUS_AN_CPT, false)) { 488 PCS_MRX_STATUS_AN_CPT, false)) {
478 dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n"); 489 dev_err(&bgx->pdev->dev, "BGX AN_CPT not completed\n");
@@ -678,12 +689,71 @@ static int bgx_xaui_check_link(struct lmac *lmac)
678 return -1; 689 return -1;
679} 690}
680 691
692static void bgx_poll_for_sgmii_link(struct lmac *lmac)
693{
694 u64 pcs_link, an_result;
695 u8 speed;
696
697 pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
698 BGX_GMP_PCS_MRX_STATUS);
699
700 /*Link state bit is sticky, read it again*/
701 if (!(pcs_link & PCS_MRX_STATUS_LINK))
702 pcs_link = bgx_reg_read(lmac->bgx, lmac->lmacid,
703 BGX_GMP_PCS_MRX_STATUS);
704
705 if (bgx_poll_reg(lmac->bgx, lmac->lmacid, BGX_GMP_PCS_MRX_STATUS,
706 PCS_MRX_STATUS_AN_CPT, false)) {
707 lmac->link_up = false;
708 lmac->last_speed = SPEED_UNKNOWN;
709 lmac->last_duplex = DUPLEX_UNKNOWN;
710 goto next_poll;
711 }
712
713 lmac->link_up = ((pcs_link & PCS_MRX_STATUS_LINK) != 0) ? true : false;
714 an_result = bgx_reg_read(lmac->bgx, lmac->lmacid,
715 BGX_GMP_PCS_ANX_AN_RESULTS);
716
717 speed = (an_result >> 3) & 0x3;
718 lmac->last_duplex = (an_result >> 1) & 0x1;
719 switch (speed) {
720 case 0:
721 lmac->last_speed = 10;
722 break;
723 case 1:
724 lmac->last_speed = 100;
725 break;
726 case 2:
727 lmac->last_speed = 1000;
728 break;
729 default:
730 lmac->link_up = false;
731 lmac->last_speed = SPEED_UNKNOWN;
732 lmac->last_duplex = DUPLEX_UNKNOWN;
733 break;
734 }
735
736next_poll:
737
738 if (lmac->last_link != lmac->link_up) {
739 if (lmac->link_up)
740 bgx_sgmii_change_link_state(lmac);
741 lmac->last_link = lmac->link_up;
742 }
743
744 queue_delayed_work(lmac->check_link, &lmac->dwork, HZ * 3);
745}
746
681static void bgx_poll_for_link(struct work_struct *work) 747static void bgx_poll_for_link(struct work_struct *work)
682{ 748{
683 struct lmac *lmac; 749 struct lmac *lmac;
684 u64 spu_link, smu_link; 750 u64 spu_link, smu_link;
685 751
686 lmac = container_of(work, struct lmac, dwork.work); 752 lmac = container_of(work, struct lmac, dwork.work);
753 if (lmac->is_sgmii) {
754 bgx_poll_for_sgmii_link(lmac);
755 return;
756 }
687 757
688 /* Receive link is latching low. Force it high and verify it */ 758 /* Receive link is latching low. Force it high and verify it */
689 bgx_reg_modify(lmac->bgx, lmac->lmacid, 759 bgx_reg_modify(lmac->bgx, lmac->lmacid,
@@ -775,9 +845,21 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
775 (lmac->lmac_type != BGX_MODE_XLAUI) && 845 (lmac->lmac_type != BGX_MODE_XLAUI) &&
776 (lmac->lmac_type != BGX_MODE_40G_KR) && 846 (lmac->lmac_type != BGX_MODE_40G_KR) &&
777 (lmac->lmac_type != BGX_MODE_10G_KR)) { 847 (lmac->lmac_type != BGX_MODE_10G_KR)) {
778 if (!lmac->phydev) 848 if (!lmac->phydev) {
779 return -ENODEV; 849 if (lmac->autoneg) {
780 850 bgx_reg_write(bgx, lmacid,
851 BGX_GMP_PCS_LINKX_TIMER,
852 PCS_LINKX_TIMER_COUNT);
853 goto poll;
854 } else {
855 /* Default to below link speed and duplex */
856 lmac->link_up = true;
857 lmac->last_speed = 1000;
858 lmac->last_duplex = 1;
859 bgx_sgmii_change_link_state(lmac);
860 return 0;
861 }
862 }
781 lmac->phydev->dev_flags = 0; 863 lmac->phydev->dev_flags = 0;
782 864
783 if (phy_connect_direct(&lmac->netdev, lmac->phydev, 865 if (phy_connect_direct(&lmac->netdev, lmac->phydev,
@@ -786,15 +868,17 @@ static int bgx_lmac_enable(struct bgx *bgx, u8 lmacid)
786 return -ENODEV; 868 return -ENODEV;
787 869
788 phy_start_aneg(lmac->phydev); 870 phy_start_aneg(lmac->phydev);
789 } else { 871 return 0;
790 lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
791 WQ_MEM_RECLAIM, 1);
792 if (!lmac->check_link)
793 return -ENOMEM;
794 INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
795 queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
796 } 872 }
797 873
874poll:
875 lmac->check_link = alloc_workqueue("check_link", WQ_UNBOUND |
876 WQ_MEM_RECLAIM, 1);
877 if (!lmac->check_link)
878 return -ENOMEM;
879 INIT_DELAYED_WORK(&lmac->dwork, bgx_poll_for_link);
880 queue_delayed_work(lmac->check_link, &lmac->dwork, 0);
881
798 return 0; 882 return 0;
799} 883}
800 884