From: Marek Vasut <marex@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH V3 2/3] usb: eth: add ASIX AX88179 DRIVER
Date: Fri, 26 Sep 2014 10:23:58 +0200 [thread overview]
Message-ID: <201409261023.58724.marex@denx.de> (raw)
In-Reply-To: <1411718929-23048-2-git-send-email-rgriessl@cit-ec.uni-bielefeld.de>
On Friday, September 26, 2014 at 10:08:48 AM, Rene Griessl wrote:
> changes in v3:
> -added all compatible devices from linux driver
> -fixed issues from review
>
> changes in v2:
> -added usb_ether.h to change list
> -added 2nd patch to enable driver for arndale board
The changelog goes to the [*] marker below. And you're missing a meaningful
commit message too. Also, if the driver is pulled from Linux, please specify
from which commit in there, so future developers might re-sync the driver if
needed be and they'd know from which point the driver was derived.
> Signed-off-by: Rene Griessl <rgriessl@cit-ec.uni-bielefeld.de>
> ---
> drivers/usb/eth/Makefile | 1 +
> drivers/usb/eth/asix88179.c | 659
> ++++++++++++++++++++++++++++++++++++++++++++ drivers/usb/eth/usb_ether.c |
> 7 +
> include/usb_ether.h | 6 +
> 4 files changed, 673 insertions(+)
> create mode 100644 drivers/usb/eth/asix88179.c
>
> diff --git a/drivers/usb/eth/Makefile b/drivers/usb/eth/Makefile
> index e6ae9f1..c92d2b0 100644
> --- a/drivers/usb/eth/Makefile
> +++ b/drivers/usb/eth/Makefile
> @@ -6,5 +6,6 @@
> # new USB host ethernet layer dependencies
> obj-$(CONFIG_USB_HOST_ETHER) += usb_ether.o
> obj-$(CONFIG_USB_ETHER_ASIX) += asix.o
> +obj-$(CONFIG_USB_ETHER_ASIX88179) += asix88179.o
> obj-$(CONFIG_USB_ETHER_MCS7830) += mcs7830.o
> obj-$(CONFIG_USB_ETHER_SMSC95XX) += smsc95xx.o
> diff --git a/drivers/usb/eth/asix88179.c b/drivers/usb/eth/asix88179.c
> new file mode 100644
> index 0000000..2079056
> --- /dev/null
> +++ b/drivers/usb/eth/asix88179.c
> @@ -0,0 +1,659 @@
> +/*
> + * Copyright (c) 2014 Rene Griessl <rgriessl@cit-ec.uni-bielefeld.de>
> + * based on the U-Boot Asix driver as well as information
> + * from the Linux AX88179_178a driver
> + *
> + * SPDX-License-Identifier: GPL-2.0+
> + */
> +
> +
One newline too many here.
> +#include <common.h>
> +#include <usb.h>
> +#include <net.h>
> +#include <linux/mii.h>
> +#include "usb_ether.h"
> +#include <malloc.h>
> +
> +
DTTO
> +/* ASIX AX88179 based USB 3.0 Ethernet Devices */
> +#define AX88179_PHY_ID 0x03
> +#define AX_EEPROM_LEN 0x100
> +#define AX88179_EEPROM_MAGIC 0x17900b95
> +#define AX_MCAST_FLTSIZE 8
> +#define AX_MAX_MCAST 64
> +#define AX_INT_PPLS_LINK (1 << 16)
> +#define AX_RXHDR_L4_TYPE_MASK 0x1c
> +#define AX_RXHDR_L4_TYPE_UDP 4
> +#define AX_RXHDR_L4_TYPE_TCP 16
> +#define AX_RXHDR_L3CSUM_ERR 2
> +#define AX_RXHDR_L4CSUM_ERR 1
> +#define AX_RXHDR_CRC_ERR (1 << 29)
> +#define AX_RXHDR_DROP_ERR (1 << 31)
> +#define AX_ACCESS_MAC 0x01
> +#define AX_ACCESS_PHY 0x02
> +#define AX_ACCESS_EEPROM 0x04
> +#define AX_ACCESS_EFUS 0x05
> +#define AX_PAUSE_WATERLVL_HIGH 0x54
> +#define AX_PAUSE_WATERLVL_LOW 0x55
> +
> +#define PHYSICAL_LINK_STATUS 0x02
> + #define AX_USB_SS 0x04
> + #define AX_USB_HS 0x02
> +
> +#define GENERAL_STATUS 0x03
> +/* Check AX88179 version. UA1:Bit2 = 0, UA2:Bit2 = 1 */
> + #define AX_SECLD 0x04
> +
> +#define AX_SROM_ADDR 0x07
> +#define AX_SROM_CMD 0x0a
> + #define EEP_RD 0x04
> + #define EEP_BUSY 0x10
If those are bits, then just use (1 << n) notation.
[...]
> +static int curr_eth_dev; /* index for name of next device detected */
> +
> +/* driver private */
> +struct asix_private {
> + int flags;
> +};
This thing is a little iffy ... do you really need a full-blown struct here or
can you just use array ?
> +/*
> + * Asix infrastructure commands
> + */
> +static int asix_write_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16
> index, + u16 size, void *data)
> +{
> + int len;
> +
> + debug("asix_write_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
> + cmd, value, index, size);
> +
> + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, size);
I think if you really enable the debug to generate a printf() , the compiler
will spew that you wrote code before variable declaration.
> + memcpy(buf, data, size);
> +
> + len = usb_control_msg(
> + dev->pusb_dev,
> + usb_sndctrlpipe(dev->pusb_dev, 0),
> + cmd,
> + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> + value,
> + index,
> + buf,
> + size,
> + USB_CTRL_SET_TIMEOUT);
> +
> + return len == size ? 0 : -1;
Use values from errno.h here ?
> +}
> +
> +static int asix_read_cmd(struct ueth_data *dev, u8 cmd, u16 value, u16
> index, + u16 size, void *data)
> +{
> + int len;
> +
> + debug("asix_read_cmd() cmd=0x%02x value=0x%04x index=0x%04x size=%d\n",
> + cmd, value, index, size);
> + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, size);
> +
> +
> + len = usb_control_msg(
> + dev->pusb_dev,
> + usb_rcvctrlpipe(dev->pusb_dev, 0),
> + cmd,
> + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> + value,
> + index,
> + buf,
> + size,
> + USB_CTRL_GET_TIMEOUT);
> +
> + memcpy(data, buf, size);
> +
> + return len == size ? 0 : -1;
> +}
> +
> +
> +static int asix_read_mac(struct eth_device *eth)
> +{
> + struct ueth_data *dev = (struct ueth_data *)eth->priv;
> + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, buf, ETH_ALEN);
> +
> + if (dev->pusb_dev->descriptor.idProduct == 0x1790) {
> + asix_read_cmd(dev, AX_ACCESS_MAC, AX_NODE_ID, 6, 6, buf);
> + debug("asix_read_mac() returning %02x:%02x:%02x:%02x:%02x:
%02x\n",
> + buf[0], buf[1], buf[2], buf[3], buf[4], buf[5]);
> + memcpy(eth->enetaddr, buf, ETH_ALEN);
> + }
> + return 0;
> +}
> +
> +
> +
> +static int asix_basic_reset(struct ueth_data *dev)
> +{
> + ALLOC_CACHE_ALIGN_BUFFER(u8, buf, 6);
> + u16 *tmp16;
> + u8 *tmp;
> +
> + tmp16 = (u16 *)buf;
> + tmp = (u8 *)buf;
> +
> + /* Power up ethernet PHY */
> + *tmp16 = 0;
> + asix_write_cmd(dev, AX_ACCESS_MAC, AX_PHYPWR_RSTCTL, 2, 2, tmp16);
The asix_write_cmd() has some bounce-buffer logic in it already, does the tmp16
need to be aligned here too? Also, you might want to use include/bouncebuf.h and
friends instead of implementing your own bounce buffering.
[...]
> +/*
> + * Asix callbacks
> + */
> +static int asix_init(struct eth_device *eth, bd_t *bd)
> +{
> + struct ueth_data *dev = (struct ueth_data *)eth->priv;
> + int timeout = 0;
> + int link_detected;
> +
> + ALLOC_CACHE_ALIGN_BUFFER(u8, buf, 6);
> + u16 *tmp16;
> +
> + tmp16 = (u16 *)buf;
> +
> + debug("** %s()\n", __func__);
> +
> +
> + /* Configure RX control register => start operation */
> + *tmp16 = AX_RX_CTL_DROPCRCERR | AX_RX_CTL_IPE | AX_RX_CTL_START |
> + AX_RX_CTL_AP | AX_RX_CTL_AMALL | AX_RX_CTL_AB;
> + if (asix_write_cmd(dev, AX_ACCESS_MAC, AX_RX_CTL, 2, 2, tmp16) < 0)
> + goto out_err;
> +
> + do {
> + asix_read_cmd(dev, AX_ACCESS_PHY, 0x03, MII_BMSR, 2, buf);
> + link_detected = *tmp16 & BMSR_LSTATUS;
> + if (!link_detected) {
> + if (timeout == 0)
> + printf("Waiting for Ethernet connection... ");
> + udelay(TIMEOUT_RESOLUTION * 1000);
mdelay()
> + timeout += TIMEOUT_RESOLUTION;
> + }
> + } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);
Newline
> + if (link_detected) {
> + if (timeout != 0)
> + printf("done.\n");
> + return 0;
Where does this return 0; belong to ?
> + } else {/*reset device and try again*/
> + printf("unable to connect.\n");
> + printf("Reset Ethernet Device\n");
> + asix_basic_reset(dev);
> + timeout = 0;
> + do {
> + asix_read_cmd(dev, AX_ACCESS_PHY, 0x03,
> + MII_BMSR, 2, buf);
> + link_detected = *tmp16 & BMSR_LSTATUS;
> + if (!link_detected) {
> + if (timeout == 0)
> + printf("Waiting for Ethernet
connection... ");
> + udelay(TIMEOUT_RESOLUTION * 1000);
mdelay()
> + timeout += TIMEOUT_RESOLUTION;
> + }
> + } while (!link_detected && timeout < PHY_CONNECT_TIMEOUT);
> + if (link_detected) {
> + if (timeout != 0)
> + printf("done.\n");
> + return 0;
> + } else {
> + printf("unable to connect.\n");
> + goto out_err;
> + }
The indent is crazy in here ...
> + }
> +
> + return 0;
> +out_err:
> + return -1;
> +}
> +
> +static int asix_send(struct eth_device *eth, void *packet, int length)
> +{
> + struct ueth_data *dev = (struct ueth_data *)eth->priv;
> + int err;
> + u32 packet_len, tx_hdr2;
> + int actual_len;
> + ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
> + PKTSIZE + (2 * sizeof(packet_len)));
> +
> + debug("** %s(), len %d\n", __func__, length);
> +
> + packet_len = length;
> + cpu_to_le32s(&packet_len);
> +
> + memcpy(msg, &packet_len, sizeof(packet_len));
> +
> + tx_hdr2 = 0;
> + if (((length + 8) % 0x200 /*frame_size*/) == 0)
Define the frame size as a named constant, then use it here.
> + tx_hdr2 |= 0x80008000; /* Enable padding */
> +
> + cpu_to_le32s(&tx_hdr2);
> +
> + memcpy(msg + sizeof(packet_len), &tx_hdr2, sizeof(tx_hdr2));
> +
> + memcpy(msg + sizeof(packet_len) + sizeof(tx_hdr2),
> + (void *)packet, length);
> +
> + err = usb_bulk_msg(dev->pusb_dev,
> + usb_sndbulkpipe(dev->pusb_dev, dev->ep_out),
> + (void *)msg,
> + length + sizeof(packet_len) + sizeof(tx_hdr2),
> + &actual_len,
> + USB_BULK_SEND_TIMEOUT);
> + debug("Tx: len = %u, actual = %u, err = %d\n",
> + length + sizeof(packet_len), actual_len, err);
> +
> + return err;
> +}
[...]
> +/* Probe to see if a new device is actually an asix device */
> +int ax88179_eth_probe(struct usb_device *dev, unsigned int ifnum,
> + struct ueth_data *ss)
> +{
> + 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 */
> + iface = &dev->config.if_desc[ifnum];
> + iface_desc = &dev->config.if_desc[ifnum].desc;
> +
> + for (i = 0; asix_dongles[i].vendor != 0; i++) {
> + if (dev->descriptor.idVendor == asix_dongles[i].vendor &&
> + dev->descriptor.idProduct == asix_dongles[i].product)
> + /* Found a supported dongle */
> + break;
> + }
> +
> + if (asix_dongles[i].vendor == 0)
> + return 0;
> +
> + memset(ss, 0, sizeof(struct ueth_data));
> +
> + /* At this point, we know we've got a live one */
> + debug("\n\nUSB Ethernet device detected: %#04x:%#04x\n",
> + dev->descriptor.idVendor, dev->descriptor.idProduct);
> +
> + /* Initialize the ueth_data structure with some useful info */
> + ss->ifnum = ifnum;
> + ss->pusb_dev = dev;
> + ss->subclass = iface_desc->bInterfaceSubClass;
> + ss->protocol = iface_desc->bInterfaceProtocol;
> +
> + /* alloc driver private */
> + ss->dev_priv = calloc(1, sizeof(struct asix_private));
> + if (!ss->dev_priv)
> + return 0;
> +
> + ((struct asix_private *)ss->dev_priv)->flags = asix_dongles[i].flags;
> +
> + /*
> + * We are expecting a minimum of 3 endpoints - in, out (bulk), and
> + * int. We will ignore any others.
> + */
> + for (i = 0; i < iface_desc->bNumEndpoints; i++) {
> + /* is it an BULK endpoint? */
> + if ((iface->ep_desc[i].bmAttributes &
> + USB_ENDPOINT_XFERTYPE_MASK) == USB_ENDPOINT_XFER_BULK) {
if (! ...)
continue;
if ((ep_addr & USB_DIR_IN) && !ep_in_found) {
something
}
if (!(ep_addr & USB_DIR_IN) && !ep_out_found) {
something
}
> + u8 ep_addr = iface->ep_desc[i].bEndpointAddress;
> + if (ep_addr & USB_DIR_IN) {
> + if (!ep_in_found) {
> + ss->ep_in = ep_addr &
> + USB_ENDPOINT_NUMBER_MASK;
> + ep_in_found = 1;
> + }
> + } else {
> + if (!ep_out_found) {
> + ss->ep_out = ep_addr &
> + USB_ENDPOINT_NUMBER_MASK;
> + ep_out_found = 1;
> + }
> + }
See above how to trim down the indent here.
[...]
next prev parent reply other threads:[~2014-09-26 8:23 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-09-26 8:08 [U-Boot] [PATCH V3 1/3] usb: eth: fix Makefile Rene Griessl
2014-09-26 8:08 ` [U-Boot] [PATCH V3 2/3] usb: eth: add ASIX AX88179 DRIVER Rene Griessl
2014-09-26 8:23 ` Marek Vasut [this message]
2014-09-26 9:35 ` René Griessl
2014-09-26 13:47 ` Marek Vasut
2014-09-26 15:42 ` René Griessl
2014-09-26 15:49 ` Marek Vasut
2014-10-06 17:45 ` Andy Pont
2014-10-27 9:38 ` René Griessl
2014-09-26 8:08 ` [U-Boot] [PATCH V3 3/3] usb: eth: enable AX88179 DRIVER for ARNDALE 5250 Rene Griessl
2014-09-26 8:12 ` [U-Boot] [PATCH V3 1/3] usb: eth: fix Makefile Marek Vasut
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=201409261023.58724.marex@denx.de \
--to=marex@denx.de \
--cc=u-boot@lists.denx.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.