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 /drivers/net/bnx2x_link.c | |
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>
Diffstat (limited to 'drivers/net/bnx2x_link.c')
-rw-r--r-- | drivers/net/bnx2x_link.c | 776 |
1 files changed, 730 insertions, 46 deletions
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", |