xHCI: Check host USB2 LPM capability
authorAndiry Xu <andiry.xu@amd.com>
Fri, 23 Sep 2011 21:19:51 +0000 (14:19 -0700)
committerGreg Kroah-Hartman <gregkh@suse.de>
Mon, 26 Sep 2011 22:51:09 +0000 (15:51 -0700)
Check the host's USB2 LPM capability.

USB2 software LPM support is optional for xHCI 0.96 hosts. xHCI 1.0 hosts
should support software LPM, and may support hardware LPM.

Signed-off-by: Andiry Xu <andiry.xu@amd.com>
Signed-off-by: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
drivers/usb/host/xhci-ext-caps.h
drivers/usb/host/xhci-mem.c
drivers/usb/host/xhci.h

index ce5c9e51748e7632dd3480428675fc4d73fce004..c7f33123d4c08e59954d5ac8d561f9cd6e3c9fef 100644 (file)
 /* bits 1:2, 5:12, and 17:19 need to be preserved; bits 21:28 should be zero */
 #define        XHCI_LEGACY_DISABLE_SMI         ((0x3 << 1) + (0xff << 5) + (0x7 << 17))
 
+/* USB 2.0 xHCI 0.96 L1C capability - section 7.2.2.1.3.2 */
+#define XHCI_L1C               (1 << 16)
+
+/* USB 2.0 xHCI 1.0 hardware LMP capability - section 7.2.2.1.3.2 */
+#define XHCI_HLC               (1 << 19)
+
 /* command register values to disable interrupts and halt the HC */
 /* start/stop HC execution - do not write unless HC is halted*/
 #define XHCI_CMD_RUN           (1 << 0)
index bc6ec0cb3c6189cfd56969986b186cbf510e2068..9c7ddf0f3a4362d9d6d7e0ef73c870113d1cd727 100644 (file)
@@ -1959,6 +1959,23 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
        if (port_offset == 0 || (port_offset + port_count - 1) > num_ports)
                /* WTF? "Valid values are ‘1’ to MaxPorts" */
                return;
+
+       /* Check the host's USB2 LPM capability */
+       if ((xhci->hci_version == 0x96) && (major_revision != 0x03) &&
+                       (temp & XHCI_L1C)) {
+               xhci_dbg(xhci, "xHCI 0.96: support USB2 software lpm\n");
+               xhci->sw_lpm_support = 1;
+       }
+
+       if ((xhci->hci_version >= 0x100) && (major_revision != 0x03)) {
+               xhci_dbg(xhci, "xHCI 1.0: support USB2 software lpm\n");
+               xhci->sw_lpm_support = 1;
+               if (temp & XHCI_HLC) {
+                       xhci_dbg(xhci, "xHCI 1.0: support USB2 hardware lpm\n");
+                       xhci->hw_lpm_support = 1;
+               }
+       }
+
        port_offset--;
        for (i = port_offset; i < (port_offset + port_count); i++) {
                /* Duplicate entry.  Ignore the port if the revisions differ. */
index fa921cbbe87271d2e71c01a792ed24cf4ea6e037..8673f985046ed79a926052994994bdbec02545f9 100644 (file)
@@ -1459,6 +1459,10 @@ struct xhci_hcd {
        /* Array of pointers to USB 2.0 PORTSC registers */
        __le32 __iomem          **usb2_ports;
        unsigned int            num_usb2_ports;
+       /* support xHCI 0.96 spec USB2 software LPM */
+       unsigned                sw_lpm_support:1;
+       /* support xHCI 1.0 spec USB2 hardware LPM */
+       unsigned                hw_lpm_support:1;
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */