generic: add NET3380 UDC support
Add a patch to backport 5185c91385d73cdf79836eb8548e4726e43ae831 from Linux 4.8 adding USB2380 support to the NET2280 driver and create an OpenWrt menu option to select it as a module. Signed-off-by: Tim Harvey <tharvey@gateworks.com>
This commit is contained in:
parent
3314bcf715
commit
232893037a
2 changed files with 279 additions and 0 deletions
|
@ -1626,3 +1626,20 @@ define KernelPackage/usb3/description
|
||||||
endef
|
endef
|
||||||
|
|
||||||
$(eval $(call KernelPackage,usb3))
|
$(eval $(call KernelPackage,usb3))
|
||||||
|
|
||||||
|
|
||||||
|
define KernelPackage/usb-net2280
|
||||||
|
TITLE:=Support for NetChip 228x PCI USB peripheral controller
|
||||||
|
KCONFIG:= CONFIG_USB_NET2280
|
||||||
|
DEPENDS:=@PCI_SUPPORT +kmod-usb-gadget
|
||||||
|
FILES:=$(LINUX_DIR)/drivers/usb/gadget/udc/net2280.ko
|
||||||
|
AUTOLOAD:=$(call AutoLoad,46,net2280)
|
||||||
|
$(call AddDepends/usb)
|
||||||
|
endef
|
||||||
|
|
||||||
|
define KernelPackage/usb-net2280/description
|
||||||
|
Kernel support for NetChip 228x / PLX USB338x PCI USB peripheral controller.
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call KernelPackage,usb-net2280))
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,262 @@
|
||||||
|
From 5185c91385d73cdf79836eb8548e4726e43ae831 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Tim Harvey <tharvey@gateworks.com>
|
||||||
|
Date: Mon, 23 May 2016 06:58:41 -0700
|
||||||
|
Subject: [PATCH] usb: gadget: net2280: add USB2380 support
|
||||||
|
|
||||||
|
The PLX USB2380 is a PCIe version of the NET2280 and behaves more like the
|
||||||
|
USB338x but without the USB3.0 superspeed support.
|
||||||
|
|
||||||
|
This was tested with g_ether, g_serial, g_mass_storage on a Gateworks
|
||||||
|
Ventana GW2383.
|
||||||
|
|
||||||
|
Cc: Justin DeFields <justindefields@gmail.com>
|
||||||
|
Signed-off-by: Tim Harvey <tharvey@gateworks.com>
|
||||||
|
Signed-off-by: Felipe Balbi <felipe.balbi@linux.intel.com>
|
||||||
|
---
|
||||||
|
drivers/usb/gadget/udc/Kconfig | 4 +++-
|
||||||
|
drivers/usb/gadget/udc/net2280.c | 51 +++++++++++++++++++++++-----------------
|
||||||
|
drivers/usb/gadget/udc/net2280.h | 1 +
|
||||||
|
3 files changed, 34 insertions(+), 22 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/drivers/usb/gadget/udc/Kconfig b/drivers/usb/gadget/udc/Kconfig
|
||||||
|
index 7c28941..658b8da 100644
|
||||||
|
--- a/drivers/usb/gadget/udc/Kconfig
|
||||||
|
+++ b/drivers/usb/gadget/udc/Kconfig
|
||||||
|
@@ -312,7 +312,7 @@ config USB_NET2272_DMA
|
||||||
|
If unsure, say "N" here. The driver works fine in PIO mode.
|
||||||
|
|
||||||
|
config USB_NET2280
|
||||||
|
- tristate "NetChip 228x / PLX USB338x"
|
||||||
|
+ tristate "NetChip NET228x / PLX USB3x8x"
|
||||||
|
depends on PCI
|
||||||
|
help
|
||||||
|
NetChip 2280 / 2282 is a PCI based USB peripheral controller which
|
||||||
|
@@ -322,6 +322,8 @@ config USB_NET2280
|
||||||
|
(for control transfers) and several endpoints with dedicated
|
||||||
|
functions.
|
||||||
|
|
||||||
|
+ PLX 2380 is a PCIe version of the PLX 2380.
|
||||||
|
+
|
||||||
|
PLX 3380 / 3382 is a PCIe based USB peripheral controller which
|
||||||
|
supports full, high speed USB 2.0 and super speed USB 3.0
|
||||||
|
data transfers.
|
||||||
|
diff --git a/drivers/usb/gadget/udc/net2280.c b/drivers/usb/gadget/udc/net2280.c
|
||||||
|
index c894b94..614ab951 100644
|
||||||
|
--- a/drivers/usb/gadget/udc/net2280.c
|
||||||
|
+++ b/drivers/usb/gadget/udc/net2280.c
|
||||||
|
@@ -211,7 +211,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
|
||||||
|
goto print_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (dev->quirks & PLX_SUPERSPEED) {
|
||||||
|
+ if (dev->quirks & PLX_PCIE) {
|
||||||
|
if ((desc->bEndpointAddress & 0x0f) >= 0x0c) {
|
||||||
|
ret = -EDOM;
|
||||||
|
goto print_err;
|
||||||
|
@@ -245,7 +245,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
|
||||||
|
/* set type, direction, address; reset fifo counters */
|
||||||
|
writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat);
|
||||||
|
|
||||||
|
- if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) {
|
||||||
|
+ if ((dev->quirks & PLX_PCIE) && dev->enhanced_mode) {
|
||||||
|
tmp = readl(&ep->cfg->ep_cfg);
|
||||||
|
/* If USB ep number doesn't match hardware ep number */
|
||||||
|
if ((tmp & 0xf) != usb_endpoint_num(desc)) {
|
||||||
|
@@ -316,7 +316,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
|
||||||
|
BIT(CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (dev->quirks & PLX_SUPERSPEED)
|
||||||
|
+ if (dev->quirks & PLX_PCIE)
|
||||||
|
ep_clear_seqnum(ep);
|
||||||
|
writel(tmp, &ep->cfg->ep_cfg);
|
||||||
|
|
||||||
|
@@ -527,7 +527,7 @@ static int net2280_disable(struct usb_ep *_ep)
|
||||||
|
spin_lock_irqsave(&ep->dev->lock, flags);
|
||||||
|
nuke(ep);
|
||||||
|
|
||||||
|
- if (ep->dev->quirks & PLX_SUPERSPEED)
|
||||||
|
+ if (ep->dev->quirks & PLX_PCIE)
|
||||||
|
ep_reset_338x(ep->dev->regs, ep);
|
||||||
|
else
|
||||||
|
ep_reset_228x(ep->dev->regs, ep);
|
||||||
|
@@ -862,7 +862,7 @@ static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
|
||||||
|
writel(readl(&dma->dmastat), &dma->dmastat);
|
||||||
|
|
||||||
|
writel(td_dma, &dma->dmadesc);
|
||||||
|
- if (ep->dev->quirks & PLX_SUPERSPEED)
|
||||||
|
+ if (ep->dev->quirks & PLX_PCIE)
|
||||||
|
dmactl |= BIT(DMA_REQUEST_OUTSTANDING);
|
||||||
|
writel(dmactl, &dma->dmactl);
|
||||||
|
|
||||||
|
@@ -1046,7 +1046,7 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
|
||||||
|
|
||||||
|
/* kickstart this i/o queue? */
|
||||||
|
if (list_empty(&ep->queue) && !ep->stopped &&
|
||||||
|
- !((dev->quirks & PLX_SUPERSPEED) && ep->dma &&
|
||||||
|
+ !((dev->quirks & PLX_PCIE) && ep->dma &&
|
||||||
|
(readl(&ep->regs->ep_rsp) & BIT(CLEAR_ENDPOINT_HALT)))) {
|
||||||
|
|
||||||
|
/* use DMA if the endpoint supports it, else pio */
|
||||||
|
@@ -1169,7 +1169,7 @@ static void scan_dma_completions(struct net2280_ep *ep)
|
||||||
|
break;
|
||||||
|
} else if (!ep->is_in &&
|
||||||
|
(req->req.length % ep->ep.maxpacket) &&
|
||||||
|
- !(ep->dev->quirks & PLX_SUPERSPEED)) {
|
||||||
|
+ !(ep->dev->quirks & PLX_PCIE)) {
|
||||||
|
|
||||||
|
tmp = readl(&ep->regs->ep_stat);
|
||||||
|
/* AVOID TROUBLE HERE by not issuing short reads from
|
||||||
|
@@ -1367,7 +1367,7 @@ net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
|
||||||
|
ep->wedged = 1;
|
||||||
|
} else {
|
||||||
|
clear_halt(ep);
|
||||||
|
- if (ep->dev->quirks & PLX_SUPERSPEED &&
|
||||||
|
+ if (ep->dev->quirks & PLX_PCIE &&
|
||||||
|
!list_empty(&ep->queue) && ep->td_dma)
|
||||||
|
restart_dma(ep);
|
||||||
|
ep->wedged = 0;
|
||||||
|
@@ -2394,7 +2394,7 @@ static int net2280_start(struct usb_gadget *_gadget,
|
||||||
|
*/
|
||||||
|
net2280_led_active(dev, 1);
|
||||||
|
|
||||||
|
- if ((dev->quirks & PLX_SUPERSPEED) && !dev->bug7734_patched)
|
||||||
|
+ if ((dev->quirks & PLX_PCIE) && !dev->bug7734_patched)
|
||||||
|
defect7374_enable_data_eps_zero(dev);
|
||||||
|
|
||||||
|
ep0_start(dev);
|
||||||
|
@@ -3063,7 +3063,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
|
||||||
|
}
|
||||||
|
ep->stopped = 0;
|
||||||
|
dev->protocol_stall = 0;
|
||||||
|
- if (!(dev->quirks & PLX_SUPERSPEED)) {
|
||||||
|
+ if (!(dev->quirks & PLX_PCIE)) {
|
||||||
|
if (ep->dev->quirks & PLX_2280)
|
||||||
|
tmp = BIT(FIFO_OVERFLOW) |
|
||||||
|
BIT(FIFO_UNDERFLOW);
|
||||||
|
@@ -3090,7 +3090,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
|
||||||
|
cpu_to_le32s(&u.raw[0]);
|
||||||
|
cpu_to_le32s(&u.raw[1]);
|
||||||
|
|
||||||
|
- if ((dev->quirks & PLX_SUPERSPEED) && !dev->bug7734_patched)
|
||||||
|
+ if ((dev->quirks & PLX_PCIE) && !dev->bug7734_patched)
|
||||||
|
defect7374_workaround(dev, u.r);
|
||||||
|
|
||||||
|
tmp = 0;
|
||||||
|
@@ -3173,7 +3173,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
|
||||||
|
} else {
|
||||||
|
ep_vdbg(dev, "%s clear halt\n", e->ep.name);
|
||||||
|
clear_halt(e);
|
||||||
|
- if ((ep->dev->quirks & PLX_SUPERSPEED) &&
|
||||||
|
+ if ((ep->dev->quirks & PLX_PCIE) &&
|
||||||
|
!list_empty(&e->queue) && e->td_dma)
|
||||||
|
restart_dma(e);
|
||||||
|
}
|
||||||
|
@@ -3195,7 +3195,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
|
||||||
|
if (e->ep.name == ep0name)
|
||||||
|
goto do_stall;
|
||||||
|
set_halt(e);
|
||||||
|
- if ((dev->quirks & PLX_SUPERSPEED) && e->dma)
|
||||||
|
+ if ((dev->quirks & PLX_PCIE) && e->dma)
|
||||||
|
abort_dma(e);
|
||||||
|
allow_status(ep);
|
||||||
|
ep_vdbg(dev, "%s set halt\n", ep->ep.name);
|
||||||
|
@@ -3234,7 +3234,7 @@ do_stall:
|
||||||
|
#undef w_length
|
||||||
|
|
||||||
|
next_endpoints:
|
||||||
|
- if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) {
|
||||||
|
+ if ((dev->quirks & PLX_PCIE) && dev->enhanced_mode) {
|
||||||
|
u32 mask = (BIT(ENDPOINT_0_INTERRUPT) |
|
||||||
|
USB3380_IRQSTAT0_EP_INTR_MASK_IN |
|
||||||
|
USB3380_IRQSTAT0_EP_INTR_MASK_OUT);
|
||||||
|
@@ -3399,7 +3399,7 @@ __acquires(dev->lock)
|
||||||
|
writel(tmp, &dma->dmastat);
|
||||||
|
|
||||||
|
/* dma sync*/
|
||||||
|
- if (dev->quirks & PLX_SUPERSPEED) {
|
||||||
|
+ if (dev->quirks & PLX_PCIE) {
|
||||||
|
u32 r_dmacount = readl(&dma->dmacount);
|
||||||
|
if (!ep->is_in && (r_dmacount & 0x00FFFFFF) &&
|
||||||
|
(tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT)))
|
||||||
|
@@ -3468,7 +3468,7 @@ static irqreturn_t net2280_irq(int irq, void *_dev)
|
||||||
|
/* control requests and PIO */
|
||||||
|
handle_stat0_irqs(dev, readl(&dev->regs->irqstat0));
|
||||||
|
|
||||||
|
- if (dev->quirks & PLX_SUPERSPEED) {
|
||||||
|
+ if (dev->quirks & PLX_PCIE) {
|
||||||
|
/* re-enable interrupt to trigger any possible new interrupt */
|
||||||
|
u32 pciirqenb1 = readl(&dev->regs->pciirqenb1);
|
||||||
|
writel(pciirqenb1 & 0x7FFFFFFF, &dev->regs->pciirqenb1);
|
||||||
|
@@ -3513,7 +3513,7 @@ static void net2280_remove(struct pci_dev *pdev)
|
||||||
|
}
|
||||||
|
if (dev->got_irq)
|
||||||
|
free_irq(pdev->irq, dev);
|
||||||
|
- if (dev->quirks & PLX_SUPERSPEED)
|
||||||
|
+ if (dev->quirks & PLX_PCIE)
|
||||||
|
pci_disable_msi(pdev);
|
||||||
|
if (dev->regs)
|
||||||
|
iounmap(dev->regs);
|
||||||
|
@@ -3593,7 +3593,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
|
dev->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
|
||||||
|
dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
|
||||||
|
|
||||||
|
- if (dev->quirks & PLX_SUPERSPEED) {
|
||||||
|
+ if (dev->quirks & PLX_PCIE) {
|
||||||
|
u32 fsmvalue;
|
||||||
|
u32 usbstat;
|
||||||
|
dev->usb_ext = (struct usb338x_usb_ext_regs __iomem *)
|
||||||
|
@@ -3637,7 +3637,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
|
||||||
|
goto done;
|
||||||
|
}
|
||||||
|
|
||||||
|
- if (dev->quirks & PLX_SUPERSPEED)
|
||||||
|
+ if (dev->quirks & PLX_PCIE)
|
||||||
|
if (pci_enable_msi(pdev))
|
||||||
|
ep_err(dev, "Failed to enable MSI mode\n");
|
||||||
|
|
||||||
|
@@ -3755,10 +3755,19 @@ static const struct pci_device_id pci_ids[] = { {
|
||||||
|
.class = PCI_CLASS_SERIAL_USB_DEVICE,
|
||||||
|
.class_mask = ~0,
|
||||||
|
.vendor = PCI_VENDOR_ID_PLX,
|
||||||
|
+ .device = 0x2380,
|
||||||
|
+ .subvendor = PCI_ANY_ID,
|
||||||
|
+ .subdevice = PCI_ANY_ID,
|
||||||
|
+ .driver_data = PLX_PCIE,
|
||||||
|
+ },
|
||||||
|
+ {
|
||||||
|
+ .class = ((PCI_CLASS_SERIAL_USB << 8) | 0xfe),
|
||||||
|
+ .class_mask = ~0,
|
||||||
|
+ .vendor = PCI_VENDOR_ID_PLX,
|
||||||
|
.device = 0x3380,
|
||||||
|
.subvendor = PCI_ANY_ID,
|
||||||
|
.subdevice = PCI_ANY_ID,
|
||||||
|
- .driver_data = PLX_SUPERSPEED,
|
||||||
|
+ .driver_data = PLX_PCIE | PLX_SUPERSPEED,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.class = PCI_CLASS_SERIAL_USB_DEVICE,
|
||||||
|
@@ -3767,7 +3776,7 @@ static const struct pci_device_id pci_ids[] = { {
|
||||||
|
.device = 0x3382,
|
||||||
|
.subvendor = PCI_ANY_ID,
|
||||||
|
.subdevice = PCI_ANY_ID,
|
||||||
|
- .driver_data = PLX_SUPERSPEED,
|
||||||
|
+ .driver_data = PLX_PCIE | PLX_SUPERSPEED,
|
||||||
|
},
|
||||||
|
{ /* end: all zeroes */ }
|
||||||
|
};
|
||||||
|
diff --git a/drivers/usb/gadget/udc/net2280.h b/drivers/usb/gadget/udc/net2280.h
|
||||||
|
index 0d32052..2736a95 100644
|
||||||
|
--- a/drivers/usb/gadget/udc/net2280.h
|
||||||
|
+++ b/drivers/usb/gadget/udc/net2280.h
|
||||||
|
@@ -47,6 +47,7 @@ set_idx_reg(struct net2280_regs __iomem *regs, u32 index, u32 value)
|
||||||
|
#define PLX_LEGACY BIT(0)
|
||||||
|
#define PLX_2280 BIT(1)
|
||||||
|
#define PLX_SUPERSPEED BIT(2)
|
||||||
|
+#define PLX_PCIE BIT(3)
|
||||||
|
|
||||||
|
#define REG_DIAG 0x0
|
||||||
|
#define RETRY_COUNTER 16
|
||||||
|
--
|
||||||
|
1.9.1
|
||||||
|
|
Loading…
Reference in a new issue