/*
- * 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
/*
* 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 <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";
/* "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) {
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 */
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;
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;
/* 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)
/*-------------------------------------------------------------------------*/
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;
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;
&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);
#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 ... */
struct usb_ep *_ep,
unsigned bytes,
dma_addr_t *dma,
- int gfp_flags
+ gfp_t gfp_flags
)
{
void *retval;
ep = container_of (_ep, struct net2280_ep, ep);
if (!_ep)
- return 0;
+ return NULL;
*dma = DMA_ADDR_INVALID;
#if defined(USE_KMALLOC)
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;
total = req->length - req->actual;
} else {
total = 0;
- buf = 0;
+ buf = NULL;
}
/* write just one packet at a time */
*/
static void out_flush (struct net2280_ep *ep)
{
- u32 *statp, tmp;
+ u32 __iomem *statp;
+ u32 tmp;
ASSERT_OUT_NAKING (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;
}
if (count) {
tmp = readl (®s->ep_data);
- cpu_to_le32s (&tmp);
+ /* LE conversion is implicit here: */
do {
*buf++ = (u8) tmp;
tmp >>= 8;
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 ();
/* 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);
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);
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 */
/*-------------------------------------------------------------------------*/
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;
if (ep->num == 0)
allow_status (ep);
/* don't queue it */
- req = 0;
+ req = NULL;
} else
s = readl (&ep->regs->ep_stat);
}
* 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);
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;
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) {
&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;
}
spin_unlock_irqrestore (&ep->dev->lock, flags);
- return req ? 0 : -EOPNOTSUPP;
+ return 0;
}
/*-------------------------------------------------------------------------*/
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
-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);
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;
unsigned long flags;
int i;
u32 t1, t2;
- char *s;
+ const char *s;
dev = dev_get_drvdata (_dev);
next = 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;
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;
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
{
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);
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);
| (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 */
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;
}
/* 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.
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);
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);
set_halt (ep);
mode = 2;
} else if (!req && ep->stopped)
- write_fifo (ep, 0);
+ write_fifo (ep, NULL);
}
} else {
/* status; stop NAKing */
ep->stopped = 1;
if (req)
done (ep, req, -EOVERFLOW);
- req = 0;
+ req = NULL;
}
}
}
scan_dma_completions (ep);
if (unlikely (list_empty (&ep->queue)
|| ep->out_overflow)) {
- req = 0;
+ req = NULL;
break;
}
req = list_entry (ep->queue.next,
count &= DMA_BYTE_COUNT_MASK;
if (readl (&ep->dma->dmadesc)
!= req->td_dma)
- req = 0;
+ req = NULL;
break;
}
udelay(1);
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;
}
*/
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);
}
if ((wIndex & 0x0f) == (bEndpointAddress & 0x0f))
return ep;
}
- return 0;
+ return NULL;
}
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);
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;
/* 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);
/* 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);
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);
*/
}
+#undef w_value
+#undef w_index
+#undef w_length
+
next_endpoints:
/* endpoint data irq ? */
scratch = stat & 0x7f;
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);
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)
/* some status we can just ignore */
stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+ | (1 << SUSPEND_REQUEST_INTERRUPT)
| (1 << RESUME_INTERRUPT)
| (1 << SOF_INTERRUPT));
if (!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)
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
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
{
struct net2280 *dev;
unsigned long resource, len;
- void *base = 0;
+ void __iomem *base = NULL;
int retval, i;
char buf [8], *bufp;
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);
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 */,
{
if (!use_dma)
use_dma_chaining = 0;
- return pci_module_init (&net2280_pci_driver);
+ return pci_register_driver (&net2280_pci_driver);
}
module_init (init);