aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorEilon Greenstein <eilong@broadcom.com>2009-08-12 04:23:11 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-13 02:02:32 -0400
commitf57a60256d02daba1316c98da472f02cd98a58d3 (patch)
treec927a54bf16050d43418c11404afc1fd78370940 /drivers/net
parent01cd452846c98609dd3efbee0deea050e6706f02 (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.c21
-rw-r--r--drivers/net/bnx2x_link.h4
-rw-r--r--drivers/net/bnx2x_main.c72
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/*****************************************************************************/
1999static void bnx2x_hw_reset(struct bnx2x *bp, u8 port) 1999void 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 6716void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr)
6718
6719static 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 */
188u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base); 188u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base);
189 189
190/* Reset the external PHY using GPIO */
191void bnx2x_ext_phy_hw_reset(struct bnx2x *bp, u8 port);
192
193void bnx2x_sfx7101_sp_sw_reset(struct bnx2x *bp, u8 port, u8 phy_addr);
190 194
191u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr, 195u8 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;