Dear Lucas Stach,

> 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

Yea, I enjoyed my share with this one. Though the linux patch still doesn't 
work 
on my hardware completely ... I get some random trouble. Do you get any mess in 
dmesg?

> 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.
> 
> Signed-off-by: Lucas Stach <[email protected]>
> ---
>  drivers/usb/eth/asix.c | 62
> +++++++++++++++++++++++++++++++++++++++++--------- 1 Datei geändert, 51
> Zeilen hinzugefügt(+), 11 Zeilen entfernt(-)
> 
> diff --git a/drivers/usb/eth/asix.c b/drivers/usb/eth/asix.c
> index 8fb7fc8..86e0f0f 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
> @@ -322,6 +324,7 @@ static int asix_init(struct eth_device *eth, bd_t *bd)
>       int timeout = 0;
>  #define TIMEOUT_RESOLUTION 50        /* ms */
>       int link_detected;
> +     int i;
> 
>       debug("** %s()\n", __func__);
> 
> @@ -359,6 +362,35 @@ 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);
> 
> +     /*
> +      * For AX88772B to work we have to read the MAC address from the EEPROM
> +      * and set the node ID manually.
> +      */
> +     if ((dev->pusb_dev->descriptor.idVendor == 0x0b95) &&
> +         (dev->pusb_dev->descriptor.idProduct == 0x772b)) {
> +
> +             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");
> +                             goto out_err;
> +                     }
> +                     memcpy((buf + i*2), read_buf, 2);
> +             }
> +
> +             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");
> +                     goto out_err;
> +             }
> +     }

Can this be split into separate function?

>       /* Get the MAC address */
>       if (asix_read_cmd(dev, AX_CMD_READ_NODE_ID,
>                               0, 0, ETH_ALEN, buf) < 0) {
> @@ -493,13 +525,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;
> @@ -546,6 +578,7 @@ static struct asix_dongle asix_dongles[] = {
>       { 0x13b1, 0x0018 },     /* Linksys 200M v2.1 */
>       { 0x1557, 0x7720 },     /* 0Q0 cable ethernet */
>       { 0x2001, 0x3c05 },     /* DLink DUB-E100 H/W Ver B1 Alternate */
> +     { 0x0b95, 0x772b },     /* ASIX 88772B */

Maybe this list should be extended by caps as it is in linux?

>       { 0x0000, 0x0000 }      /* END - Do not remove */
>  };
> 
> @@ -555,6 +588,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 */
> @@ -591,13 +625,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? */

Best regards,
Marek Vasut
_______________________________________________
U-Boot mailing list
[email protected]
http://lists.denx.de/mailman/listinfo/u-boot

Reply via email to