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

