diff options
author | Liu Junliang <liujunliang_ljl@163.com> | 2014-02-10 01:31:42 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2014-02-10 19:53:06 -0500 |
commit | 19a38d8e0aa33b4f4d11d3b4baa902ad169daa80 (patch) | |
tree | a6785e222473f8242491ec0e96c96a7cef02cba4 | |
parent | bf06200e732de613a1277984bf34d1a21c2de03d (diff) |
USB2NET : SR9800 : One chip USB2.0 USB2NET SR9800 Device Driver Support
Signed-off-by: Liu Junliang <liujunliang_ljl@163.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/usb/Kconfig | 16 | ||||
-rw-r--r-- | drivers/net/usb/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/usb/sr9800.c | 870 | ||||
-rw-r--r-- | drivers/net/usb/sr9800.h | 202 |
4 files changed, 1089 insertions, 0 deletions
diff --git a/drivers/net/usb/Kconfig b/drivers/net/usb/Kconfig index 6b638a066c1d..409499fdb157 100644 --- a/drivers/net/usb/Kconfig +++ b/drivers/net/usb/Kconfig | |||
@@ -292,6 +292,22 @@ config USB_NET_SR9700 | |||
292 | This option adds support for CoreChip-sz SR9700 based USB 1.1 | 292 | This option adds support for CoreChip-sz SR9700 based USB 1.1 |
293 | 10/100 Ethernet adapters. | 293 | 10/100 Ethernet adapters. |
294 | 294 | ||
295 | config USB_NET_SR9800 | ||
296 | tristate "CoreChip-sz SR9800 based USB 2.0 10/100 ethernet devices" | ||
297 | depends on USB_USBNET | ||
298 | select CRC32 | ||
299 | default y | ||
300 | ---help--- | ||
301 | Say Y if you want to use one of the following 100Mbps USB Ethernet | ||
302 | device based on the CoreChip-sz SR9800 chip. | ||
303 | |||
304 | This driver makes the adapter appear as a normal Ethernet interface, | ||
305 | typically on eth0, if it is the only ethernet device, or perhaps on | ||
306 | eth1, if you have a PCI or ISA ethernet card installed. | ||
307 | |||
308 | To compile this driver as a module, choose M here: the | ||
309 | module will be called sr9800. | ||
310 | |||
295 | config USB_NET_SMSC75XX | 311 | config USB_NET_SMSC75XX |
296 | tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices" | 312 | tristate "SMSC LAN75XX based USB 2.0 gigabit ethernet devices" |
297 | depends on USB_USBNET | 313 | depends on USB_USBNET |
diff --git a/drivers/net/usb/Makefile b/drivers/net/usb/Makefile index b17b5e88bbaf..433f0a00c683 100644 --- a/drivers/net/usb/Makefile +++ b/drivers/net/usb/Makefile | |||
@@ -15,6 +15,7 @@ obj-$(CONFIG_USB_NET_CDCETHER) += cdc_ether.o r815x.o | |||
15 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o | 15 | obj-$(CONFIG_USB_NET_CDC_EEM) += cdc_eem.o |
16 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o | 16 | obj-$(CONFIG_USB_NET_DM9601) += dm9601.o |
17 | obj-$(CONFIG_USB_NET_SR9700) += sr9700.o | 17 | obj-$(CONFIG_USB_NET_SR9700) += sr9700.o |
18 | obj-$(CONFIG_USB_NET_SR9800) += sr9800.o | ||
18 | obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o | 19 | obj-$(CONFIG_USB_NET_SMSC75XX) += smsc75xx.o |
19 | obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o | 20 | obj-$(CONFIG_USB_NET_SMSC95XX) += smsc95xx.o |
20 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o | 21 | obj-$(CONFIG_USB_NET_GL620A) += gl620a.o |
diff --git a/drivers/net/usb/sr9800.c b/drivers/net/usb/sr9800.c new file mode 100644 index 000000000000..4175eb9fdeca --- /dev/null +++ b/drivers/net/usb/sr9800.c | |||
@@ -0,0 +1,870 @@ | |||
1 | /* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices | ||
2 | * | ||
3 | * Author : Liu Junliang <liujunliang_ljl@163.com> | ||
4 | * | ||
5 | * Based on asix_common.c, asix_devices.c | ||
6 | * | ||
7 | * This file is licensed under the terms of the GNU General Public License | ||
8 | * version 2. This program is licensed "as is" without any warranty of any | ||
9 | * kind, whether express or implied.* | ||
10 | */ | ||
11 | |||
12 | #include <linux/module.h> | ||
13 | #include <linux/kmod.h> | ||
14 | #include <linux/init.h> | ||
15 | #include <linux/netdevice.h> | ||
16 | #include <linux/etherdevice.h> | ||
17 | #include <linux/ethtool.h> | ||
18 | #include <linux/workqueue.h> | ||
19 | #include <linux/mii.h> | ||
20 | #include <linux/usb.h> | ||
21 | #include <linux/crc32.h> | ||
22 | #include <linux/usb/usbnet.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/if_vlan.h> | ||
25 | |||
26 | #include "sr9800.h" | ||
27 | |||
28 | static int sr_read_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
29 | u16 size, void *data) | ||
30 | { | ||
31 | int err; | ||
32 | |||
33 | err = usbnet_read_cmd(dev, cmd, SR_REQ_RD_REG, value, index, | ||
34 | data, size); | ||
35 | if ((err != size) && (err >= 0)) | ||
36 | err = -EINVAL; | ||
37 | |||
38 | return err; | ||
39 | } | ||
40 | |||
41 | static int sr_write_cmd(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
42 | u16 size, void *data) | ||
43 | { | ||
44 | int err; | ||
45 | |||
46 | err = usbnet_write_cmd(dev, cmd, SR_REQ_WR_REG, value, index, | ||
47 | data, size); | ||
48 | if ((err != size) && (err >= 0)) | ||
49 | err = -EINVAL; | ||
50 | |||
51 | return err; | ||
52 | } | ||
53 | |||
54 | static void | ||
55 | sr_write_cmd_async(struct usbnet *dev, u8 cmd, u16 value, u16 index, | ||
56 | u16 size, void *data) | ||
57 | { | ||
58 | usbnet_write_cmd_async(dev, cmd, SR_REQ_WR_REG, value, index, data, | ||
59 | size); | ||
60 | } | ||
61 | |||
62 | static int sr_rx_fixup(struct usbnet *dev, struct sk_buff *skb) | ||
63 | { | ||
64 | int offset = 0; | ||
65 | |||
66 | while (offset + sizeof(u32) < skb->len) { | ||
67 | struct sk_buff *sr_skb; | ||
68 | u16 size; | ||
69 | u32 header = get_unaligned_le32(skb->data + offset); | ||
70 | |||
71 | offset += sizeof(u32); | ||
72 | /* get the packet length */ | ||
73 | size = (u16) (header & 0x7ff); | ||
74 | if (size != ((~header >> 16) & 0x07ff)) { | ||
75 | netdev_err(dev->net, "%s : Bad Header Length\n", | ||
76 | __func__); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | if ((size > dev->net->mtu + ETH_HLEN + VLAN_HLEN) || | ||
81 | (size + offset > skb->len)) { | ||
82 | netdev_err(dev->net, "%s : Bad RX Length %d\n", | ||
83 | __func__, size); | ||
84 | return 0; | ||
85 | } | ||
86 | sr_skb = netdev_alloc_skb_ip_align(dev->net, size); | ||
87 | if (!sr_skb) | ||
88 | return 0; | ||
89 | |||
90 | skb_put(sr_skb, size); | ||
91 | memcpy(sr_skb->data, skb->data + offset, size); | ||
92 | usbnet_skb_return(dev, sr_skb); | ||
93 | |||
94 | offset += (size + 1) & 0xfffe; | ||
95 | } | ||
96 | |||
97 | if (skb->len != offset) { | ||
98 | netdev_err(dev->net, "%s : Bad SKB Length %d\n", __func__, | ||
99 | skb->len); | ||
100 | return 0; | ||
101 | } | ||
102 | |||
103 | return 1; | ||
104 | } | ||
105 | |||
106 | static struct sk_buff *sr_tx_fixup(struct usbnet *dev, struct sk_buff *skb, | ||
107 | gfp_t flags) | ||
108 | { | ||
109 | int headroom = skb_headroom(skb); | ||
110 | int tailroom = skb_tailroom(skb); | ||
111 | u32 padbytes = 0xffff0000; | ||
112 | u32 packet_len; | ||
113 | int padlen; | ||
114 | |||
115 | padlen = ((skb->len + 4) % (dev->maxpacket - 1)) ? 0 : 4; | ||
116 | |||
117 | if ((!skb_cloned(skb)) && ((headroom + tailroom) >= (4 + padlen))) { | ||
118 | if ((headroom < 4) || (tailroom < padlen)) { | ||
119 | skb->data = memmove(skb->head + 4, skb->data, | ||
120 | skb->len); | ||
121 | skb_set_tail_pointer(skb, skb->len); | ||
122 | } | ||
123 | } else { | ||
124 | struct sk_buff *skb2; | ||
125 | skb2 = skb_copy_expand(skb, 4, padlen, flags); | ||
126 | dev_kfree_skb_any(skb); | ||
127 | skb = skb2; | ||
128 | if (!skb) | ||
129 | return NULL; | ||
130 | } | ||
131 | |||
132 | skb_push(skb, 4); | ||
133 | packet_len = (((skb->len - 4) ^ 0x0000ffff) << 16) + (skb->len - 4); | ||
134 | cpu_to_le32s(&packet_len); | ||
135 | skb_copy_to_linear_data(skb, &packet_len, sizeof(packet_len)); | ||
136 | |||
137 | if (padlen) { | ||
138 | cpu_to_le32s(&padbytes); | ||
139 | memcpy(skb_tail_pointer(skb), &padbytes, sizeof(padbytes)); | ||
140 | skb_put(skb, sizeof(padbytes)); | ||
141 | } | ||
142 | |||
143 | return skb; | ||
144 | } | ||
145 | |||
146 | static void sr_status(struct usbnet *dev, struct urb *urb) | ||
147 | { | ||
148 | struct sr9800_int_data *event; | ||
149 | int link; | ||
150 | |||
151 | if (urb->actual_length < 8) | ||
152 | return; | ||
153 | |||
154 | event = urb->transfer_buffer; | ||
155 | link = event->link & 0x01; | ||
156 | if (netif_carrier_ok(dev->net) != link) { | ||
157 | usbnet_link_change(dev, link, 1); | ||
158 | netdev_dbg(dev->net, "Link Status is: %d\n", link); | ||
159 | } | ||
160 | |||
161 | return; | ||
162 | } | ||
163 | |||
164 | static inline int sr_set_sw_mii(struct usbnet *dev) | ||
165 | { | ||
166 | int ret; | ||
167 | |||
168 | ret = sr_write_cmd(dev, SR_CMD_SET_SW_MII, 0x0000, 0, 0, NULL); | ||
169 | if (ret < 0) | ||
170 | netdev_err(dev->net, "Failed to enable software MII access\n"); | ||
171 | return ret; | ||
172 | } | ||
173 | |||
174 | static inline int sr_set_hw_mii(struct usbnet *dev) | ||
175 | { | ||
176 | int ret; | ||
177 | |||
178 | ret = sr_write_cmd(dev, SR_CMD_SET_HW_MII, 0x0000, 0, 0, NULL); | ||
179 | if (ret < 0) | ||
180 | netdev_err(dev->net, "Failed to enable hardware MII access\n"); | ||
181 | return ret; | ||
182 | } | ||
183 | |||
184 | static inline int sr_get_phy_addr(struct usbnet *dev) | ||
185 | { | ||
186 | u8 buf[2]; | ||
187 | int ret; | ||
188 | |||
189 | ret = sr_read_cmd(dev, SR_CMD_READ_PHY_ID, 0, 0, 2, buf); | ||
190 | if (ret < 0) { | ||
191 | netdev_err(dev->net, "%s : Error reading PHYID register:%02x\n", | ||
192 | __func__, ret); | ||
193 | goto out; | ||
194 | } | ||
195 | netdev_dbg(dev->net, "%s : returning 0x%04x\n", __func__, | ||
196 | *((__le16 *)buf)); | ||
197 | |||
198 | ret = buf[1]; | ||
199 | |||
200 | out: | ||
201 | return ret; | ||
202 | } | ||
203 | |||
204 | static int sr_sw_reset(struct usbnet *dev, u8 flags) | ||
205 | { | ||
206 | int ret; | ||
207 | |||
208 | ret = sr_write_cmd(dev, SR_CMD_SW_RESET, flags, 0, 0, NULL); | ||
209 | if (ret < 0) | ||
210 | netdev_err(dev->net, "Failed to send software reset:%02x\n", | ||
211 | ret); | ||
212 | |||
213 | return ret; | ||
214 | } | ||
215 | |||
216 | static u16 sr_read_rx_ctl(struct usbnet *dev) | ||
217 | { | ||
218 | __le16 v; | ||
219 | int ret; | ||
220 | |||
221 | ret = sr_read_cmd(dev, SR_CMD_READ_RX_CTL, 0, 0, 2, &v); | ||
222 | if (ret < 0) { | ||
223 | netdev_err(dev->net, "Error reading RX_CTL register:%02x\n", | ||
224 | ret); | ||
225 | goto out; | ||
226 | } | ||
227 | |||
228 | ret = le16_to_cpu(v); | ||
229 | out: | ||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | static int sr_write_rx_ctl(struct usbnet *dev, u16 mode) | ||
234 | { | ||
235 | int ret; | ||
236 | |||
237 | netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); | ||
238 | ret = sr_write_cmd(dev, SR_CMD_WRITE_RX_CTL, mode, 0, 0, NULL); | ||
239 | if (ret < 0) | ||
240 | netdev_err(dev->net, | ||
241 | "Failed to write RX_CTL mode to 0x%04x:%02x\n", | ||
242 | mode, ret); | ||
243 | |||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | static u16 sr_read_medium_status(struct usbnet *dev) | ||
248 | { | ||
249 | __le16 v; | ||
250 | int ret; | ||
251 | |||
252 | ret = sr_read_cmd(dev, SR_CMD_READ_MEDIUM_STATUS, 0, 0, 2, &v); | ||
253 | if (ret < 0) { | ||
254 | netdev_err(dev->net, | ||
255 | "Error reading Medium Status register:%02x\n", ret); | ||
256 | return ret; /* TODO: callers not checking for error ret */ | ||
257 | } | ||
258 | |||
259 | return le16_to_cpu(v); | ||
260 | } | ||
261 | |||
262 | static int sr_write_medium_mode(struct usbnet *dev, u16 mode) | ||
263 | { | ||
264 | int ret; | ||
265 | |||
266 | netdev_dbg(dev->net, "%s : mode = 0x%04x\n", __func__, mode); | ||
267 | ret = sr_write_cmd(dev, SR_CMD_WRITE_MEDIUM_MODE, mode, 0, 0, NULL); | ||
268 | if (ret < 0) | ||
269 | netdev_err(dev->net, | ||
270 | "Failed to write Medium Mode mode to 0x%04x:%02x\n", | ||
271 | mode, ret); | ||
272 | return ret; | ||
273 | } | ||
274 | |||
275 | static int sr_write_gpio(struct usbnet *dev, u16 value, int sleep) | ||
276 | { | ||
277 | int ret; | ||
278 | |||
279 | netdev_dbg(dev->net, "%s : value = 0x%04x\n", __func__, value); | ||
280 | ret = sr_write_cmd(dev, SR_CMD_WRITE_GPIOS, value, 0, 0, NULL); | ||
281 | if (ret < 0) | ||
282 | netdev_err(dev->net, "Failed to write GPIO value 0x%04x:%02x\n", | ||
283 | value, ret); | ||
284 | if (sleep) | ||
285 | msleep(sleep); | ||
286 | |||
287 | return ret; | ||
288 | } | ||
289 | |||
290 | /* SR9800 have a 16-bit RX_CTL value */ | ||
291 | static void sr_set_multicast(struct net_device *net) | ||
292 | { | ||
293 | struct usbnet *dev = netdev_priv(net); | ||
294 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
295 | u16 rx_ctl = SR_DEFAULT_RX_CTL; | ||
296 | |||
297 | if (net->flags & IFF_PROMISC) { | ||
298 | rx_ctl |= SR_RX_CTL_PRO; | ||
299 | } else if (net->flags & IFF_ALLMULTI || | ||
300 | netdev_mc_count(net) > SR_MAX_MCAST) { | ||
301 | rx_ctl |= SR_RX_CTL_AMALL; | ||
302 | } else if (netdev_mc_empty(net)) { | ||
303 | /* just broadcast and directed */ | ||
304 | } else { | ||
305 | /* We use the 20 byte dev->data | ||
306 | * for our 8 byte filter buffer | ||
307 | * to avoid allocating memory that | ||
308 | * is tricky to free later | ||
309 | */ | ||
310 | struct netdev_hw_addr *ha; | ||
311 | u32 crc_bits; | ||
312 | |||
313 | memset(data->multi_filter, 0, SR_MCAST_FILTER_SIZE); | ||
314 | |||
315 | /* Build the multicast hash filter. */ | ||
316 | netdev_for_each_mc_addr(ha, net) { | ||
317 | crc_bits = ether_crc(ETH_ALEN, ha->addr) >> 26; | ||
318 | data->multi_filter[crc_bits >> 3] |= | ||
319 | 1 << (crc_bits & 7); | ||
320 | } | ||
321 | |||
322 | sr_write_cmd_async(dev, SR_CMD_WRITE_MULTI_FILTER, 0, 0, | ||
323 | SR_MCAST_FILTER_SIZE, data->multi_filter); | ||
324 | |||
325 | rx_ctl |= SR_RX_CTL_AM; | ||
326 | } | ||
327 | |||
328 | sr_write_cmd_async(dev, SR_CMD_WRITE_RX_CTL, rx_ctl, 0, 0, NULL); | ||
329 | } | ||
330 | |||
331 | static int sr_mdio_read(struct net_device *net, int phy_id, int loc) | ||
332 | { | ||
333 | struct usbnet *dev = netdev_priv(net); | ||
334 | __le16 res; | ||
335 | |||
336 | mutex_lock(&dev->phy_mutex); | ||
337 | sr_set_sw_mii(dev); | ||
338 | sr_read_cmd(dev, SR_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, &res); | ||
339 | sr_set_hw_mii(dev); | ||
340 | mutex_unlock(&dev->phy_mutex); | ||
341 | |||
342 | netdev_dbg(dev->net, | ||
343 | "%s : phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n", __func__, | ||
344 | phy_id, loc, le16_to_cpu(res)); | ||
345 | |||
346 | return le16_to_cpu(res); | ||
347 | } | ||
348 | |||
349 | static void | ||
350 | sr_mdio_write(struct net_device *net, int phy_id, int loc, int val) | ||
351 | { | ||
352 | struct usbnet *dev = netdev_priv(net); | ||
353 | __le16 res = cpu_to_le16(val); | ||
354 | |||
355 | netdev_dbg(dev->net, | ||
356 | "%s : phy_id=0x%02x, loc=0x%02x, val=0x%04x\n", __func__, | ||
357 | phy_id, loc, val); | ||
358 | mutex_lock(&dev->phy_mutex); | ||
359 | sr_set_sw_mii(dev); | ||
360 | sr_write_cmd(dev, SR_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, &res); | ||
361 | sr_set_hw_mii(dev); | ||
362 | mutex_unlock(&dev->phy_mutex); | ||
363 | } | ||
364 | |||
365 | /* Get the PHY Identifier from the PHYSID1 & PHYSID2 MII registers */ | ||
366 | static u32 sr_get_phyid(struct usbnet *dev) | ||
367 | { | ||
368 | int phy_reg; | ||
369 | u32 phy_id; | ||
370 | int i; | ||
371 | |||
372 | /* Poll for the rare case the FW or phy isn't ready yet. */ | ||
373 | for (i = 0; i < 100; i++) { | ||
374 | phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID1); | ||
375 | if (phy_reg != 0 && phy_reg != 0xFFFF) | ||
376 | break; | ||
377 | mdelay(1); | ||
378 | } | ||
379 | |||
380 | if (phy_reg <= 0 || phy_reg == 0xFFFF) | ||
381 | return 0; | ||
382 | |||
383 | phy_id = (phy_reg & 0xffff) << 16; | ||
384 | |||
385 | phy_reg = sr_mdio_read(dev->net, dev->mii.phy_id, MII_PHYSID2); | ||
386 | if (phy_reg < 0) | ||
387 | return 0; | ||
388 | |||
389 | phy_id |= (phy_reg & 0xffff); | ||
390 | |||
391 | return phy_id; | ||
392 | } | ||
393 | |||
394 | static void | ||
395 | sr_get_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
396 | { | ||
397 | struct usbnet *dev = netdev_priv(net); | ||
398 | u8 opt; | ||
399 | |||
400 | if (sr_read_cmd(dev, SR_CMD_READ_MONITOR_MODE, 0, 0, 1, &opt) < 0) { | ||
401 | wolinfo->supported = 0; | ||
402 | wolinfo->wolopts = 0; | ||
403 | return; | ||
404 | } | ||
405 | wolinfo->supported = WAKE_PHY | WAKE_MAGIC; | ||
406 | wolinfo->wolopts = 0; | ||
407 | if (opt & SR_MONITOR_LINK) | ||
408 | wolinfo->wolopts |= WAKE_PHY; | ||
409 | if (opt & SR_MONITOR_MAGIC) | ||
410 | wolinfo->wolopts |= WAKE_MAGIC; | ||
411 | } | ||
412 | |||
413 | static int | ||
414 | sr_set_wol(struct net_device *net, struct ethtool_wolinfo *wolinfo) | ||
415 | { | ||
416 | struct usbnet *dev = netdev_priv(net); | ||
417 | u8 opt = 0; | ||
418 | |||
419 | if (wolinfo->wolopts & WAKE_PHY) | ||
420 | opt |= SR_MONITOR_LINK; | ||
421 | if (wolinfo->wolopts & WAKE_MAGIC) | ||
422 | opt |= SR_MONITOR_MAGIC; | ||
423 | |||
424 | if (sr_write_cmd(dev, SR_CMD_WRITE_MONITOR_MODE, | ||
425 | opt, 0, 0, NULL) < 0) | ||
426 | return -EINVAL; | ||
427 | |||
428 | return 0; | ||
429 | } | ||
430 | |||
431 | static int sr_get_eeprom_len(struct net_device *net) | ||
432 | { | ||
433 | struct usbnet *dev = netdev_priv(net); | ||
434 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
435 | |||
436 | return data->eeprom_len; | ||
437 | } | ||
438 | |||
439 | static int sr_get_eeprom(struct net_device *net, | ||
440 | struct ethtool_eeprom *eeprom, u8 *data) | ||
441 | { | ||
442 | struct usbnet *dev = netdev_priv(net); | ||
443 | __le16 *ebuf = (__le16 *)data; | ||
444 | int ret; | ||
445 | int i; | ||
446 | |||
447 | /* Crude hack to ensure that we don't overwrite memory | ||
448 | * if an odd length is supplied | ||
449 | */ | ||
450 | if (eeprom->len % 2) | ||
451 | return -EINVAL; | ||
452 | |||
453 | eeprom->magic = SR_EEPROM_MAGIC; | ||
454 | |||
455 | /* sr9800 returns 2 bytes from eeprom on read */ | ||
456 | for (i = 0; i < eeprom->len / 2; i++) { | ||
457 | ret = sr_read_cmd(dev, SR_CMD_READ_EEPROM, eeprom->offset + i, | ||
458 | 0, 2, &ebuf[i]); | ||
459 | if (ret < 0) | ||
460 | return -EINVAL; | ||
461 | } | ||
462 | return 0; | ||
463 | } | ||
464 | |||
465 | static void sr_get_drvinfo(struct net_device *net, | ||
466 | struct ethtool_drvinfo *info) | ||
467 | { | ||
468 | struct usbnet *dev = netdev_priv(net); | ||
469 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
470 | |||
471 | /* Inherit standard device info */ | ||
472 | usbnet_get_drvinfo(net, info); | ||
473 | strncpy(info->driver, DRIVER_NAME, sizeof(info->driver)); | ||
474 | strncpy(info->version, DRIVER_VERSION, sizeof(info->version)); | ||
475 | info->eedump_len = data->eeprom_len; | ||
476 | } | ||
477 | |||
478 | static u32 sr_get_link(struct net_device *net) | ||
479 | { | ||
480 | struct usbnet *dev = netdev_priv(net); | ||
481 | |||
482 | return mii_link_ok(&dev->mii); | ||
483 | } | ||
484 | |||
485 | static int sr_ioctl(struct net_device *net, struct ifreq *rq, int cmd) | ||
486 | { | ||
487 | struct usbnet *dev = netdev_priv(net); | ||
488 | |||
489 | return generic_mii_ioctl(&dev->mii, if_mii(rq), cmd, NULL); | ||
490 | } | ||
491 | |||
492 | static int sr_set_mac_address(struct net_device *net, void *p) | ||
493 | { | ||
494 | struct usbnet *dev = netdev_priv(net); | ||
495 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
496 | struct sockaddr *addr = p; | ||
497 | |||
498 | if (netif_running(net)) | ||
499 | return -EBUSY; | ||
500 | if (!is_valid_ether_addr(addr->sa_data)) | ||
501 | return -EADDRNOTAVAIL; | ||
502 | |||
503 | memcpy(net->dev_addr, addr->sa_data, ETH_ALEN); | ||
504 | |||
505 | /* We use the 20 byte dev->data | ||
506 | * for our 6 byte mac buffer | ||
507 | * to avoid allocating memory that | ||
508 | * is tricky to free later | ||
509 | */ | ||
510 | memcpy(data->mac_addr, addr->sa_data, ETH_ALEN); | ||
511 | sr_write_cmd_async(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, | ||
512 | data->mac_addr); | ||
513 | |||
514 | return 0; | ||
515 | } | ||
516 | |||
517 | static const struct ethtool_ops sr9800_ethtool_ops = { | ||
518 | .get_drvinfo = sr_get_drvinfo, | ||
519 | .get_link = sr_get_link, | ||
520 | .get_msglevel = usbnet_get_msglevel, | ||
521 | .set_msglevel = usbnet_set_msglevel, | ||
522 | .get_wol = sr_get_wol, | ||
523 | .set_wol = sr_set_wol, | ||
524 | .get_eeprom_len = sr_get_eeprom_len, | ||
525 | .get_eeprom = sr_get_eeprom, | ||
526 | .get_settings = usbnet_get_settings, | ||
527 | .set_settings = usbnet_set_settings, | ||
528 | .nway_reset = usbnet_nway_reset, | ||
529 | }; | ||
530 | |||
531 | static int sr9800_link_reset(struct usbnet *dev) | ||
532 | { | ||
533 | struct ethtool_cmd ecmd = { .cmd = ETHTOOL_GSET }; | ||
534 | u16 mode; | ||
535 | |||
536 | mii_check_media(&dev->mii, 1, 1); | ||
537 | mii_ethtool_gset(&dev->mii, &ecmd); | ||
538 | mode = SR9800_MEDIUM_DEFAULT; | ||
539 | |||
540 | if (ethtool_cmd_speed(&ecmd) != SPEED_100) | ||
541 | mode &= ~SR_MEDIUM_PS; | ||
542 | |||
543 | if (ecmd.duplex != DUPLEX_FULL) | ||
544 | mode &= ~SR_MEDIUM_FD; | ||
545 | |||
546 | netdev_dbg(dev->net, "%s : speed: %u duplex: %d mode: 0x%04x\n", | ||
547 | __func__, ethtool_cmd_speed(&ecmd), ecmd.duplex, mode); | ||
548 | |||
549 | sr_write_medium_mode(dev, mode); | ||
550 | |||
551 | return 0; | ||
552 | } | ||
553 | |||
554 | |||
555 | static int sr9800_set_default_mode(struct usbnet *dev) | ||
556 | { | ||
557 | u16 rx_ctl; | ||
558 | int ret; | ||
559 | |||
560 | sr_mdio_write(dev->net, dev->mii.phy_id, MII_BMCR, BMCR_RESET); | ||
561 | sr_mdio_write(dev->net, dev->mii.phy_id, MII_ADVERTISE, | ||
562 | ADVERTISE_ALL | ADVERTISE_CSMA); | ||
563 | mii_nway_restart(&dev->mii); | ||
564 | |||
565 | ret = sr_write_medium_mode(dev, SR9800_MEDIUM_DEFAULT); | ||
566 | if (ret < 0) | ||
567 | goto out; | ||
568 | |||
569 | ret = sr_write_cmd(dev, SR_CMD_WRITE_IPG012, | ||
570 | SR9800_IPG0_DEFAULT | SR9800_IPG1_DEFAULT, | ||
571 | SR9800_IPG2_DEFAULT, 0, NULL); | ||
572 | if (ret < 0) { | ||
573 | netdev_dbg(dev->net, "Write IPG,IPG1,IPG2 failed: %d\n", ret); | ||
574 | goto out; | ||
575 | } | ||
576 | |||
577 | /* Set RX_CTL to default values with 2k buffer, and enable cactus */ | ||
578 | ret = sr_write_rx_ctl(dev, SR_DEFAULT_RX_CTL); | ||
579 | if (ret < 0) | ||
580 | goto out; | ||
581 | |||
582 | rx_ctl = sr_read_rx_ctl(dev); | ||
583 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after all initializations\n", | ||
584 | rx_ctl); | ||
585 | |||
586 | rx_ctl = sr_read_medium_status(dev); | ||
587 | netdev_dbg(dev->net, "Medium Status:0x%04x after all initializations\n", | ||
588 | rx_ctl); | ||
589 | |||
590 | return 0; | ||
591 | out: | ||
592 | return ret; | ||
593 | } | ||
594 | |||
595 | static int sr9800_reset(struct usbnet *dev) | ||
596 | { | ||
597 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
598 | int ret, embd_phy; | ||
599 | u16 rx_ctl; | ||
600 | |||
601 | ret = sr_write_gpio(dev, | ||
602 | SR_GPIO_RSE | SR_GPIO_GPO_2 | SR_GPIO_GPO2EN, 5); | ||
603 | if (ret < 0) | ||
604 | goto out; | ||
605 | |||
606 | embd_phy = ((sr_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0); | ||
607 | |||
608 | ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); | ||
609 | if (ret < 0) { | ||
610 | netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); | ||
611 | goto out; | ||
612 | } | ||
613 | |||
614 | ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_PRL); | ||
615 | if (ret < 0) | ||
616 | goto out; | ||
617 | |||
618 | msleep(150); | ||
619 | |||
620 | ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); | ||
621 | if (ret < 0) | ||
622 | goto out; | ||
623 | |||
624 | msleep(150); | ||
625 | |||
626 | if (embd_phy) { | ||
627 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
628 | if (ret < 0) | ||
629 | goto out; | ||
630 | } else { | ||
631 | ret = sr_sw_reset(dev, SR_SWRESET_PRTE); | ||
632 | if (ret < 0) | ||
633 | goto out; | ||
634 | } | ||
635 | |||
636 | msleep(150); | ||
637 | rx_ctl = sr_read_rx_ctl(dev); | ||
638 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); | ||
639 | ret = sr_write_rx_ctl(dev, 0x0000); | ||
640 | if (ret < 0) | ||
641 | goto out; | ||
642 | |||
643 | rx_ctl = sr_read_rx_ctl(dev); | ||
644 | netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); | ||
645 | |||
646 | ret = sr_sw_reset(dev, SR_SWRESET_PRL); | ||
647 | if (ret < 0) | ||
648 | goto out; | ||
649 | |||
650 | msleep(150); | ||
651 | |||
652 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL | SR_SWRESET_PRL); | ||
653 | if (ret < 0) | ||
654 | goto out; | ||
655 | |||
656 | msleep(150); | ||
657 | |||
658 | ret = sr9800_set_default_mode(dev); | ||
659 | if (ret < 0) | ||
660 | goto out; | ||
661 | |||
662 | /* Rewrite MAC address */ | ||
663 | memcpy(data->mac_addr, dev->net->dev_addr, ETH_ALEN); | ||
664 | ret = sr_write_cmd(dev, SR_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, | ||
665 | data->mac_addr); | ||
666 | if (ret < 0) | ||
667 | goto out; | ||
668 | |||
669 | return 0; | ||
670 | |||
671 | out: | ||
672 | return ret; | ||
673 | } | ||
674 | |||
675 | static const struct net_device_ops sr9800_netdev_ops = { | ||
676 | .ndo_open = usbnet_open, | ||
677 | .ndo_stop = usbnet_stop, | ||
678 | .ndo_start_xmit = usbnet_start_xmit, | ||
679 | .ndo_tx_timeout = usbnet_tx_timeout, | ||
680 | .ndo_change_mtu = usbnet_change_mtu, | ||
681 | .ndo_set_mac_address = sr_set_mac_address, | ||
682 | .ndo_validate_addr = eth_validate_addr, | ||
683 | .ndo_do_ioctl = sr_ioctl, | ||
684 | .ndo_set_rx_mode = sr_set_multicast, | ||
685 | }; | ||
686 | |||
687 | static int sr9800_phy_powerup(struct usbnet *dev) | ||
688 | { | ||
689 | int ret; | ||
690 | |||
691 | /* set the embedded Ethernet PHY in power-down state */ | ||
692 | ret = sr_sw_reset(dev, SR_SWRESET_IPPD | SR_SWRESET_IPRL); | ||
693 | if (ret < 0) { | ||
694 | netdev_err(dev->net, "Failed to power down PHY : %d\n", ret); | ||
695 | return ret; | ||
696 | } | ||
697 | msleep(20); | ||
698 | |||
699 | /* set the embedded Ethernet PHY in power-up state */ | ||
700 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
701 | if (ret < 0) { | ||
702 | netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); | ||
703 | return ret; | ||
704 | } | ||
705 | msleep(600); | ||
706 | |||
707 | /* set the embedded Ethernet PHY in reset state */ | ||
708 | ret = sr_sw_reset(dev, SR_SWRESET_CLEAR); | ||
709 | if (ret < 0) { | ||
710 | netdev_err(dev->net, "Failed to power up PHY: %d\n", ret); | ||
711 | return ret; | ||
712 | } | ||
713 | msleep(20); | ||
714 | |||
715 | /* set the embedded Ethernet PHY in power-up state */ | ||
716 | ret = sr_sw_reset(dev, SR_SWRESET_IPRL); | ||
717 | if (ret < 0) { | ||
718 | netdev_err(dev->net, "Failed to reset PHY: %d\n", ret); | ||
719 | return ret; | ||
720 | } | ||
721 | |||
722 | return 0; | ||
723 | } | ||
724 | |||
725 | static int sr9800_bind(struct usbnet *dev, struct usb_interface *intf) | ||
726 | { | ||
727 | struct sr_data *data = (struct sr_data *)&dev->data; | ||
728 | u16 led01_mux, led23_mux; | ||
729 | int ret, embd_phy; | ||
730 | u32 phyid; | ||
731 | u16 rx_ctl; | ||
732 | |||
733 | data->eeprom_len = SR9800_EEPROM_LEN; | ||
734 | |||
735 | usbnet_get_endpoints(dev, intf); | ||
736 | |||
737 | /* LED Setting Rule : | ||
738 | * AABB:CCDD | ||
739 | * AA : MFA0(LED0) | ||
740 | * BB : MFA1(LED1) | ||
741 | * CC : MFA2(LED2), Reserved for SR9800 | ||
742 | * DD : MFA3(LED3), Reserved for SR9800 | ||
743 | */ | ||
744 | led01_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_LINK; | ||
745 | led23_mux = (SR_LED_MUX_LINK_ACTIVE << 8) | SR_LED_MUX_TX_ACTIVE; | ||
746 | ret = sr_write_cmd(dev, SR_CMD_LED_MUX, led01_mux, led23_mux, 0, NULL); | ||
747 | if (ret < 0) { | ||
748 | netdev_err(dev->net, "set LINK LED failed : %d\n", ret); | ||
749 | goto out; | ||
750 | } | ||
751 | |||
752 | /* Get the MAC address */ | ||
753 | ret = sr_read_cmd(dev, SR_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, | ||
754 | dev->net->dev_addr); | ||
755 | if (ret < 0) { | ||
756 | netdev_dbg(dev->net, "Failed to read MAC address: %d\n", ret); | ||
757 | return ret; | ||
758 | } | ||
759 | netdev_dbg(dev->net, "mac addr : %pM\n", dev->net->dev_addr); | ||
760 | |||
761 | /* Initialize MII structure */ | ||
762 | dev->mii.dev = dev->net; | ||
763 | dev->mii.mdio_read = sr_mdio_read; | ||
764 | dev->mii.mdio_write = sr_mdio_write; | ||
765 | dev->mii.phy_id_mask = 0x1f; | ||
766 | dev->mii.reg_num_mask = 0x1f; | ||
767 | dev->mii.phy_id = sr_get_phy_addr(dev); | ||
768 | |||
769 | dev->net->netdev_ops = &sr9800_netdev_ops; | ||
770 | dev->net->ethtool_ops = &sr9800_ethtool_ops; | ||
771 | |||
772 | embd_phy = ((dev->mii.phy_id & 0x1f) == 0x10 ? 1 : 0); | ||
773 | /* Reset the PHY to normal operation mode */ | ||
774 | ret = sr_write_cmd(dev, SR_CMD_SW_PHY_SELECT, embd_phy, 0, 0, NULL); | ||
775 | if (ret < 0) { | ||
776 | netdev_dbg(dev->net, "Select PHY #1 failed: %d\n", ret); | ||
777 | return ret; | ||
778 | } | ||
779 | |||
780 | /* Init PHY routine */ | ||
781 | ret = sr9800_phy_powerup(dev); | ||
782 | if (ret < 0) | ||
783 | goto out; | ||
784 | |||
785 | rx_ctl = sr_read_rx_ctl(dev); | ||
786 | netdev_dbg(dev->net, "RX_CTL is 0x%04x after software reset\n", rx_ctl); | ||
787 | ret = sr_write_rx_ctl(dev, 0x0000); | ||
788 | if (ret < 0) | ||
789 | goto out; | ||
790 | |||
791 | rx_ctl = sr_read_rx_ctl(dev); | ||
792 | netdev_dbg(dev->net, "RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl); | ||
793 | |||
794 | /* Read PHYID register *AFTER* the PHY was reset properly */ | ||
795 | phyid = sr_get_phyid(dev); | ||
796 | netdev_dbg(dev->net, "PHYID=0x%08x\n", phyid); | ||
797 | |||
798 | /* medium mode setting */ | ||
799 | ret = sr9800_set_default_mode(dev); | ||
800 | if (ret < 0) | ||
801 | goto out; | ||
802 | |||
803 | if (dev->udev->speed == USB_SPEED_HIGH) { | ||
804 | ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, | ||
805 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].byte_cnt, | ||
806 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].threshold, | ||
807 | 0, NULL); | ||
808 | if (ret < 0) { | ||
809 | netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); | ||
810 | goto out; | ||
811 | } | ||
812 | dev->rx_urb_size = | ||
813 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_4K].size; | ||
814 | } else { | ||
815 | ret = sr_write_cmd(dev, SR_CMD_BULKIN_SIZE, | ||
816 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].byte_cnt, | ||
817 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].threshold, | ||
818 | 0, NULL); | ||
819 | if (ret < 0) { | ||
820 | netdev_err(dev->net, "Reset RX_CTL failed: %d\n", ret); | ||
821 | goto out; | ||
822 | } | ||
823 | dev->rx_urb_size = | ||
824 | SR9800_BULKIN_SIZE[SR9800_MAX_BULKIN_2K].size; | ||
825 | } | ||
826 | netdev_dbg(dev->net, "%s : setting rx_urb_size with : %ld\n", __func__, | ||
827 | dev->rx_urb_size); | ||
828 | return 0; | ||
829 | |||
830 | out: | ||
831 | return ret; | ||
832 | } | ||
833 | |||
834 | static const struct driver_info sr9800_driver_info = { | ||
835 | .description = "CoreChip SR9800 USB 2.0 Ethernet", | ||
836 | .bind = sr9800_bind, | ||
837 | .status = sr_status, | ||
838 | .link_reset = sr9800_link_reset, | ||
839 | .reset = sr9800_reset, | ||
840 | .flags = DRIVER_FLAG, | ||
841 | .rx_fixup = sr_rx_fixup, | ||
842 | .tx_fixup = sr_tx_fixup, | ||
843 | }; | ||
844 | |||
845 | static const struct usb_device_id products[] = { | ||
846 | { | ||
847 | USB_DEVICE(0x0fe6, 0x9800), /* SR9800 Device */ | ||
848 | .driver_info = (unsigned long) &sr9800_driver_info, | ||
849 | }, | ||
850 | {}, /* END */ | ||
851 | }; | ||
852 | |||
853 | MODULE_DEVICE_TABLE(usb, products); | ||
854 | |||
855 | static struct usb_driver sr_driver = { | ||
856 | .name = DRIVER_NAME, | ||
857 | .id_table = products, | ||
858 | .probe = usbnet_probe, | ||
859 | .suspend = usbnet_suspend, | ||
860 | .resume = usbnet_resume, | ||
861 | .disconnect = usbnet_disconnect, | ||
862 | .supports_autosuspend = 1, | ||
863 | }; | ||
864 | |||
865 | module_usb_driver(sr_driver); | ||
866 | |||
867 | MODULE_AUTHOR("Liu Junliang <liujunliang_ljl@163.com"); | ||
868 | MODULE_VERSION(DRIVER_VERSION); | ||
869 | MODULE_DESCRIPTION("SR9800 USB 2.0 USB2NET Dev : http://www.corechip-sz.com"); | ||
870 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/net/usb/sr9800.h b/drivers/net/usb/sr9800.h new file mode 100644 index 000000000000..18f670251275 --- /dev/null +++ b/drivers/net/usb/sr9800.h | |||
@@ -0,0 +1,202 @@ | |||
1 | /* CoreChip-sz SR9800 one chip USB 2.0 Ethernet Devices | ||
2 | * | ||
3 | * Author : Liu Junliang <liujunliang_ljl@163.com> | ||
4 | * | ||
5 | * This file is licensed under the terms of the GNU General Public License | ||
6 | * version 2. This program is licensed "as is" without any warranty of any | ||
7 | * kind, whether express or implied. | ||
8 | */ | ||
9 | |||
10 | #ifndef _SR9800_H | ||
11 | #define _SR9800_H | ||
12 | |||
13 | /* SR9800 spec. command table on Linux Platform */ | ||
14 | |||
15 | /* command : Software Station Management Control Reg */ | ||
16 | #define SR_CMD_SET_SW_MII 0x06 | ||
17 | /* command : PHY Read Reg */ | ||
18 | #define SR_CMD_READ_MII_REG 0x07 | ||
19 | /* command : PHY Write Reg */ | ||
20 | #define SR_CMD_WRITE_MII_REG 0x08 | ||
21 | /* command : Hardware Station Management Control Reg */ | ||
22 | #define SR_CMD_SET_HW_MII 0x0a | ||
23 | /* command : SROM Read Reg */ | ||
24 | #define SR_CMD_READ_EEPROM 0x0b | ||
25 | /* command : SROM Write Reg */ | ||
26 | #define SR_CMD_WRITE_EEPROM 0x0c | ||
27 | /* command : SROM Write Enable Reg */ | ||
28 | #define SR_CMD_WRITE_ENABLE 0x0d | ||
29 | /* command : SROM Write Disable Reg */ | ||
30 | #define SR_CMD_WRITE_DISABLE 0x0e | ||
31 | /* command : RX Control Read Reg */ | ||
32 | #define SR_CMD_READ_RX_CTL 0x0f | ||
33 | #define SR_RX_CTL_PRO (1 << 0) | ||
34 | #define SR_RX_CTL_AMALL (1 << 1) | ||
35 | #define SR_RX_CTL_SEP (1 << 2) | ||
36 | #define SR_RX_CTL_AB (1 << 3) | ||
37 | #define SR_RX_CTL_AM (1 << 4) | ||
38 | #define SR_RX_CTL_AP (1 << 5) | ||
39 | #define SR_RX_CTL_ARP (1 << 6) | ||
40 | #define SR_RX_CTL_SO (1 << 7) | ||
41 | #define SR_RX_CTL_RH1M (1 << 8) | ||
42 | #define SR_RX_CTL_RH2M (1 << 9) | ||
43 | #define SR_RX_CTL_RH3M (1 << 10) | ||
44 | /* command : RX Control Write Reg */ | ||
45 | #define SR_CMD_WRITE_RX_CTL 0x10 | ||
46 | /* command : IPG0/IPG1/IPG2 Control Read Reg */ | ||
47 | #define SR_CMD_READ_IPG012 0x11 | ||
48 | /* command : IPG0/IPG1/IPG2 Control Write Reg */ | ||
49 | #define SR_CMD_WRITE_IPG012 0x12 | ||
50 | /* command : Node ID Read Reg */ | ||
51 | #define SR_CMD_READ_NODE_ID 0x13 | ||
52 | /* command : Node ID Write Reg */ | ||
53 | #define SR_CMD_WRITE_NODE_ID 0x14 | ||
54 | /* command : Multicast Filter Array Read Reg */ | ||
55 | #define SR_CMD_READ_MULTI_FILTER 0x15 | ||
56 | /* command : Multicast Filter Array Write Reg */ | ||
57 | #define SR_CMD_WRITE_MULTI_FILTER 0x16 | ||
58 | /* command : Eth/HomePNA PHY Address Reg */ | ||
59 | #define SR_CMD_READ_PHY_ID 0x19 | ||
60 | /* command : Medium Status Read Reg */ | ||
61 | #define SR_CMD_READ_MEDIUM_STATUS 0x1a | ||
62 | #define SR_MONITOR_LINK (1 << 1) | ||
63 | #define SR_MONITOR_MAGIC (1 << 2) | ||
64 | #define SR_MONITOR_HSFS (1 << 4) | ||
65 | /* command : Medium Status Write Reg */ | ||
66 | #define SR_CMD_WRITE_MEDIUM_MODE 0x1b | ||
67 | #define SR_MEDIUM_GM (1 << 0) | ||
68 | #define SR_MEDIUM_FD (1 << 1) | ||
69 | #define SR_MEDIUM_AC (1 << 2) | ||
70 | #define SR_MEDIUM_ENCK (1 << 3) | ||
71 | #define SR_MEDIUM_RFC (1 << 4) | ||
72 | #define SR_MEDIUM_TFC (1 << 5) | ||
73 | #define SR_MEDIUM_JFE (1 << 6) | ||
74 | #define SR_MEDIUM_PF (1 << 7) | ||
75 | #define SR_MEDIUM_RE (1 << 8) | ||
76 | #define SR_MEDIUM_PS (1 << 9) | ||
77 | #define SR_MEDIUM_RSV (1 << 10) | ||
78 | #define SR_MEDIUM_SBP (1 << 11) | ||
79 | #define SR_MEDIUM_SM (1 << 12) | ||
80 | /* command : Monitor Mode Status Read Reg */ | ||
81 | #define SR_CMD_READ_MONITOR_MODE 0x1c | ||
82 | /* command : Monitor Mode Status Write Reg */ | ||
83 | #define SR_CMD_WRITE_MONITOR_MODE 0x1d | ||
84 | /* command : GPIO Status Read Reg */ | ||
85 | #define SR_CMD_READ_GPIOS 0x1e | ||
86 | #define SR_GPIO_GPO0EN (1 << 0) /* GPIO0 Output enable */ | ||
87 | #define SR_GPIO_GPO_0 (1 << 1) /* GPIO0 Output value */ | ||
88 | #define SR_GPIO_GPO1EN (1 << 2) /* GPIO1 Output enable */ | ||
89 | #define SR_GPIO_GPO_1 (1 << 3) /* GPIO1 Output value */ | ||
90 | #define SR_GPIO_GPO2EN (1 << 4) /* GPIO2 Output enable */ | ||
91 | #define SR_GPIO_GPO_2 (1 << 5) /* GPIO2 Output value */ | ||
92 | #define SR_GPIO_RESERVED (1 << 6) /* Reserved */ | ||
93 | #define SR_GPIO_RSE (1 << 7) /* Reload serial EEPROM */ | ||
94 | /* command : GPIO Status Write Reg */ | ||
95 | #define SR_CMD_WRITE_GPIOS 0x1f | ||
96 | /* command : Eth PHY Power and Reset Control Reg */ | ||
97 | #define SR_CMD_SW_RESET 0x20 | ||
98 | #define SR_SWRESET_CLEAR 0x00 | ||
99 | #define SR_SWRESET_RR (1 << 0) | ||
100 | #define SR_SWRESET_RT (1 << 1) | ||
101 | #define SR_SWRESET_PRTE (1 << 2) | ||
102 | #define SR_SWRESET_PRL (1 << 3) | ||
103 | #define SR_SWRESET_BZ (1 << 4) | ||
104 | #define SR_SWRESET_IPRL (1 << 5) | ||
105 | #define SR_SWRESET_IPPD (1 << 6) | ||
106 | /* command : Software Interface Selection Status Read Reg */ | ||
107 | #define SR_CMD_SW_PHY_STATUS 0x21 | ||
108 | /* command : Software Interface Selection Status Write Reg */ | ||
109 | #define SR_CMD_SW_PHY_SELECT 0x22 | ||
110 | /* command : BULK in Buffer Size Reg */ | ||
111 | #define SR_CMD_BULKIN_SIZE 0x2A | ||
112 | /* command : LED_MUX Control Reg */ | ||
113 | #define SR_CMD_LED_MUX 0x70 | ||
114 | #define SR_LED_MUX_TX_ACTIVE (1 << 0) | ||
115 | #define SR_LED_MUX_RX_ACTIVE (1 << 1) | ||
116 | #define SR_LED_MUX_COLLISION (1 << 2) | ||
117 | #define SR_LED_MUX_DUP_COL (1 << 3) | ||
118 | #define SR_LED_MUX_DUP (1 << 4) | ||
119 | #define SR_LED_MUX_SPEED (1 << 5) | ||
120 | #define SR_LED_MUX_LINK_ACTIVE (1 << 6) | ||
121 | #define SR_LED_MUX_LINK (1 << 7) | ||
122 | |||
123 | /* Register Access Flags */ | ||
124 | #define SR_REQ_RD_REG (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE) | ||
125 | #define SR_REQ_WR_REG (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE) | ||
126 | |||
127 | /* Multicast Filter Array size & Max Number */ | ||
128 | #define SR_MCAST_FILTER_SIZE 8 | ||
129 | #define SR_MAX_MCAST 64 | ||
130 | |||
131 | /* IPG0/1/2 Default Value */ | ||
132 | #define SR9800_IPG0_DEFAULT 0x15 | ||
133 | #define SR9800_IPG1_DEFAULT 0x0c | ||
134 | #define SR9800_IPG2_DEFAULT 0x12 | ||
135 | |||
136 | /* Medium Status Default Mode */ | ||
137 | #define SR9800_MEDIUM_DEFAULT \ | ||
138 | (SR_MEDIUM_FD | SR_MEDIUM_RFC | \ | ||
139 | SR_MEDIUM_TFC | SR_MEDIUM_PS | \ | ||
140 | SR_MEDIUM_AC | SR_MEDIUM_RE) | ||
141 | |||
142 | /* RX Control Default Setting */ | ||
143 | #define SR_DEFAULT_RX_CTL \ | ||
144 | (SR_RX_CTL_SO | SR_RX_CTL_AB | SR_RX_CTL_RH1M) | ||
145 | |||
146 | /* EEPROM Magic Number & EEPROM Size */ | ||
147 | #define SR_EEPROM_MAGIC 0xdeadbeef | ||
148 | #define SR9800_EEPROM_LEN 0xff | ||
149 | |||
150 | /* SR9800 Driver Version and Driver Name */ | ||
151 | #define DRIVER_VERSION "11-Nov-2013" | ||
152 | #define DRIVER_NAME "CoreChips" | ||
153 | #define DRIVER_FLAG \ | ||
154 | (FLAG_ETHER | FLAG_FRAMING_AX | FLAG_LINK_INTR | FLAG_MULTI_PACKET) | ||
155 | |||
156 | /* SR9800 BULKIN Buffer Size */ | ||
157 | #define SR9800_MAX_BULKIN_2K 0 | ||
158 | #define SR9800_MAX_BULKIN_4K 1 | ||
159 | #define SR9800_MAX_BULKIN_6K 2 | ||
160 | #define SR9800_MAX_BULKIN_8K 3 | ||
161 | #define SR9800_MAX_BULKIN_16K 4 | ||
162 | #define SR9800_MAX_BULKIN_20K 5 | ||
163 | #define SR9800_MAX_BULKIN_24K 6 | ||
164 | #define SR9800_MAX_BULKIN_32K 7 | ||
165 | |||
166 | struct {unsigned short size, byte_cnt, threshold; } SR9800_BULKIN_SIZE[] = { | ||
167 | /* 2k */ | ||
168 | {2048, 0x8000, 0x8001}, | ||
169 | /* 4k */ | ||
170 | {4096, 0x8100, 0x8147}, | ||
171 | /* 6k */ | ||
172 | {6144, 0x8200, 0x81EB}, | ||
173 | /* 8k */ | ||
174 | {8192, 0x8300, 0x83D7}, | ||
175 | /* 16 */ | ||
176 | {16384, 0x8400, 0x851E}, | ||
177 | /* 20k */ | ||
178 | {20480, 0x8500, 0x8666}, | ||
179 | /* 24k */ | ||
180 | {24576, 0x8600, 0x87AE}, | ||
181 | /* 32k */ | ||
182 | {32768, 0x8700, 0x8A3D}, | ||
183 | }; | ||
184 | |||
185 | /* This structure cannot exceed sizeof(unsigned long [5]) AKA 20 bytes */ | ||
186 | struct sr_data { | ||
187 | u8 multi_filter[SR_MCAST_FILTER_SIZE]; | ||
188 | u8 mac_addr[ETH_ALEN]; | ||
189 | u8 phymode; | ||
190 | u8 ledmode; | ||
191 | u8 eeprom_len; | ||
192 | }; | ||
193 | |||
194 | struct sr9800_int_data { | ||
195 | __le16 res1; | ||
196 | u8 link; | ||
197 | __le16 res2; | ||
198 | u8 status; | ||
199 | __le16 res3; | ||
200 | } __packed; | ||
201 | |||
202 | #endif /* _SR9800_H */ | ||