aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-hub.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r--drivers/usb/host/ehci-hub.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index e7d3d8def282..796ea0c8900f 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -107,7 +107,7 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
107} 107}
108 108
109static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, 109static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
110 bool suspending) 110 bool suspending, bool do_wakeup)
111{ 111{
112 int port; 112 int port;
113 u32 temp; 113 u32 temp;
@@ -117,8 +117,7 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
117 * when the controller is suspended or resumed. In all other 117 * when the controller is suspended or resumed. In all other
118 * cases they don't need to be changed. 118 * cases they don't need to be changed.
119 */ 119 */
120 if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || 120 if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup)
121 device_may_wakeup(ehci_to_hcd(ehci)->self.controller))
122 return; 121 return;
123 122
124 /* clear phy low-power mode before changing wakeup flags */ 123 /* clear phy low-power mode before changing wakeup flags */
@@ -167,6 +166,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
167 ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg); 166 ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
168 } 167 }
169 } 168 }
169
170 /* Does the root hub have a port wakeup pending? */
171 if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD))
172 usb_hcd_resume_root_hub(ehci_to_hcd(ehci));
170} 173}
171 174
172static int ehci_bus_suspend (struct usb_hcd *hcd) 175static int ehci_bus_suspend (struct usb_hcd *hcd)
@@ -316,7 +319,7 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
316 if (time_before (jiffies, ehci->next_statechange)) 319 if (time_before (jiffies, ehci->next_statechange))
317 msleep(5); 320 msleep(5);
318 spin_lock_irq (&ehci->lock); 321 spin_lock_irq (&ehci->lock);
319 if (!test_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags)) { 322 if (!HCD_HW_ACCESSIBLE(hcd)) {
320 spin_unlock_irq(&ehci->lock); 323 spin_unlock_irq(&ehci->lock);
321 return -ESHUTDOWN; 324 return -ESHUTDOWN;
322 } 325 }
@@ -603,6 +606,7 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
603 u32 mask; 606 u32 mask;
604 int ports, i, retval = 1; 607 int ports, i, retval = 1;
605 unsigned long flags; 608 unsigned long flags;
609 u32 ppcd = 0;
606 610
607 /* if !USB_SUSPEND, root hub timers won't get shut down ... */ 611 /* if !USB_SUSPEND, root hub timers won't get shut down ... */
608 if (!HC_IS_RUNNING(hcd->state)) 612 if (!HC_IS_RUNNING(hcd->state))
@@ -632,7 +636,15 @@ ehci_hub_status_data (struct usb_hcd *hcd, char *buf)
632 636
633 /* port N changes (bit N)? */ 637 /* port N changes (bit N)? */
634 spin_lock_irqsave (&ehci->lock, flags); 638 spin_lock_irqsave (&ehci->lock, flags);
639
640 /* get per-port change detect bits */
641 if (ehci->has_ppcd)
642 ppcd = ehci_readl(ehci, &ehci->regs->status) >> 16;
643
635 for (i = 0; i < ports; i++) { 644 for (i = 0; i < ports; i++) {
645 /* leverage per-port change bits feature */
646 if (ehci->has_ppcd && !(ppcd & (1 << i)))
647 continue;
636 temp = ehci_readl(ehci, &ehci->regs->port_status [i]); 648 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
637 649
638 /* 650 /*
@@ -790,6 +802,11 @@ static int ehci_hub_control (
790 status_reg); 802 status_reg);
791 break; 803 break;
792 case USB_PORT_FEAT_C_CONNECTION: 804 case USB_PORT_FEAT_C_CONNECTION:
805 if (ehci->has_lpm) {
806 /* clear PORTSC bits on disconnect */
807 temp &= ~PORT_LPM;
808 temp &= ~PORT_DEV_ADDR;
809 }
793 ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC, 810 ehci_writel(ehci, (temp & ~PORT_RWC_BITS) | PORT_CSC,
794 status_reg); 811 status_reg);
795 break; 812 break;