diff options
-rw-r--r-- | drivers/net/bnx2x/bnx2x_ethtool.c | 2 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.c | 4897 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.h | 2 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_main.c | 2 |
4 files changed, 2475 insertions, 2428 deletions
diff --git a/drivers/net/bnx2x/bnx2x_ethtool.c b/drivers/net/bnx2x/bnx2x_ethtool.c index becfd9eb8905..dbcfa7a5618f 100644 --- a/drivers/net/bnx2x/bnx2x_ethtool.c +++ b/drivers/net/bnx2x/bnx2x_ethtool.c | |||
@@ -1282,7 +1282,7 @@ static int bnx2x_run_loopback(struct bnx2x *bp, int loopback_mode, u8 link_up) | |||
1282 | /* check the loopback mode */ | 1282 | /* check the loopback mode */ |
1283 | switch (loopback_mode) { | 1283 | switch (loopback_mode) { |
1284 | case BNX2X_PHY_LOOPBACK: | 1284 | case BNX2X_PHY_LOOPBACK: |
1285 | if (bp->link_params.loopback_mode != LOOPBACK_XGXS_10) | 1285 | if (bp->link_params.loopback_mode != LOOPBACK_XGXS) |
1286 | return -EINVAL; | 1286 | return -EINVAL; |
1287 | break; | 1287 | break; |
1288 | case BNX2X_MAC_LOOPBACK: | 1288 | case BNX2X_MAC_LOOPBACK: |
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index fcf99bf62fa1..e2509aab9f0d 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c | |||
@@ -181,20 +181,6 @@ | |||
181 | (_bank + (_addr & 0xf)), \ | 181 | (_bank + (_addr & 0xf)), \ |
182 | _val) | 182 | _val) |
183 | 183 | ||
184 | static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port) | ||
185 | { | ||
186 | u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
187 | |||
188 | /* Set Clause 22 */ | ||
189 | REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1); | ||
190 | REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000); | ||
191 | udelay(500); | ||
192 | REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f); | ||
193 | udelay(500); | ||
194 | /* Set Clause 45 */ | ||
195 | REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0); | ||
196 | } | ||
197 | |||
198 | static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits) | 184 | static u32 bnx2x_bits_en(struct bnx2x *bp, u32 reg, u32 bits) |
199 | { | 185 | { |
200 | u32 val = REG_RD(bp, reg); | 186 | u32 val = REG_RD(bp, reg); |
@@ -510,175 +496,6 @@ static u8 bnx2x_bmac_enable(struct link_params *params, struct link_vars *vars, | |||
510 | return 0; | 496 | return 0; |
511 | } | 497 | } |
512 | 498 | ||
513 | static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port) | ||
514 | { | ||
515 | u32 val; | ||
516 | |||
517 | DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n"); | ||
518 | |||
519 | val = SERDES_RESET_BITS << (port*16); | ||
520 | |||
521 | /* reset and unreset the SerDes/XGXS */ | ||
522 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); | ||
523 | udelay(500); | ||
524 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); | ||
525 | |||
526 | bnx2x_set_serdes_access(bp, port); | ||
527 | |||
528 | REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + | ||
529 | port*0x10, | ||
530 | DEFAULT_PHY_DEV_ADDR); | ||
531 | } | ||
532 | |||
533 | static void bnx2x_xgxs_deassert(struct link_params *params) | ||
534 | { | ||
535 | struct bnx2x *bp = params->bp; | ||
536 | u8 port; | ||
537 | u32 val; | ||
538 | DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n"); | ||
539 | port = params->port; | ||
540 | |||
541 | val = XGXS_RESET_BITS << (port*16); | ||
542 | |||
543 | /* reset and unreset the SerDes/XGXS */ | ||
544 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); | ||
545 | udelay(500); | ||
546 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); | ||
547 | |||
548 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + | ||
549 | port*0x18, 0); | ||
550 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, | ||
551 | params->phy[INT_PHY].def_md_devad); | ||
552 | } | ||
553 | void bnx2x_link_status_update(struct link_params *params, | ||
554 | struct link_vars *vars) | ||
555 | { | ||
556 | struct bnx2x *bp = params->bp; | ||
557 | u8 link_10g; | ||
558 | u8 port = params->port; | ||
559 | |||
560 | if (params->switch_cfg == SWITCH_CFG_1G) | ||
561 | vars->phy_flags = PHY_SERDES_FLAG; | ||
562 | else | ||
563 | vars->phy_flags = PHY_XGXS_FLAG; | ||
564 | vars->link_status = REG_RD(bp, params->shmem_base + | ||
565 | offsetof(struct shmem_region, | ||
566 | port_mb[port].link_status)); | ||
567 | |||
568 | vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP); | ||
569 | |||
570 | if (vars->link_up) { | ||
571 | DP(NETIF_MSG_LINK, "phy link up\n"); | ||
572 | |||
573 | vars->phy_link_up = 1; | ||
574 | vars->duplex = DUPLEX_FULL; | ||
575 | switch (vars->link_status & | ||
576 | LINK_STATUS_SPEED_AND_DUPLEX_MASK) { | ||
577 | case LINK_10THD: | ||
578 | vars->duplex = DUPLEX_HALF; | ||
579 | /* fall thru */ | ||
580 | case LINK_10TFD: | ||
581 | vars->line_speed = SPEED_10; | ||
582 | break; | ||
583 | |||
584 | case LINK_100TXHD: | ||
585 | vars->duplex = DUPLEX_HALF; | ||
586 | /* fall thru */ | ||
587 | case LINK_100T4: | ||
588 | case LINK_100TXFD: | ||
589 | vars->line_speed = SPEED_100; | ||
590 | break; | ||
591 | |||
592 | case LINK_1000THD: | ||
593 | vars->duplex = DUPLEX_HALF; | ||
594 | /* fall thru */ | ||
595 | case LINK_1000TFD: | ||
596 | vars->line_speed = SPEED_1000; | ||
597 | break; | ||
598 | |||
599 | case LINK_2500THD: | ||
600 | vars->duplex = DUPLEX_HALF; | ||
601 | /* fall thru */ | ||
602 | case LINK_2500TFD: | ||
603 | vars->line_speed = SPEED_2500; | ||
604 | break; | ||
605 | |||
606 | case LINK_10GTFD: | ||
607 | vars->line_speed = SPEED_10000; | ||
608 | break; | ||
609 | |||
610 | case LINK_12GTFD: | ||
611 | vars->line_speed = SPEED_12000; | ||
612 | break; | ||
613 | |||
614 | case LINK_12_5GTFD: | ||
615 | vars->line_speed = SPEED_12500; | ||
616 | break; | ||
617 | |||
618 | case LINK_13GTFD: | ||
619 | vars->line_speed = SPEED_13000; | ||
620 | break; | ||
621 | |||
622 | case LINK_15GTFD: | ||
623 | vars->line_speed = SPEED_15000; | ||
624 | break; | ||
625 | |||
626 | case LINK_16GTFD: | ||
627 | vars->line_speed = SPEED_16000; | ||
628 | break; | ||
629 | |||
630 | default: | ||
631 | break; | ||
632 | } | ||
633 | |||
634 | vars->flow_ctrl = 0; | ||
635 | if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED) | ||
636 | vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX; | ||
637 | |||
638 | if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED) | ||
639 | vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX; | ||
640 | |||
641 | if (!vars->flow_ctrl) | ||
642 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
643 | |||
644 | if (vars->line_speed && | ||
645 | ((vars->line_speed == SPEED_10) || | ||
646 | (vars->line_speed == SPEED_100))) { | ||
647 | vars->phy_flags |= PHY_SGMII_FLAG; | ||
648 | } else { | ||
649 | vars->phy_flags &= ~PHY_SGMII_FLAG; | ||
650 | } | ||
651 | |||
652 | /* anything 10 and over uses the bmac */ | ||
653 | link_10g = ((vars->line_speed == SPEED_10000) || | ||
654 | (vars->line_speed == SPEED_12000) || | ||
655 | (vars->line_speed == SPEED_12500) || | ||
656 | (vars->line_speed == SPEED_13000) || | ||
657 | (vars->line_speed == SPEED_15000) || | ||
658 | (vars->line_speed == SPEED_16000)); | ||
659 | if (link_10g) | ||
660 | vars->mac_type = MAC_TYPE_BMAC; | ||
661 | else | ||
662 | vars->mac_type = MAC_TYPE_EMAC; | ||
663 | |||
664 | } else { /* link down */ | ||
665 | DP(NETIF_MSG_LINK, "phy link down\n"); | ||
666 | |||
667 | vars->phy_link_up = 0; | ||
668 | |||
669 | vars->line_speed = 0; | ||
670 | vars->duplex = DUPLEX_FULL; | ||
671 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
672 | |||
673 | /* indicate no mac active */ | ||
674 | vars->mac_type = MAC_TYPE_NONE; | ||
675 | } | ||
676 | |||
677 | DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n", | ||
678 | vars->link_status, vars->phy_link_up); | ||
679 | DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n", | ||
680 | vars->line_speed, vars->duplex, vars->flow_ctrl); | ||
681 | } | ||
682 | 499 | ||
683 | static void bnx2x_update_mng(struct link_params *params, u32 link_status) | 500 | static void bnx2x_update_mng(struct link_params *params, u32 link_status) |
684 | { | 501 | { |
@@ -1023,6 +840,196 @@ static void bnx2x_set_aer_mmd(struct link_params *params, | |||
1023 | MDIO_AER_BLOCK_AER_REG, 0x3800 + offset); | 840 | MDIO_AER_BLOCK_AER_REG, 0x3800 + offset); |
1024 | } | 841 | } |
1025 | 842 | ||
843 | /******************************************************************/ | ||
844 | /* Internal phy section */ | ||
845 | /******************************************************************/ | ||
846 | |||
847 | static void bnx2x_set_serdes_access(struct bnx2x *bp, u8 port) | ||
848 | { | ||
849 | u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
850 | |||
851 | /* Set Clause 22 */ | ||
852 | REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 1); | ||
853 | REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245f8000); | ||
854 | udelay(500); | ||
855 | REG_WR(bp, emac_base + EMAC_REG_EMAC_MDIO_COMM, 0x245d000f); | ||
856 | udelay(500); | ||
857 | /* Set Clause 45 */ | ||
858 | REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_ST + port*0x10, 0); | ||
859 | } | ||
860 | |||
861 | static void bnx2x_serdes_deassert(struct bnx2x *bp, u8 port) | ||
862 | { | ||
863 | u32 val; | ||
864 | |||
865 | DP(NETIF_MSG_LINK, "bnx2x_serdes_deassert\n"); | ||
866 | |||
867 | val = SERDES_RESET_BITS << (port*16); | ||
868 | |||
869 | /* reset and unreset the SerDes/XGXS */ | ||
870 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); | ||
871 | udelay(500); | ||
872 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); | ||
873 | |||
874 | bnx2x_set_serdes_access(bp, port); | ||
875 | |||
876 | REG_WR(bp, NIG_REG_SERDES0_CTRL_MD_DEVAD + | ||
877 | port*0x10, | ||
878 | DEFAULT_PHY_DEV_ADDR); | ||
879 | } | ||
880 | |||
881 | static void bnx2x_xgxs_deassert(struct link_params *params) | ||
882 | { | ||
883 | struct bnx2x *bp = params->bp; | ||
884 | u8 port; | ||
885 | u32 val; | ||
886 | DP(NETIF_MSG_LINK, "bnx2x_xgxs_deassert\n"); | ||
887 | port = params->port; | ||
888 | |||
889 | val = XGXS_RESET_BITS << (port*16); | ||
890 | |||
891 | /* reset and unreset the SerDes/XGXS */ | ||
892 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_CLEAR, val); | ||
893 | udelay(500); | ||
894 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_3_SET, val); | ||
895 | |||
896 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_ST + | ||
897 | port*0x18, 0); | ||
898 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, | ||
899 | params->phy[INT_PHY].def_md_devad); | ||
900 | } | ||
901 | |||
902 | void bnx2x_link_status_update(struct link_params *params, | ||
903 | struct link_vars *vars) | ||
904 | { | ||
905 | struct bnx2x *bp = params->bp; | ||
906 | u8 link_10g; | ||
907 | u8 port = params->port; | ||
908 | |||
909 | if (params->switch_cfg == SWITCH_CFG_1G) | ||
910 | vars->phy_flags = PHY_SERDES_FLAG; | ||
911 | else | ||
912 | vars->phy_flags = PHY_XGXS_FLAG; | ||
913 | vars->link_status = REG_RD(bp, params->shmem_base + | ||
914 | offsetof(struct shmem_region, | ||
915 | port_mb[port].link_status)); | ||
916 | |||
917 | vars->link_up = (vars->link_status & LINK_STATUS_LINK_UP); | ||
918 | |||
919 | if (vars->link_up) { | ||
920 | DP(NETIF_MSG_LINK, "phy link up\n"); | ||
921 | |||
922 | vars->phy_link_up = 1; | ||
923 | vars->duplex = DUPLEX_FULL; | ||
924 | switch (vars->link_status & | ||
925 | LINK_STATUS_SPEED_AND_DUPLEX_MASK) { | ||
926 | case LINK_10THD: | ||
927 | vars->duplex = DUPLEX_HALF; | ||
928 | /* fall thru */ | ||
929 | case LINK_10TFD: | ||
930 | vars->line_speed = SPEED_10; | ||
931 | break; | ||
932 | |||
933 | case LINK_100TXHD: | ||
934 | vars->duplex = DUPLEX_HALF; | ||
935 | /* fall thru */ | ||
936 | case LINK_100T4: | ||
937 | case LINK_100TXFD: | ||
938 | vars->line_speed = SPEED_100; | ||
939 | break; | ||
940 | |||
941 | case LINK_1000THD: | ||
942 | vars->duplex = DUPLEX_HALF; | ||
943 | /* fall thru */ | ||
944 | case LINK_1000TFD: | ||
945 | vars->line_speed = SPEED_1000; | ||
946 | break; | ||
947 | |||
948 | case LINK_2500THD: | ||
949 | vars->duplex = DUPLEX_HALF; | ||
950 | /* fall thru */ | ||
951 | case LINK_2500TFD: | ||
952 | vars->line_speed = SPEED_2500; | ||
953 | break; | ||
954 | |||
955 | case LINK_10GTFD: | ||
956 | vars->line_speed = SPEED_10000; | ||
957 | break; | ||
958 | |||
959 | case LINK_12GTFD: | ||
960 | vars->line_speed = SPEED_12000; | ||
961 | break; | ||
962 | |||
963 | case LINK_12_5GTFD: | ||
964 | vars->line_speed = SPEED_12500; | ||
965 | break; | ||
966 | |||
967 | case LINK_13GTFD: | ||
968 | vars->line_speed = SPEED_13000; | ||
969 | break; | ||
970 | |||
971 | case LINK_15GTFD: | ||
972 | vars->line_speed = SPEED_15000; | ||
973 | break; | ||
974 | |||
975 | case LINK_16GTFD: | ||
976 | vars->line_speed = SPEED_16000; | ||
977 | break; | ||
978 | |||
979 | default: | ||
980 | break; | ||
981 | } | ||
982 | |||
983 | vars->flow_ctrl = 0; | ||
984 | if (vars->link_status & LINK_STATUS_TX_FLOW_CONTROL_ENABLED) | ||
985 | vars->flow_ctrl |= BNX2X_FLOW_CTRL_TX; | ||
986 | |||
987 | if (vars->link_status & LINK_STATUS_RX_FLOW_CONTROL_ENABLED) | ||
988 | vars->flow_ctrl |= BNX2X_FLOW_CTRL_RX; | ||
989 | |||
990 | if (!vars->flow_ctrl) | ||
991 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
992 | |||
993 | if (vars->line_speed && | ||
994 | ((vars->line_speed == SPEED_10) || | ||
995 | (vars->line_speed == SPEED_100))) { | ||
996 | vars->phy_flags |= PHY_SGMII_FLAG; | ||
997 | } else { | ||
998 | vars->phy_flags &= ~PHY_SGMII_FLAG; | ||
999 | } | ||
1000 | |||
1001 | /* anything 10 and over uses the bmac */ | ||
1002 | link_10g = ((vars->line_speed == SPEED_10000) || | ||
1003 | (vars->line_speed == SPEED_12000) || | ||
1004 | (vars->line_speed == SPEED_12500) || | ||
1005 | (vars->line_speed == SPEED_13000) || | ||
1006 | (vars->line_speed == SPEED_15000) || | ||
1007 | (vars->line_speed == SPEED_16000)); | ||
1008 | if (link_10g) | ||
1009 | vars->mac_type = MAC_TYPE_BMAC; | ||
1010 | else | ||
1011 | vars->mac_type = MAC_TYPE_EMAC; | ||
1012 | |||
1013 | } else { /* link down */ | ||
1014 | DP(NETIF_MSG_LINK, "phy link down\n"); | ||
1015 | |||
1016 | vars->phy_link_up = 0; | ||
1017 | |||
1018 | vars->line_speed = 0; | ||
1019 | vars->duplex = DUPLEX_FULL; | ||
1020 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
1021 | |||
1022 | /* indicate no mac active */ | ||
1023 | vars->mac_type = MAC_TYPE_NONE; | ||
1024 | } | ||
1025 | |||
1026 | DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x\n", | ||
1027 | vars->link_status, vars->phy_link_up); | ||
1028 | DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n", | ||
1029 | vars->line_speed, vars->duplex, vars->flow_ctrl); | ||
1030 | } | ||
1031 | |||
1032 | |||
1026 | static void bnx2x_set_master_ln(struct link_params *params, | 1033 | static void bnx2x_set_master_ln(struct link_params *params, |
1027 | struct bnx2x_phy *phy) | 1034 | struct bnx2x_phy *phy) |
1028 | { | 1035 | { |
@@ -1271,9 +1278,9 @@ static void bnx2x_set_autoneg(struct bnx2x_phy *phy, | |||
1271 | reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; | 1278 | reg_val |= MDIO_CL73_IEEEB1_AN_ADV2_ADVR_1000M_KX; |
1272 | 1279 | ||
1273 | CL45_WR_OVER_CL22(bp, phy, | 1280 | CL45_WR_OVER_CL22(bp, phy, |
1274 | MDIO_REG_BANK_CL73_IEEEB1, | 1281 | MDIO_REG_BANK_CL73_IEEEB1, |
1275 | MDIO_CL73_IEEEB1_AN_ADV2, | 1282 | MDIO_CL73_IEEEB1_AN_ADV2, |
1276 | reg_val); | 1283 | reg_val); |
1277 | 1284 | ||
1278 | /* CL73 Autoneg Enabled */ | 1285 | /* CL73 Autoneg Enabled */ |
1279 | reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; | 1286 | reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; |
@@ -1560,42 +1567,6 @@ static void bnx2x_pause_resolve(struct link_vars *vars, u32 pause_result) | |||
1560 | 1567 | ||
1561 | } | 1568 | } |
1562 | 1569 | ||
1563 | static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, | ||
1564 | struct link_params *params, | ||
1565 | struct link_vars *vars) | ||
1566 | { | ||
1567 | struct bnx2x *bp = params->bp; | ||
1568 | u16 ld_pause; /* local */ | ||
1569 | u16 lp_pause; /* link partner */ | ||
1570 | u16 pause_result; | ||
1571 | u8 ret = 0; | ||
1572 | /* read twice */ | ||
1573 | |||
1574 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
1575 | |||
1576 | if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO) | ||
1577 | vars->flow_ctrl = phy->req_flow_ctrl; | ||
1578 | else if (phy->req_line_speed != SPEED_AUTO_NEG) | ||
1579 | vars->flow_ctrl = params->req_fc_auto_adv; | ||
1580 | else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) { | ||
1581 | ret = 1; | ||
1582 | bnx2x_cl45_read(bp, phy, | ||
1583 | MDIO_AN_DEVAD, | ||
1584 | MDIO_AN_REG_ADV_PAUSE, &ld_pause); | ||
1585 | bnx2x_cl45_read(bp, phy, | ||
1586 | MDIO_AN_DEVAD, | ||
1587 | MDIO_AN_REG_LP_AUTO_NEG, &lp_pause); | ||
1588 | pause_result = (ld_pause & | ||
1589 | MDIO_AN_REG_ADV_PAUSE_MASK) >> 8; | ||
1590 | pause_result |= (lp_pause & | ||
1591 | MDIO_AN_REG_ADV_PAUSE_MASK) >> 10; | ||
1592 | DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", | ||
1593 | pause_result); | ||
1594 | bnx2x_pause_resolve(vars, pause_result); | ||
1595 | } | ||
1596 | return ret; | ||
1597 | } | ||
1598 | |||
1599 | static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy, | 1570 | static u8 bnx2x_direct_parallel_detect_used(struct bnx2x_phy *phy, |
1600 | struct link_params *params) | 1571 | struct link_params *params) |
1601 | { | 1572 | { |
@@ -2004,6 +1975,79 @@ static u8 bnx2x_emac_program(struct link_params *params, | |||
2004 | return 0; | 1975 | return 0; |
2005 | } | 1976 | } |
2006 | 1977 | ||
1978 | static void bnx2x_set_preemphasis(struct bnx2x_phy *phy, | ||
1979 | struct link_params *params) | ||
1980 | { | ||
1981 | |||
1982 | u16 bank, i = 0; | ||
1983 | struct bnx2x *bp = params->bp; | ||
1984 | |||
1985 | for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3; | ||
1986 | bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) { | ||
1987 | CL45_WR_OVER_CL22(bp, phy, | ||
1988 | bank, | ||
1989 | MDIO_RX0_RX_EQ_BOOST, | ||
1990 | phy->rx_preemphasis[i]); | ||
1991 | } | ||
1992 | |||
1993 | for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3; | ||
1994 | bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) { | ||
1995 | CL45_WR_OVER_CL22(bp, phy, | ||
1996 | bank, | ||
1997 | MDIO_TX0_TX_DRIVER, | ||
1998 | phy->tx_preemphasis[i]); | ||
1999 | } | ||
2000 | } | ||
2001 | |||
2002 | static void bnx2x_init_internal_phy(struct bnx2x_phy *phy, | ||
2003 | struct link_params *params, | ||
2004 | struct link_vars *vars) | ||
2005 | { | ||
2006 | struct bnx2x *bp = params->bp; | ||
2007 | u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) || | ||
2008 | (params->loopback_mode == LOOPBACK_XGXS)); | ||
2009 | if (!(vars->phy_flags & PHY_SGMII_FLAG)) { | ||
2010 | if (SINGLE_MEDIA_DIRECT(params) && | ||
2011 | (params->feature_config_flags & | ||
2012 | FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) | ||
2013 | bnx2x_set_preemphasis(phy, params); | ||
2014 | |||
2015 | /* forced speed requested? */ | ||
2016 | if (vars->line_speed != SPEED_AUTO_NEG || | ||
2017 | (SINGLE_MEDIA_DIRECT(params) && | ||
2018 | params->loopback_mode == LOOPBACK_EXT)) { | ||
2019 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); | ||
2020 | |||
2021 | /* disable autoneg */ | ||
2022 | bnx2x_set_autoneg(phy, params, vars, 0); | ||
2023 | |||
2024 | /* program speed and duplex */ | ||
2025 | bnx2x_program_serdes(phy, params, vars); | ||
2026 | |||
2027 | } else { /* AN_mode */ | ||
2028 | DP(NETIF_MSG_LINK, "not SGMII, AN\n"); | ||
2029 | |||
2030 | /* AN enabled */ | ||
2031 | bnx2x_set_brcm_cl37_advertisment(phy, params); | ||
2032 | |||
2033 | /* program duplex & pause advertisement (for aneg) */ | ||
2034 | bnx2x_set_ieee_aneg_advertisment(phy, params, | ||
2035 | vars->ieee_fc); | ||
2036 | |||
2037 | /* enable autoneg */ | ||
2038 | bnx2x_set_autoneg(phy, params, vars, enable_cl73); | ||
2039 | |||
2040 | /* enable and restart AN */ | ||
2041 | bnx2x_restart_autoneg(phy, params, enable_cl73); | ||
2042 | } | ||
2043 | |||
2044 | } else { /* SGMII mode */ | ||
2045 | DP(NETIF_MSG_LINK, "SGMII\n"); | ||
2046 | |||
2047 | bnx2x_initialize_sgmii_process(phy, params, vars); | ||
2048 | } | ||
2049 | } | ||
2050 | |||
2007 | static u8 bnx2x_init_serdes(struct bnx2x_phy *phy, | 2051 | static u8 bnx2x_init_serdes(struct bnx2x_phy *phy, |
2008 | struct link_params *params, | 2052 | struct link_params *params, |
2009 | struct link_vars *vars) | 2053 | struct link_vars *vars) |
@@ -2058,16 +2102,845 @@ static u8 bnx2x_init_xgxs(struct bnx2x_phy *phy, | |||
2058 | return rc; | 2102 | return rc; |
2059 | } | 2103 | } |
2060 | 2104 | ||
2105 | static u16 bnx2x_wait_reset_complete(struct bnx2x *bp, | ||
2106 | struct bnx2x_phy *phy) | ||
2107 | { | ||
2108 | u16 cnt, ctrl; | ||
2109 | /* Wait for soft reset to get cleared upto 1 sec */ | ||
2110 | for (cnt = 0; cnt < 1000; cnt++) { | ||
2111 | bnx2x_cl45_read(bp, phy, | ||
2112 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl); | ||
2113 | if (!(ctrl & (1<<15))) | ||
2114 | break; | ||
2115 | msleep(1); | ||
2116 | } | ||
2117 | DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt); | ||
2118 | return cnt; | ||
2119 | } | ||
2120 | |||
2121 | static void bnx2x_link_int_enable(struct link_params *params) | ||
2122 | { | ||
2123 | u8 port = params->port; | ||
2124 | u32 mask; | ||
2125 | struct bnx2x *bp = params->bp; | ||
2126 | |||
2127 | /* setting the status to report on link up | ||
2128 | for either XGXS or SerDes */ | ||
2129 | |||
2130 | if (params->switch_cfg == SWITCH_CFG_10G) { | ||
2131 | mask = (NIG_MASK_XGXS0_LINK10G | | ||
2132 | NIG_MASK_XGXS0_LINK_STATUS); | ||
2133 | DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n"); | ||
2134 | if (!(SINGLE_MEDIA_DIRECT(params)) && | ||
2135 | params->phy[INT_PHY].type != | ||
2136 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) { | ||
2137 | mask |= NIG_MASK_MI_INT; | ||
2138 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
2139 | } | ||
2140 | |||
2141 | } else { /* SerDes */ | ||
2142 | mask = NIG_MASK_SERDES0_LINK_STATUS; | ||
2143 | DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n"); | ||
2144 | if (!(SINGLE_MEDIA_DIRECT(params)) && | ||
2145 | params->phy[INT_PHY].type != | ||
2146 | PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) { | ||
2147 | mask |= NIG_MASK_MI_INT; | ||
2148 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
2149 | } | ||
2150 | } | ||
2151 | bnx2x_bits_en(bp, | ||
2152 | NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
2153 | mask); | ||
2154 | |||
2155 | DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port, | ||
2156 | (params->switch_cfg == SWITCH_CFG_10G), | ||
2157 | REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4)); | ||
2158 | DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n", | ||
2159 | REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), | ||
2160 | REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18), | ||
2161 | REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c)); | ||
2162 | DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n", | ||
2163 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), | ||
2164 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); | ||
2165 | } | ||
2166 | |||
2167 | static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port, | ||
2168 | u8 is_mi_int) | ||
2169 | { | ||
2170 | u32 latch_status = 0, is_mi_int_status; | ||
2171 | /* Disable the MI INT ( external phy int ) | ||
2172 | * by writing 1 to the status register. Link down indication | ||
2173 | * is high-active-signal, so in this case we need to write the | ||
2174 | * status to clear the XOR | ||
2175 | */ | ||
2176 | /* Read Latched signals */ | ||
2177 | latch_status = REG_RD(bp, | ||
2178 | NIG_REG_LATCH_STATUS_0 + port*8); | ||
2179 | is_mi_int_status = REG_RD(bp, | ||
2180 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4); | ||
2181 | DP(NETIF_MSG_LINK, "original_signal = 0x%x, nig_status = 0x%x," | ||
2182 | "latch_status = 0x%x\n", | ||
2183 | is_mi_int, is_mi_int_status, latch_status); | ||
2184 | /* Handle only those with latched-signal=up.*/ | ||
2185 | if (latch_status & 1) { | ||
2186 | /* For all latched-signal=up,Write original_signal to status */ | ||
2187 | if (is_mi_int) | ||
2188 | bnx2x_bits_en(bp, | ||
2189 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
2190 | + port*4, | ||
2191 | NIG_STATUS_EMAC0_MI_INT); | ||
2192 | else | ||
2193 | bnx2x_bits_dis(bp, | ||
2194 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
2195 | + port*4, | ||
2196 | NIG_STATUS_EMAC0_MI_INT); | ||
2197 | /* For all latched-signal=up : Re-Arm Latch signals */ | ||
2198 | REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8, | ||
2199 | (latch_status & 0xfffe) | (latch_status & 1)); | ||
2200 | } | ||
2201 | } | ||
2202 | |||
2203 | static void bnx2x_link_int_ack(struct link_params *params, | ||
2204 | struct link_vars *vars, u8 is_10g, | ||
2205 | u8 is_mi_int) | ||
2206 | { | ||
2207 | struct bnx2x *bp = params->bp; | ||
2208 | u8 port = params->port; | ||
2209 | |||
2210 | /* first reset all status | ||
2211 | * we assume only one line will be change at a time */ | ||
2212 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
2213 | (NIG_STATUS_XGXS0_LINK10G | | ||
2214 | NIG_STATUS_XGXS0_LINK_STATUS | | ||
2215 | NIG_STATUS_SERDES0_LINK_STATUS)); | ||
2216 | if ((params->phy[EXT_PHY1].type | ||
2217 | == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) || | ||
2218 | (params->phy[EXT_PHY1].type | ||
2219 | == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823)) { | ||
2220 | bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int); | ||
2221 | } | ||
2222 | if (vars->phy_link_up) { | ||
2223 | if (is_10g) { | ||
2224 | /* Disable the 10G link interrupt | ||
2225 | * by writing 1 to the status register | ||
2226 | */ | ||
2227 | DP(NETIF_MSG_LINK, "10G XGXS phy link up\n"); | ||
2228 | bnx2x_bits_en(bp, | ||
2229 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
2230 | NIG_STATUS_XGXS0_LINK10G); | ||
2231 | |||
2232 | } else if (params->switch_cfg == SWITCH_CFG_10G) { | ||
2233 | /* Disable the link interrupt | ||
2234 | * by writing 1 to the relevant lane | ||
2235 | * in the status register | ||
2236 | */ | ||
2237 | u32 ser_lane = ((params->lane_config & | ||
2238 | PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >> | ||
2239 | PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT); | ||
2240 | |||
2241 | DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n", | ||
2242 | vars->line_speed); | ||
2243 | bnx2x_bits_en(bp, | ||
2244 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
2245 | ((1 << ser_lane) << | ||
2246 | NIG_STATUS_XGXS0_LINK_STATUS_SIZE)); | ||
2247 | |||
2248 | } else { /* SerDes */ | ||
2249 | DP(NETIF_MSG_LINK, "SerDes phy link up\n"); | ||
2250 | /* Disable the link interrupt | ||
2251 | * by writing 1 to the status register | ||
2252 | */ | ||
2253 | bnx2x_bits_en(bp, | ||
2254 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
2255 | NIG_STATUS_SERDES0_LINK_STATUS); | ||
2256 | } | ||
2257 | |||
2258 | } | ||
2259 | } | ||
2260 | |||
2261 | static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len) | ||
2262 | { | ||
2263 | u8 *str_ptr = str; | ||
2264 | u32 mask = 0xf0000000; | ||
2265 | u8 shift = 8*4; | ||
2266 | u8 digit; | ||
2267 | if (*len < 10) { | ||
2268 | /* Need more than 10chars for this format */ | ||
2269 | *str_ptr = '\0'; | ||
2270 | return -EINVAL; | ||
2271 | } | ||
2272 | while (shift > 0) { | ||
2273 | |||
2274 | shift -= 4; | ||
2275 | digit = ((num & mask) >> shift); | ||
2276 | if (digit < 0xa) | ||
2277 | *str_ptr = digit + '0'; | ||
2278 | else | ||
2279 | *str_ptr = digit - 0xa + 'a'; | ||
2280 | str_ptr++; | ||
2281 | mask = mask >> 4; | ||
2282 | if (shift == 4*4) { | ||
2283 | *str_ptr = ':'; | ||
2284 | str_ptr++; | ||
2285 | } | ||
2286 | } | ||
2287 | *str_ptr = '\0'; | ||
2288 | return 0; | ||
2289 | } | ||
2290 | |||
2291 | static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) | ||
2292 | { | ||
2293 | str[0] = '\0'; | ||
2294 | (*len)--; | ||
2295 | return 0; | ||
2296 | } | ||
2297 | |||
2298 | u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | ||
2299 | u8 *version, u16 len) | ||
2300 | { | ||
2301 | struct bnx2x *bp; | ||
2302 | u32 spirom_ver = 0; | ||
2303 | u8 status = 0; | ||
2304 | u8 *ver_p = version; | ||
2305 | if (version == NULL || params == NULL) | ||
2306 | return -EINVAL; | ||
2307 | bp = params->bp; | ||
2308 | |||
2309 | /* Extract first external phy*/ | ||
2310 | version[0] = '\0'; | ||
2311 | spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr); | ||
2312 | |||
2313 | if (params->phy[EXT_PHY1].format_fw_ver) | ||
2314 | status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver, | ||
2315 | ver_p, | ||
2316 | &len); | ||
2317 | return status; | ||
2318 | } | ||
2319 | |||
2320 | static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy, | ||
2321 | struct link_params *params) | ||
2322 | { | ||
2323 | u8 port = params->port; | ||
2324 | struct bnx2x *bp = params->bp; | ||
2325 | |||
2326 | if (phy->req_line_speed != SPEED_1000) { | ||
2327 | u32 md_devad; | ||
2328 | |||
2329 | DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n"); | ||
2330 | |||
2331 | /* change the uni_phy_addr in the nig */ | ||
2332 | md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD + | ||
2333 | port*0x18)); | ||
2334 | |||
2335 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5); | ||
2336 | |||
2337 | bnx2x_cl45_write(bp, phy, | ||
2338 | 5, | ||
2339 | (MDIO_REG_BANK_AER_BLOCK + | ||
2340 | (MDIO_AER_BLOCK_AER_REG & 0xf)), | ||
2341 | 0x2800); | ||
2342 | |||
2343 | bnx2x_cl45_write(bp, phy, | ||
2344 | 5, | ||
2345 | (MDIO_REG_BANK_CL73_IEEEB0 + | ||
2346 | (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)), | ||
2347 | 0x6041); | ||
2348 | msleep(200); | ||
2349 | /* set aer mmd back */ | ||
2350 | bnx2x_set_aer_mmd(params, phy); | ||
2351 | |||
2352 | /* and md_devad */ | ||
2353 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, | ||
2354 | md_devad); | ||
2355 | |||
2356 | } else { | ||
2357 | u16 mii_ctrl; | ||
2358 | DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n"); | ||
2359 | bnx2x_cl45_read(bp, phy, 5, | ||
2360 | (MDIO_REG_BANK_COMBO_IEEE0 + | ||
2361 | (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)), | ||
2362 | &mii_ctrl); | ||
2363 | bnx2x_cl45_write(bp, phy, 5, | ||
2364 | (MDIO_REG_BANK_COMBO_IEEE0 + | ||
2365 | (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)), | ||
2366 | mii_ctrl | | ||
2367 | MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK); | ||
2368 | } | ||
2369 | } | ||
2370 | |||
2371 | /* | ||
2372 | *------------------------------------------------------------------------ | ||
2373 | * bnx2x_override_led_value - | ||
2374 | * | ||
2375 | * Override the led value of the requested led | ||
2376 | * | ||
2377 | *------------------------------------------------------------------------ | ||
2378 | */ | ||
2379 | u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, | ||
2380 | u32 led_idx, u32 value) | ||
2381 | { | ||
2382 | u32 reg_val; | ||
2383 | |||
2384 | /* If port 0 then use EMAC0, else use EMAC1*/ | ||
2385 | u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
2386 | |||
2387 | DP(NETIF_MSG_LINK, | ||
2388 | "bnx2x_override_led_value() port %x led_idx %d value %d\n", | ||
2389 | port, led_idx, value); | ||
2390 | |||
2391 | switch (led_idx) { | ||
2392 | case 0: /* 10MB led */ | ||
2393 | /* Read the current value of the LED register in | ||
2394 | the EMAC block */ | ||
2395 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
2396 | /* Set the OVERRIDE bit to 1 */ | ||
2397 | reg_val |= EMAC_LED_OVERRIDE; | ||
2398 | /* If value is 1, set the 10M_OVERRIDE bit, | ||
2399 | otherwise reset it.*/ | ||
2400 | reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) : | ||
2401 | (reg_val & ~EMAC_LED_10MB_OVERRIDE); | ||
2402 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
2403 | break; | ||
2404 | case 1: /*100MB led */ | ||
2405 | /*Read the current value of the LED register in | ||
2406 | the EMAC block */ | ||
2407 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
2408 | /* Set the OVERRIDE bit to 1 */ | ||
2409 | reg_val |= EMAC_LED_OVERRIDE; | ||
2410 | /* If value is 1, set the 100M_OVERRIDE bit, | ||
2411 | otherwise reset it.*/ | ||
2412 | reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) : | ||
2413 | (reg_val & ~EMAC_LED_100MB_OVERRIDE); | ||
2414 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
2415 | break; | ||
2416 | case 2: /* 1000MB led */ | ||
2417 | /* Read the current value of the LED register in the | ||
2418 | EMAC block */ | ||
2419 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
2420 | /* Set the OVERRIDE bit to 1 */ | ||
2421 | reg_val |= EMAC_LED_OVERRIDE; | ||
2422 | /* If value is 1, set the 1000M_OVERRIDE bit, otherwise | ||
2423 | reset it. */ | ||
2424 | reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) : | ||
2425 | (reg_val & ~EMAC_LED_1000MB_OVERRIDE); | ||
2426 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
2427 | break; | ||
2428 | case 3: /* 2500MB led */ | ||
2429 | /* Read the current value of the LED register in the | ||
2430 | EMAC block*/ | ||
2431 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
2432 | /* Set the OVERRIDE bit to 1 */ | ||
2433 | reg_val |= EMAC_LED_OVERRIDE; | ||
2434 | /* If value is 1, set the 2500M_OVERRIDE bit, otherwise | ||
2435 | reset it.*/ | ||
2436 | reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) : | ||
2437 | (reg_val & ~EMAC_LED_2500MB_OVERRIDE); | ||
2438 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
2439 | break; | ||
2440 | case 4: /*10G led */ | ||
2441 | if (port == 0) { | ||
2442 | REG_WR(bp, NIG_REG_LED_10G_P0, | ||
2443 | value); | ||
2444 | } else { | ||
2445 | REG_WR(bp, NIG_REG_LED_10G_P1, | ||
2446 | value); | ||
2447 | } | ||
2448 | break; | ||
2449 | case 5: /* TRAFFIC led */ | ||
2450 | /* Find if the traffic control is via BMAC or EMAC */ | ||
2451 | if (port == 0) | ||
2452 | reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN); | ||
2453 | else | ||
2454 | reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN); | ||
2455 | |||
2456 | /* Override the traffic led in the EMAC:*/ | ||
2457 | if (reg_val == 1) { | ||
2458 | /* Read the current value of the LED register in | ||
2459 | the EMAC block */ | ||
2460 | reg_val = REG_RD(bp, emac_base + | ||
2461 | EMAC_REG_EMAC_LED); | ||
2462 | /* Set the TRAFFIC_OVERRIDE bit to 1 */ | ||
2463 | reg_val |= EMAC_LED_OVERRIDE; | ||
2464 | /* If value is 1, set the TRAFFIC bit, otherwise | ||
2465 | reset it.*/ | ||
2466 | reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) : | ||
2467 | (reg_val & ~EMAC_LED_TRAFFIC); | ||
2468 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
2469 | } else { /* Override the traffic led in the BMAC: */ | ||
2470 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 | ||
2471 | + port*4, 1); | ||
2472 | REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4, | ||
2473 | value); | ||
2474 | } | ||
2475 | break; | ||
2476 | default: | ||
2477 | DP(NETIF_MSG_LINK, | ||
2478 | "bnx2x_override_led_value() unknown led index %d " | ||
2479 | "(should be 0-5)\n", led_idx); | ||
2480 | return -EINVAL; | ||
2481 | } | ||
2482 | |||
2483 | return 0; | ||
2484 | } | ||
2485 | |||
2486 | u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) | ||
2487 | { | ||
2488 | u8 port = params->port; | ||
2489 | u16 hw_led_mode = params->hw_led_mode; | ||
2490 | u8 rc = 0; | ||
2491 | u32 tmp; | ||
2492 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
2493 | struct bnx2x *bp = params->bp; | ||
2494 | DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode); | ||
2495 | DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n", | ||
2496 | speed, hw_led_mode); | ||
2497 | switch (mode) { | ||
2498 | case LED_MODE_OFF: | ||
2499 | REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0); | ||
2500 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, | ||
2501 | SHARED_HW_CFG_LED_MAC1); | ||
2502 | |||
2503 | tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); | ||
2504 | EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE)); | ||
2505 | break; | ||
2506 | |||
2507 | case LED_MODE_OPER: | ||
2508 | if (SINGLE_MEDIA_DIRECT(params)) { | ||
2509 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); | ||
2510 | REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); | ||
2511 | } else { | ||
2512 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, | ||
2513 | hw_led_mode); | ||
2514 | } | ||
2515 | |||
2516 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + | ||
2517 | port*4, 0); | ||
2518 | /* Set blinking rate to ~15.9Hz */ | ||
2519 | REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4, | ||
2520 | LED_BLINK_RATE_VAL); | ||
2521 | REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 + | ||
2522 | port*4, 1); | ||
2523 | tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); | ||
2524 | EMAC_WR(bp, EMAC_REG_EMAC_LED, | ||
2525 | (tmp & (~EMAC_LED_OVERRIDE))); | ||
2526 | |||
2527 | if (CHIP_IS_E1(bp) && | ||
2528 | ((speed == SPEED_2500) || | ||
2529 | (speed == SPEED_1000) || | ||
2530 | (speed == SPEED_100) || | ||
2531 | (speed == SPEED_10))) { | ||
2532 | /* On Everest 1 Ax chip versions for speeds less than | ||
2533 | 10G LED scheme is different */ | ||
2534 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 | ||
2535 | + port*4, 1); | ||
2536 | REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + | ||
2537 | port*4, 0); | ||
2538 | REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 + | ||
2539 | port*4, 1); | ||
2540 | } | ||
2541 | break; | ||
2542 | |||
2543 | default: | ||
2544 | rc = -EINVAL; | ||
2545 | DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n", | ||
2546 | mode); | ||
2547 | break; | ||
2548 | } | ||
2549 | return rc; | ||
2550 | |||
2551 | } | ||
2552 | |||
2553 | u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars) | ||
2554 | { | ||
2555 | struct bnx2x *bp = params->bp; | ||
2556 | u16 gp_status = 0, phy_index = 0; | ||
2557 | |||
2558 | CL45_RD_OVER_CL22(bp, ¶ms->phy[INT_PHY], | ||
2559 | MDIO_REG_BANK_GP_STATUS, | ||
2560 | MDIO_GP_STATUS_TOP_AN_STATUS1, | ||
2561 | &gp_status); | ||
2562 | /* link is up only if both local phy and external phy are up */ | ||
2563 | if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { | ||
2564 | u8 ext_phy_link_up = 1; | ||
2565 | struct link_vars temp_vars; | ||
2566 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
2567 | phy_index++) { | ||
2568 | if (params->phy[phy_index].read_status) | ||
2569 | ext_phy_link_up &= | ||
2570 | params->phy[phy_index].read_status( | ||
2571 | ¶ms->phy[phy_index], | ||
2572 | params, &temp_vars); | ||
2573 | } | ||
2574 | if (ext_phy_link_up) | ||
2575 | return 0; | ||
2576 | } | ||
2577 | return -ESRCH; | ||
2578 | } | ||
2579 | |||
2580 | static u8 bnx2x_link_initialize(struct link_params *params, | ||
2581 | struct link_vars *vars) | ||
2582 | { | ||
2583 | u8 rc = 0; | ||
2584 | u8 phy_index, non_ext_phy; | ||
2585 | struct bnx2x *bp = params->bp; | ||
2586 | /** | ||
2587 | * In case of external phy existence, the line speed would be the | ||
2588 | * line speed linked up by the external phy. In case it is direct | ||
2589 | * only, then the line_speed during initialization will be | ||
2590 | * equal to the req_line_speed | ||
2591 | */ | ||
2592 | vars->line_speed = params->phy[INT_PHY].req_line_speed; | ||
2593 | |||
2594 | /** | ||
2595 | * Initialize the internal phy in case this is a direct board | ||
2596 | * (no external phys), or this board has external phy which requires | ||
2597 | * to first. | ||
2598 | */ | ||
2599 | |||
2600 | if (params->phy[INT_PHY].config_init) | ||
2601 | params->phy[INT_PHY].config_init( | ||
2602 | ¶ms->phy[INT_PHY], | ||
2603 | params, vars); | ||
2604 | |||
2605 | /* init ext phy and enable link state int */ | ||
2606 | non_ext_phy = (SINGLE_MEDIA_DIRECT(params) || | ||
2607 | (params->loopback_mode == LOOPBACK_XGXS)); | ||
2608 | |||
2609 | if (non_ext_phy || | ||
2610 | (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) || | ||
2611 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { | ||
2612 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; | ||
2613 | if (vars->line_speed == SPEED_AUTO_NEG) | ||
2614 | bnx2x_set_parallel_detection(phy, params); | ||
2615 | bnx2x_init_internal_phy(phy, params, vars); | ||
2616 | } | ||
2617 | |||
2618 | /* Init external phy*/ | ||
2619 | if (!non_ext_phy) | ||
2620 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
2621 | phy_index++) { | ||
2622 | params->phy[phy_index].config_init( | ||
2623 | ¶ms->phy[phy_index], | ||
2624 | params, vars); | ||
2625 | } | ||
2626 | |||
2627 | /* Reset the interrupt indication after phy was initialized */ | ||
2628 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + | ||
2629 | params->port*4, | ||
2630 | (NIG_STATUS_XGXS0_LINK10G | | ||
2631 | NIG_STATUS_XGXS0_LINK_STATUS | | ||
2632 | NIG_STATUS_SERDES0_LINK_STATUS | | ||
2633 | NIG_MASK_MI_INT)); | ||
2634 | return rc; | ||
2635 | } | ||
2636 | |||
2637 | static void bnx2x_int_link_reset(struct bnx2x_phy *phy, | ||
2638 | struct link_params *params) | ||
2639 | { | ||
2640 | /* reset the SerDes/XGXS */ | ||
2641 | REG_WR(params->bp, GRCBASE_MISC + | ||
2642 | MISC_REGISTERS_RESET_REG_3_CLEAR, | ||
2643 | (0x1ff << (params->port*16))); | ||
2644 | } | ||
2645 | |||
2646 | static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy, | ||
2647 | struct link_params *params) | ||
2648 | { | ||
2649 | struct bnx2x *bp = params->bp; | ||
2650 | u8 gpio_port; | ||
2651 | /* HW reset */ | ||
2652 | gpio_port = params->port; | ||
2653 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
2654 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
2655 | gpio_port); | ||
2656 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
2657 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
2658 | gpio_port); | ||
2659 | DP(NETIF_MSG_LINK, "reset external PHY\n"); | ||
2660 | } | ||
2661 | |||
2662 | static u8 bnx2x_update_link_down(struct link_params *params, | ||
2663 | struct link_vars *vars) | ||
2664 | { | ||
2665 | struct bnx2x *bp = params->bp; | ||
2666 | u8 port = params->port; | ||
2667 | |||
2668 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); | ||
2669 | bnx2x_set_led(params, LED_MODE_OFF, 0); | ||
2670 | |||
2671 | /* indicate no mac active */ | ||
2672 | vars->mac_type = MAC_TYPE_NONE; | ||
2673 | |||
2674 | /* update shared memory */ | ||
2675 | vars->link_status = 0; | ||
2676 | vars->line_speed = 0; | ||
2677 | bnx2x_update_mng(params, vars->link_status); | ||
2678 | |||
2679 | /* activate nig drain */ | ||
2680 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | ||
2681 | |||
2682 | /* disable emac */ | ||
2683 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); | ||
2684 | |||
2685 | msleep(10); | ||
2686 | |||
2687 | /* reset BigMac */ | ||
2688 | bnx2x_bmac_rx_disable(bp, params->port); | ||
2689 | REG_WR(bp, GRCBASE_MISC + | ||
2690 | MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
2691 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
2692 | return 0; | ||
2693 | } | ||
2694 | |||
2695 | static u8 bnx2x_update_link_up(struct link_params *params, | ||
2696 | struct link_vars *vars, | ||
2697 | u8 link_10g) | ||
2698 | { | ||
2699 | struct bnx2x *bp = params->bp; | ||
2700 | u8 port = params->port; | ||
2701 | u8 rc = 0; | ||
2702 | |||
2703 | vars->link_status |= LINK_STATUS_LINK_UP; | ||
2704 | if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) | ||
2705 | vars->link_status |= | ||
2706 | LINK_STATUS_TX_FLOW_CONTROL_ENABLED; | ||
2707 | |||
2708 | if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX) | ||
2709 | vars->link_status |= | ||
2710 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED; | ||
2711 | if (link_10g) { | ||
2712 | bnx2x_bmac_enable(params, vars, 0); | ||
2713 | bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); | ||
2714 | } else { | ||
2715 | rc = bnx2x_emac_program(params, vars); | ||
2716 | |||
2717 | bnx2x_emac_enable(params, vars, 0); | ||
2718 | |||
2719 | /* AN complete? */ | ||
2720 | if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) | ||
2721 | && (!(vars->phy_flags & PHY_SGMII_FLAG)) && | ||
2722 | SINGLE_MEDIA_DIRECT(params)) | ||
2723 | bnx2x_set_gmii_tx_driver(params); | ||
2724 | } | ||
2725 | |||
2726 | /* PBF - link up */ | ||
2727 | rc |= bnx2x_pbf_update(params, vars->flow_ctrl, | ||
2728 | vars->line_speed); | ||
2729 | |||
2730 | /* disable drain */ | ||
2731 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0); | ||
2732 | |||
2733 | /* update shared memory */ | ||
2734 | bnx2x_update_mng(params, vars->link_status); | ||
2735 | msleep(20); | ||
2736 | return rc; | ||
2737 | } | ||
2738 | /** | ||
2739 | * The bnx2x_link_update function should be called upon link | ||
2740 | * interrupt. | ||
2741 | * Link is considered up as follows: | ||
2742 | * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs | ||
2743 | * to be up | ||
2744 | * - SINGLE_MEDIA - The link between the 577xx and the external | ||
2745 | * phy (XGXS) need to up as well as the external link of the | ||
2746 | * phy (PHY_EXT1) | ||
2747 | * - DUAL_MEDIA - The link between the 577xx and the first | ||
2748 | * external phy needs to be up, and at least one of the 2 | ||
2749 | * external phy link must be up. | ||
2750 | */ | ||
2751 | u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | ||
2752 | { | ||
2753 | struct bnx2x *bp = params->bp; | ||
2754 | struct link_vars phy_vars[MAX_PHYS]; | ||
2755 | u8 port = params->port; | ||
2756 | u8 link_10g, phy_index; | ||
2757 | u8 ext_phy_link_up = 0, cur_link_up, rc = 0; | ||
2758 | u8 is_mi_int = 0; | ||
2759 | u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; | ||
2760 | u8 active_external_phy = INT_PHY; | ||
2761 | vars->link_status = 0; | ||
2762 | for (phy_index = INT_PHY; phy_index < params->num_phys; | ||
2763 | phy_index++) { | ||
2764 | phy_vars[phy_index].flow_ctrl = 0; | ||
2765 | phy_vars[phy_index].link_status = 0; | ||
2766 | phy_vars[phy_index].line_speed = 0; | ||
2767 | phy_vars[phy_index].duplex = DUPLEX_FULL; | ||
2768 | phy_vars[phy_index].phy_link_up = 0; | ||
2769 | phy_vars[phy_index].link_up = 0; | ||
2770 | } | ||
2771 | |||
2772 | DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n", | ||
2773 | port, (vars->phy_flags & PHY_XGXS_FLAG), | ||
2774 | REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4)); | ||
2775 | |||
2776 | is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + | ||
2777 | port*0x18) > 0); | ||
2778 | DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n", | ||
2779 | REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), | ||
2780 | is_mi_int, | ||
2781 | REG_RD(bp, | ||
2782 | NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c)); | ||
2783 | |||
2784 | DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n", | ||
2785 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), | ||
2786 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); | ||
2787 | |||
2788 | /* disable emac */ | ||
2789 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); | ||
2790 | |||
2791 | /** | ||
2792 | * Step 1: | ||
2793 | * Check external link change only for external phys, and apply | ||
2794 | * priority selection between them in case the link on both phys | ||
2795 | * is up. Note that the instead of the common vars, a temporary | ||
2796 | * vars argument is used since each phy may have different link/ | ||
2797 | * speed/duplex result | ||
2798 | */ | ||
2799 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
2800 | phy_index++) { | ||
2801 | struct bnx2x_phy *phy = ¶ms->phy[phy_index]; | ||
2802 | if (!phy->read_status) | ||
2803 | continue; | ||
2804 | /* Read link status and params of this ext phy */ | ||
2805 | cur_link_up = phy->read_status(phy, params, | ||
2806 | &phy_vars[phy_index]); | ||
2807 | if (cur_link_up) { | ||
2808 | DP(NETIF_MSG_LINK, "phy in index %d link is up\n", | ||
2809 | phy_index); | ||
2810 | } else { | ||
2811 | DP(NETIF_MSG_LINK, "phy in index %d link is down\n", | ||
2812 | phy_index); | ||
2813 | continue; | ||
2814 | } | ||
2815 | |||
2816 | if (!ext_phy_link_up) { | ||
2817 | ext_phy_link_up = 1; | ||
2818 | active_external_phy = phy_index; | ||
2819 | } | ||
2820 | } | ||
2821 | prev_line_speed = vars->line_speed; | ||
2822 | /** | ||
2823 | * Step 2: | ||
2824 | * Read the status of the internal phy. In case of | ||
2825 | * DIRECT_SINGLE_MEDIA board, this link is the external link, | ||
2826 | * otherwise this is the link between the 577xx and the first | ||
2827 | * external phy | ||
2828 | */ | ||
2829 | if (params->phy[INT_PHY].read_status) | ||
2830 | params->phy[INT_PHY].read_status( | ||
2831 | ¶ms->phy[INT_PHY], | ||
2832 | params, vars); | ||
2833 | /** | ||
2834 | * The INT_PHY flow control reside in the vars. This include the | ||
2835 | * case where the speed or flow control are not set to AUTO. | ||
2836 | * Otherwise, the active external phy flow control result is set | ||
2837 | * to the vars. The ext_phy_line_speed is needed to check if the | ||
2838 | * speed is different between the internal phy and external phy. | ||
2839 | * This case may be result of intermediate link speed change. | ||
2840 | */ | ||
2841 | if (active_external_phy > INT_PHY) { | ||
2842 | vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl; | ||
2843 | /** | ||
2844 | * Link speed is taken from the XGXS. AN and FC result from | ||
2845 | * the external phy. | ||
2846 | */ | ||
2847 | vars->link_status |= phy_vars[active_external_phy].link_status; | ||
2848 | ext_phy_line_speed = phy_vars[active_external_phy].line_speed; | ||
2849 | vars->duplex = phy_vars[active_external_phy].duplex; | ||
2850 | if (params->phy[active_external_phy].supported & | ||
2851 | SUPPORTED_FIBRE) | ||
2852 | vars->link_status |= LINK_STATUS_SERDES_LINK; | ||
2853 | DP(NETIF_MSG_LINK, "Active external phy selected: %x\n", | ||
2854 | active_external_phy); | ||
2855 | } | ||
2856 | DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x," | ||
2857 | " ext_phy_line_speed = %d\n", vars->flow_ctrl, | ||
2858 | vars->link_status, ext_phy_line_speed); | ||
2859 | /** | ||
2860 | * Upon link speed change set the NIG into drain mode. Comes to | ||
2861 | * deals with possible FIFO glitch due to clk change when speed | ||
2862 | * is decreased without link down indicator | ||
2863 | */ | ||
2864 | |||
2865 | if (vars->phy_link_up) { | ||
2866 | if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up && | ||
2867 | (ext_phy_line_speed != vars->line_speed)) { | ||
2868 | DP(NETIF_MSG_LINK, "Internal link speed %d is" | ||
2869 | " different than the external" | ||
2870 | " link speed %d\n", vars->line_speed, | ||
2871 | ext_phy_line_speed); | ||
2872 | vars->phy_link_up = 0; | ||
2873 | } else if (prev_line_speed != vars->line_speed) { | ||
2874 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE | ||
2875 | + params->port*4, 0); | ||
2876 | msleep(1); | ||
2877 | } | ||
2878 | } | ||
2879 | |||
2880 | /* anything 10 and over uses the bmac */ | ||
2881 | link_10g = ((vars->line_speed == SPEED_10000) || | ||
2882 | (vars->line_speed == SPEED_12000) || | ||
2883 | (vars->line_speed == SPEED_12500) || | ||
2884 | (vars->line_speed == SPEED_13000) || | ||
2885 | (vars->line_speed == SPEED_15000) || | ||
2886 | (vars->line_speed == SPEED_16000)); | ||
2887 | |||
2888 | bnx2x_link_int_ack(params, vars, link_10g, is_mi_int); | ||
2889 | |||
2890 | /** | ||
2891 | * In case external phy link is up, and internal link is down | ||
2892 | * (not initialized yet probably after link initialization, it | ||
2893 | * needs to be initialized. | ||
2894 | * Note that after link down-up as result of cable plug, the xgxs | ||
2895 | * link would probably become up again without the need | ||
2896 | * initialize it | ||
2897 | */ | ||
2898 | if (!(SINGLE_MEDIA_DIRECT(params))) { | ||
2899 | DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d," | ||
2900 | " init_preceding = %d\n", ext_phy_link_up, | ||
2901 | vars->phy_link_up, | ||
2902 | params->phy[EXT_PHY1].flags & | ||
2903 | FLAGS_INIT_XGXS_FIRST); | ||
2904 | if (!(params->phy[EXT_PHY1].flags & | ||
2905 | FLAGS_INIT_XGXS_FIRST) | ||
2906 | && ext_phy_link_up && !vars->phy_link_up) { | ||
2907 | vars->line_speed = ext_phy_line_speed; | ||
2908 | if (vars->line_speed < SPEED_1000) | ||
2909 | vars->phy_flags |= PHY_SGMII_FLAG; | ||
2910 | else | ||
2911 | vars->phy_flags &= ~PHY_SGMII_FLAG; | ||
2912 | bnx2x_init_internal_phy(¶ms->phy[INT_PHY], | ||
2913 | params, | ||
2914 | vars); | ||
2915 | } | ||
2916 | } | ||
2917 | /** | ||
2918 | * Link is up only if both local phy and external phy (in case of | ||
2919 | * non-direct board) are up | ||
2920 | */ | ||
2921 | vars->link_up = (vars->phy_link_up && | ||
2922 | (ext_phy_link_up || | ||
2923 | SINGLE_MEDIA_DIRECT(params))); | ||
2924 | |||
2925 | if (vars->link_up) | ||
2926 | rc = bnx2x_update_link_up(params, vars, link_10g); | ||
2927 | else | ||
2928 | rc = bnx2x_update_link_down(params, vars); | ||
2929 | |||
2930 | return rc; | ||
2931 | } | ||
2932 | |||
2933 | |||
2061 | /*****************************************************************************/ | 2934 | /*****************************************************************************/ |
2062 | /* External Phy section */ | 2935 | /* External Phy section */ |
2063 | /*****************************************************************************/ | 2936 | /*****************************************************************************/ |
2064 | void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port) | 2937 | void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port) |
2065 | { | 2938 | { |
2066 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | 2939 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, |
2067 | MISC_REGISTERS_GPIO_OUTPUT_LOW, port); | 2940 | MISC_REGISTERS_GPIO_OUTPUT_LOW, port); |
2068 | msleep(1); | 2941 | msleep(1); |
2069 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | 2942 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, |
2070 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); | 2943 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, port); |
2071 | } | 2944 | } |
2072 | 2945 | ||
2073 | static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port, | 2946 | static void bnx2x_save_spirom_version(struct bnx2x *bp, u8 port, |
@@ -2094,59 +2967,211 @@ static void bnx2x_save_bcm_spirom_ver(struct bnx2x *bp, | |||
2094 | phy->ver_addr); | 2967 | phy->ver_addr); |
2095 | } | 2968 | } |
2096 | 2969 | ||
2097 | static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy, | 2970 | static void bnx2x_ext_phy_set_pause(struct link_params *params, |
2098 | struct link_params *params) | 2971 | struct bnx2x_phy *phy, |
2972 | struct link_vars *vars) | ||
2099 | { | 2973 | { |
2100 | u16 val, fw_ver1, fw_ver2, cnt; | 2974 | u16 val; |
2101 | struct bnx2x *bp = params->bp; | 2975 | struct bnx2x *bp = params->bp; |
2976 | /* read modify write pause advertizing */ | ||
2977 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val); | ||
2102 | 2978 | ||
2103 | /* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/ | 2979 | val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH; |
2104 | /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */ | ||
2105 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014); | ||
2106 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200); | ||
2107 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000); | ||
2108 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300); | ||
2109 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009); | ||
2110 | 2980 | ||
2111 | for (cnt = 0; cnt < 100; cnt++) { | 2981 | /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ |
2112 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val); | 2982 | bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); |
2113 | if (val & 1) | 2983 | if ((vars->ieee_fc & |
2114 | break; | 2984 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == |
2115 | udelay(5); | 2985 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { |
2986 | val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC; | ||
2116 | } | 2987 | } |
2117 | if (cnt == 100) { | 2988 | if ((vars->ieee_fc & |
2118 | DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n"); | 2989 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == |
2119 | bnx2x_save_spirom_version(bp, params->port, 0, | 2990 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { |
2120 | phy->ver_addr); | 2991 | val |= MDIO_AN_REG_ADV_PAUSE_PAUSE; |
2992 | } | ||
2993 | DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val); | ||
2994 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val); | ||
2995 | } | ||
2996 | |||
2997 | static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy, | ||
2998 | struct link_params *params, | ||
2999 | struct link_vars *vars) | ||
3000 | { | ||
3001 | struct bnx2x *bp = params->bp; | ||
3002 | u16 ld_pause; /* local */ | ||
3003 | u16 lp_pause; /* link partner */ | ||
3004 | u16 pause_result; | ||
3005 | u8 ret = 0; | ||
3006 | /* read twice */ | ||
3007 | |||
3008 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
3009 | |||
3010 | if (phy->req_flow_ctrl != BNX2X_FLOW_CTRL_AUTO) | ||
3011 | vars->flow_ctrl = phy->req_flow_ctrl; | ||
3012 | else if (phy->req_line_speed != SPEED_AUTO_NEG) | ||
3013 | vars->flow_ctrl = params->req_fc_auto_adv; | ||
3014 | else if (vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) { | ||
3015 | ret = 1; | ||
3016 | bnx2x_cl45_read(bp, phy, | ||
3017 | MDIO_AN_DEVAD, | ||
3018 | MDIO_AN_REG_ADV_PAUSE, &ld_pause); | ||
3019 | bnx2x_cl45_read(bp, phy, | ||
3020 | MDIO_AN_DEVAD, | ||
3021 | MDIO_AN_REG_LP_AUTO_NEG, &lp_pause); | ||
3022 | pause_result = (ld_pause & | ||
3023 | MDIO_AN_REG_ADV_PAUSE_MASK) >> 8; | ||
3024 | pause_result |= (lp_pause & | ||
3025 | MDIO_AN_REG_ADV_PAUSE_MASK) >> 10; | ||
3026 | DP(NETIF_MSG_LINK, "Ext PHY pause result 0x%x\n", | ||
3027 | pause_result); | ||
3028 | bnx2x_pause_resolve(vars, pause_result); | ||
3029 | } | ||
3030 | return ret; | ||
3031 | } | ||
3032 | |||
3033 | static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp, | ||
3034 | struct bnx2x_phy *phy, | ||
3035 | struct link_vars *vars) | ||
3036 | { | ||
3037 | u16 val; | ||
3038 | bnx2x_cl45_read(bp, phy, | ||
3039 | MDIO_AN_DEVAD, | ||
3040 | MDIO_AN_REG_STATUS, &val); | ||
3041 | bnx2x_cl45_read(bp, phy, | ||
3042 | MDIO_AN_DEVAD, | ||
3043 | MDIO_AN_REG_STATUS, &val); | ||
3044 | if (val & (1<<5)) | ||
3045 | vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE; | ||
3046 | if ((val & (1<<0)) == 0) | ||
3047 | vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED; | ||
3048 | } | ||
3049 | |||
3050 | /******************************************************************/ | ||
3051 | /* common BCM8073/BCM8727 PHY SECTION */ | ||
3052 | /******************************************************************/ | ||
3053 | static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy, | ||
3054 | struct link_params *params, | ||
3055 | struct link_vars *vars) | ||
3056 | { | ||
3057 | struct bnx2x *bp = params->bp; | ||
3058 | if (phy->req_line_speed == SPEED_10 || | ||
3059 | phy->req_line_speed == SPEED_100) { | ||
3060 | vars->flow_ctrl = phy->req_flow_ctrl; | ||
2121 | return; | 3061 | return; |
2122 | } | 3062 | } |
2123 | 3063 | ||
3064 | if (bnx2x_ext_phy_resolve_fc(phy, params, vars) && | ||
3065 | (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) { | ||
3066 | u16 pause_result; | ||
3067 | u16 ld_pause; /* local */ | ||
3068 | u16 lp_pause; /* link partner */ | ||
3069 | bnx2x_cl45_read(bp, phy, | ||
3070 | MDIO_AN_DEVAD, | ||
3071 | MDIO_AN_REG_CL37_FC_LD, &ld_pause); | ||
2124 | 3072 | ||
2125 | /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */ | 3073 | bnx2x_cl45_read(bp, phy, |
2126 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000); | 3074 | MDIO_AN_DEVAD, |
2127 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200); | 3075 | MDIO_AN_REG_CL37_FC_LP, &lp_pause); |
2128 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A); | 3076 | pause_result = (ld_pause & |
2129 | for (cnt = 0; cnt < 100; cnt++) { | 3077 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5; |
2130 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val); | 3078 | pause_result |= (lp_pause & |
2131 | if (val & 1) | 3079 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7; |
2132 | break; | 3080 | |
2133 | udelay(5); | 3081 | bnx2x_pause_resolve(vars, pause_result); |
3082 | DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n", | ||
3083 | pause_result); | ||
2134 | } | 3084 | } |
2135 | if (cnt == 100) { | 3085 | } |
2136 | DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n"); | 3086 | |
2137 | bnx2x_save_spirom_version(bp, params->port, 0, | 3087 | static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp, |
2138 | phy->ver_addr); | 3088 | struct bnx2x_phy *phy, |
3089 | u8 port) | ||
3090 | { | ||
3091 | /* Boot port from external ROM */ | ||
3092 | /* EDC grst */ | ||
3093 | bnx2x_cl45_write(bp, phy, | ||
3094 | MDIO_PMA_DEVAD, | ||
3095 | MDIO_PMA_REG_GEN_CTRL, | ||
3096 | 0x0001); | ||
3097 | |||
3098 | /* ucode reboot and rst */ | ||
3099 | bnx2x_cl45_write(bp, phy, | ||
3100 | MDIO_PMA_DEVAD, | ||
3101 | MDIO_PMA_REG_GEN_CTRL, | ||
3102 | 0x008c); | ||
3103 | |||
3104 | bnx2x_cl45_write(bp, phy, | ||
3105 | MDIO_PMA_DEVAD, | ||
3106 | MDIO_PMA_REG_MISC_CTRL1, 0x0001); | ||
3107 | |||
3108 | /* Reset internal microprocessor */ | ||
3109 | bnx2x_cl45_write(bp, phy, | ||
3110 | MDIO_PMA_DEVAD, | ||
3111 | MDIO_PMA_REG_GEN_CTRL, | ||
3112 | MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); | ||
3113 | |||
3114 | /* Release srst bit */ | ||
3115 | bnx2x_cl45_write(bp, phy, | ||
3116 | MDIO_PMA_DEVAD, | ||
3117 | MDIO_PMA_REG_GEN_CTRL, | ||
3118 | MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); | ||
3119 | |||
3120 | /* wait for 120ms for code download via SPI port */ | ||
3121 | msleep(120); | ||
3122 | |||
3123 | /* Clear ser_boot_ctl bit */ | ||
3124 | bnx2x_cl45_write(bp, phy, | ||
3125 | MDIO_PMA_DEVAD, | ||
3126 | MDIO_PMA_REG_MISC_CTRL1, 0x0000); | ||
3127 | bnx2x_save_bcm_spirom_ver(bp, phy, port); | ||
3128 | } | ||
3129 | |||
3130 | static void bnx2x_8073_set_xaui_low_power_mode(struct bnx2x *bp, | ||
3131 | struct bnx2x_phy *phy) | ||
3132 | { | ||
3133 | u16 val; | ||
3134 | bnx2x_cl45_read(bp, phy, | ||
3135 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val); | ||
3136 | |||
3137 | if (val == 0) { | ||
3138 | /* Mustn't set low power mode in 8073 A0 */ | ||
2139 | return; | 3139 | return; |
2140 | } | 3140 | } |
2141 | 3141 | ||
2142 | /* lower 16 bits of the register SPI_FW_STATUS */ | 3142 | /* Disable PLL sequencer (use read-modify-write to clear bit 13) */ |
2143 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1); | 3143 | bnx2x_cl45_read(bp, phy, |
2144 | /* upper 16 bits of register SPI_FW_STATUS */ | 3144 | MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val); |
2145 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2); | 3145 | val &= ~(1<<13); |
3146 | bnx2x_cl45_write(bp, phy, | ||
3147 | MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val); | ||
2146 | 3148 | ||
2147 | bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1, | 3149 | /* PLL controls */ |
2148 | phy->ver_addr); | 3150 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805E, 0x1077); |
3151 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805D, 0x0000); | ||
3152 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805C, 0x030B); | ||
3153 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805B, 0x1240); | ||
3154 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805A, 0x2490); | ||
3155 | |||
3156 | /* Tx Controls */ | ||
3157 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A7, 0x0C74); | ||
3158 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A6, 0x9041); | ||
3159 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A5, 0x4640); | ||
3160 | |||
3161 | /* Rx Controls */ | ||
3162 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FE, 0x01C4); | ||
3163 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FD, 0x9249); | ||
3164 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FC, 0x2015); | ||
3165 | |||
3166 | /* Enable PLL sequencer (use read-modify-write to set bit 13) */ | ||
3167 | bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val); | ||
3168 | val |= (1<<13); | ||
3169 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val); | ||
2149 | } | 3170 | } |
3171 | |||
3172 | /******************************************************************/ | ||
3173 | /* BCM8073 PHY SECTION */ | ||
3174 | /******************************************************************/ | ||
2150 | static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy) | 3175 | static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy) |
2151 | { | 3176 | { |
2152 | /* This is only required for 8073A1, version 102 only */ | 3177 | /* This is only required for 8073A1, version 102 only */ |
@@ -2172,6 +3197,7 @@ static u8 bnx2x_8073_is_snr_needed(struct bnx2x *bp, struct bnx2x_phy *phy) | |||
2172 | 3197 | ||
2173 | return 1; | 3198 | return 1; |
2174 | } | 3199 | } |
3200 | |||
2175 | static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy) | 3201 | static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy) |
2176 | { | 3202 | { |
2177 | u16 val, cnt, cnt1 ; | 3203 | u16 val, cnt, cnt1 ; |
@@ -2225,87 +3251,374 @@ static u8 bnx2x_8073_xaui_wa(struct bnx2x *bp, struct bnx2x_phy *phy) | |||
2225 | return -EINVAL; | 3251 | return -EINVAL; |
2226 | } | 3252 | } |
2227 | 3253 | ||
2228 | static void bnx2x_8073_8727_external_rom_boot(struct bnx2x *bp, | 3254 | static void bnx2x_807x_force_10G(struct bnx2x *bp, struct bnx2x_phy *phy) |
2229 | struct bnx2x_phy *phy, | ||
2230 | u8 port) | ||
2231 | { | 3255 | { |
2232 | /* Boot port from external ROM */ | 3256 | /* Force KR or KX */ |
2233 | /* EDC grst */ | ||
2234 | bnx2x_cl45_write(bp, phy, | 3257 | bnx2x_cl45_write(bp, phy, |
2235 | MDIO_PMA_DEVAD, | 3258 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040); |
2236 | MDIO_PMA_REG_GEN_CTRL, | ||
2237 | 0x0001); | ||
2238 | |||
2239 | /* ucode reboot and rst */ | ||
2240 | bnx2x_cl45_write(bp, phy, | 3259 | bnx2x_cl45_write(bp, phy, |
2241 | MDIO_PMA_DEVAD, | 3260 | MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b); |
2242 | MDIO_PMA_REG_GEN_CTRL, | ||
2243 | 0x008c); | ||
2244 | |||
2245 | bnx2x_cl45_write(bp, phy, | 3261 | bnx2x_cl45_write(bp, phy, |
2246 | MDIO_PMA_DEVAD, | 3262 | MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000); |
2247 | MDIO_PMA_REG_MISC_CTRL1, 0x0001); | ||
2248 | |||
2249 | /* Reset internal microprocessor */ | ||
2250 | bnx2x_cl45_write(bp, phy, | 3263 | bnx2x_cl45_write(bp, phy, |
2251 | MDIO_PMA_DEVAD, | 3264 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000); |
2252 | MDIO_PMA_REG_GEN_CTRL, | 3265 | } |
2253 | MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); | ||
2254 | 3266 | ||
2255 | /* Release srst bit */ | 3267 | static void bnx2x_8073_set_pause_cl37(struct link_params *params, |
2256 | bnx2x_cl45_write(bp, phy, | 3268 | struct bnx2x_phy *phy, |
2257 | MDIO_PMA_DEVAD, | 3269 | struct link_vars *vars) |
2258 | MDIO_PMA_REG_GEN_CTRL, | 3270 | { |
2259 | MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); | 3271 | u16 cl37_val; |
3272 | struct bnx2x *bp = params->bp; | ||
3273 | bnx2x_cl45_read(bp, phy, | ||
3274 | MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val); | ||
2260 | 3275 | ||
2261 | /* wait for 120ms for code download via SPI port */ | 3276 | cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; |
2262 | msleep(120); | 3277 | /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ |
3278 | bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); | ||
3279 | if ((vars->ieee_fc & | ||
3280 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) == | ||
3281 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) { | ||
3282 | cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC; | ||
3283 | } | ||
3284 | if ((vars->ieee_fc & | ||
3285 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == | ||
3286 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { | ||
3287 | cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | ||
3288 | } | ||
3289 | if ((vars->ieee_fc & | ||
3290 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == | ||
3291 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { | ||
3292 | cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | ||
3293 | } | ||
3294 | DP(NETIF_MSG_LINK, | ||
3295 | "Ext phy AN advertize cl37 0x%x\n", cl37_val); | ||
2263 | 3296 | ||
2264 | /* Clear ser_boot_ctl bit */ | ||
2265 | bnx2x_cl45_write(bp, phy, | 3297 | bnx2x_cl45_write(bp, phy, |
2266 | MDIO_PMA_DEVAD, | 3298 | MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val); |
2267 | MDIO_PMA_REG_MISC_CTRL1, 0x0000); | 3299 | msleep(500); |
2268 | bnx2x_save_bcm_spirom_ver(bp, phy, port); | ||
2269 | } | 3300 | } |
2270 | 3301 | ||
2271 | static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy, | 3302 | static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy, |
2272 | struct link_params *params) | 3303 | struct link_params *params, |
3304 | struct link_vars *vars) | ||
2273 | { | 3305 | { |
2274 | struct bnx2x *bp = params->bp; | 3306 | struct bnx2x *bp = params->bp; |
2275 | /* Need to wait 100ms after reset */ | 3307 | u16 val = 0, tmp1; |
2276 | msleep(100); | 3308 | u8 gpio_port; |
3309 | DP(NETIF_MSG_LINK, "Init 8073\n"); | ||
2277 | 3310 | ||
2278 | /* Micro controller re-boot */ | 3311 | gpio_port = params->port; |
2279 | bnx2x_cl45_write(bp, phy, | 3312 | /* Restore normal power mode*/ |
2280 | MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B); | 3313 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, |
3314 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port); | ||
2281 | 3315 | ||
2282 | /* Set soft reset */ | 3316 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, |
2283 | bnx2x_cl45_write(bp, phy, | 3317 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port); |
2284 | MDIO_PMA_DEVAD, | ||
2285 | MDIO_PMA_REG_GEN_CTRL, | ||
2286 | MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); | ||
2287 | 3318 | ||
3319 | /* enable LASI */ | ||
2288 | bnx2x_cl45_write(bp, phy, | 3320 | bnx2x_cl45_write(bp, phy, |
2289 | MDIO_PMA_DEVAD, | 3321 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2)); |
2290 | MDIO_PMA_REG_MISC_CTRL1, 0x0001); | 3322 | bnx2x_cl45_write(bp, phy, |
3323 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x0004); | ||
3324 | |||
3325 | bnx2x_8073_set_pause_cl37(params, phy, vars); | ||
3326 | |||
3327 | bnx2x_8073_set_xaui_low_power_mode(bp, phy); | ||
3328 | |||
3329 | bnx2x_cl45_read(bp, phy, | ||
3330 | MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1); | ||
2291 | 3331 | ||
3332 | bnx2x_cl45_read(bp, phy, | ||
3333 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1); | ||
3334 | |||
3335 | DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1); | ||
3336 | |||
3337 | /* Enable CL37 BAM */ | ||
3338 | bnx2x_cl45_read(bp, phy, | ||
3339 | MDIO_AN_DEVAD, | ||
3340 | MDIO_AN_REG_8073_BAM, &val); | ||
2292 | bnx2x_cl45_write(bp, phy, | 3341 | bnx2x_cl45_write(bp, phy, |
2293 | MDIO_PMA_DEVAD, | 3342 | MDIO_AN_DEVAD, |
2294 | MDIO_PMA_REG_GEN_CTRL, | 3343 | MDIO_AN_REG_8073_BAM, val | 1); |
2295 | MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); | ||
2296 | 3344 | ||
2297 | /* wait for 150ms for microcode load */ | 3345 | if (params->loopback_mode == LOOPBACK_EXT) { |
2298 | msleep(150); | 3346 | bnx2x_807x_force_10G(bp, phy); |
3347 | DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n"); | ||
3348 | return 0; | ||
3349 | } else { | ||
3350 | bnx2x_cl45_write(bp, phy, | ||
3351 | MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002); | ||
3352 | } | ||
3353 | if (phy->req_line_speed != SPEED_AUTO_NEG) { | ||
3354 | if (phy->req_line_speed == SPEED_10000) { | ||
3355 | val = (1<<7); | ||
3356 | } else if (phy->req_line_speed == SPEED_2500) { | ||
3357 | val = (1<<5); | ||
3358 | /* Note that 2.5G works only | ||
3359 | when used with 1G advertisment */ | ||
3360 | } else | ||
3361 | val = (1<<5); | ||
3362 | } else { | ||
3363 | val = 0; | ||
3364 | if (phy->speed_cap_mask & | ||
3365 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) | ||
3366 | val |= (1<<7); | ||
3367 | |||
3368 | /* Note that 2.5G works only when | ||
3369 | used with 1G advertisment */ | ||
3370 | if (phy->speed_cap_mask & | ||
3371 | (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G | | ||
3372 | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) | ||
3373 | val |= (1<<5); | ||
3374 | DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val); | ||
3375 | } | ||
3376 | |||
3377 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val); | ||
3378 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1); | ||
3379 | |||
3380 | if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) && | ||
3381 | (phy->req_line_speed == SPEED_AUTO_NEG)) || | ||
3382 | (phy->req_line_speed == SPEED_2500)) { | ||
3383 | u16 phy_ver; | ||
3384 | /* Allow 2.5G for A1 and above */ | ||
3385 | bnx2x_cl45_read(bp, phy, | ||
3386 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, | ||
3387 | &phy_ver); | ||
3388 | DP(NETIF_MSG_LINK, "Add 2.5G\n"); | ||
3389 | if (phy_ver > 0) | ||
3390 | tmp1 |= 1; | ||
3391 | else | ||
3392 | tmp1 &= 0xfffe; | ||
3393 | } else { | ||
3394 | DP(NETIF_MSG_LINK, "Disable 2.5G\n"); | ||
3395 | tmp1 &= 0xfffe; | ||
3396 | } | ||
3397 | |||
3398 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1); | ||
3399 | /* Add support for CL37 (passive mode) II */ | ||
3400 | |||
3401 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1); | ||
3402 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, | ||
3403 | (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ? | ||
3404 | 0x20 : 0x40))); | ||
3405 | |||
3406 | /* Add support for CL37 (passive mode) III */ | ||
3407 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000); | ||
3408 | |||
3409 | /* The SNR will improve about 2db by changing | ||
3410 | BW and FEE main tap. Rest commands are executed | ||
3411 | after link is up*/ | ||
3412 | if (bnx2x_8073_is_snr_needed(bp, phy)) | ||
3413 | bnx2x_cl45_write(bp, phy, | ||
3414 | MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN, | ||
3415 | 0xFB0C); | ||
3416 | |||
3417 | /* Enable FEC (Forware Error Correction) Request in the AN */ | ||
3418 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1); | ||
3419 | tmp1 |= (1<<15); | ||
3420 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1); | ||
3421 | |||
3422 | bnx2x_ext_phy_set_pause(params, phy, vars); | ||
3423 | |||
3424 | /* Restart autoneg */ | ||
3425 | msleep(500); | ||
3426 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200); | ||
3427 | DP(NETIF_MSG_LINK, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n", | ||
3428 | ((val & (1<<5)) > 0), ((val & (1<<7)) > 0)); | ||
3429 | return 0; | ||
3430 | } | ||
3431 | |||
3432 | static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy, | ||
3433 | struct link_params *params, | ||
3434 | struct link_vars *vars) | ||
3435 | { | ||
3436 | struct bnx2x *bp = params->bp; | ||
3437 | u8 link_up = 0; | ||
3438 | u16 val1, val2; | ||
3439 | u16 link_status = 0; | ||
3440 | u16 an1000_status = 0; | ||
3441 | |||
3442 | bnx2x_cl45_read(bp, phy, | ||
3443 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1); | ||
3444 | |||
3445 | DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1); | ||
3446 | |||
3447 | /* clear the interrupt LASI status register */ | ||
3448 | bnx2x_cl45_read(bp, phy, | ||
3449 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2); | ||
3450 | bnx2x_cl45_read(bp, phy, | ||
3451 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1); | ||
3452 | DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n", val2, val1); | ||
3453 | /* Clear MSG-OUT */ | ||
3454 | bnx2x_cl45_read(bp, phy, | ||
3455 | MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1); | ||
3456 | |||
3457 | /* Check the LASI */ | ||
3458 | bnx2x_cl45_read(bp, phy, | ||
3459 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2); | ||
3460 | |||
3461 | DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2); | ||
3462 | |||
3463 | /* Check the link status */ | ||
3464 | bnx2x_cl45_read(bp, phy, | ||
3465 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2); | ||
3466 | DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2); | ||
3467 | |||
3468 | bnx2x_cl45_read(bp, phy, | ||
3469 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); | ||
3470 | bnx2x_cl45_read(bp, phy, | ||
3471 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); | ||
3472 | link_up = ((val1 & 4) == 4); | ||
3473 | DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1); | ||
3474 | |||
3475 | if (link_up && | ||
3476 | ((phy->req_line_speed != SPEED_10000))) { | ||
3477 | if (bnx2x_8073_xaui_wa(bp, phy) != 0) | ||
3478 | return 0; | ||
3479 | } | ||
3480 | bnx2x_cl45_read(bp, phy, | ||
3481 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status); | ||
3482 | bnx2x_cl45_read(bp, phy, | ||
3483 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status); | ||
3484 | |||
3485 | /* Check the link status on 1.1.2 */ | ||
3486 | bnx2x_cl45_read(bp, phy, | ||
3487 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); | ||
3488 | bnx2x_cl45_read(bp, phy, | ||
3489 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); | ||
3490 | DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x," | ||
3491 | "an_link_status=0x%x\n", val2, val1, an1000_status); | ||
3492 | |||
3493 | link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1))); | ||
3494 | if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) { | ||
3495 | /* The SNR will improve about 2dbby | ||
3496 | changing the BW and FEE main tap.*/ | ||
3497 | /* The 1st write to change FFE main | ||
3498 | tap is set before restart AN */ | ||
3499 | /* Change PLL Bandwidth in EDC | ||
3500 | register */ | ||
3501 | bnx2x_cl45_write(bp, phy, | ||
3502 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH, | ||
3503 | 0x26BC); | ||
3504 | |||
3505 | /* Change CDR Bandwidth in EDC register */ | ||
3506 | bnx2x_cl45_write(bp, phy, | ||
3507 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH, | ||
3508 | 0x0333); | ||
3509 | } | ||
3510 | bnx2x_cl45_read(bp, phy, | ||
3511 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS, | ||
3512 | &link_status); | ||
3513 | |||
3514 | /* Bits 0..2 --> speed detected, bits 13..15--> link is down */ | ||
3515 | if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) { | ||
3516 | link_up = 1; | ||
3517 | vars->line_speed = SPEED_10000; | ||
3518 | DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n", | ||
3519 | params->port); | ||
3520 | } else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) { | ||
3521 | link_up = 1; | ||
3522 | vars->line_speed = SPEED_2500; | ||
3523 | DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n", | ||
3524 | params->port); | ||
3525 | } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) { | ||
3526 | link_up = 1; | ||
3527 | vars->line_speed = SPEED_1000; | ||
3528 | DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n", | ||
3529 | params->port); | ||
3530 | } else { | ||
3531 | link_up = 0; | ||
3532 | DP(NETIF_MSG_LINK, "port %x: External link is down\n", | ||
3533 | params->port); | ||
3534 | } | ||
3535 | |||
3536 | if (link_up) { | ||
3537 | bnx2x_ext_phy_10G_an_resolve(bp, phy, vars); | ||
3538 | bnx2x_8073_resolve_fc(phy, params, vars); | ||
3539 | } | ||
3540 | return link_up; | ||
3541 | } | ||
3542 | |||
3543 | static void bnx2x_8073_link_reset(struct bnx2x_phy *phy, | ||
3544 | struct link_params *params) | ||
3545 | { | ||
3546 | struct bnx2x *bp = params->bp; | ||
3547 | u8 gpio_port; | ||
3548 | gpio_port = params->port; | ||
3549 | DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n", | ||
3550 | gpio_port); | ||
3551 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
3552 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
3553 | gpio_port); | ||
3554 | } | ||
3555 | |||
3556 | /******************************************************************/ | ||
3557 | /* BCM8705 PHY SECTION */ | ||
3558 | /******************************************************************/ | ||
3559 | static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy, | ||
3560 | struct link_params *params, | ||
3561 | struct link_vars *vars) | ||
3562 | { | ||
3563 | struct bnx2x *bp = params->bp; | ||
3564 | DP(NETIF_MSG_LINK, "init 8705\n"); | ||
3565 | /* Restore normal power mode*/ | ||
3566 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
3567 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | ||
3568 | /* HW reset */ | ||
3569 | bnx2x_ext_phy_hw_reset(bp, params->port); | ||
3570 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040); | ||
3571 | bnx2x_wait_reset_complete(bp, phy); | ||
2299 | 3572 | ||
2300 | /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */ | ||
2301 | bnx2x_cl45_write(bp, phy, | 3573 | bnx2x_cl45_write(bp, phy, |
2302 | MDIO_PMA_DEVAD, | 3574 | MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288); |
2303 | MDIO_PMA_REG_MISC_CTRL1, 0x0000); | 3575 | bnx2x_cl45_write(bp, phy, |
3576 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf); | ||
3577 | bnx2x_cl45_write(bp, phy, | ||
3578 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100); | ||
3579 | bnx2x_cl45_write(bp, phy, | ||
3580 | MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1); | ||
3581 | /* BCM8705 doesn't have microcode, hence the 0 */ | ||
3582 | bnx2x_save_spirom_version(bp, params->port, params->shmem_base, 0); | ||
3583 | return 0; | ||
3584 | } | ||
2304 | 3585 | ||
2305 | msleep(200); | 3586 | static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy, |
2306 | bnx2x_save_bcm_spirom_ver(bp, phy, params->port); | 3587 | struct link_params *params, |
3588 | struct link_vars *vars) | ||
3589 | { | ||
3590 | u8 link_up = 0; | ||
3591 | u16 val1, rx_sd; | ||
3592 | struct bnx2x *bp = params->bp; | ||
3593 | DP(NETIF_MSG_LINK, "read status 8705\n"); | ||
3594 | bnx2x_cl45_read(bp, phy, | ||
3595 | MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1); | ||
3596 | DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); | ||
3597 | |||
3598 | bnx2x_cl45_read(bp, phy, | ||
3599 | MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1); | ||
3600 | DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); | ||
3601 | |||
3602 | bnx2x_cl45_read(bp, phy, | ||
3603 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd); | ||
3604 | |||
3605 | bnx2x_cl45_read(bp, phy, | ||
3606 | MDIO_PMA_DEVAD, 0xc809, &val1); | ||
3607 | bnx2x_cl45_read(bp, phy, | ||
3608 | MDIO_PMA_DEVAD, 0xc809, &val1); | ||
3609 | |||
3610 | DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1); | ||
3611 | link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0)); | ||
3612 | if (link_up) { | ||
3613 | vars->line_speed = SPEED_10000; | ||
3614 | bnx2x_ext_phy_resolve_fc(phy, params, vars); | ||
3615 | } | ||
3616 | return link_up; | ||
2307 | } | 3617 | } |
2308 | 3618 | ||
3619 | /******************************************************************/ | ||
3620 | /* SFP+ module Section */ | ||
3621 | /******************************************************************/ | ||
2309 | static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, | 3622 | static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, |
2310 | struct bnx2x_phy *phy, | 3623 | struct bnx2x_phy *phy, |
2311 | u8 port, | 3624 | u8 port, |
@@ -2392,7 +3705,7 @@ static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy, | |||
2392 | MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); | 3705 | MDIO_PMA_REG_SFP_TWO_WIRE_CTRL, &val); |
2393 | if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == | 3706 | if ((val & MDIO_PMA_REG_SFP_TWO_WIRE_CTRL_STATUS_MASK) == |
2394 | MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) | 3707 | MDIO_PMA_REG_SFP_TWO_WIRE_STATUS_IDLE) |
2395 | return 0; | 3708 | return 0;; |
2396 | msleep(1); | 3709 | msleep(1); |
2397 | } | 3710 | } |
2398 | return -EINVAL; | 3711 | return -EINVAL; |
@@ -2637,6 +3950,64 @@ static u8 bnx2x_verify_sfp_module(struct bnx2x_phy *phy, | |||
2637 | return -EINVAL; | 3950 | return -EINVAL; |
2638 | } | 3951 | } |
2639 | 3952 | ||
3953 | static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, | ||
3954 | struct link_params *params) | ||
3955 | |||
3956 | { | ||
3957 | u8 val; | ||
3958 | struct bnx2x *bp = params->bp; | ||
3959 | u16 timeout; | ||
3960 | /* Initialization time after hot-plug may take up to 300ms for some | ||
3961 | phys type ( e.g. JDSU ) */ | ||
3962 | for (timeout = 0; timeout < 60; timeout++) { | ||
3963 | if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) | ||
3964 | == 0) { | ||
3965 | DP(NETIF_MSG_LINK, "SFP+ module initialization " | ||
3966 | "took %d ms\n", timeout * 5); | ||
3967 | return 0; | ||
3968 | } | ||
3969 | msleep(5); | ||
3970 | } | ||
3971 | return -EINVAL; | ||
3972 | } | ||
3973 | |||
3974 | static void bnx2x_8727_power_module(struct bnx2x *bp, | ||
3975 | struct bnx2x_phy *phy, | ||
3976 | u8 is_power_up) { | ||
3977 | /* Make sure GPIOs are not using for LED mode */ | ||
3978 | u16 val; | ||
3979 | /* | ||
3980 | * In the GPIO register, bit 4 is use to detemine if the GPIOs are | ||
3981 | * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for | ||
3982 | * output | ||
3983 | * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0 | ||
3984 | * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1 | ||
3985 | * where the 1st bit is the over-current(only input), and 2nd bit is | ||
3986 | * for power( only output ) | ||
3987 | */ | ||
3988 | |||
3989 | /* | ||
3990 | * In case of NOC feature is disabled and power is up, set GPIO control | ||
3991 | * as input to enable listening of over-current indication | ||
3992 | */ | ||
3993 | if (phy->flags & FLAGS_NOC) | ||
3994 | return; | ||
3995 | if (!(phy->flags & | ||
3996 | FLAGS_NOC) && is_power_up) | ||
3997 | val = (1<<4); | ||
3998 | else | ||
3999 | /* | ||
4000 | * Set GPIO control to OUTPUT, and set the power bit | ||
4001 | * to according to the is_power_up | ||
4002 | */ | ||
4003 | val = ((!(is_power_up)) << 1); | ||
4004 | |||
4005 | bnx2x_cl45_write(bp, phy, | ||
4006 | MDIO_PMA_DEVAD, | ||
4007 | MDIO_PMA_REG_8727_GPIO_CTRL, | ||
4008 | val); | ||
4009 | } | ||
4010 | |||
2640 | static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp, | 4011 | static u8 bnx2x_8726_set_limiting_mode(struct bnx2x *bp, |
2641 | struct bnx2x_phy *phy, | 4012 | struct bnx2x_phy *phy, |
2642 | u16 edc_mode) | 4013 | u16 edc_mode) |
@@ -2721,65 +4092,6 @@ static u8 bnx2x_8727_set_limiting_mode(struct bnx2x *bp, | |||
2721 | return 0; | 4092 | return 0; |
2722 | } | 4093 | } |
2723 | 4094 | ||
2724 | |||
2725 | static u8 bnx2x_wait_for_sfp_module_initialized(struct bnx2x_phy *phy, | ||
2726 | struct link_params *params) | ||
2727 | |||
2728 | { | ||
2729 | u8 val; | ||
2730 | struct bnx2x *bp = params->bp; | ||
2731 | u16 timeout; | ||
2732 | /* Initialization time after hot-plug may take up to 300ms for some | ||
2733 | phys type ( e.g. JDSU ) */ | ||
2734 | for (timeout = 0; timeout < 60; timeout++) { | ||
2735 | if (bnx2x_read_sfp_module_eeprom(phy, params, 1, 1, &val) | ||
2736 | == 0) { | ||
2737 | DP(NETIF_MSG_LINK, "SFP+ module initialization " | ||
2738 | "took %d ms\n", timeout * 5); | ||
2739 | return 0; | ||
2740 | } | ||
2741 | msleep(5); | ||
2742 | } | ||
2743 | return -EINVAL; | ||
2744 | } | ||
2745 | |||
2746 | static void bnx2x_8727_power_module(struct bnx2x *bp, | ||
2747 | struct bnx2x_phy *phy, | ||
2748 | u8 is_power_up) { | ||
2749 | /* Make sure GPIOs are not using for LED mode */ | ||
2750 | u16 val; | ||
2751 | /* | ||
2752 | * In the GPIO register, bit 4 is use to detemine if the GPIOs are | ||
2753 | * operating as INPUT or as OUTPUT. Bit 1 is for input, and 0 for | ||
2754 | * output | ||
2755 | * Bits 0-1 determine the gpios value for OUTPUT in case bit 4 val is 0 | ||
2756 | * Bits 8-9 determine the gpios value for INPUT in case bit 4 val is 1 | ||
2757 | * where the 1st bit is the over-current(only input), and 2nd bit is | ||
2758 | * for power( only output ) | ||
2759 | */ | ||
2760 | |||
2761 | /* | ||
2762 | * In case of NOC feature is disabled and power is up, set GPIO control | ||
2763 | * as input to enable listening of over-current indication | ||
2764 | */ | ||
2765 | if (phy->flags & FLAGS_NOC) | ||
2766 | return; | ||
2767 | if (!(phy->flags & | ||
2768 | FLAGS_NOC) && is_power_up) | ||
2769 | val = (1<<4); | ||
2770 | else | ||
2771 | /* | ||
2772 | * Set GPIO control to OUTPUT, and set the power bit | ||
2773 | * to according to the is_power_up | ||
2774 | */ | ||
2775 | val = ((!(is_power_up)) << 1); | ||
2776 | |||
2777 | bnx2x_cl45_write(bp, phy, | ||
2778 | MDIO_PMA_DEVAD, | ||
2779 | MDIO_PMA_REG_8727_GPIO_CTRL, | ||
2780 | val); | ||
2781 | } | ||
2782 | |||
2783 | static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, | 4095 | static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, |
2784 | struct link_params *params) | 4096 | struct link_params *params) |
2785 | { | 4097 | { |
@@ -2889,276 +4201,56 @@ void bnx2x_handle_module_detect_int(struct link_params *params) | |||
2889 | } | 4201 | } |
2890 | } | 4202 | } |
2891 | 4203 | ||
2892 | static void bnx2x_807x_force_10G(struct bnx2x *bp, struct bnx2x_phy *phy) | 4204 | /******************************************************************/ |
2893 | { | 4205 | /* common BCM8706/BCM8726 PHY SECTION */ |
2894 | /* Force KR or KX */ | 4206 | /******************************************************************/ |
2895 | bnx2x_cl45_write(bp, phy, | 4207 | static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy, |
2896 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x2040); | 4208 | struct link_params *params, |
2897 | bnx2x_cl45_write(bp, phy, | ||
2898 | MDIO_PMA_DEVAD, MDIO_PMA_REG_10G_CTRL2, 0x000b); | ||
2899 | bnx2x_cl45_write(bp, phy, | ||
2900 | MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0000); | ||
2901 | bnx2x_cl45_write(bp, phy, | ||
2902 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x0000); | ||
2903 | } | ||
2904 | |||
2905 | static void bnx2x_8073_set_xaui_low_power_mode(struct bnx2x *bp, | ||
2906 | struct bnx2x_phy *phy) | ||
2907 | { | ||
2908 | u16 val; | ||
2909 | bnx2x_cl45_read(bp, phy, | ||
2910 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, &val); | ||
2911 | |||
2912 | if (val == 0) { | ||
2913 | /* Mustn't set low power mode in 8073 A0 */ | ||
2914 | return; | ||
2915 | } | ||
2916 | |||
2917 | /* Disable PLL sequencer (use read-modify-write to clear bit 13) */ | ||
2918 | bnx2x_cl45_read(bp, phy, | ||
2919 | MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val); | ||
2920 | val &= ~(1<<13); | ||
2921 | bnx2x_cl45_write(bp, phy, | ||
2922 | MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val); | ||
2923 | |||
2924 | /* PLL controls */ | ||
2925 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805E, 0x1077); | ||
2926 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805D, 0x0000); | ||
2927 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805C, 0x030B); | ||
2928 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805B, 0x1240); | ||
2929 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x805A, 0x2490); | ||
2930 | |||
2931 | /* Tx Controls */ | ||
2932 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A7, 0x0C74); | ||
2933 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A6, 0x9041); | ||
2934 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80A5, 0x4640); | ||
2935 | |||
2936 | /* Rx Controls */ | ||
2937 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FE, 0x01C4); | ||
2938 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FD, 0x9249); | ||
2939 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, 0x80FC, 0x2015); | ||
2940 | |||
2941 | /* Enable PLL sequencer (use read-modify-write to set bit 13) */ | ||
2942 | bnx2x_cl45_read(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, &val); | ||
2943 | val |= (1<<13); | ||
2944 | bnx2x_cl45_write(bp, phy, MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val); | ||
2945 | } | ||
2946 | |||
2947 | static void bnx2x_8073_set_pause_cl37(struct link_params *params, | ||
2948 | struct bnx2x_phy *phy, | ||
2949 | struct link_vars *vars) | 4209 | struct link_vars *vars) |
2950 | { | 4210 | { |
2951 | u16 cl37_val; | 4211 | u8 link_up = 0; |
4212 | u16 val1, val2, rx_sd, pcs_status; | ||
2952 | struct bnx2x *bp = params->bp; | 4213 | struct bnx2x *bp = params->bp; |
4214 | DP(NETIF_MSG_LINK, "XGXS 8706/8726\n"); | ||
4215 | /* Clear RX Alarm*/ | ||
2953 | bnx2x_cl45_read(bp, phy, | 4216 | bnx2x_cl45_read(bp, phy, |
2954 | MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &cl37_val); | 4217 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2); |
2955 | 4218 | /* clear LASI indication*/ | |
2956 | cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | ||
2957 | /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ | ||
2958 | bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); | ||
2959 | if ((vars->ieee_fc & | ||
2960 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) == | ||
2961 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) { | ||
2962 | cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC; | ||
2963 | } | ||
2964 | if ((vars->ieee_fc & | ||
2965 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == | ||
2966 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { | ||
2967 | cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC; | ||
2968 | } | ||
2969 | if ((vars->ieee_fc & | ||
2970 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == | ||
2971 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { | ||
2972 | cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH; | ||
2973 | } | ||
2974 | DP(NETIF_MSG_LINK, | ||
2975 | "Ext phy AN advertize cl37 0x%x\n", cl37_val); | ||
2976 | |||
2977 | bnx2x_cl45_write(bp, phy, | ||
2978 | MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, cl37_val); | ||
2979 | msleep(500); | ||
2980 | } | ||
2981 | |||
2982 | static void bnx2x_ext_phy_set_pause(struct link_params *params, | ||
2983 | struct bnx2x_phy *phy, | ||
2984 | struct link_vars *vars) | ||
2985 | { | ||
2986 | u16 val; | ||
2987 | struct bnx2x *bp = params->bp; | ||
2988 | /* read modify write pause advertizing */ | ||
2989 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, &val); | ||
2990 | |||
2991 | val &= ~MDIO_AN_REG_ADV_PAUSE_BOTH; | ||
2992 | |||
2993 | /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */ | ||
2994 | bnx2x_calc_ieee_aneg_adv(phy, params, &vars->ieee_fc); | ||
2995 | if ((vars->ieee_fc & | ||
2996 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) == | ||
2997 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) { | ||
2998 | val |= MDIO_AN_REG_ADV_PAUSE_ASYMMETRIC; | ||
2999 | } | ||
3000 | if ((vars->ieee_fc & | ||
3001 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) == | ||
3002 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) { | ||
3003 | val |= MDIO_AN_REG_ADV_PAUSE_PAUSE; | ||
3004 | } | ||
3005 | DP(NETIF_MSG_LINK, "Ext phy AN advertize 0x%x\n", val); | ||
3006 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV_PAUSE, val); | ||
3007 | } | ||
3008 | |||
3009 | static void bnx2x_set_preemphasis(struct bnx2x_phy *phy, | ||
3010 | struct link_params *params) | ||
3011 | { | ||
3012 | |||
3013 | u16 bank, i = 0; | ||
3014 | struct bnx2x *bp = params->bp; | ||
3015 | |||
3016 | for (bank = MDIO_REG_BANK_RX0, i = 0; bank <= MDIO_REG_BANK_RX3; | ||
3017 | bank += (MDIO_REG_BANK_RX1-MDIO_REG_BANK_RX0), i++) { | ||
3018 | CL45_WR_OVER_CL22(bp, phy, | ||
3019 | bank, | ||
3020 | MDIO_RX0_RX_EQ_BOOST, | ||
3021 | phy->rx_preemphasis[i]); | ||
3022 | } | ||
3023 | |||
3024 | for (bank = MDIO_REG_BANK_TX0, i = 0; bank <= MDIO_REG_BANK_TX3; | ||
3025 | bank += (MDIO_REG_BANK_TX1 - MDIO_REG_BANK_TX0), i++) { | ||
3026 | CL45_WR_OVER_CL22(bp, phy, | ||
3027 | bank, | ||
3028 | MDIO_TX0_TX_DRIVER, | ||
3029 | phy->tx_preemphasis[i]); | ||
3030 | } | ||
3031 | } | ||
3032 | |||
3033 | static void bnx2x_848xx_set_led(struct bnx2x *bp, | ||
3034 | struct bnx2x_phy *phy) | ||
3035 | { | ||
3036 | u16 val; | ||
3037 | |||
3038 | /* PHYC_CTL_LED_CTL */ | ||
3039 | bnx2x_cl45_read(bp, phy, | 4219 | bnx2x_cl45_read(bp, phy, |
3040 | MDIO_PMA_DEVAD, | 4220 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1); |
3041 | MDIO_PMA_REG_8481_LINK_SIGNAL, &val); | 4221 | bnx2x_cl45_read(bp, phy, |
3042 | val &= 0xFE00; | 4222 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2); |
3043 | val |= 0x0092; | 4223 | DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2); |
3044 | |||
3045 | bnx2x_cl45_write(bp, phy, | ||
3046 | MDIO_PMA_DEVAD, | ||
3047 | MDIO_PMA_REG_8481_LINK_SIGNAL, val); | ||
3048 | |||
3049 | bnx2x_cl45_write(bp, phy, | ||
3050 | MDIO_PMA_DEVAD, | ||
3051 | MDIO_PMA_REG_8481_LED1_MASK, | ||
3052 | 0x80); | ||
3053 | |||
3054 | bnx2x_cl45_write(bp, phy, | ||
3055 | MDIO_PMA_DEVAD, | ||
3056 | MDIO_PMA_REG_8481_LED2_MASK, | ||
3057 | 0x18); | ||
3058 | |||
3059 | bnx2x_cl45_write(bp, phy, | ||
3060 | MDIO_PMA_DEVAD, | ||
3061 | MDIO_PMA_REG_8481_LED3_MASK, | ||
3062 | 0x0040); | ||
3063 | |||
3064 | /* 'Interrupt Mask' */ | ||
3065 | bnx2x_cl45_write(bp, phy, | ||
3066 | MDIO_AN_DEVAD, | ||
3067 | 0xFFFB, 0xFFFD); | ||
3068 | } | ||
3069 | |||
3070 | static void bnx2x_init_internal_phy(struct bnx2x_phy *phy, | ||
3071 | struct link_params *params, | ||
3072 | struct link_vars *vars) | ||
3073 | { | ||
3074 | struct bnx2x *bp = params->bp; | ||
3075 | u8 enable_cl73 = (SINGLE_MEDIA_DIRECT(params) || | ||
3076 | (params->loopback_mode == LOOPBACK_XGXS_10)); | ||
3077 | if (!(vars->phy_flags & PHY_SGMII_FLAG)) { | ||
3078 | if (SINGLE_MEDIA_DIRECT(params) && | ||
3079 | (params->feature_config_flags & | ||
3080 | FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED)) | ||
3081 | bnx2x_set_preemphasis(phy, params); | ||
3082 | |||
3083 | /* forced speed requested? */ | ||
3084 | if (vars->line_speed != SPEED_AUTO_NEG || | ||
3085 | (SINGLE_MEDIA_DIRECT(params) && | ||
3086 | params->loopback_mode == LOOPBACK_EXT)) { | ||
3087 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); | ||
3088 | |||
3089 | /* disable autoneg */ | ||
3090 | bnx2x_set_autoneg(phy, params, vars, 0); | ||
3091 | |||
3092 | /* program speed and duplex */ | ||
3093 | bnx2x_program_serdes(phy, params, vars); | ||
3094 | |||
3095 | } else { /* AN_mode */ | ||
3096 | DP(NETIF_MSG_LINK, "not SGMII, AN\n"); | ||
3097 | |||
3098 | /* AN enabled */ | ||
3099 | bnx2x_set_brcm_cl37_advertisment(phy, params); | ||
3100 | |||
3101 | /* program duplex & pause advertisement (for aneg) */ | ||
3102 | bnx2x_set_ieee_aneg_advertisment(phy, params, | ||
3103 | vars->ieee_fc); | ||
3104 | |||
3105 | /* enable autoneg */ | ||
3106 | bnx2x_set_autoneg(phy, params, vars, enable_cl73); | ||
3107 | |||
3108 | /* enable and restart AN */ | ||
3109 | bnx2x_restart_autoneg(phy, params, enable_cl73); | ||
3110 | } | ||
3111 | |||
3112 | } else { /* SGMII mode */ | ||
3113 | DP(NETIF_MSG_LINK, "SGMII\n"); | ||
3114 | 4224 | ||
3115 | bnx2x_initialize_sgmii_process(phy, params, vars); | 4225 | bnx2x_cl45_read(bp, phy, |
3116 | } | 4226 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd); |
3117 | } | 4227 | bnx2x_cl45_read(bp, phy, |
4228 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status); | ||
4229 | bnx2x_cl45_read(bp, phy, | ||
4230 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2); | ||
4231 | bnx2x_cl45_read(bp, phy, | ||
4232 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2); | ||
3118 | 4233 | ||
3119 | static u16 bnx2x_wait_reset_complete(struct bnx2x *bp, | 4234 | DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps" |
3120 | struct bnx2x_phy *phy) | 4235 | " link_status 0x%x\n", rx_sd, pcs_status, val2); |
3121 | { | 4236 | /* link is up if both bit 0 of pmd_rx_sd and |
3122 | u16 cnt, ctrl; | 4237 | * bit 0 of pcs_status are set, or if the autoneg bit |
3123 | /* Wait for soft reset to get cleared upto 1 sec */ | 4238 | * 1 is set |
3124 | for (cnt = 0; cnt < 1000; cnt++) { | 4239 | */ |
3125 | bnx2x_cl45_read(bp, phy, | 4240 | link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1))); |
3126 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, &ctrl); | 4241 | if (link_up) { |
3127 | if (!(ctrl & (1<<15))) | 4242 | if (val2 & (1<<1)) |
3128 | break; | 4243 | vars->line_speed = SPEED_1000; |
3129 | msleep(1); | 4244 | else |
4245 | vars->line_speed = SPEED_10000; | ||
4246 | bnx2x_ext_phy_resolve_fc(phy, params, vars); | ||
3130 | } | 4247 | } |
3131 | DP(NETIF_MSG_LINK, "control reg 0x%x (after %d ms)\n", ctrl, cnt); | 4248 | return link_up; |
3132 | return cnt; | ||
3133 | } | ||
3134 | |||
3135 | static u8 bnx2x_8705_config_init(struct bnx2x_phy *phy, | ||
3136 | struct link_params *params, | ||
3137 | struct link_vars *vars) | ||
3138 | { | ||
3139 | struct bnx2x *bp = params->bp; | ||
3140 | DP(NETIF_MSG_LINK, "init 8705\n"); | ||
3141 | /* Restore normal power mode*/ | ||
3142 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
3143 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | ||
3144 | /* HW reset */ | ||
3145 | bnx2x_ext_phy_hw_reset(bp, params->port); | ||
3146 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0xa040); | ||
3147 | bnx2x_wait_reset_complete(bp, phy); | ||
3148 | |||
3149 | bnx2x_cl45_write(bp, phy, | ||
3150 | MDIO_PMA_DEVAD, MDIO_PMA_REG_MISC_CTRL, 0x8288); | ||
3151 | bnx2x_cl45_write(bp, phy, | ||
3152 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, 0x7fbf); | ||
3153 | bnx2x_cl45_write(bp, phy, | ||
3154 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CMU_PLL_BYPASS, 0x0100); | ||
3155 | bnx2x_cl45_write(bp, phy, | ||
3156 | MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_CNTL, 0x1); | ||
3157 | /* BCM8705 doesn't have microcode, hence the 0 */ | ||
3158 | bnx2x_save_spirom_version(bp, params->port, params->shmem_base, 0); | ||
3159 | return 0; | ||
3160 | } | 4249 | } |
3161 | 4250 | ||
4251 | /******************************************************************/ | ||
4252 | /* BCM8706 PHY SECTION */ | ||
4253 | /******************************************************************/ | ||
3162 | static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, | 4254 | static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, |
3163 | struct link_params *params, | 4255 | struct link_params *params, |
3164 | struct link_vars *vars) | 4256 | struct link_vars *vars) |
@@ -3240,6 +4332,83 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, | |||
3240 | return 0; | 4332 | return 0; |
3241 | } | 4333 | } |
3242 | 4334 | ||
4335 | static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy, | ||
4336 | struct link_params *params, | ||
4337 | struct link_vars *vars) | ||
4338 | { | ||
4339 | return bnx2x_8706_8726_read_status(phy, params, vars); | ||
4340 | } | ||
4341 | |||
4342 | /******************************************************************/ | ||
4343 | /* BCM8726 PHY SECTION */ | ||
4344 | /******************************************************************/ | ||
4345 | static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy, | ||
4346 | struct link_params *params) | ||
4347 | { | ||
4348 | struct bnx2x *bp = params->bp; | ||
4349 | DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n"); | ||
4350 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001); | ||
4351 | } | ||
4352 | |||
4353 | static void bnx2x_8726_external_rom_boot(struct bnx2x_phy *phy, | ||
4354 | struct link_params *params) | ||
4355 | { | ||
4356 | struct bnx2x *bp = params->bp; | ||
4357 | /* Need to wait 100ms after reset */ | ||
4358 | msleep(100); | ||
4359 | |||
4360 | /* Micro controller re-boot */ | ||
4361 | bnx2x_cl45_write(bp, phy, | ||
4362 | MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x018B); | ||
4363 | |||
4364 | /* Set soft reset */ | ||
4365 | bnx2x_cl45_write(bp, phy, | ||
4366 | MDIO_PMA_DEVAD, | ||
4367 | MDIO_PMA_REG_GEN_CTRL, | ||
4368 | MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); | ||
4369 | |||
4370 | bnx2x_cl45_write(bp, phy, | ||
4371 | MDIO_PMA_DEVAD, | ||
4372 | MDIO_PMA_REG_MISC_CTRL1, 0x0001); | ||
4373 | |||
4374 | bnx2x_cl45_write(bp, phy, | ||
4375 | MDIO_PMA_DEVAD, | ||
4376 | MDIO_PMA_REG_GEN_CTRL, | ||
4377 | MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); | ||
4378 | |||
4379 | /* wait for 150ms for microcode load */ | ||
4380 | msleep(150); | ||
4381 | |||
4382 | /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */ | ||
4383 | bnx2x_cl45_write(bp, phy, | ||
4384 | MDIO_PMA_DEVAD, | ||
4385 | MDIO_PMA_REG_MISC_CTRL1, 0x0000); | ||
4386 | |||
4387 | msleep(200); | ||
4388 | bnx2x_save_bcm_spirom_ver(bp, phy, params->port); | ||
4389 | } | ||
4390 | |||
4391 | static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy, | ||
4392 | struct link_params *params, | ||
4393 | struct link_vars *vars) | ||
4394 | { | ||
4395 | struct bnx2x *bp = params->bp; | ||
4396 | u16 val1; | ||
4397 | u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars); | ||
4398 | if (link_up) { | ||
4399 | bnx2x_cl45_read(bp, phy, | ||
4400 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, | ||
4401 | &val1); | ||
4402 | if (val1 & (1<<15)) { | ||
4403 | DP(NETIF_MSG_LINK, "Tx is disabled\n"); | ||
4404 | link_up = 0; | ||
4405 | vars->line_speed = 0; | ||
4406 | } | ||
4407 | } | ||
4408 | return link_up; | ||
4409 | } | ||
4410 | |||
4411 | |||
3243 | static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy, | 4412 | static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy, |
3244 | struct link_params *params, | 4413 | struct link_params *params, |
3245 | struct link_vars *vars) | 4414 | struct link_vars *vars) |
@@ -3356,136 +4525,35 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy, | |||
3356 | 4525 | ||
3357 | } | 4526 | } |
3358 | 4527 | ||
3359 | static u8 bnx2x_8073_config_init(struct bnx2x_phy *phy, | 4528 | static void bnx2x_8726_link_reset(struct bnx2x_phy *phy, |
3360 | struct link_params *params, | 4529 | struct link_params *params) |
3361 | struct link_vars *vars) | ||
3362 | { | 4530 | { |
3363 | struct bnx2x *bp = params->bp; | 4531 | struct bnx2x *bp = params->bp; |
3364 | u16 val = 0, tmp1; | 4532 | DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port); |
3365 | u8 gpio_port; | 4533 | /* Set serial boot control for external load */ |
3366 | DP(NETIF_MSG_LINK, "Init 8073\n"); | ||
3367 | |||
3368 | gpio_port = params->port; | ||
3369 | /* Restore normal power mode*/ | ||
3370 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
3371 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port); | ||
3372 | |||
3373 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
3374 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, gpio_port); | ||
3375 | |||
3376 | /* enable LASI */ | ||
3377 | bnx2x_cl45_write(bp, phy, | ||
3378 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM_CTRL, (1<<2)); | ||
3379 | bnx2x_cl45_write(bp, phy, | ||
3380 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x0004); | ||
3381 | |||
3382 | bnx2x_8073_set_pause_cl37(params, phy, vars); | ||
3383 | |||
3384 | bnx2x_8073_set_xaui_low_power_mode(bp, phy); | ||
3385 | |||
3386 | bnx2x_cl45_read(bp, phy, | ||
3387 | MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &tmp1); | ||
3388 | |||
3389 | bnx2x_cl45_read(bp, phy, | ||
3390 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &tmp1); | ||
3391 | |||
3392 | DP(NETIF_MSG_LINK, "Before rom RX_ALARM(port1): 0x%x\n", tmp1); | ||
3393 | |||
3394 | /* Enable CL37 BAM */ | ||
3395 | bnx2x_cl45_read(bp, phy, | ||
3396 | MDIO_AN_DEVAD, | ||
3397 | MDIO_AN_REG_8073_BAM, &val); | ||
3398 | bnx2x_cl45_write(bp, phy, | 4534 | bnx2x_cl45_write(bp, phy, |
3399 | MDIO_AN_DEVAD, | 4535 | MDIO_PMA_DEVAD, |
3400 | MDIO_AN_REG_8073_BAM, val | 1); | 4536 | MDIO_PMA_REG_GEN_CTRL, 0x0001); |
3401 | |||
3402 | if (params->loopback_mode == LOOPBACK_EXT) { | ||
3403 | bnx2x_807x_force_10G(bp, phy); | ||
3404 | DP(NETIF_MSG_LINK, "Forced speed 10G on 807X\n"); | ||
3405 | return 0; | ||
3406 | } else { | ||
3407 | bnx2x_cl45_write(bp, phy, | ||
3408 | MDIO_PMA_DEVAD, MDIO_PMA_REG_BCM_CTRL, 0x0002); | ||
3409 | } | ||
3410 | if (phy->req_line_speed != SPEED_AUTO_NEG) { | ||
3411 | if (phy->req_line_speed == SPEED_10000) { | ||
3412 | val = (1<<7); | ||
3413 | } else if (phy->req_line_speed == SPEED_2500) { | ||
3414 | val = (1<<5); | ||
3415 | /* Note that 2.5G works only | ||
3416 | when used with 1G advertisment */ | ||
3417 | } else | ||
3418 | val = (1<<5); | ||
3419 | } else { | ||
3420 | val = 0; | ||
3421 | if (phy->speed_cap_mask & | ||
3422 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) | ||
3423 | val |= (1<<7); | ||
3424 | |||
3425 | /* Note that 2.5G works only when | ||
3426 | used with 1G advertisment */ | ||
3427 | if (phy->speed_cap_mask & | ||
3428 | (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G | | ||
3429 | PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)) | ||
3430 | val |= (1<<5); | ||
3431 | DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val); | ||
3432 | } | ||
3433 | |||
3434 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV, val); | ||
3435 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, &tmp1); | ||
3436 | |||
3437 | if (((phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) && | ||
3438 | (phy->req_line_speed == SPEED_AUTO_NEG)) || | ||
3439 | (phy->req_line_speed == SPEED_2500)) { | ||
3440 | u16 phy_ver; | ||
3441 | /* Allow 2.5G for A1 and above */ | ||
3442 | bnx2x_cl45_read(bp, phy, | ||
3443 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_CHIP_REV, | ||
3444 | &phy_ver); | ||
3445 | DP(NETIF_MSG_LINK, "Add 2.5G\n"); | ||
3446 | if (phy_ver > 0) | ||
3447 | tmp1 |= 1; | ||
3448 | else | ||
3449 | tmp1 &= 0xfffe; | ||
3450 | } else { | ||
3451 | DP(NETIF_MSG_LINK, "Disable 2.5G\n"); | ||
3452 | tmp1 &= 0xfffe; | ||
3453 | } | ||
3454 | |||
3455 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_8073_2_5G, tmp1); | ||
3456 | /* Add support for CL37 (passive mode) II */ | ||
3457 | |||
3458 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, &tmp1); | ||
3459 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_FC_LD, | ||
3460 | (tmp1 | ((phy->req_duplex == DUPLEX_FULL) ? | ||
3461 | 0x20 : 0x40))); | ||
3462 | |||
3463 | /* Add support for CL37 (passive mode) III */ | ||
3464 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CL37_AN, 0x1000); | ||
3465 | |||
3466 | /* The SNR will improve about 2db by changing | ||
3467 | BW and FEE main tap. Rest commands are executed | ||
3468 | after link is up*/ | ||
3469 | if (bnx2x_8073_is_snr_needed(bp, phy)) | ||
3470 | bnx2x_cl45_write(bp, phy, | ||
3471 | MDIO_PMA_DEVAD, MDIO_PMA_REG_EDC_FFE_MAIN, | ||
3472 | 0xFB0C); | ||
3473 | |||
3474 | /* Enable FEC (Forware Error Correction) Request in the AN */ | ||
3475 | bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, &tmp1); | ||
3476 | tmp1 |= (1<<15); | ||
3477 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_ADV2, tmp1); | ||
3478 | |||
3479 | bnx2x_ext_phy_set_pause(params, phy, vars); | ||
3480 | |||
3481 | /* Restart autoneg */ | ||
3482 | msleep(500); | ||
3483 | bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, 0x1200); | ||
3484 | DP(NETIF_MSG_LINK, "807x Autoneg Restart: Advertise 1G=%x, 10G=%x\n", | ||
3485 | ((val & (1<<5)) > 0), ((val & (1<<7)) > 0)); | ||
3486 | return 0; | ||
3487 | } | 4537 | } |
3488 | 4538 | ||
4539 | /******************************************************************/ | ||
4540 | /* BCM8727 PHY SECTION */ | ||
4541 | /******************************************************************/ | ||
4542 | static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy, | ||
4543 | struct link_params *params) { | ||
4544 | u32 swap_val, swap_override; | ||
4545 | u8 port; | ||
4546 | /** | ||
4547 | * The PHY reset is controlled by GPIO 1. Fake the port number | ||
4548 | * to cancel the swap done in set_gpio() | ||
4549 | */ | ||
4550 | struct bnx2x *bp = params->bp; | ||
4551 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); | ||
4552 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); | ||
4553 | port = (swap_val && swap_override) ^ 1; | ||
4554 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
4555 | MISC_REGISTERS_GPIO_OUTPUT_LOW, port); | ||
4556 | } | ||
3489 | 4557 | ||
3490 | static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, | 4558 | static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, |
3491 | struct link_params *params, | 4559 | struct link_params *params, |
@@ -3586,7 +4654,6 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, | |||
3586 | 0x0008); | 4654 | 0x0008); |
3587 | } | 4655 | } |
3588 | 4656 | ||
3589 | |||
3590 | /* Set 2-wire transfer rate of SFP+ module EEPROM | 4657 | /* Set 2-wire transfer rate of SFP+ module EEPROM |
3591 | * to 100Khz since some DACs(direct attached cables) do | 4658 | * to 100Khz since some DACs(direct attached cables) do |
3592 | * not work at 400Khz. | 4659 | * not work at 400Khz. |
@@ -3613,225 +4680,6 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, | |||
3613 | return 0; | 4680 | return 0; |
3614 | } | 4681 | } |
3615 | 4682 | ||
3616 | static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy, | ||
3617 | struct link_params *params, | ||
3618 | struct link_vars *vars) | ||
3619 | { | ||
3620 | u16 fw_ver1, fw_ver2, val; | ||
3621 | struct bnx2x *bp = params->bp; | ||
3622 | DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n"); | ||
3623 | |||
3624 | /* Restore normal power mode*/ | ||
3625 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
3626 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | ||
3627 | /* HW reset */ | ||
3628 | bnx2x_ext_phy_hw_reset(bp, params->port); | ||
3629 | bnx2x_wait_reset_complete(bp, phy); | ||
3630 | |||
3631 | bnx2x_cl45_write(bp, phy, | ||
3632 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1); | ||
3633 | DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n"); | ||
3634 | bnx2x_cl45_write(bp, phy, | ||
3635 | MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3)); | ||
3636 | |||
3637 | bnx2x_ext_phy_set_pause(params, phy, vars); | ||
3638 | /* Restart autoneg */ | ||
3639 | bnx2x_cl45_read(bp, phy, | ||
3640 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val); | ||
3641 | val |= 0x200; | ||
3642 | bnx2x_cl45_write(bp, phy, | ||
3643 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val); | ||
3644 | |||
3645 | /* Save spirom version */ | ||
3646 | bnx2x_cl45_read(bp, phy, | ||
3647 | MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1); | ||
3648 | |||
3649 | bnx2x_cl45_read(bp, phy, | ||
3650 | MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2); | ||
3651 | bnx2x_save_spirom_version(bp, params->port, | ||
3652 | (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr); | ||
3653 | return 0; | ||
3654 | } | ||
3655 | |||
3656 | static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, | ||
3657 | struct link_params *params, | ||
3658 | struct link_vars *vars) | ||
3659 | { | ||
3660 | struct bnx2x *bp = params->bp; | ||
3661 | u16 autoneg_val, an_1000_val, an_10_100_val; | ||
3662 | bnx2x_wait_reset_complete(bp, phy); | ||
3663 | bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, | ||
3664 | 1 << NIG_LATCH_BC_ENABLE_MI_INT); | ||
3665 | |||
3666 | bnx2x_cl45_write(bp, phy, | ||
3667 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000); | ||
3668 | bnx2x_848xx_set_led(bp, phy); | ||
3669 | /* set 1000 speed advertisement */ | ||
3670 | bnx2x_cl45_read(bp, phy, | ||
3671 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, | ||
3672 | &an_1000_val); | ||
3673 | |||
3674 | bnx2x_ext_phy_set_pause(params, phy, vars); | ||
3675 | bnx2x_cl45_read(bp, phy, | ||
3676 | MDIO_AN_DEVAD, | ||
3677 | MDIO_AN_REG_8481_LEGACY_AN_ADV, | ||
3678 | &an_10_100_val); | ||
3679 | bnx2x_cl45_read(bp, phy, | ||
3680 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL, | ||
3681 | &autoneg_val); | ||
3682 | /* Disable forced speed */ | ||
3683 | autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13)); | ||
3684 | an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8)); | ||
3685 | |||
3686 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && | ||
3687 | (phy->speed_cap_mask & | ||
3688 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || | ||
3689 | (phy->req_line_speed == SPEED_1000)) { | ||
3690 | an_1000_val |= (1<<8); | ||
3691 | autoneg_val |= (1<<9 | 1<<12); | ||
3692 | if (phy->req_duplex == DUPLEX_FULL) | ||
3693 | an_1000_val |= (1<<9); | ||
3694 | DP(NETIF_MSG_LINK, "Advertising 1G\n"); | ||
3695 | } else | ||
3696 | an_1000_val &= ~((1<<8) | (1<<9)); | ||
3697 | |||
3698 | bnx2x_cl45_write(bp, phy, | ||
3699 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, | ||
3700 | an_1000_val); | ||
3701 | |||
3702 | /* set 10 speed advertisement */ | ||
3703 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && | ||
3704 | (phy->speed_cap_mask & | ||
3705 | (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL | | ||
3706 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) { | ||
3707 | an_10_100_val |= (1<<7); | ||
3708 | /* Enable autoneg and restart autoneg for legacy speeds */ | ||
3709 | autoneg_val |= (1<<9 | 1<<12); | ||
3710 | |||
3711 | if (phy->req_duplex == DUPLEX_FULL) | ||
3712 | an_10_100_val |= (1<<8); | ||
3713 | DP(NETIF_MSG_LINK, "Advertising 100M\n"); | ||
3714 | } | ||
3715 | /* set 10 speed advertisement */ | ||
3716 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && | ||
3717 | (phy->speed_cap_mask & | ||
3718 | (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL | | ||
3719 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) { | ||
3720 | an_10_100_val |= (1<<5); | ||
3721 | autoneg_val |= (1<<9 | 1<<12); | ||
3722 | if (phy->req_duplex == DUPLEX_FULL) | ||
3723 | an_10_100_val |= (1<<6); | ||
3724 | DP(NETIF_MSG_LINK, "Advertising 10M\n"); | ||
3725 | } | ||
3726 | |||
3727 | /* Only 10/100 are allowed to work in FORCE mode */ | ||
3728 | if (phy->req_line_speed == SPEED_100) { | ||
3729 | autoneg_val |= (1<<13); | ||
3730 | /* Enabled AUTO-MDIX when autoneg is disabled */ | ||
3731 | bnx2x_cl45_write(bp, phy, | ||
3732 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL, | ||
3733 | (1<<15 | 1<<9 | 7<<0)); | ||
3734 | DP(NETIF_MSG_LINK, "Setting 100M force\n"); | ||
3735 | } | ||
3736 | if (phy->req_line_speed == SPEED_10) { | ||
3737 | /* Enabled AUTO-MDIX when autoneg is disabled */ | ||
3738 | bnx2x_cl45_write(bp, phy, | ||
3739 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL, | ||
3740 | (1<<15 | 1<<9 | 7<<0)); | ||
3741 | DP(NETIF_MSG_LINK, "Setting 10M force\n"); | ||
3742 | } | ||
3743 | |||
3744 | bnx2x_cl45_write(bp, phy, | ||
3745 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV, | ||
3746 | an_10_100_val); | ||
3747 | |||
3748 | if (phy->req_duplex == DUPLEX_FULL) | ||
3749 | autoneg_val |= (1<<8); | ||
3750 | |||
3751 | bnx2x_cl45_write(bp, phy, | ||
3752 | MDIO_AN_DEVAD, | ||
3753 | MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val); | ||
3754 | |||
3755 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && | ||
3756 | (phy->speed_cap_mask & | ||
3757 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) || | ||
3758 | (phy->req_line_speed == SPEED_10000)) { | ||
3759 | DP(NETIF_MSG_LINK, "Advertising 10G\n"); | ||
3760 | /* Restart autoneg for 10G*/ | ||
3761 | |||
3762 | bnx2x_cl45_write(bp, phy, | ||
3763 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, | ||
3764 | 0x3200); | ||
3765 | } else if (phy->req_line_speed != SPEED_10 && | ||
3766 | phy->req_line_speed != SPEED_100) { | ||
3767 | bnx2x_cl45_write(bp, phy, | ||
3768 | MDIO_AN_DEVAD, | ||
3769 | MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, | ||
3770 | 1); | ||
3771 | } | ||
3772 | /* Save spirom version */ | ||
3773 | bnx2x_save_848xx_spirom_version(phy, params); | ||
3774 | |||
3775 | return 0; | ||
3776 | } | ||
3777 | |||
3778 | static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, | ||
3779 | struct link_params *params, | ||
3780 | struct link_vars *vars) | ||
3781 | { | ||
3782 | struct bnx2x *bp = params->bp; | ||
3783 | u16 temp; | ||
3784 | msleep(1); | ||
3785 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, | ||
3786 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, | ||
3787 | params->port); | ||
3788 | msleep(200); /* 100 is not enough */ | ||
3789 | |||
3790 | /** | ||
3791 | * BCM84823 requires that XGXS links up first @ 10G for normal | ||
3792 | * behavior | ||
3793 | */ | ||
3794 | temp = vars->line_speed; | ||
3795 | vars->line_speed = SPEED_10000; | ||
3796 | bnx2x_set_autoneg(phy, params, vars, 0); | ||
3797 | bnx2x_program_serdes(phy, params, vars); | ||
3798 | vars->line_speed = temp; | ||
3799 | return bnx2x_848xx_cmn_config_init(phy, params, vars); | ||
3800 | } | ||
3801 | |||
3802 | static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy, | ||
3803 | struct link_params *params, | ||
3804 | struct link_vars *vars) | ||
3805 | { | ||
3806 | struct bnx2x *bp = params->bp; | ||
3807 | /* Restore normal power mode*/ | ||
3808 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
3809 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | ||
3810 | |||
3811 | /* HW reset */ | ||
3812 | bnx2x_ext_phy_hw_reset(bp, params->port); | ||
3813 | |||
3814 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); | ||
3815 | return bnx2x_848xx_cmn_config_init(phy, params, vars); | ||
3816 | } | ||
3817 | |||
3818 | |||
3819 | static void bnx2x_ext_phy_10G_an_resolve(struct bnx2x *bp, | ||
3820 | struct bnx2x_phy *phy, | ||
3821 | struct link_vars *vars) | ||
3822 | { | ||
3823 | u16 val; | ||
3824 | bnx2x_cl45_read(bp, phy, | ||
3825 | MDIO_AN_DEVAD, | ||
3826 | MDIO_AN_REG_STATUS, &val); | ||
3827 | bnx2x_cl45_read(bp, phy, | ||
3828 | MDIO_AN_DEVAD, | ||
3829 | MDIO_AN_REG_STATUS, &val); | ||
3830 | if (val & (1<<5)) | ||
3831 | vars->link_status |= LINK_STATUS_AUTO_NEGOTIATE_COMPLETE; | ||
3832 | if ((val & (1<<0)) == 0) | ||
3833 | vars->link_status |= LINK_STATUS_PARALLEL_DETECTION_USED; | ||
3834 | } | ||
3835 | static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, | 4683 | static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, |
3836 | struct link_params *params) | 4684 | struct link_params *params) |
3837 | { | 4685 | { |
@@ -3910,110 +4758,6 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, | |||
3910 | module plugged in/out */ | 4758 | module plugged in/out */ |
3911 | } | 4759 | } |
3912 | 4760 | ||
3913 | |||
3914 | static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy, | ||
3915 | struct link_params *params, | ||
3916 | struct link_vars *vars) | ||
3917 | { | ||
3918 | u8 link_up = 0; | ||
3919 | u16 val1, rx_sd; | ||
3920 | struct bnx2x *bp = params->bp; | ||
3921 | DP(NETIF_MSG_LINK, "read status 8705\n"); | ||
3922 | bnx2x_cl45_read(bp, phy, | ||
3923 | MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1); | ||
3924 | DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); | ||
3925 | |||
3926 | bnx2x_cl45_read(bp, phy, | ||
3927 | MDIO_WIS_DEVAD, MDIO_WIS_REG_LASI_STATUS, &val1); | ||
3928 | DP(NETIF_MSG_LINK, "8705 LASI status 0x%x\n", val1); | ||
3929 | |||
3930 | bnx2x_cl45_read(bp, phy, | ||
3931 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd); | ||
3932 | |||
3933 | bnx2x_cl45_read(bp, phy, | ||
3934 | MDIO_PMA_DEVAD, 0xc809, &val1); | ||
3935 | bnx2x_cl45_read(bp, phy, | ||
3936 | MDIO_PMA_DEVAD, 0xc809, &val1); | ||
3937 | |||
3938 | DP(NETIF_MSG_LINK, "8705 1.c809 val=0x%x\n", val1); | ||
3939 | link_up = ((rx_sd & 0x1) && (val1 & (1<<9)) && ((val1 & (1<<8)) == 0)); | ||
3940 | if (link_up) { | ||
3941 | vars->line_speed = SPEED_10000; | ||
3942 | bnx2x_ext_phy_resolve_fc(phy, params, vars); | ||
3943 | } | ||
3944 | return link_up; | ||
3945 | } | ||
3946 | |||
3947 | static u8 bnx2x_8706_8726_read_status(struct bnx2x_phy *phy, | ||
3948 | struct link_params *params, | ||
3949 | struct link_vars *vars) | ||
3950 | { | ||
3951 | u8 link_up = 0; | ||
3952 | u16 val1, val2, rx_sd, pcs_status; | ||
3953 | struct bnx2x *bp = params->bp; | ||
3954 | DP(NETIF_MSG_LINK, "XGXS 8706/8726\n"); | ||
3955 | /* Clear RX Alarm*/ | ||
3956 | bnx2x_cl45_read(bp, phy, | ||
3957 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2); | ||
3958 | /* clear LASI indication*/ | ||
3959 | bnx2x_cl45_read(bp, phy, | ||
3960 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1); | ||
3961 | bnx2x_cl45_read(bp, phy, | ||
3962 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2); | ||
3963 | DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x--> 0x%x\n", val1, val2); | ||
3964 | |||
3965 | bnx2x_cl45_read(bp, phy, | ||
3966 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, &rx_sd); | ||
3967 | bnx2x_cl45_read(bp, phy, | ||
3968 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &pcs_status); | ||
3969 | bnx2x_cl45_read(bp, phy, | ||
3970 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2); | ||
3971 | bnx2x_cl45_read(bp, phy, | ||
3972 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &val2); | ||
3973 | |||
3974 | DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x pcs_status 0x%x 1Gbps" | ||
3975 | " link_status 0x%x\n", rx_sd, pcs_status, val2); | ||
3976 | /* link is up if both bit 0 of pmd_rx_sd and | ||
3977 | * bit 0 of pcs_status are set, or if the autoneg bit | ||
3978 | * 1 is set | ||
3979 | */ | ||
3980 | link_up = ((rx_sd & pcs_status & 0x1) || (val2 & (1<<1))); | ||
3981 | if (link_up) { | ||
3982 | if (val2 & (1<<1)) | ||
3983 | vars->line_speed = SPEED_1000; | ||
3984 | else | ||
3985 | vars->line_speed = SPEED_10000; | ||
3986 | bnx2x_ext_phy_resolve_fc(phy, params, vars); | ||
3987 | } | ||
3988 | return link_up; | ||
3989 | } | ||
3990 | static u8 bnx2x_8706_read_status(struct bnx2x_phy *phy, | ||
3991 | struct link_params *params, | ||
3992 | struct link_vars *vars) | ||
3993 | { | ||
3994 | return bnx2x_8706_8726_read_status(phy, params, vars); | ||
3995 | } | ||
3996 | |||
3997 | static u8 bnx2x_8726_read_status(struct bnx2x_phy *phy, | ||
3998 | struct link_params *params, | ||
3999 | struct link_vars *vars) | ||
4000 | { | ||
4001 | struct bnx2x *bp = params->bp; | ||
4002 | u16 val1; | ||
4003 | u8 link_up = bnx2x_8706_8726_read_status(phy, params, vars); | ||
4004 | if (link_up) { | ||
4005 | bnx2x_cl45_read(bp, phy, | ||
4006 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PHY_IDENTIFIER, | ||
4007 | &val1); | ||
4008 | if (val1 & (1<<15)) { | ||
4009 | DP(NETIF_MSG_LINK, "Tx is disabled\n"); | ||
4010 | link_up = 0; | ||
4011 | vars->line_speed = 0; | ||
4012 | } | ||
4013 | } | ||
4014 | return link_up; | ||
4015 | } | ||
4016 | |||
4017 | static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, | 4761 | static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, |
4018 | struct link_params *params, | 4762 | struct link_params *params, |
4019 | struct link_vars *vars) | 4763 | struct link_vars *vars) |
@@ -4126,184 +4870,275 @@ static u8 bnx2x_8727_read_status(struct bnx2x_phy *phy, | |||
4126 | return link_up; | 4870 | return link_up; |
4127 | } | 4871 | } |
4128 | 4872 | ||
4129 | static void bnx2x_8073_resolve_fc(struct bnx2x_phy *phy, | 4873 | static void bnx2x_8727_link_reset(struct bnx2x_phy *phy, |
4130 | struct link_params *params, | 4874 | struct link_params *params) |
4131 | struct link_vars *vars) | ||
4132 | { | 4875 | { |
4133 | struct bnx2x *bp = params->bp; | 4876 | struct bnx2x *bp = params->bp; |
4134 | if (phy->req_line_speed == SPEED_10 || | 4877 | /* Disable Transmitter */ |
4135 | phy->req_line_speed == SPEED_100) { | 4878 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); |
4136 | vars->flow_ctrl = phy->req_flow_ctrl; | 4879 | } |
4880 | |||
4881 | /******************************************************************/ | ||
4882 | /* BCM8481/BCM84823/BCM84833 PHY SECTION */ | ||
4883 | /******************************************************************/ | ||
4884 | static void bnx2x_save_848xx_spirom_version(struct bnx2x_phy *phy, | ||
4885 | struct link_params *params) | ||
4886 | { | ||
4887 | u16 val, fw_ver1, fw_ver2, cnt; | ||
4888 | struct bnx2x *bp = params->bp; | ||
4889 | |||
4890 | /* For the 32 bits registers in 848xx, access via MDIO2ARM interface.*/ | ||
4891 | /* (1) set register 0xc200_0014(SPI_BRIDGE_CTRL_2) to 0x03000000 */ | ||
4892 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0014); | ||
4893 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200); | ||
4894 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81B, 0x0000); | ||
4895 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81C, 0x0300); | ||
4896 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x0009); | ||
4897 | |||
4898 | for (cnt = 0; cnt < 100; cnt++) { | ||
4899 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val); | ||
4900 | if (val & 1) | ||
4901 | break; | ||
4902 | udelay(5); | ||
4903 | } | ||
4904 | if (cnt == 100) { | ||
4905 | DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(1)\n"); | ||
4906 | bnx2x_save_spirom_version(bp, params->port, 0, | ||
4907 | phy->ver_addr); | ||
4137 | return; | 4908 | return; |
4138 | } | 4909 | } |
4139 | 4910 | ||
4140 | if (bnx2x_ext_phy_resolve_fc(phy, params, vars) && | ||
4141 | (vars->flow_ctrl == BNX2X_FLOW_CTRL_NONE)) { | ||
4142 | u16 pause_result; | ||
4143 | u16 ld_pause; /* local */ | ||
4144 | u16 lp_pause; /* link partner */ | ||
4145 | bnx2x_cl45_read(bp, phy, | ||
4146 | MDIO_AN_DEVAD, | ||
4147 | MDIO_AN_REG_CL37_FC_LD, &ld_pause); | ||
4148 | |||
4149 | bnx2x_cl45_read(bp, phy, | ||
4150 | MDIO_AN_DEVAD, | ||
4151 | MDIO_AN_REG_CL37_FC_LP, &lp_pause); | ||
4152 | pause_result = (ld_pause & | ||
4153 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 5; | ||
4154 | pause_result |= (lp_pause & | ||
4155 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) >> 7; | ||
4156 | 4911 | ||
4157 | bnx2x_pause_resolve(vars, pause_result); | 4912 | /* 2) read register 0xc200_0000 (SPI_FW_STATUS) */ |
4158 | DP(NETIF_MSG_LINK, "Ext PHY CL37 pause result 0x%x\n", | 4913 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA819, 0x0000); |
4159 | pause_result); | 4914 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA81A, 0xc200); |
4915 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, 0xA817, 0x000A); | ||
4916 | for (cnt = 0; cnt < 100; cnt++) { | ||
4917 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA818, &val); | ||
4918 | if (val & 1) | ||
4919 | break; | ||
4920 | udelay(5); | ||
4921 | } | ||
4922 | if (cnt == 100) { | ||
4923 | DP(NETIF_MSG_LINK, "Unable to read 848xx phy fw version(2)\n"); | ||
4924 | bnx2x_save_spirom_version(bp, params->port, 0, | ||
4925 | phy->ver_addr); | ||
4926 | return; | ||
4160 | } | 4927 | } |
4928 | |||
4929 | /* lower 16 bits of the register SPI_FW_STATUS */ | ||
4930 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81B, &fw_ver1); | ||
4931 | /* upper 16 bits of register SPI_FW_STATUS */ | ||
4932 | bnx2x_cl45_read(bp, phy, MDIO_PMA_DEVAD, 0xA81C, &fw_ver2); | ||
4933 | |||
4934 | bnx2x_save_spirom_version(bp, params->port, (fw_ver2<<16) | fw_ver1, | ||
4935 | phy->ver_addr); | ||
4161 | } | 4936 | } |
4162 | static u8 bnx2x_8073_read_status(struct bnx2x_phy *phy, | 4937 | |
4163 | struct link_params *params, | 4938 | static void bnx2x_848xx_set_led(struct bnx2x *bp, |
4164 | struct link_vars *vars) | 4939 | struct bnx2x_phy *phy) |
4165 | { | 4940 | { |
4166 | struct bnx2x *bp = params->bp; | 4941 | u16 val; |
4167 | u8 link_up = 0; | ||
4168 | u16 val1, val2; | ||
4169 | u16 link_status = 0; | ||
4170 | u16 an1000_status = 0; | ||
4171 | 4942 | ||
4943 | /* PHYC_CTL_LED_CTL */ | ||
4172 | bnx2x_cl45_read(bp, phy, | 4944 | bnx2x_cl45_read(bp, phy, |
4173 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1); | 4945 | MDIO_PMA_DEVAD, |
4946 | MDIO_PMA_REG_8481_LINK_SIGNAL, &val); | ||
4947 | val &= 0xFE00; | ||
4948 | val |= 0x0092; | ||
4174 | 4949 | ||
4175 | DP(NETIF_MSG_LINK, "8703 LASI status 0x%x\n", val1); | 4950 | bnx2x_cl45_write(bp, phy, |
4951 | MDIO_PMA_DEVAD, | ||
4952 | MDIO_PMA_REG_8481_LINK_SIGNAL, val); | ||
4176 | 4953 | ||
4177 | /* clear the interrupt LASI status register */ | 4954 | bnx2x_cl45_write(bp, phy, |
4178 | bnx2x_cl45_read(bp, phy, | 4955 | MDIO_PMA_DEVAD, |
4179 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2); | 4956 | MDIO_PMA_REG_8481_LED1_MASK, |
4180 | bnx2x_cl45_read(bp, phy, | 4957 | 0x80); |
4181 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val1); | ||
4182 | DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n", val2, val1); | ||
4183 | /* Clear MSG-OUT */ | ||
4184 | bnx2x_cl45_read(bp, phy, | ||
4185 | MDIO_PMA_DEVAD, MDIO_PMA_REG_M8051_MSGOUT_REG, &val1); | ||
4186 | 4958 | ||
4187 | /* Check the LASI */ | 4959 | bnx2x_cl45_write(bp, phy, |
4188 | bnx2x_cl45_read(bp, phy, | 4960 | MDIO_PMA_DEVAD, |
4189 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, &val2); | 4961 | MDIO_PMA_REG_8481_LED2_MASK, |
4962 | 0x18); | ||
4190 | 4963 | ||
4191 | DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2); | 4964 | bnx2x_cl45_write(bp, phy, |
4965 | MDIO_PMA_DEVAD, | ||
4966 | MDIO_PMA_REG_8481_LED3_MASK, | ||
4967 | 0x0040); | ||
4192 | 4968 | ||
4193 | /* Check the link status */ | 4969 | /* 'Interrupt Mask' */ |
4194 | bnx2x_cl45_read(bp, phy, | 4970 | bnx2x_cl45_write(bp, phy, |
4195 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, &val2); | 4971 | MDIO_AN_DEVAD, |
4196 | DP(NETIF_MSG_LINK, "KR PCS status 0x%x\n", val2); | 4972 | 0xFFFB, 0xFFFD); |
4973 | } | ||
4197 | 4974 | ||
4198 | bnx2x_cl45_read(bp, phy, | 4975 | static u8 bnx2x_848xx_cmn_config_init(struct bnx2x_phy *phy, |
4199 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); | 4976 | struct link_params *params, |
4200 | bnx2x_cl45_read(bp, phy, | 4977 | struct link_vars *vars) |
4201 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); | 4978 | { |
4202 | link_up = ((val1 & 4) == 4); | 4979 | struct bnx2x *bp = params->bp; |
4203 | DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1); | 4980 | u16 autoneg_val, an_1000_val, an_10_100_val; |
4981 | /** | ||
4982 | * This phy uses the NIG latch mechanism since link indication | ||
4983 | * arrives through its LED4 and not via its LASI signal, so we | ||
4984 | * get steady signal instead of clear on read | ||
4985 | */ | ||
4986 | bnx2x_wait_reset_complete(bp, phy); | ||
4987 | bnx2x_bits_en(bp, NIG_REG_LATCH_BC_0 + params->port*4, | ||
4988 | 1 << NIG_LATCH_BC_ENABLE_MI_INT); | ||
4204 | 4989 | ||
4205 | if (link_up && | 4990 | bnx2x_cl45_write(bp, phy, |
4206 | ((phy->req_line_speed != SPEED_10000))) { | 4991 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0000); |
4207 | if (bnx2x_8073_xaui_wa(bp, phy) != 0) | 4992 | |
4208 | return 0; | 4993 | bnx2x_848xx_set_led(bp, phy); |
4209 | } | 4994 | |
4210 | bnx2x_cl45_read(bp, phy, | 4995 | /* set 1000 speed advertisement */ |
4211 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status); | ||
4212 | bnx2x_cl45_read(bp, phy, | 4996 | bnx2x_cl45_read(bp, phy, |
4213 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, &an1000_status); | 4997 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, |
4998 | &an_1000_val); | ||
4214 | 4999 | ||
4215 | /* Check the link status on 1.1.2 */ | 5000 | bnx2x_ext_phy_set_pause(params, phy, vars); |
4216 | bnx2x_cl45_read(bp, phy, | 5001 | bnx2x_cl45_read(bp, phy, |
4217 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); | 5002 | MDIO_AN_DEVAD, |
5003 | MDIO_AN_REG_8481_LEGACY_AN_ADV, | ||
5004 | &an_10_100_val); | ||
4218 | bnx2x_cl45_read(bp, phy, | 5005 | bnx2x_cl45_read(bp, phy, |
4219 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); | 5006 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_MII_CTRL, |
4220 | DP(NETIF_MSG_LINK, "KR PMA status 0x%x->0x%x," | 5007 | &autoneg_val); |
4221 | "an_link_status=0x%x\n", val2, val1, an1000_status); | 5008 | /* Disable forced speed */ |
5009 | autoneg_val &= ~((1<<6) | (1<<8) | (1<<9) | (1<<12) | (1<<13)); | ||
5010 | an_10_100_val &= ~((1<<5) | (1<<6) | (1<<7) | (1<<8)); | ||
4222 | 5011 | ||
4223 | link_up = (((val1 & 4) == 4) || (an1000_status & (1<<1))); | 5012 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && |
4224 | if (link_up && bnx2x_8073_is_snr_needed(bp, phy)) { | 5013 | (phy->speed_cap_mask & |
4225 | /* The SNR will improve about 2dbby | 5014 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)) || |
4226 | changing the BW and FEE main tap.*/ | 5015 | (phy->req_line_speed == SPEED_1000)) { |
4227 | /* The 1st write to change FFE main | 5016 | an_1000_val |= (1<<8); |
4228 | tap is set before restart AN */ | 5017 | autoneg_val |= (1<<9 | 1<<12); |
4229 | /* Change PLL Bandwidth in EDC | 5018 | if (phy->req_duplex == DUPLEX_FULL) |
4230 | register */ | 5019 | an_1000_val |= (1<<9); |
4231 | bnx2x_cl45_write(bp, phy, | 5020 | DP(NETIF_MSG_LINK, "Advertising 1G\n"); |
4232 | MDIO_PMA_DEVAD, MDIO_PMA_REG_PLL_BANDWIDTH, | 5021 | } else |
4233 | 0x26BC); | 5022 | an_1000_val &= ~((1<<8) | (1<<9)); |
4234 | 5023 | ||
4235 | /* Change CDR Bandwidth in EDC register */ | 5024 | bnx2x_cl45_write(bp, phy, |
4236 | bnx2x_cl45_write(bp, phy, | 5025 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_1000T_CTRL, |
4237 | MDIO_PMA_DEVAD, MDIO_PMA_REG_CDR_BANDWIDTH, | 5026 | an_1000_val); |
4238 | 0x0333); | 5027 | |
5028 | /* set 10 speed advertisement */ | ||
5029 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && | ||
5030 | (phy->speed_cap_mask & | ||
5031 | (PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_FULL | | ||
5032 | PORT_HW_CFG_SPEED_CAPABILITY_D0_100M_HALF)))) { | ||
5033 | an_10_100_val |= (1<<7); | ||
5034 | /* Enable autoneg and restart autoneg for legacy speeds */ | ||
5035 | autoneg_val |= (1<<9 | 1<<12); | ||
5036 | |||
5037 | if (phy->req_duplex == DUPLEX_FULL) | ||
5038 | an_10_100_val |= (1<<8); | ||
5039 | DP(NETIF_MSG_LINK, "Advertising 100M\n"); | ||
5040 | } | ||
5041 | /* set 10 speed advertisement */ | ||
5042 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && | ||
5043 | (phy->speed_cap_mask & | ||
5044 | (PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_FULL | | ||
5045 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10M_HALF)))) { | ||
5046 | an_10_100_val |= (1<<5); | ||
5047 | autoneg_val |= (1<<9 | 1<<12); | ||
5048 | if (phy->req_duplex == DUPLEX_FULL) | ||
5049 | an_10_100_val |= (1<<6); | ||
5050 | DP(NETIF_MSG_LINK, "Advertising 10M\n"); | ||
4239 | } | 5051 | } |
4240 | bnx2x_cl45_read(bp, phy, | ||
4241 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8073_SPEED_LINK_STATUS, | ||
4242 | &link_status); | ||
4243 | 5052 | ||
4244 | /* Bits 0..2 --> speed detected, bits 13..15--> link is down */ | 5053 | /* Only 10/100 are allowed to work in FORCE mode */ |
4245 | if ((link_status & (1<<2)) && (!(link_status & (1<<15)))) { | 5054 | if (phy->req_line_speed == SPEED_100) { |
4246 | link_up = 1; | 5055 | autoneg_val |= (1<<13); |
4247 | vars->line_speed = SPEED_10000; | 5056 | /* Enabled AUTO-MDIX when autoneg is disabled */ |
4248 | DP(NETIF_MSG_LINK, "port %x: External link up in 10G\n", | 5057 | bnx2x_cl45_write(bp, phy, |
4249 | params->port); | 5058 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL, |
4250 | } else if ((link_status & (1<<1)) && (!(link_status & (1<<14)))) { | 5059 | (1<<15 | 1<<9 | 7<<0)); |
4251 | link_up = 1; | 5060 | DP(NETIF_MSG_LINK, "Setting 100M force\n"); |
4252 | vars->line_speed = SPEED_2500; | 5061 | } |
4253 | DP(NETIF_MSG_LINK, "port %x: External link up in 2.5G\n", | 5062 | if (phy->req_line_speed == SPEED_10) { |
4254 | params->port); | 5063 | /* Enabled AUTO-MDIX when autoneg is disabled */ |
4255 | } else if ((link_status & (1<<0)) && (!(link_status & (1<<13)))) { | 5064 | bnx2x_cl45_write(bp, phy, |
4256 | link_up = 1; | 5065 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_AUX_CTRL, |
4257 | vars->line_speed = SPEED_1000; | 5066 | (1<<15 | 1<<9 | 7<<0)); |
4258 | DP(NETIF_MSG_LINK, "port %x: External link up in 1G\n", | 5067 | DP(NETIF_MSG_LINK, "Setting 10M force\n"); |
4259 | params->port); | ||
4260 | } else { | ||
4261 | link_up = 0; | ||
4262 | DP(NETIF_MSG_LINK, "port %x: External link is down\n", | ||
4263 | params->port); | ||
4264 | } | 5068 | } |
4265 | 5069 | ||
4266 | if (link_up) { | 5070 | bnx2x_cl45_write(bp, phy, |
4267 | bnx2x_ext_phy_10G_an_resolve(bp, phy, vars); | 5071 | MDIO_AN_DEVAD, MDIO_AN_REG_8481_LEGACY_AN_ADV, |
4268 | bnx2x_8073_resolve_fc(phy, params, vars); | 5072 | an_10_100_val); |
5073 | |||
5074 | if (phy->req_duplex == DUPLEX_FULL) | ||
5075 | autoneg_val |= (1<<8); | ||
5076 | |||
5077 | bnx2x_cl45_write(bp, phy, | ||
5078 | MDIO_AN_DEVAD, | ||
5079 | MDIO_AN_REG_8481_LEGACY_MII_CTRL, autoneg_val); | ||
5080 | |||
5081 | if (((phy->req_line_speed == SPEED_AUTO_NEG) && | ||
5082 | (phy->speed_cap_mask & | ||
5083 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)) || | ||
5084 | (phy->req_line_speed == SPEED_10000)) { | ||
5085 | DP(NETIF_MSG_LINK, "Advertising 10G\n"); | ||
5086 | /* Restart autoneg for 10G*/ | ||
5087 | |||
5088 | bnx2x_cl45_write(bp, phy, | ||
5089 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, | ||
5090 | 0x3200); | ||
5091 | } else if (phy->req_line_speed != SPEED_10 && | ||
5092 | phy->req_line_speed != SPEED_100) { | ||
5093 | bnx2x_cl45_write(bp, phy, | ||
5094 | MDIO_AN_DEVAD, | ||
5095 | MDIO_AN_REG_8481_10GBASE_T_AN_CTRL, | ||
5096 | 1); | ||
4269 | } | 5097 | } |
4270 | return link_up; | 5098 | /* Save spirom version */ |
5099 | bnx2x_save_848xx_spirom_version(phy, params); | ||
5100 | |||
5101 | return 0; | ||
4271 | } | 5102 | } |
4272 | 5103 | ||
4273 | static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy, | 5104 | static u8 bnx2x_8481_config_init(struct bnx2x_phy *phy, |
4274 | struct link_params *params, | 5105 | struct link_params *params, |
4275 | struct link_vars *vars) | 5106 | struct link_vars *vars) |
4276 | { | 5107 | { |
4277 | struct bnx2x *bp = params->bp; | 5108 | struct bnx2x *bp = params->bp; |
4278 | u8 link_up; | 5109 | /* Restore normal power mode*/ |
4279 | u16 val1, val2; | 5110 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, |
4280 | bnx2x_cl45_read(bp, phy, | 5111 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); |
4281 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2); | 5112 | |
4282 | bnx2x_cl45_read(bp, phy, | 5113 | /* HW reset */ |
4283 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1); | 5114 | bnx2x_ext_phy_hw_reset(bp, params->port); |
4284 | DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n", | 5115 | |
4285 | val2, val1); | 5116 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); |
4286 | bnx2x_cl45_read(bp, phy, | 5117 | return bnx2x_848xx_cmn_config_init(phy, params, vars); |
4287 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); | 5118 | } |
4288 | bnx2x_cl45_read(bp, phy, | 5119 | |
4289 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); | 5120 | static u8 bnx2x_848x3_config_init(struct bnx2x_phy *phy, |
4290 | DP(NETIF_MSG_LINK, "10G-base-T PMA status 0x%x->0x%x\n", | 5121 | struct link_params *params, |
4291 | val2, val1); | 5122 | struct link_vars *vars) |
4292 | link_up = ((val1 & 4) == 4); | 5123 | { |
4293 | /* if link is up | 5124 | struct bnx2x *bp = params->bp; |
4294 | * print the AN outcome of the SFX7101 PHY | 5125 | u16 temp; |
5126 | msleep(1); | ||
5127 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, | ||
5128 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, | ||
5129 | params->port); | ||
5130 | msleep(200); /* 100 is not enough */ | ||
5131 | |||
5132 | /** | ||
5133 | * BCM84823 requires that XGXS links up first @ 10G for normal | ||
5134 | * behavior | ||
4295 | */ | 5135 | */ |
4296 | if (link_up) { | 5136 | temp = vars->line_speed; |
4297 | bnx2x_cl45_read(bp, phy, | 5137 | vars->line_speed = SPEED_10000; |
4298 | MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS, | 5138 | bnx2x_set_autoneg(phy, params, vars, 0); |
4299 | &val2); | 5139 | bnx2x_program_serdes(phy, params, vars); |
4300 | vars->line_speed = SPEED_10000; | 5140 | vars->line_speed = temp; |
4301 | DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n", | 5141 | return bnx2x_848xx_cmn_config_init(phy, params, vars); |
4302 | val2, (val2 & (1<<14))); | ||
4303 | bnx2x_ext_phy_10G_an_resolve(bp, phy, vars); | ||
4304 | bnx2x_ext_phy_resolve_fc(phy, params, vars); | ||
4305 | } | ||
4306 | return link_up; | ||
4307 | } | 5142 | } |
4308 | 5143 | ||
4309 | static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, | 5144 | static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, |
@@ -4364,7 +5199,6 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, | |||
4364 | DP(NETIF_MSG_LINK, "Link is up in %dMbps," | 5199 | DP(NETIF_MSG_LINK, "Link is up in %dMbps," |
4365 | " is_duplex_full= %d\n", vars->line_speed, | 5200 | " is_duplex_full= %d\n", vars->line_speed, |
4366 | (vars->duplex == DUPLEX_FULL)); | 5201 | (vars->duplex == DUPLEX_FULL)); |
4367 | |||
4368 | /* Check legacy speed AN resolution */ | 5202 | /* Check legacy speed AN resolution */ |
4369 | bnx2x_cl45_read(bp, phy, | 5203 | bnx2x_cl45_read(bp, phy, |
4370 | MDIO_AN_DEVAD, | 5204 | MDIO_AN_DEVAD, |
@@ -4391,192 +5225,6 @@ static u8 bnx2x_848xx_read_status(struct bnx2x_phy *phy, | |||
4391 | return link_up; | 5225 | return link_up; |
4392 | } | 5226 | } |
4393 | 5227 | ||
4394 | static void bnx2x_link_int_enable(struct link_params *params) | ||
4395 | { | ||
4396 | u8 port = params->port; | ||
4397 | u32 mask; | ||
4398 | struct bnx2x *bp = params->bp; | ||
4399 | |||
4400 | /* setting the status to report on link up | ||
4401 | for either XGXS or SerDes */ | ||
4402 | |||
4403 | if (params->switch_cfg == SWITCH_CFG_10G) { | ||
4404 | mask = (NIG_MASK_XGXS0_LINK10G | | ||
4405 | NIG_MASK_XGXS0_LINK_STATUS); | ||
4406 | DP(NETIF_MSG_LINK, "enabled XGXS interrupt\n"); | ||
4407 | if (!(SINGLE_MEDIA_DIRECT(params)) && | ||
4408 | params->phy[INT_PHY].type != | ||
4409 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE) { | ||
4410 | mask |= NIG_MASK_MI_INT; | ||
4411 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
4412 | } | ||
4413 | |||
4414 | } else { /* SerDes */ | ||
4415 | mask = NIG_MASK_SERDES0_LINK_STATUS; | ||
4416 | DP(NETIF_MSG_LINK, "enabled SerDes interrupt\n"); | ||
4417 | if (!(SINGLE_MEDIA_DIRECT(params)) && | ||
4418 | params->phy[INT_PHY].type != | ||
4419 | PORT_HW_CFG_SERDES_EXT_PHY_TYPE_NOT_CONN) { | ||
4420 | mask |= NIG_MASK_MI_INT; | ||
4421 | DP(NETIF_MSG_LINK, "enabled external phy int\n"); | ||
4422 | } | ||
4423 | } | ||
4424 | bnx2x_bits_en(bp, | ||
4425 | NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
4426 | mask); | ||
4427 | |||
4428 | DP(NETIF_MSG_LINK, "port %x, is_xgxs %x, int_status 0x%x\n", port, | ||
4429 | (params->switch_cfg == SWITCH_CFG_10G), | ||
4430 | REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4)); | ||
4431 | DP(NETIF_MSG_LINK, " int_mask 0x%x, MI_INT %x, SERDES_LINK %x\n", | ||
4432 | REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), | ||
4433 | REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + port*0x18), | ||
4434 | REG_RD(bp, NIG_REG_SERDES0_STATUS_LINK_STATUS+port*0x3c)); | ||
4435 | DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n", | ||
4436 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), | ||
4437 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); | ||
4438 | } | ||
4439 | |||
4440 | static void bnx2x_8481_rearm_latch_signal(struct bnx2x *bp, u8 port, | ||
4441 | u8 is_mi_int) | ||
4442 | { | ||
4443 | u32 latch_status = 0, is_mi_int_status; | ||
4444 | /* Disable the MI INT ( external phy int ) | ||
4445 | * by writing 1 to the status register. Link down indication | ||
4446 | * is high-active-signal, so in this case we need to write the | ||
4447 | * status to clear the XOR | ||
4448 | */ | ||
4449 | /* Read Latched signals */ | ||
4450 | latch_status = REG_RD(bp, | ||
4451 | NIG_REG_LATCH_STATUS_0 + port*8); | ||
4452 | is_mi_int_status = REG_RD(bp, | ||
4453 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4); | ||
4454 | DP(NETIF_MSG_LINK, "original_signal = 0x%x, nig_status = 0x%x," | ||
4455 | "latch_status = 0x%x\n", | ||
4456 | is_mi_int, is_mi_int_status, latch_status); | ||
4457 | /* Handle only those with latched-signal=up.*/ | ||
4458 | if (latch_status & 1) { | ||
4459 | /* For all latched-signal=up,Write original_signal to status */ | ||
4460 | if (is_mi_int) | ||
4461 | bnx2x_bits_en(bp, | ||
4462 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
4463 | + port*4, | ||
4464 | NIG_STATUS_EMAC0_MI_INT); | ||
4465 | else | ||
4466 | bnx2x_bits_dis(bp, | ||
4467 | NIG_REG_STATUS_INTERRUPT_PORT0 | ||
4468 | + port*4, | ||
4469 | NIG_STATUS_EMAC0_MI_INT); | ||
4470 | /* For all latched-signal=up : Re-Arm Latch signals */ | ||
4471 | REG_WR(bp, NIG_REG_LATCH_STATUS_0 + port*8, | ||
4472 | (latch_status & 0xfffe) | (latch_status & 1)); | ||
4473 | } | ||
4474 | } | ||
4475 | |||
4476 | /* | ||
4477 | * link management | ||
4478 | */ | ||
4479 | static void bnx2x_link_int_ack(struct link_params *params, | ||
4480 | struct link_vars *vars, u8 is_10g, | ||
4481 | u8 is_mi_int) | ||
4482 | { | ||
4483 | struct bnx2x *bp = params->bp; | ||
4484 | u8 port = params->port; | ||
4485 | |||
4486 | /* first reset all status | ||
4487 | * we assume only one line will be change at a time */ | ||
4488 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
4489 | (NIG_STATUS_XGXS0_LINK10G | | ||
4490 | NIG_STATUS_XGXS0_LINK_STATUS | | ||
4491 | NIG_STATUS_SERDES0_LINK_STATUS)); | ||
4492 | if ((params->phy[EXT_PHY1].type | ||
4493 | == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) || | ||
4494 | (params->phy[EXT_PHY1].type | ||
4495 | == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM84823)) { | ||
4496 | bnx2x_8481_rearm_latch_signal(bp, port, is_mi_int); | ||
4497 | } | ||
4498 | if (vars->phy_link_up) { | ||
4499 | if (is_10g) { | ||
4500 | /* Disable the 10G link interrupt | ||
4501 | * by writing 1 to the status register | ||
4502 | */ | ||
4503 | DP(NETIF_MSG_LINK, "10G XGXS phy link up\n"); | ||
4504 | bnx2x_bits_en(bp, | ||
4505 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
4506 | NIG_STATUS_XGXS0_LINK10G); | ||
4507 | |||
4508 | } else if (params->switch_cfg == SWITCH_CFG_10G) { | ||
4509 | /* Disable the link interrupt | ||
4510 | * by writing 1 to the relevant lane | ||
4511 | * in the status register | ||
4512 | */ | ||
4513 | u32 ser_lane = ((params->lane_config & | ||
4514 | PORT_HW_CFG_LANE_SWAP_CFG_MASTER_MASK) >> | ||
4515 | PORT_HW_CFG_LANE_SWAP_CFG_MASTER_SHIFT); | ||
4516 | |||
4517 | DP(NETIF_MSG_LINK, "%d speed XGXS phy link up\n", | ||
4518 | vars->line_speed); | ||
4519 | bnx2x_bits_en(bp, | ||
4520 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
4521 | ((1 << ser_lane) << | ||
4522 | NIG_STATUS_XGXS0_LINK_STATUS_SIZE)); | ||
4523 | |||
4524 | } else { /* SerDes */ | ||
4525 | DP(NETIF_MSG_LINK, "SerDes phy link up\n"); | ||
4526 | /* Disable the link interrupt | ||
4527 | * by writing 1 to the status register | ||
4528 | */ | ||
4529 | bnx2x_bits_en(bp, | ||
4530 | NIG_REG_STATUS_INTERRUPT_PORT0 + port*4, | ||
4531 | NIG_STATUS_SERDES0_LINK_STATUS); | ||
4532 | } | ||
4533 | |||
4534 | } | ||
4535 | } | ||
4536 | |||
4537 | static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len) | ||
4538 | { | ||
4539 | if (*len < 5) | ||
4540 | return -EINVAL; | ||
4541 | str[0] = (spirom_ver & 0xFF); | ||
4542 | str[1] = (spirom_ver & 0xFF00) >> 8; | ||
4543 | str[2] = (spirom_ver & 0xFF0000) >> 16; | ||
4544 | str[3] = (spirom_ver & 0xFF000000) >> 24; | ||
4545 | str[4] = '\0'; | ||
4546 | *len -= 5; | ||
4547 | return 0; | ||
4548 | } | ||
4549 | |||
4550 | static u8 bnx2x_format_ver(u32 num, u8 *str, u16 *len) | ||
4551 | { | ||
4552 | u8 *str_ptr = str; | ||
4553 | u32 mask = 0xf0000000; | ||
4554 | u8 shift = 8*4; | ||
4555 | u8 digit; | ||
4556 | if (*len < 10) { | ||
4557 | /* Need more than 10chars for this format */ | ||
4558 | *str_ptr = '\0'; | ||
4559 | return -EINVAL; | ||
4560 | } | ||
4561 | while (shift > 0) { | ||
4562 | |||
4563 | shift -= 4; | ||
4564 | digit = ((num & mask) >> shift); | ||
4565 | if (digit < 0xa) | ||
4566 | *str_ptr = digit + '0'; | ||
4567 | else | ||
4568 | *str_ptr = digit - 0xa + 'a'; | ||
4569 | str_ptr++; | ||
4570 | mask = mask >> 4; | ||
4571 | if (shift == 4*4) { | ||
4572 | *str_ptr = ':'; | ||
4573 | str_ptr++; | ||
4574 | } | ||
4575 | } | ||
4576 | *str_ptr = '\0'; | ||
4577 | return 0; | ||
4578 | } | ||
4579 | |||
4580 | static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len) | 5228 | static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len) |
4581 | { | 5229 | { |
4582 | u8 status = 0; | 5230 | u8 status = 0; |
@@ -4586,603 +5234,15 @@ static u8 bnx2x_848xx_format_ver(u32 raw_ver, u8 *str, u16 *len) | |||
4586 | return status; | 5234 | return status; |
4587 | } | 5235 | } |
4588 | 5236 | ||
4589 | static u8 bnx2x_null_format_ver(u32 spirom_ver, u8 *str, u16 *len) | 5237 | static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy, |
4590 | { | 5238 | struct link_params *params) |
4591 | str[0] = '\0'; | ||
4592 | (*len)--; | ||
4593 | return 0; | ||
4594 | } | ||
4595 | u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | ||
4596 | u8 *version, u16 len) | ||
4597 | { | ||
4598 | struct bnx2x *bp; | ||
4599 | u32 spirom_ver = 0; | ||
4600 | u8 status = 0; | ||
4601 | u8 *ver_p = version; | ||
4602 | if (version == NULL || params == NULL) | ||
4603 | return -EINVAL; | ||
4604 | bp = params->bp; | ||
4605 | |||
4606 | /* Extract first external phy*/ | ||
4607 | version[0] = '\0'; | ||
4608 | spirom_ver = REG_RD(bp, params->phy[EXT_PHY1].ver_addr); | ||
4609 | |||
4610 | if (params->phy[EXT_PHY1].format_fw_ver) | ||
4611 | status |= params->phy[EXT_PHY1].format_fw_ver(spirom_ver, | ||
4612 | ver_p, | ||
4613 | &len); | ||
4614 | return status; | ||
4615 | } | ||
4616 | |||
4617 | static void bnx2x_set_xgxs_loopback(struct bnx2x_phy *phy, | ||
4618 | struct link_params *params) | ||
4619 | { | ||
4620 | u8 port = params->port; | ||
4621 | struct bnx2x *bp = params->bp; | ||
4622 | |||
4623 | if (phy->req_line_speed != SPEED_1000) { | ||
4624 | u32 md_devad; | ||
4625 | |||
4626 | DP(NETIF_MSG_LINK, "XGXS 10G loopback enable\n"); | ||
4627 | |||
4628 | /* change the uni_phy_addr in the nig */ | ||
4629 | md_devad = REG_RD(bp, (NIG_REG_XGXS0_CTRL_MD_DEVAD + | ||
4630 | port*0x18)); | ||
4631 | |||
4632 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, 0x5); | ||
4633 | |||
4634 | bnx2x_cl45_write(bp, phy, | ||
4635 | 5, | ||
4636 | (MDIO_REG_BANK_AER_BLOCK + | ||
4637 | (MDIO_AER_BLOCK_AER_REG & 0xf)), | ||
4638 | 0x2800); | ||
4639 | |||
4640 | bnx2x_cl45_write(bp, phy, | ||
4641 | 5, | ||
4642 | (MDIO_REG_BANK_CL73_IEEEB0 + | ||
4643 | (MDIO_CL73_IEEEB0_CL73_AN_CONTROL & 0xf)), | ||
4644 | 0x6041); | ||
4645 | msleep(200); | ||
4646 | /* set aer mmd back */ | ||
4647 | bnx2x_set_aer_mmd(params, phy); | ||
4648 | |||
4649 | /* and md_devad */ | ||
4650 | REG_WR(bp, NIG_REG_XGXS0_CTRL_MD_DEVAD + port*0x18, | ||
4651 | md_devad); | ||
4652 | |||
4653 | } else { | ||
4654 | u16 mii_ctrl; | ||
4655 | DP(NETIF_MSG_LINK, "XGXS 1G loopback enable\n"); | ||
4656 | bnx2x_cl45_read(bp, phy, 5, | ||
4657 | (MDIO_REG_BANK_COMBO_IEEE0 + | ||
4658 | (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)), | ||
4659 | &mii_ctrl); | ||
4660 | bnx2x_cl45_write(bp, phy, 5, | ||
4661 | (MDIO_REG_BANK_COMBO_IEEE0 + | ||
4662 | (MDIO_COMBO_IEEE0_MII_CONTROL & 0xf)), | ||
4663 | mii_ctrl | | ||
4664 | MDIO_COMBO_IEEO_MII_CONTROL_LOOPBACK); | ||
4665 | } | ||
4666 | } | ||
4667 | |||
4668 | static void bnx2x_8726_config_loopback(struct bnx2x_phy *phy, | ||
4669 | struct link_params *params) | ||
4670 | { | ||
4671 | struct bnx2x *bp = params->bp; | ||
4672 | DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n"); | ||
4673 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 0x0001); | ||
4674 | } | ||
4675 | |||
4676 | static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy, | ||
4677 | struct link_params *params) | ||
4678 | { | ||
4679 | struct bnx2x *bp = params->bp; | ||
4680 | /* SFX7101_XGXS_TEST1 */ | ||
4681 | bnx2x_cl45_write(bp, phy, | ||
4682 | MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100); | ||
4683 | } | ||
4684 | |||
4685 | /* | ||
4686 | *------------------------------------------------------------------------ | ||
4687 | * bnx2x_override_led_value - | ||
4688 | * | ||
4689 | * Override the led value of the requested led | ||
4690 | * | ||
4691 | *------------------------------------------------------------------------ | ||
4692 | */ | ||
4693 | u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, | ||
4694 | u32 led_idx, u32 value) | ||
4695 | { | ||
4696 | u32 reg_val; | ||
4697 | |||
4698 | /* If port 0 then use EMAC0, else use EMAC1*/ | ||
4699 | u32 emac_base = (port) ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
4700 | |||
4701 | DP(NETIF_MSG_LINK, | ||
4702 | "bnx2x_override_led_value() port %x led_idx %d value %d\n", | ||
4703 | port, led_idx, value); | ||
4704 | |||
4705 | switch (led_idx) { | ||
4706 | case 0: /* 10MB led */ | ||
4707 | /* Read the current value of the LED register in | ||
4708 | the EMAC block */ | ||
4709 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
4710 | /* Set the OVERRIDE bit to 1 */ | ||
4711 | reg_val |= EMAC_LED_OVERRIDE; | ||
4712 | /* If value is 1, set the 10M_OVERRIDE bit, | ||
4713 | otherwise reset it.*/ | ||
4714 | reg_val = (value == 1) ? (reg_val | EMAC_LED_10MB_OVERRIDE) : | ||
4715 | (reg_val & ~EMAC_LED_10MB_OVERRIDE); | ||
4716 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
4717 | break; | ||
4718 | case 1: /*100MB led */ | ||
4719 | /*Read the current value of the LED register in | ||
4720 | the EMAC block */ | ||
4721 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
4722 | /* Set the OVERRIDE bit to 1 */ | ||
4723 | reg_val |= EMAC_LED_OVERRIDE; | ||
4724 | /* If value is 1, set the 100M_OVERRIDE bit, | ||
4725 | otherwise reset it.*/ | ||
4726 | reg_val = (value == 1) ? (reg_val | EMAC_LED_100MB_OVERRIDE) : | ||
4727 | (reg_val & ~EMAC_LED_100MB_OVERRIDE); | ||
4728 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
4729 | break; | ||
4730 | case 2: /* 1000MB led */ | ||
4731 | /* Read the current value of the LED register in the | ||
4732 | EMAC block */ | ||
4733 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
4734 | /* Set the OVERRIDE bit to 1 */ | ||
4735 | reg_val |= EMAC_LED_OVERRIDE; | ||
4736 | /* If value is 1, set the 1000M_OVERRIDE bit, otherwise | ||
4737 | reset it. */ | ||
4738 | reg_val = (value == 1) ? (reg_val | EMAC_LED_1000MB_OVERRIDE) : | ||
4739 | (reg_val & ~EMAC_LED_1000MB_OVERRIDE); | ||
4740 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
4741 | break; | ||
4742 | case 3: /* 2500MB led */ | ||
4743 | /* Read the current value of the LED register in the | ||
4744 | EMAC block*/ | ||
4745 | reg_val = REG_RD(bp, emac_base + EMAC_REG_EMAC_LED); | ||
4746 | /* Set the OVERRIDE bit to 1 */ | ||
4747 | reg_val |= EMAC_LED_OVERRIDE; | ||
4748 | /* If value is 1, set the 2500M_OVERRIDE bit, otherwise | ||
4749 | reset it.*/ | ||
4750 | reg_val = (value == 1) ? (reg_val | EMAC_LED_2500MB_OVERRIDE) : | ||
4751 | (reg_val & ~EMAC_LED_2500MB_OVERRIDE); | ||
4752 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
4753 | break; | ||
4754 | case 4: /*10G led */ | ||
4755 | if (port == 0) { | ||
4756 | REG_WR(bp, NIG_REG_LED_10G_P0, | ||
4757 | value); | ||
4758 | } else { | ||
4759 | REG_WR(bp, NIG_REG_LED_10G_P1, | ||
4760 | value); | ||
4761 | } | ||
4762 | break; | ||
4763 | case 5: /* TRAFFIC led */ | ||
4764 | /* Find if the traffic control is via BMAC or EMAC */ | ||
4765 | if (port == 0) | ||
4766 | reg_val = REG_RD(bp, NIG_REG_NIG_EMAC0_EN); | ||
4767 | else | ||
4768 | reg_val = REG_RD(bp, NIG_REG_NIG_EMAC1_EN); | ||
4769 | |||
4770 | /* Override the traffic led in the EMAC:*/ | ||
4771 | if (reg_val == 1) { | ||
4772 | /* Read the current value of the LED register in | ||
4773 | the EMAC block */ | ||
4774 | reg_val = REG_RD(bp, emac_base + | ||
4775 | EMAC_REG_EMAC_LED); | ||
4776 | /* Set the TRAFFIC_OVERRIDE bit to 1 */ | ||
4777 | reg_val |= EMAC_LED_OVERRIDE; | ||
4778 | /* If value is 1, set the TRAFFIC bit, otherwise | ||
4779 | reset it.*/ | ||
4780 | reg_val = (value == 1) ? (reg_val | EMAC_LED_TRAFFIC) : | ||
4781 | (reg_val & ~EMAC_LED_TRAFFIC); | ||
4782 | REG_WR(bp, emac_base + EMAC_REG_EMAC_LED, reg_val); | ||
4783 | } else { /* Override the traffic led in the BMAC: */ | ||
4784 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 | ||
4785 | + port*4, 1); | ||
4786 | REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + port*4, | ||
4787 | value); | ||
4788 | } | ||
4789 | break; | ||
4790 | default: | ||
4791 | DP(NETIF_MSG_LINK, | ||
4792 | "bnx2x_override_led_value() unknown led index %d " | ||
4793 | "(should be 0-5)\n", led_idx); | ||
4794 | return -EINVAL; | ||
4795 | } | ||
4796 | |||
4797 | return 0; | ||
4798 | } | ||
4799 | |||
4800 | |||
4801 | u8 bnx2x_set_led(struct link_params *params, u8 mode, u32 speed) | ||
4802 | { | ||
4803 | u8 port = params->port; | ||
4804 | u16 hw_led_mode = params->hw_led_mode; | ||
4805 | u8 rc = 0; | ||
4806 | u32 tmp; | ||
4807 | u32 emac_base = port ? GRCBASE_EMAC1 : GRCBASE_EMAC0; | ||
4808 | struct bnx2x *bp = params->bp; | ||
4809 | DP(NETIF_MSG_LINK, "bnx2x_set_led: port %x, mode %d\n", port, mode); | ||
4810 | DP(NETIF_MSG_LINK, "speed 0x%x, hw_led_mode 0x%x\n", | ||
4811 | speed, hw_led_mode); | ||
4812 | switch (mode) { | ||
4813 | case LED_MODE_OFF: | ||
4814 | REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 0); | ||
4815 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, | ||
4816 | SHARED_HW_CFG_LED_MAC1); | ||
4817 | |||
4818 | tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); | ||
4819 | EMAC_WR(bp, EMAC_REG_EMAC_LED, (tmp | EMAC_LED_OVERRIDE)); | ||
4820 | break; | ||
4821 | |||
4822 | case LED_MODE_OPER: | ||
4823 | if (SINGLE_MEDIA_DIRECT(params)) { | ||
4824 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, 0); | ||
4825 | REG_WR(bp, NIG_REG_LED_10G_P0 + port*4, 1); | ||
4826 | } else { | ||
4827 | REG_WR(bp, NIG_REG_LED_MODE_P0 + port*4, | ||
4828 | hw_led_mode); | ||
4829 | } | ||
4830 | |||
4831 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 + | ||
4832 | port*4, 0); | ||
4833 | /* Set blinking rate to ~15.9Hz */ | ||
4834 | REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_P0 + port*4, | ||
4835 | LED_BLINK_RATE_VAL); | ||
4836 | REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_RATE_ENA_P0 + | ||
4837 | port*4, 1); | ||
4838 | tmp = EMAC_RD(bp, EMAC_REG_EMAC_LED); | ||
4839 | EMAC_WR(bp, EMAC_REG_EMAC_LED, | ||
4840 | (tmp & (~EMAC_LED_OVERRIDE))); | ||
4841 | |||
4842 | if (CHIP_IS_E1(bp) && | ||
4843 | ((speed == SPEED_2500) || | ||
4844 | (speed == SPEED_1000) || | ||
4845 | (speed == SPEED_100) || | ||
4846 | (speed == SPEED_10))) { | ||
4847 | /* On Everest 1 Ax chip versions for speeds less than | ||
4848 | 10G LED scheme is different */ | ||
4849 | REG_WR(bp, NIG_REG_LED_CONTROL_OVERRIDE_TRAFFIC_P0 | ||
4850 | + port*4, 1); | ||
4851 | REG_WR(bp, NIG_REG_LED_CONTROL_TRAFFIC_P0 + | ||
4852 | port*4, 0); | ||
4853 | REG_WR(bp, NIG_REG_LED_CONTROL_BLINK_TRAFFIC_P0 + | ||
4854 | port*4, 1); | ||
4855 | } | ||
4856 | break; | ||
4857 | |||
4858 | default: | ||
4859 | rc = -EINVAL; | ||
4860 | DP(NETIF_MSG_LINK, "bnx2x_set_led: Invalid led mode %d\n", | ||
4861 | mode); | ||
4862 | break; | ||
4863 | } | ||
4864 | return rc; | ||
4865 | |||
4866 | } | ||
4867 | |||
4868 | u8 bnx2x_test_link(struct link_params *params, struct link_vars *vars) | ||
4869 | { | ||
4870 | struct bnx2x *bp = params->bp; | ||
4871 | u16 gp_status = 0, phy_index = 0; | ||
4872 | |||
4873 | CL45_RD_OVER_CL22(bp, ¶ms->phy[INT_PHY], | ||
4874 | MDIO_REG_BANK_GP_STATUS, | ||
4875 | MDIO_GP_STATUS_TOP_AN_STATUS1, | ||
4876 | &gp_status); | ||
4877 | /* link is up only if both local phy and external phy are up */ | ||
4878 | if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) { | ||
4879 | u8 ext_phy_link_up = 1; | ||
4880 | struct link_vars temp_vars; | ||
4881 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
4882 | phy_index++) { | ||
4883 | if (params->phy[phy_index].read_status) | ||
4884 | ext_phy_link_up &= | ||
4885 | params->phy[phy_index].read_status( | ||
4886 | ¶ms->phy[phy_index], | ||
4887 | params, &temp_vars); | ||
4888 | } | ||
4889 | if (ext_phy_link_up) | ||
4890 | return 0; | ||
4891 | } | ||
4892 | return -ESRCH; | ||
4893 | } | ||
4894 | |||
4895 | static u8 bnx2x_link_initialize(struct link_params *params, | ||
4896 | struct link_vars *vars) | ||
4897 | { | ||
4898 | u8 rc = 0; | ||
4899 | u8 phy_index, non_ext_phy; | ||
4900 | struct bnx2x *bp = params->bp; | ||
4901 | /** | ||
4902 | * In case of external phy existence, the line speed would be the | ||
4903 | * line speed linked up by the external phy. In case it is direct | ||
4904 | * only, then the line_speed during initialization will be | ||
4905 | * equal to the req_line_speed | ||
4906 | */ | ||
4907 | vars->line_speed = params->phy[INT_PHY].req_line_speed; | ||
4908 | |||
4909 | /** | ||
4910 | * Initialize the internal phy in case this is a direct board | ||
4911 | * (no external phys), or this board has external phy which requires | ||
4912 | * to first. | ||
4913 | */ | ||
4914 | |||
4915 | if (params->phy[INT_PHY].config_init) | ||
4916 | params->phy[INT_PHY].config_init( | ||
4917 | ¶ms->phy[INT_PHY], | ||
4918 | params, vars); | ||
4919 | |||
4920 | /* init ext phy and enable link state int */ | ||
4921 | non_ext_phy = (SINGLE_MEDIA_DIRECT(params) || | ||
4922 | (params->loopback_mode == LOOPBACK_XGXS_10)); | ||
4923 | |||
4924 | if (non_ext_phy || | ||
4925 | (params->phy[EXT_PHY1].flags & FLAGS_INIT_XGXS_FIRST) || | ||
4926 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { | ||
4927 | struct bnx2x_phy *phy = ¶ms->phy[INT_PHY]; | ||
4928 | if (vars->line_speed == SPEED_AUTO_NEG) | ||
4929 | bnx2x_set_parallel_detection(phy, params); | ||
4930 | bnx2x_init_internal_phy(phy, params, vars); | ||
4931 | } | ||
4932 | |||
4933 | /* Init external phy*/ | ||
4934 | if (!non_ext_phy) | ||
4935 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
4936 | phy_index++) { | ||
4937 | params->phy[phy_index].config_init( | ||
4938 | ¶ms->phy[phy_index], | ||
4939 | params, vars); | ||
4940 | } | ||
4941 | |||
4942 | /* Reset the interrupt indication after phy was initialized */ | ||
4943 | bnx2x_bits_dis(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + | ||
4944 | params->port*4, | ||
4945 | (NIG_STATUS_XGXS0_LINK10G | | ||
4946 | NIG_STATUS_XGXS0_LINK_STATUS | | ||
4947 | NIG_STATUS_SERDES0_LINK_STATUS | | ||
4948 | NIG_MASK_MI_INT)); | ||
4949 | return rc; | ||
4950 | } | ||
4951 | |||
4952 | static void set_phy_vars(struct link_params *params) | ||
4953 | { | ||
4954 | struct bnx2x *bp = params->bp; | ||
4955 | u8 actual_phy_idx, phy_index; | ||
4956 | |||
4957 | for (phy_index = INT_PHY; phy_index < params->num_phys; | ||
4958 | phy_index++) { | ||
4959 | |||
4960 | actual_phy_idx = phy_index; | ||
4961 | params->phy[actual_phy_idx].req_flow_ctrl = | ||
4962 | params->req_flow_ctrl; | ||
4963 | |||
4964 | params->phy[actual_phy_idx].req_line_speed = | ||
4965 | params->req_line_speed; | ||
4966 | |||
4967 | params->phy[actual_phy_idx].speed_cap_mask = | ||
4968 | params->speed_cap_mask; | ||
4969 | |||
4970 | params->phy[actual_phy_idx].req_duplex = | ||
4971 | params->req_duplex; | ||
4972 | |||
4973 | DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x," | ||
4974 | " speed_cap_mask %x\n", | ||
4975 | params->phy[actual_phy_idx].req_flow_ctrl, | ||
4976 | params->phy[actual_phy_idx].req_line_speed, | ||
4977 | params->phy[actual_phy_idx].speed_cap_mask); | ||
4978 | } | ||
4979 | } | ||
4980 | |||
4981 | u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | ||
4982 | { | ||
4983 | struct bnx2x *bp = params->bp; | ||
4984 | u32 val; | ||
4985 | |||
4986 | DP(NETIF_MSG_LINK, "Phy Initialization started\n"); | ||
4987 | DP(NETIF_MSG_LINK, "req_speed %d, req_flowctrl %d\n", | ||
4988 | params->req_line_speed, params->req_flow_ctrl); | ||
4989 | vars->link_status = 0; | ||
4990 | vars->phy_link_up = 0; | ||
4991 | vars->link_up = 0; | ||
4992 | vars->line_speed = 0; | ||
4993 | vars->duplex = DUPLEX_FULL; | ||
4994 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
4995 | vars->mac_type = MAC_TYPE_NONE; | ||
4996 | vars->phy_flags = 0; | ||
4997 | |||
4998 | /* disable attentions */ | ||
4999 | bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4, | ||
5000 | (NIG_MASK_XGXS0_LINK_STATUS | | ||
5001 | NIG_MASK_XGXS0_LINK10G | | ||
5002 | NIG_MASK_SERDES0_LINK_STATUS | | ||
5003 | NIG_MASK_MI_INT)); | ||
5004 | |||
5005 | bnx2x_emac_init(params, vars); | ||
5006 | |||
5007 | if (params->num_phys == 0) { | ||
5008 | DP(NETIF_MSG_LINK, "No phy found for initialization !!\n"); | ||
5009 | return -EINVAL; | ||
5010 | } | ||
5011 | set_phy_vars(params); | ||
5012 | |||
5013 | DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys); | ||
5014 | if (CHIP_REV_IS_FPGA(bp)) { | ||
5015 | |||
5016 | vars->link_up = 1; | ||
5017 | vars->line_speed = SPEED_10000; | ||
5018 | vars->duplex = DUPLEX_FULL; | ||
5019 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
5020 | vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD); | ||
5021 | /* enable on E1.5 FPGA */ | ||
5022 | if (CHIP_IS_E1H(bp)) { | ||
5023 | vars->flow_ctrl |= | ||
5024 | (BNX2X_FLOW_CTRL_TX | | ||
5025 | BNX2X_FLOW_CTRL_RX); | ||
5026 | vars->link_status |= | ||
5027 | (LINK_STATUS_TX_FLOW_CONTROL_ENABLED | | ||
5028 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED); | ||
5029 | } | ||
5030 | |||
5031 | bnx2x_emac_enable(params, vars, 0); | ||
5032 | bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed); | ||
5033 | /* disable drain */ | ||
5034 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); | ||
5035 | |||
5036 | /* update shared memory */ | ||
5037 | bnx2x_update_mng(params, vars->link_status); | ||
5038 | |||
5039 | return 0; | ||
5040 | |||
5041 | } else | ||
5042 | if (CHIP_REV_IS_EMUL(bp)) { | ||
5043 | |||
5044 | vars->link_up = 1; | ||
5045 | vars->line_speed = SPEED_10000; | ||
5046 | vars->duplex = DUPLEX_FULL; | ||
5047 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
5048 | vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD); | ||
5049 | |||
5050 | bnx2x_bmac_enable(params, vars, 0); | ||
5051 | |||
5052 | bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed); | ||
5053 | /* Disable drain */ | ||
5054 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE | ||
5055 | + params->port*4, 0); | ||
5056 | |||
5057 | /* update shared memory */ | ||
5058 | bnx2x_update_mng(params, vars->link_status); | ||
5059 | |||
5060 | return 0; | ||
5061 | |||
5062 | } else | ||
5063 | if (params->loopback_mode == LOOPBACK_BMAC) { | ||
5064 | |||
5065 | vars->link_up = 1; | ||
5066 | vars->line_speed = SPEED_10000; | ||
5067 | vars->duplex = DUPLEX_FULL; | ||
5068 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
5069 | vars->mac_type = MAC_TYPE_BMAC; | ||
5070 | |||
5071 | vars->phy_flags = PHY_XGXS_FLAG; | ||
5072 | |||
5073 | bnx2x_xgxs_deassert(params); | ||
5074 | |||
5075 | /* set bmac loopback */ | ||
5076 | bnx2x_bmac_enable(params, vars, 1); | ||
5077 | |||
5078 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + | ||
5079 | params->port*4, 0); | ||
5080 | |||
5081 | } else if (params->loopback_mode == LOOPBACK_EMAC) { | ||
5082 | |||
5083 | vars->link_up = 1; | ||
5084 | vars->line_speed = SPEED_1000; | ||
5085 | vars->duplex = DUPLEX_FULL; | ||
5086 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
5087 | vars->mac_type = MAC_TYPE_EMAC; | ||
5088 | |||
5089 | vars->phy_flags = PHY_XGXS_FLAG; | ||
5090 | |||
5091 | bnx2x_xgxs_deassert(params); | ||
5092 | /* set bmac loopback */ | ||
5093 | bnx2x_emac_enable(params, vars, 1); | ||
5094 | bnx2x_emac_program(params, vars); | ||
5095 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + | ||
5096 | params->port*4, 0); | ||
5097 | |||
5098 | } else if ((params->loopback_mode == LOOPBACK_XGXS_10) || | ||
5099 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { | ||
5100 | |||
5101 | vars->link_up = 1; | ||
5102 | vars->line_speed = SPEED_10000; | ||
5103 | vars->duplex = DUPLEX_FULL; | ||
5104 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
5105 | |||
5106 | vars->phy_flags = PHY_XGXS_FLAG; | ||
5107 | |||
5108 | val = REG_RD(bp, | ||
5109 | NIG_REG_XGXS0_CTRL_PHY_ADDR+ | ||
5110 | params->port*0x18); | ||
5111 | |||
5112 | bnx2x_xgxs_deassert(params); | ||
5113 | bnx2x_link_initialize(params, vars); | ||
5114 | |||
5115 | vars->mac_type = MAC_TYPE_BMAC; | ||
5116 | |||
5117 | bnx2x_bmac_enable(params, vars, 0); | ||
5118 | |||
5119 | if (params->loopback_mode == LOOPBACK_XGXS_10) { | ||
5120 | /* set 10G XGXS loopback */ | ||
5121 | params->phy[INT_PHY].config_loopback( | ||
5122 | ¶ms->phy[INT_PHY], | ||
5123 | params); | ||
5124 | |||
5125 | } else { | ||
5126 | /* set external phy loopback */ | ||
5127 | u8 phy_index; | ||
5128 | for (phy_index = EXT_PHY1; | ||
5129 | phy_index < params->num_phys; phy_index++) { | ||
5130 | if (params->phy[phy_index].config_loopback) | ||
5131 | params->phy[phy_index].config_loopback( | ||
5132 | ¶ms->phy[phy_index], | ||
5133 | params); | ||
5134 | } | ||
5135 | } | ||
5136 | |||
5137 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + | ||
5138 | params->port*4, 0); | ||
5139 | |||
5140 | bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed); | ||
5141 | } else | ||
5142 | /* No loopback */ | ||
5143 | { | ||
5144 | if (params->switch_cfg == SWITCH_CFG_10G) | ||
5145 | bnx2x_xgxs_deassert(params); | ||
5146 | else | ||
5147 | bnx2x_serdes_deassert(bp, params->port); | ||
5148 | bnx2x_link_initialize(params, vars); | ||
5149 | msleep(30); | ||
5150 | bnx2x_link_int_enable(params); | ||
5151 | } | ||
5152 | return 0; | ||
5153 | } | ||
5154 | |||
5155 | |||
5156 | static void bnx2x_8726_link_reset(struct bnx2x_phy *phy, | ||
5157 | struct link_params *params) | ||
5158 | { | 5239 | { |
5159 | struct bnx2x *bp = params->bp; | 5240 | bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1, |
5160 | DP(NETIF_MSG_LINK, "bnx2x_8726_link_reset port %d\n", params->port); | 5241 | MISC_REGISTERS_GPIO_OUTPUT_LOW, 0); |
5161 | /* Set serial boot control for external load */ | 5242 | bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1, |
5162 | bnx2x_cl45_write(bp, phy, | 5243 | MISC_REGISTERS_GPIO_OUTPUT_LOW, 1); |
5163 | MDIO_PMA_DEVAD, | ||
5164 | MDIO_PMA_REG_GEN_CTRL, 0x0001); | ||
5165 | } | 5244 | } |
5166 | 5245 | ||
5167 | static void bnx2x_8727_link_reset(struct bnx2x_phy *phy, | ||
5168 | struct link_params *params) | ||
5169 | { | ||
5170 | struct bnx2x *bp = params->bp; | ||
5171 | /* Disable Transmitter */ | ||
5172 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | ||
5173 | } | ||
5174 | static void bnx2x_8073_link_reset(struct bnx2x_phy *phy, | ||
5175 | struct link_params *params) | ||
5176 | { | ||
5177 | struct bnx2x *bp = params->bp; | ||
5178 | u8 gpio_port; | ||
5179 | gpio_port = params->port; | ||
5180 | DP(NETIF_MSG_LINK, "Setting 8073 port %d into low power mode\n", | ||
5181 | gpio_port); | ||
5182 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
5183 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
5184 | gpio_port); | ||
5185 | } | ||
5186 | static void bnx2x_8481_link_reset(struct bnx2x_phy *phy, | 5246 | static void bnx2x_8481_link_reset(struct bnx2x_phy *phy, |
5187 | struct link_params *params) | 5247 | struct link_params *params) |
5188 | { | 5248 | { |
@@ -5202,385 +5262,131 @@ static void bnx2x_848x3_link_reset(struct bnx2x_phy *phy, | |||
5202 | port); | 5262 | port); |
5203 | } | 5263 | } |
5204 | 5264 | ||
5205 | static void bnx2x_common_ext_link_reset(struct bnx2x_phy *phy, | 5265 | /******************************************************************/ |
5206 | struct link_params *params) | 5266 | /* SFX7101 PHY SECTION */ |
5267 | /******************************************************************/ | ||
5268 | static void bnx2x_7101_config_loopback(struct bnx2x_phy *phy, | ||
5269 | struct link_params *params) | ||
5207 | { | 5270 | { |
5208 | struct bnx2x *bp = params->bp; | 5271 | struct bnx2x *bp = params->bp; |
5209 | u8 gpio_port; | 5272 | /* SFX7101_XGXS_TEST1 */ |
5210 | /* HW reset */ | 5273 | bnx2x_cl45_write(bp, phy, |
5211 | gpio_port = params->port; | 5274 | MDIO_XS_DEVAD, MDIO_XS_SFX7101_XGXS_TEST1, 0x100); |
5212 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
5213 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
5214 | gpio_port); | ||
5215 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
5216 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
5217 | gpio_port); | ||
5218 | DP(NETIF_MSG_LINK, "reset external PHY\n"); | ||
5219 | } | ||
5220 | |||
5221 | static void bnx2x_int_link_reset(struct bnx2x_phy *phy, | ||
5222 | struct link_params *params) | ||
5223 | { | ||
5224 | /* reset the SerDes/XGXS */ | ||
5225 | REG_WR(params->bp, GRCBASE_MISC + | ||
5226 | MISC_REGISTERS_RESET_REG_3_CLEAR, | ||
5227 | (0x1ff << (params->port*16))); | ||
5228 | } | 5275 | } |
5229 | 5276 | ||
5230 | u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | 5277 | static u8 bnx2x_7101_config_init(struct bnx2x_phy *phy, |
5231 | u8 reset_ext_phy) | 5278 | struct link_params *params, |
5279 | struct link_vars *vars) | ||
5232 | { | 5280 | { |
5281 | u16 fw_ver1, fw_ver2, val; | ||
5233 | struct bnx2x *bp = params->bp; | 5282 | struct bnx2x *bp = params->bp; |
5234 | u8 phy_index, port = params->port; | 5283 | DP(NETIF_MSG_LINK, "Setting the SFX7101 LASI indication\n"); |
5235 | DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port); | ||
5236 | /* disable attentions */ | ||
5237 | vars->link_status = 0; | ||
5238 | bnx2x_update_mng(params, vars->link_status); | ||
5239 | bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
5240 | (NIG_MASK_XGXS0_LINK_STATUS | | ||
5241 | NIG_MASK_XGXS0_LINK10G | | ||
5242 | NIG_MASK_SERDES0_LINK_STATUS | | ||
5243 | NIG_MASK_MI_INT)); | ||
5244 | |||
5245 | /* activate nig drain */ | ||
5246 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | ||
5247 | |||
5248 | /* disable nig egress interface */ | ||
5249 | REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0); | ||
5250 | REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); | ||
5251 | 5284 | ||
5252 | /* Stop BigMac rx */ | 5285 | /* Restore normal power mode*/ |
5253 | bnx2x_bmac_rx_disable(bp, port); | 5286 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, |
5287 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | ||
5288 | /* HW reset */ | ||
5289 | bnx2x_ext_phy_hw_reset(bp, params->port); | ||
5290 | bnx2x_wait_reset_complete(bp, phy); | ||
5254 | 5291 | ||
5255 | /* disable emac */ | 5292 | bnx2x_cl45_write(bp, phy, |
5256 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); | 5293 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0x1); |
5294 | DP(NETIF_MSG_LINK, "Setting the SFX7101 LED to blink on traffic\n"); | ||
5295 | bnx2x_cl45_write(bp, phy, | ||
5296 | MDIO_PMA_DEVAD, MDIO_PMA_REG_7107_LED_CNTL, (1<<3)); | ||
5257 | 5297 | ||
5258 | msleep(10); | 5298 | bnx2x_ext_phy_set_pause(params, phy, vars); |
5259 | /* The PHY reset is controled by GPIO 1 | 5299 | /* Restart autoneg */ |
5260 | * Hold it as vars low | 5300 | bnx2x_cl45_read(bp, phy, |
5261 | */ | 5301 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, &val); |
5262 | /* clear link led */ | 5302 | val |= 0x200; |
5263 | bnx2x_set_led(params, LED_MODE_OFF, 0); | 5303 | bnx2x_cl45_write(bp, phy, |
5264 | if (reset_ext_phy) { | 5304 | MDIO_AN_DEVAD, MDIO_AN_REG_CTRL, val); |
5265 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
5266 | phy_index++) { | ||
5267 | if (params->phy[phy_index].link_reset) | ||
5268 | params->phy[phy_index].link_reset( | ||
5269 | ¶ms->phy[phy_index], | ||
5270 | params); | ||
5271 | } | ||
5272 | } | ||
5273 | 5305 | ||
5274 | if (params->phy[INT_PHY].link_reset) | 5306 | /* Save spirom version */ |
5275 | params->phy[INT_PHY].link_reset( | 5307 | bnx2x_cl45_read(bp, phy, |
5276 | ¶ms->phy[INT_PHY], params); | 5308 | MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER1, &fw_ver1); |
5277 | /* reset BigMac */ | ||
5278 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
5279 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
5280 | 5309 | ||
5281 | /* disable nig ingress interface */ | 5310 | bnx2x_cl45_read(bp, phy, |
5282 | REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0); | 5311 | MDIO_PMA_DEVAD, MDIO_PMA_REG_7101_VER2, &fw_ver2); |
5283 | REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0); | 5312 | bnx2x_save_spirom_version(bp, params->port, |
5284 | REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0); | 5313 | (u32)(fw_ver1<<16 | fw_ver2), phy->ver_addr); |
5285 | REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); | ||
5286 | vars->link_up = 0; | ||
5287 | return 0; | 5314 | return 0; |
5288 | } | 5315 | } |
5289 | 5316 | ||
5290 | static u8 bnx2x_update_link_down(struct link_params *params, | 5317 | static u8 bnx2x_7101_read_status(struct bnx2x_phy *phy, |
5291 | struct link_vars *vars) | 5318 | struct link_params *params, |
5319 | struct link_vars *vars) | ||
5292 | { | 5320 | { |
5293 | struct bnx2x *bp = params->bp; | 5321 | struct bnx2x *bp = params->bp; |
5294 | u8 port = params->port; | 5322 | u8 link_up; |
5295 | 5323 | u16 val1, val2; | |
5296 | DP(NETIF_MSG_LINK, "Port %x: Link is down\n", port); | 5324 | bnx2x_cl45_read(bp, phy, |
5297 | bnx2x_set_led(params, LED_MODE_OFF, 0); | 5325 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val2); |
5298 | 5326 | bnx2x_cl45_read(bp, phy, | |
5299 | /* indicate no mac active */ | 5327 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, &val1); |
5300 | vars->mac_type = MAC_TYPE_NONE; | 5328 | DP(NETIF_MSG_LINK, "10G-base-T LASI status 0x%x->0x%x\n", |
5301 | 5329 | val2, val1); | |
5302 | /* update shared memory */ | 5330 | bnx2x_cl45_read(bp, phy, |
5303 | vars->link_status = 0; | 5331 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val2); |
5304 | vars->line_speed = 0; | 5332 | bnx2x_cl45_read(bp, phy, |
5305 | bnx2x_update_mng(params, vars->link_status); | 5333 | MDIO_PMA_DEVAD, MDIO_PMA_REG_STATUS, &val1); |
5306 | 5334 | DP(NETIF_MSG_LINK, "10G-base-T PMA status 0x%x->0x%x\n", | |
5307 | /* activate nig drain */ | 5335 | val2, val1); |
5308 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | 5336 | link_up = ((val1 & 4) == 4); |
5309 | 5337 | /* if link is up | |
5310 | /* disable emac */ | 5338 | * print the AN outcome of the SFX7101 PHY |
5311 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); | 5339 | */ |
5340 | if (link_up) { | ||
5341 | bnx2x_cl45_read(bp, phy, | ||
5342 | MDIO_AN_DEVAD, MDIO_AN_REG_MASTER_STATUS, | ||
5343 | &val2); | ||
5344 | vars->line_speed = SPEED_10000; | ||
5345 | DP(NETIF_MSG_LINK, "SFX7101 AN status 0x%x->Master=%x\n", | ||
5346 | val2, (val2 & (1<<14))); | ||
5347 | bnx2x_ext_phy_10G_an_resolve(bp, phy, vars); | ||
5348 | bnx2x_ext_phy_resolve_fc(phy, params, vars); | ||
5349 | } | ||
5350 | return link_up; | ||
5351 | } | ||
5312 | 5352 | ||
5313 | msleep(10); | ||
5314 | 5353 | ||
5315 | /* reset BigMac */ | 5354 | static u8 bnx2x_7101_format_ver(u32 spirom_ver, u8 *str, u16 *len) |
5316 | bnx2x_bmac_rx_disable(bp, params->port); | 5355 | { |
5317 | REG_WR(bp, GRCBASE_MISC + | 5356 | if (*len < 5) |
5318 | MISC_REGISTERS_RESET_REG_2_CLEAR, | 5357 | return -EINVAL; |
5319 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | 5358 | str[0] = (spirom_ver & 0xFF); |
5359 | str[1] = (spirom_ver & 0xFF00) >> 8; | ||
5360 | str[2] = (spirom_ver & 0xFF0000) >> 16; | ||
5361 | str[3] = (spirom_ver & 0xFF000000) >> 24; | ||
5362 | str[4] = '\0'; | ||
5363 | *len -= 5; | ||
5320 | return 0; | 5364 | return 0; |
5321 | } | 5365 | } |
5322 | 5366 | ||
5323 | static u8 bnx2x_update_link_up(struct link_params *params, | 5367 | void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy) |
5324 | struct link_vars *vars, | ||
5325 | u8 link_10g) | ||
5326 | { | ||
5327 | struct bnx2x *bp = params->bp; | ||
5328 | u8 port = params->port; | ||
5329 | u8 rc = 0; | ||
5330 | |||
5331 | vars->link_status |= LINK_STATUS_LINK_UP; | ||
5332 | if (vars->flow_ctrl & BNX2X_FLOW_CTRL_TX) | ||
5333 | vars->link_status |= | ||
5334 | LINK_STATUS_TX_FLOW_CONTROL_ENABLED; | ||
5335 | |||
5336 | if (vars->flow_ctrl & BNX2X_FLOW_CTRL_RX) | ||
5337 | vars->link_status |= | ||
5338 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED; | ||
5339 | if (link_10g) { | ||
5340 | bnx2x_bmac_enable(params, vars, 0); | ||
5341 | bnx2x_set_led(params, LED_MODE_OPER, SPEED_10000); | ||
5342 | } else { | ||
5343 | rc = bnx2x_emac_program(params, vars); | ||
5344 | |||
5345 | bnx2x_emac_enable(params, vars, 0); | ||
5346 | |||
5347 | /* AN complete? */ | ||
5348 | if ((vars->link_status & LINK_STATUS_AUTO_NEGOTIATE_COMPLETE) | ||
5349 | && (!(vars->phy_flags & PHY_SGMII_FLAG)) && | ||
5350 | SINGLE_MEDIA_DIRECT(params)) | ||
5351 | bnx2x_set_gmii_tx_driver(params); | ||
5352 | } | ||
5353 | |||
5354 | /* PBF - link up */ | ||
5355 | rc |= bnx2x_pbf_update(params, vars->flow_ctrl, | ||
5356 | vars->line_speed); | ||
5357 | |||
5358 | /* disable drain */ | ||
5359 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 0); | ||
5360 | |||
5361 | /* update shared memory */ | ||
5362 | bnx2x_update_mng(params, vars->link_status); | ||
5363 | msleep(20); | ||
5364 | return rc; | ||
5365 | } | ||
5366 | /** | ||
5367 | * The bnx2x_link_update function should be called upon link | ||
5368 | * interrupt. | ||
5369 | * Link is considered up as follows: | ||
5370 | * - DIRECT_SINGLE_MEDIA - Only XGXS link (internal link) needs | ||
5371 | * to be up | ||
5372 | * - SINGLE_MEDIA - The link between the 577xx and the external | ||
5373 | * phy (XGXS) need to up as well as the external link of the | ||
5374 | * phy (PHY_EXT1) | ||
5375 | * - DUAL_MEDIA - The link between the 577xx and the first | ||
5376 | * external phy needs to be up, and at least one of the 2 | ||
5377 | * external phy link must be up. | ||
5378 | */ | ||
5379 | u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | ||
5380 | { | 5368 | { |
5381 | struct bnx2x *bp = params->bp; | 5369 | u16 val, cnt; |
5382 | struct link_vars phy_vars[MAX_PHYS]; | ||
5383 | u8 port = params->port; | ||
5384 | u8 link_10g, phy_index; | ||
5385 | u8 ext_phy_link_up = 0, cur_link_up, rc = 0; | ||
5386 | u8 is_mi_int = 0; | ||
5387 | u16 ext_phy_line_speed = 0, prev_line_speed = vars->line_speed; | ||
5388 | u8 active_external_phy = INT_PHY; | ||
5389 | vars->link_status = 0; | ||
5390 | for (phy_index = INT_PHY; phy_index < params->num_phys; | ||
5391 | phy_index++) { | ||
5392 | phy_vars[phy_index].flow_ctrl = 0; | ||
5393 | phy_vars[phy_index].link_status = 0; | ||
5394 | phy_vars[phy_index].line_speed = 0; | ||
5395 | phy_vars[phy_index].duplex = DUPLEX_FULL; | ||
5396 | phy_vars[phy_index].phy_link_up = 0; | ||
5397 | phy_vars[phy_index].link_up = 0; | ||
5398 | } | ||
5399 | |||
5400 | DP(NETIF_MSG_LINK, "port %x, XGXS?%x, int_status 0x%x\n", | ||
5401 | port, (vars->phy_flags & PHY_XGXS_FLAG), | ||
5402 | REG_RD(bp, NIG_REG_STATUS_INTERRUPT_PORT0 + port*4)); | ||
5403 | |||
5404 | is_mi_int = (u8)(REG_RD(bp, NIG_REG_EMAC0_STATUS_MISC_MI_INT + | ||
5405 | port*0x18) > 0); | ||
5406 | DP(NETIF_MSG_LINK, "int_mask 0x%x MI_INT %x, SERDES_LINK %x\n", | ||
5407 | REG_RD(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4), | ||
5408 | is_mi_int, | ||
5409 | REG_RD(bp, | ||
5410 | NIG_REG_SERDES0_STATUS_LINK_STATUS + port*0x3c)); | ||
5411 | |||
5412 | DP(NETIF_MSG_LINK, " 10G %x, XGXS_LINK %x\n", | ||
5413 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK10G + port*0x68), | ||
5414 | REG_RD(bp, NIG_REG_XGXS0_STATUS_LINK_STATUS + port*0x68)); | ||
5415 | |||
5416 | /* disable emac */ | ||
5417 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); | ||
5418 | |||
5419 | /** | ||
5420 | * Step 1: | ||
5421 | * Check external link change only for external phys, and apply | ||
5422 | * priority selection between them in case the link on both phys | ||
5423 | * is up. Note that the instead of the common vars, a temporary | ||
5424 | * vars argument is used since each phy may have different link/ | ||
5425 | * speed/duplex result | ||
5426 | */ | ||
5427 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
5428 | phy_index++) { | ||
5429 | struct bnx2x_phy *phy = ¶ms->phy[phy_index]; | ||
5430 | if (!phy->read_status) | ||
5431 | continue; | ||
5432 | /* Read link status and params of this ext phy */ | ||
5433 | cur_link_up = phy->read_status(phy, params, | ||
5434 | &phy_vars[phy_index]); | ||
5435 | if (cur_link_up) { | ||
5436 | DP(NETIF_MSG_LINK, "phy in index %d link is up\n", | ||
5437 | phy_index); | ||
5438 | } else { | ||
5439 | DP(NETIF_MSG_LINK, "phy in index %d link is down\n", | ||
5440 | phy_index); | ||
5441 | continue; | ||
5442 | } | ||
5443 | |||
5444 | if (!ext_phy_link_up) { | ||
5445 | ext_phy_link_up = 1; | ||
5446 | active_external_phy = phy_index; | ||
5447 | } | ||
5448 | } | ||
5449 | prev_line_speed = vars->line_speed; | ||
5450 | /** | ||
5451 | * Step 2: | ||
5452 | * Read the status of the internal phy. In case of | ||
5453 | * DIRECT_SINGLE_MEDIA board, this link is the external link, | ||
5454 | * otherwise this is the link between the 577xx and the first | ||
5455 | * external phy | ||
5456 | */ | ||
5457 | if (params->phy[INT_PHY].read_status) | ||
5458 | params->phy[INT_PHY].read_status( | ||
5459 | ¶ms->phy[INT_PHY], | ||
5460 | params, vars); | ||
5461 | /** | ||
5462 | * The INT_PHY flow control reside in the vars. This include the | ||
5463 | * case where the speed or flow control are not set to AUTO. | ||
5464 | * Otherwise, the active external phy flow control result is set | ||
5465 | * to the vars. The ext_phy_line_speed is needed to check if the | ||
5466 | * speed is different between the internal phy and external phy. | ||
5467 | * This case may be result of intermediate link speed change. | ||
5468 | */ | ||
5469 | if (active_external_phy > INT_PHY) { | ||
5470 | vars->flow_ctrl = phy_vars[active_external_phy].flow_ctrl; | ||
5471 | /** | ||
5472 | * Link speed is taken from the XGXS. AN and FC result from | ||
5473 | * the external phy. | ||
5474 | */ | ||
5475 | vars->link_status |= phy_vars[active_external_phy].link_status; | ||
5476 | ext_phy_line_speed = phy_vars[active_external_phy].line_speed; | ||
5477 | vars->duplex = phy_vars[active_external_phy].duplex; | ||
5478 | if (params->phy[active_external_phy].supported & | ||
5479 | SUPPORTED_FIBRE) | ||
5480 | vars->link_status |= LINK_STATUS_SERDES_LINK; | ||
5481 | DP(NETIF_MSG_LINK, "Active external phy selected: %x\n", | ||
5482 | active_external_phy); | ||
5483 | } | ||
5484 | DP(NETIF_MSG_LINK, "vars->flow_ctrl = 0x%x, vars->link_status = 0x%x," | ||
5485 | " ext_phy_line_speed = %d\n", vars->flow_ctrl, | ||
5486 | vars->link_status, ext_phy_line_speed); | ||
5487 | /** | ||
5488 | * Upon link speed change set the NIG into drain mode. Comes to | ||
5489 | * deals with possible FIFO glitch due to clk change when speed | ||
5490 | * is decreased without link down indicator | ||
5491 | */ | ||
5492 | |||
5493 | if (vars->phy_link_up) { | ||
5494 | if (!(SINGLE_MEDIA_DIRECT(params)) && ext_phy_link_up && | ||
5495 | (ext_phy_line_speed != vars->line_speed)) { | ||
5496 | DP(NETIF_MSG_LINK, "Internal link speed %d is" | ||
5497 | " different than the external" | ||
5498 | " link speed %d\n", vars->line_speed, | ||
5499 | ext_phy_line_speed); | ||
5500 | vars->phy_link_up = 0; | ||
5501 | } else if (prev_line_speed != vars->line_speed) { | ||
5502 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE | ||
5503 | + params->port*4, 0); | ||
5504 | msleep(1); | ||
5505 | } | ||
5506 | } | ||
5507 | 5370 | ||
5508 | /* anything 10 and over uses the bmac */ | 5371 | bnx2x_cl45_read(bp, phy, |
5509 | link_10g = ((vars->line_speed == SPEED_10000) || | 5372 | MDIO_PMA_DEVAD, |
5510 | (vars->line_speed == SPEED_12000) || | 5373 | MDIO_PMA_REG_7101_RESET, &val); |
5511 | (vars->line_speed == SPEED_12500) || | ||
5512 | (vars->line_speed == SPEED_13000) || | ||
5513 | (vars->line_speed == SPEED_15000) || | ||
5514 | (vars->line_speed == SPEED_16000)); | ||
5515 | 5374 | ||
5516 | bnx2x_link_int_ack(params, vars, link_10g, is_mi_int); | 5375 | for (cnt = 0; cnt < 10; cnt++) { |
5376 | msleep(50); | ||
5377 | /* Writes a self-clearing reset */ | ||
5378 | bnx2x_cl45_write(bp, phy, | ||
5379 | MDIO_PMA_DEVAD, | ||
5380 | MDIO_PMA_REG_7101_RESET, | ||
5381 | (val | (1<<15))); | ||
5382 | /* Wait for clear */ | ||
5383 | bnx2x_cl45_read(bp, phy, | ||
5384 | MDIO_PMA_DEVAD, | ||
5385 | MDIO_PMA_REG_7101_RESET, &val); | ||
5517 | 5386 | ||
5518 | /** | 5387 | if ((val & (1<<15)) == 0) |
5519 | * In case external phy link is up, and internal link is down | 5388 | break; |
5520 | * (not initialized yet probably after link initialization, it | ||
5521 | * needs to be initialized. | ||
5522 | * Note that after link down-up as result of cable plug, the xgxs | ||
5523 | * link would probably become up again without the need | ||
5524 | * initialize it | ||
5525 | */ | ||
5526 | if (!(SINGLE_MEDIA_DIRECT(params))) { | ||
5527 | DP(NETIF_MSG_LINK, "ext_phy_link_up = %d, int_link_up = %d," | ||
5528 | " init_preceding = %d\n", ext_phy_link_up, | ||
5529 | vars->phy_link_up, | ||
5530 | params->phy[EXT_PHY1].flags & | ||
5531 | FLAGS_INIT_XGXS_FIRST); | ||
5532 | if (!(params->phy[EXT_PHY1].flags & | ||
5533 | FLAGS_INIT_XGXS_FIRST) | ||
5534 | && ext_phy_link_up && !vars->phy_link_up) { | ||
5535 | vars->line_speed = ext_phy_line_speed; | ||
5536 | if (vars->line_speed < SPEED_1000) | ||
5537 | vars->phy_flags |= PHY_SGMII_FLAG; | ||
5538 | else | ||
5539 | vars->phy_flags &= ~PHY_SGMII_FLAG; | ||
5540 | bnx2x_init_internal_phy(¶ms->phy[INT_PHY], | ||
5541 | params, | ||
5542 | vars); | ||
5543 | } | ||
5544 | } | 5389 | } |
5545 | /** | ||
5546 | * Link is up only if both local phy and external phy (in case of | ||
5547 | * non-direct board) are up | ||
5548 | */ | ||
5549 | vars->link_up = (vars->phy_link_up && | ||
5550 | (ext_phy_link_up || | ||
5551 | SINGLE_MEDIA_DIRECT(params))); | ||
5552 | |||
5553 | if (vars->link_up) | ||
5554 | rc = bnx2x_update_link_up(params, vars, link_10g); | ||
5555 | else | ||
5556 | rc = bnx2x_update_link_down(params, vars); | ||
5557 | |||
5558 | return rc; | ||
5559 | } | ||
5560 | |||
5561 | static void bnx2x_8481_hw_reset(struct bnx2x_phy *phy, | ||
5562 | struct link_params *params) | ||
5563 | { | ||
5564 | bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1, | ||
5565 | MISC_REGISTERS_GPIO_OUTPUT_LOW, 0); | ||
5566 | bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1, | ||
5567 | MISC_REGISTERS_GPIO_OUTPUT_LOW, 1); | ||
5568 | } | ||
5569 | |||
5570 | static void bnx2x_8727_hw_reset(struct bnx2x_phy *phy, | ||
5571 | struct link_params *params) { | ||
5572 | u32 swap_val, swap_override; | ||
5573 | u8 port; | ||
5574 | /** | ||
5575 | * The PHY reset is controlled by GPIO 1. Fake the port number | ||
5576 | * to cancel the swap done in set_gpio() | ||
5577 | */ | ||
5578 | struct bnx2x *bp = params->bp; | ||
5579 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); | ||
5580 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); | ||
5581 | port = (swap_val && swap_override) ^ 1; | ||
5582 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
5583 | MISC_REGISTERS_GPIO_OUTPUT_LOW, port); | ||
5584 | } | 5390 | } |
5585 | 5391 | ||
5586 | static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy, | 5392 | static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy, |
@@ -5592,6 +5398,7 @@ static void bnx2x_7101_hw_reset(struct bnx2x_phy *phy, | |||
5592 | bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1, | 5398 | bnx2x_set_gpio(params->bp, MISC_REGISTERS_GPIO_1, |
5593 | MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port); | 5399 | MISC_REGISTERS_GPIO_OUTPUT_LOW, params->port); |
5594 | } | 5400 | } |
5401 | |||
5595 | /******************************************************************/ | 5402 | /******************************************************************/ |
5596 | /* STATIC PHY DECLARATION */ | 5403 | /* STATIC PHY DECLARATION */ |
5597 | /******************************************************************/ | 5404 | /******************************************************************/ |
@@ -5854,7 +5661,6 @@ static struct bnx2x_phy phy_8727 = { | |||
5854 | .mdio_ctrl = 0, | 5661 | .mdio_ctrl = 0, |
5855 | .supported = (SUPPORTED_10000baseT_Full | | 5662 | .supported = (SUPPORTED_10000baseT_Full | |
5856 | SUPPORTED_1000baseT_Full | | 5663 | SUPPORTED_1000baseT_Full | |
5857 | SUPPORTED_Autoneg | | ||
5858 | SUPPORTED_FIBRE | | 5664 | SUPPORTED_FIBRE | |
5859 | SUPPORTED_Pause | | 5665 | SUPPORTED_Pause | |
5860 | SUPPORTED_Asym_Pause), | 5666 | SUPPORTED_Asym_Pause), |
@@ -6240,6 +6046,271 @@ u32 bnx2x_supported_attr(struct link_params *params, u8 phy_idx) | |||
6240 | return 0; | 6046 | return 0; |
6241 | } | 6047 | } |
6242 | 6048 | ||
6049 | static void set_phy_vars(struct link_params *params) | ||
6050 | { | ||
6051 | struct bnx2x *bp = params->bp; | ||
6052 | u8 actual_phy_idx, phy_index; | ||
6053 | |||
6054 | for (phy_index = INT_PHY; phy_index < params->num_phys; | ||
6055 | phy_index++) { | ||
6056 | |||
6057 | actual_phy_idx = phy_index; | ||
6058 | params->phy[actual_phy_idx].req_flow_ctrl = | ||
6059 | params->req_flow_ctrl; | ||
6060 | |||
6061 | params->phy[actual_phy_idx].req_line_speed = | ||
6062 | params->req_line_speed; | ||
6063 | |||
6064 | params->phy[actual_phy_idx].speed_cap_mask = | ||
6065 | params->speed_cap_mask; | ||
6066 | |||
6067 | params->phy[actual_phy_idx].req_duplex = | ||
6068 | params->req_duplex; | ||
6069 | |||
6070 | DP(NETIF_MSG_LINK, "req_flow_ctrl %x, req_line_speed %x," | ||
6071 | " speed_cap_mask %x\n", | ||
6072 | params->phy[actual_phy_idx].req_flow_ctrl, | ||
6073 | params->phy[actual_phy_idx].req_line_speed, | ||
6074 | params->phy[actual_phy_idx].speed_cap_mask); | ||
6075 | } | ||
6076 | } | ||
6077 | |||
6078 | u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | ||
6079 | { | ||
6080 | struct bnx2x *bp = params->bp; | ||
6081 | u32 val; | ||
6082 | |||
6083 | DP(NETIF_MSG_LINK, "Phy Initialization started\n"); | ||
6084 | DP(NETIF_MSG_LINK, "req_speed %d, req_flowctrl %d\n", | ||
6085 | params->req_line_speed, params->req_flow_ctrl); | ||
6086 | vars->link_status = 0; | ||
6087 | vars->phy_link_up = 0; | ||
6088 | vars->link_up = 0; | ||
6089 | vars->line_speed = 0; | ||
6090 | vars->duplex = DUPLEX_FULL; | ||
6091 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
6092 | vars->mac_type = MAC_TYPE_NONE; | ||
6093 | vars->phy_flags = 0; | ||
6094 | |||
6095 | /* disable attentions */ | ||
6096 | bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + params->port*4, | ||
6097 | (NIG_MASK_XGXS0_LINK_STATUS | | ||
6098 | NIG_MASK_XGXS0_LINK10G | | ||
6099 | NIG_MASK_SERDES0_LINK_STATUS | | ||
6100 | NIG_MASK_MI_INT)); | ||
6101 | |||
6102 | bnx2x_emac_init(params, vars); | ||
6103 | |||
6104 | if (params->num_phys == 0) { | ||
6105 | DP(NETIF_MSG_LINK, "No phy found for initialization !!\n"); | ||
6106 | return -EINVAL; | ||
6107 | } | ||
6108 | set_phy_vars(params); | ||
6109 | |||
6110 | DP(NETIF_MSG_LINK, "Num of phys on board: %d\n", params->num_phys); | ||
6111 | if (CHIP_REV_IS_FPGA(bp)) { | ||
6112 | |||
6113 | vars->link_up = 1; | ||
6114 | vars->line_speed = SPEED_10000; | ||
6115 | vars->duplex = DUPLEX_FULL; | ||
6116 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
6117 | vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD); | ||
6118 | /* enable on E1.5 FPGA */ | ||
6119 | if (CHIP_IS_E1H(bp)) { | ||
6120 | vars->flow_ctrl |= | ||
6121 | (BNX2X_FLOW_CTRL_TX | | ||
6122 | BNX2X_FLOW_CTRL_RX); | ||
6123 | vars->link_status |= | ||
6124 | (LINK_STATUS_TX_FLOW_CONTROL_ENABLED | | ||
6125 | LINK_STATUS_RX_FLOW_CONTROL_ENABLED); | ||
6126 | } | ||
6127 | |||
6128 | bnx2x_emac_enable(params, vars, 0); | ||
6129 | bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed); | ||
6130 | /* disable drain */ | ||
6131 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + params->port*4, 0); | ||
6132 | |||
6133 | /* update shared memory */ | ||
6134 | bnx2x_update_mng(params, vars->link_status); | ||
6135 | |||
6136 | return 0; | ||
6137 | |||
6138 | } else | ||
6139 | if (CHIP_REV_IS_EMUL(bp)) { | ||
6140 | |||
6141 | vars->link_up = 1; | ||
6142 | vars->line_speed = SPEED_10000; | ||
6143 | vars->duplex = DUPLEX_FULL; | ||
6144 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
6145 | vars->link_status = (LINK_STATUS_LINK_UP | LINK_10GTFD); | ||
6146 | |||
6147 | bnx2x_bmac_enable(params, vars, 0); | ||
6148 | |||
6149 | bnx2x_pbf_update(params, vars->flow_ctrl, vars->line_speed); | ||
6150 | /* Disable drain */ | ||
6151 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE | ||
6152 | + params->port*4, 0); | ||
6153 | |||
6154 | /* update shared memory */ | ||
6155 | bnx2x_update_mng(params, vars->link_status); | ||
6156 | |||
6157 | return 0; | ||
6158 | |||
6159 | } else | ||
6160 | if (params->loopback_mode == LOOPBACK_BMAC) { | ||
6161 | |||
6162 | vars->link_up = 1; | ||
6163 | vars->line_speed = SPEED_10000; | ||
6164 | vars->duplex = DUPLEX_FULL; | ||
6165 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
6166 | vars->mac_type = MAC_TYPE_BMAC; | ||
6167 | |||
6168 | vars->phy_flags = PHY_XGXS_FLAG; | ||
6169 | |||
6170 | bnx2x_xgxs_deassert(params); | ||
6171 | |||
6172 | /* set bmac loopback */ | ||
6173 | bnx2x_bmac_enable(params, vars, 1); | ||
6174 | |||
6175 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + | ||
6176 | params->port*4, 0); | ||
6177 | |||
6178 | } else if (params->loopback_mode == LOOPBACK_EMAC) { | ||
6179 | |||
6180 | vars->link_up = 1; | ||
6181 | vars->line_speed = SPEED_1000; | ||
6182 | vars->duplex = DUPLEX_FULL; | ||
6183 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
6184 | vars->mac_type = MAC_TYPE_EMAC; | ||
6185 | |||
6186 | vars->phy_flags = PHY_XGXS_FLAG; | ||
6187 | |||
6188 | bnx2x_xgxs_deassert(params); | ||
6189 | /* set bmac loopback */ | ||
6190 | bnx2x_emac_enable(params, vars, 1); | ||
6191 | bnx2x_emac_program(params, vars); | ||
6192 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + | ||
6193 | params->port*4, 0); | ||
6194 | |||
6195 | } else if ((params->loopback_mode == LOOPBACK_XGXS) || | ||
6196 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { | ||
6197 | |||
6198 | vars->link_up = 1; | ||
6199 | vars->line_speed = SPEED_10000; | ||
6200 | vars->duplex = DUPLEX_FULL; | ||
6201 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | ||
6202 | |||
6203 | vars->phy_flags = PHY_XGXS_FLAG; | ||
6204 | |||
6205 | val = REG_RD(bp, | ||
6206 | NIG_REG_XGXS0_CTRL_PHY_ADDR+ | ||
6207 | params->port*0x18); | ||
6208 | |||
6209 | bnx2x_xgxs_deassert(params); | ||
6210 | bnx2x_link_initialize(params, vars); | ||
6211 | |||
6212 | vars->mac_type = MAC_TYPE_BMAC; | ||
6213 | |||
6214 | bnx2x_bmac_enable(params, vars, 0); | ||
6215 | |||
6216 | if (params->loopback_mode == LOOPBACK_XGXS) { | ||
6217 | /* set 10G XGXS loopback */ | ||
6218 | params->phy[INT_PHY].config_loopback( | ||
6219 | ¶ms->phy[INT_PHY], | ||
6220 | params); | ||
6221 | |||
6222 | } else { | ||
6223 | /* set external phy loopback */ | ||
6224 | u8 phy_index; | ||
6225 | for (phy_index = EXT_PHY1; | ||
6226 | phy_index < params->num_phys; phy_index++) { | ||
6227 | if (params->phy[phy_index].config_loopback) | ||
6228 | params->phy[phy_index].config_loopback( | ||
6229 | ¶ms->phy[phy_index], | ||
6230 | params); | ||
6231 | } | ||
6232 | } | ||
6233 | |||
6234 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + | ||
6235 | params->port*4, 0); | ||
6236 | |||
6237 | bnx2x_set_led(params, LED_MODE_OPER, vars->line_speed); | ||
6238 | } else | ||
6239 | /* No loopback */ | ||
6240 | { | ||
6241 | if (params->switch_cfg == SWITCH_CFG_10G) | ||
6242 | bnx2x_xgxs_deassert(params); | ||
6243 | else | ||
6244 | bnx2x_serdes_deassert(bp, params->port); | ||
6245 | bnx2x_link_initialize(params, vars); | ||
6246 | msleep(30); | ||
6247 | bnx2x_link_int_enable(params); | ||
6248 | } | ||
6249 | return 0; | ||
6250 | } | ||
6251 | u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | ||
6252 | u8 reset_ext_phy) | ||
6253 | { | ||
6254 | struct bnx2x *bp = params->bp; | ||
6255 | u8 phy_index, port = params->port; | ||
6256 | DP(NETIF_MSG_LINK, "Resetting the link of port %d\n", port); | ||
6257 | /* disable attentions */ | ||
6258 | vars->link_status = 0; | ||
6259 | bnx2x_update_mng(params, vars->link_status); | ||
6260 | bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4, | ||
6261 | (NIG_MASK_XGXS0_LINK_STATUS | | ||
6262 | NIG_MASK_XGXS0_LINK10G | | ||
6263 | NIG_MASK_SERDES0_LINK_STATUS | | ||
6264 | NIG_MASK_MI_INT)); | ||
6265 | |||
6266 | /* activate nig drain */ | ||
6267 | REG_WR(bp, NIG_REG_EGRESS_DRAIN0_MODE + port*4, 1); | ||
6268 | |||
6269 | /* disable nig egress interface */ | ||
6270 | REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0); | ||
6271 | REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); | ||
6272 | |||
6273 | /* Stop BigMac rx */ | ||
6274 | bnx2x_bmac_rx_disable(bp, port); | ||
6275 | |||
6276 | /* disable emac */ | ||
6277 | REG_WR(bp, NIG_REG_NIG_EMAC0_EN + port*4, 0); | ||
6278 | |||
6279 | msleep(10); | ||
6280 | /* The PHY reset is controled by GPIO 1 | ||
6281 | * Hold it as vars low | ||
6282 | */ | ||
6283 | /* clear link led */ | ||
6284 | bnx2x_set_led(params, LED_MODE_OFF, 0); | ||
6285 | if (reset_ext_phy) { | ||
6286 | for (phy_index = EXT_PHY1; phy_index < params->num_phys; | ||
6287 | phy_index++) { | ||
6288 | if (params->phy[phy_index].link_reset) | ||
6289 | params->phy[phy_index].link_reset( | ||
6290 | ¶ms->phy[phy_index], | ||
6291 | params); | ||
6292 | } | ||
6293 | } | ||
6294 | |||
6295 | if (params->phy[INT_PHY].link_reset) | ||
6296 | params->phy[INT_PHY].link_reset( | ||
6297 | ¶ms->phy[INT_PHY], params); | ||
6298 | /* reset BigMac */ | ||
6299 | REG_WR(bp, GRCBASE_MISC + MISC_REGISTERS_RESET_REG_2_CLEAR, | ||
6300 | (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << port)); | ||
6301 | |||
6302 | /* disable nig ingress interface */ | ||
6303 | REG_WR(bp, NIG_REG_BMAC0_IN_EN + port*4, 0); | ||
6304 | REG_WR(bp, NIG_REG_EMAC0_IN_EN + port*4, 0); | ||
6305 | REG_WR(bp, NIG_REG_BMAC0_OUT_EN + port*4, 0); | ||
6306 | REG_WR(bp, NIG_REG_EGRESS_EMAC0_OUT_EN + port*4, 0); | ||
6307 | vars->link_up = 0; | ||
6308 | return 0; | ||
6309 | } | ||
6310 | |||
6311 | /****************************************************************************/ | ||
6312 | /* Common function */ | ||
6313 | /****************************************************************************/ | ||
6243 | static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6314 | static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) |
6244 | { | 6315 | { |
6245 | struct bnx2x_phy phy[PORT_MAX]; | 6316 | struct bnx2x_phy phy[PORT_MAX]; |
@@ -6348,6 +6419,43 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6348 | return 0; | 6419 | return 0; |
6349 | } | 6420 | } |
6350 | 6421 | ||
6422 | static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) | ||
6423 | { | ||
6424 | u32 val; | ||
6425 | s8 port; | ||
6426 | struct bnx2x_phy phy; | ||
6427 | /* Use port1 because of the static port-swap */ | ||
6428 | /* Enable the module detection interrupt */ | ||
6429 | val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN); | ||
6430 | val |= ((1<<MISC_REGISTERS_GPIO_3)| | ||
6431 | (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); | ||
6432 | REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val); | ||
6433 | |||
6434 | bnx2x_ext_phy_hw_reset(bp, 1); | ||
6435 | msleep(5); | ||
6436 | for (port = 0; port < PORT_MAX; port++) { | ||
6437 | /* Extract the ext phy address for the port */ | ||
6438 | if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, | ||
6439 | port, &phy) != | ||
6440 | 0) { | ||
6441 | DP(NETIF_MSG_LINK, "populate phy failed\n"); | ||
6442 | return -EINVAL; | ||
6443 | } | ||
6444 | |||
6445 | /* Reset phy*/ | ||
6446 | bnx2x_cl45_write(bp, &phy, | ||
6447 | MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001); | ||
6448 | |||
6449 | |||
6450 | /* Set fault module detected LED on */ | ||
6451 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
6452 | MISC_REGISTERS_GPIO_HIGH, | ||
6453 | port); | ||
6454 | } | ||
6455 | |||
6456 | return 0; | ||
6457 | } | ||
6458 | |||
6351 | static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6459 | static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) |
6352 | { | 6460 | { |
6353 | s8 port, first_port, i; | 6461 | s8 port, first_port, i; |
@@ -6420,43 +6528,6 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6420 | return 0; | 6528 | return 0; |
6421 | } | 6529 | } |
6422 | 6530 | ||
6423 | static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) | ||
6424 | { | ||
6425 | u32 val; | ||
6426 | s8 port; | ||
6427 | struct bnx2x_phy phy; | ||
6428 | /* Use port1 because of the static port-swap */ | ||
6429 | /* Enable the module detection interrupt */ | ||
6430 | val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN); | ||
6431 | val |= ((1<<MISC_REGISTERS_GPIO_3)| | ||
6432 | (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); | ||
6433 | REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val); | ||
6434 | |||
6435 | bnx2x_ext_phy_hw_reset(bp, 1); | ||
6436 | msleep(5); | ||
6437 | for (port = 0; port < PORT_MAX; port++) { | ||
6438 | /* Extract the ext phy address for the port */ | ||
6439 | if (bnx2x_populate_phy(bp, EXT_PHY1, shmem_base, | ||
6440 | port, &phy) != | ||
6441 | 0) { | ||
6442 | DP(NETIF_MSG_LINK, "populate phy failed\n"); | ||
6443 | return -EINVAL; | ||
6444 | } | ||
6445 | |||
6446 | /* Reset phy*/ | ||
6447 | bnx2x_cl45_write(bp, &phy, | ||
6448 | MDIO_PMA_DEVAD, MDIO_PMA_REG_GEN_CTRL, 0x0001); | ||
6449 | |||
6450 | |||
6451 | /* Set fault module detected LED on */ | ||
6452 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
6453 | MISC_REGISTERS_GPIO_HIGH, | ||
6454 | port); | ||
6455 | } | ||
6456 | |||
6457 | return 0; | ||
6458 | } | ||
6459 | |||
6460 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 6531 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) |
6461 | { | 6532 | { |
6462 | u8 rc = 0; | 6533 | u8 rc = 0; |
@@ -6497,30 +6568,6 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6497 | return rc; | 6568 | return rc; |
6498 | } | 6569 | } |
6499 | 6570 | ||
6500 | void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, struct bnx2x_phy *phy) | ||
6501 | { | ||
6502 | u16 val, cnt; | ||
6503 | |||
6504 | bnx2x_cl45_read(bp, phy, | ||
6505 | MDIO_PMA_DEVAD, | ||
6506 | MDIO_PMA_REG_7101_RESET, &val); | ||
6507 | |||
6508 | for (cnt = 0; cnt < 10; cnt++) { | ||
6509 | msleep(50); | ||
6510 | /* Writes a self-clearing reset */ | ||
6511 | bnx2x_cl45_write(bp, phy, | ||
6512 | MDIO_PMA_DEVAD, | ||
6513 | MDIO_PMA_REG_7101_RESET, | ||
6514 | (val | (1<<15))); | ||
6515 | /* Wait for clear */ | ||
6516 | bnx2x_cl45_read(bp, phy, | ||
6517 | MDIO_PMA_DEVAD, | ||
6518 | MDIO_PMA_REG_7101_RESET, &val); | ||
6519 | |||
6520 | if ((val & (1<<15)) == 0) | ||
6521 | break; | ||
6522 | } | ||
6523 | } | ||
6524 | 6571 | ||
6525 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base) | 6572 | u8 bnx2x_hw_lock_required(struct bnx2x *bp, u32 shmem_base) |
6526 | { | 6573 | { |
diff --git a/drivers/net/bnx2x/bnx2x_link.h b/drivers/net/bnx2x/bnx2x_link.h index 99e11576c6e4..35f665f97be6 100644 --- a/drivers/net/bnx2x/bnx2x_link.h +++ b/drivers/net/bnx2x/bnx2x_link.h | |||
@@ -173,7 +173,7 @@ struct link_params { | |||
173 | #define LOOPBACK_NONE 0 | 173 | #define LOOPBACK_NONE 0 |
174 | #define LOOPBACK_EMAC 1 | 174 | #define LOOPBACK_EMAC 1 |
175 | #define LOOPBACK_BMAC 2 | 175 | #define LOOPBACK_BMAC 2 |
176 | #define LOOPBACK_XGXS_10 3 | 176 | #define LOOPBACK_XGXS 3 |
177 | #define LOOPBACK_EXT_PHY 4 | 177 | #define LOOPBACK_EXT_PHY 4 |
178 | #define LOOPBACK_EXT 5 | 178 | #define LOOPBACK_EXT 5 |
179 | 179 | ||
diff --git a/drivers/net/bnx2x/bnx2x_main.c b/drivers/net/bnx2x/bnx2x_main.c index 0210dde760d9..30618c7ed4ed 100644 --- a/drivers/net/bnx2x/bnx2x_main.c +++ b/drivers/net/bnx2x/bnx2x_main.c | |||
@@ -1269,7 +1269,7 @@ u8 bnx2x_initial_phy_init(struct bnx2x *bp, int load_mode) | |||
1269 | bnx2x_acquire_phy_lock(bp); | 1269 | bnx2x_acquire_phy_lock(bp); |
1270 | 1270 | ||
1271 | if (load_mode == LOAD_DIAG) | 1271 | if (load_mode == LOAD_DIAG) |
1272 | bp->link_params.loopback_mode = LOOPBACK_XGXS_10; | 1272 | bp->link_params.loopback_mode = LOOPBACK_XGXS; |
1273 | 1273 | ||
1274 | rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); | 1274 | rc = bnx2x_phy_init(&bp->link_params, &bp->link_vars); |
1275 | 1275 | ||