aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/gadget/net2280.c
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/gadget/net2280.c
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/gadget/net2280.c')
-rw-r--r--drivers/usb/gadget/net2280.c90
1 files changed, 69 insertions, 21 deletions
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};