aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/smsc911x.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/smsc911x.c')
-rw-r--r--drivers/net/smsc911x.c63
1 files changed, 61 insertions, 2 deletions
diff --git a/drivers/net/smsc911x.c b/drivers/net/smsc911x.c
index eb7db032a780..b60639bd181b 100644
--- a/drivers/net/smsc911x.c
+++ b/drivers/net/smsc911x.c
@@ -47,6 +47,7 @@
47#include <linux/bitops.h> 47#include <linux/bitops.h>
48#include <linux/irq.h> 48#include <linux/irq.h>
49#include <linux/io.h> 49#include <linux/io.h>
50#include <linux/swab.h>
50#include <linux/phy.h> 51#include <linux/phy.h>
51#include <linux/smsc911x.h> 52#include <linux/smsc911x.h>
52#include "smsc911x.h" 53#include "smsc911x.h"
@@ -175,6 +176,12 @@ static inline void
175smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, 176smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf,
176 unsigned int wordcount) 177 unsigned int wordcount)
177{ 178{
179 if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
180 while (wordcount--)
181 smsc911x_reg_write(pdata, TX_DATA_FIFO, swab32(*buf++));
182 return;
183 }
184
178 if (pdata->config.flags & SMSC911X_USE_32BIT) { 185 if (pdata->config.flags & SMSC911X_USE_32BIT) {
179 writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount); 186 writesl(pdata->ioaddr + TX_DATA_FIFO, buf, wordcount);
180 return; 187 return;
@@ -194,6 +201,12 @@ static inline void
194smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, 201smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf,
195 unsigned int wordcount) 202 unsigned int wordcount)
196{ 203{
204 if (pdata->config.flags & SMSC911X_SWAP_FIFO) {
205 while (wordcount--)
206 *buf++ = swab32(smsc911x_reg_read(pdata, RX_DATA_FIFO));
207 return;
208 }
209
197 if (pdata->config.flags & SMSC911X_USE_32BIT) { 210 if (pdata->config.flags & SMSC911X_USE_32BIT) {
198 readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount); 211 readsl(pdata->ioaddr + RX_DATA_FIFO, buf, wordcount);
199 return; 212 return;
@@ -1963,7 +1976,7 @@ static int __devinit smsc911x_drv_probe(struct platform_device *pdev)
1963 retval = -ENODEV; 1976 retval = -ENODEV;
1964 goto out_0; 1977 goto out_0;
1965 } 1978 }
1966 res_size = res->end - res->start; 1979 res_size = res->end - res->start + 1;
1967 1980
1968 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); 1981 irq_res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
1969 if (!irq_res) { 1982 if (!irq_res) {
@@ -2096,12 +2109,58 @@ out_0:
2096 return retval; 2109 return retval;
2097} 2110}
2098 2111
2112#ifdef CONFIG_PM
2113/* This implementation assumes the devices remains powered on its VDDVARIO
2114 * pins during suspend. */
2115
2116static 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
2130static 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
2099static struct platform_driver smsc911x_driver = { 2156static struct platform_driver smsc911x_driver = {
2100 .probe = smsc911x_drv_probe, 2157 .probe = smsc911x_drv_probe,
2101 .remove = smsc911x_drv_remove, 2158 .remove = __devexit_p(smsc911x_drv_remove),
2102 .driver = { 2159 .driver = {
2103 .name = SMSC_CHIPNAME, 2160 .name = SMSC_CHIPNAME,
2104 }, 2161 },
2162 .suspend = smsc911x_suspend,
2163 .resume = smsc911x_resume,
2105}; 2164};
2106 2165
2107/* Entry point for loading the module */ 2166/* Entry point for loading the module */