diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 123 |
1 files changed, 42 insertions, 81 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 7ce0663baf4..a3a4ab26044 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -289,7 +289,7 @@ static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) | |||
289 | static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | 289 | static void sky2_phy_init(struct sky2_hw *hw, unsigned port) |
290 | { | 290 | { |
291 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); | 291 | struct sky2_port *sky2 = netdev_priv(hw->dev[port]); |
292 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover; | 292 | u16 ctrl, ct1000, adv, pg, ledctrl, ledover, reg; |
293 | 293 | ||
294 | if (sky2->autoneg == AUTONEG_ENABLE && | 294 | if (sky2->autoneg == AUTONEG_ENABLE && |
295 | !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { | 295 | !(hw->chip_id == CHIP_ID_YUKON_XL || hw->chip_id == CHIP_ID_YUKON_EC_U)) { |
@@ -358,6 +358,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
358 | ctrl = 0; | 358 | ctrl = 0; |
359 | ct1000 = 0; | 359 | ct1000 = 0; |
360 | adv = PHY_AN_CSMA; | 360 | adv = PHY_AN_CSMA; |
361 | reg = 0; | ||
361 | 362 | ||
362 | if (sky2->autoneg == AUTONEG_ENABLE) { | 363 | if (sky2->autoneg == AUTONEG_ENABLE) { |
363 | if (hw->copper) { | 364 | if (hw->copper) { |
@@ -390,21 +391,46 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
390 | /* forced speed/duplex settings */ | 391 | /* forced speed/duplex settings */ |
391 | ct1000 = PHY_M_1000C_MSE; | 392 | ct1000 = PHY_M_1000C_MSE; |
392 | 393 | ||
393 | if (sky2->duplex == DUPLEX_FULL) | 394 | /* Disable auto update for duplex flow control and speed */ |
394 | ctrl |= PHY_CT_DUP_MD; | 395 | reg |= GM_GPCR_AU_ALL_DIS; |
395 | 396 | ||
396 | switch (sky2->speed) { | 397 | switch (sky2->speed) { |
397 | case SPEED_1000: | 398 | case SPEED_1000: |
398 | ctrl |= PHY_CT_SP1000; | 399 | ctrl |= PHY_CT_SP1000; |
400 | reg |= GM_GPCR_SPEED_1000; | ||
399 | break; | 401 | break; |
400 | case SPEED_100: | 402 | case SPEED_100: |
401 | ctrl |= PHY_CT_SP100; | 403 | ctrl |= PHY_CT_SP100; |
404 | reg |= GM_GPCR_SPEED_100; | ||
402 | break; | 405 | break; |
403 | } | 406 | } |
404 | 407 | ||
408 | if (sky2->duplex == DUPLEX_FULL) { | ||
409 | reg |= GM_GPCR_DUP_FULL; | ||
410 | ctrl |= PHY_CT_DUP_MD; | ||
411 | } else if (sky2->speed != SPEED_1000 && hw->chip_id != CHIP_ID_YUKON_EC_U) { | ||
412 | /* Turn off flow control for 10/100mbps */ | ||
413 | sky2->rx_pause = 0; | ||
414 | sky2->tx_pause = 0; | ||
415 | } | ||
416 | |||
417 | if (!sky2->rx_pause) | ||
418 | reg |= GM_GPCR_FC_RX_DIS; | ||
419 | |||
420 | if (!sky2->tx_pause) | ||
421 | reg |= GM_GPCR_FC_TX_DIS; | ||
422 | |||
423 | /* Forward pause packets to GMAC? */ | ||
424 | if (sky2->tx_pause || sky2->rx_pause) | ||
425 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); | ||
426 | else | ||
427 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | ||
428 | |||
405 | ctrl |= PHY_CT_RESET; | 429 | ctrl |= PHY_CT_RESET; |
406 | } | 430 | } |
407 | 431 | ||
432 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
433 | |||
408 | if (hw->chip_id != CHIP_ID_YUKON_FE) | 434 | if (hw->chip_id != CHIP_ID_YUKON_FE) |
409 | gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); | 435 | gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); |
410 | 436 | ||
@@ -508,6 +534,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
508 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); | 534 | gm_phy_write(hw, port, PHY_MARV_LED_OVER, ledover); |
509 | 535 | ||
510 | } | 536 | } |
537 | |||
511 | /* Enable phy interrupt on auto-negotiation complete (or link up) */ | 538 | /* Enable phy interrupt on auto-negotiation complete (or link up) */ |
512 | if (sky2->autoneg == AUTONEG_ENABLE) | 539 | if (sky2->autoneg == AUTONEG_ENABLE) |
513 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); | 540 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_IS_AN_COMPL); |
@@ -570,49 +597,11 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
570 | gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0); | 597 | gm_phy_read(hw, 1, PHY_MARV_INT_MASK) != 0); |
571 | } | 598 | } |
572 | 599 | ||
573 | if (sky2->autoneg == AUTONEG_DISABLE) { | ||
574 | reg = gma_read16(hw, port, GM_GP_CTRL); | ||
575 | reg |= GM_GPCR_AU_ALL_DIS; | ||
576 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
577 | gma_read16(hw, port, GM_GP_CTRL); | ||
578 | |||
579 | switch (sky2->speed) { | ||
580 | case SPEED_1000: | ||
581 | reg &= ~GM_GPCR_SPEED_100; | ||
582 | reg |= GM_GPCR_SPEED_1000; | ||
583 | break; | ||
584 | case SPEED_100: | ||
585 | reg &= ~GM_GPCR_SPEED_1000; | ||
586 | reg |= GM_GPCR_SPEED_100; | ||
587 | break; | ||
588 | case SPEED_10: | ||
589 | reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100); | ||
590 | break; | ||
591 | } | ||
592 | |||
593 | if (sky2->duplex == DUPLEX_FULL) | ||
594 | reg |= GM_GPCR_DUP_FULL; | ||
595 | |||
596 | /* turn off pause in 10/100mbps half duplex */ | ||
597 | else if (sky2->speed != SPEED_1000 && | ||
598 | hw->chip_id != CHIP_ID_YUKON_EC_U) | ||
599 | sky2->tx_pause = sky2->rx_pause = 0; | ||
600 | } else | ||
601 | reg = GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100 | GM_GPCR_DUP_FULL; | ||
602 | |||
603 | if (!sky2->tx_pause && !sky2->rx_pause) { | ||
604 | sky2_write32(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | ||
605 | reg |= | ||
606 | GM_GPCR_FC_TX_DIS | GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; | ||
607 | } else if (sky2->tx_pause && !sky2->rx_pause) { | ||
608 | /* disable Rx flow-control */ | ||
609 | reg |= GM_GPCR_FC_RX_DIS | GM_GPCR_AU_FCT_DIS; | ||
610 | } | ||
611 | |||
612 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
613 | |||
614 | sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); | 600 | sky2_read16(hw, SK_REG(port, GMAC_IRQ_SRC)); |
615 | 601 | ||
602 | /* Enable Transmit FIFO Underrun */ | ||
603 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); | ||
604 | |||
616 | spin_lock_bh(&sky2->phy_lock); | 605 | spin_lock_bh(&sky2->phy_lock); |
617 | sky2_phy_init(hw, port); | 606 | sky2_phy_init(hw, port); |
618 | spin_unlock_bh(&sky2->phy_lock); | 607 | spin_unlock_bh(&sky2->phy_lock); |
@@ -1529,40 +1518,10 @@ static void sky2_link_up(struct sky2_port *sky2) | |||
1529 | unsigned port = sky2->port; | 1518 | unsigned port = sky2->port; |
1530 | u16 reg; | 1519 | u16 reg; |
1531 | 1520 | ||
1532 | /* Enable Transmit FIFO Underrun */ | ||
1533 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); | ||
1534 | |||
1535 | reg = gma_read16(hw, port, GM_GP_CTRL); | ||
1536 | if (sky2->autoneg == AUTONEG_DISABLE) { | ||
1537 | reg |= GM_GPCR_AU_ALL_DIS; | ||
1538 | |||
1539 | /* Is write/read necessary? Copied from sky2_mac_init */ | ||
1540 | gma_write16(hw, port, GM_GP_CTRL, reg); | ||
1541 | gma_read16(hw, port, GM_GP_CTRL); | ||
1542 | |||
1543 | switch (sky2->speed) { | ||
1544 | case SPEED_1000: | ||
1545 | reg &= ~GM_GPCR_SPEED_100; | ||
1546 | reg |= GM_GPCR_SPEED_1000; | ||
1547 | break; | ||
1548 | case SPEED_100: | ||
1549 | reg &= ~GM_GPCR_SPEED_1000; | ||
1550 | reg |= GM_GPCR_SPEED_100; | ||
1551 | break; | ||
1552 | case SPEED_10: | ||
1553 | reg &= ~(GM_GPCR_SPEED_1000 | GM_GPCR_SPEED_100); | ||
1554 | break; | ||
1555 | } | ||
1556 | } else | ||
1557 | reg &= ~GM_GPCR_AU_ALL_DIS; | ||
1558 | |||
1559 | if (sky2->duplex == DUPLEX_FULL || sky2->autoneg == AUTONEG_ENABLE) | ||
1560 | reg |= GM_GPCR_DUP_FULL; | ||
1561 | |||
1562 | /* enable Rx/Tx */ | 1521 | /* enable Rx/Tx */ |
1522 | reg = gma_read16(hw, port, GM_GP_CTRL); | ||
1563 | reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; | 1523 | reg |= GM_GPCR_RX_ENA | GM_GPCR_TX_ENA; |
1564 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1524 | gma_write16(hw, port, GM_GP_CTRL, reg); |
1565 | gma_read16(hw, port, GM_GP_CTRL); | ||
1566 | 1525 | ||
1567 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); | 1526 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); |
1568 | 1527 | ||
@@ -1616,7 +1575,6 @@ static void sky2_link_down(struct sky2_port *sky2) | |||
1616 | reg = gma_read16(hw, port, GM_GP_CTRL); | 1575 | reg = gma_read16(hw, port, GM_GP_CTRL); |
1617 | reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); | 1576 | reg &= ~(GM_GPCR_RX_ENA | GM_GPCR_TX_ENA); |
1618 | gma_write16(hw, port, GM_GP_CTRL, reg); | 1577 | gma_write16(hw, port, GM_GP_CTRL, reg); |
1619 | gma_read16(hw, port, GM_GP_CTRL); /* PCI post */ | ||
1620 | 1578 | ||
1621 | if (sky2->rx_pause && !sky2->tx_pause) { | 1579 | if (sky2->rx_pause && !sky2->tx_pause) { |
1622 | /* restore Asymmetric Pause bit */ | 1580 | /* restore Asymmetric Pause bit */ |
@@ -1633,6 +1591,7 @@ static void sky2_link_down(struct sky2_port *sky2) | |||
1633 | 1591 | ||
1634 | if (netif_msg_link(sky2)) | 1592 | if (netif_msg_link(sky2)) |
1635 | printk(KERN_INFO PFX "%s: Link is down.\n", sky2->netdev->name); | 1593 | printk(KERN_INFO PFX "%s: Link is down.\n", sky2->netdev->name); |
1594 | |||
1636 | sky2_phy_init(hw, port); | 1595 | sky2_phy_init(hw, port); |
1637 | } | 1596 | } |
1638 | 1597 | ||
@@ -1673,8 +1632,11 @@ static int sky2_autoneg_done(struct sky2_port *sky2, u16 aux) | |||
1673 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; | 1632 | sky2->rx_pause = (aux & PHY_M_PS_RX_P_EN) != 0; |
1674 | sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0; | 1633 | sky2->tx_pause = (aux & PHY_M_PS_TX_P_EN) != 0; |
1675 | 1634 | ||
1676 | if ((sky2->tx_pause || sky2->rx_pause) | 1635 | if (sky2->duplex == DUPLEX_HALF && sky2->speed != SPEED_1000 |
1677 | && !(sky2->speed < SPEED_1000 && sky2->duplex == DUPLEX_HALF)) | 1636 | && hw->chip_id != CHIP_ID_YUKON_EC_U) |
1637 | sky2->rx_pause = sky2->tx_pause = 0; | ||
1638 | |||
1639 | if (sky2->rx_pause || sky2->tx_pause) | ||
1678 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); | 1640 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_ON); |
1679 | else | 1641 | else |
1680 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); | 1642 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_PAUSE_OFF); |
@@ -1700,7 +1662,7 @@ static void sky2_phy_intr(struct sky2_hw *hw, unsigned port) | |||
1700 | printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", | 1662 | printk(KERN_INFO PFX "%s: phy interrupt status 0x%x 0x%x\n", |
1701 | sky2->netdev->name, istatus, phystat); | 1663 | sky2->netdev->name, istatus, phystat); |
1702 | 1664 | ||
1703 | if (istatus & PHY_M_IS_AN_COMPL) { | 1665 | if (sky2->autoneg == AUTONEG_ENABLE && (istatus & PHY_M_IS_AN_COMPL)) { |
1704 | if (sky2_autoneg_done(sky2, phystat) == 0) | 1666 | if (sky2_autoneg_done(sky2, phystat) == 0) |
1705 | sky2_link_up(sky2); | 1667 | sky2_link_up(sky2); |
1706 | goto out; | 1668 | goto out; |
@@ -2890,7 +2852,6 @@ static int sky2_set_pauseparam(struct net_device *dev, | |||
2890 | struct ethtool_pauseparam *ecmd) | 2852 | struct ethtool_pauseparam *ecmd) |
2891 | { | 2853 | { |
2892 | struct sky2_port *sky2 = netdev_priv(dev); | 2854 | struct sky2_port *sky2 = netdev_priv(dev); |
2893 | int err = 0; | ||
2894 | 2855 | ||
2895 | sky2->autoneg = ecmd->autoneg; | 2856 | sky2->autoneg = ecmd->autoneg; |
2896 | sky2->tx_pause = ecmd->tx_pause != 0; | 2857 | sky2->tx_pause = ecmd->tx_pause != 0; |
@@ -2898,7 +2859,7 @@ static int sky2_set_pauseparam(struct net_device *dev, | |||
2898 | 2859 | ||
2899 | sky2_phy_reinit(sky2); | 2860 | sky2_phy_reinit(sky2); |
2900 | 2861 | ||
2901 | return err; | 2862 | return 0; |
2902 | } | 2863 | } |
2903 | 2864 | ||
2904 | static int sky2_get_coalesce(struct net_device *dev, | 2865 | static int sky2_get_coalesce(struct net_device *dev, |