diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-08-12 04:23:11 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-08-13 02:02:32 -0400 |
commit | f57a60256d02daba1316c98da472f02cd98a58d3 (patch) | |
tree | c927a54bf16050d43418c11404afc1fd78370940 /drivers/net | |
parent | 01cd452846c98609dd3efbee0deea050e6706f02 (diff) |
bnx2x: Supporting PHY FW upgrade
There are 3 operations that the driver needs to support to allow applications to
access the PHY FW (on top of the MDC/MDIO access). Since those are essentially
nvram access commands, adding them to the ethtool -E interface.
Signed-off-by: Eilon Greenstein <eilong@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/bnx2x_link.c | 21 | ||||
-rw-r--r-- | drivers/net/bnx2x_link.h | 4 | ||||
-rw-r--r-- | drivers/net/bnx2x_main.c | 72 |
3 files changed, 67 insertions, 30 deletions
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index 371310db2eba..98e3e8fc0ef7 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -1996,7 +1996,7 @@ static u8 bnx2x_emac_program(struct link_params *params, | |||
1996 | /*****************************************************************************/ | 1996 | /*****************************************************************************/ |
1997 | /* External Phy section */ | 1997 | /* External Phy section */ |
1998 | /*****************************************************************************/ | 1998 | /*****************************************************************************/ |
1999 | static void bnx2x_hw_reset(struct bnx2x *bp, u8 port) | 1999 | void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port) |
2000 | { | 2000 | { |
2001 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | 2001 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, |
2002 | MISC_REGISTERS_GPIO_OUTPUT_LOW, port); | 2002 | MISC_REGISTERS_GPIO_OUTPUT_LOW, port); |
@@ -2035,7 +2035,7 @@ static void bnx2x_ext_phy_reset(struct link_params *params, | |||
2035 | params->port); | 2035 | params->port); |
2036 | 2036 | ||
2037 | /* HW reset */ | 2037 | /* HW reset */ |
2038 | bnx2x_hw_reset(bp, params->port); | 2038 | bnx2x_ext_phy_hw_reset(bp, params->port); |
2039 | 2039 | ||
2040 | bnx2x_cl45_write(bp, params->port, | 2040 | bnx2x_cl45_write(bp, params->port, |
2041 | ext_phy_type, | 2041 | ext_phy_type, |
@@ -2106,8 +2106,7 @@ static void bnx2x_ext_phy_reset(struct link_params *params, | |||
2106 | params->port); | 2106 | params->port); |
2107 | 2107 | ||
2108 | /* HW reset */ | 2108 | /* HW reset */ |
2109 | bnx2x_hw_reset(bp, params->port); | 2109 | bnx2x_ext_phy_hw_reset(bp, params->port); |
2110 | |||
2111 | break; | 2110 | break; |
2112 | 2111 | ||
2113 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: | 2112 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481: |
@@ -2118,7 +2117,7 @@ static void bnx2x_ext_phy_reset(struct link_params *params, | |||
2118 | params->port); | 2117 | params->port); |
2119 | 2118 | ||
2120 | /* HW reset */ | 2119 | /* HW reset */ |
2121 | bnx2x_hw_reset(bp, params->port); | 2120 | bnx2x_ext_phy_hw_reset(bp, params->port); |
2122 | 2121 | ||
2123 | bnx2x_cl45_write(bp, params->port, | 2122 | bnx2x_cl45_write(bp, params->port, |
2124 | ext_phy_type, | 2123 | ext_phy_type, |
@@ -2146,7 +2145,7 @@ static void bnx2x_ext_phy_reset(struct link_params *params, | |||
2146 | 2145 | ||
2147 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: | 2146 | case PORT_HW_CFG_SERDES_EXT_PHY_TYPE_BCM5482: |
2148 | DP(NETIF_MSG_LINK, "SerDes 5482\n"); | 2147 | DP(NETIF_MSG_LINK, "SerDes 5482\n"); |
2149 | bnx2x_hw_reset(bp, params->port); | 2148 | bnx2x_ext_phy_hw_reset(bp, params->port); |
2150 | break; | 2149 | break; |
2151 | 2150 | ||
2152 | default: | 2151 | default: |
@@ -6573,7 +6572,7 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6573 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); | 6572 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); |
6574 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); | 6573 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); |
6575 | 6574 | ||
6576 | bnx2x_hw_reset(bp, 1 ^ (swap_val && swap_override)); | 6575 | bnx2x_ext_phy_hw_reset(bp, 1 ^ (swap_val && swap_override)); |
6577 | msleep(5); | 6576 | msleep(5); |
6578 | 6577 | ||
6579 | if (swap_val && swap_override) | 6578 | if (swap_val && swap_override) |
@@ -6647,7 +6646,7 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6647 | (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); | 6646 | (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); |
6648 | REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val); | 6647 | REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val); |
6649 | 6648 | ||
6650 | bnx2x_hw_reset(bp, 1); | 6649 | bnx2x_ext_phy_hw_reset(bp, 1); |
6651 | msleep(5); | 6650 | msleep(5); |
6652 | for (port = 0; port < PORT_MAX; port++) { | 6651 | for (port = 0; port < PORT_MAX; port++) { |
6653 | /* Extract the ext phy address for the port */ | 6652 | /* Extract the ext phy address for the port */ |
@@ -6714,9 +6713,7 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
6714 | return rc; | 6713 | return rc; |
6715 | } | 6714 | } |
6716 | 6715 | ||
6717 | 6716 | void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr) | |
6718 | |||
6719 | static void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr) | ||
6720 | { | 6717 | { |
6721 | u16 val, cnt; | 6718 | u16 val, cnt; |
6722 | 6719 | ||
@@ -7032,7 +7029,7 @@ static u8 bnx2x_sfx7101_flash_download(struct bnx2x *bp, u8 port, | |||
7032 | for (cnt = 0; cnt < 100; cnt++) | 7029 | for (cnt = 0; cnt < 100; cnt++) |
7033 | msleep(5); | 7030 | msleep(5); |
7034 | 7031 | ||
7035 | bnx2x_hw_reset(bp, port); | 7032 | bnx2x_ext_phy_hw_reset(bp, port); |
7036 | 7033 | ||
7037 | for (cnt = 0; cnt < 100; cnt++) | 7034 | for (cnt = 0; cnt < 100; cnt++) |
7038 | msleep(5); | 7035 | msleep(5); |
diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h index d25ef45d793f..9805d210c028 100644 --- a/drivers/net/bnx2x_link.h +++ b/drivers/net/bnx2x_link.h | |||
@@ -187,6 +187,10 @@ u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars); | |||
187 | /* One-time initialization for external phy after power up */ | 187 | /* One-time initialization for external phy after power up */ |
188 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base); | 188 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base); |
189 | 189 | ||
190 | /* Reset the external PHY using GPIO */ | ||
191 | void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port); | ||
192 | |||
193 | void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr); | ||
190 | 194 | ||
191 | u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr, | 195 | u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr, |
192 | u8 byte_cnt, u8 *o_buf); | 196 | u8 byte_cnt, u8 *o_buf); |
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 145866764d46..7853977b8de2 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
@@ -9353,7 +9353,8 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
9353 | struct ethtool_eeprom *eeprom, u8 *eebuf) | 9353 | struct ethtool_eeprom *eeprom, u8 *eebuf) |
9354 | { | 9354 | { |
9355 | struct bnx2x *bp = netdev_priv(dev); | 9355 | struct bnx2x *bp = netdev_priv(dev); |
9356 | int rc; | 9356 | int port = BP_PORT(bp); |
9357 | int rc = 0; | ||
9357 | 9358 | ||
9358 | if (!netif_running(dev)) | 9359 | if (!netif_running(dev)) |
9359 | return -EAGAIN; | 9360 | return -EAGAIN; |
@@ -9365,27 +9366,62 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
9365 | 9366 | ||
9366 | /* parameters already validated in ethtool_set_eeprom */ | 9367 | /* parameters already validated in ethtool_set_eeprom */ |
9367 | 9368 | ||
9368 | /* If the magic number is PHY (0x00504859) upgrade the PHY FW */ | 9369 | /* PHY eeprom can be accessed only by the PMF */ |
9369 | if (eeprom->magic == 0x00504859) | 9370 | if ((eeprom->magic >= 0x50485900) && (eeprom->magic <= 0x504859FF) && |
9370 | if (bp->port.pmf) { | 9371 | !bp->port.pmf) |
9372 | return -EINVAL; | ||
9373 | |||
9374 | if (eeprom->magic == 0x50485950) { | ||
9375 | /* 'PHYP' (0x50485950): prepare phy for FW upgrade */ | ||
9376 | bnx2x_stats_handle(bp, STATS_EVENT_STOP); | ||
9371 | 9377 | ||
9378 | bnx2x_acquire_phy_lock(bp); | ||
9379 | rc |= bnx2x_link_reset(&bp->link_params, | ||
9380 | &bp->link_vars, 0); | ||
9381 | if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == | ||
9382 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) | ||
9383 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
9384 | MISC_REGISTERS_GPIO_HIGH, port); | ||
9385 | bnx2x_release_phy_lock(bp); | ||
9386 | bnx2x_link_report(bp); | ||
9387 | |||
9388 | } else if (eeprom->magic == 0x50485952) { | ||
9389 | /* 'PHYR' (0x50485952): re-init link after FW upgrade */ | ||
9390 | if ((bp->state == BNX2X_STATE_OPEN) || | ||
9391 | (bp->state == BNX2X_STATE_DISABLED)) { | ||
9372 | bnx2x_acquire_phy_lock(bp); | 9392 | bnx2x_acquire_phy_lock(bp); |
9373 | rc = bnx2x_flash_download(bp, BP_PORT(bp), | 9393 | rc |= bnx2x_link_reset(&bp->link_params, |
9374 | bp->link_params.ext_phy_config, | 9394 | &bp->link_vars, 1); |
9375 | (bp->state != BNX2X_STATE_CLOSED), | 9395 | |
9376 | eebuf, eeprom->len); | 9396 | rc |= bnx2x_phy_init(&bp->link_params, |
9377 | if ((bp->state == BNX2X_STATE_OPEN) || | 9397 | &bp->link_vars); |
9378 | (bp->state == BNX2X_STATE_DISABLED)) { | ||
9379 | rc |= bnx2x_link_reset(&bp->link_params, | ||
9380 | &bp->link_vars, 1); | ||
9381 | rc |= bnx2x_phy_init(&bp->link_params, | ||
9382 | &bp->link_vars); | ||
9383 | } | ||
9384 | bnx2x_release_phy_lock(bp); | 9398 | bnx2x_release_phy_lock(bp); |
9399 | bnx2x_calc_fc_adv(bp); | ||
9400 | } | ||
9401 | } else if (eeprom->magic == 0x53985943) { | ||
9402 | /* 'PHYC' (0x53985943): PHY FW upgrade completed */ | ||
9403 | if (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config) == | ||
9404 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101) { | ||
9405 | u8 ext_phy_addr = | ||
9406 | (bp->link_params.ext_phy_config & | ||
9407 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
9408 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT; | ||
9409 | |||
9410 | /* DSP Remove Download Mode */ | ||
9411 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
9412 | MISC_REGISTERS_GPIO_LOW, port); | ||
9385 | 9413 | ||
9386 | } else /* Only the PMF can access the PHY */ | 9414 | bnx2x_acquire_phy_lock(bp); |
9387 | return -EINVAL; | 9415 | |
9388 | else | 9416 | bnx2x_sfx7101_sp_sw_reset(bp, port, ext_phy_addr); |
9417 | |||
9418 | /* wait 0.5 sec to allow it to run */ | ||
9419 | msleep(500); | ||
9420 | bnx2x_ext_phy_hw_reset(bp, port); | ||
9421 | msleep(500); | ||
9422 | bnx2x_release_phy_lock(bp); | ||
9423 | } | ||
9424 | } else | ||
9389 | rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); | 9425 | rc = bnx2x_nvram_write(bp, eeprom->offset, eebuf, eeprom->len); |
9390 | 9426 | ||
9391 | return rc; | 9427 | return rc; |