[U-Boot] [PATCH v1 1/5] usb: net: introduce support for Moschip USB ethernet
Marek Vasut
marex at denx.de
Mon Feb 17 02:40:29 CET 2014
On Monday, February 17, 2014 at 12:01:07 AM, Gerhard Sittig wrote:
> introduce an 'mcs7830' driver for Moschip based USB ethernet adapters,
> which was implemented based on the U-Boot Asix driver with additional
> information gathered from the Moschip Linux driver
>
> Signed-off-by: Gerhard Sittig <gsi at denx.de>
> ---
> the driver was tested with a Logilink and a Delock product each, both
> of which contain an MCS7830 chip rev C, by several times transferring
> a file of 50MB size via TFTP (on a board with a total of 64MB RAM)
Did you also try tftpput ? ;-)
[...]
> +#define USB_CTRL_SET_TIMEOUT 5000
> +#define USB_CTRL_GET_TIMEOUT 5000
> +#define USB_BULK_SEND_TIMEOUT 5000
> +#define USB_BULK_RECV_TIMEOUT 5000
> +#define PHY_CONNECT_TIMEOUT 5000 /* link status, connect timeout */
Why don't we use just one TIMEOUT for all ?
> +#define PHY_CONNECT_TIMEOUT_RES 50 /* link status, resolution in
msec */
> +
> +#define MCS7830_RX_URB_SIZE 2048
> +
> +#ifndef BIT
> +#define BIT(n) (1 << (n))
> +#endif
This should probably be in include/common.h or so.
> +/* command opcodes */
> +enum {
> + MCS7830_WR_BREQ = 0x0d,
> + MCS7830_RD_BREQ = 0x0e,
> +};
> +
> +/* register offsets, field bitmasks and default values */
> +enum {
> + REG_MULTICAST_HASH = 0x00,
> + REG_PHY_DATA = 0x0a,
> + REG_PHY_CMD1 = 0x0c,
> + PHY_CMD1_READ = BIT(6),
> + PHY_CMD1_WRITE = BIT(5),
> + PHY_CMD1_PHYADDR = BIT(0),
> + REG_PHY_CMD2 = 0x0d,
> + PHY_CMD2_PEND_FLAG_BIT = BIT(7),
> + PHY_CMD2_READY_FLAG_BIT = BIT(6),
> + REG_CONFIG = 0x0e,
> + CONFIG_CFG = BIT(7),
> + CONFIG_SPEED100 = BIT(6),
> + CONFIG_FDX_ENABLE = BIT(5),
> + CONFIG_RXENABLE = BIT(4),
> + CONFIG_TXENABLE = BIT(3),
> + CONFIG_SLEEPMODE = BIT(2),
> + CONFIG_ALLMULTICAST = BIT(1),
> + CONFIG_PROMISCUOUS = BIT(0),
> + REG_ETHER_ADDR = 0x0f,
> + REG_FRAME_DROP_COUNTER = 0x15,
> + REG_PAUSE_THRESHOLD = 0x16,
> + PAUSE_THRESHOLD_DEFAULT = 0,
> +};
Why don't you just use structure with padding as the rest of the U-Boot does ?
Like so:
struct regs {
u8 reg1;
u8 pad1[n];
u8 reg2;
...
};
> +
> +/* trailing status byte after RX frame */
> +enum {
> + STAT_RX_FRAME_CORRECT = BIT(5),
> + STAT_RX_LARGE_FRAME = BIT(4),
> + STAT_RX_CRC_ERROR = BIT(3),
> + STAT_RX_ALIGNMENT_ERROR = BIT(2),
> + STAT_RX_LENGTH_ERROR = BIT(1),
> + STAT_RX_SHORT_FRAME = BIT(0),
> +};
I am not quite fond of the enum for bits, but I don't care enough either .
> +struct mcs7830_private {
> + uint8_t config;
> + uint8_t mchash[8];
> +};
> +
> +/* }}} global declarations */
> +/* private helper routines {{{ */
> +
> +static int mcs7830_read_reg(struct ueth_data *dev, uint8_t idx,
> + uint16_t size, void *data)
> +{
> + int len;
> + ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size);
> +
> + debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size);
> +
> + len = usb_control_msg(dev->pusb_dev,
> + usb_rcvctrlpipe(dev->pusb_dev, 0),
> + MCS7830_RD_BREQ,
> + USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> + 0, idx, buf, size,
> + USB_CTRL_GET_TIMEOUT);
> + if (len == size) {
> + memcpy(data, buf, size);
> + return 0;
> + }
> + debug("%s() len=%d != sz=%d\n", __func__, len, size);
> + return -1;
Use errno.h defines for return codes please.
> +}
> +
> +static int mcs7830_write_reg(struct ueth_data *dev, uint8_t idx,
> + uint16_t size, void *data)
> +{
> + int len;
> + ALLOC_CACHE_ALIGN_BUFFER(uint8_t, buf, size);
> +
> + debug("%s() idx=0x%04X sz=%d\n", __func__, idx, size);
> +
> + memcpy(buf, data, size);
> + len = usb_control_msg(dev->pusb_dev,
> + usb_sndctrlpipe(dev->pusb_dev, 0),
> + MCS7830_WR_BREQ,
> + USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
> + 0, idx, buf, size,
> + USB_CTRL_SET_TIMEOUT);
> + if (len != size)
> + debug("%s() len=%d != sz=%d\n", __func__, len, size);
> + return (len == size) ? 0 : -1;
DTTO.
> +}
> +
> +static int mcs7830_read_phy(struct ueth_data *dev, uint8_t index)
> +{
> + int rc;
> + int retry;
> + uint8_t cmd[2];
> + uint16_t val;
> +
> + /* send the PHY read request */
> + cmd[0] = PHY_CMD1_READ | PHY_CMD1_PHYADDR;
> + cmd[1] = PHY_CMD2_PEND_FLAG_BIT | (index & 0x1f);
> + rc = mcs7830_write_reg(dev, REG_PHY_CMD1, sizeof(cmd), cmd);
> + if (rc < 0)
> + return rc;
> +
> + /* wait for the response to become available (usually < 1ms) */
> + retry = 10;
> + do {
> + rc = mcs7830_read_reg(dev, REG_PHY_CMD1, sizeof(cmd), cmd);
> + if (rc < 0)
> + return rc;
> + if (cmd[1] & PHY_CMD2_READY_FLAG_BIT)
> + break;
Hm ... if retry==1 , then the following if (!retry) test will fail ...
> + if (!retry)
> + return -EIO;
> + mdelay(1);
> + } while (--retry);
... and the loop will exit here. Yet, (cmd[1] & PHY_CMD2_READY_FLAG_BIT) might
still not be set . Right ?
> + /* fetch the response data */
> + rc = mcs7830_read_reg(dev, REG_PHY_DATA, sizeof(val), &val);
> + if (rc < 0)
> + return rc;
> + rc = le16_to_cpu(val);
> + debug("%s(%s, %d) => 0x%04X\n", __func__, dev->eth_dev.name, index, rc);
> + return rc;
> +}
[...]
> +static int mcs7830_init(struct eth_device *eth, bd_t *bd)
> +{
> + struct ueth_data *dev;
> + int timeout;
> + int have_link;
> +
> + debug("%s()\n", __func__);
> + dev = eth->priv;
> +
> + timeout = 0;
> + do {
> + have_link = mcs7830_read_phy(dev, MII_BMSR) & BMSR_LSTATUS;
> + if (!have_link) {
> + if (!timeout)
> + puts("Waiting for ethernet connection ... ");
> + udelay(PHY_CONNECT_TIMEOUT_RES * 1000);
> + timeout += PHY_CONNECT_TIMEOUT_RES;
> + }
> + } while (!have_link && timeout < PHY_CONNECT_TIMEOUT);
> + if (have_link) {
> + if (timeout)
> + puts("done.\n");
> + return 0;
> + } else {
> + puts("unable to connect.\n");
> + return -1;
> + }
Uh, this code is not quite clear to me ... can you not simplify this weird loop?
[...]
More information about the U-Boot
mailing list