net: smsc95xx: Add driver-model support
Add support for driver model, so that CONFIG_DM_ETH can be defined and used with this driver. Signed-off-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
parent
527298c4b5
commit
0990fcb772
@ -1,4 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2015 Google, Inc
|
||||
* Copyright (c) 2011 The Chromium OS Authors.
|
||||
* Copyright (C) 2009 NVIDIA, Corporation
|
||||
* Copyright (C) 2007-2008 SMSC (Steve Glendinning)
|
||||
@ -7,6 +8,7 @@
|
||||
*/
|
||||
|
||||
#include <common.h>
|
||||
#include <dm.h>
|
||||
#include <errno.h>
|
||||
#include <malloc.h>
|
||||
#include <usb.h>
|
||||
@ -137,11 +139,16 @@
|
||||
|
||||
#define TURBO_MODE
|
||||
|
||||
#ifndef CONFIG_DM_ETH
|
||||
/* local vars */
|
||||
static int curr_eth_dev; /* index for name of next device detected */
|
||||
#endif
|
||||
|
||||
/* driver private */
|
||||
struct smsc95xx_private {
|
||||
#ifdef CONFIG_DM_ETH
|
||||
struct ueth_data ueth;
|
||||
#endif
|
||||
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 */
|
||||
@ -714,6 +721,7 @@ static int smsc95xx_send_common(struct ueth_data *dev, void *packet, int length)
|
||||
return err;
|
||||
}
|
||||
|
||||
#ifndef CONFIG_DM_ETH
|
||||
/*
|
||||
* Smsc95xx callbacks
|
||||
*/
|
||||
@ -931,3 +939,137 @@ int smsc95xx_eth_get_info(struct usb_device *dev, struct ueth_data *ss,
|
||||
eth->priv = ss;
|
||||
return 1;
|
||||
}
|
||||
#endif /* !CONFIG_DM_ETH */
|
||||
|
||||
#ifdef CONFIG_DM_ETH
|
||||
static int smsc95xx_eth_start(struct udevice *dev)
|
||||
{
|
||||
struct usb_device *udev = dev_get_parentdata(dev);
|
||||
struct smsc95xx_private *priv = dev_get_priv(dev);
|
||||
struct eth_pdata *pdata = dev_get_platdata(dev);
|
||||
|
||||
/* Driver-model Ethernet ensures we have this */
|
||||
priv->have_hwaddr = 1;
|
||||
|
||||
return smsc95xx_init_common(udev, &priv->ueth, priv, pdata->enetaddr);
|
||||
}
|
||||
|
||||
void smsc95xx_eth_stop(struct udevice *dev)
|
||||
{
|
||||
debug("** %s()\n", __func__);
|
||||
}
|
||||
|
||||
int smsc95xx_eth_send(struct udevice *dev, void *packet, int length)
|
||||
{
|
||||
struct smsc95xx_private *priv = dev_get_priv(dev);
|
||||
|
||||
return smsc95xx_send_common(&priv->ueth, packet, length);
|
||||
}
|
||||
|
||||
int smsc95xx_eth_recv(struct udevice *dev, int flags, uchar **packetp)
|
||||
{
|
||||
struct smsc95xx_private *priv = dev_get_priv(dev);
|
||||
struct ueth_data *ueth = &priv->ueth;
|
||||
uint8_t *ptr;
|
||||
int ret, len;
|
||||
u32 packet_len;
|
||||
|
||||
len = usb_ether_get_rx_bytes(ueth, &ptr);
|
||||
debug("%s: first try, len=%d\n", __func__, len);
|
||||
if (!len) {
|
||||
if (!(flags & ETH_RECV_CHECK_DEVICE))
|
||||
return -EAGAIN;
|
||||
ret = usb_ether_receive(ueth, RX_URB_SIZE);
|
||||
if (ret == -EAGAIN)
|
||||
return ret;
|
||||
|
||||
len = usb_ether_get_rx_bytes(ueth, &ptr);
|
||||
debug("%s: second try, len=%d\n", __func__, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* 1st 4 bytes contain the length of the actual data plus error info.
|
||||
* Extract data length.
|
||||
*/
|
||||
if (len < sizeof(packet_len)) {
|
||||
debug("Rx: incomplete packet length\n");
|
||||
goto err;
|
||||
}
|
||||
memcpy(&packet_len, ptr, sizeof(packet_len));
|
||||
le32_to_cpus(&packet_len);
|
||||
if (packet_len & RX_STS_ES_) {
|
||||
debug("Rx: Error header=%#x", packet_len);
|
||||
goto err;
|
||||
}
|
||||
packet_len = ((packet_len & RX_STS_FL_) >> 16);
|
||||
|
||||
if (packet_len > len - sizeof(packet_len)) {
|
||||
debug("Rx: too large packet: %d\n", packet_len);
|
||||
goto err;
|
||||
}
|
||||
|
||||
*packetp = ptr + sizeof(packet_len);
|
||||
return packet_len;
|
||||
|
||||
err:
|
||||
usb_ether_advance_rxbuf(ueth, -1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int smsc95xx_free_pkt(struct udevice *dev, uchar *packet, int packet_len)
|
||||
{
|
||||
struct smsc95xx_private *priv = dev_get_priv(dev);
|
||||
|
||||
packet_len = ALIGN(packet_len, 4);
|
||||
usb_ether_advance_rxbuf(&priv->ueth, sizeof(u32) + packet_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int smsc95xx_write_hwaddr(struct udevice *dev)
|
||||
{
|
||||
struct usb_device *udev = dev_get_parentdata(dev);
|
||||
struct eth_pdata *pdata = dev_get_platdata(dev);
|
||||
struct smsc95xx_private *priv = dev_get_priv(dev);
|
||||
|
||||
return smsc95xx_write_hwaddr_common(udev, priv, pdata->enetaddr);
|
||||
}
|
||||
|
||||
static int smsc95xx_eth_probe(struct udevice *dev)
|
||||
{
|
||||
struct smsc95xx_private *priv = dev_get_priv(dev);
|
||||
struct ueth_data *ueth = &priv->ueth;
|
||||
|
||||
return usb_ether_register(dev, ueth, RX_URB_SIZE);
|
||||
}
|
||||
|
||||
static const struct eth_ops smsc95xx_eth_ops = {
|
||||
.start = smsc95xx_eth_start,
|
||||
.send = smsc95xx_eth_send,
|
||||
.recv = smsc95xx_eth_recv,
|
||||
.free_pkt = smsc95xx_free_pkt,
|
||||
.stop = smsc95xx_eth_stop,
|
||||
.write_hwaddr = smsc95xx_write_hwaddr,
|
||||
};
|
||||
|
||||
U_BOOT_DRIVER(smsc95xx_eth) = {
|
||||
.name = "smsc95xx_eth",
|
||||
.id = UCLASS_ETH,
|
||||
.probe = smsc95xx_eth_probe,
|
||||
.ops = &smsc95xx_eth_ops,
|
||||
.priv_auto_alloc_size = sizeof(struct smsc95xx_private),
|
||||
.platdata_auto_alloc_size = sizeof(struct eth_pdata),
|
||||
};
|
||||
|
||||
static const struct usb_device_id smsc95xx_eth_id_table[] = {
|
||||
{ USB_DEVICE(0x05ac, 0x1402) },
|
||||
{ USB_DEVICE(0x0424, 0xec00) }, /* LAN9512/LAN9514 Ethernet */
|
||||
{ USB_DEVICE(0x0424, 0x9500) }, /* LAN9500 Ethernet */
|
||||
{ USB_DEVICE(0x0424, 0x9730) }, /* LAN9730 Ethernet (HSIC) */
|
||||
{ USB_DEVICE(0x0424, 0x9900) }, /* SMSC9500 USB Ethernet (SAL10) */
|
||||
{ USB_DEVICE(0x0424, 0x9e00) }, /* LAN9500A Ethernet */
|
||||
{ } /* Terminating entry */
|
||||
};
|
||||
|
||||
U_BOOT_USB_DEVICE(smsc95xx_eth, smsc95xx_eth_id_table);
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user