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 <g...@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? [...] _______________________________________________ U-Boot mailing list U-Boot@lists.denx.de http://lists.denx.de/mailman/listinfo/u-boot