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