aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
authorStephen Hemminger <shemminger@linux-foundation.org>2007-09-19 18:36:45 -0400
committerJeff Garzik <jeff@garzik.org>2007-09-20 15:23:00 -0400
commit05745c4ab1c58fbb6ab8e8d3a40e0e395d7e2b0e (patch)
tree1a42ee7e70c0ae31c93d1d673fabe9dd982cca81 /drivers/net/sky2.c
parentea76e63598eb312e5d33a782275be91038fc6df2 (diff)
sky2: fe+ chip support
Add support for newest Marvell chips. The Yukon FE plus chip is found in some not yet released laptops. Tested on hardware evaluation boards. This version of the patch is for 2.6.23. It supersedes the two previous patches that are sitting in netdev-2.6 (upstream branch). Signed-off-by: Stephen Hemminger <shemminger@linux-foundation.org> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c136
1 files changed, 103 insertions, 33 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 060951a8022b..d0e5875628e9 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -118,12 +118,15 @@ static const struct pci_device_id sky2_id_table[] = {
118 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */ 118 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4351) }, /* 88E8036 */
119 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */ 119 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4352) }, /* 88E8038 */
120 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */ 120 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4353) }, /* 88E8039 */
121 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4354) }, /* 88E8040 */
121 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */ 122 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4356) }, /* 88EC033 */
123 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x435A) }, /* 88E8048 */
122 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */ 124 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4360) }, /* 88E8052 */
123 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */ 125 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4361) }, /* 88E8050 */
124 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */ 126 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4362) }, /* 88E8053 */
125 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */ 127 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4363) }, /* 88E8055 */
126 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */ 128 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4364) }, /* 88E8056 */
129 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4365) }, /* 88E8070 */
127 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */ 130 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4366) }, /* 88EC036 */
128 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */ 131 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4367) }, /* 88EC032 */
129 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */ 132 { PCI_DEVICE(PCI_VENDOR_ID_MARVELL, 0x4368) }, /* 88EC034 */
@@ -147,6 +150,7 @@ static const char *yukon2_name[] = {
147 "Extreme", /* 0xb5 */ 150 "Extreme", /* 0xb5 */
148 "EC", /* 0xb6 */ 151 "EC", /* 0xb6 */
149 "FE", /* 0xb7 */ 152 "FE", /* 0xb7 */
153 "FE+", /* 0xb8 */
150}; 154};
151 155
152static void sky2_set_multicast(struct net_device *dev); 156static void sky2_set_multicast(struct net_device *dev);
@@ -331,7 +335,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
331 335
332 ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); 336 ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
333 if (sky2_is_copper(hw)) { 337 if (sky2_is_copper(hw)) {
334 if (hw->chip_id == CHIP_ID_YUKON_FE) { 338 if (!(hw->flags & SKY2_HW_GIGABIT)) {
335 /* enable automatic crossover */ 339 /* enable automatic crossover */
336 ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1; 340 ctrl |= PHY_M_PC_MDI_XMODE(PHY_M_PC_ENA_AUTO) >> 1;
337 } else { 341 } else {
@@ -450,7 +454,7 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
450 454
451 gma_write16(hw, port, GM_GP_CTRL, reg); 455 gma_write16(hw, port, GM_GP_CTRL, reg);
452 456
453 if (hw->chip_id != CHIP_ID_YUKON_FE) 457 if (hw->flags & SKY2_HW_GIGABIT)
454 gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000); 458 gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, ct1000);
455 459
456 gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv); 460 gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, adv);
@@ -474,6 +478,23 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
474 gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl); 478 gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
475 break; 479 break;
476 480
481 case CHIP_ID_YUKON_FE_P:
482 /* Enable Link Partner Next Page */
483 ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL);
484 ctrl |= PHY_M_PC_ENA_LIP_NP;
485
486 /* disable Energy Detect and enable scrambler */
487 ctrl &= ~(PHY_M_PC_ENA_ENE_DT | PHY_M_PC_DIS_SCRAMB);
488 gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl);
489
490 /* set LED2 -> ACT, LED1 -> LINK, LED0 -> SPEED */
491 ctrl = PHY_M_FELP_LED2_CTRL(LED_PAR_CTRL_ACT_BL) |
492 PHY_M_FELP_LED1_CTRL(LED_PAR_CTRL_LINK) |
493 PHY_M_FELP_LED0_CTRL(LED_PAR_CTRL_SPEED);
494
495 gm_phy_write(hw, port, PHY_MARV_FE_LED_PAR, ctrl);
496 break;
497
477 case CHIP_ID_YUKON_XL: 498 case CHIP_ID_YUKON_XL:
478 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR); 499 pg = gm_phy_read(hw, port, PHY_MARV_EXT_ADR);
479 500
@@ -543,7 +564,13 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port)
543 564
544 /* set page register to 0 */ 565 /* set page register to 0 */
545 gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); 566 gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0);
567 } else if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
568 hw->chip_rev == CHIP_REV_YU_FE2_A0) {
569 /* apply workaround for integrated resistors calibration */
570 gm_phy_write(hw, port, PHY_MARV_PAGE_ADDR, 17);
571 gm_phy_write(hw, port, PHY_MARV_PAGE_DATA, 0x3f60);
546 } else if (hw->chip_id != CHIP_ID_YUKON_EX) { 572 } else if (hw->chip_id != CHIP_ID_YUKON_EX) {
573 /* no effect on Yukon-XL */
547 gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl); 574 gm_phy_write(hw, port, PHY_MARV_LED_CTRL, ledctrl);
548 575
549 if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) { 576 if (sky2->autoneg == AUTONEG_DISABLE || sky2->speed == SPEED_100) {
@@ -664,25 +691,25 @@ static void sky2_wol_init(struct sky2_port *sky2)
664 691
665static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port) 692static void sky2_set_tx_stfwd(struct sky2_hw *hw, unsigned port)
666{ 693{
667 if (hw->chip_id == CHIP_ID_YUKON_EX && hw->chip_rev != CHIP_REV_YU_EX_A0) { 694 struct net_device *dev = hw->dev[port];
695
696 if (dev->mtu <= ETH_DATA_LEN)
668 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), 697 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
669 TX_STFW_ENA | 698 TX_JUMBO_DIS | TX_STFW_ENA);
670 (hw->dev[port]->mtu > ETH_DATA_LEN) ? TX_JUMBO_ENA : TX_JUMBO_DIS); 699
671 } else { 700 else if (hw->chip_id != CHIP_ID_YUKON_EC_U)
672 if (hw->dev[port]->mtu > ETH_DATA_LEN) { 701 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
673 /* set Tx GMAC FIFO Almost Empty Threshold */ 702 TX_STFW_ENA | TX_JUMBO_ENA);
674 sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR), 703 else {
675 (ECU_JUMBO_WM << 16) | ECU_AE_THR); 704 /* set Tx GMAC FIFO Almost Empty Threshold */
705 sky2_write32(hw, SK_REG(port, TX_GMF_AE_THR),
706 (ECU_JUMBO_WM << 16) | ECU_AE_THR);
676 707
677 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), 708 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
678 TX_JUMBO_ENA | TX_STFW_DIS); 709 TX_JUMBO_ENA | TX_STFW_DIS);
679 710
680 /* Can't do offload because of lack of store/forward */ 711 /* Can't do offload because of lack of store/forward */
681 hw->dev[port]->features &= ~(NETIF_F_TSO | NETIF_F_SG 712 dev->features &= ~(NETIF_F_TSO | NETIF_F_SG | NETIF_F_ALL_CSUM);
682 | NETIF_F_ALL_CSUM);
683 } else
684 sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T),
685 TX_JUMBO_DIS | TX_STFW_ENA);
686 } 713 }
687} 714}
688 715
@@ -768,7 +795,8 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
768 /* Configure Rx MAC FIFO */ 795 /* Configure Rx MAC FIFO */
769 sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR); 796 sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_CLR);
770 rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON; 797 rx_reg = GMF_OPER_ON | GMF_RX_F_FL_ON;
771 if (hw->chip_id == CHIP_ID_YUKON_EX) 798 if (hw->chip_id == CHIP_ID_YUKON_EX ||
799 hw->chip_id == CHIP_ID_YUKON_FE_P)
772 rx_reg |= GMF_RX_OVER_ON; 800 rx_reg |= GMF_RX_OVER_ON;
773 801
774 sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg); 802 sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), rx_reg);
@@ -777,7 +805,12 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port)
777 sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR); 805 sky2_write16(hw, SK_REG(port, RX_GMF_FL_MSK), GMR_FS_ANY_ERR);
778 806
779 /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */ 807 /* Set threshold to 0xa (64 bytes) + 1 to workaround pause bug */
780 sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), RX_GMF_FL_THR_DEF+1); 808 reg = RX_GMF_FL_THR_DEF + 1;
809 /* Another magic mystery workaround from sk98lin */
810 if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
811 hw->chip_rev == CHIP_REV_YU_FE2_A0)
812 reg = 0x178;
813 sky2_write16(hw, SK_REG(port, RX_GMF_FL_THR), reg);
781 814
782 /* Configure Tx MAC FIFO */ 815 /* Configure Tx MAC FIFO */
783 sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR); 816 sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_CLR);
@@ -1704,8 +1737,12 @@ static u16 sky2_phy_speed(const struct sky2_hw *hw, u16 aux)
1704 if (hw->flags & SKY2_HW_FIBRE_PHY) 1737 if (hw->flags & SKY2_HW_FIBRE_PHY)
1705 return SPEED_1000; 1738 return SPEED_1000;
1706 1739
1707 if (hw->chip_id == CHIP_ID_YUKON_FE) 1740 if (!(hw->flags & SKY2_HW_GIGABIT)) {
1708 return (aux & PHY_M_PS_SPEED_100) ? SPEED_100 : SPEED_10; 1741 if (aux & PHY_M_PS_SPEED_100)
1742 return SPEED_100;
1743 else
1744 return SPEED_10;
1745 }
1709 1746
1710 switch (aux & PHY_M_PS_SPEED_MSK) { 1747 switch (aux & PHY_M_PS_SPEED_MSK) {
1711 case PHY_M_PS_SPEED_1000: 1748 case PHY_M_PS_SPEED_1000:
@@ -1949,7 +1986,9 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1949 if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU) 1986 if (new_mtu < ETH_ZLEN || new_mtu > ETH_JUMBO_MTU)
1950 return -EINVAL; 1987 return -EINVAL;
1951 1988
1952 if (new_mtu > ETH_DATA_LEN && hw->chip_id == CHIP_ID_YUKON_FE) 1989 if (new_mtu > ETH_DATA_LEN &&
1990 (hw->chip_id == CHIP_ID_YUKON_FE ||
1991 hw->chip_id == CHIP_ID_YUKON_FE_P))
1953 return -EINVAL; 1992 return -EINVAL;
1954 1993
1955 if (!netif_running(dev)) { 1994 if (!netif_running(dev)) {
@@ -1966,7 +2005,7 @@ static int sky2_change_mtu(struct net_device *dev, int new_mtu)
1966 2005
1967 synchronize_irq(hw->pdev->irq); 2006 synchronize_irq(hw->pdev->irq);
1968 2007
1969 if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) 2008 if (!(hw->flags & SKY2_HW_RAMBUFFER))
1970 sky2_set_tx_stfwd(hw, port); 2009 sky2_set_tx_stfwd(hw, port);
1971 2010
1972 ctl = gma_read16(hw, port, GM_GP_CTRL); 2011 ctl = gma_read16(hw, port, GM_GP_CTRL);
@@ -2205,7 +2244,7 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
2205 } 2244 }
2206 2245
2207 /* This chip reports checksum status differently */ 2246 /* This chip reports checksum status differently */
2208 if (hw->chip_id == CHIP_ID_YUKON_EX) { 2247 if (hw->flags & SKY2_HW_NEW_LE) {
2209 if (sky2->rx_csum && 2248 if (sky2->rx_csum &&
2210 (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) && 2249 (le->css & (CSS_ISIPV4 | CSS_ISIPV6)) &&
2211 (le->css & CSS_TCPUDPCSOK)) 2250 (le->css & CSS_TCPUDPCSOK))
@@ -2246,8 +2285,14 @@ static int sky2_status_intr(struct sky2_hw *hw, int to_do)
2246 if (!sky2->rx_csum) 2285 if (!sky2->rx_csum)
2247 break; 2286 break;
2248 2287
2249 if (hw->chip_id == CHIP_ID_YUKON_EX) 2288 /* If this happens then driver assuming wrong format */
2289 if (unlikely(hw->flags & SKY2_HW_NEW_LE)) {
2290 if (net_ratelimit())
2291 printk(KERN_NOTICE "%s: unexpected"
2292 " checksum status\n",
2293 dev->name);
2250 break; 2294 break;
2295 }
2251 2296
2252 /* Both checksum counters are programmed to start at 2297 /* Both checksum counters are programmed to start at
2253 * the same offset, so unless there is a problem they 2298 * the same offset, so unless there is a problem they
@@ -2549,17 +2594,25 @@ static void sky2_netpoll(struct net_device *dev)
2549#endif 2594#endif
2550 2595
2551/* Chip internal frequency for clock calculations */ 2596/* Chip internal frequency for clock calculations */
2552static inline u32 sky2_mhz(const struct sky2_hw *hw) 2597static u32 sky2_mhz(const struct sky2_hw *hw)
2553{ 2598{
2554 switch (hw->chip_id) { 2599 switch (hw->chip_id) {
2555 case CHIP_ID_YUKON_EC: 2600 case CHIP_ID_YUKON_EC:
2556 case CHIP_ID_YUKON_EC_U: 2601 case CHIP_ID_YUKON_EC_U:
2557 case CHIP_ID_YUKON_EX: 2602 case CHIP_ID_YUKON_EX:
2558 return 125; /* 125 Mhz */ 2603 return 125;
2604
2559 case CHIP_ID_YUKON_FE: 2605 case CHIP_ID_YUKON_FE:
2560 return 100; /* 100 Mhz */ 2606 return 100;
2561 default: /* YUKON_XL */ 2607
2562 return 156; /* 156 Mhz */ 2608 case CHIP_ID_YUKON_FE_P:
2609 return 50;
2610
2611 case CHIP_ID_YUKON_XL:
2612 return 156;
2613
2614 default:
2615 BUG();
2563 } 2616 }
2564} 2617}
2565 2618
@@ -2623,6 +2676,12 @@ static int __devinit sky2_init(struct sky2_hw *hw)
2623 hw->flags = SKY2_HW_RAMBUFFER; 2676 hw->flags = SKY2_HW_RAMBUFFER;
2624 break; 2677 break;
2625 2678
2679 case CHIP_ID_YUKON_FE_P:
2680 hw->flags = SKY2_HW_NEWER_PHY
2681 | SKY2_HW_NEW_LE
2682 | SKY2_HW_AUTO_TX_SUM
2683 | SKY2_HW_ADV_POWER_CTL;
2684 break;
2626 default: 2685 default:
2627 dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n", 2686 dev_err(&hw->pdev->dev, "unsupported chip type 0x%x\n",
2628 hw->chip_id); 2687 hw->chip_id);
@@ -2827,7 +2886,9 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
2827 2886
2828 sky2->wol = wol->wolopts; 2887 sky2->wol = wol->wolopts;
2829 2888
2830 if (hw->chip_id == CHIP_ID_YUKON_EC_U || hw->chip_id == CHIP_ID_YUKON_EX) 2889 if (hw->chip_id == CHIP_ID_YUKON_EC_U ||
2890 hw->chip_id == CHIP_ID_YUKON_EX ||
2891 hw->chip_id == CHIP_ID_YUKON_FE_P)
2831 sky2_write32(hw, B0_CTST, sky2->wol 2892 sky2_write32(hw, B0_CTST, sky2->wol
2832 ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF); 2893 ? Y2_HW_WOL_ON : Y2_HW_WOL_OFF);
2833 2894
@@ -3820,6 +3881,13 @@ static __devinit struct net_device *sky2_init_netdev(struct sky2_hw *hw,
3820 sky2->hw = hw; 3881 sky2->hw = hw;
3821 sky2->msg_enable = netif_msg_init(debug, default_msg); 3882 sky2->msg_enable = netif_msg_init(debug, default_msg);
3822 3883
3884 /* This chip has hardware problems that generates
3885 * bogus PHY receive status so by default shut up the message.
3886 */
3887 if (hw->chip_id == CHIP_ID_YUKON_FE_P &&
3888 hw->chip_rev == CHIP_REV_YU_FE2_A0)
3889 sky2->msg_enable &= ~NETIF_MSG_RX_ERR;
3890
3823 /* Auto speed and flow control */ 3891 /* Auto speed and flow control */
3824 sky2->autoneg = AUTONEG_ENABLE; 3892 sky2->autoneg = AUTONEG_ENABLE;
3825 sky2->flow_mode = FC_BOTH; 3893 sky2->flow_mode = FC_BOTH;
@@ -4189,7 +4257,9 @@ static int sky2_resume(struct pci_dev *pdev)
4189 pci_enable_wake(pdev, PCI_D0, 0); 4257 pci_enable_wake(pdev, PCI_D0, 0);
4190 4258
4191 /* Re-enable all clocks */ 4259 /* Re-enable all clocks */
4192 if (hw->chip_id == CHIP_ID_YUKON_EX || hw->chip_id == CHIP_ID_YUKON_EC_U) 4260 if (hw->chip_id == CHIP_ID_YUKON_EX ||
4261 hw->chip_id == CHIP_ID_YUKON_EC_U ||
4262 hw->chip_id == CHIP_ID_YUKON_FE_P)
4193 sky2_pci_write32(hw, PCI_DEV_REG3, 0); 4263 sky2_pci_write32(hw, PCI_DEV_REG3, 0);
4194 4264
4195 sky2_reset(hw); 4265 sky2_reset(hw);