These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / usb / host / xhci-pci.c
index 2af32e2..c2d6520 100644 (file)
 #include <linux/pci.h>
 #include <linux/slab.h>
 #include <linux/module.h>
+#include <linux/acpi.h>
 
 #include "xhci.h"
 #include "xhci-trace.h"
 
+#define SSIC_PORT_NUM          2
+#define SSIC_PORT_CFG2         0x880c
+#define SSIC_PORT_CFG2_OFFSET  0x30
+#define PROG_DONE              (1 << 30)
+#define SSIC_PORT_UNUSED       (1 << 31)
+
 /* Device for a quirk */
 #define PCI_VENDOR_ID_FRESCO_LOGIC     0x1b73
 #define PCI_DEVICE_ID_FRESCO_LOGIC_PDK 0x1000
 #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
+#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI             0x0aa8
 
 static const char hcd_name[] = "xhci_hcd";
 
 static struct hc_driver __read_mostly xhci_pci_hc_driver;
 
+static int xhci_pci_setup(struct usb_hcd *hcd);
+
+static const struct xhci_driver_overrides xhci_pci_overrides __initconst = {
+       .extra_priv_size = sizeof(struct xhci_hcd),
+       .reset = xhci_pci_setup,
+};
+
 /* called after powerup, by probe or system-pm "wakeup" */
 static int xhci_pci_reinit(struct xhci_hcd *xhci, struct pci_dev *pdev)
 {
@@ -135,11 +150,13 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
        if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
                pdev->device == PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_XHCI) {
                xhci->quirks |= XHCI_SPURIOUS_REBOOT;
+               xhci->quirks |= XHCI_SPURIOUS_WAKEUP;
        }
        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)) {
+                pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+                pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) {
                xhci->quirks |= XHCI_PME_STUCK_QUIRK;
        }
        if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
@@ -168,20 +185,22 @@ 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)
+#ifdef CONFIG_ACPI
+static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev)
 {
-       u32 val;
-       void __iomem *reg;
-
-       reg = (void __iomem *) xhci->cap_regs + 0x80a4;
-       val = readl(reg);
-       writel(val | BIT(28), reg);
-       readl(reg);
+       static const u8 intel_dsm_uuid[] = {
+               0xb7, 0x0c, 0x34, 0xac, 0x01, 0xe9, 0xbf, 0x45,
+               0xb7, 0xe6, 0x2b, 0x34, 0xec, 0x93, 0x1e, 0x23,
+       };
+       union acpi_object *obj;
+
+       obj = acpi_evaluate_dsm(ACPI_HANDLE(&dev->dev), intel_dsm_uuid, 3, 1,
+                               NULL);
+       ACPI_FREE(obj);
 }
+#else
+static void xhci_pme_acpi_rtd3_enable(struct pci_dev *dev) { }
+#endif /* CONFIG_ACPI */
 
 /* called during probe() after chip reset completes */
 static int xhci_pci_setup(struct usb_hcd *hcd)
@@ -190,15 +209,17 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
        int                     retval;
 
+       xhci = hcd_to_xhci(hcd);
+       if (!xhci->sbrn)
+               pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
+
        retval = xhci_gen_setup(hcd, xhci_pci_quirks);
        if (retval)
                return retval;
 
-       xhci = hcd_to_xhci(hcd);
        if (!usb_hcd_is_primary_hcd(hcd))
                return 0;
 
-       pci_read_config_byte(pdev, XHCI_SBRN_OFFSET, &xhci->sbrn);
        xhci_dbg(xhci, "Got SBRN %u\n", (unsigned int) xhci->sbrn);
 
        /* Find any debug ports */
@@ -206,7 +227,6 @@ static int xhci_pci_setup(struct usb_hcd *hcd)
        if (!retval)
                return retval;
 
-       kfree(xhci);
        return retval;
 }
 
@@ -247,11 +267,6 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                goto dealloc_usb2_hcd;
        }
 
-       /* Set the xHCI pointer before xhci_pci_setup() (aka hcd_driver.reset)
-        * is called by usb_add_hcd().
-        */
-       *((struct xhci_hcd **) xhci->shared_hcd->hcd_priv) = xhci;
-
        retval = usb_add_hcd(xhci->shared_hcd, dev->irq,
                        IRQF_SHARED);
        if (retval)
@@ -262,6 +277,9 @@ static int xhci_pci_probe(struct pci_dev *dev, const struct pci_device_id *id)
                        HCC_MAX_PSA(xhci->hcc_params) >= 4)
                xhci->shared_hcd->can_do_streams = 1;
 
+       if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
+               xhci_pme_acpi_rtd3_enable(dev);
+
        /* USB-2 and USB-3 roothubs initialized, allow runtime pm suspend */
        pm_runtime_put_noidle(&dev->dev);
 
@@ -290,11 +308,62 @@ static void xhci_pci_remove(struct pci_dev *dev)
        /* Workaround for spurious wakeups at shutdown with HSW */
        if (xhci->quirks & XHCI_SPURIOUS_WAKEUP)
                pci_set_power_state(dev, PCI_D3hot);
-
-       kfree(xhci);
 }
 
 #ifdef CONFIG_PM
+/*
+ * In some Intel xHCI controllers, in order to get D3 working,
+ * through a vendor specific SSIC CONFIG register at offset 0x883c,
+ * SSIC PORT need to be marked as "unused" before putting xHCI
+ * into D3. After D3 exit, the SSIC port need to be marked as "used".
+ * Without this change, xHCI might not enter D3 state.
+ * 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 usb_hcd *hcd, bool suspend)
+{
+       struct xhci_hcd *xhci = hcd_to_xhci(hcd);
+       struct pci_dev          *pdev = to_pci_dev(hcd->self.controller);
+       u32 val;
+       void __iomem *reg;
+       int i;
+
+       if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
+                pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
+
+               for (i = 0; i < SSIC_PORT_NUM; i++) {
+                       reg = (void __iomem *) xhci->cap_regs +
+                                       SSIC_PORT_CFG2 +
+                                       i * SSIC_PORT_CFG2_OFFSET;
+
+                       /*
+                        * Notify SSIC that SSIC profile programming
+                        * is not done.
+                        */
+                       val = readl(reg) & ~PROG_DONE;
+                       writel(val, reg);
+
+                       /* Mark SSIC port as unused(suspend) or used(resume) */
+                       val = readl(reg);
+                       if (suspend)
+                               val |= SSIC_PORT_UNUSED;
+                       else
+                               val &= ~SSIC_PORT_UNUSED;
+                       writel(val, reg);
+
+                       /* Notify SSIC that SSIC profile programming is done */
+                       val = readl(reg) | PROG_DONE;
+                       writel(val, reg);
+                       readl(reg);
+               }
+       }
+
+       reg = (void __iomem *) xhci->cap_regs + 0x80a4;
+       val = readl(reg);
+       writel(val | BIT(28), reg);
+       readl(reg);
+}
+
 static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
@@ -308,7 +377,7 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
                pdev->no_d3cold = true;
 
        if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
-               xhci_pme_quirk(xhci);
+               xhci_pme_quirk(hcd, true);
 
        return xhci_suspend(xhci, do_wakeup);
 }
@@ -341,7 +410,7 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
                usb_enable_intel_xhci_ports(pdev);
 
        if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
-               xhci_pme_quirk(xhci);
+               xhci_pme_quirk(hcd, false);
 
        retval = xhci_resume(xhci, hibernated);
        return retval;
@@ -379,7 +448,7 @@ static struct pci_driver xhci_pci_driver = {
 
 static int __init xhci_pci_init(void)
 {
-       xhci_init_driver(&xhci_pci_hc_driver, xhci_pci_setup);
+       xhci_init_driver(&xhci_pci_hc_driver, &xhci_pci_overrides);
 #ifdef CONFIG_PM
        xhci_pci_hc_driver.pci_suspend = xhci_pci_suspend;
        xhci_pci_hc_driver.pci_resume = xhci_pci_resume;