diff options
Diffstat (limited to 'drivers/usb/host/ehci-au1xxx.c')
-rw-r--r-- | drivers/usb/host/ehci-au1xxx.c | 87 |
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); | |||
20 | static int au1xxx_ehci_setup(struct usb_hcd *hcd) | 20 | static 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 = { | |||
78 | static int ehci_hcd_au1xxx_drv_probe(struct platform_device *pdev) | 80 | static 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) | |||
158 | static int ehci_hcd_au1xxx_drv_suspend(struct device *dev) | 152 | static 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) | |||
188 | static int ehci_hcd_au1xxx_drv_resume(struct device *dev) | 164 | static 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 | } |