diff options
Diffstat (limited to 'drivers/usb/gadget/ether.c')
-rw-r--r-- | drivers/usb/gadget/ether.c | 169 |
1 files changed, 115 insertions, 54 deletions
diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 497b981129b..289e5f15837 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -24,6 +24,10 @@ #include "gadget_chips.h" #include "rndis.h" +#include <dm.h> +#include <dm/uclass-internal.h> +#include <dm/device-internal.h> + #define USB_NET_NAME "usb_ether" #define atomic_read @@ -76,7 +80,6 @@ unsigned packet_received, packet_sent; /* Based on linux 2.6.27 version */ #define DRIVER_VERSION "May Day 2005" -static const char shortname[] = "ether"; static const char driver_desc[] = DRIVER_DESC; #define RX_EXTRA 20 /* guard against rx overflows */ @@ -101,6 +104,9 @@ struct eth_dev { struct usb_gadget *gadget; struct usb_request *req; /* for control responses */ struct usb_request *stat_req; /* for cdc & rndis status */ +#ifdef CONFIG_DM_USB + struct udevice *usb_udev; +#endif u8 config; struct usb_ep *in_ep, *out_ep, *status_ep; @@ -134,9 +140,14 @@ struct eth_dev { */ /*-------------------------------------------------------------------------*/ -static struct eth_dev l_ethdev; -static struct eth_device l_netdev; -static struct usb_gadget_driver eth_driver; +struct ether_priv { + struct eth_dev ethdev; + struct eth_device netdev; + struct usb_gadget_driver eth_driver; +}; + +struct ether_priv eth_priv; +struct ether_priv *l_priv = ð_priv; /*-------------------------------------------------------------------------*/ @@ -1135,7 +1146,7 @@ static void eth_status_complete(struct usb_ep *ep, struct usb_request *req) event->bNotificationType, value); if (event->bNotificationType == USB_CDC_NOTIFY_SPEED_CHANGE) { - l_ethdev.network_started = 1; + dev->network_started = 1; printf("USB network up!\n"); } } @@ -1323,7 +1334,7 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl) * that network is working. So we signalize it * here. */ - l_ethdev.network_started = 1; + dev->network_started = 1; debug("USB network up!\n"); goto done_set_intf; } @@ -1823,10 +1834,10 @@ static void rndis_control_ack_complete(struct usb_ep *ep, debug("rndis control ack complete --> %d, %d/%d\n", req->status, req->actual, req->length); - if (!l_ethdev.network_started) { + if (!dev->network_started) { if (rndis_get_state(dev->rndis_config) == RNDIS_DATA_INITIALIZED) { - l_ethdev.network_started = 1; + dev->network_started = 1; printf("USB RNDIS network up!\n"); } } @@ -1841,7 +1852,8 @@ static char rndis_resp_buf[8] __attribute__((aligned(sizeof(__le32)))); static int rndis_control_ack(struct eth_device *net) { - struct eth_dev *dev = &l_ethdev; + struct ether_priv *priv = (struct ether_priv *)net->priv; + struct eth_dev *dev = &priv->ethdev; int length; struct usb_request *resp = dev->stat_req; @@ -1982,7 +1994,7 @@ static int get_ether_addr(const char *str, u8 *dev_addr) static int eth_bind(struct usb_gadget *gadget) { - struct eth_dev *dev = &l_ethdev; + struct eth_dev *dev = &l_priv->ethdev; u8 cdc = 1, zlp = 1, rndis = 1; struct usb_ep *in_ep, *out_ep, *status_ep = NULL; int status = -ENOMEM; @@ -2175,7 +2187,7 @@ autoconf_fail: /* network device setup */ - dev->net = &l_netdev; + dev->net = &l_priv->netdev; dev->cdc = cdc; dev->zlp = zlp; @@ -2303,19 +2315,39 @@ fail: /*-------------------------------------------------------------------------*/ -static int usb_eth_init(struct eth_device *netdev, bd_t *bd) +#ifdef CONFIG_DM_USB +int dm_usb_init(struct eth_dev *e_dev) { - struct eth_dev *dev = &l_ethdev; + struct udevice *dev = NULL; + int ret; + + ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &dev); + if (!dev || ret) { + error("No USB device found\n"); + return -ENODEV; + } + + e_dev->usb_udev = dev; + + return ret; +} +#endif + +static int _usb_eth_init(struct ether_priv *priv) +{ + struct eth_dev *dev = &priv->ethdev; struct usb_gadget *gadget; unsigned long ts; unsigned long timeout = USB_CONNECT_TIMEOUT; - if (!netdev) { - error("received NULL ptr"); - goto fail; +#ifdef CONFIG_DM_USB + if (dm_usb_init(dev)) { + error("USB ether not found\n"); + return -ENODEV; } - +#else board_usb_init(0, USB_INIT_DEVICE); +#endif /* Configure default mac-addresses for the USB ethernet device */ #ifdef CONFIG_USBNET_DEV_ADDR @@ -2342,7 +2374,15 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd) goto fail; } - if (usb_gadget_register_driver(ð_driver) < 0) + priv->eth_driver.speed = DEVSPEED; + priv->eth_driver.bind = eth_bind; + priv->eth_driver.unbind = eth_unbind; + priv->eth_driver.setup = eth_setup; + priv->eth_driver.reset = eth_disconnect; + priv->eth_driver.disconnect = eth_disconnect; + priv->eth_driver.suspend = eth_suspend; + priv->eth_driver.resume = eth_resume; + if (usb_gadget_register_driver(&priv->eth_driver) < 0) goto fail; dev->network_started = 0; @@ -2357,7 +2397,7 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd) timeout = simple_strtoul(getenv("cdc_connect_timeout"), NULL, 10) * CONFIG_SYS_HZ; ts = get_timer(0); - while (!l_ethdev.network_started) { + while (!dev->network_started) { /* Handle control-c and timeouts */ if (ctrlc() || (get_timer(ts) > timeout)) { error("The remote end did not respond in time."); @@ -2373,11 +2413,11 @@ fail: return -1; } -static int usb_eth_send(struct eth_device *netdev, void *packet, int length) +static int _usb_eth_send(struct ether_priv *priv, void *packet, int length) { int retval; void *rndis_pkt = NULL; - struct eth_dev *dev = &l_ethdev; + struct eth_dev *dev = &priv->ethdev; struct usb_request *req = dev->tx_req; unsigned long ts; unsigned long timeout = USB_CONNECT_TIMEOUT; @@ -2442,34 +2482,16 @@ drop: return -ENOMEM; } -static int usb_eth_recv(struct eth_device *netdev) +static int _usb_eth_recv(struct ether_priv *priv) { - struct eth_dev *dev = &l_ethdev; - usb_gadget_handle_interrupts(0); - if (packet_received) { - debug("%s: packet received\n", __func__); - if (dev->rx_req) { - net_process_received_packet(net_rx_packets[0], - dev->rx_req->length); - packet_received = 0; - - rx_submit(dev, dev->rx_req, 0); - } else - error("dev->rx_req invalid"); - } return 0; } -void usb_eth_halt(struct eth_device *netdev) +void _usb_eth_halt(struct ether_priv *priv) { - struct eth_dev *dev = &l_ethdev; - - if (!netdev) { - error("received NULL ptr"); - return; - } + struct eth_dev *dev = &priv->ethdev; /* If the gadget not registered, simple return */ if (!dev->gadget) @@ -2496,27 +2518,65 @@ void usb_eth_halt(struct eth_device *netdev) dev->network_started = 0; } - usb_gadget_unregister_driver(ð_driver); + usb_gadget_unregister_driver(&priv->eth_driver); +#ifdef CONFIG_DM_USB + device_remove(dev->usb_udev); +#else board_usb_cleanup(0, USB_INIT_DEVICE); +#endif +} + +static int usb_eth_init(struct eth_device *netdev, bd_t *bd) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; + + return _usb_eth_init(priv); } -static struct usb_gadget_driver eth_driver = { - .speed = DEVSPEED, +static int usb_eth_send(struct eth_device *netdev, void *packet, int length) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; - .bind = eth_bind, - .unbind = eth_unbind, + return _usb_eth_send(priv, packet, length); +} - .setup = eth_setup, - .reset = eth_disconnect, - .disconnect = eth_disconnect, +static int usb_eth_recv(struct eth_device *netdev) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; + struct eth_dev *dev = &priv->ethdev; + int ret; + + ret = _usb_eth_recv(priv); + if (ret) { + error("error packet receive\n"); + return ret; + } - .suspend = eth_suspend, - .resume = eth_resume, -}; + if (!packet_received) + return 0; + + if (dev->rx_req) { + net_process_received_packet(net_rx_packets[0], + dev->rx_req->length); + } else { + error("dev->rx_req invalid"); + } + packet_received = 0; + rx_submit(dev, dev->rx_req, 0); + + return 0; +} + +void usb_eth_halt(struct eth_device *netdev) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; + + _usb_eth_halt(priv); +} int usb_eth_initialize(bd_t *bi) { - struct eth_device *netdev = &l_netdev; + struct eth_device *netdev = &l_priv->netdev; strlcpy(netdev->name, USB_NET_NAME, sizeof(netdev->name)); @@ -2524,6 +2584,7 @@ int usb_eth_initialize(bd_t *bi) netdev->send = usb_eth_send; netdev->recv = usb_eth_recv; netdev->halt = usb_eth_halt; + netdev->priv = l_priv; #ifdef CONFIG_MCAST_TFTP #error not supported |