linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / usb / gadget / net2280.c
index d28de0b..67b13ab 100644 (file)
@@ -1,8 +1,9 @@
 /*
- * Driver for the NetChip 2280 USB device controller.
- * Specs and errata are available from <http://www.netchip.com>.
+ * Driver for the PLX NET2280 USB device controller.
+ * Specs and errata are available from <http://www.plxtech.com>.
  *
- * NetChip Technology Inc. supported the development of this driver.
+ * PLX Technology Inc. (formerly NetChip Technology) supported the 
+ * development of this driver.
  *
  *
  * CODE STATUS HIGHLIGHTS
@@ -23,7 +24,7 @@
 
 /*
  * Copyright (C) 2003 David Brownell
- * Copyright (C) 2003 NetChip Technologies
+ * Copyright (C) 2003-2005 PLX Technology, Inc.
  *
  * 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
@@ -46,6 +47,7 @@
 #include <linux/config.h>
 #include <linux/module.h>
 #include <linux/pci.h>
+#include <linux/dma-mapping.h>
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/ioport.h>
 #include <asm/unaligned.h>
 
 
-#define        DRIVER_DESC             "NetChip 2280 USB Peripheral Controller"
-#define        DRIVER_VERSION          "2004 Jan 14"
+#define        DRIVER_DESC             "PLX NET2280 USB Peripheral Controller"
+#define        DRIVER_VERSION          "2005 Feb 03"
 
 #define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
 #define        EP_DONTUSE              13      /* nonzero */
 
 #define USE_RDK_LEDS           /* GPIO pins control three LEDs */
-#define USE_SYSFS_DEBUG_FILES
 
 
 static const char driver_name [] = "net2280";
@@ -114,10 +115,20 @@ static ushort fifo_mode = 0;
 /* "modprobe net2280 fifo_mode=1" etc */
 module_param (fifo_mode, ushort, 0644);
 
+/* enable_suspend -- When enabled, the driver will respond to
+ * USB suspend requests by powering down the NET2280.  Otherwise,
+ * USB suspend requests will be ignored.  This is acceptible for
+ * self-powered devices, and helps avoid some quirks.
+ */
+static int enable_suspend = 0;
+
+/* "modprobe net2280 enable_suspend=1" etc */
+module_param (enable_suspend, bool, S_IRUGO);
+
 
 #define        DIR_STRING(bAddress) (((bAddress) & USB_DIR_IN) ? "in" : "out")
 
-#if defined(USE_SYSFS_DEBUG_FILES) || defined (DEBUG)
+#if defined(CONFIG_USB_GADGET_DEBUG_FILES) || defined (DEBUG)
 static char *type_string (u8 bmAttributes)
 {
        switch ((bmAttributes) & USB_ENDPOINT_XFERTYPE_MASK) {
@@ -366,7 +377,7 @@ static int net2280_disable (struct usb_ep *_ep)
 /*-------------------------------------------------------------------------*/
 
 static struct usb_request *
-net2280_alloc_request (struct usb_ep *_ep, int gfp_flags)
+net2280_alloc_request (struct usb_ep *_ep, gfp_t gfp_flags)
 {
        struct net2280_ep       *ep;
        struct net2280_request  *req;
@@ -438,7 +449,7 @@ net2280_free_request (struct usb_ep *_ep, struct usb_request *_req)
 #elif  defined(CONFIG_PPC) && !defined(CONFIG_NOT_COHERENT_CACHE)
 #define USE_KMALLOC
 
-#elif  defined(CONFIG_MIPS) && !defined(CONFIG_NONCOHERENT_IO)
+#elif  defined(CONFIG_MIPS) && !defined(CONFIG_DMA_NONCOHERENT)
 #define USE_KMALLOC
 
 /* FIXME there are other cases, including an x86-64 one ...  */
@@ -453,7 +464,7 @@ net2280_alloc_buffer (
        struct usb_ep           *_ep,
        unsigned                bytes,
        dma_addr_t              *dma,
-       int                     gfp_flags
+       gfp_t                   gfp_flags
 )
 {
        void                    *retval;
@@ -718,7 +729,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
                dmacount |= (1 << DMA_DONE_INTERRUPT_ENABLE);
 
        /* td->dmadesc = previously set by caller */
-       td->dmaaddr = cpu_to_le32p (&req->req.dma);
+       td->dmaaddr = cpu_to_le32 (req->req.dma);
 
        /* 2280 may be polling VALID_BIT through ep->dma->dmadesc */
        wmb ();
@@ -887,7 +898,7 @@ done (struct net2280_ep *ep, struct net2280_request *req, int status)
 /*-------------------------------------------------------------------------*/
 
 static int
-net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
+net2280_queue (struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
 {
        struct net2280_request  *req;
        struct net2280_ep       *ep;
@@ -1103,7 +1114,7 @@ static void restart_dma (struct net2280_ep *ep)
                if (ep->in_fifo_validate)
                        dmactl |= (1 << DMA_FIFO_VALIDATE);
                list_for_each_entry (entry, &ep->queue, queue) {
-                       u32             dmacount;
+                       __le32          dmacount;
 
                        if (entry == req)
                                continue;
@@ -1228,7 +1239,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
                                &ep->dma->dmadesc);
                        if (req->td->dmacount & dma_done_ie)
                                writel (readl (&ep->dma->dmacount)
-                                               | dma_done_ie,
+                                               | le32_to_cpu(dma_done_ie),
                                        &ep->dma->dmacount);
                } else {
                        struct net2280_request  *prev;
@@ -1260,7 +1271,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
        }
 
        spin_unlock_irqrestore (&ep->dev->lock, flags);
-       return req ? 0 : -EOPNOTSUPP;
+       return 0;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1450,11 +1461,16 @@ static const struct usb_gadget_ops net2280_ops = {
 
 /*-------------------------------------------------------------------------*/
 
-#ifdef USE_SYSFS_DEBUG_FILES
+#ifdef CONFIG_USB_GADGET_DEBUG_FILES
+
+/* FIXME move these into procfs, and use seq_file.
+ * Sysfs _still_ doesn't behave for arbitrarily sized files,
+ * and also doesn't help products using this with 2.4 kernels.
+ */
 
 /* "function" sysfs attribute */
 static ssize_t
-show_function (struct device *_dev, char *buf)
+show_function (struct device *_dev, struct device_attribute *attr, char *buf)
 {
        struct net2280  *dev = dev_get_drvdata (_dev);
 
@@ -1467,7 +1483,7 @@ show_function (struct device *_dev, char *buf)
 static DEVICE_ATTR (function, S_IRUGO, show_function, NULL);
 
 static ssize_t
-show_registers (struct device *_dev, char *buf)
+show_registers (struct device *_dev, struct device_attribute *attr, char *buf)
 {
        struct net2280          *dev;
        char                    *next;
@@ -1475,7 +1491,7 @@ show_registers (struct device *_dev, char *buf)
        unsigned long           flags;
        int                     i;
        u32                     t1, t2;
-       char                    *s;
+       const char              *s;
 
        dev = dev_get_drvdata (_dev);
        next = buf;
@@ -1622,7 +1638,7 @@ show_registers (struct device *_dev, char *buf)
 static DEVICE_ATTR (registers, S_IRUGO, show_registers, NULL);
 
 static ssize_t
-show_queues (struct device *_dev, char *buf)
+show_queues (struct device *_dev, struct device_attribute *attr, char *buf)
 {
        struct net2280          *dev;
        char                    *next;
@@ -1703,8 +1719,10 @@ show_queues (struct device *_dev, char *buf)
                                td = req->td;
                                t = scnprintf (next, size, "\t    td %08x "
                                        " count %08x buf %08x desc %08x\n",
-                                       req->td_dma, td->dmacount,
-                                       td->dmaaddr, td->dmadesc);
+                                       (u32) req->td_dma,
+                                       le32_to_cpu (td->dmacount),
+                                       le32_to_cpu (td->dmaaddr),
+                                       le32_to_cpu (td->dmadesc));
                                if (t <= 0 || t > size)
                                        goto done;
                                size -= t;
@@ -1762,6 +1780,9 @@ static void set_fifo_mode (struct net2280 *dev, int mode)
        list_add_tail (&dev->ep [6].ep.ep_list, &dev->gadget.ep_list);
 }
 
+/* just declare this in any driver that really need it */
+extern int net2280_set_fifo_mode (struct usb_gadget *gadget, int mode);
+
 /**
  * net2280_set_fifo_mode - change allocation of fifo buffers
  * @gadget: access to the net2280 device that will be updated
@@ -2365,9 +2386,9 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                cpu_to_le32s (&u.raw [0]);
                cpu_to_le32s (&u.raw [1]);
 
-               le16_to_cpus (&u.r.wValue);
-               le16_to_cpus (&u.r.wIndex);
-               le16_to_cpus (&u.r.wLength);
+#define        w_value         le16_to_cpup (&u.r.wValue)
+#define        w_index         le16_to_cpup (&u.r.wIndex)
+#define        w_length        le16_to_cpup (&u.r.wLength)
 
                /* ack the irq */
                writel (1 << SETUP_PACKET_INTERRUPT, &dev->regs->irqstat0);
@@ -2396,25 +2417,25 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                switch (u.r.bRequest) {
                case USB_REQ_GET_STATUS: {
                        struct net2280_ep       *e;
-                       u16                     status;
+                       __le32                  status;
 
                        /* hw handles device and interface status */
                        if (u.r.bRequestType != (USB_DIR_IN|USB_RECIP_ENDPOINT))
                                goto delegate;
-                       if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0
-                                       || u.r.wLength > 2)
+                       if ((e = get_ep_by_addr (dev, w_index)) == 0
+                                       || w_length > 2)
                                goto do_stall;
 
                        if (readl (&e->regs->ep_rsp)
                                        & (1 << SET_ENDPOINT_HALT))
-                               status = __constant_cpu_to_le16 (1);
+                               status = __constant_cpu_to_le32 (1);
                        else
-                               status = __constant_cpu_to_le16 (0);
+                               status = __constant_cpu_to_le32 (0);
 
                        /* don't bother with a request object! */
                        writel (0, &dev->epregs [0].ep_irqenb);
-                       set_fifo_bytecount (ep, u.r.wLength);
-                       writel (status, &dev->epregs [0].ep_data);
+                       set_fifo_bytecount (ep, w_length);
+                       writel ((__force u32)status, &dev->epregs [0].ep_data);
                        allow_status (ep);
                        VDEBUG (dev, "%s stat %02x\n", ep->ep.name, status);
                        goto next_endpoints;
@@ -2426,10 +2447,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        /* hw handles device features */
                        if (u.r.bRequestType != USB_RECIP_ENDPOINT)
                                goto delegate;
-                       if (u.r.wValue != USB_ENDPOINT_HALT
-                                       || u.r.wLength != 0)
+                       if (w_value != USB_ENDPOINT_HALT
+                                       || w_length != 0)
                                goto do_stall;
-                       if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0)
+                       if ((e = get_ep_by_addr (dev, w_index)) == 0)
                                goto do_stall;
                        clear_halt (e);
                        allow_status (ep);
@@ -2443,10 +2464,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        /* hw handles device features */
                        if (u.r.bRequestType != USB_RECIP_ENDPOINT)
                                goto delegate;
-                       if (u.r.wValue != USB_ENDPOINT_HALT
-                                       || u.r.wLength != 0)
+                       if (w_value != USB_ENDPOINT_HALT
+                                       || w_length != 0)
                                goto do_stall;
-                       if ((e = get_ep_by_addr (dev, u.r.wIndex)) == 0)
+                       if ((e = get_ep_by_addr (dev, w_index)) == 0)
                                goto do_stall;
                        set_halt (e);
                        allow_status (ep);
@@ -2456,10 +2477,10 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        break;
                default:
 delegate:
-                       VDEBUG (dev, "setup %02x.%02x v%04x i%04x "
+                       VDEBUG (dev, "setup %02x.%02x v%04x i%04x l%04x"
                                "ep_cfg %08x\n",
                                u.r.bRequestType, u.r.bRequest,
-                               u.r.wValue, u.r.wIndex,
+                               w_value, w_index, w_length,
                                readl (&ep->regs->ep_cfg));
                        spin_unlock (&dev->lock);
                        tmp = dev->driver->setup (&dev->gadget, &u.r);
@@ -2480,6 +2501,10 @@ do_stall:
                 */
        }
 
+#undef w_value
+#undef w_index
+#undef w_length
+
 next_endpoints:
        /* endpoint data irq ? */
        scratch = stat & 0x7f;
@@ -2555,6 +2580,8 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
                if (stat & (1 << SUSPEND_REQUEST_INTERRUPT)) {
                        if (dev->driver->suspend)
                                dev->driver->suspend (&dev->gadget);
+                       if (!enable_suspend)
+                               stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
                } else {
                        if (dev->driver->resume)
                                dev->driver->resume (&dev->gadget);
@@ -2634,7 +2661,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
                                restart_dma (ep);
                        else if (ep->is_in && use_dma_chaining) {
                                struct net2280_request  *req;
-                               u32                     dmacount;
+                               __le32                  dmacount;
 
                                /* the descriptor at the head of the chain
                                 * may still have VALID_BIT clear; that's
@@ -2841,6 +2868,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
        dev->got_irq = 1;
 
        /* DMA setup */
+       /* NOTE:  we know only the 32 LSBs of dma addresses may be nonzero */
        dev->requests = pci_pool_create ("requests", pdev,
                sizeof (struct net2280_dma),
                0 /* no alignment requirements */,
@@ -2936,7 +2964,7 @@ static int __init init (void)
 {
        if (!use_dma)
                use_dma_chaining = 0;
-       return pci_module_init (&net2280_pci_driver);
+       return pci_register_driver (&net2280_pci_driver);
 }
 module_init (init);