.. | .. |
---|
52 | 52 | #include <linux/usb/gadget.h> |
---|
53 | 53 | #include <linux/prefetch.h> |
---|
54 | 54 | #include <linux/io.h> |
---|
| 55 | +#include <linux/iopoll.h> |
---|
55 | 56 | |
---|
56 | 57 | #include <asm/byteorder.h> |
---|
57 | 58 | #include <asm/irq.h> |
---|
.. | .. |
---|
360 | 361 | static int handshake(u32 __iomem *ptr, u32 mask, u32 done, int usec) |
---|
361 | 362 | { |
---|
362 | 363 | u32 result; |
---|
| 364 | + int ret; |
---|
363 | 365 | |
---|
364 | | - do { |
---|
365 | | - result = readl(ptr); |
---|
366 | | - if (result == ~(u32)0) /* "device unplugged" */ |
---|
367 | | - return -ENODEV; |
---|
368 | | - result &= mask; |
---|
369 | | - if (result == done) |
---|
370 | | - return 0; |
---|
371 | | - udelay(1); |
---|
372 | | - usec--; |
---|
373 | | - } while (usec > 0); |
---|
374 | | - return -ETIMEDOUT; |
---|
| 366 | + ret = readl_poll_timeout_atomic(ptr, result, |
---|
| 367 | + ((result & mask) == done || |
---|
| 368 | + result == U32_MAX), |
---|
| 369 | + 1, usec); |
---|
| 370 | + if (result == U32_MAX) /* device unplugged */ |
---|
| 371 | + return -ENODEV; |
---|
| 372 | + |
---|
| 373 | + return ret; |
---|
375 | 374 | } |
---|
376 | 375 | |
---|
377 | 376 | static const struct usb_ep_ops net2280_ep_ops; |
---|
.. | .. |
---|
516 | 515 | unsigned long flags; |
---|
517 | 516 | |
---|
518 | 517 | ep = container_of(_ep, struct net2280_ep, ep); |
---|
519 | | - if (!_ep || !ep->desc || _ep->name == ep0name) { |
---|
520 | | - pr_err("%s: Invalid ep=%p or ep->desc\n", __func__, _ep); |
---|
| 518 | + if (!_ep || _ep->name == ep0name) { |
---|
| 519 | + pr_err("%s: Invalid ep=%p\n", __func__, _ep); |
---|
521 | 520 | return -EINVAL; |
---|
522 | 521 | } |
---|
523 | 522 | spin_lock_irqsave(&ep->dev->lock, flags); |
---|
.. | .. |
---|
789 | 788 | (void) readl(&ep->regs->ep_rsp); |
---|
790 | 789 | } |
---|
791 | 790 | |
---|
792 | | - return is_short || ((req->req.actual == req->req.length) && |
---|
793 | | - !req->req.zero); |
---|
| 791 | + return is_short || req->req.actual == req->req.length; |
---|
794 | 792 | } |
---|
795 | 793 | |
---|
796 | 794 | /* fill out dma descriptor to match a given request */ |
---|
.. | .. |
---|
1058 | 1056 | /* PIO ... stuff the fifo, or unblock it. */ |
---|
1059 | 1057 | if (ep->is_in) |
---|
1060 | 1058 | write_fifo(ep, _req); |
---|
1061 | | - else if (list_empty(&ep->queue)) { |
---|
| 1059 | + else { |
---|
1062 | 1060 | u32 s; |
---|
1063 | 1061 | |
---|
1064 | 1062 | /* OUT FIFO might have packet(s) buffered */ |
---|
.. | .. |
---|
1547 | 1545 | } |
---|
1548 | 1546 | |
---|
1549 | 1547 | spin_unlock_irqrestore(&dev->lock, flags); |
---|
1550 | | - |
---|
1551 | | - if (!is_on && dev->driver) |
---|
1552 | | - dev->driver->disconnect(&dev->gadget); |
---|
1553 | 1548 | |
---|
1554 | 1549 | return 0; |
---|
1555 | 1550 | } |
---|
.. | .. |
---|
2248 | 2243 | } |
---|
2249 | 2244 | |
---|
2250 | 2245 | /* Hardware Defect and Workaround */ |
---|
2251 | | - val = readl(&dev->ll_lfps_regs->ll_lfps_5); |
---|
| 2246 | + val = readl(&dev->llregs->ll_lfps_5); |
---|
2252 | 2247 | val &= ~(0xf << TIMER_LFPS_6US); |
---|
2253 | 2248 | val |= 0x5 << TIMER_LFPS_6US; |
---|
2254 | | - writel(val, &dev->ll_lfps_regs->ll_lfps_5); |
---|
| 2249 | + writel(val, &dev->llregs->ll_lfps_5); |
---|
2255 | 2250 | |
---|
2256 | | - val = readl(&dev->ll_lfps_regs->ll_lfps_6); |
---|
| 2251 | + val = readl(&dev->llregs->ll_lfps_6); |
---|
2257 | 2252 | val &= ~(0xffff << TIMER_LFPS_80US); |
---|
2258 | 2253 | val |= 0x0100 << TIMER_LFPS_80US; |
---|
2259 | | - writel(val, &dev->ll_lfps_regs->ll_lfps_6); |
---|
| 2254 | + writel(val, &dev->llregs->ll_lfps_6); |
---|
2260 | 2255 | |
---|
2261 | 2256 | /* |
---|
2262 | 2257 | * AA_AB Errata. Issue 4. Workaround for SuperSpeed USB |
---|
2263 | 2258 | * Hot Reset Exit Handshake may Fail in Specific Case using |
---|
2264 | 2259 | * Default Register Settings. Workaround for Enumeration test. |
---|
2265 | 2260 | */ |
---|
2266 | | - val = readl(&dev->ll_tsn_regs->ll_tsn_counters_2); |
---|
| 2261 | + val = readl(&dev->llregs->ll_tsn_counters_2); |
---|
2267 | 2262 | val &= ~(0x1f << HOT_TX_NORESET_TS2); |
---|
2268 | 2263 | val |= 0x10 << HOT_TX_NORESET_TS2; |
---|
2269 | | - writel(val, &dev->ll_tsn_regs->ll_tsn_counters_2); |
---|
| 2264 | + writel(val, &dev->llregs->ll_tsn_counters_2); |
---|
2270 | 2265 | |
---|
2271 | | - val = readl(&dev->ll_tsn_regs->ll_tsn_counters_3); |
---|
| 2266 | + val = readl(&dev->llregs->ll_tsn_counters_3); |
---|
2272 | 2267 | val &= ~(0x1f << HOT_RX_RESET_TS2); |
---|
2273 | 2268 | val |= 0x3 << HOT_RX_RESET_TS2; |
---|
2274 | | - writel(val, &dev->ll_tsn_regs->ll_tsn_counters_3); |
---|
| 2269 | + writel(val, &dev->llregs->ll_tsn_counters_3); |
---|
| 2270 | + |
---|
| 2271 | + /* |
---|
| 2272 | + * AB errata. Errata 11. Workaround for Default Duration of LFPS |
---|
| 2273 | + * Handshake Signaling for Device-Initiated U1 Exit is too short. |
---|
| 2274 | + * Without this, various enumeration failures observed with |
---|
| 2275 | + * modern superspeed hosts. |
---|
| 2276 | + */ |
---|
| 2277 | + val = readl(&dev->llregs->ll_lfps_timers_2); |
---|
| 2278 | + writel((val & 0xffff0000) | LFPS_TIMERS_2_WORKAROUND_VALUE, |
---|
| 2279 | + &dev->llregs->ll_lfps_timers_2); |
---|
2275 | 2280 | |
---|
2276 | 2281 | /* |
---|
2277 | 2282 | * Set Recovery Idle to Recover bit: |
---|
.. | .. |
---|
2281 | 2286 | * - R-M-W to leave other bits undisturbed. |
---|
2282 | 2287 | * - Reference PLX TT-7372 |
---|
2283 | 2288 | */ |
---|
2284 | | - val = readl(&dev->ll_chicken_reg->ll_tsn_chicken_bit); |
---|
| 2289 | + val = readl(&dev->llregs->ll_tsn_chicken_bit); |
---|
2285 | 2290 | val |= BIT(RECOVERY_IDLE_TO_RECOVER_FMW); |
---|
2286 | | - writel(val, &dev->ll_chicken_reg->ll_tsn_chicken_bit); |
---|
| 2291 | + writel(val, &dev->llregs->ll_tsn_chicken_bit); |
---|
2287 | 2292 | |
---|
2288 | 2293 | INIT_LIST_HEAD(&dev->gadget.ep0->ep_list); |
---|
2289 | 2294 | |
---|
.. | .. |
---|
2855 | 2860 | static void handle_stat0_irqs_superspeed(struct net2280 *dev, |
---|
2856 | 2861 | struct net2280_ep *ep, struct usb_ctrlrequest r) |
---|
2857 | 2862 | { |
---|
| 2863 | + struct net2280_ep *e; |
---|
| 2864 | + u16 status; |
---|
2858 | 2865 | int tmp = 0; |
---|
2859 | 2866 | |
---|
2860 | 2867 | #define w_value le16_to_cpu(r.wValue) |
---|
.. | .. |
---|
2862 | 2869 | #define w_length le16_to_cpu(r.wLength) |
---|
2863 | 2870 | |
---|
2864 | 2871 | switch (r.bRequest) { |
---|
2865 | | - struct net2280_ep *e; |
---|
2866 | | - u16 status; |
---|
2867 | | - |
---|
2868 | 2872 | case USB_REQ_SET_CONFIGURATION: |
---|
2869 | 2873 | dev->addressed_state = !w_value; |
---|
2870 | 2874 | goto usb3_delegate; |
---|
.. | .. |
---|
3556 | 3560 | |
---|
3557 | 3561 | static void gadget_release(struct device *_dev) |
---|
3558 | 3562 | { |
---|
3559 | | - struct net2280 *dev = dev_get_drvdata(_dev); |
---|
| 3563 | + struct net2280 *dev = container_of(_dev, struct net2280, gadget.dev); |
---|
3560 | 3564 | |
---|
3561 | 3565 | kfree(dev); |
---|
3562 | 3566 | } |
---|
.. | .. |
---|
3567 | 3571 | { |
---|
3568 | 3572 | struct net2280 *dev = pci_get_drvdata(pdev); |
---|
3569 | 3573 | |
---|
3570 | | - usb_del_gadget_udc(&dev->gadget); |
---|
| 3574 | + if (dev->added) |
---|
| 3575 | + usb_del_gadget(&dev->gadget); |
---|
3571 | 3576 | |
---|
3572 | 3577 | BUG_ON(dev->driver); |
---|
3573 | 3578 | |
---|
.. | .. |
---|
3598 | 3603 | device_remove_file(&pdev->dev, &dev_attr_registers); |
---|
3599 | 3604 | |
---|
3600 | 3605 | ep_info(dev, "unbind\n"); |
---|
| 3606 | + usb_put_gadget(&dev->gadget); |
---|
3601 | 3607 | } |
---|
3602 | 3608 | |
---|
3603 | 3609 | /* wrap this driver around the specified device, but |
---|
.. | .. |
---|
3619 | 3625 | } |
---|
3620 | 3626 | |
---|
3621 | 3627 | pci_set_drvdata(pdev, dev); |
---|
| 3628 | + usb_initialize_gadget(&pdev->dev, &dev->gadget, gadget_release); |
---|
3622 | 3629 | spin_lock_init(&dev->lock); |
---|
3623 | 3630 | dev->quirks = id->driver_data; |
---|
3624 | 3631 | dev->pdev = pdev; |
---|
.. | .. |
---|
3653 | 3660 | * 8051 code into the chip, e.g. to turn on PCI PM. |
---|
3654 | 3661 | */ |
---|
3655 | 3662 | |
---|
3656 | | - base = ioremap_nocache(resource, len); |
---|
| 3663 | + base = ioremap(resource, len); |
---|
3657 | 3664 | if (base == NULL) { |
---|
3658 | 3665 | ep_dbg(dev, "can't map memory\n"); |
---|
3659 | 3666 | retval = -EFAULT; |
---|
.. | .. |
---|
3673 | 3680 | (base + 0x00b4); |
---|
3674 | 3681 | dev->llregs = (struct usb338x_ll_regs __iomem *) |
---|
3675 | 3682 | (base + 0x0700); |
---|
3676 | | - dev->ll_lfps_regs = (struct usb338x_ll_lfps_regs __iomem *) |
---|
3677 | | - (base + 0x0748); |
---|
3678 | | - dev->ll_tsn_regs = (struct usb338x_ll_tsn_regs __iomem *) |
---|
3679 | | - (base + 0x077c); |
---|
3680 | | - dev->ll_chicken_reg = (struct usb338x_ll_chi_regs __iomem *) |
---|
3681 | | - (base + 0x079c); |
---|
3682 | 3683 | dev->plregs = (struct usb338x_pl_regs __iomem *) |
---|
3683 | 3684 | (base + 0x0800); |
---|
3684 | 3685 | usbstat = readl(&dev->usb->usbstat); |
---|
.. | .. |
---|
3775 | 3776 | if (retval) |
---|
3776 | 3777 | goto done; |
---|
3777 | 3778 | |
---|
3778 | | - retval = usb_add_gadget_udc_release(&pdev->dev, &dev->gadget, |
---|
3779 | | - gadget_release); |
---|
| 3779 | + retval = usb_add_gadget(&dev->gadget); |
---|
3780 | 3780 | if (retval) |
---|
3781 | 3781 | goto done; |
---|
| 3782 | + dev->added = 1; |
---|
3782 | 3783 | return 0; |
---|
3783 | 3784 | |
---|
3784 | 3785 | done: |
---|
.. | .. |
---|
3859 | 3860 | |
---|
3860 | 3861 | /* pci driver glue; this is a "new style" PCI driver module */ |
---|
3861 | 3862 | static struct pci_driver net2280_pci_driver = { |
---|
3862 | | - .name = (char *) driver_name, |
---|
| 3863 | + .name = driver_name, |
---|
3863 | 3864 | .id_table = pci_ids, |
---|
3864 | 3865 | |
---|
3865 | 3866 | .probe = net2280_probe, |
---|