diff options
-rw-r--r-- | MAINTAINERS | 6 | ||||
-rw-r--r-- | drivers/net/usb/Kconfig | 8 | ||||
-rw-r--r-- | drivers/net/usb/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/usb/smsc95xx.c | 1225 | ||||
-rw-r--r-- | drivers/net/usb/smsc95xx.h | 253 |
5 files changed, 1493 insertions, 0 deletions
diff --git a/MAINTAINERS b/MAINTAINERS index e6e481483622..0e2f1e18be87 100644 --- a/MAINTAINERS +++ b/MAINTAINERS | |||
@@ -4353,6 +4353,12 @@ L: linux-usb@vger.kernel.org | |||
4353 | W: http://www.connecttech.com | 4353 | W: http://www.connecttech.com |
4354 | S: Supported | 4354 | S: Supported |
4355 | 4355 | ||
4356 | USB SMSC95XX ETHERNET DRIVER | ||
4357 | P: Steve Glendinning | ||
4358 | M: steve.glendinning@smsc.com | ||
4359 | L: netdev@vger.kernel.org | ||
4360 | S: Supported | ||
4361 | |||
4356 | USB SN9C1xx DRIVER | 4362 | USB SN9C1xx DRIVER |
4357 | P: Luca Risolia | 4363 | P: Luca Risolia |
4358 | M: luca.risolia@studio.unibo.it | 4364 | M: luca.risolia@studio.unibo.it |
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 0973b6e37024..8ee21030e9ac 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -188,6 +188,14 @@ config USB_NET_DM9601 | |||
188 | This option adds support for Davicom DM9601 based USB 1.1 | 188 | This option adds support for Davicom DM9601 based USB 1.1 |
189 | 10/100 Ethernet adapters. | 189 | 10/100 Ethernet adapters. |
190 | 190 | ||
191 | config USB_NET_SMSC95XX | ||
192 | tristate "SMSC LAN95XX based USB 2.0 10/100 ethernet devices" | ||
193 | depends on USB_USBNET | ||
194 | select CRC32 | ||
195 | help | ||
196 | This option adds support for SMSC LAN95XX based USB 2.0 | ||
197 | 10/100 Ethernet adapters. | ||
198 | |||
191 | config USB_NET_GL620A | 199 | config USB_NET_GL620A |
192 | tristate "GeneSys GL620USB-A based cables" | 200 | tristate "GeneSys GL620USB-A based cables" |
193 | depends on USB_USBNET | 201 | depends on USB_USBNET |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index 24800c157f98..6ce218dee135 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -10,6 +10,7 @@ obj-$(CONFIG_USB_HSO) += hso.o | |||
10 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o | 10 | obj-$(CONFIG_USB_NET_AX8817X) += asix.o |
11 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o | 11 | obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o |
12 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o | 12 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o |
13 | obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o | ||
13 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o | 14 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o |
14 | obj-$(CONFIG_USB_NET_NET1080) += net1080.o | 15 | obj-$(CONFIG_USB_NET_NET1080) += net1080.o |
15 | obj-$(CONFIG_USB_NET_PLUSB) += plusb.o | 16 | obj-$(CONFIG_USB_NET_PLUSB) += plusb.o |
diff --git a/drivers/net/usb/smsc95xx.c b/drivers/net/usb/smsc95xx.c new file mode 100644 index 000000000000..412bde6217c0 --- /dev/null +++ b/drivers/net/usb/smsc95xx.c | |||
@@ -0,0 +1,1225 @@ | |||
1 | /*************************************************************************** | ||
2 | * | ||
3 | * Copyright (C) 2007-2008 SMSC | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | * | ||
19 | *****************************************************************************/ | ||
20 | |||
21 | #include <linux/module.h> | ||
22 | #include <linux/kmod.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/netdevice.h> | ||
25 | #include <linux/etherdevice.h> | ||
26 | #include <linux/ethtool.h> | ||
27 | #include <linux/mii.h> | ||
28 | #include <linux/usb.h> | ||
29 | #include <linux/crc32.h> | ||
30 | #include <linux/usb/usbnet.h> | ||
31 | #include "smsc95xx.h" | ||
32 | |||
33 | #define SMSC_CHIPNAME "smsc95xx" | ||
34 | #define SMSC_DRIVER_VERSION "1.0.3" | ||
35 | #define HS_USB_PKT_SIZE (512) | ||
36 | #define FS_USB_PKT_SIZE (64) | ||
37 | #define DEFAULT_HS_BURST_CAP_SIZE (16 * 1024 + 5 * HS_USB_PKT_SIZE) | ||
38 | #define DEFAULT_FS_BURST_CAP_SIZE (6 * 1024 + 33 * FS_USB_PKT_SIZE) | ||
39 | #define DEFAULT_BULK_IN_DELAY (0x00002000) | ||
40 | #define MAX_SINGLE_PACKET_SIZE (2048) | ||
41 | #define LAN95XX_EEPROM_MAGIC (0x9500) | ||
42 | #define EEPROM_MAC_OFFSET (0x01) | ||
43 | #define DEFAULT_RX_CSUM_ENABLE (true) | ||
44 | #define SMSC95XX_INTERNAL_PHY_ID (1) | ||
45 | #define SMSC95XX_TX_OVERHEAD (8) | ||
46 | #define FLOW_CTRL_TX (1) | ||
47 | #define FLOW_CTRL_RX (2) | ||
48 | |||
49 | struct smsc95xx_priv { | ||
50 | u32 mac_cr; | ||
51 | spinlock_t mac_cr_lock; | ||
52 | bool use_rx_csum; | ||
53 | }; | ||
54 | |||
55 | struct usb_context { | ||
56 | struct usb_ctrlrequest req; | ||
57 | struct completion notify; | ||
58 | struct usbnet *dev; | ||
59 | }; | ||
60 | |||
61 | int turbo_mode = true; | ||
62 | module_param(turbo_mode, bool, 0644); | ||
63 | MODULE_PARM_DESC(turbo_mode, "Enable multiple frames per Rx transaction"); | ||
64 | |||
65 | static int smsc95xx_read_reg(struct usbnet *dev, u32 index, u32 *data) | ||
66 | { | ||
67 | u32 *buf = kmalloc(4, GFP_KERNEL); | ||
68 | int ret; | ||
69 | |||
70 | BUG_ON(!dev); | ||
71 | |||
72 | if (!buf) | ||
73 | return -ENOMEM; | ||
74 | |||
75 | ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0), | ||
76 | USB_VENDOR_REQUEST_READ_REGISTER, | ||
77 | USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
78 | 00, index, buf, 4, USB_CTRL_GET_TIMEOUT); | ||
79 | |||
80 | if (unlikely(ret < 0)) | ||
81 | devwarn(dev, "Failed to read register index 0x%08x", index); | ||
82 | |||
83 | le32_to_cpus(buf); | ||
84 | *data = *buf; | ||
85 | kfree(buf); | ||
86 | |||
87 | return ret; | ||
88 | } | ||
89 | |||
90 | static int smsc95xx_write_reg(struct usbnet *dev, u32 index, u32 data) | ||
91 | { | ||
92 | u32 *buf = kmalloc(4, GFP_KERNEL); | ||
93 | int ret; | ||
94 | |||
95 | BUG_ON(!dev); | ||
96 | |||
97 | if (!buf) | ||
98 | return -ENOMEM; | ||
99 | |||
100 | *buf = data; | ||
101 | cpu_to_le32s(buf); | ||
102 | |||
103 | ret = usb_control_msg(dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
104 | USB_VENDOR_REQUEST_WRITE_REGISTER, | ||
105 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, | ||
106 | 00, index, buf, 4, USB_CTRL_SET_TIMEOUT); | ||
107 | |||
108 | if (unlikely(ret < 0)) | ||
109 | devwarn(dev, "Failed to write register index 0x%08x", index); | ||
110 | |||
111 | kfree(buf); | ||
112 | |||
113 | return ret; | ||
114 | } | ||
115 | |||
116 | /* Loop until the read is completed with timeout | ||
117 | * called with phy_mutex held */ | ||
118 | static int smsc95xx_phy_wait_not_busy(struct usbnet *dev) | ||
119 | { | ||
120 | unsigned long start_time = jiffies; | ||
121 | u32 val; | ||
122 | |||
123 | do { | ||
124 | smsc95xx_read_reg(dev, MII_ADDR, &val); | ||
125 | if (!(val & MII_BUSY_)) | ||
126 | return 0; | ||
127 | } while (!time_after(jiffies, start_time + HZ)); | ||
128 | |||
129 | return -EIO; | ||
130 | } | ||
131 | |||
132 | static int smsc95xx_mdio_read(struct net_device *netdev, int phy_id, int idx) | ||
133 | { | ||
134 | struct usbnet *dev = netdev_priv(netdev); | ||
135 | u32 val, addr; | ||
136 | |||
137 | mutex_lock(&dev->phy_mutex); | ||
138 | |||
139 | /* confirm MII not busy */ | ||
140 | if (smsc95xx_phy_wait_not_busy(dev)) { | ||
141 | devwarn(dev, "MII is busy in smsc95xx_mdio_read"); | ||
142 | mutex_unlock(&dev->phy_mutex); | ||
143 | return -EIO; | ||
144 | } | ||
145 | |||
146 | /* set the address, index & direction (read from PHY) */ | ||
147 | phy_id &= dev->mii.phy_id_mask; | ||
148 | idx &= dev->mii.reg_num_mask; | ||
149 | addr = (phy_id << 11) | (idx << 6) | MII_READ_; | ||
150 | smsc95xx_write_reg(dev, MII_ADDR, addr); | ||
151 | |||
152 | if (smsc95xx_phy_wait_not_busy(dev)) { | ||
153 | devwarn(dev, "Timed out reading MII reg %02X", idx); | ||
154 | mutex_unlock(&dev->phy_mutex); | ||
155 | return -EIO; | ||
156 | } | ||
157 | |||
158 | smsc95xx_read_reg(dev, MII_DATA, &val); | ||
159 | |||
160 | mutex_unlock(&dev->phy_mutex); | ||
161 | |||
162 | return (u16)(val & 0xFFFF); | ||
163 | } | ||
164 | |||
165 | static void smsc95xx_mdio_write(struct net_device *netdev, int phy_id, int idx, | ||
166 | int regval) | ||
167 | { | ||
168 | struct usbnet *dev = netdev_priv(netdev); | ||
169 | u32 val, addr; | ||
170 | |||
171 | mutex_lock(&dev->phy_mutex); | ||
172 | |||
173 | /* confirm MII not busy */ | ||
174 | if (smsc95xx_phy_wait_not_busy(dev)) { | ||
175 | devwarn(dev, "MII is busy in smsc95xx_mdio_write"); | ||
176 | mutex_unlock(&dev->phy_mutex); | ||
177 | return; | ||
178 | } | ||
179 | |||
180 | val = regval; | ||
181 | smsc95xx_write_reg(dev, MII_DATA, val); | ||
182 | |||
183 | /* set the address, index & direction (write to PHY) */ | ||
184 | phy_id &= dev->mii.phy_id_mask; | ||
185 | idx &= dev->mii.reg_num_mask; | ||
186 | addr = (phy_id << 11) | (idx << 6) | MII_WRITE_; | ||
187 | smsc95xx_write_reg(dev, MII_ADDR, addr); | ||
188 | |||
189 | if (smsc95xx_phy_wait_not_busy(dev)) | ||
190 | devwarn(dev, "Timed out writing MII reg %02X", idx); | ||
191 | |||
192 | mutex_unlock(&dev->phy_mutex); | ||
193 | } | ||
194 | |||
195 | static int smsc95xx_wait_eeprom(struct usbnet *dev) | ||
196 | { | ||
197 | unsigned long start_time = jiffies; | ||
198 | u32 val; | ||
199 | |||
200 | do { | ||
201 | smsc95xx_read_reg(dev, E2P_CMD, &val); | ||
202 | if (!(val & E2P_CMD_BUSY_) || (val & E2P_CMD_TIMEOUT_)) | ||
203 | break; | ||
204 | udelay(40); | ||
205 | } while (!time_after(jiffies, start_time + HZ)); | ||
206 | |||
207 | if (val & (E2P_CMD_TIMEOUT_ | E2P_CMD_BUSY_)) { | ||
208 | devwarn(dev, "EEPROM read operation timeout"); | ||
209 | return -EIO; | ||
210 | } | ||
211 | |||
212 | return 0; | ||
213 | } | ||
214 | |||
215 | static int smsc95xx_eeprom_confirm_not_busy(struct usbnet *dev) | ||
216 | { | ||
217 | unsigned long start_time = jiffies; | ||
218 | u32 val; | ||
219 | |||
220 | do { | ||
221 | smsc95xx_read_reg(dev, E2P_CMD, &val); | ||
222 | |||
223 | if (!(val & E2P_CMD_LOADED_)) { | ||
224 | devwarn(dev, "No EEPROM present"); | ||
225 | return -EIO; | ||
226 | } | ||
227 | |||
228 | if (!(val & E2P_CMD_BUSY_)) | ||
229 | return 0; | ||
230 | |||
231 | udelay(40); | ||
232 | } while (!time_after(jiffies, start_time + HZ)); | ||
233 | |||
234 | devwarn(dev, "EEPROM is busy"); | ||
235 | return -EIO; | ||
236 | } | ||
237 | |||
238 | static int smsc95xx_read_eeprom(struct usbnet *dev, u32 offset, u32 length, | ||
239 | u8 *data) | ||
240 | { | ||
241 | u32 val; | ||
242 | int i, ret; | ||
243 | |||
244 | BUG_ON(!dev); | ||
245 | BUG_ON(!data); | ||
246 | |||
247 | ret = smsc95xx_eeprom_confirm_not_busy(dev); | ||
248 | if (ret) | ||
249 | return ret; | ||
250 | |||
251 | for (i = 0; i < length; i++) { | ||
252 | val = E2P_CMD_BUSY_ | E2P_CMD_READ_ | (offset & E2P_CMD_ADDR_); | ||
253 | smsc95xx_write_reg(dev, E2P_CMD, val); | ||
254 | |||
255 | ret = smsc95xx_wait_eeprom(dev); | ||
256 | if (ret < 0) | ||
257 | return ret; | ||
258 | |||
259 | smsc95xx_read_reg(dev, E2P_DATA, &val); | ||
260 | |||
261 | data[i] = val & 0xFF; | ||
262 | offset++; | ||
263 | } | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static int smsc95xx_write_eeprom(struct usbnet *dev, u32 offset, u32 length, | ||
269 | u8 *data) | ||
270 | { | ||
271 | u32 val; | ||
272 | int i, ret; | ||
273 | |||
274 | BUG_ON(!dev); | ||
275 | BUG_ON(!data); | ||
276 | |||
277 | ret = smsc95xx_eeprom_confirm_not_busy(dev); | ||
278 | if (ret) | ||
279 | return ret; | ||
280 | |||
281 | /* Issue write/erase enable command */ | ||
282 | val = E2P_CMD_BUSY_ | E2P_CMD_EWEN_; | ||
283 | smsc95xx_write_reg(dev, E2P_CMD, val); | ||
284 | |||
285 | ret = smsc95xx_wait_eeprom(dev); | ||
286 | if (ret < 0) | ||
287 | return ret; | ||
288 | |||
289 | for (i = 0; i < length; i++) { | ||
290 | |||
291 | /* Fill data register */ | ||
292 | val = data[i]; | ||
293 | smsc95xx_write_reg(dev, E2P_DATA, val); | ||
294 | |||
295 | /* Send "write" command */ | ||
296 | val = E2P_CMD_BUSY_ | E2P_CMD_WRITE_ | (offset & E2P_CMD_ADDR_); | ||
297 | smsc95xx_write_reg(dev, E2P_CMD, val); | ||
298 | |||
299 | ret = smsc95xx_wait_eeprom(dev); | ||
300 | if (ret < 0) | ||
301 | return ret; | ||
302 | |||
303 | offset++; | ||
304 | } | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | |||
309 | static void smsc95xx_async_cmd_callback(struct urb *urb, struct pt_regs *regs) | ||
310 | { | ||
311 | struct usb_context *usb_context = urb->context; | ||
312 | struct usbnet *dev = usb_context->dev; | ||
313 | |||
314 | if (urb->status < 0) | ||
315 | devwarn(dev, "async callback failed with %d", urb->status); | ||
316 | |||
317 | complete(&usb_context->notify); | ||
318 | |||
319 | kfree(usb_context); | ||
320 | usb_free_urb(urb); | ||
321 | } | ||
322 | |||
323 | static int smsc95xx_write_reg_async(struct usbnet *dev, u32 index, u32 *data) | ||
324 | { | ||
325 | struct usb_context *usb_context; | ||
326 | int status; | ||
327 | struct urb *urb; | ||
328 | const u32 size = 4; | ||
329 | |||
330 | urb = usb_alloc_urb(0, GFP_ATOMIC); | ||
331 | if (!urb) { | ||
332 | devwarn(dev, "Error allocating URB"); | ||
333 | return -ENOMEM; | ||
334 | } | ||
335 | |||
336 | usb_context = kmalloc(sizeof(struct usb_context), GFP_ATOMIC); | ||
337 | if (usb_context == NULL) { | ||
338 | devwarn(dev, "Error allocating control msg"); | ||
339 | usb_free_urb(urb); | ||
340 | return -ENOMEM; | ||
341 | } | ||
342 | |||
343 | usb_context->req.bRequestType = | ||
344 | USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE; | ||
345 | usb_context->req.bRequest = USB_VENDOR_REQUEST_WRITE_REGISTER; | ||
346 | usb_context->req.wValue = 00; | ||
347 | usb_context->req.wIndex = cpu_to_le32(index); | ||
348 | usb_context->req.wLength = cpu_to_le32(size); | ||
349 | init_completion(&usb_context->notify); | ||
350 | |||
351 | usb_fill_control_urb(urb, dev->udev, usb_sndctrlpipe(dev->udev, 0), | ||
352 | (void *)&usb_context->req, data, size, | ||
353 | (usb_complete_t)smsc95xx_async_cmd_callback, | ||
354 | (void *)usb_context); | ||
355 | |||
356 | status = usb_submit_urb(urb, GFP_ATOMIC); | ||
357 | if (status < 0) { | ||
358 | devwarn(dev, "Error submitting control msg, sts=%d", status); | ||
359 | kfree(usb_context); | ||
360 | usb_free_urb(urb); | ||
361 | } | ||
362 | |||
363 | return status; | ||
364 | } | ||
365 | |||
366 | /* returns hash bit number for given MAC address | ||
367 | * example: | ||
368 | * 01 00 5E 00 00 01 -> returns bit number 31 */ | ||
369 | static unsigned int smsc95xx_hash(char addr[ETH_ALEN]) | ||
370 | { | ||
371 | return (ether_crc(ETH_ALEN, addr) >> 26) & 0x3f; | ||
372 | } | ||
373 | |||
374 | static void smsc95xx_set_multicast(struct net_device *netdev) | ||
375 | { | ||
376 | struct usbnet *dev = netdev_priv(netdev); | ||
377 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
378 | u32 hash_hi = 0; | ||
379 | u32 hash_lo = 0; | ||
380 | unsigned long flags; | ||
381 | |||
382 | spin_lock_irqsave(&pdata->mac_cr_lock, flags); | ||
383 | |||
384 | if (dev->net->flags & IFF_PROMISC) { | ||
385 | if (netif_msg_drv(dev)) | ||
386 | devdbg(dev, "promiscuous mode enabled"); | ||
387 | pdata->mac_cr |= MAC_CR_PRMS_; | ||
388 | pdata->mac_cr &= ~(MAC_CR_MCPAS_ | MAC_CR_HPFILT_); | ||
389 | } else if (dev->net->flags & IFF_ALLMULTI) { | ||
390 | if (netif_msg_drv(dev)) | ||
391 | devdbg(dev, "receive all multicast enabled"); | ||
392 | pdata->mac_cr |= MAC_CR_MCPAS_; | ||
393 | pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_HPFILT_); | ||
394 | } else if (dev->net->mc_count > 0) { | ||
395 | struct dev_mc_list *mc_list = dev->net->mc_list; | ||
396 | int count = 0; | ||
397 | |||
398 | pdata->mac_cr |= MAC_CR_HPFILT_; | ||
399 | pdata->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_); | ||
400 | |||
401 | while (mc_list) { | ||
402 | count++; | ||
403 | if (mc_list->dmi_addrlen == ETH_ALEN) { | ||
404 | u32 bitnum = smsc95xx_hash(mc_list->dmi_addr); | ||
405 | u32 mask = 0x01 << (bitnum & 0x1F); | ||
406 | if (bitnum & 0x20) | ||
407 | hash_hi |= mask; | ||
408 | else | ||
409 | hash_lo |= mask; | ||
410 | } else { | ||
411 | devwarn(dev, "dmi_addrlen != 6"); | ||
412 | } | ||
413 | mc_list = mc_list->next; | ||
414 | } | ||
415 | |||
416 | if (count != ((u32)dev->net->mc_count)) | ||
417 | devwarn(dev, "mc_count != dev->mc_count"); | ||
418 | |||
419 | if (netif_msg_drv(dev)) | ||
420 | devdbg(dev, "HASHH=0x%08X, HASHL=0x%08X", hash_hi, | ||
421 | hash_lo); | ||
422 | } else { | ||
423 | if (netif_msg_drv(dev)) | ||
424 | devdbg(dev, "receive own packets only"); | ||
425 | pdata->mac_cr &= | ||
426 | ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_); | ||
427 | } | ||
428 | |||
429 | spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); | ||
430 | |||
431 | /* Initiate async writes, as we can't wait for completion here */ | ||
432 | smsc95xx_write_reg_async(dev, HASHH, &hash_hi); | ||
433 | smsc95xx_write_reg_async(dev, HASHL, &hash_lo); | ||
434 | smsc95xx_write_reg_async(dev, MAC_CR, &pdata->mac_cr); | ||
435 | } | ||
436 | |||
437 | static u8 smsc95xx_resolve_flowctrl_fulldplx(u16 lcladv, u16 rmtadv) | ||
438 | { | ||
439 | u8 cap = 0; | ||
440 | |||
441 | if (lcladv & ADVERTISE_PAUSE_CAP) { | ||
442 | if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
443 | if (rmtadv & LPA_PAUSE_CAP) | ||
444 | cap = FLOW_CTRL_TX | FLOW_CTRL_RX; | ||
445 | else if (rmtadv & LPA_PAUSE_ASYM) | ||
446 | cap = FLOW_CTRL_RX; | ||
447 | } else { | ||
448 | if (rmtadv & LPA_PAUSE_CAP) | ||
449 | cap = FLOW_CTRL_TX | FLOW_CTRL_RX; | ||
450 | } | ||
451 | } else if (lcladv & ADVERTISE_PAUSE_ASYM) { | ||
452 | if ((rmtadv & LPA_PAUSE_CAP) && (rmtadv & LPA_PAUSE_ASYM)) | ||
453 | cap = FLOW_CTRL_TX; | ||
454 | } | ||
455 | |||
456 | return cap; | ||
457 | } | ||
458 | |||
459 | static void smsc95xx_phy_update_flowcontrol(struct usbnet *dev, u8 duplex, | ||
460 | u16 lcladv, u16 rmtadv) | ||
461 | { | ||
462 | u32 flow, afc_cfg = 0; | ||
463 | |||
464 | int ret = smsc95xx_read_reg(dev, AFC_CFG, &afc_cfg); | ||
465 | if (ret < 0) { | ||
466 | devwarn(dev, "error reading AFC_CFG"); | ||
467 | return; | ||
468 | } | ||
469 | |||
470 | if (duplex == DUPLEX_FULL) { | ||
471 | u8 cap = smsc95xx_resolve_flowctrl_fulldplx(lcladv, rmtadv); | ||
472 | |||
473 | if (cap & FLOW_CTRL_RX) | ||
474 | flow = 0xFFFF0002; | ||
475 | else | ||
476 | flow = 0; | ||
477 | |||
478 | if (cap & FLOW_CTRL_TX) | ||
479 | afc_cfg |= 0xF; | ||
480 | else | ||
481 | afc_cfg &= ~0xF; | ||
482 | |||
483 | if (netif_msg_link(dev)) | ||
484 | devdbg(dev, "rx pause %s, tx pause %s", | ||
485 | (cap & FLOW_CTRL_RX ? "enabled" : "disabled"), | ||
486 | (cap & FLOW_CTRL_TX ? "enabled" : "disabled")); | ||
487 | } else { | ||
488 | if (netif_msg_link(dev)) | ||
489 | devdbg(dev, "half duplex"); | ||
490 | flow = 0; | ||
491 | afc_cfg |= 0xF; | ||
492 | } | ||
493 | |||
494 | smsc95xx_write_reg(dev, FLOW, flow); | ||
495 | smsc95xx_write_reg(dev, AFC_CFG, afc_cfg); | ||
496 | } | ||
497 | |||
498 | static int smsc95xx_link_reset(struct usbnet *dev) | ||
499 | { | ||
500 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
501 | struct mii_if_info *mii = &dev->mii; | ||
502 | struct ethtool_cmd ecmd; | ||
503 | unsigned long flags; | ||
504 | u16 lcladv, rmtadv; | ||
505 | u32 intdata; | ||
506 | |||
507 | /* clear interrupt status */ | ||
508 | smsc95xx_mdio_read(dev->net, mii->phy_id, PHY_INT_SRC); | ||
509 | intdata = 0xFFFFFFFF; | ||
510 | smsc95xx_write_reg(dev, INT_STS, intdata); | ||
511 | |||
512 | mii_check_media(mii, 1, 1); | ||
513 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
514 | lcladv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_ADVERTISE); | ||
515 | rmtadv = smsc95xx_mdio_read(dev->net, mii->phy_id, MII_LPA); | ||
516 | |||
517 | if (netif_msg_link(dev)) | ||
518 | devdbg(dev, "speed: %d duplex: %d lcladv: %04x rmtadv: %04x", | ||
519 | ecmd.speed, ecmd.duplex, lcladv, rmtadv); | ||
520 | |||
521 | spin_lock_irqsave(&pdata->mac_cr_lock, flags); | ||
522 | if (ecmd.duplex != DUPLEX_FULL) { | ||
523 | pdata->mac_cr &= ~MAC_CR_FDPX_; | ||
524 | pdata->mac_cr |= MAC_CR_RCVOWN_; | ||
525 | } else { | ||
526 | pdata->mac_cr &= ~MAC_CR_RCVOWN_; | ||
527 | pdata->mac_cr |= MAC_CR_FDPX_; | ||
528 | } | ||
529 | spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); | ||
530 | |||
531 | smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); | ||
532 | |||
533 | smsc95xx_phy_update_flowcontrol(dev, ecmd.duplex, lcladv, rmtadv); | ||
534 | |||
535 | return 0; | ||
536 | } | ||
537 | |||
538 | static void smsc95xx_status(struct usbnet *dev, struct urb *urb) | ||
539 | { | ||
540 | u32 intdata; | ||
541 | |||
542 | if (urb->actual_length != 4) { | ||
543 | devwarn(dev, "unexpected urb length %d", urb->actual_length); | ||
544 | return; | ||
545 | } | ||
546 | |||
547 | memcpy(&intdata, urb->transfer_buffer, 4); | ||
548 | le32_to_cpus(intdata); | ||
549 | |||
550 | if (netif_msg_link(dev)) | ||
551 | devdbg(dev, "intdata: 0x%08X", intdata); | ||
552 | |||
553 | if (intdata & INT_ENP_PHY_INT_) | ||
554 | usbnet_defer_kevent(dev, EVENT_LINK_RESET); | ||
555 | else | ||
556 | devwarn(dev, "unexpected interrupt, intdata=0x%08X", intdata); | ||
557 | } | ||
558 | |||
559 | /* Enable or disable Rx checksum offload engine */ | ||
560 | static int smsc95xx_set_rx_csum(struct usbnet *dev, bool enable) | ||
561 | { | ||
562 | u32 read_buf; | ||
563 | int ret = smsc95xx_read_reg(dev, COE_CR, &read_buf); | ||
564 | if (ret < 0) { | ||
565 | devwarn(dev, "Failed to read COE_CR: %d", ret); | ||
566 | return ret; | ||
567 | } | ||
568 | |||
569 | if (enable) | ||
570 | read_buf |= Rx_COE_EN_; | ||
571 | else | ||
572 | read_buf &= ~Rx_COE_EN_; | ||
573 | |||
574 | ret = smsc95xx_write_reg(dev, COE_CR, read_buf); | ||
575 | if (ret < 0) { | ||
576 | devwarn(dev, "Failed to write COE_CR: %d", ret); | ||
577 | return ret; | ||
578 | } | ||
579 | |||
580 | if (netif_msg_hw(dev)) | ||
581 | devdbg(dev, "COE_CR = 0x%08x", read_buf); | ||
582 | return 0; | ||
583 | } | ||
584 | |||
585 | static int smsc95xx_ethtool_get_eeprom_len(struct net_device *net) | ||
586 | { | ||
587 | return MAX_EEPROM_SIZE; | ||
588 | } | ||
589 | |||
590 | static int smsc95xx_ethtool_get_eeprom(struct net_device *netdev, | ||
591 | struct ethtool_eeprom *ee, u8 *data) | ||
592 | { | ||
593 | struct usbnet *dev = netdev_priv(netdev); | ||
594 | |||
595 | ee->magic = LAN95XX_EEPROM_MAGIC; | ||
596 | |||
597 | return smsc95xx_read_eeprom(dev, ee->offset, ee->len, data); | ||
598 | } | ||
599 | |||
600 | static int smsc95xx_ethtool_set_eeprom(struct net_device *netdev, | ||
601 | struct ethtool_eeprom *ee, u8 *data) | ||
602 | { | ||
603 | struct usbnet *dev = netdev_priv(netdev); | ||
604 | |||
605 | if (ee->magic != LAN95XX_EEPROM_MAGIC) { | ||
606 | devwarn(dev, "EEPROM: magic value mismatch, magic = 0x%x", | ||
607 | ee->magic); | ||
608 | return -EINVAL; | ||
609 | } | ||
610 | |||
611 | return smsc95xx_write_eeprom(dev, ee->offset, ee->len, data); | ||
612 | } | ||
613 | |||
614 | static u32 smsc95xx_ethtool_get_rx_csum(struct net_device *netdev) | ||
615 | { | ||
616 | struct usbnet *dev = netdev_priv(netdev); | ||
617 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
618 | |||
619 | return pdata->use_rx_csum; | ||
620 | } | ||
621 | |||
622 | static int smsc95xx_ethtool_set_rx_csum(struct net_device *netdev, u32 val) | ||
623 | { | ||
624 | struct usbnet *dev = netdev_priv(netdev); | ||
625 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
626 | |||
627 | pdata->use_rx_csum = !!val; | ||
628 | |||
629 | return smsc95xx_set_rx_csum(dev, pdata->use_rx_csum); | ||
630 | } | ||
631 | |||
632 | static struct ethtool_ops smsc95xx_ethtool_ops = { | ||
633 | .get_link = usbnet_get_link, | ||
634 | .nway_reset = usbnet_nway_reset, | ||
635 | .get_drvinfo = usbnet_get_drvinfo, | ||
636 | .get_msglevel = usbnet_get_msglevel, | ||
637 | .set_msglevel = usbnet_set_msglevel, | ||
638 | .get_settings = usbnet_get_settings, | ||
639 | .set_settings = usbnet_set_settings, | ||
640 | .get_eeprom_len = smsc95xx_ethtool_get_eeprom_len, | ||
641 | .get_eeprom = smsc95xx_ethtool_get_eeprom, | ||
642 | .set_eeprom = smsc95xx_ethtool_set_eeprom, | ||
643 | .get_rx_csum = smsc95xx_ethtool_get_rx_csum, | ||
644 | .set_rx_csum = smsc95xx_ethtool_set_rx_csum, | ||
645 | }; | ||
646 | |||
647 | static int smsc95xx_ioctl(struct net_device *netdev, struct ifreq *rq, int cmd) | ||
648 | { | ||
649 | struct usbnet *dev = netdev_priv(netdev); | ||
650 | |||
651 | if (!netif_running(netdev)) | ||
652 | return -EINVAL; | ||
653 | |||
654 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
655 | } | ||
656 | |||
657 | static void smsc95xx_init_mac_address(struct usbnet *dev) | ||
658 | { | ||
659 | /* try reading mac address from EEPROM */ | ||
660 | if (smsc95xx_read_eeprom(dev, EEPROM_MAC_OFFSET, ETH_ALEN, | ||
661 | dev->net->dev_addr) == 0) { | ||
662 | if (is_valid_ether_addr(dev->net->dev_addr)) { | ||
663 | /* eeprom values are valid so use them */ | ||
664 | if (netif_msg_ifup(dev)) | ||
665 | devdbg(dev, "MAC address read from EEPROM"); | ||
666 | return; | ||
667 | } | ||
668 | } | ||
669 | |||
670 | /* no eeprom, or eeprom values are invalid. generate random MAC */ | ||
671 | random_ether_addr(dev->net->dev_addr); | ||
672 | if (netif_msg_ifup(dev)) | ||
673 | devdbg(dev, "MAC address set to random_ether_addr"); | ||
674 | } | ||
675 | |||
676 | static int smsc95xx_set_mac_address(struct usbnet *dev) | ||
677 | { | ||
678 | u32 addr_lo = dev->net->dev_addr[0] | dev->net->dev_addr[1] << 8 | | ||
679 | dev->net->dev_addr[2] << 16 | dev->net->dev_addr[3] << 24; | ||
680 | u32 addr_hi = dev->net->dev_addr[4] | dev->net->dev_addr[5] << 8; | ||
681 | int ret; | ||
682 | |||
683 | ret = smsc95xx_write_reg(dev, ADDRL, addr_lo); | ||
684 | if (ret < 0) { | ||
685 | devwarn(dev, "Failed to write ADDRL: %d", ret); | ||
686 | return ret; | ||
687 | } | ||
688 | |||
689 | ret = smsc95xx_write_reg(dev, ADDRH, addr_hi); | ||
690 | if (ret < 0) { | ||
691 | devwarn(dev, "Failed to write ADDRH: %d", ret); | ||
692 | return ret; | ||
693 | } | ||
694 | |||
695 | return 0; | ||
696 | } | ||
697 | |||
698 | /* starts the TX path */ | ||
699 | static void smsc95xx_start_tx_path(struct usbnet *dev) | ||
700 | { | ||
701 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
702 | unsigned long flags; | ||
703 | u32 reg_val; | ||
704 | |||
705 | /* Enable Tx at MAC */ | ||
706 | spin_lock_irqsave(&pdata->mac_cr_lock, flags); | ||
707 | pdata->mac_cr |= MAC_CR_TXEN_; | ||
708 | spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); | ||
709 | |||
710 | smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); | ||
711 | |||
712 | /* Enable Tx at SCSRs */ | ||
713 | reg_val = TX_CFG_ON_; | ||
714 | smsc95xx_write_reg(dev, TX_CFG, reg_val); | ||
715 | } | ||
716 | |||
717 | /* Starts the Receive path */ | ||
718 | static void smsc95xx_start_rx_path(struct usbnet *dev) | ||
719 | { | ||
720 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
721 | unsigned long flags; | ||
722 | |||
723 | spin_lock_irqsave(&pdata->mac_cr_lock, flags); | ||
724 | pdata->mac_cr |= MAC_CR_RXEN_; | ||
725 | spin_unlock_irqrestore(&pdata->mac_cr_lock, flags); | ||
726 | |||
727 | smsc95xx_write_reg(dev, MAC_CR, pdata->mac_cr); | ||
728 | } | ||
729 | |||
730 | static int smsc95xx_phy_initialize(struct usbnet *dev) | ||
731 | { | ||
732 | /* Initialize MII structure */ | ||
733 | dev->mii.dev = dev->net; | ||
734 | dev->mii.mdio_read = smsc95xx_mdio_read; | ||
735 | dev->mii.mdio_write = smsc95xx_mdio_write; | ||
736 | dev->mii.phy_id_mask = 0x1f; | ||
737 | dev->mii.reg_num_mask = 0x1f; | ||
738 | dev->mii.phy_id = SMSC95XX_INTERNAL_PHY_ID; | ||
739 | |||
740 | smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | ||
741 | smsc95xx_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
742 | ADVERTISE_ALL | ADVERTISE_CSMA | ADVERTISE_PAUSE_CAP | | ||
743 | ADVERTISE_PAUSE_ASYM); | ||
744 | |||
745 | /* read to clear */ | ||
746 | smsc95xx_mdio_read(dev->net, dev->mii.phy_id, PHY_INT_SRC); | ||
747 | |||
748 | smsc95xx_mdio_write(dev->net, dev->mii.phy_id, PHY_INT_MASK, | ||
749 | PHY_INT_MASK_DEFAULT_); | ||
750 | mii_nway_restart(&dev->mii); | ||
751 | |||
752 | if (netif_msg_ifup(dev)) | ||
753 | devdbg(dev, "phy initialised succesfully"); | ||
754 | return 0; | ||
755 | } | ||
756 | |||
757 | static int smsc95xx_reset(struct usbnet *dev) | ||
758 | { | ||
759 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
760 | u32 read_buf, write_buf, burst_cap; | ||
761 | int ret = 0, timeout; | ||
762 | DECLARE_MAC_BUF(mac); | ||
763 | |||
764 | if (netif_msg_ifup(dev)) | ||
765 | devdbg(dev, "entering smsc95xx_reset"); | ||
766 | |||
767 | write_buf = HW_CFG_LRST_; | ||
768 | ret = smsc95xx_write_reg(dev, HW_CFG, write_buf); | ||
769 | if (ret < 0) { | ||
770 | devwarn(dev, "Failed to write HW_CFG_LRST_ bit in HW_CFG " | ||
771 | "register, ret = %d", ret); | ||
772 | return ret; | ||
773 | } | ||
774 | |||
775 | timeout = 0; | ||
776 | do { | ||
777 | ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); | ||
778 | if (ret < 0) { | ||
779 | devwarn(dev, "Failed to read HW_CFG: %d", ret); | ||
780 | return ret; | ||
781 | } | ||
782 | msleep(10); | ||
783 | timeout++; | ||
784 | } while ((read_buf & HW_CFG_LRST_) && (timeout < 100)); | ||
785 | |||
786 | if (timeout >= 100) { | ||
787 | devwarn(dev, "timeout waiting for completion of Lite Reset"); | ||
788 | return ret; | ||
789 | } | ||
790 | |||
791 | write_buf = PM_CTL_PHY_RST_; | ||
792 | ret = smsc95xx_write_reg(dev, PM_CTRL, write_buf); | ||
793 | if (ret < 0) { | ||
794 | devwarn(dev, "Failed to write PM_CTRL: %d", ret); | ||
795 | return ret; | ||
796 | } | ||
797 | |||
798 | timeout = 0; | ||
799 | do { | ||
800 | ret = smsc95xx_read_reg(dev, PM_CTRL, &read_buf); | ||
801 | if (ret < 0) { | ||
802 | devwarn(dev, "Failed to read PM_CTRL: %d", ret); | ||
803 | return ret; | ||
804 | } | ||
805 | msleep(10); | ||
806 | timeout++; | ||
807 | } while ((read_buf & PM_CTL_PHY_RST_) && (timeout < 100)); | ||
808 | |||
809 | if (timeout >= 100) { | ||
810 | devwarn(dev, "timeout waiting for PHY Reset"); | ||
811 | return ret; | ||
812 | } | ||
813 | |||
814 | smsc95xx_init_mac_address(dev); | ||
815 | |||
816 | ret = smsc95xx_set_mac_address(dev); | ||
817 | if (ret < 0) | ||
818 | return ret; | ||
819 | |||
820 | if (netif_msg_ifup(dev)) | ||
821 | devdbg(dev, "MAC Address: %s", | ||
822 | print_mac(mac, dev->net->dev_addr)); | ||
823 | |||
824 | ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); | ||
825 | if (ret < 0) { | ||
826 | devwarn(dev, "Failed to read HW_CFG: %d", ret); | ||
827 | return ret; | ||
828 | } | ||
829 | |||
830 | if (netif_msg_ifup(dev)) | ||
831 | devdbg(dev, "Read Value from HW_CFG : 0x%08x", read_buf); | ||
832 | |||
833 | read_buf |= HW_CFG_BIR_; | ||
834 | |||
835 | ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); | ||
836 | if (ret < 0) { | ||
837 | devwarn(dev, "Failed to write HW_CFG_BIR_ bit in HW_CFG " | ||
838 | "register, ret = %d", ret); | ||
839 | return ret; | ||
840 | } | ||
841 | |||
842 | ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); | ||
843 | if (ret < 0) { | ||
844 | devwarn(dev, "Failed to read HW_CFG: %d", ret); | ||
845 | return ret; | ||
846 | } | ||
847 | if (netif_msg_ifup(dev)) | ||
848 | devdbg(dev, "Read Value from HW_CFG after writing " | ||
849 | "HW_CFG_BIR_: 0x%08x", read_buf); | ||
850 | |||
851 | if (!turbo_mode) { | ||
852 | burst_cap = 0; | ||
853 | dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE; | ||
854 | } else if (dev->udev->speed == USB_SPEED_HIGH) { | ||
855 | burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE; | ||
856 | dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE; | ||
857 | } else { | ||
858 | burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE; | ||
859 | dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE; | ||
860 | } | ||
861 | |||
862 | if (netif_msg_ifup(dev)) | ||
863 | devdbg(dev, "rx_urb_size=%ld", (ulong)dev->rx_urb_size); | ||
864 | |||
865 | ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap); | ||
866 | if (ret < 0) { | ||
867 | devwarn(dev, "Failed to write BURST_CAP: %d", ret); | ||
868 | return ret; | ||
869 | } | ||
870 | |||
871 | ret = smsc95xx_read_reg(dev, BURST_CAP, &read_buf); | ||
872 | if (ret < 0) { | ||
873 | devwarn(dev, "Failed to read BURST_CAP: %d", ret); | ||
874 | return ret; | ||
875 | } | ||
876 | if (netif_msg_ifup(dev)) | ||
877 | devdbg(dev, "Read Value from BURST_CAP after writing: 0x%08x", | ||
878 | read_buf); | ||
879 | |||
880 | read_buf = DEFAULT_BULK_IN_DELAY; | ||
881 | ret = smsc95xx_write_reg(dev, BULK_IN_DLY, read_buf); | ||
882 | if (ret < 0) { | ||
883 | devwarn(dev, "ret = %d", ret); | ||
884 | return ret; | ||
885 | } | ||
886 | |||
887 | ret = smsc95xx_read_reg(dev, BULK_IN_DLY, &read_buf); | ||
888 | if (ret < 0) { | ||
889 | devwarn(dev, "Failed to read BULK_IN_DLY: %d", ret); | ||
890 | return ret; | ||
891 | } | ||
892 | if (netif_msg_ifup(dev)) | ||
893 | devdbg(dev, "Read Value from BULK_IN_DLY after writing: " | ||
894 | "0x%08x", read_buf); | ||
895 | |||
896 | ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); | ||
897 | if (ret < 0) { | ||
898 | devwarn(dev, "Failed to read HW_CFG: %d", ret); | ||
899 | return ret; | ||
900 | } | ||
901 | if (netif_msg_ifup(dev)) | ||
902 | devdbg(dev, "Read Value from HW_CFG: 0x%08x", read_buf); | ||
903 | |||
904 | if (turbo_mode) | ||
905 | read_buf |= (HW_CFG_MEF_ | HW_CFG_BCE_); | ||
906 | |||
907 | read_buf &= ~HW_CFG_RXDOFF_; | ||
908 | |||
909 | /* set Rx data offset=2, Make IP header aligns on word boundary. */ | ||
910 | read_buf |= NET_IP_ALIGN << 9; | ||
911 | |||
912 | ret = smsc95xx_write_reg(dev, HW_CFG, read_buf); | ||
913 | if (ret < 0) { | ||
914 | devwarn(dev, "Failed to write HW_CFG register, ret=%d", ret); | ||
915 | return ret; | ||
916 | } | ||
917 | |||
918 | ret = smsc95xx_read_reg(dev, HW_CFG, &read_buf); | ||
919 | if (ret < 0) { | ||
920 | devwarn(dev, "Failed to read HW_CFG: %d", ret); | ||
921 | return ret; | ||
922 | } | ||
923 | if (netif_msg_ifup(dev)) | ||
924 | devdbg(dev, "Read Value from HW_CFG after writing: 0x%08x", | ||
925 | read_buf); | ||
926 | |||
927 | write_buf = 0xFFFFFFFF; | ||
928 | ret = smsc95xx_write_reg(dev, INT_STS, write_buf); | ||
929 | if (ret < 0) { | ||
930 | devwarn(dev, "Failed to write INT_STS register, ret=%d", ret); | ||
931 | return ret; | ||
932 | } | ||
933 | |||
934 | ret = smsc95xx_read_reg(dev, ID_REV, &read_buf); | ||
935 | if (ret < 0) { | ||
936 | devwarn(dev, "Failed to read ID_REV: %d", ret); | ||
937 | return ret; | ||
938 | } | ||
939 | if (netif_msg_ifup(dev)) | ||
940 | devdbg(dev, "ID_REV = 0x%08x", read_buf); | ||
941 | |||
942 | /* Init Tx */ | ||
943 | write_buf = 0; | ||
944 | ret = smsc95xx_write_reg(dev, FLOW, write_buf); | ||
945 | if (ret < 0) { | ||
946 | devwarn(dev, "Failed to write FLOW: %d", ret); | ||
947 | return ret; | ||
948 | } | ||
949 | |||
950 | read_buf = AFC_CFG_DEFAULT; | ||
951 | ret = smsc95xx_write_reg(dev, AFC_CFG, read_buf); | ||
952 | if (ret < 0) { | ||
953 | devwarn(dev, "Failed to write AFC_CFG: %d", ret); | ||
954 | return ret; | ||
955 | } | ||
956 | |||
957 | /* Don't need mac_cr_lock during initialisation */ | ||
958 | ret = smsc95xx_read_reg(dev, MAC_CR, &pdata->mac_cr); | ||
959 | if (ret < 0) { | ||
960 | devwarn(dev, "Failed to read MAC_CR: %d", ret); | ||
961 | return ret; | ||
962 | } | ||
963 | |||
964 | /* Init Rx */ | ||
965 | /* Set Vlan */ | ||
966 | write_buf = (u32)ETH_P_8021Q; | ||
967 | ret = smsc95xx_write_reg(dev, VLAN1, write_buf); | ||
968 | if (ret < 0) { | ||
969 | devwarn(dev, "Failed to write VAN1: %d", ret); | ||
970 | return ret; | ||
971 | } | ||
972 | |||
973 | /* Enable or disable Rx checksum offload engine */ | ||
974 | ret = smsc95xx_set_rx_csum(dev, pdata->use_rx_csum); | ||
975 | if (ret < 0) { | ||
976 | devwarn(dev, "Failed to set Rx csum offload: %d", ret); | ||
977 | return ret; | ||
978 | } | ||
979 | |||
980 | smsc95xx_set_multicast(dev->net); | ||
981 | |||
982 | if (smsc95xx_phy_initialize(dev) < 0) | ||
983 | return -EIO; | ||
984 | |||
985 | ret = smsc95xx_read_reg(dev, INT_EP_CTL, &read_buf); | ||
986 | if (ret < 0) { | ||
987 | devwarn(dev, "Failed to read INT_EP_CTL: %d", ret); | ||
988 | return ret; | ||
989 | } | ||
990 | |||
991 | /* enable PHY interrupts */ | ||
992 | read_buf |= INT_EP_CTL_PHY_INT_; | ||
993 | |||
994 | ret = smsc95xx_write_reg(dev, INT_EP_CTL, read_buf); | ||
995 | if (ret < 0) { | ||
996 | devwarn(dev, "Failed to write INT_EP_CTL: %d", ret); | ||
997 | return ret; | ||
998 | } | ||
999 | |||
1000 | smsc95xx_start_tx_path(dev); | ||
1001 | smsc95xx_start_rx_path(dev); | ||
1002 | |||
1003 | if (netif_msg_ifup(dev)) | ||
1004 | devdbg(dev, "smsc95xx_reset, return 0"); | ||
1005 | return 0; | ||
1006 | } | ||
1007 | |||
1008 | static int smsc95xx_bind(struct usbnet *dev, struct usb_interface *intf) | ||
1009 | { | ||
1010 | struct smsc95xx_priv *pdata = NULL; | ||
1011 | int ret; | ||
1012 | |||
1013 | printk(KERN_INFO SMSC_CHIPNAME " v" SMSC_DRIVER_VERSION "\n"); | ||
1014 | |||
1015 | ret = usbnet_get_endpoints(dev, intf); | ||
1016 | if (ret < 0) { | ||
1017 | devwarn(dev, "usbnet_get_endpoints failed: %d", ret); | ||
1018 | return ret; | ||
1019 | } | ||
1020 | |||
1021 | dev->data[0] = (unsigned long)kzalloc(sizeof(struct smsc95xx_priv), | ||
1022 | GFP_KERNEL); | ||
1023 | |||
1024 | pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
1025 | if (!pdata) { | ||
1026 | devwarn(dev, "Unable to allocate struct smsc95xx_priv"); | ||
1027 | return -ENOMEM; | ||
1028 | } | ||
1029 | |||
1030 | spin_lock_init(&pdata->mac_cr_lock); | ||
1031 | |||
1032 | pdata->use_rx_csum = DEFAULT_RX_CSUM_ENABLE; | ||
1033 | |||
1034 | /* Init all registers */ | ||
1035 | ret = smsc95xx_reset(dev); | ||
1036 | |||
1037 | dev->net->do_ioctl = smsc95xx_ioctl; | ||
1038 | dev->net->ethtool_ops = &smsc95xx_ethtool_ops; | ||
1039 | dev->net->set_multicast_list = smsc95xx_set_multicast; | ||
1040 | dev->net->flags |= IFF_MULTICAST; | ||
1041 | dev->net->hard_header_len += SMSC95XX_TX_OVERHEAD; | ||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static void smsc95xx_unbind(struct usbnet *dev, struct usb_interface *intf) | ||
1046 | { | ||
1047 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
1048 | if (pdata) { | ||
1049 | if (netif_msg_ifdown(dev)) | ||
1050 | devdbg(dev, "free pdata"); | ||
1051 | kfree(pdata); | ||
1052 | pdata = NULL; | ||
1053 | dev->data[0] = 0; | ||
1054 | } | ||
1055 | } | ||
1056 | |||
1057 | static void smsc95xx_rx_csum_offload(struct sk_buff *skb) | ||
1058 | { | ||
1059 | skb->csum = *(u16 *)(skb_tail_pointer(skb) - 2); | ||
1060 | skb->ip_summed = CHECKSUM_COMPLETE; | ||
1061 | skb_trim(skb, skb->len - 2); | ||
1062 | } | ||
1063 | |||
1064 | static int smsc95xx_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
1065 | { | ||
1066 | struct smsc95xx_priv *pdata = (struct smsc95xx_priv *)(dev->data[0]); | ||
1067 | |||
1068 | while (skb->len > 0) { | ||
1069 | u32 header, align_count; | ||
1070 | struct sk_buff *ax_skb; | ||
1071 | unsigned char *packet; | ||
1072 | u16 size; | ||
1073 | |||
1074 | memcpy(&header, skb->data, sizeof(header)); | ||
1075 | le32_to_cpus(&header); | ||
1076 | skb_pull(skb, 4 + NET_IP_ALIGN); | ||
1077 | packet = skb->data; | ||
1078 | |||
1079 | /* get the packet length */ | ||
1080 | size = (u16)((header & RX_STS_FL_) >> 16); | ||
1081 | align_count = (4 - ((size + NET_IP_ALIGN) % 4)) % 4; | ||
1082 | |||
1083 | if (unlikely(header & RX_STS_ES_)) { | ||
1084 | if (netif_msg_rx_err(dev)) | ||
1085 | devdbg(dev, "Error header=0x%08x", header); | ||
1086 | dev->stats.rx_errors++; | ||
1087 | dev->stats.rx_dropped++; | ||
1088 | |||
1089 | if (header & RX_STS_CRC_) { | ||
1090 | dev->stats.rx_crc_errors++; | ||
1091 | } else { | ||
1092 | if (header & (RX_STS_TL_ | RX_STS_RF_)) | ||
1093 | dev->stats.rx_frame_errors++; | ||
1094 | |||
1095 | if ((header & RX_STS_LE_) && | ||
1096 | (!(header & RX_STS_FT_))) | ||
1097 | dev->stats.rx_length_errors++; | ||
1098 | } | ||
1099 | } else { | ||
1100 | /* ETH_FRAME_LEN + 4(CRC) + 2(COE) + 4(Vlan) */ | ||
1101 | if (unlikely(size > (ETH_FRAME_LEN + 12))) { | ||
1102 | if (netif_msg_rx_err(dev)) | ||
1103 | devdbg(dev, "size err header=0x%08x", | ||
1104 | header); | ||
1105 | return 0; | ||
1106 | } | ||
1107 | |||
1108 | /* last frame in this batch */ | ||
1109 | if (skb->len == size) { | ||
1110 | if (pdata->use_rx_csum) | ||
1111 | smsc95xx_rx_csum_offload(skb); | ||
1112 | |||
1113 | skb->truesize = size + sizeof(struct sk_buff); | ||
1114 | |||
1115 | return 1; | ||
1116 | } | ||
1117 | |||
1118 | ax_skb = skb_clone(skb, GFP_ATOMIC); | ||
1119 | if (unlikely(!ax_skb)) { | ||
1120 | devwarn(dev, "Error allocating skb"); | ||
1121 | return 0; | ||
1122 | } | ||
1123 | |||
1124 | ax_skb->len = size; | ||
1125 | ax_skb->data = packet; | ||
1126 | skb_set_tail_pointer(ax_skb, size); | ||
1127 | |||
1128 | if (pdata->use_rx_csum) | ||
1129 | smsc95xx_rx_csum_offload(ax_skb); | ||
1130 | |||
1131 | ax_skb->truesize = size + sizeof(struct sk_buff); | ||
1132 | |||
1133 | usbnet_skb_return(dev, ax_skb); | ||
1134 | } | ||
1135 | |||
1136 | skb_pull(skb, size); | ||
1137 | |||
1138 | /* padding bytes before the next frame starts */ | ||
1139 | if (skb->len) | ||
1140 | skb_pull(skb, align_count); | ||
1141 | } | ||
1142 | |||
1143 | if (unlikely(skb->len < 0)) { | ||
1144 | devwarn(dev, "invalid rx length<0 %d", skb->len); | ||
1145 | return 0; | ||
1146 | } | ||
1147 | |||
1148 | return 1; | ||
1149 | } | ||
1150 | |||
1151 | static struct sk_buff *smsc95xx_tx_fixup(struct usbnet *dev, | ||
1152 | struct sk_buff *skb, gfp_t flags) | ||
1153 | { | ||
1154 | u32 tx_cmd_a, tx_cmd_b; | ||
1155 | |||
1156 | if (skb_headroom(skb) < SMSC95XX_TX_OVERHEAD) { | ||
1157 | struct sk_buff *skb2 = skb_copy_expand(skb, | ||
1158 | SMSC95XX_TX_OVERHEAD, 0, flags); | ||
1159 | dev_kfree_skb_any(skb); | ||
1160 | skb = skb2; | ||
1161 | if (!skb) | ||
1162 | return NULL; | ||
1163 | } | ||
1164 | |||
1165 | skb_push(skb, 4); | ||
1166 | tx_cmd_b = (u32)(skb->len - 4); | ||
1167 | cpu_to_le32s(&tx_cmd_b); | ||
1168 | memcpy(skb->data, &tx_cmd_b, 4); | ||
1169 | |||
1170 | skb_push(skb, 4); | ||
1171 | tx_cmd_a = (u32)(skb->len - 8) | TX_CMD_A_FIRST_SEG_ | | ||
1172 | TX_CMD_A_LAST_SEG_; | ||
1173 | cpu_to_le32s(&tx_cmd_a); | ||
1174 | memcpy(skb->data, &tx_cmd_a, 4); | ||
1175 | |||
1176 | return skb; | ||
1177 | } | ||
1178 | |||
1179 | static const struct driver_info smsc95xx_info = { | ||
1180 | .description = "smsc95xx USB 2.0 Ethernet", | ||
1181 | .bind = smsc95xx_bind, | ||
1182 | .unbind = smsc95xx_unbind, | ||
1183 | .link_reset = smsc95xx_link_reset, | ||
1184 | .reset = smsc95xx_reset, | ||
1185 | .rx_fixup = smsc95xx_rx_fixup, | ||
1186 | .tx_fixup = smsc95xx_tx_fixup, | ||
1187 | .status = smsc95xx_status, | ||
1188 | .flags = FLAG_ETHER, | ||
1189 | }; | ||
1190 | |||
1191 | static const struct usb_device_id products[] = { | ||
1192 | { | ||
1193 | /* SMSC9500 USB Ethernet Device */ | ||
1194 | USB_DEVICE(0x0424, 0x9500), | ||
1195 | .driver_info = (unsigned long) &smsc95xx_info, | ||
1196 | }, | ||
1197 | { }, /* END */ | ||
1198 | }; | ||
1199 | MODULE_DEVICE_TABLE(usb, products); | ||
1200 | |||
1201 | static struct usb_driver smsc95xx_driver = { | ||
1202 | .name = "smsc95xx", | ||
1203 | .id_table = products, | ||
1204 | .probe = usbnet_probe, | ||
1205 | .suspend = usbnet_suspend, | ||
1206 | .resume = usbnet_resume, | ||
1207 | .disconnect = usbnet_disconnect, | ||
1208 | }; | ||
1209 | |||
1210 | static int __init smsc95xx_init(void) | ||
1211 | { | ||
1212 | return usb_register(&smsc95xx_driver); | ||
1213 | } | ||
1214 | module_init(smsc95xx_init); | ||
1215 | |||
1216 | static void __exit smsc95xx_exit(void) | ||
1217 | { | ||
1218 | usb_deregister(&smsc95xx_driver); | ||
1219 | } | ||
1220 | module_exit(smsc95xx_exit); | ||
1221 | |||
1222 | MODULE_AUTHOR("Nancy Lin"); | ||
1223 | MODULE_AUTHOR("Steve Glendinning <steve.glendinning@smsc.com>"); | ||
1224 | MODULE_DESCRIPTION("SMSC95XX USB 2.0 Ethernet Devices"); | ||
1225 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/smsc95xx.h b/drivers/net/usb/smsc95xx.h new file mode 100644 index 000000000000..66b5c84f302e --- /dev/null +++ b/drivers/net/usb/smsc95xx.h | |||
@@ -0,0 +1,253 @@ | |||
1 | /*************************************************************************** | ||
2 | * | ||
3 | * Copyright (C) 2007-2008 SMSC | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License | ||
7 | * as published by the Free Software Foundation; either version 2 | ||
8 | * of the License, or (at your option) any later version. | ||
9 | * | ||
10 | * This program is distributed in the hope that it will be useful, | ||
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
13 | * GNU General Public License for more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program; if not, write to the Free Software | ||
17 | * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
18 | * | ||
19 | *****************************************************************************/ | ||
20 | |||
21 | #ifndef _SMSC95XX_H | ||
22 | #define _SMSC95XX_H | ||
23 | |||
24 | /* Tx command words */ | ||
25 | #define TX_CMD_A_DATA_OFFSET_ (0x001F0000) | ||
26 | #define TX_CMD_A_FIRST_SEG_ (0x00002000) | ||
27 | #define TX_CMD_A_LAST_SEG_ (0x00001000) | ||
28 | #define TX_CMD_A_BUF_SIZE_ (0x000007FF) | ||
29 | |||
30 | #define TX_CMD_B_CSUM_ENABLE (0x00004000) | ||
31 | #define TX_CMD_B_ADD_CRC_DISABLE_ (0x00002000) | ||
32 | #define TX_CMD_B_DISABLE_PADDING_ (0x00001000) | ||
33 | #define TX_CMD_B_PKT_BYTE_LENGTH_ (0x000007FF) | ||
34 | |||
35 | /* Rx status word */ | ||
36 | #define RX_STS_FF_ (0x40000000) /* Filter Fail */ | ||
37 | #define RX_STS_FL_ (0x3FFF0000) /* Frame Length */ | ||
38 | #define RX_STS_ES_ (0x00008000) /* Error Summary */ | ||
39 | #define RX_STS_BF_ (0x00002000) /* Broadcast Frame */ | ||
40 | #define RX_STS_LE_ (0x00001000) /* Length Error */ | ||
41 | #define RX_STS_RF_ (0x00000800) /* Runt Frame */ | ||
42 | #define RX_STS_MF_ (0x00000400) /* Multicast Frame */ | ||
43 | #define RX_STS_TL_ (0x00000080) /* Frame too long */ | ||
44 | #define RX_STS_CS_ (0x00000040) /* Collision Seen */ | ||
45 | #define RX_STS_FT_ (0x00000020) /* Frame Type */ | ||
46 | #define RX_STS_RW_ (0x00000010) /* Receive Watchdog */ | ||
47 | #define RX_STS_ME_ (0x00000008) /* Mii Error */ | ||
48 | #define RX_STS_DB_ (0x00000004) /* Dribbling */ | ||
49 | #define RX_STS_CRC_ (0x00000002) /* CRC Error */ | ||
50 | |||
51 | /* SCSRs */ | ||
52 | #define ID_REV (0x00) | ||
53 | #define ID_REV_CHIP_ID_MASK_ (0xFFFF0000) | ||
54 | #define ID_REV_CHIP_REV_MASK_ (0x0000FFFF) | ||
55 | #define ID_REV_CHIP_ID_9500_ (0x9500) | ||
56 | |||
57 | #define INT_STS (0x08) | ||
58 | #define INT_STS_TX_STOP_ (0x00020000) | ||
59 | #define INT_STS_RX_STOP_ (0x00010000) | ||
60 | #define INT_STS_PHY_INT_ (0x00008000) | ||
61 | #define INT_STS_TXE_ (0x00004000) | ||
62 | #define INT_STS_TDFU_ (0x00002000) | ||
63 | #define INT_STS_TDFO_ (0x00001000) | ||
64 | #define INT_STS_RXDF_ (0x00000800) | ||
65 | #define INT_STS_GPIOS_ (0x000007FF) | ||
66 | |||
67 | #define RX_CFG (0x0C) | ||
68 | #define RX_FIFO_FLUSH_ (0x00000001) | ||
69 | |||
70 | #define TX_CFG (0x10) | ||
71 | #define TX_CFG_ON_ (0x00000004) | ||
72 | #define TX_CFG_STOP_ (0x00000002) | ||
73 | #define TX_CFG_FIFO_FLUSH_ (0x00000001) | ||
74 | |||
75 | #define HW_CFG (0x14) | ||
76 | #define HW_CFG_BIR_ (0x00001000) | ||
77 | #define HW_CFG_LEDB_ (0x00000800) | ||
78 | #define HW_CFG_RXDOFF_ (0x00000600) | ||
79 | #define HW_CFG_DRP_ (0x00000040) | ||
80 | #define HW_CFG_MEF_ (0x00000020) | ||
81 | #define HW_CFG_LRST_ (0x00000008) | ||
82 | #define HW_CFG_PSEL_ (0x00000004) | ||
83 | #define HW_CFG_BCE_ (0x00000002) | ||
84 | #define HW_CFG_SRST_ (0x00000001) | ||
85 | |||
86 | #define PM_CTRL (0x20) | ||
87 | #define PM_CTL_DEV_RDY_ (0x00000080) | ||
88 | #define PM_CTL_SUS_MODE_ (0x00000060) | ||
89 | #define PM_CTL_SUS_MODE_0 (0x00000000) | ||
90 | #define PM_CTL_SUS_MODE_1 (0x00000020) | ||
91 | #define PM_CTL_SUS_MODE_2 (0x00000060) | ||
92 | #define PM_CTL_PHY_RST_ (0x00000010) | ||
93 | #define PM_CTL_WOL_EN_ (0x00000008) | ||
94 | #define PM_CTL_ED_EN_ (0x00000004) | ||
95 | #define PM_CTL_WUPS_ (0x00000003) | ||
96 | #define PM_CTL_WUPS_NO_ (0x00000000) | ||
97 | #define PM_CTL_WUPS_ED_ (0x00000001) | ||
98 | #define PM_CTL_WUPS_WOL_ (0x00000002) | ||
99 | #define PM_CTL_WUPS_MULTI_ (0x00000003) | ||
100 | |||
101 | #define LED_GPIO_CFG (0x24) | ||
102 | |||
103 | #define GPIO_CFG (0x28) | ||
104 | |||
105 | #define AFC_CFG (0x2C) | ||
106 | |||
107 | /* Hi watermark = 15.5Kb (~10 mtu pkts) */ | ||
108 | /* low watermark = 3k (~2 mtu pkts) */ | ||
109 | /* backpressure duration = ~ 350us */ | ||
110 | /* Apply FC on any frame. */ | ||
111 | #define AFC_CFG_DEFAULT (0x00F830A1) | ||
112 | |||
113 | #define E2P_CMD (0x30) | ||
114 | #define E2P_CMD_BUSY_ (0x80000000) | ||
115 | #define E2P_CMD_MASK_ (0x70000000) | ||
116 | #define E2P_CMD_READ_ (0x00000000) | ||
117 | #define E2P_CMD_EWDS_ (0x10000000) | ||
118 | #define E2P_CMD_EWEN_ (0x20000000) | ||
119 | #define E2P_CMD_WRITE_ (0x30000000) | ||
120 | #define E2P_CMD_WRAL_ (0x40000000) | ||
121 | #define E2P_CMD_ERASE_ (0x50000000) | ||
122 | #define E2P_CMD_ERAL_ (0x60000000) | ||
123 | #define E2P_CMD_RELOAD_ (0x70000000) | ||
124 | #define E2P_CMD_TIMEOUT_ (0x00000400) | ||
125 | #define E2P_CMD_LOADED_ (0x00000200) | ||
126 | #define E2P_CMD_ADDR_ (0x000001FF) | ||
127 | |||
128 | #define MAX_EEPROM_SIZE (512) | ||
129 | |||
130 | #define E2P_DATA (0x34) | ||
131 | #define E2P_DATA_MASK_ (0x000000FF) | ||
132 | |||
133 | #define BURST_CAP (0x38) | ||
134 | |||
135 | #define GPIO_WAKE (0x64) | ||
136 | |||
137 | #define INT_EP_CTL (0x68) | ||
138 | #define INT_EP_CTL_INTEP_ (0x80000000) | ||
139 | #define INT_EP_CTL_MACRTO_ (0x00080000) | ||
140 | #define INT_EP_CTL_TX_STOP_ (0x00020000) | ||
141 | #define INT_EP_CTL_RX_STOP_ (0x00010000) | ||
142 | #define INT_EP_CTL_PHY_INT_ (0x00008000) | ||
143 | #define INT_EP_CTL_TXE_ (0x00004000) | ||
144 | #define INT_EP_CTL_TDFU_ (0x00002000) | ||
145 | #define INT_EP_CTL_TDFO_ (0x00001000) | ||
146 | #define INT_EP_CTL_RXDF_ (0x00000800) | ||
147 | #define INT_EP_CTL_GPIOS_ (0x000007FF) | ||
148 | |||
149 | #define BULK_IN_DLY (0x6C) | ||
150 | |||
151 | /* MAC CSRs */ | ||
152 | #define MAC_CR (0x100) | ||
153 | #define MAC_CR_RXALL_ (0x80000000) | ||
154 | #define MAC_CR_RCVOWN_ (0x00800000) | ||
155 | #define MAC_CR_LOOPBK_ (0x00200000) | ||
156 | #define MAC_CR_FDPX_ (0x00100000) | ||
157 | #define MAC_CR_MCPAS_ (0x00080000) | ||
158 | #define MAC_CR_PRMS_ (0x00040000) | ||
159 | #define MAC_CR_INVFILT_ (0x00020000) | ||
160 | #define MAC_CR_PASSBAD_ (0x00010000) | ||
161 | #define MAC_CR_HFILT_ (0x00008000) | ||
162 | #define MAC_CR_HPFILT_ (0x00002000) | ||
163 | #define MAC_CR_LCOLL_ (0x00001000) | ||
164 | #define MAC_CR_BCAST_ (0x00000800) | ||
165 | #define MAC_CR_DISRTY_ (0x00000400) | ||
166 | #define MAC_CR_PADSTR_ (0x00000100) | ||
167 | #define MAC_CR_BOLMT_MASK (0x000000C0) | ||
168 | #define MAC_CR_DFCHK_ (0x00000020) | ||
169 | #define MAC_CR_TXEN_ (0x00000008) | ||
170 | #define MAC_CR_RXEN_ (0x00000004) | ||
171 | |||
172 | #define ADDRH (0x104) | ||
173 | |||
174 | #define ADDRL (0x108) | ||
175 | |||
176 | #define HASHH (0x10C) | ||
177 | |||
178 | #define HASHL (0x110) | ||
179 | |||
180 | #define MII_ADDR (0x114) | ||
181 | #define MII_WRITE_ (0x02) | ||
182 | #define MII_BUSY_ (0x01) | ||
183 | #define MII_READ_ (0x00) /* ~of MII Write bit */ | ||
184 | |||
185 | #define MII_DATA (0x118) | ||
186 | |||
187 | #define FLOW (0x11C) | ||
188 | #define FLOW_FCPT_ (0xFFFF0000) | ||
189 | #define FLOW_FCPASS_ (0x00000004) | ||
190 | #define FLOW_FCEN_ (0x00000002) | ||
191 | #define FLOW_FCBSY_ (0x00000001) | ||
192 | |||
193 | #define VLAN1 (0x120) | ||
194 | |||
195 | #define VLAN2 (0x124) | ||
196 | |||
197 | #define WUFF (0x128) | ||
198 | |||
199 | #define WUCSR (0x12C) | ||
200 | |||
201 | #define COE_CR (0x130) | ||
202 | #define Tx_COE_EN_ (0x00010000) | ||
203 | #define Rx_COE_MODE_ (0x00000002) | ||
204 | #define Rx_COE_EN_ (0x00000001) | ||
205 | |||
206 | /* Vendor-specific PHY Definitions */ | ||
207 | |||
208 | /* Mode Control/Status Register */ | ||
209 | #define PHY_MODE_CTRL_STS (17) | ||
210 | #define MODE_CTRL_STS_EDPWRDOWN_ ((u16)0x2000) | ||
211 | #define MODE_CTRL_STS_ENERGYON_ ((u16)0x0002) | ||
212 | |||
213 | #define SPECIAL_CTRL_STS (27) | ||
214 | #define SPECIAL_CTRL_STS_OVRRD_AMDIX_ ((u16)0x8000) | ||
215 | #define SPECIAL_CTRL_STS_AMDIX_ENABLE_ ((u16)0x4000) | ||
216 | #define SPECIAL_CTRL_STS_AMDIX_STATE_ ((u16)0x2000) | ||
217 | |||
218 | #define PHY_INT_SRC (29) | ||
219 | #define PHY_INT_SRC_ENERGY_ON_ ((u16)0x0080) | ||
220 | #define PHY_INT_SRC_ANEG_COMP_ ((u16)0x0040) | ||
221 | #define PHY_INT_SRC_REMOTE_FAULT_ ((u16)0x0020) | ||
222 | #define PHY_INT_SRC_LINK_DOWN_ ((u16)0x0010) | ||
223 | |||
224 | #define PHY_INT_MASK (30) | ||
225 | #define PHY_INT_MASK_ENERGY_ON_ ((u16)0x0080) | ||
226 | #define PHY_INT_MASK_ANEG_COMP_ ((u16)0x0040) | ||
227 | #define PHY_INT_MASK_REMOTE_FAULT_ ((u16)0x0020) | ||
228 | #define PHY_INT_MASK_LINK_DOWN_ ((u16)0x0010) | ||
229 | #define PHY_INT_MASK_DEFAULT_ (PHY_INT_MASK_ANEG_COMP_ | \ | ||
230 | PHY_INT_MASK_LINK_DOWN_) | ||
231 | |||
232 | #define PHY_SPECIAL (31) | ||
233 | #define PHY_SPECIAL_SPD_ ((u16)0x001C) | ||
234 | #define PHY_SPECIAL_SPD_10HALF_ ((u16)0x0004) | ||
235 | #define PHY_SPECIAL_SPD_10FULL_ ((u16)0x0014) | ||
236 | #define PHY_SPECIAL_SPD_100HALF_ ((u16)0x0008) | ||
237 | #define PHY_SPECIAL_SPD_100FULL_ ((u16)0x0018) | ||
238 | |||
239 | /* USB Vendor Requests */ | ||
240 | #define USB_VENDOR_REQUEST_WRITE_REGISTER 0xA0 | ||
241 | #define USB_VENDOR_REQUEST_READ_REGISTER 0xA1 | ||
242 | #define USB_VENDOR_REQUEST_GET_STATS 0xA2 | ||
243 | |||
244 | /* Interrupt Endpoint status word bitfields */ | ||
245 | #define INT_ENP_TX_STOP_ ((u32)BIT(17)) | ||
246 | #define INT_ENP_RX_STOP_ ((u32)BIT(16)) | ||
247 | #define INT_ENP_PHY_INT_ ((u32)BIT(15)) | ||
248 | #define INT_ENP_TXE_ ((u32)BIT(14)) | ||
249 | #define INT_ENP_TDFU_ ((u32)BIT(13)) | ||
250 | #define INT_ENP_TDFO_ ((u32)BIT(12)) | ||
251 | #define INT_ENP_RXDF_ ((u32)BIT(11)) | ||
252 | |||
253 | #endif /* _SMSC95XX_H */ | ||