Commit 5185c913 authored by Tim Harvey's avatar Tim Harvey Committed by Felipe Balbi

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: default avatarTim Harvey <tharvey@gateworks.com>
Signed-off-by: default avatarFelipe Balbi <felipe.balbi@linux.intel.com>
parent d8877fc7
...@@ -312,7 +312,7 @@ config USB_NET2272_DMA ...@@ -312,7 +312,7 @@ config USB_NET2272_DMA
If unsure, say "N" here. The driver works fine in PIO mode. If unsure, say "N" here. The driver works fine in PIO mode.
config USB_NET2280 config USB_NET2280
tristate "NetChip 228x / PLX USB338x" tristate "NetChip NET228x / PLX USB3x8x"
depends on PCI depends on PCI
help help
NetChip 2280 / 2282 is a PCI based USB peripheral controller which NetChip 2280 / 2282 is a PCI based USB peripheral controller which
...@@ -322,6 +322,8 @@ config USB_NET2280 ...@@ -322,6 +322,8 @@ config USB_NET2280
(for control transfers) and several endpoints with dedicated (for control transfers) and several endpoints with dedicated
functions. functions.
PLX 2380 is a PCIe version of the PLX 2380.
PLX 3380 / 3382 is a PCIe based USB peripheral controller which PLX 3380 / 3382 is a PCIe based USB peripheral controller which
supports full, high speed USB 2.0 and super speed USB 3.0 supports full, high speed USB 2.0 and super speed USB 3.0
data transfers. data transfers.
......
...@@ -211,7 +211,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -211,7 +211,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
goto print_err; goto print_err;
} }
if (dev->quirks & PLX_SUPERSPEED) { if (dev->quirks & PLX_PCIE) {
if ((desc->bEndpointAddress & 0x0f) >= 0x0c) { if ((desc->bEndpointAddress & 0x0f) >= 0x0c) {
ret = -EDOM; ret = -EDOM;
goto print_err; goto print_err;
...@@ -245,7 +245,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc) ...@@ -245,7 +245,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *desc)
/* set type, direction, address; reset fifo counters */ /* set type, direction, address; reset fifo counters */
writel(BIT(FIFO_FLUSH), &ep->regs->ep_stat); 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); tmp = readl(&ep->cfg->ep_cfg);
/* If USB ep number doesn't match hardware ep number */ /* If USB ep number doesn't match hardware ep number */
if ((tmp & 0xf) != usb_endpoint_num(desc)) { if ((tmp & 0xf) != usb_endpoint_num(desc)) {
...@@ -316,7 +316,7 @@ net2280_enable(struct usb_ep *_ep, const struct usb_endpoint_descriptor *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); BIT(CLEAR_NAK_OUT_PACKETS_MODE), &ep->regs->ep_rsp);
} }
if (dev->quirks & PLX_SUPERSPEED) if (dev->quirks & PLX_PCIE)
ep_clear_seqnum(ep); ep_clear_seqnum(ep);
writel(tmp, &ep->cfg->ep_cfg); writel(tmp, &ep->cfg->ep_cfg);
...@@ -527,7 +527,7 @@ static int net2280_disable(struct usb_ep *_ep) ...@@ -527,7 +527,7 @@ static int net2280_disable(struct usb_ep *_ep)
spin_lock_irqsave(&ep->dev->lock, flags); spin_lock_irqsave(&ep->dev->lock, flags);
nuke(ep); nuke(ep);
if (ep->dev->quirks & PLX_SUPERSPEED) if (ep->dev->quirks & PLX_PCIE)
ep_reset_338x(ep->dev->regs, ep); ep_reset_338x(ep->dev->regs, ep);
else else
ep_reset_228x(ep->dev->regs, ep); ep_reset_228x(ep->dev->regs, ep);
...@@ -862,7 +862,7 @@ static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma) ...@@ -862,7 +862,7 @@ static void start_queue(struct net2280_ep *ep, u32 dmactl, u32 td_dma)
writel(readl(&dma->dmastat), &dma->dmastat); writel(readl(&dma->dmastat), &dma->dmastat);
writel(td_dma, &dma->dmadesc); writel(td_dma, &dma->dmadesc);
if (ep->dev->quirks & PLX_SUPERSPEED) if (ep->dev->quirks & PLX_PCIE)
dmactl |= BIT(DMA_REQUEST_OUTSTANDING); dmactl |= BIT(DMA_REQUEST_OUTSTANDING);
writel(dmactl, &dma->dmactl); writel(dmactl, &dma->dmactl);
...@@ -1046,7 +1046,7 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags) ...@@ -1046,7 +1046,7 @@ net2280_queue(struct usb_ep *_ep, struct usb_request *_req, gfp_t gfp_flags)
/* kickstart this i/o queue? */ /* kickstart this i/o queue? */
if (list_empty(&ep->queue) && !ep->stopped && 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)))) { (readl(&ep->regs->ep_rsp) & BIT(CLEAR_ENDPOINT_HALT)))) {
/* use DMA if the endpoint supports it, else pio */ /* use DMA if the endpoint supports it, else pio */
...@@ -1169,7 +1169,7 @@ static void scan_dma_completions(struct net2280_ep *ep) ...@@ -1169,7 +1169,7 @@ static void scan_dma_completions(struct net2280_ep *ep)
break; break;
} else if (!ep->is_in && } else if (!ep->is_in &&
(req->req.length % ep->ep.maxpacket) && (req->req.length % ep->ep.maxpacket) &&
!(ep->dev->quirks & PLX_SUPERSPEED)) { !(ep->dev->quirks & PLX_PCIE)) {
tmp = readl(&ep->regs->ep_stat); tmp = readl(&ep->regs->ep_stat);
/* AVOID TROUBLE HERE by not issuing short reads from /* 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) ...@@ -1367,7 +1367,7 @@ net2280_set_halt_and_wedge(struct usb_ep *_ep, int value, int wedged)
ep->wedged = 1; ep->wedged = 1;
} else { } else {
clear_halt(ep); clear_halt(ep);
if (ep->dev->quirks & PLX_SUPERSPEED && if (ep->dev->quirks & PLX_PCIE &&
!list_empty(&ep->queue) && ep->td_dma) !list_empty(&ep->queue) && ep->td_dma)
restart_dma(ep); restart_dma(ep);
ep->wedged = 0; ep->wedged = 0;
...@@ -2394,7 +2394,7 @@ static int net2280_start(struct usb_gadget *_gadget, ...@@ -2394,7 +2394,7 @@ static int net2280_start(struct usb_gadget *_gadget,
*/ */
net2280_led_active(dev, 1); 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); defect7374_enable_data_eps_zero(dev);
ep0_start(dev); ep0_start(dev);
...@@ -3063,7 +3063,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) ...@@ -3063,7 +3063,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
} }
ep->stopped = 0; ep->stopped = 0;
dev->protocol_stall = 0; dev->protocol_stall = 0;
if (!(dev->quirks & PLX_SUPERSPEED)) { if (!(dev->quirks & PLX_PCIE)) {
if (ep->dev->quirks & PLX_2280) if (ep->dev->quirks & PLX_2280)
tmp = BIT(FIFO_OVERFLOW) | tmp = BIT(FIFO_OVERFLOW) |
BIT(FIFO_UNDERFLOW); BIT(FIFO_UNDERFLOW);
...@@ -3090,7 +3090,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) ...@@ -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[0]);
cpu_to_le32s(&u.raw[1]); 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); defect7374_workaround(dev, u.r);
tmp = 0; tmp = 0;
...@@ -3173,7 +3173,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) ...@@ -3173,7 +3173,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
} else { } else {
ep_vdbg(dev, "%s clear halt\n", e->ep.name); ep_vdbg(dev, "%s clear halt\n", e->ep.name);
clear_halt(e); clear_halt(e);
if ((ep->dev->quirks & PLX_SUPERSPEED) && if ((ep->dev->quirks & PLX_PCIE) &&
!list_empty(&e->queue) && e->td_dma) !list_empty(&e->queue) && e->td_dma)
restart_dma(e); restart_dma(e);
} }
...@@ -3195,7 +3195,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) ...@@ -3195,7 +3195,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
if (e->ep.name == ep0name) if (e->ep.name == ep0name)
goto do_stall; goto do_stall;
set_halt(e); set_halt(e);
if ((dev->quirks & PLX_SUPERSPEED) && e->dma) if ((dev->quirks & PLX_PCIE) && e->dma)
abort_dma(e); abort_dma(e);
allow_status(ep); allow_status(ep);
ep_vdbg(dev, "%s set halt\n", ep->ep.name); ep_vdbg(dev, "%s set halt\n", ep->ep.name);
...@@ -3234,7 +3234,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat) ...@@ -3234,7 +3234,7 @@ static void handle_stat0_irqs(struct net2280 *dev, u32 stat)
#undef w_length #undef w_length
next_endpoints: next_endpoints:
if ((dev->quirks & PLX_SUPERSPEED) && dev->enhanced_mode) { if ((dev->quirks & PLX_PCIE) && dev->enhanced_mode) {
u32 mask = (BIT(ENDPOINT_0_INTERRUPT) | u32 mask = (BIT(ENDPOINT_0_INTERRUPT) |
USB3380_IRQSTAT0_EP_INTR_MASK_IN | USB3380_IRQSTAT0_EP_INTR_MASK_IN |
USB3380_IRQSTAT0_EP_INTR_MASK_OUT); USB3380_IRQSTAT0_EP_INTR_MASK_OUT);
...@@ -3399,7 +3399,7 @@ __acquires(dev->lock) ...@@ -3399,7 +3399,7 @@ __acquires(dev->lock)
writel(tmp, &dma->dmastat); writel(tmp, &dma->dmastat);
/* dma sync*/ /* dma sync*/
if (dev->quirks & PLX_SUPERSPEED) { if (dev->quirks & PLX_PCIE) {
u32 r_dmacount = readl(&dma->dmacount); u32 r_dmacount = readl(&dma->dmacount);
if (!ep->is_in && (r_dmacount & 0x00FFFFFF) && if (!ep->is_in && (r_dmacount & 0x00FFFFFF) &&
(tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT))) (tmp & BIT(DMA_TRANSACTION_DONE_INTERRUPT)))
...@@ -3468,7 +3468,7 @@ static irqreturn_t net2280_irq(int irq, void *_dev) ...@@ -3468,7 +3468,7 @@ static irqreturn_t net2280_irq(int irq, void *_dev)
/* control requests and PIO */ /* control requests and PIO */
handle_stat0_irqs(dev, readl(&dev->regs->irqstat0)); 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 */ /* re-enable interrupt to trigger any possible new interrupt */
u32 pciirqenb1 = readl(&dev->regs->pciirqenb1); u32 pciirqenb1 = readl(&dev->regs->pciirqenb1);
writel(pciirqenb1 & 0x7FFFFFFF, &dev->regs->pciirqenb1); writel(pciirqenb1 & 0x7FFFFFFF, &dev->regs->pciirqenb1);
...@@ -3513,7 +3513,7 @@ static void net2280_remove(struct pci_dev *pdev) ...@@ -3513,7 +3513,7 @@ static void net2280_remove(struct pci_dev *pdev)
} }
if (dev->got_irq) if (dev->got_irq)
free_irq(pdev->irq, dev); free_irq(pdev->irq, dev);
if (dev->quirks & PLX_SUPERSPEED) if (dev->quirks & PLX_PCIE)
pci_disable_msi(pdev); pci_disable_msi(pdev);
if (dev->regs) if (dev->regs)
iounmap(dev->regs); iounmap(dev->regs);
...@@ -3593,7 +3593,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -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->dep = (struct net2280_dep_regs __iomem *) (base + 0x0200);
dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300); dev->epregs = (struct net2280_ep_regs __iomem *) (base + 0x0300);
if (dev->quirks & PLX_SUPERSPEED) { if (dev->quirks & PLX_PCIE) {
u32 fsmvalue; u32 fsmvalue;
u32 usbstat; u32 usbstat;
dev->usb_ext = (struct usb338x_usb_ext_regs __iomem *) 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) ...@@ -3637,7 +3637,7 @@ static int net2280_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto done; goto done;
} }
if (dev->quirks & PLX_SUPERSPEED) if (dev->quirks & PLX_PCIE)
if (pci_enable_msi(pdev)) if (pci_enable_msi(pdev))
ep_err(dev, "Failed to enable MSI mode\n"); ep_err(dev, "Failed to enable MSI mode\n");
...@@ -3755,10 +3755,19 @@ static const struct pci_device_id pci_ids[] = { { ...@@ -3755,10 +3755,19 @@ static const struct pci_device_id pci_ids[] = { {
.class = PCI_CLASS_SERIAL_USB_DEVICE, .class = PCI_CLASS_SERIAL_USB_DEVICE,
.class_mask = ~0, .class_mask = ~0,
.vendor = PCI_VENDOR_ID_PLX, .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, .device = 0x3380,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = PLX_SUPERSPEED, .driver_data = PLX_PCIE | PLX_SUPERSPEED,
}, },
{ {
.class = PCI_CLASS_SERIAL_USB_DEVICE, .class = PCI_CLASS_SERIAL_USB_DEVICE,
...@@ -3767,7 +3776,7 @@ static const struct pci_device_id pci_ids[] = { { ...@@ -3767,7 +3776,7 @@ static const struct pci_device_id pci_ids[] = { {
.device = 0x3382, .device = 0x3382,
.subvendor = PCI_ANY_ID, .subvendor = PCI_ANY_ID,
.subdevice = PCI_ANY_ID, .subdevice = PCI_ANY_ID,
.driver_data = PLX_SUPERSPEED, .driver_data = PLX_PCIE | PLX_SUPERSPEED,
}, },
{ /* end: all zeroes */ } { /* end: all zeroes */ }
}; };
......
...@@ -47,6 +47,7 @@ set_idx_reg(struct net2280_regs __iomem *regs, u32 index, u32 value) ...@@ -47,6 +47,7 @@ set_idx_reg(struct net2280_regs __iomem *regs, u32 index, u32 value)
#define PLX_LEGACY BIT(0) #define PLX_LEGACY BIT(0)
#define PLX_2280 BIT(1) #define PLX_2280 BIT(1)
#define PLX_SUPERSPEED BIT(2) #define PLX_SUPERSPEED BIT(2)
#define PLX_PCIE BIT(3)
#define REG_DIAG 0x0 #define REG_DIAG 0x0
#define RETRY_COUNTER 16 #define RETRY_COUNTER 16
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment