1c6e967db1a0a0c1569b229df3a10eb2b6346069
[platform/kernel/u-boot.git] / drivers / usb / eth / asix.c
1 /*
2  * Copyright (c) 2011 The Chromium OS Authors.
3  *
4  * Patched for AX88772B by Antmicro Ltd <www.antmicro.com>
5  *
6  * SPDX-License-Identifier:     GPL-2.0+
7  */
8
9 #include <common.h>
10 #include <dm.h>
11 #include <usb.h>
12 #include <malloc.h>
13 #include <memalign.h>
14 #include <linux/mii.h>
15 #include "usb_ether.h"
16
17 /* ASIX AX8817X based USB 2.0 Ethernet Devices */
18
19 #define AX_CMD_SET_SW_MII               0x06
20 #define AX_CMD_READ_MII_REG             0x07
21 #define AX_CMD_WRITE_MII_REG            0x08
22 #define AX_CMD_SET_HW_MII               0x0a
23 #define AX_CMD_READ_EEPROM              0x0b
24 #define AX_CMD_READ_RX_CTL              0x0f
25 #define AX_CMD_WRITE_RX_CTL             0x10
26 #define AX_CMD_WRITE_IPG0               0x12
27 #define AX_CMD_READ_NODE_ID             0x13
28 #define AX_CMD_WRITE_NODE_ID    0x14
29 #define AX_CMD_READ_PHY_ID              0x19
30 #define AX_CMD_WRITE_MEDIUM_MODE        0x1b
31 #define AX_CMD_WRITE_GPIOS              0x1f
32 #define AX_CMD_SW_RESET                 0x20
33 #define AX_CMD_SW_PHY_SELECT            0x22
34
35 #define AX_SWRESET_CLEAR                0x00
36 #define AX_SWRESET_PRTE                 0x04
37 #define AX_SWRESET_PRL                  0x08
38 #define AX_SWRESET_IPRL                 0x20
39 #define AX_SWRESET_IPPD                 0x40
40
41 #define AX88772_IPG0_DEFAULT            0x15
42 #define AX88772_IPG1_DEFAULT            0x0c
43 #define AX88772_IPG2_DEFAULT            0x12
44
45 /* AX88772 & AX88178 Medium Mode Register */
46 #define AX_MEDIUM_PF            0x0080
47 #define AX_MEDIUM_JFE           0x0040
48 #define AX_MEDIUM_TFC           0x0020
49 #define AX_MEDIUM_RFC           0x0010
50 #define AX_MEDIUM_ENCK          0x0008
51 #define AX_MEDIUM_AC            0x0004
52 #define AX_MEDIUM_FD            0x0002
53 #define AX_MEDIUM_GM            0x0001
54 #define AX_MEDIUM_SM            0x1000
55 #define AX_MEDIUM_SBP           0x0800
56 #define AX_MEDIUM_PS            0x0200
57 #define AX_MEDIUM_RE            0x0100
58
59 #define AX88178_MEDIUM_DEFAULT  \
60         (AX_MEDIUM_PS | AX_MEDIUM_FD | AX_MEDIUM_AC | \
61          AX_MEDIUM_RFC | AX_MEDIUM_TFC | AX_MEDIUM_JFE | \
62          AX_MEDIUM_RE)
63
64 #define AX88772_MEDIUM_DEFAULT  \
65         (AX_MEDIUM_FD | AX_MEDIUM_RFC | \
66          AX_MEDIUM_TFC | AX_MEDIUM_PS | \
67          AX_MEDIUM_AC | AX_MEDIUM_RE)
68
69 /* AX88772 & AX88178 RX_CTL values */
70 #define AX_RX_CTL_SO                    0x0080
71 #define AX_RX_CTL_AB                    0x0008
72
73 #define AX_DEFAULT_RX_CTL       \
74         (AX_RX_CTL_SO | AX_RX_CTL_AB)
75
76 /* GPIO 2 toggles */
77 #define AX_GPIO_GPO2EN          0x10    /* GPIO2 Output enable */
78 #define AX_GPIO_GPO_2           0x20    /* GPIO2 Output value */
79 #define AX_GPIO_RSE             0x80    /* Reload serial EEPROM */
80
81 /* local defines */
82 #define ASIX_BASE_NAME "asx"
83 #define USB_CTRL_SET_TIMEOUT 5000
84 #define USB_CTRL_GET_TIMEOUT 5000
85 #define USB_BULK_SEND_TIMEOUT 5000
86 #define USB_BULK_RECV_TIMEOUT 5000
87
88 #define AX_RX_URB_SIZE 2048
89 #define PHY_CONNECT_TIMEOUT 5000
90
91 /* asix_flags defines */
92 #define FLAG_NONE                       0
93 #define FLAG_TYPE_AX88172       (1U << 0)
94 #define FLAG_TYPE_AX88772       (1U << 1)
95 #define FLAG_TYPE_AX88772B      (1U << 2)
96 #define FLAG_EEPROM_MAC         (1U << 3) /* initial mac address in eeprom */
97
98
99 /* driver private */
100 struct asix_private {
101         int flags;
102 #ifdef CONFIG_DM_ETH
103         struct ueth_data ueth;
104 #endif
105 };
106
107 #ifndef CONFIG_DM_ETH
108 /* local vars */
109 static int curr_eth_dev; /* index for name of next device detected */
110 #endif
111
112 /*
113  * Asix infrastructure commands
114  */
115 static int asix_write_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16 index,
116                              u16 size, void *data)
117 {
118         int len;
119
120         debug("asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x "
121                 "size=%d\n", cmd, value, index, size);
122
123         len = usb_control_msg(
124                 dev->pusb_dev,
125                 usb_sndctrlpipe(dev->pusb_dev, 0),
126                 cmd,
127                 USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
128                 value,
129                 index,
130                 data,
131                 size,
132                 USB_CTRL_SET_TIMEOUT);
133
134         return len == size ? 0 : -1;
135 }
136
137 static int asix_read_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16 index,
138                             u16 size, void *data)
139 {
140         int len;
141
142         debug("asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
143                 cmd, value, index, size);
144
145         len = usb_control_msg(
146                 dev->pusb_dev,
147                 usb_rcvctrlpipe(dev->pusb_dev, 0),
148                 cmd,
149                 USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
150                 value,
151                 index,
152                 data,
153                 size,
154                 USB_CTRL_GET_TIMEOUT);
155         return len == size ? 0 : -1;
156 }
157
158 static inline int asix_set_sw_mii(struct ueth_data *dev)
159 {
160         int ret;
161
162         ret = asix_write_cmd(dev, AX_CMD_SET_SW_MII, 0x0000, 0, 0, NULL);
163         if (ret < 0)
164                 debug("Failed to enable software MII access\n");
165         return ret;
166 }
167
168 static inline int asix_set_hw_mii(struct ueth_data *dev)
169 {
170         int ret;
171
172         ret = asix_write_cmd(dev, AX_CMD_SET_HW_MII, 0x0000, 0, 0, NULL);
173         if (ret < 0)
174                 debug("Failed to enable hardware MII access\n");
175         return ret;
176 }
177
178 static int asix_mdio_read(struct ueth_data *dev, int phy_id, int loc)
179 {
180         ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1);
181
182         asix_set_sw_mii(dev);
183         asix_read_cmd(dev, AX_CMD_READ_MII_REG, phy_id, (__u16)loc, 2, res);
184         asix_set_hw_mii(dev);
185
186         debug("asix_mdio_read() phy_id=0x%02x, loc=0x%02x, returns=0x%04x\n",
187                         phy_id, loc, le16_to_cpu(*res));
188
189         return le16_to_cpu(*res);
190 }
191
192 static void
193 asix_mdio_write(struct ueth_data *dev, int phy_id, int loc, int val)
194 {
195         ALLOC_CACHE_ALIGN_BUFFER(__le16, res, 1);
196         *res = cpu_to_le16(val);
197
198         debug("asix_mdio_write() phy_id=0x%02x, loc=0x%02x, val=0x%04x\n",
199                         phy_id, loc, val);
200         asix_set_sw_mii(dev);
201         asix_write_cmd(dev, AX_CMD_WRITE_MII_REG, phy_id, (__u16)loc, 2, res);
202         asix_set_hw_mii(dev);
203 }
204
205 /*
206  * Asix "high level" commands
207  */
208 static int asix_sw_reset(struct ueth_data *dev, u8 flags)
209 {
210         int ret;
211
212         ret = asix_write_cmd(dev, AX_CMD_SW_RESET, flags, 0, 0, NULL);
213         if (ret < 0)
214                 debug("Failed to send software reset: %02x\n", ret);
215         else
216                 udelay(150 * 1000);
217
218         return ret;
219 }
220
221 static inline int asix_get_phy_addr(struct ueth_data *dev)
222 {
223         ALLOC_CACHE_ALIGN_BUFFER(u8, buf, 2);
224
225         int ret = asix_read_cmd(dev, AX_CMD_READ_PHY_ID, 0, 0, 2, buf);
226
227         debug("asix_get_phy_addr()\n");
228
229         if (ret < 0) {
230                 debug("Error reading PHYID register: %02x\n", ret);
231                 goto out;
232         }
233         debug("asix_get_phy_addr() returning 0x%02x%02x\n", buf[0], buf[1]);
234         ret = buf[1];
235
236 out:
237         return ret;
238 }
239
240 static int asix_write_medium_mode(struct ueth_data *dev, u16 mode)
241 {
242         int ret;
243
244         debug("asix_write_medium_mode() - mode = 0x%04x\n", mode);
245         ret = asix_write_cmd(dev, AX_CMD_WRITE_MEDIUM_MODE, mode,
246                         0, 0, NULL);
247         if (ret < 0) {
248                 debug("Failed to write Medium Mode mode to 0x%04x: %02x\n",
249                         mode, ret);
250         }
251         return ret;
252 }
253
254 static u16 asix_read_rx_ctl(struct ueth_data *dev)
255 {
256         ALLOC_CACHE_ALIGN_BUFFER(__le16, v, 1);
257
258         int ret = asix_read_cmd(dev, AX_CMD_READ_RX_CTL, 0, 0, 2, v);
259
260         if (ret < 0)
261                 debug("Error reading RX_CTL register: %02x\n", ret);
262         else
263                 ret = le16_to_cpu(*v);
264         return ret;
265 }
266
267 static int asix_write_rx_ctl(struct ueth_data *dev, u16 mode)
268 {
269         int ret;
270
271         debug("asix_write_rx_ctl() - mode = 0x%04x\n", mode);
272         ret = asix_write_cmd(dev, AX_CMD_WRITE_RX_CTL, mode, 0, 0, NULL);
273         if (ret < 0) {
274                 debug("Failed to write RX_CTL mode to 0x%04x: %02x\n",
275                                 mode, ret);
276         }
277         return ret;
278 }
279
280 static int asix_write_gpio(struct ueth_data *dev, u16 value, int sleep)
281 {
282         int ret;
283
284         debug("asix_write_gpio() - value = 0x%04x\n", value);
285         ret = asix_write_cmd(dev, AX_CMD_WRITE_GPIOS, value, 0, 0, NULL);
286         if (ret < 0) {
287                 debug("Failed to write GPIO value 0x%04x: %02x\n",
288                         value, ret);
289         }
290         if (sleep)
291                 udelay(sleep * 1000);
292
293         return ret;
294 }
295
296 static int asix_write_hwaddr_common(struct ueth_data *dev, uint8_t *enetaddr)
297 {
298         int ret;
299         ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
300
301         memcpy(buf, enetaddr, ETH_ALEN);
302
303         ret = asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, buf);
304         if (ret < 0)
305                 debug("Failed to set MAC address: %02x\n", ret);
306
307         return ret;
308 }
309
310 /*
311  * mii commands
312  */
313
314 /*
315  * mii_nway_restart - restart NWay (autonegotiation) for this interface
316  *
317  * Returns 0 on success, negative on error.
318  */
319 static int mii_nway_restart(struct ueth_data *dev)
320 {
321         int bmcr;
322         int r = -1;
323
324         /* if autoneg is off, it's an error */
325         bmcr = asix_mdio_read(dev, dev->phy_id, MII_BMCR);
326
327         if (bmcr & BMCR_ANENABLE) {
328                 bmcr |= BMCR_ANRESTART;
329                 asix_mdio_write(dev, dev->phy_id, MII_BMCR, bmcr);
330                 r = 0;
331         }
332
333         return r;
334 }
335
336 static int asix_read_mac_common(struct ueth_data *dev,
337                                 struct asix_private *priv, uint8_t *enetaddr)
338 {
339         ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
340         int i;
341
342         if (priv->flags & FLAG_EEPROM_MAC) {
343                 for (i = 0; i < (ETH_ALEN >> 1); i++) {
344                         if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
345                                           0x04 + i, 0, 2, buf) < 0) {
346                                 debug("Failed to read SROM address 04h.\n");
347                                 return -1;
348                         }
349                         memcpy(enetaddr + i * 2, buf, 2);
350                 }
351         } else {
352                 if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf)
353                      < 0) {
354                         debug("Failed to read MAC address.\n");
355                         return -1;
356                 }
357                 memcpy(enetaddr, buf, ETH_ALEN);
358         }
359
360         return 0;
361 }
362
363 static int asix_basic_reset(struct ueth_data *dev)
364 {
365         int embd_phy;
366         u16 rx_ctl;
367
368         if (asix_write_gpio(dev,
369                         AX_GPIO_RSE | AX_GPIO_GPO_2 | AX_GPIO_GPO2EN, 5) < 0)
370                 return -1;
371
372         /* 0x10 is the phy id of the embedded 10/100 ethernet phy */
373         embd_phy = ((asix_get_phy_addr(dev) & 0x1f) == 0x10 ? 1 : 0);
374         if (asix_write_cmd(dev, AX_CMD_SW_PHY_SELECT,
375                                 embd_phy, 0, 0, NULL) < 0) {
376                 debug("Select PHY #1 failed\n");
377                 return -1;
378         }
379
380         if (asix_sw_reset(dev, AX_SWRESET_IPPD | AX_SWRESET_PRL) < 0)
381                 return -1;
382
383         if (asix_sw_reset(dev, AX_SWRESET_CLEAR) < 0)
384                 return -1;
385
386         if (embd_phy) {
387                 if (asix_sw_reset(dev, AX_SWRESET_IPRL) < 0)
388                         return -1;
389         } else {
390                 if (asix_sw_reset(dev, AX_SWRESET_PRTE) < 0)
391                         return -1;
392         }
393
394         rx_ctl = asix_read_rx_ctl(dev);
395         debug("RX_CTL is 0x%04x after software reset\n", rx_ctl);
396         if (asix_write_rx_ctl(dev, 0x0000) < 0)
397                 return -1;
398
399         rx_ctl = asix_read_rx_ctl(dev);
400         debug("RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
401
402         dev->phy_id = asix_get_phy_addr(dev);
403         if (dev->phy_id < 0)
404                 debug("Failed to read phy id\n");
405
406         asix_mdio_write(dev, dev->phy_id, MII_BMCR, BMCR_RESET);
407         asix_mdio_write(dev, dev->phy_id, MII_ADVERTISE,
408                         ADVERTISE_ALL | ADVERTISE_CSMA);
409         mii_nway_restart(dev);
410
411         if (asix_write_medium_mode(dev, AX88772_MEDIUM_DEFAULT) < 0)
412                 return -1;
413
414         if (asix_write_cmd(dev, AX_CMD_WRITE_IPG0,
415                                 AX88772_IPG0_DEFAULT | AX88772_IPG1_DEFAULT,
416                                 AX88772_IPG2_DEFAULT, 0, NULL) < 0) {
417                 debug("Write IPG,IPG1,IPG2 failed\n");
418                 return -1;
419         }
420
421         return 0;
422 }
423
424 static int asix_init_common(struct ueth_data *dev, uint8_t *enetaddr)
425 {
426         int timeout = 0;
427 #define TIMEOUT_RESOLUTION 50   /* ms */
428         int link_detected;
429
430         debug("** %s()\n", __func__);
431
432         if (asix_write_rx_ctl(dev, AX_DEFAULT_RX_CTL) < 0)
433                 goto out_err;
434
435         if (asix_write_hwaddr_common(dev, enetaddr) < 0)
436                 goto out_err;
437
438         do {
439                 link_detected = asix_mdio_read(dev, dev->phy_id, MII_BMSR) &
440                         BMSR_LSTATUS;
441                 if (!link_detected) {
442                         if (timeout == 0)
443                                 printf("Waiting for Ethernet connection... ");
444                         udelay(TIMEOUT_RESOLUTION * 1000);
445                         timeout += TIMEOUT_RESOLUTION;
446                 }
447         } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);
448         if (link_detected) {
449                 if (timeout != 0)
450                         printf("done.\n");
451         } else {
452                 printf("unable to connect.\n");
453                 goto out_err;
454         }
455
456         /*
457          * Wait some more to avoid timeout on first transfer
458          * (e.g. EHCI timed out on TD - token=0x8008d80)
459          */
460         mdelay(25);
461
462         return 0;
463 out_err:
464         return -1;
465 }
466
467 static int asix_send_common(struct ueth_data *dev, void *packet, int length)
468 {
469         int err;
470         u32 packet_len;
471         int actual_len;
472         ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
473                 PKTSIZE + sizeof(packet_len));
474
475         debug("** %s(), len %d\n", __func__, length);
476
477         packet_len = (((length) ^ 0x0000ffff) << 16) + (length);
478         cpu_to_le32s(&packet_len);
479
480         memcpy(msg, &packet_len, sizeof(packet_len));
481         memcpy(msg + sizeof(packet_len), (void *)packet, length);
482
483         err = usb_bulk_msg(dev->pusb_dev,
484                                 usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
485                                 (void *)msg,
486                                 length + sizeof(packet_len),
487                                 &actual_len,
488                                 USB_BULK_SEND_TIMEOUT);
489         debug("Tx: len = %zu, actual = %u, err = %d\n",
490                         length + sizeof(packet_len), actual_len, err);
491
492         return err;
493 }
494
495 #ifndef CONFIG_DM_ETH
496 /*
497  * Asix callbacks
498  */
499 static int asix_init(struct eth_device *eth, bd_t *bd)
500 {
501         struct ueth_data *dev = (struct ueth_data *)eth->priv;
502
503         return asix_init_common(dev, eth->enetaddr);
504 }
505
506 static int asix_send(struct eth_device *eth, void *packet, int length)
507 {
508         struct ueth_data *dev = (struct ueth_data *)eth->priv;
509
510         return asix_send_common(dev, packet, length);
511 }
512
513 static int asix_recv(struct eth_device *eth)
514 {
515         struct ueth_data *dev = (struct ueth_data *)eth->priv;
516         ALLOC_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE);
517         unsigned char *buf_ptr;
518         int err;
519         int actual_len;
520         u32 packet_len;
521
522         debug("** %s()\n", __func__);
523
524         err = usb_bulk_msg(dev->pusb_dev,
525                                 usb_rcvbulkpipe(dev->pusb_dev, dev->ep_in),
526                                 (void *)recv_buf,
527                                 AX_RX_URB_SIZE,
528                                 &actual_len,
529                                 USB_BULK_RECV_TIMEOUT);
530         debug("Rx: len = %u, actual = %u, err = %d\n", AX_RX_URB_SIZE,
531                 actual_len, err);
532         if (err != 0) {
533                 debug("Rx: failed to receive\n");
534                 return -1;
535         }
536         if (actual_len > AX_RX_URB_SIZE) {
537                 debug("Rx: received too many bytes %d\n", actual_len);
538                 return -1;
539         }
540
541         buf_ptr = recv_buf;
542         while (actual_len > 0) {
543                 /*
544                  * 1st 4 bytes contain the length of the actual data as two
545                  * complementary 16-bit words. Extract the length of the data.
546                  */
547                 if (actual_len < sizeof(packet_len)) {
548                         debug("Rx: incomplete packet length\n");
549                         return -1;
550                 }
551                 memcpy(&packet_len, buf_ptr, sizeof(packet_len));
552                 le32_to_cpus(&packet_len);
553                 if (((~packet_len >> 16) & 0x7ff) != (packet_len & 0x7ff)) {
554                         debug("Rx: malformed packet length: %#x (%#x:%#x)\n",
555                               packet_len, (~packet_len >> 16) & 0x7ff,
556                               packet_len & 0x7ff);
557                         return -1;
558                 }
559                 packet_len = packet_len & 0x7ff;
560                 if (packet_len > actual_len - sizeof(packet_len)) {
561                         debug("Rx: too large packet: %d\n", packet_len);
562                         return -1;
563                 }
564
565                 /* Notify net stack */
566                 net_process_received_packet(buf_ptr + sizeof(packet_len),
567                                             packet_len);
568
569                 /* Adjust for next iteration. Packets are padded to 16-bits */
570                 if (packet_len & 1)
571                         packet_len++;
572                 actual_len -= sizeof(packet_len) + packet_len;
573                 buf_ptr += sizeof(packet_len) + packet_len;
574         }
575
576         return err;
577 }
578
579 static void asix_halt(struct eth_device *eth)
580 {
581         debug("** %s()\n", __func__);
582 }
583
584 static int asix_write_hwaddr(struct eth_device *eth)
585 {
586         struct ueth_data *dev = (struct ueth_data *)eth->priv;
587
588         return asix_write_hwaddr_common(dev, eth->enetaddr);
589 }
590
591 /*
592  * Asix probing functions
593  */
594 void asix_eth_before_probe(void)
595 {
596         curr_eth_dev = 0;
597 }
598
599 struct asix_dongle {
600         unsigned short vendor;
601         unsigned short product;
602         int flags;
603 };
604
605 static const struct asix_dongle asix_dongles[] = {
606         { 0x05ac, 0x1402, FLAG_TYPE_AX88772 },  /* Apple USB Ethernet Adapter */
607         { 0x07d1, 0x3c05, FLAG_TYPE_AX88772 },  /* D-Link DUB-E100 H/W Ver B1 */
608         { 0x2001, 0x1a02, FLAG_TYPE_AX88772 },  /* D-Link DUB-E100 H/W Ver C1 */
609         /* Cables-to-Go USB Ethernet Adapter */
610         { 0x0b95, 0x772a, FLAG_TYPE_AX88772 },
611         { 0x0b95, 0x7720, FLAG_TYPE_AX88772 },  /* Trendnet TU2-ET100 V3.0R */
612         { 0x0b95, 0x1720, FLAG_TYPE_AX88172 },  /* SMC */
613         { 0x0db0, 0xa877, FLAG_TYPE_AX88772 },  /* MSI - ASIX 88772a */
614         { 0x13b1, 0x0018, FLAG_TYPE_AX88172 },  /* Linksys 200M v2.1 */
615         { 0x1557, 0x7720, FLAG_TYPE_AX88772 },  /* 0Q0 cable ethernet */
616         /* DLink DUB-E100 H/W Ver B1 Alternate */
617         { 0x2001, 0x3c05, FLAG_TYPE_AX88772 },
618         /* ASIX 88772B */
619         { 0x0b95, 0x772b, FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
620         { 0x0b95, 0x7e2b, FLAG_TYPE_AX88772B },
621         { 0x0000, 0x0000, FLAG_NONE }   /* END - Do not remove */
622 };
623
624 /* Probe to see if a new device is actually an asix device */
625 int asix_eth_probe(struct usb_device *dev, unsigned int ifnum,
626                       struct ueth_data *ss)
627 {
628         struct usb_interface *iface;
629         struct usb_interface_descriptor *iface_desc;
630         int ep_in_found = 0, ep_out_found = 0;
631         int i;
632
633         /* let's examine the device now */
634         iface = &dev->config.if_desc[ifnum];
635         iface_desc = &dev->config.if_desc[ifnum].desc;
636
637         for (i = 0; asix_dongles[i].vendor != 0; i++) {
638                 if (dev->descriptor.idVendor == asix_dongles[i].vendor &&
639                     dev->descriptor.idProduct == asix_dongles[i].product)
640                         /* Found a supported dongle */
641                         break;
642         }
643
644         if (asix_dongles[i].vendor == 0)
645                 return 0;
646
647         memset(ss, 0, sizeof(struct ueth_data));
648
649         /* At this point, we know we've got a live one */
650         debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n",
651               dev->descriptor.idVendor, dev->descriptor.idProduct);
652
653         /* Initialize the ueth_data structure with some useful info */
654         ss->ifnum = ifnum;
655         ss->pusb_dev = dev;
656         ss->subclass = iface_desc->bInterfaceSubClass;
657         ss->protocol = iface_desc->bInterfaceProtocol;
658
659         /* alloc driver private */
660         ss->dev_priv = calloc(1, sizeof(struct asix_private));
661         if (!ss->dev_priv)
662                 return 0;
663
664         ((struct asix_private *)ss->dev_priv)->flags = asix_dongles[i].flags;
665
666         /*
667          * We are expecting a minimum of 3 endpoints - in, out (bulk), and
668          * int. We will ignore any others.
669          */
670         for (i = 0; i < iface_desc->bNumEndpoints; i++) {
671                 /* is it an BULK endpoint? */
672                 if ((iface->ep_desc[i].bmAttributes &
673                      USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
674                         u8 ep_addr = iface->ep_desc[i].bEndpointAddress;
675                         if (ep_addr & USB_DIR_IN) {
676                                 if (!ep_in_found) {
677                                         ss->ep_in = ep_addr &
678                                                 USB_ENDPOINT_NUMBER_MASK;
679                                         ep_in_found = 1;
680                                 }
681                         } else {
682                                 if (!ep_out_found) {
683                                         ss->ep_out = ep_addr &
684                                                 USB_ENDPOINT_NUMBER_MASK;
685                                         ep_out_found = 1;
686                                 }
687                         }
688                 }
689
690                 /* is it an interrupt endpoint? */
691                 if ((iface->ep_desc[i].bmAttributes &
692                     USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_INT) {
693                         ss->ep_int = iface->ep_desc[i].bEndpointAddress &
694                                 USB_ENDPOINT_NUMBER_MASK;
695                         ss->irqinterval = iface->ep_desc[i].bInterval;
696                 }
697         }
698         debug("Endpoints In %d Out %d Int %d\n",
699                   ss->ep_in, ss->ep_out, ss->ep_int);
700
701         /* Do some basic sanity checks, and bail if we find a problem */
702         if (usb_set_interface(dev, iface_desc->bInterfaceNumber, 0) ||
703             !ss->ep_in || !ss->ep_out || !ss->ep_int) {
704                 debug("Problems with device\n");
705                 return 0;
706         }
707         dev->privptr = (void *)ss;
708         return 1;
709 }
710
711 int asix_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
712                                 struct eth_device *eth)
713 {
714         struct asix_private *priv = (struct asix_private *)ss->dev_priv;
715
716         if (!eth) {
717                 debug("%s: missing parameter.\n", __func__);
718                 return 0;
719         }
720         sprintf(eth->name, "%s%d", ASIX_BASE_NAME, curr_eth_dev++);
721         eth->init = asix_init;
722         eth->send = asix_send;
723         eth->recv = asix_recv;
724         eth->halt = asix_halt;
725         if (!(priv->flags & FLAG_TYPE_AX88172))
726                 eth->write_hwaddr = asix_write_hwaddr;
727         eth->priv = ss;
728
729         if (asix_basic_reset(ss))
730                 return 0;
731
732         /* Get the MAC address */
733         if (asix_read_mac_common(ss, priv, eth->enetaddr))
734                 return 0;
735         debug("MAC %pM\n", eth->enetaddr);
736
737         return 1;
738 }
739 #endif
740
741 #ifdef CONFIG_DM_ETH
742 static int asix_eth_start(struct udevice *dev)
743 {
744         struct eth_pdata *pdata = dev_get_platdata(dev);
745         struct asix_private *priv = dev_get_priv(dev);
746
747         return asix_init_common(&priv->ueth, pdata->enetaddr);
748 }
749
750 void asix_eth_stop(struct udevice *dev)
751 {
752         debug("** %s()\n", __func__);
753 }
754
755 int asix_eth_send(struct udevice *dev, void *packet, int length)
756 {
757         struct asix_private *priv = dev_get_priv(dev);
758
759         return asix_send_common(&priv->ueth, packet, length);
760 }
761
762 int asix_eth_recv(struct udevice *dev, int flags, uchar **packetp)
763 {
764         struct asix_private *priv = dev_get_priv(dev);
765         struct ueth_data *ueth = &priv->ueth;
766         uint8_t *ptr;
767         int ret, len;
768         u32 packet_len;
769
770         len = usb_ether_get_rx_bytes(ueth, &ptr);
771         debug("%s: first try, len=%d\n", __func__, len);
772         if (!len) {
773                 if (!(flags & ETH_RECV_CHECK_DEVICE))
774                         return -EAGAIN;
775                 ret = usb_ether_receive(ueth, AX_RX_URB_SIZE);
776                 if (ret == -EAGAIN)
777                         return ret;
778
779                 len = usb_ether_get_rx_bytes(ueth, &ptr);
780                 debug("%s: second try, len=%d\n", __func__, len);
781         }
782
783         /*
784          * 1st 4 bytes contain the length of the actual data as two
785          * complementary 16-bit words. Extract the length of the data.
786          */
787         if (len < sizeof(packet_len)) {
788                 debug("Rx: incomplete packet length\n");
789                 goto err;
790         }
791         memcpy(&packet_len, ptr, sizeof(packet_len));
792         le32_to_cpus(&packet_len);
793         if (((~packet_len >> 16) & 0x7ff) != (packet_len & 0x7ff)) {
794                 debug("Rx: malformed packet length: %#x (%#x:%#x)\n",
795                       packet_len, (~packet_len >> 16) & 0x7ff,
796                       packet_len & 0x7ff);
797                 goto err;
798         }
799         packet_len = packet_len & 0x7ff;
800         if (packet_len > len - sizeof(packet_len)) {
801                 debug("Rx: too large packet: %d\n", packet_len);
802                 goto err;
803         }
804
805         *packetp = ptr + sizeof(packet_len);
806         return packet_len;
807
808 err:
809         usb_ether_advance_rxbuf(ueth, -1);
810         return -EINVAL;
811 }
812
813 static int asix_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
814 {
815         struct asix_private *priv = dev_get_priv(dev);
816
817         if (packet_len & 1)
818                 packet_len++;
819         usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
820
821         return 0;
822 }
823
824 int asix_write_hwaddr(struct udevice *dev)
825 {
826         struct eth_pdata *pdata = dev_get_platdata(dev);
827         struct asix_private *priv = dev_get_priv(dev);
828
829         if (priv->flags & FLAG_TYPE_AX88172)
830                 return -ENOSYS;
831
832         return asix_write_hwaddr_common(&priv->ueth, pdata->enetaddr);
833 }
834
835 static int asix_eth_probe(struct udevice *dev)
836 {
837         struct eth_pdata *pdata = dev_get_platdata(dev);
838         struct asix_private *priv = dev_get_priv(dev);
839         struct ueth_data *ss = &priv->ueth;
840         int ret;
841
842         priv->flags = dev->driver_data;
843         ret = usb_ether_register(dev, ss, AX_RX_URB_SIZE);
844         if (ret)
845                 return ret;
846
847         ret = asix_basic_reset(ss);
848         if (ret)
849                 goto err;
850
851         /* Get the MAC address */
852         ret = asix_read_mac_common(ss, priv, pdata->enetaddr);
853         if (ret)
854                 goto err;
855         debug("MAC %pM\n", pdata->enetaddr);
856
857         return 0;
858
859 err:
860         return usb_ether_deregister(ss);
861 }
862
863 static const struct eth_ops asix_eth_ops = {
864         .start  = asix_eth_start,
865         .send   = asix_eth_send,
866         .recv   = asix_eth_recv,
867         .free_pkt = asix_free_pkt,
868         .stop   = asix_eth_stop,
869         .write_hwaddr = asix_write_hwaddr,
870 };
871
872 U_BOOT_DRIVER(asix_eth) = {
873         .name   = "asix_eth",
874         .id     = UCLASS_ETH,
875         .probe = asix_eth_probe,
876         .ops    = &asix_eth_ops,
877         .priv_auto_alloc_size = sizeof(struct asix_private),
878         .platdata_auto_alloc_size = sizeof(struct eth_pdata),
879 };
880
881 static const struct usb_device_id asix_eth_id_table[] = {
882         /* Apple USB Ethernet Adapter */
883         { USB_DEVICE(0x05ac, 0x1402), .driver_info = FLAG_TYPE_AX88772 },
884         /* D-Link DUB-E100 H/W Ver B1 */
885         { USB_DEVICE(0x07d1, 0x3c05), .driver_info = FLAG_TYPE_AX88772 },
886         /* D-Link DUB-E100 H/W Ver C1 */
887         { USB_DEVICE(0x2001, 0x1a02), .driver_info = FLAG_TYPE_AX88772 },
888         /* Cables-to-Go USB Ethernet Adapter */
889         { USB_DEVICE(0x0b95, 0x772a), .driver_info = FLAG_TYPE_AX88772 },
890         /* Trendnet TU2-ET100 V3.0R */
891         { USB_DEVICE(0x0b95, 0x7720), .driver_info = FLAG_TYPE_AX88772 },
892         /* SMC */
893         { USB_DEVICE(0x0b95, 0x1720), .driver_info = FLAG_TYPE_AX88172 },
894         /* MSI - ASIX 88772a */
895         { USB_DEVICE(0x0db0, 0xa877), .driver_info = FLAG_TYPE_AX88772 },
896         /* Linksys 200M v2.1 */
897         { USB_DEVICE(0x13b1, 0x0018), .driver_info = FLAG_TYPE_AX88172 },
898         /* 0Q0 cable ethernet */
899         { USB_DEVICE(0x1557, 0x7720), .driver_info = FLAG_TYPE_AX88772 },
900         /* DLink DUB-E100 H/W Ver B1 Alternate */
901         { USB_DEVICE(0x2001, 0x3c05), .driver_info = FLAG_TYPE_AX88772 },
902         /* ASIX 88772B */
903         { USB_DEVICE(0x0b95, 0x772b),
904                 .driver_info = FLAG_TYPE_AX88772B | FLAG_EEPROM_MAC },
905         { USB_DEVICE(0x0b95, 0x7e2b), .driver_info = FLAG_TYPE_AX88772B },
906         { }             /* Terminating entry */
907 };
908
909 U_BOOT_USB_DEVICE(asix_eth, asix_eth_id_table);
910 #endif