aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host')
-rw-r--r--drivers/usb/host/ehci-au1xxx.c73
-rw-r--r--drivers/usb/host/ehci-hcd.c89
-rw-r--r--drivers/usb/host/ehci-hub.c4
-rw-r--r--drivers/usb/host/ehci-msm.c19
-rw-r--r--drivers/usb/host/ehci-pci.c74
-rw-r--r--drivers/usb/host/ehci-platform.c7
-rw-r--r--drivers/usb/host/ehci-s5p.c61
-rw-r--r--drivers/usb/host/ehci-sead3.c74
-rw-r--r--drivers/usb/host/ehci-spear.c61
9 files changed, 114 insertions, 348 deletions
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index bf7441afed16..182d39565906 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -158,28 +158,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
158static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) 158static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
159{ 159{
160 struct usb_hcd *hcd = dev_get_drvdata(dev); 160 struct usb_hcd *hcd = dev_get_drvdata(dev);
161 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 161 bool do_wakeup = device_may_wakeup(dev);
162 unsigned long flags; 162 int rc;
163 int rc = 0;
164
165 if (time_before(jiffies, ehci->next_statechange))
166 msleep(10);
167
168 /* Root hub was already suspended. Disable irq emission and
169 * mark HW unaccessible. The PM and USB cores make sure that
170 * the root hub is either suspended or stopped.
171 */
172 ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
173 spin_lock_irqsave(&ehci->lock, flags);
174 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
175 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
176
177 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
178 spin_unlock_irqrestore(&ehci->lock, flags);
179
180 // could save FLADJ in case of Vaux power loss
181 // ... we'd only use it to handle clock skew
182 163
164 rc = ehci_suspend(hcd, do_wakeup);
183 alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); 165 alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
184 166
185 return rc; 167 return rc;
@@ -188,56 +170,9 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
188static int ehci_hcd_au1xxx_drv_resume(struct device *dev) 170static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
189{ 171{
190 struct usb_hcd *hcd = dev_get_drvdata(dev); 172 struct usb_hcd *hcd = dev_get_drvdata(dev);
191 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
192 173
193 alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); 174 alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
194 175 ehci_resume(hcd, false);
195 // maybe restore FLADJ
196
197 if (time_before(jiffies, ehci->next_statechange))
198 msleep(100);
199
200 /* Mark hardware accessible again as we are out of D3 state by now */
201 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
202
203 /* If CF is still set, we maintained PCI Vaux power.
204 * Just undo the effect of ehci_pci_suspend().
205 */
206 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
207 int mask = INTR_MASK;
208
209 ehci_prepare_ports_for_controller_resume(ehci);
210 if (!hcd->self.root_hub->do_remote_wakeup)
211 mask &= ~STS_PCD;
212 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
213 ehci_readl(ehci, &ehci->regs->intr_enable);
214 return 0;
215 }
216
217 ehci_dbg(ehci, "lost power, restarting\n");
218 usb_root_hub_lost_power(hcd->self.root_hub);
219
220 /* Else reset, to cope with power loss or flush-to-storage
221 * style "resume" having let BIOS kick in during reboot.
222 */
223 (void) ehci_halt(ehci);
224 (void) ehci_reset(ehci);
225
226 /* emptying the schedule aborts any urbs */
227 spin_lock_irq(&ehci->lock);
228 if (ehci->reclaim)
229 end_unlink_async(ehci);
230 ehci_work(ehci);
231 spin_unlock_irq(&ehci->lock);
232
233 ehci_writel(ehci, ehci->command, &ehci->regs->command);
234 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
235 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
236
237 /* here we "know" root ports should always stay powered */
238 ehci_port_power(ehci, 1);
239
240 ehci->rh_state = EHCI_RH_SUSPENDED;
241 176
242 return 0; 177 return 0;
243} 178}
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c49fc1e7895d..e6823a0cf642 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1242,6 +1242,95 @@ static int ehci_get_frame (struct usb_hcd *hcd)
1242} 1242}
1243 1243
1244/*-------------------------------------------------------------------------*/ 1244/*-------------------------------------------------------------------------*/
1245
1246#ifdef CONFIG_PM
1247
1248/* suspend/resume, section 4.3 */
1249
1250/* These routines handle the generic parts of controller suspend/resume */
1251
1252static int __maybe_unused ehci_suspend(struct usb_hcd *hcd, bool do_wakeup)
1253{
1254 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1255
1256 if (time_before(jiffies, ehci->next_statechange))
1257 msleep(10);
1258
1259 /*
1260 * Root hub was already suspended. Disable IRQ emission and
1261 * mark HW unaccessible. The PM and USB cores make sure that
1262 * the root hub is either suspended or stopped.
1263 */
1264 ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
1265
1266 spin_lock_irq(&ehci->lock);
1267 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
1268 (void) ehci_readl(ehci, &ehci->regs->intr_enable);
1269
1270 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
1271 spin_unlock_irq(&ehci->lock);
1272
1273 return 0;
1274}
1275
1276/* Returns 0 if power was preserved, 1 if power was lost */
1277static int __maybe_unused ehci_resume(struct usb_hcd *hcd, bool hibernated)
1278{
1279 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
1280
1281 if (time_before(jiffies, ehci->next_statechange))
1282 msleep(100);
1283
1284 /* Mark hardware accessible again as we are back to full power by now */
1285 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
1286
1287 /*
1288 * If CF is still set and we aren't resuming from hibernation
1289 * then we maintained suspend power.
1290 * Just undo the effect of ehci_suspend().
1291 */
1292 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
1293 !hibernated) {
1294 int mask = INTR_MASK;
1295
1296 ehci_prepare_ports_for_controller_resume(ehci);
1297 if (!hcd->self.root_hub->do_remote_wakeup)
1298 mask &= ~STS_PCD;
1299 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
1300 ehci_readl(ehci, &ehci->regs->intr_enable);
1301 return 0;
1302 }
1303
1304 /*
1305 * Else reset, to cope with power loss or resume from hibernation
1306 * having let the firmware kick in during reboot.
1307 */
1308 usb_root_hub_lost_power(hcd->self.root_hub);
1309 (void) ehci_halt(ehci);
1310 (void) ehci_reset(ehci);
1311
1312 /* emptying the schedule aborts any urbs */
1313 spin_lock_irq(&ehci->lock);
1314 if (ehci->reclaim)
1315 end_unlink_async(ehci);
1316 ehci_work(ehci);
1317 spin_unlock_irq(&ehci->lock);
1318
1319 ehci_writel(ehci, ehci->command, &ehci->regs->command);
1320 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
1321 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
1322
1323 /* here we "know" root ports should always stay powered */
1324 ehci_port_power(ehci, 1);
1325
1326 ehci->rh_state = EHCI_RH_SUSPENDED;
1327 return 1;
1328}
1329
1330#endif
1331
1332/*-------------------------------------------------------------------------*/
1333
1245/* 1334/*
1246 * The EHCI in ChipIdea HDRC cannot be a separate module or device, 1335 * The EHCI in ChipIdea HDRC cannot be a separate module or device,
1247 * because its registers (and irq) are shared between host/gadget/otg 1336 * because its registers (and irq) are shared between host/gadget/otg
diff --git a/drivers/usb/host/ehci-hub.c b/drivers/usb/host/ehci-hub.c
index db05e358677a..b3e2d66e95bb 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 ehci->owned_ports = 0; 107 ehci->owned_ports = 0;
108} 108}
109 109
110static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci) 110static int ehci_port_change(struct ehci_hcd *ehci)
111{ 111{
112 int i = HCS_N_PORTS(ehci->hcs_params); 112 int i = HCS_N_PORTS(ehci->hcs_params);
113 113
@@ -128,7 +128,7 @@ static int __maybe_unused ehci_port_change(struct ehci_hcd *ehci)
128 return 0; 128 return 0;
129} 129}
130 130
131static __maybe_unused void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci, 131static void ehci_adjust_port_wakeup_flags(struct ehci_hcd *ehci,
132 bool suspending, bool do_wakeup) 132 bool suspending, bool do_wakeup)
133{ 133{
134 int port; 134 int port;
diff --git a/drivers/usb/host/ehci-msm.c b/drivers/usb/host/ehci-msm.c
index 6b4ffb598db1..17dd9e94001e 100644
--- a/drivers/usb/host/ehci-msm.c
+++ b/drivers/usb/host/ehci-msm.c
@@ -198,24 +198,11 @@ static int __devexit ehci_msm_remove(struct platform_device *pdev)
198static int ehci_msm_pm_suspend(struct device *dev) 198static int ehci_msm_pm_suspend(struct device *dev)
199{ 199{
200 struct usb_hcd *hcd = dev_get_drvdata(dev); 200 struct usb_hcd *hcd = dev_get_drvdata(dev);
201 bool wakeup = device_may_wakeup(dev); 201 bool do_wakeup = device_may_wakeup(dev);
202 202
203 dev_dbg(dev, "ehci-msm PM suspend\n"); 203 dev_dbg(dev, "ehci-msm PM suspend\n");
204 204
205 /* 205 return ehci_suspend(hcd, do_wakeup);
206 * EHCI helper function has also the same check before manipulating
207 * port wakeup flags. We do check here the same condition before
208 * calling the same helper function to avoid bringing hardware
209 * from Low power mode when there is no need for adjusting port
210 * wakeup flags.
211 */
212 if (hcd->self.root_hub->do_remote_wakeup && !wakeup) {
213 pm_runtime_resume(dev);
214 ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd),
215 wakeup);
216 }
217
218 return 0;
219} 206}
220 207
221static int ehci_msm_pm_resume(struct device *dev) 208static int ehci_msm_pm_resume(struct device *dev)
@@ -223,7 +210,7 @@ static int ehci_msm_pm_resume(struct device *dev)
223 struct usb_hcd *hcd = dev_get_drvdata(dev); 210 struct usb_hcd *hcd = dev_get_drvdata(dev);
224 211
225 dev_dbg(dev, "ehci-msm PM resume\n"); 212 dev_dbg(dev, "ehci-msm PM resume\n");
226 ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); 213 ehci_resume(hcd, false);
227 214
228 return 0; 215 return 0;
229} 216}
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 123481793a47..6e767bce0605 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -331,29 +331,7 @@ done:
331 331
332static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup) 332static int ehci_pci_suspend(struct usb_hcd *hcd, bool do_wakeup)
333{ 333{
334 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 334 return ehci_suspend(hcd, do_wakeup);
335 unsigned long flags;
336 int rc = 0;
337
338 if (time_before(jiffies, ehci->next_statechange))
339 msleep(10);
340
341 /* Root hub was already suspended. Disable irq emission and
342 * mark HW unaccessible. The PM and USB cores make sure that
343 * the root hub is either suspended or stopped.
344 */
345 ehci_prepare_ports_for_controller_suspend(ehci, do_wakeup);
346 spin_lock_irqsave (&ehci->lock, flags);
347 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
348 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
349
350 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
351 spin_unlock_irqrestore (&ehci->lock, flags);
352
353 // could save FLADJ in case of Vaux power loss
354 // ... we'd only use it to handle clock skew
355
356 return rc;
357} 335}
358 336
359static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev) 337static bool usb_is_intel_switchable_ehci(struct pci_dev *pdev)
@@ -402,54 +380,8 @@ static int ehci_pci_resume(struct usb_hcd *hcd, bool hibernated)
402 if (usb_is_intel_switchable_ehci(pdev)) 380 if (usb_is_intel_switchable_ehci(pdev))
403 ehci_enable_xhci_companion(); 381 ehci_enable_xhci_companion();
404 382
405 // maybe restore FLADJ 383 if (ehci_resume(hcd, hibernated) != 0)
406 384 (void) ehci_pci_reinit(ehci, pdev);
407 if (time_before(jiffies, ehci->next_statechange))
408 msleep(100);
409
410 /* Mark hardware accessible again as we are out of D3 state by now */
411 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
412
413 /* If CF is still set and we aren't resuming from hibernation
414 * then we maintained PCI Vaux power.
415 * Just undo the effect of ehci_pci_suspend().
416 */
417 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF &&
418 !hibernated) {
419 int mask = INTR_MASK;
420
421 ehci_prepare_ports_for_controller_resume(ehci);
422 if (!hcd->self.root_hub->do_remote_wakeup)
423 mask &= ~STS_PCD;
424 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
425 ehci_readl(ehci, &ehci->regs->intr_enable);
426 return 0;
427 }
428
429 usb_root_hub_lost_power(hcd->self.root_hub);
430
431 /* Else reset, to cope with power loss or flush-to-storage
432 * style "resume" having let BIOS kick in during reboot.
433 */
434 (void) ehci_halt(ehci);
435 (void) ehci_reset(ehci);
436 (void) ehci_pci_reinit(ehci, pdev);
437
438 /* emptying the schedule aborts any urbs */
439 spin_lock_irq(&ehci->lock);
440 if (ehci->reclaim)
441 end_unlink_async(ehci);
442 ehci_work(ehci);
443 spin_unlock_irq(&ehci->lock);
444
445 ehci_writel(ehci, ehci->command, &ehci->regs->command);
446 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
447 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
448
449 /* here we "know" root ports should always stay powered */
450 ehci_port_power(ehci, 1);
451
452 ehci->rh_state = EHCI_RH_SUSPENDED;
453 return 0; 385 return 0;
454} 386}
455#endif 387#endif
diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c
index dfe881a34ae2..4b1d896d5a22 100644
--- a/drivers/usb/host/ehci-platform.c
+++ b/drivers/usb/host/ehci-platform.c
@@ -153,17 +153,16 @@ static int __devexit ehci_platform_remove(struct platform_device *dev)
153static int ehci_platform_suspend(struct device *dev) 153static int ehci_platform_suspend(struct device *dev)
154{ 154{
155 struct usb_hcd *hcd = dev_get_drvdata(dev); 155 struct usb_hcd *hcd = dev_get_drvdata(dev);
156 bool wakeup = device_may_wakeup(dev); 156 bool do_wakeup = device_may_wakeup(dev);
157 157
158 ehci_prepare_ports_for_controller_suspend(hcd_to_ehci(hcd), wakeup); 158 return ehci_suspend(hcd, do_wakeup);
159 return 0;
160} 159}
161 160
162static int ehci_platform_resume(struct device *dev) 161static int ehci_platform_resume(struct device *dev)
163{ 162{
164 struct usb_hcd *hcd = dev_get_drvdata(dev); 163 struct usb_hcd *hcd = dev_get_drvdata(dev);
165 164
166 ehci_prepare_ports_for_controller_resume(hcd_to_ehci(hcd)); 165 ehci_resume(hcd, false);
167 return 0; 166 return 0;
168} 167}
169 168
diff --git a/drivers/usb/host/ehci-s5p.c b/drivers/usb/host/ehci-s5p.c
index 1e483f052ff7..c7e0936d4a7c 100644
--- a/drivers/usb/host/ehci-s5p.c
+++ b/drivers/usb/host/ehci-s5p.c
@@ -200,27 +200,12 @@ static int s5p_ehci_suspend(struct device *dev)
200{ 200{
201 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); 201 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
202 struct usb_hcd *hcd = s5p_ehci->hcd; 202 struct usb_hcd *hcd = s5p_ehci->hcd;
203 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 203 bool do_wakeup = device_may_wakeup(dev);
204 struct platform_device *pdev = to_platform_device(dev); 204 struct platform_device *pdev = to_platform_device(dev);
205 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; 205 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
206 unsigned long flags; 206 int rc;
207 int rc = 0;
208 207
209 if (time_before(jiffies, ehci->next_statechange)) 208 rc = ehci_suspend(hcd, do_wakeup);
210 msleep(20);
211
212 /*
213 * Root hub was already suspended. Disable irq emission and
214 * mark HW unaccessible. The PM and USB cores make sure that
215 * the root hub is either suspended or stopped.
216 */
217 ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
218 spin_lock_irqsave(&ehci->lock, flags);
219 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
220 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
221
222 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
223 spin_unlock_irqrestore(&ehci->lock, flags);
224 209
225 if (pdata && pdata->phy_exit) 210 if (pdata && pdata->phy_exit)
226 pdata->phy_exit(pdev, S5P_USB_PHY_HOST); 211 pdata->phy_exit(pdev, S5P_USB_PHY_HOST);
@@ -234,7 +219,6 @@ static int s5p_ehci_resume(struct device *dev)
234{ 219{
235 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev); 220 struct s5p_ehci_hcd *s5p_ehci = dev_get_drvdata(dev);
236 struct usb_hcd *hcd = s5p_ehci->hcd; 221 struct usb_hcd *hcd = s5p_ehci->hcd;
237 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
238 struct platform_device *pdev = to_platform_device(dev); 222 struct platform_device *pdev = to_platform_device(dev);
239 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data; 223 struct s5p_ehci_platdata *pdata = pdev->dev.platform_data;
240 224
@@ -246,44 +230,7 @@ static int s5p_ehci_resume(struct device *dev)
246 /* DMA burst Enable */ 230 /* DMA burst Enable */
247 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs)); 231 writel(EHCI_INSNREG00_ENABLE_DMA_BURST, EHCI_INSNREG00(hcd->regs));
248 232
249 if (time_before(jiffies, ehci->next_statechange)) 233 ehci_resume(hcd, false);
250 msleep(100);
251
252 /* Mark hardware accessible again as we are out of D3 state by now */
253 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
254
255 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
256 int mask = INTR_MASK;
257
258 ehci_prepare_ports_for_controller_resume(ehci);
259 if (!hcd->self.root_hub->do_remote_wakeup)
260 mask &= ~STS_PCD;
261 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
262 ehci_readl(ehci, &ehci->regs->intr_enable);
263 return 0;
264 }
265
266 usb_root_hub_lost_power(hcd->self.root_hub);
267
268 (void) ehci_halt(ehci);
269 (void) ehci_reset(ehci);
270
271 /* emptying the schedule aborts any urbs */
272 spin_lock_irq(&ehci->lock);
273 if (ehci->reclaim)
274 end_unlink_async(ehci);
275 ehci_work(ehci);
276 spin_unlock_irq(&ehci->lock);
277
278 ehci_writel(ehci, ehci->command, &ehci->regs->command);
279 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
280 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
281
282 /* here we "know" root ports should always stay powered */
283 ehci_port_power(ehci, 1);
284
285 ehci->rh_state = EHCI_RH_SUSPENDED;
286
287 return 0; 234 return 0;
288} 235}
289#else 236#else
diff --git a/drivers/usb/host/ehci-sead3.c b/drivers/usb/host/ehci-sead3.c
index cc199e87a7a9..58c96bd50d22 100644
--- a/drivers/usb/host/ehci-sead3.c
+++ b/drivers/usb/host/ehci-sead3.c
@@ -160,84 +160,16 @@ static int ehci_hcd_sead3_drv_remove(struct platform_device *pdev)
160static int ehci_hcd_sead3_drv_suspend(struct device *dev) 160static int ehci_hcd_sead3_drv_suspend(struct device *dev)
161{ 161{
162 struct usb_hcd *hcd = dev_get_drvdata(dev); 162 struct usb_hcd *hcd = dev_get_drvdata(dev);
163 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 163 bool do_wakeup = device_may_wakeup(dev);
164 unsigned long flags;
165 int rc = 0;
166
167 if (time_before(jiffies, ehci->next_statechange))
168 msleep(20);
169
170 /* Root hub was already suspended. Disable irq emission and
171 * mark HW unaccessible. The PM and USB cores make sure that
172 * the root hub is either suspended or stopped.
173 */
174 ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
175 spin_lock_irqsave(&ehci->lock, flags);
176 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
177 (void)ehci_readl(ehci, &ehci->regs->intr_enable);
178
179 clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
180 spin_unlock_irqrestore(&ehci->lock, flags);
181 164
182 /* could save FLADJ in case of Vaux power loss 165 return ehci_suspend(hcd, do_wakeup);
183 * ... we'd only use it to handle clock skew
184 */
185
186 return rc;
187} 166}
188 167
189static int ehci_hcd_sead3_drv_resume(struct device *dev) 168static int ehci_hcd_sead3_drv_resume(struct device *dev)
190{ 169{
191 struct usb_hcd *hcd = dev_get_drvdata(dev); 170 struct usb_hcd *hcd = dev_get_drvdata(dev);
192 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
193
194 /* maybe restore FLADJ. */
195
196 if (time_before(jiffies, ehci->next_statechange))
197 msleep(100);
198
199 /* Mark hardware accessible again as we are out of D3 state by now */
200 set_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
201
202 /* If CF is still set, we maintained PCI Vaux power.
203 * Just undo the effect of ehci_pci_suspend().
204 */
205 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
206 int mask = INTR_MASK;
207
208 ehci_prepare_ports_for_controller_resume(ehci);
209 if (!hcd->self.root_hub->do_remote_wakeup)
210 mask &= ~STS_PCD;
211 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
212 ehci_readl(ehci, &ehci->regs->intr_enable);
213 return 0;
214 }
215
216 ehci_dbg(ehci, "lost power, restarting\n");
217 usb_root_hub_lost_power(hcd->self.root_hub);
218
219 /* Else reset, to cope with power loss or flush-to-storage
220 * style "resume" having let BIOS kick in during reboot.
221 */
222 (void) ehci_halt(ehci);
223 (void) ehci_reset(ehci);
224
225 /* emptying the schedule aborts any urbs */
226 spin_lock_irq(&ehci->lock);
227 if (ehci->reclaim)
228 end_unlink_async(ehci);
229 ehci_work(ehci);
230 spin_unlock_irq(&ehci->lock);
231
232 ehci_writel(ehci, ehci->command, &ehci->regs->command);
233 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
234 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
235
236 /* here we "know" root ports should always stay powered */
237 ehci_port_power(ehci, 1);
238
239 ehci->rh_state = EHCI_RH_SUSPENDED;
240 171
172 ehci_resume(hcd, false);
241 return 0; 173 return 0;
242} 174}
243 175
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 37ba8c8d2fd0..7ed533e6cca8 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -97,71 +97,16 @@ static const struct hc_driver ehci_spear_hc_driver = {
97static int ehci_spear_drv_suspend(struct device *dev) 97static int ehci_spear_drv_suspend(struct device *dev)
98{ 98{
99 struct usb_hcd *hcd = dev_get_drvdata(dev); 99 struct usb_hcd *hcd = dev_get_drvdata(dev);
100 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 100 bool do_wakeup = device_may_wakeup(dev);
101 unsigned long flags;
102 int rc = 0;
103
104 if (time_before(jiffies, ehci->next_statechange))
105 msleep(10);
106
107 /*
108 * Root hub was already suspended. Disable irq emission and mark HW
109 * unaccessible. The PM and USB cores make sure that the root hub is
110 * either suspended or stopped.
111 */
112 spin_lock_irqsave(&ehci->lock, flags);
113 ehci_prepare_ports_for_controller_suspend(ehci, device_may_wakeup(dev));
114 ehci_writel(ehci, 0, &ehci->regs->intr_enable);
115 ehci_readl(ehci, &ehci->regs->intr_enable);
116 spin_unlock_irqrestore(&ehci->lock, flags);
117 101
118 return rc; 102 return ehci_suspend(hcd, do_wakeup);
119} 103}
120 104
121static int ehci_spear_drv_resume(struct device *dev) 105static int ehci_spear_drv_resume(struct device *dev)
122{ 106{
123 struct usb_hcd *hcd = dev_get_drvdata(dev); 107 struct usb_hcd *hcd = dev_get_drvdata(dev);
124 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
125
126 if (time_before(jiffies, ehci->next_statechange))
127 msleep(100);
128
129 if (ehci_readl(ehci, &ehci->regs->configured_flag) == FLAG_CF) {
130 int mask = INTR_MASK;
131
132 ehci_prepare_ports_for_controller_resume(ehci);
133
134 if (!hcd->self.root_hub->do_remote_wakeup)
135 mask &= ~STS_PCD;
136
137 ehci_writel(ehci, mask, &ehci->regs->intr_enable);
138 ehci_readl(ehci, &ehci->regs->intr_enable);
139 return 0;
140 }
141
142 usb_root_hub_lost_power(hcd->self.root_hub);
143
144 /*
145 * Else reset, to cope with power loss or flush-to-storage style
146 * "resume" having let BIOS kick in during reboot.
147 */
148 ehci_halt(ehci);
149 ehci_reset(ehci);
150
151 /* emptying the schedule aborts any urbs */
152 spin_lock_irq(&ehci->lock);
153 if (ehci->reclaim)
154 end_unlink_async(ehci);
155
156 ehci_work(ehci);
157 spin_unlock_irq(&ehci->lock);
158
159 ehci_writel(ehci, ehci->command, &ehci->regs->command);
160 ehci_writel(ehci, FLAG_CF, &ehci->regs->configured_flag);
161 ehci_readl(ehci, &ehci->regs->command); /* unblock posted writes */
162 108
163 /* here we "know" root ports should always stay powered */ 109 ehci_resume(hcd, false);
164 ehci_port_power(ehci, 1);
165 return 0; 110 return 0;
166} 111}
167#endif /* CONFIG_PM */ 112#endif /* CONFIG_PM */