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.c173
1 files changed, 125 insertions, 48 deletions
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index ef956220f854..e7d3d8def282 100644
--- a/drivers/usb/host/ehci-hub.c
+++ b/drivers/usb/host/ehci-hub.c
@@ -106,12 +106,75 @@ static void ehci_handover_companion_ports(struct ehci_hcd *ehci)
106 ehci->owned_ports = 0; 106 ehci->owned_ports = 0;
107} 107}
108 108
109static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
110 bool suspending)
111{
112 int port;
113 u32 temp;
114
115 /* If remote wakeup is enabled for the root hub but disabled
116 * for the controller, we must adjust all the port wakeup flags
117 * when the controller is suspended or resumed. In all other
118 * cases they don't need to be changed.
119 */
120 if (!ehci_to_hcd(ehci)->self.root_hub->do_remote_wakeup ||
121 device_may_wakeup(ehci_to_hcd(ehci)->self.controller))
122 return;
123
124 /* clear phy low-power mode before changing wakeup flags */
125 if (ehci->has_hostpc) {
126 port = HCS_N_PORTS(ehci->hcs_params);
127 while (port--) {
128 u32 __iomem *hostpc_reg;
129
130 hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
131 + HOSTPC0 + 4 * port);
132 temp = ehci_readl(ehci, hostpc_reg);
133 ehci_writel(ehci, temp & ~HOSTPC_PHCD, hostpc_reg);
134 }
135 msleep(5);
136 }
137
138 port = HCS_N_PORTS(ehci->hcs_params);
139 while (port--) {
140 u32 __iomem *reg = &ehci->regs->port_status[port];
141 u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
142 u32 t2 = t1 & ~PORT_WAKE_BITS;
143
144 /* If we are suspending the controller, clear the flags.
145 * If we are resuming the controller, set the wakeup flags.
146 */
147 if (!suspending) {
148 if (t1 & PORT_CONNECT)
149 t2 |= PORT_WKOC_E | PORT_WKDISC_E;
150 else
151 t2 |= PORT_WKOC_E | PORT_WKCONN_E;
152 }
153 ehci_vdbg(ehci, "port %d, %08x -> %08x\n",
154 port + 1, t1, t2);
155 ehci_writel(ehci, t2, reg);
156 }
157
158 /* enter phy low-power mode again */
159 if (ehci->has_hostpc) {
160 port = HCS_N_PORTS(ehci->hcs_params);
161 while (port--) {
162 u32 __iomem *hostpc_reg;
163
164 hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
165 + HOSTPC0 + 4 * port);
166 temp = ehci_readl(ehci, hostpc_reg);
167 ehci_writel(ehci, temp | HOSTPC_PHCD, hostpc_reg);
168 }
169 }
170}
171
109static int ehci_bus_suspend (struct usb_hcd *hcd) 172static int ehci_bus_suspend (struct usb_hcd *hcd)
110{ 173{
111 struct ehci_hcd *ehci = hcd_to_ehci (hcd); 174 struct ehci_hcd *ehci = hcd_to_ehci (hcd);
112 int port; 175 int port;
113 int mask; 176 int mask;
114 u32 __iomem *hostpc_reg = NULL; 177 int changed;
115 178
116 ehci_dbg(ehci, "suspend root hub\n"); 179 ehci_dbg(ehci, "suspend root hub\n");
117 180
@@ -155,15 +218,13 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
155 */ 218 */
156 ehci->bus_suspended = 0; 219 ehci->bus_suspended = 0;
157 ehci->owned_ports = 0; 220 ehci->owned_ports = 0;
221 changed = 0;
158 port = HCS_N_PORTS(ehci->hcs_params); 222 port = HCS_N_PORTS(ehci->hcs_params);
159 while (port--) { 223 while (port--) {
160 u32 __iomem *reg = &ehci->regs->port_status [port]; 224 u32 __iomem *reg = &ehci->regs->port_status [port];
161 u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS; 225 u32 t1 = ehci_readl(ehci, reg) & ~PORT_RWC_BITS;
162 u32 t2 = t1; 226 u32 t2 = t1 & ~PORT_WAKE_BITS;
163 227
164 if (ehci->has_hostpc)
165 hostpc_reg = (u32 __iomem *)((u8 *)ehci->regs
166 + HOSTPC0 + 4 * (port & 0xff));
167 /* keep track of which ports we suspend */ 228 /* keep track of which ports we suspend */
168 if (t1 & PORT_OWNER) 229 if (t1 & PORT_OWNER)
169 set_bit(port, &ehci->owned_ports); 230 set_bit(port, &ehci->owned_ports);
@@ -172,40 +233,45 @@ static int ehci_bus_suspend (struct usb_hcd *hcd)
172 set_bit(port, &ehci->bus_suspended); 233 set_bit(port, &ehci->bus_suspended);
173 } 234 }
174 235
175 /* enable remote wakeup on all ports */ 236 /* enable remote wakeup on all ports, if told to do so */
176 if (hcd->self.root_hub->do_remote_wakeup) { 237 if (hcd->self.root_hub->do_remote_wakeup) {
177 /* only enable appropriate wake bits, otherwise the 238 /* only enable appropriate wake bits, otherwise the
178 * hardware can not go phy low power mode. If a race 239 * hardware can not go phy low power mode. If a race
179 * condition happens here(connection change during bits 240 * condition happens here(connection change during bits
180 * set), the port change detection will finally fix it. 241 * set), the port change detection will finally fix it.
181 */ 242 */
182 if (t1 & PORT_CONNECT) { 243 if (t1 & PORT_CONNECT)
183 t2 |= PORT_WKOC_E | PORT_WKDISC_E; 244 t2 |= PORT_WKOC_E | PORT_WKDISC_E;
184 t2 &= ~PORT_WKCONN_E; 245 else
185 } else {
186 t2 |= PORT_WKOC_E | PORT_WKCONN_E; 246 t2 |= PORT_WKOC_E | PORT_WKCONN_E;
187 t2 &= ~PORT_WKDISC_E; 247 }
188 }
189 } else
190 t2 &= ~PORT_WAKE_BITS;
191 248
192 if (t1 != t2) { 249 if (t1 != t2) {
193 ehci_vdbg (ehci, "port %d, %08x -> %08x\n", 250 ehci_vdbg (ehci, "port %d, %08x -> %08x\n",
194 port + 1, t1, t2); 251 port + 1, t1, t2);
195 ehci_writel(ehci, t2, reg); 252 ehci_writel(ehci, t2, reg);
196 if (hostpc_reg) { 253 changed = 1;
197 u32 t3; 254 }
255 }
198 256
199 spin_unlock_irq(&ehci->lock); 257 if (changed && ehci->has_hostpc) {
200 msleep(5);/* 5ms for HCD enter low pwr mode */ 258 spin_unlock_irq(&ehci->lock);
201 spin_lock_irq(&ehci->lock); 259 msleep(5); /* 5 ms for HCD to enter low-power mode */
202 t3 = ehci_readl(ehci, hostpc_reg); 260 spin_lock_irq(&ehci->lock);
203 ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg); 261
204 t3 = ehci_readl(ehci, hostpc_reg); 262 port = HCS_N_PORTS(ehci->hcs_params);
205 ehci_dbg(ehci, "Port%d phy low pwr mode %s\n", 263 while (port--) {
264 u32 __iomem *hostpc_reg;
265 u32 t3;
266
267 hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
268 + HOSTPC0 + 4 * port);
269 t3 = ehci_readl(ehci, hostpc_reg);
270 ehci_writel(ehci, t3 | HOSTPC_PHCD, hostpc_reg);
271 t3 = ehci_readl(ehci, hostpc_reg);
272 ehci_dbg(ehci, "Port %d phy low-power mode %s\n",
206 port, (t3 & HOSTPC_PHCD) ? 273 port, (t3 & HOSTPC_PHCD) ?
207 "succeeded" : "failed"); 274 "succeeded" : "failed");
208 }
209 } 275 }
210 } 276 }
211 277
@@ -291,19 +357,28 @@ static int ehci_bus_resume (struct usb_hcd *hcd)
291 msleep(8); 357 msleep(8);
292 spin_lock_irq(&ehci->lock); 358 spin_lock_irq(&ehci->lock);
293 359
360 /* clear phy low-power mode before resume */
361 if (ehci->bus_suspended && ehci->has_hostpc) {
362 i = HCS_N_PORTS(ehci->hcs_params);
363 while (i--) {
364 if (test_bit(i, &ehci->bus_suspended)) {
365 u32 __iomem *hostpc_reg;
366
367 hostpc_reg = (u32 __iomem *)((u8 *) ehci->regs
368 + HOSTPC0 + 4 * i);
369 temp = ehci_readl(ehci, hostpc_reg);
370 ehci_writel(ehci, temp & ~HOSTPC_PHCD,
371 hostpc_reg);
372 }
373 }
374 spin_unlock_irq(&ehci->lock);
375 msleep(5);
376 spin_lock_irq(&ehci->lock);
377 }
378
294 /* manually resume the ports we suspended during bus_suspend() */ 379 /* manually resume the ports we suspended during bus_suspend() */
295 i = HCS_N_PORTS (ehci->hcs_params); 380 i = HCS_N_PORTS (ehci->hcs_params);
296 while (i--) { 381 while (i--) {
297 /* clear phy low power mode before resume */
298 if (ehci->has_hostpc) {
299 u32 __iomem *hostpc_reg =
300 (u32 __iomem *)((u8 *)ehci->regs
301 + HOSTPC0 + 4 * (i & 0xff));
302 temp = ehci_readl(ehci, hostpc_reg);
303 ehci_writel(ehci, temp & ~HOSTPC_PHCD,
304 hostpc_reg);
305 mdelay(5);
306 }
307 temp = ehci_readl(ehci, &ehci->regs->port_status [i]); 382 temp = ehci_readl(ehci, &ehci->regs->port_status [i]);
308 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS); 383 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
309 if (test_bit(i, &ehci->bus_suspended) && 384 if (test_bit(i, &ehci->bus_suspended) &&
@@ -685,23 +760,25 @@ static int ehci_hub_control (
685 goto error; 760 goto error;
686 if (ehci->no_selective_suspend) 761 if (ehci->no_selective_suspend)
687 break; 762 break;
688 if (temp & PORT_SUSPEND) { 763 if (!(temp & PORT_SUSPEND))
689 if ((temp & PORT_PE) == 0) 764 break;
690 goto error; 765 if ((temp & PORT_PE) == 0)
691 /* clear phy low power mode before resume */ 766 goto error;
692 if (hostpc_reg) { 767
693 temp1 = ehci_readl(ehci, hostpc_reg); 768 /* clear phy low-power mode before resume */
694 ehci_writel(ehci, temp1 & ~HOSTPC_PHCD, 769 if (hostpc_reg) {
770 temp1 = ehci_readl(ehci, hostpc_reg);
771 ehci_writel(ehci, temp1 & ~HOSTPC_PHCD,
695 hostpc_reg); 772 hostpc_reg);
696 mdelay(5); 773 spin_unlock_irqrestore(&ehci->lock, flags);
697 } 774 msleep(5);/* wait to leave low-power mode */
698 /* resume signaling for 20 msec */ 775 spin_lock_irqsave(&ehci->lock, flags);
699 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
700 ehci_writel(ehci, temp | PORT_RESUME,
701 status_reg);
702 ehci->reset_done [wIndex] = jiffies
703 + msecs_to_jiffies (20);
704 } 776 }
777 /* resume signaling for 20 msec */
778 temp &= ~(PORT_RWC_BITS | PORT_WAKE_BITS);
779 ehci_writel(ehci, temp | PORT_RESUME, status_reg);
780 ehci->reset_done[wIndex] = jiffies
781 + msecs_to_jiffies(20);
705 break; 782 break;
706 case USB_PORT_FEAT_C_SUSPEND: 783 case USB_PORT_FEAT_C_SUSPEND:
707 clear_bit(wIndex, &ehci->port_c_suspend); 784 clear_bit(wIndex, &ehci->port_c_suspend);