diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-08-12 04:23:04 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-13 02:02:27 -0400 |
commit | 239d686d494f10ecd83a89ddc4e31f9462ca4901 (patch) | |
tree | e3ce31aeb39bb144fa8ce9f74eadf764d39f05fd /drivers/net/bnx2x_link.c | |
parent | bc7f0a053021491e292fc00810c4f2a8524453dd (diff) |
bnx2x: Adding XAUI CL73 autoneg support
Adding CL73 support to the built in PHY in the 5771x device. Also supporting
fallbacks to CL73 if the link partner does not respond.
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/bnx2x_link.c')
-rw-r--r-- | drivers/net/bnx2x_link.c | 197 |
1 files changed, 167 insertions, 30 deletions
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index db4f3c057a19..371310db2eba 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -1151,7 +1151,8 @@ static void bnx2x_set_parallel_detection(struct link_params *params, | |||
1151 | } | 1151 | } |
1152 | 1152 | ||
1153 | static void bnx2x_set_autoneg(struct link_params *params, | 1153 | static void bnx2x_set_autoneg(struct link_params *params, |
1154 | struct link_vars *vars) | 1154 | struct link_vars *vars, |
1155 | u8 enable_cl73) | ||
1155 | { | 1156 | { |
1156 | struct bnx2x *bp = params->bp; | 1157 | struct bnx2x *bp = params->bp; |
1157 | u16 reg_val; | 1158 | u16 reg_val; |
@@ -1181,7 +1182,9 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1181 | params->phy_addr, | 1182 | params->phy_addr, |
1182 | MDIO_REG_BANK_SERDES_DIGITAL, | 1183 | MDIO_REG_BANK_SERDES_DIGITAL, |
1183 | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, ®_val); | 1184 | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, ®_val); |
1184 | reg_val &= ~MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN; | 1185 | reg_val &= ~(MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_SIGNAL_DETECT_EN | |
1186 | MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_INVERT_SIGNAL_DETECT); | ||
1187 | reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_FIBER_MODE; | ||
1185 | if (vars->line_speed == SPEED_AUTO_NEG) | 1188 | if (vars->line_speed == SPEED_AUTO_NEG) |
1186 | reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; | 1189 | reg_val |= MDIO_SERDES_DIGITAL_A_1000X_CONTROL1_AUTODET; |
1187 | else | 1190 | else |
@@ -1213,8 +1216,51 @@ static void bnx2x_set_autoneg(struct link_params *params, | |||
1213 | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL, | 1216 | MDIO_BAM_NEXT_PAGE_MP5_NEXT_PAGE_CTRL, |
1214 | reg_val); | 1217 | reg_val); |
1215 | 1218 | ||
1216 | /* CL73 Autoneg Disabled */ | 1219 | if (enable_cl73) { |
1217 | reg_val = 0; | 1220 | /* Enable Cl73 FSM status bits */ |
1221 | CL45_WR_OVER_CL22(bp, params->port, | ||
1222 | params->phy_addr, | ||
1223 | MDIO_REG_BANK_CL73_USERB0, | ||
1224 | MDIO_CL73_USERB0_CL73_UCTRL, | ||
1225 | MDIO_CL73_USERB0_CL73_UCTRL_USTAT1_MUXSEL); | ||
1226 | |||
1227 | /* Enable BAM Station Manager*/ | ||
1228 | CL45_WR_OVER_CL22(bp, params->port, | ||
1229 | params->phy_addr, | ||
1230 | MDIO_REG_BANK_CL73_USERB0, | ||
1231 | MDIO_CL73_USERB0_CL73_BAM_CTRL1, | ||
1232 | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_EN | | ||
1233 | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_STATION_MNGR_EN | | ||
1234 | MDIO_CL73_USERB0_CL73_BAM_CTRL1_BAM_NP_AFTER_BP_EN); | ||
1235 | |||
1236 | /* Merge CL73 and CL37 aneg resolution */ | ||
1237 | CL45_RD_OVER_CL22(bp, params->port, | ||
1238 | params->phy_addr, | ||
1239 | MDIO_REG_BANK_CL73_USERB0, | ||
1240 | MDIO_CL73_USERB0_CL73_BAM_CTRL3, | ||
1241 | ®_val); | ||
1242 | |||
1243 | if (params->speed_cap_mask & | ||
1244 | PORT_HW_CFG_SPEED_CAPABILITY_D0_10G) { | ||
1245 | /* Set the CL73 AN speed */ | ||
1246 | CL45_RD_OVER_CL22(bp, params->port, | ||
1247 | params->phy_addr, | ||
1248 | MDIO_REG_BANK_CL73_IEEEB1, | ||
1249 | MDIO_CL73_IEEEB1_AN_ADV2, | ||
1250 | ®_val); | ||
1251 | |||
1252 | CL45_WR_OVER_CL22(bp, params->port, | ||
1253 | params->phy_addr, | ||
1254 | MDIO_REG_BANK_CL73_IEEEB1, | ||
1255 | MDIO_CL73_IEEEB1_AN_ADV2, | ||
1256 | reg_val | MDIO_CL73_IEEEB1_AN_ADV2_ADVR_10G_KX4); | ||
1257 | |||
1258 | } | ||
1259 | /* CL73 Autoneg Enabled */ | ||
1260 | reg_val = MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN; | ||
1261 | |||
1262 | } else /* CL73 Autoneg Disabled */ | ||
1263 | reg_val = 0; | ||
1218 | 1264 | ||
1219 | CL45_WR_OVER_CL22(bp, params->port, | 1265 | CL45_WR_OVER_CL22(bp, params->port, |
1220 | params->phy_addr, | 1266 | params->phy_addr, |
@@ -1297,7 +1343,7 @@ static void bnx2x_set_brcm_cl37_advertisment(struct link_params *params) | |||
1297 | CL45_WR_OVER_CL22(bp, params->port, | 1343 | CL45_WR_OVER_CL22(bp, params->port, |
1298 | params->phy_addr, | 1344 | params->phy_addr, |
1299 | MDIO_REG_BANK_OVER_1G, | 1345 | MDIO_REG_BANK_OVER_1G, |
1300 | MDIO_OVER_1G_UP3, 0); | 1346 | MDIO_OVER_1G_UP3, 0x400); |
1301 | } | 1347 | } |
1302 | 1348 | ||
1303 | static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc) | 1349 | static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc) |
@@ -1345,28 +1391,46 @@ static void bnx2x_set_ieee_aneg_advertisment(struct link_params *params, | |||
1345 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc); | 1391 | MDIO_COMBO_IEEE0_AUTO_NEG_ADV, (u16)ieee_fc); |
1346 | } | 1392 | } |
1347 | 1393 | ||
1348 | static void bnx2x_restart_autoneg(struct link_params *params) | 1394 | static void bnx2x_restart_autoneg(struct link_params *params, u8 enable_cl73) |
1349 | { | 1395 | { |
1350 | struct bnx2x *bp = params->bp; | 1396 | struct bnx2x *bp = params->bp; |
1351 | u16 mii_control; | 1397 | u16 mii_control; |
1398 | |||
1352 | DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n"); | 1399 | DP(NETIF_MSG_LINK, "bnx2x_restart_autoneg\n"); |
1353 | /* Enable and restart BAM/CL37 aneg */ | 1400 | /* Enable and restart BAM/CL37 aneg */ |
1354 | 1401 | ||
1355 | CL45_RD_OVER_CL22(bp, params->port, | 1402 | if (enable_cl73) { |
1356 | params->phy_addr, | 1403 | CL45_RD_OVER_CL22(bp, params->port, |
1357 | MDIO_REG_BANK_COMBO_IEEE0, | 1404 | params->phy_addr, |
1358 | MDIO_COMBO_IEEE0_MII_CONTROL, | 1405 | MDIO_REG_BANK_CL73_IEEEB0, |
1359 | &mii_control); | 1406 | MDIO_CL73_IEEEB0_CL73_AN_CONTROL, |
1360 | DP(NETIF_MSG_LINK, | 1407 | &mii_control); |
1361 | "bnx2x_restart_autoneg mii_control before = 0x%x\n", | 1408 | |
1362 | mii_control); | 1409 | CL45_WR_OVER_CL22(bp, params->port, |
1363 | CL45_WR_OVER_CL22(bp, params->port, | 1410 | params->phy_addr, |
1364 | params->phy_addr, | 1411 | MDIO_REG_BANK_CL73_IEEEB0, |
1365 | MDIO_REG_BANK_COMBO_IEEE0, | 1412 | MDIO_CL73_IEEEB0_CL73_AN_CONTROL, |
1366 | MDIO_COMBO_IEEE0_MII_CONTROL, | 1413 | (mii_control | |
1367 | (mii_control | | 1414 | MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN | |
1368 | MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | | 1415 | MDIO_CL73_IEEEB0_CL73_AN_CONTROL_RESTART_AN)); |
1369 | MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN)); | 1416 | } else { |
1417 | |||
1418 | CL45_RD_OVER_CL22(bp, params->port, | ||
1419 | params->phy_addr, | ||
1420 | MDIO_REG_BANK_COMBO_IEEE0, | ||
1421 | MDIO_COMBO_IEEE0_MII_CONTROL, | ||
1422 | &mii_control); | ||
1423 | DP(NETIF_MSG_LINK, | ||
1424 | "bnx2x_restart_autoneg mii_control before = 0x%x\n", | ||
1425 | mii_control); | ||
1426 | CL45_WR_OVER_CL22(bp, params->port, | ||
1427 | params->phy_addr, | ||
1428 | MDIO_REG_BANK_COMBO_IEEE0, | ||
1429 | MDIO_COMBO_IEEE0_MII_CONTROL, | ||
1430 | (mii_control | | ||
1431 | MDIO_COMBO_IEEO_MII_CONTROL_AN_EN | | ||
1432 | MDIO_COMBO_IEEO_MII_CONTROL_RESTART_AN)); | ||
1433 | } | ||
1370 | } | 1434 | } |
1371 | 1435 | ||
1372 | static void bnx2x_initialize_sgmii_process(struct link_params *params, | 1436 | static void bnx2x_initialize_sgmii_process(struct link_params *params, |
@@ -1438,7 +1502,7 @@ static void bnx2x_initialize_sgmii_process(struct link_params *params, | |||
1438 | 1502 | ||
1439 | } else { /* AN mode */ | 1503 | } else { /* AN mode */ |
1440 | /* enable and restart AN */ | 1504 | /* enable and restart AN */ |
1441 | bnx2x_restart_autoneg(params); | 1505 | bnx2x_restart_autoneg(params, 0); |
1442 | } | 1506 | } |
1443 | } | 1507 | } |
1444 | 1508 | ||
@@ -1591,7 +1655,73 @@ static void bnx2x_flow_ctrl_resolve(struct link_params *params, | |||
1591 | DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl); | 1655 | DP(NETIF_MSG_LINK, "flow_ctrl 0x%x\n", vars->flow_ctrl); |
1592 | } | 1656 | } |
1593 | 1657 | ||
1594 | 1658 | static void bnx2x_check_fallback_to_cl37(struct link_params *params) | |
1659 | { | ||
1660 | struct bnx2x *bp = params->bp; | ||
1661 | u16 rx_status, ustat_val, cl37_fsm_recieved; | ||
1662 | DP(NETIF_MSG_LINK, "bnx2x_check_fallback_to_cl37\n"); | ||
1663 | /* Step 1: Make sure signal is detected */ | ||
1664 | CL45_RD_OVER_CL22(bp, params->port, | ||
1665 | params->phy_addr, | ||
1666 | MDIO_REG_BANK_RX0, | ||
1667 | MDIO_RX0_RX_STATUS, | ||
1668 | &rx_status); | ||
1669 | if ((rx_status & MDIO_RX0_RX_STATUS_SIGDET) != | ||
1670 | (MDIO_RX0_RX_STATUS_SIGDET)) { | ||
1671 | DP(NETIF_MSG_LINK, "Signal is not detected. Restoring CL73." | ||
1672 | "rx_status(0x80b0) = 0x%x\n", rx_status); | ||
1673 | CL45_WR_OVER_CL22(bp, params->port, | ||
1674 | params->phy_addr, | ||
1675 | MDIO_REG_BANK_CL73_IEEEB0, | ||
1676 | MDIO_CL73_IEEEB0_CL73_AN_CONTROL, | ||
1677 | MDIO_CL73_IEEEB0_CL73_AN_CONTROL_AN_EN); | ||
1678 | return; | ||
1679 | } | ||
1680 | /* Step 2: Check CL73 state machine */ | ||
1681 | CL45_RD_OVER_CL22(bp, params->port, | ||
1682 | params->phy_addr, | ||
1683 | MDIO_REG_BANK_CL73_USERB0, | ||
1684 | MDIO_CL73_USERB0_CL73_USTAT1, | ||
1685 | &ustat_val); | ||
1686 | if ((ustat_val & | ||
1687 | (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK | | ||
1688 | MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) != | ||
1689 | (MDIO_CL73_USERB0_CL73_USTAT1_LINK_STATUS_CHECK | | ||
1690 | MDIO_CL73_USERB0_CL73_USTAT1_AN_GOOD_CHECK_BAM37)) { | ||
1691 | DP(NETIF_MSG_LINK, "CL73 state-machine is not stable. " | ||
1692 | "ustat_val(0x8371) = 0x%x\n", ustat_val); | ||
1693 | return; | ||
1694 | } | ||
1695 | /* Step 3: Check CL37 Message Pages received to indicate LP | ||
1696 | supports only CL37 */ | ||
1697 | CL45_RD_OVER_CL22(bp, params->port, | ||
1698 | params->phy_addr, | ||
1699 | MDIO_REG_BANK_REMOTE_PHY, | ||
1700 | MDIO_REMOTE_PHY_MISC_RX_STATUS, | ||
1701 | &cl37_fsm_recieved); | ||
1702 | if ((cl37_fsm_recieved & | ||
1703 | (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG | | ||
1704 | MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) != | ||
1705 | (MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_OVER1G_MSG | | ||
1706 | MDIO_REMOTE_PHY_MISC_RX_STATUS_CL37_FSM_RECEIVED_BRCM_OUI_MSG)) { | ||
1707 | DP(NETIF_MSG_LINK, "No CL37 FSM were received. " | ||
1708 | "misc_rx_status(0x8330) = 0x%x\n", | ||
1709 | cl37_fsm_recieved); | ||
1710 | return; | ||
1711 | } | ||
1712 | /* The combined cl37/cl73 fsm state information indicating that we are | ||
1713 | connected to a device which does not support cl73, but does support | ||
1714 | cl37 BAM. In this case we disable cl73 and restart cl37 auto-neg */ | ||
1715 | /* Disable CL73 */ | ||
1716 | CL45_WR_OVER_CL22(bp, params->port, | ||
1717 | params->phy_addr, | ||
1718 | MDIO_REG_BANK_CL73_IEEEB0, | ||
1719 | MDIO_CL73_IEEEB0_CL73_AN_CONTROL, | ||
1720 | 0); | ||
1721 | /* Restart CL37 autoneg */ | ||
1722 | bnx2x_restart_autoneg(params, 0); | ||
1723 | DP(NETIF_MSG_LINK, "Disabling CL73, and restarting CL37 autoneg\n"); | ||
1724 | } | ||
1595 | static u8 bnx2x_link_settings_status(struct link_params *params, | 1725 | static u8 bnx2x_link_settings_status(struct link_params *params, |
1596 | struct link_vars *vars, | 1726 | struct link_vars *vars, |
1597 | u32 gp_status, | 1727 | u32 gp_status, |
@@ -1755,6 +1885,13 @@ static u8 bnx2x_link_settings_status(struct link_params *params, | |||
1755 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; | 1885 | vars->flow_ctrl = BNX2X_FLOW_CTRL_NONE; |
1756 | vars->autoneg = AUTO_NEG_DISABLED; | 1886 | vars->autoneg = AUTO_NEG_DISABLED; |
1757 | vars->mac_type = MAC_TYPE_NONE; | 1887 | vars->mac_type = MAC_TYPE_NONE; |
1888 | |||
1889 | if ((params->req_line_speed == SPEED_AUTO_NEG) && | ||
1890 | ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | ||
1891 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT))) { | ||
1892 | /* Check signal is detected */ | ||
1893 | bnx2x_check_fallback_to_cl37(params); | ||
1894 | } | ||
1758 | } | 1895 | } |
1759 | 1896 | ||
1760 | DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n", | 1897 | DP(NETIF_MSG_LINK, "gp_status 0x%x phy_link_up %x line_speed %x \n", |
@@ -3425,7 +3562,8 @@ static void bnx2x_8481_set_10G_led_mode(struct link_params *params, | |||
3425 | 3562 | ||
3426 | 3563 | ||
3427 | static void bnx2x_init_internal_phy(struct link_params *params, | 3564 | static void bnx2x_init_internal_phy(struct link_params *params, |
3428 | struct link_vars *vars) | 3565 | struct link_vars *vars, |
3566 | u8 enable_cl73) | ||
3429 | { | 3567 | { |
3430 | struct bnx2x *bp = params->bp; | 3568 | struct bnx2x *bp = params->bp; |
3431 | if (!(vars->phy_flags & PHY_SGMII_FLAG)) { | 3569 | if (!(vars->phy_flags & PHY_SGMII_FLAG)) { |
@@ -3440,7 +3578,7 @@ static void bnx2x_init_internal_phy(struct link_params *params, | |||
3440 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); | 3578 | DP(NETIF_MSG_LINK, "not SGMII, no AN\n"); |
3441 | 3579 | ||
3442 | /* disable autoneg */ | 3580 | /* disable autoneg */ |
3443 | bnx2x_set_autoneg(params, vars); | 3581 | bnx2x_set_autoneg(params, vars, 0); |
3444 | 3582 | ||
3445 | /* program speed and duplex */ | 3583 | /* program speed and duplex */ |
3446 | bnx2x_program_serdes(params, vars); | 3584 | bnx2x_program_serdes(params, vars); |
@@ -3456,10 +3594,10 @@ static void bnx2x_init_internal_phy(struct link_params *params, | |||
3456 | vars->ieee_fc); | 3594 | vars->ieee_fc); |
3457 | 3595 | ||
3458 | /* enable autoneg */ | 3596 | /* enable autoneg */ |
3459 | bnx2x_set_autoneg(params, vars); | 3597 | bnx2x_set_autoneg(params, vars, enable_cl73); |
3460 | 3598 | ||
3461 | /* enable and restart AN */ | 3599 | /* enable and restart AN */ |
3462 | bnx2x_restart_autoneg(params); | 3600 | bnx2x_restart_autoneg(params, enable_cl73); |
3463 | } | 3601 | } |
3464 | 3602 | ||
3465 | } else { /* SGMII mode */ | 3603 | } else { /* SGMII mode */ |
@@ -5815,11 +5953,10 @@ static u8 bnx2x_link_initialize(struct link_params *params, | |||
5815 | if (non_ext_phy || | 5953 | if (non_ext_phy || |
5816 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || | 5954 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || |
5817 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) || | 5955 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) || |
5818 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481) || | ||
5819 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { | 5956 | (params->loopback_mode == LOOPBACK_EXT_PHY)) { |
5820 | if (params->req_line_speed == SPEED_AUTO_NEG) | 5957 | if (params->req_line_speed == SPEED_AUTO_NEG) |
5821 | bnx2x_set_parallel_detection(params, vars->phy_flags); | 5958 | bnx2x_set_parallel_detection(params, vars->phy_flags); |
5822 | bnx2x_init_internal_phy(params, vars); | 5959 | bnx2x_init_internal_phy(params, vars, non_ext_phy); |
5823 | } | 5960 | } |
5824 | 5961 | ||
5825 | if (!non_ext_phy) | 5962 | if (!non_ext_phy) |
@@ -6296,7 +6433,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
6296 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) && | 6433 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) && |
6297 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) && | 6434 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) && |
6298 | (ext_phy_link_up && !vars->phy_link_up)) | 6435 | (ext_phy_link_up && !vars->phy_link_up)) |
6299 | bnx2x_init_internal_phy(params, vars); | 6436 | bnx2x_init_internal_phy(params, vars, 0); |
6300 | 6437 | ||
6301 | /* link is up only if both local phy and external phy are up */ | 6438 | /* link is up only if both local phy and external phy are up */ |
6302 | vars->link_up = (ext_phy_link_up && vars->phy_link_up); | 6439 | vars->link_up = (ext_phy_link_up && vars->phy_link_up); |