aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb/host/ehci-au1xxx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb/host/ehci-au1xxx.c')
-rw-r--r--drivers/usb/host/ehci-au1xxx.c87
1 files changed, 8 insertions, 79 deletions
diff --git a/drivers/usb/host/ehci-au1xxx.c b/drivers/usb/host/ehci-au1xxx.c
index bf7441afed16..cba10d625a5d 100644
--- a/drivers/usb/host/ehci-au1xxx.c
+++ b/drivers/usb/host/ehci-au1xxx.c
@@ -20,10 +20,12 @@ extern int usb_disabled(void);
20static int au1xxx_ehci_setup(struct usb_hcd *hcd) 20static int au1xxx_ehci_setup(struct usb_hcd *hcd)
21{ 21{
22 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 22 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
23 int ret = ehci_init(hcd); 23 int ret;
24
25 ehci->caps = hcd->regs;
26 ret = ehci_setup(hcd);
24 27
25 ehci->need_io_watchdog = 0; 28 ehci->need_io_watchdog = 0;
26 ehci_reset(ehci);
27 return ret; 29 return ret;
28} 30}
29 31
@@ -78,7 +80,6 @@ static const struct hc_driver ehci_au1xxx_hc_driver = {
78static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) 80static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
79{ 81{
80 struct usb_hcd *hcd; 82 struct usb_hcd *hcd;
81 struct ehci_hcd *ehci;
82 struct resource *res; 83 struct resource *res;
83 int ret; 84 int ret;
84 85
@@ -116,13 +117,6 @@ static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev)
116 goto err3; 117 goto err3;
117 } 118 }
118 119
119 ehci = hcd_to_ehci(hcd);
120 ehci->caps = hcd->regs;
121 ehci->regs = hcd->regs +
122 HC_LENGTH(ehci, readl(&ehci->caps->hc_capbase));
123 /* cache this readonly data; minimize chip reads */
124 ehci->hcs_params = readl(&ehci->caps->hcs_params);
125
126 ret = usb_add_hcd(hcd, pdev->resource[1].start, 120 ret = usb_add_hcd(hcd, pdev->resource[1].start,
127 IRQF_SHARED); 121 IRQF_SHARED);
128 if (ret == 0) { 122 if (ret == 0) {
@@ -158,28 +152,10 @@ static int ehci_hcd_au1xxx_drv_remove(struct platform_device *pdev)
158static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) 152static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
159{ 153{
160 struct usb_hcd *hcd = dev_get_drvdata(dev); 154 struct usb_hcd *hcd = dev_get_drvdata(dev);
161 struct ehci_hcd *ehci = hcd_to_ehci(hcd); 155 bool do_wakeup = device_may_wakeup(dev);
162 unsigned long flags; 156 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 157
158 rc = ehci_suspend(hcd, do_wakeup);
183 alchemy_usb_control(ALCHEMY_USB_EHCI0, 0); 159 alchemy_usb_control(ALCHEMY_USB_EHCI0, 0);
184 160
185 return rc; 161 return rc;
@@ -188,56 +164,9 @@ static int ehci_hcd_au1xxx_drv_suspend(struct device *dev)
188static int ehci_hcd_au1xxx_drv_resume(struct device *dev) 164static int ehci_hcd_au1xxx_drv_resume(struct device *dev)
189{ 165{
190 struct usb_hcd *hcd = dev_get_drvdata(dev); 166 struct usb_hcd *hcd = dev_get_drvdata(dev);
191 struct ehci_hcd *ehci = hcd_to_ehci(hcd);
192 167
193 alchemy_usb_control(ALCHEMY_USB_EHCI0, 1); 168 alchemy_usb_control(ALCHEMY_USB_EHCI0, 1);
194 169 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 170
242 return 0; 171 return 0;
243} 172}