aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/xhci-hub.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 06:23:15 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-25 06:23:15 -0400
commit1be025d3cb40cd295123af2c394f7229ef9b30ca (patch)
tree5dc14e1ea412cc7fdc3e563ad23187059fe8bfb5 /drivers/usb/host/xhci-hub.c
parent2d03423b2319cc854adeb28a03f65de5b5e0ab63 (diff)
parenta2c76b83fdd763c826f38a55127ccf25708099ce (diff)
Merge branch 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb
* 'usb-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb: (260 commits) usb: renesas_usbhs: fixup inconsistent return from usbhs_pkt_push() usb/isp1760: Allow to optionally trigger low-level chip reset via GPIOLIB. USB: gadget: midi: memory leak in f_midi_bind_config() USB: gadget: midi: fix range check in f_midi_out_open() QE/FHCI: fixed the CONTROL bug usb: renesas_usbhs: tidyup for smatch warnings USB: Fix USB Kconfig dependency problem on 85xx/QoirQ platforms EHCI: workaround for MosChip controller bug usb: gadget: file_storage: fix race on unloading USB: ftdi_sio.c: Use ftdi async_icount structure for TIOCMIWAIT, as in other drivers USB: ftdi_sio.c:Fill MSR fields of the ftdi async_icount structure USB: ftdi_sio.c: Fill LSR fields of the ftdi async_icount structure USB: ftdi_sio.c:Fill TX field of the ftdi async_icount structure USB: ftdi_sio.c: Fill the RX field of the ftdi async_icount structure USB: ftdi_sio.c: Basic icount infrastructure for ftdi_sio usb/isp1760: Let OF bindings depend on general CONFIG_OF instead of PPC_OF . USB: ftdi_sio: Support TI/Luminary Micro Stellaris BD-ICDI Board USB: Fix runtime wakeup on OHCI xHCI/USB: Make xHCI driver have a BOS descriptor. usb: gadget: add new usb gadget for ACM and mass storage ...
Diffstat (limited to 'drivers/usb/host/xhci-hub.c')
-rw-r--r--drivers/usb/host/xhci-hub.c139
1 files changed, 89 insertions, 50 deletions
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index 723f8231193d..431efe72b1f7 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -28,6 +28,25 @@
28#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \ 28#define PORT_RWC_BITS (PORT_CSC | PORT_PEC | PORT_WRC | PORT_OCC | \
29 PORT_RC | PORT_PLC | PORT_PE) 29 PORT_RC | PORT_PLC | PORT_PE)
30 30
31/* usb 1.1 root hub device descriptor */
32static u8 usb_bos_descriptor [] = {
33 USB_DT_BOS_SIZE, /* __u8 bLength, 5 bytes */
34 USB_DT_BOS, /* __u8 bDescriptorType */
35 0x0F, 0x00, /* __le16 wTotalLength, 15 bytes */
36 0x1, /* __u8 bNumDeviceCaps */
37 /* First device capability */
38 USB_DT_USB_SS_CAP_SIZE, /* __u8 bLength, 10 bytes */
39 USB_DT_DEVICE_CAPABILITY, /* Device Capability */
40 USB_SS_CAP_TYPE, /* bDevCapabilityType, SUPERSPEED_USB */
41 0x00, /* bmAttributes, LTM off by default */
42 USB_5GBPS_OPERATION, 0x00, /* wSpeedsSupported, 5Gbps only */
43 0x03, /* bFunctionalitySupport,
44 USB 3.0 speed only */
45 0x00, /* bU1DevExitLat, set later. */
46 0x00, 0x00 /* __le16 bU2DevExitLat, set later. */
47};
48
49
31static void xhci_common_hub_descriptor(struct xhci_hcd *xhci, 50static void xhci_common_hub_descriptor(struct xhci_hcd *xhci,
32 struct usb_hub_descriptor *desc, int ports) 51 struct usb_hub_descriptor *desc, int ports)
33{ 52{
@@ -232,7 +251,7 @@ int xhci_find_slot_id_by_port(struct usb_hcd *hcd, struct xhci_hcd *xhci,
232 continue; 251 continue;
233 speed = xhci->devs[i]->udev->speed; 252 speed = xhci->devs[i]->udev->speed;
234 if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3)) 253 if (((speed == USB_SPEED_SUPER) == (hcd->speed == HCD_USB3))
235 && xhci->devs[i]->port == port) { 254 && xhci->devs[i]->fake_port == port) {
236 slot_id = i; 255 slot_id = i;
237 break; 256 break;
238 } 257 }
@@ -392,13 +411,39 @@ static int xhci_get_ports(struct usb_hcd *hcd, __le32 __iomem ***port_array)
392 return max_ports; 411 return max_ports;
393} 412}
394 413
414void xhci_set_link_state(struct xhci_hcd *xhci, __le32 __iomem **port_array,
415 int port_id, u32 link_state)
416{
417 u32 temp;
418
419 temp = xhci_readl(xhci, port_array[port_id]);
420 temp = xhci_port_state_to_neutral(temp);
421 temp &= ~PORT_PLS_MASK;
422 temp |= PORT_LINK_STROBE | link_state;
423 xhci_writel(xhci, temp, port_array[port_id]);
424}
425
426/* Test and clear port RWC bit */
427void xhci_test_and_clear_bit(struct xhci_hcd *xhci, __le32 __iomem **port_array,
428 int port_id, u32 port_bit)
429{
430 u32 temp;
431
432 temp = xhci_readl(xhci, port_array[port_id]);
433 if (temp & port_bit) {
434 temp = xhci_port_state_to_neutral(temp);
435 temp |= port_bit;
436 xhci_writel(xhci, temp, port_array[port_id]);
437 }
438}
439
395int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, 440int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
396 u16 wIndex, char *buf, u16 wLength) 441 u16 wIndex, char *buf, u16 wLength)
397{ 442{
398 struct xhci_hcd *xhci = hcd_to_xhci(hcd); 443 struct xhci_hcd *xhci = hcd_to_xhci(hcd);
399 int max_ports; 444 int max_ports;
400 unsigned long flags; 445 unsigned long flags;
401 u32 temp, temp1, status; 446 u32 temp, status;
402 int retval = 0; 447 int retval = 0;
403 __le32 __iomem **port_array; 448 __le32 __iomem **port_array;
404 int slot_id; 449 int slot_id;
@@ -429,6 +474,21 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
429 xhci_hub_descriptor(hcd, xhci, 474 xhci_hub_descriptor(hcd, xhci,
430 (struct usb_hub_descriptor *) buf); 475 (struct usb_hub_descriptor *) buf);
431 break; 476 break;
477 case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
478 if ((wValue & 0xff00) != (USB_DT_BOS << 8))
479 goto error;
480
481 if (hcd->speed != HCD_USB3)
482 goto error;
483
484 memcpy(buf, &usb_bos_descriptor,
485 USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE);
486 temp = xhci_readl(xhci, &xhci->cap_regs->hcs_params3);
487 buf[12] = HCS_U1_LATENCY(temp);
488 put_unaligned_le16(HCS_U2_LATENCY(temp), &buf[13]);
489
490 spin_unlock_irqrestore(&xhci->lock, flags);
491 return USB_DT_BOS_SIZE + USB_DT_USB_SS_CAP_SIZE;
432 case GetPortStatus: 492 case GetPortStatus:
433 if (!wIndex || wIndex > max_ports) 493 if (!wIndex || wIndex > max_ports)
434 goto error; 494 goto error;
@@ -472,11 +532,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
472 xhci_dbg(xhci, "Resume USB2 port %d\n", 532 xhci_dbg(xhci, "Resume USB2 port %d\n",
473 wIndex + 1); 533 wIndex + 1);
474 bus_state->resume_done[wIndex] = 0; 534 bus_state->resume_done[wIndex] = 0;
475 temp1 = xhci_port_state_to_neutral(temp); 535 xhci_set_link_state(xhci, port_array, wIndex,
476 temp1 &= ~PORT_PLS_MASK; 536 XDEV_U0);
477 temp1 |= PORT_LINK_STROBE | XDEV_U0;
478 xhci_writel(xhci, temp1, port_array[wIndex]);
479
480 xhci_dbg(xhci, "set port %d resume\n", 537 xhci_dbg(xhci, "set port %d resume\n",
481 wIndex + 1); 538 wIndex + 1);
482 slot_id = xhci_find_slot_id_by_port(hcd, xhci, 539 slot_id = xhci_find_slot_id_by_port(hcd, xhci,
@@ -551,10 +608,19 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
551 switch (wValue) { 608 switch (wValue) {
552 case USB_PORT_FEAT_SUSPEND: 609 case USB_PORT_FEAT_SUSPEND:
553 temp = xhci_readl(xhci, port_array[wIndex]); 610 temp = xhci_readl(xhci, port_array[wIndex]);
611 if ((temp & PORT_PLS_MASK) != XDEV_U0) {
612 /* Resume the port to U0 first */
613 xhci_set_link_state(xhci, port_array, wIndex,
614 XDEV_U0);
615 spin_unlock_irqrestore(&xhci->lock, flags);
616 msleep(10);
617 spin_lock_irqsave(&xhci->lock, flags);
618 }
554 /* In spec software should not attempt to suspend 619 /* In spec software should not attempt to suspend
555 * a port unless the port reports that it is in the 620 * a port unless the port reports that it is in the
556 * enabled (PED = ‘1’,PLS < ‘3’) state. 621 * enabled (PED = ‘1’,PLS < ‘3’) state.
557 */ 622 */
623 temp = xhci_readl(xhci, port_array[wIndex]);
558 if ((temp & PORT_PE) == 0 || (temp & PORT_RESET) 624 if ((temp & PORT_PE) == 0 || (temp & PORT_RESET)
559 || (temp & PORT_PLS_MASK) >= XDEV_U3) { 625 || (temp & PORT_PLS_MASK) >= XDEV_U3) {
560 xhci_warn(xhci, "USB core suspending device " 626 xhci_warn(xhci, "USB core suspending device "
@@ -573,10 +639,7 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
573 xhci_stop_device(xhci, slot_id, 1); 639 xhci_stop_device(xhci, slot_id, 1);
574 spin_lock_irqsave(&xhci->lock, flags); 640 spin_lock_irqsave(&xhci->lock, flags);
575 641
576 temp = xhci_port_state_to_neutral(temp); 642 xhci_set_link_state(xhci, port_array, wIndex, XDEV_U3);
577 temp &= ~PORT_PLS_MASK;
578 temp |= PORT_LINK_STROBE | XDEV_U3;
579 xhci_writel(xhci, temp, port_array[wIndex]);
580 643
581 spin_unlock_irqrestore(&xhci->lock, flags); 644 spin_unlock_irqrestore(&xhci->lock, flags);
582 msleep(10); /* wait device to enter */ 645 msleep(10); /* wait device to enter */
@@ -610,10 +673,8 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
610 } 673 }
611 } 674 }
612 675
613 temp = xhci_port_state_to_neutral(temp); 676 xhci_set_link_state(xhci, port_array, wIndex,
614 temp &= ~PORT_PLS_MASK; 677 link_state);
615 temp |= PORT_LINK_STROBE | link_state;
616 xhci_writel(xhci, temp, port_array[wIndex]);
617 678
618 spin_unlock_irqrestore(&xhci->lock, flags); 679 spin_unlock_irqrestore(&xhci->lock, flags);
619 msleep(20); /* wait device to enter */ 680 msleep(20); /* wait device to enter */
@@ -677,24 +738,13 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
677 if ((temp & PORT_PE) == 0) 738 if ((temp & PORT_PE) == 0)
678 goto error; 739 goto error;
679 740
680 temp = xhci_port_state_to_neutral(temp); 741 xhci_set_link_state(xhci, port_array, wIndex,
681 temp &= ~PORT_PLS_MASK; 742 XDEV_RESUME);
682 temp |= PORT_LINK_STROBE | XDEV_RESUME; 743 spin_unlock_irqrestore(&xhci->lock, flags);
683 xhci_writel(xhci, temp,
684 port_array[wIndex]);
685
686 spin_unlock_irqrestore(&xhci->lock,
687 flags);
688 msleep(20); 744 msleep(20);
689 spin_lock_irqsave(&xhci->lock, flags); 745 spin_lock_irqsave(&xhci->lock, flags);
690 746 xhci_set_link_state(xhci, port_array, wIndex,
691 temp = xhci_readl(xhci, 747 XDEV_U0);
692 port_array[wIndex]);
693 temp = xhci_port_state_to_neutral(temp);
694 temp &= ~PORT_PLS_MASK;
695 temp |= PORT_LINK_STROBE | XDEV_U0;
696 xhci_writel(xhci, temp,
697 port_array[wIndex]);
698 } 748 }
699 bus_state->port_c_suspend |= 1 << wIndex; 749 bus_state->port_c_suspend |= 1 << wIndex;
700 750
@@ -910,25 +960,18 @@ int xhci_bus_resume(struct usb_hcd *hcd)
910 if (test_bit(port_index, &bus_state->bus_suspended) && 960 if (test_bit(port_index, &bus_state->bus_suspended) &&
911 (temp & PORT_PLS_MASK)) { 961 (temp & PORT_PLS_MASK)) {
912 if (DEV_SUPERSPEED(temp)) { 962 if (DEV_SUPERSPEED(temp)) {
913 temp = xhci_port_state_to_neutral(temp); 963 xhci_set_link_state(xhci, port_array,
914 temp &= ~PORT_PLS_MASK; 964 port_index, XDEV_U0);
915 temp |= PORT_LINK_STROBE | XDEV_U0;
916 xhci_writel(xhci, temp, port_array[port_index]);
917 } else { 965 } else {
918 temp = xhci_port_state_to_neutral(temp); 966 xhci_set_link_state(xhci, port_array,
919 temp &= ~PORT_PLS_MASK; 967 port_index, XDEV_RESUME);
920 temp |= PORT_LINK_STROBE | XDEV_RESUME;
921 xhci_writel(xhci, temp, port_array[port_index]);
922 968
923 spin_unlock_irqrestore(&xhci->lock, flags); 969 spin_unlock_irqrestore(&xhci->lock, flags);
924 msleep(20); 970 msleep(20);
925 spin_lock_irqsave(&xhci->lock, flags); 971 spin_lock_irqsave(&xhci->lock, flags);
926 972
927 temp = xhci_readl(xhci, port_array[port_index]); 973 xhci_set_link_state(xhci, port_array,
928 temp = xhci_port_state_to_neutral(temp); 974 port_index, XDEV_U0);
929 temp &= ~PORT_PLS_MASK;
930 temp |= PORT_LINK_STROBE | XDEV_U0;
931 xhci_writel(xhci, temp, port_array[port_index]);
932 } 975 }
933 /* wait for the port to enter U0 and report port link 976 /* wait for the port to enter U0 and report port link
934 * state change. 977 * state change.
@@ -938,12 +981,8 @@ int xhci_bus_resume(struct usb_hcd *hcd)
938 spin_lock_irqsave(&xhci->lock, flags); 981 spin_lock_irqsave(&xhci->lock, flags);
939 982
940 /* Clear PLC */ 983 /* Clear PLC */
941 temp = xhci_readl(xhci, port_array[port_index]); 984 xhci_test_and_clear_bit(xhci, port_array, port_index,
942 if (temp & PORT_PLC) { 985 PORT_PLC);
943 temp = xhci_port_state_to_neutral(temp);
944 temp |= PORT_PLC;
945 xhci_writel(xhci, temp, port_array[port_index]);
946 }
947 986
948 slot_id = xhci_find_slot_id_by_port(hcd, 987 slot_id = xhci_find_slot_id_by_port(hcd,
949 xhci, port_index + 1); 988 xhci, port_index + 1);