[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