aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ucc_geth.c
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2009-08-27 03:35:57 -0400
committerDavid S. Miller <davem@davemloft.net>2009-08-31 00:51:47 -0400
commit2394905f67aeec5f9452f2881cbeb2b42009de0e (patch)
tree799de0b229027408b0f894cb9f50e36f4707f3d7 /drivers/net/ucc_geth.c
parentbf5aec2e79418adb42f1457152b427fd3d6316d9 (diff)
ucc_geth: Implement suspend/resume and Wake-On-LAN support
This patch implements suspend/resume and WOL support for UCC Ethernet driver. We support two wake up events: wake on PHY/link changes and wake on magic packet. In some CPUs (like MPC8569) QE shuts down during sleep, so magic packet detection is unusable, and also on resume we should fully reinitialize UCC structures. Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ucc_geth.c')
-rw-r--r--drivers/net/ucc_geth.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/drivers/net/ucc_geth.c b/drivers/net/ucc_geth.c
index d2ca61d3dffc..7fb96f33bade 100644
--- a/drivers/net/ucc_geth.c
+++ b/drivers/net/ucc_geth.c
@@ -3497,6 +3497,10 @@ static int ucc_geth_open(struct net_device *dev)
3497 napi_enable(&ugeth->napi); 3497 napi_enable(&ugeth->napi);
3498 netif_start_queue(dev); 3498 netif_start_queue(dev);
3499 3499
3500 device_set_wakeup_capable(&dev->dev,
3501 qe_alive_during_sleep() || ugeth->phydev->irq);
3502 device_set_wakeup_enable(&dev->dev, ugeth->wol_en);
3503
3500 return err; 3504 return err;
3501 3505
3502err: 3506err:
@@ -3561,6 +3565,85 @@ static void ucc_geth_timeout(struct net_device *dev)
3561 schedule_work(&ugeth->timeout_work); 3565 schedule_work(&ugeth->timeout_work);
3562} 3566}
3563 3567
3568
3569#ifdef CONFIG_PM
3570
3571static int ucc_geth_suspend(struct of_device *ofdev, pm_message_t state)
3572{
3573 struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
3574 struct ucc_geth_private *ugeth = netdev_priv(ndev);
3575
3576 if (!netif_running(ndev))
3577 return 0;
3578
3579 napi_disable(&ugeth->napi);
3580
3581 /*
3582 * Disable the controller, otherwise we'll wakeup on any network
3583 * activity.
3584 */
3585 ugeth_disable(ugeth, COMM_DIR_RX_AND_TX);
3586
3587 if (ugeth->wol_en & WAKE_MAGIC) {
3588 setbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
3589 setbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
3590 ucc_fast_enable(ugeth->uccf, COMM_DIR_RX_AND_TX);
3591 } else if (!(ugeth->wol_en & WAKE_PHY)) {
3592 phy_stop(ugeth->phydev);
3593 }
3594
3595 return 0;
3596}
3597
3598static int ucc_geth_resume(struct of_device *ofdev)
3599{
3600 struct net_device *ndev = dev_get_drvdata(&ofdev->dev);
3601 struct ucc_geth_private *ugeth = netdev_priv(ndev);
3602 int err;
3603
3604 if (!netif_running(ndev))
3605 return 0;
3606
3607 if (qe_alive_during_sleep()) {
3608 if (ugeth->wol_en & WAKE_MAGIC) {
3609 ucc_fast_disable(ugeth->uccf, COMM_DIR_RX_AND_TX);
3610 clrbits32(&ugeth->ug_regs->maccfg2, MACCFG2_MPE);
3611 clrbits32(ugeth->uccf->p_uccm, UCC_GETH_UCCE_MPD);
3612 }
3613 ugeth_enable(ugeth, COMM_DIR_RX_AND_TX);
3614 } else {
3615 /*
3616 * Full reinitialization is required if QE shuts down
3617 * during sleep.
3618 */
3619 ucc_geth_memclean(ugeth);
3620
3621 err = ucc_geth_init_mac(ugeth);
3622 if (err) {
3623 ugeth_err("%s: Cannot initialize MAC, aborting.",
3624 ndev->name);
3625 return err;
3626 }
3627 }
3628
3629 ugeth->oldlink = 0;
3630 ugeth->oldspeed = 0;
3631 ugeth->oldduplex = -1;
3632
3633 phy_stop(ugeth->phydev);
3634 phy_start(ugeth->phydev);
3635
3636 napi_enable(&ugeth->napi);
3637 netif_start_queue(ndev);
3638
3639 return 0;
3640}
3641
3642#else
3643#define ucc_geth_suspend NULL
3644#define ucc_geth_resume NULL
3645#endif
3646
3564static phy_interface_t to_phy_interface(const char *phy_connection_type) 3647static phy_interface_t to_phy_interface(const char *phy_connection_type)
3565{ 3648{
3566 if (strcasecmp(phy_connection_type, "mii") == 0) 3649 if (strcasecmp(phy_connection_type, "mii") == 0)
@@ -3852,6 +3935,8 @@ static struct of_platform_driver ucc_geth_driver = {
3852 .match_table = ucc_geth_match, 3935 .match_table = ucc_geth_match,
3853 .probe = ucc_geth_probe, 3936 .probe = ucc_geth_probe,
3854 .remove = ucc_geth_remove, 3937 .remove = ucc_geth_remove,
3938 .suspend = ucc_geth_suspend,
3939 .resume = ucc_geth_resume,
3855}; 3940};
3856 3941
3857static int __init ucc_geth_init(void) 3942static int __init ucc_geth_init(void)