diff options
Diffstat (limited to 'drivers/net/skge.c')
-rw-r--r-- | drivers/net/skge.c | 93 |
1 files changed, 58 insertions, 35 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c index 39c6677dff5e..d476a3cc2e94 100644 --- a/drivers/net/skge.c +++ b/drivers/net/skge.c | |||
@@ -163,27 +163,46 @@ static void skge_wol_init(struct skge_port *skge) | |||
163 | { | 163 | { |
164 | struct skge_hw *hw = skge->hw; | 164 | struct skge_hw *hw = skge->hw; |
165 | int port = skge->port; | 165 | int port = skge->port; |
166 | enum pause_control save_mode; | 166 | u16 ctrl; |
167 | u32 ctrl; | ||
168 | 167 | ||
169 | /* Bring hardware out of reset */ | ||
170 | skge_write16(hw, B0_CTST, CS_RST_CLR); | 168 | skge_write16(hw, B0_CTST, CS_RST_CLR); |
171 | skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); | 169 | skge_write16(hw, SK_REG(port, GMAC_LINK_CTRL), GMLC_RST_CLR); |
172 | 170 | ||
173 | skge_write8(hw, SK_REG(port, GPHY_CTRL), GPC_RST_CLR); | 171 | /* Turn on Vaux */ |
174 | skge_write8(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); | 172 | skge_write8(hw, B0_POWER_CTRL, |
173 | PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); | ||
175 | 174 | ||
176 | /* Force to 10/100 skge_reset will re-enable on resume */ | 175 | /* WA code for COMA mode -- clear PHY reset */ |
177 | save_mode = skge->flow_control; | 176 | if (hw->chip_id == CHIP_ID_YUKON_LITE && |
178 | skge->flow_control = FLOW_MODE_SYMMETRIC; | 177 | hw->chip_rev >= CHIP_REV_YU_LITE_A3) { |
178 | u32 reg = skge_read32(hw, B2_GP_IO); | ||
179 | reg |= GP_DIR_9; | ||
180 | reg &= ~GP_IO_9; | ||
181 | skge_write32(hw, B2_GP_IO, reg); | ||
182 | } | ||
179 | 183 | ||
180 | ctrl = skge->advertising; | 184 | skge_write32(hw, SK_REG(port, GPHY_CTRL), |
181 | skge->advertising &= ~(ADVERTISED_1000baseT_Half|ADVERTISED_1000baseT_Full); | 185 | GPC_DIS_SLEEP | |
186 | GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | | ||
187 | GPC_ANEG_1 | GPC_RST_SET); | ||
182 | 188 | ||
183 | skge_phy_reset(skge); | 189 | skge_write32(hw, SK_REG(port, GPHY_CTRL), |
190 | GPC_DIS_SLEEP | | ||
191 | GPC_HWCFG_M_3 | GPC_HWCFG_M_2 | GPC_HWCFG_M_1 | GPC_HWCFG_M_0 | | ||
192 | GPC_ANEG_1 | GPC_RST_CLR); | ||
193 | |||
194 | skge_write32(hw, SK_REG(port, GMAC_CTRL), GMC_RST_CLR); | ||
195 | |||
196 | /* Force to 10/100 skge_reset will re-enable on resume */ | ||
197 | gm_phy_write(hw, port, PHY_MARV_AUNE_ADV, | ||
198 | PHY_AN_100FULL | PHY_AN_100HALF | | ||
199 | PHY_AN_10FULL | PHY_AN_10HALF| PHY_AN_CSMA); | ||
200 | /* no 1000 HD/FD */ | ||
201 | gm_phy_write(hw, port, PHY_MARV_1000T_CTRL, 0); | ||
202 | gm_phy_write(hw, port, PHY_MARV_CTRL, | ||
203 | PHY_CT_RESET | PHY_CT_SPS_LSB | PHY_CT_ANE | | ||
204 | PHY_CT_RE_CFG | PHY_CT_DUP_MD); | ||
184 | 205 | ||
185 | skge->flow_control = save_mode; | ||
186 | skge->advertising = ctrl; | ||
187 | 206 | ||
188 | /* Set GMAC to no flow control and auto update for speed/duplex */ | 207 | /* Set GMAC to no flow control and auto update for speed/duplex */ |
189 | gma_write16(hw, port, GM_GP_CTRL, | 208 | gma_write16(hw, port, GM_GP_CTRL, |
@@ -227,12 +246,10 @@ static int skge_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol) | |||
227 | struct skge_port *skge = netdev_priv(dev); | 246 | struct skge_port *skge = netdev_priv(dev); |
228 | struct skge_hw *hw = skge->hw; | 247 | struct skge_hw *hw = skge->hw; |
229 | 248 | ||
230 | if (wol->wolopts & wol_supported(hw)) | 249 | if (wol->wolopts & ~wol_supported(hw)) |
231 | return -EOPNOTSUPP; | 250 | return -EOPNOTSUPP; |
232 | 251 | ||
233 | skge->wol = wol->wolopts; | 252 | skge->wol = wol->wolopts; |
234 | if (!netif_running(dev)) | ||
235 | skge_wol_init(skge); | ||
236 | return 0; | 253 | return 0; |
237 | } | 254 | } |
238 | 255 | ||
@@ -2535,10 +2552,12 @@ static int skge_down(struct net_device *dev) | |||
2535 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); | 2552 | printk(KERN_INFO PFX "%s: disabling interface\n", dev->name); |
2536 | 2553 | ||
2537 | netif_stop_queue(dev); | 2554 | netif_stop_queue(dev); |
2555 | |||
2538 | if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) | 2556 | if (hw->chip_id == CHIP_ID_GENESIS && hw->phy_type == SK_PHY_XMAC) |
2539 | del_timer_sync(&skge->link_timer); | 2557 | del_timer_sync(&skge->link_timer); |
2540 | 2558 | ||
2541 | netif_poll_disable(dev); | 2559 | netif_poll_disable(dev); |
2560 | netif_carrier_off(dev); | ||
2542 | 2561 | ||
2543 | spin_lock_irq(&hw->hw_lock); | 2562 | spin_lock_irq(&hw->hw_lock); |
2544 | hw->intr_mask &= ~portmask[port]; | 2563 | hw->intr_mask &= ~portmask[port]; |
@@ -3765,21 +3784,6 @@ static void __devexit skge_remove(struct pci_dev *pdev) | |||
3765 | } | 3784 | } |
3766 | 3785 | ||
3767 | #ifdef CONFIG_PM | 3786 | #ifdef CONFIG_PM |
3768 | static int vaux_avail(struct pci_dev *pdev) | ||
3769 | { | ||
3770 | int pm_cap; | ||
3771 | |||
3772 | pm_cap = pci_find_capability(pdev, PCI_CAP_ID_PM); | ||
3773 | if (pm_cap) { | ||
3774 | u16 ctl; | ||
3775 | pci_read_config_word(pdev, pm_cap + PCI_PM_PMC, &ctl); | ||
3776 | if (ctl & PCI_PM_CAP_AUX_POWER) | ||
3777 | return 1; | ||
3778 | } | ||
3779 | return 0; | ||
3780 | } | ||
3781 | |||
3782 | |||
3783 | static int skge_suspend(struct pci_dev *pdev, pm_message_t state) | 3787 | static int skge_suspend(struct pci_dev *pdev, pm_message_t state) |
3784 | { | 3788 | { |
3785 | struct skge_hw *hw = pci_get_drvdata(pdev); | 3789 | struct skge_hw *hw = pci_get_drvdata(pdev); |
@@ -3801,10 +3805,6 @@ static int skge_suspend(struct pci_dev *pdev, pm_message_t state) | |||
3801 | wol |= skge->wol; | 3805 | wol |= skge->wol; |
3802 | } | 3806 | } |
3803 | 3807 | ||
3804 | if (wol && vaux_avail(pdev)) | ||
3805 | skge_write8(hw, B0_POWER_CTRL, | ||
3806 | PC_VAUX_ENA | PC_VCC_ENA | PC_VAUX_ON | PC_VCC_OFF); | ||
3807 | |||
3808 | skge_write32(hw, B0_IMSK, 0); | 3808 | skge_write32(hw, B0_IMSK, 0); |
3809 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); | 3809 | pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); |
3810 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); | 3810 | pci_set_power_state(pdev, pci_choose_state(pdev, state)); |
@@ -3850,6 +3850,28 @@ out: | |||
3850 | } | 3850 | } |
3851 | #endif | 3851 | #endif |
3852 | 3852 | ||
3853 | static void skge_shutdown(struct pci_dev *pdev) | ||
3854 | { | ||
3855 | struct skge_hw *hw = pci_get_drvdata(pdev); | ||
3856 | int i, wol = 0; | ||
3857 | |||
3858 | for (i = 0; i < hw->ports; i++) { | ||
3859 | struct net_device *dev = hw->dev[i]; | ||
3860 | struct skge_port *skge = netdev_priv(dev); | ||
3861 | |||
3862 | if (skge->wol) | ||
3863 | skge_wol_init(skge); | ||
3864 | wol |= skge->wol; | ||
3865 | } | ||
3866 | |||
3867 | pci_enable_wake(pdev, PCI_D3hot, wol); | ||
3868 | pci_enable_wake(pdev, PCI_D3cold, wol); | ||
3869 | |||
3870 | pci_disable_device(pdev); | ||
3871 | pci_set_power_state(pdev, PCI_D3hot); | ||
3872 | |||
3873 | } | ||
3874 | |||
3853 | static struct pci_driver skge_driver = { | 3875 | static struct pci_driver skge_driver = { |
3854 | .name = DRV_NAME, | 3876 | .name = DRV_NAME, |
3855 | .id_table = skge_id_table, | 3877 | .id_table = skge_id_table, |
@@ -3859,6 +3881,7 @@ static struct pci_driver skge_driver = { | |||
3859 | .suspend = skge_suspend, | 3881 | .suspend = skge_suspend, |
3860 | .resume = skge_resume, | 3882 | .resume = skge_resume, |
3861 | #endif | 3883 | #endif |
3884 | .shutdown = skge_shutdown, | ||
3862 | }; | 3885 | }; |
3863 | 3886 | ||
3864 | static int __init skge_init_module(void) | 3887 | static int __init skge_init_module(void) |