diff options
author | Eilon Greenstein <eilong@broadcom.com> | 2009-02-12 03:36:55 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-02-16 02:31:24 -0500 |
commit | 589abe3a0f594a7707a15674ca9e80370c972832 (patch) | |
tree | a7930047ca7f5340b9053948fcba98128de4d588 | |
parent | 4acac6a53a3c9dfc604a9a8647f16b0242080e93 (diff) |
bnx2x: Supporting BCM8726 PHY
Also adding the ability to recognize the optic module and disable it if it is
not authorized for safety reasons - since this feature might upset some users
which are willing to take the risk, it is optional and can be disabled by
setting an nvram bit (or a trivial driver patch to set this bit).
This dual port PHY requires special handling if the ports are swapped.
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>
-rw-r--r-- | drivers/net/bnx2x_hsi.h | 13 | ||||
-rw-r--r-- | drivers/net/bnx2x_link.c | 776 | ||||
-rw-r--r-- | drivers/net/bnx2x_link.h | 14 | ||||
-rw-r--r-- | drivers/net/bnx2x_main.c | 90 | ||||
-rw-r--r-- | drivers/net/bnx2x_reg.h | 22 |
5 files changed, 851 insertions, 64 deletions
diff --git a/drivers/net/bnx2x_hsi.h b/drivers/net/bnx2x_hsi.h index 85e4df68b5d8..7b9acb3667ef 100644 --- a/drivers/net/bnx2x_hsi.h +++ b/drivers/net/bnx2x_hsi.h | |||
@@ -245,7 +245,7 @@ struct port_hw_cfg { /* port 0: 0x12c port 1: 0x2bc */ | |||
245 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073 0x00000300 | 245 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073 0x00000300 |
246 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705 0x00000400 | 246 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705 0x00000400 |
247 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 0x00000500 | 247 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706 0x00000500 |
248 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8276 0x00000600 | 248 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726 0x00000600 |
249 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700 | 249 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8481 0x00000700 |
250 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800 | 250 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101 0x00000800 |
251 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00 | 251 | #define PORT_HW_CFG_XGXS_EXT_PHY_TYPE_FAILURE 0x0000fd00 |
@@ -299,6 +299,12 @@ struct shared_feat_cfg { /* NVRAM Offset */ | |||
299 | 299 | ||
300 | u32 config; /* 0x450 */ | 300 | u32 config; /* 0x450 */ |
301 | #define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001 | 301 | #define SHARED_FEATURE_BMC_ECHO_MODE_EN 0x00000001 |
302 | |||
303 | /* Use the values from options 47 and 48 instead of the HW default | ||
304 | values */ | ||
305 | #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_DISABLED 0x00000000 | ||
306 | #define SHARED_FEAT_CFG_OVERRIDE_PREEMPHASIS_CFG_ENABLED 0x00000002 | ||
307 | |||
302 | #define SHARED_FEATURE_MF_MODE_DISABLED 0x00000100 | 308 | #define SHARED_FEATURE_MF_MODE_DISABLED 0x00000100 |
303 | 309 | ||
304 | }; | 310 | }; |
@@ -352,6 +358,11 @@ struct port_feat_cfg { /* port 0: 0x454 port 1: 0x4c8 */ | |||
352 | #define PORT_FEATURE_MBA_ENABLED 0x02000000 | 358 | #define PORT_FEATURE_MBA_ENABLED 0x02000000 |
353 | #define PORT_FEATURE_MFW_ENABLED 0x04000000 | 359 | #define PORT_FEATURE_MFW_ENABLED 0x04000000 |
354 | 360 | ||
361 | /* Check the optic vendor via i2c before allowing it to be used by | ||
362 | SW */ | ||
363 | #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_DISABLED 0x00000000 | ||
364 | #define PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_ENABLED 0x08000000 | ||
365 | |||
355 | u32 wol_config; | 366 | u32 wol_config; |
356 | /* Default is used when driver sets to "auto" mode */ | 367 | /* Default is used when driver sets to "auto" mode */ |
357 | #define PORT_FEATURE_WOL_DEFAULT_MASK 0x00000003 | 368 | #define PORT_FEATURE_WOL_DEFAULT_MASK 0x00000003 |
diff --git a/drivers/net/bnx2x_link.c b/drivers/net/bnx2x_link.c index aea26b4dc453..55f50c7093e0 100644 --- a/drivers/net/bnx2x_link.c +++ b/drivers/net/bnx2x_link.c | |||
@@ -139,6 +139,26 @@ | |||
139 | #define PHY_SGMII_FLAG 0x2 | 139 | #define PHY_SGMII_FLAG 0x2 |
140 | #define PHY_SERDES_FLAG 0x4 | 140 | #define PHY_SERDES_FLAG 0x4 |
141 | 141 | ||
142 | /* */ | ||
143 | #define SFP_EEPROM_CON_TYPE_ADDR 0x2 | ||
144 | #define SFP_EEPROM_CON_TYPE_VAL_LC 0x7 | ||
145 | #define SFP_EEPROM_CON_TYPE_VAL_COPPER 0x21 | ||
146 | |||
147 | #define SFP_EEPROM_FC_TX_TECH_ADDR 0x8 | ||
148 | #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE 0x4 | ||
149 | #define SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE 0x8 | ||
150 | #define SFP_EEPROM_VENDOR_NAME_ADDR 0x14 | ||
151 | #define SFP_EEPROM_VENDOR_NAME_SIZE 16 | ||
152 | #define SFP_EEPROM_OPTIONS_ADDR 0x40 | ||
153 | #define SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK 0x1 | ||
154 | #define SFP_EEPROM_OPTIONS_SIZE 2 | ||
155 | |||
156 | #define SFP_MODULE_TYPE_UNKNOWN 0x0 | ||
157 | #define SFP_MODULE_TYPE_LC 0x1 | ||
158 | #define SFP_MODULE_TYPE_ACTIVE_COPPER_CABLE 0x2 | ||
159 | #define SFP_MODULE_TYPE_PASSIVE_COPPER_CABLE 0x3 | ||
160 | |||
161 | #define SFP_LIMITING_MODE_VALUE 0x0044 | ||
142 | /**********************************************************/ | 162 | /**********************************************************/ |
143 | /* INTERFACE */ | 163 | /* INTERFACE */ |
144 | /**********************************************************/ | 164 | /**********************************************************/ |
@@ -749,12 +769,17 @@ static u8 bnx2x_pbf_update(struct link_params *params, u32 flow_ctrl, | |||
749 | return 0; | 769 | return 0; |
750 | } | 770 | } |
751 | 771 | ||
752 | static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port) | 772 | static u32 bnx2x_get_emac_base(struct bnx2x *bp, u32 ext_phy_type, u8 port) |
753 | { | 773 | { |
754 | u32 emac_base; | 774 | u32 emac_base; |
755 | switch (ext_phy_type) { | 775 | switch (ext_phy_type) { |
756 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | 776 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: |
757 | emac_base = GRCBASE_EMAC0; | 777 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: |
778 | /* All MDC/MDIO is directed through single EMAC */ | ||
779 | if (REG_RD(bp, NIG_REG_PORT_SWAP)) | ||
780 | emac_base = GRCBASE_EMAC0; | ||
781 | else | ||
782 | emac_base = GRCBASE_EMAC1; | ||
758 | break; | 783 | break; |
759 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | 784 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: |
760 | emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1; | 785 | emac_base = (port) ? GRCBASE_EMAC0 : GRCBASE_EMAC1; |
@@ -772,11 +797,12 @@ u8 bnx2x_cl45_write(struct bnx2x *bp, u8 port, u32 ext_phy_type, | |||
772 | { | 797 | { |
773 | u32 tmp, saved_mode; | 798 | u32 tmp, saved_mode; |
774 | u8 i, rc = 0; | 799 | u8 i, rc = 0; |
775 | u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port); | 800 | u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port); |
776 | 801 | ||
777 | /* set clause 45 mode, slow down the MDIO clock to 2.5MHz | 802 | /* set clause 45 mode, slow down the MDIO clock to 2.5MHz |
778 | * (a value of 49==0x31) and make sure that the AUTO poll is off | 803 | * (a value of 49==0x31) and make sure that the AUTO poll is off |
779 | */ | 804 | */ |
805 | |||
780 | saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); | 806 | saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); |
781 | tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL | | 807 | tmp = saved_mode & ~(EMAC_MDIO_MODE_AUTO_POLL | |
782 | EMAC_MDIO_MODE_CLOCK_CNT); | 808 | EMAC_MDIO_MODE_CLOCK_CNT); |
@@ -841,10 +867,11 @@ u8 bnx2x_cl45_read(struct bnx2x *bp, u8 port, u32 ext_phy_type, | |||
841 | u16 i; | 867 | u16 i; |
842 | u8 rc = 0; | 868 | u8 rc = 0; |
843 | 869 | ||
844 | u32 mdio_ctrl = bnx2x_get_emac_base(ext_phy_type, port); | 870 | u32 mdio_ctrl = bnx2x_get_emac_base(bp, ext_phy_type, port); |
845 | /* set clause 45 mode, slow down the MDIO clock to 2.5MHz | 871 | /* set clause 45 mode, slow down the MDIO clock to 2.5MHz |
846 | * (a value of 49==0x31) and make sure that the AUTO poll is off | 872 | * (a value of 49==0x31) and make sure that the AUTO poll is off |
847 | */ | 873 | */ |
874 | |||
848 | saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); | 875 | saved_mode = REG_RD(bp, mdio_ctrl + EMAC_REG_EMAC_MDIO_MODE); |
849 | val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL | | 876 | val = saved_mode & ((EMAC_MDIO_MODE_AUTO_POLL | |
850 | EMAC_MDIO_MODE_CLOCK_CNT)); | 877 | EMAC_MDIO_MODE_CLOCK_CNT)); |
@@ -1726,7 +1753,9 @@ static u8 bnx2x_link_settings_status(struct link_params *params, | |||
1726 | ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | 1753 | ((XGXS_EXT_PHY_TYPE(params->ext_phy_config) == |
1727 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) || | 1754 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) || |
1728 | (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | 1755 | (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == |
1729 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705))) { | 1756 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || |
1757 | (XGXS_EXT_PHY_TYPE(params->ext_phy_config) == | ||
1758 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726))) { | ||
1730 | vars->autoneg = AUTO_NEG_ENABLED; | 1759 | vars->autoneg = AUTO_NEG_ENABLED; |
1731 | 1760 | ||
1732 | if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) { | 1761 | if (gp_status & MDIO_AN_CL73_OR_37_COMPLETE) { |
@@ -1902,6 +1931,25 @@ static void bnx2x_ext_phy_reset(struct link_params *params, | |||
1902 | MDIO_PMA_DEVAD, | 1931 | MDIO_PMA_DEVAD, |
1903 | MDIO_PMA_REG_CTRL, 0xa040); | 1932 | MDIO_PMA_REG_CTRL, 0xa040); |
1904 | break; | 1933 | break; |
1934 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
1935 | |||
1936 | /* Restore normal power mode*/ | ||
1937 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
1938 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, | ||
1939 | params->port); | ||
1940 | |||
1941 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | ||
1942 | MISC_REGISTERS_GPIO_OUTPUT_HIGH, | ||
1943 | params->port); | ||
1944 | |||
1945 | bnx2x_cl45_write(bp, params->port, | ||
1946 | ext_phy_type, | ||
1947 | ext_phy_addr, | ||
1948 | MDIO_PMA_DEVAD, | ||
1949 | MDIO_PMA_REG_CTRL, | ||
1950 | 1<<15); | ||
1951 | |||
1952 | break; | ||
1905 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | 1953 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: |
1906 | /* Unset Low Power Mode and SW reset */ | 1954 | /* Unset Low Power Mode and SW reset */ |
1907 | /* Restore normal power mode*/ | 1955 | /* Restore normal power mode*/ |
@@ -2198,6 +2246,484 @@ static void bnx2x_bcm8073_external_rom_boot(struct bnx2x *bp, u8 port, | |||
2198 | 2246 | ||
2199 | } | 2247 | } |
2200 | 2248 | ||
2249 | static void bnx2x_bcm8726_external_rom_boot(struct link_params *params) | ||
2250 | { | ||
2251 | struct bnx2x *bp = params->bp; | ||
2252 | u8 port = params->port; | ||
2253 | u8 ext_phy_addr = ((params->ext_phy_config & | ||
2254 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
2255 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
2256 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); | ||
2257 | |||
2258 | /* Need to wait 100ms after reset */ | ||
2259 | msleep(100); | ||
2260 | |||
2261 | /* Set serial boot control for external load */ | ||
2262 | bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, | ||
2263 | MDIO_PMA_DEVAD, | ||
2264 | MDIO_PMA_REG_MISC_CTRL1, 0x0001); | ||
2265 | |||
2266 | /* Micro controller re-boot */ | ||
2267 | bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, | ||
2268 | MDIO_PMA_DEVAD, | ||
2269 | MDIO_PMA_REG_GEN_CTRL, | ||
2270 | MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); | ||
2271 | |||
2272 | /* Set soft reset */ | ||
2273 | bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, | ||
2274 | MDIO_PMA_DEVAD, | ||
2275 | MDIO_PMA_REG_GEN_CTRL, | ||
2276 | MDIO_PMA_REG_GEN_CTRL_ROM_MICRO_RESET); | ||
2277 | |||
2278 | /* Clear soft reset. | ||
2279 | Will automatically reset micro-controller re-boot */ | ||
2280 | bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, | ||
2281 | MDIO_PMA_DEVAD, | ||
2282 | MDIO_PMA_REG_GEN_CTRL, | ||
2283 | MDIO_PMA_REG_GEN_CTRL_ROM_RESET_INTERNAL_MP); | ||
2284 | |||
2285 | /* wait for 100ms for microcode load */ | ||
2286 | msleep(100); | ||
2287 | |||
2288 | /* Disable serial boot control, tristates pins SS_N, SCK, MOSI, MISO */ | ||
2289 | bnx2x_cl45_write(bp, port, ext_phy_type, ext_phy_addr, | ||
2290 | MDIO_PMA_DEVAD, | ||
2291 | MDIO_PMA_REG_MISC_CTRL1, 0x0000); | ||
2292 | |||
2293 | msleep(200); | ||
2294 | } | ||
2295 | |||
2296 | static void bnx2x_bcm8726_set_transmitter(struct bnx2x *bp, u8 port, | ||
2297 | u8 ext_phy_addr, u8 tx_en) | ||
2298 | { | ||
2299 | u16 val; | ||
2300 | DP(NETIF_MSG_LINK, "Setting transmitter tx_en=%x for port %x\n", | ||
2301 | tx_en, port); | ||
2302 | /* Disable/Enable transmitter ( TX laser of the SFP+ module.)*/ | ||
2303 | bnx2x_cl45_read(bp, port, | ||
2304 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2305 | ext_phy_addr, | ||
2306 | MDIO_PMA_DEVAD, | ||
2307 | MDIO_PMA_REG_PHY_IDENTIFIER, | ||
2308 | &val); | ||
2309 | |||
2310 | if (tx_en) | ||
2311 | val &= ~(1<<15); | ||
2312 | else | ||
2313 | val |= (1<<15); | ||
2314 | |||
2315 | bnx2x_cl45_write(bp, port, | ||
2316 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2317 | ext_phy_addr, | ||
2318 | MDIO_PMA_DEVAD, | ||
2319 | MDIO_PMA_REG_PHY_IDENTIFIER, | ||
2320 | val); | ||
2321 | } | ||
2322 | |||
2323 | |||
2324 | static u8 bnx2x_read_sfp_module_eeprom(struct link_params *params, u16 addr, | ||
2325 | u8 byte_cnt, u8 *o_buf) { | ||
2326 | struct bnx2x *bp = params->bp; | ||
2327 | u16 val, i; | ||
2328 | u8 port = params->port; | ||
2329 | u8 ext_phy_addr = ((params->ext_phy_config & | ||
2330 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
2331 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
2332 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); | ||
2333 | if (byte_cnt > 16) { | ||
2334 | DP(NETIF_MSG_LINK, "Reading from eeprom is" | ||
2335 | " is limited to 0xf\n"); | ||
2336 | return -EINVAL; | ||
2337 | } | ||
2338 | /* Set the read command byte count */ | ||
2339 | bnx2x_cl45_write(bp, port, | ||
2340 | ext_phy_type, | ||
2341 | ext_phy_addr, | ||
2342 | MDIO_PMA_DEVAD, | ||
2343 | MDIO_PMA_REG_8726_TWO_WIRE_BYTE_CNT, | ||
2344 | (byte_cnt | 0xa000)); | ||
2345 | |||
2346 | /* Set the read command address */ | ||
2347 | bnx2x_cl45_write(bp, port, | ||
2348 | ext_phy_type, | ||
2349 | ext_phy_addr, | ||
2350 | MDIO_PMA_DEVAD, | ||
2351 | MDIO_PMA_REG_8726_TWO_WIRE_MEM_ADDR, | ||
2352 | addr); | ||
2353 | |||
2354 | /* Activate read command */ | ||
2355 | bnx2x_cl45_write(bp, port, | ||
2356 | ext_phy_type, | ||
2357 | ext_phy_addr, | ||
2358 | MDIO_PMA_DEVAD, | ||
2359 | MDIO_PMA_REG_8726_TWO_WIRE_CTRL, | ||
2360 | 0x2c0f); | ||
2361 | |||
2362 | /* Wait up to 500us for command complete status */ | ||
2363 | for (i = 0; i < 100; i++) { | ||
2364 | bnx2x_cl45_read(bp, port, | ||
2365 | ext_phy_type, | ||
2366 | ext_phy_addr, | ||
2367 | MDIO_PMA_DEVAD, | ||
2368 | MDIO_PMA_REG_8726_TWO_WIRE_CTRL, &val); | ||
2369 | if ((val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK) == | ||
2370 | MDIO_PMA_REG_8726_TWO_WIRE_STATUS_COMPLETE) | ||
2371 | break; | ||
2372 | udelay(5); | ||
2373 | } | ||
2374 | |||
2375 | if ((val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK) != | ||
2376 | MDIO_PMA_REG_8726_TWO_WIRE_STATUS_COMPLETE) { | ||
2377 | DP(NETIF_MSG_LINK, | ||
2378 | "Got bad status 0x%x when reading from SFP+ EEPROM\n", | ||
2379 | (val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK)); | ||
2380 | return -EINVAL; | ||
2381 | } | ||
2382 | |||
2383 | /* Read the buffer */ | ||
2384 | for (i = 0; i < byte_cnt; i++) { | ||
2385 | bnx2x_cl45_read(bp, port, | ||
2386 | ext_phy_type, | ||
2387 | ext_phy_addr, | ||
2388 | MDIO_PMA_DEVAD, | ||
2389 | MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF + i, &val); | ||
2390 | o_buf[i] = (u8)(val & MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK); | ||
2391 | } | ||
2392 | |||
2393 | for (i = 0; i < 100; i++) { | ||
2394 | bnx2x_cl45_read(bp, port, | ||
2395 | ext_phy_type, | ||
2396 | ext_phy_addr, | ||
2397 | MDIO_PMA_DEVAD, | ||
2398 | MDIO_PMA_REG_8726_TWO_WIRE_CTRL, &val); | ||
2399 | if ((val & MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK) == | ||
2400 | MDIO_PMA_REG_8726_TWO_WIRE_STATUS_IDLE) | ||
2401 | return 0;; | ||
2402 | msleep(1); | ||
2403 | } | ||
2404 | return -EINVAL; | ||
2405 | } | ||
2406 | |||
2407 | |||
2408 | static u8 bnx2x_get_sfp_module_type(struct link_params *params, | ||
2409 | u8 *module_type) | ||
2410 | { | ||
2411 | struct bnx2x *bp = params->bp; | ||
2412 | u8 val; | ||
2413 | *module_type = SFP_MODULE_TYPE_UNKNOWN; | ||
2414 | |||
2415 | /* First check for copper cable */ | ||
2416 | if (bnx2x_read_sfp_module_eeprom(params, | ||
2417 | SFP_EEPROM_CON_TYPE_ADDR, | ||
2418 | 1, | ||
2419 | &val) != 0) { | ||
2420 | DP(NETIF_MSG_LINK, "Failed to read from SFP+ module EEPROM"); | ||
2421 | return -EINVAL; | ||
2422 | } | ||
2423 | |||
2424 | switch (val) { | ||
2425 | case SFP_EEPROM_CON_TYPE_VAL_COPPER: | ||
2426 | { | ||
2427 | u8 copper_module_type; | ||
2428 | /* Check if its active cable( includes SFP+ module) | ||
2429 | of passive cable*/ | ||
2430 | if (bnx2x_read_sfp_module_eeprom(params, | ||
2431 | SFP_EEPROM_FC_TX_TECH_ADDR, | ||
2432 | 1, | ||
2433 | &copper_module_type) != | ||
2434 | 0) { | ||
2435 | DP(NETIF_MSG_LINK, | ||
2436 | "Failed to read copper-cable-type" | ||
2437 | " from SFP+ EEPROM\n"); | ||
2438 | return -EINVAL; | ||
2439 | } | ||
2440 | |||
2441 | if (copper_module_type & | ||
2442 | SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_ACTIVE) { | ||
2443 | DP(NETIF_MSG_LINK, "Active Copper cable detected\n"); | ||
2444 | *module_type = SFP_MODULE_TYPE_ACTIVE_COPPER_CABLE; | ||
2445 | } else if (copper_module_type & | ||
2446 | SFP_EEPROM_FC_TX_TECH_BITMASK_COPPER_PASSIVE) { | ||
2447 | DP(NETIF_MSG_LINK, "Passive Copper" | ||
2448 | " cable detected\n"); | ||
2449 | *module_type = | ||
2450 | SFP_MODULE_TYPE_PASSIVE_COPPER_CABLE; | ||
2451 | } else { | ||
2452 | DP(NETIF_MSG_LINK, "Unknown copper-cable-" | ||
2453 | "type 0x%x !!!\n", copper_module_type); | ||
2454 | return -EINVAL; | ||
2455 | } | ||
2456 | break; | ||
2457 | } | ||
2458 | case SFP_EEPROM_CON_TYPE_VAL_LC: | ||
2459 | DP(NETIF_MSG_LINK, "Optic module detected\n"); | ||
2460 | *module_type = SFP_MODULE_TYPE_LC; | ||
2461 | break; | ||
2462 | |||
2463 | default: | ||
2464 | DP(NETIF_MSG_LINK, "Unable to determine module type 0x%x !!!\n", | ||
2465 | val); | ||
2466 | return -EINVAL; | ||
2467 | } | ||
2468 | return 0; | ||
2469 | } | ||
2470 | |||
2471 | |||
2472 | /* This function read the relevant field from the module ( SFP+ ), | ||
2473 | and verify it is compliant with this board */ | ||
2474 | static u8 bnx2x_verify_sfp_module(struct link_params *params, | ||
2475 | u8 module_type) | ||
2476 | { | ||
2477 | struct bnx2x *bp = params->bp; | ||
2478 | u8 *str_p, *tmp_buf; | ||
2479 | u16 i; | ||
2480 | |||
2481 | #define COMPLIANCE_STR_CNT 6 | ||
2482 | u8 *compliance_str[] = {"Broadcom", "JDSU", "Molex Inc", "PICOLIGHT", | ||
2483 | "FINISAR CORP. ", "Amphenol"}; | ||
2484 | u8 buf[SFP_EEPROM_VENDOR_NAME_SIZE]; | ||
2485 | /* Passive Copper cables are allowed to participate, | ||
2486 | since the module is hardwired to the copper cable */ | ||
2487 | |||
2488 | if (!(params->feature_config_flags & | ||
2489 | FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED)) { | ||
2490 | DP(NETIF_MSG_LINK, "NOT enforcing module verification\n"); | ||
2491 | return 0; | ||
2492 | } | ||
2493 | |||
2494 | if (module_type != SFP_MODULE_TYPE_LC) { | ||
2495 | DP(NETIF_MSG_LINK, "No need to verify copper cable\n"); | ||
2496 | return 0; | ||
2497 | } | ||
2498 | |||
2499 | /* In case of non copper cable or Active copper cable, | ||
2500 | verify that the SFP+ module is compliant with this board*/ | ||
2501 | if (bnx2x_read_sfp_module_eeprom(params, | ||
2502 | SFP_EEPROM_VENDOR_NAME_ADDR, | ||
2503 | SFP_EEPROM_VENDOR_NAME_SIZE, | ||
2504 | buf) != 0) { | ||
2505 | DP(NETIF_MSG_LINK, "Failed to read Vendor-Name from" | ||
2506 | " module EEPROM\n"); | ||
2507 | return -EINVAL; | ||
2508 | } | ||
2509 | for (i = 0; i < COMPLIANCE_STR_CNT; i++) { | ||
2510 | str_p = compliance_str[i]; | ||
2511 | tmp_buf = buf; | ||
2512 | while (*str_p) { | ||
2513 | if ((u8)(*tmp_buf) != (u8)(*str_p)) | ||
2514 | break; | ||
2515 | str_p++; | ||
2516 | tmp_buf++; | ||
2517 | } | ||
2518 | |||
2519 | if (!(*str_p)) { | ||
2520 | DP(NETIF_MSG_LINK, "SFP+ Module verified, " | ||
2521 | "index=%x\n", i); | ||
2522 | return 0; | ||
2523 | } | ||
2524 | } | ||
2525 | DP(NETIF_MSG_LINK, "Incompliant SFP+ module. Disable module !!!\n"); | ||
2526 | return -EINVAL; | ||
2527 | } | ||
2528 | |||
2529 | |||
2530 | static u8 bnx2x_bcm8726_set_limiting_mode(struct link_params *params, | ||
2531 | u8 module_type) | ||
2532 | { | ||
2533 | struct bnx2x *bp = params->bp; | ||
2534 | u8 port = params->port; | ||
2535 | u8 options[SFP_EEPROM_OPTIONS_SIZE]; | ||
2536 | u8 limiting_mode; | ||
2537 | u8 ext_phy_addr = ((params->ext_phy_config & | ||
2538 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
2539 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
2540 | |||
2541 | if (bnx2x_read_sfp_module_eeprom(params, | ||
2542 | SFP_EEPROM_OPTIONS_ADDR, | ||
2543 | SFP_EEPROM_OPTIONS_SIZE, | ||
2544 | options) != 0) { | ||
2545 | DP(NETIF_MSG_LINK, "Failed to read Option field from" | ||
2546 | " module EEPROM\n"); | ||
2547 | return -EINVAL; | ||
2548 | } | ||
2549 | limiting_mode = !(options[0] & | ||
2550 | SFP_EEPROM_OPTIONS_LINEAR_RX_OUT_MASK); | ||
2551 | if (limiting_mode && | ||
2552 | (module_type != SFP_MODULE_TYPE_PASSIVE_COPPER_CABLE)) { | ||
2553 | DP(NETIF_MSG_LINK, | ||
2554 | "Module options = 0x%x.Setting LIMITING MODE\n", | ||
2555 | options[0]); | ||
2556 | bnx2x_cl45_write(bp, port, | ||
2557 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2558 | ext_phy_addr, | ||
2559 | MDIO_PMA_DEVAD, | ||
2560 | MDIO_PMA_REG_ROM_VER2, | ||
2561 | SFP_LIMITING_MODE_VALUE); | ||
2562 | } else { /* LRM mode ( default )*/ | ||
2563 | u16 cur_limiting_mode; | ||
2564 | DP(NETIF_MSG_LINK, "Module options = 0x%x.Setting LRM MODE\n", | ||
2565 | options[0]); | ||
2566 | |||
2567 | bnx2x_cl45_read(bp, port, | ||
2568 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2569 | ext_phy_addr, | ||
2570 | MDIO_PMA_DEVAD, | ||
2571 | MDIO_PMA_REG_ROM_VER2, | ||
2572 | &cur_limiting_mode); | ||
2573 | |||
2574 | /* Changing to LRM mode takes quite few seconds. | ||
2575 | So do it only if current mode is limiting | ||
2576 | ( default is LRM )*/ | ||
2577 | if (cur_limiting_mode != SFP_LIMITING_MODE_VALUE) | ||
2578 | return 0; | ||
2579 | |||
2580 | bnx2x_cl45_write(bp, port, | ||
2581 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2582 | ext_phy_addr, | ||
2583 | MDIO_PMA_DEVAD, | ||
2584 | MDIO_PMA_REG_LRM_MODE, | ||
2585 | 0); | ||
2586 | bnx2x_cl45_write(bp, port, | ||
2587 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2588 | ext_phy_addr, | ||
2589 | MDIO_PMA_DEVAD, | ||
2590 | MDIO_PMA_REG_ROM_VER2, | ||
2591 | 0x128); | ||
2592 | bnx2x_cl45_write(bp, port, | ||
2593 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2594 | ext_phy_addr, | ||
2595 | MDIO_PMA_DEVAD, | ||
2596 | MDIO_PMA_REG_MISC_CTRL0, | ||
2597 | 0x4008); | ||
2598 | bnx2x_cl45_write(bp, port, | ||
2599 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, | ||
2600 | ext_phy_addr, | ||
2601 | MDIO_PMA_DEVAD, | ||
2602 | MDIO_PMA_REG_LRM_MODE, | ||
2603 | 0xaaaa); | ||
2604 | } | ||
2605 | return 0; | ||
2606 | } | ||
2607 | |||
2608 | static u8 bnx2x_wait_for_sfp_module_initialized(struct link_params *params) | ||
2609 | { | ||
2610 | u8 val; | ||
2611 | struct bnx2x *bp = params->bp; | ||
2612 | u16 timeout; | ||
2613 | /* Initialization time after hot-plug may take up to 300ms for some | ||
2614 | phys type ( e.g. JDSU ) */ | ||
2615 | for (timeout = 0; timeout < 60; timeout++) { | ||
2616 | if (bnx2x_read_sfp_module_eeprom(params, 1, 1, &val) | ||
2617 | == 0) { | ||
2618 | DP(NETIF_MSG_LINK, "SFP+ module initialization " | ||
2619 | "took %d ms\n", timeout * 5); | ||
2620 | return 0; | ||
2621 | } | ||
2622 | msleep(5); | ||
2623 | } | ||
2624 | return -EINVAL; | ||
2625 | } | ||
2626 | |||
2627 | static u8 bnx2x_sfp_module_detection(struct link_params *params) | ||
2628 | { | ||
2629 | struct bnx2x *bp = params->bp; | ||
2630 | u8 module_type; | ||
2631 | u8 ext_phy_addr = ((params->ext_phy_config & | ||
2632 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
2633 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
2634 | u32 ext_phy_type = XGXS_EXT_PHY_TYPE(params->ext_phy_config); | ||
2635 | |||
2636 | if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) { | ||
2637 | DP(NETIF_MSG_LINK, "Module detection is not required " | ||
2638 | "for this phy\n"); | ||
2639 | return 0; | ||
2640 | } | ||
2641 | |||
2642 | DP(NETIF_MSG_LINK, "SFP+ module plugged in/out detected on port %d\n", | ||
2643 | params->port); | ||
2644 | |||
2645 | if (bnx2x_get_sfp_module_type(params, | ||
2646 | &module_type) != 0) { | ||
2647 | DP(NETIF_MSG_LINK, "Failed to get valid module type\n"); | ||
2648 | if (!(params->feature_config_flags & | ||
2649 | FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED)) { | ||
2650 | /* In case module detection is disabled, it trys to | ||
2651 | link up. The issue that can happen here is LRM / | ||
2652 | LIMITING mode which set according to the module-type*/ | ||
2653 | DP(NETIF_MSG_LINK, "Unable to read module-type." | ||
2654 | "Probably due to Bit Stretching." | ||
2655 | " Proceeding...\n"); | ||
2656 | } else { | ||
2657 | return -EINVAL; | ||
2658 | } | ||
2659 | } else if (bnx2x_verify_sfp_module(params, module_type) != | ||
2660 | 0) { | ||
2661 | /* check SFP+ module compatibility */ | ||
2662 | DP(NETIF_MSG_LINK, "Module verification failed!!\n"); | ||
2663 | /* Turn on fault module-detected led */ | ||
2664 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
2665 | MISC_REGISTERS_GPIO_HIGH, | ||
2666 | params->port); | ||
2667 | return -EINVAL; | ||
2668 | } | ||
2669 | |||
2670 | /* Turn off fault module-detected led */ | ||
2671 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
2672 | MISC_REGISTERS_GPIO_LOW, | ||
2673 | params->port); | ||
2674 | |||
2675 | /* Check and set limiting mode / LRM mode */ | ||
2676 | if (bnx2x_bcm8726_set_limiting_mode(params, module_type) | ||
2677 | != 0) { | ||
2678 | DP(NETIF_MSG_LINK, "Setting limiting mode failed!!\n"); | ||
2679 | return -EINVAL; | ||
2680 | } | ||
2681 | |||
2682 | /* Enable transmit for this module */ | ||
2683 | bnx2x_bcm8726_set_transmitter(bp, params->port, | ||
2684 | ext_phy_addr, 1); | ||
2685 | return 0; | ||
2686 | } | ||
2687 | |||
2688 | void bnx2x_handle_module_detect_int(struct link_params *params) | ||
2689 | { | ||
2690 | struct bnx2x *bp = params->bp; | ||
2691 | u32 gpio_val; | ||
2692 | u8 port = params->port; | ||
2693 | /* Set valid module led off */ | ||
2694 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
2695 | MISC_REGISTERS_GPIO_HIGH, | ||
2696 | params->port); | ||
2697 | |||
2698 | /* Get current gpio val refelecting module plugged in / out*/ | ||
2699 | gpio_val = bnx2x_get_gpio(bp, MISC_REGISTERS_GPIO_3, port); | ||
2700 | |||
2701 | /* Call the handling function in case module is detected */ | ||
2702 | if (gpio_val == 0) { | ||
2703 | |||
2704 | bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3, | ||
2705 | MISC_REGISTERS_GPIO_INT_OUTPUT_CLR, | ||
2706 | port); | ||
2707 | |||
2708 | if (bnx2x_wait_for_sfp_module_initialized(params) | ||
2709 | == 0) | ||
2710 | bnx2x_sfp_module_detection(params); | ||
2711 | else | ||
2712 | DP(NETIF_MSG_LINK, "SFP+ module is not initialized\n"); | ||
2713 | } else { | ||
2714 | u8 ext_phy_addr = ((params->ext_phy_config & | ||
2715 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
2716 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
2717 | bnx2x_set_gpio_int(bp, MISC_REGISTERS_GPIO_3, | ||
2718 | MISC_REGISTERS_GPIO_INT_OUTPUT_SET, | ||
2719 | port); | ||
2720 | /* Module was plugged out. */ | ||
2721 | /* Disable transmit for this module */ | ||
2722 | bnx2x_bcm8726_set_transmitter(bp, params->port, | ||
2723 | ext_phy_addr, 0); | ||
2724 | } | ||
2725 | } | ||
2726 | |||
2201 | static void bnx2x_bcm807x_force_10G(struct link_params *params) | 2727 | static void bnx2x_bcm807x_force_10G(struct link_params *params) |
2202 | { | 2728 | { |
2203 | struct bnx2x *bp = params->bp; | 2729 | struct bnx2x *bp = params->bp; |
@@ -2580,7 +3106,68 @@ static u8 bnx2x_ext_phy_init(struct link_params *params, struct link_vars *vars) | |||
2580 | } | 3106 | } |
2581 | 3107 | ||
2582 | break; | 3108 | break; |
3109 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
3110 | DP(NETIF_MSG_LINK, "Initializing BCM8726\n"); | ||
3111 | bnx2x_bcm8726_external_rom_boot(params); | ||
3112 | |||
3113 | /* Need to call module detected on initialization since | ||
3114 | the module detection triggered by actual module | ||
3115 | insertion might occur before driver is loaded, and when | ||
3116 | driver is loaded, it reset all registers, including the | ||
3117 | transmitter */ | ||
3118 | bnx2x_sfp_module_detection(params); | ||
3119 | if (params->req_line_speed == SPEED_1000) { | ||
3120 | DP(NETIF_MSG_LINK, "Setting 1G force\n"); | ||
3121 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3122 | ext_phy_addr, MDIO_PMA_DEVAD, | ||
3123 | MDIO_PMA_REG_CTRL, 0x40); | ||
3124 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3125 | ext_phy_addr, MDIO_PMA_DEVAD, | ||
3126 | MDIO_PMA_REG_10G_CTRL2, 0xD); | ||
3127 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3128 | ext_phy_addr, MDIO_PMA_DEVAD, | ||
3129 | MDIO_PMA_REG_LASI_CTRL, 0x5); | ||
3130 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3131 | ext_phy_addr, MDIO_PMA_DEVAD, | ||
3132 | MDIO_PMA_REG_RX_ALARM_CTRL, | ||
3133 | 0x400); | ||
3134 | } else if ((params->req_line_speed == | ||
3135 | SPEED_AUTO_NEG) && | ||
3136 | ((params->speed_cap_mask & | ||
3137 | PORT_HW_CFG_SPEED_CAPABILITY_D0_1G))) { | ||
3138 | DP(NETIF_MSG_LINK, "Setting 1G clause37 \n"); | ||
3139 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3140 | ext_phy_addr, MDIO_AN_DEVAD, | ||
3141 | MDIO_AN_REG_ADV, 0x20); | ||
3142 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3143 | ext_phy_addr, MDIO_AN_DEVAD, | ||
3144 | MDIO_AN_REG_CL37_CL73, 0x040c); | ||
3145 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3146 | ext_phy_addr, MDIO_AN_DEVAD, | ||
3147 | MDIO_AN_REG_CL37_FC_LD, 0x0020); | ||
3148 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3149 | ext_phy_addr, MDIO_AN_DEVAD, | ||
3150 | MDIO_AN_REG_CL37_AN, 0x1000); | ||
3151 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3152 | ext_phy_addr, MDIO_AN_DEVAD, | ||
3153 | MDIO_AN_REG_CTRL, 0x1200); | ||
3154 | |||
3155 | /* Enable RX-ALARM control to receive | ||
3156 | interrupt for 1G speed change */ | ||
3157 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3158 | ext_phy_addr, MDIO_PMA_DEVAD, | ||
3159 | MDIO_PMA_REG_LASI_CTRL, 0x4); | ||
3160 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3161 | ext_phy_addr, MDIO_PMA_DEVAD, | ||
3162 | MDIO_PMA_REG_RX_ALARM_CTRL, | ||
3163 | 0x400); | ||
2583 | 3164 | ||
3165 | } else { /* Default 10G. Set only LASI control */ | ||
3166 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
3167 | ext_phy_addr, MDIO_PMA_DEVAD, | ||
3168 | MDIO_PMA_REG_LASI_CTRL, 1); | ||
3169 | } | ||
3170 | break; | ||
2584 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | 3171 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: |
2585 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | 3172 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: |
2586 | { | 3173 | { |
@@ -2910,38 +3497,43 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, | |||
2910 | break; | 3497 | break; |
2911 | 3498 | ||
2912 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 3499 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
2913 | DP(NETIF_MSG_LINK, "XGXS 8706\n"); | 3500 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: |
3501 | DP(NETIF_MSG_LINK, "XGXS 8706/8726\n"); | ||
3502 | /* Clear RX Alarm*/ | ||
2914 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 3503 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
2915 | ext_phy_addr, | 3504 | ext_phy_addr, |
2916 | MDIO_PMA_DEVAD, | 3505 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_ALARM, |
2917 | MDIO_PMA_REG_LASI_STATUS, &val1); | 3506 | &val2); |
2918 | DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1); | 3507 | /* clear LASI indication*/ |
2919 | |||
2920 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 3508 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
2921 | ext_phy_addr, | 3509 | ext_phy_addr, |
2922 | MDIO_PMA_DEVAD, | 3510 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, |
2923 | MDIO_PMA_REG_LASI_STATUS, &val1); | 3511 | &val1); |
2924 | DP(NETIF_MSG_LINK, "8706 LASI status 0x%x\n", val1); | 3512 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
3513 | ext_phy_addr, | ||
3514 | MDIO_PMA_DEVAD, MDIO_PMA_REG_LASI_STATUS, | ||
3515 | &val2); | ||
3516 | DP(NETIF_MSG_LINK, "8706/8726 LASI status 0x%x-->" | ||
3517 | "0x%x\n", val1, val2); | ||
2925 | 3518 | ||
2926 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 3519 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
2927 | ext_phy_addr, | 3520 | ext_phy_addr, |
2928 | MDIO_PMA_DEVAD, | 3521 | MDIO_PMA_DEVAD, MDIO_PMA_REG_RX_SD, |
2929 | MDIO_PMA_REG_RX_SD, &rx_sd); | 3522 | &rx_sd); |
2930 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 3523 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
2931 | ext_phy_addr, | 3524 | ext_phy_addr, |
2932 | MDIO_PCS_DEVAD, | 3525 | MDIO_PCS_DEVAD, MDIO_PCS_REG_STATUS, |
2933 | MDIO_PCS_REG_STATUS, &pcs_status); | 3526 | &pcs_status); |
2934 | |||
2935 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 3527 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
2936 | ext_phy_addr, | 3528 | ext_phy_addr, |
2937 | MDIO_AN_DEVAD, | 3529 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, |
2938 | MDIO_AN_REG_LINK_STATUS, &val2); | 3530 | &val2); |
2939 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 3531 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
2940 | ext_phy_addr, | 3532 | ext_phy_addr, |
2941 | MDIO_AN_DEVAD, | 3533 | MDIO_AN_DEVAD, MDIO_AN_REG_LINK_STATUS, |
2942 | MDIO_AN_REG_LINK_STATUS, &val2); | 3534 | &val2); |
2943 | 3535 | ||
2944 | DP(NETIF_MSG_LINK, "8706 rx_sd 0x%x" | 3536 | DP(NETIF_MSG_LINK, "8706/8726 rx_sd 0x%x" |
2945 | " pcs_status 0x%x 1Gbps link_status 0x%x\n", | 3537 | " pcs_status 0x%x 1Gbps link_status 0x%x\n", |
2946 | rx_sd, pcs_status, val2); | 3538 | rx_sd, pcs_status, val2); |
2947 | /* link is up if both bit 0 of pmd_rx_sd and | 3539 | /* link is up if both bit 0 of pmd_rx_sd and |
@@ -2951,19 +3543,31 @@ static u8 bnx2x_ext_phy_is_link_up(struct link_params *params, | |||
2951 | ext_phy_link_up = ((rx_sd & pcs_status & 0x1) || | 3543 | ext_phy_link_up = ((rx_sd & pcs_status & 0x1) || |
2952 | (val2 & (1<<1))); | 3544 | (val2 & (1<<1))); |
2953 | if (ext_phy_link_up) { | 3545 | if (ext_phy_link_up) { |
3546 | if (ext_phy_type == | ||
3547 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) { | ||
3548 | /* If transmitter is disabled, | ||
3549 | ignore false link up indication */ | ||
3550 | bnx2x_cl45_read(bp, params->port, | ||
3551 | ext_phy_type, | ||
3552 | ext_phy_addr, | ||
3553 | MDIO_PMA_DEVAD, | ||
3554 | MDIO_PMA_REG_PHY_IDENTIFIER, | ||
3555 | &val1); | ||
3556 | if (val1 & (1<<15)) { | ||
3557 | DP(NETIF_MSG_LINK, "Tx is " | ||
3558 | "disabled\n"); | ||
3559 | ext_phy_link_up = 0; | ||
3560 | break; | ||
3561 | } | ||
3562 | } | ||
3563 | |||
2954 | if (val2 & (1<<1)) | 3564 | if (val2 & (1<<1)) |
2955 | vars->line_speed = SPEED_1000; | 3565 | vars->line_speed = SPEED_1000; |
2956 | else | 3566 | else |
2957 | vars->line_speed = SPEED_10000; | 3567 | vars->line_speed = SPEED_10000; |
2958 | } | 3568 | } |
2959 | 3569 | ||
2960 | /* clear LASI indication*/ | ||
2961 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | ||
2962 | ext_phy_addr, | ||
2963 | MDIO_PMA_DEVAD, | ||
2964 | MDIO_PMA_REG_RX_ALARM, &val2); | ||
2965 | break; | 3570 | break; |
2966 | |||
2967 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | 3571 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: |
2968 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | 3572 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: |
2969 | { | 3573 | { |
@@ -3523,7 +4127,7 @@ u8 bnx2x_get_ext_phy_fw_version(struct link_params *params, u8 driver_loaded, | |||
3523 | } | 4127 | } |
3524 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | 4128 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: |
3525 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 4129 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
3526 | 4130 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | |
3527 | bnx2x_cl45_read(bp, params->port, ext_phy_type, | 4131 | bnx2x_cl45_read(bp, params->port, ext_phy_type, |
3528 | ext_phy_addr, | 4132 | ext_phy_addr, |
3529 | MDIO_PMA_DEVAD, | 4133 | MDIO_PMA_DEVAD, |
@@ -3636,6 +4240,14 @@ static void bnx2x_ext_phy_loopback(struct link_params *params) | |||
3636 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 4240 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
3637 | DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n"); | 4241 | DP(NETIF_MSG_LINK, "ext_phy_loopback: 8706\n"); |
3638 | break; | 4242 | break; |
4243 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
4244 | DP(NETIF_MSG_LINK, "PMA/PMD ext_phy_loopback: 8726\n"); | ||
4245 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | ||
4246 | ext_phy_addr, | ||
4247 | MDIO_PMA_DEVAD, | ||
4248 | MDIO_PMA_REG_CTRL, | ||
4249 | 0x0001); | ||
4250 | break; | ||
3639 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | 4251 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: |
3640 | /* SFX7101_XGXS_TEST1 */ | 4252 | /* SFX7101_XGXS_TEST1 */ |
3641 | bnx2x_cl45_write(bp, params->port, ext_phy_type, | 4253 | bnx2x_cl45_write(bp, params->port, ext_phy_type, |
@@ -3910,7 +4522,8 @@ static u8 bnx2x_link_initialize(struct link_params *params, | |||
3910 | (params->loopback_mode == LOOPBACK_EXT_PHY)); | 4522 | (params->loopback_mode == LOOPBACK_EXT_PHY)); |
3911 | 4523 | ||
3912 | if (non_ext_phy || | 4524 | if (non_ext_phy || |
3913 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705)) { | 4525 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) || |
4526 | (ext_phy_type == PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726)) { | ||
3914 | if (params->req_line_speed == SPEED_AUTO_NEG) | 4527 | if (params->req_line_speed == SPEED_AUTO_NEG) |
3915 | bnx2x_set_parallel_detection(params, vars->phy_flags); | 4528 | bnx2x_set_parallel_detection(params, vars->phy_flags); |
3916 | bnx2x_init_internal_phy(params, vars); | 4529 | bnx2x_init_internal_phy(params, vars); |
@@ -4112,7 +4725,23 @@ u8 bnx2x_phy_init(struct link_params *params, struct link_vars *vars) | |||
4112 | return 0; | 4725 | return 0; |
4113 | } | 4726 | } |
4114 | 4727 | ||
4115 | u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars) | 4728 | static void bnx2x_8726_reset_phy(struct bnx2x *bp, u8 port, u8 ext_phy_addr) |
4729 | { | ||
4730 | DP(NETIF_MSG_LINK, "bnx2x_8726_reset_phy port %d\n", port); | ||
4731 | |||
4732 | /* Set serial boot control for external load */ | ||
4733 | bnx2x_cl45_write(bp, port, | ||
4734 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726, ext_phy_addr, | ||
4735 | MDIO_PMA_DEVAD, | ||
4736 | MDIO_PMA_REG_GEN_CTRL, 0x0001); | ||
4737 | |||
4738 | /* Disable Transmitter */ | ||
4739 | bnx2x_bcm8726_set_transmitter(bp, port, ext_phy_addr, 0); | ||
4740 | |||
4741 | } | ||
4742 | |||
4743 | u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | ||
4744 | u8 reset_ext_phy) | ||
4116 | { | 4745 | { |
4117 | 4746 | ||
4118 | struct bnx2x *bp = params->bp; | 4747 | struct bnx2x *bp = params->bp; |
@@ -4150,28 +4779,37 @@ u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars) | |||
4150 | */ | 4779 | */ |
4151 | /* clear link led */ | 4780 | /* clear link led */ |
4152 | bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id); | 4781 | bnx2x_set_led(bp, port, LED_MODE_OFF, 0, hw_led_mode, chip_id); |
4153 | if (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT) { | 4782 | if (reset_ext_phy) { |
4154 | if ((ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072) && | 4783 | switch (ext_phy_type) { |
4155 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073)) { | 4784 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: |
4785 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | ||
4786 | break; | ||
4787 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | ||
4788 | DP(NETIF_MSG_LINK, "Setting 8073 port %d into " | ||
4789 | "low power mode\n", | ||
4790 | port); | ||
4791 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
4792 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
4793 | port); | ||
4794 | break; | ||
4795 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
4796 | { | ||
4797 | u8 ext_phy_addr = ((params->ext_phy_config & | ||
4798 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
4799 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
4800 | /* Set soft reset */ | ||
4801 | bnx2x_8726_reset_phy(bp, params->port, ext_phy_addr); | ||
4802 | break; | ||
4803 | } | ||
4804 | default: | ||
4156 | /* HW reset */ | 4805 | /* HW reset */ |
4157 | |||
4158 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, | 4806 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_1, |
4159 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | 4807 | MISC_REGISTERS_GPIO_OUTPUT_LOW, |
4160 | port); | 4808 | port); |
4161 | |||
4162 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | 4809 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, |
4163 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | 4810 | MISC_REGISTERS_GPIO_OUTPUT_LOW, |
4164 | port); | 4811 | port); |
4165 | |||
4166 | DP(NETIF_MSG_LINK, "reset external PHY\n"); | 4812 | DP(NETIF_MSG_LINK, "reset external PHY\n"); |
4167 | } else if (ext_phy_type == | ||
4168 | PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073) { | ||
4169 | DP(NETIF_MSG_LINK, "Setting 8073 port %d into " | ||
4170 | "low power mode\n", | ||
4171 | port); | ||
4172 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_2, | ||
4173 | MISC_REGISTERS_GPIO_OUTPUT_LOW, | ||
4174 | port); | ||
4175 | } | 4813 | } |
4176 | } | 4814 | } |
4177 | /* reset the SerDes/XGXS */ | 4815 | /* reset the SerDes/XGXS */ |
@@ -4337,6 +4975,7 @@ u8 bnx2x_link_update(struct link_params *params, struct link_vars *vars) | |||
4337 | 4975 | ||
4338 | if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) && | 4976 | if ((ext_phy_type != PORT_HW_CFG_SERDES_EXT_PHY_TYPE_DIRECT) && |
4339 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) && | 4977 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705) && |
4978 | (ext_phy_type != PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726) && | ||
4340 | (ext_phy_link_up && !vars->phy_link_up)) | 4979 | (ext_phy_link_up && !vars->phy_link_up)) |
4341 | bnx2x_init_internal_phy(params, vars); | 4980 | bnx2x_init_internal_phy(params, vars); |
4342 | 4981 | ||
@@ -4469,6 +5108,45 @@ static u8 bnx2x_8073_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
4469 | 5108 | ||
4470 | } | 5109 | } |
4471 | 5110 | ||
5111 | |||
5112 | static u8 bnx2x_8726_common_init_phy(struct bnx2x *bp, u32 shmem_base) | ||
5113 | { | ||
5114 | u8 ext_phy_addr; | ||
5115 | u32 val; | ||
5116 | s8 port; | ||
5117 | /* Use port1 because of the static port-swap */ | ||
5118 | /* Enable the module detection interrupt */ | ||
5119 | val = REG_RD(bp, MISC_REG_GPIO_EVENT_EN); | ||
5120 | val |= ((1<<MISC_REGISTERS_GPIO_3)| | ||
5121 | (1<<(MISC_REGISTERS_GPIO_3 + MISC_REGISTERS_GPIO_PORT_SHIFT))); | ||
5122 | REG_WR(bp, MISC_REG_GPIO_EVENT_EN, val); | ||
5123 | |||
5124 | bnx2x_hw_reset(bp, 1); | ||
5125 | msleep(5); | ||
5126 | for (port = 0; port < PORT_MAX; port++) { | ||
5127 | /* Extract the ext phy address for the port */ | ||
5128 | u32 ext_phy_config = REG_RD(bp, shmem_base + | ||
5129 | offsetof(struct shmem_region, | ||
5130 | dev_info.port_hw_config[port].external_phy_config)); | ||
5131 | |||
5132 | ext_phy_addr = | ||
5133 | ((ext_phy_config & | ||
5134 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_MASK) >> | ||
5135 | PORT_HW_CFG_XGXS_EXT_PHY_ADDR_SHIFT); | ||
5136 | DP(NETIF_MSG_LINK, "8726_common_init : ext_phy_addr = 0x%x\n", | ||
5137 | ext_phy_addr); | ||
5138 | |||
5139 | bnx2x_8726_reset_phy(bp, port, ext_phy_addr); | ||
5140 | |||
5141 | /* Set fault module detected LED on */ | ||
5142 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_0, | ||
5143 | MISC_REGISTERS_GPIO_HIGH, | ||
5144 | port); | ||
5145 | } | ||
5146 | |||
5147 | return 0; | ||
5148 | } | ||
5149 | |||
4472 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) | 5150 | u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) |
4473 | { | 5151 | { |
4474 | u8 rc = 0; | 5152 | u8 rc = 0; |
@@ -4488,6 +5166,12 @@ u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) | |||
4488 | rc = bnx2x_8073_common_init_phy(bp, shmem_base); | 5166 | rc = bnx2x_8073_common_init_phy(bp, shmem_base); |
4489 | break; | 5167 | break; |
4490 | } | 5168 | } |
5169 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
5170 | /* GPIO1 affects both ports, so there's need to pull | ||
5171 | it for single port alone */ | ||
5172 | rc = bnx2x_8726_common_init_phy(bp, shmem_base); | ||
5173 | |||
5174 | break; | ||
4491 | default: | 5175 | default: |
4492 | DP(NETIF_MSG_LINK, | 5176 | DP(NETIF_MSG_LINK, |
4493 | "bnx2x_common_init_phy: ext_phy 0x%x not required\n", | 5177 | "bnx2x_common_init_phy: ext_phy 0x%x not required\n", |
diff --git a/drivers/net/bnx2x_link.h b/drivers/net/bnx2x_link.h index 47cb585f4278..1318683f6e51 100644 --- a/drivers/net/bnx2x_link.h +++ b/drivers/net/bnx2x_link.h | |||
@@ -89,6 +89,9 @@ struct link_params { | |||
89 | 89 | ||
90 | /* phy_addr populated by the CLC */ | 90 | /* phy_addr populated by the CLC */ |
91 | u8 phy_addr; | 91 | u8 phy_addr; |
92 | u32 feature_config_flags; | ||
93 | #define FEATURE_CONFIG_OVERRIDE_PREEMPHASIS_ENABLED (1<<0) | ||
94 | #define FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED (2<<0) | ||
92 | /* Device pointer passed to all callback functions */ | 95 | /* Device pointer passed to all callback functions */ |
93 | struct bnx2x *bp; | 96 | struct bnx2x *bp; |
94 | }; | 97 | }; |
@@ -125,8 +128,11 @@ struct link_vars { | |||
125 | /* Initialize the phy */ | 128 | /* Initialize the phy */ |
126 | u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output); | 129 | u8 bnx2x_phy_init(struct link_params *input, struct link_vars *output); |
127 | 130 | ||
128 | /* Reset the link. Should be called when driver or interface goes down */ | 131 | /* Reset the link. Should be called when driver or interface goes down |
129 | u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars); | 132 | Before calling phy firmware upgrade, the reset_ext_phy should be set |
133 | to 0 */ | ||
134 | u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars, | ||
135 | u8 reset_ext_phy); | ||
130 | 136 | ||
131 | /* bnx2x_link_update should be called upon link interrupt */ | 137 | /* bnx2x_link_update should be called upon link interrupt */ |
132 | u8 bnx2x_link_update(struct link_params *input, struct link_vars *output); | 138 | u8 bnx2x_link_update(struct link_params *input, struct link_vars *output); |
@@ -163,6 +169,10 @@ u8 bnx2x_override_led_value(struct bnx2x *bp, u8 port, u32 led_idx, u32 value); | |||
163 | 169 | ||
164 | u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config, | 170 | u8 bnx2x_flash_download(struct bnx2x *bp, u8 port, u32 ext_phy_config, |
165 | u8 driver_loaded, char data[], u32 size); | 171 | u8 driver_loaded, char data[], u32 size); |
172 | /* bnx2x_handle_module_detect_int should be called upon module detection | ||
173 | interrupt */ | ||
174 | void bnx2x_handle_module_detect_int(struct link_params *params); | ||
175 | |||
166 | /* Get the actual link status. In case it returns 0, link is up, | 176 | /* Get the actual link status. In case it returns 0, link is up, |
167 | otherwise link is down*/ | 177 | otherwise link is down*/ |
168 | u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars); | 178 | u8 bnx2x_test_link(struct link_params *input, struct link_vars *vars); |
diff --git a/drivers/net/bnx2x_main.c b/drivers/net/bnx2x_main.c index 95f8e58e73b4..5acbd98778b8 100644 --- a/drivers/net/bnx2x_main.c +++ b/drivers/net/bnx2x_main.c | |||
@@ -2112,7 +2112,7 @@ static void bnx2x__link_reset(struct bnx2x *bp) | |||
2112 | { | 2112 | { |
2113 | if (!BP_NOMCP(bp)) { | 2113 | if (!BP_NOMCP(bp)) { |
2114 | bnx2x_acquire_phy_lock(bp); | 2114 | bnx2x_acquire_phy_lock(bp); |
2115 | bnx2x_link_reset(&bp->link_params, &bp->link_vars); | 2115 | bnx2x_link_reset(&bp->link_params, &bp->link_vars, 1); |
2116 | bnx2x_release_phy_lock(bp); | 2116 | bnx2x_release_phy_lock(bp); |
2117 | } else | 2117 | } else |
2118 | BNX2X_ERR("Bootcode is missing -not resetting link\n"); | 2118 | BNX2X_ERR("Bootcode is missing -not resetting link\n"); |
@@ -2613,6 +2613,13 @@ static inline void bnx2x_attn_int_deasserted0(struct bnx2x *bp, u32 attn) | |||
2613 | } | 2613 | } |
2614 | } | 2614 | } |
2615 | 2615 | ||
2616 | if (attn & (AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 | | ||
2617 | AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1)) { | ||
2618 | bnx2x_acquire_phy_lock(bp); | ||
2619 | bnx2x_handle_module_detect_int(&bp->link_params); | ||
2620 | bnx2x_release_phy_lock(bp); | ||
2621 | } | ||
2622 | |||
2616 | if (attn & HW_INTERRUT_ASSERT_SET_0) { | 2623 | if (attn & HW_INTERRUT_ASSERT_SET_0) { |
2617 | 2624 | ||
2618 | val = REG_RD(bp, reg_offset); | 2625 | val = REG_RD(bp, reg_offset); |
@@ -5905,6 +5912,37 @@ static int bnx2x_init_port(struct bnx2x *bp) | |||
5905 | /* Port DMAE comes here */ | 5912 | /* Port DMAE comes here */ |
5906 | 5913 | ||
5907 | switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) { | 5914 | switch (XGXS_EXT_PHY_TYPE(bp->link_params.ext_phy_config)) { |
5915 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
5916 | { | ||
5917 | u32 swap_val, swap_override, aeu_gpio_mask, offset; | ||
5918 | |||
5919 | bnx2x_set_gpio(bp, MISC_REGISTERS_GPIO_3, | ||
5920 | MISC_REGISTERS_GPIO_INPUT_HI_Z, port); | ||
5921 | |||
5922 | /* The GPIO should be swapped if the swap register is | ||
5923 | set and active */ | ||
5924 | swap_val = REG_RD(bp, NIG_REG_PORT_SWAP); | ||
5925 | swap_override = REG_RD(bp, NIG_REG_STRAP_OVERRIDE); | ||
5926 | |||
5927 | /* Select function upon port-swap configuration */ | ||
5928 | if (port == 0) { | ||
5929 | offset = MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0; | ||
5930 | aeu_gpio_mask = (swap_val && swap_override) ? | ||
5931 | AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1 : | ||
5932 | AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0; | ||
5933 | } else { | ||
5934 | offset = MISC_REG_AEU_ENABLE1_FUNC_1_OUT_0; | ||
5935 | aeu_gpio_mask = (swap_val && swap_override) ? | ||
5936 | AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_0 : | ||
5937 | AEU_INPUTS_ATTN_BITS_GPIO3_FUNCTION_1; | ||
5938 | } | ||
5939 | val = REG_RD(bp, offset); | ||
5940 | /* add GPIO3 to group */ | ||
5941 | val |= aeu_gpio_mask; | ||
5942 | REG_WR(bp, offset, val); | ||
5943 | } | ||
5944 | break; | ||
5945 | |||
5908 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: | 5946 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_SFX7101: |
5909 | /* add SPIO 5 to group 0 */ | 5947 | /* add SPIO 5 to group 0 */ |
5910 | val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); | 5948 | val = REG_RD(bp, MISC_REG_AEU_ENABLE1_FUNC_0_OUT_0); |
@@ -7623,48 +7661,60 @@ static void __devinit bnx2x_link_settings_supported(struct bnx2x *bp, | |||
7623 | SUPPORTED_Asym_Pause); | 7661 | SUPPORTED_Asym_Pause); |
7624 | break; | 7662 | break; |
7625 | 7663 | ||
7626 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | 7664 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: |
7627 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n", | 7665 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n", |
7628 | ext_phy_type); | 7666 | ext_phy_type); |
7629 | 7667 | ||
7630 | bp->port.supported |= (SUPPORTED_10000baseT_Full | | 7668 | bp->port.supported |= (SUPPORTED_10000baseT_Full | |
7669 | SUPPORTED_1000baseT_Full | | ||
7631 | SUPPORTED_FIBRE | | 7670 | SUPPORTED_FIBRE | |
7671 | SUPPORTED_Autoneg | | ||
7632 | SUPPORTED_Pause | | 7672 | SUPPORTED_Pause | |
7633 | SUPPORTED_Asym_Pause); | 7673 | SUPPORTED_Asym_Pause); |
7634 | break; | 7674 | break; |
7635 | 7675 | ||
7636 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | 7676 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: |
7637 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n", | 7677 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8073)\n", |
7638 | ext_phy_type); | 7678 | ext_phy_type); |
7639 | 7679 | ||
7640 | bp->port.supported |= (SUPPORTED_10000baseT_Full | | 7680 | bp->port.supported |= (SUPPORTED_10000baseT_Full | |
7681 | SUPPORTED_2500baseX_Full | | ||
7641 | SUPPORTED_1000baseT_Full | | 7682 | SUPPORTED_1000baseT_Full | |
7642 | SUPPORTED_FIBRE | | 7683 | SUPPORTED_FIBRE | |
7684 | SUPPORTED_Autoneg | | ||
7685 | SUPPORTED_Pause | | ||
7686 | SUPPORTED_Asym_Pause); | ||
7687 | break; | ||
7688 | |||
7689 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | ||
7690 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8705)\n", | ||
7691 | ext_phy_type); | ||
7692 | |||
7693 | bp->port.supported |= (SUPPORTED_10000baseT_Full | | ||
7694 | SUPPORTED_FIBRE | | ||
7643 | SUPPORTED_Pause | | 7695 | SUPPORTED_Pause | |
7644 | SUPPORTED_Asym_Pause); | 7696 | SUPPORTED_Asym_Pause); |
7645 | break; | 7697 | break; |
7646 | 7698 | ||
7647 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | 7699 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: |
7648 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8072)\n", | 7700 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8706)\n", |
7649 | ext_phy_type); | 7701 | ext_phy_type); |
7650 | 7702 | ||
7651 | bp->port.supported |= (SUPPORTED_10000baseT_Full | | 7703 | bp->port.supported |= (SUPPORTED_10000baseT_Full | |
7652 | SUPPORTED_1000baseT_Full | | 7704 | SUPPORTED_1000baseT_Full | |
7653 | SUPPORTED_FIBRE | | 7705 | SUPPORTED_FIBRE | |
7654 | SUPPORTED_Autoneg | | ||
7655 | SUPPORTED_Pause | | 7706 | SUPPORTED_Pause | |
7656 | SUPPORTED_Asym_Pause); | 7707 | SUPPORTED_Asym_Pause); |
7657 | break; | 7708 | break; |
7658 | 7709 | ||
7659 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | 7710 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: |
7660 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8073)\n", | 7711 | BNX2X_DEV_INFO("ext_phy_type 0x%x (8726)\n", |
7661 | ext_phy_type); | 7712 | ext_phy_type); |
7662 | 7713 | ||
7663 | bp->port.supported |= (SUPPORTED_10000baseT_Full | | 7714 | bp->port.supported |= (SUPPORTED_10000baseT_Full | |
7664 | SUPPORTED_2500baseX_Full | | ||
7665 | SUPPORTED_1000baseT_Full | | 7715 | SUPPORTED_1000baseT_Full | |
7666 | SUPPORTED_FIBRE | | ||
7667 | SUPPORTED_Autoneg | | 7716 | SUPPORTED_Autoneg | |
7717 | SUPPORTED_FIBRE | | ||
7668 | SUPPORTED_Pause | | 7718 | SUPPORTED_Pause | |
7669 | SUPPORTED_Asym_Pause); | 7719 | SUPPORTED_Asym_Pause); |
7670 | break; | 7720 | break; |
@@ -7905,6 +7955,7 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) | |||
7905 | { | 7955 | { |
7906 | int port = BP_PORT(bp); | 7956 | int port = BP_PORT(bp); |
7907 | u32 val, val2; | 7957 | u32 val, val2; |
7958 | u32 config; | ||
7908 | 7959 | ||
7909 | bp->link_params.bp = bp; | 7960 | bp->link_params.bp = bp; |
7910 | bp->link_params.port = port; | 7961 | bp->link_params.port = port; |
@@ -7923,6 +7974,14 @@ static void __devinit bnx2x_get_port_hwinfo(struct bnx2x *bp) | |||
7923 | bp->port.link_config = | 7974 | bp->port.link_config = |
7924 | SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); | 7975 | SHMEM_RD(bp, dev_info.port_feature_config[port].link_config); |
7925 | 7976 | ||
7977 | config = SHMEM_RD(bp, dev_info.port_feature_config[port].config); | ||
7978 | if (config & PORT_FEAT_CFG_OPT_MDL_ENFRCMNT_ENABLED) | ||
7979 | bp->link_params.feature_config_flags |= | ||
7980 | FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED; | ||
7981 | else | ||
7982 | bp->link_params.feature_config_flags &= | ||
7983 | ~FEATURE_CONFIG_MODULE_ENFORCMENT_ENABLED; | ||
7984 | |||
7926 | BNX2X_DEV_INFO("serdes_config 0x%08x lane_config 0x%08x\n" | 7985 | BNX2X_DEV_INFO("serdes_config 0x%08x lane_config 0x%08x\n" |
7927 | KERN_INFO " ext_phy_config 0x%08x speed_cap_mask 0x%08x" | 7986 | KERN_INFO " ext_phy_config 0x%08x speed_cap_mask 0x%08x" |
7928 | " link_config 0x%08x\n", | 7987 | " link_config 0x%08x\n", |
@@ -8121,10 +8180,11 @@ static int bnx2x_get_settings(struct net_device *dev, struct ethtool_cmd *cmd) | |||
8121 | 8180 | ||
8122 | switch (ext_phy_type) { | 8181 | switch (ext_phy_type) { |
8123 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: | 8182 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_DIRECT: |
8124 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | ||
8125 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | ||
8126 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: | 8183 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8072: |
8127 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: | 8184 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8073: |
8185 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8705: | ||
8186 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8706: | ||
8187 | case PORT_HW_CFG_XGXS_EXT_PHY_TYPE_BCM8726: | ||
8128 | cmd->port = PORT_FIBRE; | 8188 | cmd->port = PORT_FIBRE; |
8129 | break; | 8189 | break; |
8130 | 8190 | ||
@@ -8807,7 +8867,7 @@ static int bnx2x_set_eeprom(struct net_device *dev, | |||
8807 | if ((bp->state == BNX2X_STATE_OPEN) || | 8867 | if ((bp->state == BNX2X_STATE_OPEN) || |
8808 | (bp->state == BNX2X_STATE_DISABLED)) { | 8868 | (bp->state == BNX2X_STATE_DISABLED)) { |
8809 | rc |= bnx2x_link_reset(&bp->link_params, | 8869 | rc |= bnx2x_link_reset(&bp->link_params, |
8810 | &bp->link_vars); | 8870 | &bp->link_vars, 1); |
8811 | rc |= bnx2x_phy_init(&bp->link_params, | 8871 | rc |= bnx2x_phy_init(&bp->link_params, |
8812 | &bp->link_vars); | 8872 | &bp->link_vars); |
8813 | } | 8873 | } |
diff --git a/drivers/net/bnx2x_reg.h b/drivers/net/bnx2x_reg.h index 6fc1d0df9789..520bf695864e 100644 --- a/drivers/net/bnx2x_reg.h +++ b/drivers/net/bnx2x_reg.h | |||
@@ -5800,9 +5800,25 @@ Theotherbitsarereservedandshouldbezero*/ | |||
5800 | #define MDIO_PMA_REG_ROM_VER2 0xca1a | 5800 | #define MDIO_PMA_REG_ROM_VER2 0xca1a |
5801 | #define MDIO_PMA_REG_EDC_FFE_MAIN 0xca1b | 5801 | #define MDIO_PMA_REG_EDC_FFE_MAIN 0xca1b |
5802 | #define MDIO_PMA_REG_PLL_BANDWIDTH 0xca1d | 5802 | #define MDIO_PMA_REG_PLL_BANDWIDTH 0xca1d |
5803 | #define MDIO_PMA_REG_MISC_CTRL0 0xca23 | ||
5804 | #define MDIO_PMA_REG_LRM_MODE 0xca3f | ||
5803 | #define MDIO_PMA_REG_CDR_BANDWIDTH 0xca46 | 5805 | #define MDIO_PMA_REG_CDR_BANDWIDTH 0xca46 |
5804 | #define MDIO_PMA_REG_MISC_CTRL1 0xca85 | 5806 | #define MDIO_PMA_REG_MISC_CTRL1 0xca85 |
5805 | 5807 | ||
5808 | #define MDIO_PMA_REG_8726_TWO_WIRE_CTRL 0x8000 | ||
5809 | #define MDIO_PMA_REG_8726_TWO_WIRE_CTRL_STATUS_MASK 0x000c | ||
5810 | #define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_IDLE 0x0000 | ||
5811 | #define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_COMPLETE 0x0004 | ||
5812 | #define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_IN_PROGRESS 0x0008 | ||
5813 | #define MDIO_PMA_REG_8726_TWO_WIRE_STATUS_FAILED 0x000c | ||
5814 | #define MDIO_PMA_REG_8726_TWO_WIRE_BYTE_CNT 0x8002 | ||
5815 | #define MDIO_PMA_REG_8726_TWO_WIRE_MEM_ADDR 0x8003 | ||
5816 | #define MDIO_PMA_REG_8726_TWO_WIRE_DATA_BUF 0xc820 | ||
5817 | #define MDIO_PMA_REG_8726_TWO_WIRE_DATA_MASK 0xff | ||
5818 | #define MDIO_PMA_REG_8726_TX_CTRL1 0xca01 | ||
5819 | #define MDIO_PMA_REG_8726_TX_CTRL2 0xca05 | ||
5820 | |||
5821 | |||
5806 | #define MDIO_PMA_REG_7101_RESET 0xc000 | 5822 | #define MDIO_PMA_REG_7101_RESET 0xc000 |
5807 | #define MDIO_PMA_REG_7107_LED_CNTL 0xc007 | 5823 | #define MDIO_PMA_REG_7107_LED_CNTL 0xc007 |
5808 | #define MDIO_PMA_REG_7101_VER1 0xc026 | 5824 | #define MDIO_PMA_REG_7101_VER1 0xc026 |
@@ -5832,6 +5848,12 @@ Theotherbitsarereservedandshouldbezero*/ | |||
5832 | #define MDIO_XS_PLL_SEQUENCER 0x8000 | 5848 | #define MDIO_XS_PLL_SEQUENCER 0x8000 |
5833 | #define MDIO_XS_SFX7101_XGXS_TEST1 0xc00a | 5849 | #define MDIO_XS_SFX7101_XGXS_TEST1 0xc00a |
5834 | 5850 | ||
5851 | #define MDIO_XS_8706_REG_BANK_RX0 0x80bc | ||
5852 | #define MDIO_XS_8706_REG_BANK_RX1 0x80cc | ||
5853 | #define MDIO_XS_8706_REG_BANK_RX2 0x80dc | ||
5854 | #define MDIO_XS_8706_REG_BANK_RX3 0x80ec | ||
5855 | #define MDIO_XS_8706_REG_BANK_RXA 0x80fc | ||
5856 | |||
5835 | #define MDIO_AN_DEVAD 0x7 | 5857 | #define MDIO_AN_DEVAD 0x7 |
5836 | /*ieee*/ | 5858 | /*ieee*/ |
5837 | #define MDIO_AN_REG_CTRL 0x0000 | 5859 | #define MDIO_AN_REG_CTRL 0x0000 |