aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMathias Nyman <mathias.nyman@linux.intel.com>2015-10-01 11:40:34 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-10-04 05:34:17 -0400
commit47189098f8bebe4d937945df70d3ca8e6c0b3e4d (patch)
treed2e3d2ae95da94fcbc65fd7beb758ca0e2dffdb3
parent3220befddc0da1f4e09fc790a32a9bd8427e8889 (diff)
xhci: parse xhci protocol speed ID list for usb 3.1 usage
xhci 1.1 controllers that support USB 3.1 must provide a protocol speed ID (PSI) list to inform the driver of the supported speeds. The PSI list can be read from the xhci supported protocol extended capabilities. The PSI values will be used to create a USB 3.1 SuperSpeedPlus capability descriptor for the xhci USB 3.1 roothub. Signed-off-by: Mathias Nyman <mathias.nyman@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r--drivers/usb/host/xhci-mem.c38
-rw-r--r--drivers/usb/host/xhci.h24
2 files changed, 61 insertions, 1 deletions
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index 41f841fa6c4d..bc540903542a 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -2072,14 +2072,23 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
2072{ 2072{
2073 u32 temp, port_offset, port_count; 2073 u32 temp, port_offset, port_count;
2074 int i; 2074 int i;
2075 struct xhci_hub *rhub;
2075 2076
2076 if (major_revision > 0x03) { 2077 temp = readl(addr);
2078
2079 if (XHCI_EXT_PORT_MAJOR(temp) == 0x03) {
2080 rhub = &xhci->usb3_rhub;
2081 } else if (XHCI_EXT_PORT_MAJOR(temp) <= 0x02) {
2082 rhub = &xhci->usb2_rhub;
2083 } else {
2077 xhci_warn(xhci, "Ignoring unknown port speed, " 2084 xhci_warn(xhci, "Ignoring unknown port speed, "
2078 "Ext Cap %p, revision = 0x%x\n", 2085 "Ext Cap %p, revision = 0x%x\n",
2079 addr, major_revision); 2086 addr, major_revision);
2080 /* Ignoring port protocol we can't understand. FIXME */ 2087 /* Ignoring port protocol we can't understand. FIXME */
2081 return; 2088 return;
2082 } 2089 }
2090 rhub->maj_rev = XHCI_EXT_PORT_MAJOR(temp);
2091 rhub->min_rev = XHCI_EXT_PORT_MINOR(temp);
2083 2092
2084 /* Port offset and count in the third dword, see section 7.2 */ 2093 /* Port offset and count in the third dword, see section 7.2 */
2085 temp = readl(addr + 2); 2094 temp = readl(addr + 2);
@@ -2094,6 +2103,33 @@ static void xhci_add_in_port(struct xhci_hcd *xhci, unsigned int num_ports,
2094 /* WTF? "Valid values are ‘1’ to MaxPorts" */ 2103 /* WTF? "Valid values are ‘1’ to MaxPorts" */
2095 return; 2104 return;
2096 2105
2106 rhub->psi_count = XHCI_EXT_PORT_PSIC(temp);
2107 if (rhub->psi_count) {
2108 rhub->psi = kcalloc(rhub->psi_count, sizeof(*rhub->psi),
2109 GFP_KERNEL);
2110 if (!rhub->psi)
2111 rhub->psi_count = 0;
2112
2113 rhub->psi_uid_count++;
2114 for (i = 0; i < rhub->psi_count; i++) {
2115 rhub->psi[i] = readl(addr + 4 + i);
2116
2117 /* count unique ID values, two consecutive entries can
2118 * have the same ID if link is assymetric
2119 */
2120 if (i && (XHCI_EXT_PORT_PSIV(rhub->psi[i]) !=
2121 XHCI_EXT_PORT_PSIV(rhub->psi[i - 1])))
2122 rhub->psi_uid_count++;
2123
2124 xhci_dbg(xhci, "PSIV:%d PSIE:%d PLT:%d PFD:%d LP:%d PSIM:%d\n",
2125 XHCI_EXT_PORT_PSIV(rhub->psi[i]),
2126 XHCI_EXT_PORT_PSIE(rhub->psi[i]),
2127 XHCI_EXT_PORT_PLT(rhub->psi[i]),
2128 XHCI_EXT_PORT_PFD(rhub->psi[i]),
2129 XHCI_EXT_PORT_LP(rhub->psi[i]),
2130 XHCI_EXT_PORT_PSIM(rhub->psi[i]));
2131 }
2132 }
2097 /* cache usb2 port capabilities */ 2133 /* cache usb2 port capabilities */
2098 if (major_revision < 0x03 && xhci->num_ext_caps < max_caps) 2134 if (major_revision < 0x03 && xhci->num_ext_caps < max_caps)
2099 xhci->ext_caps[xhci->num_ext_caps++] = temp; 2135 xhci->ext_caps[xhci->num_ext_caps++] = temp;
diff --git a/drivers/usb/host/xhci.h b/drivers/usb/host/xhci.h
index 17d4d4408637..cd4a6e795329 100644
--- a/drivers/usb/host/xhci.h
+++ b/drivers/usb/host/xhci.h
@@ -540,9 +540,23 @@ struct xhci_protocol_caps {
540}; 540};
541 541
542#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff) 542#define XHCI_EXT_PORT_MAJOR(x) (((x) >> 24) & 0xff)
543#define XHCI_EXT_PORT_MINOR(x) (((x) >> 16) & 0xff)
544#define XHCI_EXT_PORT_PSIC(x) (((x) >> 28) & 0x0f)
543#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff) 545#define XHCI_EXT_PORT_OFF(x) ((x) & 0xff)
544#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff) 546#define XHCI_EXT_PORT_COUNT(x) (((x) >> 8) & 0xff)
545 547
548#define XHCI_EXT_PORT_PSIV(x) (((x) >> 0) & 0x0f)
549#define XHCI_EXT_PORT_PSIE(x) (((x) >> 4) & 0x03)
550#define XHCI_EXT_PORT_PLT(x) (((x) >> 6) & 0x03)
551#define XHCI_EXT_PORT_PFD(x) (((x) >> 8) & 0x01)
552#define XHCI_EXT_PORT_LP(x) (((x) >> 14) & 0x03)
553#define XHCI_EXT_PORT_PSIM(x) (((x) >> 16) & 0xffff)
554
555#define PLT_MASK (0x03 << 6)
556#define PLT_SYM (0x00 << 6)
557#define PLT_ASYM_RX (0x02 << 6)
558#define PLT_ASYM_TX (0x03 << 6)
559
546/** 560/**
547 * struct xhci_container_ctx 561 * struct xhci_container_ctx
548 * @type: Type of context. Used to calculated offsets to contained contexts. 562 * @type: Type of context. Used to calculated offsets to contained contexts.
@@ -1469,6 +1483,14 @@ static inline unsigned int hcd_index(struct usb_hcd *hcd)
1469 return 1; 1483 return 1;
1470} 1484}
1471 1485
1486struct xhci_hub {
1487 u8 maj_rev;
1488 u8 min_rev;
1489 u32 *psi; /* array of protocol speed ID entries */
1490 u8 psi_count;
1491 u8 psi_uid_count;
1492};
1493
1472/* There is one xhci_hcd structure per controller */ 1494/* There is one xhci_hcd structure per controller */
1473struct xhci_hcd { 1495struct xhci_hcd {
1474 struct usb_hcd *main_hcd; 1496 struct usb_hcd *main_hcd;
@@ -1608,6 +1630,8 @@ struct xhci_hcd {
1608 unsigned int num_usb3_ports; 1630 unsigned int num_usb3_ports;
1609 /* Array of pointers to USB 2.0 PORTSC registers */ 1631 /* Array of pointers to USB 2.0 PORTSC registers */
1610 __le32 __iomem **usb2_ports; 1632 __le32 __iomem **usb2_ports;
1633 struct xhci_hub usb2_rhub;
1634 struct xhci_hub usb3_rhub;
1611 unsigned int num_usb2_ports; 1635 unsigned int num_usb2_ports;
1612 /* support xHCI 0.96 spec USB2 software LPM */ 1636 /* support xHCI 0.96 spec USB2 software LPM */
1613 unsigned sw_lpm_support:1; 1637 unsigned sw_lpm_support:1;