diff options
Diffstat (limited to 'drivers/usb/host/ohci-hcd.c')
-rw-r--r-- | drivers/usb/host/ohci-hcd.c | 58 |
1 files changed, 25 insertions, 33 deletions
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c index 1e27f10c1592..13cd2177b557 100644 --- a/drivers/usb/host/ohci-hcd.c +++ b/drivers/usb/host/ohci-hcd.c | |||
@@ -95,12 +95,11 @@ | |||
95 | #include <linux/init.h> | 95 | #include <linux/init.h> |
96 | #include <linux/timer.h> | 96 | #include <linux/timer.h> |
97 | #include <linux/list.h> | 97 | #include <linux/list.h> |
98 | #include <linux/interrupt.h> /* for in_interrupt () */ | ||
99 | #include <linux/usb.h> | 98 | #include <linux/usb.h> |
100 | #include <linux/usb_otg.h> | 99 | #include <linux/usb_otg.h> |
101 | #include "../core/hcd.h" | ||
102 | #include <linux/dma-mapping.h> | 100 | #include <linux/dma-mapping.h> |
103 | #include <linux/dmapool.h> /* needed by ohci-mem.c when no PCI */ | 101 | #include <linux/dmapool.h> |
102 | #include <linux/reboot.h> | ||
104 | 103 | ||
105 | #include <asm/io.h> | 104 | #include <asm/io.h> |
106 | #include <asm/irq.h> | 105 | #include <asm/irq.h> |
@@ -108,8 +107,9 @@ | |||
108 | #include <asm/unaligned.h> | 107 | #include <asm/unaligned.h> |
109 | #include <asm/byteorder.h> | 108 | #include <asm/byteorder.h> |
110 | 109 | ||
110 | #include "../core/hcd.h" | ||
111 | 111 | ||
112 | #define DRIVER_VERSION "2004 Nov 08" | 112 | #define DRIVER_VERSION "2005 April 22" |
113 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" | 113 | #define DRIVER_AUTHOR "Roman Weissgaerber, David Brownell" |
114 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" | 114 | #define DRIVER_DESC "USB 1.1 'Open' Host Controller (OHCI) Driver" |
115 | 115 | ||
@@ -141,6 +141,7 @@ static const char hcd_name [] = "ohci_hcd"; | |||
141 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); | 141 | static void ohci_dump (struct ohci_hcd *ohci, int verbose); |
142 | static int ohci_init (struct ohci_hcd *ohci); | 142 | static int ohci_init (struct ohci_hcd *ohci); |
143 | static void ohci_stop (struct usb_hcd *hcd); | 143 | static void ohci_stop (struct usb_hcd *hcd); |
144 | static int ohci_reboot (struct notifier_block *, unsigned long , void *); | ||
144 | 145 | ||
145 | #include "ohci-hub.c" | 146 | #include "ohci-hub.c" |
146 | #include "ohci-dbg.c" | 147 | #include "ohci-dbg.c" |
@@ -420,6 +421,23 @@ static void ohci_usb_reset (struct ohci_hcd *ohci) | |||
420 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | 421 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); |
421 | } | 422 | } |
422 | 423 | ||
424 | /* reboot notifier forcibly disables IRQs and DMA, helping kexec and | ||
425 | * other cases where the next software may expect clean state from the | ||
426 | * "firmware". this is bus-neutral, unlike shutdown() methods. | ||
427 | */ | ||
428 | static int | ||
429 | ohci_reboot (struct notifier_block *block, unsigned long code, void *null) | ||
430 | { | ||
431 | struct ohci_hcd *ohci; | ||
432 | |||
433 | ohci = container_of (block, struct ohci_hcd, reboot_notifier); | ||
434 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | ||
435 | ohci_usb_reset (ohci); | ||
436 | /* flush the writes */ | ||
437 | (void) ohci_readl (ohci, &ohci->regs->control); | ||
438 | return 0; | ||
439 | } | ||
440 | |||
423 | /*-------------------------------------------------------------------------* | 441 | /*-------------------------------------------------------------------------* |
424 | * HC functions | 442 | * HC functions |
425 | *-------------------------------------------------------------------------*/ | 443 | *-------------------------------------------------------------------------*/ |
@@ -487,13 +505,10 @@ static int ohci_init (struct ohci_hcd *ohci) | |||
487 | /* Start an OHCI controller, set the BUS operational | 505 | /* Start an OHCI controller, set the BUS operational |
488 | * resets USB and controller | 506 | * resets USB and controller |
489 | * enable interrupts | 507 | * enable interrupts |
490 | * connect the virtual root hub | ||
491 | */ | 508 | */ |
492 | static int ohci_run (struct ohci_hcd *ohci) | 509 | static int ohci_run (struct ohci_hcd *ohci) |
493 | { | 510 | { |
494 | u32 mask, temp; | 511 | u32 mask, temp; |
495 | struct usb_device *udev; | ||
496 | struct usb_bus *bus; | ||
497 | int first = ohci->fminterval == 0; | 512 | int first = ohci->fminterval == 0; |
498 | 513 | ||
499 | disable (ohci); | 514 | disable (ohci); |
@@ -654,37 +669,13 @@ retry: | |||
654 | 669 | ||
655 | // POTPGT delay is bits 24-31, in 2 ms units. | 670 | // POTPGT delay is bits 24-31, in 2 ms units. |
656 | mdelay ((temp >> 23) & 0x1fe); | 671 | mdelay ((temp >> 23) & 0x1fe); |
657 | bus = &ohci_to_hcd(ohci)->self; | ||
658 | ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; | 672 | ohci_to_hcd(ohci)->state = HC_STATE_RUNNING; |
659 | 673 | ||
660 | ohci_dump (ohci, 1); | 674 | ohci_dump (ohci, 1); |
661 | 675 | ||
662 | udev = bus->root_hub; | 676 | if (ohci_to_hcd(ohci)->self.root_hub == NULL) |
663 | if (udev) { | 677 | create_debug_files (ohci); |
664 | return 0; | ||
665 | } | ||
666 | |||
667 | /* connect the virtual root hub */ | ||
668 | udev = usb_alloc_dev (NULL, bus, 0); | ||
669 | if (!udev) { | ||
670 | disable (ohci); | ||
671 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | ||
672 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | ||
673 | return -ENOMEM; | ||
674 | } | ||
675 | |||
676 | udev->speed = USB_SPEED_FULL; | ||
677 | if (usb_hcd_register_root_hub (udev, ohci_to_hcd(ohci)) != 0) { | ||
678 | usb_put_dev (udev); | ||
679 | disable (ohci); | ||
680 | ohci->hc_control &= ~OHCI_CTRL_HCFS; | ||
681 | ohci_writel (ohci, ohci->hc_control, &ohci->regs->control); | ||
682 | return -ENODEV; | ||
683 | } | ||
684 | if (ohci->power_budget) | ||
685 | hub_set_power_budget(udev, ohci->power_budget); | ||
686 | 678 | ||
687 | create_debug_files (ohci); | ||
688 | return 0; | 679 | return 0; |
689 | } | 680 | } |
690 | 681 | ||
@@ -781,6 +772,7 @@ static void ohci_stop (struct usb_hcd *hcd) | |||
781 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); | 772 | ohci_writel (ohci, OHCI_INTR_MIE, &ohci->regs->intrdisable); |
782 | 773 | ||
783 | remove_debug_files (ohci); | 774 | remove_debug_files (ohci); |
775 | unregister_reboot_notifier (&ohci->reboot_notifier); | ||
784 | ohci_mem_cleanup (ohci); | 776 | ohci_mem_cleanup (ohci); |
785 | if (ohci->hcca) { | 777 | if (ohci->hcca) { |
786 | dma_free_coherent (hcd->self.controller, | 778 | dma_free_coherent (hcd->self.controller, |