Skip to content

Commit 7e70cbf

Browse files
LuBaolugregkh
authored andcommitted
usb: xhci: add a quirk bit for ssic port unused
Two workarounds introduced by commit b8cb91e ("xhci: Workaround for PME stuck issues in Intel xhci") and commit abce329 ("xhci: Workaround to get D3 working in Intel xHCI") share a single quirk bit XHCI_PME_STUCK_QUIRK. These two workarounds actually are different and might happen on different hardwares. Need to separate them by adding a quirk bit for the later. Cc: [email protected] Signed-off-by: Lu Baolu <[email protected]> Signed-off-by: Mathias Nyman <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent fa89537 commit 7e70cbf

File tree

2 files changed

+46
-34
lines changed

2 files changed

+46
-34
lines changed

drivers/usb/host/xhci-pci.c

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
156156
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
157157
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
158158
}
159+
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
160+
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
161+
xhci->quirks |= XHCI_SSIC_PORT_UNUSED;
162+
}
159163
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
160164
pdev->device == PCI_DEVICE_ID_EJ168) {
161165
xhci->quirks |= XHCI_RESET_ON_RESUME;
@@ -314,46 +318,47 @@ static void xhci_pci_remove(struct pci_dev *dev)
314318
* SSIC PORT need to be marked as "unused" before putting xHCI
315319
* into D3. After D3 exit, the SSIC port need to be marked as "used".
316320
* Without this change, xHCI might not enter D3 state.
317-
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
318-
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
319321
*/
320-
static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
322+
static void xhci_ssic_port_unused_quirk(struct usb_hcd *hcd, bool suspend)
321323
{
322324
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
323-
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
324325
u32 val;
325326
void __iomem *reg;
326327
int i;
327328

328-
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
329-
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
330-
331-
for (i = 0; i < SSIC_PORT_NUM; i++) {
332-
reg = (void __iomem *) xhci->cap_regs +
333-
SSIC_PORT_CFG2 +
334-
i * SSIC_PORT_CFG2_OFFSET;
335-
336-
/*
337-
* Notify SSIC that SSIC profile programming
338-
* is not done.
339-
*/
340-
val = readl(reg) & ~PROG_DONE;
341-
writel(val, reg);
342-
343-
/* Mark SSIC port as unused(suspend) or used(resume) */
344-
val = readl(reg);
345-
if (suspend)
346-
val |= SSIC_PORT_UNUSED;
347-
else
348-
val &= ~SSIC_PORT_UNUSED;
349-
writel(val, reg);
350-
351-
/* Notify SSIC that SSIC profile programming is done */
352-
val = readl(reg) | PROG_DONE;
353-
writel(val, reg);
354-
readl(reg);
355-
}
329+
for (i = 0; i < SSIC_PORT_NUM; i++) {
330+
reg = (void __iomem *) xhci->cap_regs +
331+
SSIC_PORT_CFG2 +
332+
i * SSIC_PORT_CFG2_OFFSET;
333+
334+
/* Notify SSIC that SSIC profile programming is not done. */
335+
val = readl(reg) & ~PROG_DONE;
336+
writel(val, reg);
337+
338+
/* Mark SSIC port as unused(suspend) or used(resume) */
339+
val = readl(reg);
340+
if (suspend)
341+
val |= SSIC_PORT_UNUSED;
342+
else
343+
val &= ~SSIC_PORT_UNUSED;
344+
writel(val, reg);
345+
346+
/* Notify SSIC that SSIC profile programming is done */
347+
val = readl(reg) | PROG_DONE;
348+
writel(val, reg);
349+
readl(reg);
356350
}
351+
}
352+
353+
/*
354+
* Make sure PME works on some Intel xHCI controllers by writing 1 to clear
355+
* the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
356+
*/
357+
static void xhci_pme_quirk(struct usb_hcd *hcd)
358+
{
359+
struct xhci_hcd *xhci = hcd_to_xhci(hcd);
360+
void __iomem *reg;
361+
u32 val;
357362

358363
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
359364
val = readl(reg);
@@ -374,7 +379,10 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
374379
pdev->no_d3cold = true;
375380

376381
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
377-
xhci_pme_quirk(hcd, true);
382+
xhci_pme_quirk(hcd);
383+
384+
if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
385+
xhci_ssic_port_unused_quirk(hcd, true);
378386

379387
return xhci_suspend(xhci, do_wakeup);
380388
}
@@ -406,8 +414,11 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
406414
if (pdev->vendor == PCI_VENDOR_ID_INTEL)
407415
usb_enable_intel_xhci_ports(pdev);
408416

417+
if (xhci->quirks & XHCI_SSIC_PORT_UNUSED)
418+
xhci_ssic_port_unused_quirk(hcd, false);
419+
409420
if (xhci->quirks & XHCI_PME_STUCK_QUIRK)
410-
xhci_pme_quirk(hcd, false);
421+
xhci_pme_quirk(hcd);
411422

412423
retval = xhci_resume(xhci, hibernated);
413424
return retval;

drivers/usb/host/xhci.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1631,6 +1631,7 @@ struct xhci_hcd {
16311631
#define XHCI_BROKEN_STREAMS (1 << 19)
16321632
#define XHCI_PME_STUCK_QUIRK (1 << 20)
16331633
#define XHCI_MTK_HOST (1 << 21)
1634+
#define XHCI_SSIC_PORT_UNUSED (1 << 22)
16341635
unsigned int num_active_eps;
16351636
unsigned int limit_active_eps;
16361637
/* There are two roothubs to keep track of bus suspend info for */

0 commit comments

Comments
 (0)