aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/bnx2x_link.c576
-rw-r--r--drivers/net/bnx2x_link.h3
-rw-r--r--drivers/net/bnx2x_main.c7
3 files changed, 428 insertions, 158 deletions
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c
index c9cffa6d47b..693efce7cda 100644
--- a/drivers/net/bnx2x_link.c
+++ b/drivers/net/bnx2x_link.c
@@ -2121,42 +2121,45 @@ static u8 bnx2x_bcm8073_xaui_wa(struct link_params *params)
}
-static void bnx2x_bcm8073_external_rom_boot(struct link_params *params)
+static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port,
+ u8 ext_phy_addr)
{
- struct bnx2x *bp = params->bp;
- u8 port = params->port;
- u8 ext_phy_addr = ((params->ext_phy_config &
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
- PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
- u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- u16 fw_ver1, fw_ver2, val;
- /* Need to wait 100ms after reset */
- msleep(100);
- /* Boot port from external ROM */
+ u16 fw_ver1, fw_ver2;
+ /* Boot port from external ROM */
/* EDC grst */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
0x0001);
/* ucode reboot and rst */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
0x008c);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_MISC_CTRL1, 0x0001);
/* Reset internal microprocessor */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET);
/* Release srst bit */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_GEN_CTRL,
MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP);
@@ -2165,35 +2168,52 @@ static void bnx2x_bcm8073_external_rom_boot(struct link_params *params)
msleep(100);
/* Clear ser_boot_ctl bit */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_MISC_CTRL1, 0x0000);
- bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_ROM_VER1, &fw_ver1);
- bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_ROM_VER2, &fw_ver2);
+ bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_ROM_VER2, &fw_ver2);
DP(NETIF_MSG_LINK, "8073 FW version 0x%x:0x%x\n", fw_ver1, fw_ver2);
- /* Only set bit 10 = 1 (Tx power down) */
- bnx2x_cl45_read(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_TX_POWER_DOWN, &val);
+}
+static void bnx2x_bcm807x_force_10G(struct link_params *params)
+{
+ struct bnx2x *bp = params->bp;
+ u8 port = params->port;
+ u8 ext_phy_addr = ((params->ext_phy_config &
+ PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+ PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+ u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
+
+ /* Force KR or KX */
bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_TX_POWER_DOWN, (val | 1<<10));
-
- msleep(600);
- /* Release bit 10 (Release Tx power down) */
+ MDIO_PMA_REG_CTRL,
+ 0x2040);
bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
-
+ MDIO_PMA_REG_10G_CTRL2,
+ 0x000b);
+ bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_BCM_CTRL,
+ 0x0000);
+ bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_CTRL,
+ 0x0000);
}
-
static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
{
struct bnx2x *bp = params->bp;
@@ -2259,32 +2279,51 @@ static void bnx2x_bcm8073_set_xaui_low_power_mode(struct link_params *params)
bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
MDIO_XS_DEVAD, MDIO_XS_PLL_SEQUENCER, val);
}
-static void bnx2x_bcm807x_force_10G(struct link_params *params)
+
+static void bnx2x_8073_set_pause_cl37(struct link_params *params,
+ struct link_vars *vars)
{
+
struct bnx2x *bp = params->bp;
- u8 port = params->port;
+ u16 cl37_val;
u8 ext_phy_addr = ((params->ext_phy_config &
PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config);
- /* Force KR or KX */
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- 0x2040);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_10G_CTRL2,
- 0x000b);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_BCM_CTRL,
- 0x0000);
- bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr,
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_CL37_FC_LD, &cl37_val);
+
+ cl37_val &= ~MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ /* Please refer to Table 28B-3 of 802.3ab-1999 spec. */
+
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC) {
+ cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_SYMMETRIC;
+ }
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC) {
+ cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_ASYMMETRIC;
+ }
+ if ((vars->ieee_fc &
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) ==
+ MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH) {
+ cl37_val |= MDIO_COMBO_IEEE0_AUTO_NEG_ADV_PAUSE_BOTH;
+ }
+ DP(NETIF_MSG_LINK,
+ "Ext phy AN advertize cl37 0x%x\n", cl37_val);
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
MDIO_AN_DEVAD,
- MDIO_AN_REG_CTRL,
- 0x0000);
+ MDIO_AN_REG_CL37_FC_LD, cl37_val);
+ msleep(500);
}
static void bnx2x_ext_phy_set_pause(struct link_params *params,
@@ -2542,54 +2581,43 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
rx_alarm_ctrl_val = 0x400;
lasi_ctrl_val = 0x0004;
} else {
- /* In 8073, port1 is directed through emac0 and
- * port0 is directed through emac1
- */
rx_alarm_ctrl_val = (1<<2);
- /*lasi_ctrl_val = 0x0005;*/
lasi_ctrl_val = 0x0004;
}
- /* Wait for soft reset to get cleared upto 1 sec */
- for (cnt = 0; cnt < 1000; cnt++) {
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_CTRL,
- &ctrl);
- if (!(ctrl & (1<<15)))
- break;
- msleep(1);
- }
- DP(NETIF_MSG_LINK,
- "807x control reg 0x%x (after %d ms)\n",
- ctrl, cnt);
+ /* enable LASI */
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_RX_ALARM_CTRL,
+ rx_alarm_ctrl_val);
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_LASI_CTRL,
+ lasi_ctrl_val);
+
+ bnx2x_8073_set_pause_cl37(params, vars);
if (ext_phy_type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072){
bnx2x_bcm8072_external_rom_boot(params);
} else {
- bnx2x_bcm8073_external_rom_boot(params);
+
/* In case of 8073 with long xaui lines,
don't set the 8073 xaui low power*/
bnx2x_bcm8073_set_xaui_low_power_mode(params);
}
- /* enable LASI */
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM_CTRL,
- rx_alarm_ctrl_val);
-
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_CTRL,
- lasi_ctrl_val);
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xca13,
+ &tmp1);
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
@@ -2603,12 +2631,21 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
/* If this is forced speed, set to KR or KX
* (all other are not supported)
*/
- if (!(params->req_line_speed == SPEED_AUTO_NEG)) {
- if (params->req_line_speed == SPEED_10000) {
- bnx2x_bcm807x_force_10G(params);
- DP(NETIF_MSG_LINK,
- "Forced speed 10G on 807X\n");
- break;
+ if (params->loopback_mode == LOOPBACK_EXT) {
+ bnx2x_bcm807x_force_10G(params);
+ DP(NETIF_MSG_LINK,
+ "Forced speed 10G on 807X\n");
+ break;
+ } else {
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type, ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_BCM_CTRL,
+ 0x0002);
+ }
+ if (params->req_line_speed != SPEED_AUTO_NEG) {
+ if (params->req_line_speed == SPEED_10000) {
+ val = (1<<7);
} else if (params->req_line_speed ==
SPEED_2500) {
val = (1<<5);
@@ -2623,11 +2660,14 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
PORT_HW_CFG_SPEED_CAPABILITY_D0_10G)
val |= (1<<7);
+ /* Note that 2.5G works only when
+ used with 1G advertisment */
if (params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_1G)
+ (PORT_HW_CFG_SPEED_CAPABILITY_D0_1G |
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G))
val |= (1<<5);
- DP(NETIF_MSG_LINK, "807x autoneg val = 0x%x\n", val);
- /*val = ((1<<5)|(1<<7));*/
+ DP(NETIF_MSG_LINK,
+ "807x autoneg val = 0x%x\n", val);
}
bnx2x_cl45_write(bp, params->port,
@@ -2638,20 +2678,19 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
if (ext_phy_type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
- /* Disable 2.5Ghz */
+
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
MDIO_AN_DEVAD,
0x8329, &tmp1);
-/* SUPPORT_SPEED_CAPABILITY
- (Due to the nature of the link order, its not
- possible to enable 2.5G within the autoneg
- capabilities)
- if (params->speed_cap_mask &
- PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G)
-*/
- if (params->req_line_speed == SPEED_2500) {
+
+ if (((params->speed_cap_mask &
+ PORT_HW_CFG_SPEED_CAPABILITY_D0_2_5G) &&
+ (params->req_line_speed ==
+ SPEED_AUTO_NEG)) ||
+ (params->req_line_speed ==
+ SPEED_2500)) {
u16 phy_ver;
/* Allow 2.5G for A1 and above */
bnx2x_cl45_read(bp, params->port,
@@ -2659,49 +2698,53 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
ext_phy_addr,
MDIO_PMA_DEVAD,
0xc801, &phy_ver);
-
+ DP(NETIF_MSG_LINK, "Add 2.5G\n");
if (phy_ver > 0)
tmp1 |= 1;
else
tmp1 &= 0xfffe;
- }
- else
+ } else {
+ DP(NETIF_MSG_LINK, "Disable 2.5G\n");
tmp1 &= 0xfffe;
+ }
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
0x8329, tmp1);
}
- /* Add support for CL37 (passive mode) I */
- bnx2x_cl45_write(bp, params->port,
+
+ /* Add support for CL37 (passive mode) II */
+
+ bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD, 0x040c);
- /* Add support for CL37 (passive mode) II */
+ MDIO_AN_REG_CL37_FC_LD,
+ &tmp1);
+
bnx2x_cl45_write(bp, params->port,
ext_phy_type,
ext_phy_addr,
MDIO_AN_DEVAD,
- MDIO_AN_REG_CL37_FC_LD, 0x20);
+ MDIO_AN_REG_CL37_FC_LD, (tmp1 |
+ ((params->req_duplex == DUPLEX_FULL) ?
+ 0x20 : 0x40)));
+
/* Add support for CL37 (passive mode) III */
bnx2x_cl45_write(bp, params->port,
ext_phy_type,
ext_phy_addr,
MDIO_AN_DEVAD,
MDIO_AN_REG_CL37_AN, 0x1000);
- /* Restart autoneg */
- msleep(500);
if (ext_phy_type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
-
- /* The SNR will improve about 2db by changing the
+ /* The SNR will improve about 2db by changing
BW and FEE main tap. Rest commands are executed
after link is up*/
- /* Change FFE main cursor to 5 in EDC register */
+ /*Change FFE main cursor to 5 in EDC register*/
if (bnx2x_8073_is_snr_needed(params))
bnx2x_cl45_write(bp, params->port,
ext_phy_type,
@@ -2710,25 +2753,28 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars)
MDIO_PMA_REG_EDC_FFE_MAIN,
0xFB0C);
- /* Enable FEC (Forware Error Correction)
- Request in the AN */
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV2, &tmp1);
+ /* Enable FEC (Forware Error Correction)
+ Request in the AN */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_ADV2, &tmp1);
- tmp1 |= (1<<15);
+ tmp1 |= (1<<15);
+
+ bnx2x_cl45_write(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ MDIO_AN_REG_ADV2, tmp1);
- bnx2x_cl45_write(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_AN_DEVAD,
- MDIO_AN_REG_ADV2, tmp1);
}
bnx2x_ext_phy_set_pause(params, vars);
+ /* Restart autoneg */
+ msleep(500);
bnx2x_cl45_write(bp, params->port,
ext_phy_type,
ext_phy_addr,
@@ -2910,6 +2956,8 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072:
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
{
+ u16 link_status = 0;
+ u16 an1000_status = 0;
if (ext_phy_type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) {
bnx2x_cl45_read(bp, params->port,
@@ -2936,14 +2984,9 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
MDIO_PMA_DEVAD,
MDIO_PMA_REG_LASI_STATUS, &val1);
- bnx2x_cl45_read(bp, params->port,
- ext_phy_type,
- ext_phy_addr,
- MDIO_PMA_DEVAD,
- MDIO_PMA_REG_LASI_STATUS, &val2);
DP(NETIF_MSG_LINK,
- "8703 LASI status 0x%x->0x%x\n",
- val1, val2);
+ "8703 LASI status 0x%x\n",
+ val1);
}
/* clear the interrupt LASI status register */
@@ -2959,20 +3002,23 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
MDIO_PCS_REG_STATUS, &val1);
DP(NETIF_MSG_LINK, "807x PCS status 0x%x->0x%x\n",
val2, val1);
- /* Check the LASI */
+ /* Clear MSG-OUT */
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM, &val2);
+ 0xca13,
+ &val1);
+
+ /* Check the LASI */
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
MDIO_PMA_DEVAD,
- MDIO_PMA_REG_RX_ALARM,
- &val1);
- DP(NETIF_MSG_LINK, "KR 0x9003 0x%x->0x%x\n",
- val2, val1);
+ MDIO_PMA_REG_RX_ALARM, &val2);
+
+ DP(NETIF_MSG_LINK, "KR 0x9003 0x%x\n", val2);
+
/* Check the link status */
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
@@ -2995,29 +3041,29 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
DP(NETIF_MSG_LINK, "PMA_REG_STATUS=0x%x\n", val1);
if (ext_phy_type ==
PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) {
- u16 an1000_status = 0;
+
if (ext_phy_link_up &&
- (
- (params->req_line_speed != SPEED_10000)
- )) {
+ ((params->req_line_speed !=
+ SPEED_10000))) {
if (bnx2x_bcm8073_xaui_wa(params)
!= 0) {
ext_phy_link_up = 0;
break;
}
- bnx2x_cl45_read(bp, params->port,
+ }
+ bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
- MDIO_XS_DEVAD,
+ MDIO_AN_DEVAD,
0x8304,
&an1000_status);
- bnx2x_cl45_read(bp, params->port,
+ bnx2x_cl45_read(bp, params->port,
ext_phy_type,
ext_phy_addr,
- MDIO_XS_DEVAD,
+ MDIO_AN_DEVAD,
0x8304,
&an1000_status);
- }
+
/* Check the link status on 1.1.2 */
bnx2x_cl45_read(bp, params->port,
ext_phy_type,
@@ -3033,8 +3079,8 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
"an_link_status=0x%x\n",
val2, val1, an1000_status);
- ext_phy_link_up = (((val1 & 4) == 4) ||
- (an1000_status & (1<<1)));
+ ext_phy_link_up = (((val1 & 4) == 4) ||
+ (an1000_status & (1<<1)));
if (ext_phy_link_up &&
bnx2x_8073_is_snr_needed(params)) {
/* The SNR will improve about 2dbby
@@ -3058,8 +3104,74 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params,
MDIO_PMA_REG_CDR_BANDWIDTH,
0x0333);
+
+ }
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_PMA_DEVAD,
+ 0xc820,
+ &link_status);
+
+ /* Bits 0..2 --> speed detected,
+ bits 13..15--> link is down */
+ if ((link_status & (1<<2)) &&
+ (!(link_status & (1<<15)))) {
+ ext_phy_link_up = 1;
+ vars->line_speed = SPEED_10000;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " up in 10G\n", params->port);
+ } else if ((link_status & (1<<1)) &&
+ (!(link_status & (1<<14)))) {
+ ext_phy_link_up = 1;
+ vars->line_speed = SPEED_2500;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " up in 2.5G\n", params->port);
+ } else if ((link_status & (1<<0)) &&
+ (!(link_status & (1<<13)))) {
+ ext_phy_link_up = 1;
+ vars->line_speed = SPEED_1000;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " up in 1G\n", params->port);
+ } else {
+ ext_phy_link_up = 0;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " is down\n", params->port);
+ }
+ } else {
+ /* See if 1G link is up for the 8072 */
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ 0x8304,
+ &an1000_status);
+ bnx2x_cl45_read(bp, params->port,
+ ext_phy_type,
+ ext_phy_addr,
+ MDIO_AN_DEVAD,
+ 0x8304,
+ &an1000_status);
+ if (an1000_status & (1<<1)) {
+ ext_phy_link_up = 1;
+ vars->line_speed = SPEED_1000;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " up in 1G\n", params->port);
+ } else if (ext_phy_link_up) {
+ ext_phy_link_up = 1;
+ vars->line_speed = SPEED_10000;
+ DP(NETIF_MSG_LINK,
+ "port %x: External link"
+ " up in 10G\n", params->port);
}
}
+
+
break;
}
case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101:
@@ -4203,6 +4315,154 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars)
return rc;
}
+static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+{
+ u8 ext_phy_addr[PORT_MAX];
+ u16 val;
+ s8 port;
+
+ /* PART1 - Reset both phys */
+ for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+ /* Extract the ext phy address for the port */
+ u32 ext_phy_config = REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[port].external_phy_config));
+
+ /* disable attentions */
+ bnx2x_bits_dis(bp, NIG_REG_MASK_INTERRUPT_PORT0 + port*4,
+ (NIG_MASK_XGXS0_LINK_STATUS |
+ NIG_MASK_XGXS0_LINK10G |
+ NIG_MASK_SERDES0_LINK_STATUS |
+ NIG_MASK_MI_INT));
+
+ ext_phy_addr[port] =
+ ((ext_phy_config &
+ PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >>
+ PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT);
+
+ /* Need to take the phy out of low power mode in order
+ to write to access its registers */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_HIGH, port);
+
+ /* Reset the phy */
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_CTRL,
+ 1<<15);
+ }
+
+ /* Add delay of 150ms after reset */
+ msleep(150);
+
+ /* PART2 - Download firmware to both phys */
+ for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+ u16 fw_ver1;
+
+ bnx2x_bcm8073_external_rom_boot(bp, port,
+ ext_phy_addr[port]);
+
+ bnx2x_cl45_read(bp, port, PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_ROM_VER1, &fw_ver1);
+ if (fw_ver1 == 0) {
+ DP(NETIF_MSG_LINK,
+ "bnx2x_8073_common_init_phy port %x "
+ "fw Download failed\n", port);
+ return -EINVAL;
+ }
+
+ /* Only set bit 10 = 1 (Tx power down) */
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_POWER_DOWN, &val);
+
+ /* Phase1 of TX_POWER_DOWN reset */
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_POWER_DOWN,
+ (val | 1<<10));
+ }
+
+ /* Toggle Transmitter: Power down and then up with 600ms
+ delay between */
+ msleep(600);
+
+ /* PART3 - complete TX_POWER_DOWN process, and set GPIO2 back to low */
+ for (port = PORT_MAX - 1; port >= PORT_0; port--) {
+ /* Phase2 of POWER_DOWN_RESET*/
+ /* Release bit 10 (Release Tx power down) */
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_POWER_DOWN, &val);
+
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_TX_POWER_DOWN, (val & (~(1<<10))));
+ msleep(15);
+
+ /* Read modify write the SPI-ROM version select register */
+ bnx2x_cl45_read(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_EDC_FFE_MAIN, &val);
+ bnx2x_cl45_write(bp, port,
+ PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073,
+ ext_phy_addr[port],
+ MDIO_PMA_DEVAD,
+ MDIO_PMA_REG_EDC_FFE_MAIN, (val | (1<<12)));
+
+ /* set GPIO2 back to LOW */
+ bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2,
+ MISC_REGISTERS_GPIO_OUTPUT_LOW, port);
+ }
+ return 0;
+
+}
+
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base)
+{
+ u8 rc = 0;
+ u32 ext_phy_type;
+
+ DP(NETIF_MSG_LINK, "bnx2x_common_init_phy\n");
+
+ /* Read the ext_phy_type for arbitrary port(0) */
+ ext_phy_type = XGXS_EXT_PHY_TYPE(
+ REG_RD(bp, shmem_base +
+ offsetof(struct shmem_region,
+ dev_info.port_hw_config[0].external_phy_config)));
+
+ switch (ext_phy_type) {
+ case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073:
+ {
+ rc = bnx2x_8073_common_init_phy(bp, shmem_base);
+ break;
+ }
+ default:
+ DP(NETIF_MSG_LINK,
+ "bnx2x_common_init_phy: ext_phy 0x%x not required\n",
+ ext_phy_type);
+ break;
+ }
+
+ return rc;
+}
+
+
+
static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
{
u16 val, cnt;
diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h
index b222552b868..80c945ca3a5 100644
--- a/drivers/net/bnx2x_link.h
+++ b/drivers/net/bnx2x_link.h
@@ -55,6 +55,7 @@ struct link_params {
#define LOOPBACK_BMAC 2
#define LOOPBACK_XGXS_10 3
#define LOOPBACK_EXT_PHY 4
+#define LOOPBACK_EXT 5
u16 req_duplex;
u16 req_flow_ctrl;
@@ -166,5 +167,7 @@ u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config,
otherwise link is down*/
u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars);
+/* One-time initialization for external phy after power up */
+u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base);
#endif /* BNX2X_LINK_H */
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c
index 85ea799a053..594b08aac93 100644
--- a/drivers/net/bnx2x_main.c
+++ b/drivers/net/bnx2x_main.c
@@ -5377,6 +5377,13 @@ static int bnx2x_init_common(struct bnx2x *bp)
((u32 *)&tmp)[1]);
}
+ if (!BP_NOMCP(bp)) {
+ bnx2x_acquire_phy_lock(bp);
+ bnx2x_common_init_phy(bp, bp->common.shmem_base);
+ bnx2x_release_phy_lock(bp);
+ } else
+ BNX2X_ERR("Bootcode is missing - can not initialize link\n");
+
return 0;
}