diff options
Diffstat (limited to 'drivers/net/smsc911x.c')
-rw-r--r-- | drivers/net/smsc911x.c | 63 |
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 | |||
175 | smsc911x_tx_writefifo(struct smsc911x_data *pdata, unsigned int *buf, | 176 | smsc911x_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 | |||
194 | smsc911x_rx_readfifo(struct smsc911x_data *pdata, unsigned int *buf, | 201 | smsc911x_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 | |||
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 | |||
2099 | static struct platform_driver smsc911x_driver = { | 2156 | static 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 */ |