Commit fa895377 authored by Lu Baolu's avatar Lu Baolu Committed by Greg Kroah-Hartman

usb: xhci: handle both SSIC ports in PME stuck quirk

Commit abce329c ("xhci: Workaround to get D3 working in Intel xHCI")
adds a workaround for a limitation of PME storm caused by SSIC port in
some Intel SoCs. This commit only handled one SSIC port, while there
are actually two SSIC ports in the chips. This patch handles both SSIC
ports. Without this fix, users still see PME storm.

Cc: stable@vger.kernel.org # v4.2+
Signed-off-by: default avatarZhuang Jin Can <jin.can.zhuang@intel.com>
Signed-off-by: default avatarLu Baolu <baolu.lu@linux.intel.com>
Signed-off-by: default avatarMathias Nyman <mathias.nyman@linux.intel.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent a6835090
...@@ -28,7 +28,9 @@ ...@@ -28,7 +28,9 @@
#include "xhci.h" #include "xhci.h"
#include "xhci-trace.h" #include "xhci-trace.h"
#define PORT2_SSIC_CONFIG_REG2 0x883c #define SSIC_PORT_NUM 2
#define SSIC_PORT_CFG2 0x880c
#define SSIC_PORT_CFG2_OFFSET 0x30
#define PROG_DONE (1 << 30) #define PROG_DONE (1 << 30)
#define SSIC_PORT_UNUSED (1 << 31) #define SSIC_PORT_UNUSED (1 << 31)
...@@ -321,28 +323,36 @@ static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend) ...@@ -321,28 +323,36 @@ static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
struct pci_dev *pdev = to_pci_dev(hcd->self.controller); struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
u32 val; u32 val;
void __iomem *reg; void __iomem *reg;
int i;
if (pdev->vendor == PCI_VENDOR_ID_INTEL && if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) { pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2; for (i = 0; i < SSIC_PORT_NUM; i++) {
reg = (void __iomem *) xhci->cap_regs +
/* Notify SSIC that SSIC profile programming is not done */ SSIC_PORT_CFG2 +
val = readl(reg) & ~PROG_DONE; i * SSIC_PORT_CFG2_OFFSET;
writel(val, reg);
/*
/* Mark SSIC port as unused(suspend) or used(resume) */ * Notify SSIC that SSIC profile programming
val = readl(reg); * is not done.
if (suspend) */
val |= SSIC_PORT_UNUSED; val = readl(reg) & ~PROG_DONE;
else writel(val, reg);
val &= ~SSIC_PORT_UNUSED;
writel(val, reg); /* Mark SSIC port as unused(suspend) or used(resume) */
val = readl(reg);
/* Notify SSIC that SSIC profile programming is done */ if (suspend)
val = readl(reg) | PROG_DONE; val |= SSIC_PORT_UNUSED;
writel(val, reg); else
readl(reg); 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; reg = (void __iomem *) xhci->cap_regs + 0x80a4;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment