aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/bnx2x_link.c
diff options
context:
space:
mode:
authorEilon Greenstein <eilong@broadcom.com>2009-02-12 03:36:55 -0500
committerDavid S. Miller <davem@davemloft.net>2009-02-16 02:31:24 -0500
commit589abe3a0f594a7707a15674ca9e80370c972832 (patch)
treea7930047ca7f5340b9053948fcba98128de4d588 /drivers/net/bnx2x_link.c
parent4acac6a53a3c9dfc604a9a8647f16b0242080e93 (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.c776
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
752static u32 bnx2x_get_emac_base(u32 ext_phy_type, u8 port) 772static 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
2249static 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
2296static 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
2324static 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
2408static 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 */
2474static 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
2530static 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
2608static 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
2627static 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
2688void 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
2201static void bnx2x_bcm807x_force_10G(struct link_params *params) 2727static 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
4115u8 bnx2x_link_reset(struct link_params *params, struct link_vars *vars) 4728static 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
4743u8 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
5112static 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
4472u8 bnx2x_common_init_phy(struct bnx2x *bp, u32 shmem_base) 5150u8 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",