diff options
author | Daniel Mack <daniel@caiaq.de> | 2009-05-05 15:22:53 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-05-05 15:22:53 -0400 |
commit | b6907b0c705b6db221f937b4d343e2a6b280c8c5 (patch) | |
tree | 1cc95afd264bc7ca29fb7ea4f1e32a35aff64fe8 /drivers/net/smsc911x.c | |
parent | c7ae011dc8306d982c25fb4f679752e790a08dc4 (diff) |
net: smsc911x: add power management functions
This adds a power management implementation for smsc911x.c which assumes
the chips remains powered during suspend. The device is put in its D1
power saving mode.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Acked-by: Steve Glendinning <steve.glendinning@smsc.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/smsc911x.c')
-rw-r--r-- | drivers/net/smsc911x.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c index 5113b26fc2d9..9a8528c5bb5e 100644 --- a/drivers/net/smsc911x.c +++ b/drivers/net/smsc911x.c | |||
@@ -2109,12 +2109,58 @@ out_0: | |||
2109 | return retval; | 2109 | return retval; |
2110 | } | 2110 | } |
2111 | 2111 | ||
2112 | #ifdef CONFIG_PM | ||
2113 | /* This implementation assumes the devices remains powered on its VDDVARIO | ||
2114 | * pins during suspend. */ | ||
2115 | |||
2116 | static int smsc911x_suspend(struct platform_device *pdev, pm_message_t state) | ||
2117 | { | ||
2118 | struct net_device *dev = platform_get_drvdata(pdev); | ||
2119 | struct smsc911x_data *pdata = netdev_priv(dev); | ||
2120 | |||
2121 | /* enable wake on LAN, energy detection and the external PME | ||
2122 | * signal. */ | ||
2123 | smsc911x_reg_write(pdata, PMT_CTRL, | ||
2124 | PMT_CTRL_PM_MODE_D1_ | PMT_CTRL_WOL_EN_ | | ||
2125 | PMT_CTRL_ED_EN_ | PMT_CTRL_PME_EN_); | ||
2126 | |||
2127 | return 0; | ||
2128 | } | ||
2129 | |||
2130 | static int smsc911x_resume(struct platform_device *pdev) | ||
2131 | { | ||
2132 | struct net_device *dev = platform_get_drvdata(pdev); | ||
2133 | struct smsc911x_data *pdata = netdev_priv(dev); | ||
2134 | unsigned int to = 100; | ||
2135 | |||
2136 | /* Note 3.11 from the datasheet: | ||
2137 | * "When the LAN9220 is in a power saving state, a write of any | ||
2138 | * data to the BYTE_TEST register will wake-up the device." | ||
2139 | */ | ||
2140 | smsc911x_reg_write(pdata, BYTE_TEST, 0); | ||
2141 | |||
2142 | /* poll the READY bit in PMT_CTRL. Any other access to the device is | ||
2143 | * forbidden while this bit isn't set. Try for 100ms and return -EIO | ||
2144 | * if it failed. */ | ||
2145 | while (!(smsc911x_reg_read(pdata, PMT_CTRL) & PMT_CTRL_READY_) && --to) | ||
2146 | udelay(1000); | ||
2147 | |||
2148 | return (to == 0) ? -EIO : 0; | ||
2149 | } | ||
2150 | |||
2151 | #else | ||
2152 | #define smsc911x_suspend NULL | ||
2153 | #define smsc911x_resume NULL | ||
2154 | #endif | ||
2155 | |||
2112 | static struct platform_driver smsc911x_driver = { | 2156 | static struct platform_driver smsc911x_driver = { |
2113 | .probe = smsc911x_drv_probe, | 2157 | .probe = smsc911x_drv_probe, |
2114 | .remove = smsc911x_drv_remove, | 2158 | .remove = smsc911x_drv_remove, |
2115 | .driver = { | 2159 | .driver = { |
2116 | .name = SMSC_CHIPNAME, | 2160 | .name = SMSC_CHIPNAME, |
2117 | }, | 2161 | }, |
2162 | .suspend = smsc911x_suspend, | ||
2163 | .resume = smsc911x_resume, | ||
2118 | }; | 2164 | }; |
2119 | 2165 | ||
2120 | /* Entry point for loading the module */ | 2166 | /* Entry point for loading the module */ |