@@ -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 ;
0 commit comments