aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
authorGuennadi Liakhovetski <g.liakhovetski@gmx.de>2006-03-19 14:49:14 -0500
committerGreg Kroah-Hartman <gregkh@suse.de>2006-04-14 14:12:19 -0400
commit950ee4c8f094feecd3add994a2cf4fd335ca509b (patch)
tree732fb062b0b415fbf85673d1e57ac4b7d563de6d /drivers/usb
parentf043ca43c1ae354346f72dc5826d820d5619f0b2 (diff)
[PATCH] USB: net2282 and net2280 software compatibility
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.
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/gadget/Kconfig4
-rw-r--r--drivers/usb/gadget/net2280.c90
-rw-r--r--drivers/usb/gadget/net2280.h2
3 files changed, 73 insertions, 23 deletions
diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig
index d80f71877d68..363b2ad74ae6 100644
--- a/drivers/usb/gadget/Kconfig
+++ b/drivers/usb/gadget/Kconfig
@@ -69,11 +69,11 @@ choice
69 often need board-specific hooks. 69 often need board-specific hooks.
70 70
71config USB_GADGET_NET2280 71config USB_GADGET_NET2280
72 boolean "NetChip 2280" 72 boolean "NetChip 228x"
73 depends on PCI 73 depends on PCI
74 select USB_GADGET_DUALSPEED 74 select USB_GADGET_DUALSPEED
75 help 75 help
76 NetChip 2280 is a PCI based USB peripheral controller which 76 NetChip 2280 / 2282 is a PCI based USB peripheral controller which
77 supports both full and high speed USB 2.0 data transfers. 77 supports both full and high speed USB 2.0 data transfers.
78 78
79 It has six configurable endpoints, as well as endpoint zero 79 It has six configurable endpoints, as well as endpoint zero
diff --git a/drivers/usb/gadget/net2280.c b/drivers/usb/gadget/net2280.c
index fb73dc100535..7682c07035bd 100644
--- a/drivers/usb/gadget/net2280.c
+++ b/drivers/usb/gadget/net2280.c
@@ -26,6 +26,8 @@
26 * Copyright (C) 2003 David Brownell 26 * Copyright (C) 2003 David Brownell
27 * Copyright (C) 2003-2005 PLX Technology, Inc. 27 * Copyright (C) 2003-2005 PLX Technology, Inc.
28 * 28 *
29 * Modified Seth Levy 2005 PLX Technology, Inc. to provide compatibility with 2282 chip
30 *
29 * This program is free software; you can redistribute it and/or modify 31 * This program is free software; you can redistribute it and/or modify
30 * it under the terms of the GNU General Public License as published by 32 * it under the terms of the GNU General Public License as published by
31 * the Free Software Foundation; either version 2 of the License, or 33 * the Free Software Foundation; either version 2 of the License, or
@@ -71,8 +73,8 @@
71#include <asm/unaligned.h> 73#include <asm/unaligned.h>
72 74
73 75
74#define DRIVER_DESC "PLX NET2280 USB Peripheral Controller" 76#define DRIVER_DESC "PLX NET228x USB Peripheral Controller"
75#define DRIVER_VERSION "2005 Feb 03" 77#define DRIVER_VERSION "2005 Sept 27"
76 78
77#define DMA_ADDR_INVALID (~(dma_addr_t)0) 79#define DMA_ADDR_INVALID (~(dma_addr_t)0)
78#define EP_DONTUSE 13 /* nonzero */ 80#define EP_DONTUSE 13 /* nonzero */
@@ -118,7 +120,7 @@ module_param (fifo_mode, ushort, 0644);
118/* enable_suspend -- When enabled, the driver will respond to 120/* enable_suspend -- When enabled, the driver will respond to
119 * USB suspend requests by powering down the NET2280. Otherwise, 121 * USB suspend requests by powering down the NET2280. Otherwise,
120 * USB suspend requests will be ignored. This is acceptible for 122 * USB suspend requests will be ignored. This is acceptible for
121 * self-powered devices, and helps avoid some quirks. 123 * self-powered devices
122 */ 124 */
123static int enable_suspend = 0; 125static int enable_suspend = 0;
124 126
@@ -223,6 +225,11 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
223 ep->is_in = (tmp & USB_DIR_IN) != 0; 225 ep->is_in = (tmp & USB_DIR_IN) != 0;
224 if (!ep->is_in) 226 if (!ep->is_in)
225 writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp); 227 writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
228 else if (dev->pdev->device != 0x2280) {
229 /* Added for 2282, Don't use nak packets on an in endpoint, this was ignored on 2280 */
230 writel ((1 << CLEAR_NAK_OUT_PACKETS)
231 | (1 << CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
232 }
226 233
227 writel (tmp, &ep->regs->ep_cfg); 234 writel (tmp, &ep->regs->ep_cfg);
228 235
@@ -232,8 +239,9 @@ net2280_enable (struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
232 writel (tmp, &dev->regs->pciirqenb0); 239 writel (tmp, &dev->regs->pciirqenb0);
233 240
234 tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE) 241 tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
235 | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE) 242 | (1 << DATA_PACKET_TRANSMITTED_INTERRUPT_ENABLE);
236 | readl (&ep->regs->ep_irqenb); 243 if (dev->pdev->device == 0x2280)
244 tmp |= readl (&ep->regs->ep_irqenb);
237 writel (tmp, &ep->regs->ep_irqenb); 245 writel (tmp, &ep->regs->ep_irqenb);
238 } else { /* dma, per-request */ 246 } else { /* dma, per-request */
239 tmp = (1 << (8 + ep->num)); /* completion */ 247 tmp = (1 << (8 + ep->num)); /* completion */
@@ -314,10 +322,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
314 /* init to our chosen defaults, notably so that we NAK OUT 322 /* init to our chosen defaults, notably so that we NAK OUT
315 * packets until the driver queues a read (+note erratum 0112) 323 * packets until the driver queues a read (+note erratum 0112)
316 */ 324 */
317 tmp = (1 << SET_NAK_OUT_PACKETS_MODE) 325 if (!ep->is_in || ep->dev->pdev->device == 0x2280) {
326 tmp = (1 << SET_NAK_OUT_PACKETS_MODE)
318 | (1 << SET_NAK_OUT_PACKETS) 327 | (1 << SET_NAK_OUT_PACKETS)
319 | (1 << CLEAR_EP_HIDE_STATUS_PHASE) 328 | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
320 | (1 << CLEAR_INTERRUPT_MODE); 329 | (1 << CLEAR_INTERRUPT_MODE);
330 } else {
331 /* added for 2282 */
332 tmp = (1 << CLEAR_NAK_OUT_PACKETS_MODE)
333 | (1 << CLEAR_NAK_OUT_PACKETS)
334 | (1 << CLEAR_EP_HIDE_STATUS_PHASE)
335 | (1 << CLEAR_INTERRUPT_MODE);
336 }
321 337
322 if (ep->num != 0) { 338 if (ep->num != 0) {
323 tmp |= (1 << CLEAR_ENDPOINT_TOGGLE) 339 tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
@@ -326,14 +342,18 @@ static void ep_reset (struct net2280_regs __iomem *regs, struct net2280_ep *ep)
326 writel (tmp, &ep->regs->ep_rsp); 342 writel (tmp, &ep->regs->ep_rsp);
327 343
328 /* scrub most status bits, and flush any fifo state */ 344 /* scrub most status bits, and flush any fifo state */
329 writel ( (1 << TIMEOUT) 345 if (ep->dev->pdev->device == 0x2280)
346 tmp = (1 << FIFO_OVERFLOW)
347 | (1 << FIFO_UNDERFLOW);
348 else
349 tmp = 0;
350
351 writel (tmp | (1 << TIMEOUT)
330 | (1 << USB_STALL_SENT) 352 | (1 << USB_STALL_SENT)
331 | (1 << USB_IN_NAK_SENT) 353 | (1 << USB_IN_NAK_SENT)
332 | (1 << USB_IN_ACK_RCVD) 354 | (1 << USB_IN_ACK_RCVD)
333 | (1 << USB_OUT_PING_NAK_SENT) 355 | (1 << USB_OUT_PING_NAK_SENT)
334 | (1 << USB_OUT_ACK_SENT) 356 | (1 << USB_OUT_ACK_SENT)
335 | (1 << FIFO_OVERFLOW)
336 | (1 << FIFO_UNDERFLOW)
337 | (1 << FIFO_FLUSH) 357 | (1 << FIFO_FLUSH)
338 | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT) 358 | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
339 | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT) 359 | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
@@ -718,7 +738,7 @@ fill_dma_desc (struct net2280_ep *ep, struct net2280_request *req, int valid)
718 */ 738 */
719 if (ep->is_in) 739 if (ep->is_in)
720 dmacount |= (1 << DMA_DIRECTION); 740 dmacount |= (1 << DMA_DIRECTION);
721 else if ((dmacount % ep->ep.maxpacket) != 0) 741 if ((!ep->is_in && (dmacount % ep->ep.maxpacket) != 0) || ep->dev->pdev->device != 0x2280)
722 dmacount |= (1 << END_OF_CHAIN); 742 dmacount |= (1 << END_OF_CHAIN);
723 743
724 req->valid = valid; 744 req->valid = valid;
@@ -760,9 +780,12 @@ static inline void stop_dma (struct net2280_dma_regs __iomem *dma)
760static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma) 780static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
761{ 781{
762 struct net2280_dma_regs __iomem *dma = ep->dma; 782 struct net2280_dma_regs __iomem *dma = ep->dma;
783 unsigned int tmp = (1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION);
763 784
764 writel ((1 << VALID_BIT) | (ep->is_in << DMA_DIRECTION), 785 if (ep->dev->pdev->device != 0x2280)
765 &dma->dmacount); 786 tmp |= (1 << END_OF_CHAIN);
787
788 writel (tmp, &dma->dmacount);
766 writel (readl (&dma->dmastat), &dma->dmastat); 789 writel (readl (&dma->dmastat), &dma->dmastat);
767 790
768 writel (td_dma, &dma->dmadesc); 791 writel (td_dma, &dma->dmadesc);
@@ -2110,7 +2133,11 @@ static void handle_ep_small (struct net2280_ep *ep)
2110 VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n", 2133 VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
2111 ep->ep.name, t, req ? &req->req : 0); 2134 ep->ep.name, t, req ? &req->req : 0);
2112#endif 2135#endif
2113 writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat); 2136 if (!ep->is_in || ep->dev->pdev->device == 0x2280)
2137 writel (t & ~(1 << NAK_OUT_PACKETS), &ep->regs->ep_stat);
2138 else
2139 /* Added for 2282 */
2140 writel (t, &ep->regs->ep_stat);
2114 2141
2115 /* for ep0, monitor token irqs to catch data stage length errors 2142 /* for ep0, monitor token irqs to catch data stage length errors
2116 * and to synchronize on status. 2143 * and to synchronize on status.
@@ -2337,7 +2364,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
2337 u32 raw [2]; 2364 u32 raw [2];
2338 struct usb_ctrlrequest r; 2365 struct usb_ctrlrequest r;
2339 } u; 2366 } u;
2340 int tmp = 0; 2367 int tmp;
2341 struct net2280_request *req; 2368 struct net2280_request *req;
2342 2369
2343 if (dev->gadget.speed == USB_SPEED_UNKNOWN) { 2370 if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
@@ -2364,14 +2391,19 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
2364 } 2391 }
2365 ep->stopped = 0; 2392 ep->stopped = 0;
2366 dev->protocol_stall = 0; 2393 dev->protocol_stall = 0;
2367 writel ( (1 << TIMEOUT) 2394
2395 if (ep->dev->pdev->device == 0x2280)
2396 tmp = (1 << FIFO_OVERFLOW)
2397 | (1 << FIFO_UNDERFLOW);
2398 else
2399 tmp = 0;
2400
2401 writel (tmp | (1 << TIMEOUT)
2368 | (1 << USB_STALL_SENT) 2402 | (1 << USB_STALL_SENT)
2369 | (1 << USB_IN_NAK_SENT) 2403 | (1 << USB_IN_NAK_SENT)
2370 | (1 << USB_IN_ACK_RCVD) 2404 | (1 << USB_IN_ACK_RCVD)
2371 | (1 << USB_OUT_PING_NAK_SENT) 2405 | (1 << USB_OUT_PING_NAK_SENT)
2372 | (1 << USB_OUT_ACK_SENT) 2406 | (1 << USB_OUT_ACK_SENT)
2373 | (1 << FIFO_OVERFLOW)
2374 | (1 << FIFO_UNDERFLOW)
2375 | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT) 2407 | (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
2376 | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT) 2408 | (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
2377 | (1 << DATA_PACKET_RECEIVED_INTERRUPT) 2409 | (1 << DATA_PACKET_RECEIVED_INTERRUPT)
@@ -2385,6 +2417,8 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
2385 cpu_to_le32s (&u.raw [0]); 2417 cpu_to_le32s (&u.raw [0]);
2386 cpu_to_le32s (&u.raw [1]); 2418 cpu_to_le32s (&u.raw [1]);
2387 2419
2420 tmp = 0;
2421
2388#define w_value le16_to_cpup (&u.r.wValue) 2422#define w_value le16_to_cpup (&u.r.wValue)
2389#define w_index le16_to_cpup (&u.r.wIndex) 2423#define w_index le16_to_cpup (&u.r.wIndex)
2390#define w_length le16_to_cpup (&u.r.wLength) 2424#define w_length le16_to_cpup (&u.r.wLength)
@@ -2594,10 +2628,17 @@ static void handle_stat1_irqs (struct net2280 *dev, u32 stat)
2594 writel (stat, &dev->regs->irqstat1); 2628 writel (stat, &dev->regs->irqstat1);
2595 2629
2596 /* some status we can just ignore */ 2630 /* some status we can just ignore */
2597 stat &= ~((1 << CONTROL_STATUS_INTERRUPT) 2631 if (dev->pdev->device == 0x2280)
2598 | (1 << SUSPEND_REQUEST_INTERRUPT) 2632 stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
2599 | (1 << RESUME_INTERRUPT) 2633 | (1 << SUSPEND_REQUEST_INTERRUPT)
2600 | (1 << SOF_INTERRUPT)); 2634 | (1 << RESUME_INTERRUPT)
2635 | (1 << SOF_INTERRUPT));
2636 else
2637 stat &= ~((1 << CONTROL_STATUS_INTERRUPT)
2638 | (1 << RESUME_INTERRUPT)
2639 | (1 << SOF_DOWN_INTERRUPT)
2640 | (1 << SOF_INTERRUPT));
2641
2601 if (!stat) 2642 if (!stat)
2602 return; 2643 return;
2603 // DEBUG (dev, "irqstat1 %08x\n", stat); 2644 // DEBUG (dev, "irqstat1 %08x\n", stat);
@@ -2939,6 +2980,13 @@ static struct pci_device_id pci_ids [] = { {
2939 .device = 0x2280, 2980 .device = 0x2280,
2940 .subvendor = PCI_ANY_ID, 2981 .subvendor = PCI_ANY_ID,
2941 .subdevice = PCI_ANY_ID, 2982 .subdevice = PCI_ANY_ID,
2983}, {
2984 .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
2985 .class_mask = ~0,
2986 .vendor = 0x17cc,
2987 .device = 0x2282,
2988 .subvendor = PCI_ANY_ID,
2989 .subdevice = PCI_ANY_ID,
2942 2990
2943}, { /* end: all zeroes */ } 2991}, { /* end: all zeroes */ }
2944}; 2992};
diff --git a/drivers/usb/gadget/net2280.h b/drivers/usb/gadget/net2280.h
index fff4509cf340..e195abec8d7f 100644
--- a/drivers/usb/gadget/net2280.h
+++ b/drivers/usb/gadget/net2280.h
@@ -179,6 +179,7 @@ struct net2280_regs {
179#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19 179#define PCI_TARGET_ABORT_RECEIVED_INTERRUPT 19
180#define PCI_RETRY_ABORT_INTERRUPT 17 180#define PCI_RETRY_ABORT_INTERRUPT 17
181#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16 181#define PCI_MASTER_CYCLE_DONE_INTERRUPT 16
182#define SOF_DOWN_INTERRUPT 14
182#define GPIO_INTERRUPT 13 183#define GPIO_INTERRUPT 13
183#define DMA_D_INTERRUPT 12 184#define DMA_D_INTERRUPT 12
184#define DMA_C_INTERRUPT 11 185#define DMA_C_INTERRUPT 11
@@ -346,6 +347,7 @@ struct net2280_dma_regs { /* [11.7] */
346#define DMA_ENABLE 1 347#define DMA_ENABLE 1
347#define DMA_ADDRESS_HOLD 0 348#define DMA_ADDRESS_HOLD 0
348 u32 dmastat; 349 u32 dmastat;
350#define DMA_ABORT_DONE_INTERRUPT 27
349#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25 351#define DMA_SCATTER_GATHER_DONE_INTERRUPT 25
350#define DMA_TRANSACTION_DONE_INTERRUPT 24 352#define DMA_TRANSACTION_DONE_INTERRUPT 24
351#define DMA_ABORT 1 353#define DMA_ABORT 1