diff options
author | Guennadi Liakhovetski <g.liakhovetski@gmx.de> | 2006-03-19 14:49:14 -0500 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2006-04-14 14:12:19 -0400 |
commit | 950ee4c8f094feecd3add994a2cf4fd335ca509b (patch) | |
tree | 732fb062b0b415fbf85673d1e57ac4b7d563de6d /drivers/usb/gadget/net2280.c | |
parent | f043ca43c1ae354346f72dc5826d820d5619f0b2 (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.c | 90 |
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 | */ |
123 | static int enable_suspend = 0; | 125 | static 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) | |||
760 | static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma) | 780 | static 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 | }; |