浏览代码

[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.
Guennadi Liakhovetski 19 年之前
父节点
当前提交
950ee4c8f0
共有 3 个文件被更改,包括 73 次插入23 次删除
  1. 2 2
      drivers/usb/gadget/Kconfig
  2. 69 21
      drivers/usb/gadget/net2280.c
  3. 2 0
      drivers/usb/gadget/net2280.h

+ 2 - 2
drivers/usb/gadget/Kconfig

@@ -69,11 +69,11 @@ choice
 	   often need board-specific hooks.
 	   often need board-specific hooks.
 
 
 config USB_GADGET_NET2280
 config USB_GADGET_NET2280
-	boolean "NetChip 2280"
+	boolean "NetChip 228x"
 	depends on PCI
 	depends on PCI
 	select USB_GADGET_DUALSPEED
 	select USB_GADGET_DUALSPEED
 	help
 	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.  
 	   supports both full and high speed USB 2.0 data transfers.  
 	   
 	   
 	   It has six configurable endpoints, as well as endpoint zero
 	   It has six configurable endpoints, as well as endpoint zero

+ 69 - 21
drivers/usb/gadget/net2280.c

@@ -26,6 +26,8 @@
  * Copyright (C) 2003 David Brownell
  * Copyright (C) 2003 David Brownell
  * Copyright (C) 2003-2005 PLX Technology, Inc.
  * 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
  * 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
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * 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	DMA_ADDR_INVALID	(~(dma_addr_t)0)
 #define	EP_DONTUSE		13	/* nonzero */
 #define	EP_DONTUSE		13	/* nonzero */
@@ -118,7 +120,7 @@ module_param (fifo_mode, ushort, 0644);
 /* enable_suspend -- When enabled, the driver will respond to
 /* enable_suspend -- When enabled, the driver will respond to
  * USB suspend requests by powering down the NET2280.  Otherwise,
  * USB suspend requests by powering down the NET2280.  Otherwise,
  * USB suspend requests will be ignored.  This is acceptible for
  * 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;
 	ep->is_in = (tmp & USB_DIR_IN) != 0;
 	if (!ep->is_in)
 	if (!ep->is_in)
 		writel ((1 << SET_NAK_OUT_PACKETS), &ep->regs->ep_rsp);
 		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);
 		writel (tmp, &dev->regs->pciirqenb0);
 
 
 		tmp = (1 << DATA_PACKET_RECEIVED_INTERRUPT_ENABLE)
 		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);
 		writel (tmp, &ep->regs->ep_irqenb);
 	} else {				/* dma, per-request */
 	} else {				/* dma, per-request */
 		tmp = (1 << (8 + ep->num));	/* completion */
 		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
 	/* init to our chosen defaults, notably so that we NAK OUT
 	 * packets until the driver queues a read (+note erratum 0112)
 	 * 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 << SET_NAK_OUT_PACKETS)
 		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
 		| (1 << CLEAR_EP_HIDE_STATUS_PHASE)
 		| (1 << CLEAR_INTERRUPT_MODE);
 		| (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) {
 	if (ep->num != 0) {
 		tmp |= (1 << CLEAR_ENDPOINT_TOGGLE)
 		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);
 	writel (tmp, &ep->regs->ep_rsp);
 
 
 	/* scrub most status bits, and flush any fifo state */
 	/* 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_STALL_SENT)
 		| (1 << USB_IN_NAK_SENT)
 		| (1 << USB_IN_NAK_SENT)
 		| (1 << USB_IN_ACK_RCVD)
 		| (1 << USB_IN_ACK_RCVD)
 		| (1 << USB_OUT_PING_NAK_SENT)
 		| (1 << USB_OUT_PING_NAK_SENT)
 		| (1 << USB_OUT_ACK_SENT)
 		| (1 << USB_OUT_ACK_SENT)
-		| (1 << FIFO_OVERFLOW)
-		| (1 << FIFO_UNDERFLOW)
 		| (1 << FIFO_FLUSH)
 		| (1 << FIFO_FLUSH)
 		| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
 		| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
 		| (1 << SHORT_PACKET_TRANSFERRED_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)
 	if (ep->is_in)
 		dmacount |= (1 << DMA_DIRECTION);
 		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);
 		dmacount |= (1 << END_OF_CHAIN);
 
 
 	req->valid = valid;
 	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)
 static void start_queue (struct net2280_ep *ep, u32 dmactl, u32 td_dma)
 {
 {
 	struct net2280_dma_regs	__iomem *dma = ep->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 (readl (&dma->dmastat), &dma->dmastat);
 
 
 	writel (td_dma, &dma->dmadesc);
 	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",
 	VDEBUG (ep->dev, "%s ack ep_stat %08x, req %p\n",
 			ep->ep.name, t, req ? &req->req : 0);
 			ep->ep.name, t, req ? &req->req : 0);
 #endif
 #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
 	/* for ep0, monitor token irqs to catch data stage length errors
 	 * and to synchronize on status.
 	 * and to synchronize on status.
@@ -2337,7 +2364,7 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 			u32			raw [2];
 			u32			raw [2];
 			struct usb_ctrlrequest	r;
 			struct usb_ctrlrequest	r;
 		} u;
 		} u;
-		int				tmp = 0;
+		int				tmp;
 		struct net2280_request		*req;
 		struct net2280_request		*req;
 
 
 		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
 		if (dev->gadget.speed == USB_SPEED_UNKNOWN) {
@@ -2364,14 +2391,19 @@ static void handle_stat0_irqs (struct net2280 *dev, u32 stat)
 		}
 		}
 		ep->stopped = 0;
 		ep->stopped = 0;
 		dev->protocol_stall = 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_STALL_SENT)
 			| (1 << USB_IN_NAK_SENT)
 			| (1 << USB_IN_NAK_SENT)
 			| (1 << USB_IN_ACK_RCVD)
 			| (1 << USB_IN_ACK_RCVD)
 			| (1 << USB_OUT_PING_NAK_SENT)
 			| (1 << USB_OUT_PING_NAK_SENT)
 			| (1 << USB_OUT_ACK_SENT)
 			| (1 << USB_OUT_ACK_SENT)
-			| (1 << FIFO_OVERFLOW)
-			| (1 << FIFO_UNDERFLOW)
 			| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
 			| (1 << SHORT_PACKET_OUT_DONE_INTERRUPT)
 			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
 			| (1 << SHORT_PACKET_TRANSFERRED_INTERRUPT)
 			| (1 << DATA_PACKET_RECEIVED_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 [0]);
 		cpu_to_le32s (&u.raw [1]);
 		cpu_to_le32s (&u.raw [1]);
 
 
+		tmp = 0;
+
 #define	w_value		le16_to_cpup (&u.r.wValue)
 #define	w_value		le16_to_cpup (&u.r.wValue)
 #define	w_index		le16_to_cpup (&u.r.wIndex)
 #define	w_index		le16_to_cpup (&u.r.wIndex)
 #define	w_length	le16_to_cpup (&u.r.wLength)
 #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);
 		writel (stat, &dev->regs->irqstat1);
 
 
 	/* some status we can just ignore */
 	/* 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)
 	if (!stat)
 		return;
 		return;
 	// DEBUG (dev, "irqstat1 %08x\n", stat);
 	// DEBUG (dev, "irqstat1 %08x\n", stat);
@@ -2939,6 +2980,13 @@ static struct pci_device_id pci_ids [] = { {
 	.device =	0x2280,
 	.device =	0x2280,
 	.subvendor =	PCI_ANY_ID,
 	.subvendor =	PCI_ANY_ID,
 	.subdevice =	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 */ }
 };
 };

+ 2 - 0
drivers/usb/gadget/net2280.h

@@ -179,6 +179,7 @@ struct net2280_regs {
 #define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
 #define     PCI_TARGET_ABORT_RECEIVED_INTERRUPT                 19
 #define     PCI_RETRY_ABORT_INTERRUPT                           17
 #define     PCI_RETRY_ABORT_INTERRUPT                           17
 #define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
 #define     PCI_MASTER_CYCLE_DONE_INTERRUPT                     16
+#define     SOF_DOWN_INTERRUPT                                  14
 #define     GPIO_INTERRUPT                                      13
 #define     GPIO_INTERRUPT                                      13
 #define     DMA_D_INTERRUPT                                     12
 #define     DMA_D_INTERRUPT                                     12
 #define     DMA_C_INTERRUPT                                     11
 #define     DMA_C_INTERRUPT                                     11
@@ -346,6 +347,7 @@ struct net2280_dma_regs {	/* [11.7] */
 #define     DMA_ENABLE                                          1
 #define     DMA_ENABLE                                          1
 #define     DMA_ADDRESS_HOLD                                    0
 #define     DMA_ADDRESS_HOLD                                    0
 	u32		dmastat;
 	u32		dmastat;
+#define     DMA_ABORT_DONE_INTERRUPT                            27
 #define     DMA_SCATTER_GATHER_DONE_INTERRUPT                   25
 #define     DMA_SCATTER_GATHER_DONE_INTERRUPT                   25
 #define     DMA_TRANSACTION_DONE_INTERRUPT                      24
 #define     DMA_TRANSACTION_DONE_INTERRUPT                      24
 #define     DMA_ABORT                                           1
 #define     DMA_ABORT                                           1