diff options
Diffstat (limited to 'drivers/usb/host/ohci-pci.c')
-rw-r--r-- | drivers/usb/host/ohci-pci.c | 151 |
1 files changed, 45 insertions, 106 deletions
diff --git a/drivers/usb/host/ohci-pci.c b/drivers/usb/host/ohci-pci.c index 951514ef446d..08613e241894 100644 --- a/drivers/usb/host/ohci-pci.c +++ b/drivers/usb/host/ohci-pci.c | |||
@@ -14,12 +14,19 @@ | |||
14 | * This file is licenced under the GPL. | 14 | * This file is licenced under the GPL. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef CONFIG_PCI | ||
18 | #error "This file is PCI bus glue. CONFIG_PCI must be defined." | ||
19 | #endif | ||
20 | |||
21 | #include <linux/pci.h> | ||
22 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/kernel.h> | ||
19 | #include <linux/module.h> | ||
20 | #include <linux/pci.h> | ||
21 | #include <linux/usb.h> | ||
22 | #include <linux/usb/hcd.h> | ||
23 | |||
24 | #include "ohci.h" | ||
25 | #include "pci-quirks.h" | ||
26 | |||
27 | #define DRIVER_DESC "OHCI PCI platform driver" | ||
28 | |||
29 | static const char hcd_name[] = "ohci-pci"; | ||
23 | 30 | ||
24 | 31 | ||
25 | /*-------------------------------------------------------------------------*/ | 32 | /*-------------------------------------------------------------------------*/ |
@@ -123,13 +130,6 @@ static void ohci_quirk_nec_worker(struct work_struct *work) | |||
123 | struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); | 130 | struct ohci_hcd *ohci = container_of(work, struct ohci_hcd, nec_work); |
124 | int status; | 131 | int status; |
125 | 132 | ||
126 | status = ohci_init(ohci); | ||
127 | if (status != 0) { | ||
128 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", | ||
129 | "ohci_init", status); | ||
130 | return; | ||
131 | } | ||
132 | |||
133 | status = ohci_restart(ohci); | 133 | status = ohci_restart(ohci); |
134 | if (status != 0) | 134 | if (status != 0) |
135 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", | 135 | ohci_err(ohci, "Restarting NEC controller failed in %s, %d\n", |
@@ -175,19 +175,6 @@ static int ohci_quirk_amd700(struct usb_hcd *hcd) | |||
175 | return 0; | 175 | return 0; |
176 | } | 176 | } |
177 | 177 | ||
178 | static void sb800_prefetch(struct ohci_hcd *ohci, int on) | ||
179 | { | ||
180 | struct pci_dev *pdev; | ||
181 | u16 misc; | ||
182 | |||
183 | pdev = to_pci_dev(ohci_to_hcd(ohci)->self.controller); | ||
184 | pci_read_config_word(pdev, 0x50, &misc); | ||
185 | if (on == 0) | ||
186 | pci_write_config_word(pdev, 0x50, misc & 0xfcff); | ||
187 | else | ||
188 | pci_write_config_word(pdev, 0x50, misc | 0x0300); | ||
189 | } | ||
190 | |||
191 | /* List of quirks for OHCI */ | 178 | /* List of quirks for OHCI */ |
192 | static const struct pci_device_id ohci_pci_quirks[] = { | 179 | static const struct pci_device_id ohci_pci_quirks[] = { |
193 | { | 180 | { |
@@ -249,10 +236,10 @@ static const struct pci_device_id ohci_pci_quirks[] = { | |||
249 | static int ohci_pci_reset (struct usb_hcd *hcd) | 236 | static int ohci_pci_reset (struct usb_hcd *hcd) |
250 | { | 237 | { |
251 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | 238 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); |
239 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
252 | int ret = 0; | 240 | int ret = 0; |
253 | 241 | ||
254 | if (hcd->self.controller) { | 242 | if (hcd->self.controller) { |
255 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
256 | const struct pci_device_id *quirk_id; | 243 | const struct pci_device_id *quirk_id; |
257 | 244 | ||
258 | quirk_id = pci_match_id(ohci_pci_quirks, pdev); | 245 | quirk_id = pci_match_id(ohci_pci_quirks, pdev); |
@@ -262,94 +249,25 @@ static int ohci_pci_reset (struct usb_hcd *hcd) | |||
262 | ret = quirk(hcd); | 249 | ret = quirk(hcd); |
263 | } | 250 | } |
264 | } | 251 | } |
265 | if (ret == 0) { | ||
266 | ohci_hcd_init (ohci); | ||
267 | return ohci_init (ohci); | ||
268 | } | ||
269 | return ret; | ||
270 | } | ||
271 | |||
272 | |||
273 | static int ohci_pci_start (struct usb_hcd *hcd) | ||
274 | { | ||
275 | struct ohci_hcd *ohci = hcd_to_ohci (hcd); | ||
276 | int ret; | ||
277 | |||
278 | #ifdef CONFIG_PM /* avoid warnings about unused pdev */ | ||
279 | if (hcd->self.controller) { | ||
280 | struct pci_dev *pdev = to_pci_dev(hcd->self.controller); | ||
281 | |||
282 | /* RWC may not be set for add-in PCI cards, since boot | ||
283 | * firmware probably ignored them. This transfers PCI | ||
284 | * PM wakeup capabilities. | ||
285 | */ | ||
286 | if (device_can_wakeup(&pdev->dev)) | ||
287 | ohci->hc_control |= OHCI_CTRL_RWC; | ||
288 | } | ||
289 | #endif /* CONFIG_PM */ | ||
290 | 252 | ||
291 | ret = ohci_run (ohci); | 253 | if (ret == 0) |
292 | if (ret < 0) { | 254 | ret = ohci_setup(hcd); |
293 | ohci_err (ohci, "can't start\n"); | 255 | /* |
294 | ohci_stop (hcd); | 256 | * After ohci setup RWC may not be set for add-in PCI cards. |
295 | } | 257 | * This transfers PCI PM wakeup capabilities. |
258 | */ | ||
259 | if (device_can_wakeup(&pdev->dev)) | ||
260 | ohci->hc_control |= OHCI_CTRL_RWC; | ||
296 | return ret; | 261 | return ret; |
297 | } | 262 | } |
298 | 263 | ||
264 | static struct hc_driver __read_mostly ohci_pci_hc_driver; | ||
299 | 265 | ||
300 | /*-------------------------------------------------------------------------*/ | 266 | static const struct ohci_driver_overrides pci_overrides __initconst = { |
301 | 267 | .product_desc = "OHCI PCI host controller", | |
302 | static const struct hc_driver ohci_pci_hc_driver = { | ||
303 | .description = hcd_name, | ||
304 | .product_desc = "OHCI Host Controller", | ||
305 | .hcd_priv_size = sizeof(struct ohci_hcd), | ||
306 | |||
307 | /* | ||
308 | * generic hardware linkage | ||
309 | */ | ||
310 | .irq = ohci_irq, | ||
311 | .flags = HCD_MEMORY | HCD_USB11, | ||
312 | |||
313 | /* | ||
314 | * basic lifecycle operations | ||
315 | */ | ||
316 | .reset = ohci_pci_reset, | 268 | .reset = ohci_pci_reset, |
317 | .start = ohci_pci_start, | ||
318 | .stop = ohci_stop, | ||
319 | .shutdown = ohci_shutdown, | ||
320 | |||
321 | #ifdef CONFIG_PM | ||
322 | .pci_suspend = ohci_suspend, | ||
323 | .pci_resume = ohci_resume, | ||
324 | #endif | ||
325 | |||
326 | /* | ||
327 | * managing i/o requests and associated device resources | ||
328 | */ | ||
329 | .urb_enqueue = ohci_urb_enqueue, | ||
330 | .urb_dequeue = ohci_urb_dequeue, | ||
331 | .endpoint_disable = ohci_endpoint_disable, | ||
332 | |||
333 | /* | ||
334 | * scheduling support | ||
335 | */ | ||
336 | .get_frame_number = ohci_get_frame, | ||
337 | |||
338 | /* | ||
339 | * root hub support | ||
340 | */ | ||
341 | .hub_status_data = ohci_hub_status_data, | ||
342 | .hub_control = ohci_hub_control, | ||
343 | #ifdef CONFIG_PM | ||
344 | .bus_suspend = ohci_bus_suspend, | ||
345 | .bus_resume = ohci_bus_resume, | ||
346 | #endif | ||
347 | .start_port_reset = ohci_start_port_reset, | ||
348 | }; | 269 | }; |
349 | 270 | ||
350 | /*-------------------------------------------------------------------------*/ | ||
351 | |||
352 | |||
353 | static const struct pci_device_id pci_ids [] = { { | 271 | static const struct pci_device_id pci_ids [] = { { |
354 | /* handle any USB OHCI controller */ | 272 | /* handle any USB OHCI controller */ |
355 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), | 273 | PCI_DEVICE_CLASS(PCI_CLASS_SERIAL_USB_OHCI, ~0), |
@@ -377,3 +295,24 @@ static struct pci_driver ohci_pci_driver = { | |||
377 | }, | 295 | }, |
378 | #endif | 296 | #endif |
379 | }; | 297 | }; |
298 | |||
299 | static int __init ohci_pci_init(void) | ||
300 | { | ||
301 | if (usb_disabled()) | ||
302 | return -ENODEV; | ||
303 | |||
304 | pr_info("%s: " DRIVER_DESC "\n", hcd_name); | ||
305 | |||
306 | ohci_init_driver(&ohci_pci_hc_driver, &pci_overrides); | ||
307 | return pci_register_driver(&ohci_pci_driver); | ||
308 | } | ||
309 | module_init(ohci_pci_init); | ||
310 | |||
311 | static void __exit ohci_pci_cleanup(void) | ||
312 | { | ||
313 | pci_unregister_driver(&ohci_pci_driver); | ||
314 | } | ||
315 | module_exit(ohci_pci_cleanup); | ||
316 | |||
317 | MODULE_DESCRIPTION(DRIVER_DESC); | ||
318 | MODULE_LICENSE("GPL"); | ||