X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=drivers%2Fusb%2Fgadget%2Fether.c;h=4137d76c42afb29a95a29b66a49798e54322af64;hb=12d0b8f5f07b76d7447d60f7528d578233553909;hp=141ff8be59ab3c361ba79b2365d501e20fb13a54;hpb=e536ab8849b2b4f6d68bbc8e1d1f9bc033db06bd;p=u-boot diff --git a/drivers/usb/gadget/ether.c b/drivers/usb/gadget/ether.c index 141ff8be59..4137d76c42 100644 --- a/drivers/usb/gadget/ether.c +++ b/drivers/usb/gadget/ether.c @@ -9,18 +9,26 @@ */ #include -#include +#include +#include #include #include #include #include #include +#include #include +#include #include #include "gadget_chips.h" #include "rndis.h" +#include +#include +#include +#include + #define USB_NET_NAME "usb_ether" #define atomic_read @@ -73,7 +81,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 */ @@ -98,6 +105,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; @@ -106,7 +116,11 @@ struct eth_dev { struct usb_request *tx_req, *rx_req; +#ifndef CONFIG_DM_ETH struct eth_device *net; +#else + struct udevice *net; +#endif struct net_device_stats stats; unsigned int tx_qlen; @@ -131,9 +145,18 @@ 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; +#ifndef CONFIG_DM_ETH + struct eth_device netdev; +#else + struct udevice *netdev; +#endif + struct usb_gadget_driver eth_driver; +}; + +struct ether_priv eth_priv; +struct ether_priv *l_priv = ð_priv; /*-------------------------------------------------------------------------*/ @@ -253,7 +276,7 @@ static inline int BITRATE(struct usb_gadget *g) #if defined(CONFIG_USBNET_MANUFACTURER) static char *iManufacturer = CONFIG_USBNET_MANUFACTURER; #else -static char *iManufacturer = "U-boot"; +static char *iManufacturer = "U-Boot"; #endif /* These probably need to be configurable. */ @@ -484,6 +507,7 @@ static const struct usb_cdc_mdlm_desc mdlm_desc = { * can't really use its struct. All we do here is say that we're using * the submode of "SAFE" which directly matches the CDC Subset. */ +#ifdef CONFIG_USB_ETH_SUBSET static const u8 mdlm_detail_desc[] = { 6, USB_DT_CS_INTERFACE, @@ -493,6 +517,7 @@ static const u8 mdlm_detail_desc[] = { 0, /* network control capabilities (none) */ 0, /* network data capabilities ("raw" encapsulation) */ }; +#endif #endif @@ -1132,7 +1157,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"); } } @@ -1320,7 +1345,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; } @@ -1820,10 +1845,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"); } } @@ -1836,9 +1861,14 @@ static void rndis_control_ack_complete(struct usb_ep *ep, static char rndis_resp_buf[8] __attribute__((aligned(sizeof(__le32)))); +#ifndef CONFIG_DM_ETH static int rndis_control_ack(struct eth_device *net) +#else +static int rndis_control_ack(struct udevice *net) +#endif { - 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; @@ -1979,12 +2009,15 @@ 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; int gcnum; u8 tmp[7]; +#ifdef CONFIG_DM_ETH + struct eth_pdata *pdata = dev_get_platdata(l_priv->netdev); +#endif /* these flags are only ever cleared; compiler take note */ #ifndef CONFIG_USB_ETH_CDC @@ -2172,7 +2205,11 @@ autoconf_fail: /* network device setup */ - dev->net = &l_netdev; +#ifndef CONFIG_DM_ETH + dev->net = &l_priv->netdev; +#else + dev->net = l_priv->netdev; +#endif dev->cdc = cdc; dev->zlp = zlp; @@ -2181,6 +2218,7 @@ autoconf_fail: dev->out_ep = out_ep; dev->status_ep = status_ep; + memset(tmp, 0, sizeof(tmp)); /* * Module params for these addresses should come from ID proms. * The host side address is used with CDC and RNDIS, and commonly @@ -2188,10 +2226,13 @@ autoconf_fail: * host side code for the SAFE thing cares -- its original BLAN * thing didn't, Sharp never assigned those addresses on Zaurii. */ +#ifndef CONFIG_DM_ETH get_ether_addr(dev_addr, dev->net->enetaddr); - - memset(tmp, 0, sizeof(tmp)); memcpy(tmp, dev->net->enetaddr, sizeof(dev->net->enetaddr)); +#else + get_ether_addr(dev_addr, pdata->enetaddr); + memcpy(tmp, pdata->enetaddr, sizeof(pdata->enetaddr)); +#endif get_ether_addr(host_addr, dev->host_mac); @@ -2252,10 +2293,11 @@ autoconf_fail: status_ep ? " STATUS " : "", status_ep ? status_ep->name : "" ); - printf("MAC %02x:%02x:%02x:%02x:%02x:%02x\n", - dev->net->enetaddr[0], dev->net->enetaddr[1], - dev->net->enetaddr[2], dev->net->enetaddr[3], - dev->net->enetaddr[4], dev->net->enetaddr[5]); +#ifndef CONFIG_DM_ETH + printf("MAC %pM\n", dev->net->enetaddr); +#else + printf("MAC %pM\n", pdata->enetaddr); +#endif if (cdc || rndis) printf("HOST MAC %02x:%02x:%02x:%02x:%02x:%02x\n", @@ -2300,17 +2342,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 @@ -2337,7 +2401,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; @@ -2352,7 +2424,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."); @@ -2368,11 +2440,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; @@ -2437,34 +2509,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) @@ -2491,25 +2545,64 @@ void usb_eth_halt(struct eth_device *netdev) dev->network_started = 0; } - usb_gadget_unregister_driver(ð_driver); + usb_gadget_unregister_driver(&priv->eth_driver); +#ifndef CONFIG_DM_USB + board_usb_cleanup(0, USB_INIT_DEVICE); +#endif } -static struct usb_gadget_driver eth_driver = { - .speed = DEVSPEED, +#ifndef CONFIG_DM_ETH +static int usb_eth_init(struct eth_device *netdev, bd_t *bd) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; - .bind = eth_bind, - .unbind = eth_unbind, + return _usb_eth_init(priv); +} - .setup = eth_setup, - .disconnect = eth_disconnect, +static int usb_eth_send(struct eth_device *netdev, void *packet, int length) +{ + struct ether_priv *priv = (struct ether_priv *)netdev->priv; - .suspend = eth_suspend, - .resume = eth_resume, -}; + return _usb_eth_send(priv, packet, length); +} + +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; + } + + 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)); @@ -2517,6 +2610,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 @@ -2524,3 +2618,114 @@ int usb_eth_initialize(bd_t *bi) eth_register(netdev); return 0; } +#else +static int usb_eth_start(struct udevice *dev) +{ + struct ether_priv *priv = dev_get_priv(dev); + + return _usb_eth_init(priv); +} + +static int usb_eth_send(struct udevice *dev, void *packet, int length) +{ + struct ether_priv *priv = dev_get_priv(dev); + + return _usb_eth_send(priv, packet, length); +} + +static int usb_eth_recv(struct udevice *dev, int flags, uchar **packetp) +{ + struct ether_priv *priv = dev_get_priv(dev); + struct eth_dev *ethdev = &priv->ethdev; + int ret; + + ret = _usb_eth_recv(priv); + if (ret) { + error("error packet receive\n"); + return ret; + } + + if (packet_received) { + if (ethdev->rx_req) { + *packetp = (uchar *)net_rx_packets[0]; + return ethdev->rx_req->length; + } else { + error("dev->rx_req invalid"); + return -EFAULT; + } + } + + return -EAGAIN; +} + +static int usb_eth_free_pkt(struct udevice *dev, uchar *packet, + int length) +{ + struct ether_priv *priv = dev_get_priv(dev); + struct eth_dev *ethdev = &priv->ethdev; + + packet_received = 0; + + return rx_submit(ethdev, ethdev->rx_req, 0); +} + +static void usb_eth_stop(struct udevice *dev) +{ + struct ether_priv *priv = dev_get_priv(dev); + + _usb_eth_halt(priv); +} + +static int usb_eth_probe(struct udevice *dev) +{ + struct ether_priv *priv = dev_get_priv(dev); + struct eth_pdata *pdata = dev_get_platdata(dev); + + priv->netdev = dev; + l_priv = priv; + + get_ether_addr(CONFIG_USBNET_DEVADDR, pdata->enetaddr); + eth_setenv_enetaddr("usbnet_devaddr", pdata->enetaddr); + + return 0; +} + +static const struct eth_ops usb_eth_ops = { + .start = usb_eth_start, + .send = usb_eth_send, + .recv = usb_eth_recv, + .free_pkt = usb_eth_free_pkt, + .stop = usb_eth_stop, +}; + +int usb_ether_init(void) +{ + struct udevice *dev; + struct udevice *usb_dev; + int ret; + + ret = uclass_first_device(UCLASS_USB_DEV_GENERIC, &usb_dev); + if (!usb_dev || ret) { + error("No USB device found\n"); + return ret; + } + + ret = device_bind_driver(usb_dev, "usb_ether", "usb_ether", &dev); + if (!dev || ret) { + error("usb - not able to bind usb_ether device\n"); + return ret; + } + + return 0; +} + +U_BOOT_DRIVER(eth_usb) = { + .name = "usb_ether", + .id = UCLASS_ETH, + .probe = usb_eth_probe, + .ops = &usb_eth_ops, + .priv_auto_alloc_size = sizeof(struct ether_priv), + .platdata_auto_alloc_size = sizeof(struct eth_pdata), + .flags = DM_FLAG_ALLOC_PRIV_DMA, +}; +#endif /* CONFIG_DM_ETH */