Merge git://www.denx.de/git/u-boot-marvell
[oweals/u-boot.git] / drivers / usb / gadget / ether.c
index d975fb680e3ce11d62b807ee845c1427887d9751..cfe9a24e24fbb8584bdb24887794bf7361b1bb20 100644 (file)
@@ -5,30 +5,20 @@
  * Copyright (C) 2003-2004 Robert Schwebel, Benedikt Spranger
  * Copyright (C) 2008 Nokia Corporation
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * SPDX-License-Identifier:    GPL-2.0+
  */
 
 #include <common.h>
+#include <console.h>
 #include <asm/errno.h>
 #include <linux/netdevice.h>
 #include <linux/usb/ch9.h>
-#include <usbdescriptors.h>
 #include <linux/usb/cdc.h>
 #include <linux/usb/gadget.h>
 #include <net.h>
+#include <usb.h>
 #include <malloc.h>
+#include <memalign.h>
 #include <linux/ctype.h>
 
 #include "gadget_chips.h"
 
 #define atomic_read
 extern struct platform_data brd;
-#define spin_lock(x)
-#define spin_unlock(x)
 
 
 unsigned packet_received, packet_sent;
 
-#define DEV_CONFIG_CDC 1
-#define GFP_ATOMIC ((gfp_t) 0)
-#define GFP_KERNEL ((gfp_t) 0)
-
 /*
  * Ethernet gadget driver -- with CDC and non-CDC options
  * Builds on hardware support for a full duplex link.
@@ -87,7 +71,6 @@ unsigned packet_received, packet_sent;
 #define ETH_ZLEN       60              /* Min. octets in frame sans FCS */
 #define ETH_DATA_LEN   1500            /* Max. octets in payload        */
 #define ETH_FRAME_LEN  PKTSIZE_ALIGN   /* Max. octets in frame sans FCS */
-#define ETH_FCS_LEN    4               /* Octets in the FCS             */
 
 #define DRIVER_DESC            "Ethernet Gadget"
 /* Based on linux 2.6.27 version */
@@ -160,9 +143,9 @@ static struct usb_gadget_driver eth_driver;
 /* "main" config is either CDC, or its simple subset */
 static inline int is_cdc(struct eth_dev *dev)
 {
-#if    !defined(DEV_CONFIG_SUBSET)
+#if    !defined(CONFIG_USB_ETH_SUBSET)
        return 1;               /* only cdc possible */
-#elif  !defined(DEV_CONFIG_CDC)
+#elif  !defined(CONFIG_USB_ETH_CDC)
        return 0;               /* only subset possible */
 #else
        return dev->cdc;        /* depends on what hardware we found */
@@ -406,7 +389,7 @@ rndis_config = {
  * get those drivers from MCCI, or bundled with various products.
  */
 
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
 static struct usb_interface_descriptor
 control_intf = {
        .bLength =              sizeof control_intf,
@@ -445,7 +428,7 @@ static const struct usb_cdc_header_desc header_desc = {
        .bcdCDC =               __constant_cpu_to_le16(0x0110),
 };
 
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 
 static const struct usb_cdc_union_desc union_desc = {
        .bLength =              sizeof union_desc,
@@ -479,7 +462,7 @@ static const struct usb_cdc_acm_descriptor acm_descriptor = {
 
 #endif
 
-#ifndef DEV_CONFIG_CDC
+#ifndef CONFIG_USB_ETH_CDC
 
 /*
  * "SAFE" loosely follows CDC WMC MDLM, violating the spec in various
@@ -529,7 +512,7 @@ static const struct usb_cdc_ether_desc ether_desc = {
        .bNumberPowerFilters =  0,
 };
 
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 
 /*
  * include the status endpoint if we can, even where it's optional.
@@ -561,7 +544,7 @@ fs_status_desc = {
 };
 #endif
 
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
 
 /* the default data interface has no endpoints ... */
 
@@ -616,7 +599,7 @@ rndis_data_intf = {
 
 #endif
 
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
 
 /*
  * "Simple" CDC-subset option is a simple vendor-neutral model that most
@@ -649,6 +632,7 @@ fs_source_desc = {
 
        .bEndpointAddress =     USB_DIR_IN,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       __constant_cpu_to_le16(64),
 };
 
 static struct usb_endpoint_descriptor
@@ -658,11 +642,12 @@ fs_sink_desc = {
 
        .bEndpointAddress =     USB_DIR_OUT,
        .bmAttributes =         USB_ENDPOINT_XFER_BULK,
+       .wMaxPacketSize =       __constant_cpu_to_le16(64),
 };
 
 static const struct usb_descriptor_header *fs_eth_function[11] = {
        (struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
        /* "cdc" mode descriptors */
        (struct usb_descriptor_header *) &control_intf,
        (struct usb_descriptor_header *) &header_desc,
@@ -676,12 +661,12 @@ static const struct usb_descriptor_header *fs_eth_function[11] = {
        (struct usb_descriptor_header *) &fs_source_desc,
        (struct usb_descriptor_header *) &fs_sink_desc,
        NULL,
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
 };
 
 static inline void fs_subset_descriptors(void)
 {
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
        /* behavior is "CDC Subset"; extra descriptors say "SAFE" */
        fs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
        fs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
@@ -719,7 +704,7 @@ static const struct usb_descriptor_header *fs_rndis_function[] = {
  * descriptors, unless they only run at full speed.
  */
 
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
 static struct usb_endpoint_descriptor
 hs_status_desc = {
        .bLength =              USB_DT_ENDPOINT_SIZE,
@@ -729,7 +714,7 @@ hs_status_desc = {
        .wMaxPacketSize =       __constant_cpu_to_le16(STATUS_BYTECOUNT),
        .bInterval =            LOG2_STATUS_INTERVAL_MSEC + 4,
 };
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
 
 static struct usb_endpoint_descriptor
 hs_source_desc = {
@@ -762,7 +747,7 @@ dev_qualifier = {
 
 static const struct usb_descriptor_header *hs_eth_function[11] = {
        (struct usb_descriptor_header *) &otg_descriptor,
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
        /* "cdc" mode descriptors */
        (struct usb_descriptor_header *) &control_intf,
        (struct usb_descriptor_header *) &header_desc,
@@ -776,12 +761,12 @@ static const struct usb_descriptor_header *hs_eth_function[11] = {
        (struct usb_descriptor_header *) &hs_source_desc,
        (struct usb_descriptor_header *) &hs_sink_desc,
        NULL,
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
 };
 
 static inline void hs_subset_descriptors(void)
 {
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
        /* behavior is "CDC Subset"; extra descriptors say "SAFE" */
        hs_eth_function[1] = (struct usb_descriptor_header *) &subset_data_intf;
        hs_eth_function[2] = (struct usb_descriptor_header *) &header_desc;
@@ -843,11 +828,11 @@ static struct usb_string          strings[] = {
        { STRING_SERIALNUMBER,  serial_number, },
        { STRING_DATA,          "Ethernet Data", },
        { STRING_ETHADDR,       ethaddr, },
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
        { STRING_CDC,           "CDC Ethernet", },
        { STRING_CONTROL,       "CDC Communications Control", },
 #endif
-#ifdef DEV_CONFIG_SUBSET
+#ifdef CONFIG_USB_ETH_SUBSET
        { STRING_SUBSET,        "CDC Ethernet Subset", },
 #endif
 #ifdef CONFIG_USB_ETH_RNDIS
@@ -863,32 +848,11 @@ static struct usb_gadget_strings  stringtab = {
 };
 
 /*============================================================================*/
-static u8 control_req[USB_BUFSIZ];
-static u8 status_req[STATUS_BYTECOUNT] __attribute__ ((aligned(4)));
-
-
-/**
- * strlcpy - Copy a %NUL terminated string into a sized buffer
- * @dest: Where to copy the string to
- * @src: Where to copy the string from
- * @size: size of destination buffer
- *
- * Compatible with *BSD: the result is always a valid
- * NUL-terminated string that fits in the buffer (unless,
- * of course, the buffer size is zero). It does not pad
- * out the result like strncpy() does.
- */
-size_t strlcpy(char *dest, const char *src, size_t size)
-{
-       size_t ret = strlen(src);
+DEFINE_CACHE_ALIGN_BUFFER(u8, control_req, USB_BUFSIZ);
 
-       if (size) {
-               size_t len = (ret >= size) ? size - 1 : ret;
-               memcpy(dest, src, len);
-               dest[len] = '\0';
-       }
-       return ret;
-}
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+DEFINE_CACHE_ALIGN_BUFFER(u8, status_req, STATUS_BYTECOUNT);
+#endif
 
 /*============================================================================*/
 
@@ -951,7 +915,7 @@ set_ether_config(struct eth_dev *dev, gfp_t gfp_flags)
        int                                     result = 0;
        struct usb_gadget                       *gadget = dev->gadget;
 
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
        /* status endpoint used for RNDIS and (optionally) CDC */
        if (!subset_active(dev) && dev->status_ep) {
                dev->status = ep_desc(gadget, &hs_status_desc,
@@ -1132,7 +1096,7 @@ static int eth_set_config(struct eth_dev *dev, unsigned number,
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
 
 /*
  * The interrupt endpoint is used in CDC networking models (Ethernet, ATM)
@@ -1287,6 +1251,7 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                switch (wValue >> 8) {
 
                case USB_DT_DEVICE:
+                       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
                        value = min(wLength, (u16) sizeof device_desc);
                        memcpy(req->buf, &device_desc, value);
                        break;
@@ -1352,10 +1317,18 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                if (gadget_is_pxa(gadget)) {
                        value = eth_set_config(dev, DEV_CONFIG_VALUE,
                                                GFP_ATOMIC);
+                       /*
+                        * PXA25x driver use non-CDC ethernet gadget.
+                        * But only _CDC and _RNDIS code can signalize
+                        * that network is working. So we signalize it
+                        * here.
+                        */
+                       l_ethdev.network_started = 1;
+                       debug("USB network up!\n");
                        goto done_set_intf;
                }
 
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
                switch (wIndex) {
                case 0:         /* control/master intf */
                        if (wValue != 0)
@@ -1397,7 +1370,7 @@ eth_setup(struct usb_gadget *gadget, const struct usb_ctrlrequest *ctrl)
                 * all non-PXA hardware talks real CDC ...
                 */
                debug("set_interface ignored!\n");
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
 
 done_set_intf:
                break;
@@ -1420,7 +1393,7 @@ done_set_intf:
                value = min(wLength, (u16) 1);
                break;
 
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
        case USB_CDC_SET_ETHERNET_PACKET_FILTER:
                /*
                 * see 6.2.30: no data, wIndex = interface,
@@ -1444,7 +1417,7 @@ done_set_intf:
         * case USB_CDC_GET_ETHERNET_STATISTIC:
         */
 
-#endif /* DEV_CONFIG_CDC */
+#endif /* CONFIG_USB_ETH_CDC */
 
 #ifdef CONFIG_USB_ETH_RNDIS
        /*
@@ -1537,6 +1510,8 @@ static int rx_submit(struct eth_dev *dev, struct usb_request *req,
         */
 
        debug("%s\n", __func__);
+       if (!req)
+               return -EINVAL;
 
        size = (ETHER_HDR_SIZE + dev->mtu + RX_EXTRA);
        size += dev->out_ep->maxpacket - 1;
@@ -1550,7 +1525,7 @@ static int rx_submit(struct eth_dev *dev, struct usb_request *req,
         * RNDIS headers involve variable numbers of LE32 values.
         */
 
-       req->buf = (u8 *) NetRxPackets[0];
+       req->buf = (u8 *)net_rx_packets[0];
        req->length = size;
        req->complete = rx_complete;
 
@@ -1673,13 +1648,13 @@ static int eth_start_xmit (struct sk_buff *skb, struct net_device *net)
        if (!eth_is_promisc (dev)) {
                u8              *dest = skb->data;
 
-               if (is_multicast_ether_addr(dest)) {
+               if (is_multicast_ethaddr(dest)) {
                        u16     type;
 
                        /* ignores USB_CDC_PACKET_TYPE_MULTICAST and host
                         * SET_ETHERNET_MULTICAST_FILTERS requests
                         */
-                       if (is_broadcast_ether_addr(dest))
+                       if (is_broadcast_ethaddr(dest))
                                type = USB_CDC_PACKET_TYPE_BROADCAST;
                        else
                                type = USB_CDC_PACKET_TYPE_ALL_MULTICAST;
@@ -1935,7 +1910,7 @@ static int eth_stop(struct eth_dev *dev)
                /* Wait until host receives OID_GEN_MEDIA_CONNECT_STATUS */
                ts = get_timer(0);
                while (get_timer(ts) < timeout)
-                       usb_gadget_handle_interrupts();
+                       usb_gadget_handle_interrupts(0);
 #endif
 
                rndis_uninit(dev->rndis_config);
@@ -1969,8 +1944,8 @@ static int is_eth_addr_valid(char *str)
                        p = q;
                }
 
-               if (i == 6) /* it looks ok */
-                       return 1;
+               /* Now check the contents. */
+               return is_valid_ethaddr(ea);
        }
        return 0;
 }
@@ -1999,7 +1974,7 @@ static int get_ether_addr(const char *str, u8 *dev_addr)
                        num |= (nibble(*str++));
                        dev_addr[i] = num;
                }
-               if (is_valid_ether_addr(dev_addr))
+               if (is_valid_ethaddr(dev_addr))
                        return 0;
        }
        return 1;
@@ -2015,7 +1990,7 @@ static int eth_bind(struct usb_gadget *gadget)
        u8                      tmp[7];
 
        /* these flags are only ever cleared; compiler take note */
-#ifndef        DEV_CONFIG_CDC
+#ifndef        CONFIG_USB_ETH_CDC
        cdc = 0;
 #endif
 #ifndef        CONFIG_USB_ETH_RNDIS
@@ -2127,7 +2102,7 @@ autoconf_fail:
                goto autoconf_fail;
        out_ep->driver_data = out_ep;   /* claim */
 
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
        /*
         * CDC Ethernet control interface doesn't require a status endpoint.
         * Since some hosts expect one, try to allocate one anyway.
@@ -2139,7 +2114,7 @@ autoconf_fail:
                } else if (rndis) {
                        error("can't run RNDIS on %s", gadget->name);
                        return -ENODEV;
-#ifdef DEV_CONFIG_CDC
+#ifdef CONFIG_USB_ETH_CDC
                } else if (cdc) {
                        control_intf.bNumEndpoints = 0;
                        /* FIXME remove endpoint from descriptor list */
@@ -2161,7 +2136,6 @@ autoconf_fail:
                hs_subset_descriptors();
        }
 
-       device_desc.bMaxPacketSize0 = gadget->ep0->maxpacket;
        usb_gadget_set_selfpowered(gadget);
 
        /* For now RNDIS is always a second config */
@@ -2182,7 +2156,7 @@ autoconf_fail:
                                fs_source_desc.bEndpointAddress;
                hs_sink_desc.bEndpointAddress =
                                fs_sink_desc.bEndpointAddress;
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
                if (status_ep)
                        hs_status_desc.bEndpointAddress =
                                        fs_status_desc.bEndpointAddress;
@@ -2251,7 +2225,7 @@ autoconf_fail:
        dev->req->complete = eth_setup_complete;
 
        /* ... and maybe likewise for status transfer */
-#if defined(DEV_CONFIG_CDC) || defined(CONFIG_USB_ETH_RNDIS)
+#if defined(CONFIG_USB_ETH_CDC) || defined(CONFIG_USB_ETH_RNDIS)
        if (dev->status_ep) {
                dev->stat_req = usb_ep_alloc_request(dev->status_ep,
                                                        GFP_KERNEL);
@@ -2341,6 +2315,8 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
                goto fail;
        }
 
+       board_usb_init(0, USB_INIT_DEVICE);
+
        /* Configure default mac-addresses for the USB ethernet device */
 #ifdef CONFIG_USBNET_DEV_ADDR
        strlcpy(dev_addr, CONFIG_USBNET_DEV_ADDR, sizeof(dev_addr));
@@ -2387,7 +2363,7 @@ static int usb_eth_init(struct eth_device *netdev, bd_t *bd)
                        error("The remote end did not respond in time.");
                        goto fail;
                }
-               usb_gadget_handle_interrupts();
+               usb_gadget_handle_interrupts(0);
        }
 
        packet_received = 0;
@@ -2455,7 +2431,7 @@ static int usb_eth_send(struct eth_device *netdev, void *packet, int length)
                        printf("timeout sending packets to usb ethernet\n");
                        return -1;
                }
-               usb_gadget_handle_interrupts();
+               usb_gadget_handle_interrupts(0);
        }
        if (rndis_pkt)
                free(rndis_pkt);
@@ -2470,12 +2446,13 @@ static int usb_eth_recv(struct eth_device *netdev)
 {
        struct eth_dev *dev = &l_ethdev;
 
-       usb_gadget_handle_interrupts();
+       usb_gadget_handle_interrupts(0);
 
        if (packet_received) {
                debug("%s: packet received\n", __func__);
                if (dev->rx_req) {
-                       NetReceive(NetRxPackets[0], dev->rx_req->length);
+                       net_process_received_packet(net_rx_packets[0],
+                                                   dev->rx_req->length);
                        packet_received = 0;
 
                        rx_submit(dev, dev->rx_req, 0);
@@ -2515,11 +2492,12 @@ void usb_eth_halt(struct eth_device *netdev)
 
        /* Clear pending interrupt */
        if (dev->network_started) {
-               usb_gadget_handle_interrupts();
+               usb_gadget_handle_interrupts(0);
                dev->network_started = 0;
        }
 
        usb_gadget_unregister_driver(&eth_driver);
+       board_usb_cleanup(0, USB_INIT_DEVICE);
 }
 
 static struct usb_gadget_driver eth_driver = {
@@ -2529,6 +2507,7 @@ static struct usb_gadget_driver eth_driver = {
        .unbind         = eth_unbind,
 
        .setup          = eth_setup,
+       .reset          = eth_disconnect,
        .disconnect     = eth_disconnect,
 
        .suspend        = eth_suspend,