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.c98
1 files changed, 92 insertions, 6 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index 59cb9cd00ad2..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
287static 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
287static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port) 367static void sky2_gmac_reset(struct sky2_hw *hw, unsigned port)
288{ 368{
289 u16 reg; 369 u16 reg;
@@ -2786,6 +2866,10 @@ static int __devinit sky2_init(struct sky2_hw *hw)
2786 hw->flags = SKY2_HW_GIGABIT 2866 hw->flags = SKY2_HW_GIGABIT
2787 | SKY2_HW_NEWER_PHY 2867 | SKY2_HW_NEWER_PHY
2788 | 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;
2789 break; 2873 break;
2790 2874
2791 case CHIP_ID_YUKON_EX: 2875 case CHIP_ID_YUKON_EX:
@@ -2836,6 +2920,11 @@ static int __devinit sky2_init(struct sky2_hw *hw)
2836 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')
2837 hw->flags |= SKY2_HW_FIBRE_PHY; 2921 hw->flags |= SKY2_HW_FIBRE_PHY;
2838 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 }
2839 2928
2840 hw->ports = 1; 2929 hw->ports = 1;
2841 t8 = sky2_read8(hw, B2_Y2_HW_RES); 2930 t8 = sky2_read8(hw, B2_Y2_HW_RES);
@@ -4407,7 +4496,7 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
4407 4496
4408 pci_save_state(pdev); 4497 pci_save_state(pdev);
4409 pci_enable_wake(pdev, pci_choose_state(pdev, state), wol); 4498 pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
4410 pci_set_power_state(pdev, pci_choose_state(pdev, state)); 4499 sky2_power_state(hw, pci_choose_state(pdev, state));
4411 4500
4412 return 0; 4501 return 0;
4413} 4502}
@@ -4420,9 +4509,7 @@ static int sky2_resume(struct pci_dev *pdev)
4420 if (!hw) 4509 if (!hw)
4421 return 0; 4510 return 0;
4422 4511
4423 err = pci_set_power_state(pdev, PCI_D0); 4512 sky2_power_state(hw, PCI_D0);
4424 if (err)
4425 goto out;
4426 4513
4427 err = pci_restore_state(pdev); 4514 err = pci_restore_state(pdev);
4428 if (err) 4515 if (err)
@@ -4490,8 +4577,7 @@ static void sky2_shutdown(struct pci_dev *pdev)
4490 pci_enable_wake(pdev, PCI_D3cold, wol); 4577 pci_enable_wake(pdev, PCI_D3cold, wol);
4491 4578
4492 pci_disable_device(pdev); 4579 pci_disable_device(pdev);
4493 pci_set_power_state(pdev, PCI_D3hot); 4580 sky2_power_state(hw, PCI_D3hot);
4494
4495} 4581}
4496 4582
4497static struct pci_driver sky2_driver = { 4583static struct pci_driver sky2_driver = {