diff options
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r-- | drivers/net/sky2.c | 202 |
1 files changed, 171 insertions, 31 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 4b0f03358777..c83406f4f2a7 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c | |||
@@ -284,6 +284,86 @@ static void sky2_power_aux(struct sky2_hw *hw) | |||
284 | PC_VAUX_ON | PC_VCC_OFF)); | 284 | PC_VAUX_ON | PC_VCC_OFF)); |
285 | } | 285 | } |
286 | 286 | ||
287 | static void sky2_power_state(struct sky2_hw *hw, pci_power_t state) | ||
288 | { | ||
289 | u16 power_control = sky2_pci_read16(hw, hw->pm_cap + PCI_PM_CTRL); | ||
290 | int pex = pci_find_capability(hw->pdev, PCI_CAP_ID_EXP); | ||
291 | u32 reg; | ||
292 | |||
293 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
294 | |||
295 | switch (state) { | ||
296 | case PCI_D0: | ||
297 | break; | ||
298 | |||
299 | case PCI_D1: | ||
300 | power_control |= 1; | ||
301 | break; | ||
302 | |||
303 | case PCI_D2: | ||
304 | power_control |= 2; | ||
305 | break; | ||
306 | |||
307 | case PCI_D3hot: | ||
308 | case PCI_D3cold: | ||
309 | power_control |= 3; | ||
310 | if (hw->flags & SKY2_HW_ADV_POWER_CTL) { | ||
311 | /* additional power saving measurements */ | ||
312 | reg = sky2_pci_read32(hw, PCI_DEV_REG4); | ||
313 | |||
314 | /* set gating core clock for LTSSM in L1 state */ | ||
315 | reg |= P_PEX_LTSSM_STAT(P_PEX_LTSSM_L1_STAT) | | ||
316 | /* auto clock gated scheme controlled by CLKREQ */ | ||
317 | P_ASPM_A1_MODE_SELECT | | ||
318 | /* enable Gate Root Core Clock */ | ||
319 | P_CLK_GATE_ROOT_COR_ENA; | ||
320 | |||
321 | if (pex && (hw->flags & SKY2_HW_CLK_POWER)) { | ||
322 | /* enable Clock Power Management (CLKREQ) */ | ||
323 | u16 ctrl = sky2_pci_read16(hw, pex + PCI_EXP_DEVCTL); | ||
324 | |||
325 | ctrl |= PCI_EXP_DEVCTL_AUX_PME; | ||
326 | sky2_pci_write16(hw, pex + PCI_EXP_DEVCTL, ctrl); | ||
327 | } else | ||
328 | /* force CLKREQ Enable in Our4 (A1b only) */ | ||
329 | reg |= P_ASPM_FORCE_CLKREQ_ENA; | ||
330 | |||
331 | /* set Mask Register for Release/Gate Clock */ | ||
332 | sky2_pci_write32(hw, PCI_DEV_REG5, | ||
333 | P_REL_PCIE_EXIT_L1_ST | P_GAT_PCIE_ENTER_L1_ST | | ||
334 | P_REL_PCIE_RX_EX_IDLE | P_GAT_PCIE_RX_EL_IDLE | | ||
335 | P_REL_GPHY_LINK_UP | P_GAT_GPHY_LINK_DOWN); | ||
336 | } else | ||
337 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, Y2_ASF_CLK_HALT); | ||
338 | |||
339 | /* put CPU into reset state */ | ||
340 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, HCU_CCSR_ASF_RESET); | ||
341 | if (hw->chip_id == CHIP_ID_YUKON_SUPR && hw->chip_rev == CHIP_REV_YU_SU_A0) | ||
342 | /* put CPU into halt state */ | ||
343 | sky2_write8(hw, B28_Y2_ASF_STAT_CMD, HCU_CCSR_ASF_HALTED); | ||
344 | |||
345 | if (pex && !(hw->flags & SKY2_HW_RAM_BUFFER)) { | ||
346 | reg = sky2_pci_read32(hw, PCI_DEV_REG1); | ||
347 | /* force to PCIe L1 */ | ||
348 | reg |= PCI_FORCE_PEX_L1; | ||
349 | sky2_pci_write32(hw, PCI_DEV_REG1, reg); | ||
350 | } | ||
351 | break; | ||
352 | |||
353 | default: | ||
354 | dev_warn(&hw->pdev->dev, PFX "Invalid power state (%d) ", | ||
355 | state); | ||
356 | return; | ||
357 | } | ||
358 | |||
359 | power_control |= PCI_PM_CTRL_PME_ENABLE; | ||
360 | /* Finally, set the new power state. */ | ||
361 | sky2_pci_write32(hw, hw->pm_cap + PCI_PM_CTRL, power_control); | ||
362 | |||
363 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
364 | sky2_pci_read32(hw, B0_CTST); | ||
365 | } | ||
366 | |||
287 | static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) | 367 | static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) |
288 | { | 368 | { |
289 | u16 reg; | 369 | u16 reg; |
@@ -619,28 +699,71 @@ static void sky2_phy_init(struct sky2_hw *hw, unsigned port) | |||
619 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); | 699 | gm_phy_write(hw, port, PHY_MARV_INT_MASK, PHY_M_DEF_MSK); |
620 | } | 700 | } |
621 | 701 | ||
622 | static void sky2_phy_power(struct sky2_hw *hw, unsigned port, int onoff) | 702 | static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; |
703 | static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA }; | ||
704 | |||
705 | static void sky2_phy_power_up(struct sky2_hw *hw, unsigned port) | ||
623 | { | 706 | { |
624 | u32 reg1; | 707 | u32 reg1; |
625 | static const u32 phy_power[] = { PCI_Y2_PHY1_POWD, PCI_Y2_PHY2_POWD }; | ||
626 | static const u32 coma_mode[] = { PCI_Y2_PHY1_COMA, PCI_Y2_PHY2_COMA }; | ||
627 | 708 | ||
628 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | 709 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); |
629 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); | 710 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); |
630 | /* Turn on/off phy power saving */ | 711 | reg1 &= ~phy_power[port]; |
631 | if (onoff) | ||
632 | reg1 &= ~phy_power[port]; | ||
633 | else | ||
634 | reg1 |= phy_power[port]; | ||
635 | 712 | ||
636 | if (onoff && hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) | 713 | if (hw->chip_id == CHIP_ID_YUKON_XL && hw->chip_rev > 1) |
637 | reg1 |= coma_mode[port]; | 714 | reg1 |= coma_mode[port]; |
638 | 715 | ||
639 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); | 716 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); |
640 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | 717 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); |
641 | sky2_pci_read32(hw, PCI_DEV_REG1); | 718 | sky2_pci_read32(hw, PCI_DEV_REG1); |
719 | } | ||
720 | |||
721 | static void sky2_phy_power_down(struct sky2_hw *hw, unsigned port) | ||
722 | { | ||
723 | u32 reg1; | ||
724 | u16 ctrl; | ||
725 | |||
726 | /* release GPHY Control reset */ | ||
727 | sky2_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); | ||
728 | |||
729 | /* release GMAC reset */ | ||
730 | sky2_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); | ||
642 | 731 | ||
643 | udelay(100); | 732 | if (hw->flags & SKY2_HW_NEWER_PHY) { |
733 | /* select page 2 to access MAC control register */ | ||
734 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 2); | ||
735 | |||
736 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
737 | /* allow GMII Power Down */ | ||
738 | ctrl &= ~PHY_M_MAC_GMIF_PUP; | ||
739 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
740 | |||
741 | /* set page register back to 0 */ | ||
742 | gm_phy_write(hw, port, PHY_MARV_EXT_ADR, 0); | ||
743 | } | ||
744 | |||
745 | /* setup General Purpose Control Register */ | ||
746 | gma_write16(hw, port, GM_GP_CTRL, | ||
747 | GM_GPCR_FL_PASS | GM_GPCR_SPEED_100 | GM_GPCR_AU_ALL_DIS); | ||
748 | |||
749 | if (hw->chip_id != CHIP_ID_YUKON_EC) { | ||
750 | if (hw->chip_id == CHIP_ID_YUKON_EC_U) { | ||
751 | ctrl = gm_phy_read(hw, port, PHY_MARV_PHY_CTRL); | ||
752 | |||
753 | /* enable Power Down */ | ||
754 | ctrl |= PHY_M_PC_POW_D_ENA; | ||
755 | gm_phy_write(hw, port, PHY_MARV_PHY_CTRL, ctrl); | ||
756 | } | ||
757 | |||
758 | /* set IEEE compatible Power Down Mode (dev. #4.99) */ | ||
759 | gm_phy_write(hw, port, PHY_MARV_CTRL, PHY_CT_PDOWN); | ||
760 | } | ||
761 | |||
762 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_ON); | ||
763 | reg1 = sky2_pci_read32(hw, PCI_DEV_REG1); | ||
764 | reg1 |= phy_power[port]; /* set PHY to PowerDown/COMA Mode */ | ||
765 | sky2_pci_write32(hw, PCI_DEV_REG1, reg1); | ||
766 | sky2_write8(hw, B2_TST_CTRL1, TST_CFG_WRITE_OFF); | ||
644 | } | 767 | } |
645 | 768 | ||
646 | /* Force a renegotiation */ | 769 | /* Force a renegotiation */ |
@@ -675,8 +798,11 @@ static void sky2_wol_init(struct sky2_port *sky2) | |||
675 | 798 | ||
676 | sky2->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); | 799 | sky2->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); |
677 | sky2->flow_mode = FC_NONE; | 800 | sky2->flow_mode = FC_NONE; |
678 | sky2_phy_power(hw, port, 1); | 801 | |
679 | sky2_phy_reinit(sky2); | 802 | spin_lock_bh(&sky2->phy_lock); |
803 | sky2_phy_power_up(hw, port); | ||
804 | sky2_phy_init(hw, port); | ||
805 | spin_unlock_bh(&sky2->phy_lock); | ||
680 | 806 | ||
681 | sky2->flow_mode = save_mode; | 807 | sky2->flow_mode = save_mode; |
682 | sky2->advertising = ctrl; | 808 | sky2->advertising = ctrl; |
@@ -781,6 +907,7 @@ static void sky2_mac_init(struct sky2_hw *hw, unsigned port) | |||
781 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); | 907 | sky2_write8(hw, SK_REG(port, GMAC_IRQ_MSK), GMAC_DEF_MSK); |
782 | 908 | ||
783 | spin_lock_bh(&sky2->phy_lock); | 909 | spin_lock_bh(&sky2->phy_lock); |
910 | sky2_phy_power_up(hw, port); | ||
784 | sky2_phy_init(hw, port); | 911 | sky2_phy_init(hw, port); |
785 | spin_unlock_bh(&sky2->phy_lock); | 912 | spin_unlock_bh(&sky2->phy_lock); |
786 | 913 | ||
@@ -1159,17 +1286,9 @@ static int sky2_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) | |||
1159 | } | 1286 | } |
1160 | 1287 | ||
1161 | #ifdef SKY2_VLAN_TAG_USED | 1288 | #ifdef SKY2_VLAN_TAG_USED |
1162 | static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) | 1289 | static void sky2_set_vlan_mode(struct sky2_hw *hw, u16 port, bool onoff) |
1163 | { | 1290 | { |
1164 | struct sky2_port *sky2 = netdev_priv(dev); | 1291 | if (onoff) { |
1165 | struct sky2_hw *hw = sky2->hw; | ||
1166 | u16 port = sky2->port; | ||
1167 | |||
1168 | netif_tx_lock_bh(dev); | ||
1169 | napi_disable(&hw->napi); | ||
1170 | |||
1171 | sky2->vlgrp = grp; | ||
1172 | if (grp) { | ||
1173 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), | 1292 | sky2_write32(hw, SK_REG(port, RX_GMF_CTRL_T), |
1174 | RX_VLAN_STRIP_ON); | 1293 | RX_VLAN_STRIP_ON); |
1175 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | 1294 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), |
@@ -1180,6 +1299,19 @@ static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp | |||
1180 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), | 1299 | sky2_write32(hw, SK_REG(port, TX_GMF_CTRL_T), |
1181 | TX_VLAN_TAG_OFF); | 1300 | TX_VLAN_TAG_OFF); |
1182 | } | 1301 | } |
1302 | } | ||
1303 | |||
1304 | static void sky2_vlan_rx_register(struct net_device *dev, struct vlan_group *grp) | ||
1305 | { | ||
1306 | struct sky2_port *sky2 = netdev_priv(dev); | ||
1307 | struct sky2_hw *hw = sky2->hw; | ||
1308 | u16 port = sky2->port; | ||
1309 | |||
1310 | netif_tx_lock_bh(dev); | ||
1311 | napi_disable(&hw->napi); | ||
1312 | |||
1313 | sky2->vlgrp = grp; | ||
1314 | sky2_set_vlan_mode(hw, port, grp != NULL); | ||
1183 | 1315 | ||
1184 | sky2_read32(hw, B0_Y2_SP_LISR); | 1316 | sky2_read32(hw, B0_Y2_SP_LISR); |
1185 | napi_enable(&hw->napi); | 1317 | napi_enable(&hw->napi); |
@@ -1380,8 +1512,6 @@ static int sky2_up(struct net_device *dev) | |||
1380 | if (!sky2->rx_ring) | 1512 | if (!sky2->rx_ring) |
1381 | goto err_out; | 1513 | goto err_out; |
1382 | 1514 | ||
1383 | sky2_phy_power(hw, port, 1); | ||
1384 | |||
1385 | sky2_mac_init(hw, port); | 1515 | sky2_mac_init(hw, port); |
1386 | 1516 | ||
1387 | /* Register is number of 4K blocks on internal RAM buffer. */ | 1517 | /* Register is number of 4K blocks on internal RAM buffer. */ |
@@ -1418,6 +1548,10 @@ static int sky2_up(struct net_device *dev) | |||
1418 | sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, | 1548 | sky2_prefetch_init(hw, txqaddr[port], sky2->tx_le_map, |
1419 | TX_RING_SIZE - 1); | 1549 | TX_RING_SIZE - 1); |
1420 | 1550 | ||
1551 | #ifdef SKY2_VLAN_TAG_USED | ||
1552 | sky2_set_vlan_mode(hw, port, sky2->vlgrp != NULL); | ||
1553 | #endif | ||
1554 | |||
1421 | err = sky2_rx_start(sky2); | 1555 | err = sky2_rx_start(sky2); |
1422 | if (err) | 1556 | if (err) |
1423 | goto err_out; | 1557 | goto err_out; |
@@ -1758,7 +1892,7 @@ static int sky2_down(struct net_device *dev) | |||
1758 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); | 1892 | sky2_write8(hw, SK_REG(port, RX_GMF_CTRL_T), GMF_RST_SET); |
1759 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); | 1893 | sky2_write8(hw, SK_REG(port, TX_GMF_CTRL_T), GMF_RST_SET); |
1760 | 1894 | ||
1761 | sky2_phy_power(hw, port, 0); | 1895 | sky2_phy_power_down(hw, port); |
1762 | 1896 | ||
1763 | netif_carrier_off(dev); | 1897 | netif_carrier_off(dev); |
1764 | 1898 | ||
@@ -2732,6 +2866,10 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2732 | hw->flags = SKY2_HW_GIGABIT | 2866 | hw->flags = SKY2_HW_GIGABIT |
2733 | | SKY2_HW_NEWER_PHY | 2867 | | SKY2_HW_NEWER_PHY |
2734 | | SKY2_HW_ADV_POWER_CTL; | 2868 | | SKY2_HW_ADV_POWER_CTL; |
2869 | |||
2870 | /* check for Rev. A1 dev 4200 */ | ||
2871 | if (sky2_read16(hw, Q_ADDR(Q_XA1, Q_WM)) == 0) | ||
2872 | hw->flags |= SKY2_HW_CLK_POWER; | ||
2735 | break; | 2873 | break; |
2736 | 2874 | ||
2737 | case CHIP_ID_YUKON_EX: | 2875 | case CHIP_ID_YUKON_EX: |
@@ -2782,6 +2920,11 @@ static int __devinit sky2_init(struct sky2_hw *hw) | |||
2782 | if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') | 2920 | if (hw->pmd_type == 'L' || hw->pmd_type == 'S' || hw->pmd_type == 'P') |
2783 | hw->flags |= SKY2_HW_FIBRE_PHY; | 2921 | hw->flags |= SKY2_HW_FIBRE_PHY; |
2784 | 2922 | ||
2923 | hw->pm_cap = pci_find_capability(hw->pdev, PCI_CAP_ID_PM); | ||
2924 | if (hw->pm_cap == 0) { | ||
2925 | dev_err(&hw->pdev->dev, "cannot find PowerManagement capability\n"); | ||
2926 | return -EIO; | ||
2927 | } | ||
2785 | 2928 | ||
2786 | hw->ports = 1; | 2929 | hw->ports = 1; |
2787 | t8 = sky2_read8(hw, B2_Y2_HW_RES); | 2930 | t8 = sky2_read8(hw, B2_Y2_HW_RES); |
@@ -4353,7 +4496,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) | |||
4353 | 4496 | ||
4354 | pci_save_state(pdev); | 4497 | pci_save_state(pdev); |
4355 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); | 4498 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); |
4356 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 4499 | sky2_power_state(hw, pci_choose_state(pdev, state)); |
4357 | 4500 | ||
4358 | return 0; | 4501 | return 0; |
4359 | } | 4502 | } |
@@ -4366,9 +4509,7 @@ static int sky2_resume(struct pci_dev *pdev) | |||
4366 | if (!hw) | 4509 | if (!hw) |
4367 | return 0; | 4510 | return 0; |
4368 | 4511 | ||
4369 | err = pci_set_power_state(pdev, PCI_D0); | 4512 | sky2_power_state(hw, PCI_D0); |
4370 | if (err) | ||
4371 | goto out; | ||
4372 | 4513 | ||
4373 | err = pci_restore_state(pdev); | 4514 | err = pci_restore_state(pdev); |
4374 | if (err) | 4515 | if (err) |
@@ -4436,8 +4577,7 @@ static void sky2_shutdown(struct pci_dev *pdev) | |||
4436 | pci_enable_wake(pdev, PCI_D3cold, wol); | 4577 | pci_enable_wake(pdev, PCI_D3cold, wol); |
4437 | 4578 | ||
4438 | pci_disable_device(pdev); | 4579 | pci_disable_device(pdev); |
4439 | pci_set_power_state(pdev, PCI_D3hot); | 4580 | sky2_power_state(hw, PCI_D3hot); |
4440 | |||
4441 | } | 4581 | } |
4442 | 4582 | ||
4443 | static struct pci_driver sky2_driver = { | 4583 | static struct pci_driver sky2_driver = { |