@@ -150,6 +150,10 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
150150 pdev -> device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI )) {
151151 xhci -> quirks |= XHCI_PME_STUCK_QUIRK ;
152152 }
153+ if (pdev -> vendor == PCI_VENDOR_ID_INTEL &&
154+ pdev -> device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ) {
155+ xhci -> quirks |= XHCI_SSIC_PORT_UNUSED ;
156+ }
153157 if (pdev -> vendor == PCI_VENDOR_ID_ETRON &&
154158 pdev -> device == PCI_DEVICE_ID_EJ168 ) {
155159 xhci -> quirks |= XHCI_RESET_ON_RESUME ;
@@ -310,46 +314,47 @@ static void xhci_pci_remove(struct pci_dev *dev)
310314 * SSIC PORT need to be marked as "unused" before putting xHCI
311315 * into D3. After D3 exit, the SSIC port need to be marked as "used".
312316 * Without this change, xHCI might not enter D3 state.
313- * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
314- * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
315317 */
316- static void xhci_pme_quirk (struct usb_hcd * hcd , bool suspend )
318+ static void xhci_ssic_port_unused_quirk (struct usb_hcd * hcd , bool suspend )
317319{
318320 struct xhci_hcd * xhci = hcd_to_xhci (hcd );
319- struct pci_dev * pdev = to_pci_dev (hcd -> self .controller );
320321 u32 val ;
321322 void __iomem * reg ;
322323 int i ;
323324
324- if (pdev -> vendor == PCI_VENDOR_ID_INTEL &&
325- pdev -> device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ) {
326-
327- for (i = 0 ; i < SSIC_PORT_NUM ; i ++ ) {
328- reg = (void __iomem * ) xhci -> cap_regs +
329- SSIC_PORT_CFG2 +
330- i * SSIC_PORT_CFG2_OFFSET ;
331-
332- /*
333- * Notify SSIC that SSIC profile programming
334- * is not done.
335- */
336- val = readl (reg ) & ~PROG_DONE ;
337- writel (val , reg );
338-
339- /* Mark SSIC port as unused(suspend) or used(resume) */
340- val = readl (reg );
341- if (suspend )
342- val |= SSIC_PORT_UNUSED ;
343- else
344- val &= ~SSIC_PORT_UNUSED ;
345- writel (val , reg );
346-
347- /* Notify SSIC that SSIC profile programming is done */
348- val = readl (reg ) | PROG_DONE ;
349- writel (val , reg );
350- readl (reg );
351- }
325+ for (i = 0 ; i < SSIC_PORT_NUM ; i ++ ) {
326+ reg = (void __iomem * ) xhci -> cap_regs +
327+ SSIC_PORT_CFG2 +
328+ i * SSIC_PORT_CFG2_OFFSET ;
329+
330+ /* Notify SSIC that SSIC profile programming is not done. */
331+ val = readl (reg ) & ~PROG_DONE ;
332+ writel (val , reg );
333+
334+ /* Mark SSIC port as unused(suspend) or used(resume) */
335+ val = readl (reg );
336+ if (suspend )
337+ val |= SSIC_PORT_UNUSED ;
338+ else
339+ val &= ~SSIC_PORT_UNUSED ;
340+ writel (val , reg );
341+
342+ /* Notify SSIC that SSIC profile programming is done */
343+ val = readl (reg ) | PROG_DONE ;
344+ writel (val , reg );
345+ readl (reg );
352346 }
347+ }
348+
349+ /*
350+ * Make sure PME works on some Intel xHCI controllers by writing 1 to clear
351+ * the Internal PME flag bit in vendor specific PMCTRL register at offset 0x80a4
352+ */
353+ static void xhci_pme_quirk (struct usb_hcd * hcd )
354+ {
355+ struct xhci_hcd * xhci = hcd_to_xhci (hcd );
356+ void __iomem * reg ;
357+ u32 val ;
353358
354359 reg = (void __iomem * ) xhci -> cap_regs + 0x80a4 ;
355360 val = readl (reg );
@@ -370,7 +375,10 @@ static int xhci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
370375 pdev -> no_d3cold = true;
371376
372377 if (xhci -> quirks & XHCI_PME_STUCK_QUIRK )
373- xhci_pme_quirk (hcd , true);
378+ xhci_pme_quirk (hcd );
379+
380+ if (xhci -> quirks & XHCI_SSIC_PORT_UNUSED )
381+ xhci_ssic_port_unused_quirk (hcd , true);
374382
375383 return xhci_suspend (xhci , do_wakeup );
376384}
@@ -402,8 +410,11 @@ static int xhci_pci_resume(struct usb_hcd *hcd, bool hibernated)
402410 if (pdev -> vendor == PCI_VENDOR_ID_INTEL )
403411 usb_enable_intel_xhci_ports (pdev );
404412
413+ if (xhci -> quirks & XHCI_SSIC_PORT_UNUSED )
414+ xhci_ssic_port_unused_quirk (hcd , false);
415+
405416 if (xhci -> quirks & XHCI_PME_STUCK_QUIRK )
406- xhci_pme_quirk (hcd , false );
417+ xhci_pme_quirk (hcd );
407418
408419 retval = xhci_resume (xhci , hibernated );
409420 return retval ;
0 commit comments