aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c123
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)
289static void sky2_phy_init(struct sky2_hw *hw, unsigned port) 289static 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
2904static int sky2_get_coalesce(struct net_device *dev, 2865static int sky2_get_coalesce(struct net_device *dev,