vserver 2.0 rc7
[linux-2.6.git] / drivers / usb / gadget / net2280.c
index 2ae8309..e5457f2 100644 (file)
@@ -1,19 +1,16 @@
 /*
- * 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
  *
- * Used with a gadget driver like "zero.c" this enumerates fine to Windows
- * or Linux hosts; handles disconnect, reconnect, and reset, for full or
- * high speed operation; and passes USB-IF "chapter 9" tests.
- *
- * Handles standard stress loads from the Linux "usbtest" driver, with
- * either DMA (default) or PIO (use_dma=n) used for ep-{a,b,c,d}.  Testing
- * with "ttcp" (and the "ether.c" driver) behaves nicely too.
+ * This driver should work well with most "gadget" drivers, including
+ * the File Storage, Serial, and Ethernet/RNDIS gadget drivers
+ * as well as Gadget Zero and Gadgetfs.
  *
  * DMA is enabled by default.  Drivers using transfer queues might use
  * DMA chaining to remove IRQ latencies between transfers.  (Except when
@@ -27,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
 #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";
@@ -118,10 +114,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) {
@@ -182,7 +188,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
        if (ep->dma && (max % 4) != 0 && use_dma_chaining) {
                DEBUG (ep->dev, "%s, no dma for maxpacket %d\n",
                        ep->ep.name, ep->ep.maxpacket);
-               ep->dma = 0;
+               ep->dma = NULL;
        }
 
        /* set type, direction, address; reset fifo counters */
@@ -257,7 +263,7 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
        return 0;
 }
 
-static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
+static int handshake (u32 __iomem *ptr, u32 mask, u32 done, int usec)
 {
        u32     result;
 
@@ -276,11 +282,11 @@ static int handshake (u32 *ptr, u32 mask, u32 done, int usec)
 
 static struct usb_ep_ops net2280_ep_ops;
 
-static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
+static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
 {
        u32             tmp;
 
-       ep->desc = 0;
+       ep->desc = NULL;
        INIT_LIST_HEAD (&ep->queue);
 
        ep->ep.maxpacket = ~0;
@@ -307,14 +313,16 @@ static void ep_reset (struct net2280_regs *regs, struct net2280_ep *ep)
        /* init to our chosen defaults, notably so that we NAK OUT
         * packets until the driver queues a read (+note erratum 0112)
         */
-       writel (  (1 << SET_NAK_OUT_PACKETS_MODE)
+       tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
                | (1 << SET_NAK_OUT_PACKETS)
                | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
-               | (1 << CLEAR_INTERRUPT_MODE)
-               | (1 << CLEAR_CONTROL_STATUS_PHASE_HANDSHAKE)
-               | (1 << CLEAR_ENDPOINT_TOGGLE)
-               | (1 << CLEAR_ENDPOINT_HALT)
-               , &ep->regs->ep_rsp);
+               | (1 << CLEAR_INTERRUPT_MODE);
+
+       if (ep->num != 0) {
+               tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
+                       | (1 << CLEAR_ENDPOINT_HALT);
+       }
+       writel (tmp, &ep->regs->ep_rsp);
 
        /* scrub most status bits, and flush any fifo state */
        writel (  (1 << TIMEOUT)
@@ -374,12 +382,12 @@ net2280_alloc_request (struct usb_ep *_ep, int gfp_flags)
        struct net2280_request  *req;
 
        if (!_ep)
-               return 0;
+               return NULL;
        ep = container_of (_ep, struct net2280_ep, ep);
 
        req = kmalloc (sizeof *req, gfp_flags);
        if (!req)
-               return 0;
+               return NULL;
 
        memset (req, 0, sizeof *req);
        req->req.dma = DMA_ADDR_INVALID;
@@ -393,7 +401,7 @@ net2280_alloc_request (struct usb_ep *_ep, int gfp_flags)
                                &req->td_dma);
                if (!td) {
                        kfree (req);
-                       return 0;
+                       return NULL;
                }
                td->dmacount = 0;       /* not VALID */
                td->dmaaddr = __constant_cpu_to_le32 (DMA_ADDR_INVALID);
@@ -463,7 +471,7 @@ net2280_alloc_buffer (
 
        ep = container_of (_ep, struct net2280_ep, ep);
        if (!_ep)
-               return 0;
+               return NULL;
        *dma = DMA_ADDR_INVALID;
 
 #if    defined(USE_KMALLOC)
@@ -517,7 +525,7 @@ net2280_free_buffer (
 static void
 write_fifo (struct net2280_ep *ep, struct usb_request *req)
 {
-       struct net2280_ep_regs  *regs = ep->regs;
+       struct net2280_ep_regs  __iomem *regs = ep->regs;
        u8                      *buf;
        u32                     tmp;
        unsigned                count, total;
@@ -530,7 +538,7 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req)
                total = req->length - req->actual;
        } else {
                total = 0;
-               buf = 0;
+               buf = NULL;
        }
 
        /* write just one packet at a time */
@@ -577,7 +585,8 @@ write_fifo (struct net2280_ep *ep, struct usb_request *req)
  */
 static void out_flush (struct net2280_ep *ep)
 {
-       u32     *statp, tmp;
+       u32     __iomem *statp;
+       u32     tmp;
 
        ASSERT_OUT_NAKING (ep);
 
@@ -610,7 +619,7 @@ static void out_flush (struct net2280_ep *ep)
 static int
 read_fifo (struct net2280_ep *ep, struct net2280_request *req)
 {
-       struct net2280_ep_regs  *regs = ep->regs;
+       struct net2280_ep_regs  __iomem *regs = ep->regs;
        u8                      *buf = req->req.buf + req->req.actual;
        unsigned                count, tmp, is_short;
        unsigned                cleanup = 0, prevent = 0;
@@ -678,7 +687,7 @@ read_fifo (struct net2280_ep *ep, struct net2280_request *req)
        }
        if (count) {
                tmp = readl (&regs->ep_data);
-               cpu_to_le32s (&tmp);
+               /* LE conversion is implicit here: */
                do {
                        *buf++ = (u8) tmp;
                        tmp >>= 8;
@@ -719,7 +728,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 ();
@@ -737,12 +746,12 @@ static const u32 dmactl_default =
                /* erratum 0116 workaround part 2 (no AUTOSTART) */
                | (1 << DMA_ENABLE);
 
-static inline void spin_stop_dma (struct net2280_dma_regs *dma)
+static inline void spin_stop_dma (struct net2280_dma_regs __iomem *dma)
 {
        handshake (&dma->dmactl, (1 << DMA_ENABLE), 0, 50);
 }
 
-static inline void stop_dma (struct net2280_dma_regs *dma)
+static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
 {
        writel (readl (&dma->dmactl) & ~(1 << DMA_ENABLE), &dma->dmactl);
        spin_stop_dma (dma);
@@ -750,7 +759,7 @@ static inline void stop_dma (struct net2280_dma_regs *dma)
 
 static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 {
-       struct net2280_dma_regs *dma = ep->dma;
+       struct net2280_dma_regs __iomem *dma = ep->dma;
 
        writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
                        &dma->dmacount);
@@ -771,7 +780,7 @@ static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 static void start_dma (struct net2280_ep *ep, struct net2280_request *req)
 {
        u32                     tmp;
-       struct net2280_dma_regs *dma = ep->dma;
+       struct net2280_dma_regs __iomem *dma = ep->dma;
 
        /* FIXME can't use DMA for ZLPs */
 
@@ -966,7 +975,7 @@ net2280_queue (struct usb_ep *_ep, struct usb_request *_req, int gfp_flags)
                                                if (ep->num == 0)
                                                        allow_status (ep);
                                                /* don't queue it */
-                                               req = 0;
+                                               req = NULL;
                                        } else
                                                s = readl (&ep->regs->ep_stat);
                                }
@@ -1095,7 +1104,7 @@ static void restart_dma (struct net2280_ep *ep)
         *  OUT:  was "usb-short", we must restart.
         */
        if (ep->is_in && !req->valid) {
-               struct net2280_request  *entry, *prev = 0;
+               struct net2280_request  *entry, *prev = NULL;
                int                     reqmode, done = 0;
 
                DEBUG (ep->dev, "%s dma hiccup td %p\n", ep->ep.name, req->td);
@@ -1220,7 +1229,7 @@ static int net2280_dequeue (struct usb_ep *_ep, struct usb_request *_req)
                        DEBUG (ep->dev, "unlink (%s) pio\n", _ep->name);
                        done (ep, req, -ECONNRESET);
                }
-               req = 0;
+               req = NULL;
 
        /* patch up hardware chaining data */
        } else if (ep->dma && use_dma_chaining) {
@@ -1261,7 +1270,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;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1419,15 +1428,44 @@ static int net2280_set_selfpowered (struct usb_gadget *_gadget, int value)
        return 0;
 }
 
+static int net2280_pullup(struct usb_gadget *_gadget, int is_on)
+{
+       struct net2280  *dev;
+       u32             tmp;
+       unsigned long   flags;
+
+       if (!_gadget)
+               return -ENODEV;
+       dev = container_of (_gadget, struct net2280, gadget);
+
+       spin_lock_irqsave (&dev->lock, flags);
+       tmp = readl (&dev->usb->usbctl);
+       dev->softconnect = (is_on != 0);
+       if (is_on)
+               tmp |= (1 << USB_DETECT_ENABLE);
+       else
+               tmp &= ~(1 << USB_DETECT_ENABLE);
+       writel (tmp, &dev->usb->usbctl);
+       spin_unlock_irqrestore (&dev->lock, flags);
+
+       return 0;
+}
+
 static const struct usb_gadget_ops net2280_ops = {
        .get_frame      = net2280_get_frame,
        .wakeup         = net2280_wakeup,
        .set_selfpowered = net2280_set_selfpowered,
+       .pullup         = net2280_pullup,
 };
 
 /*-------------------------------------------------------------------------*/
 
-#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
@@ -1680,8 +1718,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;
@@ -1807,8 +1847,6 @@ static void usb_reset (struct net2280 *dev)
 {
        u32     tmp;
 
-       /* force immediate bus disconnect, and synch through pci */
-       writel (0, &dev->usb->usbctl);
        dev->gadget.speed = USB_SPEED_UNKNOWN;
        (void) readl (&dev->usb->usbctl);
 
@@ -1903,7 +1941,7 @@ static void ep0_start (struct net2280 *dev)
        writel (  (1 << USB_ROOT_PORT_WAKEUP_ENABLE)
                | (1 << SELF_POWERED_USB_DEVICE)
                | (1 << REMOTE_WAKEUP_SUPPORT)
-               | (1 << USB_DETECT_ENABLE)
+               | (dev->softconnect << USB_DETECT_ENABLE)
                | (1 << SELF_POWERED_STATUS)
                , &dev->usb->usbctl);
 
@@ -1917,6 +1955,7 @@ static void ep0_start (struct net2280 *dev)
                | (1 << PCI_RETRY_ABORT_INTERRUPT_ENABLE)
                | (1 << VBUS_INTERRUPT_ENABLE)
                | (1 << ROOT_PORT_RESET_INTERRUPT_ENABLE)
+               | (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT_ENABLE)
                , &dev->regs->pciirqenb1);
 
        /* don't leave any writes posted */
@@ -1954,15 +1993,16 @@ int usb_gadget_register_driver (struct usb_gadget_driver *driver)
                dev->ep [i].irqs = 0;
 
        /* hook up the driver ... */
-       driver->driver.bus = 0;
+       dev->softconnect = 1;
+       driver->driver.bus = NULL;
        dev->driver = driver;
        dev->gadget.dev.driver = &driver->driver;
        retval = driver->bind (&dev->gadget);
        if (retval) {
                DEBUG (dev, "bind to driver %s --> %d\n",
                                driver->driver.name, retval);
-               dev->driver = 0;
-               dev->gadget.dev.driver = 0;
+               dev->driver = NULL;
+               dev->gadget.dev.driver = NULL;
                return retval;
        }
 
@@ -1992,7 +2032,7 @@ stop_activity (struct net2280 *dev, struct usb_gadget_driver *driver)
 
        /* don't disconnect if it's not connected */
        if (dev->gadget.speed == USB_SPEED_UNKNOWN)
-               driver = 0;
+               driver = NULL;
 
        /* stop hardware; prevent new request submissions;
         * and kill any outstanding requests.
@@ -2025,9 +2065,11 @@ int usb_gadget_unregister_driver (struct usb_gadget_driver *driver)
        stop_activity (dev, driver);
        spin_unlock_irqrestore (&dev->lock, flags);
 
+       net2280_pullup (&dev->gadget, 0);
+
        driver->unbind (&dev->gadget);
-       dev->gadget.dev.driver = 0;
-       dev->driver = 0;
+       dev->gadget.dev.driver = NULL;
+       dev->driver = NULL;
 
        net2280_led_active (dev, 0);
        device_remove_file (&dev->pdev->dev, &dev_attr_function);
@@ -2056,7 +2098,7 @@ static void handle_ep_small (struct net2280_ep *ep)
                req = list_entry (ep->queue.next,
                        struct net2280_request, queue);
        else
-               req = 0;
+               req = NULL;
 
        /* ack all, and handle what we care about */
        t = readl (&ep->regs->ep_stat);
@@ -2095,7 +2137,7 @@ static void handle_ep_small (struct net2280_ep *ep)
                                        set_halt (ep);
                                        mode = 2;
                                } else if (!req && ep->stopped)
-                                       write_fifo (ep, 0);
+                                       write_fifo (ep, NULL);
                        }
                } else {
                        /* status; stop NAKing */
@@ -2115,7 +2157,7 @@ static void handle_ep_small (struct net2280_ep *ep)
                                ep->stopped = 1;
                                if (req)
                                        done (ep, req, -EOVERFLOW);
-                               req = 0;
+                               req = NULL;
                        }
                }
        }
@@ -2142,7 +2184,7 @@ static void handle_ep_small (struct net2280_ep *ep)
                                scan_dma_completions (ep);
                                if (unlikely (list_empty (&ep->queue)
                                                || ep->out_overflow)) {
-                                       req = 0;
+                                       req = NULL;
                                        break;
                                }
                                req = list_entry (ep->queue.next,
@@ -2156,7 +2198,7 @@ static void handle_ep_small (struct net2280_ep *ep)
                                        count &= DMA_BYTE_COUNT_MASK;
                                        if (readl (&ep->dma->dmadesc)
                                                        != req->td_dma)
-                                               req = 0;
+                                               req = NULL;
                                        break;
                                }
                                udelay(1);
@@ -2209,7 +2251,7 @@ static void handle_ep_small (struct net2280_ep *ep)
                        if (ep->num == 0) {
                                /* wait for control status */
                                if (mode != 2)
-                                       req = 0;
+                                       req = NULL;
                        } else if (!req->req.zero || len != ep->ep.maxpacket)
                                mode = 2;
                }
@@ -2231,13 +2273,13 @@ static void handle_ep_small (struct net2280_ep *ep)
                         */
                        if (!ep->stopped)
                                allow_status (ep);
-                       req = 0;
+                       req = NULL;
                } else {
                        if (!list_empty (&ep->queue) && !ep->stopped)
                                req = list_entry (ep->queue.next,
                                        struct net2280_request, queue);
                        else
-                               req = 0;
+                               req = NULL;
                        if (req && !ep->is_in)
                                stop_out_naking (ep);
                }
@@ -2272,7 +2314,7 @@ get_ep_by_addr (struct net2280 *dev, u16 wIndex)
                if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
                        return ep;
        }
-       return 0;
+       return NULL;
 }
 
 static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
@@ -2489,15 +2531,23 @@ next_endpoints:
 static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 {
        struct net2280_ep       *ep;
-       u32                     tmp, num, scratch;
+       u32                     tmp, num, mask, scratch;
 
        /* after disconnect there's nothing else to do! */
        tmp = (1 << VBUS_INTERRUPT) | (1 << ROOT_PORT_RESET_INTERRUPT);
+       mask = (1 << HIGH_SPEED) | (1 << FULL_SPEED);
+
+       /* VBUS disconnect is indicated by VBUS_PIN and VBUS_INTERRUPT set.
+        * Root Port Reset is indicated by ROOT_PORT_RESET_INTERRRUPT set and
+        * both HIGH_SPEED and FULL_SPEED clear (as ROOT_PORT_RESET_INTERRUPT 
+        * only indicates a change in the reset state).
+        */
        if (stat & tmp) {
                writel (tmp, &dev->regs->irqstat1);
-               if (((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) != 0
-                       || (readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0
-                       ) && dev->gadget.speed != USB_SPEED_UNKNOWN) {
+               if ((((stat & (1 << ROOT_PORT_RESET_INTERRUPT)) && 
+                               ((readl (&dev->usb->usbstat) & mask) == 0))
+                               || ((readl (&dev->usb->usbctl) & (1 << VBUS_PIN)) == 0) 
+                           ) && ( dev->gadget.speed != USB_SPEED_UNKNOWN)) {
                        DEBUG (dev, "disconnect %s\n",
                                        dev->driver->driver.name);
                        stop_activity (dev, dev->driver);
@@ -2513,19 +2563,24 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
                        return;
        }
 
-       /* NOTE: we don't actually suspend the hardware; that starts to
-        * interact with PCI power management, and needs something like a
-        * controller->suspend() call to clear SUSPEND_REQUEST_INTERRUPT.
-        * we shouldn't see resume interrupts.
-        * for rev 0100, this also avoids erratum 0102.
+       /* NOTE: chip stays in PCI D0 state for now, but it could
+        * enter D1 to save more power
         */
        tmp = (1 << SUSPEND_REQUEST_CHANGE_INTERRUPT);
        if (stat & tmp) {
-               if (dev->driver->suspend)
-                       dev->driver->suspend (&dev->gadget);
+               writel (tmp, &dev->regs->irqstat1);
+               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);
+                       /* at high speed, note erratum 0133 */
+               }
                stat &= ~tmp;
        }
-       stat &= ~(1 << SUSPEND_REQUEST_INTERRUPT);
 
        /* clear any other status/irqs */
        if (stat)
@@ -2533,6 +2588,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
 
        /* some status we can just ignore */
        stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+                       | (1 << SUSPEND_REQUEST_INTERRUPT)
                        | (1 << RESUME_INTERRUPT)
                        | (1 << SOF_INTERRUPT));
        if (!stat)
@@ -2544,7 +2600,7 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
        stat &= ~DMA_INTERRUPTS;
        scratch >>= 9;
        for (num = 0; scratch; num++) {
-               struct net2280_dma_regs *dma;
+               struct net2280_dma_regs __iomem *dma;
 
                tmp = 1 << num;
                if ((tmp & scratch) == 0)
@@ -2698,11 +2754,11 @@ static void net2280_remove (struct pci_dev *pdev)
                pci_disable_device (pdev);
        device_unregister (&dev->gadget.dev);
        device_remove_file (&pdev->dev, &dev_attr_registers);
-       pci_set_drvdata (pdev, 0);
+       pci_set_drvdata (pdev, NULL);
 
        INFO (dev, "unbind\n");
 
-       the_controller = 0;
+       the_controller = NULL;
 }
 
 /* wrap this driver around the specified device, but
@@ -2713,7 +2769,7 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
 {
        struct net2280          *dev;
        unsigned long           resource, len;
-       void                    *base = 0;
+       void                    __iomem *base = NULL;
        int                     retval, i;
        char                    buf [8], *bufp;
 
@@ -2771,14 +2827,15 @@ static int net2280_probe (struct pci_dev *pdev, const struct pci_device_id *id)
                retval = -EFAULT;
                goto done;
        }
-       dev->regs = (struct net2280_regs *) base;
-       dev->usb = (struct net2280_usb_regs *) (base + 0x0080);
-       dev->pci = (struct net2280_pci_regs *) (base + 0x0100);
-       dev->dma = (struct net2280_dma_regs *) (base + 0x0180);
-       dev->dep = (struct net2280_dep_regs *) (base + 0x0200);
-       dev->epregs = (struct net2280_ep_regs *) (base + 0x0300);
+       dev->regs = (struct net2280_regs __iomem *) base;
+       dev->usb = (struct net2280_usb_regs __iomem *) (base + 0x0080);
+       dev->pci = (struct net2280_pci_regs __iomem *) (base + 0x0100);
+       dev->dma = (struct net2280_dma_regs __iomem *) (base + 0x0180);
+       dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
+       dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
 
        /* put into initial config, link up all endpoints */
+       writel (0, &dev->usb->usbctl);
        usb_reset (dev);
        usb_reinit (dev);
 
@@ -2803,6 +2860,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 */,
@@ -2898,7 +2956,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);