diff options
author | Yaniv Rosner <yanivr@broadcom.com> | 2011-01-30 23:22:28 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-31 16:22:43 -0500 |
commit | a8db5b4cbde619246cd3db9a59dac5d0757aff36 (patch) | |
tree | a3db21157aebb2f81e7c1ed34a591bf5bd35b6b2 /drivers/net/bnx2x | |
parent | 6d870c391ec0e4da4fd75df7e6aca7252162c408 (diff) |
bnx2x: Enhance SFP+ module control
Add flexible support to control various SFP+ module features either throughout MDIO registers or GPIO pins according to NVRAM configuration
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')
-rw-r--r-- | drivers/net/bnx2x/bnx2x_hsi.h | 82 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_link.c | 251 | ||||
-rw-r--r-- | drivers/net/bnx2x/bnx2x_reg.h | 1 |
3 files changed, 289 insertions, 45 deletions
diff --git a/drivers/net/bnx2x/bnx2x_hsi.h b/drivers/net/bnx2x/bnx2x_hsi.h index 548f5631c0dc..34e313cf3e25 100644 --- a/drivers/net/bnx2x/bnx2x_hsi.h +++ b/drivers/net/bnx2x/bnx2x_hsi.h | |||
@@ -237,8 +237,26 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ | |||
237 | #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT 16 | 237 | #define PORT_HW_CFG_SERDES_RX_DRV_EQUALIZER_SHIFT 16 |
238 | 238 | ||
239 | 239 | ||
240 | u32 Reserved0[16]; /* 0x158 */ | 240 | u32 Reserved0[3]; /* 0x158 */ |
241 | 241 | /* Controls the TX laser of the SFP+ module */ | |
242 | u32 sfp_ctrl; /* 0x164 */ | ||
243 | #define PORT_HW_CFG_TX_LASER_MASK 0x000000FF | ||
244 | #define PORT_HW_CFG_TX_LASER_SHIFT 0 | ||
245 | #define PORT_HW_CFG_TX_LASER_MDIO 0x00000000 | ||
246 | #define PORT_HW_CFG_TX_LASER_GPIO0 0x00000001 | ||
247 | #define PORT_HW_CFG_TX_LASER_GPIO1 0x00000002 | ||
248 | #define PORT_HW_CFG_TX_LASER_GPIO2 0x00000003 | ||
249 | #define PORT_HW_CFG_TX_LASER_GPIO3 0x00000004 | ||
250 | |||
251 | /* Controls the fault module LED of the SFP+ */ | ||
252 | #define PORT_HW_CFG_FAULT_MODULE_LED_MASK 0x0000FF00 | ||
253 | #define PORT_HW_CFG_FAULT_MODULE_LED_SHIFT 8 | ||
254 | #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO0 0x00000000 | ||
255 | #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO1 0x00000100 | ||
256 | #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO2 0x00000200 | ||
257 | #define PORT_HW_CFG_FAULT_MODULE_LED_GPIO3 0x00000300 | ||
258 | #define PORT_HW_CFG_FAULT_MODULE_LED_DISABLED 0x00000400 | ||
259 | u32 Reserved01[12]; /* 0x158 */ | ||
242 | /* for external PHY, or forced mode or during AN */ | 260 | /* for external PHY, or forced mode or during AN */ |
243 | u16 xgxs_config_rx[4]; /* 0x198 */ | 261 | u16 xgxs_config_rx[4]; /* 0x198 */ |
244 | 262 | ||
@@ -246,6 +264,66 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ | |||
246 | 264 | ||
247 | u32 Reserved1[56]; /* 0x1A8 */ | 265 | u32 Reserved1[56]; /* 0x1A8 */ |
248 | u32 default_cfg; /* 0x288 */ | 266 | u32 default_cfg; /* 0x288 */ |
267 | #define PORT_HW_CFG_GPIO0_CONFIG_MASK 0x00000003 | ||
268 | #define PORT_HW_CFG_GPIO0_CONFIG_SHIFT 0 | ||
269 | #define PORT_HW_CFG_GPIO0_CONFIG_NA 0x00000000 | ||
270 | #define PORT_HW_CFG_GPIO0_CONFIG_LOW 0x00000001 | ||
271 | #define PORT_HW_CFG_GPIO0_CONFIG_HIGH 0x00000002 | ||
272 | #define PORT_HW_CFG_GPIO0_CONFIG_INPUT 0x00000003 | ||
273 | |||
274 | #define PORT_HW_CFG_GPIO1_CONFIG_MASK 0x0000000C | ||
275 | #define PORT_HW_CFG_GPIO1_CONFIG_SHIFT 2 | ||
276 | #define PORT_HW_CFG_GPIO1_CONFIG_NA 0x00000000 | ||
277 | #define PORT_HW_CFG_GPIO1_CONFIG_LOW 0x00000004 | ||
278 | #define PORT_HW_CFG_GPIO1_CONFIG_HIGH 0x00000008 | ||
279 | #define PORT_HW_CFG_GPIO1_CONFIG_INPUT 0x0000000c | ||
280 | |||
281 | #define PORT_HW_CFG_GPIO2_CONFIG_MASK 0x00000030 | ||
282 | #define PORT_HW_CFG_GPIO2_CONFIG_SHIFT 4 | ||
283 | #define PORT_HW_CFG_GPIO2_CONFIG_NA 0x00000000 | ||
284 | #define PORT_HW_CFG_GPIO2_CONFIG_LOW 0x00000010 | ||
285 | #define PORT_HW_CFG_GPIO2_CONFIG_HIGH 0x00000020 | ||
286 | #define PORT_HW_CFG_GPIO2_CONFIG_INPUT 0x00000030 | ||
287 | |||
288 | #define PORT_HW_CFG_GPIO3_CONFIG_MASK 0x000000C0 | ||
289 | #define PORT_HW_CFG_GPIO3_CONFIG_SHIFT 6 | ||
290 | #define PORT_HW_CFG_GPIO3_CONFIG_NA 0x00000000 | ||
291 | #define PORT_HW_CFG_GPIO3_CONFIG_LOW 0x00000040 | ||
292 | #define PORT_HW_CFG_GPIO3_CONFIG_HIGH 0x00000080 | ||
293 | #define PORT_HW_CFG_GPIO3_CONFIG_INPUT 0x000000c0 | ||
294 | |||
295 | /* | ||
296 | * When KR link is required to be set to force which is not | ||
297 | * KR-compliant, this parameter determine what is the trigger for it. | ||
298 | * When GPIO is selected, low input will force the speed. Currently | ||
299 | * default speed is 1G. In the future, it may be widen to select the | ||
300 | * forced speed in with another parameter. Note when force-1G is | ||
301 | * enabled, it override option 56: Link Speed option. | ||
302 | */ | ||
303 | #define PORT_HW_CFG_FORCE_KR_ENABLER_MASK 0x00000F00 | ||
304 | #define PORT_HW_CFG_FORCE_KR_ENABLER_SHIFT 8 | ||
305 | #define PORT_HW_CFG_FORCE_KR_ENABLER_NOT_FORCED 0x00000000 | ||
306 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P0 0x00000100 | ||
307 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P0 0x00000200 | ||
308 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P0 0x00000300 | ||
309 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P0 0x00000400 | ||
310 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO0_P1 0x00000500 | ||
311 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO1_P1 0x00000600 | ||
312 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO2_P1 0x00000700 | ||
313 | #define PORT_HW_CFG_FORCE_KR_ENABLER_GPIO3_P1 0x00000800 | ||
314 | #define PORT_HW_CFG_FORCE_KR_ENABLER_FORCED 0x00000900 | ||
315 | /* Enable to determine with which GPIO to reset the external phy */ | ||
316 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_MASK 0x000F0000 | ||
317 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_SHIFT 16 | ||
318 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_PHY_TYPE 0x00000000 | ||
319 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0 0x00010000 | ||
320 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0 0x00020000 | ||
321 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0 0x00030000 | ||
322 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0 0x00040000 | ||
323 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1 0x00050000 | ||
324 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1 0x00060000 | ||
325 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1 0x00070000 | ||
326 | #define PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1 0x00080000 | ||
249 | /* Enable BAM on KR */ | 327 | /* Enable BAM on KR */ |
250 | #define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000 | 328 | #define PORT_HW_CFG_ENABLE_BAM_ON_KR_MASK 0x00100000 |
251 | #define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20 | 329 | #define PORT_HW_CFG_ENABLE_BAM_ON_KR_SHIFT 20 |
diff --git a/drivers/net/bnx2x/bnx2x_link.c b/drivers/net/bnx2x/bnx2x_link.c index 187387e86d25..a089b62d3df6 100644 --- a/drivers/net/bnx2x/bnx2x_link.c +++ b/drivers/net/bnx2x/bnx2x_link.c | |||
@@ -4464,30 +4464,74 @@ static u8 bnx2x_8705_read_status(struct bnx2x_phy *phy, | |||
4464 | /******************************************************************/ | 4464 | /******************************************************************/ |
4465 | /* SFP+ module Section */ | 4465 | /* SFP+ module Section */ |
4466 | /******************************************************************/ | 4466 | /******************************************************************/ |
4467 | static void bnx2x_sfp_set_transmitter(struct bnx2x *bp, | 4467 | static u8 bnx2x_get_gpio_port(struct link_params *params) |
4468 | { | ||
4469 | u8 gpio_port; | ||
4470 | u32 swap_val, swap_override; | ||
4471 | struct bnx2x *bp = params->bp; | ||
4472 | if (CHIP_IS_E2(bp)) | ||
4473 | gpio_port = BP_PATH(bp); | ||
4474 | else | ||
4475 | gpio_port = params->port; | ||
4476 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); | ||
4477 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); | ||
4478 | return gpio_port ^ (swap_val && swap_override); | ||
4479 | } | ||
4480 | static void bnx2x_sfp_set_transmitter(struct link_params *params, | ||
4468 | struct bnx2x_phy *phy, | 4481 | struct bnx2x_phy *phy, |
4469 | u8 port, | ||
4470 | u8 tx_en) | 4482 | u8 tx_en) |
4471 | { | 4483 | { |
4472 | u16 val; | 4484 | u16 val; |
4485 | u8 port = params->port; | ||
4486 | struct bnx2x *bp = params->bp; | ||
4487 | u32 tx_en_mode; | ||
4473 | 4488 | ||
4474 | DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n", | ||
4475 | tx_en, port); | ||
4476 | /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/ | 4489 | /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/ |
4477 | bnx2x_cl45_read(bp, phy, | 4490 | tx_en_mode = REG_RD(bp, params->shmem_base + |
4478 | MDIO_PMA_DEVAD, | 4491 | offsetof(struct shmem_region, |
4479 | MDIO_PMA_REG_PHY_IDENTIFIER, | 4492 | dev_info.port_hw_config[port].sfp_ctrl)) & |
4480 | &val); | 4493 | PORT_HW_CFG_TX_LASER_MASK; |
4494 | DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x " | ||
4495 | "mode = %x\n", tx_en, port, tx_en_mode); | ||
4496 | switch (tx_en_mode) { | ||
4497 | case PORT_HW_CFG_TX_LASER_MDIO: | ||
4481 | 4498 | ||
4482 | if (tx_en) | 4499 | bnx2x_cl45_read(bp, phy, |
4483 | val &= ~(1<<15); | 4500 | MDIO_PMA_DEVAD, |
4484 | else | 4501 | MDIO_PMA_REG_PHY_IDENTIFIER, |
4485 | val |= (1<<15); | 4502 | &val); |
4486 | 4503 | ||
4487 | bnx2x_cl45_write(bp, phy, | 4504 | if (tx_en) |
4488 | MDIO_PMA_DEVAD, | 4505 | val &= ~(1<<15); |
4489 | MDIO_PMA_REG_PHY_IDENTIFIER, | 4506 | else |
4490 | val); | 4507 | val |= (1<<15); |
4508 | |||
4509 | bnx2x_cl45_write(bp, phy, | ||
4510 | MDIO_PMA_DEVAD, | ||
4511 | MDIO_PMA_REG_PHY_IDENTIFIER, | ||
4512 | val); | ||
4513 | break; | ||
4514 | case PORT_HW_CFG_TX_LASER_GPIO0: | ||
4515 | case PORT_HW_CFG_TX_LASER_GPIO1: | ||
4516 | case PORT_HW_CFG_TX_LASER_GPIO2: | ||
4517 | case PORT_HW_CFG_TX_LASER_GPIO3: | ||
4518 | { | ||
4519 | u16 gpio_pin; | ||
4520 | u8 gpio_port, gpio_mode; | ||
4521 | if (tx_en) | ||
4522 | gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_HIGH; | ||
4523 | else | ||
4524 | gpio_mode = MISC_REGISTERS_GPIO_OUTPUT_LOW; | ||
4525 | |||
4526 | gpio_pin = tx_en_mode - PORT_HW_CFG_TX_LASER_GPIO0; | ||
4527 | gpio_port = bnx2x_get_gpio_port(params); | ||
4528 | bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port); | ||
4529 | break; | ||
4530 | } | ||
4531 | default: | ||
4532 | DP(NETIF_MSG_LINK, "Invalid TX_LASER_MDIO 0x%x\n", tx_en_mode); | ||
4533 | break; | ||
4534 | } | ||
4491 | } | 4535 | } |
4492 | 4536 | ||
4493 | static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy, | 4537 | static u8 bnx2x_8726_read_sfp_module_eeprom(struct bnx2x_phy *phy, |
@@ -4966,11 +5010,11 @@ static void bnx2x_8727_specific_func(struct bnx2x_phy *phy, | |||
4966 | 5010 | ||
4967 | switch (action) { | 5011 | switch (action) { |
4968 | case DISABLE_TX: | 5012 | case DISABLE_TX: |
4969 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | 5013 | bnx2x_sfp_set_transmitter(params, phy, 0); |
4970 | break; | 5014 | break; |
4971 | case ENABLE_TX: | 5015 | case ENABLE_TX: |
4972 | if (!(phy->flags & FLAGS_SFP_NOT_APPROVED)) | 5016 | if (!(phy->flags & FLAGS_SFP_NOT_APPROVED)) |
4973 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 1); | 5017 | bnx2x_sfp_set_transmitter(params, phy, 1); |
4974 | break; | 5018 | break; |
4975 | default: | 5019 | default: |
4976 | DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n", | 5020 | DP(NETIF_MSG_LINK, "Function 0x%x not supported by 8727\n", |
@@ -4979,6 +5023,38 @@ static void bnx2x_8727_specific_func(struct bnx2x_phy *phy, | |||
4979 | } | 5023 | } |
4980 | } | 5024 | } |
4981 | 5025 | ||
5026 | static void bnx2x_set_sfp_module_fault_led(struct link_params *params, | ||
5027 | u8 gpio_mode) | ||
5028 | { | ||
5029 | struct bnx2x *bp = params->bp; | ||
5030 | |||
5031 | u32 fault_led_gpio = REG_RD(bp, params->shmem_base + | ||
5032 | offsetof(struct shmem_region, | ||
5033 | dev_info.port_hw_config[params->port].sfp_ctrl)) & | ||
5034 | PORT_HW_CFG_FAULT_MODULE_LED_MASK; | ||
5035 | switch (fault_led_gpio) { | ||
5036 | case PORT_HW_CFG_FAULT_MODULE_LED_DISABLED: | ||
5037 | return; | ||
5038 | case PORT_HW_CFG_FAULT_MODULE_LED_GPIO0: | ||
5039 | case PORT_HW_CFG_FAULT_MODULE_LED_GPIO1: | ||
5040 | case PORT_HW_CFG_FAULT_MODULE_LED_GPIO2: | ||
5041 | case PORT_HW_CFG_FAULT_MODULE_LED_GPIO3: | ||
5042 | { | ||
5043 | u8 gpio_port = bnx2x_get_gpio_port(params); | ||
5044 | u16 gpio_pin = fault_led_gpio - | ||
5045 | PORT_HW_CFG_FAULT_MODULE_LED_GPIO0; | ||
5046 | DP(NETIF_MSG_LINK, "Set fault module-detected led " | ||
5047 | "pin %x port %x mode %x\n", | ||
5048 | gpio_pin, gpio_port, gpio_mode); | ||
5049 | bnx2x_set_gpio(bp, gpio_pin, gpio_mode, gpio_port); | ||
5050 | } | ||
5051 | break; | ||
5052 | default: | ||
5053 | DP(NETIF_MSG_LINK, "Error: Invalid fault led mode 0x%x\n", | ||
5054 | fault_led_gpio); | ||
5055 | } | ||
5056 | } | ||
5057 | |||
4982 | static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, | 5058 | static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, |
4983 | struct link_params *params) | 5059 | struct link_params *params) |
4984 | { | 5060 | { |
@@ -5001,9 +5077,9 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, | |||
5001 | DP(NETIF_MSG_LINK, "Module verification failed!!\n"); | 5077 | DP(NETIF_MSG_LINK, "Module verification failed!!\n"); |
5002 | rc = -EINVAL; | 5078 | rc = -EINVAL; |
5003 | /* Turn on fault module-detected led */ | 5079 | /* Turn on fault module-detected led */ |
5004 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | 5080 | bnx2x_set_sfp_module_fault_led(params, |
5005 | MISC_REGISTERS_GPIO_HIGH, | 5081 | MISC_REGISTERS_GPIO_HIGH); |
5006 | params->port); | 5082 | |
5007 | if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) && | 5083 | if ((phy->type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8727) && |
5008 | ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == | 5084 | ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == |
5009 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) { | 5085 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_POWER_DOWN)) { |
@@ -5014,10 +5090,7 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, | |||
5014 | } | 5090 | } |
5015 | } else { | 5091 | } else { |
5016 | /* Turn off fault module-detected led */ | 5092 | /* Turn off fault module-detected led */ |
5017 | DP(NETIF_MSG_LINK, "Turn off fault module-detected led\n"); | 5093 | bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_LOW); |
5018 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
5019 | MISC_REGISTERS_GPIO_LOW, | ||
5020 | params->port); | ||
5021 | } | 5094 | } |
5022 | 5095 | ||
5023 | /* power up the SFP module */ | 5096 | /* power up the SFP module */ |
@@ -5039,9 +5112,9 @@ static u8 bnx2x_sfp_module_detection(struct bnx2x_phy *phy, | |||
5039 | if (rc == 0 || | 5112 | if (rc == 0 || |
5040 | (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) != | 5113 | (val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) != |
5041 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) | 5114 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) |
5042 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 1); | 5115 | bnx2x_sfp_set_transmitter(params, phy, 1); |
5043 | else | 5116 | else |
5044 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | 5117 | bnx2x_sfp_set_transmitter(params, phy, 0); |
5045 | 5118 | ||
5046 | return rc; | 5119 | return rc; |
5047 | } | 5120 | } |
@@ -5054,9 +5127,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params) | |||
5054 | u8 port = params->port; | 5127 | u8 port = params->port; |
5055 | 5128 | ||
5056 | /* Set valid module led off */ | 5129 | /* Set valid module led off */ |
5057 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | 5130 | bnx2x_set_sfp_module_fault_led(params, MISC_REGISTERS_GPIO_HIGH); |
5058 | MISC_REGISTERS_GPIO_HIGH, | ||
5059 | params->port); | ||
5060 | 5131 | ||
5061 | /* Get current gpio val reflecting module plugged in / out*/ | 5132 | /* Get current gpio val reflecting module plugged in / out*/ |
5062 | gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port); | 5133 | gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port); |
@@ -5087,7 +5158,7 @@ void bnx2x_handle_module_detect_int(struct link_params *params) | |||
5087 | */ | 5158 | */ |
5088 | if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == | 5159 | if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == |
5089 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) | 5160 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) |
5090 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | 5161 | bnx2x_sfp_set_transmitter(params, phy, 0); |
5091 | } | 5162 | } |
5092 | } | 5163 | } |
5093 | 5164 | ||
@@ -5146,7 +5217,8 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, | |||
5146 | struct link_params *params, | 5217 | struct link_params *params, |
5147 | struct link_vars *vars) | 5218 | struct link_vars *vars) |
5148 | { | 5219 | { |
5149 | u16 cnt, val; | 5220 | u32 tx_en_mode; |
5221 | u16 cnt, val, tmp1; | ||
5150 | struct bnx2x *bp = params->bp; | 5222 | struct bnx2x *bp = params->bp; |
5151 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | 5223 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, |
5152 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | 5224 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); |
@@ -5220,6 +5292,26 @@ static u8 bnx2x_8706_config_init(struct bnx2x_phy *phy, | |||
5220 | 0x0004); | 5292 | 0x0004); |
5221 | } | 5293 | } |
5222 | bnx2x_save_bcm_spirom_ver(bp, phy, params->port); | 5294 | bnx2x_save_bcm_spirom_ver(bp, phy, params->port); |
5295 | |||
5296 | /* | ||
5297 | * If TX Laser is controlled by GPIO_0, do not let PHY go into low | ||
5298 | * power mode, if TX Laser is disabled | ||
5299 | */ | ||
5300 | |||
5301 | tx_en_mode = REG_RD(bp, params->shmem_base + | ||
5302 | offsetof(struct shmem_region, | ||
5303 | dev_info.port_hw_config[params->port].sfp_ctrl)) | ||
5304 | & PORT_HW_CFG_TX_LASER_MASK; | ||
5305 | |||
5306 | if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) { | ||
5307 | DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n"); | ||
5308 | bnx2x_cl45_read(bp, phy, | ||
5309 | MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, &tmp1); | ||
5310 | tmp1 |= 0x1; | ||
5311 | bnx2x_cl45_write(bp, phy, | ||
5312 | MDIO_PMA_DEVAD, MDIO_PMA_REG_DIGITAL_CTRL, tmp1); | ||
5313 | } | ||
5314 | |||
5223 | return 0; | 5315 | return 0; |
5224 | } | 5316 | } |
5225 | 5317 | ||
@@ -5308,12 +5400,6 @@ static u8 bnx2x_8726_config_init(struct bnx2x_phy *phy, | |||
5308 | u32 val; | 5400 | u32 val; |
5309 | u32 swap_val, swap_override, aeu_gpio_mask, offset; | 5401 | u32 swap_val, swap_override, aeu_gpio_mask, offset; |
5310 | DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); | 5402 | DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); |
5311 | /* Restore normal power mode*/ | ||
5312 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
5313 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | ||
5314 | |||
5315 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
5316 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, params->port); | ||
5317 | 5403 | ||
5318 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); | 5404 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_CTRL, 1<<15); |
5319 | bnx2x_wait_reset_complete(bp, phy, params); | 5405 | bnx2x_wait_reset_complete(bp, phy, params); |
@@ -5500,7 +5586,8 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, | |||
5500 | struct link_params *params, | 5586 | struct link_params *params, |
5501 | struct link_vars *vars) | 5587 | struct link_vars *vars) |
5502 | { | 5588 | { |
5503 | u16 tmp1, val, mod_abs; | 5589 | u32 tx_en_mode; |
5590 | u16 tmp1, val, mod_abs, tmp2; | ||
5504 | u16 rx_alarm_ctrl_val; | 5591 | u16 rx_alarm_ctrl_val; |
5505 | u16 lasi_ctrl_val; | 5592 | u16 lasi_ctrl_val; |
5506 | struct bnx2x *bp = params->bp; | 5593 | struct bnx2x *bp = params->bp; |
@@ -5637,6 +5724,26 @@ static u8 bnx2x_8727_config_init(struct bnx2x_phy *phy, | |||
5637 | phy->tx_preemphasis[1]); | 5724 | phy->tx_preemphasis[1]); |
5638 | } | 5725 | } |
5639 | 5726 | ||
5727 | /* | ||
5728 | * If TX Laser is controlled by GPIO_0, do not let PHY go into low | ||
5729 | * power mode, if TX Laser is disabled | ||
5730 | */ | ||
5731 | tx_en_mode = REG_RD(bp, params->shmem_base + | ||
5732 | offsetof(struct shmem_region, | ||
5733 | dev_info.port_hw_config[params->port].sfp_ctrl)) | ||
5734 | & PORT_HW_CFG_TX_LASER_MASK; | ||
5735 | |||
5736 | if (tx_en_mode == PORT_HW_CFG_TX_LASER_GPIO0) { | ||
5737 | |||
5738 | DP(NETIF_MSG_LINK, "Enabling TXONOFF_PWRDN_DIS\n"); | ||
5739 | bnx2x_cl45_read(bp, phy, | ||
5740 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, &tmp2); | ||
5741 | tmp2 |= 0x1000; | ||
5742 | tmp2 &= 0xFFEF; | ||
5743 | bnx2x_cl45_write(bp, phy, | ||
5744 | MDIO_PMA_DEVAD, MDIO_PMA_REG_8727_OPT_CFG_REG, tmp2); | ||
5745 | } | ||
5746 | |||
5640 | return 0; | 5747 | return 0; |
5641 | } | 5748 | } |
5642 | 5749 | ||
@@ -5713,7 +5820,7 @@ static void bnx2x_8727_handle_mod_abs(struct bnx2x_phy *phy, | |||
5713 | 5820 | ||
5714 | if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == | 5821 | if ((val & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_MASK) == |
5715 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) | 5822 | PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLE_TX_LASER) |
5716 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | 5823 | bnx2x_sfp_set_transmitter(params, phy, 0); |
5717 | 5824 | ||
5718 | if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0) | 5825 | if (bnx2x_wait_for_sfp_module_initialized(phy, params) == 0) |
5719 | bnx2x_sfp_module_detection(phy, params); | 5826 | bnx2x_sfp_module_detection(phy, params); |
@@ -5873,7 +5980,7 @@ static void bnx2x_8727_link_reset(struct bnx2x_phy *phy, | |||
5873 | { | 5980 | { |
5874 | struct bnx2x *bp = params->bp; | 5981 | struct bnx2x *bp = params->bp; |
5875 | /* Disable Transmitter */ | 5982 | /* Disable Transmitter */ |
5876 | bnx2x_sfp_set_transmitter(bp, phy, params->port, 0); | 5983 | bnx2x_sfp_set_transmitter(params, phy, 0); |
5877 | /* Clear LASI */ | 5984 | /* Clear LASI */ |
5878 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0); | 5985 | bnx2x_cl45_write(bp, phy, MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_CTRL, 0); |
5879 | 5986 | ||
@@ -7889,12 +7996,57 @@ static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, | |||
7889 | 7996 | ||
7890 | return 0; | 7997 | return 0; |
7891 | } | 7998 | } |
7999 | static void bnx2x_get_ext_phy_reset_gpio(struct bnx2x *bp, u32 shmem_base, | ||
8000 | u8 *io_gpio, u8 *io_port) | ||
8001 | { | ||
8002 | |||
8003 | u32 phy_gpio_reset = REG_RD(bp, shmem_base + | ||
8004 | offsetof(struct shmem_region, | ||
8005 | dev_info.port_hw_config[PORT_0].default_cfg)); | ||
8006 | switch (phy_gpio_reset) { | ||
8007 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P0: | ||
8008 | *io_gpio = 0; | ||
8009 | *io_port = 0; | ||
8010 | break; | ||
8011 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P0: | ||
8012 | *io_gpio = 1; | ||
8013 | *io_port = 0; | ||
8014 | break; | ||
8015 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P0: | ||
8016 | *io_gpio = 2; | ||
8017 | *io_port = 0; | ||
8018 | break; | ||
8019 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P0: | ||
8020 | *io_gpio = 3; | ||
8021 | *io_port = 0; | ||
8022 | break; | ||
8023 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO0_P1: | ||
8024 | *io_gpio = 0; | ||
8025 | *io_port = 1; | ||
8026 | break; | ||
8027 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO1_P1: | ||
8028 | *io_gpio = 1; | ||
8029 | *io_port = 1; | ||
8030 | break; | ||
8031 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO2_P1: | ||
8032 | *io_gpio = 2; | ||
8033 | *io_port = 1; | ||
8034 | break; | ||
8035 | case PORT_HW_CFG_EXT_PHY_GPIO_RST_GPIO3_P1: | ||
8036 | *io_gpio = 3; | ||
8037 | *io_port = 1; | ||
8038 | break; | ||
8039 | default: | ||
8040 | /* Don't override the io_gpio and io_port */ | ||
8041 | break; | ||
8042 | } | ||
8043 | } | ||
7892 | static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, | 8044 | static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, |
7893 | u32 shmem_base_path[], | 8045 | u32 shmem_base_path[], |
7894 | u32 shmem2_base_path[], u8 phy_index, | 8046 | u32 shmem2_base_path[], u8 phy_index, |
7895 | u32 chip_id) | 8047 | u32 chip_id) |
7896 | { | 8048 | { |
7897 | s8 port; | 8049 | s8 port, reset_gpio; |
7898 | u32 swap_val, swap_override; | 8050 | u32 swap_val, swap_override; |
7899 | struct bnx2x_phy phy[PORT_MAX]; | 8051 | struct bnx2x_phy phy[PORT_MAX]; |
7900 | struct bnx2x_phy *phy_blk[PORT_MAX]; | 8052 | struct bnx2x_phy *phy_blk[PORT_MAX]; |
@@ -7902,13 +8054,26 @@ static u8 bnx2x_8727_common_init_phy(struct bnx2x *bp, | |||
7902 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); | 8054 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); |
7903 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); | 8055 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); |
7904 | 8056 | ||
8057 | reset_gpio = MISC_REGISTERS_GPIO_1; | ||
7905 | port = 1; | 8058 | port = 1; |
7906 | 8059 | ||
7907 | bnx2x_ext_phy_hw_reset(bp, port ^ (swap_val && swap_override)); | 8060 | /* |
8061 | * Retrieve the reset gpio/port which control the reset. | ||
8062 | * Default is GPIO1, PORT1 | ||
8063 | */ | ||
8064 | bnx2x_get_ext_phy_reset_gpio(bp, shmem_base_path[0], | ||
8065 | (u8 *)&reset_gpio, (u8 *)&port); | ||
7908 | 8066 | ||
7909 | /* Calculate the port based on port swap */ | 8067 | /* Calculate the port based on port swap */ |
7910 | port ^= (swap_val && swap_override); | 8068 | port ^= (swap_val && swap_override); |
7911 | 8069 | ||
8070 | /* Initiate PHY reset*/ | ||
8071 | bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
8072 | port); | ||
8073 | msleep(1); | ||
8074 | bnx2x_set_gpio(bp, reset_gpio, MISC_REGISTERS_GPIO_OUTPUT_HIGH, | ||
8075 | port); | ||
8076 | |||
7912 | msleep(5); | 8077 | msleep(5); |
7913 | 8078 | ||
7914 | /* PART1 - Reset both phys */ | 8079 | /* PART1 - Reset both phys */ |
diff --git a/drivers/net/bnx2x/bnx2x_reg.h b/drivers/net/bnx2x/bnx2x_reg.h index e01330bb36c7..1c89f19a4425 100644 --- a/drivers/net/bnx2x/bnx2x_reg.h +++ b/drivers/net/bnx2x/bnx2x_reg.h | |||
@@ -6083,6 +6083,7 @@ Theotherbitsarereservedandshouldbezero*/ | |||
6083 | #define MDIO_PMA_REG_8727_PCS_OPT_CTRL 0xc808 | 6083 | #define MDIO_PMA_REG_8727_PCS_OPT_CTRL 0xc808 |
6084 | #define MDIO_PMA_REG_8727_GPIO_CTRL 0xc80e | 6084 | #define MDIO_PMA_REG_8727_GPIO_CTRL 0xc80e |
6085 | #define MDIO_PMA_REG_8727_PCS_GP 0xc842 | 6085 | #define MDIO_PMA_REG_8727_PCS_GP 0xc842 |
6086 | #define MDIO_PMA_REG_8727_OPT_CFG_REG 0xc8e4 | ||
6086 | 6087 | ||
6087 | #define MDIO_AN_REG_8727_MISC_CTRL 0x8309 | 6088 | #define MDIO_AN_REG_8727_MISC_CTRL 0x8309 |
6088 | 6089 | ||