* Copyright (C) 2003 David Brownell
* Copyright (C) 2003-2005 PLX Technology, Inc.
*
- * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
- *
* 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
#include <asm/unaligned.h>
-#define DRIVER_DESC "PLX NET228x USB Peripheral Controller"
-#define DRIVER_VERSION "2005 Sept 27"
+#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 */
/* 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
+ * self-powered devices, and helps avoid some quirks.
*/
static int enable_suspend = 0;
ep->is_in = (tmp & USB_DIR_IN) != 0;
if (!ep->is_in)
writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
- else if (dev->pdev->device != 0x2280) {
- /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
- writel ((1 << CLEAR_NAK_OUT_PACKETS)
- | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
- }
writel (tmp, &ep->regs->ep_cfg);
writel (tmp, &dev->regs->pciirqenb0);
tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
- | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
- if (dev->pdev->device == 0x2280)
- tmp |= readl (&ep->regs->ep_irqenb);
+ | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
+ | readl (&ep->regs->ep_irqenb);
writel (tmp, &ep->regs->ep_irqenb);
} else { /* dma, per-request */
tmp = (1 << (8 + ep->num)); /* completion */
/* init to our chosen defaults, notably so that we NAK OUT
* packets until the driver queues a read (+note erratum 0112)
*/
- if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
- tmp = (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);
- } else {
- /* added for 2282 */
- tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
- | (1 << CLEAR_NAK_OUT_PACKETS)
- | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
- | (1 << CLEAR_INTERRUPT_MODE);
- }
if (ep->num != 0) {
tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
writel (tmp, &ep->regs->ep_rsp);
/* scrub most status bits, and flush any fifo state */
- if (ep->dev->pdev->device == 0x2280)
- tmp = (1 << FIFO_OVERFLOW)
- | (1 << FIFO_UNDERFLOW);
- else
- tmp = 0;
-
- writel (tmp | (1 << TIMEOUT)
+ writel ( (1 << TIMEOUT)
| (1 << USB_STALL_SENT)
| (1 << USB_IN_NAK_SENT)
| (1 << USB_IN_ACK_RCVD)
| (1 << USB_OUT_PING_NAK_SENT)
| (1 << USB_OUT_ACK_SENT)
+ | (1 << FIFO_OVERFLOW)
+ | (1 << FIFO_UNDERFLOW)
| (1 << FIFO_FLUSH)
| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
return NULL;
ep = container_of (_ep, struct net2280_ep, ep);
- req = kzalloc(sizeof(*req), gfp_flags);
+ req = kmalloc (sizeof *req, gfp_flags);
if (!req)
return NULL;
+ memset (req, 0, sizeof *req);
req->req.dma = DMA_ADDR_INVALID;
INIT_LIST_HEAD (&req->queue);
*/
if (ep->is_in)
dmacount |= (1 << DMA_DIRECTION);
- if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
+ else if ((dmacount % ep->ep.maxpacket) != 0)
dmacount |= (1 << END_OF_CHAIN);
req->valid = valid;
static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
{
struct net2280_dma_regs __iomem *dma = ep->dma;
- unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
-
- if (ep->dev->pdev->device != 0x2280)
- tmp |= (1 << END_OF_CHAIN);
- writel (tmp, &dma->dmacount);
+ writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
+ &dma->dmacount);
writel (readl (&dma->dmastat), &dma->dmastat);
writel (td_dma, &dma->dmadesc);
VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
ep->ep.name, t, req ? &req->req : 0);
#endif
- if (!ep->is_in || ep->dev->pdev->device == 0x2280)
- writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
- else
- /* Added for 2282 */
- writel (t, &ep->regs->ep_stat);
+ writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
/* for ep0, monitor token irqs to catch data stage length errors
* and to synchronize on status.
ep->stopped = 1;
set_halt (ep);
mode = 2;
- } else if (!req && !ep->stopped)
+ } else if (!req && ep->stopped)
write_fifo (ep, NULL);
}
} else {
if (likely (req)) {
req->td->dmacount = 0;
t = readl (&ep->regs->ep_avail);
- dma_done (ep, req, count,
- (ep->out_overflow || t) ? -EOVERFLOW : 0);
+ dma_done (ep, req, count, t);
}
/* also flush to prevent erratum 0106 trouble */
/* if we wrote it all, we're usually done */
if (req->req.actual == req->req.length) {
if (ep->num == 0) {
- /* send zlps until the status stage */
+ /* wait for control status */
+ if (mode != 2)
+ req = NULL;
} else if (!req->req.zero || len != ep->ep.maxpacket)
mode = 2;
}
u32 raw [2];
struct usb_ctrlrequest r;
} u;
- int tmp;
+ int tmp = 0;
struct net2280_request *req;
if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
}
ep->stopped = 0;
dev->protocol_stall = 0;
-
- if (ep->dev->pdev->device == 0x2280)
- tmp = (1 << FIFO_OVERFLOW)
- | (1 << FIFO_UNDERFLOW);
- else
- tmp = 0;
-
- writel (tmp | (1 << TIMEOUT)
+ writel ( (1 << TIMEOUT)
| (1 << USB_STALL_SENT)
| (1 << USB_IN_NAK_SENT)
| (1 << USB_IN_ACK_RCVD)
| (1 << USB_OUT_PING_NAK_SENT)
| (1 << USB_OUT_ACK_SENT)
+ | (1 << FIFO_OVERFLOW)
+ | (1 << FIFO_UNDERFLOW)
| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
| (1 << DATA_PACKET_RECEIVED_INTERRUPT)
cpu_to_le32s (&u.raw [0]);
cpu_to_le32s (&u.raw [1]);
- tmp = 0;
-
#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)
writel (stat, &dev->regs->irqstat1);
/* some status we can just ignore */
- if (dev->pdev->device == 0x2280)
- stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
- | (1 << SUSPEND_REQUEST_INTERRUPT)
- | (1 << RESUME_INTERRUPT)
- | (1 << SOF_INTERRUPT));
- else
- stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
- | (1 << RESUME_INTERRUPT)
- | (1 << SOF_DOWN_INTERRUPT)
- | (1 << SOF_INTERRUPT));
-
+ stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
+ | (1 << SUSPEND_REQUEST_INTERRUPT)
+ | (1 << RESUME_INTERRUPT)
+ | (1 << SOF_INTERRUPT));
if (!stat)
return;
// DEBUG (dev, "irqstat1 %08x\n", stat);
{
struct net2280 *dev = _dev;
- /* shared interrupt, not ours */
- if (!(readl(&dev->regs->irqstat0) & (1 << INTA_ASSERTED)))
- return IRQ_NONE;
-
spin_lock (&dev->lock);
/* handle disconnect, dma, and more */
}
/* alloc, and start init */
- dev = kzalloc (sizeof *dev, SLAB_KERNEL);
+ dev = kmalloc (sizeof *dev, SLAB_KERNEL);
if (dev == NULL){
retval = -ENOMEM;
goto done;
}
- pci_set_drvdata (pdev, dev);
+ memset (dev, 0, sizeof *dev);
spin_lock_init (&dev->lock);
dev->pdev = pdev;
dev->gadget.ops = &net2280_ops;
dev->chiprev = get_idx_reg (dev->regs, REG_CHIPREV) & 0xffff;
/* done */
+ pci_set_drvdata (pdev, dev);
INFO (dev, "%s\n", driver_desc);
INFO (dev, "irq %s, pci mem %p, chip rev %04x\n",
bufp, base, dev->chiprev);
.device = 0x2280,
.subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID,
-}, {
- .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
- .class_mask = ~0,
- .vendor = 0x17cc,
- .device = 0x2282,
- .subvendor = PCI_ANY_ID,
- .subdevice = PCI_ANY_ID,
}, { /* end: all zeroes */ }
};