]> err.no Git - linux-2.6/commitdiff
[PATCH] USB: net2282 and net2280 software compatibility
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>
Sun, 19 Mar 2006 19:49:14 +0000 (20:49 +0100)
committerGreg Kroah-Hartman <gregkh@suse.de>
Fri, 14 Apr 2006 18:12:19 +0000 (11:12 -0700)
Below is a patch to gadgets/net2280.[ch] which adds support for the
net2282 controller. The original code was kindly provided by PLX
Technology, I just merged it with the current net2280 driver in the
kernel. Tested on 2.6.15.6, but only with 2282. I did the merge, so
that the behaviour for the 2280 is unaffected (except for short delays
for extra checks).

Signed-off-by: G. Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Support for net2282 in net2280 driver.

drivers/usb/gadget/Kconfig
drivers/usb/gadget/net2280.c
drivers/usb/gadget/net2280.h

index d80f71877d684fbddb46fb6f322dec3e7766b3a3..363b2ad74ae60db025df978abe30aea313033cf3 100644 (file)
@@ -69,11 +69,11 @@ choice
           often need board-specific hooks.
 
 config USB_GADGET_NET2280
           often need board-specific hooks.
 
 config USB_GADGET_NET2280
-       boolean "NetChip 2280"
+       boolean "NetChip 228x"
        depends on PCI
        select USB_GADGET_DUALSPEED
        help
        depends on PCI
        select USB_GADGET_DUALSPEED
        help
-          NetChip 2280 is a PCI based USB peripheral controller which
+          NetChip 2280 / 2282 is a PCI based USB peripheral controller which
           supports both full and high speed USB 2.0 data transfers.  
           
           It has six configurable endpoints, as well as endpoint zero
           supports both full and high speed USB 2.0 data transfers.  
           
           It has six configurable endpoints, as well as endpoint zero
index fb73dc100535c80d2e16de0ea68f62e533e5ab84..7682c07035bded7412de9f00201c3e5c36cb0b9a 100644 (file)
@@ -26,6 +26,8 @@
  * Copyright (C) 2003 David Brownell
  * Copyright (C) 2003-2005 PLX Technology, Inc.
  *
  * 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
  * 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
@@ -71,8 +73,8 @@
 #include <asm/unaligned.h>
 
 
 #include <asm/unaligned.h>
 
 
-#define        DRIVER_DESC             "PLX NET2280 USB Peripheral Controller"
-#define        DRIVER_VERSION          "2005 Feb 03"
+#define        DRIVER_DESC             "PLX NET228x USB Peripheral Controller"
+#define        DRIVER_VERSION          "2005 Sept 27"
 
 #define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
 #define        EP_DONTUSE              13      /* nonzero */
 
 #define        DMA_ADDR_INVALID        (~(dma_addr_t)0)
 #define        EP_DONTUSE              13      /* nonzero */
@@ -118,7 +120,7 @@ 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
 /* 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.
+ * self-powered devices
  */
 static int enable_suspend = 0;
 
  */
 static int enable_suspend = 0;
 
@@ -223,6 +225,11 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
        ep->is_in = (tmp & USB_DIR_IN) != 0;
        if (!ep->is_in)
                writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
        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, &ep->regs->ep_cfg);
 
@@ -232,8 +239,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
                writel (tmp, &dev->regs->pciirqenb0);
 
                tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
                writel (tmp, &dev->regs->pciirqenb0);
 
                tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
-                       | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE)
-                       | readl (&ep->regs->ep_irqenb);
+                       | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
+               if (dev->pdev->device == 0x2280)
+                       tmp |= readl (&ep->regs->ep_irqenb);
                writel (tmp, &ep->regs->ep_irqenb);
        } else {                                /* dma, per-request */
                tmp = (1 << (8 + ep->num));     /* completion */
                writel (tmp, &ep->regs->ep_irqenb);
        } else {                                /* dma, per-request */
                tmp = (1 << (8 + ep->num));     /* completion */
@@ -314,10 +322,18 @@ static void ep_reset (struct net2280_regs __iomem *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)
         */
        /* init to our chosen defaults, notably so that we NAK OUT
         * packets until the driver queues a read (+note erratum 0112)
         */
-       tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
+       if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
+               tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
                | (1 << SET_NAK_OUT_PACKETS)
                | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
                | (1 << CLEAR_INTERRUPT_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)
 
        if (ep->num != 0) {
                tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
@@ -326,14 +342,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
        writel (tmp, &ep->regs->ep_rsp);
 
        /* scrub most status bits, and flush any fifo state */
        writel (tmp, &ep->regs->ep_rsp);
 
        /* scrub most status bits, and flush any fifo state */
-       writel (  (1 << TIMEOUT)
+       if (ep->dev->pdev->device == 0x2280)
+               tmp = (1 << FIFO_OVERFLOW)
+                       | (1 << FIFO_UNDERFLOW);
+       else
+               tmp = 0;
+
+       writel (tmp | (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 << 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)
                | (1 << FIFO_FLUSH)
                | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
                | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
@@ -718,7 +738,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
         */
        if (ep->is_in)
                dmacount |= (1 << DMA_DIRECTION);
         */
        if (ep->is_in)
                dmacount |= (1 << DMA_DIRECTION);
-       else if ((dmacount % ep->ep.maxpacket) != 0)
+       if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
                dmacount |= (1 << END_OF_CHAIN);
 
        req->valid = valid;
                dmacount |= (1 << END_OF_CHAIN);
 
        req->valid = valid;
@@ -760,9 +780,12 @@ static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
 static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 {
        struct net2280_dma_regs __iomem *dma = ep->dma;
 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);
 
 
-       writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION),
-                       &dma->dmacount);
+       if (ep->dev->pdev->device != 0x2280)
+               tmp |= (1 << END_OF_CHAIN);
+
+       writel (tmp, &dma->dmacount);
        writel (readl (&dma->dmastat), &dma->dmastat);
 
        writel (td_dma, &dma->dmadesc);
        writel (readl (&dma->dmastat), &dma->dmastat);
 
        writel (td_dma, &dma->dmadesc);
@@ -2110,7 +2133,11 @@ static void handle_ep_small (struct net2280_ep *ep)
        VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
                        ep->ep.name, t, req ? &req->req : 0);
 #endif
        VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
                        ep->ep.name, t, req ? &req->req : 0);
 #endif
-       writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
+       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);
 
        /* for ep0, monitor token irqs to catch data stage length errors
         * and to synchronize on status.
 
        /* for ep0, monitor token irqs to catch data stage length errors
         * and to synchronize on status.
@@ -2337,7 +2364,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                        u32                     raw [2];
                        struct usb_ctrlrequest  r;
                } u;
                        u32                     raw [2];
                        struct usb_ctrlrequest  r;
                } u;
-               int                             tmp = 0;
+               int                             tmp;
                struct net2280_request          *req;
 
                if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
                struct net2280_request          *req;
 
                if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
@@ -2364,14 +2391,19 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                }
                ep->stopped = 0;
                dev->protocol_stall = 0;
                }
                ep->stopped = 0;
                dev->protocol_stall = 0;
-               writel (  (1 << TIMEOUT)
+
+               if (ep->dev->pdev->device == 0x2280)
+                       tmp = (1 << FIFO_OVERFLOW)
+                               | (1 << FIFO_UNDERFLOW);
+               else
+                       tmp = 0;
+
+               writel (tmp | (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 << 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)
                        | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
                        | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
                        | (1 << DATA_PACKET_RECEIVED_INTERRUPT)
@@ -2385,6 +2417,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
                cpu_to_le32s (&u.raw [0]);
                cpu_to_le32s (&u.raw [1]);
 
                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)
 #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)
@@ -2594,10 +2628,17 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
                writel (stat, &dev->regs->irqstat1);
 
        /* some status we can just ignore */
                writel (stat, &dev->regs->irqstat1);
 
        /* some status we can just ignore */
-       stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
-                       | (1 << SUSPEND_REQUEST_INTERRUPT)
-                       | (1 << RESUME_INTERRUPT)
-                       | (1 << SOF_INTERRUPT));
+       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));
+
        if (!stat)
                return;
        // DEBUG (dev, "irqstat1 %08x\n", stat);
        if (!stat)
                return;
        // DEBUG (dev, "irqstat1 %08x\n", stat);
@@ -2939,6 +2980,13 @@ static struct pci_device_id pci_ids [] = { {
        .device =       0x2280,
        .subvendor =    PCI_ANY_ID,
        .subdevice =    PCI_ANY_ID,
        .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 */ }
 };
 
 }, { /* end: all zeroes */ }
 };
index fff4509cf340d2d62c20bb91bd5fb136086d14da..e195abec8d7f5f5ca2b89b67f437cdf0dfec395c 100644 (file)
@@ -179,6 +179,7 @@ struct net2280_regs {
 #define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
 #define     PCI_RETRY_ABORT_INTERRUPT                           17
 #define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
 #define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
 #define     PCI_RETRY_ABORT_INTERRUPT                           17
 #define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
+#define     SOF_DOWN_INTERRUPT                                  14
 #define     GPIO_INTERRUPT                                      13
 #define     DMA_D_INTERRUPT                                     12
 #define     DMA_C_INTERRUPT                                     11
 #define     GPIO_INTERRUPT                                      13
 #define     DMA_D_INTERRUPT                                     12
 #define     DMA_C_INTERRUPT                                     11
@@ -346,6 +347,7 @@ struct net2280_dma_regs {   /* [11.7] */
 #define     DMA_ENABLE                                          1
 #define     DMA_ADDRESS_HOLD                                    0
        u32             dmastat;
 #define     DMA_ENABLE                                          1
 #define     DMA_ADDRESS_HOLD                                    0
        u32             dmastat;
+#define     DMA_ABORT_DONE_INTERRUPT                            27
 #define     DMA_SCATTER_GATHER_DONE_INTERRUPT                   25
 #define     DMA_TRANSACTION_DONE_INTERRUPT                      24
 #define     DMA_ABORT                                           1
 #define     DMA_SCATTER_GATHER_DONE_INTERRUPT                   25
 #define     DMA_TRANSACTION_DONE_INTERRUPT                      24
 #define     DMA_ABORT                                           1