aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
diff options
context:
space:
mode:
authorYaniv Rosner <yanivr@broadcom.com>2012-11-26 22:46:29 -0500
committerDavid S. Miller <davem@davemloft.net>2012-11-28 10:59:20 -0500
commit4e7b4997886e1dcbb0024308fb474c5994e8af2b (patch)
treedd28ceb8a19f14a52ee3d4d085a472a9c1ff249a /drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
parentb884d95b8222a50144e3d84fe9becedae836e56d (diff)
bnx2x: Add support for 20G-KR2
Signed-off-by: Yaniv Rosner <yanivr@broadcom.com> Signed-off-by: Eilon Greenstein <eilong@broadcom.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c')
-rw-r--r--drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c366
1 files changed, 334 insertions, 32 deletions
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
index c98da25f22eb..eb44b230676e 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
@@ -121,6 +121,7 @@
121#define GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI 121#define GP_STATUS_10G_XFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_XFI
122#define GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS 122#define GP_STATUS_20G_DXGXS MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_DXGXS
123#define GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI 123#define GP_STATUS_10G_SFI MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_10G_SFI
124#define GP_STATUS_20G_KR2 MDIO_GP_STATUS_TOP_AN_STATUS1_ACTUAL_SPEED_20G_KR2
124#define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD 125#define LINK_10THD LINK_STATUS_SPEED_AND_DUPLEX_10THD
125#define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD 126#define LINK_10TFD LINK_STATUS_SPEED_AND_DUPLEX_10TFD
126#define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD 127#define LINK_100TXHD LINK_STATUS_SPEED_AND_DUPLEX_100TXHD
@@ -1664,7 +1665,10 @@ static void bnx2x_xmac_init(struct link_params *params, u32 max_speed)
1664 * ports of the path 1665 * ports of the path
1665 */ 1666 */
1666 1667
1667 if ((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) && 1668 if (((CHIP_NUM(bp) == CHIP_NUM_57840_4_10) ||
1669 (CHIP_NUM(bp) == CHIP_NUM_57840_2_20) ||
1670 (CHIP_NUM(bp) == CHIP_NUM_57840_OBSOLETE)) &&
1671 is_port4mode &&
1668 (REG_RD(bp, MISC_REG_RESET_REG_2) & 1672 (REG_RD(bp, MISC_REG_RESET_REG_2) &
1669 MISC_REGISTERS_RESET_REG_2_XMAC)) { 1673 MISC_REGISTERS_RESET_REG_2_XMAC)) {
1670 DP(NETIF_MSG_LINK, 1674 DP(NETIF_MSG_LINK,
@@ -1760,6 +1764,18 @@ static int bnx2x_xmac_enable(struct link_params *params,
1760 */ 1764 */
1761 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0); 1765 REG_WR(bp, NIG_REG_EGRESS_EMAC0_PORT + params->port*4, 0);
1762 1766
1767 /* When XMAC is in XLGMII mode, disable sending idles for fault
1768 * detection.
1769 */
1770 if (!(params->phy[INT_PHY].flags & FLAGS_TX_ERROR_CHECK)) {
1771 REG_WR(bp, xmac_base + XMAC_REG_RX_LSS_CTRL,
1772 (XMAC_RX_LSS_CTRL_REG_LOCAL_FAULT_DISABLE |
1773 XMAC_RX_LSS_CTRL_REG_REMOTE_FAULT_DISABLE));
1774 REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS, 0);
1775 REG_WR(bp, xmac_base + XMAC_REG_CLEAR_RX_LSS_STATUS,
1776 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_LOCAL_FAULT_STATUS |
1777 XMAC_CLEAR_RX_LSS_STATUS_REG_CLEAR_REMOTE_FAULT_STATUS);
1778 }
1763 /* Set Max packet size */ 1779 /* Set Max packet size */
1764 REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710); 1780 REG_WR(bp, xmac_base + XMAC_REG_RX_MAX_SIZE, 0x2710);
1765 1781
@@ -1780,6 +1796,12 @@ static int bnx2x_xmac_enable(struct link_params *params,
1780 /* Enable TX and RX */ 1796 /* Enable TX and RX */
1781 val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN; 1797 val = XMAC_CTRL_REG_TX_EN | XMAC_CTRL_REG_RX_EN;
1782 1798
1799 /* Set MAC in XLGMII mode for dual-mode */
1800 if ((vars->line_speed == SPEED_20000) &&
1801 (params->phy[INT_PHY].supported &
1802 SUPPORTED_20000baseKR2_Full))
1803 val |= XMAC_CTRL_REG_XLGMII_ALIGN_ENB;
1804
1783 /* Check loopback mode */ 1805 /* Check loopback mode */
1784 if (lb) 1806 if (lb)
1785 val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK; 1807 val |= XMAC_CTRL_REG_LINE_LOCAL_LPBK;
@@ -2096,6 +2118,16 @@ static void bnx2x_update_mng(struct link_params *params, u32 link_status)
2096 port_mb[params->port].link_status), link_status); 2118 port_mb[params->port].link_status), link_status);
2097} 2119}
2098 2120
2121static void bnx2x_update_link_attr(struct link_params *params, u32 link_attr)
2122{
2123 struct bnx2x *bp = params->bp;
2124
2125 if (SHMEM2_HAS(bp, link_attr_sync))
2126 REG_WR(bp, params->shmem2_base +
2127 offsetof(struct shmem2_region,
2128 link_attr_sync[params->port]), link_attr);
2129}
2130
2099static void bnx2x_update_pfc_nig(struct link_params *params, 2131static void bnx2x_update_pfc_nig(struct link_params *params,
2100 struct link_vars *vars, 2132 struct link_vars *vars,
2101 struct bnx2x_nig_brb_pfc_port_params *nig_params) 2133 struct bnx2x_nig_brb_pfc_port_params *nig_params)
@@ -3147,6 +3179,15 @@ static void bnx2x_cl45_read_or_write(struct bnx2x *bp, struct bnx2x_phy *phy,
3147 bnx2x_cl45_write(bp, phy, devad, reg, val | or_val); 3179 bnx2x_cl45_write(bp, phy, devad, reg, val | or_val);
3148} 3180}
3149 3181
3182static void bnx2x_cl45_read_and_write(struct bnx2x *bp,
3183 struct bnx2x_phy *phy,
3184 u8 devad, u16 reg, u16 and_val)
3185{
3186 u16 val;
3187 bnx2x_cl45_read(bp, phy, devad, reg, &val);
3188 bnx2x_cl45_write(bp, phy, devad, reg, val & and_val);
3189}
3190
3150int bnx2x_phy_read(struct link_params *params, u8 phy_addr, 3191int bnx2x_phy_read(struct link_params *params, u8 phy_addr,
3151 u8 devad, u16 reg, u16 *ret_val) 3192 u8 devad, u16 reg, u16 *ret_val)
3152{ 3193{
@@ -3551,6 +3592,44 @@ static u8 bnx2x_ext_phy_resolve_fc(struct bnx2x_phy *phy,
3551 * init configuration, and set/clear SGMII flag. Internal 3592 * init configuration, and set/clear SGMII flag. Internal
3552 * phy init is done purely in phy_init stage. 3593 * phy init is done purely in phy_init stage.
3553 */ 3594 */
3595static void bnx2x_warpcore_enable_AN_KR2(struct bnx2x_phy *phy,
3596 struct link_params *params,
3597 struct link_vars *vars)
3598{
3599 struct bnx2x *bp = params->bp;
3600 u16 i;
3601 static struct bnx2x_reg_set reg_set[] = {
3602 /* Step 1 - Program the TX/RX alignment markers */
3603 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0xa157},
3604 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xcbe2},
3605 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0x7537},
3606 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0xa157},
3607 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xcbe2},
3608 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0x7537},
3609 /* Step 2 - Configure the NP registers */
3610 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000a},
3611 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6400},
3612 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0620},
3613 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0157},
3614 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x6464},
3615 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x3150},
3616 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x3150},
3617 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0157},
3618 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0620}
3619 };
3620 DP(NETIF_MSG_LINK, "Enabling 20G-KR2\n");
3621
3622 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
3623 MDIO_WC_REG_CL49_USERB0_CTRL, (3<<6));
3624
3625 for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
3626 bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
3627 reg_set[i].val);
3628
3629 /* Start KR2 work-around timer which handles BCM8073 link-parner */
3630 vars->link_attr_sync |= LINK_ATTR_SYNC_KR2_ENABLE;
3631 bnx2x_update_link_attr(params, vars->link_attr_sync);
3632}
3554 3633
3555static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy, 3634static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
3556 struct link_params *params) 3635 struct link_params *params)
@@ -3564,6 +3643,21 @@ static void bnx2x_warpcore_set_lpi_passthrough(struct bnx2x_phy *phy,
3564 MDIO_WC_REG_DIGITAL4_MISC5, 0xc000); 3643 MDIO_WC_REG_DIGITAL4_MISC5, 0xc000);
3565} 3644}
3566 3645
3646static void bnx2x_warpcore_restart_AN_KR(struct bnx2x_phy *phy,
3647 struct link_params *params)
3648{
3649 /* Restart autoneg on the leading lane only */
3650 struct bnx2x *bp = params->bp;
3651 u16 lane = bnx2x_get_warpcore_lane(phy, params);
3652 CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
3653 MDIO_AER_BLOCK_AER_REG, lane);
3654 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
3655 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200);
3656
3657 /* Restore AER */
3658 bnx2x_set_aer_mmd(params, phy);
3659}
3660
3567static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy, 3661static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
3568 struct link_params *params, 3662 struct link_params *params,
3569 struct link_vars *vars) { 3663 struct link_vars *vars) {
@@ -3576,7 +3670,9 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
3576 {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415}, 3670 {MDIO_WC_DEVAD, MDIO_WC_REG_RX66_CONTROL, 0x7415},
3577 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190}, 3671 {MDIO_WC_DEVAD, MDIO_WC_REG_SERDESDIGITAL_MISC2, 0x6190},
3578 /* Disable Autoneg: re-enable it after adv is done. */ 3672 /* Disable Autoneg: re-enable it after adv is done. */
3579 {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0} 3673 {MDIO_AN_DEVAD, MDIO_WC_REG_IEEE0BLK_MIICNTL, 0},
3674 {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2},
3675 {MDIO_WC_DEVAD, MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0},
3580 }; 3676 };
3581 DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n"); 3677 DP(NETIF_MSG_LINK, "Enable Auto Negotiation for KR\n");
3582 /* Set to default registers that may be overriden by 10G force */ 3678 /* Set to default registers that may be overriden by 10G force */
@@ -3586,7 +3682,7 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
3586 3682
3587 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 3683 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
3588 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl); 3684 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &cl72_ctrl);
3589 cl72_ctrl &= 0xf8ff; 3685 cl72_ctrl &= 0x08ff;
3590 cl72_ctrl |= 0x3800; 3686 cl72_ctrl |= 0x3800;
3591 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, 3687 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3592 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl); 3688 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, cl72_ctrl);
@@ -3624,6 +3720,16 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
3624 ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) | 3720 ((0x02 << MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
3625 (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) | 3721 (0x06 << MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
3626 (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET))); 3722 (0x09 << MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
3723 /* Configure the next lane if dual mode */
3724 if (phy->flags & FLAGS_WC_DUAL_MODE)
3725 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3726 MDIO_WC_REG_TX0_TX_DRIVER + 0x10*(lane+1),
3727 ((0x02 <<
3728 MDIO_WC_REG_TX0_TX_DRIVER_POST2_COEFF_OFFSET) |
3729 (0x06 <<
3730 MDIO_WC_REG_TX0_TX_DRIVER_IDRIVER_OFFSET) |
3731 (0x09 <<
3732 MDIO_WC_REG_TX0_TX_DRIVER_IPRE_DRIVER_OFFSET)));
3627 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, 3733 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3628 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL, 3734 MDIO_WC_REG_CL72_USERB0_CL72_OS_DEF_CTRL,
3629 0x03f0); 3735 0x03f0);
@@ -3670,10 +3776,26 @@ static void bnx2x_warpcore_enable_AN_KR(struct bnx2x_phy *phy,
3670 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, 3776 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3671 MDIO_WC_REG_DIGITAL3_UP1, 0x1f); 3777 MDIO_WC_REG_DIGITAL3_UP1, 0x1f);
3672 3778
3673 /* Enable Autoneg */ 3779 if (((phy->req_line_speed == SPEED_AUTO_NEG) &&
3674 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD, 3780 (phy->speed_cap_mask & PORT_HW_CFG_SPEED_CAPABILITY_D0_20G)) ||
3675 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1200); 3781 (phy->req_line_speed == SPEED_20000)) {
3782
3783 CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
3784 MDIO_AER_BLOCK_AER_REG, lane);
3785
3786 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
3787 MDIO_WC_REG_RX1_PCI_CTRL + (0x10*lane),
3788 (1<<11));
3789
3790 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
3791 MDIO_WC_REG_XGXS_X2_CONTROL3, 0x7);
3792 bnx2x_set_aer_mmd(params, phy);
3676 3793
3794 bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
3795 }
3796
3797 /* Enable Autoneg: only on the main lane */
3798 bnx2x_warpcore_restart_AN_KR(phy, params);
3677} 3799}
3678 3800
3679static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy, 3801static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
@@ -3692,9 +3814,7 @@ static void bnx2x_warpcore_set_10G_KR(struct bnx2x_phy *phy,
3692 {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1}, 3814 {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL3_UP1, 0x1},
3693 {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa}, 3815 {MDIO_WC_DEVAD, MDIO_WC_REG_DIGITAL5_MISC7, 0xa},
3694 /* Leave cl72 training enable, needed for KR */ 3816 /* Leave cl72 training enable, needed for KR */
3695 {MDIO_PMA_DEVAD, 3817 {MDIO_PMA_DEVAD, MDIO_WC_REG_PMD_KR_CONTROL, 0x2}
3696 MDIO_WC_REG_PMD_IEEE9BLK_TENGBASE_KR_PMD_CONTROL_REGISTER_150,
3697 0x2}
3698 }; 3818 };
3699 3819
3700 for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++) 3820 for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
@@ -3858,10 +3978,57 @@ static void bnx2x_warpcore_set_10G_XFI(struct bnx2x_phy *phy,
3858 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF)); 3978 MDIO_WC_REG_DSC2B0_DSC_MISC_CTRL0, (val & 0x7FFF));
3859} 3979}
3860 3980
3861static void bnx2x_warpcore_set_20G_KR2(struct bnx2x *bp, 3981static void bnx2x_warpcore_set_20G_force_KR2(struct bnx2x_phy *phy,
3862 struct bnx2x_phy *phy) 3982 struct link_params *params)
3863{ 3983{
3864 DP(NETIF_MSG_LINK, "KR2 still not supported !!!\n"); 3984 u16 val;
3985 struct bnx2x *bp = params->bp;
3986 /* Set global registers, so set AER lane to 0 */
3987 CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
3988 MDIO_AER_BLOCK_AER_REG, 0);
3989
3990 /* Disable sequencer */
3991 bnx2x_cl45_read_and_write(bp, phy, MDIO_WC_DEVAD,
3992 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, ~(1<<13));
3993
3994 bnx2x_set_aer_mmd(params, phy);
3995
3996 bnx2x_cl45_read_and_write(bp, phy, MDIO_PMA_DEVAD,
3997 MDIO_WC_REG_PMD_KR_CONTROL, ~(1<<1));
3998 bnx2x_cl45_write(bp, phy, MDIO_AN_DEVAD,
3999 MDIO_AN_REG_CTRL, 0);
4000 /* Turn off CL73 */
4001 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
4002 MDIO_WC_REG_CL73_USERB0_CTRL, &val);
4003 val &= ~(1<<5);
4004 val |= (1<<6);
4005 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
4006 MDIO_WC_REG_CL73_USERB0_CTRL, val);
4007
4008 /* Set 20G KR2 force speed */
4009 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
4010 MDIO_WC_REG_SERDESDIGITAL_MISC1, 0x1f);
4011
4012 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
4013 MDIO_WC_REG_DIGITAL4_MISC3, (1<<7));
4014
4015 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
4016 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, &val);
4017 val &= ~(3<<14);
4018 val |= (1<<15);
4019 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
4020 MDIO_WC_REG_CL72_USERB0_CL72_MISC1_CONTROL, val);
4021 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
4022 MDIO_WC_REG_CL72_USERB0_CL72_TX_FIR_TAP, 0x835A);
4023
4024 /* Enable sequencer (over lane 0) */
4025 CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
4026 MDIO_AER_BLOCK_AER_REG, 0);
4027
4028 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
4029 MDIO_WC_REG_XGXSBLK0_XGXSCONTROL, (1<<13));
4030
4031 bnx2x_set_aer_mmd(params, phy);
3865} 4032}
3866 4033
3867static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp, 4034static void bnx2x_warpcore_set_20G_DXGXS(struct bnx2x *bp,
@@ -4293,16 +4460,14 @@ static void bnx2x_warpcore_config_init(struct bnx2x_phy *phy,
4293 4460
4294 bnx2x_sfp_module_detection(phy, params); 4461 bnx2x_sfp_module_detection(phy, params);
4295 break; 4462 break;
4296
4297 case PORT_HW_CFG_NET_SERDES_IF_KR2: 4463 case PORT_HW_CFG_NET_SERDES_IF_KR2:
4298 if (vars->line_speed != SPEED_20000) { 4464 if (!params->loopback_mode) {
4299 DP(NETIF_MSG_LINK, "Speed not supported yet\n"); 4465 bnx2x_warpcore_enable_AN_KR(phy, params, vars);
4300 return; 4466 } else {
4467 DP(NETIF_MSG_LINK, "Setting KR 20G-Force\n");
4468 bnx2x_warpcore_set_20G_force_KR2(phy, params);
4301 } 4469 }
4302 DP(NETIF_MSG_LINK, "Setting 20G KR2\n");
4303 bnx2x_warpcore_set_20G_KR2(bp, phy);
4304 break; 4470 break;
4305
4306 default: 4471 default:
4307 DP(NETIF_MSG_LINK, 4472 DP(NETIF_MSG_LINK,
4308 "Unsupported Serdes Net Interface 0x%x\n", 4473 "Unsupported Serdes Net Interface 0x%x\n",
@@ -4413,8 +4578,9 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
4413 DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n", 4578 DP(NETIF_MSG_LINK, "Setting Warpcore loopback type %x, speed %d\n",
4414 params->loopback_mode, phy->req_line_speed); 4579 params->loopback_mode, phy->req_line_speed);
4415 4580
4416 if (phy->req_line_speed < SPEED_10000) { 4581 if (phy->req_line_speed < SPEED_10000 ||
4417 /* 10/100/1000 */ 4582 phy->supported & SUPPORTED_20000baseKR2_Full) {
4583 /* 10/100/1000/20G-KR2 */
4418 4584
4419 /* Update those 1-copy registers */ 4585 /* Update those 1-copy registers */
4420 CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK, 4586 CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
@@ -4427,18 +4593,20 @@ static void bnx2x_set_warpcore_loopback(struct bnx2x_phy *phy,
4427 lane = bnx2x_get_warpcore_lane(phy, params); 4593 lane = bnx2x_get_warpcore_lane(phy, params);
4428 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 4594 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
4429 MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16); 4595 MDIO_WC_REG_XGXSBLK1_LANECTRL2, &val16);
4596 val16 |= (1<<lane);
4597 if (phy->flags & FLAGS_WC_DUAL_MODE)
4598 val16 |= (2<<lane);
4430 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD, 4599 bnx2x_cl45_write(bp, phy, MDIO_WC_DEVAD,
4431 MDIO_WC_REG_XGXSBLK1_LANECTRL2, 4600 MDIO_WC_REG_XGXSBLK1_LANECTRL2,
4432 val16 | (1<<lane)); 4601 val16);
4433 4602
4434 /* Switch back to 4-copy registers */ 4603 /* Switch back to 4-copy registers */
4435 bnx2x_set_aer_mmd(params, phy); 4604 bnx2x_set_aer_mmd(params, phy);
4436 } else { 4605 } else {
4437 /* 10G & 20G */ 4606 /* 10G / 20G-DXGXS */
4438 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, 4607 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
4439 MDIO_WC_REG_COMBO_IEEE0_MIICTRL, 4608 MDIO_WC_REG_COMBO_IEEE0_MIICTRL,
4440 0x4000); 4609 0x4000);
4441
4442 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD, 4610 bnx2x_cl45_read_or_write(bp, phy, MDIO_WC_DEVAD,
4443 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1); 4611 MDIO_WC_REG_IEEE0BLK_MIICNTL, 0x1);
4444 } 4612 }
@@ -4603,6 +4771,10 @@ void bnx2x_link_status_update(struct link_params *params,
4603 params->feature_config_flags &= 4771 params->feature_config_flags &=
4604 ~FEATURE_CONFIG_PFC_ENABLED; 4772 ~FEATURE_CONFIG_PFC_ENABLED;
4605 4773
4774 if (SHMEM2_HAS(bp, link_attr_sync))
4775 vars->link_attr_sync = SHMEM2_RD(bp,
4776 link_attr_sync[params->port]);
4777
4606 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n", 4778 DP(NETIF_MSG_LINK, "link_status 0x%x phy_link_up %x int_mask 0x%x\n",
4607 vars->link_status, vars->phy_link_up, vars->aeu_int_mask); 4779 vars->link_status, vars->phy_link_up, vars->aeu_int_mask);
4608 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n", 4780 DP(NETIF_MSG_LINK, "line_speed %x duplex %x flow_ctrl 0x%x\n",
@@ -5332,6 +5504,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
5332 vars->link_status |= LINK_10GTFD; 5504 vars->link_status |= LINK_10GTFD;
5333 break; 5505 break;
5334 case GP_STATUS_20G_DXGXS: 5506 case GP_STATUS_20G_DXGXS:
5507 case GP_STATUS_20G_KR2:
5335 vars->line_speed = SPEED_20000; 5508 vars->line_speed = SPEED_20000;
5336 vars->link_status |= LINK_20GTFD; 5509 vars->link_status |= LINK_20GTFD;
5337 break; 5510 break;
@@ -5439,7 +5612,15 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
5439 int rc = 0; 5612 int rc = 0;
5440 lane = bnx2x_get_warpcore_lane(phy, params); 5613 lane = bnx2x_get_warpcore_lane(phy, params);
5441 /* Read gp_status */ 5614 /* Read gp_status */
5442 if (phy->req_line_speed > SPEED_10000) { 5615 if ((params->loopback_mode) &&
5616 (phy->flags & FLAGS_WC_DUAL_MODE)) {
5617 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
5618 MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
5619 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
5620 MDIO_WC_REG_DIGITAL5_LINK_STATUS, &link_up);
5621 link_up &= 0x1;
5622 } else if ((phy->req_line_speed > SPEED_10000) &&
5623 (phy->supported & SUPPORTED_20000baseMLD2_Full)) {
5443 u16 temp_link_up; 5624 u16 temp_link_up;
5444 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 5625 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
5445 1, &temp_link_up); 5626 1, &temp_link_up);
@@ -5452,12 +5633,22 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
5452 bnx2x_ext_phy_resolve_fc(phy, params, vars); 5633 bnx2x_ext_phy_resolve_fc(phy, params, vars);
5453 } else { 5634 } else {
5454 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD, 5635 bnx2x_cl45_read(bp, phy, MDIO_WC_DEVAD,
5455 MDIO_WC_REG_GP2_STATUS_GP_2_1, &gp_status1); 5636 MDIO_WC_REG_GP2_STATUS_GP_2_1,
5637 &gp_status1);
5456 DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1); 5638 DP(NETIF_MSG_LINK, "0x81d1 = 0x%x\n", gp_status1);
5457 /* Check for either KR or generic link up. */ 5639 /* Check for either KR, 1G, or AN up. */
5458 gp_status1 = ((gp_status1 >> 8) & 0xf) | 5640 link_up = ((gp_status1 >> 8) |
5459 ((gp_status1 >> 12) & 0xf); 5641 (gp_status1 >> 12) |
5460 link_up = gp_status1 & (1 << lane); 5642 (gp_status1)) &
5643 (1 << lane);
5644 if (phy->supported & SUPPORTED_20000baseKR2_Full) {
5645 u16 an_link;
5646 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
5647 MDIO_AN_REG_STATUS, &an_link);
5648 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
5649 MDIO_AN_REG_STATUS, &an_link);
5650 link_up |= (an_link & (1<<2));
5651 }
5461 if (link_up && SINGLE_MEDIA_DIRECT(params)) { 5652 if (link_up && SINGLE_MEDIA_DIRECT(params)) {
5462 u16 pd, gp_status4; 5653 u16 pd, gp_status4;
5463 if (phy->req_line_speed == SPEED_AUTO_NEG) { 5654 if (phy->req_line_speed == SPEED_AUTO_NEG) {
@@ -5522,7 +5713,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
5522 if ((lane & 1) == 0) 5713 if ((lane & 1) == 0)
5523 gp_speed <<= 8; 5714 gp_speed <<= 8;
5524 gp_speed &= 0x3f00; 5715 gp_speed &= 0x3f00;
5525 5716 link_up = !!link_up;
5526 5717
5527 rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed, 5718 rc = bnx2x_get_link_speed_duplex(phy, params, vars, link_up, gp_speed,
5528 duplex); 5719 duplex);
@@ -11564,9 +11755,11 @@ static int bnx2x_populate_int_phy(struct bnx2x *bp, u32 shmem_base, u8 port,
11564 phy->media_type = ETH_PHY_KR; 11755 phy->media_type = ETH_PHY_KR;
11565 phy->flags |= FLAGS_WC_DUAL_MODE; 11756 phy->flags |= FLAGS_WC_DUAL_MODE;
11566 phy->supported &= (SUPPORTED_20000baseKR2_Full | 11757 phy->supported &= (SUPPORTED_20000baseKR2_Full |
11758 SUPPORTED_Autoneg |
11567 SUPPORTED_FIBRE | 11759 SUPPORTED_FIBRE |
11568 SUPPORTED_Pause | 11760 SUPPORTED_Pause |
11569 SUPPORTED_Asym_Pause); 11761 SUPPORTED_Asym_Pause);
11762 phy->flags &= ~FLAGS_TX_ERROR_CHECK;
11570 break; 11763 break;
11571 default: 11764 default:
11572 DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n", 11765 DP(NETIF_MSG_LINK, "Unknown WC interface type 0x%x\n",
@@ -12018,13 +12211,17 @@ static void bnx2x_init_xgxs_loopback(struct link_params *params,
12018 struct link_vars *vars) 12211 struct link_vars *vars)
12019{ 12212{
12020 struct bnx2x *bp = params->bp; 12213 struct bnx2x *bp = params->bp;
12214 struct bnx2x_phy *int_phy = &params->phy[INT_PHY];
12021 vars->link_up = 1; 12215 vars->link_up = 1;
12022 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; 12216 vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE;
12023 vars->duplex = DUPLEX_FULL; 12217 vars->duplex = DUPLEX_FULL;
12024 if (params->req_line_speed[0] == SPEED_1000) 12218 if (params->req_line_speed[0] == SPEED_1000)
12025 vars->line_speed = SPEED_1000; 12219 vars->line_speed = SPEED_1000;
12220 else if ((params->req_line_speed[0] == SPEED_20000) ||
12221 (int_phy->flags & FLAGS_WC_DUAL_MODE))
12222 vars->line_speed = SPEED_20000;
12026 else 12223 else
12027 vars->line_speed = SPEED_10000; 12224 vars->line_speed = SPEED_10000;
12028 12225
12029 if (!USES_WARPCORE(bp)) 12226 if (!USES_WARPCORE(bp))
12030 bnx2x_xgxs_deassert(params); 12227 bnx2x_xgxs_deassert(params);
@@ -13139,6 +13336,108 @@ static void bnx2x_sfp_tx_fault_detection(struct bnx2x_phy *phy,
13139 } 13336 }
13140 } 13337 }
13141} 13338}
13339static void bnx2x_disable_kr2(struct link_params *params,
13340 struct link_vars *vars,
13341 struct bnx2x_phy *phy)
13342{
13343 struct bnx2x *bp = params->bp;
13344 int i;
13345 static struct bnx2x_reg_set reg_set[] = {
13346 /* Step 1 - Program the TX/RX alignment markers */
13347 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL5, 0x7690},
13348 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL7, 0xe647},
13349 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL6, 0xc4f0},
13350 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_TX_CTRL9, 0x7690},
13351 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL11, 0xe647},
13352 {MDIO_WC_DEVAD, MDIO_WC_REG_CL82_USERB1_RX_CTRL10, 0xc4f0},
13353 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_USERB0_CTRL, 0x000c},
13354 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL1, 0x6000},
13355 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CTRL3, 0x0000},
13356 {MDIO_WC_DEVAD, MDIO_WC_REG_CL73_BAM_CODE_FIELD, 0x0002},
13357 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI1, 0x0000},
13358 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI2, 0x0af7},
13359 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_OUI3, 0x0af7},
13360 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_BAM_CODE, 0x0002},
13361 {MDIO_WC_DEVAD, MDIO_WC_REG_ETA_CL73_LD_UD_CODE, 0x0000}
13362 };
13363 DP(NETIF_MSG_LINK, "Disabling 20G-KR2\n");
13364
13365 for (i = 0; i < sizeof(reg_set)/sizeof(struct bnx2x_reg_set); i++)
13366 bnx2x_cl45_write(bp, phy, reg_set[i].devad, reg_set[i].reg,
13367 reg_set[i].val);
13368 vars->link_attr_sync &= ~LINK_ATTR_SYNC_KR2_ENABLE;
13369 bnx2x_update_link_attr(params, vars->link_attr_sync);
13370
13371 /* Restart AN on leading lane */
13372 bnx2x_warpcore_restart_AN_KR(phy, params);
13373}
13374
13375static void bnx2x_kr2_recovery(struct link_params *params,
13376 struct link_vars *vars,
13377 struct bnx2x_phy *phy)
13378{
13379 struct bnx2x *bp = params->bp;
13380 DP(NETIF_MSG_LINK, "KR2 recovery\n");
13381 bnx2x_warpcore_enable_AN_KR2(phy, params, vars);
13382 bnx2x_warpcore_restart_AN_KR(phy, params);
13383}
13384
13385static void bnx2x_check_kr2_wa(struct link_params *params,
13386 struct link_vars *vars,
13387 struct bnx2x_phy *phy)
13388{
13389 struct bnx2x *bp = params->bp;
13390 u16 base_page, next_page, not_kr2_device, lane;
13391 int sigdet = bnx2x_warpcore_get_sigdet(phy, params);
13392
13393 if (!sigdet) {
13394 if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
13395 bnx2x_kr2_recovery(params, vars, phy);
13396 return;
13397 }
13398
13399 lane = bnx2x_get_warpcore_lane(phy, params);
13400 CL22_WR_OVER_CL45(bp, phy, MDIO_REG_BANK_AER_BLOCK,
13401 MDIO_AER_BLOCK_AER_REG, lane);
13402 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
13403 MDIO_AN_REG_LP_AUTO_NEG, &base_page);
13404 bnx2x_cl45_read(bp, phy, MDIO_AN_DEVAD,
13405 MDIO_AN_REG_LP_AUTO_NEG2, &next_page);
13406 bnx2x_set_aer_mmd(params, phy);
13407
13408 /* CL73 has not begun yet */
13409 if (base_page == 0) {
13410 if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE))
13411 bnx2x_kr2_recovery(params, vars, phy);
13412 return;
13413 }
13414
13415 /* In case NP bit is not set in the BasePage, or it is set,
13416 * but only KX is advertised, declare this link partner as non-KR2
13417 * device.
13418 */
13419 not_kr2_device = (((base_page & 0x8000) == 0) ||
13420 (((base_page & 0x8000) &&
13421 ((next_page & 0xe0) == 0x2))));
13422
13423 /* In case KR2 is already disabled, check if we need to re-enable it */
13424 if (!(vars->link_attr_sync & LINK_ATTR_SYNC_KR2_ENABLE)) {
13425 if (!not_kr2_device) {
13426 DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page,
13427 next_page);
13428 bnx2x_kr2_recovery(params, vars, phy);
13429 }
13430 return;
13431 }
13432 /* KR2 is enabled, but not KR2 device */
13433 if (not_kr2_device) {
13434 /* Disable KR2 on both lanes */
13435 DP(NETIF_MSG_LINK, "BP=0x%x, NP=0x%x\n", base_page, next_page);
13436 bnx2x_disable_kr2(params, vars, phy);
13437 return;
13438 }
13439}
13440
13142void bnx2x_period_func(struct link_params *params, struct link_vars *vars) 13441void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
13143{ 13442{
13144 u16 phy_idx; 13443 u16 phy_idx;
@@ -13156,6 +13455,9 @@ void bnx2x_period_func(struct link_params *params, struct link_vars *vars)
13156 if (CHIP_IS_E3(bp)) { 13455 if (CHIP_IS_E3(bp)) {
13157 struct bnx2x_phy *phy = &params->phy[INT_PHY]; 13456 struct bnx2x_phy *phy = &params->phy[INT_PHY];
13158 bnx2x_set_aer_mmd(params, phy); 13457 bnx2x_set_aer_mmd(params, phy);
13458 if ((phy->supported & SUPPORTED_20000baseKR2_Full) &&
13459 (phy->speed_cap_mask & SPEED_20000))
13460 bnx2x_check_kr2_wa(params, vars, phy);
13159 bnx2x_check_over_curr(params, vars); 13461 bnx2x_check_over_curr(params, vars);
13160 if (vars->rx_tx_asic_rst) 13462 if (vars->rx_tx_asic_rst)
13161 bnx2x_warpcore_config_runtime(phy, params, vars); 13463 bnx2x_warpcore_config_runtime(phy, params, vars);