aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x_link.c
diff options
context:
space:
mode:
authorEilon Greenstein <eilong@broadcom.com>2009-08-12 04:23:04 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-13 02:02:27 -0400
commit239d686d494f10ecd83a89ddc4e31f9462ca4901 (patch)
treee3ce31aeb39bb144fa8ce9f74eadf764d39f05fd /drivers/net/bnx2x_link.c
parentbc7f0a053021491e292fc00810c4f2a8524453dd (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.c197
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
1153static void bnx2x_set_autoneg(struct link_params *params, 1153static 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, &reg_val); 1184 MDIO_SERDES_DIGITAL_A_1000X_CONTROL1, &reg_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 &reg_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 &reg_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
1303static void bnx2x_calc_ieee_aneg_adv(struct link_params *params, u32 *ieee_fc) 1349static 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
1348static void bnx2x_restart_autoneg(struct link_params *params) 1394static 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
1372static void bnx2x_initialize_sgmii_process(struct link_params *params, 1436static 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 1658static 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}
1595static u8 bnx2x_link_settings_status(struct link_params *params, 1725static 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
3427static void bnx2x_init_internal_phy(struct link_params *params, 3564static 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);