diff options
author | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
---|---|---|
committer | Glenn Elliott <gelliott@cs.unc.edu> | 2012-03-04 19:47:13 -0500 |
commit | c71c03bda1e86c9d5198c5d83f712e695c4f2a1e (patch) | |
tree | ecb166cb3e2b7e2adb3b5e292245fefd23381ac8 /drivers/usb/host/ehci-hub.c | |
parent | ea53c912f8a86a8567697115b6a0d8152beee5c8 (diff) | |
parent | 6a00f206debf8a5c8899055726ad127dbeeed098 (diff) |
Merge branch 'mpi-master' into wip-k-fmlpwip-k-fmlp
Conflicts:
litmus/sched_cedf.c
Diffstat (limited to 'drivers/usb/host/ehci-hub.c')
-rw-r--r-- | drivers/usb/host/ehci-hub.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c index 796ea0c8900f..ea6184bf48d0 100644 --- a/drivers/usb/host/ehci-hub.c +++ b/drivers/usb/host/ehci-hub.c | |||
@@ -27,6 +27,7 @@ | |||
27 | */ | 27 | */ |
28 | 28 | ||
29 | /*-------------------------------------------------------------------------*/ | 29 | /*-------------------------------------------------------------------------*/ |
30 | #include <linux/usb/otg.h> | ||
30 | 31 | ||
31 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) | 32 | #define PORT_WAKE_BITS (PORT_WKOC_E|PORT_WKDISC_E|PORT_WKCONN_E) |
32 | 33 | ||
@@ -106,11 +107,33 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci) | |||
106 | ehci->owned_ports = 0; | 107 | ehci->owned_ports = 0; |
107 | } | 108 | } |
108 | 109 | ||
109 | static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | 110 | static int ehci_port_change(struct ehci_hcd *ehci) |
111 | { | ||
112 | int i = HCS_N_PORTS(ehci->hcs_params); | ||
113 | |||
114 | /* First check if the controller indicates a change event */ | ||
115 | |||
116 | if (ehci_readl(ehci, &ehci->regs->status) & STS_PCD) | ||
117 | return 1; | ||
118 | |||
119 | /* | ||
120 | * Not all controllers appear to update this while going from D3 to D0, | ||
121 | * so check the individual port status registers as well | ||
122 | */ | ||
123 | |||
124 | while (i--) | ||
125 | if (ehci_readl(ehci, &ehci->regs->port_status[i]) & PORT_CSC) | ||
126 | return 1; | ||
127 | |||
128 | return 0; | ||
129 | } | ||
130 | |||
131 | static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | ||
110 | bool suspending, bool do_wakeup) | 132 | bool suspending, bool do_wakeup) |
111 | { | 133 | { |
112 | int port; | 134 | int port; |
113 | u32 temp; | 135 | u32 temp; |
136 | unsigned long flags; | ||
114 | 137 | ||
115 | /* If remote wakeup is enabled for the root hub but disabled | 138 | /* If remote wakeup is enabled for the root hub but disabled |
116 | * for the controller, we must adjust all the port wakeup flags | 139 | * for the controller, we must adjust all the port wakeup flags |
@@ -120,6 +143,8 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |||
120 | if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) | 143 | if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup || do_wakeup) |
121 | return; | 144 | return; |
122 | 145 | ||
146 | spin_lock_irqsave(&ehci->lock, flags); | ||
147 | |||
123 | /* clear phy low-power mode before changing wakeup flags */ | 148 | /* clear phy low-power mode before changing wakeup flags */ |
124 | if (ehci->has_hostpc) { | 149 | if (ehci->has_hostpc) { |
125 | port = HCS_N_PORTS(ehci->hcs_params); | 150 | port = HCS_N_PORTS(ehci->hcs_params); |
@@ -131,7 +156,9 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |||
131 | temp = ehci_readl(ehci, hostpc_reg); | 156 | temp = ehci_readl(ehci, hostpc_reg); |
132 | ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); | 157 | ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg); |
133 | } | 158 | } |
159 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
134 | msleep(5); | 160 | msleep(5); |
161 | spin_lock_irqsave(&ehci->lock, flags); | ||
135 | } | 162 | } |
136 | 163 | ||
137 | port = HCS_N_PORTS(ehci->hcs_params); | 164 | port = HCS_N_PORTS(ehci->hcs_params); |
@@ -168,8 +195,10 @@ static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, | |||
168 | } | 195 | } |
169 | 196 | ||
170 | /* Does the root hub have a port wakeup pending? */ | 197 | /* Does the root hub have a port wakeup pending? */ |
171 | if (!suspending && (ehci_readl(ehci, &ehci->regs->status) & STS_PCD)) | 198 | if (!suspending && ehci_port_change(ehci)) |
172 | usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); | 199 | usb_hcd_resume_root_hub(ehci_to_hcd(ehci)); |
200 | |||
201 | spin_unlock_irqrestore(&ehci->lock, flags); | ||
173 | } | 202 | } |
174 | 203 | ||
175 | static int ehci_bus_suspend (struct usb_hcd *hcd) | 204 | static int ehci_bus_suspend (struct usb_hcd *hcd) |
@@ -531,14 +560,15 @@ static ssize_t store_companion(struct device *dev, | |||
531 | } | 560 | } |
532 | static DEVICE_ATTR(companion, 0644, show_companion, store_companion); | 561 | static DEVICE_ATTR(companion, 0644, show_companion, store_companion); |
533 | 562 | ||
534 | static inline void create_companion_file(struct ehci_hcd *ehci) | 563 | static inline int create_companion_file(struct ehci_hcd *ehci) |
535 | { | 564 | { |
536 | int i; | 565 | int i = 0; |
537 | 566 | ||
538 | /* with integrated TT there is no companion! */ | 567 | /* with integrated TT there is no companion! */ |
539 | if (!ehci_is_TDI(ehci)) | 568 | if (!ehci_is_TDI(ehci)) |
540 | i = device_create_file(ehci_to_hcd(ehci)->self.controller, | 569 | i = device_create_file(ehci_to_hcd(ehci)->self.controller, |
541 | &dev_attr_companion); | 570 | &dev_attr_companion); |
571 | return i; | ||
542 | } | 572 | } |
543 | 573 | ||
544 | static inline void remove_companion_file(struct ehci_hcd *ehci) | 574 | static inline void remove_companion_file(struct ehci_hcd *ehci) |
@@ -688,8 +718,8 @@ ehci_hub_descriptor ( | |||
688 | desc->bDescLength = 7 + 2 * temp; | 718 | desc->bDescLength = 7 + 2 * temp; |
689 | 719 | ||
690 | /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ | 720 | /* two bitmaps: ports removable, and usb 1.0 legacy PortPwrCtrlMask */ |
691 | memset (&desc->bitmap [0], 0, temp); | 721 | memset(&desc->u.hs.DeviceRemovable[0], 0, temp); |
692 | memset (&desc->bitmap [temp], 0xff, temp); | 722 | memset(&desc->u.hs.DeviceRemovable[temp], 0xff, temp); |
693 | 723 | ||
694 | temp = 0x0008; /* per-port overcurrent reporting */ | 724 | temp = 0x0008; /* per-port overcurrent reporting */ |
695 | if (HCS_PPC (ehci->hcs_params)) | 725 | if (HCS_PPC (ehci->hcs_params)) |
@@ -772,6 +802,13 @@ static int ehci_hub_control ( | |||
772 | goto error; | 802 | goto error; |
773 | if (ehci->no_selective_suspend) | 803 | if (ehci->no_selective_suspend) |
774 | break; | 804 | break; |
805 | #ifdef CONFIG_USB_OTG | ||
806 | if ((hcd->self.otg_port == (wIndex + 1)) | ||
807 | && hcd->self.b_hnp_enable) { | ||
808 | otg_start_hnp(ehci->transceiver); | ||
809 | break; | ||
810 | } | ||
811 | #endif | ||
775 | if (!(temp & PORT_SUSPEND)) | 812 | if (!(temp & PORT_SUSPEND)) |
776 | break; | 813 | break; |
777 | if ((temp & PORT_PE) == 0) | 814 | if ((temp & PORT_PE) == 0) |