* MA 02111-1307 USA
*/
+#include <asm/unaligned.h>
#include <common.h>
#include <usb.h>
#include <linux/mii.h>
#include "usb_ether.h"
+#include <malloc.h>
/* SMSC LAN95xx based USB 2.0 Ethernet Devices */
/* local vars */
static int curr_eth_dev; /* index for name of next device detected */
+/* driver private */
+struct smsc95xx_private {
+ size_t rx_urb_size; /* maximum USB URB size */
+ u32 mac_cr; /* MAC control register value */
+ int have_hwaddr; /* 1 if we have a hardware MAC address */
+};
/*
* Smsc95xx infrastructure commands
static int smsc95xx_write_reg(struct ueth_data *dev, u32 index, u32 data)
{
int len;
+ ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
cpu_to_le32s(&data);
+ tmpbuf[0] = data;
len = usb_control_msg(dev->pusb_dev, usb_sndctrlpipe(dev->pusb_dev, 0),
USB_VENDOR_REQUEST_WRITE_REGISTER,
USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, &data, sizeof(data), USB_CTRL_SET_TIMEOUT);
+ 00, index, tmpbuf, sizeof(data), USB_CTRL_SET_TIMEOUT);
if (len != sizeof(data)) {
debug("smsc95xx_write_reg failed: index=%d, data=%d, len=%d",
index, data, len);
static int smsc95xx_read_reg(struct ueth_data *dev, u32 index, u32 *data)
{
int len;
+ ALLOC_CACHE_ALIGN_BUFFER(u32, tmpbuf, 1);
len = usb_control_msg(dev->pusb_dev, usb_rcvctrlpipe(dev->pusb_dev, 0),
USB_VENDOR_REQUEST_READ_REGISTER,
USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
- 00, index, data, sizeof(data), USB_CTRL_GET_TIMEOUT);
+ 00, index, tmpbuf, sizeof(data), USB_CTRL_GET_TIMEOUT);
+ *data = tmpbuf[0];
if (len != sizeof(data)) {
debug("smsc95xx_read_reg failed: index=%d, len=%d",
index, len);
do {
smsc95xx_read_reg(dev, E2P_CMD, &val);
- if (!(val & E2P_CMD_LOADED_)) {
- debug("No EEPROM present\n");
- return -1;
- }
if (!(val & E2P_CMD_BUSY_))
return 0;
udelay(40);
static int smsc95xx_write_hwaddr(struct eth_device *eth)
{
struct ueth_data *dev = (struct ueth_data *)eth->priv;
- u32 addr_lo, addr_hi;
+ struct smsc95xx_private *priv = dev->dev_priv;
+ u32 addr_lo = __get_unaligned_le32(ð->enetaddr[0]);
+ u32 addr_hi = __get_unaligned_le16(ð->enetaddr[4]);
int ret;
/* set hardware address */
debug("** %s()\n", __func__);
- addr_lo = cpu_to_le32(*((u32 *)eth->enetaddr));
- addr_hi = cpu_to_le16(*((u16 *)(eth->enetaddr + 4)));
ret = smsc95xx_write_reg(dev, ADDRL, addr_lo);
- if (ret < 0) {
- debug("Failed to write ADDRL: %d\n", ret);
+ if (ret < 0)
return ret;
- }
ret = smsc95xx_write_reg(dev, ADDRH, addr_hi);
if (ret < 0)
return ret;
- debug("MAC %02x:%02x:%02x:%02x:%02x:%02x\n",
- eth->enetaddr[0], eth->enetaddr[1],
- eth->enetaddr[2], eth->enetaddr[3],
- eth->enetaddr[4], eth->enetaddr[5]);
- dev->have_hwaddr = 1;
+
+ debug("MAC %pM\n", eth->enetaddr);
+ priv->have_hwaddr = 1;
return 0;
}
static void smsc95xx_set_multicast(struct ueth_data *dev)
{
+ struct smsc95xx_private *priv = dev->dev_priv;
+
/* No multicast in u-boot */
- dev->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
+ priv->mac_cr &= ~(MAC_CR_PRMS_ | MAC_CR_MCPAS_ | MAC_CR_HPFILT_);
}
/* starts the TX path */
static void smsc95xx_start_tx_path(struct ueth_data *dev)
{
+ struct smsc95xx_private *priv = dev->dev_priv;
u32 reg_val;
/* Enable Tx at MAC */
- dev->mac_cr |= MAC_CR_TXEN_;
+ priv->mac_cr |= MAC_CR_TXEN_;
- smsc95xx_write_reg(dev, MAC_CR, dev->mac_cr);
+ smsc95xx_write_reg(dev, MAC_CR, priv->mac_cr);
/* Enable Tx at SCSRs */
reg_val = TX_CFG_ON_;
/* Starts the Receive path */
static void smsc95xx_start_rx_path(struct ueth_data *dev)
{
- dev->mac_cr |= MAC_CR_RXEN_;
- smsc95xx_write_reg(dev, MAC_CR, dev->mac_cr);
+ struct smsc95xx_private *priv = dev->dev_priv;
+
+ priv->mac_cr |= MAC_CR_RXEN_;
+ smsc95xx_write_reg(dev, MAC_CR, priv->mac_cr);
}
/*
u32 burst_cap;
int timeout;
struct ueth_data *dev = (struct ueth_data *)eth->priv;
+ struct smsc95xx_private *priv =
+ (struct smsc95xx_private *)dev->dev_priv;
#define TIMEOUT_RESOLUTION 50 /* ms */
int link_detected;
debug("timeout waiting for PHY Reset\n");
return -1;
}
- if (!dev->have_hwaddr && smsc95xx_init_mac_address(eth, dev) == 0)
- dev->have_hwaddr = 1;
- if (!dev->have_hwaddr) {
+ if (!priv->have_hwaddr && smsc95xx_init_mac_address(eth, dev) == 0)
+ priv->have_hwaddr = 1;
+ if (!priv->have_hwaddr) {
puts("Error: SMSC95xx: No MAC address set - set usbethaddr\n");
return -1;
}
#ifdef TURBO_MODE
if (dev->pusb_dev->speed == USB_SPEED_HIGH) {
burst_cap = DEFAULT_HS_BURST_CAP_SIZE / HS_USB_PKT_SIZE;
- dev->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
+ priv->rx_urb_size = DEFAULT_HS_BURST_CAP_SIZE;
} else {
burst_cap = DEFAULT_FS_BURST_CAP_SIZE / FS_USB_PKT_SIZE;
- dev->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
+ priv->rx_urb_size = DEFAULT_FS_BURST_CAP_SIZE;
}
#else
burst_cap = 0;
- dev->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
+ priv->rx_urb_size = MAX_SINGLE_PACKET_SIZE;
#endif
- debug("rx_urb_size=%ld\n", (ulong)dev->rx_urb_size);
+ debug("rx_urb_size=%ld\n", (ulong)priv->rx_urb_size);
ret = smsc95xx_write_reg(dev, BURST_CAP, burst_cap);
if (ret < 0)
if (ret < 0)
return ret;
- ret = smsc95xx_read_reg(dev, MAC_CR, &dev->mac_cr);
+ ret = smsc95xx_read_reg(dev, MAC_CR, &priv->mac_cr);
if (ret < 0)
return ret;
return 0;
}
-static int smsc95xx_send(struct eth_device *eth, volatile void* packet,
- int length)
+static int smsc95xx_send(struct eth_device *eth, void* packet, int length)
{
struct ueth_data *dev = (struct ueth_data *)eth->priv;
int err;
int actual_len;
u32 tx_cmd_a;
u32 tx_cmd_b;
- unsigned char msg[PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b)];
+ ALLOC_CACHE_ALIGN_BUFFER(unsigned char, msg,
+ PKTSIZE + sizeof(tx_cmd_a) + sizeof(tx_cmd_b));
debug("** %s(), len %d, buf %#x\n", __func__, length, (int)msg);
if (length > PKTSIZE)
static int smsc95xx_recv(struct eth_device *eth)
{
struct ueth_data *dev = (struct ueth_data *)eth->priv;
- static unsigned char recv_buf[AX_RX_URB_SIZE];
+ DEFINE_CACHE_ALIGN_BUFFER(unsigned char, recv_buf, AX_RX_URB_SIZE);
unsigned char *buf_ptr;
int err;
int actual_len;
static const struct smsc95xx_dongle smsc95xx_dongles[] = {
{ 0x0424, 0xec00 }, /* LAN9512/LAN9514 Ethernet */
{ 0x0424, 0x9500 }, /* LAN9500 Ethernet */
+ { 0x0424, 0x9730 }, /* LAN9730 Ethernet (HSIC) */
{ 0x0000, 0x0000 } /* END - Do not remove */
};
return 0;
}
dev->privptr = (void *)ss;
+
+ /* alloc driver private */
+ ss->dev_priv = calloc(1, sizeof(struct smsc95xx_private));
+ if (!ss->dev_priv)
+ return 0;
+
return 1;
}