From 232893037a9c77bf7e880bd2f2c33b7df620d6e4 Mon Sep 17 00:00:00 2001 From: Tim Harvey Date: Thu, 1 Sep 2016 07:55:15 -0700 Subject: [PATCH] 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 --- package/kernel/linux/modules/usb.mk | 17 ++ ...dget-udc-net2280-add-usb2380-support.patch | 262 ++++++++++++++++++ 2 files changed, 279 insertions(+) create mode 100644 target/linux/generic/patches-4.4/160-usb-gadget-udc-net2280-add-usb2380-support.patch diff --git a/package/kernel/linux/modules/usb.mk b/package/kernel/linux/modules/usb.mk index a36993e483..52c28c9110 100644 --- a/package/kernel/linux/modules/usb.mk +++ b/package/kernel/linux/modules/usb.mk @@ -1626,3 +1626,20 @@ define KernelPackage/usb3/description endef $(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)) + diff --git a/target/linux/generic/patches-4.4/160-usb-gadget-udc-net2280-add-usb2380-support.patch b/target/linux/generic/patches-4.4/160-usb-gadget-udc-net2280-add-usb2380-support.patch new file mode 100644 index 0000000000..edb8fcf705 --- /dev/null +++ b/target/linux/generic/patches-4.4/160-usb-gadget-udc-net2280-add-usb2380-support.patch @@ -0,0 +1,262 @@ +From 5185c91385d73cdf79836eb8548e4726e43ae831 Mon Sep 17 00:00:00 2001 +From: Tim Harvey +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 +Signed-off-by: Tim Harvey +Signed-off-by: Felipe Balbi +--- + 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 +