aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@osdl.org>2006-09-06 15:44:53 -0400
committerJeff Garzik <jeff@garzik.org>2006-09-13 13:27:44 -0400
commitb89165f2b75ba0a79eb5ed60924835cf3c54c51a (patch)
tree6ed4af3b2746c94416858753449f74310cb5407c /drivers
parent2eaba1a280b6380f5b1238c53ce62e4381fc5f97 (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')
-rw-r--r--drivers/net/sky2.c81
-rw-r--r--drivers/net/sky2.h15
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
1497static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux) 1513static 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)
2269static int sky2_reset(struct sky2_hw *hw) 2285static 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
2415static u32 sky2_supported_modes(const struct sky2_hw *hw) 2429static 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
2434static int sky2_get_settings(struct net_device *dev, struct ethtool_cmd *ecmd) 2449static 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 *****/
1322enum {
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 *****/
1322enum { 1330enum {
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
1903static 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 */
1896static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg) 1909static inline u32 sky2_read32(const struct sky2_hw *hw, unsigned reg)
1897{ 1910{