aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-spear.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-spear.c')
-rw-r--r--drivers/usb/host/ehci-spear.c71
1 files changed, 4 insertions, 67 deletions
diff --git a/drivers/usb/host/ehci-spear.c b/drivers/usb/host/ehci-spear.c
index 37ba8c8d2fd0..c718a065e154 100644
--- a/drivers/usb/host/ehci-spear.c
+++ b/drivers/usb/host/ehci-spear.c
@@ -41,19 +41,11 @@ static int ehci_spear_setup(struct usb_hcd *hcd)
41 41
42 /* registers start at offset 0x0 */ 42 /* registers start at offset 0x0 */
43 ehci->caps = hcd->regs; 43 ehci->caps = hcd->regs;
44 ehci->regs = hcd->regs + HC_LENGTH(ehci, ehci_readl(ehci,
45 &ehci->caps->hc_capbase));
46 /* cache this readonly data; minimize chip reads */
47 ehci->hcs_params = ehci_readl(ehci, &ehci->caps->hcs_params);
48 retval = ehci_halt(ehci);
49 if (retval)
50 return retval;
51 44
52 retval = ehci_init(hcd); 45 retval = ehci_setup(hcd);
53 if (retval) 46 if (retval)
54 return retval; 47 return retval;
55 48
56 ehci_reset(ehci);
57 ehci_port_power(ehci, 0); 49 ehci_port_power(ehci, 0);
58 50
59 return retval; 51 return retval;
@@ -97,71 +89,16 @@ static const struct hc_driver ehci_spear_hc_driver = {
97static int ehci_spear_drv_suspend(struct device *dev) 89static int ehci_spear_drv_suspend(struct device *dev)
98{ 90{
99 struct usb_hcd *hcd = dev_get_drvdata(dev); 91 struct usb_hcd *hcd = dev_get_drvdata(dev);
100 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 92 bool do_wakeup = device_may_wakeup(dev);
101 unsigned long flags;
102 int rc = 0;
103 93
104 if (time_before(jiffies, ehci->next_statechange)) 94 return ehci_suspend(hcd, do_wakeup);
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
118 return rc;
119} 95}
120 96
121static int ehci_spear_drv_resume(struct device *dev) 97static int ehci_spear_drv_resume(struct device *dev)
122{ 98{
123 struct usb_hcd *hcd = dev_get_drvdata(dev); 99 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 100
163 /* here we "know" root ports should always stay powered */ 101 ehci_resume(hcd, false);
164 ehci_port_power(ehci, 1);
165 return 0; 102 return 0;
166} 103}
167#endif /* CONFIG_PM */ 104#endif /* CONFIG_PM */