aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r--drivers/usb/host/xhci.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 54cb762d15c8..b0649a4bd315 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -3539,6 +3539,187 @@ int xhci_address_device(struct usb_hcd *hcd, struct usb_device *udev)
3539 return 0; 3539 return 0;
3540} 3540}
3541 3541
3542#ifdef CONFIG_USB_SUSPEND
3543
3544/* BESL to HIRD Encoding array for USB2 LPM */
3545static int xhci_besl_encoding[16] = {125, 150, 200, 300, 400, 500, 1000, 2000,
3546 3000, 4000, 5000, 6000, 7000, 8000, 9000, 10000};
3547
3548/* Calculate HIRD/BESL for USB2 PORTPMSC*/
3549static int xhci_calculate_hird_besl(int u2del, bool use_besl)
3550{
3551 int hird;
3552
3553 if (use_besl) {
3554 for (hird = 0; hird < 16; hird++) {
3555 if (xhci_besl_encoding[hird] >= u2del)
3556 break;
3557 }
3558 } else {
3559 if (u2del <= 50)
3560 hird = 0;
3561 else
3562 hird = (u2del - 51) / 75 + 1;
3563
3564 if (hird > 15)
3565 hird = 15;
3566 }
3567
3568 return hird;
3569}
3570
3571static int xhci_usb2_software_lpm_test(struct usb_hcd *hcd,
3572 struct usb_device *udev)
3573{
3574 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
3575 struct dev_info *dev_info;
3576 __le32 __iomem **port_array;
3577 __le32 __iomem *addr, *pm_addr;
3578 u32 temp, dev_id;
3579 unsigned int port_num;
3580 unsigned long flags;
3581 int u2del, hird;
3582 int ret;
3583
3584 if (hcd->speed == HCD_USB3 || !xhci->sw_lpm_support ||
3585 !udev->lpm_capable)
3586 return -EINVAL;
3587
3588 /* we only support lpm for non-hub device connected to root hub yet */
3589 if (!udev->parent || udev->parent->parent ||
3590 udev->descriptor.bDeviceClass == USB_CLASS_HUB)
3591 return -EINVAL;
3592
3593 spin_lock_irqsave(&xhci->lock, flags);
3594
3595 /* Look for devices in lpm_failed_devs list */
3596 dev_id = le16_to_cpu(udev->descriptor.idVendor) << 16 |
3597 le16_to_cpu(udev->descriptor.idProduct);
3598 list_for_each_entry(dev_info, &xhci->lpm_failed_devs, list) {
3599 if (dev_info->dev_id == dev_id) {
3600 ret = -EINVAL;
3601 goto finish;
3602 }
3603 }
3604
3605 port_array = xhci->usb2_ports;
3606 port_num = udev->portnum - 1;
3607
3608 if (port_num > HCS_MAX_PORTS(xhci->hcs_params1)) {
3609 xhci_dbg(xhci, "invalid port number %d\n", udev->portnum);
3610 ret = -EINVAL;
3611 goto finish;
3612 }
3613
3614 /*
3615 * Test USB 2.0 software LPM.
3616 * FIXME: some xHCI 1.0 hosts may implement a new register to set up
3617 * hardware-controlled USB 2.0 LPM. See section 5.4.11 and 4.23.5.1.1.1
3618 * in the June 2011 errata release.
3619 */
3620 xhci_dbg(xhci, "test port %d software LPM\n", port_num);
3621 /*
3622 * Set L1 Device Slot and HIRD/BESL.
3623 * Check device's USB 2.0 extension descriptor to determine whether
3624 * HIRD or BESL shoule be used. See USB2.0 LPM errata.
3625 */
3626 pm_addr = port_array[port_num] + 1;
3627 u2del = HCS_U2_LATENCY(xhci->hcs_params3);
3628 if (le32_to_cpu(udev->bos->ext_cap->bmAttributes) & (1 << 2))
3629 hird = xhci_calculate_hird_besl(u2del, 1);
3630 else
3631 hird = xhci_calculate_hird_besl(u2del, 0);
3632
3633 temp = PORT_L1DS(udev->slot_id) | PORT_HIRD(hird);
3634 xhci_writel(xhci, temp, pm_addr);
3635
3636 /* Set port link state to U2(L1) */
3637 addr = port_array[port_num];
3638 xhci_set_link_state(xhci, port_array, port_num, XDEV_U2);
3639
3640 /* wait for ACK */
3641 spin_unlock_irqrestore(&xhci->lock, flags);
3642 msleep(10);
3643 spin_lock_irqsave(&xhci->lock, flags);
3644
3645 /* Check L1 Status */
3646 ret = handshake(xhci, pm_addr, PORT_L1S_MASK, PORT_L1S_SUCCESS, 125);
3647 if (ret != -ETIMEDOUT) {
3648 /* enter L1 successfully */
3649 temp = xhci_readl(xhci, addr);
3650 xhci_dbg(xhci, "port %d entered L1 state, port status 0x%x\n",
3651 port_num, temp);
3652 ret = 0;
3653 } else {
3654 temp = xhci_readl(xhci, pm_addr);
3655 xhci_dbg(xhci, "port %d software lpm failed, L1 status %d\n",
3656 port_num, temp & PORT_L1S_MASK);
3657 ret = -EINVAL;
3658 }
3659
3660 /* Resume the port */
3661 xhci_set_link_state(xhci, port_array, port_num, XDEV_U0);
3662
3663 spin_unlock_irqrestore(&xhci->lock, flags);
3664 msleep(10);
3665 spin_lock_irqsave(&xhci->lock, flags);
3666
3667 /* Clear PLC */
3668 xhci_test_and_clear_bit(xhci, port_array, port_num, PORT_PLC);
3669
3670 /* Check PORTSC to make sure the device is in the right state */
3671 if (!ret) {
3672 temp = xhci_readl(xhci, addr);
3673 xhci_dbg(xhci, "resumed port %d status 0x%x\n", port_num, temp);
3674 if (!(temp & PORT_CONNECT) || !(temp & PORT_PE) ||
3675 (temp & PORT_PLS_MASK) != XDEV_U0) {
3676 xhci_dbg(xhci, "port L1 resume fail\n");
3677 ret = -EINVAL;
3678 }
3679 }
3680
3681 if (ret) {
3682 /* Insert dev to lpm_failed_devs list */
3683 xhci_warn(xhci, "device LPM test failed, may disconnect and "
3684 "re-enumerate\n");
3685 dev_info = kzalloc(sizeof(struct dev_info), GFP_ATOMIC);
3686 if (!dev_info) {
3687 ret = -ENOMEM;
3688 goto finish;
3689 }
3690 dev_info->dev_id = dev_id;
3691 INIT_LIST_HEAD(&dev_info->list);
3692 list_add(&dev_info->list, &xhci->lpm_failed_devs);
3693 } else {
3694 xhci_ring_device(xhci, udev->slot_id);
3695 }
3696
3697finish:
3698 spin_unlock_irqrestore(&xhci->lock, flags);
3699 return ret;
3700}
3701
3702int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
3703{
3704 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
3705 int ret;
3706
3707 ret = xhci_usb2_software_lpm_test(hcd, udev);
3708 if (!ret)
3709 xhci_dbg(xhci, "software LPM test succeed\n");
3710
3711 return 0;
3712}
3713
3714#else
3715
3716int xhci_update_device(struct usb_hcd *hcd, struct usb_device *udev)
3717{
3718 return 0;
3719}
3720
3721#endif /* CONFIG_USB_SUSPEND */
3722
3542/* Once a hub descriptor is fetched for a device, we need to update the xHC's 3723/* Once a hub descriptor is fetched for a device, we need to update the xHC's
3543 * internal data structures for the device. 3724 * internal data structures for the device.
3544 */ 3725 */