summaryrefslogtreecommitdiff
path: root/drivers/usb/host/xhci-pci.c
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2015-04-03 13:38:43 -0700
committerOlof Johansson <olof@lixom.net>2015-04-03 13:38:43 -0700
commit47f36e4921ae11dccf3163f75f70bb55686780f1 (patch)
tree770560b54cbf2f3b8ae64aa5f202d25aa6c33c56 /drivers/usb/host/xhci-pci.c
parent63fad06a2733f78f7565a436a97848aee8099600 (diff)
parent874c571414d5617f4042298986b6a826816ee885 (diff)
Merge tag 'arm-perf-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux into next/drivers
Merge "arm-cci PMU updates for 4.1" from Will Deacon: CCI-400 PMU updates This series reworks some of the CCI-400 PMU code so that it can be used on both ARM and ARM64-based systems, without the need to boot in secure mode on the latter. This paves the way for CCI-500 support in future. * tag 'arm-perf-4.1' of git://git.kernel.org/pub/scm/linux/kernel/git/will/linux: arm-cci: Fix CCI PMU event validation arm-cci: Split the code for PMU vs driver support arm-cci: Get rid of secure transactions for PMU driver arm-cci: Abstract the CCI400 PMU specific definitions arm-cci: Rearrange code for splitting PMU vs driver code drivers: cci: reject groups spanning multiple HW PMUs + Linux 4.0-rc4 Signed-off-by: Olof Johansson <olof@lixom.net>
Diffstat (limited to 'drivers/usb/host/xhci-pci.c')
-rw-r--r--drivers/usb/host/xhci-pci.c30
1 files changed, 30 insertions, 0 deletions
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index 7f76c8a12f89..fd53c9ebd662 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -37,6 +37,9 @@
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_XHCI 0x8c31
#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI 0x9c31
+#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
+#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
+#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f
static const char hcd_name[] = "xhci_hcd";
@@ -133,6 +136,12 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
xhci->quirks |= XHCI_SPURIOUS_REBOOT;
}
+ if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+ (pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
+ xhci->quirks |= XHCI_PME_STUCK_QUIRK;
+ }
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
pdev->device == PCI_DEVICE_ID_EJ168) {
xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -159,6 +168,21 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
"QUIRK: Resetting on resume");
}
+/*
+ * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
+ * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
+ */
+static void xhci_pme_quirk(struct xhci_hcd *xhci)
+{
+ u32 val;
+ void __iomem *reg;
+
+ reg = (void __iomem *) xhci->cap_regs + 0x80a4;
+ val = readl(reg);
+ writel(val | BIT(28), reg);
+ readl(reg);
+}
+
/* called during probe() after chip reset completes */
static int xhci_pci_setup(struct usb_hcd *hcd)
{
@@ -283,6 +307,9 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
pdev->no_d3cold = true;
+ if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+ xhci_pme_quirk(xhci);
+
return xhci_suspend(xhci, do_wakeup);
}
@@ -313,6 +340,9 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
usb_enable_intel_xhci_ports(pdev);
+ if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+ xhci_pme_quirk(xhci);
+
retval = xhci_resume(xhci, hibernated);
return retval;
}