[U-Boot] [PATCH v2] net: asix: add support for AX88772B

Joe Hershberger joe.hershberger at gmail.com
Mon Aug 20 21:45:10 CEST 2012


Hi Lucas,

On Mon, Aug 20, 2012 at 12:52 PM, Lucas Stach <dev at lynxeye.de> wrote:
> There are multiple changes needed to make AX88772B work:
>
> 1. add vendor and product ID (trivial)
>
> 2. We need to read out the MAC address from the EEPROM and write
> it into the NodeID register manually.
>
> 3. The packet length check has to be adjusted, as all ASIX chips
> only use 11 bits to indicate the length. AX88772B uses the other
> bits to indicate unrelated things, which cause the check to fail.
> This fix is based on a fix for the Linux kernel by Marek Vasut.
> Linux upstream commit: bca0beb9363f8487ac902931a50eb00180a2d14a
>
> 4. AX88772B provides several bulk endpoints. Only the first
> IN/OUT endpoints work in the default configuration. So stop
> enumeration after we found them to avoid overwriting the
> endpoint config with a non-working one.
>
> This was tested to work on a Colibri T20 board.
> Patch is based on u-boot-net/next.
>
> v2:
> - split out eeprom mac load into separate function
> - add flags to driver to get a clean way to enable workarounds
>   or special functions
>
> Signed-off-by: Lucas Stach <dev at lynxeye.de>
> ---
>  drivers/usb/eth/asix.c | 91 ++++++++++++++++++++++++++++++++++++++------------
>  include/usb_ether.h    |  3 ++
>  2 Dateien geändert, 73 Zeilen hinzugefügt(+), 21 Zeilen entfernt(-)
>
> diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
> index 8fb7fc8..bfa76d3 100644
> --- a/drivers/usb/eth/asix.c
> +++ b/drivers/usb/eth/asix.c
> @@ -31,10 +31,12 @@
>  #define AX_CMD_READ_MII_REG            0x07
>  #define AX_CMD_WRITE_MII_REG           0x08
>  #define AX_CMD_SET_HW_MII              0x0a
> +#define AX_CMD_READ_EEPROM             0x0b
>  #define AX_CMD_READ_RX_CTL             0x0f
>  #define AX_CMD_WRITE_RX_CTL            0x10
>  #define AX_CMD_WRITE_IPG0              0x12
>  #define AX_CMD_READ_NODE_ID            0x13
> +#define AX_CMD_WRITE_NODE_ID   0x14
>  #define AX_CMD_READ_PHY_ID             0x19
>  #define AX_CMD_WRITE_MEDIUM_MODE       0x1b
>  #define AX_CMD_WRITE_GPIOS             0x1f
> @@ -97,6 +99,10 @@
>  #define AX_RX_URB_SIZE 2048
>  #define PHY_CONNECT_TIMEOUT 5000
>
> +/* asix_flags defines */
> +#define FLAG_NONE                      0
> +#define FLAG_EEPROM_MAC                (1U << 0) /* needs manual load of mac address */
> +
>  /* local vars */
>  static int curr_eth_dev; /* index for name of next device detected */
>
> @@ -310,6 +316,35 @@ static int mii_nway_restart(struct ueth_data *dev)
>         return r;
>  }
>
> +static int asix_load_mac_from_eeprom(struct ueth_data *dev)
> +{
> +       int i;
> +       ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
> +       ALLOC_CACHE_ALIGN_BUFFER(unsigned char, read_buf, 2);
> +
> +       memset(buf, 0, ETH_ALEN);
> +
> +       for (i = 0; i < (ETH_ALEN >> 1); i++) {
> +               memset(read_buf, 0, 2);
> +               if (asix_read_cmd(dev, AX_CMD_READ_EEPROM,
> +                                 0x04 + i, 0, 2, read_buf)) {
> +                       debug("Failed to read SROM address 04h.\n");
> +                       return -1;
> +               }
> +               memcpy((buf + i*2), read_buf, 2);
> +       }

This should be written to eth->enetaddr in asix_init().  That means
that if you need to read from the EEPROM, then do that, otherwise do
what you currently do (AX_CMD_READ_NODE_ID).  Perhaps just pass in a
pointer to eth->enetaddr to this function and store it there.

> +
> +       debug("MAC read from EEPROM: %02x:%02x:%02x:%02x:%02x:%02x\n",
> +             buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
> +
> +       if (asix_write_cmd(dev, AX_CMD_WRITE_NODE_ID, 0, 0, ETH_ALEN, buf)) {
> +               printf("Failed to set MAC address.\n");
> +               return -1;
> +       }

This write should be a separate function and should be registered as
write_hwaddr in asix_eth_get_info();

> +
> +       return 0;
> +}
> +
>  /*
>   * Asix callbacks
>   */
> @@ -359,6 +394,10 @@ static int asix_init(struct eth_device *eth, bd_t *bd)
>         rx_ctl = asix_read_rx_ctl(dev);
>         debug("RX_CTL is 0x%04x setting to 0x0000\n", rx_ctl);
>
> +       if (dev->asix_flags & FLAG_EEPROM_MAC)
> +               if (asix_load_mac_from_eeprom(dev))
> +                       goto out_err;
> +
>         /* Get the MAC address */
>         if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
>                                 0, 0, ETH_ALEN, buf) < 0) {
> @@ -493,13 +532,13 @@ static int asix_recv(struct eth_device *eth)
>                 }
>                 memcpy(&packet_len, buf_ptr, sizeof(packet_len));
>                 le32_to_cpus(&packet_len);
> -               if (((packet_len >> 16) ^ 0xffff) != (packet_len & 0xffff)) {
> +               if (((~packet_len >> 16) & 0x7ff) != (packet_len & 0x7ff)) {
>                         debug("Rx: malformed packet length: %#x (%#x:%#x)\n",
> -                             packet_len, (packet_len >> 16) ^ 0xffff,
> -                             packet_len & 0xffff);
> +                             packet_len, (~packet_len >> 16) & 0x7ff,
> +                             packet_len & 0x7ff);
>                         return -1;
>                 }
> -               packet_len = packet_len & 0xffff;
> +               packet_len = packet_len & 0x7ff;
>                 if (packet_len > actual_len - sizeof(packet_len)) {
>                         debug("Rx: too large packet: %d\n", packet_len);
>                         return -1;
> @@ -534,19 +573,21 @@ void asix_eth_before_probe(void)
>  struct asix_dongle {
>         unsigned short vendor;
>         unsigned short product;
> +       int flags;
>  };
>
>  static struct asix_dongle asix_dongles[] = {
> -       { 0x05ac, 0x1402 },     /* Apple USB Ethernet Adapter */
> -       { 0x07d1, 0x3c05 },     /* D-Link DUB-E100 H/W Ver B1 */
> -       { 0x0b95, 0x772a },     /* Cables-to-Go USB Ethernet Adapter */
> -       { 0x0b95, 0x7720 },     /* Trendnet TU2-ET100 V3.0R */
> -       { 0x0b95, 0x1720 },     /* SMC */
> -       { 0x0db0, 0xa877 },     /* MSI - ASIX 88772a */
> -       { 0x13b1, 0x0018 },     /* Linksys 200M v2.1 */
> -       { 0x1557, 0x7720 },     /* 0Q0 cable ethernet */
> -       { 0x2001, 0x3c05 },     /* DLink DUB-E100 H/W Ver B1 Alternate */
> -       { 0x0000, 0x0000 }      /* END - Do not remove */
> +       { 0x05ac, 0x1402, FLAG_NONE },  /* Apple USB Ethernet Adapter */
> +       { 0x07d1, 0x3c05, FLAG_NONE },  /* D-Link DUB-E100 H/W Ver B1 */
> +       { 0x0b95, 0x772a, FLAG_NONE },  /* Cables-to-Go USB Ethernet Adapter */
> +       { 0x0b95, 0x7720, FLAG_NONE },  /* Trendnet TU2-ET100 V3.0R */
> +       { 0x0b95, 0x1720, FLAG_NONE },  /* SMC */
> +       { 0x0db0, 0xa877, FLAG_NONE },  /* MSI - ASIX 88772a */
> +       { 0x13b1, 0x0018, FLAG_NONE },  /* Linksys 200M v2.1 */
> +       { 0x1557, 0x7720, FLAG_NONE },  /* 0Q0 cable ethernet */
> +       { 0x2001, 0x3c05, FLAG_NONE },  /* DLink DUB-E100 H/W Ver B1 Alternate */
> +       { 0x0b95, 0x772b, FLAG_EEPROM_MAC },    /* ASIX 88772B */
> +       { 0x0000, 0x0000, FLAG_NONE }   /* END - Do not remove */
>  };
>
>  /* Probe to see if a new device is actually an asix device */
> @@ -555,6 +596,7 @@ int asix_eth_probe(struct usb_device *dev, unsigned int ifnum,
>  {
>         struct usb_interface *iface;
>         struct usb_interface_descriptor *iface_desc;
> +       int ep_in_found = 0, ep_out_found = 0;
>         int i;
>
>         /* let's examine the device now */
> @@ -582,6 +624,7 @@ int asix_eth_probe(struct usb_device *dev, unsigned int ifnum,
>         ss->pusb_dev = dev;
>         ss->subclass = iface_desc->bInterfaceSubClass;
>         ss->protocol = iface_desc->bInterfaceProtocol;
> +       ss->asix_flags = asix_dongles[i].flags;
>
>         /*
>          * We are expecting a minimum of 3 endpoints - in, out (bulk), and
> @@ -591,13 +634,19 @@ int asix_eth_probe(struct usb_device *dev, unsigned int ifnum,
>                 /* is it an BULK endpoint? */
>                 if ((iface->ep_desc[i].bmAttributes &
>                      USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
> -                       if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN)
> -                               ss->ep_in = iface->ep_desc[i].bEndpointAddress &
> -                                       USB_ENDPOINT_NUMBER_MASK;
> -                       else
> -                               ss->ep_out =
> -                                       iface->ep_desc[i].bEndpointAddress &
> -                                       USB_ENDPOINT_NUMBER_MASK;
> +                       if (iface->ep_desc[i].bEndpointAddress & USB_DIR_IN) {
> +                               if (!ep_in_found) {
> +                                       ss->ep_in = iface->ep_desc[i].bEndpointAddress &
> +                                                   USB_ENDPOINT_NUMBER_MASK;
> +                                       ep_in_found = 1;
> +                               }
> +                       } else {
> +                               if (!ep_out_found) {
> +                                       ss->ep_out = iface->ep_desc[i].bEndpointAddress &
> +                                                    USB_ENDPOINT_NUMBER_MASK;
> +                                       ep_out_found = 1;
> +                               }
> +                       }
>                 }
>
>                 /* is it an interrupt endpoint? */
> diff --git a/include/usb_ether.h b/include/usb_ether.h
> index a7fb26b..a63fa74 100644
> --- a/include/usb_ether.h
> +++ b/include/usb_ether.h
> @@ -56,6 +56,9 @@ struct ueth_data {
>         u32 mac_cr;  /* MAC control register value */
>         int have_hwaddr;  /* 1 if we have a hardware MAC address */
>  #endif
> +#ifdef CONFIG_USB_ETHER_ASIX
> +       int asix_flags;
> +#endif
>  };
>
>  /*
> --
> 1.7.11.4
>
> _______________________________________________
> U-Boot mailing list
> U-Boot at lists.denx.de
> http://lists.denx.de/mailman/listinfo/u-boot


More information about the U-Boot mailing list