diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-09-06 15:44:53 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2006-09-13 13:27:44 -0400 |
commit | b89165f2b75ba0a79eb5ed60924835cf3c54c51a (patch) | |
tree | 6ed4af3b2746c94416858753449f74310cb5407c /drivers/net | |
parent | 2eaba1a280b6380f5b1238c53ce62e4381fc5f97 (diff) |
[PATCH] sky2: fiber support
Fix the support for fiber connected gigabit boards.
Allow half duplex gigabit to be configured.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/sky2.c | 81 | ||||
-rw-r--r-- | drivers/net/sky2.h | 15 |
2 files changed, 63 insertions, 33 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index a3a4ab26044a..2b9272c0955a 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -308,7 +308,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
308 | } | 308 | } |
309 | 309 | ||
310 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | 310 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); |
311 | if (hw->copper) { | 311 | if (sky2_is_copper(hw)) { |
312 | if (hw->chip_id == CHIP_ID_YUKON_FE) { | 312 | if (hw->chip_id == CHIP_ID_YUKON_FE) { |
313 | /* enable automatic crossover */ | 313 | /* enable automatic crossover */ |
314 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; | 314 | ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; |
@@ -325,25 +325,37 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
325 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; | 325 | ctrl |= PHY_M_PC_DSC(2) | PHY_M_PC_DOWN_S_ENA; |
326 | } | 326 | } |
327 | } | 327 | } |
328 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
329 | } else { | 328 | } else { |
330 | /* workaround for deviation #4.88 (CRC errors) */ | 329 | /* workaround for deviation #4.88 (CRC errors) */ |
331 | /* disable Automatic Crossover */ | 330 | /* disable Automatic Crossover */ |
332 | 331 | ||
333 | ctrl &= ~PHY_M_PC_MDIX_MSK; | 332 | ctrl &= ~PHY_M_PC_MDIX_MSK; |
334 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | 333 | } |
335 | 334 | ||
336 | if (hw->chip_id == CHIP_ID_YUKON_XL) { | 335 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); |
337 | /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ | 336 | |
338 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); | 337 | /* special setup for PHY 88E1112 Fiber */ |
339 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | 338 | if (hw->chip_id == CHIP_ID_YUKON_XL && !sky2_is_copper(hw)) { |
340 | ctrl &= ~PHY_M_MAC_MD_MSK; | 339 | pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); |
341 | ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX); | ||
342 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
343 | 340 | ||
341 | /* Fiber: select 1000BASE-X only mode MAC Specific Ctrl Reg. */ | ||
342 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); | ||
343 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
344 | ctrl &= ~PHY_M_MAC_MD_MSK; | ||
345 | ctrl |= PHY_M_MAC_MODE_SEL(PHY_M_MAC_MD_1000BX); | ||
346 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
347 | |||
348 | if (hw->pmd_type == 'P') { | ||
344 | /* select page 1 to access Fiber registers */ | 349 | /* select page 1 to access Fiber registers */ |
345 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1); | 350 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 1); |
351 | |||
352 | /* for SFP-module set SIGDET polarity to low */ | ||
353 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
354 | ctrl |= PHY_M_FIB_SIGD_POL; | ||
355 | gm_phy_write(hw, port, PHY_MARV_CTRL, ctrl); | ||
346 | } | 356 | } |
357 | |||
358 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, pg); | ||
347 | } | 359 | } |
348 | 360 | ||
349 | ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); | 361 | ctrl = gm_phy_read(hw, port, PHY_MARV_CTRL); |
@@ -361,7 +373,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
361 | reg = 0; | 373 | reg = 0; |
362 | 374 | ||
363 | if (sky2->autoneg == AUTONEG_ENABLE) { | 375 | if (sky2->autoneg == AUTONEG_ENABLE) { |
364 | if (hw->copper) { | 376 | if (sky2_is_copper(hw)) { |
365 | if (sky2->advertising & ADVERTISED_1000baseT_Full) | 377 | if (sky2->advertising & ADVERTISED_1000baseT_Full) |
366 | ct1000 |= PHY_M_1000C_AFD; | 378 | ct1000 |= PHY_M_1000C_AFD; |
367 | if (sky2->advertising & ADVERTISED_1000baseT_Half) | 379 | if (sky2->advertising & ADVERTISED_1000baseT_Half) |
@@ -374,8 +386,12 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
374 | adv |= PHY_M_AN_10_FD; | 386 | adv |= PHY_M_AN_10_FD; |
375 | if (sky2->advertising & ADVERTISED_10baseT_Half) | 387 | if (sky2->advertising & ADVERTISED_10baseT_Half) |
376 | adv |= PHY_M_AN_10_HD; | 388 | adv |= PHY_M_AN_10_HD; |
377 | } else /* special defines for FIBER (88E1011S only) */ | 389 | } else { /* special defines for FIBER (88E1040S only) */ |
378 | adv |= PHY_M_AN_1000X_AHD | PHY_M_AN_1000X_AFD; | 390 | if (sky2->advertising & ADVERTISED_1000baseT_Full) |
391 | adv |= PHY_M_AN_1000X_AFD; | ||
392 | if (sky2->advertising & ADVERTISED_1000baseT_Half) | ||
393 | adv |= PHY_M_AN_1000X_AHD; | ||
394 | } | ||
379 | 395 | ||
380 | /* Set Flow-control capabilities */ | 396 | /* Set Flow-control capabilities */ |
381 | if (sky2->tx_pause && sky2->rx_pause) | 397 | if (sky2->tx_pause && sky2->rx_pause) |
@@ -1496,7 +1512,7 @@ static int sky2_down(struct net_device *dev) | |||
1496 | 1512 | ||
1497 | static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) | 1513 | static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) |
1498 | { | 1514 | { |
1499 | if (!hw->copper) | 1515 | if (!sky2_is_copper(hw)) |
1500 | return SPEED_1000; | 1516 | return SPEED_1000; |
1501 | 1517 | ||
1502 | if (hw->chip_id == CHIP_ID_YUKON_FE) | 1518 | if (hw->chip_id == CHIP_ID_YUKON_FE) |
@@ -2269,7 +2285,7 @@ static inline u32 sky2_clk2us(const struct sky2_hw *hw, u32 clk) | |||
2269 | static int sky2_reset(struct sky2_hw *hw) | 2285 | static int sky2_reset(struct sky2_hw *hw) |
2270 | { | 2286 | { |
2271 | u16 status; | 2287 | u16 status; |
2272 | u8 t8, pmd_type; | 2288 | u8 t8; |
2273 | int i; | 2289 | int i; |
2274 | 2290 | ||
2275 | sky2_write8(hw, B0_CTST, CS_RST_CLR); | 2291 | sky2_write8(hw, B0_CTST, CS_RST_CLR); |
@@ -2315,9 +2331,7 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2315 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); | 2331 | sky2_pci_write32(hw, PEX_UNC_ERR_STAT, 0xffffffffUL); |
2316 | 2332 | ||
2317 | 2333 | ||
2318 | pmd_type = sky2_read8(hw, B2_PMD_TYP); | 2334 | hw->pmd_type = sky2_read8(hw, B2_PMD_TYP); |
2319 | hw->copper = !(pmd_type == 'L' || pmd_type == 'S'); | ||
2320 | |||
2321 | hw->ports = 1; | 2335 | hw->ports = 1; |
2322 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | 2336 | t8 = sky2_read8(hw, B2_Y2_HW_RES); |
2323 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { | 2337 | if ((t8 & CFG_DUAL_MAC_MSK) == CFG_DUAL_MAC_MSK) { |
@@ -2414,21 +2428,22 @@ static int sky2_reset(struct sky2_hw *hw) | |||
2414 | 2428 | ||
2415 | static u32 sky2_supported_modes(const struct sky2_hw *hw) | 2429 | static u32 sky2_supported_modes(const struct sky2_hw *hw) |
2416 | { | 2430 | { |
2417 | u32 modes; | 2431 | if (sky2_is_copper(hw)) { |
2418 | if (hw->copper) { | 2432 | u32 modes = SUPPORTED_10baseT_Half |
2419 | modes = SUPPORTED_10baseT_Half | 2433 | | SUPPORTED_10baseT_Full |
2420 | | SUPPORTED_10baseT_Full | 2434 | | SUPPORTED_100baseT_Half |
2421 | | SUPPORTED_100baseT_Half | 2435 | | SUPPORTED_100baseT_Full |
2422 | | SUPPORTED_100baseT_Full | 2436 | | SUPPORTED_Autoneg | SUPPORTED_TP; |
2423 | | SUPPORTED_Autoneg | SUPPORTED_TP; | ||
2424 | 2437 | ||
2425 | if (hw->chip_id != CHIP_ID_YUKON_FE) | 2438 | if (hw->chip_id != CHIP_ID_YUKON_FE) |
2426 | modes |= SUPPORTED_1000baseT_Half | 2439 | modes |= SUPPORTED_1000baseT_Half |
2427 | | SUPPORTED_1000baseT_Full; | 2440 | | SUPPORTED_1000baseT_Full; |
2441 | return modes; | ||
2428 | } else | 2442 | } else |
2429 | modes = SUPPORTED_1000baseT_Full | SUPPORTED_FIBRE | 2443 | return SUPPORTED_1000baseT_Half |
2430 | | SUPPORTED_Autoneg; | 2444 | | SUPPORTED_1000baseT_Full |
2431 | return modes; | 2445 | | SUPPORTED_Autoneg |
2446 | | SUPPORTED_FIBRE; | ||
2432 | } | 2447 | } |
2433 | 2448 | ||
2434 | static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | 2449 | static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) |
@@ -2439,7 +2454,7 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
2439 | ecmd->transceiver = XCVR_INTERNAL; | 2454 | ecmd->transceiver = XCVR_INTERNAL; |
2440 | ecmd->supported = sky2_supported_modes(hw); | 2455 | ecmd->supported = sky2_supported_modes(hw); |
2441 | ecmd->phy_address = PHY_ADDR_MARV; | 2456 | ecmd->phy_address = PHY_ADDR_MARV; |
2442 | if (hw->copper) { | 2457 | if (sky2_is_copper(hw)) { |
2443 | ecmd->supported = SUPPORTED_10baseT_Half | 2458 | ecmd->supported = SUPPORTED_10baseT_Half |
2444 | | SUPPORTED_10baseT_Full | 2459 | | SUPPORTED_10baseT_Full |
2445 | | SUPPORTED_100baseT_Half | 2460 | | SUPPORTED_100baseT_Half |
@@ -2448,12 +2463,14 @@ static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) | |||
2448 | | SUPPORTED_1000baseT_Full | 2463 | | SUPPORTED_1000baseT_Full |
2449 | | SUPPORTED_Autoneg | SUPPORTED_TP; | 2464 | | SUPPORTED_Autoneg | SUPPORTED_TP; |
2450 | ecmd->port = PORT_TP; | 2465 | ecmd->port = PORT_TP; |
2451 | } else | 2466 | ecmd->speed = sky2->speed; |
2467 | } else { | ||
2468 | ecmd->speed = SPEED_1000; | ||
2452 | ecmd->port = PORT_FIBRE; | 2469 | ecmd->port = PORT_FIBRE; |
2470 | } | ||
2453 | 2471 | ||
2454 | ecmd->advertising = sky2->advertising; | 2472 | ecmd->advertising = sky2->advertising; |
2455 | ecmd->autoneg = sky2->autoneg; | 2473 | ecmd->autoneg = sky2->autoneg; |
2456 | ecmd->speed = sky2->speed; | ||
2457 | ecmd->duplex = sky2->duplex; | 2474 | ecmd->duplex = sky2->duplex; |
2458 | return 0; | 2475 | return 0; |
2459 | } | 2476 | } |
diff --git a/drivers/net/sky2.h b/drivers/net/sky2.h index a27194c874fc..be464636f07a 100644 --- a/drivers/net/sky2.h +++ b/drivers/net/sky2.h | |||
@@ -1318,6 +1318,14 @@ enum { | |||
1318 | }; | 1318 | }; |
1319 | 1319 | ||
1320 | /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ | 1320 | /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ |
1321 | /***** PHY_MARV_PHY_CTRL (page 1) 16 bit r/w Fiber Specific Ctrl *****/ | ||
1322 | enum { | ||
1323 | PHY_M_FIB_FORCE_LNK = 1<<10,/* Force Link Good */ | ||
1324 | PHY_M_FIB_SIGD_POL = 1<<9, /* SIGDET Polarity */ | ||
1325 | PHY_M_FIB_TX_DIS = 1<<3, /* Transmitter Disable */ | ||
1326 | }; | ||
1327 | |||
1328 | /* for Yukon-2 Gigabit Ethernet PHY (88E1112 only) */ | ||
1321 | /***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/ | 1329 | /***** PHY_MARV_PHY_CTRL (page 2) 16 bit r/w MAC Specific Ctrl *****/ |
1322 | enum { | 1330 | enum { |
1323 | PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */ | 1331 | PHY_M_MAC_MD_MSK = 7<<7, /* Bit 9.. 7: Mode Select Mask */ |
@@ -1880,7 +1888,7 @@ struct sky2_hw { | |||
1880 | int pm_cap; | 1888 | int pm_cap; |
1881 | u8 chip_id; | 1889 | u8 chip_id; |
1882 | u8 chip_rev; | 1890 | u8 chip_rev; |
1883 | u8 copper; | 1891 | u8 pmd_type; |
1884 | u8 ports; | 1892 | u8 ports; |
1885 | 1893 | ||
1886 | struct sky2_status_le *st_le; | 1894 | struct sky2_status_le *st_le; |
@@ -1892,6 +1900,11 @@ struct sky2_hw { | |||
1892 | wait_queue_head_t msi_wait; | 1900 | wait_queue_head_t msi_wait; |
1893 | }; | 1901 | }; |
1894 | 1902 | ||
1903 | static inline int sky2_is_copper(const struct sky2_hw *hw) | ||
1904 | { | ||
1905 | return !(hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P'); | ||
1906 | } | ||
1907 | |||
1895 | /* Register accessor for memory mapped device */ | 1908 | /* Register accessor for memory mapped device */ |
1896 | static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg) | 1909 | static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg) |
1897 | { | 1910 | { |