aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/usb/host/ehci-au1xxx.c16
-rw-r--r--drivers/usb/host/ehci-fsl.c2
-rw-r--r--drivers/usb/host/ehci-hub.c173
-rw-r--r--drivers/usb/host/ehci-pci.c15
-rw-r--r--drivers/usb/host/ehci.h10
5 files changed, 145 insertions, 71 deletions
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index 7a27b7c4ee8..faa61748db7 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -224,26 +224,17 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
224 msleep(10); 224 msleep(10);
225 225
226 /* Root hub was already suspended. Disable irq emission and 226 /* Root hub was already suspended. Disable irq emission and
227 * mark HW unaccessible, bail out if RH has been resumed. Use 227 * mark HW unaccessible. The PM and USB cores make sure that
228 * the spinlock to properly synchronize with possible pending 228 * the root hub is either suspended or stopped.
229 * RH suspend or resume activity.
230 *
231 * This is still racy as hcd->state is manipulated outside of
232 * any locks =P But that will be a different fix.
233 */ 229 */
234 spin_lock_irqsave(&ehci->lock, flags); 230 spin_lock_irqsave(&ehci->lock, flags);
235 if (hcd->state != HC_STATE_SUSPENDED) { 231 ehci_prepare_ports_for_controller_suspend(ehci);
236 rc = -EINVAL;
237 goto bail;
238 }
239 ehci_writel(ehci, 0, &ehci->regs->intr_enable); 232 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
240 (void)ehci_readl(ehci, &ehci->regs->intr_enable); 233 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
241 234
242 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 235 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
243 236
244 au1xxx_stop_ehc(); 237 au1xxx_stop_ehc();
245
246bail:
247 spin_unlock_irqrestore(&ehci->lock, flags); 238 spin_unlock_irqrestore(&ehci->lock, flags);
248 239
249 // could save FLADJ in case of Vaux power loss 240 // could save FLADJ in case of Vaux power loss
@@ -273,6 +264,7 @@ static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
273 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) { 264 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
274 int mask = INTR_MASK; 265 int mask = INTR_MASK;
275 266
267 ehci_prepare_ports_for_controller_resume(ehci);
276 if (!hcd->self.root_hub->do_remote_wakeup) 268 if (!hcd->self.root_hub->do_remote_wakeup)
277 mask &= ~STS_PCD; 269 mask &= ~STS_PCD;
278 ehci_writel(ehci, mask, &ehci->regs->intr_enable); 270 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index 0e26aa13f15..5cd967d2893 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -313,6 +313,7 @@ static int ehci_fsl_drv_suspend(struct device *dev)
313 struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd); 313 struct ehci_fsl *ehci_fsl = hcd_to_ehci_fsl(hcd);
314 void __iomem *non_ehci = hcd->regs; 314 void __iomem *non_ehci = hcd->regs;
315 315
316 ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd));
316 if (!fsl_deep_sleep()) 317 if (!fsl_deep_sleep())
317 return 0; 318 return 0;
318 319
@@ -327,6 +328,7 @@ static int ehci_fsl_drv_resume(struct device *dev)
327 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 328 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
328 void __iomem *non_ehci = hcd->regs; 329 void __iomem *non_ehci = hcd->regs;
329 330
331 ehci_prepare_ports_for_controller_resume(ehci);
330 if (!fsl_deep_sleep()) 332 if (!fsl_deep_sleep())
331 return 0; 333 return 0;
332 334
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index ef956220f85..e7d3d8def28 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);
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index d120059bbbf..d43d176161a 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -287,23 +287,15 @@ static int ehci_pci_suspend(struct usb_hcd *hcd)
287 msleep(10); 287 msleep(10);
288 288
289 /* Root hub was already suspended. Disable irq emission and 289 /* Root hub was already suspended. Disable irq emission and
290 * mark HW unaccessible, bail out if RH has been resumed. Use 290 * mark HW unaccessible. The PM and USB cores make sure that
291 * the spinlock to properly synchronize with possible pending 291 * the root hub is either suspended or stopped.
292 * RH suspend or resume activity.
293 *
294 * This is still racy as hcd->state is manipulated outside of
295 * any locks =P But that will be a different fix.
296 */ 292 */
297 spin_lock_irqsave (&ehci->lock, flags); 293 spin_lock_irqsave (&ehci->lock, flags);
298 if (hcd->state != HC_STATE_SUSPENDED) { 294 ehci_prepare_ports_for_controller_suspend(ehci);
299 rc = -EINVAL;
300 goto bail;
301 }
302 ehci_writel(ehci, 0, &ehci->regs->intr_enable); 295 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
303 (void)ehci_readl(ehci, &ehci->regs->intr_enable); 296 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
304 297
305 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags); 298 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
306 bail:
307 spin_unlock_irqrestore (&ehci->lock, flags); 299 spin_unlock_irqrestore (&ehci->lock, flags);
308 300
309 // could save FLADJ in case of Vaux power loss 301 // could save FLADJ in case of Vaux power loss
@@ -333,6 +325,7 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
333 !hibernated) { 325 !hibernated) {
334 int mask = INTR_MASK; 326 int mask = INTR_MASK;
335 327
328 ehci_prepare_ports_for_controller_resume(ehci);
336 if (!hcd->self.root_hub->do_remote_wakeup) 329 if (!hcd->self.root_hub->do_remote_wakeup)
337 mask &= ~STS_PCD; 330 mask &= ~STS_PCD;
338 ehci_writel(ehci, mask, &ehci->regs->intr_enable); 331 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 4ebe9ad209e..650a687f285 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -536,6 +536,16 @@ struct ehci_fstn {
536 536
537/*-------------------------------------------------------------------------*/ 537/*-------------------------------------------------------------------------*/
538 538
539/* Prepare the PORTSC wakeup flags during controller suspend/resume */
540
541#define ehci_prepare_ports_for_controller_suspend(ehci) \
542 ehci_adjust_port_wakeup_flags(ehci, true);
543
544#define ehci_prepare_ports_for_controller_resume(ehci) \
545 ehci_adjust_port_wakeup_flags(ehci, false);
546
547/*-------------------------------------------------------------------------*/
548
539#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT 549#ifdef CONFIG_USB_EHCI_ROOT_HUB_TT
540 550
541/* 551/*